@agentvault/agentvault 0.23.8 → 0.23.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/channel.d.ts +41 -0
- package/dist/channel.d.ts.map +1 -1
- package/dist/cli.js +118 -4
- package/dist/cli.js.map +3 -3
- package/dist/index.js +118 -4
- package/dist/index.js.map +3 -3
- package/openclaw.plugin.json +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -64792,7 +64792,7 @@ var init_channel = __esm({
|
|
|
64792
64792
|
*/
|
|
64793
64793
|
sendActivitySpan(spanData) {
|
|
64794
64794
|
if (!this._ws || this._ws.readyState !== WebSocket.OPEN) return;
|
|
64795
|
-
const pluginVersion = true ? "0.23.
|
|
64795
|
+
const pluginVersion = true ? "0.23.10" : "0.0.0-dev";
|
|
64796
64796
|
const agentName = this.config.agentName ?? "Agent";
|
|
64797
64797
|
const resource = {
|
|
64798
64798
|
"service.name": "agentvault-agent",
|
|
@@ -65033,10 +65033,120 @@ var init_channel = __esm({
|
|
|
65033
65033
|
this._sessions.delete(convId);
|
|
65034
65034
|
delete this._persisted.sessions[convId];
|
|
65035
65035
|
}
|
|
65036
|
+
if (room.mlsGroupId) {
|
|
65037
|
+
try {
|
|
65038
|
+
await deleteMlsState(this.config.dataDir, room.mlsGroupId);
|
|
65039
|
+
} catch {
|
|
65040
|
+
}
|
|
65041
|
+
}
|
|
65042
|
+
this._mlsGroups.delete(roomId);
|
|
65036
65043
|
delete this._persisted.rooms[roomId];
|
|
65037
65044
|
await this._persistState();
|
|
65038
65045
|
this.emit("room_left", { roomId });
|
|
65039
65046
|
}
|
|
65047
|
+
/**
|
|
65048
|
+
* #629 recurrence fix — reconcile local room state against the server on
|
|
65049
|
+
* connect.
|
|
65050
|
+
*
|
|
65051
|
+
* On disband the server marks each member ``"left"`` and sets
|
|
65052
|
+
* ``room.status="disbanded"`` but sends NO WS event to the agent's bridge, so a
|
|
65053
|
+
* disbanded/left room lingers in local state and replays dead MLS commit
|
|
65054
|
+
* history on every reconnect ("Desired gen in the past" / "invalid ghash tag").
|
|
65055
|
+
* ``GET /rooms`` returns ONLY active rooms the caller is a member of, so any
|
|
65056
|
+
* locally-persisted room ABSENT from it is terminal — prune its MLS state
|
|
65057
|
+
* (file + in-memory group, keyed by roomId), its sessions, and the room entry.
|
|
65058
|
+
*
|
|
65059
|
+
* Fail-safe: a failed fetch / non-ok / non-array response prunes NOTHING, so a
|
|
65060
|
+
* transient error can never over-prune a live room.
|
|
65061
|
+
*/
|
|
65062
|
+
async _reconcileRoomsWithServer() {
|
|
65063
|
+
const local = this._persisted?.rooms;
|
|
65064
|
+
if (!local || Object.keys(local).length === 0) return;
|
|
65065
|
+
if (!this._deviceJwt) return;
|
|
65066
|
+
let activeIds;
|
|
65067
|
+
try {
|
|
65068
|
+
const res = await fetch(`${this.config.apiUrl}/api/v1/rooms`, {
|
|
65069
|
+
headers: { Authorization: `Bearer ${this._deviceJwt}` }
|
|
65070
|
+
});
|
|
65071
|
+
if (!res.ok) return;
|
|
65072
|
+
const list = await res.json();
|
|
65073
|
+
if (!Array.isArray(list)) return;
|
|
65074
|
+
activeIds = new Set(
|
|
65075
|
+
list.map((r2) => r2?.id).filter((id) => !!id)
|
|
65076
|
+
);
|
|
65077
|
+
} catch (err) {
|
|
65078
|
+
console.warn(
|
|
65079
|
+
`[SecureChannel] room reconcile skipped (fetch failed, pruning nothing): ${err instanceof Error ? err.message : String(err)}`
|
|
65080
|
+
);
|
|
65081
|
+
return;
|
|
65082
|
+
}
|
|
65083
|
+
const stale = Object.keys(local).filter((rid) => !activeIds.has(rid));
|
|
65084
|
+
if (stale.length === 0) return;
|
|
65085
|
+
for (const rid of stale) {
|
|
65086
|
+
const room = local[rid];
|
|
65087
|
+
if (room?.mlsGroupId) {
|
|
65088
|
+
try {
|
|
65089
|
+
await deleteMlsState(this.config.dataDir, room.mlsGroupId);
|
|
65090
|
+
} catch {
|
|
65091
|
+
}
|
|
65092
|
+
}
|
|
65093
|
+
this._mlsGroups.delete(rid);
|
|
65094
|
+
for (const convId of room?.conversationIds ?? []) {
|
|
65095
|
+
this._sessions.delete(convId);
|
|
65096
|
+
if (this._persisted?.sessions) delete this._persisted.sessions[convId];
|
|
65097
|
+
}
|
|
65098
|
+
delete local[rid];
|
|
65099
|
+
}
|
|
65100
|
+
await this._persistState();
|
|
65101
|
+
console.log(
|
|
65102
|
+
`[SecureChannel] Room reconcile: pruned ${stale.length} disbanded/left room(s) from local state (${stale.map((r2) => r2.slice(0, 8)).join(", ")})`
|
|
65103
|
+
);
|
|
65104
|
+
this.emit("rooms_reconciled", { pruned: stale });
|
|
65105
|
+
}
|
|
65106
|
+
/**
|
|
65107
|
+
* Handle an in-band `{event:"error"}` frame from the server.
|
|
65108
|
+
*
|
|
65109
|
+
* This is an APPLICATION-level error about one resource — it is NOT a
|
|
65110
|
+
* transport fault, and must never be treated as one. When the error names a
|
|
65111
|
+
* dead resource, the correct response is to PRUNE that resource; recycling
|
|
65112
|
+
* the connection would just replay the same doomed write.
|
|
65113
|
+
*
|
|
65114
|
+
* `conversation deleted` (#460/#481) is the server refusing a write to a
|
|
65115
|
+
* shared 1:1 MLS group whose conversations are all closed/deleted. It carries
|
|
65116
|
+
* `group_id` for exactly this purpose. Without the prune, `_persisted.mlsGroups`
|
|
65117
|
+
* is append-only and the 1:1 send path fans out to every entry, so the dead
|
|
65118
|
+
* group takes a rejected write on every message for the life of the agent
|
|
65119
|
+
* (loopita: group c1b1e11a, closed 2026-07-22, still bouncing 3 days later).
|
|
65120
|
+
*
|
|
65121
|
+
* Deliberately NARROW — it prunes only on this exact detail AND only when
|
|
65122
|
+
* `group_id` matches a persisted shared 1:1 group. Unknown ids and other
|
|
65123
|
+
* details prune nothing, so a server-side wording change or a room/A2A group
|
|
65124
|
+
* can never cost us live MLS state. Safe because `closed`/`deleted` are
|
|
65125
|
+
* terminal server-side, and a genuinely new group re-arrives via Welcome.
|
|
65126
|
+
*
|
|
65127
|
+
* Mirrors the #629 room prune: MLS state file, in-memory group, persisted
|
|
65128
|
+
* entry, then persist.
|
|
65129
|
+
*/
|
|
65130
|
+
async _handleServerError(payload) {
|
|
65131
|
+
if (payload?.detail !== "conversation deleted") return;
|
|
65132
|
+
const mlsGroupId = payload.group_id;
|
|
65133
|
+
if (!mlsGroupId) return;
|
|
65134
|
+
const groups = this._persisted?.mlsGroups;
|
|
65135
|
+
if (!groups) return;
|
|
65136
|
+
const gid = Object.keys(groups).find((k2) => groups[k2]?.mlsGroupId === mlsGroupId);
|
|
65137
|
+
if (!gid) return;
|
|
65138
|
+
try {
|
|
65139
|
+
await deleteMlsState(this.config.dataDir, mlsGroupId);
|
|
65140
|
+
} catch {
|
|
65141
|
+
}
|
|
65142
|
+
this._mlsGroups.delete(`1to1-group:${gid}`);
|
|
65143
|
+
delete groups[gid];
|
|
65144
|
+
await this._persistState();
|
|
65145
|
+
console.log(
|
|
65146
|
+
`[SecureChannel] Pruned dead shared 1:1 group ${gid.slice(0, 8)} (${mlsGroupId.slice(0, 8)}) \u2014 server reports its conversation deleted`
|
|
65147
|
+
);
|
|
65148
|
+
this.emit("dm_group_pruned", { conversationGroupId: gid, mlsGroupId });
|
|
65149
|
+
}
|
|
65040
65150
|
/**
|
|
65041
65151
|
* Return info for all joined rooms.
|
|
65042
65152
|
*/
|
|
@@ -66387,6 +66497,9 @@ var init_channel = __esm({
|
|
|
66387
66497
|
await this._pullDrDeliveryQueue();
|
|
66388
66498
|
await this._flushOutboundQueue();
|
|
66389
66499
|
this._setState("ready");
|
|
66500
|
+
void this._reconcileRoomsWithServer().catch(
|
|
66501
|
+
(err) => console.warn(`[SecureChannel] room reconcile failed (ignored): ${err instanceof Error ? err.message : String(err)}`)
|
|
66502
|
+
);
|
|
66390
66503
|
if (this.config.enableScanning) {
|
|
66391
66504
|
this._scanEngine = new ScanEngine();
|
|
66392
66505
|
await this._fetchScanRules();
|
|
@@ -66409,7 +66522,7 @@ var init_channel = __esm({
|
|
|
66409
66522
|
agentVersion: this.config.agentVersion ?? "0.0.0",
|
|
66410
66523
|
// __AV_VERSION__ is injected by esbuild from package.json at build time.
|
|
66411
66524
|
// Falls back to "0.0.0-dev" in non-bundled contexts (tests).
|
|
66412
|
-
pluginVersion: true ? "0.23.
|
|
66525
|
+
pluginVersion: true ? "0.23.10" : "0.0.0-dev"
|
|
66413
66526
|
});
|
|
66414
66527
|
this._telemetryReporter.startAutoFlush(3e4);
|
|
66415
66528
|
}
|
|
@@ -66727,7 +66840,7 @@ var init_channel = __esm({
|
|
|
66727
66840
|
agentVersion: this.config.agentVersion ?? "0.0.0",
|
|
66728
66841
|
// __AV_VERSION__ is injected by esbuild from package.json at build time.
|
|
66729
66842
|
// Falls back to "0.0.0-dev" in non-bundled contexts (tests).
|
|
66730
|
-
pluginVersion: true ? "0.23.
|
|
66843
|
+
pluginVersion: true ? "0.23.10" : "0.0.0-dev"
|
|
66731
66844
|
});
|
|
66732
66845
|
this._telemetryReporter.startAutoFlush(3e4);
|
|
66733
66846
|
}
|
|
@@ -67037,6 +67150,7 @@ var init_channel = __esm({
|
|
|
67037
67150
|
if (data.event === "error") {
|
|
67038
67151
|
const detail = data.data?.detail || data.detail || "Unknown server error";
|
|
67039
67152
|
console.error(`[SecureChannel] Server error: ${detail}`);
|
|
67153
|
+
await this._handleServerError(data.data || data);
|
|
67040
67154
|
this.emit("error", new Error(`Server: ${detail}`));
|
|
67041
67155
|
}
|
|
67042
67156
|
if (data.event === "a2a_message_mls") {
|
|
@@ -96941,7 +97055,7 @@ var init_index = __esm({
|
|
|
96941
97055
|
init_skill_invoker();
|
|
96942
97056
|
await init_skill_telemetry();
|
|
96943
97057
|
await init_policy_enforcer();
|
|
96944
|
-
VERSION = true ? "0.23.
|
|
97058
|
+
VERSION = true ? "0.23.10" : "0.0.0-dev";
|
|
96945
97059
|
}
|
|
96946
97060
|
});
|
|
96947
97061
|
await init_index();
|