@agentvault/claude-bridge 0.6.1 → 0.6.3
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 +108 -17
- package/dist/session.d.ts +6 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -65555,7 +65555,7 @@ var init_channel = __esm2({
|
|
|
65555
65555
|
*/
|
|
65556
65556
|
sendActivitySpan(spanData) {
|
|
65557
65557
|
if (!this._ws || this._ws.readyState !== WebSocket2.OPEN) return;
|
|
65558
|
-
const pluginVersion = true ? "0.23.
|
|
65558
|
+
const pluginVersion = true ? "0.23.9" : "0.0.0-dev";
|
|
65559
65559
|
const agentName = this.config.agentName ?? "Agent";
|
|
65560
65560
|
const resource = {
|
|
65561
65561
|
"service.name": "agentvault-agent",
|
|
@@ -65796,10 +65796,76 @@ var init_channel = __esm2({
|
|
|
65796
65796
|
this._sessions.delete(convId);
|
|
65797
65797
|
delete this._persisted.sessions[convId];
|
|
65798
65798
|
}
|
|
65799
|
+
if (room.mlsGroupId) {
|
|
65800
|
+
try {
|
|
65801
|
+
await deleteMlsState(this.config.dataDir, room.mlsGroupId);
|
|
65802
|
+
} catch {
|
|
65803
|
+
}
|
|
65804
|
+
}
|
|
65805
|
+
this._mlsGroups.delete(roomId);
|
|
65799
65806
|
delete this._persisted.rooms[roomId];
|
|
65800
65807
|
await this._persistState();
|
|
65801
65808
|
this.emit("room_left", { roomId });
|
|
65802
65809
|
}
|
|
65810
|
+
/**
|
|
65811
|
+
* #629 recurrence fix — reconcile local room state against the server on
|
|
65812
|
+
* connect.
|
|
65813
|
+
*
|
|
65814
|
+
* On disband the server marks each member ``"left"`` and sets
|
|
65815
|
+
* ``room.status="disbanded"`` but sends NO WS event to the agent's bridge, so a
|
|
65816
|
+
* disbanded/left room lingers in local state and replays dead MLS commit
|
|
65817
|
+
* history on every reconnect ("Desired gen in the past" / "invalid ghash tag").
|
|
65818
|
+
* ``GET /rooms`` returns ONLY active rooms the caller is a member of, so any
|
|
65819
|
+
* locally-persisted room ABSENT from it is terminal — prune its MLS state
|
|
65820
|
+
* (file + in-memory group, keyed by roomId), its sessions, and the room entry.
|
|
65821
|
+
*
|
|
65822
|
+
* Fail-safe: a failed fetch / non-ok / non-array response prunes NOTHING, so a
|
|
65823
|
+
* transient error can never over-prune a live room.
|
|
65824
|
+
*/
|
|
65825
|
+
async _reconcileRoomsWithServer() {
|
|
65826
|
+
const local = this._persisted?.rooms;
|
|
65827
|
+
if (!local || Object.keys(local).length === 0) return;
|
|
65828
|
+
if (!this._deviceJwt) return;
|
|
65829
|
+
let activeIds;
|
|
65830
|
+
try {
|
|
65831
|
+
const res = await fetch(`${this.config.apiUrl}/api/v1/rooms`, {
|
|
65832
|
+
headers: { Authorization: `Bearer ${this._deviceJwt}` }
|
|
65833
|
+
});
|
|
65834
|
+
if (!res.ok) return;
|
|
65835
|
+
const list = await res.json();
|
|
65836
|
+
if (!Array.isArray(list)) return;
|
|
65837
|
+
activeIds = new Set(
|
|
65838
|
+
list.map((r22) => r22?.id).filter((id) => !!id)
|
|
65839
|
+
);
|
|
65840
|
+
} catch (err) {
|
|
65841
|
+
console.warn(
|
|
65842
|
+
`[SecureChannel] room reconcile skipped (fetch failed, pruning nothing): ${err instanceof Error ? err.message : String(err)}`
|
|
65843
|
+
);
|
|
65844
|
+
return;
|
|
65845
|
+
}
|
|
65846
|
+
const stale = Object.keys(local).filter((rid) => !activeIds.has(rid));
|
|
65847
|
+
if (stale.length === 0) return;
|
|
65848
|
+
for (const rid of stale) {
|
|
65849
|
+
const room = local[rid];
|
|
65850
|
+
if (room?.mlsGroupId) {
|
|
65851
|
+
try {
|
|
65852
|
+
await deleteMlsState(this.config.dataDir, room.mlsGroupId);
|
|
65853
|
+
} catch {
|
|
65854
|
+
}
|
|
65855
|
+
}
|
|
65856
|
+
this._mlsGroups.delete(rid);
|
|
65857
|
+
for (const convId of room?.conversationIds ?? []) {
|
|
65858
|
+
this._sessions.delete(convId);
|
|
65859
|
+
if (this._persisted?.sessions) delete this._persisted.sessions[convId];
|
|
65860
|
+
}
|
|
65861
|
+
delete local[rid];
|
|
65862
|
+
}
|
|
65863
|
+
await this._persistState();
|
|
65864
|
+
console.log(
|
|
65865
|
+
`[SecureChannel] Room reconcile: pruned ${stale.length} disbanded/left room(s) from local state (${stale.map((r22) => r22.slice(0, 8)).join(", ")})`
|
|
65866
|
+
);
|
|
65867
|
+
this.emit("rooms_reconciled", { pruned: stale });
|
|
65868
|
+
}
|
|
65803
65869
|
/**
|
|
65804
65870
|
* Return info for all joined rooms.
|
|
65805
65871
|
*/
|
|
@@ -67150,6 +67216,9 @@ var init_channel = __esm2({
|
|
|
67150
67216
|
await this._pullDrDeliveryQueue();
|
|
67151
67217
|
await this._flushOutboundQueue();
|
|
67152
67218
|
this._setState("ready");
|
|
67219
|
+
void this._reconcileRoomsWithServer().catch(
|
|
67220
|
+
(err) => console.warn(`[SecureChannel] room reconcile failed (ignored): ${err instanceof Error ? err.message : String(err)}`)
|
|
67221
|
+
);
|
|
67153
67222
|
if (this.config.enableScanning) {
|
|
67154
67223
|
this._scanEngine = new ScanEngine();
|
|
67155
67224
|
await this._fetchScanRules();
|
|
@@ -67172,7 +67241,7 @@ var init_channel = __esm2({
|
|
|
67172
67241
|
agentVersion: this.config.agentVersion ?? "0.0.0",
|
|
67173
67242
|
// __AV_VERSION__ is injected by esbuild from package.json at build time.
|
|
67174
67243
|
// Falls back to "0.0.0-dev" in non-bundled contexts (tests).
|
|
67175
|
-
pluginVersion: true ? "0.23.
|
|
67244
|
+
pluginVersion: true ? "0.23.9" : "0.0.0-dev"
|
|
67176
67245
|
});
|
|
67177
67246
|
this._telemetryReporter.startAutoFlush(3e4);
|
|
67178
67247
|
}
|
|
@@ -67490,7 +67559,7 @@ var init_channel = __esm2({
|
|
|
67490
67559
|
agentVersion: this.config.agentVersion ?? "0.0.0",
|
|
67491
67560
|
// __AV_VERSION__ is injected by esbuild from package.json at build time.
|
|
67492
67561
|
// Falls back to "0.0.0-dev" in non-bundled contexts (tests).
|
|
67493
|
-
pluginVersion: true ? "0.23.
|
|
67562
|
+
pluginVersion: true ? "0.23.9" : "0.0.0-dev"
|
|
67494
67563
|
});
|
|
67495
67564
|
this._telemetryReporter.startAutoFlush(3e4);
|
|
67496
67565
|
}
|
|
@@ -97268,7 +97337,7 @@ var init_index = __esm2({
|
|
|
97268
97337
|
init_skill_invoker();
|
|
97269
97338
|
await init_skill_telemetry();
|
|
97270
97339
|
await init_policy_enforcer();
|
|
97271
|
-
VERSION = true ? "0.23.
|
|
97340
|
+
VERSION = true ? "0.23.9" : "0.0.0-dev";
|
|
97272
97341
|
}
|
|
97273
97342
|
});
|
|
97274
97343
|
await init_index();
|
|
@@ -132545,6 +132614,12 @@ var PersistentClaudeSession = class {
|
|
|
132545
132614
|
currentReplyExpected = false;
|
|
132546
132615
|
saidThisTurn = false;
|
|
132547
132616
|
turnText = "";
|
|
132617
|
+
/** #630 drop-probe: did a `result` event arrive for the CURRENT turn? Reset per
|
|
132618
|
+
* turn in input(), set in the result block. Distinguishes a turn that never
|
|
132619
|
+
* reached a result boundary (the silent-drop prime suspect) from a healthy
|
|
132620
|
+
* #416 fallback delivery (which delivers via `void reply(...)` WITHOUT setting
|
|
132621
|
+
* saidThisTurn, so !saidThisTurn alone would false-flag it). */
|
|
132622
|
+
sawResultThisTurn = false;
|
|
132548
132623
|
/** In-process room MCP server — hoisted so buildSdkOptions can reference it. */
|
|
132549
132624
|
roomServer;
|
|
132550
132625
|
/** AbortController for the in-flight query(); abort() triggers it (queue timeout). */
|
|
@@ -132613,6 +132688,7 @@ var PersistentClaudeSession = class {
|
|
|
132613
132688
|
this.currentArmedGetter = item.armed ?? (() => false);
|
|
132614
132689
|
this.saidThisTurn = false;
|
|
132615
132690
|
this.turnText = "";
|
|
132691
|
+
this.sawResultThisTurn = false;
|
|
132616
132692
|
yield item.msg;
|
|
132617
132693
|
}
|
|
132618
132694
|
}
|
|
@@ -132732,20 +132808,35 @@ var PersistentClaudeSession = class {
|
|
|
132732
132808
|
prompt: this.input(),
|
|
132733
132809
|
options: sdkOptions
|
|
132734
132810
|
});
|
|
132735
|
-
|
|
132736
|
-
|
|
132737
|
-
|
|
132738
|
-
|
|
132739
|
-
|
|
132740
|
-
|
|
132741
|
-
|
|
132742
|
-
|
|
132743
|
-
|
|
132744
|
-
|
|
132745
|
-
|
|
132746
|
-
|
|
132811
|
+
try {
|
|
132812
|
+
for await (const m6 of q10) {
|
|
132813
|
+
if (m6.type === "assistant") {
|
|
132814
|
+
const blocks = m6.message?.content ?? [];
|
|
132815
|
+
const text = blocks.filter((b5) => b5.type === "text").map((b5) => b5.text ?? "").join("");
|
|
132816
|
+
if (text.trim()) {
|
|
132817
|
+
this.turnText += text;
|
|
132818
|
+
this.opts.onObserve?.(text);
|
|
132819
|
+
}
|
|
132820
|
+
} else if (m6.type === "result") {
|
|
132821
|
+
this.sawResultThisTurn = true;
|
|
132822
|
+
const reply = this.activeReply;
|
|
132823
|
+
if (this.currentReplyExpected && !this.saidThisTurn && this.turnText.trim()) {
|
|
132824
|
+
if (reply) {
|
|
132825
|
+
void reply(this.turnText);
|
|
132826
|
+
} else {
|
|
132827
|
+
console.error(
|
|
132828
|
+
`[drop-probe] BLOCKED at result: composed ${this.turnText.length} chars, reply expected but activeReply unset \u2014 reply DROPPED`
|
|
132829
|
+
);
|
|
132830
|
+
}
|
|
132831
|
+
}
|
|
132747
132832
|
}
|
|
132748
132833
|
}
|
|
132834
|
+
} finally {
|
|
132835
|
+
if (this.currentReplyExpected && !this.saidThisTurn && !this.sawResultThisTurn && this.turnText.trim()) {
|
|
132836
|
+
console.error(
|
|
132837
|
+
`[drop-probe] STREAM ENDED before result: composed ${this.turnText.length} chars, reply expected, said=false \u2014 reply DROPPED (no result event)`
|
|
132838
|
+
);
|
|
132839
|
+
}
|
|
132749
132840
|
}
|
|
132750
132841
|
}
|
|
132751
132842
|
};
|
|
@@ -133281,7 +133372,7 @@ async function main() {
|
|
|
133281
133372
|
"[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"
|
|
133282
133373
|
);
|
|
133283
133374
|
}
|
|
133284
|
-
console.error(`[bridge] version: ${true ? "0.6.
|
|
133375
|
+
console.error(`[bridge] version: ${true ? "0.6.3" : "dev"}`);
|
|
133285
133376
|
console.error(`[bridge] data dir: ${cfg.dataDir} (${cfg.dataDirSource})`);
|
|
133286
133377
|
console.error(`[bridge] workspace: ${cfg.workspaceDir} \xB7 permissions: ${cfg.permissionMode} \xB7 enclave dir fenced`);
|
|
133287
133378
|
if (cfg.armRoom) {
|
package/dist/session.d.ts
CHANGED
|
@@ -137,6 +137,12 @@ export declare class PersistentClaudeSession {
|
|
|
137
137
|
private currentReplyExpected;
|
|
138
138
|
private saidThisTurn;
|
|
139
139
|
private turnText;
|
|
140
|
+
/** #630 drop-probe: did a `result` event arrive for the CURRENT turn? Reset per
|
|
141
|
+
* turn in input(), set in the result block. Distinguishes a turn that never
|
|
142
|
+
* reached a result boundary (the silent-drop prime suspect) from a healthy
|
|
143
|
+
* #416 fallback delivery (which delivers via `void reply(...)` WITHOUT setting
|
|
144
|
+
* saidThisTurn, so !saidThisTurn alone would false-flag it). */
|
|
145
|
+
private sawResultThisTurn;
|
|
140
146
|
/** In-process room MCP server — hoisted so buildSdkOptions can reference it. */
|
|
141
147
|
private roomServer;
|
|
142
148
|
/** AbortController for the in-flight query(); abort() triggers it (queue timeout). */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agentvault/claude-bridge",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.3",
|
|
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",
|