fix(runner): restore provider plan negotiation
This commit is contained in:
parent
da949fe78f
commit
db1a18d5ab
|
|
@ -92,6 +92,10 @@ function createTransportBackedNativeSessionBackend(
|
|||
): NativeSessionBackend {
|
||||
const driverIdentity = transportDriverIdentity(input);
|
||||
const isCodex = input.provider.kind === "codex";
|
||||
const supportsCollaborativePlanning =
|
||||
isCodex ||
|
||||
input.provider.kind === "opencode" ||
|
||||
input.provider.kind === "acpx";
|
||||
if (
|
||||
input.provider.kind === "codex"
|
||||
&& input.provider.approvalPolicy !== undefined
|
||||
|
|
@ -113,14 +117,18 @@ function createTransportBackedNativeSessionBackend(
|
|||
baseInstructions: nativeSystemInstructions(input),
|
||||
includeSkillInstructions: isCodex && "runtimeContext" in input,
|
||||
requestedCollaborationMode:
|
||||
isCodex && "executionMode" in input ? input.executionMode : "default",
|
||||
supportsCollaborativePlanning && "executionMode" in input
|
||||
? input.executionMode
|
||||
: "default",
|
||||
taskEnvelope: createCodexTaskEnvelope({
|
||||
objective: input.completionContract.contract.objective,
|
||||
contractRevision: input.completionContract.contract.revision,
|
||||
criteria: input.completionContract.contract.criteria,
|
||||
constraints: [
|
||||
"Work only inside the supplied working directory.",
|
||||
...(isCodex && "executionMode" in input && input.executionMode === "plan"
|
||||
...(supportsCollaborativePlanning &&
|
||||
"executionMode" in input &&
|
||||
input.executionMode === "plan"
|
||||
? [
|
||||
"Use native plan collaboration mode and do not modify workspace files.",
|
||||
"Treat the supplied Paperclip planning context as the canonical pinned base revision.",
|
||||
|
|
@ -143,7 +151,9 @@ function createTransportBackedNativeSessionBackend(
|
|||
capabilities: isCodex
|
||||
? {}
|
||||
: { steering: false, goals: false, threadLineage: false },
|
||||
collaborationModes: isCodex ? ["default", "plan"] : ["default"],
|
||||
collaborationModes: supportsCollaborativePlanning
|
||||
? ["default", "plan"]
|
||||
: ["default"],
|
||||
requireProviderSessionIdentity: options.transportFactory !== undefined,
|
||||
}));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { describe, expect, it } from "vitest";
|
||||
|
||||
import type { NativeExecutionInput } from "../contracts/native-execution.js";
|
||||
import { FakeCodexTransport } from "../drivers/codex/codex-app-server-driver.test-support.js";
|
||||
import { createNativeSessionBackend } from "../index.js";
|
||||
import { createCodexNativeSessionBackend } from "./codex-native-backend.js";
|
||||
|
||||
|
|
@ -126,6 +127,23 @@ function opencodeExecution(): NativeExecutionInput {
|
|||
};
|
||||
}
|
||||
|
||||
function planningExecution(input: NativeExecutionInput): NativeExecutionInput {
|
||||
return {
|
||||
...input,
|
||||
schema: "paperclip.native-execution-input.v2",
|
||||
task: { ...input.task, workMode: "planning" },
|
||||
executionMode: "plan",
|
||||
planningContext: {
|
||||
documentId: null,
|
||||
baseRevisionId: null,
|
||||
baseRevisionNumber: 0,
|
||||
markdown: "",
|
||||
sha256: "empty-plan",
|
||||
reviewContext: {},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function managedExecution(
|
||||
kind: "claude_managed" | "aws_agentcore",
|
||||
): NativeExecutionInput {
|
||||
|
|
@ -251,10 +269,53 @@ describe("native backend factory", () => {
|
|||
resume: true,
|
||||
interruption: true,
|
||||
dynamicTools: true,
|
||||
collaborationModes: ["default", "plan"],
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it.each([
|
||||
["OpenCode", opencodeExecution()],
|
||||
["ACPX Codex", acpxExecution("codex")],
|
||||
["ACPX Claude", acpxExecution("claude")],
|
||||
])(
|
||||
"opens %s planning runs through the runner-managed plan contract",
|
||||
async (_label, input) => {
|
||||
const transport = new FakeCodexTransport();
|
||||
const backend = createNativeSessionBackend(planningExecution(input), {
|
||||
codexTransportFactory: () => transport,
|
||||
});
|
||||
|
||||
await expect(backend.descriptor()).resolves.toMatchObject({
|
||||
capabilities: { collaborationModes: ["default", "plan"] },
|
||||
});
|
||||
const session = await backend.openSession({
|
||||
identity: {
|
||||
runId: "run",
|
||||
sessionId: "session",
|
||||
companyId: "company",
|
||||
issueId: "issue",
|
||||
agentId: "agent",
|
||||
},
|
||||
workingDirectory: process.cwd(),
|
||||
});
|
||||
|
||||
await expect(
|
||||
session.startTurn({
|
||||
message: { role: "user", text: "Author a plan." },
|
||||
requestedCollaborationMode: "plan",
|
||||
}),
|
||||
).resolves.toMatchObject({ effectiveCollaborationMode: "plan" });
|
||||
expect(
|
||||
transport.calls.find((call) => call.method === "thread/start")?.params,
|
||||
).toMatchObject({ permissions: "paperclip-runner-workspace-read-only" });
|
||||
expect(
|
||||
transport.calls.find((call) => call.method === "turn/start")?.params,
|
||||
).toMatchObject({ collaborationMode: { mode: "plan" } });
|
||||
await session.close({ reason: "test complete" });
|
||||
},
|
||||
);
|
||||
|
||||
it.each([
|
||||
[
|
||||
"claude_managed" as const,
|
||||
|
|
@ -337,6 +398,7 @@ describe("native backend factory", () => {
|
|||
resume: true,
|
||||
interruption: true,
|
||||
dynamicTools: true,
|
||||
collaborationModes: ["default", "plan"],
|
||||
},
|
||||
});
|
||||
},
|
||||
|
|
|
|||
Loading…
Reference in New Issue