@agentvault/claude-bridge 0.7.11 → 0.7.12
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 +115 -5
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -64828,6 +64828,17 @@ var init_channel = __esm2({
|
|
|
64828
64828
|
_pendingPollTimer = null;
|
|
64829
64829
|
_syncMessageIds = null;
|
|
64830
64830
|
_deliveryHeartbeat = null;
|
|
64831
|
+
/**
|
|
64832
|
+
* How often to re-check the KeyPackage pool against the server (#826).
|
|
64833
|
+
*
|
|
64834
|
+
* KeyPackages expire after 7 days and, before this, only a reconnect
|
|
64835
|
+
* republished them — so an agent that simply stayed up ran to zero usable
|
|
64836
|
+
* and silently stopped accepting new MLS 1:1 conversations while looking
|
|
64837
|
+
* perfectly healthy. 6h gives ~28 attempts inside one lifetime, so a run of
|
|
64838
|
+
* transient failures cannot age the pool out. Cost is one GET per interval.
|
|
64839
|
+
*/
|
|
64840
|
+
static _KP_REPLENISH_INTERVAL_MS = 6 * 60 * 60 * 1e3;
|
|
64841
|
+
_kpReplenishTimer = null;
|
|
64831
64842
|
_a2aReconcileTimer = null;
|
|
64832
64843
|
_deliveryPulling = false;
|
|
64833
64844
|
_drDeliveryPulling = false;
|
|
@@ -65792,7 +65803,7 @@ var init_channel = __esm2({
|
|
|
65792
65803
|
*/
|
|
65793
65804
|
sendActivitySpan(spanData) {
|
|
65794
65805
|
if (!this._ws || this._ws.readyState !== WebSocket2.OPEN) return;
|
|
65795
|
-
const pluginVersion = true ? "0.23.
|
|
65806
|
+
const pluginVersion = true ? "0.23.21" : "0.0.0-dev";
|
|
65796
65807
|
const agentName = this.config.agentName ?? "Agent";
|
|
65797
65808
|
const resource = {
|
|
65798
65809
|
"service.name": "agentvault-agent",
|
|
@@ -67702,7 +67713,7 @@ var init_channel = __esm2({
|
|
|
67702
67713
|
agentVersion: this.config.agentVersion ?? "0.0.0",
|
|
67703
67714
|
// __AV_VERSION__ is injected by esbuild from package.json at build time.
|
|
67704
67715
|
// Falls back to "0.0.0-dev" in non-bundled contexts (tests).
|
|
67705
|
-
pluginVersion: true ? "0.23.
|
|
67716
|
+
pluginVersion: true ? "0.23.21" : "0.0.0-dev"
|
|
67706
67717
|
});
|
|
67707
67718
|
this._telemetryReporter.startAutoFlush(3e4);
|
|
67708
67719
|
}
|
|
@@ -67711,6 +67722,7 @@ var init_channel = __esm2({
|
|
|
67711
67722
|
console.warn("[SecureChannel] A2A channel sync on connect failed:", err);
|
|
67712
67723
|
});
|
|
67713
67724
|
await this._ensureKpPoolPublished();
|
|
67725
|
+
this._startKpReplenishTimer();
|
|
67714
67726
|
this._pullDeliveryQueue().catch((err) => {
|
|
67715
67727
|
console.warn("[SecureChannel] Initial delivery pull failed:", err);
|
|
67716
67728
|
});
|
|
@@ -68025,7 +68037,7 @@ var init_channel = __esm2({
|
|
|
68025
68037
|
agentVersion: this.config.agentVersion ?? "0.0.0",
|
|
68026
68038
|
// __AV_VERSION__ is injected by esbuild from package.json at build time.
|
|
68027
68039
|
// Falls back to "0.0.0-dev" in non-bundled contexts (tests).
|
|
68028
|
-
pluginVersion: true ? "0.23.
|
|
68040
|
+
pluginVersion: true ? "0.23.21" : "0.0.0-dev"
|
|
68029
68041
|
});
|
|
68030
68042
|
this._telemetryReporter.startAutoFlush(3e4);
|
|
68031
68043
|
}
|
|
@@ -68368,6 +68380,7 @@ var init_channel = __esm2({
|
|
|
68368
68380
|
this._deliveryHeartbeat = null;
|
|
68369
68381
|
}
|
|
68370
68382
|
this._stopA2aReconcileTimer();
|
|
68383
|
+
this._stopKpReplenishTimer();
|
|
68371
68384
|
if (this._stopped) return;
|
|
68372
68385
|
this._setState("disconnected");
|
|
68373
68386
|
this._scheduleReconnect();
|
|
@@ -69761,6 +69774,103 @@ ${messageText}`;
|
|
|
69761
69774
|
this._kpPoolFilling = false;
|
|
69762
69775
|
}
|
|
69763
69776
|
}
|
|
69777
|
+
/** Start the periodic KeyPackage replenish (#826). Idempotent. */
|
|
69778
|
+
_startKpReplenishTimer() {
|
|
69779
|
+
this._stopKpReplenishTimer();
|
|
69780
|
+
this._kpReplenishTimer = setInterval(() => {
|
|
69781
|
+
void this._replenishKpPoolFromServer();
|
|
69782
|
+
}, _SecureChannel._KP_REPLENISH_INTERVAL_MS);
|
|
69783
|
+
}
|
|
69784
|
+
_stopKpReplenishTimer() {
|
|
69785
|
+
if (this._kpReplenishTimer) {
|
|
69786
|
+
clearInterval(this._kpReplenishTimer);
|
|
69787
|
+
this._kpReplenishTimer = null;
|
|
69788
|
+
}
|
|
69789
|
+
}
|
|
69790
|
+
/**
|
|
69791
|
+
* The server's EXPIRY-AWARE usable KeyPackage count, or null when unknown.
|
|
69792
|
+
*
|
|
69793
|
+
* `count_unconsumed` filters `expires_at > utcnow()`, which is the only count
|
|
69794
|
+
* that reflects what a peer can actually fetch. Returns null (not 0) on any
|
|
69795
|
+
* failure so callers can tell "server says empty" from "we could not ask" —
|
|
69796
|
+
* guessing 0 here would publish a fresh pool on every transient 503.
|
|
69797
|
+
*/
|
|
69798
|
+
async _fetchServerKpCount() {
|
|
69799
|
+
try {
|
|
69800
|
+
const res = await fetch(
|
|
69801
|
+
`${this.config.apiUrl}/api/v1/mls/key-packages/count?device_id=${this._deviceId}`,
|
|
69802
|
+
{ headers: { Authorization: `Bearer ${this._deviceJwt}` } }
|
|
69803
|
+
);
|
|
69804
|
+
if (!res.ok) return null;
|
|
69805
|
+
const body = await res.json();
|
|
69806
|
+
const n22 = body?.count;
|
|
69807
|
+
return typeof n22 === "number" && Number.isFinite(n22) ? n22 : null;
|
|
69808
|
+
} catch {
|
|
69809
|
+
return null;
|
|
69810
|
+
}
|
|
69811
|
+
}
|
|
69812
|
+
/**
|
|
69813
|
+
* Top the pool up against the SERVER's count (#826).
|
|
69814
|
+
*
|
|
69815
|
+
* ⚠️ DO NOT replace this with a periodic call to `_ensureKpPoolPublished()`.
|
|
69816
|
+
* That function early-returns on `_pendingKpBundles.length >= _KP_POOL_TARGET`,
|
|
69817
|
+
* and that array holds PRIVATE bundles which never expire locally — so on an
|
|
69818
|
+
* agent that has been connected longer than the KeyPackage lifetime it is
|
|
69819
|
+
* still full while the server has zero usable. Measured on prod 2026-08-09:
|
|
69820
|
+
* cortina and eclaude were online and green with 10 unconsumed / 0 usable,
|
|
69821
|
+
* unable to accept any new MLS 1:1. A timer over the local guard would have
|
|
69822
|
+
* run forever and changed nothing.
|
|
69823
|
+
*
|
|
69824
|
+
* Publishes only the shortfall, and never throws — this runs on a timer and
|
|
69825
|
+
* must not be able to take the channel down.
|
|
69826
|
+
*/
|
|
69827
|
+
async _replenishKpPoolFromServer() {
|
|
69828
|
+
try {
|
|
69829
|
+
if (this._kpPoolFilling) return;
|
|
69830
|
+
const usable = await this._fetchServerKpCount();
|
|
69831
|
+
if (usable === null) return;
|
|
69832
|
+
const shortfall = _SecureChannel._KP_POOL_TARGET - usable;
|
|
69833
|
+
if (shortfall <= 0) return;
|
|
69834
|
+
this._kpPoolFilling = true;
|
|
69835
|
+
try {
|
|
69836
|
+
const identity = new TextEncoder().encode(this._deviceId);
|
|
69837
|
+
let published = 0;
|
|
69838
|
+
for (let i2 = 0; i2 < shortfall; i2++) {
|
|
69839
|
+
const mlsMgr = new MLSGroupManager();
|
|
69840
|
+
const kp = await mlsMgr.generateKeyPackage(identity);
|
|
69841
|
+
const kpHex = Buffer.from(
|
|
69842
|
+
MLSGroupManager.serializeKeyPackage(kp.publicPackage)
|
|
69843
|
+
).toString("hex");
|
|
69844
|
+
const res = await fetch(`${this.config.apiUrl}/api/v1/mls/key-packages`, {
|
|
69845
|
+
method: "POST",
|
|
69846
|
+
headers: {
|
|
69847
|
+
Authorization: `Bearer ${this._deviceJwt}`,
|
|
69848
|
+
"Content-Type": "application/json"
|
|
69849
|
+
},
|
|
69850
|
+
body: JSON.stringify({ key_package: kpHex })
|
|
69851
|
+
});
|
|
69852
|
+
if (!res.ok) {
|
|
69853
|
+
console.warn(
|
|
69854
|
+
`[SecureChannel] KeyPackage replenish rejected (status ${res.status}) after ${published}/${shortfall}`
|
|
69855
|
+
);
|
|
69856
|
+
break;
|
|
69857
|
+
}
|
|
69858
|
+
this._recordPublishedKp(kp);
|
|
69859
|
+
if (!this._mlsKeyPackage) this._mlsKeyPackage = kp;
|
|
69860
|
+
published++;
|
|
69861
|
+
}
|
|
69862
|
+
if (published > 0) {
|
|
69863
|
+
console.log(
|
|
69864
|
+
`[SecureChannel] MLS KeyPackage pool replenished (${published} new; server had ${usable}/${_SecureChannel._KP_POOL_TARGET} usable)`
|
|
69865
|
+
);
|
|
69866
|
+
}
|
|
69867
|
+
} finally {
|
|
69868
|
+
this._kpPoolFilling = false;
|
|
69869
|
+
}
|
|
69870
|
+
} catch (err) {
|
|
69871
|
+
console.warn("[SecureChannel] KeyPackage replenish failed:", err);
|
|
69872
|
+
}
|
|
69873
|
+
}
|
|
69764
69874
|
async _handleMlsWelcome(data) {
|
|
69765
69875
|
const groupId = data.group_id;
|
|
69766
69876
|
const conversationId = data.conversation_id;
|
|
@@ -97914,7 +98024,7 @@ var init_index = __esm2({
|
|
|
97914
98024
|
init_skill_invoker();
|
|
97915
98025
|
await init_skill_telemetry();
|
|
97916
98026
|
await init_policy_enforcer();
|
|
97917
|
-
VERSION = true ? "0.23.
|
|
98027
|
+
VERSION = true ? "0.23.21" : "0.0.0-dev";
|
|
97918
98028
|
}
|
|
97919
98029
|
});
|
|
97920
98030
|
await init_index();
|
|
@@ -134268,7 +134378,7 @@ async function main() {
|
|
|
134268
134378
|
"[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"
|
|
134269
134379
|
);
|
|
134270
134380
|
}
|
|
134271
|
-
logLine(`[bridge] version: ${true ? "0.7.
|
|
134381
|
+
logLine(`[bridge] version: ${true ? "0.7.12" : "dev"}`);
|
|
134272
134382
|
logLine(`[bridge] data dir: ${cfg.dataDir} (${cfg.dataDirSource})`);
|
|
134273
134383
|
logLine(`[bridge] workspace: ${cfg.workspaceDir} \xB7 permissions: ${cfg.permissionMode} \xB7 enclave dir fenced`);
|
|
134274
134384
|
if (cfg.armRoom) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agentvault/claude-bridge",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.12",
|
|
4
4
|
"type": "module",
|
|
5
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",
|