Skip to content

Commit 8a994de

Browse files
committed
fix(agents): fall back to pi when codex harness is unavailable
1 parent 33be0fb commit 8a994de

3 files changed

Lines changed: 26 additions & 0 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ Docs: https://docs.openclaw.ai
1919
- CLI/context engines: bootstrap and finalize non-legacy context engines for CLI turns while preserving transcript snapshots and deferred maintenance ownership. (#81869) Thanks @sahilsatralkar.
2020
- Telegram: persist polling updates through restart replay so queued same-topic messages resume in order instead of losing context after a gateway restart. (#82256) Thanks @VACInc.
2121
- Gateway/Gmail: abort in-flight Gmail watcher startup and hot-reload restarts before shutdown so reloads cannot spawn `gog serve` after the Gateway is closing. Thanks @frankekn.
22+
- Agents/Codex: fall back to the embedded PI runner when OpenAI's implicit Codex harness preference cannot find a registered Codex plugin, preventing OpenAI-compatible gateway requests from failing with an unregistered harness error. Fixes #82437.
2223
- MCP plugin tools: forward host MCP `tools/call` `AbortSignal` through `createPluginToolsMcpHandlers().callTool` into plugin `tool.execute`, so host cancellation actually cancels in-flight plugin tool calls instead of letting them run to completion. Fixes #82424. (#82443) Thanks @joshavant.
2324
- Plugins: accept `api.on("deactivate")` as a compatibility alias for `gateway_stop`, so external plugin cleanup handlers run on Gateway shutdown instead of being ignored as unknown hooks.
2425
- Media: ignore image MIME and filename hints when bytes sniff as generic containers, so zip/octet-stream payloads mislabeled as images do not become local image media or keep image file extensions when staged.

src/agents/harness/selection.test.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,17 @@ describe("runAgentHarnessAttempt", () => {
210210
expect(piRunAttempt).not.toHaveBeenCalled();
211211
});
212212

213+
it("falls back to PI when the implicit OpenAI Codex harness is unavailable", async () => {
214+
const result = await runAgentHarnessAttempt({
215+
...createAttemptParams(),
216+
provider: "openai",
217+
modelId: "gpt-5.4",
218+
});
219+
220+
expect(result.sessionIdUsed).toBe("pi");
221+
expect(piRunAttempt).toHaveBeenCalledTimes(1);
222+
});
223+
213224
it("honors explicit PI runtime for OpenAI agent model runs", async () => {
214225
const result = await runAgentHarnessAttempt({
215226
...createAttemptParams(providerRuntimeConfig("openai", "pi")),
@@ -402,6 +413,10 @@ describe("selectAgentHarness", () => {
402413
);
403414
});
404415

416+
it("selects PI when the implicit OpenAI Codex harness is unavailable", () => {
417+
expect(selectAgentHarness({ provider: "openai", modelId: "gpt-5.4" }).id).toBe("pi");
418+
});
419+
405420
it("ignores legacy agentRuntime as a runtime policy source", () => {
406421
const config = {
407422
agents: {

src/agents/harness/selection.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ type AgentHarnessSelectionDecision = {
3333
selectedReason:
3434
| "forced_pi"
3535
| "forced_plugin"
36+
// Implicit Codex preference found no registered Codex harness, so PI handled the run.
37+
| "implicit_plugin_unavailable_pi"
3638
// Auto mode chose a registered plugin harness that supports the provider/model.
3739
| "auto_plugin"
3840
// Auto mode found no supporting plugin harness, so PI handled the run.
@@ -109,6 +111,14 @@ function selectAgentHarnessDecision(params: {
109111
candidates: listHarnessCandidates(pluginHarnesses),
110112
});
111113
}
114+
if (runtime === "codex" && policy.runtimeSource === "implicit") {
115+
return buildSelectionDecision({
116+
harness: piHarness,
117+
policy,
118+
selectedReason: "implicit_plugin_unavailable_pi",
119+
candidates: listHarnessCandidates(pluginHarnesses),
120+
});
121+
}
112122
throw new Error(`Requested agent harness "${runtime}" is not registered.`);
113123
}
114124

0 commit comments

Comments
 (0)