@xopcai/xopc 0.0.102 → 0.0.104

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 (995) hide show
  1. package/README.md +8 -5
  2. package/README.zh-CN.md +8 -5
  3. package/dist/_virtual/_rolldown/runtime.js +2 -3
  4. package/dist/browser-ext/manifest.json +1 -1
  5. package/dist/extensions/feishu/src/adapters/cli-login.d.ts +1 -1
  6. package/dist/extensions/feishu/src/adapters/cli-login.js +1 -1
  7. package/dist/extensions/feishu/src/adapters/cli-login.js.map +1 -1
  8. package/dist/extensions/feishu/src/adapters/gateway-setup.d.ts +2 -0
  9. package/dist/extensions/feishu/src/adapters/gateway-setup.js +225 -0
  10. package/dist/extensions/feishu/src/adapters/gateway-setup.js.map +1 -0
  11. package/dist/extensions/feishu/src/index.d.ts +8 -1
  12. package/dist/extensions/feishu/src/index.js +14 -1
  13. package/dist/extensions/feishu/src/index.js.map +1 -0
  14. package/dist/extensions/feishu/src/outbound/outbound-adapter.js +1 -1
  15. package/dist/extensions/feishu/src/plugin.d.ts +2 -1
  16. package/dist/extensions/feishu/src/plugin.js +2 -0
  17. package/dist/extensions/feishu/src/plugin.js.map +1 -1
  18. package/dist/extensions/feishu/src/streaming/streaming-adapter.js +1 -1
  19. package/dist/extensions/feishu/src/transport/webhook/monitor.js +2 -2
  20. package/dist/extensions/feishu/src/transport/webhook/monitor.js.map +1 -1
  21. package/dist/extensions/feishu/xopc.extension.json +66 -1
  22. package/dist/extensions/telegram/src/adapters/gateway-setup.d.ts +2 -0
  23. package/dist/extensions/telegram/src/adapters/gateway-setup.js +146 -0
  24. package/dist/extensions/telegram/src/adapters/gateway-setup.js.map +1 -0
  25. package/dist/extensions/telegram/src/adapters/security-adapter.js +1 -1
  26. package/dist/extensions/telegram/src/command-handler.js +1 -2
  27. package/dist/extensions/telegram/src/command-handler.js.map +1 -1
  28. package/dist/extensions/telegram/src/config-schema.js +2 -2
  29. package/dist/extensions/telegram/src/config-schema.js.map +1 -1
  30. package/dist/extensions/telegram/src/doctor.d.ts +1 -0
  31. package/dist/extensions/telegram/src/doctor.js +68 -0
  32. package/dist/extensions/telegram/src/doctor.js.map +1 -1
  33. package/dist/extensions/telegram/src/index.d.ts +8 -1
  34. package/dist/extensions/telegram/src/index.js +15 -2
  35. package/dist/extensions/telegram/src/index.js.map +1 -0
  36. package/dist/extensions/telegram/src/plugin.d.ts +13 -5
  37. package/dist/extensions/telegram/src/plugin.js +32 -12
  38. package/dist/extensions/telegram/src/plugin.js.map +1 -1
  39. package/dist/extensions/telegram/src/proxy-fetch.js +22 -5
  40. package/dist/extensions/telegram/src/proxy-fetch.js.map +1 -1
  41. package/dist/extensions/telegram/src/send-options.js +8 -5
  42. package/dist/extensions/telegram/src/send-options.js.map +1 -1
  43. package/dist/extensions/telegram/xopc.extension.json +412 -5
  44. package/dist/extensions/weixin/src/adapters/onboard-cli.js +2 -2
  45. package/dist/extensions/weixin/src/adapters/onboard-cli.js.map +1 -1
  46. package/dist/extensions/weixin/src/api/api.js +1 -1
  47. package/dist/extensions/weixin/src/index.d.ts +8 -0
  48. package/dist/extensions/weixin/src/index.js +12 -1
  49. package/dist/extensions/weixin/src/index.js.map +1 -0
  50. package/dist/extensions/weixin/src/messaging/process-message.js +1 -1
  51. package/dist/extensions/weixin/src/plugin.d.ts +2 -1
  52. package/dist/extensions/weixin/src/plugin.js +77 -2
  53. package/dist/extensions/weixin/src/plugin.js.map +1 -1
  54. package/dist/extensions/weixin/xopc.extension.json +52 -0
  55. package/dist/gateway/static/root/assets/agents-CvsBrBfi.js +396 -0
  56. package/dist/gateway/static/root/assets/{apps-page-Uv4kOmDE.js → apps-page-L-IwQTe0.js} +1 -1
  57. package/dist/gateway/static/root/assets/browser-BLJWD7WI.js +8 -0
  58. package/dist/gateway/static/root/assets/channels-settings-D95KuPeP.js +1 -0
  59. package/dist/gateway/static/root/assets/cron-page-CfkWXDAI.js +1 -0
  60. package/dist/gateway/static/root/assets/{dist-DH4IuRV0.js → dist-C6vclgEL.js} +1 -1
  61. package/dist/gateway/static/root/assets/{extension-debug-page-BNkhvRQW.js → extension-debug-page-D4JYAbsX.js} +1 -1
  62. package/dist/gateway/static/root/assets/{extension-page-CcIGQah2.js → extension-page-_T62gi6e.js} +1 -1
  63. package/dist/gateway/static/root/assets/extension-settings-page-CkJbjyM-.js +1 -0
  64. package/dist/gateway/static/root/assets/{fetch-drJUxxKP.js → fetch-B5aiIguv.js} +1 -1
  65. package/dist/gateway/static/root/assets/gateway-startup-retry-DqmLXhs6.js +1 -0
  66. package/dist/gateway/static/root/assets/heartbeat-config-api-HwJV1K_Y.js +1 -0
  67. package/dist/gateway/static/root/assets/index-BPYKW7FB.css +1 -0
  68. package/dist/gateway/static/root/assets/index-DvTb6wNR.js +4845 -0
  69. package/dist/gateway/static/root/assets/{logs-page-CiG0m81R.js → logs-page-DsjtTjBy.js} +2 -2
  70. package/dist/gateway/static/root/assets/{note-detail-page-DG3DVFTf.js → note-detail-page-B2V7RhgD.js} +43 -43
  71. package/dist/gateway/static/root/assets/{note-time-DjlllCF3.js → note-time-BG8GCTr4.js} +1 -1
  72. package/dist/gateway/static/root/assets/notes-page-xrcVBQ6Z.js +1 -0
  73. package/dist/gateway/static/root/assets/schema-form-S-QUvhul.js +1 -0
  74. package/dist/gateway/static/root/assets/sessions-page-CrQer6Au.js +1 -0
  75. package/dist/gateway/static/root/assets/settings-advanced-gate-DujQl9c7.js +2 -0
  76. package/dist/gateway/static/root/assets/{settings-form-section-C3_sEFfD.js → settings-form-section-r1V7dRV6.js} +1 -1
  77. package/dist/gateway/static/root/assets/settings-page-C9nrONQ2.js +3 -0
  78. package/dist/gateway/static/root/assets/share-preview-page-DOFy0FNt.js +2 -0
  79. package/dist/gateway/static/root/assets/skills-page-DmTsrs_a.js +2 -0
  80. package/dist/gateway/static/root/assets/{theme-store-B6KXPHgK.js → theme-store-Bo3j5Ovv.js} +1 -1
  81. package/dist/gateway/static/root/assets/url-WgQIjFZu.js +3 -0
  82. package/dist/gateway/static/root/assets/voice-api-key-field-AjmUAlEQ.js +1 -0
  83. package/dist/gateway/static/root/assets/{workflow-page.utils-g57BRfEd.js → workflow-page.utils-DLEJ92gK.js} +1 -1
  84. package/dist/gateway/static/root/assets/workflows-page-BnjjKrM1.js +27 -0
  85. package/dist/gateway/static/root/index.html +6 -5
  86. package/dist/package.js +1 -1
  87. package/dist/src/agent/agent-manager.d.ts +18 -6
  88. package/dist/src/agent/agent-manager.js +60 -35
  89. package/dist/src/agent/agent-manager.js.map +1 -1
  90. package/dist/src/agent/builtin-agent-ids.d.ts +2 -0
  91. package/dist/src/agent/builtin-agent-ids.js +17 -0
  92. package/dist/src/agent/builtin-agent-ids.js.map +1 -0
  93. package/dist/src/agent/child-agent-factory.d.ts +4 -0
  94. package/dist/src/agent/child-agent-factory.js +28 -8
  95. package/dist/src/agent/child-agent-factory.js.map +1 -1
  96. package/dist/src/agent/context/workspace-seed.js +1 -1
  97. package/dist/src/agent/context/workspace-templates/AGENTS.md +23 -184
  98. package/dist/src/agent/embedded/run-turn.js +8 -2
  99. package/dist/src/agent/embedded/run-turn.js.map +1 -1
  100. package/dist/src/agent/embedded/session-tool-result-guard.js +1 -1
  101. package/dist/src/agent/embedded/subscribe-session.js +33 -51
  102. package/dist/src/agent/embedded/subscribe-session.js.map +1 -1
  103. package/dist/src/agent/embedded/types.d.ts +36 -35
  104. package/dist/src/agent/fallback/candidates.js +1 -1
  105. package/dist/src/agent/fallback/candidates.js.map +1 -1
  106. package/dist/src/agent/inbound/attachment-pipeline.js +2 -2
  107. package/dist/src/agent/inbound/attachment-pipeline.js.map +1 -1
  108. package/dist/src/agent/inbound/inbound-loop.js +1 -1
  109. package/dist/src/agent/inbound/turn-dispatcher.d.ts +1 -0
  110. package/dist/src/agent/inbound/turn-dispatcher.js +24 -5
  111. package/dist/src/agent/inbound/turn-dispatcher.js.map +1 -1
  112. package/dist/src/agent/models/manager.d.ts +1 -1
  113. package/dist/src/agent/models/manager.js +1 -1
  114. package/dist/src/agent/models/manager.js.map +1 -1
  115. package/dist/src/agent/orchestration/run-agent-turn-with-fallbacks.d.ts +1 -1
  116. package/dist/src/agent/orchestration/run-agent-turn-with-fallbacks.js +1 -1
  117. package/dist/src/agent/orchestration/run-agent-turn-with-fallbacks.js.map +1 -1
  118. package/dist/src/agent/prompt/sections/tooling.js +4 -0
  119. package/dist/src/agent/prompt/sections/tooling.js.map +1 -1
  120. package/dist/src/agent/service/direct-turn-helpers.d.ts +1 -0
  121. package/dist/src/agent/service/direct-turn-helpers.js +1 -1
  122. package/dist/src/agent/service/direct-turn-helpers.js.map +1 -1
  123. package/dist/src/agent/service/process-direct-streaming.d.ts +1 -0
  124. package/dist/src/agent/service/process-direct-streaming.js +35 -18
  125. package/dist/src/agent/service/process-direct-streaming.js.map +1 -1
  126. package/dist/src/agent/service-inbound-utils.d.ts +0 -1
  127. package/dist/src/agent/service-inbound-utils.js +1 -17
  128. package/dist/src/agent/service-inbound-utils.js.map +1 -1
  129. package/dist/src/agent/service.d.ts +4 -4
  130. package/dist/src/agent/service.js +27 -15
  131. package/dist/src/agent/service.js.map +1 -1
  132. package/dist/src/agent/session/session-config-service.d.ts +1 -0
  133. package/dist/src/agent/session/session-config-service.js +9 -1
  134. package/dist/src/agent/session/session-config-service.js.map +1 -1
  135. package/dist/src/agent/session/session-inspector.d.ts +2 -1
  136. package/dist/src/agent/session/session-inspector.js +4 -0
  137. package/dist/src/agent/session/session-inspector.js.map +1 -1
  138. package/dist/src/agent/skills/config.js +1 -3
  139. package/dist/src/agent/skills/config.js.map +1 -1
  140. package/dist/src/agent/skills/format-skills-prompt.d.ts +1 -0
  141. package/dist/src/agent/skills/format-skills-prompt.js +3 -2
  142. package/dist/src/agent/skills/format-skills-prompt.js.map +1 -1
  143. package/dist/src/agent/skills/hub-pull.js +1 -1
  144. package/dist/src/agent/skills/index.js +20 -5
  145. package/dist/src/agent/skills/index.js.map +1 -1
  146. package/dist/src/agent/skills/installer.js +14 -27
  147. package/dist/src/agent/skills/installer.js.map +1 -1
  148. package/dist/src/agent/skills/marketplace/adapters/clawhub/adapter.js +11 -1
  149. package/dist/src/agent/skills/marketplace/adapters/clawhub/adapter.js.map +1 -1
  150. package/dist/src/agent/skills/marketplace/adapters/skillhub/adapter.js +18 -4
  151. package/dist/src/agent/skills/marketplace/adapters/skillhub/adapter.js.map +1 -1
  152. package/dist/src/agent/skills/marketplace/adapters/store/adapter.js +11 -2
  153. package/dist/src/agent/skills/marketplace/adapters/store/adapter.js.map +1 -1
  154. package/dist/src/agent/skills/marketplace/adapters/store/store-api-client.d.ts +2 -2
  155. package/dist/src/agent/skills/marketplace/adapters/store/store-api-client.js.map +1 -1
  156. package/dist/src/agent/skills/skill-manager.d.ts +4 -1
  157. package/dist/src/agent/skills/skill-manager.js +3 -3
  158. package/dist/src/agent/skills/skill-manager.js.map +1 -1
  159. package/dist/src/agent/skills/skill-view-path.d.ts +1 -17
  160. package/dist/src/agent/skills/skill-view-path.js +3 -66
  161. package/dist/src/agent/skills/skill-view-path.js.map +1 -1
  162. package/dist/src/agent/skills/test-framework.js +2 -3
  163. package/dist/src/agent/skills/test-framework.js.map +1 -1
  164. package/dist/src/agent/streaming/reasoning-visibility-sse.js +1 -0
  165. package/dist/src/agent/streaming/reasoning-visibility-sse.js.map +1 -1
  166. package/dist/src/agent/tool-manuals/browser.d.ts +1 -0
  167. package/{skills/browser/SKILL.md → dist/src/agent/tool-manuals/browser.js} +51 -54
  168. package/dist/src/agent/tool-manuals/browser.js.map +1 -0
  169. package/dist/src/agent/tool-manuals/index.d.ts +10 -0
  170. package/dist/src/agent/tool-manuals/index.js +28 -0
  171. package/dist/src/agent/tool-manuals/index.js.map +1 -0
  172. package/dist/src/agent/tools/browser/tool/browser-use-tool.js +1 -1
  173. package/dist/src/agent/tools/browser/tool/browser-use-tool.js.map +1 -1
  174. package/dist/src/agent/tools/factory.js +7 -5
  175. package/dist/src/agent/tools/factory.js.map +1 -1
  176. package/dist/src/agent/tools/index.d.ts +1 -0
  177. package/dist/src/agent/tools/index.js +5 -4
  178. package/dist/src/agent/tools/send-media.js +1 -2
  179. package/dist/src/agent/tools/send-media.js.map +1 -1
  180. package/dist/src/agent/tools/session-search-tool.js +1 -1
  181. package/dist/src/agent/tools/shell.js +1 -1
  182. package/dist/src/agent/tools/skills-tools.js +37 -8
  183. package/dist/src/agent/tools/skills-tools.js.map +1 -1
  184. package/dist/src/agent/tools/tool-manual-tool.d.ts +6 -0
  185. package/dist/src/agent/tools/tool-manual-tool.js +34 -0
  186. package/dist/src/agent/tools/tool-manual-tool.js.map +1 -0
  187. package/dist/src/agent/tools/web-extract.js +2 -2
  188. package/dist/src/agent/tools/web.js +1 -1
  189. package/dist/src/agent/workflow/catalog.d.ts +7 -2
  190. package/dist/src/agent/workflow/catalog.js +66 -25
  191. package/dist/src/agent/workflow/catalog.js.map +1 -1
  192. package/dist/src/agent/workflow/subagent-runner.d.ts +3 -0
  193. package/dist/src/agent/workflow/subagent-runner.js +50 -4
  194. package/dist/src/agent/workflow/subagent-runner.js.map +1 -1
  195. package/dist/src/agent/workflow/types.d.ts +10 -0
  196. package/dist/src/auth/credentials.d.ts +7 -0
  197. package/dist/src/auth/credentials.js +45 -7
  198. package/dist/src/auth/credentials.js.map +1 -1
  199. package/dist/src/auth/index.d.ts +1 -1
  200. package/dist/src/auth/index.js.map +1 -1
  201. package/dist/src/auth/oauth/github-copilot.d.ts +1 -1
  202. package/dist/src/auth/oauth/google-antigravity.d.ts +1 -3
  203. package/dist/src/auth/oauth/google-antigravity.js +1 -1
  204. package/dist/src/auth/oauth/google-gemini-cli.d.ts +1 -3
  205. package/dist/src/auth/oauth/google-gemini-cli.js +1 -1
  206. package/dist/src/auth/oauth/{vendor-pi-google → google-oauth}/google-antigravity.js +3 -5
  207. package/dist/src/auth/oauth/google-oauth/google-antigravity.js.map +1 -0
  208. package/dist/src/auth/oauth/{vendor-pi-google → google-oauth}/google-gemini-cli.js +4 -5
  209. package/dist/src/auth/oauth/google-oauth/google-gemini-cli.js.map +1 -0
  210. package/dist/src/auth/oauth/{vendor-pi-google → google-oauth}/oauth-page.js +12 -4
  211. package/dist/src/auth/oauth/google-oauth/oauth-page.js.map +1 -0
  212. package/dist/src/auth/oauth/{vendor-pi-google → google-oauth}/pkce.d.ts +1 -1
  213. package/dist/src/auth/oauth/{vendor-pi-google → google-oauth}/pkce.js +2 -2
  214. package/dist/src/auth/oauth/google-oauth/pkce.js.map +1 -0
  215. package/dist/src/auth/oauth/index.js +2 -2
  216. package/dist/src/auth/oauth/kimi-coding.d.ts +1 -1
  217. package/dist/src/auth/oauth/kimi-coding.js +1 -1
  218. package/dist/src/auth/oauth/kimi-coding.js.map +1 -1
  219. package/dist/src/auth/oauth/minimax-cn.js +1 -1
  220. package/dist/src/auth/oauth/minimax-cn.js.map +1 -1
  221. package/dist/src/auth/oauth/minimax.js +1 -1
  222. package/dist/src/auth/oauth/minimax.js.map +1 -1
  223. package/dist/src/auth/oauth/openai-codex.d.ts +7 -2
  224. package/dist/src/auth/oauth/openai-codex.js +318 -1
  225. package/dist/src/auth/oauth/openai-codex.js.map +1 -0
  226. package/dist/src/auth/profiles/store.js +3 -2
  227. package/dist/src/auth/profiles/store.js.map +1 -1
  228. package/dist/src/browser/actions/extension-registry-bridge.js +1 -1
  229. package/dist/src/browser/actions/registry.js +2 -2
  230. package/dist/src/browser/cdp-local-launcher.js +1 -1
  231. package/dist/src/browser/index.js +3 -3
  232. package/dist/src/browser/providers/browser-ext-install.js +1 -1
  233. package/dist/src/browser/providers/cloakbrowser.js +1 -1
  234. package/dist/src/channels/attachments/attachment-classifiers.d.ts +1 -0
  235. package/dist/src/channels/attachments/attachment-classifiers.js +13 -2
  236. package/dist/src/channels/attachments/attachment-classifiers.js.map +1 -1
  237. package/dist/src/channels/catalog/channel-catalog-service.d.ts +11 -0
  238. package/dist/src/channels/catalog/channel-catalog-service.js +168 -0
  239. package/dist/src/channels/catalog/channel-catalog-service.js.map +1 -0
  240. package/dist/src/channels/catalog/channel-catalog-types.d.ts +22 -0
  241. package/dist/src/channels/catalog/channel-catalog-types.js +1 -0
  242. package/dist/src/channels/dock.d.ts +0 -7
  243. package/dist/src/channels/dock.js +1 -21
  244. package/dist/src/channels/index.d.ts +1 -3
  245. package/dist/src/channels/index.js +1 -5
  246. package/dist/src/channels/lifecycle-supervisor.d.ts +1 -0
  247. package/dist/src/channels/lifecycle-supervisor.js +11 -0
  248. package/dist/src/channels/lifecycle-supervisor.js.map +1 -1
  249. package/dist/src/channels/manager.d.ts +1 -0
  250. package/dist/src/channels/manager.js +3 -0
  251. package/dist/src/channels/manager.js.map +1 -1
  252. package/dist/src/channels/pairing/pairing-channel.d.ts +2 -3
  253. package/dist/src/channels/pairing/pairing-messages.js +1 -1
  254. package/dist/src/channels/pairing/pairing-messages.js.map +1 -1
  255. package/dist/src/channels/pairing/pairing-service.d.ts +1 -1
  256. package/dist/src/channels/pairing/pairing-service.js +8 -27
  257. package/dist/src/channels/pairing/pairing-service.js.map +1 -1
  258. package/dist/src/channels/plugin-types.d.ts +3 -1
  259. package/dist/src/channels/plugins/types.adapters.d.ts +55 -2
  260. package/dist/src/channels/telegram/index.js +1 -1
  261. package/dist/src/chat-commands/builtins/config.js +4 -4
  262. package/dist/src/chat-commands/builtins/config.js.map +1 -1
  263. package/dist/src/chat-commands/builtins/model.js +2 -2
  264. package/dist/src/chat-commands/builtins/model.js.map +1 -1
  265. package/dist/src/chat-commands/config-paths.js +1 -1
  266. package/dist/src/chat-commands/config-paths.js.map +1 -1
  267. package/dist/src/chat-commands/context.js +1 -1
  268. package/dist/src/chat-commands/context.js.map +1 -1
  269. package/dist/src/cli/bin.js +1 -1
  270. package/dist/src/cli/command-manifest.js +2 -2
  271. package/dist/src/cli/command-manifest.js.map +1 -1
  272. package/dist/src/cli/commands/agent.js +2 -2
  273. package/dist/src/cli/commands/agent.js.map +1 -1
  274. package/dist/src/cli/commands/agents.js +2 -4
  275. package/dist/src/cli/commands/agents.js.map +1 -1
  276. package/dist/src/cli/commands/auth.js +40 -52
  277. package/dist/src/cli/commands/auth.js.map +1 -1
  278. package/dist/src/cli/commands/browser-cli-helpers.js +1 -1
  279. package/dist/src/cli/commands/channels.d.ts +1 -5
  280. package/dist/src/cli/commands/channels.js +115 -281
  281. package/dist/src/cli/commands/channels.js.map +1 -1
  282. package/dist/src/cli/commands/config.js +2 -2
  283. package/dist/src/cli/commands/config.js.map +1 -1
  284. package/dist/src/cli/commands/doctor/checks/channel-config.js +16 -69
  285. package/dist/src/cli/commands/doctor/checks/channel-config.js.map +1 -1
  286. package/dist/src/cli/commands/doctor/checks/channel-pairing-pending.js +6 -4
  287. package/dist/src/cli/commands/doctor/checks/channel-pairing-pending.js.map +1 -1
  288. package/dist/src/cli/commands/doctor/checks/channel-plugins.js +2 -2
  289. package/dist/src/cli/commands/doctor/checks/channel-plugins.js.map +1 -1
  290. package/dist/src/cli/commands/doctor/checks/database-schema.js +1 -1
  291. package/dist/src/cli/commands/doctor/checks/provider-auth.js +13 -9
  292. package/dist/src/cli/commands/doctor/checks/provider-auth.js.map +1 -1
  293. package/dist/src/cli/commands/extension-dev.js +2 -1
  294. package/dist/src/cli/commands/extension-dev.js.map +1 -1
  295. package/dist/src/cli/commands/extension-marketplace.js +2 -1
  296. package/dist/src/cli/commands/extension-marketplace.js.map +1 -1
  297. package/dist/src/cli/commands/extension-pack.js +2 -1
  298. package/dist/src/cli/commands/extension-pack.js.map +1 -1
  299. package/dist/src/cli/commands/models.js +192 -54
  300. package/dist/src/cli/commands/models.js.map +1 -1
  301. package/dist/src/cli/commands/onboard/channels/index.js +1 -1
  302. package/dist/src/cli/commands/onboard/channels/index.js.map +1 -1
  303. package/dist/src/cli/commands/onboard/channels/registry.d.ts +2 -1
  304. package/dist/src/cli/commands/onboard/channels/registry.js +32 -8
  305. package/dist/src/cli/commands/onboard/channels/registry.js.map +1 -1
  306. package/dist/src/cli/commands/onboard/model.d.ts +1 -4
  307. package/dist/src/cli/commands/onboard/model.js +257 -184
  308. package/dist/src/cli/commands/onboard/model.js.map +1 -1
  309. package/dist/src/cli/commands/onboard.js +4 -6
  310. package/dist/src/cli/commands/onboard.js.map +1 -1
  311. package/dist/src/cli/commands/setup-shared/runner.d.ts +1 -1
  312. package/dist/src/cli/commands/setup-shared/runner.js.map +1 -1
  313. package/dist/src/cli/commands/setup-shared/types.d.ts +1 -1
  314. package/dist/src/cli/commands/setup-shared/types.js.map +1 -1
  315. package/dist/src/cli/commands/tui.js +13 -5
  316. package/dist/src/cli/commands/tui.js.map +1 -1
  317. package/dist/src/cli/extension-cli-register.js +1 -1
  318. package/dist/src/cli/utils/oauth-login.d.ts +17 -0
  319. package/dist/src/cli/utils/oauth-login.js +93 -0
  320. package/dist/src/cli/utils/oauth-login.js.map +1 -0
  321. package/dist/src/cli/utils/oauth-providers.js +2 -2
  322. package/dist/src/commands/agents.config.d.ts +3 -3
  323. package/dist/src/commands/agents.config.js +7 -7
  324. package/dist/src/commands/agents.config.js.map +1 -1
  325. package/dist/src/config/agent-profile.d.ts +1 -1
  326. package/dist/src/config/agent-profile.js +6 -2
  327. package/dist/src/config/agent-profile.js.map +1 -1
  328. package/dist/src/config/agent-typed-models.d.ts +2 -2
  329. package/dist/src/config/agent-typed-models.js +13 -2
  330. package/dist/src/config/agent-typed-models.js.map +1 -1
  331. package/dist/src/config/index.js +3 -3
  332. package/dist/src/config/integration.d.ts +1 -1
  333. package/dist/src/config/loader.d.ts +0 -1
  334. package/dist/src/config/loader.js +4 -9
  335. package/dist/src/config/loader.js.map +1 -1
  336. package/dist/src/config/models-json.d.ts +6 -6
  337. package/dist/src/config/rules.js +2 -12
  338. package/dist/src/config/rules.js.map +1 -1
  339. package/dist/src/config/schema.d.ts +74 -47
  340. package/dist/src/config/schema.js +28 -66
  341. package/dist/src/config/schema.js.map +1 -1
  342. package/dist/src/config/validate-channel-configs.d.ts +0 -3
  343. package/dist/src/config/validate-channel-configs.js +29 -10
  344. package/dist/src/config/validate-channel-configs.js.map +1 -1
  345. package/dist/src/cron/executor.js +1 -4
  346. package/dist/src/cron/executor.js.map +1 -1
  347. package/dist/src/extensions/activation-context.js +3 -1
  348. package/dist/src/extensions/activation-context.js.map +1 -1
  349. package/dist/src/extensions/activation-planner.js +12 -0
  350. package/dist/src/extensions/activation-planner.js.map +1 -1
  351. package/dist/src/extensions/api.d.ts +5 -1
  352. package/dist/src/extensions/api.js +12 -0
  353. package/dist/src/extensions/api.js.map +1 -1
  354. package/dist/src/extensions/discover-extensions.js +17 -13
  355. package/dist/src/extensions/discover-extensions.js.map +1 -1
  356. package/dist/src/extensions/extension-metadata-snapshot.js +11 -5
  357. package/dist/src/extensions/extension-metadata-snapshot.js.map +1 -1
  358. package/dist/src/extensions/index.js +12 -4
  359. package/dist/src/extensions/index.js.map +1 -0
  360. package/dist/src/extensions/loader.d.ts +5 -1
  361. package/dist/src/extensions/loader.js +12 -11
  362. package/dist/src/extensions/loader.js.map +1 -1
  363. package/dist/src/extensions/manifest-registry.js +98 -93
  364. package/dist/src/extensions/manifest-registry.js.map +1 -1
  365. package/dist/src/extensions/normalize-manifest.js +91 -15
  366. package/dist/src/extensions/normalize-manifest.js.map +1 -1
  367. package/dist/src/extensions/sdk/index.js +1 -1
  368. package/dist/src/extensions/sdk/testing.js +4 -0
  369. package/dist/src/extensions/sdk/testing.js.map +1 -1
  370. package/dist/src/extensions/types/core.d.ts +32 -1
  371. package/dist/src/extensions/types/manifest.d.ts +60 -0
  372. package/dist/src/extensions/types/tui.d.ts +414 -5
  373. package/dist/src/gateway/agent-builtin-tools.d.ts +1 -1
  374. package/dist/src/gateway/agent-builtin-tools.js +16 -0
  375. package/dist/src/gateway/agent-builtin-tools.js.map +1 -1
  376. package/dist/src/gateway/agent-run-relay.d.ts +2 -3
  377. package/dist/src/gateway/agent-run-relay.js +10 -3
  378. package/dist/src/gateway/agent-run-relay.js.map +1 -1
  379. package/dist/src/gateway/agents-admin.d.ts +32 -19
  380. package/dist/src/gateway/agents-admin.js +113 -93
  381. package/dist/src/gateway/agents-admin.js.map +1 -1
  382. package/dist/src/gateway/chat-stream/mapper.d.ts +34 -0
  383. package/dist/src/gateway/chat-stream/mapper.js +244 -0
  384. package/dist/src/gateway/chat-stream/mapper.js.map +1 -0
  385. package/dist/src/gateway/chat-stream/protocol.d.ts +100 -0
  386. package/dist/src/gateway/chat-stream/protocol.js +1 -0
  387. package/dist/src/gateway/hono/lib/agent-model.d.ts +4 -4
  388. package/dist/src/gateway/hono/lib/agent-model.js +13 -11
  389. package/dist/src/gateway/hono/lib/agent-model.js.map +1 -1
  390. package/dist/src/gateway/hono/lib/config-payload.d.ts +19 -7
  391. package/dist/src/gateway/hono/lib/config-payload.js +16 -15
  392. package/dist/src/gateway/hono/lib/config-payload.js.map +1 -1
  393. package/dist/src/gateway/hono/oauth-async.js +2 -2
  394. package/dist/src/gateway/hono/oauth.js +2 -2
  395. package/dist/src/gateway/hono/routes/agents.js +83 -48
  396. package/dist/src/gateway/hono/routes/agents.js.map +1 -1
  397. package/dist/src/gateway/hono/routes/channels.js +134 -214
  398. package/dist/src/gateway/hono/routes/channels.js.map +1 -1
  399. package/dist/src/gateway/hono/routes/commands-skills.js +10 -4
  400. package/dist/src/gateway/hono/routes/commands-skills.js.map +1 -1
  401. package/dist/src/gateway/hono/routes/config-patch/agents.js +26 -13
  402. package/dist/src/gateway/hono/routes/config-patch/agents.js.map +1 -1
  403. package/dist/src/gateway/hono/routes/config-patch/channels.d.ts +1 -11
  404. package/dist/src/gateway/hono/routes/config-patch/channels.js +18 -165
  405. package/dist/src/gateway/hono/routes/config-patch/channels.js.map +1 -1
  406. package/dist/src/gateway/hono/routes/config.js +5 -2
  407. package/dist/src/gateway/hono/routes/config.js.map +1 -1
  408. package/dist/src/gateway/hono/routes/dreaming.js +1 -1
  409. package/dist/src/gateway/hono/routes/lazy-bundles.js +13 -1
  410. package/dist/src/gateway/hono/routes/lazy-bundles.js.map +1 -1
  411. package/dist/src/gateway/hono/routes/models.js +25 -5
  412. package/dist/src/gateway/hono/routes/models.js.map +1 -1
  413. package/dist/src/gateway/hono/routes/public-gateway.js +2 -4
  414. package/dist/src/gateway/hono/routes/public-gateway.js.map +1 -1
  415. package/dist/src/gateway/hono/routes/sessions.js +179 -0
  416. package/dist/src/gateway/hono/routes/sessions.js.map +1 -1
  417. package/dist/src/gateway/hono/routes/tui.d.ts +3 -0
  418. package/dist/src/gateway/hono/routes/tui.js +16 -0
  419. package/dist/src/gateway/hono/routes/tui.js.map +1 -0
  420. package/dist/src/gateway/hono/routes/workflows.js +25 -1
  421. package/dist/src/gateway/hono/routes/workflows.js.map +1 -1
  422. package/dist/src/gateway/hono/sse.d.ts +5 -7
  423. package/dist/src/gateway/hono/sse.js +21 -38
  424. package/dist/src/gateway/hono/sse.js.map +1 -1
  425. package/dist/src/gateway/protocol.js.map +1 -1
  426. package/dist/src/gateway/service/agent-runner.d.ts +2 -4
  427. package/dist/src/gateway/service/agent-runner.js +1 -1
  428. package/dist/src/gateway/service/agent-runner.js.map +1 -1
  429. package/dist/src/gateway/service/marketplace-service.d.ts +4 -3
  430. package/dist/src/gateway/service/marketplace-service.js +7 -4
  431. package/dist/src/gateway/service/marketplace-service.js.map +1 -1
  432. package/dist/src/gateway/service/run-gateway-agent.d.ts +2 -6
  433. package/dist/src/gateway/service/run-gateway-agent.js +63 -36
  434. package/dist/src/gateway/service/run-gateway-agent.js.map +1 -1
  435. package/dist/src/gateway/service/sessions-api.d.ts +19 -0
  436. package/dist/src/gateway/service/sessions-api.js +12 -0
  437. package/dist/src/gateway/service/sessions-api.js.map +1 -1
  438. package/dist/src/gateway/service.d.ts +6 -0
  439. package/dist/src/gateway/service.js +73 -57
  440. package/dist/src/gateway/service.js.map +1 -1
  441. package/dist/src/mcp/channel-bridge.js +1 -1
  442. package/dist/src/media/store.js +3 -0
  443. package/dist/src/media/store.js.map +1 -1
  444. package/dist/src/notes/service.js +1 -1
  445. package/dist/src/notes/service.js.map +1 -1
  446. package/dist/src/project-trust/trust-store.d.ts +30 -0
  447. package/dist/src/project-trust/trust-store.js +194 -0
  448. package/dist/src/project-trust/trust-store.js.map +1 -0
  449. package/dist/src/providers/index.d.ts +4 -4
  450. package/dist/src/providers/index.js +41 -22
  451. package/dist/src/providers/index.js.map +1 -1
  452. package/dist/src/providers/presentation.d.ts +34 -0
  453. package/dist/src/providers/presentation.js +162 -0
  454. package/dist/src/providers/presentation.js.map +1 -0
  455. package/dist/src/routing/resolve-route.d.ts +0 -3
  456. package/dist/src/routing/resolve-route.js.map +1 -1
  457. package/dist/src/routing/resolve-tui-session-key.d.ts +2 -0
  458. package/dist/src/routing/resolve-tui-session-key.js +8 -3
  459. package/dist/src/routing/resolve-tui-session-key.js.map +1 -1
  460. package/dist/src/session/client-history.d.ts +32 -0
  461. package/dist/src/session/client-history.js +232 -1
  462. package/dist/src/session/client-history.js.map +1 -1
  463. package/dist/src/session/manager.d.ts +37 -4
  464. package/dist/src/session/manager.js +39 -15
  465. package/dist/src/session/manager.js.map +1 -1
  466. package/dist/src/session/session-context-for-llm.d.ts +93 -1
  467. package/dist/src/session/session-context-for-llm.js +105 -2
  468. package/dist/src/session/session-context-for-llm.js.map +1 -1
  469. package/dist/src/session/store.d.ts +37 -0
  470. package/dist/src/session/store.js +127 -2
  471. package/dist/src/session/store.js.map +1 -1
  472. package/dist/src/session/stored-rows-to-file-entries.js +37 -1
  473. package/dist/src/session/stored-rows-to-file-entries.js.map +1 -1
  474. package/dist/src/session/types.d.ts +14 -1
  475. package/dist/src/session/types.js.map +1 -1
  476. package/dist/src/share/share-thumbnail.js +1 -1
  477. package/dist/src/storage/sqlite/migrations/004_add_session_type_metadata.sql +15 -0
  478. package/dist/src/storage/sqlite/migrations/runner.d.ts +1 -1
  479. package/dist/src/storage/sqlite/migrations/runner.js +3 -3
  480. package/dist/src/storage/sqlite/migrations/runner.js.map +1 -1
  481. package/dist/src/storage/sqlite/migrations/runner.ts +1 -1
  482. package/dist/src/storage/sqlite/row-mappers.d.ts +14 -1
  483. package/dist/src/storage/sqlite/row-mappers.js +14 -1
  484. package/dist/src/storage/sqlite/row-mappers.js.map +1 -1
  485. package/dist/src/storage/sqlite/schema.js +1 -1
  486. package/dist/src/storage/sqlite/session-metadata.js +1 -0
  487. package/dist/src/storage/sqlite/session-metadata.js.map +1 -1
  488. package/dist/src/storage/sqlite/session-repository.js +52 -25
  489. package/dist/src/storage/sqlite/session-repository.js.map +1 -1
  490. package/dist/src/tui/backends/embedded-backend.d.ts +53 -4
  491. package/dist/src/tui/backends/embedded-backend.js +227 -39
  492. package/dist/src/tui/backends/embedded-backend.js.map +1 -1
  493. package/dist/src/tui/backends/gateway-sse-backend.d.ts +59 -3
  494. package/dist/src/tui/backends/gateway-sse-backend.js +416 -26
  495. package/dist/src/tui/backends/gateway-sse-backend.js.map +1 -1
  496. package/dist/src/tui/chat-history.d.ts +5 -1
  497. package/dist/src/tui/chat-history.js +78 -8
  498. package/dist/src/tui/chat-history.js.map +1 -1
  499. package/dist/src/tui/clipboard-text.d.ts +5 -0
  500. package/dist/src/tui/clipboard-text.js +46 -0
  501. package/dist/src/tui/clipboard-text.js.map +1 -0
  502. package/dist/src/tui/components/assistant-message.d.ts +19 -3
  503. package/dist/src/tui/components/assistant-message.js +115 -9
  504. package/dist/src/tui/components/assistant-message.js.map +1 -1
  505. package/dist/src/tui/components/bash-execution.d.ts +3 -2
  506. package/dist/src/tui/components/bash-execution.js +31 -3
  507. package/dist/src/tui/components/bash-execution.js.map +1 -1
  508. package/dist/src/tui/components/bash-summary.d.ts +23 -0
  509. package/dist/src/tui/components/bash-summary.js +87 -0
  510. package/dist/src/tui/components/bash-summary.js.map +1 -0
  511. package/dist/src/tui/components/branch-message-summary.d.ts +17 -0
  512. package/dist/src/tui/components/branch-message-summary.js +43 -0
  513. package/dist/src/tui/components/branch-message-summary.js.map +1 -0
  514. package/dist/src/tui/components/branch-summary.d.ts +13 -0
  515. package/dist/src/tui/components/branch-summary.js +51 -0
  516. package/dist/src/tui/components/branch-summary.js.map +1 -0
  517. package/dist/src/tui/components/chat-log.d.ts +46 -6
  518. package/dist/src/tui/components/chat-log.js +183 -21
  519. package/dist/src/tui/components/chat-log.js.map +1 -1
  520. package/dist/src/tui/components/compaction-summary.d.ts +13 -0
  521. package/dist/src/tui/components/compaction-summary.js +46 -0
  522. package/dist/src/tui/components/compaction-summary.js.map +1 -0
  523. package/dist/src/tui/components/custom-editor.d.ts +1 -0
  524. package/dist/src/tui/components/custom-editor.js +2 -0
  525. package/dist/src/tui/components/custom-editor.js.map +1 -1
  526. package/dist/src/tui/components/custom-message.d.ts +23 -0
  527. package/dist/src/tui/components/custom-message.js +65 -0
  528. package/dist/src/tui/components/custom-message.js.map +1 -0
  529. package/dist/src/tui/components/extension-dialog.d.ts +42 -0
  530. package/dist/src/tui/components/extension-dialog.js +127 -0
  531. package/dist/src/tui/components/extension-dialog.js.map +1 -0
  532. package/dist/src/tui/components/scoped-models-selector.d.ts +7 -2
  533. package/dist/src/tui/components/scoped-models-selector.js +89 -16
  534. package/dist/src/tui/components/scoped-models-selector.js.map +1 -1
  535. package/dist/src/tui/components/searchable-select-list.d.ts +30 -3
  536. package/dist/src/tui/components/searchable-select-list.js +82 -10
  537. package/dist/src/tui/components/searchable-select-list.js.map +1 -1
  538. package/dist/src/tui/components/session-selector.d.ts +18 -4
  539. package/dist/src/tui/components/session-selector.js +207 -40
  540. package/dist/src/tui/components/session-selector.js.map +1 -1
  541. package/dist/src/tui/components/settings-selector.d.ts +6 -2
  542. package/dist/src/tui/components/settings-selector.js +126 -7
  543. package/dist/src/tui/components/settings-selector.js.map +1 -1
  544. package/dist/src/tui/components/thinking-selector.d.ts +12 -0
  545. package/dist/src/tui/components/thinking-selector.js +48 -0
  546. package/dist/src/tui/components/thinking-selector.js.map +1 -0
  547. package/dist/src/tui/components/tool-execution.d.ts +57 -3
  548. package/dist/src/tui/components/tool-execution.js +378 -28
  549. package/dist/src/tui/components/tool-execution.js.map +1 -1
  550. package/dist/src/tui/components/tui-bottom-bar.d.ts +9 -1
  551. package/dist/src/tui/components/tui-bottom-bar.js +56 -11
  552. package/dist/src/tui/components/tui-bottom-bar.js.map +1 -1
  553. package/dist/src/tui/components/tui-header.d.ts +9 -2
  554. package/dist/src/tui/components/tui-header.js +25 -5
  555. package/dist/src/tui/components/tui-header.js.map +1 -1
  556. package/dist/src/tui/components/user-message.d.ts +4 -2
  557. package/dist/src/tui/components/user-message.js +42 -9
  558. package/dist/src/tui/components/user-message.js.map +1 -1
  559. package/dist/src/tui/components/visual-truncate.d.ts +11 -0
  560. package/dist/src/tui/components/visual-truncate.js +27 -0
  561. package/dist/src/tui/components/visual-truncate.js.map +1 -0
  562. package/dist/src/tui/extension-host/autocomplete.d.ts +43 -0
  563. package/dist/src/tui/extension-host/autocomplete.js +116 -0
  564. package/dist/src/tui/extension-host/autocomplete.js.map +1 -0
  565. package/dist/src/tui/extension-host/host.d.ts +31 -1
  566. package/dist/src/tui/extension-host/host.js +123 -6
  567. package/dist/src/tui/extension-host/host.js.map +1 -1
  568. package/dist/src/tui/extension-host/load-extensions.d.ts +6 -1
  569. package/dist/src/tui/extension-host/load-extensions.js +4 -3
  570. package/dist/src/tui/extension-host/load-extensions.js.map +1 -1
  571. package/dist/src/tui/extension-host/runtime-context.d.ts +21 -0
  572. package/dist/src/tui/extension-host/runtime-context.js +152 -0
  573. package/dist/src/tui/extension-host/runtime-context.js.map +1 -0
  574. package/dist/src/tui/extension-host/runtime.d.ts +52 -4
  575. package/dist/src/tui/extension-host/runtime.js +547 -85
  576. package/dist/src/tui/extension-host/runtime.js.map +1 -1
  577. package/dist/src/tui/extension-host/surface.d.ts +20 -0
  578. package/dist/src/tui/extension-host/surface.js +30 -6
  579. package/dist/src/tui/extension-host/surface.js.map +1 -1
  580. package/dist/src/tui/extension-host/tool-renderers.d.ts +6 -3
  581. package/dist/src/tui/extension-host/tool-renderers.js +43 -5
  582. package/dist/src/tui/extension-host/tool-renderers.js.map +1 -1
  583. package/dist/src/tui/format-tui-hotkeys.d.ts +12 -2
  584. package/dist/src/tui/format-tui-hotkeys.js +22 -5
  585. package/dist/src/tui/format-tui-hotkeys.js.map +1 -1
  586. package/dist/src/tui/tui-agent-events.d.ts +8 -6
  587. package/dist/src/tui/tui-agent-events.js +200 -59
  588. package/dist/src/tui/tui-agent-events.js.map +1 -1
  589. package/dist/src/tui/tui-backend.d.ts +169 -3
  590. package/dist/src/tui/tui-command-formatters.d.ts +76 -0
  591. package/dist/src/tui/tui-command-formatters.js +594 -0
  592. package/dist/src/tui/tui-command-formatters.js.map +1 -0
  593. package/dist/src/tui/tui-commands.d.ts +57 -7
  594. package/dist/src/tui/tui-commands.js +639 -43
  595. package/dist/src/tui/tui-commands.js.map +1 -1
  596. package/dist/src/tui/tui-context-usage.d.ts +1 -1
  597. package/dist/src/tui/tui-context-usage.js +9 -1
  598. package/dist/src/tui/tui-context-usage.js.map +1 -1
  599. package/dist/src/tui/tui-extension-user-message.d.ts +8 -0
  600. package/dist/src/tui/tui-extension-user-message.js +32 -0
  601. package/dist/src/tui/tui-extension-user-message.js.map +1 -0
  602. package/dist/src/tui/tui-follow-up-queue.d.ts +9 -0
  603. package/dist/src/tui/tui-follow-up-queue.js +18 -0
  604. package/dist/src/tui/tui-follow-up-queue.js.map +1 -0
  605. package/dist/src/tui/tui-local-shell.d.ts +11 -1
  606. package/dist/src/tui/tui-local-shell.js +50 -8
  607. package/dist/src/tui/tui-local-shell.js.map +1 -1
  608. package/dist/src/tui/tui-model-picker.d.ts +26 -0
  609. package/dist/src/tui/tui-model-picker.js +152 -0
  610. package/dist/src/tui/tui-model-picker.js.map +1 -0
  611. package/dist/src/tui/tui-oauth-login.d.ts +16 -0
  612. package/dist/src/tui/tui-oauth-login.js +189 -0
  613. package/dist/src/tui/tui-oauth-login.js.map +1 -0
  614. package/dist/src/tui/tui-overlays.d.ts +3 -3
  615. package/dist/src/tui/tui-overlays.js +6 -7
  616. package/dist/src/tui/tui-overlays.js.map +1 -1
  617. package/dist/src/tui/tui-picker-overlay.d.ts +27 -32
  618. package/dist/src/tui/tui-picker-overlay.js +340 -30
  619. package/dist/src/tui/tui-picker-overlay.js.map +1 -1
  620. package/dist/src/tui/tui-picker-services.d.ts +41 -0
  621. package/dist/src/tui/tui-picker-services.js +1 -0
  622. package/dist/src/tui/tui-run-state.d.ts +11 -0
  623. package/dist/src/tui/tui-run-state.js +114 -0
  624. package/dist/src/tui/tui-run-state.js.map +1 -0
  625. package/dist/src/tui/tui-runtime-hints.d.ts +4 -0
  626. package/dist/src/tui/tui-runtime-hints.js +18 -0
  627. package/dist/src/tui/tui-runtime-hints.js.map +1 -0
  628. package/dist/src/tui/tui-scoped-models.d.ts +1 -1
  629. package/dist/src/tui/tui-scoped-models.js +2 -2
  630. package/dist/src/tui/tui-scoped-models.js.map +1 -1
  631. package/dist/src/tui/tui-session-actions.d.ts +5 -3
  632. package/dist/src/tui/tui-session-actions.js +21 -9
  633. package/dist/src/tui/tui-session-actions.js.map +1 -1
  634. package/dist/src/tui/tui-session-format.d.ts +4 -1
  635. package/dist/src/tui/tui-session-format.js +17 -3
  636. package/dist/src/tui/tui-session-format.js.map +1 -1
  637. package/dist/src/tui/tui-session-snapshot.d.ts +82 -0
  638. package/dist/src/tui/tui-session-snapshot.js +184 -0
  639. package/dist/src/tui/tui-session-snapshot.js.map +1 -0
  640. package/dist/src/tui/tui-session-stats.d.ts +3 -0
  641. package/dist/src/tui/tui-session-stats.js +59 -0
  642. package/dist/src/tui/tui-session-stats.js.map +1 -0
  643. package/dist/src/tui/tui-settings.d.ts +21 -0
  644. package/dist/src/tui/tui-settings.js +28 -1
  645. package/dist/src/tui/tui-settings.js.map +1 -1
  646. package/dist/src/tui/tui-skills-autocomplete.js +1 -1
  647. package/dist/src/tui/tui-skills-autocomplete.js.map +1 -1
  648. package/dist/src/tui/tui-startup-resources.d.ts +3 -0
  649. package/dist/src/tui/tui-startup-resources.js +39 -0
  650. package/dist/src/tui/tui-startup-resources.js.map +1 -0
  651. package/dist/src/tui/tui-startup-text.d.ts +10 -0
  652. package/dist/src/tui/tui-startup-text.js +58 -0
  653. package/dist/src/tui/tui-startup-text.js.map +1 -0
  654. package/dist/src/tui/tui-stdio-filter.d.ts +1 -0
  655. package/dist/src/tui/tui-stdio-filter.js +11 -7
  656. package/dist/src/tui/tui-stdio-filter.js.map +1 -1
  657. package/dist/src/tui/tui-submit.d.ts +2 -0
  658. package/dist/src/tui/tui-submit.js +2 -1
  659. package/dist/src/tui/tui-submit.js.map +1 -1
  660. package/dist/src/tui/tui-tool-diff.js +61 -7
  661. package/dist/src/tui/tui-tool-diff.js.map +1 -1
  662. package/dist/src/tui/tui-tool-result.d.ts +17 -0
  663. package/dist/src/tui/tui-tool-result.js +74 -0
  664. package/dist/src/tui/tui-tool-result.js.map +1 -0
  665. package/dist/src/tui/tui-transcript-tree-picker.d.ts +57 -0
  666. package/dist/src/tui/tui-transcript-tree-picker.js +604 -0
  667. package/dist/src/tui/tui-transcript-tree-picker.js.map +1 -0
  668. package/dist/src/tui/tui-transcript-tree.d.ts +7 -0
  669. package/dist/src/tui/tui-transcript-tree.js +316 -0
  670. package/dist/src/tui/tui-transcript-tree.js.map +1 -0
  671. package/dist/src/tui/tui-types.d.ts +25 -34
  672. package/dist/src/tui/tui-types.js +12 -0
  673. package/dist/src/tui/tui-types.js.map +1 -1
  674. package/dist/src/tui/tui.js +1288 -112
  675. package/dist/src/tui/tui.js.map +1 -1
  676. package/dist/src/tui/xopc-tui-keybindings.d.ts +127 -2
  677. package/dist/src/tui/xopc-tui-keybindings.js +127 -2
  678. package/dist/src/tui/xopc-tui-keybindings.js.map +1 -1
  679. package/dist/src/workflows/domain/definition-utils.d.ts +2 -1
  680. package/dist/src/workflows/domain/definition-utils.js +18 -8
  681. package/dist/src/workflows/domain/definition-utils.js.map +1 -1
  682. package/dist/src/workflows/domain/definition.d.ts +25 -0
  683. package/dist/src/workflows/domain/event.d.ts +1 -0
  684. package/dist/src/workflows/domain/result.d.ts +15 -0
  685. package/dist/src/workflows/domain/run.d.ts +2 -0
  686. package/dist/src/workflows/domain/run.js.map +1 -1
  687. package/dist/src/workflows/engine/projector.js +4 -0
  688. package/dist/src/workflows/engine/projector.js.map +1 -1
  689. package/dist/src/workflows/engine/workflow-engine.d.ts +37 -1
  690. package/dist/src/workflows/engine/workflow-engine.js +75 -11
  691. package/dist/src/workflows/engine/workflow-engine.js.map +1 -1
  692. package/dist/src/workflows/index.d.ts +1 -0
  693. package/dist/src/workflows/index.js +4 -1
  694. package/dist/src/workflows/registry/catalog-workflow-definition-registry.d.ts +9 -0
  695. package/dist/src/workflows/registry/catalog-workflow-definition-registry.js +40 -0
  696. package/dist/src/workflows/registry/catalog-workflow-definition-registry.js.map +1 -0
  697. package/dist/src/workflows/registry/index.d.ts +2 -0
  698. package/dist/src/workflows/registry/index.js +2 -0
  699. package/dist/src/workflows/registry/workflow-definition-registry.d.ts +15 -0
  700. package/dist/src/workflows/registry/workflow-definition-registry.js +1 -0
  701. package/dist/src/workflows/runtime/index.d.ts +2 -0
  702. package/dist/src/workflows/runtime/index.js +2 -1
  703. package/dist/src/workflows/runtime/script-workflow-runtime.d.ts +5 -0
  704. package/dist/src/workflows/runtime/script-workflow-runtime.js +15 -0
  705. package/dist/src/workflows/runtime/script-workflow-runtime.js.map +1 -0
  706. package/dist/src/workflows/runtime/workflow-runtime-port.d.ts +16 -0
  707. package/dist/src/workflows/runtime/workflow-runtime-port.js +1 -0
  708. package/dist/src/workflows/service/run-view-to-snapshot.js +3 -0
  709. package/dist/src/workflows/service/run-view-to-snapshot.js.map +1 -1
  710. package/dist/src/workflows/service/workflow-run-service.d.ts +3 -0
  711. package/dist/src/workflows/service/workflow-run-service.js +10 -15
  712. package/dist/src/workflows/service/workflow-run-service.js.map +1 -1
  713. package/dist/src/workflows/service/workflow-session-bridge.d.ts +1 -1
  714. package/dist/src/workflows/service/workflow-session-bridge.js +4 -1
  715. package/dist/src/workflows/service/workflow-session-bridge.js.map +1 -1
  716. package/package.json +21 -15
  717. package/skills/creative/frontend-design/SKILL.md +1 -1
  718. package/skills/creative/theme-factory/SKILL.md +1 -1
  719. package/skills/documents/xlsx/SKILL.md +1 -1
  720. package/skills/engineering/diagnose/SKILL.md +2 -2
  721. package/skills/engineering/tdd/SKILL.md +1 -1
  722. package/skills/tools/github/SKILL.md +6 -1
  723. package/skills/tools/webapp-testing/SKILL.md +4 -1
  724. package/dist/extensions/telegram/src/adapters/config-surface.d.ts +0 -2
  725. package/dist/extensions/telegram/src/adapters/config-surface.js +0 -26
  726. package/dist/extensions/telegram/src/adapters/config-surface.js.map +0 -1
  727. package/dist/extensions/weixin/src/__tests__/workflow-progress.test.js +0 -158
  728. package/dist/extensions/weixin/src/__tests__/workflow-progress.test.js.map +0 -1
  729. package/dist/gateway/static/root/assets/agents-DQ0mQxIA.js +0 -222
  730. package/dist/gateway/static/root/assets/channels-settings-BEtP53V6.js +0 -1
  731. package/dist/gateway/static/root/assets/channels-status-swr-CxTtS1hI.js +0 -8
  732. package/dist/gateway/static/root/assets/cron-api-CznlPIZT.js +0 -1
  733. package/dist/gateway/static/root/assets/cron-page-Dx6dE3eD.js +0 -1
  734. package/dist/gateway/static/root/assets/extension-settings-page-DuDCSb3J.js +0 -1
  735. package/dist/gateway/static/root/assets/field-primitives-BUwUiDf5.js +0 -1
  736. package/dist/gateway/static/root/assets/heartbeat-config-api-BjFW1cl-.js +0 -1
  737. package/dist/gateway/static/root/assets/index-DKgHC1Ta.js +0 -4840
  738. package/dist/gateway/static/root/assets/index-DjNDHzwG.css +0 -1
  739. package/dist/gateway/static/root/assets/notes-page-D40ZpS0Y.js +0 -1
  740. package/dist/gateway/static/root/assets/sessions-page-BvtdbmW8.js +0 -1
  741. package/dist/gateway/static/root/assets/settings-advanced-gate-BQamRjkV.js +0 -2
  742. package/dist/gateway/static/root/assets/settings-page-D972_jaS.js +0 -3
  743. package/dist/gateway/static/root/assets/share-preview-page-CKCTMo0_.js +0 -2
  744. package/dist/gateway/static/root/assets/skills-page-QwFCB4yV.js +0 -2
  745. package/dist/gateway/static/root/assets/url-q28QhI7l.js +0 -3
  746. package/dist/gateway/static/root/assets/utils-DCm11_KW.js +0 -1
  747. package/dist/gateway/static/root/assets/voice-api-key-field-CywiB7Dw.js +0 -1
  748. package/dist/gateway/static/root/assets/workflows-page-Be7l_SWw.js +0 -27
  749. package/dist/src/agent/embedded/map-stream-events.d.ts +0 -9
  750. package/dist/src/agent/embedded/map-stream-events.js +0 -63
  751. package/dist/src/agent/embedded/map-stream-events.js.map +0 -1
  752. package/dist/src/auth/oauth/vendor-pi-google/google-antigravity.js.map +0 -1
  753. package/dist/src/auth/oauth/vendor-pi-google/google-gemini-cli.js.map +0 -1
  754. package/dist/src/auth/oauth/vendor-pi-google/oauth-page.js.map +0 -1
  755. package/dist/src/auth/oauth/vendor-pi-google/pkce.js.map +0 -1
  756. package/dist/src/channels/dock.js.map +0 -1
  757. package/dist/src/channels/plugins/bundled.d.ts +0 -11
  758. package/dist/src/channels/plugins/bundled.js +0 -10
  759. package/dist/src/channels/plugins/bundled.js.map +0 -1
  760. package/dist/src/channels/registry.d.ts +0 -25
  761. package/dist/src/channels/registry.js +0 -82
  762. package/dist/src/channels/registry.js.map +0 -1
  763. package/dist/src/config/localized-text.d.ts +0 -6
  764. package/dist/src/config/localized-text.js +0 -42
  765. package/dist/src/config/localized-text.js.map +0 -1
  766. package/dist/src/generated/bundled-channel-plugins.d.ts +0 -10
  767. package/dist/src/generated/bundled-channel-plugins.js +0 -16
  768. package/dist/src/generated/bundled-channel-plugins.js.map +0 -1
  769. package/dist/src/tui/stream-assembler.d.ts +0 -22
  770. package/dist/src/tui/stream-assembler.js +0 -63
  771. package/dist/src/tui/stream-assembler.js.map +0 -1
  772. package/skills/browser/SKILL-zh.md +0 -188
  773. package/skills/business/company-values/SKILL-zh.md +0 -80
  774. package/skills/business/company-values/SKILL.md +0 -80
  775. package/skills/business/find-community/SKILL-zh.md +0 -50
  776. package/skills/business/find-community/SKILL.md +0 -50
  777. package/skills/business/first-customers/SKILL-zh.md +0 -76
  778. package/skills/business/first-customers/SKILL.md +0 -76
  779. package/skills/business/grow-sustainably/SKILL-zh.md +0 -92
  780. package/skills/business/grow-sustainably/SKILL.md +0 -92
  781. package/skills/business/marketing-plan/SKILL-zh.md +0 -100
  782. package/skills/business/marketing-plan/SKILL.md +0 -100
  783. package/skills/business/minimalist-review/SKILL-zh.md +0 -82
  784. package/skills/business/minimalist-review/SKILL.md +0 -82
  785. package/skills/business/mvp/SKILL-zh.md +0 -81
  786. package/skills/business/mvp/SKILL.md +0 -81
  787. package/skills/business/pricing/SKILL-zh.md +0 -64
  788. package/skills/business/pricing/SKILL.md +0 -64
  789. package/skills/business/processize/SKILL-zh.md +0 -91
  790. package/skills/business/processize/SKILL.md +0 -91
  791. package/skills/business/validate-idea/SKILL-zh.md +0 -68
  792. package/skills/business/validate-idea/SKILL.md +0 -68
  793. package/skills/creative/algorithmic-art/LICENSE.txt +0 -202
  794. package/skills/creative/algorithmic-art/SKILL-zh.md +0 -405
  795. package/skills/creative/algorithmic-art/SKILL.md +0 -405
  796. package/skills/creative/algorithmic-art/templates/generator_template.js +0 -223
  797. package/skills/creative/algorithmic-art/templates/viewer.html +0 -599
  798. package/skills/creative/frontend-design/SKILL-zh.md +0 -42
  799. package/skills/creative/theme-factory/SKILL-zh.md +0 -59
  800. package/skills/creative/web-artifacts-builder/LICENSE.txt +0 -202
  801. package/skills/creative/web-artifacts-builder/SKILL-zh.md +0 -74
  802. package/skills/creative/web-artifacts-builder/SKILL.md +0 -74
  803. package/skills/creative/web-artifacts-builder/scripts/bundle-artifact.sh +0 -54
  804. package/skills/creative/web-artifacts-builder/scripts/init-artifact.sh +0 -322
  805. package/skills/creative/web-artifacts-builder/scripts/shadcn-components.tar.gz +0 -0
  806. package/skills/documents/doc-coauthoring/SKILL-zh.md +0 -375
  807. package/skills/documents/doc-coauthoring/SKILL.md +0 -375
  808. package/skills/documents/docx/LICENSE.txt +0 -30
  809. package/skills/documents/docx/SKILL-zh.md +0 -590
  810. package/skills/documents/docx/SKILL.md +0 -590
  811. package/skills/documents/docx/scripts/__init__.py +0 -1
  812. package/skills/documents/docx/scripts/accept_changes.py +0 -135
  813. package/skills/documents/docx/scripts/comment.py +0 -318
  814. package/skills/documents/docx/scripts/office/helpers/__init__.py +0 -0
  815. package/skills/documents/docx/scripts/office/helpers/merge_runs.py +0 -199
  816. package/skills/documents/docx/scripts/office/helpers/simplify_redlines.py +0 -197
  817. package/skills/documents/docx/scripts/office/pack.py +0 -159
  818. package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +0 -1499
  819. package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +0 -146
  820. package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +0 -1085
  821. package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +0 -11
  822. package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-main.xsd +0 -3081
  823. package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +0 -23
  824. package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +0 -185
  825. package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +0 -287
  826. package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/pml.xsd +0 -1676
  827. package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +0 -28
  828. package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +0 -144
  829. package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +0 -174
  830. package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +0 -25
  831. package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +0 -18
  832. package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +0 -59
  833. package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +0 -56
  834. package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +0 -195
  835. package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-math.xsd +0 -582
  836. package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +0 -25
  837. package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/sml.xsd +0 -4439
  838. package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-main.xsd +0 -570
  839. package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +0 -509
  840. package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +0 -12
  841. package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +0 -108
  842. package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +0 -96
  843. package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/wml.xsd +0 -3646
  844. package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/xml.xsd +0 -116
  845. package/skills/documents/docx/scripts/office/schemas/ecma/fouth-edition/opc-contentTypes.xsd +0 -42
  846. package/skills/documents/docx/scripts/office/schemas/ecma/fouth-edition/opc-coreProperties.xsd +0 -50
  847. package/skills/documents/docx/scripts/office/schemas/ecma/fouth-edition/opc-digSig.xsd +0 -49
  848. package/skills/documents/docx/scripts/office/schemas/ecma/fouth-edition/opc-relationships.xsd +0 -33
  849. package/skills/documents/docx/scripts/office/schemas/mce/mc.xsd +0 -75
  850. package/skills/documents/docx/scripts/office/schemas/microsoft/wml-2010.xsd +0 -560
  851. package/skills/documents/docx/scripts/office/schemas/microsoft/wml-2012.xsd +0 -67
  852. package/skills/documents/docx/scripts/office/schemas/microsoft/wml-2018.xsd +0 -14
  853. package/skills/documents/docx/scripts/office/schemas/microsoft/wml-cex-2018.xsd +0 -20
  854. package/skills/documents/docx/scripts/office/schemas/microsoft/wml-cid-2016.xsd +0 -13
  855. package/skills/documents/docx/scripts/office/schemas/microsoft/wml-sdtdatahash-2020.xsd +0 -4
  856. package/skills/documents/docx/scripts/office/schemas/microsoft/wml-symex-2015.xsd +0 -8
  857. package/skills/documents/docx/scripts/office/soffice.py +0 -183
  858. package/skills/documents/docx/scripts/office/unpack.py +0 -132
  859. package/skills/documents/docx/scripts/office/validate.py +0 -111
  860. package/skills/documents/docx/scripts/office/validators/__init__.py +0 -15
  861. package/skills/documents/docx/scripts/office/validators/base.py +0 -847
  862. package/skills/documents/docx/scripts/office/validators/docx.py +0 -446
  863. package/skills/documents/docx/scripts/office/validators/pptx.py +0 -275
  864. package/skills/documents/docx/scripts/office/validators/redlining.py +0 -247
  865. package/skills/documents/docx/scripts/templates/comments.xml +0 -3
  866. package/skills/documents/docx/scripts/templates/commentsExtended.xml +0 -3
  867. package/skills/documents/docx/scripts/templates/commentsExtensible.xml +0 -3
  868. package/skills/documents/docx/scripts/templates/commentsIds.xml +0 -3
  869. package/skills/documents/docx/scripts/templates/people.xml +0 -3
  870. package/skills/documents/pdf/LICENSE.txt +0 -30
  871. package/skills/documents/pdf/SKILL-zh.md +0 -314
  872. package/skills/documents/pdf/SKILL.md +0 -314
  873. package/skills/documents/pdf/forms.md +0 -294
  874. package/skills/documents/pdf/reference.md +0 -612
  875. package/skills/documents/pdf/scripts/check_bounding_boxes.py +0 -65
  876. package/skills/documents/pdf/scripts/check_fillable_fields.py +0 -11
  877. package/skills/documents/pdf/scripts/convert_pdf_to_images.py +0 -33
  878. package/skills/documents/pdf/scripts/create_validation_image.py +0 -37
  879. package/skills/documents/pdf/scripts/extract_form_field_info.py +0 -122
  880. package/skills/documents/pdf/scripts/extract_form_structure.py +0 -115
  881. package/skills/documents/pdf/scripts/fill_fillable_fields.py +0 -98
  882. package/skills/documents/pdf/scripts/fill_pdf_form_with_annotations.py +0 -107
  883. package/skills/documents/pptx/LICENSE.txt +0 -30
  884. package/skills/documents/pptx/SKILL-zh.md +0 -232
  885. package/skills/documents/pptx/SKILL.md +0 -232
  886. package/skills/documents/pptx/editing.md +0 -205
  887. package/skills/documents/pptx/pptxgenjs.md +0 -420
  888. package/skills/documents/pptx/scripts/__init__.py +0 -0
  889. package/skills/documents/pptx/scripts/add_slide.py +0 -195
  890. package/skills/documents/pptx/scripts/clean.py +0 -286
  891. package/skills/documents/pptx/scripts/office/helpers/__init__.py +0 -0
  892. package/skills/documents/pptx/scripts/office/helpers/merge_runs.py +0 -199
  893. package/skills/documents/pptx/scripts/office/helpers/simplify_redlines.py +0 -197
  894. package/skills/documents/pptx/scripts/office/pack.py +0 -159
  895. package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +0 -1499
  896. package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +0 -146
  897. package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +0 -1085
  898. package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +0 -11
  899. package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-main.xsd +0 -3081
  900. package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +0 -23
  901. package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +0 -185
  902. package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +0 -287
  903. package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/pml.xsd +0 -1676
  904. package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +0 -28
  905. package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +0 -144
  906. package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +0 -174
  907. package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +0 -25
  908. package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +0 -18
  909. package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +0 -59
  910. package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +0 -56
  911. package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +0 -195
  912. package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-math.xsd +0 -582
  913. package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +0 -25
  914. package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/sml.xsd +0 -4439
  915. package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-main.xsd +0 -570
  916. package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +0 -509
  917. package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +0 -12
  918. package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +0 -108
  919. package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +0 -96
  920. package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/wml.xsd +0 -3646
  921. package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/xml.xsd +0 -116
  922. package/skills/documents/pptx/scripts/office/schemas/ecma/fouth-edition/opc-contentTypes.xsd +0 -42
  923. package/skills/documents/pptx/scripts/office/schemas/ecma/fouth-edition/opc-coreProperties.xsd +0 -50
  924. package/skills/documents/pptx/scripts/office/schemas/ecma/fouth-edition/opc-digSig.xsd +0 -49
  925. package/skills/documents/pptx/scripts/office/schemas/ecma/fouth-edition/opc-relationships.xsd +0 -33
  926. package/skills/documents/pptx/scripts/office/schemas/mce/mc.xsd +0 -75
  927. package/skills/documents/pptx/scripts/office/schemas/microsoft/wml-2010.xsd +0 -560
  928. package/skills/documents/pptx/scripts/office/schemas/microsoft/wml-2012.xsd +0 -67
  929. package/skills/documents/pptx/scripts/office/schemas/microsoft/wml-2018.xsd +0 -14
  930. package/skills/documents/pptx/scripts/office/schemas/microsoft/wml-cex-2018.xsd +0 -20
  931. package/skills/documents/pptx/scripts/office/schemas/microsoft/wml-cid-2016.xsd +0 -13
  932. package/skills/documents/pptx/scripts/office/schemas/microsoft/wml-sdtdatahash-2020.xsd +0 -4
  933. package/skills/documents/pptx/scripts/office/schemas/microsoft/wml-symex-2015.xsd +0 -8
  934. package/skills/documents/pptx/scripts/office/soffice.py +0 -183
  935. package/skills/documents/pptx/scripts/office/unpack.py +0 -132
  936. package/skills/documents/pptx/scripts/office/validate.py +0 -111
  937. package/skills/documents/pptx/scripts/office/validators/__init__.py +0 -15
  938. package/skills/documents/pptx/scripts/office/validators/base.py +0 -847
  939. package/skills/documents/pptx/scripts/office/validators/docx.py +0 -446
  940. package/skills/documents/pptx/scripts/office/validators/pptx.py +0 -275
  941. package/skills/documents/pptx/scripts/office/validators/redlining.py +0 -247
  942. package/skills/documents/pptx/scripts/thumbnail.py +0 -289
  943. package/skills/documents/xlsx/SKILL-zh.md +0 -292
  944. package/skills/engineering/diagnose/SKILL-zh.md +0 -117
  945. package/skills/engineering/grill-with-docs/ADR-FORMAT.md +0 -47
  946. package/skills/engineering/grill-with-docs/CONTEXT-FORMAT.md +0 -77
  947. package/skills/engineering/grill-with-docs/SKILL-zh.md +0 -88
  948. package/skills/engineering/grill-with-docs/SKILL.md +0 -88
  949. package/skills/engineering/improve-codebase-architecture/DEEPENING.md +0 -37
  950. package/skills/engineering/improve-codebase-architecture/INTERFACE-DESIGN.md +0 -44
  951. package/skills/engineering/improve-codebase-architecture/LANGUAGE.md +0 -53
  952. package/skills/engineering/improve-codebase-architecture/SKILL-zh.md +0 -71
  953. package/skills/engineering/improve-codebase-architecture/SKILL.md +0 -71
  954. package/skills/engineering/tdd/SKILL-zh.md +0 -109
  955. package/skills/engineering/to-issues/SKILL-zh.md +0 -81
  956. package/skills/engineering/to-issues/SKILL.md +0 -81
  957. package/skills/engineering/to-prd/SKILL-zh.md +0 -76
  958. package/skills/engineering/to-prd/SKILL.md +0 -74
  959. package/skills/engineering/zoom-out/SKILL-zh.md +0 -7
  960. package/skills/engineering/zoom-out/SKILL.md +0 -7
  961. package/skills/tools/find-skills/SKILL-zh.md +0 -440
  962. package/skills/tools/github/SKILL-zh.md +0 -48
  963. package/skills/tools/internal-comms/LICENSE.txt +0 -202
  964. package/skills/tools/internal-comms/SKILL-zh.md +0 -32
  965. package/skills/tools/internal-comms/SKILL.md +0 -32
  966. package/skills/tools/internal-comms/examples/3p-updates.md +0 -47
  967. package/skills/tools/internal-comms/examples/company-newsletter.md +0 -65
  968. package/skills/tools/internal-comms/examples/faq-answers.md +0 -30
  969. package/skills/tools/internal-comms/examples/general-comms.md +0 -16
  970. package/skills/tools/skill-creator/LICENSE.txt +0 -202
  971. package/skills/tools/skill-creator/SKILL-zh.md +0 -483
  972. package/skills/tools/skill-creator/SKILL.md +0 -485
  973. package/skills/tools/skill-creator/agents/analyzer.md +0 -274
  974. package/skills/tools/skill-creator/agents/comparator.md +0 -202
  975. package/skills/tools/skill-creator/agents/grader.md +0 -223
  976. package/skills/tools/skill-creator/assets/eval_review.html +0 -146
  977. package/skills/tools/skill-creator/eval-viewer/generate_review.py +0 -471
  978. package/skills/tools/skill-creator/eval-viewer/viewer.html +0 -1325
  979. package/skills/tools/skill-creator/references/schemas.md +0 -430
  980. package/skills/tools/skill-creator/scripts/__init__.py +0 -0
  981. package/skills/tools/skill-creator/scripts/aggregate_benchmark.py +0 -401
  982. package/skills/tools/skill-creator/scripts/generate_report.py +0 -326
  983. package/skills/tools/skill-creator/scripts/improve_description.py +0 -247
  984. package/skills/tools/skill-creator/scripts/package_skill.py +0 -136
  985. package/skills/tools/skill-creator/scripts/quick_validate.py +0 -103
  986. package/skills/tools/skill-creator/scripts/run_eval.py +0 -310
  987. package/skills/tools/skill-creator/scripts/run_loop.py +0 -328
  988. package/skills/tools/skill-creator/scripts/utils.py +0 -47
  989. package/skills/tools/summarize/SKILL-zh.md +0 -47
  990. package/skills/tools/weather/SKILL-zh.md +0 -46
  991. package/skills/tools/weather/SKILL.md +0 -46
  992. package/skills/tools/webapp-testing/SKILL-zh.md +0 -96
  993. /package/dist/src/auth/oauth/{vendor-pi-google → google-oauth}/google-antigravity.d.ts +0 -0
  994. /package/dist/src/auth/oauth/{vendor-pi-google → google-oauth}/google-gemini-cli.d.ts +0 -0
  995. /package/dist/src/auth/oauth/{vendor-pi-google → google-oauth}/oauth-page.d.ts +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"attachment-pipeline.js","names":[],"sources":["../../../../src/agent/inbound/attachment-pipeline.ts"],"sourcesContent":["import type { AgentMessage } from '@earendil-works/pi-agent-core';\nimport type { ImageContent } from '@earendil-works/pi-ai';\n\nimport type { Config } from '../../config/schema.js';\nimport {\n isImageInboundAttachment,\n type MediaRef,\n} from '../../channels/attachments/inbound-persist.js';\nimport { readMediaReferenceBase64 } from '../../media/media-reference.js';\nimport { expandAtFileMentionsInPlainText } from '../context/expand-at-file-mentions.js';\nimport { readAgentMessageContent } from '../memory/agent-message-access.js';\nimport { resolveInboundImageContentParts } from '../image/inbound-image-handling.js';\nimport { resolveImageHandlingStrategy } from '../image/vision-detection.js';\nimport type { AgentInstanceGateway } from '../agent-instance-gateway.js';\n\nexport type TranscriptUserMessage = AgentMessage & {\n media?: MediaRef[];\n MediaPath?: string;\n MediaPaths?: string[];\n MediaTypes?: string[];\n};\n\nexport type LlmUserTurn = {\n text: string;\n images: ImageContent[];\n};\n\nconst VISION_INLINE_MAX_BYTES = 2 * 1024 * 1024;\n\nfunction textBlocksFromContent(content: unknown): string[] {\n if (typeof content === 'string') {\n return content.trim() ? [content] : [];\n }\n if (!Array.isArray(content)) {\n return [];\n }\n const out: string[] = [];\n for (const block of content) {\n if (block && typeof block === 'object' && (block as { type?: string }).type === 'text') {\n const t = (block as { text?: string }).text;\n if (typeof t === 'string' && t.trim()) {\n out.push(t);\n }\n }\n }\n return out;\n}\n\nfunction joinTextBlocks(parts: string[]): string {\n return parts.join('\\n').trim();\n}\n\nfunction buildMediaPathFields(media: MediaRef[]): Pick<TranscriptUserMessage, 'MediaPath' | 'MediaPaths' | 'MediaTypes'> {\n if (!media.length) return {};\n return {\n MediaPath: media[0]!.path,\n MediaPaths: media.map((m) => m.path),\n MediaTypes: media.map((m) => m.mimeType),\n };\n}\n\nfunction assertUserContentHasNoInlineMedia(content: unknown): void {\n if (!Array.isArray(content)) {\n return;\n }\n for (const block of content) {\n if (!block || typeof block !== 'object') {\n continue;\n }\n const type = (block as { type?: string }).type;\n if (type === 'image') {\n throw new Error('User transcript content must not contain image blocks');\n }\n }\n}\n\nexport function assertTranscriptUserMessage(message: AgentMessage): void {\n if ((message as { role?: string }).role !== 'user') {\n return;\n }\n assertUserContentHasNoInlineMedia((message as { content?: unknown }).content);\n const media = (message as TranscriptUserMessage).media;\n if (!media?.length) {\n return;\n }\n for (const ref of media) {\n if (!ref.uri?.trim()) {\n throw new Error('User transcript media ref missing uri');\n }\n if ('data' in ref && typeof (ref as { data?: unknown }).data === 'string') {\n throw new Error('User transcript media ref must not include data');\n }\n }\n}\n\nasync function readImageBase64FromRef(ref: MediaRef): Promise<{ data: string; mimeType: string }> {\n const loaded = await readMediaReferenceBase64(ref.uri, VISION_INLINE_MAX_BYTES);\n return {\n data: loaded.data,\n mimeType: ref.mimeType?.startsWith('image/') ? ref.mimeType : loaded.mimeType,\n };\n}\n\nfunction appendMediaAttachedLines(textParts: string[], media: MediaRef[]): void {\n for (const ref of media) {\n if (!isImageInboundAttachment(ref)) {\n textParts.push(\n [\n `[media attached: ${ref.name} (${ref.mimeType}, ${ref.size} bytes)]`,\n `xopc-media-uri:${ref.uri}`,\n `xopc-media-path:${ref.path}`,\n 'Use the read_media tool with the xopc-media-uri value when you need to inspect this attachment.',\n ].join('\\n'),\n );\n }\n }\n}\n\nasync function expandUserText(\n text: string,\n sessionKey: string,\n agentManager: AgentInstanceGateway,\n): Promise<string> {\n if (!text.trim()) {\n return '';\n }\n let out = text;\n if (/@file:/.test(out)) {\n const wsKey = sessionKey || 'agent:main:main';\n const root = agentManager.getResolvedWorkspaceForSession(wsKey);\n out = await expandAtFileMentionsInPlainText(out, root);\n }\n return out.trim();\n}\n\n/**\n * Build the transcript row for a user turn (text + media metadata only).\n */\nexport async function buildTranscriptUserMessage(opts: {\n text: string;\n prepared: MediaRef[] | undefined;\n sessionKey: string;\n modelRef: string;\n config: Config | undefined;\n agentManager: AgentInstanceGateway;\n}): Promise<TranscriptUserMessage> {\n const expandedText = await expandUserText(opts.text, opts.sessionKey, opts.agentManager);\n const prepared = opts.prepared ?? [];\n const imageRefs = prepared.filter(isImageInboundAttachment);\n\n const textParts: string[] = [];\n if (expandedText) {\n textParts.push(expandedText);\n }\n\n const strategy = resolveImageHandlingStrategy(opts.modelRef);\n\n if (strategy !== 'native') {\n appendMediaAttachedLines(textParts, prepared.filter((m) => !isImageInboundAttachment(m)));\n }\n\n if (imageRefs.length > 0 && strategy !== 'native') {\n const images = await Promise.all(imageRefs.map((ref) => readImageBase64FromRef(ref)));\n const parts = await resolveInboundImageContentParts({\n modelRef: opts.modelRef,\n cfg: opts.config,\n userTextForContext: expandedText,\n images,\n });\n for (const part of parts) {\n if (part.type === 'text' && part.text.trim()) {\n textParts.push(part.text.trim());\n }\n }\n }\n\n if (textParts.length === 0 && prepared.length > 0) {\n textParts.push('Please analyze the attachment(s) I sent.');\n }\n\n const content = joinTextBlocks(textParts);\n const message: TranscriptUserMessage = {\n role: 'user',\n content,\n timestamp: Date.now(),\n ...(prepared.length > 0 ? { media: prepared, ...buildMediaPathFields(prepared) } : {}),\n };\n assertTranscriptUserMessage(message);\n return message;\n}\n\n/** Hydrate images from media store for the current LLM prompt. */\nexport async function hydrateUserTurnForLlm(opts: {\n message: TranscriptUserMessage;\n modelRef: string;\n}): Promise<LlmUserTurn> {\n const text = joinTextBlocks(textBlocksFromContent(readAgentMessageContent(opts.message)));\n const media = opts.message.media ?? [];\n const images: ImageContent[] = [];\n\n if (resolveImageHandlingStrategy(opts.modelRef) === 'native') {\n for (const ref of media.filter(isImageInboundAttachment)) {\n const loaded = await readImageBase64FromRef(ref);\n images.push({ type: 'image', data: loaded.data, mimeType: loaded.mimeType });\n }\n }\n\n return { text, images };\n}\n\nconst pendingTranscriptBySession = new Map<string, TranscriptUserMessage>();\n\nfunction messageTextForPendingCompare(message: AgentMessage): string {\n return joinTextBlocks(textBlocksFromContent(readAgentMessageContent(message)));\n}\n\nfunction pendingMatchesMessage(pending: TranscriptUserMessage, message: AgentMessage): boolean {\n const pendingText = messageTextForPendingCompare(pending);\n const actualText = messageTextForPendingCompare(message);\n if (!pendingText) {\n return true;\n }\n if (!actualText) {\n return false;\n }\n return actualText.includes(pendingText) || pendingText.includes(actualText);\n}\n\nexport function setPendingTranscriptUserMessage(sessionKey: string, message: TranscriptUserMessage): void {\n assertTranscriptUserMessage(message);\n pendingTranscriptBySession.set(sessionKey, message);\n}\n\nexport function takePendingTranscriptUserMessage(sessionKey: string): TranscriptUserMessage | undefined {\n const msg = pendingTranscriptBySession.get(sessionKey);\n pendingTranscriptBySession.delete(sessionKey);\n return msg;\n}\n\nexport function clearPendingTranscriptUserMessage(sessionKey: string, message?: TranscriptUserMessage): void {\n const existing = pendingTranscriptBySession.get(sessionKey);\n if (!existing) {\n return;\n }\n if (message && existing !== message) {\n return;\n }\n pendingTranscriptBySession.delete(sessionKey);\n}\n\nexport function pendingTranscriptReferencesMediaUri(sessionKey: string, uri: string): boolean {\n const pending = pendingTranscriptBySession.get(sessionKey);\n return pending?.media?.some((ref) => ref.uri === uri.trim()) === true;\n}\n\nexport function transformUserMessageForPersistence(\n sessionKey: string | undefined,\n message: AgentMessage,\n): AgentMessage {\n if ((message as { role?: string }).role !== 'user') {\n return message;\n }\n if (sessionKey) {\n const pending = pendingTranscriptBySession.get(sessionKey);\n if (pending && pendingMatchesMessage(pending, message)) {\n pendingTranscriptBySession.delete(sessionKey);\n return pending;\n }\n }\n assertTranscriptUserMessage(message);\n return message;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"attachment-pipeline.js","names":[],"sources":["../../../../src/agent/inbound/attachment-pipeline.ts"],"sourcesContent":["import type { AgentMessage } from '@earendil-works/pi-agent-core';\nimport type { ImageContent } from '@earendil-works/pi-ai';\n\nimport type { Config } from '../../config/schema.js';\nimport {\n isImageInboundAttachment,\n type MediaRef,\n} from '../../channels/attachments/inbound-persist.js';\nimport { readMediaReferenceBase64 } from '../../media/media-reference.js';\nimport { expandAtFileMentionsInPlainText } from '../context/expand-at-file-mentions.js';\nimport { readAgentMessageContent } from '../memory/agent-message-access.js';\nimport { resolveInboundImageContentParts } from '../image/inbound-image-handling.js';\nimport { resolveImageHandlingStrategy } from '../image/vision-detection.js';\nimport type { AgentInstanceGateway } from '../agent-instance-gateway.js';\n\nexport type TranscriptUserMessage = AgentMessage & {\n media?: MediaRef[];\n MediaPath?: string;\n MediaPaths?: string[];\n MediaTypes?: string[];\n};\n\nexport type LlmUserTurn = {\n text: string;\n images: ImageContent[];\n};\n\nconst VISION_INLINE_MAX_BYTES = 2 * 1024 * 1024;\n\nfunction textBlocksFromContent(content: unknown): string[] {\n if (typeof content === 'string') {\n return content.trim() ? [content] : [];\n }\n if (!Array.isArray(content)) {\n return [];\n }\n const out: string[] = [];\n for (const block of content) {\n if (block && typeof block === 'object' && (block as { type?: string }).type === 'text') {\n const t = (block as { text?: string }).text;\n if (typeof t === 'string' && t.trim()) {\n out.push(t);\n }\n }\n }\n return out;\n}\n\nfunction joinTextBlocks(parts: string[]): string {\n return parts.join('\\n').trim();\n}\n\nfunction buildMediaPathFields(media: MediaRef[]): Pick<TranscriptUserMessage, 'MediaPath' | 'MediaPaths' | 'MediaTypes'> {\n if (!media.length) return {};\n return {\n MediaPath: media[0]!.path,\n MediaPaths: media.map((m) => m.path),\n MediaTypes: media.map((m) => m.mimeType),\n };\n}\n\nfunction assertUserContentHasNoInlineMedia(content: unknown): void {\n if (!Array.isArray(content)) {\n return;\n }\n for (const block of content) {\n if (!block || typeof block !== 'object') {\n continue;\n }\n const type = (block as { type?: string }).type;\n if (type === 'image') {\n throw new Error('User transcript content must not contain image blocks');\n }\n }\n}\n\nexport function assertTranscriptUserMessage(message: AgentMessage): void {\n if ((message as { role?: string }).role !== 'user') {\n return;\n }\n assertUserContentHasNoInlineMedia((message as { content?: unknown }).content);\n const media = (message as TranscriptUserMessage).media;\n if (!media?.length) {\n return;\n }\n for (const ref of media) {\n if (!ref.uri?.trim()) {\n throw new Error('User transcript media ref missing uri');\n }\n if ('data' in ref && typeof (ref as { data?: unknown }).data === 'string') {\n throw new Error('User transcript media ref must not include data');\n }\n }\n}\n\nasync function readImageBase64FromRef(ref: MediaRef): Promise<{ data: string; mimeType: string }> {\n const loaded = await readMediaReferenceBase64(ref.uri, VISION_INLINE_MAX_BYTES);\n return {\n data: loaded.data,\n mimeType: ref.mimeType || loaded.mimeType,\n };\n}\n\nfunction appendMediaAttachedLines(textParts: string[], media: MediaRef[]): void {\n for (const ref of media) {\n if (!isImageInboundAttachment(ref)) {\n textParts.push(\n [\n `[media attached: ${ref.name} (${ref.mimeType}, ${ref.size} bytes)]`,\n `xopc-media-uri:${ref.uri}`,\n `xopc-media-path:${ref.path}`,\n 'Use the read_media tool with the xopc-media-uri value when you need to inspect this attachment.',\n ].join('\\n'),\n );\n }\n }\n}\n\nasync function expandUserText(\n text: string,\n sessionKey: string,\n agentManager: AgentInstanceGateway,\n): Promise<string> {\n if (!text.trim()) {\n return '';\n }\n let out = text;\n if (/@file:/.test(out)) {\n const wsKey = sessionKey || 'agent:main:main';\n const root = agentManager.getResolvedWorkspaceForSession(wsKey);\n out = await expandAtFileMentionsInPlainText(out, root);\n }\n return out.trim();\n}\n\n/**\n * Build the transcript row for a user turn (text + media metadata only).\n */\nexport async function buildTranscriptUserMessage(opts: {\n text: string;\n prepared: MediaRef[] | undefined;\n sessionKey: string;\n modelRef: string;\n config: Config | undefined;\n agentManager: AgentInstanceGateway;\n}): Promise<TranscriptUserMessage> {\n const expandedText = await expandUserText(opts.text, opts.sessionKey, opts.agentManager);\n const prepared = opts.prepared ?? [];\n const imageRefs = prepared.filter(isImageInboundAttachment);\n\n const textParts: string[] = [];\n if (expandedText) {\n textParts.push(expandedText);\n }\n\n const strategy = resolveImageHandlingStrategy(opts.modelRef);\n\n appendMediaAttachedLines(textParts, prepared.filter((m) => !isImageInboundAttachment(m)));\n\n if (imageRefs.length > 0 && strategy !== 'native') {\n const images = await Promise.all(imageRefs.map((ref) => readImageBase64FromRef(ref)));\n const parts = await resolveInboundImageContentParts({\n modelRef: opts.modelRef,\n cfg: opts.config,\n userTextForContext: expandedText,\n images,\n });\n for (const part of parts) {\n if (part.type === 'text' && part.text.trim()) {\n textParts.push(part.text.trim());\n }\n }\n }\n\n if (textParts.length === 0 && prepared.length > 0) {\n textParts.push('Please analyze the attachment(s) I sent.');\n }\n\n const content = joinTextBlocks(textParts);\n const message: TranscriptUserMessage = {\n role: 'user',\n content,\n timestamp: Date.now(),\n ...(prepared.length > 0 ? { media: prepared, ...buildMediaPathFields(prepared) } : {}),\n };\n assertTranscriptUserMessage(message);\n return message;\n}\n\n/** Hydrate images from media store for the current LLM prompt. */\nexport async function hydrateUserTurnForLlm(opts: {\n message: TranscriptUserMessage;\n modelRef: string;\n}): Promise<LlmUserTurn> {\n const text = joinTextBlocks(textBlocksFromContent(readAgentMessageContent(opts.message)));\n const media = opts.message.media ?? [];\n const images: ImageContent[] = [];\n\n if (resolveImageHandlingStrategy(opts.modelRef) === 'native') {\n for (const ref of media.filter(isImageInboundAttachment)) {\n const loaded = await readImageBase64FromRef(ref);\n images.push({ type: 'image', data: loaded.data, mimeType: loaded.mimeType });\n }\n }\n\n return { text, images };\n}\n\nconst pendingTranscriptBySession = new Map<string, TranscriptUserMessage>();\n\nfunction messageTextForPendingCompare(message: AgentMessage): string {\n return joinTextBlocks(textBlocksFromContent(readAgentMessageContent(message)));\n}\n\nfunction pendingMatchesMessage(pending: TranscriptUserMessage, message: AgentMessage): boolean {\n const pendingText = messageTextForPendingCompare(pending);\n const actualText = messageTextForPendingCompare(message);\n if (!pendingText) {\n return true;\n }\n if (!actualText) {\n return false;\n }\n return actualText.includes(pendingText) || pendingText.includes(actualText);\n}\n\nexport function setPendingTranscriptUserMessage(sessionKey: string, message: TranscriptUserMessage): void {\n assertTranscriptUserMessage(message);\n pendingTranscriptBySession.set(sessionKey, message);\n}\n\nexport function takePendingTranscriptUserMessage(sessionKey: string): TranscriptUserMessage | undefined {\n const msg = pendingTranscriptBySession.get(sessionKey);\n pendingTranscriptBySession.delete(sessionKey);\n return msg;\n}\n\nexport function clearPendingTranscriptUserMessage(sessionKey: string, message?: TranscriptUserMessage): void {\n const existing = pendingTranscriptBySession.get(sessionKey);\n if (!existing) {\n return;\n }\n if (message && existing !== message) {\n return;\n }\n pendingTranscriptBySession.delete(sessionKey);\n}\n\nexport function pendingTranscriptReferencesMediaUri(sessionKey: string, uri: string): boolean {\n const pending = pendingTranscriptBySession.get(sessionKey);\n return pending?.media?.some((ref) => ref.uri === uri.trim()) === true;\n}\n\nexport function transformUserMessageForPersistence(\n sessionKey: string | undefined,\n message: AgentMessage,\n): AgentMessage {\n if ((message as { role?: string }).role !== 'user') {\n return message;\n }\n if (sessionKey) {\n const pending = pendingTranscriptBySession.get(sessionKey);\n if (pending && pendingMatchesMessage(pending, message)) {\n pendingTranscriptBySession.delete(sessionKey);\n return pending;\n }\n }\n assertTranscriptUserMessage(message);\n return message;\n}\n"],"mappings":"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"}
@@ -4,8 +4,8 @@ import { shouldSkipResetOverlapCommand } from "../../session/reset-triggers.js";
4
4
  import { initSessionTurn } from "../../session/init-session-turn.js";
5
5
  import { MessageBusShutdownError } from "../../infra/bus/queue.js";
6
6
  import "../../infra/bus/index.js";
7
- import { inboundMessageLogRequestId } from "../service-inbound-utils.js";
8
7
  import { runEmbeddedTurnForSession } from "../embedded/run-for-session.js";
8
+ import { inboundMessageLogRequestId } from "../service-inbound-utils.js";
9
9
  //#region src/agent/inbound/inbound-loop.ts
10
10
  init_logger();
11
11
  /** Initial back-off when bus consume fails. Doubles each consecutive failure. */
@@ -64,6 +64,7 @@ export declare class TurnDispatcher {
64
64
  /** Streaming direct turn (webchat SSE / CLI streaming). */
65
65
  processDirectStreaming(content: string, sessionKey?: string, attachments?: DirectAttachment[], thinking?: string, options?: {
66
66
  signal?: AbortSignal;
67
+ runId?: string;
67
68
  }): AsyncGenerator<ProcessDirectStreamingSseEvent, void, unknown>;
68
69
  /** Push an out-of-band event into the live webchat stream for a session. */
69
70
  enqueueWebchatSseEvent(sessionKey: string, event: {
@@ -27,7 +27,8 @@ var TurnDispatcher = class {
27
27
  sessionKey,
28
28
  attachments,
29
29
  thinking,
30
- signal: options?.signal
30
+ signal: options?.signal,
31
+ runId: options?.runId
31
32
  });
32
33
  }
33
34
  /** Push an out-of-band event into the live webchat stream for a session. */
@@ -38,10 +39,28 @@ var TurnDispatcher = class {
38
39
  /** Stream assistant text to live webchat session + notify transcript listeners. */
39
40
  notifyWebchatTranscriptAppend(sessionKey, assistantText) {
40
41
  const trimmed = assistantText.trim();
41
- if (trimmed) this.enqueueWebchatSseEvent(sessionKey, {
42
- type: "token",
43
- content: trimmed
44
- });
42
+ if (trimmed) {
43
+ const message = {
44
+ role: "assistant",
45
+ content: [{
46
+ type: "text",
47
+ text: trimmed
48
+ }],
49
+ timestamp: Date.now()
50
+ };
51
+ this.enqueueWebchatSseEvent(sessionKey, {
52
+ type: "message_start",
53
+ message
54
+ });
55
+ this.enqueueWebchatSseEvent(sessionKey, {
56
+ type: "message_update",
57
+ message
58
+ });
59
+ this.enqueueWebchatSseEvent(sessionKey, {
60
+ type: "message_end",
61
+ message
62
+ });
63
+ }
45
64
  this.cfg.onSessionTranscriptUpdated?.(sessionKey);
46
65
  }
47
66
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"turn-dispatcher.js","names":[],"sources":["../../../../src/agent/inbound/turn-dispatcher.ts"],"sourcesContent":["/**\n * TurnDispatcher — single entry point for direct (non-bus) agent turns.\n *\n * Wraps the two existing direct-turn runners (one-shot and streaming) so the\n * parent `AgentService` no longer carries a pair of huge `createXxxDeps()`\n * factories. The public surface — `processDirect`, `processDirectStreaming`,\n * `steerWebchatSession`, `enqueueWebchatSseEvent`,\n * `notifyWebchatTranscriptAppend` — matches what `AgentService` exposed\n * previously, so callers (gateway, CLI) are unchanged.\n *\n * Like `OutboundCoordinator` and `InboundLoop`, this class accepts a wide\n * dependency bag in its constructor (the direct-turn pipeline touches almost\n * every other subsystem). The win is that AgentService becomes the only place\n * that wires those dependencies together; individual responsibilities now live\n * in their own classes and are unit-testable.\n */\n\nimport type { Config } from '../../config/schema.js';\nimport type { ContextualLogger } from '../../utils/logger/types.js';\n\nimport type { AgentManager } from '../agent-manager.js';\nimport type { CommandHandler } from '../messaging/command-handler.js';\nimport type { ModelManager } from '../models/index.js';\nimport type { SessionConfigStore } from '../../session/index.js';\nimport type { SessionStore } from '../../session/store.js';\nimport type {\n SessionContext,\n SessionHydrator,\n SessionStateBag,\n} from '../session/index.js';\nimport { queueEmbeddedSteer } from '../embedded/runs.js';\nimport type {\n InboundAttachmentInput,\n MediaRef,\n} from '../../channels/attachments/inbound-persist.js';\nimport {\n buildDirectUserMessageContent,\n} from '../service/build-direct-message-content.js';\nimport {\n runProcessDirectStreaming,\n type ProcessDirectStreamingDeps,\n type ProcessDirectStreamingSseEvent,\n} from '../service/process-direct-streaming.js';\nimport {\n runProcessDirect,\n type RunProcessDirectDeps,\n} from '../service/process-direct-one-shot.js';\nimport { maybeEmitWebchatTts } from '../service/webchat-tts.js';\n\nexport interface TurnDispatcherConfig {\n log: ContextualLogger;\n agentManager: AgentManager;\n sessionStore: SessionStore;\n modelManager: ModelManager;\n sessionConfigStore: SessionConfigStore;\n sessionState: SessionStateBag;\n commandHandler: CommandHandler;\n getConfig: () => Config | undefined;\n /** Strict accessor — required for direct-turn paths that must have a config. */\n requireConfig: () => Config;\n parseSessionKey: (sessionKey: string) => { channel: string; chatId: string };\n /** Establish per-session context (also creates the Agent + subscribes to events). */\n initSessionContext: (sessionKey: string, channel: string, chatId: string) => SessionContext;\n /** Per-session config hydration: workspace, model, thinking. */\n sessionHydrator: SessionHydrator;\n prepareInboundAttachments: (\n sessionKey: string,\n attachments?: InboundAttachmentInput[],\n ) => Promise<MediaRef[] | undefined>;\n enqueueMaybeAutoTitleAfterPersist: (sessionKey: string) => void;\n enqueueProvisionalSessionTitle?: (sessionKey: string, userText: string) => void;\n endDirectRequestContext: () => void;\n /** Gateway hook fired after assistant text lands on disk (UI refetch). */\n onSessionTranscriptUpdated?: (sessionKey: string) => void;\n resetSession: (sessionKey: string) => Promise<{ sessionId: string; previousSessionId: string } | null>;\n}\n\nexport type DirectAttachment = InboundAttachmentInput;\n\nexport class TurnDispatcher {\n private readonly cfg: TurnDispatcherConfig;\n private readonly log: ContextualLogger;\n\n constructor(cfg: TurnDispatcherConfig) {\n this.cfg = cfg;\n this.log = cfg.log;\n }\n\n /** One-shot direct turn (CLI / embedded TUI). */\n processDirect(\n content: string,\n sessionKey = 'agent:main:main',\n attachments?: DirectAttachment[],\n thinking?: string,\n ): Promise<string> {\n return runProcessDirect(this.buildOneShotDeps(), {\n content,\n sessionKey,\n attachments,\n thinking,\n });\n }\n\n /** Streaming direct turn (webchat SSE / CLI streaming). */\n async *processDirectStreaming(\n content: string,\n sessionKey = 'agent:main:main',\n attachments?: DirectAttachment[],\n thinking?: string,\n options?: { signal?: AbortSignal },\n ): AsyncGenerator<ProcessDirectStreamingSseEvent, void, unknown> {\n yield* runProcessDirectStreaming(this.buildStreamingDeps(), {\n content,\n sessionKey,\n attachments,\n thinking,\n signal: options?.signal,\n });\n }\n\n /** Push an out-of-band event into the live webchat stream for a session. */\n enqueueWebchatSseEvent(\n sessionKey: string,\n event: { type: string; [key: string]: unknown },\n ): void {\n const pub = this.cfg.sessionState.getWebchatPublisher(sessionKey);\n if (pub) {\n pub(event);\n }\n }\n\n /** Stream assistant text to live webchat session + notify transcript listeners. */\n notifyWebchatTranscriptAppend(sessionKey: string, assistantText: string): void {\n const trimmed = assistantText.trim();\n if (trimmed) {\n this.enqueueWebchatSseEvent(sessionKey, { type: 'token', content: trimmed });\n }\n this.cfg.onSessionTranscriptUpdated?.(sessionKey);\n }\n\n /**\n * Queue a steering user message into pi-agent's in-flight run (delivered\n * after current tool work, before the next LLM call). See `Agent.steer`\n * in `@earendil-works/pi-agent-core`.\n */\n async steerWebchatSession(sessionKey: string, text: string): Promise<boolean> {\n const trimmed = text.trim();\n if (!trimmed) return false;\n try {\n return await queueEmbeddedSteer(sessionKey, trimmed);\n } catch (err) {\n this.log.warn({ err, sessionKey }, 'steerWebchatSession failed');\n return false;\n }\n }\n\n private buildStreamingDeps(): ProcessDirectStreamingDeps {\n const c = this.cfg;\n return {\n log: this.log,\n parseSessionKey: c.parseSessionKey,\n initDirectStreamingSession: c.initSessionContext,\n registerWebchatSsePublisher: (sk, publisher) =>\n c.sessionState.registerWebchatPublisher(sk, publisher),\n unregisterWebchatSsePublisher: (sk) => c.sessionState.unregisterWebchatPublisher(sk),\n agentManager: c.agentManager,\n hydrateSessionWorkspaceFromStore: (sk) => c.sessionHydrator.workspace(sk),\n hydrateSessionModelFromStore: (sk) => c.sessionHydrator.model(sk),\n sessionStore: c.sessionStore,\n modelManager: c.modelManager,\n applyResolvedThinkingLevel: (sk, t) => c.sessionHydrator.thinking(sk, t),\n getConfig: c.getConfig,\n sessionConfigStore: c.sessionConfigStore,\n commandHandler: c.commandHandler,\n prepareInboundAttachments: c.prepareInboundAttachments,\n buildTranscriptUserMessage: async (text, prepared, sk) =>\n buildDirectUserMessageContent({\n content: text,\n attachments: prepared,\n sessionKey: sk,\n config: c.requireConfig(),\n agentManager: c.agentManager,\n modelManager: c.modelManager,\n }),\n recordPersistentGoalStreamOutcome: (sk, o) =>\n c.sessionState.recordPersistentGoalStreamOutcome(sk, o),\n enqueueProvisionalSessionTitle: (sk, userText) => {\n c.enqueueProvisionalSessionTitle?.(sk, userText);\n },\n onTurnComplete: (sk, text) => {\n if (text) {\n c.sessionState.setLastAssistantText(sk, text);\n }\n c.enqueueMaybeAutoTitleAfterPersist(sk);\n },\n reloadWebchatTranscript: (sk) => {\n c.onSessionTranscriptUpdated?.(sk);\n },\n maybeEmitWebchatTts: (sk, hadVoice) =>\n maybeEmitWebchatTts(\n {\n config: c.getConfig(),\n sessionStore: c.sessionStore,\n getLastAssistantPlainText: (sessionKey) =>\n c.sessionState.getLastAssistantText(sessionKey) ??\n c.agentManager.getLastAssistantContent(sessionKey) ??\n '',\n log: this.log,\n },\n sk,\n hadVoice,\n ),\n endDirectRequestContext: c.endDirectRequestContext,\n resetSession: c.resetSession,\n };\n }\n\n private buildOneShotDeps(): RunProcessDirectDeps {\n const c = this.cfg;\n const cfg = c.requireConfig();\n return {\n log: this.log,\n config: cfg,\n parseSessionKey: c.parseSessionKey,\n initSessionContext: (sk, channel, chatId) => {\n void c.initSessionContext(sk, channel, chatId);\n },\n hydrateSessionWorkspaceFromStore: (sk) => c.sessionHydrator.workspace(sk),\n hydrateSessionModelFromStore: (sk) => c.sessionHydrator.model(sk),\n agentManager: c.agentManager,\n sessionStore: c.sessionStore,\n modelManager: c.modelManager,\n applyResolvedThinkingLevel: (sk, t) => c.sessionHydrator.thinking(sk, t),\n prepareInboundAttachments: c.prepareInboundAttachments,\n commandHandler: c.commandHandler,\n onTurnComplete: (sk, text) => {\n if (text) {\n c.sessionState.setLastAssistantText(sk, text);\n }\n c.enqueueMaybeAutoTitleAfterPersist(sk);\n },\n endDirectRequestContext: c.endDirectRequestContext,\n resetSession: c.resetSession,\n };\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"turn-dispatcher.js","names":[],"sources":["../../../../src/agent/inbound/turn-dispatcher.ts"],"sourcesContent":["/**\n * TurnDispatcher — single entry point for direct (non-bus) agent turns.\n *\n * Wraps the two existing direct-turn runners (one-shot and streaming) so the\n * parent `AgentService` no longer carries a pair of huge `createXxxDeps()`\n * factories. The public surface — `processDirect`, `processDirectStreaming`,\n * `steerWebchatSession`, `enqueueWebchatSseEvent`,\n * `notifyWebchatTranscriptAppend` — matches what `AgentService` exposed\n * previously, so callers (gateway, CLI) are unchanged.\n *\n * Like `OutboundCoordinator` and `InboundLoop`, this class accepts a wide\n * dependency bag in its constructor (the direct-turn pipeline touches almost\n * every other subsystem). The win is that AgentService becomes the only place\n * that wires those dependencies together; individual responsibilities now live\n * in their own classes and are unit-testable.\n */\n\nimport type { Config } from '../../config/schema.js';\nimport type { ContextualLogger } from '../../utils/logger/types.js';\n\nimport type { AgentManager } from '../agent-manager.js';\nimport type { CommandHandler } from '../messaging/command-handler.js';\nimport type { ModelManager } from '../models/index.js';\nimport type { SessionConfigStore } from '../../session/index.js';\nimport type { SessionStore } from '../../session/store.js';\nimport type {\n SessionContext,\n SessionHydrator,\n SessionStateBag,\n} from '../session/index.js';\nimport { queueEmbeddedSteer } from '../embedded/runs.js';\nimport type {\n InboundAttachmentInput,\n MediaRef,\n} from '../../channels/attachments/inbound-persist.js';\nimport {\n buildDirectUserMessageContent,\n} from '../service/build-direct-message-content.js';\nimport {\n runProcessDirectStreaming,\n type ProcessDirectStreamingDeps,\n type ProcessDirectStreamingSseEvent,\n} from '../service/process-direct-streaming.js';\nimport {\n runProcessDirect,\n type RunProcessDirectDeps,\n} from '../service/process-direct-one-shot.js';\nimport { maybeEmitWebchatTts } from '../service/webchat-tts.js';\n\nexport interface TurnDispatcherConfig {\n log: ContextualLogger;\n agentManager: AgentManager;\n sessionStore: SessionStore;\n modelManager: ModelManager;\n sessionConfigStore: SessionConfigStore;\n sessionState: SessionStateBag;\n commandHandler: CommandHandler;\n getConfig: () => Config | undefined;\n /** Strict accessor — required for direct-turn paths that must have a config. */\n requireConfig: () => Config;\n parseSessionKey: (sessionKey: string) => { channel: string; chatId: string };\n /** Establish per-session context (also creates the Agent + subscribes to events). */\n initSessionContext: (sessionKey: string, channel: string, chatId: string) => SessionContext;\n /** Per-session config hydration: workspace, model, thinking. */\n sessionHydrator: SessionHydrator;\n prepareInboundAttachments: (\n sessionKey: string,\n attachments?: InboundAttachmentInput[],\n ) => Promise<MediaRef[] | undefined>;\n enqueueMaybeAutoTitleAfterPersist: (sessionKey: string) => void;\n enqueueProvisionalSessionTitle?: (sessionKey: string, userText: string) => void;\n endDirectRequestContext: () => void;\n /** Gateway hook fired after assistant text lands on disk (UI refetch). */\n onSessionTranscriptUpdated?: (sessionKey: string) => void;\n resetSession: (sessionKey: string) => Promise<{ sessionId: string; previousSessionId: string } | null>;\n}\n\nexport type DirectAttachment = InboundAttachmentInput;\n\nexport class TurnDispatcher {\n private readonly cfg: TurnDispatcherConfig;\n private readonly log: ContextualLogger;\n\n constructor(cfg: TurnDispatcherConfig) {\n this.cfg = cfg;\n this.log = cfg.log;\n }\n\n /** One-shot direct turn (CLI / embedded TUI). */\n processDirect(\n content: string,\n sessionKey = 'agent:main:main',\n attachments?: DirectAttachment[],\n thinking?: string,\n ): Promise<string> {\n return runProcessDirect(this.buildOneShotDeps(), {\n content,\n sessionKey,\n attachments,\n thinking,\n });\n }\n\n /** Streaming direct turn (webchat SSE / CLI streaming). */\n async *processDirectStreaming(\n content: string,\n sessionKey = 'agent:main:main',\n attachments?: DirectAttachment[],\n thinking?: string,\n options?: { signal?: AbortSignal; runId?: string },\n ): AsyncGenerator<ProcessDirectStreamingSseEvent, void, unknown> {\n yield* runProcessDirectStreaming(this.buildStreamingDeps(), {\n content,\n sessionKey,\n attachments,\n thinking,\n signal: options?.signal,\n runId: options?.runId,\n });\n }\n\n /** Push an out-of-band event into the live webchat stream for a session. */\n enqueueWebchatSseEvent(\n sessionKey: string,\n event: { type: string; [key: string]: unknown },\n ): void {\n const pub = this.cfg.sessionState.getWebchatPublisher(sessionKey);\n if (pub) {\n pub(event);\n }\n }\n\n /** Stream assistant text to live webchat session + notify transcript listeners. */\n notifyWebchatTranscriptAppend(sessionKey: string, assistantText: string): void {\n const trimmed = assistantText.trim();\n if (trimmed) {\n const message = {\n role: 'assistant',\n content: [{ type: 'text', text: trimmed }],\n timestamp: Date.now(),\n };\n this.enqueueWebchatSseEvent(sessionKey, { type: 'message_start', message });\n this.enqueueWebchatSseEvent(sessionKey, { type: 'message_update', message });\n this.enqueueWebchatSseEvent(sessionKey, { type: 'message_end', message });\n }\n this.cfg.onSessionTranscriptUpdated?.(sessionKey);\n }\n\n /**\n * Queue a steering user message into pi-agent's in-flight run (delivered\n * after current tool work, before the next LLM call). See `Agent.steer`\n * in `@earendil-works/pi-agent-core`.\n */\n async steerWebchatSession(sessionKey: string, text: string): Promise<boolean> {\n const trimmed = text.trim();\n if (!trimmed) return false;\n try {\n return await queueEmbeddedSteer(sessionKey, trimmed);\n } catch (err) {\n this.log.warn({ err, sessionKey }, 'steerWebchatSession failed');\n return false;\n }\n }\n\n private buildStreamingDeps(): ProcessDirectStreamingDeps {\n const c = this.cfg;\n return {\n log: this.log,\n parseSessionKey: c.parseSessionKey,\n initDirectStreamingSession: c.initSessionContext,\n registerWebchatSsePublisher: (sk, publisher) =>\n c.sessionState.registerWebchatPublisher(sk, publisher),\n unregisterWebchatSsePublisher: (sk) => c.sessionState.unregisterWebchatPublisher(sk),\n agentManager: c.agentManager,\n hydrateSessionWorkspaceFromStore: (sk) => c.sessionHydrator.workspace(sk),\n hydrateSessionModelFromStore: (sk) => c.sessionHydrator.model(sk),\n sessionStore: c.sessionStore,\n modelManager: c.modelManager,\n applyResolvedThinkingLevel: (sk, t) => c.sessionHydrator.thinking(sk, t),\n getConfig: c.getConfig,\n sessionConfigStore: c.sessionConfigStore,\n commandHandler: c.commandHandler,\n prepareInboundAttachments: c.prepareInboundAttachments,\n buildTranscriptUserMessage: async (text, prepared, sk) =>\n buildDirectUserMessageContent({\n content: text,\n attachments: prepared,\n sessionKey: sk,\n config: c.requireConfig(),\n agentManager: c.agentManager,\n modelManager: c.modelManager,\n }),\n recordPersistentGoalStreamOutcome: (sk, o) =>\n c.sessionState.recordPersistentGoalStreamOutcome(sk, o),\n enqueueProvisionalSessionTitle: (sk, userText) => {\n c.enqueueProvisionalSessionTitle?.(sk, userText);\n },\n onTurnComplete: (sk, text) => {\n if (text) {\n c.sessionState.setLastAssistantText(sk, text);\n }\n c.enqueueMaybeAutoTitleAfterPersist(sk);\n },\n reloadWebchatTranscript: (sk) => {\n c.onSessionTranscriptUpdated?.(sk);\n },\n maybeEmitWebchatTts: (sk, hadVoice) =>\n maybeEmitWebchatTts(\n {\n config: c.getConfig(),\n sessionStore: c.sessionStore,\n getLastAssistantPlainText: (sessionKey) =>\n c.sessionState.getLastAssistantText(sessionKey) ??\n c.agentManager.getLastAssistantContent(sessionKey) ??\n '',\n log: this.log,\n },\n sk,\n hadVoice,\n ),\n endDirectRequestContext: c.endDirectRequestContext,\n resetSession: c.resetSession,\n };\n }\n\n private buildOneShotDeps(): RunProcessDirectDeps {\n const c = this.cfg;\n const cfg = c.requireConfig();\n return {\n log: this.log,\n config: cfg,\n parseSessionKey: c.parseSessionKey,\n initSessionContext: (sk, channel, chatId) => {\n void c.initSessionContext(sk, channel, chatId);\n },\n hydrateSessionWorkspaceFromStore: (sk) => c.sessionHydrator.workspace(sk),\n hydrateSessionModelFromStore: (sk) => c.sessionHydrator.model(sk),\n agentManager: c.agentManager,\n sessionStore: c.sessionStore,\n modelManager: c.modelManager,\n applyResolvedThinkingLevel: (sk, t) => c.sessionHydrator.thinking(sk, t),\n prepareInboundAttachments: c.prepareInboundAttachments,\n commandHandler: c.commandHandler,\n onTurnComplete: (sk, text) => {\n if (text) {\n c.sessionState.setLastAssistantText(sk, text);\n }\n c.enqueueMaybeAutoTitleAfterPersist(sk);\n },\n endDirectRequestContext: c.endDirectRequestContext,\n resetSession: c.resetSession,\n };\n }\n}\n"],"mappings":"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"}
@@ -71,7 +71,7 @@ export declare class ModelManager {
71
71
  */
72
72
  applyModelForSession(agent: Agent, sessionKey: string): Promise<void>;
73
73
  /**
74
- * Ordered model candidates for the session (primary + `agents.defaults.model.fallbacks`).
74
+ * Ordered model candidates for the session (primary + `agents.defaults.models.chat.fallbacks`).
75
75
  */
76
76
  getFallbackCandidatesForSession(sessionKey: string): ModelCandidate[];
77
77
  /**
@@ -148,7 +148,7 @@ var ModelManager = class {
148
148
  }, "Applied model for session");
149
149
  }
150
150
  /**
151
- * Ordered model candidates for the session (primary + `agents.defaults.model.fallbacks`).
151
+ * Ordered model candidates for the session (primary + `agents.defaults.models.chat.fallbacks`).
152
152
  */
153
153
  getFallbackCandidatesForSession(sessionKey) {
154
154
  const parsed = parseModelRef(this.getModelForSession(sessionKey));
@@ -1 +1 @@
1
- {"version":3,"file":"manager.js","names":["getAllModelsFromProviders"],"sources":["../../../../src/agent/models/manager.ts"],"sourcesContent":["/**\n * Model management module\n * \n * Handles model selection, switching, and automatic fallback\n * when a provider fails.\n */\n\nimport { Agent, type AgentMessage } from '@earendil-works/pi-agent-core';\nimport type { Model, Api } from '@earendil-works/pi-ai';\nimport { type Config, getAgentDefaultModelRef } from '../../config/schema.js';\nimport { createLogger } from '../../utils/logger.js';\nimport { resolveModel, getAllModels as getAllModelsFromProviders, getDefaultModelSync } from '../../providers/index.js';\nimport {\n isFailoverError,\n describeFailoverError,\n resolveFallbackCandidates,\n type ModelCandidate,\n} from '../fallback/index.js';\nimport { parseModelRef } from './selection.js';\nimport {\n isAssistantTurnAborted,\n isAssistantTurnFailed,\n maybeRetryTurnAfterTransientLlmFailure,\n} from '../orchestration/llm-turn-retry.js';\nimport {\n resolveAgentTurnTimeoutMs,\n runAgentTurnWithTimeout,\n} from '../orchestration/run-agent-turn-with-timeout.js';\n\nconst log = createLogger('ModelManager');\n\nexport interface ModelManagerConfig {\n defaultModel?: string;\n config?: Config;\n}\n\nexport interface RunResult {\n content: string | null;\n usage?: {\n prompt_tokens: number;\n completion_tokens: number;\n total_tokens: number;\n };\n}\n\n/**\n * Get the last assistant content from agent messages\n */\nfunction getLastAssistantContent(agent: Agent): string | null {\n const messages = agent.state.messages;\n for (let i = messages.length - 1; i >= 0; i--) {\n const msg = messages[i];\n if (msg.role === 'assistant') {\n return msg.content\n .filter((c) => c.type === 'text')\n .map((c) => c.text || '')\n .join('');\n }\n }\n return null;\n}\n\nexport class ModelManager {\n private defaultModel: string;\n private config?: Config;\n private currentModelName: string;\n private currentProvider: string;\n private sessionModels: Map<string, string> = new Map();\n /** Baseline model from `agents.list` / defaults merge when the session agent is created. */\n private sessionProfileDefaults: Map<string, string> = new Map();\n private channelManager?: any;\n\n constructor(config: ModelManagerConfig = {}) {\n this.config = config.config;\n this.defaultModel = config.defaultModel || getDefaultModelSync(config.config);\n this.currentModelName = this.defaultModel;\n this.currentProvider = this.defaultModel.split('/')[0] || 'anthropic';\n }\n\n /**\n * Set channel manager reference for accessing session-specific settings\n */\n setChannelManager(channelManager: any): void {\n this.channelManager = channelManager;\n }\n\n /**\n * Apply updated config so default model and failover metadata match disk/runtime config.\n */\n updateFromConfig(config: Config): void {\n this.config = config;\n const ref = getAgentDefaultModelRef(config);\n this.defaultModel = ref ? ref : getDefaultModelSync(config);\n this.sessionProfileDefaults.clear();\n }\n\n /**\n * Set the config-derived default model for a session (from effective agent profile).\n * Cleared by {@link updateFromConfig} or {@link clearSessionProfileDefault}.\n */\n setSessionProfileDefault(sessionKey: string, modelRef: string): void {\n this.sessionProfileDefaults.set(sessionKey, modelRef);\n }\n\n clearSessionProfileDefault(sessionKey: string): void {\n this.sessionProfileDefaults.delete(sessionKey);\n }\n\n /**\n * Get current model name\n */\n getCurrentModel(): string {\n return this.currentModelName;\n }\n\n /**\n * Get current provider\n */\n getCurrentProvider(): string {\n return this.currentProvider;\n }\n\n /**\n * Switch model for a specific session\n */\n async switchModelForSession(sessionKey: string, modelId: string): Promise<boolean> {\n try {\n resolveModel(modelId);\n this.sessionModels.set(sessionKey, modelId);\n log.info({ sessionKey, modelId }, 'Model switched for session');\n return true;\n } catch (err) {\n log.error({ err, sessionKey, modelId }, 'Failed to switch model');\n return false;\n }\n }\n\n /** Drop in-memory session override so the global default is used again. */\n clearSessionModelOverride(sessionKey: string): void {\n this.sessionModels.delete(sessionKey);\n }\n\n /**\n * Resolved pi-ai model for session (for transcript policy, tools, etc.)\n */\n getResolvedModelForSession(sessionKey: string): Model<Api> {\n return resolveModel(this.getModelForSession(sessionKey));\n }\n\n /**\n * Get model for session, checking session override first\n */\n getModelForSession(sessionKey: string): string {\n const sessionModel = this.sessionModels.get(sessionKey);\n if (sessionModel) {\n return sessionModel;\n }\n\n const profileDefault = this.sessionProfileDefaults.get(sessionKey);\n if (profileDefault) {\n return profileDefault;\n }\n\n return this.defaultModel;\n }\n\n /**\n * Apply model to agent if different from current\n */\n async applyModelForSession(agent: Agent, sessionKey: string): Promise<void> {\n const targetModelId = this.getModelForSession(sessionKey);\n\n let found: Model<Api>;\n try {\n found = resolveModel(targetModelId);\n } catch (err) {\n log.error({ err, sessionKey, modelId: targetModelId }, 'Failed to apply model');\n return;\n }\n\n const sm = agent.state.model as Model<Api> | undefined;\n if (sm && sm.provider === found.provider && sm.id === found.id) {\n this.currentModelName = targetModelId;\n this.currentProvider = found.provider || 'unknown';\n return;\n }\n\n agent.state.model = found;\n this.currentModelName = targetModelId;\n this.currentProvider = found.provider || 'unknown';\n\n log.info({ sessionKey, modelId: targetModelId }, 'Applied model for session');\n }\n\n /**\n * Ordered model candidates for the session (primary + `agents.defaults.model.fallbacks`).\n */\n getFallbackCandidatesForSession(sessionKey: string): ModelCandidate[] {\n const ref = this.getModelForSession(sessionKey);\n const parsed = parseModelRef(ref);\n if (!parsed) {\n return [];\n }\n return resolveFallbackCandidates({\n cfg: this.config,\n provider: parsed.provider,\n model: parsed.model,\n });\n }\n\n /**\n * Apply a resolved pi-ai model and sync {@link currentModelName} / {@link currentProvider}.\n */\n applyResolvedModel(agent: Agent, model: Model<Api>, modelRef: string): void {\n agent.state.model = model;\n this.currentModelName = modelRef;\n this.currentProvider = model.provider || 'unknown';\n }\n\n /**\n * Run the agent with automatic model fallback on failure.\n */\n async runWithFallback(\n agent: Agent,\n sessionKey: string,\n userMessage: AgentMessage,\n provider: string,\n model: string\n ): Promise<RunResult> {\n const candidates = resolveFallbackCandidates({\n cfg: this.config ?? undefined,\n provider,\n model,\n });\n\n let lastError: unknown;\n\n for (let i = 0; i < candidates.length; i++) {\n const candidate = candidates[i];\n const modelRef = `${candidate.provider}/${candidate.model}`;\n\n let candidateModel: Model<Api>;\n try {\n candidateModel = resolveModel(modelRef);\n } catch {\n log.warn({ provider: candidate.provider, model: candidate.model }, 'Fallback model not found');\n continue;\n }\n\n log.info(\n { attempt: i + 1, total: candidates.length, provider: candidate.provider, model: candidate.model },\n 'Attempting model',\n );\n\n const beforeLen = agent.state.messages.length;\n\n try {\n this.applyResolvedModel(agent, candidateModel, modelRef);\n\n const runTurn = async () => {\n await agent.prompt(userMessage);\n await agent.waitForIdle();\n await maybeRetryTurnAfterTransientLlmFailure(agent, { sessionKey, log });\n };\n\n await runAgentTurnWithTimeout(agent, runTurn, resolveAgentTurnTimeoutMs(this.config));\n\n if (isAssistantTurnAborted(agent)) {\n const usage = (agent.state as { lastUsage?: RunResult['usage'] }).lastUsage;\n return { content: getLastAssistantContent(agent), usage };\n }\n\n if (!isAssistantTurnFailed(agent)) {\n const usage = (agent.state as { lastUsage?: RunResult['usage'] }).lastUsage;\n log.info(\n { provider: candidate.provider, model: candidate.model, success: true },\n 'Model call completed',\n );\n return { content: getLastAssistantContent(agent), usage };\n }\n\n lastError = new Error(`Assistant turn failed: ${modelRef}`);\n log.warn(\n { attempt: i + 1, sessionKey, modelRef },\n 'Model turn failed after retries, trying fallback',\n );\n } catch (err) {\n lastError = err;\n if (err instanceof DOMException && err.name === 'AbortError') {\n log.info({ sessionKey }, 'User aborted model call');\n throw err;\n }\n\n const errorDetails = {\n attempt: i + 1,\n provider: candidate.provider,\n model: candidate.model,\n errorMessage: err instanceof Error ? err.message : String(err),\n };\n\n if (isFailoverError(err)) {\n const described = describeFailoverError(err);\n log.warn({ ...errorDetails, ...described }, 'Model call failed, trying fallback');\n } else {\n log.warn(errorDetails, 'Model call failed, trying fallback');\n }\n }\n\n agent.state.messages = agent.state.messages.slice(0, beforeLen);\n }\n\n if (lastError) {\n const em = lastError instanceof Error ? lastError.message : String(lastError);\n const attemptedModelRefs = candidates.map((c) => `${c.provider}/${c.model}`);\n log.error(\n {\n err: lastError instanceof Error ? lastError : undefined,\n errorMessage: em,\n attemptedCandidates: candidates.length,\n attemptedModelRefs,\n sessionKey,\n },\n `All model candidates failed (${candidates.length} refs): ${em}`,\n );\n throw lastError instanceof Error ? lastError : new Error(String(lastError));\n }\n\n return { content: null };\n }\n\n /**\n * Find model by reference (provider/modelId)\n */\n findByRef(ref: string): Model<Api> | undefined {\n try {\n return resolveModel(ref);\n } catch {\n return undefined;\n }\n }\n\n /**\n * Find model by provider and ID\n */\n find(provider: string, modelId: string): Model<Api> | undefined {\n try {\n return resolveModel(`${provider}/${modelId}`);\n } catch {\n return undefined;\n }\n }\n\n /**\n * Get all available models\n */\n getAllModels(): readonly Model<Api>[] {\n return getAllModelsFromProviders();\n }\n\n /**\n * Get models grouped by provider\n */\n getModelsByProvider(): Map<string, Model<Api>[]> {\n const all = this.getAllModels();\n const grouped = new Map<string, Model<Api>[]>();\n for (const model of all) {\n const list = grouped.get(model.provider) ?? [];\n list.push(model);\n grouped.set(model.provider, list);\n }\n return grouped;\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"manager.js","names":["getAllModelsFromProviders"],"sources":["../../../../src/agent/models/manager.ts"],"sourcesContent":["/**\n * Model management module\n * \n * Handles model selection, switching, and automatic fallback\n * when a provider fails.\n */\n\nimport { Agent, type AgentMessage } from '@earendil-works/pi-agent-core';\nimport type { Model, Api } from '@earendil-works/pi-ai';\nimport { type Config, getAgentDefaultModelRef } from '../../config/schema.js';\nimport { createLogger } from '../../utils/logger.js';\nimport { resolveModel, getAllModels as getAllModelsFromProviders, getDefaultModelSync } from '../../providers/index.js';\nimport {\n isFailoverError,\n describeFailoverError,\n resolveFallbackCandidates,\n type ModelCandidate,\n} from '../fallback/index.js';\nimport { parseModelRef } from './selection.js';\nimport {\n isAssistantTurnAborted,\n isAssistantTurnFailed,\n maybeRetryTurnAfterTransientLlmFailure,\n} from '../orchestration/llm-turn-retry.js';\nimport {\n resolveAgentTurnTimeoutMs,\n runAgentTurnWithTimeout,\n} from '../orchestration/run-agent-turn-with-timeout.js';\n\nconst log = createLogger('ModelManager');\n\nexport interface ModelManagerConfig {\n defaultModel?: string;\n config?: Config;\n}\n\nexport interface RunResult {\n content: string | null;\n usage?: {\n prompt_tokens: number;\n completion_tokens: number;\n total_tokens: number;\n };\n}\n\n/**\n * Get the last assistant content from agent messages\n */\nfunction getLastAssistantContent(agent: Agent): string | null {\n const messages = agent.state.messages;\n for (let i = messages.length - 1; i >= 0; i--) {\n const msg = messages[i];\n if (msg.role === 'assistant') {\n return msg.content\n .filter((c) => c.type === 'text')\n .map((c) => c.text || '')\n .join('');\n }\n }\n return null;\n}\n\nexport class ModelManager {\n private defaultModel: string;\n private config?: Config;\n private currentModelName: string;\n private currentProvider: string;\n private sessionModels: Map<string, string> = new Map();\n /** Baseline model from `agents.list` / defaults merge when the session agent is created. */\n private sessionProfileDefaults: Map<string, string> = new Map();\n private channelManager?: any;\n\n constructor(config: ModelManagerConfig = {}) {\n this.config = config.config;\n this.defaultModel = config.defaultModel || getDefaultModelSync(config.config);\n this.currentModelName = this.defaultModel;\n this.currentProvider = this.defaultModel.split('/')[0] || 'anthropic';\n }\n\n /**\n * Set channel manager reference for accessing session-specific settings\n */\n setChannelManager(channelManager: any): void {\n this.channelManager = channelManager;\n }\n\n /**\n * Apply updated config so default model and failover metadata match disk/runtime config.\n */\n updateFromConfig(config: Config): void {\n this.config = config;\n const ref = getAgentDefaultModelRef(config);\n this.defaultModel = ref ? ref : getDefaultModelSync(config);\n this.sessionProfileDefaults.clear();\n }\n\n /**\n * Set the config-derived default model for a session (from effective agent profile).\n * Cleared by {@link updateFromConfig} or {@link clearSessionProfileDefault}.\n */\n setSessionProfileDefault(sessionKey: string, modelRef: string): void {\n this.sessionProfileDefaults.set(sessionKey, modelRef);\n }\n\n clearSessionProfileDefault(sessionKey: string): void {\n this.sessionProfileDefaults.delete(sessionKey);\n }\n\n /**\n * Get current model name\n */\n getCurrentModel(): string {\n return this.currentModelName;\n }\n\n /**\n * Get current provider\n */\n getCurrentProvider(): string {\n return this.currentProvider;\n }\n\n /**\n * Switch model for a specific session\n */\n async switchModelForSession(sessionKey: string, modelId: string): Promise<boolean> {\n try {\n resolveModel(modelId);\n this.sessionModels.set(sessionKey, modelId);\n log.info({ sessionKey, modelId }, 'Model switched for session');\n return true;\n } catch (err) {\n log.error({ err, sessionKey, modelId }, 'Failed to switch model');\n return false;\n }\n }\n\n /** Drop in-memory session override so the global default is used again. */\n clearSessionModelOverride(sessionKey: string): void {\n this.sessionModels.delete(sessionKey);\n }\n\n /**\n * Resolved pi-ai model for session (for transcript policy, tools, etc.)\n */\n getResolvedModelForSession(sessionKey: string): Model<Api> {\n return resolveModel(this.getModelForSession(sessionKey));\n }\n\n /**\n * Get model for session, checking session override first\n */\n getModelForSession(sessionKey: string): string {\n const sessionModel = this.sessionModels.get(sessionKey);\n if (sessionModel) {\n return sessionModel;\n }\n\n const profileDefault = this.sessionProfileDefaults.get(sessionKey);\n if (profileDefault) {\n return profileDefault;\n }\n\n return this.defaultModel;\n }\n\n /**\n * Apply model to agent if different from current\n */\n async applyModelForSession(agent: Agent, sessionKey: string): Promise<void> {\n const targetModelId = this.getModelForSession(sessionKey);\n\n let found: Model<Api>;\n try {\n found = resolveModel(targetModelId);\n } catch (err) {\n log.error({ err, sessionKey, modelId: targetModelId }, 'Failed to apply model');\n return;\n }\n\n const sm = agent.state.model as Model<Api> | undefined;\n if (sm && sm.provider === found.provider && sm.id === found.id) {\n this.currentModelName = targetModelId;\n this.currentProvider = found.provider || 'unknown';\n return;\n }\n\n agent.state.model = found;\n this.currentModelName = targetModelId;\n this.currentProvider = found.provider || 'unknown';\n\n log.info({ sessionKey, modelId: targetModelId }, 'Applied model for session');\n }\n\n /**\n * Ordered model candidates for the session (primary + `agents.defaults.models.chat.fallbacks`).\n */\n getFallbackCandidatesForSession(sessionKey: string): ModelCandidate[] {\n const ref = this.getModelForSession(sessionKey);\n const parsed = parseModelRef(ref);\n if (!parsed) {\n return [];\n }\n return resolveFallbackCandidates({\n cfg: this.config,\n provider: parsed.provider,\n model: parsed.model,\n });\n }\n\n /**\n * Apply a resolved pi-ai model and sync {@link currentModelName} / {@link currentProvider}.\n */\n applyResolvedModel(agent: Agent, model: Model<Api>, modelRef: string): void {\n agent.state.model = model;\n this.currentModelName = modelRef;\n this.currentProvider = model.provider || 'unknown';\n }\n\n /**\n * Run the agent with automatic model fallback on failure.\n */\n async runWithFallback(\n agent: Agent,\n sessionKey: string,\n userMessage: AgentMessage,\n provider: string,\n model: string\n ): Promise<RunResult> {\n const candidates = resolveFallbackCandidates({\n cfg: this.config ?? undefined,\n provider,\n model,\n });\n\n let lastError: unknown;\n\n for (let i = 0; i < candidates.length; i++) {\n const candidate = candidates[i];\n const modelRef = `${candidate.provider}/${candidate.model}`;\n\n let candidateModel: Model<Api>;\n try {\n candidateModel = resolveModel(modelRef);\n } catch {\n log.warn({ provider: candidate.provider, model: candidate.model }, 'Fallback model not found');\n continue;\n }\n\n log.info(\n { attempt: i + 1, total: candidates.length, provider: candidate.provider, model: candidate.model },\n 'Attempting model',\n );\n\n const beforeLen = agent.state.messages.length;\n\n try {\n this.applyResolvedModel(agent, candidateModel, modelRef);\n\n const runTurn = async () => {\n await agent.prompt(userMessage);\n await agent.waitForIdle();\n await maybeRetryTurnAfterTransientLlmFailure(agent, { sessionKey, log });\n };\n\n await runAgentTurnWithTimeout(agent, runTurn, resolveAgentTurnTimeoutMs(this.config));\n\n if (isAssistantTurnAborted(agent)) {\n const usage = (agent.state as { lastUsage?: RunResult['usage'] }).lastUsage;\n return { content: getLastAssistantContent(agent), usage };\n }\n\n if (!isAssistantTurnFailed(agent)) {\n const usage = (agent.state as { lastUsage?: RunResult['usage'] }).lastUsage;\n log.info(\n { provider: candidate.provider, model: candidate.model, success: true },\n 'Model call completed',\n );\n return { content: getLastAssistantContent(agent), usage };\n }\n\n lastError = new Error(`Assistant turn failed: ${modelRef}`);\n log.warn(\n { attempt: i + 1, sessionKey, modelRef },\n 'Model turn failed after retries, trying fallback',\n );\n } catch (err) {\n lastError = err;\n if (err instanceof DOMException && err.name === 'AbortError') {\n log.info({ sessionKey }, 'User aborted model call');\n throw err;\n }\n\n const errorDetails = {\n attempt: i + 1,\n provider: candidate.provider,\n model: candidate.model,\n errorMessage: err instanceof Error ? err.message : String(err),\n };\n\n if (isFailoverError(err)) {\n const described = describeFailoverError(err);\n log.warn({ ...errorDetails, ...described }, 'Model call failed, trying fallback');\n } else {\n log.warn(errorDetails, 'Model call failed, trying fallback');\n }\n }\n\n agent.state.messages = agent.state.messages.slice(0, beforeLen);\n }\n\n if (lastError) {\n const em = lastError instanceof Error ? lastError.message : String(lastError);\n const attemptedModelRefs = candidates.map((c) => `${c.provider}/${c.model}`);\n log.error(\n {\n err: lastError instanceof Error ? lastError : undefined,\n errorMessage: em,\n attemptedCandidates: candidates.length,\n attemptedModelRefs,\n sessionKey,\n },\n `All model candidates failed (${candidates.length} refs): ${em}`,\n );\n throw lastError instanceof Error ? lastError : new Error(String(lastError));\n }\n\n return { content: null };\n }\n\n /**\n * Find model by reference (provider/modelId)\n */\n findByRef(ref: string): Model<Api> | undefined {\n try {\n return resolveModel(ref);\n } catch {\n return undefined;\n }\n }\n\n /**\n * Find model by provider and ID\n */\n find(provider: string, modelId: string): Model<Api> | undefined {\n try {\n return resolveModel(`${provider}/${modelId}`);\n } catch {\n return undefined;\n }\n }\n\n /**\n * Get all available models\n */\n getAllModels(): readonly Model<Api>[] {\n return getAllModelsFromProviders();\n }\n\n /**\n * Get models grouped by provider\n */\n getModelsByProvider(): Map<string, Model<Api>[]> {\n const all = this.getAllModels();\n const grouped = new Map<string, Model<Api>[]>();\n for (const model of all) {\n const list = grouped.get(model.provider) ?? [];\n list.push(model);\n grouped.set(model.provider, list);\n }\n return grouped;\n }\n}\n"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Primary chat model + `agents.defaults.model.fallbacks`: one user turn with rollback on failure.
2
+ * Primary chat model + `agents.defaults.models.chat.fallbacks`: one user turn with rollback on failure.
3
3
  * Used by channel orchestrator, gateway webchat stream, and direct CLI-style turns.
4
4
  */
5
5
  import type { Agent, AgentMessage } from '@earendil-works/pi-agent-core';
@@ -9,7 +9,7 @@ async function runAgentTurnWithModelFallbacks(params) {
9
9
  const beforeUserPrompt = params.beforeUserPrompt ?? (async () => {});
10
10
  const afterUserPrompt = params.afterUserPrompt ?? (async () => {});
11
11
  const candidates = modelManager.getFallbackCandidatesForSession(sessionKey);
12
- if (candidates.length === 0) throw new Error("No model candidates available. Configure agents.defaults.model and provider API keys.");
12
+ if (candidates.length === 0) throw new Error("No model candidates available. Configure agents.defaults.models.chat and provider API keys.");
13
13
  let lastError;
14
14
  for (let i = 0; i < candidates.length; i++) {
15
15
  const candidate = candidates[i];
@@ -1 +1 @@
1
- {"version":3,"file":"run-agent-turn-with-fallbacks.js","names":[],"sources":["../../../../src/agent/orchestration/run-agent-turn-with-fallbacks.ts"],"sourcesContent":["/**\n * Primary chat model + `agents.defaults.model.fallbacks`: one user turn with rollback on failure.\n * Used by channel orchestrator, gateway webchat stream, and direct CLI-style turns.\n */\n\nimport type { Agent, AgentMessage } from '@earendil-works/pi-agent-core';\nimport type { Model, Api } from '@earendil-works/pi-ai';\n\nimport type { Config } from '../../config/schema.js';\nimport { resolveModel } from '../../providers/index.js';\nimport type { ModelManager } from '../models/index.js';\nimport {\n isAssistantTurnAborted,\n isAssistantTurnFailed,\n maybeRetryTurnAfterTransientLlmFailure,\n} from './llm-turn-retry.js';\nimport { resolveAgentTurnTimeoutMs, runAgentTurnWithTimeout } from './run-agent-turn-with-timeout.js';\n\nexport { resolveAgentTurnTimeoutMs };\n\ntype FallbackLog = {\n info: (obj: Record<string, unknown>, msg: string) => void;\n warn: (obj: Record<string, unknown>, msg: string) => void;\n debug?: (obj: Record<string, unknown>, msg: string) => void;\n};\n\nexport async function runAgentTurnWithModelFallbacks(params: {\n agent: Agent;\n sessionKey: string;\n modelManager: ModelManager;\n userMessage: AgentMessage;\n log: FallbackLog;\n /** Before `prompt` adds the user message (e.g. background-review nudge counters). */\n beforeUserPrompt?: () => void | Promise<void>;\n /** After `prompt` adds the user message; before `waitForIdle`. */\n afterUserPrompt?: () => Promise<void>;\n /** Overrides {@link resolveAgentTurnTimeoutMs} when set. */\n timeoutMs?: number;\n /** Supplies `agents.defaults.maxTaskDurationMs` for the default turn limit. */\n getConfig?: () => Config | undefined;\n}): Promise<void> {\n const { agent, sessionKey, modelManager, userMessage, log } = params;\n const timeoutMs = params.timeoutMs ?? resolveAgentTurnTimeoutMs(params.getConfig?.());\n const beforeUserPrompt = params.beforeUserPrompt ?? (async () => {});\n const afterUserPrompt = params.afterUserPrompt ?? (async () => {});\n\n const candidates = modelManager.getFallbackCandidatesForSession(sessionKey);\n if (candidates.length === 0) {\n throw new Error(\n 'No model candidates available. Configure agents.defaults.model and provider API keys.',\n );\n }\n\n let lastError: unknown;\n\n for (let i = 0; i < candidates.length; i++) {\n const candidate = candidates[i];\n const modelRef = `${candidate.provider}/${candidate.model}`;\n\n let resolved: Model<Api>;\n try {\n resolved = resolveModel(modelRef);\n } catch (err) {\n lastError = err;\n log.warn({ err, modelRef, attempt: i + 1 }, 'Skipping model candidate (resolve failed)');\n continue;\n }\n\n const beforeLen = agent.state.messages.length;\n\n try {\n modelManager.applyResolvedModel(agent, resolved, modelRef);\n\n log.info(\n { attempt: i + 1, total: candidates.length, provider: candidate.provider, model: candidate.model },\n 'Running agent turn',\n );\n\n const runTurn = async () => {\n await beforeUserPrompt();\n await agent.prompt(userMessage);\n await afterUserPrompt();\n await agent.waitForIdle();\n await maybeRetryTurnAfterTransientLlmFailure(agent, { sessionKey, log });\n };\n\n await runAgentTurnWithTimeout(agent, runTurn, timeoutMs);\n\n if (isAssistantTurnAborted(agent)) {\n return;\n }\n\n if (!isAssistantTurnFailed(agent)) {\n return;\n }\n\n lastError = new Error(`Assistant turn failed: ${modelRef}`);\n log.warn(\n { sessionKey, attempt: i + 1, total: candidates.length, modelRef },\n 'Model turn failed after retries, trying fallback',\n );\n } catch (err) {\n lastError = err;\n if (err instanceof DOMException && err.name === 'AbortError') {\n throw err;\n }\n log.warn({ err, sessionKey, attempt: i + 1, modelRef }, 'Model call threw, trying fallback');\n }\n\n agent.state.messages = agent.state.messages.slice(0, beforeLen);\n }\n\n if (lastError instanceof Error) {\n throw lastError;\n }\n throw new Error(lastError != null ? String(lastError) : 'All model candidates failed');\n}\n"],"mappings":";;;;gBASwD;AAiBxD,eAAsB,+BAA+B,QAcnC;CAChB,MAAM,EAAE,OAAO,YAAY,cAAc,aAAa,QAAQ;CAC9D,MAAM,YAAY,OAAO,aAAa,0BAA0B,OAAO,aAAa,CAAC;CACrF,MAAM,mBAAmB,OAAO,qBAAqB,YAAY;CACjE,MAAM,kBAAkB,OAAO,oBAAoB,YAAY;CAE/D,MAAM,aAAa,aAAa,gCAAgC,WAAW;AAC3E,KAAI,WAAW,WAAW,EACxB,OAAM,IAAI,MACR,wFACD;CAGH,IAAI;AAEJ,MAAK,IAAI,IAAI,GAAG,IAAI,WAAW,QAAQ,KAAK;EAC1C,MAAM,YAAY,WAAW;EAC7B,MAAM,WAAW,GAAG,UAAU,SAAS,GAAG,UAAU;EAEpD,IAAI;AACJ,MAAI;AACF,cAAW,aAAa,SAAS;WAC1B,KAAK;AACZ,eAAY;AACZ,OAAI,KAAK;IAAE;IAAK;IAAU,SAAS,IAAI;IAAG,EAAE,4CAA4C;AACxF;;EAGF,MAAM,YAAY,MAAM,MAAM,SAAS;AAEvC,MAAI;AACF,gBAAa,mBAAmB,OAAO,UAAU,SAAS;AAE1D,OAAI,KACF;IAAE,SAAS,IAAI;IAAG,OAAO,WAAW;IAAQ,UAAU,UAAU;IAAU,OAAO,UAAU;IAAO,EAClG,qBACD;GAED,MAAM,UAAU,YAAY;AAC1B,UAAM,kBAAkB;AACxB,UAAM,MAAM,OAAO,YAAY;AAC/B,UAAM,iBAAiB;AACvB,UAAM,MAAM,aAAa;AACzB,UAAM,uCAAuC,OAAO;KAAE;KAAY;KAAK,CAAC;;AAG1E,SAAM,wBAAwB,OAAO,SAAS,UAAU;AAExD,OAAI,uBAAuB,MAAM,CAC/B;AAGF,OAAI,CAAC,sBAAsB,MAAM,CAC/B;AAGF,+BAAY,IAAI,MAAM,0BAA0B,WAAW;AAC3D,OAAI,KACF;IAAE;IAAY,SAAS,IAAI;IAAG,OAAO,WAAW;IAAQ;IAAU,EAClE,mDACD;WACM,KAAK;AACZ,eAAY;AACZ,OAAI,eAAe,gBAAgB,IAAI,SAAS,aAC9C,OAAM;AAER,OAAI,KAAK;IAAE;IAAK;IAAY,SAAS,IAAI;IAAG;IAAU,EAAE,oCAAoC;;AAG9F,QAAM,MAAM,WAAW,MAAM,MAAM,SAAS,MAAM,GAAG,UAAU;;AAGjE,KAAI,qBAAqB,MACvB,OAAM;AAER,OAAM,IAAI,MAAM,aAAa,OAAO,OAAO,UAAU,GAAG,8BAA8B"}
1
+ {"version":3,"file":"run-agent-turn-with-fallbacks.js","names":[],"sources":["../../../../src/agent/orchestration/run-agent-turn-with-fallbacks.ts"],"sourcesContent":["/**\n * Primary chat model + `agents.defaults.models.chat.fallbacks`: one user turn with rollback on failure.\n * Used by channel orchestrator, gateway webchat stream, and direct CLI-style turns.\n */\n\nimport type { Agent, AgentMessage } from '@earendil-works/pi-agent-core';\nimport type { Model, Api } from '@earendil-works/pi-ai';\n\nimport type { Config } from '../../config/schema.js';\nimport { resolveModel } from '../../providers/index.js';\nimport type { ModelManager } from '../models/index.js';\nimport {\n isAssistantTurnAborted,\n isAssistantTurnFailed,\n maybeRetryTurnAfterTransientLlmFailure,\n} from './llm-turn-retry.js';\nimport { resolveAgentTurnTimeoutMs, runAgentTurnWithTimeout } from './run-agent-turn-with-timeout.js';\n\nexport { resolveAgentTurnTimeoutMs };\n\ntype FallbackLog = {\n info: (obj: Record<string, unknown>, msg: string) => void;\n warn: (obj: Record<string, unknown>, msg: string) => void;\n debug?: (obj: Record<string, unknown>, msg: string) => void;\n};\n\nexport async function runAgentTurnWithModelFallbacks(params: {\n agent: Agent;\n sessionKey: string;\n modelManager: ModelManager;\n userMessage: AgentMessage;\n log: FallbackLog;\n /** Before `prompt` adds the user message (e.g. background-review nudge counters). */\n beforeUserPrompt?: () => void | Promise<void>;\n /** After `prompt` adds the user message; before `waitForIdle`. */\n afterUserPrompt?: () => Promise<void>;\n /** Overrides {@link resolveAgentTurnTimeoutMs} when set. */\n timeoutMs?: number;\n /** Supplies `agents.defaults.maxTaskDurationMs` for the default turn limit. */\n getConfig?: () => Config | undefined;\n}): Promise<void> {\n const { agent, sessionKey, modelManager, userMessage, log } = params;\n const timeoutMs = params.timeoutMs ?? resolveAgentTurnTimeoutMs(params.getConfig?.());\n const beforeUserPrompt = params.beforeUserPrompt ?? (async () => {});\n const afterUserPrompt = params.afterUserPrompt ?? (async () => {});\n\n const candidates = modelManager.getFallbackCandidatesForSession(sessionKey);\n if (candidates.length === 0) {\n throw new Error(\n 'No model candidates available. Configure agents.defaults.models.chat and provider API keys.',\n );\n }\n\n let lastError: unknown;\n\n for (let i = 0; i < candidates.length; i++) {\n const candidate = candidates[i];\n const modelRef = `${candidate.provider}/${candidate.model}`;\n\n let resolved: Model<Api>;\n try {\n resolved = resolveModel(modelRef);\n } catch (err) {\n lastError = err;\n log.warn({ err, modelRef, attempt: i + 1 }, 'Skipping model candidate (resolve failed)');\n continue;\n }\n\n const beforeLen = agent.state.messages.length;\n\n try {\n modelManager.applyResolvedModel(agent, resolved, modelRef);\n\n log.info(\n { attempt: i + 1, total: candidates.length, provider: candidate.provider, model: candidate.model },\n 'Running agent turn',\n );\n\n const runTurn = async () => {\n await beforeUserPrompt();\n await agent.prompt(userMessage);\n await afterUserPrompt();\n await agent.waitForIdle();\n await maybeRetryTurnAfterTransientLlmFailure(agent, { sessionKey, log });\n };\n\n await runAgentTurnWithTimeout(agent, runTurn, timeoutMs);\n\n if (isAssistantTurnAborted(agent)) {\n return;\n }\n\n if (!isAssistantTurnFailed(agent)) {\n return;\n }\n\n lastError = new Error(`Assistant turn failed: ${modelRef}`);\n log.warn(\n { sessionKey, attempt: i + 1, total: candidates.length, modelRef },\n 'Model turn failed after retries, trying fallback',\n );\n } catch (err) {\n lastError = err;\n if (err instanceof DOMException && err.name === 'AbortError') {\n throw err;\n }\n log.warn({ err, sessionKey, attempt: i + 1, modelRef }, 'Model call threw, trying fallback');\n }\n\n agent.state.messages = agent.state.messages.slice(0, beforeLen);\n }\n\n if (lastError instanceof Error) {\n throw lastError;\n }\n throw new Error(lastError != null ? String(lastError) : 'All model candidates failed');\n}\n"],"mappings":";;;;gBASwD;AAiBxD,eAAsB,+BAA+B,QAcnC;CAChB,MAAM,EAAE,OAAO,YAAY,cAAc,aAAa,QAAQ;CAC9D,MAAM,YAAY,OAAO,aAAa,0BAA0B,OAAO,aAAa,CAAC;CACrF,MAAM,mBAAmB,OAAO,qBAAqB,YAAY;CACjE,MAAM,kBAAkB,OAAO,oBAAoB,YAAY;CAE/D,MAAM,aAAa,aAAa,gCAAgC,WAAW;AAC3E,KAAI,WAAW,WAAW,EACxB,OAAM,IAAI,MACR,8FACD;CAGH,IAAI;AAEJ,MAAK,IAAI,IAAI,GAAG,IAAI,WAAW,QAAQ,KAAK;EAC1C,MAAM,YAAY,WAAW;EAC7B,MAAM,WAAW,GAAG,UAAU,SAAS,GAAG,UAAU;EAEpD,IAAI;AACJ,MAAI;AACF,cAAW,aAAa,SAAS;WAC1B,KAAK;AACZ,eAAY;AACZ,OAAI,KAAK;IAAE;IAAK;IAAU,SAAS,IAAI;IAAG,EAAE,4CAA4C;AACxF;;EAGF,MAAM,YAAY,MAAM,MAAM,SAAS;AAEvC,MAAI;AACF,gBAAa,mBAAmB,OAAO,UAAU,SAAS;AAE1D,OAAI,KACF;IAAE,SAAS,IAAI;IAAG,OAAO,WAAW;IAAQ,UAAU,UAAU;IAAU,OAAO,UAAU;IAAO,EAClG,qBACD;GAED,MAAM,UAAU,YAAY;AAC1B,UAAM,kBAAkB;AACxB,UAAM,MAAM,OAAO,YAAY;AAC/B,UAAM,iBAAiB;AACvB,UAAM,MAAM,aAAa;AACzB,UAAM,uCAAuC,OAAO;KAAE;KAAY;KAAK,CAAC;;AAG1E,SAAM,wBAAwB,OAAO,SAAS,UAAU;AAExD,OAAI,uBAAuB,MAAM,CAC/B;AAGF,OAAI,CAAC,sBAAsB,MAAM,CAC/B;AAGF,+BAAY,IAAI,MAAM,0BAA0B,WAAW;AAC3D,OAAI,KACF;IAAE;IAAY,SAAS,IAAI;IAAG,OAAO,WAAW;IAAQ;IAAU,EAClE,mDACD;WACM,KAAK;AACZ,eAAY;AACZ,OAAI,eAAe,gBAAgB,IAAI,SAAS,aAC9C,OAAM;AAER,OAAI,KAAK;IAAE;IAAK;IAAY,SAAS,IAAI;IAAG;IAAU,EAAE,oCAAoC;;AAG9F,QAAM,MAAM,WAAW,MAAM,MAAM,SAAS,MAAM,GAAG,UAAU;;AAGjE,KAAI,qBAAqB,MACvB,OAAM;AAER,OAAM,IAAI,MAAM,aAAa,OAAO,OAAO,UAAU,GAAG,8BAA8B"}
@@ -18,6 +18,7 @@ const CORE_TOOL_ORDER = [
18
18
  "session_search",
19
19
  "curated_memory",
20
20
  "session_status",
21
+ "tool_manual",
21
22
  "delegate_task",
22
23
  "workflow",
23
24
  "cronjob",
@@ -51,6 +52,7 @@ const CORE_TOOL_SUMMARIES = {
51
52
  session_search: "Search other chat sessions or list recent sessions",
52
53
  curated_memory: "Read/write structured notes under agent home memories/",
53
54
  session_status: "Show session usage/time/model state",
55
+ tool_manual: "Load built-in usage manuals for complex tools",
54
56
  delegate_task: "Spawn an isolated sub-agent for a delegated task",
55
57
  workflow: "Start a persisted multi-phase workflow run",
56
58
  cronjob: "Manage scheduled cron jobs",
@@ -95,6 +97,7 @@ function buildToolingSection(params) {
95
97
  const shellToolName = resolveToolName("shell");
96
98
  const hasDelegate = availableTools.has("delegate_task");
97
99
  const hasWorkflow = availableTools.has("workflow");
100
+ const hasToolManual = availableTools.has("tool_manual");
98
101
  const orchestrationLines = [];
99
102
  if (hasDelegate) orchestrationLines.push("- Sub-agent delegation → use `delegate_task(goal, context?, toolset?)` for focused parallel work; results return to you automatically.");
100
103
  if (hasWorkflow) orchestrationLines.push("- Multi-phase workflows → use `workflow` to start persisted runs with subagents when a script defines phases.");
@@ -104,6 +107,7 @@ function buildToolingSection(params) {
104
107
  "Tool names are case-sensitive. Call tools exactly as listed.",
105
108
  toolLines.length > 0 ? toolLines.join("\n") : "- No tools are registered for this session.",
106
109
  `For long waits, avoid rapid poll loops: use \`${shellToolName}\` with enough yieldMs or poll in reasonable intervals.`,
110
+ hasToolManual ? "Some complex tools have built-in manuals. Use `tool_manual(tool)` before non-trivial use." : "",
107
111
  hasDelegate ? "If a task is complex or long-running, delegate it. Completion is push-based: the sub-agent result returns when done." : "",
108
112
  ...orchestrationLines,
109
113
  "Do not poll delegate/workflow status in a tight loop; check on-demand or wait for completion."
@@ -1 +1 @@
1
- {"version":3,"file":"tooling.js","names":[],"sources":["../../../../../src/agent/prompt/sections/tooling.ts"],"sourcesContent":["const CORE_TOOL_ORDER = [\n 'read_file',\n 'write_file',\n 'edit_file',\n 'grep',\n 'find',\n 'list_dir',\n 'shell',\n 'web_search',\n 'web_fetch',\n 'web_extract',\n 'browser_use',\n 'send_message',\n 'send_media',\n 'memory_search',\n 'memory_get',\n 'session_search',\n 'curated_memory',\n 'session_status',\n 'delegate_task',\n 'workflow',\n 'cronjob',\n 'skills_list',\n 'skill_view',\n 'skill_manage',\n 'todo',\n 'clarify',\n 'text_to_speech',\n 'image',\n 'image_generate',\n 'create_share',\n 'execute_code',\n] as const;\n\nconst CORE_TOOL_SUMMARIES: Record<string, string> = {\n read_file: 'Read file contents',\n write_file: 'Create or overwrite files',\n edit_file: 'Make precise edits to files',\n grep: 'Search file contents for patterns',\n find: 'Find files by glob pattern',\n list_dir: 'List directory contents',\n shell: 'Run shell commands (supports background via yieldMs/background)',\n web_search: 'Search the web',\n web_fetch: 'Fetch and extract readable content from a URL',\n web_extract: 'Extract structured content from a URL',\n browser_use: 'Control the configured browser',\n send_message: 'Send messages to the current channel',\n send_media: 'Send media attachments to the current channel',\n memory_search: 'Semantic search over workspace and profile memory files',\n memory_get: 'Read specific lines from memory files',\n session_search: 'Search other chat sessions or list recent sessions',\n curated_memory: 'Read/write structured notes under agent home memories/',\n session_status: 'Show session usage/time/model state',\n delegate_task: 'Spawn an isolated sub-agent for a delegated task',\n workflow: 'Start a persisted multi-phase workflow run',\n cronjob: 'Manage scheduled cron jobs',\n skills_list: 'List available skills',\n skill_view: 'Load a skill SKILL.md or sub-documents',\n skill_manage: 'Create or update skills on disk',\n todo: 'Manage in-session todo items',\n clarify: 'Ask the user a blocking clarification question',\n text_to_speech: 'Send a standalone voice message',\n image: 'Analyze an image with the configured vision model',\n image_generate: 'Generate images with the configured image model',\n create_share: 'Create a shareable link for workspace files',\n execute_code: 'Run code in a sandbox with a restricted tool subset',\n};\n\nexport function buildToolingSection(params: {\n toolNames?: string[];\n toolSummaries?: Record<string, string>;\n}): string {\n const rawToolNames = (params.toolNames ?? []).map((tool) => tool.trim()).filter(Boolean);\n const canonicalByNormalized = new Map<string, string>();\n for (const name of rawToolNames) {\n const normalized = name.toLowerCase();\n if (!canonicalByNormalized.has(normalized)) {\n canonicalByNormalized.set(normalized, name);\n }\n }\n const resolveToolName = (normalized: string) =>\n canonicalByNormalized.get(normalized) ?? normalized;\n\n const normalizedTools = rawToolNames.map((tool) => tool.toLowerCase());\n const availableTools = new Set(normalizedTools);\n\n const externalToolSummaries = new Map<string, string>();\n for (const [key, value] of Object.entries(params.toolSummaries ?? {})) {\n const normalized = key.trim().toLowerCase();\n if (!normalized || !value?.trim()) {\n continue;\n }\n externalToolSummaries.set(normalized, value.trim());\n }\n\n const extraTools = Array.from(\n new Set(normalizedTools.filter((tool) => !CORE_TOOL_ORDER.includes(tool as (typeof CORE_TOOL_ORDER)[number]))),\n );\n const enabledTools = CORE_TOOL_ORDER.filter((tool) => availableTools.has(tool));\n const toolLines = enabledTools.map((tool) => {\n const summary = CORE_TOOL_SUMMARIES[tool] ?? externalToolSummaries.get(tool);\n const name = resolveToolName(tool);\n return summary ? `- ${name}: ${summary}` : `- ${name}`;\n });\n for (const tool of extraTools.toSorted()) {\n const summary = CORE_TOOL_SUMMARIES[tool] ?? externalToolSummaries.get(tool);\n const name = resolveToolName(tool);\n toolLines.push(summary ? `- ${name}: ${summary}` : `- ${name}`);\n }\n\n const shellToolName = resolveToolName('shell');\n const hasDelegate = availableTools.has('delegate_task');\n const hasWorkflow = availableTools.has('workflow');\n\n const orchestrationLines: string[] = [];\n if (hasDelegate) {\n orchestrationLines.push(\n '- Sub-agent delegation → use `delegate_task(goal, context?, toolset?)` for focused parallel work; results return to you automatically.',\n );\n }\n if (hasWorkflow) {\n orchestrationLines.push(\n '- Multi-phase workflows → use `workflow` to start persisted runs with subagents when a script defines phases.',\n );\n }\n\n return [\n '## Tooling',\n 'Tool availability (filtered by policy):',\n 'Tool names are case-sensitive. Call tools exactly as listed.',\n toolLines.length > 0\n ? toolLines.join('\\n')\n : '- No tools are registered for this session.',\n `For long waits, avoid rapid poll loops: use \\`${shellToolName}\\` with enough yieldMs or poll in reasonable intervals.`,\n hasDelegate\n ? 'If a task is complex or long-running, delegate it. Completion is push-based: the sub-agent result returns when done.'\n : '',\n ...orchestrationLines,\n 'Do not poll delegate/workflow status in a tight loop; check on-demand or wait for completion.',\n ]\n .filter(Boolean)\n .join('\\n');\n}\n\nexport function hasSkillsTools(toolNames: string[]): boolean {\n const normalized = new Set(toolNames.map((t) => t.toLowerCase()));\n return normalized.has('skills_list') || normalized.has('skill_view');\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"tooling.js","names":[],"sources":["../../../../../src/agent/prompt/sections/tooling.ts"],"sourcesContent":["const CORE_TOOL_ORDER = [\n 'read_file',\n 'write_file',\n 'edit_file',\n 'grep',\n 'find',\n 'list_dir',\n 'shell',\n 'web_search',\n 'web_fetch',\n 'web_extract',\n 'browser_use',\n 'send_message',\n 'send_media',\n 'memory_search',\n 'memory_get',\n 'session_search',\n 'curated_memory',\n 'session_status',\n 'tool_manual',\n 'delegate_task',\n 'workflow',\n 'cronjob',\n 'skills_list',\n 'skill_view',\n 'skill_manage',\n 'todo',\n 'clarify',\n 'text_to_speech',\n 'image',\n 'image_generate',\n 'create_share',\n 'execute_code',\n] as const;\n\nconst CORE_TOOL_SUMMARIES: Record<string, string> = {\n read_file: 'Read file contents',\n write_file: 'Create or overwrite files',\n edit_file: 'Make precise edits to files',\n grep: 'Search file contents for patterns',\n find: 'Find files by glob pattern',\n list_dir: 'List directory contents',\n shell: 'Run shell commands (supports background via yieldMs/background)',\n web_search: 'Search the web',\n web_fetch: 'Fetch and extract readable content from a URL',\n web_extract: 'Extract structured content from a URL',\n browser_use: 'Control the configured browser',\n send_message: 'Send messages to the current channel',\n send_media: 'Send media attachments to the current channel',\n memory_search: 'Semantic search over workspace and profile memory files',\n memory_get: 'Read specific lines from memory files',\n session_search: 'Search other chat sessions or list recent sessions',\n curated_memory: 'Read/write structured notes under agent home memories/',\n session_status: 'Show session usage/time/model state',\n tool_manual: 'Load built-in usage manuals for complex tools',\n delegate_task: 'Spawn an isolated sub-agent for a delegated task',\n workflow: 'Start a persisted multi-phase workflow run',\n cronjob: 'Manage scheduled cron jobs',\n skills_list: 'List available skills',\n skill_view: 'Load a skill SKILL.md or sub-documents',\n skill_manage: 'Create or update skills on disk',\n todo: 'Manage in-session todo items',\n clarify: 'Ask the user a blocking clarification question',\n text_to_speech: 'Send a standalone voice message',\n image: 'Analyze an image with the configured vision model',\n image_generate: 'Generate images with the configured image model',\n create_share: 'Create a shareable link for workspace files',\n execute_code: 'Run code in a sandbox with a restricted tool subset',\n};\n\nexport function buildToolingSection(params: {\n toolNames?: string[];\n toolSummaries?: Record<string, string>;\n}): string {\n const rawToolNames = (params.toolNames ?? []).map((tool) => tool.trim()).filter(Boolean);\n const canonicalByNormalized = new Map<string, string>();\n for (const name of rawToolNames) {\n const normalized = name.toLowerCase();\n if (!canonicalByNormalized.has(normalized)) {\n canonicalByNormalized.set(normalized, name);\n }\n }\n const resolveToolName = (normalized: string) =>\n canonicalByNormalized.get(normalized) ?? normalized;\n\n const normalizedTools = rawToolNames.map((tool) => tool.toLowerCase());\n const availableTools = new Set(normalizedTools);\n\n const externalToolSummaries = new Map<string, string>();\n for (const [key, value] of Object.entries(params.toolSummaries ?? {})) {\n const normalized = key.trim().toLowerCase();\n if (!normalized || !value?.trim()) {\n continue;\n }\n externalToolSummaries.set(normalized, value.trim());\n }\n\n const extraTools = Array.from(\n new Set(normalizedTools.filter((tool) => !CORE_TOOL_ORDER.includes(tool as (typeof CORE_TOOL_ORDER)[number]))),\n );\n const enabledTools = CORE_TOOL_ORDER.filter((tool) => availableTools.has(tool));\n const toolLines = enabledTools.map((tool) => {\n const summary = CORE_TOOL_SUMMARIES[tool] ?? externalToolSummaries.get(tool);\n const name = resolveToolName(tool);\n return summary ? `- ${name}: ${summary}` : `- ${name}`;\n });\n for (const tool of extraTools.toSorted()) {\n const summary = CORE_TOOL_SUMMARIES[tool] ?? externalToolSummaries.get(tool);\n const name = resolveToolName(tool);\n toolLines.push(summary ? `- ${name}: ${summary}` : `- ${name}`);\n }\n\n const shellToolName = resolveToolName('shell');\n const hasDelegate = availableTools.has('delegate_task');\n const hasWorkflow = availableTools.has('workflow');\n const hasToolManual = availableTools.has('tool_manual');\n\n const orchestrationLines: string[] = [];\n if (hasDelegate) {\n orchestrationLines.push(\n '- Sub-agent delegation → use `delegate_task(goal, context?, toolset?)` for focused parallel work; results return to you automatically.',\n );\n }\n if (hasWorkflow) {\n orchestrationLines.push(\n '- Multi-phase workflows → use `workflow` to start persisted runs with subagents when a script defines phases.',\n );\n }\n\n return [\n '## Tooling',\n 'Tool availability (filtered by policy):',\n 'Tool names are case-sensitive. Call tools exactly as listed.',\n toolLines.length > 0\n ? toolLines.join('\\n')\n : '- No tools are registered for this session.',\n `For long waits, avoid rapid poll loops: use \\`${shellToolName}\\` with enough yieldMs or poll in reasonable intervals.`,\n hasToolManual\n ? 'Some complex tools have built-in manuals. Use `tool_manual(tool)` before non-trivial use.'\n : '',\n hasDelegate\n ? 'If a task is complex or long-running, delegate it. Completion is push-based: the sub-agent result returns when done.'\n : '',\n ...orchestrationLines,\n 'Do not poll delegate/workflow status in a tight loop; check on-demand or wait for completion.',\n ]\n .filter(Boolean)\n .join('\\n');\n}\n\nexport function hasSkillsTools(toolNames: string[]): boolean {\n const normalized = new Set(toolNames.map((t) => t.toLowerCase()));\n return normalized.has('skills_list') || normalized.has('skill_view');\n}\n"],"mappings":"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"}
@@ -56,6 +56,7 @@ export interface RunDirectAgentTurnDeps {
56
56
  }
57
57
  export interface RunDirectAgentTurnInput {
58
58
  sessionKey: string;
59
+ runId?: string;
59
60
  userMessage: AgentMessage;
60
61
  abortSignal?: AbortSignal;
61
62
  onEvent?: (event: EmbeddedStreamEvent) => void;
@@ -81,7 +81,7 @@ async function runDirectAgentTurn(deps, input) {
81
81
  })).images;
82
82
  const result = await runEmbeddedTurnForSession({
83
83
  sessionKey: input.sessionKey,
84
- runId: crypto.randomUUID(),
84
+ runId: input.runId ?? crypto.randomUUID(),
85
85
  userMessage: userMessageForModel,
86
86
  llmImages,
87
87
  sessionStore: deps.sessionStore,
@@ -1 +1 @@
1
- {"version":3,"file":"direct-turn-helpers.js","names":[],"sources":["../../../../src/agent/service/direct-turn-helpers.ts"],"sourcesContent":["/**\n * Shared building blocks for the two direct-turn entry points (streaming\n * webchat SSE and one-shot CLI). Both flows do the same hydrate → maybe-slash\n * → run-embedded-turn → after-turn dance; this module captures that core so\n * the entry points only manage their I/O specifics (event sink, voice STT,\n * TTS, transcript persistence).\n */\n\nimport crypto from 'node:crypto';\n\nimport type { AgentMessage } from '@earendil-works/pi-agent-core';\n\nimport { commandRegistry } from '../../chat-commands/index.js';\nimport { parseSlashCommand } from '../../chat-commands/command-parse.js';\nimport { shouldSkipResetOverlapCommand } from '../../session/reset-triggers.js';\nimport { hydrateUserTurnForLlm, type TranscriptUserMessage } from '../inbound/attachment-pipeline.js';\nimport type { CommandHandler } from '../messaging/command-handler.js';\nimport type { SessionStore } from '../../session/index.js';\nimport type { Config } from '../../config/schema.js';\nimport type { AgentInstanceGateway } from '../agent-instance-gateway.js';\nimport type { ModelManager } from '../models/index.js';\nimport { extractAgentUserPlainText } from '../memory/user-message-text.js';\nimport { runEmbeddedTurnForSession } from '../embedded/run-for-session.js';\nimport type { EmbeddedStreamEvent } from '../embedded/types.js';\n\nexport interface HydratePerTurnStateDeps {\n hydrateSessionWorkspaceFromStore: (sessionKey: string) => Promise<void>;\n hydrateSessionModelFromStore: (sessionKey: string) => Promise<void>;\n applyResolvedThinkingLevel: (sessionKey: string, thinking?: string | null) => Promise<void>;\n}\n\n/** Workspace + model + thinking level — common prep before any direct turn. */\nexport async function hydratePerTurnState(\n deps: HydratePerTurnStateDeps,\n sessionKey: string,\n thinking?: string,\n): Promise<void> {\n await deps.hydrateSessionWorkspaceFromStore(sessionKey);\n await deps.hydrateSessionModelFromStore(sessionKey);\n await deps.applyResolvedThinkingLevel(sessionKey, thinking);\n}\n\nexport interface SlashCommandOutcome {\n /** True if the input parsed as a registered slash command (handled or not). */\n matched: boolean;\n /** Aggregated user-visible reply text (assistant view). */\n aggregatedText: string;\n /** The parsed command name when matched. */\n command?: string;\n}\n\nexport interface TryRunSlashCommandDeps {\n commandHandler: Pick<CommandHandler, 'executeCommandAndAggregateReply'>;\n log: { warn: (obj: Record<string, unknown>, msg: string) => void };\n}\n\n/**\n * Detect a slash command and, if registered, execute it and aggregate the reply\n * text. Errors thrown inside the command surface as `aggregatedText` so callers\n * can persist the receipt or stream it as a token.\n */\nexport async function tryRunSlashCommand(\n deps: TryRunSlashCommandDeps,\n ctx: {\n sessionKey: string;\n channel: string;\n chatId: string;\n senderId?: string;\n isGroup?: boolean;\n inboundMetadata?: Record<string, unknown>;\n },\n content: string,\n options?: { skipResetCommands?: boolean },\n): Promise<SlashCommandOutcome> {\n const parsed = parseSlashCommand(content);\n if (!parsed) {\n return { matched: false, aggregatedText: '' };\n }\n if (options?.skipResetCommands && shouldSkipResetOverlapCommand(parsed.command, true)) {\n return { matched: false, aggregatedText: '' };\n }\n if (!commandRegistry.has(parsed.command)) {\n return { matched: false, aggregatedText: '' };\n }\n try {\n const { aggregatedText } = await deps.commandHandler.executeCommandAndAggregateReply(\n parsed.command,\n parsed.args,\n {\n sessionKey: ctx.sessionKey,\n channel: ctx.channel,\n chatId: ctx.chatId,\n senderId: ctx.senderId ?? '',\n isGroup: ctx.isGroup ?? false,\n inboundMetadata: ctx.inboundMetadata ?? {},\n },\n );\n return { matched: true, aggregatedText: aggregatedText ?? '', command: parsed.command };\n } catch (err) {\n const em = err instanceof Error ? err.message : String(err);\n deps.log.warn(\n { err, sessionKey: ctx.sessionKey, command: parsed.command },\n `Slash command failed: ${em}`,\n );\n return { matched: true, aggregatedText: `Command error: ${em}`, command: parsed.command };\n }\n}\n\nexport interface RunDirectAgentTurnDeps {\n sessionStore: SessionStore;\n agentManager: AgentInstanceGateway;\n modelManager: ModelManager;\n config: Config | undefined;\n}\n\nexport interface RunDirectAgentTurnInput {\n sessionKey: string;\n userMessage: AgentMessage;\n abortSignal?: AbortSignal;\n onEvent?: (event: EmbeddedStreamEvent) => void;\n}\n\nexport interface RunDirectAgentTurnResult {\n ok: boolean;\n errorMessage?: string;\n lastAssistantText?: string;\n}\n\n/**\n * Convert a user message into an embedded turn, including the standard memory\n * prefetch + background-review nudge wiring used by every direct entry point.\n */\nexport async function runDirectAgentTurn(\n deps: RunDirectAgentTurnDeps,\n input: RunDirectAgentTurnInput,\n): Promise<RunDirectAgentTurnResult> {\n const userPlain = extractAgentUserPlainText(input.userMessage);\n const userMessageForModel = await deps.agentManager.applyMemoryPrefetchToUserMessage(\n input.userMessage,\n input.sessionKey,\n );\n\n const modelRef = deps.modelManager.getModelForSession(input.sessionKey);\n const llmTurn = await hydrateUserTurnForLlm({\n message: input.userMessage as TranscriptUserMessage,\n modelRef,\n });\n const llmImages = llmTurn.images;\n\n const result = await runEmbeddedTurnForSession({\n sessionKey: input.sessionKey,\n runId: crypto.randomUUID(),\n userMessage: userMessageForModel,\n llmImages,\n sessionStore: deps.sessionStore,\n agentManager: deps.agentManager,\n modelManager: deps.modelManager,\n getConfig: () => deps.config,\n abortSignal: input.abortSignal,\n beforeTurn: () => deps.agentManager.beginBackgroundReviewUserTurn(input.sessionKey),\n onEvent: input.onEvent,\n });\n\n deps.agentManager.afterAgentTurn(input.sessionKey, userPlain);\n deps.agentManager.scheduleBackgroundReviewAfterUserTurn(input.sessionKey);\n\n return result;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AAgCA,eAAsB,oBACpB,MACA,YACA,UACe;AACf,OAAM,KAAK,iCAAiC,WAAW;AACvD,OAAM,KAAK,6BAA6B,WAAW;AACnD,OAAM,KAAK,2BAA2B,YAAY,SAAS;;;;;;;AAsB7D,eAAsB,mBACpB,MACA,KAQA,SACA,SAC8B;CAC9B,MAAM,SAAS,kBAAkB,QAAQ;AACzC,KAAI,CAAC,OACH,QAAO;EAAE,SAAS;EAAO,gBAAgB;EAAI;AAE/C,KAAI,SAAS,qBAAqB,8BAA8B,OAAO,SAAS,KAAK,CACnF,QAAO;EAAE,SAAS;EAAO,gBAAgB;EAAI;AAE/C,KAAI,CAAC,gBAAgB,IAAI,OAAO,QAAQ,CACtC,QAAO;EAAE,SAAS;EAAO,gBAAgB;EAAI;AAE/C,KAAI;EACF,MAAM,EAAE,mBAAmB,MAAM,KAAK,eAAe,gCACnD,OAAO,SACP,OAAO,MACP;GACE,YAAY,IAAI;GAChB,SAAS,IAAI;GACb,QAAQ,IAAI;GACZ,UAAU,IAAI,YAAY;GAC1B,SAAS,IAAI,WAAW;GACxB,iBAAiB,IAAI,mBAAmB,EAAE;GAC3C,CACF;AACD,SAAO;GAAE,SAAS;GAAM,gBAAgB,kBAAkB;GAAI,SAAS,OAAO;GAAS;UAChF,KAAK;EACZ,MAAM,KAAK,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI;AAC3D,OAAK,IAAI,KACP;GAAE;GAAK,YAAY,IAAI;GAAY,SAAS,OAAO;GAAS,EAC5D,yBAAyB,KAC1B;AACD,SAAO;GAAE,SAAS;GAAM,gBAAgB,kBAAkB;GAAM,SAAS,OAAO;GAAS;;;;;;;AA4B7F,eAAsB,mBACpB,MACA,OACmC;CACnC,MAAM,YAAY,0BAA0B,MAAM,YAAY;CAC9D,MAAM,sBAAsB,MAAM,KAAK,aAAa,iCAClD,MAAM,aACN,MAAM,WACP;CAED,MAAM,WAAW,KAAK,aAAa,mBAAmB,MAAM,WAAW;CAKvE,MAAM,aAAY,MAJI,sBAAsB;EAC1C,SAAS,MAAM;EACf;EACD,CAAC,EACwB;CAE1B,MAAM,SAAS,MAAM,0BAA0B;EAC7C,YAAY,MAAM;EAClB,OAAO,OAAO,YAAY;EAC1B,aAAa;EACb;EACA,cAAc,KAAK;EACnB,cAAc,KAAK;EACnB,cAAc,KAAK;EACnB,iBAAiB,KAAK;EACtB,aAAa,MAAM;EACnB,kBAAkB,KAAK,aAAa,8BAA8B,MAAM,WAAW;EACnF,SAAS,MAAM;EAChB,CAAC;AAEF,MAAK,aAAa,eAAe,MAAM,YAAY,UAAU;AAC7D,MAAK,aAAa,sCAAsC,MAAM,WAAW;AAEzE,QAAO"}
1
+ {"version":3,"file":"direct-turn-helpers.js","names":[],"sources":["../../../../src/agent/service/direct-turn-helpers.ts"],"sourcesContent":["/**\n * Shared building blocks for the two direct-turn entry points (streaming\n * webchat SSE and one-shot CLI). Both flows do the same hydrate → maybe-slash\n * → run-embedded-turn → after-turn dance; this module captures that core so\n * the entry points only manage their I/O specifics (event sink, voice STT,\n * TTS, transcript persistence).\n */\n\nimport crypto from 'node:crypto';\n\nimport type { AgentMessage } from '@earendil-works/pi-agent-core';\n\nimport { commandRegistry } from '../../chat-commands/index.js';\nimport { parseSlashCommand } from '../../chat-commands/command-parse.js';\nimport { shouldSkipResetOverlapCommand } from '../../session/reset-triggers.js';\nimport { hydrateUserTurnForLlm, type TranscriptUserMessage } from '../inbound/attachment-pipeline.js';\nimport type { CommandHandler } from '../messaging/command-handler.js';\nimport type { SessionStore } from '../../session/index.js';\nimport type { Config } from '../../config/schema.js';\nimport type { AgentInstanceGateway } from '../agent-instance-gateway.js';\nimport type { ModelManager } from '../models/index.js';\nimport { extractAgentUserPlainText } from '../memory/user-message-text.js';\nimport { runEmbeddedTurnForSession } from '../embedded/run-for-session.js';\nimport type { EmbeddedStreamEvent } from '../embedded/types.js';\n\nexport interface HydratePerTurnStateDeps {\n hydrateSessionWorkspaceFromStore: (sessionKey: string) => Promise<void>;\n hydrateSessionModelFromStore: (sessionKey: string) => Promise<void>;\n applyResolvedThinkingLevel: (sessionKey: string, thinking?: string | null) => Promise<void>;\n}\n\n/** Workspace + model + thinking level — common prep before any direct turn. */\nexport async function hydratePerTurnState(\n deps: HydratePerTurnStateDeps,\n sessionKey: string,\n thinking?: string,\n): Promise<void> {\n await deps.hydrateSessionWorkspaceFromStore(sessionKey);\n await deps.hydrateSessionModelFromStore(sessionKey);\n await deps.applyResolvedThinkingLevel(sessionKey, thinking);\n}\n\nexport interface SlashCommandOutcome {\n /** True if the input parsed as a registered slash command (handled or not). */\n matched: boolean;\n /** Aggregated user-visible reply text (assistant view). */\n aggregatedText: string;\n /** The parsed command name when matched. */\n command?: string;\n}\n\nexport interface TryRunSlashCommandDeps {\n commandHandler: Pick<CommandHandler, 'executeCommandAndAggregateReply'>;\n log: { warn: (obj: Record<string, unknown>, msg: string) => void };\n}\n\n/**\n * Detect a slash command and, if registered, execute it and aggregate the reply\n * text. Errors thrown inside the command surface as `aggregatedText` so callers\n * can persist the receipt or stream it as a token.\n */\nexport async function tryRunSlashCommand(\n deps: TryRunSlashCommandDeps,\n ctx: {\n sessionKey: string;\n channel: string;\n chatId: string;\n senderId?: string;\n isGroup?: boolean;\n inboundMetadata?: Record<string, unknown>;\n },\n content: string,\n options?: { skipResetCommands?: boolean },\n): Promise<SlashCommandOutcome> {\n const parsed = parseSlashCommand(content);\n if (!parsed) {\n return { matched: false, aggregatedText: '' };\n }\n if (options?.skipResetCommands && shouldSkipResetOverlapCommand(parsed.command, true)) {\n return { matched: false, aggregatedText: '' };\n }\n if (!commandRegistry.has(parsed.command)) {\n return { matched: false, aggregatedText: '' };\n }\n try {\n const { aggregatedText } = await deps.commandHandler.executeCommandAndAggregateReply(\n parsed.command,\n parsed.args,\n {\n sessionKey: ctx.sessionKey,\n channel: ctx.channel,\n chatId: ctx.chatId,\n senderId: ctx.senderId ?? '',\n isGroup: ctx.isGroup ?? false,\n inboundMetadata: ctx.inboundMetadata ?? {},\n },\n );\n return { matched: true, aggregatedText: aggregatedText ?? '', command: parsed.command };\n } catch (err) {\n const em = err instanceof Error ? err.message : String(err);\n deps.log.warn(\n { err, sessionKey: ctx.sessionKey, command: parsed.command },\n `Slash command failed: ${em}`,\n );\n return { matched: true, aggregatedText: `Command error: ${em}`, command: parsed.command };\n }\n}\n\nexport interface RunDirectAgentTurnDeps {\n sessionStore: SessionStore;\n agentManager: AgentInstanceGateway;\n modelManager: ModelManager;\n config: Config | undefined;\n}\n\nexport interface RunDirectAgentTurnInput {\n sessionKey: string;\n runId?: string;\n userMessage: AgentMessage;\n abortSignal?: AbortSignal;\n onEvent?: (event: EmbeddedStreamEvent) => void;\n}\n\nexport interface RunDirectAgentTurnResult {\n ok: boolean;\n errorMessage?: string;\n lastAssistantText?: string;\n}\n\n/**\n * Convert a user message into an embedded turn, including the standard memory\n * prefetch + background-review nudge wiring used by every direct entry point.\n */\nexport async function runDirectAgentTurn(\n deps: RunDirectAgentTurnDeps,\n input: RunDirectAgentTurnInput,\n): Promise<RunDirectAgentTurnResult> {\n const userPlain = extractAgentUserPlainText(input.userMessage);\n const userMessageForModel = await deps.agentManager.applyMemoryPrefetchToUserMessage(\n input.userMessage,\n input.sessionKey,\n );\n\n const modelRef = deps.modelManager.getModelForSession(input.sessionKey);\n const llmTurn = await hydrateUserTurnForLlm({\n message: input.userMessage as TranscriptUserMessage,\n modelRef,\n });\n const llmImages = llmTurn.images;\n\n const result = await runEmbeddedTurnForSession({\n sessionKey: input.sessionKey,\n runId: input.runId ?? crypto.randomUUID(),\n userMessage: userMessageForModel,\n llmImages,\n sessionStore: deps.sessionStore,\n agentManager: deps.agentManager,\n modelManager: deps.modelManager,\n getConfig: () => deps.config,\n abortSignal: input.abortSignal,\n beforeTurn: () => deps.agentManager.beginBackgroundReviewUserTurn(input.sessionKey),\n onEvent: input.onEvent,\n });\n\n deps.agentManager.afterAgentTurn(input.sessionKey, userPlain);\n deps.agentManager.scheduleBackgroundReviewAfterUserTurn(input.sessionKey);\n\n return result;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AAgCA,eAAsB,oBACpB,MACA,YACA,UACe;AACf,OAAM,KAAK,iCAAiC,WAAW;AACvD,OAAM,KAAK,6BAA6B,WAAW;AACnD,OAAM,KAAK,2BAA2B,YAAY,SAAS;;;;;;;AAsB7D,eAAsB,mBACpB,MACA,KAQA,SACA,SAC8B;CAC9B,MAAM,SAAS,kBAAkB,QAAQ;AACzC,KAAI,CAAC,OACH,QAAO;EAAE,SAAS;EAAO,gBAAgB;EAAI;AAE/C,KAAI,SAAS,qBAAqB,8BAA8B,OAAO,SAAS,KAAK,CACnF,QAAO;EAAE,SAAS;EAAO,gBAAgB;EAAI;AAE/C,KAAI,CAAC,gBAAgB,IAAI,OAAO,QAAQ,CACtC,QAAO;EAAE,SAAS;EAAO,gBAAgB;EAAI;AAE/C,KAAI;EACF,MAAM,EAAE,mBAAmB,MAAM,KAAK,eAAe,gCACnD,OAAO,SACP,OAAO,MACP;GACE,YAAY,IAAI;GAChB,SAAS,IAAI;GACb,QAAQ,IAAI;GACZ,UAAU,IAAI,YAAY;GAC1B,SAAS,IAAI,WAAW;GACxB,iBAAiB,IAAI,mBAAmB,EAAE;GAC3C,CACF;AACD,SAAO;GAAE,SAAS;GAAM,gBAAgB,kBAAkB;GAAI,SAAS,OAAO;GAAS;UAChF,KAAK;EACZ,MAAM,KAAK,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI;AAC3D,OAAK,IAAI,KACP;GAAE;GAAK,YAAY,IAAI;GAAY,SAAS,OAAO;GAAS,EAC5D,yBAAyB,KAC1B;AACD,SAAO;GAAE,SAAS;GAAM,gBAAgB,kBAAkB;GAAM,SAAS,OAAO;GAAS;;;;;;;AA6B7F,eAAsB,mBACpB,MACA,OACmC;CACnC,MAAM,YAAY,0BAA0B,MAAM,YAAY;CAC9D,MAAM,sBAAsB,MAAM,KAAK,aAAa,iCAClD,MAAM,aACN,MAAM,WACP;CAED,MAAM,WAAW,KAAK,aAAa,mBAAmB,MAAM,WAAW;CAKvE,MAAM,aAAY,MAJI,sBAAsB;EAC1C,SAAS,MAAM;EACf;EACD,CAAC,EACwB;CAE1B,MAAM,SAAS,MAAM,0BAA0B;EAC7C,YAAY,MAAM;EAClB,OAAO,MAAM,SAAS,OAAO,YAAY;EACzC,aAAa;EACb;EACA,cAAc,KAAK;EACnB,cAAc,KAAK;EACnB,cAAc,KAAK;EACnB,iBAAiB,KAAK;EACtB,aAAa,MAAM;EACnB,kBAAkB,KAAK,aAAa,8BAA8B,MAAM,WAAW;EACnF,SAAS,MAAM;EAChB,CAAC;AAEF,MAAK,aAAa,eAAe,MAAM,YAAY,UAAU;AAC7D,MAAK,aAAa,sCAAsC,MAAM,WAAW;AAEzE,QAAO"}
@@ -60,6 +60,7 @@ export interface ProcessDirectStreamingInput {
60
60
  attachments?: DirectStreamInboundAttachment[];
61
61
  thinking?: string;
62
62
  signal?: AbortSignal;
63
+ runId?: string;
63
64
  }
64
65
  export type ProcessDirectStreamingSseEvent = {
65
66
  type: string;
@@ -6,11 +6,38 @@ import { initSessionTurn } from "../../session/init-session-turn.js";
6
6
  import "../../session/index.js";
7
7
  import { isVoiceLikeAttachment, mergeSttConfigFromAppConfig, mergeVoiceTranscriptsIntoUserText } from "../../channels/attachments/voice-stt-webchat.js";
8
8
  import { abortEmbeddedRun } from "../embedded/runs.js";
9
- import { mapEmbeddedEventToGatewaySse } from "../embedded/map-stream-events.js";
10
9
  import { applyReasoningVisibilityToSseEvent } from "../streaming/reasoning-visibility-sse.js";
11
10
  import { AsyncQueue } from "./async-queue.js";
12
11
  import { hydratePerTurnState, runDirectAgentTurn, tryRunSlashCommand } from "./direct-turn-helpers.js";
13
12
  //#region src/agent/service/process-direct-streaming.ts
13
+ function makeAssistantReceiptMessage(text) {
14
+ return {
15
+ role: "assistant",
16
+ content: [{
17
+ type: "text",
18
+ text
19
+ }],
20
+ timestamp: Date.now()
21
+ };
22
+ }
23
+ function pushAssistantReceipt(queue, text, runId) {
24
+ const message = makeAssistantReceiptMessage(text);
25
+ queue.push({
26
+ type: "message_start",
27
+ runId,
28
+ message
29
+ });
30
+ queue.push({
31
+ type: "message_update",
32
+ runId,
33
+ message
34
+ });
35
+ queue.push({
36
+ type: "message_end",
37
+ runId,
38
+ message
39
+ });
40
+ }
14
41
  async function* runProcessDirectStreaming(deps, input) {
15
42
  const sessionKey = input.sessionKey ?? "agent:main:main";
16
43
  const { channel, chatId } = deps.parseSessionKey(sessionKey);
@@ -57,10 +84,7 @@ async function* runProcessDirectStreaming(deps, input) {
57
84
  if (turn.bareReset && turn.ackMessage) {
58
85
  ranSlashCommand = true;
59
86
  webchatSlashReceipt = turn.ackMessage;
60
- pushVisible({
61
- type: "token",
62
- content: turn.ackMessage
63
- });
87
+ pushAssistantReceipt(queue, turn.ackMessage, input.runId);
64
88
  return;
65
89
  }
66
90
  turnBody = turn.bodyStripped;
@@ -122,16 +146,10 @@ async function* runProcessDirectStreaming(deps, input) {
122
146
  const text = slash.aggregatedText.trim();
123
147
  if (text) {
124
148
  webchatSlashReceipt = text;
125
- pushVisible({
126
- type: "token",
127
- content: text
128
- });
149
+ pushAssistantReceipt(queue, text, input.runId);
129
150
  } else if (channel === "webchat") {
130
151
  webchatSlashReceipt = "Command finished with no assistant text. If you used `/goal`, a follow-up turn may still be scheduled automatically.";
131
- pushVisible({
132
- type: "token",
133
- content: webchatSlashReceipt
134
- });
152
+ pushAssistantReceipt(queue, webchatSlashReceipt, input.runId);
135
153
  }
136
154
  return;
137
155
  }
@@ -158,12 +176,11 @@ async function* runProcessDirectStreaming(deps, input) {
158
176
  sessionKey,
159
177
  userMessage,
160
178
  abortSignal: signal,
179
+ runId: input.runId,
161
180
  onEvent: (embeddedEvent) => {
162
- const mapped = mapEmbeddedEventToGatewaySse(embeddedEvent);
163
- if (mapped) {
164
- if (mapped.type === "error" && typeof mapped.content === "string") mapped.content = formatStreamError(mapped.content);
165
- pushVisible(mapped);
166
- }
181
+ const event = { ...embeddedEvent };
182
+ if (event.type === "error" && typeof event.content === "string") event.content = formatStreamError(event.content);
183
+ pushVisible(event);
167
184
  }
168
185
  });
169
186
  if (result.lastAssistantText) deps.onTurnComplete?.(sessionKey, result.lastAssistantText);