@herbertgao/pi-extensions 2026.8.1 → 2026.8.3

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 (403) hide show
  1. package/README.md +13 -3
  2. package/node_modules/@czottmann/pi-automode/README.md +16 -2
  3. package/node_modules/@czottmann/pi-automode/docs/GLOSSARY.md +35 -0
  4. package/node_modules/@czottmann/pi-automode/docs/automode-classifier-flow.md +18 -9
  5. package/node_modules/@czottmann/pi-automode/docs/defaults.md +6 -2
  6. package/node_modules/@czottmann/pi-automode/examples/automode.local.json +6 -0
  7. package/node_modules/@czottmann/pi-automode/extensions/auto-mode/classifier.ts +11 -7
  8. package/node_modules/@czottmann/pi-automode/extensions/auto-mode/config.ts +100 -0
  9. package/node_modules/@czottmann/pi-automode/extensions/auto-mode/constants.ts +32 -0
  10. package/node_modules/@czottmann/pi-automode/extensions/auto-mode/extension.ts +78 -3
  11. package/node_modules/@czottmann/pi-automode/extensions/auto-mode/hard-deny.ts +16 -4
  12. package/node_modules/@czottmann/pi-automode/extensions/auto-mode/paths.ts +23 -1
  13. package/node_modules/@czottmann/pi-automode/extensions/auto-mode/permissions.ts +22 -1
  14. package/node_modules/@czottmann/pi-automode/extensions/auto-mode/types.ts +18 -2
  15. package/node_modules/@czottmann/pi-automode/package.json +4 -4
  16. package/node_modules/@dietrichgebert/ponytail/.opencode/command/ponytail-audit.md +5 -0
  17. package/node_modules/@dietrichgebert/ponytail/.opencode/command/ponytail-debt.md +5 -0
  18. package/node_modules/@dietrichgebert/ponytail/.opencode/command/ponytail-gain.md +5 -0
  19. package/node_modules/@dietrichgebert/ponytail/.opencode/command/ponytail-help.md +5 -0
  20. package/node_modules/@dietrichgebert/ponytail/.opencode/command/ponytail-review.md +5 -0
  21. package/node_modules/@dietrichgebert/ponytail/.opencode/command/ponytail.md +5 -0
  22. package/node_modules/@dietrichgebert/ponytail/.opencode/plugins/ponytail-frontmatter.cjs +23 -0
  23. package/node_modules/@dietrichgebert/ponytail/.opencode/plugins/ponytail.mjs +99 -0
  24. package/node_modules/@dietrichgebert/ponytail/.qoder/rules/ponytail.md +30 -0
  25. package/node_modules/@dietrichgebert/ponytail/.qoder-plugin/plugin.json +16 -0
  26. package/node_modules/@dietrichgebert/ponytail/AGENTS.md +32 -0
  27. package/node_modules/@dietrichgebert/ponytail/LICENSE +21 -0
  28. package/node_modules/@dietrichgebert/ponytail/README.es.md +298 -0
  29. package/node_modules/@dietrichgebert/ponytail/README.ko.md +315 -0
  30. package/node_modules/@dietrichgebert/ponytail/README.md +351 -0
  31. package/node_modules/@dietrichgebert/ponytail/assets/benchmark-3model.svg +21 -0
  32. package/node_modules/@dietrichgebert/ponytail/assets/benchmark-agentic.svg +62 -0
  33. package/node_modules/@dietrichgebert/ponytail/assets/logo-dark.png +0 -0
  34. package/node_modules/@dietrichgebert/ponytail/assets/logo-dark.svg +115 -0
  35. package/node_modules/@dietrichgebert/ponytail/assets/logo-greenpt-dark.svg +27 -0
  36. package/node_modules/@dietrichgebert/ponytail/assets/logo-greenpt.svg +27 -0
  37. package/node_modules/@dietrichgebert/ponytail/assets/logo.png +0 -0
  38. package/node_modules/@dietrichgebert/ponytail/assets/social-preview.png +0 -0
  39. package/node_modules/@dietrichgebert/ponytail/assets/waitlist-banner-es.png +0 -0
  40. package/node_modules/@dietrichgebert/ponytail/assets/waitlist-banner-ko.png +0 -0
  41. package/node_modules/@dietrichgebert/ponytail/assets/waitlist-banner.png +0 -0
  42. package/node_modules/@dietrichgebert/ponytail/hooks/claude-codex-hooks.json +44 -0
  43. package/node_modules/@dietrichgebert/ponytail/hooks/copilot-hooks.json +21 -0
  44. package/node_modules/@dietrichgebert/ponytail/hooks/ponytail-activate.js +96 -0
  45. package/node_modules/@dietrichgebert/ponytail/hooks/ponytail-config.js +169 -0
  46. package/node_modules/@dietrichgebert/ponytail/hooks/ponytail-instructions.js +98 -0
  47. package/node_modules/@dietrichgebert/ponytail/hooks/ponytail-mode-tracker.js +130 -0
  48. package/node_modules/@dietrichgebert/ponytail/hooks/ponytail-runtime.js +85 -0
  49. package/node_modules/@dietrichgebert/ponytail/hooks/ponytail-statusline.ps1 +24 -0
  50. package/node_modules/@dietrichgebert/ponytail/hooks/ponytail-statusline.sh +18 -0
  51. package/node_modules/@dietrichgebert/ponytail/hooks/ponytail-subagent.js +77 -0
  52. package/node_modules/@dietrichgebert/ponytail/hooks/qoder-hooks.json +26 -0
  53. package/node_modules/@dietrichgebert/ponytail/package.json +47 -0
  54. package/node_modules/@dietrichgebert/ponytail/pi-extension/index.js +211 -0
  55. package/node_modules/@dietrichgebert/ponytail/pi-extension/package.json +8 -0
  56. package/node_modules/@dietrichgebert/ponytail/scripts/uninstall.js +60 -0
  57. package/node_modules/@dietrichgebert/ponytail/skills/ponytail/SKILL.md +120 -0
  58. package/node_modules/@dietrichgebert/ponytail/skills/ponytail-audit/SKILL.md +41 -0
  59. package/node_modules/@dietrichgebert/ponytail/skills/ponytail-debt/SKILL.md +44 -0
  60. package/node_modules/@dietrichgebert/ponytail/skills/ponytail-gain/SKILL.md +50 -0
  61. package/node_modules/@dietrichgebert/ponytail/skills/ponytail-help/SKILL.md +71 -0
  62. package/node_modules/@dietrichgebert/ponytail/skills/ponytail-review/SKILL.md +57 -0
  63. package/node_modules/@herbertgao/pi-cc-extensions/README.en.md +6 -10
  64. package/node_modules/@herbertgao/pi-cc-extensions/README.md +5 -9
  65. package/node_modules/@herbertgao/pi-cc-extensions/assets/readme/hero.en.svg +101 -0
  66. package/node_modules/@herbertgao/pi-cc-extensions/extensions/config/config.ts +1 -17
  67. package/node_modules/@herbertgao/pi-cc-extensions/extensions/config/panel.ts +15 -9
  68. package/node_modules/@herbertgao/pi-cc-extensions/extensions/{utils/agent-summary.ts → feature/agent-summary/core.ts} +37 -35
  69. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/{agent-summary.ts → agent-summary/index.ts} +3 -3
  70. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/compact-thinking.ts +24 -83
  71. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/context.ts +1 -1
  72. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/{session-reference.ts → reference/index.ts} +1 -1
  73. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/{agent-autocomplete.ts → reference/subagent.ts} +19 -9
  74. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/{pi-startup-header.ts → shell/startup-header.ts} +1 -1
  75. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/{working-message.ts → shell/working-message.ts} +5 -2
  76. package/node_modules/@herbertgao/pi-cc-extensions/extensions/index.ts +32 -28
  77. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/compact-mode.ts +452 -94
  78. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/default-mode.ts +727 -0
  79. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/index.ts +66 -776
  80. package/node_modules/@herbertgao/pi-cc-extensions/extensions/{feature → renderer}/markdown-enhance.ts +134 -11
  81. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/hover.ts +130 -0
  82. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{mouse-interaction.ts → mouse/interaction.ts} +90 -568
  83. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/layout.ts +144 -0
  84. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/packets.ts +143 -0
  85. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/scroll.ts +195 -0
  86. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-diff → tool/diff}/ansi-utils.ts +56 -1
  87. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-diff → tool/diff}/diff-renderer.ts +4 -4
  88. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-diff → tool/diff}/line-width-safety.ts +1 -1
  89. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/write-display-utils.ts +12 -0
  90. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-diff → tool/diff}/write-execution.ts +1 -2
  91. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-grouping.ts → tool/grouping.ts} +27 -10
  92. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-result.ts → tool/result.ts} +4 -13
  93. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/transcript-refresh.ts +91 -0
  94. package/node_modules/@herbertgao/pi-cc-extensions/extensions/utils/fullscreen-detect.ts +0 -27
  95. package/node_modules/@herbertgao/pi-cc-extensions/package.json +3 -3
  96. package/node_modules/@herbertgao/pi-cc-extensions/themes/cc-dark.json +1 -0
  97. package/node_modules/@herbertgao/pi-cc-extensions/themes/cc-light.json +2 -2
  98. package/node_modules/@herbertgao/pi-stash/README.md +9 -9
  99. package/node_modules/@herbertgao/pi-stash/package.json +1 -1
  100. package/node_modules/@herbertgao/pi-stash/src/index.ts +2 -1
  101. package/node_modules/@herbertgao/pi-subagents/CHANGELOG.md +20 -0
  102. package/node_modules/@herbertgao/pi-subagents/README.md +6 -2
  103. package/node_modules/@herbertgao/pi-subagents/package.json +3 -3
  104. package/node_modules/@herbertgao/pi-subagents/src/agent-manager.ts +1 -0
  105. package/node_modules/@herbertgao/pi-subagents/src/agent-runner.ts +3 -1
  106. package/node_modules/@herbertgao/pi-subagents/src/custom-agents.ts +85 -11
  107. package/node_modules/@herbertgao/pi-subagents/src/index.ts +61 -39
  108. package/node_modules/@herbertgao/pi-subagents/src/nested-tools.ts +26 -35
  109. package/node_modules/@herbertgao/pi-subagents/src/prompts.ts +15 -1
  110. package/node_modules/@herbertgao/pi-subagents/src/settings.ts +12 -0
  111. package/node_modules/@herbertgao/pi-subagents/src/types.ts +2 -0
  112. package/node_modules/@narumitw/pi-btw/LICENSE +21 -0
  113. package/node_modules/@narumitw/pi-btw/README.md +210 -0
  114. package/node_modules/@narumitw/pi-btw/package.json +53 -0
  115. package/node_modules/@narumitw/pi-btw/src/bring-to-main.ts +632 -0
  116. package/node_modules/@narumitw/pi-btw/src/btw.ts +996 -0
  117. package/node_modules/@narumitw/pi-btw/src/fullscreen-ui.ts +339 -0
  118. package/node_modules/@narumitw/pi-btw/src/index.ts +1 -0
  119. package/node_modules/@narumitw/pi-btw/src/menu.ts +296 -0
  120. package/node_modules/@narumitw/pi-btw/src/settings.ts +237 -0
  121. package/node_modules/@narumitw/pi-btw/src/side-thread.ts +238 -0
  122. package/node_modules/@narumitw/pi-btw/src/text.ts +10 -0
  123. package/node_modules/@narumitw/pi-btw/src/transcript-pager.ts +620 -0
  124. package/node_modules/@pi-plugins/fast-mode/LICENSE +21 -0
  125. package/node_modules/@pi-plugins/fast-mode/README.md +92 -0
  126. package/node_modules/@pi-plugins/fast-mode/dist/index.d.mts +6 -0
  127. package/node_modules/@pi-plugins/fast-mode/dist/index.d.mts.map +1 -0
  128. package/node_modules/@pi-plugins/fast-mode/dist/index.mjs +2026 -0
  129. package/node_modules/@pi-plugins/fast-mode/dist/index.mjs.map +1 -0
  130. package/node_modules/@pi-plugins/fast-mode/package.json +73 -0
  131. package/node_modules/pi-mcp-adapter/CHANGELOG.md +78 -0
  132. package/node_modules/pi-mcp-adapter/README.md +80 -16
  133. package/node_modules/pi-mcp-adapter/agent-dir.ts +40 -0
  134. package/node_modules/pi-mcp-adapter/agent-plugin-loader.ts +377 -0
  135. package/node_modules/pi-mcp-adapter/commands.ts +21 -9
  136. package/node_modules/pi-mcp-adapter/config.ts +110 -49
  137. package/node_modules/pi-mcp-adapter/direct-tools.ts +40 -27
  138. package/node_modules/pi-mcp-adapter/elicitation-handler.ts +37 -36
  139. package/node_modules/pi-mcp-adapter/errors.ts +21 -17
  140. package/node_modules/pi-mcp-adapter/host-html-template.ts +13 -7
  141. package/node_modules/pi-mcp-adapter/index.ts +52 -17
  142. package/node_modules/pi-mcp-adapter/init.ts +9 -7
  143. package/node_modules/pi-mcp-adapter/json-schema-validator.ts +2 -2
  144. package/node_modules/pi-mcp-adapter/lifecycle.ts +8 -8
  145. package/node_modules/pi-mcp-adapter/logger.ts +1 -1
  146. package/node_modules/pi-mcp-adapter/mcp-auth-flow.ts +122 -25
  147. package/node_modules/pi-mcp-adapter/mcp-auth.ts +120 -2
  148. package/node_modules/pi-mcp-adapter/mcp-callback-server.ts +138 -61
  149. package/node_modules/pi-mcp-adapter/mcp-code.ts +13 -11
  150. package/node_modules/pi-mcp-adapter/mcp-oauth-provider.ts +62 -17
  151. package/node_modules/pi-mcp-adapter/mcp-output-guard.ts +15 -11
  152. package/node_modules/pi-mcp-adapter/mcp-panel.ts +34 -15
  153. package/node_modules/pi-mcp-adapter/mcp-probe.ts +131 -34
  154. package/node_modules/pi-mcp-adapter/mcp-script-worker.mjs +2 -2
  155. package/node_modules/pi-mcp-adapter/mcp-setup-panel.ts +7 -4
  156. package/node_modules/pi-mcp-adapter/mcp-trace.ts +59 -64
  157. package/node_modules/pi-mcp-adapter/metadata-cache.ts +34 -26
  158. package/node_modules/pi-mcp-adapter/npx-resolver.ts +6 -4
  159. package/node_modules/pi-mcp-adapter/oauth-handler.ts +1 -1
  160. package/node_modules/pi-mcp-adapter/oauth.ts +48 -0
  161. package/node_modules/pi-mcp-adapter/onboarding-state.ts +19 -11
  162. package/node_modules/pi-mcp-adapter/package.json +20 -9
  163. package/node_modules/pi-mcp-adapter/panel-keys.ts +20 -4
  164. package/node_modules/pi-mcp-adapter/prompts.ts +2 -2
  165. package/node_modules/pi-mcp-adapter/proxy-modes.ts +56 -21
  166. package/node_modules/pi-mcp-adapter/sampling-handler.ts +22 -15
  167. package/node_modules/pi-mcp-adapter/search-ranking.ts +2 -1
  168. package/node_modules/pi-mcp-adapter/server-manager.ts +165 -113
  169. package/node_modules/pi-mcp-adapter/session-recovery.ts +11 -12
  170. package/node_modules/pi-mcp-adapter/skills/mcp-scripting/SKILL.md +3 -3
  171. package/node_modules/pi-mcp-adapter/state.ts +3 -1
  172. package/node_modules/pi-mcp-adapter/tool-approval.ts +67 -4
  173. package/node_modules/pi-mcp-adapter/tool-metadata.ts +6 -5
  174. package/node_modules/pi-mcp-adapter/tool-registrar.ts +187 -3
  175. package/node_modules/pi-mcp-adapter/tool-result-renderer.ts +14 -2
  176. package/node_modules/pi-mcp-adapter/ts-shape.ts +9 -2
  177. package/node_modules/pi-mcp-adapter/types.ts +111 -22
  178. package/node_modules/pi-mcp-adapter/ui-app-bridge-helpers.ts +40 -0
  179. package/node_modules/pi-mcp-adapter/ui-resource-handler.ts +28 -19
  180. package/node_modules/pi-mcp-adapter/ui-server.ts +90 -58
  181. package/node_modules/pi-mcp-adapter/ui-session.ts +16 -14
  182. package/node_modules/pi-mcp-adapter/unix-socket-transport.ts +4 -4
  183. package/node_modules/pi-mcp-adapter/utils.ts +23 -9
  184. package/node_modules/pi-web-access/CHANGELOG.md +45 -0
  185. package/node_modules/pi-web-access/README.md +104 -29
  186. package/node_modules/pi-web-access/bocha.ts +221 -0
  187. package/node_modules/pi-web-access/curator-page.ts +113 -12
  188. package/node_modules/pi-web-access/curator-server.ts +56 -20
  189. package/node_modules/pi-web-access/datalab-pdf-extract.ts +568 -0
  190. package/node_modules/pi-web-access/duckduckgo.ts +123 -0
  191. package/node_modules/pi-web-access/extract.ts +288 -143
  192. package/node_modules/pi-web-access/feature-config.ts +29 -0
  193. package/node_modules/pi-web-access/gemini-api.ts +4 -0
  194. package/node_modules/pi-web-access/gemini-search.ts +45 -12
  195. package/node_modules/pi-web-access/gemini-web.ts +68 -3
  196. package/node_modules/pi-web-access/index.ts +160 -71
  197. package/node_modules/pi-web-access/jina-search.ts +284 -0
  198. package/node_modules/pi-web-access/kagi.ts +12 -12
  199. package/node_modules/pi-web-access/openai-search.ts +12 -2
  200. package/node_modules/pi-web-access/package.json +4 -3
  201. package/node_modules/pi-web-access/pdf-extract.ts +327 -228
  202. package/node_modules/pi-web-access/storage.ts +440 -2
  203. package/node_modules/pi-web-access/summary-model-scope.ts +1 -1
  204. package/node_modules/pi-web-access/summary-review.ts +4 -2
  205. package/node_modules/pi-web-access/video-extract.ts +10 -8
  206. package/node_modules/pi-web-access/xai-search.ts +12 -2
  207. package/node_modules/pi-web-access/youtube-extract.ts +2 -1
  208. package/node_modules/remote-pi/LICENSE +21 -0
  209. package/node_modules/remote-pi/README.md +675 -0
  210. package/node_modules/remote-pi/dist/actions/handlers.d.ts +122 -0
  211. package/node_modules/remote-pi/dist/actions/handlers.js +160 -0
  212. package/node_modules/remote-pi/dist/actions/handlers.js.map +1 -0
  213. package/node_modules/remote-pi/dist/actions/registry.d.ts +39 -0
  214. package/node_modules/remote-pi/dist/actions/registry.js +58 -0
  215. package/node_modules/remote-pi/dist/actions/registry.js.map +1 -0
  216. package/node_modules/remote-pi/dist/bin/supervisord.d.ts +2 -0
  217. package/node_modules/remote-pi/dist/bin/supervisord.js +86 -0
  218. package/node_modules/remote-pi/dist/bin/supervisord.js.map +1 -0
  219. package/node_modules/remote-pi/dist/commands/builtin_mirror.d.ts +58 -0
  220. package/node_modules/remote-pi/dist/commands/builtin_mirror.js +71 -0
  221. package/node_modules/remote-pi/dist/commands/builtin_mirror.js.map +1 -0
  222. package/node_modules/remote-pi/dist/commands/list_commands.d.ts +60 -0
  223. package/node_modules/remote-pi/dist/commands/list_commands.js +73 -0
  224. package/node_modules/remote-pi/dist/commands/list_commands.js.map +1 -0
  225. package/node_modules/remote-pi/dist/config.d.ts +62 -0
  226. package/node_modules/remote-pi/dist/config.js +115 -0
  227. package/node_modules/remote-pi/dist/config.js.map +1 -0
  228. package/node_modules/remote-pi/dist/daemon/client.d.ts +20 -0
  229. package/node_modules/remote-pi/dist/daemon/client.js +131 -0
  230. package/node_modules/remote-pi/dist/daemon/client.js.map +1 -0
  231. package/node_modules/remote-pi/dist/daemon/control_protocol.d.ts +176 -0
  232. package/node_modules/remote-pi/dist/daemon/control_protocol.js +63 -0
  233. package/node_modules/remote-pi/dist/daemon/control_protocol.js.map +1 -0
  234. package/node_modules/remote-pi/dist/daemon/cron_log.d.ts +45 -0
  235. package/node_modules/remote-pi/dist/daemon/cron_log.js +72 -0
  236. package/node_modules/remote-pi/dist/daemon/cron_log.js.map +1 -0
  237. package/node_modules/remote-pi/dist/daemon/cron_registry.d.ts +80 -0
  238. package/node_modules/remote-pi/dist/daemon/cron_registry.js +194 -0
  239. package/node_modules/remote-pi/dist/daemon/cron_registry.js.map +1 -0
  240. package/node_modules/remote-pi/dist/daemon/id.d.ts +24 -0
  241. package/node_modules/remote-pi/dist/daemon/id.js +36 -0
  242. package/node_modules/remote-pi/dist/daemon/id.js.map +1 -0
  243. package/node_modules/remote-pi/dist/daemon/install.d.ts +170 -0
  244. package/node_modules/remote-pi/dist/daemon/install.js +547 -0
  245. package/node_modules/remote-pi/dist/daemon/install.js.map +1 -0
  246. package/node_modules/remote-pi/dist/daemon/registry.d.ts +63 -0
  247. package/node_modules/remote-pi/dist/daemon/registry.js +153 -0
  248. package/node_modules/remote-pi/dist/daemon/registry.js.map +1 -0
  249. package/node_modules/remote-pi/dist/daemon/rpc_child.d.ts +194 -0
  250. package/node_modules/remote-pi/dist/daemon/rpc_child.js +389 -0
  251. package/node_modules/remote-pi/dist/daemon/rpc_child.js.map +1 -0
  252. package/node_modules/remote-pi/dist/daemon/supervisor.d.ts +93 -0
  253. package/node_modules/remote-pi/dist/daemon/supervisor.js +596 -0
  254. package/node_modules/remote-pi/dist/daemon/supervisor.js.map +1 -0
  255. package/node_modules/remote-pi/dist/extension_ui_bridge.d.ts +26 -0
  256. package/node_modules/remote-pi/dist/extension_ui_bridge.js +341 -0
  257. package/node_modules/remote-pi/dist/extension_ui_bridge.js.map +1 -0
  258. package/node_modules/remote-pi/dist/index.d.ts +213 -0
  259. package/node_modules/remote-pi/dist/index.js +4996 -0
  260. package/node_modules/remote-pi/dist/index.js.map +1 -0
  261. package/node_modules/remote-pi/dist/mcp/mesh_result.d.ts +10 -0
  262. package/node_modules/remote-pi/dist/mcp/mesh_result.js +42 -0
  263. package/node_modules/remote-pi/dist/mcp/mesh_result.js.map +1 -0
  264. package/node_modules/remote-pi/dist/mcp/mesh_server.d.ts +16 -0
  265. package/node_modules/remote-pi/dist/mcp/mesh_server.js +327 -0
  266. package/node_modules/remote-pi/dist/mcp/mesh_server.js.map +1 -0
  267. package/node_modules/remote-pi/dist/mesh/canonical.d.ts +30 -0
  268. package/node_modules/remote-pi/dist/mesh/canonical.js +61 -0
  269. package/node_modules/remote-pi/dist/mesh/canonical.js.map +1 -0
  270. package/node_modules/remote-pi/dist/mesh/client.d.ts +18 -0
  271. package/node_modules/remote-pi/dist/mesh/client.js +125 -0
  272. package/node_modules/remote-pi/dist/mesh/client.js.map +1 -0
  273. package/node_modules/remote-pi/dist/mesh/encoding.d.ts +38 -0
  274. package/node_modules/remote-pi/dist/mesh/encoding.js +216 -0
  275. package/node_modules/remote-pi/dist/mesh/encoding.js.map +1 -0
  276. package/node_modules/remote-pi/dist/mesh/self_revoke.d.ts +73 -0
  277. package/node_modules/remote-pi/dist/mesh/self_revoke.js +401 -0
  278. package/node_modules/remote-pi/dist/mesh/self_revoke.js.map +1 -0
  279. package/node_modules/remote-pi/dist/mesh/siblings.d.ts +49 -0
  280. package/node_modules/remote-pi/dist/mesh/siblings.js +159 -0
  281. package/node_modules/remote-pi/dist/mesh/siblings.js.map +1 -0
  282. package/node_modules/remote-pi/dist/mesh/types.d.ts +34 -0
  283. package/node_modules/remote-pi/dist/mesh/types.js +11 -0
  284. package/node_modules/remote-pi/dist/mesh/types.js.map +1 -0
  285. package/node_modules/remote-pi/dist/mesh/verify.d.ts +17 -0
  286. package/node_modules/remote-pi/dist/mesh/verify.js +86 -0
  287. package/node_modules/remote-pi/dist/mesh/verify.js.map +1 -0
  288. package/node_modules/remote-pi/dist/pairing/crypto.d.ts +8 -0
  289. package/node_modules/remote-pi/dist/pairing/crypto.js +22 -0
  290. package/node_modules/remote-pi/dist/pairing/crypto.js.map +1 -0
  291. package/node_modules/remote-pi/dist/pairing/handshake.d.ts +28 -0
  292. package/node_modules/remote-pi/dist/pairing/handshake.js +113 -0
  293. package/node_modules/remote-pi/dist/pairing/handshake.js.map +1 -0
  294. package/node_modules/remote-pi/dist/pairing/noise-sha256.d.ts +16 -0
  295. package/node_modules/remote-pi/dist/pairing/noise-sha256.js +103 -0
  296. package/node_modules/remote-pi/dist/pairing/noise-sha256.js.map +1 -0
  297. package/node_modules/remote-pi/dist/pairing/qr.d.ts +59 -0
  298. package/node_modules/remote-pi/dist/pairing/qr.js +125 -0
  299. package/node_modules/remote-pi/dist/pairing/qr.js.map +1 -0
  300. package/node_modules/remote-pi/dist/pairing/storage.d.ts +120 -0
  301. package/node_modules/remote-pi/dist/pairing/storage.js +604 -0
  302. package/node_modules/remote-pi/dist/pairing/storage.js.map +1 -0
  303. package/node_modules/remote-pi/dist/protocol/codec.d.ts +7 -0
  304. package/node_modules/remote-pi/dist/protocol/codec.js +49 -0
  305. package/node_modules/remote-pi/dist/protocol/codec.js.map +1 -0
  306. package/node_modules/remote-pi/dist/protocol/types.d.ts +393 -0
  307. package/node_modules/remote-pi/dist/protocol/types.js +2 -0
  308. package/node_modules/remote-pi/dist/protocol/types.js.map +1 -0
  309. package/node_modules/remote-pi/dist/rooms.d.ts +29 -0
  310. package/node_modules/remote-pi/dist/rooms.js +57 -0
  311. package/node_modules/remote-pi/dist/rooms.js.map +1 -0
  312. package/node_modules/remote-pi/dist/session/address.d.ts +49 -0
  313. package/node_modules/remote-pi/dist/session/address.js +58 -0
  314. package/node_modules/remote-pi/dist/session/address.js.map +1 -0
  315. package/node_modules/remote-pi/dist/session/agent_bridge.d.ts +55 -0
  316. package/node_modules/remote-pi/dist/session/agent_bridge.js +146 -0
  317. package/node_modules/remote-pi/dist/session/agent_bridge.js.map +1 -0
  318. package/node_modules/remote-pi/dist/session/bridge.d.ts +37 -0
  319. package/node_modules/remote-pi/dist/session/bridge.js +130 -0
  320. package/node_modules/remote-pi/dist/session/bridge.js.map +1 -0
  321. package/node_modules/remote-pi/dist/session/broker.d.ts +189 -0
  322. package/node_modules/remote-pi/dist/session/broker.js +507 -0
  323. package/node_modules/remote-pi/dist/session/broker.js.map +1 -0
  324. package/node_modules/remote-pi/dist/session/broker_remote.d.ts +74 -0
  325. package/node_modules/remote-pi/dist/session/broker_remote.js +583 -0
  326. package/node_modules/remote-pi/dist/session/broker_remote.js.map +1 -0
  327. package/node_modules/remote-pi/dist/session/cwd_lock.d.ts +33 -0
  328. package/node_modules/remote-pi/dist/session/cwd_lock.js +126 -0
  329. package/node_modules/remote-pi/dist/session/cwd_lock.js.map +1 -0
  330. package/node_modules/remote-pi/dist/session/envelope.d.ts +33 -0
  331. package/node_modules/remote-pi/dist/session/envelope.js +117 -0
  332. package/node_modules/remote-pi/dist/session/envelope.js.map +1 -0
  333. package/node_modules/remote-pi/dist/session/global_config.d.ts +33 -0
  334. package/node_modules/remote-pi/dist/session/global_config.js +73 -0
  335. package/node_modules/remote-pi/dist/session/global_config.js.map +1 -0
  336. package/node_modules/remote-pi/dist/session/ipc.d.ts +27 -0
  337. package/node_modules/remote-pi/dist/session/ipc.js +22 -0
  338. package/node_modules/remote-pi/dist/session/ipc.js.map +1 -0
  339. package/node_modules/remote-pi/dist/session/leader_election.d.ts +32 -0
  340. package/node_modules/remote-pi/dist/session/leader_election.js +106 -0
  341. package/node_modules/remote-pi/dist/session/leader_election.js.map +1 -0
  342. package/node_modules/remote-pi/dist/session/local_config.d.ts +55 -0
  343. package/node_modules/remote-pi/dist/session/local_config.js +157 -0
  344. package/node_modules/remote-pi/dist/session/local_config.js.map +1 -0
  345. package/node_modules/remote-pi/dist/session/mesh_message.d.ts +20 -0
  346. package/node_modules/remote-pi/dist/session/mesh_message.js +28 -0
  347. package/node_modules/remote-pi/dist/session/mesh_message.js.map +1 -0
  348. package/node_modules/remote-pi/dist/session/mesh_node.d.ts +116 -0
  349. package/node_modules/remote-pi/dist/session/mesh_node.js +573 -0
  350. package/node_modules/remote-pi/dist/session/mesh_node.js.map +1 -0
  351. package/node_modules/remote-pi/dist/session/peer.d.ts +139 -0
  352. package/node_modules/remote-pi/dist/session/peer.js +451 -0
  353. package/node_modules/remote-pi/dist/session/peer.js.map +1 -0
  354. package/node_modules/remote-pi/dist/session/peer_inventory.d.ts +13 -0
  355. package/node_modules/remote-pi/dist/session/peer_inventory.js +48 -0
  356. package/node_modules/remote-pi/dist/session/peer_inventory.js.map +1 -0
  357. package/node_modules/remote-pi/dist/session/peer_limits.d.ts +9 -0
  358. package/node_modules/remote-pi/dist/session/peer_limits.js +21 -0
  359. package/node_modules/remote-pi/dist/session/peer_limits.js.map +1 -0
  360. package/node_modules/remote-pi/dist/session/setup_wizard.d.ts +39 -0
  361. package/node_modules/remote-pi/dist/session/setup_wizard.js +63 -0
  362. package/node_modules/remote-pi/dist/session/setup_wizard.js.map +1 -0
  363. package/node_modules/remote-pi/dist/session/tool_gate.d.ts +5 -0
  364. package/node_modules/remote-pi/dist/session/tool_gate.js +11 -0
  365. package/node_modules/remote-pi/dist/session/tool_gate.js.map +1 -0
  366. package/node_modules/remote-pi/dist/session/tools.d.ts +24 -0
  367. package/node_modules/remote-pi/dist/session/tools.js +252 -0
  368. package/node_modules/remote-pi/dist/session/tools.js.map +1 -0
  369. package/node_modules/remote-pi/dist/session/wizard.d.ts +13 -0
  370. package/node_modules/remote-pi/dist/session/wizard.js +20 -0
  371. package/node_modules/remote-pi/dist/session/wizard.js.map +1 -0
  372. package/node_modules/remote-pi/dist/settings.d.ts +15 -0
  373. package/node_modules/remote-pi/dist/settings.js +52 -0
  374. package/node_modules/remote-pi/dist/settings.js.map +1 -0
  375. package/node_modules/remote-pi/dist/transport/peer_channel.d.ts +37 -0
  376. package/node_modules/remote-pi/dist/transport/peer_channel.js +98 -0
  377. package/node_modules/remote-pi/dist/transport/peer_channel.js.map +1 -0
  378. package/node_modules/remote-pi/dist/transport/pi_forward_client.d.ts +29 -0
  379. package/node_modules/remote-pi/dist/transport/pi_forward_client.js +62 -0
  380. package/node_modules/remote-pi/dist/transport/pi_forward_client.js.map +1 -0
  381. package/node_modules/remote-pi/dist/transport/relay_client.d.ts +91 -0
  382. package/node_modules/remote-pi/dist/transport/relay_client.js +206 -0
  383. package/node_modules/remote-pi/dist/transport/relay_client.js.map +1 -0
  384. package/node_modules/remote-pi/dist/ui/footer.d.ts +32 -0
  385. package/node_modules/remote-pi/dist/ui/footer.js +34 -0
  386. package/node_modules/remote-pi/dist/ui/footer.js.map +1 -0
  387. package/node_modules/remote-pi/docs/daemon.md +289 -0
  388. package/node_modules/remote-pi/package.json +88 -0
  389. package/node_modules/remote-pi/service-templates/launchd.plist.template +35 -0
  390. package/node_modules/remote-pi/service-templates/systemd.service.template +19 -0
  391. package/node_modules/remote-pi/service-templates/task-launcher.vbs.template +10 -0
  392. package/node_modules/remote-pi/service-templates/task-scheduler.xml.template +38 -0
  393. package/node_modules/remote-pi/skills/agent-network/SKILL.md +310 -0
  394. package/package.json +37 -12
  395. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool-diff/write-display-utils.ts +0 -29
  396. /package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/{session-reference-core.ts → reference/session.ts} +0 -0
  397. /package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/{pi-aliases.ts → shell/aliases.ts} +0 -0
  398. /package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-diff → tool/diff}/ATTRIBUTION.md +0 -0
  399. /package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-diff → tool/diff}/diff-presentation.ts +0 -0
  400. /package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-diff → tool/diff}/index.ts +0 -0
  401. /package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-diff → tool/diff}/render-utils.ts +0 -0
  402. /package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-diff → tool/diff}/shiki-highlight.ts +0 -0
  403. /package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-diff → tool/diff}/types.ts +0 -0
@@ -0,0 +1,339 @@
1
+ import { spawn } from "node:child_process";
2
+ import type {
3
+ ExtensionCommandContext,
4
+ KeybindingsManager,
5
+ Theme,
6
+ } from "@earendil-works/pi-coding-agent";
7
+ import {
8
+ type Component,
9
+ type OverlayHandle,
10
+ type TUI,
11
+ TuiAltScreen,
12
+ truncateToWidth,
13
+ } from "@earendil-works/pi-tui";
14
+ import { sanitizeSingleLine } from "./text.js";
15
+
16
+ type BtwCustomOptions = Parameters<ExtensionCommandContext["ui"]["custom"]>[1];
17
+ type BtwCustomFactory<T> = (
18
+ tui: TUI,
19
+ theme: Theme,
20
+ keybindings: KeybindingsManager,
21
+ done: (result: T) => void,
22
+ ) => (Component & { dispose?(): void }) | Promise<Component & { dispose?(): void }>;
23
+
24
+ type BtwFullscreenTui = TUI & { flash?: (message: string, durationMs?: number) => void };
25
+
26
+ export type BtwFullscreenTuiFactory = (parent: TUI) => BtwFullscreenTui;
27
+
28
+ export interface BtwFullscreenDependencies {
29
+ createTui?: BtwFullscreenTuiFactory;
30
+ openUrl?: (url: string) => void;
31
+ }
32
+
33
+ export type RunBtwFullscreen = <T>(
34
+ ctx: ExtensionCommandContext,
35
+ run: (ctx: ExtensionCommandContext) => Promise<T>,
36
+ ) => Promise<T>;
37
+
38
+ type FullscreenOutcome<T> = { kind: "completed"; value: T } | { kind: "failed"; error: unknown };
39
+
40
+ class FullscreenUiDisposedError extends Error {
41
+ constructor() {
42
+ super("The dedicated pi-btw UI was disposed.");
43
+ this.name = "FullscreenUiDisposedError";
44
+ }
45
+ }
46
+
47
+ export async function runBtwFullscreen<T>(
48
+ ctx: ExtensionCommandContext,
49
+ run: (ctx: ExtensionCommandContext) => Promise<T>,
50
+ dependencies: BtwFullscreenDependencies = {},
51
+ ): Promise<T> {
52
+ const createTui =
53
+ dependencies.createTui ??
54
+ ((parent: TUI) => createBtwFullscreenTui(parent, dependencies.openUrl ?? openUrlInBrowser));
55
+ let liveEditorText = ctx.ui.getEditorText();
56
+ let restoreEditor = false;
57
+ const outcome = await ctx.ui.custom<FullscreenOutcome<T>>(
58
+ (parent, theme, keybindings, done) =>
59
+ new BtwFullscreenHost(
60
+ parent,
61
+ theme,
62
+ keybindings,
63
+ ctx,
64
+ run,
65
+ (value) => {
66
+ try {
67
+ liveEditorText = ctx.ui.getEditorText();
68
+ restoreEditor = true;
69
+ } catch {
70
+ // A replaced session owns a different editor and must not receive stale text.
71
+ }
72
+ done(value);
73
+ },
74
+ createTui,
75
+ ),
76
+ );
77
+ if (restoreEditor) {
78
+ try {
79
+ if (ctx.ui.getEditorText() !== liveEditorText) ctx.ui.setEditorText(liveEditorText);
80
+ } catch {
81
+ // A replaced session owns a different editor and must not receive stale restoration.
82
+ }
83
+ }
84
+ if (outcome.kind === "failed") throw outcome.error;
85
+ return outcome.value;
86
+ }
87
+
88
+ function createBtwFullscreenTui(parent: TUI, openUrl: (url: string) => void): BtwFullscreenTui {
89
+ return new TuiAltScreen(parent.terminal, parent.getShowHardwareCursor(), undefined, {
90
+ mouse: true,
91
+ openUrl,
92
+ });
93
+ }
94
+
95
+ // Pi does not export its browser opener, so mirror its shell-free launcher for this isolated TUI.
96
+ function openUrlInBrowser(target: string): void {
97
+ const [command, args] =
98
+ process.platform === "darwin"
99
+ ? ["open", [target]]
100
+ : process.platform === "win32"
101
+ ? ["rundll32", ["url.dll,FileProtocolHandler", target]]
102
+ : ["xdg-open", [target]];
103
+ spawn(command, args, { stdio: "ignore", detached: true })
104
+ .on("error", () => {})
105
+ .unref();
106
+ }
107
+
108
+ class BtwFullscreenHost<T> implements Component {
109
+ private fullscreen: BtwFullscreenTui | undefined;
110
+ private cancelActiveCustom: (() => void) | undefined;
111
+ private started = false;
112
+ private disposed = false;
113
+ private finished = false;
114
+
115
+ constructor(
116
+ private readonly parent: TUI,
117
+ private readonly theme: Theme,
118
+ private readonly keybindings: KeybindingsManager,
119
+ private readonly ctx: ExtensionCommandContext,
120
+ private readonly run: (ctx: ExtensionCommandContext) => Promise<T>,
121
+ private readonly done: (outcome: FullscreenOutcome<T>) => void,
122
+ private readonly createTui: BtwFullscreenTuiFactory,
123
+ ) {
124
+ queueMicrotask(() => void this.start());
125
+ }
126
+
127
+ render(width: number): string[] {
128
+ return [truncateToWidth(this.theme.fg("muted", "Opening btw side thread…"), width)];
129
+ }
130
+
131
+ invalidate(): void {}
132
+
133
+ dispose(): void {
134
+ if (this.disposed || this.finished) return;
135
+ this.disposed = true;
136
+ this.cancelActiveCustom?.();
137
+ }
138
+
139
+ private async start(): Promise<void> {
140
+ if (this.started || this.finished) return;
141
+ this.started = true;
142
+ let outcome: FullscreenOutcome<T>;
143
+ let parentStopped = false;
144
+ let fullscreenCreated = false;
145
+ try {
146
+ if (this.disposed) throw new FullscreenUiDisposedError();
147
+ this.parent.stop({ preserveScreen: true });
148
+ parentStopped = true;
149
+ if (this.disposed) throw new FullscreenUiDisposedError();
150
+ this.fullscreen = this.createTui(this.parent);
151
+ fullscreenCreated = true;
152
+ this.fullscreen.start();
153
+ outcome = { kind: "completed", value: await this.run(this.createContext()) };
154
+ } catch (error) {
155
+ outcome = { kind: "failed", error };
156
+ }
157
+
158
+ let cleanupError: unknown;
159
+ try {
160
+ this.cancelActiveCustom?.();
161
+ } catch (error) {
162
+ cleanupError = error;
163
+ }
164
+ if (fullscreenCreated) {
165
+ try {
166
+ this.fullscreen?.stop({ preserveScreen: true });
167
+ } catch (error) {
168
+ cleanupError ??= error;
169
+ }
170
+ }
171
+ if (parentStopped) {
172
+ try {
173
+ this.parent.start();
174
+ this.parent.renderNow(false);
175
+ } catch (error) {
176
+ cleanupError ??= error;
177
+ }
178
+ }
179
+ if (cleanupError !== undefined) outcome = { kind: "failed", error: cleanupError };
180
+ this.finished = true;
181
+ this.done(outcome);
182
+ }
183
+
184
+ private createContext(): ExtensionCommandContext {
185
+ const ui = new Proxy(this.ctx.ui, {
186
+ get: (target, property) => {
187
+ if (property === "custom") {
188
+ return <Value>(factory: BtwCustomFactory<Value>, options?: BtwCustomOptions) =>
189
+ this.showCustom(factory, options);
190
+ }
191
+ if (property === "notify") {
192
+ return (
193
+ message: string,
194
+ level?: Parameters<ExtensionCommandContext["ui"]["notify"]>[1],
195
+ ) => {
196
+ target.notify(message, level);
197
+ const display = sanitizeSingleLine(message);
198
+ if (display) this.fullscreen?.flash?.(display);
199
+ };
200
+ }
201
+ const value = Reflect.get(target, property, target) as unknown;
202
+ return typeof value === "function" ? value.bind(target) : value;
203
+ },
204
+ });
205
+ return new Proxy(this.ctx, {
206
+ get: (target, property) => (property === "ui" ? ui : Reflect.get(target, property, target)),
207
+ });
208
+ }
209
+
210
+ private showCustom<Value>(
211
+ factory: BtwCustomFactory<Value>,
212
+ options?: BtwCustomOptions,
213
+ ): Promise<Value> {
214
+ const fullscreen = this.fullscreen;
215
+ if (!fullscreen || this.disposed || this.finished) {
216
+ return Promise.reject(new FullscreenUiDisposedError());
217
+ }
218
+ if (this.cancelActiveCustom) {
219
+ return Promise.reject(new Error("pi-btw attempted to open overlapping custom UI."));
220
+ }
221
+
222
+ return new Promise<Value>((resolve, reject) => {
223
+ let component: (Component & { dispose?(): void }) | undefined;
224
+ let overlay: OverlayHandle | undefined;
225
+ let mounted = false;
226
+ let factorySettled = false;
227
+ let closed = false;
228
+ let promiseSettled = false;
229
+ let componentDisposed = false;
230
+ let pendingValue: Value | undefined;
231
+ let hasPendingValue = false;
232
+
233
+ const disposeComponent = () => {
234
+ if (!component || componentDisposed) return;
235
+ componentDisposed = true;
236
+ try {
237
+ component.dispose?.();
238
+ } catch {
239
+ // Cleanup must continue so terminal ownership is restored.
240
+ }
241
+ };
242
+ const unmount = () => {
243
+ let cleanupError: unknown;
244
+ try {
245
+ if (overlay) overlay.hide();
246
+ else if (mounted && component) fullscreen.removeChild(component);
247
+ } catch (error) {
248
+ cleanupError = error;
249
+ }
250
+ if (overlay || mounted) {
251
+ try {
252
+ fullscreen.setFocus(null);
253
+ fullscreen.requestRender();
254
+ } catch (error) {
255
+ cleanupError ??= error;
256
+ }
257
+ }
258
+ disposeComponent();
259
+ if (cleanupError !== undefined) throw cleanupError;
260
+ };
261
+ const complete = () => {
262
+ if (promiseSettled || !hasPendingValue) return;
263
+ promiseSettled = true;
264
+ this.cancelActiveCustom = undefined;
265
+ if (!factorySettled) {
266
+ resolve(pendingValue as Value);
267
+ return;
268
+ }
269
+ try {
270
+ unmount();
271
+ resolve(pendingValue as Value);
272
+ } catch (error) {
273
+ reject(error);
274
+ }
275
+ };
276
+ const close = (value: Value) => {
277
+ if (closed || promiseSettled) return;
278
+ closed = true;
279
+ pendingValue = value;
280
+ hasPendingValue = true;
281
+ complete();
282
+ };
283
+ const fail = (error: unknown) => {
284
+ if (promiseSettled) return;
285
+ closed = true;
286
+ promiseSettled = true;
287
+ this.cancelActiveCustom = undefined;
288
+ try {
289
+ unmount();
290
+ reject(error);
291
+ } catch (cleanupError) {
292
+ reject(cleanupError);
293
+ }
294
+ };
295
+ this.cancelActiveCustom = () => {
296
+ if (promiseSettled) return;
297
+ disposeComponent();
298
+ if (!promiseSettled) fail(new FullscreenUiDisposedError());
299
+ };
300
+
301
+ let created: ReturnType<BtwCustomFactory<Value>>;
302
+ try {
303
+ created = factory(fullscreen, this.theme, this.keybindings, close);
304
+ } catch (error) {
305
+ factorySettled = true;
306
+ fail(error);
307
+ return;
308
+ }
309
+ Promise.resolve(created)
310
+ .then((value) => {
311
+ component = value;
312
+ factorySettled = true;
313
+ if (promiseSettled) {
314
+ disposeComponent();
315
+ return;
316
+ }
317
+ if (closed) {
318
+ complete();
319
+ return;
320
+ }
321
+ if (options?.overlay) {
322
+ const overlayOptions =
323
+ typeof options.overlayOptions === "function"
324
+ ? options.overlayOptions()
325
+ : options.overlayOptions;
326
+ overlay = fullscreen.showOverlay(component, overlayOptions);
327
+ options.onHandle?.(overlay);
328
+ } else {
329
+ fullscreen.clear();
330
+ fullscreen.addChild(component);
331
+ mounted = true;
332
+ fullscreen.setFocus(component);
333
+ fullscreen.requestRender();
334
+ }
335
+ })
336
+ .catch(fail);
337
+ });
338
+ }
339
+ }
@@ -0,0 +1 @@
1
+ export { default } from "./btw.js";
@@ -0,0 +1,296 @@
1
+ import type {
2
+ ExtensionCommandContext,
3
+ KeybindingsManager,
4
+ Theme,
5
+ } from "@earendil-works/pi-coding-agent";
6
+ import type { Component, TUI } from "@earendil-works/pi-tui";
7
+ import type { MenuContext, RunMenuResult } from "@narumitw/pi-tui-kit";
8
+ import {
9
+ type BtwSettings,
10
+ btwSettingsPath,
11
+ effectiveRememberThinkingLevelChanges,
12
+ readBtwSettings,
13
+ type UpdateBtwSettingsOptions,
14
+ updateBtwSettings,
15
+ } from "./settings.js";
16
+ import { BTW_THINKING_LEVELS, type BtwThinkingLevel } from "./side-thread.js";
17
+ import { sanitizeSingleLine } from "./text.js";
18
+
19
+ interface BtwMenuState {
20
+ kind: "valid" | "invalid";
21
+ settings: BtwSettings;
22
+ reason?: string;
23
+ }
24
+
25
+ export interface BtwResumeThreadSummary {
26
+ id: string;
27
+ title: string;
28
+ questionCount: number;
29
+ }
30
+
31
+ export interface ShowBtwCommandMenuOptions {
32
+ currentThinkingLevel: BtwThinkingLevel;
33
+ availableThinkingLevels: readonly BtwThinkingLevel[];
34
+ resumeThreads?: readonly BtwResumeThreadSummary[];
35
+ settingsPath?: string;
36
+ readSettings?: typeof readBtwSettings;
37
+ updateSettings?: (
38
+ patch: Partial<Pick<BtwSettings, "thinkingLevel" | "rememberThinkingLevelChanges">>,
39
+ options: UpdateBtwSettingsOptions,
40
+ ) => Promise<BtwSettings>;
41
+ }
42
+
43
+ export type BtwCommandMenuResult = "start" | "closed" | { kind: "resume"; threadId: string };
44
+
45
+ type BtwMenuScreen = "main" | "resume" | "settings" | "invalid";
46
+ type BtwMenuAction = "start" | "resume" | "set-thinking" | "set-remember";
47
+ type BtwCustomOptions = Parameters<ExtensionCommandContext["ui"]["custom"]>[1];
48
+
49
+ type BtwCustomFactory<T> = (
50
+ tui: TUI,
51
+ theme: Theme,
52
+ keybindings: KeybindingsManager,
53
+ done: (result: T) => void,
54
+ ) => Component;
55
+
56
+ export async function showBtwCommandMenu(
57
+ ctx: ExtensionCommandContext,
58
+ options: ShowBtwCommandMenuOptions,
59
+ ): Promise<BtwCommandMenuResult> {
60
+ if (ctx.mode !== "tui") return "closed";
61
+ const { defineMenu, runMenu } = await import("@narumitw/pi-tui-kit");
62
+ if (ctx.signal?.aborted) return "closed";
63
+ const settingsPath = options.settingsPath ?? btwSettingsPath();
64
+ const readSettings = options.readSettings ?? readBtwSettings;
65
+ const updateSettings = options.updateSettings ?? updateBtwSettings;
66
+ const levels =
67
+ options.availableThinkingLevels.length > 0
68
+ ? [...options.availableThinkingLevels]
69
+ : (["off"] satisfies BtwThinkingLevel[]);
70
+ const displaySettingsPath = sanitizeSingleLine(settingsPath);
71
+ const resumeThreads = options.resumeThreads ?? [];
72
+ let startSelected = false;
73
+ let resumedThreadId: string | undefined;
74
+
75
+ const loadState = async (): Promise<BtwMenuState> => {
76
+ const loaded = await readSettings(settingsPath);
77
+ if (loaded.kind === "invalid") {
78
+ return { kind: "invalid", settings: {}, reason: loaded.reason };
79
+ }
80
+ return { kind: "valid", settings: loaded.kind === "loaded" ? loaded.settings : {} };
81
+ };
82
+ const displayThinkingLevel = (settings: BtwSettings): BtwThinkingLevel =>
83
+ clampToAvailableThinkingLevel(settings.thinkingLevel ?? options.currentThinkingLevel, levels);
84
+
85
+ const menu = defineMenu<BtwMenuState, BtwMenuScreen, BtwMenuAction, MenuContext>({
86
+ start: "main",
87
+ screens: {
88
+ main: ({ state }) => ({
89
+ kind: "actions",
90
+ title: "Pi BTW",
91
+ lines: [
92
+ `Thinking: ${displayThinkingLevel(state.settings)} · Remember changes: ${effectiveRememberThinkingLevelChanges(state.settings) ? "On" : "Off"}`,
93
+ ],
94
+ items: [
95
+ {
96
+ id: "start",
97
+ label: "Start side thread",
98
+ description: "Open an empty side thread",
99
+ action: "start",
100
+ },
101
+ ...(resumeThreads.length > 0
102
+ ? [
103
+ {
104
+ id: "resume" as const,
105
+ label: "Resume side thread",
106
+ description: "Continue an in-memory side thread",
107
+ to: "resume" as const,
108
+ },
109
+ ]
110
+ : []),
111
+ {
112
+ id: "settings",
113
+ label: "Settings",
114
+ description: "Choose pi-btw thinking and whether shortcut changes are remembered",
115
+ to: state.kind === "invalid" ? "invalid" : "settings",
116
+ },
117
+ ],
118
+ hint: "close",
119
+ }),
120
+ resume: () => ({
121
+ kind: "choice",
122
+ title: "Resume BTW side thread",
123
+ items: resumeThreads.map((thread) => ({
124
+ id: thread.id,
125
+ label: thread.title,
126
+ description: `${thread.questionCount} ${thread.questionCount === 1 ? "question" : "questions"}`,
127
+ })),
128
+ action: "resume",
129
+ viewportSize: 10,
130
+ hint: "back",
131
+ }),
132
+ settings: ({ state }) => ({
133
+ kind: "settings",
134
+ title: "Pi BTW Settings",
135
+ lines: [`User settings · ${displaySettingsPath}`],
136
+ items: [
137
+ {
138
+ id: "thinkingLevel",
139
+ label: "Thinking level",
140
+ description: "Set the starting level for future pi-btw side threads.",
141
+ currentValue: displayThinkingLevel(state.settings),
142
+ values: levels,
143
+ action: "set-thinking",
144
+ },
145
+ {
146
+ id: "rememberThinkingLevelChanges",
147
+ label: "Remember thinking level changes",
148
+ description: "Save side-thread shortcut changes to pi-btw.json for next time.",
149
+ currentValue: effectiveRememberThinkingLevelChanges(state.settings) ? "On" : "Off",
150
+ values: ["On", "Off"],
151
+ action: "set-remember",
152
+ },
153
+ ],
154
+ }),
155
+ invalid: ({ state }) => ({
156
+ kind: "detail",
157
+ title: "Pi BTW Settings · Read only",
158
+ lines: [
159
+ `Invalid settings file. Fix ${displaySettingsPath} before saving.`,
160
+ sanitizeSingleLine(state.reason ?? "The settings file is invalid."),
161
+ ],
162
+ hint: "back",
163
+ }),
164
+ },
165
+ actions: {
166
+ start: async () => {
167
+ startSelected = true;
168
+ return { kind: "close" };
169
+ },
170
+ resume: async ({ itemId }: { itemId: string }) => {
171
+ if (!resumeThreads.some((thread) => thread.id === itemId)) {
172
+ return { kind: "rejected" } as const;
173
+ }
174
+ resumedThreadId = itemId;
175
+ return { kind: "close" } as const;
176
+ },
177
+ "set-thinking": async ({ value, signal }) => {
178
+ if (!value || !levels.includes(value as BtwThinkingLevel)) return { kind: "rejected" };
179
+ try {
180
+ await updateSettings(
181
+ { thinkingLevel: value as BtwThinkingLevel },
182
+ { settingsPath, signal },
183
+ );
184
+ if (signal.aborted) return { kind: "rejected" };
185
+ notifySafely(ctx, `Pi BTW thinking level: ${value}.`, "info");
186
+ return { kind: "stay" };
187
+ } catch (error) {
188
+ if (!signal.aborted) notifySaveFailure(ctx, error);
189
+ return { kind: "rejected" };
190
+ }
191
+ },
192
+ "set-remember": async ({ value, signal }) => {
193
+ if (value !== "On" && value !== "Off") return { kind: "rejected" };
194
+ try {
195
+ await updateSettings(
196
+ { rememberThinkingLevelChanges: value === "On" },
197
+ { settingsPath, signal },
198
+ );
199
+ if (signal.aborted) return { kind: "rejected" };
200
+ notifySafely(ctx, `Remember thinking level changes: ${value}.`, "info");
201
+ return { kind: "stay" };
202
+ } catch (error) {
203
+ if (!signal.aborted) notifySaveFailure(ctx, error);
204
+ return { kind: "rejected" };
205
+ }
206
+ },
207
+ },
208
+ });
209
+
210
+ const result = await runBtwMenuPreservingEditor(ctx, (menuContext) =>
211
+ runMenu(menuContext, menu, { getState: loadState }),
212
+ );
213
+ if (result.kind !== "closed" || result.reason !== "close") return "closed";
214
+ if (resumedThreadId) return { kind: "resume", threadId: resumedThreadId };
215
+ return startSelected ? "start" : "closed";
216
+ }
217
+
218
+ export async function runBtwMenuPreservingEditor(
219
+ ctx: ExtensionCommandContext,
220
+ run: (menuContext: MenuContext) => Promise<RunMenuResult>,
221
+ ): Promise<RunMenuResult> {
222
+ let liveEditorText = ctx.ui.getEditorText();
223
+ let completed = false;
224
+ const ui = new Proxy(ctx.ui, {
225
+ get(target, property) {
226
+ if (property === "custom") {
227
+ return <Value>(factory: BtwCustomFactory<Value>, customOptions?: BtwCustomOptions) =>
228
+ target.custom<Value>(
229
+ (tui, theme, keybindings, done) =>
230
+ factory(tui, theme, keybindings, (value) => {
231
+ try {
232
+ liveEditorText = target.getEditorText();
233
+ } catch {
234
+ // Keep completion finite if session replacement invalidates the editor context.
235
+ }
236
+ completed = true;
237
+ done(value);
238
+ }),
239
+ customOptions,
240
+ );
241
+ }
242
+ const value = Reflect.get(target, property, target) as unknown;
243
+ return typeof value === "function" ? value.bind(target) : value;
244
+ },
245
+ });
246
+ const result = await run({ mode: ctx.mode, hasUI: ctx.hasUI, ui });
247
+ if (result.kind !== "stale" && completed) {
248
+ try {
249
+ if (ctx.ui.getEditorText() !== liveEditorText) ctx.ui.setEditorText(liveEditorText);
250
+ } catch {
251
+ // A replaced context owns a different editor and must not receive stale restoration.
252
+ }
253
+ }
254
+ return result;
255
+ }
256
+
257
+ function clampToAvailableThinkingLevel(
258
+ requested: BtwThinkingLevel,
259
+ available: readonly BtwThinkingLevel[],
260
+ ): BtwThinkingLevel {
261
+ if (available.includes(requested)) return requested;
262
+ const requestedIndex = BTW_THINKING_LEVELS.indexOf(requested);
263
+ for (let index = requestedIndex; index < BTW_THINKING_LEVELS.length; index += 1) {
264
+ const candidate = BTW_THINKING_LEVELS[index];
265
+ if (candidate && available.includes(candidate)) return candidate;
266
+ }
267
+ for (let index = requestedIndex - 1; index >= 0; index -= 1) {
268
+ const candidate = BTW_THINKING_LEVELS[index];
269
+ if (candidate && available.includes(candidate)) return candidate;
270
+ }
271
+ return available[0] ?? "off";
272
+ }
273
+
274
+ function notifySaveFailure(ctx: ExtensionCommandContext, error: unknown): void {
275
+ notifySafely(
276
+ ctx,
277
+ `Pi BTW settings were not saved; the previous value remains active: ${formatError(error)}`,
278
+ "error",
279
+ );
280
+ }
281
+
282
+ function notifySafely(
283
+ ctx: ExtensionCommandContext,
284
+ message: string,
285
+ level: Parameters<ExtensionCommandContext["ui"]["notify"]>[1],
286
+ ): void {
287
+ try {
288
+ ctx.ui.notify(sanitizeSingleLine(message), level);
289
+ } catch {
290
+ // A completed save remains valid if its command context was replaced before notification.
291
+ }
292
+ }
293
+
294
+ function formatError(error: unknown): string {
295
+ return error instanceof Error ? error.message : String(error);
296
+ }