@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.
- package/README.md +9 -2
- package/node_modules/@herbertgao/pi-cc-extensions/README.en.md +6 -8
- package/node_modules/@herbertgao/pi-cc-extensions/README.md +5 -7
- package/node_modules/@herbertgao/pi-cc-extensions/assets/readme/hero.en.svg +101 -0
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/config/config.ts +1 -17
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/config/panel.ts +5 -3
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/{utils/agent-summary.ts → feature/agent-summary/core.ts} +37 -35
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/{agent-summary.ts → agent-summary/index.ts} +2 -6
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/{session-reference.ts → reference/index.ts} +1 -1
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/{agent-autocomplete.ts → reference/subagent.ts} +19 -9
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/{pi-startup-header.ts → shell/startup-header.ts} +1 -1
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/{working-message.ts → shell/working-message.ts} +5 -2
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/index.ts +32 -28
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/compact-mode.ts +379 -85
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/default-mode.ts +727 -0
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/index.ts +65 -775
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/{feature → renderer}/markdown-enhance.ts +35 -31
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{mouse-hover.ts → mouse/hover.ts} +5 -5
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{mouse-interaction.ts → mouse/interaction.ts} +34 -35
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{mouse-layout.ts → mouse/layout.ts} +5 -21
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{mouse-packets.ts → mouse/packets.ts} +1 -1
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{mouse-scroll.ts → mouse/scroll.ts} +48 -37
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-diff → tool/diff}/ansi-utils.ts +56 -1
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-diff → tool/diff}/diff-renderer.ts +2 -2
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-diff → tool/diff}/line-width-safety.ts +1 -1
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/write-display-utils.ts +12 -0
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-diff → tool/diff}/write-execution.ts +1 -2
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-grouping.ts → tool/grouping.ts} +18 -8
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-result.ts → tool/result.ts} +4 -13
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/utils/fullscreen-detect.ts +0 -27
- package/node_modules/@herbertgao/pi-cc-extensions/package.json +3 -3
- package/node_modules/@herbertgao/pi-subagents/CHANGELOG.md +6 -0
- package/node_modules/@herbertgao/pi-subagents/package.json +2 -2
- package/node_modules/@herbertgao/pi-subagents/src/agent-manager.ts +1 -0
- package/node_modules/@herbertgao/pi-subagents/src/agent-runner.ts +3 -1
- package/node_modules/@herbertgao/pi-subagents/src/index.ts +33 -35
- package/node_modules/@herbertgao/pi-subagents/src/nested-tools.ts +26 -35
- package/node_modules/@herbertgao/pi-subagents/src/prompts.ts +15 -1
- package/node_modules/pi-mcp-adapter/CHANGELOG.md +19 -0
- package/node_modules/pi-mcp-adapter/README.md +19 -4
- package/node_modules/pi-mcp-adapter/agent-dir.ts +40 -0
- package/node_modules/pi-mcp-adapter/commands.ts +12 -2
- package/node_modules/pi-mcp-adapter/direct-tools.ts +6 -8
- package/node_modules/pi-mcp-adapter/index.ts +15 -3
- package/node_modules/pi-mcp-adapter/mcp-auth-flow.ts +87 -4
- package/node_modules/pi-mcp-adapter/mcp-callback-server.ts +138 -61
- package/node_modules/pi-mcp-adapter/mcp-oauth-provider.ts +43 -4
- package/node_modules/pi-mcp-adapter/oauth.ts +48 -0
- package/node_modules/pi-mcp-adapter/package.json +8 -2
- package/node_modules/pi-mcp-adapter/proxy-modes.ts +8 -10
- package/node_modules/pi-mcp-adapter/tool-registrar.ts +187 -3
- package/node_modules/pi-mcp-adapter/types.ts +2 -0
- package/node_modules/pi-web-access/CHANGELOG.md +45 -0
- package/node_modules/pi-web-access/README.md +104 -29
- package/node_modules/pi-web-access/bocha.ts +221 -0
- package/node_modules/pi-web-access/curator-page.ts +113 -12
- package/node_modules/pi-web-access/curator-server.ts +56 -20
- package/node_modules/pi-web-access/datalab-pdf-extract.ts +568 -0
- package/node_modules/pi-web-access/duckduckgo.ts +123 -0
- package/node_modules/pi-web-access/extract.ts +288 -143
- package/node_modules/pi-web-access/feature-config.ts +29 -0
- package/node_modules/pi-web-access/gemini-api.ts +4 -0
- package/node_modules/pi-web-access/gemini-search.ts +45 -12
- package/node_modules/pi-web-access/gemini-web.ts +68 -3
- package/node_modules/pi-web-access/index.ts +160 -71
- package/node_modules/pi-web-access/jina-search.ts +284 -0
- package/node_modules/pi-web-access/kagi.ts +12 -12
- package/node_modules/pi-web-access/openai-search.ts +12 -2
- package/node_modules/pi-web-access/package.json +4 -3
- package/node_modules/pi-web-access/pdf-extract.ts +327 -228
- package/node_modules/pi-web-access/storage.ts +440 -2
- package/node_modules/pi-web-access/summary-model-scope.ts +1 -1
- package/node_modules/pi-web-access/summary-review.ts +4 -2
- package/node_modules/pi-web-access/video-extract.ts +10 -8
- package/node_modules/pi-web-access/xai-search.ts +12 -2
- package/node_modules/pi-web-access/youtube-extract.ts +2 -1
- package/node_modules/remote-pi/LICENSE +21 -0
- package/node_modules/remote-pi/README.md +675 -0
- package/node_modules/remote-pi/dist/actions/handlers.d.ts +122 -0
- package/node_modules/remote-pi/dist/actions/handlers.js +160 -0
- package/node_modules/remote-pi/dist/actions/handlers.js.map +1 -0
- package/node_modules/remote-pi/dist/actions/registry.d.ts +39 -0
- package/node_modules/remote-pi/dist/actions/registry.js +58 -0
- package/node_modules/remote-pi/dist/actions/registry.js.map +1 -0
- package/node_modules/remote-pi/dist/bin/supervisord.d.ts +2 -0
- package/node_modules/remote-pi/dist/bin/supervisord.js +86 -0
- package/node_modules/remote-pi/dist/bin/supervisord.js.map +1 -0
- package/node_modules/remote-pi/dist/commands/builtin_mirror.d.ts +58 -0
- package/node_modules/remote-pi/dist/commands/builtin_mirror.js +71 -0
- package/node_modules/remote-pi/dist/commands/builtin_mirror.js.map +1 -0
- package/node_modules/remote-pi/dist/commands/list_commands.d.ts +60 -0
- package/node_modules/remote-pi/dist/commands/list_commands.js +73 -0
- package/node_modules/remote-pi/dist/commands/list_commands.js.map +1 -0
- package/node_modules/remote-pi/dist/config.d.ts +62 -0
- package/node_modules/remote-pi/dist/config.js +115 -0
- package/node_modules/remote-pi/dist/config.js.map +1 -0
- package/node_modules/remote-pi/dist/daemon/client.d.ts +20 -0
- package/node_modules/remote-pi/dist/daemon/client.js +131 -0
- package/node_modules/remote-pi/dist/daemon/client.js.map +1 -0
- package/node_modules/remote-pi/dist/daemon/control_protocol.d.ts +176 -0
- package/node_modules/remote-pi/dist/daemon/control_protocol.js +63 -0
- package/node_modules/remote-pi/dist/daemon/control_protocol.js.map +1 -0
- package/node_modules/remote-pi/dist/daemon/cron_log.d.ts +45 -0
- package/node_modules/remote-pi/dist/daemon/cron_log.js +72 -0
- package/node_modules/remote-pi/dist/daemon/cron_log.js.map +1 -0
- package/node_modules/remote-pi/dist/daemon/cron_registry.d.ts +80 -0
- package/node_modules/remote-pi/dist/daemon/cron_registry.js +194 -0
- package/node_modules/remote-pi/dist/daemon/cron_registry.js.map +1 -0
- package/node_modules/remote-pi/dist/daemon/id.d.ts +24 -0
- package/node_modules/remote-pi/dist/daemon/id.js +36 -0
- package/node_modules/remote-pi/dist/daemon/id.js.map +1 -0
- package/node_modules/remote-pi/dist/daemon/install.d.ts +170 -0
- package/node_modules/remote-pi/dist/daemon/install.js +547 -0
- package/node_modules/remote-pi/dist/daemon/install.js.map +1 -0
- package/node_modules/remote-pi/dist/daemon/registry.d.ts +63 -0
- package/node_modules/remote-pi/dist/daemon/registry.js +153 -0
- package/node_modules/remote-pi/dist/daemon/registry.js.map +1 -0
- package/node_modules/remote-pi/dist/daemon/rpc_child.d.ts +194 -0
- package/node_modules/remote-pi/dist/daemon/rpc_child.js +389 -0
- package/node_modules/remote-pi/dist/daemon/rpc_child.js.map +1 -0
- package/node_modules/remote-pi/dist/daemon/supervisor.d.ts +93 -0
- package/node_modules/remote-pi/dist/daemon/supervisor.js +596 -0
- package/node_modules/remote-pi/dist/daemon/supervisor.js.map +1 -0
- package/node_modules/remote-pi/dist/extension_ui_bridge.d.ts +26 -0
- package/node_modules/remote-pi/dist/extension_ui_bridge.js +341 -0
- package/node_modules/remote-pi/dist/extension_ui_bridge.js.map +1 -0
- package/node_modules/remote-pi/dist/index.d.ts +213 -0
- package/node_modules/remote-pi/dist/index.js +4996 -0
- package/node_modules/remote-pi/dist/index.js.map +1 -0
- package/node_modules/remote-pi/dist/mcp/mesh_result.d.ts +10 -0
- package/node_modules/remote-pi/dist/mcp/mesh_result.js +42 -0
- package/node_modules/remote-pi/dist/mcp/mesh_result.js.map +1 -0
- package/node_modules/remote-pi/dist/mcp/mesh_server.d.ts +16 -0
- package/node_modules/remote-pi/dist/mcp/mesh_server.js +327 -0
- package/node_modules/remote-pi/dist/mcp/mesh_server.js.map +1 -0
- package/node_modules/remote-pi/dist/mesh/canonical.d.ts +30 -0
- package/node_modules/remote-pi/dist/mesh/canonical.js +61 -0
- package/node_modules/remote-pi/dist/mesh/canonical.js.map +1 -0
- package/node_modules/remote-pi/dist/mesh/client.d.ts +18 -0
- package/node_modules/remote-pi/dist/mesh/client.js +125 -0
- package/node_modules/remote-pi/dist/mesh/client.js.map +1 -0
- package/node_modules/remote-pi/dist/mesh/encoding.d.ts +38 -0
- package/node_modules/remote-pi/dist/mesh/encoding.js +216 -0
- package/node_modules/remote-pi/dist/mesh/encoding.js.map +1 -0
- package/node_modules/remote-pi/dist/mesh/self_revoke.d.ts +73 -0
- package/node_modules/remote-pi/dist/mesh/self_revoke.js +401 -0
- package/node_modules/remote-pi/dist/mesh/self_revoke.js.map +1 -0
- package/node_modules/remote-pi/dist/mesh/siblings.d.ts +49 -0
- package/node_modules/remote-pi/dist/mesh/siblings.js +159 -0
- package/node_modules/remote-pi/dist/mesh/siblings.js.map +1 -0
- package/node_modules/remote-pi/dist/mesh/types.d.ts +34 -0
- package/node_modules/remote-pi/dist/mesh/types.js +11 -0
- package/node_modules/remote-pi/dist/mesh/types.js.map +1 -0
- package/node_modules/remote-pi/dist/mesh/verify.d.ts +17 -0
- package/node_modules/remote-pi/dist/mesh/verify.js +86 -0
- package/node_modules/remote-pi/dist/mesh/verify.js.map +1 -0
- package/node_modules/remote-pi/dist/pairing/crypto.d.ts +8 -0
- package/node_modules/remote-pi/dist/pairing/crypto.js +22 -0
- package/node_modules/remote-pi/dist/pairing/crypto.js.map +1 -0
- package/node_modules/remote-pi/dist/pairing/handshake.d.ts +28 -0
- package/node_modules/remote-pi/dist/pairing/handshake.js +113 -0
- package/node_modules/remote-pi/dist/pairing/handshake.js.map +1 -0
- package/node_modules/remote-pi/dist/pairing/noise-sha256.d.ts +16 -0
- package/node_modules/remote-pi/dist/pairing/noise-sha256.js +103 -0
- package/node_modules/remote-pi/dist/pairing/noise-sha256.js.map +1 -0
- package/node_modules/remote-pi/dist/pairing/qr.d.ts +59 -0
- package/node_modules/remote-pi/dist/pairing/qr.js +125 -0
- package/node_modules/remote-pi/dist/pairing/qr.js.map +1 -0
- package/node_modules/remote-pi/dist/pairing/storage.d.ts +120 -0
- package/node_modules/remote-pi/dist/pairing/storage.js +604 -0
- package/node_modules/remote-pi/dist/pairing/storage.js.map +1 -0
- package/node_modules/remote-pi/dist/protocol/codec.d.ts +7 -0
- package/node_modules/remote-pi/dist/protocol/codec.js +49 -0
- package/node_modules/remote-pi/dist/protocol/codec.js.map +1 -0
- package/node_modules/remote-pi/dist/protocol/types.d.ts +393 -0
- package/node_modules/remote-pi/dist/protocol/types.js +2 -0
- package/node_modules/remote-pi/dist/protocol/types.js.map +1 -0
- package/node_modules/remote-pi/dist/rooms.d.ts +29 -0
- package/node_modules/remote-pi/dist/rooms.js +57 -0
- package/node_modules/remote-pi/dist/rooms.js.map +1 -0
- package/node_modules/remote-pi/dist/session/address.d.ts +49 -0
- package/node_modules/remote-pi/dist/session/address.js +58 -0
- package/node_modules/remote-pi/dist/session/address.js.map +1 -0
- package/node_modules/remote-pi/dist/session/agent_bridge.d.ts +55 -0
- package/node_modules/remote-pi/dist/session/agent_bridge.js +146 -0
- package/node_modules/remote-pi/dist/session/agent_bridge.js.map +1 -0
- package/node_modules/remote-pi/dist/session/bridge.d.ts +37 -0
- package/node_modules/remote-pi/dist/session/bridge.js +130 -0
- package/node_modules/remote-pi/dist/session/bridge.js.map +1 -0
- package/node_modules/remote-pi/dist/session/broker.d.ts +189 -0
- package/node_modules/remote-pi/dist/session/broker.js +507 -0
- package/node_modules/remote-pi/dist/session/broker.js.map +1 -0
- package/node_modules/remote-pi/dist/session/broker_remote.d.ts +74 -0
- package/node_modules/remote-pi/dist/session/broker_remote.js +583 -0
- package/node_modules/remote-pi/dist/session/broker_remote.js.map +1 -0
- package/node_modules/remote-pi/dist/session/cwd_lock.d.ts +33 -0
- package/node_modules/remote-pi/dist/session/cwd_lock.js +126 -0
- package/node_modules/remote-pi/dist/session/cwd_lock.js.map +1 -0
- package/node_modules/remote-pi/dist/session/envelope.d.ts +33 -0
- package/node_modules/remote-pi/dist/session/envelope.js +117 -0
- package/node_modules/remote-pi/dist/session/envelope.js.map +1 -0
- package/node_modules/remote-pi/dist/session/global_config.d.ts +33 -0
- package/node_modules/remote-pi/dist/session/global_config.js +73 -0
- package/node_modules/remote-pi/dist/session/global_config.js.map +1 -0
- package/node_modules/remote-pi/dist/session/ipc.d.ts +27 -0
- package/node_modules/remote-pi/dist/session/ipc.js +22 -0
- package/node_modules/remote-pi/dist/session/ipc.js.map +1 -0
- package/node_modules/remote-pi/dist/session/leader_election.d.ts +32 -0
- package/node_modules/remote-pi/dist/session/leader_election.js +106 -0
- package/node_modules/remote-pi/dist/session/leader_election.js.map +1 -0
- package/node_modules/remote-pi/dist/session/local_config.d.ts +55 -0
- package/node_modules/remote-pi/dist/session/local_config.js +157 -0
- package/node_modules/remote-pi/dist/session/local_config.js.map +1 -0
- package/node_modules/remote-pi/dist/session/mesh_message.d.ts +20 -0
- package/node_modules/remote-pi/dist/session/mesh_message.js +28 -0
- package/node_modules/remote-pi/dist/session/mesh_message.js.map +1 -0
- package/node_modules/remote-pi/dist/session/mesh_node.d.ts +116 -0
- package/node_modules/remote-pi/dist/session/mesh_node.js +573 -0
- package/node_modules/remote-pi/dist/session/mesh_node.js.map +1 -0
- package/node_modules/remote-pi/dist/session/peer.d.ts +139 -0
- package/node_modules/remote-pi/dist/session/peer.js +451 -0
- package/node_modules/remote-pi/dist/session/peer.js.map +1 -0
- package/node_modules/remote-pi/dist/session/peer_inventory.d.ts +13 -0
- package/node_modules/remote-pi/dist/session/peer_inventory.js +48 -0
- package/node_modules/remote-pi/dist/session/peer_inventory.js.map +1 -0
- package/node_modules/remote-pi/dist/session/peer_limits.d.ts +9 -0
- package/node_modules/remote-pi/dist/session/peer_limits.js +21 -0
- package/node_modules/remote-pi/dist/session/peer_limits.js.map +1 -0
- package/node_modules/remote-pi/dist/session/setup_wizard.d.ts +39 -0
- package/node_modules/remote-pi/dist/session/setup_wizard.js +63 -0
- package/node_modules/remote-pi/dist/session/setup_wizard.js.map +1 -0
- package/node_modules/remote-pi/dist/session/tool_gate.d.ts +5 -0
- package/node_modules/remote-pi/dist/session/tool_gate.js +11 -0
- package/node_modules/remote-pi/dist/session/tool_gate.js.map +1 -0
- package/node_modules/remote-pi/dist/session/tools.d.ts +24 -0
- package/node_modules/remote-pi/dist/session/tools.js +252 -0
- package/node_modules/remote-pi/dist/session/tools.js.map +1 -0
- package/node_modules/remote-pi/dist/session/wizard.d.ts +13 -0
- package/node_modules/remote-pi/dist/session/wizard.js +20 -0
- package/node_modules/remote-pi/dist/session/wizard.js.map +1 -0
- package/node_modules/remote-pi/dist/settings.d.ts +15 -0
- package/node_modules/remote-pi/dist/settings.js +52 -0
- package/node_modules/remote-pi/dist/settings.js.map +1 -0
- package/node_modules/remote-pi/dist/transport/peer_channel.d.ts +37 -0
- package/node_modules/remote-pi/dist/transport/peer_channel.js +98 -0
- package/node_modules/remote-pi/dist/transport/peer_channel.js.map +1 -0
- package/node_modules/remote-pi/dist/transport/pi_forward_client.d.ts +29 -0
- package/node_modules/remote-pi/dist/transport/pi_forward_client.js +62 -0
- package/node_modules/remote-pi/dist/transport/pi_forward_client.js.map +1 -0
- package/node_modules/remote-pi/dist/transport/relay_client.d.ts +91 -0
- package/node_modules/remote-pi/dist/transport/relay_client.js +206 -0
- package/node_modules/remote-pi/dist/transport/relay_client.js.map +1 -0
- package/node_modules/remote-pi/dist/ui/footer.d.ts +32 -0
- package/node_modules/remote-pi/dist/ui/footer.js +34 -0
- package/node_modules/remote-pi/dist/ui/footer.js.map +1 -0
- package/node_modules/remote-pi/docs/daemon.md +289 -0
- package/node_modules/remote-pi/package.json +88 -0
- package/node_modules/remote-pi/service-templates/launchd.plist.template +35 -0
- package/node_modules/remote-pi/service-templates/systemd.service.template +19 -0
- package/node_modules/remote-pi/service-templates/task-launcher.vbs.template +10 -0
- package/node_modules/remote-pi/service-templates/task-scheduler.xml.template +38 -0
- package/node_modules/remote-pi/skills/agent-network/SKILL.md +310 -0
- package/package.json +19 -9
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool-diff/write-display-utils.ts +0 -29
- /package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/{session-reference-core.ts → reference/session.ts} +0 -0
- /package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/{pi-aliases.ts → shell/aliases.ts} +0 -0
- /package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-diff → tool/diff}/ATTRIBUTION.md +0 -0
- /package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-diff → tool/diff}/diff-presentation.ts +0 -0
- /package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-diff → tool/diff}/index.ts +0 -0
- /package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-diff → tool/diff}/render-utils.ts +0 -0
- /package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-diff → tool/diff}/shiki-highlight.ts +0 -0
- /package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{tool-diff → tool/diff}/types.ts +0 -0
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
const SERVER_TYPES = new Set([
|
|
2
|
+
"pair_ok",
|
|
3
|
+
"pair_error",
|
|
4
|
+
"user_input",
|
|
5
|
+
"queued_message_state",
|
|
6
|
+
"agent_chunk",
|
|
7
|
+
"agent_done",
|
|
8
|
+
"agent_message",
|
|
9
|
+
"tool_request",
|
|
10
|
+
"tool_result",
|
|
11
|
+
"error",
|
|
12
|
+
"cancelled",
|
|
13
|
+
"pong",
|
|
14
|
+
"bye",
|
|
15
|
+
"session_history",
|
|
16
|
+
// Plan/57 — interactive extension prompt (ask_user via pi-ask).
|
|
17
|
+
"extension_ui_request",
|
|
18
|
+
]);
|
|
19
|
+
export class DecodeError extends Error {
|
|
20
|
+
code;
|
|
21
|
+
constructor(code, message) {
|
|
22
|
+
super(message);
|
|
23
|
+
this.code = code;
|
|
24
|
+
this.name = "DecodeError";
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
export function encodeClient(msg) {
|
|
28
|
+
return JSON.stringify(msg) + "\n";
|
|
29
|
+
}
|
|
30
|
+
export function decodeServer(line) {
|
|
31
|
+
let obj;
|
|
32
|
+
try {
|
|
33
|
+
obj = JSON.parse(line.trim());
|
|
34
|
+
}
|
|
35
|
+
catch (e) {
|
|
36
|
+
throw new DecodeError("invalid_message", `not JSON: ${e.message}`);
|
|
37
|
+
}
|
|
38
|
+
if (!obj ||
|
|
39
|
+
typeof obj !== "object" ||
|
|
40
|
+
typeof obj.type !== "string") {
|
|
41
|
+
throw new DecodeError("invalid_message", "missing 'type'");
|
|
42
|
+
}
|
|
43
|
+
const t = obj.type;
|
|
44
|
+
if (!SERVER_TYPES.has(t)) {
|
|
45
|
+
throw new DecodeError("unsupported_type", `unknown type: ${t}`);
|
|
46
|
+
}
|
|
47
|
+
return obj;
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=codec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codec.js","sourceRoot":"","sources":["../../src/protocol/codec.ts"],"names":[],"mappings":"AAEA,MAAM,YAAY,GAAG,IAAI,GAAG,CAAwB;IAClD,SAAS;IACT,YAAY;IACZ,YAAY;IACZ,sBAAsB;IACtB,aAAa;IACb,YAAY;IACZ,eAAe;IACf,cAAc;IACd,aAAa;IACb,OAAO;IACP,WAAW;IACX,MAAM;IACN,KAAK;IACL,iBAAiB;IACjB,gEAAgE;IAChE,sBAAsB;CACvB,CAAC,CAAC;AAEH,MAAM,OAAO,WAAY,SAAQ,KAAK;IAElB;IADlB,YACkB,IAA4C,EAC5D,OAAe;QAEf,KAAK,CAAC,OAAO,CAAC,CAAC;QAHC,SAAI,GAAJ,IAAI,CAAwC;QAI5D,IAAI,CAAC,IAAI,GAAG,aAAa,CAAC;IAC5B,CAAC;CACF;AAED,MAAM,UAAU,YAAY,CAAC,GAAkB;IAC7C,OAAO,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC;AACpC,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,IAAY;IACvC,IAAI,GAAY,CAAC;IACjB,IAAI,CAAC;QACH,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;IAChC,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,MAAM,IAAI,WAAW,CAAC,iBAAiB,EAAE,aAAc,CAAW,CAAC,OAAO,EAAE,CAAC,CAAC;IAChF,CAAC;IACD,IACE,CAAC,GAAG;QACJ,OAAO,GAAG,KAAK,QAAQ;QACvB,OAAQ,GAA+B,CAAC,IAAI,KAAK,QAAQ,EACzD,CAAC;QACD,MAAM,IAAI,WAAW,CAAC,iBAAiB,EAAE,gBAAgB,CAAC,CAAC;IAC7D,CAAC;IACD,MAAM,CAAC,GAAI,GAA+B,CAAC,IAAc,CAAC;IAC1D,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,CAA0B,CAAC,EAAE,CAAC;QAClD,MAAM,IAAI,WAAW,CAAC,kBAAkB,EAAE,iBAAiB,CAAC,EAAE,CAAC,CAAC;IAClE,CAAC;IACD,OAAO,GAAoB,CAAC;AAC9B,CAAC"}
|
|
@@ -0,0 +1,393 @@
|
|
|
1
|
+
export type PairErrorCode = "token_expired" | "token_consumed" | "token_unknown" | "internal_error";
|
|
2
|
+
export type StreamingBehavior = "steer";
|
|
3
|
+
export type QueuedMessageItem = {
|
|
4
|
+
id: string;
|
|
5
|
+
text: string;
|
|
6
|
+
editable: boolean;
|
|
7
|
+
created_at: number;
|
|
8
|
+
};
|
|
9
|
+
export type ExtensionUiMethod = "select" | "confirm" | "input" | "editor" | "notify";
|
|
10
|
+
export type AskQuestionWireType = "single" | "multi" | "preview";
|
|
11
|
+
export interface AskOptionWire {
|
|
12
|
+
value: string;
|
|
13
|
+
label: string;
|
|
14
|
+
description?: string;
|
|
15
|
+
/** Preview-pane content (preview questions only). */
|
|
16
|
+
preview?: string;
|
|
17
|
+
/** pi-ask addition: option allows freeform custom entry. */
|
|
18
|
+
freeform?: boolean;
|
|
19
|
+
}
|
|
20
|
+
export interface AskQuestionWire {
|
|
21
|
+
id: string;
|
|
22
|
+
label: string;
|
|
23
|
+
prompt: string;
|
|
24
|
+
type: AskQuestionWireType;
|
|
25
|
+
required: boolean;
|
|
26
|
+
/** pi-ask addition: type actually presented after live toggle / policy. */
|
|
27
|
+
presentedType?: AskQuestionWireType;
|
|
28
|
+
/** pi-ask addition: type originally requested by the model. */
|
|
29
|
+
requestedType?: AskQuestionWireType;
|
|
30
|
+
options: AskOptionWire[];
|
|
31
|
+
}
|
|
32
|
+
/** Optional pi-ask enrichment on an extension_ui_request — lets the app render
|
|
33
|
+
* the full flow (multi/preview/notes) instead of the degraded SDK select. A
|
|
34
|
+
* flow maps to ONE request carrying every question; the app renders a
|
|
35
|
+
* full-screen modal and submits ONE response with all answers (pi-ask resolves
|
|
36
|
+
* a flow in a single submit). When `ask` is absent the SDK method/options
|
|
37
|
+
* drive rendering (future generic prompts). */
|
|
38
|
+
export interface AskEnrichmentWire {
|
|
39
|
+
flow_id: string;
|
|
40
|
+
tool_call_id: string | null;
|
|
41
|
+
/** pi-ask RemoteAskSource: "tool" | "answer" | "answer:again" | "ask:replay". */
|
|
42
|
+
source: string;
|
|
43
|
+
title: string | null;
|
|
44
|
+
questions: AskQuestionWire[];
|
|
45
|
+
}
|
|
46
|
+
/** pi-ask RemoteAskAnswer — one question's answered parts.
|
|
47
|
+
*
|
|
48
|
+
* CASING EXCEPTION: inside the `ask` envelope the keys mirror pi-ask's own
|
|
49
|
+
* schema VERBATIM (camelCase: `presentedType`, `requestedType`, `customText`,
|
|
50
|
+
* `optionNotes`) so the bridge can forward the response to pi-ask's submit
|
|
51
|
+
* event without a remap pass. The snake_case convention of this protocol
|
|
52
|
+
* applies at the frame level (`flow_id`, `tool_call_id`, `notify_type`). */
|
|
53
|
+
export interface AskAnswerWire {
|
|
54
|
+
values?: string[];
|
|
55
|
+
customText?: string;
|
|
56
|
+
note?: string;
|
|
57
|
+
optionNotes?: Record<string, string>;
|
|
58
|
+
}
|
|
59
|
+
/** Optional pi-ask enrichment on an extension_ui_response — carries the
|
|
60
|
+
* structured answer so multi/preview/notes survive the round-trip. */
|
|
61
|
+
export type AskResponseEnrichmentWire = {
|
|
62
|
+
flow_id: string;
|
|
63
|
+
kind: "answer";
|
|
64
|
+
mode?: "submit" | "elaborate";
|
|
65
|
+
answers: Record<string, AskAnswerWire>;
|
|
66
|
+
} | {
|
|
67
|
+
flow_id: string;
|
|
68
|
+
kind: "cancel";
|
|
69
|
+
};
|
|
70
|
+
/** ServerMessage: interactive extension prompt. Mirrors RpcExtensionUIRequest
|
|
71
|
+
* (select/confirm/input/editor/notify). The `ask` envelope is present when the
|
|
72
|
+
* prompt originates from a pi-ask flow, carrying the full question schema. */
|
|
73
|
+
export type ExtensionUiRequestWire = {
|
|
74
|
+
type: "extension_ui_request";
|
|
75
|
+
id: string;
|
|
76
|
+
method: "select";
|
|
77
|
+
title: string;
|
|
78
|
+
options: string[];
|
|
79
|
+
ask?: AskEnrichmentWire;
|
|
80
|
+
} | {
|
|
81
|
+
type: "extension_ui_request";
|
|
82
|
+
id: string;
|
|
83
|
+
method: "confirm";
|
|
84
|
+
title: string;
|
|
85
|
+
message: string;
|
|
86
|
+
ask?: AskEnrichmentWire;
|
|
87
|
+
} | {
|
|
88
|
+
type: "extension_ui_request";
|
|
89
|
+
id: string;
|
|
90
|
+
method: "input";
|
|
91
|
+
title: string;
|
|
92
|
+
placeholder?: string;
|
|
93
|
+
ask?: AskEnrichmentWire;
|
|
94
|
+
} | {
|
|
95
|
+
type: "extension_ui_request";
|
|
96
|
+
id: string;
|
|
97
|
+
method: "editor";
|
|
98
|
+
title: string;
|
|
99
|
+
prefill?: string;
|
|
100
|
+
ask?: AskEnrichmentWire;
|
|
101
|
+
} | {
|
|
102
|
+
type: "extension_ui_request";
|
|
103
|
+
id: string;
|
|
104
|
+
method: "notify";
|
|
105
|
+
message: string;
|
|
106
|
+
notify_type?: "info" | "warning" | "error";
|
|
107
|
+
};
|
|
108
|
+
/** ClientMessage: response to an extension_ui_request. Mirrors
|
|
109
|
+
* RpcExtensionUIResponse (value / confirmed / cancelled). The `ask` envelope
|
|
110
|
+
* carries pi-ask's structured answer when the app rendered the rich flow. */
|
|
111
|
+
export type ExtensionUiResponseWire = {
|
|
112
|
+
type: "extension_ui_response";
|
|
113
|
+
id: string;
|
|
114
|
+
value: string;
|
|
115
|
+
ask?: AskResponseEnrichmentWire;
|
|
116
|
+
} | {
|
|
117
|
+
type: "extension_ui_response";
|
|
118
|
+
id: string;
|
|
119
|
+
confirmed: boolean;
|
|
120
|
+
ask?: AskResponseEnrichmentWire;
|
|
121
|
+
} | {
|
|
122
|
+
type: "extension_ui_response";
|
|
123
|
+
id: string;
|
|
124
|
+
cancelled: true;
|
|
125
|
+
ask?: AskResponseEnrichmentWire;
|
|
126
|
+
} | {
|
|
127
|
+
type: "extension_ui_response";
|
|
128
|
+
id: string;
|
|
129
|
+
ask: AskResponseEnrichmentWire;
|
|
130
|
+
};
|
|
131
|
+
export type ClientMessage = {
|
|
132
|
+
type: "pair_request";
|
|
133
|
+
id: string;
|
|
134
|
+
token: string;
|
|
135
|
+
device_name: string;
|
|
136
|
+
} | {
|
|
137
|
+
type: "user_message";
|
|
138
|
+
id: string;
|
|
139
|
+
text: string;
|
|
140
|
+
images?: WireImage[];
|
|
141
|
+
streaming_behavior?: StreamingBehavior;
|
|
142
|
+
} | {
|
|
143
|
+
type: "queued_message_set";
|
|
144
|
+
id: string;
|
|
145
|
+
text: string;
|
|
146
|
+
} | {
|
|
147
|
+
type: "queued_message_clear";
|
|
148
|
+
id: string;
|
|
149
|
+
target_id?: string;
|
|
150
|
+
} | {
|
|
151
|
+
type: "approve_tool";
|
|
152
|
+
id: string;
|
|
153
|
+
tool_call_id: string;
|
|
154
|
+
decision: "allow" | "deny";
|
|
155
|
+
} | {
|
|
156
|
+
type: "cancel";
|
|
157
|
+
id: string;
|
|
158
|
+
target_id: string;
|
|
159
|
+
} | {
|
|
160
|
+
type: "ping";
|
|
161
|
+
id: string;
|
|
162
|
+
} | {
|
|
163
|
+
type: "session_sync";
|
|
164
|
+
id: string;
|
|
165
|
+
limit?: number;
|
|
166
|
+
} | {
|
|
167
|
+
type: "session_new";
|
|
168
|
+
id: string;
|
|
169
|
+
} | {
|
|
170
|
+
type: "session_compact";
|
|
171
|
+
id: string;
|
|
172
|
+
} | {
|
|
173
|
+
type: "model_set";
|
|
174
|
+
id: string;
|
|
175
|
+
provider: string;
|
|
176
|
+
model_id: string;
|
|
177
|
+
} | {
|
|
178
|
+
type: "thinking_set";
|
|
179
|
+
id: string;
|
|
180
|
+
level: ThinkingLevel;
|
|
181
|
+
} | {
|
|
182
|
+
type: "list_models";
|
|
183
|
+
id: string;
|
|
184
|
+
} | ExtensionUiResponseWire;
|
|
185
|
+
/**
|
|
186
|
+
* Plan/30 — one inline image attachment on a `user_message`. Mirrors the
|
|
187
|
+
* SDK's `ImageContent` ({@link https }) split across the wire: `data` is the
|
|
188
|
+
* base64-encoded (compressed) image bytes, `mime` its content type
|
|
189
|
+
* (e.g. `"image/jpeg"`). The Pi maps `{ data, mime }` → the SDK's
|
|
190
|
+
* `{ type:"image", data, mimeType }` before handing it to the model.
|
|
191
|
+
*/
|
|
192
|
+
export interface WireImage {
|
|
193
|
+
/** Base64-encoded image bytes (compressed app-side). */
|
|
194
|
+
data: string;
|
|
195
|
+
/** MIME type, e.g. `"image/jpeg"`. Maps to the SDK's `mimeType`. */
|
|
196
|
+
mime: string;
|
|
197
|
+
}
|
|
198
|
+
export type Usage = {
|
|
199
|
+
input_tokens: number;
|
|
200
|
+
output_tokens: number;
|
|
201
|
+
};
|
|
202
|
+
export type KnownErrorCode = "tool_approval_required" | "invalid_message" | "unsupported_type" | "too_large" | "rate_limited" | "timeout" | "internal_error";
|
|
203
|
+
export type ErrorCode = KnownErrorCode | (string & {});
|
|
204
|
+
export type SessionHistoryEvent = {
|
|
205
|
+
ts: number;
|
|
206
|
+
type: "user_input";
|
|
207
|
+
id: string;
|
|
208
|
+
text: string;
|
|
209
|
+
images?: WireImage[];
|
|
210
|
+
} | {
|
|
211
|
+
ts: number;
|
|
212
|
+
type: "tool_request";
|
|
213
|
+
tool_call_id: string;
|
|
214
|
+
tool: string;
|
|
215
|
+
args: Record<string, unknown>;
|
|
216
|
+
} | {
|
|
217
|
+
ts: number;
|
|
218
|
+
type: "tool_result";
|
|
219
|
+
tool_call_id: string;
|
|
220
|
+
result?: unknown;
|
|
221
|
+
error?: string;
|
|
222
|
+
} | {
|
|
223
|
+
ts: number;
|
|
224
|
+
type: "agent_message";
|
|
225
|
+
in_reply_to: string;
|
|
226
|
+
text: string;
|
|
227
|
+
usage?: Usage;
|
|
228
|
+
} | {
|
|
229
|
+
ts: number;
|
|
230
|
+
type: "compaction";
|
|
231
|
+
summary: string;
|
|
232
|
+
tokens_before: number;
|
|
233
|
+
};
|
|
234
|
+
export type ServerMessage = {
|
|
235
|
+
type: "pair_ok";
|
|
236
|
+
in_reply_to: string;
|
|
237
|
+
session_name: string;
|
|
238
|
+
session_started_at: number;
|
|
239
|
+
room_id: string;
|
|
240
|
+
/**
|
|
241
|
+
* Plan/27 Wave A: identifies the host coding agent driving this
|
|
242
|
+
* pi-extension instance. `name` is hardcoded to "Pi coding agent"
|
|
243
|
+
* today; future Pi forks (Claude Code, OpenCode) populate their own
|
|
244
|
+
* here. `version` is the pi-extension `package.json` version.
|
|
245
|
+
* Optional in the wire schema so app-side parsing tolerates older
|
|
246
|
+
* Pi builds that predate this field — every new pairing emits both.
|
|
247
|
+
*/
|
|
248
|
+
harness?: {
|
|
249
|
+
name: string;
|
|
250
|
+
version: string;
|
|
251
|
+
};
|
|
252
|
+
/**
|
|
253
|
+
* Plan/27 Wave A: `os.hostname()` of the machine the Pi runs on.
|
|
254
|
+
* App displays it in the device list so the user can distinguish
|
|
255
|
+
* two paired PCs that happen to share a nickname or sit in the
|
|
256
|
+
* same project folder.
|
|
257
|
+
*/
|
|
258
|
+
hostname?: string;
|
|
259
|
+
} | {
|
|
260
|
+
type: "pair_error";
|
|
261
|
+
in_reply_to: string;
|
|
262
|
+
code: PairErrorCode;
|
|
263
|
+
message: string;
|
|
264
|
+
} | {
|
|
265
|
+
type: "user_input";
|
|
266
|
+
id: string;
|
|
267
|
+
text: string;
|
|
268
|
+
streaming_behavior?: StreamingBehavior;
|
|
269
|
+
} | {
|
|
270
|
+
type: "user_message";
|
|
271
|
+
id: string;
|
|
272
|
+
text: string;
|
|
273
|
+
images?: WireImage[];
|
|
274
|
+
streaming_behavior?: StreamingBehavior;
|
|
275
|
+
} | {
|
|
276
|
+
type: "queued_message_state";
|
|
277
|
+
id?: string;
|
|
278
|
+
text?: string;
|
|
279
|
+
items?: QueuedMessageItem[];
|
|
280
|
+
} | {
|
|
281
|
+
type: "steer_consumed";
|
|
282
|
+
id: string;
|
|
283
|
+
} | {
|
|
284
|
+
type: "agent_chunk";
|
|
285
|
+
in_reply_to: string;
|
|
286
|
+
delta: string;
|
|
287
|
+
} | {
|
|
288
|
+
type: "agent_done";
|
|
289
|
+
in_reply_to: string;
|
|
290
|
+
usage?: Usage;
|
|
291
|
+
} | {
|
|
292
|
+
type: "agent_message";
|
|
293
|
+
in_reply_to: string;
|
|
294
|
+
text: string;
|
|
295
|
+
usage?: Usage;
|
|
296
|
+
} | {
|
|
297
|
+
type: "compaction";
|
|
298
|
+
summary: string;
|
|
299
|
+
tokens_before: number;
|
|
300
|
+
ts?: number;
|
|
301
|
+
} | {
|
|
302
|
+
type: "tool_request";
|
|
303
|
+
tool_call_id: string;
|
|
304
|
+
tool: string;
|
|
305
|
+
args: Record<string, unknown>;
|
|
306
|
+
} | {
|
|
307
|
+
type: "tool_result";
|
|
308
|
+
tool_call_id: string;
|
|
309
|
+
result?: unknown;
|
|
310
|
+
error?: string;
|
|
311
|
+
} | {
|
|
312
|
+
type: "error";
|
|
313
|
+
in_reply_to?: string;
|
|
314
|
+
code: ErrorCode;
|
|
315
|
+
message: string;
|
|
316
|
+
} | {
|
|
317
|
+
type: "cancelled";
|
|
318
|
+
in_reply_to: string;
|
|
319
|
+
target_id: string;
|
|
320
|
+
} | {
|
|
321
|
+
type: "pong";
|
|
322
|
+
in_reply_to: string;
|
|
323
|
+
} | {
|
|
324
|
+
type: "bye";
|
|
325
|
+
reason: ByeReason;
|
|
326
|
+
} | {
|
|
327
|
+
type: "session_history";
|
|
328
|
+
in_reply_to: string;
|
|
329
|
+
session_started_at: number;
|
|
330
|
+
events: SessionHistoryEvent[];
|
|
331
|
+
eos: boolean;
|
|
332
|
+
truncated: boolean;
|
|
333
|
+
} | {
|
|
334
|
+
type: "action_ok";
|
|
335
|
+
in_reply_to: string;
|
|
336
|
+
action: ActionName;
|
|
337
|
+
} | {
|
|
338
|
+
type: "action_error";
|
|
339
|
+
in_reply_to: string;
|
|
340
|
+
action: ActionName;
|
|
341
|
+
error: string;
|
|
342
|
+
} | {
|
|
343
|
+
type: "models_list";
|
|
344
|
+
in_reply_to: string;
|
|
345
|
+
models: WireModel[];
|
|
346
|
+
current?: WireModel;
|
|
347
|
+
} | ExtensionUiRequestWire;
|
|
348
|
+
/**
|
|
349
|
+
* Plan/28 — Stable names for the typed actions the app can request. Kept
|
|
350
|
+
* as a closed string union so a switch in either side gets exhaustiveness
|
|
351
|
+
* checking from the compiler.
|
|
352
|
+
*/
|
|
353
|
+
export type ActionName = "session_new" | "session_compact" | "model_set" | "thinking_set";
|
|
354
|
+
/**
|
|
355
|
+
* Plan/28 — Mirror of the SDK's `ThinkingLevel` (defined in
|
|
356
|
+
* `@earendil-works/pi-agent-core/types`). Re-declared locally so the wire
|
|
357
|
+
* protocol owns its own enum and we don't leak SDK-internal types onto
|
|
358
|
+
* the app's network surface.
|
|
359
|
+
*
|
|
360
|
+
* Note: `"xhigh"` is only honored by select model families — the SDK uses
|
|
361
|
+
* each `Model.thinkingLevelMap` to decide if the requested level is
|
|
362
|
+
* supported, falling back to a sensible neighbour when not. The app
|
|
363
|
+
* surfaces all 6 buttons but can grey out unsupported ones using the
|
|
364
|
+
* model's metadata if the picker fetches it later.
|
|
365
|
+
*/
|
|
366
|
+
export type ThinkingLevel = "off" | "minimal" | "low" | "medium" | "high" | "xhigh";
|
|
367
|
+
/**
|
|
368
|
+
* Plan/28 — Wire shape for one model entry in the app's model picker.
|
|
369
|
+
*
|
|
370
|
+
* Subset of the SDK's `Model<Api>` interface — only the fields the app
|
|
371
|
+
* actually renders. Cost / max-tokens / API class are left off the wire
|
|
372
|
+
* deliberately; if the app's picker grows to need them, they get added
|
|
373
|
+
* here and to the handler's mapping in `index.ts` in one diff.
|
|
374
|
+
*/
|
|
375
|
+
export interface WireModel {
|
|
376
|
+
/** Stable identifier inside the provider's catalog. E.g. `"claude-opus-4-7"`. */
|
|
377
|
+
id: string;
|
|
378
|
+
/** Display name for the picker row. E.g. `"Claude Opus 4.7"`. */
|
|
379
|
+
name: string;
|
|
380
|
+
/** Provider slug. E.g. `"anthropic"`, `"openai"`. */
|
|
381
|
+
provider: string;
|
|
382
|
+
/** Whether the model supports the thinking surface (`reasoning: true`
|
|
383
|
+
* in the SDK). Useful so the app can decide whether the thinking
|
|
384
|
+
* segmented control should be enabled when this model is selected. */
|
|
385
|
+
reasoning: boolean;
|
|
386
|
+
/** Context window in tokens, for display in the picker subtitle. */
|
|
387
|
+
context_window: number;
|
|
388
|
+
/** Plan/30: true when the model accepts image input (SDK `Model.input`
|
|
389
|
+
* includes `"image"`). The app uses it to enable/disable the attach
|
|
390
|
+
* button — a text-only model greys out image attachments. */
|
|
391
|
+
vision: boolean;
|
|
392
|
+
}
|
|
393
|
+
export type ByeReason = "peer_stop" | "session_replaced" | "shutdown";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/protocol/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Deterministic room id derived from a cwd. Two Pi processes in the same
|
|
3
|
+
* directory produce the same id; different cwds produce different ids
|
|
4
|
+
* (with cryptographic-strength collision resistance). Symlinks are resolved
|
|
5
|
+
* via `realpath` so `/a` and `/symlink-to-a` map to the same room.
|
|
6
|
+
*
|
|
7
|
+
* Format: first 12 chars of base64url(sha256(realpath)).
|
|
8
|
+
*/
|
|
9
|
+
export declare function roomIdForCwd(cwd: string): string;
|
|
10
|
+
/**
|
|
11
|
+
* THE single derivation of the App↔Pi `room_id` (plan/41) — keyed by
|
|
12
|
+
* `(cwd, name)` so several agents in the SAME folder get distinct rooms (the
|
|
13
|
+
* app then renders one tile per agent instead of merging them into one).
|
|
14
|
+
*
|
|
15
|
+
* Default-preserving: when `name` is absent OR equals `defaultAgentName(cwd)`
|
|
16
|
+
* (an agent with no custom `agent_name`), it returns the LEGACY `roomIdForCwd`
|
|
17
|
+
* EXACTLY — so a single unnamed agent's existing conversation is NOT re-keyed
|
|
18
|
+
* on upgrade. A custom or `#N`-suffixed name → a name-scoped id (same formula
|
|
19
|
+
* the cwd-lock uses).
|
|
20
|
+
*
|
|
21
|
+
* Using the ASSIGNED leaf name (the broker's `#N` on collision) disambiguates
|
|
22
|
+
* even two unnamed agents: the 1st stays `folder` (== default → legacy room),
|
|
23
|
+
* the 2nd becomes `folder#2` (≠ default → name-scoped room).
|
|
24
|
+
*
|
|
25
|
+
* INVARIANT: every callsite that derives the App↔Pi room for the same agent
|
|
26
|
+
* MUST go through this function — otherwise the app would pair on a room the
|
|
27
|
+
* Pi never announces.
|
|
28
|
+
*/
|
|
29
|
+
export declare function roomIdFor(cwd: string, name?: string): string;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { realpathSync } from "node:fs";
|
|
3
|
+
import { defaultAgentName } from "./session/local_config.js";
|
|
4
|
+
/**
|
|
5
|
+
* Deterministic room id derived from a cwd. Two Pi processes in the same
|
|
6
|
+
* directory produce the same id; different cwds produce different ids
|
|
7
|
+
* (with cryptographic-strength collision resistance). Symlinks are resolved
|
|
8
|
+
* via `realpath` so `/a` and `/symlink-to-a` map to the same room.
|
|
9
|
+
*
|
|
10
|
+
* Format: first 12 chars of base64url(sha256(realpath)).
|
|
11
|
+
*/
|
|
12
|
+
export function roomIdForCwd(cwd) {
|
|
13
|
+
let target;
|
|
14
|
+
try {
|
|
15
|
+
target = realpathSync(cwd);
|
|
16
|
+
}
|
|
17
|
+
catch {
|
|
18
|
+
// cwd doesn't exist (unlikely in production) — fallback to raw path.
|
|
19
|
+
target = cwd;
|
|
20
|
+
}
|
|
21
|
+
return createHash("sha256").update(target).digest("base64url").slice(0, 12);
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* THE single derivation of the App↔Pi `room_id` (plan/41) — keyed by
|
|
25
|
+
* `(cwd, name)` so several agents in the SAME folder get distinct rooms (the
|
|
26
|
+
* app then renders one tile per agent instead of merging them into one).
|
|
27
|
+
*
|
|
28
|
+
* Default-preserving: when `name` is absent OR equals `defaultAgentName(cwd)`
|
|
29
|
+
* (an agent with no custom `agent_name`), it returns the LEGACY `roomIdForCwd`
|
|
30
|
+
* EXACTLY — so a single unnamed agent's existing conversation is NOT re-keyed
|
|
31
|
+
* on upgrade. A custom or `#N`-suffixed name → a name-scoped id (same formula
|
|
32
|
+
* the cwd-lock uses).
|
|
33
|
+
*
|
|
34
|
+
* Using the ASSIGNED leaf name (the broker's `#N` on collision) disambiguates
|
|
35
|
+
* even two unnamed agents: the 1st stays `folder` (== default → legacy room),
|
|
36
|
+
* the 2nd becomes `folder#2` (≠ default → name-scoped room).
|
|
37
|
+
*
|
|
38
|
+
* INVARIANT: every callsite that derives the App↔Pi room for the same agent
|
|
39
|
+
* MUST go through this function — otherwise the app would pair on a room the
|
|
40
|
+
* Pi never announces.
|
|
41
|
+
*/
|
|
42
|
+
export function roomIdFor(cwd, name) {
|
|
43
|
+
if (!name || name === defaultAgentName(cwd))
|
|
44
|
+
return roomIdForCwd(cwd);
|
|
45
|
+
let target;
|
|
46
|
+
try {
|
|
47
|
+
target = realpathSync(cwd);
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
target = cwd;
|
|
51
|
+
}
|
|
52
|
+
// NUL separator (U+0000): impossible in a POSIX path and stripped from any
|
|
53
|
+
// sanitized name, so the cwd/name boundary is unambiguous.
|
|
54
|
+
const sep = String.fromCharCode(0);
|
|
55
|
+
return createHash("sha256").update(target + sep + name).digest("base64url").slice(0, 12);
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=rooms.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rooms.js","sourceRoot":"","sources":["../src/rooms.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAE7D;;;;;;;GAOG;AACH,MAAM,UAAU,YAAY,CAAC,GAAW;IACtC,IAAI,MAAc,CAAC;IACnB,IAAI,CAAC;QACH,MAAM,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC;IAC7B,CAAC;IAAC,MAAM,CAAC;QACP,qEAAqE;QACrE,MAAM,GAAG,GAAG,CAAC;IACf,CAAC;IACD,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;AAC9E,CAAC;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,UAAU,SAAS,CAAC,GAAW,EAAE,IAAa;IAClD,IAAI,CAAC,IAAI,IAAI,IAAI,KAAK,gBAAgB,CAAC,GAAG,CAAC;QAAE,OAAO,YAAY,CAAC,GAAG,CAAC,CAAC;IACtE,IAAI,MAAc,CAAC;IACnB,IAAI,CAAC;QACH,MAAM,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC;IAC7B,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,GAAG,GAAG,CAAC;IACf,CAAC;IACD,2EAA2E;IAC3E,2DAA2D;IAC3D,MAAM,GAAG,GAAG,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IACnC,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;AAC3F,CAAC"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mesh addressing for plan/35 (malha direta). An "agent" ≡ a cwd (cwd_lock
|
|
3
|
+
* guarantees at most one Pi per folder), so the folder *is* the address:
|
|
4
|
+
*
|
|
5
|
+
* - **local** → an absolute path on this machine. A local peer is reached by
|
|
6
|
+
* `POST`ing its inbox socket directly (see `apiSockPath`).
|
|
7
|
+
* - **remote** → `<label>:/path`, where `<label>` names a sibling machine
|
|
8
|
+
* (resolved to a pubkey via `mesh_versions`/siblings in Wave C) and `/path`
|
|
9
|
+
* is the folder on that machine. Routed cross-PC through the relay.
|
|
10
|
+
*
|
|
11
|
+
* The address an agent passes is ALWAYS the absolute folder path; the `.sock`
|
|
12
|
+
* file itself lives OUTSIDE the cwd (decisão fixada — "Transporte local"). The
|
|
13
|
+
* folder is hashed to the file name, so the mapping is deterministic and both
|
|
14
|
+
* the inbox (its own socket) and a sender (the peer's socket) land on the same
|
|
15
|
+
* file without coordinating.
|
|
16
|
+
*
|
|
17
|
+
* Wave 0 only *parses* what it is handed — contacts (known routes) live in the
|
|
18
|
+
* agent's context/CLAUDE.md (decisão Q5), not in an allowlist module. The
|
|
19
|
+
* `<label>→pubkey` resolution and remote send arrive in Wave C; here we keep
|
|
20
|
+
* the parser and the local route→socket mapping.
|
|
21
|
+
*/
|
|
22
|
+
export type Address = {
|
|
23
|
+
kind: "local";
|
|
24
|
+
path: string;
|
|
25
|
+
} | {
|
|
26
|
+
kind: "remote";
|
|
27
|
+
label: string;
|
|
28
|
+
path: string;
|
|
29
|
+
};
|
|
30
|
+
export declare class AddressError extends Error {
|
|
31
|
+
constructor(message: string);
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Parses a mesh address. A `:` separates a remote `<label>` from its `/path`;
|
|
35
|
+
* with no `:` the whole string is a local absolute path (decisão fixada:
|
|
36
|
+
* "Sem ':' → local"). Both the local path and the remote path must be
|
|
37
|
+
* absolute — the folder is the canonical route.
|
|
38
|
+
*/
|
|
39
|
+
export declare function parseAddress(raw: string): Address;
|
|
40
|
+
/**
|
|
41
|
+
* The inbox socket path for a folder. Single source of truth shared by the
|
|
42
|
+
* inbox server (its own socket) and the send client (a local peer's socket).
|
|
43
|
+
*
|
|
44
|
+
* `~/.pi/remote-pi/socks/<roomId>.sock`, where `roomId = roomIdForCwd(folder)`
|
|
45
|
+
* (`sha256(realpath(folder))[:12]` — the same hash `cwd_lock` uses). The folder
|
|
46
|
+
* is the address; the hash is only the file name. `realpath` canonicalization
|
|
47
|
+
* means `/a` and a symlink to `/a` map to the same socket.
|
|
48
|
+
*/
|
|
49
|
+
export declare function apiSockPath(folderPath: string): string;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { homedir } from "node:os";
|
|
2
|
+
import { isAbsolute, join } from "node:path";
|
|
3
|
+
import { roomIdForCwd } from "../rooms.js";
|
|
4
|
+
export class AddressError extends Error {
|
|
5
|
+
constructor(message) {
|
|
6
|
+
super(message);
|
|
7
|
+
this.name = "AddressError";
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Parses a mesh address. A `:` separates a remote `<label>` from its `/path`;
|
|
12
|
+
* with no `:` the whole string is a local absolute path (decisão fixada:
|
|
13
|
+
* "Sem ':' → local"). Both the local path and the remote path must be
|
|
14
|
+
* absolute — the folder is the canonical route.
|
|
15
|
+
*/
|
|
16
|
+
export function parseAddress(raw) {
|
|
17
|
+
const trimmed = raw.trim();
|
|
18
|
+
if (!trimmed)
|
|
19
|
+
throw new AddressError("empty address");
|
|
20
|
+
const colon = trimmed.indexOf(":");
|
|
21
|
+
if (colon === -1) {
|
|
22
|
+
if (!isAbsolute(trimmed)) {
|
|
23
|
+
throw new AddressError(`local address must be an absolute path: ${trimmed}`);
|
|
24
|
+
}
|
|
25
|
+
return { kind: "local", path: trimmed };
|
|
26
|
+
}
|
|
27
|
+
const label = trimmed.slice(0, colon);
|
|
28
|
+
const path = trimmed.slice(colon + 1);
|
|
29
|
+
if (!label)
|
|
30
|
+
throw new AddressError(`remote address missing label: ${trimmed}`);
|
|
31
|
+
if (!path)
|
|
32
|
+
throw new AddressError(`remote address missing path: ${trimmed}`);
|
|
33
|
+
if (!isAbsolute(path)) {
|
|
34
|
+
throw new AddressError(`remote address path must be absolute: ${trimmed}`);
|
|
35
|
+
}
|
|
36
|
+
return { kind: "remote", label, path };
|
|
37
|
+
}
|
|
38
|
+
/** Directory holding inbox sockets, resolved at call time (not module load) so
|
|
39
|
+
* tests can redirect it via `REMOTE_PI_HOME` — the same override `cwd_lock`
|
|
40
|
+
* honors. Kept OUT of the cwd: `sun_path` is capped at 104 chars on macOS
|
|
41
|
+
* (EINVAL at ≥105), so a socket nested inside a deep cwd would overflow. */
|
|
42
|
+
function socksDir() {
|
|
43
|
+
const root = process.env["REMOTE_PI_HOME"] || homedir();
|
|
44
|
+
return join(root, ".pi", "remote-pi", "socks");
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* The inbox socket path for a folder. Single source of truth shared by the
|
|
48
|
+
* inbox server (its own socket) and the send client (a local peer's socket).
|
|
49
|
+
*
|
|
50
|
+
* `~/.pi/remote-pi/socks/<roomId>.sock`, where `roomId = roomIdForCwd(folder)`
|
|
51
|
+
* (`sha256(realpath(folder))[:12]` — the same hash `cwd_lock` uses). The folder
|
|
52
|
+
* is the address; the hash is only the file name. `realpath` canonicalization
|
|
53
|
+
* means `/a` and a symlink to `/a` map to the same socket.
|
|
54
|
+
*/
|
|
55
|
+
export function apiSockPath(folderPath) {
|
|
56
|
+
return join(socksDir(), `${roomIdForCwd(folderPath)}.sock`);
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=address.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"address.js","sourceRoot":"","sources":["../../src/session/address.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AA4B3C,MAAM,OAAO,YAAa,SAAQ,KAAK;IACrC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,cAAc,CAAC;IAC7B,CAAC;CACF;AAED;;;;;GAKG;AACH,MAAM,UAAU,YAAY,CAAC,GAAW;IACtC,MAAM,OAAO,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC;IAC3B,IAAI,CAAC,OAAO;QAAE,MAAM,IAAI,YAAY,CAAC,eAAe,CAAC,CAAC;IAEtD,MAAM,KAAK,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IACnC,IAAI,KAAK,KAAK,CAAC,CAAC,EAAE,CAAC;QACjB,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;YACzB,MAAM,IAAI,YAAY,CAAC,2CAA2C,OAAO,EAAE,CAAC,CAAC;QAC/E,CAAC;QACD,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;IAC1C,CAAC;IAED,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;IACtC,MAAM,IAAI,GAAG,OAAO,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;IACtC,IAAI,CAAC,KAAK;QAAE,MAAM,IAAI,YAAY,CAAC,iCAAiC,OAAO,EAAE,CAAC,CAAC;IAC/E,IAAI,CAAC,IAAI;QAAE,MAAM,IAAI,YAAY,CAAC,gCAAgC,OAAO,EAAE,CAAC,CAAC;IAC7E,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QACtB,MAAM,IAAI,YAAY,CAAC,yCAAyC,OAAO,EAAE,CAAC,CAAC;IAC7E,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;AACzC,CAAC;AAED;;;6EAG6E;AAC7E,SAAS,QAAQ;IACf,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,IAAI,OAAO,EAAE,CAAC;IACxD,OAAO,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,WAAW,EAAE,OAAO,CAAC,CAAC;AACjD,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,WAAW,CAAC,UAAkB;IAC5C,OAAO,IAAI,CAAC,QAAQ,EAAE,EAAE,GAAG,YAAY,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;AAC9D,CAAC"}
|