Merge branch 'codex/work-folders-storybook-refresh' into codex/work-folders-runtime-hardening-refresh
* codex/work-folders-storybook-refresh: fix: keep supported ACPX profiles available in the Pi layer test: wait for active Daytona transfers before teardown
This commit is contained in:
commit
b79f09ef24
|
|
@ -4854,15 +4854,21 @@ describe("daytona native file-sync hooks", () => {
|
|||
// Hold the inbound upload and the outbound download open at the same time, so
|
||||
// the shared lease has two active sync calls when teardown starts.
|
||||
let releaseUpload!: () => void;
|
||||
let uploadStarted!: () => void;
|
||||
const uploadReady = new Promise<void>((resolve) => { uploadStarted = resolve; });
|
||||
sandbox.fs.uploadFiles.mockImplementation(async () => {
|
||||
await new Promise<void>((resolve) => {
|
||||
releaseUpload = resolve;
|
||||
uploadStarted();
|
||||
});
|
||||
});
|
||||
let releaseDownload!: () => void;
|
||||
let downloadStarted!: () => void;
|
||||
const downloadReady = new Promise<void>((resolve) => { downloadStarted = resolve; });
|
||||
sandbox.fs.downloadFiles.mockImplementation(async (requests: Array<{ source: string; destination: string }>) => {
|
||||
await new Promise<void>((resolve) => {
|
||||
releaseDownload = resolve;
|
||||
downloadStarted();
|
||||
});
|
||||
return Promise.all(
|
||||
requests.map(async (request) => {
|
||||
|
|
@ -4879,9 +4885,9 @@ describe("daytona native file-sync hooks", () => {
|
|||
const outboundCall = plugin.definition.onEnvironmentSyncOut?.(
|
||||
syncOutParams({ operationId: "out-active", sourcePath: `${REMOTE_DIR}/out.txt`, targetPath: outboundTarget }),
|
||||
);
|
||||
// Let both sync calls register on the activity gate and reach their hung
|
||||
// transfer, so teardown sees a refCount of two.
|
||||
await new Promise((resolve) => setTimeout(resolve, 0));
|
||||
// Wait for both actual transfers, rather than assuming one event-loop tick
|
||||
// completes the asynchronous filesystem preparation on a busy runner.
|
||||
await Promise.all([uploadReady, downloadReady]);
|
||||
|
||||
const destroyCall = plugin.definition.onEnvironmentDestroyLease?.({
|
||||
driverKey: "daytona",
|
||||
|
|
|
|||
|
|
@ -279,6 +279,8 @@ describe("server adapter registry", () => {
|
|||
|
||||
it.each([
|
||||
["claude", "claude-sonnet-5"],
|
||||
["codex", "gpt-5.6-sol"],
|
||||
["pi", "openrouter/deepseek/deepseek-v4-flash-0731"],
|
||||
] as const)("does not claim runtime readiness from the remote ACPX %s platform alone", async (acpxAgent, model) => {
|
||||
const result = await requireServerAdapter("paperclip_runner").testEnvironment({
|
||||
companyId: "company-1",
|
||||
|
|
@ -315,20 +317,23 @@ describe("server adapter registry", () => {
|
|||
});
|
||||
});
|
||||
|
||||
it("accepts the qualified ACPX Pi profile", async () => {
|
||||
it.each([
|
||||
["codex", "gpt-5.6-sol"],
|
||||
["pi", "openrouter/deepseek/deepseek-v4-flash-0731"],
|
||||
])("accepts qualified ACPX %s without claiming installation readiness", async (acpxAgent, model) => {
|
||||
const result = await requireServerAdapter("paperclip_runner").testEnvironment({
|
||||
companyId: "company-1",
|
||||
adapterType: "paperclip_runner",
|
||||
config: {
|
||||
provider: "acpx",
|
||||
acpxAgent: "pi",
|
||||
model: "openrouter/deepseek/deepseek-v4-flash-0731",
|
||||
acpxAgent,
|
||||
model,
|
||||
},
|
||||
});
|
||||
|
||||
expect(result).toMatchObject({
|
||||
status: "pass",
|
||||
checks: [{ code: "acpx_profile_qualified", level: "info" }],
|
||||
status: "warn",
|
||||
checks: [{ code: "acpx_runtime_unverified", level: "warn" }],
|
||||
});
|
||||
});
|
||||
it("wraps built-in npm runtime installs with the sandbox-aware install helper", () => {
|
||||
|
|
|
|||
|
|
@ -405,7 +405,6 @@ const paperclipRunnerAdapter: ServerAdapterModule = {
|
|||
}
|
||||
if (profile.provider === "acpx") {
|
||||
try {
|
||||
if (profile.acpxAgent !== "claude") throw new Error("Select Codex to use the native Codex runner.");
|
||||
const target = context.executionTarget;
|
||||
if (target?.kind === "remote") {
|
||||
const probe = await runAdapterExecutionTargetShellCommand(
|
||||
|
|
@ -414,8 +413,8 @@ const paperclipRunnerAdapter: ServerAdapterModule = {
|
|||
);
|
||||
if (probe.timedOut || probe.exitCode !== 0) throw new Error("Could not verify the remote ACPX runner platform.");
|
||||
const [os, arch] = probe.stdout.trim().split(/\s+/);
|
||||
if (!((os === "Linux" && arch === "x86_64") || (os === "Darwin" && ["arm64", "x86_64"].includes(arch ?? "")))) {
|
||||
throw new Error("ACPX Claude requires Linux x64 or macOS ARM64/x64.");
|
||||
if (!((os === "Linux" && arch === "x86_64") || (profile.acpxAgent === "claude" && os === "Darwin" && ["arm64", "x86_64"].includes(arch ?? "")))) {
|
||||
throw new Error(`ACPX ${profile.acpxAgent} requires Linux x64${profile.acpxAgent === "claude" ? " or macOS ARM64/x64" : ""}.`);
|
||||
}
|
||||
return {
|
||||
adapterType: "paperclip_runner", status: "warn" as const, testedAt: new Date().toISOString(),
|
||||
|
|
@ -423,6 +422,13 @@ const paperclipRunnerAdapter: ServerAdapterModule = {
|
|||
message: "The remote platform is supported. Runtime package integrity and readiness must still be verified by the remote runner before launch." }],
|
||||
};
|
||||
}
|
||||
if (profile.acpxAgent !== "claude") {
|
||||
return {
|
||||
adapterType: "paperclip_runner", status: "warn" as const, testedAt: new Date().toISOString(),
|
||||
checks: [{ code: "acpx_runtime_unverified", level: "warn" as const,
|
||||
message: `The ACPX ${profile.acpxAgent} profile is qualified. Runtime package integrity, platform support, and readiness must still be verified by the runner before launch.` }],
|
||||
};
|
||||
}
|
||||
const { probeAcpxClaudeInstallation } = await import("@paperclipai/paperclip-runner/live");
|
||||
await probeAcpxClaudeInstallation(profile.model);
|
||||
return {
|
||||
|
|
|
|||
Loading…
Reference in New Issue