@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
@@ -40,6 +40,7 @@ function appendHistoryToChatLog(chatLog, messages, toolsExpanded, showThinking =
40
40
  chatLog.setShowThinking(showThinking);
41
41
  messages.forEach((hm, idx) => {
42
42
  const historyIndex = (opts?.startIndex ?? 0) + idx;
43
+ const displayIndex = hm.displayIndex ?? historyIndex;
43
44
  const runId = `history:${historyIndex}`;
44
45
  if (hm.kind === "bash") {
45
46
  if (hm.bash) chatLog.addBashSummary(hm.bash);
@@ -76,14 +77,26 @@ function appendHistoryToChatLog(chatLog, messages, toolsExpanded, showThinking =
76
77
  return;
77
78
  }
78
79
  if (hm.role === "user") {
79
- chatLog.addUser(historyContentText(hm.content));
80
+ chatLog.addUser(historyContentText(hm.content), {
81
+ displayIndex,
82
+ historyIndex,
83
+ role: "user"
84
+ });
80
85
  return;
81
86
  }
82
87
  if (hm.role === "system") {
83
- chatLog.addSystem(historyContentText(hm.content));
88
+ chatLog.addSystem(historyContentText(hm.content), {
89
+ displayIndex,
90
+ historyIndex,
91
+ role: "system"
92
+ });
84
93
  return;
85
94
  }
86
- chatLog.finalizeAssistant(assistantHistoryMessage(hm.content), runId);
95
+ chatLog.finalizeAssistant(assistantHistoryMessage(hm.content), runId, {
96
+ displayIndex,
97
+ historyIndex,
98
+ role: "assistant"
99
+ });
87
100
  const tools = hm.toolCalls ?? [];
88
101
  for (let t = 0; t < tools.length; t++) {
89
102
  const tc = tools[t];
@@ -1 +1 @@
1
- {"version":3,"file":"chat-history.js","names":[],"sources":["../../../src/tui/chat-history.ts"],"sourcesContent":["import type { AgentMessage } from '@earendil-works/pi-agent-core';\n\nimport type { HistoryMessage } from './tui-backend.js';\nimport { ChatLog } from './components/chat-log.js';\nimport { createAssistantMessageFromText } from './components/assistant-message.js';\n\nexport function historyMessageKey(message: HistoryMessage, index: number): string {\n if (message.id) return `id:${message.id}`;\n return [\n 'fallback',\n index,\n message.kind ?? 'message',\n message.role,\n message.timestamp ?? '',\n JSON.stringify(message.content),\n ].join(':');\n}\n\nfunction historyContentText(content: unknown): string {\n if (typeof content === 'string') return content;\n if (!Array.isArray(content)) return '';\n return content\n .map((block) => {\n if (!block || typeof block !== 'object') return '';\n const rec = block as { type?: unknown; text?: unknown; thinking?: unknown };\n if (rec.type === 'text' && typeof rec.text === 'string') return rec.text;\n if (rec.type === 'thinking' && typeof rec.thinking === 'string') return rec.thinking;\n return '';\n })\n .filter(Boolean)\n .join('\\n');\n}\n\nfunction assistantHistoryMessage(content: unknown): AgentMessage {\n if (typeof content === 'string') {\n return createAssistantMessageFromText(content.trim() ? content : ' ');\n }\n if (Array.isArray(content)) {\n return {\n role: 'assistant',\n content,\n timestamp: Date.now(),\n } as AgentMessage;\n }\n return createAssistantMessageFromText(' ');\n}\n\nexport function historyKeysHaveAppendOnlyPrefix(\n previousKeys: readonly string[],\n nextKeys: readonly string[],\n): boolean {\n return (\n previousKeys.length > 0 &&\n previousKeys.length <= nextKeys.length &&\n previousKeys.every((key, index) => nextKeys[index] === key)\n );\n}\n\n/** Replay persisted transcript into the scroll log (synthetic run ids per assistant row). */\nexport function appendHistoryToChatLog(\n chatLog: ChatLog,\n messages: HistoryMessage[],\n toolsExpanded: boolean,\n showThinking = true,\n opts?: { startIndex?: number },\n): void {\n chatLog.setToolsExpanded(toolsExpanded);\n chatLog.setShowThinking(showThinking);\n\n messages.forEach((hm, idx) => {\n const historyIndex = (opts?.startIndex ?? 0) + idx;\n const runId = `history:${historyIndex}`;\n\n if (hm.kind === 'bash') {\n if (hm.bash) {\n chatLog.addBashSummary(hm.bash);\n } else {\n chatLog.addSystem(historyContentText(hm.content));\n }\n return;\n }\n\n if (hm.kind === 'custom') {\n if (hm.custom) {\n if (hm.custom.state) return;\n if (hm.custom.display === false) return;\n chatLog.addCustomMessage({\n customType: hm.custom.customType,\n content: historyContentText(hm.content),\n rawContent: hm.rawContent,\n details: hm.custom.details,\n display: hm.custom.display,\n });\n } else {\n chatLog.addSystem(historyContentText(hm.content));\n }\n return;\n }\n\n if (hm.kind === 'branch') {\n if (hm.branch) {\n chatLog.addBranchMessageSummary(hm.branch);\n } else {\n chatLog.addSystem(historyContentText(hm.content));\n }\n return;\n }\n\n if (hm.kind === 'compaction') {\n chatLog.addCompactionSummary({\n compacted: true,\n summary: historyContentText(hm.content),\n tokensBefore: hm.tokensBefore,\n tokensAfter: hm.tokensAfter,\n transcriptSummary: historyContentText(hm.content),\n });\n return;\n }\n\n if (hm.role === 'user') {\n chatLog.addUser(historyContentText(hm.content));\n return;\n }\n\n if (hm.role === 'system') {\n chatLog.addSystem(historyContentText(hm.content));\n return;\n }\n\n chatLog.finalizeAssistant(assistantHistoryMessage(hm.content), runId);\n\n const tools = hm.toolCalls ?? [];\n for (let t = 0; t < tools.length; t++) {\n const tc = tools[t]!;\n const tid = `history:${historyIndex}:t:${t}`;\n chatLog.startTool(tid, tc.name, tc.args ?? {}, runId);\n if (tc.result !== undefined) {\n chatLog.updateToolResult(tid, tc.result, tc.isError ?? false);\n }\n }\n });\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"chat-history.js","names":[],"sources":["../../../src/tui/chat-history.ts"],"sourcesContent":["import type { AgentMessage } from '@earendil-works/pi-agent-core';\n\nimport type { HistoryMessage } from './tui-backend.js';\nimport { ChatLog } from './components/chat-log.js';\nimport { createAssistantMessageFromText } from './components/assistant-message.js';\n\nexport function historyMessageKey(message: HistoryMessage, index: number): string {\n if (message.id) return `id:${message.id}`;\n return [\n 'fallback',\n index,\n message.kind ?? 'message',\n message.role,\n message.timestamp ?? '',\n JSON.stringify(message.content),\n ].join(':');\n}\n\nfunction historyContentText(content: unknown): string {\n if (typeof content === 'string') return content;\n if (!Array.isArray(content)) return '';\n return content\n .map((block) => {\n if (!block || typeof block !== 'object') return '';\n const rec = block as { type?: unknown; text?: unknown; thinking?: unknown };\n if (rec.type === 'text' && typeof rec.text === 'string') return rec.text;\n if (rec.type === 'thinking' && typeof rec.thinking === 'string') return rec.thinking;\n return '';\n })\n .filter(Boolean)\n .join('\\n');\n}\n\nfunction assistantHistoryMessage(content: unknown): AgentMessage {\n if (typeof content === 'string') {\n return createAssistantMessageFromText(content.trim() ? content : ' ');\n }\n if (Array.isArray(content)) {\n return {\n role: 'assistant',\n content,\n timestamp: Date.now(),\n } as AgentMessage;\n }\n return createAssistantMessageFromText(' ');\n}\n\nexport function historyKeysHaveAppendOnlyPrefix(\n previousKeys: readonly string[],\n nextKeys: readonly string[],\n): boolean {\n return (\n previousKeys.length > 0 &&\n previousKeys.length <= nextKeys.length &&\n previousKeys.every((key, index) => nextKeys[index] === key)\n );\n}\n\n/** Replay persisted transcript into the scroll log (synthetic run ids per assistant row). */\nexport function appendHistoryToChatLog(\n chatLog: ChatLog,\n messages: HistoryMessage[],\n toolsExpanded: boolean,\n showThinking = true,\n opts?: { startIndex?: number },\n): void {\n chatLog.setToolsExpanded(toolsExpanded);\n chatLog.setShowThinking(showThinking);\n\n messages.forEach((hm, idx) => {\n const historyIndex = (opts?.startIndex ?? 0) + idx;\n const displayIndex = hm.displayIndex ?? historyIndex;\n const runId = `history:${historyIndex}`;\n\n if (hm.kind === 'bash') {\n if (hm.bash) {\n chatLog.addBashSummary(hm.bash);\n } else {\n chatLog.addSystem(historyContentText(hm.content));\n }\n return;\n }\n\n if (hm.kind === 'custom') {\n if (hm.custom) {\n if (hm.custom.state) return;\n if (hm.custom.display === false) return;\n chatLog.addCustomMessage({\n customType: hm.custom.customType,\n content: historyContentText(hm.content),\n rawContent: hm.rawContent,\n details: hm.custom.details,\n display: hm.custom.display,\n });\n } else {\n chatLog.addSystem(historyContentText(hm.content));\n }\n return;\n }\n\n if (hm.kind === 'branch') {\n if (hm.branch) {\n chatLog.addBranchMessageSummary(hm.branch);\n } else {\n chatLog.addSystem(historyContentText(hm.content));\n }\n return;\n }\n\n if (hm.kind === 'compaction') {\n chatLog.addCompactionSummary({\n compacted: true,\n summary: historyContentText(hm.content),\n tokensBefore: hm.tokensBefore,\n tokensAfter: hm.tokensAfter,\n transcriptSummary: historyContentText(hm.content),\n });\n return;\n }\n\n if (hm.role === 'user') {\n chatLog.addUser(historyContentText(hm.content), {\n displayIndex,\n historyIndex,\n role: 'user',\n });\n return;\n }\n\n if (hm.role === 'system') {\n chatLog.addSystem(historyContentText(hm.content), {\n displayIndex,\n historyIndex,\n role: 'system',\n });\n return;\n }\n\n chatLog.finalizeAssistant(assistantHistoryMessage(hm.content), runId, {\n displayIndex,\n historyIndex,\n role: 'assistant',\n });\n\n const tools = hm.toolCalls ?? [];\n for (let t = 0; t < tools.length; t++) {\n const tc = tools[t]!;\n const tid = `history:${historyIndex}:t:${t}`;\n chatLog.startTool(tid, tc.name, tc.args ?? {}, runId);\n if (tc.result !== undefined) {\n chatLog.updateToolResult(tid, tc.result, tc.isError ?? false);\n }\n }\n });\n}\n"],"mappings":"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"}
@@ -1,8 +1,8 @@
1
1
  import { tmpdir } from "node:os";
2
2
  import { join } from "node:path";
3
3
  import { readFileSync, unlinkSync, writeFileSync } from "node:fs";
4
- import { randomUUID } from "node:crypto";
5
4
  import { spawnSync } from "node:child_process";
5
+ import { randomUUID } from "node:crypto";
6
6
  //#region src/tui/clipboard-image.ts
7
7
  const SUPPORTED_IMAGE_MIME_TYPES = [
8
8
  "image/png",
@@ -16,6 +16,16 @@ function blockText(block, key) {
16
16
  const value = block[key];
17
17
  return typeof value === "string" ? value : "";
18
18
  }
19
+ function compactToolAdjacentText(text, linkedToolCall) {
20
+ if (!linkedToolCall) return text;
21
+ return text.split("\n").filter((line) => !isMechanicalToolSummaryLine(line)).join("\n").trim();
22
+ }
23
+ function isMechanicalToolSummaryLine(line) {
24
+ const normalized = line.trim();
25
+ if (!normalized) return false;
26
+ const withoutBullet = normalized.replace(/^[-*•]\s+/, "");
27
+ return /^(Added|Deleted|Edited|Modified|Updated)\s+.+\(\+\d+\s+-\d+\)\.?$/i.test(withoutBullet) || /^Edited\s+\d+\s+files?\s+\(\+\d+\s+-\d+\)\.?$/i.test(withoutBullet) || /^Created\s+.+\(\+\d+\s+-0\)\.?$/i.test(withoutBullet) || /^Removed\s+.+\(\+0\s+-\d+\)\.?$/i.test(withoutBullet);
28
+ }
19
29
  function reviewMarkdown(block) {
20
30
  const findings = Array.isArray(block.findings) ? block.findings : [];
21
31
  const lines = ["Code review", ""];
@@ -109,7 +119,7 @@ var AssistantMessageComponent = class extends Container {
109
119
  this.contentContainer.clear();
110
120
  const blocks = contentBlocks(this.message);
111
121
  const visibleBlocks = blocks.filter((block) => {
112
- if (block.type === "text") return blockText(block, "text").trim().length > 0;
122
+ if (block.type === "text") return compactToolAdjacentText(blockText(block, "text"), this.linkedToolCall).trim().length > 0;
113
123
  if (block.type === "thinking") return blockText(block, "thinking").trim().length > 0;
114
124
  if (block.type === "image" || block.type === "image_url") return true;
115
125
  if (block.type === "review") return true;
@@ -123,7 +133,7 @@ var AssistantMessageComponent = class extends Container {
123
133
  for (let i = 0; i < blocks.length; i++) {
124
134
  const block = blocks[i];
125
135
  if (block.type === "text") {
126
- const text = blockText(block, "text").trim();
136
+ const text = compactToolAdjacentText(blockText(block, "text"), this.linkedToolCall).trim();
127
137
  if (!text) continue;
128
138
  if (renderedVisible > 0) this.contentContainer.addChild(new Spacer(1));
129
139
  this.contentContainer.addChild(new Markdown(text, 1, 0, markdownTheme, { color: (line) => theme.assistantText(line) }, { preserveOrderedListMarkers: true }));
@@ -1 +1 @@
1
- {"version":3,"file":"assistant-message.js","names":[],"sources":["../../../../src/tui/components/assistant-message.ts"],"sourcesContent":["import type { AgentMessage } from '@earendil-works/pi-agent-core';\nimport { Container, Markdown, Spacer, Text } from '@earendil-works/pi-tui';\n\nimport { markdownTheme, theme } from '../theme.js';\n\nconst OSC133_ZONE_START = '\\x1b]133;A\\x07';\nconst OSC133_ZONE_END = '\\x1b]133;B\\x07';\nconst OSC133_ZONE_FINAL = '\\x1b]133;C\\x07';\n\nexport type AssistantMessageOptions = {\n hideThinkingBlock?: boolean;\n hiddenThinkingLabel?: string;\n};\n\ntype ContentBlock = Record<string, unknown> & { type?: string };\n\nfunction contentBlocks(message: AgentMessage | undefined): ContentBlock[] {\n const content = (message as { content?: unknown } | undefined)?.content;\n if (typeof content === 'string') {\n return content.trim() ? [{ type: 'text', text: content }] : [];\n }\n return Array.isArray(content)\n ? content.filter((block): block is ContentBlock => !!block && typeof block === 'object')\n : [];\n}\n\nfunction blockText(block: ContentBlock, key: 'text' | 'thinking'): string {\n const value = block[key];\n return typeof value === 'string' ? value : '';\n}\n\nfunction reviewMarkdown(block: ContentBlock): string {\n const findings = Array.isArray(block.findings) ? block.findings : [];\n const lines: string[] = ['Code review', ''];\n if (findings.length === 0) {\n lines.push('No findings.');\n } else {\n lines.push('Findings:');\n for (const item of findings) {\n if (!item || typeof item !== 'object' || Array.isArray(item)) continue;\n const rec = item as Record<string, unknown>;\n const title = typeof rec.title === 'string' ? rec.title : '';\n const body = typeof rec.body === 'string' ? rec.body : '';\n const priority = typeof rec.priority === 'number' ? rec.priority : 2;\n const filePath = typeof rec.filePath === 'string' ? rec.filePath : '';\n const lineStart = typeof rec.lineStart === 'number' ? rec.lineStart : undefined;\n const lineEnd = typeof rec.lineEnd === 'number' ? rec.lineEnd : undefined;\n const loc = filePath\n ? `${filePath}${lineStart ? `:${lineStart}${lineEnd && lineEnd !== lineStart ? `-${lineEnd}` : ''}` : ''}`\n : '';\n const suffix = loc ? ` - ${loc}` : '';\n lines.push(`- [P${priority}] ${title || body.slice(0, 80)}${suffix}`);\n if (body) lines.push(` ${body.replace(/\\n+/g, '\\n ')}`);\n }\n }\n const correctness = typeof block.overallCorrectness === 'string' ? block.overallCorrectness : 'unknown';\n const explanation = typeof block.overallExplanation === 'string' ? block.overallExplanation : '';\n lines.push('');\n lines.push(`Overall correctness: ${correctness}`);\n if (explanation) lines.push(explanation);\n return lines.join('\\n');\n}\n\nfunction hasToolCalls(message: AgentMessage | undefined): boolean {\n return contentBlocks(message).some((block) => block.type === 'toolCall' || block.type === 'tool_use');\n}\n\nfunction stopReason(message: AgentMessage | undefined): string | undefined {\n return (message as { stopReason?: string } | undefined)?.stopReason;\n}\n\nfunction errorMessage(message: AgentMessage | undefined): string | undefined {\n return (message as { errorMessage?: string } | undefined)?.errorMessage;\n}\n\nexport function createAssistantMessageFromText(text: string): AgentMessage {\n return {\n role: 'assistant',\n content: [{ type: 'text', text }],\n timestamp: Date.now(),\n } as AgentMessage;\n}\n\nexport class AssistantMessageComponent extends Container {\n private readonly contentContainer = new Container();\n private message: AgentMessage | undefined;\n private linkedToolCall = false;\n private hideThinkingBlock = false;\n private hiddenThinkingLabel = 'Thinking...';\n\n constructor(message?: AgentMessage, options: AssistantMessageOptions = {}) {\n super();\n this.hideThinkingBlock = options.hideThinkingBlock ?? false;\n this.hiddenThinkingLabel = options.hiddenThinkingLabel ?? 'Thinking...';\n this.addChild(this.contentContainer);\n if (message) {\n this.updateContent(message);\n }\n }\n\n updateContent(message: AgentMessage): void {\n this.message = message;\n this.refresh();\n }\n\n setHasToolCalls(hasTools: boolean): void {\n this.linkedToolCall = hasTools;\n this.refresh();\n }\n\n setHideThinkingBlock(hide: boolean): void {\n if (this.hideThinkingBlock === hide) return;\n this.hideThinkingBlock = hide;\n this.refresh();\n }\n\n setHiddenThinkingLabel(label: string): void {\n if (this.hiddenThinkingLabel === label) return;\n this.hiddenThinkingLabel = label;\n this.refresh();\n }\n\n override invalidate(): void {\n super.invalidate();\n this.refresh();\n }\n\n override render(width: number): string[] {\n const lines = super.render(width);\n if (hasToolCalls(this.message) || this.linkedToolCall || lines.length === 0) return lines;\n lines[0] = OSC133_ZONE_START + lines[0];\n lines[lines.length - 1] = OSC133_ZONE_END + OSC133_ZONE_FINAL + lines[lines.length - 1];\n return lines;\n }\n\n private refresh(): void {\n this.contentContainer.clear();\n const blocks = contentBlocks(this.message);\n const visibleBlocks = blocks.filter((block) => {\n if (block.type === 'text') return blockText(block, 'text').trim().length > 0;\n if (block.type === 'thinking') return blockText(block, 'thinking').trim().length > 0;\n if (block.type === 'image' || block.type === 'image_url') return true;\n if (block.type === 'review') return true;\n return false;\n });\n const reason = stopReason(this.message);\n const hasErrorState =\n !hasToolCalls(this.message) && !this.linkedToolCall && (reason === 'aborted' || reason === 'error');\n if (visibleBlocks.length === 0 && !hasErrorState) return;\n\n this.contentContainer.addChild(new Spacer(1));\n let renderedVisible = 0;\n for (let i = 0; i < blocks.length; i++) {\n const block = blocks[i]!;\n if (block.type === 'text') {\n const text = blockText(block, 'text').trim();\n if (!text) continue;\n if (renderedVisible > 0) this.contentContainer.addChild(new Spacer(1));\n this.contentContainer.addChild(\n new Markdown(\n text,\n 1,\n 0,\n markdownTheme,\n { color: (line) => theme.assistantText(line) },\n { preserveOrderedListMarkers: true },\n ),\n );\n renderedVisible++;\n } else if (block.type === 'thinking') {\n const thinking = blockText(block, 'thinking').trim();\n if (!thinking) continue;\n if (renderedVisible > 0) this.contentContainer.addChild(new Spacer(1));\n const text = this.hideThinkingBlock ? this.hiddenThinkingLabel : thinking;\n this.contentContainer.addChild(\n new Markdown(\n text,\n 1,\n 0,\n markdownTheme,\n { color: (line) => theme.dim(theme.italic(line)) },\n { preserveOrderedListMarkers: true },\n ),\n );\n renderedVisible++;\n } else if (block.type === 'image' || block.type === 'image_url') {\n if (renderedVisible > 0) this.contentContainer.addChild(new Spacer(1));\n this.contentContainer.addChild(new Text(theme.dim('[image]'), 1, 0));\n renderedVisible++;\n } else if (block.type === 'review') {\n const text = reviewMarkdown(block).trim();\n if (!text) continue;\n if (renderedVisible > 0) this.contentContainer.addChild(new Spacer(1));\n this.contentContainer.addChild(\n new Markdown(\n text,\n 1,\n 0,\n markdownTheme,\n { color: (line) => theme.assistantText(line) },\n { preserveOrderedListMarkers: true },\n ),\n );\n renderedVisible++;\n }\n }\n\n if (hasErrorState) {\n if (renderedVisible > 0) this.contentContainer.addChild(new Spacer(1));\n const text =\n reason === 'aborted'\n ? errorMessage(this.message) && errorMessage(this.message) !== 'Request was aborted'\n ? errorMessage(this.message)!\n : 'Operation aborted'\n : `Error: ${errorMessage(this.message) || 'Unknown error'}`;\n this.contentContainer.addChild(new Text(theme.error(text), 1, 0));\n }\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"assistant-message.js","names":[],"sources":["../../../../src/tui/components/assistant-message.ts"],"sourcesContent":["import type { AgentMessage } from '@earendil-works/pi-agent-core';\nimport { Container, Markdown, Spacer, Text } from '@earendil-works/pi-tui';\n\nimport { markdownTheme, theme } from '../theme.js';\n\nconst OSC133_ZONE_START = '\\x1b]133;A\\x07';\nconst OSC133_ZONE_END = '\\x1b]133;B\\x07';\nconst OSC133_ZONE_FINAL = '\\x1b]133;C\\x07';\n\nexport type AssistantMessageOptions = {\n hideThinkingBlock?: boolean;\n hiddenThinkingLabel?: string;\n};\n\ntype ContentBlock = Record<string, unknown> & { type?: string };\n\nfunction contentBlocks(message: AgentMessage | undefined): ContentBlock[] {\n const content = (message as { content?: unknown } | undefined)?.content;\n if (typeof content === 'string') {\n return content.trim() ? [{ type: 'text', text: content }] : [];\n }\n return Array.isArray(content)\n ? content.filter((block): block is ContentBlock => !!block && typeof block === 'object')\n : [];\n}\n\nfunction blockText(block: ContentBlock, key: 'text' | 'thinking'): string {\n const value = block[key];\n return typeof value === 'string' ? value : '';\n}\n\nfunction compactToolAdjacentText(text: string, linkedToolCall: boolean): string {\n if (!linkedToolCall) return text;\n const lines = text.split('\\n');\n const kept = lines.filter((line) => !isMechanicalToolSummaryLine(line));\n return kept.join('\\n').trim();\n}\n\nfunction isMechanicalToolSummaryLine(line: string): boolean {\n const normalized = line.trim();\n if (!normalized) return false;\n const withoutBullet = normalized.replace(/^[-*•]\\s+/, '');\n return (\n /^(Added|Deleted|Edited|Modified|Updated)\\s+.+\\(\\+\\d+\\s+-\\d+\\)\\.?$/i.test(withoutBullet) ||\n /^Edited\\s+\\d+\\s+files?\\s+\\(\\+\\d+\\s+-\\d+\\)\\.?$/i.test(withoutBullet) ||\n /^Created\\s+.+\\(\\+\\d+\\s+-0\\)\\.?$/i.test(withoutBullet) ||\n /^Removed\\s+.+\\(\\+0\\s+-\\d+\\)\\.?$/i.test(withoutBullet)\n );\n}\n\nfunction reviewMarkdown(block: ContentBlock): string {\n const findings = Array.isArray(block.findings) ? block.findings : [];\n const lines: string[] = ['Code review', ''];\n if (findings.length === 0) {\n lines.push('No findings.');\n } else {\n lines.push('Findings:');\n for (const item of findings) {\n if (!item || typeof item !== 'object' || Array.isArray(item)) continue;\n const rec = item as Record<string, unknown>;\n const title = typeof rec.title === 'string' ? rec.title : '';\n const body = typeof rec.body === 'string' ? rec.body : '';\n const priority = typeof rec.priority === 'number' ? rec.priority : 2;\n const filePath = typeof rec.filePath === 'string' ? rec.filePath : '';\n const lineStart = typeof rec.lineStart === 'number' ? rec.lineStart : undefined;\n const lineEnd = typeof rec.lineEnd === 'number' ? rec.lineEnd : undefined;\n const loc = filePath\n ? `${filePath}${lineStart ? `:${lineStart}${lineEnd && lineEnd !== lineStart ? `-${lineEnd}` : ''}` : ''}`\n : '';\n const suffix = loc ? ` - ${loc}` : '';\n lines.push(`- [P${priority}] ${title || body.slice(0, 80)}${suffix}`);\n if (body) lines.push(` ${body.replace(/\\n+/g, '\\n ')}`);\n }\n }\n const correctness = typeof block.overallCorrectness === 'string' ? block.overallCorrectness : 'unknown';\n const explanation = typeof block.overallExplanation === 'string' ? block.overallExplanation : '';\n lines.push('');\n lines.push(`Overall correctness: ${correctness}`);\n if (explanation) lines.push(explanation);\n return lines.join('\\n');\n}\n\nfunction hasToolCalls(message: AgentMessage | undefined): boolean {\n return contentBlocks(message).some((block) => block.type === 'toolCall' || block.type === 'tool_use');\n}\n\nfunction stopReason(message: AgentMessage | undefined): string | undefined {\n return (message as { stopReason?: string } | undefined)?.stopReason;\n}\n\nfunction errorMessage(message: AgentMessage | undefined): string | undefined {\n return (message as { errorMessage?: string } | undefined)?.errorMessage;\n}\n\nexport function createAssistantMessageFromText(text: string): AgentMessage {\n return {\n role: 'assistant',\n content: [{ type: 'text', text }],\n timestamp: Date.now(),\n } as AgentMessage;\n}\n\nexport class AssistantMessageComponent extends Container {\n private readonly contentContainer = new Container();\n private message: AgentMessage | undefined;\n private linkedToolCall = false;\n private hideThinkingBlock = false;\n private hiddenThinkingLabel = 'Thinking...';\n\n constructor(message?: AgentMessage, options: AssistantMessageOptions = {}) {\n super();\n this.hideThinkingBlock = options.hideThinkingBlock ?? false;\n this.hiddenThinkingLabel = options.hiddenThinkingLabel ?? 'Thinking...';\n this.addChild(this.contentContainer);\n if (message) {\n this.updateContent(message);\n }\n }\n\n updateContent(message: AgentMessage): void {\n this.message = message;\n this.refresh();\n }\n\n setHasToolCalls(hasTools: boolean): void {\n this.linkedToolCall = hasTools;\n this.refresh();\n }\n\n setHideThinkingBlock(hide: boolean): void {\n if (this.hideThinkingBlock === hide) return;\n this.hideThinkingBlock = hide;\n this.refresh();\n }\n\n setHiddenThinkingLabel(label: string): void {\n if (this.hiddenThinkingLabel === label) return;\n this.hiddenThinkingLabel = label;\n this.refresh();\n }\n\n override invalidate(): void {\n super.invalidate();\n this.refresh();\n }\n\n override render(width: number): string[] {\n const lines = super.render(width);\n if (hasToolCalls(this.message) || this.linkedToolCall || lines.length === 0) return lines;\n lines[0] = OSC133_ZONE_START + lines[0];\n lines[lines.length - 1] = OSC133_ZONE_END + OSC133_ZONE_FINAL + lines[lines.length - 1];\n return lines;\n }\n\n private refresh(): void {\n this.contentContainer.clear();\n const blocks = contentBlocks(this.message);\n const visibleBlocks = blocks.filter((block) => {\n if (block.type === 'text') {\n return compactToolAdjacentText(blockText(block, 'text'), this.linkedToolCall).trim().length > 0;\n }\n if (block.type === 'thinking') return blockText(block, 'thinking').trim().length > 0;\n if (block.type === 'image' || block.type === 'image_url') return true;\n if (block.type === 'review') return true;\n return false;\n });\n const reason = stopReason(this.message);\n const hasErrorState =\n !hasToolCalls(this.message) && !this.linkedToolCall && (reason === 'aborted' || reason === 'error');\n if (visibleBlocks.length === 0 && !hasErrorState) return;\n\n this.contentContainer.addChild(new Spacer(1));\n let renderedVisible = 0;\n for (let i = 0; i < blocks.length; i++) {\n const block = blocks[i]!;\n if (block.type === 'text') {\n const text = compactToolAdjacentText(blockText(block, 'text'), this.linkedToolCall).trim();\n if (!text) continue;\n if (renderedVisible > 0) this.contentContainer.addChild(new Spacer(1));\n this.contentContainer.addChild(\n new Markdown(\n text,\n 1,\n 0,\n markdownTheme,\n { color: (line) => theme.assistantText(line) },\n { preserveOrderedListMarkers: true },\n ),\n );\n renderedVisible++;\n } else if (block.type === 'thinking') {\n const thinking = blockText(block, 'thinking').trim();\n if (!thinking) continue;\n if (renderedVisible > 0) this.contentContainer.addChild(new Spacer(1));\n const text = this.hideThinkingBlock ? this.hiddenThinkingLabel : thinking;\n this.contentContainer.addChild(\n new Markdown(\n text,\n 1,\n 0,\n markdownTheme,\n { color: (line) => theme.dim(theme.italic(line)) },\n { preserveOrderedListMarkers: true },\n ),\n );\n renderedVisible++;\n } else if (block.type === 'image' || block.type === 'image_url') {\n if (renderedVisible > 0) this.contentContainer.addChild(new Spacer(1));\n this.contentContainer.addChild(new Text(theme.dim('[image]'), 1, 0));\n renderedVisible++;\n } else if (block.type === 'review') {\n const text = reviewMarkdown(block).trim();\n if (!text) continue;\n if (renderedVisible > 0) this.contentContainer.addChild(new Spacer(1));\n this.contentContainer.addChild(\n new Markdown(\n text,\n 1,\n 0,\n markdownTheme,\n { color: (line) => theme.assistantText(line) },\n { preserveOrderedListMarkers: true },\n ),\n );\n renderedVisible++;\n }\n }\n\n if (hasErrorState) {\n if (renderedVisible > 0) this.contentContainer.addChild(new Spacer(1));\n const text =\n reason === 'aborted'\n ? errorMessage(this.message) && errorMessage(this.message) !== 'Request was aborted'\n ? errorMessage(this.message)!\n : 'Operation aborted'\n : `Error: ${errorMessage(this.message) || 'Unknown error'}`;\n this.contentContainer.addChild(new Text(theme.error(text), 1, 0));\n }\n }\n}\n"],"mappings":"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"}
@@ -8,6 +8,12 @@ import { type CustomMessageSummary } from './custom-message.js';
8
8
  import type { TuiMessageRenderer } from '../../extensions/types/tui.js';
9
9
  import { type ToolExecutionOptions } from './tool-execution.js';
10
10
  import type { TuiBranchSummary, TuiCompactionResult } from '../tui-backend.js';
11
+ export type ChatLogEntryMeta = {
12
+ displayIndex?: number;
13
+ historyIndex?: number;
14
+ rowNumber?: number;
15
+ role?: 'user' | 'assistant' | 'system';
16
+ };
11
17
  export declare class ChatLog extends Container {
12
18
  private readonly keybindings?;
13
19
  private toolById;
@@ -30,13 +36,16 @@ export declare class ChatLog extends Container {
30
36
  private lastStatusEntry;
31
37
  private lastStatusText;
32
38
  private workflowStatusByRunId;
39
+ private entryRecords;
40
+ private viewportRowsProvider;
41
+ private historyViewDisplayIndex;
33
42
  constructor(keybindings?: KeybindingsManager);
34
43
  private pruneOverflow;
35
44
  private dropReferences;
36
45
  private append;
37
46
  clearAll(): void;
38
47
  private createAssistantMessage;
39
- addSystem(text: string): void;
48
+ addSystem(text: string, meta?: ChatLogEntryMeta): void;
40
49
  addStatus(text: string): void;
41
50
  updateWorkflowRun(runId: string, text: string): void;
42
51
  addCompactionSummary(result: TuiCompactionResult): void;
@@ -44,14 +53,14 @@ export declare class ChatLog extends Container {
44
53
  addBranchMessageSummary(summary: BranchMessageSummary): void;
45
54
  addCustomMessage(summary: CustomMessageSummary): void;
46
55
  setCustomMessageRenderer(customType: string, renderer: TuiMessageRenderer | undefined): void;
47
- addUser(text: string | unknown[]): void;
56
+ addUser(text: string | unknown[], meta?: ChatLogEntryMeta): void;
48
57
  /** Stream local `!command` output in a bordered block. */
49
58
  addBashExecution(command: string, ui: import('@earendil-works/pi-tui').TUI, excludeFromContext: boolean): BashExecutionComponent;
50
59
  /** Replay a completed shell execution from persisted transcript history. */
51
60
  addBashSummary(summary: BashSummary): void;
52
61
  startAssistant(message: AgentMessage, runId: string): void;
53
62
  updateAssistant(message: AgentMessage, runId: string): void;
54
- finalizeAssistant(message: AgentMessage, runId: string): void;
63
+ finalizeAssistant(message: AgentMessage, runId: string, meta?: ChatLogEntryMeta): void;
55
64
  dropAssistant(runId: string): void;
56
65
  startTool(toolCallId: string, toolName: string, args: unknown, runId: string): void;
57
66
  markToolExecutionStarted(toolCallId: string): void;
@@ -64,4 +73,15 @@ export declare class ChatLog extends Container {
64
73
  setHiddenThinkingLabel(label?: string): void;
65
74
  setToolImageOptions(options: ToolExecutionOptions): void;
66
75
  getLastAssistantText(): string;
76
+ setViewportRowsProvider(provider: (() => number) | undefined): void;
77
+ jumpToDisplayIndex(displayIndex: number): boolean;
78
+ jumpToLatest(): void;
79
+ getTimelineViewportState(): {
80
+ mode: 'latest';
81
+ } | {
82
+ mode: 'history';
83
+ displayIndex: number;
84
+ };
85
+ render(width: number): string[];
86
+ private findEntryRecord;
67
87
  }
@@ -42,6 +42,9 @@ var ChatLog = class extends Container {
42
42
  lastStatusEntry = null;
43
43
  lastStatusText = null;
44
44
  workflowStatusByRunId = /* @__PURE__ */ new Map();
45
+ entryRecords = [];
46
+ viewportRowsProvider;
47
+ historyViewDisplayIndex = null;
45
48
  constructor(keybindings) {
46
49
  super();
47
50
  this.keybindings = keybindings;
@@ -70,9 +73,15 @@ var ChatLog = class extends Container {
70
73
  this.lastStatusText = null;
71
74
  }
72
75
  for (const [runId, status] of this.workflowStatusByRunId.entries()) if (status.entry === component) this.workflowStatusByRunId.delete(runId);
76
+ this.entryRecords = this.entryRecords.filter((entry) => entry.component !== component);
77
+ if (!this.findEntryRecord(this.historyViewDisplayIndex)) this.historyViewDisplayIndex = null;
73
78
  }
74
- append(component) {
79
+ append(component, meta) {
75
80
  this.addChild(component);
81
+ if (meta) this.entryRecords.push({
82
+ component,
83
+ ...meta
84
+ });
76
85
  this.pruneOverflow();
77
86
  }
78
87
  clearAll() {
@@ -91,6 +100,8 @@ var ChatLog = class extends Container {
91
100
  this.lastStatusEntry = null;
92
101
  this.lastStatusText = null;
93
102
  this.workflowStatusByRunId.clear();
103
+ this.entryRecords = [];
104
+ this.historyViewDisplayIndex = null;
94
105
  }
95
106
  createAssistantMessage(message) {
96
107
  const component = new AssistantMessageComponent(message, {
@@ -100,11 +111,11 @@ var ChatLog = class extends Container {
100
111
  this.assistantMessages.push(component);
101
112
  return component;
102
113
  }
103
- addSystem(text) {
114
+ addSystem(text, meta) {
104
115
  const entry = new Container();
105
116
  entry.addChild(new Spacer(1));
106
117
  entry.addChild(new Text(theme.system(text), 1, 0));
107
- this.append(entry);
118
+ this.append(entry, meta);
108
119
  }
109
120
  addStatus(text) {
110
121
  if (this.lastStatusEntry && this.lastStatusText && this.children[this.children.length - 1] === this.lastStatusEntry) {
@@ -166,9 +177,9 @@ var ChatLog = class extends Container {
166
177
  else this.customMessageRenderers.delete(customType);
167
178
  for (const block of this.customBlocks) if (block.matchesCustomType(customType)) block.setRenderer(renderer);
168
179
  }
169
- addUser(text) {
180
+ addUser(text, meta) {
170
181
  this.assistantAnchorByRunId.clear();
171
- this.append(new UserMessageComponent(text));
182
+ this.append(new UserMessageComponent(text), meta);
172
183
  }
173
184
  /** Stream local `!command` output in a bordered block. */
174
185
  addBashExecution(command, ui, excludeFromContext) {
@@ -212,7 +223,7 @@ var ChatLog = class extends Container {
212
223
  existing.updateContent(message);
213
224
  existing.setHasToolCalls(this.runsWithTools.has(runId));
214
225
  }
215
- finalizeAssistant(message, runId) {
226
+ finalizeAssistant(message, runId, meta) {
216
227
  const text = assistantPlainText(message);
217
228
  if (text.trim()) this.lastAssistantText = text;
218
229
  const existing = this.streamingRuns.get(runId);
@@ -225,7 +236,7 @@ var ChatLog = class extends Container {
225
236
  }
226
237
  const finalMessage = this.createAssistantMessage(message);
227
238
  finalMessage.setHasToolCalls(this.runsWithTools.has(runId));
228
- this.append(finalMessage);
239
+ this.append(finalMessage, meta);
229
240
  if (text.trim()) this.assistantAnchorByRunId.set(runId, finalMessage);
230
241
  }
231
242
  dropAssistant(runId) {
@@ -245,8 +256,7 @@ var ChatLog = class extends Container {
245
256
  component.setExpanded(this.toolsExpanded);
246
257
  this.toolById.set(toolCallId, component);
247
258
  (this.streamingRuns.get(runId) ?? this.assistantAnchorByRunId.get(runId))?.setHasToolCalls(true);
248
- this.addChild(component);
249
- this.pruneOverflow();
259
+ this.append(component);
250
260
  }
251
261
  markToolExecutionStarted(toolCallId) {
252
262
  const existing = this.toolById.get(toolCallId);
@@ -300,6 +310,55 @@ var ChatLog = class extends Container {
300
310
  getLastAssistantText() {
301
311
  return this.lastAssistantText;
302
312
  }
313
+ setViewportRowsProvider(provider) {
314
+ this.viewportRowsProvider = provider;
315
+ }
316
+ jumpToDisplayIndex(displayIndex) {
317
+ const target = this.findEntryRecord(displayIndex);
318
+ if (!target) return false;
319
+ this.historyViewDisplayIndex = target.displayIndex ?? null;
320
+ return true;
321
+ }
322
+ jumpToLatest() {
323
+ this.historyViewDisplayIndex = null;
324
+ }
325
+ getTimelineViewportState() {
326
+ if (this.historyViewDisplayIndex === null) return { mode: "latest" };
327
+ return {
328
+ mode: "history",
329
+ displayIndex: this.historyViewDisplayIndex
330
+ };
331
+ }
332
+ render(width) {
333
+ const allLines = [];
334
+ const ranges = [];
335
+ for (const child of this.children) {
336
+ const start = allLines.length;
337
+ const childLines = child.render(width);
338
+ allLines.push(...childLines);
339
+ const record = this.entryRecords.find((entry) => entry.component === child);
340
+ if (record) ranges.push({
341
+ record,
342
+ start,
343
+ end: allLines.length
344
+ });
345
+ }
346
+ if (this.historyViewDisplayIndex === null) return allLines;
347
+ const target = this.findEntryRecord(this.historyViewDisplayIndex);
348
+ const range = target ? ranges.find((candidate) => candidate.record.component === target.component) : void 0;
349
+ if (!range) {
350
+ this.historyViewDisplayIndex = null;
351
+ return allLines;
352
+ }
353
+ const viewportRows = Math.max(8, Math.floor(this.viewportRowsProvider?.() ?? 24));
354
+ const start = Math.max(0, range.start - 1);
355
+ const end = Math.min(allLines.length, start + Math.max(1, viewportRows - 1));
356
+ return [theme.dim("Viewing previous transcript - /timeline latest returns to live view."), ...allLines.slice(start, end)];
357
+ }
358
+ findEntryRecord(displayIndex) {
359
+ if (displayIndex === null || !Number.isFinite(displayIndex)) return void 0;
360
+ return this.entryRecords.find((entry) => entry.displayIndex === displayIndex);
361
+ }
303
362
  };
304
363
  //#endregion
305
364
  export { ChatLog };
@@ -1 +1 @@
1
- {"version":3,"file":"chat-log.js","names":[],"sources":["../../../../src/tui/components/chat-log.ts"],"sourcesContent":["import type { Component, KeybindingsManager } from '@earendil-works/pi-tui';\nimport { Container, Spacer, Text } from '@earendil-works/pi-tui';\nimport type { AgentMessage, AgentToolResult } from '@earendil-works/pi-agent-core';\n\nimport { BashExecutionComponent } from './bash-execution.js';\nimport { BashSummaryComponent, type BashSummary } from './bash-summary.js';\nimport { BranchMessageSummaryComponent, type BranchMessageSummary } from './branch-message-summary.js';\nimport { BranchSummaryComponent } from './branch-summary.js';\nimport { CompactionSummaryComponent } from './compaction-summary.js';\nimport { CustomMessageComponent, type CustomMessageSummary } from './custom-message.js';\nimport type { TuiMessageRenderer } from '../../extensions/types/tui.js';\nimport { theme } from '../theme.js';\nimport { AssistantMessageComponent } from './assistant-message.js';\nimport { ToolExecutionComponent, type ToolExecutionOptions } from './tool-execution.js';\nimport { UserMessageComponent } from './user-message.js';\nimport type { TuiBranchSummary, TuiCompactionResult } from '../tui-backend.js';\n\nconst MAX_COMPONENTS = 180;\n\ntype ExpandableBlock = { setExpanded(expanded: boolean): void };\n\nfunction assistantPlainText(message: AgentMessage): string {\n const content = (message as { content?: unknown }).content;\n if (typeof content === 'string') return content;\n if (!Array.isArray(content)) return '';\n return content\n .map((block) => {\n if (!block || typeof block !== 'object') return '';\n const rec = block as { type?: unknown; text?: unknown };\n return rec.type === 'text' && typeof rec.text === 'string' ? rec.text : '';\n })\n .join('');\n}\n\nexport class ChatLog extends Container {\n private toolById = new Map<string, ToolExecutionComponent>();\n private bashBlocks: Array<Component & ExpandableBlock> = [];\n private compactionBlocks: CompactionSummaryComponent[] = [];\n private branchBlocks: BranchSummaryComponent[] = [];\n private branchMessageBlocks: BranchMessageSummaryComponent[] = [];\n private customBlocks: CustomMessageComponent[] = [];\n private customMessageRenderers = new Map<string, TuiMessageRenderer>();\n private assistantMessages: AssistantMessageComponent[] = [];\n private streamingRuns = new Map<string, AssistantMessageComponent>();\n /** After finalizeAssistant, late tool execution events can still arrive; keep the bubble to link tools. */\n private assistantAnchorByRunId = new Map<string, AssistantMessageComponent>();\n private runsWithTools = new Set<string>();\n private toolsExpanded = false;\n private showThinking = true;\n private hiddenThinkingLabel = 'Thinking...';\n private toolImageOptions: ToolExecutionOptions = {};\n private lastAssistantText = '';\n private lastStatusEntry: Container | null = null;\n private lastStatusText: Text | null = null;\n private workflowStatusByRunId = new Map<string, { entry: Container; text: Text }>();\n\n constructor(private readonly keybindings?: KeybindingsManager) {\n super();\n if (keybindings) {\n this.toolImageOptions.keybindings = keybindings;\n }\n }\n\n private pruneOverflow(): void {\n while (this.children.length > MAX_COMPONENTS) {\n const oldest = this.children[0];\n if (!oldest) return;\n this.removeChild(oldest);\n this.dropReferences(oldest);\n }\n }\n\n private dropReferences(component: Component): void {\n for (const [id, tool] of this.toolById.entries()) {\n if (tool === component) this.toolById.delete(id);\n }\n for (const [runId, msg] of this.streamingRuns.entries()) {\n if (msg === component) this.streamingRuns.delete(runId);\n }\n for (const [runId, msg] of this.assistantAnchorByRunId.entries()) {\n if (msg === component) this.assistantAnchorByRunId.delete(runId);\n }\n this.bashBlocks = this.bashBlocks.filter((entry) => entry !== component);\n this.compactionBlocks = this.compactionBlocks.filter((entry) => entry !== component);\n this.branchBlocks = this.branchBlocks.filter((entry) => entry !== component);\n this.branchMessageBlocks = this.branchMessageBlocks.filter((entry) => entry !== component);\n this.customBlocks = this.customBlocks.filter((entry) => entry !== component);\n this.assistantMessages = this.assistantMessages.filter((entry) => entry !== component);\n if (this.lastStatusEntry === component) {\n this.lastStatusEntry = null;\n this.lastStatusText = null;\n }\n for (const [runId, status] of this.workflowStatusByRunId.entries()) {\n if (status.entry === component) this.workflowStatusByRunId.delete(runId);\n }\n }\n\n private append(component: Component): void {\n this.addChild(component);\n this.pruneOverflow();\n }\n\n clearAll(): void {\n this.clear();\n this.toolById.clear();\n this.bashBlocks = [];\n this.compactionBlocks = [];\n this.branchBlocks = [];\n this.branchMessageBlocks = [];\n this.customBlocks = [];\n this.assistantMessages = [];\n this.streamingRuns.clear();\n this.assistantAnchorByRunId.clear();\n this.runsWithTools.clear();\n this.lastAssistantText = '';\n this.lastStatusEntry = null;\n this.lastStatusText = null;\n this.workflowStatusByRunId.clear();\n }\n\n private createAssistantMessage(message?: AgentMessage): AssistantMessageComponent {\n const component = new AssistantMessageComponent(message, {\n hideThinkingBlock: !this.showThinking,\n hiddenThinkingLabel: this.hiddenThinkingLabel,\n });\n this.assistantMessages.push(component);\n return component;\n }\n\n addSystem(text: string): void {\n const entry = new Container();\n entry.addChild(new Spacer(1));\n entry.addChild(new Text(theme.system(text), 1, 0));\n this.append(entry);\n }\n\n addStatus(text: string): void {\n if (\n this.lastStatusEntry &&\n this.lastStatusText &&\n this.children[this.children.length - 1] === this.lastStatusEntry\n ) {\n this.lastStatusText.setText(theme.system(text));\n return;\n }\n\n const entry = new Container();\n const statusText = new Text(theme.system(text), 1, 0);\n entry.addChild(new Spacer(1));\n entry.addChild(statusText);\n this.lastStatusEntry = entry;\n this.lastStatusText = statusText;\n this.append(entry);\n }\n\n updateWorkflowRun(runId: string, text: string): void {\n const existing = this.workflowStatusByRunId.get(runId);\n if (existing) {\n existing.text.setText(theme.system(text));\n return;\n }\n\n const entry = new Container();\n const statusText = new Text(theme.system(text), 1, 0);\n entry.addChild(new Spacer(1));\n entry.addChild(statusText);\n this.workflowStatusByRunId.set(runId, { entry, text: statusText });\n this.append(entry);\n }\n\n addCompactionSummary(result: TuiCompactionResult): void {\n const component = new CompactionSummaryComponent(result, this.keybindings);\n component.setExpanded(this.toolsExpanded);\n this.compactionBlocks.push(component);\n this.append(component);\n }\n\n addBranchSummary(summary: TuiBranchSummary): void {\n const component = new BranchSummaryComponent(summary, this.keybindings);\n component.setExpanded(this.toolsExpanded);\n this.branchBlocks.push(component);\n this.append(component);\n }\n\n addBranchMessageSummary(summary: BranchMessageSummary): void {\n this.assistantAnchorByRunId.clear();\n const component = new BranchMessageSummaryComponent(summary, this.keybindings);\n component.setExpanded(this.toolsExpanded);\n this.branchMessageBlocks.push(component);\n this.append(component);\n }\n\n addCustomMessage(summary: CustomMessageSummary): void {\n this.assistantAnchorByRunId.clear();\n const component = new CustomMessageComponent(\n summary,\n this.customMessageRenderers.get(summary.customType),\n );\n component.setExpanded(this.toolsExpanded);\n this.customBlocks.push(component);\n this.append(component);\n }\n\n setCustomMessageRenderer(customType: string, renderer: TuiMessageRenderer | undefined): void {\n if (renderer) {\n this.customMessageRenderers.set(customType, renderer);\n } else {\n this.customMessageRenderers.delete(customType);\n }\n for (const block of this.customBlocks) {\n if (block.matchesCustomType(customType)) {\n block.setRenderer(renderer);\n }\n }\n }\n\n addUser(text: string | unknown[]): void {\n this.assistantAnchorByRunId.clear();\n this.append(new UserMessageComponent(text));\n }\n\n /** Stream local `!command` output in a bordered block. */\n addBashExecution(\n command: string,\n ui: import('@earendil-works/pi-tui').TUI,\n excludeFromContext: boolean,\n ): BashExecutionComponent {\n this.assistantAnchorByRunId.clear();\n const component = new BashExecutionComponent(command, ui, excludeFromContext, this.keybindings);\n component.setExpanded(this.toolsExpanded);\n this.bashBlocks.push(component);\n this.append(component);\n return component;\n }\n\n /** Replay a completed shell execution from persisted transcript history. */\n addBashSummary(summary: BashSummary): void {\n this.assistantAnchorByRunId.clear();\n const component = new BashSummaryComponent(summary, this.keybindings);\n component.setExpanded(this.toolsExpanded);\n this.bashBlocks.push(component);\n this.append(component);\n }\n\n startAssistant(message: AgentMessage, runId: string): void {\n const text = assistantPlainText(message);\n if (text.trim()) this.lastAssistantText = text;\n const existing = this.streamingRuns.get(runId);\n if (existing) {\n existing.updateContent(message);\n existing.setHasToolCalls(this.runsWithTools.has(runId));\n return;\n }\n const component = this.createAssistantMessage(message);\n component.setHasToolCalls(this.runsWithTools.has(runId));\n this.streamingRuns.set(runId, component);\n this.append(component);\n }\n\n updateAssistant(message: AgentMessage, runId: string): void {\n const text = assistantPlainText(message);\n if (text.trim()) this.lastAssistantText = text;\n const existing = this.streamingRuns.get(runId);\n if (!existing) {\n this.startAssistant(message, runId);\n return;\n }\n existing.updateContent(message);\n existing.setHasToolCalls(this.runsWithTools.has(runId));\n }\n\n finalizeAssistant(message: AgentMessage, runId: string): void {\n const text = assistantPlainText(message);\n if (text.trim()) this.lastAssistantText = text;\n const existing = this.streamingRuns.get(runId);\n if (existing) {\n existing.updateContent(message);\n existing.setHasToolCalls(this.runsWithTools.has(runId));\n this.streamingRuns.delete(runId);\n this.assistantAnchorByRunId.set(runId, existing);\n return;\n }\n const finalMessage = this.createAssistantMessage(message);\n finalMessage.setHasToolCalls(this.runsWithTools.has(runId));\n this.append(finalMessage);\n if (text.trim()) {\n this.assistantAnchorByRunId.set(runId, finalMessage);\n }\n }\n\n dropAssistant(runId: string): void {\n const existing = this.streamingRuns.get(runId);\n if (!existing) return;\n this.removeChild(existing);\n this.streamingRuns.delete(runId);\n }\n\n startTool(toolCallId: string, toolName: string, args: unknown, runId: string): void {\n const existing = this.toolById.get(toolCallId);\n if (existing) {\n existing.setArgs(args);\n return;\n }\n this.runsWithTools.add(runId);\n const component = new ToolExecutionComponent(toolName, toolCallId, args, {\n ...this.toolImageOptions,\n });\n component.setExpanded(this.toolsExpanded);\n this.toolById.set(toolCallId, component);\n\n const assistant = this.streamingRuns.get(runId) ?? this.assistantAnchorByRunId.get(runId);\n assistant?.setHasToolCalls(true);\n this.addChild(component);\n this.pruneOverflow();\n }\n\n markToolExecutionStarted(toolCallId: string): void {\n const existing = this.toolById.get(toolCallId);\n if (!existing) return;\n existing.markExecutionStarted();\n }\n\n markToolArgsComplete(toolCallId: string): void {\n const existing = this.toolById.get(toolCallId);\n if (!existing) return;\n existing.setArgsComplete();\n }\n\n updateToolResult(toolCallId: string, result: AgentToolResult<any> | unknown, isError: boolean, isPartial = false): void {\n const existing = this.toolById.get(toolCallId);\n if (!existing) return;\n existing.updateResult(result, isPartial, isError);\n }\n\n updateToolDetails(toolCallId: string, details: unknown): void {\n const existing = this.toolById.get(toolCallId);\n if (!existing) return;\n existing.setPartialDetails(details);\n }\n\n updateToolArgs(toolCallId: string, args: unknown): void {\n const existing = this.toolById.get(toolCallId);\n if (!existing) return;\n existing.setArgs(args);\n }\n\n setToolsExpanded(expanded: boolean): void {\n this.toolsExpanded = expanded;\n for (const tool of this.toolById.values()) {\n tool.setExpanded(expanded);\n }\n for (const bash of this.bashBlocks) {\n bash.setExpanded(expanded);\n }\n for (const compaction of this.compactionBlocks) {\n compaction.setExpanded(expanded);\n }\n for (const branch of this.branchBlocks) {\n branch.setExpanded(expanded);\n }\n for (const branch of this.branchMessageBlocks) {\n branch.setExpanded(expanded);\n }\n for (const custom of this.customBlocks) {\n custom.setExpanded(expanded);\n }\n }\n\n setShowThinking(showThinking: boolean): void {\n this.showThinking = showThinking;\n for (const assistant of this.assistantMessages) {\n assistant.setHideThinkingBlock(!showThinking);\n }\n }\n\n setHiddenThinkingLabel(label?: string): void {\n this.hiddenThinkingLabel = label ?? 'Thinking...';\n for (const assistant of this.assistantMessages) {\n assistant.setHiddenThinkingLabel(this.hiddenThinkingLabel);\n }\n }\n\n setToolImageOptions(options: ToolExecutionOptions): void {\n this.toolImageOptions = { ...options, keybindings: this.keybindings };\n for (const tool of this.toolById.values()) {\n tool.setImageOptions(this.toolImageOptions);\n }\n }\n\n getLastAssistantText(): string {\n return this.lastAssistantText;\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"chat-log.js","names":[],"sources":["../../../../src/tui/components/chat-log.ts"],"sourcesContent":["import type { Component, KeybindingsManager } from '@earendil-works/pi-tui';\nimport { Container, Spacer, Text } from '@earendil-works/pi-tui';\nimport type { AgentMessage, AgentToolResult } from '@earendil-works/pi-agent-core';\n\nimport { BashExecutionComponent } from './bash-execution.js';\nimport { BashSummaryComponent, type BashSummary } from './bash-summary.js';\nimport { BranchMessageSummaryComponent, type BranchMessageSummary } from './branch-message-summary.js';\nimport { BranchSummaryComponent } from './branch-summary.js';\nimport { CompactionSummaryComponent } from './compaction-summary.js';\nimport { CustomMessageComponent, type CustomMessageSummary } from './custom-message.js';\nimport type { TuiMessageRenderer } from '../../extensions/types/tui.js';\nimport { theme } from '../theme.js';\nimport { AssistantMessageComponent } from './assistant-message.js';\nimport { ToolExecutionComponent, type ToolExecutionOptions } from './tool-execution.js';\nimport { UserMessageComponent } from './user-message.js';\nimport type { TuiBranchSummary, TuiCompactionResult } from '../tui-backend.js';\n\nconst MAX_COMPONENTS = 180;\n\ntype ExpandableBlock = { setExpanded(expanded: boolean): void };\nexport type ChatLogEntryMeta = {\n displayIndex?: number;\n historyIndex?: number;\n rowNumber?: number;\n role?: 'user' | 'assistant' | 'system';\n};\n\ntype ChatLogEntryRecord = ChatLogEntryMeta & { component: Component };\n\nfunction assistantPlainText(message: AgentMessage): string {\n const content = (message as { content?: unknown }).content;\n if (typeof content === 'string') return content;\n if (!Array.isArray(content)) return '';\n return content\n .map((block) => {\n if (!block || typeof block !== 'object') return '';\n const rec = block as { type?: unknown; text?: unknown };\n return rec.type === 'text' && typeof rec.text === 'string' ? rec.text : '';\n })\n .join('');\n}\n\nexport class ChatLog extends Container {\n private toolById = new Map<string, ToolExecutionComponent>();\n private bashBlocks: Array<Component & ExpandableBlock> = [];\n private compactionBlocks: CompactionSummaryComponent[] = [];\n private branchBlocks: BranchSummaryComponent[] = [];\n private branchMessageBlocks: BranchMessageSummaryComponent[] = [];\n private customBlocks: CustomMessageComponent[] = [];\n private customMessageRenderers = new Map<string, TuiMessageRenderer>();\n private assistantMessages: AssistantMessageComponent[] = [];\n private streamingRuns = new Map<string, AssistantMessageComponent>();\n /** After finalizeAssistant, late tool execution events can still arrive; keep the bubble to link tools. */\n private assistantAnchorByRunId = new Map<string, AssistantMessageComponent>();\n private runsWithTools = new Set<string>();\n private toolsExpanded = false;\n private showThinking = true;\n private hiddenThinkingLabel = 'Thinking...';\n private toolImageOptions: ToolExecutionOptions = {};\n private lastAssistantText = '';\n private lastStatusEntry: Container | null = null;\n private lastStatusText: Text | null = null;\n private workflowStatusByRunId = new Map<string, { entry: Container; text: Text }>();\n private entryRecords: ChatLogEntryRecord[] = [];\n private viewportRowsProvider: (() => number) | undefined;\n private historyViewDisplayIndex: number | null = null;\n\n constructor(private readonly keybindings?: KeybindingsManager) {\n super();\n if (keybindings) {\n this.toolImageOptions.keybindings = keybindings;\n }\n }\n\n private pruneOverflow(): void {\n while (this.children.length > MAX_COMPONENTS) {\n const oldest = this.children[0];\n if (!oldest) return;\n this.removeChild(oldest);\n this.dropReferences(oldest);\n }\n }\n\n private dropReferences(component: Component): void {\n for (const [id, tool] of this.toolById.entries()) {\n if (tool === component) this.toolById.delete(id);\n }\n for (const [runId, msg] of this.streamingRuns.entries()) {\n if (msg === component) this.streamingRuns.delete(runId);\n }\n for (const [runId, msg] of this.assistantAnchorByRunId.entries()) {\n if (msg === component) this.assistantAnchorByRunId.delete(runId);\n }\n this.bashBlocks = this.bashBlocks.filter((entry) => entry !== component);\n this.compactionBlocks = this.compactionBlocks.filter((entry) => entry !== component);\n this.branchBlocks = this.branchBlocks.filter((entry) => entry !== component);\n this.branchMessageBlocks = this.branchMessageBlocks.filter((entry) => entry !== component);\n this.customBlocks = this.customBlocks.filter((entry) => entry !== component);\n this.assistantMessages = this.assistantMessages.filter((entry) => entry !== component);\n if (this.lastStatusEntry === component) {\n this.lastStatusEntry = null;\n this.lastStatusText = null;\n }\n for (const [runId, status] of this.workflowStatusByRunId.entries()) {\n if (status.entry === component) this.workflowStatusByRunId.delete(runId);\n }\n this.entryRecords = this.entryRecords.filter((entry) => entry.component !== component);\n if (!this.findEntryRecord(this.historyViewDisplayIndex)) {\n this.historyViewDisplayIndex = null;\n }\n }\n\n private append(component: Component, meta?: ChatLogEntryMeta): void {\n this.addChild(component);\n if (meta) {\n this.entryRecords.push({ component, ...meta });\n }\n this.pruneOverflow();\n }\n\n clearAll(): void {\n this.clear();\n this.toolById.clear();\n this.bashBlocks = [];\n this.compactionBlocks = [];\n this.branchBlocks = [];\n this.branchMessageBlocks = [];\n this.customBlocks = [];\n this.assistantMessages = [];\n this.streamingRuns.clear();\n this.assistantAnchorByRunId.clear();\n this.runsWithTools.clear();\n this.lastAssistantText = '';\n this.lastStatusEntry = null;\n this.lastStatusText = null;\n this.workflowStatusByRunId.clear();\n this.entryRecords = [];\n this.historyViewDisplayIndex = null;\n }\n\n private createAssistantMessage(message?: AgentMessage): AssistantMessageComponent {\n const component = new AssistantMessageComponent(message, {\n hideThinkingBlock: !this.showThinking,\n hiddenThinkingLabel: this.hiddenThinkingLabel,\n });\n this.assistantMessages.push(component);\n return component;\n }\n\n addSystem(text: string, meta?: ChatLogEntryMeta): void {\n const entry = new Container();\n entry.addChild(new Spacer(1));\n entry.addChild(new Text(theme.system(text), 1, 0));\n this.append(entry, meta);\n }\n\n addStatus(text: string): void {\n if (\n this.lastStatusEntry &&\n this.lastStatusText &&\n this.children[this.children.length - 1] === this.lastStatusEntry\n ) {\n this.lastStatusText.setText(theme.system(text));\n return;\n }\n\n const entry = new Container();\n const statusText = new Text(theme.system(text), 1, 0);\n entry.addChild(new Spacer(1));\n entry.addChild(statusText);\n this.lastStatusEntry = entry;\n this.lastStatusText = statusText;\n this.append(entry);\n }\n\n updateWorkflowRun(runId: string, text: string): void {\n const existing = this.workflowStatusByRunId.get(runId);\n if (existing) {\n existing.text.setText(theme.system(text));\n return;\n }\n\n const entry = new Container();\n const statusText = new Text(theme.system(text), 1, 0);\n entry.addChild(new Spacer(1));\n entry.addChild(statusText);\n this.workflowStatusByRunId.set(runId, { entry, text: statusText });\n this.append(entry);\n }\n\n addCompactionSummary(result: TuiCompactionResult): void {\n const component = new CompactionSummaryComponent(result, this.keybindings);\n component.setExpanded(this.toolsExpanded);\n this.compactionBlocks.push(component);\n this.append(component);\n }\n\n addBranchSummary(summary: TuiBranchSummary): void {\n const component = new BranchSummaryComponent(summary, this.keybindings);\n component.setExpanded(this.toolsExpanded);\n this.branchBlocks.push(component);\n this.append(component);\n }\n\n addBranchMessageSummary(summary: BranchMessageSummary): void {\n this.assistantAnchorByRunId.clear();\n const component = new BranchMessageSummaryComponent(summary, this.keybindings);\n component.setExpanded(this.toolsExpanded);\n this.branchMessageBlocks.push(component);\n this.append(component);\n }\n\n addCustomMessage(summary: CustomMessageSummary): void {\n this.assistantAnchorByRunId.clear();\n const component = new CustomMessageComponent(\n summary,\n this.customMessageRenderers.get(summary.customType),\n );\n component.setExpanded(this.toolsExpanded);\n this.customBlocks.push(component);\n this.append(component);\n }\n\n setCustomMessageRenderer(customType: string, renderer: TuiMessageRenderer | undefined): void {\n if (renderer) {\n this.customMessageRenderers.set(customType, renderer);\n } else {\n this.customMessageRenderers.delete(customType);\n }\n for (const block of this.customBlocks) {\n if (block.matchesCustomType(customType)) {\n block.setRenderer(renderer);\n }\n }\n }\n\n addUser(text: string | unknown[], meta?: ChatLogEntryMeta): void {\n this.assistantAnchorByRunId.clear();\n this.append(new UserMessageComponent(text), meta);\n }\n\n /** Stream local `!command` output in a bordered block. */\n addBashExecution(\n command: string,\n ui: import('@earendil-works/pi-tui').TUI,\n excludeFromContext: boolean,\n ): BashExecutionComponent {\n this.assistantAnchorByRunId.clear();\n const component = new BashExecutionComponent(command, ui, excludeFromContext, this.keybindings);\n component.setExpanded(this.toolsExpanded);\n this.bashBlocks.push(component);\n this.append(component);\n return component;\n }\n\n /** Replay a completed shell execution from persisted transcript history. */\n addBashSummary(summary: BashSummary): void {\n this.assistantAnchorByRunId.clear();\n const component = new BashSummaryComponent(summary, this.keybindings);\n component.setExpanded(this.toolsExpanded);\n this.bashBlocks.push(component);\n this.append(component);\n }\n\n startAssistant(message: AgentMessage, runId: string): void {\n const text = assistantPlainText(message);\n if (text.trim()) this.lastAssistantText = text;\n const existing = this.streamingRuns.get(runId);\n if (existing) {\n existing.updateContent(message);\n existing.setHasToolCalls(this.runsWithTools.has(runId));\n return;\n }\n const component = this.createAssistantMessage(message);\n component.setHasToolCalls(this.runsWithTools.has(runId));\n this.streamingRuns.set(runId, component);\n this.append(component);\n }\n\n updateAssistant(message: AgentMessage, runId: string): void {\n const text = assistantPlainText(message);\n if (text.trim()) this.lastAssistantText = text;\n const existing = this.streamingRuns.get(runId);\n if (!existing) {\n this.startAssistant(message, runId);\n return;\n }\n existing.updateContent(message);\n existing.setHasToolCalls(this.runsWithTools.has(runId));\n }\n\n finalizeAssistant(message: AgentMessage, runId: string, meta?: ChatLogEntryMeta): void {\n const text = assistantPlainText(message);\n if (text.trim()) this.lastAssistantText = text;\n const existing = this.streamingRuns.get(runId);\n if (existing) {\n existing.updateContent(message);\n existing.setHasToolCalls(this.runsWithTools.has(runId));\n this.streamingRuns.delete(runId);\n this.assistantAnchorByRunId.set(runId, existing);\n return;\n }\n const finalMessage = this.createAssistantMessage(message);\n finalMessage.setHasToolCalls(this.runsWithTools.has(runId));\n this.append(finalMessage, meta);\n if (text.trim()) {\n this.assistantAnchorByRunId.set(runId, finalMessage);\n }\n }\n\n dropAssistant(runId: string): void {\n const existing = this.streamingRuns.get(runId);\n if (!existing) return;\n this.removeChild(existing);\n this.streamingRuns.delete(runId);\n }\n\n startTool(toolCallId: string, toolName: string, args: unknown, runId: string): void {\n const existing = this.toolById.get(toolCallId);\n if (existing) {\n existing.setArgs(args);\n return;\n }\n this.runsWithTools.add(runId);\n const component = new ToolExecutionComponent(toolName, toolCallId, args, {\n ...this.toolImageOptions,\n });\n component.setExpanded(this.toolsExpanded);\n this.toolById.set(toolCallId, component);\n\n const assistant = this.streamingRuns.get(runId) ?? this.assistantAnchorByRunId.get(runId);\n assistant?.setHasToolCalls(true);\n this.append(component);\n }\n\n markToolExecutionStarted(toolCallId: string): void {\n const existing = this.toolById.get(toolCallId);\n if (!existing) return;\n existing.markExecutionStarted();\n }\n\n markToolArgsComplete(toolCallId: string): void {\n const existing = this.toolById.get(toolCallId);\n if (!existing) return;\n existing.setArgsComplete();\n }\n\n updateToolResult(toolCallId: string, result: AgentToolResult<any> | unknown, isError: boolean, isPartial = false): void {\n const existing = this.toolById.get(toolCallId);\n if (!existing) return;\n existing.updateResult(result, isPartial, isError);\n }\n\n updateToolDetails(toolCallId: string, details: unknown): void {\n const existing = this.toolById.get(toolCallId);\n if (!existing) return;\n existing.setPartialDetails(details);\n }\n\n updateToolArgs(toolCallId: string, args: unknown): void {\n const existing = this.toolById.get(toolCallId);\n if (!existing) return;\n existing.setArgs(args);\n }\n\n setToolsExpanded(expanded: boolean): void {\n this.toolsExpanded = expanded;\n for (const tool of this.toolById.values()) {\n tool.setExpanded(expanded);\n }\n for (const bash of this.bashBlocks) {\n bash.setExpanded(expanded);\n }\n for (const compaction of this.compactionBlocks) {\n compaction.setExpanded(expanded);\n }\n for (const branch of this.branchBlocks) {\n branch.setExpanded(expanded);\n }\n for (const branch of this.branchMessageBlocks) {\n branch.setExpanded(expanded);\n }\n for (const custom of this.customBlocks) {\n custom.setExpanded(expanded);\n }\n }\n\n setShowThinking(showThinking: boolean): void {\n this.showThinking = showThinking;\n for (const assistant of this.assistantMessages) {\n assistant.setHideThinkingBlock(!showThinking);\n }\n }\n\n setHiddenThinkingLabel(label?: string): void {\n this.hiddenThinkingLabel = label ?? 'Thinking...';\n for (const assistant of this.assistantMessages) {\n assistant.setHiddenThinkingLabel(this.hiddenThinkingLabel);\n }\n }\n\n setToolImageOptions(options: ToolExecutionOptions): void {\n this.toolImageOptions = { ...options, keybindings: this.keybindings };\n for (const tool of this.toolById.values()) {\n tool.setImageOptions(this.toolImageOptions);\n }\n }\n\n getLastAssistantText(): string {\n return this.lastAssistantText;\n }\n\n setViewportRowsProvider(provider: (() => number) | undefined): void {\n this.viewportRowsProvider = provider;\n }\n\n jumpToDisplayIndex(displayIndex: number): boolean {\n const target = this.findEntryRecord(displayIndex);\n if (!target) return false;\n this.historyViewDisplayIndex = target.displayIndex ?? null;\n return true;\n }\n\n jumpToLatest(): void {\n this.historyViewDisplayIndex = null;\n }\n\n getTimelineViewportState(): { mode: 'latest' } | { mode: 'history'; displayIndex: number } {\n if (this.historyViewDisplayIndex === null) return { mode: 'latest' };\n return { mode: 'history', displayIndex: this.historyViewDisplayIndex };\n }\n\n override render(width: number): string[] {\n const allLines: string[] = [];\n const ranges: Array<{ record: ChatLogEntryRecord; start: number; end: number }> = [];\n for (const child of this.children) {\n const start = allLines.length;\n const childLines = child.render(width);\n allLines.push(...childLines);\n const record = this.entryRecords.find((entry) => entry.component === child);\n if (record) {\n ranges.push({ record, start, end: allLines.length });\n }\n }\n\n if (this.historyViewDisplayIndex === null) return allLines;\n\n const target = this.findEntryRecord(this.historyViewDisplayIndex);\n const range = target\n ? ranges.find((candidate) => candidate.record.component === target.component)\n : undefined;\n if (!range) {\n this.historyViewDisplayIndex = null;\n return allLines;\n }\n\n const viewportRows = Math.max(8, Math.floor(this.viewportRowsProvider?.() ?? 24));\n const start = Math.max(0, range.start - 1);\n const end = Math.min(allLines.length, start + Math.max(1, viewportRows - 1));\n return [\n theme.dim('Viewing previous transcript - /timeline latest returns to live view.'),\n ...allLines.slice(start, end),\n ];\n }\n\n private findEntryRecord(displayIndex: number | null): ChatLogEntryRecord | undefined {\n if (displayIndex === null || !Number.isFinite(displayIndex)) return undefined;\n return this.entryRecords.find((entry) => entry.displayIndex === displayIndex);\n }\n}\n"],"mappings":"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"}
@@ -17,6 +17,7 @@ export declare class ToolExecutionComponent extends Container {
17
17
  private contentText;
18
18
  private collapsedOutputComponent;
19
19
  private collapsedReadSummaryComponent;
20
+ private expandedOutputComponent;
20
21
  private toolName;
21
22
  private toolCallId;
22
23
  private args;
@@ -42,6 +43,8 @@ export declare class ToolExecutionComponent extends Container {
42
43
  private isError;
43
44
  private isPartial;
44
45
  private executionStarted;
46
+ private startedAt;
47
+ private completedAt;
45
48
  constructor(toolName: string, toolCallId: string, args: unknown, options?: ToolExecutionOptions);
46
49
  setArgs(args: unknown): void;
47
50
  markExecutionStarted(): void;
@@ -63,8 +66,13 @@ export declare class ToolExecutionComponent extends Container {
63
66
  private formatToolCallFallback;
64
67
  private formatToolResultFallback;
65
68
  private formatToolExecution;
69
+ private toolStatusLabel;
70
+ private toolDurationLabel;
71
+ private collapsedSpecializedSummary;
72
+ private shouldRenderDetailsPreview;
66
73
  private getDisplayResultText;
67
74
  private refreshImages;
68
75
  private refreshCollapsedOutput;
69
76
  private refreshCollapsedReadSummary;
77
+ private refreshExpandedOutput;
70
78
  }