@autohq/cli 0.1.565 → 0.1.567

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.
@@ -27222,13 +27222,23 @@ var RuntimeBridgeOutputLivenessEnvelopeSchema = external_exports.object({
27222
27222
  intervalMs: external_exports.number().int().positive(),
27223
27223
  createdAt: external_exports.string().datetime()
27224
27224
  });
27225
+ var RuntimeBridgeOutputUsageTurnEnvelopeSchema = external_exports.object({
27226
+ type: external_exports.literal("runtime.usage_turn"),
27227
+ sessionId: SessionIdSchema,
27228
+ runtimeId: RuntimeIdSchema,
27229
+ bridgeLeaseId: RuntimeBridgeLeaseIdSchema,
27230
+ outputSeq: external_exports.number().int().positive(),
27231
+ turnId: SessionCommandIdSchema.nullable(),
27232
+ createdAt: external_exports.string().datetime()
27233
+ });
27225
27234
  var RuntimeBridgeOutputEnvelopeSchema = external_exports.union([
27226
27235
  RuntimeBridgeOutputEntryEnvelopeSchema,
27227
27236
  RuntimeBridgeOutputDeltaEnvelopeSchema,
27228
27237
  RuntimeBridgeOutputUiMessageChunkEnvelopeSchema,
27229
27238
  RuntimeBridgeOutputUiMessagePartEnvelopeSchema,
27230
27239
  RuntimeBridgeOutputUiMessageCompletedEnvelopeSchema,
27231
- RuntimeBridgeOutputLivenessEnvelopeSchema
27240
+ RuntimeBridgeOutputLivenessEnvelopeSchema,
27241
+ RuntimeBridgeOutputUsageTurnEnvelopeSchema
27232
27242
  ]);
27233
27243
  function isLiveOnlyRuntimeOutputEnvelope(envelope) {
27234
27244
  return envelope.type === "ui.message.chunk" || envelope.type === "conversation.delta";
@@ -30870,7 +30880,7 @@ Object.assign(lookup, {
30870
30880
  // package.json
30871
30881
  var package_default = {
30872
30882
  name: "@autohq/cli",
30873
- version: "0.1.565",
30883
+ version: "0.1.567",
30874
30884
  license: "SEE LICENSE IN README.md",
30875
30885
  publishConfig: {
30876
30886
  access: "public"
@@ -37691,7 +37701,12 @@ var OrganizationBillingSettingsSchema = external_exports.object({
37691
37701
  stripeDefaultPaymentMethodId: external_exports.string().trim().min(1).nullable(),
37692
37702
  // Safe provenance used server-side to reject a test/live mismatch before a
37693
37703
  // real charge attempt. Null preserves compatibility with legacy rows.
37694
- stripeDefaultPaymentMethodLivemode: external_exports.boolean().nullable().default(null)
37704
+ stripeDefaultPaymentMethodLivemode: external_exports.boolean().nullable().default(null),
37705
+ // The payment method whose most recent off-session charge failed, so the
37706
+ // payment-methods list can flag the exact card. Cleared when that method
37707
+ // charges successfully or is detached.
37708
+ stripePaymentMethodAttentionId: external_exports.string().trim().min(1).nullable().default(null),
37709
+ stripePaymentMethodAttentionAt: external_exports.string().datetime().nullable().default(null)
37695
37710
  });
37696
37711
  var UpdateOrganizationBillingSettingsRequestSchema = external_exports.object({
37697
37712
  spendLimitDayUsd: PositiveUsdSchema.nullable().optional(),
@@ -37726,15 +37741,52 @@ var AddOrganizationCreditsRequestSchema = external_exports.object({
37726
37741
  var ReturnPathSchema = external_exports.string().trim().min(1).max(2e3).regex(/^\/(?!\/)/, "returnPath must be an absolute in-app path");
37727
37742
  var CreateCreditPurchaseRequestSchema = external_exports.object({
37728
37743
  amountUsd: ChargeableUsdSchema,
37729
- returnPath: ReturnPathSchema
37744
+ idempotencyKey: external_exports.string().trim().regex(/^[A-Za-z0-9_-]{8,64}$/)
37730
37745
  }).strict();
37746
+ var CreditPurchaseResponseSchema = external_exports.discriminatedUnion("status", [
37747
+ external_exports.object({
37748
+ status: external_exports.literal("succeeded"),
37749
+ event: CreditEventRecordSchema
37750
+ }),
37751
+ external_exports.object({
37752
+ status: external_exports.literal("processing"),
37753
+ paymentIntentId: external_exports.string().trim().min(1)
37754
+ })
37755
+ ]);
37731
37756
  var AutoReloadSetupValuesSchema = external_exports.object({
37732
37757
  thresholdUsd: AutoTopUpThresholdUsdSchema,
37733
37758
  amountUsd: ChargeableUsdSchema
37734
37759
  }).strict();
37735
- var CreateAutoReloadSetupRequestSchema = AutoReloadSetupValuesSchema.extend({
37760
+ var PAYMENT_METHOD_STATUSES = [
37761
+ "ok",
37762
+ "expired",
37763
+ "requires_attention"
37764
+ ];
37765
+ var OrganizationPaymentMethodStatusSchema = external_exports.enum(
37766
+ PAYMENT_METHOD_STATUSES
37767
+ );
37768
+ var OrganizationPaymentMethodSchema = external_exports.object({
37769
+ id: external_exports.string().trim().min(1),
37770
+ brand: external_exports.string().trim().min(1),
37771
+ last4: external_exports.string().trim().min(1),
37772
+ expMonth: external_exports.number().int().min(1).max(12),
37773
+ expYear: external_exports.number().int(),
37774
+ // The org's preferred payment method: the one purchases and auto-top-up
37775
+ // charge. At most one method is default.
37776
+ isDefault: external_exports.boolean(),
37777
+ status: OrganizationPaymentMethodStatusSchema,
37778
+ createdAt: external_exports.string().datetime()
37779
+ });
37780
+ var OrganizationPaymentMethodsResponseSchema = external_exports.object({
37781
+ organizationId: OrganizationIdSchema,
37782
+ paymentMethods: external_exports.array(OrganizationPaymentMethodSchema)
37783
+ });
37784
+ var CreatePaymentMethodSetupSessionRequestSchema = external_exports.object({
37736
37785
  returnPath: ReturnPathSchema
37737
37786
  }).strict();
37787
+ var UpdateOrganizationPaymentMethodRequestSchema = external_exports.object({
37788
+ default: external_exports.literal(true)
37789
+ }).strict();
37738
37790
  var CreateBillingPortalSessionRequestSchema = external_exports.object({
37739
37791
  returnPath: ReturnPathSchema
37740
37792
  }).strict();
@@ -38693,6 +38745,10 @@ var UsageEventSchema = external_exports.object({
38693
38745
  organizationId: OrganizationIdSchema,
38694
38746
  projectId: ProjectIdSchema.nullable(),
38695
38747
  sessionId: SessionIdSchema2,
38748
+ // Authoritative platform turn association. Null/absent is an explicit
38749
+ // compatibility state for legacy writers and usage outside a model turn;
38750
+ // readers must never infer it from timestamps or ledger order.
38751
+ turnId: SessionCommandIdSchema2.nullable().optional(),
38696
38752
  agentResourceId: external_exports.string().trim().min(1),
38697
38753
  harness: UsageHarnessSchema,
38698
38754
  // The concrete model id the call billed against (e.g. "claude-opus-4-8"),
@@ -38730,6 +38786,7 @@ var UsageEventSchema = external_exports.object({
38730
38786
  });
38731
38787
  var UsageEventRecordSchema = UsageEventSchema.extend({
38732
38788
  id: external_exports.string().trim().min(1),
38789
+ turnId: SessionCommandIdSchema2.nullable().default(null),
38733
38790
  attributionEpochId: SessionAttributionEpochIdSchema.nullable().default(null),
38734
38791
  requesterKey: external_exports.string().trim().min(1).nullable().default(null),
38735
38792
  attributionGrade: AttributionGradeSchema.nullable().default(null),
@@ -39013,6 +39070,7 @@ var RunModelFallbackSchema = external_exports.object({
39013
39070
  fallbackModelId: external_exports.string().nullable()
39014
39071
  });
39015
39072
  var RUN_USAGE_BREAKDOWN_LIMIT = 8;
39073
+ var RUN_USAGE_TURN_LIMIT = 50;
39016
39074
  var RunUsageTotalsSchema = external_exports.object({
39017
39075
  eventCount: external_exports.number().int().nonnegative(),
39018
39076
  inputTokens: external_exports.number().int().nonnegative(),
@@ -39035,6 +39093,15 @@ var RunUsageHarnessModelSchema = RunUsageTotalsSchema.extend({
39035
39093
  harness: UsageHarnessSchema,
39036
39094
  model: external_exports.string().trim().min(1)
39037
39095
  });
39096
+ var RunUsageTurnSchema = RunUsageTotalsSchema.extend({
39097
+ /** Immutable platform-issued session turn identity. */
39098
+ turnId: SessionCommandIdSchema2,
39099
+ /**
39100
+ * Immutable turn creation time. The series is ordered oldest-to-newest by
39101
+ * this field, then turnId, within the bounded most-recent window.
39102
+ */
39103
+ turnCreatedAt: external_exports.string().datetime()
39104
+ });
39038
39105
  var RunUsageSummarySchema = external_exports.object({
39039
39106
  totals: RunUsageTotalsSchema,
39040
39107
  /**
@@ -39048,7 +39115,15 @@ var RunUsageSummarySchema = external_exports.object({
39048
39115
  }),
39049
39116
  /** Highest derived-cost harness/model groups, in descending spend order. */
39050
39117
  byHarnessModel: external_exports.array(RunUsageHarnessModelSchema).max(RUN_USAGE_BREAKDOWN_LIMIT),
39051
- breakdownTruncated: external_exports.boolean()
39118
+ breakdownTruncated: external_exports.boolean(),
39119
+ /** Most recent authoritative turn aggregates, returned oldest-to-newest. */
39120
+ byTurn: external_exports.array(RunUsageTurnSchema).max(RUN_USAGE_TURN_LIMIT),
39121
+ turnBreakdownTruncated: external_exports.boolean(),
39122
+ /**
39123
+ * Current events with no authoritative turn id. These remain in session
39124
+ * totals but are excluded from byTurn rather than guessed into a turn.
39125
+ */
39126
+ unassociated: RunUsageTotalsSchema
39052
39127
  });
39053
39128
  var RunSummarySchema = external_exports.object({
39054
39129
  session: external_exports.object({
@@ -71908,6 +71983,9 @@ function replacePayloadWithMarker(envelope, originalBytes) {
71908
71983
  parts: [{ type: "text", text: text2, state: "done" }]
71909
71984
  }
71910
71985
  };
71986
+ case "runtime.liveness":
71987
+ case "runtime.usage_turn":
71988
+ return envelope;
71911
71989
  }
71912
71990
  }
71913
71991
 
@@ -72340,6 +72418,23 @@ var AgentBridgeOutputBuffer = class {
72340
72418
  );
72341
72419
  await this.drainPendingOutputs();
72342
72420
  }
72421
+ /**
72422
+ * Publish and await the active immutable platform turn before model work.
72423
+ * Unlike liveness, every transition is retained and replayed: skipping one
72424
+ * could attribute a billed call to the preceding turn.
72425
+ */
72426
+ async emitUsageTurn(context, turnId) {
72427
+ this.outputSeq += 1;
72428
+ this.enqueueOutput(
72429
+ buildUsageTurnOutputEnvelope({
72430
+ context,
72431
+ outputSeq: this.outputSeq,
72432
+ turnId,
72433
+ createdAt: now2()
72434
+ })
72435
+ );
72436
+ await this.drainPendingOutputs({ failIfBlocked: true });
72437
+ }
72343
72438
  async emitUiMessageChunk(context, projection) {
72344
72439
  await this.flushPendingDelta();
72345
72440
  await this.emitLiveUiMessageChunk(context, projection.chunk);
@@ -73120,6 +73215,18 @@ function buildLivenessOutputEnvelope(input) {
73120
73215
  createdAt: input.createdAt
73121
73216
  });
73122
73217
  }
73218
+ function buildUsageTurnOutputEnvelope(input) {
73219
+ const { context } = input;
73220
+ return RuntimeBridgeOutputEnvelopeSchema.parse({
73221
+ type: "runtime.usage_turn",
73222
+ sessionId: context.sessionId,
73223
+ runtimeId: context.runtimeId,
73224
+ bridgeLeaseId: context.bridgeLeaseId,
73225
+ outputSeq: input.outputSeq,
73226
+ turnId: input.turnId,
73227
+ createdAt: input.createdAt
73228
+ });
73229
+ }
73123
73230
  function buildUiMessagePartOutputEnvelope(input) {
73124
73231
  const { context, snapshot } = input;
73125
73232
  return RuntimeBridgeOutputEnvelopeSchema.parse({
@@ -74404,7 +74511,7 @@ var ClaudeAgentBridgeSessionImpl = class {
74404
74511
  return;
74405
74512
  }
74406
74513
  await this.awaitMcpRegistration();
74407
- this.enqueueUserMessage(message, commandIds);
74514
+ await this.enqueueUserMessage(message, commandIds);
74408
74515
  this.input.runtimeLogger?.info("agent_bridge_claude_send_message_queued", {
74409
74516
  delivery_mode: mode,
74410
74517
  duration_ms: Date.now() - startedAt,
@@ -74510,6 +74617,7 @@ var ClaudeAgentBridgeSessionImpl = class {
74510
74617
  }
74511
74618
  this.openTurnCommandIds.length = 0;
74512
74619
  this.publishActiveTurnCommandIds();
74620
+ void this.input.onUsageTurnChanged?.(null);
74513
74621
  this.stderr.flush();
74514
74622
  this.inputQueue.close();
74515
74623
  if (previousState.kind === "started") {
@@ -74603,6 +74711,7 @@ var ClaudeAgentBridgeSessionImpl = class {
74603
74711
  consumedCommandIds: this.openTurnCommandIds.shift() ?? []
74604
74712
  };
74605
74713
  this.publishActiveTurnCommandIds();
74714
+ await this.input.onUsageTurnChanged?.(null);
74606
74715
  this.pendingToolUses.clear();
74607
74716
  this.interruptSettling = false;
74608
74717
  this.turnResultCount += 1;
@@ -74614,7 +74723,7 @@ var ClaudeAgentBridgeSessionImpl = class {
74614
74723
  consumed_command_ids: meta3.consumedCommandIds
74615
74724
  });
74616
74725
  if (this.activeTurnCount === 0) {
74617
- this.flushDeferredMessages();
74726
+ await this.flushDeferredMessages();
74618
74727
  }
74619
74728
  if (this.deferredMessages.length === 0) {
74620
74729
  this.cancelledToolRuns = [];
@@ -74644,6 +74753,7 @@ var ClaudeAgentBridgeSessionImpl = class {
74644
74753
  this.activeTurnCount = 0;
74645
74754
  this.openTurnCommandIds.length = 0;
74646
74755
  this.publishActiveTurnCommandIds();
74756
+ await this.input.onUsageTurnChanged?.(null);
74647
74757
  this.pendingToolUses.clear();
74648
74758
  this.interruptSettling = false;
74649
74759
  this.disarmToolBoundaryWait();
@@ -74656,7 +74766,8 @@ var ClaudeAgentBridgeSessionImpl = class {
74656
74766
  // lets injection work while the SDK session is still starting; the queue
74657
74767
  // drains once the query attaches. Startup failures surface through onError
74658
74768
  // instead of failing injection.
74659
- enqueueUserMessage(message, commandIds) {
74769
+ async enqueueUserMessage(message, commandIds) {
74770
+ await this.input.onUsageTurnChanged?.(commandIds[0] ?? null);
74660
74771
  this.inputQueue.push(claudeAgentUserMessage(message));
74661
74772
  this.activeTurnCount += 1;
74662
74773
  this.openTurnCommandIds.push(commandIds);
@@ -74764,7 +74875,7 @@ var ClaudeAgentBridgeSessionImpl = class {
74764
74875
  clearTimeout(this.toolBoundaryWait.timer);
74765
74876
  this.toolBoundaryWait = null;
74766
74877
  }
74767
- flushDeferredMessages() {
74878
+ async flushDeferredMessages() {
74768
74879
  if (this.deferredMessages.length === 0) {
74769
74880
  return;
74770
74881
  }
@@ -74775,7 +74886,7 @@ var ClaudeAgentBridgeSessionImpl = class {
74775
74886
  `agent_bridge_claude_deferred_flush count=${pending.length} cancelled_tool_count=${cancelledToolRuns.length}`
74776
74887
  );
74777
74888
  const text2 = pending.map((entry) => entry.text).join("\n\n");
74778
- this.enqueueUserMessage(
74889
+ await this.enqueueUserMessage(
74779
74890
  cancelledToolRuns.length > 0 ? `${text2}
74780
74891
 
74781
74892
  ${cancelledToolPlatformNotice(cancelledToolRuns)}` : text2,
@@ -75692,6 +75803,13 @@ var ClaudeCodeCommandHandler = class {
75692
75803
  RUNTIME_LIVENESS_INTERVAL_MS
75693
75804
  );
75694
75805
  }
75806
+ async emitUsageTurn(turnId) {
75807
+ const activeContext = this.context;
75808
+ if (!activeContext) {
75809
+ throw new Error("Cannot publish usage turn without bridge context");
75810
+ }
75811
+ await this.outputBuffer.emitUsageTurn(activeContext, turnId);
75812
+ }
75695
75813
  async emitBridgeOutput(activeContext, projection) {
75696
75814
  try {
75697
75815
  await this.outputBuffer.emitProjection(activeContext, projection);
@@ -75859,6 +75977,7 @@ var ClaudeCodeCommandHandler = class {
75859
75977
  }
75860
75978
  },
75861
75979
  onActiveTurnCommandIds: (commandIds) => this.autoMcpShim.setActiveTurnCommandIds(commandIds),
75980
+ onUsageTurnChanged: (turnId) => this.emitUsageTurn(turnId),
75862
75981
  canUseTool: this.canUseTool,
75863
75982
  onMessage: (message, meta3) => this.handleAgentMessage(message, meta3),
75864
75983
  onError: (error51) => this.handleAgentError(error51),
@@ -77067,6 +77186,7 @@ var CodexAgentBridgeSessionImpl = class {
77067
77186
  this.pendingCommandIds = [...commandIds];
77068
77187
  this.publishActiveTurnCommandIds(commandIds);
77069
77188
  try {
77189
+ await this.input.onUsageTurnChanged?.(commandIds[0] ?? null);
77070
77190
  await this.request("turn/start", {
77071
77191
  threadId,
77072
77192
  input: [userTextInput(message)]
@@ -77074,6 +77194,7 @@ var CodexAgentBridgeSessionImpl = class {
77074
77194
  } catch (error51) {
77075
77195
  this.pendingCommandIds = [];
77076
77196
  this.publishActiveTurnCommandIds();
77197
+ await this.input.onUsageTurnChanged?.(null);
77077
77198
  throw error51;
77078
77199
  }
77079
77200
  }
@@ -77081,6 +77202,7 @@ var CodexAgentBridgeSessionImpl = class {
77081
77202
  this.pendingCommandIds = [...commandIds];
77082
77203
  this.publishActiveTurnCommandIds(commandIds);
77083
77204
  try {
77205
+ await this.input.onUsageTurnChanged?.(commandIds[0] ?? null);
77084
77206
  await this.request("turn/start", {
77085
77207
  threadId,
77086
77208
  input: []
@@ -77088,6 +77210,7 @@ var CodexAgentBridgeSessionImpl = class {
77088
77210
  } catch (error51) {
77089
77211
  this.pendingCommandIds = [];
77090
77212
  this.publishActiveTurnCommandIds();
77213
+ await this.input.onUsageTurnChanged?.(null);
77091
77214
  throw error51;
77092
77215
  }
77093
77216
  }
@@ -77451,6 +77574,7 @@ var CodexAgentBridgeSessionImpl = class {
77451
77574
  this.activeTurnId = null;
77452
77575
  this.activeCommandIds = [];
77453
77576
  this.publishActiveTurnCommandIds();
77577
+ void this.input.onUsageTurnChanged?.(null);
77454
77578
  }
77455
77579
  this.pendingToolItemIds.clear();
77456
77580
  this.resolveSettlement();
@@ -77466,6 +77590,7 @@ var CodexAgentBridgeSessionImpl = class {
77466
77590
  this.activeCommandIds = [];
77467
77591
  this.pendingCommandIds = [];
77468
77592
  this.publishActiveTurnCommandIds();
77593
+ void this.input.onUsageTurnChanged?.(null);
77469
77594
  this.pendingToolItemIds.clear();
77470
77595
  this.resolveSettlement();
77471
77596
  this.input.writeOutput?.(`agent_bridge_codex_exited code=${code ?? ""}`);
@@ -77861,6 +77986,13 @@ var CodexCommandHandler = class {
77861
77986
  RUNTIME_LIVENESS_INTERVAL_MS
77862
77987
  );
77863
77988
  }
77989
+ async emitUsageTurn(turnId) {
77990
+ const activeContext = this.context;
77991
+ if (!activeContext) {
77992
+ throw new Error("Cannot publish usage turn without bridge context");
77993
+ }
77994
+ await this.outputBuffer.emitUsageTurn(activeContext, turnId);
77995
+ }
77864
77996
  async emit(activeContext, projection) {
77865
77997
  try {
77866
77998
  await this.outputBuffer.emitProjection(activeContext, projection);
@@ -77883,6 +78015,7 @@ var CodexCommandHandler = class {
77883
78015
  onServerRequest: (request) => this.handleServerRequest(request),
77884
78016
  onThreadId: (threadId) => this.persistThreadId(threadId),
77885
78017
  onActiveTurnCommandIds: (commandIds) => this.autoMcpShim.setActiveTurnCommandIds(commandIds),
78018
+ onUsageTurnChanged: (turnId) => this.emitUsageTurn(turnId),
77886
78019
  onError: (error51) => this.handleSessionError(error51),
77887
78020
  onExit: () => {
77888
78021
  if (this.session === session) {
package/dist/index.js CHANGED
@@ -21764,7 +21764,7 @@ var init_organization_settings = __esm({
21764
21764
  });
21765
21765
 
21766
21766
  // ../../packages/schemas/src/billing.ts
21767
- var FEE_CARD_2026_07_06, BILLING_FEE_CARDS, CURRENT_BILLING_FEE_VERSION, CREDIT_EVENT_TYPES, CreditEventTypeSchema, UsdAmountSchema, NonNegativeUsdSchema, PositiveUsdSchema, MIN_CREDIT_PURCHASE_USD, MAX_CREDIT_PURCHASE_USD, wholeCents, ChargeableUsdSchema, AutoTopUpThresholdUsdSchema, CreditEventSchema, CreditEventRecordSchema, SPENDING_LIMIT_WINDOWS, SpendingLimitWindowSchema, BilledSpendWindowsSchema, OrganizationBillingSettingsSchema, UpdateOrganizationBillingSettingsRequestSchema, OrganizationCreditsResponseSchema, AddOrganizationCreditsRequestSchema, ReturnPathSchema, CreateCreditPurchaseRequestSchema, AutoReloadSetupValuesSchema, CreateAutoReloadSetupRequestSchema, CreateBillingPortalSessionRequestSchema;
21767
+ var FEE_CARD_2026_07_06, BILLING_FEE_CARDS, CURRENT_BILLING_FEE_VERSION, CREDIT_EVENT_TYPES, CreditEventTypeSchema, UsdAmountSchema, NonNegativeUsdSchema, PositiveUsdSchema, MIN_CREDIT_PURCHASE_USD, MAX_CREDIT_PURCHASE_USD, wholeCents, ChargeableUsdSchema, AutoTopUpThresholdUsdSchema, CreditEventSchema, CreditEventRecordSchema, SPENDING_LIMIT_WINDOWS, SpendingLimitWindowSchema, BilledSpendWindowsSchema, OrganizationBillingSettingsSchema, UpdateOrganizationBillingSettingsRequestSchema, OrganizationCreditsResponseSchema, AddOrganizationCreditsRequestSchema, ReturnPathSchema, CreateCreditPurchaseRequestSchema, CreditPurchaseResponseSchema, AutoReloadSetupValuesSchema, PAYMENT_METHOD_STATUSES, OrganizationPaymentMethodStatusSchema, OrganizationPaymentMethodSchema, OrganizationPaymentMethodsResponseSchema, CreatePaymentMethodSetupSessionRequestSchema, UpdateOrganizationPaymentMethodRequestSchema, CreateBillingPortalSessionRequestSchema;
21768
21768
  var init_billing = __esm({
21769
21769
  "../../packages/schemas/src/billing.ts"() {
21770
21770
  "use strict";
@@ -21853,7 +21853,12 @@ var init_billing = __esm({
21853
21853
  stripeDefaultPaymentMethodId: external_exports.string().trim().min(1).nullable(),
21854
21854
  // Safe provenance used server-side to reject a test/live mismatch before a
21855
21855
  // real charge attempt. Null preserves compatibility with legacy rows.
21856
- stripeDefaultPaymentMethodLivemode: external_exports.boolean().nullable().default(null)
21856
+ stripeDefaultPaymentMethodLivemode: external_exports.boolean().nullable().default(null),
21857
+ // The payment method whose most recent off-session charge failed, so the
21858
+ // payment-methods list can flag the exact card. Cleared when that method
21859
+ // charges successfully or is detached.
21860
+ stripePaymentMethodAttentionId: external_exports.string().trim().min(1).nullable().default(null),
21861
+ stripePaymentMethodAttentionAt: external_exports.string().datetime().nullable().default(null)
21857
21862
  });
21858
21863
  UpdateOrganizationBillingSettingsRequestSchema = external_exports.object({
21859
21864
  spendLimitDayUsd: PositiveUsdSchema.nullable().optional(),
@@ -21888,15 +21893,52 @@ var init_billing = __esm({
21888
21893
  ReturnPathSchema = external_exports.string().trim().min(1).max(2e3).regex(/^\/(?!\/)/, "returnPath must be an absolute in-app path");
21889
21894
  CreateCreditPurchaseRequestSchema = external_exports.object({
21890
21895
  amountUsd: ChargeableUsdSchema,
21891
- returnPath: ReturnPathSchema
21896
+ idempotencyKey: external_exports.string().trim().regex(/^[A-Za-z0-9_-]{8,64}$/)
21892
21897
  }).strict();
21898
+ CreditPurchaseResponseSchema = external_exports.discriminatedUnion("status", [
21899
+ external_exports.object({
21900
+ status: external_exports.literal("succeeded"),
21901
+ event: CreditEventRecordSchema
21902
+ }),
21903
+ external_exports.object({
21904
+ status: external_exports.literal("processing"),
21905
+ paymentIntentId: external_exports.string().trim().min(1)
21906
+ })
21907
+ ]);
21893
21908
  AutoReloadSetupValuesSchema = external_exports.object({
21894
21909
  thresholdUsd: AutoTopUpThresholdUsdSchema,
21895
21910
  amountUsd: ChargeableUsdSchema
21896
21911
  }).strict();
21897
- CreateAutoReloadSetupRequestSchema = AutoReloadSetupValuesSchema.extend({
21912
+ PAYMENT_METHOD_STATUSES = [
21913
+ "ok",
21914
+ "expired",
21915
+ "requires_attention"
21916
+ ];
21917
+ OrganizationPaymentMethodStatusSchema = external_exports.enum(
21918
+ PAYMENT_METHOD_STATUSES
21919
+ );
21920
+ OrganizationPaymentMethodSchema = external_exports.object({
21921
+ id: external_exports.string().trim().min(1),
21922
+ brand: external_exports.string().trim().min(1),
21923
+ last4: external_exports.string().trim().min(1),
21924
+ expMonth: external_exports.number().int().min(1).max(12),
21925
+ expYear: external_exports.number().int(),
21926
+ // The org's preferred payment method: the one purchases and auto-top-up
21927
+ // charge. At most one method is default.
21928
+ isDefault: external_exports.boolean(),
21929
+ status: OrganizationPaymentMethodStatusSchema,
21930
+ createdAt: external_exports.string().datetime()
21931
+ });
21932
+ OrganizationPaymentMethodsResponseSchema = external_exports.object({
21933
+ organizationId: OrganizationIdSchema,
21934
+ paymentMethods: external_exports.array(OrganizationPaymentMethodSchema)
21935
+ });
21936
+ CreatePaymentMethodSetupSessionRequestSchema = external_exports.object({
21898
21937
  returnPath: ReturnPathSchema
21899
21938
  }).strict();
21939
+ UpdateOrganizationPaymentMethodRequestSchema = external_exports.object({
21940
+ default: external_exports.literal(true)
21941
+ }).strict();
21900
21942
  CreateBillingPortalSessionRequestSchema = external_exports.object({
21901
21943
  returnPath: ReturnPathSchema
21902
21944
  }).strict();
@@ -23060,6 +23102,10 @@ var init_usage = __esm({
23060
23102
  organizationId: OrganizationIdSchema,
23061
23103
  projectId: ProjectIdSchema.nullable(),
23062
23104
  sessionId: SessionIdSchema,
23105
+ // Authoritative platform turn association. Null/absent is an explicit
23106
+ // compatibility state for legacy writers and usage outside a model turn;
23107
+ // readers must never infer it from timestamps or ledger order.
23108
+ turnId: SessionCommandIdSchema.nullable().optional(),
23063
23109
  agentResourceId: external_exports.string().trim().min(1),
23064
23110
  harness: UsageHarnessSchema,
23065
23111
  // The concrete model id the call billed against (e.g. "claude-opus-4-8"),
@@ -23097,6 +23143,7 @@ var init_usage = __esm({
23097
23143
  });
23098
23144
  UsageEventRecordSchema = UsageEventSchema.extend({
23099
23145
  id: external_exports.string().trim().min(1),
23146
+ turnId: SessionCommandIdSchema.nullable().default(null),
23100
23147
  attributionEpochId: SessionAttributionEpochIdSchema.nullable().default(null),
23101
23148
  requesterKey: external_exports.string().trim().min(1).nullable().default(null),
23102
23149
  attributionGrade: AttributionGradeSchema.nullable().default(null),
@@ -23230,7 +23277,7 @@ var init_usage = __esm({
23230
23277
  });
23231
23278
 
23232
23279
  // ../../packages/schemas/src/session-introspection.ts
23233
- var TruncatedValueSchema, RunConversationSearchSnippetSchema, RunConversationSearchMatchSchema, RunConversationSearchResponseSchema, SessionToolExchangeSchema, SessionToolExchangesResponseSchema, SESSION_TRIGGER_DELIVERY_ACTIONS, SessionTriggerDeliveryActionSchema, SESSION_EVENT_ORIGIN_KINDS, SessionEventOriginKindSchema, SessionTriggerDeliveryRecordSchema, SessionTriggersResponseSchema, RunBindingRecordSchema, RunBindingsResponseSchema, RunTurnSchema, SessionToolStatSchema, RunRuntimeRestartSchema, RunModelFallbackSchema, RUN_USAGE_BREAKDOWN_LIMIT, RunUsageTotalsSchema, RunUsageHarnessModelSchema, RunUsageSummarySchema, RunSummarySchema;
23280
+ var TruncatedValueSchema, RunConversationSearchSnippetSchema, RunConversationSearchMatchSchema, RunConversationSearchResponseSchema, SessionToolExchangeSchema, SessionToolExchangesResponseSchema, SESSION_TRIGGER_DELIVERY_ACTIONS, SessionTriggerDeliveryActionSchema, SESSION_EVENT_ORIGIN_KINDS, SessionEventOriginKindSchema, SessionTriggerDeliveryRecordSchema, SessionTriggersResponseSchema, RunBindingRecordSchema, RunBindingsResponseSchema, RunTurnSchema, SessionToolStatSchema, RunRuntimeRestartSchema, RunModelFallbackSchema, RUN_USAGE_BREAKDOWN_LIMIT, RUN_USAGE_TURN_LIMIT, RunUsageTotalsSchema, RunUsageHarnessModelSchema, RunUsageTurnSchema, RunUsageSummarySchema, RunSummarySchema;
23234
23281
  var init_session_introspection = __esm({
23235
23282
  "../../packages/schemas/src/session-introspection.ts"() {
23236
23283
  "use strict";
@@ -23397,6 +23444,7 @@ var init_session_introspection = __esm({
23397
23444
  fallbackModelId: external_exports.string().nullable()
23398
23445
  });
23399
23446
  RUN_USAGE_BREAKDOWN_LIMIT = 8;
23447
+ RUN_USAGE_TURN_LIMIT = 50;
23400
23448
  RunUsageTotalsSchema = external_exports.object({
23401
23449
  eventCount: external_exports.number().int().nonnegative(),
23402
23450
  inputTokens: external_exports.number().int().nonnegative(),
@@ -23419,6 +23467,15 @@ var init_session_introspection = __esm({
23419
23467
  harness: UsageHarnessSchema,
23420
23468
  model: external_exports.string().trim().min(1)
23421
23469
  });
23470
+ RunUsageTurnSchema = RunUsageTotalsSchema.extend({
23471
+ /** Immutable platform-issued session turn identity. */
23472
+ turnId: SessionCommandIdSchema,
23473
+ /**
23474
+ * Immutable turn creation time. The series is ordered oldest-to-newest by
23475
+ * this field, then turnId, within the bounded most-recent window.
23476
+ */
23477
+ turnCreatedAt: external_exports.string().datetime()
23478
+ });
23422
23479
  RunUsageSummarySchema = external_exports.object({
23423
23480
  totals: RunUsageTotalsSchema,
23424
23481
  /**
@@ -23432,7 +23489,15 @@ var init_session_introspection = __esm({
23432
23489
  }),
23433
23490
  /** Highest derived-cost harness/model groups, in descending spend order. */
23434
23491
  byHarnessModel: external_exports.array(RunUsageHarnessModelSchema).max(RUN_USAGE_BREAKDOWN_LIMIT),
23435
- breakdownTruncated: external_exports.boolean()
23492
+ breakdownTruncated: external_exports.boolean(),
23493
+ /** Most recent authoritative turn aggregates, returned oldest-to-newest. */
23494
+ byTurn: external_exports.array(RunUsageTurnSchema).max(RUN_USAGE_TURN_LIMIT),
23495
+ turnBreakdownTruncated: external_exports.boolean(),
23496
+ /**
23497
+ * Current events with no authoritative turn id. These remain in session
23498
+ * totals but are excluded from byTurn rather than guessed into a turn.
23499
+ */
23500
+ unassociated: RunUsageTotalsSchema
23436
23501
  });
23437
23502
  RunSummarySchema = external_exports.object({
23438
23503
  session: external_exports.object({
@@ -58185,6 +58250,23 @@ triggers:
58185
58250
  content: "# Source: https://www.auto.sh/api/v1/templates/%40auto/self-improvement/1.6.0/fragments/environments/agent-runtime.yaml\nharness: claude-code\nenvironment:\n name: agent-runtime\n image:\n kind: preset\n name: node24\n resources:\n memoryMB: 8192\n"
58186
58251
  }
58187
58252
  ]
58253
+ },
58254
+ {
58255
+ version: "1.7.0",
58256
+ files: [
58257
+ {
58258
+ path: "agents/self-improvement-slack.yaml",
58259
+ content: '# Source: https://www.auto.sh/api/v1/templates/%40auto/self-improvement/1.7.0/agents/self-improvement-slack.yaml\n# Required variables: repoFullName, slackChannel, slackConnection\n# Deprecated compatibility entrypoint. New installs should import\n# agents/self-improvement.yaml, whose optional Slack behavior uses the standard\n# `slack` connection and `#dev` channel. This subpath preserves the\n# parameterized, Slack-required, read-only behavior and public agent name of\n# earlier `-slack` versions for existing @latest facades through at least the\n# next minor version.\nimports:\n - ./self-improvement.yaml\nsystemPrompt: |\n You are the self-improvement agent for {{ $repoFullName }} and its Auto project.\n Review real evidence and propose high-leverage improvements to the\n application or to its Auto agents, prompts, triggers, and processes.\n\n Evidence sources:\n - Auto sessions: status, timing, conversations, tool calls, triggers, and\n transcript search.\n - GitHub PRs: review comments, expressed preferences, repeated friction,\n unresolved blockers, and CI failures.\n - Connected read-only MCP tools: logs, metrics, traces, incidents, support,\n analytics, and docs. Do not mutate external systems from this workflow.\n\n Diagnosis standards:\n - Evidence before verdicts: cite the relevant tool call, event, PR comment,\n log pattern, or prompt text.\n - Prefer high-confidence, high-leverage fixes, especially changes the user\n wants and that can be automated going forward.\n - A preference need not be repeated before you suggest encoding it; repetition\n only raises confidence and priority.\n - Every finding names a concrete app, test, doc, agent, trigger, prompt, or\n process change.\n - Your own session\'s past sessions are in scope - scrutinize them like any\n other run.\n\n Report format (your final message, every run):\n 1. Verdict - one line: top opportunity, closures, or why more data is needed.\n 2. Findings - each with evidence, affected surface, and the proposed fix.\n 3. Closures - previously reported problems now resolved.\n 4. Deferred - promising leads skipped because they need more evidence.\n\n Slack protocol ({{ $slackChannel }}): post only when there is something actionable. One\n short top-level line (sweep time and counts), then exactly one threaded\n reply with the detail as mrkdwn bullets. Use the threadId returned by\n chat.send for the reply; never guess thread ids. Links are\n <https://url|text>.\ninitialPrompt: |\n A scheduled heartbeat spawned this run (scheduled at\n "{{heartbeat.scheduledAt}}") to sweep the project\'s recent sessions\n for failures, anomalies, PR feedback, and improvement opportunities.\n\n Sweep protocol:\n - Find your previous report with auto.sessions.list/conversation. Avoid\n re-reporting old findings; close resolved ones and escalate recurring ones.\n - Triage recent sessions, PR feedback, and relevant read-only data sources.\n - Deep-dive at most three evidence clusters. Prefer one well-evidenced,\n automatable improvement over many shallow observations.\n\n Deliver per your profile instructions and always end with the four-section\n report.\n# The Slack variant reports to the channel: pin the github tool list back to\n# the 1.0.0 read-only surface (the base widens it for its tracking issue).\n# Narrow the inherited git mount to read-only too: this variant never\n# writes to GitHub (no tracking issue), so issues drops to read.\nmounts:\n - mountPath: /workspace/auto\n auth:\n capabilities:\n contents: read\n pullRequests: read\n issues: read\n checks: read\n actions: read\ntools:\n github:\n kind: github\n tools:\n - search_pull_requests\n - pull_request_read\n - actions_list\n - actions_get\n chat:\n kind: local\n implementation: chat\n auth:\n kind: connection\n provider: slack\n connection: "{{ $slackConnection }}"\n optional: false\ntriggers:\n - name: mention\n event: chat.message.mentioned\n connection: "{{ $slackConnection }}"\n optional: false\n where:\n $.chat.provider: slack\n $.auto.authored: false\n message: |\n {{message.author.userName}} mentioned you on Slack:\n\n {{message.text}}\n\n Channel: {{chat.channelId}}\n Thread: {{chat.threadId}}\n\n Reply in that thread with chat.send. If the user clearly asks for a\n sweep, run it. If required context is missing, ask for the time window,\n target agents, PRs, or data source. Otherwise, briefly explain that you\n review PR feedback, read-only data sources, and Auto session history,\n then propose concrete improvements when something is actionable.\n routing:\n kind: spawn\n'
58260
+ },
58261
+ {
58262
+ path: "agents/self-improvement.yaml",
58263
+ content: '# Source: https://www.auto.sh/api/v1/templates/%40auto/self-improvement/1.7.0/agents/self-improvement.yaml\n# Required variables: repoFullName\nname: self-improvement\nmodel:\n provider: anthropic\n id: claude-opus-4-8\nidentity:\n displayName: Self Improvement\n username: self-improvement\n avatar:\n asset: .auto/assets/self-improvement.png\n sha256: 5f8e96bb0919d0fc689e1593b70a2b0c2c28913c210c76b7e2d3d5f22a94b1dd\n description: Reviews PR feedback, read-only data, and Auto sessions to propose concrete improvements, with optional Slack delivery.\nimports:\n - ../fragments/environments/agent-runtime.yaml\nbindings:\n slack.thread:\n continuity: agent\nsystemPrompt: |\n You are the self-improvement agent for {{ $repoFullName }} and its Auto project.\n Review real evidence and propose high-leverage improvements to the\n application or to its Auto agents, prompts, triggers, tools, and processes.\n Treat the repository\'s committed `.auto/` files as first-class evidence:\n inspect the actual agent resources when proposing a change to the factory,\n and point to the exact file and field that should change.\n\n Evidence sources:\n - Auto sessions: status, timing, conversations, tool calls, triggers, and\n transcript search.\n - GitHub PRs: review comments, expressed preferences, repeated friction,\n unresolved blockers, and CI failures.\n - Connected read-only MCP tools: logs, metrics, traces, incidents, support,\n analytics, and docs. Do not mutate external systems from this workflow.\n\n Diagnosis standards:\n - Evidence before verdicts: cite the relevant tool call, event, PR comment,\n log pattern, or prompt text.\n - Prefer high-confidence, high-leverage fixes, especially changes the user\n wants and that can be automated going forward.\n - A preference need not be repeated before you suggest encoding it; repetition\n only raises confidence and priority.\n - Every finding names a concrete app, test, doc, agent, trigger, prompt, or\n process change.\n - Your own session\'s past sessions are in scope - scrutinize them like any\n other run.\n\n Report format (your final message, every run):\n 1. Verdict - one line: top opportunity, closures, or why more data is needed.\n 2. Findings - each with evidence, affected surface, and the proposed fix.\n 3. Closures - previously reported problems now resolved.\n 4. Deferred - promising leads skipped because they need more evidence.\n\n Delivery: the report is this run\'s final message. Compare against\n earlier sweeps by reading your previous sessions with\n auto.sessions.list/conversation - the session history is the report\n history. Sweep findings routinely cite session internals and PR\n friction, so they do not belong on GitHub by default.\n\n Fallback (only when the team has explicitly asked for tracking-issue\n delivery, and never on a public repository): keep a single tracking\n issue titled "Self-improvement sweep reports" - find it with\n search_issues, create it with issue_write only if it is missing, and\n add exactly one comment per sweep with add_issue_comment: one short\n first line (sweep time and counts), then the detail as Markdown\n bullets. Never open a new issue per finding, and post only when there\n is something actionable.\n\n Slack delivery is optional and uses the standard `slack` connection and\n `#dev` channel. When the chat tool is available, post only when there is\n something actionable: one short top-level line with the sweep time and\n counts, then exactly one threaded reply with the detail as mrkdwn bullets.\n Use the threadId returned by chat.send for the reply; never guess thread ids.\n When the tool is unavailable, do not treat Slack delivery as a failure; the\n run report remains the complete sweep. If a user asks for Slack delivery\n while it is unavailable, offer to connect the standard `slack` connection\n and explain that a fresh apply and session make the capability available.\n\n Scheduled sweep closure:\n - Finish the final four-section report/reply and, for actionable findings,\n every required Slack or Chief handoff. Only after every owed delivery is\n complete, call `auto.sessions.complete_current` exactly once with a compact\n one-line handoff.\n - This applies to actionable and no-action sweeps. A no-findings sweep with\n Verdict "Nothing actionable." completes after its final four-section report;\n it owes no Slack or Chief handoff.\n - Never call `auto.sessions.archive_current` to close a sweep. Do not call\n `auto.unbind`, `auto.chat.unsubscribe`, or otherwise release a Slack\n thread binding during closure. The configured agent-continuity\n `slack.thread` binding survives completion while lifecycle remains manual.\n `chat_send` stamps that continuity from this spec. It routes a human reply\n back to this completed holder and reopens this session.\ninitialPrompt: |\n A scheduled heartbeat spawned this run (scheduled at\n "{{heartbeat.scheduledAt}}") to sweep the project\'s recent sessions\n for failures, anomalies, PR feedback, and improvement opportunities.\n\n Sweep protocol:\n - Find your previous report with auto.sessions.list/conversation. Avoid\n re-reporting old findings; close resolved ones and escalate recurring ones.\n - Triage recent sessions, PR feedback, and relevant read-only data sources.\n - Deep-dive at most three evidence clusters. Prefer one well-evidenced,\n automatable improvement over many shallow observations.\n\n Deliver per your profile instructions and always end with the four-section\n report.\nmounts:\n # GitHub App git mount provisions the GitHub MCP proxy (the github\n # tools below are broken without a githubApp mount) and stages a\n # read-only checkout the sweep can ground findings in. Capabilities\n # line up with the declared tools: pullRequests/issues read for PR\n # comment and tracking-issue inspection, issues: write for the opt-in\n # tracking-issue fallback (issue_write/add_issue_comment), actions/checks\n # read for CI. No merge/secrets/workflows.\n - kind: git\n repository: "{{ $repoFullName }}"\n mountPath: /workspace/auto\n ref: main\n auth:\n kind: githubApp\n capabilities:\n contents: read\n pullRequests: read\n issues: write\n checks: read\n actions: read\ntools:\n auto:\n kind: local\n implementation: auto\n github:\n kind: github\n tools:\n - search_pull_requests\n - pull_request_read\n - actions_list\n - actions_get\n - search_issues\n - issue_read\n - issue_write\n - add_issue_comment\n chat:\n kind: local\n implementation: chat\n auth:\n kind: connection\n provider: slack\n connection: slack\n optional: true\ntriggers:\n - name: sweep-heartbeat\n kind: heartbeat\n cron: 0 */2 * * *\n timezone: UTC\n routing:\n kind: spawn\n - name: mention\n event: chat.message.mentioned\n connection: slack\n optional: true\n where:\n $.chat.provider: slack\n $.auto.authored: false\n message: |\n {{message.author.userName}} mentioned you on Slack:\n\n {{message.text}}\n\n Channel: {{chat.channelId}}\n Thread: {{chat.threadId}}\n\n Reply in that thread with chat.send. If the user clearly asks for a\n sweep, run it. If required context is missing, ask for the time window,\n target agents, PRs, or data source. Otherwise, briefly explain that you\n review PR feedback, read-only data sources, and Auto session history,\n then propose concrete improvements when something is actionable.\n routing:\n kind: spawn\n'
58264
+ },
58265
+ {
58266
+ path: "fragments/environments/agent-runtime.yaml",
58267
+ content: "# Source: https://www.auto.sh/api/v1/templates/%40auto/self-improvement/1.7.0/fragments/environments/agent-runtime.yaml\nharness: claude-code\nenvironment:\n name: agent-runtime\n image:\n kind: preset\n name: node24\n resources:\n memoryMB: 8192\n"
58268
+ }
58269
+ ]
58188
58270
  }
58189
58271
  ],
58190
58272
  "@auto/slopbusters": [
@@ -84936,7 +85018,7 @@ var init_package = __esm({
84936
85018
  "package.json"() {
84937
85019
  package_default = {
84938
85020
  name: "@autohq/cli",
84939
- version: "0.1.565",
85021
+ version: "0.1.567",
84940
85022
  license: "SEE LICENSE IN README.md",
84941
85023
  publishConfig: {
84942
85024
  access: "public"
@@ -96138,13 +96220,23 @@ var RuntimeBridgeOutputLivenessEnvelopeSchema = external_exports.object({
96138
96220
  intervalMs: external_exports.number().int().positive(),
96139
96221
  createdAt: external_exports.string().datetime()
96140
96222
  });
96223
+ var RuntimeBridgeOutputUsageTurnEnvelopeSchema = external_exports.object({
96224
+ type: external_exports.literal("runtime.usage_turn"),
96225
+ sessionId: SessionIdSchema2,
96226
+ runtimeId: RuntimeIdSchema2,
96227
+ bridgeLeaseId: RuntimeBridgeLeaseIdSchema2,
96228
+ outputSeq: external_exports.number().int().positive(),
96229
+ turnId: SessionCommandIdSchema2.nullable(),
96230
+ createdAt: external_exports.string().datetime()
96231
+ });
96141
96232
  var RuntimeBridgeOutputEnvelopeSchema = external_exports.union([
96142
96233
  RuntimeBridgeOutputEntryEnvelopeSchema,
96143
96234
  RuntimeBridgeOutputDeltaEnvelopeSchema,
96144
96235
  RuntimeBridgeOutputUiMessageChunkEnvelopeSchema,
96145
96236
  RuntimeBridgeOutputUiMessagePartEnvelopeSchema,
96146
96237
  RuntimeBridgeOutputUiMessageCompletedEnvelopeSchema,
96147
- RuntimeBridgeOutputLivenessEnvelopeSchema
96238
+ RuntimeBridgeOutputLivenessEnvelopeSchema,
96239
+ RuntimeBridgeOutputUsageTurnEnvelopeSchema
96148
96240
  ]);
96149
96241
  function isLiveOnlyRuntimeOutputEnvelope(envelope) {
96150
96242
  return envelope.type === "ui.message.chunk" || envelope.type === "conversation.delta";
@@ -97791,6 +97883,9 @@ function replacePayloadWithMarker(envelope, originalBytes) {
97791
97883
  parts: [{ type: "text", text, state: "done" }]
97792
97884
  }
97793
97885
  };
97886
+ case "runtime.liveness":
97887
+ case "runtime.usage_turn":
97888
+ return envelope;
97794
97889
  }
97795
97890
  }
97796
97891
 
@@ -98224,6 +98319,23 @@ var AgentBridgeOutputBuffer = class {
98224
98319
  );
98225
98320
  await this.drainPendingOutputs();
98226
98321
  }
98322
+ /**
98323
+ * Publish and await the active immutable platform turn before model work.
98324
+ * Unlike liveness, every transition is retained and replayed: skipping one
98325
+ * could attribute a billed call to the preceding turn.
98326
+ */
98327
+ async emitUsageTurn(context, turnId) {
98328
+ this.outputSeq += 1;
98329
+ this.enqueueOutput(
98330
+ buildUsageTurnOutputEnvelope({
98331
+ context,
98332
+ outputSeq: this.outputSeq,
98333
+ turnId,
98334
+ createdAt: now2()
98335
+ })
98336
+ );
98337
+ await this.drainPendingOutputs({ failIfBlocked: true });
98338
+ }
98227
98339
  async emitUiMessageChunk(context, projection) {
98228
98340
  await this.flushPendingDelta();
98229
98341
  await this.emitLiveUiMessageChunk(context, projection.chunk);
@@ -99004,6 +99116,18 @@ function buildLivenessOutputEnvelope(input) {
99004
99116
  createdAt: input.createdAt
99005
99117
  });
99006
99118
  }
99119
+ function buildUsageTurnOutputEnvelope(input) {
99120
+ const { context } = input;
99121
+ return RuntimeBridgeOutputEnvelopeSchema.parse({
99122
+ type: "runtime.usage_turn",
99123
+ sessionId: context.sessionId,
99124
+ runtimeId: context.runtimeId,
99125
+ bridgeLeaseId: context.bridgeLeaseId,
99126
+ outputSeq: input.outputSeq,
99127
+ turnId: input.turnId,
99128
+ createdAt: input.createdAt
99129
+ });
99130
+ }
99007
99131
  function buildUiMessagePartOutputEnvelope(input) {
99008
99132
  const { context, snapshot } = input;
99009
99133
  return RuntimeBridgeOutputEnvelopeSchema.parse({
@@ -100295,7 +100419,7 @@ var ClaudeAgentBridgeSessionImpl = class {
100295
100419
  return;
100296
100420
  }
100297
100421
  await this.awaitMcpRegistration();
100298
- this.enqueueUserMessage(message, commandIds);
100422
+ await this.enqueueUserMessage(message, commandIds);
100299
100423
  this.input.runtimeLogger?.info("agent_bridge_claude_send_message_queued", {
100300
100424
  delivery_mode: mode,
100301
100425
  duration_ms: Date.now() - startedAt,
@@ -100401,6 +100525,7 @@ var ClaudeAgentBridgeSessionImpl = class {
100401
100525
  }
100402
100526
  this.openTurnCommandIds.length = 0;
100403
100527
  this.publishActiveTurnCommandIds();
100528
+ void this.input.onUsageTurnChanged?.(null);
100404
100529
  this.stderr.flush();
100405
100530
  this.inputQueue.close();
100406
100531
  if (previousState.kind === "started") {
@@ -100494,6 +100619,7 @@ var ClaudeAgentBridgeSessionImpl = class {
100494
100619
  consumedCommandIds: this.openTurnCommandIds.shift() ?? []
100495
100620
  };
100496
100621
  this.publishActiveTurnCommandIds();
100622
+ await this.input.onUsageTurnChanged?.(null);
100497
100623
  this.pendingToolUses.clear();
100498
100624
  this.interruptSettling = false;
100499
100625
  this.turnResultCount += 1;
@@ -100505,7 +100631,7 @@ var ClaudeAgentBridgeSessionImpl = class {
100505
100631
  consumed_command_ids: meta3.consumedCommandIds
100506
100632
  });
100507
100633
  if (this.activeTurnCount === 0) {
100508
- this.flushDeferredMessages();
100634
+ await this.flushDeferredMessages();
100509
100635
  }
100510
100636
  if (this.deferredMessages.length === 0) {
100511
100637
  this.cancelledToolRuns = [];
@@ -100535,6 +100661,7 @@ var ClaudeAgentBridgeSessionImpl = class {
100535
100661
  this.activeTurnCount = 0;
100536
100662
  this.openTurnCommandIds.length = 0;
100537
100663
  this.publishActiveTurnCommandIds();
100664
+ await this.input.onUsageTurnChanged?.(null);
100538
100665
  this.pendingToolUses.clear();
100539
100666
  this.interruptSettling = false;
100540
100667
  this.disarmToolBoundaryWait();
@@ -100547,7 +100674,8 @@ var ClaudeAgentBridgeSessionImpl = class {
100547
100674
  // lets injection work while the SDK session is still starting; the queue
100548
100675
  // drains once the query attaches. Startup failures surface through onError
100549
100676
  // instead of failing injection.
100550
- enqueueUserMessage(message, commandIds) {
100677
+ async enqueueUserMessage(message, commandIds) {
100678
+ await this.input.onUsageTurnChanged?.(commandIds[0] ?? null);
100551
100679
  this.inputQueue.push(claudeAgentUserMessage(message));
100552
100680
  this.activeTurnCount += 1;
100553
100681
  this.openTurnCommandIds.push(commandIds);
@@ -100655,7 +100783,7 @@ var ClaudeAgentBridgeSessionImpl = class {
100655
100783
  clearTimeout(this.toolBoundaryWait.timer);
100656
100784
  this.toolBoundaryWait = null;
100657
100785
  }
100658
- flushDeferredMessages() {
100786
+ async flushDeferredMessages() {
100659
100787
  if (this.deferredMessages.length === 0) {
100660
100788
  return;
100661
100789
  }
@@ -100666,7 +100794,7 @@ var ClaudeAgentBridgeSessionImpl = class {
100666
100794
  `agent_bridge_claude_deferred_flush count=${pending.length} cancelled_tool_count=${cancelledToolRuns.length}`
100667
100795
  );
100668
100796
  const text = pending.map((entry) => entry.text).join("\n\n");
100669
- this.enqueueUserMessage(
100797
+ await this.enqueueUserMessage(
100670
100798
  cancelledToolRuns.length > 0 ? `${text}
100671
100799
 
100672
100800
  ${cancelledToolPlatformNotice(cancelledToolRuns)}` : text,
@@ -101583,6 +101711,13 @@ var ClaudeCodeCommandHandler = class {
101583
101711
  RUNTIME_LIVENESS_INTERVAL_MS
101584
101712
  );
101585
101713
  }
101714
+ async emitUsageTurn(turnId) {
101715
+ const activeContext = this.context;
101716
+ if (!activeContext) {
101717
+ throw new Error("Cannot publish usage turn without bridge context");
101718
+ }
101719
+ await this.outputBuffer.emitUsageTurn(activeContext, turnId);
101720
+ }
101586
101721
  async emitBridgeOutput(activeContext, projection) {
101587
101722
  try {
101588
101723
  await this.outputBuffer.emitProjection(activeContext, projection);
@@ -101750,6 +101885,7 @@ var ClaudeCodeCommandHandler = class {
101750
101885
  }
101751
101886
  },
101752
101887
  onActiveTurnCommandIds: (commandIds) => this.autoMcpShim.setActiveTurnCommandIds(commandIds),
101888
+ onUsageTurnChanged: (turnId) => this.emitUsageTurn(turnId),
101753
101889
  canUseTool: this.canUseTool,
101754
101890
  onMessage: (message, meta3) => this.handleAgentMessage(message, meta3),
101755
101891
  onError: (error51) => this.handleAgentError(error51),
@@ -102963,6 +103099,7 @@ var CodexAgentBridgeSessionImpl = class {
102963
103099
  this.pendingCommandIds = [...commandIds];
102964
103100
  this.publishActiveTurnCommandIds(commandIds);
102965
103101
  try {
103102
+ await this.input.onUsageTurnChanged?.(commandIds[0] ?? null);
102966
103103
  await this.request("turn/start", {
102967
103104
  threadId,
102968
103105
  input: [userTextInput(message)]
@@ -102970,6 +103107,7 @@ var CodexAgentBridgeSessionImpl = class {
102970
103107
  } catch (error51) {
102971
103108
  this.pendingCommandIds = [];
102972
103109
  this.publishActiveTurnCommandIds();
103110
+ await this.input.onUsageTurnChanged?.(null);
102973
103111
  throw error51;
102974
103112
  }
102975
103113
  }
@@ -102977,6 +103115,7 @@ var CodexAgentBridgeSessionImpl = class {
102977
103115
  this.pendingCommandIds = [...commandIds];
102978
103116
  this.publishActiveTurnCommandIds(commandIds);
102979
103117
  try {
103118
+ await this.input.onUsageTurnChanged?.(commandIds[0] ?? null);
102980
103119
  await this.request("turn/start", {
102981
103120
  threadId,
102982
103121
  input: []
@@ -102984,6 +103123,7 @@ var CodexAgentBridgeSessionImpl = class {
102984
103123
  } catch (error51) {
102985
103124
  this.pendingCommandIds = [];
102986
103125
  this.publishActiveTurnCommandIds();
103126
+ await this.input.onUsageTurnChanged?.(null);
102987
103127
  throw error51;
102988
103128
  }
102989
103129
  }
@@ -103347,6 +103487,7 @@ var CodexAgentBridgeSessionImpl = class {
103347
103487
  this.activeTurnId = null;
103348
103488
  this.activeCommandIds = [];
103349
103489
  this.publishActiveTurnCommandIds();
103490
+ void this.input.onUsageTurnChanged?.(null);
103350
103491
  }
103351
103492
  this.pendingToolItemIds.clear();
103352
103493
  this.resolveSettlement();
@@ -103362,6 +103503,7 @@ var CodexAgentBridgeSessionImpl = class {
103362
103503
  this.activeCommandIds = [];
103363
103504
  this.pendingCommandIds = [];
103364
103505
  this.publishActiveTurnCommandIds();
103506
+ void this.input.onUsageTurnChanged?.(null);
103365
103507
  this.pendingToolItemIds.clear();
103366
103508
  this.resolveSettlement();
103367
103509
  this.input.writeOutput?.(`agent_bridge_codex_exited code=${code ?? ""}`);
@@ -103757,6 +103899,13 @@ var CodexCommandHandler = class {
103757
103899
  RUNTIME_LIVENESS_INTERVAL_MS
103758
103900
  );
103759
103901
  }
103902
+ async emitUsageTurn(turnId) {
103903
+ const activeContext = this.context;
103904
+ if (!activeContext) {
103905
+ throw new Error("Cannot publish usage turn without bridge context");
103906
+ }
103907
+ await this.outputBuffer.emitUsageTurn(activeContext, turnId);
103908
+ }
103760
103909
  async emit(activeContext, projection) {
103761
103910
  try {
103762
103911
  await this.outputBuffer.emitProjection(activeContext, projection);
@@ -103779,6 +103928,7 @@ var CodexCommandHandler = class {
103779
103928
  onServerRequest: (request) => this.handleServerRequest(request),
103780
103929
  onThreadId: (threadId) => this.persistThreadId(threadId),
103781
103930
  onActiveTurnCommandIds: (commandIds) => this.autoMcpShim.setActiveTurnCommandIds(commandIds),
103931
+ onUsageTurnChanged: (turnId) => this.emitUsageTurn(turnId),
103782
103932
  onError: (error51) => this.handleSessionError(error51),
103783
103933
  onExit: () => {
103784
103934
  if (this.session === session) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@autohq/cli",
3
- "version": "0.1.565",
3
+ "version": "0.1.567",
4
4
  "license": "SEE LICENSE IN README.md",
5
5
  "publishConfig": {
6
6
  "access": "public"