@herbertgao/pi-extensions 2026.8.2 → 2026.8.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (392) hide show
  1. package/README.md +50 -2
  2. package/examples/pi-footer.json +275 -0
  3. package/node_modules/@herbertgao/pi-cc-extensions/README.en.md +6 -8
  4. package/node_modules/@herbertgao/pi-cc-extensions/README.md +5 -7
  5. package/node_modules/@herbertgao/pi-cc-extensions/assets/readme/hero.en.svg +101 -0
  6. package/node_modules/@herbertgao/pi-cc-extensions/extensions/config/config.ts +1 -17
  7. package/node_modules/@herbertgao/pi-cc-extensions/extensions/config/panel.ts +5 -3
  8. package/node_modules/@herbertgao/pi-cc-extensions/extensions/{utils/agent-summary.ts → feature/agent-summary/core.ts} +37 -35
  9. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/{agent-summary.ts → agent-summary/index.ts} +2 -6
  10. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/{session-reference.ts → reference/index.ts} +1 -1
  11. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/{agent-autocomplete.ts → reference/subagent.ts} +19 -9
  12. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/{pi-startup-header.ts → shell/startup-header.ts} +1 -1
  13. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/{working-message.ts → shell/working-message.ts} +5 -2
  14. package/node_modules/@herbertgao/pi-cc-extensions/extensions/index.ts +32 -28
  15. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/compact-mode.ts +379 -85
  16. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/default-mode.ts +727 -0
  17. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/index.ts +65 -775
  18. package/node_modules/@herbertgao/pi-cc-extensions/extensions/{feature → renderer}/markdown-enhance.ts +35 -31
  19. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{mouse-hover.ts → mouse/hover.ts} +5 -5
  20. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{mouse-interaction.ts → mouse/interaction.ts} +34 -35
  21. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{mouse-layout.ts → mouse/layout.ts} +5 -21
  22. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{mouse-packets.ts → mouse/packets.ts} +1 -1
  23. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{mouse-scroll.ts → mouse/scroll.ts} +48 -37
  24. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-diff → tool/diff}/ansi-utils.ts +56 -1
  25. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-diff → tool/diff}/diff-renderer.ts +2 -2
  26. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-diff → tool/diff}/line-width-safety.ts +1 -1
  27. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/write-display-utils.ts +12 -0
  28. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-diff → tool/diff}/write-execution.ts +1 -2
  29. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-grouping.ts → tool/grouping.ts} +18 -8
  30. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-result.ts → tool/result.ts} +4 -13
  31. package/node_modules/@herbertgao/pi-cc-extensions/extensions/utils/fullscreen-detect.ts +0 -27
  32. package/node_modules/@herbertgao/pi-cc-extensions/package.json +3 -3
  33. package/node_modules/@herbertgao/pi-subagents/CHANGELOG.md +6 -0
  34. package/node_modules/@herbertgao/pi-subagents/package.json +2 -2
  35. package/node_modules/@herbertgao/pi-subagents/src/agent-manager.ts +1 -0
  36. package/node_modules/@herbertgao/pi-subagents/src/agent-runner.ts +3 -1
  37. package/node_modules/@herbertgao/pi-subagents/src/index.ts +33 -35
  38. package/node_modules/@herbertgao/pi-subagents/src/nested-tools.ts +26 -35
  39. package/node_modules/@herbertgao/pi-subagents/src/prompts.ts +15 -1
  40. package/node_modules/pi-footer/CHANGELOG.md +145 -0
  41. package/node_modules/pi-footer/LICENSE +21 -0
  42. package/node_modules/pi-footer/README.md +354 -0
  43. package/node_modules/pi-footer/package.json +68 -0
  44. package/node_modules/pi-footer/src/cache.ts +106 -0
  45. package/node_modules/pi-footer/src/colors.ts +237 -0
  46. package/node_modules/pi-footer/src/config.ts +202 -0
  47. package/node_modules/pi-footer/src/event-widgets.ts +41 -0
  48. package/node_modules/pi-footer/src/extension-statuses.ts +102 -0
  49. package/node_modules/pi-footer/src/git.ts +135 -0
  50. package/node_modules/pi-footer/src/index.ts +268 -0
  51. package/node_modules/pi-footer/src/metrics.ts +141 -0
  52. package/node_modules/pi-footer/src/presets.ts +383 -0
  53. package/node_modules/pi-footer/src/render.ts +114 -0
  54. package/node_modules/pi-footer/src/separators.ts +52 -0
  55. package/node_modules/pi-footer/src/types.ts +122 -0
  56. package/node_modules/pi-footer/src/ui/color-level-confirm.ts +22 -0
  57. package/node_modules/pi-footer/src/ui/color-options.ts +195 -0
  58. package/node_modules/pi-footer/src/ui/config-lifecycle.ts +61 -0
  59. package/node_modules/pi-footer/src/ui/edit-colors.ts +13 -0
  60. package/node_modules/pi-footer/src/ui/events.ts +35 -0
  61. package/node_modules/pi-footer/src/ui/extension-status-picker.ts +60 -0
  62. package/node_modules/pi-footer/src/ui/extension-statuses.ts +73 -0
  63. package/node_modules/pi-footer/src/ui/fields.ts +252 -0
  64. package/node_modules/pi-footer/src/ui/global-menu.ts +126 -0
  65. package/node_modules/pi-footer/src/ui/helpers.ts +44 -0
  66. package/node_modules/pi-footer/src/ui/layout.ts +17 -0
  67. package/node_modules/pi-footer/src/ui/line-list.ts +19 -0
  68. package/node_modules/pi-footer/src/ui/model.ts +64 -0
  69. package/node_modules/pi-footer/src/ui/navigation.ts +29 -0
  70. package/node_modules/pi-footer/src/ui/option-edit.ts +93 -0
  71. package/node_modules/pi-footer/src/ui/overlay-render.ts +103 -0
  72. package/node_modules/pi-footer/src/ui/screen-context.ts +18 -0
  73. package/node_modules/pi-footer/src/ui/screen-controller.ts +27 -0
  74. package/node_modules/pi-footer/src/ui/screen-render.ts +32 -0
  75. package/node_modules/pi-footer/src/ui/screen-state.ts +20 -0
  76. package/node_modules/pi-footer/src/ui/screen.ts +243 -0
  77. package/node_modules/pi-footer/src/ui/screens/add-widget.ts +92 -0
  78. package/node_modules/pi-footer/src/ui/screens/confirm-exit.ts +52 -0
  79. package/node_modules/pi-footer/src/ui/screens/controller.ts +12 -0
  80. package/node_modules/pi-footer/src/ui/screens/edit-colors.ts +68 -0
  81. package/node_modules/pi-footer/src/ui/screens/edit-widget.ts +115 -0
  82. package/node_modules/pi-footer/src/ui/screens/extension-status-row.ts +61 -0
  83. package/node_modules/pi-footer/src/ui/screens/global.ts +75 -0
  84. package/node_modules/pi-footer/src/ui/screens/line-list.ts +108 -0
  85. package/node_modules/pi-footer/src/ui/screens/main.ts +99 -0
  86. package/node_modules/pi-footer/src/ui/screens/terminal.ts +121 -0
  87. package/node_modules/pi-footer/src/ui/screens/widget-list.ts +154 -0
  88. package/node_modules/pi-footer/src/ui/terminal-menu.ts +32 -0
  89. package/node_modules/pi-footer/src/ui/theme.ts +48 -0
  90. package/node_modules/pi-footer/src/ui/title-bar.ts +100 -0
  91. package/node_modules/pi-footer/src/ui/widget-actions.ts +76 -0
  92. package/node_modules/pi-footer/src/ui.ts +66 -0
  93. package/node_modules/pi-footer/src/widgets/context.ts +28 -0
  94. package/node_modules/pi-footer/src/widgets/core/active-tools.ts +17 -0
  95. package/node_modules/pi-footer/src/widgets/core/context-window.ts +24 -0
  96. package/node_modules/pi-footer/src/widgets/core/cwd-basename.ts +19 -0
  97. package/node_modules/pi-footer/src/widgets/core/cwd.ts +108 -0
  98. package/node_modules/pi-footer/src/widgets/core/event.ts +34 -0
  99. package/node_modules/pi-footer/src/widgets/core/external-status.ts +102 -0
  100. package/node_modules/pi-footer/src/widgets/core/model-provider.ts +20 -0
  101. package/node_modules/pi-footer/src/widgets/core/model.ts +35 -0
  102. package/node_modules/pi-footer/src/widgets/core/provider.ts +17 -0
  103. package/node_modules/pi-footer/src/widgets/core/session-name.ts +17 -0
  104. package/node_modules/pi-footer/src/widgets/core/text-verbosity.ts +17 -0
  105. package/node_modules/pi-footer/src/widgets/core/thinking-level.ts +17 -0
  106. package/node_modules/pi-footer/src/widgets/git/ahead-behind.ts +17 -0
  107. package/node_modules/pi-footer/src/widgets/git/branch.ts +81 -0
  108. package/node_modules/pi-footer/src/widgets/git/clean.ts +19 -0
  109. package/node_modules/pi-footer/src/widgets/git/deletions.ts +17 -0
  110. package/node_modules/pi-footer/src/widgets/git/diff.ts +38 -0
  111. package/node_modules/pi-footer/src/widgets/git/insertions.ts +17 -0
  112. package/node_modules/pi-footer/src/widgets/git/remote.ts +17 -0
  113. package/node_modules/pi-footer/src/widgets/git/root.ts +17 -0
  114. package/node_modules/pi-footer/src/widgets/git/sha.ts +17 -0
  115. package/node_modules/pi-footer/src/widgets/git/staged.ts +17 -0
  116. package/node_modules/pi-footer/src/widgets/git/status.ts +19 -0
  117. package/node_modules/pi-footer/src/widgets/git/unstaged.ts +17 -0
  118. package/node_modules/pi-footer/src/widgets/git/untracked.ts +17 -0
  119. package/node_modules/pi-footer/src/widgets/instance.ts +118 -0
  120. package/node_modules/pi-footer/src/widgets/layout/custom-text.ts +18 -0
  121. package/node_modules/pi-footer/src/widgets/layout/flex-separator.ts +32 -0
  122. package/node_modules/pi-footer/src/widgets/layout/separator.ts +57 -0
  123. package/node_modules/pi-footer/src/widgets/layout/spacer.ts +31 -0
  124. package/node_modules/pi-footer/src/widgets/options.ts +122 -0
  125. package/node_modules/pi-footer/src/widgets/project/runtime.ts +361 -0
  126. package/node_modules/pi-footer/src/widgets/registry.ts +223 -0
  127. package/node_modules/pi-footer/src/widgets/session/assistant-messages.ts +17 -0
  128. package/node_modules/pi-footer/src/widgets/session/compactions.ts +17 -0
  129. package/node_modules/pi-footer/src/widgets/session/elapsed.ts +18 -0
  130. package/node_modules/pi-footer/src/widgets/session/last-activity.ts +18 -0
  131. package/node_modules/pi-footer/src/widgets/session/messages.ts +19 -0
  132. package/node_modules/pi-footer/src/widgets/session/session-id.ts +17 -0
  133. package/node_modules/pi-footer/src/widgets/session/session-start.ts +18 -0
  134. package/node_modules/pi-footer/src/widgets/session/tool-results.ts +17 -0
  135. package/node_modules/pi-footer/src/widgets/session/total-messages.ts +19 -0
  136. package/node_modules/pi-footer/src/widgets/session/total-time.ts +18 -0
  137. package/node_modules/pi-footer/src/widgets/session/user-messages.ts +17 -0
  138. package/node_modules/pi-footer/src/widgets/store.ts +26 -0
  139. package/node_modules/pi-footer/src/widgets/tokens/cache-hit-rate.ts +55 -0
  140. package/node_modules/pi-footer/src/widgets/tokens/cache-read.ts +18 -0
  141. package/node_modules/pi-footer/src/widgets/tokens/cache-write.ts +18 -0
  142. package/node_modules/pi-footer/src/widgets/tokens/context-bar.ts +108 -0
  143. package/node_modules/pi-footer/src/widgets/tokens/context-length.ts +26 -0
  144. package/node_modules/pi-footer/src/widgets/tokens/context-remaining.ts +29 -0
  145. package/node_modules/pi-footer/src/widgets/tokens/context.ts +29 -0
  146. package/node_modules/pi-footer/src/widgets/tokens/cost.ts +51 -0
  147. package/node_modules/pi-footer/src/widgets/tokens/input-speed.ts +25 -0
  148. package/node_modules/pi-footer/src/widgets/tokens/input-tokens.ts +18 -0
  149. package/node_modules/pi-footer/src/widgets/tokens/output-speed.ts +25 -0
  150. package/node_modules/pi-footer/src/widgets/tokens/output-tokens.ts +18 -0
  151. package/node_modules/pi-footer/src/widgets/tokens/tokens.ts +20 -0
  152. package/node_modules/pi-footer/src/widgets/tokens/total-speed.ts +25 -0
  153. package/node_modules/pi-footer/src/widgets/tokens/total-tokens.ts +18 -0
  154. package/node_modules/pi-footer/src/widgets/types.ts +181 -0
  155. package/node_modules/pi-footer/src/widgets/utils/colors.ts +11 -0
  156. package/node_modules/pi-footer/src/widgets/utils/context.ts +112 -0
  157. package/node_modules/pi-footer/src/widgets/utils/session.ts +19 -0
  158. package/node_modules/pi-footer/src/widgets/utils/token-format.ts +78 -0
  159. package/node_modules/pi-mcp-adapter/CHANGELOG.md +19 -0
  160. package/node_modules/pi-mcp-adapter/README.md +19 -4
  161. package/node_modules/pi-mcp-adapter/agent-dir.ts +40 -0
  162. package/node_modules/pi-mcp-adapter/commands.ts +12 -2
  163. package/node_modules/pi-mcp-adapter/direct-tools.ts +6 -8
  164. package/node_modules/pi-mcp-adapter/index.ts +15 -3
  165. package/node_modules/pi-mcp-adapter/mcp-auth-flow.ts +87 -4
  166. package/node_modules/pi-mcp-adapter/mcp-callback-server.ts +138 -61
  167. package/node_modules/pi-mcp-adapter/mcp-oauth-provider.ts +43 -4
  168. package/node_modules/pi-mcp-adapter/oauth.ts +48 -0
  169. package/node_modules/pi-mcp-adapter/package.json +8 -2
  170. package/node_modules/pi-mcp-adapter/proxy-modes.ts +8 -10
  171. package/node_modules/pi-mcp-adapter/tool-registrar.ts +187 -3
  172. package/node_modules/pi-mcp-adapter/types.ts +2 -0
  173. package/node_modules/pi-web-access/CHANGELOG.md +45 -0
  174. package/node_modules/pi-web-access/README.md +104 -29
  175. package/node_modules/pi-web-access/bocha.ts +221 -0
  176. package/node_modules/pi-web-access/curator-page.ts +113 -12
  177. package/node_modules/pi-web-access/curator-server.ts +56 -20
  178. package/node_modules/pi-web-access/datalab-pdf-extract.ts +568 -0
  179. package/node_modules/pi-web-access/duckduckgo.ts +123 -0
  180. package/node_modules/pi-web-access/extract.ts +288 -143
  181. package/node_modules/pi-web-access/feature-config.ts +29 -0
  182. package/node_modules/pi-web-access/gemini-api.ts +4 -0
  183. package/node_modules/pi-web-access/gemini-search.ts +45 -12
  184. package/node_modules/pi-web-access/gemini-web.ts +68 -3
  185. package/node_modules/pi-web-access/index.ts +160 -71
  186. package/node_modules/pi-web-access/jina-search.ts +284 -0
  187. package/node_modules/pi-web-access/kagi.ts +12 -12
  188. package/node_modules/pi-web-access/openai-search.ts +12 -2
  189. package/node_modules/pi-web-access/package.json +4 -3
  190. package/node_modules/pi-web-access/pdf-extract.ts +327 -228
  191. package/node_modules/pi-web-access/storage.ts +440 -2
  192. package/node_modules/pi-web-access/summary-model-scope.ts +1 -1
  193. package/node_modules/pi-web-access/summary-review.ts +4 -2
  194. package/node_modules/pi-web-access/video-extract.ts +10 -8
  195. package/node_modules/pi-web-access/xai-search.ts +12 -2
  196. package/node_modules/pi-web-access/youtube-extract.ts +2 -1
  197. package/node_modules/remote-pi/LICENSE +21 -0
  198. package/node_modules/remote-pi/README.md +675 -0
  199. package/node_modules/remote-pi/dist/actions/handlers.d.ts +122 -0
  200. package/node_modules/remote-pi/dist/actions/handlers.js +160 -0
  201. package/node_modules/remote-pi/dist/actions/handlers.js.map +1 -0
  202. package/node_modules/remote-pi/dist/actions/registry.d.ts +39 -0
  203. package/node_modules/remote-pi/dist/actions/registry.js +58 -0
  204. package/node_modules/remote-pi/dist/actions/registry.js.map +1 -0
  205. package/node_modules/remote-pi/dist/bin/supervisord.d.ts +2 -0
  206. package/node_modules/remote-pi/dist/bin/supervisord.js +86 -0
  207. package/node_modules/remote-pi/dist/bin/supervisord.js.map +1 -0
  208. package/node_modules/remote-pi/dist/commands/builtin_mirror.d.ts +58 -0
  209. package/node_modules/remote-pi/dist/commands/builtin_mirror.js +71 -0
  210. package/node_modules/remote-pi/dist/commands/builtin_mirror.js.map +1 -0
  211. package/node_modules/remote-pi/dist/commands/list_commands.d.ts +60 -0
  212. package/node_modules/remote-pi/dist/commands/list_commands.js +73 -0
  213. package/node_modules/remote-pi/dist/commands/list_commands.js.map +1 -0
  214. package/node_modules/remote-pi/dist/config.d.ts +62 -0
  215. package/node_modules/remote-pi/dist/config.js +115 -0
  216. package/node_modules/remote-pi/dist/config.js.map +1 -0
  217. package/node_modules/remote-pi/dist/daemon/client.d.ts +20 -0
  218. package/node_modules/remote-pi/dist/daemon/client.js +131 -0
  219. package/node_modules/remote-pi/dist/daemon/client.js.map +1 -0
  220. package/node_modules/remote-pi/dist/daemon/control_protocol.d.ts +176 -0
  221. package/node_modules/remote-pi/dist/daemon/control_protocol.js +63 -0
  222. package/node_modules/remote-pi/dist/daemon/control_protocol.js.map +1 -0
  223. package/node_modules/remote-pi/dist/daemon/cron_log.d.ts +45 -0
  224. package/node_modules/remote-pi/dist/daemon/cron_log.js +72 -0
  225. package/node_modules/remote-pi/dist/daemon/cron_log.js.map +1 -0
  226. package/node_modules/remote-pi/dist/daemon/cron_registry.d.ts +80 -0
  227. package/node_modules/remote-pi/dist/daemon/cron_registry.js +194 -0
  228. package/node_modules/remote-pi/dist/daemon/cron_registry.js.map +1 -0
  229. package/node_modules/remote-pi/dist/daemon/id.d.ts +24 -0
  230. package/node_modules/remote-pi/dist/daemon/id.js +36 -0
  231. package/node_modules/remote-pi/dist/daemon/id.js.map +1 -0
  232. package/node_modules/remote-pi/dist/daemon/install.d.ts +170 -0
  233. package/node_modules/remote-pi/dist/daemon/install.js +547 -0
  234. package/node_modules/remote-pi/dist/daemon/install.js.map +1 -0
  235. package/node_modules/remote-pi/dist/daemon/registry.d.ts +63 -0
  236. package/node_modules/remote-pi/dist/daemon/registry.js +153 -0
  237. package/node_modules/remote-pi/dist/daemon/registry.js.map +1 -0
  238. package/node_modules/remote-pi/dist/daemon/rpc_child.d.ts +194 -0
  239. package/node_modules/remote-pi/dist/daemon/rpc_child.js +389 -0
  240. package/node_modules/remote-pi/dist/daemon/rpc_child.js.map +1 -0
  241. package/node_modules/remote-pi/dist/daemon/supervisor.d.ts +93 -0
  242. package/node_modules/remote-pi/dist/daemon/supervisor.js +596 -0
  243. package/node_modules/remote-pi/dist/daemon/supervisor.js.map +1 -0
  244. package/node_modules/remote-pi/dist/extension_ui_bridge.d.ts +26 -0
  245. package/node_modules/remote-pi/dist/extension_ui_bridge.js +341 -0
  246. package/node_modules/remote-pi/dist/extension_ui_bridge.js.map +1 -0
  247. package/node_modules/remote-pi/dist/index.d.ts +213 -0
  248. package/node_modules/remote-pi/dist/index.js +4996 -0
  249. package/node_modules/remote-pi/dist/index.js.map +1 -0
  250. package/node_modules/remote-pi/dist/mcp/mesh_result.d.ts +10 -0
  251. package/node_modules/remote-pi/dist/mcp/mesh_result.js +42 -0
  252. package/node_modules/remote-pi/dist/mcp/mesh_result.js.map +1 -0
  253. package/node_modules/remote-pi/dist/mcp/mesh_server.d.ts +16 -0
  254. package/node_modules/remote-pi/dist/mcp/mesh_server.js +327 -0
  255. package/node_modules/remote-pi/dist/mcp/mesh_server.js.map +1 -0
  256. package/node_modules/remote-pi/dist/mesh/canonical.d.ts +30 -0
  257. package/node_modules/remote-pi/dist/mesh/canonical.js +61 -0
  258. package/node_modules/remote-pi/dist/mesh/canonical.js.map +1 -0
  259. package/node_modules/remote-pi/dist/mesh/client.d.ts +18 -0
  260. package/node_modules/remote-pi/dist/mesh/client.js +125 -0
  261. package/node_modules/remote-pi/dist/mesh/client.js.map +1 -0
  262. package/node_modules/remote-pi/dist/mesh/encoding.d.ts +38 -0
  263. package/node_modules/remote-pi/dist/mesh/encoding.js +216 -0
  264. package/node_modules/remote-pi/dist/mesh/encoding.js.map +1 -0
  265. package/node_modules/remote-pi/dist/mesh/self_revoke.d.ts +73 -0
  266. package/node_modules/remote-pi/dist/mesh/self_revoke.js +401 -0
  267. package/node_modules/remote-pi/dist/mesh/self_revoke.js.map +1 -0
  268. package/node_modules/remote-pi/dist/mesh/siblings.d.ts +49 -0
  269. package/node_modules/remote-pi/dist/mesh/siblings.js +159 -0
  270. package/node_modules/remote-pi/dist/mesh/siblings.js.map +1 -0
  271. package/node_modules/remote-pi/dist/mesh/types.d.ts +34 -0
  272. package/node_modules/remote-pi/dist/mesh/types.js +11 -0
  273. package/node_modules/remote-pi/dist/mesh/types.js.map +1 -0
  274. package/node_modules/remote-pi/dist/mesh/verify.d.ts +17 -0
  275. package/node_modules/remote-pi/dist/mesh/verify.js +86 -0
  276. package/node_modules/remote-pi/dist/mesh/verify.js.map +1 -0
  277. package/node_modules/remote-pi/dist/pairing/crypto.d.ts +8 -0
  278. package/node_modules/remote-pi/dist/pairing/crypto.js +22 -0
  279. package/node_modules/remote-pi/dist/pairing/crypto.js.map +1 -0
  280. package/node_modules/remote-pi/dist/pairing/handshake.d.ts +28 -0
  281. package/node_modules/remote-pi/dist/pairing/handshake.js +113 -0
  282. package/node_modules/remote-pi/dist/pairing/handshake.js.map +1 -0
  283. package/node_modules/remote-pi/dist/pairing/noise-sha256.d.ts +16 -0
  284. package/node_modules/remote-pi/dist/pairing/noise-sha256.js +103 -0
  285. package/node_modules/remote-pi/dist/pairing/noise-sha256.js.map +1 -0
  286. package/node_modules/remote-pi/dist/pairing/qr.d.ts +59 -0
  287. package/node_modules/remote-pi/dist/pairing/qr.js +125 -0
  288. package/node_modules/remote-pi/dist/pairing/qr.js.map +1 -0
  289. package/node_modules/remote-pi/dist/pairing/storage.d.ts +120 -0
  290. package/node_modules/remote-pi/dist/pairing/storage.js +604 -0
  291. package/node_modules/remote-pi/dist/pairing/storage.js.map +1 -0
  292. package/node_modules/remote-pi/dist/protocol/codec.d.ts +7 -0
  293. package/node_modules/remote-pi/dist/protocol/codec.js +49 -0
  294. package/node_modules/remote-pi/dist/protocol/codec.js.map +1 -0
  295. package/node_modules/remote-pi/dist/protocol/types.d.ts +393 -0
  296. package/node_modules/remote-pi/dist/protocol/types.js +2 -0
  297. package/node_modules/remote-pi/dist/protocol/types.js.map +1 -0
  298. package/node_modules/remote-pi/dist/rooms.d.ts +29 -0
  299. package/node_modules/remote-pi/dist/rooms.js +57 -0
  300. package/node_modules/remote-pi/dist/rooms.js.map +1 -0
  301. package/node_modules/remote-pi/dist/session/address.d.ts +49 -0
  302. package/node_modules/remote-pi/dist/session/address.js +58 -0
  303. package/node_modules/remote-pi/dist/session/address.js.map +1 -0
  304. package/node_modules/remote-pi/dist/session/agent_bridge.d.ts +55 -0
  305. package/node_modules/remote-pi/dist/session/agent_bridge.js +146 -0
  306. package/node_modules/remote-pi/dist/session/agent_bridge.js.map +1 -0
  307. package/node_modules/remote-pi/dist/session/bridge.d.ts +37 -0
  308. package/node_modules/remote-pi/dist/session/bridge.js +130 -0
  309. package/node_modules/remote-pi/dist/session/bridge.js.map +1 -0
  310. package/node_modules/remote-pi/dist/session/broker.d.ts +189 -0
  311. package/node_modules/remote-pi/dist/session/broker.js +507 -0
  312. package/node_modules/remote-pi/dist/session/broker.js.map +1 -0
  313. package/node_modules/remote-pi/dist/session/broker_remote.d.ts +74 -0
  314. package/node_modules/remote-pi/dist/session/broker_remote.js +583 -0
  315. package/node_modules/remote-pi/dist/session/broker_remote.js.map +1 -0
  316. package/node_modules/remote-pi/dist/session/cwd_lock.d.ts +33 -0
  317. package/node_modules/remote-pi/dist/session/cwd_lock.js +126 -0
  318. package/node_modules/remote-pi/dist/session/cwd_lock.js.map +1 -0
  319. package/node_modules/remote-pi/dist/session/envelope.d.ts +33 -0
  320. package/node_modules/remote-pi/dist/session/envelope.js +117 -0
  321. package/node_modules/remote-pi/dist/session/envelope.js.map +1 -0
  322. package/node_modules/remote-pi/dist/session/global_config.d.ts +33 -0
  323. package/node_modules/remote-pi/dist/session/global_config.js +73 -0
  324. package/node_modules/remote-pi/dist/session/global_config.js.map +1 -0
  325. package/node_modules/remote-pi/dist/session/ipc.d.ts +27 -0
  326. package/node_modules/remote-pi/dist/session/ipc.js +22 -0
  327. package/node_modules/remote-pi/dist/session/ipc.js.map +1 -0
  328. package/node_modules/remote-pi/dist/session/leader_election.d.ts +32 -0
  329. package/node_modules/remote-pi/dist/session/leader_election.js +106 -0
  330. package/node_modules/remote-pi/dist/session/leader_election.js.map +1 -0
  331. package/node_modules/remote-pi/dist/session/local_config.d.ts +55 -0
  332. package/node_modules/remote-pi/dist/session/local_config.js +157 -0
  333. package/node_modules/remote-pi/dist/session/local_config.js.map +1 -0
  334. package/node_modules/remote-pi/dist/session/mesh_message.d.ts +20 -0
  335. package/node_modules/remote-pi/dist/session/mesh_message.js +28 -0
  336. package/node_modules/remote-pi/dist/session/mesh_message.js.map +1 -0
  337. package/node_modules/remote-pi/dist/session/mesh_node.d.ts +116 -0
  338. package/node_modules/remote-pi/dist/session/mesh_node.js +573 -0
  339. package/node_modules/remote-pi/dist/session/mesh_node.js.map +1 -0
  340. package/node_modules/remote-pi/dist/session/peer.d.ts +139 -0
  341. package/node_modules/remote-pi/dist/session/peer.js +451 -0
  342. package/node_modules/remote-pi/dist/session/peer.js.map +1 -0
  343. package/node_modules/remote-pi/dist/session/peer_inventory.d.ts +13 -0
  344. package/node_modules/remote-pi/dist/session/peer_inventory.js +48 -0
  345. package/node_modules/remote-pi/dist/session/peer_inventory.js.map +1 -0
  346. package/node_modules/remote-pi/dist/session/peer_limits.d.ts +9 -0
  347. package/node_modules/remote-pi/dist/session/peer_limits.js +21 -0
  348. package/node_modules/remote-pi/dist/session/peer_limits.js.map +1 -0
  349. package/node_modules/remote-pi/dist/session/setup_wizard.d.ts +39 -0
  350. package/node_modules/remote-pi/dist/session/setup_wizard.js +63 -0
  351. package/node_modules/remote-pi/dist/session/setup_wizard.js.map +1 -0
  352. package/node_modules/remote-pi/dist/session/tool_gate.d.ts +5 -0
  353. package/node_modules/remote-pi/dist/session/tool_gate.js +11 -0
  354. package/node_modules/remote-pi/dist/session/tool_gate.js.map +1 -0
  355. package/node_modules/remote-pi/dist/session/tools.d.ts +24 -0
  356. package/node_modules/remote-pi/dist/session/tools.js +252 -0
  357. package/node_modules/remote-pi/dist/session/tools.js.map +1 -0
  358. package/node_modules/remote-pi/dist/session/wizard.d.ts +13 -0
  359. package/node_modules/remote-pi/dist/session/wizard.js +20 -0
  360. package/node_modules/remote-pi/dist/session/wizard.js.map +1 -0
  361. package/node_modules/remote-pi/dist/settings.d.ts +15 -0
  362. package/node_modules/remote-pi/dist/settings.js +52 -0
  363. package/node_modules/remote-pi/dist/settings.js.map +1 -0
  364. package/node_modules/remote-pi/dist/transport/peer_channel.d.ts +37 -0
  365. package/node_modules/remote-pi/dist/transport/peer_channel.js +98 -0
  366. package/node_modules/remote-pi/dist/transport/peer_channel.js.map +1 -0
  367. package/node_modules/remote-pi/dist/transport/pi_forward_client.d.ts +29 -0
  368. package/node_modules/remote-pi/dist/transport/pi_forward_client.js +62 -0
  369. package/node_modules/remote-pi/dist/transport/pi_forward_client.js.map +1 -0
  370. package/node_modules/remote-pi/dist/transport/relay_client.d.ts +91 -0
  371. package/node_modules/remote-pi/dist/transport/relay_client.js +206 -0
  372. package/node_modules/remote-pi/dist/transport/relay_client.js.map +1 -0
  373. package/node_modules/remote-pi/dist/ui/footer.d.ts +32 -0
  374. package/node_modules/remote-pi/dist/ui/footer.js +34 -0
  375. package/node_modules/remote-pi/dist/ui/footer.js.map +1 -0
  376. package/node_modules/remote-pi/docs/daemon.md +289 -0
  377. package/node_modules/remote-pi/package.json +88 -0
  378. package/node_modules/remote-pi/service-templates/launchd.plist.template +35 -0
  379. package/node_modules/remote-pi/service-templates/systemd.service.template +19 -0
  380. package/node_modules/remote-pi/service-templates/task-launcher.vbs.template +10 -0
  381. package/node_modules/remote-pi/service-templates/task-scheduler.xml.template +38 -0
  382. package/node_modules/remote-pi/skills/agent-network/SKILL.md +310 -0
  383. package/package.json +25 -10
  384. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool-diff/write-display-utils.ts +0 -29
  385. /package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/{session-reference-core.ts → reference/session.ts} +0 -0
  386. /package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/{pi-aliases.ts → shell/aliases.ts} +0 -0
  387. /package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-diff → tool/diff}/ATTRIBUTION.md +0 -0
  388. /package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-diff → tool/diff}/diff-presentation.ts +0 -0
  389. /package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-diff → tool/diff}/index.ts +0 -0
  390. /package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-diff → tool/diff}/render-utils.ts +0 -0
  391. /package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-diff → tool/diff}/shiki-highlight.ts +0 -0
  392. /package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-diff → tool/diff}/types.ts +0 -0
@@ -0,0 +1,18 @@
1
+ import { defineWidget } from "../types.js";
2
+ import { formatTokenCount, tokenFormatStyleProperty } from "../utils/token-format.js";
3
+
4
+ export const OutputTokensWidget = defineWidget({
5
+ type: "output-tokens",
6
+ label: "Output Tokens",
7
+ category: "Tokens",
8
+ description: "Output token total",
9
+ dependencies: ["metrics"],
10
+ baseOptions: ["raw", "hideWhenZero", "icon"],
11
+ baseOptionDefaults: {},
12
+ properties: [tokenFormatStyleProperty()],
13
+ icons: { emoji: "⬇️", nerd: "󰧚", text: "out" },
14
+ defaultStyle: { fg: "white", bg: "default", bold: false },
15
+ render({ ctx, options, renderWidget }) {
16
+ return renderWidget(formatTokenCount(ctx.metrics.outputTokens, options.tokenFormatStyle));
17
+ },
18
+ });
@@ -0,0 +1,20 @@
1
+ import { defineWidget } from "../types.js";
2
+ import { formatTokenCount, tokenFormatStyleProperty } from "../utils/token-format.js";
3
+
4
+ export const TokensWidget = defineWidget({
5
+ type: "tokens",
6
+ label: "Input/Output Tokens",
7
+ category: "Tokens",
8
+ description: "Input and output token totals",
9
+ dependencies: ["metrics"],
10
+ baseOptions: ["raw", "icon"],
11
+ baseOptionDefaults: {},
12
+ properties: [tokenFormatStyleProperty()],
13
+ icons: { emoji: "🔢", nerd: "󰓹", text: "tok" },
14
+ defaultStyle: { fg: "cyan", bg: "default", bold: false },
15
+ render({ ctx, options, renderWidget }) {
16
+ return renderWidget(
17
+ `↑${formatTokenCount(ctx.metrics.inputTokens, options.tokenFormatStyle)} ↓${formatTokenCount(ctx.metrics.outputTokens, options.tokenFormatStyle)}`,
18
+ );
19
+ },
20
+ });
@@ -0,0 +1,25 @@
1
+ import { defineWidget } from "../types.js";
2
+ import { formatTokenSpeed, tokenFormatStyleProperty } from "../utils/token-format.js";
3
+
4
+ export const TotalSpeedWidget = defineWidget({
5
+ type: "total-speed",
6
+ label: "Total Speed",
7
+ category: "Tokens",
8
+ description: "Average total tokens per minute",
9
+ dependencies: ["metrics"],
10
+ baseOptions: ["raw", "hideWhenZero", "icon"],
11
+ baseOptionDefaults: {},
12
+ properties: [tokenFormatStyleProperty()],
13
+ icons: { emoji: "⚡", nerd: "↕", text: "tok/min" },
14
+ defaultStyle: { fg: "brightGreen", bg: "default", bold: false },
15
+ render({ ctx, options, renderWidget }) {
16
+ return renderWidget(
17
+ formatTokenSpeed(
18
+ ctx.metrics.totalTokens,
19
+ ctx.metrics.firstTimestampMs,
20
+ ctx.metrics.lastTimestampMs,
21
+ options.tokenFormatStyle,
22
+ ),
23
+ );
24
+ },
25
+ });
@@ -0,0 +1,18 @@
1
+ import { defineWidget } from "../types.js";
2
+ import { formatTokenCount, tokenFormatStyleProperty } from "../utils/token-format.js";
3
+
4
+ export const TotalTokensWidget = defineWidget({
5
+ type: "total-tokens",
6
+ label: "Total Tokens",
7
+ category: "Tokens",
8
+ description: "Total token count",
9
+ dependencies: ["metrics"],
10
+ baseOptions: ["raw", "hideWhenZero", "icon"],
11
+ baseOptionDefaults: {},
12
+ properties: [tokenFormatStyleProperty()],
13
+ icons: { emoji: "🔢", nerd: "󰓹", text: "tok" },
14
+ defaultStyle: { fg: "cyan", bg: "default", bold: false },
15
+ render({ ctx, options, renderWidget }) {
16
+ return renderWidget(formatTokenCount(ctx.metrics.totalTokens, options.tokenFormatStyle));
17
+ },
18
+ });
@@ -0,0 +1,181 @@
1
+ import type { Theme } from "@earendil-works/pi-coding-agent";
2
+
3
+ import type { ColorLevel } from "../colors.js";
4
+ import type { GetExtensionStatuses } from "../extension-statuses.js";
5
+ import type {
6
+ IconMode,
7
+ StatuslineData,
8
+ WidgetEntry,
9
+ WidgetOptions,
10
+ WidgetStyle,
11
+ } from "../types.js";
12
+
13
+ export interface WidgetIconSet {
14
+ emoji: string;
15
+ nerd: string;
16
+ text: string;
17
+ }
18
+
19
+ export type PropertyKind = "boolean" | "number" | "choice" | "text";
20
+
21
+ export interface ChoiceOption<TId extends string = string> {
22
+ id: TId;
23
+ label: string;
24
+ list: string;
25
+ }
26
+
27
+ export type WidgetPropertyDefault = string | number | boolean;
28
+
29
+ // Edit-action discriminant for properties that open a dedicated editor flow. Extend as needed.
30
+ export type WidgetEditAction = "external-status-key";
31
+
32
+ export interface WidgetProperty {
33
+ id: string;
34
+ label: string;
35
+ kind: PropertyKind;
36
+ description: string;
37
+ default: WidgetPropertyDefault;
38
+ showWhen?: {
39
+ property: string;
40
+ equals: string | number | boolean;
41
+ };
42
+ options?: {
43
+ min?: number;
44
+ max?: number;
45
+ choices?: readonly ChoiceOption[];
46
+ label?: string;
47
+ showInFields?: boolean;
48
+ showInWidgets?: boolean;
49
+ showInColors?: boolean;
50
+ listProperty?: string;
51
+ quoteValue?: boolean;
52
+ editAction?: WidgetEditAction;
53
+ };
54
+ }
55
+
56
+ export type WidgetBaseOption = "raw" | "hideWhenEmpty" | "hideWhenZero" | "text" | "icon";
57
+
58
+ export interface WidgetRenderOptions extends WidgetStyle {
59
+ icons?: WidgetIconSet;
60
+ preservedTrimStyles?: string;
61
+ stripIncomingStyles?: boolean;
62
+ }
63
+
64
+ // The widget dependency set is the materialized snapshot (StatuslineData) plus the one live
65
+ // accessor that must never enter the snapshot — see F1 / pi live-accessor rule.
66
+ export type WidgetDependencyValues = StatuslineData & {
67
+ getExtensionStatuses: GetExtensionStatuses | undefined;
68
+ };
69
+
70
+ export type WidgetDependency = keyof WidgetDependencyValues;
71
+
72
+ export interface BaseWidgetContext {
73
+ iconMode: IconMode;
74
+ minimalist: boolean;
75
+ colorLevel: ColorLevel;
76
+ theme?: Theme;
77
+ requestRender?: () => void;
78
+ }
79
+
80
+ export type WidgetContext<TDeps extends readonly WidgetDependency[] = readonly []> =
81
+ BaseWidgetContext & Pick<WidgetDependencyValues, TDeps[number]>;
82
+
83
+ export type WidgetInstanceOptions<TOptions extends object> = WidgetOptions & TOptions;
84
+
85
+ export interface Widget<TOptions extends object = {}> {
86
+ readonly entry: WidgetEntry;
87
+ readonly id: string;
88
+ readonly type: WidgetEntry["type"];
89
+ enabled: boolean;
90
+ options: WidgetInstanceOptions<TOptions>;
91
+
92
+ render(ctx: WidgetContext): string | undefined;
93
+ toggle(enabled?: boolean): void;
94
+ update(options: Partial<WidgetInstanceOptions<TOptions>>): void;
95
+ toEntry(): WidgetEntry;
96
+ }
97
+
98
+ type BaseOptionsToObject<TBaseOptions extends readonly WidgetBaseOption[]> = Required<
99
+ Pick<WidgetOptions, TBaseOptions[number]>
100
+ >;
101
+
102
+ type WidgetChoiceValue<TProperty> = TProperty extends {
103
+ readonly kind: "choice";
104
+ readonly options: { readonly choices: readonly (infer TChoice)[] };
105
+ }
106
+ ? TChoice extends { readonly id: infer TId extends string }
107
+ ? TId
108
+ : string
109
+ : string;
110
+
111
+ type WidgetPropertyValue<TProperty extends Pick<WidgetProperty, "kind">> =
112
+ TProperty["kind"] extends "boolean"
113
+ ? boolean
114
+ : TProperty["kind"] extends "number"
115
+ ? number
116
+ : TProperty["kind"] extends "choice"
117
+ ? WidgetChoiceValue<TProperty>
118
+ : string;
119
+
120
+ type PropertiesToObject<TProperties extends readonly WidgetProperty[]> = {
121
+ [TProperty in TProperties[number] as TProperty["id"]]: WidgetPropertyValue<TProperty>;
122
+ };
123
+
124
+ export type OptionsFor<TSpec extends Pick<WidgetSpec, "baseOptions" | "properties">> =
125
+ WidgetOptions &
126
+ BaseOptionsToObject<TSpec["baseOptions"]> &
127
+ PropertiesToObject<TSpec["properties"]> &
128
+ WidgetStyle;
129
+
130
+ export type ContextFor<TSpec extends Pick<WidgetSpec, "dependencies">> = BaseWidgetContext &
131
+ Pick<WidgetDependencyValues, TSpec["dependencies"][number]>;
132
+
133
+ export interface TypedWidgetRenderArgs<
134
+ TSpec extends Pick<WidgetSpec, "dependencies" | "baseOptions" | "properties">,
135
+ > {
136
+ readonly ctx: ContextFor<TSpec>;
137
+ readonly options: OptionsFor<TSpec>;
138
+ readonly renderWidget: (
139
+ value: string | undefined,
140
+ renderOptions?: WidgetRenderOptions,
141
+ ) => string | undefined;
142
+ }
143
+
144
+ export interface WidgetSpec<
145
+ TType extends string = string,
146
+ TCategory extends string = string,
147
+ TDependencies extends readonly WidgetDependency[] = readonly WidgetDependency[],
148
+ TBaseOptions extends readonly WidgetBaseOption[] = readonly WidgetBaseOption[],
149
+ TProperties extends readonly WidgetProperty[] = readonly WidgetProperty[],
150
+ > {
151
+ readonly type: TType;
152
+ readonly label: string;
153
+ readonly category: TCategory;
154
+ readonly description: string;
155
+ readonly dependencies: TDependencies;
156
+ readonly baseOptions: TBaseOptions;
157
+ readonly baseOptionDefaults?: Partial<WidgetOptions>;
158
+ readonly properties: TProperties;
159
+ readonly icons: WidgetIconSet;
160
+ readonly defaultStyle: WidgetStyle;
161
+ readonly createOptionDefaults?: () => Partial<WidgetOptions>;
162
+ render(
163
+ args: TypedWidgetRenderArgs<{
164
+ readonly dependencies: TDependencies;
165
+ readonly baseOptions: TBaseOptions;
166
+ readonly properties: TProperties;
167
+ }>,
168
+ ): string | undefined;
169
+ }
170
+
171
+ export function defineWidget<
172
+ const TType extends string,
173
+ const TCategory extends string,
174
+ const TDependencies extends readonly WidgetDependency[],
175
+ const TBaseOptions extends readonly WidgetBaseOption[],
176
+ const TProperties extends readonly WidgetProperty[],
177
+ >(
178
+ spec: WidgetSpec<TType, TCategory, TDependencies, TBaseOptions, TProperties>,
179
+ ): WidgetSpec<TType, TCategory, TDependencies, TBaseOptions, TProperties> {
180
+ return spec;
181
+ }
@@ -0,0 +1,11 @@
1
+ import type { ColorName } from "../../colors.js";
2
+
3
+ export function colorPair(
4
+ fg: ColorName | undefined,
5
+ bg: ColorName | undefined,
6
+ ): { fg?: ColorName; bg?: ColorName } {
7
+ return {
8
+ ...(fg === undefined ? {} : { fg }),
9
+ ...(bg === undefined ? {} : { bg }),
10
+ };
11
+ }
@@ -0,0 +1,112 @@
1
+ import { normalizeColor, type ConditionalColorFields } from "../../colors.js";
2
+ import type { WidgetOptions } from "../../types.js";
3
+ import { colorPair } from "./colors.js";
4
+
5
+ export function contextPercent(tokens: number | undefined, maxTokens: number | undefined) {
6
+ if (tokens === undefined || maxTokens === undefined || maxTokens <= 0) return undefined;
7
+ return Math.min(100, Math.max(0, (tokens / maxTokens) * 100));
8
+ }
9
+
10
+ interface ContextColorOptions extends WidgetOptions, ConditionalColorFields {
11
+ contextConditionalColors: boolean;
12
+ contextWarningPercent: number;
13
+ contextDangerPercent: number;
14
+ }
15
+
16
+ export function contextColors(
17
+ options: ContextColorOptions,
18
+ contextTokens: number | undefined,
19
+ contextMaxTokens: number | undefined,
20
+ ) {
21
+ if (!options.contextConditionalColors) return colorPair(options.fg, options.bg);
22
+ const percent = contextPercent(contextTokens, contextMaxTokens);
23
+ if (percent === undefined) return colorPair(options.fg, options.bg);
24
+
25
+ if (percent >= options.contextDangerPercent) {
26
+ return colorPair(
27
+ normalizeColor(options.dangerFg) ?? options.fg,
28
+ normalizeColor(options.dangerBg) ?? options.bg,
29
+ );
30
+ }
31
+
32
+ if (percent >= options.contextWarningPercent) {
33
+ return colorPair(
34
+ normalizeColor(options.warningFg) ?? options.fg,
35
+ normalizeColor(options.warningBg) ?? options.bg,
36
+ );
37
+ }
38
+
39
+ return colorPair(options.fg, options.bg);
40
+ }
41
+
42
+ export function contextColorProperties() {
43
+ return [
44
+ {
45
+ id: "contextConditionalColors",
46
+ label: "Conditional colors",
47
+ kind: "boolean",
48
+ description: "Use warning/danger colors based on context usage",
49
+ default: false,
50
+ options: {
51
+ label: "with-colors",
52
+ showInWidgets: true,
53
+ showInColors: true,
54
+ listProperty: "",
55
+ },
56
+ },
57
+ {
58
+ id: "contextWarningPercent",
59
+ label: "Warning zone threshold",
60
+ kind: "number",
61
+ description: "Context usage percentage for warning colors",
62
+ default: 70,
63
+ showWhen: { property: "contextConditionalColors", equals: true },
64
+ options: { min: 0, max: 100, showInWidgets: false, showInColors: false },
65
+ },
66
+ {
67
+ id: "contextDangerPercent",
68
+ label: "Danger zone threshold",
69
+ kind: "number",
70
+ description: "Context usage percentage for danger colors",
71
+ default: 90,
72
+ showWhen: { property: "contextConditionalColors", equals: true },
73
+ options: { min: 0, max: 100, showInWidgets: false, showInColors: false },
74
+ },
75
+ {
76
+ id: "warningFg",
77
+ label: "Warning foreground",
78
+ kind: "text",
79
+ description: "Warning foreground",
80
+ default: "yellow",
81
+ showWhen: { property: "contextConditionalColors", equals: true },
82
+ options: { showInFields: false, showInWidgets: false, showInColors: false },
83
+ },
84
+ {
85
+ id: "warningBg",
86
+ label: "Warning background",
87
+ kind: "text",
88
+ description: "Warning background",
89
+ default: "default",
90
+ showWhen: { property: "contextConditionalColors", equals: true },
91
+ options: { showInFields: false, showInWidgets: false, showInColors: false },
92
+ },
93
+ {
94
+ id: "dangerFg",
95
+ label: "Danger foreground",
96
+ kind: "text",
97
+ description: "Danger foreground",
98
+ default: "red",
99
+ showWhen: { property: "contextConditionalColors", equals: true },
100
+ options: { showInFields: false, showInWidgets: false, showInColors: false },
101
+ },
102
+ {
103
+ id: "dangerBg",
104
+ label: "Danger background",
105
+ kind: "text",
106
+ description: "Danger background",
107
+ default: "default",
108
+ showWhen: { property: "contextConditionalColors", equals: true },
109
+ options: { showInFields: false, showInWidgets: false, showInColors: false },
110
+ },
111
+ ] as const;
112
+ }
@@ -0,0 +1,19 @@
1
+ export function formatTime(timestamp: number | undefined): string {
2
+ if (timestamp === undefined) return "";
3
+ return new Date(timestamp).toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" });
4
+ }
5
+
6
+ function formatDuration(ms: number): string {
7
+ if (!Number.isFinite(ms) || ms <= 0) return "0m";
8
+ const totalMinutes = Math.max(1, Math.floor(ms / 60_000));
9
+ const hours = Math.floor(totalMinutes / 60);
10
+ const minutes = totalMinutes % 60;
11
+ if (hours === 0) return `${minutes}m`;
12
+ return minutes === 0 ? `${hours}h` : `${hours}h ${minutes}m`;
13
+ }
14
+
15
+ export function formatElapsed(first: number | undefined, last: number | undefined): string {
16
+ if (first === undefined) return "0m";
17
+ const end = last === undefined || last < first ? Date.now() : last;
18
+ return formatDuration(end - first);
19
+ }
@@ -0,0 +1,78 @@
1
+ export function formatCount(value: number) {
2
+ if (value < 1000) return `${value}`;
3
+ if (value < 1000000) return `${trimFixed(value / 1000, 1)}k`;
4
+ return `${trimFixed(value / 1000000, 1)}m`;
5
+ }
6
+
7
+ export function formatPiTokenCount(value: number) {
8
+ if (value < 1000) return `${value}`;
9
+ if (value < 10000) return `${(value / 1000).toFixed(1)}k`;
10
+ if (value < 1000000) return `${Math.round(value / 1000)}k`;
11
+ if (value < 10000000) return `${(value / 1000000).toFixed(1)}M`;
12
+ return `${Math.round(value / 1000000)}M`;
13
+ }
14
+
15
+ function trimFixed(value: number, digits: number) {
16
+ return value.toFixed(digits).replace(/\.0$/, "");
17
+ }
18
+ const TOKEN_FORMAT_STYLES = {
19
+ default: {
20
+ label: "Default",
21
+ list: "Default",
22
+ format: formatCount,
23
+ },
24
+ compact: {
25
+ label: "Compact",
26
+ list: "Compact",
27
+ format: formatPiTokenCount,
28
+ },
29
+ } as const;
30
+
31
+ export type TokenFormatStyle = keyof typeof TOKEN_FORMAT_STYLES;
32
+
33
+ const TOKEN_FORMAT_STYLE_VALUES = Object.keys(TOKEN_FORMAT_STYLES) as TokenFormatStyle[];
34
+
35
+ const TOKEN_FORMAT_CHOICES = TOKEN_FORMAT_STYLE_VALUES.map((style) => ({
36
+ id: style,
37
+ label: TOKEN_FORMAT_STYLES[style].label,
38
+ list: TOKEN_FORMAT_STYLES[style].list,
39
+ }));
40
+
41
+ export function formatTokenCount(value: number, style: TokenFormatStyle) {
42
+ return TOKEN_FORMAT_STYLES[style].format(value);
43
+ }
44
+
45
+ export function formatTokenSpeed(
46
+ tokens: number,
47
+ first: number | undefined,
48
+ last: number | undefined,
49
+ tokenFormatStyle: TokenFormatStyle,
50
+ ) {
51
+ if (
52
+ first === undefined ||
53
+ last === undefined ||
54
+ !Number.isFinite(first) ||
55
+ !Number.isFinite(last) ||
56
+ last <= first
57
+ ) {
58
+ return "0/min";
59
+ }
60
+ const minutes = Math.max((last - first) / 60000, 1 / 60);
61
+ return `${formatTokenCount(Math.round(tokens / minutes), tokenFormatStyle)}/min`;
62
+ }
63
+
64
+ export function tokenFormatStyleProperty() {
65
+ return {
66
+ id: "tokenFormatStyle",
67
+ label: "Token format",
68
+ kind: "choice",
69
+ description: "Token display format",
70
+ default: "default",
71
+ options: {
72
+ choices: TOKEN_FORMAT_CHOICES,
73
+ showInWidgets: true,
74
+ showInColors: false,
75
+ listProperty: "format",
76
+ },
77
+ } as const;
78
+ }
@@ -7,6 +7,25 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [2.23.0] - 2026-08-11
11
+
12
+ ### Added
13
+ - Added interactive callback URL pasting to `/mcp-auth` for OAuth flows running on remote or headless machines. Thanks @trevorleibert-mixpanel for PR #330.
14
+
15
+ ### Fixed
16
+ - Stopped load-time MCP initialization from printing a TUI startup error when Pi action methods are not bound yet. Thanks @21307369 for issue #327.
17
+ - Kept interactive OAuth authorization URLs clickable as a single terminal hyperlink. Thanks @rfccg for PR #329.
18
+
19
+ ## [2.22.0] - 2026-08-11
20
+
21
+ ### Added
22
+ - Added the `pi-mcp-adapter/oauth` subpath for URL-bound OAuth token reuse by cooperating Pi extensions. Thanks @ThePhoenixCoding for issue #323.
23
+ - Added `oauth.logoUri` for OAuth Dynamic Client Registration, with validation that requires an absolute HTTP(S) URL. Thanks @grinich for PR #321.
24
+
25
+ ### Fixed
26
+ - Materialized binary MCP resources as private temporary files before model-facing output, with bounded per-session cleanup. Thanks @zenworr and @shaworr for PR #324.
27
+ - Named OAuth callback pages and dynamic client registrations after rebranded Pi hosts, while preserving stock Pi defaults and avoiding guessed client homepages. Thanks @grinich for PR #320.
28
+
10
29
  ## [2.21.2] - 2026-08-09
11
30
 
12
31
  ### Fixed
@@ -153,6 +153,17 @@ A supplied `config` is a complete, isolated snapshot. It is not merged with file
153
153
 
154
154
  With `configPath` and no `config`, the adapter keeps normal file merge behavior, and that path takes precedence over argv and `--mcp-config`. The default export keeps the normal file-based behavior. OAuth credentials are stored in the operating system credential store and keyed by the configured server name; URL binding prevents credentials from being accepted for a different server URL. `settings.oauthDir` and `MCP_OAUTH_DIR` are used only as legacy plaintext import locations for older `tokens.json` files, not as credential namespaces. CSRF state and PKCE verifiers are flow-local, so concurrent authorization flows do not share transient secrets.
155
155
 
156
+ Cooperating Pi extensions can use `pi-mcp-adapter/oauth` to reuse URL-bound OAuth tokens without deep-importing private files:
157
+
158
+ ```ts
159
+ import { getMcpOAuthTokensForUrl, updateMcpOAuthTokensForUrl } from "pi-mcp-adapter/oauth";
160
+
161
+ const tokens = await getMcpOAuthTokensForUrl("jira", "https://jira.example.com/mcp");
162
+ updateMcpOAuthTokensForUrl("jira", "https://jira.example.com/mcp", { accessToken: "..." });
163
+ ```
164
+
165
+ The public subpath exposes only token read/update helpers plus a status helper. The async read path uses the adapter's refresh logic before it returns tokens. The helpers keep secure-store storage, URL binding, refresh persistence, chunk handling, legacy import, and fail-closed credential-store errors. They do not expose client registration secrets, PKCE verifiers, or OAuth state.
166
+
156
167
  ### Runtime status snapshots
157
168
 
158
169
  Extensions can subscribe to the adapter's versioned shared event-bus channel instead of parsing `/mcp` or `mcp({})` output:
@@ -203,7 +214,8 @@ In the configuration examples below, `30000` is illustrative only. If `requestTi
203
214
  | `oauth.scope` | Requested OAuth scopes |
204
215
  | `oauth.redirectUri` | Exact localhost redirect URI for browser OAuth, including port and path, for providers that pre-register callbacks |
205
216
  | `oauth.clientName` | Client display name advertised during Dynamic Client Registration fallback |
206
- | `oauth.clientUri` | Client homepage URI advertised during Dynamic Client Registration fallback |
217
+ | `oauth.clientUri` | Client homepage URI advertised during Dynamic Client Registration fallback. Defaults to `piConfig.clientUri` from the host's manifest when set, and is omitted rather than guessed under a rebranded host |
218
+ | `oauth.logoUri` | Client logo URL advertised during Dynamic Client Registration fallback (RFC 7591 `logo_uri`). Must be an absolute `http(s)` URL — consent screens fetch it server-side, so local paths render nothing. Omitted from the registration request when unset |
207
219
  | `oauth.skipIssuerMetadataValidation` | `true` disables the OAuth authorization-server metadata issuer check for this server. This weakens OAuth mix-up protection and should only be used for known-misconfigured internal servers while their metadata is being fixed. |
208
220
  | `bearerToken` / `bearerTokenEnv` | Token or env var name; `bearerToken` supports `${VAR}` and `$env:VAR` interpolation. A leading `!` in `bearerToken` runs a command when the HTTP server connects; use `!!` for a literal leading `!`. |
209
221
  | `lifecycle` | `"lazy"` (default), `"eager"`, `"keep-alive"`, or `"lazy-keep-alive"` |
@@ -253,7 +265,9 @@ The adapter owns only its client socket and closes that connection when the Pi r
253
265
 
254
266
  ### Remote/headless OAuth
255
267
 
256
- If Pi is running on a remote server and cannot open a local browser, start OAuth through the proxy tool. Persistent OAuth still requires an available OS credential store; on headless Linux that usually means an unlocked Secret Service/libsecret keyring. The adapter fails closed instead of falling back to plaintext credentials when the secure store is unavailable.
268
+ If Pi is running on a remote server, `/mcp-auth <server>` prints the authorization URL and opens a callback input. Open the URL in your local browser. After approval, the browser may fail to load the localhost callback page because localhost refers to your workstation; copy the full URL from its address bar and paste it into Pi. The input closes automatically instead when the browser can reach Pi's callback directly.
269
+
270
+ The same flow is available through the proxy tool for non-interactive clients. Persistent OAuth still requires an available OS credential store; on headless Linux that usually means an unlocked Secret Service/libsecret keyring. The adapter fails closed instead of falling back to plaintext credentials when the secure store is unavailable.
257
271
 
258
272
  On Linux, if credential access fails because Pi inherited a revoked session keyring, the adapter uses a best-effort recovery path through `keyctl session - node <packaged helper>` so explicit re-authentication can write fresh credentials without killing a long-lived tmux server. This path requires `keyctl` and `node` on `PATH`; missing, locked, or otherwise unavailable credential stores still fail closed.
259
273
 
@@ -372,9 +386,10 @@ Oversized MCP tool/resource results are guarded by default so a single huge resp
372
386
 
373
387
  - Inline text output is capped at **50 KiB / 2,000 lines** (matching Pi's built-in `bash` guard). Larger output is truncated to a head preview and the full text is saved to a temp file whose path is included in the result, so the agent can `read`/`grep` it.
374
388
  - **Image content blocks pass through unchanged** — only text output is guarded. Images are delivered to the provider as native image content.
389
+ - Binary resource blobs up to **10 MiB** are decoded to private temp files and replaced with file references. Each session is limited to **100 MiB** and **10,000 files**. The files are removed at session teardown.
375
390
  - In proxy mode, `details.mcpResult` is kept raw when its JSON is **≤ 16 KiB**; larger results are replaced with a compact summary (block counts, sizes, key previews) and the raw JSON is saved to a temp file. Direct tools keep their lean details and never carry `mcpResult`.
376
391
 
377
- Tune the limits with the object form:
392
+ Tune the text and details limits with the object form:
378
393
 
379
394
  ```json
380
395
  {
@@ -384,7 +399,7 @@ Tune the limits with the object form:
384
399
  }
385
400
  ```
386
401
 
387
- Set `"outputGuard": false` — or the env kill switch `MCP_OUTPUT_GUARD=0` — to disable the guard and restore raw output behavior. Saved temp files are created with mode `0600` under the system temp directory and are not cleaned up automatically; note that spilled MCP output may contain sensitive data.
402
+ Set `"outputGuard": false` — or the env kill switch `MCP_OUTPUT_GUARD=0` — to disable text and details guarding. Binary resource materialization and its safety limits remain active. Output-guard spill files are created with mode `0600` under the system temp directory and are not cleaned up automatically; note that spilled MCP output may contain sensitive data.
388
403
 
389
404
  ### MCP Scripting
390
405
 
@@ -1,3 +1,4 @@
1
+ import { readFileSync } from "node:fs";
1
2
  import { homedir } from "node:os";
2
3
  import { join, resolve } from "node:path";
3
4
 
@@ -18,3 +19,42 @@ export function getAgentDir(): string {
18
19
  export function getAgentPath(...segments: string[]): string {
19
20
  return join(getAgentDir(), ...segments);
20
21
  }
22
+
23
+ /**
24
+ * What the host calls itself.
25
+ *
26
+ * pi supports rebranding through `piConfig.name` in the package.json that its
27
+ * `getPackageDir()` resolves, and distributions built on pi (arc, tau, …) point
28
+ * `PI_PACKAGE_DIR` at their own manifest. Read that manifest directly rather
29
+ * than importing pi: this package deliberately depends on pi-ai and pi-tui
30
+ * only, and `getAgentDir()` above reads its env var the same self-contained way.
31
+ *
32
+ * Falls back to "pi", which is what pi's own APP_NAME resolves to.
33
+ */
34
+ function readPiConfig(): { name?: unknown; clientUri?: unknown } | undefined {
35
+ const dir = process.env.PI_PACKAGE_DIR?.trim()
36
+ if (!dir) return undefined
37
+ try {
38
+ const manifest = JSON.parse(readFileSync(join(resolve(dir), "package.json"), "utf8")) as {
39
+ piConfig?: { name?: unknown; clientUri?: unknown }
40
+ }
41
+ return manifest.piConfig
42
+ } catch {
43
+ return undefined
44
+ }
45
+ }
46
+
47
+ export function getAppName(): string {
48
+ const name = readPiConfig()?.name
49
+ return typeof name === "string" && name.trim() ? name.trim() : "pi"
50
+ }
51
+
52
+ /**
53
+ * Home page the host declares for itself, via `piConfig.clientUri` in the same
54
+ * manifest that carries `piConfig.name`. Only the distribution knows its own
55
+ * URL, so this is the one place it can come from without guessing.
56
+ */
57
+ export function getAppClientUri(): string | undefined {
58
+ const uri = readPiConfig()?.clientUri
59
+ return typeof uri === "string" && uri.trim() ? uri.trim() : undefined
60
+ }
@@ -25,6 +25,10 @@ import { loadOnboardingState, markSetupCompleted as persistSetupCompleted, markS
25
25
  import { openPath, resolveServerUrl, sanitizeTerminalText } from "./utils.ts";
26
26
  import { isAbortError } from "./runtime-owner.ts";
27
27
 
28
+ function terminalHyperlink(label: string, url: string): string {
29
+ return `\u001B]8;;${sanitizeTerminalText(url)}\u001B\\${sanitizeTerminalText(label)}\u001B]8;;\u001B\\`;
30
+ }
31
+
28
32
  export async function showStatus(state: McpExtensionState, ctx: ExtensionContext): Promise<void> {
29
33
  if (!ctx.hasUI) return;
30
34
 
@@ -273,11 +277,17 @@ export async function authenticateServer(
273
277
  ...(authStorageOptions.baseDir ? { authStorageOptions } : {}),
274
278
  onAuthorizationUrl: (authorizationUrl) => {
275
279
  ui.notify(
276
- `Open this URL to authenticate ${serverName}:\n\n${authorizationUrl}\n\n` +
277
- "After approving, return to Pi; the local callback will complete automatically.",
280
+ `Open this URL to authenticate ${serverName}:\n\n${terminalHyperlink(authorizationUrl, authorizationUrl)}\n\n` +
281
+ "After approving, Pi will complete automatically if the browser can reach its localhost callback. " +
282
+ "On a remote machine, copy the full localhost URL from the browser address bar and paste it into Pi.",
278
283
  "info"
279
284
  );
280
285
  },
286
+ onAuthorizationInput: (_authorizationUrl, inputSignal) => ui.input(
287
+ `Complete ${serverName} OAuth`,
288
+ "Paste the full callback URL, or wait for automatic completion",
289
+ { signal: inputSignal },
290
+ ),
281
291
  ...(signal ? { signal } : {}),
282
292
  ...(runtime ? { runtime } : {}),
283
293
  });