@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
@@ -7,16 +7,19 @@
7
7
  import { ToolExecutionComponent } from "@earendil-works/pi-coding-agent";
8
8
  import { Text, truncateToWidth, visibleWidth } from "@earendil-works/pi-tui";
9
9
  import { config, getToolDisplayConfig, type CompactStyleMode } from "../config/config.ts";
10
- import { isToolCallHovered } from "./mouse/interaction.ts";
10
+ import {
11
+ COMPONENT_TOOL_RENDER_MODE,
12
+ GLOBAL_TOOL_RENDER_PATCH,
13
+ patchRegistry,
14
+ TOOL_EXPANDED_BACKGROUND_PATCH,
15
+ } from "../utils/patch-keys.ts";
16
+ import { isToolCallHovered } from "./mouse/hover.ts";
11
17
  import {
12
18
  countLines,
13
- fitToolCallSummary,
14
19
  hasExpandableDetail,
15
20
  insetComponent,
16
21
  isToolExpanded,
17
- oneLine,
18
22
  outputLineCount,
19
- pathSummary,
20
23
  pendingIcon,
21
24
  renderCollapsedToolResultToWidth,
22
25
  renderExpandedToolResult,
@@ -27,27 +30,29 @@ import {
27
30
  textFromResult,
28
31
  toolIconColor,
29
32
  toolViewportWidth,
30
- type ToolCallSummary,
31
33
  } from "./tool/result.ts";
32
- import { showMoreHintText } from "./show-more-hint.ts";
34
+ import { oneLine } from "../utils/format.ts";
35
+ import { showMoreHintText } from "./tool/show-more-hint.ts";
36
+ import {
37
+ CODEMODE_TOOL_NAME,
38
+ codemodeExpandedBody,
39
+ createCodemodeResultComponent,
40
+ } from "./tool/codemode.ts";
41
+ import { countWriteDiffStats } from "./tool/diff/diff-renderer.ts";
33
42
  import { renderRichToolResult, type WriteExecutionMetadataStore } from "./tool/diff/index.ts";
34
- import { getMessageDisplayTheme } from "./message-display.ts";
43
+ import { getMessageDisplayTheme } from "./tool/message-display.ts";
44
+ import { mcpToolTitle } from "./tool/mcp-title.ts";
45
+ import {
46
+ fitToolCallSummary,
47
+ humanizeToolLabel,
48
+ renderToolSummary,
49
+ toolCallSummary,
50
+ } from "./tool/names.ts";
35
51
 
36
52
  // 成功勾:亮绿 truecolor(与 message-display 一致)
37
53
  const BRIGHT_GREEN = "\x1b[38;2;80;220;100m";
38
54
  const ANSI_FG_RESET = "\x1b[39m";
39
55
 
40
- const GLOBAL_TOOL_RENDER_PATCH = Symbol.for("pi.ccstyle.global-tool-render-patch");
41
- const COMPONENT_TOOL_RENDER_MODE = Symbol.for("pi.ccstyle.component-tool-render-mode");
42
- const COMPONENT_TOOL_SELF_SHELL_MODE = Symbol.for("pi.ccstyle.component-tool-self-shell-mode");
43
- const TOOL_EXPANDED_BACKGROUND_PATCH = Symbol.for("pi.ccstyle.tool-expanded-background-patch");
44
-
45
- const AGENT_FAMILY_TOOL_NAMES = new Set([
46
- "Agent",
47
- "Agents",
48
- "get_subagent_result",
49
- "steer_subagent",
50
- ]);
51
56
  // pi-subagents 等扩展为 Agent 提供专用渲染器,ccstyle 必须保留。
52
57
  const DEDICATED_RENDERER_TOOLS = new Set(["Agent"]);
53
58
 
@@ -64,23 +69,32 @@ type ToolRenderMethods = {
64
69
  getResultRenderer: (...args: any[]) => any;
65
70
  };
66
71
 
72
+ type ToolPaintHit = {
73
+ width: number;
74
+ expanded: boolean;
75
+ isPartial: boolean;
76
+ result: unknown;
77
+ args: unknown;
78
+ callHover: boolean;
79
+ ioHover: string | null;
80
+ lines: string[];
81
+ };
82
+
67
83
  type GlobalToolRenderPatch = {
68
84
  version: 2;
69
85
  prototype: any;
70
- owner: object;
71
86
  active: boolean;
72
- enabled: () => boolean;
73
87
  mode: () => CompactStyleMode;
74
88
  wrap: (tool: any) => any;
75
89
  byDefinition: WeakMap<object, any>;
76
90
  byName: Map<string, any>;
77
91
  downstream: ToolRenderMethods;
78
92
  installed: ToolRenderMethods;
79
- // 兼容旧扩展读取 Symbol 上的 legacy 字段。
80
- originalHasRendererDefinition: ToolRenderMethods["hasRendererDefinition"];
81
- originalGetRenderShell: ToolRenderMethods["getRenderShell"];
82
- originalGetCallRenderer: ToolRenderMethods["getCallRenderer"];
83
- originalGetResultRenderer: ToolRenderMethods["getResultRenderer"];
93
+ originalRender?: (width: number) => string[];
94
+ originalInvalidate?: () => void;
95
+ renderPaint?: (width: number) => string[];
96
+ invalidatePaint?: () => void;
97
+ paintCache?: WeakMap<object, ToolPaintHit>;
84
98
  };
85
99
 
86
100
  type ToolExpandedBackgroundPatch = {
@@ -91,6 +105,8 @@ type ToolExpandedBackgroundPatch = {
91
105
  dispose: () => void;
92
106
  };
93
107
 
108
+ /** rich diff 的两个入口(本处与 compact 的 paintCompactEditWrite)都靠 renderRichToolResult
109
+ * 返回 undefined 让位,这里只判断模式与工具名,避免多一个可能与让位不一致的 gate。 */
94
110
  export function shouldRenderRichDiff(
95
111
  mode: CompactStyleMode,
96
112
  toolName: string,
@@ -99,25 +115,6 @@ export function shouldRenderRichDiff(
99
115
  return mode === "on" && !isError && (toolName === "edit" || toolName === "write");
100
116
  }
101
117
 
102
- export function isMcpToolDefinition(definition: any, toolName: string): boolean {
103
- const label = typeof definition?.label === "string" ? definition.label.trim() : "";
104
- if (/^MCP(?::|$)/i.test(label)) return true;
105
- if (toolName === "mcp" || /^mcp[_:-]|[_:-]mcp[_:-]/i.test(toolName)) return true;
106
- if (label) return false;
107
- const description = typeof definition?.description === "string" ? definition.description : "";
108
- return /\bModel Context Protocol\b/i.test(description);
109
- }
110
-
111
- export function humanizeMcpToolName(toolName: string): string {
112
- const words = toolName
113
- .replace(/^mcp(?:[_:-]+)+/i, "")
114
- .split(/[_:-]+/)
115
- .filter(Boolean);
116
- return words.length
117
- ? words.map((word) => word[0]!.toUpperCase() + word.slice(1)).join(" ")
118
- : "MCP";
119
- }
120
-
121
118
  /** 排除名单内且自带 renderer 的工具保留原渲染。 */
122
119
  export function preservesOriginalRenderer(
123
120
  extensionDefinition: any,
@@ -143,97 +140,6 @@ function renderDefault(tool: any, slot: "renderCall" | "renderResult", args: any
143
140
  return new Text(fallback, 0, 0);
144
141
  }
145
142
 
146
- function humanizeToolLabel(label: string): string {
147
- return label
148
- .replace(/([a-z0-9])([A-Z])/g, "$1 $2")
149
- .replace(/[_-]+/g, " ")
150
- .replace(/\b\w/g, (char) => char.toUpperCase());
151
- }
152
-
153
- function singleToolCallSummary(
154
- toolName: string,
155
- label: string,
156
- args: any,
157
- cwd?: string,
158
- ): ToolCallSummary {
159
- const title = label === toolName ? humanizeToolLabel(label) : label;
160
- if (!args || typeof args !== "object") return { main: title, detail: "" };
161
- const name = toolName.toLowerCase();
162
- const value = (fallback: string, ...keys: string[]) => {
163
- const found = keys.map((key) => args[key]).find((item) => typeof item === "string" && item);
164
- return `${title} ${oneLine(found || fallback)}`;
165
- };
166
- if (AGENT_FAMILY_TOOL_NAMES.has(toolName) && args.agent_id) {
167
- return { main: `${title} ${oneLine(args.agent_id)}`, detail: "" };
168
- }
169
- // Agents 走 ccstyle wrapper;Agent 保留专用渲染器。
170
- if (name === "agents") {
171
- return {
172
- main: value("launch agents", "description", "prompt"),
173
- detail: "",
174
- };
175
- }
176
- if (name === "skill") return { main: value("run skill", "name"), detail: "" };
177
- if (name === "enterplanmode" || name === "enter_plan_mode") {
178
- return { main: `${title} enable read-only planning`, detail: "" };
179
- }
180
- if (name === "exitplanmode" || name === "exit_plan_mode") {
181
- return { main: `${title} present plan`, detail: "" };
182
- }
183
- if (name === "taskcreate") return { main: value("create task", "subject"), detail: "" };
184
- if (name === "tasklist") return { main: `${title} task list`, detail: "" };
185
- if (name === "taskget" || name === "taskupdate") {
186
- return { main: value("task", "taskId", "task_id"), detail: "" };
187
- }
188
- if (name === "taskoutput" || name === "taskstop") {
189
- return { main: value("background task", "task_id", "taskId"), detail: "" };
190
- }
191
- if (name === "taskexecute") {
192
- const ids = Array.isArray(args.task_ids)
193
- ? args.task_ids
194
- : Array.isArray(args.taskIds)
195
- ? args.taskIds
196
- : [];
197
- const summary = ids.length
198
- ? `${ids[0]}${ids.length > 1 ? ` (+${ids.length - 1} tasks)` : ""}`
199
- : "start tasks";
200
- return { main: `${title} ${summary}`, detail: "" };
201
- }
202
- if (toolName === "read") {
203
- const details = [
204
- args.offset !== undefined ? `offset=${args.offset}` : "",
205
- args.limit !== undefined ? `limit=${args.limit}` : "",
206
- ].filter(Boolean);
207
- const detail = details.length ? ` (${details.join(", ")})` : "";
208
- if (typeof args.path === "string" && args.path) {
209
- return pathSummary(title, args.path, cwd, detail);
210
- }
211
- return { main: title, detail };
212
- }
213
- const preferredPath = args.path ?? args.file_path;
214
- if (typeof preferredPath === "string" && preferredPath) {
215
- return pathSummary(title, preferredPath, cwd);
216
- }
217
- const preferred =
218
- args.command ??
219
- args.query ??
220
- args.question ??
221
- args.pattern ??
222
- args.url ??
223
- args.name ??
224
- args.tool_use_id ??
225
- args.toolCallId ??
226
- args.id ??
227
- args.message;
228
- return {
229
- main:
230
- preferred !== undefined && preferred !== null && typeof preferred !== "object"
231
- ? `${title} ${oneLine(preferred)}`
232
- : title,
233
- detail: "",
234
- };
235
- }
236
-
237
143
  type ParsedTask = { id: string; status: string; subject: string };
238
144
 
239
145
  function parseTaskList(text: string): ParsedTask[] {
@@ -256,7 +162,7 @@ function taskListSummary(tasks: ParsedTask[]): string {
256
162
  counts.completed ? `${counts.completed} completed` : "",
257
163
  ]
258
164
  .filter(Boolean)
259
- .join(" • ");
165
+ .join(" · ");
260
166
  }
261
167
 
262
168
  function renderExpandedTaskResult(
@@ -277,11 +183,16 @@ function renderExpandedTaskResult(
277
183
  : task.status === "in_progress"
278
184
  ? "warning"
279
185
  : "muted";
280
- return ` ${theme.fg("accent", `#${task.id}`)} ${theme.fg(color, task.status)} ${theme.fg("dim", task.subject)}`;
186
+ return `${theme.fg("accent", `#${task.id}`)} ${theme.fg(color, task.status)} ${theme.fg("dim", task.subject)}`;
281
187
  });
282
188
  if (tasks.length > rows.length)
283
- rows.push(theme.fg("muted", ` … ${tasks.length - rows.length} more tasks`));
284
- return new Text(` ↳ ${theme.fg("muted", taskListSummary(tasks))}\n${rows.join("\n")}`, 0, 0);
189
+ rows.push(theme.fg("muted", `… ${tasks.length - rows.length} more tasks`));
190
+ // 贴左:外层展开卡片 Box(1,1) 提供 1 格 padding
191
+ return new Text(
192
+ `↳ ${theme.fg("muted", taskListSummary(tasks))}\n${rows.map((r) => ` ${r}`).join("\n")}`,
193
+ 0,
194
+ 0,
195
+ );
285
196
  }
286
197
  const line = text.trim();
287
198
  if (!line || line.includes("\n")) return undefined;
@@ -299,7 +210,7 @@ function renderExpandedTaskResult(
299
210
  } else if (toolName === "TaskStop") {
300
211
  formatted = `${theme.fg("success", "Stopped")} ${theme.fg("muted", line)}`;
301
212
  }
302
- return formatted ? new Text(` ↳ ${formatted}`, 0, 0) : undefined;
213
+ return formatted ? new Text(`↳ ${formatted}`, 0, 0) : undefined;
303
214
  }
304
215
 
305
216
  /** 用 ccstyle call/result 包装任意工具定义。 */
@@ -308,15 +219,16 @@ function createCcstyleTool(
308
219
  writeExecutionMetadata: WriteExecutionMetadataStore,
309
220
  ): any {
310
221
  const toolName = originalTool.name;
311
- const label = isMcpToolDefinition(originalTool, toolName)
312
- ? humanizeMcpToolName(toolName)
313
- : originalTool.label || toolName;
222
+ const label = originalTool.label || toolName;
223
+ const defaultTitle = label === toolName ? humanizeToolLabel(label) : label;
224
+ // MCP 工具直接用 adapter 暴露的真实工具名,不做人性化
225
+ const title = mcpToolTitle({ toolName, definition: originalTool }) ?? defaultTitle;
314
226
 
315
227
  return {
316
228
  ...originalTool,
317
229
  renderShell: "self",
318
230
  renderCall(args: any, theme: any, context: any) {
319
- if (config.mode !== "on") {
231
+ if (config.mode === "off") {
320
232
  return renderDefault(originalTool, "renderCall", [args, theme, context], String(toolName));
321
233
  }
322
234
 
@@ -324,31 +236,71 @@ function createCcstyleTool(
324
236
  const isPending =
325
237
  visualState === "pending" ||
326
238
  (!visualState && (context?.isPartial || context?.executionStarted));
327
- if (isPending && context?.executionStarted) scheduleAnimation(context);
328
- const rawIcon = isPending ? pendingIcon(toolName) : settledIcon(toolName, visualState);
329
- const icon =
239
+ const animating = isPending && Boolean(context?.executionStarted);
240
+ if (animating) scheduleAnimation(context, { light: true });
241
+ const settledRawIcon = isPending ? "" : settledIcon(toolName, visualState);
242
+ const settledIconStyled =
330
243
  visualState === "success"
331
- ? `${BRIGHT_GREEN}${rawIcon}${ANSI_FG_RESET}`
332
- : theme.fg(toolIconColor(context), rawIcon);
333
- const summary = singleToolCallSummary(toolName, label, args, context?.cwd);
244
+ ? `${BRIGHT_GREEN}${settledRawIcon}${ANSI_FG_RESET}`
245
+ : theme.fg(toolIconColor(context), settledRawIcon);
246
+ // 逐帧 spinner:帧在 render() 内取,动画定时器只需 requestRender,
247
+ // 不再每次 tick 走 updateDisplay 把整张卡重建一遍。
248
+ const pendingIconStyled = () => theme.fg(toolIconColor(context), pendingIcon(toolName));
249
+ const summary = toolCallSummary(toolName, args, {
250
+ title,
251
+ variant: "default",
252
+ cwd: context?.cwd,
253
+ });
254
+ let writeStatsText = "";
255
+ let writeStatsStyled = "";
256
+ if (toolName === "write" && visualState === "success") {
257
+ const meta = writeExecutionMetadata.get(context?.toolCallId);
258
+ const stats = countWriteDiffStats(
259
+ typeof args?.content === "string" ? args.content : undefined,
260
+ meta?.previousContent,
261
+ meta?.fileExistedBeforeWrite,
262
+ );
263
+ if (stats) {
264
+ writeStatsText = ` (+${stats.added} -${stats.removed})`;
265
+ writeStatsStyled = ` ${theme.fg("dim", "(")}${theme.fg("success", `+${stats.added}`)} ${theme.fg("error", `-${stats.removed}`)}${theme.fg("dim", ")")}`;
266
+ }
267
+ }
268
+ const extraText = writeStatsText || summary.detail;
269
+ const extraStyled = writeStatsStyled || theme.fg("dim", summary.detail);
334
270
  let cachedWidth: number | undefined;
335
271
  let cachedLine: string | undefined;
272
+ let cachedIcon: string | undefined;
273
+ const expanded = Boolean(context?.expanded);
336
274
  return {
337
275
  render(width: number) {
338
- if (cachedLine !== undefined && cachedWidth === width) return [cachedLine];
276
+ // 轻量 tick 只会 requestRender,靠这里续期,动画才能自维持。
277
+ if (animating) scheduleAnimation(context, { light: true });
278
+ const icon = isPending ? pendingIconStyled() : settledIconStyled;
279
+ if (cachedLine !== undefined && cachedWidth === width && cachedIcon === icon) {
280
+ return [cachedLine];
281
+ }
339
282
  const viewportWidth = toolViewportWidth(width);
340
- const callWidth = Math.max(0, viewportWidth - visibleWidth(icon) - 2);
341
- const mainWidth = Math.max(0, callWidth - visibleWidth(summary.detail));
283
+ // 展开态贴左(外层 Box 已 pad 1);折叠 self-shell 保留 1 格前导空格
284
+ const lead = expanded ? "" : " ";
285
+ const callWidth = Math.max(
286
+ 0,
287
+ viewportWidth - visibleWidth(icon) - 1 - (expanded ? 0 : 1),
288
+ );
289
+ const mainWidth = Math.max(0, callWidth - visibleWidth(extraText));
342
290
  cachedWidth = width;
343
- const line = ` ${icon} ${theme.fg("toolTitle", fitToolCallSummary(summary, mainWidth))}${theme.fg("dim", summary.detail)}`;
344
- cachedLine = truncateToWidth(line, viewportWidth, "");
345
- return [cachedLine];
291
+ cachedIcon = icon;
292
+ // 路径按最终可用宽度中间截断,避免整行二次截断隐藏文件名。
293
+ cachedLine = `${lead}${icon} ${renderToolSummary(summary, mainWidth, theme.fg.bind(theme))}${extraStyled}`;
294
+ return [truncateToWidth(cachedLine, viewportWidth, "")];
295
+ },
296
+ invalidate() {
297
+ cachedLine = undefined;
298
+ cachedIcon = undefined;
346
299
  },
347
- invalidate() {},
348
300
  };
349
301
  },
350
302
  renderResult(result: any, options: any, theme: any, context: any) {
351
- if (config.mode !== "on") {
303
+ if (config.mode === "off") {
352
304
  return renderDefault(
353
305
  originalTool,
354
306
  "renderResult",
@@ -357,13 +309,40 @@ function createCcstyleTool(
357
309
  );
358
310
  }
359
311
 
312
+ const expanded = isToolExpanded(options, context);
313
+ const isError = Boolean(options?.isError || context?.isError);
314
+ // codemode:折叠态自己画子调用树,展开态给全部子调用与去掉脚本头的输出
315
+ if (toolName === CODEMODE_TOOL_NAME) {
316
+ if (!options?.isPartial) setToolVisualState(context, isError ? "error" : "success");
317
+ if (expanded) {
318
+ return renderExpandedToolResult(
319
+ codemodeExpandedBody(result),
320
+ theme,
321
+ isError,
322
+ context?.lastComponent,
323
+ context?.args,
324
+ context,
325
+ true,
326
+ );
327
+ }
328
+ // 折叠态不再复用展开视图,免得 hover/鼠标命中指向已隐藏的组件
329
+ if (context?.state) context.state.ccstyleIoView = undefined;
330
+ const toolCallId = context?.toolCallId;
331
+ return createCodemodeResultComponent({
332
+ result,
333
+ theme,
334
+ running: Boolean(options?.isPartial),
335
+ isError,
336
+ isHovered: () => isToolCallHovered(toolCallId),
337
+ });
338
+ }
360
339
  if (options?.isPartial) {
361
- return new Text(theme.fg("muted", " ↳ Pending…"), 0, 0);
340
+ // 展开态贴左(Box 提供 1 格 pad);折叠态保持 3 格对齐标题
341
+ const pending = expanded ? "↳ Pending…" : " ↳ Pending…";
342
+ return new Text(theme.fg("muted", pending), 0, 0);
362
343
  }
363
344
 
364
- const isError = options?.isError || context?.isError;
365
345
  setToolVisualState(context, isError ? "error" : "success");
366
- const expanded = isToolExpanded(options, context);
367
346
  const toolCallId = context?.toolCallId;
368
347
  if (shouldRenderRichDiff(config.mode, toolName, Boolean(isError))) {
369
348
  // getter 保证 Diff indicator / wrap / limits 下次绘制即更新
@@ -381,7 +360,8 @@ function createCcstyleTool(
381
360
  writeExecutionMetadata,
382
361
  getToolDisplayConfig,
383
362
  );
384
- if (richResult) return insetComponent(richResult);
363
+ // 展开态由 Box(1,1) 提供内边距;折叠态 inset 一级缩进
364
+ if (richResult) return expanded ? richResult : insetComponent(richResult);
385
365
  }
386
366
 
387
367
  const text = textFromResult(result, expanded);
@@ -398,14 +378,15 @@ function createCcstyleTool(
398
378
  ? taskListSummary(tasks)
399
379
  : isError
400
380
  ? text
401
- ? oneLine(text)
381
+ ? // 72 与原 result.ts 默认一致,保持错误摘要截断宽度。
382
+ oneLine(text, 72)
402
383
  : "Failed"
403
384
  : outputLines
404
385
  ? `${outputLines} ${lineWord} ${action}`
405
386
  : "Done";
406
387
  const expandable = !expanded && (tasks.length > 0 || hasExpandableDetail(text, args));
407
388
  const hintText = showMoreHintText();
408
- const hintPrefix = expandable ? theme.fg("dim", " • ") : "";
389
+ const hintPrefix = expandable ? theme.fg("dim", " · ") : "";
409
390
  const hint = expandable ? hintPrefix + theme.fg("dim", hintText) : "";
410
391
  const hoveredHint = expandable ? hintPrefix + theme.fg("text", hintText) : "";
411
392
  if (expanded) {
@@ -416,6 +397,7 @@ function createCcstyleTool(
416
397
  context?.lastComponent,
417
398
  args,
418
399
  context,
400
+ true, // mode=on:贴左,由外层 Box(1,1) 提供 1 格 padding
419
401
  );
420
402
  }
421
403
  if (context?.state) context.state.ccstyleIoView = undefined;
@@ -466,19 +448,15 @@ function shouldGloballyStyleTool(component: any, patch: GlobalToolRenderPatch):
466
448
  const builtInDefinition = component.builtInToolDefinition;
467
449
  const definition = extensionDefinition ?? builtInDefinition;
468
450
  const toolName = String(component.toolName || definition?.name || "");
451
+ // compact 也复用同一套 ccstyle call/result,避免折叠态工具卡回落到 Pi 原生样式。
469
452
  const useCcstyle =
470
- patch.mode() === "on" &&
453
+ patch.mode() !== "off" &&
471
454
  !DEDICATED_RENDERER_TOOLS.has(toolName) &&
472
455
  !preservesOriginalRenderer(extensionDefinition, toolName, builtInDefinition);
473
456
  component[COMPONENT_TOOL_RENDER_MODE] = useCcstyle;
474
457
  return useCcstyle;
475
458
  }
476
459
 
477
- function shouldUseSelfShell(component: any, _patch: GlobalToolRenderPatch): boolean {
478
- component[COMPONENT_TOOL_SELF_SHELL_MODE] = false;
479
- return false;
480
- }
481
-
482
460
  function getGloballyStyledTool(component: any, patch: GlobalToolRenderPatch): any {
483
461
  const definition = component.toolDefinition ?? component.builtInToolDefinition;
484
462
  if (definition && typeof definition === "object") {
@@ -516,107 +494,88 @@ function isOwnershipAwarePatch(value: any): value is GlobalToolRenderPatch {
516
494
  );
517
495
  }
518
496
 
519
- function isLegacyInstalledWrapper(method: unknown, downstreamField: string): boolean {
520
- if (typeof method !== "function") return false;
521
- try {
522
- const source = Function.prototype.toString.call(method);
523
- return (
524
- source.includes(downstreamField) &&
525
- (source.includes("shouldGloballyStyleTool") ||
526
- source.includes("shouldUseSelfShell") ||
527
- source.includes("getGloballyStyledTool"))
528
- );
529
- } catch {
530
- return false;
531
- }
532
- }
533
-
534
- function downstreamForGlobalToolInstall(prototype: any, previous: any): ToolRenderMethods {
497
+ function downstreamForGlobalToolInstall(
498
+ prototype: any,
499
+ previous: GlobalToolRenderPatch | undefined,
500
+ ): ToolRenderMethods {
535
501
  const current = prototypeToolRenderMethods(prototype);
536
- if (!previous || previous.prototype !== prototype) return current;
537
- if (isOwnershipAwarePatch(previous)) {
538
- return {
539
- hasRendererDefinition:
540
- current.hasRendererDefinition === previous.installed.hasRendererDefinition
541
- ? previous.downstream.hasRendererDefinition
542
- : current.hasRendererDefinition,
543
- getRenderShell:
544
- current.getRenderShell === previous.installed.getRenderShell
545
- ? previous.downstream.getRenderShell
546
- : current.getRenderShell,
547
- getCallRenderer:
548
- current.getCallRenderer === previous.installed.getCallRenderer
549
- ? previous.downstream.getCallRenderer
550
- : current.getCallRenderer,
551
- getResultRenderer:
552
- current.getResultRenderer === previous.installed.getResultRenderer
553
- ? previous.downstream.getResultRenderer
554
- : current.getResultRenderer,
555
- };
502
+ if (!previous || previous.prototype !== prototype || !isOwnershipAwarePatch(previous)) {
503
+ return current;
556
504
  }
557
-
558
- // pre-v2 Symbol 无 wrapper 引用;能识别则回退,否则保留当前方法为 external。
559
- const legacyDownstream = (method: Function, field: string): Function => {
560
- const saved = previous[field];
561
- return typeof saved === "function" && isLegacyInstalledWrapper(method, field) ? saved : method;
562
- };
563
505
  return {
564
- hasRendererDefinition: legacyDownstream(
565
- current.hasRendererDefinition,
566
- "originalHasRendererDefinition",
567
- ) as ToolRenderMethods["hasRendererDefinition"],
568
- getRenderShell: legacyDownstream(
569
- current.getRenderShell,
570
- "originalGetRenderShell",
571
- ) as ToolRenderMethods["getRenderShell"],
572
- getCallRenderer: legacyDownstream(
573
- current.getCallRenderer,
574
- "originalGetCallRenderer",
575
- ) as ToolRenderMethods["getCallRenderer"],
576
- getResultRenderer: legacyDownstream(
577
- current.getResultRenderer,
578
- "originalGetResultRenderer",
579
- ) as ToolRenderMethods["getResultRenderer"],
506
+ hasRendererDefinition:
507
+ current.hasRendererDefinition === previous.installed.hasRendererDefinition
508
+ ? previous.downstream.hasRendererDefinition
509
+ : current.hasRendererDefinition,
510
+ getRenderShell:
511
+ current.getRenderShell === previous.installed.getRenderShell
512
+ ? previous.downstream.getRenderShell
513
+ : current.getRenderShell,
514
+ getCallRenderer:
515
+ current.getCallRenderer === previous.installed.getCallRenderer
516
+ ? previous.downstream.getCallRenderer
517
+ : current.getCallRenderer,
518
+ getResultRenderer:
519
+ current.getResultRenderer === previous.installed.getResultRenderer
520
+ ? previous.downstream.getResultRenderer
521
+ : current.getResultRenderer,
580
522
  };
581
523
  }
582
524
 
583
- function disconnectGlobalToolRenderPatch(patch: any): void {
584
- if (!patch || typeof patch !== "object") return;
525
+ function disconnectGlobalToolRenderPatch(patch: GlobalToolRenderPatch | undefined): void {
526
+ if (!patch) return;
585
527
  patch.active = false;
586
- patch.enabled = () => false;
587
- patch.mode = () => "off";
588
- patch.wrap = (tool: any) => tool;
589
528
  patch.byDefinition = new WeakMap();
590
- if (patch.byName && typeof patch.byName.clear === "function") patch.byName.clear();
591
- else patch.byName = new Map();
529
+ patch.byName.clear();
530
+ }
531
+
532
+ function ioHoverOf(tool: any): string | null {
533
+ const view = tool?.resultRendererComponent;
534
+ if (!view || typeof view.getHoveredSection !== "function") return null;
535
+ return view.getHoveredSection();
536
+ }
537
+
538
+ function toolPaintMatches(hit: ToolPaintHit, tool: any, width: number): boolean {
539
+ return (
540
+ hit.width === width &&
541
+ hit.expanded === Boolean(tool.expanded) &&
542
+ hit.isPartial === Boolean(tool.isPartial) &&
543
+ hit.result === tool.result &&
544
+ hit.args === tool.args &&
545
+ hit.callHover === isToolCallHovered(tool.toolCallId) &&
546
+ hit.ioHover === ioHoverOf(tool)
547
+ );
592
548
  }
593
549
 
594
550
  function installGlobalToolRendering(
595
551
  writeExecutionMetadata: WriteExecutionMetadataStore,
596
552
  ): GlobalToolRenderPatch {
597
553
  const prototype = (ToolExecutionComponent as any).prototype;
598
- const host = globalThis as any;
599
- const previous = host[GLOBAL_TOOL_RENDER_PATCH];
554
+ const previous = patchRegistry.get<GlobalToolRenderPatch>(GLOBAL_TOOL_RENDER_PATCH);
600
555
  const downstream = downstreamForGlobalToolInstall(prototype, previous);
601
- // 外部仍持有的旧 wrapper 先变为无回调 pass-through,再挂新安装。
602
- disconnectGlobalToolRenderPatch(previous);
556
+ const originalRender =
557
+ previous?.originalRender && prototype.render === previous.renderPaint
558
+ ? previous.originalRender
559
+ : prototype.render;
560
+ const originalInvalidate =
561
+ previous?.originalInvalidate && prototype.invalidate === previous.invalidatePaint
562
+ ? previous.originalInvalidate
563
+ : prototype.invalidate;
564
+ if (isOwnershipAwarePatch(previous)) disconnectGlobalToolRenderPatch(previous);
603
565
 
604
566
  const patch: GlobalToolRenderPatch = {
605
567
  version: 2,
606
568
  prototype,
607
- owner: {},
608
569
  active: true,
609
- enabled: () => config.mode === "on",
610
570
  mode: () => config.mode,
611
571
  wrap: (tool: any) => createCcstyleTool(tool, writeExecutionMetadata),
612
572
  byDefinition: new WeakMap(),
613
573
  byName: new Map(),
614
574
  downstream,
615
575
  installed: undefined as any,
616
- originalHasRendererDefinition: downstream.hasRendererDefinition,
617
- originalGetRenderShell: downstream.getRenderShell,
618
- originalGetCallRenderer: downstream.getCallRenderer,
619
- originalGetResultRenderer: downstream.getResultRenderer,
576
+ originalRender,
577
+ originalInvalidate,
578
+ paintCache: new WeakMap(),
620
579
  };
621
580
 
622
581
  patch.installed = {
@@ -626,14 +585,12 @@ function installGlobalToolRendering(
626
585
  },
627
586
  getRenderShell: function (this: any, ...args: any[]) {
628
587
  if (!patch.active) return patch.downstream.getRenderShell.apply(this, args);
629
- const useSelfShell = shouldUseSelfShell(this, patch);
630
588
  const useCcstyle = shouldGloballyStyleTool(this, patch);
631
- const shell =
632
- useSelfShell || (useCcstyle && !this.expanded)
633
- ? "self"
634
- : useCcstyle
635
- ? "default"
636
- : patch.downstream.getRenderShell.apply(this, args);
589
+ const shell = useCcstyle
590
+ ? this.expanded
591
+ ? "default"
592
+ : "self"
593
+ : patch.downstream.getRenderShell.apply(this, args);
637
594
  syncToolShell(this, shell);
638
595
  return shell;
639
596
  },
@@ -655,7 +612,42 @@ function installGlobalToolRendering(
655
612
  prototype.getRenderShell = patch.installed.getRenderShell;
656
613
  prototype.getCallRenderer = patch.installed.getCallRenderer;
657
614
  prototype.getResultRenderer = patch.installed.getResultRenderer;
658
- host[GLOBAL_TOOL_RENDER_PATCH] = patch;
615
+ // fullscreen 滚动/选区每帧整树 render;内容未变时复用上一帧行,避免重做 diff/Box。
616
+ patch.renderPaint = function (this: any, width: number): string[] {
617
+ if (!patch.active || patch.mode() === "off") {
618
+ return originalRender.call(this, width);
619
+ }
620
+ const cache = patch.paintCache;
621
+ // A running partial tool owns a time-varying spinner. Light animation ticks
622
+ // request a repaint without invalidating the component, so settled-content
623
+ // caching must not intercept those paints.
624
+ const cacheable = !(this.executionStarted && this.isPartial);
625
+ const hit = cacheable ? cache?.get(this) : undefined;
626
+ if (hit && toolPaintMatches(hit, this, width)) return hit.lines;
627
+ const lines = originalRender.call(this, width);
628
+ if (cacheable) {
629
+ cache?.set(this, {
630
+ width,
631
+ expanded: Boolean(this.expanded),
632
+ isPartial: Boolean(this.isPartial),
633
+ result: this.result,
634
+ args: this.args,
635
+ callHover: isToolCallHovered(this.toolCallId),
636
+ ioHover: ioHoverOf(this),
637
+ lines,
638
+ });
639
+ } else {
640
+ cache?.delete(this);
641
+ }
642
+ return lines;
643
+ };
644
+ patch.invalidatePaint = function (this: any): void {
645
+ patch.paintCache?.delete(this);
646
+ originalInvalidate.call(this);
647
+ };
648
+ prototype.render = patch.renderPaint;
649
+ prototype.invalidate = patch.invalidatePaint;
650
+ patchRegistry.install(GLOBAL_TOOL_RENDER_PATCH, patch);
659
651
  return patch;
660
652
  }
661
653
 
@@ -675,15 +667,23 @@ function deactivateGlobalToolRendering(patch: GlobalToolRenderPatch): void {
675
667
  if (prototype.getResultRenderer === patch.installed.getResultRenderer) {
676
668
  prototype.getResultRenderer = patch.downstream.getResultRenderer;
677
669
  }
670
+ if (patch.renderPaint && prototype.render === patch.renderPaint && patch.originalRender) {
671
+ prototype.render = patch.originalRender;
672
+ }
673
+ if (
674
+ patch.invalidatePaint &&
675
+ prototype.invalidate === patch.invalidatePaint &&
676
+ patch.originalInvalidate
677
+ ) {
678
+ prototype.invalidate = patch.originalInvalidate;
679
+ }
678
680
  }
679
681
 
680
682
  /** 展开面板背景统一为 user message 背景色;折叠行保持原生状态色。
681
683
  * 必须在 compact-mode 之后安装,shutdown 时先于 compact-mode 释放。 */
682
684
  export function installToolExpandedBackground(): () => void {
683
- const host = globalThis as any;
684
- const previous = host[TOOL_EXPANDED_BACKGROUND_PATCH] as ToolExpandedBackgroundPatch | undefined;
685
+ const previous = patchRegistry.get<ToolExpandedBackgroundPatch>(TOOL_EXPANDED_BACKGROUND_PATCH);
685
686
  if (previous) previous.dispose();
686
- // SAFETY: Pi's runtime ToolExecutionComponent prototype owns updateDisplay; its public type omits it.
687
687
  const prototype = ToolExecutionComponent.prototype as unknown as { updateDisplay: () => void };
688
688
  const original = prototype.updateDisplay;
689
689
  const patch: ToolExpandedBackgroundPatch = {
@@ -695,7 +695,14 @@ export function installToolExpandedBackground(): () => void {
695
695
  const theme = getMessageDisplayTheme();
696
696
  if (!theme?.bg) return;
697
697
  const box = this.contentBox;
698
- if (box?.setBgFn) box.setBgFn((text: string) => theme.bg("userMessageBg", text));
698
+ // 展开最外层卡片:上下左右内间距 1 格
699
+ if (box) {
700
+ box.paddingX = 1;
701
+ box.paddingY = 1;
702
+ if (box.setBgFn) {
703
+ box.setBgFn((text: string) => theme.bg(config.expandedCardBackground, text));
704
+ }
705
+ }
699
706
  },
700
707
  original,
701
708
  dispose: () => {
@@ -703,13 +710,11 @@ export function installToolExpandedBackground(): () => void {
703
710
  if (prototype.updateDisplay === patch.installed) {
704
711
  prototype.updateDisplay = original;
705
712
  }
706
- if (host[TOOL_EXPANDED_BACKGROUND_PATCH] === patch) {
707
- delete host[TOOL_EXPANDED_BACKGROUND_PATCH];
708
- }
713
+ patchRegistry.dispose(TOOL_EXPANDED_BACKGROUND_PATCH, patch);
709
714
  },
710
715
  };
711
716
  prototype.updateDisplay = patch.installed;
712
- host[TOOL_EXPANDED_BACKGROUND_PATCH] = patch;
717
+ patchRegistry.install(TOOL_EXPANDED_BACKGROUND_PATCH, patch);
713
718
  return patch.dispose;
714
719
  }
715
720
 
@@ -721,7 +726,7 @@ export function installDefaultMode(
721
726
  return {
722
727
  isOwner() {
723
728
  return (
724
- (globalThis as any)[GLOBAL_TOOL_RENDER_PATCH] === globalToolRendering &&
729
+ patchRegistry.owns(GLOBAL_TOOL_RENDER_PATCH, globalToolRendering) &&
725
730
  globalToolRendering.active
726
731
  );
727
732
  },