@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,8 +1,8 @@
1
1
  import { visibleWidth } from "@earendil-works/pi-tui";
2
2
  import { ThinkingPreviewBlock } from "../../feature/compact-thinking.ts";
3
3
  import { isCompactAssistantComponent } from "../compact-mode.ts";
4
- import { isMessageDisplayComponent } from "../message-display.ts";
5
4
  import { ToolGroupComponent } from "../tool/grouping.ts";
5
+ import { isMessageDisplayComponent } from "../tool/message-display.ts";
6
6
  import { isToolExecutionComponent, stripTerminalSequencesPreservingLayout } from "./packets.ts";
7
7
  import { getScrollButtonWidget } from "./scroll.ts";
8
8
 
@@ -11,12 +11,17 @@ export type ComponentRowHit = {
11
11
  row: number;
12
12
  /** 内部工具命中时所属的展开 group;普通卡点击仍折叠整个 group。 */
13
13
  group?: ToolGroupComponent;
14
+ /** compact 展开面板内的命中:外层面板,单击非提示区时收起它。 */
15
+ owner?: any;
14
16
  };
15
17
 
16
- /** 行内 [click to show more] 提示的命中列区间(1-based,含两端)。 */
18
+ /** 行内 [click to show more] / [↑ Collapse] 提示的命中列区间(1-based,含两端)。 */
17
19
  export function collapsedHintHitbox(line: string): { startCol: number; endCol: number } | null {
18
20
  const plain = stripTerminalSequencesPreservingLayout(line);
19
- const match = /(\([^()\n]* \/ click\)|click to show more|to show more)(?=\)?\s*$)/.exec(plain);
21
+ const match =
22
+ /(\([^()\n]* \/ click\)|click to show more|to show more|↑ Collapse|to collapse)(?=\)?\s*$)/.exec(
23
+ plain,
24
+ );
20
25
  if (!match?.[1]) return null;
21
26
  const startCol = visibleWidth(plain.slice(0, match.index)) + 1;
22
27
  return { startCol, endCol: startCol + visibleWidth(match[1]) - 1 };
@@ -119,11 +124,15 @@ export function componentAtLocalRow(
119
124
  return { component, row: localRow };
120
125
  }
121
126
  if (isCompactAssistantComponent(component)) {
122
- // 折叠:整行摘要。展开:先命中内部 thinking hint,其余仍归外层卡片。
127
+ // 折叠:整行摘要。展开:先命中面板内 thinking/工具卡/文本,其余(空行)仍归外层卡片。
123
128
  if (component.expanded === true) {
124
129
  const inner = nestedChildAtRow(component, localRow, width);
125
- if (inner instanceof ThinkingPreviewBlock) {
126
- return { component: inner, row: localRow };
130
+ if (inner) {
131
+ // 展开的 thinking 有自己的展开态:点它只收它自己,不收整块面板。
132
+ const ownExpandable = inner instanceof ThinkingPreviewBlock && inner.expanded === true;
133
+ return ownExpandable
134
+ ? { component: inner, row: localRow }
135
+ : { component: inner, row: localRow, owner: component };
127
136
  }
128
137
  }
129
138
  return { component, row: localRow };
@@ -1,12 +1,16 @@
1
1
  import type { ExpandedToolIoView, ToolIoSection } from "../tool/result.ts";
2
-
3
- /** SGR 鼠标协议包(code;col;row + M/m 终结符)。 */
4
- export type SgrMousePacket = {
5
- code: number;
6
- col: number;
7
- row: number;
8
- final: "M" | "m";
9
- };
2
+ import { walkComponentTree } from "../../utils/component-tree.ts";
3
+ export {
4
+ stripTerminalSequences,
5
+ stripTerminalSequencesPreservingLayout,
6
+ } from "../../utils/ansi-text.ts";
7
+ export {
8
+ parseSgrMousePackets,
9
+ isSgrLeftPress,
10
+ isSgrLeftRelease,
11
+ isSgrIdleMotion,
12
+ type SgrMousePacket,
13
+ } from "../../utils/sgr-mouse.ts";
10
14
 
11
15
  /** Final painted placement of one outermost tool/group row after parent layout. */
12
16
  export type FrameToolPlacement = {
@@ -24,53 +28,6 @@ const TOOL_FRAME_MARKER_RE = /\x1b_cc:t(\d+):(\d+)\x07/g;
24
28
  const TOOL_VIEW_MARKER_RE = /\x1b_cc:v(\d+):([io])\x07/g;
25
29
  export const toolFrameMarker = (id: number, row: number) => `\x1b_cc:t${id}:${row}\x07`;
26
30
 
27
- /**
28
- * 解析整段终端输入为 SGR 鼠标包序列;数据必须完全由连续 SGR 包组成
29
- * (夹杂其他字节返回 null,交由常规输入链处理)。
30
- */
31
- export function parseSgrMousePackets(data: string): SgrMousePacket[] | null {
32
- const pattern = /\x1b\[<(\d+);(\d+);(\d+)([Mm])/g;
33
- const packets: SgrMousePacket[] = [];
34
- let offset = 0;
35
-
36
- for (const match of data.matchAll(pattern)) {
37
- if (match.index !== offset) return null;
38
- offset = match.index + match[0].length;
39
- packets.push({
40
- code: Number(match[1]),
41
- col: Number(match[2]),
42
- row: Number(match[3]),
43
- final: match[4] as "M" | "m",
44
- });
45
- }
46
-
47
- return packets.length > 0 && offset === data.length ? packets : null;
48
- }
49
-
50
- /** 是否为左键按下(排除修饰键、32 表示 motion 事件)。 */
51
- export function isSgrLeftPress(packet: SgrMousePacket): boolean {
52
- const baseButton = packet.code & ~(4 | 8 | 16 | 32);
53
- return packet.final === "M" && baseButton === 0 && (packet.code & 32) === 0;
54
- }
55
-
56
- /** 是否为左键松开。 */
57
- export function isSgrLeftRelease(packet: SgrMousePacket): boolean {
58
- const baseButton = packet.code & ~(4 | 8 | 16 | 32);
59
- return packet.final === "m" && baseButton === 0 && (packet.code & 32) === 0;
60
- }
61
-
62
- /** 仅剥离终端序列、保留原布局(换行/空白不动),用于命中区间计算。 */
63
- export function stripTerminalSequencesPreservingLayout(value: string): string {
64
- return value
65
- .replace(/\x1b\][^\x07]*(?:\x07|\x1b\\)/g, "")
66
- .replace(/\x1b\[[0-?]*[ -/]*[@-~]/g, "");
67
- }
68
-
69
- /** 剥离终端序列并折叠空白(用于纯文本比较)。 */
70
- export function stripTerminalSequences(value: string): string {
71
- return stripTerminalSequencesPreservingLayout(value).replace(/\s+/g, " ").trim();
72
- }
73
-
74
31
  /** 工具执行组件识别(toolCallId + setExpanded + render)。 */
75
32
  export function isToolExecutionComponent(value: any): boolean {
76
33
  return Boolean(
@@ -83,24 +40,13 @@ export function isToolExecutionComponent(value: any): boolean {
83
40
  }
84
41
 
85
42
  /** 深度收集组件树中的工具执行组件(含 getMountedRoots 分支)。 */
86
- export function collectToolComponents(component: any, tools: any[], seen = new Set<any>()): void {
87
- if (!component || typeof component !== "object" || seen.has(component)) return;
88
- seen.add(component);
89
- if (isToolExecutionComponent(component)) {
90
- tools.push(component);
91
- return;
92
- }
93
- if (Array.isArray(component.children)) {
94
- for (const child of component.children) collectToolComponents(child, tools, seen);
95
- }
96
- try {
97
- const mounted = component.getMountedRoots?.();
98
- if (Array.isArray(mounted)) {
99
- for (const root of mounted) collectToolComponents(root, tools, seen);
43
+ export function collectToolComponents(component: any, tools: any[]): void {
44
+ walkComponentTree(component, (value: any) => {
45
+ if (isToolExecutionComponent(value)) {
46
+ tools.push(value);
47
+ return false;
100
48
  }
101
- } catch {
102
- // renderer 切换中的惰性 Proxy 可能暂时没有 mounted roots。
103
- }
49
+ });
104
50
  }
105
51
 
106
52
  /** 剥离一行中的零宽帧/视图 marker。 */
@@ -8,35 +8,39 @@ import {
8
8
  import { config } from "../../config/config.ts";
9
9
  import { isLazyProxyTui } from "../../utils/fullscreen-detect.ts";
10
10
  import { parseSgrMousePackets } from "./packets.ts";
11
+ import {
12
+ OFFICIAL_SCROLL_TO_END_KEY,
13
+ patchRegistry,
14
+ SCROLL_BUTTON_STATE_SLOT,
15
+ TOOL_MOUSE_TUI_SLOT,
16
+ } from "../../utils/patch-keys.ts";
11
17
 
12
18
  const ZENTUI_PAGE_UP_INPUT = /^\x1b\[5;9(?::[12])?~$|^\x1b\[57421;9(?::[12])?u$|^\x1b\[1;6A$/;
13
19
  const ZENTUI_PAGE_DOWN_INPUT = /^\x1b\[6;9(?::[12])?~$|^\x1b\[57422;9(?::[12])?u$|^\x1b\[1;6B$/;
14
20
  const SCROLL_BOTTOM_SHORTCUT = "ctrl+end";
15
21
 
16
- /**
17
- * 当前安装的 tui 宿主。宿主放本模块(滚动按钮/调度依赖它),
18
- * 由 mouse-interaction 经 setToolMouseTui 维护;跨模块一律经绑定/setter 访问。
19
- *
20
- * 状态镜像到 globalThis(Symbol 槽):jiti 转译下经 re-export 链读取的
21
- * 模块级 let 绑定是初始值快照(死绑定,实测恒 null),函数调用才是活引用。
22
- * 跨模块读取一律用 getToolMouseTui(),避免拿到加载时的快照。
23
- */
24
- const TOOL_MOUSE_TUI_SLOT = Symbol.for("pi.ccstyle.tool-mouse-tui");
25
- (globalThis as any)[TOOL_MOUSE_TUI_SLOT] ??= null;
22
+ patchRegistry.ensure(TOOL_MOUSE_TUI_SLOT, () => null);
26
23
  export function getToolMouseTui(): any {
27
- return (globalThis as any)[TOOL_MOUSE_TUI_SLOT];
24
+ return patchRegistry.get(TOOL_MOUSE_TUI_SLOT);
28
25
  }
29
26
  export function setToolMouseTui(tui: any): void {
30
- (globalThis as any)[TOOL_MOUSE_TUI_SLOT] = tui;
27
+ patchRegistry.install(TOOL_MOUSE_TUI_SLOT, tui);
31
28
  }
32
29
 
33
- // 滚动按钮状态同 toolMouseTui:镜像到 globalThis(Symbol 槽),跨模块读取
34
- // 一律用 getter(jiti 转译下模块级 let 绑定是初始值快照)。
35
- const SCROLL_BUTTON_STATE_SLOT = Symbol.for("pi.ccstyle.scroll-button-state");
36
- type ScrollButtonState = { visible: boolean; hovered: boolean; widget: any };
30
+ type ScrollButtonState = {
31
+ visible: boolean;
32
+ hovered: boolean;
33
+ widget: any;
34
+ /** 按钮可见期间新落的 transcript 块数(消息 + 工具卡)。 */
35
+ newCount: number;
36
+ };
37
37
  function scrollButtonState(): ScrollButtonState {
38
- const host = globalThis as any;
39
- return (host[SCROLL_BUTTON_STATE_SLOT] ??= { visible: false, hovered: false, widget: null });
38
+ return patchRegistry.ensure(SCROLL_BUTTON_STATE_SLOT, () => ({
39
+ visible: false,
40
+ hovered: false,
41
+ widget: null,
42
+ newCount: 0,
43
+ }));
40
44
  }
41
45
  export function getScrollButtonVisible(): boolean {
42
46
  return scrollButtonState().visible;
@@ -47,8 +51,32 @@ export function getScrollButtonHovered(): boolean {
47
51
  export function getScrollButtonWidget(): any {
48
52
  return scrollButtonState().widget;
49
53
  }
54
+ export function getScrollButtonNewCount(): number {
55
+ return scrollButtonState().newCount;
56
+ }
50
57
  export function setScrollButtonVisible(visible: boolean): void {
51
- scrollButtonState().visible = visible;
58
+ const state = scrollButtonState();
59
+ state.visible = visible;
60
+ // 计数只在离开底部期间有效:跟随输出即清零,文案回到 Back to bottom。
61
+ if (!visible) state.newCount = 0;
62
+ }
63
+
64
+ /**
65
+ * 记账一块新落进 transcript 的内容(用户/助手消息、工具卡)。
66
+ * 仅在按钮可见(已滚动离开底部)时累加,并请求重绘让按钮文案立即更新。
67
+ */
68
+ export function noteNewTranscriptItem(): void {
69
+ const state = scrollButtonState();
70
+ const tui = getToolMouseTui();
71
+ if (!state.visible || !tui) return;
72
+ // 提交新消息时官方可能直接跳回底部(不经过滚动输入):先按实时跟随状态校正,
73
+ // 否则跟随期间的内容会被当成“离开底部时的新消息”计入。
74
+ if (isAtTranscriptBottom(tui)) {
75
+ hideScrollButton(tui);
76
+ return;
77
+ }
78
+ state.newCount += 1;
79
+ tui.requestRender?.();
52
80
  }
53
81
 
54
82
  /** 返回是否发生变化(调用方据此决定是否需要重渲染)。 */
@@ -67,15 +95,16 @@ export function resetScrollButtonState(): void {
67
95
  scrollButtonState().visible = false;
68
96
  scrollButtonState().hovered = false;
69
97
  scrollButtonState().widget = null;
98
+ scrollButtonState().newCount = 0;
70
99
  scrollButtonSyncScheduled = false;
71
100
  }
72
101
 
73
102
  let scrollButtonSyncScheduled = false;
74
103
 
104
+ // 交互开关只取决于配置模式:原实现按 isLazyProxyTui(toolMouseTui) 分两分支,
105
+ // 两分支恒真(0.84+ 惰性 Proxy 下判定不再影响开关),折叠为单条件。
75
106
  export function toolMouseInteractionActive(): boolean {
76
- if (config.mode === "off") return false;
77
- if (isLazyProxyTui(getToolMouseTui())) return true;
78
- return true;
107
+ return config.mode !== "off";
79
108
  }
80
109
 
81
110
  /** 惰性 Proxy 官方 fullscreen(TuiAltScreen)判定。 */
@@ -83,13 +112,12 @@ export function fullscreenLazyTui(tui: any): boolean {
83
112
  return isLazyProxyTui(tui) && tui.mode === "fullscreen";
84
113
  }
85
114
 
86
- const OFFICIAL_SCROLL_TO_END_KEY = Symbol.for("pi.ccstyle.official-scroll-to-end");
87
-
88
115
  /** 关掉 pi 0.85 Jump to latest overlay,避免和本仓库 dock 按钮叠两层。 */
89
116
  export function disableOfficialScrollToEnd(tui: any): void {
90
117
  if (!tui) return;
91
118
  const current = tui.scrollToEndIndicator;
92
119
  if (typeof current !== "function") return;
120
+ // 原函数放 object 里,避免惰性 Proxy 对 function 属性再包一层。
93
121
  if (!tui[OFFICIAL_SCROLL_TO_END_KEY]) {
94
122
  tui[OFFICIAL_SCROLL_TO_END_KEY] = { original: current };
95
123
  }
@@ -210,12 +238,19 @@ export function updateScrollButtonFromInput(tui: any, data: string): void {
210
238
  if (matchesKey(data, "enter") || matchesKey(data, "return")) hideScrollButton(tui);
211
239
  }
212
240
 
241
+ /** 无新内容时提示原文案;有新内容时换成累计条数。 */
242
+ function scrollButtonText(): string {
243
+ const count = getScrollButtonNewCount();
244
+ const shortcut = formatShortcut(SCROLL_BOTTOM_SHORTCUT);
245
+ if (count <= 0) return `Back to bottom · ${shortcut}`;
246
+ return `${count} new message${count === 1 ? "" : "s"} · ${shortcut}`;
247
+ }
248
+
213
249
  export function renderScrollButton(width: number, theme: any): string[] {
214
250
  if (!getScrollButtonVisible() || !fullscreenLazyTui(getToolMouseTui())) return [];
215
- const shortcut = formatShortcut(SCROLL_BOTTOM_SHORTCUT);
216
251
  const label = theme.fg(
217
252
  getScrollButtonHovered() ? "text" : "accent",
218
- `[ ↓ Back to bottom · ${shortcut} ]`,
253
+ `[ ↓ ${scrollButtonText()} ]`,
219
254
  );
220
255
  const leftPad = Math.max(0, Math.floor((width - visibleWidth(label)) / 2));
221
256
  return [`${" ".repeat(leftPad)}${truncateToWidth(label, width, "…")}`];
@@ -0,0 +1,303 @@
1
+ /**
2
+ * codemode 的结果渲染:折叠态把子调用摊成工具组那样的树,最后一行用 └ 收尾。
3
+ *
4
+ * 数据来自 `result.details.calls`(CodemodeNestedCall[],partial 更新里也有),所以运行中就能
5
+ * 看到子调用进度。两个坑:
6
+ *
7
+ * - 子调用不会单独成行:pi 会跳过带 `parentToolCallId` 的 tool_execution_start,进度只能在这里显示。
8
+ * - 输出以 "Script completed\nWall time …\nOutput:\n" 开头(pi 原生也切掉),行数统计与展开正文都得去掉它,
9
+ * 否则折叠摘要会多算 3 行。
10
+ */
11
+ import { truncateToWidth, visibleWidth } from "@earendil-works/pi-tui";
12
+ import { stripAnsi } from "../../utils/ansi-text.ts";
13
+ import { toolLoadingIcon } from "../../utils/tool-loading-icon.ts";
14
+ import { sanitizeToolResultText } from "../../utils/tool-result-sanitize.ts";
15
+ import { mcpToolTitle } from "./mcp-title.ts";
16
+ import {
17
+ type ToolCallSummary,
18
+ humanizeToolLabel,
19
+ renderToolSummary,
20
+ toolCallSummary,
21
+ } from "./names.ts";
22
+ import { showMoreHintText } from "./show-more-hint.ts";
23
+ import { headTruncateToWidth, toolViewportWidth } from "./result.ts";
24
+
25
+ export const CODEMODE_TOOL_NAME = "codemode";
26
+
27
+ /** 折叠态最多列几条子调用(与 pi 原生一致,更早的折叠成一行)。 */
28
+ const COLLAPSED_CALL_LIMIT = 8;
29
+ /** 折叠态正文缩进,与 ` ↳ …` 对齐。 */
30
+ const INDENT = " ";
31
+
32
+ /** 脚本结果头;只有整块正文恰好等于它时才算头。 */
33
+ const SCRIPT_HEADER = /^Script (completed|failed)\nWall time [\d.]+ seconds\nOutput:\n$/;
34
+
35
+ export type CodemodeNestedCall = {
36
+ name?: unknown;
37
+ /** 紧凑 JSON;过长时 pi 会截断,截断后 JSON.parse 会失败。 */
38
+ args?: unknown;
39
+ status?: unknown;
40
+ durationMs?: unknown;
41
+ error?: unknown;
42
+ cost?: unknown;
43
+ };
44
+
45
+ export function codemodeCalls(result: any): CodemodeNestedCall[] {
46
+ const calls = result?.details?.calls;
47
+ return Array.isArray(calls) ? calls : [];
48
+ }
49
+
50
+ /** 去掉脚本头之后的输出正文(已清理终端转义)。 */
51
+ export function codemodeOutputText(result: any): string {
52
+ const content = Array.isArray(result?.content) ? result.content : [];
53
+ const blocks = content
54
+ .filter((item: any) => item?.type === "text")
55
+ .map((item: any) => String(item?.text ?? ""));
56
+ if (blocks.length > 0 && SCRIPT_HEADER.test(blocks[0]!)) blocks.shift();
57
+ return sanitizeToolResultText(blocks.join("\n"), 16_384).trim();
58
+ }
59
+
60
+ export function codemodeOutputLineCount(result: any): number {
61
+ const text = codemodeOutputText(result).replace(/\n+$/, "");
62
+ return text ? text.split("\n").length : 0;
63
+ }
64
+
65
+ /** 汇总行片段(按重要度先后排列,渲染时从尾部丢以适配宽度)。 */
66
+ export function codemodeSummaryParts(
67
+ calls: readonly CodemodeNestedCall[],
68
+ outputLines: number,
69
+ running: boolean,
70
+ ): string[] {
71
+ const total = calls.length;
72
+ const failed = calls.filter((call) => call?.status === "error").length;
73
+ const runningCount = calls.filter((call) => !call?.status || call?.status === "running").length;
74
+ const parts: string[] = [];
75
+ if (running) {
76
+ if (runningCount)
77
+ parts.push(`${runningCount} ${runningCount === 1 ? "call" : "calls"} running`);
78
+ const done = total - runningCount;
79
+ if (done) parts.push(`${done} done`);
80
+ if (failed) parts.push(`${failed} failed`);
81
+ return parts.length ? parts : ["running…"];
82
+ }
83
+ if (total) parts.push(`${total} ${total === 1 ? "call" : "calls"}`);
84
+ if (failed) parts.push(`${failed} failed`);
85
+ if (outputLines) parts.push(`${outputLines} ${outputLines === 1 ? "line" : "lines"} output`);
86
+ return parts.length ? parts : ["Done"];
87
+ }
88
+
89
+ /** 宽度不够时从尾部丢片段(先丢输出行数,再丢条数),不断词。 */
90
+ function fitSummaryParts(parts: readonly string[], width: number): string {
91
+ const kept = [...parts];
92
+ while (kept.length > 1 && visibleWidth(kept.join(" · ")) > width) kept.pop();
93
+ const text = kept.join(" · ");
94
+ return visibleWidth(text) <= width ? text : headTruncateToWidth(text, width);
95
+ }
96
+
97
+ function formatDuration(ms: number): string {
98
+ return ms < 1000 ? `${Math.round(ms)}ms` : `${(ms / 1000).toFixed(1)}s`;
99
+ }
100
+
101
+ /** 与 pi 原生一致:不到 1 分显示两位有效数字。 */
102
+ function formatCost(cost: number): string {
103
+ return `$${cost >= 0.01 ? cost.toFixed(2) : cost.toPrecision(2)}`;
104
+ }
105
+
106
+ /** 单次子调用的耗时/费用(纯文本,着色由调用方决定)。 */
107
+ function callMeta(call: CodemodeNestedCall): string[] {
108
+ const out: string[] = [];
109
+ const duration = call?.durationMs;
110
+ if (typeof duration === "number" && Number.isFinite(duration) && duration >= 0) {
111
+ out.push(formatDuration(duration));
112
+ }
113
+ const cost = call?.cost;
114
+ if (typeof cost === "number" && Number.isFinite(cost) && cost > 0) out.push(formatCost(cost));
115
+ return out;
116
+ }
117
+
118
+ /** 截断的紧凑 JSON 里能恢复出的对象;complete 标记是否原本就完整。 */
119
+ type ParsedCallArgs = { args: Record<string, unknown>; complete: boolean };
120
+
121
+ /** 截断串尾部补闭合符号的候选:先试收字符串,再收数组与对象。 */
122
+ const REPAIR_CLOSERS = ['"}', '"}]}', '"}}', "}", "]}"];
123
+
124
+ /**
125
+ * 子调用参数:先直接解析;pi 从尾部截断过(超 200 字符)的串再补救一次——
126
+ * 逐字回退补上缺少的闭合符号,取最长能解析出的对象。截断保留的是开头字段,
127
+ * path/command/pattern 这类先出现的取得到;被切掉的尾部值本就无从恢复。
128
+ */
129
+ function parseCallArgs(raw: string): ParsedCallArgs | undefined {
130
+ try {
131
+ const parsed = JSON.parse(raw);
132
+ if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
133
+ return { args: parsed, complete: true };
134
+ }
135
+ return undefined;
136
+ } catch {
137
+ // 截断串:走补救
138
+ }
139
+ const body = raw.endsWith("...") ? raw.slice(0, -3) : raw;
140
+ if (!body.startsWith("{")) return undefined;
141
+ for (let end = body.length; end > 0; end--) {
142
+ for (const closer of REPAIR_CLOSERS) {
143
+ try {
144
+ const parsed = JSON.parse(body.slice(0, end) + closer);
145
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) continue;
146
+ // 空对象等于没恢复出字段,再短也只会更空
147
+ if (Object.keys(parsed).length === 0) return undefined;
148
+ return { args: parsed, complete: false };
149
+ } catch {
150
+ // 试下一个闭合符号 / 下一个长度
151
+ }
152
+ }
153
+ }
154
+ return undefined;
155
+ }
156
+
157
+ /** 子调用参数:能解析就复用字段链摘要,认不出(截断后也不成形)就贴原文。 */
158
+ function callSummary(call: CodemodeNestedCall): ToolCallSummary {
159
+ const name = String(call?.name ?? "tool");
160
+ const title = mcpToolTitle({ toolName: name }) ?? humanizeToolLabel(name);
161
+ const raw = typeof call?.args === "string" ? call.args : "";
162
+ if (!raw) return { main: title, detail: "" };
163
+ const parsed = parseCallArgs(raw);
164
+ if (parsed) {
165
+ const summary = toolCallSummary(name, parsed.args, { title, variant: "default" });
166
+ // 截断串只恢复出部分字段:字段链认出来了才用,认不出仍旧贴原文,
167
+ // 免得把不完整的 JSON 当成完整入参摊开。
168
+ if (parsed.complete || summary.payload === undefined) return summary;
169
+ }
170
+ return { main: title, detail: "", payload: raw };
171
+ }
172
+
173
+ function statusIcon(status: unknown, theme: any): string {
174
+ switch (status) {
175
+ case "ok":
176
+ return theme.fg("success", "✓");
177
+ case "error":
178
+ return theme.fg("error", "✗");
179
+ case "cancelled":
180
+ return theme.fg("muted", "⊘");
181
+ default:
182
+ // 运行中:帧在 render() 内取,动画定时器只负责 requestRender
183
+ return theme.fg("accent", toolLoadingIcon());
184
+ }
185
+ }
186
+
187
+ function callRow(call: CodemodeNestedCall, theme: any, rowWidth: number): string {
188
+ const fg = theme.fg.bind(theme);
189
+ const prefix = `${INDENT}${fg("dim", "├")} ${statusIcon(call?.status, theme)} `;
190
+ // detail(read 的 offset/limit 等)与工具组行一样接在标题后
191
+ const summary = callSummary(call);
192
+ const detail = fg("dim", summary.detail);
193
+ const suffix = callMeta(call)
194
+ .map((text) => ` ${fg("dim", text)}`)
195
+ .join("");
196
+ const mainWidth = Math.max(
197
+ 0,
198
+ rowWidth - visibleWidth(prefix) - visibleWidth(detail) - visibleWidth(suffix),
199
+ );
200
+ const row = `${prefix}${renderToolSummary(summary, mainWidth, fg)}${detail}${suffix}`;
201
+ return truncateToWidth(row, rowWidth, "");
202
+ }
203
+
204
+ /**
205
+ * 折叠态(含运行中的 partial 更新)的行:子调用全用 ├,最后一行用 └ 收汇总,
206
+ * 与工具组的树一致。
207
+ */
208
+ export function codemodeCollapsedLines(options: {
209
+ result: any;
210
+ theme: any;
211
+ running: boolean;
212
+ isError: boolean;
213
+ width: number;
214
+ /** 鼠标悬停整卡时展开提示用 text 色,与其它折叠卡一致。 */
215
+ hovered?: boolean;
216
+ }): string[] {
217
+ const { result, theme, running, isError } = options;
218
+ const fg = theme.fg.bind(theme);
219
+ const calls = codemodeCalls(result);
220
+ const rowWidth = toolViewportWidth(options.width);
221
+ const shown = calls.slice(-COLLAPSED_CALL_LIMIT);
222
+ const lines: string[] = [];
223
+ if (shown.length < calls.length) {
224
+ const hidden = calls.length - shown.length;
225
+ lines.push(
226
+ truncateToWidth(
227
+ `${INDENT}${fg("dim", "├")} ${fg("dim", `… ${hidden} earlier ${hidden === 1 ? "call" : "calls"}`)}`,
228
+ rowWidth,
229
+ "",
230
+ ),
231
+ );
232
+ }
233
+ for (const call of shown) lines.push(callRow(call, theme, rowWidth));
234
+
235
+ const summary = codemodeSummaryParts(calls, codemodeOutputLineCount(result), running);
236
+ // 没有子调用时不画衔接符,避免孤零零一个 └
237
+ const prefix = shown.length > 0 ? `${INDENT}${fg("dim", "└")} ` : INDENT;
238
+ const hint = running ? "" : ` ${fg(options.hovered ? "text" : "dim", `· ${showMoreHintText()}`)}`;
239
+ const bodyWidth = Math.max(1, rowWidth - visibleWidth(prefix) - visibleWidth(hint));
240
+ const body = fg(isError ? "error" : "muted", fitSummaryParts(summary, bodyWidth));
241
+ lines.push(truncateToWidth(`${prefix}${body}${hint}`, rowWidth, ""));
242
+ return lines;
243
+ }
244
+
245
+ /** 展开态正文:全部子调用(含错误文本)+ 去掉脚本头的输出 + 全量输出路径。 */
246
+ export function codemodeExpandedBody(result: any): string {
247
+ const parts: string[] = [];
248
+ const calls = codemodeCalls(result);
249
+ if (calls.length > 0) {
250
+ parts.push(
251
+ calls
252
+ .map((call) => {
253
+ const name = String(call?.name ?? "tool");
254
+ const raw = typeof call?.args === "string" ? call.args : "";
255
+ const meta = callMeta(call);
256
+ const head = [name, raw, ...meta].filter(Boolean).join(" ");
257
+ const error =
258
+ typeof call?.error === "string" && call.error
259
+ ? `\n ${call.error.split("\n").join("\n ")}`
260
+ : "";
261
+ return `${head}${error}`;
262
+ })
263
+ .join("\n"),
264
+ );
265
+ }
266
+ const output = codemodeOutputText(result);
267
+ if (output) parts.push(output);
268
+ const full = result?.details?.fullOutputPath;
269
+ if (typeof full === "string" && full.trim()) parts.push(`Full output: ${full.trim()}`);
270
+ return parts.join("\n\n");
271
+ }
272
+
273
+ /**
274
+ * 折叠态结果组件。只有汇总行是展开入口,与 diff 卡一致;行本身很便宜,
275
+ * 不自己缓存(settled 卡另有整行 paint 缓存,运行中本就按帧重算)。hover 状态在
276
+ * render() 内取,才能跟鼠标 motion 的 requestRender 同步。
277
+ */
278
+ export function createCodemodeResultComponent(options: {
279
+ result: any;
280
+ theme: any;
281
+ running: boolean;
282
+ isError: boolean;
283
+ /** 折叠态 hover 查询,与 diff 卡同一套(mouse/hover)。 */
284
+ isHovered?: () => boolean;
285
+ }): any {
286
+ const { result, theme, running, isError } = options;
287
+ return {
288
+ render(width: number): string[] {
289
+ return codemodeCollapsedLines({
290
+ result,
291
+ theme,
292
+ running,
293
+ isError,
294
+ width,
295
+ hovered: options.isHovered?.() ?? false,
296
+ });
297
+ },
298
+ invalidate(): void {},
299
+ isCollapsedHintLine(plainLine: string): boolean {
300
+ return !running && /(click to show more|to show more)\s*$/.test(stripAnsi(plainLine));
301
+ },
302
+ };
303
+ }