@xopcai/xopc 0.0.124 → 0.0.126

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 (496) 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/Combination-BzaXOLd9.js +41 -0
  18. package/dist/gateway/static/root/assets/{agent-avatar-dicebear-B5uSVAyJ.js → agent-avatar-dicebear-C70vgt60.js} +1 -1
  19. package/dist/gateway/static/root/assets/agents-DRYVahI-.js +2 -0
  20. package/dist/gateway/static/root/assets/app-management-settings-panel-D9-HW6cy.js +1 -0
  21. package/dist/gateway/static/root/assets/appearance-settings-BHlahIDL.js +1 -0
  22. package/dist/gateway/static/root/assets/apps-page-BdJ1eQg3.js +1 -0
  23. package/dist/gateway/static/root/assets/{archive-plugin-CXUGRp2i.js → archive-plugin-B-aoIt0w.js} +1 -1
  24. package/dist/gateway/static/root/assets/{attachment-load-Cmiub3Wg.js → attachment-load-BD0G0FD5.js} +1 -1
  25. package/dist/gateway/static/root/assets/automation-suggestion-card-iJRVI7aZ.js +1 -0
  26. package/dist/gateway/static/root/assets/automations-page-D8hYQbkl.js +4 -0
  27. package/dist/gateway/static/root/assets/{binary-plugins-0Izz-N3p.js → binary-plugins-B0mNlVSz.js} +1 -1
  28. package/dist/gateway/static/root/assets/{block-editor-C1Kv0IkJ.js → block-editor-CJY9Lu5G.js} +3 -3
  29. package/dist/gateway/static/root/assets/browser-settings-page-CiWEO-Iy.js +8 -0
  30. package/dist/gateway/static/root/assets/capability-presets-api-Bgc8ag55.js +1 -0
  31. package/dist/gateway/static/root/assets/capability-presets-settings-panel-B1nIi0TC.js +1 -0
  32. package/dist/gateway/static/root/assets/{channel-recipient-api-BeA2aVor.js → channel-recipient-api-0sauApoC.js} +1 -1
  33. package/dist/gateway/static/root/assets/channels-settings-BddPdqVo.js +1 -0
  34. package/dist/gateway/static/root/assets/code-editor-gbRgS14t.js +1 -0
  35. package/dist/gateway/static/root/assets/connectors-page-Ba2GDhSE.js +2 -0
  36. package/dist/gateway/static/root/assets/{directory-picker-path-field-2rjzUu57.js → directory-picker-path-field-CiEc4KmY.js} +1 -1
  37. package/dist/gateway/static/root/assets/dist-By6Rh2ee.js +1 -0
  38. package/dist/gateway/static/root/assets/dist-CkobR7mk.js +1 -0
  39. package/dist/gateway/static/root/assets/dist-DokQNVMQ.js +1 -0
  40. package/dist/gateway/static/root/assets/dreaming-settings-4bvpk5wr.js +3 -0
  41. package/dist/gateway/static/root/assets/extension-debug-page-BbyczVZ3.js +1 -0
  42. package/dist/gateway/static/root/assets/extension-page-DLN1I3DR.js +1 -0
  43. package/dist/gateway/static/root/assets/extension-settings-page-D9VGHmYJ.js +1 -0
  44. package/dist/gateway/static/root/assets/{fetch-BU5S0Sn7.js → fetch-5V96dUz3.js} +1 -1
  45. package/dist/gateway/static/root/assets/{gateway-config-api-BIPGwrl1.js → gateway-config-api-BtIzObwp.js} +1 -1
  46. package/dist/gateway/static/root/assets/gateway-settings-KFsGGDhg.js +1 -0
  47. package/dist/gateway/static/root/assets/{gateway-startup-retry-Cd0Zz30N.js → gateway-startup-retry-DEMad2wt.js} +1 -1
  48. package/dist/gateway/static/root/assets/goal-create-dialog-4PcF6Sh6.js +1 -0
  49. package/dist/gateway/static/root/assets/goal-detail-page-B482PSaG.js +1 -0
  50. package/dist/gateway/static/root/assets/{goals-config-api-B95KdGMj.js → goals-config-api-CVN7-pdM.js} +1 -1
  51. package/dist/gateway/static/root/assets/goals-page-CUdgJuDn.js +2 -0
  52. package/dist/gateway/static/root/assets/goals-settings-IYCH3-Pi.js +1 -0
  53. package/dist/gateway/static/root/assets/heartbeat-settings-Cf_a2Bmz.js +1 -0
  54. package/dist/gateway/static/root/assets/{html-workspace-editor-CQLWDiwE.js → html-workspace-editor-DV90ddkE.js} +1 -1
  55. package/dist/gateway/static/root/assets/index-CA2tR2vm.js +256 -0
  56. package/dist/gateway/static/root/assets/index-Ds3u0LOk.css +1 -0
  57. package/dist/gateway/static/root/assets/keyboard-shortcuts-settings-lKTg6St7.js +1 -0
  58. package/dist/gateway/static/root/assets/logs-page-BCporcNH.js +2 -0
  59. package/dist/gateway/static/root/assets/{markdown-editor-AssmZFx4.js → markdown-editor-BFOjBBla.js} +2 -2
  60. package/dist/gateway/static/root/assets/markdown-split-Bv4k6iGJ.js +1 -0
  61. package/dist/gateway/static/root/assets/{media-plugins-BhIQU5yS.js → media-plugins-Bbi8g3N8.js} +1 -1
  62. package/dist/gateway/static/root/assets/messages-C22hxE1N.js +3 -0
  63. package/dist/gateway/static/root/assets/models-hub-panel-D68Pyow7.js +2 -0
  64. package/dist/gateway/static/root/assets/notes-page-CuUMOiyv.js +1 -0
  65. package/dist/gateway/static/root/assets/notes-workbench-Dx2N5zTk.js +2 -0
  66. package/dist/gateway/static/root/assets/page-tabs-Cp395RYD.js +1 -0
  67. package/dist/gateway/static/root/assets/{preview-open-alternatives-DGzet1d7.js → preview-open-alternatives-DqV5OM4m.js} +1 -1
  68. package/dist/gateway/static/root/assets/project-detail-page-sB8AzZi3.js +1 -0
  69. package/dist/gateway/static/root/assets/projects-page-LBnJqWK2.js +1 -0
  70. package/dist/gateway/static/root/assets/remote-access-hub-Dbj0o6SC.js +1 -0
  71. package/dist/gateway/static/root/assets/{save-bar-controls-Cqgb-jqa.js → save-bar-controls-BItmzAzI.js} +1 -1
  72. package/dist/gateway/static/root/assets/{schedule-field-DVZcI8Yt.js → schedule-field-BQ8IjjCn.js} +1 -1
  73. package/dist/gateway/static/root/assets/{schema-form-Bj7sOxC8.js → schema-form-BRpD6x3d.js} +1 -1
  74. package/dist/gateway/static/root/assets/sessions-page-DhDZKspB.js +1 -0
  75. package/dist/gateway/static/root/assets/settings-advanced-gate-BvXLMNL6.js +1 -0
  76. package/dist/gateway/static/root/assets/{settings-collapsible-section-BmXn-8N6.js → settings-collapsible-section-BKSPQM4R.js} +1 -1
  77. package/dist/gateway/static/root/assets/settings-form-section-BmyfthNQ.js +1 -0
  78. package/dist/gateway/static/root/assets/settings-page-Cfm9UxAr.js +1 -0
  79. package/dist/gateway/static/root/assets/settings-page-layout-Bls5tfbH.js +1 -0
  80. package/dist/gateway/static/root/assets/setup-status-panel-kQEsTGAs.js +1 -0
  81. package/dist/gateway/static/root/assets/{share-preview-page-IB1v8i86.js → share-preview-page-DbYZNAPb.js} +1 -1
  82. package/dist/gateway/static/root/assets/shares-settings-BtR4B0kn.js +1 -0
  83. package/dist/gateway/static/root/assets/skill-reload-api-CJNVOWoK.js +1 -0
  84. package/dist/gateway/static/root/assets/skills-page-DcWDHrt3.js +2 -0
  85. package/dist/gateway/static/root/assets/{system-settings-panel-BxQ384RC.js → system-settings-panel-DKDAojWM.js} +1 -1
  86. package/dist/gateway/static/root/assets/{typed-models-lib-BkcpvFYO.js → typed-models-lib-BCCV4Kkp.js} +1 -1
  87. package/dist/gateway/static/root/assets/{use-channel-catalog-Cd0FaEQ4.js → use-channel-catalog-NBqg3iFY.js} +1 -1
  88. package/dist/gateway/static/root/assets/{user-profile-settings-panel-DQ7NnRSY.js → user-profile-settings-panel-suQ2x-LB.js} +1 -1
  89. package/dist/gateway/static/root/assets/{utils-YKhVf7Ka.js → utils-DPGVr3tS.js} +1 -1
  90. package/dist/gateway/static/root/assets/{vendor-codemirror-CNP1wPe7.js → vendor-codemirror-BvNgyE1Q.js} +1 -1
  91. package/dist/gateway/static/root/assets/voice-api-key-field-DaJASKFP.js +1 -0
  92. package/dist/gateway/static/root/assets/work-item-detail-page-BrCZpAWh.js +1 -0
  93. package/dist/gateway/static/root/assets/workflow-run-setup-panel-BTkRVNAh.js +3 -0
  94. package/dist/gateway/static/root/assets/{workflow-start-dialog-BNJVCWoS.js → workflow-start-dialog-DAImVtdO.js} +1 -1
  95. package/dist/gateway/static/root/assets/workflows-page-vyJ8wSXm.js +18 -0
  96. package/dist/gateway/static/root/index.html +8 -7
  97. package/dist/package.js +1 -1
  98. package/dist/src/activity/context.d.ts +11 -0
  99. package/dist/src/activity/context.js +36 -0
  100. package/dist/src/activity/context.js.map +1 -0
  101. package/dist/src/activity/emitter.d.ts +6 -0
  102. package/dist/src/activity/emitter.js +43 -0
  103. package/dist/src/activity/emitter.js.map +1 -0
  104. package/dist/src/activity/index.d.ts +3 -0
  105. package/dist/src/activity/index.js +3 -0
  106. package/dist/src/activity/service.d.ts +12 -0
  107. package/dist/src/activity/service.js +59 -0
  108. package/dist/src/activity/service.js.map +1 -0
  109. package/dist/src/activity/types.d.ts +109 -0
  110. package/dist/src/activity/types.js +1 -0
  111. package/dist/src/agent/agent-manager.d.ts +7 -0
  112. package/dist/src/agent/agent-manager.js +12 -5
  113. package/dist/src/agent/agent-manager.js.map +1 -1
  114. package/dist/src/agent/child-agent-factory.d.ts +2 -0
  115. package/dist/src/agent/child-agent-factory.js +2 -0
  116. package/dist/src/agent/child-agent-factory.js.map +1 -1
  117. package/dist/src/agent/coding/index.d.ts +1 -0
  118. package/dist/src/agent/coding/index.js +2 -0
  119. package/dist/src/agent/coding/turn-diff-tracker.d.ts +67 -0
  120. package/dist/src/agent/coding/turn-diff-tracker.js +233 -0
  121. package/dist/src/agent/coding/turn-diff-tracker.js.map +1 -0
  122. package/dist/src/agent/context/project-context.js +2 -2
  123. package/dist/src/agent/context/workspace-seed.js +2 -2
  124. package/dist/src/agent/embedded/run-for-session.js +1 -1
  125. package/dist/src/agent/goals/post-turn.js +2 -2
  126. package/dist/src/agent/ipc/bus.js +1 -1
  127. package/dist/src/agent/mcp/bundle-mcp-materialize.js +1 -1
  128. package/dist/src/agent/mcp/bundle-mcp-runtime.js +1 -1
  129. package/dist/src/agent/mcp/mcp-transport-config.js +1 -1
  130. package/dist/src/agent/mcp/mcp-transport.js +1 -1
  131. package/dist/src/agent/memory/dreaming/config.d.ts +2 -2
  132. package/dist/src/agent/memory/dreaming/config.js +3 -3
  133. package/dist/src/agent/memory/dreaming/config.js.map +1 -1
  134. package/dist/src/agent/memory/dreaming/constants.d.ts +1 -1
  135. package/dist/src/agent/memory/dreaming/constants.js +1 -1
  136. package/dist/src/agent/memory/dreaming/constants.js.map +1 -1
  137. package/dist/src/agent/memory/dreaming/deep-promotion.d.ts +1 -0
  138. package/dist/src/agent/memory/dreaming/deep-promotion.js +11 -20
  139. package/dist/src/agent/memory/dreaming/deep-promotion.js.map +1 -1
  140. package/dist/src/agent/memory/dreaming/events.d.ts +3 -3
  141. package/dist/src/agent/memory/dreaming/events.js +6 -6
  142. package/dist/src/agent/memory/dreaming/events.js.map +1 -1
  143. package/dist/src/agent/memory/dreaming/last-run.d.ts +2 -2
  144. package/dist/src/agent/memory/dreaming/last-run.js +1 -1
  145. package/dist/src/agent/memory/dreaming/last-run.js.map +1 -1
  146. package/dist/src/agent/memory/dreaming/light-sweep.d.ts +1 -1
  147. package/dist/src/agent/memory/dreaming/light-sweep.js +3 -3
  148. package/dist/src/agent/memory/dreaming/light-sweep.js.map +1 -1
  149. package/dist/src/agent/memory/dreaming/preview.d.ts +1 -0
  150. package/dist/src/agent/memory/dreaming/preview.js +2 -2
  151. package/dist/src/agent/memory/dreaming/preview.js.map +1 -1
  152. package/dist/src/agent/memory/dreaming/rem-patterns.d.ts +1 -1
  153. package/dist/src/agent/memory/dreaming/rem-patterns.js +13 -13
  154. package/dist/src/agent/memory/dreaming/rem-patterns.js.map +1 -1
  155. package/dist/src/agent/memory/dreaming/scope.d.ts +14 -0
  156. package/dist/src/agent/memory/dreaming/scope.js +27 -0
  157. package/dist/src/agent/memory/dreaming/scope.js.map +1 -0
  158. package/dist/src/agent/memory/dreaming/short-term-store.d.ts +4 -4
  159. package/dist/src/agent/memory/dreaming/short-term-store.js +17 -17
  160. package/dist/src/agent/memory/dreaming/short-term-store.js.map +1 -1
  161. package/dist/src/agent/memory/plugin-discovery.js +1 -1
  162. package/dist/src/agent/models/manager.js +1 -1
  163. package/dist/src/agent/orchestration/agent-event-handler.d.ts +2 -0
  164. package/dist/src/agent/orchestration/agent-event-handler.js +13 -0
  165. package/dist/src/agent/orchestration/agent-event-handler.js.map +1 -1
  166. package/dist/src/agent/orchestration/agent-orchestrator.js +22 -12
  167. package/dist/src/agent/orchestration/agent-orchestrator.js.map +1 -1
  168. package/dist/src/agent/sandbox/command-validator.js +12 -0
  169. package/dist/src/agent/sandbox/command-validator.js.map +1 -1
  170. package/dist/src/agent/service.d.ts +2 -1
  171. package/dist/src/agent/service.js +24 -9
  172. package/dist/src/agent/service.js.map +1 -1
  173. package/dist/src/agent/service.types.d.ts +7 -0
  174. package/dist/src/agent/session/session-inspector.d.ts +5 -3
  175. package/dist/src/agent/session/session-inspector.js +17 -8
  176. package/dist/src/agent/session/session-inspector.js.map +1 -1
  177. package/dist/src/agent/skills/hub-pull.js +1 -1
  178. package/dist/src/agent/source-context/types.d.ts +1 -1
  179. package/dist/src/agent/source-context/types.js +1 -1
  180. package/dist/src/agent/source-context/types.js.map +1 -1
  181. package/dist/src/agent/tool-manuals/index.js +15 -6
  182. package/dist/src/agent/tool-manuals/index.js.map +1 -1
  183. package/dist/src/agent/tool-manuals/xopc-use.d.ts +1 -0
  184. package/dist/src/agent/tool-manuals/xopc-use.js +204 -0
  185. package/dist/src/agent/tool-manuals/xopc-use.js.map +1 -0
  186. package/dist/src/agent/tools/apply-patch.js +116 -62
  187. package/dist/src/agent/tools/apply-patch.js.map +1 -1
  188. package/dist/src/agent/tools/concurrency.d.ts +8 -0
  189. package/dist/src/agent/tools/concurrency.js +31 -0
  190. package/dist/src/agent/tools/concurrency.js.map +1 -0
  191. package/dist/src/agent/tools/dreaming-tool.d.ts +2 -0
  192. package/dist/src/agent/tools/dreaming-tool.js +13 -10
  193. package/dist/src/agent/tools/dreaming-tool.js.map +1 -1
  194. package/dist/src/agent/tools/exec-command.js +4 -0
  195. package/dist/src/agent/tools/exec-command.js.map +1 -1
  196. package/dist/src/agent/tools/executor.d.ts +6 -4
  197. package/dist/src/agent/tools/executor.js +7 -4
  198. package/dist/src/agent/tools/executor.js.map +1 -1
  199. package/dist/src/agent/tools/factory.d.ts +10 -0
  200. package/dist/src/agent/tools/factory.js +16 -1
  201. package/dist/src/agent/tools/factory.js.map +1 -1
  202. package/dist/src/agent/tools/find.js +2 -0
  203. package/dist/src/agent/tools/find.js.map +1 -1
  204. package/dist/src/agent/tools/goal-tool.js +2 -2
  205. package/dist/src/agent/tools/grep.js +2 -0
  206. package/dist/src/agent/tools/grep.js.map +1 -1
  207. package/dist/src/agent/tools/index.d.ts +3 -0
  208. package/dist/src/agent/tools/index.js +4 -1
  209. package/dist/src/agent/tools/list-dir.js +2 -0
  210. package/dist/src/agent/tools/list-dir.js.map +1 -1
  211. package/dist/src/agent/tools/memory-tool.d.ts +1 -0
  212. package/dist/src/agent/tools/memory-tool.js +2 -2
  213. package/dist/src/agent/tools/memory-tool.js.map +1 -1
  214. package/dist/src/agent/tools/metadata.d.ts +15 -0
  215. package/dist/src/agent/tools/metadata.js +26 -0
  216. package/dist/src/agent/tools/metadata.js.map +1 -0
  217. package/dist/src/agent/tools/read.js +2 -0
  218. package/dist/src/agent/tools/read.js.map +1 -1
  219. package/dist/src/agent/tools/workflow-tool.js +1 -1
  220. package/dist/src/agent/tools/write.js +6 -0
  221. package/dist/src/agent/tools/write.js.map +1 -1
  222. package/dist/src/agent/tools/xopc-use-tool.d.ts +34 -0
  223. package/dist/src/agent/tools/xopc-use-tool.js +636 -0
  224. package/dist/src/agent/tools/xopc-use-tool.js.map +1 -0
  225. package/dist/src/agent/workflow/subagent-runner.d.ts +1 -0
  226. package/dist/src/agent/workflow/subagent-runner.js +5 -1
  227. package/dist/src/agent/workflow/subagent-runner.js.map +1 -1
  228. package/dist/src/agent/workflow/workflow-child-tools.js +5 -0
  229. package/dist/src/agent/workflow/workflow-child-tools.js.map +1 -1
  230. package/dist/src/agent-manifest/schema.d.ts +27 -27
  231. package/dist/src/automations/api/routes.js +1 -1
  232. package/dist/src/automations/domain/validation.d.ts +55 -55
  233. package/dist/src/automations/draft/automation-draft-validator.d.ts +25 -25
  234. package/dist/src/automations/service/action-executor.js +2 -2
  235. package/dist/src/browser/cdp-local-launcher.js +1 -1
  236. package/dist/src/browser/providers/browser-ext-install.js +3 -3
  237. package/dist/src/browser/providers/cloakbrowser.js +2 -2
  238. package/dist/src/browser/providers/playwright-doctor.js +1 -1
  239. package/dist/src/browser/stealth.js +1 -1
  240. package/dist/src/chat-commands/agent-edit.js +1 -1
  241. package/dist/src/chat-commands/builtins/config.js +1 -1
  242. package/dist/src/chat-commands/builtins/goal.js +2 -2
  243. package/dist/src/chat-commands/context.js +1 -1
  244. package/dist/src/cli/commands/agent.js +1 -1
  245. package/dist/src/cli/commands/doctor/checks/database-schema.js +2 -2
  246. package/dist/src/cli/commands/doctor/checks/session-integrity.js +1 -1
  247. package/dist/src/cli/commands/extension-marketplace.js +1 -1
  248. package/dist/src/cli/commands/extension-pack.js +1 -1
  249. package/dist/src/cli/commands/gateway/lifecycle.js +1 -1
  250. package/dist/src/cli/commands/goal.js +3 -3
  251. package/dist/src/cli/commands/init.js +1 -1
  252. package/dist/src/cli/commands/project.js +4 -4
  253. package/dist/src/config/agent-profile.js +1 -1
  254. package/dist/src/config/gateway-bind.js +1 -1
  255. package/dist/src/config/index.js +1 -1
  256. package/dist/src/config/loader.js +1 -1
  257. package/dist/src/config/models-json.d.ts +14 -14
  258. package/dist/src/config/models-json.js +1 -1
  259. package/dist/src/config/schema.d.ts +60 -60
  260. package/dist/src/connectors/health.d.ts +2 -1
  261. package/dist/src/connectors/health.js +59 -1
  262. package/dist/src/connectors/health.js.map +1 -1
  263. package/dist/src/connectors/install.d.ts +1 -0
  264. package/dist/src/connectors/install.js +28 -1
  265. package/dist/src/connectors/install.js.map +1 -1
  266. package/dist/src/connectors/instances.js +7 -0
  267. package/dist/src/connectors/instances.js.map +1 -1
  268. package/dist/src/connectors/materialize.js +2 -1
  269. package/dist/src/connectors/materialize.js.map +1 -1
  270. package/dist/src/connectors/registries/modelscope.js +38 -13
  271. package/dist/src/connectors/registries/modelscope.js.map +1 -1
  272. package/dist/src/connectors/types.d.ts +2 -0
  273. package/dist/src/daemon/launchd.js +1 -1
  274. package/dist/src/daemon/systemd.js +1 -1
  275. package/dist/src/extensions/discover-extensions.js +1 -1
  276. package/dist/src/extensions/loader.js +2 -2
  277. package/dist/src/gateway/agents-admin.js +1 -1
  278. package/dist/src/gateway/dreaming-automation-reconciler.d.ts +1 -0
  279. package/dist/src/gateway/dreaming-automation-reconciler.js +62 -42
  280. package/dist/src/gateway/dreaming-automation-reconciler.js.map +1 -1
  281. package/dist/src/gateway/hono/app.js +7 -1
  282. package/dist/src/gateway/hono/app.js.map +1 -1
  283. package/dist/src/gateway/hono/lib/config-payload.d.ts +14 -14
  284. package/dist/src/gateway/hono/lib/static-ui.js +1 -1
  285. package/dist/src/gateway/hono/middleware/log-context.js +8 -1
  286. package/dist/src/gateway/hono/middleware/log-context.js.map +1 -1
  287. package/dist/src/gateway/hono/routes/activity.d.ts +14 -0
  288. package/dist/src/gateway/hono/routes/activity.js +72 -0
  289. package/dist/src/gateway/hono/routes/activity.js.map +1 -0
  290. package/dist/src/gateway/hono/routes/connectors.js +46 -2
  291. package/dist/src/gateway/hono/routes/connectors.js.map +1 -1
  292. package/dist/src/gateway/hono/routes/dreaming.js +111 -66
  293. package/dist/src/gateway/hono/routes/dreaming.js.map +1 -1
  294. package/dist/src/gateway/hono/routes/goals.js +1 -1
  295. package/dist/src/gateway/hono/routes/index.js +2 -0
  296. package/dist/src/gateway/hono/routes/index.js.map +1 -1
  297. package/dist/src/gateway/hono/routes/memory.js +2 -2
  298. package/dist/src/gateway/hono/routes/projects.js +903 -50
  299. package/dist/src/gateway/hono/routes/projects.js.map +1 -1
  300. package/dist/src/gateway/hono/routes/sessions.js +102 -2
  301. package/dist/src/gateway/hono/routes/sessions.js.map +1 -1
  302. package/dist/src/gateway/hono/routes/workflows.js +2 -2
  303. package/dist/src/gateway/lock.js +1 -1
  304. package/dist/src/gateway/ports.js +1 -1
  305. package/dist/src/gateway/service/sessions-api.d.ts +10 -0
  306. package/dist/src/gateway/service/sessions-api.js +31 -0
  307. package/dist/src/gateway/service/sessions-api.js.map +1 -1
  308. package/dist/src/gateway/service.js +28 -16
  309. package/dist/src/gateway/service.js.map +1 -1
  310. package/dist/src/goals/goal-store.js +1 -1
  311. package/dist/src/goals/goal-store.js.map +1 -1
  312. package/dist/src/goals/goal-workflow-judge.js +1 -1
  313. package/dist/src/infra/ports.js +1 -1
  314. package/dist/src/infra/ssh-tunnel.js +1 -1
  315. package/dist/src/infra/update-check.js +1 -1
  316. package/dist/src/infra/update-restart.js +1 -1
  317. package/dist/src/mcp/channel-bridge.js +1 -1
  318. package/dist/src/media/store.js +1 -1
  319. package/dist/src/media/store.js.map +1 -1
  320. package/dist/src/media/types.d.ts +1 -1
  321. package/dist/src/media/uri.js +2 -1
  322. package/dist/src/media/uri.js.map +1 -1
  323. package/dist/src/migrations/runner.js +1 -1
  324. package/dist/src/notes/service.js +65 -6
  325. package/dist/src/notes/service.js.map +1 -1
  326. package/dist/src/notes/store.js +1 -1
  327. package/dist/src/projects/project-service.d.ts +2 -1
  328. package/dist/src/projects/project-service.js +59 -2
  329. package/dist/src/projects/project-service.js.map +1 -1
  330. package/dist/src/projects/project-store.d.ts +2 -1
  331. package/dist/src/projects/project-store.js +43 -0
  332. package/dist/src/projects/project-store.js.map +1 -1
  333. package/dist/src/projects/types.d.ts +10 -0
  334. package/dist/src/projects/workspace.js +1 -1
  335. package/dist/src/routing/agent-session-key.js +1 -1
  336. package/dist/src/routing/resolve-route.js +1 -1
  337. package/dist/src/routing/resolve-tui-session-key.js +1 -1
  338. package/dist/src/session/client-history.d.ts +3 -0
  339. package/dist/src/session/client-history.js +24 -9
  340. package/dist/src/session/client-history.js.map +1 -1
  341. package/dist/src/session/init-session-turn.js +1 -1
  342. package/dist/src/session/resolve-session.js +1 -1
  343. package/dist/src/session/session-context-for-llm.d.ts +2 -0
  344. package/dist/src/session/session-context-for-llm.js +14 -1
  345. package/dist/src/session/session-context-for-llm.js.map +1 -1
  346. package/dist/src/session/session-title.js +2 -2
  347. package/dist/src/session/store.js +3 -3
  348. package/dist/src/session/store.js.map +1 -1
  349. package/dist/src/session/types.d.ts +4 -0
  350. package/dist/src/session/types.js.map +1 -1
  351. package/dist/src/storage/sqlite/activity-repository.d.ts +8 -0
  352. package/dist/src/storage/sqlite/activity-repository.js +208 -0
  353. package/dist/src/storage/sqlite/activity-repository.js.map +1 -0
  354. package/dist/src/storage/sqlite/connection.js +1 -1
  355. package/dist/src/storage/sqlite/index.d.ts +1 -0
  356. package/dist/src/storage/sqlite/index.js +2 -1
  357. package/dist/src/storage/sqlite/migrations/022_work_items.sql +61 -0
  358. package/dist/src/storage/sqlite/migrations/023_work_item_attachments.sql +15 -0
  359. package/dist/src/storage/sqlite/migrations/024_activity_events.sql +62 -0
  360. package/dist/src/storage/sqlite/migrations/runner.d.ts +1 -1
  361. package/dist/src/storage/sqlite/migrations/runner.js +3 -3
  362. package/dist/src/storage/sqlite/migrations/runner.js.map +1 -1
  363. package/dist/src/storage/sqlite/migrations/runner.ts +1 -1
  364. package/dist/src/storage/sqlite/row-mappers.js +1 -1
  365. package/dist/src/storage/sqlite/schema.js +1 -1
  366. package/dist/src/storage/sqlite/schema.sql +141 -0
  367. package/dist/src/storage/sqlite/session-repository.js +11 -0
  368. package/dist/src/storage/sqlite/session-repository.js.map +1 -1
  369. package/dist/src/tui/backends/embedded-backend.d.ts +13 -0
  370. package/dist/src/tui/backends/embedded-backend.js +76 -7
  371. package/dist/src/tui/backends/embedded-backend.js.map +1 -1
  372. package/dist/src/tui/backends/gateway-sse-backend.d.ts +13 -0
  373. package/dist/src/tui/backends/gateway-sse-backend.js +53 -0
  374. package/dist/src/tui/backends/gateway-sse-backend.js.map +1 -1
  375. package/dist/src/tui/chat-history.js +16 -3
  376. package/dist/src/tui/chat-history.js.map +1 -1
  377. package/dist/src/tui/clipboard-image.js +1 -1
  378. package/dist/src/tui/components/assistant-message.js +12 -2
  379. package/dist/src/tui/components/assistant-message.js.map +1 -1
  380. package/dist/src/tui/components/chat-log.d.ts +23 -3
  381. package/dist/src/tui/components/chat-log.js +68 -9
  382. package/dist/src/tui/components/chat-log.js.map +1 -1
  383. package/dist/src/tui/components/tool-execution.d.ts +8 -0
  384. package/dist/src/tui/components/tool-execution.js +87 -77
  385. package/dist/src/tui/components/tool-execution.js.map +1 -1
  386. package/dist/src/tui/components/tui-bottom-bar.js +9 -5
  387. package/dist/src/tui/components/tui-bottom-bar.js.map +1 -1
  388. package/dist/src/tui/components/visual-truncate.d.ts +1 -0
  389. package/dist/src/tui/components/visual-truncate.js +28 -1
  390. package/dist/src/tui/components/visual-truncate.js.map +1 -1
  391. package/dist/src/tui/tool-summary.d.ts +22 -0
  392. package/dist/src/tui/tool-summary.js +212 -0
  393. package/dist/src/tui/tool-summary.js.map +1 -0
  394. package/dist/src/tui/tui-backend.d.ts +16 -0
  395. package/dist/src/tui/tui-command-formatters.js +2 -2
  396. package/dist/src/tui/tui-commands.d.ts +9 -0
  397. package/dist/src/tui/tui-commands.js +95 -6
  398. package/dist/src/tui/tui-commands.js.map +1 -1
  399. package/dist/src/tui/tui-picker-overlay.d.ts +1 -0
  400. package/dist/src/tui/tui-picker-overlay.js +36 -1
  401. package/dist/src/tui/tui-picker-overlay.js.map +1 -1
  402. package/dist/src/tui/tui-picker-services.d.ts +13 -0
  403. package/dist/src/tui/tui-run-state.js +11 -0
  404. package/dist/src/tui/tui-run-state.js.map +1 -1
  405. package/dist/src/tui/tui-run-status-format.d.ts +3 -0
  406. package/dist/src/tui/tui-run-status-format.js +33 -0
  407. package/dist/src/tui/tui-run-status-format.js.map +1 -0
  408. package/dist/src/tui/tui-session-actions.d.ts +5 -0
  409. package/dist/src/tui/tui-session-actions.js +24 -0
  410. package/dist/src/tui/tui-session-actions.js.map +1 -1
  411. package/dist/src/tui/tui-timeline-picker.d.ts +19 -0
  412. package/dist/src/tui/tui-timeline-picker.js +81 -0
  413. package/dist/src/tui/tui-timeline-picker.js.map +1 -0
  414. package/dist/src/tui/tui-timeline.d.ts +15 -0
  415. package/dist/src/tui/tui-timeline.js +65 -0
  416. package/dist/src/tui/tui-timeline.js.map +1 -0
  417. package/dist/src/tui/tui-tool-diff.d.ts +15 -0
  418. package/dist/src/tui/tui-tool-diff.js +178 -7
  419. package/dist/src/tui/tui-tool-diff.js.map +1 -1
  420. package/dist/src/tui/tui-types.d.ts +1 -0
  421. package/dist/src/tui/tui-types.js +1 -0
  422. package/dist/src/tui/tui-types.js.map +1 -1
  423. package/dist/src/tui/tui.js +31 -25
  424. package/dist/src/tui/tui.js.map +1 -1
  425. package/dist/src/utils/index.js +1 -1
  426. package/dist/src/utils/logger/index.js +1 -1
  427. package/dist/src/utils/logger/stats.d.ts +3 -3
  428. package/dist/src/utils/logger.js +1 -1
  429. package/dist/src/work-items/agent-context.d.ts +7 -0
  430. package/dist/src/work-items/agent-context.js +75 -0
  431. package/dist/src/work-items/agent-context.js.map +1 -0
  432. package/dist/src/work-items/index.d.ts +4 -0
  433. package/dist/src/work-items/index.js +4 -0
  434. package/dist/src/work-items/types.d.ts +112 -0
  435. package/dist/src/work-items/types.js +1 -0
  436. package/dist/src/work-items/work-item-service.d.ts +35 -0
  437. package/dist/src/work-items/work-item-service.js +277 -0
  438. package/dist/src/work-items/work-item-service.js.map +1 -0
  439. package/dist/src/work-items/work-item-store.d.ts +21 -0
  440. package/dist/src/work-items/work-item-store.js +302 -0
  441. package/dist/src/work-items/work-item-store.js.map +1 -0
  442. package/dist/src/workflows/draft/workflow-draft-service.js +1 -1
  443. package/dist/src/workflows/service/workflow-run-service.js +4 -3
  444. package/dist/src/workflows/service/workflow-run-service.js.map +1 -1
  445. package/dist/src/workflows/service/workflow-session-bridge.js +4 -1
  446. package/dist/src/workflows/service/workflow-session-bridge.js.map +1 -1
  447. package/package.json +5 -5
  448. package/dist/gateway/static/root/assets/Combination-HAlzriaz.js +0 -41
  449. package/dist/gateway/static/root/assets/agents-BjIxt67Z.js +0 -2
  450. package/dist/gateway/static/root/assets/app-management-settings-panel-CYCONLIL.js +0 -1
  451. package/dist/gateway/static/root/assets/appearance-settings-Clw3ryKg.js +0 -1
  452. package/dist/gateway/static/root/assets/apps-page-QICTeGjX.js +0 -1
  453. package/dist/gateway/static/root/assets/automation-suggestion-card-CU0-4nQ-.js +0 -1
  454. package/dist/gateway/static/root/assets/automations-page-Car-jtiz.js +0 -1
  455. package/dist/gateway/static/root/assets/browser-settings-page-CMeBJzlS.js +0 -8
  456. package/dist/gateway/static/root/assets/capability-presets-api-BmQTM9Il.js +0 -1
  457. package/dist/gateway/static/root/assets/capability-presets-settings-panel-DZEJEoCF.js +0 -1
  458. package/dist/gateway/static/root/assets/channels-settings-kkW-xFau.js +0 -1
  459. package/dist/gateway/static/root/assets/code-editor-dZTY2dRW.js +0 -1
  460. package/dist/gateway/static/root/assets/connectors-page-BvaQvO5F.js +0 -2
  461. package/dist/gateway/static/root/assets/dist-Mys7eFJ5.js +0 -1
  462. package/dist/gateway/static/root/assets/dist-wO9a2_ID.js +0 -1
  463. package/dist/gateway/static/root/assets/dreaming-settings-DnHO686d.js +0 -1
  464. package/dist/gateway/static/root/assets/extension-debug-page-BGLRuWVN.js +0 -1
  465. package/dist/gateway/static/root/assets/extension-page-D978ePp9.js +0 -1
  466. package/dist/gateway/static/root/assets/extension-settings-page-B6Ih4Swx.js +0 -1
  467. package/dist/gateway/static/root/assets/gateway-settings-CMEA3r5u.js +0 -1
  468. package/dist/gateway/static/root/assets/goal-create-dialog-B-KHKeXN.js +0 -1
  469. package/dist/gateway/static/root/assets/goal-detail-page-BxrSoWdj.js +0 -1
  470. package/dist/gateway/static/root/assets/goals-page-BTJzIl28.js +0 -2
  471. package/dist/gateway/static/root/assets/goals-settings-BJyEuLLm.js +0 -1
  472. package/dist/gateway/static/root/assets/heartbeat-settings-wkOjYNQT.js +0 -1
  473. package/dist/gateway/static/root/assets/index-BLaXr6Ev.css +0 -1
  474. package/dist/gateway/static/root/assets/index-c_9TVr_C.js +0 -191
  475. package/dist/gateway/static/root/assets/keyboard-shortcuts-settings-BT8T4DyC.js +0 -1
  476. package/dist/gateway/static/root/assets/logs-page-CrxBJUgI.js +0 -2
  477. package/dist/gateway/static/root/assets/markdown-split-Dv66bO2b.js +0 -1
  478. package/dist/gateway/static/root/assets/messages-O6TAtdFC.js +0 -3
  479. package/dist/gateway/static/root/assets/models-hub-panel-DOOpz6y1.js +0 -2
  480. package/dist/gateway/static/root/assets/notes-page-Br16pK9v.js +0 -1
  481. package/dist/gateway/static/root/assets/notes-workbench-PSJAi0ZC.js +0 -2
  482. package/dist/gateway/static/root/assets/project-detail-page-CIGGgKuw.js +0 -1
  483. package/dist/gateway/static/root/assets/projects-page-B2grhsBt.js +0 -1
  484. package/dist/gateway/static/root/assets/remote-access-hub-CXMORxBD.js +0 -1
  485. package/dist/gateway/static/root/assets/sessions-page-Bi2wkBzU.js +0 -1
  486. package/dist/gateway/static/root/assets/settings-advanced-gate-B1L3G4IA.js +0 -1
  487. package/dist/gateway/static/root/assets/settings-form-section-BnqYMWHR.js +0 -1
  488. package/dist/gateway/static/root/assets/settings-page-BfRSHJmO.js +0 -1
  489. package/dist/gateway/static/root/assets/settings-page-layout-CdWZU1hd.js +0 -1
  490. package/dist/gateway/static/root/assets/setup-status-panel-CWtPM7RK.js +0 -1
  491. package/dist/gateway/static/root/assets/shares-settings-ngbsBgij.js +0 -1
  492. package/dist/gateway/static/root/assets/skill-reload-api-BIe442Gv.js +0 -1
  493. package/dist/gateway/static/root/assets/skills-page-BfchZRVa.js +0 -2
  494. package/dist/gateway/static/root/assets/voice-api-key-field-C5Ov8Uk_.js +0 -1
  495. package/dist/gateway/static/root/assets/workflow-run-setup-panel-BYD9BtOq.js +0 -3
  496. package/dist/gateway/static/root/assets/workflows-page-BYF29ANm.js +0 -18
@@ -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
+ }
@@ -0,0 +1,81 @@
1
+ import { searchableSelectListTheme, theme } from "./theme.js";
2
+ import { formatKeyIds } from "./format-tui-hotkeys.js";
3
+ import { formatTimelineToolSummary } from "./tui-timeline.js";
4
+ import { SearchableSelectList } from "./components/searchable-select-list.js";
5
+ //#region src/tui/tui-timeline-picker.ts
6
+ function formatTime(timestamp) {
7
+ if (timestamp === void 0) return "";
8
+ const date = new Date(timestamp);
9
+ if (Number.isNaN(date.getTime())) return "";
10
+ return new Intl.DateTimeFormat(void 0, {
11
+ hour: "2-digit",
12
+ minute: "2-digit"
13
+ }).format(date);
14
+ }
15
+ function timelineSelectItems(turns, activeDisplayIndex) {
16
+ const activeTurn = activeDisplayIndex === void 0 ? void 0 : [...turns].reverse().find((turn) => turn.displayIndex <= activeDisplayIndex);
17
+ return turns.map((turn) => {
18
+ const current = activeTurn?.id === turn.id;
19
+ const description = [
20
+ formatTimelineToolSummary(turn.toolCount),
21
+ formatTime(turn.timestamp),
22
+ turn.running ? "running" : "",
23
+ current ? "current" : ""
24
+ ].filter(Boolean).join(" · ");
25
+ return {
26
+ value: turn.id,
27
+ label: `${String(turn.turn).padStart(3, " ")} ${turn.preview}`,
28
+ description,
29
+ searchText: `${turn.turn} ${turn.preview} ${description}`,
30
+ turn
31
+ };
32
+ });
33
+ }
34
+ function formatTimelineOpenedHint(keybindings) {
35
+ return `Timeline (${formatKeyIds(keybindings, "tui.select.up", { capitalize: true })}/${formatKeyIds(keybindings, "tui.select.down", { capitalize: true })} · type to filter · ${formatKeyIds(keybindings, "tui.select.confirm", { capitalize: true })} jump · ${formatKeyIds(keybindings, "tui.select.cancel", { capitalize: true })} close)`;
36
+ }
37
+ var TimelineSelectList = class {
38
+ list;
39
+ items;
40
+ onSelect;
41
+ onCancel;
42
+ constructor(turns, options) {
43
+ this.items = timelineSelectItems(turns, options.activeDisplayIndex);
44
+ this.list = new SearchableSelectList(this.items, Math.min(14, Math.max(1, this.items.length)), searchableSelectListTheme, {
45
+ searchPromptText: "timeline: ",
46
+ wrapNavigation: true,
47
+ ...options.initialQuery ? { initialQuery: options.initialQuery } : {}
48
+ });
49
+ this.list.onSelect = (item) => {
50
+ const turn = item.turn;
51
+ if (turn) this.onSelect?.(turn);
52
+ };
53
+ this.list.onCancel = () => this.onCancel?.();
54
+ const activeItem = this.items.find((item) => item.description?.includes("current"));
55
+ if (activeItem) this.list.setSelectedValue(activeItem.value);
56
+ }
57
+ get focused() {
58
+ return this.list.focused;
59
+ }
60
+ set focused(value) {
61
+ this.list.focused = value;
62
+ }
63
+ invalidate() {
64
+ this.list.invalidate();
65
+ }
66
+ render(width) {
67
+ const count = this.items.length;
68
+ return [
69
+ theme.dim(`Timeline · ${count} turn${count === 1 ? "" : "s"}`),
70
+ "",
71
+ ...this.list.render(width)
72
+ ];
73
+ }
74
+ handleInput(keyData) {
75
+ this.list.handleInput(keyData);
76
+ }
77
+ };
78
+ //#endregion
79
+ export { TimelineSelectList, formatTimelineOpenedHint };
80
+
81
+ //# sourceMappingURL=tui-timeline-picker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tui-timeline-picker.js","names":[],"sources":["../../../src/tui/tui-timeline-picker.ts"],"sourcesContent":["import type {\n Component,\n Focusable,\n KeybindingsManager,\n SelectItem,\n} from '@earendil-works/pi-tui';\n\nimport { SearchableSelectList } from './components/searchable-select-list.js';\nimport { formatKeyIds } from './format-tui-hotkeys.js';\nimport { searchableSelectListTheme, theme } from './theme.js';\nimport {\n formatTimelineToolSummary,\n type TuiTimelineTurn,\n} from './tui-timeline.js';\n\ntype TimelineSelectItem = SelectItem & {\n searchText?: string;\n turn: TuiTimelineTurn;\n};\n\nfunction formatTime(timestamp?: number): string {\n if (timestamp === undefined) return '';\n const date = new Date(timestamp);\n if (Number.isNaN(date.getTime())) return '';\n return new Intl.DateTimeFormat(undefined, {\n hour: '2-digit',\n minute: '2-digit',\n }).format(date);\n}\n\nfunction timelineSelectItems(\n turns: readonly TuiTimelineTurn[],\n activeDisplayIndex?: number,\n): TimelineSelectItem[] {\n const activeTurn = activeDisplayIndex === undefined\n ? undefined\n : [...turns].reverse().find((turn) => turn.displayIndex <= activeDisplayIndex);\n\n return turns.map((turn) => {\n const current = activeTurn?.id === turn.id;\n const description = [\n formatTimelineToolSummary(turn.toolCount),\n formatTime(turn.timestamp),\n turn.running ? 'running' : '',\n current ? 'current' : '',\n ].filter(Boolean).join(' · ');\n return {\n value: turn.id,\n label: `${String(turn.turn).padStart(3, ' ')} ${turn.preview}`,\n description,\n searchText: `${turn.turn} ${turn.preview} ${description}`,\n turn,\n };\n });\n}\n\nexport function formatTimelineOpenedHint(keybindings: KeybindingsManager): string {\n const up = formatKeyIds(keybindings, 'tui.select.up', { capitalize: true });\n const down = formatKeyIds(keybindings, 'tui.select.down', { capitalize: true });\n const confirm = formatKeyIds(keybindings, 'tui.select.confirm', { capitalize: true });\n const cancel = formatKeyIds(keybindings, 'tui.select.cancel', { capitalize: true });\n return `Timeline (${up}/${down} · type to filter · ${confirm} jump · ${cancel} close)`;\n}\n\nexport class TimelineSelectList implements Component, Focusable {\n private readonly list: SearchableSelectList;\n private readonly items: TimelineSelectItem[];\n\n onSelect?: (turn: TuiTimelineTurn) => void;\n onCancel?: () => void;\n\n constructor(\n turns: readonly TuiTimelineTurn[],\n options: {\n activeDisplayIndex?: number;\n initialQuery?: string;\n keybindings: KeybindingsManager;\n },\n ) {\n this.items = timelineSelectItems(turns, options.activeDisplayIndex);\n this.list = new SearchableSelectList(\n this.items,\n Math.min(14, Math.max(1, this.items.length)),\n searchableSelectListTheme,\n {\n searchPromptText: 'timeline: ',\n wrapNavigation: true,\n ...(options.initialQuery ? { initialQuery: options.initialQuery } : {}),\n },\n );\n this.list.onSelect = (item) => {\n const turn = (item as TimelineSelectItem).turn;\n if (turn) this.onSelect?.(turn);\n };\n this.list.onCancel = () => this.onCancel?.();\n\n const activeItem = this.items.find((item) => item.description?.includes('current'));\n if (activeItem) this.list.setSelectedValue(activeItem.value);\n }\n\n get focused(): boolean {\n return this.list.focused;\n }\n\n set focused(value: boolean) {\n this.list.focused = value;\n }\n\n invalidate(): void {\n this.list.invalidate();\n }\n\n render(width: number): string[] {\n const count = this.items.length;\n return [\n theme.dim(`Timeline · ${count} turn${count === 1 ? '' : 's'}`),\n '',\n ...this.list.render(width),\n ];\n }\n\n handleInput(keyData: string): void {\n this.list.handleInput(keyData);\n }\n}\n"],"mappings":";;;;;AAoBA,SAAS,WAAW,WAA4B;AAC9C,KAAI,cAAc,KAAA,EAAW,QAAO;CACpC,MAAM,OAAO,IAAI,KAAK,UAAU;AAChC,KAAI,OAAO,MAAM,KAAK,SAAS,CAAC,CAAE,QAAO;AACzC,QAAO,IAAI,KAAK,eAAe,KAAA,GAAW;EACxC,MAAM;EACN,QAAQ;EACT,CAAC,CAAC,OAAO,KAAK;;AAGjB,SAAS,oBACP,OACA,oBACsB;CACtB,MAAM,aAAa,uBAAuB,KAAA,IACtC,KAAA,IACA,CAAC,GAAG,MAAM,CAAC,SAAS,CAAC,MAAM,SAAS,KAAK,gBAAgB,mBAAmB;AAEhF,QAAO,MAAM,KAAK,SAAS;EACzB,MAAM,UAAU,YAAY,OAAO,KAAK;EACxC,MAAM,cAAc;GAClB,0BAA0B,KAAK,UAAU;GACzC,WAAW,KAAK,UAAU;GAC1B,KAAK,UAAU,YAAY;GAC3B,UAAU,YAAY;GACvB,CAAC,OAAO,QAAQ,CAAC,KAAK,MAAM;AAC7B,SAAO;GACL,OAAO,KAAK;GACZ,OAAO,GAAG,OAAO,KAAK,KAAK,CAAC,SAAS,GAAG,IAAI,CAAC,IAAI,KAAK;GACtD;GACA,YAAY,GAAG,KAAK,KAAK,GAAG,KAAK,QAAQ,GAAG;GAC5C;GACD;GACD;;AAGJ,SAAgB,yBAAyB,aAAyC;AAKhF,QAAO,aAJI,aAAa,aAAa,iBAAiB,EAAE,YAAY,MAAM,CAIpD,CAAC,GAHV,aAAa,aAAa,mBAAmB,EAAE,YAAY,MAAM,CAGhD,CAAC,sBAFf,aAAa,aAAa,sBAAsB,EAAE,YAAY,MAAM,CAExB,CAAC,UAD9C,aAAa,aAAa,qBAAqB,EAAE,YAAY,MAAM,CACL,CAAC;;AAGhF,IAAa,qBAAb,MAAgE;CAC9D;CACA;CAEA;CACA;CAEA,YACE,OACA,SAKA;AACA,OAAK,QAAQ,oBAAoB,OAAO,QAAQ,mBAAmB;AACnE,OAAK,OAAO,IAAI,qBACd,KAAK,OACL,KAAK,IAAI,IAAI,KAAK,IAAI,GAAG,KAAK,MAAM,OAAO,CAAC,EAC5C,2BACA;GACE,kBAAkB;GAClB,gBAAgB;GAChB,GAAI,QAAQ,eAAe,EAAE,cAAc,QAAQ,cAAc,GAAG,EAAE;GACvE,CACF;AACD,OAAK,KAAK,YAAY,SAAS;GAC7B,MAAM,OAAQ,KAA4B;AAC1C,OAAI,KAAM,MAAK,WAAW,KAAK;;AAEjC,OAAK,KAAK,iBAAiB,KAAK,YAAY;EAE5C,MAAM,aAAa,KAAK,MAAM,MAAM,SAAS,KAAK,aAAa,SAAS,UAAU,CAAC;AACnF,MAAI,WAAY,MAAK,KAAK,iBAAiB,WAAW,MAAM;;CAG9D,IAAI,UAAmB;AACrB,SAAO,KAAK,KAAK;;CAGnB,IAAI,QAAQ,OAAgB;AAC1B,OAAK,KAAK,UAAU;;CAGtB,aAAmB;AACjB,OAAK,KAAK,YAAY;;CAGxB,OAAO,OAAyB;EAC9B,MAAM,QAAQ,KAAK,MAAM;AACzB,SAAO;GACL,MAAM,IAAI,cAAc,MAAM,OAAO,UAAU,IAAI,KAAK,MAAM;GAC9D;GACA,GAAG,KAAK,KAAK,OAAO,MAAM;GAC3B;;CAGH,YAAY,SAAuB;AACjC,OAAK,KAAK,YAAY,QAAQ"}