@xopcai/xopc 0.0.117 → 0.0.119

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 (590) hide show
  1. package/README.md +26 -24
  2. package/README.zh-CN.md +46 -42
  3. package/dist/browser-ext/manifest.json +1 -1
  4. package/dist/extensions/telegram/xopc.extension.json +1 -1
  5. package/dist/gateway/static/root/assets/{agent-avatar-dicebear-BBLhJ2C6.js → agent-avatar-dicebear-CU8J6zou.js} +1 -1
  6. package/dist/gateway/static/root/assets/agents-B0hkpLhP.js +2 -0
  7. package/dist/gateway/static/root/assets/app-management-settings-panel-B9vfYoEr.js +1 -0
  8. package/dist/gateway/static/root/assets/appearance-settings-ClOzIO24.js +1 -0
  9. package/dist/gateway/static/root/assets/{apps-page-DdDx0V4z.js → apps-page-DU0dz9Zo.js} +1 -1
  10. package/dist/gateway/static/root/assets/{archive-plugin-DZsVqMhU.js → archive-plugin-BkVIgZzA.js} +1 -1
  11. package/dist/gateway/static/root/assets/{attachment-load-CIol6JWX.js → attachment-load-CaCMWh1D.js} +1 -1
  12. package/dist/gateway/static/root/assets/automation-suggestion-card-DhGDpKP3.js +1 -0
  13. package/dist/gateway/static/root/assets/automations-page-CTedroVo.js +1 -0
  14. package/dist/gateway/static/root/assets/{binary-plugins-B3UauMfp.js → binary-plugins-B4TO_bsn.js} +1 -1
  15. package/dist/gateway/static/root/assets/{block-editor-2HJoFchH.js → block-editor-DJRWwWNI.js} +6 -6
  16. package/dist/gateway/static/root/assets/browser-settings-page-FCDwOOBK.js +8 -0
  17. package/dist/gateway/static/root/assets/capability-presets-api-Befi89CL.js +1 -0
  18. package/dist/gateway/static/root/assets/capability-presets-settings-panel-_G8eb2vJ.js +1 -0
  19. package/dist/gateway/static/root/assets/channel-recipient-api-BNSuJb5f.js +1 -0
  20. package/dist/gateway/static/root/assets/channels-settings-C3d5JBJX.js +1 -0
  21. package/dist/gateway/static/root/assets/cn-BQ_8x0bT.js +1 -0
  22. package/dist/gateway/static/root/assets/connectors-page-yaUNvt5u.js +2 -0
  23. package/dist/gateway/static/root/assets/cron-expression-B3B1eqnr.js +2 -0
  24. package/dist/gateway/static/root/assets/dreaming-settings-DNrdg1Ve.js +1 -0
  25. package/dist/gateway/static/root/assets/{extension-debug-page-DX5WRE_t.js → extension-debug-page-DYh402XV.js} +1 -1
  26. package/dist/gateway/static/root/assets/{extension-page-Buah7Bw-.js → extension-page-Cr_TizrN.js} +1 -1
  27. package/dist/gateway/static/root/assets/{extension-settings-page-DuroLVnf.js → extension-settings-page-BU1KoKRj.js} +1 -1
  28. package/dist/gateway/static/root/assets/{fetch-B5zdl27C.js → fetch-Y7AEX4H3.js} +1 -1
  29. package/dist/gateway/static/root/assets/format-cron-label-arqgGlVV.js +1 -0
  30. package/dist/gateway/static/root/assets/{gateway-config-api-gT4ZhE7h.js → gateway-config-api-RbMmAOpX.js} +1 -1
  31. package/dist/gateway/static/root/assets/gateway-settings-C79wkXef.js +1 -0
  32. package/dist/gateway/static/root/assets/{gateway-startup-retry-B3kL8KGY.js → gateway-startup-retry-DiD_Tx4N.js} +1 -1
  33. package/dist/gateway/static/root/assets/goal-detail-page-9paXuHdo.js +1 -0
  34. package/dist/gateway/static/root/assets/{goals-config-api-AR-fVh0P.js → goals-config-api-DqxVi0p5.js} +1 -1
  35. package/dist/gateway/static/root/assets/{goals-page-Cpb21ezg.js → goals-page-CS0R-Af2.js} +2 -2
  36. package/dist/gateway/static/root/assets/goals-settings-CSuzZ8Ae.js +1 -0
  37. package/dist/gateway/static/root/assets/heartbeat-settings-DXPaYJm3.js +1 -0
  38. package/dist/gateway/static/root/assets/index-BoKafJIZ.js +191 -0
  39. package/dist/gateway/static/root/assets/index-CArhCcYn.css +1 -0
  40. package/dist/gateway/static/root/assets/keyboard-shortcuts-settings-Dvg53qnd.js +1 -0
  41. package/dist/gateway/static/root/assets/{logs-page-DefCgF4o.js → logs-page-DLXPcksQ.js} +2 -2
  42. package/dist/gateway/static/root/assets/{markdown-split-ChbR9LGO.js → markdown-split-CpHxbtWJ.js} +1 -1
  43. package/dist/gateway/static/root/assets/{media-plugins-B82oP80n.js → media-plugins-SFPQRSxq.js} +1 -1
  44. package/dist/gateway/static/root/assets/messages-CrDHEbss.js +3 -0
  45. package/dist/gateway/static/root/assets/models-hub-panel-BDF2iyRk.js +2 -0
  46. package/dist/gateway/static/root/assets/note-detail-page-CSb_hwig.js +2 -0
  47. package/dist/gateway/static/root/assets/{note-image-lightbox-CDknITM3.js → note-image-lightbox-BUYURRgn.js} +1 -1
  48. package/dist/gateway/static/root/assets/notes-page-BsIBSFyZ.js +1 -0
  49. package/dist/gateway/static/root/assets/{preview-open-alternatives-DV3xQsWB.js → preview-open-alternatives-BHz9iWYA.js} +1 -1
  50. package/dist/gateway/static/root/assets/remote-access-hub-CwzSovcS.js +1 -0
  51. package/dist/gateway/static/root/assets/{save-bar-controls-BODCXnvY.js → save-bar-controls-CefkOlRg.js} +1 -1
  52. package/dist/gateway/static/root/assets/schedule-field-CmTRoOcE.js +1 -0
  53. package/dist/gateway/static/root/assets/{schema-form-qtfEI6QM.js → schema-form-FMKv1vGu.js} +1 -1
  54. package/dist/gateway/static/root/assets/sessions-page-PHmX-NmA.js +1 -0
  55. package/dist/gateway/static/root/assets/settings-advanced-gate-BRAeKJN4.js +1 -0
  56. package/dist/gateway/static/root/assets/{settings-collapsible-section-BHZKjVcS.js → settings-collapsible-section-BouO6JTi.js} +1 -1
  57. package/dist/gateway/static/root/assets/{settings-form-section-5i35D-J1.js → settings-form-section-D-4lBl6X.js} +1 -1
  58. package/dist/gateway/static/root/assets/settings-page-KKrbFjy8.js +1 -0
  59. package/dist/gateway/static/root/assets/settings-page-layout-BJ4Gsef5.js +1 -0
  60. package/dist/gateway/static/root/assets/setup-status-panel-CrUjHPQo.js +1 -0
  61. package/dist/gateway/static/root/assets/{share-preview-page-B0H63tDv.js → share-preview-page-BDy2btRN.js} +1 -1
  62. package/dist/gateway/static/root/assets/shares-settings-B18OBmH5.js +1 -0
  63. package/dist/gateway/static/root/assets/skill-reload-api-C28-2uKQ.js +1 -0
  64. package/dist/gateway/static/root/assets/skills-page-Bm2ebkwl.js +2 -0
  65. package/dist/gateway/static/root/assets/system-settings-panel-CRngrlnZ.js +1 -0
  66. package/dist/gateway/static/root/assets/typed-models-lib-BltBc0b-.js +1 -0
  67. package/dist/gateway/static/root/assets/{use-channel-catalog-BCjP_VHb.js → use-channel-catalog-CjN-51e6.js} +1 -1
  68. package/dist/gateway/static/root/assets/user-profile-settings-panel-DJ1dKwZy.js +1 -0
  69. package/dist/gateway/static/root/assets/utils-B5M5-YvK.js +1 -0
  70. package/dist/gateway/static/root/assets/voice-api-key-field-CeEevm7z.js +1 -0
  71. package/dist/gateway/static/root/assets/{voice-player-store-BlF9V05n.js → voice-player-store-B7ykUlHM.js} +1 -1
  72. package/dist/gateway/static/root/assets/workflow-run-setup-panel-C4PzUQjB.js +3 -0
  73. package/dist/gateway/static/root/assets/workflows-page-BL84_-Ky.js +18 -0
  74. package/dist/gateway/static/root/index.html +6 -7
  75. package/dist/package.js +1 -1
  76. package/dist/src/agent/agent-manager.d.ts +4 -5
  77. package/dist/src/agent/agent-manager.js +6 -9
  78. package/dist/src/agent/agent-manager.js.map +1 -1
  79. package/dist/src/agent/agent-scope.js +0 -2
  80. package/dist/src/agent/agent-scope.js.map +1 -1
  81. package/dist/src/agent/background-review/prompts.d.ts +2 -2
  82. package/dist/src/agent/background-review/prompts.js +2 -2
  83. package/dist/src/agent/background-review/prompts.js.map +1 -1
  84. package/dist/src/agent/background-review/settings.d.ts +1 -1
  85. package/dist/src/agent/background-review/settings.js +7 -8
  86. package/dist/src/agent/background-review/settings.js.map +1 -1
  87. package/dist/src/agent/bootstrap/bootstrap-cache.d.ts +1 -0
  88. package/dist/src/agent/bootstrap/bootstrap-cache.js +4 -3
  89. package/dist/src/agent/bootstrap/bootstrap-cache.js.map +1 -1
  90. package/dist/src/agent/bootstrap/bootstrap-files.d.ts +4 -0
  91. package/dist/src/agent/bootstrap/bootstrap-files.js +4 -3
  92. package/dist/src/agent/bootstrap/bootstrap-files.js.map +1 -1
  93. package/dist/src/agent/bootstrap/filter-bootstrap-files.js +4 -2
  94. package/dist/src/agent/bootstrap/filter-bootstrap-files.js.map +1 -1
  95. package/dist/src/agent/bootstrap/load-bootstrap-files.d.ts +2 -1
  96. package/dist/src/agent/bootstrap/load-bootstrap-files.js +17 -16
  97. package/dist/src/agent/bootstrap/load-bootstrap-files.js.map +1 -1
  98. package/dist/src/agent/bootstrap/types.d.ts +1 -1
  99. package/dist/src/agent/context/workspace-templates/AGENTS.md +1 -1
  100. package/dist/src/agent/context/workspace.d.ts +4 -2
  101. package/dist/src/agent/context/workspace.js +5 -4
  102. package/dist/src/agent/context/workspace.js.map +1 -1
  103. package/dist/src/agent/embedded/run-for-session.js +106 -15
  104. package/dist/src/agent/embedded/run-for-session.js.map +1 -1
  105. package/dist/src/agent/fallback/candidates.d.ts +0 -8
  106. package/dist/src/agent/fallback/candidates.js +10 -11
  107. package/dist/src/agent/fallback/candidates.js.map +1 -1
  108. package/dist/src/agent/index.js +1 -1
  109. package/dist/src/agent/lifecycle/handlers/compaction.d.ts +1 -3
  110. package/dist/src/agent/lifecycle/handlers/compaction.js +1 -16
  111. package/dist/src/agent/lifecycle/handlers/compaction.js.map +1 -1
  112. package/dist/src/agent/lifecycle/progress.d.ts +0 -1
  113. package/dist/src/agent/lifecycle/progress.js +1 -6
  114. package/dist/src/agent/lifecycle/progress.js.map +1 -1
  115. package/dist/src/agent/lifecycle/timeout-wrapper.d.ts +1 -2
  116. package/dist/src/agent/lifecycle/timeout-wrapper.js +1 -7
  117. package/dist/src/agent/lifecycle/timeout-wrapper.js.map +1 -1
  118. package/dist/src/agent/memory/builtin-memory-store.d.ts +4 -2
  119. package/dist/src/agent/memory/builtin-memory-store.js +11 -6
  120. package/dist/src/agent/memory/builtin-memory-store.js.map +1 -1
  121. package/dist/src/agent/memory/builtin-provider.js +36 -7
  122. package/dist/src/agent/memory/builtin-provider.js.map +1 -1
  123. package/dist/src/agent/memory/candidate-extractor.d.ts +6 -0
  124. package/dist/src/agent/memory/candidate-extractor.js +60 -0
  125. package/dist/src/agent/memory/candidate-extractor.js.map +1 -0
  126. package/dist/src/agent/memory/manager.d.ts +2 -1
  127. package/dist/src/agent/memory/manager.js +27 -3
  128. package/dist/src/agent/memory/manager.js.map +1 -1
  129. package/dist/src/agent/memory/memory-config.js +3 -0
  130. package/dist/src/agent/memory/memory-config.js.map +1 -1
  131. package/dist/src/agent/memory/prefetch-coordinator.js.map +1 -1
  132. package/dist/src/agent/memory/types.d.ts +27 -4
  133. package/dist/src/agent/middleware/self-verify.d.ts +0 -1
  134. package/dist/src/agent/middleware/self-verify.js +0 -2
  135. package/dist/src/agent/middleware/self-verify.js.map +1 -1
  136. package/dist/src/agent/models/index.d.ts +1 -1
  137. package/dist/src/agent/models/manager.d.ts +4 -20
  138. package/dist/src/agent/models/manager.js +9 -126
  139. package/dist/src/agent/models/manager.js.map +1 -1
  140. package/dist/src/agent/orchestration/agent-orchestrator.d.ts +0 -4
  141. package/dist/src/agent/orchestration/agent-orchestrator.js +1 -9
  142. package/dist/src/agent/orchestration/agent-orchestrator.js.map +1 -1
  143. package/dist/src/agent/prompt/memory/index.d.ts +4 -2
  144. package/dist/src/agent/prompt/memory/index.js +18 -12
  145. package/dist/src/agent/prompt/memory/index.js.map +1 -1
  146. package/dist/src/agent/prompt/sections/memory-skills.js +1 -1
  147. package/dist/src/agent/prompt/sections/memory-skills.js.map +1 -1
  148. package/dist/src/agent/prompt/sections/tooling.js +2 -2
  149. package/dist/src/agent/prompt/sections/tooling.js.map +1 -1
  150. package/dist/src/agent/prompt/service-prompt-builder.d.ts +0 -1
  151. package/dist/src/agent/prompt/service-prompt-builder.js +4 -31
  152. package/dist/src/agent/prompt/service-prompt-builder.js.map +1 -1
  153. package/dist/src/agent/prompt/subagent-context.js +1 -1
  154. package/dist/src/agent/prompt/subagent-context.js.map +1 -1
  155. package/dist/src/agent/prompt/types.d.ts +1 -1
  156. package/dist/src/agent/reply/post-compaction-context.js +1 -3
  157. package/dist/src/agent/reply/post-compaction-context.js.map +1 -1
  158. package/dist/src/agent/reply/startup-context.js +1 -5
  159. package/dist/src/agent/reply/startup-context.js.map +1 -1
  160. package/dist/src/agent/service.d.ts +4 -12
  161. package/dist/src/agent/service.js +10 -48
  162. package/dist/src/agent/service.js.map +1 -1
  163. package/dist/src/agent/service.types.d.ts +2 -2
  164. package/dist/src/agent/session/session-config-service.d.ts +11 -11
  165. package/dist/src/agent/session/session-config-service.js +14 -14
  166. package/dist/src/agent/session/session-config-service.js.map +1 -1
  167. package/dist/src/agent/session/session-inspector.js +3 -2
  168. package/dist/src/agent/session/session-inspector.js.map +1 -1
  169. package/dist/src/agent/starter-agents.js +12 -12
  170. package/dist/src/agent/starter-agents.js.map +1 -1
  171. package/dist/src/agent/tools/automation-tool.d.ts +14 -0
  172. package/dist/src/agent/tools/automation-tool.js +102 -0
  173. package/dist/src/agent/tools/automation-tool.js.map +1 -0
  174. package/dist/src/agent/tools/curated-memory-tool.js +57 -2
  175. package/dist/src/agent/tools/curated-memory-tool.js.map +1 -1
  176. package/dist/src/agent/tools/delegate-tool.js +1 -1
  177. package/dist/src/agent/tools/delegate-tool.js.map +1 -1
  178. package/dist/src/agent/tools/factory.d.ts +3 -3
  179. package/dist/src/agent/tools/factory.js +2 -2
  180. package/dist/src/agent/tools/factory.js.map +1 -1
  181. package/dist/src/agent/tools/index.d.ts +1 -1
  182. package/dist/src/agent/tools/index.js +2 -2
  183. package/dist/src/agent/tools/web-extract.js +6 -8
  184. package/dist/src/agent/tools/web-extract.js.map +1 -1
  185. package/dist/src/agent-manifest/index.js +2 -2
  186. package/dist/src/agent-manifest/resolver.d.ts +4 -2
  187. package/dist/src/agent-manifest/resolver.js +6 -3
  188. package/dist/src/agent-manifest/resolver.js.map +1 -1
  189. package/dist/src/agent-manifest/schema.d.ts +238 -0
  190. package/dist/src/agent-manifest/schema.js +16 -5
  191. package/dist/src/agent-manifest/schema.js.map +1 -1
  192. package/dist/src/agent-manifest/validator.d.ts +3 -2
  193. package/dist/src/agent-manifest/validator.js +2 -1
  194. package/dist/src/agent-manifest/validator.js.map +1 -1
  195. package/dist/src/ai-assist/text-assist.d.ts +1 -1
  196. package/dist/src/ai-assist/text-assist.js +56 -0
  197. package/dist/src/ai-assist/text-assist.js.map +1 -1
  198. package/dist/src/auth/profiles/store.js.map +1 -1
  199. package/dist/src/automations/api/routes.d.ts +3 -0
  200. package/dist/src/automations/api/routes.js +193 -0
  201. package/dist/src/automations/api/routes.js.map +1 -0
  202. package/dist/src/automations/domain/index.d.ts +3 -0
  203. package/dist/src/automations/domain/index.js +3 -0
  204. package/dist/src/automations/domain/schedule.d.ts +4 -0
  205. package/dist/src/automations/domain/schedule.js +37 -0
  206. package/dist/src/automations/domain/schedule.js.map +1 -0
  207. package/dist/src/automations/domain/types.d.ts +160 -0
  208. package/dist/src/automations/domain/validation.d.ts +370 -0
  209. package/dist/src/automations/domain/validation.js +149 -0
  210. package/dist/src/automations/domain/validation.js.map +1 -0
  211. package/dist/src/automations/draft/automation-draft-prompt.d.ts +26 -0
  212. package/dist/src/automations/draft/automation-draft-prompt.js +127 -0
  213. package/dist/src/automations/draft/automation-draft-prompt.js.map +1 -0
  214. package/dist/src/automations/draft/automation-draft-service.d.ts +12 -0
  215. package/dist/src/automations/draft/automation-draft-service.js +135 -0
  216. package/dist/src/automations/draft/automation-draft-service.js.map +1 -0
  217. package/dist/src/automations/draft/automation-draft-validator.d.ts +99 -0
  218. package/dist/src/automations/draft/automation-draft-validator.js +105 -0
  219. package/dist/src/automations/draft/automation-draft-validator.js.map +1 -0
  220. package/dist/src/automations/draft/automation-draft.types.d.ts +40 -0
  221. package/dist/src/automations/draft/index.d.ts +3 -0
  222. package/dist/src/automations/draft/index.js +3 -0
  223. package/dist/src/automations/index.d.ts +3 -0
  224. package/dist/src/automations/index.js +8 -0
  225. package/dist/src/automations/product-events.d.ts +5 -0
  226. package/dist/src/automations/product-events.js +21 -0
  227. package/dist/src/automations/product-events.js.map +1 -0
  228. package/dist/src/automations/service/action-executor.d.ts +9 -0
  229. package/dist/src/automations/service/action-executor.js +157 -0
  230. package/dist/src/automations/service/action-executor.js.map +1 -0
  231. package/dist/src/automations/service/automation-service.d.ts +54 -0
  232. package/dist/src/automations/service/automation-service.js +404 -0
  233. package/dist/src/automations/service/automation-service.js.map +1 -0
  234. package/dist/src/automations/service/index.d.ts +2 -0
  235. package/dist/src/automations/service/index.js +3 -0
  236. package/dist/src/automations/storage/automation-repository.d.ts +6 -0
  237. package/dist/src/automations/storage/automation-repository.js +61 -0
  238. package/dist/src/automations/storage/automation-repository.js.map +1 -0
  239. package/dist/src/automations/storage/automation-run-repository.d.ts +17 -0
  240. package/dist/src/automations/storage/automation-run-repository.js +130 -0
  241. package/dist/src/automations/storage/automation-run-repository.js.map +1 -0
  242. package/dist/src/automations/storage/index.d.ts +2 -0
  243. package/dist/src/automations/storage/index.js +3 -0
  244. package/dist/src/channels/pipeline.d.ts +1 -1
  245. package/dist/src/channels/pipeline.js.map +1 -1
  246. package/dist/src/channels/plugin-types.d.ts +3 -0
  247. package/dist/src/chat-commands/agent-edit.js +0 -1
  248. package/dist/src/chat-commands/agent-edit.js.map +1 -1
  249. package/dist/src/chat-commands/builtins/model.js +2 -2
  250. package/dist/src/chat-commands/builtins/model.js.map +1 -1
  251. package/dist/src/chat-commands/builtins/thinking.js.map +1 -1
  252. package/dist/src/cli/command-catalog.js +0 -39
  253. package/dist/src/cli/command-catalog.js.map +1 -1
  254. package/dist/src/cli/command-loaders.js +0 -1
  255. package/dist/src/cli/command-loaders.js.map +1 -1
  256. package/dist/src/cli/command-manifest.d.ts +1 -1
  257. package/dist/src/cli/command-manifest.js +1 -5
  258. package/dist/src/cli/command-manifest.js.map +1 -1
  259. package/dist/src/cli/commands/agents.js +7 -6
  260. package/dist/src/cli/commands/agents.js.map +1 -1
  261. package/dist/src/cli/commands/doctor/checks/database-schema.js +1 -1
  262. package/dist/src/cli/commands/doctor/checks/{cron-health.d.ts → migrations.d.ts} +1 -1
  263. package/dist/src/cli/commands/doctor/checks/migrations.js +40 -0
  264. package/dist/src/cli/commands/doctor/checks/migrations.js.map +1 -0
  265. package/dist/src/cli/commands/doctor/checks/provider-auth.js +1 -0
  266. package/dist/src/cli/commands/doctor/checks/provider-auth.js.map +1 -1
  267. package/dist/src/cli/commands/doctor/checks/workspace-status.js +0 -1
  268. package/dist/src/cli/commands/doctor/checks/workspace-status.js.map +1 -1
  269. package/dist/src/cli/commands/doctor/flow.js +2 -2
  270. package/dist/src/cli/commands/doctor/flow.js.map +1 -1
  271. package/dist/src/cli/commands/gateway/call.js +2 -2
  272. package/dist/src/cli/commands/gateway/call.js.map +1 -1
  273. package/dist/src/cli/commands/gateway/lifecycle.js +1 -1
  274. package/dist/src/cli/commands/gateway/run-foreground.js +4 -2
  275. package/dist/src/cli/commands/gateway/run-foreground.js.map +1 -1
  276. package/dist/src/cli/commands/init.js +33 -14
  277. package/dist/src/cli/commands/init.js.map +1 -1
  278. package/dist/src/cli/commands/models.js +13 -31
  279. package/dist/src/cli/commands/models.js.map +1 -1
  280. package/dist/src/cli/commands/onboard/model.js +17 -10
  281. package/dist/src/cli/commands/onboard/model.js.map +1 -1
  282. package/dist/src/cli/commands/onboard.js +2 -2
  283. package/dist/src/cli/commands/onboard.js.map +1 -1
  284. package/dist/src/cli/commands/tui.js +26 -4
  285. package/dist/src/cli/commands/tui.js.map +1 -1
  286. package/dist/src/cli/index.d.ts +1 -0
  287. package/dist/src/cli/index.js +10 -5
  288. package/dist/src/cli/index.js.map +1 -1
  289. package/dist/src/cli/registry.js +1 -1
  290. package/dist/src/cli/registry.js.map +1 -1
  291. package/dist/src/cli/templates.d.ts +1 -1
  292. package/dist/src/cli/templates.js +1 -11
  293. package/dist/src/cli/templates.js.map +1 -1
  294. package/dist/src/cli/utils/init-workspace-core.js +2 -0
  295. package/dist/src/cli/utils/init-workspace-core.js.map +1 -1
  296. package/dist/src/commands/agents.config.d.ts +9 -0
  297. package/dist/src/commands/agents.config.js +42 -12
  298. package/dist/src/commands/agents.config.js.map +1 -1
  299. package/dist/src/config/agent-profile.js +5 -3
  300. package/dist/src/config/agent-profile.js.map +1 -1
  301. package/dist/src/config/agent-typed-models.js +3 -5
  302. package/dist/src/config/agent-typed-models.js.map +1 -1
  303. package/dist/src/config/config-surface.d.ts +3 -0
  304. package/dist/src/config/index.d.ts +0 -1
  305. package/dist/src/config/index.js +3 -3
  306. package/dist/src/config/index.js.map +1 -1
  307. package/dist/src/config/paths.d.ts +8 -10
  308. package/dist/src/config/paths.js +16 -16
  309. package/dist/src/config/paths.js.map +1 -1
  310. package/dist/src/config/profile.js +0 -1
  311. package/dist/src/config/profile.js.map +1 -1
  312. package/dist/src/config/rules.js +0 -5
  313. package/dist/src/config/rules.js.map +1 -1
  314. package/dist/src/config/schema.d.ts +45 -44
  315. package/dist/src/config/schema.js +68 -52
  316. package/dist/src/config/schema.js.map +1 -1
  317. package/dist/src/config/web-patch.d.ts +0 -12
  318. package/dist/src/config/web-patch.js +2 -29
  319. package/dist/src/config/web-patch.js.map +1 -1
  320. package/dist/src/extensions/api.d.ts +2 -0
  321. package/dist/src/extensions/api.js +10 -0
  322. package/dist/src/extensions/api.js.map +1 -1
  323. package/dist/src/extensions/extension-registry-impl.d.ts +4 -1
  324. package/dist/src/extensions/extension-registry-impl.js +8 -0
  325. package/dist/src/extensions/extension-registry-impl.js.map +1 -1
  326. package/dist/src/extensions/loader.d.ts +3 -3
  327. package/dist/src/extensions/loader.js +3 -3
  328. package/dist/src/extensions/loader.js.map +1 -1
  329. package/dist/src/extensions/sdk/testing.d.ts +2 -0
  330. package/dist/src/extensions/sdk/testing.js +7 -0
  331. package/dist/src/extensions/sdk/testing.js.map +1 -1
  332. package/dist/src/extensions/types/core.d.ts +10 -1
  333. package/dist/src/extensions/types/index.d.ts +1 -1
  334. package/dist/src/extensions/types/{phase4.d.ts → registration.d.ts} +2 -2
  335. package/dist/src/gateway/agent-builtin-tools.d.ts +1 -1
  336. package/dist/src/gateway/agent-builtin-tools.js +1 -1
  337. package/dist/src/gateway/agent-builtin-tools.js.map +1 -1
  338. package/dist/src/gateway/agents-admin.d.ts +8 -0
  339. package/dist/src/gateway/agents-admin.js +63 -34
  340. package/dist/src/gateway/agents-admin.js.map +1 -1
  341. package/dist/src/gateway/capability-presets-admin.d.ts +1 -0
  342. package/dist/src/gateway/capability-presets-admin.js +19 -10
  343. package/dist/src/gateway/capability-presets-admin.js.map +1 -1
  344. package/dist/src/gateway/chat-stream/mapper.js +9 -2
  345. package/dist/src/gateway/chat-stream/mapper.js.map +1 -1
  346. package/dist/src/gateway/dreaming-automation-reconciler.d.ts +11 -0
  347. package/dist/src/gateway/dreaming-automation-reconciler.js +105 -0
  348. package/dist/src/gateway/dreaming-automation-reconciler.js.map +1 -0
  349. package/dist/src/gateway/global-defaults-admin.d.ts +36 -0
  350. package/dist/src/gateway/global-defaults-admin.js +146 -0
  351. package/dist/src/gateway/global-defaults-admin.js.map +1 -0
  352. package/dist/src/gateway/heartbeat/service.d.ts +0 -2
  353. package/dist/src/gateway/heartbeat/service.js +0 -7
  354. package/dist/src/gateway/heartbeat/service.js.map +1 -1
  355. package/dist/src/gateway/hono/lib/config-payload.d.ts +5 -6
  356. package/dist/src/gateway/hono/lib/config-payload.js +2 -2
  357. package/dist/src/gateway/hono/lib/config-payload.js.map +1 -1
  358. package/dist/src/gateway/hono/routes/agents.js +33 -1
  359. package/dist/src/gateway/hono/routes/agents.js.map +1 -1
  360. package/dist/src/gateway/hono/routes/commands-skills.js +4 -5
  361. package/dist/src/gateway/hono/routes/commands-skills.js.map +1 -1
  362. package/dist/src/gateway/hono/routes/config-patch/misc.d.ts +1 -1
  363. package/dist/src/gateway/hono/routes/config-patch/misc.js +12 -6
  364. package/dist/src/gateway/hono/routes/config-patch/misc.js.map +1 -1
  365. package/dist/src/gateway/hono/routes/dreaming.js +27 -37
  366. package/dist/src/gateway/hono/routes/dreaming.js.map +1 -1
  367. package/dist/src/gateway/hono/routes/global-defaults.d.ts +3 -0
  368. package/dist/src/gateway/hono/routes/global-defaults.js +61 -0
  369. package/dist/src/gateway/hono/routes/global-defaults.js.map +1 -0
  370. package/dist/src/gateway/hono/routes/home.d.ts +2 -2
  371. package/dist/src/gateway/hono/routes/home.js +34 -25
  372. package/dist/src/gateway/hono/routes/home.js.map +1 -1
  373. package/dist/src/gateway/hono/routes/lazy-bundles.js +21 -9
  374. package/dist/src/gateway/hono/routes/lazy-bundles.js.map +1 -1
  375. package/dist/src/gateway/hono/routes/memory.js +75 -4
  376. package/dist/src/gateway/hono/routes/memory.js.map +1 -1
  377. package/dist/src/gateway/hono/routes/migrations.d.ts +3 -0
  378. package/dist/src/gateway/hono/routes/migrations.js +35 -0
  379. package/dist/src/gateway/hono/routes/migrations.js.map +1 -0
  380. package/dist/src/gateway/hono/routes/models.js +1 -1
  381. package/dist/src/gateway/hono/routes/public-gateway.js +2 -1
  382. package/dist/src/gateway/hono/routes/public-gateway.js.map +1 -1
  383. package/dist/src/gateway/hono/routes/sessions.js +14 -0
  384. package/dist/src/gateway/hono/routes/sessions.js.map +1 -1
  385. package/dist/src/gateway/run-loop.js +2 -0
  386. package/dist/src/gateway/run-loop.js.map +1 -1
  387. package/dist/src/gateway/security/operator-scopes.js +5 -1
  388. package/dist/src/gateway/security/operator-scopes.js.map +1 -1
  389. package/dist/src/gateway/service/config-coordinator.d.ts +4 -4
  390. package/dist/src/gateway/service/config-coordinator.js +14 -8
  391. package/dist/src/gateway/service/config-coordinator.js.map +1 -1
  392. package/dist/src/gateway/service/marketplace-service.d.ts +4 -4
  393. package/dist/src/gateway/service/marketplace-service.js +11 -7
  394. package/dist/src/gateway/service/marketplace-service.js.map +1 -1
  395. package/dist/src/gateway/service/sessions-api.d.ts +2 -1
  396. package/dist/src/gateway/service/sessions-api.js +6 -1
  397. package/dist/src/gateway/service/sessions-api.js.map +1 -1
  398. package/dist/src/gateway/service.d.ts +7 -3
  399. package/dist/src/gateway/service.js +61 -27
  400. package/dist/src/gateway/service.js.map +1 -1
  401. package/dist/src/goals/goal-service.js +45 -4
  402. package/dist/src/goals/goal-service.js.map +1 -1
  403. package/dist/src/infra/update-restart.js +1 -1
  404. package/dist/src/migrations/config/default-capability-preset.d.ts +10 -0
  405. package/dist/src/migrations/config/default-capability-preset.js +135 -0
  406. package/dist/src/migrations/config/default-capability-preset.js.map +1 -0
  407. package/dist/src/migrations/index.d.ts +4 -0
  408. package/dist/src/migrations/index.js +4 -0
  409. package/dist/src/migrations/registry.d.ts +8 -0
  410. package/dist/src/migrations/registry.js +18 -0
  411. package/dist/src/migrations/registry.js.map +1 -0
  412. package/dist/src/migrations/runner.d.ts +17 -0
  413. package/dist/src/migrations/runner.js +191 -0
  414. package/dist/src/migrations/runner.js.map +1 -0
  415. package/dist/src/migrations/types.d.ts +34 -0
  416. package/dist/src/notes/service.js +27 -2
  417. package/dist/src/notes/service.js.map +1 -1
  418. package/dist/src/providers/index.d.ts +4 -5
  419. package/dist/src/providers/index.js +16 -16
  420. package/dist/src/providers/index.js.map +1 -1
  421. package/dist/src/providers/model-registry.d.ts +0 -1
  422. package/dist/src/providers/model-registry.js +0 -3
  423. package/dist/src/providers/model-registry.js.map +1 -1
  424. package/dist/src/routing/resolve-tui-session-key.d.ts +3 -0
  425. package/dist/src/routing/resolve-tui-session-key.js +14 -3
  426. package/dist/src/routing/resolve-tui-session-key.js.map +1 -1
  427. package/dist/src/session/session-workspace.js +2 -7
  428. package/dist/src/session/session-workspace.js.map +1 -1
  429. package/dist/src/session/store.js +0 -5
  430. package/dist/src/session/store.js.map +1 -1
  431. package/dist/src/session/transcript-outline.d.ts +47 -0
  432. package/dist/src/session/transcript-outline.js +481 -0
  433. package/dist/src/session/transcript-outline.js.map +1 -0
  434. package/dist/src/storage/sqlite/index.d.ts +1 -3
  435. package/dist/src/storage/sqlite/index.js +2 -4
  436. package/dist/src/storage/sqlite/memory-index-repository.d.ts +1 -0
  437. package/dist/src/storage/sqlite/memory-index-repository.js +15 -14
  438. package/dist/src/storage/sqlite/memory-index-repository.js.map +1 -1
  439. package/dist/src/storage/sqlite/memory-records-repository.d.ts +44 -1
  440. package/dist/src/storage/sqlite/memory-records-repository.js +164 -20
  441. package/dist/src/storage/sqlite/memory-records-repository.js.map +1 -1
  442. package/dist/src/storage/sqlite/migrations/014_memory_record_governance.sql +10 -0
  443. package/dist/src/storage/sqlite/migrations/015_memory_trace_feedback.sql +4 -0
  444. package/dist/src/storage/sqlite/migrations/016_automations.sql +47 -0
  445. package/dist/src/storage/sqlite/migrations/017_automation_run_events.sql +14 -0
  446. package/dist/src/storage/sqlite/migrations/018_automation_safety.sql +1 -0
  447. package/dist/src/storage/sqlite/migrations/runner.d.ts +1 -1
  448. package/dist/src/storage/sqlite/migrations/runner.js +3 -3
  449. package/dist/src/storage/sqlite/migrations/runner.js.map +1 -1
  450. package/dist/src/storage/sqlite/migrations/runner.ts +1 -1
  451. package/dist/src/storage/sqlite/schema.js +1 -1
  452. package/dist/src/storage/sqlite/schema.sql +56 -46
  453. package/dist/src/tui/backends/embedded-backend.d.ts +9 -0
  454. package/dist/src/tui/backends/embedded-backend.js +55 -27
  455. package/dist/src/tui/backends/embedded-backend.js.map +1 -1
  456. package/dist/src/tui/backends/gateway-sse-backend.d.ts +4 -0
  457. package/dist/src/tui/backends/gateway-sse-backend.js +30 -3
  458. package/dist/src/tui/backends/gateway-sse-backend.js.map +1 -1
  459. package/dist/src/tui/components/tui-header.d.ts +0 -1
  460. package/dist/src/tui/components/tui-header.js +3 -8
  461. package/dist/src/tui/components/tui-header.js.map +1 -1
  462. package/dist/src/tui/tui-backend.d.ts +4 -0
  463. package/dist/src/tui/tui-commands.d.ts +5 -0
  464. package/dist/src/tui/tui-commands.js +43 -0
  465. package/dist/src/tui/tui-commands.js.map +1 -1
  466. package/dist/src/tui/tui-startup-resources.js +2 -1
  467. package/dist/src/tui/tui-startup-resources.js.map +1 -1
  468. package/dist/src/tui/tui-startup-text.js +12 -12
  469. package/dist/src/tui/tui-startup-text.js.map +1 -1
  470. package/dist/src/tui/tui-transcript-tree.d.ts +1 -1
  471. package/dist/src/tui/tui-transcript-tree.js +17 -257
  472. package/dist/src/tui/tui-transcript-tree.js.map +1 -1
  473. package/dist/src/tui/tui-types.d.ts +2 -0
  474. package/dist/src/tui/tui-types.js.map +1 -1
  475. package/dist/src/tui/tui.js +11 -3
  476. package/dist/src/tui/tui.js.map +1 -1
  477. package/dist/src/workflows/domain/index.js +1 -1
  478. package/dist/src/workflows/domain/run.d.ts +7 -7
  479. package/dist/src/workflows/domain/run.js.map +1 -1
  480. package/dist/src/workflows/index.js +2 -2
  481. package/dist/src/workflows/service/workflow-run-service.d.ts +2 -0
  482. package/dist/src/workflows/service/workflow-run-service.js +31 -9
  483. package/dist/src/workflows/service/workflow-run-service.js.map +1 -1
  484. package/dist/src/workflows/service/workflow-run-service.types.d.ts +1 -1
  485. package/package.json +4 -2
  486. package/dist/gateway/static/root/assets/agents-C6xgagZd.js +0 -71
  487. package/dist/gateway/static/root/assets/app-management-settings-panel-CBpLONvG.js +0 -1
  488. package/dist/gateway/static/root/assets/appearance-settings-CGcc54yj.js +0 -1
  489. package/dist/gateway/static/root/assets/browser-settings-page-CUOO-PQk.js +0 -8
  490. package/dist/gateway/static/root/assets/capability-presets-api-XQoMTI0A.js +0 -1
  491. package/dist/gateway/static/root/assets/capability-presets-settings-panel-CfqF-kGr.js +0 -1
  492. package/dist/gateway/static/root/assets/channels-settings-BYyRzsex.js +0 -1
  493. package/dist/gateway/static/root/assets/cn-JdwAhgNB.js +0 -1
  494. package/dist/gateway/static/root/assets/connectors-page-DIvEz4NX.js +0 -2
  495. package/dist/gateway/static/root/assets/createLucideIcon-DPHK1VkS.js +0 -1
  496. package/dist/gateway/static/root/assets/cron-api-R41aQCX9.js +0 -1
  497. package/dist/gateway/static/root/assets/cron-dreaming-jobs-nCMWCf0p.js +0 -1
  498. package/dist/gateway/static/root/assets/cron-page-D97nFqQD.js +0 -3
  499. package/dist/gateway/static/root/assets/dreaming-settings-Bceaw1PG.js +0 -1
  500. package/dist/gateway/static/root/assets/format-cron-label-BsotZDO5.js +0 -2
  501. package/dist/gateway/static/root/assets/format-interval-label-Dn_QKIqb.js +0 -1
  502. package/dist/gateway/static/root/assets/gateway-settings-iISWAZRm.js +0 -1
  503. package/dist/gateway/static/root/assets/goal-detail-page-DCUROLMQ.js +0 -1
  504. package/dist/gateway/static/root/assets/goals-settings-CPAuFwoD.js +0 -1
  505. package/dist/gateway/static/root/assets/heartbeat-config-api-D7bKFEeO.js +0 -1
  506. package/dist/gateway/static/root/assets/heartbeat-settings-CC69vNx0.js +0 -1
  507. package/dist/gateway/static/root/assets/index-CwhK8qCh.js +0 -122
  508. package/dist/gateway/static/root/assets/index-CyfhARL-.css +0 -1
  509. package/dist/gateway/static/root/assets/interval-presets-0DtsnxE0.js +0 -1
  510. package/dist/gateway/static/root/assets/keyboard-shortcuts-settings-BPREtN8B.js +0 -1
  511. package/dist/gateway/static/root/assets/messages-Cf1O9JB0.js +0 -3
  512. package/dist/gateway/static/root/assets/models-hub-panel-DmKiIihT.js +0 -2
  513. package/dist/gateway/static/root/assets/note-detail-page-CxxfLRJZ.js +0 -2
  514. package/dist/gateway/static/root/assets/notes-page-X2slSx7V.js +0 -1
  515. package/dist/gateway/static/root/assets/remote-access-hub-BvmUWqgu.js +0 -1
  516. package/dist/gateway/static/root/assets/schedule-field-CgJSCD3B.js +0 -1
  517. package/dist/gateway/static/root/assets/sessions-page-B0yESuuL.js +0 -1
  518. package/dist/gateway/static/root/assets/settings-advanced-gate-q2M8RKOo.js +0 -1
  519. package/dist/gateway/static/root/assets/settings-page-CGozabLD.js +0 -1
  520. package/dist/gateway/static/root/assets/setup-status-panel-FoOSe6nU.js +0 -1
  521. package/dist/gateway/static/root/assets/shares-settings-Cy5zWyYQ.js +0 -1
  522. package/dist/gateway/static/root/assets/skill-reload-api-DaZNFro9.js +0 -1
  523. package/dist/gateway/static/root/assets/skills-page-CnwtUzvw.js +0 -2
  524. package/dist/gateway/static/root/assets/system-settings-panel-DXs2VmBt.js +0 -1
  525. package/dist/gateway/static/root/assets/typed-models-lib-4gPuydz_.js +0 -1
  526. package/dist/gateway/static/root/assets/voice-api-key-field-DvKiOglO.js +0 -1
  527. package/dist/gateway/static/root/assets/workflows-page-CAVZcONQ.js +0 -18
  528. package/dist/src/agent/context/workspace-templates/USER.md +0 -24
  529. package/dist/src/agent/fallback/error.d.ts +0 -22
  530. package/dist/src/agent/fallback/error.js +0 -32
  531. package/dist/src/agent/fallback/error.js.map +0 -1
  532. package/dist/src/agent/fallback/index.d.ts +0 -5
  533. package/dist/src/agent/fallback/index.js +0 -9
  534. package/dist/src/agent/fallback/index.js.map +0 -1
  535. package/dist/src/agent/orchestration/run-agent-turn-with-fallbacks.d.ts +0 -29
  536. package/dist/src/agent/orchestration/run-agent-turn-with-fallbacks.js +0 -76
  537. package/dist/src/agent/orchestration/run-agent-turn-with-fallbacks.js.map +0 -1
  538. package/dist/src/agent/service/reconcile-dreaming-cron.d.ts +0 -6
  539. package/dist/src/agent/service/reconcile-dreaming-cron.js +0 -84
  540. package/dist/src/agent/service/reconcile-dreaming-cron.js.map +0 -1
  541. package/dist/src/agent/tools/cronjob-tool.d.ts +0 -29
  542. package/dist/src/agent/tools/cronjob-tool.js +0 -274
  543. package/dist/src/agent/tools/cronjob-tool.js.map +0 -1
  544. package/dist/src/cli/commands/cron-cli.d.ts +0 -2
  545. package/dist/src/cli/commands/cron-cli.js +0 -15
  546. package/dist/src/cli/commands/cron-cli.js.map +0 -1
  547. package/dist/src/cli/commands/cron.d.ts +0 -4
  548. package/dist/src/cli/commands/cron.js +0 -188
  549. package/dist/src/cli/commands/cron.js.map +0 -1
  550. package/dist/src/cli/commands/doctor/checks/cron-health.js +0 -35
  551. package/dist/src/cli/commands/doctor/checks/cron-health.js.map +0 -1
  552. package/dist/src/cron/execution-types.d.ts +0 -42
  553. package/dist/src/cron/executor.d.ts +0 -67
  554. package/dist/src/cron/executor.js +0 -669
  555. package/dist/src/cron/executor.js.map +0 -1
  556. package/dist/src/cron/index.d.ts +0 -7
  557. package/dist/src/cron/index.js +0 -7
  558. package/dist/src/cron/job-content.d.ts +0 -5
  559. package/dist/src/cron/job-content.js +0 -15
  560. package/dist/src/cron/job-content.js.map +0 -1
  561. package/dist/src/cron/run-log-store.d.ts +0 -12
  562. package/dist/src/cron/run-log-store.js +0 -58
  563. package/dist/src/cron/run-log-store.js.map +0 -1
  564. package/dist/src/cron/schedule.d.ts +0 -10
  565. package/dist/src/cron/schedule.js +0 -85
  566. package/dist/src/cron/schedule.js.map +0 -1
  567. package/dist/src/cron/service.d.ts +0 -58
  568. package/dist/src/cron/service.js +0 -419
  569. package/dist/src/cron/service.js.map +0 -1
  570. package/dist/src/cron/types.d.ts +0 -183
  571. package/dist/src/cron/validation.d.ts +0 -500
  572. package/dist/src/cron/validation.js +0 -192
  573. package/dist/src/cron/validation.js.map +0 -1
  574. package/dist/src/cron/workflow-run-completion.d.ts +0 -23
  575. package/dist/src/cron/workflow-run-completion.js +0 -72
  576. package/dist/src/cron/workflow-run-completion.js.map +0 -1
  577. package/dist/src/extensions/types/phase4.js +0 -1
  578. package/dist/src/gateway/hono/routes/cron.d.ts +0 -3
  579. package/dist/src/gateway/hono/routes/cron.js +0 -109
  580. package/dist/src/gateway/hono/routes/cron.js.map +0 -1
  581. package/dist/src/storage/sqlite/cron-job-repository.d.ts +0 -6
  582. package/dist/src/storage/sqlite/cron-job-repository.js +0 -70
  583. package/dist/src/storage/sqlite/cron-job-repository.js.map +0 -1
  584. package/dist/src/storage/sqlite/cron-run-repository.d.ts +0 -5
  585. package/dist/src/storage/sqlite/cron-run-repository.js +0 -96
  586. package/dist/src/storage/sqlite/cron-run-repository.js.map +0 -1
  587. /package/dist/src/{cron → automations/domain}/types.js +0 -0
  588. /package/dist/src/{config/defaults.d.ts → automations/draft/automation-draft.types.js} +0 -0
  589. /package/dist/src/{config/defaults.js → extensions/types/registration.js} +0 -0
  590. /package/dist/src/{cron/execution-types.js → migrations/types.js} +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"gateway-sse-backend.js","names":[],"sources":["../../../../src/tui/backends/gateway-sse-backend.ts"],"sourcesContent":["import { prependEnvelopeTimestamp } from '../../channels/envelope-timestamp.js';\nimport { parseModelRef } from '../../agent/models/selection.js';\nimport type { ExportFormat } from '../../session/types.js';\nimport type { TranscriptStoredRow } from '../../session/session-context-for-llm.js';\nimport { transcriptRowsToClientHistory } from '../../session/client-history.js';\nimport { createLogger } from '../../utils/logger.js';\nimport { consumeSSEStream, parseSSEData } from '../sse-consumer.js';\nimport type {\n ChatSendOptions,\n HistoryMessage,\n TuiBackend,\n TuiCompactionResult,\n TuiEvent,\n TuiModelChoice,\n TuiShareRequest,\n TuiShareResult,\n TuiSessionStats,\n TuiSessionItem,\n TuiStartupResources,\n TuiTranscriptTreeEntry,\n TuiAgentInfo,\n TuiWorkspaceFileSearchEntry,\n TuiWorkflowRunStartRequest,\n TuiWorkflowRunStartResult,\n} from '../tui-backend.js';\nimport type { SessionInfo } from '../tui-types.js';\nimport { computeTuiSessionStats } from '../tui-session-stats.js';\nimport { buildTuiTranscriptTree, transcriptTreeEntryIdToRowNumber } from '../tui-transcript-tree.js';\n\nconst log = createLogger('TUI:GatewaySSE');\n\ninterface GatewaySSEOptions {\n url: string;\n token?: string;\n}\n\nfunction normalizeGatewayModelChoice(model: TuiModelChoice): TuiModelChoice {\n const providerPrefix = `${model.provider}/`;\n const id = model.id.startsWith(providerPrefix)\n ? model.id.slice(providerPrefix.length)\n : model.id;\n return { ...model, id };\n}\n\n/** Fetch wrapper that adds auth headers. */\nasync function gatewayFetch(\n baseUrl: string,\n path: string,\n token: string | undefined,\n init?: RequestInit,\n): Promise<Response> {\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n ...(token ? { Authorization: `Bearer ${token}` } : {}),\n ...(init?.headers as Record<string, string> | undefined),\n };\n return fetch(`${baseUrl}${path}`, { ...init, headers });\n}\n\n/**\n * TUI backend that communicates with a running xopc gateway via HTTP + SSE.\n *\n * - Agent streaming: `POST /api/agent` with `Accept: text/event-stream`\n * - Broadcast events: `GET /api/events` via long-lived SSE\n * - REST calls for sessions, models, etc.\n */\nexport class GatewaySseBackend implements TuiBackend {\n private readonly baseUrl: string;\n private readonly token: string | undefined;\n private eventAbort: AbortController | null = null;\n private chatAbort: AbortController | null = null;\n\n onEvent?: (evt: TuiEvent) => void;\n onConnected?: () => void;\n onDisconnected?: (reason: string) => void;\n onGap?: (info: { expected: number; received: number }) => void;\n\n constructor(opts: GatewaySSEOptions) {\n this.baseUrl = opts.url.replace(/\\/+$/, '');\n this.token = opts.token;\n }\n\n get connectionLabel(): string {\n return this.baseUrl;\n }\n\n start(): void {\n this.startEventStream();\n }\n\n stop(): void {\n this.eventAbort?.abort();\n this.eventAbort = null;\n this.chatAbort?.abort();\n this.chatAbort = null;\n }\n\n getActiveSignal(): AbortSignal | undefined {\n const signal = this.chatAbort?.signal;\n return signal && !signal.aborted ? signal : undefined;\n }\n\n // ── Agent chat (POST /api/agent → SSE response body) ──\n\n async sendChat(opts: ChatSendOptions): Promise<{ runId: string }> {\n this.chatAbort?.abort();\n this.chatAbort = new AbortController();\n const signal = this.chatAbort.signal;\n const runId = crypto.randomUUID();\n\n\n // Fire-and-forget: run the HTTP request + SSE consumption in background\n // so the TUI event loop stays responsive for keyboard input.\n void (async () => {\n try {\n const res = await gatewayFetch(this.baseUrl, '/api/agent', this.token, {\n method: 'POST',\n headers: { Accept: 'text/event-stream' },\n body: JSON.stringify({\n // Prepend envelope timestamp for regular messages so the model knows\n // the current date/time. Skip for slash commands — parseSlashCommand\n // requires lines starting with '/'.\n message: opts.message.trimStart().startsWith('/')\n ? opts.message\n : prependEnvelopeTimestamp(opts.message),\n channel: 'webchat',\n sessionKey: opts.sessionKey,\n attachments: opts.attachments,\n thinking: opts.thinking,\n }),\n signal,\n });\n\n if (!res.ok) {\n const body = (await res.json().catch(() => ({}))) as { error?: { message?: string } };\n this.onEvent?.({\n event: 'error',\n data: {\n type: 'error',\n runId,\n sessionKey: opts.sessionKey,\n timestamp: Date.now(),\n payload: { code: 'GATEWAY_ERROR', message: body.error?.message ?? `Gateway error: ${res.status}` },\n },\n source: 'agent-response',\n });\n return;\n }\n\n const contentType = res.headers.get('Content-Type') ?? '';\n\n if (contentType.includes('text/event-stream') && res.body) {\n await consumeSSEStream(\n res.body,\n (sseEvent) => {\n if (signal.aborted) return;\n const data = parseSSEData<Record<string, unknown>>(sseEvent.data);\n if (!data) return;\n this.onEvent?.({ event: sseEvent.event, data, source: 'agent-response' });\n },\n signal,\n );\n } else {\n const json = (await res.json()) as { ok?: boolean; payload?: { content?: string } };\n if (json.ok && json.payload?.content) {\n const messageId = `msg_${runId}_1`;\n const base = { runId, sessionKey: opts.sessionKey, timestamp: Date.now() };\n this.onEvent?.({ event: 'run_start', data: { ...base, type: 'run_start', payload: { channel: 'webchat' } }, source: 'agent-response' });\n this.onEvent?.({ event: 'assistant_message_start', data: { ...base, type: 'assistant_message_start', payload: { messageId } }, source: 'agent-response' });\n this.onEvent?.({ event: 'assistant_delta', data: { ...base, type: 'assistant_delta', payload: { messageId, delta: json.payload.content } }, source: 'agent-response' });\n this.onEvent?.({ event: 'assistant_message_end', data: { ...base, type: 'assistant_message_end', payload: { messageId } }, source: 'agent-response' });\n this.onEvent?.({ event: 'run_end', data: { ...base, type: 'run_end', payload: { status: 'success' } }, source: 'agent-response' });\n }\n }\n } catch (error) {\n if (signal.aborted) return;\n const errorMessage = error instanceof Error ? error.message : String(error);\n this.onEvent?.({\n event: 'error',\n data: { type: 'error', runId, sessionKey: opts.sessionKey, timestamp: Date.now(), payload: { code: 'NETWORK_ERROR', message: errorMessage } },\n source: 'agent-response',\n });\n }\n })();\n\n return { runId };\n }\n\n async searchWorkspaceFiles(\n sessionKey: string,\n query: string,\n options?: { limit?: number },\n ): Promise<TuiWorkspaceFileSearchEntry[]> {\n try {\n const params = new URLSearchParams();\n params.set('q', query);\n params.set('limit', String(options?.limit ?? 15));\n params.set('sessionKey', sessionKey);\n const res = await gatewayFetch(\n this.baseUrl,\n `/api/workspace/editor/files/search?${params.toString()}`,\n this.token,\n );\n if (!res.ok) return [];\n const json = (await res.json()) as {\n ok?: boolean;\n payload?: { entries?: TuiWorkspaceFileSearchEntry[] };\n };\n return json.payload?.entries ?? [];\n } catch (err) {\n const errorMessage = err instanceof Error ? err.message : String(err);\n log.warn({ err, sessionKey, errorMessage }, `Gateway workspace file search failed: ${errorMessage}`);\n return [];\n }\n }\n\n async startWorkflowRun(opts: TuiWorkflowRunStartRequest): Promise<TuiWorkflowRunStartResult> {\n const goal = opts.goal?.trim();\n const res = await gatewayFetch(this.baseUrl, '/api/workflows/runs', this.token, {\n method: 'POST',\n body: JSON.stringify({\n definitionId: opts.definitionId,\n agentId: opts.agentId,\n parentSessionKey: opts.sessionKey,\n source: { kind: 'chat', sessionKey: opts.sessionKey },\n ...(goal ? { goal } : {}),\n ...(opts.input !== undefined ? { input: opts.input } : {}),\n }),\n });\n const json = (await res.json().catch(() => ({}))) as {\n runId?: string;\n sessionKey?: string;\n error?: string;\n code?: string;\n };\n if (!res.ok || !json.runId || !json.sessionKey) {\n throw new Error(json.error ?? `Workflow start failed (${res.status})`);\n }\n return {\n runId: json.runId,\n sessionKey: json.sessionKey,\n definitionId: opts.definitionId,\n };\n }\n\n async resumeChat(opts: { sessionKey: string; runId: string }): Promise<{ ok: boolean; reason?: string }> {\n this.chatAbort?.abort();\n this.chatAbort = new AbortController();\n const signal = this.chatAbort.signal;\n this.onEvent?.({\n event: 'run_start',\n data: { type: 'run_start', runId: opts.runId, sessionKey: opts.sessionKey, timestamp: Date.now(), payload: { channel: 'webchat' } },\n source: 'agent-resume',\n });\n\n let res: Response;\n try {\n res = await gatewayFetch(this.baseUrl, '/api/agent/resume', this.token, {\n method: 'POST',\n headers: { Accept: 'text/event-stream' },\n body: JSON.stringify({ runId: opts.runId, sessionKey: opts.sessionKey }),\n signal,\n });\n } catch (error) {\n if (signal.aborted) return { ok: false, reason: 'resume aborted' };\n const errorMessage = error instanceof Error ? error.message : String(error);\n return { ok: false, reason: errorMessage };\n }\n\n if (!res.ok) {\n const body = (await res.json().catch(() => ({}))) as { error?: { message?: string } };\n return { ok: false, reason: body.error?.message ?? `Resume failed: ${res.status}` };\n }\n\n const contentType = res.headers.get('Content-Type') ?? '';\n if (!contentType.includes('text/event-stream') || !res.body) {\n return { ok: false, reason: 'Resume endpoint did not return an SSE stream' };\n }\n\n void (async () => {\n try {\n await consumeSSEStream(\n res.body,\n (sseEvent) => {\n if (signal.aborted) return;\n const data = parseSSEData<Record<string, unknown>>(sseEvent.data);\n if (!data) return;\n this.onEvent?.({ event: sseEvent.event, data, source: 'agent-resume' });\n },\n signal,\n );\n } catch (error) {\n if (signal.aborted) return;\n const errorMessage = error instanceof Error ? error.message : String(error);\n this.onEvent?.({\n event: 'error',\n data: { type: 'error', runId: opts.runId, sessionKey: opts.sessionKey, timestamp: Date.now(), payload: { code: 'NETWORK_ERROR', message: errorMessage } },\n source: 'agent-resume',\n });\n }\n })();\n\n return { ok: true };\n }\n\n async abortChat(opts: { sessionKey: string; runId: string }): Promise<{ ok: boolean }> {\n this.chatAbort?.abort();\n this.chatAbort = null;\n try {\n const res = await gatewayFetch(this.baseUrl, '/api/agent/abort', this.token, {\n method: 'POST',\n body: JSON.stringify({ runId: opts.runId }),\n });\n const json = (await res.json()) as { ok?: boolean };\n return { ok: json.ok ?? false };\n } catch {\n return { ok: false };\n }\n }\n\n async steerChat(opts: { sessionKey: string; message: string }): Promise<{ ok: boolean }> {\n try {\n const res = await gatewayFetch(this.baseUrl, '/api/agent/steer', this.token, {\n method: 'POST',\n body: JSON.stringify({ sessionKey: opts.sessionKey, message: opts.message }),\n });\n if (!res.ok) return { ok: false };\n const json = (await res.json()) as { ok?: boolean };\n return { ok: json.ok === true };\n } catch {\n return { ok: false };\n }\n }\n\n // ── REST helpers ──\n\n async getStartupResources(sessionKey: string): Promise<TuiStartupResources> {\n const empty: TuiStartupResources = { context: [], skills: [], workflows: [], connectors: [] };\n try {\n const res = await gatewayFetch(\n this.baseUrl,\n `/api/tui/startup-resources?sessionKey=${encodeURIComponent(sessionKey)}`,\n this.token,\n );\n if (!res.ok) return empty;\n const json = (await res.json()) as { payload?: Partial<TuiStartupResources> };\n return {\n context: Array.isArray(json.payload?.context) ? json.payload.context : [],\n skills: Array.isArray(json.payload?.skills) ? json.payload.skills : [],\n workflows: Array.isArray(json.payload?.workflows) ? json.payload.workflows : [],\n connectors: Array.isArray(json.payload?.connectors) ? json.payload.connectors : [],\n };\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n log.warn({ err: error, sessionKey, errorMessage }, `Failed to load startup resources: ${errorMessage}`);\n return empty;\n }\n }\n\n async loadHistory(opts: {\n sessionKey: string;\n limit?: number;\n }): Promise<{ messages: HistoryMessage[] }> {\n try {\n const res = await gatewayFetch(\n this.baseUrl,\n `/api/sessions/${encodeURIComponent(opts.sessionKey)}?include=transcriptRows`,\n this.token,\n );\n if (!res.ok) return { messages: [] };\n const json = (await res.json()) as {\n session?: { transcriptRows?: unknown[] };\n };\n const rows = Array.isArray(json.session?.transcriptRows)\n ? (json.session.transcriptRows as TranscriptStoredRow[])\n : [];\n return { messages: transcriptRowsToClientHistory(rows, { limit: opts.limit }) };\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n log.warn({ err: error, errorMessage }, `Failed to load history: ${errorMessage}`);\n return { messages: [] };\n }\n }\n\n async loadTranscriptTree(sessionKey: string): Promise<TuiTranscriptTreeEntry[]> {\n try {\n const res = await gatewayFetch(\n this.baseUrl,\n `/api/sessions/${encodeURIComponent(sessionKey)}?include=transcriptRows`,\n this.token,\n );\n if (!res.ok) return [];\n const json = (await res.json()) as {\n session?: { transcriptRows?: unknown[] };\n };\n const rows = Array.isArray(json.session?.transcriptRows)\n ? (json.session.transcriptRows as TranscriptStoredRow[])\n : [];\n return buildTuiTranscriptTree(rows);\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n log.warn({ err: error, sessionKey, errorMessage }, `Failed to load transcript tree: ${errorMessage}`);\n return [];\n }\n }\n\n async getSessionStats(sessionKey: string): Promise<TuiSessionStats> {\n try {\n const res = await gatewayFetch(\n this.baseUrl,\n `/api/sessions/${encodeURIComponent(sessionKey)}?include=transcriptRows`,\n this.token,\n );\n if (!res.ok) return computeTuiSessionStats([]);\n const json = (await res.json()) as {\n session?: { transcriptRows?: unknown[] };\n };\n const rows = Array.isArray(json.session?.transcriptRows)\n ? (json.session.transcriptRows as TranscriptStoredRow[])\n : [];\n return computeTuiSessionStats(rows);\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n log.warn({ err: error, sessionKey, errorMessage }, `Failed to load session stats: ${errorMessage}`);\n return computeTuiSessionStats([]);\n }\n }\n\n async listSessions(): Promise<TuiSessionItem[]> {\n try {\n const res = await gatewayFetch(this.baseUrl, '/api/sessions', this.token);\n if (!res.ok) return [];\n const json = (await res.json()) as {\n items?: Array<{\n key: string;\n name?: string;\n updatedAt?: string;\n estimatedTokens?: number;\n messageCount?: number;\n customData?: Record<string, unknown>;\n cwd?: string;\n }>;\n };\n return (json.items ?? []).map((s) => ({\n key: s.key,\n displayName: s.name,\n updatedAt: s.updatedAt ? Date.parse(s.updatedAt) : undefined,\n totalTokens: s.estimatedTokens ?? null,\n messageCount: typeof s.messageCount === 'number' ? s.messageCount : undefined,\n model:\n typeof s.customData?.model === 'string'\n ? s.customData.model\n : typeof s.customData?.modelRef === 'string'\n ? s.customData.modelRef\n : null,\n forkedFromSessionKey:\n typeof s.customData?.forkedFromSessionKey === 'string'\n ? s.customData.forkedFromSessionKey\n : undefined,\n cwd: typeof s.cwd === 'string' ? s.cwd : undefined,\n }));\n } catch {\n return [];\n }\n }\n\n async listAgents(): Promise<TuiAgentInfo[]> {\n const agents = new Map<string, TuiAgentInfo>();\n try {\n const res = await gatewayFetch(this.baseUrl, '/api/agents', this.token);\n if (res.ok) {\n const json = (await res.json()) as {\n payload?: { agents?: Array<{ id?: unknown; name?: unknown }> };\n };\n for (const row of json.payload?.agents ?? []) {\n if (typeof row.id !== 'string' || !row.id.trim()) continue;\n const id = row.id.trim().toLowerCase();\n agents.set(id, {\n id,\n enabled: true,\n ...(typeof row.name === 'string' && row.name.trim()\n ? { displayName: row.name.trim() }\n : {}),\n });\n }\n }\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n log.warn({ err: error, errorMessage }, `Failed to load agents: ${errorMessage}`);\n }\n return [...agents.values()].sort((a, b) => a.id.localeCompare(b.id));\n }\n\n async getSessionInfo(sessionKey: string): Promise<SessionInfo> {\n const out: SessionInfo = {};\n try {\n const sessionPath = `/api/sessions/${encodeURIComponent(sessionKey)}`;\n const [sessionRes, agentCfgRes] = await Promise.all([\n gatewayFetch(this.baseUrl, sessionPath, this.token),\n gatewayFetch(this.baseUrl, `${sessionPath}/agent-config`, this.token),\n ]);\n\n type SessionRow = {\n name?: string;\n estimatedTokens?: number;\n customData?: Record<string, unknown>;\n };\n let session: SessionRow | undefined;\n\n if (sessionRes.ok) {\n const json = (await sessionRes.json()) as { session?: SessionRow };\n session = json.session;\n if (session) {\n if (session.name) out.displayName = session.name;\n if (session.estimatedTokens != null) out.totalTokens = session.estimatedTokens;\n }\n }\n\n if (agentCfgRes.ok) {\n const json = (await agentCfgRes.json()) as {\n ok?: boolean;\n payload?: {\n model?: string;\n thinkingLevel?: string;\n reasoningLevel?: string;\n verboseLevel?: string;\n effectiveWorkspacePath?: string;\n workingDirectoryLocked?: boolean;\n };\n };\n const p = json.payload;\n if (p?.model && typeof p.model === 'string') {\n const parsed = parseModelRef(p.model);\n if (parsed) {\n out.model = parsed.model;\n out.modelProvider = parsed.provider;\n } else {\n out.model = p.model;\n }\n }\n if (p?.thinkingLevel && typeof p.thinkingLevel === 'string') {\n out.thinkingLevel = p.thinkingLevel;\n }\n if (p?.reasoningLevel && typeof p.reasoningLevel === 'string') {\n out.reasoningLevel = p.reasoningLevel;\n }\n if (p?.verboseLevel && typeof p.verboseLevel === 'string') {\n out.verboseLevel = p.verboseLevel;\n }\n if (p?.effectiveWorkspacePath && typeof p.effectiveWorkspacePath === 'string') {\n out.effectiveWorkspacePath = p.effectiveWorkspacePath;\n }\n if (typeof p?.workingDirectoryLocked === 'boolean') {\n out.workingDirectoryLocked = p.workingDirectoryLocked;\n }\n }\n\n if (!out.model && session?.customData) {\n const cd = session.customData;\n const ref =\n typeof cd.model === 'string'\n ? cd.model\n : typeof cd.modelRef === 'string'\n ? cd.modelRef\n : undefined;\n if (ref) {\n const parsed = parseModelRef(ref);\n if (parsed) {\n out.model = parsed.model;\n out.modelProvider = parsed.provider;\n } else {\n out.model = ref;\n }\n }\n if (!out.modelProvider && typeof cd.modelProvider === 'string') {\n out.modelProvider = cd.modelProvider;\n }\n }\n\n if (out.totalTokens != null) {\n const models = await this.listModels();\n const match = models.find(\n (m) =>\n m.id === out.model &&\n (!out.modelProvider || m.provider === out.modelProvider),\n );\n const contextWindow = match?.contextWindow ?? 128_000;\n out.contextWindow = contextWindow;\n out.contextUsagePercent =\n contextWindow > 0\n ? Math.min(100, Math.round((out.totalTokens / contextWindow) * 100))\n : null;\n }\n\n return out;\n } catch {\n return {};\n }\n }\n\n async listModels(): Promise<TuiModelChoice[]> {\n try {\n const res = await gatewayFetch(this.baseUrl, '/api/models', this.token);\n if (!res.ok) return [];\n const json = (await res.json()) as {\n ok?: boolean;\n payload?: { models?: TuiModelChoice[] };\n };\n return (json.payload?.models ?? []).map(normalizeGatewayModelChoice);\n } catch {\n return [];\n }\n }\n\n async resetSession(sessionKey: string): Promise<void> {\n await gatewayFetch(\n this.baseUrl,\n `/api/sessions/${encodeURIComponent(sessionKey)}/reset`,\n this.token,\n { method: 'POST' },\n ).catch(() => {});\n }\n\n async compactSession(\n sessionKey: string,\n options?: { force?: boolean; instructions?: string },\n ): Promise<TuiCompactionResult> {\n try {\n const res = await gatewayFetch(\n this.baseUrl,\n `/api/sessions/${encodeURIComponent(sessionKey)}/compaction/run`,\n this.token,\n {\n method: 'POST',\n body: JSON.stringify({\n force: options?.force ?? true,\n instructions: options?.instructions,\n }),\n },\n );\n if (!res.ok) {\n return { compacted: false, summary: `Compaction failed (${res.status})` };\n }\n const json = (await res.json()) as {\n ok?: boolean;\n payload?: {\n result?: {\n compacted?: boolean;\n summary?: string;\n tokensBefore?: number;\n tokensAfter?: number;\n };\n };\n };\n const result = json.payload?.result;\n if (!result?.compacted) {\n return { compacted: false, summary: 'Nothing to compact' };\n }\n return {\n compacted: true,\n summary: `Compacted (${result.tokensBefore ?? '?'} → ${result.tokensAfter ?? '?'} tokens)`,\n tokensBefore: result.tokensBefore,\n tokensAfter: result.tokensAfter,\n transcriptSummary: result.summary,\n };\n } catch (err) {\n const errorMessage = err instanceof Error ? err.message : String(err);\n return { compacted: false, summary: errorMessage };\n }\n }\n\n async exportSession(sessionKey: string, format: ExportFormat): Promise<string> {\n const params = new URLSearchParams({ format });\n const res = await gatewayFetch(\n this.baseUrl,\n `/api/sessions/${encodeURIComponent(sessionKey)}/export?${params.toString()}`,\n this.token,\n );\n if (!res.ok) {\n throw new Error(`Export failed (${res.status})`);\n }\n const json = (await res.json()) as { content?: string };\n return json.content ?? '';\n }\n\n async importSession(\n targetSessionKey: string,\n jsonContent: string,\n ): Promise<{ sessionKey: string; rowCount: number }> {\n const res = await gatewayFetch(\n this.baseUrl,\n '/api/sessions/import',\n this.token,\n { method: 'POST', body: JSON.stringify({ targetKey: targetSessionKey, content: jsonContent }) },\n );\n const json = (await res.json().catch(() => ({}))) as {\n ok?: boolean;\n error?: string;\n sessionKey?: string;\n rowCount?: number;\n };\n if (!res.ok || json.ok === false || !json.sessionKey) {\n throw new Error(json.error ?? `Import failed (${res.status})`);\n }\n return { sessionKey: json.sessionKey, rowCount: json.rowCount ?? 0 };\n }\n\n async createShare(\n sessionKey: string,\n request: TuiShareRequest,\n options?: { agentId?: string },\n ): Promise<TuiShareResult> {\n const res = await gatewayFetch(this.baseUrl, '/api/shares/auto', this.token, {\n method: 'POST',\n body: JSON.stringify({\n path: request.path,\n audience: request.audience,\n mode: request.mode,\n title: request.title,\n description: request.description,\n sessionKey,\n agentId: options?.agentId,\n }),\n });\n const json = (await res.json().catch(() => ({}))) as {\n ok?: boolean;\n error?: { message?: string };\n payload?: {\n share?: {\n kind?: string;\n title?: string;\n description?: string;\n shareUrl?: string;\n reachability?: string;\n reachabilityHint?: string | null;\n expiresAt?: string;\n maxViews?: number | null;\n };\n thumbnail?: { url?: string };\n routing?: { reason?: string; hint?: string };\n };\n };\n if (!res.ok || json.ok === false || !json.payload?.share?.shareUrl) {\n throw new Error(json.error?.message ?? `Share failed (${res.status})`);\n }\n const share = json.payload.share;\n return {\n kind: share.kind ?? 'share',\n shareUrl: share.shareUrl,\n title: share.title,\n description: share.description,\n thumbnailUrl: json.payload.thumbnail?.url,\n reachability: share.reachability,\n reachabilityHint: share.reachabilityHint,\n expiresAt: share.expiresAt,\n maxViews: share.maxViews,\n routingReason: json.payload.routing?.reason,\n routingHint: json.payload.routing?.hint,\n };\n }\n\n async btwQuery(sessionKey: string, question: string): Promise<{ text: string; error?: string }> {\n const res = await gatewayFetch(\n this.baseUrl,\n `/api/sessions/${encodeURIComponent(sessionKey)}/btw`,\n this.token,\n { method: 'POST', body: JSON.stringify({ question }) },\n );\n if (!res.ok) {\n return { text: '', error: `BTW failed (${res.status})` };\n }\n return (await res.json()) as { text: string; error?: string };\n }\n\n async forkSession(\n sourceSessionKey: string,\n targetSessionKey: string,\n ): Promise<{ sessionKey: string; rowCount: number }> {\n const res = await gatewayFetch(\n this.baseUrl,\n `/api/sessions/${encodeURIComponent(sourceSessionKey)}/fork`,\n this.token,\n { method: 'POST', body: JSON.stringify({ targetKey: targetSessionKey }) },\n );\n const json = (await res.json().catch(() => ({}))) as {\n ok?: boolean;\n error?: string;\n sessionKey?: string;\n rowCount?: number;\n };\n if (!res.ok || json.ok === false || !json.sessionKey) {\n throw new Error(json.error ?? `Fork failed (${res.status})`);\n }\n return { sessionKey: json.sessionKey, rowCount: json.rowCount ?? 0 };\n }\n\n async forkSessionAt(\n sourceSessionKey: string,\n targetSessionKey: string,\n entryId: string,\n ): Promise<{ sessionKey: string; rowCount: number }> {\n const throughRow = transcriptTreeEntryIdToRowNumber(entryId);\n if (throughRow == null) {\n throw new Error(`Invalid transcript entry: ${entryId}`);\n }\n const res = await gatewayFetch(\n this.baseUrl,\n `/api/sessions/${encodeURIComponent(sourceSessionKey)}/fork-row`,\n this.token,\n { method: 'POST', body: JSON.stringify({ targetKey: targetSessionKey, throughRow }) },\n );\n const json = (await res.json().catch(() => ({}))) as {\n ok?: boolean;\n error?: string;\n sessionKey?: string;\n rowCount?: number;\n };\n if (!res.ok || json.ok === false || !json.sessionKey) {\n throw new Error(json.error ?? `Fork failed (${res.status})`);\n }\n return { sessionKey: json.sessionKey, rowCount: json.rowCount ?? 0 };\n }\n\n async setTranscriptLabel(\n sessionKey: string,\n entryId: string,\n label: string | undefined,\n ): Promise<{ ok: boolean }> {\n const res = await gatewayFetch(\n this.baseUrl,\n `/api/sessions/${encodeURIComponent(sessionKey)}/transcript/label`,\n this.token,\n { method: 'POST', body: JSON.stringify({ targetId: entryId, label }) },\n );\n const json = (await res.json().catch(() => ({}))) as { ok?: boolean; error?: string };\n if (!res.ok || json.ok === false) {\n throw new Error(json.error ?? `Label update failed (${res.status})`);\n }\n return { ok: true };\n }\n\n async appendCustomEntry(\n sessionKey: string,\n customType: string,\n data?: unknown,\n ): Promise<{ ok: boolean }> {\n const res = await gatewayFetch(\n this.baseUrl,\n `/api/sessions/${encodeURIComponent(sessionKey)}/transcript/custom`,\n this.token,\n { method: 'POST', body: JSON.stringify({ customType, data }) },\n );\n const json = (await res.json().catch(() => ({}))) as { ok?: boolean; error?: string };\n if (!res.ok || json.ok === false) {\n throw new Error(json.error ?? `Custom entry append failed (${res.status})`);\n }\n return { ok: true };\n }\n\n async appendCustomMessage(\n sessionKey: string,\n message: {\n customType: string;\n content?: string | unknown[];\n display?: boolean;\n details?: unknown;\n },\n ): Promise<{ ok: boolean }> {\n const res = await gatewayFetch(\n this.baseUrl,\n `/api/sessions/${encodeURIComponent(sessionKey)}/transcript/custom-message`,\n this.token,\n { method: 'POST', body: JSON.stringify(message) },\n );\n const json = (await res.json().catch(() => ({}))) as { ok?: boolean; error?: string };\n if (!res.ok || json.ok === false) {\n throw new Error(json.error ?? `Custom message append failed (${res.status})`);\n }\n return { ok: true };\n }\n\n async appendBashExecution(\n sessionKey: string,\n entry: {\n command: string;\n output?: string;\n exitCode?: number | null;\n signal?: string | null;\n excludeFromContext?: boolean;\n truncated?: boolean;\n fullOutputPath?: string;\n },\n ): Promise<{ ok: boolean }> {\n const res = await gatewayFetch(\n this.baseUrl,\n `/api/sessions/${encodeURIComponent(sessionKey)}/transcript/bash`,\n this.token,\n { method: 'POST', body: JSON.stringify(entry) },\n );\n const json = (await res.json().catch(() => ({}))) as { ok?: boolean; error?: string };\n if (!res.ok || json.ok === false) {\n throw new Error(json.error ?? `Bash execution append failed (${res.status})`);\n }\n return { ok: true };\n }\n\n async patchSession(sessionKey: string, patch: Record<string, unknown>): Promise<void> {\n const res = await gatewayFetch(\n this.baseUrl,\n `/api/sessions/${encodeURIComponent(sessionKey)}/agent-config`,\n this.token,\n { method: 'PATCH', body: JSON.stringify(patch) },\n );\n const json = (await res.json().catch(() => ({}))) as { ok?: boolean; error?: string };\n if (!res.ok || json.ok === false) {\n throw new Error(json.error ?? `Session config patch failed (${res.status})`);\n }\n }\n\n async renameSession(sessionKey: string, name: string): Promise<{ ok: boolean }> {\n try {\n const res = await gatewayFetch(\n this.baseUrl,\n `/api/sessions/${encodeURIComponent(sessionKey)}/rename`,\n this.token,\n { method: 'POST', body: JSON.stringify({ name }) },\n );\n return { ok: res.ok };\n } catch {\n return { ok: false };\n }\n }\n\n async deleteSession(sessionKey: string): Promise<{ ok: boolean }> {\n try {\n const res = await gatewayFetch(\n this.baseUrl,\n `/api/sessions/${encodeURIComponent(sessionKey)}`,\n this.token,\n { method: 'DELETE' },\n );\n if (!res.ok) return { ok: false };\n const json = (await res.json()) as { deleted?: boolean };\n return { ok: json.deleted !== false };\n } catch {\n return { ok: false };\n }\n }\n\n // ── Broadcast SSE (GET /api/events) ──\n\n private startEventStream(): void {\n this.eventAbort?.abort();\n this.eventAbort = new AbortController();\n\n const url = new URL(`${this.baseUrl}/api/events`);\n if (this.token) url.searchParams.set('token', this.token);\n\n const connect = async () => {\n try {\n const res = await fetch(url.toString(), {\n signal: this.eventAbort!.signal,\n headers: { Accept: 'text/event-stream' },\n });\n\n if (!res.ok || !res.body) {\n this.onDisconnected?.(`event stream error: ${res.status}`);\n this.scheduleReconnect();\n return;\n }\n\n this.onConnected?.();\n\n await consumeSSEStream(\n res.body,\n (sseEvent) => {\n if (sseEvent.event === 'connected') return;\n if (sseEvent.event === 'gap') {\n const gapData = parseSSEData(sseEvent.data) as {\n expected?: unknown;\n received?: unknown;\n } | null;\n if (\n gapData &&\n typeof gapData.expected === 'number' &&\n typeof gapData.received === 'number'\n ) {\n this.onGap?.({ expected: gapData.expected, received: gapData.received });\n }\n return;\n }\n const data = parseSSEData(sseEvent.data);\n if (data !== null) {\n this.onEvent?.({ event: sseEvent.event, data, source: 'broadcast' });\n }\n },\n this.eventAbort!.signal,\n );\n\n // Stream ended normally\n if (!this.eventAbort?.signal.aborted) {\n this.onDisconnected?.('stream closed');\n this.scheduleReconnect();\n }\n } catch (error) {\n if (this.eventAbort?.signal.aborted) return;\n const errorMessage = error instanceof Error ? error.message : String(error);\n log.warn({ err: error, errorMessage }, `Event stream failed: ${errorMessage}`);\n this.onDisconnected?.(errorMessage);\n this.scheduleReconnect();\n }\n };\n\n void connect();\n }\n\n private scheduleReconnect(): void {\n if (this.eventAbort?.signal.aborted) return;\n setTimeout(() => {\n if (!this.eventAbort?.signal.aborted) {\n this.startEventStream();\n }\n }, 3000);\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"gateway-sse-backend.js","names":[],"sources":["../../../../src/tui/backends/gateway-sse-backend.ts"],"sourcesContent":["import { prependEnvelopeTimestamp } from '../../channels/envelope-timestamp.js';\nimport { parseModelRef } from '../../agent/models/selection.js';\nimport type { ExportFormat } from '../../session/types.js';\nimport type { TranscriptStoredRow } from '../../session/session-context-for-llm.js';\nimport { transcriptRowsToClientHistory } from '../../session/client-history.js';\nimport { createLogger } from '../../utils/logger.js';\nimport { consumeSSEStream, parseSSEData } from '../sse-consumer.js';\nimport type {\n ChatSendOptions,\n HistoryMessage,\n TuiBackend,\n TuiCompactionResult,\n TuiEvent,\n TuiModelChoice,\n TuiShareRequest,\n TuiShareResult,\n TuiSessionStats,\n TuiSessionItem,\n TuiStartupResources,\n TuiTranscriptTreeEntry,\n TuiAgentInfo,\n TuiWorkspaceFileSearchEntry,\n TuiWorkflowRunStartRequest,\n TuiWorkflowRunStartResult,\n} from '../tui-backend.js';\nimport type { SessionInfo } from '../tui-types.js';\nimport { computeTuiSessionStats } from '../tui-session-stats.js';\nimport { buildTuiTranscriptTree, transcriptTreeEntryIdToRowNumber } from '../tui-transcript-tree.js';\n\nconst log = createLogger('TUI:GatewaySSE');\n\ninterface GatewaySSEOptions {\n url: string;\n token?: string;\n}\n\nfunction normalizeGatewayModelChoice(model: TuiModelChoice): TuiModelChoice {\n const providerPrefix = `${model.provider}/`;\n const id = model.id.startsWith(providerPrefix)\n ? model.id.slice(providerPrefix.length)\n : model.id;\n return { ...model, id };\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return !!value && typeof value === 'object' && !Array.isArray(value);\n}\n\nexport function normalizeGatewaySseEvent(evt: TuiEvent): TuiEvent {\n if (evt.event !== 'agent.stream' || !isRecord(evt.data)) return evt;\n const inner = evt.data.event;\n if (!isRecord(inner) || typeof inner.type !== 'string' || !inner.type) return evt;\n return { event: inner.type, data: inner, source: evt.source };\n}\n\n/** Fetch wrapper that adds auth headers. */\nasync function gatewayFetch(\n baseUrl: string,\n path: string,\n token: string | undefined,\n init?: RequestInit,\n): Promise<Response> {\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n ...(token ? { Authorization: `Bearer ${token}` } : {}),\n ...(init?.headers as Record<string, string> | undefined),\n };\n return fetch(`${baseUrl}${path}`, { ...init, headers });\n}\n\n/**\n * TUI backend that communicates with a running xopc gateway via HTTP + SSE.\n *\n * - Agent streaming: `POST /api/agent` with `Accept: text/event-stream`\n * - Broadcast events: `GET /api/events` via long-lived SSE\n * - REST calls for sessions, models, etc.\n */\nexport class GatewaySseBackend implements TuiBackend {\n private readonly baseUrl: string;\n private readonly token: string | undefined;\n private eventAbort: AbortController | null = null;\n private chatAbort: AbortController | null = null;\n\n onEvent?: (evt: TuiEvent) => void;\n onConnected?: () => void;\n onDisconnected?: (reason: string) => void;\n onGap?: (info: { expected: number; received: number }) => void;\n\n constructor(opts: GatewaySSEOptions) {\n this.baseUrl = opts.url.replace(/\\/+$/, '');\n this.token = opts.token;\n }\n\n get connectionLabel(): string {\n return this.baseUrl;\n }\n\n start(): void {\n this.startEventStream();\n }\n\n stop(): void {\n this.eventAbort?.abort();\n this.eventAbort = null;\n this.chatAbort?.abort();\n this.chatAbort = null;\n }\n\n getActiveSignal(): AbortSignal | undefined {\n const signal = this.chatAbort?.signal;\n return signal && !signal.aborted ? signal : undefined;\n }\n\n // ── Agent chat (POST /api/agent → SSE response body) ──\n\n async sendChat(opts: ChatSendOptions): Promise<{ runId: string }> {\n this.chatAbort?.abort();\n this.chatAbort = new AbortController();\n const signal = this.chatAbort.signal;\n const runId = crypto.randomUUID();\n\n\n // Fire-and-forget: run the HTTP request + SSE consumption in background\n // so the TUI event loop stays responsive for keyboard input.\n void (async () => {\n try {\n const res = await gatewayFetch(this.baseUrl, '/api/agent', this.token, {\n method: 'POST',\n headers: { Accept: 'text/event-stream' },\n body: JSON.stringify({\n // Prepend envelope timestamp for regular messages so the model knows\n // the current date/time. Skip for slash commands — parseSlashCommand\n // requires lines starting with '/'.\n message: opts.message.trimStart().startsWith('/')\n ? opts.message\n : prependEnvelopeTimestamp(opts.message),\n channel: 'webchat',\n sessionKey: opts.sessionKey,\n attachments: opts.attachments,\n thinking: opts.thinking,\n }),\n signal,\n });\n\n if (!res.ok) {\n const body = (await res.json().catch(() => ({}))) as { error?: { message?: string } };\n this.onEvent?.({\n event: 'error',\n data: {\n type: 'error',\n runId,\n sessionKey: opts.sessionKey,\n timestamp: Date.now(),\n payload: { code: 'GATEWAY_ERROR', message: body.error?.message ?? `Gateway error: ${res.status}` },\n },\n source: 'agent-response',\n });\n return;\n }\n\n const contentType = res.headers.get('Content-Type') ?? '';\n\n if (contentType.includes('text/event-stream') && res.body) {\n await consumeSSEStream(\n res.body,\n (sseEvent) => {\n if (signal.aborted) return;\n const data = parseSSEData<Record<string, unknown>>(sseEvent.data);\n if (!data) return;\n this.onEvent?.({ event: sseEvent.event, data, source: 'agent-response' });\n },\n signal,\n );\n } else {\n const json = (await res.json()) as { ok?: boolean; payload?: { content?: string } };\n if (json.ok && json.payload?.content) {\n const messageId = `msg_${runId}_1`;\n const base = { runId, sessionKey: opts.sessionKey, timestamp: Date.now() };\n this.onEvent?.({ event: 'run_start', data: { ...base, type: 'run_start', payload: { channel: 'webchat' } }, source: 'agent-response' });\n this.onEvent?.({ event: 'assistant_message_start', data: { ...base, type: 'assistant_message_start', payload: { messageId } }, source: 'agent-response' });\n this.onEvent?.({ event: 'assistant_delta', data: { ...base, type: 'assistant_delta', payload: { messageId, delta: json.payload.content } }, source: 'agent-response' });\n this.onEvent?.({ event: 'assistant_message_end', data: { ...base, type: 'assistant_message_end', payload: { messageId } }, source: 'agent-response' });\n this.onEvent?.({ event: 'run_end', data: { ...base, type: 'run_end', payload: { status: 'success' } }, source: 'agent-response' });\n }\n }\n } catch (error) {\n if (signal.aborted) return;\n const errorMessage = error instanceof Error ? error.message : String(error);\n this.onEvent?.({\n event: 'error',\n data: { type: 'error', runId, sessionKey: opts.sessionKey, timestamp: Date.now(), payload: { code: 'NETWORK_ERROR', message: errorMessage } },\n source: 'agent-response',\n });\n }\n })();\n\n return { runId };\n }\n\n async searchWorkspaceFiles(\n sessionKey: string,\n query: string,\n options?: { limit?: number },\n ): Promise<TuiWorkspaceFileSearchEntry[]> {\n try {\n const params = new URLSearchParams();\n params.set('q', query);\n params.set('limit', String(options?.limit ?? 15));\n params.set('sessionKey', sessionKey);\n const res = await gatewayFetch(\n this.baseUrl,\n `/api/workspace/editor/files/search?${params.toString()}`,\n this.token,\n );\n if (!res.ok) return [];\n const json = (await res.json()) as {\n ok?: boolean;\n payload?: { entries?: TuiWorkspaceFileSearchEntry[] };\n };\n return json.payload?.entries ?? [];\n } catch (err) {\n const errorMessage = err instanceof Error ? err.message : String(err);\n log.warn({ err, sessionKey, errorMessage }, `Gateway workspace file search failed: ${errorMessage}`);\n return [];\n }\n }\n\n async startWorkflowRun(opts: TuiWorkflowRunStartRequest): Promise<TuiWorkflowRunStartResult> {\n const goal = opts.goal?.trim();\n const res = await gatewayFetch(this.baseUrl, '/api/workflows/runs', this.token, {\n method: 'POST',\n body: JSON.stringify({\n definitionId: opts.definitionId,\n agentId: opts.agentId,\n parentSessionKey: opts.sessionKey,\n source: { kind: 'chat', sessionKey: opts.sessionKey },\n ...(goal ? { goal } : {}),\n ...(opts.input !== undefined ? { input: opts.input } : {}),\n }),\n });\n const json = (await res.json().catch(() => ({}))) as {\n runId?: string;\n sessionKey?: string;\n error?: string;\n code?: string;\n };\n if (!res.ok || !json.runId || !json.sessionKey) {\n throw new Error(json.error ?? `Workflow start failed (${res.status})`);\n }\n return {\n runId: json.runId,\n sessionKey: json.sessionKey,\n definitionId: opts.definitionId,\n };\n }\n\n async resumeChat(opts: { sessionKey: string; runId: string }): Promise<{ ok: boolean; reason?: string }> {\n this.chatAbort?.abort();\n this.chatAbort = new AbortController();\n const signal = this.chatAbort.signal;\n this.onEvent?.({\n event: 'run_start',\n data: { type: 'run_start', runId: opts.runId, sessionKey: opts.sessionKey, timestamp: Date.now(), payload: { channel: 'webchat' } },\n source: 'agent-resume',\n });\n\n let res: Response;\n try {\n res = await gatewayFetch(this.baseUrl, '/api/agent/resume', this.token, {\n method: 'POST',\n headers: { Accept: 'text/event-stream' },\n body: JSON.stringify({ runId: opts.runId, sessionKey: opts.sessionKey }),\n signal,\n });\n } catch (error) {\n if (signal.aborted) return { ok: false, reason: 'resume aborted' };\n const errorMessage = error instanceof Error ? error.message : String(error);\n return { ok: false, reason: errorMessage };\n }\n\n if (!res.ok) {\n const body = (await res.json().catch(() => ({}))) as { error?: { message?: string } };\n return { ok: false, reason: body.error?.message ?? `Resume failed: ${res.status}` };\n }\n\n const contentType = res.headers.get('Content-Type') ?? '';\n if (!contentType.includes('text/event-stream') || !res.body) {\n return { ok: false, reason: 'Resume endpoint did not return an SSE stream' };\n }\n\n void (async () => {\n try {\n await consumeSSEStream(\n res.body,\n (sseEvent) => {\n if (signal.aborted) return;\n const data = parseSSEData<Record<string, unknown>>(sseEvent.data);\n if (!data) return;\n this.onEvent?.({ event: sseEvent.event, data, source: 'agent-resume' });\n },\n signal,\n );\n } catch (error) {\n if (signal.aborted) return;\n const errorMessage = error instanceof Error ? error.message : String(error);\n this.onEvent?.({\n event: 'error',\n data: { type: 'error', runId: opts.runId, sessionKey: opts.sessionKey, timestamp: Date.now(), payload: { code: 'NETWORK_ERROR', message: errorMessage } },\n source: 'agent-resume',\n });\n }\n })();\n\n return { ok: true };\n }\n\n async abortChat(opts: { sessionKey: string; runId: string }): Promise<{ ok: boolean }> {\n this.chatAbort?.abort();\n this.chatAbort = null;\n try {\n const res = await gatewayFetch(this.baseUrl, '/api/agent/abort', this.token, {\n method: 'POST',\n body: JSON.stringify({ runId: opts.runId }),\n });\n const json = (await res.json()) as { ok?: boolean };\n return { ok: json.ok ?? false };\n } catch {\n return { ok: false };\n }\n }\n\n async steerChat(opts: { sessionKey: string; message: string }): Promise<{ ok: boolean }> {\n try {\n const res = await gatewayFetch(this.baseUrl, '/api/agent/steer', this.token, {\n method: 'POST',\n body: JSON.stringify({ sessionKey: opts.sessionKey, message: opts.message }),\n });\n if (!res.ok) return { ok: false };\n const json = (await res.json()) as { ok?: boolean };\n return { ok: json.ok === true };\n } catch {\n return { ok: false };\n }\n }\n\n // ── REST helpers ──\n\n async getStartupResources(sessionKey: string): Promise<TuiStartupResources> {\n const empty: TuiStartupResources = { context: [], skills: [], workflows: [], connectors: [] };\n try {\n const res = await gatewayFetch(\n this.baseUrl,\n `/api/tui/startup-resources?sessionKey=${encodeURIComponent(sessionKey)}`,\n this.token,\n );\n if (!res.ok) return empty;\n const json = (await res.json()) as { payload?: Partial<TuiStartupResources> };\n return {\n context: Array.isArray(json.payload?.context) ? json.payload.context : [],\n skills: Array.isArray(json.payload?.skills) ? json.payload.skills : [],\n workflows: Array.isArray(json.payload?.workflows) ? json.payload.workflows : [],\n connectors: Array.isArray(json.payload?.connectors) ? json.payload.connectors : [],\n };\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n log.warn({ err: error, sessionKey, errorMessage }, `Failed to load startup resources: ${errorMessage}`);\n return empty;\n }\n }\n\n async loadHistory(opts: {\n sessionKey: string;\n limit?: number;\n }): Promise<{ messages: HistoryMessage[] }> {\n try {\n const res = await gatewayFetch(\n this.baseUrl,\n `/api/sessions/${encodeURIComponent(opts.sessionKey)}?include=transcriptRows`,\n this.token,\n );\n if (!res.ok) return { messages: [] };\n const json = (await res.json()) as {\n session?: { transcriptRows?: unknown[] };\n };\n const rows = Array.isArray(json.session?.transcriptRows)\n ? (json.session.transcriptRows as TranscriptStoredRow[])\n : [];\n return { messages: transcriptRowsToClientHistory(rows, { limit: opts.limit }) };\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n log.warn({ err: error, errorMessage }, `Failed to load history: ${errorMessage}`);\n return { messages: [] };\n }\n }\n\n async loadTranscriptTree(sessionKey: string): Promise<TuiTranscriptTreeEntry[]> {\n try {\n const res = await gatewayFetch(\n this.baseUrl,\n `/api/sessions/${encodeURIComponent(sessionKey)}?include=transcriptRows`,\n this.token,\n );\n if (!res.ok) return [];\n const json = (await res.json()) as {\n session?: { transcriptRows?: unknown[] };\n };\n const rows = Array.isArray(json.session?.transcriptRows)\n ? (json.session.transcriptRows as TranscriptStoredRow[])\n : [];\n return buildTuiTranscriptTree(rows);\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n log.warn({ err: error, sessionKey, errorMessage }, `Failed to load transcript tree: ${errorMessage}`);\n return [];\n }\n }\n\n async getSessionStats(sessionKey: string): Promise<TuiSessionStats> {\n try {\n const res = await gatewayFetch(\n this.baseUrl,\n `/api/sessions/${encodeURIComponent(sessionKey)}?include=transcriptRows`,\n this.token,\n );\n if (!res.ok) return computeTuiSessionStats([]);\n const json = (await res.json()) as {\n session?: { transcriptRows?: unknown[] };\n };\n const rows = Array.isArray(json.session?.transcriptRows)\n ? (json.session.transcriptRows as TranscriptStoredRow[])\n : [];\n return computeTuiSessionStats(rows);\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n log.warn({ err: error, sessionKey, errorMessage }, `Failed to load session stats: ${errorMessage}`);\n return computeTuiSessionStats([]);\n }\n }\n\n async listSessions(): Promise<TuiSessionItem[]> {\n try {\n const res = await gatewayFetch(this.baseUrl, '/api/sessions', this.token);\n if (!res.ok) return [];\n const json = (await res.json()) as {\n items?: Array<{\n key: string;\n name?: string;\n updatedAt?: string;\n estimatedTokens?: number;\n messageCount?: number;\n customData?: Record<string, unknown>;\n cwd?: string;\n }>;\n };\n return (json.items ?? []).map((s) => ({\n key: s.key,\n displayName: s.name,\n updatedAt: s.updatedAt ? Date.parse(s.updatedAt) : undefined,\n totalTokens: s.estimatedTokens ?? null,\n messageCount: typeof s.messageCount === 'number' ? s.messageCount : undefined,\n model:\n typeof s.customData?.model === 'string'\n ? s.customData.model\n : typeof s.customData?.modelRef === 'string'\n ? s.customData.modelRef\n : null,\n forkedFromSessionKey:\n typeof s.customData?.forkedFromSessionKey === 'string'\n ? s.customData.forkedFromSessionKey\n : undefined,\n cwd: typeof s.cwd === 'string' ? s.cwd : undefined,\n }));\n } catch {\n return [];\n }\n }\n\n async listAgents(): Promise<TuiAgentInfo[]> {\n const agents = new Map<string, TuiAgentInfo>();\n try {\n const res = await gatewayFetch(this.baseUrl, '/api/agents', this.token);\n if (res.ok) {\n const json = (await res.json()) as {\n payload?: { agents?: Array<{ id?: unknown; name?: unknown }> };\n };\n for (const row of json.payload?.agents ?? []) {\n if (typeof row.id !== 'string' || !row.id.trim()) continue;\n const id = row.id.trim().toLowerCase();\n agents.set(id, {\n id,\n enabled: true,\n ...(typeof row.name === 'string' && row.name.trim()\n ? { displayName: row.name.trim() }\n : {}),\n });\n }\n }\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n log.warn({ err: error, errorMessage }, `Failed to load agents: ${errorMessage}`);\n }\n return [...agents.values()].sort((a, b) => a.id.localeCompare(b.id));\n }\n\n async setTuiDefaultAgent(agentId: string): Promise<{ agentId: string }> {\n const target = agentId.trim().toLowerCase();\n const res = await gatewayFetch(this.baseUrl, '/api/config', this.token, {\n method: 'PATCH',\n body: JSON.stringify({ tui: { defaultAgent: target } }),\n });\n const json = (await res.json().catch(() => ({}))) as {\n ok?: boolean;\n error?: { message?: string } | string;\n payload?: { config?: { tui?: { defaultAgent?: unknown } } };\n };\n if (!res.ok || json.ok === false) {\n const error =\n typeof json.error === 'string'\n ? json.error\n : json.error?.message;\n throw new Error(error ?? `TUI default agent update failed (${res.status})`);\n }\n const saved = json.payload?.config?.tui?.defaultAgent;\n return { agentId: typeof saved === 'string' && saved.trim() ? saved.trim().toLowerCase() : target };\n }\n\n async getSessionInfo(sessionKey: string): Promise<SessionInfo> {\n const out: SessionInfo = {};\n try {\n const sessionPath = `/api/sessions/${encodeURIComponent(sessionKey)}`;\n const [sessionRes, agentCfgRes] = await Promise.all([\n gatewayFetch(this.baseUrl, sessionPath, this.token),\n gatewayFetch(this.baseUrl, `${sessionPath}/agent-config`, this.token),\n ]);\n\n type SessionRow = {\n name?: string;\n estimatedTokens?: number;\n customData?: Record<string, unknown>;\n };\n let session: SessionRow | undefined;\n\n if (sessionRes.ok) {\n const json = (await sessionRes.json()) as { session?: SessionRow };\n session = json.session;\n if (session) {\n if (session.name) out.displayName = session.name;\n if (session.estimatedTokens != null) out.totalTokens = session.estimatedTokens;\n }\n }\n\n if (agentCfgRes.ok) {\n const json = (await agentCfgRes.json()) as {\n ok?: boolean;\n payload?: {\n model?: string;\n thinkingLevel?: string;\n reasoningLevel?: string;\n verboseLevel?: string;\n effectiveWorkspacePath?: string;\n workingDirectoryLocked?: boolean;\n };\n };\n const p = json.payload;\n if (p?.model && typeof p.model === 'string') {\n const parsed = parseModelRef(p.model);\n if (parsed) {\n out.model = parsed.model;\n out.modelProvider = parsed.provider;\n } else {\n out.model = p.model;\n }\n }\n if (p?.thinkingLevel && typeof p.thinkingLevel === 'string') {\n out.thinkingLevel = p.thinkingLevel;\n }\n if (p?.reasoningLevel && typeof p.reasoningLevel === 'string') {\n out.reasoningLevel = p.reasoningLevel;\n }\n if (p?.verboseLevel && typeof p.verboseLevel === 'string') {\n out.verboseLevel = p.verboseLevel;\n }\n if (p?.effectiveWorkspacePath && typeof p.effectiveWorkspacePath === 'string') {\n out.effectiveWorkspacePath = p.effectiveWorkspacePath;\n }\n if (typeof p?.workingDirectoryLocked === 'boolean') {\n out.workingDirectoryLocked = p.workingDirectoryLocked;\n }\n }\n\n if (!out.model && session?.customData) {\n const cd = session.customData;\n const ref =\n typeof cd.model === 'string'\n ? cd.model\n : typeof cd.modelRef === 'string'\n ? cd.modelRef\n : undefined;\n if (ref) {\n const parsed = parseModelRef(ref);\n if (parsed) {\n out.model = parsed.model;\n out.modelProvider = parsed.provider;\n } else {\n out.model = ref;\n }\n }\n if (!out.modelProvider && typeof cd.modelProvider === 'string') {\n out.modelProvider = cd.modelProvider;\n }\n }\n\n if (out.totalTokens != null) {\n const models = await this.listModels();\n const match = models.find(\n (m) =>\n m.id === out.model &&\n (!out.modelProvider || m.provider === out.modelProvider),\n );\n const contextWindow = match?.contextWindow ?? 128_000;\n out.contextWindow = contextWindow;\n out.contextUsagePercent =\n contextWindow > 0\n ? Math.min(100, Math.round((out.totalTokens / contextWindow) * 100))\n : null;\n }\n\n return out;\n } catch {\n return {};\n }\n }\n\n async listModels(): Promise<TuiModelChoice[]> {\n try {\n const res = await gatewayFetch(this.baseUrl, '/api/models', this.token);\n if (!res.ok) return [];\n const json = (await res.json()) as {\n ok?: boolean;\n payload?: { models?: TuiModelChoice[] };\n };\n return (json.payload?.models ?? []).map(normalizeGatewayModelChoice);\n } catch {\n return [];\n }\n }\n\n async resetSession(sessionKey: string): Promise<void> {\n await gatewayFetch(\n this.baseUrl,\n `/api/sessions/${encodeURIComponent(sessionKey)}/reset`,\n this.token,\n { method: 'POST' },\n ).catch(() => {});\n }\n\n async compactSession(\n sessionKey: string,\n options?: { force?: boolean; instructions?: string },\n ): Promise<TuiCompactionResult> {\n try {\n const res = await gatewayFetch(\n this.baseUrl,\n `/api/sessions/${encodeURIComponent(sessionKey)}/compaction/run`,\n this.token,\n {\n method: 'POST',\n body: JSON.stringify({\n force: options?.force ?? true,\n instructions: options?.instructions,\n }),\n },\n );\n if (!res.ok) {\n return { compacted: false, summary: `Compaction failed (${res.status})` };\n }\n const json = (await res.json()) as {\n ok?: boolean;\n payload?: {\n result?: {\n compacted?: boolean;\n summary?: string;\n tokensBefore?: number;\n tokensAfter?: number;\n };\n };\n };\n const result = json.payload?.result;\n if (!result?.compacted) {\n return { compacted: false, summary: 'Nothing to compact' };\n }\n return {\n compacted: true,\n summary: `Compacted (${result.tokensBefore ?? '?'} → ${result.tokensAfter ?? '?'} tokens)`,\n tokensBefore: result.tokensBefore,\n tokensAfter: result.tokensAfter,\n transcriptSummary: result.summary,\n };\n } catch (err) {\n const errorMessage = err instanceof Error ? err.message : String(err);\n return { compacted: false, summary: errorMessage };\n }\n }\n\n async exportSession(sessionKey: string, format: ExportFormat): Promise<string> {\n const params = new URLSearchParams({ format });\n const res = await gatewayFetch(\n this.baseUrl,\n `/api/sessions/${encodeURIComponent(sessionKey)}/export?${params.toString()}`,\n this.token,\n );\n if (!res.ok) {\n throw new Error(`Export failed (${res.status})`);\n }\n const json = (await res.json()) as { content?: string };\n return json.content ?? '';\n }\n\n async importSession(\n targetSessionKey: string,\n jsonContent: string,\n ): Promise<{ sessionKey: string; rowCount: number }> {\n const res = await gatewayFetch(\n this.baseUrl,\n '/api/sessions/import',\n this.token,\n { method: 'POST', body: JSON.stringify({ targetKey: targetSessionKey, content: jsonContent }) },\n );\n const json = (await res.json().catch(() => ({}))) as {\n ok?: boolean;\n error?: string;\n sessionKey?: string;\n rowCount?: number;\n };\n if (!res.ok || json.ok === false || !json.sessionKey) {\n throw new Error(json.error ?? `Import failed (${res.status})`);\n }\n return { sessionKey: json.sessionKey, rowCount: json.rowCount ?? 0 };\n }\n\n async createShare(\n sessionKey: string,\n request: TuiShareRequest,\n options?: { agentId?: string },\n ): Promise<TuiShareResult> {\n const res = await gatewayFetch(this.baseUrl, '/api/shares/auto', this.token, {\n method: 'POST',\n body: JSON.stringify({\n path: request.path,\n audience: request.audience,\n mode: request.mode,\n title: request.title,\n description: request.description,\n sessionKey,\n agentId: options?.agentId,\n }),\n });\n const json = (await res.json().catch(() => ({}))) as {\n ok?: boolean;\n error?: { message?: string };\n payload?: {\n share?: {\n kind?: string;\n title?: string;\n description?: string;\n shareUrl?: string;\n reachability?: string;\n reachabilityHint?: string | null;\n expiresAt?: string;\n maxViews?: number | null;\n };\n thumbnail?: { url?: string };\n routing?: { reason?: string; hint?: string };\n };\n };\n if (!res.ok || json.ok === false || !json.payload?.share?.shareUrl) {\n throw new Error(json.error?.message ?? `Share failed (${res.status})`);\n }\n const share = json.payload.share;\n return {\n kind: share.kind ?? 'share',\n shareUrl: share.shareUrl,\n title: share.title,\n description: share.description,\n thumbnailUrl: json.payload.thumbnail?.url,\n reachability: share.reachability,\n reachabilityHint: share.reachabilityHint,\n expiresAt: share.expiresAt,\n maxViews: share.maxViews,\n routingReason: json.payload.routing?.reason,\n routingHint: json.payload.routing?.hint,\n };\n }\n\n async btwQuery(sessionKey: string, question: string): Promise<{ text: string; error?: string }> {\n const res = await gatewayFetch(\n this.baseUrl,\n `/api/sessions/${encodeURIComponent(sessionKey)}/btw`,\n this.token,\n { method: 'POST', body: JSON.stringify({ question }) },\n );\n if (!res.ok) {\n return { text: '', error: `BTW failed (${res.status})` };\n }\n return (await res.json()) as { text: string; error?: string };\n }\n\n async forkSession(\n sourceSessionKey: string,\n targetSessionKey: string,\n ): Promise<{ sessionKey: string; rowCount: number }> {\n const res = await gatewayFetch(\n this.baseUrl,\n `/api/sessions/${encodeURIComponent(sourceSessionKey)}/fork`,\n this.token,\n { method: 'POST', body: JSON.stringify({ targetKey: targetSessionKey }) },\n );\n const json = (await res.json().catch(() => ({}))) as {\n ok?: boolean;\n error?: string;\n sessionKey?: string;\n rowCount?: number;\n };\n if (!res.ok || json.ok === false || !json.sessionKey) {\n throw new Error(json.error ?? `Fork failed (${res.status})`);\n }\n return { sessionKey: json.sessionKey, rowCount: json.rowCount ?? 0 };\n }\n\n async forkSessionAt(\n sourceSessionKey: string,\n targetSessionKey: string,\n entryId: string,\n ): Promise<{ sessionKey: string; rowCount: number }> {\n const throughRow = transcriptTreeEntryIdToRowNumber(entryId);\n if (throughRow == null) {\n throw new Error(`Invalid transcript entry: ${entryId}`);\n }\n const res = await gatewayFetch(\n this.baseUrl,\n `/api/sessions/${encodeURIComponent(sourceSessionKey)}/fork-row`,\n this.token,\n { method: 'POST', body: JSON.stringify({ targetKey: targetSessionKey, throughRow }) },\n );\n const json = (await res.json().catch(() => ({}))) as {\n ok?: boolean;\n error?: string;\n sessionKey?: string;\n rowCount?: number;\n };\n if (!res.ok || json.ok === false || !json.sessionKey) {\n throw new Error(json.error ?? `Fork failed (${res.status})`);\n }\n return { sessionKey: json.sessionKey, rowCount: json.rowCount ?? 0 };\n }\n\n async setTranscriptLabel(\n sessionKey: string,\n entryId: string,\n label: string | undefined,\n ): Promise<{ ok: boolean }> {\n const res = await gatewayFetch(\n this.baseUrl,\n `/api/sessions/${encodeURIComponent(sessionKey)}/transcript/label`,\n this.token,\n { method: 'POST', body: JSON.stringify({ targetId: entryId, label }) },\n );\n const json = (await res.json().catch(() => ({}))) as { ok?: boolean; error?: string };\n if (!res.ok || json.ok === false) {\n throw new Error(json.error ?? `Label update failed (${res.status})`);\n }\n return { ok: true };\n }\n\n async appendCustomEntry(\n sessionKey: string,\n customType: string,\n data?: unknown,\n ): Promise<{ ok: boolean }> {\n const res = await gatewayFetch(\n this.baseUrl,\n `/api/sessions/${encodeURIComponent(sessionKey)}/transcript/custom`,\n this.token,\n { method: 'POST', body: JSON.stringify({ customType, data }) },\n );\n const json = (await res.json().catch(() => ({}))) as { ok?: boolean; error?: string };\n if (!res.ok || json.ok === false) {\n throw new Error(json.error ?? `Custom entry append failed (${res.status})`);\n }\n return { ok: true };\n }\n\n async appendCustomMessage(\n sessionKey: string,\n message: {\n customType: string;\n content?: string | unknown[];\n display?: boolean;\n details?: unknown;\n },\n ): Promise<{ ok: boolean }> {\n const res = await gatewayFetch(\n this.baseUrl,\n `/api/sessions/${encodeURIComponent(sessionKey)}/transcript/custom-message`,\n this.token,\n { method: 'POST', body: JSON.stringify(message) },\n );\n const json = (await res.json().catch(() => ({}))) as { ok?: boolean; error?: string };\n if (!res.ok || json.ok === false) {\n throw new Error(json.error ?? `Custom message append failed (${res.status})`);\n }\n return { ok: true };\n }\n\n async appendBashExecution(\n sessionKey: string,\n entry: {\n command: string;\n output?: string;\n exitCode?: number | null;\n signal?: string | null;\n excludeFromContext?: boolean;\n truncated?: boolean;\n fullOutputPath?: string;\n },\n ): Promise<{ ok: boolean }> {\n const res = await gatewayFetch(\n this.baseUrl,\n `/api/sessions/${encodeURIComponent(sessionKey)}/transcript/bash`,\n this.token,\n { method: 'POST', body: JSON.stringify(entry) },\n );\n const json = (await res.json().catch(() => ({}))) as { ok?: boolean; error?: string };\n if (!res.ok || json.ok === false) {\n throw new Error(json.error ?? `Bash execution append failed (${res.status})`);\n }\n return { ok: true };\n }\n\n async patchSession(sessionKey: string, patch: Record<string, unknown>): Promise<void> {\n const res = await gatewayFetch(\n this.baseUrl,\n `/api/sessions/${encodeURIComponent(sessionKey)}/agent-config`,\n this.token,\n { method: 'PATCH', body: JSON.stringify(patch) },\n );\n const json = (await res.json().catch(() => ({}))) as { ok?: boolean; error?: string };\n if (!res.ok || json.ok === false) {\n throw new Error(json.error ?? `Session config patch failed (${res.status})`);\n }\n }\n\n async renameSession(sessionKey: string, name: string): Promise<{ ok: boolean }> {\n try {\n const res = await gatewayFetch(\n this.baseUrl,\n `/api/sessions/${encodeURIComponent(sessionKey)}/rename`,\n this.token,\n { method: 'POST', body: JSON.stringify({ name }) },\n );\n return { ok: res.ok };\n } catch {\n return { ok: false };\n }\n }\n\n async deleteSession(sessionKey: string): Promise<{ ok: boolean }> {\n try {\n const res = await gatewayFetch(\n this.baseUrl,\n `/api/sessions/${encodeURIComponent(sessionKey)}`,\n this.token,\n { method: 'DELETE' },\n );\n if (!res.ok) return { ok: false };\n const json = (await res.json()) as { deleted?: boolean };\n return { ok: json.deleted !== false };\n } catch {\n return { ok: false };\n }\n }\n\n // ── Broadcast SSE (GET /api/events) ──\n\n private startEventStream(): void {\n this.eventAbort?.abort();\n this.eventAbort = new AbortController();\n\n const url = new URL(`${this.baseUrl}/api/events`);\n if (this.token) url.searchParams.set('token', this.token);\n\n const connect = async () => {\n try {\n const res = await fetch(url.toString(), {\n signal: this.eventAbort!.signal,\n headers: { Accept: 'text/event-stream' },\n });\n\n if (!res.ok || !res.body) {\n this.onDisconnected?.(`event stream error: ${res.status}`);\n this.scheduleReconnect();\n return;\n }\n\n this.onConnected?.();\n\n await consumeSSEStream(\n res.body,\n (sseEvent) => {\n if (sseEvent.event === 'connected') return;\n if (sseEvent.event === 'gap') {\n const gapData = parseSSEData(sseEvent.data) as {\n expected?: unknown;\n received?: unknown;\n } | null;\n if (\n gapData &&\n typeof gapData.expected === 'number' &&\n typeof gapData.received === 'number'\n ) {\n this.onGap?.({ expected: gapData.expected, received: gapData.received });\n }\n return;\n }\n const data = parseSSEData(sseEvent.data);\n if (data !== null) {\n this.onEvent?.(normalizeGatewaySseEvent({ event: sseEvent.event, data, source: 'broadcast' }));\n }\n },\n this.eventAbort!.signal,\n );\n\n // Stream ended normally\n if (!this.eventAbort?.signal.aborted) {\n this.onDisconnected?.('stream closed');\n this.scheduleReconnect();\n }\n } catch (error) {\n if (this.eventAbort?.signal.aborted) return;\n const errorMessage = error instanceof Error ? error.message : String(error);\n log.warn({ err: error, errorMessage }, `Event stream failed: ${errorMessage}`);\n this.onDisconnected?.(errorMessage);\n this.scheduleReconnect();\n }\n };\n\n void connect();\n }\n\n private scheduleReconnect(): void {\n if (this.eventAbort?.signal.aborted) return;\n setTimeout(() => {\n if (!this.eventAbort?.signal.aborted) {\n this.startEventStream();\n }\n }, 3000);\n }\n}\n"],"mappings":"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"}
@@ -17,7 +17,6 @@ export declare class TuiHeader implements Component {
17
17
  setCustomComponent(component: Component | undefined): void;
18
18
  invalidate(): void;
19
19
  private getCompactHints;
20
- private getExpandedHints;
21
20
  render(width: number): string[];
22
21
  private customComponent;
23
22
  }
@@ -1,9 +1,9 @@
1
1
  import { theme } from "../theme.js";
2
2
  import { formatKeyIds } from "../format-tui-hotkeys.js";
3
- import { truncateToWidth, visibleWidth } from "@earendil-works/pi-tui";
3
+ import { truncateToWidth } from "@earendil-works/pi-tui";
4
4
  //#region src/tui/components/tui-header.ts
5
5
  const COMPACT_HINTS = "escape interrupt · ctrl+c/ctrl+d clear/exit · / commands · ! bash · ctrl+o tools";
6
- const EXPANDED_HINTS = ["Press /start to show full startup help and loaded resources.", "xopc can use skills, workflows, connectors, and project context."];
6
+ const STARTUP_HELP_HINT = "Press /start to show full startup help and loaded resources.";
7
7
  /** Collapsible startup header (pi-style hints subset). */
8
8
  var TuiHeader = class {
9
9
  extensionLines = [];
@@ -26,18 +26,13 @@ var TuiHeader = class {
26
26
  if (!this.keybindings) return COMPACT_HINTS;
27
27
  return `${formatKeyIds(this.keybindings, "app.interrupt", { capitalize: false })} interrupt · ${formatKeyIds(this.keybindings, "app.clear", { capitalize: false })}/${formatKeyIds(this.keybindings, "app.exit", { capitalize: false })} clear/exit · / commands · ! bash · ${formatKeyIds(this.keybindings, "app.tools.expand", { capitalize: false })} tools`;
28
28
  }
29
- getExpandedHints() {
30
- if (!this.keybindings) return EXPANDED_HINTS;
31
- return EXPANDED_HINTS;
32
- }
33
29
  render(width) {
34
30
  if (this.customComponent) return this.customComponent.render(width).map((line) => truncateToWidth(line, width, theme.dim("…")));
35
31
  const { version, connectionLabel, sessionKey, showHints } = this.getModel();
36
32
  const lines = [truncateToWidth(theme.header(`xopc tui v${version} — ${connectionLabel} — ${sessionKey}`), width, theme.dim("…"))];
37
33
  if (showHints) {
38
34
  lines.push(truncateToWidth(theme.dim(this.getCompactHints()), width, theme.dim("…")));
39
- for (const hint of this.getExpandedHints()) if (visibleWidth(hint) <= width) lines.push(theme.dim(hint));
40
- else lines.push(truncateToWidth(theme.dim(hint), width, theme.dim("…")));
35
+ lines.push(truncateToWidth(theme.dim(STARTUP_HELP_HINT), width, theme.dim("…")));
41
36
  }
42
37
  for (const extLine of this.extensionLines) lines.push(truncateToWidth(theme.dim(extLine), width, theme.dim("…")));
43
38
  for (const component of this.extensionComponents) for (const line of component.render(width)) lines.push(truncateToWidth(line, width, theme.dim("…")));
@@ -1 +1 @@
1
- {"version":3,"file":"tui-header.js","names":[],"sources":["../../../../src/tui/components/tui-header.ts"],"sourcesContent":["import type { Component, KeybindingsManager } from '@earendil-works/pi-tui';\nimport { truncateToWidth, visibleWidth } from '@earendil-works/pi-tui';\n\nimport { theme } from '../theme.js';\nimport { formatKeyIds } from '../format-tui-hotkeys.js';\n\nexport type TuiHeaderModel = {\n version: string;\n connectionLabel: string;\n sessionKey: string;\n showHints: boolean;\n};\n\nconst COMPACT_HINTS =\n 'escape interrupt · ctrl+c/ctrl+d clear/exit · / commands · ! bash · ctrl+o tools';\n\nconst EXPANDED_HINTS = [\n 'Press /start to show full startup help and loaded resources.',\n 'xopc can use skills, workflows, connectors, and project context.',\n];\n\n/** Collapsible startup header (pi-style hints subset). */\nexport class TuiHeader implements Component {\n private extensionLines: string[] = [];\n private extensionComponents: Component[] = [];\n\n constructor(\n private readonly getModel: () => TuiHeaderModel,\n private readonly keybindings?: KeybindingsManager,\n ) {}\n\n setExtensionLines(lines: string[]): void {\n this.extensionLines = lines;\n }\n\n setExtensionComponents(components: Component[]): void {\n this.extensionComponents = components;\n }\n\n setCustomComponent(component: Component | undefined): void {\n this.customComponent = component;\n }\n\n invalidate(): void {}\n\n private getCompactHints(): string {\n if (!this.keybindings) return COMPACT_HINTS;\n const interrupt = formatKeyIds(this.keybindings, 'app.interrupt', { capitalize: false });\n const clear = formatKeyIds(this.keybindings, 'app.clear', { capitalize: false });\n const exit = formatKeyIds(this.keybindings, 'app.exit', { capitalize: false });\n const tools = formatKeyIds(this.keybindings, 'app.tools.expand', { capitalize: false });\n return `${interrupt} interrupt · ${clear}/${exit} clear/exit · / commands · ! bash · ${tools} tools`;\n }\n\n private getExpandedHints(): string[] {\n if (!this.keybindings) return EXPANDED_HINTS;\n return EXPANDED_HINTS;\n }\n\n render(width: number): string[] {\n if (this.customComponent) {\n const rendered = this.customComponent.render(width);\n return rendered.map((line) => truncateToWidth(line, width, theme.dim('…')));\n }\n\n const { version, connectionLabel, sessionKey, showHints } = this.getModel();\n const title = theme.header(`xopc tui v${version} — ${connectionLabel} — ${sessionKey}`);\n const lines = [truncateToWidth(title, width, theme.dim('…'))];\n\n if (showHints) {\n lines.push(truncateToWidth(theme.dim(this.getCompactHints()), width, theme.dim('…')));\n for (const hint of this.getExpandedHints()) {\n if (visibleWidth(hint) <= width) {\n lines.push(theme.dim(hint));\n } else {\n lines.push(truncateToWidth(theme.dim(hint), width, theme.dim('…')));\n }\n }\n }\n\n for (const extLine of this.extensionLines) {\n lines.push(truncateToWidth(theme.dim(extLine), width, theme.dim('…')));\n }\n for (const component of this.extensionComponents) {\n for (const line of component.render(width)) {\n lines.push(truncateToWidth(line, width, theme.dim('…')));\n }\n }\n\n return lines;\n }\n\n private customComponent: Component | undefined;\n}\n"],"mappings":";;;;AAaA,MAAM,gBACJ;AAEF,MAAM,iBAAiB,CACrB,gEACA,mEACD;;AAGD,IAAa,YAAb,MAA4C;CAC1C,iBAAmC,EAAE;CACrC,sBAA2C,EAAE;CAE7C,YACE,UACA,aACA;AAFiB,OAAA,WAAA;AACA,OAAA,cAAA;;CAGnB,kBAAkB,OAAuB;AACvC,OAAK,iBAAiB;;CAGxB,uBAAuB,YAA+B;AACpD,OAAK,sBAAsB;;CAG7B,mBAAmB,WAAwC;AACzD,OAAK,kBAAkB;;CAGzB,aAAmB;CAEnB,kBAAkC;AAChC,MAAI,CAAC,KAAK,YAAa,QAAO;AAK9B,SAAO,GAJW,aAAa,KAAK,aAAa,iBAAiB,EAAE,YAAY,OAAO,CAIpE,CAAC,eAHN,aAAa,KAAK,aAAa,aAAa,EAAE,YAAY,OAAO,CAGvC,CAAC,GAF5B,aAAa,KAAK,aAAa,YAAY,EAAE,YAAY,OAAO,CAE7B,CAAC,sCADnC,aAAa,KAAK,aAAa,oBAAoB,EAAE,YAAY,OAAO,CACM,CAAC;;CAG/F,mBAAqC;AACnC,MAAI,CAAC,KAAK,YAAa,QAAO;AAC9B,SAAO;;CAGT,OAAO,OAAyB;AAC9B,MAAI,KAAK,gBAEP,QADiB,KAAK,gBAAgB,OAAO,MAC9B,CAAC,KAAK,SAAS,gBAAgB,MAAM,OAAO,MAAM,IAAI,IAAI,CAAC,CAAC;EAG7E,MAAM,EAAE,SAAS,iBAAiB,YAAY,cAAc,KAAK,UAAU;EAE3E,MAAM,QAAQ,CAAC,gBADD,MAAM,OAAO,aAAa,QAAQ,KAAK,gBAAgB,KAAK,aACtC,EAAE,OAAO,MAAM,IAAI,IAAI,CAAC,CAAC;AAE7D,MAAI,WAAW;AACb,SAAM,KAAK,gBAAgB,MAAM,IAAI,KAAK,iBAAiB,CAAC,EAAE,OAAO,MAAM,IAAI,IAAI,CAAC,CAAC;AACrF,QAAK,MAAM,QAAQ,KAAK,kBAAkB,CACxC,KAAI,aAAa,KAAK,IAAI,MACxB,OAAM,KAAK,MAAM,IAAI,KAAK,CAAC;OAE3B,OAAM,KAAK,gBAAgB,MAAM,IAAI,KAAK,EAAE,OAAO,MAAM,IAAI,IAAI,CAAC,CAAC;;AAKzE,OAAK,MAAM,WAAW,KAAK,eACzB,OAAM,KAAK,gBAAgB,MAAM,IAAI,QAAQ,EAAE,OAAO,MAAM,IAAI,IAAI,CAAC,CAAC;AAExE,OAAK,MAAM,aAAa,KAAK,oBAC3B,MAAK,MAAM,QAAQ,UAAU,OAAO,MAAM,CACxC,OAAM,KAAK,gBAAgB,MAAM,OAAO,MAAM,IAAI,IAAI,CAAC,CAAC;AAI5D,SAAO;;CAGT"}
1
+ {"version":3,"file":"tui-header.js","names":[],"sources":["../../../../src/tui/components/tui-header.ts"],"sourcesContent":["import type { Component, KeybindingsManager } from '@earendil-works/pi-tui';\nimport { truncateToWidth } from '@earendil-works/pi-tui';\n\nimport { theme } from '../theme.js';\nimport { formatKeyIds } from '../format-tui-hotkeys.js';\n\nexport type TuiHeaderModel = {\n version: string;\n connectionLabel: string;\n sessionKey: string;\n showHints: boolean;\n};\n\nconst COMPACT_HINTS =\n 'escape interrupt · ctrl+c/ctrl+d clear/exit · / commands · ! bash · ctrl+o tools';\nconst STARTUP_HELP_HINT = 'Press /start to show full startup help and loaded resources.';\n\n/** Collapsible startup header (pi-style hints subset). */\nexport class TuiHeader implements Component {\n private extensionLines: string[] = [];\n private extensionComponents: Component[] = [];\n\n constructor(\n private readonly getModel: () => TuiHeaderModel,\n private readonly keybindings?: KeybindingsManager,\n ) {}\n\n setExtensionLines(lines: string[]): void {\n this.extensionLines = lines;\n }\n\n setExtensionComponents(components: Component[]): void {\n this.extensionComponents = components;\n }\n\n setCustomComponent(component: Component | undefined): void {\n this.customComponent = component;\n }\n\n invalidate(): void {}\n\n private getCompactHints(): string {\n if (!this.keybindings) return COMPACT_HINTS;\n const interrupt = formatKeyIds(this.keybindings, 'app.interrupt', { capitalize: false });\n const clear = formatKeyIds(this.keybindings, 'app.clear', { capitalize: false });\n const exit = formatKeyIds(this.keybindings, 'app.exit', { capitalize: false });\n const tools = formatKeyIds(this.keybindings, 'app.tools.expand', { capitalize: false });\n return `${interrupt} interrupt · ${clear}/${exit} clear/exit · / commands · ! bash · ${tools} tools`;\n }\n\n render(width: number): string[] {\n if (this.customComponent) {\n const rendered = this.customComponent.render(width);\n return rendered.map((line) => truncateToWidth(line, width, theme.dim('…')));\n }\n\n const { version, connectionLabel, sessionKey, showHints } = this.getModel();\n const title = theme.header(`xopc tui v${version} — ${connectionLabel} — ${sessionKey}`);\n const lines = [truncateToWidth(title, width, theme.dim('…'))];\n\n if (showHints) {\n lines.push(truncateToWidth(theme.dim(this.getCompactHints()), width, theme.dim('…')));\n lines.push(truncateToWidth(theme.dim(STARTUP_HELP_HINT), width, theme.dim('…')));\n }\n\n for (const extLine of this.extensionLines) {\n lines.push(truncateToWidth(theme.dim(extLine), width, theme.dim('…')));\n }\n for (const component of this.extensionComponents) {\n for (const line of component.render(width)) {\n lines.push(truncateToWidth(line, width, theme.dim('…')));\n }\n }\n\n return lines;\n }\n\n private customComponent: Component | undefined;\n}\n"],"mappings":";;;;AAaA,MAAM,gBACJ;AACF,MAAM,oBAAoB;;AAG1B,IAAa,YAAb,MAA4C;CAC1C,iBAAmC,EAAE;CACrC,sBAA2C,EAAE;CAE7C,YACE,UACA,aACA;AAFiB,OAAA,WAAA;AACA,OAAA,cAAA;;CAGnB,kBAAkB,OAAuB;AACvC,OAAK,iBAAiB;;CAGxB,uBAAuB,YAA+B;AACpD,OAAK,sBAAsB;;CAG7B,mBAAmB,WAAwC;AACzD,OAAK,kBAAkB;;CAGzB,aAAmB;CAEnB,kBAAkC;AAChC,MAAI,CAAC,KAAK,YAAa,QAAO;AAK9B,SAAO,GAJW,aAAa,KAAK,aAAa,iBAAiB,EAAE,YAAY,OAAO,CAIpE,CAAC,eAHN,aAAa,KAAK,aAAa,aAAa,EAAE,YAAY,OAAO,CAGvC,CAAC,GAF5B,aAAa,KAAK,aAAa,YAAY,EAAE,YAAY,OAAO,CAE7B,CAAC,sCADnC,aAAa,KAAK,aAAa,oBAAoB,EAAE,YAAY,OAAO,CACM,CAAC;;CAG/F,OAAO,OAAyB;AAC9B,MAAI,KAAK,gBAEP,QADiB,KAAK,gBAAgB,OAAO,MAC9B,CAAC,KAAK,SAAS,gBAAgB,MAAM,OAAO,MAAM,IAAI,IAAI,CAAC,CAAC;EAG7E,MAAM,EAAE,SAAS,iBAAiB,YAAY,cAAc,KAAK,UAAU;EAE3E,MAAM,QAAQ,CAAC,gBADD,MAAM,OAAO,aAAa,QAAQ,KAAK,gBAAgB,KAAK,aACtC,EAAE,OAAO,MAAM,IAAI,IAAI,CAAC,CAAC;AAE7D,MAAI,WAAW;AACb,SAAM,KAAK,gBAAgB,MAAM,IAAI,KAAK,iBAAiB,CAAC,EAAE,OAAO,MAAM,IAAI,IAAI,CAAC,CAAC;AACrF,SAAM,KAAK,gBAAgB,MAAM,IAAI,kBAAkB,EAAE,OAAO,MAAM,IAAI,IAAI,CAAC,CAAC;;AAGlF,OAAK,MAAM,WAAW,KAAK,eACzB,OAAM,KAAK,gBAAgB,MAAM,IAAI,QAAQ,EAAE,OAAO,MAAM,IAAI,IAAI,CAAC,CAAC;AAExE,OAAK,MAAM,aAAa,KAAK,oBAC3B,MAAK,MAAM,QAAQ,UAAU,OAAO,MAAM,CACxC,OAAM,KAAK,gBAAgB,MAAM,OAAO,MAAM,IAAI,IAAI,CAAC,CAAC;AAI5D,SAAO;;CAGT"}
@@ -211,6 +211,10 @@ export interface TuiBackend {
211
211
  listSessions(): Promise<TuiSessionItem[]>;
212
212
  /** List agents available for TUI agent switching. */
213
213
  listAgents(): Promise<TuiAgentInfo[]>;
214
+ /** Persist the default agent for fresh TUI sessions. */
215
+ setTuiDefaultAgent?(agentId: string): Promise<{
216
+ agentId: string;
217
+ }>;
214
218
  /** Fetch session info (model, tokens, thinking). */
215
219
  getSessionInfo(sessionKey: string): Promise<SessionInfo>;
216
220
  /** List available models. */
@@ -53,6 +53,11 @@ export type CommandHandlerDeps = {
53
53
  switchModel?: (modelRef: string) => void | Promise<void>;
54
54
  listSessions?: () => TuiSessionItem[] | Promise<TuiSessionItem[]>;
55
55
  listAgents?: () => TuiAgentInfo[] | Promise<TuiAgentInfo[]>;
56
+ setTuiDefaultAgent?: (agentId: string) => {
57
+ agentId: string;
58
+ } | Promise<{
59
+ agentId: string;
60
+ }>;
56
61
  switchAgentSession?: (sessionKey: string, agentId: string) => void | Promise<void>;
57
62
  getSessionStats?: () => TuiSessionStats | Promise<TuiSessionStats>;
58
63
  getStartupResources?: () => TuiStartupResources | undefined;
@@ -99,6 +99,10 @@ function getSlashCommands(_isLocal, keybindings) {
99
99
  name: "agents",
100
100
  description: "List available agents"
101
101
  },
102
+ {
103
+ name: "tui-default-agent",
104
+ description: "Set default agent for new TUI sessions"
105
+ },
102
106
  {
103
107
  name: "new",
104
108
  description: "Start a new isolated TUI session (tui-{uuid})"
@@ -465,6 +469,45 @@ function createTuiCommandHandler(deps) {
465
469
  });
466
470
  return;
467
471
  }
472
+ case "tui-default-agent": {
473
+ const targetRaw = commandArgs.trim();
474
+ if (!targetRaw) {
475
+ Promise.resolve(deps.listAgents?.() ?? []).then((agents) => {
476
+ chatLog.addSystem([
477
+ "Usage: /tui-default-agent <agent-id>",
478
+ "This changes new TUI sessions only; the current session is unchanged.",
479
+ "",
480
+ formatAgentsList(agents, parseAgentSessionKey(state.currentSessionKey)?.agentId)
481
+ ].join("\n"));
482
+ tui.requestRender();
483
+ }).catch((err) => {
484
+ const errorMessage = err instanceof Error ? err.message : String(err);
485
+ chatLog.addSystem(`TUI default agent help failed: ${errorMessage}`);
486
+ tui.requestRender();
487
+ });
488
+ return;
489
+ }
490
+ (async () => {
491
+ if (!isValidAgentId(targetRaw)) {
492
+ chatLog.addSystem(`Invalid agent id: ${targetRaw}`);
493
+ tui.requestRender();
494
+ return;
495
+ }
496
+ if (!deps.setTuiDefaultAgent) {
497
+ chatLog.addSystem("TUI default agent updates are not available in this mode.");
498
+ tui.requestRender();
499
+ return;
500
+ }
501
+ const result = await deps.setTuiDefaultAgent(normalizeAgentId(targetRaw));
502
+ chatLog.addSystem(`TUI default agent set to ${result.agentId}. New TUI sessions will use it.`);
503
+ tui.requestRender();
504
+ })().catch((err) => {
505
+ const errorMessage = err instanceof Error ? err.message : String(err);
506
+ chatLog.addSystem(`TUI default agent update failed: ${errorMessage}`);
507
+ tui.requestRender();
508
+ });
509
+ return;
510
+ }
468
511
  case "usage":
469
512
  Promise.resolve(deps.getSessionStats?.()).catch(() => void 0).then((stats) => {
470
513
  chatLog.addSystem(formatTuiUsageInfo(state, stats));