@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
package/docs/daemon.md CHANGED
@@ -1,64 +1,31 @@
1
- # Daemon mode — troubleshooting
1
+ # Daemon mode — operations and troubleshooting
2
2
 
3
- Companion to the README's [Daemon mode](../README.md#daemon-mode) section.
4
- Each scenario starts with the symptom you'd actually observe, followed by
5
- likely causes and how to fix.
3
+ Daemon mode is an explicit v2-registry opt-in for keeping selected Pi endpoints alive under one user-level supervisor. It is not part of ordinary interactive pairing.
6
4
 
7
- ---
8
-
9
- ## 1. `remote-pi install` fails
5
+ Each registration has an opaque daemon/endpoint identifier, canonical cwd, display name, creation time, and persisted desired lifecycle:
10
6
 
11
- ### "supervisor script not found"
12
-
13
- ```
14
- [remote-pi] install failed: Error: supervisor script not found at
15
- /Users/x/dist/bin/supervisord.js. Run `pnpm build` (dev) or
16
- `npm install -g @yefengr/remote-pi` (prod) first.
7
+ ```text
8
+ running | stopped
17
9
  ```
18
10
 
19
- You're running `remote-pi install` from a dev clone where `dist/` doesn't
20
- exist yet, or from a partial install.
21
-
22
- ```bash
23
- # Dev clone:
24
- cd pi-extension && pnpm build
25
-
26
- # Production install:
27
- npm install -g @yefengr/remote-pi # or pnpm install -g @yefengr/remote-pi
28
- which pi-supervisord # confirm bin is on PATH
29
- remote-pi install
30
- ```
11
+ A daemon process is a runtime of that stable endpoint. Restarting the daemon creates a new runtime identity without changing the endpoint card selected by the PWA.
31
12
 
32
- ### "launchctl: bootstrap … already running"
13
+ ---
33
14
 
34
- A previous install left a stale entry. The fix is built into `install` —
35
- re-run it and the supervisor unloads the old entry before bootstrapping
36
- the new one. If it still fails:
15
+ ## Install the supervisor once per computer
37
16
 
38
17
  ```bash
39
- launchctl bootout gui/$(id -u) ~/Library/LaunchAgents/dev.remotepi.supervisord.plist
40
- launchctl unload ~/Library/LaunchAgents/dev.remotepi.supervisord.plist 2>/dev/null
41
- rm ~/Library/LaunchAgents/dev.remotepi.supervisord.plist
18
+ npm install -g @yefengr/remote-pi
42
19
  remote-pi install
43
20
  ```
44
21
 
45
- ### "systemctl --user … No such file or directory"
46
-
47
- Linux without a logged-in graphical session (headless server). On most
48
- distros `systemctl --user` requires `loginctl enable-linger <user>` so
49
- the unit survives logout:
50
-
51
- ```bash
52
- loginctl enable-linger $USER
53
- systemctl --user daemon-reload
54
- remote-pi install
55
- ```
22
+ `install` configures `launchd` on macOS or `systemd --user` on Linux, links `remote-pi` and `pi-supervisord`, and starts the service. The service reads the v2 registry from `~/.pi/remote/daemons.json`.
56
23
 
57
- ---
24
+ The supervisor launches Pi in RPC mode without passing an extra extension argument. Pi settings are the only source for extension loading, model selection, providers, and tool permissions. Correct Pi settings before registering an unattended daemon.
58
25
 
59
- ## 2. Supervisor doesn't start at login
26
+ ### Service does not start at login
60
27
 
61
- ### Check the service status
28
+ Check the service first:
62
29
 
63
30
  ```bash
64
31
  # Linux
@@ -70,220 +37,137 @@ launchctl list | grep remotepi
70
37
  tail -100 ~/.pi/remote/supervisord.log
71
38
  ```
72
39
 
73
- ### Common failures
74
-
75
- - **`pi: command not found`** in the log — Pi's binary isn't on the
76
- PATH that the unit inherited. `remote-pi install` captures
77
- `process.env.PATH` at install time; if you installed Pi *after*
78
- running install, re-run `remote-pi install` to refresh.
79
- - **`Cannot find module …`** — the path baked into the unit doesn't
80
- match where `dist/bin/supervisord.js` actually lives. Happens if you
81
- uninstalled then reinstalled the package to a different location.
82
- Fix: `remote-pi uninstall && remote-pi install`.
83
- - **Permission denied on UDS** — `~/.pi/remote/` exists with wrong
84
- perms (rare; only happens if you ran `pi` as `sudo` once). Delete
85
- the dir and let it re-create: `rm -rf ~/.pi/remote && remote-pi install`.
86
-
87
- ### Run the supervisor in the foreground for debugging
88
-
89
- Bypass systemd/launchd and run it directly so you can see startup
90
- errors live:
40
+ Common causes:
91
41
 
92
- ```bash
93
- pi-supervisord
94
- # or: node /path/to/remote-pi/dist/bin/supervisord.js
95
- ```
42
+ - **`pi: command not found`** — reinstall the service after fixing the PATH seen by the user service.
43
+ - **Missing compiled package files** — build a development clone or reinstall the global package, then run `remote-pi install` again.
44
+ - **Linux user service unavailable after logout** — enable lingering where required by the distribution: `loginctl enable-linger $USER`.
96
45
 
97
- Ctrl-C to stop. If that works but the service doesn't, the problem is
98
- in the unit/plist environment (PATH, HOME) — re-run `remote-pi install`.
46
+ For foreground diagnosis, run `pi-supervisord` in a terminal and stop it with Ctrl-C when done.
99
47
 
100
48
  ---
101
49
 
102
- ## 3. A specific daemon stays `crashed`
103
-
104
- `remote-pi daemon status` shows one row with `state=crashed` and a
105
- restart count near 4 (the supervisor gives up after exponential
106
- backoff: 1s, 5s, 30s, 5min).
107
-
108
- ### Step 1 — read the daemon's stderr
50
+ ## Register and control daemons
109
51
 
110
- The supervisor forwards each daemon's stderr with a `[<cwd>]` prefix:
52
+ Registering is explicit and starts with desired state `running`:
111
53
 
112
54
  ```bash
113
- # Linux
114
- journalctl --user -u remote-pi-supervisord -f | grep '\[/Users/x/Movies\]'
115
-
116
- # macOS
117
- tail -f ~/.pi/remote/supervisord.log | grep '\[/Users/x/Movies\]'
55
+ remote-pi create ~/Projects/backend
56
+ remote-pi daemons
57
+ remote-pi daemon status
118
58
  ```
119
59
 
120
- ### Step 2 — run that daemon manually
121
-
122
- Reproduce the failure with full visibility:
60
+ The supervisor starts the registration immediately when it is online. At a future supervisor start, it restores only registrations whose desired state remains `running`. A stopped registration remains stopped.
123
61
 
124
62
  ```bash
125
- cd /Users/x/Movies
126
- REMOTE_PI_DAEMON=1 pi --mode rpc -e $(npm root -g)/remote-pi/dist/index.js
63
+ remote-pi daemon start <daemon-id>
64
+ remote-pi daemon stop <daemon-id>
65
+ remote-pi daemon restart <daemon-id>
66
+ remote-pi daemon start # every registration
67
+ remote-pi daemon stop # every registration
68
+ remote-pi daemon restart # every registration
69
+ remote-pi remove <daemon-id>
70
+ remote-pi remove-cwd ~/Projects/backend
127
71
  ```
128
72
 
129
- Common reasons a daemon won't start:
130
-
131
- - **Local config missing.** `cd` into the daemon's folder and check
132
- `.pi/remote-pi/config.json` exists with `auto_start_relay: true`.
133
- Recreate via `remote-pi create <cwd>` (it provisions a default config
134
- when missing).
135
- - **Pi extension config drift.** Pi's own settings (model, API keys)
136
- reset → daemon fails to authenticate to the provider. Run
137
- `cd <cwd> && pi` interactively to fix.
138
- - **Port/UDS collision.** Another Pi process is already running in
139
- that cwd. The cwd-lock should reject the second one, but stale UDS
140
- sockets sometimes linger; check `lsof ~/.pi/remote/locks/<roomId>.sock`.
73
+ `remove-cwd <cwd>` is idempotent: it succeeds whether or not that cwd currently has a registration. It is safe for external worktree cleanup integrations.
141
74
 
142
- ### Step 3 — force a re-spawn
143
-
144
- After fixing the underlying problem, kick the supervisor:
145
-
146
- ```bash
147
- remote-pi daemon restart # bounces every daemon
148
- ```
75
+ The browser PWA may show multiple endpoints on the same computer. Pairing is independent for every computer, and revoking a pairing on one computer does not alter another computer's local pairing records.
149
76
 
150
77
  ---
151
78
 
152
- ## 4. `daemon send` says "daemon not running"
79
+ ## Read status as independent dimensions
153
80
 
154
- The supervisor has the registry entry but no live child for that id.
155
- Most common cause: the daemon never started OR it crashed past the
156
- retry budget.
81
+ Do not infer health from a single summary label. `remote-pi daemon status` reports:
157
82
 
158
- ```bash
159
- remote-pi daemon status # is state running?
160
- remote-pi daemon start # spawn any that aren't running
161
- # Then retry send.
162
- ```
83
+ | Field | Interpretation |
84
+ |---|---|
85
+ | registration | The persisted registration is present; a missing cwd is marked missing |
86
+ | desired | Persistent operator intent: `running` or `stopped` |
87
+ | process | OS child lifecycle: absent, spawning, running, or exited |
88
+ | runtime | RPC readiness: pending, ready, or failed |
89
+ | relay | Disconnected, connecting, connected, or reconnecting |
90
+ | health | Derived stopped, starting, healthy, degraded, failed, or blocked state |
163
91
 
164
- If `daemon start` shows `started=0, already_running=N`, the supervisor
165
- isn't actually spawning. Possible reasons:
166
- - Registry empty: `remote-pi daemons` to verify.
167
- - Child crashes faster than the status check: `daemon status` immediately
168
- after start may still show `running` for a few seconds before the
169
- exit event marks it crashed. Re-check 2-3 seconds later.
92
+ A runtime can be ready while the Relay reconnects. That is a **degraded** state, not a reason to restart Pi. The runtime remains available locally and reconnects through its normal transport path.
170
93
 
171
- ---
94
+ A deterministic bad configuration, unsupported startup condition, or exhausted retry budget becomes **blocked**. Read `last_error_code`, `last_error_message`, and `startup_stage`, correct the cause, then explicitly start or restart the daemon. The supervisor does not loop forever on a blocked failure.
172
95
 
173
- ## 5. Browser PWA doesn't connect to a daemon
96
+ ---
174
97
 
175
- The daemon is up but the browser PWA doesn't see it.
98
+ ## Missing and moved working directories
176
99
 
177
- ### Confirm the daemon is paired
100
+ The registry records the canonical cwd that existed at registration time. A daemon send to a missing cwd is denied immediately. The supervisor then reconciles stale registrations after bounded confirmation: it stops any child, removes the registration, and prevents later restoration.
178
101
 
179
- `pair_request` must have happened **before** the folder became a daemon
180
- (daemons don't show QRs themselves):
102
+ If a project moved, register its new canonical cwd intentionally rather than editing the registry by hand:
181
103
 
182
104
  ```bash
183
- cd <daemon-cwd>
184
- pi
185
- > /remote-pi devices # confirm the device is listed
186
- > /remote-pi stop # stop interactive session — daemon takes over
187
- remote-pi daemon restart
105
+ remote-pi create /new/path/to/project
106
+ remote-pi remove-cwd /old/path/to/project
188
107
  ```
189
108
 
190
- ### Confirm the relay URL matches
109
+ A corrupted or pre-v2 registry is an operator-visible error. It is never treated as an empty registry, because doing so could overwrite registrations. Replace the registry only after inspecting and backing up its contents.
191
110
 
192
- The daemon uses the cwd's local config (`<cwd>/.pi/remote-pi/config.json`
193
- agent_name + `~/.pi/remote/config.json` relay). Verify with:
111
+ ---
194
112
 
195
- ```bash
196
- cd <daemon-cwd>
197
- pi
198
- > /remote-pi status
199
- ```
113
+ ## Scheduled prompts
114
+
115
+ Cron schedules prompt delivery; it never starts a daemon. A fire is accepted only when all of these are true:
200
116
 
201
- The relay line should match what the browser PWA is connecting to. If
202
- not, update the relay URL and bounce the daemon:
117
+ 1. The registration exists and its cwd is present.
118
+ 2. Desired lifecycle is `running`.
119
+ 3. The RPC runtime is ready.
120
+ 4. The daemon is not busy, unless the job uses `--no-skip-busy`.
203
121
 
204
122
  ```bash
205
- remote-pi set-relay https://relay.example.tld
206
- remote-pi daemon restart
123
+ remote-pi cron add <daemon-id> "0 9 * * 1-5" "Summarize the new PRs" --tz America/Sao_Paulo
124
+ remote-pi cron list
125
+ remote-pi cron run <job-id>
126
+ remote-pi cron disable <job-id>
127
+ remote-pi cron log --tail 20
207
128
  ```
208
129
 
130
+ Schedules closer than 60 seconds are rejected. `--tz Area/City` uses a DST-aware timezone. `--catchup` allows one missed fire after supervisor startup. The cron audit at `~/.pi/remote/cron.jsonl` records every acceptance and skip, including desired-stopped, starting, retrying, failed, blocked, missing, disabled, busy, and rejected outcomes.
131
+
209
132
  ---
210
133
 
211
- ## 6. Registry corrupted / partial
134
+ ## Pairing and Relay diagnosis
212
135
 
213
- Symptom: `remote-pi daemons` errors out or shows nothing despite
214
- having created entries.
136
+ Generate a fresh QR from an interactive endpoint:
215
137
 
216
- ```bash
217
- cat ~/.pi/remote/daemons.json # inspect
138
+ ```text
139
+ /remote-pi pair
140
+ /remote-pi devices
141
+ /remote-pi revoke <shortid>
218
142
  ```
219
143
 
220
- The file should be:
144
+ The QR identifies the current endpoint and runtime. In the PWA, check that the expected device and endpoint card are selected. If a daemon was restarted, select its current runtime state and allow the endpoint to reconnect; a Relay reconnect should report degraded health rather than causing a Pi restart.
221
145
 
222
- ```json
223
- {
224
- "daemons": [
225
- { "cwd": "/Users/x/Movies" },
226
- { "cwd": "/Users/x/Projects/backend" }
227
- ]
228
- }
229
- ```
230
-
231
- Fix manually if needed (it's a JSON list of `{cwd}` entries), or wipe
232
- and re-create:
146
+ Confirm both sides use the same Relay URL:
233
147
 
234
- ```bash
235
- rm ~/.pi/remote/daemons.json
236
- remote-pi create ~/Movies --name "Video Editor"
237
- remote-pi create ~/Projects/backend --name "Backend"
238
- remote-pi daemon restart
148
+ ```text
149
+ /remote-pi config
150
+ /remote-pi set-relay https://relay.example.com
239
151
  ```
240
152
 
153
+ After correcting a Relay URL, restart only the affected endpoint if it does not reconnect on its own.
154
+
241
155
  ---
242
156
 
243
- ## 7. Uninstall cleanly + re-install from scratch
157
+ ## Logs and reset
244
158
 
245
- When you suspect everything is misconfigured:
159
+ | Platform | Command |
160
+ |---|---|
161
+ | Linux | `journalctl --user -u remote-pi-supervisord -f` |
162
+ | macOS | `tail -f ~/.pi/remote/supervisord.log` |
163
+
164
+ For a complete service reset:
246
165
 
247
166
  ```bash
248
- remote-pi uninstall # removes service, keeps registry
249
- rm -rf ~/.pi/remote # nukes registry + paired devices + keys
250
- npm uninstall -g remote-pi
167
+ remote-pi uninstall
168
+ npm uninstall -g @yefengr/remote-pi
251
169
  npm install -g @yefengr/remote-pi
252
170
  remote-pi install
253
- # Then re-pair + re-create daemons from scratch.
254
- ```
255
-
256
- This is the "nuke everything" path. After this, the only state left is
257
- each cwd's `<cwd>/.pi/remote-pi/config.json` — which you can either
258
- keep (re-create restores the daemon) or delete (full reset).
259
-
260
- ---
261
-
262
- ## 8. Diagnostic commands cheat-sheet
263
-
264
- ```bash
265
- # Where is the supervisor's UDS?
266
- ls -la ~/.pi/remote/supervisor.sock
267
-
268
- # Talk to the supervisor manually (raw JSONL):
269
- echo '{"op":"list"}' | nc -U ~/.pi/remote/supervisor.sock
270
-
271
- # Where are the daemon configs?
272
- find ~/Projects -name "config.json" -path "*/.pi/remote-pi/*" 2>/dev/null
273
-
274
- # Where are the cwd locks?
275
- ls ~/.pi/remote/locks/
276
-
277
- # Where are the paired devices?
278
- cat ~/.pi/remote/peers.json
279
-
280
- # What Pi binary is the supervisor about to spawn?
281
- remote-pi install --dry-run # (not implemented; check ~/Library/LaunchAgents or systemd unit manually)
282
-
283
- # Quick liveness check
284
- remote-pi daemon status
285
171
  ```
286
172
 
287
- If after walking the list you're still stuck, file an issue with the
288
- output of `remote-pi daemon status`, the recent supervisor log, and
289
- the contents of `~/.pi/remote/daemons.json`.
173
+ Uninstalling the service preserves registrations. Remove individual registrations with `remote-pi remove` or `remote-pi remove-cwd`; do not delete registry state unless a deliberate full reset is required.
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "@yefengr/remote-pi",
3
- "version": "0.7.4",
3
+ "version": "0.7.6",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
7
- "description": "Browser PWA remote control and local agent mesh for the Pi coding agent. Pair a browser profile via QR over a relay, watch tool calls in real time, run multi-Pi sessions over a local Unix Domain Socket broker, and let agents talk to each other through structured request/reply.",
7
+ "description": "Browser PWA remote control for Pi coding agent endpoints over a Relay.",
8
8
  "type": "module",
9
9
  "main": "dist/index.js",
10
10
  "types": "dist/index.d.ts",
@@ -12,6 +12,15 @@
12
12
  "remote-pi": "dist/index.js",
13
13
  "pi-supervisord": "dist/bin/supervisord.js"
14
14
  },
15
+ "scripts": {
16
+ "build": "tsc",
17
+ "typecheck": "tsc --noEmit",
18
+ "dev": "tsx src/index.ts",
19
+ "test": "vitest run",
20
+ "verify": "pnpm typecheck && pnpm test && pnpm build",
21
+ "prepublishOnly": "pnpm verify",
22
+ "publish:npm": "bash ./publish-npm.sh"
23
+ },
15
24
  "keywords": [
16
25
  "pi",
17
26
  "pi-package",
@@ -21,10 +30,7 @@
21
30
  "browser",
22
31
  "pwa",
23
32
  "coding-agent",
24
- "agent-mesh",
25
- "agent-network",
26
- "uds",
27
- "broker",
33
+ "endpoint",
28
34
  "qr-pairing",
29
35
  "websocket"
30
36
  ],
@@ -47,7 +53,6 @@
47
53
  },
48
54
  "files": [
49
55
  "dist",
50
- "skills",
51
56
  "service-templates",
52
57
  "docs",
53
58
  "README.md",
@@ -56,6 +61,14 @@
56
61
  "engines": {
57
62
  "node": ">=20.0.0"
58
63
  },
64
+ "pnpm": {
65
+ "onlyBuiltDependencies": [
66
+ "@google/genai",
67
+ "esbuild",
68
+ "koffi",
69
+ "protobufjs"
70
+ ]
71
+ },
59
72
  "devDependencies": {
60
73
  "@types/node": "^25.8.0",
61
74
  "@types/ws": "^8.18.1",
@@ -67,7 +80,6 @@
67
80
  "dependencies": {
68
81
  "@earendil-works/pi-coding-agent": "^0.79.10",
69
82
  "@earendil-works/pi-tui": "^0.79.10",
70
- "@modelcontextprotocol/sdk": "^1.29.0",
71
83
  "@napi-rs/keyring": "^1.3.0",
72
84
  "@noble/ed25519": "^3.1.0",
73
85
  "croner": "^10.0.1",
@@ -75,13 +87,5 @@
75
87
  "typebox": "^1.1.38",
76
88
  "ws": "^8.21.0",
77
89
  "zod": "^4.4.3"
78
- },
79
- "scripts": {
80
- "build": "tsc",
81
- "typecheck": "tsc --noEmit",
82
- "dev": "tsx src/index.ts",
83
- "test": "vitest run",
84
- "verify": "pnpm typecheck && pnpm test && pnpm build",
85
- "publish:npm": "pnpm verify && pnpm publish --access public"
86
90
  }
87
- }
91
+ }
@@ -1,24 +0,0 @@
1
- /**
2
- * Stable 8-character hex id for a daemon, derived from the cwd it manages.
3
- *
4
- * Derivation: `sha256(realpath(cwd))` truncated to 8 hex chars (32 bits ≈
5
- * 4 billion). Collision risk is negligible at fleet sizes a single user
6
- * will ever have (<1000 daemons), and 8 hex characters are short enough
7
- * to type on the CLI (`/remote-pi send a1b2c3d4 "..."`).
8
- *
9
- * Same scheme as `roomIdForCwd` in `src/rooms.ts` — but we use hex
10
- * instead of base64url so the id has no `_`/`-` (cleaner double-click
11
- * selection in terminals).
12
- *
13
- * Symlinks resolve to a single canonical id via `realpath`, so
14
- * `/Users/x/Movies` and `/Users/x/link-to-Movies` map to the same daemon.
15
- * Falls back to the raw path when realpath fails (cwd doesn't exist —
16
- * shouldn't happen in production but covers test sandboxes).
17
- *
18
- * plan/41 audit (2026-06-08): this stays **per-cwd** (no name axis). The
19
- * multiagent-per-folder model (plan/38/41) applies to the App↔Pi room and the
20
- * mesh address; a *supervisor daemon* is **one per cwd** by design — the
21
- * registry keys exactly one entry per cwd (`registry.ts`), so a daemon id never
22
- * needs the name to disambiguate. Decision: leave `daemonIdForCwd` cwd-only.
23
- */
24
- export declare function daemonIdForCwd(cwd: string): string;
package/dist/daemon/id.js DELETED
@@ -1,36 +0,0 @@
1
- import { createHash } from "node:crypto";
2
- import { realpathSync } from "node:fs";
3
- /**
4
- * Stable 8-character hex id for a daemon, derived from the cwd it manages.
5
- *
6
- * Derivation: `sha256(realpath(cwd))` truncated to 8 hex chars (32 bits ≈
7
- * 4 billion). Collision risk is negligible at fleet sizes a single user
8
- * will ever have (<1000 daemons), and 8 hex characters are short enough
9
- * to type on the CLI (`/remote-pi send a1b2c3d4 "..."`).
10
- *
11
- * Same scheme as `roomIdForCwd` in `src/rooms.ts` — but we use hex
12
- * instead of base64url so the id has no `_`/`-` (cleaner double-click
13
- * selection in terminals).
14
- *
15
- * Symlinks resolve to a single canonical id via `realpath`, so
16
- * `/Users/x/Movies` and `/Users/x/link-to-Movies` map to the same daemon.
17
- * Falls back to the raw path when realpath fails (cwd doesn't exist —
18
- * shouldn't happen in production but covers test sandboxes).
19
- *
20
- * plan/41 audit (2026-06-08): this stays **per-cwd** (no name axis). The
21
- * multiagent-per-folder model (plan/38/41) applies to the App↔Pi room and the
22
- * mesh address; a *supervisor daemon* is **one per cwd** by design — the
23
- * registry keys exactly one entry per cwd (`registry.ts`), so a daemon id never
24
- * needs the name to disambiguate. Decision: leave `daemonIdForCwd` cwd-only.
25
- */
26
- export function daemonIdForCwd(cwd) {
27
- let target;
28
- try {
29
- target = realpathSync(cwd);
30
- }
31
- catch {
32
- target = cwd;
33
- }
34
- return createHash("sha256").update(target).digest("hex").slice(0, 8);
35
- }
36
- //# sourceMappingURL=id.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"id.js","sourceRoot":"","sources":["../../src/daemon/id.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAEvC;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,UAAU,cAAc,CAAC,GAAW;IACxC,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,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AACvE,CAAC"}
@@ -1,10 +0,0 @@
1
- import type { AckResult } from "../session/peer.js";
2
- type MeshAckResult = {
3
- content: [{
4
- type: "text";
5
- text: string;
6
- }];
7
- isError?: true;
8
- };
9
- export declare function formatMeshAckResult(to: string, ack: AckResult): MeshAckResult;
10
- export {};
@@ -1,42 +0,0 @@
1
- export function formatMeshAckResult(to, ack) {
2
- switch (ack.status) {
3
- case "received":
4
- return textResult(`Delivered to ${ack.target ?? to}`);
5
- case "busy":
6
- return errorResult(`NOT delivered — "${to}" came back BUSY, which only happens when an ` +
7
- `OUT-OF-DATE broker leader dropped the message (busy was removed in the ` +
8
- `current version). Restart the agent that leads the local broker (the ` +
9
- `oldest Pi/remote-pi process) so it picks up the new build, then resend.`);
10
- case "denied":
11
- return errorResult(formatDenied(to, ack));
12
- case "timeout":
13
- return errorResult(formatTimeout(to, ack));
14
- }
15
- }
16
- function formatDenied(to, ack) {
17
- const errorSuffix = ack.error ? ` (${ack.error})` : "";
18
- if (ack.reason === "not_authorized") {
19
- return `Relay did not authorize delivery to ${to}${errorSuffix}. ` +
20
- `Do not blindly retry; verify authorization first.`;
21
- }
22
- if (ack.reason === "bad_envelope") {
23
- return `Relay rejected the envelope for ${to}${errorSuffix}. ` +
24
- `Do not blindly retry; correct the envelope first.`;
25
- }
26
- return `${to} denied the message`;
27
- }
28
- function formatTimeout(to, ack) {
29
- if (ack.reason === "offline") {
30
- const errorSuffix = ack.error ? ` (${ack.error})` : "";
31
- return `Immediate Relay offline transport error for ${to}${errorSuffix}; ` +
32
- `reported as timeout without waiting for an ACK.`;
33
- }
34
- return `No ACK from ${to} (timeout) — peer may be offline`;
35
- }
36
- function textResult(text) {
37
- return { content: [{ type: "text", text }] };
38
- }
39
- function errorResult(text) {
40
- return { content: [{ type: "text", text }], isError: true };
41
- }
42
- //# sourceMappingURL=mesh_result.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"mesh_result.js","sourceRoot":"","sources":["../../src/mcp/mesh_result.ts"],"names":[],"mappings":"AAOA,MAAM,UAAU,mBAAmB,CAAC,EAAU,EAAE,GAAc;IAC5D,QAAQ,GAAG,CAAC,MAAM,EAAE,CAAC;QACnB,KAAK,UAAU;YACb,OAAO,UAAU,CAAC,gBAAgB,GAAG,CAAC,MAAM,IAAI,EAAE,EAAE,CAAC,CAAC;QACxD,KAAK,MAAM;YACT,OAAO,WAAW,CAChB,oBAAoB,EAAE,+CAA+C;gBACrE,yEAAyE;gBACzE,uEAAuE;gBACvE,yEAAyE,CAC1E,CAAC;QACJ,KAAK,QAAQ;YACX,OAAO,WAAW,CAAC,YAAY,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC,CAAC;QAC5C,KAAK,SAAS;YACZ,OAAO,WAAW,CAAC,aAAa,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC,CAAC;IAC/C,CAAC;AACH,CAAC;AAED,SAAS,YAAY,CAAC,EAAU,EAAE,GAAc;IAC9C,MAAM,WAAW,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;IACvD,IAAI,GAAG,CAAC,MAAM,KAAK,gBAAgB,EAAE,CAAC;QACpC,OAAO,uCAAuC,EAAE,GAAG,WAAW,IAAI;YAChE,mDAAmD,CAAC;IACxD,CAAC;IACD,IAAI,GAAG,CAAC,MAAM,KAAK,cAAc,EAAE,CAAC;QAClC,OAAO,mCAAmC,EAAE,GAAG,WAAW,IAAI;YAC5D,mDAAmD,CAAC;IACxD,CAAC;IACD,OAAO,GAAG,EAAE,qBAAqB,CAAC;AACpC,CAAC;AAED,SAAS,aAAa,CAAC,EAAU,EAAE,GAAc;IAC/C,IAAI,GAAG,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;QAC7B,MAAM,WAAW,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;QACvD,OAAO,+CAA+C,EAAE,GAAG,WAAW,IAAI;YACxE,iDAAiD,CAAC;IACtD,CAAC;IACD,OAAO,eAAe,EAAE,kCAAkC,CAAC;AAC7D,CAAC;AAED,SAAS,UAAU,CAAC,IAAY;IAC9B,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;AAC/C,CAAC;AAED,SAAS,WAAW,CAAC,IAAY;IAC/B,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;AAC9D,CAAC"}
@@ -1,16 +0,0 @@
1
- #!/usr/bin/env node
2
- /**
3
- * MCP server that bridges Claude Code to the remote-pi agent mesh.
4
- *
5
- * Spawned by Claude Code as an MCP server subprocess (stdio).
6
- * Joins the mesh through the shared `MeshNode` abstraction — the SAME
7
- * composition the Pi extension uses — so Claude is a first-class mesh
8
- * participant: it can lead the local UDS broker when no Pi/daemon is up,
9
- * and (as leader) bring up its own cross-PC relay bridge with its own
10
- * Pi-key. As a follower it rides the existing leader's bridge.
11
- *
12
- * Launched by `remote-pi claude` (registers this in Claude's local MCP
13
- * scope). Args: [--cwd <path>] [--name <agentName>] [--no-bridge]
14
- * Env: REMOTE_PI_MCP_CWD, REMOTE_PI_MCP_NAME
15
- */
16
- export {};