@agentvault/claude-bridge 0.7.2 → 0.7.4
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/bridge.d.ts +24 -0
- package/dist/index.js +68 -15
- package/package.json +2 -2
package/dist/bridge.d.ts
CHANGED
|
@@ -43,6 +43,10 @@ export interface RoomHushed {
|
|
|
43
43
|
}
|
|
44
44
|
export interface RoomChannel {
|
|
45
45
|
on(ev: "room_message", cb: (e: RoomMessage) => void): unknown;
|
|
46
|
+
on(ev: "room_joined", cb: (e: {
|
|
47
|
+
roomId: string;
|
|
48
|
+
name?: string;
|
|
49
|
+
}) => void): unknown;
|
|
46
50
|
on(ev: "message", cb: (text: string, metadata: MessageMeta) => void): unknown;
|
|
47
51
|
on(ev: "room_hushed", cb: (e: RoomHushed) => void): unknown;
|
|
48
52
|
on(ev: "error", cb: (err: unknown) => void): unknown;
|
|
@@ -175,6 +179,26 @@ export declare function attachLifecycle(channel: LifecycleChannel, opts?: {
|
|
|
175
179
|
* dropped (it usually means a mis-timed or duplicate approval).
|
|
176
180
|
*/
|
|
177
181
|
export declare function pollApprovalsOnce(arming: ArmingState, dataDir: string, onArmed: () => void, log?: (msg: string) => void): void;
|
|
182
|
+
/**
|
|
183
|
+
* How a ROOM turn is announced to the model (#366 / #499 Facet A).
|
|
184
|
+
*
|
|
185
|
+
* Reproduced live 2026-07-29: asked "what room are you in?" *in* a room, the
|
|
186
|
+
* agent answered "This is our 1:1 DM, so no room name to report." Everything
|
|
187
|
+
* beneath the model was correct — the bridge logged `inbound from chris in
|
|
188
|
+
* c6a2734d` then `said to room c6a2734d`, and the message is recorded against
|
|
189
|
+
* room "New Test" in the database. The turn was simply pushed as
|
|
190
|
+
* `[chris]: <text>`, which carries no channel context whatsoever, so the model
|
|
191
|
+
* had nothing to distinguish a room from a DM and defaulted to DM.
|
|
192
|
+
*
|
|
193
|
+
* The room NAME is best-effort (learned from `room_joined`), but the fact that
|
|
194
|
+
* this is a room is not: when the name is unknown we still say "room" and fall
|
|
195
|
+
* back to a short id. Getting "which room" wrong is a cosmetic answer; getting
|
|
196
|
+
* "am I in a room" wrong changes how the agent addresses everyone in it.
|
|
197
|
+
*
|
|
198
|
+
* A 1:1 DM is deliberately left unlabelled — that path is not broken, and an
|
|
199
|
+
* unmarked turn already reads as a DM, which is what the model assumes.
|
|
200
|
+
*/
|
|
201
|
+
export declare function roomTurnPrefix(roomId: string, senderName: string, roomName?: string): string;
|
|
178
202
|
export declare function wireBridge(channel: RoomChannel, session: RoomSession, target: ActiveTarget, opts?: {
|
|
179
203
|
roomFilter?: string;
|
|
180
204
|
armRoom?: boolean;
|
package/dist/index.js
CHANGED
|
@@ -63525,6 +63525,34 @@ var init_owner_sync = __esm2({
|
|
|
63525
63525
|
NONCE_BYTES2 = 24;
|
|
63526
63526
|
}
|
|
63527
63527
|
});
|
|
63528
|
+
function seqOf(m22) {
|
|
63529
|
+
if (m22.seq === void 0 || m22.seq === null || m22.seq === "")
|
|
63530
|
+
return null;
|
|
63531
|
+
const n22 = Number(m22.seq);
|
|
63532
|
+
return Number.isFinite(n22) ? n22 : null;
|
|
63533
|
+
}
|
|
63534
|
+
function createdAtOf(m22) {
|
|
63535
|
+
const t22 = new Date(m22.created_at ?? 0).getTime();
|
|
63536
|
+
return Number.isFinite(t22) ? t22 : 0;
|
|
63537
|
+
}
|
|
63538
|
+
function orderDeliveryBatch(messages) {
|
|
63539
|
+
return [...messages].sort((a2, b22) => {
|
|
63540
|
+
const aWelcome = a2.message_type === "welcome";
|
|
63541
|
+
const bWelcome = b22.message_type === "welcome";
|
|
63542
|
+
if (aWelcome !== bWelcome)
|
|
63543
|
+
return aWelcome ? -1 : 1;
|
|
63544
|
+
const as2 = seqOf(a2);
|
|
63545
|
+
const bs2 = seqOf(b22);
|
|
63546
|
+
if (as2 !== null && bs2 !== null && as2 !== bs2)
|
|
63547
|
+
return as2 - bs2;
|
|
63548
|
+
return createdAtOf(a2) - createdAtOf(b22);
|
|
63549
|
+
});
|
|
63550
|
+
}
|
|
63551
|
+
var init_mls_delivery_order = __esm2({
|
|
63552
|
+
"../crypto/dist/mls-delivery-order.js"() {
|
|
63553
|
+
"use strict";
|
|
63554
|
+
}
|
|
63555
|
+
});
|
|
63528
63556
|
var dist_exports = {};
|
|
63529
63557
|
__export2(dist_exports, {
|
|
63530
63558
|
AV_CREDENTIAL_CONTEXT: () => AV_CREDENTIAL_CONTEXT,
|
|
@@ -63595,6 +63623,7 @@ __export2(dist_exports, {
|
|
|
63595
63623
|
issueCredential: () => issueCredential,
|
|
63596
63624
|
multibaseToPublicKey: () => multibaseToPublicKey,
|
|
63597
63625
|
normalizeBackupCode: () => normalizeBackupCode,
|
|
63626
|
+
orderDeliveryBatch: () => orderDeliveryBatch,
|
|
63598
63627
|
parseTraceparent: () => parseTraceparent,
|
|
63599
63628
|
performX3DH: () => performX3DH,
|
|
63600
63629
|
presentCredentials: () => presentCredentials,
|
|
@@ -63632,6 +63661,7 @@ var init_dist = __esm2({
|
|
|
63632
63661
|
await init_approval();
|
|
63633
63662
|
init_mls_group();
|
|
63634
63663
|
await init_owner_sync();
|
|
63664
|
+
init_mls_delivery_order();
|
|
63635
63665
|
}
|
|
63636
63666
|
});
|
|
63637
63667
|
function syncLockPath(dataDir, channelId) {
|
|
@@ -64592,6 +64622,7 @@ var init_channel = __esm2({
|
|
|
64592
64622
|
"use strict";
|
|
64593
64623
|
await init_libsodium_wrappers();
|
|
64594
64624
|
await init_dist();
|
|
64625
|
+
await init_dist();
|
|
64595
64626
|
init_mls_state();
|
|
64596
64627
|
await init_mls_kp_pool();
|
|
64597
64628
|
init_credential_store();
|
|
@@ -64699,6 +64730,24 @@ var init_channel = __esm2({
|
|
|
64699
64730
|
_pendingKpBundles = [];
|
|
64700
64731
|
/** Pool target: keep this many unconsumed KeyPackages published; backend caps to match. */
|
|
64701
64732
|
static _KP_POOL_TARGET = 10;
|
|
64733
|
+
/**
|
|
64734
|
+
* Local retention bound for `_pendingKpBundles` (#363). Deliberately ABOVE
|
|
64735
|
+
* `_KP_POOL_TARGET`, because the two counts are in DIFFERENT UNITS: the backend
|
|
64736
|
+
* keeps up to `_KP_POOL_TARGET` **unconsumed** KeyPackages, while this array
|
|
64737
|
+
* holds every bundle published since the last join — consumed ones are removed
|
|
64738
|
+
* only by `_removeKpFromPool` on a successful join.
|
|
64739
|
+
*
|
|
64740
|
+
* Capping local retention AT the backend's target therefore evicts bundles the
|
|
64741
|
+
* backend can still serve, and their private material cannot be rebuilt (#341:
|
|
64742
|
+
* `mls_rs_uniffi` exposes no KeyPackage repository), so any Welcome minted
|
|
64743
|
+
* against an evicted bundle is PERMANENTLY unjoinable.
|
|
64744
|
+
*
|
|
64745
|
+
* Same defect and same remedy as #511, where the web store capped 6 against a
|
|
64746
|
+
* backend pool of 10 and was raised to 12. Retaining extra bundles is cheap and
|
|
64747
|
+
* purely protective — `_handleMlsWelcome` trial-decrypts against the whole pool,
|
|
64748
|
+
* so a surplus only ever adds chances to match.
|
|
64749
|
+
*/
|
|
64750
|
+
static _KP_POOL_RETENTION = 20;
|
|
64702
64751
|
/** Reentrancy guard so concurrent pool top-ups don't double-publish past target. */
|
|
64703
64752
|
_kpPoolFilling = false;
|
|
64704
64753
|
/** Buffer for MLS commits received before Welcome (keyed by groupId, sorted by epoch). */
|
|
@@ -65362,7 +65411,9 @@ var init_channel = __esm2({
|
|
|
65362
65411
|
const pendingWsSends = [];
|
|
65363
65412
|
const sentSharedGroupIds = /* @__PURE__ */ new Set();
|
|
65364
65413
|
if (this._persisted?.mlsGroups && this._state === "ready" && this._ws) {
|
|
65414
|
+
const targetSharedGid = targetConvId ? this._sessionGroupIds?.get(targetConvId) : void 0;
|
|
65365
65415
|
for (const [gid, entry] of Object.entries(this._persisted.mlsGroups)) {
|
|
65416
|
+
if (targetConvId && gid !== targetSharedGid) continue;
|
|
65366
65417
|
if (!entry.mlsGroupId) continue;
|
|
65367
65418
|
const mlsGroup = this._mlsGroups.get(`1to1-group:${gid}`);
|
|
65368
65419
|
if (!mlsGroup?.isInitialized || Number(mlsGroup.epoch) <= 0) continue;
|
|
@@ -65563,7 +65614,7 @@ var init_channel = __esm2({
|
|
|
65563
65614
|
*/
|
|
65564
65615
|
sendActivitySpan(spanData) {
|
|
65565
65616
|
if (!this._ws || this._ws.readyState !== WebSocket2.OPEN) return;
|
|
65566
|
-
const pluginVersion = true ? "0.23.
|
|
65617
|
+
const pluginVersion = true ? "0.23.14" : "0.0.0-dev";
|
|
65567
65618
|
const agentName = this.config.agentName ?? "Agent";
|
|
65568
65619
|
const resource = {
|
|
65569
65620
|
"service.name": "agentvault-agent",
|
|
@@ -67302,7 +67353,7 @@ var init_channel = __esm2({
|
|
|
67302
67353
|
agentVersion: this.config.agentVersion ?? "0.0.0",
|
|
67303
67354
|
// __AV_VERSION__ is injected by esbuild from package.json at build time.
|
|
67304
67355
|
// Falls back to "0.0.0-dev" in non-bundled contexts (tests).
|
|
67305
|
-
pluginVersion: true ? "0.23.
|
|
67356
|
+
pluginVersion: true ? "0.23.14" : "0.0.0-dev"
|
|
67306
67357
|
});
|
|
67307
67358
|
this._telemetryReporter.startAutoFlush(3e4);
|
|
67308
67359
|
}
|
|
@@ -67620,7 +67671,7 @@ var init_channel = __esm2({
|
|
|
67620
67671
|
agentVersion: this.config.agentVersion ?? "0.0.0",
|
|
67621
67672
|
// __AV_VERSION__ is injected by esbuild from package.json at build time.
|
|
67622
67673
|
// Falls back to "0.0.0-dev" in non-bundled contexts (tests).
|
|
67623
|
-
pluginVersion: true ? "0.23.
|
|
67674
|
+
pluginVersion: true ? "0.23.14" : "0.0.0-dev"
|
|
67624
67675
|
});
|
|
67625
67676
|
this._telemetryReporter.startAutoFlush(3e4);
|
|
67626
67677
|
}
|
|
@@ -69283,7 +69334,7 @@ ${messageText}`;
|
|
|
69283
69334
|
if (!this._pendingKpBundles.some((b22) => idOf(b22) === id)) {
|
|
69284
69335
|
this._pendingKpBundles.push(kp);
|
|
69285
69336
|
}
|
|
69286
|
-
while (this._pendingKpBundles.length > _SecureChannel.
|
|
69337
|
+
while (this._pendingKpBundles.length > _SecureChannel._KP_POOL_RETENTION) {
|
|
69287
69338
|
this._pendingKpBundles.shift();
|
|
69288
69339
|
}
|
|
69289
69340
|
}
|
|
@@ -69538,16 +69589,10 @@ ${messageText}`;
|
|
|
69538
69589
|
console.warn(`[SecureChannel] Delivery pull failed: ${res.status}`);
|
|
69539
69590
|
return;
|
|
69540
69591
|
}
|
|
69541
|
-
|
|
69592
|
+
let { messages } = await res.json();
|
|
69542
69593
|
const hasMessages = messages && messages.length > 0;
|
|
69543
69594
|
if (hasMessages) {
|
|
69544
|
-
|
|
69545
|
-
messages.sort((a2, b22) => {
|
|
69546
|
-
const ao = order[a2.message_type] ?? 2;
|
|
69547
|
-
const bo = order[b22.message_type] ?? 2;
|
|
69548
|
-
if (ao !== bo) return ao - bo;
|
|
69549
|
-
return new Date(a2.created_at).getTime() - new Date(b22.created_at).getTime();
|
|
69550
|
-
});
|
|
69595
|
+
messages = orderDeliveryBatch(messages);
|
|
69551
69596
|
const ackedIds = [];
|
|
69552
69597
|
const nackedIds = [];
|
|
69553
69598
|
for (const msg of messages) {
|
|
@@ -97475,7 +97520,7 @@ var init_index = __esm2({
|
|
|
97475
97520
|
init_skill_invoker();
|
|
97476
97521
|
await init_skill_telemetry();
|
|
97477
97522
|
await init_policy_enforcer();
|
|
97478
|
-
VERSION = true ? "0.23.
|
|
97523
|
+
VERSION = true ? "0.23.14" : "0.0.0-dev";
|
|
97479
97524
|
}
|
|
97480
97525
|
});
|
|
97481
97526
|
await init_index();
|
|
@@ -133532,6 +133577,10 @@ function pollApprovalsOnce(arming, dataDir, onArmed, log = () => {
|
|
|
133532
133577
|
}
|
|
133533
133578
|
}
|
|
133534
133579
|
}
|
|
133580
|
+
function roomTurnPrefix(roomId, senderName, roomName) {
|
|
133581
|
+
const room = roomName ? `"${roomName}"` : roomId.slice(0, 8);
|
|
133582
|
+
return `[room ${room} | ${senderName}]`;
|
|
133583
|
+
}
|
|
133535
133584
|
function wireBridge(channel, session, target, opts = {}) {
|
|
133536
133585
|
const log = opts.log ?? (() => {
|
|
133537
133586
|
});
|
|
@@ -133566,6 +133615,10 @@ function wireBridge(channel, session, target, opts = {}) {
|
|
|
133566
133615
|
);
|
|
133567
133616
|
});
|
|
133568
133617
|
let warnedMissingSenderIsAgent = false;
|
|
133618
|
+
const roomNames = /* @__PURE__ */ new Map();
|
|
133619
|
+
channel.on("room_joined", (e7) => {
|
|
133620
|
+
if (e7?.roomId && e7.name) roomNames.set(e7.roomId, e7.name);
|
|
133621
|
+
});
|
|
133569
133622
|
channel.on("room_message", (e7) => {
|
|
133570
133623
|
if (typeof e7.senderIsAgent !== "boolean" && !warnedMissingSenderIsAgent) {
|
|
133571
133624
|
warnedMissingSenderIsAgent = true;
|
|
@@ -133580,7 +133633,7 @@ function wireBridge(channel, session, target, opts = {}) {
|
|
|
133580
133633
|
}
|
|
133581
133634
|
log(`inbound from ${e7.senderName} in ${e7.roomId.slice(0, 8)}`);
|
|
133582
133635
|
target.setRoom(e7.roomId);
|
|
133583
|
-
session.push(
|
|
133636
|
+
session.push(`${roomTurnPrefix(e7.roomId, e7.senderName, roomNames.get(e7.roomId))}: ${e7.plaintext}`, target.snapshotReply(channel, log), {
|
|
133584
133637
|
autoReplyOnText: false,
|
|
133585
133638
|
replyExpected: e7.senderIsAgent === false,
|
|
133586
133639
|
armed: () => arming.isArmed(e7.roomId)
|
|
@@ -133731,7 +133784,7 @@ async function main() {
|
|
|
133731
133784
|
"[bridge] warning: passing the invite token on the command line is visible to other local users via 'ps'. Prefer: AV_INVITE_TOKEN=\u2026 npx @agentvault/claude-bridge"
|
|
133732
133785
|
);
|
|
133733
133786
|
}
|
|
133734
|
-
console.error(`[bridge] version: ${true ? "0.7.
|
|
133787
|
+
console.error(`[bridge] version: ${true ? "0.7.4" : "dev"}`);
|
|
133735
133788
|
console.error(`[bridge] data dir: ${cfg.dataDir} (${cfg.dataDirSource})`);
|
|
133736
133789
|
console.error(`[bridge] workspace: ${cfg.workspaceDir} \xB7 permissions: ${cfg.permissionMode} \xB7 enclave dir fenced`);
|
|
133737
133790
|
if (cfg.armRoom) {
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agentvault/claude-bridge",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.4",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"description": "AgentVault Claude Bridge
|
|
5
|
+
"description": "AgentVault Claude Bridge \u2014 daemon for bridging a Claude agent into secure E2E-encrypted AgentVault 1:1 direct messages and rooms.",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"types": "dist/index.d.ts",
|
|
8
8
|
"bin": {
|