@xopcai/xopc 0.0.103 → 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 (930) hide show
  1. package/README.md +7 -4
  2. package/README.zh-CN.md +7 -4
  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 +1 -1
  20. package/dist/extensions/feishu/xopc.extension.json +66 -1
  21. package/dist/extensions/telegram/src/adapters/gateway-setup.d.ts +2 -0
  22. package/dist/extensions/telegram/src/adapters/gateway-setup.js +146 -0
  23. package/dist/extensions/telegram/src/adapters/gateway-setup.js.map +1 -0
  24. package/dist/extensions/telegram/src/adapters/security-adapter.js +1 -1
  25. package/dist/extensions/telegram/src/command-handler.js +1 -2
  26. package/dist/extensions/telegram/src/command-handler.js.map +1 -1
  27. package/dist/extensions/telegram/src/config-schema.js +2 -2
  28. package/dist/extensions/telegram/src/config-schema.js.map +1 -1
  29. package/dist/extensions/telegram/src/doctor.d.ts +1 -0
  30. package/dist/extensions/telegram/src/doctor.js +68 -0
  31. package/dist/extensions/telegram/src/doctor.js.map +1 -1
  32. package/dist/extensions/telegram/src/index.d.ts +8 -1
  33. package/dist/extensions/telegram/src/index.js +15 -2
  34. package/dist/extensions/telegram/src/index.js.map +1 -0
  35. package/dist/extensions/telegram/src/plugin.d.ts +13 -5
  36. package/dist/extensions/telegram/src/plugin.js +32 -12
  37. package/dist/extensions/telegram/src/plugin.js.map +1 -1
  38. package/dist/extensions/telegram/src/proxy-fetch.js +22 -5
  39. package/dist/extensions/telegram/src/proxy-fetch.js.map +1 -1
  40. package/dist/extensions/telegram/xopc.extension.json +412 -5
  41. package/dist/extensions/weixin/src/adapters/onboard-cli.js +2 -2
  42. package/dist/extensions/weixin/src/adapters/onboard-cli.js.map +1 -1
  43. package/dist/extensions/weixin/src/api/api.js +1 -1
  44. package/dist/extensions/weixin/src/index.d.ts +8 -0
  45. package/dist/extensions/weixin/src/index.js +12 -1
  46. package/dist/extensions/weixin/src/index.js.map +1 -0
  47. package/dist/extensions/weixin/src/messaging/process-message.js +1 -1
  48. package/dist/extensions/weixin/src/plugin.d.ts +2 -1
  49. package/dist/extensions/weixin/src/plugin.js +77 -2
  50. package/dist/extensions/weixin/src/plugin.js.map +1 -1
  51. package/dist/extensions/weixin/xopc.extension.json +52 -0
  52. package/dist/gateway/static/root/assets/agents-CvsBrBfi.js +396 -0
  53. package/dist/gateway/static/root/assets/{apps-page-C5RmwmTT.js → apps-page-L-IwQTe0.js} +1 -1
  54. package/dist/gateway/static/root/assets/browser-BLJWD7WI.js +8 -0
  55. package/dist/gateway/static/root/assets/channels-settings-D95KuPeP.js +1 -0
  56. package/dist/gateway/static/root/assets/cron-page-CfkWXDAI.js +1 -0
  57. package/dist/gateway/static/root/assets/{dist-CWm8hTXZ.js → dist-C6vclgEL.js} +1 -1
  58. package/dist/gateway/static/root/assets/{extension-debug-page-BzYgTkS9.js → extension-debug-page-D4JYAbsX.js} +1 -1
  59. package/dist/gateway/static/root/assets/{extension-page-BmTZH6gL.js → extension-page-_T62gi6e.js} +1 -1
  60. package/dist/gateway/static/root/assets/extension-settings-page-CkJbjyM-.js +1 -0
  61. package/dist/gateway/static/root/assets/{fetch-CMoWY2Si.js → fetch-B5aiIguv.js} +1 -1
  62. package/dist/gateway/static/root/assets/gateway-startup-retry-DqmLXhs6.js +1 -0
  63. package/dist/gateway/static/root/assets/heartbeat-config-api-HwJV1K_Y.js +1 -0
  64. package/dist/gateway/static/root/assets/index-BPYKW7FB.css +1 -0
  65. package/dist/gateway/static/root/assets/index-DvTb6wNR.js +4845 -0
  66. package/dist/gateway/static/root/assets/{logs-page-BjdQjHwk.js → logs-page-DsjtTjBy.js} +2 -2
  67. package/dist/gateway/static/root/assets/{note-detail-page-8Er4197b.js → note-detail-page-B2V7RhgD.js} +43 -43
  68. package/dist/gateway/static/root/assets/{note-time-CF3vf1jm.js → note-time-BG8GCTr4.js} +1 -1
  69. package/dist/gateway/static/root/assets/notes-page-xrcVBQ6Z.js +1 -0
  70. package/dist/gateway/static/root/assets/schema-form-S-QUvhul.js +1 -0
  71. package/dist/gateway/static/root/assets/sessions-page-CrQer6Au.js +1 -0
  72. package/dist/gateway/static/root/assets/settings-advanced-gate-DujQl9c7.js +2 -0
  73. package/dist/gateway/static/root/assets/{settings-form-section-C7qA7y0J.js → settings-form-section-r1V7dRV6.js} +1 -1
  74. package/dist/gateway/static/root/assets/settings-page-C9nrONQ2.js +3 -0
  75. package/dist/gateway/static/root/assets/{share-preview-page-Tvr5Mtq5.js → share-preview-page-DOFy0FNt.js} +1 -1
  76. package/dist/gateway/static/root/assets/skills-page-DmTsrs_a.js +2 -0
  77. package/dist/gateway/static/root/assets/{theme-store-HTvJlFLL.js → theme-store-Bo3j5Ovv.js} +1 -1
  78. package/dist/gateway/static/root/assets/url-WgQIjFZu.js +3 -0
  79. package/dist/gateway/static/root/assets/voice-api-key-field-AjmUAlEQ.js +1 -0
  80. package/dist/gateway/static/root/assets/{workflow-page.utils-CeBkAjP7.js → workflow-page.utils-DLEJ92gK.js} +1 -1
  81. package/dist/gateway/static/root/assets/workflows-page-BnjjKrM1.js +27 -0
  82. package/dist/gateway/static/root/index.html +6 -5
  83. package/dist/package.js +1 -1
  84. package/dist/src/agent/agent-manager.d.ts +18 -6
  85. package/dist/src/agent/agent-manager.js +60 -35
  86. package/dist/src/agent/agent-manager.js.map +1 -1
  87. package/dist/src/agent/builtin-agent-ids.d.ts +2 -0
  88. package/dist/src/agent/builtin-agent-ids.js +17 -0
  89. package/dist/src/agent/builtin-agent-ids.js.map +1 -0
  90. package/dist/src/agent/child-agent-factory.d.ts +4 -0
  91. package/dist/src/agent/child-agent-factory.js +28 -8
  92. package/dist/src/agent/child-agent-factory.js.map +1 -1
  93. package/dist/src/agent/context/workspace-seed.js +1 -1
  94. package/dist/src/agent/context/workspace-templates/AGENTS.md +23 -184
  95. package/dist/src/agent/embedded/run-turn.js +8 -2
  96. package/dist/src/agent/embedded/run-turn.js.map +1 -1
  97. package/dist/src/agent/embedded/session-tool-result-guard.js +1 -1
  98. package/dist/src/agent/embedded/subscribe-session.js +33 -51
  99. package/dist/src/agent/embedded/subscribe-session.js.map +1 -1
  100. package/dist/src/agent/embedded/types.d.ts +36 -35
  101. package/dist/src/agent/fallback/candidates.js +1 -1
  102. package/dist/src/agent/fallback/candidates.js.map +1 -1
  103. package/dist/src/agent/inbound/inbound-loop.js +1 -1
  104. package/dist/src/agent/inbound/turn-dispatcher.d.ts +1 -0
  105. package/dist/src/agent/inbound/turn-dispatcher.js +24 -5
  106. package/dist/src/agent/inbound/turn-dispatcher.js.map +1 -1
  107. package/dist/src/agent/models/manager.d.ts +1 -1
  108. package/dist/src/agent/models/manager.js +1 -1
  109. package/dist/src/agent/models/manager.js.map +1 -1
  110. package/dist/src/agent/orchestration/run-agent-turn-with-fallbacks.d.ts +1 -1
  111. package/dist/src/agent/orchestration/run-agent-turn-with-fallbacks.js +1 -1
  112. package/dist/src/agent/orchestration/run-agent-turn-with-fallbacks.js.map +1 -1
  113. package/dist/src/agent/prompt/sections/tooling.js +4 -0
  114. package/dist/src/agent/prompt/sections/tooling.js.map +1 -1
  115. package/dist/src/agent/service/direct-turn-helpers.d.ts +1 -0
  116. package/dist/src/agent/service/direct-turn-helpers.js +1 -1
  117. package/dist/src/agent/service/direct-turn-helpers.js.map +1 -1
  118. package/dist/src/agent/service/process-direct-streaming.d.ts +1 -0
  119. package/dist/src/agent/service/process-direct-streaming.js +35 -18
  120. package/dist/src/agent/service/process-direct-streaming.js.map +1 -1
  121. package/dist/src/agent/service-inbound-utils.d.ts +0 -1
  122. package/dist/src/agent/service-inbound-utils.js +1 -17
  123. package/dist/src/agent/service-inbound-utils.js.map +1 -1
  124. package/dist/src/agent/service.d.ts +4 -4
  125. package/dist/src/agent/service.js +27 -15
  126. package/dist/src/agent/service.js.map +1 -1
  127. package/dist/src/agent/session/session-config-service.d.ts +1 -0
  128. package/dist/src/agent/session/session-config-service.js +9 -1
  129. package/dist/src/agent/session/session-config-service.js.map +1 -1
  130. package/dist/src/agent/session/session-inspector.d.ts +2 -1
  131. package/dist/src/agent/session/session-inspector.js +4 -0
  132. package/dist/src/agent/session/session-inspector.js.map +1 -1
  133. package/dist/src/agent/skills/config.js +1 -3
  134. package/dist/src/agent/skills/config.js.map +1 -1
  135. package/dist/src/agent/skills/format-skills-prompt.d.ts +1 -0
  136. package/dist/src/agent/skills/format-skills-prompt.js +3 -2
  137. package/dist/src/agent/skills/format-skills-prompt.js.map +1 -1
  138. package/dist/src/agent/skills/hub-pull.js +1 -1
  139. package/dist/src/agent/skills/index.js +20 -5
  140. package/dist/src/agent/skills/index.js.map +1 -1
  141. package/dist/src/agent/skills/installer.js +14 -27
  142. package/dist/src/agent/skills/installer.js.map +1 -1
  143. package/dist/src/agent/skills/marketplace/adapters/clawhub/adapter.js +11 -1
  144. package/dist/src/agent/skills/marketplace/adapters/clawhub/adapter.js.map +1 -1
  145. package/dist/src/agent/skills/marketplace/adapters/skillhub/adapter.js +18 -4
  146. package/dist/src/agent/skills/marketplace/adapters/skillhub/adapter.js.map +1 -1
  147. package/dist/src/agent/skills/marketplace/adapters/store/adapter.js +11 -2
  148. package/dist/src/agent/skills/marketplace/adapters/store/adapter.js.map +1 -1
  149. package/dist/src/agent/skills/marketplace/adapters/store/store-api-client.d.ts +2 -2
  150. package/dist/src/agent/skills/marketplace/adapters/store/store-api-client.js.map +1 -1
  151. package/dist/src/agent/skills/skill-manager.d.ts +4 -1
  152. package/dist/src/agent/skills/skill-manager.js +3 -3
  153. package/dist/src/agent/skills/skill-manager.js.map +1 -1
  154. package/dist/src/agent/skills/skill-view-path.d.ts +1 -17
  155. package/dist/src/agent/skills/skill-view-path.js +3 -66
  156. package/dist/src/agent/skills/skill-view-path.js.map +1 -1
  157. package/dist/src/agent/skills/test-framework.js +2 -3
  158. package/dist/src/agent/skills/test-framework.js.map +1 -1
  159. package/dist/src/agent/streaming/reasoning-visibility-sse.js +1 -0
  160. package/dist/src/agent/streaming/reasoning-visibility-sse.js.map +1 -1
  161. package/dist/src/agent/tool-manuals/browser.d.ts +1 -0
  162. package/{skills/browser/SKILL.md → dist/src/agent/tool-manuals/browser.js} +51 -54
  163. package/dist/src/agent/tool-manuals/browser.js.map +1 -0
  164. package/dist/src/agent/tool-manuals/index.d.ts +10 -0
  165. package/dist/src/agent/tool-manuals/index.js +28 -0
  166. package/dist/src/agent/tool-manuals/index.js.map +1 -0
  167. package/dist/src/agent/tools/browser/tool/browser-use-tool.js +1 -1
  168. package/dist/src/agent/tools/browser/tool/browser-use-tool.js.map +1 -1
  169. package/dist/src/agent/tools/factory.js +7 -5
  170. package/dist/src/agent/tools/factory.js.map +1 -1
  171. package/dist/src/agent/tools/index.d.ts +1 -0
  172. package/dist/src/agent/tools/index.js +5 -4
  173. package/dist/src/agent/tools/session-search-tool.js +1 -1
  174. package/dist/src/agent/tools/shell.js +1 -1
  175. package/dist/src/agent/tools/skills-tools.js +37 -8
  176. package/dist/src/agent/tools/skills-tools.js.map +1 -1
  177. package/dist/src/agent/tools/tool-manual-tool.d.ts +6 -0
  178. package/dist/src/agent/tools/tool-manual-tool.js +34 -0
  179. package/dist/src/agent/tools/tool-manual-tool.js.map +1 -0
  180. package/dist/src/agent/tools/web-extract.js +2 -2
  181. package/dist/src/agent/tools/web.js +1 -1
  182. package/dist/src/agent/workflow/catalog.d.ts +7 -2
  183. package/dist/src/agent/workflow/catalog.js +66 -25
  184. package/dist/src/agent/workflow/catalog.js.map +1 -1
  185. package/dist/src/agent/workflow/subagent-runner.d.ts +3 -0
  186. package/dist/src/agent/workflow/subagent-runner.js +50 -4
  187. package/dist/src/agent/workflow/subagent-runner.js.map +1 -1
  188. package/dist/src/agent/workflow/types.d.ts +10 -0
  189. package/dist/src/auth/credentials.js +10 -5
  190. package/dist/src/auth/credentials.js.map +1 -1
  191. package/dist/src/browser/actions/extension-registry-bridge.js +1 -1
  192. package/dist/src/browser/actions/registry.js +2 -2
  193. package/dist/src/browser/cdp-local-launcher.js +1 -1
  194. package/dist/src/browser/index.js +3 -3
  195. package/dist/src/browser/providers/browser-ext-install.js +1 -1
  196. package/dist/src/browser/providers/cloakbrowser.js +1 -1
  197. package/dist/src/channels/catalog/channel-catalog-service.d.ts +11 -0
  198. package/dist/src/channels/catalog/channel-catalog-service.js +168 -0
  199. package/dist/src/channels/catalog/channel-catalog-service.js.map +1 -0
  200. package/dist/src/channels/catalog/channel-catalog-types.d.ts +22 -0
  201. package/dist/src/channels/catalog/channel-catalog-types.js +1 -0
  202. package/dist/src/channels/dock.d.ts +0 -7
  203. package/dist/src/channels/dock.js +1 -21
  204. package/dist/src/channels/index.d.ts +1 -3
  205. package/dist/src/channels/index.js +1 -5
  206. package/dist/src/channels/lifecycle-supervisor.d.ts +1 -0
  207. package/dist/src/channels/lifecycle-supervisor.js +11 -0
  208. package/dist/src/channels/lifecycle-supervisor.js.map +1 -1
  209. package/dist/src/channels/manager.d.ts +1 -0
  210. package/dist/src/channels/manager.js +3 -0
  211. package/dist/src/channels/manager.js.map +1 -1
  212. package/dist/src/channels/pairing/pairing-channel.d.ts +2 -3
  213. package/dist/src/channels/pairing/pairing-messages.js +1 -1
  214. package/dist/src/channels/pairing/pairing-messages.js.map +1 -1
  215. package/dist/src/channels/pairing/pairing-service.d.ts +1 -1
  216. package/dist/src/channels/pairing/pairing-service.js +8 -27
  217. package/dist/src/channels/pairing/pairing-service.js.map +1 -1
  218. package/dist/src/channels/plugin-types.d.ts +3 -1
  219. package/dist/src/channels/plugins/types.adapters.d.ts +55 -2
  220. package/dist/src/channels/telegram/index.js +1 -1
  221. package/dist/src/chat-commands/builtins/config.js +4 -4
  222. package/dist/src/chat-commands/builtins/config.js.map +1 -1
  223. package/dist/src/chat-commands/config-paths.js +1 -1
  224. package/dist/src/chat-commands/config-paths.js.map +1 -1
  225. package/dist/src/chat-commands/context.js +1 -1
  226. package/dist/src/chat-commands/context.js.map +1 -1
  227. package/dist/src/cli/bin.js +1 -1
  228. package/dist/src/cli/command-manifest.js +1 -1
  229. package/dist/src/cli/command-manifest.js.map +1 -1
  230. package/dist/src/cli/commands/agent.js +2 -2
  231. package/dist/src/cli/commands/agent.js.map +1 -1
  232. package/dist/src/cli/commands/agents.js +2 -4
  233. package/dist/src/cli/commands/agents.js.map +1 -1
  234. package/dist/src/cli/commands/auth.js +1 -1
  235. package/dist/src/cli/commands/browser-cli-helpers.js +1 -1
  236. package/dist/src/cli/commands/channels.d.ts +1 -5
  237. package/dist/src/cli/commands/channels.js +115 -281
  238. package/dist/src/cli/commands/channels.js.map +1 -1
  239. package/dist/src/cli/commands/config.js +2 -2
  240. package/dist/src/cli/commands/config.js.map +1 -1
  241. package/dist/src/cli/commands/doctor/checks/channel-config.js +16 -69
  242. package/dist/src/cli/commands/doctor/checks/channel-config.js.map +1 -1
  243. package/dist/src/cli/commands/doctor/checks/channel-pairing-pending.js +6 -4
  244. package/dist/src/cli/commands/doctor/checks/channel-pairing-pending.js.map +1 -1
  245. package/dist/src/cli/commands/doctor/checks/channel-plugins.js +2 -2
  246. package/dist/src/cli/commands/doctor/checks/channel-plugins.js.map +1 -1
  247. package/dist/src/cli/commands/doctor/checks/database-schema.js +1 -1
  248. package/dist/src/cli/commands/doctor/checks/provider-auth.js +13 -9
  249. package/dist/src/cli/commands/doctor/checks/provider-auth.js.map +1 -1
  250. package/dist/src/cli/commands/extension-dev.js +2 -1
  251. package/dist/src/cli/commands/extension-dev.js.map +1 -1
  252. package/dist/src/cli/commands/extension-marketplace.js +2 -1
  253. package/dist/src/cli/commands/extension-marketplace.js.map +1 -1
  254. package/dist/src/cli/commands/extension-pack.js +2 -1
  255. package/dist/src/cli/commands/extension-pack.js.map +1 -1
  256. package/dist/src/cli/commands/models.js +7 -4
  257. package/dist/src/cli/commands/models.js.map +1 -1
  258. package/dist/src/cli/commands/onboard/channels/index.js +1 -1
  259. package/dist/src/cli/commands/onboard/channels/index.js.map +1 -1
  260. package/dist/src/cli/commands/onboard/channels/registry.d.ts +2 -1
  261. package/dist/src/cli/commands/onboard/channels/registry.js +32 -8
  262. package/dist/src/cli/commands/onboard/channels/registry.js.map +1 -1
  263. package/dist/src/cli/commands/onboard/model.js +8 -5
  264. package/dist/src/cli/commands/onboard/model.js.map +1 -1
  265. package/dist/src/cli/commands/onboard.js +4 -6
  266. package/dist/src/cli/commands/onboard.js.map +1 -1
  267. package/dist/src/cli/commands/setup-shared/runner.d.ts +1 -1
  268. package/dist/src/cli/commands/setup-shared/runner.js.map +1 -1
  269. package/dist/src/cli/commands/setup-shared/types.d.ts +1 -1
  270. package/dist/src/cli/commands/setup-shared/types.js.map +1 -1
  271. package/dist/src/cli/commands/tui.js +13 -5
  272. package/dist/src/cli/commands/tui.js.map +1 -1
  273. package/dist/src/cli/extension-cli-register.js +1 -1
  274. package/dist/src/commands/agents.config.d.ts +3 -3
  275. package/dist/src/commands/agents.config.js +7 -7
  276. package/dist/src/commands/agents.config.js.map +1 -1
  277. package/dist/src/config/agent-profile.d.ts +1 -1
  278. package/dist/src/config/agent-profile.js +6 -2
  279. package/dist/src/config/agent-profile.js.map +1 -1
  280. package/dist/src/config/agent-typed-models.d.ts +2 -2
  281. package/dist/src/config/agent-typed-models.js +13 -2
  282. package/dist/src/config/agent-typed-models.js.map +1 -1
  283. package/dist/src/config/index.js +3 -3
  284. package/dist/src/config/integration.d.ts +1 -1
  285. package/dist/src/config/loader.d.ts +0 -1
  286. package/dist/src/config/loader.js +4 -9
  287. package/dist/src/config/loader.js.map +1 -1
  288. package/dist/src/config/models-json.d.ts +6 -6
  289. package/dist/src/config/rules.js +2 -12
  290. package/dist/src/config/rules.js.map +1 -1
  291. package/dist/src/config/schema.d.ts +74 -47
  292. package/dist/src/config/schema.js +28 -66
  293. package/dist/src/config/schema.js.map +1 -1
  294. package/dist/src/config/validate-channel-configs.d.ts +0 -3
  295. package/dist/src/config/validate-channel-configs.js +29 -10
  296. package/dist/src/config/validate-channel-configs.js.map +1 -1
  297. package/dist/src/cron/executor.js +1 -4
  298. package/dist/src/cron/executor.js.map +1 -1
  299. package/dist/src/extensions/activation-context.js +3 -1
  300. package/dist/src/extensions/activation-context.js.map +1 -1
  301. package/dist/src/extensions/activation-planner.js +12 -0
  302. package/dist/src/extensions/activation-planner.js.map +1 -1
  303. package/dist/src/extensions/api.d.ts +5 -1
  304. package/dist/src/extensions/api.js +12 -0
  305. package/dist/src/extensions/api.js.map +1 -1
  306. package/dist/src/extensions/discover-extensions.js +17 -13
  307. package/dist/src/extensions/discover-extensions.js.map +1 -1
  308. package/dist/src/extensions/extension-metadata-snapshot.js +11 -5
  309. package/dist/src/extensions/extension-metadata-snapshot.js.map +1 -1
  310. package/dist/src/extensions/index.js +12 -4
  311. package/dist/src/extensions/index.js.map +1 -0
  312. package/dist/src/extensions/loader.d.ts +5 -1
  313. package/dist/src/extensions/loader.js +12 -11
  314. package/dist/src/extensions/loader.js.map +1 -1
  315. package/dist/src/extensions/manifest-registry.js +98 -93
  316. package/dist/src/extensions/manifest-registry.js.map +1 -1
  317. package/dist/src/extensions/normalize-manifest.js +91 -15
  318. package/dist/src/extensions/normalize-manifest.js.map +1 -1
  319. package/dist/src/extensions/sdk/index.js +1 -1
  320. package/dist/src/extensions/sdk/testing.js +4 -0
  321. package/dist/src/extensions/sdk/testing.js.map +1 -1
  322. package/dist/src/extensions/types/core.d.ts +32 -1
  323. package/dist/src/extensions/types/manifest.d.ts +60 -0
  324. package/dist/src/extensions/types/tui.d.ts +414 -5
  325. package/dist/src/gateway/agent-builtin-tools.d.ts +1 -1
  326. package/dist/src/gateway/agent-builtin-tools.js +16 -0
  327. package/dist/src/gateway/agent-builtin-tools.js.map +1 -1
  328. package/dist/src/gateway/agent-run-relay.d.ts +2 -3
  329. package/dist/src/gateway/agent-run-relay.js +10 -3
  330. package/dist/src/gateway/agent-run-relay.js.map +1 -1
  331. package/dist/src/gateway/agents-admin.d.ts +32 -19
  332. package/dist/src/gateway/agents-admin.js +113 -93
  333. package/dist/src/gateway/agents-admin.js.map +1 -1
  334. package/dist/src/gateway/chat-stream/mapper.d.ts +34 -0
  335. package/dist/src/gateway/chat-stream/mapper.js +244 -0
  336. package/dist/src/gateway/chat-stream/mapper.js.map +1 -0
  337. package/dist/src/gateway/chat-stream/protocol.d.ts +100 -0
  338. package/dist/src/gateway/chat-stream/protocol.js +1 -0
  339. package/dist/src/gateway/heartbeat/service.js +1 -1
  340. package/dist/src/gateway/hono/lib/agent-model.d.ts +4 -4
  341. package/dist/src/gateway/hono/lib/agent-model.js +13 -11
  342. package/dist/src/gateway/hono/lib/agent-model.js.map +1 -1
  343. package/dist/src/gateway/hono/lib/config-payload.d.ts +19 -7
  344. package/dist/src/gateway/hono/lib/config-payload.js +16 -15
  345. package/dist/src/gateway/hono/lib/config-payload.js.map +1 -1
  346. package/dist/src/gateway/hono/routes/agents.js +83 -48
  347. package/dist/src/gateway/hono/routes/agents.js.map +1 -1
  348. package/dist/src/gateway/hono/routes/channels.js +134 -214
  349. package/dist/src/gateway/hono/routes/channels.js.map +1 -1
  350. package/dist/src/gateway/hono/routes/commands-skills.js +10 -4
  351. package/dist/src/gateway/hono/routes/commands-skills.js.map +1 -1
  352. package/dist/src/gateway/hono/routes/config-patch/agents.js +26 -13
  353. package/dist/src/gateway/hono/routes/config-patch/agents.js.map +1 -1
  354. package/dist/src/gateway/hono/routes/config-patch/channels.d.ts +1 -11
  355. package/dist/src/gateway/hono/routes/config-patch/channels.js +18 -165
  356. package/dist/src/gateway/hono/routes/config-patch/channels.js.map +1 -1
  357. package/dist/src/gateway/hono/routes/config.js +5 -2
  358. package/dist/src/gateway/hono/routes/config.js.map +1 -1
  359. package/dist/src/gateway/hono/routes/dreaming.js +1 -1
  360. package/dist/src/gateway/hono/routes/lazy-bundles.js +13 -1
  361. package/dist/src/gateway/hono/routes/lazy-bundles.js.map +1 -1
  362. package/dist/src/gateway/hono/routes/public-gateway.js +2 -4
  363. package/dist/src/gateway/hono/routes/public-gateway.js.map +1 -1
  364. package/dist/src/gateway/hono/routes/sessions.js +179 -0
  365. package/dist/src/gateway/hono/routes/sessions.js.map +1 -1
  366. package/dist/src/gateway/hono/routes/tui.d.ts +3 -0
  367. package/dist/src/gateway/hono/routes/tui.js +16 -0
  368. package/dist/src/gateway/hono/routes/tui.js.map +1 -0
  369. package/dist/src/gateway/hono/routes/workflows.js +25 -1
  370. package/dist/src/gateway/hono/routes/workflows.js.map +1 -1
  371. package/dist/src/gateway/hono/sse.d.ts +5 -7
  372. package/dist/src/gateway/hono/sse.js +21 -38
  373. package/dist/src/gateway/hono/sse.js.map +1 -1
  374. package/dist/src/gateway/protocol.js.map +1 -1
  375. package/dist/src/gateway/service/agent-runner.d.ts +2 -4
  376. package/dist/src/gateway/service/agent-runner.js +1 -1
  377. package/dist/src/gateway/service/agent-runner.js.map +1 -1
  378. package/dist/src/gateway/service/marketplace-service.d.ts +4 -3
  379. package/dist/src/gateway/service/marketplace-service.js +7 -4
  380. package/dist/src/gateway/service/marketplace-service.js.map +1 -1
  381. package/dist/src/gateway/service/run-gateway-agent.d.ts +2 -6
  382. package/dist/src/gateway/service/run-gateway-agent.js +63 -36
  383. package/dist/src/gateway/service/run-gateway-agent.js.map +1 -1
  384. package/dist/src/gateway/service/sessions-api.d.ts +19 -0
  385. package/dist/src/gateway/service/sessions-api.js +12 -0
  386. package/dist/src/gateway/service/sessions-api.js.map +1 -1
  387. package/dist/src/gateway/service.d.ts +6 -0
  388. package/dist/src/gateway/service.js +73 -57
  389. package/dist/src/gateway/service.js.map +1 -1
  390. package/dist/src/heartbeat/index.js +1 -1
  391. package/dist/src/mcp/channel-bridge.js +1 -1
  392. package/dist/src/project-trust/trust-store.d.ts +30 -0
  393. package/dist/src/project-trust/trust-store.js +194 -0
  394. package/dist/src/project-trust/trust-store.js.map +1 -0
  395. package/dist/src/providers/index.d.ts +1 -1
  396. package/dist/src/providers/index.js +18 -7
  397. package/dist/src/providers/index.js.map +1 -1
  398. package/dist/src/routing/resolve-route.d.ts +0 -3
  399. package/dist/src/routing/resolve-route.js.map +1 -1
  400. package/dist/src/routing/resolve-tui-session-key.d.ts +2 -0
  401. package/dist/src/routing/resolve-tui-session-key.js +8 -3
  402. package/dist/src/routing/resolve-tui-session-key.js.map +1 -1
  403. package/dist/src/session/client-history.d.ts +32 -0
  404. package/dist/src/session/client-history.js +232 -1
  405. package/dist/src/session/client-history.js.map +1 -1
  406. package/dist/src/session/manager.d.ts +37 -4
  407. package/dist/src/session/manager.js +39 -15
  408. package/dist/src/session/manager.js.map +1 -1
  409. package/dist/src/session/session-context-for-llm.d.ts +93 -1
  410. package/dist/src/session/session-context-for-llm.js +105 -2
  411. package/dist/src/session/session-context-for-llm.js.map +1 -1
  412. package/dist/src/session/store.d.ts +37 -0
  413. package/dist/src/session/store.js +127 -2
  414. package/dist/src/session/store.js.map +1 -1
  415. package/dist/src/session/stored-rows-to-file-entries.js +37 -1
  416. package/dist/src/session/stored-rows-to-file-entries.js.map +1 -1
  417. package/dist/src/session/types.d.ts +14 -1
  418. package/dist/src/session/types.js.map +1 -1
  419. package/dist/src/share/share-thumbnail.js +1 -1
  420. package/dist/src/storage/sqlite/migrations/004_add_session_type_metadata.sql +15 -0
  421. package/dist/src/storage/sqlite/migrations/runner.d.ts +1 -1
  422. package/dist/src/storage/sqlite/migrations/runner.js +3 -3
  423. package/dist/src/storage/sqlite/migrations/runner.js.map +1 -1
  424. package/dist/src/storage/sqlite/migrations/runner.ts +1 -1
  425. package/dist/src/storage/sqlite/row-mappers.d.ts +14 -1
  426. package/dist/src/storage/sqlite/row-mappers.js +14 -1
  427. package/dist/src/storage/sqlite/row-mappers.js.map +1 -1
  428. package/dist/src/storage/sqlite/schema.js +1 -1
  429. package/dist/src/storage/sqlite/session-metadata.js +1 -0
  430. package/dist/src/storage/sqlite/session-metadata.js.map +1 -1
  431. package/dist/src/storage/sqlite/session-repository.js +52 -25
  432. package/dist/src/storage/sqlite/session-repository.js.map +1 -1
  433. package/dist/src/tui/backends/embedded-backend.d.ts +53 -4
  434. package/dist/src/tui/backends/embedded-backend.js +227 -39
  435. package/dist/src/tui/backends/embedded-backend.js.map +1 -1
  436. package/dist/src/tui/backends/gateway-sse-backend.d.ts +59 -3
  437. package/dist/src/tui/backends/gateway-sse-backend.js +416 -26
  438. package/dist/src/tui/backends/gateway-sse-backend.js.map +1 -1
  439. package/dist/src/tui/chat-history.d.ts +5 -1
  440. package/dist/src/tui/chat-history.js +78 -8
  441. package/dist/src/tui/chat-history.js.map +1 -1
  442. package/dist/src/tui/clipboard-text.d.ts +5 -0
  443. package/dist/src/tui/clipboard-text.js +46 -0
  444. package/dist/src/tui/clipboard-text.js.map +1 -0
  445. package/dist/src/tui/components/assistant-message.d.ts +19 -3
  446. package/dist/src/tui/components/assistant-message.js +115 -9
  447. package/dist/src/tui/components/assistant-message.js.map +1 -1
  448. package/dist/src/tui/components/bash-execution.d.ts +3 -2
  449. package/dist/src/tui/components/bash-execution.js +31 -3
  450. package/dist/src/tui/components/bash-execution.js.map +1 -1
  451. package/dist/src/tui/components/bash-summary.d.ts +23 -0
  452. package/dist/src/tui/components/bash-summary.js +87 -0
  453. package/dist/src/tui/components/bash-summary.js.map +1 -0
  454. package/dist/src/tui/components/branch-message-summary.d.ts +17 -0
  455. package/dist/src/tui/components/branch-message-summary.js +43 -0
  456. package/dist/src/tui/components/branch-message-summary.js.map +1 -0
  457. package/dist/src/tui/components/branch-summary.d.ts +13 -0
  458. package/dist/src/tui/components/branch-summary.js +51 -0
  459. package/dist/src/tui/components/branch-summary.js.map +1 -0
  460. package/dist/src/tui/components/chat-log.d.ts +46 -6
  461. package/dist/src/tui/components/chat-log.js +183 -21
  462. package/dist/src/tui/components/chat-log.js.map +1 -1
  463. package/dist/src/tui/components/compaction-summary.d.ts +13 -0
  464. package/dist/src/tui/components/compaction-summary.js +46 -0
  465. package/dist/src/tui/components/compaction-summary.js.map +1 -0
  466. package/dist/src/tui/components/custom-editor.d.ts +1 -0
  467. package/dist/src/tui/components/custom-editor.js +2 -0
  468. package/dist/src/tui/components/custom-editor.js.map +1 -1
  469. package/dist/src/tui/components/custom-message.d.ts +23 -0
  470. package/dist/src/tui/components/custom-message.js +65 -0
  471. package/dist/src/tui/components/custom-message.js.map +1 -0
  472. package/dist/src/tui/components/extension-dialog.d.ts +42 -0
  473. package/dist/src/tui/components/extension-dialog.js +127 -0
  474. package/dist/src/tui/components/extension-dialog.js.map +1 -0
  475. package/dist/src/tui/components/scoped-models-selector.d.ts +7 -2
  476. package/dist/src/tui/components/scoped-models-selector.js +89 -16
  477. package/dist/src/tui/components/scoped-models-selector.js.map +1 -1
  478. package/dist/src/tui/components/searchable-select-list.d.ts +30 -3
  479. package/dist/src/tui/components/searchable-select-list.js +82 -10
  480. package/dist/src/tui/components/searchable-select-list.js.map +1 -1
  481. package/dist/src/tui/components/session-selector.d.ts +18 -4
  482. package/dist/src/tui/components/session-selector.js +207 -40
  483. package/dist/src/tui/components/session-selector.js.map +1 -1
  484. package/dist/src/tui/components/settings-selector.d.ts +6 -2
  485. package/dist/src/tui/components/settings-selector.js +126 -7
  486. package/dist/src/tui/components/settings-selector.js.map +1 -1
  487. package/dist/src/tui/components/thinking-selector.d.ts +12 -0
  488. package/dist/src/tui/components/thinking-selector.js +48 -0
  489. package/dist/src/tui/components/thinking-selector.js.map +1 -0
  490. package/dist/src/tui/components/tool-execution.d.ts +57 -3
  491. package/dist/src/tui/components/tool-execution.js +378 -28
  492. package/dist/src/tui/components/tool-execution.js.map +1 -1
  493. package/dist/src/tui/components/tui-bottom-bar.d.ts +9 -1
  494. package/dist/src/tui/components/tui-bottom-bar.js +56 -11
  495. package/dist/src/tui/components/tui-bottom-bar.js.map +1 -1
  496. package/dist/src/tui/components/tui-header.d.ts +9 -2
  497. package/dist/src/tui/components/tui-header.js +25 -5
  498. package/dist/src/tui/components/tui-header.js.map +1 -1
  499. package/dist/src/tui/components/user-message.d.ts +4 -2
  500. package/dist/src/tui/components/user-message.js +42 -9
  501. package/dist/src/tui/components/user-message.js.map +1 -1
  502. package/dist/src/tui/components/visual-truncate.d.ts +11 -0
  503. package/dist/src/tui/components/visual-truncate.js +27 -0
  504. package/dist/src/tui/components/visual-truncate.js.map +1 -0
  505. package/dist/src/tui/extension-host/autocomplete.d.ts +43 -0
  506. package/dist/src/tui/extension-host/autocomplete.js +116 -0
  507. package/dist/src/tui/extension-host/autocomplete.js.map +1 -0
  508. package/dist/src/tui/extension-host/host.d.ts +31 -1
  509. package/dist/src/tui/extension-host/host.js +123 -6
  510. package/dist/src/tui/extension-host/host.js.map +1 -1
  511. package/dist/src/tui/extension-host/load-extensions.d.ts +6 -1
  512. package/dist/src/tui/extension-host/load-extensions.js +4 -3
  513. package/dist/src/tui/extension-host/load-extensions.js.map +1 -1
  514. package/dist/src/tui/extension-host/runtime-context.d.ts +21 -0
  515. package/dist/src/tui/extension-host/runtime-context.js +152 -0
  516. package/dist/src/tui/extension-host/runtime-context.js.map +1 -0
  517. package/dist/src/tui/extension-host/runtime.d.ts +52 -4
  518. package/dist/src/tui/extension-host/runtime.js +547 -85
  519. package/dist/src/tui/extension-host/runtime.js.map +1 -1
  520. package/dist/src/tui/extension-host/surface.d.ts +20 -0
  521. package/dist/src/tui/extension-host/surface.js +30 -6
  522. package/dist/src/tui/extension-host/surface.js.map +1 -1
  523. package/dist/src/tui/extension-host/tool-renderers.d.ts +6 -3
  524. package/dist/src/tui/extension-host/tool-renderers.js +43 -5
  525. package/dist/src/tui/extension-host/tool-renderers.js.map +1 -1
  526. package/dist/src/tui/format-tui-hotkeys.d.ts +12 -2
  527. package/dist/src/tui/format-tui-hotkeys.js +22 -5
  528. package/dist/src/tui/format-tui-hotkeys.js.map +1 -1
  529. package/dist/src/tui/tui-agent-events.d.ts +8 -6
  530. package/dist/src/tui/tui-agent-events.js +200 -59
  531. package/dist/src/tui/tui-agent-events.js.map +1 -1
  532. package/dist/src/tui/tui-backend.d.ts +169 -3
  533. package/dist/src/tui/tui-command-formatters.d.ts +76 -0
  534. package/dist/src/tui/tui-command-formatters.js +594 -0
  535. package/dist/src/tui/tui-command-formatters.js.map +1 -0
  536. package/dist/src/tui/tui-commands.d.ts +57 -7
  537. package/dist/src/tui/tui-commands.js +639 -43
  538. package/dist/src/tui/tui-commands.js.map +1 -1
  539. package/dist/src/tui/tui-context-usage.d.ts +1 -1
  540. package/dist/src/tui/tui-context-usage.js +9 -1
  541. package/dist/src/tui/tui-context-usage.js.map +1 -1
  542. package/dist/src/tui/tui-extension-user-message.d.ts +8 -0
  543. package/dist/src/tui/tui-extension-user-message.js +32 -0
  544. package/dist/src/tui/tui-extension-user-message.js.map +1 -0
  545. package/dist/src/tui/tui-follow-up-queue.d.ts +9 -0
  546. package/dist/src/tui/tui-follow-up-queue.js +18 -0
  547. package/dist/src/tui/tui-follow-up-queue.js.map +1 -0
  548. package/dist/src/tui/tui-local-shell.d.ts +11 -1
  549. package/dist/src/tui/tui-local-shell.js +50 -8
  550. package/dist/src/tui/tui-local-shell.js.map +1 -1
  551. package/dist/src/tui/tui-model-picker.d.ts +26 -0
  552. package/dist/src/tui/tui-model-picker.js +152 -0
  553. package/dist/src/tui/tui-model-picker.js.map +1 -0
  554. package/dist/src/tui/tui-oauth-login.d.ts +16 -0
  555. package/dist/src/tui/tui-oauth-login.js +189 -0
  556. package/dist/src/tui/tui-oauth-login.js.map +1 -0
  557. package/dist/src/tui/tui-overlays.d.ts +3 -3
  558. package/dist/src/tui/tui-overlays.js +6 -7
  559. package/dist/src/tui/tui-overlays.js.map +1 -1
  560. package/dist/src/tui/tui-picker-overlay.d.ts +27 -32
  561. package/dist/src/tui/tui-picker-overlay.js +340 -30
  562. package/dist/src/tui/tui-picker-overlay.js.map +1 -1
  563. package/dist/src/tui/tui-picker-services.d.ts +41 -0
  564. package/dist/src/tui/tui-picker-services.js +1 -0
  565. package/dist/src/tui/tui-run-state.d.ts +11 -0
  566. package/dist/src/tui/tui-run-state.js +114 -0
  567. package/dist/src/tui/tui-run-state.js.map +1 -0
  568. package/dist/src/tui/tui-runtime-hints.d.ts +4 -0
  569. package/dist/src/tui/tui-runtime-hints.js +18 -0
  570. package/dist/src/tui/tui-runtime-hints.js.map +1 -0
  571. package/dist/src/tui/tui-scoped-models.d.ts +1 -1
  572. package/dist/src/tui/tui-scoped-models.js +2 -2
  573. package/dist/src/tui/tui-scoped-models.js.map +1 -1
  574. package/dist/src/tui/tui-session-actions.d.ts +5 -3
  575. package/dist/src/tui/tui-session-actions.js +21 -9
  576. package/dist/src/tui/tui-session-actions.js.map +1 -1
  577. package/dist/src/tui/tui-session-format.d.ts +4 -1
  578. package/dist/src/tui/tui-session-format.js +17 -3
  579. package/dist/src/tui/tui-session-format.js.map +1 -1
  580. package/dist/src/tui/tui-session-snapshot.d.ts +82 -0
  581. package/dist/src/tui/tui-session-snapshot.js +184 -0
  582. package/dist/src/tui/tui-session-snapshot.js.map +1 -0
  583. package/dist/src/tui/tui-session-stats.d.ts +3 -0
  584. package/dist/src/tui/tui-session-stats.js +59 -0
  585. package/dist/src/tui/tui-session-stats.js.map +1 -0
  586. package/dist/src/tui/tui-settings.d.ts +21 -0
  587. package/dist/src/tui/tui-settings.js +28 -1
  588. package/dist/src/tui/tui-settings.js.map +1 -1
  589. package/dist/src/tui/tui-skills-autocomplete.js +1 -1
  590. package/dist/src/tui/tui-skills-autocomplete.js.map +1 -1
  591. package/dist/src/tui/tui-startup-resources.d.ts +3 -0
  592. package/dist/src/tui/tui-startup-resources.js +39 -0
  593. package/dist/src/tui/tui-startup-resources.js.map +1 -0
  594. package/dist/src/tui/tui-startup-text.d.ts +10 -0
  595. package/dist/src/tui/tui-startup-text.js +58 -0
  596. package/dist/src/tui/tui-startup-text.js.map +1 -0
  597. package/dist/src/tui/tui-stdio-filter.d.ts +1 -0
  598. package/dist/src/tui/tui-stdio-filter.js +11 -7
  599. package/dist/src/tui/tui-stdio-filter.js.map +1 -1
  600. package/dist/src/tui/tui-submit.d.ts +2 -0
  601. package/dist/src/tui/tui-submit.js +2 -1
  602. package/dist/src/tui/tui-submit.js.map +1 -1
  603. package/dist/src/tui/tui-tool-diff.js +61 -7
  604. package/dist/src/tui/tui-tool-diff.js.map +1 -1
  605. package/dist/src/tui/tui-tool-result.d.ts +17 -0
  606. package/dist/src/tui/tui-tool-result.js +74 -0
  607. package/dist/src/tui/tui-tool-result.js.map +1 -0
  608. package/dist/src/tui/tui-transcript-tree-picker.d.ts +57 -0
  609. package/dist/src/tui/tui-transcript-tree-picker.js +604 -0
  610. package/dist/src/tui/tui-transcript-tree-picker.js.map +1 -0
  611. package/dist/src/tui/tui-transcript-tree.d.ts +7 -0
  612. package/dist/src/tui/tui-transcript-tree.js +316 -0
  613. package/dist/src/tui/tui-transcript-tree.js.map +1 -0
  614. package/dist/src/tui/tui-types.d.ts +25 -34
  615. package/dist/src/tui/tui-types.js +12 -0
  616. package/dist/src/tui/tui-types.js.map +1 -1
  617. package/dist/src/tui/tui.js +1288 -112
  618. package/dist/src/tui/tui.js.map +1 -1
  619. package/dist/src/tui/xopc-tui-keybindings.d.ts +127 -2
  620. package/dist/src/tui/xopc-tui-keybindings.js +127 -2
  621. package/dist/src/tui/xopc-tui-keybindings.js.map +1 -1
  622. package/dist/src/workflows/domain/definition-utils.d.ts +2 -1
  623. package/dist/src/workflows/domain/definition-utils.js +18 -8
  624. package/dist/src/workflows/domain/definition-utils.js.map +1 -1
  625. package/dist/src/workflows/domain/definition.d.ts +25 -0
  626. package/dist/src/workflows/domain/event.d.ts +1 -0
  627. package/dist/src/workflows/domain/result.d.ts +15 -0
  628. package/dist/src/workflows/domain/run.d.ts +2 -0
  629. package/dist/src/workflows/domain/run.js.map +1 -1
  630. package/dist/src/workflows/engine/projector.js +4 -0
  631. package/dist/src/workflows/engine/projector.js.map +1 -1
  632. package/dist/src/workflows/engine/workflow-engine.d.ts +37 -1
  633. package/dist/src/workflows/engine/workflow-engine.js +75 -11
  634. package/dist/src/workflows/engine/workflow-engine.js.map +1 -1
  635. package/dist/src/workflows/index.d.ts +1 -0
  636. package/dist/src/workflows/index.js +4 -1
  637. package/dist/src/workflows/registry/catalog-workflow-definition-registry.d.ts +9 -0
  638. package/dist/src/workflows/registry/catalog-workflow-definition-registry.js +40 -0
  639. package/dist/src/workflows/registry/catalog-workflow-definition-registry.js.map +1 -0
  640. package/dist/src/workflows/registry/index.d.ts +2 -0
  641. package/dist/src/workflows/registry/index.js +2 -0
  642. package/dist/src/workflows/registry/workflow-definition-registry.d.ts +15 -0
  643. package/dist/src/workflows/registry/workflow-definition-registry.js +1 -0
  644. package/dist/src/workflows/runtime/index.d.ts +2 -0
  645. package/dist/src/workflows/runtime/index.js +2 -1
  646. package/dist/src/workflows/runtime/script-workflow-runtime.d.ts +5 -0
  647. package/dist/src/workflows/runtime/script-workflow-runtime.js +15 -0
  648. package/dist/src/workflows/runtime/script-workflow-runtime.js.map +1 -0
  649. package/dist/src/workflows/runtime/workflow-runtime-port.d.ts +16 -0
  650. package/dist/src/workflows/runtime/workflow-runtime-port.js +1 -0
  651. package/dist/src/workflows/service/run-view-to-snapshot.js +3 -0
  652. package/dist/src/workflows/service/run-view-to-snapshot.js.map +1 -1
  653. package/dist/src/workflows/service/workflow-run-service.d.ts +3 -0
  654. package/dist/src/workflows/service/workflow-run-service.js +10 -15
  655. package/dist/src/workflows/service/workflow-run-service.js.map +1 -1
  656. package/dist/src/workflows/service/workflow-session-bridge.d.ts +1 -1
  657. package/dist/src/workflows/service/workflow-session-bridge.js +4 -1
  658. package/dist/src/workflows/service/workflow-session-bridge.js.map +1 -1
  659. package/package.json +21 -15
  660. package/skills/creative/frontend-design/SKILL.md +1 -1
  661. package/skills/creative/theme-factory/SKILL.md +1 -1
  662. package/skills/documents/xlsx/SKILL.md +1 -1
  663. package/skills/engineering/diagnose/SKILL.md +2 -2
  664. package/skills/engineering/tdd/SKILL.md +1 -1
  665. package/skills/tools/github/SKILL.md +6 -1
  666. package/skills/tools/webapp-testing/SKILL.md +4 -1
  667. package/dist/extensions/telegram/src/adapters/config-surface.d.ts +0 -2
  668. package/dist/extensions/telegram/src/adapters/config-surface.js +0 -26
  669. package/dist/extensions/telegram/src/adapters/config-surface.js.map +0 -1
  670. package/dist/extensions/weixin/src/__tests__/workflow-progress.test.js +0 -158
  671. package/dist/extensions/weixin/src/__tests__/workflow-progress.test.js.map +0 -1
  672. package/dist/gateway/static/root/assets/agents-BwXkia_W.js +0 -222
  673. package/dist/gateway/static/root/assets/channels-settings-tlOTdaXw.js +0 -1
  674. package/dist/gateway/static/root/assets/channels-status-swr-D4XjqwqC.js +0 -8
  675. package/dist/gateway/static/root/assets/cron-api-DcmfGuj0.js +0 -1
  676. package/dist/gateway/static/root/assets/cron-page-CijJ4G6F.js +0 -1
  677. package/dist/gateway/static/root/assets/extension-settings-page-CyJk_G64.js +0 -1
  678. package/dist/gateway/static/root/assets/field-primitives-C4GpxsDo.js +0 -1
  679. package/dist/gateway/static/root/assets/heartbeat-config-api-CLD0Gpi3.js +0 -1
  680. package/dist/gateway/static/root/assets/index-0HmunJW9.js +0 -4845
  681. package/dist/gateway/static/root/assets/index-Bk75Phrd.css +0 -1
  682. package/dist/gateway/static/root/assets/notes-page-BBnTh0uI.js +0 -1
  683. package/dist/gateway/static/root/assets/sessions-page-B0riYK7j.js +0 -1
  684. package/dist/gateway/static/root/assets/settings-advanced-gate-DiP_WHu_.js +0 -2
  685. package/dist/gateway/static/root/assets/settings-page-1ZPhcCZ9.js +0 -3
  686. package/dist/gateway/static/root/assets/skills-page-BQ1hllKD.js +0 -2
  687. package/dist/gateway/static/root/assets/url-F3_D_6zZ.js +0 -3
  688. package/dist/gateway/static/root/assets/utils-CPr3FBh2.js +0 -1
  689. package/dist/gateway/static/root/assets/voice-api-key-field-BkbDl6dH.js +0 -1
  690. package/dist/gateway/static/root/assets/workflows-page-D059ysoF.js +0 -27
  691. package/dist/src/agent/embedded/map-stream-events.d.ts +0 -9
  692. package/dist/src/agent/embedded/map-stream-events.js +0 -63
  693. package/dist/src/agent/embedded/map-stream-events.js.map +0 -1
  694. package/dist/src/channels/dock.js.map +0 -1
  695. package/dist/src/channels/plugins/bundled.d.ts +0 -11
  696. package/dist/src/channels/plugins/bundled.js +0 -10
  697. package/dist/src/channels/plugins/bundled.js.map +0 -1
  698. package/dist/src/channels/registry.d.ts +0 -25
  699. package/dist/src/channels/registry.js +0 -82
  700. package/dist/src/channels/registry.js.map +0 -1
  701. package/dist/src/config/localized-text.d.ts +0 -6
  702. package/dist/src/config/localized-text.js +0 -42
  703. package/dist/src/config/localized-text.js.map +0 -1
  704. package/dist/src/generated/bundled-channel-plugins.d.ts +0 -10
  705. package/dist/src/generated/bundled-channel-plugins.js +0 -16
  706. package/dist/src/generated/bundled-channel-plugins.js.map +0 -1
  707. package/dist/src/tui/stream-assembler.d.ts +0 -22
  708. package/dist/src/tui/stream-assembler.js +0 -63
  709. package/dist/src/tui/stream-assembler.js.map +0 -1
  710. package/skills/browser/SKILL-zh.md +0 -188
  711. package/skills/business/company-values/SKILL-zh.md +0 -80
  712. package/skills/business/company-values/SKILL.md +0 -80
  713. package/skills/business/find-community/SKILL-zh.md +0 -50
  714. package/skills/business/find-community/SKILL.md +0 -50
  715. package/skills/business/first-customers/SKILL-zh.md +0 -76
  716. package/skills/business/first-customers/SKILL.md +0 -76
  717. package/skills/business/grow-sustainably/SKILL-zh.md +0 -92
  718. package/skills/business/grow-sustainably/SKILL.md +0 -92
  719. package/skills/business/marketing-plan/SKILL-zh.md +0 -100
  720. package/skills/business/marketing-plan/SKILL.md +0 -100
  721. package/skills/business/minimalist-review/SKILL-zh.md +0 -82
  722. package/skills/business/minimalist-review/SKILL.md +0 -82
  723. package/skills/business/mvp/SKILL-zh.md +0 -81
  724. package/skills/business/mvp/SKILL.md +0 -81
  725. package/skills/business/pricing/SKILL-zh.md +0 -64
  726. package/skills/business/pricing/SKILL.md +0 -64
  727. package/skills/business/processize/SKILL-zh.md +0 -91
  728. package/skills/business/processize/SKILL.md +0 -91
  729. package/skills/business/validate-idea/SKILL-zh.md +0 -68
  730. package/skills/business/validate-idea/SKILL.md +0 -68
  731. package/skills/creative/algorithmic-art/LICENSE.txt +0 -202
  732. package/skills/creative/algorithmic-art/SKILL-zh.md +0 -405
  733. package/skills/creative/algorithmic-art/SKILL.md +0 -405
  734. package/skills/creative/algorithmic-art/templates/generator_template.js +0 -223
  735. package/skills/creative/algorithmic-art/templates/viewer.html +0 -599
  736. package/skills/creative/frontend-design/SKILL-zh.md +0 -42
  737. package/skills/creative/theme-factory/SKILL-zh.md +0 -59
  738. package/skills/creative/web-artifacts-builder/LICENSE.txt +0 -202
  739. package/skills/creative/web-artifacts-builder/SKILL-zh.md +0 -74
  740. package/skills/creative/web-artifacts-builder/SKILL.md +0 -74
  741. package/skills/creative/web-artifacts-builder/scripts/bundle-artifact.sh +0 -54
  742. package/skills/creative/web-artifacts-builder/scripts/init-artifact.sh +0 -322
  743. package/skills/creative/web-artifacts-builder/scripts/shadcn-components.tar.gz +0 -0
  744. package/skills/documents/doc-coauthoring/SKILL-zh.md +0 -375
  745. package/skills/documents/doc-coauthoring/SKILL.md +0 -375
  746. package/skills/documents/docx/LICENSE.txt +0 -30
  747. package/skills/documents/docx/SKILL-zh.md +0 -590
  748. package/skills/documents/docx/SKILL.md +0 -590
  749. package/skills/documents/docx/scripts/__init__.py +0 -1
  750. package/skills/documents/docx/scripts/accept_changes.py +0 -135
  751. package/skills/documents/docx/scripts/comment.py +0 -318
  752. package/skills/documents/docx/scripts/office/helpers/__init__.py +0 -0
  753. package/skills/documents/docx/scripts/office/helpers/merge_runs.py +0 -199
  754. package/skills/documents/docx/scripts/office/helpers/simplify_redlines.py +0 -197
  755. package/skills/documents/docx/scripts/office/pack.py +0 -159
  756. package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +0 -1499
  757. package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +0 -146
  758. package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +0 -1085
  759. package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +0 -11
  760. package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-main.xsd +0 -3081
  761. package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +0 -23
  762. package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +0 -185
  763. package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +0 -287
  764. package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/pml.xsd +0 -1676
  765. package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +0 -28
  766. package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +0 -144
  767. package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +0 -174
  768. package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +0 -25
  769. package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +0 -18
  770. package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +0 -59
  771. package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +0 -56
  772. package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +0 -195
  773. package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-math.xsd +0 -582
  774. package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +0 -25
  775. package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/sml.xsd +0 -4439
  776. package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-main.xsd +0 -570
  777. package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +0 -509
  778. package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +0 -12
  779. package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +0 -108
  780. package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +0 -96
  781. package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/wml.xsd +0 -3646
  782. package/skills/documents/docx/scripts/office/schemas/ISO-IEC29500-4_2016/xml.xsd +0 -116
  783. package/skills/documents/docx/scripts/office/schemas/ecma/fouth-edition/opc-contentTypes.xsd +0 -42
  784. package/skills/documents/docx/scripts/office/schemas/ecma/fouth-edition/opc-coreProperties.xsd +0 -50
  785. package/skills/documents/docx/scripts/office/schemas/ecma/fouth-edition/opc-digSig.xsd +0 -49
  786. package/skills/documents/docx/scripts/office/schemas/ecma/fouth-edition/opc-relationships.xsd +0 -33
  787. package/skills/documents/docx/scripts/office/schemas/mce/mc.xsd +0 -75
  788. package/skills/documents/docx/scripts/office/schemas/microsoft/wml-2010.xsd +0 -560
  789. package/skills/documents/docx/scripts/office/schemas/microsoft/wml-2012.xsd +0 -67
  790. package/skills/documents/docx/scripts/office/schemas/microsoft/wml-2018.xsd +0 -14
  791. package/skills/documents/docx/scripts/office/schemas/microsoft/wml-cex-2018.xsd +0 -20
  792. package/skills/documents/docx/scripts/office/schemas/microsoft/wml-cid-2016.xsd +0 -13
  793. package/skills/documents/docx/scripts/office/schemas/microsoft/wml-sdtdatahash-2020.xsd +0 -4
  794. package/skills/documents/docx/scripts/office/schemas/microsoft/wml-symex-2015.xsd +0 -8
  795. package/skills/documents/docx/scripts/office/soffice.py +0 -183
  796. package/skills/documents/docx/scripts/office/unpack.py +0 -132
  797. package/skills/documents/docx/scripts/office/validate.py +0 -111
  798. package/skills/documents/docx/scripts/office/validators/__init__.py +0 -15
  799. package/skills/documents/docx/scripts/office/validators/base.py +0 -847
  800. package/skills/documents/docx/scripts/office/validators/docx.py +0 -446
  801. package/skills/documents/docx/scripts/office/validators/pptx.py +0 -275
  802. package/skills/documents/docx/scripts/office/validators/redlining.py +0 -247
  803. package/skills/documents/docx/scripts/templates/comments.xml +0 -3
  804. package/skills/documents/docx/scripts/templates/commentsExtended.xml +0 -3
  805. package/skills/documents/docx/scripts/templates/commentsExtensible.xml +0 -3
  806. package/skills/documents/docx/scripts/templates/commentsIds.xml +0 -3
  807. package/skills/documents/docx/scripts/templates/people.xml +0 -3
  808. package/skills/documents/pdf/LICENSE.txt +0 -30
  809. package/skills/documents/pdf/SKILL-zh.md +0 -314
  810. package/skills/documents/pdf/SKILL.md +0 -314
  811. package/skills/documents/pdf/forms.md +0 -294
  812. package/skills/documents/pdf/reference.md +0 -612
  813. package/skills/documents/pdf/scripts/check_bounding_boxes.py +0 -65
  814. package/skills/documents/pdf/scripts/check_fillable_fields.py +0 -11
  815. package/skills/documents/pdf/scripts/convert_pdf_to_images.py +0 -33
  816. package/skills/documents/pdf/scripts/create_validation_image.py +0 -37
  817. package/skills/documents/pdf/scripts/extract_form_field_info.py +0 -122
  818. package/skills/documents/pdf/scripts/extract_form_structure.py +0 -115
  819. package/skills/documents/pdf/scripts/fill_fillable_fields.py +0 -98
  820. package/skills/documents/pdf/scripts/fill_pdf_form_with_annotations.py +0 -107
  821. package/skills/documents/pptx/LICENSE.txt +0 -30
  822. package/skills/documents/pptx/SKILL-zh.md +0 -232
  823. package/skills/documents/pptx/SKILL.md +0 -232
  824. package/skills/documents/pptx/editing.md +0 -205
  825. package/skills/documents/pptx/pptxgenjs.md +0 -420
  826. package/skills/documents/pptx/scripts/__init__.py +0 -0
  827. package/skills/documents/pptx/scripts/add_slide.py +0 -195
  828. package/skills/documents/pptx/scripts/clean.py +0 -286
  829. package/skills/documents/pptx/scripts/office/helpers/__init__.py +0 -0
  830. package/skills/documents/pptx/scripts/office/helpers/merge_runs.py +0 -199
  831. package/skills/documents/pptx/scripts/office/helpers/simplify_redlines.py +0 -197
  832. package/skills/documents/pptx/scripts/office/pack.py +0 -159
  833. package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +0 -1499
  834. package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +0 -146
  835. package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +0 -1085
  836. package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +0 -11
  837. package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-main.xsd +0 -3081
  838. package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +0 -23
  839. package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +0 -185
  840. package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +0 -287
  841. package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/pml.xsd +0 -1676
  842. package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +0 -28
  843. package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +0 -144
  844. package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +0 -174
  845. package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +0 -25
  846. package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +0 -18
  847. package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +0 -59
  848. package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +0 -56
  849. package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +0 -195
  850. package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-math.xsd +0 -582
  851. package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +0 -25
  852. package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/sml.xsd +0 -4439
  853. package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-main.xsd +0 -570
  854. package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +0 -509
  855. package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +0 -12
  856. package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +0 -108
  857. package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +0 -96
  858. package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/wml.xsd +0 -3646
  859. package/skills/documents/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/xml.xsd +0 -116
  860. package/skills/documents/pptx/scripts/office/schemas/ecma/fouth-edition/opc-contentTypes.xsd +0 -42
  861. package/skills/documents/pptx/scripts/office/schemas/ecma/fouth-edition/opc-coreProperties.xsd +0 -50
  862. package/skills/documents/pptx/scripts/office/schemas/ecma/fouth-edition/opc-digSig.xsd +0 -49
  863. package/skills/documents/pptx/scripts/office/schemas/ecma/fouth-edition/opc-relationships.xsd +0 -33
  864. package/skills/documents/pptx/scripts/office/schemas/mce/mc.xsd +0 -75
  865. package/skills/documents/pptx/scripts/office/schemas/microsoft/wml-2010.xsd +0 -560
  866. package/skills/documents/pptx/scripts/office/schemas/microsoft/wml-2012.xsd +0 -67
  867. package/skills/documents/pptx/scripts/office/schemas/microsoft/wml-2018.xsd +0 -14
  868. package/skills/documents/pptx/scripts/office/schemas/microsoft/wml-cex-2018.xsd +0 -20
  869. package/skills/documents/pptx/scripts/office/schemas/microsoft/wml-cid-2016.xsd +0 -13
  870. package/skills/documents/pptx/scripts/office/schemas/microsoft/wml-sdtdatahash-2020.xsd +0 -4
  871. package/skills/documents/pptx/scripts/office/schemas/microsoft/wml-symex-2015.xsd +0 -8
  872. package/skills/documents/pptx/scripts/office/soffice.py +0 -183
  873. package/skills/documents/pptx/scripts/office/unpack.py +0 -132
  874. package/skills/documents/pptx/scripts/office/validate.py +0 -111
  875. package/skills/documents/pptx/scripts/office/validators/__init__.py +0 -15
  876. package/skills/documents/pptx/scripts/office/validators/base.py +0 -847
  877. package/skills/documents/pptx/scripts/office/validators/docx.py +0 -446
  878. package/skills/documents/pptx/scripts/office/validators/pptx.py +0 -275
  879. package/skills/documents/pptx/scripts/office/validators/redlining.py +0 -247
  880. package/skills/documents/pptx/scripts/thumbnail.py +0 -289
  881. package/skills/documents/xlsx/SKILL-zh.md +0 -292
  882. package/skills/engineering/diagnose/SKILL-zh.md +0 -117
  883. package/skills/engineering/grill-with-docs/ADR-FORMAT.md +0 -47
  884. package/skills/engineering/grill-with-docs/CONTEXT-FORMAT.md +0 -77
  885. package/skills/engineering/grill-with-docs/SKILL-zh.md +0 -88
  886. package/skills/engineering/grill-with-docs/SKILL.md +0 -88
  887. package/skills/engineering/improve-codebase-architecture/DEEPENING.md +0 -37
  888. package/skills/engineering/improve-codebase-architecture/INTERFACE-DESIGN.md +0 -44
  889. package/skills/engineering/improve-codebase-architecture/LANGUAGE.md +0 -53
  890. package/skills/engineering/improve-codebase-architecture/SKILL-zh.md +0 -71
  891. package/skills/engineering/improve-codebase-architecture/SKILL.md +0 -71
  892. package/skills/engineering/tdd/SKILL-zh.md +0 -109
  893. package/skills/engineering/to-issues/SKILL-zh.md +0 -81
  894. package/skills/engineering/to-issues/SKILL.md +0 -81
  895. package/skills/engineering/to-prd/SKILL-zh.md +0 -76
  896. package/skills/engineering/to-prd/SKILL.md +0 -74
  897. package/skills/engineering/zoom-out/SKILL-zh.md +0 -7
  898. package/skills/engineering/zoom-out/SKILL.md +0 -7
  899. package/skills/tools/find-skills/SKILL-zh.md +0 -440
  900. package/skills/tools/github/SKILL-zh.md +0 -48
  901. package/skills/tools/internal-comms/LICENSE.txt +0 -202
  902. package/skills/tools/internal-comms/SKILL-zh.md +0 -32
  903. package/skills/tools/internal-comms/SKILL.md +0 -32
  904. package/skills/tools/internal-comms/examples/3p-updates.md +0 -47
  905. package/skills/tools/internal-comms/examples/company-newsletter.md +0 -65
  906. package/skills/tools/internal-comms/examples/faq-answers.md +0 -30
  907. package/skills/tools/internal-comms/examples/general-comms.md +0 -16
  908. package/skills/tools/skill-creator/LICENSE.txt +0 -202
  909. package/skills/tools/skill-creator/SKILL-zh.md +0 -483
  910. package/skills/tools/skill-creator/SKILL.md +0 -485
  911. package/skills/tools/skill-creator/agents/analyzer.md +0 -274
  912. package/skills/tools/skill-creator/agents/comparator.md +0 -202
  913. package/skills/tools/skill-creator/agents/grader.md +0 -223
  914. package/skills/tools/skill-creator/assets/eval_review.html +0 -146
  915. package/skills/tools/skill-creator/eval-viewer/generate_review.py +0 -471
  916. package/skills/tools/skill-creator/eval-viewer/viewer.html +0 -1325
  917. package/skills/tools/skill-creator/references/schemas.md +0 -430
  918. package/skills/tools/skill-creator/scripts/__init__.py +0 -0
  919. package/skills/tools/skill-creator/scripts/aggregate_benchmark.py +0 -401
  920. package/skills/tools/skill-creator/scripts/generate_report.py +0 -326
  921. package/skills/tools/skill-creator/scripts/improve_description.py +0 -247
  922. package/skills/tools/skill-creator/scripts/package_skill.py +0 -136
  923. package/skills/tools/skill-creator/scripts/quick_validate.py +0 -103
  924. package/skills/tools/skill-creator/scripts/run_eval.py +0 -310
  925. package/skills/tools/skill-creator/scripts/run_loop.py +0 -328
  926. package/skills/tools/skill-creator/scripts/utils.py +0 -47
  927. package/skills/tools/summarize/SKILL-zh.md +0 -47
  928. package/skills/tools/weather/SKILL-zh.md +0 -46
  929. package/skills/tools/weather/SKILL.md +0 -46
  930. package/skills/tools/webapp-testing/SKILL-zh.md +0 -96
@@ -1,23 +1,39 @@
1
1
  import { version } from "../../package.js";
2
+ import { resolveStateDir, resolveXopcDatabasePath } from "../config/paths-state.js";
3
+ import { init_paths } from "../config/paths.js";
2
4
  import { loadConfig } from "../config/loader.js";
3
5
  import { parseAgentSessionKey } from "../routing/session-key-utils.js";
4
6
  import { init_agent_session_key } from "../routing/agent-session-key.js";
7
+ import { resolveEffectiveAgentProfileForSession } from "../config/agent-profile.js";
8
+ import { getAllModels, getAllProviders, getApiKey, init_providers, isProviderConfiguredSync } from "../providers/index.js";
5
9
  import "../config/index.js";
10
+ import { MAX_WEBCHAT_ATTACHMENT_FILE_BYTES } from "../gateway/chat-limits.js";
11
+ import { ProjectTrustStore, hasTrustRequiringProjectResources } from "../project-trust/trust-store.js";
6
12
  import { resolveTuiSessionKey, resolveTuiStartupSessionKey } from "../routing/resolve-tui-session-key.js";
7
- import { saveClipboardImageToTempFile } from "./clipboard-image.js";
8
- import { createXopcTuiKeybindingsManager } from "./tui-keybindings-file.js";
9
- import { StreamAssembler } from "./stream-assembler.js";
10
- import { applyThemeById, getBashExcludeBorderColor, getBashModeBorderColor, getThinkingBorderColor, initTuiTheme } from "./theme-manager.js";
13
+ import { applyThemeById, getBashExcludeBorderColor, getBashModeBorderColor, getCustomThemesDir, getThemeExports, getThinkingBorderColor, initTuiTheme, listAvailableThemeIds, resolveThemePalette } from "./theme-manager.js";
11
14
  import { editorTheme, theme } from "./theme.js";
12
- import { clearPendingToolCallIds, dispatchAgentSSE } from "./tui-agent-events.js";
15
+ import { extensionForImageMimeType, readClipboardImage } from "./clipboard-image.js";
16
+ import { copyTextToClipboard } from "./clipboard-text.js";
17
+ import { createXopcTuiKeybindingsManager } from "./tui-keybindings-file.js";
18
+ import { formatKeyIds } from "./format-tui-hotkeys.js";
19
+ import { isActiveRunStreamStale, markActiveRunStalled, markRunRecovering, markRunRecoveryComplete, markRunSending } from "./tui-run-state.js";
20
+ import { clearSeenStreamEvents, clearSeenStreamEventsForRun, dispatchAgentEvent } from "./tui-agent-events.js";
21
+ import { transcriptTreeEntryIdToRowNumber } from "./tui-transcript-tree.js";
22
+ import { formatTuiCompactionResult, formatTuiShareResult } from "./tui-command-formatters.js";
23
+ import { formatTuiStartupText } from "./tui-startup-text.js";
13
24
  import { createTuiCommandHandler, getSlashCommands } from "./tui-commands.js";
25
+ import { extensionCustomMessageContentToText, extensionCustomMessageToTurnText, extensionUserMessageContentToText } from "./tui-extension-user-message.js";
14
26
  import { resolveFdPath } from "./tui-fd-path.js";
27
+ import { drainFollowUpQueue, restoreQueuedMessages } from "./tui-follow-up-queue.js";
15
28
  import { createBackspaceDeduper, drainAndStopTuiSafely, isIgnorableTuiStopError, resolveCtrlCAction, stopTuiSafely } from "./tui-lifecycle.js";
16
29
  import { createLocalShellRunner } from "./tui-local-shell.js";
17
- import { createOverlayHandlers } from "./tui-overlays.js";
18
30
  import { filterModelsForCycle, loadScopedModelRefs, saveScopedModelRefs } from "./tui-scoped-models.js";
19
- import { openModelPickerOverlay, openScopedModelsOverlay, openSessionPickerOverlay, openSettingsOverlay } from "./tui-picker-overlay.js";
31
+ import { openModelPickerOverlay } from "./tui-model-picker.js";
32
+ import { runTuiOAuthLogin } from "./tui-oauth-login.js";
33
+ import { openAgentPickerOverlay, openProjectTrustOverlay, openScopedModelsOverlay, openSessionPickerOverlay, openSessionTreeOverlay, openSettingsOverlay, openThinkingSelectorOverlay, openTranscriptTreeOverlay, openUserMessageForkOverlay } from "./tui-picker-overlay.js";
34
+ import { formatBusyResponseHint, formatSteerUnavailableHint, formatSuspendUnsupportedHint } from "./tui-runtime-hints.js";
20
35
  import { createSessionActions } from "./tui-session-actions.js";
36
+ import { TuiSessionSnapshot } from "./tui-session-snapshot.js";
21
37
  import { loadTuiSettings, saveTuiSettings } from "./tui-settings.js";
22
38
  import { installTuiStdioFilter } from "./tui-stdio-filter.js";
23
39
  import { createEditorSubmitHandler, createSubmitBurstCoalescer, shouldEnableWindowsGitBashPasteFallback } from "./tui-submit.js";
@@ -31,13 +47,17 @@ import { TuiBottomBar } from "./components/tui-bottom-bar.js";
31
47
  import { TuiHeader } from "./components/tui-header.js";
32
48
  import { loadExtensionsForTuiLocalMode } from "./extension-host/load-extensions.js";
33
49
  import { createTuiExtensionRuntime } from "./extension-host/runtime.js";
34
- import { mkdtempSync, readFileSync, unlinkSync, writeFileSync } from "node:fs";
35
- import { join } from "node:path";
50
+ import { randomUUID } from "node:crypto";
51
+ import { mkdirSync, mkdtempSync, readFileSync, unlinkSync, writeFileSync } from "node:fs";
52
+ import { dirname, isAbsolute, join, resolve } from "node:path";
36
53
  import { tmpdir } from "node:os";
37
54
  import { spawnSync } from "node:child_process";
38
55
  import { Container, Loader, ProcessTerminal, TUI, setKeybindings } from "@earendil-works/pi-tui";
56
+ import { Buffer } from "node:buffer";
39
57
  //#region src/tui/tui.ts
58
+ init_paths();
40
59
  init_agent_session_key();
60
+ init_providers();
41
61
  const THINK_LEVEL_CYCLE = [
42
62
  "off",
43
63
  "minimal",
@@ -54,12 +74,102 @@ function nextThinkLevel(current) {
54
74
  return THINK_LEVEL_CYCLE[((idx >= 0 ? idx : mediumIdx >= 0 ? mediumIdx : 0) + 1) % THINK_LEVEL_CYCLE.length];
55
75
  }
56
76
  const DOUBLE_ESCAPE_WINDOW_MS = 500;
77
+ function escapeHtml(text) {
78
+ return text.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
79
+ }
80
+ function exportExtension(format) {
81
+ if (format === "json") return "json";
82
+ if (format === "markdown") return "md";
83
+ return "html";
84
+ }
85
+ function wrapMarkdownExportAsHtml(markdown) {
86
+ return [
87
+ "<!doctype html>",
88
+ "<html>",
89
+ "<head>",
90
+ "<meta charset=\"utf-8\">",
91
+ "<title>xopc session export</title>",
92
+ "<style>body{font:14px/1.5 system-ui,sans-serif;margin:32px;max-width:960px}pre{white-space:pre-wrap}</style>",
93
+ "</head>",
94
+ "<body>",
95
+ "<pre>",
96
+ escapeHtml(markdown),
97
+ "</pre>",
98
+ "</body>",
99
+ "</html>",
100
+ ""
101
+ ].join("\n");
102
+ }
103
+ function defaultExportPath(sessionKey, format) {
104
+ const safeKey = sessionKey.replace(/[^a-z0-9_.-]+/gi, "_").replace(/^_+|_+$/g, "") || "session";
105
+ const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
106
+ return resolve(process.cwd(), `xopc-session-${safeKey}-${stamp}.${exportExtension(format)}`);
107
+ }
108
+ function userDisplayContentForAttachments(text, attachments) {
109
+ if (!attachments?.length) return text;
110
+ const blocks = [];
111
+ if (text.trim()) blocks.push({
112
+ type: "text",
113
+ text
114
+ });
115
+ for (const att of attachments) {
116
+ if (att.mimeType?.startsWith("image/") || att.type === "image" || att.type === "photo") {
117
+ blocks.push({
118
+ type: "image",
119
+ name: att.name
120
+ });
121
+ continue;
122
+ }
123
+ blocks.push({
124
+ type: "file",
125
+ name: att.name
126
+ });
127
+ }
128
+ return blocks;
129
+ }
130
+ function shellQuote(value) {
131
+ if (/^[A-Za-z0-9_/:@%+=,.-]+$/.test(value)) return value;
132
+ return `'${value.replace(/'/g, `'\\''`)}'`;
133
+ }
134
+ function formatTuiResumeCommand(opts, sessionKey) {
135
+ const parts = ["xopc", "tui"];
136
+ if (opts.local === true) parts.push("--local");
137
+ if (opts.url) parts.push("--url", shellQuote(opts.url));
138
+ parts.push("--session", shellQuote(sessionKey));
139
+ return parts.join(" ");
140
+ }
141
+ function isLoopbackGatewayUrl(rawUrl) {
142
+ try {
143
+ const hostname = new URL(rawUrl).hostname.toLowerCase();
144
+ return hostname === "localhost" || hostname === "127.0.0.1" || hostname === "::1" || hostname === "[::1]";
145
+ } catch {
146
+ return false;
147
+ }
148
+ }
149
+ function resolveStartupWorkingDirectory(opts, isLocalMode) {
150
+ const explicit = opts.workdir?.trim();
151
+ if (explicit) return resolve(explicit);
152
+ if (opts.useStartupCwd === false || opts.session?.trim()) return;
153
+ const gatewayUrl = opts.url ?? "http://localhost:3120";
154
+ if (isLocalMode || isLoopbackGatewayUrl(gatewayUrl)) return process.cwd();
155
+ }
156
+ function assistantMessagePlainText(message) {
157
+ const content = message.content;
158
+ if (typeof content === "string") return content;
159
+ if (!Array.isArray(content)) return "";
160
+ return content.map((block) => {
161
+ if (!block || typeof block !== "object") return "";
162
+ const rec = block;
163
+ return rec.type === "text" && typeof rec.text === "string" ? rec.text : "";
164
+ }).join("");
165
+ }
57
166
  async function runTui(opts) {
58
167
  const stdioFilter = installTuiStdioFilter();
59
168
  const restoreStdio = () => stdioFilter.restore();
60
169
  const isLocalMode = opts.local === true;
170
+ const config = loadConfig();
61
171
  const startup = resolveTuiStartupSessionKey({
62
- cfg: loadConfig(),
172
+ cfg: config,
63
173
  sessionOption: opts.session,
64
174
  cwd: process.cwd()
65
175
  });
@@ -75,16 +185,41 @@ async function runTui(opts) {
75
185
  let tuiSettings = loadTuiSettings();
76
186
  initTuiTheme({ themeId: opts.theme ?? tuiSettings.theme });
77
187
  const state = createInitialState(startup.sessionKey);
188
+ const projectTrustStore = new ProjectTrustStore();
189
+ let projectTrustSessionDecision = null;
190
+ const isCurrentProjectTrusted = () => {
191
+ if (projectTrustSessionDecision !== null) return projectTrustSessionDecision;
192
+ if (!hasTrustRequiringProjectResources(process.cwd())) return true;
193
+ return projectTrustStore.get(process.cwd()) === true;
194
+ };
195
+ let projectTrustPromptShown = false;
196
+ const sessionStateDir = resolveStateDir();
197
+ const sessionDatabasePath = resolveXopcDatabasePath();
198
+ const sessionSnapshot = new TuiSessionSnapshot(() => state.currentSessionKey, () => process.cwd(), () => state.sessionInfo.displayName, () => `${sessionDatabasePath}#session=${encodeURIComponent(state.currentSessionKey)}`, () => sessionStateDir);
78
199
  state.scopedModelRefs = loadScopedModelRefs();
79
200
  state.showThinking = tuiSettings.showThinking;
80
201
  state.toolsExpanded = tuiSettings.toolsExpanded;
81
- const assembler = new StreamAssembler();
202
+ let pendingImageAttachments = [];
203
+ const pendingNextTurnCustomMessages = [];
204
+ let lastRetryMessageText = null;
205
+ let setExtensionLabel = (_entryId, _label) => {};
206
+ let sendExtensionUserMessage = (_content, _options) => {};
207
+ let appendExtensionEntry = (_customType, _data) => {};
208
+ let sendExtensionMessage = (_message, _options) => {};
82
209
  let extensionRegistry;
83
- if (isLocalMode) extensionRegistry = await loadExtensionsForTuiLocalMode();
210
+ if (isLocalMode) extensionRegistry = await loadExtensionsForTuiLocalMode({
211
+ setLabel: (entryId, label) => setExtensionLabel(entryId, label),
212
+ sendUserMessage: (content, options) => sendExtensionUserMessage(content, options),
213
+ appendEntry: (customType, data) => appendExtensionEntry(customType, data),
214
+ sendMessage: (message, options) => sendExtensionMessage(message, options)
215
+ });
84
216
  const client = isLocalMode ? new EmbeddedBackend({ extensionRegistry }) : new GatewaySseBackend({
85
217
  url: opts.url ?? "http://localhost:3120",
86
218
  token: opts.token
87
219
  });
220
+ const startupWorkingDirectory = resolveStartupWorkingDirectory(opts, isLocalMode);
221
+ if (startupWorkingDirectory) state.sessionInfo.effectiveWorkspacePath = startupWorkingDirectory;
222
+ let startupWorkingDirectoryApplied = false;
88
223
  const keybindings = createXopcTuiKeybindingsManager();
89
224
  setKeybindings(keybindings);
90
225
  let modelChoices = [];
@@ -94,6 +229,8 @@ async function runTui(opts) {
94
229
  tui.requestRender();
95
230
  };
96
231
  const tui = new TUI(new ProcessTerminal());
232
+ tui.setShowHardwareCursor(tuiSettings.showHardwareCursor);
233
+ tui.setClearOnShrink(tuiSettings.clearOnShrink);
97
234
  const dedupeBackspace = createBackspaceDeduper();
98
235
  tui.addInputListener((data) => {
99
236
  const next = dedupeBackspace(data);
@@ -105,17 +242,108 @@ async function runTui(opts) {
105
242
  connectionLabel: client.connectionLabel,
106
243
  sessionKey: state.currentSessionKey,
107
244
  showHints: tuiSettings.showStartupHints
108
- }));
245
+ }), keybindings);
109
246
  const statusContainer = new Container();
110
- const bottomBar = new TuiBottomBar(() => state, () => opts.thinking);
111
- const chatLog = new ChatLog();
247
+ const bottomBar = new TuiBottomBar(() => state, () => opts.thinking, () => formatKeyIds(keybindings, "app.message.dequeue", { capitalize: true }));
248
+ const chatLog = new ChatLog(keybindings);
249
+ let startupResources;
250
+ let startupCardShown = false;
251
+ chatLog.setShowThinking(state.showThinking);
112
252
  chatLog.setToolsExpanded(state.toolsExpanded);
113
- const editor = new CustomEditor(tui, editorTheme, keybindings);
253
+ chatLog.setToolImageOptions({
254
+ showImages: tuiSettings.showImages,
255
+ imageWidthCells: tuiSettings.imageWidthCells,
256
+ cwd: process.cwd()
257
+ });
258
+ setExtensionLabel = (entryId, label) => {
259
+ sessionSnapshot.setLabel(entryId, label);
260
+ client.setTranscriptLabel(state.currentSessionKey, entryId, label).catch((err) => {
261
+ const errorMessage = err instanceof Error ? err.message : String(err);
262
+ chatLog.addSystem(`Label update failed: ${errorMessage}`);
263
+ }).finally(() => {
264
+ updateFooter();
265
+ tui.requestRender();
266
+ });
267
+ };
268
+ appendExtensionEntry = (customType, data) => {
269
+ const normalized = customType.trim();
270
+ if (!normalized) throw new Error("appendEntry requires customType.");
271
+ sessionSnapshot.appendCustomEntry(normalized, data);
272
+ client.appendCustomEntry(state.currentSessionKey, normalized, data).catch((err) => {
273
+ const errorMessage = err instanceof Error ? err.message : String(err);
274
+ chatLog.addSystem(`Custom entry append failed: ${errorMessage}`);
275
+ }).finally(() => {
276
+ updateFooter();
277
+ tui.requestRender();
278
+ });
279
+ };
280
+ sendExtensionMessage = (message, options) => {
281
+ const customType = message.customType.trim();
282
+ if (!customType) throw new Error("sendMessage requires customType.");
283
+ const display = message.display ?? true;
284
+ const nextMessage = {
285
+ customType,
286
+ content: message.content,
287
+ display,
288
+ details: message.details
289
+ };
290
+ sessionSnapshot.appendCustomMessage(nextMessage);
291
+ if (display) {
292
+ chatLog.addCustomMessage({
293
+ customType,
294
+ content: extensionCustomMessageContentToText(message.content),
295
+ rawContent: message.content,
296
+ details: message.details,
297
+ display
298
+ });
299
+ tui.requestRender();
300
+ }
301
+ const persist = client.appendCustomMessage(state.currentSessionKey, nextMessage).catch((err) => {
302
+ const errorMessage = err instanceof Error ? err.message : String(err);
303
+ chatLog.addSystem(`Custom message append failed: ${errorMessage}`);
304
+ throw err;
305
+ }).finally(() => {
306
+ updateFooter();
307
+ tui.requestRender();
308
+ });
309
+ const turnText = extensionCustomMessageToTurnText(nextMessage).trim();
310
+ if (!turnText) return;
311
+ persist.then(() => {
312
+ const controlText = `Continue with the extension message "${customType}" above.`;
313
+ if (options?.deliverAs === "nextTurn") {
314
+ pendingNextTurnCustomMessages.push(controlText);
315
+ chatLog.addSystem(theme.dim(`Queued extension message for next turn (${pendingNextTurnCustomMessages.length}).`));
316
+ bottomBar.invalidate();
317
+ tui.requestRender();
318
+ return;
319
+ }
320
+ if (state.activeRunId) {
321
+ if (options?.deliverAs === "followUp") {
322
+ state.messageFollowUpQueue.push(controlText);
323
+ chatLog.addSystem(theme.dim(`Queued extension follow-up (${state.messageFollowUpQueue.length} in queue). ${tuiSettings.followUpMode === "all" ? "All queued messages send together when this reply finishes." : "Next sends when this reply finishes."}`));
324
+ bottomBar.invalidate();
325
+ tui.requestRender();
326
+ return;
327
+ }
328
+ steerMessage(turnText);
329
+ return;
330
+ }
331
+ if (options?.triggerTurn) sendMessage(controlText);
332
+ }).catch(() => {});
333
+ };
334
+ const defaultEditor = new CustomEditor(tui, editorTheme, keybindings, {
335
+ paddingX: tuiSettings.editorPaddingX,
336
+ autocompleteMaxVisible: tuiSettings.autocompleteMaxVisible
337
+ });
338
+ let editor = defaultEditor;
339
+ let editorComponentFactory;
340
+ const editorContainer = new Container();
341
+ editorContainer.addChild(editor);
114
342
  const root = new Container();
115
343
  root.addChild(header);
116
344
  root.addChild(chatLog);
117
345
  root.addChild(statusContainer);
118
- root.addChild(editor);
346
+ root.addChild(editorContainer);
119
347
  root.addChild(bottomBar);
120
348
  tui.addChild(root);
121
349
  tui.setFocus(editor);
@@ -123,7 +351,10 @@ async function runTui(opts) {
123
351
  let isBashExcludeContext = false;
124
352
  const updateEditorBorderColor = () => {
125
353
  if (isBashMode) editor.borderColor = isBashExcludeContext ? getBashExcludeBorderColor() : getBashModeBorderColor();
126
- else editor.borderColor = getThinkingBorderColor(state.sessionInfo.thinkingLevel ?? opts.thinking ?? "off");
354
+ else {
355
+ const level = state.sessionInfo.thinkingLevel ?? opts.thinking ?? "off";
356
+ editor.borderColor = getThinkingBorderColor(level);
357
+ }
127
358
  tui.requestRender();
128
359
  };
129
360
  editor.onChange = (text) => {
@@ -136,8 +367,330 @@ async function runTui(opts) {
136
367
  updateEditorBorderColor();
137
368
  }
138
369
  };
139
- const { openOverlay, closeOverlay } = createOverlayHandlers(tui, editor);
140
- const slashCommands = getSlashCommands(isLocalMode);
370
+ const copyDefaultEditorAppHandlers = (target) => {
371
+ const customEditor = target;
372
+ if (!(customEditor.actionHandlers instanceof Map)) return;
373
+ customEditor.onEscape ??= () => defaultEditor.onEscape?.();
374
+ customEditor.onCtrlD ??= () => defaultEditor.onCtrlD?.();
375
+ customEditor.onPasteImage ??= () => defaultEditor.onPasteImage?.();
376
+ customEditor.onExtensionShortcut ??= (data) => defaultEditor.onExtensionShortcut?.(data) ?? false;
377
+ for (const [action, handler] of defaultEditor.actionHandlers) customEditor.actionHandlers.set(action, handler);
378
+ };
379
+ const setEditorExtensionShortcut = () => {
380
+ const customEditor = editor;
381
+ customEditor.onExtensionShortcut = (data) => extensionRuntime.handleShortcut(data);
382
+ };
383
+ const setEditorComponent = (factory) => {
384
+ editorComponentFactory = factory;
385
+ const currentText = editor.getText();
386
+ editorContainer.clear();
387
+ if (factory) {
388
+ const nextEditor = factory(tui, editorTheme, keybindings);
389
+ nextEditor.onSubmit = defaultEditor.onSubmit;
390
+ nextEditor.onChange = defaultEditor.onChange;
391
+ nextEditor.setText(currentText);
392
+ if (nextEditor.borderColor !== void 0) nextEditor.borderColor = defaultEditor.borderColor;
393
+ nextEditor.setPaddingX?.(tuiSettings.editorPaddingX);
394
+ nextEditor.setAutocompleteMaxVisible?.(tuiSettings.autocompleteMaxVisible);
395
+ nextEditor.setAutocompleteProvider?.(extensionRuntime.autocompleteProvider);
396
+ copyDefaultEditorAppHandlers(nextEditor);
397
+ editor = nextEditor;
398
+ } else {
399
+ defaultEditor.setText(currentText);
400
+ editor = defaultEditor;
401
+ }
402
+ editorContainer.addChild(editor);
403
+ setEditorExtensionShortcut();
404
+ tui.setFocus(editor);
405
+ updateEditorBorderColor();
406
+ tui.requestRender();
407
+ };
408
+ let activeEditorSelectorClose = null;
409
+ const closeEditorSelector = () => {
410
+ activeEditorSelectorClose?.();
411
+ };
412
+ const openEditorSelector = (component, focus = component) => {
413
+ closeEditorSelector();
414
+ editorContainer.clear();
415
+ editorContainer.addChild(component);
416
+ tui.setFocus(focus);
417
+ tui.requestRender();
418
+ const close = () => {
419
+ if (activeEditorSelectorClose !== close) return;
420
+ activeEditorSelectorClose = null;
421
+ editorContainer.clear();
422
+ editorContainer.addChild(editor);
423
+ tui.setFocus(editor);
424
+ tui.requestRender();
425
+ };
426
+ activeEditorSelectorClose = close;
427
+ return close;
428
+ };
429
+ const openCommandOverlay = (component, _options) => {
430
+ let hidden = false;
431
+ let closeCurrent = openEditorSelector(component, component);
432
+ return {
433
+ hide: () => closeCurrent(),
434
+ setHidden: (nextHidden) => {
435
+ hidden = nextHidden;
436
+ if (nextHidden) closeCurrent();
437
+ else closeCurrent = openEditorSelector(component, component);
438
+ },
439
+ isHidden: () => hidden,
440
+ focus: () => tui.setFocus(component),
441
+ unfocus: () => tui.setFocus(editor),
442
+ isFocused: () => false
443
+ };
444
+ };
445
+ const closeCommandOverlay = () => {
446
+ closeEditorSelector();
447
+ };
448
+ const slashCommands = getSlashCommands(isLocalMode, keybindings);
449
+ let extensionWorkingMessage;
450
+ let extensionWorkingVisible = true;
451
+ let extensionWorkingIndicator;
452
+ const getAllExtensionThemes = () => {
453
+ const customDir = getCustomThemesDir();
454
+ return listAvailableThemeIds().map((name) => ({
455
+ name,
456
+ path: name === "auto" || name === "dark" || name === "light" ? void 0 : join(customDir, `${name}.json`)
457
+ }));
458
+ };
459
+ const getExtensionTheme = (name) => {
460
+ const normalized = name.trim().toLowerCase() || "auto";
461
+ if (!listAvailableThemeIds().includes(normalized)) return void 0;
462
+ const currentTheme = tuiSettings.theme;
463
+ applyThemeById(normalized);
464
+ const resolved = getThemeExports().theme;
465
+ applyThemeById(currentTheme);
466
+ return resolved;
467
+ };
468
+ const setExtensionTheme = (nextTheme) => {
469
+ const normalized = nextTheme.trim().toLowerCase() || "auto";
470
+ if (!listAvailableThemeIds().includes(normalized)) return {
471
+ success: false,
472
+ error: `Unknown theme: ${nextTheme}`
473
+ };
474
+ try {
475
+ resolveThemePalette(normalized);
476
+ tuiSettings = {
477
+ ...tuiSettings,
478
+ theme: normalized
479
+ };
480
+ saveTuiSettings(tuiSettings);
481
+ applyThemeById(normalized);
482
+ updateEditorBorderColor();
483
+ chatLog.invalidate();
484
+ header.invalidate();
485
+ bottomBar.invalidate();
486
+ tui.requestRender();
487
+ return { success: true };
488
+ } catch (err) {
489
+ return {
490
+ success: false,
491
+ error: err instanceof Error ? err.message : String(err)
492
+ };
493
+ }
494
+ };
495
+ const getAvailableProviderCount = () => getAllProviders().filter((provider) => isProviderConfiguredSync(provider)).length;
496
+ const getExtensionSystemPrompt = () => resolveEffectiveAgentProfileForSession(config, state.currentSessionKey).systemPromptOverride ?? "";
497
+ const waitForTuiIdle = async () => {
498
+ while (state.activeRunId != null || state.isCompacting || state.activityStatus === "sending" || state.activityStatus === "waiting" || state.activityStatus === "streaming" || state.activityStatus === "running" || state.activityStatus === "compacting") await new Promise((resolveDelay) => setTimeout(resolveDelay, 50));
499
+ };
500
+ const createReplacementContext = () => {
501
+ const model = state.sessionInfo.model ? {
502
+ ...state.sessionInfo.modelProvider ? { provider: state.sessionInfo.modelProvider } : {},
503
+ id: state.sessionInfo.model,
504
+ ref: state.sessionInfo.modelProvider ? `${state.sessionInfo.modelProvider}/${state.sessionInfo.model}` : state.sessionInfo.model,
505
+ contextWindow: state.sessionInfo.contextWindow ?? null
506
+ } : void 0;
507
+ return {
508
+ mode: "tui",
509
+ hasUI: true,
510
+ signal: client.getActiveSignal?.(),
511
+ ui: {
512
+ select: async () => void 0,
513
+ confirm: async () => false,
514
+ input: async () => void 0,
515
+ notify: (message, level) => {
516
+ const prefix = level === "error" ? "Error: " : level === "warn" || level === "warning" ? "Warning: " : "";
517
+ chatLog.addSystem(`${prefix}${message}`);
518
+ tui.requestRender();
519
+ },
520
+ onTerminalInput: (handler) => tui.addInputListener(handler),
521
+ setStatus: () => {},
522
+ setWorkingMessage: (message) => {
523
+ extensionWorkingMessage = message?.trim() || void 0;
524
+ renderStatus();
525
+ },
526
+ setWorkingVisible: (visible) => {
527
+ extensionWorkingVisible = visible;
528
+ renderStatus();
529
+ },
530
+ setWorkingIndicator: (indicator) => {
531
+ extensionWorkingIndicator = indicator ?? void 0;
532
+ statusLoader?.setIndicator(indicator ?? void 0);
533
+ renderStatus();
534
+ },
535
+ setHiddenThinkingLabel: (label) => {
536
+ chatLog.setHiddenThinkingLabel(label ?? void 0);
537
+ tui.requestRender();
538
+ },
539
+ setWidget: () => {},
540
+ setFooter: () => {},
541
+ setHeader: () => {},
542
+ custom: async () => void 0,
543
+ setTitle: (title) => tui.terminal.setTitle(title),
544
+ pasteToEditor: (text) => editor.handleInput(`\x1b[200~${text}\x1b[201~`),
545
+ setEditorText: (text) => editor.setText(text),
546
+ getEditorText: () => editor.getExpandedText?.() ?? editor.getText(),
547
+ editor: async () => void 0,
548
+ addAutocompleteProvider: () => () => {},
549
+ setEditorComponent,
550
+ getEditorComponent: () => editorComponentFactory,
551
+ theme,
552
+ getAllThemes: getAllExtensionThemes,
553
+ getTheme: getExtensionTheme,
554
+ setTheme: setExtensionTheme,
555
+ getToolsExpanded: () => state.toolsExpanded,
556
+ setToolsExpanded: (expanded) => {
557
+ state.toolsExpanded = expanded;
558
+ tuiSettings = {
559
+ ...tuiSettings,
560
+ toolsExpanded: expanded
561
+ };
562
+ saveTuiSettings(tuiSettings);
563
+ chatLog.setToolsExpanded(expanded);
564
+ updateFooter();
565
+ tui.requestRender();
566
+ }
567
+ },
568
+ sessionManager: sessionSnapshot.manager(),
569
+ modelRegistry: {
570
+ find(provider, modelId) {
571
+ return getAllModels().find((candidate) => candidate.provider === provider && candidate.id === modelId);
572
+ },
573
+ async getApiKeyAndHeaders(nextModel) {
574
+ const provider = typeof nextModel.provider === "string" ? nextModel.provider : void 0;
575
+ if (!provider) return {
576
+ ok: false,
577
+ error: "Model provider is missing."
578
+ };
579
+ try {
580
+ return {
581
+ ok: true,
582
+ apiKey: await getApiKey(provider),
583
+ headers: {}
584
+ };
585
+ } catch (error) {
586
+ return {
587
+ ok: false,
588
+ error: error instanceof Error ? error.message : String(error)
589
+ };
590
+ }
591
+ }
592
+ },
593
+ model,
594
+ cwd: process.cwd(),
595
+ sessionKey: state.currentSessionKey,
596
+ isProjectTrusted: isCurrentProjectTrusted,
597
+ isIdle: () => !state.activeRunId && !state.isCompacting,
598
+ hasPendingMessages: () => state.messageFollowUpQueue.length > 0 || state.steeringQueue.length > 0 || state.compactionQueue.length > 0,
599
+ abort: () => abortActive(),
600
+ shutdown: () => requestExit(),
601
+ compact: (options) => runCompaction(options?.customInstructions, {
602
+ onComplete: options?.onComplete,
603
+ onError: options?.onError
604
+ }),
605
+ getSystemPrompt: getExtensionSystemPrompt,
606
+ getSystemPromptOptions: () => ({
607
+ cwd: process.cwd(),
608
+ sessionKey: state.currentSessionKey,
609
+ ...model ? { model } : {}
610
+ }),
611
+ waitForIdle: waitForTuiIdle,
612
+ newSession: (options) => runExtensionNewSession(options),
613
+ fork: (entryId, options) => runExtensionFork(entryId, options),
614
+ navigateTree: (targetId, options) => runExtensionNavigateTree(targetId, options),
615
+ switchSession: (sessionPath, options) => runExtensionSwitchSession(sessionPath, options),
616
+ reload: async () => {
617
+ await loadSessionHistory({ merge: true });
618
+ await refreshSessionInfoWithBorder();
619
+ },
620
+ getModel: () => model,
621
+ setModel: (modelRef) => switchCurrentModel(modelRef),
622
+ getThinkingLevel: () => state.sessionInfo.thinkingLevel,
623
+ setThinkingLevel,
624
+ getReasoningLevel: () => state.sessionInfo.reasoningLevel,
625
+ setReasoningLevel,
626
+ getVerboseLevel: () => state.sessionInfo.verboseLevel,
627
+ setVerboseLevel,
628
+ getCommands: () => slashCommands.map((command) => ({
629
+ name: command.name,
630
+ description: command.description,
631
+ source: "builtin"
632
+ })),
633
+ getContextUsage: () => {
634
+ const tokens = state.sessionInfo.totalTokens ?? state.sessionInfo.contextTokens ?? null;
635
+ const contextWindow = state.sessionInfo.contextWindow ?? null;
636
+ const percent = state.sessionInfo.contextUsagePercent ?? null;
637
+ if (tokens == null && contextWindow == null) return void 0;
638
+ return {
639
+ estimatedTokens: tokens,
640
+ tokens,
641
+ contextWindow,
642
+ usagePercent: percent,
643
+ percent
644
+ };
645
+ },
646
+ notify: (message, level) => {
647
+ const prefix = level === "error" ? "Error: " : level === "warn" || level === "warning" ? "Warning: " : "";
648
+ chatLog.addSystem(`${prefix}${message}`);
649
+ tui.requestRender();
650
+ },
651
+ sendMessage: async (message, options) => sendExtensionMessage(message, options),
652
+ sendUserMessage: async (content, options) => sendExtensionUserMessage(content, options)
653
+ };
654
+ };
655
+ const runWithReplacementContext = async (callback) => {
656
+ if (callback) await callback(createReplacementContext());
657
+ };
658
+ const runExtensionNewSession = async (options) => {
659
+ await abortActive({ clearUi: false });
660
+ await setSession(resolveSessionKey(`session-${randomUUID()}`));
661
+ await options?.setup?.(sessionSnapshot.manager());
662
+ await runWithReplacementContext(options?.withSession);
663
+ return { cancelled: false };
664
+ };
665
+ const runExtensionFork = async (entryId, options) => {
666
+ const rowNumber = transcriptTreeEntryIdToRowNumber(entryId);
667
+ if (rowNumber == null) throw new Error(`Invalid entry ID for forking: ${entryId}`);
668
+ const throughRow = options?.position === "before" ? rowNumber - 1 : rowNumber;
669
+ if (throughRow <= 0) throw new Error(`Invalid entry ID for forking: ${entryId}`);
670
+ const sourceSessionKey = state.currentSessionKey;
671
+ const targetKey = resolveSessionKey(`fork-${randomUUID()}`);
672
+ await abortActive({ clearUi: false });
673
+ const result = await client.forkSessionAt(sourceSessionKey, targetKey, `row-${throughRow}`);
674
+ await setSession(result.sessionKey);
675
+ chatLog.addBranchSummary({
676
+ sourceSessionKey,
677
+ targetSessionKey: result.sessionKey,
678
+ rowCount: result.rowCount,
679
+ entryId
680
+ });
681
+ await runWithReplacementContext(options?.withSession);
682
+ return { cancelled: false };
683
+ };
684
+ const runExtensionNavigateTree = async (targetId, options) => {
685
+ if (options?.label) setExtensionLabel(targetId, options.label);
686
+ return runExtensionFork(targetId, { position: "at" });
687
+ };
688
+ const runExtensionSwitchSession = async (sessionPath, options) => {
689
+ await abortActive({ clearUi: false });
690
+ await setSession(sessionPath);
691
+ await runWithReplacementContext(options?.withSession);
692
+ return { cancelled: false };
693
+ };
141
694
  const extensionRuntime = createTuiExtensionRuntime({
142
695
  registry: extensionRegistry,
143
696
  tui,
@@ -146,17 +699,91 @@ async function runTui(opts) {
146
699
  bottomBar,
147
700
  getState: () => state,
148
701
  baseSlashCommands: slashCommands,
702
+ keybindings,
703
+ addInputListener: (handler) => tui.addInputListener(handler),
704
+ setTitle: (title) => tui.terminal.setTitle(title),
705
+ pasteToEditor: (text) => editor.handleInput(`\x1b[200~${text}\x1b[201~`),
706
+ setEditorText: (text) => editor.setText(text),
707
+ getEditorText: () => editor.getExpandedText?.() ?? editor.getText(),
708
+ setEditorComponent,
709
+ getEditorComponent: () => editorComponentFactory,
710
+ getThemeObject: () => theme,
711
+ getAllThemes: getAllExtensionThemes,
712
+ getTheme: getExtensionTheme,
713
+ setTheme: setExtensionTheme,
714
+ getToolsExpanded: () => state.toolsExpanded,
715
+ setToolsExpanded: (expanded) => {
716
+ state.toolsExpanded = expanded;
717
+ tuiSettings = {
718
+ ...tuiSettings,
719
+ toolsExpanded: expanded
720
+ };
721
+ saveTuiSettings(tuiSettings);
722
+ chatLog.setToolsExpanded(expanded);
723
+ updateFooter();
724
+ tui.requestRender();
725
+ },
726
+ getAvailableProviderCount,
727
+ getActiveSignal: () => client.getActiveSignal?.(),
728
+ isProjectTrusted: isCurrentProjectTrusted,
729
+ getSessionManager: () => sessionSnapshot.manager(),
730
+ getSystemPrompt: getExtensionSystemPrompt,
731
+ getSystemPromptOptions: () => ({
732
+ cwd: process.cwd(),
733
+ sessionKey: state.currentSessionKey,
734
+ ...state.sessionInfo.model ? { model: {
735
+ ...state.sessionInfo.modelProvider ? { provider: state.sessionInfo.modelProvider } : {},
736
+ id: state.sessionInfo.model,
737
+ ref: state.sessionInfo.modelProvider ? `${state.sessionInfo.modelProvider}/${state.sessionInfo.model}` : state.sessionInfo.model,
738
+ contextWindow: state.sessionInfo.contextWindow ?? null
739
+ } } : {}
740
+ }),
741
+ waitForIdle: waitForTuiIdle,
742
+ newSession: runExtensionNewSession,
743
+ forkSession: runExtensionFork,
744
+ navigateTree: runExtensionNavigateTree,
745
+ switchSession: runExtensionSwitchSession,
746
+ reload: async () => {
747
+ await loadSessionHistory();
748
+ await refreshSessionInfoWithBorder();
749
+ },
750
+ sendUserMessage: async (content, options) => sendExtensionUserMessage(content, options),
751
+ sendMessage: async (message, options) => sendExtensionMessage(message, options),
149
752
  cwd: process.cwd(),
150
753
  fdPath: resolveFdPath(),
151
- openOverlay,
152
- closeOverlay,
754
+ openOverlay: openCommandOverlay,
755
+ closeOverlay: closeCommandOverlay,
153
756
  onInvalidate: () => {
154
757
  updateHeader();
155
758
  updateFooter();
156
759
  tui.requestRender();
760
+ },
761
+ abortActive: () => abortActive(),
762
+ requestExit: () => requestExit(),
763
+ compactSession: (options) => runCompaction(options?.customInstructions, {
764
+ onComplete: options?.onComplete,
765
+ onError: options?.onError
766
+ }),
767
+ setModel: (modelRef) => switchCurrentModel(modelRef),
768
+ setThinkingLevel: (level) => setThinkingLevel(level),
769
+ setReasoningLevel: (level) => setReasoningLevel(level),
770
+ setVerboseLevel: (level) => setVerboseLevel(level),
771
+ setWorkingMessage: (message) => {
772
+ extensionWorkingMessage = message?.trim() || void 0;
773
+ renderStatus();
774
+ },
775
+ setWorkingVisible: (visible) => {
776
+ extensionWorkingVisible = visible;
777
+ renderStatus();
778
+ },
779
+ setWorkingIndicator: (indicator) => {
780
+ extensionWorkingIndicator = indicator;
781
+ statusLoader?.setIndicator(indicator);
782
+ renderStatus();
157
783
  }
158
784
  });
159
- editor.setAutocompleteProvider(extensionRuntime.autocompleteProvider);
785
+ editor.setAutocompleteProvider?.(extensionRuntime.autocompleteProvider);
786
+ setEditorExtensionShortcut();
160
787
  let statusLoader = null;
161
788
  let statusStartedAt = null;
162
789
  let lastActivityStatus = "";
@@ -166,7 +793,8 @@ async function runTui(opts) {
166
793
  "waiting",
167
794
  "streaming",
168
795
  "running",
169
- "compacting"
796
+ "compacting",
797
+ "recovering"
170
798
  ]);
171
799
  const syncTerminalProgress = () => {
172
800
  if (!tuiSettings.showTerminalProgress) {
@@ -179,6 +807,11 @@ async function runTui(opts) {
179
807
  let streamWatchdogId = null;
180
808
  const touchStreamingActivity = () => {
181
809
  lastStreamActivityAt = Date.now();
810
+ if (state.activeRunId && state.runStatus.lastActivityAt == null) state.runStatus = {
811
+ ...state.runStatus,
812
+ runId: state.activeRunId,
813
+ lastActivityAt: lastStreamActivityAt
814
+ };
182
815
  };
183
816
  const formatElapsed = (startMs) => {
184
817
  const totalSeconds = Math.max(0, Math.floor((Date.now() - startMs) / 1e3));
@@ -186,24 +819,29 @@ async function runTui(opts) {
186
819
  return `${Math.floor(totalSeconds / 60)}m ${totalSeconds % 60}s`;
187
820
  };
188
821
  const renderStatus = () => {
189
- if (busyStates.has(state.activityStatus)) {
822
+ const isBusy = busyStates.has(state.activityStatus);
823
+ if (isBusy && extensionWorkingVisible) {
190
824
  if (!statusStartedAt || lastActivityStatus !== state.activityStatus) statusStartedAt = Date.now();
191
825
  if (!statusLoader) {
192
826
  statusContainer.clear();
193
- statusLoader = new Loader(tui, (spinner) => theme.accent(spinner), (text) => theme.bold(theme.accentSoft(text)), "");
827
+ statusLoader = new Loader(tui, (spinner) => theme.accent(spinner), (text) => theme.bold(theme.accentSoft(text)), "", extensionWorkingIndicator);
194
828
  statusContainer.addChild(statusLoader);
195
829
  }
196
830
  const elapsed = formatElapsed(statusStartedAt);
197
- statusLoader.setMessage(`${state.progressMessage ?? state.activityStatus} ${elapsed} | ${state.connectionStatus}`);
831
+ const loaderMessage = state.progressMessage ?? extensionWorkingMessage ?? state.activityStatus;
832
+ statusLoader.setMessage(`${loaderMessage} • ${elapsed} | ${state.connectionStatus}`);
198
833
  if (!elapsedTimerId) elapsedTimerId = setInterval(() => {
199
834
  if (statusStartedAt && statusLoader) {
200
835
  const el = formatElapsed(statusStartedAt);
201
- statusLoader.setMessage(`${state.progressMessage ?? state.activityStatus} ${el} | ${state.connectionStatus}`);
836
+ const message = state.progressMessage ?? extensionWorkingMessage ?? state.activityStatus;
837
+ statusLoader.setMessage(`${message} • ${el} | ${state.connectionStatus}`);
202
838
  }
203
839
  }, 1e3);
204
840
  } else {
205
- state.progressMessage = null;
206
- statusStartedAt = null;
841
+ if (!isBusy) {
842
+ state.progressMessage = null;
843
+ statusStartedAt = null;
844
+ }
207
845
  if (elapsedTimerId) {
208
846
  clearInterval(elapsedTimerId);
209
847
  elapsedTimerId = null;
@@ -262,6 +900,7 @@ async function runTui(opts) {
262
900
  tui.terminal.setProgress(false);
263
901
  drainAndStopTuiSafely(tui).then(() => {
264
902
  restoreStdio();
903
+ process.stdout.write(`\nTo resume this session: ${formatTuiResumeCommand(opts, state.currentSessionKey)}\n`);
265
904
  finishTui?.();
266
905
  process.exit(0);
267
906
  });
@@ -271,11 +910,11 @@ async function runTui(opts) {
271
910
  chatLog,
272
911
  tui,
273
912
  state,
274
- assembler,
275
913
  resolveSessionKey,
276
914
  updateHeader,
277
915
  updateFooter,
278
916
  setActivityStatus,
917
+ sessionSnapshot,
279
918
  onAgentIdChange: (agentId) => {
280
919
  currentAgentId = agentId;
281
920
  }
@@ -284,6 +923,166 @@ async function runTui(opts) {
284
923
  await refreshSessionInfo();
285
924
  updateEditorBorderColor();
286
925
  };
926
+ const refreshStartupResources = async () => {
927
+ if (!client.getStartupResources) return;
928
+ try {
929
+ startupResources = await client.getStartupResources(state.currentSessionKey);
930
+ } catch {
931
+ startupResources = void 0;
932
+ }
933
+ };
934
+ const showStartupCardOnce = () => {
935
+ if (startupCardShown) return;
936
+ startupCardShown = true;
937
+ chatLog.addSystem(formatTuiStartupText({
938
+ state,
939
+ isLocal: isLocalMode,
940
+ keybindings,
941
+ resources: startupResources,
942
+ expanded: false
943
+ }));
944
+ };
945
+ const applyStartupWorkingDirectory = async () => {
946
+ if (startupWorkingDirectoryApplied || !startupWorkingDirectory) return;
947
+ startupWorkingDirectoryApplied = true;
948
+ await client.patchSession(state.currentSessionKey, { workingDirectory: startupWorkingDirectory });
949
+ state.sessionInfo.effectiveWorkspacePath = startupWorkingDirectory;
950
+ state.sessionInfo.workingDirectoryLocked = true;
951
+ };
952
+ let streamRecoveryPromise = null;
953
+ const recoverActiveRunFromHistory = (reason) => {
954
+ if (!state.activeRunId) return Promise.resolve();
955
+ if (streamRecoveryPromise) return streamRecoveryPromise;
956
+ const runId = state.activeRunId;
957
+ markRunRecovering(state, Date.now());
958
+ state.progressMessage = "recovering stream history";
959
+ setActivityStatus("recovering");
960
+ streamRecoveryPromise = (async () => {
961
+ try {
962
+ await loadSessionHistory();
963
+ await refreshSessionInfoWithBorder();
964
+ if (state.activeRunId === runId) {
965
+ clearSeenStreamEventsForRun(runId);
966
+ if (client.resumeChat) {
967
+ const resumed = await client.resumeChat({
968
+ sessionKey: state.currentSessionKey,
969
+ runId
970
+ });
971
+ if (resumed.ok) {
972
+ state.progressMessage = "resuming stream";
973
+ setActivityStatus("recovering");
974
+ chatLog.addSystem(theme.dim(`Reattached to active run after ${reason}.`));
975
+ } else {
976
+ markRunRecoveryComplete(state, Date.now());
977
+ state.progressMessage = "stream stalled; resume unavailable";
978
+ setActivityStatus("stalled");
979
+ chatLog.addSystem(theme.dim(`Recovered persisted history after ${reason}, but could not resume stream: ${resumed.reason ?? "run relay unavailable"}. Press Escape or /abort to stop it.`));
980
+ }
981
+ } else {
982
+ markRunRecoveryComplete(state, Date.now());
983
+ state.progressMessage = "stream stalled; waiting for new events or abort";
984
+ setActivityStatus("stalled");
985
+ chatLog.addSystem(theme.dim(`Recovered persisted history after ${reason}. Active run is still marked stalled; press Escape or /abort to stop it.`));
986
+ }
987
+ }
988
+ } catch (error) {
989
+ const errorMessage = error instanceof Error ? error.message : String(error);
990
+ chatLog.addSystem(theme.dim(`Stream recovery failed after ${reason}: ${errorMessage}`));
991
+ if (state.activeRunId === runId) {
992
+ markRunRecoveryComplete(state, Date.now());
993
+ setActivityStatus("stalled");
994
+ }
995
+ } finally {
996
+ streamRecoveryPromise = null;
997
+ updateFooter();
998
+ tui.requestRender();
999
+ }
1000
+ })();
1001
+ return streamRecoveryPromise;
1002
+ };
1003
+ const setThinkingLevel = async (level) => {
1004
+ try {
1005
+ await client.patchSession(state.currentSessionKey, { thinkingLevel: level });
1006
+ state.sessionInfo.thinkingLevel = level;
1007
+ await refreshSessionInfoWithBorder();
1008
+ updateFooter();
1009
+ chatLog.addStatus(theme.dim(`Thinking level: ${level}`));
1010
+ } catch (err) {
1011
+ const errorMessage = err instanceof Error ? err.message : String(err);
1012
+ chatLog.addSystem(`Thinking level change failed: ${errorMessage}`);
1013
+ } finally {
1014
+ tui.requestRender();
1015
+ }
1016
+ };
1017
+ const setReasoningLevel = async (level) => {
1018
+ try {
1019
+ await client.patchSession(state.currentSessionKey, { reasoningLevel: level });
1020
+ state.sessionInfo.reasoningLevel = level;
1021
+ await refreshSessionInfoWithBorder();
1022
+ updateFooter();
1023
+ chatLog.addStatus(theme.dim(`Reasoning visibility: ${level}`));
1024
+ } catch (err) {
1025
+ const errorMessage = err instanceof Error ? err.message : String(err);
1026
+ chatLog.addSystem(`Reasoning visibility change failed: ${errorMessage}`);
1027
+ } finally {
1028
+ tui.requestRender();
1029
+ }
1030
+ };
1031
+ const setVerboseLevel = async (level) => {
1032
+ try {
1033
+ await client.patchSession(state.currentSessionKey, { verboseLevel: level });
1034
+ state.sessionInfo.verboseLevel = level;
1035
+ await refreshSessionInfoWithBorder();
1036
+ updateFooter();
1037
+ chatLog.addStatus(theme.dim(`Verbose mode: ${level}`));
1038
+ } catch (err) {
1039
+ const errorMessage = err instanceof Error ? err.message : String(err);
1040
+ chatLog.addSystem(`Verbose mode change failed: ${errorMessage}`);
1041
+ } finally {
1042
+ tui.requestRender();
1043
+ }
1044
+ };
1045
+ const copyLastAssistant = async () => {
1046
+ const text = chatLog.getLastAssistantText().trim();
1047
+ if (!text) {
1048
+ chatLog.addSystem("No assistant messages to copy yet.");
1049
+ tui.requestRender();
1050
+ return;
1051
+ }
1052
+ try {
1053
+ await copyTextToClipboard(text);
1054
+ chatLog.addStatus(theme.dim("Copied last assistant message to clipboard"));
1055
+ } catch (err) {
1056
+ const errorMessage = err instanceof Error ? err.message : String(err);
1057
+ chatLog.addSystem(`Copy failed: ${errorMessage}`);
1058
+ } finally {
1059
+ tui.requestRender();
1060
+ }
1061
+ };
1062
+ const renameCurrentSession = async (name) => {
1063
+ const nextName = name.trim();
1064
+ if (!nextName) {
1065
+ chatLog.addSystem("Usage: /name <name>");
1066
+ tui.requestRender();
1067
+ return;
1068
+ }
1069
+ try {
1070
+ if (!(await client.renameSession(state.currentSessionKey, nextName)).ok) {
1071
+ chatLog.addSystem("Session rename failed.");
1072
+ tui.requestRender();
1073
+ return;
1074
+ }
1075
+ state.sessionInfo.displayName = nextName;
1076
+ updateFooter();
1077
+ updateHeader();
1078
+ chatLog.addStatus(theme.dim(`Session name set: ${nextName}`));
1079
+ } catch (err) {
1080
+ const errorMessage = err instanceof Error ? err.message : String(err);
1081
+ chatLog.addSystem(`Session rename failed: ${errorMessage}`);
1082
+ } finally {
1083
+ tui.requestRender();
1084
+ }
1085
+ };
287
1086
  const resolveModelChoiceIndex = () => {
288
1087
  const choices = cycleModelChoices();
289
1088
  if (choices.length === 0) return -1;
@@ -315,11 +1114,140 @@ async function runTui(opts) {
315
1114
  }
316
1115
  const idx = resolveModelChoiceIndex();
317
1116
  const next = choices[((idx >= 0 ? idx : 0) + (dir === "forward" ? 1 : -1) + choices.length) % choices.length];
318
- sendMessage(`/switch ${next.provider}/${next.id}`);
1117
+ switchCurrentModel(`${next.provider}/${next.id}`);
1118
+ };
1119
+ const listCurrentModels = async () => {
1120
+ if (modelChoices.length === 0) await refreshModelChoices();
1121
+ return modelChoices;
1122
+ };
1123
+ const switchCurrentModel = async (modelRef) => {
1124
+ const trimmed = modelRef.trim();
1125
+ if (!trimmed.includes("/")) {
1126
+ chatLog.addSystem("Usage: /switch <provider/model>");
1127
+ tui.requestRender();
1128
+ return;
1129
+ }
1130
+ if (modelChoices.length === 0) await refreshModelChoices();
1131
+ const [provider, id] = trimmed.split("/", 2);
1132
+ const selected = modelChoices.find((choice) => choice.provider === provider && choice.id === id);
1133
+ if (!selected) {
1134
+ chatLog.addSystem(`Model not found: ${trimmed}`);
1135
+ tui.requestRender();
1136
+ return;
1137
+ }
1138
+ try {
1139
+ await client.patchSession(state.currentSessionKey, { model: trimmed });
1140
+ state.sessionInfo.modelProvider = selected.provider;
1141
+ state.sessionInfo.model = selected.id;
1142
+ if (selected.contextWindow != null) state.sessionInfo.contextWindow = selected.contextWindow;
1143
+ await refreshSessionInfoWithBorder();
1144
+ updateFooter();
1145
+ updateHeader();
1146
+ chatLog.addStatus(theme.dim(`Model: ${trimmed}`));
1147
+ } catch (err) {
1148
+ const errorMessage = err instanceof Error ? err.message : String(err);
1149
+ chatLog.addSystem(`Model switch failed: ${errorMessage}`);
1150
+ } finally {
1151
+ tui.requestRender();
1152
+ }
1153
+ };
1154
+ const exportCurrentSession = async (request) => {
1155
+ const outputPath = request.outputPath ? isAbsolute(request.outputPath) ? request.outputPath : resolve(process.cwd(), request.outputPath) : defaultExportPath(state.currentSessionKey, request.format);
1156
+ try {
1157
+ const backendFormat = request.format === "json" ? "json" : "markdown";
1158
+ const raw = await client.exportSession(state.currentSessionKey, backendFormat);
1159
+ const content = request.format === "html" ? wrapMarkdownExportAsHtml(raw) : raw;
1160
+ mkdirSync(dirname(outputPath), { recursive: true });
1161
+ writeFileSync(outputPath, content, "utf8");
1162
+ chatLog.addStatus(theme.dim(`Exported ${request.format} session to: ${outputPath}`));
1163
+ } catch (err) {
1164
+ const errorMessage = err instanceof Error ? err.message : String(err);
1165
+ chatLog.addSystem(`Export failed: ${errorMessage}`);
1166
+ } finally {
1167
+ tui.requestRender();
1168
+ }
1169
+ };
1170
+ const importSessionExport = async (request) => {
1171
+ const rawPath = request.inputPath?.trim();
1172
+ if (!rawPath) {
1173
+ chatLog.addSystem("Usage: /import <path.json> [target-session]");
1174
+ tui.requestRender();
1175
+ return;
1176
+ }
1177
+ const inputPath = isAbsolute(rawPath) ? rawPath : resolve(process.cwd(), rawPath);
1178
+ const targetKey = resolveSessionKey(request.targetKey?.trim() || `import-${randomUUID()}`);
1179
+ try {
1180
+ const content = readFileSync(inputPath, "utf8");
1181
+ const result = await client.importSession(targetKey, content);
1182
+ await setSession(result.sessionKey);
1183
+ chatLog.addStatus(theme.dim(`Imported ${result.rowCount} transcript rows from: ${inputPath}`));
1184
+ } catch (err) {
1185
+ const errorMessage = err instanceof Error ? err.message : String(err);
1186
+ chatLog.addSystem(`Import failed: ${errorMessage}`);
1187
+ } finally {
1188
+ tui.requestRender();
1189
+ }
1190
+ };
1191
+ const createShareLink = async (request) => {
1192
+ try {
1193
+ chatLog.addStatus(theme.dim(`Creating share for: ${request.path}`));
1194
+ tui.requestRender();
1195
+ const result = await client.createShare(state.currentSessionKey, request, { agentId: currentAgentId });
1196
+ chatLog.addSystem(formatTuiShareResult(result));
1197
+ } catch (err) {
1198
+ const errorMessage = err instanceof Error ? err.message : String(err);
1199
+ chatLog.addSystem(`Share failed: ${errorMessage}`);
1200
+ } finally {
1201
+ tui.requestRender();
1202
+ }
1203
+ };
1204
+ const runBtwQuery = async (question) => {
1205
+ const previousStatus = state.activityStatus;
1206
+ try {
1207
+ setActivityStatus("waiting");
1208
+ state.progressMessage = "btw";
1209
+ const result = await client.btwQuery(state.currentSessionKey, question);
1210
+ if (result.error) {
1211
+ chatLog.addSystem(`BTW failed: ${result.error}`);
1212
+ return;
1213
+ }
1214
+ chatLog.addSystem(`BTW\n\n${result.text}`);
1215
+ } catch (err) {
1216
+ const errorMessage = err instanceof Error ? err.message : String(err);
1217
+ chatLog.addSystem(`BTW failed: ${errorMessage}`);
1218
+ } finally {
1219
+ state.activityStatus = previousStatus;
1220
+ renderStatus();
1221
+ tui.requestRender();
1222
+ }
1223
+ };
1224
+ const forkCurrentSession = async (rawKey) => {
1225
+ const targetKey = resolveSessionKey(rawKey?.trim() || `fork-${randomUUID()}`);
1226
+ if (targetKey === state.currentSessionKey) {
1227
+ chatLog.addSystem("Fork target must be different from the current session.");
1228
+ tui.requestRender();
1229
+ return;
1230
+ }
1231
+ const sourceSessionKey = state.currentSessionKey;
1232
+ try {
1233
+ await abortActive({ clearUi: false });
1234
+ const result = await client.forkSession(sourceSessionKey, targetKey);
1235
+ await setSession(result.sessionKey);
1236
+ chatLog.addBranchSummary({
1237
+ sourceSessionKey,
1238
+ targetSessionKey: result.sessionKey,
1239
+ rowCount: result.rowCount
1240
+ });
1241
+ } catch (err) {
1242
+ const errorMessage = err instanceof Error ? err.message : String(err);
1243
+ chatLog.addSystem(`Fork failed: ${errorMessage}`);
1244
+ } finally {
1245
+ tui.requestRender();
1246
+ }
319
1247
  };
320
1248
  const handleCtrlZ = () => {
321
1249
  if (process.platform === "win32") {
322
- chatLog.addSystem("Suspend (Ctrl+Z) is not supported on Windows.");
1250
+ chatLog.addSystem(formatSuspendUnsupportedHint(keybindings));
323
1251
  tui.requestRender();
324
1252
  return;
325
1253
  }
@@ -361,7 +1289,8 @@ async function runTui(opts) {
361
1289
  })();
362
1290
  };
363
1291
  const isAgentBusy = () => state.activeRunId != null || state.isCompacting || busyStates.has(state.activityStatus);
364
- const steerMessage = (text) => {
1292
+ let steeringInFlightForRunId = null;
1293
+ const sendSteeringToActiveRun = (text) => {
365
1294
  chatLog.addUser(text);
366
1295
  touchStreamingActivity();
367
1296
  tui.requestRender();
@@ -369,7 +1298,7 @@ async function runTui(opts) {
369
1298
  sessionKey: state.currentSessionKey,
370
1299
  message: text
371
1300
  }).then(({ ok }) => {
372
- if (!ok) chatLog.addSystem(theme.dim("Could not steer — no active run or steer failed. Press Escape to abort, or Alt+Enter to queue a follow-up."));
1301
+ if (!ok) chatLog.addSystem(theme.dim(formatSteerUnavailableHint(keybindings)));
373
1302
  else chatLog.addSystem(theme.dim("Steered — message injects at the next tool boundary (pi-style)."));
374
1303
  tui.requestRender();
375
1304
  }).catch((error) => {
@@ -378,52 +1307,117 @@ async function runTui(opts) {
378
1307
  tui.requestRender();
379
1308
  });
380
1309
  };
1310
+ const flushSteeringQueue = () => {
1311
+ if (state.exitRequested) return;
1312
+ if (state.activeRunId) return;
1313
+ const next = drainFollowUpQueue(state.steeringQueue, tuiSettings.steeringMode);
1314
+ if (next === void 0) return;
1315
+ sendMessage(next);
1316
+ };
1317
+ const steerMessage = (text) => {
1318
+ if (!state.activeRunId) {
1319
+ sendMessage(text);
1320
+ return;
1321
+ }
1322
+ if (steeringInFlightForRunId === state.activeRunId) {
1323
+ state.steeringQueue.push(text);
1324
+ chatLog.addSystem(theme.dim(`Queued steering (${state.steeringQueue.length} in queue). ${tuiSettings.steeringMode === "all" ? "All queued steering sends together after this reply." : "Next sends after this reply."}`));
1325
+ bottomBar.invalidate();
1326
+ tui.requestRender();
1327
+ return;
1328
+ }
1329
+ steeringInFlightForRunId = state.activeRunId;
1330
+ sendSteeringToActiveRun(text);
1331
+ };
381
1332
  const sendMessage = (text) => {
1333
+ if (state.activeRunId && pendingImageAttachments.length > 0) {
1334
+ chatLog.addSystem(theme.dim("Image attachments cannot be steered into an active run. Wait for this reply to finish, then send."));
1335
+ tui.requestRender();
1336
+ return;
1337
+ }
1338
+ const pendingCustomText = pendingNextTurnCustomMessages.splice(0).join("\n\n").trim();
1339
+ const messageText = [text, pendingCustomText].filter(Boolean).join("\n\n");
1340
+ const attachments = pendingImageAttachments;
1341
+ pendingImageAttachments = [];
382
1342
  if (state.isCompacting) {
383
- state.compactionQueue.push(text);
1343
+ state.compactionQueue.push(messageText);
1344
+ if (attachments.length > 0) pendingImageAttachments.unshift(...attachments);
384
1345
  chatLog.addSystem(theme.dim(`Queued during compaction (${state.compactionQueue.length}). Sends when compact finishes.`));
385
1346
  bottomBar.invalidate();
386
1347
  tui.requestRender();
387
1348
  return;
388
1349
  }
389
1350
  if (state.activeRunId) {
390
- chatLog.addSystem("A response is still in progress. Press Enter to steer, Alt+Enter to queue, or Escape to abort.");
1351
+ chatLog.addSystem(formatBusyResponseHint(keybindings));
1352
+ if (pendingCustomText) pendingNextTurnCustomMessages.unshift(pendingCustomText);
1353
+ if (attachments.length > 0) pendingImageAttachments.unshift(...attachments);
391
1354
  tui.requestRender();
392
1355
  return;
393
1356
  }
394
- chatLog.addUser(text);
1357
+ chatLog.addUser(userDisplayContentForAttachments(text, attachments));
1358
+ sessionSnapshot.appendMessage("user", messageText);
1359
+ lastRetryMessageText = messageText;
1360
+ markRunSending(state);
395
1361
  setActivityStatus("sending");
396
1362
  touchStreamingActivity();
397
1363
  tui.requestRender();
398
1364
  client.sendChat({
399
1365
  sessionKey: state.currentSessionKey,
400
- message: text,
1366
+ message: messageText,
1367
+ attachments: attachments.length > 0 ? attachments : void 0,
401
1368
  thinking: opts.thinking
402
1369
  }).catch((error) => {
403
1370
  const errorMessage = error instanceof Error ? error.message : String(error);
1371
+ if (attachments.length > 0) pendingImageAttachments.unshift(...attachments);
404
1372
  chatLog.addSystem(`❌ Failed to send: ${errorMessage}`);
405
1373
  setActivityStatus("idle");
406
1374
  tui.requestRender();
407
1375
  });
408
1376
  };
409
- const runCompaction = async () => {
410
- if (state.isCompacting) return;
1377
+ sendExtensionUserMessage = (content, options) => {
1378
+ const text = extensionUserMessageContentToText(content).trim();
1379
+ if (!text) throw new Error("sendUserMessage requires text content.");
1380
+ if (!state.activeRunId) {
1381
+ sendMessage(text);
1382
+ return;
1383
+ }
1384
+ if (options?.deliverAs === "steer") {
1385
+ steerMessage(text);
1386
+ return;
1387
+ }
1388
+ if (options?.deliverAs === "followUp") {
1389
+ state.messageFollowUpQueue.push(text);
1390
+ chatLog.addSystem(theme.dim(`Queued follow-up (${state.messageFollowUpQueue.length} in queue). ${tuiSettings.followUpMode === "all" ? "All queued messages send together when this reply finishes." : "Next sends when this reply finishes."}`));
1391
+ bottomBar.invalidate();
1392
+ tui.requestRender();
1393
+ return;
1394
+ }
1395
+ throw new Error("Agent is busy. Use deliverAs: \"steer\" or \"followUp\".");
1396
+ };
1397
+ const runCompaction = async (instructions, callbacks) => {
1398
+ if (state.isCompacting) return void 0;
411
1399
  state.isCompacting = true;
412
1400
  setActivityStatus("compacting");
413
- chatLog.addSystem(theme.dim("Compacting session…"));
1401
+ chatLog.addSystem(theme.dim(instructions ? `Compacting session with instructions: ${instructions}` : "Compacting session…"));
414
1402
  tui.requestRender();
415
1403
  try {
416
- const result = await client.compactSession(state.currentSessionKey, { force: true });
417
- chatLog.addSystem(result.summary ?? (result.compacted ? "Session compacted" : "Nothing to compact"));
1404
+ const result = await client.compactSession(state.currentSessionKey, {
1405
+ force: true,
1406
+ instructions
1407
+ });
418
1408
  if (result.compacted) {
419
- assembler.clear();
420
- clearPendingToolCallIds();
1409
+ clearSeenStreamEvents();
421
1410
  state.historyLoaded = false;
422
1411
  await loadSessionHistory();
423
- }
1412
+ chatLog.addCompactionSummary(result);
1413
+ } else chatLog.addSystem(formatTuiCompactionResult(result));
1414
+ callbacks?.onComplete?.(result);
1415
+ return result;
424
1416
  } catch (error) {
425
1417
  const errorMessage = error instanceof Error ? error.message : String(error);
426
1418
  chatLog.addSystem(`❌ Compaction failed: ${errorMessage}`);
1419
+ callbacks?.onError?.(error instanceof Error ? error : new Error(errorMessage));
1420
+ return;
427
1421
  } finally {
428
1422
  state.isCompacting = false;
429
1423
  setActivityStatus("idle");
@@ -439,7 +1433,21 @@ async function runTui(opts) {
439
1433
  saveTuiSettings(tuiSettings);
440
1434
  state.showThinking = tuiSettings.showThinking;
441
1435
  state.toolsExpanded = tuiSettings.toolsExpanded;
1436
+ chatLog.setShowThinking(tuiSettings.showThinking);
442
1437
  chatLog.setToolsExpanded(tuiSettings.toolsExpanded);
1438
+ chatLog.setToolImageOptions({
1439
+ showImages: tuiSettings.showImages,
1440
+ imageWidthCells: tuiSettings.imageWidthCells,
1441
+ cwd: process.cwd()
1442
+ });
1443
+ tui.setShowHardwareCursor(tuiSettings.showHardwareCursor);
1444
+ tui.setClearOnShrink(tuiSettings.clearOnShrink);
1445
+ defaultEditor.setPaddingX(tuiSettings.editorPaddingX);
1446
+ defaultEditor.setAutocompleteMaxVisible(tuiSettings.autocompleteMaxVisible);
1447
+ if (editor !== defaultEditor) {
1448
+ editor.setPaddingX?.(tuiSettings.editorPaddingX);
1449
+ editor.setAutocompleteMaxVisible?.(tuiSettings.autocompleteMaxVisible);
1450
+ }
443
1451
  applyThemeById(tuiSettings.theme);
444
1452
  header.invalidate();
445
1453
  updateEditorBorderColor();
@@ -452,74 +1460,189 @@ async function runTui(opts) {
452
1460
  updateEditorBorderColor();
453
1461
  tui.requestRender();
454
1462
  };
455
- const reloadKeybindings = () => {
1463
+ const reloadTuiRuntime = async () => {
1464
+ if (state.activeRunId) throw new Error("Wait for the current response to finish before reloading.");
1465
+ if (state.isCompacting) throw new Error("Wait for compaction to finish before reloading.");
456
1466
  keybindings.reload();
457
1467
  setKeybindings(keybindings);
1468
+ applyTuiSettings(loadTuiSettings());
1469
+ extensionRuntime.dispose();
1470
+ await extensionRuntime.activate();
1471
+ editor.setAutocompleteProvider?.(extensionRuntime.autocompleteProvider);
1472
+ setEditorExtensionShortcut();
1473
+ updateHeader();
1474
+ updateFooter();
458
1475
  tui.requestRender();
459
1476
  };
460
1477
  const uiOverlays = {
1478
+ openModelPicker: (_initialSearch) => {},
1479
+ openAgentPicker: () => {},
461
1480
  openSessionPicker: () => {},
1481
+ openSessionTree: () => {},
1482
+ openTranscriptTree: () => {},
1483
+ openUserMessageFork: () => {},
462
1484
  openScopedModels: () => {},
1485
+ openThinkingSelector: () => {},
463
1486
  openSettings: () => {},
464
- reloadKeybindings: () => reloadKeybindings()
1487
+ openProjectTrust: () => {},
1488
+ reloadKeybindings: () => reloadTuiRuntime()
1489
+ };
1490
+ const recoverCurrentStream = async () => {
1491
+ if (state.activeRunId) {
1492
+ await recoverActiveRunFromHistory("manual recover");
1493
+ return;
1494
+ }
1495
+ await loadSessionHistory({ merge: true });
1496
+ await refreshSessionInfoWithBorder();
1497
+ chatLog.addSystem(theme.dim("Reloaded persisted history; no active run to recover."));
1498
+ tui.requestRender();
1499
+ };
1500
+ const retryLastMessage = async () => {
1501
+ const message = lastRetryMessageText?.trim();
1502
+ if (!message) {
1503
+ chatLog.addSystem("No previous user message to retry.");
1504
+ return;
1505
+ }
1506
+ if (state.activeRunId) await abortActive({ clearUi: false });
1507
+ sendMessage(message);
1508
+ };
1509
+ const switchAgentSession = async (sessionKey, agentId) => {
1510
+ const previousWorkspace = state.sessionInfo.effectiveWorkspacePath?.trim();
1511
+ await setSession(sessionKey);
1512
+ await refreshStartupResources();
1513
+ if (previousWorkspace && state.sessionInfo.workingDirectoryLocked !== true) try {
1514
+ await client.patchSession(state.currentSessionKey, { workingDirectory: previousWorkspace });
1515
+ state.sessionInfo.effectiveWorkspacePath = previousWorkspace;
1516
+ state.sessionInfo.workingDirectoryLocked = true;
1517
+ await refreshSessionInfoWithBorder();
1518
+ } catch (err) {
1519
+ const errorMessage = err instanceof Error ? err.message : String(err);
1520
+ chatLog.addSystem(`Switched agent, but workspace was not copied: ${errorMessage}`);
1521
+ }
1522
+ currentAgentId = agentId;
1523
+ updateHeader();
1524
+ updateFooter();
465
1525
  };
466
1526
  const handleCommand = createTuiCommandHandler({
467
1527
  state,
468
1528
  chatLog,
469
1529
  tui,
470
- assembler,
471
1530
  isLocalMode,
472
1531
  abortActive,
473
1532
  sendMessage,
474
1533
  requestExit,
475
1534
  updateFooter,
476
1535
  keybindings,
1536
+ recoverStream: recoverCurrentStream,
1537
+ retryLastMessage,
477
1538
  uiOverlays,
1539
+ setThinkingLevel,
1540
+ setReasoningLevel,
1541
+ setVerboseLevel,
1542
+ copyLastAssistant,
1543
+ renameCurrentSession,
478
1544
  runCompaction,
1545
+ listModels: listCurrentModels,
1546
+ switchModel: switchCurrentModel,
1547
+ listSessions: () => client.listSessions(),
1548
+ listAgents: () => client.listAgents(),
1549
+ switchAgentSession,
1550
+ getSessionStats: () => client.getSessionStats(state.currentSessionKey),
1551
+ getStartupResources: () => startupResources,
1552
+ loadTranscriptTree: () => client.loadTranscriptTree(state.currentSessionKey),
1553
+ exportSession: exportCurrentSession,
1554
+ importSession: importSessionExport,
1555
+ createShare: createShareLink,
1556
+ runBtwQuery,
1557
+ forkSession: forkCurrentSession,
479
1558
  extensionSlashCommands: extensionRuntime.slashCommands,
1559
+ extensionShortcuts: extensionRuntime.shortcuts,
480
1560
  currentAgentId,
481
- setSession,
482
- resetSession: resetCurrentSession
1561
+ setSession: async (rawKey) => {
1562
+ await setSession(rawKey);
1563
+ await refreshStartupResources();
1564
+ },
1565
+ resetSession: resetCurrentSession,
1566
+ projectTrust: {
1567
+ cwd: process.cwd(),
1568
+ hasProjectResources: () => hasTrustRequiringProjectResources(process.cwd()),
1569
+ getStorePath: () => projectTrustStore.getPath(),
1570
+ getEntry: () => projectTrustStore.getEntry(process.cwd()),
1571
+ getSessionDecision: () => projectTrustSessionDecision
1572
+ },
1573
+ runLogin: (provider) => runTuiOAuthLogin(provider, {
1574
+ chatLog,
1575
+ tui,
1576
+ editor,
1577
+ openOverlay: openCommandOverlay,
1578
+ closeOverlay: closeCommandOverlay,
1579
+ keybindings
1580
+ })
483
1581
  });
484
1582
  const { runLocalShellLine } = createLocalShellRunner({
485
1583
  chatLog,
486
1584
  tui,
487
1585
  editor,
488
- openOverlay,
489
- closeOverlay,
1586
+ openOverlay: openCommandOverlay,
1587
+ closeOverlay: closeCommandOverlay,
490
1588
  pauseStdioFilter: () => stdioFilter.pause(),
491
1589
  resumeStdioFilter: () => stdioFilter.resume(),
492
1590
  runWithInheritedStdio: async (work) => {
493
1591
  await withTuiSuspended(tui, work);
1592
+ },
1593
+ keybindings,
1594
+ getCwd: () => {
1595
+ const workspace = state.sessionInfo.effectiveWorkspacePath?.trim();
1596
+ if (!workspace) throw new Error("Workspace is not loaded yet.");
1597
+ return workspace;
1598
+ },
1599
+ onComplete: async (entry) => {
1600
+ await client.appendBashExecution(state.currentSessionKey, entry).catch((err) => {
1601
+ const errorMessage = err instanceof Error ? err.message : String(err);
1602
+ chatLog.addSystem(`Bash transcript append failed: ${errorMessage}`);
1603
+ }).finally(() => {
1604
+ updateFooter();
1605
+ tui.requestRender();
1606
+ });
494
1607
  }
495
1608
  });
496
1609
  const submitBurst = createSubmitBurstCoalescer({
497
1610
  submit: createEditorSubmitHandler({
498
- editor,
1611
+ editor: {
1612
+ setText: (value) => editor.setText(value),
1613
+ addToHistory: (value) => editor.addToHistory?.(value)
1614
+ },
499
1615
  handleCommand,
500
1616
  sendMessage,
501
1617
  handleBangLine: runLocalShellLine,
502
1618
  isAgentBusy,
503
- steerWhileBusy: steerMessage
1619
+ steerWhileBusy: steerMessage,
1620
+ hasPendingAttachments: () => pendingImageAttachments.length > 0,
1621
+ defaultAttachmentMessage: "Please analyze the attached image."
504
1622
  }),
505
1623
  enabled: shouldEnableWindowsGitBashPasteFallback()
506
1624
  });
507
- editor.onSubmit = submitBurst;
1625
+ defaultEditor.onSubmit = submitBurst;
508
1626
  const flushFollowUpQueue = () => {
509
1627
  if (state.exitRequested) return;
510
1628
  if (state.activeRunId) return;
511
- const next = state.messageFollowUpQueue.shift();
1629
+ const next = drainFollowUpQueue(state.messageFollowUpQueue, tuiSettings.followUpMode);
512
1630
  if (next === void 0) return;
513
1631
  sendMessage(next);
514
1632
  };
515
1633
  const handleFollowUp = () => {
516
1634
  const text = editor.getText().trim();
517
- if (!text) return;
1635
+ if (!text && pendingImageAttachments.length === 0) return;
518
1636
  if (isAgentBusy()) {
1637
+ if (pendingImageAttachments.length > 0) {
1638
+ chatLog.addSystem(theme.dim("Image attachments cannot be queued while the agent is busy. Wait for this reply to finish, then send."));
1639
+ tui.requestRender();
1640
+ return;
1641
+ }
519
1642
  editor.addToHistory(text);
520
1643
  state.messageFollowUpQueue.push(text);
521
1644
  editor.setText("");
522
- chatLog.addSystem(theme.dim(`Queued follow-up (${state.messageFollowUpQueue.length} in queue). Next sends when this reply finishes.`));
1645
+ chatLog.addSystem(theme.dim(`Queued follow-up (${state.messageFollowUpQueue.length} in queue). ${tuiSettings.followUpMode === "all" ? "All queued messages send together when this reply finishes." : "Next sends when this reply finishes."}`));
523
1646
  bottomBar.invalidate();
524
1647
  tui.requestRender();
525
1648
  return;
@@ -527,17 +1650,17 @@ async function runTui(opts) {
527
1650
  submitBurst(text);
528
1651
  };
529
1652
  const handleDequeue = () => {
530
- if (state.messageFollowUpQueue.length === 0) {
531
- chatLog.addSystem(theme.dim("No queued messages to restore."));
1653
+ const restored = restoreQueuedMessages({
1654
+ steeringQueue: state.steeringQueue,
1655
+ followUpQueue: state.messageFollowUpQueue
1656
+ }, editor.getText());
1657
+ if (restored.restoredCount === 0) {
1658
+ chatLog.addStatus(theme.dim("No queued messages to restore."));
532
1659
  tui.requestRender();
533
1660
  return;
534
1661
  }
535
- const queued = [...state.messageFollowUpQueue];
536
- state.messageFollowUpQueue.length = 0;
537
- const current = editor.getText().trim();
538
- const combined = [queued.join("\n\n"), current].filter(Boolean).join("\n\n");
539
- editor.setText(combined);
540
- chatLog.addSystem(theme.dim(`Restored ${queued.length} queued message${queued.length > 1 ? "s" : ""} to editor.`));
1662
+ editor.setText(restored.text);
1663
+ chatLog.addStatus(theme.dim(`Restored ${restored.restoredCount} queued message${restored.restoredCount > 1 ? "s" : ""} to editor.`));
541
1664
  bottomBar.invalidate();
542
1665
  tui.requestRender();
543
1666
  };
@@ -583,17 +1706,21 @@ async function runTui(opts) {
583
1706
  const pickerSvc = {
584
1707
  tui,
585
1708
  editor,
586
- openOverlay,
587
- closeOverlay,
1709
+ openOverlay: openCommandOverlay,
1710
+ closeOverlay: closeCommandOverlay,
588
1711
  chatLog,
589
1712
  client,
590
1713
  sendMessage,
1714
+ switchModel: switchCurrentModel,
1715
+ openEditorSelector,
591
1716
  refreshSessionInfo,
592
1717
  updateHeader,
593
1718
  state,
594
1719
  setSessionKey,
1720
+ switchAgentSession,
595
1721
  clearChatForSessionSwitch,
596
1722
  loadSessionHistory,
1723
+ setEditorText: (text) => editor.setText(text),
597
1724
  setModelChoices,
598
1725
  getScopedModelRefs: () => state.scopedModelRefs,
599
1726
  setScopedModelRefs: (refs) => {
@@ -604,24 +1731,40 @@ async function runTui(opts) {
604
1731
  getTuiSettings: () => ({ ...tuiSettings }),
605
1732
  applyTuiSettings,
606
1733
  previewTheme,
607
- reloadKeybindings
1734
+ reloadKeybindings: reloadTuiRuntime,
1735
+ setThinkingLevel,
1736
+ getProjectTrustStore: () => projectTrustStore,
1737
+ getProjectTrustSessionDecision: () => projectTrustSessionDecision,
1738
+ setProjectTrustSessionDecision: (decision) => {
1739
+ projectTrustSessionDecision = decision;
1740
+ },
1741
+ keybindings
608
1742
  };
1743
+ uiOverlays.openModelPicker = (initialSearch) => void openModelPickerOverlay(pickerSvc, initialSearch);
1744
+ uiOverlays.openAgentPicker = () => void openAgentPickerOverlay(pickerSvc);
609
1745
  uiOverlays.openSessionPicker = () => void openSessionPickerOverlay(pickerSvc);
1746
+ uiOverlays.openSessionTree = () => void openSessionTreeOverlay(pickerSvc);
1747
+ uiOverlays.openTranscriptTree = () => void openTranscriptTreeOverlay(pickerSvc);
1748
+ uiOverlays.openUserMessageFork = () => void openUserMessageForkOverlay(pickerSvc);
610
1749
  uiOverlays.openScopedModels = () => void openScopedModelsOverlay(pickerSvc);
1750
+ uiOverlays.openThinkingSelector = () => openThinkingSelectorOverlay(pickerSvc);
611
1751
  uiOverlays.openSettings = () => openSettingsOverlay(pickerSvc);
1752
+ uiOverlays.openProjectTrust = () => openProjectTrustOverlay(pickerSvc);
1753
+ const showSessionTree = () => {
1754
+ uiOverlays.openTranscriptTree();
1755
+ };
612
1756
  const handleDoubleEscape = () => {
613
1757
  switch (tuiSettings.doubleEscapeAction) {
614
1758
  case "tree":
615
- chatLog.addSystem(theme.dim("Session tree is not available in xopc TUI yet."));
1759
+ showSessionTree();
616
1760
  break;
617
1761
  case "fork":
618
- chatLog.addSystem(theme.dim("Session fork is not available in xopc TUI yet."));
1762
+ uiOverlays.openUserMessageFork();
619
1763
  break;
620
1764
  default: break;
621
1765
  }
622
- tui.requestRender();
623
1766
  };
624
- editor.onEscape = () => {
1767
+ defaultEditor.onEscape = () => {
625
1768
  if (state.activeRunId) {
626
1769
  abortActive();
627
1770
  return;
@@ -635,19 +1778,20 @@ async function runTui(opts) {
635
1778
  }
636
1779
  state.lastEscapeAt = now;
637
1780
  };
638
- editor.onCtrlD = () => requestExit();
639
- editor.onAction("app.clear", handleCtrlC);
640
- editor.onAction("app.exit", () => requestExit());
641
- editor.onAction("app.suspend", handleCtrlZ);
642
- editor.onAction("app.thinking.cycle", () => {
643
- sendMessage(`/think ${nextThinkLevel(state.sessionInfo.thinkingLevel ?? opts.thinking ?? "medium")}`);
644
- updateEditorBorderColor();
1781
+ defaultEditor.onCtrlD = () => requestExit();
1782
+ defaultEditor.onAction("app.clear", handleCtrlC);
1783
+ defaultEditor.onAction("app.exit", () => requestExit());
1784
+ defaultEditor.onAction("app.suspend", handleCtrlZ);
1785
+ defaultEditor.onAction("app.thinking.cycle", () => {
1786
+ setThinkingLevel(nextThinkLevel(state.sessionInfo.thinkingLevel ?? opts.thinking ?? "medium"));
645
1787
  });
646
- editor.onAction("app.model.cycleForward", () => cycleModel("forward"));
647
- editor.onAction("app.model.cycleBackward", () => cycleModel("backward"));
648
- editor.onAction("app.model.select", () => void openModelPickerOverlay(pickerSvc));
649
- editor.onAction("app.session.resume", () => void openSessionPickerOverlay(pickerSvc));
650
- editor.onAction("app.tools.expand", () => {
1788
+ defaultEditor.onAction("app.model.cycleForward", () => cycleModel("forward"));
1789
+ defaultEditor.onAction("app.model.cycleBackward", () => cycleModel("backward"));
1790
+ defaultEditor.onAction("app.model.select", () => uiOverlays.openModelPicker());
1791
+ defaultEditor.onAction("app.session.resume", () => void openSessionPickerOverlay(pickerSvc));
1792
+ defaultEditor.onAction("app.session.tree", showSessionTree);
1793
+ defaultEditor.onAction("app.session.fork", () => uiOverlays.openUserMessageFork());
1794
+ defaultEditor.onAction("app.tools.expand", () => {
651
1795
  state.toolsExpanded = !state.toolsExpanded;
652
1796
  tuiSettings = {
653
1797
  ...tuiSettings,
@@ -658,65 +1802,95 @@ async function runTui(opts) {
658
1802
  setActivityStatus(state.toolsExpanded ? "tools expanded" : "tools collapsed");
659
1803
  tui.requestRender();
660
1804
  });
661
- editor.onAction("app.thinking.toggle", () => {
1805
+ defaultEditor.onAction("app.thinking.toggle", () => {
662
1806
  state.showThinking = !state.showThinking;
663
1807
  tuiSettings = {
664
1808
  ...tuiSettings,
665
1809
  showThinking: state.showThinking
666
1810
  };
667
1811
  saveTuiSettings(tuiSettings);
1812
+ chatLog.setShowThinking(state.showThinking);
668
1813
  updateFooter();
669
1814
  tui.requestRender();
670
1815
  });
671
- editor.onAction("app.editor.external", openExternalEditor);
672
- editor.onPasteImage = () => {
1816
+ defaultEditor.onAction("app.editor.external", openExternalEditor);
1817
+ defaultEditor.onPasteImage = () => {
673
1818
  (async () => {
674
- const filePath = await saveClipboardImageToTempFile();
675
- if (!filePath) return;
676
- editor.insertTextAtCursor(filePath);
677
- chatLog.addSystem(theme.dim(`Pasted image path: ${filePath}`));
1819
+ const image = await readClipboardImage();
1820
+ if (!image) {
1821
+ chatLog.addStatus(theme.dim("No image found on clipboard."));
1822
+ tui.requestRender();
1823
+ return;
1824
+ }
1825
+ if (pendingImageAttachments.length >= 10) {
1826
+ chatLog.addSystem(`Attachment limit reached (10). Send or clear the current draft first.`);
1827
+ tui.requestRender();
1828
+ return;
1829
+ }
1830
+ if (image.bytes.byteLength > 33554432) {
1831
+ chatLog.addSystem(`Clipboard image is too large (${image.bytes.byteLength} bytes; max ${MAX_WEBCHAT_ATTACHMENT_FILE_BYTES}).`);
1832
+ tui.requestRender();
1833
+ return;
1834
+ }
1835
+ const ext = extensionForImageMimeType(image.mimeType) ?? "png";
1836
+ const name = `clipboard-${pendingImageAttachments.length + 1}.${ext}`;
1837
+ pendingImageAttachments.push({
1838
+ type: "image",
1839
+ mimeType: image.mimeType,
1840
+ data: Buffer.from(image.bytes).toString("base64"),
1841
+ name,
1842
+ size: image.bytes.byteLength
1843
+ });
1844
+ chatLog.addStatus(theme.dim(`Attached image: ${name} (${pendingImageAttachments.length} pending). Send a message to include it.`));
678
1845
  tui.requestRender();
679
1846
  })();
680
1847
  };
681
- editor.onAction("app.message.followUp", handleFollowUp);
682
- editor.onAction("app.message.dequeue", handleDequeue);
1848
+ defaultEditor.onAction("app.message.followUp", handleFollowUp);
1849
+ defaultEditor.onAction("app.message.dequeue", handleDequeue);
683
1850
  streamWatchdogId = setInterval(() => {
684
- if (!state.activeRunId) return;
685
- if (!busyStates.has(state.activityStatus)) return;
686
- if (Date.now() - lastStreamActivityAt < 3e4) return;
687
- const rid = state.activeRunId;
688
- const finalText = assembler.finalize(rid, state.showThinking);
689
- if (finalText) chatLog.finalizeAssistant(finalText, rid);
690
- chatLog.addSystem("⚠️ No stream activity for 30s; UI reset (connection may have stalled). Retry or check gateway.");
691
- state.activeRunId = null;
692
- setActivityStatus("idle");
693
- refreshSessionInfoWithBorder().finally(() => {
694
- updateFooter();
695
- tui.requestRender();
696
- });
697
- flushFollowUpQueue();
1851
+ const now = Date.now();
1852
+ if (!isActiveRunStreamStale(state, now, 3e4)) return;
1853
+ if (!markActiveRunStalled(state, now)) return;
1854
+ chatLog.addSystem(theme.dim("No stream activity for 30s; preserving active run and reloading persisted history."));
1855
+ setActivityStatus("stalled");
1856
+ recoverActiveRunFromHistory("stream watchdog");
698
1857
  tui.requestRender();
699
1858
  }, 5e3);
700
1859
  const onAgentRunEnded = () => {
701
1860
  state.progressMessage = null;
1861
+ steeringInFlightForRunId = null;
702
1862
  refreshSessionInfoWithBorder().finally(() => {
703
1863
  updateFooter();
704
1864
  tui.requestRender();
705
1865
  });
1866
+ flushSteeringQueue();
706
1867
  flushFollowUpQueue();
707
1868
  };
708
1869
  client.onEvent = (evt) => {
709
1870
  const data = evt.data ?? {};
710
- dispatchAgentSSE(evt.event, data, state, chatLog, assembler, tui, setActivityStatus, touchStreamingActivity, onAgentRunEnded);
1871
+ dispatchAgentEvent(evt.event, data, state, chatLog, tui, setActivityStatus, touchStreamingActivity, onAgentRunEnded, (message) => sessionSnapshot.appendMessage("assistant", assistantMessagePlainText(message)), evt.source);
711
1872
  };
712
1873
  client.onConnected = () => {
713
1874
  state.isConnected = true;
714
1875
  setConnectionStatus(isLocalMode ? "local ready" : "gateway connected");
715
1876
  touchStreamingActivity();
716
1877
  (async () => {
1878
+ try {
1879
+ await applyStartupWorkingDirectory();
1880
+ } catch (err) {
1881
+ const errorMessage = err instanceof Error ? err.message : String(err);
1882
+ chatLog.addSystem(`Working directory not changed: ${errorMessage}`);
1883
+ }
717
1884
  await refreshSessionInfoWithBorder();
718
1885
  await refreshModelChoices();
719
- await loadSessionHistory();
1886
+ await refreshStartupResources();
1887
+ await loadSessionHistory({ merge: true });
1888
+ showStartupCardOnce();
1889
+ if (state.activeRunId) recoverActiveRunFromHistory("broadcast reconnect");
1890
+ if (!projectTrustPromptShown && isLocalMode && projectTrustSessionDecision === null && hasTrustRequiringProjectResources(process.cwd()) && projectTrustStore.get(process.cwd()) === null) {
1891
+ projectTrustPromptShown = true;
1892
+ chatLog.addSystem("Project-local xopc resources detected. Use /trust to trust this folder, trust a parent folder, or keep it untrusted.");
1893
+ }
720
1894
  updateHeader();
721
1895
  updateFooter();
722
1896
  tui.requestRender();
@@ -743,6 +1917,8 @@ async function runTui(opts) {
743
1917
  client.onGap = (info) => {
744
1918
  chatLog.addSystem(`⚠️ Event gap: expected ${info.expected}, received ${info.received}. Some updates may be missing.`);
745
1919
  setConnectionStatus(`event gap: expected ${info.expected}, got ${info.received}`);
1920
+ if (state.activeRunId) recoverActiveRunFromHistory("broadcast event gap");
1921
+ else loadSessionHistory({ merge: true });
746
1922
  tui.requestRender();
747
1923
  };
748
1924
  const sigintHandler = () => handleCtrlC();