@agentvault/claude-bridge 0.7.8 → 0.7.9

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 CHANGED
@@ -133175,6 +133175,28 @@ var PersistentClaudeSession = class {
133175
133175
  * #416 fallback delivery (which delivers via `void reply(...)` WITHOUT setting
133176
133176
  * saidThisTurn, so !saidThisTurn alone would false-flag it). */
133177
133177
  sawResultThisTurn = false;
133178
+ /**
133179
+ * Per-turn telemetry lifted off the SDK's `result` message.
133180
+ *
133181
+ * The message arrives on EVERY turn and we kept one boolean from it
133182
+ * (`sawResultThisTurn`), discarding the rest. That is the #791 shape: data
133183
+ * delivered on the healthy path that nothing reads.
133184
+ *
133185
+ * It costs us a real answer. A turn that produced nothing (`composed=0,
133186
+ * said=false`) could be the model choosing silence, the turn cap being hit, or
133187
+ * the provider returning 429 — three different bugs with one symptom, and
133188
+ * `subtype`/`apiErrorStatus` are what separate them. 4 of 12 turns on
133189
+ * 2026-08-07 were silent and could not be attributed.
133190
+ *
133191
+ * `durationApiMs` vs `durationMs` also gives the model-time / SDK-overhead
133192
+ * split directly. That split previously had to be reconstructed by joining
133193
+ * `WorkerIncident.ranMs` against SDK transcripts on disk by wall clock.
133194
+ *
133195
+ * Every field is OPTIONAL and left undefined when no result arrives (abort or
133196
+ * crash mid-turn): absent must read as absent, never as a zero that looks like
133197
+ * a real measurement.
133198
+ */
133199
+ resultTelemetry = {};
133178
133200
  /** In-process room MCP server — hoisted so buildSdkOptions can reference it. */
133179
133201
  roomServer;
133180
133202
  /** AbortController for the in-flight query(); abort() triggers it (queue timeout). */
@@ -133239,7 +133261,8 @@ var PersistentClaudeSession = class {
133239
133261
  return {
133240
133262
  composedChars: this.turnText.length,
133241
133263
  sawResult: this.sawResultThisTurn,
133242
- said: this.saidThisTurn
133264
+ said: this.saidThisTurn,
133265
+ ...this.resultTelemetry
133243
133266
  };
133244
133267
  }
133245
133268
  async *input() {
@@ -133261,6 +133284,7 @@ var PersistentClaudeSession = class {
133261
133284
  this.saidThisTurn = false;
133262
133285
  this.turnText = "";
133263
133286
  this.sawResultThisTurn = false;
133287
+ this.resultTelemetry = {};
133264
133288
  yield item.msg;
133265
133289
  }
133266
133290
  }
@@ -133403,6 +133427,17 @@ var PersistentClaudeSession = class {
133403
133427
  }
133404
133428
  } else if (m6.type === "result") {
133405
133429
  this.sawResultThisTurn = true;
133430
+ const r7 = m6;
133431
+ const num = (k2) => typeof r7[k2] === "number" ? r7[k2] : void 0;
133432
+ const str = (k2) => typeof r7[k2] === "string" ? r7[k2] : void 0;
133433
+ this.resultTelemetry = {
133434
+ durationMs: num("duration_ms"),
133435
+ durationApiMs: num("duration_api_ms"),
133436
+ numTurns: num("num_turns"),
133437
+ subtype: str("subtype"),
133438
+ stopReason: str("stop_reason"),
133439
+ apiErrorStatus: num("api_error_status")
133440
+ };
133406
133441
  const reply = this.activeReply;
133407
133442
  if (this.currentReplyExpected && !this.saidThisTurn && this.turnText.trim()) {
133408
133443
  if (reply) {
@@ -134113,7 +134148,7 @@ async function main() {
134113
134148
  "[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"
134114
134149
  );
134115
134150
  }
134116
- logLine(`[bridge] version: ${true ? "0.7.8" : "dev"}`);
134151
+ logLine(`[bridge] version: ${true ? "0.7.9" : "dev"}`);
134117
134152
  logLine(`[bridge] data dir: ${cfg.dataDir} (${cfg.dataDirSource})`);
134118
134153
  logLine(`[bridge] workspace: ${cfg.workspaceDir} \xB7 permissions: ${cfg.permissionMode} \xB7 enclave dir fenced`);
134119
134154
  if (cfg.armRoom) {
package/dist/session.d.ts CHANGED
@@ -143,6 +143,28 @@ export declare class PersistentClaudeSession {
143
143
  * #416 fallback delivery (which delivers via `void reply(...)` WITHOUT setting
144
144
  * saidThisTurn, so !saidThisTurn alone would false-flag it). */
145
145
  private sawResultThisTurn;
146
+ /**
147
+ * Per-turn telemetry lifted off the SDK's `result` message.
148
+ *
149
+ * The message arrives on EVERY turn and we kept one boolean from it
150
+ * (`sawResultThisTurn`), discarding the rest. That is the #791 shape: data
151
+ * delivered on the healthy path that nothing reads.
152
+ *
153
+ * It costs us a real answer. A turn that produced nothing (`composed=0,
154
+ * said=false`) could be the model choosing silence, the turn cap being hit, or
155
+ * the provider returning 429 — three different bugs with one symptom, and
156
+ * `subtype`/`apiErrorStatus` are what separate them. 4 of 12 turns on
157
+ * 2026-08-07 were silent and could not be attributed.
158
+ *
159
+ * `durationApiMs` vs `durationMs` also gives the model-time / SDK-overhead
160
+ * split directly. That split previously had to be reconstructed by joining
161
+ * `WorkerIncident.ranMs` against SDK transcripts on disk by wall clock.
162
+ *
163
+ * Every field is OPTIONAL and left undefined when no result arrives (abort or
164
+ * crash mid-turn): absent must read as absent, never as a zero that looks like
165
+ * a real measurement.
166
+ */
167
+ private resultTelemetry;
146
168
  /** In-process room MCP server — hoisted so buildSdkOptions can reference it. */
147
169
  private roomServer;
148
170
  /** AbortController for the in-flight query(); abort() triggers it (queue timeout). */
@@ -185,6 +207,12 @@ export declare class PersistentClaudeSession {
185
207
  composedChars: number;
186
208
  sawResult: boolean;
187
209
  said: boolean;
210
+ durationMs?: number;
211
+ durationApiMs?: number;
212
+ numTurns?: number;
213
+ subtype?: string;
214
+ stopReason?: string;
215
+ apiErrorStatus?: number;
188
216
  };
189
217
  private input;
190
218
  /**
@@ -61,11 +61,27 @@ export type WorkerIncident = {
61
61
  * could not separate them.
62
62
  */
63
63
  replyExpected?: boolean;
64
- /** What the worker had produced when it died, when the session can report it. */
64
+ /**
65
+ * What the worker had produced when it died, when the session can report it.
66
+ *
67
+ * The `duration*`/`numTurns`/`subtype`/`stopReason`/`apiErrorStatus` fields are
68
+ * lifted off the SDK's `result` message (see `PersistentClaudeSession`). They
69
+ * are what makes a SILENT turn attributable: `composed=0, said=false` is
70
+ * produced identically by the model choosing silence (`subtype: success`), the
71
+ * turn cap (`error_max_turns`) and a provider error (`apiErrorStatus: 429`).
72
+ * Absent on any turn that never reached a result boundary — undefined means
73
+ * "no result arrived", never zero.
74
+ */
65
75
  session?: {
66
76
  composedChars: number;
67
77
  sawResult: boolean;
68
78
  said: boolean;
79
+ durationMs?: number;
80
+ durationApiMs?: number;
81
+ numTurns?: number;
82
+ subtype?: string;
83
+ stopReason?: string;
84
+ apiErrorStatus?: number;
69
85
  };
70
86
  };
71
87
  export interface WorkerQueueDeps {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentvault/claude-bridge",
3
- "version": "0.7.8",
3
+ "version": "0.7.9",
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",