@xopcai/xopc 0.0.124 → 0.0.126

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (496) hide show
  1. package/README.md +56 -102
  2. package/README.zh-CN.md +51 -98
  3. package/dist/browser-ext/manifest.json +1 -1
  4. package/dist/extensions/feishu/src/schema/config-schema.d.ts +6 -6
  5. package/dist/extensions/feishu/src/workflow-progress.js +1 -1
  6. package/dist/extensions/telegram/src/adapters/streaming-adapter.js +1 -1
  7. package/dist/extensions/telegram/src/config-schema.d.ts +8 -8
  8. package/dist/extensions/telegram/src/inbound-processor.js +1 -1
  9. package/dist/extensions/telegram/src/plugin.js +1 -1
  10. package/dist/extensions/telegram/src/routing-integration.js +2 -2
  11. package/dist/extensions/telegram/src/workflow-progress.js +1 -1
  12. package/dist/extensions/telegram/xopc.extension.json +1 -1
  13. package/dist/extensions/weixin/src/api/api.js +1 -1
  14. package/dist/extensions/weixin/src/config-schema.d.ts +3 -3
  15. package/dist/extensions/weixin/src/plugin.js +1 -1
  16. package/dist/extensions/weixin/src/workflow-progress.js +1 -1
  17. package/dist/gateway/static/root/assets/Combination-BzaXOLd9.js +41 -0
  18. package/dist/gateway/static/root/assets/{agent-avatar-dicebear-B5uSVAyJ.js → agent-avatar-dicebear-C70vgt60.js} +1 -1
  19. package/dist/gateway/static/root/assets/agents-DRYVahI-.js +2 -0
  20. package/dist/gateway/static/root/assets/app-management-settings-panel-D9-HW6cy.js +1 -0
  21. package/dist/gateway/static/root/assets/appearance-settings-BHlahIDL.js +1 -0
  22. package/dist/gateway/static/root/assets/apps-page-BdJ1eQg3.js +1 -0
  23. package/dist/gateway/static/root/assets/{archive-plugin-CXUGRp2i.js → archive-plugin-B-aoIt0w.js} +1 -1
  24. package/dist/gateway/static/root/assets/{attachment-load-Cmiub3Wg.js → attachment-load-BD0G0FD5.js} +1 -1
  25. package/dist/gateway/static/root/assets/automation-suggestion-card-iJRVI7aZ.js +1 -0
  26. package/dist/gateway/static/root/assets/automations-page-D8hYQbkl.js +4 -0
  27. package/dist/gateway/static/root/assets/{binary-plugins-0Izz-N3p.js → binary-plugins-B0mNlVSz.js} +1 -1
  28. package/dist/gateway/static/root/assets/{block-editor-C1Kv0IkJ.js → block-editor-CJY9Lu5G.js} +3 -3
  29. package/dist/gateway/static/root/assets/browser-settings-page-CiWEO-Iy.js +8 -0
  30. package/dist/gateway/static/root/assets/capability-presets-api-Bgc8ag55.js +1 -0
  31. package/dist/gateway/static/root/assets/capability-presets-settings-panel-B1nIi0TC.js +1 -0
  32. package/dist/gateway/static/root/assets/{channel-recipient-api-BeA2aVor.js → channel-recipient-api-0sauApoC.js} +1 -1
  33. package/dist/gateway/static/root/assets/channels-settings-BddPdqVo.js +1 -0
  34. package/dist/gateway/static/root/assets/code-editor-gbRgS14t.js +1 -0
  35. package/dist/gateway/static/root/assets/connectors-page-Ba2GDhSE.js +2 -0
  36. package/dist/gateway/static/root/assets/{directory-picker-path-field-2rjzUu57.js → directory-picker-path-field-CiEc4KmY.js} +1 -1
  37. package/dist/gateway/static/root/assets/dist-By6Rh2ee.js +1 -0
  38. package/dist/gateway/static/root/assets/dist-CkobR7mk.js +1 -0
  39. package/dist/gateway/static/root/assets/dist-DokQNVMQ.js +1 -0
  40. package/dist/gateway/static/root/assets/dreaming-settings-4bvpk5wr.js +3 -0
  41. package/dist/gateway/static/root/assets/extension-debug-page-BbyczVZ3.js +1 -0
  42. package/dist/gateway/static/root/assets/extension-page-DLN1I3DR.js +1 -0
  43. package/dist/gateway/static/root/assets/extension-settings-page-D9VGHmYJ.js +1 -0
  44. package/dist/gateway/static/root/assets/{fetch-BU5S0Sn7.js → fetch-5V96dUz3.js} +1 -1
  45. package/dist/gateway/static/root/assets/{gateway-config-api-BIPGwrl1.js → gateway-config-api-BtIzObwp.js} +1 -1
  46. package/dist/gateway/static/root/assets/gateway-settings-KFsGGDhg.js +1 -0
  47. package/dist/gateway/static/root/assets/{gateway-startup-retry-Cd0Zz30N.js → gateway-startup-retry-DEMad2wt.js} +1 -1
  48. package/dist/gateway/static/root/assets/goal-create-dialog-4PcF6Sh6.js +1 -0
  49. package/dist/gateway/static/root/assets/goal-detail-page-B482PSaG.js +1 -0
  50. package/dist/gateway/static/root/assets/{goals-config-api-B95KdGMj.js → goals-config-api-CVN7-pdM.js} +1 -1
  51. package/dist/gateway/static/root/assets/goals-page-CUdgJuDn.js +2 -0
  52. package/dist/gateway/static/root/assets/goals-settings-IYCH3-Pi.js +1 -0
  53. package/dist/gateway/static/root/assets/heartbeat-settings-Cf_a2Bmz.js +1 -0
  54. package/dist/gateway/static/root/assets/{html-workspace-editor-CQLWDiwE.js → html-workspace-editor-DV90ddkE.js} +1 -1
  55. package/dist/gateway/static/root/assets/index-CA2tR2vm.js +256 -0
  56. package/dist/gateway/static/root/assets/index-Ds3u0LOk.css +1 -0
  57. package/dist/gateway/static/root/assets/keyboard-shortcuts-settings-lKTg6St7.js +1 -0
  58. package/dist/gateway/static/root/assets/logs-page-BCporcNH.js +2 -0
  59. package/dist/gateway/static/root/assets/{markdown-editor-AssmZFx4.js → markdown-editor-BFOjBBla.js} +2 -2
  60. package/dist/gateway/static/root/assets/markdown-split-Bv4k6iGJ.js +1 -0
  61. package/dist/gateway/static/root/assets/{media-plugins-BhIQU5yS.js → media-plugins-Bbi8g3N8.js} +1 -1
  62. package/dist/gateway/static/root/assets/messages-C22hxE1N.js +3 -0
  63. package/dist/gateway/static/root/assets/models-hub-panel-D68Pyow7.js +2 -0
  64. package/dist/gateway/static/root/assets/notes-page-CuUMOiyv.js +1 -0
  65. package/dist/gateway/static/root/assets/notes-workbench-Dx2N5zTk.js +2 -0
  66. package/dist/gateway/static/root/assets/page-tabs-Cp395RYD.js +1 -0
  67. package/dist/gateway/static/root/assets/{preview-open-alternatives-DGzet1d7.js → preview-open-alternatives-DqV5OM4m.js} +1 -1
  68. package/dist/gateway/static/root/assets/project-detail-page-sB8AzZi3.js +1 -0
  69. package/dist/gateway/static/root/assets/projects-page-LBnJqWK2.js +1 -0
  70. package/dist/gateway/static/root/assets/remote-access-hub-Dbj0o6SC.js +1 -0
  71. package/dist/gateway/static/root/assets/{save-bar-controls-Cqgb-jqa.js → save-bar-controls-BItmzAzI.js} +1 -1
  72. package/dist/gateway/static/root/assets/{schedule-field-DVZcI8Yt.js → schedule-field-BQ8IjjCn.js} +1 -1
  73. package/dist/gateway/static/root/assets/{schema-form-Bj7sOxC8.js → schema-form-BRpD6x3d.js} +1 -1
  74. package/dist/gateway/static/root/assets/sessions-page-DhDZKspB.js +1 -0
  75. package/dist/gateway/static/root/assets/settings-advanced-gate-BvXLMNL6.js +1 -0
  76. package/dist/gateway/static/root/assets/{settings-collapsible-section-BmXn-8N6.js → settings-collapsible-section-BKSPQM4R.js} +1 -1
  77. package/dist/gateway/static/root/assets/settings-form-section-BmyfthNQ.js +1 -0
  78. package/dist/gateway/static/root/assets/settings-page-Cfm9UxAr.js +1 -0
  79. package/dist/gateway/static/root/assets/settings-page-layout-Bls5tfbH.js +1 -0
  80. package/dist/gateway/static/root/assets/setup-status-panel-kQEsTGAs.js +1 -0
  81. package/dist/gateway/static/root/assets/{share-preview-page-IB1v8i86.js → share-preview-page-DbYZNAPb.js} +1 -1
  82. package/dist/gateway/static/root/assets/shares-settings-BtR4B0kn.js +1 -0
  83. package/dist/gateway/static/root/assets/skill-reload-api-CJNVOWoK.js +1 -0
  84. package/dist/gateway/static/root/assets/skills-page-DcWDHrt3.js +2 -0
  85. package/dist/gateway/static/root/assets/{system-settings-panel-BxQ384RC.js → system-settings-panel-DKDAojWM.js} +1 -1
  86. package/dist/gateway/static/root/assets/{typed-models-lib-BkcpvFYO.js → typed-models-lib-BCCV4Kkp.js} +1 -1
  87. package/dist/gateway/static/root/assets/{use-channel-catalog-Cd0FaEQ4.js → use-channel-catalog-NBqg3iFY.js} +1 -1
  88. package/dist/gateway/static/root/assets/{user-profile-settings-panel-DQ7NnRSY.js → user-profile-settings-panel-suQ2x-LB.js} +1 -1
  89. package/dist/gateway/static/root/assets/{utils-YKhVf7Ka.js → utils-DPGVr3tS.js} +1 -1
  90. package/dist/gateway/static/root/assets/{vendor-codemirror-CNP1wPe7.js → vendor-codemirror-BvNgyE1Q.js} +1 -1
  91. package/dist/gateway/static/root/assets/voice-api-key-field-DaJASKFP.js +1 -0
  92. package/dist/gateway/static/root/assets/work-item-detail-page-BrCZpAWh.js +1 -0
  93. package/dist/gateway/static/root/assets/workflow-run-setup-panel-BTkRVNAh.js +3 -0
  94. package/dist/gateway/static/root/assets/{workflow-start-dialog-BNJVCWoS.js → workflow-start-dialog-DAImVtdO.js} +1 -1
  95. package/dist/gateway/static/root/assets/workflows-page-vyJ8wSXm.js +18 -0
  96. package/dist/gateway/static/root/index.html +8 -7
  97. package/dist/package.js +1 -1
  98. package/dist/src/activity/context.d.ts +11 -0
  99. package/dist/src/activity/context.js +36 -0
  100. package/dist/src/activity/context.js.map +1 -0
  101. package/dist/src/activity/emitter.d.ts +6 -0
  102. package/dist/src/activity/emitter.js +43 -0
  103. package/dist/src/activity/emitter.js.map +1 -0
  104. package/dist/src/activity/index.d.ts +3 -0
  105. package/dist/src/activity/index.js +3 -0
  106. package/dist/src/activity/service.d.ts +12 -0
  107. package/dist/src/activity/service.js +59 -0
  108. package/dist/src/activity/service.js.map +1 -0
  109. package/dist/src/activity/types.d.ts +109 -0
  110. package/dist/src/activity/types.js +1 -0
  111. package/dist/src/agent/agent-manager.d.ts +7 -0
  112. package/dist/src/agent/agent-manager.js +12 -5
  113. package/dist/src/agent/agent-manager.js.map +1 -1
  114. package/dist/src/agent/child-agent-factory.d.ts +2 -0
  115. package/dist/src/agent/child-agent-factory.js +2 -0
  116. package/dist/src/agent/child-agent-factory.js.map +1 -1
  117. package/dist/src/agent/coding/index.d.ts +1 -0
  118. package/dist/src/agent/coding/index.js +2 -0
  119. package/dist/src/agent/coding/turn-diff-tracker.d.ts +67 -0
  120. package/dist/src/agent/coding/turn-diff-tracker.js +233 -0
  121. package/dist/src/agent/coding/turn-diff-tracker.js.map +1 -0
  122. package/dist/src/agent/context/project-context.js +2 -2
  123. package/dist/src/agent/context/workspace-seed.js +2 -2
  124. package/dist/src/agent/embedded/run-for-session.js +1 -1
  125. package/dist/src/agent/goals/post-turn.js +2 -2
  126. package/dist/src/agent/ipc/bus.js +1 -1
  127. package/dist/src/agent/mcp/bundle-mcp-materialize.js +1 -1
  128. package/dist/src/agent/mcp/bundle-mcp-runtime.js +1 -1
  129. package/dist/src/agent/mcp/mcp-transport-config.js +1 -1
  130. package/dist/src/agent/mcp/mcp-transport.js +1 -1
  131. package/dist/src/agent/memory/dreaming/config.d.ts +2 -2
  132. package/dist/src/agent/memory/dreaming/config.js +3 -3
  133. package/dist/src/agent/memory/dreaming/config.js.map +1 -1
  134. package/dist/src/agent/memory/dreaming/constants.d.ts +1 -1
  135. package/dist/src/agent/memory/dreaming/constants.js +1 -1
  136. package/dist/src/agent/memory/dreaming/constants.js.map +1 -1
  137. package/dist/src/agent/memory/dreaming/deep-promotion.d.ts +1 -0
  138. package/dist/src/agent/memory/dreaming/deep-promotion.js +11 -20
  139. package/dist/src/agent/memory/dreaming/deep-promotion.js.map +1 -1
  140. package/dist/src/agent/memory/dreaming/events.d.ts +3 -3
  141. package/dist/src/agent/memory/dreaming/events.js +6 -6
  142. package/dist/src/agent/memory/dreaming/events.js.map +1 -1
  143. package/dist/src/agent/memory/dreaming/last-run.d.ts +2 -2
  144. package/dist/src/agent/memory/dreaming/last-run.js +1 -1
  145. package/dist/src/agent/memory/dreaming/last-run.js.map +1 -1
  146. package/dist/src/agent/memory/dreaming/light-sweep.d.ts +1 -1
  147. package/dist/src/agent/memory/dreaming/light-sweep.js +3 -3
  148. package/dist/src/agent/memory/dreaming/light-sweep.js.map +1 -1
  149. package/dist/src/agent/memory/dreaming/preview.d.ts +1 -0
  150. package/dist/src/agent/memory/dreaming/preview.js +2 -2
  151. package/dist/src/agent/memory/dreaming/preview.js.map +1 -1
  152. package/dist/src/agent/memory/dreaming/rem-patterns.d.ts +1 -1
  153. package/dist/src/agent/memory/dreaming/rem-patterns.js +13 -13
  154. package/dist/src/agent/memory/dreaming/rem-patterns.js.map +1 -1
  155. package/dist/src/agent/memory/dreaming/scope.d.ts +14 -0
  156. package/dist/src/agent/memory/dreaming/scope.js +27 -0
  157. package/dist/src/agent/memory/dreaming/scope.js.map +1 -0
  158. package/dist/src/agent/memory/dreaming/short-term-store.d.ts +4 -4
  159. package/dist/src/agent/memory/dreaming/short-term-store.js +17 -17
  160. package/dist/src/agent/memory/dreaming/short-term-store.js.map +1 -1
  161. package/dist/src/agent/memory/plugin-discovery.js +1 -1
  162. package/dist/src/agent/models/manager.js +1 -1
  163. package/dist/src/agent/orchestration/agent-event-handler.d.ts +2 -0
  164. package/dist/src/agent/orchestration/agent-event-handler.js +13 -0
  165. package/dist/src/agent/orchestration/agent-event-handler.js.map +1 -1
  166. package/dist/src/agent/orchestration/agent-orchestrator.js +22 -12
  167. package/dist/src/agent/orchestration/agent-orchestrator.js.map +1 -1
  168. package/dist/src/agent/sandbox/command-validator.js +12 -0
  169. package/dist/src/agent/sandbox/command-validator.js.map +1 -1
  170. package/dist/src/agent/service.d.ts +2 -1
  171. package/dist/src/agent/service.js +24 -9
  172. package/dist/src/agent/service.js.map +1 -1
  173. package/dist/src/agent/service.types.d.ts +7 -0
  174. package/dist/src/agent/session/session-inspector.d.ts +5 -3
  175. package/dist/src/agent/session/session-inspector.js +17 -8
  176. package/dist/src/agent/session/session-inspector.js.map +1 -1
  177. package/dist/src/agent/skills/hub-pull.js +1 -1
  178. package/dist/src/agent/source-context/types.d.ts +1 -1
  179. package/dist/src/agent/source-context/types.js +1 -1
  180. package/dist/src/agent/source-context/types.js.map +1 -1
  181. package/dist/src/agent/tool-manuals/index.js +15 -6
  182. package/dist/src/agent/tool-manuals/index.js.map +1 -1
  183. package/dist/src/agent/tool-manuals/xopc-use.d.ts +1 -0
  184. package/dist/src/agent/tool-manuals/xopc-use.js +204 -0
  185. package/dist/src/agent/tool-manuals/xopc-use.js.map +1 -0
  186. package/dist/src/agent/tools/apply-patch.js +116 -62
  187. package/dist/src/agent/tools/apply-patch.js.map +1 -1
  188. package/dist/src/agent/tools/concurrency.d.ts +8 -0
  189. package/dist/src/agent/tools/concurrency.js +31 -0
  190. package/dist/src/agent/tools/concurrency.js.map +1 -0
  191. package/dist/src/agent/tools/dreaming-tool.d.ts +2 -0
  192. package/dist/src/agent/tools/dreaming-tool.js +13 -10
  193. package/dist/src/agent/tools/dreaming-tool.js.map +1 -1
  194. package/dist/src/agent/tools/exec-command.js +4 -0
  195. package/dist/src/agent/tools/exec-command.js.map +1 -1
  196. package/dist/src/agent/tools/executor.d.ts +6 -4
  197. package/dist/src/agent/tools/executor.js +7 -4
  198. package/dist/src/agent/tools/executor.js.map +1 -1
  199. package/dist/src/agent/tools/factory.d.ts +10 -0
  200. package/dist/src/agent/tools/factory.js +16 -1
  201. package/dist/src/agent/tools/factory.js.map +1 -1
  202. package/dist/src/agent/tools/find.js +2 -0
  203. package/dist/src/agent/tools/find.js.map +1 -1
  204. package/dist/src/agent/tools/goal-tool.js +2 -2
  205. package/dist/src/agent/tools/grep.js +2 -0
  206. package/dist/src/agent/tools/grep.js.map +1 -1
  207. package/dist/src/agent/tools/index.d.ts +3 -0
  208. package/dist/src/agent/tools/index.js +4 -1
  209. package/dist/src/agent/tools/list-dir.js +2 -0
  210. package/dist/src/agent/tools/list-dir.js.map +1 -1
  211. package/dist/src/agent/tools/memory-tool.d.ts +1 -0
  212. package/dist/src/agent/tools/memory-tool.js +2 -2
  213. package/dist/src/agent/tools/memory-tool.js.map +1 -1
  214. package/dist/src/agent/tools/metadata.d.ts +15 -0
  215. package/dist/src/agent/tools/metadata.js +26 -0
  216. package/dist/src/agent/tools/metadata.js.map +1 -0
  217. package/dist/src/agent/tools/read.js +2 -0
  218. package/dist/src/agent/tools/read.js.map +1 -1
  219. package/dist/src/agent/tools/workflow-tool.js +1 -1
  220. package/dist/src/agent/tools/write.js +6 -0
  221. package/dist/src/agent/tools/write.js.map +1 -1
  222. package/dist/src/agent/tools/xopc-use-tool.d.ts +34 -0
  223. package/dist/src/agent/tools/xopc-use-tool.js +636 -0
  224. package/dist/src/agent/tools/xopc-use-tool.js.map +1 -0
  225. package/dist/src/agent/workflow/subagent-runner.d.ts +1 -0
  226. package/dist/src/agent/workflow/subagent-runner.js +5 -1
  227. package/dist/src/agent/workflow/subagent-runner.js.map +1 -1
  228. package/dist/src/agent/workflow/workflow-child-tools.js +5 -0
  229. package/dist/src/agent/workflow/workflow-child-tools.js.map +1 -1
  230. package/dist/src/agent-manifest/schema.d.ts +27 -27
  231. package/dist/src/automations/api/routes.js +1 -1
  232. package/dist/src/automations/domain/validation.d.ts +55 -55
  233. package/dist/src/automations/draft/automation-draft-validator.d.ts +25 -25
  234. package/dist/src/automations/service/action-executor.js +2 -2
  235. package/dist/src/browser/cdp-local-launcher.js +1 -1
  236. package/dist/src/browser/providers/browser-ext-install.js +3 -3
  237. package/dist/src/browser/providers/cloakbrowser.js +2 -2
  238. package/dist/src/browser/providers/playwright-doctor.js +1 -1
  239. package/dist/src/browser/stealth.js +1 -1
  240. package/dist/src/chat-commands/agent-edit.js +1 -1
  241. package/dist/src/chat-commands/builtins/config.js +1 -1
  242. package/dist/src/chat-commands/builtins/goal.js +2 -2
  243. package/dist/src/chat-commands/context.js +1 -1
  244. package/dist/src/cli/commands/agent.js +1 -1
  245. package/dist/src/cli/commands/doctor/checks/database-schema.js +2 -2
  246. package/dist/src/cli/commands/doctor/checks/session-integrity.js +1 -1
  247. package/dist/src/cli/commands/extension-marketplace.js +1 -1
  248. package/dist/src/cli/commands/extension-pack.js +1 -1
  249. package/dist/src/cli/commands/gateway/lifecycle.js +1 -1
  250. package/dist/src/cli/commands/goal.js +3 -3
  251. package/dist/src/cli/commands/init.js +1 -1
  252. package/dist/src/cli/commands/project.js +4 -4
  253. package/dist/src/config/agent-profile.js +1 -1
  254. package/dist/src/config/gateway-bind.js +1 -1
  255. package/dist/src/config/index.js +1 -1
  256. package/dist/src/config/loader.js +1 -1
  257. package/dist/src/config/models-json.d.ts +14 -14
  258. package/dist/src/config/models-json.js +1 -1
  259. package/dist/src/config/schema.d.ts +60 -60
  260. package/dist/src/connectors/health.d.ts +2 -1
  261. package/dist/src/connectors/health.js +59 -1
  262. package/dist/src/connectors/health.js.map +1 -1
  263. package/dist/src/connectors/install.d.ts +1 -0
  264. package/dist/src/connectors/install.js +28 -1
  265. package/dist/src/connectors/install.js.map +1 -1
  266. package/dist/src/connectors/instances.js +7 -0
  267. package/dist/src/connectors/instances.js.map +1 -1
  268. package/dist/src/connectors/materialize.js +2 -1
  269. package/dist/src/connectors/materialize.js.map +1 -1
  270. package/dist/src/connectors/registries/modelscope.js +38 -13
  271. package/dist/src/connectors/registries/modelscope.js.map +1 -1
  272. package/dist/src/connectors/types.d.ts +2 -0
  273. package/dist/src/daemon/launchd.js +1 -1
  274. package/dist/src/daemon/systemd.js +1 -1
  275. package/dist/src/extensions/discover-extensions.js +1 -1
  276. package/dist/src/extensions/loader.js +2 -2
  277. package/dist/src/gateway/agents-admin.js +1 -1
  278. package/dist/src/gateway/dreaming-automation-reconciler.d.ts +1 -0
  279. package/dist/src/gateway/dreaming-automation-reconciler.js +62 -42
  280. package/dist/src/gateway/dreaming-automation-reconciler.js.map +1 -1
  281. package/dist/src/gateway/hono/app.js +7 -1
  282. package/dist/src/gateway/hono/app.js.map +1 -1
  283. package/dist/src/gateway/hono/lib/config-payload.d.ts +14 -14
  284. package/dist/src/gateway/hono/lib/static-ui.js +1 -1
  285. package/dist/src/gateway/hono/middleware/log-context.js +8 -1
  286. package/dist/src/gateway/hono/middleware/log-context.js.map +1 -1
  287. package/dist/src/gateway/hono/routes/activity.d.ts +14 -0
  288. package/dist/src/gateway/hono/routes/activity.js +72 -0
  289. package/dist/src/gateway/hono/routes/activity.js.map +1 -0
  290. package/dist/src/gateway/hono/routes/connectors.js +46 -2
  291. package/dist/src/gateway/hono/routes/connectors.js.map +1 -1
  292. package/dist/src/gateway/hono/routes/dreaming.js +111 -66
  293. package/dist/src/gateway/hono/routes/dreaming.js.map +1 -1
  294. package/dist/src/gateway/hono/routes/goals.js +1 -1
  295. package/dist/src/gateway/hono/routes/index.js +2 -0
  296. package/dist/src/gateway/hono/routes/index.js.map +1 -1
  297. package/dist/src/gateway/hono/routes/memory.js +2 -2
  298. package/dist/src/gateway/hono/routes/projects.js +903 -50
  299. package/dist/src/gateway/hono/routes/projects.js.map +1 -1
  300. package/dist/src/gateway/hono/routes/sessions.js +102 -2
  301. package/dist/src/gateway/hono/routes/sessions.js.map +1 -1
  302. package/dist/src/gateway/hono/routes/workflows.js +2 -2
  303. package/dist/src/gateway/lock.js +1 -1
  304. package/dist/src/gateway/ports.js +1 -1
  305. package/dist/src/gateway/service/sessions-api.d.ts +10 -0
  306. package/dist/src/gateway/service/sessions-api.js +31 -0
  307. package/dist/src/gateway/service/sessions-api.js.map +1 -1
  308. package/dist/src/gateway/service.js +28 -16
  309. package/dist/src/gateway/service.js.map +1 -1
  310. package/dist/src/goals/goal-store.js +1 -1
  311. package/dist/src/goals/goal-store.js.map +1 -1
  312. package/dist/src/goals/goal-workflow-judge.js +1 -1
  313. package/dist/src/infra/ports.js +1 -1
  314. package/dist/src/infra/ssh-tunnel.js +1 -1
  315. package/dist/src/infra/update-check.js +1 -1
  316. package/dist/src/infra/update-restart.js +1 -1
  317. package/dist/src/mcp/channel-bridge.js +1 -1
  318. package/dist/src/media/store.js +1 -1
  319. package/dist/src/media/store.js.map +1 -1
  320. package/dist/src/media/types.d.ts +1 -1
  321. package/dist/src/media/uri.js +2 -1
  322. package/dist/src/media/uri.js.map +1 -1
  323. package/dist/src/migrations/runner.js +1 -1
  324. package/dist/src/notes/service.js +65 -6
  325. package/dist/src/notes/service.js.map +1 -1
  326. package/dist/src/notes/store.js +1 -1
  327. package/dist/src/projects/project-service.d.ts +2 -1
  328. package/dist/src/projects/project-service.js +59 -2
  329. package/dist/src/projects/project-service.js.map +1 -1
  330. package/dist/src/projects/project-store.d.ts +2 -1
  331. package/dist/src/projects/project-store.js +43 -0
  332. package/dist/src/projects/project-store.js.map +1 -1
  333. package/dist/src/projects/types.d.ts +10 -0
  334. package/dist/src/projects/workspace.js +1 -1
  335. package/dist/src/routing/agent-session-key.js +1 -1
  336. package/dist/src/routing/resolve-route.js +1 -1
  337. package/dist/src/routing/resolve-tui-session-key.js +1 -1
  338. package/dist/src/session/client-history.d.ts +3 -0
  339. package/dist/src/session/client-history.js +24 -9
  340. package/dist/src/session/client-history.js.map +1 -1
  341. package/dist/src/session/init-session-turn.js +1 -1
  342. package/dist/src/session/resolve-session.js +1 -1
  343. package/dist/src/session/session-context-for-llm.d.ts +2 -0
  344. package/dist/src/session/session-context-for-llm.js +14 -1
  345. package/dist/src/session/session-context-for-llm.js.map +1 -1
  346. package/dist/src/session/session-title.js +2 -2
  347. package/dist/src/session/store.js +3 -3
  348. package/dist/src/session/store.js.map +1 -1
  349. package/dist/src/session/types.d.ts +4 -0
  350. package/dist/src/session/types.js.map +1 -1
  351. package/dist/src/storage/sqlite/activity-repository.d.ts +8 -0
  352. package/dist/src/storage/sqlite/activity-repository.js +208 -0
  353. package/dist/src/storage/sqlite/activity-repository.js.map +1 -0
  354. package/dist/src/storage/sqlite/connection.js +1 -1
  355. package/dist/src/storage/sqlite/index.d.ts +1 -0
  356. package/dist/src/storage/sqlite/index.js +2 -1
  357. package/dist/src/storage/sqlite/migrations/022_work_items.sql +61 -0
  358. package/dist/src/storage/sqlite/migrations/023_work_item_attachments.sql +15 -0
  359. package/dist/src/storage/sqlite/migrations/024_activity_events.sql +62 -0
  360. package/dist/src/storage/sqlite/migrations/runner.d.ts +1 -1
  361. package/dist/src/storage/sqlite/migrations/runner.js +3 -3
  362. package/dist/src/storage/sqlite/migrations/runner.js.map +1 -1
  363. package/dist/src/storage/sqlite/migrations/runner.ts +1 -1
  364. package/dist/src/storage/sqlite/row-mappers.js +1 -1
  365. package/dist/src/storage/sqlite/schema.js +1 -1
  366. package/dist/src/storage/sqlite/schema.sql +141 -0
  367. package/dist/src/storage/sqlite/session-repository.js +11 -0
  368. package/dist/src/storage/sqlite/session-repository.js.map +1 -1
  369. package/dist/src/tui/backends/embedded-backend.d.ts +13 -0
  370. package/dist/src/tui/backends/embedded-backend.js +76 -7
  371. package/dist/src/tui/backends/embedded-backend.js.map +1 -1
  372. package/dist/src/tui/backends/gateway-sse-backend.d.ts +13 -0
  373. package/dist/src/tui/backends/gateway-sse-backend.js +53 -0
  374. package/dist/src/tui/backends/gateway-sse-backend.js.map +1 -1
  375. package/dist/src/tui/chat-history.js +16 -3
  376. package/dist/src/tui/chat-history.js.map +1 -1
  377. package/dist/src/tui/clipboard-image.js +1 -1
  378. package/dist/src/tui/components/assistant-message.js +12 -2
  379. package/dist/src/tui/components/assistant-message.js.map +1 -1
  380. package/dist/src/tui/components/chat-log.d.ts +23 -3
  381. package/dist/src/tui/components/chat-log.js +68 -9
  382. package/dist/src/tui/components/chat-log.js.map +1 -1
  383. package/dist/src/tui/components/tool-execution.d.ts +8 -0
  384. package/dist/src/tui/components/tool-execution.js +87 -77
  385. package/dist/src/tui/components/tool-execution.js.map +1 -1
  386. package/dist/src/tui/components/tui-bottom-bar.js +9 -5
  387. package/dist/src/tui/components/tui-bottom-bar.js.map +1 -1
  388. package/dist/src/tui/components/visual-truncate.d.ts +1 -0
  389. package/dist/src/tui/components/visual-truncate.js +28 -1
  390. package/dist/src/tui/components/visual-truncate.js.map +1 -1
  391. package/dist/src/tui/tool-summary.d.ts +22 -0
  392. package/dist/src/tui/tool-summary.js +212 -0
  393. package/dist/src/tui/tool-summary.js.map +1 -0
  394. package/dist/src/tui/tui-backend.d.ts +16 -0
  395. package/dist/src/tui/tui-command-formatters.js +2 -2
  396. package/dist/src/tui/tui-commands.d.ts +9 -0
  397. package/dist/src/tui/tui-commands.js +95 -6
  398. package/dist/src/tui/tui-commands.js.map +1 -1
  399. package/dist/src/tui/tui-picker-overlay.d.ts +1 -0
  400. package/dist/src/tui/tui-picker-overlay.js +36 -1
  401. package/dist/src/tui/tui-picker-overlay.js.map +1 -1
  402. package/dist/src/tui/tui-picker-services.d.ts +13 -0
  403. package/dist/src/tui/tui-run-state.js +11 -0
  404. package/dist/src/tui/tui-run-state.js.map +1 -1
  405. package/dist/src/tui/tui-run-status-format.d.ts +3 -0
  406. package/dist/src/tui/tui-run-status-format.js +33 -0
  407. package/dist/src/tui/tui-run-status-format.js.map +1 -0
  408. package/dist/src/tui/tui-session-actions.d.ts +5 -0
  409. package/dist/src/tui/tui-session-actions.js +24 -0
  410. package/dist/src/tui/tui-session-actions.js.map +1 -1
  411. package/dist/src/tui/tui-timeline-picker.d.ts +19 -0
  412. package/dist/src/tui/tui-timeline-picker.js +81 -0
  413. package/dist/src/tui/tui-timeline-picker.js.map +1 -0
  414. package/dist/src/tui/tui-timeline.d.ts +15 -0
  415. package/dist/src/tui/tui-timeline.js +65 -0
  416. package/dist/src/tui/tui-timeline.js.map +1 -0
  417. package/dist/src/tui/tui-tool-diff.d.ts +15 -0
  418. package/dist/src/tui/tui-tool-diff.js +178 -7
  419. package/dist/src/tui/tui-tool-diff.js.map +1 -1
  420. package/dist/src/tui/tui-types.d.ts +1 -0
  421. package/dist/src/tui/tui-types.js +1 -0
  422. package/dist/src/tui/tui-types.js.map +1 -1
  423. package/dist/src/tui/tui.js +31 -25
  424. package/dist/src/tui/tui.js.map +1 -1
  425. package/dist/src/utils/index.js +1 -1
  426. package/dist/src/utils/logger/index.js +1 -1
  427. package/dist/src/utils/logger/stats.d.ts +3 -3
  428. package/dist/src/utils/logger.js +1 -1
  429. package/dist/src/work-items/agent-context.d.ts +7 -0
  430. package/dist/src/work-items/agent-context.js +75 -0
  431. package/dist/src/work-items/agent-context.js.map +1 -0
  432. package/dist/src/work-items/index.d.ts +4 -0
  433. package/dist/src/work-items/index.js +4 -0
  434. package/dist/src/work-items/types.d.ts +112 -0
  435. package/dist/src/work-items/types.js +1 -0
  436. package/dist/src/work-items/work-item-service.d.ts +35 -0
  437. package/dist/src/work-items/work-item-service.js +277 -0
  438. package/dist/src/work-items/work-item-service.js.map +1 -0
  439. package/dist/src/work-items/work-item-store.d.ts +21 -0
  440. package/dist/src/work-items/work-item-store.js +302 -0
  441. package/dist/src/work-items/work-item-store.js.map +1 -0
  442. package/dist/src/workflows/draft/workflow-draft-service.js +1 -1
  443. package/dist/src/workflows/service/workflow-run-service.js +4 -3
  444. package/dist/src/workflows/service/workflow-run-service.js.map +1 -1
  445. package/dist/src/workflows/service/workflow-session-bridge.js +4 -1
  446. package/dist/src/workflows/service/workflow-session-bridge.js.map +1 -1
  447. package/package.json +5 -5
  448. package/dist/gateway/static/root/assets/Combination-HAlzriaz.js +0 -41
  449. package/dist/gateway/static/root/assets/agents-BjIxt67Z.js +0 -2
  450. package/dist/gateway/static/root/assets/app-management-settings-panel-CYCONLIL.js +0 -1
  451. package/dist/gateway/static/root/assets/appearance-settings-Clw3ryKg.js +0 -1
  452. package/dist/gateway/static/root/assets/apps-page-QICTeGjX.js +0 -1
  453. package/dist/gateway/static/root/assets/automation-suggestion-card-CU0-4nQ-.js +0 -1
  454. package/dist/gateway/static/root/assets/automations-page-Car-jtiz.js +0 -1
  455. package/dist/gateway/static/root/assets/browser-settings-page-CMeBJzlS.js +0 -8
  456. package/dist/gateway/static/root/assets/capability-presets-api-BmQTM9Il.js +0 -1
  457. package/dist/gateway/static/root/assets/capability-presets-settings-panel-DZEJEoCF.js +0 -1
  458. package/dist/gateway/static/root/assets/channels-settings-kkW-xFau.js +0 -1
  459. package/dist/gateway/static/root/assets/code-editor-dZTY2dRW.js +0 -1
  460. package/dist/gateway/static/root/assets/connectors-page-BvaQvO5F.js +0 -2
  461. package/dist/gateway/static/root/assets/dist-Mys7eFJ5.js +0 -1
  462. package/dist/gateway/static/root/assets/dist-wO9a2_ID.js +0 -1
  463. package/dist/gateway/static/root/assets/dreaming-settings-DnHO686d.js +0 -1
  464. package/dist/gateway/static/root/assets/extension-debug-page-BGLRuWVN.js +0 -1
  465. package/dist/gateway/static/root/assets/extension-page-D978ePp9.js +0 -1
  466. package/dist/gateway/static/root/assets/extension-settings-page-B6Ih4Swx.js +0 -1
  467. package/dist/gateway/static/root/assets/gateway-settings-CMEA3r5u.js +0 -1
  468. package/dist/gateway/static/root/assets/goal-create-dialog-B-KHKeXN.js +0 -1
  469. package/dist/gateway/static/root/assets/goal-detail-page-BxrSoWdj.js +0 -1
  470. package/dist/gateway/static/root/assets/goals-page-BTJzIl28.js +0 -2
  471. package/dist/gateway/static/root/assets/goals-settings-BJyEuLLm.js +0 -1
  472. package/dist/gateway/static/root/assets/heartbeat-settings-wkOjYNQT.js +0 -1
  473. package/dist/gateway/static/root/assets/index-BLaXr6Ev.css +0 -1
  474. package/dist/gateway/static/root/assets/index-c_9TVr_C.js +0 -191
  475. package/dist/gateway/static/root/assets/keyboard-shortcuts-settings-BT8T4DyC.js +0 -1
  476. package/dist/gateway/static/root/assets/logs-page-CrxBJUgI.js +0 -2
  477. package/dist/gateway/static/root/assets/markdown-split-Dv66bO2b.js +0 -1
  478. package/dist/gateway/static/root/assets/messages-O6TAtdFC.js +0 -3
  479. package/dist/gateway/static/root/assets/models-hub-panel-DOOpz6y1.js +0 -2
  480. package/dist/gateway/static/root/assets/notes-page-Br16pK9v.js +0 -1
  481. package/dist/gateway/static/root/assets/notes-workbench-PSJAi0ZC.js +0 -2
  482. package/dist/gateway/static/root/assets/project-detail-page-CIGGgKuw.js +0 -1
  483. package/dist/gateway/static/root/assets/projects-page-B2grhsBt.js +0 -1
  484. package/dist/gateway/static/root/assets/remote-access-hub-CXMORxBD.js +0 -1
  485. package/dist/gateway/static/root/assets/sessions-page-Bi2wkBzU.js +0 -1
  486. package/dist/gateway/static/root/assets/settings-advanced-gate-B1L3G4IA.js +0 -1
  487. package/dist/gateway/static/root/assets/settings-form-section-BnqYMWHR.js +0 -1
  488. package/dist/gateway/static/root/assets/settings-page-BfRSHJmO.js +0 -1
  489. package/dist/gateway/static/root/assets/settings-page-layout-CdWZU1hd.js +0 -1
  490. package/dist/gateway/static/root/assets/setup-status-panel-CWtPM7RK.js +0 -1
  491. package/dist/gateway/static/root/assets/shares-settings-ngbsBgij.js +0 -1
  492. package/dist/gateway/static/root/assets/skill-reload-api-BIe442Gv.js +0 -1
  493. package/dist/gateway/static/root/assets/skills-page-BfchZRVa.js +0 -2
  494. package/dist/gateway/static/root/assets/voice-api-key-field-C5Ov8Uk_.js +0 -1
  495. package/dist/gateway/static/root/assets/workflow-run-setup-panel-BYD9BtOq.js +0 -3
  496. package/dist/gateway/static/root/assets/workflows-page-BYF29ANm.js +0 -18
@@ -1,14 +1,14 @@
1
1
  import { theme } from "../theme.js";
2
2
  import { formatKeyIds } from "../format-tui-hotkeys.js";
3
- import { isDiffFriendlyTool, looksLikeUnifiedDiff, renderUnifiedDiff } from "../tui-tool-diff.js";
3
+ import { displayToolName, formatArgsSummary, formatCollapsedToolSummary, formatExecExpandedOutput, getToolSummaryKind, isExecStyleTool, isReadStyleTool } from "../tool-summary.js";
4
+ import { isDiffFriendlyTool, looksLikeUnifiedDiff, renderPatchSummary, renderUnifiedDiff } from "../tui-tool-diff.js";
4
5
  import { parseTuiToolResult } from "../tui-tool-result.js";
5
- import { truncateToVisualLines } from "./visual-truncate.js";
6
+ import { truncateToVisualLines, truncateToVisualLinesMiddle } from "./visual-truncate.js";
6
7
  import { hasStructuredTuiToolRenderer, renderToolCallWithExtensions, renderToolResultWithExtensions, renderToolWithExtensions } from "../extension-host/tool-renderers.js";
7
- import { basename, dirname } from "node:path";
8
8
  import { Container, Image, Spacer, Text, getCapabilities } from "@earendil-works/pi-tui";
9
9
  //#region src/tui/components/tool-execution.ts
10
- const MAX_ARG_VALUE_LENGTH = 120;
11
10
  const COLLAPSED_RESULT_VISUAL_LINES = 4;
11
+ const EXPANDED_RESULT_VISUAL_LINES = 80;
12
12
  function sanitize(text) {
13
13
  return text.replace(/[\x00-\x08\x0B\x0C\x0E-\x1F]/g, "");
14
14
  }
@@ -30,65 +30,6 @@ function getToolResultDisplayText(content, options) {
30
30
  }
31
31
  return trimTrailingBlankDisplayLines(parts.filter(Boolean).join("\n"));
32
32
  }
33
- function formatArgsSummary(args, toolName) {
34
- if (!args || typeof args !== "object") return "";
35
- const compactRead = isReadStyleTool(toolName) ? formatCompactReadArgs(args) : null;
36
- if (compactRead) return compactRead;
37
- const entries = Object.entries(args);
38
- if (entries.length === 0) return "";
39
- return entries.map(([key, value]) => {
40
- const stringValue = formatArgValue(value);
41
- return `${key}=${stringValue.length > MAX_ARG_VALUE_LENGTH ? `${stringValue.slice(0, MAX_ARG_VALUE_LENGTH - 3)}...` : stringValue}`;
42
- }).join(", ");
43
- }
44
- function isReadStyleTool(toolName) {
45
- return [
46
- "read",
47
- "read_file",
48
- "memory_get"
49
- ].includes(toolName);
50
- }
51
- function formatCompactReadArgs(args) {
52
- if (!args || typeof args !== "object") return null;
53
- const record = args;
54
- const rawPath = typeof record.path === "string" ? record.path : typeof record.file_path === "string" ? record.file_path : void 0;
55
- if (!rawPath) return null;
56
- const normalized = rawPath.replace(/\\/g, "/");
57
- const base = basename(normalized);
58
- let label = null;
59
- if (base === "SKILL.md") {
60
- const parent = basename(dirname(normalized));
61
- label = parent ? `[skill] ${parent}` : "[skill]";
62
- } else if (base === "AGENTS.md") label = `read resource ${normalized}`;
63
- if (!label) return null;
64
- const start = firstFiniteNumber(record.offset, record.from, record.start, record.line);
65
- const count = firstFiniteNumber(record.limit, record.lines, record.count);
66
- if (start != null && count != null && count > 0) label += `:${start}-${start + count - 1}`;
67
- return label;
68
- }
69
- function firstFiniteNumber(...values) {
70
- for (const value of values) {
71
- if (typeof value === "number" && Number.isFinite(value)) return Math.floor(value);
72
- if (typeof value === "string" && value.trim()) {
73
- const parsed = Number(value);
74
- if (Number.isFinite(parsed)) return Math.floor(parsed);
75
- }
76
- }
77
- return null;
78
- }
79
- function formatArgValue(value) {
80
- if (typeof value === "string") return value;
81
- if (typeof value === "bigint") return `${value.toString()}n`;
82
- if (typeof value === "function") return "[function]";
83
- if (typeof value === "symbol") return String(value);
84
- if (value instanceof Error) return value.message || value.name;
85
- try {
86
- const json = JSON.stringify(value);
87
- return json === void 0 ? String(value) : json;
88
- } catch {
89
- return String(value);
90
- }
91
- }
92
33
  function isTuiComponent(value) {
93
34
  return Boolean(value && typeof value === "object" && typeof value.render === "function");
94
35
  }
@@ -97,6 +38,7 @@ var ToolExecutionComponent = class extends Container {
97
38
  contentText;
98
39
  collapsedOutputComponent = null;
99
40
  collapsedReadSummaryComponent = null;
41
+ expandedOutputComponent = null;
100
42
  toolName;
101
43
  toolCallId;
102
44
  args;
@@ -122,6 +64,8 @@ var ToolExecutionComponent = class extends Container {
122
64
  isError = false;
123
65
  isPartial = true;
124
66
  executionStarted = false;
67
+ startedAt = Date.now();
68
+ completedAt;
125
69
  constructor(toolName, toolCallId, args, options = {}) {
126
70
  super();
127
71
  this.toolName = toolName;
@@ -145,6 +89,7 @@ var ToolExecutionComponent = class extends Container {
145
89
  }
146
90
  markExecutionStarted() {
147
91
  this.executionStarted = true;
92
+ this.startedAt = Date.now();
148
93
  this.refresh();
149
94
  }
150
95
  setArgsComplete() {
@@ -162,6 +107,7 @@ var ToolExecutionComponent = class extends Container {
162
107
  this.resultDetails = parsed.envelope?.details;
163
108
  this.isError = isError;
164
109
  this.isPartial = isPartial;
110
+ if (!isPartial) this.completedAt = Date.now();
165
111
  this.refresh();
166
112
  }
167
113
  setImageOptions(options) {
@@ -180,6 +126,7 @@ var ToolExecutionComponent = class extends Container {
180
126
  const bgFn = this.isPartial ? (text) => theme.toolPendingBg(text) : this.isError ? (text) => theme.toolErrorBg(text) : (text) => theme.toolSuccessBg(text);
181
127
  this.refreshCollapsedOutput(null);
182
128
  this.refreshCollapsedReadSummary(null);
129
+ this.refreshExpandedOutput(null);
183
130
  if (this.customRendererComponent) {
184
131
  this.contentContainer.removeChild(this.customRendererComponent);
185
132
  this.customRendererComponent = void 0;
@@ -290,8 +237,10 @@ var ToolExecutionComponent = class extends Container {
290
237
  }
291
238
  formatToolCallFallback() {
292
239
  const argsStr = formatArgsSummary(this.args, this.toolName);
293
- const titleParts = [theme.toolTitle(theme.bold(this.toolName))];
240
+ const titleParts = [theme.dim(this.toolStatusLabel()), theme.toolTitle(theme.bold(displayToolName(this.toolName)))];
294
241
  if (argsStr) titleParts.push(theme.dim(`(${argsStr})`));
242
+ const duration = this.toolDurationLabel();
243
+ if (duration) titleParts.push(theme.dim(duration));
295
244
  if (this.isPartial && !this.resultText && !this.resultContent && this.resultDetails === void 0) titleParts.push(theme.dim("…"));
296
245
  return titleParts.join(" ");
297
246
  }
@@ -301,18 +250,18 @@ var ToolExecutionComponent = class extends Container {
301
250
  if (output) {
302
251
  const expandKey = this.keybindings ? formatKeyIds(this.keybindings, "app.tools.expand", { capitalize: true }) : "Ctrl+O";
303
252
  const lineCount = output.split("\n").length;
304
- if (this.expanded && isDiffFriendlyTool(this.toolName) && looksLikeUnifiedDiff(output)) text += renderUnifiedDiff(output);
305
- else if (this.expanded) text += theme.toolOutput(output);
306
- else if (isReadStyleTool(this.toolName)) {
307
- const rows = new Text(output, 1, 0).render(80).length;
308
- const plural = rows === 1 ? "row" : "rows";
309
- text += theme.dim(` ${rows} ${plural}; ${expandKey} to expand`);
310
- } else {
253
+ const useDiff = isDiffFriendlyTool(this.toolName) && looksLikeUnifiedDiff(output);
254
+ if (this.expanded && useDiff) text += renderPatchSummary(output) ?? renderUnifiedDiff(output);
255
+ else if (this.expanded && isExecStyleTool(this.toolName)) this.refreshExpandedOutput(theme.toolOutput(formatExecExpandedOutput(output, this.resultDetails)));
256
+ else if (this.expanded) this.refreshExpandedOutput(theme.toolOutput(output));
257
+ else if (useDiff) text += theme.dim("preview");
258
+ else if (getToolSummaryKind(this.toolName) !== "generic") text += this.collapsedSpecializedSummary(output, expandKey);
259
+ else {
311
260
  const suffix = lineCount > COLLAPSED_RESULT_VISUAL_LINES ? theme.dim(` (${lineCount} lines; ${expandKey} to expand)`) : "";
312
261
  text += theme.dim(`preview${suffix}`);
313
262
  }
314
263
  }
315
- if (this.expanded && this.resultDetails !== void 0) {
264
+ if (this.shouldRenderDetailsPreview()) {
316
265
  const detailsText = formatDetailsPreview(this.resultDetails);
317
266
  if (detailsText) text = [text, theme.dim(detailsText)].filter(Boolean).join("\n");
318
267
  }
@@ -320,28 +269,62 @@ var ToolExecutionComponent = class extends Container {
320
269
  }
321
270
  formatToolExecution() {
322
271
  const argsStr = formatArgsSummary(this.args, this.toolName);
323
- const titleParts = [theme.toolTitle(theme.bold(this.toolName))];
272
+ const titleParts = [theme.dim(this.toolStatusLabel()), theme.toolTitle(theme.bold(displayToolName(this.toolName)))];
324
273
  if (argsStr) titleParts.push(theme.dim(`(${argsStr})`));
274
+ const duration = this.toolDurationLabel();
275
+ if (duration) titleParts.push(theme.dim(duration));
325
276
  let text = titleParts.join(" ");
326
277
  const output = this.getDisplayResultText();
327
278
  if (output) {
328
279
  const expandKey = this.keybindings ? formatKeyIds(this.keybindings, "app.tools.expand", { capitalize: true }) : "Ctrl+O";
329
280
  const lineCount = output.split("\n").length;
330
- if (this.expanded && isDiffFriendlyTool(this.toolName) && looksLikeUnifiedDiff(output)) text += `\n${renderUnifiedDiff(output)}`;
331
- else if (this.expanded) text += `\n${theme.toolOutput(output)}`;
332
- else if (isReadStyleTool(this.toolName)) this.refreshCollapsedReadSummary(output, expandKey);
281
+ const useDiff = isDiffFriendlyTool(this.toolName) && looksLikeUnifiedDiff(output);
282
+ if (this.expanded && useDiff) text += `\n${renderPatchSummary(output) ?? renderUnifiedDiff(output)}`;
283
+ else if (this.expanded && isExecStyleTool(this.toolName)) this.refreshExpandedOutput(theme.toolOutput(formatExecExpandedOutput(output, this.resultDetails)));
284
+ else if (this.expanded) this.refreshExpandedOutput(theme.toolOutput(output));
285
+ else if (useDiff) {
286
+ const suffix = output.split("\n").length > COLLAPSED_RESULT_VISUAL_LINES ? theme.dim(` (${output.split("\n").length} lines; ${expandKey} to expand)`) : "";
287
+ text += `\n${theme.dim(`preview${suffix}`)}`;
288
+ } else if (isReadStyleTool(this.toolName)) this.refreshCollapsedReadSummary(output, expandKey);
289
+ else if (getToolSummaryKind(this.toolName) !== "generic") text += `\n${this.collapsedSpecializedSummary(output, expandKey)}`;
333
290
  else {
334
291
  const suffix = lineCount > COLLAPSED_RESULT_VISUAL_LINES ? theme.dim(` (${lineCount} lines; ${expandKey} to expand)`) : "";
335
292
  text += `\n${theme.dim(`preview${suffix}`)}`;
336
293
  this.refreshCollapsedOutput(theme.toolOutput(output), lineCount > COLLAPSED_RESULT_VISUAL_LINES ? void 0 : `${expandKey} to expand`);
337
294
  }
338
295
  } else if (this.isPartial) text += `\n${theme.dim("…")}`;
339
- if (this.expanded && this.resultDetails !== void 0) {
296
+ if (this.shouldRenderDetailsPreview()) {
340
297
  const detailsText = formatDetailsPreview(this.resultDetails);
341
298
  if (detailsText) text += `\n${theme.dim(detailsText)}`;
342
299
  }
343
300
  return text;
344
301
  }
302
+ toolStatusLabel() {
303
+ if (this.isError) return "Failed";
304
+ if (this.isPartial && !this.resultText && !this.resultContent && this.resultDetails === void 0) return this.executionStarted ? "Calling" : "Queued";
305
+ if (this.isPartial) return "Calling";
306
+ return "Called";
307
+ }
308
+ toolDurationLabel() {
309
+ if (this.completedAt === void 0) return "";
310
+ const durationMs = Math.max(0, this.completedAt - this.startedAt);
311
+ if (durationMs < 100) return "";
312
+ return `${durationMs}ms`;
313
+ }
314
+ collapsedSpecializedSummary(output, expandKey) {
315
+ return theme.dim(formatCollapsedToolSummary({
316
+ toolName: this.toolName,
317
+ args: this.args,
318
+ output,
319
+ content: this.resultContent,
320
+ details: this.resultDetails,
321
+ isError: this.isError,
322
+ expandKey
323
+ }));
324
+ }
325
+ shouldRenderDetailsPreview() {
326
+ return this.expanded && this.resultDetails !== void 0 && !isExecStyleTool(this.toolName);
327
+ }
345
328
  getDisplayResultText() {
346
329
  if (!this.resultContent) return trimTrailingBlankDisplayLines(this.resultText);
347
330
  return getToolResultDisplayText(this.resultContent, {
@@ -384,6 +367,15 @@ var ToolExecutionComponent = class extends Container {
384
367
  this.collapsedReadSummaryComponent = createCollapsedReadSummaryComponent(text, expandKey, 1);
385
368
  this.contentContainer.addChild(this.collapsedReadSummaryComponent);
386
369
  }
370
+ refreshExpandedOutput(text) {
371
+ if (this.expandedOutputComponent) {
372
+ this.contentContainer.removeChild(this.expandedOutputComponent);
373
+ this.expandedOutputComponent = null;
374
+ }
375
+ if (!text) return;
376
+ this.expandedOutputComponent = createVisualMiddleComponent(text, EXPANDED_RESULT_VISUAL_LINES, 1);
377
+ this.contentContainer.addChild(this.expandedOutputComponent);
378
+ }
387
379
  };
388
380
  function formatDetailsPreview(details) {
389
381
  if (details === null) return "";
@@ -412,6 +404,24 @@ function createVisualTailComponent(text, maxVisualLines, paddingX, truncationHin
412
404
  }
413
405
  };
414
406
  }
407
+ function createVisualMiddleComponent(text, maxVisualLines, paddingX) {
408
+ let cachedWidth;
409
+ let cachedLines;
410
+ return {
411
+ render(width) {
412
+ if (cachedWidth !== width || cachedLines === void 0) {
413
+ const result = truncateToVisualLinesMiddle(text, maxVisualLines, width, paddingX);
414
+ cachedWidth = width;
415
+ cachedLines = result.visualLines;
416
+ }
417
+ return cachedLines;
418
+ },
419
+ invalidate() {
420
+ cachedWidth = void 0;
421
+ cachedLines = void 0;
422
+ }
423
+ };
424
+ }
415
425
  function createCollapsedReadSummaryComponent(text, expandKey, paddingX) {
416
426
  let cachedWidth;
417
427
  let cachedLine;
@@ -1 +1 @@
1
- {"version":3,"file":"tool-execution.js","names":[],"sources":["../../../../src/tui/components/tool-execution.ts"],"sourcesContent":["import {\n Container,\n type Component,\n getCapabilities,\n Image,\n type KeybindingsManager,\n Spacer,\n Text,\n} from '@earendil-works/pi-tui';\nimport { basename, dirname } from 'node:path';\nimport type { AgentToolResult } from '@earendil-works/pi-agent-core';\n\nimport { theme } from '../theme.js';\nimport { formatKeyIds } from '../format-tui-hotkeys.js';\nimport { isDiffFriendlyTool, looksLikeUnifiedDiff, renderUnifiedDiff } from '../tui-tool-diff.js';\nimport {\n hasStructuredTuiToolRenderer,\n renderToolCallWithExtensions,\n renderToolResultWithExtensions,\n renderToolWithExtensions,\n} from '../extension-host/tool-renderers.js';\nimport {\n parseTuiToolResult,\n type TuiToolContentBlock,\n} from '../tui-tool-result.js';\nimport { truncateToVisualLines } from './visual-truncate.js';\n\nconst MAX_ARG_VALUE_LENGTH = 120;\nconst COLLAPSED_RESULT_VISUAL_LINES = 4;\n\nexport interface ToolExecutionOptions {\n showImages?: boolean;\n imageWidthCells?: number;\n keybindings?: KeybindingsManager;\n toolCallId?: string;\n cwd?: string;\n}\n\nfunction sanitize(text: string): string {\n return text.replace(/[\\x00-\\x08\\x0B\\x0C\\x0E-\\x1F]/g, '');\n}\n\nfunction trimTrailingBlankDisplayLines(text: string): string {\n return text.replace(/(?:\\r?\\n[ \\t]*)+$/g, '');\n}\n\nexport function getToolResultDisplayText(\n content: TuiToolContentBlock[],\n options: { showImages: boolean; supportsInlineImages: boolean },\n): string {\n const parts: string[] = [];\n for (const block of content) {\n if (block.type === 'text') {\n if (block.text) parts.push(sanitize(block.text));\n continue;\n }\n if (block.type === 'image' && (!options.supportsInlineImages || !options.showImages)) {\n parts.push(block.mimeType ? `[image:${block.mimeType}]` : '[image]');\n continue;\n }\n if (block.type !== 'image') {\n parts.push(block.text ? sanitize(block.text) : `[${block.type}]`);\n }\n }\n return trimTrailingBlankDisplayLines(parts.filter(Boolean).join('\\n'));\n}\n\nfunction formatArgsSummary(args: unknown, toolName: string): string {\n if (!args || typeof args !== 'object') return '';\n const compactRead = isReadStyleTool(toolName) ? formatCompactReadArgs(args) : null;\n if (compactRead) return compactRead;\n const entries = Object.entries(args as Record<string, unknown>);\n if (entries.length === 0) return '';\n return entries\n .map(([key, value]) => {\n const stringValue = formatArgValue(value);\n const truncated =\n stringValue.length > MAX_ARG_VALUE_LENGTH\n ? `${stringValue.slice(0, MAX_ARG_VALUE_LENGTH - 3)}...`\n : stringValue;\n return `${key}=${truncated}`;\n })\n .join(', ');\n}\n\nfunction isReadStyleTool(toolName: string): boolean {\n return ['read', 'read_file', 'memory_get'].includes(toolName);\n}\n\nfunction formatCompactReadArgs(args: unknown): string | null {\n if (!args || typeof args !== 'object') return null;\n const record = args as Record<string, unknown>;\n const rawPath = typeof record.path === 'string'\n ? record.path\n : typeof record.file_path === 'string'\n ? record.file_path\n : undefined;\n if (!rawPath) return null;\n\n const normalized = rawPath.replace(/\\\\/g, '/');\n const base = basename(normalized);\n let label: string | null = null;\n if (base === 'SKILL.md') {\n const parent = basename(dirname(normalized));\n label = parent ? `[skill] ${parent}` : '[skill]';\n } else if (base === 'AGENTS.md') {\n label = `read resource ${normalized}`;\n }\n if (!label) return null;\n\n const start = firstFiniteNumber(record.offset, record.from, record.start, record.line);\n const count = firstFiniteNumber(record.limit, record.lines, record.count);\n if (start != null && count != null && count > 0) {\n label += `:${start}-${start + count - 1}`;\n }\n return label;\n}\n\nfunction firstFiniteNumber(...values: unknown[]): number | null {\n for (const value of values) {\n if (typeof value === 'number' && Number.isFinite(value)) return Math.floor(value);\n if (typeof value === 'string' && value.trim()) {\n const parsed = Number(value);\n if (Number.isFinite(parsed)) return Math.floor(parsed);\n }\n }\n return null;\n}\n\nfunction formatArgValue(value: unknown): string {\n if (typeof value === 'string') return value;\n if (typeof value === 'bigint') return `${value.toString()}n`;\n if (typeof value === 'function') return '[function]';\n if (typeof value === 'symbol') return String(value);\n if (value instanceof Error) return value.message || value.name;\n try {\n const json = JSON.stringify(value);\n return json === undefined ? String(value) : json;\n } catch {\n return String(value);\n }\n}\n\nfunction isTuiComponent(value: unknown): value is Component {\n return Boolean(\n value &&\n typeof value === 'object' &&\n typeof (value as { render?: unknown }).render === 'function',\n );\n}\n\nexport class ToolExecutionComponent extends Container {\n private contentContainer: Container;\n private contentText: Text;\n private collapsedOutputComponent: ReturnType<typeof createVisualTailComponent> | null = null;\n private collapsedReadSummaryComponent: ReturnType<typeof createCollapsedReadSummaryComponent> | null = null;\n private toolName: string;\n private toolCallId: string;\n private args: unknown;\n private argsComplete = true;\n private resultText = '';\n private resultContent: TuiToolContentBlock[] | undefined;\n private resultDetails: unknown;\n private rendererState: Record<string, unknown> = {};\n private lastRendererOutput: string[] | Component | undefined;\n private lastCallRendererOutput: string[] | Component | undefined;\n private lastResultRendererOutput: string[] | Component | undefined;\n private customRendererComponent: Component | undefined;\n private structuredRendererComponents: Component[] = [];\n private contentTextAttached = true;\n private rendererInvalidationQueued = false;\n private imageComponents: Image[] = [];\n private imageSpacers: Spacer[] = [];\n private showImages: boolean;\n private imageWidthCells: number;\n private keybindings: KeybindingsManager | undefined;\n private cwd: string;\n private expanded = false;\n private isError = false;\n private isPartial = true;\n private executionStarted = false;\n\n constructor(toolName: string, toolCallId: string, args: unknown, options: ToolExecutionOptions = {}) {\n super();\n this.toolName = toolName;\n this.toolCallId = toolCallId;\n this.args = args;\n this.showImages = options.showImages ?? true;\n this.imageWidthCells = Math.max(1, Math.floor(options.imageWidthCells ?? 60));\n this.keybindings = options.keybindings;\n this.cwd = options.cwd ?? process.cwd();\n\n this.addChild(new Spacer(1));\n\n const bgFn = (text: string) => theme.toolPendingBg(text);\n this.contentContainer = new Container();\n this.contentText = new Text('', 1, 1, bgFn);\n this.contentContainer.addChild(this.contentText);\n this.addChild(this.contentContainer);\n\n this.refresh();\n }\n\n setArgs(args: unknown): void {\n this.args = args;\n this.refresh();\n }\n\n markExecutionStarted(): void {\n this.executionStarted = true;\n this.refresh();\n }\n\n setArgsComplete(): void {\n this.argsComplete = true;\n this.refresh();\n }\n\n setExpanded(expanded: boolean): void {\n this.expanded = expanded;\n this.refresh();\n }\n\n updateResult(result: AgentToolResult<any> | unknown, isPartial = false, isError = false): void {\n const parsed = parseTuiToolResult(result);\n this.resultText = sanitize(parsed.text);\n this.resultContent = parsed.envelope?.content;\n this.resultDetails = parsed.envelope?.details;\n this.isError = isError;\n this.isPartial = isPartial;\n this.refresh();\n }\n\n setImageOptions(options: ToolExecutionOptions): void {\n if (options.showImages !== undefined) {\n this.showImages = options.showImages;\n }\n if (options.imageWidthCells !== undefined) {\n this.imageWidthCells = Math.max(1, Math.floor(options.imageWidthCells));\n }\n if (options.keybindings !== undefined) {\n this.keybindings = options.keybindings;\n }\n if (options.cwd !== undefined) {\n this.cwd = options.cwd;\n }\n this.refresh();\n }\n\n setPartialDetails(details: unknown): void {\n this.resultDetails = details;\n this.isPartial = true;\n this.refresh();\n }\n\n private refresh(): void {\n const bgFn = this.isPartial\n ? (text: string) => theme.toolPendingBg(text)\n : this.isError\n ? (text: string) => theme.toolErrorBg(text)\n : (text: string) => theme.toolSuccessBg(text);\n this.refreshCollapsedOutput(null);\n this.refreshCollapsedReadSummary(null);\n if (this.customRendererComponent) {\n this.contentContainer.removeChild(this.customRendererComponent);\n this.customRendererComponent = undefined;\n }\n for (const component of this.structuredRendererComponents) {\n this.contentContainer.removeChild(component);\n }\n this.structuredRendererComponents = [];\n this.contentText.setCustomBgFn(bgFn);\n\n if (hasStructuredTuiToolRenderer(this.toolName)) {\n this.detachContentText();\n this.renderStructuredExtensionTool();\n } else {\n const custom = this.renderExtensionTool();\n if (Array.isArray(custom) && custom.length > 0) {\n this.ensureContentTextAttached();\n this.lastRendererOutput = custom;\n this.contentText.setText(custom.join('\\n'));\n } else if (isTuiComponent(custom)) {\n this.detachContentText();\n this.customRendererComponent = custom;\n this.lastRendererOutput = custom;\n this.contentContainer.addChild(custom);\n } else {\n this.ensureContentTextAttached();\n this.lastRendererOutput = undefined;\n this.contentText.setText(this.formatToolExecution());\n }\n }\n this.refreshImages();\n }\n\n private appendRendererResult(result: ReturnType<typeof renderToolWithExtensions>): boolean {\n if (Array.isArray(result) && result.length > 0) {\n const component = new Text(result.join('\\n'), 1, 1);\n this.structuredRendererComponents.push(component);\n this.contentContainer.addChild(component);\n return true;\n }\n if (isTuiComponent(result)) {\n this.structuredRendererComponents.push(result);\n this.contentContainer.addChild(result);\n return true;\n }\n return false;\n }\n\n private renderStructuredExtensionTool(): void {\n const call = this.renderExtensionToolCall();\n if (this.appendRendererResult(call)) {\n this.lastCallRendererOutput = call as string[] | Component;\n } else {\n this.lastCallRendererOutput = undefined;\n this.ensureContentTextAttached();\n this.contentText.setText(this.formatToolCallFallback());\n }\n\n if (!this.isPartial || this.resultDetails !== undefined || this.resultText || this.resultContent) {\n const result = this.renderExtensionToolResult();\n if (this.appendRendererResult(result)) {\n this.lastResultRendererOutput = result as string[] | Component;\n } else {\n this.appendRendererResult([this.formatToolResultFallback()].filter(Boolean));\n this.lastResultRendererOutput = undefined;\n }\n }\n }\n\n private ensureContentTextAttached(): void {\n if (this.contentTextAttached) return;\n this.contentContainer.addChild(this.contentText);\n this.contentTextAttached = true;\n }\n\n private detachContentText(): void {\n if (!this.contentTextAttached) return;\n this.contentContainer.removeChild(this.contentText);\n this.contentTextAttached = false;\n }\n\n private requestRendererInvalidate(): void {\n if (this.rendererInvalidationQueued) return;\n this.rendererInvalidationQueued = true;\n queueMicrotask(() => {\n this.rendererInvalidationQueued = false;\n this.refresh();\n this.invalidate();\n });\n }\n\n private renderExtensionTool(): ReturnType<typeof renderToolWithExtensions> {\n return renderToolWithExtensions(this.createRenderContext(this.lastRendererOutput));\n }\n\n private renderExtensionToolCall(): ReturnType<typeof renderToolWithExtensions> {\n return renderToolCallWithExtensions(\n this.createRenderContext(this.lastCallRendererOutput),\n theme,\n );\n }\n\n private renderExtensionToolResult(): ReturnType<typeof renderToolWithExtensions> {\n return renderToolResultWithExtensions(\n this.createRenderContext(this.lastResultRendererOutput),\n theme,\n );\n }\n\n private createRenderContext(lastComponent: string[] | Component | undefined) {\n return {\n toolName: this.toolName,\n toolCallId: this.toolCallId,\n args: this.args,\n resultText: this.getDisplayResultText(),\n content: this.resultContent,\n details: this.resultDetails,\n invalidate: () => this.requestRendererInvalidate(),\n lastComponent,\n state: this.rendererState,\n cwd: this.cwd,\n executionStarted: this.executionStarted,\n argsComplete: this.argsComplete,\n isError: this.isError,\n isPartial: this.isPartial,\n expanded: this.expanded,\n showImages: this.showImages,\n };\n }\n\n private formatToolCallFallback(): string {\n const argsStr = formatArgsSummary(this.args, this.toolName);\n const titleParts = [theme.toolTitle(theme.bold(this.toolName))];\n if (argsStr) {\n titleParts.push(theme.dim(`(${argsStr})`));\n }\n if (this.isPartial && !this.resultText && !this.resultContent && this.resultDetails === undefined) {\n titleParts.push(theme.dim('…'));\n }\n return titleParts.join(' ');\n }\n\n private formatToolResultFallback(): string {\n const output = this.getDisplayResultText();\n let text = '';\n if (output) {\n const expandKey = this.keybindings\n ? formatKeyIds(this.keybindings, 'app.tools.expand', { capitalize: true })\n : 'Ctrl+O';\n const lineCount = output.split('\\n').length;\n const useDiff =\n this.expanded &&\n isDiffFriendlyTool(this.toolName) &&\n looksLikeUnifiedDiff(output);\n if (useDiff) {\n text += renderUnifiedDiff(output);\n } else if (this.expanded) {\n text += theme.toolOutput(output);\n } else if (isReadStyleTool(this.toolName)) {\n const rows = new Text(output, 1, 0).render(80).length;\n const plural = rows === 1 ? 'row' : 'rows';\n text += theme.dim(` ${rows} ${plural}; ${expandKey} to expand`);\n } else {\n const suffix = lineCount > COLLAPSED_RESULT_VISUAL_LINES\n ? theme.dim(` (${lineCount} lines; ${expandKey} to expand)`)\n : '';\n text += theme.dim(`preview${suffix}`);\n }\n }\n if (this.expanded && this.resultDetails !== undefined) {\n const detailsText = formatDetailsPreview(this.resultDetails);\n if (detailsText) {\n text = [text, theme.dim(detailsText)].filter(Boolean).join('\\n');\n }\n }\n return text;\n }\n\n private formatToolExecution(): string {\n // Title line: 🔧 tool_name (args_summary)\n const argsStr = formatArgsSummary(this.args, this.toolName);\n const titleParts = [theme.toolTitle(theme.bold(this.toolName))];\n if (argsStr) {\n titleParts.push(theme.dim(`(${argsStr})`));\n }\n let text = titleParts.join(' ');\n\n // Output / result — collapsed: single-line summary; expanded: full output\n const output = this.getDisplayResultText();\n if (output) {\n const expandKey = this.keybindings\n ? formatKeyIds(this.keybindings, 'app.tools.expand', { capitalize: true })\n : 'Ctrl+O';\n const lineCount = output.split('\\n').length;\n const useDiff =\n this.expanded &&\n isDiffFriendlyTool(this.toolName) &&\n looksLikeUnifiedDiff(output);\n if (useDiff) {\n text += `\\n${renderUnifiedDiff(output)}`;\n } else if (this.expanded) {\n text += `\\n${theme.toolOutput(output)}`;\n } else if (isReadStyleTool(this.toolName)) {\n this.refreshCollapsedReadSummary(output, expandKey);\n } else {\n const suffix = lineCount > COLLAPSED_RESULT_VISUAL_LINES\n ? theme.dim(` (${lineCount} lines; ${expandKey} to expand)`)\n : '';\n text += `\\n${theme.dim(`preview${suffix}`)}`;\n this.refreshCollapsedOutput(\n theme.toolOutput(output),\n lineCount > COLLAPSED_RESULT_VISUAL_LINES ? undefined : `${expandKey} to expand`,\n );\n }\n } else if (this.isPartial) {\n text += `\\n${theme.dim('…')}`;\n }\n\n if (this.expanded && this.resultDetails !== undefined) {\n const detailsText = formatDetailsPreview(this.resultDetails);\n if (detailsText) {\n text += `\\n${theme.dim(detailsText)}`;\n }\n }\n\n return text;\n }\n\n private getDisplayResultText(): string {\n if (!this.resultContent) {\n return trimTrailingBlankDisplayLines(this.resultText);\n }\n return getToolResultDisplayText(this.resultContent, {\n showImages: this.showImages,\n supportsInlineImages: Boolean(getCapabilities().images),\n });\n }\n\n private refreshImages(): void {\n for (const image of this.imageComponents) {\n this.removeChild(image);\n }\n this.imageComponents = [];\n for (const spacer of this.imageSpacers) {\n this.removeChild(spacer);\n }\n this.imageSpacers = [];\n\n const imageBlocks = this.resultContent?.filter(\n (block) => block.type === 'image' && block.data && block.mimeType,\n ) ?? [];\n if (imageBlocks.length === 0) return;\n\n const capabilities = getCapabilities();\n if (!capabilities.images || !this.showImages) return;\n\n for (const block of imageBlocks) {\n const spacer = new Spacer(1);\n const image = new Image(\n block.data!,\n block.mimeType!,\n { fallbackColor: (text: string) => theme.toolOutput(text) },\n { maxWidthCells: this.imageWidthCells },\n );\n this.imageSpacers.push(spacer);\n this.imageComponents.push(image);\n this.addChild(spacer);\n this.addChild(image);\n }\n }\n\n private refreshCollapsedOutput(text: string | null, truncationHint?: string): void {\n if (this.collapsedOutputComponent) {\n this.contentContainer.removeChild(this.collapsedOutputComponent);\n this.collapsedOutputComponent = null;\n }\n if (!text) return;\n this.collapsedOutputComponent = createVisualTailComponent(\n text,\n COLLAPSED_RESULT_VISUAL_LINES,\n 1,\n truncationHint,\n );\n this.contentContainer.addChild(this.collapsedOutputComponent);\n }\n\n private refreshCollapsedReadSummary(text: string | null, expandKey?: string): void {\n if (this.collapsedReadSummaryComponent) {\n this.contentContainer.removeChild(this.collapsedReadSummaryComponent);\n this.collapsedReadSummaryComponent = null;\n }\n if (!text || !expandKey) return;\n this.collapsedReadSummaryComponent = createCollapsedReadSummaryComponent(text, expandKey, 1);\n this.contentContainer.addChild(this.collapsedReadSummaryComponent);\n }\n}\n\nfunction formatDetailsPreview(details: unknown): string {\n if (details === null) return '';\n if (typeof details === 'string') return details;\n try {\n return JSON.stringify(details, null, 2);\n } catch {\n return String(details);\n }\n}\n\nfunction createVisualTailComponent(\n text: string,\n maxVisualLines: number,\n paddingX: number,\n truncationHint?: string,\n) {\n let cachedWidth: number | undefined;\n let cachedLines: string[] | undefined;\n return {\n render(width: number): string[] {\n if (cachedWidth !== width || cachedLines === undefined) {\n const result = truncateToVisualLines(text, maxVisualLines, width, paddingX);\n cachedWidth = width;\n cachedLines =\n result.skippedCount > 0 && truncationHint\n ? [theme.dim(` (${result.skippedCount} rows hidden; ${truncationHint})`), ...result.visualLines]\n : result.visualLines;\n }\n return cachedLines;\n },\n invalidate(): void {\n cachedWidth = undefined;\n cachedLines = undefined;\n },\n };\n}\n\nfunction createCollapsedReadSummaryComponent(text: string, expandKey: string, paddingX: number) {\n let cachedWidth: number | undefined;\n let cachedLine: string | undefined;\n return {\n render(width: number): string[] {\n if (cachedWidth !== width || cachedLine === undefined) {\n const rows = new Text(text, paddingX, 0).render(width).length;\n const plural = rows === 1 ? 'row' : 'rows';\n cachedWidth = width;\n cachedLine = theme.dim(` ${rows} ${plural}; ${expandKey} to expand`);\n }\n return [cachedLine];\n },\n invalidate(): void {\n cachedWidth = undefined;\n cachedLine = undefined;\n },\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"tool-execution.js","names":[],"sources":["../../../../src/tui/components/tool-execution.ts"],"sourcesContent":["import {\n Container,\n type Component,\n getCapabilities,\n Image,\n type KeybindingsManager,\n Spacer,\n Text,\n} from '@earendil-works/pi-tui';\nimport type { AgentToolResult } from '@earendil-works/pi-agent-core';\n\nimport { theme } from '../theme.js';\nimport { formatKeyIds } from '../format-tui-hotkeys.js';\nimport {\n isDiffFriendlyTool,\n looksLikeUnifiedDiff,\n renderPatchSummary,\n renderUnifiedDiff,\n} from '../tui-tool-diff.js';\nimport {\n hasStructuredTuiToolRenderer,\n renderToolCallWithExtensions,\n renderToolResultWithExtensions,\n renderToolWithExtensions,\n} from '../extension-host/tool-renderers.js';\nimport {\n parseTuiToolResult,\n type TuiToolContentBlock,\n} from '../tui-tool-result.js';\nimport {\n displayToolName,\n formatArgsSummary,\n formatCollapsedToolSummary,\n formatExecExpandedOutput,\n getToolSummaryKind,\n isExecStyleTool,\n isReadStyleTool,\n} from '../tool-summary.js';\nimport { truncateToVisualLines, truncateToVisualLinesMiddle } from './visual-truncate.js';\n\nconst COLLAPSED_RESULT_VISUAL_LINES = 4;\nconst EXPANDED_RESULT_VISUAL_LINES = 80;\n\nexport interface ToolExecutionOptions {\n showImages?: boolean;\n imageWidthCells?: number;\n keybindings?: KeybindingsManager;\n toolCallId?: string;\n cwd?: string;\n}\n\nfunction sanitize(text: string): string {\n return text.replace(/[\\x00-\\x08\\x0B\\x0C\\x0E-\\x1F]/g, '');\n}\n\nfunction trimTrailingBlankDisplayLines(text: string): string {\n return text.replace(/(?:\\r?\\n[ \\t]*)+$/g, '');\n}\n\nexport function getToolResultDisplayText(\n content: TuiToolContentBlock[],\n options: { showImages: boolean; supportsInlineImages: boolean },\n): string {\n const parts: string[] = [];\n for (const block of content) {\n if (block.type === 'text') {\n if (block.text) parts.push(sanitize(block.text));\n continue;\n }\n if (block.type === 'image' && (!options.supportsInlineImages || !options.showImages)) {\n parts.push(block.mimeType ? `[image:${block.mimeType}]` : '[image]');\n continue;\n }\n if (block.type !== 'image') {\n parts.push(block.text ? sanitize(block.text) : `[${block.type}]`);\n }\n }\n return trimTrailingBlankDisplayLines(parts.filter(Boolean).join('\\n'));\n}\n\nfunction isTuiComponent(value: unknown): value is Component {\n return Boolean(\n value &&\n typeof value === 'object' &&\n typeof (value as { render?: unknown }).render === 'function',\n );\n}\n\nexport class ToolExecutionComponent extends Container {\n private contentContainer: Container;\n private contentText: Text;\n private collapsedOutputComponent: ReturnType<typeof createVisualTailComponent> | null = null;\n private collapsedReadSummaryComponent: ReturnType<typeof createCollapsedReadSummaryComponent> | null = null;\n private expandedOutputComponent: ReturnType<typeof createVisualMiddleComponent> | null = null;\n private toolName: string;\n private toolCallId: string;\n private args: unknown;\n private argsComplete = true;\n private resultText = '';\n private resultContent: TuiToolContentBlock[] | undefined;\n private resultDetails: unknown;\n private rendererState: Record<string, unknown> = {};\n private lastRendererOutput: string[] | Component | undefined;\n private lastCallRendererOutput: string[] | Component | undefined;\n private lastResultRendererOutput: string[] | Component | undefined;\n private customRendererComponent: Component | undefined;\n private structuredRendererComponents: Component[] = [];\n private contentTextAttached = true;\n private rendererInvalidationQueued = false;\n private imageComponents: Image[] = [];\n private imageSpacers: Spacer[] = [];\n private showImages: boolean;\n private imageWidthCells: number;\n private keybindings: KeybindingsManager | undefined;\n private cwd: string;\n private expanded = false;\n private isError = false;\n private isPartial = true;\n private executionStarted = false;\n private startedAt = Date.now();\n private completedAt: number | undefined;\n\n constructor(toolName: string, toolCallId: string, args: unknown, options: ToolExecutionOptions = {}) {\n super();\n this.toolName = toolName;\n this.toolCallId = toolCallId;\n this.args = args;\n this.showImages = options.showImages ?? true;\n this.imageWidthCells = Math.max(1, Math.floor(options.imageWidthCells ?? 60));\n this.keybindings = options.keybindings;\n this.cwd = options.cwd ?? process.cwd();\n\n this.addChild(new Spacer(1));\n\n const bgFn = (text: string) => theme.toolPendingBg(text);\n this.contentContainer = new Container();\n this.contentText = new Text('', 1, 1, bgFn);\n this.contentContainer.addChild(this.contentText);\n this.addChild(this.contentContainer);\n\n this.refresh();\n }\n\n setArgs(args: unknown): void {\n this.args = args;\n this.refresh();\n }\n\n markExecutionStarted(): void {\n this.executionStarted = true;\n this.startedAt = Date.now();\n this.refresh();\n }\n\n setArgsComplete(): void {\n this.argsComplete = true;\n this.refresh();\n }\n\n setExpanded(expanded: boolean): void {\n this.expanded = expanded;\n this.refresh();\n }\n\n updateResult(result: AgentToolResult<any> | unknown, isPartial = false, isError = false): void {\n const parsed = parseTuiToolResult(result);\n this.resultText = sanitize(parsed.text);\n this.resultContent = parsed.envelope?.content;\n this.resultDetails = parsed.envelope?.details;\n this.isError = isError;\n this.isPartial = isPartial;\n if (!isPartial) {\n this.completedAt = Date.now();\n }\n this.refresh();\n }\n\n setImageOptions(options: ToolExecutionOptions): void {\n if (options.showImages !== undefined) {\n this.showImages = options.showImages;\n }\n if (options.imageWidthCells !== undefined) {\n this.imageWidthCells = Math.max(1, Math.floor(options.imageWidthCells));\n }\n if (options.keybindings !== undefined) {\n this.keybindings = options.keybindings;\n }\n if (options.cwd !== undefined) {\n this.cwd = options.cwd;\n }\n this.refresh();\n }\n\n setPartialDetails(details: unknown): void {\n this.resultDetails = details;\n this.isPartial = true;\n this.refresh();\n }\n\n private refresh(): void {\n const bgFn = this.isPartial\n ? (text: string) => theme.toolPendingBg(text)\n : this.isError\n ? (text: string) => theme.toolErrorBg(text)\n : (text: string) => theme.toolSuccessBg(text);\n this.refreshCollapsedOutput(null);\n this.refreshCollapsedReadSummary(null);\n this.refreshExpandedOutput(null);\n if (this.customRendererComponent) {\n this.contentContainer.removeChild(this.customRendererComponent);\n this.customRendererComponent = undefined;\n }\n for (const component of this.structuredRendererComponents) {\n this.contentContainer.removeChild(component);\n }\n this.structuredRendererComponents = [];\n this.contentText.setCustomBgFn(bgFn);\n\n if (hasStructuredTuiToolRenderer(this.toolName)) {\n this.detachContentText();\n this.renderStructuredExtensionTool();\n } else {\n const custom = this.renderExtensionTool();\n if (Array.isArray(custom) && custom.length > 0) {\n this.ensureContentTextAttached();\n this.lastRendererOutput = custom;\n this.contentText.setText(custom.join('\\n'));\n } else if (isTuiComponent(custom)) {\n this.detachContentText();\n this.customRendererComponent = custom;\n this.lastRendererOutput = custom;\n this.contentContainer.addChild(custom);\n } else {\n this.ensureContentTextAttached();\n this.lastRendererOutput = undefined;\n this.contentText.setText(this.formatToolExecution());\n }\n }\n this.refreshImages();\n }\n\n private appendRendererResult(result: ReturnType<typeof renderToolWithExtensions>): boolean {\n if (Array.isArray(result) && result.length > 0) {\n const component = new Text(result.join('\\n'), 1, 1);\n this.structuredRendererComponents.push(component);\n this.contentContainer.addChild(component);\n return true;\n }\n if (isTuiComponent(result)) {\n this.structuredRendererComponents.push(result);\n this.contentContainer.addChild(result);\n return true;\n }\n return false;\n }\n\n private renderStructuredExtensionTool(): void {\n const call = this.renderExtensionToolCall();\n if (this.appendRendererResult(call)) {\n this.lastCallRendererOutput = call as string[] | Component;\n } else {\n this.lastCallRendererOutput = undefined;\n this.ensureContentTextAttached();\n this.contentText.setText(this.formatToolCallFallback());\n }\n\n if (!this.isPartial || this.resultDetails !== undefined || this.resultText || this.resultContent) {\n const result = this.renderExtensionToolResult();\n if (this.appendRendererResult(result)) {\n this.lastResultRendererOutput = result as string[] | Component;\n } else {\n this.appendRendererResult([this.formatToolResultFallback()].filter(Boolean));\n this.lastResultRendererOutput = undefined;\n }\n }\n }\n\n private ensureContentTextAttached(): void {\n if (this.contentTextAttached) return;\n this.contentContainer.addChild(this.contentText);\n this.contentTextAttached = true;\n }\n\n private detachContentText(): void {\n if (!this.contentTextAttached) return;\n this.contentContainer.removeChild(this.contentText);\n this.contentTextAttached = false;\n }\n\n private requestRendererInvalidate(): void {\n if (this.rendererInvalidationQueued) return;\n this.rendererInvalidationQueued = true;\n queueMicrotask(() => {\n this.rendererInvalidationQueued = false;\n this.refresh();\n this.invalidate();\n });\n }\n\n private renderExtensionTool(): ReturnType<typeof renderToolWithExtensions> {\n return renderToolWithExtensions(this.createRenderContext(this.lastRendererOutput));\n }\n\n private renderExtensionToolCall(): ReturnType<typeof renderToolWithExtensions> {\n return renderToolCallWithExtensions(\n this.createRenderContext(this.lastCallRendererOutput),\n theme,\n );\n }\n\n private renderExtensionToolResult(): ReturnType<typeof renderToolWithExtensions> {\n return renderToolResultWithExtensions(\n this.createRenderContext(this.lastResultRendererOutput),\n theme,\n );\n }\n\n private createRenderContext(lastComponent: string[] | Component | undefined) {\n return {\n toolName: this.toolName,\n toolCallId: this.toolCallId,\n args: this.args,\n resultText: this.getDisplayResultText(),\n content: this.resultContent,\n details: this.resultDetails,\n invalidate: () => this.requestRendererInvalidate(),\n lastComponent,\n state: this.rendererState,\n cwd: this.cwd,\n executionStarted: this.executionStarted,\n argsComplete: this.argsComplete,\n isError: this.isError,\n isPartial: this.isPartial,\n expanded: this.expanded,\n showImages: this.showImages,\n };\n }\n\n private formatToolCallFallback(): string {\n const argsStr = formatArgsSummary(this.args, this.toolName);\n const titleParts = [\n theme.dim(this.toolStatusLabel()),\n theme.toolTitle(theme.bold(displayToolName(this.toolName))),\n ];\n if (argsStr) {\n titleParts.push(theme.dim(`(${argsStr})`));\n }\n const duration = this.toolDurationLabel();\n if (duration) {\n titleParts.push(theme.dim(duration));\n }\n if (this.isPartial && !this.resultText && !this.resultContent && this.resultDetails === undefined) {\n titleParts.push(theme.dim('…'));\n }\n return titleParts.join(' ');\n }\n\n private formatToolResultFallback(): string {\n const output = this.getDisplayResultText();\n let text = '';\n if (output) {\n const expandKey = this.keybindings\n ? formatKeyIds(this.keybindings, 'app.tools.expand', { capitalize: true })\n : 'Ctrl+O';\n const lineCount = output.split('\\n').length;\n const useDiff =\n isDiffFriendlyTool(this.toolName) &&\n looksLikeUnifiedDiff(output);\n if (this.expanded && useDiff) {\n text += renderPatchSummary(output) ?? renderUnifiedDiff(output);\n } else if (this.expanded && isExecStyleTool(this.toolName)) {\n this.refreshExpandedOutput(theme.toolOutput(formatExecExpandedOutput(output, this.resultDetails)));\n } else if (this.expanded) {\n this.refreshExpandedOutput(theme.toolOutput(output));\n } else if (useDiff) {\n text += theme.dim('preview');\n } else if (getToolSummaryKind(this.toolName) !== 'generic') {\n text += this.collapsedSpecializedSummary(output, expandKey);\n } else {\n const suffix = lineCount > COLLAPSED_RESULT_VISUAL_LINES\n ? theme.dim(` (${lineCount} lines; ${expandKey} to expand)`)\n : '';\n text += theme.dim(`preview${suffix}`);\n }\n }\n if (this.shouldRenderDetailsPreview()) {\n const detailsText = formatDetailsPreview(this.resultDetails);\n if (detailsText) {\n text = [text, theme.dim(detailsText)].filter(Boolean).join('\\n');\n }\n }\n return text;\n }\n\n private formatToolExecution(): string {\n const argsStr = formatArgsSummary(this.args, this.toolName);\n const titleParts = [\n theme.dim(this.toolStatusLabel()),\n theme.toolTitle(theme.bold(displayToolName(this.toolName))),\n ];\n if (argsStr) {\n titleParts.push(theme.dim(`(${argsStr})`));\n }\n const duration = this.toolDurationLabel();\n if (duration) {\n titleParts.push(theme.dim(duration));\n }\n let text = titleParts.join(' ');\n\n // Output / result — collapsed: single-line summary; expanded: full output\n const output = this.getDisplayResultText();\n if (output) {\n const expandKey = this.keybindings\n ? formatKeyIds(this.keybindings, 'app.tools.expand', { capitalize: true })\n : 'Ctrl+O';\n const lineCount = output.split('\\n').length;\n const useDiff =\n isDiffFriendlyTool(this.toolName) &&\n looksLikeUnifiedDiff(output);\n if (this.expanded && useDiff) {\n text += `\\n${renderPatchSummary(output) ?? renderUnifiedDiff(output)}`;\n } else if (this.expanded && isExecStyleTool(this.toolName)) {\n this.refreshExpandedOutput(theme.toolOutput(formatExecExpandedOutput(output, this.resultDetails)));\n } else if (this.expanded) {\n this.refreshExpandedOutput(theme.toolOutput(output));\n } else if (useDiff) {\n const suffix = output.split('\\n').length > COLLAPSED_RESULT_VISUAL_LINES\n ? theme.dim(` (${output.split('\\n').length} lines; ${expandKey} to expand)`)\n : '';\n text += `\\n${theme.dim(`preview${suffix}`)}`;\n } else if (isReadStyleTool(this.toolName)) {\n this.refreshCollapsedReadSummary(output, expandKey);\n } else if (getToolSummaryKind(this.toolName) !== 'generic') {\n text += `\\n${this.collapsedSpecializedSummary(output, expandKey)}`;\n } else {\n const suffix = lineCount > COLLAPSED_RESULT_VISUAL_LINES\n ? theme.dim(` (${lineCount} lines; ${expandKey} to expand)`)\n : '';\n text += `\\n${theme.dim(`preview${suffix}`)}`;\n this.refreshCollapsedOutput(\n theme.toolOutput(output),\n lineCount > COLLAPSED_RESULT_VISUAL_LINES ? undefined : `${expandKey} to expand`,\n );\n }\n } else if (this.isPartial) {\n text += `\\n${theme.dim('…')}`;\n }\n\n if (this.shouldRenderDetailsPreview()) {\n const detailsText = formatDetailsPreview(this.resultDetails);\n if (detailsText) {\n text += `\\n${theme.dim(detailsText)}`;\n }\n }\n\n return text;\n }\n\n private toolStatusLabel(): string {\n if (this.isError) return 'Failed';\n if (this.isPartial && !this.resultText && !this.resultContent && this.resultDetails === undefined) {\n return this.executionStarted ? 'Calling' : 'Queued';\n }\n if (this.isPartial) return 'Calling';\n return 'Called';\n }\n\n private toolDurationLabel(): string {\n if (this.completedAt === undefined) return '';\n const durationMs = Math.max(0, this.completedAt - this.startedAt);\n if (durationMs < 100) return '';\n return `${durationMs}ms`;\n }\n\n private collapsedSpecializedSummary(output: string, expandKey: string): string {\n return theme.dim(formatCollapsedToolSummary({\n toolName: this.toolName,\n args: this.args,\n output,\n content: this.resultContent,\n details: this.resultDetails,\n isError: this.isError,\n expandKey,\n }));\n }\n\n private shouldRenderDetailsPreview(): boolean {\n return this.expanded && this.resultDetails !== undefined && !isExecStyleTool(this.toolName);\n }\n\n private getDisplayResultText(): string {\n if (!this.resultContent) {\n return trimTrailingBlankDisplayLines(this.resultText);\n }\n return getToolResultDisplayText(this.resultContent, {\n showImages: this.showImages,\n supportsInlineImages: Boolean(getCapabilities().images),\n });\n }\n\n private refreshImages(): void {\n for (const image of this.imageComponents) {\n this.removeChild(image);\n }\n this.imageComponents = [];\n for (const spacer of this.imageSpacers) {\n this.removeChild(spacer);\n }\n this.imageSpacers = [];\n\n const imageBlocks = this.resultContent?.filter(\n (block) => block.type === 'image' && block.data && block.mimeType,\n ) ?? [];\n if (imageBlocks.length === 0) return;\n\n const capabilities = getCapabilities();\n if (!capabilities.images || !this.showImages) return;\n\n for (const block of imageBlocks) {\n const spacer = new Spacer(1);\n const image = new Image(\n block.data!,\n block.mimeType!,\n { fallbackColor: (text: string) => theme.toolOutput(text) },\n { maxWidthCells: this.imageWidthCells },\n );\n this.imageSpacers.push(spacer);\n this.imageComponents.push(image);\n this.addChild(spacer);\n this.addChild(image);\n }\n }\n\n private refreshCollapsedOutput(text: string | null, truncationHint?: string): void {\n if (this.collapsedOutputComponent) {\n this.contentContainer.removeChild(this.collapsedOutputComponent);\n this.collapsedOutputComponent = null;\n }\n if (!text) return;\n this.collapsedOutputComponent = createVisualTailComponent(\n text,\n COLLAPSED_RESULT_VISUAL_LINES,\n 1,\n truncationHint,\n );\n this.contentContainer.addChild(this.collapsedOutputComponent);\n }\n\n private refreshCollapsedReadSummary(text: string | null, expandKey?: string): void {\n if (this.collapsedReadSummaryComponent) {\n this.contentContainer.removeChild(this.collapsedReadSummaryComponent);\n this.collapsedReadSummaryComponent = null;\n }\n if (!text || !expandKey) return;\n this.collapsedReadSummaryComponent = createCollapsedReadSummaryComponent(text, expandKey, 1);\n this.contentContainer.addChild(this.collapsedReadSummaryComponent);\n }\n\n private refreshExpandedOutput(text: string | null): void {\n if (this.expandedOutputComponent) {\n this.contentContainer.removeChild(this.expandedOutputComponent);\n this.expandedOutputComponent = null;\n }\n if (!text) return;\n this.expandedOutputComponent = createVisualMiddleComponent(\n text,\n EXPANDED_RESULT_VISUAL_LINES,\n 1,\n );\n this.contentContainer.addChild(this.expandedOutputComponent);\n }\n}\n\nfunction formatDetailsPreview(details: unknown): string {\n if (details === null) return '';\n if (typeof details === 'string') return details;\n try {\n return JSON.stringify(details, null, 2);\n } catch {\n return String(details);\n }\n}\n\nfunction createVisualTailComponent(\n text: string,\n maxVisualLines: number,\n paddingX: number,\n truncationHint?: string,\n) {\n let cachedWidth: number | undefined;\n let cachedLines: string[] | undefined;\n return {\n render(width: number): string[] {\n if (cachedWidth !== width || cachedLines === undefined) {\n const result = truncateToVisualLines(text, maxVisualLines, width, paddingX);\n cachedWidth = width;\n cachedLines =\n result.skippedCount > 0 && truncationHint\n ? [theme.dim(` (${result.skippedCount} rows hidden; ${truncationHint})`), ...result.visualLines]\n : result.visualLines;\n }\n return cachedLines;\n },\n invalidate(): void {\n cachedWidth = undefined;\n cachedLines = undefined;\n },\n };\n}\n\nfunction createVisualMiddleComponent(\n text: string,\n maxVisualLines: number,\n paddingX: number,\n) {\n let cachedWidth: number | undefined;\n let cachedLines: string[] | undefined;\n return {\n render(width: number): string[] {\n if (cachedWidth !== width || cachedLines === undefined) {\n const result = truncateToVisualLinesMiddle(text, maxVisualLines, width, paddingX);\n cachedWidth = width;\n cachedLines = result.visualLines;\n }\n return cachedLines;\n },\n invalidate(): void {\n cachedWidth = undefined;\n cachedLines = undefined;\n },\n };\n}\n\nfunction createCollapsedReadSummaryComponent(text: string, expandKey: string, paddingX: number) {\n let cachedWidth: number | undefined;\n let cachedLine: string | undefined;\n return {\n render(width: number): string[] {\n if (cachedWidth !== width || cachedLine === undefined) {\n const rows = new Text(text, paddingX, 0).render(width).length;\n const plural = rows === 1 ? 'row' : 'rows';\n cachedWidth = width;\n cachedLine = theme.dim(` ${rows} ${plural}; ${expandKey} to expand`);\n }\n return [cachedLine];\n },\n invalidate(): void {\n cachedWidth = undefined;\n cachedLine = undefined;\n },\n };\n}\n"],"mappings":"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"}
@@ -1,6 +1,7 @@
1
1
  import { theme } from "../theme.js";
2
2
  import { formatContextUsageLabel } from "../tui-context-usage.js";
3
3
  import { getGitBranchCached } from "../tui-git-branch.js";
4
+ import { formatActiveRunStatus } from "../tui-run-status-format.js";
4
5
  import { isAbsolute, relative, resolve, sep } from "node:path";
5
6
  import { truncateToWidth, visibleWidth } from "@earendil-works/pi-tui";
6
7
  //#region src/tui/components/tui-bottom-bar.ts
@@ -8,7 +9,11 @@ const BUSY_ACTIVITY = new Set([
8
9
  "sending",
9
10
  "waiting",
10
11
  "streaming",
11
- "running"
12
+ "running",
13
+ "compacting",
14
+ "stalled",
15
+ "recovering",
16
+ "aborting"
12
17
  ]);
13
18
  /** Compact token counts (aligned with pi coding-agent footer). */
14
19
  function formatTokens(count) {
@@ -86,15 +91,14 @@ var TuiBottomBar = class {
86
91
  const pwdLine = truncateToWidth(theme.dim(`${cwdWithBranch} · ${sessionLine}`), width, theme.dim("…"));
87
92
  const busy = BUSY_ACTIVITY.has(state.activityStatus);
88
93
  const leftParts = [state.connectionStatus];
89
- if (!busy && state.activityStatus && state.activityStatus !== "idle") leftParts.push(state.activityStatus);
94
+ const activeRunStatus = formatActiveRunStatus(state);
95
+ if (activeRunStatus) leftParts.push(activeRunStatus);
96
+ else if (!busy && state.activityStatus && state.activityStatus !== "idle") leftParts.push(state.activityStatus);
90
97
  if (state.sessionInfo.totalTokens != null) leftParts.push(formatTokens(state.sessionInfo.totalTokens));
91
98
  const ctxLabel = formatContextUsageLabel(state.sessionInfo.contextUsagePercent ?? null, state.sessionInfo.contextWindow ?? null);
92
99
  if (ctxLabel) leftParts.push(ctxLabel);
93
100
  if (state.isCompacting) leftParts.push("compact…");
94
101
  else if (state.compactionQueue.length > 0) leftParts.push(`C${state.compactionQueue.length}`);
95
- if (state.runStatus?.phase === "stalled") leftParts.push("run:stalled");
96
- else if (state.runStatus?.phase === "recovering") leftParts.push("run:recovering");
97
- else if (state.runStatus?.source === "agent-resume" && state.activeRunId) leftParts.push("run:resumed");
98
102
  if (state.messageFollowUpQueue.length > 0) leftParts.push(`Q${state.messageFollowUpQueue.length}`);
99
103
  if (state.steeringQueue.length > 0) leftParts.push(`S${state.steeringQueue.length}`);
100
104
  let statsLeft = leftParts.join(" · ");
@@ -1 +1 @@
1
- {"version":3,"file":"tui-bottom-bar.js","names":[],"sources":["../../../../src/tui/components/tui-bottom-bar.ts"],"sourcesContent":["import { isAbsolute, relative, resolve, sep } from 'node:path';\n\nimport type { Component } from '@earendil-works/pi-tui';\nimport { truncateToWidth, visibleWidth } from '@earendil-works/pi-tui';\n\nimport { theme } from '../theme.js';\nimport { formatContextUsageLabel } from '../tui-context-usage.js';\nimport { getGitBranchCached } from '../tui-git-branch.js';\nimport type { TuiState } from '../tui-types.js';\n\nconst BUSY_ACTIVITY = new Set(['sending', 'waiting', 'streaming', 'running']);\n\n/** Compact token counts (aligned with pi coding-agent footer). */\nexport function formatTokens(count: number): string {\n if (count < 1000) return count.toString();\n if (count < 10000) return `${(count / 1000).toFixed(1)}k`;\n if (count < 1_000_000) return `${Math.round(count / 1000)}k`;\n if (count < 10_000_000) return `${(count / 1_000_000).toFixed(1)}M`;\n return `${Math.round(count / 1_000_000)}M`;\n}\n\nexport function sanitizeStatusText(text: string): string {\n return text\n .replace(/[\\r\\n\\t]/g, ' ')\n .replace(/ +/g, ' ')\n .trim();\n}\n\nexport function formatQueuedMessageLines(\n state: TuiState,\n width: number,\n dequeueHint: string,\n): string[] {\n const lines: string[] = [];\n const add = (label: string, text: string) => {\n const sanitized = sanitizeStatusText(text);\n if (!sanitized) return;\n lines.push(\n truncateToWidth(theme.dim(`${label}: ${sanitized}`), width, theme.dim('…')),\n );\n };\n\n for (const message of state.steeringQueue) {\n add('Steering', message);\n }\n for (const message of state.messageFollowUpQueue) {\n add('Follow-up', message);\n }\n for (const message of state.compactionQueue) {\n add('Queued', message);\n }\n if (lines.length > 0) {\n lines.push(\n truncateToWidth(theme.dim(`↳ ${dequeueHint} to edit all queued messages`), width, theme.dim('…')),\n );\n }\n return lines;\n}\n\nexport function formatCwdForFooter(cwd: string, home: string | undefined): string {\n if (!home) return cwd;\n\n const resolvedCwd = resolve(cwd);\n const resolvedHome = resolve(home);\n const relativeToHome = relative(resolvedHome, resolvedCwd);\n const isInsideHome =\n relativeToHome === '' ||\n (relativeToHome !== '..' &&\n !relativeToHome.startsWith(`..${sep}`) &&\n !isAbsolute(relativeToHome));\n\n if (!isInsideHome) return cwd;\n return relativeToHome === '' ? '~' : `~${sep}${relativeToHome}`;\n}\n\nfunction shortenPath(cwd: string): string {\n const formatted = formatCwdForFooter(cwd, process.env.HOME || process.env.USERPROFILE);\n if (formatted !== cwd) return formatted;\n return cwd;\n}\n\n/**\n * Multi-line footer below the input editor (pi coding-agent style):\n * cwd · session, then a single padded row: status/tokens on the left, model on the right.\n */\nexport class TuiBottomBar implements Component {\n private extensionLines: string[] = [];\n private extensionComponents: Component[] = [];\n private extensionStatusParts: string[] = [];\n private customComponent: Component | undefined;\n\n constructor(\n private readonly getState: () => TuiState,\n private readonly getThinkingDefault: () => string | undefined,\n private readonly getDequeueHint: () => string = () => 'Alt+Up',\n ) {}\n\n setExtensionLines(lines: string[]): void {\n this.extensionLines = lines;\n }\n\n setExtensionComponents(components: Component[]): void {\n this.extensionComponents = components;\n }\n\n setExtensionStatusParts(parts: string[]): void {\n this.extensionStatusParts = parts;\n }\n\n setCustomComponent(component: Component | undefined): void {\n this.customComponent = component;\n }\n\n invalidate(): void {}\n\n render(width: number): string[] {\n if (this.customComponent) {\n const rendered = this.customComponent.render(width);\n return rendered.map((line) => truncateToWidth(line, width, theme.dim('…')));\n }\n\n const state = this.getState();\n const cwdRaw = state.sessionInfo.effectiveWorkspacePath;\n const cwdWithBranch = cwdRaw\n ? (() => {\n const cwd = shortenPath(cwdRaw);\n const branch = getGitBranchCached(cwdRaw);\n return branch ? `${cwd} (${branch})` : cwd;\n })()\n : 'workspace loading';\n const sessionLine = state.sessionInfo.displayName ?? `session ${state.currentSessionKey}`;\n const pwdLine = truncateToWidth(\n theme.dim(`${cwdWithBranch} · ${sessionLine}`),\n width,\n theme.dim('…'),\n );\n\n const busy = BUSY_ACTIVITY.has(state.activityStatus);\n const leftParts: string[] = [state.connectionStatus];\n if (!busy && state.activityStatus && state.activityStatus !== 'idle') {\n leftParts.push(state.activityStatus);\n }\n if (state.sessionInfo.totalTokens != null) {\n leftParts.push(formatTokens(state.sessionInfo.totalTokens));\n }\n const ctxLabel = formatContextUsageLabel(\n state.sessionInfo.contextUsagePercent ?? null,\n state.sessionInfo.contextWindow ?? null,\n );\n if (ctxLabel) {\n leftParts.push(ctxLabel);\n }\n if (state.isCompacting) {\n leftParts.push('compact…');\n } else if (state.compactionQueue.length > 0) {\n leftParts.push(`C${state.compactionQueue.length}`);\n }\n if (state.runStatus?.phase === 'stalled') {\n leftParts.push('run:stalled');\n } else if (state.runStatus?.phase === 'recovering') {\n leftParts.push('run:recovering');\n } else if (state.runStatus?.source === 'agent-resume' && state.activeRunId) {\n leftParts.push('run:resumed');\n }\n if (state.messageFollowUpQueue.length > 0) {\n leftParts.push(`Q${state.messageFollowUpQueue.length}`);\n }\n if (state.steeringQueue.length > 0) {\n leftParts.push(`S${state.steeringQueue.length}`);\n }\n let statsLeft = leftParts.join(' · ');\n\n const modelId = state.sessionInfo.model ?? 'unknown';\n const prov = state.sessionInfo.modelProvider;\n const thinkingHint = state.showThinking\n ? `thinking:${this.getThinkingDefault() ?? 'on'}`\n : 'thinking:off';\n let rightSide = prov ? `(${prov}) ${modelId}` : modelId;\n rightSide = `${rightSide} • ${thinkingHint}`;\n\n const minPadding = 2;\n let statsLeftWidth = visibleWidth(statsLeft);\n if (statsLeftWidth > width) {\n statsLeft = truncateToWidth(statsLeft, width, '…');\n statsLeftWidth = visibleWidth(statsLeft);\n }\n\n const rightWidth = visibleWidth(rightSide);\n const totalNeeded = statsLeftWidth + minPadding + rightWidth;\n\n let statsLine: string;\n if (totalNeeded <= width) {\n const padding = ' '.repeat(width - statsLeftWidth - rightWidth);\n statsLine = statsLeft + padding + rightSide;\n } else {\n const availableForRight = width - statsLeftWidth - minPadding;\n if (availableForRight > 0) {\n const truncatedRight = truncateToWidth(rightSide, availableForRight, '');\n const tw = visibleWidth(truncatedRight);\n const padding = ' '.repeat(Math.max(0, width - statsLeftWidth - tw));\n statsLine = statsLeft + padding + truncatedRight;\n } else {\n statsLine = statsLeft;\n }\n }\n\n const statsDimmed = theme.dim(statsLine);\n const lines = [pwdLine, statsDimmed];\n if (this.extensionStatusParts.length > 0) {\n const statusLine = this.extensionStatusParts\n .map((part) => sanitizeStatusText(part))\n .filter(Boolean)\n .join(' ');\n if (statusLine) {\n lines.push(truncateToWidth(theme.dim(statusLine), width, theme.dim('…')));\n }\n }\n lines.push(...formatQueuedMessageLines(state, width, this.getDequeueHint()));\n for (const extLine of this.extensionLines) {\n lines.push(truncateToWidth(theme.dim(sanitizeStatusText(extLine)), width, theme.dim('…')));\n }\n for (const component of this.extensionComponents) {\n for (const line of component.render(width)) {\n lines.push(truncateToWidth(line, width, theme.dim('…')));\n }\n }\n return lines;\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"tui-bottom-bar.js","names":[],"sources":["../../../../src/tui/components/tui-bottom-bar.ts"],"sourcesContent":["import { isAbsolute, relative, resolve, sep } from 'node:path';\n\nimport type { Component } from '@earendil-works/pi-tui';\nimport { truncateToWidth, visibleWidth } from '@earendil-works/pi-tui';\n\nimport { theme } from '../theme.js';\nimport { formatContextUsageLabel } from '../tui-context-usage.js';\nimport { getGitBranchCached } from '../tui-git-branch.js';\nimport { formatActiveRunStatus } from '../tui-run-status-format.js';\nimport type { TuiState } from '../tui-types.js';\n\nconst BUSY_ACTIVITY = new Set([\n 'sending',\n 'waiting',\n 'streaming',\n 'running',\n 'compacting',\n 'stalled',\n 'recovering',\n 'aborting',\n]);\n\n/** Compact token counts (aligned with pi coding-agent footer). */\nexport function formatTokens(count: number): string {\n if (count < 1000) return count.toString();\n if (count < 10000) return `${(count / 1000).toFixed(1)}k`;\n if (count < 1_000_000) return `${Math.round(count / 1000)}k`;\n if (count < 10_000_000) return `${(count / 1_000_000).toFixed(1)}M`;\n return `${Math.round(count / 1_000_000)}M`;\n}\n\nexport function sanitizeStatusText(text: string): string {\n return text\n .replace(/[\\r\\n\\t]/g, ' ')\n .replace(/ +/g, ' ')\n .trim();\n}\n\nexport function formatQueuedMessageLines(\n state: TuiState,\n width: number,\n dequeueHint: string,\n): string[] {\n const lines: string[] = [];\n const add = (label: string, text: string) => {\n const sanitized = sanitizeStatusText(text);\n if (!sanitized) return;\n lines.push(\n truncateToWidth(theme.dim(`${label}: ${sanitized}`), width, theme.dim('…')),\n );\n };\n\n for (const message of state.steeringQueue) {\n add('Steering', message);\n }\n for (const message of state.messageFollowUpQueue) {\n add('Follow-up', message);\n }\n for (const message of state.compactionQueue) {\n add('Queued', message);\n }\n if (lines.length > 0) {\n lines.push(\n truncateToWidth(theme.dim(`↳ ${dequeueHint} to edit all queued messages`), width, theme.dim('…')),\n );\n }\n return lines;\n}\n\nexport function formatCwdForFooter(cwd: string, home: string | undefined): string {\n if (!home) return cwd;\n\n const resolvedCwd = resolve(cwd);\n const resolvedHome = resolve(home);\n const relativeToHome = relative(resolvedHome, resolvedCwd);\n const isInsideHome =\n relativeToHome === '' ||\n (relativeToHome !== '..' &&\n !relativeToHome.startsWith(`..${sep}`) &&\n !isAbsolute(relativeToHome));\n\n if (!isInsideHome) return cwd;\n return relativeToHome === '' ? '~' : `~${sep}${relativeToHome}`;\n}\n\nfunction shortenPath(cwd: string): string {\n const formatted = formatCwdForFooter(cwd, process.env.HOME || process.env.USERPROFILE);\n if (formatted !== cwd) return formatted;\n return cwd;\n}\n\n/**\n * Multi-line footer below the input editor (pi coding-agent style):\n * cwd · session, then a single padded row: status/tokens on the left, model on the right.\n */\nexport class TuiBottomBar implements Component {\n private extensionLines: string[] = [];\n private extensionComponents: Component[] = [];\n private extensionStatusParts: string[] = [];\n private customComponent: Component | undefined;\n\n constructor(\n private readonly getState: () => TuiState,\n private readonly getThinkingDefault: () => string | undefined,\n private readonly getDequeueHint: () => string = () => 'Alt+Up',\n ) {}\n\n setExtensionLines(lines: string[]): void {\n this.extensionLines = lines;\n }\n\n setExtensionComponents(components: Component[]): void {\n this.extensionComponents = components;\n }\n\n setExtensionStatusParts(parts: string[]): void {\n this.extensionStatusParts = parts;\n }\n\n setCustomComponent(component: Component | undefined): void {\n this.customComponent = component;\n }\n\n invalidate(): void {}\n\n render(width: number): string[] {\n if (this.customComponent) {\n const rendered = this.customComponent.render(width);\n return rendered.map((line) => truncateToWidth(line, width, theme.dim('…')));\n }\n\n const state = this.getState();\n const cwdRaw = state.sessionInfo.effectiveWorkspacePath;\n const cwdWithBranch = cwdRaw\n ? (() => {\n const cwd = shortenPath(cwdRaw);\n const branch = getGitBranchCached(cwdRaw);\n return branch ? `${cwd} (${branch})` : cwd;\n })()\n : 'workspace loading';\n const sessionLine = state.sessionInfo.displayName ?? `session ${state.currentSessionKey}`;\n const pwdLine = truncateToWidth(\n theme.dim(`${cwdWithBranch} · ${sessionLine}`),\n width,\n theme.dim('…'),\n );\n\n const busy = BUSY_ACTIVITY.has(state.activityStatus);\n const leftParts: string[] = [state.connectionStatus];\n const activeRunStatus = formatActiveRunStatus(state);\n if (activeRunStatus) {\n leftParts.push(activeRunStatus);\n } else if (!busy && state.activityStatus && state.activityStatus !== 'idle') {\n leftParts.push(state.activityStatus);\n }\n if (state.sessionInfo.totalTokens != null) {\n leftParts.push(formatTokens(state.sessionInfo.totalTokens));\n }\n const ctxLabel = formatContextUsageLabel(\n state.sessionInfo.contextUsagePercent ?? null,\n state.sessionInfo.contextWindow ?? null,\n );\n if (ctxLabel) {\n leftParts.push(ctxLabel);\n }\n if (state.isCompacting) {\n leftParts.push('compact…');\n } else if (state.compactionQueue.length > 0) {\n leftParts.push(`C${state.compactionQueue.length}`);\n }\n if (state.messageFollowUpQueue.length > 0) {\n leftParts.push(`Q${state.messageFollowUpQueue.length}`);\n }\n if (state.steeringQueue.length > 0) {\n leftParts.push(`S${state.steeringQueue.length}`);\n }\n let statsLeft = leftParts.join(' · ');\n\n const modelId = state.sessionInfo.model ?? 'unknown';\n const prov = state.sessionInfo.modelProvider;\n const thinkingHint = state.showThinking\n ? `thinking:${this.getThinkingDefault() ?? 'on'}`\n : 'thinking:off';\n let rightSide = prov ? `(${prov}) ${modelId}` : modelId;\n rightSide = `${rightSide} • ${thinkingHint}`;\n\n const minPadding = 2;\n let statsLeftWidth = visibleWidth(statsLeft);\n if (statsLeftWidth > width) {\n statsLeft = truncateToWidth(statsLeft, width, '…');\n statsLeftWidth = visibleWidth(statsLeft);\n }\n\n const rightWidth = visibleWidth(rightSide);\n const totalNeeded = statsLeftWidth + minPadding + rightWidth;\n\n let statsLine: string;\n if (totalNeeded <= width) {\n const padding = ' '.repeat(width - statsLeftWidth - rightWidth);\n statsLine = statsLeft + padding + rightSide;\n } else {\n const availableForRight = width - statsLeftWidth - minPadding;\n if (availableForRight > 0) {\n const truncatedRight = truncateToWidth(rightSide, availableForRight, '');\n const tw = visibleWidth(truncatedRight);\n const padding = ' '.repeat(Math.max(0, width - statsLeftWidth - tw));\n statsLine = statsLeft + padding + truncatedRight;\n } else {\n statsLine = statsLeft;\n }\n }\n\n const statsDimmed = theme.dim(statsLine);\n const lines = [pwdLine, statsDimmed];\n if (this.extensionStatusParts.length > 0) {\n const statusLine = this.extensionStatusParts\n .map((part) => sanitizeStatusText(part))\n .filter(Boolean)\n .join(' ');\n if (statusLine) {\n lines.push(truncateToWidth(theme.dim(statusLine), width, theme.dim('…')));\n }\n }\n lines.push(...formatQueuedMessageLines(state, width, this.getDequeueHint()));\n for (const extLine of this.extensionLines) {\n lines.push(truncateToWidth(theme.dim(sanitizeStatusText(extLine)), width, theme.dim('…')));\n }\n for (const component of this.extensionComponents) {\n for (const line of component.render(width)) {\n lines.push(truncateToWidth(line, width, theme.dim('…')));\n }\n }\n return lines;\n }\n}\n"],"mappings":";;;;;;;AAWA,MAAM,gBAAgB,IAAI,IAAI;CAC5B;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD,CAAC;;AAGF,SAAgB,aAAa,OAAuB;AAClD,KAAI,QAAQ,IAAM,QAAO,MAAM,UAAU;AACzC,KAAI,QAAQ,IAAO,QAAO,IAAI,QAAQ,KAAM,QAAQ,EAAE,CAAC;AACvD,KAAI,QAAQ,IAAW,QAAO,GAAG,KAAK,MAAM,QAAQ,IAAK,CAAC;AAC1D,KAAI,QAAQ,IAAY,QAAO,IAAI,QAAQ,KAAW,QAAQ,EAAE,CAAC;AACjE,QAAO,GAAG,KAAK,MAAM,QAAQ,IAAU,CAAC;;AAG1C,SAAgB,mBAAmB,MAAsB;AACvD,QAAO,KACJ,QAAQ,aAAa,IAAI,CACzB,QAAQ,OAAO,IAAI,CACnB,MAAM;;AAGX,SAAgB,yBACd,OACA,OACA,aACU;CACV,MAAM,QAAkB,EAAE;CAC1B,MAAM,OAAO,OAAe,SAAiB;EAC3C,MAAM,YAAY,mBAAmB,KAAK;AAC1C,MAAI,CAAC,UAAW;AAChB,QAAM,KACJ,gBAAgB,MAAM,IAAI,GAAG,MAAM,IAAI,YAAY,EAAE,OAAO,MAAM,IAAI,IAAI,CAAC,CAC5E;;AAGH,MAAK,MAAM,WAAW,MAAM,cAC1B,KAAI,YAAY,QAAQ;AAE1B,MAAK,MAAM,WAAW,MAAM,qBAC1B,KAAI,aAAa,QAAQ;AAE3B,MAAK,MAAM,WAAW,MAAM,gBAC1B,KAAI,UAAU,QAAQ;AAExB,KAAI,MAAM,SAAS,EACjB,OAAM,KACJ,gBAAgB,MAAM,IAAI,KAAK,YAAY,8BAA8B,EAAE,OAAO,MAAM,IAAI,IAAI,CAAC,CAClG;AAEH,QAAO;;AAGT,SAAgB,mBAAmB,KAAa,MAAkC;AAChF,KAAI,CAAC,KAAM,QAAO;CAElB,MAAM,cAAc,QAAQ,IAAI;CAEhC,MAAM,iBAAiB,SADF,QAAQ,KACe,EAAE,YAAY;AAO1D,KAAI,EALF,mBAAmB,MAClB,mBAAmB,QAClB,CAAC,eAAe,WAAW,KAAK,MAAM,IACtC,CAAC,WAAW,eAAe,EAEZ,QAAO;AAC1B,QAAO,mBAAmB,KAAK,MAAM,IAAI,MAAM;;AAGjD,SAAS,YAAY,KAAqB;CACxC,MAAM,YAAY,mBAAmB,KAAK,QAAQ,IAAI,QAAQ,QAAQ,IAAI,YAAY;AACtF,KAAI,cAAc,IAAK,QAAO;AAC9B,QAAO;;;;;;AAOT,IAAa,eAAb,MAA+C;CAC7C,iBAAmC,EAAE;CACrC,sBAA2C,EAAE;CAC7C,uBAAyC,EAAE;CAC3C;CAEA,YACE,UACA,oBACA,uBAAsD,UACtD;AAHiB,OAAA,WAAA;AACA,OAAA,qBAAA;AACA,OAAA,iBAAA;;CAGnB,kBAAkB,OAAuB;AACvC,OAAK,iBAAiB;;CAGxB,uBAAuB,YAA+B;AACpD,OAAK,sBAAsB;;CAG7B,wBAAwB,OAAuB;AAC7C,OAAK,uBAAuB;;CAG9B,mBAAmB,WAAwC;AACzD,OAAK,kBAAkB;;CAGzB,aAAmB;CAEnB,OAAO,OAAyB;AAC9B,MAAI,KAAK,gBAEP,QADiB,KAAK,gBAAgB,OAAO,MAC9B,CAAC,KAAK,SAAS,gBAAgB,MAAM,OAAO,MAAM,IAAI,IAAI,CAAC,CAAC;EAG7E,MAAM,QAAQ,KAAK,UAAU;EAC7B,MAAM,SAAS,MAAM,YAAY;EACjC,MAAM,gBAAgB,gBACX;GACL,MAAM,MAAM,YAAY,OAAO;GAC/B,MAAM,SAAS,mBAAmB,OAAO;AACzC,UAAO,SAAS,GAAG,IAAI,IAAI,OAAO,KAAK;MACrC,GACJ;EACJ,MAAM,cAAc,MAAM,YAAY,eAAe,WAAW,MAAM;EACtE,MAAM,UAAU,gBACd,MAAM,IAAI,GAAG,cAAc,KAAK,cAAc,EAC9C,OACA,MAAM,IAAI,IAAI,CACf;EAED,MAAM,OAAO,cAAc,IAAI,MAAM,eAAe;EACpD,MAAM,YAAsB,CAAC,MAAM,iBAAiB;EACpD,MAAM,kBAAkB,sBAAsB,MAAM;AACpD,MAAI,gBACF,WAAU,KAAK,gBAAgB;WACtB,CAAC,QAAQ,MAAM,kBAAkB,MAAM,mBAAmB,OACnE,WAAU,KAAK,MAAM,eAAe;AAEtC,MAAI,MAAM,YAAY,eAAe,KACnC,WAAU,KAAK,aAAa,MAAM,YAAY,YAAY,CAAC;EAE7D,MAAM,WAAW,wBACf,MAAM,YAAY,uBAAuB,MACzC,MAAM,YAAY,iBAAiB,KACpC;AACD,MAAI,SACF,WAAU,KAAK,SAAS;AAE1B,MAAI,MAAM,aACR,WAAU,KAAK,WAAW;WACjB,MAAM,gBAAgB,SAAS,EACxC,WAAU,KAAK,IAAI,MAAM,gBAAgB,SAAS;AAEpD,MAAI,MAAM,qBAAqB,SAAS,EACtC,WAAU,KAAK,IAAI,MAAM,qBAAqB,SAAS;AAEzD,MAAI,MAAM,cAAc,SAAS,EAC/B,WAAU,KAAK,IAAI,MAAM,cAAc,SAAS;EAElD,IAAI,YAAY,UAAU,KAAK,MAAM;EAErC,MAAM,UAAU,MAAM,YAAY,SAAS;EAC3C,MAAM,OAAO,MAAM,YAAY;EAC/B,MAAM,eAAe,MAAM,eACvB,YAAY,KAAK,oBAAoB,IAAI,SACzC;EACJ,IAAI,YAAY,OAAO,IAAI,KAAK,IAAI,YAAY;AAChD,cAAY,GAAG,UAAU,KAAK;EAE9B,MAAM,aAAa;EACnB,IAAI,iBAAiB,aAAa,UAAU;AAC5C,MAAI,iBAAiB,OAAO;AAC1B,eAAY,gBAAgB,WAAW,OAAO,IAAI;AAClD,oBAAiB,aAAa,UAAU;;EAG1C,MAAM,aAAa,aAAa,UAAU;EAC1C,MAAM,cAAc,iBAAiB,aAAa;EAElD,IAAI;AACJ,MAAI,eAAe,OAAO;GACxB,MAAM,UAAU,IAAI,OAAO,QAAQ,iBAAiB,WAAW;AAC/D,eAAY,YAAY,UAAU;SAC7B;GACL,MAAM,oBAAoB,QAAQ,iBAAiB;AACnD,OAAI,oBAAoB,GAAG;IACzB,MAAM,iBAAiB,gBAAgB,WAAW,mBAAmB,GAAG;IACxE,MAAM,KAAK,aAAa,eAAe;IACvC,MAAM,UAAU,IAAI,OAAO,KAAK,IAAI,GAAG,QAAQ,iBAAiB,GAAG,CAAC;AACpE,gBAAY,YAAY,UAAU;SAElC,aAAY;;EAKhB,MAAM,QAAQ,CAAC,SADK,MAAM,IAAI,UACK,CAAC;AACpC,MAAI,KAAK,qBAAqB,SAAS,GAAG;GACxC,MAAM,aAAa,KAAK,qBACrB,KAAK,SAAS,mBAAmB,KAAK,CAAC,CACvC,OAAO,QAAQ,CACf,KAAK,IAAI;AACZ,OAAI,WACF,OAAM,KAAK,gBAAgB,MAAM,IAAI,WAAW,EAAE,OAAO,MAAM,IAAI,IAAI,CAAC,CAAC;;AAG7E,QAAM,KAAK,GAAG,yBAAyB,OAAO,OAAO,KAAK,gBAAgB,CAAC,CAAC;AAC5E,OAAK,MAAM,WAAW,KAAK,eACzB,OAAM,KAAK,gBAAgB,MAAM,IAAI,mBAAmB,QAAQ,CAAC,EAAE,OAAO,MAAM,IAAI,IAAI,CAAC,CAAC;AAE5F,OAAK,MAAM,aAAa,KAAK,oBAC3B,MAAK,MAAM,QAAQ,UAAU,OAAO,MAAM,CACxC,OAAM,KAAK,gBAAgB,MAAM,OAAO,MAAM,IAAI,IAAI,CAAC,CAAC;AAG5D,SAAO"}
@@ -9,3 +9,4 @@ export interface VisualTruncateResult {
9
9
  * across many terminal rows.
10
10
  */
11
11
  export declare function truncateToVisualLines(text: string, maxVisualLines: number, width: number, paddingX?: number): VisualTruncateResult;
12
+ export declare function truncateToVisualLinesMiddle(text: string, maxVisualLines: number, width: number, paddingX?: number): VisualTruncateResult;
@@ -21,7 +21,34 @@ function truncateToVisualLines(text, maxVisualLines, width, paddingX = 0) {
21
21
  skippedCount: rendered.length - maxVisualLines
22
22
  };
23
23
  }
24
+ function truncateToVisualLinesMiddle(text, maxVisualLines, width, paddingX = 0) {
25
+ if (!text || maxVisualLines <= 0) return {
26
+ visualLines: [],
27
+ skippedCount: 0
28
+ };
29
+ const rendered = new Text(text, paddingX, 0).render(width);
30
+ if (rendered.length <= maxVisualLines) return {
31
+ visualLines: rendered,
32
+ skippedCount: 0
33
+ };
34
+ if (maxVisualLines === 1) return {
35
+ visualLines: ["..."],
36
+ skippedCount: rendered.length - 1
37
+ };
38
+ const visibleWithoutMarker = maxVisualLines - 1;
39
+ const headCount = Math.ceil(visibleWithoutMarker / 2);
40
+ const tailCount = Math.floor(visibleWithoutMarker / 2);
41
+ const skippedCount = rendered.length - headCount - tailCount;
42
+ return {
43
+ visualLines: [
44
+ ...rendered.slice(0, headCount),
45
+ `... ${skippedCount} rows hidden ...`,
46
+ ...rendered.slice(rendered.length - tailCount)
47
+ ],
48
+ skippedCount
49
+ };
50
+ }
24
51
  //#endregion
25
- export { truncateToVisualLines };
52
+ export { truncateToVisualLines, truncateToVisualLinesMiddle };
26
53
 
27
54
  //# sourceMappingURL=visual-truncate.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"visual-truncate.js","names":[],"sources":["../../../../src/tui/components/visual-truncate.ts"],"sourcesContent":["import { Text } from '@earendil-works/pi-tui';\n\nexport interface VisualTruncateResult {\n visualLines: string[];\n skippedCount: number;\n}\n\n/**\n * Truncate text by rendered terminal rows, not source lines.\n *\n * This keeps collapsed previews bounded when one very long logical line wraps\n * across many terminal rows.\n */\nexport function truncateToVisualLines(\n text: string,\n maxVisualLines: number,\n width: number,\n paddingX = 0,\n): VisualTruncateResult {\n if (!text || maxVisualLines <= 0) {\n return { visualLines: [], skippedCount: 0 };\n }\n\n const rendered = new Text(text, paddingX, 0).render(width);\n if (rendered.length <= maxVisualLines) {\n return { visualLines: rendered, skippedCount: 0 };\n }\n\n return {\n visualLines: rendered.slice(-maxVisualLines),\n skippedCount: rendered.length - maxVisualLines,\n };\n}\n"],"mappings":";;;;;;;;AAaA,SAAgB,sBACd,MACA,gBACA,OACA,WAAW,GACW;AACtB,KAAI,CAAC,QAAQ,kBAAkB,EAC7B,QAAO;EAAE,aAAa,EAAE;EAAE,cAAc;EAAG;CAG7C,MAAM,WAAW,IAAI,KAAK,MAAM,UAAU,EAAE,CAAC,OAAO,MAAM;AAC1D,KAAI,SAAS,UAAU,eACrB,QAAO;EAAE,aAAa;EAAU,cAAc;EAAG;AAGnD,QAAO;EACL,aAAa,SAAS,MAAM,CAAC,eAAe;EAC5C,cAAc,SAAS,SAAS;EACjC"}
1
+ {"version":3,"file":"visual-truncate.js","names":[],"sources":["../../../../src/tui/components/visual-truncate.ts"],"sourcesContent":["import { Text } from '@earendil-works/pi-tui';\n\nexport interface VisualTruncateResult {\n visualLines: string[];\n skippedCount: number;\n}\n\n/**\n * Truncate text by rendered terminal rows, not source lines.\n *\n * This keeps collapsed previews bounded when one very long logical line wraps\n * across many terminal rows.\n */\nexport function truncateToVisualLines(\n text: string,\n maxVisualLines: number,\n width: number,\n paddingX = 0,\n): VisualTruncateResult {\n if (!text || maxVisualLines <= 0) {\n return { visualLines: [], skippedCount: 0 };\n }\n\n const rendered = new Text(text, paddingX, 0).render(width);\n if (rendered.length <= maxVisualLines) {\n return { visualLines: rendered, skippedCount: 0 };\n }\n\n return {\n visualLines: rendered.slice(-maxVisualLines),\n skippedCount: rendered.length - maxVisualLines,\n };\n}\n\nexport function truncateToVisualLinesMiddle(\n text: string,\n maxVisualLines: number,\n width: number,\n paddingX = 0,\n): VisualTruncateResult {\n if (!text || maxVisualLines <= 0) {\n return { visualLines: [], skippedCount: 0 };\n }\n\n const rendered = new Text(text, paddingX, 0).render(width);\n if (rendered.length <= maxVisualLines) {\n return { visualLines: rendered, skippedCount: 0 };\n }\n\n if (maxVisualLines === 1) {\n return {\n visualLines: ['...'],\n skippedCount: rendered.length - 1,\n };\n }\n\n const visibleWithoutMarker = maxVisualLines - 1;\n const headCount = Math.ceil(visibleWithoutMarker / 2);\n const tailCount = Math.floor(visibleWithoutMarker / 2);\n const skippedCount = rendered.length - headCount - tailCount;\n return {\n visualLines: [\n ...rendered.slice(0, headCount),\n `... ${skippedCount} rows hidden ...`,\n ...rendered.slice(rendered.length - tailCount),\n ],\n skippedCount,\n };\n}\n"],"mappings":";;;;;;;;AAaA,SAAgB,sBACd,MACA,gBACA,OACA,WAAW,GACW;AACtB,KAAI,CAAC,QAAQ,kBAAkB,EAC7B,QAAO;EAAE,aAAa,EAAE;EAAE,cAAc;EAAG;CAG7C,MAAM,WAAW,IAAI,KAAK,MAAM,UAAU,EAAE,CAAC,OAAO,MAAM;AAC1D,KAAI,SAAS,UAAU,eACrB,QAAO;EAAE,aAAa;EAAU,cAAc;EAAG;AAGnD,QAAO;EACL,aAAa,SAAS,MAAM,CAAC,eAAe;EAC5C,cAAc,SAAS,SAAS;EACjC;;AAGH,SAAgB,4BACd,MACA,gBACA,OACA,WAAW,GACW;AACtB,KAAI,CAAC,QAAQ,kBAAkB,EAC7B,QAAO;EAAE,aAAa,EAAE;EAAE,cAAc;EAAG;CAG7C,MAAM,WAAW,IAAI,KAAK,MAAM,UAAU,EAAE,CAAC,OAAO,MAAM;AAC1D,KAAI,SAAS,UAAU,eACrB,QAAO;EAAE,aAAa;EAAU,cAAc;EAAG;AAGnD,KAAI,mBAAmB,EACrB,QAAO;EACL,aAAa,CAAC,MAAM;EACpB,cAAc,SAAS,SAAS;EACjC;CAGH,MAAM,uBAAuB,iBAAiB;CAC9C,MAAM,YAAY,KAAK,KAAK,uBAAuB,EAAE;CACrD,MAAM,YAAY,KAAK,MAAM,uBAAuB,EAAE;CACtD,MAAM,eAAe,SAAS,SAAS,YAAY;AACnD,QAAO;EACL,aAAa;GACX,GAAG,SAAS,MAAM,GAAG,UAAU;GAC/B,OAAO,aAAa;GACpB,GAAG,SAAS,MAAM,SAAS,SAAS,UAAU;GAC/C;EACD;EACD"}
@@ -0,0 +1,22 @@
1
+ import type { TuiToolContentBlock } from './tui-tool-result.js';
2
+ export type ToolSummaryKind = 'read' | 'search' | 'exec' | 'mcp' | 'generic';
3
+ export interface ToolSummaryContext {
4
+ toolName: string;
5
+ args: unknown;
6
+ output: string;
7
+ content?: TuiToolContentBlock[];
8
+ details: unknown;
9
+ isError: boolean;
10
+ expandKey: string;
11
+ }
12
+ export declare function formatArgsSummary(args: unknown, toolName: string): string;
13
+ export declare function getToolSummaryKind(toolName: string): ToolSummaryKind;
14
+ export declare function isReadStyleTool(toolName: string): boolean;
15
+ export declare function isSearchStyleTool(toolName: string): boolean;
16
+ export declare function isExecStyleTool(toolName: string): boolean;
17
+ export declare function isMcpStyleTool(toolName: string): boolean;
18
+ export declare function displayToolName(toolName: string): string;
19
+ export declare function compactPath(path: string, maxLength?: number): string;
20
+ export declare function formatCollapsedToolSummary(ctx: ToolSummaryContext): string;
21
+ export declare function formatExecExpandedOutput(output: string, details: unknown): string;
22
+ export declare function extractExitCode(details: unknown): number | undefined;