@herbertgao/pi-extensions 2026.9.19 → 2026.10.0

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 (444) hide show
  1. package/README.md +14 -16
  2. package/THIRD_PARTY_NOTICES.md +29 -3
  3. package/node_modules/@herbertgao/pi-bark/README.md +39 -3
  4. package/node_modules/@herbertgao/pi-bark/package.json +1 -1
  5. package/node_modules/@herbertgao/pi-bark/src/index.ts +275 -15
  6. package/node_modules/@herbertgao/pi-cc-extensions/README.en.md +85 -68
  7. package/node_modules/@herbertgao/pi-cc-extensions/README.md +79 -62
  8. package/node_modules/@herbertgao/pi-cc-extensions/assets/readme/preview.webp +0 -0
  9. package/node_modules/@herbertgao/pi-cc-extensions/extensions/config/config.ts +116 -34
  10. package/node_modules/@herbertgao/pi-cc-extensions/extensions/config/panel.ts +370 -118
  11. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/agent-summary/core.ts +6 -36
  12. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/agent-summary/index.ts +2 -2
  13. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/compact-thinking.ts +31 -33
  14. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/context.ts +330 -360
  15. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/reference/index.ts +56 -108
  16. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/reference/session.ts +97 -15
  17. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/reference/subagent.ts +80 -45
  18. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/shell/flush-docked-bash.ts +36 -0
  19. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/shell/footer-layout.ts +229 -0
  20. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/shell/footer.ts +521 -0
  21. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/shell/mcp-chip.ts +136 -0
  22. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/shell/startup-header.ts +92 -61
  23. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/shell/working-message.ts +58 -38
  24. package/node_modules/@herbertgao/pi-cc-extensions/extensions/index.ts +19 -3
  25. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/compact-mode.ts +1127 -231
  26. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/default-mode.ts +267 -262
  27. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/index.ts +38 -48
  28. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/markdown-enhance.ts +8 -2
  29. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/hover.ts +2 -7
  30. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/interaction.ts +287 -114
  31. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/layout.ts +15 -6
  32. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/packets.ts +18 -72
  33. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/scroll.ts +61 -26
  34. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/codemode.ts +303 -0
  35. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/ansi-utils.ts +25 -57
  36. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/diff-component.ts +125 -0
  37. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/diff-edit-render.ts +227 -0
  38. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/diff-header.ts +136 -0
  39. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/diff-highlight.ts +151 -0
  40. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/diff-inline.ts +324 -0
  41. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/diff-layout.ts +762 -0
  42. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/diff-limits.ts +152 -0
  43. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/diff-palette.ts +410 -0
  44. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/diff-parse.ts +535 -0
  45. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/diff-presentation.ts +4 -4
  46. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/diff-renderer.ts +21 -3219
  47. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/diff-text.ts +44 -0
  48. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/diff-write-render.ts +568 -0
  49. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/index.ts +103 -48
  50. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/line-width-safety.ts +8 -7
  51. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/write-execution.ts +2 -1
  52. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/grouping.ts +171 -196
  53. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/mcp-title.ts +39 -0
  54. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{message-display.ts → tool/message-display.ts} +27 -93
  55. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/names.ts +429 -0
  56. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/result.ts +259 -164
  57. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{show-more-hint.ts → tool/show-more-hint.ts} +10 -0
  58. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/transcript-refresh.ts +8 -26
  59. package/node_modules/@herbertgao/pi-cc-extensions/extensions/utils/ansi-color.ts +44 -0
  60. package/node_modules/@herbertgao/pi-cc-extensions/extensions/utils/ansi-text.ts +77 -0
  61. package/node_modules/@herbertgao/pi-cc-extensions/extensions/utils/component-tree.ts +34 -0
  62. package/node_modules/@herbertgao/pi-cc-extensions/extensions/utils/format.ts +28 -0
  63. package/node_modules/@herbertgao/pi-cc-extensions/extensions/utils/fullscreen-detect.ts +51 -0
  64. package/node_modules/@herbertgao/pi-cc-extensions/extensions/utils/patch-keys.ts +124 -0
  65. package/node_modules/@herbertgao/pi-cc-extensions/extensions/utils/sgr-mouse.ts +70 -0
  66. package/node_modules/@herbertgao/pi-cc-extensions/package.json +10 -8
  67. package/node_modules/@herbertgao/pi-subagents/CHANGELOG.md +6 -0
  68. package/node_modules/@herbertgao/pi-subagents/package.json +1 -1
  69. package/node_modules/@herbertgao/pi-subagents/src/mention-clone.ts +3 -2
  70. package/node_modules/@herbertgao/sol-pi/CONTRIBUTING.md +22 -0
  71. package/node_modules/@herbertgao/sol-pi/README.md +36 -17
  72. package/node_modules/@herbertgao/sol-pi/THIRD_PARTY_NOTICES.md +10 -6
  73. package/node_modules/@herbertgao/sol-pi/agents-install.md +15 -12
  74. package/node_modules/@herbertgao/sol-pi/docs/compatibility.md +24 -8
  75. package/node_modules/@herbertgao/sol-pi/docs/configuration.md +2 -2
  76. package/node_modules/@herbertgao/sol-pi/docs/star-history.md +18 -0
  77. package/node_modules/@herbertgao/sol-pi/package.json +4 -2
  78. package/node_modules/@herbertgao/sol-pi/scripts/check-sol-pi-config.mjs +1 -1
  79. package/node_modules/@herbertgao/sol-pi/src/sol-pi/config.ts +1 -1
  80. package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/action-fusion/file-queue.ts +23 -4
  81. package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/action-fusion/index.ts +32 -1
  82. package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/action-fusion/then-run.ts +3 -2
  83. package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/observation-pack/observation.ts +1 -1
  84. package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/online-context-compact/economics.ts +27 -7
  85. package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/online-context-compact/extension.ts +137 -41
  86. package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/online-context-compact/index.ts +1 -0
  87. package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/online-context-compact/plan.ts +2 -1
  88. package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/online-context-compact/projection.ts +58 -0
  89. package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/online-context-compact/state.ts +28 -6
  90. package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/online-context-compact/tools.ts +2 -1
  91. package/node_modules/@herbertgao/sol-pi/src/sol-pi/runtime-paths.ts +15 -2
  92. package/node_modules/@juicesharp/rpiv-ask-user-question/package.json +2 -2
  93. package/node_modules/@pi-plugins/fast-mode/README.md +7 -1
  94. package/node_modules/@pi-plugins/fast-mode/dist/index.d.mts.map +1 -1
  95. package/node_modules/@pi-plugins/fast-mode/dist/index.mjs +7 -1
  96. package/node_modules/@pi-plugins/fast-mode/dist/index.mjs.map +1 -1
  97. package/node_modules/@pi-plugins/fast-mode/package.json +5 -5
  98. package/node_modules/pi-antigravity/README.md +3 -0
  99. package/node_modules/pi-antigravity/package.json +8 -8
  100. package/node_modules/pi-antigravity/src/auth/oauth.ts +6 -3
  101. package/node_modules/pi-antigravity/src/index.ts +114 -110
  102. package/node_modules/pi-antigravity/src/stream/stream.ts +1 -1
  103. package/node_modules/pi-antigravity/src/utils/util.ts +18 -1
  104. package/node_modules/pi-multi-account/CHANGELOG.md +20 -0
  105. package/node_modules/pi-multi-account/README.md +46 -8
  106. package/node_modules/pi-multi-account/config-file-transaction.ts +42 -0
  107. package/node_modules/pi-multi-account/index.ts +255 -269
  108. package/node_modules/pi-multi-account/model-pins.ts +36 -0
  109. package/node_modules/pi-multi-account/package.json +9 -7
  110. package/node_modules/pi-multi-account/slot-proxy-auth.ts +12 -2
  111. package/node_modules/pi-multi-account/slot-proxy.ts +27 -5
  112. package/node_modules/pi-web-access/CHANGELOG.md +17 -0
  113. package/node_modules/pi-web-access/README.md +6 -3
  114. package/node_modules/pi-web-access/brave-rate-limit.ts +170 -0
  115. package/node_modules/pi-web-access/brave.ts +28 -11
  116. package/node_modules/pi-web-access/dist/index.js +202 -33
  117. package/node_modules/pi-web-access/gemini-search.ts +2 -5
  118. package/node_modules/pi-web-access/index.ts +13 -7
  119. package/node_modules/pi-web-access/openai-search.ts +24 -10
  120. package/node_modules/pi-web-access/package.json +1 -1
  121. package/node_modules/pi-web-access/summary-review.ts +8 -2
  122. package/node_modules/{@herbertgao/resume-from → resume-from}/README.md +16 -12
  123. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/claude-code/adapter.d.ts +0 -5
  124. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/claude-code/adapter.js +2 -3
  125. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/claude-code/contract.d.ts +2 -2
  126. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/claude-code/reader.d.ts +3 -0
  127. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/claude-code/reader.js +27 -15
  128. package/node_modules/{@herbertgao/resume-from/dist/adapters/codex → resume-from/dist/adapters/claude-code}/redaction.js +16 -3
  129. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/claude-code/writer.d.ts +2 -4
  130. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/claude-code/writer.js +1 -1
  131. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/codex/contract.d.ts +2 -4
  132. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/codex/index.js +1 -2
  133. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/codex/read.d.ts +16 -0
  134. package/node_modules/resume-from/dist/adapters/codex/read.js +723 -0
  135. package/node_modules/{@herbertgao/resume-from/dist/adapters/pi → resume-from/dist/adapters/codex}/redaction.js +16 -3
  136. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/codex/rollout.d.ts +44 -4
  137. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/codex/rollout.js +88 -4
  138. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/codex/write.d.ts +2 -2
  139. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/codex/write.js +2 -2
  140. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/contract.d.ts +5 -1
  141. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/pi/adapter.js +10 -6
  142. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/pi/contract.d.ts +2 -2
  143. package/node_modules/{@herbertgao/resume-from/dist/adapters/claude-code → resume-from/dist/adapters/pi}/redaction.js +16 -3
  144. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/pi/serialize.d.ts +2 -4
  145. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/pi/serialize.js +2 -2
  146. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/cli/render.d.ts +1 -1
  147. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/cli/render.js +4 -4
  148. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/cli/runner.js +2 -2
  149. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/contract.d.ts +2 -2
  150. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/pi-extension/command.js +31 -8
  151. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/wiring.d.ts +1 -1
  152. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/wiring.js +1 -2
  153. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/confirmation.d.ts +4 -1
  154. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/confirmation.js +2 -2
  155. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/contract.d.ts +8 -6
  156. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/discovery/contract.d.ts +10 -5
  157. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/discovery/finder.d.ts +2 -1
  158. package/node_modules/resume-from/dist/import/discovery/finder.js +269 -0
  159. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/landing/contract.d.ts +3 -3
  160. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/landing/lander.js +3 -3
  161. package/node_modules/resume-from/dist/import/pipeline.d.ts +28 -0
  162. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/pipeline.js +31 -11
  163. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/preview/builder.d.ts +2 -2
  164. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/preview/builder.js +9 -5
  165. package/node_modules/resume-from/dist/import/preview/warnings.d.ts +14 -0
  166. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/preview/warnings.js +26 -20
  167. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/wiring.js +12 -2
  168. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/repo/contract.d.ts +9 -3
  169. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/repo/git.d.ts +4 -4
  170. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/repo/git.js +7 -4
  171. package/node_modules/resume-from/dist/platform/repo/reader.d.ts +3 -0
  172. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/repo/reader.js +60 -20
  173. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/session/contract.d.ts +8 -1
  174. package/node_modules/{@herbertgao/resume-from → resume-from}/package.json +19 -32
  175. package/node_modules/{@herbertgao/resume-from → resume-from}/shims/pi/extensions/resume-from.js +2 -2
  176. package/package.json +18 -22
  177. package/node_modules/@herbertgao/pi-cc-extensions/assets/readme/hero.en.svg +0 -101
  178. package/node_modules/@herbertgao/pi-cc-extensions/assets/readme/hero.svg +0 -101
  179. package/node_modules/@herbertgao/pi-cc-extensions/assets/readme/welcome.webp +0 -0
  180. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/render-utils.ts +0 -5
  181. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/types.ts +0 -30
  182. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/write-display-utils.ts +0 -12
  183. package/node_modules/@herbertgao/resume-from/dist/adapters/codex/read.js +0 -270
  184. package/node_modules/@herbertgao/resume-from/dist/import/discovery/finder.js +0 -129
  185. package/node_modules/@herbertgao/resume-from/dist/import/pipeline.d.ts +0 -17
  186. package/node_modules/@herbertgao/resume-from/dist/import/preview/warnings.d.ts +0 -11
  187. package/node_modules/@herbertgao/resume-from/dist/platform/repo/reader.d.ts +0 -8
  188. package/node_modules/pi-footer/CHANGELOG.md +0 -145
  189. package/node_modules/pi-footer/LICENSE +0 -21
  190. package/node_modules/pi-footer/README.md +0 -354
  191. package/node_modules/pi-footer/package.json +0 -68
  192. package/node_modules/pi-footer/src/cache.ts +0 -106
  193. package/node_modules/pi-footer/src/colors.ts +0 -237
  194. package/node_modules/pi-footer/src/config.ts +0 -202
  195. package/node_modules/pi-footer/src/event-widgets.ts +0 -41
  196. package/node_modules/pi-footer/src/extension-statuses.ts +0 -102
  197. package/node_modules/pi-footer/src/git.ts +0 -135
  198. package/node_modules/pi-footer/src/index.ts +0 -268
  199. package/node_modules/pi-footer/src/metrics.ts +0 -141
  200. package/node_modules/pi-footer/src/presets.ts +0 -383
  201. package/node_modules/pi-footer/src/render.ts +0 -114
  202. package/node_modules/pi-footer/src/separators.ts +0 -52
  203. package/node_modules/pi-footer/src/types.ts +0 -122
  204. package/node_modules/pi-footer/src/ui/color-level-confirm.ts +0 -22
  205. package/node_modules/pi-footer/src/ui/color-options.ts +0 -195
  206. package/node_modules/pi-footer/src/ui/config-lifecycle.ts +0 -61
  207. package/node_modules/pi-footer/src/ui/edit-colors.ts +0 -13
  208. package/node_modules/pi-footer/src/ui/events.ts +0 -35
  209. package/node_modules/pi-footer/src/ui/extension-status-picker.ts +0 -60
  210. package/node_modules/pi-footer/src/ui/extension-statuses.ts +0 -73
  211. package/node_modules/pi-footer/src/ui/fields.ts +0 -252
  212. package/node_modules/pi-footer/src/ui/global-menu.ts +0 -126
  213. package/node_modules/pi-footer/src/ui/helpers.ts +0 -44
  214. package/node_modules/pi-footer/src/ui/layout.ts +0 -17
  215. package/node_modules/pi-footer/src/ui/line-list.ts +0 -19
  216. package/node_modules/pi-footer/src/ui/model.ts +0 -64
  217. package/node_modules/pi-footer/src/ui/navigation.ts +0 -29
  218. package/node_modules/pi-footer/src/ui/option-edit.ts +0 -93
  219. package/node_modules/pi-footer/src/ui/overlay-render.ts +0 -103
  220. package/node_modules/pi-footer/src/ui/screen-context.ts +0 -18
  221. package/node_modules/pi-footer/src/ui/screen-controller.ts +0 -27
  222. package/node_modules/pi-footer/src/ui/screen-render.ts +0 -32
  223. package/node_modules/pi-footer/src/ui/screen-state.ts +0 -20
  224. package/node_modules/pi-footer/src/ui/screen.ts +0 -243
  225. package/node_modules/pi-footer/src/ui/screens/add-widget.ts +0 -92
  226. package/node_modules/pi-footer/src/ui/screens/confirm-exit.ts +0 -52
  227. package/node_modules/pi-footer/src/ui/screens/controller.ts +0 -12
  228. package/node_modules/pi-footer/src/ui/screens/edit-colors.ts +0 -68
  229. package/node_modules/pi-footer/src/ui/screens/edit-widget.ts +0 -115
  230. package/node_modules/pi-footer/src/ui/screens/extension-status-row.ts +0 -61
  231. package/node_modules/pi-footer/src/ui/screens/global.ts +0 -75
  232. package/node_modules/pi-footer/src/ui/screens/line-list.ts +0 -108
  233. package/node_modules/pi-footer/src/ui/screens/main.ts +0 -99
  234. package/node_modules/pi-footer/src/ui/screens/terminal.ts +0 -121
  235. package/node_modules/pi-footer/src/ui/screens/widget-list.ts +0 -154
  236. package/node_modules/pi-footer/src/ui/terminal-menu.ts +0 -32
  237. package/node_modules/pi-footer/src/ui/theme.ts +0 -48
  238. package/node_modules/pi-footer/src/ui/title-bar.ts +0 -100
  239. package/node_modules/pi-footer/src/ui/widget-actions.ts +0 -76
  240. package/node_modules/pi-footer/src/ui.ts +0 -66
  241. package/node_modules/pi-footer/src/widgets/context.ts +0 -28
  242. package/node_modules/pi-footer/src/widgets/core/active-tools.ts +0 -17
  243. package/node_modules/pi-footer/src/widgets/core/context-window.ts +0 -24
  244. package/node_modules/pi-footer/src/widgets/core/cwd-basename.ts +0 -19
  245. package/node_modules/pi-footer/src/widgets/core/cwd.ts +0 -108
  246. package/node_modules/pi-footer/src/widgets/core/event.ts +0 -34
  247. package/node_modules/pi-footer/src/widgets/core/external-status.ts +0 -102
  248. package/node_modules/pi-footer/src/widgets/core/model-provider.ts +0 -20
  249. package/node_modules/pi-footer/src/widgets/core/model.ts +0 -35
  250. package/node_modules/pi-footer/src/widgets/core/provider.ts +0 -17
  251. package/node_modules/pi-footer/src/widgets/core/session-name.ts +0 -17
  252. package/node_modules/pi-footer/src/widgets/core/text-verbosity.ts +0 -17
  253. package/node_modules/pi-footer/src/widgets/core/thinking-level.ts +0 -17
  254. package/node_modules/pi-footer/src/widgets/git/ahead-behind.ts +0 -17
  255. package/node_modules/pi-footer/src/widgets/git/branch.ts +0 -81
  256. package/node_modules/pi-footer/src/widgets/git/clean.ts +0 -19
  257. package/node_modules/pi-footer/src/widgets/git/deletions.ts +0 -17
  258. package/node_modules/pi-footer/src/widgets/git/diff.ts +0 -38
  259. package/node_modules/pi-footer/src/widgets/git/insertions.ts +0 -17
  260. package/node_modules/pi-footer/src/widgets/git/remote.ts +0 -17
  261. package/node_modules/pi-footer/src/widgets/git/root.ts +0 -17
  262. package/node_modules/pi-footer/src/widgets/git/sha.ts +0 -17
  263. package/node_modules/pi-footer/src/widgets/git/staged.ts +0 -17
  264. package/node_modules/pi-footer/src/widgets/git/status.ts +0 -19
  265. package/node_modules/pi-footer/src/widgets/git/unstaged.ts +0 -17
  266. package/node_modules/pi-footer/src/widgets/git/untracked.ts +0 -17
  267. package/node_modules/pi-footer/src/widgets/instance.ts +0 -118
  268. package/node_modules/pi-footer/src/widgets/layout/custom-text.ts +0 -18
  269. package/node_modules/pi-footer/src/widgets/layout/flex-separator.ts +0 -32
  270. package/node_modules/pi-footer/src/widgets/layout/separator.ts +0 -57
  271. package/node_modules/pi-footer/src/widgets/layout/spacer.ts +0 -31
  272. package/node_modules/pi-footer/src/widgets/options.ts +0 -122
  273. package/node_modules/pi-footer/src/widgets/project/runtime.ts +0 -361
  274. package/node_modules/pi-footer/src/widgets/registry.ts +0 -223
  275. package/node_modules/pi-footer/src/widgets/session/assistant-messages.ts +0 -17
  276. package/node_modules/pi-footer/src/widgets/session/compactions.ts +0 -17
  277. package/node_modules/pi-footer/src/widgets/session/elapsed.ts +0 -18
  278. package/node_modules/pi-footer/src/widgets/session/last-activity.ts +0 -18
  279. package/node_modules/pi-footer/src/widgets/session/messages.ts +0 -19
  280. package/node_modules/pi-footer/src/widgets/session/session-id.ts +0 -17
  281. package/node_modules/pi-footer/src/widgets/session/session-start.ts +0 -18
  282. package/node_modules/pi-footer/src/widgets/session/tool-results.ts +0 -17
  283. package/node_modules/pi-footer/src/widgets/session/total-messages.ts +0 -19
  284. package/node_modules/pi-footer/src/widgets/session/total-time.ts +0 -18
  285. package/node_modules/pi-footer/src/widgets/session/user-messages.ts +0 -17
  286. package/node_modules/pi-footer/src/widgets/store.ts +0 -26
  287. package/node_modules/pi-footer/src/widgets/tokens/cache-hit-rate.ts +0 -55
  288. package/node_modules/pi-footer/src/widgets/tokens/cache-read.ts +0 -18
  289. package/node_modules/pi-footer/src/widgets/tokens/cache-write.ts +0 -18
  290. package/node_modules/pi-footer/src/widgets/tokens/context-bar.ts +0 -108
  291. package/node_modules/pi-footer/src/widgets/tokens/context-length.ts +0 -26
  292. package/node_modules/pi-footer/src/widgets/tokens/context-remaining.ts +0 -29
  293. package/node_modules/pi-footer/src/widgets/tokens/context.ts +0 -29
  294. package/node_modules/pi-footer/src/widgets/tokens/cost.ts +0 -51
  295. package/node_modules/pi-footer/src/widgets/tokens/input-speed.ts +0 -25
  296. package/node_modules/pi-footer/src/widgets/tokens/input-tokens.ts +0 -18
  297. package/node_modules/pi-footer/src/widgets/tokens/output-speed.ts +0 -25
  298. package/node_modules/pi-footer/src/widgets/tokens/output-tokens.ts +0 -18
  299. package/node_modules/pi-footer/src/widgets/tokens/tokens.ts +0 -20
  300. package/node_modules/pi-footer/src/widgets/tokens/total-speed.ts +0 -25
  301. package/node_modules/pi-footer/src/widgets/tokens/total-tokens.ts +0 -18
  302. package/node_modules/pi-footer/src/widgets/types.ts +0 -181
  303. package/node_modules/pi-footer/src/widgets/utils/colors.ts +0 -11
  304. package/node_modules/pi-footer/src/widgets/utils/context.ts +0 -112
  305. package/node_modules/pi-footer/src/widgets/utils/session.ts +0 -19
  306. package/node_modules/pi-footer/src/widgets/utils/token-format.ts +0 -78
  307. /package/node_modules/{@herbertgao/resume-from → resume-from}/LICENSE +0 -0
  308. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/claude-code/contract.js +0 -0
  309. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/claude-code/entries.d.ts +0 -0
  310. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/claude-code/entries.js +0 -0
  311. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/claude-code/index.d.ts +0 -0
  312. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/claude-code/index.js +0 -0
  313. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/claude-code/layout.d.ts +0 -0
  314. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/claude-code/layout.js +0 -0
  315. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/claude-code/readback.d.ts +0 -0
  316. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/claude-code/readback.js +0 -0
  317. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/claude-code/redaction.d.ts +0 -0
  318. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/claude-code/validation.d.ts +0 -0
  319. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/claude-code/validation.js +0 -0
  320. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/codex/contract.js +0 -0
  321. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/codex/index.d.ts +0 -0
  322. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/codex/readback.d.ts +0 -0
  323. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/codex/readback.js +0 -0
  324. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/codex/redaction.d.ts +0 -0
  325. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/codex/validation.d.ts +0 -0
  326. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/codex/validation.js +0 -0
  327. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/contract.js +0 -0
  328. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/pi/adapter.d.ts +0 -0
  329. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/pi/contract.js +0 -0
  330. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/pi/format.d.ts +0 -0
  331. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/pi/format.js +0 -0
  332. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/pi/index.d.ts +0 -0
  333. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/pi/index.js +0 -0
  334. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/pi/parse.d.ts +0 -0
  335. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/pi/parse.js +0 -0
  336. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/pi/redaction.d.ts +0 -0
  337. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/pi/validate.d.ts +0 -0
  338. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/pi/validate.js +0 -0
  339. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/bin.d.ts +0 -0
  340. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/bin.js +0 -0
  341. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/contract.d.ts +0 -0
  342. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/contract.js +0 -0
  343. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/agents.d.ts +0 -0
  344. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/agents.js +0 -0
  345. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/cli/args.d.ts +0 -0
  346. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/cli/args.js +0 -0
  347. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/cli/contract.d.ts +0 -0
  348. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/cli/contract.js +0 -0
  349. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/cli/index.d.ts +0 -0
  350. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/cli/index.js +0 -0
  351. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/cli/presentation.d.ts +0 -0
  352. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/cli/presentation.js +0 -0
  353. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/cli/runner.d.ts +0 -0
  354. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/contract.js +0 -0
  355. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/entry.d.ts +0 -0
  356. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/entry.js +0 -0
  357. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/index.d.ts +0 -0
  358. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/index.js +0 -0
  359. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/pi-extension/command.d.ts +0 -0
  360. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/pi-extension/contract.d.ts +0 -0
  361. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/pi-extension/contract.js +0 -0
  362. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/pi-extension/index.d.ts +0 -0
  363. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/pi-extension/index.js +0 -0
  364. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/pi-extension/picker.d.ts +0 -0
  365. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/pi-extension/picker.js +0 -0
  366. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/pi-extension/presentation.d.ts +0 -0
  367. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/pi-extension/presentation.js +0 -0
  368. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/pi-extension/register.d.ts +0 -0
  369. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/pi-extension/register.js +0 -0
  370. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/pi-extension/ui.d.ts +0 -0
  371. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/pi-extension/ui.js +0 -0
  372. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/profile.d.ts +0 -0
  373. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/profile.js +0 -0
  374. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/registry.d.ts +0 -0
  375. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/registry.js +0 -0
  376. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/contract.js +0 -0
  377. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/discovery/contract.js +0 -0
  378. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/discovery/errors.d.ts +0 -0
  379. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/discovery/errors.js +0 -0
  380. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/discovery/homes.d.ts +0 -0
  381. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/discovery/homes.js +0 -0
  382. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/discovery/index.d.ts +0 -0
  383. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/discovery/index.js +0 -0
  384. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/discovery/ordering.d.ts +0 -0
  385. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/discovery/ordering.js +0 -0
  386. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/errors.d.ts +0 -0
  387. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/errors.js +0 -0
  388. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/index.d.ts +0 -0
  389. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/index.js +0 -0
  390. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/landing/contract.js +0 -0
  391. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/landing/errors.d.ts +0 -0
  392. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/landing/errors.js +0 -0
  393. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/landing/handover.d.ts +0 -0
  394. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/landing/handover.js +0 -0
  395. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/landing/index.d.ts +0 -0
  396. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/landing/index.js +0 -0
  397. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/landing/lander.d.ts +0 -0
  398. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/landing/marker.d.ts +0 -0
  399. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/landing/marker.js +0 -0
  400. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/preview/contract.d.ts +0 -0
  401. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/preview/contract.js +0 -0
  402. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/preview/format.d.ts +0 -0
  403. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/preview/format.js +0 -0
  404. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/preview/index.d.ts +0 -0
  405. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/preview/index.js +0 -0
  406. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/transfer/contract.d.ts +0 -0
  407. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/transfer/contract.js +0 -0
  408. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/transfer/index.d.ts +0 -0
  409. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/transfer/index.js +0 -0
  410. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/transfer/rules.d.ts +0 -0
  411. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/transfer/rules.js +0 -0
  412. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/wiring.d.ts +0 -0
  413. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/index.d.ts +0 -0
  414. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/index.js +0 -0
  415. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/config/contract.d.ts +0 -0
  416. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/config/contract.js +0 -0
  417. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/config/defaults.d.ts +0 -0
  418. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/config/defaults.js +0 -0
  419. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/config/errors.d.ts +0 -0
  420. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/config/errors.js +0 -0
  421. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/config/index.d.ts +0 -0
  422. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/config/index.js +0 -0
  423. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/config/loader.d.ts +0 -0
  424. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/config/loader.js +0 -0
  425. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/config/paths.d.ts +0 -0
  426. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/config/paths.js +0 -0
  427. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/config/validate.d.ts +0 -0
  428. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/config/validate.js +0 -0
  429. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/repo/contract.js +0 -0
  430. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/repo/index.d.ts +0 -0
  431. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/repo/index.js +0 -0
  432. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/store/contract.d.ts +0 -0
  433. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/store/contract.js +0 -0
  434. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/store/file-committer.d.ts +0 -0
  435. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/store/file-committer.js +0 -0
  436. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/store/index.d.ts +0 -0
  437. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/store/index.js +0 -0
  438. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/tokens/contract.d.ts +0 -0
  439. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/tokens/contract.js +0 -0
  440. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/tokens/estimator.d.ts +0 -0
  441. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/tokens/estimator.js +0 -0
  442. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/tokens/index.d.ts +0 -0
  443. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/tokens/index.js +0 -0
  444. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/session/contract.js +0 -0
@@ -1,32 +1,39 @@
1
1
  import { Text, truncateToWidth, visibleWidth, wrapTextWithAnsi } from "@earendil-works/pi-tui";
2
- import { posix, win32 } from "node:path";
3
2
  import { inspect } from "node:util";
4
3
  import { config } from "../../config/config.ts";
5
- import { showMoreHintText } from "../show-more-hint.ts";
4
+ import { createCodeBlockHighlighter } from "./diff/diff-highlight.ts";
5
+ import { showMoreHintText } from "./show-more-hint.ts";
6
6
  import { TOOL_LOADING_INTERVAL_MS, toolLoadingIcon } from "../../utils/tool-loading-icon.ts";
7
+ import { getToolMouseTui } from "../mouse/scroll.ts";
7
8
  import { sanitizeToolResultText } from "../../utils/tool-result-sanitize.ts";
8
9
 
10
+ const TOOL_VIEWPORT_WIDTH_RATIO = 0.8;
11
+ /** 宽屏右侧留白上限:比例留白超过这么多列时改用固定留白。 */
12
+ const TOOL_VIEWPORT_MAX_GUTTER = 24;
13
+
9
14
  export function toolViewportWidth(width: number): number {
10
- return Math.max(1, Math.floor(width));
15
+ return Math.max(
16
+ 1,
17
+ Math.floor(width * TOOL_VIEWPORT_WIDTH_RATIO),
18
+ Math.floor(width) - TOOL_VIEWPORT_MAX_GUTTER,
19
+ );
11
20
  }
12
21
 
13
- /** 与默认工具结果相同的一级缩进包装。 */
22
+ /** 与默认工具结果相同的一级缩进包装。子组件只扣始终加上的 1 列;↳ 行多出的 2 列由 truncateToWidth 吃掉。 */
14
23
  export function insetComponent(component: any): any {
15
- return {
24
+ const wrapped: Record<string, unknown> = {
16
25
  render: (width: number) =>
17
26
  component.render(Math.max(1, width - 1)).map((line: string) => {
18
27
  const nestedMarker = line.replace(/^((?:\x1b\[[0-?]*[ -/]*[@-~])*)↳/, "$1 ↳");
19
- return ` ${nestedMarker}`;
28
+ return truncateToWidth(` ${nestedMarker}`, Math.max(0, width), "");
20
29
  }),
21
30
  invalidate: () => component.invalidate?.(),
22
31
  };
23
- }
24
-
25
- export function oneLine(value: unknown, max = 4096): string {
26
- const text = sanitizeToolResultText(String(value ?? ""))
27
- .replace(/\s+/g, " ")
28
- .trim();
29
- return text.length > max ? `${text.slice(0, max - 1)}…` : text;
32
+ // 内层 diff 声明的 remainder 行:鼠标层只能看到这个包装组件。
33
+ if (typeof component.isCollapsedHintLine === "function") {
34
+ wrapped.isCollapsedHintLine = (line: string) => component.isCollapsedHintLine(line);
35
+ }
36
+ return wrapped;
30
37
  }
31
38
 
32
39
  function rawTextFromResult(result: any): string {
@@ -72,14 +79,11 @@ function hasExpandableResult(text: string): boolean {
72
79
  return countLines(text) > 1;
73
80
  }
74
81
 
75
- function toolIcon(_name: string): string {
76
- return "●";
77
- }
78
-
79
82
  const activeAnimationContexts = new Set<any>();
80
83
  let sharedAnimationTimer: ReturnType<typeof setTimeout> | null = null;
81
84
 
82
85
  function clearAnimation(context: any) {
86
+ if (context?.state) context.state.ccstyleAnimationLight = false;
83
87
  if (!context?.state?.ccstyleAnimationScheduled) return;
84
88
  context.state.ccstyleAnimationScheduled = false;
85
89
  activeAnimationContexts.delete(context);
@@ -92,6 +96,7 @@ function clearAnimation(context: any) {
92
96
  export function clearAllAnimations() {
93
97
  for (const ctx of activeAnimationContexts) {
94
98
  ctx.state.ccstyleAnimationScheduled = false;
99
+ ctx.state.ccstyleAnimationLight = false;
95
100
  }
96
101
  activeAnimationContexts.clear();
97
102
  if (sharedAnimationTimer) {
@@ -100,8 +105,15 @@ export function clearAllAnimations() {
100
105
  }
101
106
  }
102
107
 
103
- export function scheduleAnimation(context: any, intervalMs = TOOL_LOADING_INTERVAL_MS) {
108
+ export function scheduleAnimation(
109
+ context: any,
110
+ options: { light?: boolean; intervalMs?: number } = {},
111
+ ) {
104
112
  const state = (context.state ??= {});
113
+ // light:调用方自己在 render() 内重取 loading 帧,定时器只需请求重绘;
114
+ // 否则定时器走 context.invalidate()(compact 摘要等靠它重建)。
115
+ // 每次调用都按本次 options 写入,避免上次 light 残留后非 light 调用仍跳过 invalidate。
116
+ state.ccstyleAnimationLight = Boolean(options.light);
105
117
  if (state.ccstyleAnimationScheduled) return;
106
118
  state.ccstyleAnimationScheduled = true;
107
119
  activeAnimationContexts.add(context);
@@ -110,11 +122,16 @@ export function scheduleAnimation(context: any, intervalMs = TOOL_LOADING_INTERV
110
122
  sharedAnimationTimer = null;
111
123
  const contexts = Array.from(activeAnimationContexts);
112
124
  activeAnimationContexts.clear();
125
+ const tui = getToolMouseTui();
126
+ const canRequestRender = typeof tui?.requestRender === "function";
127
+ let lightFrames = false;
113
128
  for (const ctx of contexts) {
114
129
  ctx.state.ccstyleAnimationScheduled = false;
115
- ctx.invalidate?.();
130
+ if (ctx.state.ccstyleAnimationLight && canRequestRender) lightFrames = true;
131
+ else ctx.invalidate?.();
116
132
  }
117
- }, intervalMs);
133
+ if (lightFrames) tui.requestRender();
134
+ }, options.intervalMs ?? TOOL_LOADING_INTERVAL_MS);
118
135
  }
119
136
  }
120
137
 
@@ -127,7 +144,8 @@ type ToolVisualState = "pending" | "success" | "error";
127
144
  export function settledIcon(name: string, state: ToolVisualState | undefined): string {
128
145
  if (state === "success") return "✓";
129
146
  if (state === "error") return "✗";
130
- return toolIcon(name);
147
+ // toolIcon(name) 曾恒返回 "●",已内联;name 保留以稳定导出签名。
148
+ return "●";
131
149
  }
132
150
 
133
151
  export function setToolVisualState(context: any, visualState: ToolVisualState) {
@@ -213,8 +231,8 @@ export class ExpandedToolResultText {
213
231
  }
214
232
  }
215
233
 
216
- /** Affordance next to truncated Input/Output headers — click opens full preview. */
217
- export const SHOW_MORE_LABEL = "• click to show more";
234
+ /** 截断体末行 `… +N more lines` 旁的展开提示,点击打开全量预览。 */
235
+ export const SHOW_MORE_LABEL = "· click to show more";
218
236
 
219
237
  export type ToolIoSection = "input" | "output";
220
238
 
@@ -232,6 +250,8 @@ const EXPANDED_TOOL_IO_VIEW_GENERATION = Symbol("ccstyle-expanded-tool-io-view")
232
250
  * └ Output click to show more
233
251
  * result line…
234
252
  *
253
+ * flushLeft=true(仅 mode=on 展开卡):去掉树线前导空格,由外层 Box(1,1) 提供 1 格 padding。
254
+ *
235
255
  * Reused across re-renders via context.lastComponent when possible.
236
256
  */
237
257
  export class ExpandedToolIoView {
@@ -247,16 +267,31 @@ export class ExpandedToolIoView {
247
267
  private hoveredSection: ToolIoSection | null = null;
248
268
  /** Which sections currently show the show-more affordance (after last render). */
249
269
  private truncated: { input: boolean; output: boolean } = { input: false, output: false };
250
- /** 0-based body/footer line indexes that carry show-more after last render. */
270
+ /** 0-based header line indexes that carry show-more after last render. */
251
271
  private showMoreHeaderRows: { input?: number; output?: number } = {};
272
+ /** Input 里的代码块(codemode 的 `code`):着色行覆盖默认 dim/muted 样式。 */
273
+ private inputCode?:
274
+ | {
275
+ startLine: number;
276
+ language: string;
277
+ standalone: boolean;
278
+ code: string;
279
+ theme: unknown;
280
+ rows: () => string[];
281
+ }
282
+ | undefined;
283
+
284
+ /** flushLeft:贴左渲染(mode=on 展开卡);默认 false 保留前导空格(compact 等共用路径)。 */
285
+ private flushLeft: boolean;
252
286
 
253
287
  constructor(
254
288
  theme: any,
255
289
  inputBody: string,
256
290
  outputBody: string,
257
291
  isError: boolean,
258
- maxOutputLines = config.expandedPreviewMaxLines,
259
- maxInputLines = config.expandedPreviewMaxLines,
292
+ maxOutputLines = config.expandedOutputMaxLines,
293
+ maxInputLines = config.expandedInputMaxLines,
294
+ flushLeft = false,
260
295
  ) {
261
296
  this.theme = theme;
262
297
  this.inputBody = inputBody;
@@ -264,6 +299,7 @@ export class ExpandedToolIoView {
264
299
  this.isError = isError;
265
300
  this.maxOutputLines = Math.max(1, maxOutputLines);
266
301
  this.maxInputLines = Math.max(1, maxInputLines);
302
+ this.flushLeft = flushLeft;
267
303
  }
268
304
 
269
305
  setContent(
@@ -272,16 +308,19 @@ export class ExpandedToolIoView {
272
308
  isError: boolean,
273
309
  maxOutputLines?: number,
274
310
  maxInputLines?: number,
311
+ flushLeft?: boolean,
275
312
  ): void {
276
313
  const nextOut =
277
314
  maxOutputLines !== undefined ? Math.max(1, maxOutputLines) : this.maxOutputLines;
278
315
  const nextIn = maxInputLines !== undefined ? Math.max(1, maxInputLines) : this.maxInputLines;
316
+ const nextFlush = flushLeft !== undefined ? flushLeft : this.flushLeft;
279
317
  if (
280
318
  this.inputBody === inputBody &&
281
319
  this.outputBody === outputBody &&
282
320
  this.isError === isError &&
283
321
  this.maxOutputLines === nextOut &&
284
- this.maxInputLines === nextIn
322
+ this.maxInputLines === nextIn &&
323
+ this.flushLeft === nextFlush
285
324
  ) {
286
325
  return;
287
326
  }
@@ -290,6 +329,7 @@ export class ExpandedToolIoView {
290
329
  this.isError = isError;
291
330
  this.maxOutputLines = nextOut;
292
331
  this.maxInputLines = nextIn;
332
+ this.flushLeft = nextFlush;
293
333
  this.invalidate();
294
334
  }
295
335
 
@@ -297,6 +337,57 @@ export class ExpandedToolIoView {
297
337
  return this.inputBody;
298
338
  }
299
339
 
340
+ /**
341
+ * 登记 Input 里的代码块:同步 cli-highlight 打底,shiki 异步升级,落地后
342
+ * 经 invalidate 重画。同一份代码与主题只建一次(视图按宽度缓存行)。
343
+ */
344
+ setInputCode(block: InputCodeBlock | undefined): void {
345
+ if (!block) {
346
+ if (this.inputCode) {
347
+ this.inputCode = undefined;
348
+ this.invalidate();
349
+ }
350
+ return;
351
+ }
352
+ if (this.inputCode?.code === block.code && this.inputCode.theme === this.theme) {
353
+ this.inputCode.startLine = block.startLine;
354
+ this.inputCode.standalone = block.standalone;
355
+ return;
356
+ }
357
+ this.inputCode = {
358
+ startLine: block.startLine,
359
+ language: block.language,
360
+ standalone: block.standalone,
361
+ code: block.code,
362
+ theme: this.theme,
363
+ rows: createCodeBlockHighlighter(block.code, block.language, this.theme, () => {
364
+ // 视图自己的行缓存 + 外层工具卡(清 paint 缓存并 requestRender)
365
+ this.invalidate();
366
+ invalidateIoView(this);
367
+ }),
368
+ };
369
+ this.invalidate();
370
+ }
371
+
372
+ /**
373
+ * 整段 Input 就是代码块时给出语言与代码,供全量预览包一层围栏(弹框按 Markdown
374
+ * 渲染,围栏代码块由 pi 的 highlightCode 着色)。混了别的字段时返回 undefined。
375
+ */
376
+ getInputCodeFence(): { language: string; code: string } | undefined {
377
+ const block = this.inputCode;
378
+ return block?.standalone ? { language: block.language, code: block.code } : undefined;
379
+ }
380
+
381
+ /** 代码块里某一源行的着色内容(已剥掉行首缩进);不在块内时为 undefined。 */
382
+ private inputCodeLine(sourceIndex: number): string | undefined {
383
+ const block = this.inputCode;
384
+ if (!block) return undefined;
385
+ const offset = sourceIndex - block.startLine;
386
+ if (offset < 0) return undefined;
387
+ const rows = block.rows();
388
+ return offset < rows.length ? rows[offset] : undefined;
389
+ }
390
+
300
391
  getOutputBody(): string {
301
392
  return this.outputBody.trim() ? this.outputBody : "Done";
302
393
  }
@@ -307,10 +398,14 @@ export class ExpandedToolIoView {
307
398
  this.invalidate();
308
399
  }
309
400
 
310
- /** True when the plain footer line is a truncated section with show-more. */
401
+ getHoveredSection(): ToolIoSection | null {
402
+ return this.hoveredSection;
403
+ }
404
+
405
+ /** True when the plain truncation footer carries show-more. Input 续行带 │,Output 不带。 */
311
406
  matchShowMoreLine(plainLine: string): ToolIoSection | null {
312
407
  const line = plainLine.replace(/\x1b\[[0-9;]*m/g, "");
313
- if (!line.includes(` • ${showMoreHintText()}`) || !/\+\d+ more lines/.test(line)) return null;
408
+ if (!line.includes(` · ${showMoreHintText()}`) || !/\+\d+ more lines/.test(line)) return null;
314
409
  if (this.truncated.input && line.includes("│")) return "input";
315
410
  if (this.truncated.output) return "output";
316
411
  return null;
@@ -331,7 +426,7 @@ export class ExpandedToolIoView {
331
426
  /** Column range (1-based, visible cells) of show-more on a rendered header, if present. */
332
427
  showMoreHitbox(plainLine: string): { startCol: number; endCol: number } | null {
333
428
  const line = plainLine.replace(/\x1b\[[0-9;]*m/g, "");
334
- const label = ` • ${showMoreHintText()}`;
429
+ const label = ` · ${showMoreHintText()}`;
335
430
  const idx = line.lastIndexOf(label);
336
431
  if (idx < 0) return null;
337
432
  const before = line.slice(0, idx);
@@ -347,7 +442,9 @@ export class ExpandedToolIoView {
347
442
 
348
443
  const theme = this.theme;
349
444
  const safeWidth = Math.max(1, Math.floor(width));
350
- const rail = " │ ";
445
+ // flushLeft:贴左(外层 Box 负责 1 格 pad);否则保留 1 格前导空格(compact 共用)
446
+ const lead = this.flushLeft ? "" : " ";
447
+ const rail = `${lead}│ `;
351
448
  const railWidth = visibleWidth(rail);
352
449
  const bodyWidth = toolViewportWidth(safeWidth);
353
450
  const contentWidth = Math.max(1, bodyWidth - railWidth);
@@ -357,7 +454,7 @@ export class ExpandedToolIoView {
357
454
  this.showMoreHeaderRows = {};
358
455
 
359
456
  const pushHeader = (corner: "├" | "└", label: string) => {
360
- const mark = theme.fg("dim", ` ${corner} `);
457
+ const mark = theme.fg("dim", `${lead}${corner} `);
361
458
  const title = theme.fg(
362
459
  "accent",
363
460
  typeof theme.bold === "function" ? theme.bold(label) : label,
@@ -366,20 +463,13 @@ export class ExpandedToolIoView {
366
463
  };
367
464
 
368
465
  const pushRailLine = (styledContent: string, continued = true) => {
369
- const prefix = continued ? rail : " ";
466
+ // 续行 rail;Output 正文相对 └ 缩进 2 格(+ 可选 lead)
467
+ const prefix = continued ? rail : `${lead} `;
370
468
  lines.push(truncateToWidth(theme.fg("dim", prefix) + styledContent, safeWidth, ""));
371
469
  };
372
470
 
373
471
  const pushBlankRail = () => {
374
- lines.push(truncateToWidth(theme.fg("dim", " │"), safeWidth, ""));
375
- };
376
-
377
- /** Style `key: value` input rows — dim keys, readable values. */
378
- const styleInputLine = (rawLine: string): string => {
379
- const match = rawLine.match(/^([A-Za-z_][\w.-]*)(:\s*)(.*)$/);
380
- if (!match) return theme.fg("muted", rawLine);
381
- const [, key, sep, rest] = match;
382
- return theme.fg("dim", key + sep) + theme.fg("muted", rest ?? "");
472
+ lines.push(truncateToWidth(theme.fg("dim", `${lead}│`), safeWidth, ""));
383
473
  };
384
474
 
385
475
  const pushBody = (
@@ -393,8 +483,13 @@ export class ExpandedToolIoView {
393
483
  }
394
484
  const sourceLines = raw.split("\n");
395
485
  const wrapped: string[] = [];
396
- for (const source of sourceLines) {
397
- const styled = opts.input ? styleInputLine(source) : theme.fg(bodyColor, source);
486
+ for (const [index, source] of sourceLines.entries()) {
487
+ if (opts.input) {
488
+ // 代码块的行用着色版本(已剥缩进),其余走默认 dim/muted
489
+ wrapped.push(...wrapInputLine(source, contentWidth, theme, this.inputCodeLine(index)));
490
+ continue;
491
+ }
492
+ const styled = theme.fg(bodyColor, source);
398
493
  const parts = wrapTextWithAnsi(styled, contentWidth);
399
494
  if (parts.length === 0) wrapped.push(styled);
400
495
  else wrapped.push(...parts);
@@ -407,8 +502,9 @@ export class ExpandedToolIoView {
407
502
  if (truncated) {
408
503
  const hidden = Math.max(0, wrapped.length - visible.length);
409
504
  if (hidden > 0) {
505
+ // hover 只高亮文字,圆点保持 dim(与 group hint 一致)。
410
506
  const more =
411
- theme.fg("dim", " •") +
507
+ theme.fg("dim", " ·") +
412
508
  theme.fg(
413
509
  this.hoveredSection === opts.section ? "text" : "dim",
414
510
  ` ${showMoreHintText()}`,
@@ -423,9 +519,18 @@ export class ExpandedToolIoView {
423
519
  const hasInput = this.inputBody.trim().length > 0;
424
520
  const outputText = this.getOutputBody();
425
521
 
522
+ // Decide show-more from the same truncation rules as pushBody.
426
523
  const inputWouldTruncate =
427
524
  hasInput &&
428
- bodyExceedsLineLimit(this.inputBody, this.maxInputLines, contentWidth, true, theme);
525
+ bodyExceedsLineLimit(
526
+ this.inputBody,
527
+ this.maxInputLines,
528
+ contentWidth,
529
+ true,
530
+ theme,
531
+ bodyColor,
532
+ (inputIndex: number) => this.inputCodeLine(inputIndex),
533
+ );
429
534
  const outputWouldTruncate = bodyExceedsLineLimit(
430
535
  outputText,
431
536
  this.maxOutputLines,
@@ -447,11 +552,19 @@ export class ExpandedToolIoView {
447
552
  pushBlankRail();
448
553
  this.truncated.output = outputWouldTruncate;
449
554
  pushHeader("└", "Output");
450
- pushBody(outputText, { limit: this.maxOutputLines, continued: false, section: "output" });
555
+ pushBody(outputText, {
556
+ limit: this.maxOutputLines,
557
+ continued: false,
558
+ section: "output",
559
+ });
451
560
  } else {
452
561
  this.truncated.output = outputWouldTruncate;
453
562
  pushHeader("└", "Output");
454
- pushBody(outputText, { limit: this.maxOutputLines, continued: false, section: "output" });
563
+ pushBody(outputText, {
564
+ limit: this.maxOutputLines,
565
+ continued: false,
566
+ section: "output",
567
+ });
455
568
  }
456
569
 
457
570
  this.cachedWidth = width;
@@ -477,6 +590,40 @@ export function isExpandedToolIoView(value: unknown): value is ExpandedToolIoVie
477
590
  );
478
591
  }
479
592
 
593
+ /** Input 行着色:`key: value` 拆成 dim 键 + muted 值,其余整行 muted。 */
594
+ function styleInputSourceLine(line: string, theme: any): string {
595
+ const match = line.match(/^([A-Za-z_][\w.-]*)(:\s*)(.*)$/);
596
+ if (!match) return theme.fg("muted", line);
597
+ const [, key, sep, rest] = match;
598
+ return theme.fg("dim", key + sep) + theme.fg("muted", rest ?? "");
599
+ }
600
+
601
+ /**
602
+ * 折一行 Input 源码。不带 styledBody 时与改动前完全一致(其他工具不受影响);
603
+ * 代码块(styledBody = 已着色且已剥缩进的行)续行跟着源码前导缩进:顶到 rail
604
+ * 会被读成新的一行,所以缩进先剥掉、折行宽度相应扣减,再给每一行加回去。
605
+ * 行数判断(bodyExceedsLineLimit)与实际渲染共用这一套,展开提示才对得上。
606
+ */
607
+ function wrapInputLine(
608
+ source: string,
609
+ contentWidth: number,
610
+ theme: any,
611
+ styledBody?: string,
612
+ ): string[] {
613
+ if (styledBody === undefined) {
614
+ const styled = styleInputSourceLine(source, theme);
615
+ const parts = wrapTextWithAnsi(styled, contentWidth);
616
+ return parts.length ? parts : [styled];
617
+ }
618
+ const lead = /^[ \t]*/.exec(source)?.[0] ?? "";
619
+ const leadWidth = visibleWidth(lead);
620
+ const parts = wrapTextWithAnsi(styledBody, Math.max(1, contentWidth - leadWidth));
621
+ const rows = parts.length ? parts : [styledBody];
622
+ if (!leadWidth) return rows;
623
+ const prefix = theme.fg("muted", lead);
624
+ return rows.map((row) => prefix + row);
625
+ }
626
+
480
627
  /** True when body needs truncation at the given line limit (source lines or wrapped rows). */
481
628
  function bodyExceedsLineLimit(
482
629
  body: string,
@@ -485,23 +632,18 @@ function bodyExceedsLineLimit(
485
632
  asInput: boolean,
486
633
  theme: any,
487
634
  bodyColor = "toolOutput",
635
+ /** 代码块的源行取着色内容,行数判断与实际渲染保持同一套规则。 */
636
+ codeLine?: (sourceIndex: number) => string | undefined,
488
637
  ): boolean {
489
638
  const raw = body.replace(/\t/g, " ").replace(/\n+$/, "");
490
639
  if (!raw.trim()) return false;
491
640
  const sourceLines = raw.split("\n");
492
641
  if (sourceLines.length > limit) return true;
493
642
  let total = 0;
494
- for (const source of sourceLines) {
495
- let styled: string;
496
- if (asInput) {
497
- const match = source.match(/^([A-Za-z_][\w.-]*)(:\s*)(.*)$/);
498
- styled = match
499
- ? theme.fg("dim", match[1] + match[2]) + theme.fg("muted", match[3] ?? "")
500
- : theme.fg("muted", source);
501
- } else {
502
- styled = theme.fg(bodyColor, source);
503
- }
504
- const parts = wrapTextWithAnsi(styled, contentWidth);
643
+ for (const [index, source] of sourceLines.entries()) {
644
+ const parts = asInput
645
+ ? wrapInputLine(source, contentWidth, theme, codeLine?.(index))
646
+ : wrapTextWithAnsi(theme.fg(bodyColor, source), contentWidth);
505
647
  total += Math.max(1, parts.length);
506
648
  if (total > limit) return true;
507
649
  }
@@ -558,123 +700,42 @@ export function middleTruncateToWidth(text: string, width: number): string {
558
700
  return `${left}…${right}`;
559
701
  }
560
702
 
561
- export type ToolCallSummary = {
562
- main: string;
563
- detail: string;
564
- /** 路径摘要保留结构,供最终渲染按实际宽度优先保留文件名。 */
565
- path?: { prefix: string; value: string };
703
+ /**
704
+ * 展开卡 Input 的代码块:源行起始下标(相对 text)+ 语言 + 剥掉行首缩进的代码。
705
+ * standalone = 整段 Input 就是这块代码(没有 `code:` 标签),全量预览可以整段包围栏。
706
+ */
707
+ export type InputCodeBlock = {
708
+ startLine: number;
709
+ language: string;
710
+ code: string;
711
+ standalone: boolean;
566
712
  };
567
713
 
568
- function pathApi(value: string) {
569
- if (posix.isAbsolute(value)) return posix;
570
- if (win32.isAbsolute(value)) return win32;
571
- return undefined;
572
- }
573
-
574
- /** cwd 内绝对路径转相对路径;cwd 外路径保持不变。 */
575
- export function displayPath(value: unknown, cwd?: string): string {
576
- const text = oneLine(value, 4096);
577
- const base = cwd ? oneLine(cwd, 4096) : "";
578
- const api = pathApi(text);
579
- if (!api || !base || !api.isAbsolute(base)) return text;
580
- const relative = api.relative(base, text);
581
- if (!relative) return api.basename(text) || ".";
582
- if (relative === ".." || relative.startsWith(`..${api.sep}`) || api.isAbsolute(relative)) {
583
- return text;
584
- }
585
- return relative;
586
- }
714
+ export type ToolInputBody = { text: string; codeBlock?: InputCodeBlock };
587
715
 
588
- function headToWidth(text: string, width: number, ellipsis = ""): string {
589
- if (visibleWidth(text) <= width) return text;
590
- if (width <= 0) return "";
591
- const suffix = visibleWidth(ellipsis) <= width ? ellipsis : "";
592
- const contentWidth = width - visibleWidth(suffix);
593
- let head = "";
594
- for (const char of Array.from(text)) {
595
- if (visibleWidth(head + char) > contentWidth) break;
596
- head += char;
597
- }
598
- return head + suffix;
599
- }
600
-
601
- function tailToWidth(text: string, width: number): string {
602
- if (width <= 0) return "";
603
- let tail = "";
604
- for (const char of Array.from(text).reverse()) {
605
- if (visibleWidth(char + tail) > width) break;
606
- tail = char + tail;
607
- }
608
- return tail;
609
- }
610
-
611
- /** 中间截断路径:目录保留开头,末尾优先完整保留文件名。 */
612
- export function truncatePathToWidth(path: string, width: number): string {
613
- if (visibleWidth(path) <= width) return path;
614
- if (width <= 1) return width === 1 ? "…" : "";
615
- const separatorIndex = Math.max(path.lastIndexOf("/"), path.lastIndexOf("\\"));
616
- const filename = separatorIndex >= 0 ? path.slice(separatorIndex + 1) : path;
617
- const filenameWidth = visibleWidth(filename);
618
- if (separatorIndex >= 0 && filenameWidth + 1 <= width) {
619
- const separator = path[separatorIndex]!;
620
- const suffix = `${separator}${filename}`;
621
- const prefixWidth = width - visibleWidth(suffix) - 1;
622
- const prefix = headToWidth(path.slice(0, separatorIndex), Math.max(0, prefixWidth));
623
- return `${prefix}…${prefix ? suffix : filename}`;
624
- }
625
- const leftWidth = Math.max(1, Math.floor((width - 1) * 0.45));
626
- const rightWidth = Math.max(0, width - leftWidth - 1);
627
- return `${headToWidth(filename, leftWidth)}…${tailToWidth(filename, rightWidth)}`;
628
- }
629
-
630
- /** 路径展示的统一入口:相对化后按当前可用宽度中间截断。 */
631
- export function formatDisplayPath(value: unknown, cwd: string | undefined, width: number): string {
632
- return truncatePathToWidth(displayPath(value, cwd), Math.max(0, Math.floor(width)));
633
- }
634
-
635
- /** 按最终终端宽度渲染摘要;路径摘要不会再被整行头部截断。 */
636
- export function fitToolCallSummary(summary: ToolCallSummary, width: number): string {
637
- if (!summary.path) return headTruncateToWidth(summary.main, width);
638
- const prefix = summary.path.prefix;
639
- const pathWidth = Math.max(0, width - visibleWidth(prefix) - 1);
640
- if (pathWidth <= 0) return headTruncateToWidth(prefix, width);
641
- return `${prefix} ${truncatePathToWidth(summary.path.value, pathWidth)}`;
642
- }
643
-
644
- export function pathSummary(
645
- prefix: string,
646
- value: unknown,
647
- cwd: string | undefined,
648
- detail = "",
649
- ): ToolCallSummary {
650
- const path = displayPath(value, cwd);
651
- return {
652
- main: `${prefix} ${path}`,
653
- detail,
654
- path: { prefix, value: path },
655
- };
656
- }
716
+ /** 按字段名判定可着色的入参:codemode / mcpscript 的 `code` 都是 JS 脚本。 */
717
+ const INPUT_CODE_LANGUAGES: Record<string, string> = { code: "javascript" };
657
718
 
658
719
  /** Pretty-print tool call args for the expanded Input section. */
659
- export function formatToolInputArgs(args: unknown, maxChars = 8_000): string {
660
- if (args === undefined || args === null) return "";
720
+ export function formatToolInputBody(args: unknown, maxChars = 8_000): ToolInputBody {
721
+ if (args === undefined || args === null) return { text: "" };
661
722
  if (typeof args !== "object") {
662
723
  const text = sanitizeToolResultText(String(args));
663
- return text.length > maxChars ? `${text.slice(0, maxChars)}…` : text;
724
+ return { text: text.length > maxChars ? `${text.slice(0, maxChars)}…` : text };
664
725
  }
665
726
  if (Array.isArray(args)) {
666
727
  try {
667
728
  const json = JSON.stringify(args, null, 2);
668
- return json.length > maxChars ? `${json.slice(0, maxChars)}…` : json;
729
+ return { text: json.length > maxChars ? `${json.slice(0, maxChars)}…` : json };
669
730
  } catch {
670
- return sanitizeToolResultText(String(args));
731
+ return { text: sanitizeToolResultText(String(args)) };
671
732
  }
672
733
  }
673
734
 
674
735
  const entries = Object.entries(args as Record<string, unknown>).filter(
675
736
  ([, value]) => value !== undefined,
676
737
  );
677
- if (entries.length === 0) return "";
738
+ if (entries.length === 0) return { text: "" };
678
739
 
679
740
  // Stable, human-first field order for common tools.
680
741
  const preferred = [
@@ -700,13 +761,30 @@ export function formatToolInputArgs(args: unknown, maxChars = 8_000): string {
700
761
  });
701
762
 
702
763
  const lines: string[] = [];
764
+ let codeBlock: InputCodeBlock | undefined;
703
765
  for (const [rawKey, value] of entries) {
704
766
  const key = sanitizeToolResultText(rawKey);
705
767
  if (typeof value === "string") {
706
768
  const safeValue = sanitizeToolResultText(value);
707
769
  if (safeValue.includes("\n")) {
708
- lines.push(`${key}:`);
709
- for (const line of safeValue.replace(/\t/g, " ").split("\n")) {
770
+ const expanded = safeValue.replace(/\t/g, " ");
771
+ const language = INPUT_CODE_LANGUAGES[key];
772
+ // 只有一个 code 字段时(codemode 等)整块 Input 就是脚本,`code:` 标签是噪音
773
+ const standaloneCode = Boolean(language) && entries.length === 1;
774
+ if (!standaloneCode) lines.push(`${key}:`);
775
+ if (language) {
776
+ // 缩进由 wrapInputLine 负责,着色只喂剥掉行首缩进的正文
777
+ codeBlock = {
778
+ startLine: lines.length,
779
+ language,
780
+ code: expanded
781
+ .split("\n")
782
+ .map((line) => line.replace(/^[ \t]*/, ""))
783
+ .join("\n"),
784
+ standalone: standaloneCode,
785
+ };
786
+ }
787
+ for (const line of expanded.split("\n")) {
710
788
  lines.push(` ${line}`);
711
789
  }
712
790
  } else {
@@ -731,7 +809,13 @@ export function formatToolInputArgs(args: unknown, maxChars = 8_000): string {
731
809
  }
732
810
  }
733
811
  const text = lines.join("\n");
734
- return text.length > maxChars ? `${text.slice(0, maxChars)}…` : text;
812
+ // 截断后的行号与着色行不再对齐,这时只给纯文本
813
+ if (text.length > maxChars) return { text: `${text.slice(0, maxChars)}…` };
814
+ return codeBlock ? { text, codeBlock } : { text };
815
+ }
816
+
817
+ export function formatToolInputArgs(args: unknown, maxChars = 8_000): string {
818
+ return formatToolInputBody(args, maxChars).text;
735
819
  }
736
820
 
737
821
  export function hasExpandableDetail(outputText: string, args: unknown): boolean {
@@ -746,8 +830,10 @@ export function renderExpandedToolResult(
746
830
  lastComponent?: unknown,
747
831
  args?: unknown,
748
832
  context?: any,
833
+ /** mode=on 展开卡贴左;compact 等保持默认前导空格 */
834
+ flushLeft = false,
749
835
  ): ExpandedToolIoView | ExpandedToolResultText | Text {
750
- const inputBody = formatToolInputArgs(args);
836
+ const { text: inputBody, codeBlock } = formatToolInputBody(args);
751
837
  const outputBody = body;
752
838
  const maxOutputLines = config.expandedOutputMaxLines;
753
839
  const maxInputLines = config.expandedInputMaxLines;
@@ -756,7 +842,14 @@ export function renderExpandedToolResult(
756
842
  if (inputBody.trim() || outputBody.trim()) {
757
843
  let view: ExpandedToolIoView;
758
844
  if (isExpandedToolIoView(lastComponent)) {
759
- lastComponent.setContent(inputBody, outputBody, isError, maxOutputLines, maxInputLines);
845
+ lastComponent.setContent(
846
+ inputBody,
847
+ outputBody,
848
+ isError,
849
+ maxOutputLines,
850
+ maxInputLines,
851
+ flushLeft,
852
+ );
760
853
  view = lastComponent;
761
854
  } else {
762
855
  view = new ExpandedToolIoView(
@@ -766,8 +859,10 @@ export function renderExpandedToolResult(
766
859
  isError,
767
860
  maxOutputLines,
768
861
  maxInputLines,
862
+ flushLeft,
769
863
  );
770
864
  }
865
+ view.setInputCode(codeBlock);
771
866
  if (context) rememberIoView(context, view);
772
867
  return view;
773
868
  }
@@ -803,7 +898,7 @@ function frameViewId(view: ExpandedToolIoView): number | null {
803
898
  function withIoViewMarkers(view: ExpandedToolIoView, lines: string[]): string[] {
804
899
  const id = frameViewId(view);
805
900
  if (id === null) return lines;
806
- // Mark by exact recorded show-more row from render — never scan body text heuristically.
901
+ // Mark by exact header row from render — never scan body text for Input/Output labels.
807
902
  const marked = lines.slice();
808
903
  for (const { section, line } of view.showMoreHeaderLineIndexes()) {
809
904
  if (line < 0 || line >= marked.length) continue;