diff --git a/patches/@mariozechner__pi-ai@0.42.2.patch b/patches/@mariozechner__pi-ai@0.42.2.patch index 2d1564f23..956de72a0 100644 --- a/patches/@mariozechner__pi-ai@0.42.2.patch +++ b/patches/@mariozechner__pi-ai@0.42.2.patch @@ -34,12 +34,13 @@ index 188a8294f26fe1bfe3fb298a7f58e4d8eaf2a529..a3aeb6a7ff53bc4f7f44362adb950b2c const reasoningItem = JSON.parse(block.thinkingSignature); output.push(reasoningItem); } -@@ -470,6 +476,15 @@ function convertMessages(model, context) { +@@ -470,6 +476,16 @@ function convertMessages(model, context) { } if (output.length === 0) continue; + // OpenAI rejects standalone reasoning items when replaying a tool-only turn. + // Only submit reasoning items when we also submit an assistant message item. ++ // Repro: pnpm test src/agents/openai-responses.reasoning-replay.test.ts + const hasMessage = output.some((item) => item?.type === "message"); + if (!hasMessage) { + for (let i = output.length - 1; i >= 0; i -= 1) { @@ -50,7 +51,7 @@ index 188a8294f26fe1bfe3fb298a7f58e4d8eaf2a529..a3aeb6a7ff53bc4f7f44362adb950b2c messages.push(...output); } else if (msg.role === "toolResult") { -@@ -515,7 +530,7 @@ function convertTools(tools) { +@@ -515,7 +531,7 @@ function convertTools(tools) { name: tool.name, description: tool.description, parameters: tool.parameters, @@ -63,12 +64,13 @@ diff --git a/dist/providers/openai-responses.js b/dist/providers/openai-response index f07085c64390b211340d6a826b28ea9c2e77302f..523ed38a5a6151d6ff08dd89120315e7aaaf19b6 100644 --- a/dist/providers/openai-responses.js +++ b/dist/providers/openai-responses.js -@@ -436,6 +436,15 @@ function convertMessages(model, context) { +@@ -436,6 +436,16 @@ function convertMessages(model, context) { } if (output.length === 0) continue; + // OpenAI rejects standalone reasoning items when replaying a tool-only turn. + // Only submit reasoning items when we also submit an assistant message item. ++ // Repro: pnpm test src/agents/openai-responses.reasoning-replay.test.ts + const hasMessage = output.some((item) => item?.type === "message"); + if (!hasMessage) { + for (let i = output.length - 1; i >= 0; i -= 1) { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 74e5d2ae1..17d826333 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -8,21 +8,9 @@ overrides: '@sinclair/typebox': 0.34.47 patchedDependencies: - '@mariozechner/pi-agent-core': - hash: 01312ceb1f6be7e42822c24c9a7a4f7db56b24ae114a364855bd3819779d1cf4 - path: patches/@mariozechner__pi-agent-core.patch '@mariozechner/pi-ai@0.42.2': - hash: 53800c5f6cd7b43591675f7d836e599255e4a39cdd38d166b8e35947c835db93 + hash: d8d7c692952a4064a56dc4c67818939d17a48886eb355867de2bcc9118915c97 path: patches/@mariozechner__pi-ai@0.42.2.patch - '@mariozechner/pi-coding-agent': - hash: 58af7c712ebe270527c2ad9d3351fac39d6cd4b81cc475a258d87840b446b90e - path: patches/@mariozechner__pi-coding-agent.patch - playwright-core@1.57.0: - hash: 66f1f266424dbe354068aaa5bba87bfb0e1d7d834a938c25dd70d43cdf1c1b02 - path: patches/playwright-core@1.57.0.patch - qrcode-terminal: - hash: ed82029850dbdf551f5df1de320945af52b8ea8500cc7bd4f39258e7a3d92e12 - path: patches/qrcode-terminal.patch importers: @@ -45,13 +33,13 @@ importers: version: 1.3.4 '@mariozechner/pi-agent-core': specifier: ^0.42.2 - version: 0.42.2(patch_hash=01312ceb1f6be7e42822c24c9a7a4f7db56b24ae114a364855bd3819779d1cf4)(ws@8.19.0)(zod@4.3.5) + version: 0.42.2(ws@8.19.0)(zod@4.3.5) '@mariozechner/pi-ai': specifier: ^0.42.2 - version: 0.42.2(patch_hash=53800c5f6cd7b43591675f7d836e599255e4a39cdd38d166b8e35947c835db93)(ws@8.19.0)(zod@4.3.5) + version: 0.42.2(patch_hash=d8d7c692952a4064a56dc4c67818939d17a48886eb355867de2bcc9118915c97)(ws@8.19.0)(zod@4.3.5) '@mariozechner/pi-coding-agent': specifier: ^0.42.2 - version: 0.42.2(patch_hash=58af7c712ebe270527c2ad9d3351fac39d6cd4b81cc475a258d87840b446b90e)(ws@8.19.0)(zod@4.3.5) + version: 0.42.2(ws@8.19.0)(zod@4.3.5) '@mariozechner/pi-tui': specifier: ^0.42.2 version: 0.42.2 @@ -129,13 +117,13 @@ importers: version: 0.2.0 playwright-core: specifier: 1.57.0 - version: 1.57.0(patch_hash=66f1f266424dbe354068aaa5bba87bfb0e1d7d834a938c25dd70d43cdf1c1b02) + version: 1.57.0 proper-lockfile: specifier: ^4.1.2 version: 4.1.2 qrcode-terminal: specifier: ^0.12.0 - version: 0.12.0(patch_hash=ed82029850dbdf551f5df1de320945af52b8ea8500cc7bd4f39258e7a3d92e12) + version: 0.12.0 sharp: specifier: ^0.34.5 version: 0.34.5 @@ -3787,9 +3775,9 @@ snapshots: transitivePeerDependencies: - tailwindcss - '@mariozechner/pi-agent-core@0.42.2(patch_hash=01312ceb1f6be7e42822c24c9a7a4f7db56b24ae114a364855bd3819779d1cf4)(ws@8.19.0)(zod@4.3.5)': + '@mariozechner/pi-agent-core@0.42.2(ws@8.19.0)(zod@4.3.5)': dependencies: - '@mariozechner/pi-ai': 0.42.2(patch_hash=53800c5f6cd7b43591675f7d836e599255e4a39cdd38d166b8e35947c835db93)(ws@8.19.0)(zod@4.3.5) + '@mariozechner/pi-ai': 0.42.2(patch_hash=d8d7c692952a4064a56dc4c67818939d17a48886eb355867de2bcc9118915c97)(ws@8.19.0)(zod@4.3.5) '@mariozechner/pi-tui': 0.42.2 transitivePeerDependencies: - '@modelcontextprotocol/sdk' @@ -3799,7 +3787,7 @@ snapshots: - ws - zod - '@mariozechner/pi-ai@0.42.2(patch_hash=53800c5f6cd7b43591675f7d836e599255e4a39cdd38d166b8e35947c835db93)(ws@8.19.0)(zod@4.3.5)': + '@mariozechner/pi-ai@0.42.2(patch_hash=d8d7c692952a4064a56dc4c67818939d17a48886eb355867de2bcc9118915c97)(ws@8.19.0)(zod@4.3.5)': dependencies: '@anthropic-ai/sdk': 0.71.2(zod@4.3.5) '@google/genai': 1.34.0 @@ -3819,11 +3807,11 @@ snapshots: - ws - zod - '@mariozechner/pi-coding-agent@0.42.2(patch_hash=58af7c712ebe270527c2ad9d3351fac39d6cd4b81cc475a258d87840b446b90e)(ws@8.19.0)(zod@4.3.5)': + '@mariozechner/pi-coding-agent@0.42.2(ws@8.19.0)(zod@4.3.5)': dependencies: '@mariozechner/clipboard': 0.3.0 - '@mariozechner/pi-agent-core': 0.42.2(patch_hash=01312ceb1f6be7e42822c24c9a7a4f7db56b24ae114a364855bd3819779d1cf4)(ws@8.19.0)(zod@4.3.5) - '@mariozechner/pi-ai': 0.42.2(patch_hash=53800c5f6cd7b43591675f7d836e599255e4a39cdd38d166b8e35947c835db93)(ws@8.19.0)(zod@4.3.5) + '@mariozechner/pi-agent-core': 0.42.2(ws@8.19.0)(zod@4.3.5) + '@mariozechner/pi-ai': 0.42.2(patch_hash=d8d7c692952a4064a56dc4c67818939d17a48886eb355867de2bcc9118915c97)(ws@8.19.0)(zod@4.3.5) '@mariozechner/pi-tui': 0.42.2 chalk: 5.6.2 cli-highlight: 2.1.11 @@ -5686,11 +5674,11 @@ snapshots: dependencies: pngjs: 7.0.0 - playwright-core@1.57.0(patch_hash=66f1f266424dbe354068aaa5bba87bfb0e1d7d834a938c25dd70d43cdf1c1b02): {} + playwright-core@1.57.0: {} playwright@1.57.0: dependencies: - playwright-core: 1.57.0(patch_hash=66f1f266424dbe354068aaa5bba87bfb0e1d7d834a938c25dd70d43cdf1c1b02) + playwright-core: 1.57.0 optionalDependencies: fsevents: 2.3.2 @@ -5775,7 +5763,7 @@ snapshots: '@thi.ng/bitstream': 2.4.37 optional: true - qrcode-terminal@0.12.0(patch_hash=ed82029850dbdf551f5df1de320945af52b8ea8500cc7bd4f39258e7a3d92e12): {} + qrcode-terminal@0.12.0: {} qs@6.14.1: dependencies: diff --git a/src/agents/model-auth.ts b/src/agents/model-auth.ts index ac648caad..4d21e99d8 100644 --- a/src/agents/model-auth.ts +++ b/src/agents/model-auth.ts @@ -2,7 +2,6 @@ import { type Api, getEnvApiKey, type Model } from "@mariozechner/pi-ai"; import type { ClawdbotConfig } from "../config/config.js"; import type { ModelProviderConfig } from "../config/types.js"; import { getShellEnvAppliedKeys } from "../infra/shell-env.js"; -import { normalizeProviderId } from "./model-selection.js"; import { type AuthProfileStore, ensureAuthProfileStore, @@ -10,6 +9,7 @@ import { resolveApiKeyForProfile, resolveAuthProfileOrder, } from "./auth-profiles.js"; +import { normalizeProviderId } from "./model-selection.js"; export { ensureAuthProfileStore, diff --git a/src/agents/pi-embedded-runner.ts b/src/agents/pi-embedded-runner.ts index d0c19af57..e6fc8e75e 100644 --- a/src/agents/pi-embedded-runner.ts +++ b/src/agents/pi-embedded-runner.ts @@ -559,7 +559,9 @@ export function buildEmbeddedSandboxInfo( bashElevated?: BashElevatedDefaults, ): EmbeddedSandboxInfo | undefined { if (!sandbox?.enabled) return undefined; - const elevatedAllowed = Boolean(bashElevated?.enabled && bashElevated.allowed); + const elevatedAllowed = Boolean( + bashElevated?.enabled && bashElevated.allowed, + ); return { enabled: true, workspaceDir: sandbox.workspaceDir,