@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
@@ -102,14 +102,11 @@ function trimUrl(url: string): string {
102
102
  function linkifyUrls(markdown: string): string {
103
103
  const lines = markdown.split("\n");
104
104
  const out: string[] = [];
105
- let inFence = false;
105
+ let fence: MarkdownFence | undefined;
106
106
  for (const line of lines) {
107
- if (/^```/.test(line)) {
108
- inFence = !inFence;
109
- out.push(line);
110
- continue;
111
- }
112
- if (inFence) {
107
+ const scanned = scanMarkdownFence(line, fence);
108
+ fence = scanned.fence;
109
+ if (scanned.protected) {
113
110
  out.push(line);
114
111
  continue;
115
112
  }
@@ -141,6 +138,7 @@ const CODE_FENCE_OPEN = /^ {0,3}(`{3,}|~{3,})/;
141
138
  const CODE_FENCE_CLOSE = /^ {0,3}(`+|~+)[ \t]*$/;
142
139
 
143
140
  type FenceLine = { blockquoteDepth: number; content: string };
141
+ type MarkdownFence = { marker: string; blockquoteDepth: number };
144
142
 
145
143
  function parseFenceLine(line: string): FenceLine {
146
144
  let content = line;
@@ -152,6 +150,26 @@ function parseFenceLine(line: string): FenceLine {
152
150
  return { blockquoteDepth, content };
153
151
  }
154
152
 
153
+ function scanMarkdownFence(
154
+ line: string,
155
+ fence: MarkdownFence | undefined,
156
+ ): { protected: boolean; fence: MarkdownFence | undefined } {
157
+ const parsed = parseFenceLine(line);
158
+ if (fence && parsed.blockquoteDepth >= fence.blockquoteDepth) {
159
+ const close = parsed.content.match(CODE_FENCE_CLOSE)?.[1];
160
+ const closed =
161
+ parsed.blockquoteDepth === fence.blockquoteDepth &&
162
+ close?.[0] === fence.marker[0] &&
163
+ close.length >= fence.marker.length;
164
+ return { protected: true, fence: closed ? undefined : fence };
165
+ }
166
+ const marker = parsed.content.match(CODE_FENCE_OPEN)?.[1];
167
+ return {
168
+ protected: Boolean(marker),
169
+ fence: marker ? { marker, blockquoteDepth: parsed.blockquoteDepth } : undefined,
170
+ };
171
+ }
172
+
155
173
  function replaceCircled(text: string): string {
156
174
  return text.replace(CIRCLED_RE, (ch) => `(${ch.codePointAt(0)! - 0x2460 + 1})`);
157
175
  }
@@ -205,7 +223,7 @@ function deCircledProse(prose: string): string {
205
223
  function deCircled(markdown: string): string {
206
224
  const output: string[] = [];
207
225
  let prose: string[] = [];
208
- let fence: { marker: string; blockquoteDepth: number } | undefined;
226
+ let fence: MarkdownFence | undefined;
209
227
  const flushProse = () => {
210
228
  if (prose.length === 0) return;
211
229
  output.push(deCircledProse(prose.join("\n")));
@@ -213,30 +231,15 @@ function deCircled(markdown: string): string {
213
231
  };
214
232
 
215
233
  for (const line of markdown.split("\n")) {
216
- const parsed = parseFenceLine(line);
217
- if (fence && parsed.blockquoteDepth >= fence.blockquoteDepth) {
218
- output.push(line);
219
- const close = parsed.content.match(CODE_FENCE_CLOSE)?.[1];
220
- if (
221
- parsed.blockquoteDepth === fence.blockquoteDepth &&
222
- close?.[0] === fence.marker[0] &&
223
- close.length >= fence.marker.length
224
- ) {
225
- fence = undefined;
226
- }
227
- continue;
228
- }
229
- fence = undefined;
230
-
231
- if (parsed.content.trim() === "") {
234
+ const scanned = scanMarkdownFence(line, fence);
235
+ fence = scanned.fence;
236
+ if (scanned.protected) {
232
237
  flushProse();
233
238
  output.push(line);
234
239
  continue;
235
240
  }
236
- const open = parsed.content.match(CODE_FENCE_OPEN)?.[1];
237
- if (open) {
241
+ if (parseFenceLine(line).content.trim() === "") {
238
242
  flushProse();
239
- fence = { marker: open, blockquoteDepth: parsed.blockquoteDepth };
240
243
  output.push(line);
241
244
  continue;
242
245
  }
@@ -331,17 +334,18 @@ function renderDiagrams(
331
334
  function renderAdmonitions(markdown: string): string {
332
335
  const lines = markdown.split("\n");
333
336
  const out: string[] = [];
334
- let inFence = false;
337
+ let fence: MarkdownFence | undefined;
335
338
  let i = 0;
336
339
  while (i < lines.length) {
337
340
  const line = lines[i];
338
- if (/^```/.test(line)) {
339
- inFence = !inFence;
341
+ const scanned = scanMarkdownFence(line, fence);
342
+ fence = scanned.fence;
343
+ if (scanned.protected) {
340
344
  out.push(line);
341
345
  i++;
342
346
  continue;
343
347
  }
344
- if (!inFence && /^>\s*\[\s*!/i.test(line)) {
348
+ if (/^>\s*\[\s*!/i.test(line)) {
345
349
  const result = renderAdmonition(lines, i);
346
350
  if (result) {
347
351
  out.push(...result.output);
@@ -1,13 +1,13 @@
1
- import { setHoveredCompactAssistant } from "./compact-mode.ts";
1
+ import { setHoveredCompactAssistant } from "../compact-mode.ts";
2
2
  import {
3
3
  isExpandedToolIoView,
4
4
  invalidateIoView,
5
5
  type ExpandedToolIoView,
6
6
  type ToolIoSection,
7
- } from "./tool-result.ts";
8
- import type { ToolGroupComponent } from "./tool-grouping.ts";
9
- import { componentAtLocalRow, type ComponentRowHit } from "./mouse-layout.ts";
10
- import { setScrollButtonHovered } from "./mouse-scroll.ts";
7
+ } from "../tool/result.ts";
8
+ import type { ToolGroupComponent } from "../tool/grouping.ts";
9
+ import { componentAtLocalRow, type ComponentRowHit } from "./layout.ts";
10
+ import { setScrollButtonHovered } from "./scroll.ts";
11
11
 
12
12
  const TOOL_HOVER_STATE_KEY = Symbol.for("pi.ccstyle.tool-hover-state");
13
13
 
@@ -1,9 +1,9 @@
1
- import { hasActiveTextPreview, showTextPreview } from "../feature/context.ts";
2
- import { ToolGroupComponent } from "./tool-grouping.ts";
3
- import { isCompactAssistantComponent, setHoveredCompactAssistant } from "./compact-mode.ts";
4
- import { config } from "../config/config.ts";
5
- import { isLazyProxyTui } from "../utils/fullscreen-detect.ts";
6
- import { setToolTuiFullscreen } from "./show-more-hint.ts";
1
+ import { hasActiveTextPreview, showTextPreview } from "../../feature/context.ts";
2
+ import { ToolGroupComponent } from "../tool/grouping.ts";
3
+ import { isCompactAssistantComponent, setHoveredCompactAssistant } from "../compact-mode.ts";
4
+ import { config } from "../../config/config.ts";
5
+ import { isLazyProxyTui } from "../../utils/fullscreen-detect.ts";
6
+ import { setToolTuiFullscreen } from "../show-more-hint.ts";
7
7
  import {
8
8
  type ExpandedToolIoView,
9
9
  getActiveIoViewFrame,
@@ -11,7 +11,7 @@ import {
11
11
  type IoViewFrameState,
12
12
  setActiveIoViewFrame,
13
13
  type ToolIoSection,
14
- } from "./tool-result.ts";
14
+ } from "../tool/result.ts";
15
15
  import {
16
16
  collectToolComponents,
17
17
  extractToolFramePlacements,
@@ -23,7 +23,7 @@ import {
23
23
  toolFrameMarker,
24
24
  type FrameToolPlacement,
25
25
  type SgrMousePacket,
26
- } from "./mouse-packets.ts";
26
+ } from "./packets.ts";
27
27
  import {
28
28
  collectFullscreenToolCards,
29
29
  componentAtLocalRow,
@@ -31,7 +31,7 @@ import {
31
31
  fullscreenContentWidth,
32
32
  fullscreenLeafAt,
33
33
  isScrollbarColumnAt,
34
- } from "./mouse-layout.ts";
34
+ } from "./layout.ts";
35
35
  import {
36
36
  fullscreenLazyTui,
37
37
  hideScrollButton,
@@ -43,12 +43,12 @@ import {
43
43
  setScrollButtonVisible,
44
44
  setScrollButtonWidget,
45
45
  setToolMouseTui,
46
- scrollButtonVisible,
47
- scrollButtonWidget,
46
+ getScrollButtonVisible,
47
+ getScrollButtonWidget,
48
+ getToolMouseTui,
48
49
  toolMouseInteractionActive,
49
- toolMouseTui,
50
50
  updateScrollButtonFromInput,
51
- } from "./mouse-scroll.ts";
51
+ } from "./scroll.ts";
52
52
  import {
53
53
  applyFullscreenHover,
54
54
  cachedFullscreenComponentAtRow,
@@ -57,7 +57,7 @@ import {
57
57
  setHoveredToolGroup,
58
58
  setHoveredToolIo,
59
59
  type FullscreenHoverTarget,
60
- } from "./mouse-hover.ts";
60
+ } from "./hover.ts";
61
61
 
62
62
  type FrameToolRender = {
63
63
  component: any;
@@ -264,7 +264,7 @@ function handleFullscreenToolClick(tui: any, packet: SgrMousePacket): boolean {
264
264
  const component = target.component;
265
265
  const card = target.group ?? component;
266
266
  // 回到底部按钮:按组件引用命中,不依赖渲染行缓存。
267
- if (scrollButtonVisible && component === scrollButtonWidget) {
267
+ if (getScrollButtonVisible() && component === getScrollButtonWidget()) {
268
268
  tui.scrollToBottom?.();
269
269
  hideScrollButton(tui);
270
270
  return true;
@@ -338,7 +338,7 @@ function handleFullscreenToolHover(tui: any, packet: SgrMousePacket): void {
338
338
  if (hit) {
339
339
  const line = hit.box.lines?.[hit.localRow];
340
340
  // 回到底部按钮:渲染行文本 + 列区间识别(零组件树开销)。
341
- if (typeof line === "string" && scrollButtonVisible && line.includes("[ ↓")) {
341
+ if (typeof line === "string" && getScrollButtonVisible() && line.includes("[ ↓")) {
342
342
  const plain = stripTerminalSequencesPreservingLayout(line);
343
343
  const idx = plain.indexOf("[ ↓");
344
344
  if (idx >= 0 && x >= idx && x <= idx + plain.length - 1) {
@@ -729,40 +729,40 @@ function patchToolMouseMotionAfterRender(tui: any): void {
729
729
  }
730
730
 
731
731
  function handleToolMouseInput(data: string): { consume: true } | undefined {
732
- if (!toolMouseTui) return undefined;
732
+ if (!getToolMouseTui()) return undefined;
733
733
  // 惰性 Proxy fullscreen:鼠标由 handleViewportInput 包装消费(官方链之前),
734
734
  // 此处只处理键盘(鼠标事件在官方 listener 已被 consume,到不了这里)。
735
- if (fullscreenLazyTui(toolMouseTui)) {
736
- scheduleScrollButtonSync(toolMouseTui, data);
735
+ if (fullscreenLazyTui(getToolMouseTui())) {
736
+ scheduleScrollButtonSync(getToolMouseTui(), data);
737
737
  if (isScrollBottomInput(data)) {
738
- toolMouseTui.scrollToBottom?.();
739
- hideScrollButton(toolMouseTui);
738
+ getToolMouseTui().scrollToBottom?.();
739
+ hideScrollButton(getToolMouseTui());
740
740
  return { consume: true };
741
741
  }
742
742
  return undefined;
743
743
  }
744
- updateScrollButtonFromInput(toolMouseTui, data);
744
+ updateScrollButtonFromInput(getToolMouseTui(), data);
745
745
  // Off mode restores native input: wheel keeps scrolling through Pi's normal
746
746
  // dispatcher, while hover/click affordances are entirely inactive.
747
747
  if (!toolMouseInteractionActive()) return undefined;
748
748
  const packets = parseSgrMousePackets(data);
749
749
  if (!packets) {
750
- scheduleScrollButtonSync(toolMouseTui, data);
750
+ scheduleScrollButtonSync(getToolMouseTui(), data);
751
751
  return undefined;
752
752
  }
753
753
 
754
754
  let consumed = false;
755
755
  for (const packet of packets) {
756
- updateToolSummaryHover(toolMouseTui, packet);
756
+ updateToolSummaryHover(getToolMouseTui(), packet);
757
757
  if (!isSgrLeftPress(packet)) continue;
758
- if (toggleToolAtMouseClick(toolMouseTui, packet)) {
758
+ if (toggleToolAtMouseClick(getToolMouseTui(), packet)) {
759
759
  consumed = true;
760
760
  }
761
761
  }
762
762
 
763
763
  // Let scrolling, motion, release, and clicks outside tool results reach the
764
764
  // normal TUI input chain (including other extensions such as pi-zentui).
765
- scheduleScrollButtonSync(toolMouseTui, data);
765
+ scheduleScrollButtonSync(getToolMouseTui(), data);
766
766
  return consumed ? { consume: true } : undefined;
767
767
  }
768
768
 
@@ -782,8 +782,8 @@ export function teardownToolMouseInteraction(
782
782
  setHoveredToolIo(null, null);
783
783
  setHoveredCompactAssistant(null);
784
784
  try {
785
- if (isLazyProxyTui(toolMouseTui)) releaseFullscreenToolMouseMotion(toolMouseTui);
786
- else toolMouseTui?.terminal?.write?.(TOOL_MOUSE_DISABLE);
785
+ if (isLazyProxyTui(getToolMouseTui())) releaseFullscreenToolMouseMotion(getToolMouseTui());
786
+ else getToolMouseTui()?.terminal?.write?.(TOOL_MOUSE_DISABLE);
787
787
  } catch {
788
788
  // The terminal may already be closed during shutdown.
789
789
  }
@@ -793,7 +793,7 @@ export function teardownToolMouseInteraction(
793
793
  // The UI context may already have been reset during /reload.
794
794
  }
795
795
  restoreToolMouseRenderPatch();
796
- restoreFullscreenViewportInput(toolMouseTui);
796
+ restoreFullscreenViewportInput(getToolMouseTui());
797
797
  resetScrollButtonState();
798
798
  setToolMouseTui(null);
799
799
  toolMouseUi = null;
@@ -807,7 +807,7 @@ export function resetToolHoverState(): void {
807
807
  setHoveredCompactAssistant(null);
808
808
  setScrollButtonVisible(false);
809
809
  setScrollButtonHovered(false);
810
- releaseFullscreenToolMouseMotion(toolMouseTui);
810
+ releaseFullscreenToolMouseMotion(getToolMouseTui());
811
811
  }
812
812
 
813
813
  export function installToolMouseInteraction(
@@ -839,7 +839,7 @@ export function installToolMouseInteraction(
839
839
  },
840
840
  invalidate() {},
841
841
  });
842
- return scrollButtonWidget;
842
+ return getScrollButtonWidget();
843
843
  }
844
844
  // Wrap doRender to capture the live frame for tool click/hover mapping.
845
845
  patchToolMouseMotionAfterRender(tui);
@@ -861,7 +861,7 @@ function refreshToolRendererComponents(tui: any): void {
861
861
  }
862
862
 
863
863
  export function scheduleSessionRender(refresh?: () => void): void {
864
- const tui = toolMouseTui;
864
+ const tui = getToolMouseTui();
865
865
  if (!tui || typeof tui.requestRender !== "function") return;
866
866
  if (sessionRenderTimer) clearTimeout(sessionRenderTimer);
867
867
  // Restored transcripts are populated at different points for startup, reload,
@@ -869,7 +869,7 @@ export function scheduleSessionRender(refresh?: () => void): void {
869
869
  // rebuild finish so messages are not left hidden until the next terminal input.
870
870
  sessionRenderTimer = setTimeout(() => {
871
871
  sessionRenderTimer = null;
872
- if (toolMouseTui !== tui) return;
872
+ if (getToolMouseTui() !== tui) return;
873
873
  patchToolMouseMotionAfterRender(tui);
874
874
  refreshToolRendererComponents(tui);
875
875
  refresh?.();
@@ -877,10 +877,9 @@ export function scheduleSessionRender(refresh?: () => void): void {
877
877
  }, 0);
878
878
  }
879
879
 
880
- export { toolMouseTui } from "./mouse-scroll.ts";
881
880
  export {
882
881
  hoveredToolCallId,
883
882
  isToolCallHovered,
884
883
  setHoveredToolGroup,
885
884
  setHoveredToolIo,
886
- } from "./mouse-hover.ts";
885
+ } from "./hover.ts";
@@ -1,11 +1,8 @@
1
1
  import { visibleWidth } from "@earendil-works/pi-tui";
2
- import { isCompactAssistantComponent } from "./compact-mode.ts";
3
- import { ToolGroupComponent } from "./tool-grouping.ts";
4
- import {
5
- isToolExecutionComponent,
6
- stripTerminalSequencesPreservingLayout,
7
- } from "./mouse-packets.ts";
8
- import { scrollButtonWidget } from "./mouse-scroll.ts";
2
+ import { isCompactAssistantComponent } from "../compact-mode.ts";
3
+ import { ToolGroupComponent } from "../tool/grouping.ts";
4
+ import { isToolExecutionComponent, stripTerminalSequencesPreservingLayout } from "./packets.ts";
5
+ import { getScrollButtonWidget } from "./scroll.ts";
9
6
 
10
7
  export type ComponentRowHit = {
11
8
  component: any;
@@ -14,19 +11,6 @@ export type ComponentRowHit = {
14
11
  group?: ToolGroupComponent;
15
12
  };
16
13
 
17
- /** 深度渲染组件树(容器 render 隐藏时回退 children)。 */
18
- export function renderComponentTree(component: any, width: number): string[] {
19
- if (!component || typeof component !== "object") return [];
20
- try {
21
- const lines = component.render?.(width);
22
- if (Array.isArray(lines) && lines.length > 0) return lines;
23
- } catch {
24
- // Fall through to children for hidden container renderers.
25
- }
26
- if (!Array.isArray(component.children)) return [];
27
- return component.children.flatMap((child: any) => renderComponentTree(child, width));
28
- }
29
-
30
14
  /** 行内 [click to show more] 提示的命中列区间(1-based,含两端)。 */
31
15
  export function collapsedHintHitbox(line: string): { startCol: number; endCol: number } | null {
32
16
  const plain = stripTerminalSequencesPreservingLayout(line);
@@ -113,7 +97,7 @@ export function componentAtLocalRow(
113
97
  // compact 摘要行整体作为可展开卡片(折叠摘要 / 展开内容)。
114
98
  return { component, row: localRow };
115
99
  }
116
- if (component === scrollButtonWidget) {
100
+ if (component === getScrollButtonWidget()) {
117
101
  return { component, row: localRow };
118
102
  }
119
103
  if (!Array.isArray(component.children)) return null;
@@ -1,4 +1,4 @@
1
- import type { ExpandedToolIoView, ToolIoSection } from "./tool-result.ts";
1
+ import type { ExpandedToolIoView, ToolIoSection } from "../tool/result.ts";
2
2
 
3
3
  /** SGR 鼠标协议包(code;col;row + M/m 终结符)。 */
4
4
  export type SgrMousePacket = {
@@ -5,9 +5,9 @@ import {
5
5
  visibleWidth,
6
6
  type Keybinding,
7
7
  } from "@earendil-works/pi-tui";
8
- import { config } from "../config/config.ts";
9
- import { isLazyProxyTui } from "../utils/fullscreen-detect.ts";
10
- import { parseSgrMousePackets } from "./mouse-packets.ts";
8
+ import { config } from "../../config/config.ts";
9
+ import { isLazyProxyTui } from "../../utils/fullscreen-detect.ts";
10
+ import { parseSgrMousePackets } from "./packets.ts";
11
11
 
12
12
  const ZENTUI_PAGE_UP_INPUT = /^\x1b\[5;9(?::[12])?~$|^\x1b\[57421;9(?::[12])?u$|^\x1b\[1;6A$/;
13
13
  const ZENTUI_PAGE_DOWN_INPUT = /^\x1b\[6;9(?::[12])?~$|^\x1b\[57422;9(?::[12])?u$|^\x1b\[1;6B$/;
@@ -16,43 +16,65 @@ const SCROLL_BOTTOM_SHORTCUT = "ctrl+end";
16
16
  /**
17
17
  * 当前安装的 tui 宿主。宿主放本模块(滚动按钮/调度依赖它),
18
18
  * 由 mouse-interaction 经 setToolMouseTui 维护;跨模块一律经绑定/setter 访问。
19
+ *
20
+ * 状态镜像到 globalThis(Symbol 槽):jiti 转译下经 re-export 链读取的
21
+ * 模块级 let 绑定是初始值快照(死绑定,实测恒 null),函数调用才是活引用。
22
+ * 跨模块读取一律用 getToolMouseTui(),避免拿到加载时的快照。
19
23
  */
20
- export let toolMouseTui: any = null;
24
+ const TOOL_MOUSE_TUI_SLOT = Symbol.for("pi.ccstyle.tool-mouse-tui");
25
+ (globalThis as any)[TOOL_MOUSE_TUI_SLOT] ??= null;
26
+ export function getToolMouseTui(): any {
27
+ return (globalThis as any)[TOOL_MOUSE_TUI_SLOT];
28
+ }
21
29
  export function setToolMouseTui(tui: any): void {
22
- toolMouseTui = tui;
30
+ (globalThis as any)[TOOL_MOUSE_TUI_SLOT] = tui;
23
31
  }
24
32
 
25
- export let scrollButtonVisible = false;
26
- export let scrollButtonHovered = false;
27
- export let scrollButtonWidget: any = null;
28
- let scrollButtonSyncScheduled = false;
29
-
33
+ // 滚动按钮状态同 toolMouseTui:镜像到 globalThis(Symbol 槽),跨模块读取
34
+ // 一律用 getter(jiti 转译下模块级 let 绑定是初始值快照)。
35
+ const SCROLL_BUTTON_STATE_SLOT = Symbol.for("pi.ccstyle.scroll-button-state");
36
+ type ScrollButtonState = { visible: boolean; hovered: boolean; widget: any };
37
+ function scrollButtonState(): ScrollButtonState {
38
+ const host = globalThis as any;
39
+ return (host[SCROLL_BUTTON_STATE_SLOT] ??= { visible: false, hovered: false, widget: null });
40
+ }
41
+ export function getScrollButtonVisible(): boolean {
42
+ return scrollButtonState().visible;
43
+ }
44
+ export function getScrollButtonHovered(): boolean {
45
+ return scrollButtonState().hovered;
46
+ }
47
+ export function getScrollButtonWidget(): any {
48
+ return scrollButtonState().widget;
49
+ }
30
50
  export function setScrollButtonVisible(visible: boolean): void {
31
- scrollButtonVisible = visible;
51
+ scrollButtonState().visible = visible;
32
52
  }
33
53
 
34
54
  /** 返回是否发生变化(调用方据此决定是否需要重渲染)。 */
35
55
  export function setScrollButtonHovered(hovered: boolean): boolean {
36
- if (hovered === scrollButtonHovered) return false;
37
- scrollButtonHovered = hovered;
56
+ if (hovered === scrollButtonState().hovered) return false;
57
+ scrollButtonState().hovered = hovered;
38
58
  return true;
39
59
  }
40
60
 
41
61
  export function setScrollButtonWidget(widget: any): void {
42
- scrollButtonWidget = widget;
62
+ scrollButtonState().widget = widget;
43
63
  }
44
64
 
45
65
  /** teardown 全量清零(visible/hovered/widget/sync 调度)。 */
46
66
  export function resetScrollButtonState(): void {
47
- scrollButtonVisible = false;
48
- scrollButtonHovered = false;
49
- scrollButtonWidget = null;
67
+ scrollButtonState().visible = false;
68
+ scrollButtonState().hovered = false;
69
+ scrollButtonState().widget = null;
50
70
  scrollButtonSyncScheduled = false;
51
71
  }
52
72
 
73
+ let scrollButtonSyncScheduled = false;
74
+
53
75
  export function toolMouseInteractionActive(): boolean {
54
76
  if (config.mode === "off") return false;
55
- if (isLazyProxyTui(toolMouseTui)) return true;
77
+ if (isLazyProxyTui(getToolMouseTui())) return true;
56
78
  return true;
57
79
  }
58
80
 
@@ -80,17 +102,6 @@ export function isScrollBottomInput(data: string): boolean {
80
102
  return matchesKey(data, SCROLL_BOTTOM_SHORTCUT);
81
103
  }
82
104
 
83
- function wheelDirection(data: string): "up" | "down" | null {
84
- const packets = parseSgrMousePackets(data);
85
- for (const packet of packets ?? []) {
86
- if (packet.final !== "M") continue;
87
- const baseButton = packet.code & ~(4 | 8 | 16 | 32);
88
- if (baseButton === 64) return "up";
89
- if (baseButton === 65) return "down";
90
- }
91
- return null;
92
- }
93
-
94
105
  function isScrollNavigationInput(data: string): boolean {
95
106
  if (
96
107
  matchesKey(data, "pageUp") ||
@@ -127,9 +138,9 @@ function isAtTranscriptBottom(tui: any): boolean {
127
138
  }
128
139
 
129
140
  export function hideScrollButton(tui: any): void {
130
- const changed = scrollButtonVisible || scrollButtonHovered;
131
- scrollButtonVisible = false;
132
- scrollButtonHovered = false;
141
+ const changed = getScrollButtonVisible() || getScrollButtonHovered();
142
+ setScrollButtonVisible(false);
143
+ setScrollButtonHovered(false);
133
144
  if (changed) tui.requestRender?.();
134
145
  }
135
146
 
@@ -145,7 +156,7 @@ export function scheduleScrollButtonSync(tui: any, data: string): void {
145
156
  const previousLines = tui.previousLines;
146
157
  const check = (attempt: number) => {
147
158
  scrollButtonSyncScheduled = false;
148
- if (toolMouseTui !== tui) return;
159
+ if (getToolMouseTui() !== tui) return;
149
160
  // Pi renders on its own frame timer. Inspect the resulting viewport before
150
161
  // showing the button so empty or non-scrollable transcripts never flash it.
151
162
  const rendered = tui.previousLines !== previousLines;
@@ -159,8 +170,8 @@ export function scheduleScrollButtonSync(tui: any, data: string): void {
159
170
  return;
160
171
  }
161
172
  const nextVisible = !isAtTranscriptBottom(tui);
162
- if (nextVisible !== scrollButtonVisible) {
163
- scrollButtonVisible = nextVisible;
173
+ if (nextVisible !== getScrollButtonVisible()) {
174
+ setScrollButtonVisible(nextVisible);
164
175
  tui.requestRender?.();
165
176
  }
166
177
  };
@@ -173,10 +184,10 @@ export function updateScrollButtonFromInput(tui: any, data: string): void {
173
184
  }
174
185
 
175
186
  export function renderScrollButton(width: number, theme: any): string[] {
176
- if (!scrollButtonVisible || !fullscreenLazyTui(toolMouseTui)) return [];
187
+ if (!getScrollButtonVisible() || !fullscreenLazyTui(getToolMouseTui())) return [];
177
188
  const shortcut = formatShortcut(SCROLL_BOTTOM_SHORTCUT);
178
189
  const label = theme.fg(
179
- scrollButtonHovered ? "text" : "accent",
190
+ getScrollButtonHovered() ? "text" : "accent",
180
191
  `[ ↓ Back to bottom · ${shortcut} ]`,
181
192
  );
182
193
  const leftPad = Math.max(0, Math.floor((width - visibleWidth(label)) / 2));
@@ -1,4 +1,5 @@
1
1
  const ANSI_SGR_PATTERN = /\x1b\[([0-9;]*)m/g;
2
+ const ANSI_SGR_WITH_COLON_PATTERN = /\x1b\[([0-9;:]*)m/g;
2
3
  const STYLE_RESET_PARAMS = [39, 22, 23, 24, 25, 27, 28, 29, 59] as const;
3
4
 
4
5
  export { ANSI_SGR_PATTERN, STYLE_RESET_PARAMS };
@@ -108,6 +109,60 @@ export function filterSgrSequences(text: string, filter: (params: number[]) => n
108
109
  });
109
110
  }
110
111
 
112
+ function isValidColonForeground(segment: string): boolean {
113
+ const params = segment.split(":");
114
+ const isByte = (value: string | undefined) =>
115
+ value !== undefined && /^\d+$/.test(value) && Number(value) <= 255;
116
+ if (params[0] !== "38") return false;
117
+ if (params[1] === "5") return params.length === 3 && isByte(params[2]);
118
+ return (
119
+ params[1] === "2" &&
120
+ params.length === 6 &&
121
+ (params[2] === "" || /^\d+$/.test(params[2] ?? "")) &&
122
+ params.slice(3).every(isByte)
123
+ );
124
+ }
125
+
126
+ function sanitizeColonSgr(rawParams: string): string {
127
+ const segments = rawParams.split(";");
128
+ const sanitized: string[] = [];
129
+ for (let index = 0; index < segments.length; index++) {
130
+ const segment = segments[index] ?? "";
131
+ if (segment.includes(":")) {
132
+ const code = Number.parseInt(segment, 10);
133
+ if (code !== 48 && (code !== 38 || isValidColonForeground(segment))) {
134
+ sanitized.push(segment);
135
+ }
136
+ continue;
137
+ }
138
+ const param = Number.parseInt(segment, 10);
139
+ if (!Number.isFinite(param)) continue;
140
+ if (param === 0) {
141
+ sanitized.push(...STYLE_RESET_PARAMS.map(String));
142
+ continue;
143
+ }
144
+ if (param === 49 || (param >= 40 && param <= 47) || (param >= 100 && param <= 107)) {
145
+ continue;
146
+ }
147
+ if (param === 38 || param === 48) {
148
+ const mode = Number.parseInt(segments[index + 1] ?? "", 10);
149
+ const advance = mode === 5 ? 2 : mode === 2 ? 4 : 0;
150
+ if (advance > 0) {
151
+ if (param === 38) sanitized.push(...segments.slice(index, index + advance + 1));
152
+ index += advance;
153
+ continue;
154
+ }
155
+ }
156
+ sanitized.push(segment);
157
+ }
158
+ return sanitized.length > 0 ? `\x1b[${sanitized.join(";")}m` : "";
159
+ }
160
+
111
161
  export function sanitizeAnsiForThemedOutput(text: string): string {
112
- return filterSgrSequences(text, stripBackgroundSgrParams);
162
+ if (!text || !text.includes("\x1b[")) return text;
163
+ return text.replace(ANSI_SGR_WITH_COLON_PATTERN, (sequence, rawParams: string) =>
164
+ rawParams.includes(":")
165
+ ? sanitizeColonSgr(rawParams)
166
+ : filterSgrSequences(sequence, stripBackgroundSgrParams),
167
+ );
113
168
  }
@@ -30,11 +30,11 @@ import {
30
30
  resolveDiffPresentationMode,
31
31
  type DiffPresentationMode,
32
32
  } from "./diff-presentation.ts";
33
- import { sanitizeToolResultText } from "../../utils/tool-result-sanitize.ts";
33
+ import { sanitizeToolResultText } from "../../../utils/tool-result-sanitize.ts";
34
34
  import { pluralize, sanitizeAnsiForThemedOutput } from "./render-utils.ts";
35
35
  import { splitWriteContentLines } from "./write-display-utils.ts";
36
36
  import { MAX_HL_CHARS, shikiHighlightCache } from "./shiki-highlight.ts";
37
- import { showMoreHintText } from "../show-more-hint.ts";
37
+ import { showMoreHintText } from "../../show-more-hint.ts";
38
38
  import {
39
39
  DEFAULT_TOOL_DISPLAY_CONFIG,
40
40
  type DiffIndicatorMode,
@@ -1,6 +1,6 @@
1
1
  import { normalizeDiffRenderWidth } from "./diff-presentation.ts";
2
2
  import { pluralize } from "./render-utils.ts";
3
- import { showMoreHintText } from "../show-more-hint.ts";
3
+ import { showMoreHintText } from "../../show-more-hint.ts";
4
4
 
5
5
  export interface WidthMeasurementOps {
6
6
  measure(text: string): number;
@@ -0,0 +1,12 @@
1
+ export function splitWriteContentLines(content: string): string[] {
2
+ if (!content) {
3
+ return [];
4
+ }
5
+
6
+ const normalized = content.replace(/\r\n?/g, "\n");
7
+ const lines = normalized.split("\n");
8
+ if (lines.length > 0 && lines[lines.length - 1] === "") {
9
+ lines.pop();
10
+ }
11
+ return lines;
12
+ }
@@ -94,13 +94,12 @@ export async function executeWriteWithMetadata(
94
94
  await mkdir(dirname(absolutePath), { recursive: true });
95
95
  throwIfAborted();
96
96
  await writeFile(absolutePath, params.content, "utf8");
97
- throwIfAborted();
98
97
  store.set(toolCallId, metadata);
99
98
  return {
100
99
  content: [
101
100
  {
102
101
  type: "text",
103
- text: `Successfully wrote ${params.content.length} bytes to ${params.path}`,
102
+ text: `Successfully wrote ${Buffer.byteLength(params.content, "utf8")} bytes to ${params.path}`,
104
103
  },
105
104
  ],
106
105
  details: undefined,