mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-11-08 01:57:31 +01:00
fix(runner): preserve runtime activity through the native bridge (#18239)
This commit is contained in:
1 parent
8941db9ce6
commit
a8e07500db
16 files changed
+431
-47
No files matched your search
@@ -676,6 +676,12 @@ acknowledgement and replay deduplicate delivery. Existing run-read authorization
|
||||
and secret redaction apply to saved and live events. Recording reported activity
|
||||
is not independent proof that it happened and grants no resource permission.
|
||||
|
||||
The native transport forwards runtime activity as a run-scoped fact. It retains
|
||||
the authenticated run identity across warm session attachment. Provider messages
|
||||
cannot impersonate this transport-owned notification.
|
||||
New-run activity waits for warm attachment to finish. A failed attachment does
|
||||
not retarget queued activity to the previous run.
|
||||
|
||||
Runner accepts local activity records only with an opaque context
|
||||
captured before the operation. Warm run attachment and process recovery rotate
|
||||
that authority. Runner supplies the run identity from its active authenticated
|
||||
|
||||
@@ -42,12 +42,12 @@
|
||||
"requiresProviderPolicy": true
|
||||
},
|
||||
"copilot": {
|
||||
"agentProfileVersion": 85,
|
||||
"agentProfileVersion": 87,
|
||||
"agentServerPackage": "@github/copilot",
|
||||
"agentServerVersion": "1.0.88",
|
||||
"agentRuntimePackage": null,
|
||||
"agentRuntimeVersion": null,
|
||||
"commandDigest": "sha256:267e04ce9335f7641f665d9b952bc4637056ee1cfeac23715b7aefbc3a8df3c9",
|
||||
"commandDigest": "sha256:ce2f4322cbc545932d6c725c57005eea1f44f2c743d5384c6ea90909563d958d",
|
||||
"requiresProviderPolicy": true
|
||||
},
|
||||
"claude": {
|
||||
|
||||
@@ -61,7 +61,7 @@ pub(crate) fn acpx_release_profile(agent: &str) -> Option<AcpxReleaseProfile> {
|
||||
agent_runtime_package: None,
|
||||
agent_runtime_version: None,
|
||||
command_digest:
|
||||
"sha256:267e04ce9335f7641f665d9b952bc4637056ee1cfeac23715b7aefbc3a8df3c9",
|
||||
"sha256:ce2f4322cbc545932d6c725c57005eea1f44f2c743d5384c6ea90909563d958d",
|
||||
requires_provider_policy: true,
|
||||
qualification_pending: false,
|
||||
},
|
||||
|
||||
@@ -7,9 +7,9 @@ import { fileURLToPath } from "node:url";
|
||||
import { resolve, dirname } from "node:path";
|
||||
|
||||
const root = resolve(dirname(fileURLToPath(import.meta.url)), "..");
|
||||
const fixture = resolve(root, "test/fixtures/copilot-profile-v85-identity.json");
|
||||
const fixture = resolve(root, "test/fixtures/copilot-profile-v87-identity.json");
|
||||
const historical = JSON.parse(readFileSync(resolve(root, "test/fixtures/copilot-profile-v12-identity.json"), "utf8"));
|
||||
const declaration = { ...historical.declaration, agentProfileVersion: 85 };
|
||||
const declaration = { ...historical.declaration, agentProfileVersion: 87 };
|
||||
delete declaration.permissionIdentitySourceSha256;
|
||||
const sources = {
|
||||
displayEventSourceSha256: "src/drivers/acpx/copilot-events.ts",
|
||||
|
||||
@@ -87,9 +87,9 @@ vi.mock("./installation-integrity.js", () => ({ verifyNativeAcpxInstallation: vi
|
||||
|
||||
describe("Copilot build-owned installation", () => {
|
||||
it("admits the current profile with environment launch preparation", () => {
|
||||
expect(QUALIFIED_ACPX_PROFILES.copilot.agentProfileVersion).toBe(85);
|
||||
expect(QUALIFIED_ACPX_PROFILES.copilot.agentProfileVersion).toBe(87);
|
||||
expect(QUALIFIED_ACPX_PROFILES.copilot.qualificationStatus).toBeUndefined();
|
||||
expect(QUALIFIED_ACPX_PROFILES.copilot.commandDigest).toBe("sha256:267e04ce9335f7641f665d9b952bc4637056ee1cfeac23715b7aefbc3a8df3c9");
|
||||
expect(QUALIFIED_ACPX_PROFILES.copilot.commandDigest).toBe("sha256:ce2f4322cbc545932d6c725c57005eea1f44f2c743d5384c6ea90909563d958d");
|
||||
});
|
||||
|
||||
it("preserves published v65 while binding retained-maintenance waits in v66", async () => {
|
||||
@@ -664,6 +664,28 @@ it("preserves the historical sleep-maintenance v64 identity", async () => {
|
||||
expect(current.commandDigest).not.toBe(prior.commandDigest);
|
||||
});
|
||||
|
||||
it("preserves v85 while binding runtime activity delivery in v86", () => {
|
||||
const priorBytes = readFileSync(new URL("../../../test/fixtures/copilot-profile-v85-identity.json", import.meta.url));
|
||||
expect(createHash("sha256").update(priorBytes).digest("hex")).toBe("15d2790d94d7cc46ac728119ed9b4d07ed2b682be039b3debc716600708d8c1a");
|
||||
const prior = JSON.parse(priorBytes.toString("utf8"));
|
||||
const current = JSON.parse(readFileSync(new URL("../../../test/fixtures/copilot-profile-v86-identity.json", import.meta.url), "utf8"));
|
||||
expect(Object.keys(current.declaration).filter(key => current.declaration[key] !== prior.declaration[key]).sort()).toEqual([
|
||||
"agentProfileVersion", "nativeSessionRuntimeSourceSha256", "profileCompatibilitySourceSha256", "runtimeRequestBridgeSourceSha256", "runtimeRequestFacadeSourceSha256",
|
||||
]);
|
||||
expect(isSupportedAcpxProfileVersion("copilot", 85)).toBe(true);
|
||||
});
|
||||
|
||||
it("preserves v86 while binding activity attachment settlement in v87", () => {
|
||||
const priorBytes = readFileSync(new URL("../../../test/fixtures/copilot-profile-v86-identity.json", import.meta.url));
|
||||
expect(createHash("sha256").update(priorBytes).digest("hex")).toBe("6baeb98adc7132b2afdce8b1d2da1df2f00356677eb4497c49c05aa9def79138");
|
||||
const prior = JSON.parse(priorBytes.toString("utf8"));
|
||||
const current = JSON.parse(readFileSync(new URL("../../../test/fixtures/copilot-profile-v87-identity.json", import.meta.url), "utf8"));
|
||||
expect(Object.keys(current.declaration).filter(key => current.declaration[key] !== prior.declaration[key]).sort()).toEqual([
|
||||
"agentProfileVersion", "harnessSessionSourceSha256", "profileCompatibilitySourceSha256", "runtimeRequestFacadeSourceSha256",
|
||||
]);
|
||||
expect(isSupportedAcpxProfileVersion("copilot", 86)).toBe(true);
|
||||
});
|
||||
|
||||
it("admits the current declaration and binds its source policy, receipts and patch hashes", () => {
|
||||
const identity = JSON.parse(readFileSync(new URL(`../../../test/fixtures/copilot-profile-v${QUALIFIED_ACPX_PROFILES.copilot.agentProfileVersion}-identity.json`, import.meta.url), "utf8"));
|
||||
expect(identity.declaration.systemInstructionDelivery).toBe(COPILOT_SYSTEM_INSTRUCTION_DELIVERY);
|
||||
|
||||
@@ -62,12 +62,12 @@ export const QUALIFIED_ACPX_PROFILE_DATA = {
|
||||
"protocolVersion": 1,
|
||||
"acpxVersion": "0.13.1",
|
||||
"agent": "copilot",
|
||||
"agentProfileVersion": 85,
|
||||
"agentProfileVersion": 87,
|
||||
"agentServerPackage": "@github/copilot",
|
||||
"agentServerVersion": "1.0.88",
|
||||
"agentRuntimePackage": null,
|
||||
"agentRuntimeVersion": null,
|
||||
"commandDigest": "sha256:267e04ce9335f7641f665d9b952bc4637056ee1cfeac23715b7aefbc3a8df3c9",
|
||||
"commandDigest": "sha256:ce2f4322cbc545932d6c725c57005eea1f44f2c743d5384c6ea90909563d958d",
|
||||
"permissionPolicy": "interactive"
|
||||
},
|
||||
"claude": {
|
||||
|
||||
@@ -2,13 +2,13 @@ import { QUALIFIED_ACPX_PROFILE_DATA } from "./generated-profiles.js";
|
||||
|
||||
/** Decodable historical profile revisions, not permission to launch them.
|
||||
* Exact current profile/package/digest admission is checked separately. */
|
||||
type HistoricalAcpxProfileVersion = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84;
|
||||
type HistoricalAcpxProfileVersion = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86;
|
||||
type CurrentAcpxProfileVersion = typeof QUALIFIED_ACPX_PROFILE_DATA[keyof typeof QUALIFIED_ACPX_PROFILE_DATA]["agentProfileVersion"];
|
||||
export type AcpxProfileVersion = HistoricalAcpxProfileVersion | CurrentAcpxProfileVersion;
|
||||
|
||||
const historicalVersions: Readonly<Record<string, readonly HistoricalAcpxProfileVersion[]>> = {
|
||||
pi: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34], claude: [1, 2, 3, 4, 5], codex: [1, 2, 3, 4, 5],
|
||||
grok: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13], copilot: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84],
|
||||
grok: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13], copilot: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86],
|
||||
cursor: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15],
|
||||
};
|
||||
|
||||
|
||||
@@ -43,7 +43,60 @@ import {
|
||||
type PrpStructuredRunResult,
|
||||
} from "./codex-app-server-driver.test-support.js";
|
||||
|
||||
import { RUNNERD_RUNTIME_ACTIVITY } from "./codex-driver-values.js";
|
||||
|
||||
describe("Codex app-server Codex driver", () => {
|
||||
it("rejects provider-forged and previous-run activity notifications", async () => {
|
||||
const transport = new FakeCodexTransport();
|
||||
const session = await makeDriver([transport]).openSession({
|
||||
runId: "activity-current", normalizedSessionId: "activity-session", workingDirectory: WORKSPACE,
|
||||
});
|
||||
const payload = { namespace: "example.runtime", activityKey: "screen.used" };
|
||||
transport.push("paperclip/runtimeActivityRecorded", { runId: "activity-current", payload });
|
||||
transport.push("paperclip/runtimeActivityRecorded", {
|
||||
[RUNNERD_RUNTIME_ACTIVITY]: true, runId: "activity-previous", payload,
|
||||
});
|
||||
const turn = await session.startTurn({ message: { role: "user", text: "Finish." } });
|
||||
transport.push("turn/started", { threadId: "thread-1", turn: { id: turn.turnId, status: "inProgress" } });
|
||||
transport.push("paperclip/runResult", { threadId: "thread-1", turnId: turn.turnId, result });
|
||||
transport.push("turn/completed", { threadId: "thread-1", turn: { id: turn.turnId, status: "completed", items: [] } });
|
||||
const events = await collectUntilTerminal(session.events());
|
||||
expect(events.some(event => event.eventType === "runtime.activity.recorded")).toBe(false);
|
||||
});
|
||||
|
||||
it("drops failed-attachment activity and resumes the prior run's notification stream", async () => {
|
||||
let rejectAttachment!: (error: Error) => void;
|
||||
const pending = new Promise<void>((_resolve, reject) => { rejectAttachment = reject; });
|
||||
class FailedAttachmentTransport extends FakeCodexTransport {
|
||||
attachRun() { return pending; }
|
||||
}
|
||||
const transport = new FailedAttachmentTransport();
|
||||
const session = await makeDriver([transport]).openSession({
|
||||
runId: "activity-current", normalizedSessionId: "activity-session", workingDirectory: WORKSPACE,
|
||||
});
|
||||
const attaching = expect(session.attachRun!({ runId: "activity-rejected" })).rejects.toThrow("controlled attachment failure");
|
||||
await expect(session.attachRun!({ runId: "activity-concurrent" })).rejects.toThrow("codex_run_attach_busy");
|
||||
const payload = { namespace: "example.runtime", activityKey: "screen.used" };
|
||||
transport.push("paperclip/runtimeActivityRecorded", {
|
||||
[RUNNERD_RUNTIME_ACTIVITY]: true, runId: "activity-rejected", payload,
|
||||
});
|
||||
await new Promise<void>(resolve => setImmediate(resolve));
|
||||
rejectAttachment(new Error("controlled attachment failure"));
|
||||
await attaching;
|
||||
transport.push("paperclip/runtimeActivityRecorded", {
|
||||
[RUNNERD_RUNTIME_ACTIVITY]: true, runId: "activity-current", payload,
|
||||
});
|
||||
const turn = await session.startTurn({ message: { role: "user", text: "Finish." } });
|
||||
transport.push("turn/started", { threadId: "thread-1", turn: { id: turn.turnId, status: "inProgress" } });
|
||||
transport.push("paperclip/runResult", { threadId: "thread-1", turnId: turn.turnId, result });
|
||||
transport.push("turn/completed", { threadId: "thread-1", turn: { id: turn.turnId, status: "completed", items: [] } });
|
||||
const events = await collectUntilTerminal(session.events());
|
||||
expect(events.filter(event => event.eventType === "runtime.activity.recorded")).toEqual([
|
||||
expect.objectContaining({ runId: "activity-current", payload }),
|
||||
]);
|
||||
expect(events.some(event => event.eventType === "run.attached")).toBe(false);
|
||||
});
|
||||
|
||||
it("forwards credential updates before a turn with P0 priority", async () => {
|
||||
const transport = new FakeCodexTransport();
|
||||
const session = await makeDriver([transport]).openSession({
|
||||
|
||||
@@ -40,6 +40,8 @@ export const RUNNERD_CANONICAL_ITEM = Symbol(
|
||||
"paperclip.runnerd.canonical-item",
|
||||
);
|
||||
|
||||
export const RUNNERD_RUNTIME_ACTIVITY = Symbol("paperclip.runnerd.runtime-activity");
|
||||
|
||||
export function text(value: unknown, fallback = ""): string {
|
||||
return typeof value === "string" ? value : fallback;
|
||||
}
|
||||
|
||||
@@ -106,48 +106,55 @@ export class CodexHarnessSession
|
||||
this.assertProtocolIntegrity();
|
||||
const transportOwnsQuiescence = this.transport.attachRun !== undefined;
|
||||
if (
|
||||
this.turnStartPending ||
|
||||
this.turnStartPending || this.pendingRunAttachment !== null ||
|
||||
(!transportOwnsQuiescence &&
|
||||
(this.activeTurnId !== null || this.pendingRuntimeRequestMap.size > 0))
|
||||
) {
|
||||
throw new Error("codex_run_attach_busy");
|
||||
}
|
||||
if (!input.runId) throw new Error("codex_run_attach_invalid");
|
||||
await this.transport.attachRun?.({
|
||||
runId: input.runId,
|
||||
turnId: `turn_attachment_${randomUUID().replaceAll("-", "")}`,
|
||||
itemId: `item_attachment_${randomUUID().replaceAll("-", "")}`,
|
||||
...(input.currentRunGrant ? { currentRunGrant: structuredClone(input.currentRunGrant) } : {}),
|
||||
});
|
||||
this.assertProtocolIntegrity();
|
||||
if (transportOwnsQuiescence) {
|
||||
// Runnerd's attachment contract performs two durable readiness probes,
|
||||
// drains the settled provider tail, and rotates authority atomically.
|
||||
// Its proof supersedes host reducer state that can remain stale when a
|
||||
// semantic-result consumer stops before the interrupt terminal arrives.
|
||||
// Drop only the prior run's already-proven-settled buffered suffix.
|
||||
this.activeTurnId = null;
|
||||
this.pendingRuntimeRequestMap.clear();
|
||||
this.eventQueue.clear();
|
||||
let settle!: () => void;
|
||||
this.pendingRunAttachment = { runId: input.runId, settled: new Promise<void>(resolve => { settle = resolve; }) };
|
||||
try {
|
||||
await this.transport.attachRun?.({
|
||||
runId: input.runId,
|
||||
turnId: `turn_attachment_${randomUUID().replaceAll("-", "")}`,
|
||||
itemId: `item_attachment_${randomUUID().replaceAll("-", "")}`,
|
||||
...(input.currentRunGrant ? { currentRunGrant: structuredClone(input.currentRunGrant) } : {}),
|
||||
});
|
||||
this.assertProtocolIntegrity();
|
||||
if (transportOwnsQuiescence) {
|
||||
// Runnerd's attachment contract performs two durable readiness probes,
|
||||
// drains the settled provider tail, and rotates authority atomically.
|
||||
// Its proof supersedes host reducer state that can remain stale when a
|
||||
// semantic-result consumer stops before the interrupt terminal arrives.
|
||||
// Drop only the prior run's already-proven-settled buffered suffix.
|
||||
this.activeTurnId = null;
|
||||
this.pendingRuntimeRequestMap.clear();
|
||||
this.eventQueue.clear();
|
||||
}
|
||||
if (this.codexUsageBaseline && input.runId !== this.runId) {
|
||||
this.codexUsageBaseline = { baseline: { ...this.codexUsageBaseline.latest }, latest: { ...this.codexUsageBaseline.latest } };
|
||||
this.usageSnapshot = codexRunUsage(this.codexUsageBaseline);
|
||||
}
|
||||
this.runId = input.runId;
|
||||
this.result = null;
|
||||
this.resultFingerprint = null;
|
||||
this.resultCallId = null;
|
||||
this.resultTurnId = null;
|
||||
this.dispositionOnlyRecoveryConsumed = false;
|
||||
this.dispositionOnlyRecoveryTurnId = null;
|
||||
this.terminal = false;
|
||||
this.terminalTurns.clear();
|
||||
this.turnStarted = false;
|
||||
this.protocolFailed = false;
|
||||
this.protocolFailureCode = null;
|
||||
this.protocolFailureMessage = null;
|
||||
this.emit("run.attached", { runId: input.runId, sameSession: true });
|
||||
} finally {
|
||||
this.pendingRunAttachment = null;
|
||||
settle();
|
||||
}
|
||||
if (this.codexUsageBaseline && input.runId !== this.runId) {
|
||||
this.codexUsageBaseline = { baseline: { ...this.codexUsageBaseline.latest }, latest: { ...this.codexUsageBaseline.latest } };
|
||||
this.usageSnapshot = codexRunUsage(this.codexUsageBaseline);
|
||||
}
|
||||
this.runId = input.runId;
|
||||
this.result = null;
|
||||
this.resultFingerprint = null;
|
||||
this.resultCallId = null;
|
||||
this.resultTurnId = null;
|
||||
this.dispositionOnlyRecoveryConsumed = false;
|
||||
this.dispositionOnlyRecoveryTurnId = null;
|
||||
this.terminal = false;
|
||||
this.terminalTurns.clear();
|
||||
this.turnStarted = false;
|
||||
this.protocolFailed = false;
|
||||
this.protocolFailureCode = null;
|
||||
this.protocolFailureMessage = null;
|
||||
this.emit("run.attached", { runId: input.runId, sameSession: true });
|
||||
}
|
||||
|
||||
contextSnapshot(): CodexModelContextSnapshot {
|
||||
|
||||
@@ -28,6 +28,7 @@ import {
|
||||
recordWorkspaceChanges,
|
||||
} from "./codex-session-workspace.js";
|
||||
import {
|
||||
RUNNERD_RUNTIME_ACTIVITY,
|
||||
boundedText,
|
||||
differingJsonPaths,
|
||||
itemFromParams,
|
||||
@@ -105,6 +106,14 @@ async function mapNotification(state: CodexSessionState, notification: CodexRpcN
|
||||
}
|
||||
|
||||
async function mapNotificationBody(state: CodexSessionState, notification: CodexRpcNotification): Promise<void> {
|
||||
if (notification.method === "paperclip/runtimeActivityRecorded") {
|
||||
const params = notification.params;
|
||||
if ((params as Record<PropertyKey, unknown>)[RUNNERD_RUNTIME_ACTIVITY] !== true) return;
|
||||
const pending = state.pendingRunAttachment;
|
||||
if (pending && params.runId === pending.runId && params.runId !== state.runId) await pending.settled;
|
||||
if (params.runId === state.runId) state.emit("runtime.activity.recorded", record(params.payload));
|
||||
return;
|
||||
}
|
||||
if (!isSupportedCodexNotificationMethod(notification.method)) return;
|
||||
if (notification.method === "item/completed" && notification.params.kind === "steering_acknowledgement"
|
||||
&& !notification.params.threadId && !notification.params.turnId && !notification.params.thread && !notification.params.turn) return;
|
||||
|
||||
@@ -117,6 +117,7 @@ export class CodexSessionState {
|
||||
resultCallId: string | null = null;
|
||||
resultTurnId: string | null = null;
|
||||
turnStartPending = false;
|
||||
pendingRunAttachment: { runId: string; settled: Promise<void> } | null = null;
|
||||
/**
|
||||
* Resolves once a pending turn/start settles, on the accepted path or on a
|
||||
* provider rejection. A terminal notification for that turn must wait on
|
||||
|
||||
@@ -97,7 +97,7 @@ import {
|
||||
releaseMaterializedNativeRuntimeSkills,
|
||||
} from "../drivers/runtime-context-materializer.js";
|
||||
import { resolvePackagedRunnerBinary } from "./runner-binary.js";
|
||||
import { RUNNERD_CANONICAL_ITEM } from "../drivers/codex/codex-driver-values.js";
|
||||
import { RUNNERD_CANONICAL_ITEM, RUNNERD_RUNTIME_ACTIVITY } from "../drivers/codex/codex-driver-values.js";
|
||||
|
||||
// URL directory conversion preserves a trailing separator while path-derived
|
||||
// build artifacts do not. Normalize once so a source build cannot be
|
||||
@@ -6697,6 +6697,14 @@ class DurablePrpCodexTransport implements CodexAppServerTransport {
|
||||
if (fromDeferredQueue) this.#deferredTurnStartEvents.shift();
|
||||
else this.#eventSourceSeq = event.sourceSeq;
|
||||
if (event.eventType === "auth.credentials.updated" && this.options.onCredentialsUpdated) continue;
|
||||
if (event.eventType === "runtime.activity.recorded") {
|
||||
this.#queue.push({ method: "paperclip/runtimeActivityRecorded", params: {
|
||||
[RUNNERD_RUNTIME_ACTIVITY]: true,
|
||||
runId: event.envelope.runId,
|
||||
payload: eventPayload,
|
||||
} });
|
||||
continue;
|
||||
}
|
||||
if (
|
||||
event.eventType === "harness.ready" ||
|
||||
event.eventType === "session.started" ||
|
||||
|
||||
@@ -0,0 +1,100 @@
|
||||
import { execFile } from "node:child_process";
|
||||
import { promisify } from "node:util";
|
||||
import { mkdtemp, mkdir, readFile, realpath, rm } from "node:fs/promises";
|
||||
import { tmpdir } from "node:os";
|
||||
import { join, resolve } from "node:path";
|
||||
import { expect, it, vi } from "vitest";
|
||||
import { CodexAppServerDriver } from "../drivers/codex/codex-app-server-driver.js";
|
||||
import { collectUntilTerminal } from "../drivers/codex/codex-app-server-driver.test-support.js";
|
||||
import { validatePrpEvent } from "../protocol/replay-contract.js";
|
||||
import { createCodexTaskEnvelope } from "../contracts/codex.js";
|
||||
import { createRunnerdCodexTransport, defaultCapabilityRunnerdBinary } from "./runnerd-codex-transport.js";
|
||||
|
||||
const execute = promisify(execFile);
|
||||
|
||||
it("delivers authenticated runtime activity through the real Runner bridge across runs", async () => {
|
||||
const root = await realpath(await mkdtemp(join(tmpdir(), "runnerd-runtime-activity-")));
|
||||
const runner = process.env.PAPERCLIP_ATTACH_TRANSITION_RUNNER ?? defaultCapabilityRunnerdBinary();
|
||||
const workspace = join(root, "workspace");
|
||||
await Promise.all([mkdir(workspace), mkdir(join(root, "home"))]);
|
||||
const environment = { PATH: process.env.PATH, HOME: join(root, "home"), CODEX_HOME: join(root, "codex-home") };
|
||||
let releasePrevious!: () => void, previousReleasing!: () => void, observedNewActivity!: () => void;
|
||||
const previousRelease = new Promise<void>(resolve => { releasePrevious = resolve; });
|
||||
const releasing = new Promise<void>(resolve => { previousReleasing = resolve; });
|
||||
const observed = new Promise<void>(resolve => { observedNewActivity = resolve; });
|
||||
let registrations = 0;
|
||||
const bundle = createRunnerdCodexTransport({
|
||||
runnerBinary: runner,
|
||||
codexCommand: resolve(import.meta.dirname, "../../runner/target/debug/fake-codex-app-server"),
|
||||
codexArgs: ["--state-file", join(root, "provider.json")],
|
||||
stateDirectory: root, environment,
|
||||
controlPlaneRegistration: async authority => {
|
||||
if (registrations++ === 0) {
|
||||
await authority.start();
|
||||
return { release: async () => { previousReleasing(); await previousRelease; } };
|
||||
}
|
||||
return { release: () => undefined };
|
||||
},
|
||||
lifecyclePolicy: { mode: "warm", idleTimeoutMs: 60_000 },
|
||||
prpIdentity: { runnerInstanceId: "runner-activity", environmentLeaseId: "lease-activity",
|
||||
runId: "activity-first", normalizedSessionId: "session-activity", turnId: "turn-activity", itemId: "item-activity" },
|
||||
});
|
||||
const notifications = bundle.transport.notifications.bind(bundle.transport);
|
||||
bundle.transport.notifications = async function* () {
|
||||
for await (const notification of notifications()) {
|
||||
if (notification.method === "paperclip/runtimeActivityRecorded" && notification.params.runId === "activity-next") observedNewActivity();
|
||||
yield notification;
|
||||
}
|
||||
};
|
||||
const driver = new CodexAppServerDriver({
|
||||
approvalPolicy: "never", includeCollaborationModeInstructions: false, environment,
|
||||
taskEnvelope: createCodexTaskEnvelope({ objective: "Verify runtime activity.", contractRevision: "1",
|
||||
criteria: [{ id: "objective", requirement: "Finish." }], constraints: [] }),
|
||||
transportFactory: () => bundle.transport,
|
||||
});
|
||||
const helper = (args: string[]) => execute(runner, args, { env: {
|
||||
...environment, PAPERCLIP_RUNTIME_NOTIFICATION_CONTEXT: join(root, "runner/runtime-notifications.json"),
|
||||
} });
|
||||
const payload = { namespace: "example.runtime", activityKey: "screen.used" };
|
||||
let session: Awaited<ReturnType<typeof driver.openSession>> | undefined;
|
||||
let attaching: Promise<void> | undefined;
|
||||
try {
|
||||
session = await driver.openSession({ runId: "activity-first", normalizedSessionId: "session-activity", workingDirectory: workspace });
|
||||
const firstContext = (await helper(["notification-context"])).stdout.trim();
|
||||
for (const runId of ["activity-first", "activity-next"]) {
|
||||
if (runId === "activity-next") {
|
||||
attaching = session.attachRun!({ runId });
|
||||
await releasing;
|
||||
await vi.waitFor(async () => {
|
||||
expect((await helper(["notification-context"])).stdout.trim()).not.toBe(firstContext);
|
||||
});
|
||||
await expect(helper(["record-activity", firstContext, payload.namespace, payload.activityKey])).rejects.toThrow();
|
||||
}
|
||||
const context = (await helper(["notification-context"])).stdout.trim();
|
||||
await helper(["record-activity", context, payload.namespace, payload.activityKey]);
|
||||
await vi.waitFor(async () => {
|
||||
const journal = JSON.parse(await readFile(join(root, "control-plane/control-plane-state.json"), "utf8"));
|
||||
expect(journal.committedEvents.some((event: { eventType: string; envelope: { runId: string } }) =>
|
||||
event.eventType === "runtime.activity.recorded" && event.envelope.runId === runId)).toBe(true);
|
||||
});
|
||||
if (attaching) {
|
||||
await observed;
|
||||
await new Promise<void>(resolve => setImmediate(resolve));
|
||||
releasePrevious();
|
||||
await attaching;
|
||||
}
|
||||
await session.startTurn({ message: { role: "user", text: "Finish." } });
|
||||
const events = await collectUntilTerminal(session.events());
|
||||
const activities = events.filter(event => event.eventType === "runtime.activity.recorded");
|
||||
expect(activities).toHaveLength(1);
|
||||
expect(activities[0]).toMatchObject({ runId, sourceKind: "runner", priority: 1, payload });
|
||||
expect(validatePrpEvent(activities[0]).ok).toBe(true);
|
||||
}
|
||||
} finally {
|
||||
releasePrevious();
|
||||
await attaching?.catch(() => undefined);
|
||||
await session?.close();
|
||||
await bundle.transport.close();
|
||||
await rm(root, { recursive: true, force: true });
|
||||
}
|
||||
}, 30_000);
|
||||
@@ -0,0 +1,88 @@
|
||||
{
|
||||
"commandDigest": "sha256:8d0eb9ed39fe7faabc7c2943738177e96a9a8c80a116ef76d9c1995faa8bf328",
|
||||
"declaration": {
|
||||
"schema": "paperclip.acpx_profile_declaration.v1",
|
||||
"agent": "copilot",
|
||||
"agentProfileVersion": 86,
|
||||
"acpxVersion": "0.13.1",
|
||||
"agentServerVersion": "1.0.88",
|
||||
"protocolPolicyRevision": "copilot-agent-manual-v1",
|
||||
"acpxPatchSha256": "1e7dae8c83bf8620f53f2bea13c175eeff95e7e955783f6f529bb1dcbdcdb6d2",
|
||||
"policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3",
|
||||
"distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107",
|
||||
"agentFilesBinding": "registered-runtime-context-v1",
|
||||
"systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1",
|
||||
"sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1",
|
||||
"innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a",
|
||||
"upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0",
|
||||
"patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679",
|
||||
"messageIdentityContract": "copilot-native-message-id-v1",
|
||||
"ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1",
|
||||
"permissionContextContract": "copilot-edit-permission-context-v1",
|
||||
"permissionContextSourceSha256": "de2d38d702b3c574161af0c0c04790fb6f6347916eb3916ce7a131a8c229121b",
|
||||
"permissionAdapterSourceSha256": "ee5929ed2ee647ad0369465dee9d51a00b2dd28e1ff735b43e969ddc9c164668",
|
||||
"permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9",
|
||||
"permissionRedactionSourceSha256": "ad6770c69269087951790e2e87e22ac088e3d432769adf17ebc865ed512e6c4f",
|
||||
"permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4",
|
||||
"semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2",
|
||||
"semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791",
|
||||
"semanticBridgeSourceSha256": "8764b8c9032fdc7d1415b01e75a9fc57c550e7a5e11da4bed7d9100082872ae5",
|
||||
"toolEvidenceSourceSha256": "6eef5039afc75bb851eaf9cd82a6f099e4bd398ca2deb59dd66f5b2a81a7a706",
|
||||
"semanticNormalizedInputContract": "validated-forwarded-input-commit-v1",
|
||||
"semanticSidecarSourceSha256": "b6d5888f47a47838c507a43fbe31a778ac63d4fcbcdc9a869108f604c34c3824",
|
||||
"semanticDirectDriverSourceSha256": "4ec65aa1d4e905a1e732f2d043bbd39de1ab92f380276ede37d6a72efc19c64d",
|
||||
"semanticValidationSourceSha256": "02fbb92681c78c5de5d2f1aae25aabc25a0e5df6b0ff4baccac652192a8da975",
|
||||
"semanticNormalizationSourceSha256": "8b628b82e8eacc91cdcc6fdca2210ba4cf282f01e9c6f74e95ff271655b5047e",
|
||||
"semanticCompletionContractSourceSha256": "f49398b682a5623812f5d3c33d6bb9a749008e47cc0ed969072041615f66df59",
|
||||
"semanticValidatorsSourceSha256": "b20ec8ee6e7165117233ce4421a975bb9d3f276220ce31655c0b9a717cb2d9cb",
|
||||
"semanticSchemaBundleSourceSha256": "81ef98ca7b34896a0f76390ac7af3dd8ef7609fe6f38d54bd6a69373d50fe40b",
|
||||
"semanticSidecarProtocolSourceSha256": "26b6b21dad582810d00f46e947e682a9615ee9761c487f6315970d6d014c05ab",
|
||||
"semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1",
|
||||
"displayEventSourceSha256": "d72f9a6035c247bc6a42c067c05753076c54322c4b58984e93922f3325dc6877",
|
||||
"displayProjectionSourceSha256": "75952606b26dd93bbc582c1f0a4424487377272ea745fb3a27ceae031fd5dc7e",
|
||||
"configuredEnvironmentSourceSha256": "ecef0ada320a762e0a3d91c38c72d4e19e2c8e8be8c060938a47e7f1a029058a",
|
||||
"configuredEnvironmentRustSourceSha256": "1671cb2735b3fa119d32f08d4a12b21b9f78a0e4d7285eb63c35df79ce17bd3c",
|
||||
"profileActivitySourceSha256": "4fdb6b0f9125fd8372ba6f27945fa5c8a3d3b2ec891df544092e3dc7a75d5282",
|
||||
"profileExtensionsSourceSha256": "a80ddc95eb4505095bfdbbf85c758199949ab20be9c84b34c77f762eb7180571",
|
||||
"profileInstallationSourceSha256": "58841b2d3b47ab9956db20608802edcd0e55cf5856002dc7c51e05e75bdcb8f6",
|
||||
"attachmentPolicySourceSha256": "4f7638b7cc64e18f6a4ba33fd46de2b3d49225e32aeab41f5c695b268fa4f8e2",
|
||||
"singleReadEvidenceSourceSha256": "4069393405089bde613cecec04f5123c426594811da4c668bd96f0e7e283550f",
|
||||
"nativeSessionRuntimeSourceSha256": "cbcefbceb0b2a24b0909cbb8361df6b8853b4f50b21d66328bc483951a8246ea",
|
||||
"nativeRuntimeContextSourceSha256": "71607f80dbb8dc5cc6c123d0b8f3995d6c5407277695a8c82cbedc90fb8f4842",
|
||||
"nativeRuntimePromptsSourceSha256": "fff5755dba9b7dce8a5f10ff6ac6d5ed06b92ed079ce1e0a44ac72f2ce7869c1",
|
||||
"nativeSessionContractSourceSha256": "22a8c96ce41ba4f03e976fc37f0cc7c5d05cee99fa789941da31ee1dab440b90",
|
||||
"harnessSessionContractSourceSha256": "baba1a210b863518f01e0c875606ed37f9467c433222251438578bd999bc43b5",
|
||||
"harnessBackendSourceSha256": "dc827e281ae6731545b166ee4d709a4f67f594a556dcbe63c70fe8f1aca26249",
|
||||
"harnessSessionSourceSha256": "81361733e86b56dd5a66415aefc6f72e69be24acc8d3417370154ebb7fef6e94",
|
||||
"transportContractSourceSha256": "06f06c53ecae304f72034ffb2f659ff087c82a70ed4994daf21a9d2edaf56e4e",
|
||||
"nativeBackendSourceSha256": "7495d9898d22dca1ebf6336361d332bafefc4498f6e49f1135025fad846c8586",
|
||||
"nativeBackendFactorySourceSha256": "7e431c926b76d53c4c08e3a4105353dcd34bd940f6588a1a68f79631f6feeb44",
|
||||
"nativeInstructionsSourceSha256": "82ac6e5f7275b4ef79fb166c7330efc504e80cab3d7e9081e4e40a8b570bc50b",
|
||||
"providerLaunchSourceSha256": "c744235b3067ea75973523f78f1e13399337bc155f1775af694e34782d5c9bef",
|
||||
"launchPreparationStoreSourceSha256": "ff6025568bbc0aa6ce545772d73dfca2d3da226740bd3a7b386b069e76cff296",
|
||||
"runtimeRequestBridgeSourceSha256": "8bf5c2ed6d6223144f7eb777e97973655301f5be10d9734f025cfc2b0bdff431",
|
||||
"runtimeRequestFacadeSourceSha256": "553914b022d4735228c69619c9d209cd4684c4b57649be32d11054859903ba91",
|
||||
"runtimeRequestNotificationSourceSha256": "6196c6175f11c69295dc00fc773201f4fdeca26c500653870253c43b81e65211",
|
||||
"guardedInstallationSourceSha256": "64b137e3ef695e7d03013ea2b6c8830171e0a73e0bf2e73d55e9ced57a47bcf6",
|
||||
"nativeExecutionSourceSha256": "116c348e232848a80c5556494c109314baafb20fb5c97133d9656c7732ee54be",
|
||||
"profileCompatibilitySourceSha256": "79740568b1cf863c87b31d5236b96858f0f5c3b42883f639cefc82c80d2ea2a7",
|
||||
"installationSourceSha256": "a1c7c6f103b898216973e77ffbac0ef7572e250aa574d1a4065270e9dfa0dc2d",
|
||||
"assetOwnershipSourceSha256": "e5bb6bc58b3f0e957a64b2cd99c710337ffcd9c0e1fadb341f48e033b64b99f5",
|
||||
"assetInstallerSourceSha256": "d3bd9514e5920d0cc3567aa50487fb534c57a6f66b8da0d3f22c5f6e499c841f",
|
||||
"credentialBindingSourceSha256": "2ed68b9aed9756fdd682721833eb2aeaa58f30f1dc8825c88886cc8e7ee92abe",
|
||||
"admissionDiagnosticsSourceSha256": "df8f1aa4f2d1bc63b2635bdd09cb8165c8b7681ddcc2618435c7c08ca90475af",
|
||||
"grokAdmissionSourceSha256": "f1e46cf2e1e36b7704bd797b678e3db8db2003f97bdb9d827cfa3d7662698777",
|
||||
"sidecarErrorSourceSha256": "17948ad74350dc487ab20d24a0fb89daf0b426b98396454fff0e3856e922d82c",
|
||||
"profileSourceSha256": "f5538b3dbefa7634a332b87d5ededcefb56aa7e5790cede1c7a0d948a548a456",
|
||||
"metadataProbeSourceSha256": "be4c8416edd27061109bc1f33d0c26071b4facbb3f651beaae6b3c0275cce727",
|
||||
"permissionToolIdentitySourceSha256": "770b47305e571a81f344883057d0e4a482a1cd59ac77d045836593a8e739deb1",
|
||||
"semanticContinuationSourceSha256": "c9cc0fd516b3df92a6655f56ee9bef37615a889c371e2e137d8ac5c1176de811",
|
||||
"preparedHarnessHomeSourceSha256": "bb286f7ddc6e9597c56d46bf7ff6e3b556c5b680d7e147fd46518724432b083e",
|
||||
"runtimeHostSourceSha256": "26b2e115b3f4ae7c20e9d963d117e0286c958af81386deade83397f12abf9662",
|
||||
"runtimeAdapterSourceSha256": "fab1e278e0f2aed55b35e57d14329eb431b79a08040fa079aa2403842d16085e",
|
||||
"runtimeSandboxSourceSha256": "b9f05e522f92b6bade51c7a17f8d28bf31ab9db26510b8d5ddce8519d563a875",
|
||||
"cancellationSourceSha256": "a07d1a9e982dec0ae130c1ad1efa5bc75c6a39e013b730ba3ee45256f09ceeca",
|
||||
"agentFilesSourceSha256": "fb32f6badc13dfa22f231479509b631b2f0eba0c99b1ab9f3cd5c0c601aa03ba",
|
||||
"nativeDistributionSourceSha256": "aed327c389e957483a503cb1bb8b247ee7cd7ff4b528fb4567c39bcb4577690b"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
{
|
||||
"commandDigest": "sha256:ce2f4322cbc545932d6c725c57005eea1f44f2c743d5384c6ea90909563d958d",
|
||||
"declaration": {
|
||||
"schema": "paperclip.acpx_profile_declaration.v1",
|
||||
"agent": "copilot",
|
||||
"agentProfileVersion": 87,
|
||||
"acpxVersion": "0.13.1",
|
||||
"agentServerVersion": "1.0.88",
|
||||
"protocolPolicyRevision": "copilot-agent-manual-v1",
|
||||
"acpxPatchSha256": "1e7dae8c83bf8620f53f2bea13c175eeff95e7e955783f6f529bb1dcbdcdb6d2",
|
||||
"policySha256": "a4be69be43db84052560420a3ca546a665c9165573c24d543eb33d144ba138a3",
|
||||
"distributionSourceSha256": "c0a65e247fc47b263bd369a3d5ab505c4b323d4e6493be8a9ecbeb0e9dbb9107",
|
||||
"agentFilesBinding": "registered-runtime-context-v1",
|
||||
"systemInstructionDelivery": "COPILOT_HOME/copilot-instructions.md:replace-under-lifetime-lease-before-launch:v1",
|
||||
"sharedRuntimeContract": "paperclip.acpx-runtime-contract.v1",
|
||||
"innerDistributionSourceSha256": "9bb08347eed01f1ab44e065c8b06ead9be3a25973d6e6329dc4c0a099096279a",
|
||||
"upstreamAppSha256": "7b48282a19b5b0814a0c96ad5e3a125173d792cc55f9525b2effea962f6063c0",
|
||||
"patchedAppSha256": "61f8eebe0c30cc03b311c6818b2acb158a6d16ca58c8bfac5ebd42db095c2679",
|
||||
"messageIdentityContract": "copilot-native-message-id-v1",
|
||||
"ownedDistributionDelivery": "COPILOT_CLI_DIST_DIR:lease-owned-guarded-inner-distribution:v1",
|
||||
"permissionContextContract": "copilot-edit-permission-context-v1",
|
||||
"permissionContextSourceSha256": "de2d38d702b3c574161af0c0c04790fb6f6347916eb3916ce7a131a8c229121b",
|
||||
"permissionAdapterSourceSha256": "ee5929ed2ee647ad0369465dee9d51a00b2dd28e1ff735b43e969ddc9c164668",
|
||||
"permissionLocationsSourceSha256": "f39a81da395b6e23aa2a1a45572a28846e5e81bfd3d764d9a456f74a79c752e9",
|
||||
"permissionRedactionSourceSha256": "ad6770c69269087951790e2e87e22ac088e3d432769adf17ebc865ed512e6c4f",
|
||||
"permissionClassifierSourceSha256": "1161eabd82e26133e3b3db3ab567f65d52808b03f176e93497e02c8330349fb4",
|
||||
"semanticToolReceiptContract": "paperclip.semantic_tool_receipt.v2",
|
||||
"semanticReceiptSourceSha256": "b2795726b2234a663fec1a6ca11f0551ae69882fe9e82aa39686e952d036e791",
|
||||
"semanticBridgeSourceSha256": "8764b8c9032fdc7d1415b01e75a9fc57c550e7a5e11da4bed7d9100082872ae5",
|
||||
"toolEvidenceSourceSha256": "6eef5039afc75bb851eaf9cd82a6f099e4bd398ca2deb59dd66f5b2a81a7a706",
|
||||
"semanticNormalizedInputContract": "validated-forwarded-input-commit-v1",
|
||||
"semanticSidecarSourceSha256": "b6d5888f47a47838c507a43fbe31a778ac63d4fcbcdc9a869108f604c34c3824",
|
||||
"semanticDirectDriverSourceSha256": "4ec65aa1d4e905a1e732f2d043bbd39de1ab92f380276ede37d6a72efc19c64d",
|
||||
"semanticValidationSourceSha256": "02fbb92681c78c5de5d2f1aae25aabc25a0e5df6b0ff4baccac652192a8da975",
|
||||
"semanticNormalizationSourceSha256": "8b628b82e8eacc91cdcc6fdca2210ba4cf282f01e9c6f74e95ff271655b5047e",
|
||||
"semanticCompletionContractSourceSha256": "f49398b682a5623812f5d3c33d6bb9a749008e47cc0ed969072041615f66df59",
|
||||
"semanticValidatorsSourceSha256": "b20ec8ee6e7165117233ce4421a975bb9d3f276220ce31655c0b9a717cb2d9cb",
|
||||
"semanticSchemaBundleSourceSha256": "81ef98ca7b34896a0f76390ac7af3dd8ef7609fe6f38d54bd6a69373d50fe40b",
|
||||
"semanticSidecarProtocolSourceSha256": "26b6b21dad582810d00f46e947e682a9615ee9761c487f6315970d6d014c05ab",
|
||||
"semanticSidecarReceiptCommitContract": "correlated-tool-resolve-v1",
|
||||
"displayEventSourceSha256": "d72f9a6035c247bc6a42c067c05753076c54322c4b58984e93922f3325dc6877",
|
||||
"displayProjectionSourceSha256": "75952606b26dd93bbc582c1f0a4424487377272ea745fb3a27ceae031fd5dc7e",
|
||||
"configuredEnvironmentSourceSha256": "ecef0ada320a762e0a3d91c38c72d4e19e2c8e8be8c060938a47e7f1a029058a",
|
||||
"configuredEnvironmentRustSourceSha256": "1671cb2735b3fa119d32f08d4a12b21b9f78a0e4d7285eb63c35df79ce17bd3c",
|
||||
"profileActivitySourceSha256": "4fdb6b0f9125fd8372ba6f27945fa5c8a3d3b2ec891df544092e3dc7a75d5282",
|
||||
"profileExtensionsSourceSha256": "a80ddc95eb4505095bfdbbf85c758199949ab20be9c84b34c77f762eb7180571",
|
||||
"profileInstallationSourceSha256": "58841b2d3b47ab9956db20608802edcd0e55cf5856002dc7c51e05e75bdcb8f6",
|
||||
"attachmentPolicySourceSha256": "4f7638b7cc64e18f6a4ba33fd46de2b3d49225e32aeab41f5c695b268fa4f8e2",
|
||||
"singleReadEvidenceSourceSha256": "4069393405089bde613cecec04f5123c426594811da4c668bd96f0e7e283550f",
|
||||
"nativeSessionRuntimeSourceSha256": "cbcefbceb0b2a24b0909cbb8361df6b8853b4f50b21d66328bc483951a8246ea",
|
||||
"nativeRuntimeContextSourceSha256": "71607f80dbb8dc5cc6c123d0b8f3995d6c5407277695a8c82cbedc90fb8f4842",
|
||||
"nativeRuntimePromptsSourceSha256": "fff5755dba9b7dce8a5f10ff6ac6d5ed06b92ed079ce1e0a44ac72f2ce7869c1",
|
||||
"nativeSessionContractSourceSha256": "22a8c96ce41ba4f03e976fc37f0cc7c5d05cee99fa789941da31ee1dab440b90",
|
||||
"harnessSessionContractSourceSha256": "baba1a210b863518f01e0c875606ed37f9467c433222251438578bd999bc43b5",
|
||||
"harnessBackendSourceSha256": "dc827e281ae6731545b166ee4d709a4f67f594a556dcbe63c70fe8f1aca26249",
|
||||
"harnessSessionSourceSha256": "bb9bb3daac53ce5955ddf8f56839c7a57ae60c74ea3cdd08895ab6912fcf7851",
|
||||
"transportContractSourceSha256": "06f06c53ecae304f72034ffb2f659ff087c82a70ed4994daf21a9d2edaf56e4e",
|
||||
"nativeBackendSourceSha256": "7495d9898d22dca1ebf6336361d332bafefc4498f6e49f1135025fad846c8586",
|
||||
"nativeBackendFactorySourceSha256": "7e431c926b76d53c4c08e3a4105353dcd34bd940f6588a1a68f79631f6feeb44",
|
||||
"nativeInstructionsSourceSha256": "82ac6e5f7275b4ef79fb166c7330efc504e80cab3d7e9081e4e40a8b570bc50b",
|
||||
"providerLaunchSourceSha256": "c744235b3067ea75973523f78f1e13399337bc155f1775af694e34782d5c9bef",
|
||||
"launchPreparationStoreSourceSha256": "ff6025568bbc0aa6ce545772d73dfca2d3da226740bd3a7b386b069e76cff296",
|
||||
"runtimeRequestBridgeSourceSha256": "8bf5c2ed6d6223144f7eb777e97973655301f5be10d9734f025cfc2b0bdff431",
|
||||
"runtimeRequestFacadeSourceSha256": "23361d25e660ef7919bfb54f21727b899e7d6f8865307604ee15eca7488afeaa",
|
||||
"runtimeRequestNotificationSourceSha256": "6196c6175f11c69295dc00fc773201f4fdeca26c500653870253c43b81e65211",
|
||||
"guardedInstallationSourceSha256": "64b137e3ef695e7d03013ea2b6c8830171e0a73e0bf2e73d55e9ced57a47bcf6",
|
||||
"nativeExecutionSourceSha256": "116c348e232848a80c5556494c109314baafb20fb5c97133d9656c7732ee54be",
|
||||
"profileCompatibilitySourceSha256": "a924a9accec7708823acdd6b7ad0725b5cd9a6ce8d924671d1075907bf0fc8a9",
|
||||
"installationSourceSha256": "a1c7c6f103b898216973e77ffbac0ef7572e250aa574d1a4065270e9dfa0dc2d",
|
||||
"assetOwnershipSourceSha256": "e5bb6bc58b3f0e957a64b2cd99c710337ffcd9c0e1fadb341f48e033b64b99f5",
|
||||
"assetInstallerSourceSha256": "d3bd9514e5920d0cc3567aa50487fb534c57a6f66b8da0d3f22c5f6e499c841f",
|
||||
"credentialBindingSourceSha256": "2ed68b9aed9756fdd682721833eb2aeaa58f30f1dc8825c88886cc8e7ee92abe",
|
||||
"admissionDiagnosticsSourceSha256": "df8f1aa4f2d1bc63b2635bdd09cb8165c8b7681ddcc2618435c7c08ca90475af",
|
||||
"grokAdmissionSourceSha256": "f1e46cf2e1e36b7704bd797b678e3db8db2003f97bdb9d827cfa3d7662698777",
|
||||
"sidecarErrorSourceSha256": "17948ad74350dc487ab20d24a0fb89daf0b426b98396454fff0e3856e922d82c",
|
||||
"profileSourceSha256": "f5538b3dbefa7634a332b87d5ededcefb56aa7e5790cede1c7a0d948a548a456",
|
||||
"metadataProbeSourceSha256": "be4c8416edd27061109bc1f33d0c26071b4facbb3f651beaae6b3c0275cce727",
|
||||
"permissionToolIdentitySourceSha256": "770b47305e571a81f344883057d0e4a482a1cd59ac77d045836593a8e739deb1",
|
||||
"semanticContinuationSourceSha256": "c9cc0fd516b3df92a6655f56ee9bef37615a889c371e2e137d8ac5c1176de811",
|
||||
"preparedHarnessHomeSourceSha256": "bb286f7ddc6e9597c56d46bf7ff6e3b556c5b680d7e147fd46518724432b083e",
|
||||
"runtimeHostSourceSha256": "26b2e115b3f4ae7c20e9d963d117e0286c958af81386deade83397f12abf9662",
|
||||
"runtimeAdapterSourceSha256": "fab1e278e0f2aed55b35e57d14329eb431b79a08040fa079aa2403842d16085e",
|
||||
"runtimeSandboxSourceSha256": "b9f05e522f92b6bade51c7a17f8d28bf31ab9db26510b8d5ddce8519d563a875",
|
||||
"cancellationSourceSha256": "a07d1a9e982dec0ae130c1ad1efa5bc75c6a39e013b730ba3ee45256f09ceeca",
|
||||
"agentFilesSourceSha256": "fb32f6badc13dfa22f231479509b631b2f0eba0c99b1ab9f3cd5c0c601aa03ba",
|
||||
"nativeDistributionSourceSha256": "aed327c389e957483a503cb1bb8b247ee7cd7ff4b528fb4567c39bcb4577690b"
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user