@yefengr/remote-pi 0.7.4 → 0.7.6

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 (165) hide show
  1. package/README.md +81 -586
  2. package/dist/bin/supervisord.js +4 -5
  3. package/dist/bin/supervisord.js.map +1 -1
  4. package/dist/config.d.ts +1 -1
  5. package/dist/config.js +2 -2
  6. package/dist/daemon/cli-links.d.ts +30 -0
  7. package/dist/daemon/cli-links.js +134 -0
  8. package/dist/daemon/cli-links.js.map +1 -0
  9. package/dist/daemon/commands.d.ts +27 -0
  10. package/dist/daemon/commands.js +295 -0
  11. package/dist/daemon/commands.js.map +1 -0
  12. package/dist/daemon/control_protocol.d.ts +53 -31
  13. package/dist/daemon/control_protocol.js +8 -31
  14. package/dist/daemon/control_protocol.js.map +1 -1
  15. package/dist/daemon/cron_log.d.ts +2 -23
  16. package/dist/daemon/cron_log.js +10 -25
  17. package/dist/daemon/cron_log.js.map +1 -1
  18. package/dist/daemon/cron_registry.d.ts +3 -40
  19. package/dist/daemon/cron_registry.js +58 -103
  20. package/dist/daemon/cron_registry.js.map +1 -1
  21. package/dist/daemon/install-runtime.d.ts +10 -0
  22. package/dist/daemon/install-runtime.js +81 -0
  23. package/dist/daemon/install-runtime.js.map +1 -0
  24. package/dist/daemon/install.d.ts +3 -63
  25. package/dist/daemon/install.js +5 -289
  26. package/dist/daemon/install.js.map +1 -1
  27. package/dist/daemon/preflight.d.ts +51 -0
  28. package/dist/daemon/preflight.js +136 -0
  29. package/dist/daemon/preflight.js.map +1 -0
  30. package/dist/daemon/registry.d.ts +33 -45
  31. package/dist/daemon/registry.js +171 -117
  32. package/dist/daemon/registry.js.map +1 -1
  33. package/dist/daemon/rpc_child.d.ts +92 -146
  34. package/dist/daemon/rpc_child.js +336 -263
  35. package/dist/daemon/rpc_child.js.map +1 -1
  36. package/dist/daemon/status.d.ts +45 -0
  37. package/dist/daemon/status.js +87 -0
  38. package/dist/daemon/status.js.map +1 -0
  39. package/dist/daemon/supervisor-ipc.d.ts +2 -0
  40. package/dist/daemon/supervisor-ipc.js +20 -0
  41. package/dist/daemon/supervisor-ipc.js.map +1 -0
  42. package/dist/daemon/supervisor.d.ts +48 -71
  43. package/dist/daemon/supervisor.js +430 -420
  44. package/dist/daemon/supervisor.js.map +1 -1
  45. package/dist/extension_ui_bridge.d.ts +4 -3
  46. package/dist/extension_ui_bridge.js +10 -0
  47. package/dist/extension_ui_bridge.js.map +1 -1
  48. package/dist/index.d.ts +25 -230
  49. package/dist/index.js +515 -5553
  50. package/dist/index.js.map +1 -1
  51. package/dist/pairing/crypto.d.ts +8 -1
  52. package/dist/pairing/crypto.js +56 -6
  53. package/dist/pairing/crypto.js.map +1 -1
  54. package/dist/pairing/owner_storage.d.ts +42 -0
  55. package/dist/pairing/owner_storage.js +207 -0
  56. package/dist/pairing/owner_storage.js.map +1 -0
  57. package/dist/pairing/qr.d.ts +3 -42
  58. package/dist/pairing/qr.js +9 -59
  59. package/dist/pairing/qr.js.map +1 -1
  60. package/dist/pairing/storage.d.ts +3 -45
  61. package/dist/pairing/storage.js +10 -223
  62. package/dist/pairing/storage.js.map +1 -1
  63. package/dist/protocol/types.d.ts +1 -1
  64. package/dist/protocol/v2/schemas.d.ts +1 -1
  65. package/dist/protocol/v2/schemas.js +1 -1
  66. package/dist/protocol/v2/schemas.js.map +1 -1
  67. package/dist/runtime/owner_router.d.ts +16 -0
  68. package/dist/runtime/owner_router.js +37 -0
  69. package/dist/runtime/owner_router.js.map +1 -0
  70. package/dist/session/ipc.d.ts +1 -22
  71. package/dist/session/ipc.js +4 -11
  72. package/dist/session/ipc.js.map +1 -1
  73. package/dist/session/local_config.d.ts +4 -47
  74. package/dist/session/local_config.js +19 -101
  75. package/dist/session/local_config.js.map +1 -1
  76. package/dist/transport/peer_channel.d.ts +25 -39
  77. package/dist/transport/peer_channel.js +74 -131
  78. package/dist/transport/peer_channel.js.map +1 -1
  79. package/dist/transport/relay_client.d.ts +26 -70
  80. package/dist/transport/relay_client.js +37 -106
  81. package/dist/transport/relay_client.js.map +1 -1
  82. package/docs/daemon.md +91 -207
  83. package/package.json +21 -17
  84. package/dist/daemon/id.d.ts +0 -24
  85. package/dist/daemon/id.js +0 -36
  86. package/dist/daemon/id.js.map +0 -1
  87. package/dist/mcp/mesh_result.d.ts +0 -10
  88. package/dist/mcp/mesh_result.js +0 -42
  89. package/dist/mcp/mesh_result.js.map +0 -1
  90. package/dist/mcp/mesh_server.d.ts +0 -16
  91. package/dist/mcp/mesh_server.js +0 -327
  92. package/dist/mcp/mesh_server.js.map +0 -1
  93. package/dist/mesh/canonical.d.ts +0 -30
  94. package/dist/mesh/canonical.js +0 -61
  95. package/dist/mesh/canonical.js.map +0 -1
  96. package/dist/mesh/client.d.ts +0 -18
  97. package/dist/mesh/client.js +0 -125
  98. package/dist/mesh/client.js.map +0 -1
  99. package/dist/mesh/encoding.d.ts +0 -38
  100. package/dist/mesh/encoding.js +0 -216
  101. package/dist/mesh/encoding.js.map +0 -1
  102. package/dist/mesh/self_revoke.d.ts +0 -73
  103. package/dist/mesh/self_revoke.js +0 -401
  104. package/dist/mesh/self_revoke.js.map +0 -1
  105. package/dist/mesh/siblings.d.ts +0 -49
  106. package/dist/mesh/siblings.js +0 -159
  107. package/dist/mesh/siblings.js.map +0 -1
  108. package/dist/mesh/types.d.ts +0 -34
  109. package/dist/mesh/types.js +0 -11
  110. package/dist/mesh/types.js.map +0 -1
  111. package/dist/mesh/verify.d.ts +0 -17
  112. package/dist/mesh/verify.js +0 -86
  113. package/dist/mesh/verify.js.map +0 -1
  114. package/dist/rooms.d.ts +0 -29
  115. package/dist/rooms.js +0 -57
  116. package/dist/rooms.js.map +0 -1
  117. package/dist/session/bridge.d.ts +0 -37
  118. package/dist/session/bridge.js +0 -130
  119. package/dist/session/bridge.js.map +0 -1
  120. package/dist/session/broker.d.ts +0 -189
  121. package/dist/session/broker.js +0 -507
  122. package/dist/session/broker.js.map +0 -1
  123. package/dist/session/broker_remote.d.ts +0 -74
  124. package/dist/session/broker_remote.js +0 -583
  125. package/dist/session/broker_remote.js.map +0 -1
  126. package/dist/session/cwd_lock.d.ts +0 -33
  127. package/dist/session/cwd_lock.js +0 -126
  128. package/dist/session/cwd_lock.js.map +0 -1
  129. package/dist/session/envelope.d.ts +0 -33
  130. package/dist/session/envelope.js +0 -117
  131. package/dist/session/envelope.js.map +0 -1
  132. package/dist/session/global_config.d.ts +0 -33
  133. package/dist/session/global_config.js +0 -73
  134. package/dist/session/global_config.js.map +0 -1
  135. package/dist/session/leader_election.d.ts +0 -32
  136. package/dist/session/leader_election.js +0 -106
  137. package/dist/session/leader_election.js.map +0 -1
  138. package/dist/session/mesh_node.d.ts +0 -116
  139. package/dist/session/mesh_node.js +0 -573
  140. package/dist/session/mesh_node.js.map +0 -1
  141. package/dist/session/peer.d.ts +0 -139
  142. package/dist/session/peer.js +0 -451
  143. package/dist/session/peer.js.map +0 -1
  144. package/dist/session/peer_inventory.d.ts +0 -13
  145. package/dist/session/peer_inventory.js +0 -48
  146. package/dist/session/peer_inventory.js.map +0 -1
  147. package/dist/session/peer_limits.d.ts +0 -9
  148. package/dist/session/peer_limits.js +0 -21
  149. package/dist/session/peer_limits.js.map +0 -1
  150. package/dist/session/setup_wizard.d.ts +0 -39
  151. package/dist/session/setup_wizard.js +0 -63
  152. package/dist/session/setup_wizard.js.map +0 -1
  153. package/dist/session/tools.d.ts +0 -24
  154. package/dist/session/tools.js +0 -252
  155. package/dist/session/tools.js.map +0 -1
  156. package/dist/session/wizard.d.ts +0 -13
  157. package/dist/session/wizard.js +0 -20
  158. package/dist/session/wizard.js.map +0 -1
  159. package/dist/transport/pi_forward_client.d.ts +0 -29
  160. package/dist/transport/pi_forward_client.js +0 -62
  161. package/dist/transport/pi_forward_client.js.map +0 -1
  162. package/dist/ui/footer.d.ts +0 -32
  163. package/dist/ui/footer.js +0 -34
  164. package/dist/ui/footer.js.map +0 -1
  165. package/skills/agent-network/SKILL.md +0 -310
@@ -1,55 +1,12 @@
1
1
  export interface LocalConfig {
2
2
  agent_name?: string;
3
- /**
4
- * If true (default), `/remote-pi` with no args auto-joins the local UDS
5
- * mesh and starts the relay on a fresh terminal. The field name is
6
- * historical (plano 21); the UX wording was reworked to "use the relay
7
- * on this terminal to connect to the remote mesh (PWA + PCs)". Legacy
8
- * configs without this field are treated as `true` for backward compat.
9
- */
3
+ /** Whether an interactive Pi starts its Relay endpoint automatically. */
10
4
  auto_start_relay?: boolean;
11
5
  }
12
- /**
13
- * Normalize a name segment to a mesh-safe token: trim, replace the addressing
14
- * separators (`/ : @ #`) and whitespace runs with `-`, collapse repeats, strip
15
- * edges. The `@` is included so a sanitized name can never contain the address
16
- * separator — `<cwd>@<name>` stays unambiguous on the wire. Returns undefined
17
- * when the input isn't a usable non-empty string, sanitizes to empty, or is a
18
- * reserved addressing keyword (`broadcast` / `broker`). Used by the broker's
19
- * `sanitizeMeshName` to keep the `<nome>` half of a peer address safe to
20
- * compose (plan/38).
21
- */
22
- export declare function sanitizeSegment(v: unknown): string | undefined;
23
- /**
24
- * Migrate a persisted `agent_name` to the plan/38 leaf-name model (decision E).
25
- * Two legacy shapes get rewritten on read so a pre-fix config never fossilizes a
26
- * runtime accident as if it were an explicit choice:
27
- *
28
- * - **`#N` collision suffix** — could only have come from a broker/lock
29
- * assignment (the user can't type `#`: `sanitizeSegment` maps it to `-`), so
30
- * a trailing `#<digits>` is stripped and the clean base re-derived.
31
- * - **legacy `parent/folder`** — the old `defaultAgentName` shape; the `/`
32
- * means it predates the leaf-only model, so we keep only the leaf segment.
33
- *
34
- * Returns the cleaned name, or undefined when nothing usable remains (so the
35
- * caller falls back to `defaultAgentName(cwd)`).
36
- */
37
- export declare function migrateAgentName(raw: string): string | undefined;
38
- /**
39
- * True when a local config is available for this cwd — either inline via
40
- * `REMOTE_PI_DIRECT_CONFIG` or as `<cwd>/.pi/remote-pi/config.json` on disk.
41
- */
42
6
  export declare function localConfigExists(cwd: string): boolean;
43
7
  export declare function loadLocalConfig(cwd: string): LocalConfig;
44
8
  export declare function saveLocalConfig(cwd: string, patch: Partial<LocalConfig>): void;
45
- /**
46
- * Default agent name when none is configured (plan/38 decision D): the **leaf**
47
- * of the cwd, `basename(cwd)`. The cwd now travels as its own address axis
48
- * (`<cwd>@<nome>`), so the name no longer needs the `parent/folder` prefix that
49
- * used to disambiguate folders — the broker keys peers by `(cwd, nome)`, and a
50
- * clean leaf means `#N` almost never fires. Falls back to `"agent"` for a
51
- * path with no usable basename (root / empty).
52
- */
9
+ /** Default display name when none is configured. */
53
10
  export declare function defaultAgentName(cwd: string): string;
54
- /** Resolves auto_start_relay with backward-compat (undefined → true). */
55
- export declare function effectiveAutoStartRelay(cfg: LocalConfig): boolean;
11
+ /** Resolves the default for omitted config values. */
12
+ export declare function effectiveAutoStartRelay(config: LocalConfig): boolean;
@@ -2,64 +2,10 @@ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
2
2
  import { basename, dirname, join } from "node:path";
3
3
  const LOCAL_DIR = ".pi/remote-pi";
4
4
  const LOCAL_FILE = "config.json";
5
- /**
6
- * Escape hatch: when set, carries the WHOLE local config as inline JSON,
7
- * bypassing the on-disk `config.json`. For CI/ops/daemons that inject config
8
- * via env instead of writing a file — mirrors `REMOTE_PI_RELAY` for the relay
9
- * URL. Takes precedence over the file; an unset/empty/unparseable value falls
10
- * back to the file (never fatal).
11
- */
12
5
  const DIRECT_CONFIG_ENV = "REMOTE_PI_DIRECT_CONFIG";
13
6
  function pathFor(cwd) {
14
7
  return join(cwd, LOCAL_DIR, LOCAL_FILE);
15
8
  }
16
- /**
17
- * Normalize a name segment to a mesh-safe token: trim, replace the addressing
18
- * separators (`/ : @ #`) and whitespace runs with `-`, collapse repeats, strip
19
- * edges. The `@` is included so a sanitized name can never contain the address
20
- * separator — `<cwd>@<name>` stays unambiguous on the wire. Returns undefined
21
- * when the input isn't a usable non-empty string, sanitizes to empty, or is a
22
- * reserved addressing keyword (`broadcast` / `broker`). Used by the broker's
23
- * `sanitizeMeshName` to keep the `<nome>` half of a peer address safe to
24
- * compose (plan/38).
25
- */
26
- export function sanitizeSegment(v) {
27
- if (typeof v !== "string")
28
- return undefined;
29
- const token = v.trim().replace(/[/:@#\s]+/g, "-").replace(/-{2,}/g, "-").replace(/^-+|-+$/g, "");
30
- if (!token)
31
- return undefined;
32
- if (token.toLowerCase() === "broadcast" || token.toLowerCase() === "broker")
33
- return undefined;
34
- return token;
35
- }
36
- /**
37
- * Migrate a persisted `agent_name` to the plan/38 leaf-name model (decision E).
38
- * Two legacy shapes get rewritten on read so a pre-fix config never fossilizes a
39
- * runtime accident as if it were an explicit choice:
40
- *
41
- * - **`#N` collision suffix** — could only have come from a broker/lock
42
- * assignment (the user can't type `#`: `sanitizeSegment` maps it to `-`), so
43
- * a trailing `#<digits>` is stripped and the clean base re-derived.
44
- * - **legacy `parent/folder`** — the old `defaultAgentName` shape; the `/`
45
- * means it predates the leaf-only model, so we keep only the leaf segment.
46
- *
47
- * Returns the cleaned name, or undefined when nothing usable remains (so the
48
- * caller falls back to `defaultAgentName(cwd)`).
49
- */
50
- export function migrateAgentName(raw) {
51
- // Legacy `parent/folder` (or any path-ish value) → keep the trailing segment.
52
- const leaf = raw.includes("/") ? raw.slice(raw.lastIndexOf("/") + 1) : raw;
53
- // Drop a runtime collision suffix a pre-fix build may have frozen into config.
54
- const clean = leaf.replace(/#\d+$/, "").trim();
55
- return clean.length > 0 ? clean : undefined;
56
- }
57
- /**
58
- * Parse a raw JSON string into a LocalConfig, surfacing only known fields.
59
- * Returns null when the input isn't a usable JSON object. Legacy `session_name`
60
- * from pre-refactor configs is silently dropped — the local UDS mesh is now
61
- * always a single fixed session, so the field has no meaning.
62
- */
63
9
  function parseLocalConfig(raw) {
64
10
  let parsed;
65
11
  try {
@@ -70,88 +16,60 @@ function parseLocalConfig(raw) {
70
16
  }
71
17
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed))
72
18
  return null;
73
- const src = parsed;
74
- const cfg = {};
75
- if (typeof src["agent_name"] === "string") {
76
- // Migrate on read (plan/38 decision E): strip a frozen `#N` and the legacy
77
- // `parent/folder` shape so neither fossilizes as an explicit name.
78
- const migrated = migrateAgentName(src["agent_name"]);
79
- if (migrated)
80
- cfg.agent_name = migrated;
19
+ const source = parsed;
20
+ const config = {};
21
+ if (typeof source["agent_name"] === "string" && source["agent_name"].trim()) {
22
+ config.agent_name = source["agent_name"].trim();
23
+ }
24
+ if (typeof source["auto_start_relay"] === "boolean") {
25
+ config.auto_start_relay = source["auto_start_relay"];
81
26
  }
82
- if (typeof src["auto_start_relay"] === "boolean")
83
- cfg.auto_start_relay = src["auto_start_relay"];
84
- return cfg;
27
+ return config;
85
28
  }
86
- /** Inline config from `REMOTE_PI_DIRECT_CONFIG`, when set + parseable; else null. */
87
29
  function directConfig() {
88
30
  const raw = process.env[DIRECT_CONFIG_ENV];
89
31
  if (!raw || raw.trim().length === 0)
90
32
  return null;
91
33
  return parseLocalConfig(raw);
92
34
  }
93
- /**
94
- * True when a local config is available for this cwd — either inline via
95
- * `REMOTE_PI_DIRECT_CONFIG` or as `<cwd>/.pi/remote-pi/config.json` on disk.
96
- */
97
35
  export function localConfigExists(cwd) {
98
36
  return directConfig() !== null || existsSync(pathFor(cwd));
99
37
  }
100
38
  export function loadLocalConfig(cwd) {
101
- // Precedence: inline `REMOTE_PI_DIRECT_CONFIG` env wins over the file. An
102
- // unset/empty/malformed env falls through to the on-disk config.json.
103
39
  const direct = directConfig();
104
40
  if (direct)
105
41
  return direct;
106
- const p = pathFor(cwd);
107
- if (!existsSync(p))
42
+ const path = pathFor(cwd);
43
+ if (!existsSync(path))
108
44
  return {};
109
45
  try {
110
- return parseLocalConfig(readFileSync(p, "utf8")) ?? {};
46
+ return parseLocalConfig(readFileSync(path, "utf8")) ?? {};
111
47
  }
112
48
  catch {
113
49
  return {};
114
50
  }
115
51
  }
116
52
  export function saveLocalConfig(cwd, patch) {
117
- const p = pathFor(cwd);
53
+ const path = pathFor(cwd);
118
54
  const current = loadLocalConfig(cwd);
119
55
  const next = { ...current, ...patch };
120
- // Always persist auto_start_relay explicitly (default true) so future reads
121
- // never need to guess. Backward-compat: legacy files without the field
122
- // are treated as true on read; we lock that intent in on first save.
123
56
  if (typeof next.auto_start_relay !== "boolean")
124
57
  next.auto_start_relay = true;
125
- // Best-effort persistence: a read-only config.json is a legitimate deployment
126
- // (NixOS/Home Manager symlink into the immutable Nix store, read-only root,
127
- // EPERM). The name/config sync is cosmetic — it must NEVER crash the pi
128
- // process with an uncaughtException. `saveLocalConfig` is reached via
129
- // fire-and-forget async paths (`void _syncNameFromPi()` from `turn_start` /
130
- // `session_start`), so a sync throw from `mkdirSync`/`writeFileSync` sails
131
- // past the runner's per-handler try/catch and takes down pi. Guard both fs
132
- // calls together so a partial attempt can't throw past the caller.
133
58
  try {
134
- mkdirSync(dirname(p), { recursive: true });
135
- writeFileSync(p, JSON.stringify(next, null, 2));
59
+ mkdirSync(dirname(path), { recursive: true });
60
+ writeFileSync(path, JSON.stringify(next, null, 2));
136
61
  }
137
62
  catch (error) {
138
63
  const message = error instanceof Error ? error.message : String(error);
139
- console.warn(`[remote-pi] could not persist local config ${p}: ${message}`);
64
+ console.warn(`[remote-pi] could not persist local config ${path}: ${message}`);
140
65
  }
141
66
  }
142
- /**
143
- * Default agent name when none is configured (plan/38 decision D): the **leaf**
144
- * of the cwd, `basename(cwd)`. The cwd now travels as its own address axis
145
- * (`<cwd>@<nome>`), so the name no longer needs the `parent/folder` prefix that
146
- * used to disambiguate folders — the broker keys peers by `(cwd, nome)`, and a
147
- * clean leaf means `#N` almost never fires. Falls back to `"agent"` for a
148
- * path with no usable basename (root / empty).
149
- */
67
+ /** Default display name when none is configured. */
150
68
  export function defaultAgentName(cwd) {
151
69
  return basename(cwd) || "agent";
152
70
  }
153
- /** Resolves auto_start_relay with backward-compat (undefined → true). */
154
- export function effectiveAutoStartRelay(cfg) {
155
- return cfg.auto_start_relay !== false;
71
+ /** Resolves the default for omitted config values. */
72
+ export function effectiveAutoStartRelay(config) {
73
+ return config.auto_start_relay !== false;
156
74
  }
157
75
  //# sourceMappingURL=local_config.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"local_config.js","sourceRoot":"","sources":["../../src/session/local_config.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"local_config.js","sourceRoot":"","sources":["../../src/session/local_config.ts"],"names":[],"mappings":"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"}
@@ -1,57 +1,43 @@
1
- import type { ClientMessage, ServerMessage } from "../protocol/types.js";
2
1
  import { type ClientFrame, type ServerFrame } from "../protocol/v2/index.js";
3
2
  import type { RelayClient } from "./relay_client.js";
4
- /** Sink for ServerMessage outbound to the remote app. */
5
- export interface PeerChannel {
6
- send(msg: ServerMessage): void;
7
- }
3
+ export type RoutePurpose = "pairing" | "session";
4
+ export type RouteFrame = {
5
+ type: "route";
6
+ purpose: RoutePurpose;
7
+ device_id: string;
8
+ endpoint_id: string;
9
+ runtime_instance_id: string;
10
+ target_owner_id?: string;
11
+ source_owner_id?: string;
12
+ ct: string;
13
+ };
14
+ export type HostRouteIdentity = {
15
+ deviceId: string;
16
+ endpointId: string;
17
+ runtimeInstanceId: string;
18
+ };
8
19
  export interface V2Channel {
9
20
  getPeerId(): string;
10
21
  sendV2(msg: ServerFrame): void;
11
22
  detach(): void;
12
23
  }
13
24
  /**
14
- * Plaintext PeerChannel backed by a RelayClient WebSocket.
15
- *
16
- * Usage (after pair_request handshake completes):
17
- * const channel = new PlainPeerChannel(relay, appPeerId, myRoomId, onMsg)
18
- * channel.send(serverMessage) // base64-encodes JSON, routes via relay
19
- * // incoming relay messages destined for appPeerId are auto-decoded
20
- * // and delivered via onMessage callback
21
- *
22
- * `myRoomId` is the *local* Pi's room id — sent on every outbound envelope
23
- * so the app can correlate which Pi sent it (multi-pi support, plano 17).
25
+ * A Host-side protocol-v2 channel for one authorized Owner. The relay
26
+ * authenticates and injects `source_owner_id` for Owner-to-Host routes; this
27
+ * channel only accepts routes for its immutable endpoint identity and owner.
24
28
  */
25
29
  export declare class V2PeerChannel implements V2Channel {
26
30
  private readonly relay;
27
- private readonly remotePeerId;
31
+ private readonly ownerId;
32
+ private readonly host;
28
33
  private readonly onMessage;
29
34
  private readonly unsubscribe;
30
- constructor(relay: RelayClient, remotePeerId: string, onMessage: (msg: ClientFrame) => void);
35
+ constructor(relay: RelayClient, ownerId: string, host: HostRouteIdentity, onMessage: (msg: ClientFrame) => void);
31
36
  getPeerId(): string;
32
37
  sendV2(msg: ServerFrame): void;
33
38
  detach(): void;
34
39
  private onLine;
40
+ private sendUpgradeRequired;
35
41
  }
36
- /** @deprecated Protocol v1 test helper. Production uses V2PeerChannel. */
37
- export declare class PlainPeerChannel implements PeerChannel {
38
- private readonly relay;
39
- private readonly remotePeerId;
40
- private readonly onMessage;
41
- private readonly _unsubscribe;
42
- constructor(relay: RelayClient, remotePeerId: string,
43
- /**
44
- * This Pi's room id. Currently NOT injected in the outer envelope
45
- * (defensive — relay/app not yet ready). Kept in the constructor for
46
- * forward-compat so callers don't need to change again when we re-enable.
47
- */
48
- myRoomId: string | undefined, onMessage: (msg: ClientMessage) => void,
49
- /** Called when this specific peer connection is considered lost. */
50
- _onDisconnect?: () => void);
51
- /** Authenticated Owner peer id used as a server-derived sender reference. */
52
- getPeerId(): string;
53
- send(msg: ServerMessage): void;
54
- /** Detaches from relay (does not close the relay itself). */
55
- detach(): void;
56
- private _onLine;
57
- }
42
+ export declare function parseIncomingRoute(line: string, host: HostRouteIdentity, ownerId?: string): RouteFrame | null;
43
+ export declare function sendRoute(relay: RelayClient, host: HostRouteIdentity, ownerId: string, purpose: RoutePurpose, ct: string): void;
@@ -1,171 +1,114 @@
1
1
  import { decodeClientFrameV2, encodeServerFrameV2, } from "../protocol/v2/index.js";
2
2
  /**
3
- * Plaintext PeerChannel backed by a RelayClient WebSocket.
4
- *
5
- * Usage (after pair_request handshake completes):
6
- * const channel = new PlainPeerChannel(relay, appPeerId, myRoomId, onMsg)
7
- * channel.send(serverMessage) // base64-encodes JSON, routes via relay
8
- * // incoming relay messages destined for appPeerId are auto-decoded
9
- * // and delivered via onMessage callback
10
- *
11
- * `myRoomId` is the *local* Pi's room id — sent on every outbound envelope
12
- * so the app can correlate which Pi sent it (multi-pi support, plano 17).
3
+ * A Host-side protocol-v2 channel for one authorized Owner. The relay
4
+ * authenticates and injects `source_owner_id` for Owner-to-Host routes; this
5
+ * channel only accepts routes for its immutable endpoint identity and owner.
13
6
  */
14
7
  export class V2PeerChannel {
15
8
  relay;
16
- remotePeerId;
9
+ ownerId;
10
+ host;
17
11
  onMessage;
18
12
  unsubscribe;
19
- constructor(relay, remotePeerId, onMessage) {
13
+ constructor(relay, ownerId, host, onMessage) {
20
14
  this.relay = relay;
21
- this.remotePeerId = remotePeerId;
15
+ this.ownerId = ownerId;
16
+ this.host = host;
22
17
  this.onMessage = onMessage;
23
18
  const listener = (line) => this.onLine(line);
24
19
  relay.on("message", listener);
25
20
  this.unsubscribe = () => relay.off("message", listener);
26
21
  }
27
22
  getPeerId() {
28
- return this.remotePeerId;
23
+ return this.ownerId;
29
24
  }
30
25
  sendV2(msg) {
31
- let ct;
32
26
  try {
33
- ct = Buffer.from(encodeServerFrameV2(msg)).toString("base64");
34
- this.relay.send(JSON.stringify({ peer: this.remotePeerId, ct }));
27
+ const ct = Buffer.from(encodeServerFrameV2(msg)).toString("base64");
28
+ this.relay.send(JSON.stringify({
29
+ type: "route",
30
+ purpose: msg.type === "pair_ok" || msg.type === "pair_error" ? "pairing" : "session",
31
+ device_id: this.host.deviceId,
32
+ endpoint_id: this.host.endpointId,
33
+ runtime_instance_id: this.host.runtimeInstanceId,
34
+ target_owner_id: this.ownerId,
35
+ ct,
36
+ }));
35
37
  }
36
38
  catch {
37
- // Reconnect plus authoritative history recovers dropped formal events.
39
+ // Formal history recovers messages lost while the relay reconnects.
38
40
  }
39
41
  }
40
42
  detach() {
41
43
  this.unsubscribe();
42
44
  }
43
45
  onLine(line) {
44
- let outer;
45
- try {
46
- outer = JSON.parse(line);
47
- }
48
- catch {
49
- return;
50
- }
51
- if (outer.peer !== this.remotePeerId || !outer.ct)
46
+ const outer = parseIncomingRoute(line, this.host, this.ownerId);
47
+ if (!outer)
52
48
  return;
53
49
  try {
54
- const plaintext = Buffer.from(outer.ct, "base64").toString("utf8");
55
- this.onMessage(decodeClientFrameV2(plaintext));
50
+ const frame = decodeClientFrameV2(Buffer.from(outer.ct, "base64").toString("utf8"));
51
+ const expectedPurpose = frame.type === "pair_request" ? "pairing" : "session";
52
+ if (outer.purpose !== expectedPurpose)
53
+ return;
54
+ this.onMessage(frame);
56
55
  }
57
56
  catch {
58
- // Strict v2 boundary. A parseable legacy/invalid request receives an upgrade
59
- // error; malformed bytes without an id cannot be safely targeted.
60
- try {
61
- const raw = JSON.parse(Buffer.from(outer.ct, "base64").toString("utf8"));
62
- const id = typeof raw.id === "string" ? raw.id : undefined;
63
- const channelId = typeof raw.channel_id === "string" ? raw.channel_id : undefined;
64
- if (id) {
65
- this.sendV2({
66
- protocol_version: 2,
67
- type: "protocol_error",
68
- ...(channelId ? { target_channel_id: channelId } : {}),
69
- in_reply_to: id,
70
- code: "protocol_upgrade_required",
71
- message: "Protocol v2 is required",
72
- });
73
- }
74
- }
75
- catch {
76
- // Ignore malformed outer payloads.
77
- }
57
+ this.sendUpgradeRequired(outer.ct);
78
58
  }
79
59
  }
80
- }
81
- /** @deprecated Protocol v1 test helper. Production uses V2PeerChannel. */
82
- export class PlainPeerChannel {
83
- relay;
84
- remotePeerId;
85
- onMessage;
86
- _unsubscribe;
87
- constructor(relay, remotePeerId,
88
- /**
89
- * This Pi's room id. Currently NOT injected in the outer envelope
90
- * (defensive — relay/app not yet ready). Kept in the constructor for
91
- * forward-compat so callers don't need to change again when we re-enable.
92
- */
93
- myRoomId, onMessage,
94
- /** Called when this specific peer connection is considered lost. */
95
- _onDisconnect) {
96
- this.relay = relay;
97
- this.remotePeerId = remotePeerId;
98
- this.onMessage = onMessage;
99
- const listener = (line) => this._onLine(line);
100
- relay.on("message", listener);
101
- this._unsubscribe = () => relay.off("message", listener);
102
- void _onDisconnect;
103
- void myRoomId; // intentionally unused — see send() comment
104
- }
105
- // ── PeerChannel interface ──────────────────────────────────────────────────
106
- /** Authenticated Owner peer id used as a server-derived sender reference. */
107
- getPeerId() {
108
- return this.remotePeerId;
109
- }
110
- send(msg) {
111
- const ct = Buffer.from(JSON.stringify(msg)).toString("base64");
112
- // NOTE: `room` removed from the outer envelope until relay (W1.A) + app
113
- // (W1.C) accept the field. Multi-Pi multiplexing already works via
114
- // `room_id`/`room_meta` in the WS-level `hello` — outer routing stays by
115
- // `peer` alone. Re-add the field once downstream is ready.
116
- const outer = { peer: this.remotePeerId, ct };
117
- // Best-effort delivery. The relay WS can be mid-reconnect (idle/NAT drop, or
118
- // a session_new/session-replacement teardown) when we push a server→app frame
119
- // — notably the action_ok/action_error ack a handler emits right after
120
- // newSession. `relay.send` throws "relay: not connected" in that window; since
121
- // this runs inside an async SDK event callback, letting it propagate becomes an
122
- // uncaughtException that kills the whole pi process. The relay auto-reconnects
123
- // and the app re-syncs via session_sync, so a dropped frame is recoverable — a
124
- // crash is not. Mirrors RelayClient.sendControl's no-op-when-closed policy.
60
+ sendUpgradeRequired(ct) {
125
61
  try {
126
- this.relay.send(JSON.stringify(outer));
62
+ const raw = JSON.parse(Buffer.from(ct, "base64").toString("utf8"));
63
+ const id = typeof raw.id === "string" ? raw.id : undefined;
64
+ const channelId = typeof raw.channel_id === "string" ? raw.channel_id : undefined;
65
+ if (!id)
66
+ return;
67
+ this.sendV2({
68
+ protocol_version: 2,
69
+ type: "protocol_error",
70
+ ...(channelId ? { target_channel_id: channelId } : {}),
71
+ in_reply_to: id,
72
+ code: "protocol_upgrade_required",
73
+ message: "Protocol v2 is required",
74
+ });
127
75
  }
128
76
  catch {
129
- /* relay down — drop this frame; reconnect + session_sync will recover */
77
+ // Invalid bytes without a request id are not targetable.
130
78
  }
131
79
  }
132
- /** Detaches from relay (does not close the relay itself). */
133
- detach() {
134
- this._unsubscribe();
80
+ }
81
+ export function parseIncomingRoute(line, host, ownerId) {
82
+ let route;
83
+ try {
84
+ route = JSON.parse(line);
135
85
  }
136
- // ── Incoming line from relay ────────────────────────────────────────────────
137
- _onLine(line) {
138
- let outer;
139
- try {
140
- outer = JSON.parse(line);
141
- }
142
- catch {
143
- return; // malformed line
144
- }
145
- if (outer.peer !== this.remotePeerId)
146
- return;
147
- if (!outer.ct)
148
- return;
149
- let plaintext;
150
- try {
151
- plaintext = Buffer.from(outer.ct, "base64").toString("utf8");
152
- }
153
- catch {
154
- return;
155
- }
156
- let msg;
157
- try {
158
- msg = JSON.parse(plaintext);
159
- }
160
- catch {
161
- return;
162
- }
163
- if (!msg ||
164
- typeof msg !== "object" ||
165
- typeof msg.type !== "string") {
166
- return;
167
- }
168
- this.onMessage(msg);
86
+ catch {
87
+ return null;
169
88
  }
89
+ if (route.type !== "route" ||
90
+ (route.purpose !== "pairing" && route.purpose !== "session") ||
91
+ typeof route.ct !== "string" ||
92
+ route.device_id !== host.deviceId ||
93
+ route.endpoint_id !== host.endpointId ||
94
+ route.runtime_instance_id !== host.runtimeInstanceId ||
95
+ typeof route.source_owner_id !== "string" ||
96
+ route.target_owner_id !== undefined) {
97
+ return null;
98
+ }
99
+ if (ownerId !== undefined && route.source_owner_id !== ownerId)
100
+ return null;
101
+ return route;
102
+ }
103
+ export function sendRoute(relay, host, ownerId, purpose, ct) {
104
+ relay.send(JSON.stringify({
105
+ type: "route",
106
+ purpose,
107
+ device_id: host.deviceId,
108
+ endpoint_id: host.endpointId,
109
+ runtime_instance_id: host.runtimeInstanceId,
110
+ target_owner_id: ownerId,
111
+ ct,
112
+ }));
170
113
  }
171
114
  //# sourceMappingURL=peer_channel.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"peer_channel.js","sourceRoot":"","sources":["../../src/transport/peer_channel.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"peer_channel.js","sourceRoot":"","sources":["../../src/transport/peer_channel.ts"],"names":[],"mappings":"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"}