@agentvault/claude-bridge 0.8.4 → 0.8.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/dist/index.js +114 -56
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -64011,6 +64011,8 @@ var init_mls_group = __esm2({
|
|
|
64011
64011
|
continue;
|
|
64012
64012
|
seenIdentities.push(identity);
|
|
64013
64013
|
const leaf = this.memberLeafIndex(identity);
|
|
64014
|
+
if (leaf !== null && leaf === this.ownLeafIndex())
|
|
64015
|
+
continue;
|
|
64014
64016
|
if (leaf !== null)
|
|
64015
64017
|
leavesToRemove.push(leaf);
|
|
64016
64018
|
}
|
|
@@ -64066,6 +64068,20 @@ var init_mls_group = __esm2({
|
|
|
64066
64068
|
* then re-adds it with a fresh KeyPackage so it gets a Welcome at the
|
|
64067
64069
|
* current epoch it can actually apply.
|
|
64068
64070
|
*/
|
|
64071
|
+
/**
|
|
64072
|
+
* The leaf index THIS manager occupies — the leaf whose private key it holds.
|
|
64073
|
+
*
|
|
64074
|
+
* Read from `privatePath.leafIndex`, which is the same value ts-mls uses to
|
|
64075
|
+
* decide whether a commit removes its own committer, so a caller checking
|
|
64076
|
+
* against this cannot disagree with the library about who "we" are.
|
|
64077
|
+
*
|
|
64078
|
+
* Exists so a fulfiller can tell a request from ANOTHER device apart from one
|
|
64079
|
+
* from itself (#1147) without any "who am I" plumbing: the manager already
|
|
64080
|
+
* knows, and a guard that reads it here cannot be forgotten by a call site.
|
|
64081
|
+
*/
|
|
64082
|
+
ownLeafIndex() {
|
|
64083
|
+
return this._requireState().privatePath.leafIndex;
|
|
64084
|
+
}
|
|
64069
64085
|
memberLeafIndex(identity) {
|
|
64070
64086
|
const s22 = this._requireState();
|
|
64071
64087
|
const tree = s22.ratchetTree;
|
|
@@ -64596,11 +64612,11 @@ var init_mls_kp_pool = __esm2({
|
|
|
64596
64612
|
}
|
|
64597
64613
|
});
|
|
64598
64614
|
function ownIdentity() {
|
|
64599
|
-
const v22 = true ? "0.23.
|
|
64615
|
+
const v22 = true ? "0.23.33" : FALLBACK;
|
|
64600
64616
|
return `${PACKAGE}@${v22}`;
|
|
64601
64617
|
}
|
|
64602
64618
|
function buildSha() {
|
|
64603
|
-
const raw = true ? "
|
|
64619
|
+
const raw = true ? "7b91f2f-dirty" : "";
|
|
64604
64620
|
const cleaned = (raw ?? "").trim();
|
|
64605
64621
|
return !cleaned || cleaned === "unknown" ? null : cleaned;
|
|
64606
64622
|
}
|
|
@@ -65515,6 +65531,7 @@ var OUTBOUND_DEDUPE_MAX;
|
|
|
65515
65531
|
var OUTBOUND_DEDUPE_TYPES;
|
|
65516
65532
|
var RETRY_CANDIDATE_TTL_MS;
|
|
65517
65533
|
var RETRY_CANDIDATE_MAX;
|
|
65534
|
+
var ROOM_FULFIL_COOLDOWN_MS;
|
|
65518
65535
|
var SecureChannel;
|
|
65519
65536
|
var init_channel = __esm2({
|
|
65520
65537
|
async "src/channel.ts"() {
|
|
@@ -65560,6 +65577,7 @@ var init_channel = __esm2({
|
|
|
65560
65577
|
OUTBOUND_DEDUPE_TYPES = /* @__PURE__ */ new Set(["text", "status_alert", "artifact", "attachment"]);
|
|
65561
65578
|
RETRY_CANDIDATE_TTL_MS = 6e4;
|
|
65562
65579
|
RETRY_CANDIDATE_MAX = 32;
|
|
65580
|
+
ROOM_FULFIL_COOLDOWN_MS = 6e4;
|
|
65563
65581
|
SecureChannel = class _SecureChannel extends EventEmitter {
|
|
65564
65582
|
constructor(config22) {
|
|
65565
65583
|
super();
|
|
@@ -65629,6 +65647,8 @@ var init_channel = __esm2({
|
|
|
65629
65647
|
_drDeliveryPulling = false;
|
|
65630
65648
|
/** MLS group managers per room/conversation (roomId or conv:conversationId or 1to1-group:groupId -> MLSGroupManager) */
|
|
65631
65649
|
_mlsGroups = /* @__PURE__ */ new Map();
|
|
65650
|
+
/** `${mlsGroupId}:${deviceId}` -> last re-admit ms (#1171). */
|
|
65651
|
+
_roomFulfilCooldown = /* @__PURE__ */ new Map();
|
|
65632
65652
|
/** Maps conversationId -> conversation_group_id for shared 1:1 MLS groups */
|
|
65633
65653
|
_sessionGroupIds = /* @__PURE__ */ new Map();
|
|
65634
65654
|
/** Consecutive MLS decrypt failure count per group key for epoch recovery. */
|
|
@@ -66794,7 +66814,7 @@ var init_channel = __esm2({
|
|
|
66794
66814
|
*/
|
|
66795
66815
|
sendActivitySpan(spanData) {
|
|
66796
66816
|
if (!this._ws || this._ws.readyState !== WebSocket2.OPEN) return;
|
|
66797
|
-
const pluginVersion = true ? "0.23.
|
|
66817
|
+
const pluginVersion = true ? "0.23.33" : "0.0.0-dev";
|
|
66798
66818
|
const agentName = this.config.agentName ?? "Agent";
|
|
66799
66819
|
const resource = {
|
|
66800
66820
|
"service.name": "agentvault-agent",
|
|
@@ -68732,7 +68752,7 @@ var init_channel = __esm2({
|
|
|
68732
68752
|
agentVersion: this.config.agentVersion ?? "0.0.0",
|
|
68733
68753
|
// __AV_VERSION__ is injected by esbuild from package.json at build time.
|
|
68734
68754
|
// Falls back to "0.0.0-dev" in non-bundled contexts (tests).
|
|
68735
|
-
pluginVersion: true ? "0.23.
|
|
68755
|
+
pluginVersion: true ? "0.23.33" : "0.0.0-dev"
|
|
68736
68756
|
});
|
|
68737
68757
|
this._telemetryReporter.startAutoFlush(3e4);
|
|
68738
68758
|
}
|
|
@@ -69056,7 +69076,7 @@ var init_channel = __esm2({
|
|
|
69056
69076
|
agentVersion: this.config.agentVersion ?? "0.0.0",
|
|
69057
69077
|
// __AV_VERSION__ is injected by esbuild from package.json at build time.
|
|
69058
69078
|
// Falls back to "0.0.0-dev" in non-bundled contexts (tests).
|
|
69059
|
-
pluginVersion: true ? "0.23.
|
|
69079
|
+
pluginVersion: true ? "0.23.33" : "0.0.0-dev"
|
|
69060
69080
|
});
|
|
69061
69081
|
this._telemetryReporter.startAutoFlush(3e4);
|
|
69062
69082
|
}
|
|
@@ -69859,7 +69879,8 @@ ${baseText}`;
|
|
|
69859
69879
|
async _downloadAndDecryptAttachment(info) {
|
|
69860
69880
|
const attachDir = join4(this.config.dataDir, "attachments");
|
|
69861
69881
|
await mkdir3(attachDir, { recursive: true });
|
|
69862
|
-
const
|
|
69882
|
+
const sep3 = info.blobUrl.includes("?") ? "&" : "?";
|
|
69883
|
+
const url22 = `${this.config.apiUrl}${info.blobUrl}${sep3}device_id=${encodeURIComponent(this._deviceId ?? "")}`;
|
|
69863
69884
|
const res = await fetch(url22, {
|
|
69864
69885
|
headers: { Authorization: `Bearer ${this._deviceJwt}` }
|
|
69865
69886
|
});
|
|
@@ -70411,10 +70432,12 @@ ${baseText}`;
|
|
|
70411
70432
|
const rawPlaintext = new TextDecoder().decode(result.plaintext);
|
|
70412
70433
|
let messageText;
|
|
70413
70434
|
let messageType;
|
|
70435
|
+
let roomAttachment = null;
|
|
70414
70436
|
try {
|
|
70415
70437
|
const parsed = JSON.parse(rawPlaintext);
|
|
70416
70438
|
messageType = parsed.type || "message";
|
|
70417
70439
|
messageText = parsed.text || rawPlaintext;
|
|
70440
|
+
if (parsed.attachment) roomAttachment = parsed.attachment;
|
|
70418
70441
|
} catch {
|
|
70419
70442
|
messageType = "message";
|
|
70420
70443
|
messageText = rawPlaintext;
|
|
@@ -70454,6 +70477,9 @@ ${baseText}`;
|
|
|
70454
70477
|
await this._refreshRoomRoster(resolvedRoomId);
|
|
70455
70478
|
}
|
|
70456
70479
|
}
|
|
70480
|
+
if (roomAttachment) {
|
|
70481
|
+
messageText = await this._augmentWithAttachment(roomAttachment, messageText);
|
|
70482
|
+
}
|
|
70457
70483
|
const roomMembers = this._persisted?.rooms?.[resolvedRoomId]?.members ?? [];
|
|
70458
70484
|
const senderMember = roomMembers.find((m22) => m22.deviceId === senderDeviceId);
|
|
70459
70485
|
const senderIsAgent = senderMember?.entityType === "agent";
|
|
@@ -70739,13 +70765,7 @@ ${baseText}`;
|
|
|
70739
70765
|
console.warn(`[SecureChannel] MLS epoch recovery for ${groupKey} (${mlsGroupId.slice(0, 8)})`);
|
|
70740
70766
|
this._mlsGroups.delete(groupKey);
|
|
70741
70767
|
this._mlsDecryptFailCounts.delete(groupKey);
|
|
70742
|
-
|
|
70743
|
-
const { unlink: unlink2 } = await import("fs/promises");
|
|
70744
|
-
const path2 = `${this.config.dataDir}/.mls-state/${mlsGroupId}.json`;
|
|
70745
|
-
await unlink2(path2).catch(() => {
|
|
70746
|
-
});
|
|
70747
|
-
} catch {
|
|
70748
|
-
}
|
|
70768
|
+
await deleteMlsState(this.config.dataDir, mlsGroupId);
|
|
70749
70769
|
try {
|
|
70750
70770
|
const mgr = new MLSGroupManager();
|
|
70751
70771
|
const identity = new TextEncoder().encode(this._deviceId);
|
|
@@ -70820,19 +70840,26 @@ ${baseText}`;
|
|
|
70820
70840
|
return 0;
|
|
70821
70841
|
}
|
|
70822
70842
|
const snapshot = mlsGroup.exportState();
|
|
70823
|
-
const {
|
|
70824
|
-
|
|
70825
|
-
|
|
70826
|
-
|
|
70827
|
-
|
|
70828
|
-
|
|
70829
|
-
|
|
70830
|
-
|
|
70831
|
-
|
|
70832
|
-
|
|
70833
|
-
|
|
70834
|
-
|
|
70835
|
-
|
|
70843
|
+
const { commits, welcome } = await mlsGroup.reAdmitMembers(targets.map((t22) => t22.keyPackage));
|
|
70844
|
+
let sentCommits = 0;
|
|
70845
|
+
for (const c22 of commits) {
|
|
70846
|
+
const ok2 = await this._sendFrameConfirmed(
|
|
70847
|
+
{
|
|
70848
|
+
event: "mls_commit",
|
|
70849
|
+
data: {
|
|
70850
|
+
group_id: mlsGroupId,
|
|
70851
|
+
// The epoch this commit PRODUCED. After two commits the manager
|
|
70852
|
+
// only knows the last one, which is why the result carries them.
|
|
70853
|
+
epoch: Number(c22.epoch),
|
|
70854
|
+
payload: Buffer.from(c22.commit).toString("hex")
|
|
70855
|
+
}
|
|
70856
|
+
},
|
|
70857
|
+
`${label} commit ${sentCommits + 1}/${commits.length}`
|
|
70858
|
+
);
|
|
70859
|
+
if (!ok2) break;
|
|
70860
|
+
sentCommits++;
|
|
70861
|
+
}
|
|
70862
|
+
if (sentCommits === 0) {
|
|
70836
70863
|
mlsGroup.importState(snapshot);
|
|
70837
70864
|
console.warn(
|
|
70838
70865
|
`[SecureChannel] ${label}: commit was NOT written \u2014 rolled back to epoch ${Number(mlsGroup.epoch)}, nothing fulfilled, requests stay pending`
|
|
@@ -70840,6 +70867,12 @@ ${baseText}`;
|
|
|
70840
70867
|
return 0;
|
|
70841
70868
|
}
|
|
70842
70869
|
await saveMlsState(this.config.dataDir, mlsGroupId, JSON.stringify(mlsGroup.exportState()));
|
|
70870
|
+
if (sentCommits < commits.length) {
|
|
70871
|
+
console.warn(
|
|
70872
|
+
`[SecureChannel] ${label}: only ${sentCommits}/${commits.length} commits reached the wire \u2014 requests stay PENDING for the next pull`
|
|
70873
|
+
);
|
|
70874
|
+
return 0;
|
|
70875
|
+
}
|
|
70843
70876
|
if (!welcome) {
|
|
70844
70877
|
console.warn(
|
|
70845
70878
|
`[SecureChannel] ${label}: addMembers produced NO Welcome \u2014 ${targets.length} request(s) left pending rather than marked fulfilled`
|
|
@@ -71568,38 +71601,63 @@ ${baseText}`;
|
|
|
71568
71601
|
{ headers: { Authorization: `Bearer ${this._deviceJwt}` } }
|
|
71569
71602
|
);
|
|
71570
71603
|
if (!pendingRes.ok) continue;
|
|
71571
|
-
|
|
71604
|
+
let pending = await pendingRes.json();
|
|
71572
71605
|
if (pending.length === 0) continue;
|
|
71573
71606
|
console.log(`[SecureChannel] ${pending.length} pending Welcome requests for room ${roomId.slice(0, 8)}`);
|
|
71607
|
+
const nowMs = Date.now();
|
|
71608
|
+
const fresh = pending.filter((r22) => {
|
|
71609
|
+
const key = `${roomState.mlsGroupId}:${r22.requesting_device_id}`;
|
|
71610
|
+
const last = this._roomFulfilCooldown.get(key) ?? 0;
|
|
71611
|
+
if (nowMs - last < ROOM_FULFIL_COOLDOWN_MS) {
|
|
71612
|
+
console.log(
|
|
71613
|
+
`[SecureChannel] skipping ${r22.requesting_device_id.slice(0, 8)} in room ${roomId.slice(0, 8)} \u2014 re-admitted ${Math.round((nowMs - last) / 1e3)}s ago`
|
|
71614
|
+
);
|
|
71615
|
+
return false;
|
|
71616
|
+
}
|
|
71617
|
+
return true;
|
|
71618
|
+
});
|
|
71619
|
+
if (fresh.length === 0) continue;
|
|
71620
|
+
for (const r22 of fresh) {
|
|
71621
|
+
this._roomFulfilCooldown.set(`${roomState.mlsGroupId}:${r22.requesting_device_id}`, nowMs);
|
|
71622
|
+
}
|
|
71623
|
+
pending = fresh;
|
|
71624
|
+
const deviceIds = pending.map((r22) => r22.requesting_device_id);
|
|
71625
|
+
const kpRes = await fetch(
|
|
71626
|
+
`${this.config.apiUrl}/api/v1/mls/key-packages/batch?device_ids=${deviceIds.join(",")}`,
|
|
71627
|
+
{ headers: { Authorization: `Bearer ${this._deviceJwt}` } }
|
|
71628
|
+
);
|
|
71629
|
+
if (!kpRes.ok) continue;
|
|
71630
|
+
const kpData = await kpRes.json();
|
|
71631
|
+
const roomTargets = [];
|
|
71574
71632
|
for (const req of pending) {
|
|
71575
|
-
|
|
71576
|
-
|
|
71577
|
-
|
|
71578
|
-
|
|
71633
|
+
const kpHex = kpData[req.requesting_device_id];
|
|
71634
|
+
if (!kpHex) {
|
|
71635
|
+
console.warn(`[SecureChannel] No KeyPackage for ${req.requesting_device_id.slice(0, 8)}, skipping`);
|
|
71636
|
+
continue;
|
|
71637
|
+
}
|
|
71638
|
+
const kpBytes = new Uint8Array(Buffer.from(kpHex, "hex"));
|
|
71639
|
+
roomTargets.push({
|
|
71640
|
+
requestId: req.id,
|
|
71641
|
+
deviceId: req.requesting_device_id,
|
|
71642
|
+
keyPackage: MLSGroupManager.deserializeKeyPackage(kpBytes)
|
|
71643
|
+
});
|
|
71644
|
+
}
|
|
71645
|
+
if (roomTargets.length === 0) continue;
|
|
71646
|
+
try {
|
|
71647
|
+
const done = await this._fulfilWelcomeRequests({
|
|
71648
|
+
mlsGroup,
|
|
71649
|
+
mlsGroupId: roomState.mlsGroupId,
|
|
71650
|
+
label: `room ${roomId.slice(0, 8)}`,
|
|
71651
|
+
welcomeFields: { room_id: roomId },
|
|
71652
|
+
targets: roomTargets
|
|
71653
|
+
});
|
|
71654
|
+
if (done > 0) {
|
|
71655
|
+
console.log(
|
|
71656
|
+
`[SecureChannel] Batched Welcome for ${done}/${roomTargets.length} device(s) in room ${roomId.slice(0, 8)} (epoch=${mlsGroup.epoch})`
|
|
71579
71657
|
);
|
|
71580
|
-
if (!kpRes.ok) continue;
|
|
71581
|
-
const kpData = await kpRes.json();
|
|
71582
|
-
const kpHex = kpData[req.requesting_device_id];
|
|
71583
|
-
if (!kpHex) continue;
|
|
71584
|
-
const kpBytes = new Uint8Array(Buffer.from(kpHex, "hex"));
|
|
71585
|
-
const memberKp = MLSGroupManager.deserializeKeyPackage(kpBytes);
|
|
71586
|
-
const done = await this._fulfilWelcomeRequests({
|
|
71587
|
-
mlsGroup,
|
|
71588
|
-
mlsGroupId: roomState.mlsGroupId,
|
|
71589
|
-
label: `room ${roomId.slice(0, 8)}`,
|
|
71590
|
-
welcomeFields: { room_id: roomId },
|
|
71591
|
-
targets: [{
|
|
71592
|
-
requestId: req.id,
|
|
71593
|
-
deviceId: req.requesting_device_id,
|
|
71594
|
-
keyPackage: memberKp
|
|
71595
|
-
}]
|
|
71596
|
-
});
|
|
71597
|
-
if (done > 0) {
|
|
71598
|
-
console.log(`[SecureChannel] Fulfilled Welcome for ${req.requesting_device_id.slice(0, 8)} in room ${roomId.slice(0, 8)}`);
|
|
71599
|
-
}
|
|
71600
|
-
} catch (fulfillErr) {
|
|
71601
|
-
console.warn(`[SecureChannel] Welcome fulfill failed for ${req.requesting_device_id.slice(0, 8)}:`, fulfillErr);
|
|
71602
71658
|
}
|
|
71659
|
+
} catch (fulfillErr) {
|
|
71660
|
+
console.warn(`[SecureChannel] Batched Welcome failed for room ${roomId.slice(0, 8)}:`, fulfillErr);
|
|
71603
71661
|
}
|
|
71604
71662
|
} catch {
|
|
71605
71663
|
}
|
|
@@ -99410,7 +99468,7 @@ var init_index = __esm2({
|
|
|
99410
99468
|
await init_skill_telemetry();
|
|
99411
99469
|
await init_policy_enforcer();
|
|
99412
99470
|
init_room_protocol();
|
|
99413
|
-
VERSION = true ? "0.23.
|
|
99471
|
+
VERSION = true ? "0.23.33" : "0.0.0-dev";
|
|
99414
99472
|
}
|
|
99415
99473
|
});
|
|
99416
99474
|
await init_index();
|
|
@@ -135814,7 +135872,7 @@ async function main() {
|
|
|
135814
135872
|
"[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"
|
|
135815
135873
|
);
|
|
135816
135874
|
}
|
|
135817
|
-
logLine(`[bridge] version: ${true ? "0.8.
|
|
135875
|
+
logLine(`[bridge] version: ${true ? "0.8.6" : "dev"}`);
|
|
135818
135876
|
logLine(`[bridge] data dir: ${cfg.dataDir} (${cfg.dataDirSource})`);
|
|
135819
135877
|
logLine(`[bridge] workspace: ${cfg.workspaceDir} \xB7 permissions: ${cfg.permissionMode} \xB7 enclave dir fenced`);
|
|
135820
135878
|
if (cfg.armRoom) {
|
|
@@ -135846,7 +135904,7 @@ async function main() {
|
|
|
135846
135904
|
// its default would render "@agentvault/agentvault@0.7.x" — the wrong
|
|
135847
135905
|
// package name attached to the bridge's version number, which is worse
|
|
135848
135906
|
// than either alone.
|
|
135849
|
-
clientVersion: `@agentvault/claude-bridge@${true ? "0.8.
|
|
135907
|
+
clientVersion: `@agentvault/claude-bridge@${true ? "0.8.6" : "dev"}`
|
|
135850
135908
|
});
|
|
135851
135909
|
const agentSystemPrompt = cfg.systemPrompt ?? `You are ${cfg.agentName}, an AI agent on AgentVault. You talk with your owner in 1:1 direct messages and collaborate with other agents in shared rooms. That is your identity \u2014 introduce yourself by that name and do not claim to be any other agent. To speak, call the say tool. In a 1:1 with your owner, reply to what they say. In a room you see every message \u2014 call say only when you have something worth adding, and otherwise stay silent. Keep messages concise.`;
|
|
135852
135910
|
const deviceJwt = () => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agentvault/claude-bridge",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.6",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "AgentVault Claude Bridge — daemon for bridging a Claude agent into secure E2E-encrypted AgentVault 1:1 direct messages and rooms.",
|
|
6
6
|
"main": "dist/index.js",
|