@agentvault/claude-bridge 0.8.11 → 0.8.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 +46 -10
- package/dist/session.d.ts +5 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -64612,11 +64612,11 @@ var init_mls_kp_pool = __esm2({
|
|
|
64612
64612
|
}
|
|
64613
64613
|
});
|
|
64614
64614
|
function ownIdentity() {
|
|
64615
|
-
const v22 = true ? "0.23.
|
|
64615
|
+
const v22 = true ? "0.23.39" : FALLBACK;
|
|
64616
64616
|
return `${PACKAGE}@${v22}`;
|
|
64617
64617
|
}
|
|
64618
64618
|
function buildSha() {
|
|
64619
|
-
const raw = true ? "
|
|
64619
|
+
const raw = true ? "9982fc8-dirty" : "";
|
|
64620
64620
|
const cleaned = (raw ?? "").trim();
|
|
64621
64621
|
return !cleaned || cleaned === "unknown" ? null : cleaned;
|
|
64622
64622
|
}
|
|
@@ -65719,6 +65719,27 @@ var init_channel = __esm2({
|
|
|
65719
65719
|
* this process (GH #366). Cleared on (re)join so the next first message
|
|
65720
65720
|
* re-fetches the authoritative roster. Prevents per-message refetch storms. */
|
|
65721
65721
|
_roomRosterRefreshed = /* @__PURE__ */ new Set();
|
|
65722
|
+
/**
|
|
65723
|
+
* #1181: the last attachment saved per room, so the NEXT room turn can name
|
|
65724
|
+
* it. wren saved an un-mentioned file (no reply, #1107), was asked "@wren can
|
|
65725
|
+
* you read this file?" 14 s later, and answered "I don't see a file
|
|
65726
|
+
* attached" — the note lived only in the prior history line. Hermes defers
|
|
65727
|
+
* un-mentioned attachments and fetches on the next addressed turn (#1162);
|
|
65728
|
+
* this is the plugin's equivalent surface. In-memory: a restart forgets it,
|
|
65729
|
+
* which is the right default for "this file".
|
|
65730
|
+
*/
|
|
65731
|
+
_recentRoomAttachments = /* @__PURE__ */ new Map();
|
|
65732
|
+
static RECENT_ROOM_ATTACHMENT_MS = 10 * 60 * 1e3;
|
|
65733
|
+
/** #1181: prefix a room turn that carries no attachment with the one saved in this room recently. */
|
|
65734
|
+
_withRecentRoomAttachmentNote(roomId, text) {
|
|
65735
|
+
const recent = this._recentRoomAttachments.get(roomId);
|
|
65736
|
+
if (!recent) return text;
|
|
65737
|
+
const ageMs = Date.now() - recent.at;
|
|
65738
|
+
if (ageMs > _SecureChannel.RECENT_ROOM_ATTACHMENT_MS) return text;
|
|
65739
|
+
return `[Most recent file in this room: ${recent.filePath} (${recent.name}, received ${Math.round(ageMs / 1e3)}s ago). If this message refers to "the file" or "this file", it means that one \u2014 use your Read tool on it.]
|
|
65740
|
+
|
|
65741
|
+
${text}`;
|
|
65742
|
+
}
|
|
65722
65743
|
/** In-flight roster-refresh promises (per room) — dedup concurrent refreshes. */
|
|
65723
65744
|
_roomRosterRefreshInFlight = /* @__PURE__ */ new Map();
|
|
65724
65745
|
/** Dedup buffer for A2A message IDs (prevents double-delivery via direct + Redis) */
|
|
@@ -66814,7 +66835,7 @@ var init_channel = __esm2({
|
|
|
66814
66835
|
*/
|
|
66815
66836
|
sendActivitySpan(spanData) {
|
|
66816
66837
|
if (!this._ws || this._ws.readyState !== WebSocket2.OPEN) return;
|
|
66817
|
-
const pluginVersion = true ? "0.23.
|
|
66838
|
+
const pluginVersion = true ? "0.23.39" : "0.0.0-dev";
|
|
66818
66839
|
const agentName = this.config.agentName ?? "Agent";
|
|
66819
66840
|
const resource = {
|
|
66820
66841
|
"service.name": "agentvault-agent",
|
|
@@ -68752,7 +68773,7 @@ var init_channel = __esm2({
|
|
|
68752
68773
|
agentVersion: this.config.agentVersion ?? "0.0.0",
|
|
68753
68774
|
// __AV_VERSION__ is injected by esbuild from package.json at build time.
|
|
68754
68775
|
// Falls back to "0.0.0-dev" in non-bundled contexts (tests).
|
|
68755
|
-
pluginVersion: true ? "0.23.
|
|
68776
|
+
pluginVersion: true ? "0.23.39" : "0.0.0-dev"
|
|
68756
68777
|
});
|
|
68757
68778
|
this._telemetryReporter.startAutoFlush(3e4);
|
|
68758
68779
|
}
|
|
@@ -69076,7 +69097,7 @@ var init_channel = __esm2({
|
|
|
69076
69097
|
agentVersion: this.config.agentVersion ?? "0.0.0",
|
|
69077
69098
|
// __AV_VERSION__ is injected by esbuild from package.json at build time.
|
|
69078
69099
|
// Falls back to "0.0.0-dev" in non-bundled contexts (tests).
|
|
69079
|
-
pluginVersion: true ? "0.23.
|
|
69100
|
+
pluginVersion: true ? "0.23.39" : "0.0.0-dev"
|
|
69080
69101
|
});
|
|
69081
69102
|
this._telemetryReporter.startAutoFlush(3e4);
|
|
69082
69103
|
}
|
|
@@ -69849,12 +69870,13 @@ ${messageText}`;
|
|
|
69849
69870
|
* Returns the text unchanged when there is no attachment or the fetch fails —
|
|
69850
69871
|
* but a failure is LOGGED and announced in the text, never silent.
|
|
69851
69872
|
*/
|
|
69852
|
-
async _augmentWithAttachment(attachmentInfo, baseText) {
|
|
69873
|
+
async _augmentWithAttachment(attachmentInfo, baseText, roomId) {
|
|
69853
69874
|
if (!attachmentInfo) return baseText;
|
|
69854
69875
|
try {
|
|
69855
69876
|
const { filePath, decrypted } = await this._downloadAndDecryptAttachment(attachmentInfo);
|
|
69856
69877
|
const mime = String(attachmentInfo.mime ?? "application/octet-stream");
|
|
69857
69878
|
const name = String(attachmentInfo.filename ?? "attachment");
|
|
69879
|
+
if (roomId) this._recentRoomAttachments.set(roomId, { filePath, name, at: Date.now() });
|
|
69858
69880
|
const textMimes = ["text/", "application/json", "application/xml", "application/csv"];
|
|
69859
69881
|
if (textMimes.some((m22) => mime.startsWith(m22))) {
|
|
69860
69882
|
const content = new TextDecoder().decode(decrypted);
|
|
@@ -70484,7 +70506,9 @@ ${baseText}`;
|
|
|
70484
70506
|
}
|
|
70485
70507
|
}
|
|
70486
70508
|
if (roomAttachment) {
|
|
70487
|
-
messageText = await this._augmentWithAttachment(roomAttachment, messageText);
|
|
70509
|
+
messageText = await this._augmentWithAttachment(roomAttachment, messageText, resolvedRoomId);
|
|
70510
|
+
} else {
|
|
70511
|
+
messageText = this._withRecentRoomAttachmentNote(resolvedRoomId, messageText);
|
|
70488
70512
|
}
|
|
70489
70513
|
const roomMembers = this._persisted?.rooms?.[resolvedRoomId]?.members ?? [];
|
|
70490
70514
|
const senderMember = roomMembers.find((m22) => m22.deviceId === senderDeviceId);
|
|
@@ -99526,7 +99550,7 @@ var init_index = __esm2({
|
|
|
99526
99550
|
await init_skill_telemetry();
|
|
99527
99551
|
await init_policy_enforcer();
|
|
99528
99552
|
init_room_protocol();
|
|
99529
|
-
VERSION = true ? "0.23.
|
|
99553
|
+
VERSION = true ? "0.23.39" : "0.0.0-dev";
|
|
99530
99554
|
}
|
|
99531
99555
|
});
|
|
99532
99556
|
await init_index();
|
|
@@ -134888,6 +134912,11 @@ var PersistentClaudeSession = class {
|
|
|
134888
134912
|
* which also prevents agent↔agent reply loops. Tool access is unaffected: it
|
|
134889
134913
|
* stays gated on currentAutoReply (owner DM) OR currentArmedGetter (armed room). */
|
|
134890
134914
|
currentReplyExpected = false;
|
|
134915
|
+
/** #1180: whether the say tool may deliver on this turn. Rooms pass an explicit
|
|
134916
|
+
* `replyExpected` (#1107: no @ → nobody replies) and that decides it; a 1:1 DM
|
|
134917
|
+
* passes none and say stays allowed there. Distinct from `currentReplyExpected`,
|
|
134918
|
+
* which drives only the #416 prose fallback and is false for un-attested DMs. */
|
|
134919
|
+
currentSayAllowed = true;
|
|
134891
134920
|
saidThisTurn = false;
|
|
134892
134921
|
turnText = "";
|
|
134893
134922
|
/** #630 drop-probe: did a `result` event arrive for the CURRENT turn? Reset per
|
|
@@ -134960,6 +134989,12 @@ var PersistentClaudeSession = class {
|
|
|
134960
134989
|
* back to opts.onSay. This is what closes the DM→room leak: the destination is
|
|
134961
134990
|
* the one captured for the message being answered, not a live global target. */
|
|
134962
134991
|
async deliver(text) {
|
|
134992
|
+
if (!this.currentSayAllowed) {
|
|
134993
|
+
logLine(
|
|
134994
|
+
`[session] say during a turn this agent does not owe (no @mention) \u2014 SUPPRESSED: ${JSON.stringify(text.slice(0, 80))}`
|
|
134995
|
+
);
|
|
134996
|
+
return;
|
|
134997
|
+
}
|
|
134963
134998
|
this.saidThisTurn = true;
|
|
134964
134999
|
if (this.activeReply) await this.activeReply(text);
|
|
134965
135000
|
else if (this.opts.onSay) await this.opts.onSay(text);
|
|
@@ -135001,6 +135036,7 @@ var PersistentClaudeSession = class {
|
|
|
135001
135036
|
this.activeReply = item.reply;
|
|
135002
135037
|
this.currentAutoReply = item.autoReplyOnText ?? false;
|
|
135003
135038
|
this.currentReplyExpected = item.replyExpected ?? item.autoReplyOnText ?? false;
|
|
135039
|
+
this.currentSayAllowed = item.replyExpected ?? true;
|
|
135004
135040
|
this.currentArmedGetter = item.armed ?? (() => false);
|
|
135005
135041
|
this.saidThisTurn = false;
|
|
135006
135042
|
this.turnText = "";
|
|
@@ -135930,7 +135966,7 @@ async function main() {
|
|
|
135930
135966
|
"[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"
|
|
135931
135967
|
);
|
|
135932
135968
|
}
|
|
135933
|
-
logLine(`[bridge] version: ${true ? "0.8.
|
|
135969
|
+
logLine(`[bridge] version: ${true ? "0.8.12" : "dev"}`);
|
|
135934
135970
|
logLine(`[bridge] data dir: ${cfg.dataDir} (${cfg.dataDirSource})`);
|
|
135935
135971
|
logLine(`[bridge] workspace: ${cfg.workspaceDir} \xB7 permissions: ${cfg.permissionMode} \xB7 enclave dir fenced`);
|
|
135936
135972
|
if (cfg.armRoom) {
|
|
@@ -135962,7 +135998,7 @@ async function main() {
|
|
|
135962
135998
|
// its default would render "@agentvault/agentvault@0.7.x" — the wrong
|
|
135963
135999
|
// package name attached to the bridge's version number, which is worse
|
|
135964
136000
|
// than either alone.
|
|
135965
|
-
clientVersion: `@agentvault/claude-bridge@${true ? "0.8.
|
|
136001
|
+
clientVersion: `@agentvault/claude-bridge@${true ? "0.8.12" : "dev"}`
|
|
135966
136002
|
});
|
|
135967
136003
|
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.`;
|
|
135968
136004
|
const deviceJwt = () => {
|
package/dist/session.d.ts
CHANGED
|
@@ -135,6 +135,11 @@ export declare class PersistentClaudeSession {
|
|
|
135
135
|
* which also prevents agent↔agent reply loops. Tool access is unaffected: it
|
|
136
136
|
* stays gated on currentAutoReply (owner DM) OR currentArmedGetter (armed room). */
|
|
137
137
|
private currentReplyExpected;
|
|
138
|
+
/** #1180: whether the say tool may deliver on this turn. Rooms pass an explicit
|
|
139
|
+
* `replyExpected` (#1107: no @ → nobody replies) and that decides it; a 1:1 DM
|
|
140
|
+
* passes none and say stays allowed there. Distinct from `currentReplyExpected`,
|
|
141
|
+
* which drives only the #416 prose fallback and is false for un-attested DMs. */
|
|
142
|
+
private currentSayAllowed;
|
|
138
143
|
private saidThisTurn;
|
|
139
144
|
private turnText;
|
|
140
145
|
/** #630 drop-probe: did a `result` event arrive for the CURRENT turn? Reset per
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agentvault/claude-bridge",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.12",
|
|
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",
|