@herbertgao/pi-extensions 2026.8.2 → 2026.8.4

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 (392) hide show
  1. package/README.md +50 -2
  2. package/examples/pi-footer.json +275 -0
  3. package/node_modules/@herbertgao/pi-cc-extensions/README.en.md +6 -8
  4. package/node_modules/@herbertgao/pi-cc-extensions/README.md +5 -7
  5. package/node_modules/@herbertgao/pi-cc-extensions/assets/readme/hero.en.svg +101 -0
  6. package/node_modules/@herbertgao/pi-cc-extensions/extensions/config/config.ts +1 -17
  7. package/node_modules/@herbertgao/pi-cc-extensions/extensions/config/panel.ts +5 -3
  8. package/node_modules/@herbertgao/pi-cc-extensions/extensions/{utils/agent-summary.ts → feature/agent-summary/core.ts} +37 -35
  9. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/{agent-summary.ts → agent-summary/index.ts} +2 -6
  10. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/{session-reference.ts → reference/index.ts} +1 -1
  11. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/{agent-autocomplete.ts → reference/subagent.ts} +19 -9
  12. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/{pi-startup-header.ts → shell/startup-header.ts} +1 -1
  13. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/{working-message.ts → shell/working-message.ts} +5 -2
  14. package/node_modules/@herbertgao/pi-cc-extensions/extensions/index.ts +32 -28
  15. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/compact-mode.ts +379 -85
  16. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/default-mode.ts +727 -0
  17. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/index.ts +65 -775
  18. package/node_modules/@herbertgao/pi-cc-extensions/extensions/{feature → renderer}/markdown-enhance.ts +35 -31
  19. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{mouse-hover.ts → mouse/hover.ts} +5 -5
  20. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{mouse-interaction.ts → mouse/interaction.ts} +34 -35
  21. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{mouse-layout.ts → mouse/layout.ts} +5 -21
  22. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{mouse-packets.ts → mouse/packets.ts} +1 -1
  23. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{mouse-scroll.ts → mouse/scroll.ts} +48 -37
  24. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-diff → tool/diff}/ansi-utils.ts +56 -1
  25. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-diff → tool/diff}/diff-renderer.ts +2 -2
  26. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-diff → tool/diff}/line-width-safety.ts +1 -1
  27. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/write-display-utils.ts +12 -0
  28. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-diff → tool/diff}/write-execution.ts +1 -2
  29. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-grouping.ts → tool/grouping.ts} +18 -8
  30. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-result.ts → tool/result.ts} +4 -13
  31. package/node_modules/@herbertgao/pi-cc-extensions/extensions/utils/fullscreen-detect.ts +0 -27
  32. package/node_modules/@herbertgao/pi-cc-extensions/package.json +3 -3
  33. package/node_modules/@herbertgao/pi-subagents/CHANGELOG.md +6 -0
  34. package/node_modules/@herbertgao/pi-subagents/package.json +2 -2
  35. package/node_modules/@herbertgao/pi-subagents/src/agent-manager.ts +1 -0
  36. package/node_modules/@herbertgao/pi-subagents/src/agent-runner.ts +3 -1
  37. package/node_modules/@herbertgao/pi-subagents/src/index.ts +33 -35
  38. package/node_modules/@herbertgao/pi-subagents/src/nested-tools.ts +26 -35
  39. package/node_modules/@herbertgao/pi-subagents/src/prompts.ts +15 -1
  40. package/node_modules/pi-footer/CHANGELOG.md +145 -0
  41. package/node_modules/pi-footer/LICENSE +21 -0
  42. package/node_modules/pi-footer/README.md +354 -0
  43. package/node_modules/pi-footer/package.json +68 -0
  44. package/node_modules/pi-footer/src/cache.ts +106 -0
  45. package/node_modules/pi-footer/src/colors.ts +237 -0
  46. package/node_modules/pi-footer/src/config.ts +202 -0
  47. package/node_modules/pi-footer/src/event-widgets.ts +41 -0
  48. package/node_modules/pi-footer/src/extension-statuses.ts +102 -0
  49. package/node_modules/pi-footer/src/git.ts +135 -0
  50. package/node_modules/pi-footer/src/index.ts +268 -0
  51. package/node_modules/pi-footer/src/metrics.ts +141 -0
  52. package/node_modules/pi-footer/src/presets.ts +383 -0
  53. package/node_modules/pi-footer/src/render.ts +114 -0
  54. package/node_modules/pi-footer/src/separators.ts +52 -0
  55. package/node_modules/pi-footer/src/types.ts +122 -0
  56. package/node_modules/pi-footer/src/ui/color-level-confirm.ts +22 -0
  57. package/node_modules/pi-footer/src/ui/color-options.ts +195 -0
  58. package/node_modules/pi-footer/src/ui/config-lifecycle.ts +61 -0
  59. package/node_modules/pi-footer/src/ui/edit-colors.ts +13 -0
  60. package/node_modules/pi-footer/src/ui/events.ts +35 -0
  61. package/node_modules/pi-footer/src/ui/extension-status-picker.ts +60 -0
  62. package/node_modules/pi-footer/src/ui/extension-statuses.ts +73 -0
  63. package/node_modules/pi-footer/src/ui/fields.ts +252 -0
  64. package/node_modules/pi-footer/src/ui/global-menu.ts +126 -0
  65. package/node_modules/pi-footer/src/ui/helpers.ts +44 -0
  66. package/node_modules/pi-footer/src/ui/layout.ts +17 -0
  67. package/node_modules/pi-footer/src/ui/line-list.ts +19 -0
  68. package/node_modules/pi-footer/src/ui/model.ts +64 -0
  69. package/node_modules/pi-footer/src/ui/navigation.ts +29 -0
  70. package/node_modules/pi-footer/src/ui/option-edit.ts +93 -0
  71. package/node_modules/pi-footer/src/ui/overlay-render.ts +103 -0
  72. package/node_modules/pi-footer/src/ui/screen-context.ts +18 -0
  73. package/node_modules/pi-footer/src/ui/screen-controller.ts +27 -0
  74. package/node_modules/pi-footer/src/ui/screen-render.ts +32 -0
  75. package/node_modules/pi-footer/src/ui/screen-state.ts +20 -0
  76. package/node_modules/pi-footer/src/ui/screen.ts +243 -0
  77. package/node_modules/pi-footer/src/ui/screens/add-widget.ts +92 -0
  78. package/node_modules/pi-footer/src/ui/screens/confirm-exit.ts +52 -0
  79. package/node_modules/pi-footer/src/ui/screens/controller.ts +12 -0
  80. package/node_modules/pi-footer/src/ui/screens/edit-colors.ts +68 -0
  81. package/node_modules/pi-footer/src/ui/screens/edit-widget.ts +115 -0
  82. package/node_modules/pi-footer/src/ui/screens/extension-status-row.ts +61 -0
  83. package/node_modules/pi-footer/src/ui/screens/global.ts +75 -0
  84. package/node_modules/pi-footer/src/ui/screens/line-list.ts +108 -0
  85. package/node_modules/pi-footer/src/ui/screens/main.ts +99 -0
  86. package/node_modules/pi-footer/src/ui/screens/terminal.ts +121 -0
  87. package/node_modules/pi-footer/src/ui/screens/widget-list.ts +154 -0
  88. package/node_modules/pi-footer/src/ui/terminal-menu.ts +32 -0
  89. package/node_modules/pi-footer/src/ui/theme.ts +48 -0
  90. package/node_modules/pi-footer/src/ui/title-bar.ts +100 -0
  91. package/node_modules/pi-footer/src/ui/widget-actions.ts +76 -0
  92. package/node_modules/pi-footer/src/ui.ts +66 -0
  93. package/node_modules/pi-footer/src/widgets/context.ts +28 -0
  94. package/node_modules/pi-footer/src/widgets/core/active-tools.ts +17 -0
  95. package/node_modules/pi-footer/src/widgets/core/context-window.ts +24 -0
  96. package/node_modules/pi-footer/src/widgets/core/cwd-basename.ts +19 -0
  97. package/node_modules/pi-footer/src/widgets/core/cwd.ts +108 -0
  98. package/node_modules/pi-footer/src/widgets/core/event.ts +34 -0
  99. package/node_modules/pi-footer/src/widgets/core/external-status.ts +102 -0
  100. package/node_modules/pi-footer/src/widgets/core/model-provider.ts +20 -0
  101. package/node_modules/pi-footer/src/widgets/core/model.ts +35 -0
  102. package/node_modules/pi-footer/src/widgets/core/provider.ts +17 -0
  103. package/node_modules/pi-footer/src/widgets/core/session-name.ts +17 -0
  104. package/node_modules/pi-footer/src/widgets/core/text-verbosity.ts +17 -0
  105. package/node_modules/pi-footer/src/widgets/core/thinking-level.ts +17 -0
  106. package/node_modules/pi-footer/src/widgets/git/ahead-behind.ts +17 -0
  107. package/node_modules/pi-footer/src/widgets/git/branch.ts +81 -0
  108. package/node_modules/pi-footer/src/widgets/git/clean.ts +19 -0
  109. package/node_modules/pi-footer/src/widgets/git/deletions.ts +17 -0
  110. package/node_modules/pi-footer/src/widgets/git/diff.ts +38 -0
  111. package/node_modules/pi-footer/src/widgets/git/insertions.ts +17 -0
  112. package/node_modules/pi-footer/src/widgets/git/remote.ts +17 -0
  113. package/node_modules/pi-footer/src/widgets/git/root.ts +17 -0
  114. package/node_modules/pi-footer/src/widgets/git/sha.ts +17 -0
  115. package/node_modules/pi-footer/src/widgets/git/staged.ts +17 -0
  116. package/node_modules/pi-footer/src/widgets/git/status.ts +19 -0
  117. package/node_modules/pi-footer/src/widgets/git/unstaged.ts +17 -0
  118. package/node_modules/pi-footer/src/widgets/git/untracked.ts +17 -0
  119. package/node_modules/pi-footer/src/widgets/instance.ts +118 -0
  120. package/node_modules/pi-footer/src/widgets/layout/custom-text.ts +18 -0
  121. package/node_modules/pi-footer/src/widgets/layout/flex-separator.ts +32 -0
  122. package/node_modules/pi-footer/src/widgets/layout/separator.ts +57 -0
  123. package/node_modules/pi-footer/src/widgets/layout/spacer.ts +31 -0
  124. package/node_modules/pi-footer/src/widgets/options.ts +122 -0
  125. package/node_modules/pi-footer/src/widgets/project/runtime.ts +361 -0
  126. package/node_modules/pi-footer/src/widgets/registry.ts +223 -0
  127. package/node_modules/pi-footer/src/widgets/session/assistant-messages.ts +17 -0
  128. package/node_modules/pi-footer/src/widgets/session/compactions.ts +17 -0
  129. package/node_modules/pi-footer/src/widgets/session/elapsed.ts +18 -0
  130. package/node_modules/pi-footer/src/widgets/session/last-activity.ts +18 -0
  131. package/node_modules/pi-footer/src/widgets/session/messages.ts +19 -0
  132. package/node_modules/pi-footer/src/widgets/session/session-id.ts +17 -0
  133. package/node_modules/pi-footer/src/widgets/session/session-start.ts +18 -0
  134. package/node_modules/pi-footer/src/widgets/session/tool-results.ts +17 -0
  135. package/node_modules/pi-footer/src/widgets/session/total-messages.ts +19 -0
  136. package/node_modules/pi-footer/src/widgets/session/total-time.ts +18 -0
  137. package/node_modules/pi-footer/src/widgets/session/user-messages.ts +17 -0
  138. package/node_modules/pi-footer/src/widgets/store.ts +26 -0
  139. package/node_modules/pi-footer/src/widgets/tokens/cache-hit-rate.ts +55 -0
  140. package/node_modules/pi-footer/src/widgets/tokens/cache-read.ts +18 -0
  141. package/node_modules/pi-footer/src/widgets/tokens/cache-write.ts +18 -0
  142. package/node_modules/pi-footer/src/widgets/tokens/context-bar.ts +108 -0
  143. package/node_modules/pi-footer/src/widgets/tokens/context-length.ts +26 -0
  144. package/node_modules/pi-footer/src/widgets/tokens/context-remaining.ts +29 -0
  145. package/node_modules/pi-footer/src/widgets/tokens/context.ts +29 -0
  146. package/node_modules/pi-footer/src/widgets/tokens/cost.ts +51 -0
  147. package/node_modules/pi-footer/src/widgets/tokens/input-speed.ts +25 -0
  148. package/node_modules/pi-footer/src/widgets/tokens/input-tokens.ts +18 -0
  149. package/node_modules/pi-footer/src/widgets/tokens/output-speed.ts +25 -0
  150. package/node_modules/pi-footer/src/widgets/tokens/output-tokens.ts +18 -0
  151. package/node_modules/pi-footer/src/widgets/tokens/tokens.ts +20 -0
  152. package/node_modules/pi-footer/src/widgets/tokens/total-speed.ts +25 -0
  153. package/node_modules/pi-footer/src/widgets/tokens/total-tokens.ts +18 -0
  154. package/node_modules/pi-footer/src/widgets/types.ts +181 -0
  155. package/node_modules/pi-footer/src/widgets/utils/colors.ts +11 -0
  156. package/node_modules/pi-footer/src/widgets/utils/context.ts +112 -0
  157. package/node_modules/pi-footer/src/widgets/utils/session.ts +19 -0
  158. package/node_modules/pi-footer/src/widgets/utils/token-format.ts +78 -0
  159. package/node_modules/pi-mcp-adapter/CHANGELOG.md +19 -0
  160. package/node_modules/pi-mcp-adapter/README.md +19 -4
  161. package/node_modules/pi-mcp-adapter/agent-dir.ts +40 -0
  162. package/node_modules/pi-mcp-adapter/commands.ts +12 -2
  163. package/node_modules/pi-mcp-adapter/direct-tools.ts +6 -8
  164. package/node_modules/pi-mcp-adapter/index.ts +15 -3
  165. package/node_modules/pi-mcp-adapter/mcp-auth-flow.ts +87 -4
  166. package/node_modules/pi-mcp-adapter/mcp-callback-server.ts +138 -61
  167. package/node_modules/pi-mcp-adapter/mcp-oauth-provider.ts +43 -4
  168. package/node_modules/pi-mcp-adapter/oauth.ts +48 -0
  169. package/node_modules/pi-mcp-adapter/package.json +8 -2
  170. package/node_modules/pi-mcp-adapter/proxy-modes.ts +8 -10
  171. package/node_modules/pi-mcp-adapter/tool-registrar.ts +187 -3
  172. package/node_modules/pi-mcp-adapter/types.ts +2 -0
  173. package/node_modules/pi-web-access/CHANGELOG.md +45 -0
  174. package/node_modules/pi-web-access/README.md +104 -29
  175. package/node_modules/pi-web-access/bocha.ts +221 -0
  176. package/node_modules/pi-web-access/curator-page.ts +113 -12
  177. package/node_modules/pi-web-access/curator-server.ts +56 -20
  178. package/node_modules/pi-web-access/datalab-pdf-extract.ts +568 -0
  179. package/node_modules/pi-web-access/duckduckgo.ts +123 -0
  180. package/node_modules/pi-web-access/extract.ts +288 -143
  181. package/node_modules/pi-web-access/feature-config.ts +29 -0
  182. package/node_modules/pi-web-access/gemini-api.ts +4 -0
  183. package/node_modules/pi-web-access/gemini-search.ts +45 -12
  184. package/node_modules/pi-web-access/gemini-web.ts +68 -3
  185. package/node_modules/pi-web-access/index.ts +160 -71
  186. package/node_modules/pi-web-access/jina-search.ts +284 -0
  187. package/node_modules/pi-web-access/kagi.ts +12 -12
  188. package/node_modules/pi-web-access/openai-search.ts +12 -2
  189. package/node_modules/pi-web-access/package.json +4 -3
  190. package/node_modules/pi-web-access/pdf-extract.ts +327 -228
  191. package/node_modules/pi-web-access/storage.ts +440 -2
  192. package/node_modules/pi-web-access/summary-model-scope.ts +1 -1
  193. package/node_modules/pi-web-access/summary-review.ts +4 -2
  194. package/node_modules/pi-web-access/video-extract.ts +10 -8
  195. package/node_modules/pi-web-access/xai-search.ts +12 -2
  196. package/node_modules/pi-web-access/youtube-extract.ts +2 -1
  197. package/node_modules/remote-pi/LICENSE +21 -0
  198. package/node_modules/remote-pi/README.md +675 -0
  199. package/node_modules/remote-pi/dist/actions/handlers.d.ts +122 -0
  200. package/node_modules/remote-pi/dist/actions/handlers.js +160 -0
  201. package/node_modules/remote-pi/dist/actions/handlers.js.map +1 -0
  202. package/node_modules/remote-pi/dist/actions/registry.d.ts +39 -0
  203. package/node_modules/remote-pi/dist/actions/registry.js +58 -0
  204. package/node_modules/remote-pi/dist/actions/registry.js.map +1 -0
  205. package/node_modules/remote-pi/dist/bin/supervisord.d.ts +2 -0
  206. package/node_modules/remote-pi/dist/bin/supervisord.js +86 -0
  207. package/node_modules/remote-pi/dist/bin/supervisord.js.map +1 -0
  208. package/node_modules/remote-pi/dist/commands/builtin_mirror.d.ts +58 -0
  209. package/node_modules/remote-pi/dist/commands/builtin_mirror.js +71 -0
  210. package/node_modules/remote-pi/dist/commands/builtin_mirror.js.map +1 -0
  211. package/node_modules/remote-pi/dist/commands/list_commands.d.ts +60 -0
  212. package/node_modules/remote-pi/dist/commands/list_commands.js +73 -0
  213. package/node_modules/remote-pi/dist/commands/list_commands.js.map +1 -0
  214. package/node_modules/remote-pi/dist/config.d.ts +62 -0
  215. package/node_modules/remote-pi/dist/config.js +115 -0
  216. package/node_modules/remote-pi/dist/config.js.map +1 -0
  217. package/node_modules/remote-pi/dist/daemon/client.d.ts +20 -0
  218. package/node_modules/remote-pi/dist/daemon/client.js +131 -0
  219. package/node_modules/remote-pi/dist/daemon/client.js.map +1 -0
  220. package/node_modules/remote-pi/dist/daemon/control_protocol.d.ts +176 -0
  221. package/node_modules/remote-pi/dist/daemon/control_protocol.js +63 -0
  222. package/node_modules/remote-pi/dist/daemon/control_protocol.js.map +1 -0
  223. package/node_modules/remote-pi/dist/daemon/cron_log.d.ts +45 -0
  224. package/node_modules/remote-pi/dist/daemon/cron_log.js +72 -0
  225. package/node_modules/remote-pi/dist/daemon/cron_log.js.map +1 -0
  226. package/node_modules/remote-pi/dist/daemon/cron_registry.d.ts +80 -0
  227. package/node_modules/remote-pi/dist/daemon/cron_registry.js +194 -0
  228. package/node_modules/remote-pi/dist/daemon/cron_registry.js.map +1 -0
  229. package/node_modules/remote-pi/dist/daemon/id.d.ts +24 -0
  230. package/node_modules/remote-pi/dist/daemon/id.js +36 -0
  231. package/node_modules/remote-pi/dist/daemon/id.js.map +1 -0
  232. package/node_modules/remote-pi/dist/daemon/install.d.ts +170 -0
  233. package/node_modules/remote-pi/dist/daemon/install.js +547 -0
  234. package/node_modules/remote-pi/dist/daemon/install.js.map +1 -0
  235. package/node_modules/remote-pi/dist/daemon/registry.d.ts +63 -0
  236. package/node_modules/remote-pi/dist/daemon/registry.js +153 -0
  237. package/node_modules/remote-pi/dist/daemon/registry.js.map +1 -0
  238. package/node_modules/remote-pi/dist/daemon/rpc_child.d.ts +194 -0
  239. package/node_modules/remote-pi/dist/daemon/rpc_child.js +389 -0
  240. package/node_modules/remote-pi/dist/daemon/rpc_child.js.map +1 -0
  241. package/node_modules/remote-pi/dist/daemon/supervisor.d.ts +93 -0
  242. package/node_modules/remote-pi/dist/daemon/supervisor.js +596 -0
  243. package/node_modules/remote-pi/dist/daemon/supervisor.js.map +1 -0
  244. package/node_modules/remote-pi/dist/extension_ui_bridge.d.ts +26 -0
  245. package/node_modules/remote-pi/dist/extension_ui_bridge.js +341 -0
  246. package/node_modules/remote-pi/dist/extension_ui_bridge.js.map +1 -0
  247. package/node_modules/remote-pi/dist/index.d.ts +213 -0
  248. package/node_modules/remote-pi/dist/index.js +4996 -0
  249. package/node_modules/remote-pi/dist/index.js.map +1 -0
  250. package/node_modules/remote-pi/dist/mcp/mesh_result.d.ts +10 -0
  251. package/node_modules/remote-pi/dist/mcp/mesh_result.js +42 -0
  252. package/node_modules/remote-pi/dist/mcp/mesh_result.js.map +1 -0
  253. package/node_modules/remote-pi/dist/mcp/mesh_server.d.ts +16 -0
  254. package/node_modules/remote-pi/dist/mcp/mesh_server.js +327 -0
  255. package/node_modules/remote-pi/dist/mcp/mesh_server.js.map +1 -0
  256. package/node_modules/remote-pi/dist/mesh/canonical.d.ts +30 -0
  257. package/node_modules/remote-pi/dist/mesh/canonical.js +61 -0
  258. package/node_modules/remote-pi/dist/mesh/canonical.js.map +1 -0
  259. package/node_modules/remote-pi/dist/mesh/client.d.ts +18 -0
  260. package/node_modules/remote-pi/dist/mesh/client.js +125 -0
  261. package/node_modules/remote-pi/dist/mesh/client.js.map +1 -0
  262. package/node_modules/remote-pi/dist/mesh/encoding.d.ts +38 -0
  263. package/node_modules/remote-pi/dist/mesh/encoding.js +216 -0
  264. package/node_modules/remote-pi/dist/mesh/encoding.js.map +1 -0
  265. package/node_modules/remote-pi/dist/mesh/self_revoke.d.ts +73 -0
  266. package/node_modules/remote-pi/dist/mesh/self_revoke.js +401 -0
  267. package/node_modules/remote-pi/dist/mesh/self_revoke.js.map +1 -0
  268. package/node_modules/remote-pi/dist/mesh/siblings.d.ts +49 -0
  269. package/node_modules/remote-pi/dist/mesh/siblings.js +159 -0
  270. package/node_modules/remote-pi/dist/mesh/siblings.js.map +1 -0
  271. package/node_modules/remote-pi/dist/mesh/types.d.ts +34 -0
  272. package/node_modules/remote-pi/dist/mesh/types.js +11 -0
  273. package/node_modules/remote-pi/dist/mesh/types.js.map +1 -0
  274. package/node_modules/remote-pi/dist/mesh/verify.d.ts +17 -0
  275. package/node_modules/remote-pi/dist/mesh/verify.js +86 -0
  276. package/node_modules/remote-pi/dist/mesh/verify.js.map +1 -0
  277. package/node_modules/remote-pi/dist/pairing/crypto.d.ts +8 -0
  278. package/node_modules/remote-pi/dist/pairing/crypto.js +22 -0
  279. package/node_modules/remote-pi/dist/pairing/crypto.js.map +1 -0
  280. package/node_modules/remote-pi/dist/pairing/handshake.d.ts +28 -0
  281. package/node_modules/remote-pi/dist/pairing/handshake.js +113 -0
  282. package/node_modules/remote-pi/dist/pairing/handshake.js.map +1 -0
  283. package/node_modules/remote-pi/dist/pairing/noise-sha256.d.ts +16 -0
  284. package/node_modules/remote-pi/dist/pairing/noise-sha256.js +103 -0
  285. package/node_modules/remote-pi/dist/pairing/noise-sha256.js.map +1 -0
  286. package/node_modules/remote-pi/dist/pairing/qr.d.ts +59 -0
  287. package/node_modules/remote-pi/dist/pairing/qr.js +125 -0
  288. package/node_modules/remote-pi/dist/pairing/qr.js.map +1 -0
  289. package/node_modules/remote-pi/dist/pairing/storage.d.ts +120 -0
  290. package/node_modules/remote-pi/dist/pairing/storage.js +604 -0
  291. package/node_modules/remote-pi/dist/pairing/storage.js.map +1 -0
  292. package/node_modules/remote-pi/dist/protocol/codec.d.ts +7 -0
  293. package/node_modules/remote-pi/dist/protocol/codec.js +49 -0
  294. package/node_modules/remote-pi/dist/protocol/codec.js.map +1 -0
  295. package/node_modules/remote-pi/dist/protocol/types.d.ts +393 -0
  296. package/node_modules/remote-pi/dist/protocol/types.js +2 -0
  297. package/node_modules/remote-pi/dist/protocol/types.js.map +1 -0
  298. package/node_modules/remote-pi/dist/rooms.d.ts +29 -0
  299. package/node_modules/remote-pi/dist/rooms.js +57 -0
  300. package/node_modules/remote-pi/dist/rooms.js.map +1 -0
  301. package/node_modules/remote-pi/dist/session/address.d.ts +49 -0
  302. package/node_modules/remote-pi/dist/session/address.js +58 -0
  303. package/node_modules/remote-pi/dist/session/address.js.map +1 -0
  304. package/node_modules/remote-pi/dist/session/agent_bridge.d.ts +55 -0
  305. package/node_modules/remote-pi/dist/session/agent_bridge.js +146 -0
  306. package/node_modules/remote-pi/dist/session/agent_bridge.js.map +1 -0
  307. package/node_modules/remote-pi/dist/session/bridge.d.ts +37 -0
  308. package/node_modules/remote-pi/dist/session/bridge.js +130 -0
  309. package/node_modules/remote-pi/dist/session/bridge.js.map +1 -0
  310. package/node_modules/remote-pi/dist/session/broker.d.ts +189 -0
  311. package/node_modules/remote-pi/dist/session/broker.js +507 -0
  312. package/node_modules/remote-pi/dist/session/broker.js.map +1 -0
  313. package/node_modules/remote-pi/dist/session/broker_remote.d.ts +74 -0
  314. package/node_modules/remote-pi/dist/session/broker_remote.js +583 -0
  315. package/node_modules/remote-pi/dist/session/broker_remote.js.map +1 -0
  316. package/node_modules/remote-pi/dist/session/cwd_lock.d.ts +33 -0
  317. package/node_modules/remote-pi/dist/session/cwd_lock.js +126 -0
  318. package/node_modules/remote-pi/dist/session/cwd_lock.js.map +1 -0
  319. package/node_modules/remote-pi/dist/session/envelope.d.ts +33 -0
  320. package/node_modules/remote-pi/dist/session/envelope.js +117 -0
  321. package/node_modules/remote-pi/dist/session/envelope.js.map +1 -0
  322. package/node_modules/remote-pi/dist/session/global_config.d.ts +33 -0
  323. package/node_modules/remote-pi/dist/session/global_config.js +73 -0
  324. package/node_modules/remote-pi/dist/session/global_config.js.map +1 -0
  325. package/node_modules/remote-pi/dist/session/ipc.d.ts +27 -0
  326. package/node_modules/remote-pi/dist/session/ipc.js +22 -0
  327. package/node_modules/remote-pi/dist/session/ipc.js.map +1 -0
  328. package/node_modules/remote-pi/dist/session/leader_election.d.ts +32 -0
  329. package/node_modules/remote-pi/dist/session/leader_election.js +106 -0
  330. package/node_modules/remote-pi/dist/session/leader_election.js.map +1 -0
  331. package/node_modules/remote-pi/dist/session/local_config.d.ts +55 -0
  332. package/node_modules/remote-pi/dist/session/local_config.js +157 -0
  333. package/node_modules/remote-pi/dist/session/local_config.js.map +1 -0
  334. package/node_modules/remote-pi/dist/session/mesh_message.d.ts +20 -0
  335. package/node_modules/remote-pi/dist/session/mesh_message.js +28 -0
  336. package/node_modules/remote-pi/dist/session/mesh_message.js.map +1 -0
  337. package/node_modules/remote-pi/dist/session/mesh_node.d.ts +116 -0
  338. package/node_modules/remote-pi/dist/session/mesh_node.js +573 -0
  339. package/node_modules/remote-pi/dist/session/mesh_node.js.map +1 -0
  340. package/node_modules/remote-pi/dist/session/peer.d.ts +139 -0
  341. package/node_modules/remote-pi/dist/session/peer.js +451 -0
  342. package/node_modules/remote-pi/dist/session/peer.js.map +1 -0
  343. package/node_modules/remote-pi/dist/session/peer_inventory.d.ts +13 -0
  344. package/node_modules/remote-pi/dist/session/peer_inventory.js +48 -0
  345. package/node_modules/remote-pi/dist/session/peer_inventory.js.map +1 -0
  346. package/node_modules/remote-pi/dist/session/peer_limits.d.ts +9 -0
  347. package/node_modules/remote-pi/dist/session/peer_limits.js +21 -0
  348. package/node_modules/remote-pi/dist/session/peer_limits.js.map +1 -0
  349. package/node_modules/remote-pi/dist/session/setup_wizard.d.ts +39 -0
  350. package/node_modules/remote-pi/dist/session/setup_wizard.js +63 -0
  351. package/node_modules/remote-pi/dist/session/setup_wizard.js.map +1 -0
  352. package/node_modules/remote-pi/dist/session/tool_gate.d.ts +5 -0
  353. package/node_modules/remote-pi/dist/session/tool_gate.js +11 -0
  354. package/node_modules/remote-pi/dist/session/tool_gate.js.map +1 -0
  355. package/node_modules/remote-pi/dist/session/tools.d.ts +24 -0
  356. package/node_modules/remote-pi/dist/session/tools.js +252 -0
  357. package/node_modules/remote-pi/dist/session/tools.js.map +1 -0
  358. package/node_modules/remote-pi/dist/session/wizard.d.ts +13 -0
  359. package/node_modules/remote-pi/dist/session/wizard.js +20 -0
  360. package/node_modules/remote-pi/dist/session/wizard.js.map +1 -0
  361. package/node_modules/remote-pi/dist/settings.d.ts +15 -0
  362. package/node_modules/remote-pi/dist/settings.js +52 -0
  363. package/node_modules/remote-pi/dist/settings.js.map +1 -0
  364. package/node_modules/remote-pi/dist/transport/peer_channel.d.ts +37 -0
  365. package/node_modules/remote-pi/dist/transport/peer_channel.js +98 -0
  366. package/node_modules/remote-pi/dist/transport/peer_channel.js.map +1 -0
  367. package/node_modules/remote-pi/dist/transport/pi_forward_client.d.ts +29 -0
  368. package/node_modules/remote-pi/dist/transport/pi_forward_client.js +62 -0
  369. package/node_modules/remote-pi/dist/transport/pi_forward_client.js.map +1 -0
  370. package/node_modules/remote-pi/dist/transport/relay_client.d.ts +91 -0
  371. package/node_modules/remote-pi/dist/transport/relay_client.js +206 -0
  372. package/node_modules/remote-pi/dist/transport/relay_client.js.map +1 -0
  373. package/node_modules/remote-pi/dist/ui/footer.d.ts +32 -0
  374. package/node_modules/remote-pi/dist/ui/footer.js +34 -0
  375. package/node_modules/remote-pi/dist/ui/footer.js.map +1 -0
  376. package/node_modules/remote-pi/docs/daemon.md +289 -0
  377. package/node_modules/remote-pi/package.json +88 -0
  378. package/node_modules/remote-pi/service-templates/launchd.plist.template +35 -0
  379. package/node_modules/remote-pi/service-templates/systemd.service.template +19 -0
  380. package/node_modules/remote-pi/service-templates/task-launcher.vbs.template +10 -0
  381. package/node_modules/remote-pi/service-templates/task-scheduler.xml.template +38 -0
  382. package/node_modules/remote-pi/skills/agent-network/SKILL.md +310 -0
  383. package/package.json +25 -10
  384. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool-diff/write-display-utils.ts +0 -29
  385. /package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/{session-reference-core.ts → reference/session.ts} +0 -0
  386. /package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/{pi-aliases.ts → shell/aliases.ts} +0 -0
  387. /package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-diff → tool/diff}/ATTRIBUTION.md +0 -0
  388. /package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-diff → tool/diff}/diff-presentation.ts +0 -0
  389. /package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-diff → tool/diff}/index.ts +0 -0
  390. /package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-diff → tool/diff}/render-utils.ts +0 -0
  391. /package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-diff → tool/diff}/shiki-highlight.ts +0 -0
  392. /package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-diff → tool/diff}/types.ts +0 -0
@@ -1,21 +1,22 @@
1
1
  import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
2
- import { ToolExecutionComponent } from "@earendil-works/pi-coding-agent";
3
- import { Text, truncateToWidth, visibleWidth } from "@earendil-works/pi-tui";
4
2
  import type { CompactThinkingController } from "../feature/compact-thinking.ts";
5
- import { installToolGrouping, type ToolGroupingHooks } from "./tool-grouping.ts";
3
+ import { installToolGrouping, type ToolGroupingHooks } from "./tool/grouping.ts";
6
4
  import {
7
5
  installCompactMode,
8
6
  refreshCompactModeComponents,
9
7
  type CompactModeHooks,
8
+ type CompactThinkingQuery,
10
9
  } from "./compact-mode.ts";
10
+ import {
11
+ installDefaultMode,
12
+ installToolExpandedBackground,
13
+ type DefaultModeHooks,
14
+ } from "./default-mode.ts";
11
15
  import { isLazyProxyTui } from "../utils/fullscreen-detect.ts";
12
16
  import { showCcstylePanel } from "../config/panel.ts";
13
17
  import {
14
18
  config,
15
- DEFAULT_CONFIG,
16
19
  formatConfigStatus,
17
- getCompactThinkingConfig,
18
- getToolDisplayConfig,
19
20
  normalizeConfig,
20
21
  saveConfig,
21
22
  setConfig,
@@ -24,73 +25,46 @@ import {
24
25
  } from "../config/config.ts";
25
26
  import {
26
27
  installToolMouseInteraction,
27
- isToolCallHovered,
28
28
  resetToolHoverState,
29
29
  scheduleSessionRender,
30
30
  setHoveredToolGroup,
31
31
  setHoveredToolIo,
32
32
  teardownToolMouseInteraction,
33
- toolMouseTui,
34
33
  TOOL_MOUSE_DISABLE,
35
- } from "./mouse-interaction.ts";
36
- import {
37
- clearAllAnimations,
38
- countLines,
39
- hasExpandableDetail,
40
- headTruncateToWidth,
41
- insetComponent,
42
- isToolExpanded,
43
- middleTruncateToWidth,
44
- oneLine,
45
- outputLineCount,
46
- pendingIcon,
47
- renderCollapsedToolResultToWidth,
48
- renderExpandedToolResult,
49
- resolveToolVisualState,
50
- scheduleAnimation,
51
- settledIcon,
52
- setToolVisualState,
53
- textFromResult,
54
- toolIconColor,
55
- toolViewportWidth,
56
- } from "./tool-result.ts";
57
- import { showMoreHintText } from "./show-more-hint.ts";
58
- import type { CompactThinkingQuery } from "./compact-mode.ts";
59
- import {
60
- installWriteOverride,
61
- renderRichToolResult,
62
- WriteExecutionMetadataStore,
63
- } from "./tool-diff/index.ts";
34
+ } from "./mouse/interaction.ts";
35
+ import { getToolMouseTui } from "./mouse/scroll.ts";
36
+ import { clearAllAnimations } from "./tool/result.ts";
37
+ import { installWriteOverride, WriteExecutionMetadataStore } from "./tool/diff/index.ts";
64
38
  import {
65
- getMessageDisplayTheme,
66
39
  installMessageDisplayRendering,
67
40
  refreshMessageDisplays,
68
41
  setMessageDisplayTheme,
69
42
  } from "./message-display.ts";
70
43
 
71
44
  /**
72
- * Claude Code Style for pi — 装配入口(拆分后位于 ccstyle/index.ts)。
45
+ * Claude Code Style for pi — 装配入口。
73
46
  *
74
- * Tool rendering (summaries, rich edit/write diffs, expand/collapse) is applied
75
- * via prototype-level patches.
47
+ * mode=on → default-mode(工具卡样式 + 展开背景)
48
+ * mode=compact → compact-mode(消息折叠摘要)
49
+ * 共用 → tool-grouping / message-display / mouse / write override
76
50
  */
77
- // Bright green for success icon (truecolor ANSI escape)
78
- const BRIGHT_GREEN = "\x1b[38;2;80;220;100m";
79
- const ANSI_FG_RESET = "\x1b[39m";
51
+
52
+ const GLOBAL_COMPACTION_RENDER_PATCH = Symbol.for("pi.ccstyle.compaction-render-patch");
53
+
54
+ let compactModeHooks: CompactModeHooks | undefined;
80
55
 
81
56
  function refreshCurrentTranscript(ctx?: any, toolGrouping?: ToolGroupingHooks): void {
82
- toolGrouping?.refresh(toolMouseTui);
83
- refreshMessageDisplays(toolMouseTui);
84
- refreshCompactModeComponents(toolMouseTui);
57
+ const tui = getToolMouseTui();
58
+ toolGrouping?.refresh(tui);
59
+ refreshMessageDisplays(tui);
60
+ refreshCompactModeComponents(tui);
85
61
  compactModeHooks?.refresh();
86
- toolMouseTui?.requestRender?.(true);
62
+ tui?.requestRender?.(true);
87
63
  ctx?.ui?.requestRender?.(true);
88
64
  }
89
65
 
90
- let compactModeHooks: CompactModeHooks | undefined;
91
-
92
66
  function syncCompactMode(ctx: any): void {
93
- refreshCompactModeComponents(toolMouseTui);
67
+ refreshCompactModeComponents(getToolMouseTui());
94
68
  compactModeHooks?.sync(ctx);
95
69
  }
96
70
 
@@ -98,708 +72,30 @@ function applyStyleMode(mode: CompactStyleMode, ctx: any, toolGrouping?: ToolGro
98
72
  config.mode = mode;
99
73
  saveConfig();
100
74
  if (mode === "off") {
101
- // Native rendering mode: drop hover/click state and fully disable mouse
102
- // reporting so the terminal restores its default scrollback wheel scrolling.
75
+ // Native rendering:清 hover/click,关闭鼠标上报以恢复终端默认滚轮。
103
76
  resetToolHoverState();
104
77
  setHoveredToolGroup(null);
105
78
  setHoveredToolIo(null, null);
106
79
  // 惰性 Proxy(regular/fullscreen)不持有 reporting:regular 保终端回滚,
107
80
  // fullscreen 归官方所有,均不能在此关闭。
108
- if (toolMouseTui && !isLazyProxyTui(toolMouseTui)) {
109
- toolMouseTui.terminal?.write?.(TOOL_MOUSE_DISABLE);
81
+ const tui = getToolMouseTui();
82
+ if (tui && !isLazyProxyTui(tui)) {
83
+ tui.terminal?.write?.(TOOL_MOUSE_DISABLE);
110
84
  }
111
85
  } else if (mode === "compact") {
112
86
  // 切入 compact:先收集当前 transcript,再同步全局展开状态和补丁所有权。
113
87
  syncCompactMode(ctx);
114
88
  }
89
+ // 立即重塑一次;再延迟一帧(与 session_start 同款),等面板/custom
90
+ // 卸下、主 transcript 重新挂载后再扫树,避免必须 /reload。
115
91
  refreshCurrentTranscript(ctx, toolGrouping);
92
+ scheduleSessionRender(() => {
93
+ if (mode === "compact") syncCompactMode(ctx);
94
+ refreshCurrentTranscript(ctx, toolGrouping);
95
+ });
116
96
  ctx.ui.notify(`Claude Code style: ${mode}`, "info");
117
97
  }
118
98
 
119
- function renderDefault(tool: any, slot: "renderCall" | "renderResult", args: any[], fallback = "") {
120
- try {
121
- if (typeof tool?.[slot] === "function") return tool[slot](...args);
122
- } catch {
123
- // Fall through to raw fallback.
124
- }
125
- return new Text(fallback, 0, 0);
126
- }
127
-
128
- function singleLine(text: string) {
129
- return {
130
- render: (width: number) => [truncateToWidth(text, width, "…")],
131
- invalidate() {},
132
- };
133
- }
134
-
135
- function humanizeToolLabel(label: string): string {
136
- return label
137
- .replace(/([a-z0-9])([A-Z])/g, "$1 $2")
138
- .replace(/[_-]+/g, " ")
139
- .replace(/\b\w/g, (char) => char.toUpperCase());
140
- }
141
-
142
- function singleToolCallSummary(
143
- toolName: string,
144
- label: string,
145
- args: any,
146
- ): { main: string; detail: string } {
147
- const title = label === toolName ? humanizeToolLabel(label) : label;
148
- if (!args || typeof args !== "object") return { main: title, detail: "" };
149
- const name = toolName.toLowerCase();
150
- const value = (fallback: string, ...keys: string[]) => {
151
- const found = keys.map((key) => args[key]).find((item) => typeof item === "string" && item);
152
- // 与多 tool 摘要对齐:从头截断,上限 96 字符(tool-grouping oneLine 默认值)。
153
- return `${title} ${oneLine(found || fallback, 96)}`;
154
- };
155
- if (AGENT_FAMILY_TOOL_NAMES.has(toolName) && args.agent_id) {
156
- return { main: `${title} ${oneLine(args.agent_id, 96)}`, detail: "" };
157
- }
158
- // Agents still uses the ccstyle wrapper; Agent keeps its dedicated renderer.
159
- if (name === "agents") {
160
- return {
161
- main: value("launch agents", "description", "prompt"),
162
- detail: "",
163
- };
164
- }
165
- if (name === "skill") return { main: value("run skill", "name"), detail: "" };
166
- if (name === "enterplanmode" || name === "enter_plan_mode") {
167
- return { main: `${title} enable read-only planning`, detail: "" };
168
- }
169
- if (name === "exitplanmode" || name === "exit_plan_mode") {
170
- return { main: `${title} present plan`, detail: "" };
171
- }
172
- if (name === "taskcreate") return { main: value("create task", "subject"), detail: "" };
173
- if (name === "tasklist") return { main: `${title} task list`, detail: "" };
174
- if (name === "taskget" || name === "taskupdate") {
175
- return { main: value("task", "taskId", "task_id"), detail: "" };
176
- }
177
- if (name === "taskoutput" || name === "taskstop") {
178
- return { main: value("background task", "task_id", "taskId"), detail: "" };
179
- }
180
- if (name === "taskexecute") {
181
- const ids = Array.isArray(args.task_ids)
182
- ? args.task_ids
183
- : Array.isArray(args.taskIds)
184
- ? args.taskIds
185
- : [];
186
- const summary = ids.length
187
- ? `${ids[0]}${ids.length > 1 ? ` (+${ids.length - 1} tasks)` : ""}`
188
- : "start tasks";
189
- return { main: `${title} ${summary}`, detail: "" };
190
- }
191
- if (toolName === "read") {
192
- const details = [
193
- args.offset !== undefined ? `offset=${args.offset}` : "",
194
- args.limit !== undefined ? `limit=${args.limit}` : "",
195
- ].filter(Boolean);
196
- return {
197
- main: `${title}${args.path ? ` ${oneLine(args.path, 96)}` : ""}`,
198
- detail: details.length ? ` (${details.join(", ")})` : "",
199
- };
200
- }
201
- const preferred =
202
- args.path ??
203
- args.file_path ??
204
- args.command ??
205
- args.query ??
206
- args.question ??
207
- args.pattern ??
208
- args.url ??
209
- args.name ??
210
- args.tool_use_id ??
211
- args.toolCallId ??
212
- args.id ??
213
- args.message;
214
- return {
215
- main:
216
- preferred !== undefined && preferred !== null && typeof preferred !== "object"
217
- ? `${title} ${oneLine(preferred, 96)}`
218
- : title,
219
- detail: "",
220
- };
221
- }
222
-
223
- export function shouldRenderRichDiff(
224
- mode: CompactStyleMode,
225
- toolName: string,
226
- isError: boolean,
227
- ): boolean {
228
- return mode === "on" && !isError && (toolName === "edit" || toolName === "write");
229
- }
230
-
231
- type ParsedTask = { id: string; status: string; subject: string };
232
-
233
- function parseTaskList(text: string): ParsedTask[] {
234
- return text
235
- .split("\n")
236
- .map((line) => line.match(/^#(\d+) \[([^\]]+)] (.+)$/))
237
- .filter((match): match is RegExpMatchArray => Boolean(match))
238
- .map((match) => ({ id: match[1]!, status: match[2]!, subject: match[3]! }));
239
- }
240
-
241
- function taskListSummary(tasks: ParsedTask[]): string {
242
- const counts = { pending: 0, in_progress: 0, completed: 0 };
243
- for (const task of tasks) {
244
- if (task.status in counts) counts[task.status as keyof typeof counts]++;
245
- }
246
- return [
247
- `${tasks.length} tasks`,
248
- counts.in_progress ? `${counts.in_progress} in progress` : "",
249
- counts.pending ? `${counts.pending} pending` : "",
250
- counts.completed ? `${counts.completed} completed` : "",
251
- ]
252
- .filter(Boolean)
253
- .join(" • ");
254
- }
255
-
256
- function renderExpandedTaskResult(
257
- toolName: string,
258
- text: string,
259
- theme: any,
260
- isError: boolean,
261
- ): any | undefined {
262
- if (isError) return undefined;
263
- if (toolName === "TaskList") {
264
- const tasks = parseTaskList(text);
265
- if (!tasks.length) return undefined;
266
- const limit = Math.max(1, config.expandedPreviewMaxLines);
267
- const rows = tasks.slice(0, limit).map((task) => {
268
- const color =
269
- task.status === "completed"
270
- ? "success"
271
- : task.status === "in_progress"
272
- ? "warning"
273
- : "muted";
274
- return ` ${theme.fg("accent", `#${task.id}`)} ${theme.fg(color, task.status)} ${theme.fg("dim", task.subject)}`;
275
- });
276
- if (tasks.length > rows.length)
277
- rows.push(theme.fg("muted", ` … ${tasks.length - rows.length} more tasks`));
278
- return new Text(` ↳ ${theme.fg("muted", taskListSummary(tasks))}\n${rows.join("\n")}`, 0, 0);
279
- }
280
- const line = text.trim();
281
- if (!line || line.includes("\n")) return undefined;
282
- let formatted: string | undefined;
283
- let match: RegExpMatchArray | null;
284
- if (
285
- toolName === "TaskCreate" &&
286
- (match = line.match(/^Task #(\d+) created successfully: (.+)$/))
287
- ) {
288
- formatted = `${theme.fg("success", "Created task")} ${theme.fg("accent", `#${match[1]}`)} ${theme.fg("muted", match[2])}`;
289
- } else if (toolName === "TaskUpdate" && (match = line.match(/^Updated task #(\d+) (.+)$/))) {
290
- formatted = `${theme.fg("success", "Updated task")} ${theme.fg("accent", `#${match[1]}`)} ${theme.fg("muted", match[2])}`;
291
- } else if (toolName === "TaskExecute") {
292
- formatted = `${theme.fg("success", "Started")} ${theme.fg("muted", line)}`;
293
- } else if (toolName === "TaskStop") {
294
- formatted = `${theme.fg("success", "Stopped")} ${theme.fg("muted", line)}`;
295
- }
296
- return formatted ? new Text(` ↳ ${formatted}`, 0, 0) : undefined;
297
- }
298
-
299
- /** Wrap an arbitrary tool definition with ccstyle call/result rendering. */
300
- function createCcstyleTool(
301
- originalTool: any,
302
- writeExecutionMetadata: WriteExecutionMetadataStore,
303
- ): any {
304
- const toolName = originalTool.name;
305
- const label = isMcpToolDefinition(originalTool, toolName)
306
- ? humanizeMcpToolName(toolName)
307
- : originalTool.label || toolName;
308
-
309
- return {
310
- ...originalTool,
311
- renderShell: "self",
312
- renderCall(args: any, theme: any, context: any) {
313
- if (config.mode !== "on") {
314
- return renderDefault(originalTool, "renderCall", [args, theme, context], String(toolName));
315
- }
316
-
317
- const visualState = resolveToolVisualState(context);
318
- const isPending =
319
- visualState === "pending" ||
320
- (!visualState && (context?.isPartial || context?.executionStarted));
321
- if (isPending) scheduleAnimation(context);
322
- const rawIcon = isPending ? pendingIcon(toolName) : settledIcon(toolName, visualState);
323
- const icon =
324
- visualState === "success"
325
- ? `${BRIGHT_GREEN}${rawIcon}${ANSI_FG_RESET}`
326
- : theme.fg(toolIconColor(context), rawIcon);
327
- const summary = singleToolCallSummary(toolName, label, args);
328
- let cachedWidth: number | undefined;
329
- let cachedLine: string | undefined;
330
- return {
331
- render(width: number) {
332
- if (cachedLine !== undefined && cachedWidth === width) return [cachedLine];
333
- const viewportWidth = toolViewportWidth(width);
334
- const callWidth = Math.max(0, viewportWidth - visibleWidth(icon) - 2);
335
- const mainWidth = Math.max(0, callWidth - visibleWidth(summary.detail));
336
- cachedWidth = width;
337
- // 纯文本先截断再着色(省略号不带 ANSI,避免 reset 破坏卡片背景);从头截断,与多 tool 一致
338
- cachedLine = ` ${icon} ${theme.fg("toolTitle", headTruncateToWidth(summary.main, mainWidth))}${theme.fg("dim", summary.detail)}`;
339
- return [truncateToWidth(cachedLine, viewportWidth, "")];
340
- },
341
- invalidate() {},
342
- };
343
- },
344
- renderResult(result: any, options: any, theme: any, context: any) {
345
- if (config.mode !== "on") {
346
- return renderDefault(
347
- originalTool,
348
- "renderResult",
349
- [result, options, theme, context],
350
- textFromResult(result),
351
- );
352
- }
353
-
354
- if (options?.isPartial) {
355
- return new Text(theme.fg("muted", " ↳ Pending…"), 0, 0);
356
- }
357
-
358
- const isError = options?.isError || context?.isError;
359
- setToolVisualState(context, isError ? "error" : "success");
360
- const expanded = isToolExpanded(options, context);
361
- const toolCallId = context?.toolCallId;
362
- if (shouldRenderRichDiff(config.mode, toolName, Boolean(isError))) {
363
- // Pass getter so Diff indicator / wrap / limits update on the next paint
364
- // without recreating the tool result component.
365
- const richResult = renderRichToolResult(
366
- toolName,
367
- result,
368
- {
369
- ...options,
370
- expanded,
371
- // 全局共享状态避免 /reload 后旧 result renderer 闭包失联。
372
- isHovered: () => isToolCallHovered(toolCallId),
373
- },
374
- theme,
375
- context,
376
- writeExecutionMetadata,
377
- getToolDisplayConfig,
378
- );
379
- if (richResult) return insetComponent(richResult);
380
- }
381
-
382
- const text = textFromResult(result, expanded);
383
- const args = context?.args;
384
- if (expanded) {
385
- const taskResult = renderExpandedTaskResult(toolName, text, theme, Boolean(isError));
386
- if (taskResult) return taskResult;
387
- }
388
- const tasks = !isError && toolName === "TaskList" ? parseTaskList(text) : [];
389
- const outputLines = outputLineCount(result) || countLines(text);
390
- const lineWord = outputLines === 1 ? "line" : "lines";
391
- const action = toolName === "read" ? "loaded" : "returned";
392
- const rendered = tasks.length
393
- ? taskListSummary(tasks)
394
- : isError
395
- ? text
396
- ? oneLine(text)
397
- : "Failed"
398
- : outputLines
399
- ? `${outputLines} ${lineWord} ${action}`
400
- : "Done";
401
- const expandable = !expanded && (tasks.length > 0 || hasExpandableDetail(text, args));
402
- const hintText = showMoreHintText();
403
- const hintPrefix = expandable ? theme.fg("dim", " • ") : "";
404
- const hint = expandable ? hintPrefix + theme.fg("dim", hintText) : "";
405
- const hoveredHint = expandable ? hintPrefix + theme.fg("text", hintText) : "";
406
- if (expanded) {
407
- return renderExpandedToolResult(
408
- text || "",
409
- theme,
410
- Boolean(isError),
411
- context?.lastComponent,
412
- args,
413
- context,
414
- );
415
- }
416
- if (context?.state) context.state.ccstyleIoView = undefined;
417
- let cachedWidth: number | undefined;
418
- let cachedLine: string | undefined;
419
- let cachedHoveredLine: string | undefined;
420
- return {
421
- render(width: number) {
422
- if (cachedLine === undefined || cachedWidth !== width) {
423
- cachedWidth = width;
424
- cachedLine = theme.fg(
425
- isError ? "error" : "muted",
426
- renderCollapsedToolResultToWidth(rendered, hint, width),
427
- );
428
- cachedHoveredLine = theme.fg(
429
- isError ? "error" : "muted",
430
- renderCollapsedToolResultToWidth(rendered, hoveredHint, width),
431
- );
432
- }
433
- return [isToolCallHovered(toolCallId) ? cachedHoveredLine! : cachedLine];
434
- },
435
- invalidate() {},
436
- };
437
- },
438
- };
439
- }
440
-
441
- /**
442
- * Apart from the write override used to capture pre-write content, renderers are
443
- * applied through ToolExecutionComponent. Patch its lookup once so tools use the
444
- * same ccstyle fallback shell by default. Tools named in excludeRenderers keep
445
- * their original renderer.
446
- */
447
- const GLOBAL_TOOL_RENDER_PATCH = Symbol.for("pi.ccstyle.global-tool-render-patch");
448
- const COMPONENT_TOOL_RENDER_MODE = Symbol.for("pi.ccstyle.component-tool-render-mode");
449
- const COMPONENT_TOOL_SELF_SHELL_MODE = Symbol.for("pi.ccstyle.component-tool-self-shell-mode");
450
- const AGENT_FAMILY_TOOL_NAMES = new Set([
451
- "Agent",
452
- "Agents",
453
- "get_subagent_result",
454
- "steer_subagent",
455
- ]);
456
- // pi-subagents 等扩展为 Agent 提供专用渲染器(displayName/运行统计),ccstyle 必须保留,不能 wrap。
457
- const DEDICATED_RENDERER_TOOLS = new Set(["Agent"]);
458
-
459
- type ToolRenderMethods = {
460
- hasRendererDefinition: (...args: any[]) => boolean;
461
- getRenderShell: (...args: any[]) => "default" | "self";
462
- getCallRenderer: (...args: any[]) => any;
463
- getResultRenderer: (...args: any[]) => any;
464
- };
465
-
466
- type GlobalToolRenderPatch = {
467
- version: 2;
468
- prototype: any;
469
- owner: object;
470
- active: boolean;
471
- enabled: () => boolean;
472
- mode: () => CompactStyleMode;
473
- wrap: (tool: any) => any;
474
- byDefinition: WeakMap<object, any>;
475
- byName: Map<string, any>;
476
- downstream: ToolRenderMethods;
477
- installed: ToolRenderMethods;
478
- // Keep the legacy aliases so an older extension build can read this Symbol.
479
- originalHasRendererDefinition: ToolRenderMethods["hasRendererDefinition"];
480
- originalGetRenderShell: ToolRenderMethods["getRenderShell"];
481
- originalGetCallRenderer: ToolRenderMethods["getCallRenderer"];
482
- originalGetResultRenderer: ToolRenderMethods["getResultRenderer"];
483
- };
484
-
485
- export function isMcpToolDefinition(definition: any, toolName: string): boolean {
486
- const label = typeof definition?.label === "string" ? definition.label.trim() : "";
487
- if (/^MCP(?::|$)/i.test(label)) return true;
488
- if (toolName === "mcp" || /^mcp[_:-]|[_:-]mcp[_:-]/i.test(toolName)) return true;
489
- if (label) return false;
490
- const description = typeof definition?.description === "string" ? definition.description : "";
491
- return /\bModel Context Protocol\b/i.test(description);
492
- }
493
-
494
- export function humanizeMcpToolName(toolName: string): string {
495
- const words = toolName
496
- .replace(/^mcp(?:[_:-]+)+/i, "")
497
- .split(/[_:-]+/)
498
- .filter(Boolean);
499
- return words.length
500
- ? words.map((word) => word[0]!.toUpperCase() + word.slice(1)).join(" ")
501
- : "MCP";
502
- }
503
-
504
- /** Return true when this tool must keep its original renderer. */
505
- export function preservesOriginalRenderer(
506
- extensionDefinition: any,
507
- toolName: string,
508
- builtInToolDefinition?: any,
509
- excludeRenderers: readonly string[] = config.excludeRenderers,
510
- ): boolean {
511
- if (!excludeRenderers.includes(toolName)) return false;
512
- return [extensionDefinition, builtInToolDefinition].some(
513
- (definition) =>
514
- definition?.renderShell === "self" ||
515
- typeof definition?.renderCall === "function" ||
516
- typeof definition?.renderResult === "function",
517
- );
518
- }
519
-
520
- function syncToolShell(component: any, shell: "default" | "self"): void {
521
- const target = shell === "self" ? component.selfRenderContainer : component.contentBox;
522
- if (!target || !Array.isArray(component.children)) return;
523
- const candidates = new Set(
524
- [component.contentText, component.contentBox, component.selfRenderContainer].filter(Boolean),
525
- );
526
- const indexes = component.children
527
- .map((child: any, index: number) => (candidates.has(child) ? index : -1))
528
- .filter((index: number) => index >= 0);
529
- const targetIndex = indexes[0];
530
- // During construction getRenderShell() runs immediately before Pi mounts the
531
- // selected shell. Do not mount it here or the constructor will add it twice.
532
- if (targetIndex === undefined) return;
533
- component.children[targetIndex] = target;
534
- for (const index of indexes.sort((left: number, right: number) => right - left)) {
535
- if (index !== targetIndex) component.children.splice(index, 1);
536
- }
537
- }
538
-
539
- function shouldGloballyStyleTool(component: any, patch: GlobalToolRenderPatch): boolean {
540
- const extensionDefinition = component.toolDefinition;
541
- const builtInDefinition = component.builtInToolDefinition;
542
- const definition = extensionDefinition ?? builtInDefinition;
543
- const toolName = String(component.toolName || definition?.name || "");
544
- const useCcstyle =
545
- patch.mode() === "on" &&
546
- !DEDICATED_RENDERER_TOOLS.has(toolName) &&
547
- !preservesOriginalRenderer(extensionDefinition, toolName, builtInDefinition);
548
- component[COMPONENT_TOOL_RENDER_MODE] = useCcstyle;
549
- return useCcstyle;
550
- }
551
-
552
- function shouldUseSelfShell(component: any, _patch: GlobalToolRenderPatch): boolean {
553
- component[COMPONENT_TOOL_SELF_SHELL_MODE] = false;
554
- return false;
555
- }
556
-
557
- function getGloballyStyledTool(component: any, patch: GlobalToolRenderPatch): any {
558
- const definition = component.toolDefinition ?? component.builtInToolDefinition;
559
- if (definition && typeof definition === "object") {
560
- let wrapped = patch.byDefinition.get(definition);
561
- if (!wrapped) {
562
- wrapped = patch.wrap(definition);
563
- patch.byDefinition.set(definition, wrapped);
564
- }
565
- return wrapped;
566
- }
567
-
568
- const name = String(component.toolName || "tool");
569
- let wrapped = patch.byName.get(name);
570
- if (!wrapped) {
571
- wrapped = patch.wrap({ name, label: name });
572
- patch.byName.set(name, wrapped);
573
- }
574
- return wrapped;
575
- }
576
-
577
- function prototypeToolRenderMethods(prototype: any): ToolRenderMethods {
578
- return {
579
- hasRendererDefinition: prototype.hasRendererDefinition,
580
- getRenderShell: prototype.getRenderShell,
581
- getCallRenderer: prototype.getCallRenderer,
582
- getResultRenderer: prototype.getResultRenderer,
583
- };
584
- }
585
-
586
- function isOwnershipAwarePatch(value: any): value is GlobalToolRenderPatch {
587
- if (!value || value.version !== 2 || !value.installed || !value.downstream) return false;
588
- return ["hasRendererDefinition", "getRenderShell", "getCallRenderer", "getResultRenderer"].every(
589
- (name) =>
590
- typeof value.installed[name] === "function" && typeof value.downstream[name] === "function",
591
- );
592
- }
593
-
594
- function isLegacyInstalledWrapper(method: unknown, downstreamField: string): boolean {
595
- if (typeof method !== "function") return false;
596
- try {
597
- const source = Function.prototype.toString.call(method);
598
- return (
599
- source.includes(downstreamField) &&
600
- (source.includes("shouldGloballyStyleTool") ||
601
- source.includes("shouldUseSelfShell") ||
602
- source.includes("getGloballyStyledTool"))
603
- );
604
- } catch {
605
- return false;
606
- }
607
- }
608
-
609
- function downstreamForGlobalToolInstall(prototype: any, previous: any): ToolRenderMethods {
610
- const current = prototypeToolRenderMethods(prototype);
611
- if (!previous || previous.prototype !== prototype) return current;
612
- if (isOwnershipAwarePatch(previous)) {
613
- return {
614
- hasRendererDefinition:
615
- current.hasRendererDefinition === previous.installed.hasRendererDefinition
616
- ? previous.downstream.hasRendererDefinition
617
- : current.hasRendererDefinition,
618
- getRenderShell:
619
- current.getRenderShell === previous.installed.getRenderShell
620
- ? previous.downstream.getRenderShell
621
- : current.getRenderShell,
622
- getCallRenderer:
623
- current.getCallRenderer === previous.installed.getCallRenderer
624
- ? previous.downstream.getCallRenderer
625
- : current.getCallRenderer,
626
- getResultRenderer:
627
- current.getResultRenderer === previous.installed.getResultRenderer
628
- ? previous.downstream.getResultRenderer
629
- : current.getResultRenderer,
630
- };
631
- }
632
-
633
- // Pre-v2 Symbol state did not retain wrapper references. Recognize its known
634
- // wrappers when possible; otherwise preserve the current method as external.
635
- const legacyDownstream = (method: Function, field: string): Function => {
636
- const saved = previous[field];
637
- return typeof saved === "function" && isLegacyInstalledWrapper(method, field) ? saved : method;
638
- };
639
- return {
640
- hasRendererDefinition: legacyDownstream(
641
- current.hasRendererDefinition,
642
- "originalHasRendererDefinition",
643
- ) as ToolRenderMethods["hasRendererDefinition"],
644
- getRenderShell: legacyDownstream(
645
- current.getRenderShell,
646
- "originalGetRenderShell",
647
- ) as ToolRenderMethods["getRenderShell"],
648
- getCallRenderer: legacyDownstream(
649
- current.getCallRenderer,
650
- "originalGetCallRenderer",
651
- ) as ToolRenderMethods["getCallRenderer"],
652
- getResultRenderer: legacyDownstream(
653
- current.getResultRenderer,
654
- "originalGetResultRenderer",
655
- ) as ToolRenderMethods["getResultRenderer"],
656
- };
657
- }
658
-
659
- function disconnectGlobalToolRenderPatch(patch: any): void {
660
- if (!patch || typeof patch !== "object") return;
661
- patch.active = false;
662
- patch.enabled = () => false;
663
- patch.mode = () => "off";
664
- patch.wrap = (tool: any) => tool;
665
- patch.byDefinition = new WeakMap();
666
- if (patch.byName && typeof patch.byName.clear === "function") patch.byName.clear();
667
- else patch.byName = new Map();
668
- }
669
-
670
- function installGlobalToolRendering(
671
- writeExecutionMetadata: WriteExecutionMetadataStore,
672
- ): GlobalToolRenderPatch {
673
- const prototype = (ToolExecutionComponent as any).prototype;
674
- const host = globalThis as any;
675
- const previous = host[GLOBAL_TOOL_RENDER_PATCH];
676
- const downstream = downstreamForGlobalToolInstall(prototype, previous);
677
- // Any wrapper retained by an external owner must become a callback-free
678
- // pass-through before the new installation is linked above it.
679
- disconnectGlobalToolRenderPatch(previous);
680
-
681
- const patch: GlobalToolRenderPatch = {
682
- version: 2,
683
- prototype,
684
- owner: {},
685
- active: true,
686
- enabled: () => config.mode === "on",
687
- mode: () => config.mode,
688
- wrap: (tool: any) => createCcstyleTool(tool, writeExecutionMetadata),
689
- byDefinition: new WeakMap(),
690
- byName: new Map(),
691
- downstream,
692
- installed: undefined as any,
693
- originalHasRendererDefinition: downstream.hasRendererDefinition,
694
- originalGetRenderShell: downstream.getRenderShell,
695
- originalGetCallRenderer: downstream.getCallRenderer,
696
- originalGetResultRenderer: downstream.getResultRenderer,
697
- };
698
-
699
- patch.installed = {
700
- hasRendererDefinition: function (this: any, ...args: any[]) {
701
- if (patch.active && shouldGloballyStyleTool(this, patch)) return true;
702
- return patch.downstream.hasRendererDefinition.apply(this, args);
703
- },
704
- getRenderShell: function (this: any, ...args: any[]) {
705
- if (!patch.active) return patch.downstream.getRenderShell.apply(this, args);
706
- const useSelfShell = shouldUseSelfShell(this, patch);
707
- const useCcstyle = shouldGloballyStyleTool(this, patch);
708
- const shell =
709
- useSelfShell || (useCcstyle && !this.expanded)
710
- ? "self"
711
- : useCcstyle
712
- ? "default"
713
- : patch.downstream.getRenderShell.apply(this, args);
714
- syncToolShell(this, shell);
715
- return shell;
716
- },
717
- getCallRenderer: function (this: any, ...args: any[]) {
718
- if (patch.active && shouldGloballyStyleTool(this, patch)) {
719
- return getGloballyStyledTool(this, patch).renderCall;
720
- }
721
- return patch.downstream.getCallRenderer.apply(this, args);
722
- },
723
- getResultRenderer: function (this: any, ...args: any[]) {
724
- if (patch.active && shouldGloballyStyleTool(this, patch)) {
725
- return getGloballyStyledTool(this, patch).renderResult;
726
- }
727
- return patch.downstream.getResultRenderer.apply(this, args);
728
- },
729
- };
730
-
731
- prototype.hasRendererDefinition = patch.installed.hasRendererDefinition;
732
- prototype.getRenderShell = patch.installed.getRenderShell;
733
- prototype.getCallRenderer = patch.installed.getCallRenderer;
734
- prototype.getResultRenderer = patch.installed.getResultRenderer;
735
- host[GLOBAL_TOOL_RENDER_PATCH] = patch;
736
- return patch;
737
- }
738
-
739
- function deactivateGlobalToolRendering(patch: GlobalToolRenderPatch): void {
740
- if (!patch.active) return;
741
- disconnectGlobalToolRenderPatch(patch);
742
- const prototype = patch.prototype;
743
- if (prototype.hasRendererDefinition === patch.installed.hasRendererDefinition) {
744
- prototype.hasRendererDefinition = patch.downstream.hasRendererDefinition;
745
- }
746
- if (prototype.getRenderShell === patch.installed.getRenderShell) {
747
- prototype.getRenderShell = patch.downstream.getRenderShell;
748
- }
749
- if (prototype.getCallRenderer === patch.installed.getCallRenderer) {
750
- prototype.getCallRenderer = patch.downstream.getCallRenderer;
751
- }
752
- if (prototype.getResultRenderer === patch.installed.getResultRenderer) {
753
- prototype.getResultRenderer = patch.downstream.getResultRenderer;
754
- }
755
- }
756
-
757
- const GLOBAL_COMPACTION_RENDER_PATCH = Symbol.for("pi.ccstyle.compaction-render-patch");
758
-
759
- const TOOL_EXPANDED_BACKGROUND_PATCH = Symbol.for("pi.ccstyle.tool-expanded-background-patch");
760
-
761
- type ToolExpandedBackgroundPatch = {
762
- active: boolean;
763
- prototype: any;
764
- installed: (...args: any[]) => void;
765
- original: (...args: any[]) => void;
766
- dispose: () => void;
767
- };
768
-
769
- /** 展开面板背景统一为 user message 背景色;折叠行保持原生状态色(由 original 重设)。 */
770
- function installToolExpandedBackground(): () => void {
771
- const host = globalThis as any;
772
- const previous = host[TOOL_EXPANDED_BACKGROUND_PATCH] as ToolExpandedBackgroundPatch | undefined;
773
- if (previous) previous.dispose();
774
- const prototype = ToolExecutionComponent.prototype as unknown as { updateDisplay: () => void };
775
- const original = prototype.updateDisplay;
776
- const patch: ToolExpandedBackgroundPatch = {
777
- active: true,
778
- prototype,
779
- installed: function (this: any) {
780
- original.call(this);
781
- if (!patch.active || config.mode !== "on" || !this.expanded) return;
782
- const theme = getMessageDisplayTheme();
783
- if (!theme?.bg) return;
784
- const box = this.contentBox;
785
- if (box?.setBgFn) box.setBgFn((text: string) => theme.bg("userMessageBg", text));
786
- },
787
- original,
788
- dispose: () => {
789
- patch.active = false;
790
- if (prototype.updateDisplay === patch.installed) {
791
- prototype.updateDisplay = original;
792
- }
793
- if (host[TOOL_EXPANDED_BACKGROUND_PATCH] === patch) {
794
- delete host[TOOL_EXPANDED_BACKGROUND_PATCH];
795
- }
796
- },
797
- };
798
- prototype.updateDisplay = patch.installed;
799
- host[TOOL_EXPANDED_BACKGROUND_PATCH] = patch;
800
- return patch.dispose;
801
- }
802
-
803
99
  type LegacyCompactionRenderPatch = {
804
100
  enabled?: () => boolean;
805
101
  };
@@ -817,25 +113,26 @@ export default function (
817
113
  configOverride?: Partial<Config>,
818
114
  compactThinking?: CompactThinkingController,
819
115
  ) {
820
- // The optional override keeps integration tests independent from the user's global config.
116
+ // 可选 override:集成测试不依赖用户全局配置。
821
117
  if (configOverride) setConfig(normalizeConfig({ ...config, ...configOverride }));
822
118
  const writeExecutionMetadata = new WriteExecutionMetadataStore();
823
119
  const mouseOwner = {};
824
120
  let installation:
825
121
  | {
826
- globalToolRendering: GlobalToolRenderPatch;
122
+ defaultMode: DefaultModeHooks;
827
123
  toolGrouping: ToolGroupingHooks;
828
124
  compactMode: CompactModeHooks;
829
125
  disposeMessageDisplay: () => void;
830
126
  disposeToolExpandedBackground: () => void;
831
127
  }
832
128
  | undefined;
129
+
833
130
  const ensureTuiInstallation = (ctx: any) => {
834
131
  if (ctx?.mode !== "tui" || !ctx?.hasUI) return undefined;
835
132
  // 渲染层(工具样式/分组)是原型与组件级 patch,fullscreen 官方布局
836
133
  // 同样渲染这些组件,因此两种模式都安装。
837
134
  if (installation) return installation;
838
- const globalToolRendering = installGlobalToolRendering(writeExecutionMetadata);
135
+ const defaultMode = installDefaultMode(writeExecutionMetadata);
839
136
  const toolGrouping = installToolGrouping(() => config.mode === "on");
840
137
  const compactMode = installCompactMode({
841
138
  query: compactThinking as CompactThinkingQuery | undefined,
@@ -843,10 +140,11 @@ export default function (
843
140
  });
844
141
  compactModeHooks = compactMode;
845
142
  const disposeMessageDisplay = installMessageDisplayRendering();
143
+ // 展开背景必须在 compact-mode 之后装,shutdown 时先于 compact 释放。
846
144
  const disposeToolExpandedBackground = installToolExpandedBackground();
847
145
  deactivateLegacyCompactionRendering();
848
146
  installation = {
849
- globalToolRendering,
147
+ defaultMode,
850
148
  toolGrouping,
851
149
  compactMode,
852
150
  disposeMessageDisplay,
@@ -910,15 +208,14 @@ export default function (
910
208
 
911
209
  pi.on("tool_execution_end", async (event) => {
912
210
  if (config.mode !== "compact") return;
913
- // Agent 工具在 tool_execution_end 收尾思考:延迟到所有监听器之后刷新,
914
- // 让 compact-thinking 先写入最终时长,再重绘摘要行。
211
+ // Agent 等工具收尾后延迟刷新,让 compact-thinking 先落最终态。
915
212
  const toolCallId: string | undefined = event?.toolCallId;
916
213
  setTimeout(() => {
917
214
  compactModeHooks?.refreshToolCallMessage(toolCallId);
918
215
  }, 0);
919
216
  });
920
217
 
921
- pi.on("session_start", async (event, ctx) => {
218
+ pi.on("session_start", async (_event, ctx) => {
922
219
  // 延迟到 session_start 注册 write override:加载阶段 getAllTools 不可用且其他扩展
923
220
  // 尚未注册工具,无法检测外部 write 所有者(如 pi-spark),直接注册会与对方撞名。
924
221
  // session_start 时所有扩展已加载完毕,installWriteOverride 内部会检测并让位。
@@ -936,10 +233,10 @@ export default function (
936
233
  // compact-thinking 的 session_start 处理在本 handler 之后执行(在其之上再装
937
234
  // 一层 updateContent);延迟再同步一次,保证 compact 补丁最终位于外层。
938
235
  setTimeout(() => syncCompactMode(ctx), 0);
939
- scheduleSessionRender(() => hooks.toolGrouping.refresh(toolMouseTui));
236
+ scheduleSessionRender(() => hooks.toolGrouping.refresh(getToolMouseTui()));
940
237
  });
941
238
 
942
- pi.on("session_compact", async (event, ctx) => {
239
+ pi.on("session_compact", async (_event, ctx) => {
943
240
  const hooks = ensureTuiInstallation(ctx);
944
241
  // Compaction rebuilds the transcript without session_start. Rebind after
945
242
  // other TUI extensions may have replaced the root input dispatcher.
@@ -950,34 +247,35 @@ export default function (
950
247
  syncCompactMode(ctx);
951
248
  scheduleSessionRender(() => {
952
249
  syncCompactMode(ctx);
953
- hooks.toolGrouping.refresh(toolMouseTui);
250
+ hooks.toolGrouping.refresh(getToolMouseTui());
954
251
  });
955
252
  });
956
253
 
957
- pi.on("session_tree", async (event, ctx) => {
254
+ pi.on("session_tree", async (_event, ctx) => {
958
255
  // 会话树重建后在当前帧和下一帧各同步一次,替换旧组件引用。
959
256
  if (ctx?.mode !== "tui" || !ctx?.hasUI) return;
960
257
  syncCompactMode(ctx);
961
258
  scheduleSessionRender(() => syncCompactMode(ctx));
962
259
  });
963
260
 
964
- pi.on("tool_execution_start", async (event, ctx) => {
261
+ pi.on("tool_execution_start", async (_event, ctx) => {
965
262
  installation?.toolGrouping.setTheme(ctx.ui.theme);
966
263
  });
967
264
 
968
- pi.on("session_shutdown", async (event, ctx) => {
265
+ pi.on("session_shutdown", async () => {
969
266
  writeExecutionMetadata.clear();
970
267
  // 鼠标交互独立于渲染层:fullscreen 下 installation 为 undefined,
971
268
  // 但 onTerminalInput 监听与 handleViewportInput 包装仍需释放。
972
269
  teardownToolMouseInteraction(mouseOwner);
973
270
  const current = installation;
974
- if (
975
- !current ||
976
- (globalThis as any)[GLOBAL_TOOL_RENDER_PATCH] !== current.globalToolRendering ||
977
- !current.globalToolRendering.active
978
- )
271
+ if (!current) return;
272
+ if (!current.defaultMode.isOwner()) {
273
+ // Replacement installers already disposed these owner-aware patches.
274
+ // Drop only this stale runtime's closure; global teardown belongs to the owner.
275
+ installation = undefined;
979
276
  return;
980
- deactivateGlobalToolRendering(current.globalToolRendering);
277
+ }
278
+ current.defaultMode.shutdown();
981
279
  current.toolGrouping.shutdown();
982
280
  current.disposeToolExpandedBackground();
983
281
  current.compactMode.shutdown();
@@ -989,26 +287,18 @@ export default function (
989
287
  });
990
288
  }
991
289
 
992
- // ---- 对外导出:保持与拆分前 claude-code-style.ts 完全一致的符号集合 ----
290
+ // ---- 对外导出:入口/测试实际消费的符号 ----
291
+ export { getCompactThinkingConfig } from "../config/config.ts";
993
292
  export {
994
- DEFAULT_CONFIG,
995
- formatConfigStatus,
996
- getCompactThinkingConfig,
997
- getToolDisplayConfig,
998
- normalizeConfig,
999
- } from "../config/config.ts";
1000
- export type { CompactStyleMode, Config } from "../config/config.ts";
293
+ humanizeMcpToolName,
294
+ isMcpToolDefinition,
295
+ preservesOriginalRenderer,
296
+ shouldRenderRichDiff,
297
+ } from "./default-mode.ts";
1001
298
  export {
1002
299
  ExpandedToolIoView,
1003
300
  ExpandedToolResultText,
1004
- formatExpandHint,
1005
301
  formatToolInputArgs,
1006
- headTruncateToWidth,
1007
- middleTruncateToWidth,
1008
- outputLineCount,
1009
- renderCollapsedToolResult,
1010
- renderCollapsedToolResultToWidth,
1011
302
  SHOW_MORE_LABEL,
1012
- } from "./tool-result.ts";
1013
- export type { ToolIoSection } from "./tool-result.ts";
1014
- export { installToolMouseInteraction } from "./mouse-interaction.ts";
303
+ } from "./tool/result.ts";
304
+ export { installToolMouseInteraction } from "./mouse/interaction.ts";