refactor: dedupe cli runner session reuse

This commit is contained in:
Peter Steinberger
2026-03-26 20:35:19 +00:00
parent 61d29efc04
commit 3f54076d37
2 changed files with 80 additions and 112 deletions

View File

@@ -156,6 +156,46 @@ async function runCliAgentWithBackendConfig(params: {
});
}
const EXISTING_CODEX_CONFIG = {
agents: {
defaults: {
cliBackends: {
"codex-cli": {
command: "codex",
args: ["exec", "--json"],
resumeArgs: ["exec", "resume", "{sessionId}", "--json"],
output: "text",
modelArg: "--model",
sessionMode: "existing",
},
},
},
},
} satisfies OpenClawConfig;
async function runExistingCodexCliAgent(params: {
runId: string;
cliSessionBindingAuthProfileId: string;
authProfileId: string;
}) {
await runCliAgent({
sessionId: "s1",
sessionFile: "/tmp/session.jsonl",
workspaceDir: "/tmp",
config: EXISTING_CODEX_CONFIG,
prompt: "hi",
provider: "codex-cli",
model: "gpt-5.4",
timeoutMs: 1_000,
runId: params.runId,
cliSessionBinding: {
sessionId: "thread-123",
authProfileId: params.cliSessionBindingAuthProfileId,
},
authProfileId: params.authProfileId,
});
}
describe("runCliAgent with process supervisor", () => {
afterEach(() => {
vi.unstubAllEnvs();
@@ -238,35 +278,9 @@ describe("runCliAgent with process supervisor", () => {
it("keeps resuming the CLI across model changes and passes the new model flag", async () => {
mockSuccessfulCliRun();
await runCliAgent({
sessionId: "s1",
sessionFile: "/tmp/session.jsonl",
workspaceDir: "/tmp",
config: {
agents: {
defaults: {
cliBackends: {
"codex-cli": {
command: "codex",
args: ["exec", "--json"],
resumeArgs: ["exec", "resume", "{sessionId}", "--json"],
output: "text",
modelArg: "--model",
sessionMode: "existing",
},
},
},
},
} satisfies OpenClawConfig,
prompt: "hi",
provider: "codex-cli",
model: "gpt-5.4",
timeoutMs: 1_000,
await runExistingCodexCliAgent({
runId: "run-model-switch",
cliSessionBinding: {
sessionId: "thread-123",
authProfileId: "openai:default",
},
cliSessionBindingAuthProfileId: "openai:default",
authProfileId: "openai:default",
});
@@ -286,35 +300,9 @@ describe("runCliAgent with process supervisor", () => {
it("starts a fresh CLI session when the auth profile changes", async () => {
mockSuccessfulCliRun();
await runCliAgent({
sessionId: "s1",
sessionFile: "/tmp/session.jsonl",
workspaceDir: "/tmp",
config: {
agents: {
defaults: {
cliBackends: {
"codex-cli": {
command: "codex",
args: ["exec", "--json"],
resumeArgs: ["exec", "resume", "{sessionId}", "--json"],
output: "text",
modelArg: "--model",
sessionMode: "existing",
},
},
},
},
} satisfies OpenClawConfig,
prompt: "hi",
provider: "codex-cli",
model: "gpt-5.4",
timeoutMs: 1_000,
await runExistingCodexCliAgent({
runId: "run-auth-change",
cliSessionBinding: {
sessionId: "thread-123",
authProfileId: "openai:work",
},
cliSessionBindingAuthProfileId: "openai:work",
authProfileId: "openai:personal",
});

View File

@@ -446,39 +446,46 @@ export async function runCliAgent(params: {
}
};
const buildCliRunResult = (resultParams: {
output: Awaited<ReturnType<typeof executeCliWithSession>>;
effectiveCliSessionId?: string;
}): EmbeddedPiRunResult => {
const text = resultParams.output.text?.trim();
const payloads = text ? [{ text }] : undefined;
return {
payloads,
meta: {
durationMs: Date.now() - started,
systemPromptReport,
agentMeta: {
sessionId: resultParams.effectiveCliSessionId ?? params.sessionId ?? "",
provider: params.provider,
model: modelId,
usage: resultParams.output.usage,
...(resultParams.effectiveCliSessionId
? {
cliSessionBinding: {
sessionId: resultParams.effectiveCliSessionId,
...(params.authProfileId ? { authProfileId: params.authProfileId } : {}),
...(extraSystemPromptHash ? { extraSystemPromptHash } : {}),
...(preparedBackend.mcpConfigHash
? { mcpConfigHash: preparedBackend.mcpConfigHash }
: {}),
},
}
: {}),
},
},
};
};
// Try with the provided CLI session ID first
try {
try {
const output = await executeCliWithSession(reusableCliSession.sessionId);
const text = output.text?.trim();
const payloads = text ? [{ text }] : undefined;
const effectiveCliSessionId = output.sessionId ?? reusableCliSession.sessionId;
return {
payloads,
meta: {
durationMs: Date.now() - started,
systemPromptReport,
agentMeta: {
sessionId: effectiveCliSessionId ?? params.sessionId ?? "",
provider: params.provider,
model: modelId,
usage: output.usage,
...(effectiveCliSessionId
? {
cliSessionBinding: {
sessionId: effectiveCliSessionId,
...(params.authProfileId ? { authProfileId: params.authProfileId } : {}),
...(extraSystemPromptHash ? { extraSystemPromptHash } : {}),
...(preparedBackend.mcpConfigHash
? { mcpConfigHash: preparedBackend.mcpConfigHash }
: {}),
},
}
: {}),
},
},
};
return buildCliRunResult({ output, effectiveCliSessionId });
} catch (err) {
if (err instanceof FailoverError) {
// Check if this is a session expired error and we have a session to clear
@@ -493,35 +500,8 @@ export async function runCliAgent(params: {
// For now, retry without the session ID to create a new session
const output = await executeCliWithSession(undefined);
const text = output.text?.trim();
const payloads = text ? [{ text }] : undefined;
const effectiveCliSessionId = output.sessionId;
return {
payloads,
meta: {
durationMs: Date.now() - started,
systemPromptReport,
agentMeta: {
sessionId: output.sessionId ?? params.sessionId ?? "",
provider: params.provider,
model: modelId,
usage: output.usage,
...(effectiveCliSessionId
? {
cliSessionBinding: {
sessionId: effectiveCliSessionId,
...(params.authProfileId ? { authProfileId: params.authProfileId } : {}),
...(extraSystemPromptHash ? { extraSystemPromptHash } : {}),
...(preparedBackend.mcpConfigHash
? { mcpConfigHash: preparedBackend.mcpConfigHash }
: {}),
},
}
: {}),
},
},
};
return buildCliRunResult({ output, effectiveCliSessionId });
}
throw err;
}