@autohq/cli 0.1.309 → 0.1.311

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.
@@ -19692,7 +19692,12 @@ var RuntimeBridgeOutputEntryEnvelopeWireSchema = external_exports.object({
19692
19692
  turnStatus: RuntimeTurnStatusSchema.optional(),
19693
19693
  // Present only on a turn's terminal result entry; carries the captured
19694
19694
  // token/cost usage the persisting side turns into ledger rows.
19695
- usage: RuntimeBridgeTurnUsageSchema.optional()
19695
+ usage: RuntimeBridgeTurnUsageSchema.optional(),
19696
+ // Present only on a turn's terminal result entry: the commands whose
19697
+ // messages that harness turn consumed, from the runtime's injection-order
19698
+ // ground truth. The persisting side settles exactly these turns; absent
19699
+ // (older runtimes, non-command turns) it falls back to cursor attribution.
19700
+ consumedCommandIds: external_exports.array(SessionCommandIdSchema).optional()
19696
19701
  }).strict();
19697
19702
  var LegacyRuntimeBridgeOutputEntryEnvelopeSchema = RuntimeBridgeOutputEntryEnvelopeWireSchema.omit({ turnStatus: true }).extend({
19698
19703
  sessionStatusAfter: external_exports.enum(["awaiting", "failed"])
@@ -19752,6 +19757,9 @@ var RuntimeBridgeOutputUiMessageCompletedEnvelopeSchema = external_exports.objec
19752
19757
  message: JsonValueSchema,
19753
19758
  turnStatus: external_exports.enum(["waiting_for_input", "completed", "failed"]).optional(),
19754
19759
  usage: RuntimeBridgeTurnUsageSchema.optional(),
19760
+ // See the conversation.entry envelope: terminal-result-only declaration of
19761
+ // the commands this turn consumed, for exact turn-ledger settlement.
19762
+ consumedCommandIds: external_exports.array(SessionCommandIdSchema).optional(),
19755
19763
  createdAt: external_exports.string().datetime(),
19756
19764
  completedAt: external_exports.string().datetime().nullable()
19757
19765
  }).strict();
@@ -23399,7 +23407,7 @@ Object.assign(lookup, {
23399
23407
  // package.json
23400
23408
  var package_default = {
23401
23409
  name: "@autohq/cli",
23402
- version: "0.1.309",
23410
+ version: "0.1.311",
23403
23411
  license: "SEE LICENSE IN README.md",
23404
23412
  publishConfig: {
23405
23413
  access: "public"
@@ -39535,6 +39543,7 @@ var AgentBridgeOutputBuffer = class {
39535
39543
  status: terminalEntryStatus(projection),
39536
39544
  turnStatus: turnFailed ? void 0 : projection.turnStatus,
39537
39545
  usage: turnFailed ? void 0 : projection.usage,
39546
+ consumedCommandIds: turnFailed ? void 0 : projection.consumedCommandIds,
39538
39547
  createdAt: completedAt,
39539
39548
  completedAt
39540
39549
  });
@@ -39557,6 +39566,7 @@ var AgentBridgeOutputBuffer = class {
39557
39566
  status: terminalEntryStatus(projection),
39558
39567
  ...projection.turnStatus ? { turnStatus: projection.turnStatus } : {},
39559
39568
  ...projection.usage ? { usage: projection.usage } : {},
39569
+ ...projection.consumedCommandIds ? { consumedCommandIds: projection.consumedCommandIds } : {},
39560
39570
  content: {
39561
39571
  parts: [{ type: "text", text: statusText }]
39562
39572
  }
@@ -39953,7 +39963,8 @@ function buildOutputEnvelope(context, outputSeq, projection) {
39953
39963
  createdAt,
39954
39964
  completedAt: entry.status === "in_progress" ? null : createdAt,
39955
39965
  ...entry.turnStatus ? { turnStatus: entry.turnStatus } : {},
39956
- ...entry.usage ? { usage: entry.usage } : {}
39966
+ ...entry.usage ? { usage: entry.usage } : {},
39967
+ ...entry.consumedCommandIds ? { consumedCommandIds: entry.consumedCommandIds } : {}
39957
39968
  });
39958
39969
  }
39959
39970
  function buildDeltaOutputEnvelope(input) {
@@ -40015,6 +40026,7 @@ function buildUiMessageCompletedOutputEnvelope(input) {
40015
40026
  message: toJsonValue(input.message),
40016
40027
  ...input.turnStatus ? { turnStatus: input.turnStatus } : {},
40017
40028
  ...input.usage ? { usage: input.usage } : {},
40029
+ ...input.consumedCommandIds ? { consumedCommandIds: input.consumedCommandIds } : {},
40018
40030
  createdAt: input.createdAt,
40019
40031
  completedAt: input.completedAt
40020
40032
  });
@@ -60346,6 +60358,13 @@ var ClaudeAgentBridgeSessionImpl = class {
60346
60358
  // settlement after the ack). Flushed once the turn ends and the session is
60347
60359
  // idle.
60348
60360
  deferredMessages = [];
60361
+ // Consumed-command ids per enqueued turn, in injection order. Results arrive
60362
+ // in turn order, so each terminal `result` settles the OLDEST open entry —
60363
+ // which is also why an interrupted turn's result (arriving after the
60364
+ // interrupter enqueued) still resolves to the interrupted command. A
60365
+ // deferred flush enqueues one concatenated turn, so its entry carries every
60366
+ // flushed command id.
60367
+ openTurnCommandIds = [];
60349
60368
  // tool_use ids the assistant has emitted whose tool_result has not yet been
60350
60369
  // observed. A non-empty set means a tool call is in flight, so an immediate
60351
60370
  // interrupt would append the new user message after an unresolved
@@ -60407,6 +60426,7 @@ var ClaudeAgentBridgeSessionImpl = class {
60407
60426
  }
60408
60427
  async sendMessage(message, options) {
60409
60428
  const mode = options?.mode ?? "interrupt";
60429
+ const commandIds = options?.commandId ? [options.commandId] : [];
60410
60430
  const startedAt = Date.now();
60411
60431
  this.input.runtimeLogger?.info("agent_bridge_claude_send_message_started", {
60412
60432
  delivery_mode: mode,
@@ -60416,7 +60436,7 @@ var ClaudeAgentBridgeSessionImpl = class {
60416
60436
  deferred_count: this.deferredMessages.length
60417
60437
  });
60418
60438
  if (mode === "deferred" && this.hasInterruptibleTurn()) {
60419
- this.deferredMessages.push(message);
60439
+ this.deferredMessages.push({ text: message, commandIds });
60420
60440
  this.input.runtimeLogger?.info("agent_bridge_claude_message_deferred", {
60421
60441
  active_turn_count: this.activeTurnCount,
60422
60442
  pending_tool_use_count: this.pendingToolUseIds.size,
@@ -60426,7 +60446,7 @@ var ClaudeAgentBridgeSessionImpl = class {
60426
60446
  }
60427
60447
  const interruption = await this.interruptActiveTurnBeforeMessage();
60428
60448
  if (interruption === "defer" && this.hasInterruptibleTurn()) {
60429
- this.deferredMessages.push(message);
60449
+ this.deferredMessages.push({ text: message, commandIds });
60430
60450
  this.input.runtimeLogger?.info(
60431
60451
  "agent_bridge_claude_message_deferred_after_interrupt_timeout",
60432
60452
  {
@@ -60438,7 +60458,7 @@ var ClaudeAgentBridgeSessionImpl = class {
60438
60458
  return;
60439
60459
  }
60440
60460
  await this.awaitMcpRegistration();
60441
- this.enqueueUserMessage(message);
60461
+ this.enqueueUserMessage(message, commandIds);
60442
60462
  this.input.runtimeLogger?.info("agent_bridge_claude_send_message_queued", {
60443
60463
  delivery_mode: mode,
60444
60464
  duration_ms: Date.now() - startedAt,
@@ -60448,6 +60468,20 @@ var ClaudeAgentBridgeSessionImpl = class {
60448
60468
  deferred_count: this.deferredMessages.length
60449
60469
  });
60450
60470
  }
60471
+ noteActiveTurnCommand(commandId) {
60472
+ const activeTurn = this.openTurnCommandIds[0];
60473
+ if (activeTurn) {
60474
+ activeTurn.push(commandId);
60475
+ }
60476
+ this.input.runtimeLogger?.info(
60477
+ "agent_bridge_claude_active_turn_command_noted",
60478
+ {
60479
+ attributed: Boolean(activeTurn),
60480
+ active_turn_count: this.activeTurnCount,
60481
+ open_turn_entries: this.openTurnCommandIds.length
60482
+ }
60483
+ );
60484
+ }
60451
60485
  close() {
60452
60486
  const previousState = this.state;
60453
60487
  if (previousState.kind === "closed") {
@@ -60463,6 +60497,7 @@ var ClaudeAgentBridgeSessionImpl = class {
60463
60497
  );
60464
60498
  this.deferredMessages.length = 0;
60465
60499
  }
60500
+ this.openTurnCommandIds.length = 0;
60466
60501
  this.stderr.flush();
60467
60502
  this.inputQueue.close();
60468
60503
  if (previousState.kind === "started") {
@@ -60546,8 +60581,12 @@ var ClaudeAgentBridgeSessionImpl = class {
60546
60581
  try {
60547
60582
  for await (const message of query) {
60548
60583
  this.trackToolUseLifecycle(message);
60584
+ let meta3;
60549
60585
  if (isClaudeAgentTurnResult(message)) {
60550
60586
  this.activeTurnCount = Math.max(0, this.activeTurnCount - 1);
60587
+ meta3 = {
60588
+ consumedCommandIds: this.openTurnCommandIds.shift() ?? []
60589
+ };
60551
60590
  this.pendingToolUseIds.clear();
60552
60591
  this.turnResultCount += 1;
60553
60592
  this.resolveTurnSettlement(true);
@@ -60555,7 +60594,8 @@ var ClaudeAgentBridgeSessionImpl = class {
60555
60594
  active_turn_count: this.activeTurnCount,
60556
60595
  pending_tool_use_count: this.pendingToolUseIds.size,
60557
60596
  turn_result_count: this.turnResultCount,
60558
- deferred_count: this.deferredMessages.length
60597
+ deferred_count: this.deferredMessages.length,
60598
+ consumed_command_ids: meta3.consumedCommandIds
60559
60599
  });
60560
60600
  if (this.activeTurnCount === 0) {
60561
60601
  this.flushDeferredMessages();
@@ -60575,7 +60615,7 @@ var ClaudeAgentBridgeSessionImpl = class {
60575
60615
  this.close();
60576
60616
  return;
60577
60617
  }
60578
- await this.input.onMessage(message);
60618
+ await this.input.onMessage(message, meta3);
60579
60619
  }
60580
60620
  } catch (error51) {
60581
60621
  if (this.state.kind !== "closed") {
@@ -60583,6 +60623,7 @@ var ClaudeAgentBridgeSessionImpl = class {
60583
60623
  }
60584
60624
  } finally {
60585
60625
  this.activeTurnCount = 0;
60626
+ this.openTurnCommandIds.length = 0;
60586
60627
  this.pendingToolUseIds.clear();
60587
60628
  this.resolveTurnSettlement(false);
60588
60629
  this.state = { kind: "closed" };
@@ -60594,9 +60635,10 @@ var ClaudeAgentBridgeSessionImpl = class {
60594
60635
  // lets injection work while the SDK session is still starting; the queue
60595
60636
  // drains once the query attaches. Startup failures surface through onError
60596
60637
  // instead of failing injection.
60597
- enqueueUserMessage(message) {
60638
+ enqueueUserMessage(message, commandIds) {
60598
60639
  this.inputQueue.push(claudeAgentUserMessage(message));
60599
60640
  this.activeTurnCount += 1;
60641
+ this.openTurnCommandIds.push(commandIds);
60600
60642
  this.input.runtimeLogger?.info("agent_bridge_claude_message_enqueued", {
60601
60643
  state: this.state.kind,
60602
60644
  active_turn_count: this.activeTurnCount,
@@ -60680,7 +60722,10 @@ var ClaudeAgentBridgeSessionImpl = class {
60680
60722
  this.input.writeOutput?.(
60681
60723
  `agent_bridge_claude_deferred_flush count=${pending.length}`
60682
60724
  );
60683
- this.enqueueUserMessage(pending.join("\n\n"));
60725
+ this.enqueueUserMessage(
60726
+ pending.map((entry) => entry.text).join("\n\n"),
60727
+ pending.flatMap((entry) => entry.commandIds)
60728
+ );
60684
60729
  }
60685
60730
  async interruptActiveTurnBeforeMessage() {
60686
60731
  if (!this.hasInterruptibleTurn()) {
@@ -61347,7 +61392,8 @@ var ClaudeCodeCommandHandler = class {
61347
61392
  })
61348
61393
  );
61349
61394
  await this.ensureAgentSession().sendMessage(message, {
61350
- mode
61395
+ mode,
61396
+ commandId: delivery.commandId
61351
61397
  });
61352
61398
  this.input.runtimeLogger?.info(
61353
61399
  "agent_bridge_claude_command_send_message_ready",
@@ -61402,6 +61448,7 @@ var ClaudeCodeCommandHandler = class {
61402
61448
  const pending = this.pendingQuestions.get(answer.toolCallId);
61403
61449
  if (pending) {
61404
61450
  this.pendingQuestions.delete(answer.toolCallId);
61451
+ this.agentSession?.noteActiveTurnCommand(delivery.commandId);
61405
61452
  pending.resolve({
61406
61453
  behavior: "allow",
61407
61454
  updatedInput: {
@@ -61428,7 +61475,9 @@ var ClaudeCodeCommandHandler = class {
61428
61475
  }
61429
61476
  }
61430
61477
  });
61431
- await this.ensureAgentSession().sendMessage(message);
61478
+ await this.ensureAgentSession().sendMessage(message, {
61479
+ commandId: delivery.commandId
61480
+ });
61432
61481
  this.input.writeOutput?.(
61433
61482
  `agent_bridge_question_answer_fallback tool_use_id=${answer.toolCallId}`
61434
61483
  );
@@ -61484,7 +61533,7 @@ var ClaudeCodeCommandHandler = class {
61484
61533
  );
61485
61534
  }
61486
61535
  }
61487
- async handleAgentMessage(message) {
61536
+ async handleAgentMessage(message, meta3) {
61488
61537
  const activeContext = this.context;
61489
61538
  if (!activeContext) {
61490
61539
  return;
@@ -61500,7 +61549,10 @@ var ClaudeCodeCommandHandler = class {
61500
61549
  return;
61501
61550
  }
61502
61551
  for (const projection of projections) {
61503
- await this.emitBridgeOutput(activeContext, projection);
61552
+ await this.emitBridgeOutput(
61553
+ activeContext,
61554
+ withConsumedCommandIds(projection, meta3)
61555
+ );
61504
61556
  }
61505
61557
  }
61506
61558
  async handleAgentError(error51) {
@@ -61568,7 +61620,7 @@ var ClaudeCodeCommandHandler = class {
61568
61620
  claude: this.input.claude,
61569
61621
  resumeAgentId: this.storedResumeAgentId(),
61570
61622
  canUseTool: this.canUseTool,
61571
- onMessage: (message) => this.handleAgentMessage(message),
61623
+ onMessage: (message, meta3) => this.handleAgentMessage(message, meta3),
61572
61624
  onError: (error51) => this.handleAgentError(error51),
61573
61625
  onExit: () => {
61574
61626
  if (this.agentSession === session) {
@@ -61583,6 +61635,13 @@ var ClaudeCodeCommandHandler = class {
61583
61635
  return session;
61584
61636
  }
61585
61637
  };
61638
+ function withConsumedCommandIds(projection, meta3) {
61639
+ const consumedCommandIds = meta3?.consumedCommandIds;
61640
+ if (!consumedCommandIds || consumedCommandIds.length === 0 || projection.type !== "ui_message_chunk" || !projection.turnStatus) {
61641
+ return projection;
61642
+ }
61643
+ return { ...projection, consumedCommandIds };
61644
+ }
61586
61645
  function answerFallbackMessage(answer) {
61587
61646
  const lines = Object.entries(answer.answers).map(
61588
61647
  ([question, value2]) => `- ${question}: ${value2}`
package/dist/index.js CHANGED
@@ -25610,7 +25610,7 @@ var init_package = __esm({
25610
25610
  "package.json"() {
25611
25611
  package_default = {
25612
25612
  name: "@autohq/cli",
25613
- version: "0.1.309",
25613
+ version: "0.1.311",
25614
25614
  license: "SEE LICENSE IN README.md",
25615
25615
  publishConfig: {
25616
25616
  access: "public"
@@ -27723,15 +27723,15 @@ var init_template_staleness = __esm({
27723
27723
  function readProjectApplyDirectorySource(input) {
27724
27724
  const resourceRoot = normalizeSourcePath(input.resourceRoot ?? "");
27725
27725
  const displayResourceRoot2 = input.displayResourceRoot ?? (resourceRoot || ".auto");
27726
- const fileIndex = sourceFileIndex(input.files);
27727
- assertNoLegacySessionSourceFiles(
27728
- input.files,
27729
- resourceRoot,
27730
- displayResourceRoot2
27731
- );
27732
- assertNoStandaloneSourceFiles(input.files, resourceRoot, displayResourceRoot2);
27733
- assertValidFragmentSourceFiles(input.files, resourceRoot, fileIndex);
27734
- const agentFiles = input.files.filter(
27726
+ const files = injectManagedTemplateFiles({
27727
+ files: input.files,
27728
+ registry: defaultTemplateRegistry
27729
+ });
27730
+ const fileIndex = sourceFileIndex(files);
27731
+ assertNoLegacySessionSourceFiles(files, resourceRoot, displayResourceRoot2);
27732
+ assertNoStandaloneSourceFiles(files, resourceRoot, displayResourceRoot2);
27733
+ assertValidFragmentSourceFiles(files, resourceRoot, fileIndex);
27734
+ const agentFiles = files.filter(
27735
27735
  (file2) => isResourceFileUnderDirectory(
27736
27736
  file2.path,
27737
27737
  sourcePathJoin(resourceRoot, primaryApplyDirectory())
@@ -27747,7 +27747,7 @@ function readProjectApplyDirectorySource(input) {
27747
27747
  }))
27748
27748
  );
27749
27749
  }
27750
- const configResource = readProjectConfigResource(input.files, resourceRoot);
27750
+ const configResource = readProjectConfigResource(files, resourceRoot);
27751
27751
  const resources = [
27752
27752
  ...dedupeGeneratedResources(resourceRecords),
27753
27753
  ...configResource ? [configResource] : []
@@ -27765,7 +27765,12 @@ function readProjectApplyDirectorySource(input) {
27765
27765
  }
27766
27766
  function readProjectApplyFileSource(input) {
27767
27767
  const request = readProjectApplyDocumentSourceFile(input.file, {
27768
- fileIndex: sourceFileIndex(input.files ?? [input.file])
27768
+ fileIndex: sourceFileIndex(
27769
+ injectManagedTemplateFiles({
27770
+ files: input.files ?? [input.file],
27771
+ registry: defaultTemplateRegistry
27772
+ })
27773
+ )
27769
27774
  });
27770
27775
  return ProjectApplyRequestSchema.parse({
27771
27776
  ...request,
@@ -35642,7 +35647,12 @@ var RuntimeBridgeOutputEntryEnvelopeWireSchema = external_exports.object({
35642
35647
  turnStatus: RuntimeTurnStatusSchema.optional(),
35643
35648
  // Present only on a turn's terminal result entry; carries the captured
35644
35649
  // token/cost usage the persisting side turns into ledger rows.
35645
- usage: RuntimeBridgeTurnUsageSchema.optional()
35650
+ usage: RuntimeBridgeTurnUsageSchema.optional(),
35651
+ // Present only on a turn's terminal result entry: the commands whose
35652
+ // messages that harness turn consumed, from the runtime's injection-order
35653
+ // ground truth. The persisting side settles exactly these turns; absent
35654
+ // (older runtimes, non-command turns) it falls back to cursor attribution.
35655
+ consumedCommandIds: external_exports.array(SessionCommandIdSchema2).optional()
35646
35656
  }).strict();
35647
35657
  var LegacyRuntimeBridgeOutputEntryEnvelopeSchema = RuntimeBridgeOutputEntryEnvelopeWireSchema.omit({ turnStatus: true }).extend({
35648
35658
  sessionStatusAfter: external_exports.enum(["awaiting", "failed"])
@@ -35702,6 +35712,9 @@ var RuntimeBridgeOutputUiMessageCompletedEnvelopeSchema = external_exports.objec
35702
35712
  message: JsonValueSchema2,
35703
35713
  turnStatus: external_exports.enum(["waiting_for_input", "completed", "failed"]).optional(),
35704
35714
  usage: RuntimeBridgeTurnUsageSchema.optional(),
35715
+ // See the conversation.entry envelope: terminal-result-only declaration of
35716
+ // the commands this turn consumed, for exact turn-ledger settlement.
35717
+ consumedCommandIds: external_exports.array(SessionCommandIdSchema2).optional(),
35705
35718
  createdAt: external_exports.string().datetime(),
35706
35719
  completedAt: external_exports.string().datetime().nullable()
35707
35720
  }).strict();
@@ -36632,6 +36645,7 @@ var AgentBridgeOutputBuffer = class {
36632
36645
  status: terminalEntryStatus(projection),
36633
36646
  turnStatus: turnFailed ? void 0 : projection.turnStatus,
36634
36647
  usage: turnFailed ? void 0 : projection.usage,
36648
+ consumedCommandIds: turnFailed ? void 0 : projection.consumedCommandIds,
36635
36649
  createdAt: completedAt,
36636
36650
  completedAt
36637
36651
  });
@@ -36654,6 +36668,7 @@ var AgentBridgeOutputBuffer = class {
36654
36668
  status: terminalEntryStatus(projection),
36655
36669
  ...projection.turnStatus ? { turnStatus: projection.turnStatus } : {},
36656
36670
  ...projection.usage ? { usage: projection.usage } : {},
36671
+ ...projection.consumedCommandIds ? { consumedCommandIds: projection.consumedCommandIds } : {},
36657
36672
  content: {
36658
36673
  parts: [{ type: "text", text: statusText }]
36659
36674
  }
@@ -37050,7 +37065,8 @@ function buildOutputEnvelope(context, outputSeq, projection) {
37050
37065
  createdAt,
37051
37066
  completedAt: entry.status === "in_progress" ? null : createdAt,
37052
37067
  ...entry.turnStatus ? { turnStatus: entry.turnStatus } : {},
37053
- ...entry.usage ? { usage: entry.usage } : {}
37068
+ ...entry.usage ? { usage: entry.usage } : {},
37069
+ ...entry.consumedCommandIds ? { consumedCommandIds: entry.consumedCommandIds } : {}
37054
37070
  });
37055
37071
  }
37056
37072
  function buildDeltaOutputEnvelope(input) {
@@ -37112,6 +37128,7 @@ function buildUiMessageCompletedOutputEnvelope(input) {
37112
37128
  message: toJsonValue(input.message),
37113
37129
  ...input.turnStatus ? { turnStatus: input.turnStatus } : {},
37114
37130
  ...input.usage ? { usage: input.usage } : {},
37131
+ ...input.consumedCommandIds ? { consumedCommandIds: input.consumedCommandIds } : {},
37115
37132
  createdAt: input.createdAt,
37116
37133
  completedAt: input.completedAt
37117
37134
  });
@@ -37872,6 +37889,13 @@ var ClaudeAgentBridgeSessionImpl = class {
37872
37889
  // settlement after the ack). Flushed once the turn ends and the session is
37873
37890
  // idle.
37874
37891
  deferredMessages = [];
37892
+ // Consumed-command ids per enqueued turn, in injection order. Results arrive
37893
+ // in turn order, so each terminal `result` settles the OLDEST open entry —
37894
+ // which is also why an interrupted turn's result (arriving after the
37895
+ // interrupter enqueued) still resolves to the interrupted command. A
37896
+ // deferred flush enqueues one concatenated turn, so its entry carries every
37897
+ // flushed command id.
37898
+ openTurnCommandIds = [];
37875
37899
  // tool_use ids the assistant has emitted whose tool_result has not yet been
37876
37900
  // observed. A non-empty set means a tool call is in flight, so an immediate
37877
37901
  // interrupt would append the new user message after an unresolved
@@ -37933,6 +37957,7 @@ var ClaudeAgentBridgeSessionImpl = class {
37933
37957
  }
37934
37958
  async sendMessage(message, options) {
37935
37959
  const mode = options?.mode ?? "interrupt";
37960
+ const commandIds = options?.commandId ? [options.commandId] : [];
37936
37961
  const startedAt = Date.now();
37937
37962
  this.input.runtimeLogger?.info("agent_bridge_claude_send_message_started", {
37938
37963
  delivery_mode: mode,
@@ -37942,7 +37967,7 @@ var ClaudeAgentBridgeSessionImpl = class {
37942
37967
  deferred_count: this.deferredMessages.length
37943
37968
  });
37944
37969
  if (mode === "deferred" && this.hasInterruptibleTurn()) {
37945
- this.deferredMessages.push(message);
37970
+ this.deferredMessages.push({ text: message, commandIds });
37946
37971
  this.input.runtimeLogger?.info("agent_bridge_claude_message_deferred", {
37947
37972
  active_turn_count: this.activeTurnCount,
37948
37973
  pending_tool_use_count: this.pendingToolUseIds.size,
@@ -37952,7 +37977,7 @@ var ClaudeAgentBridgeSessionImpl = class {
37952
37977
  }
37953
37978
  const interruption = await this.interruptActiveTurnBeforeMessage();
37954
37979
  if (interruption === "defer" && this.hasInterruptibleTurn()) {
37955
- this.deferredMessages.push(message);
37980
+ this.deferredMessages.push({ text: message, commandIds });
37956
37981
  this.input.runtimeLogger?.info(
37957
37982
  "agent_bridge_claude_message_deferred_after_interrupt_timeout",
37958
37983
  {
@@ -37964,7 +37989,7 @@ var ClaudeAgentBridgeSessionImpl = class {
37964
37989
  return;
37965
37990
  }
37966
37991
  await this.awaitMcpRegistration();
37967
- this.enqueueUserMessage(message);
37992
+ this.enqueueUserMessage(message, commandIds);
37968
37993
  this.input.runtimeLogger?.info("agent_bridge_claude_send_message_queued", {
37969
37994
  delivery_mode: mode,
37970
37995
  duration_ms: Date.now() - startedAt,
@@ -37974,6 +37999,20 @@ var ClaudeAgentBridgeSessionImpl = class {
37974
37999
  deferred_count: this.deferredMessages.length
37975
38000
  });
37976
38001
  }
38002
+ noteActiveTurnCommand(commandId) {
38003
+ const activeTurn = this.openTurnCommandIds[0];
38004
+ if (activeTurn) {
38005
+ activeTurn.push(commandId);
38006
+ }
38007
+ this.input.runtimeLogger?.info(
38008
+ "agent_bridge_claude_active_turn_command_noted",
38009
+ {
38010
+ attributed: Boolean(activeTurn),
38011
+ active_turn_count: this.activeTurnCount,
38012
+ open_turn_entries: this.openTurnCommandIds.length
38013
+ }
38014
+ );
38015
+ }
37977
38016
  close() {
37978
38017
  const previousState = this.state;
37979
38018
  if (previousState.kind === "closed") {
@@ -37989,6 +38028,7 @@ var ClaudeAgentBridgeSessionImpl = class {
37989
38028
  );
37990
38029
  this.deferredMessages.length = 0;
37991
38030
  }
38031
+ this.openTurnCommandIds.length = 0;
37992
38032
  this.stderr.flush();
37993
38033
  this.inputQueue.close();
37994
38034
  if (previousState.kind === "started") {
@@ -38072,8 +38112,12 @@ var ClaudeAgentBridgeSessionImpl = class {
38072
38112
  try {
38073
38113
  for await (const message of query) {
38074
38114
  this.trackToolUseLifecycle(message);
38115
+ let meta3;
38075
38116
  if (isClaudeAgentTurnResult(message)) {
38076
38117
  this.activeTurnCount = Math.max(0, this.activeTurnCount - 1);
38118
+ meta3 = {
38119
+ consumedCommandIds: this.openTurnCommandIds.shift() ?? []
38120
+ };
38077
38121
  this.pendingToolUseIds.clear();
38078
38122
  this.turnResultCount += 1;
38079
38123
  this.resolveTurnSettlement(true);
@@ -38081,7 +38125,8 @@ var ClaudeAgentBridgeSessionImpl = class {
38081
38125
  active_turn_count: this.activeTurnCount,
38082
38126
  pending_tool_use_count: this.pendingToolUseIds.size,
38083
38127
  turn_result_count: this.turnResultCount,
38084
- deferred_count: this.deferredMessages.length
38128
+ deferred_count: this.deferredMessages.length,
38129
+ consumed_command_ids: meta3.consumedCommandIds
38085
38130
  });
38086
38131
  if (this.activeTurnCount === 0) {
38087
38132
  this.flushDeferredMessages();
@@ -38101,7 +38146,7 @@ var ClaudeAgentBridgeSessionImpl = class {
38101
38146
  this.close();
38102
38147
  return;
38103
38148
  }
38104
- await this.input.onMessage(message);
38149
+ await this.input.onMessage(message, meta3);
38105
38150
  }
38106
38151
  } catch (error51) {
38107
38152
  if (this.state.kind !== "closed") {
@@ -38109,6 +38154,7 @@ var ClaudeAgentBridgeSessionImpl = class {
38109
38154
  }
38110
38155
  } finally {
38111
38156
  this.activeTurnCount = 0;
38157
+ this.openTurnCommandIds.length = 0;
38112
38158
  this.pendingToolUseIds.clear();
38113
38159
  this.resolveTurnSettlement(false);
38114
38160
  this.state = { kind: "closed" };
@@ -38120,9 +38166,10 @@ var ClaudeAgentBridgeSessionImpl = class {
38120
38166
  // lets injection work while the SDK session is still starting; the queue
38121
38167
  // drains once the query attaches. Startup failures surface through onError
38122
38168
  // instead of failing injection.
38123
- enqueueUserMessage(message) {
38169
+ enqueueUserMessage(message, commandIds) {
38124
38170
  this.inputQueue.push(claudeAgentUserMessage(message));
38125
38171
  this.activeTurnCount += 1;
38172
+ this.openTurnCommandIds.push(commandIds);
38126
38173
  this.input.runtimeLogger?.info("agent_bridge_claude_message_enqueued", {
38127
38174
  state: this.state.kind,
38128
38175
  active_turn_count: this.activeTurnCount,
@@ -38206,7 +38253,10 @@ var ClaudeAgentBridgeSessionImpl = class {
38206
38253
  this.input.writeOutput?.(
38207
38254
  `agent_bridge_claude_deferred_flush count=${pending.length}`
38208
38255
  );
38209
- this.enqueueUserMessage(pending.join("\n\n"));
38256
+ this.enqueueUserMessage(
38257
+ pending.map((entry) => entry.text).join("\n\n"),
38258
+ pending.flatMap((entry) => entry.commandIds)
38259
+ );
38210
38260
  }
38211
38261
  async interruptActiveTurnBeforeMessage() {
38212
38262
  if (!this.hasInterruptibleTurn()) {
@@ -38873,7 +38923,8 @@ var ClaudeCodeCommandHandler = class {
38873
38923
  })
38874
38924
  );
38875
38925
  await this.ensureAgentSession().sendMessage(message, {
38876
- mode
38926
+ mode,
38927
+ commandId: delivery.commandId
38877
38928
  });
38878
38929
  this.input.runtimeLogger?.info(
38879
38930
  "agent_bridge_claude_command_send_message_ready",
@@ -38928,6 +38979,7 @@ var ClaudeCodeCommandHandler = class {
38928
38979
  const pending = this.pendingQuestions.get(answer.toolCallId);
38929
38980
  if (pending) {
38930
38981
  this.pendingQuestions.delete(answer.toolCallId);
38982
+ this.agentSession?.noteActiveTurnCommand(delivery.commandId);
38931
38983
  pending.resolve({
38932
38984
  behavior: "allow",
38933
38985
  updatedInput: {
@@ -38954,7 +39006,9 @@ var ClaudeCodeCommandHandler = class {
38954
39006
  }
38955
39007
  }
38956
39008
  });
38957
- await this.ensureAgentSession().sendMessage(message);
39009
+ await this.ensureAgentSession().sendMessage(message, {
39010
+ commandId: delivery.commandId
39011
+ });
38958
39012
  this.input.writeOutput?.(
38959
39013
  `agent_bridge_question_answer_fallback tool_use_id=${answer.toolCallId}`
38960
39014
  );
@@ -39010,7 +39064,7 @@ var ClaudeCodeCommandHandler = class {
39010
39064
  );
39011
39065
  }
39012
39066
  }
39013
- async handleAgentMessage(message) {
39067
+ async handleAgentMessage(message, meta3) {
39014
39068
  const activeContext = this.context;
39015
39069
  if (!activeContext) {
39016
39070
  return;
@@ -39026,7 +39080,10 @@ var ClaudeCodeCommandHandler = class {
39026
39080
  return;
39027
39081
  }
39028
39082
  for (const projection of projections) {
39029
- await this.emitBridgeOutput(activeContext, projection);
39083
+ await this.emitBridgeOutput(
39084
+ activeContext,
39085
+ withConsumedCommandIds(projection, meta3)
39086
+ );
39030
39087
  }
39031
39088
  }
39032
39089
  async handleAgentError(error51) {
@@ -39094,7 +39151,7 @@ var ClaudeCodeCommandHandler = class {
39094
39151
  claude: this.input.claude,
39095
39152
  resumeAgentId: this.storedResumeAgentId(),
39096
39153
  canUseTool: this.canUseTool,
39097
- onMessage: (message) => this.handleAgentMessage(message),
39154
+ onMessage: (message, meta3) => this.handleAgentMessage(message, meta3),
39098
39155
  onError: (error51) => this.handleAgentError(error51),
39099
39156
  onExit: () => {
39100
39157
  if (this.agentSession === session) {
@@ -39109,6 +39166,13 @@ var ClaudeCodeCommandHandler = class {
39109
39166
  return session;
39110
39167
  }
39111
39168
  };
39169
+ function withConsumedCommandIds(projection, meta3) {
39170
+ const consumedCommandIds = meta3?.consumedCommandIds;
39171
+ if (!consumedCommandIds || consumedCommandIds.length === 0 || projection.type !== "ui_message_chunk" || !projection.turnStatus) {
39172
+ return projection;
39173
+ }
39174
+ return { ...projection, consumedCommandIds };
39175
+ }
39112
39176
  function answerFallbackMessage(answer) {
39113
39177
  const lines = Object.entries(answer.answers).map(
39114
39178
  ([question, value]) => `- ${question}: ${value}`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@autohq/cli",
3
- "version": "0.1.309",
3
+ "version": "0.1.311",
4
4
  "license": "SEE LICENSE IN README.md",
5
5
  "publishConfig": {
6
6
  "access": "public"