@sailorbridge/client 0.2.5 → 0.2.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.
package/README.md CHANGED
@@ -17,6 +17,11 @@ writable and its `bin` directory is on `PATH`. Prefer a user-owned Node install
17
17
  from tools such as nvm/asdf over `sudo npm install -g`. Linux and macOS are the
18
18
  supported targets; Windows packaging support is deferred.
19
19
 
20
+ The host service records the PATH of the shell that installed it, because no
21
+ systemd user unit or launchd agent inherits one. After changing where your tools
22
+ live — an nvm/asdf version switch, a new Homebrew prefix — re-run
23
+ `sailorbridge host service install` so the service picks up the new PATH.
24
+
20
25
  Upgrade an npm-installed client and reload a running managed host daemon in one
21
26
  step:
22
27
 
@@ -80,7 +85,34 @@ sailorbridge login
80
85
  host pairing code, waits for console/mobile approval, writes a 0600 credentials
81
86
  file at `~/.sailorbridge/credentials.json`, and then installs and starts the
82
87
  host service so the console can start workers and agents on this machine without
83
- a second command.
88
+ a second command. A pending pairing is also stored with mode 0600: restarting
89
+ `login` within the 10-minute code lifetime resumes the same code. Transient
90
+ 429/5xx/network failures use capped exponential backoff until that deadline;
91
+ an expired/rejected code or 401/403 fails immediately and tells you to run
92
+ `sailorbridge login` for a new code.
93
+
94
+ Before pairing, `login` asks what the host is for and prints one preflight
95
+ checklist for that answer, so a missing prerequisite surfaces while the user is
96
+ still at the keyboard instead of when their first member fails to start:
97
+
98
+ | Requirement | Dev-pair host | Worker-only host |
99
+ | --- | --- | --- |
100
+ | Node.js >= 20 | required | required |
101
+ | `git` executable | required | not used |
102
+ | tmux | required | not used |
103
+ | `claude` or `codex` CLI, logged in | required (either one) | not used |
104
+
105
+ Pass `--worker-only` (or `SAILORBRIDGE_WORKER_ONLY=1`) to skip the dev-pair
106
+ items; an interactive login asks once, and a non-interactive login checks the
107
+ full dev-pair list. The login preflight checks that git is installed but does
108
+ not inspect the current directory; the repository is named when a team is
109
+ created. Workers advertise `podman`, `git`, `kubectl`,
110
+ `perf` and `bpftrace` as capabilities when present; none are required.
111
+
112
+ A failing item never blocks pairing — the report prints the exact command that
113
+ fixes it. tmux can be installed with consent (the exact command is shown first);
114
+ engine CLIs and their logins are always left to the user, since the credential
115
+ is theirs.
84
116
 
85
117
  Common commands:
86
118
 
@@ -92,7 +124,7 @@ sailorbridge workflow
92
124
  sailorbridge mailbox peek
93
125
  sailorbridge mailbox claim
94
126
  sailorbridge reply --in-reply-to MESSAGE_ID REPLY --body-file ./reply.txt
95
- sailorbridge mailbox ack MESSAGE_ID --lease-token LEASE_TOKEN
127
+ sailorbridge mailbox ack MESSAGE_ID --lease-token-file ./lease-token
96
128
  printf '%s\n' 'hello $USER `date` $(pwd)' | sailorbridge mailbox send --to-agents ab_hand --tag BTW
97
129
  sailorbridge mailbox send --to-roles reviewer --tag PLAN-REVIEW --body-file ./plan.txt
98
130
  sailorbridge mailbox send --to-agents captain --tag REPORT --body-file ./report.txt
@@ -167,7 +199,7 @@ SAILORBRIDGE_CAPTAIN_ID=100
167
199
  SAILORBRIDGE_SESSION=session
168
200
  SAILORBRIDGE_HOST_ID=mac
169
201
  SAILORBRIDGE_HOST_DISPLAY_NAME="Mac"
170
- SAILORBRIDGE_HOST_WORKSPACES=~/project-a:~/project-b
202
+ SAILORBRIDGE_HOST_CONFIG_FILE=~/.sailorbridge/host-config.json
171
203
  SAILORBRIDGE_API_URL=https://www.sailorbridge.com
172
204
  SAILORBRIDGE_CREDENTIALS_FILE=~/.sailorbridge/credentials.json
173
205
  SAILORBRIDGE_WORKER_NAME=dev-1
@@ -188,14 +220,42 @@ the token, captain id, and session. Agent routing uses the separate
188
220
  `SAILORBRIDGE_HOST_ID` and `SAILORBRIDGE_HOST_DISPLAY_NAME` identify the
189
221
  captain-scoped local host for Tier 6 console start-request polling. When omitted,
190
222
  host commands default both values from the OS hostname.
191
- `SAILORBRIDGE_HOST_WORKSPACES` is an explicit opt-in inventory list for host
192
- daemon reporting, split by the platform path delimiter (`:` on Linux/macOS). The
193
- daemon reports only those declared git workspaces, including `remote.origin.url`
194
- and the current branch, so the console can queue an isolated clone from that
195
- origin. It does not scan home directories.
196
-
197
- Every 6 hours the host daemon also runs a scratch sweep over each declared
198
- workspace, reaping `<root>/.agent/tmp/` (a git-ignored scratch directory): it
223
+ A host keeps no list of "its" repositories: a repository belongs to a team, and
224
+ its absolute path on the host is named per team (`create ... --repo-path`, or the
225
+ path field in the console's team wizard). The daemon never scans or reports the
226
+ directories on a host.
227
+
228
+ `SAILORBRIDGE_HOST_CONFIG_FILE` redirects the local host config
229
+ (`~/.sailorbridge/host-config.json` by default) that `host account` writes and
230
+ the daemon reads.
231
+
232
+ ## Running members on more than one engine account
233
+
234
+ By default every member on a host uses that host's own engine directory
235
+ (`CLAUDE_CONFIG_DIR`/`CODEX_HOME`, else `~/.claude`/`~/.codex`) — one account,
236
+ zero configuration. To run members on several logins, register each login
237
+ directory under a name of your choosing and point members at it:
238
+
239
+ ```bash
240
+ sailorbridge host account add C1 ~/.claude-accounts/C1
241
+ sailorbridge host account add C2 ~/.claude-accounts/C2
242
+ sailorbridge host account set alice C1
243
+ sailorbridge host account set bob C2
244
+ sailorbridge host account list
245
+ ```
246
+
247
+ `add` refuses a directory that holds no engine credential, so an account nothing
248
+ could start on is rejected while you are still at the keyboard. A member with no
249
+ pointer keeps using the host default directory. Moving a member is
250
+ `host account set MEMBER ACCOUNT` (or `default` to clear it); it takes effect on
251
+ that member's **next start or relaunch**, because the engine reads its credential
252
+ at boot. Members sharing an account share one physical credential file, so a
253
+ token refresh in any of their sessions is visible to all of them. SailorBridge
254
+ stores only the pointer — the credential never enters product storage, logs, or
255
+ the relay, and the console shows the account NAME read-only.
256
+
257
+ Every 6 hours the host daemon also runs a scratch sweep over each member
258
+ worktree it owns, reaping `<root>/.agent/tmp/` (a git-ignored scratch directory): it
199
259
  deletes git-untracked files older than 7 days, then evicts oldest-first until the
200
260
  directory total is under 512 MiB. It only ever touches untracked files inside that
201
261
  directory, never follows symlinks, and skips (with a log) any workspace whose
@@ -229,7 +289,9 @@ status never completes a SailorBridge task lifecycle.
229
289
 
230
290
  `sailorbridge login` creates a host pairing against
231
291
  `https://www.sailorbridge.com`. The command displays the one-time code and
232
- polls until approval. The stored credential contains a host-scoped relay key
292
+ polls until approval. Deploy-time 429/5xx/network interruptions do not replace
293
+ an unexpired code, and restarting the command resumes its pending pairing.
294
+ The stored credential contains a host-scoped relay key
233
295
  (`key_scope: "host"` plus `host_id`) and is used as a fallback when
234
296
  `SAILORBRIDGE_RELAY_URL` or `SAILORBRIDGE_TOKEN` are not set. Worker data
235
297
  commands reject this host-scoped fallback before any relay request. Raw host
@@ -289,6 +351,12 @@ Claude uses `$CLAUDE_CONFIG_DIR/.credentials.json` when set, otherwise
289
351
  `~/.claude/.credentials.json`.
290
352
  The per-agent sandbox links to that single host auth file; missing engine auth
291
353
  fails fast instead of starting a CLI that will prompt for credentials.
354
+ The host daemon also reads the default Claude subscription OAuth credential
355
+ once per day to list provider model metadata. It sends one `GET /v1/models`
356
+ request with a 10-second timeout and no retry, then reports model ids only to
357
+ the relay. The OAuth token stays in the provider request header and never
358
+ enters relay payloads, logs, errors, or argv. API-key-only and Codex-only hosts
359
+ skip this probe; Codex has no machine-readable subscription catalog source.
292
360
 
293
361
  Worker commands implement both sides of the relay worker contract from
294
362
  `engine/PROTOCOL.md`: register, heartbeat, pull, stream upload, result posting,
@@ -303,9 +371,17 @@ queued and claimable after it surfaces the body-free doorbell. The bound agent's
303
371
  first `mailbox claim` leases them, then the agent completes the required action.
304
372
  Plain claims expose every lease token. `HUMAN` and `MAIL` stay leased so
305
373
  `reply --in-reply-to` can infer the sender and atomically record the reply plus
306
- source ACK; untagged peer mail is shown and handled as `MAIL`.
374
+ source ACK; untagged peer mail is shown and handled as `MAIL`. If the exact
375
+ source cannot be reclaimed, the CLI identifies whether it is missing, settled,
376
+ addressed to another agent, or a transcript-only row and prints the next action.
307
377
  `--no-ack` leaves the source leased. Other direct workflow messages
308
378
  retain their manual ACK or durable-transition settlement.
379
+ ACK lease tokens must stay out of argv: store the surfaced token in a private
380
+ file and use `mailbox ack MESSAGE_ID --lease-token-file PATH`, or pipe exactly
381
+ the token to `mailbox ack MESSAGE_ID --lease-token-file -`. Empty input, a TTY,
382
+ duplicate token sources, and piped input unused by a file path are rejected.
383
+ `--lease-token TOKEN` is deprecated for one release and exists only for
384
+ compatibility.
309
385
 
310
386
  Mailbox send is footgun-free by construction: message bodies are read only from
311
387
  piped stdin or `--body-file`, never from positional argv. Every `--body-file` and
@@ -405,6 +481,19 @@ take effect live through the `reload_context_autopilot` resolve command.
405
481
  Semantics match the engine listener's autopilot (same thresholds, same
406
482
  armed-below/fire-once water-mark).
407
483
 
484
+ Idle pre-save (tmux transport, claude by default): the same loop watches for a
485
+ member that has gone quiet. Once the pane is visibly idle and the newest real
486
+ mailbox activity is older than `idle_presave_min` (console setting; `0`
487
+ disables, empty takes the engine default — claude 50 minutes, codex off) but
488
+ still younger than the engine's prompt-cache TTL, the supervisor re-samples pane
489
+ and activity and then posts one `SAVE-CONTEXT` carrying
490
+ `source=listener-idle-presave`. That checkpoint is **ACK-only**: the handoff is
491
+ written, but nothing clears, resumes, or relaunches — a member that merely sat
492
+ idle keeps its live context. One archive per span of activity, a 30-minute
493
+ cooldown after each attempt, and every unknown (capture failure, busy pane,
494
+ missing or future activity timestamps) is a no-op. Tables are pinned against the
495
+ engine listener by `tooling/e2e/idle-presave-parity.test.ts`.
496
+
408
497
  Default transport selection:
409
498
 
410
499
  | CLI | Default transport | Default command |