@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,237 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { constants } from "node:fs";
3
+ import { mkdir, open, rename, rm, writeFile } from "node:fs/promises";
4
+ import { basename, dirname, join } from "node:path";
5
+ import { getAgentDir } from "@earendil-works/pi-coding-agent";
6
+ import { BTW_THINKING_LEVELS, type BtwThinkingLevel } from "./side-thread.js";
7
+
8
+ export const BTW_SETTINGS_FILE = "pi-btw.json";
9
+ export const DEFAULT_REMEMBER_THINKING_LEVEL_CHANGES = true;
10
+ const MAX_SETTINGS_BYTES = 64 * 1024;
11
+
12
+ export interface BtwSettings {
13
+ model?: string;
14
+ thinkingLevel?: BtwThinkingLevel;
15
+ rememberThinkingLevelChanges?: boolean;
16
+ }
17
+
18
+ export type BtwSettingsLoadResult =
19
+ | { kind: "missing" }
20
+ | { kind: "invalid"; reason: string }
21
+ | { kind: "loaded"; settings: BtwSettings };
22
+
23
+ export interface UpdateBtwSettingsOptions {
24
+ settingsPath?: string;
25
+ signal?: AbortSignal;
26
+ beforeRename?: (temporaryPath: string, settingsPath: string) => Promise<void>;
27
+ }
28
+
29
+ type SettingsDocument = Record<string, unknown>;
30
+
31
+ const mutationQueues = new Map<string, Promise<void>>();
32
+
33
+ export function btwSettingsPath(): string {
34
+ return join(getAgentDir(), BTW_SETTINGS_FILE);
35
+ }
36
+
37
+ export function normalizeBtwSettings(value: unknown): BtwSettings | undefined {
38
+ if (!isSettingsDocument(value)) return undefined;
39
+
40
+ const settings: BtwSettings = {};
41
+ if (Object.hasOwn(value, "model")) {
42
+ const model = Reflect.get(value, "model");
43
+ if (typeof model !== "string" || !parseBtwModelReference(model)) return undefined;
44
+ settings.model = model;
45
+ }
46
+ if (Object.hasOwn(value, "thinkingLevel")) {
47
+ const thinkingLevel = Reflect.get(value, "thinkingLevel");
48
+ if (!isBtwThinkingLevel(thinkingLevel)) return undefined;
49
+ settings.thinkingLevel = thinkingLevel;
50
+ }
51
+ if (Object.hasOwn(value, "rememberThinkingLevelChanges")) {
52
+ const remember = Reflect.get(value, "rememberThinkingLevelChanges");
53
+ if (typeof remember !== "boolean") return undefined;
54
+ settings.rememberThinkingLevelChanges = remember;
55
+ }
56
+ return settings;
57
+ }
58
+
59
+ export function parseBtwModelReference(
60
+ reference: string,
61
+ ): { provider: string; modelId: string } | undefined {
62
+ if (/[\s\p{Cc}]/u.test(reference)) return undefined;
63
+ const separator = reference.indexOf("/");
64
+ if (separator <= 0 || separator === reference.length - 1) return undefined;
65
+ return { provider: reference.slice(0, separator), modelId: reference.slice(separator + 1) };
66
+ }
67
+
68
+ export function effectiveRememberThinkingLevelChanges(settings: BtwSettings): boolean {
69
+ return settings.rememberThinkingLevelChanges ?? DEFAULT_REMEMBER_THINKING_LEVEL_CHANGES;
70
+ }
71
+
72
+ export async function readBtwSettings(
73
+ settingsPath = btwSettingsPath(),
74
+ ): Promise<BtwSettingsLoadResult> {
75
+ await awaitBtwSettingsWrites(settingsPath);
76
+ return readBtwSettingsUncoordinated(settingsPath);
77
+ }
78
+
79
+ export function updateBtwSettings(
80
+ patch: Partial<Pick<BtwSettings, "thinkingLevel" | "rememberThinkingLevelChanges">>,
81
+ options: UpdateBtwSettingsOptions = {},
82
+ ): Promise<BtwSettings> {
83
+ const settingsPath = options.settingsPath ?? btwSettingsPath();
84
+ return enqueueMutation(settingsPath, async () => {
85
+ options.signal?.throwIfAborted();
86
+ const current = await readSettingsDocumentForUpdate(settingsPath);
87
+ const updated: SettingsDocument = { ...current, ...patch };
88
+ const settings = normalizeBtwSettings(updated);
89
+ if (!settings) throw invalidSettingsError(settingsPath, "invalid settings shape");
90
+ await publishSettings(settingsPath, updated, options.signal, options.beforeRename);
91
+ return settings;
92
+ });
93
+ }
94
+
95
+ export async function awaitBtwSettingsWrites(settingsPath = btwSettingsPath()): Promise<void> {
96
+ await mutationQueues.get(settingsPath);
97
+ }
98
+
99
+ function enqueueMutation<T>(settingsPath: string, mutation: () => Promise<T>): Promise<T> {
100
+ const previous = mutationQueues.get(settingsPath) ?? Promise.resolve();
101
+ const result = previous.then(mutation, mutation);
102
+ const settled = result.then(
103
+ () => undefined,
104
+ () => undefined,
105
+ );
106
+ mutationQueues.set(settingsPath, settled);
107
+ void settled.finally(() => {
108
+ if (mutationQueues.get(settingsPath) === settled) mutationQueues.delete(settingsPath);
109
+ });
110
+ return result;
111
+ }
112
+
113
+ async function readBtwSettingsUncoordinated(settingsPath: string): Promise<BtwSettingsLoadResult> {
114
+ let contents: string;
115
+ try {
116
+ contents = await readSettingsContents(settingsPath);
117
+ } catch (error: unknown) {
118
+ if (isNodeError(error) && error.code === "ENOENT") return { kind: "missing" };
119
+ return { kind: "invalid", reason: `${settingsPath}: ${formatError(error)}` };
120
+ }
121
+
122
+ try {
123
+ const settings = normalizeBtwSettings(JSON.parse(contents) as unknown);
124
+ return settings
125
+ ? { kind: "loaded", settings }
126
+ : { kind: "invalid", reason: `${settingsPath}: invalid settings shape` };
127
+ } catch {
128
+ return { kind: "invalid", reason: `${settingsPath}: invalid JSON` };
129
+ }
130
+ }
131
+
132
+ async function readSettingsDocumentForUpdate(settingsPath: string): Promise<SettingsDocument> {
133
+ let contents: string;
134
+ try {
135
+ contents = await readSettingsContents(settingsPath);
136
+ } catch (error: unknown) {
137
+ if (isNodeError(error) && error.code === "ENOENT") return {};
138
+ throw invalidSettingsError(settingsPath, formatError(error));
139
+ }
140
+
141
+ let parsed: unknown;
142
+ try {
143
+ parsed = JSON.parse(contents) as unknown;
144
+ } catch {
145
+ throw invalidSettingsError(settingsPath, "invalid JSON");
146
+ }
147
+ if (!isSettingsDocument(parsed) || !normalizeBtwSettings(parsed)) {
148
+ throw invalidSettingsError(settingsPath, "invalid settings shape");
149
+ }
150
+ return parsed;
151
+ }
152
+
153
+ async function readSettingsContents(settingsPath: string): Promise<string> {
154
+ const flags = constants.O_RDONLY | (constants.O_NONBLOCK ?? 0);
155
+ const handle = await open(settingsPath, flags);
156
+ try {
157
+ const descriptorStats = await handle.stat();
158
+ if (!descriptorStats.isFile()) throw new Error("settings path is not a regular file");
159
+ if (descriptorStats.size > MAX_SETTINGS_BYTES) {
160
+ throw new Error(`settings file exceeds ${MAX_SETTINGS_BYTES} bytes`);
161
+ }
162
+
163
+ const buffer = Buffer.alloc(MAX_SETTINGS_BYTES + 1);
164
+ let offset = 0;
165
+ while (offset < buffer.byteLength) {
166
+ const { bytesRead } = await handle.read(buffer, offset, buffer.byteLength - offset, offset);
167
+ if (bytesRead === 0) break;
168
+ offset += bytesRead;
169
+ }
170
+ if (offset > MAX_SETTINGS_BYTES) {
171
+ throw new Error(`settings file exceeds ${MAX_SETTINGS_BYTES} bytes`);
172
+ }
173
+ try {
174
+ return new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(
175
+ buffer.subarray(0, offset),
176
+ );
177
+ } catch {
178
+ throw new Error("settings file is not valid UTF-8");
179
+ }
180
+ } finally {
181
+ await handle.close();
182
+ }
183
+ }
184
+
185
+ async function publishSettings(
186
+ settingsPath: string,
187
+ document: SettingsDocument,
188
+ signal?: AbortSignal,
189
+ beforeRename?: (temporaryPath: string, settingsPath: string) => Promise<void>,
190
+ ): Promise<void> {
191
+ signal?.throwIfAborted();
192
+ const contents = `${JSON.stringify(document, null, 2)}\n`;
193
+ if (Buffer.byteLength(contents, "utf8") > MAX_SETTINGS_BYTES) {
194
+ throw new Error(`settings document exceeds ${MAX_SETTINGS_BYTES} bytes`);
195
+ }
196
+ const directory = dirname(settingsPath);
197
+ await mkdir(directory, { recursive: true });
198
+ signal?.throwIfAborted();
199
+ const temporaryPath = join(
200
+ directory,
201
+ `.${basename(settingsPath)}.${process.pid}.${randomUUID()}.tmp`,
202
+ );
203
+ try {
204
+ await writeFile(temporaryPath, contents, {
205
+ encoding: "utf8",
206
+ flag: "wx",
207
+ mode: 0o600,
208
+ signal,
209
+ });
210
+ await beforeRename?.(temporaryPath, settingsPath);
211
+ signal?.throwIfAborted();
212
+ await rename(temporaryPath, settingsPath);
213
+ } catch (error) {
214
+ await rm(temporaryPath, { force: true }).catch(() => undefined);
215
+ throw error;
216
+ }
217
+ }
218
+
219
+ function isSettingsDocument(value: unknown): value is SettingsDocument {
220
+ return typeof value === "object" && value !== null && !Array.isArray(value);
221
+ }
222
+
223
+ function isBtwThinkingLevel(value: unknown): value is BtwThinkingLevel {
224
+ return BTW_THINKING_LEVELS.includes(value as BtwThinkingLevel);
225
+ }
226
+
227
+ function invalidSettingsError(settingsPath: string, reason: string): Error {
228
+ return new Error(`pi-btw settings at ${settingsPath} are invalid: ${reason}`);
229
+ }
230
+
231
+ function isNodeError(error: unknown): error is NodeJS.ErrnoException {
232
+ return error instanceof Error && "code" in error;
233
+ }
234
+
235
+ function formatError(error: unknown): string {
236
+ return error instanceof Error ? error.message : String(error);
237
+ }
@@ -0,0 +1,238 @@
1
+ import type {
2
+ Api,
3
+ AssistantMessage,
4
+ Context,
5
+ Message,
6
+ Model,
7
+ ProviderHeaders,
8
+ SimpleStreamOptions,
9
+ UserMessage,
10
+ } from "@earendil-works/pi-ai";
11
+
12
+ export const BTW_THINKING_LEVELS = [
13
+ "off",
14
+ "minimal",
15
+ "low",
16
+ "medium",
17
+ "high",
18
+ "xhigh",
19
+ "max",
20
+ ] as const;
21
+
22
+ export type BtwThinkingLevel = (typeof BTW_THINKING_LEVELS)[number];
23
+
24
+ export interface SideQuestionAuth {
25
+ apiKey?: string;
26
+ headers?: ProviderHeaders;
27
+ env?: Record<string, string>;
28
+ }
29
+
30
+ export type CompleteSimpleFunction = <TApi extends Api>(
31
+ model: Model<TApi>,
32
+ context: Context,
33
+ options?: SimpleStreamOptions,
34
+ ) => Promise<AssistantMessage>;
35
+
36
+ export type SideThreadTurn =
37
+ | {
38
+ kind: "answered";
39
+ question: string;
40
+ answer: string;
41
+ response: AssistantMessage;
42
+ }
43
+ | {
44
+ kind: "error";
45
+ question: string;
46
+ answer: string;
47
+ };
48
+
49
+ export interface SideThread {
50
+ conversationContext: string;
51
+ turns: SideThreadTurn[];
52
+ }
53
+
54
+ export function createSideThread(conversationContext: string): SideThread {
55
+ return { conversationContext, turns: [] };
56
+ }
57
+
58
+ export function buildSideThreadMessages(thread: SideThread, question: string): Message[] {
59
+ const answeredTurns = thread.turns.filter(
60
+ (turn): turn is Extract<SideThreadTurn, { kind: "answered" }> => turn.kind === "answered",
61
+ );
62
+ const messages: Message[] = [];
63
+
64
+ if (answeredTurns.length === 0) {
65
+ messages.push(createUserMessage(buildUserPrompt(question, thread.conversationContext)));
66
+ return messages;
67
+ }
68
+
69
+ const [first, ...rest] = answeredTurns;
70
+ messages.push(
71
+ createUserMessage(buildUserPrompt(first.question, thread.conversationContext)),
72
+ first.response,
73
+ );
74
+ for (const turn of rest) {
75
+ messages.push(createUserMessage(buildFollowUpPrompt(turn.question)), turn.response);
76
+ }
77
+ messages.push(createUserMessage(buildFollowUpPrompt(question)));
78
+ return messages;
79
+ }
80
+
81
+ export interface CompleteSideThreadTurnOptions {
82
+ thread: SideThread;
83
+ model: Model<Api>;
84
+ question: string;
85
+ thinkingLevel: BtwThinkingLevel;
86
+ auth: SideQuestionAuth;
87
+ signal?: AbortSignal;
88
+ completeSimple: CompleteSimpleFunction;
89
+ }
90
+
91
+ export type CompleteSideThreadTurnResult =
92
+ | { kind: "answered"; response: AssistantMessage; answer: string }
93
+ | { kind: "aborted" }
94
+ | { kind: "error"; message: string };
95
+
96
+ export async function completeSideThreadTurn({
97
+ thread,
98
+ model,
99
+ question,
100
+ thinkingLevel,
101
+ auth,
102
+ signal,
103
+ completeSimple,
104
+ }: CompleteSideThreadTurnOptions): Promise<CompleteSideThreadTurnResult> {
105
+ if (signal?.aborted) return { kind: "aborted" };
106
+ try {
107
+ const response = await completeSimple(
108
+ model,
109
+ { systemPrompt: SYSTEM_PROMPT, messages: buildSideThreadMessages(thread, question) },
110
+ buildStreamOptions(auth, thinkingLevel, signal),
111
+ );
112
+ if (signal?.aborted || response?.stopReason === "aborted") return { kind: "aborted" };
113
+ if (!isAssistantMessage(response)) {
114
+ return { kind: "error", message: "The side model returned a malformed response." };
115
+ }
116
+ if (response.stopReason === "error") {
117
+ return {
118
+ kind: "error",
119
+ message: response.errorMessage ?? "The side model returned an error.",
120
+ };
121
+ }
122
+
123
+ const answer = extractAssistantText(response) || "No response received.";
124
+ thread.turns.push({ kind: "answered", question, answer, response });
125
+ return { kind: "answered", response, answer };
126
+ } catch (error: unknown) {
127
+ if (signal?.aborted) return { kind: "aborted" };
128
+ return { kind: "error", message: formatError(error) };
129
+ }
130
+ }
131
+
132
+ export interface CompleteSideQuestionOptions {
133
+ model: Model<Api>;
134
+ question: string;
135
+ conversationContext: string;
136
+ thinkingLevel: BtwThinkingLevel;
137
+ auth: SideQuestionAuth;
138
+ signal?: AbortSignal;
139
+ completeSimple: CompleteSimpleFunction;
140
+ }
141
+
142
+ export async function completeSideQuestion({
143
+ model,
144
+ question,
145
+ conversationContext,
146
+ thinkingLevel,
147
+ auth,
148
+ signal,
149
+ completeSimple,
150
+ }: CompleteSideQuestionOptions): Promise<AssistantMessage> {
151
+ return completeSimple(
152
+ model,
153
+ {
154
+ systemPrompt: SYSTEM_PROMPT,
155
+ messages: [createUserMessage(buildUserPrompt(question, conversationContext))],
156
+ },
157
+ buildStreamOptions(auth, thinkingLevel, signal),
158
+ );
159
+ }
160
+
161
+ export function extractAssistantText(response: AssistantMessage): string {
162
+ return response.content
163
+ .filter(
164
+ (content): content is { type: "text"; text: string } =>
165
+ content !== null &&
166
+ typeof content === "object" &&
167
+ content.type === "text" &&
168
+ typeof content.text === "string",
169
+ )
170
+ .map((content) => content.text)
171
+ .join("\n")
172
+ .trim();
173
+ }
174
+
175
+ function isAssistantMessage(value: unknown): value is AssistantMessage {
176
+ if (value === null || typeof value !== "object") return false;
177
+ const candidate = value as Partial<AssistantMessage>;
178
+ return (
179
+ candidate.role === "assistant" &&
180
+ Array.isArray(candidate.content) &&
181
+ typeof candidate.stopReason === "string"
182
+ );
183
+ }
184
+
185
+ export function buildUserPrompt(question: string, conversationContext: string): string {
186
+ return [
187
+ "Answer this side question without modifying the main conversation.",
188
+ "",
189
+ "<side_question>",
190
+ question,
191
+ "</side_question>",
192
+ "",
193
+ "<conversation_context>",
194
+ conversationContext || "No prior conversation context was available.",
195
+ "</conversation_context>",
196
+ ].join("\n");
197
+ }
198
+
199
+ export function buildFollowUpPrompt(question: string): string {
200
+ return [
201
+ "Continue the same side conversation.",
202
+ "",
203
+ "<side_question>",
204
+ question,
205
+ "</side_question>",
206
+ ].join("\n");
207
+ }
208
+
209
+ function createUserMessage(text: string): UserMessage {
210
+ return {
211
+ role: "user",
212
+ content: [{ type: "text", text }],
213
+ timestamp: Date.now(),
214
+ };
215
+ }
216
+
217
+ function buildStreamOptions(
218
+ auth: SideQuestionAuth,
219
+ thinkingLevel: BtwThinkingLevel,
220
+ signal?: AbortSignal,
221
+ ): SimpleStreamOptions {
222
+ const options: SimpleStreamOptions = {
223
+ apiKey: auth.apiKey,
224
+ headers: auth.headers,
225
+ env: auth.env,
226
+ signal,
227
+ };
228
+ if (thinkingLevel !== "off") options.reasoning = thinkingLevel;
229
+ return options;
230
+ }
231
+
232
+ function formatError(error: unknown): string {
233
+ return error instanceof Error ? error.message : String(error);
234
+ }
235
+
236
+ const SYSTEM_PROMPT = `You answer quick side questions for a coding-agent user.
237
+
238
+ Use the provided conversation context only as background. Answer the user's side question directly and concisely. Do not claim to have changed files, run tools, or affected the main task. If the context is insufficient, say what is unknown and give the best next step.`;
@@ -0,0 +1,10 @@
1
+ export function sanitizeSingleLine(text: string): string {
2
+ return [...text.replace(/[\r\n\t]/gu, " ")]
3
+ .filter((character) => {
4
+ const code = character.charCodeAt(0);
5
+ return code > 31 && (code < 127 || code > 159);
6
+ })
7
+ .join("")
8
+ .replace(/ +/gu, " ")
9
+ .trim();
10
+ }