@agentvault/claude-bridge 0.5.7 → 0.5.10
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/dist/arming.d.ts +44 -14
- package/dist/bridge.d.ts +39 -3
- package/dist/config.d.ts +3 -2
- package/dist/index.js +422 -131
- package/dist/router.d.ts +40 -0
- package/dist/service/spec.d.ts.map +1 -1
- package/dist/session.d.ts +28 -2
- package/dist/worker-queue.d.ts +46 -0
- package/package.json +1 -1
package/dist/arming.d.ts
CHANGED
|
@@ -10,24 +10,54 @@ export declare class ArmingState {
|
|
|
10
10
|
private pending;
|
|
11
11
|
private consumed;
|
|
12
12
|
/**
|
|
13
|
-
* Replace the armed set. Use
|
|
14
|
-
*
|
|
13
|
+
* Replace the armed set. Use for the host-local launch seed (AV_ARM_ROOM) —
|
|
14
|
+
* itself a host-local action and therefore allowed to arm — and as the
|
|
15
|
+
* primitive `applyAuthoritative` below delegates to for non-shell workers.
|
|
15
16
|
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
17
|
+
* The B-pure posture (Task 4) treats the backend connect/live
|
|
18
|
+
* `arming_snapshot` the same way — see `applyAuthoritative`'s docstring for
|
|
19
|
+
* the current arm-from-snapshot rationale. Shell-capable (OS-isolated)
|
|
20
|
+
* workers do NOT use this path; they stay on `reconcileDisarm` (disarm-only,
|
|
21
|
+
* see below) until #20.
|
|
21
22
|
*/
|
|
22
23
|
applySnapshot(roomIds: string[]): void;
|
|
23
24
|
/**
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
25
|
+
* Set the armed set to EXACTLY `intendedArmed`: arms every room in the list
|
|
26
|
+
* that isn't already armed, and disarms every currently-armed room that is
|
|
27
|
+
* absent from it. This is the AUTHORITATIVE arm-from-snapshot path (Task 4,
|
|
28
|
+
* reversing the prior disarm-only safeguard for non-shell workers).
|
|
29
|
+
*
|
|
30
|
+
* Why arming from the snapshot is now safe: `intendedArmed` is derived
|
|
31
|
+
* server-side from `devices.work_allowed`, and that flag can only be flipped
|
|
32
|
+
* by `PUT /devices/{id}/work_allowed`, which REJECTS any device-bound caller
|
|
33
|
+
* outright (C1 guard — a human account owner only; an agent, including a
|
|
34
|
+
* compromised one, cannot self-authorize). So "arm from snapshot" no longer
|
|
35
|
+
* means "a web session can arm a worker" in the old adversarial sense — it
|
|
36
|
+
* means "the verified owner's grant is applied end-to-end, live, without
|
|
37
|
+
* requiring a separate host-local approval step for every reconnect." This is
|
|
38
|
+
* the accepted B-pure posture; see #20 to harden it further with local
|
|
39
|
+
* approval for non-shell workers too. Shell-capable (OS-isolated) workers are
|
|
40
|
+
* carved out of this path entirely (C2) — see the shell-gate in bridge.ts —
|
|
41
|
+
* because a shell worker armed by a web flag is a live RCE surface even under
|
|
42
|
+
* an honest owner (a compromised owner web session, or a compromised backend,
|
|
43
|
+
* would get arbitrary code execution). Those workers stay on `reconcileDisarm`
|
|
44
|
+
* (disarm-only) until #20 delivers local approval for them as well.
|
|
45
|
+
*/
|
|
46
|
+
applyAuthoritative(intendedArmed: string[]): void;
|
|
47
|
+
/**
|
|
48
|
+
* Disarm-only reconciliation from the backend connect/live snapshot. Disarms
|
|
49
|
+
* any currently-armed room whose intent is no longer armed (i.e. NOT in
|
|
50
|
+
* `intendedArmed`) — so a disarm issued while the bridge was offline still
|
|
51
|
+
* takes effect on reconnect — but NEVER arms a room. Used for OS-isolated
|
|
52
|
+
* (shell-capable) workers ONLY (C2): a shell worker must never be armed by a
|
|
53
|
+
* web-originated flag, because a compromised owner session or backend would
|
|
54
|
+
* translate directly into host code execution. Those workers can be armed
|
|
55
|
+
* only by the host-local launch seed (`AV_ARM_ROOM`, via `applySnapshot`)
|
|
56
|
+
* until #20 delivers a local-approval path for them too. Non-shell workers
|
|
57
|
+
* use `applyAuthoritative` instead (Task 4) — see its docstring. Returns the
|
|
58
|
+
* rooms that were disarmed. In-memory arming survives a WS reconnect, so a
|
|
59
|
+
* genuinely-armed room is unaffected here; only a full process restart
|
|
60
|
+
* (which clears this state) requires re-arming.
|
|
31
61
|
*/
|
|
32
62
|
reconcileDisarm(intendedArmed: string[]): string[];
|
|
33
63
|
isArmed(roomId: string): boolean;
|
package/dist/bridge.d.ts
CHANGED
|
@@ -3,6 +3,13 @@ export interface RoomMessage {
|
|
|
3
3
|
roomId: string;
|
|
4
4
|
senderName: string;
|
|
5
5
|
plaintext: string;
|
|
6
|
+
/** True when the sender is another agent (SecureChannel derives this from the
|
|
7
|
+
* room roster). Used to decide reply expectation: a human/owner speaking in a
|
|
8
|
+
* room always expects a reply; agent-authored traffic does not (the agent may
|
|
9
|
+
* stay silent, and it prevents agent↔agent reply loops). Absent on older
|
|
10
|
+
* payloads / tests → treated as "not an agent" is NOT assumed: replyExpected is
|
|
11
|
+
* set only when we affirmatively know the sender is a human (=== false). */
|
|
12
|
+
senderIsAgent?: boolean;
|
|
6
13
|
}
|
|
7
14
|
/** Slice 2 Plan C arming events (SecureChannel re-emits these from the backend). */
|
|
8
15
|
export interface ArmRequested {
|
|
@@ -15,6 +22,10 @@ export interface DisarmEvent {
|
|
|
15
22
|
}
|
|
16
23
|
export interface ArmingSnapshot {
|
|
17
24
|
roomIds: string[];
|
|
25
|
+
/** Task 3 (P1 bridge): the device-level owner grant this snapshot carries
|
|
26
|
+
* (backend `devices.work_allowed`, Task 2). Optional so older/test payloads
|
|
27
|
+
* without it don't break — treated as `false` (fail-closed) when absent. */
|
|
28
|
+
workAllowed?: boolean;
|
|
18
29
|
}
|
|
19
30
|
/** Metadata SecureChannel attaches to a 1:1 `message` event. `roomId` is set only
|
|
20
31
|
* when the `message` actually originated in a room (handled by room_message), so
|
|
@@ -37,6 +48,11 @@ export interface RoomChannel {
|
|
|
37
48
|
on(ev: "arm_requested", cb: (e: ArmRequested) => void): unknown;
|
|
38
49
|
on(ev: "disarm", cb: (e: DisarmEvent) => void): unknown;
|
|
39
50
|
on(ev: "arming_snapshot", cb: (e: ArmingSnapshot) => void): unknown;
|
|
51
|
+
/** Task 3: SecureChannel's connection lifecycle signal. It never emits a
|
|
52
|
+
* bare `"close"` — a WS drop is reported as `state` moving to
|
|
53
|
+
* `"disconnected"` (or `"error"`), and a completed reconnect as `"ready"`
|
|
54
|
+
* (both the dedicated `state` value AND the separate `"ready"` event). */
|
|
55
|
+
on(ev: "state", cb: (s: string) => void): unknown;
|
|
40
56
|
sendToRoom(roomId: string, text: string): Promise<void>;
|
|
41
57
|
send(text: string): Promise<void>;
|
|
42
58
|
/** Optional so legacy/test fakes without arming support don't break wiring. */
|
|
@@ -59,9 +75,12 @@ export interface RoomSession {
|
|
|
59
75
|
/** `reply` is the immutable reply sink captured for THIS message (see
|
|
60
76
|
* ActiveTarget.snapshotReply) — the session invokes it when Claude answers.
|
|
61
77
|
* `opts.autoReplyOnText` (set for 1:1 DMs) makes the session fall back to
|
|
62
|
-
* sending plain assistant text when the model never calls the say tool (#416).
|
|
78
|
+
* sending plain assistant text when the model never calls the say tool (#416).
|
|
79
|
+
* `opts.replyExpected` requests that same fallback for a room turn (a human/owner
|
|
80
|
+
* sender) WITHOUT enabling tools — decoupled from autoReplyOnText on purpose. */
|
|
63
81
|
push(text: string, reply?: (text: string) => Promise<void>, opts?: {
|
|
64
82
|
autoReplyOnText?: boolean;
|
|
83
|
+
replyExpected?: boolean;
|
|
65
84
|
armed?: () => boolean;
|
|
66
85
|
}): void;
|
|
67
86
|
}
|
|
@@ -148,11 +167,28 @@ export declare function wireBridge(channel: RoomChannel, session: RoomSession, t
|
|
|
148
167
|
roomFilter?: string;
|
|
149
168
|
armRoom?: boolean;
|
|
150
169
|
log?: (msg: string) => void;
|
|
151
|
-
/** Slice 2 Plan C (T11): worker capability + local-approval marker dir. */
|
|
152
|
-
worker?: boolean;
|
|
170
|
+
/** Slice 2 Plan C (T11): worker capability (derived from workspaceDir) + local-approval marker dir. */
|
|
153
171
|
workspaceDir?: string;
|
|
154
172
|
dataDir?: string;
|
|
155
173
|
/** Override the approval poll interval (ms) — for tests. */
|
|
156
174
|
approvalPollMs?: number;
|
|
175
|
+
/**
|
|
176
|
+
* Task 4 (C2 shell-gate): true when this worker runs Bash unconfined
|
|
177
|
+
* (AV_WORKER_OS_ISOLATED=1 — see config.ts/index.ts, threaded from the
|
|
178
|
+
* session's `osIsolated`). When true, the `arming_snapshot` handler stays
|
|
179
|
+
* disarm-only regardless of B1/worker-capability — a shell worker must
|
|
180
|
+
* never be armed by a web-originated flag (RCE risk). Falls back to
|
|
181
|
+
* reading the env directly only if the caller doesn't thread this.
|
|
182
|
+
*/
|
|
183
|
+
osIsolated?: boolean;
|
|
184
|
+
/**
|
|
185
|
+
* Task 3 (P1 bridge): out-param that receives the live `workAllowed()`
|
|
186
|
+
* getter once, synchronously, during wiring. Callers (index.ts, Task 4)
|
|
187
|
+
* capture it to thread device-level tool-capability into the router +
|
|
188
|
+
* session gate. Kept as an out-param rather than changing wireBridge's
|
|
189
|
+
* return type so every existing `const arming = wireBridge(...)` caller
|
|
190
|
+
* (index.ts, arming-authoritative.test.ts, bridge.test.ts) stays intact.
|
|
191
|
+
*/
|
|
192
|
+
onWorkAllowed?: (getter: () => boolean) => void;
|
|
157
193
|
}): ArmingState;
|
|
158
194
|
//# sourceMappingURL=bridge.d.ts.map
|
package/dist/config.d.ts
CHANGED
|
@@ -14,8 +14,9 @@ export interface BridgeConfig {
|
|
|
14
14
|
roomFilter?: string;
|
|
15
15
|
model?: string;
|
|
16
16
|
systemPrompt?: string;
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
/** Per-agent filesystem sandbox (Facet-A fence). Always set: auto-defaults
|
|
18
|
+
* to a sibling of the key/data dir (H-2) unless AV_WORKSPACE_DIR overrides it. */
|
|
19
|
+
workspaceDir: string;
|
|
19
20
|
permissionMode: "auto" | "acceptEdits" | "bypassPermissions";
|
|
20
21
|
/** Slice 2: arm the pinned room (roomFilter) for worker tools on room turns.
|
|
21
22
|
* Off by default. Valid only with worker + roomFilter + workspaceDir. */
|