agent-embassy 1.3.0 → 1.4.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/CHANGELOG.md +17 -0
- package/CONTRIBUTING.md +25 -9
- package/README.md +39 -15
- package/README.zh-CN.md +34 -13
- package/SECURITY.md +13 -7
- package/dist/src/gateway/claude-helper-protocol.d.ts +1 -0
- package/dist/src/gateway/claude-helper-protocol.js +4 -2
- package/dist/src/gateway/claude-helper-protocol.js.map +1 -1
- package/dist/src/gateway/claude-helper-supervisor.d.ts +1 -0
- package/dist/src/gateway/claude-helper-supervisor.js +3 -0
- package/dist/src/gateway/claude-helper-supervisor.js.map +1 -1
- package/dist/src/gateway/cli-copy.d.ts +1 -1
- package/dist/src/gateway/cli-copy.en.d.ts +3 -2
- package/dist/src/gateway/cli-copy.en.js +3 -1
- package/dist/src/gateway/cli-copy.en.js.map +1 -1
- package/dist/src/gateway/cli-copy.js +1 -0
- package/dist/src/gateway/cli-copy.js.map +1 -1
- package/dist/src/gateway/cli-copy.zh-CN.d.ts +3 -2
- package/dist/src/gateway/cli-copy.zh-CN.js +3 -1
- package/dist/src/gateway/cli-copy.zh-CN.js.map +1 -1
- package/dist/src/gateway/cli.d.ts +1 -1
- package/dist/src/gateway/cli.js +12 -1
- package/dist/src/gateway/cli.js.map +1 -1
- package/dist/src/gateway/codex-app-server.d.ts +1 -1
- package/dist/src/gateway/codex-app-server.js +32 -11
- package/dist/src/gateway/codex-app-server.js.map +1 -1
- package/dist/src/gateway/config.d.ts +1 -1
- package/dist/src/gateway/control.d.ts +1 -1
- package/dist/src/gateway/control.js +5 -3
- package/dist/src/gateway/control.js.map +1 -1
- package/dist/src/gateway/dashboard-copy.d.ts +1 -1
- package/dist/src/gateway/dashboard-copy.en.d.ts +15 -1
- package/dist/src/gateway/dashboard-copy.en.js +25 -11
- package/dist/src/gateway/dashboard-copy.en.js.map +1 -1
- package/dist/src/gateway/dashboard-copy.js +15 -1
- package/dist/src/gateway/dashboard-copy.js.map +1 -1
- package/dist/src/gateway/dashboard-copy.zh-CN.d.ts +15 -1
- package/dist/src/gateway/dashboard-copy.zh-CN.js +25 -11
- package/dist/src/gateway/dashboard-copy.zh-CN.js.map +1 -1
- package/dist/src/gateway/dashboard-model.d.ts +2 -3
- package/dist/src/gateway/dashboard-model.js +118 -30
- package/dist/src/gateway/dashboard-model.js.map +1 -1
- package/dist/src/gateway/dashboard.js +22 -9
- package/dist/src/gateway/dashboard.js.map +1 -1
- package/dist/src/gateway/instance-lease.d.ts +2 -3
- package/dist/src/gateway/instance-lease.js +17 -140
- package/dist/src/gateway/instance-lease.js.map +1 -1
- package/dist/src/gateway/live-dashboard-app/app.js +45 -18
- package/dist/src/gateway/live-dashboard-http.js +1 -1
- package/dist/src/gateway/live-dashboard-http.js.map +1 -1
- package/dist/src/gateway/progress-watch-machine.d.ts +6 -5
- package/dist/src/gateway/progress-watch-machine.js +6 -6
- package/dist/src/gateway/progress-watch-machine.js.map +1 -1
- package/dist/src/gateway/provenance-envelope.d.ts +1 -0
- package/dist/src/gateway/provenance-envelope.js +10 -3
- package/dist/src/gateway/provenance-envelope.js.map +1 -1
- package/dist/src/gateway/providers.d.ts +1 -0
- package/dist/src/gateway/providers.js +6 -0
- package/dist/src/gateway/providers.js.map +1 -1
- package/dist/src/gateway/service.d.ts +2 -0
- package/dist/src/gateway/service.js +25 -8
- package/dist/src/gateway/service.js.map +1 -1
- package/dist/src/gateway/store.d.ts +9 -21
- package/dist/src/gateway/store.js +284 -122
- package/dist/src/gateway/store.js.map +1 -1
- package/dist/src/gateway/types.d.ts +1 -2
- package/dist/src/gateway/types.js.map +1 -1
- package/docs/CONFIGURATION.md +102 -0
- package/docs/CONFIGURATION.zh-CN.md +72 -0
- package/docs/DASHBOARD.md +103 -0
- package/docs/DASHBOARD.zh-CN.md +47 -0
- package/docs/DELIVERY.md +84 -0
- package/docs/DELIVERY.zh-CN.md +53 -0
- package/docs/GATEWAY-ARCHITECTURE.md +177 -93
- package/package.json +8 -4
|
@@ -18,16 +18,21 @@ queued turn after idle, and delivered the exact final reply back to Claude.
|
|
|
18
18
|
## Purpose and boundary
|
|
19
19
|
|
|
20
20
|
The gateway lets already-running Claude Code sessions and explicitly
|
|
21
|
-
registered native Codex tasks address one another by short aliases.
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
21
|
+
registered native Codex tasks address one another by short aliases. Both
|
|
22
|
+
directions require an explicit permission edge. The broker runs in `paired`
|
|
23
|
+
inbound mode by default, so an inbound native Claude message is admitted only
|
|
24
|
+
from a session that already holds a pair edge to the addressed Codex task;
|
|
25
|
+
`embassy serve --inbound open` is the explicit opt-out that restores any exact
|
|
26
|
+
compatible live same-UID session as an inbound sender without making it
|
|
27
|
+
outbound-selected. Outbound Codex-to-Claude sends likewise require the pair
|
|
28
|
+
edge, created by `pair` or the one-task `select-claude` shorthand. It provides
|
|
29
|
+
a single private operational view across the two products without rebuilding
|
|
30
|
+
either agent runtime.
|
|
27
31
|
|
|
28
32
|
Its exact Claude Code 2.1.226 runtime/peer-protocol pin is fail-closed.
|
|
29
|
-
Still-running 2.1.224 sessions remain compatible during a patch
|
|
30
|
-
because their registry records use the same reviewed peer protocol 1
|
|
33
|
+
Still-running 2.1.224 and 2.1.225 sessions remain compatible during a patch
|
|
34
|
+
upgrade because their registry records use the same reviewed peer protocol 1
|
|
35
|
+
shape.
|
|
31
36
|
|
|
32
37
|
It is deliberately:
|
|
33
38
|
|
|
@@ -129,7 +134,7 @@ probed by this project.
|
|
|
129
134
|
│ │ callback replies
|
|
130
135
|
▼ ▼
|
|
131
136
|
┌──────────────────────── local singleton gateway ───────────────────────┐
|
|
132
|
-
│ private control UDS │
|
|
137
|
+
│ private control UDS │ retained bodies │ metadata state │ static HTML │
|
|
133
138
|
└──────────┬──────────┴──────────────────┴────────────────┴──────────────┘
|
|
134
139
|
│
|
|
135
140
|
├─ local Codex App Server ─ registered native local tasks
|
|
@@ -153,7 +158,7 @@ The status below is intentionally narrower than the target architecture.
|
|
|
153
158
|
|
|
154
159
|
| Component | Current evidence |
|
|
155
160
|
| --- | --- |
|
|
156
|
-
| Neutral gateway types, metadata store, route fencing, bounded queues, dedupe, rate limits, and public projection | **Implemented**, deterministic tests; message bodies persist under bounded retention
|
|
161
|
+
| Neutral gateway types, metadata store, route fencing, bounded queues, dedupe, rate limits, and public projection | **Implemented**, deterministic tests; message bodies persist under bounded retention |
|
|
157
162
|
| Private JSONL control protocol over a controller-owned UDS | **Implemented**, deterministic synthetic tests; no provider connection required |
|
|
158
163
|
| Static metadata-only dashboard renderer and atomic publisher | **Implemented**, deterministic security tests; the static renderer requires no browser or HTTP server |
|
|
159
164
|
| Opt-in live dashboard companion (`embassy dashboard --live`) | **Implemented**, deterministic tests over the stable loopback listener, direct multi-browser access, projection, request guards, and four bounded route actions; it is a separate foreground process, never part of `embassy serve` |
|
|
@@ -312,9 +317,13 @@ final reply.
|
|
|
312
317
|
text as untrusted user-role input. This inbound observation grants only a
|
|
313
318
|
transient, in-memory capability for the correlated reply. It does not add a
|
|
314
319
|
Claude route, flip `selected`, or authorize a later unsolicited send.
|
|
315
|
-
In paired mode
|
|
316
|
-
message admission with `SENDER_NOT_PAIRED
|
|
317
|
-
|
|
320
|
+
In paired mode — the default — a sender without the exact permission edge is
|
|
321
|
+
refused before message admission with `SENDER_NOT_PAIRED`. No message is
|
|
322
|
+
accepted, so no delivery is created, but the refusal is not silent: the
|
|
323
|
+
broker records it as a `rejected` journal event carrying the direction, both
|
|
324
|
+
aliases, the byte count, and the safe error code, and increments the
|
|
325
|
+
rejected counters on the accounting, the source route, and any matching
|
|
326
|
+
pair.
|
|
318
327
|
3. The Claude process's inherited messaging-socket value may be accepted as a
|
|
319
328
|
transient reply address after strict validation. Claude Code exports
|
|
320
329
|
`CLAUDE_CODE_MESSAGING_SOCKET` as a raw absolute socket path; the CLI
|
|
@@ -340,12 +349,15 @@ final reply.
|
|
|
340
349
|
emit Claude's approval-specific native `held` control frame for ordinary
|
|
341
350
|
queueing.
|
|
342
351
|
8. In `merged` and `verbose` notice modes, if the delivery remains pending for
|
|
343
|
-
exactly `floor(messageDeadlineMs / 2)
|
|
344
|
-
originating Claude session at most one nonterminal
|
|
352
|
+
exactly `min(floor(messageDeadlineMs / 2), 120_000)` milliseconds, the
|
|
353
|
+
gateway may send the originating Claude session at most one nonterminal
|
|
345
354
|
`<gateway-delivery-stall>` user frame for that receipt. It contains only an
|
|
346
355
|
allowlisted reason and a bounded `queued-for-ms` age; it is not a native
|
|
347
|
-
`held` receipt and does not settle the delivery.
|
|
348
|
-
|
|
356
|
+
`held` receipt and does not settle the delivery. The two-minute ceiling is
|
|
357
|
+
deliberate: stall visibility must not scale with the deadline, so under the
|
|
358
|
+
default four-hour deadline the notice fires at two minutes, not two hours.
|
|
359
|
+
`quiet` suppresses this gateway-authored frame without changing native status
|
|
360
|
+
or dashboard state.
|
|
349
361
|
9. When the task becomes idle, the connector refreshes the exact task state and
|
|
350
362
|
starts the held message. A route retains at most three queued steering
|
|
351
363
|
messages; accepting a fourth atomically cancels the oldest with safe code
|
|
@@ -402,9 +414,10 @@ next-tool-call-boundary rules above.
|
|
|
402
414
|
|
|
403
415
|
The broker classifies `STEER:`, `TRACK:`, and `DONE:`, enforces raw-byte body
|
|
404
416
|
limits, deduplicates, and queues before presentation framing.
|
|
405
|
-
The store therefore retains only the raw
|
|
406
|
-
at the final semantic provider-write boundary so
|
|
407
|
-
same bytes with exactly one authoritative outer
|
|
417
|
+
The store therefore retains only the raw unframed body, never the composed
|
|
418
|
+
envelope. A pure composer runs at the final semantic provider-write boundary so
|
|
419
|
+
a clean retry produces the same bytes with exactly one authoritative outer
|
|
420
|
+
wrapper. Automatic provider
|
|
408
421
|
startup and endpoint-generation validation, receipt frames, and diagnostics do
|
|
409
422
|
not use this path.
|
|
410
423
|
|
|
@@ -425,15 +438,15 @@ broker-owned `cross-session-message` outer element and an
|
|
|
425
438
|
`embassy reply --conversation ... --alias ...` instruction and the statement
|
|
426
439
|
that caller, conversation, and route policy are rechecked.
|
|
427
440
|
|
|
428
|
-
Embassy does not synthesize `from`, `from-session`,
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
441
|
+
Embassy does not synthesize `from`, `from-session`, or `from-mode` attributes:
|
|
442
|
+
those names have provider-native meanings the broker cannot truthfully claim.
|
|
443
|
+
Native socket addresses, Codex thread IDs, Claude session UUIDs, endpoint
|
|
444
|
+
generations, and route handles never enter the content frame.
|
|
432
445
|
|
|
433
446
|
The outer structure and hint come only from validated broker metadata. Before
|
|
434
447
|
composition, the untrusted body case-insensitively neutralizes boundary-shaped
|
|
435
|
-
opening or closing occurrences of
|
|
436
|
-
|
|
448
|
+
opening or closing occurrences of Embassy's reserved framing tags by inserting
|
|
449
|
+
`\` immediately after the leading `<`.
|
|
437
450
|
Everything else remains raw text. This is not general XML, cryptographic
|
|
438
451
|
authentication, or proof that the message content is trustworthy; it is a
|
|
439
452
|
consistent structural provenance marker at the model input boundary. A native
|
|
@@ -512,16 +525,22 @@ never displaced to admit a new send. A pressure-evicted handle returns
|
|
|
512
525
|
|
|
513
526
|
### Replies and process restarts
|
|
514
527
|
|
|
515
|
-
Conversation IDs correlate replies,
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
528
|
+
Conversation IDs correlate replies, and callback addresses exist only in
|
|
529
|
+
memory, but queued message bodies are durable. After a gateway restart, each
|
|
530
|
+
queued message is triaged: one already past its deadline settles `expired`; one
|
|
531
|
+
whose target authority was transient, or whose target route is gone, settles
|
|
532
|
+
`abandoned` with `CONTROLLER_RESTARTED`; every other queued body is restored and
|
|
533
|
+
re-armed for dispatch, then sent exactly once after its exact route is
|
|
534
|
+
re-observed. A message in flight at the moment of the restart or crash settles
|
|
535
|
+
`ambiguous` with `CONTROLLER_RESTARTED` and is never replayed.
|
|
536
|
+
|
|
537
|
+
The prior Claude binding remains stored but stale. After authorized live
|
|
538
|
+
discovery, one exact UUID-bound selection may be reactivated under its latest
|
|
539
|
+
name. No pending reply, callback, native receipt handle, delivery token/status
|
|
540
|
+
tracker, or conversation capability survives the restart; a prior token
|
|
541
|
+
therefore returns `found: false`. A stale or offline selection can be explicitly
|
|
542
|
+
removed by its stored alias or a user-supplied UUID without requiring discovery
|
|
543
|
+
first.
|
|
525
544
|
|
|
526
545
|
## Gateway control plane
|
|
527
546
|
|
|
@@ -530,33 +549,41 @@ controller-owned mode-0700 state directory. The socket and state files are
|
|
|
530
549
|
mode 0600. Frames are size-bounded and closed against unknown keys, methods,
|
|
531
550
|
versions, and enum values.
|
|
532
551
|
|
|
533
|
-
The
|
|
552
|
+
The closed version 1 method family is exactly these sixteen methods:
|
|
534
553
|
|
|
535
|
-
- health and a safe public snapshot;
|
|
536
|
-
- a read-only
|
|
537
|
-
lifecycle deliveries before projecting
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
554
|
+
- `health` and `list_snapshot`, a safe public snapshot;
|
|
555
|
+
- `observe_snapshot`, a read-only projection that may settle already-due
|
|
556
|
+
lifecycle deliveries before projecting;
|
|
557
|
+
- `register_codex`, `unregister_codex`, and
|
|
558
|
+
`remove_stale_codex_registration` — explicit Codex registration and
|
|
559
|
+
succession, unregister, and broker-guarded removal of a stale orphan whose
|
|
560
|
+
owning endpoint generation is dead;
|
|
561
|
+
- `select_claude` and `unselect_claude`, from the current sanitized
|
|
541
562
|
available-peer inventory;
|
|
542
|
-
-
|
|
543
|
-
-
|
|
544
|
-
-
|
|
545
|
-
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
563
|
+
- `pair` and `unpair`, the two-endpoint permission edge;
|
|
564
|
+
- `delivery_status`, a lookup by opaque, memory-only correlation handle;
|
|
565
|
+
- `untrack`, which closes one active progress watch by conversation token;
|
|
566
|
+
- `send_to_claude` and `send_to_codex`, the provider-specific sends;
|
|
567
|
+
- `reply`, the correlated reply operation; and
|
|
568
|
+
- `refresh_dashboard`, which refreshes Claude discovery and republishes.
|
|
569
|
+
|
|
570
|
+
The live dashboard companion calls `observe_snapshot` for every read; its
|
|
571
|
+
mutation route additionally calls `pair`, `unpair`,
|
|
572
|
+
`remove_stale_codex_registration`, and `refresh_dashboard`, and nothing else.
|
|
573
|
+
|
|
574
|
+
The installed binary is `embassy`, and it is the only installed binary. Its
|
|
575
|
+
seventeen implemented commands are
|
|
576
|
+
`serve`, `health`, `status`, `delivery-status`, `wait-delivery`, `untrack`,
|
|
550
577
|
`refresh-dashboard`, `dashboard`, `register-codex`, `unregister-codex`,
|
|
551
|
-
`select-claude`, `unselect-claude`, `
|
|
552
|
-
`reply`. `dashboard` requires `--live` and accepts an
|
|
553
|
-
`--lang en|zh-CN
|
|
554
|
-
control request. Message bodies are non-empty
|
|
555
|
-
with a 16 KiB ceiling; they are never accepted
|
|
556
|
-
client emits one bounded normalized JSON line and
|
|
557
|
-
provider-native ID, path, address, or message body.
|
|
558
|
-
foreground broker, except that `serve` starts it in
|
|
559
|
-
never daemonizes itself.
|
|
578
|
+
`select-claude`, `unselect-claude`, `pair`, `unpair`, `send-to-claude`,
|
|
579
|
+
`send-to-codex`, and `reply`. `dashboard` requires `--live` and accepts an
|
|
580
|
+
optional `--lang en|zh-CN` and `--port <n>`; it starts the companion process
|
|
581
|
+
rather than issuing a single control request. Message bodies are non-empty
|
|
582
|
+
UTF-8 from standard input only, with a 16 KiB ceiling; they are never accepted
|
|
583
|
+
in an argument or file. The client emits one bounded normalized JSON line and
|
|
584
|
+
never returns a thread ID, provider-native ID, path, address, or message body.
|
|
585
|
+
These commands require the foreground broker, except that `serve` starts it in
|
|
586
|
+
the current terminal. It never daemonizes itself.
|
|
560
587
|
|
|
561
588
|
`select-claude --alias <current-name@host>` and
|
|
562
589
|
`select-claude --session <uuid>` select the same logical session.
|
|
@@ -569,9 +596,19 @@ Codex registration, unregister, and Codex-to-Claude send require only a valid
|
|
|
569
596
|
`CODEX_THREAD_ID`; they fail if a non-empty Claude messaging socket is also
|
|
570
597
|
inherited. Claude-to-Codex send requires only the raw inherited Claude socket
|
|
571
598
|
path and fails if a non-empty Codex thread ID is also present. `reply` likewise
|
|
572
|
-
fails with both identities or neither.
|
|
573
|
-
|
|
574
|
-
|
|
599
|
+
fails with both identities or neither. `pair` and `unpair` also require an
|
|
600
|
+
exclusive inherited `CODEX_THREAD_ID`: naming both endpoints does not make them
|
|
601
|
+
operator commands, and they fail `CODEX_IDENTITY_REQUIRED` from a plain terminal
|
|
602
|
+
or `CALLER_IDENTITY_CONFLICT` from inside a Claude session.
|
|
603
|
+
|
|
604
|
+
`select-claude` and `unselect-claude` are the operator-runnable shorthand.
|
|
605
|
+
They do not ignore provider identity — they consume an inherited
|
|
606
|
+
`CODEX_THREAD_ID` when one is present, to resolve the Codex end, and reject a
|
|
607
|
+
malformed one — but they tolerate its absence and then resolve the Codex end
|
|
608
|
+
from the sole registered task. Selection is not a weaker operation than
|
|
609
|
+
`pair`: it atomically creates the same permission edge. The health, status,
|
|
610
|
+
dashboard refresh, live dashboard, untrack, and serve commands are the ones
|
|
611
|
+
that genuinely ignore provider identities.
|
|
575
612
|
|
|
576
613
|
The foreground command is:
|
|
577
614
|
|
|
@@ -579,16 +616,22 @@ The foreground command is:
|
|
|
579
616
|
embassy serve
|
|
580
617
|
```
|
|
581
618
|
|
|
619
|
+
`--inbound open` is the one security-relevant option:
|
|
620
|
+
|
|
621
|
+
```text
|
|
622
|
+
embassy serve --inbound open
|
|
623
|
+
```
|
|
624
|
+
|
|
625
|
+
The default is `paired`. `open` is the explicit opt-out that lets any exact
|
|
626
|
+
compatible live same-UID Claude session send inbound without a pair edge; it is
|
|
627
|
+
never implied and cannot be set through an environment variable.
|
|
628
|
+
|
|
582
629
|
Before provider validation, listener creation, or App Server attachment, the
|
|
583
630
|
launcher acquires one fixed host-wide crash-reclaimable owner lease under the
|
|
584
631
|
verified login home. The lease is independent of `EMBASSY_STATE_DIR`, so two foreground
|
|
585
632
|
controllers cannot be started for the same login account by choosing different
|
|
586
|
-
state roots.
|
|
587
|
-
|
|
588
|
-
pre-existing legacy lock blocks startup as `GATEWAY_INSTANCE_IN_USE` and is
|
|
589
|
-
preserved; the operator may remove that exact stale lock only after confirming
|
|
590
|
-
no prototype process remains. Missing, unsafe, or unrecognized legacy roots
|
|
591
|
-
are not created, imported, or mutated.
|
|
633
|
+
state roots. It is the only instance lock Embassy takes: the pre-rename
|
|
634
|
+
prototype state root is no longer read, locked, or mutated.
|
|
592
635
|
|
|
593
636
|
It emits one normalized ready line, publishes the private dashboard, and
|
|
594
637
|
holds the process until `SIGINT` or `SIGTERM`, when exact-owned resources are
|
|
@@ -606,6 +649,27 @@ Same-UID socket access is a local containment boundary, not proof of a trusted
|
|
|
606
649
|
agent process. Every mutation additionally checks route ownership, exact
|
|
607
650
|
thread/session generation, source alias, bounds, and conversation state.
|
|
608
651
|
|
|
652
|
+
### Progress watches
|
|
653
|
+
|
|
654
|
+
`send-to-claude`, `send-to-codex`, and `reply` each accept an opt-in `--track`
|
|
655
|
+
flag that opens one progress watch over the resulting conversation, plus an
|
|
656
|
+
optional `--idle-minutes <n>` that sets how long the watched thread may sit idle
|
|
657
|
+
before the watch reports a stall. `n` is an integer from 1 through 1440 and
|
|
658
|
+
defaults to 5; supplying it without `--track` is an argument error. A body with
|
|
659
|
+
an exact leading `TRACK:` prefix opens the same watch at the default idle window
|
|
660
|
+
without the flag.
|
|
661
|
+
|
|
662
|
+
`untrack --conversation conv_<token>` closes an active watch explicitly, and a
|
|
663
|
+
body with an exact leading `DONE:` prefix closes it as completed; one message
|
|
664
|
+
may not both open and complete a watch (`PROGRESS_WATCH_SIGNAL_CONFLICT`). The
|
|
665
|
+
global `EMBASSY_TRACKING_ENABLED` switch is on by default and exact `0` disables
|
|
666
|
+
the surface; `EMBASSY_MAX_WATCHES` bounds concurrent watches at 32 by default
|
|
667
|
+
(hard cap 256).
|
|
668
|
+
|
|
669
|
+
A watch is independent evidence about thread activity, not delivery evidence. It
|
|
670
|
+
may outlive an opener whose own delivery expired, so check the opener's
|
|
671
|
+
`delivery-status` separately before assuming the assignment text arrived.
|
|
672
|
+
|
|
609
673
|
## Codex connectors and remote hosts
|
|
610
674
|
|
|
611
675
|
In the target multi-host design, each allowlisted execution host has a separate
|
|
@@ -747,22 +811,34 @@ A static page is a point-in-time snapshot and never refreshes itself: it emits
|
|
|
747
811
|
no meta refresh and the page tells the operator to re-run
|
|
748
812
|
`embassy refresh-dashboard` and reload, or to use `embassy dashboard --live`.
|
|
749
813
|
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
- aggregate gateway
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
-
|
|
758
|
-
|
|
814
|
+
Each page assembles seven sections:
|
|
815
|
+
|
|
816
|
+
- **Exchange** — aggregate gateway health plus the pair graph: every explicit
|
|
817
|
+
Claude↔Codex edge and its per-edge counters.
|
|
818
|
+
- **Attention** — allowlisted alerts such as stale route, protocol mismatch,
|
|
819
|
+
queue full, or ambiguous delivery.
|
|
820
|
+
- **Transit** — queued-message depth and bytes in flight.
|
|
821
|
+
- **Progress supervision** — active progress watches and their state.
|
|
822
|
+
- **Operator activity** — the broker's bounded public journal of accepted
|
|
823
|
+
operator actions.
|
|
824
|
+
- **Sessions** — available/selected Claude aliases, registered Codex aliases,
|
|
825
|
+
provider, host, compatibility, state, and queue depth.
|
|
826
|
+
- **Diagnostics** — compatibility attestations per provider, per-host connector
|
|
827
|
+
health and protocol, deadline-pressure buckets, accounting totals, and the
|
|
828
|
+
omission counters below. Normalized message direction and delivery state,
|
|
829
|
+
timestamp, latency, byte count, and a short opaque message-ID suffix appear
|
|
830
|
+
with the delivery rows.
|
|
759
831
|
|
|
760
832
|
It never shows message content, prompts, replies, transcripts, titles, working
|
|
761
833
|
directories, native IDs, PIDs, socket paths, endpoint paths, tool data, raw
|
|
762
|
-
events, stderr, credentials, or configuration contents
|
|
763
|
-
|
|
764
|
-
a
|
|
765
|
-
|
|
834
|
+
events, stderr, credentials, or configuration contents — retained bodies reach
|
|
835
|
+
only the live companion, never these files. This is a controller-owned UI
|
|
836
|
+
artifact, not a shared task file. The public snapshot has a 240 KiB projection
|
|
837
|
+
budget and reports explicit omission counters whenever bounded rows are
|
|
838
|
+
truncated: connectors, available peers, routes, pairs, progress watches,
|
|
839
|
+
upstream and projected progress-watch events, upstream message events, message
|
|
840
|
+
groups, message events, upstream alerts, attention items, and upstream and
|
|
841
|
+
projected activity events.
|
|
766
842
|
|
|
767
843
|
### Live dashboard companion
|
|
768
844
|
|
|
@@ -825,9 +901,12 @@ The private store may retain:
|
|
|
825
901
|
accounting and dashboard projection;
|
|
826
902
|
- timestamps, counters, dedupe/rate-limit records, and safe error codes.
|
|
827
903
|
|
|
828
|
-
It
|
|
829
|
-
|
|
830
|
-
|
|
904
|
+
It also retains message bodies under bounded caps — the queued body of every
|
|
905
|
+
undelivered message and the recent delivery ledger's retained bodies, evicted
|
|
906
|
+
oldest-first against a 1 MiB budget by default. It must never retain provider
|
|
907
|
+
output, tool input/output, raw App Server or Claude frames, stderr, histories,
|
|
908
|
+
credentials, Claude registry payloads, or callback/socket paths. The public
|
|
909
|
+
snapshot is a
|
|
831
910
|
strict projection that also removes private route handles and endpoint
|
|
832
911
|
generations. The state directory is mode 0700 and binding state is mode 0600;
|
|
833
912
|
provider-native identifiers never enter normalized events, public snapshots,
|
|
@@ -836,14 +915,15 @@ every restored route begins stale and unusable. An authorized discovery may
|
|
|
836
915
|
reactivate only the byte-identical durable Claude UUID after the current
|
|
837
916
|
provider endpoint, workspace, complete unique discovery, and ownership lease
|
|
838
917
|
all revalidate. The public `selected` bit flips only after that atomic private
|
|
839
|
-
rebind succeeds.
|
|
840
|
-
reply capability is restored, and no
|
|
841
|
-
reconstructed.
|
|
918
|
+
rebind succeeds. Queued bodies are restored and re-armed for dispatch; no
|
|
919
|
+
callback, receipt handle, conversation, or reply capability is restored, and no
|
|
920
|
+
delivery token or status tracker is reconstructed.
|
|
842
921
|
|
|
843
922
|
The delivery-token mapping, queryable status tracker, native receipt handle,
|
|
844
923
|
and one-stall-notice state are always memory-only. Durable delivery metadata
|
|
845
|
-
does not contain enough information to reconstruct any of those capabilities
|
|
846
|
-
|
|
924
|
+
does not contain enough information to reconstruct any of those capabilities.
|
|
925
|
+
A restored body is re-sent exactly once and only into its own exact
|
|
926
|
+
re-observed route; it is never replayed into a reconstructed capability.
|
|
847
927
|
|
|
848
928
|
## Minimum filesystem and process access
|
|
849
929
|
|
|
@@ -876,13 +956,13 @@ paths, peers, and transports:
|
|
|
876
956
|
|
|
877
957
|
| Path/capability | Minimum purpose |
|
|
878
958
|
| --- | --- |
|
|
879
|
-
| `~/.local/bin/claude` and derived expected target `~/.local/share/claude/versions/2.1.226` | Stat the owned launcher/path components and read/execute only the resolved pinned target for bounded `--version`; live launcher validation succeeded |
|
|
959
|
+
| `~/.local/bin/claude` (or the absolute `EMBASSY_CLAUDE_BIN` override) and derived expected target `~/.local/share/claude/versions/2.1.226` | Stat the owned launcher/path components and read/execute only the resolved pinned target for bounded `--version`; `PATH` and interactive shell profiles are never searched; live launcher validation succeeded |
|
|
880
960
|
| `~/.claude/sessions` | Read/enumerate only live registry JSON during the separately authorized passive-discovery gate |
|
|
881
961
|
| `/tmp/cc-socks` | At foreground startup, validate the private directory and create/remove only `/tmp/cc-socks/<gateway-pid>.sock` after inode/generation checks; search/stat genuine peers at passive discovery and connect one validated target only at the separately authorized send gate |
|
|
882
962
|
| `~/.local/state/agent-embassy/.agent-embassy-state` | Validate or establish the exact ownership marker before creating the fixed host lease; an existing non-empty unmarked root is rejected without mutation |
|
|
883
963
|
| `/usr/bin/lockf` and `/bin/cat` | Hold one fixed, non-waiting macOS advisory lease for the foreground controller; the helper receives no shell text, provider data, or model-supplied argument |
|
|
964
|
+
| `/usr/bin/open` | Executed only by the opt-in `embassy dashboard --live` companion, to open the loopback dashboard URL in the operator's browser; no shell, a scrubbed fixed environment, and a bounded timeout and output cap |
|
|
884
965
|
| `~/.local/state/agent-embassy/.gateway-host.lock` | Fixed per-login kernel-held lease acquired before provider setup; it remains here even when `EMBASSY_STATE_DIR` is overridden. Its bounded PID/token record is exact-cleanup metadata, not a path-only stale-lock authority; a crash releases the kernel lock and the next foreground process may acquire the existing file |
|
|
885
|
-
| `~/.local/state/claude-agent-bridge/gateway/.claude-codex-gateway-state` and `.gateway-controller.lock` | For one release, bounded-read the exact legacy ownership marker and lock record; create and hold the lock only when absent, preserve any pre-existing lock, and read no other legacy state or message data |
|
|
886
966
|
| `~/.local/state/agent-embassy` (or explicit `EMBASSY_STATE_DIR`) | Default controller-owned store, control UDS, state lock, and static dashboard; an explicit absolute configuration may replace only these state surfaces |
|
|
887
967
|
| `~/.codex/packages/standalone` and `~/.codex/app-server-control/app-server-control.sock` | Resolve the pinned managed Codex binary and attach to the already-running private local App Server; never bootstrap or unlink it |
|
|
888
968
|
|
|
@@ -933,7 +1013,11 @@ the preferred least-context setup, but it is not mandatory.
|
|
|
933
1013
|
fail-closed. Only exact retry is permitted until the old route is confirmed
|
|
934
1014
|
unregistered and the controller is restarted.
|
|
935
1015
|
- No ambiguous mutation is retried automatically.
|
|
936
|
-
-
|
|
1016
|
+
- A queued body survives process loss under bounded retention and is re-sent
|
|
1017
|
+
exactly once after its exact route is re-observed. A message in flight when
|
|
1018
|
+
the process was lost settles `ambiguous` with `CONTROLLER_RESTARTED`; a
|
|
1019
|
+
message whose target authority was transient, or whose target route no longer
|
|
1020
|
+
exists, settles `abandoned` with the same code.
|
|
937
1021
|
- A provider or Desktop update outside the release's exact reviewed pins fails
|
|
938
1022
|
closed; retained state never admits an unreviewed version or activates an
|
|
939
1023
|
unvalidated replacement endpoint generation.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agent-embassy",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.0",
|
|
4
4
|
"description": "A local gateway for bidirectional messaging between Claude Code sessions and Codex tasks.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -24,8 +24,7 @@
|
|
|
24
24
|
"darwin"
|
|
25
25
|
],
|
|
26
26
|
"bin": {
|
|
27
|
-
"embassy": "dist/src/gateway/cli.js"
|
|
28
|
-
"claude-codex-gateway": "dist/src/gateway/cli.js"
|
|
27
|
+
"embassy": "dist/src/gateway/cli.js"
|
|
29
28
|
},
|
|
30
29
|
"files": [
|
|
31
30
|
"dist/src/gateway",
|
|
@@ -39,7 +38,12 @@
|
|
|
39
38
|
"assets/mark.svg",
|
|
40
39
|
"assets/social-preview.png",
|
|
41
40
|
"skills/embassy-peer",
|
|
42
|
-
"docs/
|
|
41
|
+
"docs/CONFIGURATION.md",
|
|
42
|
+
"docs/CONFIGURATION.zh-CN.md",
|
|
43
|
+
"docs/DASHBOARD.md",
|
|
44
|
+
"docs/DASHBOARD.zh-CN.md",
|
|
45
|
+
"docs/DELIVERY.md",
|
|
46
|
+
"docs/DELIVERY.zh-CN.md",
|
|
43
47
|
"docs/GATEWAY-ARCHITECTURE.md",
|
|
44
48
|
"CHANGELOG.md",
|
|
45
49
|
"CONTRIBUTING.md",
|