@herbertgao/pi-extensions 2026.8.2 → 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 (272) hide show
  1. package/README.md +9 -2
  2. package/node_modules/@herbertgao/pi-cc-extensions/README.en.md +6 -8
  3. package/node_modules/@herbertgao/pi-cc-extensions/README.md +5 -7
  4. package/node_modules/@herbertgao/pi-cc-extensions/assets/readme/hero.en.svg +101 -0
  5. package/node_modules/@herbertgao/pi-cc-extensions/extensions/config/config.ts +1 -17
  6. package/node_modules/@herbertgao/pi-cc-extensions/extensions/config/panel.ts +5 -3
  7. package/node_modules/@herbertgao/pi-cc-extensions/extensions/{utils/agent-summary.ts → feature/agent-summary/core.ts} +37 -35
  8. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/{agent-summary.ts → agent-summary/index.ts} +2 -6
  9. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/{session-reference.ts → reference/index.ts} +1 -1
  10. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/{agent-autocomplete.ts → reference/subagent.ts} +19 -9
  11. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/{pi-startup-header.ts → shell/startup-header.ts} +1 -1
  12. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/{working-message.ts → shell/working-message.ts} +5 -2
  13. package/node_modules/@herbertgao/pi-cc-extensions/extensions/index.ts +32 -28
  14. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/compact-mode.ts +379 -85
  15. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/default-mode.ts +727 -0
  16. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/index.ts +65 -775
  17. package/node_modules/@herbertgao/pi-cc-extensions/extensions/{feature → renderer}/markdown-enhance.ts +35 -31
  18. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{mouse-hover.ts → mouse/hover.ts} +5 -5
  19. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{mouse-interaction.ts → mouse/interaction.ts} +34 -35
  20. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{mouse-layout.ts → mouse/layout.ts} +5 -21
  21. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{mouse-packets.ts → mouse/packets.ts} +1 -1
  22. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{mouse-scroll.ts → mouse/scroll.ts} +48 -37
  23. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-diff → tool/diff}/ansi-utils.ts +56 -1
  24. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-diff → tool/diff}/diff-renderer.ts +2 -2
  25. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-diff → tool/diff}/line-width-safety.ts +1 -1
  26. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/write-display-utils.ts +12 -0
  27. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-diff → tool/diff}/write-execution.ts +1 -2
  28. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-grouping.ts → tool/grouping.ts} +18 -8
  29. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-result.ts → tool/result.ts} +4 -13
  30. package/node_modules/@herbertgao/pi-cc-extensions/extensions/utils/fullscreen-detect.ts +0 -27
  31. package/node_modules/@herbertgao/pi-cc-extensions/package.json +3 -3
  32. package/node_modules/@herbertgao/pi-subagents/CHANGELOG.md +6 -0
  33. package/node_modules/@herbertgao/pi-subagents/package.json +2 -2
  34. package/node_modules/@herbertgao/pi-subagents/src/agent-manager.ts +1 -0
  35. package/node_modules/@herbertgao/pi-subagents/src/agent-runner.ts +3 -1
  36. package/node_modules/@herbertgao/pi-subagents/src/index.ts +33 -35
  37. package/node_modules/@herbertgao/pi-subagents/src/nested-tools.ts +26 -35
  38. package/node_modules/@herbertgao/pi-subagents/src/prompts.ts +15 -1
  39. package/node_modules/pi-mcp-adapter/CHANGELOG.md +19 -0
  40. package/node_modules/pi-mcp-adapter/README.md +19 -4
  41. package/node_modules/pi-mcp-adapter/agent-dir.ts +40 -0
  42. package/node_modules/pi-mcp-adapter/commands.ts +12 -2
  43. package/node_modules/pi-mcp-adapter/direct-tools.ts +6 -8
  44. package/node_modules/pi-mcp-adapter/index.ts +15 -3
  45. package/node_modules/pi-mcp-adapter/mcp-auth-flow.ts +87 -4
  46. package/node_modules/pi-mcp-adapter/mcp-callback-server.ts +138 -61
  47. package/node_modules/pi-mcp-adapter/mcp-oauth-provider.ts +43 -4
  48. package/node_modules/pi-mcp-adapter/oauth.ts +48 -0
  49. package/node_modules/pi-mcp-adapter/package.json +8 -2
  50. package/node_modules/pi-mcp-adapter/proxy-modes.ts +8 -10
  51. package/node_modules/pi-mcp-adapter/tool-registrar.ts +187 -3
  52. package/node_modules/pi-mcp-adapter/types.ts +2 -0
  53. package/node_modules/pi-web-access/CHANGELOG.md +45 -0
  54. package/node_modules/pi-web-access/README.md +104 -29
  55. package/node_modules/pi-web-access/bocha.ts +221 -0
  56. package/node_modules/pi-web-access/curator-page.ts +113 -12
  57. package/node_modules/pi-web-access/curator-server.ts +56 -20
  58. package/node_modules/pi-web-access/datalab-pdf-extract.ts +568 -0
  59. package/node_modules/pi-web-access/duckduckgo.ts +123 -0
  60. package/node_modules/pi-web-access/extract.ts +288 -143
  61. package/node_modules/pi-web-access/feature-config.ts +29 -0
  62. package/node_modules/pi-web-access/gemini-api.ts +4 -0
  63. package/node_modules/pi-web-access/gemini-search.ts +45 -12
  64. package/node_modules/pi-web-access/gemini-web.ts +68 -3
  65. package/node_modules/pi-web-access/index.ts +160 -71
  66. package/node_modules/pi-web-access/jina-search.ts +284 -0
  67. package/node_modules/pi-web-access/kagi.ts +12 -12
  68. package/node_modules/pi-web-access/openai-search.ts +12 -2
  69. package/node_modules/pi-web-access/package.json +4 -3
  70. package/node_modules/pi-web-access/pdf-extract.ts +327 -228
  71. package/node_modules/pi-web-access/storage.ts +440 -2
  72. package/node_modules/pi-web-access/summary-model-scope.ts +1 -1
  73. package/node_modules/pi-web-access/summary-review.ts +4 -2
  74. package/node_modules/pi-web-access/video-extract.ts +10 -8
  75. package/node_modules/pi-web-access/xai-search.ts +12 -2
  76. package/node_modules/pi-web-access/youtube-extract.ts +2 -1
  77. package/node_modules/remote-pi/LICENSE +21 -0
  78. package/node_modules/remote-pi/README.md +675 -0
  79. package/node_modules/remote-pi/dist/actions/handlers.d.ts +122 -0
  80. package/node_modules/remote-pi/dist/actions/handlers.js +160 -0
  81. package/node_modules/remote-pi/dist/actions/handlers.js.map +1 -0
  82. package/node_modules/remote-pi/dist/actions/registry.d.ts +39 -0
  83. package/node_modules/remote-pi/dist/actions/registry.js +58 -0
  84. package/node_modules/remote-pi/dist/actions/registry.js.map +1 -0
  85. package/node_modules/remote-pi/dist/bin/supervisord.d.ts +2 -0
  86. package/node_modules/remote-pi/dist/bin/supervisord.js +86 -0
  87. package/node_modules/remote-pi/dist/bin/supervisord.js.map +1 -0
  88. package/node_modules/remote-pi/dist/commands/builtin_mirror.d.ts +58 -0
  89. package/node_modules/remote-pi/dist/commands/builtin_mirror.js +71 -0
  90. package/node_modules/remote-pi/dist/commands/builtin_mirror.js.map +1 -0
  91. package/node_modules/remote-pi/dist/commands/list_commands.d.ts +60 -0
  92. package/node_modules/remote-pi/dist/commands/list_commands.js +73 -0
  93. package/node_modules/remote-pi/dist/commands/list_commands.js.map +1 -0
  94. package/node_modules/remote-pi/dist/config.d.ts +62 -0
  95. package/node_modules/remote-pi/dist/config.js +115 -0
  96. package/node_modules/remote-pi/dist/config.js.map +1 -0
  97. package/node_modules/remote-pi/dist/daemon/client.d.ts +20 -0
  98. package/node_modules/remote-pi/dist/daemon/client.js +131 -0
  99. package/node_modules/remote-pi/dist/daemon/client.js.map +1 -0
  100. package/node_modules/remote-pi/dist/daemon/control_protocol.d.ts +176 -0
  101. package/node_modules/remote-pi/dist/daemon/control_protocol.js +63 -0
  102. package/node_modules/remote-pi/dist/daemon/control_protocol.js.map +1 -0
  103. package/node_modules/remote-pi/dist/daemon/cron_log.d.ts +45 -0
  104. package/node_modules/remote-pi/dist/daemon/cron_log.js +72 -0
  105. package/node_modules/remote-pi/dist/daemon/cron_log.js.map +1 -0
  106. package/node_modules/remote-pi/dist/daemon/cron_registry.d.ts +80 -0
  107. package/node_modules/remote-pi/dist/daemon/cron_registry.js +194 -0
  108. package/node_modules/remote-pi/dist/daemon/cron_registry.js.map +1 -0
  109. package/node_modules/remote-pi/dist/daemon/id.d.ts +24 -0
  110. package/node_modules/remote-pi/dist/daemon/id.js +36 -0
  111. package/node_modules/remote-pi/dist/daemon/id.js.map +1 -0
  112. package/node_modules/remote-pi/dist/daemon/install.d.ts +170 -0
  113. package/node_modules/remote-pi/dist/daemon/install.js +547 -0
  114. package/node_modules/remote-pi/dist/daemon/install.js.map +1 -0
  115. package/node_modules/remote-pi/dist/daemon/registry.d.ts +63 -0
  116. package/node_modules/remote-pi/dist/daemon/registry.js +153 -0
  117. package/node_modules/remote-pi/dist/daemon/registry.js.map +1 -0
  118. package/node_modules/remote-pi/dist/daemon/rpc_child.d.ts +194 -0
  119. package/node_modules/remote-pi/dist/daemon/rpc_child.js +389 -0
  120. package/node_modules/remote-pi/dist/daemon/rpc_child.js.map +1 -0
  121. package/node_modules/remote-pi/dist/daemon/supervisor.d.ts +93 -0
  122. package/node_modules/remote-pi/dist/daemon/supervisor.js +596 -0
  123. package/node_modules/remote-pi/dist/daemon/supervisor.js.map +1 -0
  124. package/node_modules/remote-pi/dist/extension_ui_bridge.d.ts +26 -0
  125. package/node_modules/remote-pi/dist/extension_ui_bridge.js +341 -0
  126. package/node_modules/remote-pi/dist/extension_ui_bridge.js.map +1 -0
  127. package/node_modules/remote-pi/dist/index.d.ts +213 -0
  128. package/node_modules/remote-pi/dist/index.js +4996 -0
  129. package/node_modules/remote-pi/dist/index.js.map +1 -0
  130. package/node_modules/remote-pi/dist/mcp/mesh_result.d.ts +10 -0
  131. package/node_modules/remote-pi/dist/mcp/mesh_result.js +42 -0
  132. package/node_modules/remote-pi/dist/mcp/mesh_result.js.map +1 -0
  133. package/node_modules/remote-pi/dist/mcp/mesh_server.d.ts +16 -0
  134. package/node_modules/remote-pi/dist/mcp/mesh_server.js +327 -0
  135. package/node_modules/remote-pi/dist/mcp/mesh_server.js.map +1 -0
  136. package/node_modules/remote-pi/dist/mesh/canonical.d.ts +30 -0
  137. package/node_modules/remote-pi/dist/mesh/canonical.js +61 -0
  138. package/node_modules/remote-pi/dist/mesh/canonical.js.map +1 -0
  139. package/node_modules/remote-pi/dist/mesh/client.d.ts +18 -0
  140. package/node_modules/remote-pi/dist/mesh/client.js +125 -0
  141. package/node_modules/remote-pi/dist/mesh/client.js.map +1 -0
  142. package/node_modules/remote-pi/dist/mesh/encoding.d.ts +38 -0
  143. package/node_modules/remote-pi/dist/mesh/encoding.js +216 -0
  144. package/node_modules/remote-pi/dist/mesh/encoding.js.map +1 -0
  145. package/node_modules/remote-pi/dist/mesh/self_revoke.d.ts +73 -0
  146. package/node_modules/remote-pi/dist/mesh/self_revoke.js +401 -0
  147. package/node_modules/remote-pi/dist/mesh/self_revoke.js.map +1 -0
  148. package/node_modules/remote-pi/dist/mesh/siblings.d.ts +49 -0
  149. package/node_modules/remote-pi/dist/mesh/siblings.js +159 -0
  150. package/node_modules/remote-pi/dist/mesh/siblings.js.map +1 -0
  151. package/node_modules/remote-pi/dist/mesh/types.d.ts +34 -0
  152. package/node_modules/remote-pi/dist/mesh/types.js +11 -0
  153. package/node_modules/remote-pi/dist/mesh/types.js.map +1 -0
  154. package/node_modules/remote-pi/dist/mesh/verify.d.ts +17 -0
  155. package/node_modules/remote-pi/dist/mesh/verify.js +86 -0
  156. package/node_modules/remote-pi/dist/mesh/verify.js.map +1 -0
  157. package/node_modules/remote-pi/dist/pairing/crypto.d.ts +8 -0
  158. package/node_modules/remote-pi/dist/pairing/crypto.js +22 -0
  159. package/node_modules/remote-pi/dist/pairing/crypto.js.map +1 -0
  160. package/node_modules/remote-pi/dist/pairing/handshake.d.ts +28 -0
  161. package/node_modules/remote-pi/dist/pairing/handshake.js +113 -0
  162. package/node_modules/remote-pi/dist/pairing/handshake.js.map +1 -0
  163. package/node_modules/remote-pi/dist/pairing/noise-sha256.d.ts +16 -0
  164. package/node_modules/remote-pi/dist/pairing/noise-sha256.js +103 -0
  165. package/node_modules/remote-pi/dist/pairing/noise-sha256.js.map +1 -0
  166. package/node_modules/remote-pi/dist/pairing/qr.d.ts +59 -0
  167. package/node_modules/remote-pi/dist/pairing/qr.js +125 -0
  168. package/node_modules/remote-pi/dist/pairing/qr.js.map +1 -0
  169. package/node_modules/remote-pi/dist/pairing/storage.d.ts +120 -0
  170. package/node_modules/remote-pi/dist/pairing/storage.js +604 -0
  171. package/node_modules/remote-pi/dist/pairing/storage.js.map +1 -0
  172. package/node_modules/remote-pi/dist/protocol/codec.d.ts +7 -0
  173. package/node_modules/remote-pi/dist/protocol/codec.js +49 -0
  174. package/node_modules/remote-pi/dist/protocol/codec.js.map +1 -0
  175. package/node_modules/remote-pi/dist/protocol/types.d.ts +393 -0
  176. package/node_modules/remote-pi/dist/protocol/types.js +2 -0
  177. package/node_modules/remote-pi/dist/protocol/types.js.map +1 -0
  178. package/node_modules/remote-pi/dist/rooms.d.ts +29 -0
  179. package/node_modules/remote-pi/dist/rooms.js +57 -0
  180. package/node_modules/remote-pi/dist/rooms.js.map +1 -0
  181. package/node_modules/remote-pi/dist/session/address.d.ts +49 -0
  182. package/node_modules/remote-pi/dist/session/address.js +58 -0
  183. package/node_modules/remote-pi/dist/session/address.js.map +1 -0
  184. package/node_modules/remote-pi/dist/session/agent_bridge.d.ts +55 -0
  185. package/node_modules/remote-pi/dist/session/agent_bridge.js +146 -0
  186. package/node_modules/remote-pi/dist/session/agent_bridge.js.map +1 -0
  187. package/node_modules/remote-pi/dist/session/bridge.d.ts +37 -0
  188. package/node_modules/remote-pi/dist/session/bridge.js +130 -0
  189. package/node_modules/remote-pi/dist/session/bridge.js.map +1 -0
  190. package/node_modules/remote-pi/dist/session/broker.d.ts +189 -0
  191. package/node_modules/remote-pi/dist/session/broker.js +507 -0
  192. package/node_modules/remote-pi/dist/session/broker.js.map +1 -0
  193. package/node_modules/remote-pi/dist/session/broker_remote.d.ts +74 -0
  194. package/node_modules/remote-pi/dist/session/broker_remote.js +583 -0
  195. package/node_modules/remote-pi/dist/session/broker_remote.js.map +1 -0
  196. package/node_modules/remote-pi/dist/session/cwd_lock.d.ts +33 -0
  197. package/node_modules/remote-pi/dist/session/cwd_lock.js +126 -0
  198. package/node_modules/remote-pi/dist/session/cwd_lock.js.map +1 -0
  199. package/node_modules/remote-pi/dist/session/envelope.d.ts +33 -0
  200. package/node_modules/remote-pi/dist/session/envelope.js +117 -0
  201. package/node_modules/remote-pi/dist/session/envelope.js.map +1 -0
  202. package/node_modules/remote-pi/dist/session/global_config.d.ts +33 -0
  203. package/node_modules/remote-pi/dist/session/global_config.js +73 -0
  204. package/node_modules/remote-pi/dist/session/global_config.js.map +1 -0
  205. package/node_modules/remote-pi/dist/session/ipc.d.ts +27 -0
  206. package/node_modules/remote-pi/dist/session/ipc.js +22 -0
  207. package/node_modules/remote-pi/dist/session/ipc.js.map +1 -0
  208. package/node_modules/remote-pi/dist/session/leader_election.d.ts +32 -0
  209. package/node_modules/remote-pi/dist/session/leader_election.js +106 -0
  210. package/node_modules/remote-pi/dist/session/leader_election.js.map +1 -0
  211. package/node_modules/remote-pi/dist/session/local_config.d.ts +55 -0
  212. package/node_modules/remote-pi/dist/session/local_config.js +157 -0
  213. package/node_modules/remote-pi/dist/session/local_config.js.map +1 -0
  214. package/node_modules/remote-pi/dist/session/mesh_message.d.ts +20 -0
  215. package/node_modules/remote-pi/dist/session/mesh_message.js +28 -0
  216. package/node_modules/remote-pi/dist/session/mesh_message.js.map +1 -0
  217. package/node_modules/remote-pi/dist/session/mesh_node.d.ts +116 -0
  218. package/node_modules/remote-pi/dist/session/mesh_node.js +573 -0
  219. package/node_modules/remote-pi/dist/session/mesh_node.js.map +1 -0
  220. package/node_modules/remote-pi/dist/session/peer.d.ts +139 -0
  221. package/node_modules/remote-pi/dist/session/peer.js +451 -0
  222. package/node_modules/remote-pi/dist/session/peer.js.map +1 -0
  223. package/node_modules/remote-pi/dist/session/peer_inventory.d.ts +13 -0
  224. package/node_modules/remote-pi/dist/session/peer_inventory.js +48 -0
  225. package/node_modules/remote-pi/dist/session/peer_inventory.js.map +1 -0
  226. package/node_modules/remote-pi/dist/session/peer_limits.d.ts +9 -0
  227. package/node_modules/remote-pi/dist/session/peer_limits.js +21 -0
  228. package/node_modules/remote-pi/dist/session/peer_limits.js.map +1 -0
  229. package/node_modules/remote-pi/dist/session/setup_wizard.d.ts +39 -0
  230. package/node_modules/remote-pi/dist/session/setup_wizard.js +63 -0
  231. package/node_modules/remote-pi/dist/session/setup_wizard.js.map +1 -0
  232. package/node_modules/remote-pi/dist/session/tool_gate.d.ts +5 -0
  233. package/node_modules/remote-pi/dist/session/tool_gate.js +11 -0
  234. package/node_modules/remote-pi/dist/session/tool_gate.js.map +1 -0
  235. package/node_modules/remote-pi/dist/session/tools.d.ts +24 -0
  236. package/node_modules/remote-pi/dist/session/tools.js +252 -0
  237. package/node_modules/remote-pi/dist/session/tools.js.map +1 -0
  238. package/node_modules/remote-pi/dist/session/wizard.d.ts +13 -0
  239. package/node_modules/remote-pi/dist/session/wizard.js +20 -0
  240. package/node_modules/remote-pi/dist/session/wizard.js.map +1 -0
  241. package/node_modules/remote-pi/dist/settings.d.ts +15 -0
  242. package/node_modules/remote-pi/dist/settings.js +52 -0
  243. package/node_modules/remote-pi/dist/settings.js.map +1 -0
  244. package/node_modules/remote-pi/dist/transport/peer_channel.d.ts +37 -0
  245. package/node_modules/remote-pi/dist/transport/peer_channel.js +98 -0
  246. package/node_modules/remote-pi/dist/transport/peer_channel.js.map +1 -0
  247. package/node_modules/remote-pi/dist/transport/pi_forward_client.d.ts +29 -0
  248. package/node_modules/remote-pi/dist/transport/pi_forward_client.js +62 -0
  249. package/node_modules/remote-pi/dist/transport/pi_forward_client.js.map +1 -0
  250. package/node_modules/remote-pi/dist/transport/relay_client.d.ts +91 -0
  251. package/node_modules/remote-pi/dist/transport/relay_client.js +206 -0
  252. package/node_modules/remote-pi/dist/transport/relay_client.js.map +1 -0
  253. package/node_modules/remote-pi/dist/ui/footer.d.ts +32 -0
  254. package/node_modules/remote-pi/dist/ui/footer.js +34 -0
  255. package/node_modules/remote-pi/dist/ui/footer.js.map +1 -0
  256. package/node_modules/remote-pi/docs/daemon.md +289 -0
  257. package/node_modules/remote-pi/package.json +88 -0
  258. package/node_modules/remote-pi/service-templates/launchd.plist.template +35 -0
  259. package/node_modules/remote-pi/service-templates/systemd.service.template +19 -0
  260. package/node_modules/remote-pi/service-templates/task-launcher.vbs.template +10 -0
  261. package/node_modules/remote-pi/service-templates/task-scheduler.xml.template +38 -0
  262. package/node_modules/remote-pi/skills/agent-network/SKILL.md +310 -0
  263. package/package.json +19 -9
  264. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool-diff/write-display-utils.ts +0 -29
  265. /package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/{session-reference-core.ts → reference/session.ts} +0 -0
  266. /package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/{pi-aliases.ts → shell/aliases.ts} +0 -0
  267. /package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-diff → tool/diff}/ATTRIBUTION.md +0 -0
  268. /package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-diff → tool/diff}/diff-presentation.ts +0 -0
  269. /package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-diff → tool/diff}/index.ts +0 -0
  270. /package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-diff → tool/diff}/render-utils.ts +0 -0
  271. /package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-diff → tool/diff}/shiki-highlight.ts +0 -0
  272. /package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-diff → tool/diff}/types.ts +0 -0
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Mesh-membership types — pi-extension side. Mirrors the wire shape defined
3
+ * in plan/24-mesh-membership.md and must stay bit-compatible with the Dart
4
+ * (app) and Rust (relay) implementations of the same protocol.
5
+ *
6
+ * On the wire, JSON field names are `snake_case` (per the plan); this module
7
+ * exposes `camelCase` for ergonomic TS use. Conversion happens at the
8
+ * (de)serialization boundary in `verify.ts` / `canonical.ts`.
9
+ */
10
+ export interface MeshMember {
11
+ /** Pi Ed25519 pubkey, canonical RFC 4648 standard base64 with padding. */
12
+ remoteEpk: string;
13
+ /** Relay URL where this member registers. */
14
+ relayUrl: string;
15
+ /** ISO-8601 timestamp of when the pairing happened. */
16
+ pairedAt: string;
17
+ /** Optional Owner-set label. */
18
+ nickname?: string;
19
+ }
20
+ export interface MeshHeader {
21
+ /** Owner-scoped monotonic counter. Higher = newer. */
22
+ version: number;
23
+ /** Issued-at, ms since epoch. */
24
+ issuedAt: number;
25
+ /** Owner's Ed25519 pubkey, raw 32 bytes. */
26
+ ownerPk: Uint8Array;
27
+ members: MeshMember[];
28
+ }
29
+ export interface MeshEnvelope {
30
+ /** Canonical JSON bytes of the header (snake_case keys, sorted, no whitespace). */
31
+ blob: Uint8Array;
32
+ /** Ed25519 signature of `blob`, 64 bytes. */
33
+ sig: Uint8Array;
34
+ }
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Mesh-membership types — pi-extension side. Mirrors the wire shape defined
3
+ * in plan/24-mesh-membership.md and must stay bit-compatible with the Dart
4
+ * (app) and Rust (relay) implementations of the same protocol.
5
+ *
6
+ * On the wire, JSON field names are `snake_case` (per the plan); this module
7
+ * exposes `camelCase` for ergonomic TS use. Conversion happens at the
8
+ * (de)serialization boundary in `verify.ts` / `canonical.ts`.
9
+ */
10
+ export {};
11
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/mesh/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG"}
@@ -0,0 +1,17 @@
1
+ import type { MeshEnvelope, MeshHeader } from "./types.js";
2
+ /**
3
+ * Verifies the Ed25519 signature on a mesh envelope and decodes the blob
4
+ * into a typed `MeshHeader`.
5
+ *
6
+ * The verification key is extracted *from the blob* (`owner_pk` field) —
7
+ * the caller MUST then check that `sha256(header.ownerPk)` matches the
8
+ * URL hash they queried with. Otherwise a malicious relay could serve a
9
+ * valid-but-different-owner blob at our hash slot.
10
+ *
11
+ * Throws on:
12
+ * - JSON parse failure
13
+ * - Missing or wrong-type required fields
14
+ * - `owner_pk` not 32 bytes
15
+ * - Signature mismatch
16
+ */
17
+ export declare function verifyEnvelope(env: MeshEnvelope): Promise<MeshHeader>;
@@ -0,0 +1,86 @@
1
+ import { ed25519Verify } from "../pairing/crypto.js";
2
+ import { canonicalizeEd25519PublicKey, decodeEd25519PublicKey, } from "./encoding.js";
3
+ /**
4
+ * Verifies the Ed25519 signature on a mesh envelope and decodes the blob
5
+ * into a typed `MeshHeader`.
6
+ *
7
+ * The verification key is extracted *from the blob* (`owner_pk` field) —
8
+ * the caller MUST then check that `sha256(header.ownerPk)` matches the
9
+ * URL hash they queried with. Otherwise a malicious relay could serve a
10
+ * valid-but-different-owner blob at our hash slot.
11
+ *
12
+ * Throws on:
13
+ * - JSON parse failure
14
+ * - Missing or wrong-type required fields
15
+ * - `owner_pk` not 32 bytes
16
+ * - Signature mismatch
17
+ */
18
+ export async function verifyEnvelope(env) {
19
+ let parsed;
20
+ try {
21
+ parsed = JSON.parse(new TextDecoder().decode(env.blob));
22
+ }
23
+ catch {
24
+ throw new Error("mesh: blob is not valid JSON");
25
+ }
26
+ if (!parsed || typeof parsed !== "object") {
27
+ throw new Error("mesh: blob is not a JSON object");
28
+ }
29
+ const o = parsed;
30
+ if (typeof o["owner_pk"] !== "string") {
31
+ throw new Error("mesh: owner_pk missing or not a string");
32
+ }
33
+ if (typeof o["version"] !== "number" || !Number.isInteger(o["version"])) {
34
+ throw new Error("mesh: version missing or not an integer");
35
+ }
36
+ if (typeof o["issued_at"] !== "number" || !Number.isInteger(o["issued_at"])) {
37
+ throw new Error("mesh: issued_at missing or not an integer");
38
+ }
39
+ if (!Array.isArray(o["members"])) {
40
+ throw new Error("mesh: members missing or not an array");
41
+ }
42
+ const rawMembers = o["members"].map((raw, index) => {
43
+ if (!raw || typeof raw !== "object") {
44
+ throw new Error(`mesh: members[${index}] is not an object`);
45
+ }
46
+ const member = raw;
47
+ if (typeof member["remote_epk"] !== "string") {
48
+ throw new Error(`mesh: members[${index}].remote_epk invalid`);
49
+ }
50
+ if (typeof member["relay_url"] !== "string") {
51
+ throw new Error(`mesh: members[${index}].relay_url invalid`);
52
+ }
53
+ if (typeof member["paired_at"] !== "string") {
54
+ throw new Error(`mesh: members[${index}].paired_at invalid`);
55
+ }
56
+ const nickname = member["nickname"];
57
+ if (nickname !== undefined &&
58
+ nickname !== null &&
59
+ typeof nickname !== "string") {
60
+ throw new Error(`mesh: members[${index}].nickname invalid`);
61
+ }
62
+ return {
63
+ remoteEpk: member["remote_epk"],
64
+ relayUrl: member["relay_url"],
65
+ pairedAt: member["paired_at"],
66
+ ...(typeof nickname === "string" ? { nickname } : {}),
67
+ };
68
+ });
69
+ const ownerPk = decodeEd25519PublicKey(o["owner_pk"], "owner_pk");
70
+ if (!ed25519Verify(ownerPk, env.blob, env.sig)) {
71
+ throw new Error("mesh: signature verification failed");
72
+ }
73
+ const members = rawMembers.map((member, index) => ({
74
+ remoteEpk: canonicalizeEd25519PublicKey(member.remoteEpk, `members[${index}].remote_epk`),
75
+ relayUrl: member.relayUrl,
76
+ pairedAt: member.pairedAt,
77
+ ...(member.nickname !== undefined ? { nickname: member.nickname } : {}),
78
+ }));
79
+ return {
80
+ version: o["version"],
81
+ issuedAt: o["issued_at"],
82
+ ownerPk,
83
+ members,
84
+ };
85
+ }
86
+ //# sourceMappingURL=verify.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verify.js","sourceRoot":"","sources":["../../src/mesh/verify.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ export interface Ed25519Keypair {
2
+ publicKey: Uint8Array;
3
+ secretKey: Uint8Array;
4
+ }
5
+ /** Generates an Ed25519 keypair for relay challenge-response auth. */
6
+ export declare function generateEd25519Keypair(): Ed25519Keypair;
7
+ export declare function ed25519Sign(sk: Uint8Array, msg: Uint8Array): Uint8Array;
8
+ export declare function ed25519Verify(pk: Uint8Array, msg: Uint8Array, sig: Uint8Array): boolean;
@@ -0,0 +1,22 @@
1
+ import { createHash, randomBytes } from "node:crypto";
2
+ import * as ed from "@noble/ed25519";
3
+ // Configure @noble/ed25519 v3 to use Node.js built-in SHA-512
4
+ ed.hashes["sha512"] = (...msgs) => {
5
+ const h = createHash("sha512");
6
+ for (const m of msgs)
7
+ h.update(m);
8
+ return Uint8Array.from(h.digest());
9
+ };
10
+ /** Generates an Ed25519 keypair for relay challenge-response auth. */
11
+ export function generateEd25519Keypair() {
12
+ const secretKey = randomBytes(32);
13
+ const publicKey = ed.getPublicKey(secretKey);
14
+ return { secretKey, publicKey: Buffer.from(publicKey) };
15
+ }
16
+ export function ed25519Sign(sk, msg) {
17
+ return Buffer.from(ed.sign(msg, sk));
18
+ }
19
+ export function ed25519Verify(pk, msg, sig) {
20
+ return ed.verify(sig, msg, pk);
21
+ }
22
+ //# sourceMappingURL=crypto.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"crypto.js","sourceRoot":"","sources":["../../src/pairing/crypto.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AACtD,OAAO,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAErC,8DAA8D;AAC7D,EAAE,CAAC,MAAkC,CAAC,QAAQ,CAAC,GAAG,CACjD,GAAG,IAAkB,EACrB,EAAE;IACF,MAAM,CAAC,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC;IAC/B,KAAK,MAAM,CAAC,IAAI,IAAI;QAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;IAClC,OAAO,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC;AACrC,CAAC,CAAC;AAOF,sEAAsE;AACtE,MAAM,UAAU,sBAAsB;IACpC,MAAM,SAAS,GAAG,WAAW,CAAC,EAAE,CAAC,CAAC;IAClC,MAAM,SAAS,GAAG,EAAE,CAAC,YAAY,CAAC,SAAS,CAAC,CAAC;IAC7C,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;AAC1D,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,EAAc,EAAE,GAAe;IACzD,OAAO,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC;AACvC,CAAC;AAED,MAAM,UAAU,aAAa,CAC3B,EAAc,EACd,GAAe,EACf,GAAe;IAEf,OAAO,EAAE,CAAC,MAAM,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC;AACjC,CAAC"}
@@ -0,0 +1,28 @@
1
+ import { type X25519Keypair } from "./crypto.js";
2
+ export interface SessionKeys {
3
+ /** Cipher state for sending (ChaCha20-Poly1305). First 32 bytes = key. */
4
+ tx: Uint8Array;
5
+ /** Cipher state for receiving (ChaCha20-Poly1305). First 32 bytes = key. */
6
+ rx: Uint8Array;
7
+ /** 6-emoji safety number derived from the handshake hash. */
8
+ safetyNumber: string;
9
+ /** Raw 32-byte SHA-256 handshake hash, usable for further derivation. */
10
+ handshakeHash: Buffer;
11
+ /**
12
+ * Curve25519 static public key received from the initiator (app).
13
+ * Extracted from state.rs before destroy() — use for peer identity validation.
14
+ */
15
+ remoteStaticKey?: Uint8Array;
16
+ }
17
+ /**
18
+ * Runs Noise_XX_25519_ChaChaPoly_SHA256 as **responder** (the Mac side).
19
+ * Pattern: receive msg1 (→e), send msg2 (←e,ee,s,es), receive msg3 (→s,se)
20
+ * @param prologue Optional prologue bytes mixed into handshake hash (default: empty).
21
+ */
22
+ export declare function runHandshakeResponder(localStatic: X25519Keypair, sendFn: (msg: Buffer) => Promise<void>, recvFn: () => Promise<Buffer>, prologue?: Uint8Array): Promise<SessionKeys>;
23
+ /**
24
+ * Runs Noise_XX_25519_ChaChaPoly_SHA256 as **initiator** (the mobile side).
25
+ * Exported for use in tests — production initiator is the app (Dart).
26
+ * @param prologue Optional prologue bytes mixed into handshake hash (default: empty).
27
+ */
28
+ export declare function runHandshakeInitiator(localStatic: X25519Keypair, sendFn: (msg: Buffer) => Promise<void>, recvFn: () => Promise<Buffer>, prologue?: Uint8Array): Promise<SessionKeys>;
@@ -0,0 +1,113 @@
1
+ import { deriveSafetyNumber } from "./crypto.js";
2
+ import { HASH_LEN_SHA256, HASH_OFFSET_SHA256, NoiseXX_SHA256, } from "./noise-sha256.js";
3
+ // Noise_XX_25519_ChaChaPoly_SHA256 — SHA-256 HASHLEN=32
4
+ // symmetricState layout: [ck(32), h(32), cipher_state(40)] = 104 bytes
5
+ // h (handshake hash) lives at bytes [32..64].
6
+ const HASH_OFFSET = HASH_OFFSET_SHA256; // 32
7
+ const HASH_LEN = HASH_LEN_SHA256; // 32
8
+ const MSG_BUF_SIZE = 4096;
9
+ function _logStep(label, ss) {
10
+ const h = Buffer.from(ss.subarray(32, 64)).toString("hex");
11
+ const ck = Buffer.from(ss.subarray(0, 32)).toString("hex");
12
+ const k = Buffer.from(ss.subarray(64, 96)).toString("hex");
13
+ const n = Buffer.from(ss.subarray(96, 104)).readBigUInt64LE(0).toString();
14
+ console.error(`== RT STEP ${label} ==`);
15
+ console.error(`h: ${h}`);
16
+ console.error(`ck: ${ck}`);
17
+ console.error(`k: ${k}`);
18
+ console.error(`n: ${n}`);
19
+ }
20
+ /**
21
+ * Runs Noise_XX_25519_ChaChaPoly_SHA256 as **responder** (the Mac side).
22
+ * Pattern: receive msg1 (→e), send msg2 (←e,ee,s,es), receive msg3 (→s,se)
23
+ * @param prologue Optional prologue bytes mixed into handshake hash (default: empty).
24
+ */
25
+ export async function runHandshakeResponder(localStatic, sendFn, recvFn, prologue = Buffer.alloc(0)) {
26
+ const state = NoiseXX_SHA256.initialize("XX", false, prologue, localStatic);
27
+ // Payload buffers: allocate generously so non-empty payloads from the app
28
+ // don't cause RangeError. We don't use handshake payloads in the protocol,
29
+ // but the Dart side might include app-level data. 1 KiB is ample.
30
+ const PAYLOAD_BUF = 1024;
31
+ // msg1: -> e (receive from initiator)
32
+ const msg1 = await recvFn();
33
+ console.error(`[remote-pi] msg1 received: ${msg1.length} bytes (expected: 32)`);
34
+ NoiseXX_SHA256.readMessage(state, msg1, Buffer.alloc(PAYLOAD_BUF));
35
+ _logStep("after readMessage1", state.symmetricState);
36
+ // msg2: <- e, ee, s, es (send to initiator)
37
+ const msg2buf = Buffer.alloc(MSG_BUF_SIZE);
38
+ NoiseXX_SHA256.writeMessage(state, Buffer.alloc(0), msg2buf);
39
+ const msg2bytes = NoiseXX_SHA256.writeMessage.bytes;
40
+ await sendFn(msg2buf.subarray(0, msg2bytes));
41
+ console.error(`[remote-pi] msg2 sent: ${msg2bytes} bytes (expected: 96)`);
42
+ _logStep("after writeMessage2", state.symmetricState);
43
+ // msg3: -> s, se (receive → handshake complete)
44
+ const msg3 = await recvFn();
45
+ console.error(`[remote-pi] msg3 received: ${msg3.length} bytes (expected: 64)`);
46
+ // Noise XX msg3 must be ≥ 64 bytes: 48 (encrypted static key) + 16 (MAC of
47
+ // empty payload). An AssertionError otherwise. Clear diagnostic if too short.
48
+ if (msg3.length < 64) {
49
+ const hexDump = msg3.toString("hex");
50
+ // Decode what 45/48 bytes might indicate:
51
+ // 48 bytes → static key encrypted (32 + 16 MAC) but NO payload MAC
52
+ // <48 bytes → static key may be unencrypted (32 B) + partial tag, or wrong format
53
+ const hint = msg3.length === 48
54
+ ? "static key encrypted OK but payload MAC (16 B) missing — call EncryptAndHash([]) after SE"
55
+ : msg3.length >= 32
56
+ ? `${msg3.length - 32} extra bytes after 32 B key — key may be unencrypted (no AEAD) or wrong cipher`
57
+ : "message shorter than a 32-byte key — framing or encoding error";
58
+ NoiseXX_SHA256.destroy(state);
59
+ throw new Error(`handshake_failed: msg3 too short (${msg3.length} B, need ≥64 B)\n` +
60
+ ` hint: ${hint}\n` +
61
+ ` hex: ${hexDump}\n` +
62
+ ` expected structure: [encrypt(s_pk)=48 B][encrypt([])=16 B]\n` +
63
+ ` ensure Dart calls EncryptAndHash with empty payload after SE token`);
64
+ }
65
+ const result = NoiseXX_SHA256.readMessage(state, msg3, Buffer.alloc(PAYLOAD_BUF));
66
+ _logStep("after readMessage3", state.symmetricState);
67
+ const handshakeHash = Buffer.from(state.symmetricState.subarray(HASH_OFFSET, HASH_OFFSET + HASH_LEN));
68
+ // Capture initiator's static public key BEFORE destroy().
69
+ // state.rs is set during readMessage of msg3 (TOK_S token).
70
+ const remoteStaticKey = state.rs
71
+ ? new Uint8Array(state.rs.subarray(0, 32))
72
+ : undefined;
73
+ NoiseXX_SHA256.destroy(state);
74
+ if (!result)
75
+ throw new Error("handshake_failed: split did not occur");
76
+ return {
77
+ tx: result.tx,
78
+ rx: result.rx,
79
+ safetyNumber: deriveSafetyNumber(handshakeHash),
80
+ handshakeHash,
81
+ remoteStaticKey,
82
+ };
83
+ }
84
+ /**
85
+ * Runs Noise_XX_25519_ChaChaPoly_SHA256 as **initiator** (the mobile side).
86
+ * Exported for use in tests — production initiator is the app (Dart).
87
+ * @param prologue Optional prologue bytes mixed into handshake hash (default: empty).
88
+ */
89
+ export async function runHandshakeInitiator(localStatic, sendFn, recvFn, prologue = Buffer.alloc(0)) {
90
+ const state = NoiseXX_SHA256.initialize("XX", true, prologue, localStatic);
91
+ // msg1: -> e
92
+ const msg1buf = Buffer.alloc(MSG_BUF_SIZE);
93
+ NoiseXX_SHA256.writeMessage(state, Buffer.alloc(0), msg1buf);
94
+ await sendFn(msg1buf.subarray(0, NoiseXX_SHA256.writeMessage.bytes));
95
+ // msg2: <- e, ee, s, es
96
+ const msg2 = await recvFn();
97
+ NoiseXX_SHA256.readMessage(state, msg2, Buffer.alloc(0));
98
+ // msg3: -> s, se (handshake complete)
99
+ const msg3buf = Buffer.alloc(MSG_BUF_SIZE);
100
+ const result = NoiseXX_SHA256.writeMessage(state, Buffer.alloc(0), msg3buf);
101
+ await sendFn(msg3buf.subarray(0, NoiseXX_SHA256.writeMessage.bytes));
102
+ const handshakeHash = Buffer.from(state.symmetricState.subarray(HASH_OFFSET, HASH_OFFSET + HASH_LEN));
103
+ NoiseXX_SHA256.destroy(state);
104
+ if (!result)
105
+ throw new Error("handshake_failed: split did not occur");
106
+ return {
107
+ tx: result.tx,
108
+ rx: result.rx,
109
+ safetyNumber: deriveSafetyNumber(handshakeHash),
110
+ handshakeHash,
111
+ };
112
+ }
113
+ //# sourceMappingURL=handshake.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handshake.js","sourceRoot":"","sources":["../../src/pairing/handshake.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import Noise from "noise-protocol";
2
+ import type { X25519Keypair } from "./crypto.js";
3
+ export declare const HASH_OFFSET_SHA256 = 32;
4
+ export declare const HASH_LEN_SHA256 = 32;
5
+ /**
6
+ * Test-only: makes the NEXT internal ephemeral `generateKeypair` call use
7
+ * the provided fixed keys instead of random ones. Consumes after one use.
8
+ * Required to reproduce official Noise test vectors.
9
+ */
10
+ export declare function setNextEphemeralForTest(pk: Uint8Array, sk: Uint8Array): void;
11
+ export declare const NoiseXX_SHA256: typeof Noise;
12
+ /**
13
+ * Builds a noise-protocol keypair from a raw 32-byte X25519 private scalar.
14
+ * Computes the public key via X25519 base-point multiplication.
15
+ */
16
+ export declare function keypairFromRawSk(rawSk: Uint8Array): X25519Keypair;
@@ -0,0 +1,103 @@
1
+ /**
2
+ * Assembles Noise_XX_25519_ChaChaPoly_SHA256 using noise-protocol's
3
+ * createHandshake factory with a plugged-in SHA-256 hash module.
4
+ *
5
+ * The default noise-protocol uses BLAKE2b — incompatible with the Dart side
6
+ * which needs a zero-dependency SHA-256 path.
7
+ */
8
+ import { createHash, createHmac } from "node:crypto";
9
+ import { createRequire } from "node:module";
10
+ import Noise from "noise-protocol";
11
+ // Resolve sodium-universal through noise-protocol's dependency tree.
12
+ // sodium-universal is not hoisted into pi-extension's own node_modules.
13
+ const _reqNoise = createRequire(import.meta.resolve("noise-protocol"));
14
+ // Internal noise-protocol factories (CJS modules, no TS types)
15
+ const _createDH = _reqNoise("noise-protocol/dh");
16
+ const _createCipher = _reqNoise("noise-protocol/cipher");
17
+ const _createCipherState = _reqNoise("noise-protocol/cipher-state");
18
+ const _createSymmetricState = _reqNoise("noise-protocol/symmetric-state");
19
+ const _sm = _reqNoise("sodium-universal/crypto_scalarmult");
20
+ // ── SHA-256 hash module ──────────────────────────────────────────────────────
21
+ // With SHA-256: symmetricState layout = [ck(32), h(32), cipher_state(40)]
22
+ // The handshake hash h is at bytes [32..64] in state.symmetricState.
23
+ export const HASH_OFFSET_SHA256 = 32;
24
+ export const HASH_LEN_SHA256 = 32;
25
+ const _tempHK = Buffer.alloc(32);
26
+ const _B = [Buffer.from([0x01]), Buffer.from([0x02]), Buffer.from([0x03])];
27
+ function _hash(out, data) {
28
+ const h = createHash("sha256");
29
+ for (const d of data)
30
+ h.update(d);
31
+ out.set(h.digest());
32
+ }
33
+ function _hmac(out, key, parts) {
34
+ const h = createHmac("sha256", key);
35
+ for (const p of parts)
36
+ h.update(p);
37
+ out.set(h.digest());
38
+ }
39
+ function _hkdf(out1, out2, out3, ck, ikm) {
40
+ _hmac(_tempHK, ck, [ikm]);
41
+ _hmac(out1, _tempHK, [_B[0]]);
42
+ _hmac(out2, _tempHK, [out1, _B[1]]);
43
+ if (out3 != null)
44
+ _hmac(out3, _tempHK, [out2, _B[2]]);
45
+ _tempHK.fill(0);
46
+ }
47
+ const _sha256Hash = {
48
+ HASHLEN: 32,
49
+ BLOCKLEN: 64,
50
+ ALG: "SHA256",
51
+ hash: _hash,
52
+ hkdf: _hkdf,
53
+ };
54
+ // ── DH wrapper with test key-injection hook ───────────────────────────────────
55
+ let _nextEph = null;
56
+ /**
57
+ * Test-only: makes the NEXT internal ephemeral `generateKeypair` call use
58
+ * the provided fixed keys instead of random ones. Consumes after one use.
59
+ * Required to reproduce official Noise test vectors.
60
+ */
61
+ export function setNextEphemeralForTest(pk, sk) {
62
+ _nextEph = { pk: Buffer.from(pk), sk: Buffer.from(sk) };
63
+ }
64
+ const _baseDH = _createDH();
65
+ const _patchedDH = {
66
+ ..._baseDH,
67
+ generateKeypair(pk, sk) {
68
+ if (_nextEph) {
69
+ pk.set(_nextEph.pk);
70
+ sk.set(_nextEph.sk);
71
+ _nextEph = null;
72
+ }
73
+ else {
74
+ _baseDH.generateKeypair(pk, sk);
75
+ }
76
+ },
77
+ };
78
+ // ── Assembles the full Noise_XX_25519_ChaChaPoly_SHA256 instance ─────────────
79
+ const _cipher = _createCipher();
80
+ const _cipherState = _createCipherState({ cipher: _cipher });
81
+ const _symmetricState = _createSymmetricState({
82
+ hash: _sha256Hash,
83
+ cipherState: _cipherState,
84
+ });
85
+ export const NoiseXX_SHA256 = Noise.createHandshake({
86
+ dh: _patchedDH,
87
+ hash: _sha256Hash,
88
+ cipher: _cipher,
89
+ cipherState: _cipherState,
90
+ symmetricState: _symmetricState,
91
+ });
92
+ // ── Key-building utility ─────────────────────────────────────────────────────
93
+ /**
94
+ * Builds a noise-protocol keypair from a raw 32-byte X25519 private scalar.
95
+ * Computes the public key via X25519 base-point multiplication.
96
+ */
97
+ export function keypairFromRawSk(rawSk) {
98
+ const kp = NoiseXX_SHA256.keygen(); // sodium-allocated buffers of correct size
99
+ kp.secretKey.set(Buffer.from(rawSk));
100
+ _sm.crypto_scalarmult_base(kp.publicKey, kp.secretKey);
101
+ return kp;
102
+ }
103
+ //# sourceMappingURL=noise-sha256.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"noise-sha256.js","sourceRoot":"","sources":["../../src/pairing/noise-sha256.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,KAAK,MAAM,gBAAgB,CAAC;AAGnC,qEAAqE;AACrE,wEAAwE;AACxE,MAAM,SAAS,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC,CAAC;AAKvE,+DAA+D;AAC/D,MAAM,SAAS,GAAG,SAAS,CAAC,mBAAmB,CAAiB,CAAC;AACjE,MAAM,aAAa,GAAG,SAAS,CAAC,uBAAuB,CAAiB,CAAC;AACzE,MAAM,kBAAkB,GAAG,SAAS,CAClC,6BAA6B,CACL,CAAC;AAC3B,MAAM,qBAAqB,GAAG,SAAS,CACrC,gCAAgC,CACR,CAAC;AAC3B,MAAM,GAAG,GAAG,SAAS,CAAC,oCAAoC,CAEzD,CAAC;AAEF,gFAAgF;AAEhF,0EAA0E;AAC1E,qEAAqE;AACrE,MAAM,CAAC,MAAM,kBAAkB,GAAG,EAAE,CAAC;AACrC,MAAM,CAAC,MAAM,eAAe,GAAG,EAAE,CAAC;AAElC,MAAM,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;AACjC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAE3E,SAAS,KAAK,CAAC,GAAe,EAAE,IAAkB;IAChD,MAAM,CAAC,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC;IAC/B,KAAK,MAAM,CAAC,IAAI,IAAI;QAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;IAClC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC;AACtB,CAAC;AAED,SAAS,KAAK,CAAC,GAAe,EAAE,GAAe,EAAE,KAAmB;IAClE,MAAM,CAAC,GAAG,UAAU,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;IACpC,KAAK,MAAM,CAAC,IAAI,KAAK;QAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;IACnC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC;AACtB,CAAC;AAED,SAAS,KAAK,CACZ,IAAgB,EAChB,IAAgB,EAChB,IAAuB,EACvB,EAAc,EACd,GAAe;IAEf,KAAK,CAAC,OAAO,EAAE,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC1B,KAAK,CAAC,IAAI,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC9B,KAAK,CAAC,IAAI,EAAE,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACpC,IAAI,IAAI,IAAI,IAAI;QAAE,KAAK,CAAC,IAAI,EAAE,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACtD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,MAAM,WAAW,GAAW;IAC1B,OAAO,EAAE,EAAE;IACX,QAAQ,EAAE,EAAE;IACZ,GAAG,EAAE,QAAQ;IACb,IAAI,EAAE,KAAK;IACX,IAAI,EAAE,KAAK;CACZ,CAAC;AAEF,iFAAiF;AAEjF,IAAI,QAAQ,GAA8C,IAAI,CAAC;AAE/D;;;;GAIG;AACH,MAAM,UAAU,uBAAuB,CAAC,EAAc,EAAE,EAAc;IACpE,QAAQ,GAAG,EAAE,EAAE,EAAE,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC;AAC1D,CAAC;AAED,MAAM,OAAO,GAAG,SAAS,EAAE,CAAC;AAC5B,MAAM,UAAU,GAAW;IACzB,GAAG,OAAO;IACV,eAAe,CAAC,EAAc,EAAE,EAAc;QAC5C,IAAI,QAAQ,EAAE,CAAC;YACb,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;YACpB,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;YACpB,QAAQ,GAAG,IAAI,CAAC;QAClB,CAAC;aAAM,CAAC;YACL,OAAO,CAAC,eAA4D,CACnE,EAAE,EACF,EAAE,CACH,CAAC;QACJ,CAAC;IACH,CAAC;CACF,CAAC;AAEF,gFAAgF;AAEhF,MAAM,OAAO,GAAG,aAAa,EAAE,CAAC;AAChC,MAAM,YAAY,GAAG,kBAAkB,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC;AAC7D,MAAM,eAAe,GAAG,qBAAqB,CAAC;IAC5C,IAAI,EAAE,WAAW;IACjB,WAAW,EAAE,YAAY;CAC1B,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,cAAc,GAAG,KAAK,CAAC,eAAe,CAAC;IAClD,EAAE,EAAE,UAAU;IACd,IAAI,EAAE,WAAW;IACjB,MAAM,EAAE,OAAO;IACf,WAAW,EAAE,YAAY;IACzB,cAAc,EAAE,eAAe;CAChC,CAAC,CAAC;AAEH,gFAAgF;AAEhF;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAAiB;IAChD,MAAM,EAAE,GAAG,cAAc,CAAC,MAAM,EAAE,CAAC,CAAC,2CAA2C;IAC/E,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;IACrC,GAAG,CAAC,sBAAsB,CAAC,EAAE,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,CAAC;IACvD,OAAO,EAAE,CAAC;AACZ,CAAC"}
@@ -0,0 +1,59 @@
1
+ /** Default ephemeral-token lifetime (also the QR rotation period). */
2
+ export declare const TOKEN_TTL_MS = 60000;
3
+ /** Bounds for a caller-supplied pairing TTL (e.g. `/remote-pi pair --ttl <s>`). */
4
+ export declare const PAIR_TTL_MIN_MS = 10000;
5
+ export declare const PAIR_TTL_MAX_MS = 600000;
6
+ /** Clamp an arbitrary ttl (ms) into the safe pairing range; NaN → default. */
7
+ export declare function clampPairTtlMs(ttlMs: number): number;
8
+ /** Encapsulates the single active QR token. One instance per Pi process. */
9
+ export declare class QRSession {
10
+ private active;
11
+ /** Generates a fresh 16-byte random token encoded as base64url. */
12
+ generateToken(): string;
13
+ /**
14
+ * Issues a new active token, invalidating any previous one.
15
+ * Returns the token and its expiry timestamp.
16
+ */
17
+ issueToken(ttlMs?: number): {
18
+ token: string;
19
+ expiresAt: number;
20
+ };
21
+ /** Validates and atomically consumes a token. */
22
+ consumeToken(token: string): "ok" | "expired" | "consumed" | "unknown";
23
+ clear(): void;
24
+ }
25
+ export declare const qrSession: QRSession;
26
+ export declare function buildQRUri(token: string, longtermEdPk: Uint8Array, // Ed25519 — only peer ID after E2E rollback
27
+ sessionName: string,
28
+ /**
29
+ * Pi room id (12 chars, base64url) derived from cwd. App routes pair_request
30
+ * to this room so the relay delivers it to the right Pi instance among N
31
+ * paralelos com mesmo epk. Adicionado no fix do plano 17 (sem `rm` o app
32
+ * cai em room=main e o relay drops com "dest not found").
33
+ */
34
+ roomId?: string): string;
35
+ /**
36
+ * Returns the QR ASCII as a string (pure Unicode block characters —
37
+ * `█ ▀ ▄` and space, NO ANSI escapes — qrcode-terminal v0.12 small mode
38
+ * is escape-free, see lib/main.js:48-53).
39
+ *
40
+ * The caller can either write the string to stderr (legacy path, breaks
41
+ * the Pi TUI layout) or inject it via `pi.sendMessage` (renders inside
42
+ * the chat panel as proper content).
43
+ */
44
+ export declare function renderQRAscii(uri: string): string;
45
+ /**
46
+ * Legacy stderr writer — kept for the standalone CLI mode
47
+ * (`pi-extension/src/index.ts` bottom block, which runs outside a Pi TUI).
48
+ * Inside the Pi TUI extension flow, use `renderQRAscii` + `pi.sendMessage`
49
+ * instead — direct stderr writes from inside an extension break the TUI's
50
+ * scrollable output widget (the QR overflows the panel and other writes
51
+ * collide with the prompt area).
52
+ */
53
+ export declare function displayQR(uri: string): void;
54
+ /**
55
+ * Starts a rotating QR session: generates a new QR every 60s, printing it
56
+ * to stdout. Returns a `stop()` function that cancels the rotation and clears
57
+ * the active token.
58
+ */
59
+ export declare function startQRRotation(longtermEdPk: Uint8Array, sessionName: string, roomId?: string): () => void;