@xopcai/xopc 0.0.125 → 0.0.127

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 (386) hide show
  1. package/README.md +56 -102
  2. package/README.zh-CN.md +51 -98
  3. package/dist/browser-ext/manifest.json +1 -1
  4. package/dist/extensions/feishu/src/schema/config-schema.d.ts +6 -6
  5. package/dist/extensions/feishu/src/workflow-progress.js +1 -1
  6. package/dist/extensions/telegram/src/adapters/streaming-adapter.js +1 -1
  7. package/dist/extensions/telegram/src/config-schema.d.ts +8 -8
  8. package/dist/extensions/telegram/src/inbound-processor.js +1 -1
  9. package/dist/extensions/telegram/src/plugin.js +1 -1
  10. package/dist/extensions/telegram/src/routing-integration.js +2 -2
  11. package/dist/extensions/telegram/src/workflow-progress.js +1 -1
  12. package/dist/extensions/telegram/xopc.extension.json +1 -1
  13. package/dist/extensions/weixin/src/api/api.js +1 -1
  14. package/dist/extensions/weixin/src/config-schema.d.ts +3 -3
  15. package/dist/extensions/weixin/src/plugin.js +1 -1
  16. package/dist/extensions/weixin/src/workflow-progress.js +1 -1
  17. package/dist/gateway/static/root/assets/{agent-avatar-dicebear-BKDKICZV.js → agent-avatar-dicebear-CgGgO4OV.js} +1 -1
  18. package/dist/gateway/static/root/assets/agents-k59l7NMb.js +2 -0
  19. package/dist/gateway/static/root/assets/{app-management-settings-panel-DI4BqHKW.js → app-management-settings-panel-DeQsTsyy.js} +1 -1
  20. package/dist/gateway/static/root/assets/{appearance-settings-6_ie3NQ4.js → appearance-settings-BnHQW7Hv.js} +1 -1
  21. package/dist/gateway/static/root/assets/apps-page-BG9b4abG.js +1 -0
  22. package/dist/gateway/static/root/assets/{archive-plugin-kUHEJ1HK.js → archive-plugin-5NXT7Zqv.js} +1 -1
  23. package/dist/gateway/static/root/assets/{attachment-load-Dm-9prpU.js → attachment-load-DghwhYe0.js} +1 -1
  24. package/dist/gateway/static/root/assets/{automation-suggestion-card-OTxQTPnC.js → automation-suggestion-card-DYmESgwl.js} +1 -1
  25. package/dist/gateway/static/root/assets/automations-page-De8mVutL.js +4 -0
  26. package/dist/gateway/static/root/assets/{binary-plugins-DllA_jQ0.js → binary-plugins-DSbPKdWX.js} +1 -1
  27. package/dist/gateway/static/root/assets/{block-editor-Cm6CWNj1.js → block-editor-CoZ-_np-.js} +28 -28
  28. package/dist/gateway/static/root/assets/browser-settings-page-C_ZRa4LF.js +8 -0
  29. package/dist/gateway/static/root/assets/{capability-presets-api-VJ89b6I2.js → capability-presets-api-hny224j-.js} +1 -1
  30. package/dist/gateway/static/root/assets/{capability-presets-settings-panel-BaPj8wC2.js → capability-presets-settings-panel-Drc0qLsw.js} +1 -1
  31. package/dist/gateway/static/root/assets/{channel-recipient-api-B5PwBEUx.js → channel-recipient-api-DAlOHxKJ.js} +1 -1
  32. package/dist/gateway/static/root/assets/channels-settings-CA20zBV9.js +1 -0
  33. package/dist/gateway/static/root/assets/connectors-page-qMyMB5te.js +2 -0
  34. package/dist/gateway/static/root/assets/desktop-pet-XG6Vb_fZ.js +1 -0
  35. package/dist/gateway/static/root/assets/desktop-pet-settings-npJ0Oh5p.js +1 -0
  36. package/dist/gateway/static/root/assets/desktop-pet-sprite-DqZ6fbIj.js +1 -0
  37. package/dist/gateway/static/root/assets/directory-picker-path-field-BR2ItBuf.js +1 -0
  38. package/dist/gateway/static/root/assets/dreaming-settings-CkUZ997f.js +3 -0
  39. package/dist/gateway/static/root/assets/{extension-debug-page-BaM0FpW7.js → extension-debug-page-Tl0f1rNv.js} +1 -1
  40. package/dist/gateway/static/root/assets/{extension-page-DuZWVOGA.js → extension-page-Ck7QuwE3.js} +1 -1
  41. package/dist/gateway/static/root/assets/{extension-settings-page-DarVtbmJ.js → extension-settings-page-3RMhQtZ3.js} +1 -1
  42. package/dist/gateway/static/root/assets/{fetch-NFKfkqrd.js → fetch-pg2ErdAk.js} +1 -1
  43. package/dist/gateway/static/root/assets/{gateway-config-api-CFEm9rgy.js → gateway-config-api-DbG97ia2.js} +1 -1
  44. package/dist/gateway/static/root/assets/gateway-settings-B8cyqKk-.js +1 -0
  45. package/dist/gateway/static/root/assets/{gateway-startup-retry-Dtwh_yGg.js → gateway-startup-retry-Yh8h3hkj.js} +1 -1
  46. package/dist/gateway/static/root/assets/{goal-create-dialog-BKP7ylcG.js → goal-create-dialog-DmeW7Zz3.js} +1 -1
  47. package/dist/gateway/static/root/assets/goal-detail-page-DrTyGbVD.js +1 -0
  48. package/dist/gateway/static/root/assets/{goals-config-api-DTWZNA_Y.js → goals-config-api-CxCWGIBB.js} +1 -1
  49. package/dist/gateway/static/root/assets/goals-page-DV1bJhIh.js +2 -0
  50. package/dist/gateway/static/root/assets/{goals-settings-Bhct0ZT-.js → goals-settings-9DrfOkP5.js} +1 -1
  51. package/dist/gateway/static/root/assets/{heartbeat-settings-C-UxSU4a.js → heartbeat-settings-KaDpZrv0.js} +1 -1
  52. package/dist/gateway/static/root/assets/index-C2F0Clvm.js +256 -0
  53. package/dist/gateway/static/root/assets/index-COQSX5d_.css +1 -0
  54. package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-DCjy2y4d.js → keyboard-shortcuts-settings-CfQrt_Rb.js} +1 -1
  55. package/dist/gateway/static/root/assets/logs-page-C9dpiNTF.js +2 -0
  56. package/dist/gateway/static/root/assets/{markdown-split-BaqxP-GQ.js → markdown-split-BwiMdCf_.js} +1 -1
  57. package/dist/gateway/static/root/assets/{media-plugins-DQ_EXloK.js → media-plugins-DhoizyZv.js} +1 -1
  58. package/dist/gateway/static/root/assets/messages-DmnbiNxU.js +3 -0
  59. package/dist/gateway/static/root/assets/models-hub-panel-zdCdmBmH.js +2 -0
  60. package/dist/gateway/static/root/assets/notes-page-MpGeFfPt.js +1 -0
  61. package/dist/gateway/static/root/assets/notes-workbench-DYCM3yd2.js +2 -0
  62. package/dist/gateway/static/root/assets/{page-tabs-EIZhLppK.js → page-tabs-DDC2t4Z8.js} +1 -1
  63. package/dist/gateway/static/root/assets/{preview-open-alternatives-r_uB4Epr.js → preview-open-alternatives-BTmk-XDM.js} +1 -1
  64. package/dist/gateway/static/root/assets/project-detail-page-Cu0ElRnS.js +1 -0
  65. package/dist/gateway/static/root/assets/projects-page-DakNaUjZ.js +1 -0
  66. package/dist/gateway/static/root/assets/remote-access-hub-DYKjt7L9.js +1 -0
  67. package/dist/gateway/static/root/assets/{save-bar-controls-B132Uf-2.js → save-bar-controls-DqU-yKIh.js} +1 -1
  68. package/dist/gateway/static/root/assets/{schedule-field-B5qshALm.js → schedule-field-CUttkoSB.js} +1 -1
  69. package/dist/gateway/static/root/assets/{schema-form-CvLmkdS9.js → schema-form-CVSQA9nI.js} +1 -1
  70. package/dist/gateway/static/root/assets/sessions-page-CcGHDsz1.js +1 -0
  71. package/dist/gateway/static/root/assets/settings-advanced-gate-CuFdeKNu.js +1 -0
  72. package/dist/gateway/static/root/assets/{settings-collapsible-section-pRlvqsAf.js → settings-collapsible-section-CK7ogS-P.js} +1 -1
  73. package/dist/gateway/static/root/assets/settings-form-section-Bugp38Fa.js +1 -0
  74. package/dist/gateway/static/root/assets/settings-page-0AJoUvxi.js +1 -0
  75. package/dist/gateway/static/root/assets/settings-page-layout-DBRWwdhh.js +1 -0
  76. package/dist/gateway/static/root/assets/setup-status-panel-D6a_hEk7.js +1 -0
  77. package/dist/gateway/static/root/assets/{share-preview-page-v6-IOp8t.js → share-preview-page-BtsuETKF.js} +1 -1
  78. package/dist/gateway/static/root/assets/shares-settings-CcEFT7S9.js +1 -0
  79. package/dist/gateway/static/root/assets/skill-reload-api-BcN_RuTD.js +1 -0
  80. package/dist/gateway/static/root/assets/skills-page-BbRZZZA5.js +2 -0
  81. package/dist/gateway/static/root/assets/{system-settings-panel-HUU2FFjM.js → system-settings-panel-DJ6YuLqR.js} +1 -1
  82. package/dist/gateway/static/root/assets/{typed-models-lib-AH160QHh.js → typed-models-lib-B0T7N8Km.js} +1 -1
  83. package/dist/gateway/static/root/assets/{use-channel-catalog-BXzDmjCQ.js → use-channel-catalog-C6vrxdzZ.js} +1 -1
  84. package/dist/gateway/static/root/assets/{user-profile-settings-panel-DxwnQvQ3.js → user-profile-settings-panel-DZ0nKMgj.js} +1 -1
  85. package/dist/gateway/static/root/assets/{utils-i5POEtqd.js → utils-CehXcWAY.js} +1 -1
  86. package/dist/gateway/static/root/assets/voice-api-key-field-2QKflCx8.js +1 -0
  87. package/dist/gateway/static/root/assets/work-item-detail-page-DfJnuWq1.js +1 -0
  88. package/dist/gateway/static/root/assets/{workflow-run-setup-panel-ClVVMgN-.js → workflow-run-setup-panel-c4jeaohQ.js} +2 -2
  89. package/dist/gateway/static/root/assets/{workflow-start-dialog-Dv4ZA1T0.js → workflow-start-dialog-ENRHjoqa.js} +1 -1
  90. package/dist/gateway/static/root/assets/workflows-page-BJwwFTm_.js +18 -0
  91. package/dist/gateway/static/root/index.html +5 -5
  92. package/dist/package.js +1 -1
  93. package/dist/src/activity/context.d.ts +11 -0
  94. package/dist/src/activity/context.js +36 -0
  95. package/dist/src/activity/context.js.map +1 -0
  96. package/dist/src/activity/emitter.d.ts +6 -0
  97. package/dist/src/activity/emitter.js +43 -0
  98. package/dist/src/activity/emitter.js.map +1 -0
  99. package/dist/src/activity/index.d.ts +3 -0
  100. package/dist/src/activity/index.js +3 -0
  101. package/dist/src/activity/service.d.ts +12 -0
  102. package/dist/src/activity/service.js +59 -0
  103. package/dist/src/activity/service.js.map +1 -0
  104. package/dist/src/activity/types.d.ts +109 -0
  105. package/dist/src/activity/types.js +1 -0
  106. package/dist/src/agent/agent-instance-gateway.d.ts +5 -0
  107. package/dist/src/agent/agent-manager.d.ts +21 -0
  108. package/dist/src/agent/agent-manager.js +118 -6
  109. package/dist/src/agent/agent-manager.js.map +1 -1
  110. package/dist/src/agent/capabilities/definitions.d.ts +153 -0
  111. package/dist/src/agent/capabilities/definitions.js +156 -0
  112. package/dist/src/agent/capabilities/definitions.js.map +1 -0
  113. package/dist/src/agent/capabilities/index.d.ts +2 -0
  114. package/dist/src/agent/capabilities/index.js +3 -0
  115. package/dist/src/agent/capabilities/registry.d.ts +10 -0
  116. package/dist/src/agent/capabilities/registry.js +51 -0
  117. package/dist/src/agent/capabilities/registry.js.map +1 -0
  118. package/dist/src/agent/context/project-context.js +2 -2
  119. package/dist/src/agent/context/workspace-seed.js +2 -2
  120. package/dist/src/agent/embedded/run-for-session.js +1 -1
  121. package/dist/src/agent/goals/post-turn.js +2 -2
  122. package/dist/src/agent/ipc/bus.js +1 -1
  123. package/dist/src/agent/mcp/bundle-mcp-materialize.js +1 -1
  124. package/dist/src/agent/mcp/bundle-mcp-runtime.js +1 -1
  125. package/dist/src/agent/mcp/mcp-transport-config.js +1 -1
  126. package/dist/src/agent/mcp/mcp-transport.js +1 -1
  127. package/dist/src/agent/memory/plugin-discovery.js +1 -1
  128. package/dist/src/agent/models/manager.js +1 -1
  129. package/dist/src/agent/orchestration/agent-orchestrator.js +1 -1
  130. package/dist/src/agent/service/process-direct-one-shot.js +5 -3
  131. package/dist/src/agent/service/process-direct-one-shot.js.map +1 -1
  132. package/dist/src/agent/service/process-direct-streaming.js +4 -3
  133. package/dist/src/agent/service/process-direct-streaming.js.map +1 -1
  134. package/dist/src/agent/service.d.ts +2 -0
  135. package/dist/src/agent/service.js +9 -3
  136. package/dist/src/agent/service.js.map +1 -1
  137. package/dist/src/agent/service.types.d.ts +7 -0
  138. package/dist/src/agent/session/session-inspector.js +1 -1
  139. package/dist/src/agent/skills/hub-pull.js +1 -1
  140. package/dist/src/agent/skills/parse-skill-metadata.js +9 -1
  141. package/dist/src/agent/skills/parse-skill-metadata.js.map +1 -1
  142. package/dist/src/agent/skills/skill-manager.d.ts +4 -0
  143. package/dist/src/agent/skills/skill-manager.js +17 -0
  144. package/dist/src/agent/skills/skill-manager.js.map +1 -1
  145. package/dist/src/agent/skills/types.d.ts +5 -0
  146. package/dist/src/agent/tool-manuals/index.js +15 -6
  147. package/dist/src/agent/tool-manuals/index.js.map +1 -1
  148. package/dist/src/agent/tool-manuals/xopc-use.d.ts +1 -0
  149. package/dist/src/agent/tool-manuals/xopc-use.js +204 -0
  150. package/dist/src/agent/tool-manuals/xopc-use.js.map +1 -0
  151. package/dist/src/agent/tools/desktop-pet-tool.d.ts +24 -0
  152. package/dist/src/agent/tools/desktop-pet-tool.js +90 -0
  153. package/dist/src/agent/tools/desktop-pet-tool.js.map +1 -0
  154. package/dist/src/agent/tools/factory.d.ts +9 -0
  155. package/dist/src/agent/tools/factory.js +26 -0
  156. package/dist/src/agent/tools/factory.js.map +1 -1
  157. package/dist/src/agent/tools/goal-tool.js +2 -2
  158. package/dist/src/agent/tools/index.d.ts +2 -0
  159. package/dist/src/agent/tools/index.js +3 -1
  160. package/dist/src/agent/tools/workflow-tool.js +1 -1
  161. package/dist/src/agent/tools/xopc-use-tool.d.ts +34 -0
  162. package/dist/src/agent/tools/xopc-use-tool.js +636 -0
  163. package/dist/src/agent/tools/xopc-use-tool.js.map +1 -0
  164. package/dist/src/agent-manifest/schema.d.ts +27 -27
  165. package/dist/src/automations/api/routes.js +1 -1
  166. package/dist/src/automations/domain/validation.d.ts +55 -55
  167. package/dist/src/automations/draft/automation-draft-service.js +1 -1
  168. package/dist/src/automations/draft/automation-draft-validator.d.ts +25 -25
  169. package/dist/src/automations/service/action-executor.js +2 -2
  170. package/dist/src/browser/cdp-local-launcher.js +1 -1
  171. package/dist/src/browser/providers/browser-ext-install.js +3 -3
  172. package/dist/src/browser/providers/cloakbrowser.js +2 -2
  173. package/dist/src/browser/providers/playwright-doctor.js +1 -1
  174. package/dist/src/browser/stealth.js +1 -1
  175. package/dist/src/chat-commands/agent-edit.js +1 -1
  176. package/dist/src/chat-commands/builtins/config.js +1 -1
  177. package/dist/src/chat-commands/builtins/goal.js +2 -2
  178. package/dist/src/chat-commands/context.js +1 -1
  179. package/dist/src/cli/commands/agent.js +3 -3
  180. package/dist/src/cli/commands/doctor/checks/database-schema.js +2 -2
  181. package/dist/src/cli/commands/doctor/checks/session-integrity.js +1 -1
  182. package/dist/src/cli/commands/extension-marketplace.js +1 -1
  183. package/dist/src/cli/commands/extension-pack.js +1 -1
  184. package/dist/src/cli/commands/gateway/lifecycle.js +1 -1
  185. package/dist/src/cli/commands/goal.js +3 -3
  186. package/dist/src/cli/commands/init.js +1 -1
  187. package/dist/src/cli/commands/models.js +1 -1
  188. package/dist/src/cli/commands/onboard.js +1 -1
  189. package/dist/src/cli/commands/profile.js +1 -1
  190. package/dist/src/cli/commands/project.js +4 -4
  191. package/dist/src/cli/commands/tunnel.js +1 -1
  192. package/dist/src/cli/commands/update.js +1 -1
  193. package/dist/src/cli/extension-cli-register.js +1 -1
  194. package/dist/src/config/agent-profile.js +1 -1
  195. package/dist/src/config/gateway-bind.js +1 -1
  196. package/dist/src/config/index.js +2 -2
  197. package/dist/src/config/loader.js +1 -1
  198. package/dist/src/config/models-json.d.ts +14 -14
  199. package/dist/src/config/models-json.js +1 -1
  200. package/dist/src/config/schema.d.ts +60 -60
  201. package/dist/src/daemon/launchd.js +1 -1
  202. package/dist/src/daemon/systemd.js +1 -1
  203. package/dist/src/extensions/discover-extensions.js +1 -1
  204. package/dist/src/extensions/loader.js +2 -2
  205. package/dist/src/gateway/agent-builtin-tools.d.ts +1 -1
  206. package/dist/src/gateway/agent-builtin-tools.js +1 -0
  207. package/dist/src/gateway/agent-builtin-tools.js.map +1 -1
  208. package/dist/src/gateway/agents-admin.js +1 -1
  209. package/dist/src/gateway/hono/lib/config-payload.d.ts +14 -14
  210. package/dist/src/gateway/hono/lib/static-ui.js +1 -1
  211. package/dist/src/gateway/hono/middleware/log-context.js +8 -1
  212. package/dist/src/gateway/hono/middleware/log-context.js.map +1 -1
  213. package/dist/src/gateway/hono/routes/activity.d.ts +14 -0
  214. package/dist/src/gateway/hono/routes/activity.js +72 -0
  215. package/dist/src/gateway/hono/routes/activity.js.map +1 -0
  216. package/dist/src/gateway/hono/routes/commands-skills.js +7 -0
  217. package/dist/src/gateway/hono/routes/commands-skills.js.map +1 -1
  218. package/dist/src/gateway/hono/routes/goals.js +1 -1
  219. package/dist/src/gateway/hono/routes/index.js +2 -0
  220. package/dist/src/gateway/hono/routes/index.js.map +1 -1
  221. package/dist/src/gateway/hono/routes/lazy-bundles.js +2 -1
  222. package/dist/src/gateway/hono/routes/lazy-bundles.js.map +1 -1
  223. package/dist/src/gateway/hono/routes/memory.js +2 -2
  224. package/dist/src/gateway/hono/routes/projects.js +93 -15
  225. package/dist/src/gateway/hono/routes/projects.js.map +1 -1
  226. package/dist/src/gateway/hono/routes/sessions.js +101 -2
  227. package/dist/src/gateway/hono/routes/sessions.js.map +1 -1
  228. package/dist/src/gateway/hono/routes/workflows.js +2 -2
  229. package/dist/src/gateway/lock.js +1 -1
  230. package/dist/src/gateway/ports.js +1 -1
  231. package/dist/src/gateway/run-loop.js +1 -1
  232. package/dist/src/gateway/service/run-gateway-agent.js +6 -2
  233. package/dist/src/gateway/service/run-gateway-agent.js.map +1 -1
  234. package/dist/src/gateway/service/sessions-api.d.ts +10 -0
  235. package/dist/src/gateway/service/sessions-api.js +31 -0
  236. package/dist/src/gateway/service/sessions-api.js.map +1 -1
  237. package/dist/src/gateway/service.js +12 -9
  238. package/dist/src/gateway/service.js.map +1 -1
  239. package/dist/src/goals/goal-store.js +1 -1
  240. package/dist/src/goals/goal-store.js.map +1 -1
  241. package/dist/src/goals/goal-workflow-judge.js +1 -1
  242. package/dist/src/infra/ports.js +1 -1
  243. package/dist/src/infra/ssh-tunnel.js +1 -1
  244. package/dist/src/infra/update-check.js +1 -1
  245. package/dist/src/infra/update-restart.js +1 -1
  246. package/dist/src/migrations/runner.js +1 -1
  247. package/dist/src/notes/service.js +65 -6
  248. package/dist/src/notes/service.js.map +1 -1
  249. package/dist/src/notes/store.js +1 -1
  250. package/dist/src/pets/factory.d.ts +25 -0
  251. package/dist/src/pets/factory.js +327 -0
  252. package/dist/src/pets/factory.js.map +1 -0
  253. package/dist/src/pets/manifest.d.ts +2 -0
  254. package/dist/src/pets/manifest.js +16 -0
  255. package/dist/src/pets/manifest.js.map +1 -0
  256. package/dist/src/pets/validator.d.ts +12 -0
  257. package/dist/src/pets/validator.js +175 -0
  258. package/dist/src/pets/validator.js.map +1 -0
  259. package/dist/src/projects/project-service.d.ts +4 -1
  260. package/dist/src/projects/project-service.js +65 -2
  261. package/dist/src/projects/project-service.js.map +1 -1
  262. package/dist/src/projects/project-store.d.ts +3 -1
  263. package/dist/src/projects/project-store.js +56 -6
  264. package/dist/src/projects/project-store.js.map +1 -1
  265. package/dist/src/projects/types.d.ts +12 -0
  266. package/dist/src/projects/workspace.js +1 -1
  267. package/dist/src/routing/agent-session-key.js +1 -1
  268. package/dist/src/routing/resolve-route.js +1 -1
  269. package/dist/src/routing/resolve-tui-session-key.js +1 -1
  270. package/dist/src/session/client-history.d.ts +3 -0
  271. package/dist/src/session/client-history.js +24 -9
  272. package/dist/src/session/client-history.js.map +1 -1
  273. package/dist/src/session/init-session-turn.js +1 -1
  274. package/dist/src/session/resolve-session.js +1 -1
  275. package/dist/src/session/session-title.js +24 -4
  276. package/dist/src/session/session-title.js.map +1 -1
  277. package/dist/src/session/store.js +1 -1
  278. package/dist/src/session/types.d.ts +4 -0
  279. package/dist/src/session/types.js.map +1 -1
  280. package/dist/src/storage/sqlite/activity-repository.d.ts +8 -0
  281. package/dist/src/storage/sqlite/activity-repository.js +208 -0
  282. package/dist/src/storage/sqlite/activity-repository.js.map +1 -0
  283. package/dist/src/storage/sqlite/connection.js +1 -1
  284. package/dist/src/storage/sqlite/index.d.ts +1 -0
  285. package/dist/src/storage/sqlite/index.js +2 -1
  286. package/dist/src/storage/sqlite/migrations/024_activity_events.sql +62 -0
  287. package/dist/src/storage/sqlite/migrations/025_project_pinned_at.sql +5 -0
  288. package/dist/src/storage/sqlite/migrations/runner.d.ts +1 -1
  289. package/dist/src/storage/sqlite/migrations/runner.js +3 -3
  290. package/dist/src/storage/sqlite/migrations/runner.js.map +1 -1
  291. package/dist/src/storage/sqlite/migrations/runner.ts +1 -1
  292. package/dist/src/storage/sqlite/row-mappers.js +1 -1
  293. package/dist/src/storage/sqlite/schema.js +1 -1
  294. package/dist/src/storage/sqlite/schema.sql +63 -0
  295. package/dist/src/storage/sqlite/session-repository.js +11 -0
  296. package/dist/src/storage/sqlite/session-repository.js.map +1 -1
  297. package/dist/src/tui/backends/embedded-backend.d.ts +13 -0
  298. package/dist/src/tui/backends/embedded-backend.js +76 -7
  299. package/dist/src/tui/backends/embedded-backend.js.map +1 -1
  300. package/dist/src/tui/backends/gateway-sse-backend.d.ts +13 -0
  301. package/dist/src/tui/backends/gateway-sse-backend.js +53 -0
  302. package/dist/src/tui/backends/gateway-sse-backend.js.map +1 -1
  303. package/dist/src/tui/chat-history.js +16 -3
  304. package/dist/src/tui/chat-history.js.map +1 -1
  305. package/dist/src/tui/clipboard-image.js +1 -1
  306. package/dist/src/tui/components/chat-log.d.ts +23 -3
  307. package/dist/src/tui/components/chat-log.js +68 -9
  308. package/dist/src/tui/components/chat-log.js.map +1 -1
  309. package/dist/src/tui/components/tui-bottom-bar.js +9 -5
  310. package/dist/src/tui/components/tui-bottom-bar.js.map +1 -1
  311. package/dist/src/tui/tui-backend.d.ts +16 -0
  312. package/dist/src/tui/tui-command-formatters.js +2 -2
  313. package/dist/src/tui/tui-commands.d.ts +9 -0
  314. package/dist/src/tui/tui-commands.js +95 -6
  315. package/dist/src/tui/tui-commands.js.map +1 -1
  316. package/dist/src/tui/tui-picker-overlay.d.ts +1 -0
  317. package/dist/src/tui/tui-picker-overlay.js +36 -1
  318. package/dist/src/tui/tui-picker-overlay.js.map +1 -1
  319. package/dist/src/tui/tui-picker-services.d.ts +13 -0
  320. package/dist/src/tui/tui-run-state.js +11 -0
  321. package/dist/src/tui/tui-run-state.js.map +1 -1
  322. package/dist/src/tui/tui-run-status-format.d.ts +3 -0
  323. package/dist/src/tui/tui-run-status-format.js +33 -0
  324. package/dist/src/tui/tui-run-status-format.js.map +1 -0
  325. package/dist/src/tui/tui-session-actions.d.ts +5 -0
  326. package/dist/src/tui/tui-session-actions.js +24 -0
  327. package/dist/src/tui/tui-session-actions.js.map +1 -1
  328. package/dist/src/tui/tui-timeline-picker.d.ts +19 -0
  329. package/dist/src/tui/tui-timeline-picker.js +81 -0
  330. package/dist/src/tui/tui-timeline-picker.js.map +1 -0
  331. package/dist/src/tui/tui-timeline.d.ts +15 -0
  332. package/dist/src/tui/tui-timeline.js +65 -0
  333. package/dist/src/tui/tui-timeline.js.map +1 -0
  334. package/dist/src/tui/tui-types.d.ts +1 -0
  335. package/dist/src/tui/tui-types.js +1 -0
  336. package/dist/src/tui/tui-types.js.map +1 -1
  337. package/dist/src/tui/tui.js +31 -25
  338. package/dist/src/tui/tui.js.map +1 -1
  339. package/dist/src/utils/index.js +1 -1
  340. package/dist/src/utils/logger/index.js +1 -1
  341. package/dist/src/utils/logger/stats.d.ts +3 -3
  342. package/dist/src/utils/logger.js +1 -1
  343. package/dist/src/work-items/agent-context.d.ts +5 -1
  344. package/dist/src/work-items/agent-context.js +39 -3
  345. package/dist/src/work-items/agent-context.js.map +1 -1
  346. package/dist/src/work-items/work-item-service.d.ts +2 -0
  347. package/dist/src/work-items/work-item-service.js +97 -0
  348. package/dist/src/work-items/work-item-service.js.map +1 -1
  349. package/dist/src/workflows/draft/workflow-draft-service.js +1 -1
  350. package/dist/src/workflows/service/workflow-session-bridge.js +1 -1
  351. package/package.json +5 -5
  352. package/skills/creative/hatch-pet/SKILL.md +63 -0
  353. package/dist/gateway/static/root/assets/agents-BnTB7-c5.js +0 -2
  354. package/dist/gateway/static/root/assets/apps-page-B6bG65SW.js +0 -1
  355. package/dist/gateway/static/root/assets/automations-page-1lVbo0dS.js +0 -1
  356. package/dist/gateway/static/root/assets/browser-settings-page-CzDBlOK0.js +0 -8
  357. package/dist/gateway/static/root/assets/channels-settings-Df4m7p1k.js +0 -1
  358. package/dist/gateway/static/root/assets/connectors-page-BMTphmHS.js +0 -2
  359. package/dist/gateway/static/root/assets/directory-picker-path-field-DySMzOF6.js +0 -1
  360. package/dist/gateway/static/root/assets/dist-By6Rh2ee.js +0 -1
  361. package/dist/gateway/static/root/assets/dreaming-settings-D_AjSnV_.js +0 -3
  362. package/dist/gateway/static/root/assets/gateway-settings-BMk2S5td.js +0 -1
  363. package/dist/gateway/static/root/assets/goal-detail-page-C2cTxf71.js +0 -1
  364. package/dist/gateway/static/root/assets/goals-page-CTmA3hWK.js +0 -2
  365. package/dist/gateway/static/root/assets/index-BNHDd2j1.css +0 -1
  366. package/dist/gateway/static/root/assets/index-BPXLPMuY.js +0 -193
  367. package/dist/gateway/static/root/assets/logs-page-CGc3_CQU.js +0 -2
  368. package/dist/gateway/static/root/assets/messages-CjuIJcZl.js +0 -3
  369. package/dist/gateway/static/root/assets/models-hub-panel-Drz4UQMb.js +0 -2
  370. package/dist/gateway/static/root/assets/notes-page-CY1ylng1.js +0 -1
  371. package/dist/gateway/static/root/assets/notes-workbench-X7IaD--t.js +0 -2
  372. package/dist/gateway/static/root/assets/project-detail-page-DE5adRBE.js +0 -1
  373. package/dist/gateway/static/root/assets/projects-page-CuOb1k6F.js +0 -1
  374. package/dist/gateway/static/root/assets/remote-access-hub-BOxNrUVA.js +0 -1
  375. package/dist/gateway/static/root/assets/sessions-page-CY0IQcGW.js +0 -1
  376. package/dist/gateway/static/root/assets/settings-advanced-gate-D4NBNVCB.js +0 -1
  377. package/dist/gateway/static/root/assets/settings-form-section-BBYUDLVd.js +0 -1
  378. package/dist/gateway/static/root/assets/settings-page-DaO7zYZM.js +0 -1
  379. package/dist/gateway/static/root/assets/settings-page-layout-D8g9PAek.js +0 -1
  380. package/dist/gateway/static/root/assets/setup-status-panel-Bks0CLLT.js +0 -1
  381. package/dist/gateway/static/root/assets/shares-settings-CEZsKm9r.js +0 -1
  382. package/dist/gateway/static/root/assets/skill-reload-api-oTkHbb9W.js +0 -1
  383. package/dist/gateway/static/root/assets/skills-page-DigsbZ6K.js +0 -2
  384. package/dist/gateway/static/root/assets/voice-api-key-field-CEJklEgb.js +0 -1
  385. package/dist/gateway/static/root/assets/work-item-detail-page-CD6FL_Rs.js +0 -1
  386. package/dist/gateway/static/root/assets/workflows-page-OLQiUpoW.js +0 -18
@@ -6,11 +6,13 @@ import { searchableSelectListTheme, theme } from "./theme.js";
6
6
  import { formatKeyIds } from "./format-tui-hotkeys.js";
7
7
  import { formatSessionPickerDescription } from "./tui-session-format.js";
8
8
  import { filterTuiTranscriptTreeEntries } from "./tui-transcript-tree.js";
9
+ import { buildTuiTimelineTurns } from "./tui-timeline.js";
9
10
  import { SearchableSelectList } from "./components/searchable-select-list.js";
10
11
  import { ScopedModelsSelector } from "./components/scoped-models-selector.js";
11
12
  import { SettingsSelector } from "./components/settings-selector.js";
12
13
  import { SessionSelector } from "./components/session-selector.js";
13
14
  import { ThinkingSelector } from "./components/thinking-selector.js";
15
+ import { TimelineSelectList, formatTimelineOpenedHint } from "./tui-timeline-picker.js";
14
16
  import { TranscriptTreeSelectList, defaultTranscriptForkKey, formatTranscriptTreeFilterHint, formatUserMessageForkOpenedHint, userMessageForkSelectItems } from "./tui-transcript-tree-picker.js";
15
17
  //#region src/tui/tui-picker-overlay.ts
16
18
  init_agent_session_key();
@@ -61,6 +63,39 @@ function agentSelectItems(agents, currentAgentId) {
61
63
  function formatSessionTreeOpenedHint(keybindings) {
62
64
  return `Session tree (${formatSelectNavigationHint(keybindings)} · type to filter · ${formatKeyIds(keybindings, "tui.select.confirm", { capitalize: true })} resume · ${formatKeyIds(keybindings, "tui.select.cancel", { capitalize: true })} close)`;
63
65
  }
66
+ async function openTimelineOverlay(svc, initialQuery) {
67
+ const turns = buildTuiTimelineTurns(await svc.client.loadTimeline(svc.state.currentSessionKey));
68
+ if (turns.length === 0) {
69
+ svc.chatLog.addSystem("No timeline turns found.");
70
+ svc.tui.requestRender();
71
+ return;
72
+ }
73
+ const viewState = svc.chatLog.getTimelineViewportState();
74
+ const activeDisplayIndex = viewState.mode === "history" ? viewState.displayIndex : turns[turns.length - 1]?.displayIndex;
75
+ const list = new TimelineSelectList(turns, {
76
+ keybindings: svc.keybindings,
77
+ ...activeDisplayIndex !== void 0 ? { activeDisplayIndex } : {},
78
+ ...initialQuery ? { initialQuery } : {}
79
+ });
80
+ list.onSelect = (turn) => {
81
+ svc.closeOverlay();
82
+ svc.tui.setFocus(svc.editor);
83
+ (async () => {
84
+ if (!svc.chatLog.jumpToDisplayIndex(turn.displayIndex)) {
85
+ if (!(turn.rowNumber !== void 0 ? await svc.loadHistoryWindow({ rowNumber: turn.rowNumber }) : false) || !svc.chatLog.jumpToDisplayIndex(turn.displayIndex)) svc.chatLog.addSystem(`Turn ${turn.turn} is outside loaded history.`);
86
+ }
87
+ svc.tui.requestRender();
88
+ })();
89
+ };
90
+ list.onCancel = () => {
91
+ svc.closeOverlay();
92
+ svc.tui.setFocus(svc.editor);
93
+ svc.tui.requestRender();
94
+ };
95
+ svc.openOverlay(list);
96
+ svc.chatLog.addSystem(theme.dim(formatTimelineOpenedHint(svc.keybindings)));
97
+ svc.tui.requestRender();
98
+ }
64
99
  function resumeSession(svc, sessionKey) {
65
100
  svc.setSessionKey(sessionKey);
66
101
  svc.clearChatForSessionSwitch();
@@ -596,6 +631,6 @@ function openProjectTrustOverlay(svc) {
596
631
  svc.tui.requestRender();
597
632
  }
598
633
  //#endregion
599
- export { formatAgentPickerOpenedHint, formatProjectTrustOpenedHint, formatReviewPickerOpenedHint, formatScopedModelsOpenedHint, formatScopedModelsSavedHint, formatSessionTreeOpenedHint, formatSettingsOpenedHint, formatThinkingLevelSavedHint, formatThinkingSelectorHint, openAgentPickerOverlay, openProjectTrustOverlay, openReviewLauncherOverlay, openScopedModelsOverlay, openSessionPickerOverlay, openSessionTreeOverlay, openSettingsOverlay, openThinkingSelectorOverlay, openTranscriptTreeOverlay, openUserMessageForkOverlay, sessionTreeSelectItems };
634
+ export { formatAgentPickerOpenedHint, formatProjectTrustOpenedHint, formatReviewPickerOpenedHint, formatScopedModelsOpenedHint, formatScopedModelsSavedHint, formatSessionTreeOpenedHint, formatSettingsOpenedHint, formatThinkingLevelSavedHint, formatThinkingSelectorHint, openAgentPickerOverlay, openProjectTrustOverlay, openReviewLauncherOverlay, openScopedModelsOverlay, openSessionPickerOverlay, openSessionTreeOverlay, openSettingsOverlay, openThinkingSelectorOverlay, openTimelineOverlay, openTranscriptTreeOverlay, openUserMessageForkOverlay, sessionTreeSelectItems };
600
635
 
601
636
  //# sourceMappingURL=tui-picker-overlay.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"tui-picker-overlay.js","names":[],"sources":["../../../src/tui/tui-picker-overlay.ts"],"sourcesContent":["import type { KeybindingsManager, SelectItem } from '@earendil-works/pi-tui';\n\nimport { ScopedModelsSelector } from './components/scoped-models-selector.js';\nimport { SettingsSelector } from './components/settings-selector.js';\nimport { SearchableSelectList } from './components/searchable-select-list.js';\nimport { SessionSelector } from './components/session-selector.js';\nimport { ThinkingSelector } from './components/thinking-selector.js';\nimport { formatKeyIds } from './format-tui-hotkeys.js';\nimport type { TuiAgentInfo, TuiSessionItem } from './tui-backend.js';\nimport type { PickerServices } from './tui-picker-services.js';\nimport { formatSessionPickerDescription } from './tui-session-format.js';\nimport { searchableSelectListTheme, theme } from './theme.js';\nimport { filterTuiTranscriptTreeEntries } from './tui-transcript-tree.js';\nimport {\n defaultTranscriptForkKey,\n formatTranscriptTreeFilterHint,\n formatUserMessageForkOpenedHint,\n TranscriptTreeSelectList,\n userMessageForkSelectItems,\n} from './tui-transcript-tree-picker.js';\nimport {\n listThinkingLevels,\n normalizeThinkLevel,\n type ThinkLevel,\n} from '../agent/transcript/thinking-types.js';\nimport { parseAgentSessionKey } from '../routing/agent-session-key.js';\nimport {\n getProjectTrustOptions,\n hasTrustRequiringProjectResources,\n} from '../project-trust/trust-store.js';\nimport type { ReviewContext } from '../review/review-git.js';\n\ntype SearchableSelectItem = SelectItem & { searchText?: string };\n\nfunction formatSelectNavigationHint(keybindings: KeybindingsManager): string {\n const up = formatKeyIds(keybindings, 'tui.select.up', { capitalize: true });\n const down = formatKeyIds(keybindings, 'tui.select.down', { capitalize: true });\n return `${up}/${down}`;\n}\n\nexport function formatScopedModelsOpenedHint(keybindings: KeybindingsManager): string {\n const modelCycle = formatKeyIds(keybindings, 'app.model.cycleForward', { capitalize: true });\n return `Scoped models for ${modelCycle}`;\n}\n\nexport function formatScopedModelsSavedHint(params: {\n refs: string[] | null;\n total: number;\n keybindings: KeybindingsManager;\n}): string {\n const modelCycle = formatKeyIds(params.keybindings, 'app.model.cycleForward', {\n capitalize: true,\n });\n if (params.refs === null) {\n return `${modelCycle} cycles all ${params.total} models`;\n }\n const count = params.refs.length;\n return `${modelCycle} cycles ${count} scoped model${count === 1 ? '' : 's'}`;\n}\n\nexport function formatSettingsOpenedHint(keybindings: KeybindingsManager): string {\n const nav = formatSelectNavigationHint(keybindings);\n const confirm = formatKeyIds(keybindings, 'tui.select.confirm', { capitalize: true });\n const cancel = formatKeyIds(keybindings, 'tui.select.cancel', { capitalize: true });\n return `Settings (${nav} · ${confirm} toggle · ${cancel} close)`;\n}\n\nexport function formatThinkingSelectorHint(keybindings: KeybindingsManager): string {\n const nav = formatSelectNavigationHint(keybindings);\n const confirm = formatKeyIds(keybindings, 'tui.select.confirm', { capitalize: true });\n const cancel = formatKeyIds(keybindings, 'tui.select.cancel', { capitalize: true });\n return `Thinking level (${nav} · ${confirm} select · ${cancel} close)`;\n}\n\nexport function formatThinkingLevelSavedHint(level: ThinkLevel): string {\n return `Thinking level: ${level}`;\n}\n\nexport function formatProjectTrustOpenedHint(keybindings: KeybindingsManager): string {\n const nav = formatSelectNavigationHint(keybindings);\n const confirm = formatKeyIds(keybindings, 'tui.select.confirm', { capitalize: true });\n const cancel = formatKeyIds(keybindings, 'tui.select.cancel', { capitalize: true });\n return `Project trust (${nav} · ${confirm} select · ${cancel} close)`;\n}\n\nexport function formatReviewPickerOpenedHint(keybindings: KeybindingsManager): string {\n const nav = formatSelectNavigationHint(keybindings);\n const confirm = formatKeyIds(keybindings, 'tui.select.confirm', { capitalize: true });\n const cancel = formatKeyIds(keybindings, 'tui.select.cancel', { capitalize: true });\n return `Review (${nav} · type to filter · ${confirm} select · ${cancel} close)`;\n}\n\nexport function formatAgentPickerOpenedHint(keybindings: KeybindingsManager): string {\n const nav = formatSelectNavigationHint(keybindings);\n const confirm = formatKeyIds(keybindings, 'tui.select.confirm', { capitalize: true });\n const cancel = formatKeyIds(keybindings, 'tui.select.cancel', { capitalize: true });\n return `Switch agent (${nav} · ${confirm} select · ${cancel} close)`;\n}\n\nfunction agentSelectItems(agents: TuiAgentInfo[], currentAgentId?: string): SelectItem[] {\n const current = currentAgentId?.trim().toLowerCase();\n return [...agents]\n .filter((agent) => agent.enabled !== false)\n .sort((a, b) => {\n if (a.id === current && b.id !== current) return -1;\n if (b.id === current && a.id !== current) return 1;\n if (a.id === 'coder' && b.id !== 'coder') return -1;\n if (b.id === 'coder' && a.id !== 'coder') return 1;\n return a.id.localeCompare(b.id);\n })\n .map((agent) => ({\n label: agent.id === current ? `${agent.id} (current)` : agent.id,\n value: agent.id,\n description: agent.displayName,\n }));\n}\n\nexport function formatSessionTreeOpenedHint(keybindings: KeybindingsManager): string {\n const nav = formatSelectNavigationHint(keybindings);\n const confirm = formatKeyIds(keybindings, 'tui.select.confirm', { capitalize: true });\n const cancel = formatKeyIds(keybindings, 'tui.select.cancel', { capitalize: true });\n return `Session tree (${nav} · type to filter · ${confirm} resume · ${cancel} close)`;\n}\n\nfunction resumeSession(svc: PickerServices, sessionKey: string): void {\n svc.setSessionKey(sessionKey);\n svc.clearChatForSessionSwitch();\n svc.chatLog.addSystem(`Session: ${sessionKey}`);\n void svc\n .refreshSessionInfo()\n .then(() => svc.loadSessionHistory())\n .then(() => {\n svc.updateHeader();\n svc.tui.requestRender();\n });\n svc.tui.requestRender();\n}\n\nfunction sessionTreeGroup(session: TuiSessionItem): { agentId: string; root: string; leaf: string } {\n const raw = session.key.trim();\n const parts = raw.split(':').filter(Boolean);\n if (parts.length >= 3 && parts[0] === 'agent') {\n const rest = parts.slice(2);\n return {\n agentId: parts[1] ?? 'main',\n root: rest[0] ?? raw,\n leaf: rest.length > 1 ? rest.slice(1).join(':') : rest.join(':') || raw,\n };\n }\n return { agentId: 'legacy', root: raw || 'session', leaf: raw || 'session' };\n}\n\nexport function sessionTreeSelectItems(\n sessions: TuiSessionItem[],\n currentSessionKey?: string,\n): SelectItem[] {\n const byKey = new Map(sessions.map((session) => [session.key, session]));\n return [...sessions]\n .sort((a, b) => {\n const ga = sessionTreeGroup(a);\n const gb = sessionTreeGroup(b);\n const groupCmp = `${ga.agentId}:${ga.root}`.localeCompare(`${gb.agentId}:${gb.root}`);\n if (groupCmp !== 0) return groupCmp;\n return (b.updatedAt ?? 0) - (a.updatedAt ?? 0);\n })\n .map((session) => {\n const group = sessionTreeGroup(session);\n const current = session.key === currentSessionKey ? '* ' : ' ';\n const label = session.displayName?.trim() || group.leaf;\n const parent = session.forkedFromSessionKey\n ? (byKey.get(session.forkedFromSessionKey)?.displayName?.trim() ?? session.forkedFromSessionKey)\n : null;\n const description = [\n `${group.agentId}/${group.root}`,\n formatSessionPickerDescription(session, { showKey: Boolean(session.displayName) }),\n parent ? `forked from ${parent}` : '',\n ]\n .filter(Boolean)\n .join(' · ');\n return {\n value: session.key,\n label: `${current}${label}`,\n description,\n searchText: `${session.key} ${session.displayName ?? ''} ${session.model ?? ''} ${parent ?? ''}`,\n };\n });\n}\n\n\n\n\n\nexport async function openAgentPickerOverlay(svc: PickerServices): Promise<void> {\n const parsed = parseAgentSessionKey(svc.state.currentSessionKey);\n if (!parsed) {\n svc.chatLog.addSystem('Cannot switch agent: current session is not an agent session.');\n svc.tui.requestRender();\n return;\n }\n if (svc.state.activeRunId) {\n svc.chatLog.addSystem('Cannot switch agent while a run is active. Abort first.');\n svc.tui.requestRender();\n return;\n }\n if (!svc.switchAgentSession) {\n svc.chatLog.addSystem('Agent switching is not available in this mode.');\n svc.tui.requestRender();\n return;\n }\n const agents = await svc.client.listAgents();\n const items = agentSelectItems(agents, parsed.agentId);\n if (items.length === 0) {\n svc.chatLog.addSystem('No agents available.');\n svc.tui.requestRender();\n return;\n }\n svc.chatLog.addSystem(theme.dim(formatAgentPickerOpenedHint(svc.keybindings)));\n const list = new SearchableSelectList(items, Math.min(10, items.length), searchableSelectListTheme, {\n searchPromptText: 'agent> ',\n });\n const closeSelector = svc.openEditorSelector(list, list);\n list.onSelect = (item) => {\n closeSelector();\n const targetAgentId = item.value;\n if (targetAgentId === parsed.agentId) {\n svc.chatLog.addSystem(`Already using agent: ${targetAgentId}`);\n svc.tui.requestRender();\n return;\n }\n const targetSessionKey = `agent:${targetAgentId}:${parsed.rest}`;\n void Promise.resolve(svc.switchAgentSession?.(targetSessionKey, targetAgentId))\n .then(() => {\n svc.chatLog.addSystem(`Switched to agent: ${targetAgentId}\\nSession: ${targetSessionKey}`);\n })\n .catch((err: unknown) => {\n const errorMessage = err instanceof Error ? err.message : String(err);\n svc.chatLog.addSystem(`Agent switch failed: ${errorMessage}`);\n })\n .finally(() => svc.tui.requestRender());\n svc.tui.requestRender();\n };\n list.onCancel = () => closeSelector();\n svc.tui.requestRender();\n}\n\nfunction quoteReviewArg(value: string): string {\n return /^[A-Za-z0-9._/@:-]+$/.test(value) ? value : JSON.stringify(value);\n}\n\nfunction formatReviewStatus(status: ReviewContext['status']): string {\n if (status.isClean) return 'working tree clean';\n const parts: string[] = [];\n if (status.changedFiles > 0) parts.push(`${status.changedFiles} changed`);\n if (status.untrackedFiles > 0) parts.push(`${status.untrackedFiles} untracked`);\n return parts.join(', ');\n}\n\nfunction reviewPresetItems(context: ReviewContext): SearchableSelectItem[] {\n return [\n {\n value: 'base',\n label: 'Review against a base branch',\n description: context.defaultBaseBranch ? `PR Style · default ${context.defaultBaseBranch}` : 'PR Style',\n searchText: 'pr pull request base branch merge base',\n },\n {\n value: 'uncommitted',\n label: 'Review uncommitted changes',\n description: formatReviewStatus(context.status),\n searchText: 'workspace working tree uncommitted diff status',\n },\n {\n value: 'commit',\n label: 'Review a commit',\n description: context.commits.length > 0 ? `${context.commits.length} recent commits` : 'no commits found',\n searchText: 'commit sha history log',\n },\n {\n value: 'custom',\n label: 'Custom review instructions',\n description: 'edit prompt before sending',\n searchText: 'custom instructions focus prompt',\n },\n ];\n}\n\nfunction branchSelectItems(context: ReviewContext): SelectItem[] {\n return context.branches\n .filter((branch) => !branch.current)\n .map((branch) => ({\n value: branch.name,\n label: branch.name,\n description: [\n branch.name === context.defaultBaseBranch ? 'default' : '',\n branch.remote ? 'remote' : 'local',\n ].filter(Boolean).join(' · '),\n searchText: branch.name,\n }));\n}\n\nfunction commitSelectItems(context: ReviewContext): SelectItem[] {\n return context.commits.map((commit) => ({\n value: commit.sha,\n label: commit.subject,\n description: [commit.shortSha, commit.date?.slice(0, 10)].filter(Boolean).join(' · '),\n searchText: `${commit.sha} ${commit.shortSha} ${commit.subject}`,\n }));\n}\n\nfunction openReviewBranchSelector(svc: PickerServices, context: ReviewContext): void {\n const items = branchSelectItems(context);\n if (items.length === 0) {\n svc.closeOverlay();\n svc.tui.setFocus(svc.editor);\n svc.chatLog.addSystem('No base branches available for review.');\n svc.tui.requestRender();\n return;\n }\n const list = new SearchableSelectList(items, Math.min(10, items.length), searchableSelectListTheme, {\n searchPromptText: 'branch> ',\n });\n const defaultIndex = context.defaultBaseBranch\n ? items.findIndex((item) => item.value === context.defaultBaseBranch)\n : -1;\n if (defaultIndex >= 0) list.setSelectedIndex(defaultIndex);\n list.onSelect = (item) => {\n svc.closeOverlay();\n svc.tui.setFocus(svc.editor);\n svc.sendMessage(`/review --base ${quoteReviewArg(item.value)}`);\n };\n list.onCancel = () => {\n openReviewPresetSelector(svc, context);\n };\n svc.openOverlay(list);\n svc.chatLog.addSystem(theme.dim('Select a base branch to review'));\n svc.tui.requestRender();\n}\n\nfunction openReviewCommitSelector(svc: PickerServices, context: ReviewContext): void {\n const items = commitSelectItems(context);\n if (items.length === 0) {\n svc.closeOverlay();\n svc.tui.setFocus(svc.editor);\n svc.chatLog.addSystem('No commits available for review.');\n svc.tui.requestRender();\n return;\n }\n const list = new SearchableSelectList(items, Math.min(12, items.length), searchableSelectListTheme, {\n searchPromptText: 'commit> ',\n });\n list.onSelect = (item) => {\n svc.closeOverlay();\n svc.tui.setFocus(svc.editor);\n svc.sendMessage(`/review --commit ${item.value}`);\n };\n list.onCancel = () => {\n openReviewPresetSelector(svc, context);\n };\n svc.openOverlay(list);\n svc.chatLog.addSystem(theme.dim('Select a commit to review'));\n svc.tui.requestRender();\n}\n\nfunction openReviewPresetSelector(svc: PickerServices, context: ReviewContext): void {\n const items = reviewPresetItems(context);\n const list = new SearchableSelectList(items, Math.min(8, items.length), searchableSelectListTheme, {\n searchPromptText: 'review> ',\n });\n list.onSelect = (item) => {\n if (item.value === 'uncommitted') {\n svc.closeOverlay();\n svc.tui.setFocus(svc.editor);\n svc.sendMessage('/review --uncommitted');\n return;\n }\n if (item.value === 'custom') {\n svc.closeOverlay();\n svc.tui.setFocus(svc.editor);\n svc.setEditorText('/review --custom ');\n svc.tui.requestRender();\n return;\n }\n if (item.value === 'base') {\n openReviewBranchSelector(svc, context);\n return;\n }\n if (item.value === 'commit') {\n openReviewCommitSelector(svc, context);\n }\n };\n list.onCancel = () => {\n svc.closeOverlay();\n svc.tui.setFocus(svc.editor);\n svc.tui.requestRender();\n };\n\n svc.openOverlay(list);\n svc.chatLog.addSystem(theme.dim(formatReviewPickerOpenedHint(svc.keybindings)));\n svc.tui.requestRender();\n}\n\nexport async function openReviewLauncherOverlay(svc: PickerServices): Promise<void> {\n if (!svc.client.getReviewContext) {\n svc.chatLog.addSystem('Review picker is not available in this mode. Use /review --uncommitted, /review --base <branch>, or /review --commit <sha>.');\n svc.tui.requestRender();\n return;\n }\n let context: ReviewContext;\n try {\n context = await svc.client.getReviewContext(svc.state.currentSessionKey);\n } catch (err) {\n const errorMessage = err instanceof Error ? err.message : String(err);\n svc.chatLog.addSystem(`Review picker failed: ${errorMessage}`);\n svc.tui.requestRender();\n return;\n }\n openReviewPresetSelector(svc, context);\n}\n\n/** Ctrl+Shift+P — session picker with rename/delete. */\nexport async function openSessionPickerOverlay(svc: PickerServices): Promise<void> {\n const sessions = await svc.client.listSessions();\n if (sessions.length === 0) {\n svc.chatLog.addSystem('No sessions listed.');\n svc.tui.requestRender();\n return;\n }\n\n const selector = new SessionSelector(\n sessions,\n {\n onResume: (sessionKey) => {\n svc.closeOverlay();\n svc.tui.setFocus(svc.editor);\n resumeSession(svc, sessionKey);\n },\n onRename: async (sessionKey, name) => {\n const result = await svc.client.renameSession(sessionKey, name);\n return result.ok ? { ok: true } : { ok: false, error: 'Rename failed' };\n },\n onDelete: async (sessionKey) => {\n if (sessionKey === svc.state.currentSessionKey) {\n return { ok: false, error: 'Switch away before deleting the active session' };\n }\n const result = await svc.client.deleteSession(sessionKey);\n return result.ok ? { ok: true } : { ok: false, error: 'Delete failed' };\n },\n onCancel: () => {\n svc.closeOverlay();\n svc.tui.setFocus(svc.editor);\n svc.tui.requestRender();\n },\n requestRender: () => svc.tui.requestRender(),\n },\n svc.keybindings,\n sessions.find((s) => s.key === svc.state.currentSessionKey)?.cwd ?? process.cwd(),\n svc.state.currentSessionKey,\n );\n\n svc.openOverlay(selector);\n svc.chatLog.addSystem(theme.dim('Session picker'));\n svc.tui.requestRender();\n}\n\n/** Searchable session tree navigation overlay. */\nexport async function openSessionTreeOverlay(svc: PickerServices): Promise<void> {\n const sessions = await svc.client.listSessions();\n if (sessions.length === 0) {\n svc.chatLog.addSystem('No sessions listed.');\n svc.tui.requestRender();\n return;\n }\n\n const items = sessionTreeSelectItems(sessions, svc.state.currentSessionKey);\n const list = new SearchableSelectList(items, Math.min(14, items.length), searchableSelectListTheme);\n list.onSelect = (item) => {\n svc.closeOverlay();\n svc.tui.setFocus(svc.editor);\n resumeSession(svc, item.value);\n };\n list.onCancel = () => {\n svc.closeOverlay();\n svc.tui.setFocus(svc.editor);\n svc.tui.requestRender();\n };\n\n svc.openOverlay(list);\n svc.chatLog.addSystem(theme.dim(formatSessionTreeOpenedHint(svc.keybindings)));\n svc.tui.requestRender();\n}\n\n/** Searchable current-transcript tree overlay. */\nexport async function openTranscriptTreeOverlay(svc: PickerServices): Promise<void> {\n const entries = await svc.client.loadTranscriptTree(svc.state.currentSessionKey);\n const filterMode = svc.getTuiSettings().treeFilterMode;\n const visibleEntries = filterTuiTranscriptTreeEntries(entries, filterMode);\n if (visibleEntries.length === 0) {\n svc.chatLog.addSystem('No transcript entries found.');\n svc.tui.requestRender();\n return;\n }\n\n const byId = new Map(entries.map((entry) => [entry.id, entry]));\n const list = new TranscriptTreeSelectList(entries, filterMode, svc.keybindings, Math.min(16, visibleEntries.length));\n list.onSelect = (item) => {\n const entry = byId.get(item.value);\n svc.closeOverlay();\n svc.tui.setFocus(svc.editor);\n if (!entry) {\n svc.tui.requestRender();\n return;\n }\n const targetKey = defaultTranscriptForkKey(svc.state.currentSessionKey, entry.id);\n const sourceSessionKey = svc.state.currentSessionKey;\n svc.chatLog.addSystem(theme.dim(`Forking transcript at ${entry.id}...`));\n void svc.client\n .forkSessionAt(sourceSessionKey, targetKey, entry.id)\n .then((result) => {\n resumeSession(svc, result.sessionKey);\n svc.chatLog.addBranchSummary({\n sourceSessionKey,\n targetSessionKey: result.sessionKey,\n rowCount: result.rowCount,\n entryId: entry.id,\n });\n })\n .catch((err) => {\n const errorMessage = err instanceof Error ? err.message : String(err);\n svc.chatLog.addSystem(`Fork failed: ${errorMessage}`);\n svc.tui.requestRender();\n });\n svc.tui.requestRender();\n };\n list.onCancel = () => {\n svc.closeOverlay();\n svc.tui.setFocus(svc.editor);\n svc.tui.requestRender();\n };\n list.onFilterChange = (mode) => {\n svc.chatLog.addSystem(theme.dim(`Transcript tree filter: ${mode}`));\n svc.tui.requestRender();\n };\n list.onLabelSubmit = (entry, label) => {\n void svc.client\n .setTranscriptLabel(svc.state.currentSessionKey, entry.id, label)\n .then(() => {\n list.updateEntryLabel(entry.id, label);\n svc.chatLog.addSystem(\n theme.dim(label?.trim() ? `Labeled ${entry.id}: ${label.trim()}` : `Cleared label for ${entry.id}`),\n );\n svc.tui.requestRender();\n })\n .catch((err) => {\n const errorMessage = err instanceof Error ? err.message : String(err);\n svc.chatLog.addSystem(`Label failed: ${errorMessage}`);\n svc.tui.requestRender();\n });\n };\n\n svc.openOverlay(list);\n svc.chatLog.addSystem(theme.dim(formatTranscriptTreeFilterHint(svc.keybindings, filterMode)));\n svc.tui.requestRender();\n}\n\n/** Pi-style `/fork` overlay: select a previous user message and branch there. */\nexport async function openUserMessageForkOverlay(svc: PickerServices): Promise<void> {\n const entries = await svc.client.loadTranscriptTree(svc.state.currentSessionKey);\n const byId = new Map(entries.map((entry) => [entry.id, entry]));\n const items = userMessageForkSelectItems(entries);\n if (items.length === 0) {\n svc.chatLog.addSystem('No messages to fork from.');\n svc.tui.requestRender();\n return;\n }\n\n const list = new SearchableSelectList(items, Math.min(10, items.length), searchableSelectListTheme, {\n wrapNavigation: true,\n });\n list.setSelectedIndex(items.length - 1);\n list.onSelect = (item) => {\n svc.closeOverlay();\n svc.tui.setFocus(svc.editor);\n const entry = byId.get(item.value);\n const targetKey = defaultTranscriptForkKey(svc.state.currentSessionKey, item.value);\n const sourceSessionKey = svc.state.currentSessionKey;\n svc.chatLog.addSystem(theme.dim(`Forking from ${item.value}...`));\n void svc.client\n .forkSessionAt(sourceSessionKey, targetKey, item.value)\n .then((result) => {\n resumeSession(svc, result.sessionKey);\n if (entry?.contentText) {\n svc.setEditorText(entry.contentText);\n }\n svc.chatLog.addBranchSummary({\n sourceSessionKey,\n targetSessionKey: result.sessionKey,\n rowCount: result.rowCount,\n entryId: item.value,\n restoredText: entry?.contentText,\n });\n })\n .catch((err) => {\n const errorMessage = err instanceof Error ? err.message : String(err);\n svc.chatLog.addSystem(`Fork failed: ${errorMessage}`);\n svc.tui.requestRender();\n });\n svc.tui.requestRender();\n };\n list.onCancel = () => {\n svc.closeOverlay();\n svc.tui.setFocus(svc.editor);\n svc.tui.requestRender();\n };\n\n svc.openOverlay(list);\n svc.chatLog.addSystem(theme.dim(formatUserMessageForkOpenedHint(svc.keybindings)));\n svc.tui.requestRender();\n}\n\n/** `/scoped-models` — limit Ctrl+P model cycle set. */\nexport async function openScopedModelsOverlay(svc: PickerServices): Promise<void> {\n const catalog = await svc.client.listModels();\n svc.setModelChoices(catalog);\n if (catalog.length === 0) {\n svc.chatLog.addSystem('No models available.');\n svc.tui.requestRender();\n return;\n }\n\n const selector = new ScopedModelsSelector(\n catalog,\n svc.getScopedModelRefs(),\n {\n onSave: (refs) => {\n svc.setScopedModelRefs(refs);\n svc.refreshCycleModels();\n svc.closeOverlay();\n svc.tui.setFocus(svc.editor);\n svc.chatLog.addSystem(\n theme.dim(formatScopedModelsSavedHint({\n refs,\n total: catalog.length,\n keybindings: svc.keybindings,\n })),\n );\n svc.tui.requestRender();\n },\n onCancel: () => {\n svc.closeOverlay();\n svc.tui.setFocus(svc.editor);\n svc.tui.requestRender();\n },\n requestRender: () => svc.tui.requestRender(),\n },\n svc.keybindings,\n );\n\n svc.openOverlay(selector);\n svc.chatLog.addSystem(theme.dim(formatScopedModelsOpenedHint(svc.keybindings)));\n svc.tui.requestRender();\n}\n\n/** `/settings` — TUI preferences overlay. */\nexport function openSettingsOverlay(svc: PickerServices): void {\n const selector = new SettingsSelector(svc.getTuiSettings(), {\n onChange: (settings) => svc.applyTuiSettings(settings),\n onThemePreview: (themeId) => svc.previewTheme(themeId),\n onReloadKeybindings: () => svc.reloadKeybindings(),\n onCancel: () => {\n svc.previewTheme(svc.getTuiSettings().theme);\n svc.closeOverlay();\n svc.tui.setFocus(svc.editor);\n svc.tui.requestRender();\n },\n });\n\n svc.openOverlay(selector);\n svc.chatLog.addSystem(theme.dim(formatSettingsOpenedHint(svc.keybindings)));\n svc.tui.requestRender();\n}\n\n/** `/think` — select and persist the current session thinking level. */\nexport function openThinkingSelectorOverlay(svc: PickerServices): void {\n const current = normalizeThinkLevel(svc.state.sessionInfo.thinkingLevel) ?? 'medium';\n const levels = listThinkingLevels(\n svc.state.sessionInfo.modelProvider,\n svc.state.sessionInfo.model,\n ).map((level) => (level === 'on' ? 'low' : level)) as ThinkLevel[];\n const uniqueLevels = [...new Set(levels)];\n\n const selector = new ThinkingSelector(current, uniqueLevels, {\n onSelect: (level) => {\n void svc.setThinkingLevel(level).then(() => {\n svc.closeOverlay();\n svc.tui.setFocus(svc.editor);\n });\n },\n onCancel: () => {\n svc.closeOverlay();\n svc.tui.setFocus(svc.editor);\n svc.tui.requestRender();\n },\n }, svc.keybindings);\n\n svc.openOverlay(selector);\n svc.chatLog.addSystem(theme.dim(formatThinkingSelectorHint(svc.keybindings)));\n svc.tui.requestRender();\n}\n\nexport function openProjectTrustOverlay(svc: PickerServices): void {\n const cwd = process.cwd();\n const trustStore = svc.getProjectTrustStore();\n const currentStored = trustStore.getEntry(cwd);\n const sessionDecision = svc.getProjectTrustSessionDecision();\n const hasProjectResources = hasTrustRequiringProjectResources(cwd);\n const options = getProjectTrustOptions(cwd, { includeSessionOnly: true });\n const optionsByLabel = new Map(options.map((option) => [option.label, option]));\n const items: SelectItem[] = options.map((option) => ({\n value: option.label,\n label: option.label,\n description: option.savedPath ?? 'Current TUI session only',\n }));\n const list = new SearchableSelectList(items, Math.min(8, items.length), searchableSelectListTheme, {\n searchPromptText: 'trust: ',\n });\n\n list.onSelect = (item) => {\n const selected = optionsByLabel.get(item.value);\n if (!selected) return;\n if (selected.updates.length > 0) {\n trustStore.setMany(selected.updates);\n svc.setProjectTrustSessionDecision(null);\n } else {\n svc.setProjectTrustSessionDecision(selected.trusted);\n }\n svc.closeOverlay();\n svc.tui.setFocus(svc.editor);\n const scope = selected.savedPath ? `saved for ${selected.savedPath}` : 'this session only';\n svc.chatLog.addSystem(theme.dim(`Project trust: ${selected.trusted ? 'trusted' : 'not trusted'} (${scope})`));\n svc.tui.requestRender();\n };\n list.onCancel = () => {\n svc.closeOverlay();\n svc.tui.setFocus(svc.editor);\n svc.tui.requestRender();\n };\n\n svc.openOverlay(list);\n const storedLabel = currentStored\n ? `${currentStored.decision ? 'trusted' : 'not trusted'} from ${currentStored.path}`\n : 'not saved';\n const sessionLabel = sessionDecision === null ? 'none' : sessionDecision ? 'trusted' : 'not trusted';\n svc.chatLog.addSystem(\n theme.dim(\n [\n formatProjectTrustOpenedHint(svc.keybindings),\n `Project resources: ${hasProjectResources ? 'detected' : 'none detected'}`,\n `Stored: ${storedLabel}`,\n `Session: ${sessionLabel}`,\n ].join('\\n'),\n ),\n );\n svc.tui.requestRender();\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"tui-picker-overlay.js","names":[],"sources":["../../../src/tui/tui-picker-overlay.ts"],"sourcesContent":["import type { KeybindingsManager, SelectItem } from '@earendil-works/pi-tui';\n\nimport { ScopedModelsSelector } from './components/scoped-models-selector.js';\nimport { SettingsSelector } from './components/settings-selector.js';\nimport { SearchableSelectList } from './components/searchable-select-list.js';\nimport { SessionSelector } from './components/session-selector.js';\nimport { ThinkingSelector } from './components/thinking-selector.js';\nimport { formatKeyIds } from './format-tui-hotkeys.js';\nimport type { TuiAgentInfo, TuiSessionItem } from './tui-backend.js';\nimport type { PickerServices } from './tui-picker-services.js';\nimport { formatSessionPickerDescription } from './tui-session-format.js';\nimport { searchableSelectListTheme, theme } from './theme.js';\nimport { buildTuiTimelineTurns } from './tui-timeline.js';\nimport {\n formatTimelineOpenedHint,\n TimelineSelectList,\n} from './tui-timeline-picker.js';\nimport { filterTuiTranscriptTreeEntries } from './tui-transcript-tree.js';\nimport {\n defaultTranscriptForkKey,\n formatTranscriptTreeFilterHint,\n formatUserMessageForkOpenedHint,\n TranscriptTreeSelectList,\n userMessageForkSelectItems,\n} from './tui-transcript-tree-picker.js';\nimport {\n listThinkingLevels,\n normalizeThinkLevel,\n type ThinkLevel,\n} from '../agent/transcript/thinking-types.js';\nimport { parseAgentSessionKey } from '../routing/agent-session-key.js';\nimport {\n getProjectTrustOptions,\n hasTrustRequiringProjectResources,\n} from '../project-trust/trust-store.js';\nimport type { ReviewContext } from '../review/review-git.js';\n\ntype SearchableSelectItem = SelectItem & { searchText?: string };\n\nfunction formatSelectNavigationHint(keybindings: KeybindingsManager): string {\n const up = formatKeyIds(keybindings, 'tui.select.up', { capitalize: true });\n const down = formatKeyIds(keybindings, 'tui.select.down', { capitalize: true });\n return `${up}/${down}`;\n}\n\nexport function formatScopedModelsOpenedHint(keybindings: KeybindingsManager): string {\n const modelCycle = formatKeyIds(keybindings, 'app.model.cycleForward', { capitalize: true });\n return `Scoped models for ${modelCycle}`;\n}\n\nexport function formatScopedModelsSavedHint(params: {\n refs: string[] | null;\n total: number;\n keybindings: KeybindingsManager;\n}): string {\n const modelCycle = formatKeyIds(params.keybindings, 'app.model.cycleForward', {\n capitalize: true,\n });\n if (params.refs === null) {\n return `${modelCycle} cycles all ${params.total} models`;\n }\n const count = params.refs.length;\n return `${modelCycle} cycles ${count} scoped model${count === 1 ? '' : 's'}`;\n}\n\nexport function formatSettingsOpenedHint(keybindings: KeybindingsManager): string {\n const nav = formatSelectNavigationHint(keybindings);\n const confirm = formatKeyIds(keybindings, 'tui.select.confirm', { capitalize: true });\n const cancel = formatKeyIds(keybindings, 'tui.select.cancel', { capitalize: true });\n return `Settings (${nav} · ${confirm} toggle · ${cancel} close)`;\n}\n\nexport function formatThinkingSelectorHint(keybindings: KeybindingsManager): string {\n const nav = formatSelectNavigationHint(keybindings);\n const confirm = formatKeyIds(keybindings, 'tui.select.confirm', { capitalize: true });\n const cancel = formatKeyIds(keybindings, 'tui.select.cancel', { capitalize: true });\n return `Thinking level (${nav} · ${confirm} select · ${cancel} close)`;\n}\n\nexport function formatThinkingLevelSavedHint(level: ThinkLevel): string {\n return `Thinking level: ${level}`;\n}\n\nexport function formatProjectTrustOpenedHint(keybindings: KeybindingsManager): string {\n const nav = formatSelectNavigationHint(keybindings);\n const confirm = formatKeyIds(keybindings, 'tui.select.confirm', { capitalize: true });\n const cancel = formatKeyIds(keybindings, 'tui.select.cancel', { capitalize: true });\n return `Project trust (${nav} · ${confirm} select · ${cancel} close)`;\n}\n\nexport function formatReviewPickerOpenedHint(keybindings: KeybindingsManager): string {\n const nav = formatSelectNavigationHint(keybindings);\n const confirm = formatKeyIds(keybindings, 'tui.select.confirm', { capitalize: true });\n const cancel = formatKeyIds(keybindings, 'tui.select.cancel', { capitalize: true });\n return `Review (${nav} · type to filter · ${confirm} select · ${cancel} close)`;\n}\n\nexport function formatAgentPickerOpenedHint(keybindings: KeybindingsManager): string {\n const nav = formatSelectNavigationHint(keybindings);\n const confirm = formatKeyIds(keybindings, 'tui.select.confirm', { capitalize: true });\n const cancel = formatKeyIds(keybindings, 'tui.select.cancel', { capitalize: true });\n return `Switch agent (${nav} · ${confirm} select · ${cancel} close)`;\n}\n\nfunction agentSelectItems(agents: TuiAgentInfo[], currentAgentId?: string): SelectItem[] {\n const current = currentAgentId?.trim().toLowerCase();\n return [...agents]\n .filter((agent) => agent.enabled !== false)\n .sort((a, b) => {\n if (a.id === current && b.id !== current) return -1;\n if (b.id === current && a.id !== current) return 1;\n if (a.id === 'coder' && b.id !== 'coder') return -1;\n if (b.id === 'coder' && a.id !== 'coder') return 1;\n return a.id.localeCompare(b.id);\n })\n .map((agent) => ({\n label: agent.id === current ? `${agent.id} (current)` : agent.id,\n value: agent.id,\n description: agent.displayName,\n }));\n}\n\nexport function formatSessionTreeOpenedHint(keybindings: KeybindingsManager): string {\n const nav = formatSelectNavigationHint(keybindings);\n const confirm = formatKeyIds(keybindings, 'tui.select.confirm', { capitalize: true });\n const cancel = formatKeyIds(keybindings, 'tui.select.cancel', { capitalize: true });\n return `Session tree (${nav} · type to filter · ${confirm} resume · ${cancel} close)`;\n}\n\nexport async function openTimelineOverlay(\n svc: PickerServices,\n initialQuery?: string,\n): Promise<void> {\n const items = await svc.client.loadTimeline(svc.state.currentSessionKey);\n const turns = buildTuiTimelineTurns(items);\n if (turns.length === 0) {\n svc.chatLog.addSystem('No timeline turns found.');\n svc.tui.requestRender();\n return;\n }\n\n const viewState = svc.chatLog.getTimelineViewportState();\n const activeDisplayIndex =\n viewState.mode === 'history'\n ? viewState.displayIndex\n : turns[turns.length - 1]?.displayIndex;\n const list = new TimelineSelectList(turns, {\n keybindings: svc.keybindings,\n ...(activeDisplayIndex !== undefined ? { activeDisplayIndex } : {}),\n ...(initialQuery ? { initialQuery } : {}),\n });\n list.onSelect = (turn) => {\n svc.closeOverlay();\n svc.tui.setFocus(svc.editor);\n void (async () => {\n if (!svc.chatLog.jumpToDisplayIndex(turn.displayIndex)) {\n const loaded =\n turn.rowNumber !== undefined\n ? await svc.loadHistoryWindow({ rowNumber: turn.rowNumber })\n : false;\n if (!loaded || !svc.chatLog.jumpToDisplayIndex(turn.displayIndex)) {\n svc.chatLog.addSystem(`Turn ${turn.turn} is outside loaded history.`);\n }\n }\n svc.tui.requestRender();\n })();\n };\n list.onCancel = () => {\n svc.closeOverlay();\n svc.tui.setFocus(svc.editor);\n svc.tui.requestRender();\n };\n\n svc.openOverlay(list);\n svc.chatLog.addSystem(theme.dim(formatTimelineOpenedHint(svc.keybindings)));\n svc.tui.requestRender();\n}\n\nfunction resumeSession(svc: PickerServices, sessionKey: string): void {\n svc.setSessionKey(sessionKey);\n svc.clearChatForSessionSwitch();\n svc.chatLog.addSystem(`Session: ${sessionKey}`);\n void svc\n .refreshSessionInfo()\n .then(() => svc.loadSessionHistory())\n .then(() => {\n svc.updateHeader();\n svc.tui.requestRender();\n });\n svc.tui.requestRender();\n}\n\nfunction sessionTreeGroup(session: TuiSessionItem): { agentId: string; root: string; leaf: string } {\n const raw = session.key.trim();\n const parts = raw.split(':').filter(Boolean);\n if (parts.length >= 3 && parts[0] === 'agent') {\n const rest = parts.slice(2);\n return {\n agentId: parts[1] ?? 'main',\n root: rest[0] ?? raw,\n leaf: rest.length > 1 ? rest.slice(1).join(':') : rest.join(':') || raw,\n };\n }\n return { agentId: 'legacy', root: raw || 'session', leaf: raw || 'session' };\n}\n\nexport function sessionTreeSelectItems(\n sessions: TuiSessionItem[],\n currentSessionKey?: string,\n): SelectItem[] {\n const byKey = new Map(sessions.map((session) => [session.key, session]));\n return [...sessions]\n .sort((a, b) => {\n const ga = sessionTreeGroup(a);\n const gb = sessionTreeGroup(b);\n const groupCmp = `${ga.agentId}:${ga.root}`.localeCompare(`${gb.agentId}:${gb.root}`);\n if (groupCmp !== 0) return groupCmp;\n return (b.updatedAt ?? 0) - (a.updatedAt ?? 0);\n })\n .map((session) => {\n const group = sessionTreeGroup(session);\n const current = session.key === currentSessionKey ? '* ' : ' ';\n const label = session.displayName?.trim() || group.leaf;\n const parent = session.forkedFromSessionKey\n ? (byKey.get(session.forkedFromSessionKey)?.displayName?.trim() ?? session.forkedFromSessionKey)\n : null;\n const description = [\n `${group.agentId}/${group.root}`,\n formatSessionPickerDescription(session, { showKey: Boolean(session.displayName) }),\n parent ? `forked from ${parent}` : '',\n ]\n .filter(Boolean)\n .join(' · ');\n return {\n value: session.key,\n label: `${current}${label}`,\n description,\n searchText: `${session.key} ${session.displayName ?? ''} ${session.model ?? ''} ${parent ?? ''}`,\n };\n });\n}\n\n\n\n\n\nexport async function openAgentPickerOverlay(svc: PickerServices): Promise<void> {\n const parsed = parseAgentSessionKey(svc.state.currentSessionKey);\n if (!parsed) {\n svc.chatLog.addSystem('Cannot switch agent: current session is not an agent session.');\n svc.tui.requestRender();\n return;\n }\n if (svc.state.activeRunId) {\n svc.chatLog.addSystem('Cannot switch agent while a run is active. Abort first.');\n svc.tui.requestRender();\n return;\n }\n if (!svc.switchAgentSession) {\n svc.chatLog.addSystem('Agent switching is not available in this mode.');\n svc.tui.requestRender();\n return;\n }\n const agents = await svc.client.listAgents();\n const items = agentSelectItems(agents, parsed.agentId);\n if (items.length === 0) {\n svc.chatLog.addSystem('No agents available.');\n svc.tui.requestRender();\n return;\n }\n svc.chatLog.addSystem(theme.dim(formatAgentPickerOpenedHint(svc.keybindings)));\n const list = new SearchableSelectList(items, Math.min(10, items.length), searchableSelectListTheme, {\n searchPromptText: 'agent> ',\n });\n const closeSelector = svc.openEditorSelector(list, list);\n list.onSelect = (item) => {\n closeSelector();\n const targetAgentId = item.value;\n if (targetAgentId === parsed.agentId) {\n svc.chatLog.addSystem(`Already using agent: ${targetAgentId}`);\n svc.tui.requestRender();\n return;\n }\n const targetSessionKey = `agent:${targetAgentId}:${parsed.rest}`;\n void Promise.resolve(svc.switchAgentSession?.(targetSessionKey, targetAgentId))\n .then(() => {\n svc.chatLog.addSystem(`Switched to agent: ${targetAgentId}\\nSession: ${targetSessionKey}`);\n })\n .catch((err: unknown) => {\n const errorMessage = err instanceof Error ? err.message : String(err);\n svc.chatLog.addSystem(`Agent switch failed: ${errorMessage}`);\n })\n .finally(() => svc.tui.requestRender());\n svc.tui.requestRender();\n };\n list.onCancel = () => closeSelector();\n svc.tui.requestRender();\n}\n\nfunction quoteReviewArg(value: string): string {\n return /^[A-Za-z0-9._/@:-]+$/.test(value) ? value : JSON.stringify(value);\n}\n\nfunction formatReviewStatus(status: ReviewContext['status']): string {\n if (status.isClean) return 'working tree clean';\n const parts: string[] = [];\n if (status.changedFiles > 0) parts.push(`${status.changedFiles} changed`);\n if (status.untrackedFiles > 0) parts.push(`${status.untrackedFiles} untracked`);\n return parts.join(', ');\n}\n\nfunction reviewPresetItems(context: ReviewContext): SearchableSelectItem[] {\n return [\n {\n value: 'base',\n label: 'Review against a base branch',\n description: context.defaultBaseBranch ? `PR Style · default ${context.defaultBaseBranch}` : 'PR Style',\n searchText: 'pr pull request base branch merge base',\n },\n {\n value: 'uncommitted',\n label: 'Review uncommitted changes',\n description: formatReviewStatus(context.status),\n searchText: 'workspace working tree uncommitted diff status',\n },\n {\n value: 'commit',\n label: 'Review a commit',\n description: context.commits.length > 0 ? `${context.commits.length} recent commits` : 'no commits found',\n searchText: 'commit sha history log',\n },\n {\n value: 'custom',\n label: 'Custom review instructions',\n description: 'edit prompt before sending',\n searchText: 'custom instructions focus prompt',\n },\n ];\n}\n\nfunction branchSelectItems(context: ReviewContext): SelectItem[] {\n return context.branches\n .filter((branch) => !branch.current)\n .map((branch) => ({\n value: branch.name,\n label: branch.name,\n description: [\n branch.name === context.defaultBaseBranch ? 'default' : '',\n branch.remote ? 'remote' : 'local',\n ].filter(Boolean).join(' · '),\n searchText: branch.name,\n }));\n}\n\nfunction commitSelectItems(context: ReviewContext): SelectItem[] {\n return context.commits.map((commit) => ({\n value: commit.sha,\n label: commit.subject,\n description: [commit.shortSha, commit.date?.slice(0, 10)].filter(Boolean).join(' · '),\n searchText: `${commit.sha} ${commit.shortSha} ${commit.subject}`,\n }));\n}\n\nfunction openReviewBranchSelector(svc: PickerServices, context: ReviewContext): void {\n const items = branchSelectItems(context);\n if (items.length === 0) {\n svc.closeOverlay();\n svc.tui.setFocus(svc.editor);\n svc.chatLog.addSystem('No base branches available for review.');\n svc.tui.requestRender();\n return;\n }\n const list = new SearchableSelectList(items, Math.min(10, items.length), searchableSelectListTheme, {\n searchPromptText: 'branch> ',\n });\n const defaultIndex = context.defaultBaseBranch\n ? items.findIndex((item) => item.value === context.defaultBaseBranch)\n : -1;\n if (defaultIndex >= 0) list.setSelectedIndex(defaultIndex);\n list.onSelect = (item) => {\n svc.closeOverlay();\n svc.tui.setFocus(svc.editor);\n svc.sendMessage(`/review --base ${quoteReviewArg(item.value)}`);\n };\n list.onCancel = () => {\n openReviewPresetSelector(svc, context);\n };\n svc.openOverlay(list);\n svc.chatLog.addSystem(theme.dim('Select a base branch to review'));\n svc.tui.requestRender();\n}\n\nfunction openReviewCommitSelector(svc: PickerServices, context: ReviewContext): void {\n const items = commitSelectItems(context);\n if (items.length === 0) {\n svc.closeOverlay();\n svc.tui.setFocus(svc.editor);\n svc.chatLog.addSystem('No commits available for review.');\n svc.tui.requestRender();\n return;\n }\n const list = new SearchableSelectList(items, Math.min(12, items.length), searchableSelectListTheme, {\n searchPromptText: 'commit> ',\n });\n list.onSelect = (item) => {\n svc.closeOverlay();\n svc.tui.setFocus(svc.editor);\n svc.sendMessage(`/review --commit ${item.value}`);\n };\n list.onCancel = () => {\n openReviewPresetSelector(svc, context);\n };\n svc.openOverlay(list);\n svc.chatLog.addSystem(theme.dim('Select a commit to review'));\n svc.tui.requestRender();\n}\n\nfunction openReviewPresetSelector(svc: PickerServices, context: ReviewContext): void {\n const items = reviewPresetItems(context);\n const list = new SearchableSelectList(items, Math.min(8, items.length), searchableSelectListTheme, {\n searchPromptText: 'review> ',\n });\n list.onSelect = (item) => {\n if (item.value === 'uncommitted') {\n svc.closeOverlay();\n svc.tui.setFocus(svc.editor);\n svc.sendMessage('/review --uncommitted');\n return;\n }\n if (item.value === 'custom') {\n svc.closeOverlay();\n svc.tui.setFocus(svc.editor);\n svc.setEditorText('/review --custom ');\n svc.tui.requestRender();\n return;\n }\n if (item.value === 'base') {\n openReviewBranchSelector(svc, context);\n return;\n }\n if (item.value === 'commit') {\n openReviewCommitSelector(svc, context);\n }\n };\n list.onCancel = () => {\n svc.closeOverlay();\n svc.tui.setFocus(svc.editor);\n svc.tui.requestRender();\n };\n\n svc.openOverlay(list);\n svc.chatLog.addSystem(theme.dim(formatReviewPickerOpenedHint(svc.keybindings)));\n svc.tui.requestRender();\n}\n\nexport async function openReviewLauncherOverlay(svc: PickerServices): Promise<void> {\n if (!svc.client.getReviewContext) {\n svc.chatLog.addSystem('Review picker is not available in this mode. Use /review --uncommitted, /review --base <branch>, or /review --commit <sha>.');\n svc.tui.requestRender();\n return;\n }\n let context: ReviewContext;\n try {\n context = await svc.client.getReviewContext(svc.state.currentSessionKey);\n } catch (err) {\n const errorMessage = err instanceof Error ? err.message : String(err);\n svc.chatLog.addSystem(`Review picker failed: ${errorMessage}`);\n svc.tui.requestRender();\n return;\n }\n openReviewPresetSelector(svc, context);\n}\n\n/** Ctrl+Shift+P — session picker with rename/delete. */\nexport async function openSessionPickerOverlay(svc: PickerServices): Promise<void> {\n const sessions = await svc.client.listSessions();\n if (sessions.length === 0) {\n svc.chatLog.addSystem('No sessions listed.');\n svc.tui.requestRender();\n return;\n }\n\n const selector = new SessionSelector(\n sessions,\n {\n onResume: (sessionKey) => {\n svc.closeOverlay();\n svc.tui.setFocus(svc.editor);\n resumeSession(svc, sessionKey);\n },\n onRename: async (sessionKey, name) => {\n const result = await svc.client.renameSession(sessionKey, name);\n return result.ok ? { ok: true } : { ok: false, error: 'Rename failed' };\n },\n onDelete: async (sessionKey) => {\n if (sessionKey === svc.state.currentSessionKey) {\n return { ok: false, error: 'Switch away before deleting the active session' };\n }\n const result = await svc.client.deleteSession(sessionKey);\n return result.ok ? { ok: true } : { ok: false, error: 'Delete failed' };\n },\n onCancel: () => {\n svc.closeOverlay();\n svc.tui.setFocus(svc.editor);\n svc.tui.requestRender();\n },\n requestRender: () => svc.tui.requestRender(),\n },\n svc.keybindings,\n sessions.find((s) => s.key === svc.state.currentSessionKey)?.cwd ?? process.cwd(),\n svc.state.currentSessionKey,\n );\n\n svc.openOverlay(selector);\n svc.chatLog.addSystem(theme.dim('Session picker'));\n svc.tui.requestRender();\n}\n\n/** Searchable session tree navigation overlay. */\nexport async function openSessionTreeOverlay(svc: PickerServices): Promise<void> {\n const sessions = await svc.client.listSessions();\n if (sessions.length === 0) {\n svc.chatLog.addSystem('No sessions listed.');\n svc.tui.requestRender();\n return;\n }\n\n const items = sessionTreeSelectItems(sessions, svc.state.currentSessionKey);\n const list = new SearchableSelectList(items, Math.min(14, items.length), searchableSelectListTheme);\n list.onSelect = (item) => {\n svc.closeOverlay();\n svc.tui.setFocus(svc.editor);\n resumeSession(svc, item.value);\n };\n list.onCancel = () => {\n svc.closeOverlay();\n svc.tui.setFocus(svc.editor);\n svc.tui.requestRender();\n };\n\n svc.openOverlay(list);\n svc.chatLog.addSystem(theme.dim(formatSessionTreeOpenedHint(svc.keybindings)));\n svc.tui.requestRender();\n}\n\n/** Searchable current-transcript tree overlay. */\nexport async function openTranscriptTreeOverlay(svc: PickerServices): Promise<void> {\n const entries = await svc.client.loadTranscriptTree(svc.state.currentSessionKey);\n const filterMode = svc.getTuiSettings().treeFilterMode;\n const visibleEntries = filterTuiTranscriptTreeEntries(entries, filterMode);\n if (visibleEntries.length === 0) {\n svc.chatLog.addSystem('No transcript entries found.');\n svc.tui.requestRender();\n return;\n }\n\n const byId = new Map(entries.map((entry) => [entry.id, entry]));\n const list = new TranscriptTreeSelectList(entries, filterMode, svc.keybindings, Math.min(16, visibleEntries.length));\n list.onSelect = (item) => {\n const entry = byId.get(item.value);\n svc.closeOverlay();\n svc.tui.setFocus(svc.editor);\n if (!entry) {\n svc.tui.requestRender();\n return;\n }\n const targetKey = defaultTranscriptForkKey(svc.state.currentSessionKey, entry.id);\n const sourceSessionKey = svc.state.currentSessionKey;\n svc.chatLog.addSystem(theme.dim(`Forking transcript at ${entry.id}...`));\n void svc.client\n .forkSessionAt(sourceSessionKey, targetKey, entry.id)\n .then((result) => {\n resumeSession(svc, result.sessionKey);\n svc.chatLog.addBranchSummary({\n sourceSessionKey,\n targetSessionKey: result.sessionKey,\n rowCount: result.rowCount,\n entryId: entry.id,\n });\n })\n .catch((err) => {\n const errorMessage = err instanceof Error ? err.message : String(err);\n svc.chatLog.addSystem(`Fork failed: ${errorMessage}`);\n svc.tui.requestRender();\n });\n svc.tui.requestRender();\n };\n list.onCancel = () => {\n svc.closeOverlay();\n svc.tui.setFocus(svc.editor);\n svc.tui.requestRender();\n };\n list.onFilterChange = (mode) => {\n svc.chatLog.addSystem(theme.dim(`Transcript tree filter: ${mode}`));\n svc.tui.requestRender();\n };\n list.onLabelSubmit = (entry, label) => {\n void svc.client\n .setTranscriptLabel(svc.state.currentSessionKey, entry.id, label)\n .then(() => {\n list.updateEntryLabel(entry.id, label);\n svc.chatLog.addSystem(\n theme.dim(label?.trim() ? `Labeled ${entry.id}: ${label.trim()}` : `Cleared label for ${entry.id}`),\n );\n svc.tui.requestRender();\n })\n .catch((err) => {\n const errorMessage = err instanceof Error ? err.message : String(err);\n svc.chatLog.addSystem(`Label failed: ${errorMessage}`);\n svc.tui.requestRender();\n });\n };\n\n svc.openOverlay(list);\n svc.chatLog.addSystem(theme.dim(formatTranscriptTreeFilterHint(svc.keybindings, filterMode)));\n svc.tui.requestRender();\n}\n\n/** Pi-style `/fork` overlay: select a previous user message and branch there. */\nexport async function openUserMessageForkOverlay(svc: PickerServices): Promise<void> {\n const entries = await svc.client.loadTranscriptTree(svc.state.currentSessionKey);\n const byId = new Map(entries.map((entry) => [entry.id, entry]));\n const items = userMessageForkSelectItems(entries);\n if (items.length === 0) {\n svc.chatLog.addSystem('No messages to fork from.');\n svc.tui.requestRender();\n return;\n }\n\n const list = new SearchableSelectList(items, Math.min(10, items.length), searchableSelectListTheme, {\n wrapNavigation: true,\n });\n list.setSelectedIndex(items.length - 1);\n list.onSelect = (item) => {\n svc.closeOverlay();\n svc.tui.setFocus(svc.editor);\n const entry = byId.get(item.value);\n const targetKey = defaultTranscriptForkKey(svc.state.currentSessionKey, item.value);\n const sourceSessionKey = svc.state.currentSessionKey;\n svc.chatLog.addSystem(theme.dim(`Forking from ${item.value}...`));\n void svc.client\n .forkSessionAt(sourceSessionKey, targetKey, item.value)\n .then((result) => {\n resumeSession(svc, result.sessionKey);\n if (entry?.contentText) {\n svc.setEditorText(entry.contentText);\n }\n svc.chatLog.addBranchSummary({\n sourceSessionKey,\n targetSessionKey: result.sessionKey,\n rowCount: result.rowCount,\n entryId: item.value,\n restoredText: entry?.contentText,\n });\n })\n .catch((err) => {\n const errorMessage = err instanceof Error ? err.message : String(err);\n svc.chatLog.addSystem(`Fork failed: ${errorMessage}`);\n svc.tui.requestRender();\n });\n svc.tui.requestRender();\n };\n list.onCancel = () => {\n svc.closeOverlay();\n svc.tui.setFocus(svc.editor);\n svc.tui.requestRender();\n };\n\n svc.openOverlay(list);\n svc.chatLog.addSystem(theme.dim(formatUserMessageForkOpenedHint(svc.keybindings)));\n svc.tui.requestRender();\n}\n\n/** `/scoped-models` — limit Ctrl+P model cycle set. */\nexport async function openScopedModelsOverlay(svc: PickerServices): Promise<void> {\n const catalog = await svc.client.listModels();\n svc.setModelChoices(catalog);\n if (catalog.length === 0) {\n svc.chatLog.addSystem('No models available.');\n svc.tui.requestRender();\n return;\n }\n\n const selector = new ScopedModelsSelector(\n catalog,\n svc.getScopedModelRefs(),\n {\n onSave: (refs) => {\n svc.setScopedModelRefs(refs);\n svc.refreshCycleModels();\n svc.closeOverlay();\n svc.tui.setFocus(svc.editor);\n svc.chatLog.addSystem(\n theme.dim(formatScopedModelsSavedHint({\n refs,\n total: catalog.length,\n keybindings: svc.keybindings,\n })),\n );\n svc.tui.requestRender();\n },\n onCancel: () => {\n svc.closeOverlay();\n svc.tui.setFocus(svc.editor);\n svc.tui.requestRender();\n },\n requestRender: () => svc.tui.requestRender(),\n },\n svc.keybindings,\n );\n\n svc.openOverlay(selector);\n svc.chatLog.addSystem(theme.dim(formatScopedModelsOpenedHint(svc.keybindings)));\n svc.tui.requestRender();\n}\n\n/** `/settings` — TUI preferences overlay. */\nexport function openSettingsOverlay(svc: PickerServices): void {\n const selector = new SettingsSelector(svc.getTuiSettings(), {\n onChange: (settings) => svc.applyTuiSettings(settings),\n onThemePreview: (themeId) => svc.previewTheme(themeId),\n onReloadKeybindings: () => svc.reloadKeybindings(),\n onCancel: () => {\n svc.previewTheme(svc.getTuiSettings().theme);\n svc.closeOverlay();\n svc.tui.setFocus(svc.editor);\n svc.tui.requestRender();\n },\n });\n\n svc.openOverlay(selector);\n svc.chatLog.addSystem(theme.dim(formatSettingsOpenedHint(svc.keybindings)));\n svc.tui.requestRender();\n}\n\n/** `/think` — select and persist the current session thinking level. */\nexport function openThinkingSelectorOverlay(svc: PickerServices): void {\n const current = normalizeThinkLevel(svc.state.sessionInfo.thinkingLevel) ?? 'medium';\n const levels = listThinkingLevels(\n svc.state.sessionInfo.modelProvider,\n svc.state.sessionInfo.model,\n ).map((level) => (level === 'on' ? 'low' : level)) as ThinkLevel[];\n const uniqueLevels = [...new Set(levels)];\n\n const selector = new ThinkingSelector(current, uniqueLevels, {\n onSelect: (level) => {\n void svc.setThinkingLevel(level).then(() => {\n svc.closeOverlay();\n svc.tui.setFocus(svc.editor);\n });\n },\n onCancel: () => {\n svc.closeOverlay();\n svc.tui.setFocus(svc.editor);\n svc.tui.requestRender();\n },\n }, svc.keybindings);\n\n svc.openOverlay(selector);\n svc.chatLog.addSystem(theme.dim(formatThinkingSelectorHint(svc.keybindings)));\n svc.tui.requestRender();\n}\n\nexport function openProjectTrustOverlay(svc: PickerServices): void {\n const cwd = process.cwd();\n const trustStore = svc.getProjectTrustStore();\n const currentStored = trustStore.getEntry(cwd);\n const sessionDecision = svc.getProjectTrustSessionDecision();\n const hasProjectResources = hasTrustRequiringProjectResources(cwd);\n const options = getProjectTrustOptions(cwd, { includeSessionOnly: true });\n const optionsByLabel = new Map(options.map((option) => [option.label, option]));\n const items: SelectItem[] = options.map((option) => ({\n value: option.label,\n label: option.label,\n description: option.savedPath ?? 'Current TUI session only',\n }));\n const list = new SearchableSelectList(items, Math.min(8, items.length), searchableSelectListTheme, {\n searchPromptText: 'trust: ',\n });\n\n list.onSelect = (item) => {\n const selected = optionsByLabel.get(item.value);\n if (!selected) return;\n if (selected.updates.length > 0) {\n trustStore.setMany(selected.updates);\n svc.setProjectTrustSessionDecision(null);\n } else {\n svc.setProjectTrustSessionDecision(selected.trusted);\n }\n svc.closeOverlay();\n svc.tui.setFocus(svc.editor);\n const scope = selected.savedPath ? `saved for ${selected.savedPath}` : 'this session only';\n svc.chatLog.addSystem(theme.dim(`Project trust: ${selected.trusted ? 'trusted' : 'not trusted'} (${scope})`));\n svc.tui.requestRender();\n };\n list.onCancel = () => {\n svc.closeOverlay();\n svc.tui.setFocus(svc.editor);\n svc.tui.requestRender();\n };\n\n svc.openOverlay(list);\n const storedLabel = currentStored\n ? `${currentStored.decision ? 'trusted' : 'not trusted'} from ${currentStored.path}`\n : 'not saved';\n const sessionLabel = sessionDecision === null ? 'none' : sessionDecision ? 'trusted' : 'not trusted';\n svc.chatLog.addSystem(\n theme.dim(\n [\n formatProjectTrustOpenedHint(svc.keybindings),\n `Project resources: ${hasProjectResources ? 'detected' : 'none detected'}`,\n `Stored: ${storedLabel}`,\n `Session: ${sessionLabel}`,\n ].join('\\n'),\n ),\n );\n svc.tui.requestRender();\n}\n"],"mappings":"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"}
@@ -12,6 +12,14 @@ export type PickerServices = {
12
12
  chatLog: {
13
13
  addSystem: (t: string) => void;
14
14
  addBranchSummary: (summary: TuiBranchSummary) => void;
15
+ getTimelineViewportState: () => {
16
+ mode: 'latest';
17
+ } | {
18
+ mode: 'history';
19
+ displayIndex: number;
20
+ };
21
+ jumpToDisplayIndex: (displayIndex: number) => boolean;
22
+ jumpToLatest: () => void;
15
23
  };
16
24
  client: TuiBackend;
17
25
  sendMessage: (text: string) => void;
@@ -24,6 +32,11 @@ export type PickerServices = {
24
32
  switchAgentSession?: (sessionKey: string, agentId: string) => void | Promise<void>;
25
33
  clearChatForSessionSwitch: () => void;
26
34
  loadSessionHistory: () => Promise<void>;
35
+ loadHistoryWindow: (opts: {
36
+ rowNumber: number;
37
+ before?: number;
38
+ after?: number;
39
+ }) => Promise<boolean>;
27
40
  setEditorText: (text: string) => void;
28
41
  setModelChoices: (models: TuiModelChoice[]) => void;
29
42
  getScopedModelRefs: () => string[] | null;
@@ -7,6 +7,8 @@ const STALE_WATCH_ACTIVITY = new Set([
7
7
  ]);
8
8
  function markRunEvent(state, phase, runId, event, source, nowMs = Date.now()) {
9
9
  const directStreamRunId = (source === "agent-response" || source === "agent-resume") && runId ? runId : state.runStatus.directStreamRunId;
10
+ const isStartingNewRun = phase !== "idle" && state.runStatus.phase === "idle" && (runId === null || state.runStatus.runId === null || state.runStatus.runId !== runId);
11
+ const startedAt = phase === "idle" ? null : isStartingNewRun || state.runStatus.startedAt == null ? nowMs : state.runStatus.startedAt;
10
12
  state.runStatus = {
11
13
  ...state.runStatus,
12
14
  phase,
@@ -14,6 +16,7 @@ function markRunEvent(state, phase, runId, event, source, nowMs = Date.now()) {
14
16
  directStreamRunId,
15
17
  source,
16
18
  lastEvent: event,
19
+ startedAt,
17
20
  lastActivityAt: nowMs,
18
21
  stalledAt: null
19
22
  };
@@ -27,6 +30,7 @@ function markRunSending(state, nowMs = Date.now()) {
27
30
  lastCompletedRunId: null,
28
31
  source: "unknown",
29
32
  lastEvent: "send",
33
+ startedAt: nowMs,
30
34
  lastActivityAt: nowMs,
31
35
  stalledAt: null
32
36
  };
@@ -37,6 +41,7 @@ function markRunAborting(state, runId, nowMs = Date.now()) {
37
41
  phase: "aborting",
38
42
  runId,
39
43
  lastEvent: "abort",
44
+ startedAt: state.runStatus.startedAt ?? nowMs,
40
45
  lastActivityAt: nowMs
41
46
  };
42
47
  }
@@ -46,6 +51,7 @@ function markRunIdleAfterAbort(state, nowMs = Date.now()) {
46
51
  phase: "idle",
47
52
  runId: null,
48
53
  lastEvent: "abort",
54
+ startedAt: null,
49
55
  lastActivityAt: nowMs,
50
56
  stalledAt: null
51
57
  };
@@ -62,6 +68,7 @@ function resetRunStatus(state) {
62
68
  directStreamRunId: null,
63
69
  lastCompletedRunId: null,
64
70
  lastEvent: null,
71
+ startedAt: null,
65
72
  stalledAt: null
66
73
  };
67
74
  }
@@ -79,6 +86,7 @@ function markActiveRunStalled(state, nowMs) {
79
86
  ...state.runStatus,
80
87
  phase: "stalled",
81
88
  runId: state.activeRunId,
89
+ startedAt: state.runStatus.startedAt ?? state.runStatus.lastActivityAt ?? nowMs,
82
90
  stalledAt: nowMs
83
91
  };
84
92
  return true;
@@ -88,6 +96,7 @@ function markRunRecovering(state, nowMs) {
88
96
  ...state.runStatus,
89
97
  phase: "recovering",
90
98
  runId: state.activeRunId,
99
+ startedAt: state.runStatus.startedAt ?? state.runStatus.lastActivityAt ?? nowMs,
91
100
  recoveredAt: nowMs
92
101
  };
93
102
  }
@@ -97,6 +106,7 @@ function markRunRecoveryComplete(state, nowMs) {
97
106
  ...state.runStatus,
98
107
  phase: "stalled",
99
108
  runId: state.activeRunId,
109
+ startedAt: state.runStatus.startedAt ?? state.runStatus.lastActivityAt ?? nowMs,
100
110
  recoveredAt: nowMs
101
111
  };
102
112
  return;
@@ -105,6 +115,7 @@ function markRunRecoveryComplete(state, nowMs) {
105
115
  ...state.runStatus,
106
116
  phase: "idle",
107
117
  runId: null,
118
+ startedAt: null,
108
119
  recoveredAt: nowMs
109
120
  };
110
121
  }
@@ -1 +1 @@
1
- {"version":3,"file":"tui-run-state.js","names":[],"sources":["../../../src/tui/tui-run-state.ts"],"sourcesContent":["import type { ActivityStatus, TuiEventSource, TuiRunPhase, TuiState } from './tui-types.js';\n\nconst STALE_WATCH_ACTIVITY = new Set<ActivityStatus>(['sending', 'waiting', 'streaming', 'running']);\n\nexport function markRunEvent(\n state: TuiState,\n phase: TuiRunPhase,\n runId: string | null,\n event: string,\n source: TuiEventSource,\n nowMs = Date.now(),\n): void {\n const directStreamRunId =\n (source === 'agent-response' || source === 'agent-resume') && runId\n ? runId\n : state.runStatus.directStreamRunId;\n state.runStatus = {\n ...state.runStatus,\n phase,\n runId,\n directStreamRunId,\n source,\n lastEvent: event,\n lastActivityAt: nowMs,\n stalledAt: null,\n };\n}\n\nexport function markRunSending(state: TuiState, nowMs = Date.now()): void {\n state.runStatus = {\n ...state.runStatus,\n phase: 'sending',\n runId: null,\n directStreamRunId: null,\n lastCompletedRunId: null,\n source: 'unknown',\n lastEvent: 'send',\n lastActivityAt: nowMs,\n stalledAt: null,\n };\n}\n\nexport function markRunAborting(state: TuiState, runId: string, nowMs = Date.now()): void {\n state.runStatus = {\n ...state.runStatus,\n phase: 'aborting',\n runId,\n lastEvent: 'abort',\n lastActivityAt: nowMs,\n };\n}\n\nexport function markRunIdleAfterAbort(state: TuiState, nowMs = Date.now()): void {\n state.runStatus = {\n ...state.runStatus,\n phase: 'idle',\n runId: null,\n lastEvent: 'abort',\n lastActivityAt: nowMs,\n stalledAt: null,\n };\n}\n\nexport function markRunIdleAfterCompletion(\n state: TuiState,\n completedRunId: string,\n event: string,\n source: TuiEventSource,\n nowMs = Date.now(),\n): void {\n markRunEvent(state, 'idle', null, event, source, nowMs);\n state.runStatus.lastCompletedRunId = completedRunId;\n}\n\nexport function resetRunStatus(state: TuiState): void {\n state.runStatus = {\n ...state.runStatus,\n phase: 'idle',\n runId: null,\n directStreamRunId: null,\n lastCompletedRunId: null,\n lastEvent: null,\n stalledAt: null,\n };\n}\n\nexport function isActiveRunStreamStale(\n state: TuiState,\n nowMs: number,\n staleAfterMs: number,\n): boolean {\n if (!state.activeRunId) return false;\n if (!STALE_WATCH_ACTIVITY.has(state.activityStatus)) return false;\n if (state.runStatus.phase === 'stalled' || state.runStatus.phase === 'recovering') return false;\n if (state.runStatus.phase === 'aborting') return false;\n const lastActivityAt = state.runStatus.lastActivityAt ?? nowMs;\n return nowMs - lastActivityAt >= staleAfterMs;\n}\n\nexport function markActiveRunStalled(state: TuiState, nowMs: number): boolean {\n if (!state.activeRunId) return false;\n if (state.runStatus.phase === 'stalled' || state.runStatus.phase === 'recovering') {\n return false;\n }\n state.runStatus = {\n ...state.runStatus,\n phase: 'stalled',\n runId: state.activeRunId,\n stalledAt: nowMs,\n };\n return true;\n}\n\nexport function markRunRecovering(state: TuiState, nowMs: number): void {\n state.runStatus = {\n ...state.runStatus,\n phase: 'recovering',\n runId: state.activeRunId,\n recoveredAt: nowMs,\n };\n}\n\nexport function markRunRecoveryComplete(state: TuiState, nowMs: number): void {\n if (state.activeRunId) {\n state.runStatus = {\n ...state.runStatus,\n phase: 'stalled',\n runId: state.activeRunId,\n recoveredAt: nowMs,\n };\n return;\n }\n state.runStatus = {\n ...state.runStatus,\n phase: 'idle',\n runId: null,\n recoveredAt: nowMs,\n };\n}\n"],"mappings":";AAEA,MAAM,uBAAuB,IAAI,IAAoB;CAAC;CAAW;CAAW;CAAa;CAAU,CAAC;AAEpG,SAAgB,aACd,OACA,OACA,OACA,OACA,QACA,QAAQ,KAAK,KAAK,EACZ;CACN,MAAM,qBACH,WAAW,oBAAoB,WAAW,mBAAmB,QAC1D,QACA,MAAM,UAAU;AACtB,OAAM,YAAY;EAChB,GAAG,MAAM;EACT;EACA;EACA;EACA;EACA,WAAW;EACX,gBAAgB;EAChB,WAAW;EACZ;;AAGH,SAAgB,eAAe,OAAiB,QAAQ,KAAK,KAAK,EAAQ;AACxE,OAAM,YAAY;EAChB,GAAG,MAAM;EACT,OAAO;EACP,OAAO;EACP,mBAAmB;EACnB,oBAAoB;EACpB,QAAQ;EACR,WAAW;EACX,gBAAgB;EAChB,WAAW;EACZ;;AAGH,SAAgB,gBAAgB,OAAiB,OAAe,QAAQ,KAAK,KAAK,EAAQ;AACxF,OAAM,YAAY;EAChB,GAAG,MAAM;EACT,OAAO;EACP;EACA,WAAW;EACX,gBAAgB;EACjB;;AAGH,SAAgB,sBAAsB,OAAiB,QAAQ,KAAK,KAAK,EAAQ;AAC/E,OAAM,YAAY;EAChB,GAAG,MAAM;EACT,OAAO;EACP,OAAO;EACP,WAAW;EACX,gBAAgB;EAChB,WAAW;EACZ;;AAGH,SAAgB,2BACd,OACA,gBACA,OACA,QACA,QAAQ,KAAK,KAAK,EACZ;AACN,cAAa,OAAO,QAAQ,MAAM,OAAO,QAAQ,MAAM;AACvD,OAAM,UAAU,qBAAqB;;AAGvC,SAAgB,eAAe,OAAuB;AACpD,OAAM,YAAY;EAChB,GAAG,MAAM;EACT,OAAO;EACP,OAAO;EACP,mBAAmB;EACnB,oBAAoB;EACpB,WAAW;EACX,WAAW;EACZ;;AAGH,SAAgB,uBACd,OACA,OACA,cACS;AACT,KAAI,CAAC,MAAM,YAAa,QAAO;AAC/B,KAAI,CAAC,qBAAqB,IAAI,MAAM,eAAe,CAAE,QAAO;AAC5D,KAAI,MAAM,UAAU,UAAU,aAAa,MAAM,UAAU,UAAU,aAAc,QAAO;AAC1F,KAAI,MAAM,UAAU,UAAU,WAAY,QAAO;AAEjD,QAAO,SADgB,MAAM,UAAU,kBAAkB,UACxB;;AAGnC,SAAgB,qBAAqB,OAAiB,OAAwB;AAC5E,KAAI,CAAC,MAAM,YAAa,QAAO;AAC/B,KAAI,MAAM,UAAU,UAAU,aAAa,MAAM,UAAU,UAAU,aACnE,QAAO;AAET,OAAM,YAAY;EAChB,GAAG,MAAM;EACT,OAAO;EACP,OAAO,MAAM;EACb,WAAW;EACZ;AACD,QAAO;;AAGT,SAAgB,kBAAkB,OAAiB,OAAqB;AACtE,OAAM,YAAY;EAChB,GAAG,MAAM;EACT,OAAO;EACP,OAAO,MAAM;EACb,aAAa;EACd;;AAGH,SAAgB,wBAAwB,OAAiB,OAAqB;AAC5E,KAAI,MAAM,aAAa;AACrB,QAAM,YAAY;GAChB,GAAG,MAAM;GACT,OAAO;GACP,OAAO,MAAM;GACb,aAAa;GACd;AACD;;AAEF,OAAM,YAAY;EAChB,GAAG,MAAM;EACT,OAAO;EACP,OAAO;EACP,aAAa;EACd"}
1
+ {"version":3,"file":"tui-run-state.js","names":[],"sources":["../../../src/tui/tui-run-state.ts"],"sourcesContent":["import type { ActivityStatus, TuiEventSource, TuiRunPhase, TuiState } from './tui-types.js';\n\nconst STALE_WATCH_ACTIVITY = new Set<ActivityStatus>(['sending', 'waiting', 'streaming', 'running']);\n\nexport function markRunEvent(\n state: TuiState,\n phase: TuiRunPhase,\n runId: string | null,\n event: string,\n source: TuiEventSource,\n nowMs = Date.now(),\n): void {\n const directStreamRunId =\n (source === 'agent-response' || source === 'agent-resume') && runId\n ? runId\n : state.runStatus.directStreamRunId;\n const isStartingNewRun =\n phase !== 'idle' &&\n state.runStatus.phase === 'idle' &&\n (runId === null || state.runStatus.runId === null || state.runStatus.runId !== runId);\n const startedAt =\n phase === 'idle'\n ? null\n : isStartingNewRun || state.runStatus.startedAt == null\n ? nowMs\n : state.runStatus.startedAt;\n state.runStatus = {\n ...state.runStatus,\n phase,\n runId,\n directStreamRunId,\n source,\n lastEvent: event,\n startedAt,\n lastActivityAt: nowMs,\n stalledAt: null,\n };\n}\n\nexport function markRunSending(state: TuiState, nowMs = Date.now()): void {\n state.runStatus = {\n ...state.runStatus,\n phase: 'sending',\n runId: null,\n directStreamRunId: null,\n lastCompletedRunId: null,\n source: 'unknown',\n lastEvent: 'send',\n startedAt: nowMs,\n lastActivityAt: nowMs,\n stalledAt: null,\n };\n}\n\nexport function markRunAborting(state: TuiState, runId: string, nowMs = Date.now()): void {\n state.runStatus = {\n ...state.runStatus,\n phase: 'aborting',\n runId,\n lastEvent: 'abort',\n startedAt: state.runStatus.startedAt ?? nowMs,\n lastActivityAt: nowMs,\n };\n}\n\nexport function markRunIdleAfterAbort(state: TuiState, nowMs = Date.now()): void {\n state.runStatus = {\n ...state.runStatus,\n phase: 'idle',\n runId: null,\n lastEvent: 'abort',\n startedAt: null,\n lastActivityAt: nowMs,\n stalledAt: null,\n };\n}\n\nexport function markRunIdleAfterCompletion(\n state: TuiState,\n completedRunId: string,\n event: string,\n source: TuiEventSource,\n nowMs = Date.now(),\n): void {\n markRunEvent(state, 'idle', null, event, source, nowMs);\n state.runStatus.lastCompletedRunId = completedRunId;\n}\n\nexport function resetRunStatus(state: TuiState): void {\n state.runStatus = {\n ...state.runStatus,\n phase: 'idle',\n runId: null,\n directStreamRunId: null,\n lastCompletedRunId: null,\n lastEvent: null,\n startedAt: null,\n stalledAt: null,\n };\n}\n\nexport function isActiveRunStreamStale(\n state: TuiState,\n nowMs: number,\n staleAfterMs: number,\n): boolean {\n if (!state.activeRunId) return false;\n if (!STALE_WATCH_ACTIVITY.has(state.activityStatus)) return false;\n if (state.runStatus.phase === 'stalled' || state.runStatus.phase === 'recovering') return false;\n if (state.runStatus.phase === 'aborting') return false;\n const lastActivityAt = state.runStatus.lastActivityAt ?? nowMs;\n return nowMs - lastActivityAt >= staleAfterMs;\n}\n\nexport function markActiveRunStalled(state: TuiState, nowMs: number): boolean {\n if (!state.activeRunId) return false;\n if (state.runStatus.phase === 'stalled' || state.runStatus.phase === 'recovering') {\n return false;\n }\n state.runStatus = {\n ...state.runStatus,\n phase: 'stalled',\n runId: state.activeRunId,\n startedAt: state.runStatus.startedAt ?? state.runStatus.lastActivityAt ?? nowMs,\n stalledAt: nowMs,\n };\n return true;\n}\n\nexport function markRunRecovering(state: TuiState, nowMs: number): void {\n state.runStatus = {\n ...state.runStatus,\n phase: 'recovering',\n runId: state.activeRunId,\n startedAt: state.runStatus.startedAt ?? state.runStatus.lastActivityAt ?? nowMs,\n recoveredAt: nowMs,\n };\n}\n\nexport function markRunRecoveryComplete(state: TuiState, nowMs: number): void {\n if (state.activeRunId) {\n state.runStatus = {\n ...state.runStatus,\n phase: 'stalled',\n runId: state.activeRunId,\n startedAt: state.runStatus.startedAt ?? state.runStatus.lastActivityAt ?? nowMs,\n recoveredAt: nowMs,\n };\n return;\n }\n state.runStatus = {\n ...state.runStatus,\n phase: 'idle',\n runId: null,\n startedAt: null,\n recoveredAt: nowMs,\n };\n}\n"],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { TuiState } from './tui-types.js';
2
+ export declare function formatRunDuration(elapsedMs: number): string;
3
+ export declare function formatActiveRunStatus(state: TuiState, nowMs?: number): string | null;
@@ -0,0 +1,33 @@
1
+ //#region src/tui/tui-run-status-format.ts
2
+ const STALE_UPDATE_HINT_MS = 3e4;
3
+ function formatRunDuration(elapsedMs) {
4
+ const totalSeconds = Math.max(0, Math.floor(elapsedMs / 1e3));
5
+ if (totalSeconds < 60) return `${totalSeconds}s`;
6
+ return `${Math.floor(totalSeconds / 60)}m ${totalSeconds % 60}s`;
7
+ }
8
+ function activeRunLabel(state) {
9
+ if (state.runStatus.phase === "aborting" || state.activityStatus === "aborting") return "Stopping";
10
+ if (state.runStatus.phase === "recovering" || state.activityStatus === "recovering") return "Reconnecting output";
11
+ if (state.runStatus.phase === "stalled" || state.activityStatus === "stalled") return "Output stale";
12
+ const message = state.progressMessage?.trim();
13
+ if (message) return message;
14
+ if (state.runStatus.phase === "tool") return "Running tool";
15
+ if (state.activityStatus === "sending") return "Sending";
16
+ return "Working";
17
+ }
18
+ function formatActiveRunStatus(state, nowMs = Date.now()) {
19
+ if (!state.activeRunId) return null;
20
+ const startedAt = state.runStatus.startedAt ?? state.runStatus.lastActivityAt;
21
+ const details = [];
22
+ if (startedAt != null) details.push(formatRunDuration(nowMs - startedAt));
23
+ const lastActivityAt = state.runStatus.lastActivityAt;
24
+ const isStalePhase = state.runStatus.phase === "stalled" || state.runStatus.phase === "recovering" || state.activityStatus === "stalled" || state.activityStatus === "recovering";
25
+ if (lastActivityAt != null && (isStalePhase || nowMs - lastActivityAt >= STALE_UPDATE_HINT_MS)) details.push(`last update ${formatRunDuration(nowMs - lastActivityAt)} ago`);
26
+ if (state.runStatus.phase !== "aborting" && state.activityStatus !== "aborting") details.push("esc to interrupt");
27
+ const label = activeRunLabel(state);
28
+ return details.length > 0 ? `${label} (${details.join(" • ")})` : label;
29
+ }
30
+ //#endregion
31
+ export { formatActiveRunStatus, formatRunDuration };
32
+
33
+ //# sourceMappingURL=tui-run-status-format.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tui-run-status-format.js","names":[],"sources":["../../../src/tui/tui-run-status-format.ts"],"sourcesContent":["import type { TuiState } from './tui-types.js';\n\nconst STALE_UPDATE_HINT_MS = 30_000;\n\nexport function formatRunDuration(elapsedMs: number): string {\n const totalSeconds = Math.max(0, Math.floor(elapsedMs / 1000));\n if (totalSeconds < 60) return `${totalSeconds}s`;\n const minutes = Math.floor(totalSeconds / 60);\n const seconds = totalSeconds % 60;\n return `${minutes}m ${seconds}s`;\n}\n\nfunction activeRunLabel(state: TuiState): string {\n if (state.runStatus.phase === 'aborting' || state.activityStatus === 'aborting') {\n return 'Stopping';\n }\n if (state.runStatus.phase === 'recovering' || state.activityStatus === 'recovering') {\n return 'Reconnecting output';\n }\n if (state.runStatus.phase === 'stalled' || state.activityStatus === 'stalled') {\n return 'Output stale';\n }\n const message = state.progressMessage?.trim();\n if (message) return message;\n if (state.runStatus.phase === 'tool') return 'Running tool';\n if (state.activityStatus === 'sending') return 'Sending';\n return 'Working';\n}\n\nexport function formatActiveRunStatus(state: TuiState, nowMs = Date.now()): string | null {\n if (!state.activeRunId) return null;\n\n const startedAt = state.runStatus.startedAt ?? state.runStatus.lastActivityAt;\n const details: string[] = [];\n if (startedAt != null) {\n details.push(formatRunDuration(nowMs - startedAt));\n }\n\n const lastActivityAt = state.runStatus.lastActivityAt;\n const isStalePhase =\n state.runStatus.phase === 'stalled' ||\n state.runStatus.phase === 'recovering' ||\n state.activityStatus === 'stalled' ||\n state.activityStatus === 'recovering';\n if (\n lastActivityAt != null &&\n (isStalePhase || nowMs - lastActivityAt >= STALE_UPDATE_HINT_MS)\n ) {\n details.push(`last update ${formatRunDuration(nowMs - lastActivityAt)} ago`);\n }\n\n if (state.runStatus.phase !== 'aborting' && state.activityStatus !== 'aborting') {\n details.push('esc to interrupt');\n }\n\n const label = activeRunLabel(state);\n return details.length > 0 ? `${label} (${details.join(' • ')})` : label;\n}\n"],"mappings":";AAEA,MAAM,uBAAuB;AAE7B,SAAgB,kBAAkB,WAA2B;CAC3D,MAAM,eAAe,KAAK,IAAI,GAAG,KAAK,MAAM,YAAY,IAAK,CAAC;AAC9D,KAAI,eAAe,GAAI,QAAO,GAAG,aAAa;AAG9C,QAAO,GAFS,KAAK,MAAM,eAAe,GAEzB,CAAC,IADF,eAAe,GACD;;AAGhC,SAAS,eAAe,OAAyB;AAC/C,KAAI,MAAM,UAAU,UAAU,cAAc,MAAM,mBAAmB,WACnE,QAAO;AAET,KAAI,MAAM,UAAU,UAAU,gBAAgB,MAAM,mBAAmB,aACrE,QAAO;AAET,KAAI,MAAM,UAAU,UAAU,aAAa,MAAM,mBAAmB,UAClE,QAAO;CAET,MAAM,UAAU,MAAM,iBAAiB,MAAM;AAC7C,KAAI,QAAS,QAAO;AACpB,KAAI,MAAM,UAAU,UAAU,OAAQ,QAAO;AAC7C,KAAI,MAAM,mBAAmB,UAAW,QAAO;AAC/C,QAAO;;AAGT,SAAgB,sBAAsB,OAAiB,QAAQ,KAAK,KAAK,EAAiB;AACxF,KAAI,CAAC,MAAM,YAAa,QAAO;CAE/B,MAAM,YAAY,MAAM,UAAU,aAAa,MAAM,UAAU;CAC/D,MAAM,UAAoB,EAAE;AAC5B,KAAI,aAAa,KACf,SAAQ,KAAK,kBAAkB,QAAQ,UAAU,CAAC;CAGpD,MAAM,iBAAiB,MAAM,UAAU;CACvC,MAAM,eACJ,MAAM,UAAU,UAAU,aAC1B,MAAM,UAAU,UAAU,gBAC1B,MAAM,mBAAmB,aACzB,MAAM,mBAAmB;AAC3B,KACE,kBAAkB,SACjB,gBAAgB,QAAQ,kBAAkB,sBAE3C,SAAQ,KAAK,eAAe,kBAAkB,QAAQ,eAAe,CAAC,MAAM;AAG9E,KAAI,MAAM,UAAU,UAAU,cAAc,MAAM,mBAAmB,WACnE,SAAQ,KAAK,mBAAmB;CAGlC,MAAM,QAAQ,eAAe,MAAM;AACnC,QAAO,QAAQ,SAAS,IAAI,GAAG,MAAM,IAAI,QAAQ,KAAK,MAAM,CAAC,KAAK"}
@@ -21,6 +21,11 @@ export declare function createSessionActions(context: SessionActionsContext): {
21
21
  loadHistory: (opts?: {
22
22
  merge?: boolean;
23
23
  }) => Promise<void>;
24
+ loadHistoryWindow: (opts: {
25
+ rowNumber: number;
26
+ before?: number;
27
+ after?: number;
28
+ }) => Promise<boolean>;
24
29
  setSession: (rawKey: string) => Promise<void>;
25
30
  abortActive: (opts?: {
26
31
  clearUi?: boolean;
@@ -55,6 +55,29 @@ function createSessionActions(context) {
55
55
  tui.requestRender();
56
56
  }
57
57
  };
58
+ const loadHistoryWindow = async (opts) => {
59
+ if (!client.loadHistoryWindow) return false;
60
+ try {
61
+ const { messages } = await client.loadHistoryWindow({
62
+ sessionKey: state.currentSessionKey,
63
+ rowNumber: opts.rowNumber,
64
+ before: opts.before,
65
+ after: opts.after
66
+ });
67
+ if (messages.length === 0) return false;
68
+ sessionSnapshot?.replaceFromHistory(messages);
69
+ chatLog.clearAll();
70
+ appendHistoryToChatLog(chatLog, messages, state.toolsExpanded, state.showThinking);
71
+ lastHistoryKeys = messages.map(historyMessageKey);
72
+ state.historyLoaded = true;
73
+ return true;
74
+ } catch {
75
+ return false;
76
+ } finally {
77
+ await refreshSessionInfo();
78
+ tui.requestRender();
79
+ }
80
+ };
58
81
  const setSession = async (rawKey) => {
59
82
  const nextKey = resolveSessionKey(rawKey);
60
83
  updateAgentFromSessionKey(nextKey);
@@ -88,6 +111,7 @@ function createSessionActions(context) {
88
111
  return {
89
112
  refreshSessionInfo,
90
113
  loadHistory,
114
+ loadHistoryWindow,
91
115
  setSession,
92
116
  abortActive,
93
117
  resetCurrentSession,
@@ -1 +1 @@
1
- {"version":3,"file":"tui-session-actions.js","names":[],"sources":["../../../src/tui/tui-session-actions.ts"],"sourcesContent":["import type { TUI } from '@earendil-works/pi-tui';\n\nimport { parseAgentSessionKey } from '../routing/agent-session-key.js';\nimport {\n appendHistoryToChatLog,\n historyKeysHaveAppendOnlyPrefix,\n historyMessageKey,\n} from './chat-history.js';\nimport type { ChatLog } from './components/chat-log.js';\nimport { clearSeenStreamEvents } from './tui-agent-events.js';\nimport type { TuiBackend } from './tui-backend.js';\nimport type { TuiState } from './tui-types.js';\nimport type { TuiSessionSnapshot } from './tui-session-snapshot.js';\nimport {\n markRunAborting,\n markRunIdleAfterAbort,\n resetRunStatus,\n} from './tui-run-state.js';\n\nexport type SessionActionsContext = {\n client: TuiBackend;\n chatLog: ChatLog;\n tui: TUI;\n state: TuiState;\n resolveSessionKey: (raw?: string) => string;\n updateHeader: () => void;\n updateFooter: () => void;\n setActivityStatus: (status: string) => void;\n historyLimit?: number;\n onAgentIdChange?: (agentId: string) => void;\n sessionSnapshot?: TuiSessionSnapshot;\n};\n\nexport function createSessionActions(context: SessionActionsContext) {\n const {\n client,\n chatLog,\n tui,\n state,\n resolveSessionKey,\n updateHeader,\n updateFooter,\n setActivityStatus,\n historyLimit = 200,\n onAgentIdChange,\n sessionSnapshot,\n } = context;\n\n let refreshSessionInfoPromise: Promise<void> = Promise.resolve();\n let lastHistoryKeys: string[] = [];\n\n const updateAgentFromSessionKey = (key: string) => {\n const parsed = parseAgentSessionKey(key);\n if (!parsed?.agentId) {\n return;\n }\n onAgentIdChange?.(parsed.agentId);\n };\n\n const runRefreshSessionInfo = async () => {\n try {\n state.sessionInfo = await client.getSessionInfo(state.currentSessionKey);\n updateFooter();\n tui.requestRender();\n } catch {\n // ignore\n }\n };\n\n const refreshSessionInfo = async () => {\n refreshSessionInfoPromise = refreshSessionInfoPromise.then(\n runRefreshSessionInfo,\n runRefreshSessionInfo,\n );\n await refreshSessionInfoPromise;\n };\n\n const clearChatForSessionSwitch = () => {\n chatLog.clearAll();\n clearSeenStreamEvents();\n sessionSnapshot?.clear();\n lastHistoryKeys = [];\n resetRunStatus(state);\n state.historyLoaded = false;\n state.messageFollowUpQueue.length = 0;\n state.steeringQueue.length = 0;\n };\n\n const loadHistory = async (opts?: { merge?: boolean }) => {\n try {\n const { messages } = await client.loadHistory({\n sessionKey: state.currentSessionKey,\n limit: historyLimit,\n });\n sessionSnapshot?.replaceFromHistory(messages);\n const nextKeys = messages.map(historyMessageKey);\n const canAppend =\n opts?.merge === true &&\n historyKeysHaveAppendOnlyPrefix(lastHistoryKeys, nextKeys);\n if (canAppend) {\n appendHistoryToChatLog(\n chatLog,\n messages.slice(lastHistoryKeys.length),\n state.toolsExpanded,\n state.showThinking,\n { startIndex: lastHistoryKeys.length },\n );\n } else {\n chatLog.clearAll();\n appendHistoryToChatLog(chatLog, messages, state.toolsExpanded, state.showThinking);\n }\n lastHistoryKeys = nextKeys;\n } catch {\n // ignore; footer already hints on disconnect\n } finally {\n state.historyLoaded = true;\n await refreshSessionInfo();\n tui.requestRender();\n }\n };\n\n const setSession = async (rawKey: string) => {\n const nextKey = resolveSessionKey(rawKey);\n updateAgentFromSessionKey(nextKey);\n state.currentSessionKey = nextKey;\n state.activeRunId = null;\n setActivityStatus('idle');\n clearChatForSessionSwitch();\n updateHeader();\n updateFooter();\n await loadHistory();\n };\n\n const abortActive = async (opts?: { clearUi?: boolean }) => {\n if (!state.activeRunId) {\n return;\n }\n const runId = state.activeRunId;\n markRunAborting(state, runId);\n state.activeRunId = null;\n if (opts?.clearUi !== false) {\n chatLog.dropAssistant(runId);\n }\n setActivityStatus('idle');\n markRunIdleAfterAbort(state);\n tui.requestRender();\n await client.abortChat({ sessionKey: state.currentSessionKey, runId }).catch(() => {});\n };\n\n const resetCurrentSession = async () => {\n await client.resetSession(state.currentSessionKey);\n clearChatForSessionSwitch();\n await loadHistory();\n };\n\n return {\n refreshSessionInfo,\n loadHistory,\n setSession,\n abortActive,\n resetCurrentSession,\n clearChatForSessionSwitch,\n };\n}\n"],"mappings":";;;;;;wBAEuE;AA+BvE,SAAgB,qBAAqB,SAAgC;CACnE,MAAM,EACJ,QACA,SACA,KACA,OACA,mBACA,cACA,cACA,mBACA,eAAe,KACf,iBACA,oBACE;CAEJ,IAAI,4BAA2C,QAAQ,SAAS;CAChE,IAAI,kBAA4B,EAAE;CAElC,MAAM,6BAA6B,QAAgB;EACjD,MAAM,SAAS,qBAAqB,IAAI;AACxC,MAAI,CAAC,QAAQ,QACX;AAEF,oBAAkB,OAAO,QAAQ;;CAGnC,MAAM,wBAAwB,YAAY;AACxC,MAAI;AACF,SAAM,cAAc,MAAM,OAAO,eAAe,MAAM,kBAAkB;AACxE,iBAAc;AACd,OAAI,eAAe;UACb;;CAKV,MAAM,qBAAqB,YAAY;AACrC,8BAA4B,0BAA0B,KACpD,uBACA,sBACD;AACD,QAAM;;CAGR,MAAM,kCAAkC;AACtC,UAAQ,UAAU;AAClB,yBAAuB;AACvB,mBAAiB,OAAO;AACxB,oBAAkB,EAAE;AACpB,iBAAe,MAAM;AACrB,QAAM,gBAAgB;AACtB,QAAM,qBAAqB,SAAS;AACpC,QAAM,cAAc,SAAS;;CAG/B,MAAM,cAAc,OAAO,SAA+B;AACxD,MAAI;GACF,MAAM,EAAE,aAAa,MAAM,OAAO,YAAY;IAC5C,YAAY,MAAM;IAClB,OAAO;IACR,CAAC;AACF,oBAAiB,mBAAmB,SAAS;GAC7C,MAAM,WAAW,SAAS,IAAI,kBAAkB;AAIhD,OAFE,MAAM,UAAU,QAChB,gCAAgC,iBAAiB,SAAS,CAE1D,wBACE,SACA,SAAS,MAAM,gBAAgB,OAAO,EACtC,MAAM,eACN,MAAM,cACN,EAAE,YAAY,gBAAgB,QAAQ,CACvC;QACI;AACL,YAAQ,UAAU;AAClB,2BAAuB,SAAS,UAAU,MAAM,eAAe,MAAM,aAAa;;AAEpF,qBAAkB;UACZ,WAEE;AACR,SAAM,gBAAgB;AACtB,SAAM,oBAAoB;AAC1B,OAAI,eAAe;;;CAIvB,MAAM,aAAa,OAAO,WAAmB;EAC3C,MAAM,UAAU,kBAAkB,OAAO;AACzC,4BAA0B,QAAQ;AAClC,QAAM,oBAAoB;AAC1B,QAAM,cAAc;AACpB,oBAAkB,OAAO;AACzB,6BAA2B;AAC3B,gBAAc;AACd,gBAAc;AACd,QAAM,aAAa;;CAGrB,MAAM,cAAc,OAAO,SAAiC;AAC1D,MAAI,CAAC,MAAM,YACT;EAEF,MAAM,QAAQ,MAAM;AACpB,kBAAgB,OAAO,MAAM;AAC7B,QAAM,cAAc;AACpB,MAAI,MAAM,YAAY,MACpB,SAAQ,cAAc,MAAM;AAE9B,oBAAkB,OAAO;AACzB,wBAAsB,MAAM;AAC5B,MAAI,eAAe;AACnB,QAAM,OAAO,UAAU;GAAE,YAAY,MAAM;GAAmB;GAAO,CAAC,CAAC,YAAY,GAAG;;CAGxF,MAAM,sBAAsB,YAAY;AACtC,QAAM,OAAO,aAAa,MAAM,kBAAkB;AAClD,6BAA2B;AAC3B,QAAM,aAAa;;AAGrB,QAAO;EACL;EACA;EACA;EACA;EACA;EACA;EACD"}
1
+ {"version":3,"file":"tui-session-actions.js","names":[],"sources":["../../../src/tui/tui-session-actions.ts"],"sourcesContent":["import type { TUI } from '@earendil-works/pi-tui';\n\nimport { parseAgentSessionKey } from '../routing/agent-session-key.js';\nimport {\n appendHistoryToChatLog,\n historyKeysHaveAppendOnlyPrefix,\n historyMessageKey,\n} from './chat-history.js';\nimport type { ChatLog } from './components/chat-log.js';\nimport { clearSeenStreamEvents } from './tui-agent-events.js';\nimport type { TuiBackend } from './tui-backend.js';\nimport type { TuiState } from './tui-types.js';\nimport type { TuiSessionSnapshot } from './tui-session-snapshot.js';\nimport {\n markRunAborting,\n markRunIdleAfterAbort,\n resetRunStatus,\n} from './tui-run-state.js';\n\nexport type SessionActionsContext = {\n client: TuiBackend;\n chatLog: ChatLog;\n tui: TUI;\n state: TuiState;\n resolveSessionKey: (raw?: string) => string;\n updateHeader: () => void;\n updateFooter: () => void;\n setActivityStatus: (status: string) => void;\n historyLimit?: number;\n onAgentIdChange?: (agentId: string) => void;\n sessionSnapshot?: TuiSessionSnapshot;\n};\n\nexport function createSessionActions(context: SessionActionsContext) {\n const {\n client,\n chatLog,\n tui,\n state,\n resolveSessionKey,\n updateHeader,\n updateFooter,\n setActivityStatus,\n historyLimit = 200,\n onAgentIdChange,\n sessionSnapshot,\n } = context;\n\n let refreshSessionInfoPromise: Promise<void> = Promise.resolve();\n let lastHistoryKeys: string[] = [];\n\n const updateAgentFromSessionKey = (key: string) => {\n const parsed = parseAgentSessionKey(key);\n if (!parsed?.agentId) {\n return;\n }\n onAgentIdChange?.(parsed.agentId);\n };\n\n const runRefreshSessionInfo = async () => {\n try {\n state.sessionInfo = await client.getSessionInfo(state.currentSessionKey);\n updateFooter();\n tui.requestRender();\n } catch {\n // ignore\n }\n };\n\n const refreshSessionInfo = async () => {\n refreshSessionInfoPromise = refreshSessionInfoPromise.then(\n runRefreshSessionInfo,\n runRefreshSessionInfo,\n );\n await refreshSessionInfoPromise;\n };\n\n const clearChatForSessionSwitch = () => {\n chatLog.clearAll();\n clearSeenStreamEvents();\n sessionSnapshot?.clear();\n lastHistoryKeys = [];\n resetRunStatus(state);\n state.historyLoaded = false;\n state.messageFollowUpQueue.length = 0;\n state.steeringQueue.length = 0;\n };\n\n const loadHistory = async (opts?: { merge?: boolean }) => {\n try {\n const { messages } = await client.loadHistory({\n sessionKey: state.currentSessionKey,\n limit: historyLimit,\n });\n sessionSnapshot?.replaceFromHistory(messages);\n const nextKeys = messages.map(historyMessageKey);\n const canAppend =\n opts?.merge === true &&\n historyKeysHaveAppendOnlyPrefix(lastHistoryKeys, nextKeys);\n if (canAppend) {\n appendHistoryToChatLog(\n chatLog,\n messages.slice(lastHistoryKeys.length),\n state.toolsExpanded,\n state.showThinking,\n { startIndex: lastHistoryKeys.length },\n );\n } else {\n chatLog.clearAll();\n appendHistoryToChatLog(chatLog, messages, state.toolsExpanded, state.showThinking);\n }\n lastHistoryKeys = nextKeys;\n } catch {\n // ignore; footer already hints on disconnect\n } finally {\n state.historyLoaded = true;\n await refreshSessionInfo();\n tui.requestRender();\n }\n };\n\n const loadHistoryWindow = async (opts: {\n rowNumber: number;\n before?: number;\n after?: number;\n }): Promise<boolean> => {\n if (!client.loadHistoryWindow) {\n return false;\n }\n try {\n const { messages } = await client.loadHistoryWindow({\n sessionKey: state.currentSessionKey,\n rowNumber: opts.rowNumber,\n before: opts.before,\n after: opts.after,\n });\n if (messages.length === 0) {\n return false;\n }\n sessionSnapshot?.replaceFromHistory(messages);\n chatLog.clearAll();\n appendHistoryToChatLog(chatLog, messages, state.toolsExpanded, state.showThinking);\n lastHistoryKeys = messages.map(historyMessageKey);\n state.historyLoaded = true;\n return true;\n } catch {\n return false;\n } finally {\n await refreshSessionInfo();\n tui.requestRender();\n }\n };\n\n const setSession = async (rawKey: string) => {\n const nextKey = resolveSessionKey(rawKey);\n updateAgentFromSessionKey(nextKey);\n state.currentSessionKey = nextKey;\n state.activeRunId = null;\n setActivityStatus('idle');\n clearChatForSessionSwitch();\n updateHeader();\n updateFooter();\n await loadHistory();\n };\n\n const abortActive = async (opts?: { clearUi?: boolean }) => {\n if (!state.activeRunId) {\n return;\n }\n const runId = state.activeRunId;\n markRunAborting(state, runId);\n state.activeRunId = null;\n if (opts?.clearUi !== false) {\n chatLog.dropAssistant(runId);\n }\n setActivityStatus('idle');\n markRunIdleAfterAbort(state);\n tui.requestRender();\n await client.abortChat({ sessionKey: state.currentSessionKey, runId }).catch(() => {});\n };\n\n const resetCurrentSession = async () => {\n await client.resetSession(state.currentSessionKey);\n clearChatForSessionSwitch();\n await loadHistory();\n };\n\n return {\n refreshSessionInfo,\n loadHistory,\n loadHistoryWindow,\n setSession,\n abortActive,\n resetCurrentSession,\n clearChatForSessionSwitch,\n };\n}\n"],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ import type { Component, Focusable, KeybindingsManager } from '@earendil-works/pi-tui';
2
+ import { type TuiTimelineTurn } from './tui-timeline.js';
3
+ export declare function formatTimelineOpenedHint(keybindings: KeybindingsManager): string;
4
+ export declare class TimelineSelectList implements Component, Focusable {
5
+ private readonly list;
6
+ private readonly items;
7
+ onSelect?: (turn: TuiTimelineTurn) => void;
8
+ onCancel?: () => void;
9
+ constructor(turns: readonly TuiTimelineTurn[], options: {
10
+ activeDisplayIndex?: number;
11
+ initialQuery?: string;
12
+ keybindings: KeybindingsManager;
13
+ });
14
+ get focused(): boolean;
15
+ set focused(value: boolean);
16
+ invalidate(): void;
17
+ render(width: number): string[];
18
+ handleInput(keyData: string): void;
19
+ }