mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-02 18:00:21 +00:00
refactor: dedupe cli runner session reuse
This commit is contained in:
@@ -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",
|
||||
});
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user