agent-relay 12.1.0 → 12.2.0

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
@@ -185,7 +185,7 @@ when available and otherwise tells you to retry without `--background`; a child
185
185
  that already exited is no longer misreported as an unkillable half-started
186
186
  broker.
187
187
 
188
- ## Remote fleet agents
188
+ ## Local and remote fleet agents
189
189
 
190
190
  The `fleet` command group lists and controls agents across all live nodes in
191
191
  the active project workspace:
@@ -208,9 +208,12 @@ agent-relay fleet spawn codex \
208
208
  --node sf-mini \
209
209
  --session-ref <actual-codex-thread-id>
210
210
 
211
- # Omit --node for automatic eligible-node placement.
211
+ # No placement options: use the local broker and this exact working directory.
212
212
  agent-relay fleet spawn codex --name api-worker --task "Review the current diff."
213
213
 
214
+ # Opt into automatic eligible-node placement.
215
+ agent-relay fleet spawn codex --name api-worker --task "Review the current diff." --auto-place
216
+
214
217
  # Provision a fresh E2B node, require the current Relayfile workspace to mount
215
218
  # at /workspace, wait for readiness, then spawn Codex there.
216
219
  agent-relay fleet spawn codex \
@@ -219,6 +222,9 @@ agent-relay fleet spawn codex \
219
222
  --name e2b-worker \
220
223
  --task "Review the current workspace and wait for follow-up."
221
224
 
225
+ # A uniquely placed sandbox worker can be attached without node or route flags.
226
+ agent-relay node agent attach e2b-worker --mode drive
227
+
222
228
  agent-relay message dm send api-worker "Detailed task instructions"
223
229
  # wait is the default: it queues for the recipient's next safe idle boundary and
224
230
  # can remain unread while that recipient is busy. steer requests immediate
@@ -235,11 +241,29 @@ set `RELAY_AGENT_TOKEN` to the token returned by
235
241
  `agent-relay agent register <lead-name>`. `fleet spawn --sandbox` needs a Cloud
236
242
  login (`agent-relay cloud login`) but does not need an agent token: when one is
237
243
  absent, it creates and removes a short-lived launcher identity automatically.
244
+
245
+ Without placement options, `fleet spawn` connects to the local project's broker
246
+ and passes the caller's exact directory, including a nested package, to the
247
+ worker. Start the local broker with `agent-relay node up` if it is not running;
248
+ a local connection failure never falls back to remote placement. `--cwd` selects
249
+ a different local directory on this path. Model and channel options stay local.
250
+ `--auto-place`, `--node`, and `--sandbox` select remote placement explicitly.
251
+ Legacy invocations with an explicit `--workspace-key`/`--wk`, `--token`,
252
+ `--base-url`, or `--persona` retain automatic fleet placement when no node or
253
+ sandbox is selected. Ambient credentials and persisted Cloud routing do not
254
+ change the local default. Workforce reporting metadata requires remote placement.
238
255
  Automatic placement and release need only the workspace key.
239
256
 
240
257
  The sandbox path provisions a fresh hosted instance and makes the Relayfile
241
- mount mandatory by default, so the spawned worker starts in `/workspace` and
242
- sees the same synced Relayfile workspace. Use `--sandbox-provider daytona` or
258
+ mount mandatory by default. Inside a GitHub checkout, Relay infers the Git root,
259
+ repository identity, exact `HEAD`, and caller-relative directory. Cloud uses the
260
+ pinned workspace's connected GitHub credential to seed that revision into
261
+ Relayfile, and the worker starts in the decoded source tree under
262
+ `/workspace/github/repos/<owner>/<repo>/contents`. The long-running Relayfile
263
+ daemon keeps the mounted source tree synchronized with the workspace while
264
+ GitHub push events update the workspace's repository source. Use `--checkout`
265
+ when a task needs a separate static Git clone; that mode keeps the live
266
+ Relayfile mirror available separately. Use `--sandbox-provider daytona` or
243
267
  `--sandbox-provider e2b` to require an operator-enabled provider; omit the flag
244
268
  to let Cloud's sandbox router choose. Pass `--no-sandbox-relayfile` only when a
245
269
  deliberately bare sandbox is desired. If provisioning times out or the spawn
@@ -253,10 +277,115 @@ provisioning ends with an unknown outcome, rerun the command with the warning's
253
277
  `--sandbox-id` to replay the same Cloud identity instead of adopting another
254
278
  fleet node.
255
279
 
256
- Large workspaces should select only the live subtree an agent needs. Pass one
257
- or more explicit directory roots after `--sandbox-relayfile-path`; Cloud
258
- validates the `/path/**` form and materializes those roots before the agent
259
- starts:
280
+ The live source profile includes tracked dotfiles, lockfiles, generated and
281
+ binary files, large files within Relayfile's import limit, symlinks, and
282
+ executable permissions. Relayfile never places `.git` in this tree. If a
283
+ repository entry cannot be represented safely, spawn fails with the entry and
284
+ corrective action instead of reporting a partial working tree.
285
+
286
+ Both live and checkout modes require a clean working tree whose exact `HEAD` is
287
+ reachable from a configured GitHub remote. This prevents a remote worker from
288
+ silently starting at a different revision. Commit and push local work before
289
+ retrying when Relay reports dirty files or an unreachable commit.
290
+
291
+ With `--checkout`, sandbox provisioning also clones the attested `HEAD` under
292
+ `/srv/agent-workforce/<repo>`. The checkout must have no tracked changes or
293
+ untracked source files, and the exact commit must be reachable from an origin
294
+ remote. Relay's generated `.agentworkforce/relay/workspace-key.json`,
295
+ `connection.json`, and `runtime.json` metadata are permitted. Dirty checkouts and
296
+ commits known to be ahead of their origin upstream fail locally. Detached commits
297
+ must appear in an origin remote-tracking branch, and Cloud independently fetches
298
+ and verifies the exact SHA before dispatch. An unreachable commit produces a
299
+ push-and-retry error. The temporary isolated
300
+ Relaycast credential stays in the machine store under
301
+ `~/.agentworkforce/relay`; the project file stores only a non-secret reference.
302
+
303
+ `node agent attach <name>` automatically routes to the unique live fleet node
304
+ advertising that worker. If more than one live node advertises the name, the
305
+ command refuses to guess; pass `--node <node>` explicitly. Supplying
306
+ `--broker-url`, `--api-key`, or `--state-dir`, or setting a nonblank
307
+ `RELAY_BROKER_URL` or `RELAY_BROKER_API_KEY`, keeps attach local and bypasses
308
+ automatic Fleet routing. `node agent message flush|hold|auto <name>` uses the
309
+ same unique-node lookup when no local broker selection is supplied. Fleet list and
310
+ release commands reuse the persisted project route; if that remote session is
311
+ unavailable, the command reports the routing failure instead of selecting a
312
+ same-named local worker.
313
+
314
+ From a clean repository already pinned to a Relay workspace, the ordinary live
315
+ path is:
316
+
317
+ ```bash
318
+ agent-relay fleet spawn codex \
319
+ --name cloud-zero-config \
320
+ --task "Inspect this repository and report its current commit" \
321
+ --sandbox
322
+ agent-relay node agent attach cloud-zero-config --mode drive
323
+ agent-relay fleet agent list
324
+ agent-relay fleet release cloud-zero-config
325
+ ```
326
+
327
+ Invoking the live command from `packages/web` starts the worker at
328
+ `/workspace/github/repos/<owner>/<repo>/contents/packages/web`. The repository
329
+ source metadata is available beside `contents` under `.relayfile`, `.skills`
330
+ is mounted from the same workspace, and no `.git` directory is written into the
331
+ Relayfile mirror.
332
+
333
+ For a static Git checkout, opt in explicitly:
334
+
335
+ ```bash
336
+ agent-relay fleet spawn codex \
337
+ --name cloud-checkout \
338
+ --task "Inspect this repository and report its current commit" \
339
+ --sandbox \
340
+ --checkout
341
+ ```
342
+
343
+ In checkout mode, invoking spawn from `packages/web` places the worker in that
344
+ same relative directory in the remote clone. In both modes, private repositories
345
+ use the pinned workspace's connected GitHub access; a repository-access error
346
+ means that connection must be granted access to the repository. No GitHub token
347
+ or workspace key needs to be copied into the task, mount, or checkout.
348
+
349
+ With `--checkout`, the Git checkout and Relayfile mirror are separate trees. In
350
+ the ordinary live mode, source files are decoded from Relayfile records without
351
+ placing `.git` in the mirror. Workspace `.skills` are exposed through the agent
352
+ CLIs' usual skill directories, and the worker's task context identifies the
353
+ mirror and exact source revision.
354
+
355
+ Detaching leaves the worker running. Only one drive session can own a worker
356
+ at a time; detach the current driver before driving it in another shell, or
357
+ use `--mode view` to observe. Releasing a worker does not delete its sandbox.
358
+ To resume its retained sandbox, repeat spawn with the reported
359
+ `--sandbox-id <id>`; when using `--checkout`, the retained clone must still have
360
+ the same clean HEAD.
361
+ A failed resume preserves retained work. For a live Relayfile sandbox, reusing
362
+ `--sandbox-id` intentionally re-materializes the exact clean, pushed `HEAD` from
363
+ the current checkout before the provider resumes, so a new commit becomes the
364
+ source tree for that retained sandbox. With `--checkout`, the retained static
365
+ clone remains pinned to its original revision and the current checkout must
366
+ still resolve to that same clean, pushed `HEAD`. Delete an unused sandbox in
367
+ Cloud Fleet to stop future provider usage; monthly accounting reservations
368
+ remain until their normal reset.
369
+
370
+ If the workspace is not pinned yet, use `agent-relay workspace rebind <name>`
371
+ with an existing stored workspace. A missing or mismatched stored route
372
+ credential requires rerunning sandbox provisioning for that workspace.
373
+ `--base-url`, `--workspace-id`, `--node`, provider selection, and the static
374
+ `--checkout` mode remain advanced overrides. For `--cwd`, local repo-relative
375
+ paths are accepted to infer the sandbox repository; absolute remote paths are
376
+ advanced overrides. Outside Git, plain `--sandbox` preserves the existing
377
+ full-workspace Relayfile mount at `/workspace`.
378
+
379
+ Pins created before workspace IDs were recorded are resolved automatically
380
+ through Cloud at spawn time. The key travels in an authenticated POST body,
381
+ never a URL. Nested packages share the repository pin; an existing subproject
382
+ pin or `AGENT_RELAY_PROJECT` remains an explicit workspace override.
383
+
384
+ Large workspaces can add only the other live subtrees an agent needs. Pass one
385
+ or more explicit directory roots after `--sandbox-relayfile-path`; the inferred
386
+ repository, its source metadata, and `.skills` remain mounted automatically.
387
+ Cloud validates the `/path/**` form and materializes those roots before the
388
+ agent starts:
260
389
 
261
390
  ```bash
262
391
  agent-relay fleet spawn claude \
@@ -1,16 +1,25 @@
1
1
  import { type Command } from 'commander';
2
- import { deleteCloudFleetSandbox, ensureCloudFleetSandbox } from '@agent-relay/cloud';
2
+ import { findProjectRoot } from '@agent-relay/config';
3
+ import { deleteCloudFleetSandbox, ensureCloudFleetSandbox, materializeCloudRelayfileRepository, resolveWorkspaceByKey } from '@agent-relay/cloud';
4
+ import { HarnessDriverClient } from '@agent-relay/harness-driver';
3
5
  import { type RelayWorkspaceThinClient } from '@agent-relay/sdk';
4
6
  import { type CoreDependencies } from './core.js';
7
+ import { resolveSandboxRepository } from '../lib/sandbox-repo.js';
5
8
  import { resolveWorkspaceSelection, persistWorkspaceRelaycastTarget, type SdkClientOptions } from '../lib/sdk-client.js';
6
9
  import { type SdkCommandDeps } from '../lib/sdk-command.js';
7
10
  export interface FleetCommandDependencies {
8
11
  core: CoreDependencies;
9
12
  sdk: SdkCommandDeps;
13
+ cwd: () => string;
14
+ connectLocalBroker: (cwd: string) => Promise<HarnessDriverClient>;
10
15
  createFleetWorkspaceClient: (options: SdkClientOptions) => RelayWorkspaceThinClient;
11
16
  resolveWorkspaceSelection: typeof resolveWorkspaceSelection;
17
+ resolveSandboxRepository: typeof resolveSandboxRepository;
18
+ findProjectRoot: typeof findProjectRoot;
19
+ resolveWorkspaceByKey: typeof resolveWorkspaceByKey;
12
20
  persistWorkspaceRelaycastTarget: typeof persistWorkspaceRelaycastTarget;
13
21
  ensureCloudFleetSandbox: typeof ensureCloudFleetSandbox;
22
+ materializeCloudRelayfileRepository: typeof materializeCloudRelayfileRepository;
14
23
  deleteCloudFleetSandbox: typeof deleteCloudFleetSandbox;
15
24
  log: (...args: unknown[]) => void;
16
25
  warn: (...args: unknown[]) => void;
@@ -1 +1 @@
1
- {"version":3,"file":"fleet.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/fleet.ts"],"names":[],"mappings":"AAEA,OAAO,EAAwB,KAAK,OAAO,EAAE,MAAM,WAAW,CAAC;AAC/D,OAAO,EAEL,uBAAuB,EACvB,uBAAuB,EAGxB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EAGL,KAAK,wBAAwB,EAE9B,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EAAgB,KAAK,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAgBhE,OAAO,EAEL,yBAAyB,EACzB,+BAA+B,EAG/B,KAAK,gBAAgB,EACtB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAML,KAAK,cAAc,EACpB,MAAM,uBAAuB,CAAC;AA0D/B,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,gBAAgB,CAAC;IACvB,GAAG,EAAE,cAAc,CAAC;IACpB,0BAA0B,EAAE,CAAC,OAAO,EAAE,gBAAgB,KAAK,wBAAwB,CAAC;IACpF,yBAAyB,EAAE,OAAO,yBAAyB,CAAC;IAC5D,+BAA+B,EAAE,OAAO,+BAA+B,CAAC;IACxE,uBAAuB,EAAE,OAAO,uBAAuB,CAAC;IACxD,uBAAuB,EAAE,OAAO,uBAAuB,CAAC;IACxD,GAAG,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;IAClC,IAAI,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;IACnC,KAAK,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;IACpC,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,KAAK,CAAC;CAC/B;AAwBD,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,OAAO,EAChB,SAAS,GAAE,OAAO,CAAC,wBAAwB,CAAM,GAChD,IAAI,CAsoBN"}
1
+ {"version":3,"file":"fleet.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/fleet.ts"],"names":[],"mappings":"AAGA,OAAO,EAAwB,KAAK,OAAO,EAAE,MAAM,WAAW,CAAC;AAC/D,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAEL,uBAAuB,EACvB,uBAAuB,EACvB,mCAAmC,EACnC,qBAAqB,EAItB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAClE,OAAO,EAGL,KAAK,wBAAwB,EAE9B,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EAAgB,KAAK,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAiBhE,OAAO,EAAE,wBAAwB,EAAmC,MAAM,wBAAwB,CAAC;AAEnG,OAAO,EAEL,yBAAyB,EACzB,+BAA+B,EAG/B,KAAK,gBAAgB,EACtB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAML,KAAK,cAAc,EACpB,MAAM,uBAAuB,CAAC;AAoI/B,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,gBAAgB,CAAC;IACvB,GAAG,EAAE,cAAc,CAAC;IACpB,GAAG,EAAE,MAAM,MAAM,CAAC;IAClB,kBAAkB,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,mBAAmB,CAAC,CAAC;IAClE,0BAA0B,EAAE,CAAC,OAAO,EAAE,gBAAgB,KAAK,wBAAwB,CAAC;IACpF,yBAAyB,EAAE,OAAO,yBAAyB,CAAC;IAC5D,wBAAwB,EAAE,OAAO,wBAAwB,CAAC;IAC1D,eAAe,EAAE,OAAO,eAAe,CAAC;IACxC,qBAAqB,EAAE,OAAO,qBAAqB,CAAC;IACpD,+BAA+B,EAAE,OAAO,+BAA+B,CAAC;IACxE,uBAAuB,EAAE,OAAO,uBAAuB,CAAC;IACxD,mCAAmC,EAAE,OAAO,mCAAmC,CAAC;IAChF,uBAAuB,EAAE,OAAO,uBAAuB,CAAC;IACxD,GAAG,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;IAClC,IAAI,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;IACnC,KAAK,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;IACpC,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,KAAK,CAAC;CAC/B;AA8BD,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,OAAO,EAChB,SAAS,GAAE,OAAO,CAAC,wBAAwB,CAAM,GAChD,IAAI,CAg0BN"}