@xopcai/xopc 0.0.86 → 0.0.88

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 (658) hide show
  1. package/dist/browser-ext/manifest.json +1 -1
  2. package/dist/extensions/feishu/src/adapters/cli-login.js +3 -3
  3. package/dist/extensions/feishu/src/adapters/cli-login.js.map +1 -1
  4. package/dist/extensions/feishu/src/outbound/media-load.js +1 -1
  5. package/dist/extensions/feishu/src/workflow-progress.js +1 -1
  6. package/dist/extensions/telegram/src/delivery-chat-id.d.ts +1 -1
  7. package/dist/extensions/telegram/src/delivery-chat-id.js +1 -1
  8. package/dist/extensions/telegram/src/delivery-chat-id.js.map +1 -1
  9. package/dist/extensions/telegram/src/plugin.js +1 -1
  10. package/dist/extensions/telegram/src/routing-integration.js +3 -2
  11. package/dist/extensions/telegram/src/routing-integration.js.map +1 -1
  12. package/dist/extensions/telegram/src/workflow-progress.js +1 -1
  13. package/dist/extensions/telegram/xopc.extension.json +1 -1
  14. package/dist/extensions/weixin/src/__tests__/workflow-progress.test.js +2 -2
  15. package/dist/extensions/weixin/src/__tests__/workflow-progress.test.js.map +1 -1
  16. package/dist/extensions/weixin/src/api/api.js +3 -3
  17. package/dist/extensions/weixin/src/api/api.js.map +1 -1
  18. package/dist/extensions/weixin/src/auth/accounts.js +12 -12
  19. package/dist/extensions/weixin/src/auth/accounts.js.map +1 -1
  20. package/dist/extensions/weixin/src/cdn/upload.js +1 -1
  21. package/dist/extensions/weixin/src/delivery-to.js +2 -2
  22. package/dist/extensions/weixin/src/delivery-to.js.map +1 -1
  23. package/dist/extensions/weixin/src/media/data-url.js +1 -1
  24. package/dist/extensions/weixin/src/messaging/debug-mode.js +5 -5
  25. package/dist/extensions/weixin/src/messaging/debug-mode.js.map +1 -1
  26. package/dist/extensions/weixin/src/messaging/inbound.js +11 -11
  27. package/dist/extensions/weixin/src/messaging/inbound.js.map +1 -1
  28. package/dist/extensions/weixin/src/messaging/process-message.js +1 -1
  29. package/dist/extensions/weixin/src/plugin.js +1 -1
  30. package/dist/extensions/weixin/src/storage/sync-buf.js +4 -4
  31. package/dist/extensions/weixin/src/storage/sync-buf.js.map +1 -1
  32. package/dist/extensions/weixin/src/workflow-progress.d.ts +1 -1
  33. package/dist/extensions/weixin/src/workflow-progress.js +1 -1
  34. package/dist/extensions/weixin/src/workflow-progress.js.map +1 -1
  35. package/dist/gateway/static/root/assets/agents-CRxETUZx.js +222 -0
  36. package/dist/gateway/static/root/assets/{apps-page-DrfytjOb.js → apps-page-wKWf3l57.js} +1 -1
  37. package/dist/gateway/static/root/assets/channels-settings-DDbqVNkx.js +1 -0
  38. package/dist/gateway/static/root/assets/{channels-status-swr-Bs5kMCMI.js → channels-status-swr-DIsl75Y3.js} +1 -1
  39. package/dist/gateway/static/root/assets/copy-SxMW6Xpc.js +1 -0
  40. package/dist/gateway/static/root/assets/{cron-api-BuVcZ5zR.js → cron-api-N9hvuRrn.js} +1 -1
  41. package/dist/gateway/static/root/assets/{cron-page-BMrloeFH.js → cron-page-tlNGNxhP.js} +1 -1
  42. package/dist/gateway/static/root/assets/{dist-CKU1OOTf.js → dist-CJwfHYvT.js} +1 -1
  43. package/dist/gateway/static/root/assets/{extension-debug-page-BdW_46sN.js → extension-debug-page-BVJohZoZ.js} +1 -1
  44. package/dist/gateway/static/root/assets/{extension-page-DW47KI82.js → extension-page-BT2tmElC.js} +1 -1
  45. package/dist/gateway/static/root/assets/extension-settings-page-BSS47c2j.js +1 -0
  46. package/dist/gateway/static/root/assets/{fetch-B2MYHbWg.js → fetch-BaFNUtkE.js} +1 -1
  47. package/dist/gateway/static/root/assets/{field-primitives-DPG-oJmx.js → field-primitives-QwYEq6Hz.js} +1 -1
  48. package/dist/gateway/static/root/assets/{heartbeat-config-api-C8dNts9i.js → heartbeat-config-api-BVSidEDJ.js} +1 -1
  49. package/dist/gateway/static/root/assets/index-CqZzHNEg.css +1 -0
  50. package/dist/gateway/static/root/assets/{index-BmVYculr.js → index-qNrVJp-y.js} +97 -95
  51. package/dist/gateway/static/root/assets/{logs-page-sTsVWz0X.js → logs-page-DDonPVLn.js} +1 -1
  52. package/dist/gateway/static/root/assets/sessions-page-DKt-Wmib.js +1 -0
  53. package/dist/gateway/static/root/assets/{settings-form-section-DuvRQW--.js → settings-form-section-B8N3A3Zo.js} +1 -1
  54. package/dist/gateway/static/root/assets/settings-page-DcJjvvw4.js +3 -0
  55. package/dist/gateway/static/root/assets/{share-preview-page-BtG2kLDh.js → share-preview-page-Q7KqkO-u.js} +1 -1
  56. package/dist/gateway/static/root/assets/skills-page-DuJ4BTO3.js +2 -0
  57. package/dist/gateway/static/root/assets/{theme-store-DryYl3qD.js → theme-store-BbRc5ugR.js} +1 -1
  58. package/dist/gateway/static/root/assets/url-D6jvVYIA.js +7 -0
  59. package/dist/gateway/static/root/assets/{utils-BY7bU1DT.js → utils-CxDGduqK.js} +1 -1
  60. package/dist/gateway/static/root/assets/voice-api-key-field-CTyHz7L_.js +1 -0
  61. package/dist/gateway/static/root/assets/workflows-page-GacJ41Fv.js +27 -0
  62. package/dist/gateway/static/root/index.html +6 -5
  63. package/dist/package.js +1 -1
  64. package/dist/src/agent/agent-manager.js +7 -7
  65. package/dist/src/agent/agent-scope.d.ts +4 -0
  66. package/dist/src/agent/agent-scope.js +53 -10
  67. package/dist/src/agent/agent-scope.js.map +1 -1
  68. package/dist/src/agent/bootstrap/filter-bootstrap-files.js +2 -1
  69. package/dist/src/agent/bootstrap/filter-bootstrap-files.js.map +1 -1
  70. package/dist/src/agent/bootstrap/load-bootstrap-files.js +1 -1
  71. package/dist/src/agent/child-agent-factory.d.ts +15 -0
  72. package/dist/src/agent/child-agent-factory.js +35 -2
  73. package/dist/src/agent/child-agent-factory.js.map +1 -1
  74. package/dist/src/agent/client-error-format.d.ts +20 -0
  75. package/dist/src/agent/client-error-format.js +97 -0
  76. package/dist/src/agent/client-error-format.js.map +1 -0
  77. package/dist/src/agent/context/workspace-seed.js +2 -2
  78. package/dist/src/agent/embedded/run-turn.js +23 -4
  79. package/dist/src/agent/embedded/run-turn.js.map +1 -1
  80. package/dist/src/agent/embedded/session-tool-result-guard.js +2 -1
  81. package/dist/src/agent/embedded/session-tool-result-guard.js.map +1 -1
  82. package/dist/src/agent/embedded/tool-result-truncation.js +2 -1
  83. package/dist/src/agent/embedded/tool-result-truncation.js.map +1 -1
  84. package/dist/src/agent/fallback/candidates.js +2 -2
  85. package/dist/src/agent/fallback/candidates.js.map +1 -1
  86. package/dist/src/agent/goals/goal-locale.d.ts +1 -1
  87. package/dist/src/agent/goals/goal-run-store.js +4 -4
  88. package/dist/src/agent/goals/persistent-goal-apis.d.ts +0 -2
  89. package/dist/src/agent/goals/persistent-goal-service.js +1 -2
  90. package/dist/src/agent/goals/persistent-goal-service.js.map +1 -1
  91. package/dist/src/agent/goals/post-turn.js +2 -2
  92. package/dist/src/agent/image/generation/normalization.js +2 -12
  93. package/dist/src/agent/image/generation/normalization.js.map +1 -1
  94. package/dist/src/agent/image/generation/provider-registry.d.ts +4 -8
  95. package/dist/src/agent/image/generation/provider-registry.js.map +1 -1
  96. package/dist/src/agent/image/generation/runtime.d.ts +2 -2
  97. package/dist/src/agent/image/generation/runtime.js.map +1 -1
  98. package/dist/src/agent/image/generation/types.d.ts +0 -18
  99. package/dist/src/agent/image/image-helpers.js +6 -1
  100. package/dist/src/agent/image/image-helpers.js.map +1 -1
  101. package/dist/src/agent/image/index.d.ts +1 -1
  102. package/dist/src/agent/image/load-image-media.js +2 -2
  103. package/dist/src/agent/inbound/inbound-loop.d.ts +5 -0
  104. package/dist/src/agent/inbound/inbound-loop.js +41 -10
  105. package/dist/src/agent/inbound/inbound-loop.js.map +1 -1
  106. package/dist/src/agent/inbound/turn-dispatcher.d.ts +4 -0
  107. package/dist/src/agent/inbound/turn-dispatcher.js +7 -5
  108. package/dist/src/agent/inbound/turn-dispatcher.js.map +1 -1
  109. package/dist/src/agent/ipc/bus.js +1 -1
  110. package/dist/src/agent/ipc/inbox.js +2 -2
  111. package/dist/src/agent/ipc/socket.js +1 -1
  112. package/dist/src/agent/mcp/bundle-mcp-materialize.js +2 -1
  113. package/dist/src/agent/mcp/bundle-mcp-materialize.js.map +1 -1
  114. package/dist/src/agent/mcp/bundle-mcp-names.js +2 -1
  115. package/dist/src/agent/mcp/bundle-mcp-names.js.map +1 -1
  116. package/dist/src/agent/mcp/bundle-mcp-runtime.js +2 -1
  117. package/dist/src/agent/mcp/bundle-mcp-runtime.js.map +1 -1
  118. package/dist/src/agent/mcp/mcp-transport-config.js +2 -1
  119. package/dist/src/agent/mcp/mcp-transport-config.js.map +1 -1
  120. package/dist/src/agent/mcp/mcp-transport.js +2 -1
  121. package/dist/src/agent/mcp/mcp-transport.js.map +1 -1
  122. package/dist/src/agent/media-generation/runtime-shared.js +2 -9
  123. package/dist/src/agent/media-generation/runtime-shared.js.map +1 -1
  124. package/dist/src/agent/memory/builtin-memory-store.js +1 -1
  125. package/dist/src/agent/memory/dreaming/deep-promotion.js +1 -1
  126. package/dist/src/agent/memory/dreaming/events.js +1 -1
  127. package/dist/src/agent/memory/dreaming/last-run.js +1 -1
  128. package/dist/src/agent/memory/dreaming/light-sweep.js +1 -1
  129. package/dist/src/agent/memory/dreaming/preview.js +1 -1
  130. package/dist/src/agent/memory/dreaming/rem-patterns.js +1 -1
  131. package/dist/src/agent/memory/dreaming/short-term-store.js +1 -1
  132. package/dist/src/agent/memory/dreaming/utils.js +1 -1
  133. package/dist/src/agent/memory/plugin-discovery.js +1 -1
  134. package/dist/src/agent/messaging/command-handler.d.ts +6 -0
  135. package/dist/src/agent/messaging/command-handler.js +5 -0
  136. package/dist/src/agent/messaging/command-handler.js.map +1 -1
  137. package/dist/src/agent/models/manager.js +1 -1
  138. package/dist/src/agent/orchestration/llm-turn-retry.d.ts +2 -0
  139. package/dist/src/agent/orchestration/llm-turn-retry.js +9 -1
  140. package/dist/src/agent/orchestration/llm-turn-retry.js.map +1 -1
  141. package/dist/src/agent/prompt/safety.d.ts +0 -7
  142. package/dist/src/agent/prompt/safety.js +1 -20
  143. package/dist/src/agent/prompt/safety.js.map +1 -1
  144. package/dist/src/agent/prompt/service-prompt-builder.js +2 -2
  145. package/dist/src/agent/reply/post-compaction-context.js +1 -1
  146. package/dist/src/agent/reply/workspace-boundary-read.js +1 -1
  147. package/dist/src/agent/sandbox/path-policy.js +2 -2
  148. package/dist/src/agent/service/build-direct-message-content.js +2 -2
  149. package/dist/src/agent/service/build-direct-message-content.js.map +1 -1
  150. package/dist/src/agent/service/direct-turn-helpers.d.ts +3 -1
  151. package/dist/src/agent/service/direct-turn-helpers.js +6 -1
  152. package/dist/src/agent/service/direct-turn-helpers.js.map +1 -1
  153. package/dist/src/agent/service/process-direct-one-shot.d.ts +4 -0
  154. package/dist/src/agent/service/process-direct-one-shot.js +15 -2
  155. package/dist/src/agent/service/process-direct-one-shot.js.map +1 -1
  156. package/dist/src/agent/service/process-direct-streaming.d.ts +4 -0
  157. package/dist/src/agent/service/process-direct-streaming.js +53 -7
  158. package/dist/src/agent/service/process-direct-streaming.js.map +1 -1
  159. package/dist/src/agent/service/webchat-tts.d.ts +1 -2
  160. package/dist/src/agent/service/webchat-tts.js +2 -2
  161. package/dist/src/agent/service/webchat-tts.js.map +1 -1
  162. package/dist/src/agent/service.d.ts +8 -0
  163. package/dist/src/agent/service.js +25 -5
  164. package/dist/src/agent/service.js.map +1 -1
  165. package/dist/src/agent/session/session-inspector.js +1 -1
  166. package/dist/src/agent/skills/config.js +1 -1
  167. package/dist/src/agent/skills/hub-hash.js +2 -2
  168. package/dist/src/agent/skills/hub-lock.js +1 -1
  169. package/dist/src/agent/skills/hub-pull.js +2 -2
  170. package/dist/src/agent/skills/index.js +1 -1
  171. package/dist/src/agent/skills/managed-store.js +1 -1
  172. package/dist/src/agent/skills/scanner.js +1 -1
  173. package/dist/src/agent/skills/skill-manage-ops.js +1 -1
  174. package/dist/src/agent/skills/skill-manager.js +1 -1
  175. package/dist/src/agent/tools/create-share-tool.js +27 -20
  176. package/dist/src/agent/tools/create-share-tool.js.map +1 -1
  177. package/dist/src/agent/tools/dreaming-tool.js +1 -1
  178. package/dist/src/agent/tools/factory.js +2 -2
  179. package/dist/src/agent/tools/image-generate-tool.js +1 -1
  180. package/dist/src/agent/tools/index.d.ts +0 -1
  181. package/dist/src/agent/tools/index.js +4 -5
  182. package/dist/src/agent/tools/send-media.js +1 -1
  183. package/dist/src/agent/tools/shell.js +0 -13
  184. package/dist/src/agent/tools/shell.js.map +1 -1
  185. package/dist/src/agent/tools/skill-manage-tool.js +1 -1
  186. package/dist/src/agent/tools/workflow-tool.js +70 -16
  187. package/dist/src/agent/tools/workflow-tool.js.map +1 -1
  188. package/dist/src/agent/tools/write.js +1 -1
  189. package/dist/src/agent/workflow/agent-progress.d.ts +5 -0
  190. package/dist/src/agent/workflow/agent-progress.js +65 -0
  191. package/dist/src/agent/workflow/agent-progress.js.map +1 -0
  192. package/dist/src/agent/workflow/builtins/audit-repo.d.ts +1 -1
  193. package/dist/src/agent/workflow/builtins/audit-repo.js +14 -0
  194. package/dist/src/agent/workflow/builtins/audit-repo.js.map +1 -1
  195. package/dist/src/agent/workflow/builtins/debug-incident.d.ts +1 -1
  196. package/dist/src/agent/workflow/builtins/debug-incident.js +14 -0
  197. package/dist/src/agent/workflow/builtins/debug-incident.js.map +1 -1
  198. package/dist/src/agent/workflow/builtins/implementation-plan.d.ts +12 -0
  199. package/dist/src/agent/workflow/builtins/implementation-plan.js +175 -0
  200. package/dist/src/agent/workflow/builtins/implementation-plan.js.map +1 -0
  201. package/dist/src/agent/workflow/builtins/index.d.ts +3 -1
  202. package/dist/src/agent/workflow/builtins/index.js +11 -1
  203. package/dist/src/agent/workflow/builtins/index.js.map +1 -1
  204. package/dist/src/agent/workflow/builtins/multi-perspective-review.d.ts +1 -1
  205. package/dist/src/agent/workflow/builtins/multi-perspective-review.js +14 -0
  206. package/dist/src/agent/workflow/builtins/multi-perspective-review.js.map +1 -1
  207. package/dist/src/agent/workflow/builtins/pr-review.d.ts +1 -1
  208. package/dist/src/agent/workflow/builtins/pr-review.js +14 -0
  209. package/dist/src/agent/workflow/builtins/pr-review.js.map +1 -1
  210. package/dist/src/agent/workflow/builtins/release-check.d.ts +11 -0
  211. package/dist/src/agent/workflow/builtins/release-check.js +165 -0
  212. package/dist/src/agent/workflow/builtins/release-check.js.map +1 -0
  213. package/dist/src/agent/workflow/builtins/research.d.ts +1 -1
  214. package/dist/src/agent/workflow/builtins/research.js +14 -0
  215. package/dist/src/agent/workflow/builtins/research.js.map +1 -1
  216. package/dist/src/agent/workflow/catalog.js +1 -1
  217. package/dist/src/agent/workflow/channel-capability.d.ts +3 -3
  218. package/dist/src/agent/workflow/index.d.ts +2 -1
  219. package/dist/src/agent/workflow/index.js +3 -2
  220. package/dist/src/agent/workflow/lint.d.ts +38 -0
  221. package/dist/src/agent/workflow/lint.js +74 -0
  222. package/dist/src/agent/workflow/lint.js.map +1 -0
  223. package/dist/src/agent/workflow/meta-locale.d.ts +12 -0
  224. package/dist/src/agent/workflow/meta-locale.js +62 -0
  225. package/dist/src/agent/workflow/meta-locale.js.map +1 -0
  226. package/dist/src/agent/workflow/parser.js +7 -1
  227. package/dist/src/agent/workflow/parser.js.map +1 -1
  228. package/dist/src/agent/workflow/runtime.d.ts +4 -1
  229. package/dist/src/agent/workflow/runtime.js +88 -8
  230. package/dist/src/agent/workflow/runtime.js.map +1 -1
  231. package/dist/src/agent/workflow/snapshot.js +2 -12
  232. package/dist/src/agent/workflow/snapshot.js.map +1 -1
  233. package/dist/src/agent/workflow/step-labels.d.ts +8 -0
  234. package/dist/src/agent/workflow/step-labels.js +48 -0
  235. package/dist/src/agent/workflow/step-labels.js.map +1 -0
  236. package/dist/src/agent/workflow/subagent-runner.js +46 -1
  237. package/dist/src/agent/workflow/subagent-runner.js.map +1 -1
  238. package/dist/src/agent/workflow/types.d.ts +76 -1
  239. package/dist/src/auth/credentials.d.ts +5 -0
  240. package/dist/src/auth/credentials.js +12 -3
  241. package/dist/src/auth/credentials.js.map +1 -1
  242. package/dist/src/auth/profiles/store.js +1 -1
  243. package/dist/src/auth/sync-provider-auth.js +1 -1
  244. package/dist/src/browser/cache-dir-policy.js +1 -1
  245. package/dist/src/browser/cdp-local-launcher.js +2 -2
  246. package/dist/src/browser/index.js +4 -4
  247. package/dist/src/browser/manager.d.ts +1 -3
  248. package/dist/src/browser/manager.js +0 -6
  249. package/dist/src/browser/manager.js.map +1 -1
  250. package/dist/src/browser/providers/browser-ext-install.d.ts +4 -4
  251. package/dist/src/browser/providers/browser-ext-install.js +41 -88
  252. package/dist/src/browser/providers/browser-ext-install.js.map +1 -1
  253. package/dist/src/browser/providers/cloakbrowser.d.ts +0 -5
  254. package/dist/src/browser/providers/cloakbrowser.js +6 -59
  255. package/dist/src/browser/providers/cloakbrowser.js.map +1 -1
  256. package/dist/src/browser/providers/playwright-doctor.js +1 -1
  257. package/dist/src/browser/stealth.js +1 -1
  258. package/dist/src/channels/attachments/inbound-persist.js +1 -1
  259. package/dist/src/channels/attachments/outbound-tts-persist.js +1 -1
  260. package/dist/src/channels/attachments/voice-stt-webchat.js +10 -8
  261. package/dist/src/channels/attachments/voice-stt-webchat.js.map +1 -1
  262. package/dist/src/channels/outbound/persist-store.js +1 -1
  263. package/dist/src/channels/pairing/allow-from-file.js +9 -9
  264. package/dist/src/channels/pairing/allow-from-file.js.map +1 -1
  265. package/dist/src/channels/pairing/pairing-store.js +7 -7
  266. package/dist/src/channels/pairing/pairing-store.js.map +1 -1
  267. package/dist/src/chat-commands/builtins/config.js +2 -2
  268. package/dist/src/chat-commands/builtins/session.js +1 -1
  269. package/dist/src/chat-commands/builtins/session.js.map +1 -1
  270. package/dist/src/chat-commands/builtins/tts.js +2 -2
  271. package/dist/src/chat-commands/builtins/tts.js.map +1 -1
  272. package/dist/src/chat-commands/context.d.ts +3 -0
  273. package/dist/src/chat-commands/context.js +22 -4
  274. package/dist/src/chat-commands/context.js.map +1 -1
  275. package/dist/src/chat-commands/session-key.d.ts +4 -37
  276. package/dist/src/chat-commands/session-key.js +49 -85
  277. package/dist/src/chat-commands/session-key.js.map +1 -1
  278. package/dist/src/chat-commands/types.d.ts +2 -0
  279. package/dist/src/cli/commands/agent/interactive.js +2 -2
  280. package/dist/src/cli/commands/agent/interactive.js.map +1 -1
  281. package/dist/src/cli/commands/agent/sessions.js +2 -2
  282. package/dist/src/cli/commands/agent/sessions.js.map +1 -1
  283. package/dist/src/cli/commands/agent.js +4 -5
  284. package/dist/src/cli/commands/agent.js.map +1 -1
  285. package/dist/src/cli/commands/channels.js +1 -5
  286. package/dist/src/cli/commands/channels.js.map +1 -1
  287. package/dist/src/cli/commands/config.js +1 -1
  288. package/dist/src/cli/commands/doctor/checks/config-health.js +1 -1
  289. package/dist/src/cli/commands/doctor/checks/provider-auth.js +1 -1
  290. package/dist/src/cli/commands/doctor/checks/session-integrity.js +1 -1
  291. package/dist/src/cli/commands/doctor/checks/state-integrity.js +1 -1
  292. package/dist/src/cli/commands/doctor/checks/workspace-status.js +1 -1
  293. package/dist/src/cli/commands/extension-dev.js +1 -1
  294. package/dist/src/cli/commands/extension-marketplace.js +1 -1
  295. package/dist/src/cli/commands/extension-pack.js +1 -1
  296. package/dist/src/cli/commands/gateway/lifecycle-core.js +1 -1
  297. package/dist/src/cli/commands/gateway/lifecycle-core.js.map +1 -1
  298. package/dist/src/cli/commands/gateway/logs.d.ts +9 -0
  299. package/dist/src/cli/commands/gateway/logs.js +50 -17
  300. package/dist/src/cli/commands/gateway/logs.js.map +1 -1
  301. package/dist/src/cli/commands/image.js +23 -22
  302. package/dist/src/cli/commands/image.js.map +1 -1
  303. package/dist/src/cli/commands/init.js +4 -4
  304. package/dist/src/cli/commands/onboard.js +1 -1
  305. package/dist/src/cli/commands/session/utils.js +2 -2
  306. package/dist/src/cli/commands/session/utils.js.map +1 -1
  307. package/dist/src/cli/commands/update.js +26 -46
  308. package/dist/src/cli/commands/update.js.map +1 -1
  309. package/dist/src/cli/utils/init-workspace-core.js +2 -2
  310. package/dist/src/cli/utils/session.d.ts +0 -5
  311. package/dist/src/cli/utils/session.js +1 -6
  312. package/dist/src/cli/utils/session.js.map +1 -1
  313. package/dist/src/commands/agents.config.js +1 -1
  314. package/dist/src/commands/agents.config.js.map +1 -1
  315. package/dist/src/config/agent-profile.js +6 -28
  316. package/dist/src/config/agent-profile.js.map +1 -1
  317. package/dist/src/config/agent-typed-models.d.ts +18 -0
  318. package/dist/src/config/agent-typed-models.js +53 -0
  319. package/dist/src/config/agent-typed-models.js.map +1 -0
  320. package/dist/src/config/gateway-bind.js +1 -1
  321. package/dist/src/config/index.js +6 -6
  322. package/dist/src/config/loader.js +2 -2
  323. package/dist/src/config/model-input.js +2 -5
  324. package/dist/src/config/model-input.js.map +1 -1
  325. package/dist/src/config/models-json.js +2 -2
  326. package/dist/src/config/paths-state.js +1 -1
  327. package/dist/src/config/profile.js +2 -2
  328. package/dist/src/config/schema.d.ts +253 -217
  329. package/dist/src/config/schema.js +91 -40
  330. package/dist/src/config/schema.js.map +1 -1
  331. package/dist/src/config/voice.d.ts +3 -28
  332. package/dist/src/config/voice.js +27 -261
  333. package/dist/src/config/voice.js.map +1 -1
  334. package/dist/src/config/workspace-path-helpers.d.ts +1 -2
  335. package/dist/src/config/workspace-path-helpers.js.map +1 -1
  336. package/dist/src/config/workspace-path.js +1 -1
  337. package/dist/src/cron/executor.js +2 -2
  338. package/dist/src/cron/persistence.js +1 -1
  339. package/dist/src/cron/run-log-store.js +1 -1
  340. package/dist/src/daemon/constants.js +1 -1
  341. package/dist/src/daemon/install-plan.js +27 -3
  342. package/dist/src/daemon/install-plan.js.map +1 -1
  343. package/dist/src/daemon/launchd.d.ts +8 -0
  344. package/dist/src/daemon/launchd.js +7 -14
  345. package/dist/src/daemon/launchd.js.map +1 -1
  346. package/dist/src/daemon/schtasks.d.ts +25 -0
  347. package/dist/src/daemon/schtasks.js +168 -48
  348. package/dist/src/daemon/schtasks.js.map +1 -1
  349. package/dist/src/daemon/service.js +5 -4
  350. package/dist/src/daemon/service.js.map +1 -1
  351. package/dist/src/daemon/systemd.d.ts +6 -0
  352. package/dist/src/daemon/systemd.js +20 -5
  353. package/dist/src/daemon/systemd.js.map +1 -1
  354. package/dist/src/extensions/activation-context.js +0 -1
  355. package/dist/src/extensions/activation-context.js.map +1 -1
  356. package/dist/src/extensions/bundle-mcp.js +1 -1
  357. package/dist/src/extensions/discover-extensions.js +1 -1
  358. package/dist/src/extensions/health.js +1 -1
  359. package/dist/src/extensions/loader.js +1 -1
  360. package/dist/src/extensions/lockfile.js +2 -2
  361. package/dist/src/extensions/normalize-manifest.js +0 -1
  362. package/dist/src/extensions/normalize-manifest.js.map +1 -1
  363. package/dist/src/extensions/types/manifest.d.ts +0 -2
  364. package/dist/src/gateway/agent-builtin-tools.d.ts +1 -1
  365. package/dist/src/gateway/agent-builtin-tools.js +1 -0
  366. package/dist/src/gateway/agent-builtin-tools.js.map +1 -1
  367. package/dist/src/gateway/agents-admin.d.ts +9 -0
  368. package/dist/src/gateway/agents-admin.js +28 -4
  369. package/dist/src/gateway/agents-admin.js.map +1 -1
  370. package/dist/src/gateway/config-tools-web.js +3 -2
  371. package/dist/src/gateway/config-tools-web.js.map +1 -1
  372. package/dist/src/gateway/file-path-classifier.js +2 -2
  373. package/dist/src/gateway/heartbeat/service.js +2 -2
  374. package/dist/src/gateway/heartbeat/service.js.map +1 -1
  375. package/dist/src/gateway/hono/app.js +1 -1
  376. package/dist/src/gateway/hono/lib/agent-model.d.ts +25 -10
  377. package/dist/src/gateway/hono/lib/agent-model.js +60 -36
  378. package/dist/src/gateway/hono/lib/agent-model.js.map +1 -1
  379. package/dist/src/gateway/hono/lib/config-payload.js +29 -6
  380. package/dist/src/gateway/hono/lib/config-payload.js.map +1 -1
  381. package/dist/src/gateway/hono/lib/extension-store.js +2 -2
  382. package/dist/src/gateway/hono/lib/mask-secret-length.d.ts +6 -0
  383. package/dist/src/gateway/hono/lib/mask-secret-length.js +16 -0
  384. package/dist/src/gateway/hono/lib/mask-secret-length.js.map +1 -0
  385. package/dist/src/gateway/hono/lib/safe-providers-config.d.ts +1 -1
  386. package/dist/src/gateway/hono/lib/safe-providers-config.js +2 -1
  387. package/dist/src/gateway/hono/lib/safe-providers-config.js.map +1 -1
  388. package/dist/src/gateway/hono/lib/safe-voice-config.js +16 -54
  389. package/dist/src/gateway/hono/lib/safe-voice-config.js.map +1 -1
  390. package/dist/src/gateway/hono/lib/static-ui.js +2 -2
  391. package/dist/src/gateway/hono/oauth.js +1 -1
  392. package/dist/src/gateway/hono/routes/agents.js +2 -2
  393. package/dist/src/gateway/hono/routes/auth-registry-extensions.js +1 -1
  394. package/dist/src/gateway/hono/routes/config-patch/agents.js +25 -7
  395. package/dist/src/gateway/hono/routes/config-patch/agents.js.map +1 -1
  396. package/dist/src/gateway/hono/routes/config-patch/channels.js +0 -11
  397. package/dist/src/gateway/hono/routes/config-patch/channels.js.map +1 -1
  398. package/dist/src/gateway/hono/routes/config-patch/gateway.js +3 -2
  399. package/dist/src/gateway/hono/routes/config-patch/gateway.js.map +1 -1
  400. package/dist/src/gateway/hono/routes/config-patch/misc.js +8 -3
  401. package/dist/src/gateway/hono/routes/config-patch/misc.js.map +1 -1
  402. package/dist/src/gateway/hono/routes/config.js +59 -0
  403. package/dist/src/gateway/hono/routes/config.js.map +1 -1
  404. package/dist/src/gateway/hono/routes/dreaming.js +1 -1
  405. package/dist/src/gateway/hono/routes/goals.js +1 -1
  406. package/dist/src/gateway/hono/routes/goals.js.map +1 -1
  407. package/dist/src/gateway/hono/routes/host-fs.js +2 -2
  408. package/dist/src/gateway/hono/routes/lazy-bundles.js +8 -0
  409. package/dist/src/gateway/hono/routes/lazy-bundles.js.map +1 -1
  410. package/dist/src/gateway/hono/routes/models.js +75 -12
  411. package/dist/src/gateway/hono/routes/models.js.map +1 -1
  412. package/dist/src/gateway/hono/routes/sessions.js +28 -7
  413. package/dist/src/gateway/hono/routes/sessions.js.map +1 -1
  414. package/dist/src/gateway/hono/routes/shares.js +15 -13
  415. package/dist/src/gateway/hono/routes/shares.js.map +1 -1
  416. package/dist/src/gateway/hono/routes/tunnel.js +1 -1
  417. package/dist/src/gateway/hono/routes/update.js +4 -2
  418. package/dist/src/gateway/hono/routes/update.js.map +1 -1
  419. package/dist/src/gateway/hono/routes/voice.js +75 -0
  420. package/dist/src/gateway/hono/routes/voice.js.map +1 -1
  421. package/dist/src/gateway/hono/routes/workflows.d.ts +3 -0
  422. package/dist/src/gateway/hono/routes/workflows.js +347 -0
  423. package/dist/src/gateway/hono/routes/workflows.js.map +1 -0
  424. package/dist/src/gateway/hono/routes/workspace.js +4 -4
  425. package/dist/src/gateway/hono/sse.js +16 -33
  426. package/dist/src/gateway/hono/sse.js.map +1 -1
  427. package/dist/src/gateway/lock.js +11 -11
  428. package/dist/src/gateway/lock.js.map +1 -1
  429. package/dist/src/gateway/ports.js +6 -6
  430. package/dist/src/gateway/ports.js.map +1 -1
  431. package/dist/src/gateway/resolve-webchat-session-key.d.ts +19 -0
  432. package/dist/src/gateway/resolve-webchat-session-key.js +46 -0
  433. package/dist/src/gateway/resolve-webchat-session-key.js.map +1 -0
  434. package/dist/src/gateway/service/agent-runner.js +2 -2
  435. package/dist/src/gateway/service/marketplace-service.js +2 -2
  436. package/dist/src/gateway/service/run-gateway-agent.js +9 -11
  437. package/dist/src/gateway/service/run-gateway-agent.js.map +1 -1
  438. package/dist/src/gateway/service/sessions-api.d.ts +3 -0
  439. package/dist/src/gateway/service/sessions-api.js +8 -0
  440. package/dist/src/gateway/service/sessions-api.js.map +1 -1
  441. package/dist/src/gateway/service.d.ts +3 -2
  442. package/dist/src/gateway/service.js +9 -8
  443. package/dist/src/gateway/service.js.map +1 -1
  444. package/dist/src/gateway/session-reset-service.d.ts +20 -0
  445. package/dist/src/gateway/session-reset-service.js +54 -0
  446. package/dist/src/gateway/session-reset-service.js.map +1 -0
  447. package/dist/src/gateway/startup-readiness.d.ts +1 -1
  448. package/dist/src/gateway/startup-readiness.js +1 -0
  449. package/dist/src/gateway/startup-readiness.js.map +1 -1
  450. package/dist/src/gateway/workspace-fs-file-list.js +1 -1
  451. package/dist/src/heartbeat/index.js +1 -1
  452. package/dist/src/infra/gateway-processes.js +2 -2
  453. package/dist/src/infra/gateway-processes.js.map +1 -1
  454. package/dist/src/infra/restart.js +2 -2
  455. package/dist/src/infra/run-command.d.ts +16 -0
  456. package/dist/src/infra/run-command.js +67 -0
  457. package/dist/src/infra/run-command.js.map +1 -0
  458. package/dist/src/infra/update-check.js +1 -1
  459. package/dist/src/infra/update-global.d.ts +45 -0
  460. package/dist/src/infra/update-global.js +224 -0
  461. package/dist/src/infra/update-global.js.map +1 -0
  462. package/dist/src/infra/update-lock.js +3 -3
  463. package/dist/src/infra/update-runner.js +1 -1
  464. package/dist/src/infra/update-startup.js +2 -2
  465. package/dist/src/infra/write-file-atomic.js +2 -2
  466. package/dist/src/mcp/channel-shared.js +2 -1
  467. package/dist/src/mcp/channel-shared.js.map +1 -1
  468. package/dist/src/providers/auth-runtime/auth-profile-store.js +2 -2
  469. package/dist/src/providers/auth-runtime/auth-profile-store.js.map +1 -1
  470. package/dist/src/providers/auth-runtime/resolve-auth.js +1 -12
  471. package/dist/src/providers/auth-runtime/resolve-auth.js.map +1 -1
  472. package/dist/src/providers/auth-runtime/types.d.ts +6 -12
  473. package/dist/src/providers/index.js +2 -2
  474. package/dist/src/providers/model-registry.js +1 -1
  475. package/dist/src/routing/agent-session-key.d.ts +58 -0
  476. package/dist/src/routing/agent-session-key.js +164 -0
  477. package/dist/src/routing/agent-session-key.js.map +1 -0
  478. package/dist/src/routing/index.d.ts +1 -1
  479. package/dist/src/routing/index.js +4 -2
  480. package/dist/src/routing/index.js.map +1 -1
  481. package/dist/src/routing/resolve-route.d.ts +15 -0
  482. package/dist/src/routing/resolve-route.js +41 -20
  483. package/dist/src/routing/resolve-route.js.map +1 -1
  484. package/dist/src/routing/resolve-tui-session-key.d.ts +25 -0
  485. package/dist/src/routing/resolve-tui-session-key.js +54 -0
  486. package/dist/src/routing/resolve-tui-session-key.js.map +1 -0
  487. package/dist/src/routing/session-key-utils.d.ts +24 -0
  488. package/dist/src/routing/session-key-utils.js +92 -0
  489. package/dist/src/routing/session-key-utils.js.map +1 -0
  490. package/dist/src/routing/session-key.d.ts +19 -49
  491. package/dist/src/routing/session-key.js +143 -116
  492. package/dist/src/routing/session-key.js.map +1 -1
  493. package/dist/src/session/config-store.js +2 -2
  494. package/dist/src/session/index.d.ts +6 -0
  495. package/dist/src/session/index.js +7 -1
  496. package/dist/src/session/init-session-turn.d.ts +30 -0
  497. package/dist/src/session/init-session-turn.js +102 -0
  498. package/dist/src/session/init-session-turn.js.map +1 -0
  499. package/dist/src/session/lifecycle-timestamps.d.ts +8 -0
  500. package/dist/src/session/lifecycle-timestamps.js +16 -0
  501. package/dist/src/session/lifecycle-timestamps.js.map +1 -0
  502. package/dist/src/session/manager.d.ts +7 -1
  503. package/dist/src/session/manager.js +8 -1
  504. package/dist/src/session/manager.js.map +1 -1
  505. package/dist/src/session/parity/jsonl-transcript-io.js +2 -2
  506. package/dist/src/session/parity/sessions-json-file.js +1 -1
  507. package/dist/src/session/parity/transcript-file-lock.js +2 -2
  508. package/dist/src/session/parity/transcript-paths.js +2 -2
  509. package/dist/src/session/parity/transcript-paths.js.map +1 -1
  510. package/dist/src/session/parity/xopc-session-disk-entry.d.ts +6 -0
  511. package/dist/src/session/reset-policy.d.ts +32 -0
  512. package/dist/src/session/reset-policy.js +65 -0
  513. package/dist/src/session/reset-policy.js.map +1 -0
  514. package/dist/src/session/reset-triggers.d.ts +20 -0
  515. package/dist/src/session/reset-triggers.js +63 -0
  516. package/dist/src/session/reset-triggers.js.map +1 -0
  517. package/dist/src/session/reset-type.d.ts +12 -0
  518. package/dist/src/session/reset-type.js +25 -0
  519. package/dist/src/session/reset-type.js.map +1 -0
  520. package/dist/src/session/resolve-session.d.ts +30 -0
  521. package/dist/src/session/resolve-session.js +93 -0
  522. package/dist/src/session/resolve-session.js.map +1 -0
  523. package/dist/src/session/search-index-cache.js +1 -1
  524. package/dist/src/session/search-index.js +1 -1
  525. package/dist/src/session/session-title.js +3 -2
  526. package/dist/src/session/session-title.js.map +1 -1
  527. package/dist/src/session/store.d.ts +11 -4
  528. package/dist/src/session/store.js +62 -11
  529. package/dist/src/session/store.js.map +1 -1
  530. package/dist/src/session/transcript-events.js +2 -1
  531. package/dist/src/session/transcript-events.js.map +1 -1
  532. package/dist/src/share/share-auto.js +2 -2
  533. package/dist/src/share/share-store.js +3 -3
  534. package/dist/src/share/share-thumbnail.js +2 -2
  535. package/dist/src/share/share-url.d.ts +33 -0
  536. package/dist/src/share/share-url.js +56 -14
  537. package/dist/src/share/share-url.js.map +1 -1
  538. package/dist/src/share/share-zip.js +1 -1
  539. package/dist/src/share/site-share-store.js +3 -3
  540. package/dist/src/share/site-static-serve.js +1 -1
  541. package/dist/src/tui/backends/embedded-backend.js +4 -9
  542. package/dist/src/tui/backends/embedded-backend.js.map +1 -1
  543. package/dist/src/tui/backends/gateway-sse-backend.js +1 -1
  544. package/dist/src/tui/backends/gateway-sse-backend.js.map +1 -1
  545. package/dist/src/tui/clipboard-image.js +3 -3
  546. package/dist/src/tui/components/chat-log.js +3 -3
  547. package/dist/src/tui/components/chat-log.js.map +1 -1
  548. package/dist/src/tui/theme-manager.js +1 -1
  549. package/dist/src/tui/theme.d.ts +0 -2
  550. package/dist/src/tui/theme.js +1 -3
  551. package/dist/src/tui/theme.js.map +1 -1
  552. package/dist/src/tui/tui-agent-events.js +2 -1
  553. package/dist/src/tui/tui-agent-events.js.map +1 -1
  554. package/dist/src/tui/tui-commands.d.ts +3 -0
  555. package/dist/src/tui/tui-commands.js +45 -10
  556. package/dist/src/tui/tui-commands.js.map +1 -1
  557. package/dist/src/tui/tui-keybindings-file.js +2 -22
  558. package/dist/src/tui/tui-keybindings-file.js.map +1 -1
  559. package/dist/src/tui/tui-scoped-models.js +2 -2
  560. package/dist/src/tui/tui-session-actions.d.ts +28 -0
  561. package/dist/src/tui/tui-session-actions.js +88 -0
  562. package/dist/src/tui/tui-session-actions.js.map +1 -0
  563. package/dist/src/tui/tui-settings.js +1 -1
  564. package/dist/src/tui/tui.js +54 -49
  565. package/dist/src/tui/tui.js.map +1 -1
  566. package/dist/src/tunnel/frpc-binary.js +3 -3
  567. package/dist/src/tunnel/frpc-config.js +1 -1
  568. package/dist/src/tunnel/frpc-extract.js +1 -1
  569. package/dist/src/tunnel/tunnel-state.js +1 -1
  570. package/dist/src/utils/logger/audit.js +1 -1
  571. package/dist/src/utils/logger/log-store.js +1 -1
  572. package/dist/src/utils/logger/rotation.js +1 -1
  573. package/dist/src/utils/string-coerce.d.ts +2 -0
  574. package/dist/src/utils/string-coerce.js +10 -1
  575. package/dist/src/utils/string-coerce.js.map +1 -1
  576. package/dist/src/voice/metadata/builtin.d.ts +2 -0
  577. package/dist/src/voice/metadata/builtin.js +420 -0
  578. package/dist/src/voice/metadata/builtin.js.map +1 -0
  579. package/dist/src/voice/metadata/index.d.ts +4 -0
  580. package/dist/src/voice/metadata/index.js +3 -0
  581. package/dist/src/voice/metadata/registry.d.ts +5 -0
  582. package/dist/src/voice/metadata/registry.js +34 -0
  583. package/dist/src/voice/metadata/registry.js.map +1 -0
  584. package/dist/src/voice/metadata/types.d.ts +41 -0
  585. package/dist/src/voice/metadata/types.js +1 -0
  586. package/dist/src/voice/stt/config-slice.d.ts +2 -5
  587. package/dist/src/voice/stt/config-slice.js +5 -26
  588. package/dist/src/voice/stt/config-slice.js.map +1 -1
  589. package/dist/src/voice/stt/list-providers.d.ts +3 -3
  590. package/dist/src/voice/stt/list-providers.js +41 -6
  591. package/dist/src/voice/stt/list-providers.js.map +1 -1
  592. package/dist/src/voice/stt/types.d.ts +1 -18
  593. package/dist/src/voice/stt/types.js +4 -2
  594. package/dist/src/voice/stt/types.js.map +1 -1
  595. package/dist/src/voice/tts/audio.js +1 -1
  596. package/dist/src/voice/tts/config-slice.d.ts +3 -7
  597. package/dist/src/voice/tts/config-slice.js +7 -38
  598. package/dist/src/voice/tts/config-slice.js.map +1 -1
  599. package/dist/src/voice/tts/list-providers.d.ts +3 -3
  600. package/dist/src/voice/tts/list-providers.js +41 -6
  601. package/dist/src/voice/tts/list-providers.js.map +1 -1
  602. package/dist/src/voice/tts/merge-config.js +2 -48
  603. package/dist/src/voice/tts/merge-config.js.map +1 -1
  604. package/dist/src/voice/tts/providers/alibaba-speech.js +1 -1
  605. package/dist/src/voice/tts/providers/alibaba-speech.js.map +1 -1
  606. package/dist/src/voice/tts/providers/edge-speech.js +2 -2
  607. package/dist/src/voice/tts/types.d.ts +1 -29
  608. package/dist/src/voice/tts/types.js +19 -17
  609. package/dist/src/voice/tts/types.js.map +1 -1
  610. package/dist/src/workflows/domain/command.d.ts +18 -0
  611. package/dist/src/workflows/domain/command.js +1 -0
  612. package/dist/src/workflows/domain/definition.d.ts +62 -0
  613. package/dist/src/workflows/domain/definition.js +1 -0
  614. package/dist/src/workflows/domain/event.d.ts +67 -0
  615. package/dist/src/workflows/domain/event.js +1 -0
  616. package/dist/src/workflows/domain/index.d.ts +5 -0
  617. package/dist/src/workflows/domain/index.js +2 -0
  618. package/dist/src/workflows/domain/result.d.ts +65 -0
  619. package/dist/src/workflows/domain/result.js +1 -0
  620. package/dist/src/workflows/domain/run.d.ts +120 -0
  621. package/dist/src/workflows/domain/run.js +14 -0
  622. package/dist/src/workflows/domain/run.js.map +1 -0
  623. package/dist/src/workflows/engine/index.d.ts +2 -0
  624. package/dist/src/workflows/engine/index.js +3 -0
  625. package/dist/src/workflows/engine/projector.d.ts +3 -0
  626. package/dist/src/workflows/engine/projector.js +205 -0
  627. package/dist/src/workflows/engine/projector.js.map +1 -0
  628. package/dist/src/workflows/engine/workflow-engine.d.ts +31 -0
  629. package/dist/src/workflows/engine/workflow-engine.js +188 -0
  630. package/dist/src/workflows/engine/workflow-engine.js.map +1 -0
  631. package/dist/src/workflows/index.d.ts +6 -0
  632. package/dist/src/workflows/index.js +11 -0
  633. package/dist/src/workflows/runtime/index.d.ts +1 -0
  634. package/dist/src/workflows/runtime/index.js +4 -0
  635. package/dist/src/workflows/runtime/script-runtime.d.ts +3 -0
  636. package/dist/src/workflows/runtime/script-runtime.js +3 -0
  637. package/dist/src/workflows/store/event-store.d.ts +17 -0
  638. package/dist/src/workflows/store/event-store.js +83 -0
  639. package/dist/src/workflows/store/event-store.js.map +1 -0
  640. package/dist/src/workflows/store/paths.d.ts +7 -0
  641. package/dist/src/workflows/store/paths.js +26 -0
  642. package/dist/src/workflows/store/paths.js.map +1 -0
  643. package/dist/src/workflows/store/run-store.d.ts +13 -0
  644. package/dist/src/workflows/store/run-store.js +68 -0
  645. package/dist/src/workflows/store/run-store.js.map +1 -0
  646. package/package.json +5 -8
  647. package/dist/gateway/static/root/assets/agents-mS3_HpRI.js +0 -222
  648. package/dist/gateway/static/root/assets/channels-settings-BG6b9KrW.js +0 -1
  649. package/dist/gateway/static/root/assets/extension-settings-page-B-W4x2xP.js +0 -1
  650. package/dist/gateway/static/root/assets/index-ew_2L2We.css +0 -1
  651. package/dist/gateway/static/root/assets/sessions-page-FaG_Vlkb.js +0 -1
  652. package/dist/gateway/static/root/assets/settings-page-Bet1OerL.js +0 -3
  653. package/dist/gateway/static/root/assets/skills-page-DhUO235y.js +0 -2
  654. package/dist/gateway/static/root/assets/url-BwNL6Rgk.js +0 -3
  655. package/dist/gateway/static/root/assets/voice-api-key-field-CGEydndO.js +0 -1
  656. package/dist/src/agent/tools/browser-legacy-tools.d.ts +0 -17
  657. package/dist/src/agent/tools/browser-legacy-tools.js +0 -766
  658. package/dist/src/agent/tools/browser-legacy-tools.js.map +0 -1
@@ -20,11 +20,8 @@ import { TodoStore, createTodoTool } from "./todo-tool.js";
20
20
  import { createSessionStatusTool } from "./session-status-tool.js";
21
21
  import { createDreamingTool } from "./dreaming-tool.js";
22
22
  import { createClarifyTool } from "./clarify-tool.js";
23
- import { resolveImageModelConfigForTool } from "../image/tool-model-config.js";
24
- import { createImageTool } from "./image-tool.js";
25
- import { assertBrowserUrlAllowed } from "../../browser/url-policy.js";
26
- import { createBrowserTools } from "./browser-legacy-tools.js";
27
23
  import { BrowserManager } from "../../browser/manager.js";
24
+ import { assertBrowserUrlAllowed } from "../../browser/url-policy.js";
28
25
  import "../../browser/index.js";
29
26
  import { DEFAULT_DELEGATE_TOOLS, DELEGATE_BLOCKED_TOOLS, createDelegateTool } from "./delegate-tool.js";
30
27
  import { createWorkflowTool } from "./workflow-tool.js";
@@ -32,5 +29,7 @@ import { SANDBOX_ALLOWED_TOOLS, buildSandboxToolMap, createExecuteCodeTool } fro
32
29
  import { createCronjobTool, scanCronPrompt } from "./cronjob-tool.js";
33
30
  import { createSkillViewTool, createSkillsListTool } from "./skills-tools.js";
34
31
  import { createSkillManageTool } from "./skill-manage-tool.js";
32
+ import { resolveImageModelConfigForTool } from "../image/tool-model-config.js";
33
+ import { createImageTool } from "./image-tool.js";
35
34
  import { createImageGenerateTool, resolveImageGenerationModelConfigForTool } from "./image-generate-tool.js";
36
- export { BrowserManager, DEFAULT_DELEGATE_TOOLS, DEFAULT_MAX_BYTES, DEFAULT_MAX_LINES, DEFAULT_WEB_EXTRACT_MAX_LENGTH, DELEGATE_BLOCKED_TOOLS, GREP_MAX_LINE_LENGTH, MAX_RAW_HTML_CHARS_FOR_WEB_EXTRACT, SANDBOX_ALLOWED_TOOLS, TodoStore, assertBrowserUrlAllowed, buildSandboxToolMap, createBrowserTools, createClarifyTool, createCreateShareTool, createCronjobTool, createCuratedMemoryTool, createDelegateTool, createDreamingTool, createEditFileTool, createExecuteCodeTool, createFindTool, createGrepTool, createImageGenerateTool, createImageTool, createListDirTool, createMemoryGetTool, createMemorySearchTool, createMessageTool, createReadFileTool, createSendMediaTool, createSessionSearchTool, createSessionStatusTool, createShellTool, createSkillManageTool, createSkillViewTool, createSkillsListTool, createTodoTool, createWebExtractTool, createWebFetchTool, createWebSearchTool, createWorkflowTool, createWriteFileTool, editFileTool, findTool, formatSize, fuzzyFindText, generateDiffString, grepTool, invalidateSessionSearchIndexCache, isShareToolAvailable, listDirTool, normalizeForFuzzyMatch, normalizeToLF, resolveImageGenerationModelConfigForTool, resolveImageModelConfigForTool, restoreLineEndings, scanCronPrompt, stripBom, stripHtmlBoilerplate, truncateHead, truncateLine, truncateTail, writeFileTool };
35
+ export { BrowserManager, DEFAULT_DELEGATE_TOOLS, DEFAULT_MAX_BYTES, DEFAULT_MAX_LINES, DEFAULT_WEB_EXTRACT_MAX_LENGTH, DELEGATE_BLOCKED_TOOLS, GREP_MAX_LINE_LENGTH, MAX_RAW_HTML_CHARS_FOR_WEB_EXTRACT, SANDBOX_ALLOWED_TOOLS, TodoStore, assertBrowserUrlAllowed, buildSandboxToolMap, createClarifyTool, createCreateShareTool, createCronjobTool, createCuratedMemoryTool, createDelegateTool, createDreamingTool, createEditFileTool, createExecuteCodeTool, createFindTool, createGrepTool, createImageGenerateTool, createImageTool, createListDirTool, createMemoryGetTool, createMemorySearchTool, createMessageTool, createReadFileTool, createSendMediaTool, createSessionSearchTool, createSessionStatusTool, createShellTool, createSkillManageTool, createSkillViewTool, createSkillsListTool, createTodoTool, createWebExtractTool, createWebFetchTool, createWebSearchTool, createWorkflowTool, createWriteFileTool, editFileTool, findTool, formatSize, fuzzyFindText, generateDiffString, grepTool, invalidateSessionSearchIndexCache, isShareToolAvailable, listDirTool, normalizeForFuzzyMatch, normalizeToLF, resolveImageGenerationModelConfigForTool, resolveImageModelConfigForTool, restoreLineEndings, scanCronPrompt, stripBom, stripHtmlBoilerplate, truncateHead, truncateLine, truncateTail, writeFileTool };
@@ -1,7 +1,7 @@
1
1
  import { checkFileSafety } from "../prompt/safety.js";
2
2
  import { resolvePathUnderWorkspace } from "./tool-paths.js";
3
- import { basename } from "node:path";
4
3
  import { readFile } from "fs/promises";
4
+ import { basename } from "node:path";
5
5
  import { Type } from "@sinclair/typebox";
6
6
  //#region src/agent/tools/send-media.ts
7
7
  const SendMediaSchema = Type.Object({
@@ -1,4 +1,3 @@
1
- import { checkShellSafety } from "../prompt/safety.js";
2
1
  import { evaluateExecPolicy } from "../sandbox/exec-policy.js";
3
2
  import { spawn } from "child_process";
4
3
  import { Type } from "@sinclair/typebox";
@@ -56,18 +55,6 @@ function createShellTool(cwd, options) {
56
55
  label: "💻 Shell",
57
56
  async execute(toolCallId, params, _signal) {
58
57
  const p = params;
59
- const safety = checkShellSafety(p.command);
60
- if (!safety.allowed) return {
61
- content: [{
62
- type: "text",
63
- text: `🚫 ${safety.message}`
64
- }],
65
- details: {
66
- exitCode: null,
67
- timedOut: false,
68
- truncated: false
69
- }
70
- };
71
58
  const passthroughNames = options?.getSkillPassthroughEnvVarNames?.() ?? [];
72
59
  const policy = evaluateExecPolicy({
73
60
  command: p.command,
@@ -1 +1 @@
1
- {"version":3,"file":"shell.js","names":[],"sources":["../../../../src/agent/tools/shell.ts"],"sourcesContent":["// Shell tool - executes commands with output truncation\nimport { Type } from '@sinclair/typebox';\nimport type { AgentTool, AgentToolResult } from '@earendil-works/pi-agent-core';\nimport { spawn } from 'child_process';\nimport { evaluateExecPolicy } from '../sandbox/exec-policy.js';\nimport { checkShellSafety } from '../prompt/safety.js';\nimport { createWriteStream } from 'fs';\n\nconst MAX_SHELL_TIMEOUT = 300;\nconst DEFAULT_MAX_BYTES = 50 * 1024;\nconst DEFAULT_MAX_LINES = 2000;\n\nconst ShellSchema = Type.Object({\n command: Type.String({ description: 'Shell command to execute' }),\n});\n\nexport interface ShellDetails {\n exitCode: number | null;\n timedOut: boolean;\n truncated: boolean;\n truncatedBy?: 'lines' | 'bytes';\n outputBytes?: number;\n}\n\nfunction formatSize(bytes: number): string {\n if (bytes < 1024) return `${bytes}B`;\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)}KB`;\n return `${(bytes / (1024 * 1024)).toFixed(1)}MB`;\n}\n\nfunction truncateTail(content: string, maxLines = DEFAULT_MAX_LINES, maxBytes = DEFAULT_MAX_BYTES) {\n const totalBytes = Buffer.byteLength(content, 'utf-8');\n const lines = content.split('\\n');\n const totalLines = lines.length;\n\n if (totalLines <= maxLines && totalBytes <= maxBytes) {\n return { content, truncated: false, truncatedBy: null, totalLines, totalBytes, outputLines: totalLines, outputBytes: totalBytes };\n }\n\n const outputLinesArr: string[] = [];\n let outputBytesCount = 0;\n let truncatedBy: 'lines' | 'bytes' = 'lines';\n\n for (let i = lines.length - 1; i >= 0 && outputLinesArr.length < maxLines; i--) {\n const line = lines[i];\n const lineBytes = Buffer.byteLength(line, 'utf-8') + (outputLinesArr.length > 0 ? 1 : 0);\n\n if (outputBytesCount + lineBytes > maxBytes) {\n truncatedBy = 'bytes';\n break;\n }\n\n outputLinesArr.unshift(line);\n outputBytesCount += lineBytes;\n }\n\n return { content: outputLinesArr.join('\\n'), truncated: true, truncatedBy, totalLines, totalBytes, outputLines: outputLinesArr.length, outputBytes: outputBytesCount };\n}\n\nexport interface CreateShellToolOptions {\n /** Env var names allowed through {@link prepareSafeToolEnv} even if they match secret heuristics (skill passthrough). */\n getSkillPassthroughEnvVarNames?: () => string[];\n}\n\nexport function createShellTool(\n cwd: string,\n options?: CreateShellToolOptions,\n): AgentTool {\n return {\n name: 'shell',\n description: 'Execute shell command.',\n parameters: ShellSchema,\n label: '💻 Shell',\n\n async execute(\n toolCallId: string,\n params: any,\n _signal?: AbortSignal,\n ): Promise<AgentToolResult<ShellDetails>> {\n const p = params as { command: string };\n\n // Legacy safety check (kept for backward compat; exec-policy is the primary gate)\n const safety = checkShellSafety(p.command);\n if (!safety.allowed) {\n return {\n content: [{ type: 'text', text: `🚫 ${safety.message}` }],\n details: { exitCode: null, timedOut: false, truncated: false },\n };\n }\n\n // Sandbox exec-policy check (path + command injection + env sanitization)\n const passthroughNames = options?.getSkillPassthroughEnvVarNames?.() ?? [];\n const policy = evaluateExecPolicy({\n command: p.command,\n cwd,\n allowedEnvVars: passthroughNames,\n });\n if (!policy.allowed) {\n return {\n content: [{ type: 'text', text: `🚫 Sandbox: ${policy.reason}` }],\n details: { exitCode: null, timedOut: false, truncated: false },\n };\n }\n\n return new Promise((resolve) => {\n const _startTime = Date.now();\n let output = '';\n let errorOutput = '';\n let timedOut = false;\n let _tempFile: string | null = null;\n let tempStream: ReturnType<typeof createWriteStream> | null = null;\n const useTempFile = false; // Disabled - stream directly\n\n const effectiveTimeoutSec = Math.min(\n MAX_SHELL_TIMEOUT,\n Math.ceil(policy.timeoutMs / 1000),\n );\n const timeout = setTimeout(() => {\n timedOut = true;\n proc.kill('SIGKILL');\n }, effectiveTimeoutSec * 1000);\n\n const proc = spawn(p.command, [], {\n shell: true,\n cwd: policy.effectiveCwd,\n env: {\n ...policy.sanitizedEnv,\n COLUMNS: '200',\n },\n });\n\n proc.stdout?.on('data', (data) => {\n const text = data.toString();\n if (!useTempFile) output += text;\n });\n\n proc.stderr?.on('data', (data) => {\n const text = data.toString();\n errorOutput += text;\n });\n\n proc.on('close', (code) => {\n clearTimeout(timeout);\n tempStream?.end();\n\n const fullOutput = errorOutput + output;\n const truncation = truncateTail(fullOutput);\n\n let resultText = truncation.content;\n if (timedOut) {\n resultText = `⏱️ Command timed out after ${MAX_SHELL_TIMEOUT}s\\n` + resultText;\n }\n if (truncation.truncated) {\n resultText += `\\n\\n[Output truncated: ${formatSize(truncation.outputBytes)} of ${formatSize(truncation.totalBytes)}]`;\n }\n\n resolve({\n content: [{ type: 'text', text: resultText }],\n details: {\n exitCode: code,\n timedOut,\n truncated: truncation.truncated,\n truncatedBy: truncation.truncatedBy,\n outputBytes: truncation.outputBytes,\n },\n });\n });\n\n proc.on('error', (err) => {\n clearTimeout(timeout);\n resolve({\n content: [{ type: 'text', text: `Error: ${err.message}` }],\n details: { exitCode: null, timedOut: false, truncated: false },\n });\n });\n });\n },\n } as any;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"shell.js","names":[],"sources":["../../../../src/agent/tools/shell.ts"],"sourcesContent":["// Shell tool - executes commands with output truncation\nimport { Type } from '@sinclair/typebox';\nimport type { AgentTool, AgentToolResult } from '@earendil-works/pi-agent-core';\nimport { spawn } from 'child_process';\nimport { evaluateExecPolicy } from '../sandbox/exec-policy.js';\nimport { createWriteStream } from 'fs';\n\nconst MAX_SHELL_TIMEOUT = 300;\nconst DEFAULT_MAX_BYTES = 50 * 1024;\nconst DEFAULT_MAX_LINES = 2000;\n\nconst ShellSchema = Type.Object({\n command: Type.String({ description: 'Shell command to execute' }),\n});\n\nexport interface ShellDetails {\n exitCode: number | null;\n timedOut: boolean;\n truncated: boolean;\n truncatedBy?: 'lines' | 'bytes';\n outputBytes?: number;\n}\n\nfunction formatSize(bytes: number): string {\n if (bytes < 1024) return `${bytes}B`;\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)}KB`;\n return `${(bytes / (1024 * 1024)).toFixed(1)}MB`;\n}\n\nfunction truncateTail(content: string, maxLines = DEFAULT_MAX_LINES, maxBytes = DEFAULT_MAX_BYTES) {\n const totalBytes = Buffer.byteLength(content, 'utf-8');\n const lines = content.split('\\n');\n const totalLines = lines.length;\n\n if (totalLines <= maxLines && totalBytes <= maxBytes) {\n return { content, truncated: false, truncatedBy: null, totalLines, totalBytes, outputLines: totalLines, outputBytes: totalBytes };\n }\n\n const outputLinesArr: string[] = [];\n let outputBytesCount = 0;\n let truncatedBy: 'lines' | 'bytes' = 'lines';\n\n for (let i = lines.length - 1; i >= 0 && outputLinesArr.length < maxLines; i--) {\n const line = lines[i];\n const lineBytes = Buffer.byteLength(line, 'utf-8') + (outputLinesArr.length > 0 ? 1 : 0);\n\n if (outputBytesCount + lineBytes > maxBytes) {\n truncatedBy = 'bytes';\n break;\n }\n\n outputLinesArr.unshift(line);\n outputBytesCount += lineBytes;\n }\n\n return { content: outputLinesArr.join('\\n'), truncated: true, truncatedBy, totalLines, totalBytes, outputLines: outputLinesArr.length, outputBytes: outputBytesCount };\n}\n\nexport interface CreateShellToolOptions {\n /** Env var names allowed through {@link prepareSafeToolEnv} even if they match secret heuristics (skill passthrough). */\n getSkillPassthroughEnvVarNames?: () => string[];\n}\n\nexport function createShellTool(\n cwd: string,\n options?: CreateShellToolOptions,\n): AgentTool {\n return {\n name: 'shell',\n description: 'Execute shell command.',\n parameters: ShellSchema,\n label: '💻 Shell',\n\n async execute(\n toolCallId: string,\n params: any,\n _signal?: AbortSignal,\n ): Promise<AgentToolResult<ShellDetails>> {\n const p = params as { command: string };\n\n // Sandbox exec-policy check (path + command injection + env sanitization)\n const passthroughNames = options?.getSkillPassthroughEnvVarNames?.() ?? [];\n const policy = evaluateExecPolicy({\n command: p.command,\n cwd,\n allowedEnvVars: passthroughNames,\n });\n if (!policy.allowed) {\n return {\n content: [{ type: 'text', text: `🚫 Sandbox: ${policy.reason}` }],\n details: { exitCode: null, timedOut: false, truncated: false },\n };\n }\n\n return new Promise((resolve) => {\n const _startTime = Date.now();\n let output = '';\n let errorOutput = '';\n let timedOut = false;\n let _tempFile: string | null = null;\n let tempStream: ReturnType<typeof createWriteStream> | null = null;\n const useTempFile = false; // Disabled - stream directly\n\n const effectiveTimeoutSec = Math.min(\n MAX_SHELL_TIMEOUT,\n Math.ceil(policy.timeoutMs / 1000),\n );\n const timeout = setTimeout(() => {\n timedOut = true;\n proc.kill('SIGKILL');\n }, effectiveTimeoutSec * 1000);\n\n const proc = spawn(p.command, [], {\n shell: true,\n cwd: policy.effectiveCwd,\n env: {\n ...policy.sanitizedEnv,\n COLUMNS: '200',\n },\n });\n\n proc.stdout?.on('data', (data) => {\n const text = data.toString();\n if (!useTempFile) output += text;\n });\n\n proc.stderr?.on('data', (data) => {\n const text = data.toString();\n errorOutput += text;\n });\n\n proc.on('close', (code) => {\n clearTimeout(timeout);\n tempStream?.end();\n\n const fullOutput = errorOutput + output;\n const truncation = truncateTail(fullOutput);\n\n let resultText = truncation.content;\n if (timedOut) {\n resultText = `⏱️ Command timed out after ${MAX_SHELL_TIMEOUT}s\\n` + resultText;\n }\n if (truncation.truncated) {\n resultText += `\\n\\n[Output truncated: ${formatSize(truncation.outputBytes)} of ${formatSize(truncation.totalBytes)}]`;\n }\n\n resolve({\n content: [{ type: 'text', text: resultText }],\n details: {\n exitCode: code,\n timedOut,\n truncated: truncation.truncated,\n truncatedBy: truncation.truncatedBy,\n outputBytes: truncation.outputBytes,\n },\n });\n });\n\n proc.on('error', (err) => {\n clearTimeout(timeout);\n resolve({\n content: [{ type: 'text', text: `Error: ${err.message}` }],\n details: { exitCode: null, timedOut: false, truncated: false },\n });\n });\n });\n },\n } as any;\n}\n"],"mappings":"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"}
@@ -2,9 +2,9 @@ import { resolveStateDir } from "../../config/paths-state.js";
2
2
  import { init_paths } from "../../config/paths.js";
3
3
  import { createSkillConfigManager } from "../skills/config.js";
4
4
  import { applyPatchToContent, atomicWriteUtf8, effectiveAgentWritePolicy, ensureCategorySegment, isPathInsideDir, maxSkillMdChars, maxSupportFileBytes, mutatableSkillOrNull, resolveCreateSkillDir, scanSkillDirOrError, validateSkillMdContent, validateSkillNameSegment, validateSupportingRelativePath } from "../skills/skill-manage-ops.js";
5
+ import { readFile, rm } from "fs/promises";
5
6
  import { join } from "path";
6
7
  import { existsSync, rmSync } from "fs";
7
- import { readFile, rm } from "fs/promises";
8
8
  import { Type } from "@sinclair/typebox";
9
9
  //#region src/agent/tools/skill-manage-tool.ts
10
10
  init_paths();
@@ -1,11 +1,15 @@
1
1
  import { createLogger } from "../../utils/logger/index.js";
2
2
  import { init_logger } from "../../utils/logger.js";
3
+ import { extractProfileAgentId } from "../../config/agent-profile.js";
4
+ import { init_providers, resolveModel } from "../../providers/index.js";
5
+ import { applySubagentProgress } from "../workflow/agent-progress.js";
3
6
  import { parseWorkflowScript } from "../workflow/parser.js";
4
7
  import { getLastWorkflowMemory } from "../workflow/last-run-memory.js";
5
- import { previewValue, recomputeCounts, renderWorkflowText } from "../workflow/snapshot.js";
6
8
  import { runWorkflow } from "../workflow/runtime.js";
9
+ import { previewValue, recomputeCounts, renderWorkflowText } from "../workflow/snapshot.js";
7
10
  import { DelegateSubagentRunner } from "../workflow/subagent-runner.js";
8
11
  import "../workflow/index.js";
12
+ import { resolveModelRef } from "../../config/agent-typed-models.js";
9
13
  import { Type } from "@sinclair/typebox";
10
14
  //#region src/agent/tools/workflow-tool.ts
11
15
  /**
@@ -23,11 +27,13 @@ import { Type } from "@sinclair/typebox";
23
27
  * organised today.
24
28
  */
25
29
  init_logger();
30
+ init_providers();
26
31
  const log = createLogger("workflow-tool");
27
32
  const DEFAULT_TIMEOUT_SEC = 1800;
28
33
  const MAX_TIMEOUT_SEC = 14400;
29
34
  const DEFAULT_MAX_CONCURRENCY = 16;
30
35
  const DEFAULT_MAX_SUBAGENTS = 1e3;
36
+ const PUSH_UPDATE_THROTTLE_MS = 300;
31
37
  const WorkflowToolSchema = Type.Object({
32
38
  name: Type.Optional(Type.String({ description: "Name of a saved workflow to run. Either `name` or `script` is required. Use `name` whenever the user references a known workflow (built-in or in ~/.xopc/workflows/)." })),
33
39
  script: Type.Optional(Type.String({ description: [
@@ -98,7 +104,7 @@ function createWorkflowTool(deps) {
98
104
  const snapshot = {
99
105
  name: meta.name,
100
106
  description: meta.description,
101
- phases: [],
107
+ phases: meta.phases?.map((p) => p.title) ?? [],
102
108
  logs: [],
103
109
  agents: [],
104
110
  agentCount: 0,
@@ -107,16 +113,33 @@ function createWorkflowTool(deps) {
107
113
  errorCount: 0,
108
114
  skippedCount: 0
109
115
  };
110
- const pushUpdate = (completed = false) => {
116
+ let lastUpdatePushedAtMs = Number.NEGATIVE_INFINITY;
117
+ let liveUpdatesDisabled = false;
118
+ const pushUpdate = (completed = false, immediate = false) => {
119
+ if (liveUpdatesDisabled) return;
111
120
  recomputeCounts(snapshot);
112
- onUpdate?.({
113
- content: [{
114
- type: "text",
115
- text: renderWorkflowText(snapshot, completed, { showResultPreviews: false })
116
- }],
117
- details: snapshot
118
- });
121
+ const nowMs = Date.now();
122
+ if (!(completed || immediate || nowMs - lastUpdatePushedAtMs >= PUSH_UPDATE_THROTTLE_MS)) return;
123
+ lastUpdatePushedAtMs = nowMs;
124
+ try {
125
+ onUpdate?.({
126
+ content: [{
127
+ type: "text",
128
+ text: renderWorkflowText(snapshot, completed, { showResultPreviews: false })
129
+ }],
130
+ details: snapshot
131
+ });
132
+ } catch (e) {
133
+ liveUpdatesDisabled = true;
134
+ const message = e instanceof Error ? e.message : String(e);
135
+ log.warn({
136
+ err: e,
137
+ errorMessage: message,
138
+ workflow: meta.name
139
+ }, `workflow live progress disabled: ${message}`);
140
+ }
119
141
  };
142
+ const subagentStream = wfCfg?.subagentStream ?? "steps";
120
143
  const runner = new DelegateSubagentRunner({
121
144
  workspace: deps.workspace,
122
145
  bus: deps.bus,
@@ -125,13 +148,22 @@ function createWorkflowTool(deps) {
125
148
  toolExecutorConfig: deps.toolExecutorConfig,
126
149
  buildChildTools: deps.buildChildTools
127
150
  });
151
+ const resolveModelId = (modelRef) => {
152
+ const config = deps.getConfig();
153
+ if (!config) throw new Error("workflow model resolution requires config");
154
+ const sessionKey = deps.getCurrentSessionKey?.();
155
+ return resolveModel(resolveModelRef(config, extractProfileAgentId(sessionKey, config), modelRef));
156
+ };
128
157
  const controller = new AbortController();
129
158
  const onParentAbort = () => controller.abort();
130
159
  signal?.addEventListener("abort", onParentAbort, { once: true });
131
160
  const timeoutHandle = timeoutSec > 0 ? setTimeout(() => controller.abort(), timeoutSec * 1e3) : void 0;
132
161
  pushUpdate();
133
162
  try {
134
- const result = await runWorkflow(script, { runner }, {
163
+ const result = await runWorkflow(script, {
164
+ runner,
165
+ resolveModelId
166
+ }, {
135
167
  cwd: deps.workspace,
136
168
  args: params.args,
137
169
  signal: controller.signal,
@@ -146,24 +178,46 @@ function createWorkflowTool(deps) {
146
178
  if (!snapshot.phases.includes(title)) snapshot.phases.push(title);
147
179
  pushUpdate();
148
180
  },
149
- onAgentStart: (event) => {
181
+ onAgentQueued: (event) => {
150
182
  snapshot.agents.push({
151
183
  id: event.id,
152
184
  label: event.label,
153
185
  phase: event.phase,
154
186
  prompt: event.prompt,
155
- status: "running"
187
+ status: "queued"
156
188
  });
157
- pushUpdate();
189
+ pushUpdate(false, true);
190
+ },
191
+ onAgentStart: (event) => {
192
+ const agent = findAgentById(snapshot.agents, event.id);
193
+ if (agent) {
194
+ agent.status = "running";
195
+ agent.startedAtMs = Date.now();
196
+ } else snapshot.agents.push({
197
+ id: event.id,
198
+ label: event.label,
199
+ phase: event.phase,
200
+ prompt: event.prompt,
201
+ status: "running",
202
+ startedAtMs: Date.now()
203
+ });
204
+ pushUpdate(false, true);
158
205
  },
159
206
  onAgentEnd: (event) => {
160
207
  const agent = findAgentById(snapshot.agents, event.id);
161
208
  if (agent) {
162
209
  agent.status = event.status;
163
210
  agent.resultPreview = previewValue(event.result);
211
+ if (agent.startedAtMs != null) agent.durationMs = Date.now() - agent.startedAtMs;
212
+ agent.currentStep = void 0;
164
213
  }
165
- pushUpdate();
166
- }
214
+ pushUpdate(false, true);
215
+ },
216
+ enhanceSubagentRun: subagentStream === "off" ? void 0 : ({ id }) => ({ onProgress: (event) => {
217
+ const agent = findAgentById(snapshot.agents, id);
218
+ if (!agent) return;
219
+ if (applySubagentProgress(agent, event)) pushUpdate();
220
+ } })
167
221
  });
168
222
  if (result.agentCount === 0) {
169
223
  const reason = "workflow scripts must call agent() at least once; this workflow declared phases but never ran a subagent.";
@@ -1 +1 @@
1
- {"version":3,"file":"workflow-tool.js","names":[],"sources":["../../../../src/agent/tools/workflow-tool.ts"],"sourcesContent":["/**\n * `workflow` — the AgentTool the parent model calls to spawn a fan-out run.\n *\n * Shape mirrors `delegate-tool`: factory builds a closure over deps; `execute`\n * parses the script, instantiates the {@link DelegateSubagentRunner}, drives the\n * {@link runWorkflow} runtime, and pushes a live text snapshot through\n * `onUpdate` for streaming UIs (TUI, gateway console).\n *\n * Why this lives in `src/agent/tools/` (not under `src/agent/workflow/`):\n * the runtime is reusable infrastructure; the AgentTool wrapping is a\n * presentation concern that depends on the AgentToolsFactory wiring. Keeping\n * the wrapper here matches how `delegate-tool` and `execute-code-tool` are\n * organised today.\n */\n\nimport { Type } from '@sinclair/typebox';\nimport type { AgentTool, AgentToolResult } from '@earendil-works/pi-agent-core';\nimport type { Api, Model } from '@earendil-works/pi-ai';\n\nimport type { Config } from '../../config/schema.js';\nimport type { MessageBus } from '../../infra/bus/index.js';\nimport { createLogger } from '../../utils/logger.js';\n\nimport type { BuildChildToolsOptions } from '../child-agent-factory.js';\nimport {\n DelegateSubagentRunner,\n getLastWorkflowMemory,\n parseWorkflowScript,\n previewValue,\n recomputeCounts,\n renderWorkflowText,\n runWorkflow,\n type WorkflowAgentSnapshot,\n type WorkflowCatalog,\n type WorkflowMeta,\n type WorkflowSnapshot,\n} from '../workflow/index.js';\nimport type { ToolExecutorConfig } from './executor.js';\n\nconst log = createLogger('workflow-tool');\n\nconst DEFAULT_TIMEOUT_SEC = 30 * 60;\nconst MAX_TIMEOUT_SEC = 4 * 60 * 60;\nconst DEFAULT_MAX_CONCURRENCY = 16;\nconst DEFAULT_MAX_SUBAGENTS = 1000;\n\nconst WorkflowToolSchema = Type.Object({\n name: Type.Optional(\n Type.String({\n description:\n 'Name of a saved workflow to run. Either `name` or `script` is required. ' +\n 'Use `name` whenever the user references a known workflow (built-in or in ~/.xopc/workflows/).',\n }),\n ),\n script: Type.Optional(\n Type.String({\n description: [\n 'Raw JavaScript workflow script (no Markdown fences, no TypeScript syntax). Ignored when `name` is set.',\n \"First statement: export const meta = { name: 'snake_case', description: 'short, human-readable' }.\",\n 'Use phase(title), agent(prompt, opts), parallel(arrayOfFunctions), pipeline(items, ...stages), log(message), args, and budget.',\n 'The script must call agent() at least once.',\n 'parallel() requires functions: await parallel(items.map(item => () => agent(...))).',\n ].join(' '),\n }),\n ),\n args: Type.Optional(\n Type.Any({\n description: 'Optional JSON value exposed to the workflow script as the global `args`.',\n }),\n ),\n});\n\nexport type WorkflowToolInput = {\n name?: string;\n script?: string;\n args?: unknown;\n};\n\nexport interface WorkflowToolDeps {\n workspace: string;\n bus: MessageBus;\n /** Returns the parent agent's primary model — subagents default to this. */\n getSubagentModel: () => Model<Api>;\n getConfig: () => Config | undefined;\n /** Same injection point delegate-tool uses; supplied by AgentToolsFactory. */\n buildChildTools: (opts: BuildChildToolsOptions) => AgentTool<any, any>[];\n toolExecutorConfig?: Partial<ToolExecutorConfig>;\n /** Catalog for `name` lookups (built-in + ~/.xopc/workflows/). */\n catalog: WorkflowCatalog;\n /** Per-call sessionKey lookup — used to record \"last successful workflow\" for /workflow save. */\n getCurrentSessionKey?: () => string | undefined;\n}\n\nexport function createWorkflowTool(deps: WorkflowToolDeps): AgentTool {\n return {\n name: 'workflow',\n label: '◆ Workflow',\n description: [\n 'Run a deterministic JavaScript workflow that orchestrates multiple isolated subagents through agent(), parallel(), and pipeline().',\n 'Two ways to invoke:',\n ' 1. `name`: run a saved workflow from the catalog (built-in or ~/.xopc/workflows/). Prefer this when the user references a known name.',\n ' 2. `script`: provide a raw JS workflow inline. Use when no saved workflow fits. Header is required: export const meta = { name, description }.',\n 'Named-workflow triggers — call this tool with `{ name: \"<name>\" }` IMMEDIATELY when the user message is any of:',\n ' • a bare workflow name like \"/audit_repo\", \"/pr_review\", \"/research\", or \"audit_repo\"',\n ' • \"run the audit_repo workflow\", \"review this PR\", \"debug this error\", \"kick off research\", \"do a multi_perspective_review on X\" (extract args when natural: target, question, error, diff)',\n ' • after /workflows lists saved workflows and the user picks one',\n 'Use phase(title) at runtime to mark progress groups. Each agent() returns a string, or a schema-validated object when opts.schema is set.',\n 'Prefer for decomposable work: repo audits, PR review, incident triage, multi-perspective review, fan-out research, large refactors. Do not use for a single quick read/edit.',\n 'parallel() takes thunks, not promises: parallel(items.map(item => () => agent(...))).',\n 'pipeline(items, ...stages) interleaves items across stages — fastest path by default; only use parallel() when you genuinely need a cross-item barrier.',\n 'Failed agent()/parallel()/pipeline() entries resolve to null; check before synthesizing.',\n 'Do not use Date.now(), Math.random(), new Date(), require, import, fs, or network APIs — they are unavailable for determinism.',\n 'Always end with a synthesis agent() that consolidates findings, especially when you fan out for review or research.',\n ].join('\\n\\n'),\n parameters: WorkflowToolSchema,\n\n async execute(\n _toolCallId: string,\n params: WorkflowToolInput,\n signal?: AbortSignal,\n onUpdate?: (update: AgentToolResult<WorkflowSnapshot | undefined>) => void,\n ): Promise<AgentToolResult<WorkflowSnapshot | { error: string }>> {\n let script: string;\n let resolvedSource: 'name' | 'script' = 'script';\n try {\n const resolved = resolveScript(params, deps.catalog);\n script = resolved.script;\n resolvedSource = resolved.source;\n } catch (e) {\n const message = e instanceof Error ? e.message : String(e);\n return {\n content: [{ type: 'text', text: `workflow: ${message}` }],\n details: { error: message },\n };\n }\n\n const cfg = deps.getConfig();\n const wfCfg = cfg?.agents?.defaults?.workflow;\n const concurrency = wfCfg?.maxConcurrency ?? DEFAULT_MAX_CONCURRENCY;\n const maxSubagents = wfCfg?.maxSubagents ?? DEFAULT_MAX_SUBAGENTS;\n const timeoutSec = clampTimeout(wfCfg?.defaultTimeoutSec);\n\n // Parse early so a bad script returns an error result instead of throwing\n // through the agent loop. The runtime parses again, but that's cheap.\n let meta: WorkflowMeta;\n try {\n meta = parseWorkflowScript(script).meta;\n } catch (e) {\n const message = e instanceof Error ? e.message : String(e);\n return {\n content: [\n {\n type: 'text',\n text:\n resolvedSource === 'name'\n ? `workflow \"${params.name}\" failed to parse: ${message}`\n : `workflow parse error: ${message}`,\n },\n ],\n details: { error: message },\n };\n }\n\n const snapshot: WorkflowSnapshot = {\n name: meta.name,\n description: meta.description,\n phases: [],\n logs: [],\n agents: [],\n agentCount: 0,\n runningCount: 0,\n doneCount: 0,\n errorCount: 0,\n skippedCount: 0,\n };\n\n const pushUpdate = (completed = false) => {\n recomputeCounts(snapshot);\n onUpdate?.({\n content: [\n {\n type: 'text',\n text: renderWorkflowText(snapshot, completed, { showResultPreviews: false }),\n },\n ],\n details: snapshot,\n });\n };\n\n const runner = new DelegateSubagentRunner({\n workspace: deps.workspace,\n bus: deps.bus,\n getDefaultModel: deps.getSubagentModel,\n getConfig: deps.getConfig,\n toolExecutorConfig: deps.toolExecutorConfig,\n buildChildTools: deps.buildChildTools,\n });\n\n // Combined abort: parent signal + per-run timeout.\n const controller = new AbortController();\n const onParentAbort = () => controller.abort();\n signal?.addEventListener('abort', onParentAbort, { once: true });\n const timeoutHandle =\n timeoutSec > 0\n ? setTimeout(() => controller.abort(), timeoutSec * 1000)\n : undefined;\n\n pushUpdate();\n\n try {\n const result = await runWorkflow(script, { runner }, {\n cwd: deps.workspace,\n args: params.args,\n signal: controller.signal,\n concurrency,\n maxSubagents,\n onLog: (message) => {\n snapshot.logs.push(message);\n pushUpdate();\n },\n onPhase: (title) => {\n snapshot.currentPhase = title;\n if (!snapshot.phases.includes(title)) snapshot.phases.push(title);\n pushUpdate();\n },\n onAgentStart: (event) => {\n snapshot.agents.push({\n id: event.id,\n label: event.label,\n phase: event.phase,\n prompt: event.prompt,\n status: 'running',\n });\n pushUpdate();\n },\n onAgentEnd: (event) => {\n const agent = findAgentById(snapshot.agents, event.id);\n if (agent) {\n agent.status = event.status;\n agent.resultPreview = previewValue(event.result);\n }\n pushUpdate();\n },\n });\n\n if (result.agentCount === 0) {\n const reason =\n 'workflow scripts must call agent() at least once; this workflow declared phases but never ran a subagent.';\n snapshot.logs.push(reason);\n pushUpdate(true);\n return {\n content: [{ type: 'text', text: reason }],\n details: snapshot,\n };\n }\n\n snapshot.result = result.result;\n snapshot.durationMs = result.durationMs;\n pushUpdate(true);\n\n // Record for /workflow save — last successful run per session.\n // Failures are intentionally skipped so users do not save broken scripts.\n try {\n getLastWorkflowMemory().record(deps.getCurrentSessionKey?.(), {\n script,\n metaName: result.meta.name,\n source: resolvedSource,\n recordedAt: Date.now(),\n });\n } catch {\n // Memory recording is best-effort; never break a successful run on it.\n }\n\n return {\n content: [\n {\n type: 'text',\n text: `workflow ${result.meta.name} completed: ${result.agentCount} subagent(s), ${snapshot.errorCount} error(s).\\n\\nResult:\\n${safeStringify(result.result)}`,\n },\n ],\n details: snapshot,\n };\n } catch (e) {\n if (controller.signal.aborted) {\n for (const a of snapshot.agents) {\n if (a.status === 'running') {\n a.status = 'skipped';\n a.error = 'aborted';\n }\n }\n pushUpdate(true);\n const reason = signal?.aborted ? 'workflow aborted' : `workflow timed out after ${timeoutSec}s`;\n return {\n content: [{ type: 'text', text: reason }],\n details: snapshot,\n };\n }\n const message = e instanceof Error ? e.message : String(e);\n log.warn({ err: e, errorMessage: message, workflow: meta.name }, `workflow failed: ${message}`);\n snapshot.logs.push(`workflow failed: ${message}`);\n pushUpdate(true);\n return {\n content: [{ type: 'text', text: `workflow failed: ${message}` }],\n details: snapshot,\n };\n } finally {\n if (timeoutHandle) clearTimeout(timeoutHandle);\n signal?.removeEventListener('abort', onParentAbort);\n }\n },\n } as unknown as AgentTool;\n}\n\n// ---------------------------------------------------------------------------\n\nfunction normalizeScript(script: string): string {\n let text = script.trim();\n const fence = text.match(/^```(?:js|javascript)?\\s*\\n([\\s\\S]*?)\\n```$/i);\n if (fence) text = fence[1].trim();\n return text;\n}\n\nfunction resolveScript(\n params: WorkflowToolInput,\n catalog: WorkflowCatalog,\n): { script: string; source: 'name' | 'script' } {\n const name = params.name?.trim();\n if (name) {\n const loaded = catalog.load(name);\n return { script: loaded.script, source: 'name' };\n }\n if (!params.script || !params.script.trim()) {\n throw new Error('either `name` or `script` is required.');\n }\n return { script: normalizeScript(params.script), source: 'script' };\n}\n\nfunction clampTimeout(requested: number | undefined): number {\n const v = typeof requested === 'number' && Number.isFinite(requested) ? requested : DEFAULT_TIMEOUT_SEC;\n if (v <= 0) return 0;\n return Math.min(MAX_TIMEOUT_SEC, Math.max(1, Math.floor(v)));\n}\n\nfunction findAgentById(agents: WorkflowAgentSnapshot[], id: number): WorkflowAgentSnapshot | undefined {\n // Linear scan — agent lists are small in practice (capped at maxSubagents).\n for (let i = agents.length - 1; i >= 0; i--) {\n if (agents[i].id === id) return agents[i];\n }\n return undefined;\n}\n\nfunction safeStringify(value: unknown): string {\n try {\n return JSON.stringify(value, null, 2);\n } catch {\n return String(value);\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"workflow-tool.js","names":["resolveModelById"],"sources":["../../../../src/agent/tools/workflow-tool.ts"],"sourcesContent":["/**\n * `workflow` — the AgentTool the parent model calls to spawn a fan-out run.\n *\n * Shape mirrors `delegate-tool`: factory builds a closure over deps; `execute`\n * parses the script, instantiates the {@link DelegateSubagentRunner}, drives the\n * {@link runWorkflow} runtime, and pushes a live text snapshot through\n * `onUpdate` for streaming UIs (TUI, gateway console).\n *\n * Why this lives in `src/agent/tools/` (not under `src/agent/workflow/`):\n * the runtime is reusable infrastructure; the AgentTool wrapping is a\n * presentation concern that depends on the AgentToolsFactory wiring. Keeping\n * the wrapper here matches how `delegate-tool` and `execute-code-tool` are\n * organised today.\n */\n\nimport { Type } from '@sinclair/typebox';\nimport type { AgentTool, AgentToolResult } from '@earendil-works/pi-agent-core';\nimport type { Api, Model } from '@earendil-works/pi-ai';\n\nimport type { Config } from '../../config/schema.js';\nimport type { MessageBus } from '../../infra/bus/index.js';\nimport { createLogger } from '../../utils/logger.js';\n\nimport type { BuildChildToolsOptions } from '../child-agent-factory.js';\nimport {\n DelegateSubagentRunner,\n getLastWorkflowMemory,\n parseWorkflowScript,\n previewValue,\n recomputeCounts,\n renderWorkflowText,\n runWorkflow,\n applySubagentProgress,\n type WorkflowAgentSnapshot,\n type WorkflowCatalog,\n type WorkflowMeta,\n type WorkflowSnapshot,\n type SubagentProgressEvent,\n} from '../workflow/index.js';\nimport { resolveModel as resolveModelById } from '../../providers/index.js';\nimport { extractProfileAgentId } from '../../config/agent-profile.js';\nimport { resolveModelRef } from '../../config/agent-typed-models.js';\nimport type { ToolExecutorConfig } from './executor.js';\n\nconst log = createLogger('workflow-tool');\n\nconst DEFAULT_TIMEOUT_SEC = 30 * 60;\nconst MAX_TIMEOUT_SEC = 4 * 60 * 60;\nconst DEFAULT_MAX_CONCURRENCY = 16;\nconst DEFAULT_MAX_SUBAGENTS = 1000;\nconst PUSH_UPDATE_THROTTLE_MS = 300;\n\nconst WorkflowToolSchema = Type.Object({\n name: Type.Optional(\n Type.String({\n description:\n 'Name of a saved workflow to run. Either `name` or `script` is required. ' +\n 'Use `name` whenever the user references a known workflow (built-in or in ~/.xopc/workflows/).',\n }),\n ),\n script: Type.Optional(\n Type.String({\n description: [\n 'Raw JavaScript workflow script (no Markdown fences, no TypeScript syntax). Ignored when `name` is set.',\n \"First statement: export const meta = { name: 'snake_case', description: 'short, human-readable' }.\",\n 'Use phase(title), agent(prompt, opts), parallel(arrayOfFunctions), pipeline(items, ...stages), log(message), args, and budget.',\n 'The script must call agent() at least once.',\n 'parallel() requires functions: await parallel(items.map(item => () => agent(...))).',\n ].join(' '),\n }),\n ),\n args: Type.Optional(\n Type.Any({\n description: 'Optional JSON value exposed to the workflow script as the global `args`.',\n }),\n ),\n});\n\nexport type WorkflowToolInput = {\n name?: string;\n script?: string;\n args?: unknown;\n};\n\nexport interface WorkflowToolDeps {\n workspace: string;\n bus: MessageBus;\n /** Returns the parent agent's primary model — subagents default to this. */\n getSubagentModel: () => Model<Api>;\n getConfig: () => Config | undefined;\n /** Same injection point delegate-tool uses; supplied by AgentToolsFactory. */\n buildChildTools: (opts: BuildChildToolsOptions) => AgentTool<any, any>[];\n toolExecutorConfig?: Partial<ToolExecutorConfig>;\n /** Catalog for `name` lookups (built-in + ~/.xopc/workflows/). */\n catalog: WorkflowCatalog;\n /** Per-call sessionKey lookup — used to record \"last successful workflow\" for /workflow save. */\n getCurrentSessionKey?: () => string | undefined;\n}\n\nexport function createWorkflowTool(deps: WorkflowToolDeps): AgentTool {\n return {\n name: 'workflow',\n label: '◆ Workflow',\n description: [\n 'Run a deterministic JavaScript workflow that orchestrates multiple isolated subagents through agent(), parallel(), and pipeline().',\n 'Two ways to invoke:',\n ' 1. `name`: run a saved workflow from the catalog (built-in or ~/.xopc/workflows/). Prefer this when the user references a known name.',\n ' 2. `script`: provide a raw JS workflow inline. Use when no saved workflow fits. Header is required: export const meta = { name, description }.',\n 'Named-workflow triggers — call this tool with `{ name: \"<name>\" }` IMMEDIATELY when the user message is any of:',\n ' • a bare workflow name like \"/audit_repo\", \"/pr_review\", \"/research\", or \"audit_repo\"',\n ' • \"run the audit_repo workflow\", \"review this PR\", \"debug this error\", \"kick off research\", \"do a multi_perspective_review on X\" (extract args when natural: target, question, error, diff)',\n ' • after /workflows lists saved workflows and the user picks one',\n 'Use phase(title) at runtime to mark progress groups. Each agent() returns a string, or a schema-validated object when opts.schema is set.',\n 'Prefer for decomposable work: repo audits, PR review, incident triage, multi-perspective review, fan-out research, large refactors. Do not use for a single quick read/edit.',\n 'parallel() takes thunks, not promises: parallel(items.map(item => () => agent(...))).',\n 'pipeline(items, ...stages) interleaves items across stages — fastest path by default; only use parallel() when you genuinely need a cross-item barrier.',\n 'Failed agent()/parallel()/pipeline() entries resolve to null; check before synthesizing.',\n 'Do not use Date.now(), Math.random(), new Date(), require, import, fs, or network APIs — they are unavailable for determinism.',\n 'Always end with a synthesis agent() that consolidates findings, especially when you fan out for review or research.',\n ].join('\\n\\n'),\n parameters: WorkflowToolSchema,\n\n async execute(\n _toolCallId: string,\n params: WorkflowToolInput,\n signal?: AbortSignal,\n onUpdate?: (update: AgentToolResult<WorkflowSnapshot | undefined>) => void,\n ): Promise<AgentToolResult<WorkflowSnapshot | { error: string }>> {\n let script: string;\n let resolvedSource: 'name' | 'script' = 'script';\n try {\n const resolved = resolveScript(params, deps.catalog);\n script = resolved.script;\n resolvedSource = resolved.source;\n } catch (e) {\n const message = e instanceof Error ? e.message : String(e);\n return {\n content: [{ type: 'text', text: `workflow: ${message}` }],\n details: { error: message },\n };\n }\n\n const cfg = deps.getConfig();\n const wfCfg = cfg?.agents?.defaults?.workflow;\n const concurrency = wfCfg?.maxConcurrency ?? DEFAULT_MAX_CONCURRENCY;\n const maxSubagents = wfCfg?.maxSubagents ?? DEFAULT_MAX_SUBAGENTS;\n const timeoutSec = clampTimeout(wfCfg?.defaultTimeoutSec);\n\n // Parse early so a bad script returns an error result instead of throwing\n // through the agent loop. The runtime parses again, but that's cheap.\n let meta: WorkflowMeta;\n try {\n meta = parseWorkflowScript(script).meta;\n } catch (e) {\n const message = e instanceof Error ? e.message : String(e);\n return {\n content: [\n {\n type: 'text',\n text:\n resolvedSource === 'name'\n ? `workflow \"${params.name}\" failed to parse: ${message}`\n : `workflow parse error: ${message}`,\n },\n ],\n details: { error: message },\n };\n }\n\n const snapshot: WorkflowSnapshot = {\n name: meta.name,\n description: meta.description,\n phases: meta.phases?.map((p) => p.title) ?? [],\n logs: [],\n agents: [],\n agentCount: 0,\n runningCount: 0,\n doneCount: 0,\n errorCount: 0,\n skippedCount: 0,\n };\n\n let lastUpdatePushedAtMs = Number.NEGATIVE_INFINITY;\n let liveUpdatesDisabled = false;\n const pushUpdate = (completed = false, immediate = false) => {\n if (liveUpdatesDisabled) return;\n\n recomputeCounts(snapshot);\n const nowMs = Date.now();\n const shouldEmit =\n completed || immediate || nowMs - lastUpdatePushedAtMs >= PUSH_UPDATE_THROTTLE_MS;\n if (!shouldEmit) return;\n\n lastUpdatePushedAtMs = nowMs;\n try {\n onUpdate?.({\n content: [\n {\n type: 'text',\n text: renderWorkflowText(snapshot, completed, { showResultPreviews: false }),\n },\n ],\n details: snapshot,\n });\n } catch (e) {\n liveUpdatesDisabled = true;\n const message = e instanceof Error ? e.message : String(e);\n log.warn(\n { err: e, errorMessage: message, workflow: meta.name },\n `workflow live progress disabled: ${message}`,\n );\n }\n };\n\n const subagentStream = wfCfg?.subagentStream ?? 'steps';\n\n const runner = new DelegateSubagentRunner({\n workspace: deps.workspace,\n bus: deps.bus,\n getDefaultModel: deps.getSubagentModel,\n getConfig: deps.getConfig,\n toolExecutorConfig: deps.toolExecutorConfig,\n buildChildTools: deps.buildChildTools,\n });\n\n const resolveModelId = (modelRef: string): Model<Api> => {\n const config = deps.getConfig();\n if (!config) {\n throw new Error('workflow model resolution requires config');\n }\n const sessionKey = deps.getCurrentSessionKey?.();\n const agentId = extractProfileAgentId(sessionKey, config);\n const realRef = resolveModelRef(config, agentId, modelRef);\n return resolveModelById(realRef);\n };\n\n // Combined abort: parent signal + per-run timeout.\n const controller = new AbortController();\n const onParentAbort = () => controller.abort();\n signal?.addEventListener('abort', onParentAbort, { once: true });\n const timeoutHandle =\n timeoutSec > 0\n ? setTimeout(() => controller.abort(), timeoutSec * 1000)\n : undefined;\n\n pushUpdate();\n\n try {\n const result = await runWorkflow(script, { runner, resolveModelId }, {\n cwd: deps.workspace,\n args: params.args,\n signal: controller.signal,\n concurrency,\n maxSubagents,\n onLog: (message) => {\n snapshot.logs.push(message);\n pushUpdate();\n },\n onPhase: (title) => {\n snapshot.currentPhase = title;\n if (!snapshot.phases.includes(title)) snapshot.phases.push(title);\n pushUpdate();\n },\n onAgentQueued: (event) => {\n snapshot.agents.push({\n id: event.id,\n label: event.label,\n phase: event.phase,\n prompt: event.prompt,\n status: 'queued',\n });\n pushUpdate(false, true);\n },\n onAgentStart: (event) => {\n const agent = findAgentById(snapshot.agents, event.id);\n if (agent) {\n agent.status = 'running';\n agent.startedAtMs = Date.now();\n } else {\n snapshot.agents.push({\n id: event.id,\n label: event.label,\n phase: event.phase,\n prompt: event.prompt,\n status: 'running',\n startedAtMs: Date.now(),\n });\n }\n pushUpdate(false, true);\n },\n onAgentEnd: (event) => {\n const agent = findAgentById(snapshot.agents, event.id);\n if (agent) {\n agent.status = event.status;\n agent.resultPreview = previewValue(event.result);\n if (agent.startedAtMs != null) {\n agent.durationMs = Date.now() - agent.startedAtMs;\n }\n agent.currentStep = undefined;\n }\n pushUpdate(false, true);\n },\n enhanceSubagentRun:\n subagentStream === 'off'\n ? undefined\n : ({ id }) => ({\n onProgress: (event: SubagentProgressEvent) => {\n const agent = findAgentById(snapshot.agents, id);\n if (!agent) return;\n if (applySubagentProgress(agent, event)) {\n pushUpdate();\n }\n },\n }),\n });\n\n if (result.agentCount === 0) {\n const reason =\n 'workflow scripts must call agent() at least once; this workflow declared phases but never ran a subagent.';\n snapshot.logs.push(reason);\n pushUpdate(true);\n return {\n content: [{ type: 'text', text: reason }],\n details: snapshot,\n };\n }\n\n snapshot.result = result.result;\n snapshot.durationMs = result.durationMs;\n pushUpdate(true);\n\n // Record for /workflow save — last successful run per session.\n // Failures are intentionally skipped so users do not save broken scripts.\n try {\n getLastWorkflowMemory().record(deps.getCurrentSessionKey?.(), {\n script,\n metaName: result.meta.name,\n source: resolvedSource,\n recordedAt: Date.now(),\n });\n } catch {\n // Memory recording is best-effort; never break a successful run on it.\n }\n\n return {\n content: [\n {\n type: 'text',\n text: `workflow ${result.meta.name} completed: ${result.agentCount} subagent(s), ${snapshot.errorCount} error(s).\\n\\nResult:\\n${safeStringify(result.result)}`,\n },\n ],\n details: snapshot,\n };\n } catch (e) {\n if (controller.signal.aborted) {\n for (const a of snapshot.agents) {\n if (a.status === 'running') {\n a.status = 'skipped';\n a.error = 'aborted';\n }\n }\n pushUpdate(true);\n const reason = signal?.aborted ? 'workflow aborted' : `workflow timed out after ${timeoutSec}s`;\n return {\n content: [{ type: 'text', text: reason }],\n details: snapshot,\n };\n }\n const message = e instanceof Error ? e.message : String(e);\n log.warn({ err: e, errorMessage: message, workflow: meta.name }, `workflow failed: ${message}`);\n snapshot.logs.push(`workflow failed: ${message}`);\n pushUpdate(true);\n return {\n content: [{ type: 'text', text: `workflow failed: ${message}` }],\n details: snapshot,\n };\n } finally {\n if (timeoutHandle) clearTimeout(timeoutHandle);\n signal?.removeEventListener('abort', onParentAbort);\n }\n },\n } as unknown as AgentTool;\n}\n\n// ---------------------------------------------------------------------------\n\nfunction normalizeScript(script: string): string {\n let text = script.trim();\n const fence = text.match(/^```(?:js|javascript)?\\s*\\n([\\s\\S]*?)\\n```$/i);\n if (fence) text = fence[1].trim();\n return text;\n}\n\nfunction resolveScript(\n params: WorkflowToolInput,\n catalog: WorkflowCatalog,\n): { script: string; source: 'name' | 'script' } {\n const name = params.name?.trim();\n if (name) {\n const loaded = catalog.load(name);\n return { script: loaded.script, source: 'name' };\n }\n if (!params.script || !params.script.trim()) {\n throw new Error('either `name` or `script` is required.');\n }\n return { script: normalizeScript(params.script), source: 'script' };\n}\n\nfunction clampTimeout(requested: number | undefined): number {\n const v = typeof requested === 'number' && Number.isFinite(requested) ? requested : DEFAULT_TIMEOUT_SEC;\n if (v <= 0) return 0;\n return Math.min(MAX_TIMEOUT_SEC, Math.max(1, Math.floor(v)));\n}\n\nfunction findAgentById(agents: WorkflowAgentSnapshot[], id: number): WorkflowAgentSnapshot | undefined {\n // Linear scan — agent lists are small in practice (capped at maxSubagents).\n for (let i = agents.length - 1; i >= 0; i--) {\n if (agents[i].id === id) return agents[i];\n }\n return undefined;\n}\n\nfunction safeStringify(value: unknown): string {\n try {\n return JSON.stringify(value, null, 2);\n } catch {\n return String(value);\n }\n}\n"],"mappings":"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"}
@@ -1,8 +1,8 @@
1
1
  import { checkFileSafety } from "../prompt/safety.js";
2
2
  import { resolvePathUnderWorkspace } from "./tool-paths.js";
3
3
  import { evaluateFilePolicy } from "../sandbox/exec-policy.js";
4
- import { dirname } from "path";
5
4
  import { mkdir, writeFile } from "fs/promises";
5
+ import { dirname } from "path";
6
6
  import { Type } from "@sinclair/typebox";
7
7
  //#region src/agent/tools/write.ts
8
8
  const MAX_FILE_SIZE = 10 * 1024 * 1024;
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Apply live subagent progress events onto a {@link WorkflowAgentSnapshot}.
3
+ */
4
+ import type { SubagentProgressEvent, WorkflowAgentSnapshot } from './types.js';
5
+ export declare function applySubagentProgress(agent: WorkflowAgentSnapshot, event: SubagentProgressEvent): boolean;
@@ -0,0 +1,65 @@
1
+ import { workflowStepLabel } from "./step-labels.js";
2
+ //#region src/agent/workflow/agent-progress.ts
3
+ const MAX_STEPS = 50;
4
+ const MAX_STREAM_TEXT = 32e3;
5
+ function applySubagentProgress(agent, event) {
6
+ switch (event.type) {
7
+ case "tool_start": {
8
+ if (!agent.steps) agent.steps = [];
9
+ const { label, detail } = workflowStepLabel(event.toolName, event.args);
10
+ const step = {
11
+ id: event.toolCallId,
12
+ kind: "tool",
13
+ toolName: event.toolName,
14
+ label,
15
+ detail,
16
+ status: "running",
17
+ startedAtMs: Date.now()
18
+ };
19
+ agent.steps.push(step);
20
+ trimSteps(agent);
21
+ agent.currentStep = formatCurrentStep(step);
22
+ return true;
23
+ }
24
+ case "tool_end": {
25
+ const step = findStep(agent, event.toolCallId);
26
+ if (!step) return false;
27
+ step.status = event.isError ? "error" : "done";
28
+ if (step.startedAtMs != null) step.durationMs = Date.now() - step.startedAtMs;
29
+ if (agent.currentStep === formatCurrentStep(step)) agent.currentStep = void 0;
30
+ return true;
31
+ }
32
+ case "iteration":
33
+ agent.iteration = event.count;
34
+ agent.maxIterations = event.max;
35
+ return true;
36
+ case "text_delta":
37
+ if (!event.delta) return false;
38
+ agent.streamText = appendStreamText(agent.streamText, event.delta);
39
+ return true;
40
+ case "thinking_delta":
41
+ if (!event.delta) return false;
42
+ agent.streamText = appendStreamText(agent.streamText, event.delta);
43
+ return true;
44
+ default: return false;
45
+ }
46
+ }
47
+ function findStep(agent, id) {
48
+ return agent.steps?.find((s) => s.id === id);
49
+ }
50
+ function formatCurrentStep(step) {
51
+ return step.detail ? `${step.label}: ${step.detail}` : step.label;
52
+ }
53
+ function trimSteps(agent) {
54
+ if (!agent.steps || agent.steps.length <= MAX_STEPS) return;
55
+ agent.steps = agent.steps.slice(-MAX_STEPS);
56
+ }
57
+ function appendStreamText(existing, delta) {
58
+ const next = (existing ?? "") + delta;
59
+ if (next.length <= MAX_STREAM_TEXT) return next;
60
+ return next.slice(-MAX_STREAM_TEXT);
61
+ }
62
+ //#endregion
63
+ export { applySubagentProgress };
64
+
65
+ //# sourceMappingURL=agent-progress.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-progress.js","names":[],"sources":["../../../../src/agent/workflow/agent-progress.ts"],"sourcesContent":["/**\n * Apply live subagent progress events onto a {@link WorkflowAgentSnapshot}.\n */\n\nimport type {\n SubagentProgressEvent,\n WorkflowAgentSnapshot,\n WorkflowAgentStep,\n} from './types.js';\nimport { workflowStepLabel } from './step-labels.js';\n\nconst MAX_STEPS = 50;\nconst MAX_STREAM_TEXT = 32_000;\n\nexport function applySubagentProgress(\n agent: WorkflowAgentSnapshot,\n event: SubagentProgressEvent,\n): boolean {\n switch (event.type) {\n case 'tool_start': {\n if (!agent.steps) agent.steps = [];\n const { label, detail } = workflowStepLabel(event.toolName, event.args);\n const step: WorkflowAgentStep = {\n id: event.toolCallId,\n kind: 'tool',\n toolName: event.toolName,\n label,\n detail,\n status: 'running',\n startedAtMs: Date.now(),\n };\n agent.steps.push(step);\n trimSteps(agent);\n agent.currentStep = formatCurrentStep(step);\n return true;\n }\n case 'tool_end': {\n const step = findStep(agent, event.toolCallId);\n if (!step) return false;\n step.status = event.isError ? 'error' : 'done';\n if (step.startedAtMs != null) step.durationMs = Date.now() - step.startedAtMs;\n if (agent.currentStep === formatCurrentStep(step)) {\n agent.currentStep = undefined;\n }\n return true;\n }\n case 'iteration': {\n agent.iteration = event.count;\n agent.maxIterations = event.max;\n return true;\n }\n case 'text_delta': {\n if (!event.delta) return false;\n agent.streamText = appendStreamText(agent.streamText, event.delta);\n return true;\n }\n case 'thinking_delta': {\n if (!event.delta) return false;\n agent.streamText = appendStreamText(agent.streamText, event.delta);\n return true;\n }\n default:\n return false;\n }\n}\n\nfunction findStep(agent: WorkflowAgentSnapshot, id: string): WorkflowAgentStep | undefined {\n return agent.steps?.find((s) => s.id === id);\n}\n\nfunction formatCurrentStep(step: WorkflowAgentStep): string {\n return step.detail ? `${step.label}: ${step.detail}` : step.label;\n}\n\nfunction trimSteps(agent: WorkflowAgentSnapshot): void {\n if (!agent.steps || agent.steps.length <= MAX_STEPS) return;\n agent.steps = agent.steps.slice(-MAX_STEPS);\n}\n\nfunction appendStreamText(existing: string | undefined, delta: string): string {\n const next = (existing ?? '') + delta;\n if (next.length <= MAX_STREAM_TEXT) return next;\n return next.slice(-MAX_STREAM_TEXT);\n}\n"],"mappings":";;AAWA,MAAM,YAAY;AAClB,MAAM,kBAAkB;AAExB,SAAgB,sBACd,OACA,OACS;AACT,SAAQ,MAAM,MAAd;EACE,KAAK,cAAc;AACjB,OAAI,CAAC,MAAM,MAAO,OAAM,QAAQ,EAAE;GAClC,MAAM,EAAE,OAAO,WAAW,kBAAkB,MAAM,UAAU,MAAM,KAAK;GACvE,MAAM,OAA0B;IAC9B,IAAI,MAAM;IACV,MAAM;IACN,UAAU,MAAM;IAChB;IACA;IACA,QAAQ;IACR,aAAa,KAAK,KAAK;IACxB;AACD,SAAM,MAAM,KAAK,KAAK;AACtB,aAAU,MAAM;AAChB,SAAM,cAAc,kBAAkB,KAAK;AAC3C,UAAO;;EAET,KAAK,YAAY;GACf,MAAM,OAAO,SAAS,OAAO,MAAM,WAAW;AAC9C,OAAI,CAAC,KAAM,QAAO;AAClB,QAAK,SAAS,MAAM,UAAU,UAAU;AACxC,OAAI,KAAK,eAAe,KAAM,MAAK,aAAa,KAAK,KAAK,GAAG,KAAK;AAClE,OAAI,MAAM,gBAAgB,kBAAkB,KAAK,CAC/C,OAAM,cAAc,KAAA;AAEtB,UAAO;;EAET,KAAK;AACH,SAAM,YAAY,MAAM;AACxB,SAAM,gBAAgB,MAAM;AAC5B,UAAO;EAET,KAAK;AACH,OAAI,CAAC,MAAM,MAAO,QAAO;AACzB,SAAM,aAAa,iBAAiB,MAAM,YAAY,MAAM,MAAM;AAClE,UAAO;EAET,KAAK;AACH,OAAI,CAAC,MAAM,MAAO,QAAO;AACzB,SAAM,aAAa,iBAAiB,MAAM,YAAY,MAAM,MAAM;AAClE,UAAO;EAET,QACE,QAAO;;;AAIb,SAAS,SAAS,OAA8B,IAA2C;AACzF,QAAO,MAAM,OAAO,MAAM,MAAM,EAAE,OAAO,GAAG;;AAG9C,SAAS,kBAAkB,MAAiC;AAC1D,QAAO,KAAK,SAAS,GAAG,KAAK,MAAM,IAAI,KAAK,WAAW,KAAK;;AAG9D,SAAS,UAAU,OAAoC;AACrD,KAAI,CAAC,MAAM,SAAS,MAAM,MAAM,UAAU,UAAW;AACrD,OAAM,QAAQ,MAAM,MAAM,MAAM,CAAC,UAAU;;AAG7C,SAAS,iBAAiB,UAA8B,OAAuB;CAC7E,MAAM,QAAQ,YAAY,MAAM;AAChC,KAAI,KAAK,UAAU,gBAAiB,QAAO;AAC3C,QAAO,KAAK,MAAM,CAAC,gBAAgB"}
@@ -10,4 +10,4 @@
10
10
  * - scope: subdirectory to focus on (default '.')
11
11
  * - dimensions: subset of dimension keys, e.g. ['security', 'bugs']
12
12
  */
13
- export declare const AUDIT_REPO_SCRIPT = "export const meta = {\n name: 'audit_repo',\n description: 'Fan-out repository audit across multiple dimensions, then synthesize a structured report.',\n whenToUse: 'User asks for a thorough / multi-dimension code review of the whole repo or a major subsystem.',\n tags: ['code-review', 'audit'],\n estimatedAgents: { min: 7, max: 7 },\n phases: [\n { title: 'Inventory' },\n { title: 'Review' },\n { title: 'Synthesize' },\n ],\n}\n\nconst READ_ONLY_TOOLS = ['read_file', 'grep', 'find', 'list_dir']\n\nconst scope = args && typeof args === 'object' && args.scope\n ? String(args.scope)\n : '.'\n\nconst ALL_DIMENSIONS = [\n { key: 'bugs', focus: 'Correctness bugs, null-safety, error handling, race conditions, off-by-one, dead code.' },\n { key: 'perf', focus: 'Performance issues, hot paths, N+1 patterns, accidental quadratic loops, sync I/O, missing caching.' },\n { key: 'security', focus: 'Auth/authz, input validation, secret handling, injection sinks, unsafe deserialization, SSRF.' },\n { key: 'tests', focus: 'Test coverage gaps, brittle tests, integration vs unit gaps, missing regression cases.' },\n { key: 'style', focus: 'Inconsistent conventions, naming, unused exports, duplication, layering violations.' },\n]\n\nlet dimensions = ALL_DIMENSIONS\nif (args && typeof args === 'object' && Array.isArray(args.dimensions) && args.dimensions.length) {\n const keys = new Set(args.dimensions.map((d) => String(d)))\n dimensions = ALL_DIMENSIONS.filter((d) => keys.has(d.key))\n if (!dimensions.length) dimensions = ALL_DIMENSIONS\n}\n\nphase('Inventory')\nconst inventory = await agent(\n 'Produce a compact map of this repository scope: ' + scope + '. ' +\n 'Cover layout, main modules, the 5\u201310 most important files, and obvious entry points. Be terse and structured.',\n { label: 'repo inventory', toolset: READ_ONLY_TOOLS },\n)\n\nphase('Review')\nconst findings = await parallel(\n dimensions.map((d) => () =>\n agent(\n 'Review scope \"' + scope + '\" through the ' + d.key + ' lens.\\n' +\n 'Focus: ' + d.focus + '\\n\\n' +\n 'Inventory for orientation:\\n' + inventory + '\\n\\n' +\n 'Return findings: file paths, line numbers when known, severity (low/med/high), a one-sentence why, a one-sentence fix.',\n {\n label: d.key + ' review',\n toolset: READ_ONLY_TOOLS,\n schema: {\n type: 'object',\n properties: {\n findings: {\n type: 'array',\n items: {\n type: 'object',\n properties: {\n file: { type: 'string' },\n line: { type: ['number', 'string'] },\n severity: { type: 'string', enum: ['low', 'med', 'high'] },\n title: { type: 'string' },\n fix: { type: 'string' },\n },\n required: ['file', 'severity', 'title', 'fix'],\n },\n },\n },\n required: ['findings'],\n },\n },\n ),\n ),\n)\n\nphase('Synthesize')\nconst live = findings.filter(Boolean)\nif (!live.length) {\n return { ok: true, scope, summary: 'No findings.', byDimension: {}, priorityActions: [] }\n}\nconst byDimension = {}\nfor (let i = 0; i < dimensions.length; i++) {\n byDimension[dimensions[i].key] = live[i]?.findings ?? []\n}\n\nconst summary = await agent(\n 'Synthesize a compact report from these per-dimension findings. Deduplicate near-identical items. ' +\n 'Order by severity (high \u2192 low). Cap topFindings at 20. ' +\n 'Also return priorityActions: the top 5 fixes ranked by impact, each with effort (S|M|L).\\n\\n' +\n JSON.stringify(byDimension, null, 2),\n {\n label: 'report synthesis',\n schema: {\n type: 'object',\n properties: {\n topFindings: {\n type: 'array',\n items: {\n type: 'object',\n properties: {\n dimension: { type: 'string' },\n file: { type: 'string' },\n severity: { type: 'string' },\n title: { type: 'string' },\n fix: { type: 'string' },\n },\n required: ['dimension', 'file', 'severity', 'title'],\n },\n },\n priorityActions: {\n type: 'array',\n items: {\n type: 'object',\n properties: {\n file: { type: 'string' },\n severity: { type: 'string' },\n title: { type: 'string' },\n effort: { type: 'string', enum: ['S', 'M', 'L'] },\n },\n required: ['file', 'severity', 'title', 'effort'],\n },\n },\n summary: { type: 'string' },\n },\n required: ['topFindings', 'priorityActions', 'summary'],\n },\n },\n)\n\nreturn {\n ok: true,\n scope,\n dimensions: dimensions.map((d) => d.key),\n ...(summary ?? { topFindings: [], priorityActions: [], summary: 'synthesis failed' }),\n byDimension,\n}\n";
13
+ export declare const AUDIT_REPO_SCRIPT = "export const meta = {\n name: 'audit_repo',\n description: 'Fan-out repository audit across multiple dimensions, then synthesize a structured report.',\n whenToUse: 'User asks for a thorough / multi-dimension code review of the whole repo or a major subsystem.',\n examplePrompts: [\n { field: 'goal', text: 'Run a thorough audit of this repository' },\n { field: 'goal', text: 'Review code quality across the whole codebase' },\n ],\n i18n: {\n zh: {\n description: '\u591A\u7EF4\u5EA6\u5E76\u884C\u5BA1\u67E5\u6574\u4E2A\u4ED3\u5E93\uFF0C\u5E76\u6C47\u603B\u4E3A\u7ED3\u6784\u5316\u62A5\u544A\u3002',\n whenToUse: '\u7528\u6237\u9700\u8981\u5BF9\u6574\u5E93\u6216\u4E3B\u8981\u5B50\u7CFB\u7EDF\u505A\u5168\u9762\u3001\u591A\u7EF4\u5EA6\u7684\u4EE3\u7801\u5BA1\u67E5\u65F6\u3002',\n examplePrompts: [\n { field: 'goal', text: '\u5BF9\u6574\u4E2A\u4ED3\u5E93\u505A\u4E00\u6B21\u5168\u9762\u5BA1\u67E5' },\n { field: 'goal', text: '\u4ECE\u4EE3\u7801\u8D28\u91CF\u7EF4\u5EA6\u5BA1\u67E5\u6574\u4E2A\u4EE3\u7801\u5E93' },\n ],\n },\n },\n tags: ['code-review', 'audit'],\n estimatedAgents: { min: 7, max: 7 },\n phases: [\n { title: 'Inventory' },\n { title: 'Review' },\n { title: 'Synthesize' },\n ],\n}\n\nconst READ_ONLY_TOOLS = ['read_file', 'grep', 'find', 'list_dir']\n\nconst scope = args && typeof args === 'object' && args.scope\n ? String(args.scope)\n : '.'\n\nconst ALL_DIMENSIONS = [\n { key: 'bugs', focus: 'Correctness bugs, null-safety, error handling, race conditions, off-by-one, dead code.' },\n { key: 'perf', focus: 'Performance issues, hot paths, N+1 patterns, accidental quadratic loops, sync I/O, missing caching.' },\n { key: 'security', focus: 'Auth/authz, input validation, secret handling, injection sinks, unsafe deserialization, SSRF.' },\n { key: 'tests', focus: 'Test coverage gaps, brittle tests, integration vs unit gaps, missing regression cases.' },\n { key: 'style', focus: 'Inconsistent conventions, naming, unused exports, duplication, layering violations.' },\n]\n\nlet dimensions = ALL_DIMENSIONS\nif (args && typeof args === 'object' && Array.isArray(args.dimensions) && args.dimensions.length) {\n const keys = new Set(args.dimensions.map((d) => String(d)))\n dimensions = ALL_DIMENSIONS.filter((d) => keys.has(d.key))\n if (!dimensions.length) dimensions = ALL_DIMENSIONS\n}\n\nphase('Inventory')\nconst inventory = await agent(\n 'Produce a compact map of this repository scope: ' + scope + '. ' +\n 'Cover layout, main modules, the 5\u201310 most important files, and obvious entry points. Be terse and structured.',\n { label: 'repo inventory', toolset: READ_ONLY_TOOLS },\n)\n\nphase('Review')\nconst findings = await parallel(\n dimensions.map((d) => () =>\n agent(\n 'Review scope \"' + scope + '\" through the ' + d.key + ' lens.\\n' +\n 'Focus: ' + d.focus + '\\n\\n' +\n 'Inventory for orientation:\\n' + inventory + '\\n\\n' +\n 'Return findings: file paths, line numbers when known, severity (low/med/high), a one-sentence why, a one-sentence fix.',\n {\n label: d.key + ' review',\n toolset: READ_ONLY_TOOLS,\n schema: {\n type: 'object',\n properties: {\n findings: {\n type: 'array',\n items: {\n type: 'object',\n properties: {\n file: { type: 'string' },\n line: { type: ['number', 'string'] },\n severity: { type: 'string', enum: ['low', 'med', 'high'] },\n title: { type: 'string' },\n fix: { type: 'string' },\n },\n required: ['file', 'severity', 'title', 'fix'],\n },\n },\n },\n required: ['findings'],\n },\n },\n ),\n ),\n)\n\nphase('Synthesize')\nconst live = findings.filter(Boolean)\nif (!live.length) {\n return { ok: true, scope, summary: 'No findings.', byDimension: {}, priorityActions: [] }\n}\nconst byDimension = {}\nfor (let i = 0; i < dimensions.length; i++) {\n byDimension[dimensions[i].key] = live[i]?.findings ?? []\n}\n\nconst summary = await agent(\n 'Synthesize a compact report from these per-dimension findings. Deduplicate near-identical items. ' +\n 'Order by severity (high \u2192 low). Cap topFindings at 20. ' +\n 'Also return priorityActions: the top 5 fixes ranked by impact, each with effort (S|M|L).\\n\\n' +\n JSON.stringify(byDimension, null, 2),\n {\n label: 'report synthesis',\n schema: {\n type: 'object',\n properties: {\n topFindings: {\n type: 'array',\n items: {\n type: 'object',\n properties: {\n dimension: { type: 'string' },\n file: { type: 'string' },\n severity: { type: 'string' },\n title: { type: 'string' },\n fix: { type: 'string' },\n },\n required: ['dimension', 'file', 'severity', 'title'],\n },\n },\n priorityActions: {\n type: 'array',\n items: {\n type: 'object',\n properties: {\n file: { type: 'string' },\n severity: { type: 'string' },\n title: { type: 'string' },\n effort: { type: 'string', enum: ['S', 'M', 'L'] },\n },\n required: ['file', 'severity', 'title', 'effort'],\n },\n },\n summary: { type: 'string' },\n },\n required: ['topFindings', 'priorityActions', 'summary'],\n },\n },\n)\n\nreturn {\n ok: true,\n scope,\n dimensions: dimensions.map((d) => d.key),\n ...(summary ?? { topFindings: [], priorityActions: [], summary: 'synthesis failed' }),\n byDimension,\n}\n";
@@ -15,6 +15,20 @@ const AUDIT_REPO_SCRIPT = `export const meta = {
15
15
  name: 'audit_repo',
16
16
  description: 'Fan-out repository audit across multiple dimensions, then synthesize a structured report.',
17
17
  whenToUse: 'User asks for a thorough / multi-dimension code review of the whole repo or a major subsystem.',
18
+ examplePrompts: [
19
+ { field: 'goal', text: 'Run a thorough audit of this repository' },
20
+ { field: 'goal', text: 'Review code quality across the whole codebase' },
21
+ ],
22
+ i18n: {
23
+ zh: {
24
+ description: '多维度并行审查整个仓库,并汇总为结构化报告。',
25
+ whenToUse: '用户需要对整库或主要子系统做全面、多维度的代码审查时。',
26
+ examplePrompts: [
27
+ { field: 'goal', text: '对整个仓库做一次全面审查' },
28
+ { field: 'goal', text: '从代码质量维度审查整个代码库' },
29
+ ],
30
+ },
31
+ },
18
32
  tags: ['code-review', 'audit'],
19
33
  estimatedAgents: { min: 7, max: 7 },
20
34
  phases: [
@@ -1 +1 @@
1
- {"version":3,"file":"audit-repo.js","names":[],"sources":["../../../../../src/agent/workflow/builtins/audit-repo.ts"],"sourcesContent":["/**\n * Built-in workflow: `audit_repo`\n *\n * Fan-out repo audit. Phase 1 inventories the repo; phase 2 spawns N reviewers\n * in parallel, one per dimension (bugs / perf / security / tests / style);\n * phase 3 synthesises into a structured report. The script is kept readable so\n * users can copy it into `~/.xopc/workflows/` as a starting point.\n *\n * Args:\n * - scope: subdirectory to focus on (default '.')\n * - dimensions: subset of dimension keys, e.g. ['security', 'bugs']\n */\n\nexport const AUDIT_REPO_SCRIPT = `export const meta = {\n name: 'audit_repo',\n description: 'Fan-out repository audit across multiple dimensions, then synthesize a structured report.',\n whenToUse: 'User asks for a thorough / multi-dimension code review of the whole repo or a major subsystem.',\n tags: ['code-review', 'audit'],\n estimatedAgents: { min: 7, max: 7 },\n phases: [\n { title: 'Inventory' },\n { title: 'Review' },\n { title: 'Synthesize' },\n ],\n}\n\nconst READ_ONLY_TOOLS = ['read_file', 'grep', 'find', 'list_dir']\n\nconst scope = args && typeof args === 'object' && args.scope\n ? String(args.scope)\n : '.'\n\nconst ALL_DIMENSIONS = [\n { key: 'bugs', focus: 'Correctness bugs, null-safety, error handling, race conditions, off-by-one, dead code.' },\n { key: 'perf', focus: 'Performance issues, hot paths, N+1 patterns, accidental quadratic loops, sync I/O, missing caching.' },\n { key: 'security', focus: 'Auth/authz, input validation, secret handling, injection sinks, unsafe deserialization, SSRF.' },\n { key: 'tests', focus: 'Test coverage gaps, brittle tests, integration vs unit gaps, missing regression cases.' },\n { key: 'style', focus: 'Inconsistent conventions, naming, unused exports, duplication, layering violations.' },\n]\n\nlet dimensions = ALL_DIMENSIONS\nif (args && typeof args === 'object' && Array.isArray(args.dimensions) && args.dimensions.length) {\n const keys = new Set(args.dimensions.map((d) => String(d)))\n dimensions = ALL_DIMENSIONS.filter((d) => keys.has(d.key))\n if (!dimensions.length) dimensions = ALL_DIMENSIONS\n}\n\nphase('Inventory')\nconst inventory = await agent(\n 'Produce a compact map of this repository scope: ' + scope + '. ' +\n 'Cover layout, main modules, the 5–10 most important files, and obvious entry points. Be terse and structured.',\n { label: 'repo inventory', toolset: READ_ONLY_TOOLS },\n)\n\nphase('Review')\nconst findings = await parallel(\n dimensions.map((d) => () =>\n agent(\n 'Review scope \"' + scope + '\" through the ' + d.key + ' lens.\\\\n' +\n 'Focus: ' + d.focus + '\\\\n\\\\n' +\n 'Inventory for orientation:\\\\n' + inventory + '\\\\n\\\\n' +\n 'Return findings: file paths, line numbers when known, severity (low/med/high), a one-sentence why, a one-sentence fix.',\n {\n label: d.key + ' review',\n toolset: READ_ONLY_TOOLS,\n schema: {\n type: 'object',\n properties: {\n findings: {\n type: 'array',\n items: {\n type: 'object',\n properties: {\n file: { type: 'string' },\n line: { type: ['number', 'string'] },\n severity: { type: 'string', enum: ['low', 'med', 'high'] },\n title: { type: 'string' },\n fix: { type: 'string' },\n },\n required: ['file', 'severity', 'title', 'fix'],\n },\n },\n },\n required: ['findings'],\n },\n },\n ),\n ),\n)\n\nphase('Synthesize')\nconst live = findings.filter(Boolean)\nif (!live.length) {\n return { ok: true, scope, summary: 'No findings.', byDimension: {}, priorityActions: [] }\n}\nconst byDimension = {}\nfor (let i = 0; i < dimensions.length; i++) {\n byDimension[dimensions[i].key] = live[i]?.findings ?? []\n}\n\nconst summary = await agent(\n 'Synthesize a compact report from these per-dimension findings. Deduplicate near-identical items. ' +\n 'Order by severity (high → low). Cap topFindings at 20. ' +\n 'Also return priorityActions: the top 5 fixes ranked by impact, each with effort (S|M|L).\\\\n\\\\n' +\n JSON.stringify(byDimension, null, 2),\n {\n label: 'report synthesis',\n schema: {\n type: 'object',\n properties: {\n topFindings: {\n type: 'array',\n items: {\n type: 'object',\n properties: {\n dimension: { type: 'string' },\n file: { type: 'string' },\n severity: { type: 'string' },\n title: { type: 'string' },\n fix: { type: 'string' },\n },\n required: ['dimension', 'file', 'severity', 'title'],\n },\n },\n priorityActions: {\n type: 'array',\n items: {\n type: 'object',\n properties: {\n file: { type: 'string' },\n severity: { type: 'string' },\n title: { type: 'string' },\n effort: { type: 'string', enum: ['S', 'M', 'L'] },\n },\n required: ['file', 'severity', 'title', 'effort'],\n },\n },\n summary: { type: 'string' },\n },\n required: ['topFindings', 'priorityActions', 'summary'],\n },\n },\n)\n\nreturn {\n ok: true,\n scope,\n dimensions: dimensions.map((d) => d.key),\n ...(summary ?? { topFindings: [], priorityActions: [], summary: 'synthesis failed' }),\n byDimension,\n}\n`\n"],"mappings":";;;;;;;;;;;;;AAaA,MAAa,oBAAoB"}
1
+ {"version":3,"file":"audit-repo.js","names":[],"sources":["../../../../../src/agent/workflow/builtins/audit-repo.ts"],"sourcesContent":["/**\n * Built-in workflow: `audit_repo`\n *\n * Fan-out repo audit. Phase 1 inventories the repo; phase 2 spawns N reviewers\n * in parallel, one per dimension (bugs / perf / security / tests / style);\n * phase 3 synthesises into a structured report. The script is kept readable so\n * users can copy it into `~/.xopc/workflows/` as a starting point.\n *\n * Args:\n * - scope: subdirectory to focus on (default '.')\n * - dimensions: subset of dimension keys, e.g. ['security', 'bugs']\n */\n\nexport const AUDIT_REPO_SCRIPT = `export const meta = {\n name: 'audit_repo',\n description: 'Fan-out repository audit across multiple dimensions, then synthesize a structured report.',\n whenToUse: 'User asks for a thorough / multi-dimension code review of the whole repo or a major subsystem.',\n examplePrompts: [\n { field: 'goal', text: 'Run a thorough audit of this repository' },\n { field: 'goal', text: 'Review code quality across the whole codebase' },\n ],\n i18n: {\n zh: {\n description: '多维度并行审查整个仓库,并汇总为结构化报告。',\n whenToUse: '用户需要对整库或主要子系统做全面、多维度的代码审查时。',\n examplePrompts: [\n { field: 'goal', text: '对整个仓库做一次全面审查' },\n { field: 'goal', text: '从代码质量维度审查整个代码库' },\n ],\n },\n },\n tags: ['code-review', 'audit'],\n estimatedAgents: { min: 7, max: 7 },\n phases: [\n { title: 'Inventory' },\n { title: 'Review' },\n { title: 'Synthesize' },\n ],\n}\n\nconst READ_ONLY_TOOLS = ['read_file', 'grep', 'find', 'list_dir']\n\nconst scope = args && typeof args === 'object' && args.scope\n ? String(args.scope)\n : '.'\n\nconst ALL_DIMENSIONS = [\n { key: 'bugs', focus: 'Correctness bugs, null-safety, error handling, race conditions, off-by-one, dead code.' },\n { key: 'perf', focus: 'Performance issues, hot paths, N+1 patterns, accidental quadratic loops, sync I/O, missing caching.' },\n { key: 'security', focus: 'Auth/authz, input validation, secret handling, injection sinks, unsafe deserialization, SSRF.' },\n { key: 'tests', focus: 'Test coverage gaps, brittle tests, integration vs unit gaps, missing regression cases.' },\n { key: 'style', focus: 'Inconsistent conventions, naming, unused exports, duplication, layering violations.' },\n]\n\nlet dimensions = ALL_DIMENSIONS\nif (args && typeof args === 'object' && Array.isArray(args.dimensions) && args.dimensions.length) {\n const keys = new Set(args.dimensions.map((d) => String(d)))\n dimensions = ALL_DIMENSIONS.filter((d) => keys.has(d.key))\n if (!dimensions.length) dimensions = ALL_DIMENSIONS\n}\n\nphase('Inventory')\nconst inventory = await agent(\n 'Produce a compact map of this repository scope: ' + scope + '. ' +\n 'Cover layout, main modules, the 5–10 most important files, and obvious entry points. Be terse and structured.',\n { label: 'repo inventory', toolset: READ_ONLY_TOOLS },\n)\n\nphase('Review')\nconst findings = await parallel(\n dimensions.map((d) => () =>\n agent(\n 'Review scope \"' + scope + '\" through the ' + d.key + ' lens.\\\\n' +\n 'Focus: ' + d.focus + '\\\\n\\\\n' +\n 'Inventory for orientation:\\\\n' + inventory + '\\\\n\\\\n' +\n 'Return findings: file paths, line numbers when known, severity (low/med/high), a one-sentence why, a one-sentence fix.',\n {\n label: d.key + ' review',\n toolset: READ_ONLY_TOOLS,\n schema: {\n type: 'object',\n properties: {\n findings: {\n type: 'array',\n items: {\n type: 'object',\n properties: {\n file: { type: 'string' },\n line: { type: ['number', 'string'] },\n severity: { type: 'string', enum: ['low', 'med', 'high'] },\n title: { type: 'string' },\n fix: { type: 'string' },\n },\n required: ['file', 'severity', 'title', 'fix'],\n },\n },\n },\n required: ['findings'],\n },\n },\n ),\n ),\n)\n\nphase('Synthesize')\nconst live = findings.filter(Boolean)\nif (!live.length) {\n return { ok: true, scope, summary: 'No findings.', byDimension: {}, priorityActions: [] }\n}\nconst byDimension = {}\nfor (let i = 0; i < dimensions.length; i++) {\n byDimension[dimensions[i].key] = live[i]?.findings ?? []\n}\n\nconst summary = await agent(\n 'Synthesize a compact report from these per-dimension findings. Deduplicate near-identical items. ' +\n 'Order by severity (high → low). Cap topFindings at 20. ' +\n 'Also return priorityActions: the top 5 fixes ranked by impact, each with effort (S|M|L).\\\\n\\\\n' +\n JSON.stringify(byDimension, null, 2),\n {\n label: 'report synthesis',\n schema: {\n type: 'object',\n properties: {\n topFindings: {\n type: 'array',\n items: {\n type: 'object',\n properties: {\n dimension: { type: 'string' },\n file: { type: 'string' },\n severity: { type: 'string' },\n title: { type: 'string' },\n fix: { type: 'string' },\n },\n required: ['dimension', 'file', 'severity', 'title'],\n },\n },\n priorityActions: {\n type: 'array',\n items: {\n type: 'object',\n properties: {\n file: { type: 'string' },\n severity: { type: 'string' },\n title: { type: 'string' },\n effort: { type: 'string', enum: ['S', 'M', 'L'] },\n },\n required: ['file', 'severity', 'title', 'effort'],\n },\n },\n summary: { type: 'string' },\n },\n required: ['topFindings', 'priorityActions', 'summary'],\n },\n },\n)\n\nreturn {\n ok: true,\n scope,\n dimensions: dimensions.map((d) => d.key),\n ...(summary ?? { topFindings: [], priorityActions: [], summary: 'synthesis failed' }),\n byDimension,\n}\n`\n"],"mappings":";;;;;;;;;;;;;AAaA,MAAa,oBAAoB"}
@@ -10,4 +10,4 @@
10
10
  * - logs: optional log excerpt
11
11
  * - context: optional extra context (what changed, when it started)
12
12
  */
13
- export declare const DEBUG_INCIDENT_SCRIPT = "export const meta = {\n name: 'debug_incident',\n description: 'Triage an error or log snippet with parallel hypotheses and ranked root-cause analysis.',\n whenToUse: 'User reports a bug, crash, error message, or unexpected behavior and wants systematic triage.',\n tags: ['debug', 'incident', 'troubleshooting'],\n estimatedAgents: { min: 7, max: 7 },\n phases: [\n { title: 'Triage' },\n { title: 'Hypotheses' },\n { title: 'Rank' },\n ],\n}\n\nconst READ_TOOLS = ['read_file', 'grep', 'find', 'list_dir', 'shell']\n\nconst error = args && typeof args === 'object' && args.error\n ? String(args.error)\n : 'Infer the primary error from the most recent user message or conversation context.'\n\nconst logs = args && typeof args === 'object' && args.logs\n ? String(args.logs)\n : ''\n\nconst context = args && typeof args === 'object' && args.context\n ? String(args.context)\n : ''\n\nphase('Triage')\nconst triage = await agent(\n 'Parse this incident signal. Extract: error type, likely subsystem, affected files/modules if identifiable, and 2\u20133 key facts from logs.\\n\\n' +\n 'ERROR:\\n' + error + '\\n\\n' +\n (logs ? 'LOGS:\\n' + logs + '\\n\\n' : '') +\n (context ? 'CONTEXT:\\n' + context + '\\n\\n' : '') +\n 'Use read/grep tools to locate relevant code if the workspace may contain the failing path.',\n {\n label: 'incident triage',\n toolset: READ_TOOLS,\n schema: {\n type: 'object',\n properties: {\n errorType: { type: 'string' },\n subsystem: { type: 'string' },\n affectedPaths: { type: 'array', items: { type: 'string' } },\n keyFacts: { type: 'array', items: { type: 'string' } },\n },\n required: ['errorType', 'keyFacts'],\n },\n },\n)\n\nconst HYPOTHESES = [\n { key: 'config', angle: 'Misconfiguration, missing env vars, wrong defaults, feature flags, stale config cache.' },\n { key: 'race', angle: 'Concurrency, timing, ordering, partial failure under load, missing locks or awaits.' },\n { key: 'dependency', angle: 'Version mismatch, breaking upstream change, network/API failure, timeout, auth expiry.' },\n { key: 'data', angle: 'Bad input, schema drift, null/empty edge case, corrupt state, migration gap.' },\n { key: 'environment', angle: 'OS, permissions, disk, memory, container/network isolation, platform-specific behavior.' },\n]\n\nphase('Hypotheses')\nconst hypothesisReports = await parallel(\n HYPOTHESES.map((h) => () =>\n agent(\n 'Evaluate whether this hypothesis explains the incident. Search the codebase for supporting or refuting evidence.\\n\\n' +\n 'HYPOTHESIS: ' + h.key + ' \u2014 ' + h.angle + '\\n\\n' +\n 'TRIAGE:\\n' + JSON.stringify(triage, null, 2) + '\\n\\n' +\n 'ERROR:\\n' + error + '\\n\\n' +\n (logs ? 'LOGS:\\n' + logs + '\\n\\n' : '') +\n 'Return: likelihood (low/med/high), evidence (file paths + brief notes), and one verification step.',\n {\n label: h.key + ' hypothesis',\n toolset: READ_TOOLS,\n schema: {\n type: 'object',\n properties: {\n likelihood: { type: 'string', enum: ['low', 'med', 'high'] },\n evidence: {\n type: 'array',\n items: {\n type: 'object',\n properties: {\n path: { type: 'string' },\n note: { type: 'string' },\n },\n required: ['path', 'note'],\n },\n },\n verificationStep: { type: 'string' },\n },\n required: ['likelihood', 'evidence', 'verificationStep'],\n },\n },\n ),\n ),\n)\n\nphase('Rank')\nconst live = hypothesisReports.filter(Boolean)\nconst byHypothesis = {}\nfor (let i = 0; i < HYPOTHESES.length; i++) {\n byHypothesis[HYPOTHESES[i].key] = live[i] ?? null\n}\n\nconst ranking = await agent(\n 'Rank root causes by likelihood. Pick the top 3 with confidence and concrete next steps to confirm or fix.\\n\\n' +\n JSON.stringify({ triage, byHypothesis }, null, 2),\n {\n label: 'root cause ranking',\n schema: {\n type: 'object',\n properties: {\n topCauses: {\n type: 'array',\n items: {\n type: 'object',\n properties: {\n hypothesis: { type: 'string' },\n likelihood: { type: 'string', enum: ['low', 'med', 'high'] },\n summary: { type: 'string' },\n nextStep: { type: 'string' },\n },\n required: ['hypothesis', 'likelihood', 'summary', 'nextStep'],\n },\n },\n immediateActions: { type: 'array', items: { type: 'string' } },\n summary: { type: 'string' },\n },\n required: ['topCauses', 'summary'],\n },\n },\n)\n\nreturn {\n ok: true,\n triage,\n ...(ranking ?? { topCauses: [], summary: 'ranking failed', immediateActions: [] }),\n byHypothesis,\n}\n";
13
+ export declare const DEBUG_INCIDENT_SCRIPT = "export const meta = {\n name: 'debug_incident',\n description: 'Triage an error or log snippet with parallel hypotheses and ranked root-cause analysis.',\n whenToUse: 'User reports a bug, crash, error message, or unexpected behavior and wants systematic triage.',\n examplePrompts: [\n { field: 'error', text: 'Triage this stack trace from production' },\n { field: 'error', text: 'Why does the gateway return 502 after deploy?' },\n ],\n i18n: {\n zh: {\n description: '\u5BF9\u9519\u8BEF\u6216\u65E5\u5FD7\u7247\u6BB5\u505A\u5E76\u884C\u5047\u8BBE\u63A8\u6F14\uFF0C\u5E76\u6392\u5E8F\u6839\u56E0\u4E0E\u9A8C\u8BC1\u6B65\u9AA4\u3002',\n whenToUse: '\u7528\u6237\u62A5\u544A bug\u3001\u5D29\u6E83\u3001\u62A5\u9519\u6216\u5F02\u5E38\u884C\u4E3A\uFF0C\u9700\u8981\u7CFB\u7EDF\u5316\u6392\u67E5\u65F6\u3002',\n examplePrompts: [\n { field: 'error', text: '\u6392\u67E5\u751F\u4EA7\u73AF\u5883\u8FD9\u6761\u5806\u6808' },\n { field: 'error', text: '\u90E8\u7F72\u540E\u7F51\u5173\u8FD4\u56DE 502\uFF0C\u53EF\u80FD\u662F\u4EC0\u4E48\u539F\u56E0\uFF1F' },\n ],\n },\n },\n tags: ['debug', 'incident', 'troubleshooting'],\n estimatedAgents: { min: 7, max: 7 },\n phases: [\n { title: 'Triage' },\n { title: 'Hypotheses' },\n { title: 'Rank' },\n ],\n}\n\nconst READ_TOOLS = ['read_file', 'grep', 'find', 'list_dir', 'shell']\n\nconst error = args && typeof args === 'object' && args.error\n ? String(args.error)\n : 'Infer the primary error from the most recent user message or conversation context.'\n\nconst logs = args && typeof args === 'object' && args.logs\n ? String(args.logs)\n : ''\n\nconst context = args && typeof args === 'object' && args.context\n ? String(args.context)\n : ''\n\nphase('Triage')\nconst triage = await agent(\n 'Parse this incident signal. Extract: error type, likely subsystem, affected files/modules if identifiable, and 2\u20133 key facts from logs.\\n\\n' +\n 'ERROR:\\n' + error + '\\n\\n' +\n (logs ? 'LOGS:\\n' + logs + '\\n\\n' : '') +\n (context ? 'CONTEXT:\\n' + context + '\\n\\n' : '') +\n 'Use read/grep tools to locate relevant code if the workspace may contain the failing path.',\n {\n label: 'incident triage',\n toolset: READ_TOOLS,\n schema: {\n type: 'object',\n properties: {\n errorType: { type: 'string' },\n subsystem: { type: 'string' },\n affectedPaths: { type: 'array', items: { type: 'string' } },\n keyFacts: { type: 'array', items: { type: 'string' } },\n },\n required: ['errorType', 'keyFacts'],\n },\n },\n)\n\nconst HYPOTHESES = [\n { key: 'config', angle: 'Misconfiguration, missing env vars, wrong defaults, feature flags, stale config cache.' },\n { key: 'race', angle: 'Concurrency, timing, ordering, partial failure under load, missing locks or awaits.' },\n { key: 'dependency', angle: 'Version mismatch, breaking upstream change, network/API failure, timeout, auth expiry.' },\n { key: 'data', angle: 'Bad input, schema drift, null/empty edge case, corrupt state, migration gap.' },\n { key: 'environment', angle: 'OS, permissions, disk, memory, container/network isolation, platform-specific behavior.' },\n]\n\nphase('Hypotheses')\nconst hypothesisReports = await parallel(\n HYPOTHESES.map((h) => () =>\n agent(\n 'Evaluate whether this hypothesis explains the incident. Search the codebase for supporting or refuting evidence.\\n\\n' +\n 'HYPOTHESIS: ' + h.key + ' \u2014 ' + h.angle + '\\n\\n' +\n 'TRIAGE:\\n' + JSON.stringify(triage, null, 2) + '\\n\\n' +\n 'ERROR:\\n' + error + '\\n\\n' +\n (logs ? 'LOGS:\\n' + logs + '\\n\\n' : '') +\n 'Return: likelihood (low/med/high), evidence (file paths + brief notes), and one verification step.',\n {\n label: h.key + ' hypothesis',\n toolset: READ_TOOLS,\n schema: {\n type: 'object',\n properties: {\n likelihood: { type: 'string', enum: ['low', 'med', 'high'] },\n evidence: {\n type: 'array',\n items: {\n type: 'object',\n properties: {\n path: { type: 'string' },\n note: { type: 'string' },\n },\n required: ['path', 'note'],\n },\n },\n verificationStep: { type: 'string' },\n },\n required: ['likelihood', 'evidence', 'verificationStep'],\n },\n },\n ),\n ),\n)\n\nphase('Rank')\nconst live = hypothesisReports.filter(Boolean)\nconst byHypothesis = {}\nfor (let i = 0; i < HYPOTHESES.length; i++) {\n byHypothesis[HYPOTHESES[i].key] = live[i] ?? null\n}\n\nconst ranking = await agent(\n 'Rank root causes by likelihood. Pick the top 3 with confidence and concrete next steps to confirm or fix.\\n\\n' +\n JSON.stringify({ triage, byHypothesis }, null, 2),\n {\n label: 'root cause ranking',\n schema: {\n type: 'object',\n properties: {\n topCauses: {\n type: 'array',\n items: {\n type: 'object',\n properties: {\n hypothesis: { type: 'string' },\n likelihood: { type: 'string', enum: ['low', 'med', 'high'] },\n summary: { type: 'string' },\n nextStep: { type: 'string' },\n },\n required: ['hypothesis', 'likelihood', 'summary', 'nextStep'],\n },\n },\n immediateActions: { type: 'array', items: { type: 'string' } },\n summary: { type: 'string' },\n },\n required: ['topCauses', 'summary'],\n },\n },\n)\n\nreturn {\n ok: true,\n triage,\n ...(ranking ?? { topCauses: [], summary: 'ranking failed', immediateActions: [] }),\n byHypothesis,\n}\n";
@@ -15,6 +15,20 @@ const DEBUG_INCIDENT_SCRIPT = `export const meta = {
15
15
  name: 'debug_incident',
16
16
  description: 'Triage an error or log snippet with parallel hypotheses and ranked root-cause analysis.',
17
17
  whenToUse: 'User reports a bug, crash, error message, or unexpected behavior and wants systematic triage.',
18
+ examplePrompts: [
19
+ { field: 'error', text: 'Triage this stack trace from production' },
20
+ { field: 'error', text: 'Why does the gateway return 502 after deploy?' },
21
+ ],
22
+ i18n: {
23
+ zh: {
24
+ description: '对错误或日志片段做并行假设推演,并排序根因与验证步骤。',
25
+ whenToUse: '用户报告 bug、崩溃、报错或异常行为,需要系统化排查时。',
26
+ examplePrompts: [
27
+ { field: 'error', text: '排查生产环境这条堆栈' },
28
+ { field: 'error', text: '部署后网关返回 502,可能是什么原因?' },
29
+ ],
30
+ },
31
+ },
18
32
  tags: ['debug', 'incident', 'troubleshooting'],
19
33
  estimatedAgents: { min: 7, max: 7 },
20
34
  phases: [