@oh-my-pi/pi-coding-agent 17.0.9 → 17.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (285) hide show
  1. package/CHANGELOG.md +54 -0
  2. package/README.md +1 -1
  3. package/dist/cli.js +4659 -4261
  4. package/dist/types/async/job-manager.d.ts +37 -1
  5. package/dist/types/cli/args.d.ts +2 -0
  6. package/dist/types/cli/bench-cli.d.ts +41 -0
  7. package/dist/types/commands/bench.d.ts +15 -3
  8. package/dist/types/commands/launch.d.ts +4 -0
  9. package/dist/types/config/model-registry.d.ts +3 -1
  10. package/dist/types/config/models-config-schema.d.ts +18 -6
  11. package/dist/types/config/models-config.d.ts +14 -5
  12. package/dist/types/config/provider-globals.d.ts +2 -2
  13. package/dist/types/config/service-tier.d.ts +5 -1
  14. package/dist/types/config/settings-schema.d.ts +316 -47
  15. package/dist/types/config/settings.d.ts +7 -0
  16. package/dist/types/dap/client.d.ts +20 -0
  17. package/dist/types/exec/bash-executor.d.ts +38 -0
  18. package/dist/types/exec/direnv.d.ts +33 -0
  19. package/dist/types/export/html/args.d.ts +15 -0
  20. package/dist/types/export/html/index.d.ts +11 -26
  21. package/dist/types/export/html/web-palette.d.ts +55 -116
  22. package/dist/types/extensibility/extensions/loader.d.ts +3 -0
  23. package/dist/types/extensibility/extensions/types.d.ts +17 -2
  24. package/dist/types/extensibility/plugins/legacy-pi-compat.d.ts +13 -0
  25. package/dist/types/live/controller.d.ts +40 -0
  26. package/dist/types/live/protocol.d.ts +85 -0
  27. package/dist/types/live/protocol.test.d.ts +1 -0
  28. package/dist/types/live/transport.d.ts +48 -0
  29. package/dist/types/live/visualizer.d.ts +33 -0
  30. package/dist/types/lsp/client.d.ts +16 -1
  31. package/dist/types/mcp/config-writer.test.d.ts +1 -0
  32. package/dist/types/mcp/oauth-discovery.d.ts +2 -0
  33. package/dist/types/mcp/smithery-auth.d.ts +1 -1
  34. package/dist/types/mcp/smithery-auth.test.d.ts +1 -0
  35. package/dist/types/memory-backend/tool-names.d.ts +2 -0
  36. package/dist/types/modes/components/login-dialog.d.ts +2 -2
  37. package/dist/types/modes/components/plan-review-overlay.d.ts +26 -0
  38. package/dist/types/modes/components/settings-defs.d.ts +7 -1
  39. package/dist/types/modes/components/status-line/component.jj-cache.test.d.ts +1 -0
  40. package/dist/types/modes/components/tool-execution.d.ts +9 -1
  41. package/dist/types/modes/controllers/command-controller.d.ts +1 -1
  42. package/dist/types/modes/controllers/event-controller.d.ts +6 -1
  43. package/dist/types/modes/controllers/live-command-controller.d.ts +14 -0
  44. package/dist/types/modes/interactive-mode.d.ts +5 -0
  45. package/dist/types/modes/theme/theme.d.ts +1 -1
  46. package/dist/types/modes/types.d.ts +3 -1
  47. package/dist/types/modes/utils/context-usage.d.ts +12 -2
  48. package/dist/types/plan-mode/plan-files.d.ts +10 -0
  49. package/dist/types/registry/agent-lifecycle.d.ts +21 -9
  50. package/dist/types/registry/agent-registry.d.ts +11 -4
  51. package/dist/types/sdk.d.ts +15 -1
  52. package/dist/types/secrets/index.d.ts +15 -2
  53. package/dist/types/secrets/obfuscator.d.ts +113 -15
  54. package/dist/types/session/acp-permission-gate.d.ts +19 -0
  55. package/dist/types/session/agent-session-events.d.ts +84 -0
  56. package/dist/types/session/agent-session-types.d.ts +314 -0
  57. package/dist/types/session/agent-session.d.ts +118 -755
  58. package/dist/types/session/async-job-delivery.d.ts +28 -0
  59. package/dist/types/session/bash-runner.d.ts +75 -0
  60. package/dist/types/session/blob-store.d.ts +11 -1
  61. package/dist/types/session/blob-store.test.d.ts +1 -0
  62. package/dist/types/session/checkpoint-entries.d.ts +28 -0
  63. package/dist/types/session/eval-runner.d.ts +49 -0
  64. package/dist/types/session/irc-bridge.d.ts +46 -0
  65. package/dist/types/session/messages.d.ts +22 -0
  66. package/dist/types/session/model-controls.d.ts +180 -0
  67. package/dist/types/session/prewalk.d.ts +46 -0
  68. package/dist/types/session/queued-messages.d.ts +22 -0
  69. package/dist/types/session/redis-session-storage.d.ts +1 -0
  70. package/dist/types/session/retry-fallback-chains.d.ts +74 -0
  71. package/dist/types/session/role-models.d.ts +15 -0
  72. package/dist/types/session/session-advisors.d.ts +228 -0
  73. package/dist/types/session/session-entries.d.ts +8 -0
  74. package/dist/types/session/session-handoff.d.ts +70 -0
  75. package/dist/types/session/session-history-format.d.ts +6 -1
  76. package/dist/types/session/session-maintenance.d.ts +246 -0
  77. package/dist/types/session/session-manager.d.ts +41 -0
  78. package/dist/types/session/session-memory.d.ts +56 -0
  79. package/dist/types/session/session-provider-boundary.d.ts +62 -0
  80. package/dist/types/session/session-stats.d.ts +48 -0
  81. package/dist/types/session/session-tools.d.ts +143 -0
  82. package/dist/types/session/session-workspace.d.ts +32 -0
  83. package/dist/types/session/stream-guards.d.ts +44 -0
  84. package/dist/types/session/todo-tracker.d.ts +56 -0
  85. package/dist/types/session/ttsr-coordinator.d.ts +51 -0
  86. package/dist/types/session/turn-recovery.d.ts +225 -0
  87. package/dist/types/system-prompt.d.ts +2 -0
  88. package/dist/types/task/executor.d.ts +4 -1
  89. package/dist/types/task/output-manager.d.ts +3 -1
  90. package/dist/types/tools/approval.d.ts +1 -0
  91. package/dist/types/tools/browser/launch.d.ts +5 -0
  92. package/dist/types/tools/image-gen.d.ts +4 -4
  93. package/dist/types/tools/image-providers.d.ts +38 -0
  94. package/dist/types/tools/index.d.ts +5 -0
  95. package/dist/types/tools/path-utils.d.ts +8 -0
  96. package/dist/types/tools/todo.d.ts +10 -4
  97. package/dist/types/tools/xdev.d.ts +5 -1
  98. package/dist/types/tts/streaming-player.d.ts +14 -0
  99. package/dist/types/tts/vocalizer.d.ts +5 -0
  100. package/dist/types/utils/jj.d.ts +29 -0
  101. package/dist/types/utils/lang-from-path.d.ts +1 -0
  102. package/dist/types/utils/title-generator.d.ts +30 -0
  103. package/dist/types/vibe/runtime.d.ts +36 -8
  104. package/dist/types/web/search/index.d.ts +1 -1
  105. package/dist/types/web/search/provider.d.ts +15 -5
  106. package/dist/types/web/search/types.d.ts +94 -0
  107. package/package.json +12 -12
  108. package/scripts/generate-share-viewer.ts +4 -6
  109. package/src/advisor/__tests__/advisor.test.ts +643 -0
  110. package/src/advisor/runtime.ts +144 -43
  111. package/src/async/job-manager.ts +90 -2
  112. package/src/cli/args.ts +2 -0
  113. package/src/cli/auth-gateway-cli.ts +18 -3
  114. package/src/cli/bench-cli.ts +395 -29
  115. package/src/cli/flag-tables.ts +3 -0
  116. package/src/cli/gc-cli.ts +2 -2
  117. package/src/cli/usage-cli.ts +10 -1
  118. package/src/collab/host.ts +3 -2
  119. package/src/commands/bench.ts +18 -4
  120. package/src/commands/launch.ts +4 -0
  121. package/src/config/model-registry.ts +10 -2
  122. package/src/config/models-config-schema.ts +15 -4
  123. package/src/config/provider-globals.ts +9 -9
  124. package/src/config/service-tier.ts +26 -1
  125. package/src/config/settings-schema.ts +209 -51
  126. package/src/config/settings.ts +81 -2
  127. package/src/dap/client.ts +37 -4
  128. package/src/edit/index.ts +49 -12
  129. package/src/eval/py/executor.ts +103 -33
  130. package/src/exec/bash-executor.ts +89 -6
  131. package/src/exec/direnv.ts +145 -0
  132. package/src/export/html/args.ts +20 -0
  133. package/src/export/html/index.ts +45 -47
  134. package/src/export/html/template.css +19 -1
  135. package/src/export/html/template.html +6 -0
  136. package/src/export/html/template.js +21 -0
  137. package/src/export/html/tool-views.generated.js +31 -31
  138. package/src/export/html/web-palette.ts +116 -132
  139. package/src/export/share.ts +249 -49
  140. package/src/extensibility/extensions/loader.ts +29 -1
  141. package/src/extensibility/extensions/runner.ts +6 -0
  142. package/src/extensibility/extensions/types.ts +33 -2
  143. package/src/extensibility/plugins/legacy-pi-compat.ts +19 -1
  144. package/src/hindsight/state.ts +64 -6
  145. package/src/internal-urls/local-protocol.ts +2 -1
  146. package/src/internal-urls/memory-protocol.ts +2 -2
  147. package/src/internal-urls/skill-protocol.ts +2 -2
  148. package/src/internal-urls/ssh-protocol.ts +2 -1
  149. package/src/internal-urls/vault-protocol.ts +2 -1
  150. package/src/live/audio-worklet.txt +59 -0
  151. package/src/live/browser-runtime.txt +221 -0
  152. package/src/live/controller.ts +464 -0
  153. package/src/live/prompts/agent-final-message.md +3 -0
  154. package/src/live/prompts/live-instructions.md +23 -0
  155. package/src/live/protocol.test.ts +140 -0
  156. package/src/live/protocol.ts +233 -0
  157. package/src/live/transport.ts +490 -0
  158. package/src/live/visualizer.ts +234 -0
  159. package/src/lsp/client.ts +29 -9
  160. package/src/lsp/index.ts +19 -4
  161. package/src/main.ts +8 -1
  162. package/src/mcp/config-writer.test.ts +43 -0
  163. package/src/mcp/config-writer.ts +109 -82
  164. package/src/mcp/oauth-discovery.ts +10 -2
  165. package/src/mcp/smithery-auth.test.ts +29 -0
  166. package/src/mcp/smithery-auth.ts +3 -2
  167. package/src/memories/index.ts +40 -20
  168. package/src/memory-backend/tool-names.ts +2 -0
  169. package/src/mnemopi/backend.ts +24 -7
  170. package/src/modes/acp/acp-agent.ts +56 -10
  171. package/src/modes/acp/acp-event-mapper.ts +8 -1
  172. package/src/modes/components/agent-hub.ts +1 -1
  173. package/src/modes/components/login-dialog.ts +14 -4
  174. package/src/modes/components/plan-review-overlay.ts +350 -35
  175. package/src/modes/components/settings-defs.ts +23 -1
  176. package/src/modes/components/settings-selector.ts +169 -1
  177. package/src/modes/components/status-line/component.jj-cache.test.ts +229 -0
  178. package/src/modes/components/status-line/component.ts +123 -2
  179. package/src/modes/components/tool-execution.ts +11 -2
  180. package/src/modes/controllers/command-controller.ts +56 -15
  181. package/src/modes/controllers/event-controller.ts +111 -16
  182. package/src/modes/controllers/extension-ui-controller.test.ts +1 -0
  183. package/src/modes/controllers/extension-ui-controller.ts +20 -4
  184. package/src/modes/controllers/live-command-controller.ts +178 -0
  185. package/src/modes/controllers/mcp-command-controller.ts +10 -1
  186. package/src/modes/controllers/omfg-controller.ts +44 -40
  187. package/src/modes/controllers/selector-controller.ts +18 -10
  188. package/src/modes/controllers/session-focus-controller.ts +6 -1
  189. package/src/modes/interactive-mode.ts +157 -38
  190. package/src/modes/runtime-init.ts +2 -0
  191. package/src/modes/setup-wizard/scenes/web-search.ts +17 -9
  192. package/src/modes/theme/theme.ts +1 -1
  193. package/src/modes/types.ts +3 -1
  194. package/src/modes/utils/context-usage.ts +23 -7
  195. package/src/modes/utils/ui-helpers.ts +10 -5
  196. package/src/plan-mode/plan-files.ts +40 -0
  197. package/src/prompts/bench/cache-prefix-chunk.md +1 -0
  198. package/src/prompts/bench/cache-prefix.md +3 -0
  199. package/src/prompts/bench/cache-suffix.md +1 -0
  200. package/src/prompts/system/custom-system-prompt.md +1 -1
  201. package/src/prompts/system/project-prompt.md +8 -1
  202. package/src/prompts/system/subagent-async-pending.md +6 -0
  203. package/src/prompts/system/system-prompt.md +1 -1
  204. package/src/prompts/system/workflow-notice.md +48 -40
  205. package/src/prompts/system/xdev-mount-notice.md +4 -0
  206. package/src/prompts/tools/todo.md +3 -1
  207. package/src/registry/agent-lifecycle.ts +116 -46
  208. package/src/registry/agent-registry.ts +35 -8
  209. package/src/registry/persisted-agents.ts +26 -2
  210. package/src/sdk.ts +210 -136
  211. package/src/secrets/index.ts +127 -4
  212. package/src/secrets/obfuscator.ts +2328 -105
  213. package/src/session/acp-permission-gate.ts +165 -0
  214. package/src/session/agent-session-error-log.test.ts +1 -1
  215. package/src/session/agent-session-events.ts +66 -0
  216. package/src/session/agent-session-types.ts +334 -0
  217. package/src/session/agent-session.ts +1892 -12226
  218. package/src/session/artifacts.ts +6 -5
  219. package/src/session/async-job-delivery.ts +74 -0
  220. package/src/session/bash-runner.ts +326 -0
  221. package/src/session/blob-store.test.ts +56 -0
  222. package/src/session/blob-store.ts +18 -2
  223. package/src/session/checkpoint-entries.ts +81 -0
  224. package/src/session/eval-runner.ts +212 -0
  225. package/src/session/indexed-session-storage.ts +9 -2
  226. package/src/session/irc-bridge.ts +203 -0
  227. package/src/session/messages.ts +263 -1
  228. package/src/session/model-controls.ts +714 -0
  229. package/src/session/prewalk.ts +252 -0
  230. package/src/session/queued-messages.ts +93 -0
  231. package/src/session/redis-session-storage.ts +51 -11
  232. package/src/session/retry-fallback-chains.ts +455 -0
  233. package/src/session/role-models.ts +85 -0
  234. package/src/session/session-advisors.ts +1679 -0
  235. package/src/session/session-context.ts +6 -3
  236. package/src/session/session-entries.ts +8 -0
  237. package/src/session/session-handoff.ts +308 -0
  238. package/src/session/session-history-format.ts +20 -9
  239. package/src/session/session-loader.ts +0 -46
  240. package/src/session/session-maintenance.ts +2983 -0
  241. package/src/session/session-manager.ts +390 -30
  242. package/src/session/session-memory.ts +222 -0
  243. package/src/session/session-provider-boundary.ts +307 -0
  244. package/src/session/session-stats.ts +293 -0
  245. package/src/session/session-tools.ts +943 -0
  246. package/src/session/session-workspace.ts +53 -0
  247. package/src/session/stream-guards.ts +417 -0
  248. package/src/session/todo-tracker.ts +380 -0
  249. package/src/session/ttsr-coordinator.ts +496 -0
  250. package/src/session/turn-recovery.ts +1629 -0
  251. package/src/slash-commands/builtin-registry.ts +92 -11
  252. package/src/slash-commands/helpers/usage-report.ts +22 -3
  253. package/src/system-prompt.ts +41 -17
  254. package/src/task/executor.ts +285 -70
  255. package/src/task/index.ts +98 -105
  256. package/src/task/output-manager.ts +25 -3
  257. package/src/task/persisted-revive.ts +4 -3
  258. package/src/task/structured-subagent.ts +1 -0
  259. package/src/tools/approval.ts +55 -10
  260. package/src/tools/bash-interactive.ts +26 -0
  261. package/src/tools/bash-skill-urls.ts +28 -2
  262. package/src/tools/bash.ts +339 -123
  263. package/src/tools/browser/launch.ts +9 -1
  264. package/src/tools/browser/tab-supervisor.ts +8 -5
  265. package/src/tools/browser.ts +94 -47
  266. package/src/tools/image-gen.ts +20 -28
  267. package/src/tools/image-providers.ts +50 -0
  268. package/src/tools/index.ts +9 -0
  269. package/src/tools/path-utils.ts +49 -2
  270. package/src/tools/read.ts +156 -88
  271. package/src/tools/renderers.ts +7 -1
  272. package/src/tools/todo.ts +101 -11
  273. package/src/tools/vibe.ts +1 -2
  274. package/src/tools/write.ts +51 -1
  275. package/src/tools/xdev.ts +67 -3
  276. package/src/tts/streaming-player.ts +62 -4
  277. package/src/tts/vocalizer.ts +18 -1
  278. package/src/utils/jj.ts +125 -4
  279. package/src/utils/lang-from-path.ts +7 -0
  280. package/src/utils/title-generator.ts +137 -1
  281. package/src/vibe/runtime.ts +852 -72
  282. package/src/web/search/index.ts +3 -6
  283. package/src/web/search/provider.ts +31 -16
  284. package/src/web/search/providers/xai.ts +7 -1
  285. package/src/web/search/types.ts +3 -0
@@ -23,8 +23,9 @@ import type {
23
23
  UserMessage,
24
24
  } from "@oh-my-pi/pi-ai";
25
25
  import * as AIError from "@oh-my-pi/pi-ai/error";
26
- import { prompt } from "@oh-my-pi/pi-utils";
26
+ import { isRecord, logger, prompt } from "@oh-my-pi/pi-utils";
27
27
  import userInterjectionTemplate from "../prompts/steering/user-interjection.md" with { type: "text" };
28
+ import { formatTitleConversationContext, type TitleConversationTurn } from "../tiny/message-preproc";
28
29
 
29
30
  export {
30
31
  type BranchSummaryMessage,
@@ -41,6 +42,267 @@ export const SKILL_PROMPT_MESSAGE_TYPE = "skill-prompt";
41
42
  export const LSP_LATE_DIAGNOSTIC_MESSAGE_TYPE = "lsp-late-diagnostic";
42
43
  export const BACKGROUND_TAN_DISPATCH_MESSAGE_TYPE = "background-tan-dispatch";
43
44
 
45
+ /**
46
+ * Logs provider-error turns so their actual cause is available outside the
47
+ * session transcript. No-op for non-error stop reasons.
48
+ */
49
+ export function logProviderTurnError(msg: AssistantMessage): void {
50
+ if (msg.stopReason !== "error") return;
51
+ logger.warn("agent turn ended with provider error", {
52
+ provider: msg.provider,
53
+ model: msg.model,
54
+ errorMessage: msg.errorMessage,
55
+ errorStatus: msg.errorStatus,
56
+ errorId: msg.errorId,
57
+ });
58
+ }
59
+
60
+ const EPHEMERAL_REPLY_MAX_BYTES = 4096;
61
+ const REPLAN_TITLE_CONTEXT_TURN_LIMIT = 6;
62
+
63
+ /**
64
+ * Removes replay-bound provider state before reparenting an assistant message
65
+ * under a different user turn.
66
+ */
67
+ export function sanitizeAssistantForReparentedHistory(message: AssistantMessage): AssistantMessage {
68
+ const content: AssistantMessage["content"] = [];
69
+ for (const block of message.content) {
70
+ if (block.type === "redactedThinking") continue;
71
+ if (block.type === "thinking") {
72
+ content.push({ type: "thinking", thinking: block.thinking });
73
+ continue;
74
+ }
75
+ content.push(block);
76
+ }
77
+ return { ...message, content, providerPayload: undefined };
78
+ }
79
+
80
+ /**
81
+ * Collapses degenerate repeated lines and bounds an ephemeral side-channel
82
+ * reply to 4 KiB.
83
+ */
84
+ export function dedupeEphemeralReply(text: string): string {
85
+ if (!text) return text;
86
+ const lines = text.split("\n");
87
+ const out: string[] = [];
88
+ let i = 0;
89
+ while (i < lines.length) {
90
+ let j = i + 1;
91
+ while (j < lines.length && lines[j] === lines[i]) j++;
92
+ const runLen = j - i;
93
+ if (runLen > 3) {
94
+ out.push(lines[i], `[…${runLen}×]`);
95
+ } else {
96
+ for (let k = 0; k < runLen; k++) out.push(lines[i]);
97
+ }
98
+ i = j;
99
+ }
100
+ let result = out.join("\n");
101
+ if (Buffer.byteLength(result, "utf8") > EPHEMERAL_REPLY_MAX_BYTES) {
102
+ const suffix = "\n[…truncated]";
103
+ const budget = EPHEMERAL_REPLY_MAX_BYTES - Buffer.byteLength(suffix, "utf8");
104
+ while (Buffer.byteLength(result, "utf8") > budget) {
105
+ result = result.slice(0, -1);
106
+ }
107
+ result += suffix;
108
+ }
109
+ return result;
110
+ }
111
+
112
+ /** Builds the recent user/assistant context supplied to title regeneration. */
113
+ export function buildReplanTitleContext(messages: AgentMessage[]): string {
114
+ const turns: TitleConversationTurn[] = [];
115
+ for (let i = messages.length - 1; i >= 0 && turns.length < REPLAN_TITLE_CONTEXT_TURN_LIMIT; i--) {
116
+ const message = messages[i];
117
+ if (!message) continue;
118
+ const turn = titleConversationTurnFromMessage(message);
119
+ if (turn) turns.push(turn);
120
+ }
121
+ turns.reverse();
122
+ return formatTitleConversationContext(turns);
123
+ }
124
+
125
+ /**
126
+ * Compares session messages by provider-replay semantics, ignoring runtime-only
127
+ * fields that do not change a restored request.
128
+ */
129
+ export function didSessionMessagesChange(previousMessages: AgentMessage[], nextMessages: AgentMessage[]): boolean {
130
+ if (previousMessages.length !== nextMessages.length) return true;
131
+ return previousMessages.some(
132
+ (message, i) =>
133
+ !Bun.deepEquals(
134
+ normalizeSessionMessageForProviderReplay(message),
135
+ normalizeSessionMessageForProviderReplay(nextMessages[i]),
136
+ ),
137
+ );
138
+ }
139
+
140
+ function textFromContent(content: unknown): string {
141
+ if (typeof content === "string") return content.trim();
142
+ if (!Array.isArray(content)) return "";
143
+ const parts: string[] = [];
144
+ for (const block of content) {
145
+ if (!isRecord(block) || block.type !== "text" || typeof block.text !== "string") continue;
146
+ const text = block.text.trim();
147
+ if (text) parts.push(text);
148
+ }
149
+ return parts.join("\n\n");
150
+ }
151
+
152
+ function thinkingFromContent(content: unknown): string {
153
+ if (!Array.isArray(content)) return "";
154
+ const parts: string[] = [];
155
+ for (const block of content) {
156
+ if (!isRecord(block) || block.type !== "thinking" || typeof block.thinking !== "string") continue;
157
+ const thinking = block.thinking.trim();
158
+ if (thinking) parts.push(thinking);
159
+ }
160
+ return parts.join("\n\n");
161
+ }
162
+
163
+ function titleConversationTurnFromMessage(message: AgentMessage): TitleConversationTurn | undefined {
164
+ if (message.role !== "user" && message.role !== "assistant") return undefined;
165
+ const text = textFromContent(message.content);
166
+ const thinking = message.role === "assistant" ? thinkingFromContent(message.content) : undefined;
167
+ if (!text && !thinking) return undefined;
168
+ return { role: message.role, ...(text ? { text } : {}), ...(thinking ? { thinking } : {}) };
169
+ }
170
+
171
+ function normalizeProviderReplayValue(value: unknown): unknown {
172
+ if (Array.isArray(value)) {
173
+ return value.map(normalizeProviderReplayValue);
174
+ }
175
+ if (value && typeof value === "object") {
176
+ return Object.fromEntries(
177
+ Object.entries(value).map(([key, entryValue]) => [key, normalizeProviderReplayValue(entryValue)]),
178
+ );
179
+ }
180
+ return value;
181
+ }
182
+
183
+ function normalizeSessionMessageForProviderReplay(message: AgentMessage): unknown {
184
+ switch (message.role) {
185
+ case "user":
186
+ case "developer":
187
+ return {
188
+ role: message.role,
189
+ content: normalizeProviderReplayValue(message.content),
190
+ providerPayload: message.providerPayload,
191
+ };
192
+ case "assistant": {
193
+ const isResponsesFamilyMessage =
194
+ message.api === "openai-responses" || message.api === "openai-codex-responses";
195
+ return {
196
+ role: message.role,
197
+ content:
198
+ isResponsesFamilyMessage && Array.isArray(message.content)
199
+ ? message.content.flatMap(block => {
200
+ if (block.type === "thinking") {
201
+ return [];
202
+ }
203
+ if (block.type === "toolCall") {
204
+ return [
205
+ {
206
+ type: block.type,
207
+ id: block.id,
208
+ name: block.name,
209
+ arguments: block.arguments,
210
+ },
211
+ ];
212
+ }
213
+ if (block.type === "text") {
214
+ return [{ type: block.type, text: block.text, textSignature: block.textSignature }];
215
+ }
216
+ return [normalizeProviderReplayValue(block)];
217
+ })
218
+ : normalizeProviderReplayValue(message.content),
219
+ api: message.api,
220
+ provider: message.provider,
221
+ model: message.model,
222
+ stopReason: message.stopReason,
223
+ errorMessage: message.errorMessage,
224
+ providerPayload: isResponsesFamilyMessage ? undefined : message.providerPayload,
225
+ };
226
+ }
227
+ case "toolResult":
228
+ return {
229
+ role: message.role,
230
+ toolName: message.toolName,
231
+ toolCallId: message.toolCallId,
232
+ isError: message.isError,
233
+ content: normalizeProviderReplayValue(message.content),
234
+ };
235
+ case "bashExecution":
236
+ return {
237
+ role: message.role,
238
+ command: message.command,
239
+ output: message.output,
240
+ exitCode: message.exitCode,
241
+ cancelled: message.cancelled,
242
+ meta: message.meta
243
+ ? {
244
+ truncation: normalizeProviderReplayValue(message.meta.truncation),
245
+ limits: normalizeProviderReplayValue(message.meta.limits),
246
+ diagnostics: message.meta.diagnostics
247
+ ? normalizeProviderReplayValue({
248
+ summary: message.meta.diagnostics.summary,
249
+ messages: message.meta.diagnostics.messages,
250
+ })
251
+ : undefined,
252
+ }
253
+ : undefined,
254
+ excludeFromContext: message.excludeFromContext,
255
+ };
256
+ case "pythonExecution":
257
+ return {
258
+ role: message.role,
259
+ code: message.code,
260
+ output: message.output,
261
+ exitCode: message.exitCode,
262
+ cancelled: message.cancelled,
263
+ meta: message.meta
264
+ ? {
265
+ truncation: normalizeProviderReplayValue(message.meta.truncation),
266
+ limits: normalizeProviderReplayValue(message.meta.limits),
267
+ diagnostics: message.meta.diagnostics
268
+ ? normalizeProviderReplayValue({
269
+ summary: message.meta.diagnostics.summary,
270
+ messages: message.meta.diagnostics.messages,
271
+ })
272
+ : undefined,
273
+ }
274
+ : undefined,
275
+ excludeFromContext: message.excludeFromContext,
276
+ };
277
+ case "custom":
278
+ case "hookMessage":
279
+ return {
280
+ role: message.role,
281
+ customType: message.customType,
282
+ content: normalizeProviderReplayValue(message.content),
283
+ };
284
+ case "branchSummary":
285
+ return { role: message.role, summary: message.summary };
286
+ case "compactionSummary":
287
+ return {
288
+ role: message.role,
289
+ summary: message.summary,
290
+ providerPayload: message.providerPayload,
291
+ };
292
+ case "fileMention":
293
+ return {
294
+ role: message.role,
295
+ files: message.files.map(file => ({
296
+ path: file.path,
297
+ content: file.content,
298
+ image: file.image,
299
+ })),
300
+ };
301
+ default:
302
+ return normalizeProviderReplayValue(message);
303
+ }
304
+ }
305
+
44
306
  /** Fallback type for extension-injected messages that omit a custom type. */
45
307
  export const DEFAULT_CUSTOM_MESSAGE_TYPE = "custom-message";
46
308