@agentvault/claude-bridge 0.7.2 → 0.7.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/bridge.d.ts CHANGED
@@ -43,6 +43,10 @@ export interface RoomHushed {
43
43
  }
44
44
  export interface RoomChannel {
45
45
  on(ev: "room_message", cb: (e: RoomMessage) => void): unknown;
46
+ on(ev: "room_joined", cb: (e: {
47
+ roomId: string;
48
+ name?: string;
49
+ }) => void): unknown;
46
50
  on(ev: "message", cb: (text: string, metadata: MessageMeta) => void): unknown;
47
51
  on(ev: "room_hushed", cb: (e: RoomHushed) => void): unknown;
48
52
  on(ev: "error", cb: (err: unknown) => void): unknown;
@@ -175,6 +179,26 @@ export declare function attachLifecycle(channel: LifecycleChannel, opts?: {
175
179
  * dropped (it usually means a mis-timed or duplicate approval).
176
180
  */
177
181
  export declare function pollApprovalsOnce(arming: ArmingState, dataDir: string, onArmed: () => void, log?: (msg: string) => void): void;
182
+ /**
183
+ * How a ROOM turn is announced to the model (#366 / #499 Facet A).
184
+ *
185
+ * Reproduced live 2026-07-29: asked "what room are you in?" *in* a room, the
186
+ * agent answered "This is our 1:1 DM, so no room name to report." Everything
187
+ * beneath the model was correct — the bridge logged `inbound from chris in
188
+ * c6a2734d` then `said to room c6a2734d`, and the message is recorded against
189
+ * room "New Test" in the database. The turn was simply pushed as
190
+ * `[chris]: <text>`, which carries no channel context whatsoever, so the model
191
+ * had nothing to distinguish a room from a DM and defaulted to DM.
192
+ *
193
+ * The room NAME is best-effort (learned from `room_joined`), but the fact that
194
+ * this is a room is not: when the name is unknown we still say "room" and fall
195
+ * back to a short id. Getting "which room" wrong is a cosmetic answer; getting
196
+ * "am I in a room" wrong changes how the agent addresses everyone in it.
197
+ *
198
+ * A 1:1 DM is deliberately left unlabelled — that path is not broken, and an
199
+ * unmarked turn already reads as a DM, which is what the model assumes.
200
+ */
201
+ export declare function roomTurnPrefix(roomId: string, senderName: string, roomName?: string): string;
178
202
  export declare function wireBridge(channel: RoomChannel, session: RoomSession, target: ActiveTarget, opts?: {
179
203
  roomFilter?: string;
180
204
  armRoom?: boolean;
package/dist/index.js CHANGED
@@ -63525,6 +63525,34 @@ var init_owner_sync = __esm2({
63525
63525
  NONCE_BYTES2 = 24;
63526
63526
  }
63527
63527
  });
63528
+ function seqOf(m22) {
63529
+ if (m22.seq === void 0 || m22.seq === null || m22.seq === "")
63530
+ return null;
63531
+ const n22 = Number(m22.seq);
63532
+ return Number.isFinite(n22) ? n22 : null;
63533
+ }
63534
+ function createdAtOf(m22) {
63535
+ const t22 = new Date(m22.created_at ?? 0).getTime();
63536
+ return Number.isFinite(t22) ? t22 : 0;
63537
+ }
63538
+ function orderDeliveryBatch(messages) {
63539
+ return [...messages].sort((a2, b22) => {
63540
+ const aWelcome = a2.message_type === "welcome";
63541
+ const bWelcome = b22.message_type === "welcome";
63542
+ if (aWelcome !== bWelcome)
63543
+ return aWelcome ? -1 : 1;
63544
+ const as2 = seqOf(a2);
63545
+ const bs2 = seqOf(b22);
63546
+ if (as2 !== null && bs2 !== null && as2 !== bs2)
63547
+ return as2 - bs2;
63548
+ return createdAtOf(a2) - createdAtOf(b22);
63549
+ });
63550
+ }
63551
+ var init_mls_delivery_order = __esm2({
63552
+ "../crypto/dist/mls-delivery-order.js"() {
63553
+ "use strict";
63554
+ }
63555
+ });
63528
63556
  var dist_exports = {};
63529
63557
  __export2(dist_exports, {
63530
63558
  AV_CREDENTIAL_CONTEXT: () => AV_CREDENTIAL_CONTEXT,
@@ -63595,6 +63623,7 @@ __export2(dist_exports, {
63595
63623
  issueCredential: () => issueCredential,
63596
63624
  multibaseToPublicKey: () => multibaseToPublicKey,
63597
63625
  normalizeBackupCode: () => normalizeBackupCode,
63626
+ orderDeliveryBatch: () => orderDeliveryBatch,
63598
63627
  parseTraceparent: () => parseTraceparent,
63599
63628
  performX3DH: () => performX3DH,
63600
63629
  presentCredentials: () => presentCredentials,
@@ -63632,6 +63661,7 @@ var init_dist = __esm2({
63632
63661
  await init_approval();
63633
63662
  init_mls_group();
63634
63663
  await init_owner_sync();
63664
+ init_mls_delivery_order();
63635
63665
  }
63636
63666
  });
63637
63667
  function syncLockPath(dataDir, channelId) {
@@ -64592,6 +64622,7 @@ var init_channel = __esm2({
64592
64622
  "use strict";
64593
64623
  await init_libsodium_wrappers();
64594
64624
  await init_dist();
64625
+ await init_dist();
64595
64626
  init_mls_state();
64596
64627
  await init_mls_kp_pool();
64597
64628
  init_credential_store();
@@ -65563,7 +65594,7 @@ var init_channel = __esm2({
65563
65594
  */
65564
65595
  sendActivitySpan(spanData) {
65565
65596
  if (!this._ws || this._ws.readyState !== WebSocket2.OPEN) return;
65566
- const pluginVersion = true ? "0.23.12" : "0.0.0-dev";
65597
+ const pluginVersion = true ? "0.23.13" : "0.0.0-dev";
65567
65598
  const agentName = this.config.agentName ?? "Agent";
65568
65599
  const resource = {
65569
65600
  "service.name": "agentvault-agent",
@@ -67302,7 +67333,7 @@ var init_channel = __esm2({
67302
67333
  agentVersion: this.config.agentVersion ?? "0.0.0",
67303
67334
  // __AV_VERSION__ is injected by esbuild from package.json at build time.
67304
67335
  // Falls back to "0.0.0-dev" in non-bundled contexts (tests).
67305
- pluginVersion: true ? "0.23.12" : "0.0.0-dev"
67336
+ pluginVersion: true ? "0.23.13" : "0.0.0-dev"
67306
67337
  });
67307
67338
  this._telemetryReporter.startAutoFlush(3e4);
67308
67339
  }
@@ -67620,7 +67651,7 @@ var init_channel = __esm2({
67620
67651
  agentVersion: this.config.agentVersion ?? "0.0.0",
67621
67652
  // __AV_VERSION__ is injected by esbuild from package.json at build time.
67622
67653
  // Falls back to "0.0.0-dev" in non-bundled contexts (tests).
67623
- pluginVersion: true ? "0.23.12" : "0.0.0-dev"
67654
+ pluginVersion: true ? "0.23.13" : "0.0.0-dev"
67624
67655
  });
67625
67656
  this._telemetryReporter.startAutoFlush(3e4);
67626
67657
  }
@@ -69538,16 +69569,10 @@ ${messageText}`;
69538
69569
  console.warn(`[SecureChannel] Delivery pull failed: ${res.status}`);
69539
69570
  return;
69540
69571
  }
69541
- const { messages } = await res.json();
69572
+ let { messages } = await res.json();
69542
69573
  const hasMessages = messages && messages.length > 0;
69543
69574
  if (hasMessages) {
69544
- const order = { welcome: 0, commit: 1, application: 2 };
69545
- messages.sort((a2, b22) => {
69546
- const ao = order[a2.message_type] ?? 2;
69547
- const bo = order[b22.message_type] ?? 2;
69548
- if (ao !== bo) return ao - bo;
69549
- return new Date(a2.created_at).getTime() - new Date(b22.created_at).getTime();
69550
- });
69575
+ messages = orderDeliveryBatch(messages);
69551
69576
  const ackedIds = [];
69552
69577
  const nackedIds = [];
69553
69578
  for (const msg of messages) {
@@ -97475,7 +97500,7 @@ var init_index = __esm2({
97475
97500
  init_skill_invoker();
97476
97501
  await init_skill_telemetry();
97477
97502
  await init_policy_enforcer();
97478
- VERSION = true ? "0.23.12" : "0.0.0-dev";
97503
+ VERSION = true ? "0.23.13" : "0.0.0-dev";
97479
97504
  }
97480
97505
  });
97481
97506
  await init_index();
@@ -133532,6 +133557,10 @@ function pollApprovalsOnce(arming, dataDir, onArmed, log = () => {
133532
133557
  }
133533
133558
  }
133534
133559
  }
133560
+ function roomTurnPrefix(roomId, senderName, roomName) {
133561
+ const room = roomName ? `"${roomName}"` : roomId.slice(0, 8);
133562
+ return `[room ${room} | ${senderName}]`;
133563
+ }
133535
133564
  function wireBridge(channel, session, target, opts = {}) {
133536
133565
  const log = opts.log ?? (() => {
133537
133566
  });
@@ -133566,6 +133595,10 @@ function wireBridge(channel, session, target, opts = {}) {
133566
133595
  );
133567
133596
  });
133568
133597
  let warnedMissingSenderIsAgent = false;
133598
+ const roomNames = /* @__PURE__ */ new Map();
133599
+ channel.on("room_joined", (e7) => {
133600
+ if (e7?.roomId && e7.name) roomNames.set(e7.roomId, e7.name);
133601
+ });
133569
133602
  channel.on("room_message", (e7) => {
133570
133603
  if (typeof e7.senderIsAgent !== "boolean" && !warnedMissingSenderIsAgent) {
133571
133604
  warnedMissingSenderIsAgent = true;
@@ -133580,7 +133613,7 @@ function wireBridge(channel, session, target, opts = {}) {
133580
133613
  }
133581
133614
  log(`inbound from ${e7.senderName} in ${e7.roomId.slice(0, 8)}`);
133582
133615
  target.setRoom(e7.roomId);
133583
- session.push(`[${e7.senderName}]: ${e7.plaintext}`, target.snapshotReply(channel, log), {
133616
+ session.push(`${roomTurnPrefix(e7.roomId, e7.senderName, roomNames.get(e7.roomId))}: ${e7.plaintext}`, target.snapshotReply(channel, log), {
133584
133617
  autoReplyOnText: false,
133585
133618
  replyExpected: e7.senderIsAgent === false,
133586
133619
  armed: () => arming.isArmed(e7.roomId)
@@ -133731,7 +133764,7 @@ async function main() {
133731
133764
  "[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"
133732
133765
  );
133733
133766
  }
133734
- console.error(`[bridge] version: ${true ? "0.7.2" : "dev"}`);
133767
+ console.error(`[bridge] version: ${true ? "0.7.3" : "dev"}`);
133735
133768
  console.error(`[bridge] data dir: ${cfg.dataDir} (${cfg.dataDirSource})`);
133736
133769
  console.error(`[bridge] workspace: ${cfg.workspaceDir} \xB7 permissions: ${cfg.permissionMode} \xB7 enclave dir fenced`);
133737
133770
  if (cfg.armRoom) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentvault/claude-bridge",
3
- "version": "0.7.2",
3
+ "version": "0.7.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",