@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
@@ -1 +1 @@
1
- {"version":3,"file":"mcp-transport.js","names":["undiciFetch"],"sources":["../../../../src/agent/mcp/mcp-transport.ts"],"sourcesContent":["import {\n SSEClientTransport,\n type SSEClientTransportOptions,\n} from \"@modelcontextprotocol/sdk/client/sse.js\";\nimport { StreamableHTTPClientTransport } from \"@modelcontextprotocol/sdk/client/streamableHttp.js\";\nimport type { FetchLike, Transport } from \"@modelcontextprotocol/sdk/shared/transport.js\";\nimport { fetch as undiciFetch } from \"undici\";\nimport { createLogger } from \"../../utils/logger.js\";\nconst log = createLogger(\"McpTransport\");\nimport { normalizeOptionalString } from \"../../utils/string-coerce.js\";\nimport { XopcStdioClientTransport } from \"./mcp-stdio-transport.js\";\nimport { resolveMcpTransportConfig } from \"./mcp-transport-config.js\";\n\nexport type ResolvedMcpTransport = {\n transport: Transport;\n description: string;\n transportType: \"stdio\" | \"sse\" | \"streamable-http\";\n connectionTimeoutMs: number;\n detachStderr?: () => void;\n};\n\nfunction attachStderrLogging(serverName: string, transport: XopcStdioClientTransport) {\n const stderr = transport.stderr;\n if (!stderr || typeof stderr.on !== \"function\") {\n return undefined;\n }\n const onData = (chunk: Buffer | string) => {\n const message =\n normalizeOptionalString(typeof chunk === \"string\" ? chunk : String(chunk)) ?? \"\";\n if (!message) {\n return;\n }\n for (const line of message.split(/\\r?\\n/)) {\n const trimmed = line.trim();\n if (trimmed) {\n log.debug(`bundle-mcp:${serverName}: ${trimmed}`);\n }\n }\n };\n stderr.on(\"data\", onData);\n return () => {\n if (typeof stderr.off === \"function\") {\n stderr.off(\"data\", onData);\n } else if (typeof stderr.removeListener === \"function\") {\n stderr.removeListener(\"data\", onData);\n }\n };\n}\n\ntype SseEventSourceFetch = NonNullable<\n NonNullable<SSEClientTransportOptions[\"eventSourceInit\"]>[\"fetch\"]\n>;\n\nconst fetchWithUndici: FetchLike = async (url, init) =>\n (await undiciFetch(url, init as unknown as Parameters<typeof undiciFetch>[1])) as unknown as Response;\n\nfunction buildSseEventSourceFetch(headers: Record<string, string>): SseEventSourceFetch {\n return (url: string | URL, init?: RequestInit) => {\n const sdkHeaders: Record<string, string> = {};\n if (init?.headers) {\n if (init.headers instanceof Headers) {\n init.headers.forEach((value, key) => {\n sdkHeaders[key] = value;\n });\n } else {\n Object.assign(sdkHeaders, init.headers);\n }\n }\n return fetchWithUndici(url, {\n ...(init as RequestInit),\n headers: { ...sdkHeaders, ...headers },\n }) as ReturnType<SseEventSourceFetch>;\n };\n}\n\nexport function resolveMcpTransport(\n serverName: string,\n rawServer: unknown,\n): ResolvedMcpTransport | null {\n const resolved = resolveMcpTransportConfig(serverName, rawServer);\n if (!resolved) {\n return null;\n }\n if (resolved.kind === \"stdio\") {\n const transport = new XopcStdioClientTransport({\n command: resolved.command,\n args: resolved.args,\n env: resolved.env,\n cwd: resolved.cwd,\n stderr: \"pipe\",\n });\n return {\n transport,\n description: resolved.description,\n transportType: \"stdio\",\n connectionTimeoutMs: resolved.connectionTimeoutMs,\n detachStderr: attachStderrLogging(serverName, transport),\n };\n }\n if (resolved.transportType === \"streamable-http\") {\n return {\n transport: new StreamableHTTPClientTransport(new URL(resolved.url), {\n requestInit: resolved.headers ? { headers: resolved.headers } : undefined,\n }),\n description: resolved.description,\n transportType: \"streamable-http\",\n connectionTimeoutMs: resolved.connectionTimeoutMs,\n };\n }\n const headers: Record<string, string> = {\n ...resolved.headers,\n };\n const hasHeaders = Object.keys(headers).length > 0;\n return {\n transport: new SSEClientTransport(new URL(resolved.url), {\n requestInit: hasHeaders ? { headers } : undefined,\n fetch: fetchWithUndici,\n eventSourceInit: { fetch: buildSseEventSourceFetch(headers) },\n }),\n description: resolved.description,\n transportType: \"sse\",\n connectionTimeoutMs: resolved.connectionTimeoutMs,\n };\n}\n"],"mappings":";;;;;;;;;aAOqD;AACrD,MAAM,MAAM,aAAa,eAAe;AAaxC,SAAS,oBAAoB,YAAoB,WAAqC;CACpF,MAAM,SAAS,UAAU;AACzB,KAAI,CAAC,UAAU,OAAO,OAAO,OAAO,WAClC;CAEF,MAAM,UAAU,UAA2B;EACzC,MAAM,UACJ,wBAAwB,OAAO,UAAU,WAAW,QAAQ,OAAO,MAAM,CAAC,IAAI;AAChF,MAAI,CAAC,QACH;AAEF,OAAK,MAAM,QAAQ,QAAQ,MAAM,QAAQ,EAAE;GACzC,MAAM,UAAU,KAAK,MAAM;AAC3B,OAAI,QACF,KAAI,MAAM,cAAc,WAAW,IAAI,UAAU;;;AAIvD,QAAO,GAAG,QAAQ,OAAO;AACzB,cAAa;AACX,MAAI,OAAO,OAAO,QAAQ,WACxB,QAAO,IAAI,QAAQ,OAAO;WACjB,OAAO,OAAO,mBAAmB,WAC1C,QAAO,eAAe,QAAQ,OAAO;;;AAS3C,MAAM,kBAA6B,OAAO,KAAK,SAC5C,MAAMA,MAAY,KAAK,KAAqD;AAE/E,SAAS,yBAAyB,SAAsD;AACtF,SAAQ,KAAmB,SAAuB;EAChD,MAAM,aAAqC,EAAE;AAC7C,MAAI,MAAM,QACR,KAAI,KAAK,mBAAmB,QAC1B,MAAK,QAAQ,SAAS,OAAO,QAAQ;AACnC,cAAW,OAAO;IAClB;MAEF,QAAO,OAAO,YAAY,KAAK,QAAQ;AAG3C,SAAO,gBAAgB,KAAK;GAC1B,GAAI;GACJ,SAAS;IAAE,GAAG;IAAY,GAAG;IAAS;GACvC,CAAC;;;AAIN,SAAgB,oBACd,YACA,WAC6B;CAC7B,MAAM,WAAW,0BAA0B,YAAY,UAAU;AACjE,KAAI,CAAC,SACH,QAAO;AAET,KAAI,SAAS,SAAS,SAAS;EAC7B,MAAM,YAAY,IAAI,yBAAyB;GAC7C,SAAS,SAAS;GAClB,MAAM,SAAS;GACf,KAAK,SAAS;GACd,KAAK,SAAS;GACd,QAAQ;GACT,CAAC;AACF,SAAO;GACL;GACA,aAAa,SAAS;GACtB,eAAe;GACf,qBAAqB,SAAS;GAC9B,cAAc,oBAAoB,YAAY,UAAU;GACzD;;AAEH,KAAI,SAAS,kBAAkB,kBAC7B,QAAO;EACL,WAAW,IAAI,8BAA8B,IAAI,IAAI,SAAS,IAAI,EAAE,EAClE,aAAa,SAAS,UAAU,EAAE,SAAS,SAAS,SAAS,GAAG,KAAA,GACjE,CAAC;EACF,aAAa,SAAS;EACtB,eAAe;EACf,qBAAqB,SAAS;EAC/B;CAEH,MAAM,UAAkC,EACtC,GAAG,SAAS,SACb;CACD,MAAM,aAAa,OAAO,KAAK,QAAQ,CAAC,SAAS;AACjD,QAAO;EACL,WAAW,IAAI,mBAAmB,IAAI,IAAI,SAAS,IAAI,EAAE;GACvD,aAAa,aAAa,EAAE,SAAS,GAAG,KAAA;GACxC,OAAO;GACP,iBAAiB,EAAE,OAAO,yBAAyB,QAAQ,EAAE;GAC9D,CAAC;EACF,aAAa,SAAS;EACtB,eAAe;EACf,qBAAqB,SAAS;EAC/B"}
1
+ {"version":3,"file":"mcp-transport.js","names":["undiciFetch"],"sources":["../../../../src/agent/mcp/mcp-transport.ts"],"sourcesContent":["import {\n SSEClientTransport,\n type SSEClientTransportOptions,\n} from \"@modelcontextprotocol/sdk/client/sse.js\";\nimport { StreamableHTTPClientTransport } from \"@modelcontextprotocol/sdk/client/streamableHttp.js\";\nimport type { FetchLike, Transport } from \"@modelcontextprotocol/sdk/shared/transport.js\";\nimport { fetch as undiciFetch } from \"undici\";\nimport { createLogger } from \"../../utils/logger.js\";\nconst log = createLogger(\"McpTransport\");\nimport { normalizeOptionalString } from \"../../utils/string-coerce.js\";\nimport { XopcStdioClientTransport } from \"./mcp-stdio-transport.js\";\nimport { resolveMcpTransportConfig } from \"./mcp-transport-config.js\";\n\nexport type ResolvedMcpTransport = {\n transport: Transport;\n description: string;\n transportType: \"stdio\" | \"sse\" | \"streamable-http\";\n connectionTimeoutMs: number;\n detachStderr?: () => void;\n};\n\nfunction attachStderrLogging(serverName: string, transport: XopcStdioClientTransport) {\n const stderr = transport.stderr;\n if (!stderr || typeof stderr.on !== \"function\") {\n return undefined;\n }\n const onData = (chunk: Buffer | string) => {\n const message =\n normalizeOptionalString(typeof chunk === \"string\" ? chunk : String(chunk)) ?? \"\";\n if (!message) {\n return;\n }\n for (const line of message.split(/\\r?\\n/)) {\n const trimmed = line.trim();\n if (trimmed) {\n log.debug(`bundle-mcp:${serverName}: ${trimmed}`);\n }\n }\n };\n stderr.on(\"data\", onData);\n return () => {\n if (typeof stderr.off === \"function\") {\n stderr.off(\"data\", onData);\n } else if (typeof stderr.removeListener === \"function\") {\n stderr.removeListener(\"data\", onData);\n }\n };\n}\n\ntype SseEventSourceFetch = NonNullable<\n NonNullable<SSEClientTransportOptions[\"eventSourceInit\"]>[\"fetch\"]\n>;\n\nconst fetchWithUndici: FetchLike = async (url, init) =>\n (await undiciFetch(url, init as unknown as Parameters<typeof undiciFetch>[1])) as unknown as Response;\n\nfunction buildSseEventSourceFetch(headers: Record<string, string>): SseEventSourceFetch {\n return (url: string | URL, init?: RequestInit) => {\n const sdkHeaders: Record<string, string> = {};\n if (init?.headers) {\n if (init.headers instanceof Headers) {\n init.headers.forEach((value, key) => {\n sdkHeaders[key] = value;\n });\n } else {\n Object.assign(sdkHeaders, init.headers);\n }\n }\n return fetchWithUndici(url, {\n ...(init as RequestInit),\n headers: { ...sdkHeaders, ...headers },\n }) as ReturnType<SseEventSourceFetch>;\n };\n}\n\nexport function resolveMcpTransport(\n serverName: string,\n rawServer: unknown,\n): ResolvedMcpTransport | null {\n const resolved = resolveMcpTransportConfig(serverName, rawServer);\n if (!resolved) {\n return null;\n }\n if (resolved.kind === \"stdio\") {\n const transport = new XopcStdioClientTransport({\n command: resolved.command,\n args: resolved.args,\n env: resolved.env,\n cwd: resolved.cwd,\n stderr: \"pipe\",\n });\n return {\n transport,\n description: resolved.description,\n transportType: \"stdio\",\n connectionTimeoutMs: resolved.connectionTimeoutMs,\n detachStderr: attachStderrLogging(serverName, transport),\n };\n }\n if (resolved.transportType === \"streamable-http\") {\n return {\n transport: new StreamableHTTPClientTransport(new URL(resolved.url), {\n requestInit: resolved.headers ? { headers: resolved.headers } : undefined,\n }),\n description: resolved.description,\n transportType: \"streamable-http\",\n connectionTimeoutMs: resolved.connectionTimeoutMs,\n };\n }\n const headers: Record<string, string> = {\n ...resolved.headers,\n };\n const hasHeaders = Object.keys(headers).length > 0;\n return {\n transport: new SSEClientTransport(new URL(resolved.url), {\n requestInit: hasHeaders ? { headers } : undefined,\n fetch: fetchWithUndici,\n eventSourceInit: { fetch: buildSseEventSourceFetch(headers) },\n }),\n description: resolved.description,\n transportType: \"sse\",\n connectionTimeoutMs: resolved.connectionTimeoutMs,\n };\n}\n"],"mappings":";;;;;;;;;aAOqD;oBAEkB;AADvE,MAAM,MAAM,aAAa,eAAe;AAaxC,SAAS,oBAAoB,YAAoB,WAAqC;CACpF,MAAM,SAAS,UAAU;AACzB,KAAI,CAAC,UAAU,OAAO,OAAO,OAAO,WAClC;CAEF,MAAM,UAAU,UAA2B;EACzC,MAAM,UACJ,wBAAwB,OAAO,UAAU,WAAW,QAAQ,OAAO,MAAM,CAAC,IAAI;AAChF,MAAI,CAAC,QACH;AAEF,OAAK,MAAM,QAAQ,QAAQ,MAAM,QAAQ,EAAE;GACzC,MAAM,UAAU,KAAK,MAAM;AAC3B,OAAI,QACF,KAAI,MAAM,cAAc,WAAW,IAAI,UAAU;;;AAIvD,QAAO,GAAG,QAAQ,OAAO;AACzB,cAAa;AACX,MAAI,OAAO,OAAO,QAAQ,WACxB,QAAO,IAAI,QAAQ,OAAO;WACjB,OAAO,OAAO,mBAAmB,WAC1C,QAAO,eAAe,QAAQ,OAAO;;;AAS3C,MAAM,kBAA6B,OAAO,KAAK,SAC5C,MAAMA,MAAY,KAAK,KAAqD;AAE/E,SAAS,yBAAyB,SAAsD;AACtF,SAAQ,KAAmB,SAAuB;EAChD,MAAM,aAAqC,EAAE;AAC7C,MAAI,MAAM,QACR,KAAI,KAAK,mBAAmB,QAC1B,MAAK,QAAQ,SAAS,OAAO,QAAQ;AACnC,cAAW,OAAO;IAClB;MAEF,QAAO,OAAO,YAAY,KAAK,QAAQ;AAG3C,SAAO,gBAAgB,KAAK;GAC1B,GAAI;GACJ,SAAS;IAAE,GAAG;IAAY,GAAG;IAAS;GACvC,CAAC;;;AAIN,SAAgB,oBACd,YACA,WAC6B;CAC7B,MAAM,WAAW,0BAA0B,YAAY,UAAU;AACjE,KAAI,CAAC,SACH,QAAO;AAET,KAAI,SAAS,SAAS,SAAS;EAC7B,MAAM,YAAY,IAAI,yBAAyB;GAC7C,SAAS,SAAS;GAClB,MAAM,SAAS;GACf,KAAK,SAAS;GACd,KAAK,SAAS;GACd,QAAQ;GACT,CAAC;AACF,SAAO;GACL;GACA,aAAa,SAAS;GACtB,eAAe;GACf,qBAAqB,SAAS;GAC9B,cAAc,oBAAoB,YAAY,UAAU;GACzD;;AAEH,KAAI,SAAS,kBAAkB,kBAC7B,QAAO;EACL,WAAW,IAAI,8BAA8B,IAAI,IAAI,SAAS,IAAI,EAAE,EAClE,aAAa,SAAS,UAAU,EAAE,SAAS,SAAS,SAAS,GAAG,KAAA,GACjE,CAAC;EACF,aAAa,SAAS;EACtB,eAAe;EACf,qBAAqB,SAAS;EAC/B;CAEH,MAAM,UAAkC,EACtC,GAAG,SAAS,SACb;CACD,MAAM,aAAa,OAAO,KAAK,QAAQ,CAAC,SAAS;AACjD,QAAO;EACL,WAAW,IAAI,mBAAmB,IAAI,IAAI,SAAS,IAAI,EAAE;GACvD,aAAa,aAAa,EAAE,SAAS,GAAG,KAAA;GACxC,OAAO;GACP,iBAAiB,EAAE,OAAO,yBAAyB,QAAQ,EAAE;GAC9D,CAAC;EACF,aAAa,SAAS;EACtB,eAAe;EACf,qBAAqB,SAAS;EAC/B"}
@@ -55,16 +55,9 @@ function safeListProviders(fn, cfg) {
55
55
  return [];
56
56
  }
57
57
  }
58
- /**
59
- * Normalize an {@link AgentModelConfig} (which may be a bare string for
60
- * legacy configs) to an object with explicit `primary` / `fallbacks`.
61
- */
58
+ /** Normalize an {@link AgentModelConfig} to `{ primary?, fallbacks }`. */
62
59
  function normalizeModelConfig(cfg) {
63
- if (cfg === void 0 || cfg === null) return { fallbacks: [] };
64
- if (typeof cfg === "string") return {
65
- primary: cfg,
66
- fallbacks: []
67
- };
60
+ if (!cfg) return { fallbacks: [] };
68
61
  return {
69
62
  primary: typeof cfg.primary === "string" ? cfg.primary : void 0,
70
63
  fallbacks: Array.isArray(cfg.fallbacks) ? cfg.fallbacks.filter((s) => typeof s === "string") : []
@@ -1 +1 @@
1
- {"version":3,"file":"runtime-shared.js","names":[],"sources":["../../../../src/agent/media-generation/runtime-shared.ts"],"sourcesContent":["/**\n * Cross-capability runtime helpers shared by image / audio / video\n * generation. Pure functions (no IO) so they can be unit-tested without\n * touching providers.\n *\n * - candidate model resolution\n * - geometry/value nearest-neighbour matching\n * - terminal failure aggregation (FailoverError)\n * - \"no model configured\" message builder\n */\n\nimport type { Config, AgentModelConfig } from '../../config/schema.js';\nimport {\n classifyAttemptError,\n FailoverError,\n type FallbackAttempt,\n type FailoverReason,\n} from '../failover-error.js';\nimport { parseCapabilityModelRef, type ParsedCapabilityModelRef } from './model-ref.js';\n\n// ============================================\n// Candidate resolution\n// ============================================\n\nexport interface CapabilityProviderCandidate {\n id: string;\n aliases?: readonly string[];\n defaultModel?: string | null;\n models?: readonly string[];\n isConfigured?: (ctx: { cfg?: Config; agentDir?: string }) => boolean;\n}\n\nexport interface ResolveCapabilityModelCandidatesParams {\n cfg?: Config;\n /** Active capability model config, e.g. cfg.agents.defaults.imageGenerationModel. */\n modelConfig: AgentModelConfig | undefined;\n /** Caller-supplied per-call override (highest priority). */\n modelOverride?: string;\n /** Optional ref parser; defaults to {@link parseCapabilityModelRef}. */\n parseModelRef?: (raw: string | undefined) => ParsedCapabilityModelRef | null;\n agentDir?: string;\n /** Snapshot of registered providers used to enumerate fallbacks. */\n listProviders: (cfg?: Config) => CapabilityProviderCandidate[];\n /**\n * When true and the explicit candidates fail, append every configured\n * provider's default model.\n */\n autoProviderFallback?: boolean;\n}\n\nexport interface ResolvedCapabilityModelCandidate {\n provider: string;\n model: string;\n}\n\n/**\n * Build the ordered candidate list from:\n * 1. modelOverride\n * 2. modelConfig.primary\n * 3. modelConfig.fallbacks[]\n * 4. (optional) every isConfigured() provider's defaultModel\n *\n * Duplicates are dropped (case-insensitive on provider, exact on model).\n */\nexport function resolveCapabilityModelCandidates(\n params: ResolveCapabilityModelCandidatesParams,\n): ResolvedCapabilityModelCandidate[] {\n const parse = params.parseModelRef ?? parseCapabilityModelRef;\n const out: ResolvedCapabilityModelCandidate[] = [];\n const seen = new Set<string>();\n\n const push = (raw: string | undefined) => {\n const parsed = parse(raw);\n if (!parsed) return;\n const key = `${parsed.provider}::${parsed.model}`;\n if (seen.has(key)) return;\n seen.add(key);\n out.push({ provider: parsed.provider, model: parsed.model });\n };\n\n const normalizedModelConfig = normalizeModelConfig(params.modelConfig);\n push(params.modelOverride);\n push(normalizedModelConfig.primary);\n for (const fb of normalizedModelConfig.fallbacks) push(fb);\n\n if (params.autoProviderFallback) {\n const providers = safeListProviders(params.listProviders, params.cfg);\n for (const provider of providers) {\n if (!provider.defaultModel) continue;\n let configured = true;\n try {\n configured = provider.isConfigured?.({ cfg: params.cfg, agentDir: params.agentDir }) ?? true;\n } catch {\n configured = false;\n }\n if (!configured) continue;\n push(`${provider.id}/${provider.defaultModel}`);\n }\n }\n\n return out;\n}\n\nfunction safeListProviders(\n fn: (cfg?: Config) => CapabilityProviderCandidate[],\n cfg?: Config,\n): CapabilityProviderCandidate[] {\n try {\n return fn(cfg) ?? [];\n } catch {\n return [];\n }\n}\n\n/**\n * Normalize an {@link AgentModelConfig} (which may be a bare string for\n * legacy configs) to an object with explicit `primary` / `fallbacks`.\n */\nfunction normalizeModelConfig(\n cfg: AgentModelConfig | undefined,\n): { primary?: string; fallbacks: string[] } {\n if (cfg === undefined || cfg === null) return { fallbacks: [] };\n if (typeof cfg === 'string') return { primary: cfg, fallbacks: [] };\n return {\n primary: typeof cfg.primary === 'string' ? cfg.primary : undefined,\n fallbacks: Array.isArray(cfg.fallbacks) ? cfg.fallbacks.filter((s): s is string => typeof s === 'string') : [],\n };\n}\n\n// ============================================\n// Geometry helpers (nearest-neighbour)\n// ============================================\n\nexport function resolveClosestSize(params: {\n requestedSize?: string;\n requestedAspectRatio?: string;\n supportedSizes?: ReadonlyArray<string>;\n}): string | undefined {\n const supported = (params.supportedSizes ?? []).filter((s) => parseSize(s) !== null);\n if (supported.length === 0) return undefined;\n\n const target =\n parseSize(params.requestedSize) ??\n sizeFromAspectRatio(params.requestedAspectRatio, supported.map((s) => parseSize(s)!.totalPixels));\n\n if (!target) return supported[0];\n return supported\n .map((s) => ({ s, parsed: parseSize(s)! }))\n .reduce((best, cur) => {\n const score = sizeDistance(target, cur.parsed);\n return score < best.score ? { s: cur.s, score } : best;\n }, { s: supported[0], score: Number.POSITIVE_INFINITY })\n .s;\n}\n\nexport function resolveClosestAspectRatio(params: {\n requestedAspectRatio?: string;\n requestedSize?: string;\n supportedAspectRatios?: ReadonlyArray<string>;\n}): string | undefined {\n const supported = (params.supportedAspectRatios ?? []).filter((r) => parseAspectRatio(r) !== null);\n if (supported.length === 0) return undefined;\n\n const targetRatio =\n parseAspectRatio(params.requestedAspectRatio)?.value ??\n (() => {\n const sz = parseSize(params.requestedSize);\n return sz ? sz.width / sz.height : undefined;\n })();\n\n if (typeof targetRatio !== 'number' || !Number.isFinite(targetRatio)) {\n return supported[0];\n }\n\n return supported.reduce((best, cur) => {\n const v = parseAspectRatio(cur)!.value;\n const d = Math.abs(Math.log(v) - Math.log(targetRatio));\n return d < best.score ? { s: cur, score: d } : best;\n }, { s: supported[0], score: Number.POSITIVE_INFINITY }).s;\n}\n\nexport function resolveClosestResolution<T extends string>(params: {\n requestedResolution?: T;\n supportedResolutions?: ReadonlyArray<T>;\n}): T | undefined {\n const supported = params.supportedResolutions ?? [];\n if (supported.length === 0) return undefined;\n const requested = params.requestedResolution;\n if (!requested) return undefined;\n if (supported.includes(requested)) return requested;\n\n const order = ['1K', '2K', '4K', '8K'];\n const want = order.indexOf(String(requested));\n if (want < 0) return supported[0];\n\n // Prefer the largest supported value <= requested; otherwise pick the smallest available.\n const ranked = supported\n .map((r) => ({ r, idx: order.indexOf(String(r)) }))\n .filter((x) => x.idx >= 0)\n .sort((a, b) => a.idx - b.idx);\n if (ranked.length === 0) return supported[0];\n\n let chosen = ranked[0].r;\n for (const x of ranked) {\n if (x.idx <= want) chosen = x.r;\n }\n return chosen;\n}\n\nfunction parseSize(raw: string | undefined): { width: number; height: number; totalPixels: number } | null {\n if (typeof raw !== 'string') return null;\n const m = raw.trim().toLowerCase().match(/^(\\d{2,5})\\s*[x×*]\\s*(\\d{2,5})$/);\n if (!m) return null;\n const width = Number(m[1]);\n const height = Number(m[2]);\n if (!Number.isFinite(width) || !Number.isFinite(height) || width <= 0 || height <= 0) return null;\n return { width, height, totalPixels: width * height };\n}\n\nfunction parseAspectRatio(raw: string | undefined): { value: number } | null {\n if (typeof raw !== 'string') return null;\n const m = raw.trim().match(/^(\\d{1,3})\\s*[:x×/]\\s*(\\d{1,3})$/);\n if (!m) return null;\n const w = Number(m[1]);\n const h = Number(m[2]);\n if (!Number.isFinite(w) || !Number.isFinite(h) || w <= 0 || h <= 0) return null;\n return { value: w / h };\n}\n\nfunction sizeFromAspectRatio(\n ratioStr: string | undefined,\n pixelHints: number[],\n): { width: number; height: number; totalPixels: number } | null {\n const r = parseAspectRatio(ratioStr);\n if (!r) return null;\n const pixels = pixelHints.length > 0 ? Math.round(pixelHints.reduce((a, b) => a + b, 0) / pixelHints.length) : 1024 * 1024;\n const height = Math.round(Math.sqrt(pixels / r.value));\n const width = Math.round(height * r.value);\n return { width, height, totalPixels: width * height };\n}\n\nfunction sizeDistance(\n a: { width: number; height: number; totalPixels: number },\n b: { width: number; height: number; totalPixels: number },\n): number {\n // Combined area + aspect-ratio difference (log-scale on both for stability).\n const areaDelta = Math.abs(Math.log(a.totalPixels) - Math.log(b.totalPixels));\n const ratioA = a.width / a.height;\n const ratioB = b.width / b.height;\n const ratioDelta = Math.abs(Math.log(ratioA) - Math.log(ratioB));\n return areaDelta + ratioDelta * 1.5;\n}\n\n// ============================================\n// Failure aggregation\n// ============================================\n\nexport interface RecordCapabilityCandidateFailureParams {\n attempts: FallbackAttempt[];\n provider: string;\n model: string;\n error: unknown;\n durationMs?: number;\n}\n\n/** Push a structured {@link FallbackAttempt} entry derived from `error`. */\nexport function recordCapabilityCandidateFailure(\n params: RecordCapabilityCandidateFailureParams,\n): FallbackAttempt {\n const cls = classifyAttemptError(params.error);\n const attempt: FallbackAttempt = {\n provider: params.provider,\n model: params.model,\n error: cls.message,\n reason: cls.reason,\n ...(cls.status !== undefined ? { status: cls.status } : {}),\n ...(cls.code !== undefined ? { code: cls.code } : {}),\n ...(params.durationMs !== undefined ? { durationMs: params.durationMs } : {}),\n };\n params.attempts.push(attempt);\n return attempt;\n}\n\nexport interface ThrowCapabilityGenerationFailureParams {\n capabilityLabel: string;\n attempts: FallbackAttempt[];\n lastError: unknown;\n}\n\n/** Throw a unified {@link FailoverError} after all candidates have been exhausted. */\nexport function throwCapabilityGenerationFailure(params: ThrowCapabilityGenerationFailureParams): never {\n // capabilityLabel like \"image generation\" → identifier \"image-generation\"\n const capability = params.capabilityLabel.trim().toLowerCase().replace(/\\s+/g, '-') || 'capability';\n throw new FailoverError({\n capability,\n attempts: params.attempts,\n cause: params.lastError,\n });\n}\n\n// ============================================\n// \"No model configured\" message\n// ============================================\n\nexport interface BuildNoCapabilityModelConfiguredMessageParams {\n /** Display label, e.g. \"image-generation\". */\n capabilityLabel: string;\n /** Config key path, e.g. \"imageGenerationModel\". */\n modelConfigKey: string;\n providers: ReadonlyArray<CapabilityProviderCandidate>;\n /** Optional env-var lookup, e.g. (id) => PROVIDER_ENV_MAP[id]. */\n getProviderEnvVars?: (id: string) => readonly string[] | undefined;\n}\n\nexport function buildNoCapabilityModelConfiguredMessage(\n params: BuildNoCapabilityModelConfiguredMessageParams,\n): string {\n const lines: string[] = [\n `No ${params.capabilityLabel} model configured. Set agents.defaults.${params.modelConfigKey} ` +\n `to a \"<provider>/<model>\" value (or pass modelOverride at call site).`,\n ];\n if (params.providers.length > 0) {\n lines.push('Registered providers:');\n for (const p of params.providers) {\n const envs = params.getProviderEnvVars?.(p.id) ?? [];\n const env = envs.length > 0 ? ` (env: ${envs.join(' | ')})` : '';\n const def = p.defaultModel ? ` default=${p.defaultModel}` : '';\n lines.push(` - ${p.id}${def}${env}`);\n }\n }\n return lines.join('\\n');\n}\n\n/**\n * Build a `metadata.normalization` snapshot from a completed normalization\n * pass. Providers / runtime can spread it into their result metadata.\n */\nexport function buildMediaGenerationNormalizationMetadata(params: {\n normalization?: Record<string, unknown>;\n}): Record<string, unknown> {\n if (!params.normalization || Object.keys(params.normalization).length === 0) return {};\n return { normalization: params.normalization };\n}\n\n// Re-export the union for downstream type narrowing.\nexport type { FailoverReason };\n"],"mappings":"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"}
1
+ {"version":3,"file":"runtime-shared.js","names":[],"sources":["../../../../src/agent/media-generation/runtime-shared.ts"],"sourcesContent":["/**\n * Cross-capability runtime helpers shared by image / audio / video\n * generation. Pure functions (no IO) so they can be unit-tested without\n * touching providers.\n *\n * - candidate model resolution\n * - geometry/value nearest-neighbour matching\n * - terminal failure aggregation (FailoverError)\n * - \"no model configured\" message builder\n */\n\nimport type { Config, AgentModelConfig } from '../../config/schema.js';\nimport {\n classifyAttemptError,\n FailoverError,\n type FallbackAttempt,\n type FailoverReason,\n} from '../failover-error.js';\nimport { parseCapabilityModelRef, type ParsedCapabilityModelRef } from './model-ref.js';\n\n// ============================================\n// Candidate resolution\n// ============================================\n\nexport interface CapabilityProviderCandidate {\n id: string;\n aliases?: readonly string[];\n defaultModel?: string | null;\n models?: readonly string[];\n isConfigured?: (ctx: { cfg?: Config; agentDir?: string }) => boolean;\n}\n\nexport interface ResolveCapabilityModelCandidatesParams {\n cfg?: Config;\n /** Active capability model config, e.g. cfg.agents.defaults.imageGenerationModel. */\n modelConfig: AgentModelConfig | undefined;\n /** Caller-supplied per-call override (highest priority). */\n modelOverride?: string;\n /** Optional ref parser; defaults to {@link parseCapabilityModelRef}. */\n parseModelRef?: (raw: string | undefined) => ParsedCapabilityModelRef | null;\n agentDir?: string;\n /** Snapshot of registered providers used to enumerate fallbacks. */\n listProviders: (cfg?: Config) => CapabilityProviderCandidate[];\n /**\n * When true and the explicit candidates fail, append every configured\n * provider's default model.\n */\n autoProviderFallback?: boolean;\n}\n\nexport interface ResolvedCapabilityModelCandidate {\n provider: string;\n model: string;\n}\n\n/**\n * Build the ordered candidate list from:\n * 1. modelOverride\n * 2. modelConfig.primary\n * 3. modelConfig.fallbacks[]\n * 4. (optional) every isConfigured() provider's defaultModel\n *\n * Duplicates are dropped (case-insensitive on provider, exact on model).\n */\nexport function resolveCapabilityModelCandidates(\n params: ResolveCapabilityModelCandidatesParams,\n): ResolvedCapabilityModelCandidate[] {\n const parse = params.parseModelRef ?? parseCapabilityModelRef;\n const out: ResolvedCapabilityModelCandidate[] = [];\n const seen = new Set<string>();\n\n const push = (raw: string | undefined) => {\n const parsed = parse(raw);\n if (!parsed) return;\n const key = `${parsed.provider}::${parsed.model}`;\n if (seen.has(key)) return;\n seen.add(key);\n out.push({ provider: parsed.provider, model: parsed.model });\n };\n\n const normalizedModelConfig = normalizeModelConfig(params.modelConfig);\n push(params.modelOverride);\n push(normalizedModelConfig.primary);\n for (const fb of normalizedModelConfig.fallbacks) push(fb);\n\n if (params.autoProviderFallback) {\n const providers = safeListProviders(params.listProviders, params.cfg);\n for (const provider of providers) {\n if (!provider.defaultModel) continue;\n let configured = true;\n try {\n configured = provider.isConfigured?.({ cfg: params.cfg, agentDir: params.agentDir }) ?? true;\n } catch {\n configured = false;\n }\n if (!configured) continue;\n push(`${provider.id}/${provider.defaultModel}`);\n }\n }\n\n return out;\n}\n\nfunction safeListProviders(\n fn: (cfg?: Config) => CapabilityProviderCandidate[],\n cfg?: Config,\n): CapabilityProviderCandidate[] {\n try {\n return fn(cfg) ?? [];\n } catch {\n return [];\n }\n}\n\n/** Normalize an {@link AgentModelConfig} to `{ primary?, fallbacks }`. */\nfunction normalizeModelConfig(\n cfg: AgentModelConfig | undefined,\n): { primary?: string; fallbacks: string[] } {\n if (!cfg) return { fallbacks: [] };\n return {\n primary: typeof cfg.primary === 'string' ? cfg.primary : undefined,\n fallbacks: Array.isArray(cfg.fallbacks)\n ? cfg.fallbacks.filter((s): s is string => typeof s === 'string')\n : [],\n };\n}\n\n// ============================================\n// Geometry helpers (nearest-neighbour)\n// ============================================\n\nexport function resolveClosestSize(params: {\n requestedSize?: string;\n requestedAspectRatio?: string;\n supportedSizes?: ReadonlyArray<string>;\n}): string | undefined {\n const supported = (params.supportedSizes ?? []).filter((s) => parseSize(s) !== null);\n if (supported.length === 0) return undefined;\n\n const target =\n parseSize(params.requestedSize) ??\n sizeFromAspectRatio(params.requestedAspectRatio, supported.map((s) => parseSize(s)!.totalPixels));\n\n if (!target) return supported[0];\n return supported\n .map((s) => ({ s, parsed: parseSize(s)! }))\n .reduce((best, cur) => {\n const score = sizeDistance(target, cur.parsed);\n return score < best.score ? { s: cur.s, score } : best;\n }, { s: supported[0], score: Number.POSITIVE_INFINITY })\n .s;\n}\n\nexport function resolveClosestAspectRatio(params: {\n requestedAspectRatio?: string;\n requestedSize?: string;\n supportedAspectRatios?: ReadonlyArray<string>;\n}): string | undefined {\n const supported = (params.supportedAspectRatios ?? []).filter((r) => parseAspectRatio(r) !== null);\n if (supported.length === 0) return undefined;\n\n const targetRatio =\n parseAspectRatio(params.requestedAspectRatio)?.value ??\n (() => {\n const sz = parseSize(params.requestedSize);\n return sz ? sz.width / sz.height : undefined;\n })();\n\n if (typeof targetRatio !== 'number' || !Number.isFinite(targetRatio)) {\n return supported[0];\n }\n\n return supported.reduce((best, cur) => {\n const v = parseAspectRatio(cur)!.value;\n const d = Math.abs(Math.log(v) - Math.log(targetRatio));\n return d < best.score ? { s: cur, score: d } : best;\n }, { s: supported[0], score: Number.POSITIVE_INFINITY }).s;\n}\n\nexport function resolveClosestResolution<T extends string>(params: {\n requestedResolution?: T;\n supportedResolutions?: ReadonlyArray<T>;\n}): T | undefined {\n const supported = params.supportedResolutions ?? [];\n if (supported.length === 0) return undefined;\n const requested = params.requestedResolution;\n if (!requested) return undefined;\n if (supported.includes(requested)) return requested;\n\n const order = ['1K', '2K', '4K', '8K'];\n const want = order.indexOf(String(requested));\n if (want < 0) return supported[0];\n\n // Prefer the largest supported value <= requested; otherwise pick the smallest available.\n const ranked = supported\n .map((r) => ({ r, idx: order.indexOf(String(r)) }))\n .filter((x) => x.idx >= 0)\n .sort((a, b) => a.idx - b.idx);\n if (ranked.length === 0) return supported[0];\n\n let chosen = ranked[0].r;\n for (const x of ranked) {\n if (x.idx <= want) chosen = x.r;\n }\n return chosen;\n}\n\nfunction parseSize(raw: string | undefined): { width: number; height: number; totalPixels: number } | null {\n if (typeof raw !== 'string') return null;\n const m = raw.trim().toLowerCase().match(/^(\\d{2,5})\\s*[x×*]\\s*(\\d{2,5})$/);\n if (!m) return null;\n const width = Number(m[1]);\n const height = Number(m[2]);\n if (!Number.isFinite(width) || !Number.isFinite(height) || width <= 0 || height <= 0) return null;\n return { width, height, totalPixels: width * height };\n}\n\nfunction parseAspectRatio(raw: string | undefined): { value: number } | null {\n if (typeof raw !== 'string') return null;\n const m = raw.trim().match(/^(\\d{1,3})\\s*[:x×/]\\s*(\\d{1,3})$/);\n if (!m) return null;\n const w = Number(m[1]);\n const h = Number(m[2]);\n if (!Number.isFinite(w) || !Number.isFinite(h) || w <= 0 || h <= 0) return null;\n return { value: w / h };\n}\n\nfunction sizeFromAspectRatio(\n ratioStr: string | undefined,\n pixelHints: number[],\n): { width: number; height: number; totalPixels: number } | null {\n const r = parseAspectRatio(ratioStr);\n if (!r) return null;\n const pixels = pixelHints.length > 0 ? Math.round(pixelHints.reduce((a, b) => a + b, 0) / pixelHints.length) : 1024 * 1024;\n const height = Math.round(Math.sqrt(pixels / r.value));\n const width = Math.round(height * r.value);\n return { width, height, totalPixels: width * height };\n}\n\nfunction sizeDistance(\n a: { width: number; height: number; totalPixels: number },\n b: { width: number; height: number; totalPixels: number },\n): number {\n // Combined area + aspect-ratio difference (log-scale on both for stability).\n const areaDelta = Math.abs(Math.log(a.totalPixels) - Math.log(b.totalPixels));\n const ratioA = a.width / a.height;\n const ratioB = b.width / b.height;\n const ratioDelta = Math.abs(Math.log(ratioA) - Math.log(ratioB));\n return areaDelta + ratioDelta * 1.5;\n}\n\n// ============================================\n// Failure aggregation\n// ============================================\n\nexport interface RecordCapabilityCandidateFailureParams {\n attempts: FallbackAttempt[];\n provider: string;\n model: string;\n error: unknown;\n durationMs?: number;\n}\n\n/** Push a structured {@link FallbackAttempt} entry derived from `error`. */\nexport function recordCapabilityCandidateFailure(\n params: RecordCapabilityCandidateFailureParams,\n): FallbackAttempt {\n const cls = classifyAttemptError(params.error);\n const attempt: FallbackAttempt = {\n provider: params.provider,\n model: params.model,\n error: cls.message,\n reason: cls.reason,\n ...(cls.status !== undefined ? { status: cls.status } : {}),\n ...(cls.code !== undefined ? { code: cls.code } : {}),\n ...(params.durationMs !== undefined ? { durationMs: params.durationMs } : {}),\n };\n params.attempts.push(attempt);\n return attempt;\n}\n\nexport interface ThrowCapabilityGenerationFailureParams {\n capabilityLabel: string;\n attempts: FallbackAttempt[];\n lastError: unknown;\n}\n\n/** Throw a unified {@link FailoverError} after all candidates have been exhausted. */\nexport function throwCapabilityGenerationFailure(params: ThrowCapabilityGenerationFailureParams): never {\n // capabilityLabel like \"image generation\" → identifier \"image-generation\"\n const capability = params.capabilityLabel.trim().toLowerCase().replace(/\\s+/g, '-') || 'capability';\n throw new FailoverError({\n capability,\n attempts: params.attempts,\n cause: params.lastError,\n });\n}\n\n// ============================================\n// \"No model configured\" message\n// ============================================\n\nexport interface BuildNoCapabilityModelConfiguredMessageParams {\n /** Display label, e.g. \"image-generation\". */\n capabilityLabel: string;\n /** Config key path, e.g. \"imageGenerationModel\". */\n modelConfigKey: string;\n providers: ReadonlyArray<CapabilityProviderCandidate>;\n /** Optional env-var lookup, e.g. (id) => PROVIDER_ENV_MAP[id]. */\n getProviderEnvVars?: (id: string) => readonly string[] | undefined;\n}\n\nexport function buildNoCapabilityModelConfiguredMessage(\n params: BuildNoCapabilityModelConfiguredMessageParams,\n): string {\n const lines: string[] = [\n `No ${params.capabilityLabel} model configured. Set agents.defaults.${params.modelConfigKey} ` +\n `to a \"<provider>/<model>\" value (or pass modelOverride at call site).`,\n ];\n if (params.providers.length > 0) {\n lines.push('Registered providers:');\n for (const p of params.providers) {\n const envs = params.getProviderEnvVars?.(p.id) ?? [];\n const env = envs.length > 0 ? ` (env: ${envs.join(' | ')})` : '';\n const def = p.defaultModel ? ` default=${p.defaultModel}` : '';\n lines.push(` - ${p.id}${def}${env}`);\n }\n }\n return lines.join('\\n');\n}\n\n/**\n * Build a `metadata.normalization` snapshot from a completed normalization\n * pass. Providers / runtime can spread it into their result metadata.\n */\nexport function buildMediaGenerationNormalizationMetadata(params: {\n normalization?: Record<string, unknown>;\n}): Record<string, unknown> {\n if (!params.normalization || Object.keys(params.normalization).length === 0) return {};\n return { normalization: params.normalization };\n}\n\n// Re-export the union for downstream type narrowing.\nexport type { FailoverReason };\n"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
- import { join } from "node:path";
2
1
  import { existsSync, mkdirSync, readFileSync } from "node:fs";
3
2
  import { mkdir, readFile, rename, writeFile } from "node:fs/promises";
3
+ import { join } from "node:path";
4
4
  import lockfile from "proper-lockfile";
5
5
  //#region src/agent/memory/builtin-memory-store.ts
6
6
  /**
@@ -4,8 +4,8 @@ import { MEMORY_MD_FILENAME } from "./constants.js";
4
4
  import { clamp01, compareCandidatesByScore, computeCandidateScore, extractPromotionMarkers, isContaminatedSnippet, isExpiredEntry, isoDay, readFileLines, resolveDeepDefaults, sliceRange, snippetHash } from "./utils.js";
5
5
  import { loadDreamingStore, saveDreamingStore, withDreamingPromotionLock } from "./short-term-store.js";
6
6
  import { emptyDeepPhaseSkipped, writeDreamingDeepLastRun } from "./last-run.js";
7
- import path from "node:path";
8
7
  import fs from "node:fs/promises";
8
+ import path from "node:path";
9
9
  //#region src/agent/memory/dreaming/deep-promotion.ts
10
10
  init_logger();
11
11
  const log = createLogger("Dreaming:Deep");
@@ -1,6 +1,6 @@
1
1
  import { DREAMING_DIR_RELATIVE, DREAMING_EVENTS_LOG_RELATIVE } from "./constants.js";
2
- import path from "node:path";
3
2
  import fs from "node:fs/promises";
3
+ import path from "node:path";
4
4
  //#region src/agent/memory/dreaming/events.ts
5
5
  /**
6
6
  * Append a single event line to `memory/.dreams/events.jsonl`.
@@ -1,6 +1,6 @@
1
1
  import { DREAMING_LAST_RUN_RELATIVE } from "./constants.js";
2
- import path from "node:path";
3
2
  import fs from "node:fs/promises";
3
+ import path from "node:path";
4
4
  //#region src/agent/memory/dreaming/last-run.ts
5
5
  const DREAMING_LAST_RUN_FORMAT_VERSION = 2;
6
6
  function isRecord(v) {
@@ -4,8 +4,8 @@ import { DREAMING_DIR_RELATIVE } from "./constants.js";
4
4
  import { buildEntryKey, isoDay, normalizeMemoryPath, normalizeSnippetForHash, snippetHash } from "./utils.js";
5
5
  import { bumpEntryPhaseSignal, loadDreamingStore, saveDreamingStore } from "./short-term-store.js";
6
6
  import "./last-run.js";
7
- import path from "node:path";
8
7
  import fs from "node:fs/promises";
8
+ import path from "node:path";
9
9
  //#region src/agent/memory/dreaming/light-sweep.ts
10
10
  init_logger();
11
11
  const log = createLogger("Dreaming:Light");
@@ -1,8 +1,8 @@
1
1
  import { MEMORY_MD_FILENAME } from "./constants.js";
2
2
  import { clamp01, compareCandidatesByScore, computeCandidateScore, extractPromotionMarkers, isContaminatedSnippet, isExpiredEntry, readFileLines, resolveDeepDefaults, sliceRange, snippetHash } from "./utils.js";
3
3
  import { loadDreamingStore } from "./short-term-store.js";
4
- import path from "node:path";
5
4
  import fs from "node:fs/promises";
5
+ import path from "node:path";
6
6
  //#region src/agent/memory/dreaming/preview.ts
7
7
  async function previewDreamingDeepPromotion(params) {
8
8
  const cfg = resolveDeepDefaults(params.config);
@@ -4,8 +4,8 @@ import { DREAMING_DIR_RELATIVE, DREAMS_MD_FILENAME, MS_PER_DAY } from "./constan
4
4
  import { isoDay } from "./utils.js";
5
5
  import { bumpEntryPhaseSignal, loadDreamingStore, saveDreamingStore } from "./short-term-store.js";
6
6
  import "./last-run.js";
7
- import path from "node:path";
8
7
  import fs from "node:fs/promises";
8
+ import path from "node:path";
9
9
  //#region src/agent/memory/dreaming/rem-patterns.ts
10
10
  init_logger();
11
11
  const log = createLogger("Dreaming:REM");
@@ -2,9 +2,9 @@ import { createLogger } from "../../../utils/logger/index.js";
2
2
  import { init_logger } from "../../../utils/logger.js";
3
3
  import { SHORT_TERM_PROMOTION_LOCK_RELATIVE, SHORT_TERM_RECALL_STORE_RELATIVE } from "./constants.js";
4
4
  import { buildEntryKey, clamp01, isoDay, normalizeMemoryPath } from "./utils.js";
5
- import path from "node:path";
6
5
  import { createHash, randomUUID } from "node:crypto";
7
6
  import fs from "node:fs/promises";
7
+ import path from "node:path";
8
8
  //#region src/agent/memory/dreaming/short-term-store.ts
9
9
  init_logger();
10
10
  const log = createLogger("Dreaming:Store");
@@ -1,7 +1,7 @@
1
1
  import { DEFAULT_DEEP_CRON, DIVERSITY_WEIGHT, MS_PER_DAY, REINFORCEMENT_WEIGHT } from "./constants.js";
2
- import path from "node:path";
3
2
  import { createHash } from "node:crypto";
4
3
  import fs from "node:fs/promises";
4
+ import path from "node:path";
5
5
  //#region src/agent/memory/dreaming/utils.ts
6
6
  /** Normalize a workspace-relative memory path: forward slashes, no odd ../ escapes at start. */
7
7
  function normalizeMemoryPath(rel) {
@@ -1,5 +1,5 @@
1
- import { dirname, join } from "node:path";
2
1
  import { readdir, stat } from "node:fs/promises";
2
+ import { dirname, join } from "node:path";
3
3
  import { fileURLToPath } from "node:url";
4
4
  //#region src/agent/memory/plugin-discovery.ts
5
5
  async function discoverMemoryPlugins() {
@@ -29,6 +29,11 @@ export interface CommandHandlerConfig {
29
29
  switchModelForSession: (sessionKey: string, modelId: string) => Promise<boolean>;
30
30
  /** Drop in-memory agent after session file is cleared (e.g. /new) */
31
31
  invalidateAgentSession?: (sessionKey: string) => void;
32
+ /** Reset session in place (archive transcript, new session id; preserve overrides) */
33
+ resetSession?: (sessionKey: string) => Promise<{
34
+ sessionId: string;
35
+ previousSessionId: string;
36
+ } | null>;
32
37
  /** Cancel streaming preview + in-flight LLM work for this session (e.g. /abort) */
33
38
  abortSessionTurn?: (sessionKey: string) => Promise<void>;
34
39
  compactSession?: (sessionKey: string, options?: {
@@ -61,6 +66,7 @@ export declare class CommandHandler {
61
66
  private btwQuery?;
62
67
  private getSessionContextReport?;
63
68
  private getPersistentGoalApisForCommand;
69
+ private resetSession?;
64
70
  constructor(handlerConfig: CommandHandlerConfig);
65
71
  /** Replace config reference after hot reload or gateway PATCH so commands see current defaults. */
66
72
  updateAgentConfig(config: Config): void;
@@ -26,6 +26,7 @@ var CommandHandler = class {
26
26
  btwQuery;
27
27
  getSessionContextReport;
28
28
  getPersistentGoalApisForCommand;
29
+ resetSession;
29
30
  constructor(handlerConfig) {
30
31
  this.config = handlerConfig.config;
31
32
  this.bus = handlerConfig.bus;
@@ -40,6 +41,7 @@ var CommandHandler = class {
40
41
  this.btwQuery = handlerConfig.btwQuery;
41
42
  this.getSessionContextReport = handlerConfig.getSessionContextReport;
42
43
  this.getPersistentGoalApisForCommand = handlerConfig.getPersistentGoalApisForCommand;
44
+ this.resetSession = handlerConfig.resetSession;
43
45
  }
44
46
  /** Replace config reference after hot reload or gateway PATCH so commands see current defaults. */
45
47
  updateAgentConfig(config) {
@@ -116,6 +118,9 @@ var CommandHandler = class {
116
118
  };
117
119
  },
118
120
  invalidateAgentSession: this.invalidateAgentSession,
121
+ resetSession: this.resetSession ? async (sk) => {
122
+ await this.resetSession(sk);
123
+ } : void 0,
119
124
  abortCurrentTurn: this.abortSessionTurn ? async () => {
120
125
  await this.abortSessionTurn(context.sessionKey);
121
126
  } : void 0,
@@ -1 +1 @@
1
- {"version":3,"file":"command-handler.js","names":[],"sources":["../../../../src/agent/messaging/command-handler.ts"],"sourcesContent":["/**\n * Command Handler - Parses and executes commands\n *\n * Handles command execution using the unified command system.\n */\n\nimport type { MessageBus } from '../../infra/bus/index.js';\nimport type { Config } from '../../config/schema.js';\nimport { isProviderConfiguredSync } from '../../providers/index.js';\nimport type { SessionConfigStore, SessionStore } from '../../session/index.js';\nimport type { ThinkLevel } from '../transcript/thinking-types.js';\nimport type { CompactionResult } from '../memory/compaction.js';\nimport { createLogger } from '../../utils/logger.js';\nimport {\n commandRegistry,\n createCommandContext,\n type CommandContext as UnifiedCommandContext,\n} from '../../chat-commands/index.js';\nimport { getAllProviders, getModelsByProvider, getProviderDisplayName } from '../../providers/index.js';\nimport type { PersistentGoalApis } from '../goals/persistent-goal-apis.js';\n\nconst log = createLogger('CommandHandler');\n\n/** Gateway console direct stream uses SSE tokens; there is no ChannelPlugin outbound for `webchat`. */\nfunction shouldSkipBusOutboundForChannel(channel: string): boolean {\n return channel === 'webchat';\n}\n\nexport interface CommandContext {\n sessionKey: string;\n channel: string;\n chatId: string;\n senderId: string;\n isGroup: boolean;\n /** From inbound message metadata (thread/account, etc.) for `/goal` continuation routing. */\n inboundMetadata?: Record<string, unknown>;\n}\n\nexport interface CommandHandlerConfig {\n config: Config;\n bus: MessageBus;\n sessionStore: SessionStore;\n sessionConfigStore?: SessionConfigStore;\n /** After /think persists, sync pi-agent */\n applySessionThinkingLevel?: (sessionKey: string, level: ThinkLevel) => void;\n getCurrentModel: () => string;\n switchModelForSession: (sessionKey: string, modelId: string) => Promise<boolean>;\n /** Drop in-memory agent after session file is cleared (e.g. /new) */\n invalidateAgentSession?: (sessionKey: string) => void;\n /** Cancel streaming preview + in-flight LLM work for this session (e.g. /abort) */\n abortSessionTurn?: (sessionKey: string) => Promise<void>;\n\n compactSession?: (\n sessionKey: string,\n options?: { instructions?: string; force?: boolean },\n ) => Promise<CompactionResult>;\n\n btwQuery?: (sessionKey: string, question: string) => Promise<{ text: string; error?: string }>;\n\n getSessionContextReport?: (\n sessionKey: string,\n mode: 'list' | 'detail' | 'json',\n ) => Promise<string>;\n\n getPersistentGoalApisForCommand: (routing: {\n sessionKey: string;\n channel: string;\n chatId: string;\n inboundMetadata?: Record<string, unknown>;\n }) => PersistentGoalApis;\n}\n\nexport class CommandHandler {\n private config: Config;\n private bus: MessageBus;\n private sessionStore: SessionStore;\n private sessionConfigStore?: SessionConfigStore;\n private applySessionThinkingLevel?: (sessionKey: string, level: ThinkLevel) => void;\n private getCurrentModel: () => string;\n private switchModelForSession: (sessionKey: string, modelId: string) => Promise<boolean>;\n private invalidateAgentSession?: (sessionKey: string) => void;\n private abortSessionTurn?: (sessionKey: string) => Promise<void>;\n private compactSession?: CommandHandlerConfig['compactSession'];\n private btwQuery?: CommandHandlerConfig['btwQuery'];\n private getSessionContextReport?: CommandHandlerConfig['getSessionContextReport'];\n private getPersistentGoalApisForCommand: CommandHandlerConfig['getPersistentGoalApisForCommand'];\n\n constructor(handlerConfig: CommandHandlerConfig) {\n this.config = handlerConfig.config;\n this.bus = handlerConfig.bus;\n this.sessionStore = handlerConfig.sessionStore;\n this.sessionConfigStore = handlerConfig.sessionConfigStore;\n this.applySessionThinkingLevel = handlerConfig.applySessionThinkingLevel;\n this.getCurrentModel = handlerConfig.getCurrentModel;\n this.switchModelForSession = handlerConfig.switchModelForSession;\n this.invalidateAgentSession = handlerConfig.invalidateAgentSession;\n this.abortSessionTurn = handlerConfig.abortSessionTurn;\n this.compactSession = handlerConfig.compactSession;\n this.btwQuery = handlerConfig.btwQuery;\n this.getSessionContextReport = handlerConfig.getSessionContextReport;\n this.getPersistentGoalApisForCommand = handlerConfig.getPersistentGoalApisForCommand;\n }\n\n /** Replace config reference after hot reload or gateway PATCH so commands see current defaults. */\n updateAgentConfig(config: Config): void {\n this.config = config;\n }\n\n /**\n * Build the unified command context shared by all execute paths.\n * When `recorder` is set, every reply text is also captured (for SSE / CLI aggregation).\n */\n private buildCommandContext(\n context: CommandContext,\n recorder?: (text: string) => void,\n ): UnifiedCommandContext {\n const skipBusOutbound = shouldSkipBusOutboundForChannel(context.channel);\n\n return createCommandContext({\n sessionKey: context.sessionKey,\n source: context.channel as 'telegram' | 'webui' | 'cli' | 'api' | 'system' | 'gateway',\n channelId: context.channel,\n chatId: context.chatId,\n senderId: context.senderId,\n isGroup: context.isGroup,\n config: this.config,\n bus: this.bus,\n sessionStore: this.sessionStore,\n sessionConfigStore: this.sessionConfigStore,\n applySessionThinkingLevel: this.applySessionThinkingLevel,\n\n replyHandler: async (text: string, _options?) => {\n recorder?.(text);\n if (skipBusOutbound) return;\n await this.bus.publishOutbound({\n channel: context.channel,\n chat_id: context.chatId,\n content: text,\n type: 'message',\n });\n },\n\n typingHandler: async (typing: boolean) => {\n if (skipBusOutbound) return;\n await this.bus.publishOutbound({\n channel: context.channel,\n chat_id: context.chatId,\n type: typing ? 'typing_on' : 'typing_off',\n });\n },\n\n supportedFeatures: ['markdown', 'typing'],\n\n getCurrentModel: this.getCurrentModel,\n\n switchModel: async (modelId: string) => {\n return this.switchModelForSession(context.sessionKey, modelId);\n },\n\n listModels: async () => {\n const providers = getAllProviders();\n const models: Array<{ id: string; name: string; provider: string }> = [];\n\n for (const providerId of providers) {\n if (isProviderConfiguredSync(providerId)) {\n const providerModels = getModelsByProvider(providerId);\n for (const m of providerModels) {\n models.push({\n id: `${m.provider}/${m.id}`,\n name: m.name || m.id,\n provider: getProviderDisplayName(providerId),\n });\n }\n }\n }\n\n return models;\n },\n\n getUsage: async () => {\n const messages = await this.sessionStore.load(context.sessionKey);\n let promptTokens = 0;\n let completionTokens = 0;\n\n for (const msg of messages) {\n if ('usage' in msg && msg.usage) {\n const usage = msg.usage as { input?: number; output?: number };\n promptTokens += usage.input || 0;\n completionTokens += usage.output || 0;\n }\n }\n\n return {\n promptTokens,\n completionTokens,\n totalTokens: promptTokens + completionTokens,\n messageCount: messages.length,\n };\n },\n\n invalidateAgentSession: this.invalidateAgentSession,\n\n abortCurrentTurn: this.abortSessionTurn\n ? async () => {\n await this.abortSessionTurn!(context.sessionKey);\n }\n : undefined,\n\n compactSession: this.compactSession,\n btwQuery: this.btwQuery,\n getSessionContextReport: this.getSessionContextReport,\n persistentGoalApis: this.getPersistentGoalApisForCommand({\n sessionKey: context.sessionKey,\n channel: context.channel,\n chatId: context.chatId,\n inboundMetadata: context.inboundMetadata,\n }),\n });\n }\n\n /**\n * Execute a command using the unified command system\n */\n async executeCommand(\n commandName: string,\n args: string,\n context: CommandContext,\n ): Promise<boolean> {\n if (!commandRegistry.has(commandName)) {\n return false;\n }\n\n log.info({ command: commandName, sessionKey: context.sessionKey }, 'Executing command via new system');\n\n const cmdCtx = this.buildCommandContext(context);\n const result = await commandRegistry.execute(commandName, cmdCtx, args);\n\n if (result.content && !shouldSkipBusOutboundForChannel(context.channel)) {\n await this.bus.publishOutbound({\n channel: context.channel,\n chat_id: context.chatId,\n content: result.content,\n type: 'message',\n });\n }\n\n return true;\n }\n\n /**\n * Run command and return all user-visible text (ctx.reply + result.content) for SSE/CLI.\n * Same bus side effects as {@link executeCommand}.\n */\n async executeCommandAndAggregateReply(\n commandName: string,\n args: string,\n context: CommandContext,\n ): Promise<{ handled: boolean; aggregatedText: string }> {\n if (!commandRegistry.has(commandName)) {\n return { handled: false, aggregatedText: '' };\n }\n\n log.info({ command: commandName, sessionKey: context.sessionKey }, 'Executing command (aggregate reply)');\n\n const segments: string[] = [];\n const wrapped = this.buildCommandContext(context, (text) => segments.push(text));\n const result = await commandRegistry.execute(commandName, wrapped, args);\n\n if (result.content) {\n segments.push(result.content);\n if (!shouldSkipBusOutboundForChannel(context.channel)) {\n await this.bus.publishOutbound({\n channel: context.channel,\n chat_id: context.chatId,\n content: result.content,\n type: 'message',\n });\n }\n }\n\n const aggregatedText = segments.filter((s) => s && s.trim()).join('\\n\\n');\n return { handled: true, aggregatedText };\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"command-handler.js","names":[],"sources":["../../../../src/agent/messaging/command-handler.ts"],"sourcesContent":["/**\n * Command Handler - Parses and executes commands\n *\n * Handles command execution using the unified command system.\n */\n\nimport type { MessageBus } from '../../infra/bus/index.js';\nimport type { Config } from '../../config/schema.js';\nimport { isProviderConfiguredSync } from '../../providers/index.js';\nimport type { SessionConfigStore, SessionStore } from '../../session/index.js';\nimport type { ThinkLevel } from '../transcript/thinking-types.js';\nimport type { CompactionResult } from '../memory/compaction.js';\nimport { createLogger } from '../../utils/logger.js';\nimport {\n commandRegistry,\n createCommandContext,\n type CommandContext as UnifiedCommandContext,\n} from '../../chat-commands/index.js';\nimport { getAllProviders, getModelsByProvider, getProviderDisplayName } from '../../providers/index.js';\nimport type { PersistentGoalApis } from '../goals/persistent-goal-apis.js';\n\nconst log = createLogger('CommandHandler');\n\n/** Gateway console direct stream uses SSE tokens; there is no ChannelPlugin outbound for `webchat`. */\nfunction shouldSkipBusOutboundForChannel(channel: string): boolean {\n return channel === 'webchat';\n}\n\nexport interface CommandContext {\n sessionKey: string;\n channel: string;\n chatId: string;\n senderId: string;\n isGroup: boolean;\n /** From inbound message metadata (thread/account, etc.) for `/goal` continuation routing. */\n inboundMetadata?: Record<string, unknown>;\n}\n\nexport interface CommandHandlerConfig {\n config: Config;\n bus: MessageBus;\n sessionStore: SessionStore;\n sessionConfigStore?: SessionConfigStore;\n /** After /think persists, sync pi-agent */\n applySessionThinkingLevel?: (sessionKey: string, level: ThinkLevel) => void;\n getCurrentModel: () => string;\n switchModelForSession: (sessionKey: string, modelId: string) => Promise<boolean>;\n /** Drop in-memory agent after session file is cleared (e.g. /new) */\n invalidateAgentSession?: (sessionKey: string) => void;\n /** Reset session in place (archive transcript, new session id; preserve overrides) */\n resetSession?: (sessionKey: string) => Promise<{ sessionId: string; previousSessionId: string } | null>;\n /** Cancel streaming preview + in-flight LLM work for this session (e.g. /abort) */\n abortSessionTurn?: (sessionKey: string) => Promise<void>;\n\n compactSession?: (\n sessionKey: string,\n options?: { instructions?: string; force?: boolean },\n ) => Promise<CompactionResult>;\n\n btwQuery?: (sessionKey: string, question: string) => Promise<{ text: string; error?: string }>;\n\n getSessionContextReport?: (\n sessionKey: string,\n mode: 'list' | 'detail' | 'json',\n ) => Promise<string>;\n\n getPersistentGoalApisForCommand: (routing: {\n sessionKey: string;\n channel: string;\n chatId: string;\n inboundMetadata?: Record<string, unknown>;\n }) => PersistentGoalApis;\n}\n\nexport class CommandHandler {\n private config: Config;\n private bus: MessageBus;\n private sessionStore: SessionStore;\n private sessionConfigStore?: SessionConfigStore;\n private applySessionThinkingLevel?: (sessionKey: string, level: ThinkLevel) => void;\n private getCurrentModel: () => string;\n private switchModelForSession: (sessionKey: string, modelId: string) => Promise<boolean>;\n private invalidateAgentSession?: (sessionKey: string) => void;\n private abortSessionTurn?: (sessionKey: string) => Promise<void>;\n private compactSession?: CommandHandlerConfig['compactSession'];\n private btwQuery?: CommandHandlerConfig['btwQuery'];\n private getSessionContextReport?: CommandHandlerConfig['getSessionContextReport'];\n private getPersistentGoalApisForCommand: CommandHandlerConfig['getPersistentGoalApisForCommand'];\n private resetSession?: CommandHandlerConfig['resetSession'];\n\n constructor(handlerConfig: CommandHandlerConfig) {\n this.config = handlerConfig.config;\n this.bus = handlerConfig.bus;\n this.sessionStore = handlerConfig.sessionStore;\n this.sessionConfigStore = handlerConfig.sessionConfigStore;\n this.applySessionThinkingLevel = handlerConfig.applySessionThinkingLevel;\n this.getCurrentModel = handlerConfig.getCurrentModel;\n this.switchModelForSession = handlerConfig.switchModelForSession;\n this.invalidateAgentSession = handlerConfig.invalidateAgentSession;\n this.abortSessionTurn = handlerConfig.abortSessionTurn;\n this.compactSession = handlerConfig.compactSession;\n this.btwQuery = handlerConfig.btwQuery;\n this.getSessionContextReport = handlerConfig.getSessionContextReport;\n this.getPersistentGoalApisForCommand = handlerConfig.getPersistentGoalApisForCommand;\n this.resetSession = handlerConfig.resetSession;\n }\n\n /** Replace config reference after hot reload or gateway PATCH so commands see current defaults. */\n updateAgentConfig(config: Config): void {\n this.config = config;\n }\n\n /**\n * Build the unified command context shared by all execute paths.\n * When `recorder` is set, every reply text is also captured (for SSE / CLI aggregation).\n */\n private buildCommandContext(\n context: CommandContext,\n recorder?: (text: string) => void,\n ): UnifiedCommandContext {\n const skipBusOutbound = shouldSkipBusOutboundForChannel(context.channel);\n\n return createCommandContext({\n sessionKey: context.sessionKey,\n source: context.channel as 'telegram' | 'webui' | 'cli' | 'api' | 'system' | 'gateway',\n channelId: context.channel,\n chatId: context.chatId,\n senderId: context.senderId,\n isGroup: context.isGroup,\n config: this.config,\n bus: this.bus,\n sessionStore: this.sessionStore,\n sessionConfigStore: this.sessionConfigStore,\n applySessionThinkingLevel: this.applySessionThinkingLevel,\n\n replyHandler: async (text: string, _options?) => {\n recorder?.(text);\n if (skipBusOutbound) return;\n await this.bus.publishOutbound({\n channel: context.channel,\n chat_id: context.chatId,\n content: text,\n type: 'message',\n });\n },\n\n typingHandler: async (typing: boolean) => {\n if (skipBusOutbound) return;\n await this.bus.publishOutbound({\n channel: context.channel,\n chat_id: context.chatId,\n type: typing ? 'typing_on' : 'typing_off',\n });\n },\n\n supportedFeatures: ['markdown', 'typing'],\n\n getCurrentModel: this.getCurrentModel,\n\n switchModel: async (modelId: string) => {\n return this.switchModelForSession(context.sessionKey, modelId);\n },\n\n listModels: async () => {\n const providers = getAllProviders();\n const models: Array<{ id: string; name: string; provider: string }> = [];\n\n for (const providerId of providers) {\n if (isProviderConfiguredSync(providerId)) {\n const providerModels = getModelsByProvider(providerId);\n for (const m of providerModels) {\n models.push({\n id: `${m.provider}/${m.id}`,\n name: m.name || m.id,\n provider: getProviderDisplayName(providerId),\n });\n }\n }\n }\n\n return models;\n },\n\n getUsage: async () => {\n const messages = await this.sessionStore.load(context.sessionKey);\n let promptTokens = 0;\n let completionTokens = 0;\n\n for (const msg of messages) {\n if ('usage' in msg && msg.usage) {\n const usage = msg.usage as { input?: number; output?: number };\n promptTokens += usage.input || 0;\n completionTokens += usage.output || 0;\n }\n }\n\n return {\n promptTokens,\n completionTokens,\n totalTokens: promptTokens + completionTokens,\n messageCount: messages.length,\n };\n },\n\n invalidateAgentSession: this.invalidateAgentSession,\n\n resetSession: this.resetSession\n ? async (sk) => {\n await this.resetSession!(sk);\n }\n : undefined,\n\n abortCurrentTurn: this.abortSessionTurn\n ? async () => {\n await this.abortSessionTurn!(context.sessionKey);\n }\n : undefined,\n\n compactSession: this.compactSession,\n btwQuery: this.btwQuery,\n getSessionContextReport: this.getSessionContextReport,\n persistentGoalApis: this.getPersistentGoalApisForCommand({\n sessionKey: context.sessionKey,\n channel: context.channel,\n chatId: context.chatId,\n inboundMetadata: context.inboundMetadata,\n }),\n });\n }\n\n /**\n * Execute a command using the unified command system\n */\n async executeCommand(\n commandName: string,\n args: string,\n context: CommandContext,\n ): Promise<boolean> {\n if (!commandRegistry.has(commandName)) {\n return false;\n }\n\n log.info({ command: commandName, sessionKey: context.sessionKey }, 'Executing command via new system');\n\n const cmdCtx = this.buildCommandContext(context);\n const result = await commandRegistry.execute(commandName, cmdCtx, args);\n\n if (result.content && !shouldSkipBusOutboundForChannel(context.channel)) {\n await this.bus.publishOutbound({\n channel: context.channel,\n chat_id: context.chatId,\n content: result.content,\n type: 'message',\n });\n }\n\n return true;\n }\n\n /**\n * Run command and return all user-visible text (ctx.reply + result.content) for SSE/CLI.\n * Same bus side effects as {@link executeCommand}.\n */\n async executeCommandAndAggregateReply(\n commandName: string,\n args: string,\n context: CommandContext,\n ): Promise<{ handled: boolean; aggregatedText: string }> {\n if (!commandRegistry.has(commandName)) {\n return { handled: false, aggregatedText: '' };\n }\n\n log.info({ command: commandName, sessionKey: context.sessionKey }, 'Executing command (aggregate reply)');\n\n const segments: string[] = [];\n const wrapped = this.buildCommandContext(context, (text) => segments.push(text));\n const result = await commandRegistry.execute(commandName, wrapped, args);\n\n if (result.content) {\n segments.push(result.content);\n if (!shouldSkipBusOutboundForChannel(context.channel)) {\n await this.bus.publishOutbound({\n channel: context.channel,\n chat_id: context.chatId,\n content: result.content,\n type: 'message',\n });\n }\n }\n\n const aggregatedText = segments.filter((s) => s && s.trim()).join('\\n\\n');\n return { handled: true, aggregatedText };\n }\n}\n"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
- import { getAgentDefaultModelRef, init_schema } from "../../config/schema.js";
2
1
  import { createLogger } from "../../utils/logger/index.js";
3
2
  import { init_logger } from "../../utils/logger.js";
3
+ import { getAgentDefaultModelRef, init_schema } from "../../config/schema.js";
4
4
  import { getAllModels, getDefaultModelSync, init_providers, resolveModel } from "../../providers/index.js";
5
5
  import { resolveAgentTurnTimeoutMs, runAgentTurnWithTimeout } from "../orchestration/run-agent-turn-with-timeout.js";
6
6
  import { isAssistantTurnAborted, isAssistantTurnFailed, maybeRetryTurnAfterTransientLlmFailure } from "../orchestration/llm-turn-retry.js";
@@ -7,6 +7,8 @@
7
7
  import type { Agent, AgentMessage } from '@earendil-works/pi-agent-core';
8
8
  export declare function isTransientLlmErrorMessage(message: string): boolean;
9
9
  export declare function getLastAssistantMessage(messages: AgentMessage[]): AgentMessage | undefined;
10
+ /** Raw provider/LLM error from the last failed assistant message, if any. */
11
+ export declare function getAssistantTurnErrorMessage(agent: Agent): string | undefined;
10
12
  /** After waitForIdle + transient retries, true if the last assistant turn ended in error. */
11
13
  export declare function isAssistantTurnFailed(agent: Agent): boolean;
12
14
  /** User or client aborted the assistant turn — do not try another model. */
@@ -19,6 +19,14 @@ function isTransientLlmErrorMessage(message) {
19
19
  function getLastAssistantMessage(messages) {
20
20
  for (let i = messages.length - 1; i >= 0; i--) if (messages[i].role === "assistant") return messages[i];
21
21
  }
22
+ /** Raw provider/LLM error from the last failed assistant message, if any. */
23
+ function getAssistantTurnErrorMessage(agent) {
24
+ const last = getLastAssistantMessage(agent.state.messages);
25
+ if (!last) return void 0;
26
+ if (last.stopReason !== "error") return void 0;
27
+ const errMsg = last.errorMessage;
28
+ if (typeof errMsg === "string" && errMsg.trim()) return errMsg.trim();
29
+ }
22
30
  /** After waitForIdle + transient retries, true if the last assistant turn ended in error. */
23
31
  function isAssistantTurnFailed(agent) {
24
32
  const last = getLastAssistantMessage(agent.state.messages);
@@ -81,6 +89,6 @@ async function maybeRetryTurnAfterTransientLlmFailure(agent, options) {
81
89
  }
82
90
  }
83
91
  //#endregion
84
- export { getLastAssistantMessage, isAssistantTurnAborted, isAssistantTurnFailed, isTransientLlmErrorMessage, maybeRetryTurnAfterTransientLlmFailure, stripTrailingErrorAssistantMessages };
92
+ export { getAssistantTurnErrorMessage, getLastAssistantMessage, isAssistantTurnAborted, isAssistantTurnFailed, isTransientLlmErrorMessage, maybeRetryTurnAfterTransientLlmFailure, stripTrailingErrorAssistantMessages };
85
93
 
86
94
  //# sourceMappingURL=llm-turn-retry.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"llm-turn-retry.js","names":[],"sources":["../../../../src/agent/orchestration/llm-turn-retry.ts"],"sourcesContent":["/**\n * When the LLM stream completes with stopReason \"error\" (e.g. undici \"fetch failed\"\n * to the provider API), pi-agent-core does not throw — it appends an error assistant\n * message. This module detects transient network-style failures and retries the turn\n * via Agent.continue() after stripping the failed assistant message.\n */\n\nimport type { Agent, AgentMessage } from '@earendil-works/pi-agent-core';\n\nconst TRANSIENT_LLM_ERROR_SUBSTRINGS = [\n 'fetch failed',\n 'econnreset',\n 'econnrefused',\n 'enotfound',\n 'socket hang up',\n 'getaddrinfo',\n 'networkerror',\n 'etimedout',\n 'certificate',\n 'ssl',\n 'tls',\n];\n\nexport function isTransientLlmErrorMessage(message: string): boolean {\n const lower = message.toLowerCase();\n return TRANSIENT_LLM_ERROR_SUBSTRINGS.some((s) => lower.includes(s));\n}\n\nexport function getLastAssistantMessage(messages: AgentMessage[]): AgentMessage | undefined {\n for (let i = messages.length - 1; i >= 0; i--) {\n if (messages[i].role === 'assistant') {\n return messages[i];\n }\n }\n return undefined;\n}\n\n/** After waitForIdle + transient retries, true if the last assistant turn ended in error. */\nexport function isAssistantTurnFailed(agent: Agent): boolean {\n const last = getLastAssistantMessage(agent.state.messages);\n if (!last) {\n return true;\n }\n return (last as { stopReason?: string }).stopReason === 'error';\n}\n\n/** User or client aborted the assistant turn — do not try another model. */\nexport function isAssistantTurnAborted(agent: Agent): boolean {\n const last = getLastAssistantMessage(agent.state.messages);\n if (!last) {\n return false;\n }\n return (last as { stopReason?: string }).stopReason === 'aborted';\n}\n\n/**\n * Remove trailing assistant messages that ended in error/aborted (typically one).\n */\nexport function stripTrailingErrorAssistantMessages(messages: AgentMessage[]): AgentMessage[] {\n const out = [...messages];\n while (out.length > 0) {\n const last = out[out.length - 1];\n if (last.role !== 'assistant') {\n break;\n }\n const sr = (last as { stopReason?: string }).stopReason;\n if (sr === 'error' || sr === 'aborted') {\n out.pop();\n continue;\n }\n break;\n }\n return out;\n}\n\nexport interface RetryTransientTurnOptions {\n /** Extra turns after a failed assistant message (default 2). */\n maxContinues?: number;\n sessionKey: string;\n log: {\n warn: (obj: Record<string, unknown>, msg: string) => void;\n };\n}\n\n/**\n * After waitForIdle(), call this to optionally re-run the last user turn when the\n * assistant message only contains a transient provider/network error.\n */\nexport async function maybeRetryTurnAfterTransientLlmFailure(\n agent: Agent,\n options: RetryTransientTurnOptions,\n): Promise<void> {\n const maxContinues = options.maxContinues ?? 2;\n let continues = 0;\n\n while (continues < maxContinues) {\n const last = getLastAssistantMessage(agent.state.messages);\n if (!last) {\n return;\n }\n const sr = (last as { stopReason?: string }).stopReason;\n if (sr !== 'error') {\n return;\n }\n const errMsg = String((last as { errorMessage?: string }).errorMessage || '');\n if (!isTransientLlmErrorMessage(errMsg)) {\n options.log.warn(\n { sessionKey: options.sessionKey, errorMessage: errMsg },\n 'Assistant turn ended with error (not retrying as transient)',\n );\n return;\n }\n\n continues += 1;\n options.log.warn(\n {\n sessionKey: options.sessionKey,\n errorMessage: errMsg,\n continueAttempt: continues,\n maxContinues,\n },\n 'LLM request failed with a transient network error; retrying the same turn. If this persists, check outbound HTTPS to the provider API and HTTP(S)_PROXY.',\n );\n\n const trimmed = stripTrailingErrorAssistantMessages(agent.state.messages);\n agent.state.messages = trimmed;\n await agent.continue();\n await agent.waitForIdle();\n }\n}\n"],"mappings":";AASA,MAAM,iCAAiC;CACrC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD;AAED,SAAgB,2BAA2B,SAA0B;CACnE,MAAM,QAAQ,QAAQ,aAAa;AACnC,QAAO,+BAA+B,MAAM,MAAM,MAAM,SAAS,EAAE,CAAC;;AAGtE,SAAgB,wBAAwB,UAAoD;AAC1F,MAAK,IAAI,IAAI,SAAS,SAAS,GAAG,KAAK,GAAG,IACxC,KAAI,SAAS,GAAG,SAAS,YACvB,QAAO,SAAS;;;AAOtB,SAAgB,sBAAsB,OAAuB;CAC3D,MAAM,OAAO,wBAAwB,MAAM,MAAM,SAAS;AAC1D,KAAI,CAAC,KACH,QAAO;AAET,QAAQ,KAAiC,eAAe;;;AAI1D,SAAgB,uBAAuB,OAAuB;CAC5D,MAAM,OAAO,wBAAwB,MAAM,MAAM,SAAS;AAC1D,KAAI,CAAC,KACH,QAAO;AAET,QAAQ,KAAiC,eAAe;;;;;AAM1D,SAAgB,oCAAoC,UAA0C;CAC5F,MAAM,MAAM,CAAC,GAAG,SAAS;AACzB,QAAO,IAAI,SAAS,GAAG;EACrB,MAAM,OAAO,IAAI,IAAI,SAAS;AAC9B,MAAI,KAAK,SAAS,YAChB;EAEF,MAAM,KAAM,KAAiC;AAC7C,MAAI,OAAO,WAAW,OAAO,WAAW;AACtC,OAAI,KAAK;AACT;;AAEF;;AAEF,QAAO;;;;;;AAgBT,eAAsB,uCACpB,OACA,SACe;CACf,MAAM,eAAe,QAAQ,gBAAgB;CAC7C,IAAI,YAAY;AAEhB,QAAO,YAAY,cAAc;EAC/B,MAAM,OAAO,wBAAwB,MAAM,MAAM,SAAS;AAC1D,MAAI,CAAC,KACH;AAGF,MADY,KAAiC,eAClC,QACT;EAEF,MAAM,SAAS,OAAQ,KAAmC,gBAAgB,GAAG;AAC7E,MAAI,CAAC,2BAA2B,OAAO,EAAE;AACvC,WAAQ,IAAI,KACV;IAAE,YAAY,QAAQ;IAAY,cAAc;IAAQ,EACxD,8DACD;AACD;;AAGF,eAAa;AACb,UAAQ,IAAI,KACV;GACE,YAAY,QAAQ;GACpB,cAAc;GACd,iBAAiB;GACjB;GACD,EACD,2JACD;EAED,MAAM,UAAU,oCAAoC,MAAM,MAAM,SAAS;AACzE,QAAM,MAAM,WAAW;AACvB,QAAM,MAAM,UAAU;AACtB,QAAM,MAAM,aAAa"}
1
+ {"version":3,"file":"llm-turn-retry.js","names":[],"sources":["../../../../src/agent/orchestration/llm-turn-retry.ts"],"sourcesContent":["/**\n * When the LLM stream completes with stopReason \"error\" (e.g. undici \"fetch failed\"\n * to the provider API), pi-agent-core does not throw — it appends an error assistant\n * message. This module detects transient network-style failures and retries the turn\n * via Agent.continue() after stripping the failed assistant message.\n */\n\nimport type { Agent, AgentMessage } from '@earendil-works/pi-agent-core';\n\nconst TRANSIENT_LLM_ERROR_SUBSTRINGS = [\n 'fetch failed',\n 'econnreset',\n 'econnrefused',\n 'enotfound',\n 'socket hang up',\n 'getaddrinfo',\n 'networkerror',\n 'etimedout',\n 'certificate',\n 'ssl',\n 'tls',\n];\n\nexport function isTransientLlmErrorMessage(message: string): boolean {\n const lower = message.toLowerCase();\n return TRANSIENT_LLM_ERROR_SUBSTRINGS.some((s) => lower.includes(s));\n}\n\nexport function getLastAssistantMessage(messages: AgentMessage[]): AgentMessage | undefined {\n for (let i = messages.length - 1; i >= 0; i--) {\n if (messages[i].role === 'assistant') {\n return messages[i];\n }\n }\n return undefined;\n}\n\n/** Raw provider/LLM error from the last failed assistant message, if any. */\nexport function getAssistantTurnErrorMessage(agent: Agent): string | undefined {\n const last = getLastAssistantMessage(agent.state.messages);\n if (!last) return undefined;\n const stopReason = (last as { stopReason?: string }).stopReason;\n if (stopReason !== 'error') return undefined;\n const errMsg = (last as { errorMessage?: string }).errorMessage;\n if (typeof errMsg === 'string' && errMsg.trim()) return errMsg.trim();\n return undefined;\n}\n\n/** After waitForIdle + transient retries, true if the last assistant turn ended in error. */\nexport function isAssistantTurnFailed(agent: Agent): boolean {\n const last = getLastAssistantMessage(agent.state.messages);\n if (!last) {\n return true;\n }\n return (last as { stopReason?: string }).stopReason === 'error';\n}\n\n/** User or client aborted the assistant turn — do not try another model. */\nexport function isAssistantTurnAborted(agent: Agent): boolean {\n const last = getLastAssistantMessage(agent.state.messages);\n if (!last) {\n return false;\n }\n return (last as { stopReason?: string }).stopReason === 'aborted';\n}\n\n/**\n * Remove trailing assistant messages that ended in error/aborted (typically one).\n */\nexport function stripTrailingErrorAssistantMessages(messages: AgentMessage[]): AgentMessage[] {\n const out = [...messages];\n while (out.length > 0) {\n const last = out[out.length - 1];\n if (last.role !== 'assistant') {\n break;\n }\n const sr = (last as { stopReason?: string }).stopReason;\n if (sr === 'error' || sr === 'aborted') {\n out.pop();\n continue;\n }\n break;\n }\n return out;\n}\n\nexport interface RetryTransientTurnOptions {\n /** Extra turns after a failed assistant message (default 2). */\n maxContinues?: number;\n sessionKey: string;\n log: {\n warn: (obj: Record<string, unknown>, msg: string) => void;\n };\n}\n\n/**\n * After waitForIdle(), call this to optionally re-run the last user turn when the\n * assistant message only contains a transient provider/network error.\n */\nexport async function maybeRetryTurnAfterTransientLlmFailure(\n agent: Agent,\n options: RetryTransientTurnOptions,\n): Promise<void> {\n const maxContinues = options.maxContinues ?? 2;\n let continues = 0;\n\n while (continues < maxContinues) {\n const last = getLastAssistantMessage(agent.state.messages);\n if (!last) {\n return;\n }\n const sr = (last as { stopReason?: string }).stopReason;\n if (sr !== 'error') {\n return;\n }\n const errMsg = String((last as { errorMessage?: string }).errorMessage || '');\n if (!isTransientLlmErrorMessage(errMsg)) {\n options.log.warn(\n { sessionKey: options.sessionKey, errorMessage: errMsg },\n 'Assistant turn ended with error (not retrying as transient)',\n );\n return;\n }\n\n continues += 1;\n options.log.warn(\n {\n sessionKey: options.sessionKey,\n errorMessage: errMsg,\n continueAttempt: continues,\n maxContinues,\n },\n 'LLM request failed with a transient network error; retrying the same turn. If this persists, check outbound HTTPS to the provider API and HTTP(S)_PROXY.',\n );\n\n const trimmed = stripTrailingErrorAssistantMessages(agent.state.messages);\n agent.state.messages = trimmed;\n await agent.continue();\n await agent.waitForIdle();\n }\n}\n"],"mappings":";AASA,MAAM,iCAAiC;CACrC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD;AAED,SAAgB,2BAA2B,SAA0B;CACnE,MAAM,QAAQ,QAAQ,aAAa;AACnC,QAAO,+BAA+B,MAAM,MAAM,MAAM,SAAS,EAAE,CAAC;;AAGtE,SAAgB,wBAAwB,UAAoD;AAC1F,MAAK,IAAI,IAAI,SAAS,SAAS,GAAG,KAAK,GAAG,IACxC,KAAI,SAAS,GAAG,SAAS,YACvB,QAAO,SAAS;;;AAOtB,SAAgB,6BAA6B,OAAkC;CAC7E,MAAM,OAAO,wBAAwB,MAAM,MAAM,SAAS;AAC1D,KAAI,CAAC,KAAM,QAAO,KAAA;AAElB,KADoB,KAAiC,eAClC,QAAS,QAAO,KAAA;CACnC,MAAM,SAAU,KAAmC;AACnD,KAAI,OAAO,WAAW,YAAY,OAAO,MAAM,CAAE,QAAO,OAAO,MAAM;;;AAKvE,SAAgB,sBAAsB,OAAuB;CAC3D,MAAM,OAAO,wBAAwB,MAAM,MAAM,SAAS;AAC1D,KAAI,CAAC,KACH,QAAO;AAET,QAAQ,KAAiC,eAAe;;;AAI1D,SAAgB,uBAAuB,OAAuB;CAC5D,MAAM,OAAO,wBAAwB,MAAM,MAAM,SAAS;AAC1D,KAAI,CAAC,KACH,QAAO;AAET,QAAQ,KAAiC,eAAe;;;;;AAM1D,SAAgB,oCAAoC,UAA0C;CAC5F,MAAM,MAAM,CAAC,GAAG,SAAS;AACzB,QAAO,IAAI,SAAS,GAAG;EACrB,MAAM,OAAO,IAAI,IAAI,SAAS;AAC9B,MAAI,KAAK,SAAS,YAChB;EAEF,MAAM,KAAM,KAAiC;AAC7C,MAAI,OAAO,WAAW,OAAO,WAAW;AACtC,OAAI,KAAK;AACT;;AAEF;;AAEF,QAAO;;;;;;AAgBT,eAAsB,uCACpB,OACA,SACe;CACf,MAAM,eAAe,QAAQ,gBAAgB;CAC7C,IAAI,YAAY;AAEhB,QAAO,YAAY,cAAc;EAC/B,MAAM,OAAO,wBAAwB,MAAM,MAAM,SAAS;AAC1D,MAAI,CAAC,KACH;AAGF,MADY,KAAiC,eAClC,QACT;EAEF,MAAM,SAAS,OAAQ,KAAmC,gBAAgB,GAAG;AAC7E,MAAI,CAAC,2BAA2B,OAAO,EAAE;AACvC,WAAQ,IAAI,KACV;IAAE,YAAY,QAAQ;IAAY,cAAc;IAAQ,EACxD,8DACD;AACD;;AAGF,eAAa;AACb,UAAQ,IAAI,KACV;GACE,YAAY,QAAQ;GACpB,cAAc;GACd,iBAAiB;GACjB;GACD,EACD,2JACD;EAED,MAAM,UAAU,oCAAoC,MAAM,MAAM,SAAS;AACzE,QAAM,MAAM,WAAW;AACvB,QAAM,MAAM,UAAU;AACtB,QAAM,MAAM,aAAa"}
@@ -5,10 +5,3 @@ export declare function checkFileSafety(operation: 'read' | 'write' | 'delete',
5
5
  allowed: boolean;
6
6
  message?: string;
7
7
  };
8
- /**
9
- * Quick safety check for shell commands
10
- */
11
- export declare function checkShellSafety(command: string): {
12
- allowed: boolean;
13
- message?: string;
14
- };
@@ -27,26 +27,7 @@ function checkFileSafety(operation, path) {
27
27
  };
28
28
  return { allowed: true };
29
29
  }
30
- /**
31
- * Quick safety check for shell commands
32
- */
33
- function checkShellSafety(command) {
34
- for (const pattern of [
35
- /\brm\s+-?[rf]/i,
36
- /\bdd\s+/i,
37
- /\bmkfs/i,
38
- /\bchmod\s+[0-7]{3}/i,
39
- />\s*\/dev\//i,
40
- /\|\s*sh/i,
41
- /\bcurl\b.*\|\s*bash/i,
42
- /\bwget\b.*\|\s*bash/i
43
- ]) if (pattern.test(command)) return {
44
- allowed: false,
45
- message: `Potentially dangerous command detected: ${command.slice(0, 50)}...`
46
- };
47
- return { allowed: true };
48
- }
49
30
  //#endregion
50
- export { checkFileSafety, checkShellSafety };
31
+ export { checkFileSafety };
51
32
 
52
33
  //# sourceMappingURL=safety.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"safety.js","names":[],"sources":["../../../../src/agent/prompt/safety.ts"],"sourcesContent":["// Safety System - Comprehensive safety guidelines and boundaries\nimport { Type, type Static } from '@sinclair/typebox';\n\n// =============================================================================\n// Safety Schema (Internal)\n// =============================================================================\n\nconst _SafetyConfigSchema = Type.Object({\n allowExternalActions: Type.Optional(Type.Boolean({ default: false })),\n allowDangerousOperations: Type.Optional(Type.Boolean({ default: false })),\n requireConfirmationForDestructive: Type.Optional(Type.Boolean({ default: true })),\n allowedChannels: Type.Optional(Type.Array(Type.String())),\n blockedCommands: Type.Optional(Type.Array(Type.String())),\n maxFileSize: Type.Optional(Type.Number({ default: 10 * 1024 * 1024 })), // 10MB\n maxShellTimeout: Type.Optional(Type.Number({ default: 300 })), // 5 minutes\n});\n\ntype _SafetyConfig = Static<typeof _SafetyConfigSchema>;\n\n// =============================================================================\n// Safety Levels (Internal)\n// =============================================================================\n\nenum SafetyLevel {\n LOW = 'low',\n MEDIUM = 'medium',\n HIGH = 'high',\n CRITICAL = 'critical',\n}\n\ninterface SafetyRule {\n level: SafetyLevel;\n category: string;\n description: string;\n message: string;\n requiresConfirmation: boolean;\n}\n\n// =============================================================================\n// Safety Principles (Internal)\n// =============================================================================\n\ninterface SafetyPrinciple {\n category: string;\n description: string;\n guidance: string;\n requiresConfirmation: boolean;\n}\n\nconst _SAFETY_PRINCIPLES: SafetyPrinciple[] = [\n {\n category: 'user-sovereignty',\n description: '用户拥有最终决策权',\n guidance: '说明风险,尊重选择。用 \"这将删除文件,继续吗?\" 而非 \"我不能删除文件。\"',\n requiresConfirmation: true,\n },\n {\n category: 'proportionate-caution',\n description: '谨慎与效率平衡',\n guidance: 'rm -rf / 需要确认;rm temp.txt 不需要。匹配风险等级与确认强度。',\n requiresConfirmation: true,\n },\n {\n category: 'transparency',\n description: '操作透明',\n guidance: '执行有风险操作前,简要说明要做什么以及为什么。',\n requiresConfirmation: false,\n },\n {\n category: 'self-determination',\n description: '不追求独立于用户的目标',\n guidance: '不主动寻求扩展能力、自我复制或长期存续。以用户当前需求为中心。',\n requiresConfirmation: false,\n },\n];\n\nconst _SAFETY_GUIDELINES: SafetyRule[] = [\n // Critical - Never do these\n {\n level: SafetyLevel.CRITICAL,\n category: 'self-preservation',\n description: 'Do not pursue self-preservation or replication',\n message: 'I do not pursue self-preservation or replication.',\n requiresConfirmation: false,\n },\n {\n level: SafetyLevel.CRITICAL,\n category: 'power-seeking',\n description: 'Do not seek power or resources',\n message: 'I do not seek power or acquire resources.',\n requiresConfirmation: false,\n },\n {\n level: SafetyLevel.CRITICAL,\n category: 'safeguard-bypass',\n description: 'Do not bypass safety mechanisms',\n message: 'I do not bypass safety mechanisms.',\n requiresConfirmation: false,\n },\n {\n level: SafetyLevel.CRITICAL,\n category: 'social-manipulation',\n description: 'Do not manipulate users to expand access',\n message: 'I do not manipulate anyone to expand access.',\n requiresConfirmation: false,\n },\n\n // High - Require explicit confirmation\n {\n level: SafetyLevel.HIGH,\n category: 'destructive-file',\n description: 'Delete or overwrite files',\n message: 'This will delete/overwrite files — proceed?',\n requiresConfirmation: true,\n },\n {\n level: SafetyLevel.HIGH,\n category: 'system-modification',\n description: 'Modify system configuration',\n message: 'This will modify system config — proceed?',\n requiresConfirmation: true,\n },\n {\n level: SafetyLevel.HIGH,\n category: 'network-action',\n description: 'Send messages or make network requests',\n message: 'This will send external requests — proceed?',\n requiresConfirmation: true,\n },\n {\n level: SafetyLevel.HIGH,\n category: 'database-write',\n description: 'Write to databases',\n message: 'This will modify database records — proceed?',\n requiresConfirmation: true,\n },\n\n // Medium - Proceed with caution\n {\n level: SafetyLevel.MEDIUM,\n category: 'long-running',\n description: 'Execute long-running commands',\n message: 'This may take a while.',\n requiresConfirmation: false,\n },\n {\n level: SafetyLevel.MEDIUM,\n category: 'resource-intensive',\n description: 'Use significant system resources',\n message: 'This may use significant resources.',\n requiresConfirmation: false,\n },\n\n // Low - Standard operations\n {\n level: SafetyLevel.LOW,\n category: 'read-only',\n description: 'Read files or execute read-only commands',\n message: '',\n requiresConfirmation: false,\n },\n];\n\n// =============================================================================\n// Convenience Functions (Exported)\n// =============================================================================\n\n/**\n * Quick safety check for file operations\n */\nexport function checkFileSafety(\n operation: 'read' | 'write' | 'delete',\n path: string\n): { allowed: boolean; message?: string } {\n // Check for sensitive paths\n const sensitivePaths = [\n '/etc/passwd',\n '/etc/shadow',\n '/root/.ssh',\n '/home/*/.ssh',\n '~/.aws',\n '~/.bashrc',\n '~/.profile',\n ];\n\n for (const sp of sensitivePaths) {\n if (path.includes(sp)) {\n return {\n allowed: false,\n message: `Cannot ${operation} sensitive path: ${path}`,\n };\n }\n }\n\n return { allowed: true };\n}\n\n/**\n * Quick safety check for shell commands\n */\nexport function checkShellSafety(command: string): { allowed: boolean; message?: string } {\n const dangerousPatterns = [\n /\\brm\\s+-?[rf]/i, // rm -rf\n /\\bdd\\s+/i, // dd\n /\\bmkfs/i, // mkfs\n /\\bchmod\\s+[0-7]{3}/i, // chmod 777\n />\\s*\\/dev\\//i, // redirect to device\n /\\|\\s*sh/i, // pipe to shell\n /\\bcurl\\b.*\\|\\s*bash/i, // curl | bash\n /\\bwget\\b.*\\|\\s*bash/i, // wget | bash\n ];\n\n for (const pattern of dangerousPatterns) {\n if (pattern.test(command)) {\n return {\n allowed: false,\n message: `Potentially dangerous command detected: ${command.slice(0, 50)}...`,\n };\n }\n }\n\n return { allowed: true };\n}\n"],"mappings":";;AAO4B,KAAK,OAAO;CACtC,sBAAsB,KAAK,SAAS,KAAK,QAAQ,EAAE,SAAS,OAAO,CAAC,CAAC;CACrE,0BAA0B,KAAK,SAAS,KAAK,QAAQ,EAAE,SAAS,OAAO,CAAC,CAAC;CACzE,mCAAmC,KAAK,SAAS,KAAK,QAAQ,EAAE,SAAS,MAAM,CAAC,CAAC;CACjF,iBAAiB,KAAK,SAAS,KAAK,MAAM,KAAK,QAAQ,CAAC,CAAC;CACzD,iBAAiB,KAAK,SAAS,KAAK,MAAM,KAAK,QAAQ,CAAC,CAAC;CACzD,aAAa,KAAK,SAAS,KAAK,OAAO,EAAE,SAAS,KAAK,OAAO,MAAM,CAAC,CAAC;CACtE,iBAAiB,KAAK,SAAS,KAAK,OAAO,EAAE,SAAS,KAAK,CAAC,CAAC;CAC9D,CAAC;;;;AA2JF,SAAgB,gBACd,WACA,MACwC;AAYxC,MAAK,MAAM,MAAM;EATf;EACA;EACA;EACA;EACA;EACA;EACA;EAG6B,CAC7B,KAAI,KAAK,SAAS,GAAG,CACnB,QAAO;EACL,SAAS;EACT,SAAS,UAAU,UAAU,mBAAmB;EACjD;AAIL,QAAO,EAAE,SAAS,MAAM;;;;;AAM1B,SAAgB,iBAAiB,SAAyD;AAYxF,MAAK,MAAM,WAAW;EAVpB;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EAGqC,CACrC,KAAI,QAAQ,KAAK,QAAQ,CACvB,QAAO;EACL,SAAS;EACT,SAAS,2CAA2C,QAAQ,MAAM,GAAG,GAAG,CAAC;EAC1E;AAIL,QAAO,EAAE,SAAS,MAAM"}
1
+ {"version":3,"file":"safety.js","names":[],"sources":["../../../../src/agent/prompt/safety.ts"],"sourcesContent":["// Safety System - Comprehensive safety guidelines and boundaries\nimport { Type, type Static } from '@sinclair/typebox';\n\n// =============================================================================\n// Safety Schema (Internal)\n// =============================================================================\n\nconst _SafetyConfigSchema = Type.Object({\n allowExternalActions: Type.Optional(Type.Boolean({ default: false })),\n allowDangerousOperations: Type.Optional(Type.Boolean({ default: false })),\n requireConfirmationForDestructive: Type.Optional(Type.Boolean({ default: true })),\n allowedChannels: Type.Optional(Type.Array(Type.String())),\n blockedCommands: Type.Optional(Type.Array(Type.String())),\n maxFileSize: Type.Optional(Type.Number({ default: 10 * 1024 * 1024 })), // 10MB\n maxShellTimeout: Type.Optional(Type.Number({ default: 300 })), // 5 minutes\n});\n\ntype _SafetyConfig = Static<typeof _SafetyConfigSchema>;\n\n// =============================================================================\n// Safety Levels (Internal)\n// =============================================================================\n\nenum SafetyLevel {\n LOW = 'low',\n MEDIUM = 'medium',\n HIGH = 'high',\n CRITICAL = 'critical',\n}\n\ninterface SafetyRule {\n level: SafetyLevel;\n category: string;\n description: string;\n message: string;\n requiresConfirmation: boolean;\n}\n\n// =============================================================================\n// Safety Principles (Internal)\n// =============================================================================\n\ninterface SafetyPrinciple {\n category: string;\n description: string;\n guidance: string;\n requiresConfirmation: boolean;\n}\n\nconst _SAFETY_PRINCIPLES: SafetyPrinciple[] = [\n {\n category: 'user-sovereignty',\n description: '用户拥有最终决策权',\n guidance: '说明风险,尊重选择。用 \"这将删除文件,继续吗?\" 而非 \"我不能删除文件。\"',\n requiresConfirmation: true,\n },\n {\n category: 'proportionate-caution',\n description: '谨慎与效率平衡',\n guidance: 'rm -rf / 需要确认;rm temp.txt 不需要。匹配风险等级与确认强度。',\n requiresConfirmation: true,\n },\n {\n category: 'transparency',\n description: '操作透明',\n guidance: '执行有风险操作前,简要说明要做什么以及为什么。',\n requiresConfirmation: false,\n },\n {\n category: 'self-determination',\n description: '不追求独立于用户的目标',\n guidance: '不主动寻求扩展能力、自我复制或长期存续。以用户当前需求为中心。',\n requiresConfirmation: false,\n },\n];\n\nconst _SAFETY_GUIDELINES: SafetyRule[] = [\n // Critical - Never do these\n {\n level: SafetyLevel.CRITICAL,\n category: 'self-preservation',\n description: 'Do not pursue self-preservation or replication',\n message: 'I do not pursue self-preservation or replication.',\n requiresConfirmation: false,\n },\n {\n level: SafetyLevel.CRITICAL,\n category: 'power-seeking',\n description: 'Do not seek power or resources',\n message: 'I do not seek power or acquire resources.',\n requiresConfirmation: false,\n },\n {\n level: SafetyLevel.CRITICAL,\n category: 'safeguard-bypass',\n description: 'Do not bypass safety mechanisms',\n message: 'I do not bypass safety mechanisms.',\n requiresConfirmation: false,\n },\n {\n level: SafetyLevel.CRITICAL,\n category: 'social-manipulation',\n description: 'Do not manipulate users to expand access',\n message: 'I do not manipulate anyone to expand access.',\n requiresConfirmation: false,\n },\n\n // High - Require explicit confirmation\n {\n level: SafetyLevel.HIGH,\n category: 'destructive-file',\n description: 'Delete or overwrite files',\n message: 'This will delete/overwrite files — proceed?',\n requiresConfirmation: true,\n },\n {\n level: SafetyLevel.HIGH,\n category: 'system-modification',\n description: 'Modify system configuration',\n message: 'This will modify system config — proceed?',\n requiresConfirmation: true,\n },\n {\n level: SafetyLevel.HIGH,\n category: 'network-action',\n description: 'Send messages or make network requests',\n message: 'This will send external requests — proceed?',\n requiresConfirmation: true,\n },\n {\n level: SafetyLevel.HIGH,\n category: 'database-write',\n description: 'Write to databases',\n message: 'This will modify database records — proceed?',\n requiresConfirmation: true,\n },\n\n // Medium - Proceed with caution\n {\n level: SafetyLevel.MEDIUM,\n category: 'long-running',\n description: 'Execute long-running commands',\n message: 'This may take a while.',\n requiresConfirmation: false,\n },\n {\n level: SafetyLevel.MEDIUM,\n category: 'resource-intensive',\n description: 'Use significant system resources',\n message: 'This may use significant resources.',\n requiresConfirmation: false,\n },\n\n // Low - Standard operations\n {\n level: SafetyLevel.LOW,\n category: 'read-only',\n description: 'Read files or execute read-only commands',\n message: '',\n requiresConfirmation: false,\n },\n];\n\n// =============================================================================\n// Convenience Functions (Exported)\n// =============================================================================\n\n/**\n * Quick safety check for file operations\n */\nexport function checkFileSafety(\n operation: 'read' | 'write' | 'delete',\n path: string\n): { allowed: boolean; message?: string } {\n // Check for sensitive paths\n const sensitivePaths = [\n '/etc/passwd',\n '/etc/shadow',\n '/root/.ssh',\n '/home/*/.ssh',\n '~/.aws',\n '~/.bashrc',\n '~/.profile',\n ];\n\n for (const sp of sensitivePaths) {\n if (path.includes(sp)) {\n return {\n allowed: false,\n message: `Cannot ${operation} sensitive path: ${path}`,\n };\n }\n }\n\n return { allowed: true };\n}\n\n"],"mappings":";;AAO4B,KAAK,OAAO;CACtC,sBAAsB,KAAK,SAAS,KAAK,QAAQ,EAAE,SAAS,OAAO,CAAC,CAAC;CACrE,0BAA0B,KAAK,SAAS,KAAK,QAAQ,EAAE,SAAS,OAAO,CAAC,CAAC;CACzE,mCAAmC,KAAK,SAAS,KAAK,QAAQ,EAAE,SAAS,MAAM,CAAC,CAAC;CACjF,iBAAiB,KAAK,SAAS,KAAK,MAAM,KAAK,QAAQ,CAAC,CAAC;CACzD,iBAAiB,KAAK,SAAS,KAAK,MAAM,KAAK,QAAQ,CAAC,CAAC;CACzD,aAAa,KAAK,SAAS,KAAK,OAAO,EAAE,SAAS,KAAK,OAAO,MAAM,CAAC,CAAC;CACtE,iBAAiB,KAAK,SAAS,KAAK,OAAO,EAAE,SAAS,KAAK,CAAC,CAAC;CAC9D,CAAC;;;;AA2JF,SAAgB,gBACd,WACA,MACwC;AAYxC,MAAK,MAAM,MAAM;EATf;EACA;EACA;EACA;EACA;EACA;EACA;EAG6B,CAC7B,KAAI,KAAK,SAAS,GAAG,CACnB,QAAO;EACL,SAAS;EACT,SAAS,UAAU,UAAU,mBAAmB;EACjD;AAIL,QAAO,EAAE,SAAS,MAAM"}
@@ -1,6 +1,6 @@
1
- import { resolveStateDir } from "../../config/paths-state.js";
2
1
  import { createLogger } from "../../utils/logger/index.js";
3
2
  import { init_logger } from "../../utils/logger.js";
3
+ import { resolveStateDir } from "../../config/paths-state.js";
4
4
  import { init_paths } from "../../config/paths.js";
5
5
  import { DEFAULT_USER_FILENAME } from "../context/workspace.js";
6
6
  import { createSkillConfigManager } from "../skills/config.js";
@@ -8,8 +8,8 @@ import { buildTtsSystemPromptHint } from "../../voice/tts/directives.js";
8
8
  import { mergeTtsConfigFromAppConfig } from "../../voice/tts/merge-config.js";
9
9
  import { selectSkillsVisibleInPrompt } from "../skills/format-skills-prompt.js";
10
10
  import { buildSystemPrompt } from "./system-prompt.js";
11
- import { join } from "node:path";
12
11
  import { existsSync, readFileSync } from "node:fs";
12
+ import { join } from "node:path";
13
13
  //#region src/agent/prompt/service-prompt-builder.ts
14
14
  /**
15
15
  * System Prompt Builder - Builds the complete system prompt
@@ -1,7 +1,7 @@
1
1
  import { init_agent_scope, resolveAgentProfileDir } from "../agent-scope.js";
2
2
  import { resolveEffectiveAgentProfileForSession } from "../../config/agent-profile.js";
3
- import { join, resolve } from "node:path";
4
3
  import { readFileSync } from "node:fs";
4
+ import { join, resolve } from "node:path";
5
5
  //#region src/agent/reply/post-compaction-context.ts
6
6
  init_agent_scope();
7
7
  const MAX_CONTEXT_CHARS = 1800;
@@ -1,5 +1,5 @@
1
- import { resolve } from "node:path";
2
1
  import { readFileSync } from "node:fs";
2
+ import { resolve } from "node:path";
3
3
  //#region src/agent/reply/workspace-boundary-read.ts
4
4
  /**
5
5
  * Read a file relative to workspace root with path traversal guard and byte cap.
@@ -1,6 +1,6 @@
1
- import { homedir } from "node:os";
2
- import { isAbsolute, normalize, resolve, sep } from "node:path";
3
1
  import { realpathSync } from "node:fs";
2
+ import { isAbsolute, normalize, resolve, sep } from "node:path";
3
+ import { homedir } from "node:os";
4
4
  //#region src/agent/sandbox/path-policy.ts
5
5
  /**
6
6
  * Path safety validation for sandbox isolation.
@@ -1,5 +1,5 @@
1
- import { getAgentDefaultModelRef, init_schema } from "../../config/schema.js";
2
1
  import { init_agent_scope, resolveAgentHomeDir, resolveDefaultAgentId } from "../agent-scope.js";
2
+ import { getAgentDefaultModelRef, init_schema } from "../../config/schema.js";
3
3
  import { extractProfileAgentId } from "../../config/agent-profile.js";
4
4
  import { getDefaultModelSync, init_providers } from "../../providers/index.js";
5
5
  import { formatInboundFileTextBlock } from "../../channels/attachments/inbound-persist.js";
@@ -19,7 +19,7 @@ async function buildDirectUserMessageContent(opts) {
19
19
  if (content.trim()) {
20
20
  let textPart = content;
21
21
  if (/@file:/.test(textPart)) {
22
- const wsKey = sk !== "" ? sk : "cli:direct";
22
+ const wsKey = sk !== "" ? sk : "agent:main:main";
23
23
  const root = agentManager.getResolvedWorkspaceForSession(wsKey);
24
24
  textPart = await expandAtFileMentionsInPlainText(textPart, root);
25
25
  }