@qduc/term2 0.21.0 → 0.22.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 (656) hide show
  1. package/dist/agent.d.ts +2 -0
  2. package/dist/agent.d.ts.map +1 -1
  3. package/dist/agent.js +32 -10
  4. package/dist/agent.js.map +1 -1
  5. package/dist/app.d.ts.map +1 -1
  6. package/dist/app.js +83 -6
  7. package/dist/app.js.map +1 -1
  8. package/dist/cli.js +84 -2
  9. package/dist/cli.js.map +1 -1
  10. package/dist/components/InputBox.js +2 -3
  11. package/dist/components/InputBox.js.map +1 -1
  12. package/dist/components/common/MenuContainer.d.ts +5 -0
  13. package/dist/components/common/MenuContainer.d.ts.map +1 -1
  14. package/dist/components/common/MenuContainer.js +13 -3
  15. package/dist/components/common/MenuContainer.js.map +1 -1
  16. package/dist/components/input/MenuSurface.d.ts.map +1 -1
  17. package/dist/components/input/MenuSurface.js +12 -2
  18. package/dist/components/input/MenuSurface.js.map +1 -1
  19. package/dist/components/input/ModelMenuSession.d.ts.map +1 -1
  20. package/dist/components/input/ModelMenuSession.js +67 -16
  21. package/dist/components/input/ModelMenuSession.js.map +1 -1
  22. package/dist/components/input/SettingsMenuSession.d.ts.map +1 -1
  23. package/dist/components/input/SettingsMenuSession.js +56 -17
  24. package/dist/components/input/SettingsMenuSession.js.map +1 -1
  25. package/dist/components/input/SettingsValueMenuSession.d.ts.map +1 -1
  26. package/dist/components/input/SettingsValueMenuSession.js +33 -3
  27. package/dist/components/input/SettingsValueMenuSession.js.map +1 -1
  28. package/dist/components/input/menu-types.d.ts +1 -1
  29. package/dist/components/input/menu-types.d.ts.map +1 -1
  30. package/dist/components/input/triggers.js +2 -2
  31. package/dist/components/input/triggers.js.map +1 -1
  32. package/dist/components/layout/BackgroundTasksPanel.d.ts +0 -1
  33. package/dist/components/layout/BackgroundTasksPanel.d.ts.map +1 -1
  34. package/dist/components/layout/BackgroundTasksPanel.js +4 -112
  35. package/dist/components/layout/BackgroundTasksPanel.js.map +1 -1
  36. package/dist/components/menu/ModelSelectionMenu.d.ts +10 -0
  37. package/dist/components/menu/ModelSelectionMenu.d.ts.map +1 -1
  38. package/dist/components/menu/ModelSelectionMenu.js +85 -16
  39. package/dist/components/menu/ModelSelectionMenu.js.map +1 -1
  40. package/dist/components/menu/ProfileSelectionMenu.d.ts.map +1 -1
  41. package/dist/components/menu/ProfileSelectionMenu.js +5 -4
  42. package/dist/components/menu/ProfileSelectionMenu.js.map +1 -1
  43. package/dist/components/menu/ResumeSelectionMenu.d.ts.map +1 -1
  44. package/dist/components/menu/ResumeSelectionMenu.js +3 -5
  45. package/dist/components/menu/ResumeSelectionMenu.js.map +1 -1
  46. package/dist/components/menu/SettingsSelectionMenu.d.ts.map +1 -1
  47. package/dist/components/menu/SettingsSelectionMenu.js +4 -32
  48. package/dist/components/menu/SettingsSelectionMenu.js.map +1 -1
  49. package/dist/components/menu/SettingsValueSelectionMenu.d.ts.map +1 -1
  50. package/dist/components/menu/SettingsValueSelectionMenu.js +12 -5
  51. package/dist/components/menu/SettingsValueSelectionMenu.js.map +1 -1
  52. package/dist/components/menu/SkillSelectionMenu.d.ts.map +1 -1
  53. package/dist/components/menu/SkillSelectionMenu.js +3 -6
  54. package/dist/components/menu/SkillSelectionMenu.js.map +1 -1
  55. package/dist/components/menu/SlashCommandMenu.d.ts +8 -0
  56. package/dist/components/menu/SlashCommandMenu.d.ts.map +1 -1
  57. package/dist/components/menu/SlashCommandMenu.js +16 -6
  58. package/dist/components/menu/SlashCommandMenu.js.map +1 -1
  59. package/dist/components/menu/StandaloneModelPickerApp.d.ts +40 -0
  60. package/dist/components/menu/StandaloneModelPickerApp.d.ts.map +1 -0
  61. package/dist/components/menu/StandaloneModelPickerApp.js +106 -0
  62. package/dist/components/menu/StandaloneModelPickerApp.js.map +1 -0
  63. package/dist/components/menu/settings-value-formatter.d.ts +11 -0
  64. package/dist/components/menu/settings-value-formatter.d.ts.map +1 -0
  65. package/dist/components/menu/settings-value-formatter.js +214 -0
  66. package/dist/components/menu/settings-value-formatter.js.map +1 -0
  67. package/dist/components/message/CommandMessage.d.ts.map +1 -1
  68. package/dist/components/message/CommandMessage.js +22 -17
  69. package/dist/components/message/CommandMessage.js.map +1 -1
  70. package/dist/components/message/MessageList.d.ts.map +1 -1
  71. package/dist/components/message/MessageList.js +13 -2
  72. package/dist/components/message/MessageList.js.map +1 -1
  73. package/dist/components/message/RunCodeRenderer.d.ts +16 -0
  74. package/dist/components/message/RunCodeRenderer.d.ts.map +1 -0
  75. package/dist/components/message/RunCodeRenderer.js +25 -0
  76. package/dist/components/message/RunCodeRenderer.js.map +1 -0
  77. package/dist/components/message/command-message-helpers.d.ts +30 -0
  78. package/dist/components/message/command-message-helpers.d.ts.map +1 -1
  79. package/dist/components/message/command-message-helpers.js +85 -0
  80. package/dist/components/message/command-message-helpers.js.map +1 -1
  81. package/dist/components/prompt/ApprovalPrompt.d.ts.map +1 -1
  82. package/dist/components/prompt/ApprovalPrompt.js +12 -21
  83. package/dist/components/prompt/ApprovalPrompt.js.map +1 -1
  84. package/dist/components/theme.d.ts +1 -0
  85. package/dist/components/theme.d.ts.map +1 -1
  86. package/dist/components/theme.js +1 -0
  87. package/dist/components/theme.js.map +1 -1
  88. package/dist/contracts/streamed-model-turn.d.ts +6 -0
  89. package/dist/contracts/streamed-model-turn.d.ts.map +1 -1
  90. package/dist/hooks/conversation-ui-reducer.d.ts.map +1 -1
  91. package/dist/hooks/conversation-ui-reducer.js +5 -2
  92. package/dist/hooks/conversation-ui-reducer.js.map +1 -1
  93. package/dist/hooks/settings-completion-config.d.ts +1 -1
  94. package/dist/hooks/settings-completion-config.d.ts.map +1 -1
  95. package/dist/hooks/settings-completion-config.js +4 -122
  96. package/dist/hooks/settings-completion-config.js.map +1 -1
  97. package/dist/hooks/settings-completion-logic.d.ts +1 -1
  98. package/dist/hooks/settings-completion-logic.d.ts.map +1 -1
  99. package/dist/hooks/settings-completion-logic.js.map +1 -1
  100. package/dist/hooks/use-app-keyboard-shortcuts.d.ts.map +1 -1
  101. package/dist/hooks/use-app-keyboard-shortcuts.js +33 -20
  102. package/dist/hooks/use-app-keyboard-shortcuts.js.map +1 -1
  103. package/dist/hooks/use-conversation.d.ts +3 -0
  104. package/dist/hooks/use-conversation.d.ts.map +1 -1
  105. package/dist/hooks/use-conversation.js +107 -16
  106. package/dist/hooks/use-conversation.js.map +1 -1
  107. package/dist/hooks/use-model-selection.d.ts +33 -4
  108. package/dist/hooks/use-model-selection.d.ts.map +1 -1
  109. package/dist/hooks/use-model-selection.js +204 -114
  110. package/dist/hooks/use-model-selection.js.map +1 -1
  111. package/dist/hooks/use-settings-completion.d.ts.map +1 -1
  112. package/dist/hooks/use-settings-completion.js +1 -6
  113. package/dist/hooks/use-settings-completion.js.map +1 -1
  114. package/dist/hooks/use-settings-value-completion.d.ts +1 -8
  115. package/dist/hooks/use-settings-value-completion.d.ts.map +1 -1
  116. package/dist/hooks/use-settings-value-completion.js +10 -100
  117. package/dist/hooks/use-settings-value-completion.js.map +1 -1
  118. package/dist/hooks/use-standalone-model-picker.d.ts +64 -0
  119. package/dist/hooks/use-standalone-model-picker.d.ts.map +1 -0
  120. package/dist/hooks/use-standalone-model-picker.js +310 -0
  121. package/dist/hooks/use-standalone-model-picker.js.map +1 -0
  122. package/dist/lib/agent-client.d.ts +17 -1
  123. package/dist/lib/agent-client.d.ts.map +1 -1
  124. package/dist/lib/agent-client.js +173 -53
  125. package/dist/lib/agent-client.js.map +1 -1
  126. package/dist/lib/agent-configuration.d.ts +12 -3
  127. package/dist/lib/agent-configuration.d.ts.map +1 -1
  128. package/dist/lib/agent-configuration.js +26 -7
  129. package/dist/lib/agent-configuration.js.map +1 -1
  130. package/dist/lib/agent-factory.d.ts +3 -0
  131. package/dist/lib/agent-factory.d.ts.map +1 -1
  132. package/dist/lib/agent-factory.js +49 -7
  133. package/dist/lib/agent-factory.js.map +1 -1
  134. package/dist/lib/ask-user-answer-store.d.ts +1 -0
  135. package/dist/lib/ask-user-answer-store.d.ts.map +1 -1
  136. package/dist/lib/ask-user-answer-store.js +3 -0
  137. package/dist/lib/ask-user-answer-store.js.map +1 -1
  138. package/dist/lib/tool-invoke.d.ts +1 -0
  139. package/dist/lib/tool-invoke.d.ts.map +1 -1
  140. package/dist/lib/tool-invoke.js +1 -0
  141. package/dist/lib/tool-invoke.js.map +1 -1
  142. package/dist/non-interactive.d.ts +23 -0
  143. package/dist/non-interactive.d.ts.map +1 -1
  144. package/dist/non-interactive.js +225 -31
  145. package/dist/non-interactive.js.map +1 -1
  146. package/dist/prompts/background-shell.d.ts.map +1 -1
  147. package/dist/prompts/background-shell.js +4 -2
  148. package/dist/prompts/background-shell.js.map +1 -1
  149. package/dist/prompts/background-shell.ts +4 -2
  150. package/dist/prompts/codex.md +1 -3
  151. package/dist/prompts/fragments/gpt-6-astra.md +13 -0
  152. package/dist/prompts/gpt-5-modern.md +1 -3
  153. package/dist/prompts/gpt-5.4-mini.md +0 -2
  154. package/dist/prompts/gpt-5.5.md +0 -2
  155. package/dist/prompts/gpt-5.6.md +0 -1
  156. package/dist/prompts/lite.md +1 -6
  157. package/dist/prompts/memory.md +2 -2
  158. package/dist/prompts/orchestrator.md +4 -4
  159. package/dist/prompts/prompt-constructor.d.ts +2 -0
  160. package/dist/prompts/prompt-constructor.d.ts.map +1 -1
  161. package/dist/prompts/prompt-constructor.js +4 -2
  162. package/dist/prompts/prompt-constructor.js.map +1 -1
  163. package/dist/prompts/prompt-constructor.test.ts +178 -5
  164. package/dist/prompts/prompt-constructor.ts +7 -1
  165. package/dist/prompts/prompt-profiles.d.ts.map +1 -1
  166. package/dist/prompts/prompt-profiles.js +6 -0
  167. package/dist/prompts/prompt-profiles.js.map +1 -1
  168. package/dist/prompts/prompt-profiles.test.ts +6 -4
  169. package/dist/prompts/prompt-profiles.ts +6 -0
  170. package/dist/prompts/session-browser.md +4 -2
  171. package/dist/prompts/shell-auto-approval.d.ts +1 -1
  172. package/dist/prompts/shell-auto-approval.d.ts.map +1 -1
  173. package/dist/prompts/shell-auto-approval.js +2 -2
  174. package/dist/prompts/shell-auto-approval.ts +2 -2
  175. package/dist/prompts/subagent-delegation.js +3 -3
  176. package/dist/prompts/subagent-delegation.js.map +1 -1
  177. package/dist/prompts/subagent-delegation.test.ts +3 -3
  178. package/dist/prompts/subagent-delegation.ts +3 -3
  179. package/dist/prompts/subagents/librarian.md +4 -4
  180. package/dist/prompts/subagents/worker-prompt.test.ts +7 -0
  181. package/dist/prompts/tool-surface-guidance.d.ts +4 -0
  182. package/dist/prompts/tool-surface-guidance.d.ts.map +1 -0
  183. package/dist/prompts/tool-surface-guidance.js +19 -0
  184. package/dist/prompts/tool-surface-guidance.js.map +1 -0
  185. package/dist/prompts/tool-surface-guidance.ts +20 -0
  186. package/dist/providers/codex-compact.d.ts +2 -0
  187. package/dist/providers/codex-compact.d.ts.map +1 -1
  188. package/dist/providers/codex-compact.js +14 -0
  189. package/dist/providers/codex-compact.js.map +1 -1
  190. package/dist/providers/codex-responses-model.d.ts +23 -3
  191. package/dist/providers/codex-responses-model.d.ts.map +1 -1
  192. package/dist/providers/codex-responses-model.js +121 -33
  193. package/dist/providers/codex-responses-model.js.map +1 -1
  194. package/dist/providers/codex.provider.d.ts +2 -0
  195. package/dist/providers/codex.provider.d.ts.map +1 -1
  196. package/dist/providers/codex.provider.js +3 -2
  197. package/dist/providers/codex.provider.js.map +1 -1
  198. package/dist/providers/grok.provider.d.ts.map +1 -1
  199. package/dist/providers/grok.provider.js +5 -2
  200. package/dist/providers/grok.provider.js.map +1 -1
  201. package/dist/providers/model-catalog/catalog.generated.d.ts +453 -309
  202. package/dist/providers/model-catalog/catalog.generated.d.ts.map +1 -1
  203. package/dist/providers/model-catalog/catalog.generated.js +453 -309
  204. package/dist/providers/model-catalog/catalog.generated.js.map +1 -1
  205. package/dist/providers/opencode-session.d.ts.map +1 -1
  206. package/dist/providers/opencode-session.js +5 -0
  207. package/dist/providers/opencode-session.js.map +1 -1
  208. package/dist/providers/openrouter.provider.js +8 -1
  209. package/dist/providers/openrouter.provider.js.map +1 -1
  210. package/dist/providers/responses-websocket-sessions.d.ts +10 -0
  211. package/dist/providers/responses-websocket-sessions.d.ts.map +1 -1
  212. package/dist/providers/responses-websocket-sessions.js +9 -4
  213. package/dist/providers/responses-websocket-sessions.js.map +1 -1
  214. package/dist/providers/retrying-model.d.ts +2 -1
  215. package/dist/providers/retrying-model.d.ts.map +1 -1
  216. package/dist/providers/retrying-model.js +3 -0
  217. package/dist/providers/retrying-model.js.map +1 -1
  218. package/dist/services/agent-runtime/application-run-loop.d.ts +8 -1
  219. package/dist/services/agent-runtime/application-run-loop.d.ts.map +1 -1
  220. package/dist/services/agent-runtime/application-run-loop.js +30 -6
  221. package/dist/services/agent-runtime/application-run-loop.js.map +1 -1
  222. package/dist/services/agent-runtime/context-compaction/index.d.ts +2 -0
  223. package/dist/services/agent-runtime/context-compaction/index.d.ts.map +1 -1
  224. package/dist/services/agent-runtime/context-compaction/index.js +30 -4
  225. package/dist/services/agent-runtime/context-compaction/index.js.map +1 -1
  226. package/dist/services/agent-runtime/context-compaction/local-context-compactor.d.ts +3 -0
  227. package/dist/services/agent-runtime/context-compaction/local-context-compactor.d.ts.map +1 -1
  228. package/dist/services/agent-runtime/context-compaction/local-context-compactor.js +15 -9
  229. package/dist/services/agent-runtime/context-compaction/local-context-compactor.js.map +1 -1
  230. package/dist/services/agent-runtime/tool-invocation-context.d.ts +12 -0
  231. package/dist/services/agent-runtime/tool-invocation-context.d.ts.map +1 -1
  232. package/dist/services/agent-runtime/workflow/workflow-evaluator.d.ts +7 -1
  233. package/dist/services/agent-runtime/workflow/workflow-evaluator.d.ts.map +1 -1
  234. package/dist/services/agent-runtime/workflow/workflow-evaluator.js +78 -183
  235. package/dist/services/agent-runtime/workflow/workflow-evaluator.js.map +1 -1
  236. package/dist/services/agent-runtime/workflow/workflow-sandbox.d.ts +4 -3
  237. package/dist/services/agent-runtime/workflow/workflow-sandbox.d.ts.map +1 -1
  238. package/dist/services/agent-runtime/workflow/workflow-sandbox.js +9 -7
  239. package/dist/services/agent-runtime/workflow/workflow-sandbox.js.map +1 -1
  240. package/dist/services/agent-runtime/workflow/workflow-types.d.ts +1 -1
  241. package/dist/services/agent-runtime/workflow/workflow-types.d.ts.map +1 -1
  242. package/dist/services/agent-runtime/workflow/workflow-types.js.map +1 -1
  243. package/dist/services/approval/approval-decision-executor.d.ts +2 -1
  244. package/dist/services/approval/approval-decision-executor.d.ts.map +1 -1
  245. package/dist/services/approval/approval-decision-executor.js +22 -116
  246. package/dist/services/approval/approval-decision-executor.js.map +1 -1
  247. package/dist/services/approval/approval-descriptor.d.ts +10 -0
  248. package/dist/services/approval/approval-descriptor.d.ts.map +1 -0
  249. package/dist/services/approval/approval-descriptor.js +23 -0
  250. package/dist/services/approval/approval-descriptor.js.map +1 -0
  251. package/dist/services/approval/approval-flow-coordinator.d.ts +2 -1
  252. package/dist/services/approval/approval-flow-coordinator.d.ts.map +1 -1
  253. package/dist/services/approval/approval-flow-coordinator.js +2 -1
  254. package/dist/services/approval/approval-flow-coordinator.js.map +1 -1
  255. package/dist/services/approval/approval-grant-executor.d.ts +25 -0
  256. package/dist/services/approval/approval-grant-executor.d.ts.map +1 -0
  257. package/dist/services/approval/approval-grant-executor.js +125 -0
  258. package/dist/services/approval/approval-grant-executor.js.map +1 -0
  259. package/dist/services/approval/background-subagent-approval-controller.d.ts +2 -1
  260. package/dist/services/approval/background-subagent-approval-controller.d.ts.map +1 -1
  261. package/dist/services/approval/background-subagent-approval-controller.js.map +1 -1
  262. package/dist/services/approval/nested-approval-owner.d.ts +52 -0
  263. package/dist/services/approval/nested-approval-owner.d.ts.map +1 -0
  264. package/dist/services/approval/nested-approval-owner.js +194 -0
  265. package/dist/services/approval/nested-approval-owner.js.map +1 -0
  266. package/dist/services/approval/non-interactive-approval-policy.js +1 -1
  267. package/dist/services/approval/non-interactive-approval-policy.js.map +1 -1
  268. package/dist/services/approval/shell-auto-approval-evaluator.d.ts.map +1 -1
  269. package/dist/services/approval/shell-auto-approval-evaluator.js +2 -4
  270. package/dist/services/approval/shell-auto-approval-evaluator.js.map +1 -1
  271. package/dist/services/approval/shell-auto-approval-resolver.d.ts.map +1 -1
  272. package/dist/services/approval/shell-auto-approval-resolver.js +4 -0
  273. package/dist/services/approval/shell-auto-approval-resolver.js.map +1 -1
  274. package/dist/services/approval/tool-approval-batch-coordinator.d.ts +10 -3
  275. package/dist/services/approval/tool-approval-batch-coordinator.d.ts.map +1 -1
  276. package/dist/services/approval/tool-approval-batch-coordinator.js +16 -5
  277. package/dist/services/approval/tool-approval-batch-coordinator.js.map +1 -1
  278. package/dist/services/approval/tool-approval-policy-registry.d.ts +13 -0
  279. package/dist/services/approval/tool-approval-policy-registry.d.ts.map +1 -1
  280. package/dist/services/approval/tool-approval-policy-registry.js +16 -1
  281. package/dist/services/approval/tool-approval-policy-registry.js.map +1 -1
  282. package/dist/services/conversation/conversation-adapter-factory.d.ts +3 -1
  283. package/dist/services/conversation/conversation-adapter-factory.d.ts.map +1 -1
  284. package/dist/services/conversation/conversation-adapter-factory.js +3 -3
  285. package/dist/services/conversation/conversation-adapter-factory.js.map +1 -1
  286. package/dist/services/conversation/conversation-adapter.d.ts +3 -2
  287. package/dist/services/conversation/conversation-adapter.d.ts.map +1 -1
  288. package/dist/services/conversation/conversation-adapter.js +32 -23
  289. package/dist/services/conversation/conversation-adapter.js.map +1 -1
  290. package/dist/services/conversation/conversation-orchestrator.d.ts +11 -0
  291. package/dist/services/conversation/conversation-orchestrator.d.ts.map +1 -1
  292. package/dist/services/conversation/conversation-orchestrator.js +65 -42
  293. package/dist/services/conversation/conversation-orchestrator.js.map +1 -1
  294. package/dist/services/conversation/conversation-persistence.d.ts +6 -1
  295. package/dist/services/conversation/conversation-persistence.d.ts.map +1 -1
  296. package/dist/services/conversation/conversation-persistence.js +68 -19
  297. package/dist/services/conversation/conversation-persistence.js.map +1 -1
  298. package/dist/services/conversation/conversation-result-builder.d.ts +3 -0
  299. package/dist/services/conversation/conversation-result-builder.d.ts.map +1 -1
  300. package/dist/services/conversation/conversation-result-builder.js +27 -23
  301. package/dist/services/conversation/conversation-result-builder.js.map +1 -1
  302. package/dist/services/conversation/conversation-runtime-factory.d.ts +5 -0
  303. package/dist/services/conversation/conversation-runtime-factory.d.ts.map +1 -1
  304. package/dist/services/conversation/conversation-runtime-factory.js +1 -0
  305. package/dist/services/conversation/conversation-runtime-factory.js.map +1 -1
  306. package/dist/services/conversation/conversation-service.d.ts +11 -1
  307. package/dist/services/conversation/conversation-service.d.ts.map +1 -1
  308. package/dist/services/conversation/conversation-service.js +68 -17
  309. package/dist/services/conversation/conversation-service.js.map +1 -1
  310. package/dist/services/conversation/session-browser.d.ts +34 -27
  311. package/dist/services/conversation/session-browser.d.ts.map +1 -1
  312. package/dist/services/conversation/session-browser.js +221 -60
  313. package/dist/services/conversation/session-browser.js.map +1 -1
  314. package/dist/services/conversation/session-index/session-index-database.d.ts +138 -0
  315. package/dist/services/conversation/session-index/session-index-database.d.ts.map +1 -0
  316. package/dist/services/conversation/session-index/session-index-database.js +684 -0
  317. package/dist/services/conversation/session-index/session-index-database.js.map +1 -0
  318. package/dist/services/conversation/session-index/session-index-schema.d.ts +35 -0
  319. package/dist/services/conversation/session-index/session-index-schema.d.ts.map +1 -0
  320. package/dist/services/conversation/session-index/session-index-schema.js +156 -0
  321. package/dist/services/conversation/session-index/session-index-schema.js.map +1 -0
  322. package/dist/services/conversation/session-index/session-index-service.d.ts +30 -0
  323. package/dist/services/conversation/session-index/session-index-service.d.ts.map +1 -0
  324. package/dist/services/conversation/session-index/session-index-service.js +234 -0
  325. package/dist/services/conversation/session-index/session-index-service.js.map +1 -0
  326. package/dist/services/conversation/session-index/session-index-worker-client.d.ts +36 -0
  327. package/dist/services/conversation/session-index/session-index-worker-client.d.ts.map +1 -0
  328. package/dist/services/conversation/session-index/session-index-worker-client.js +143 -0
  329. package/dist/services/conversation/session-index/session-index-worker-client.js.map +1 -0
  330. package/dist/services/conversation/session-index/session-index-worker.d.ts +56 -0
  331. package/dist/services/conversation/session-index/session-index-worker.d.ts.map +1 -0
  332. package/dist/services/conversation/session-index/session-index-worker.js +96 -0
  333. package/dist/services/conversation/session-index/session-index-worker.js.map +1 -0
  334. package/dist/services/conversation/session-search-helpers.d.ts +4 -0
  335. package/dist/services/conversation/session-search-helpers.d.ts.map +1 -0
  336. package/dist/services/conversation/session-search-helpers.js +13 -0
  337. package/dist/services/conversation/session-search-helpers.js.map +1 -0
  338. package/dist/services/conversation-agent-client.d.ts +8 -0
  339. package/dist/services/conversation-agent-client.d.ts.map +1 -1
  340. package/dist/services/execution-context.js +2 -2
  341. package/dist/services/execution-context.js.map +1 -1
  342. package/dist/services/hooks/hook-event-factory.d.ts +2 -1
  343. package/dist/services/hooks/hook-event-factory.d.ts.map +1 -1
  344. package/dist/services/hooks/hook-event-factory.js +2 -1
  345. package/dist/services/hooks/hook-event-factory.js.map +1 -1
  346. package/dist/services/logging/conversation-log-writer.d.ts.map +1 -1
  347. package/dist/services/logging/conversation-log-writer.js +50 -26
  348. package/dist/services/logging/conversation-log-writer.js.map +1 -1
  349. package/dist/services/logging/logging-service.d.ts.map +1 -1
  350. package/dist/services/logging/logging-service.js +1 -0
  351. package/dist/services/logging/logging-service.js.map +1 -1
  352. package/dist/services/logging/provider-traffic.d.ts +22 -2
  353. package/dist/services/logging/provider-traffic.d.ts.map +1 -1
  354. package/dist/services/logging/provider-traffic.js +147 -12
  355. package/dist/services/logging/provider-traffic.js.map +1 -1
  356. package/dist/services/model-service.d.ts +42 -0
  357. package/dist/services/model-service.d.ts.map +1 -1
  358. package/dist/services/model-service.js +161 -26
  359. package/dist/services/model-service.js.map +1 -1
  360. package/dist/services/models/model-catalog-session.d.ts.map +1 -1
  361. package/dist/services/models/model-catalog-session.js +11 -7
  362. package/dist/services/models/model-catalog-session.js.map +1 -1
  363. package/dist/services/models/model-favorites.d.ts +56 -0
  364. package/dist/services/models/model-favorites.d.ts.map +1 -0
  365. package/dist/services/models/model-favorites.js +93 -0
  366. package/dist/services/models/model-favorites.js.map +1 -0
  367. package/dist/services/models/model-listing.d.ts +40 -0
  368. package/dist/services/models/model-listing.d.ts.map +1 -1
  369. package/dist/services/models/model-listing.js +35 -2
  370. package/dist/services/models/model-listing.js.map +1 -1
  371. package/dist/services/models/model-nicknames.d.ts +113 -0
  372. package/dist/services/models/model-nicknames.d.ts.map +1 -0
  373. package/dist/services/models/model-nicknames.js +182 -0
  374. package/dist/services/models/model-nicknames.js.map +1 -0
  375. package/dist/services/models/model-picker-host.d.ts +72 -0
  376. package/dist/services/models/model-picker-host.d.ts.map +1 -0
  377. package/dist/services/models/model-picker-host.js +83 -0
  378. package/dist/services/models/model-picker-host.js.map +1 -0
  379. package/dist/services/models/model-resolution.d.ts +35 -3
  380. package/dist/services/models/model-resolution.d.ts.map +1 -1
  381. package/dist/services/models/model-resolution.js +276 -47
  382. package/dist/services/models/model-resolution.js.map +1 -1
  383. package/dist/services/models/reasoning-effort.d.ts +20 -0
  384. package/dist/services/models/reasoning-effort.d.ts.map +1 -0
  385. package/dist/services/models/reasoning-effort.js +28 -0
  386. package/dist/services/models/reasoning-effort.js.map +1 -0
  387. package/dist/services/models/unified-model-catalog.d.ts +4 -0
  388. package/dist/services/models/unified-model-catalog.d.ts.map +1 -0
  389. package/dist/services/models/unified-model-catalog.js +54 -0
  390. package/dist/services/models/unified-model-catalog.js.map +1 -0
  391. package/dist/services/retry/provider-failure-classification.d.ts +16 -0
  392. package/dist/services/retry/provider-failure-classification.d.ts.map +1 -1
  393. package/dist/services/retry/provider-failure-classification.js +45 -0
  394. package/dist/services/retry/provider-failure-classification.js.map +1 -1
  395. package/dist/services/retry/retry-recovery-budget.d.ts +26 -1
  396. package/dist/services/retry/retry-recovery-budget.d.ts.map +1 -1
  397. package/dist/services/retry/retry-recovery-budget.js +33 -1
  398. package/dist/services/retry/retry-recovery-budget.js.map +1 -1
  399. package/dist/services/sandboxed-code-host/host-types.d.ts +135 -0
  400. package/dist/services/sandboxed-code-host/host-types.d.ts.map +1 -0
  401. package/dist/services/sandboxed-code-host/host-types.js +6 -0
  402. package/dist/services/sandboxed-code-host/host-types.js.map +1 -0
  403. package/dist/services/sandboxed-code-host/host-worker.d.ts +9 -0
  404. package/dist/services/sandboxed-code-host/host-worker.d.ts.map +1 -0
  405. package/dist/services/sandboxed-code-host/host-worker.js +351 -0
  406. package/dist/services/sandboxed-code-host/host-worker.js.map +1 -0
  407. package/dist/services/sandboxed-code-host/sandbox.d.ts +16 -0
  408. package/dist/services/sandboxed-code-host/sandbox.d.ts.map +1 -0
  409. package/dist/services/sandboxed-code-host/sandbox.js +21 -0
  410. package/dist/services/sandboxed-code-host/sandbox.js.map +1 -0
  411. package/dist/services/sandboxed-code-host/sandboxed-code-host.d.ts +17 -0
  412. package/dist/services/sandboxed-code-host/sandboxed-code-host.d.ts.map +1 -0
  413. package/dist/services/sandboxed-code-host/sandboxed-code-host.js +347 -0
  414. package/dist/services/sandboxed-code-host/sandboxed-code-host.js.map +1 -0
  415. package/dist/services/service-interfaces.d.ts +32 -0
  416. package/dist/services/service-interfaces.d.ts.map +1 -1
  417. package/dist/services/session/background-task-control.d.ts +3 -1
  418. package/dist/services/session/background-task-control.d.ts.map +1 -1
  419. package/dist/services/session/background-task-control.js +4 -0
  420. package/dist/services/session/background-task-control.js.map +1 -1
  421. package/dist/services/session/continuation-plan-applier.d.ts +2 -1
  422. package/dist/services/session/continuation-plan-applier.d.ts.map +1 -1
  423. package/dist/services/session/continuation-plan-applier.js.map +1 -1
  424. package/dist/services/session/continuation-recovery-handler.d.ts +2 -1
  425. package/dist/services/session/continuation-recovery-handler.d.ts.map +1 -1
  426. package/dist/services/session/continuation-recovery-handler.js +49 -5
  427. package/dist/services/session/continuation-recovery-handler.js.map +1 -1
  428. package/dist/services/session/initial-input-preparer.d.ts +2 -1
  429. package/dist/services/session/initial-input-preparer.d.ts.map +1 -1
  430. package/dist/services/session/initial-input-preparer.js +2 -1
  431. package/dist/services/session/initial-input-preparer.js.map +1 -1
  432. package/dist/services/session/initial-turn-recovery-handler.d.ts +2 -1
  433. package/dist/services/session/initial-turn-recovery-handler.d.ts.map +1 -1
  434. package/dist/services/session/initial-turn-recovery-handler.js +51 -16
  435. package/dist/services/session/initial-turn-recovery-handler.js.map +1 -1
  436. package/dist/services/session/post-execute-pending-registry.d.ts +2 -1
  437. package/dist/services/session/post-execute-pending-registry.d.ts.map +1 -1
  438. package/dist/services/session/post-execute-pending-registry.js +3 -2
  439. package/dist/services/session/post-execute-pending-registry.js.map +1 -1
  440. package/dist/services/session/session-client-factory.d.ts +4 -0
  441. package/dist/services/session/session-client-factory.d.ts.map +1 -1
  442. package/dist/services/session/session-client-factory.js +12 -4
  443. package/dist/services/session/session-client-factory.js.map +1 -1
  444. package/dist/services/session/session-composition.d.ts +26 -2
  445. package/dist/services/session/session-composition.d.ts.map +1 -1
  446. package/dist/services/session/session-composition.js +97 -18
  447. package/dist/services/session/session-composition.js.map +1 -1
  448. package/dist/services/session/session-continuity-reset.d.ts +2 -1
  449. package/dist/services/session/session-continuity-reset.d.ts.map +1 -1
  450. package/dist/services/session/session-continuity-reset.js +5 -2
  451. package/dist/services/session/session-continuity-reset.js.map +1 -1
  452. package/dist/services/session/session-identity.d.ts +20 -0
  453. package/dist/services/session/session-identity.d.ts.map +1 -0
  454. package/dist/services/session/session-identity.js +43 -0
  455. package/dist/services/session/session-identity.js.map +1 -0
  456. package/dist/services/session/session-lifecycle.d.ts +5 -1
  457. package/dist/services/session/session-lifecycle.d.ts.map +1 -1
  458. package/dist/services/session/session-lifecycle.js +5 -1
  459. package/dist/services/session/session-lifecycle.js.map +1 -1
  460. package/dist/services/session/session-stream-processor.d.ts +2 -1
  461. package/dist/services/session/session-stream-processor.d.ts.map +1 -1
  462. package/dist/services/session/session-stream-processor.js +5 -4
  463. package/dist/services/session/session-stream-processor.js.map +1 -1
  464. package/dist/services/session/test-helpers/conversation-session-fixtures.d.ts.map +1 -1
  465. package/dist/services/session/test-helpers/conversation-session-fixtures.js +14 -9
  466. package/dist/services/session/test-helpers/conversation-session-fixtures.js.map +1 -1
  467. package/dist/services/session/turn-coordinator.d.ts +2 -1
  468. package/dist/services/session/turn-coordinator.d.ts.map +1 -1
  469. package/dist/services/session/turn-coordinator.js +3 -0
  470. package/dist/services/session/turn-coordinator.js.map +1 -1
  471. package/dist/services/session/turn-workflow.d.ts +4 -1
  472. package/dist/services/session/turn-workflow.d.ts.map +1 -1
  473. package/dist/services/session/turn-workflow.js +58 -21
  474. package/dist/services/session/turn-workflow.js.map +1 -1
  475. package/dist/services/session-rollover/session-rollover-brief.d.ts +8 -1
  476. package/dist/services/session-rollover/session-rollover-brief.d.ts.map +1 -1
  477. package/dist/services/session-rollover/session-rollover-brief.js +14 -1
  478. package/dist/services/session-rollover/session-rollover-brief.js.map +1 -1
  479. package/dist/services/settings/setting-schema-utils.d.ts +2 -0
  480. package/dist/services/settings/setting-schema-utils.d.ts.map +1 -1
  481. package/dist/services/settings/setting-schema-utils.js +15 -27
  482. package/dist/services/settings/setting-schema-utils.js.map +1 -1
  483. package/dist/services/settings/settings-schema.d.ts +8 -0
  484. package/dist/services/settings/settings-schema.d.ts.map +1 -1
  485. package/dist/services/settings/settings-schema.js +23 -6
  486. package/dist/services/settings/settings-schema.js.map +1 -1
  487. package/dist/services/settings/settings-sources.d.ts +207 -0
  488. package/dist/services/settings/settings-sources.d.ts.map +1 -1
  489. package/dist/services/settings/settings-sources.js +48 -1
  490. package/dist/services/settings/settings-sources.js.map +1 -1
  491. package/dist/services/settings/settings-ui-metadata.d.ts +27 -0
  492. package/dist/services/settings/settings-ui-metadata.d.ts.map +1 -0
  493. package/dist/services/settings/settings-ui-metadata.js +283 -0
  494. package/dist/services/settings/settings-ui-metadata.js.map +1 -0
  495. package/dist/services/settings/test-helpers/settings-consumer-inventory.d.ts +10 -0
  496. package/dist/services/settings/test-helpers/settings-consumer-inventory.d.ts.map +1 -1
  497. package/dist/services/settings/test-helpers/settings-consumer-inventory.js +46 -0
  498. package/dist/services/settings/test-helpers/settings-consumer-inventory.js.map +1 -1
  499. package/dist/services/subagents/execution-runner.d.ts.map +1 -1
  500. package/dist/services/subagents/execution-runner.js +8 -0
  501. package/dist/services/subagents/execution-runner.js.map +1 -1
  502. package/dist/services/subagents/role-loader.d.ts.map +1 -1
  503. package/dist/services/subagents/role-loader.js +4 -0
  504. package/dist/services/subagents/role-loader.js.map +1 -1
  505. package/dist/services/subagents/subagent-client-types.d.ts +7 -0
  506. package/dist/services/subagents/subagent-client-types.d.ts.map +1 -1
  507. package/dist/services/subagents/subagent-manager.d.ts.map +1 -1
  508. package/dist/services/subagents/subagent-manager.js +4 -1
  509. package/dist/services/subagents/subagent-manager.js.map +1 -1
  510. package/dist/services/subagents/subagent-notification-store.d.ts +2 -0
  511. package/dist/services/subagents/subagent-notification-store.d.ts.map +1 -1
  512. package/dist/services/subagents/subagent-notification-store.js +4 -0
  513. package/dist/services/subagents/subagent-notification-store.js.map +1 -1
  514. package/dist/services/subagents/test-helpers/subagent-manager-fixtures.d.ts.map +1 -1
  515. package/dist/services/subagents/test-helpers/subagent-manager-fixtures.js +2 -1
  516. package/dist/services/subagents/test-helpers/subagent-manager-fixtures.js.map +1 -1
  517. package/dist/services/subagents/tool-policy.d.ts +8 -0
  518. package/dist/services/subagents/tool-policy.d.ts.map +1 -1
  519. package/dist/services/subagents/tool-policy.js +289 -41
  520. package/dist/services/subagents/tool-policy.js.map +1 -1
  521. package/dist/services/subagents/types.d.ts +2 -1
  522. package/dist/services/subagents/types.d.ts.map +1 -1
  523. package/dist/services/subagents/types.js.map +1 -1
  524. package/dist/test-helpers/conversation-session-with-adapter.d.ts +1 -1
  525. package/dist/test-helpers/conversation-session-with-adapter.d.ts.map +1 -1
  526. package/dist/test-helpers/conversation-session-with-adapter.js +6 -1
  527. package/dist/test-helpers/conversation-session-with-adapter.js.map +1 -1
  528. package/dist/test-helpers/vitest-cache-isolation.d.ts +2 -0
  529. package/dist/test-helpers/vitest-cache-isolation.d.ts.map +1 -0
  530. package/dist/test-helpers/vitest-cache-isolation.js +17 -0
  531. package/dist/test-helpers/vitest-cache-isolation.js.map +1 -0
  532. package/dist/tools/agent/activate-skill.d.ts.map +1 -1
  533. package/dist/tools/agent/activate-skill.js +1 -0
  534. package/dist/tools/agent/activate-skill.js.map +1 -1
  535. package/dist/tools/agent/configure-task-check-in.d.ts.map +1 -1
  536. package/dist/tools/agent/configure-task-check-in.js +1 -0
  537. package/dist/tools/agent/configure-task-check-in.js.map +1 -1
  538. package/dist/tools/agent/run-subagent-async.d.ts.map +1 -1
  539. package/dist/tools/agent/run-subagent-async.js +16 -12
  540. package/dist/tools/agent/run-subagent-async.js.map +1 -1
  541. package/dist/tools/file/apply-patch.d.ts.map +1 -1
  542. package/dist/tools/file/apply-patch.js +9 -11
  543. package/dist/tools/file/apply-patch.js.map +1 -1
  544. package/dist/tools/file/code-context.d.ts.map +1 -1
  545. package/dist/tools/file/code-context.js +40 -5
  546. package/dist/tools/file/code-context.js.map +1 -1
  547. package/dist/tools/file/create-file.d.ts.map +1 -1
  548. package/dist/tools/file/create-file.js +13 -8
  549. package/dist/tools/file/create-file.js.map +1 -1
  550. package/dist/tools/file/glob.d.ts.map +1 -1
  551. package/dist/tools/file/glob.js +49 -11
  552. package/dist/tools/file/glob.js.map +1 -1
  553. package/dist/tools/file/grep.d.ts.map +1 -1
  554. package/dist/tools/file/grep.js +32 -8
  555. package/dist/tools/file/grep.js.map +1 -1
  556. package/dist/tools/file/read-file.d.ts.map +1 -1
  557. package/dist/tools/file/read-file.js +109 -6
  558. package/dist/tools/file/read-file.js.map +1 -1
  559. package/dist/tools/file/search-replace.js +4 -4
  560. package/dist/tools/file/search-replace.js.map +1 -1
  561. package/dist/tools/file/upstream-apply-patch.d.ts.map +1 -1
  562. package/dist/tools/file/upstream-apply-patch.js +4 -1
  563. package/dist/tools/file/upstream-apply-patch.js.map +1 -1
  564. package/dist/tools/memory/memory-tools.d.ts.map +1 -1
  565. package/dist/tools/memory/memory-tools.js +19 -1
  566. package/dist/tools/memory/memory-tools.js.map +1 -1
  567. package/dist/tools/session-browser/session-browser-tools.d.ts.map +1 -1
  568. package/dist/tools/session-browser/session-browser-tools.js +24 -8
  569. package/dist/tools/session-browser/session-browser-tools.js.map +1 -1
  570. package/dist/tools/session-rollover/session-rollover-tool.d.ts.map +1 -1
  571. package/dist/tools/session-rollover/session-rollover-tool.js +8 -2
  572. package/dist/tools/session-rollover/session-rollover-tool.js.map +1 -1
  573. package/dist/tools/system/run-code/index.d.ts +2 -0
  574. package/dist/tools/system/run-code/index.d.ts.map +1 -0
  575. package/dist/tools/system/run-code/index.js +2 -0
  576. package/dist/tools/system/run-code/index.js.map +1 -0
  577. package/dist/tools/system/run-code/run-code-telemetry.d.ts +92 -0
  578. package/dist/tools/system/run-code/run-code-telemetry.d.ts.map +1 -0
  579. package/dist/tools/system/run-code/run-code-telemetry.js +189 -0
  580. package/dist/tools/system/run-code/run-code-telemetry.js.map +1 -0
  581. package/dist/tools/system/run-code/run-code.d.ts +98 -0
  582. package/dist/tools/system/run-code/run-code.d.ts.map +1 -0
  583. package/dist/tools/system/run-code/run-code.js +1078 -0
  584. package/dist/tools/system/run-code/run-code.js.map +1 -0
  585. package/dist/tools/system/run-code/tools-header.d.ts +25 -0
  586. package/dist/tools/system/run-code/tools-header.d.ts.map +1 -0
  587. package/dist/tools/system/run-code/tools-header.js +136 -0
  588. package/dist/tools/system/run-code/tools-header.js.map +1 -0
  589. package/dist/tools/system/shell.d.ts.map +1 -1
  590. package/dist/tools/system/shell.js +58 -9
  591. package/dist/tools/system/shell.js.map +1 -1
  592. package/dist/tools/system/worktree.js +2 -2
  593. package/dist/tools/system/worktree.js.map +1 -1
  594. package/dist/tools/types.d.ts +24 -0
  595. package/dist/tools/types.d.ts.map +1 -1
  596. package/dist/tools/types.js.map +1 -1
  597. package/dist/tools/utils.d.ts +10 -0
  598. package/dist/tools/utils.d.ts.map +1 -1
  599. package/dist/tools/utils.js +13 -0
  600. package/dist/tools/utils.js.map +1 -1
  601. package/dist/tools/web/web-fetch.d.ts.map +1 -1
  602. package/dist/tools/web/web-fetch.js +14 -6
  603. package/dist/tools/web/web-fetch.js.map +1 -1
  604. package/dist/tools/web/web-search.d.ts.map +1 -1
  605. package/dist/tools/web/web-search.js +2 -1
  606. package/dist/tools/web/web-search.js.map +1 -1
  607. package/dist/utils/ai/model-settings.d.ts.map +1 -1
  608. package/dist/utils/ai/model-settings.js +0 -47
  609. package/dist/utils/ai/model-settings.js.map +1 -1
  610. package/dist/utils/conversation/apply-conversation-result.d.ts.map +1 -1
  611. package/dist/utils/conversation/apply-conversation-result.js +13 -0
  612. package/dist/utils/conversation/apply-conversation-result.js.map +1 -1
  613. package/dist/utils/conversation/conversation-utils.d.ts.map +1 -1
  614. package/dist/utils/conversation/conversation-utils.js +14 -0
  615. package/dist/utils/conversation/conversation-utils.js.map +1 -1
  616. package/dist/utils/output/bound-tool-result.d.ts +23 -0
  617. package/dist/utils/output/bound-tool-result.d.ts.map +1 -1
  618. package/dist/utils/output/bound-tool-result.js +27 -0
  619. package/dist/utils/output/bound-tool-result.js.map +1 -1
  620. package/dist/utils/settings-command.d.ts +8 -0
  621. package/dist/utils/settings-command.d.ts.map +1 -1
  622. package/dist/utils/settings-command.js +45 -30
  623. package/dist/utils/settings-command.js.map +1 -1
  624. package/dist/utils/shell/execute-shell.d.ts +18 -0
  625. package/dist/utils/shell/execute-shell.d.ts.map +1 -1
  626. package/dist/utils/shell/execute-shell.js +48 -6
  627. package/dist/utils/shell/execute-shell.js.map +1 -1
  628. package/dist/utils/shell/shell-output.d.ts +7 -1
  629. package/dist/utils/shell/shell-output.d.ts.map +1 -1
  630. package/dist/utils/shell/shell-output.js +37 -7
  631. package/dist/utils/shell/shell-output.js.map +1 -1
  632. package/dist/utils/streaming/streaming-session-factory.d.ts +9 -0
  633. package/dist/utils/streaming/streaming-session-factory.d.ts.map +1 -1
  634. package/dist/utils/streaming/streaming-session-factory.js +1 -1
  635. package/dist/utils/streaming/streaming-session-factory.js.map +1 -1
  636. package/dist/utils/tool-args-display.d.ts +21 -0
  637. package/dist/utils/tool-args-display.d.ts.map +1 -0
  638. package/dist/utils/tool-args-display.js +34 -0
  639. package/dist/utils/tool-args-display.js.map +1 -0
  640. package/dist/utils/value-suggestions.d.ts +4 -10
  641. package/dist/utils/value-suggestions.d.ts.map +1 -1
  642. package/dist/utils/value-suggestions.js +77 -144
  643. package/dist/utils/value-suggestions.js.map +1 -1
  644. package/dist/utils/worker-bootstrap.d.ts +3 -0
  645. package/dist/utils/worker-bootstrap.d.ts.map +1 -0
  646. package/dist/utils/worker-bootstrap.js +7 -0
  647. package/dist/utils/worker-bootstrap.js.map +1 -0
  648. package/dist/utils/worker-cwd-preload.cjs +23 -0
  649. package/dist/utils/worker-cwd-preload.cjs.map +1 -0
  650. package/dist/utils/worker-cwd-preload.d.cts +2 -0
  651. package/dist/utils/worker-cwd-preload.d.cts.map +1 -0
  652. package/package.json +5 -2
  653. package/dist/services/agent-runtime/workflow/workflow-worker.d.ts +0 -4
  654. package/dist/services/agent-runtime/workflow/workflow-worker.d.ts.map +0 -1
  655. package/dist/services/agent-runtime/workflow/workflow-worker.js +0 -55
  656. package/dist/services/agent-runtime/workflow/workflow-worker.js.map +0 -1
@@ -0,0 +1,1078 @@
1
+ import { appendFileSync } from 'node:fs';
2
+ import { lstat } from 'node:fs/promises';
3
+ import { randomUUID } from 'node:crypto';
4
+ import { z } from 'zod';
5
+ import { relaxedNumber } from '../../utils.js';
6
+ import { normalizeToolParameters } from '../../../lib/tool-invoke.js';
7
+ import { SandboxedCodeHostImpl } from '../../../services/sandboxed-code-host/sandboxed-code-host.js';
8
+ import { applyApprovalGrant } from '../../../services/approval/approval-grant-executor.js';
9
+ import { isZodToolParameterSchema, } from '../../types.js';
10
+ import { createBaseMessage, getCallIdFromItem, getOutputText, isSuccessOutput, normalizeToolArguments, } from '../../format-helpers.js';
11
+ import { WORKFLOW_PROHIBITED_TOOLS } from '../../../services/agent-runtime/workflow/workflow-evaluator.js';
12
+ import { renderCompactSignature, renderToolsHeader } from './tools-header.js';
13
+ import { emitRunCodeCompletionTelemetry } from './run-code-telemetry.js';
14
+ import { resolveWorkspacePath, resolveWorkspacePathPhysically } from '../../utils.js';
15
+ import { resolveOutsideWorkspaceEdit } from '../../../services/approval/approval-descriptor.js';
16
+ import { parseUpstreamApplyPatch } from '../../file/upstream-apply-patch.js';
17
+ import { saveOutputArtifact, formatFullOutputSavedNote } from '../../../utils/shell/shell-output.js';
18
+ export const TOOL_NAME_RUN_CODE = 'run_code';
19
+ export const TOOL_NAME_DESCRIBE = 'describe';
20
+ const DEFAULT_TIMEOUT_MS = 120_000;
21
+ /** Node `setTimeout` wraps delays above `2**31-1` to ~1 ms. */
22
+ const MAX_TIMEOUT_MS = 2_147_483_647;
23
+ const MAX_OUTPUT_CHARS = 30_000;
24
+ let nextBridgeRunId = 0;
25
+ const createBridgeRunId = () => `run_code_bridge_${++nextBridgeRunId}`;
26
+ /**
27
+ * Script-shaped limits. They are deliberately not the workflow's: a workflow
28
+ * spawns a handful of agents, while a script's whole point is looping over many
29
+ * cheap tool calls.
30
+ */
31
+ export const RUN_CODE_LIMITS = {
32
+ /** Total `tools.*` calls one script may make. */
33
+ maxCalls: 200,
34
+ /** Parallel-safe calls that may overlap; others take a serial lane of one. */
35
+ maxConcurrency: 8,
36
+ /** Per-result cap. A larger result is truncated with an explicit marker. */
37
+ maxResultChars: 100_000,
38
+ /** Maximum raw bytes in one media attachment retained outside the script. */
39
+ maxMediaBytes: 8 * 1024 * 1024,
40
+ /** Maximum raw bytes and attachment count retained for one script run. */
41
+ maxMediaTotalBytes: 32 * 1024 * 1024,
42
+ maxMediaAttachments: 32,
43
+ maxCodeBytes: 65_536,
44
+ maxOutputBytes: 262_144,
45
+ maxConsoleBytes: 262_144,
46
+ };
47
+ /**
48
+ * Tools a script may never call.
49
+ *
50
+ * `run_code` excludes itself because each run owns its own call budget, and
51
+ * nesting would let one run spend many. The rest are the workflow's prohibited
52
+ * set: `run_subagent` in particular spawns agents outside any run budget, so a
53
+ * script could loop on it indefinitely. Shell tools are excluded because their
54
+ * complete approval state also lives in the interactive batch coordinator.
55
+ */
56
+ export const RUN_CODE_PROHIBITED_TOOLS = new Set([
57
+ ...WORKFLOW_PROHIBITED_TOOLS,
58
+ TOOL_NAME_RUN_CODE,
59
+ 'ask_mentor',
60
+ 'session_rollover',
61
+ // Shell approval also depends on coordinator-owned Docker/session state that
62
+ // the raw policy registry cannot express for an out-of-band script call.
63
+ 'shell',
64
+ 'bash',
65
+ 'enter_worktree',
66
+ 'exit_worktree',
67
+ ]);
68
+ export const runCodeParametersSchema = z.object({
69
+ code: z
70
+ .string()
71
+ .min(1)
72
+ .describe('JavaScript (not TypeScript) executed as the body of an async function. Top-level await is available. ' +
73
+ 'Return the value you want the model to receive. Use console.log only for debugging.'),
74
+ include_console: z
75
+ .boolean()
76
+ .optional()
77
+ .describe('Include console.log debugging trace in the successful result. Defaults to false.'),
78
+ // Non-positive is rejected because `setTimeout(fn, 0)` fires promptly; it
79
+ // does not disable the timer. Values above 2**31-1 wrap to ~1 ms in Node.
80
+ timeout_ms: relaxedNumber
81
+ .int()
82
+ .positive()
83
+ .max(MAX_TIMEOUT_MS)
84
+ .optional()
85
+ .describe(`Wall-clock limit for the script. Defaults to ${DEFAULT_TIMEOUT_MS}.`),
86
+ description: z.string().describe('One short line describing what the script does, shown to the user.'),
87
+ });
88
+ const RUN_CODE_DESCRIPTION = 'Write a JavaScript program and execute it. Return the value you want the model to receive; that completion value is ' +
89
+ 'the result of the run. Most tools you already have are available inside the script as ' +
90
+ "`tools.<tool_name>(params)`, returning a promise that resolves to that tool's normal result and rejecting when " +
91
+ 'the call fails, so you can try/catch it. Parameters are exactly the parameters documented for that tool; they are ' +
92
+ 'validated against the real schema before the tool runs. Prefer this over many separate tool calls when the work ' +
93
+ 'is a loop, a fan-out over many files, or a multi-step computation whose intermediate values you do not need to ' +
94
+ 'see. `console.log` is a debugging trace: it is suppressed on successful runs unless you set `include_console: true`, ' +
95
+ 'but it is included when the script fails or times out. The code runs in an isolated ' +
96
+ 'context with no filesystem, network, timers, require, or eval: `tools.*` is the only way out. Auto-approved tools ' +
97
+ 'run immediately. Tools that require user approval present the existing approval prompt and resume this script after ' +
98
+ 'a decision; denial is catchable. Some tools are structurally unavailable inside scripts; those remain direct tools.\n\n' +
99
+ `Each script may admit at most ${RUN_CODE_LIMITS.maxCalls} tools.* calls. Track progress and split large work into chunks; catch individual ` +
100
+ 'failures or use Promise.allSettled so you can return partial results. When the call budget is exhausted, the error ' +
101
+ 'reports calls admitted and calls remaining: return the partial results and start another run_code call only for ' +
102
+ 'unattempted work. Do not repeat completed tool effects. Return only the fields, line ranges, or summaries you need: ' +
103
+ 'model-visible output is limited to 30,000 characters, ' +
104
+ 'and larger host results can fail before rendering. For independent reads, preserve successful siblings with ' +
105
+ '`Promise.allSettled`, mapping rejections to `{error: r.reason.message}` before returning. ' +
106
+ 'If the final result says `Full output saved to`, read that exact path with `read_file` rather than repeating completed calls; ' +
107
+ 'for a large artifact, use line ranges or a focused `grep` projection. A scripted `read_file` result may itself have ' +
108
+ '`truncated: true` and a `fullOutputPath`; follow that path or narrow the projection before returning it. ' +
109
+ 'Use `tools.describe` before guessing parameters or returned fields. If a patch is scripted, escape backticks and ' +
110
+ '${...} inside a template literal, or use ordinary quoted strings with escaped newlines. ' +
111
+ 'Example: `const r = await Promise.allSettled([tools.read_file({path:"a.ts"}), tools.read_file({path:"b.ts"})]); ' +
112
+ 'return r.map(x => x.status === "fulfilled" ? {content:(typeof x.value === "string" ? x.value : x.value.content).slice(0,2000)} : {error:x.reason.message});`';
113
+ /**
114
+ * Static host-owned classification: exactly the action tools with an explicit
115
+ * outcome adapter. Not a naming convention, not a script declaration, and not
116
+ * the generic `effect` flag (a stall-detection marker, not an action contract).
117
+ */
118
+ const ACTION_SEMANTICS = {
119
+ configure_task_check_in: (raw) => {
120
+ const parsed = parseActionPayload(raw);
121
+ if (!isRecord(parsed) || typeof parsed.ok !== 'boolean') {
122
+ return { outcome: 'unknown', reason: 'unrecognized action result shape' };
123
+ }
124
+ if (parsed.ok === true)
125
+ return { outcome: 'applied' };
126
+ const detail = typeof parsed.error === 'string' && parsed.error ? parsed.error : 'action reported ok:false';
127
+ return { outcome: 'not_applied', reason: detail };
128
+ },
129
+ cancel_run: (raw) => {
130
+ const parsed = parseActionPayload(raw);
131
+ if (!isRecord(parsed) || typeof parsed.ok !== 'boolean') {
132
+ return { outcome: 'unknown', reason: 'unrecognized action result shape' };
133
+ }
134
+ if (parsed.ok === true &&
135
+ typeof parsed.runId === 'string' &&
136
+ parsed.runId.length > 0 &&
137
+ parsed.status === 'cancelling') {
138
+ return { outcome: 'applied', reason: 'cancellation requested and accepted; settlement is reported separately' };
139
+ }
140
+ if (parsed.ok === false &&
141
+ parsed.code === 'not_active' &&
142
+ typeof parsed.target === 'string' &&
143
+ parsed.target.length > 0) {
144
+ return { outcome: 'not_applied', reason: `not_active (target: ${parsed.target})` };
145
+ }
146
+ return { outcome: 'unknown', reason: 'unrecognized action result shape' };
147
+ },
148
+ };
149
+ const isActionTool = (name) => ACTION_SEMANTICS[name] !== undefined;
150
+ const parseActionPayload = (raw) => {
151
+ if (typeof raw !== 'string')
152
+ return raw;
153
+ try {
154
+ return JSON.parse(raw);
155
+ }
156
+ catch {
157
+ return raw;
158
+ }
159
+ };
160
+ const MAX_RECEIPT_REASON_CHARS = 280;
161
+ const clipReason = (reason) => reason.length <= MAX_RECEIPT_REASON_CHARS ? reason : `${reason.slice(0, MAX_RECEIPT_REASON_CHARS)}…`;
162
+ /**
163
+ * Marks a definition as accepting the final, wrapped tool registry.
164
+ *
165
+ * `run_code` is built in `agent.ts` from raw definitions, but the policy layer
166
+ * (plan-mode interceptors, approval wrapping, post-execute hooks) is added
167
+ * afterwards in `agent-factory.ts`. Handing the script the raw array would let
168
+ * it reach an implementation the harness had deliberately wrapped, so the
169
+ * registry is injected after wrapping instead.
170
+ */
171
+ const REGISTRY_BINDER = Symbol.for('term2.run_code.bindRegistry');
172
+ const NESTED_OWNER_BINDER = Symbol.for('term2.run_code.bindNestedApprovalOwner');
173
+ /** Installs the wrapped registry into any `run_code` definition in `tools`. */
174
+ export function bindRunCodeRegistry(tools) {
175
+ for (const tool of tools) {
176
+ tool[REGISTRY_BINDER]?.(tools);
177
+ }
178
+ }
179
+ export function bindRunCodeNestedApprovalOwner(tools, owner) {
180
+ for (const tool of tools) {
181
+ tool[NESTED_OWNER_BINDER]?.(owner, tools);
182
+ }
183
+ }
184
+ /**
185
+ * Direct calls are the tools a script structurally cannot reach, including
186
+ * `run_code` itself. Visibility does not depend on `canRequireApproval`.
187
+ */
188
+ export function isDirectlyCallable(tool) {
189
+ return RUN_CODE_PROHIBITED_TOOLS.has(tool.name);
190
+ }
191
+ function unknownToolMessage(name, registry) {
192
+ return `Unknown tool "${name}". Available: ${registry.map((entry) => entry.name).join(', ')}`;
193
+ }
194
+ function describeTool(tool) {
195
+ let parameters;
196
+ const targetSchema = tool.canonicalParameters ?? tool.parameters;
197
+ if (isZodToolParameterSchema(targetSchema)) {
198
+ try {
199
+ parameters = z.toJSONSchema(targetSchema, { io: 'input' });
200
+ }
201
+ catch {
202
+ parameters = { unconvertible: true };
203
+ }
204
+ }
205
+ else if (targetSchema && typeof targetSchema === 'object') {
206
+ parameters = targetSchema;
207
+ }
208
+ else {
209
+ parameters = { unconvertible: true };
210
+ }
211
+ return {
212
+ name: tool.name,
213
+ description: tool.description,
214
+ parameters,
215
+ // The scripted-path return contract. Agents discover it here before
216
+ // calling, and the tools header renders the same string for essential
217
+ // tools, so both surfaces stay consistent.
218
+ ...(typeof tool.scriptedReturnShape === 'string' && tool.scriptedReturnShape
219
+ ? { scriptedReturnShape: tool.scriptedReturnShape }
220
+ : {}),
221
+ };
222
+ }
223
+ const summarizeCalls = (calls) => {
224
+ const describeCalls = calls.filter((call) => call.outcome === 'describe');
225
+ const executionCalls = calls.filter((call) => call.outcome !== 'describe');
226
+ let callSummary;
227
+ if (executionCalls.length === 0) {
228
+ callSummary = 'no tool calls';
229
+ }
230
+ else {
231
+ const counts = new Map();
232
+ for (const call of executionCalls)
233
+ counts.set(call.tool, (counts.get(call.tool) ?? 0) + 1);
234
+ const parts = [...counts.entries()].map(([tool, count]) => (count > 1 ? `${tool}×${count}` : tool));
235
+ callSummary = `${executionCalls.length} tool call${executionCalls.length === 1 ? '' : 's'}: ${parts.join(', ')}`;
236
+ }
237
+ if (describeCalls.length > 0) {
238
+ return `${callSummary}; ${describeCalls.length} schema lookup${describeCalls.length === 1 ? '' : 's'}`;
239
+ }
240
+ return callSummary;
241
+ };
242
+ const clip = async (text, protectedAction) => {
243
+ if (text.length <= MAX_OUTPUT_CHARS)
244
+ return text;
245
+ let retrieval;
246
+ try {
247
+ retrieval = formatFullOutputSavedNote(await saveOutputArtifact(text, { filenamePrefix: 'run-code' }));
248
+ }
249
+ catch {
250
+ // Effects have already settled. A disk failure must not invite their replay.
251
+ retrieval =
252
+ 'Full output could not be saved; the omitted text is unavailable. Do not repeat completed tool effects.';
253
+ }
254
+ const marker = `\n[truncated: output exceeded ${MAX_OUTPUT_CHARS} characters]\n${retrieval}`;
255
+ // Preserve the lifecycle heading as well as host evidence. Script-authored
256
+ // output may consume the entire budget; it must not hide action outcomes.
257
+ const available = MAX_OUTPUT_CHARS - marker.length;
258
+ const action = protectedAction
259
+ ? `\n\n${protectedAction.full.length + 2 <= available - 64 ? protectedAction.full : protectedAction.compact}`
260
+ : '';
261
+ let prefix = (protectedAction?.prefix ?? text).slice(0, Math.max(0, available - action.length));
262
+ if (/[\uD800-\uDBFF]$/.test(prefix))
263
+ prefix = prefix.slice(0, -1);
264
+ return `${prefix}${marker}${action}`;
265
+ };
266
+ const FAILURE_PREFIXES = [
267
+ 'Error:',
268
+ 'Script failed',
269
+ 'Script timed out',
270
+ 'Script was cancelled',
271
+ 'Script exceeded its deadline',
272
+ ];
273
+ /**
274
+ * Whether a rendered run_code result reads as unsuccessful. Script-level
275
+ * failures start with a known prefix; a script can also complete at the JS
276
+ * level while its nested result is an error string (status-string tools such as
277
+ * apply_patch), which the renderer places under a `Result:` heading. Lifecycle
278
+ * status stays 'completed' in both cases — this is the call-level success bit,
279
+ * kept separate from script success (visible in the text) and task success
280
+ * (conversation-level).
281
+ */
282
+ const isUnsuccessfulRunCodeOutput = (output) => {
283
+ if (FAILURE_PREFIXES.some((prefix) => output.startsWith(prefix)))
284
+ return true;
285
+ if (output.startsWith('Result:')) {
286
+ // The renderer joins the rendered value and the trailing tool-call summary
287
+ // with a blank line. Evaluate only the value block, using the shared
288
+ // success heuristic: an 'Error:' text prefix or a JSON value carrying an
289
+ // 'error' key (string or structured envelope) both read as unsuccessful.
290
+ const valueBlock = output.slice('Result:'.length).trimStart().split('\n\n')[0];
291
+ return !isSuccessOutput(valueBlock);
292
+ }
293
+ return false;
294
+ };
295
+ /**
296
+ * Truncation is a display concern, but a script may branch on the result, so
297
+ * the marker has to be unmistakable rather than a silent cut.
298
+ */
299
+ const truncate = (text, limit) => text.length <= limit ? text : `${text.slice(0, limit)}\n[truncated: result exceeded ${limit} characters]`;
300
+ const isRecord = (value) => typeof value === 'object' && value !== null;
301
+ const isMediaContentPart = (value) => isRecord(value) && ((value.type === 'image' && 'image' in value) || (value.type === 'file' && 'file' in value));
302
+ const isContentPartArray = (value) => Array.isArray(value) &&
303
+ value.length > 0 &&
304
+ value.every((part) => isRecord(part) && (part.type === 'text' || isMediaContentPart(part)));
305
+ const MEDIA_REFERENCE_KEY = '__term2_run_code_media_reference__';
306
+ const isMediaReference = (value) => isRecord(value) && typeof value[MEDIA_REFERENCE_KEY] === 'string' && Object.keys(value).length === 1;
307
+ /** Count the bytes that will eventually be sent to the model, not its JSON wrapper. */
308
+ function mediaBytes(value) {
309
+ const payload = value.type === 'image' ? value.image : value.type === 'file' ? value.file : undefined;
310
+ if (isRecord(payload) && typeof payload.data === 'string') {
311
+ try {
312
+ return Buffer.from(payload.data, 'base64').byteLength;
313
+ }
314
+ catch {
315
+ return Buffer.byteLength(payload.data, 'utf8');
316
+ }
317
+ }
318
+ try {
319
+ return Buffer.byteLength(JSON.stringify(payload) ?? '', 'utf8');
320
+ }
321
+ catch {
322
+ return Number.POSITIVE_INFINITY;
323
+ }
324
+ }
325
+ /**
326
+ * Keep large media out of both the worker transport and its generic result
327
+ * budget. The reference is deliberately scoped to one execute call: a token
328
+ * from another run is just an ordinary object and cannot recover its bytes.
329
+ */
330
+ function createMediaReferenceStore() {
331
+ const attachments = new Map();
332
+ const byValue = new WeakMap();
333
+ let totalBytes = 0;
334
+ const capture = (value) => {
335
+ if (isMediaContentPart(value)) {
336
+ const existing = byValue.get(value);
337
+ if (existing !== undefined)
338
+ return existing ? { [MEDIA_REFERENCE_KEY]: existing } : '[media content omitted]';
339
+ const size = mediaBytes(value);
340
+ if (!Number.isFinite(size) ||
341
+ size > RUN_CODE_LIMITS.maxMediaBytes ||
342
+ attachments.size >= RUN_CODE_LIMITS.maxMediaAttachments ||
343
+ totalBytes + size > RUN_CODE_LIMITS.maxMediaTotalBytes) {
344
+ byValue.set(value, null);
345
+ return (`[media content omitted: attachment exceeds the ${RUN_CODE_LIMITS.maxMediaBytes}-byte per-image or ` +
346
+ `${RUN_CODE_LIMITS.maxMediaTotalBytes}-byte per-run limit]`);
347
+ }
348
+ const token = `run_code_media_${randomUUID()}`;
349
+ byValue.set(value, token);
350
+ attachments.set(token, value);
351
+ totalBytes += size;
352
+ return { [MEDIA_REFERENCE_KEY]: token };
353
+ }
354
+ if (Array.isArray(value))
355
+ return value.map(capture);
356
+ if (isRecord(value)) {
357
+ return Object.fromEntries(Object.entries(value).map(([key, entry]) => [key, capture(entry)]));
358
+ }
359
+ return value;
360
+ };
361
+ const resolve = (value) => {
362
+ if (isMediaReference(value))
363
+ return attachments.get(value[MEDIA_REFERENCE_KEY]) ?? value;
364
+ if (Array.isArray(value))
365
+ return value.map(resolve);
366
+ if (isRecord(value))
367
+ return Object.fromEntries(Object.entries(value).map(([key, entry]) => [key, resolve(entry)]));
368
+ return value;
369
+ };
370
+ return { capture, resolve };
371
+ }
372
+ /** Look through script wrappers without mistaking ordinary arrays for media. */
373
+ function containsMediaContent(value, ancestors = new Set()) {
374
+ if (isMediaContentPart(value))
375
+ return true;
376
+ if (!isRecord(value) && !Array.isArray(value))
377
+ return false;
378
+ if (ancestors.has(value))
379
+ return false;
380
+ ancestors.add(value);
381
+ const found = Array.isArray(value)
382
+ ? value.some((entry) => containsMediaContent(entry, ancestors))
383
+ : Object.values(value).some((entry) => containsMediaContent(entry, ancestors));
384
+ ancestors.delete(value);
385
+ return found;
386
+ }
387
+ const serializeResult = async (result, limit, toolName, callsCompleted) => {
388
+ if (typeof result === 'string')
389
+ return { ok: true, result: truncate(result, limit) };
390
+ try {
391
+ const encoded = JSON.stringify(result);
392
+ if (encoded === undefined)
393
+ return { ok: true, result: null };
394
+ if (encoded.length <= limit)
395
+ return { ok: true, result: result };
396
+ // Never turn a multimodal result into a partial JSON string: that both
397
+ // corrupts image data and makes the failure look like a successful text
398
+ // result to the script. A clear value lets the script continue (or catch
399
+ // the omission) without sending an unusable image to the worker.
400
+ if (containsMediaContent(result)) {
401
+ return {
402
+ ok: true,
403
+ result: `[truncated: media result exceeded ${limit} characters; media content omitted]`,
404
+ };
405
+ }
406
+ let retrieval = '';
407
+ try {
408
+ const artifactPath = await saveOutputArtifact(encoded, { filenamePrefix: 'tool-overflow' });
409
+ retrieval = `Full output saved to: ${artifactPath}. `;
410
+ }
411
+ catch {
412
+ retrieval = 'Full output could not be saved; the omitted result is unavailable. ';
413
+ }
414
+ const callUnit = callsCompleted === 1 ? 'call' : 'calls';
415
+ const message = `Tool "${toolName}" result exceeded ${limit} characters and could not be delivered to script. ${retrieval}${callsCompleted} nested tool ${callUnit} completed — inspect state before retrying; tool effects have already completed.`;
416
+ return { ok: false, error: message };
417
+ }
418
+ catch {
419
+ return { ok: true, result: truncate(String(result), limit) };
420
+ }
421
+ };
422
+ /** Replace embedded media with a text marker while retaining the real parts. */
423
+ function stripMediaContent(value, media) {
424
+ if (isMediaContentPart(value)) {
425
+ media.push(value);
426
+ return value.type === 'image' ? '[image content attached]' : '[file content attached]';
427
+ }
428
+ if (Array.isArray(value))
429
+ return value.map((entry) => stripMediaContent(entry, media));
430
+ if (isRecord(value)) {
431
+ return Object.fromEntries(Object.entries(value).map(([key, entry]) => [key, stripMediaContent(entry, media)]));
432
+ }
433
+ return value;
434
+ }
435
+ /** Renders one console.log's arguments the way a terminal would. */
436
+ const renderConsoleValues = (values) => values.map((value) => (typeof value === 'string' ? value : JSON.stringify(value))).join(' ');
437
+ export const formatRunCodeCommandMessage = (item, index, toolCallArgumentsById) => {
438
+ const callId = getCallIdFromItem(item);
439
+ const fallbackArgs = callId && toolCallArgumentsById.has(callId) ? toolCallArgumentsById.get(callId) : null;
440
+ const args = normalizeToolArguments(item?.rawItem?.arguments ?? item?.arguments) ?? normalizeToolArguments(fallbackArgs) ?? {};
441
+ const description = typeof args?.description === 'string' ? args.description : undefined;
442
+ const code = typeof args?.code === 'string' ? args.code : '';
443
+ const output = getOutputText(item) || 'No output';
444
+ return [
445
+ createBaseMessage(item, index, 0, false, {
446
+ command: description ? `run_code — ${description}` : 'run_code',
447
+ output,
448
+ success: !isUnsuccessfulRunCodeOutput(output),
449
+ toolName: TOOL_NAME_RUN_CODE,
450
+ toolArgs: { ...args, code },
451
+ }),
452
+ ];
453
+ };
454
+ function getConversationSessionId(context) {
455
+ if (!context || typeof context !== 'object')
456
+ return undefined;
457
+ const runContext = context.context;
458
+ if (!runContext || typeof runContext !== 'object')
459
+ return undefined;
460
+ const sessionId = runContext.sessionId;
461
+ return typeof sessionId === 'string' && sessionId.length > 0 ? sessionId : undefined;
462
+ }
463
+ function writeNestedCallRecord(tool, sessionId, outcome) {
464
+ const logPath = process.env.TERM2_NESTED_CALL_LOG;
465
+ if (!logPath || !sessionId)
466
+ return;
467
+ try {
468
+ appendFileSync(logPath, `${JSON.stringify({ tool, sessionId, timestamp: new Date().toISOString(), outcome })}\n`, 'utf8');
469
+ }
470
+ catch {
471
+ // Experiment-only logging must never affect tool execution.
472
+ }
473
+ }
474
+ export function createRunCodeToolDefinition(options) {
475
+ const { loggingService, getCwd = () => options.executionContext?.getCwd() || process.cwd() } = options;
476
+ const approvalRegistry = options.approvalPolicyRegistry;
477
+ // Set by bindRunCodeRegistry once the policy layer has wrapped every tool.
478
+ let boundRegistry;
479
+ let nestedApprovalOwner = options.nestedApprovalOwner;
480
+ const exposedTools = () => (options.getToolRegistry?.() ?? boundRegistry ?? []).filter((tool) => !RUN_CODE_PROHIBITED_TOOLS.has(tool.name));
481
+ const definition = {
482
+ name: TOOL_NAME_RUN_CODE,
483
+ // Read late, after bindRunCodeRegistry, so the model is told which tools
484
+ // the script can actually reach rather than a guess made before wrapping.
485
+ get description() {
486
+ const header = renderToolsHeader(exposedTools());
487
+ return header ? `${RUN_CODE_DESCRIPTION}\n\n${header}` : RUN_CODE_DESCRIPTION;
488
+ },
489
+ parameters: runCodeParametersSchema,
490
+ effect: 'mutating',
491
+ needsApproval: () => false,
492
+ execute: async (params, context) => {
493
+ const { code, timeout_ms, description, include_console = false } = params;
494
+ const timeout = timeout_ms ?? DEFAULT_TIMEOUT_MS;
495
+ const callerSignal = context?.signal;
496
+ const registry = exposedTools();
497
+ const bridgeRunId = createBridgeRunId();
498
+ const startedAt = Date.now();
499
+ const calls = [];
500
+ // Host-private action receipt ledger. Script code has no write path
501
+ // here: every entry is recorded by prepare/admit/invoke settlement, so
502
+ // a script cannot catch, relabel, or contradict an observed outcome.
503
+ const receipts = [];
504
+ const pendingReceiptByCallId = new Map();
505
+ let rejectedSeq = 0;
506
+ const output = [];
507
+ const sessionId = getConversationSessionId(context);
508
+ const mediaReferences = createMediaReferenceStore();
509
+ const record = (tool, outcome, started, directlyCallable) => {
510
+ calls.push({ tool, outcome, durationMs: Date.now() - started, directlyCallable });
511
+ if (outcome === 'describe')
512
+ return;
513
+ writeNestedCallRecord(tool, sessionId, outcome === 'ok' ? 'success' : outcome === 'approval_required' ? 'denied-by-approval' : 'failure');
514
+ };
515
+ const failed = (message) => ({
516
+ kind: 'result',
517
+ result: { ok: false, error: message },
518
+ });
519
+ const recordReceipt = (callId, toolName, outcome, reason) => {
520
+ const pendingIndex = pendingReceiptByCallId.get(callId);
521
+ if (pendingIndex !== undefined) {
522
+ receipts[pendingIndex] = {
523
+ callId,
524
+ tool: toolName,
525
+ outcome,
526
+ ...(reason ? { reason: clipReason(reason) } : {}),
527
+ };
528
+ pendingReceiptByCallId.delete(callId);
529
+ return;
530
+ }
531
+ receipts.push({
532
+ callId,
533
+ tool: toolName,
534
+ outcome,
535
+ ...(reason ? { reason: clipReason(reason) } : {}),
536
+ });
537
+ };
538
+ const tools = {
539
+ binding: {
540
+ name: 'tools',
541
+ kind: 'namespace',
542
+ members: [...new Set([...registry.map((tool) => tool.name), TOOL_NAME_DESCRIBE])],
543
+ },
544
+ limits: {
545
+ maxCalls: RUN_CODE_LIMITS.maxCalls,
546
+ maxConcurrency: RUN_CODE_LIMITS.maxConcurrency,
547
+ limitExceededMessage: `Tool call limit reached (${RUN_CODE_LIMITS.maxCalls} calls per script run).`,
548
+ },
549
+ // A budget-exhausted call is the script's problem, not a reason to
550
+ // discard the work it has already printed.
551
+ overBudget: ({ usedCalls, maxCalls }, rejected) => {
552
+ // The host supplies the exact prepared call that was rejected.
553
+ // Preparation is async and concurrent, so a local FIFO would be
554
+ // unable to attribute a budget rejection safely.
555
+ if (isActionTool(rejected.tool.name)) {
556
+ rejectedSeq += 1;
557
+ recordReceipt(`${bridgeRunId}:rejected-${rejectedSeq}`, rejected.tool.name, 'unknown', 'call budget exhausted before dispatch');
558
+ }
559
+ return failed(`Tool call limit reached (${maxCalls} calls per script run; ${usedCalls} calls admitted, ${Math.max(0, maxCalls - usedCalls)} remaining). ` +
560
+ 'Return the partial results you collected and start another run_code call only for unattempted work; ' +
561
+ 'Do not repeat completed tool effects.');
562
+ },
563
+ onAdmitted: (prepared, callContext) => {
564
+ if (!isActionTool(prepared.tool.name))
565
+ return;
566
+ const callId = `${bridgeRunId}:${callContext.callId}`;
567
+ pendingReceiptByCallId.set(callId, receipts.length);
568
+ receipts.push({ callId, tool: prepared.tool.name, outcome: 'unknown' });
569
+ },
570
+ prepare: async (payload) => {
571
+ const started = Date.now();
572
+ const name = typeof payload.member === 'string' ? payload.member : '';
573
+ const tool = registry.find((candidate) => candidate.name === name);
574
+ if (name === TOOL_NAME_DESCRIBE && typeof payload.params === 'string') {
575
+ const described = registry.find((candidate) => candidate.name === payload.params);
576
+ if (!described)
577
+ return failed(unknownToolMessage(payload.params, registry));
578
+ record(name, 'describe', started);
579
+ return {
580
+ kind: 'result',
581
+ result: { ok: true, result: describeTool(described) },
582
+ };
583
+ }
584
+ if (!tool) {
585
+ record(name || '(unnamed)', 'unknown_tool', started);
586
+ if (isActionTool(name)) {
587
+ rejectedSeq += 1;
588
+ recordReceipt(`${bridgeRunId}:rejected-${rejectedSeq}`, name, 'failed', unknownToolMessage(name, registry));
589
+ }
590
+ return failed(unknownToolMessage(name, registry));
591
+ }
592
+ const targetSchema = tool.canonicalParameters ?? tool.parameters;
593
+ let normalized;
594
+ try {
595
+ normalized = normalizeToolParameters(payload.params ?? {}, targetSchema);
596
+ }
597
+ catch {
598
+ normalized = payload.params ?? {};
599
+ }
600
+ if (isZodToolParameterSchema(targetSchema)) {
601
+ const parsed = targetSchema.safeParse(normalized);
602
+ if (!parsed.success) {
603
+ record(name, 'invalid_params', started);
604
+ const issues = parsed.error.issues
605
+ .map((issue) => `${issue.path.join('.') || '(root)'}: ${issue.message}`)
606
+ .join('; ');
607
+ if (isActionTool(name)) {
608
+ rejectedSeq += 1;
609
+ recordReceipt(`${bridgeRunId}:rejected-${rejectedSeq}`, name, 'failed', `Invalid parameters: ${issues}`);
610
+ }
611
+ return failed(`Invalid parameters for "${name}": ${issues}\nSignature: ${renderCompactSignature(tool)}`);
612
+ }
613
+ normalized = parsed.data;
614
+ }
615
+ const authorityRoot = getCwd();
616
+ const authority = await bindPreparedAuthority(name, normalized, authorityRoot, options.executionContext);
617
+ if (authority.kind === 'denied') {
618
+ record(name, 'approval_required', started, isDirectlyCallable(tool));
619
+ if (isActionTool(name)) {
620
+ rejectedSeq += 1;
621
+ recordReceipt(`${bridgeRunId}:rejected-${rejectedSeq}`, name, 'not_applied', authority.message);
622
+ }
623
+ return failed(authority.message);
624
+ }
625
+ const prepared = {
626
+ tool,
627
+ params: authority.params,
628
+ originalParams: normalized,
629
+ authorityRoot,
630
+ authorityMeaning: fingerprint(authority),
631
+ parallelSafe: await isParallelSafe(tool, normalized, context),
632
+ started,
633
+ };
634
+ return prepared;
635
+ },
636
+ // Mirrors the run loop: only a definition that declares itself
637
+ // parallel-safe may overlap another call, because tools such as
638
+ // enter_worktree mutate shared execution context.
639
+ lane: (prepared) => (prepared.parallelSafe ? 'default' : 'serial'),
640
+ invoke: async (prepared, callContext) => {
641
+ const decision = await approvalRegistry.evaluate({
642
+ toolName: prepared.tool.name,
643
+ args: prepared.params,
644
+ context,
645
+ });
646
+ if (decision.kind !== 'auto_approve') {
647
+ if (decision.kind === 'prompt' && nestedApprovalOwner) {
648
+ const nestedCallId = bridgeRunId + ':' + callContext.callId;
649
+ const nestedContext = withAbortSignal(context, mergeAbortSignals(callerSignal, callContext.signal), {
650
+ scripted: true,
651
+ });
652
+ tools.onWaiting?.(callContext);
653
+ try {
654
+ const resolution = await nestedApprovalOwner.request({
655
+ requestId: nestedCallId,
656
+ sessionId: sessionId ?? 'unknown',
657
+ graphIdentity: boundRegistry ?? registry,
658
+ outerRunId: bridgeRunId,
659
+ nestedCallId,
660
+ toolName: prepared.tool.name,
661
+ preparedArguments: prepared.params,
662
+ authorityContext: context,
663
+ approval: {
664
+ agentName: 'Nested run_code',
665
+ toolName: prepared.tool.name,
666
+ argumentsText: JSON.stringify(prepared.params),
667
+ rawInterruption: null,
668
+ callId: nestedCallId,
669
+ outsideWorkspaceEdit: resolveOutsideWorkspaceEdit(prepared.tool.name, prepared.params, prepared.authorityRoot),
670
+ },
671
+ signal: nestedContext.signal,
672
+ revalidateAuthority: async () => {
673
+ const currentRoot = getCwd();
674
+ const authority = await bindPreparedAuthority(prepared.tool.name, prepared.originalParams, currentRoot, options.executionContext);
675
+ return (authority.kind === 'bound' &&
676
+ currentRoot === prepared.authorityRoot &&
677
+ fingerprint(authority) === prepared.authorityMeaning);
678
+ },
679
+ revalidate: async () => {
680
+ const latest = await approvalRegistry.evaluate({
681
+ toolName: prepared.tool.name,
682
+ args: prepared.params,
683
+ context,
684
+ });
685
+ return latest.kind;
686
+ },
687
+ grant: (nestedDecision) => {
688
+ if (callContext.signal.aborted)
689
+ throw new Error('Tool execution was not approved.');
690
+ const applied = applyApprovalGrant({
691
+ sessionId: sessionId ?? 'unknown',
692
+ sessionAccess: options.sessionAccess,
693
+ nestedCompatibility: options.nestedCompatibility,
694
+ logger: loggingService,
695
+ }, {
696
+ answer: nestedDecision.answer,
697
+ toolName: prepared.tool.name,
698
+ rawArguments: prepared.params,
699
+ callId: nestedCallId,
700
+ });
701
+ if (!applied.isApproved)
702
+ throw new Error('Tool execution was not approved.');
703
+ },
704
+ dispatch: async () => prepared.tool.execute(prepared.params, nestedContext, { toolCall: { callId: nestedCallId } }),
705
+ });
706
+ if (resolution.kind === 'approved') {
707
+ record(prepared.tool.name, 'ok', prepared.started);
708
+ if (isActionTool(prepared.tool.name)) {
709
+ const semantic = ACTION_SEMANTICS[prepared.tool.name](resolution.result);
710
+ recordReceipt(`${bridgeRunId}:${callContext.callId}`, prepared.tool.name, semantic.outcome, semantic.reason);
711
+ }
712
+ const serialized = await serializeResult(mediaReferences.capture(resolution.result), RUN_CODE_LIMITS.maxResultChars, prepared.tool.name, calls.filter((c) => c.outcome !== 'describe').length);
713
+ return {
714
+ kind: 'result',
715
+ result: serialized,
716
+ };
717
+ }
718
+ if (resolution.kind === 'failed') {
719
+ record(prepared.tool.name, 'error', prepared.started);
720
+ const message = resolution.error instanceof Error ? resolution.error.message : String(resolution.error);
721
+ if (isActionTool(prepared.tool.name)) {
722
+ recordReceipt(`${bridgeRunId}:${callContext.callId}`, prepared.tool.name, 'failed', message);
723
+ }
724
+ return failed(message);
725
+ }
726
+ record(prepared.tool.name, 'approval_required', prepared.started, isDirectlyCallable(prepared.tool));
727
+ if (isActionTool(prepared.tool.name)) {
728
+ recordReceipt(`${bridgeRunId}:${callContext.callId}`, prepared.tool.name, 'not_applied', resolution.message);
729
+ }
730
+ return failed(resolution.message);
731
+ }
732
+ finally {
733
+ tools.onResumed?.(callContext);
734
+ }
735
+ }
736
+ const outcome = decision.kind === 'unknown'
737
+ ? 'unknown_policy'
738
+ : decision.kind === 'error'
739
+ ? 'policy_error'
740
+ : decision.kind === 'interceptor_denied'
741
+ ? 'interceptor_denied'
742
+ : 'approval_required';
743
+ const directlyCallable = isDirectlyCallable(prepared.tool);
744
+ record(prepared.tool.name, outcome, prepared.started, directlyCallable);
745
+ if (isActionTool(prepared.tool.name)) {
746
+ const denialReason = decision.kind === 'unknown'
747
+ ? 'no registered approval policy'
748
+ : decision.kind === 'interceptor_denied'
749
+ ? 'refused by an approval interceptor'
750
+ : decision.kind === 'error'
751
+ ? 'approval policy failed'
752
+ : 'requires approval and is unavailable from inside a script';
753
+ recordReceipt(`${bridgeRunId}:${callContext.callId}`, prepared.tool.name, 'not_applied', denialReason);
754
+ }
755
+ return failed(decision.kind === 'unknown'
756
+ ? `"${prepared.tool.name}" has no registered approval policy and is unavailable from inside a script.`
757
+ : decision.kind === 'interceptor_denied'
758
+ ? `"${prepared.tool.name}" was refused by an approval interceptor and is unavailable from inside a script.`
759
+ : decision.kind === 'error'
760
+ ? `"${prepared.tool.name}" approval policy failed and is unavailable from inside a script.`
761
+ : `"${prepared.tool.name}" requires approval and is unavailable from inside a script.`);
762
+ }
763
+ const started = Date.now();
764
+ const callId = `${bridgeRunId}:${callContext.callId}`;
765
+ try {
766
+ // Marks the call as originating inside a script: the result goes to the
767
+ // script, not into model context, so context-protection caps do not apply.
768
+ const nestedContext = withAbortSignal(context, mergeAbortSignals(callerSignal, callContext.signal), {
769
+ scripted: true,
770
+ });
771
+ const result = await prepared.tool.execute(prepared.params, nestedContext, { toolCall: { callId } });
772
+ record(prepared.tool.name, 'ok', started);
773
+ if (isActionTool(prepared.tool.name)) {
774
+ const semantic = ACTION_SEMANTICS[prepared.tool.name](result);
775
+ recordReceipt(callId, prepared.tool.name, semantic.outcome, semantic.reason);
776
+ }
777
+ const serialized = await serializeResult(mediaReferences.capture(result), RUN_CODE_LIMITS.maxResultChars, prepared.tool.name, calls.filter((c) => c.outcome !== 'describe').length);
778
+ return {
779
+ kind: 'result',
780
+ result: serialized,
781
+ };
782
+ }
783
+ catch (error) {
784
+ record(prepared.tool.name, 'error', started);
785
+ const message = error instanceof Error ? error.message : String(error);
786
+ if (isActionTool(prepared.tool.name)) {
787
+ recordReceipt(callId, prepared.tool.name, 'failed', message);
788
+ }
789
+ return failed(message);
790
+ }
791
+ },
792
+ };
793
+ loggingService.debug('run_code execution started', {
794
+ cwd: getCwd(),
795
+ timeout,
796
+ exposedTools: registry.length,
797
+ description,
798
+ });
799
+ const result = await new SandboxedCodeHostImpl().run({
800
+ code,
801
+ capabilities: { tools },
802
+ limits: {
803
+ timeoutMs: timeout,
804
+ maxCodeBytes: RUN_CODE_LIMITS.maxCodeBytes,
805
+ maxOutputBytes: RUN_CODE_LIMITS.maxOutputBytes,
806
+ maxConsoleBytes: RUN_CODE_LIMITS.maxConsoleBytes,
807
+ },
808
+ subject: 'Script',
809
+ allowVoidOutput: true,
810
+ signal: callerSignal,
811
+ onConsole: (values) => output.push(renderConsoleValues(values)),
812
+ });
813
+ const describeCalls = calls.filter((call) => call.outcome === 'describe');
814
+ const executionCalls = calls.filter((call) => call.outcome !== 'describe');
815
+ loggingService.debug('run_code execution finished', {
816
+ ok: result.ok,
817
+ toolCalls: executionCalls.length,
818
+ schemaLookups: describeCalls.length,
819
+ });
820
+ // Calls admitted but never settled (timeout, deadline, cancellation,
821
+ // worker exit) keep their pending `unknown` outcome with an honest
822
+ // reason rather than vanishing from the ledger.
823
+ for (const [callId, index] of pendingReceiptByCallId) {
824
+ receipts[index] = {
825
+ ...receipts[index],
826
+ outcome: 'unknown',
827
+ reason: 'did not settle before the script run ended',
828
+ };
829
+ pendingReceiptByCallId.delete(callId);
830
+ }
831
+ // Emitted before rendering: a script whose result cannot be rendered has
832
+ // still produced an outcome worth counting.
833
+ emitRunCodeCompletionTelemetry(loggingService, {
834
+ code,
835
+ result,
836
+ durationMs: Date.now() - startedAt,
837
+ timeoutMs: timeout,
838
+ sessionId,
839
+ runId: bridgeRunId,
840
+ calls,
841
+ receipts,
842
+ });
843
+ const resolvedResult = result.ok && !result.voidOutput
844
+ ? { ...result, output: mediaReferences.resolve(result.output) }
845
+ : result;
846
+ return renderResult(resolvedResult, output, calls, receipts, include_console);
847
+ },
848
+ formatCommandMessage: formatRunCodeCommandMessage,
849
+ };
850
+ definition[REGISTRY_BINDER] = (registry) => {
851
+ boundRegistry = registry;
852
+ };
853
+ definition[NESTED_OWNER_BINDER] = (owner, graph) => {
854
+ nestedApprovalOwner = owner;
855
+ // The factory binds run_code before hiding non-direct definitions. Use the
856
+ // complete bound graph as identity, not the later filtered model surface.
857
+ owner.bindGraph(boundRegistry ?? graph);
858
+ };
859
+ return definition;
860
+ }
861
+ const PATH_TOOLS = new Set([
862
+ 'read_file',
863
+ 'create_file',
864
+ 'search_replace',
865
+ 'apply_patch',
866
+ 'grep',
867
+ 'glob',
868
+ 'read_code_outline',
869
+ 'code_context_search',
870
+ ]);
871
+ async function bindPreparedAuthority(toolName, params, cwd, executionContext) {
872
+ const isRemote = executionContext?.isRemote() ?? false;
873
+ if (isRemote && PATH_TOOLS.has(toolName)) {
874
+ return { kind: 'denied', message: 'Cannot establish remote physical path authority for a nested tool call.' };
875
+ }
876
+ try {
877
+ const physicalRoot = isRemote ? cwd : await requirePhysicalPath(cwd, cwd);
878
+ return { kind: 'bound', physicalRoot, params: await bindPreparedArguments(toolName, params, cwd) };
879
+ }
880
+ catch (error) {
881
+ return {
882
+ kind: 'denied',
883
+ message: `Cannot establish physical path authority: ${error instanceof Error ? error.message : String(error)}`,
884
+ };
885
+ }
886
+ }
887
+ async function requirePhysicalPath(value, cwd, semantics = 'referent') {
888
+ const physicalPath = await resolveWorkspacePathPhysically(value, cwd);
889
+ if (physicalPath === undefined)
890
+ throw new Error(`Unresolved path: ${value}`);
891
+ if (semantics === 'unlink-source') {
892
+ // Move sources are both read and unlinked. Following a leaf symlink would
893
+ // preserve the read but delete its referent; reject rather than change meaning.
894
+ const lexicalPath = resolveWorkspacePath(value, cwd, { allowOutsideWorkspace: true });
895
+ const stats = await lstat(lexicalPath);
896
+ if (stats.isSymbolicLink())
897
+ throw new Error(`Symlink unlink source is unsupported: ${value}`);
898
+ }
899
+ return physicalPath;
900
+ }
901
+ async function bindPreparedArguments(toolName, params, cwd) {
902
+ if (!params || typeof params !== 'object' || Array.isArray(params) || !PATH_TOOLS.has(toolName))
903
+ return params;
904
+ const record = params;
905
+ const bindPath = async (value, semantics = 'referent') => typeof value === 'string' ? requirePhysicalPath(value, cwd, semantics) : value;
906
+ if (toolName === 'apply_patch' && typeof record.patch === 'string') {
907
+ return { ...record, patch: await bindPatchPaths(record.patch, bindPath) };
908
+ }
909
+ return 'path' in record ? { ...record, path: await bindPath(record.path) } : params;
910
+ }
911
+ async function bindPatchPaths(patch, bindPath) {
912
+ let parsed;
913
+ try {
914
+ parsed = parseUpstreamApplyPatch(patch);
915
+ }
916
+ catch {
917
+ return patch;
918
+ }
919
+ const targets = parsed.operations.flatMap((operation) => {
920
+ const moveTo = 'moveTo' in operation ? operation.moveTo : undefined;
921
+ const semantics = operation.type === 'delete_file' || moveTo ? 'unlink-source' : 'referent';
922
+ return [{ path: operation.path, semantics }, ...(moveTo ? [{ path: moveTo, semantics: 'referent' }] : [])];
923
+ });
924
+ let targetIndex = 0;
925
+ const lines = patch.replace(/\r\n?/g, '\n').split('\n');
926
+ const prefixes = ['*** Add File: ', '*** Update File: ', '*** Delete File: ', '*** Move to: '];
927
+ for (let index = 0; index < lines.length; index += 1) {
928
+ const prefix = prefixes.find((candidate) => lines[index].startsWith(candidate));
929
+ if (!prefix)
930
+ continue;
931
+ const target = targets[targetIndex++];
932
+ const bound = await bindPath(target.path, target.semantics);
933
+ lines[index] = prefix + String(bound);
934
+ }
935
+ return lines.join('\n');
936
+ }
937
+ function fingerprint(value) {
938
+ try {
939
+ return JSON.stringify(value) ?? String(value);
940
+ }
941
+ catch {
942
+ return String(value);
943
+ }
944
+ }
945
+ function withAbortSignal(context, signal, extra = {}) {
946
+ return context && typeof context === 'object'
947
+ ? { ...context, signal, ...extra }
948
+ : { signal, ...extra };
949
+ }
950
+ function mergeAbortSignals(callerSignal, hostSignal) {
951
+ if (!callerSignal || callerSignal === hostSignal)
952
+ return callerSignal ?? hostSignal;
953
+ const controller = new AbortController();
954
+ const abort = () => {
955
+ callerSignal.removeEventListener('abort', abort);
956
+ hostSignal.removeEventListener('abort', abort);
957
+ controller.abort();
958
+ };
959
+ if (callerSignal.aborted || hostSignal.aborted) {
960
+ controller.abort();
961
+ return controller.signal;
962
+ }
963
+ callerSignal.addEventListener('abort', abort, { once: true });
964
+ hostSignal.addEventListener('abort', abort, { once: true });
965
+ return controller.signal;
966
+ }
967
+ async function isParallelSafe(tool, params, context) {
968
+ const declared = tool.parallelSafe;
969
+ if (declared === undefined || declared === false)
970
+ return false;
971
+ if (declared === true)
972
+ return true;
973
+ try {
974
+ return (await declared(params, context)) === true;
975
+ }
976
+ catch {
977
+ return false;
978
+ }
979
+ }
980
+ const formatActionOutcome = (outcome) => outcome === 'not_applied' ? 'not applied' : outcome;
981
+ /**
982
+ * Host-rendered action section. Present only when at least one covered action
983
+ * call was observed; an empty ledger renders nothing and certifies nothing.
984
+ * Counts are over observed receipts only — never an inferred expected action.
985
+ */
986
+ const renderActionReceipts = (receipts, includeDetails = true) => {
987
+ if (receipts.length === 0)
988
+ return null;
989
+ const lines = receipts.map((receipt) => receipt.reason
990
+ ? `- ${receipt.tool} [${receipt.callId}]: ${formatActionOutcome(receipt.outcome)} — ${receipt.reason}`
991
+ : `- ${receipt.tool} [${receipt.callId}]: ${formatActionOutcome(receipt.outcome)}`);
992
+ const counts = (outcome) => receipts.filter((r) => r.outcome === outcome).length;
993
+ const parts = [
994
+ `${counts('applied')} applied`,
995
+ `${counts('not_applied')} not applied`,
996
+ `${counts('failed')} failed`,
997
+ `${counts('unknown')} unknown`,
998
+ ];
999
+ const unit = receipts.length === 1 ? 'call' : 'calls';
1000
+ return [
1001
+ 'Action outcomes (host-observed):',
1002
+ ...(includeDetails
1003
+ ? lines
1004
+ : [`${receipts.length} receipt details omitted from this display; full-output availability is reported above.`]),
1005
+ `Action summary: ${parts.join(', ')} across ${receipts.length} observed action ${unit}. ` +
1006
+ 'Host-observed tool outcomes are authoritative over conflicting script claims; ' +
1007
+ 'they describe tool behavior, not user-request or task outcomes.',
1008
+ ].join('\n');
1009
+ };
1010
+ function renderResult(result, output, calls, receipts, includeConsole) {
1011
+ const sections = [];
1012
+ const media = [];
1013
+ if (!result.ok && result.error) {
1014
+ sections.push(result.error.code === 'timeout'
1015
+ ? `Script timed out. ${result.error.message}`
1016
+ : result.error.code === 'deadline'
1017
+ ? `Script exceeded its deadline. ${result.error.message}`
1018
+ : result.error.code === 'cancelled'
1019
+ ? `Script was cancelled. ${result.error.message}`
1020
+ : `Script failed: ${result.error.message}`);
1021
+ }
1022
+ else if (result.voidOutput === true) {
1023
+ sections.push('Script returned no result. Return a value from the script to send it to the model.');
1024
+ }
1025
+ else {
1026
+ const stripped = containsMediaContent(result.output) ? stripMediaContent(result.output, media) : result.output;
1027
+ // A top-level content-part array already has a useful text projection;
1028
+ // wrappers (Promise.all, object fields, etc.) retain their shape in JSON,
1029
+ // with media replaced by markers so base64 never leaks into text.
1030
+ const rendered = media.length > 0 && isContentPartArray(result.output)
1031
+ ? result.output
1032
+ .filter((part) => part.type === 'text' && typeof part.text === 'string')
1033
+ .map((part) => part.text)
1034
+ .join('\n')
1035
+ : typeof stripped === 'string'
1036
+ ? stripped
1037
+ : JSON.stringify(stripped);
1038
+ sections.push(`Result:\n${rendered}`);
1039
+ }
1040
+ const printed = output.join('\n').trim();
1041
+ if (printed && (!result.ok || includeConsole))
1042
+ sections.push(`Console trace (debug):\n${printed}`);
1043
+ const refused = calls.filter((call) => call.outcome === 'approval_required');
1044
+ const directlyRefused = refused.filter((call) => call.directlyCallable === true);
1045
+ const indirectlyRefused = refused.filter((call) => call.directlyCallable === false);
1046
+ if (directlyRefused.length > 0 || indirectlyRefused.length > 0) {
1047
+ const names = [...new Set([...directlyRefused, ...indirectlyRefused].map((call) => call.tool))].join(', ');
1048
+ sections.push(`Refused (needs user approval and could not be completed from inside this script): ${names}`);
1049
+ }
1050
+ const policyFailures = calls.filter((call) => call.outcome === 'policy_error' || call.outcome === 'interceptor_denied');
1051
+ if (policyFailures.length > 0) {
1052
+ const names = [...new Set(policyFailures.map((call) => call.tool))].join(', ');
1053
+ sections.push(`Unavailable (approval policy refused or failed; no user approval was requested): ${names}`);
1054
+ }
1055
+ const actionSection = renderActionReceipts(receipts);
1056
+ if (actionSection)
1057
+ sections.push(actionSection);
1058
+ const unknownPolicy = calls.filter((call) => call.outcome === 'unknown_policy');
1059
+ const directlyUnknown = unknownPolicy.filter((call) => call.directlyCallable === true);
1060
+ const indirectlyUnknown = unknownPolicy.filter((call) => call.directlyCallable === false);
1061
+ if (directlyUnknown.length > 0 || indirectlyUnknown.length > 0) {
1062
+ const names = [...new Set([...directlyUnknown, ...indirectlyUnknown].map((call) => call.tool))].join(', ');
1063
+ sections.push(`Unavailable (no registered approval policy): ${names}`);
1064
+ }
1065
+ sections.push(`[${summarizeCalls(calls)}]`);
1066
+ const clipped = clip(sections.join('\n\n'), actionSection
1067
+ ? {
1068
+ prefix: sections.filter((section) => section !== actionSection).join('\n\n'),
1069
+ full: actionSection,
1070
+ compact: renderActionReceipts(receipts, false),
1071
+ }
1072
+ : undefined);
1073
+ if (media.length > 0) {
1074
+ return clipped.then((text) => [{ type: 'text', text }, ...media]);
1075
+ }
1076
+ return clipped;
1077
+ }
1078
+ //# sourceMappingURL=run-code.js.map