mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-10-28 12:04:41 +01:00
fix(runner): retain stages after provider error translation
Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
1 parent
0c904a7e42
commit
cb8f9025e4
7 files changed
+37
-8
No files matched your search
@@ -37,7 +37,7 @@
|
||||
"agentServerVersion": "1.0.88",
|
||||
"agentRuntimePackage": null,
|
||||
"agentRuntimeVersion": null,
|
||||
"commandDigest": "sha256:6326444af8fd447032ca8ad10ce3a1280af9aeeddacd563cf48b430202dbbefd",
|
||||
"commandDigest": "sha256:754e74c58bc9b22b49d38e0b9ff0a4708caff46abf6ac531975ea2d91c27de41",
|
||||
"requiresProviderPolicy": true
|
||||
},
|
||||
"claude": {
|
||||
|
||||
@@ -47,7 +47,7 @@ pub(crate) fn acpx_release_profile(agent: &str) -> Option<AcpxReleaseProfile> {
|
||||
agent_runtime_package: None,
|
||||
agent_runtime_version: None,
|
||||
command_digest:
|
||||
"sha256:6326444af8fd447032ca8ad10ce3a1280af9aeeddacd563cf48b430202dbbefd",
|
||||
"sha256:754e74c58bc9b22b49d38e0b9ff0a4708caff46abf6ac531975ea2d91c27de41",
|
||||
requires_provider_policy: true,
|
||||
},
|
||||
"claude" => AcpxReleaseProfile {
|
||||
|
||||
@@ -89,7 +89,7 @@ describe("Copilot build-owned installation", () => {
|
||||
it("admits the current profile with environment launch preparation", () => {
|
||||
expect(QUALIFIED_ACPX_PROFILES.copilot.agentProfileVersion).toBe(70);
|
||||
expect(QUALIFIED_ACPX_PROFILES.copilot.qualificationStatus).toBeUndefined();
|
||||
expect(QUALIFIED_ACPX_PROFILES.copilot.commandDigest).toBe("sha256:6326444af8fd447032ca8ad10ce3a1280af9aeeddacd563cf48b430202dbbefd");
|
||||
expect(QUALIFIED_ACPX_PROFILES.copilot.commandDigest).toBe("sha256:754e74c58bc9b22b49d38e0b9ff0a4708caff46abf6ac531975ea2d91c27de41");
|
||||
});
|
||||
|
||||
it("preserves v69 while binding closed startup diagnostics in v70", async () => {
|
||||
|
||||
@@ -53,7 +53,7 @@ export const QUALIFIED_ACPX_PROFILE_DATA = {
|
||||
"agentServerVersion": "1.0.88",
|
||||
"agentRuntimePackage": null,
|
||||
"agentRuntimeVersion": null,
|
||||
"commandDigest": "sha256:6326444af8fd447032ca8ad10ce3a1280af9aeeddacd563cf48b430202dbbefd",
|
||||
"commandDigest": "sha256:754e74c58bc9b22b49d38e0b9ff0a4708caff46abf6ac531975ea2d91c27de41",
|
||||
"permissionPolicy": "interactive"
|
||||
},
|
||||
"claude": {
|
||||
|
||||
@@ -203,6 +203,35 @@ afterEach(async () => {
|
||||
});
|
||||
|
||||
describe("ACPX runtime host", () => {
|
||||
it("retains the admission stage when provider classification replaces the error", async () => {
|
||||
const fixture = await hostFixture();
|
||||
const openRuntime = vi.fn(async () => { throw new Error("Unauthorized private-token-canary"); });
|
||||
const failure = await AcpxRuntimeHost.open({ ...fixture.options, agent: "copilot", model: "gpt-5.6-sol",
|
||||
permissionMode: "approve-all", environment: {COPILOT_GITHUB_TOKEN:"synthetic-test-token"} }, fixture.dependencies({openRuntime})).catch(error => error);
|
||||
expect(failure).toMatchObject({code:"COPILOT_AUTH_REQUIRED"});
|
||||
expect(acpxSidecarErrorCode(failure)).toBe("ACPX_ADMISSION_RUNTIME");
|
||||
expect(failure.message).not.toContain("private-token-canary");
|
||||
expect(openRuntime).toHaveBeenCalledOnce();
|
||||
expect(fixture.commandClose).toHaveBeenCalledOnce();
|
||||
});
|
||||
it("reports failed Pi skill materialization as skills admission before launch", async () => {
|
||||
const fixture = await hostFixture();
|
||||
const digest = "0".repeat(64);
|
||||
const bundle = {schema:NATIVE_RUNTIME_ASSET_SCHEMA,digest,manifestDigest:digest,
|
||||
rootPath:join(fixture.root,"missing-assigned-skill"),fileCount:1,totalBytes:1};
|
||||
const snapshot = {prompt:{revision:PAPERCLIP_EXECUTION_PROMPT_REVISION,text:PAPERCLIP_EXECUTION_PROMPT,digest:nativeRuntimePromptDigest()},
|
||||
instructions:{entryPath:"AGENTS.md",bundle},skills:[{key:"assigned",runtimeName:"assigned",versionId:"v1",bundle}],
|
||||
mcp:{assignmentSetId:"none",digest,bindingId:null}};
|
||||
const context = {...snapshot,aggregateDigest:canonicalNativeRuntimeContextDigest(snapshot)};
|
||||
const openRuntime = vi.fn(async () => runtimePort());
|
||||
const failure = await AcpxRuntimeHost.open({ ...fixture.options, agent:"pi",model:"anthropic/claude-sonnet-5",
|
||||
piThinkingLevel:"low",permissionMode:"approve-all",providerPolicy:{readOnly:false},runtimeContext:context },fixture.dependencies({openRuntime})).catch(error => error);
|
||||
expect(failure).toBeInstanceOf(Error);
|
||||
expect(failure.message).toContain("missing-assigned-skill");
|
||||
expect(acpxSidecarErrorCode(failure)).toBe("ACPX_ADMISSION_SKILLS");
|
||||
expect(openRuntime).not.toHaveBeenCalled();
|
||||
expect(fixture.commandClose).not.toHaveBeenCalled();
|
||||
});
|
||||
it.each(["installation", "sandbox", "credential", "runtime"] as const)("retains the failed %s admission stage through the sidecar boundary", async stage => {
|
||||
const fixture = await hostFixture();
|
||||
const failure = new Error("private-token-canary");
|
||||
|
||||
@@ -552,6 +552,7 @@ export class AcpxRuntimeHost {
|
||||
);
|
||||
options.signal?.throwIfAborted();
|
||||
}
|
||||
admissionStage = "skills";
|
||||
if (options.agent === "pi") {
|
||||
const skills = await acquireAbortableAdmissionResource({
|
||||
signal: options.signal,
|
||||
@@ -574,7 +575,6 @@ export class AcpxRuntimeHost {
|
||||
PAPERCLIP_PI_READ_ROOTS: JSON.stringify([...(options.providerPolicy?.readRoots ?? []), ...skills.readRoots]),
|
||||
});
|
||||
}
|
||||
admissionStage = "skills";
|
||||
if (!preconfigured && (options.agent === "claude" || options.agent === "grok")) {
|
||||
// The lifetime lease proves the previous provider has stopped. Refresh
|
||||
// the assigned snapshot before every launch, including durable resume;
|
||||
@@ -742,8 +742,8 @@ export class AcpxRuntimeHost {
|
||||
: [],
|
||||
});
|
||||
} catch (error) {
|
||||
recordAcpxAdmissionFailure(error, admissionStage);
|
||||
error = classifyAcpxProfileError(options.agent, error) ?? error;
|
||||
recordAcpxAdmissionFailure(error, admissionStage);
|
||||
const cleanup = cleanupRuntimeResources(
|
||||
runtime,
|
||||
toolBridge,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"commandDigest": "sha256:6326444af8fd447032ca8ad10ce3a1280af9aeeddacd563cf48b430202dbbefd",
|
||||
"commandDigest": "sha256:754e74c58bc9b22b49d38e0b9ff0a4708caff46abf6ac531975ea2d91c27de41",
|
||||
"declaration": {
|
||||
"schema": "paperclip.acpx_profile_declaration.v1",
|
||||
"agent": "copilot",
|
||||
@@ -77,7 +77,7 @@
|
||||
"metadataProbeSourceSha256": "be4c8416edd27061109bc1f33d0c26071b4facbb3f651beaae6b3c0275cce727",
|
||||
"permissionToolIdentitySourceSha256": "770b47305e571a81f344883057d0e4a482a1cd59ac77d045836593a8e739deb1",
|
||||
"semanticContinuationSourceSha256": "c9cc0fd516b3df92a6655f56ee9bef37615a889c371e2e137d8ac5c1176de811",
|
||||
"runtimeHostSourceSha256": "f12712a06c9d25ba78f61883d6582237de405e79f38586e20419522e5a7059f2",
|
||||
"runtimeHostSourceSha256": "be14218ad4477e083cfc32f6680fcfed776056a4084615d6b0efd1e521e66232",
|
||||
"runtimeAdapterSourceSha256": "7c47c05306ebe7d1ca6b5d046a96f5726a48adec4d27e7c16788f505f25b5db2",
|
||||
"runtimeSandboxSourceSha256": "981449a4c6d10f682ecf86d834eed07faca30a7d9b419fb8db4973a442a343ec",
|
||||
"cancellationSourceSha256": "a07d1a9e982dec0ae130c1ad1efa5bc75c6a39e013b730ba3ee45256f09ceeca",
|
||||
|
||||
Reference in new issue
Block a user