@autohq/cli 0.1.600 → 0.1.601

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.
@@ -33828,7 +33828,9 @@ var RUNTIME_BRIDGE_SOCKET_PATH = "/runtime/socket.io";
33828
33828
  var RUNTIME_BRIDGE_BOOTSTRAP_EVENT = "bridge.bootstrap";
33829
33829
  var RUNTIME_BRIDGE_CONNECTED_EVENT = "bridge.connected";
33830
33830
  var RUNTIME_BRIDGE_COMMAND_EVENT = "runtime.command";
33831
+ var RUNTIME_BRIDGE_LEASE_AUTHORIZATION_EVENT = "runtime.lease_authorization";
33831
33832
  var RUNTIME_BRIDGE_OUTPUT_EVENT = "runtime.output";
33833
+ var RUNTIME_BRIDGE_USAGE_TURN_EVENT = "runtime.usage_turn";
33832
33834
  var AgentBridgeMcpServerConfigSchema = external_exports.object({
33833
33835
  type: external_exports.literal("http"),
33834
33836
  url: external_exports.string().trim().min(1),
@@ -33938,6 +33940,19 @@ var RuntimeBridgeConnectedPayloadSchema = external_exports.object({
33938
33940
  runtimeId: RuntimeIdSchema,
33939
33941
  bridgeLeaseId: RuntimeBridgeLeaseIdSchema
33940
33942
  });
33943
+ var RuntimeBridgeLeaseAuthorizationRequestSchema = external_exports.object({
33944
+ sessionId: SessionIdSchema,
33945
+ runtimeId: RuntimeIdSchema,
33946
+ bridgeLeaseId: RuntimeBridgeLeaseIdSchema
33947
+ }).strict();
33948
+ var RuntimeBridgeLeaseAuthorizationAckSchema = external_exports.object({
33949
+ sessionId: SessionIdSchema,
33950
+ runtimeId: RuntimeIdSchema,
33951
+ bridgeLeaseId: RuntimeBridgeLeaseIdSchema,
33952
+ status: external_exports.enum(["authorized", "failed"]),
33953
+ error: external_exports.string().trim().min(1).optional(),
33954
+ at: external_exports.string().datetime()
33955
+ }).strict();
33941
33956
  var RuntimeBridgeCommandDeliverySchema = external_exports.object({
33942
33957
  type: external_exports.literal("command.delivery"),
33943
33958
  deliveryId: external_exports.string().trim().min(1),
@@ -37736,7 +37751,7 @@ Object.assign(lookup, {
37736
37751
  // package.json
37737
37752
  var package_default = {
37738
37753
  name: "@autohq/cli",
37739
- version: "0.1.600",
37754
+ version: "0.1.601",
37740
37755
  license: "SEE LICENSE IN README.md",
37741
37756
  publishConfig: {
37742
37757
  access: "public"
@@ -37937,6 +37952,8 @@ async function runAgentBridgeSocket(options) {
37937
37952
  token: options.token,
37938
37953
  onBootstrap: options.onBootstrap,
37939
37954
  createHandler: (bootstrap) => options.createHandler({
37955
+ authorizeLease: (request) => authorizeLeaseWithAck(socket, request, options.runtimeLogger),
37956
+ authorizeUsageTurn: (output) => emitUsageTurnWithAck(socket, output, options.runtimeLogger),
37940
37957
  emitOutput: (output) => emitOutputWithAck(socket, output, options.runtimeLogger),
37941
37958
  onOutputAckProgress: terminalAuthDrain.handleOutputAckProgress,
37942
37959
  cycleSocket: () => {
@@ -38150,19 +38167,109 @@ function createRuntimeBridgeBootstrapListener(input) {
38150
38167
  };
38151
38168
  }
38152
38169
  function emitOutputWithAck(socket, output, runtimeLogger) {
38170
+ return emitRuntimeOutputWithAck({
38171
+ event: RUNTIME_BRIDGE_OUTPUT_EVENT,
38172
+ output,
38173
+ runtimeLogger,
38174
+ socket
38175
+ });
38176
+ }
38177
+ function authorizeLeaseWithAck(socket, request, runtimeLogger) {
38153
38178
  const startedAt = Date.now();
38154
- runtimeLogger?.info(
38179
+ runtimeLogger?.info("agent_bridge_lease_authorization_started", {
38180
+ session_id: request.sessionId,
38181
+ runtime_id: request.runtimeId,
38182
+ bridge_lease_id: request.bridgeLeaseId,
38183
+ socket_id: socket.id
38184
+ });
38185
+ return new Promise((resolve4, reject) => {
38186
+ socket.timeout(AGENT_BRIDGE_OUTPUT_ACK_TIMEOUT_MS).emit(
38187
+ RUNTIME_BRIDGE_LEASE_AUTHORIZATION_EVENT,
38188
+ request,
38189
+ (error51, rawAck) => {
38190
+ if (error51) {
38191
+ runtimeLogger?.warn("agent_bridge_lease_authorization_failed", {
38192
+ session_id: request.sessionId,
38193
+ runtime_id: request.runtimeId,
38194
+ bridge_lease_id: request.bridgeLeaseId,
38195
+ socket_id: socket.id,
38196
+ duration_ms: Date.now() - startedAt,
38197
+ error: error51.message
38198
+ });
38199
+ reject(
38200
+ new AgentBridgeOutputAckTimeoutError(
38201
+ `Bridge lease authorization ack timed out: ${error51.message}`
38202
+ )
38203
+ );
38204
+ return;
38205
+ }
38206
+ const ack = RuntimeBridgeLeaseAuthorizationAckSchema.safeParse(rawAck);
38207
+ if (!ack.success) {
38208
+ runtimeLogger?.warn("agent_bridge_lease_authorization_invalid", {
38209
+ session_id: request.sessionId,
38210
+ runtime_id: request.runtimeId,
38211
+ bridge_lease_id: request.bridgeLeaseId,
38212
+ socket_id: socket.id,
38213
+ duration_ms: Date.now() - startedAt,
38214
+ error: ack.error.message
38215
+ });
38216
+ reject(
38217
+ new Error(
38218
+ `Invalid bridge lease authorization ack: ${ack.error.message}`
38219
+ )
38220
+ );
38221
+ return;
38222
+ }
38223
+ if (ack.data.status === "failed") {
38224
+ runtimeLogger?.warn("agent_bridge_lease_authorization_rejected", {
38225
+ session_id: request.sessionId,
38226
+ runtime_id: request.runtimeId,
38227
+ bridge_lease_id: request.bridgeLeaseId,
38228
+ socket_id: socket.id,
38229
+ duration_ms: Date.now() - startedAt,
38230
+ error: ack.data.error
38231
+ });
38232
+ reject(
38233
+ new Error(
38234
+ ack.data.error ?? "Bridge lease is no longer authorized"
38235
+ )
38236
+ );
38237
+ return;
38238
+ }
38239
+ runtimeLogger?.info("agent_bridge_lease_authorization_ready", {
38240
+ session_id: request.sessionId,
38241
+ runtime_id: request.runtimeId,
38242
+ bridge_lease_id: request.bridgeLeaseId,
38243
+ socket_id: socket.id,
38244
+ duration_ms: Date.now() - startedAt
38245
+ });
38246
+ resolve4(ack.data);
38247
+ }
38248
+ );
38249
+ });
38250
+ }
38251
+ function emitUsageTurnWithAck(socket, output, runtimeLogger) {
38252
+ return emitRuntimeOutputWithAck({
38253
+ event: RUNTIME_BRIDGE_USAGE_TURN_EVENT,
38254
+ output,
38255
+ runtimeLogger,
38256
+ socket
38257
+ });
38258
+ }
38259
+ function emitRuntimeOutputWithAck(input) {
38260
+ const startedAt = Date.now();
38261
+ input.runtimeLogger?.info(
38155
38262
  "agent_bridge_output_emit_started",
38156
- outputLogContext(output, socket.id)
38263
+ outputLogContext(input.output, input.socket.id)
38157
38264
  );
38158
38265
  return new Promise((resolve4, reject) => {
38159
- socket.timeout(AGENT_BRIDGE_OUTPUT_ACK_TIMEOUT_MS).emit(
38160
- RUNTIME_BRIDGE_OUTPUT_EVENT,
38161
- output,
38266
+ input.socket.timeout(AGENT_BRIDGE_OUTPUT_ACK_TIMEOUT_MS).emit(
38267
+ input.event,
38268
+ input.output,
38162
38269
  (error51, rawAck) => {
38163
38270
  if (error51) {
38164
- runtimeLogger?.warn("agent_bridge_output_emit_ack_failed", {
38165
- ...outputLogContext(output, socket.id),
38271
+ input.runtimeLogger?.warn("agent_bridge_output_emit_ack_failed", {
38272
+ ...outputLogContext(input.output, input.socket.id),
38166
38273
  duration_ms: Date.now() - startedAt,
38167
38274
  error: error51.message
38168
38275
  });
@@ -38171,8 +38278,8 @@ function emitOutputWithAck(socket, output, runtimeLogger) {
38171
38278
  }
38172
38279
  const ack = RuntimeBridgeOutputAckSchema.safeParse(rawAck);
38173
38280
  if (!ack.success) {
38174
- runtimeLogger?.warn("agent_bridge_output_emit_ack_invalid", {
38175
- ...outputLogContext(output, socket.id),
38281
+ input.runtimeLogger?.warn("agent_bridge_output_emit_ack_invalid", {
38282
+ ...outputLogContext(input.output, input.socket.id),
38176
38283
  duration_ms: Date.now() - startedAt,
38177
38284
  error: ack.error.message
38178
38285
  });
@@ -38180,8 +38287,8 @@ function emitOutputWithAck(socket, output, runtimeLogger) {
38180
38287
  return;
38181
38288
  }
38182
38289
  if (ack.data.status === "failed") {
38183
- runtimeLogger?.warn("agent_bridge_output_emit_ack_rejected", {
38184
- ...outputLogContext(output, socket.id),
38290
+ input.runtimeLogger?.warn("agent_bridge_output_emit_ack_rejected", {
38291
+ ...outputLogContext(input.output, input.socket.id),
38185
38292
  duration_ms: Date.now() - startedAt,
38186
38293
  ack_status: ack.data.status,
38187
38294
  error: ack.data.error
@@ -38191,8 +38298,8 @@ function emitOutputWithAck(socket, output, runtimeLogger) {
38191
38298
  );
38192
38299
  return;
38193
38300
  }
38194
- runtimeLogger?.info("agent_bridge_output_emit_ack_ready", {
38195
- ...outputLogContext(output, socket.id),
38301
+ input.runtimeLogger?.info("agent_bridge_output_emit_ack_ready", {
38302
+ ...outputLogContext(input.output, input.socket.id),
38196
38303
  duration_ms: Date.now() - startedAt,
38197
38304
  ack_status: ack.data.status,
38198
38305
  cursor: ack.data.cursor
@@ -83758,6 +83865,15 @@ var AgentBridgeOutputBuffer = class {
83758
83865
  await this.flushPendingDelta();
83759
83866
  await this.enqueueProjectionAndDrain(context, projection, options);
83760
83867
  }
83868
+ async enqueueEntryProjection(context, projection) {
83869
+ await this.materializePendingUiDelta();
83870
+ this.materializePendingDelta();
83871
+ this.outputSeq += 1;
83872
+ this.enqueueOutput(
83873
+ buildOutputEnvelope(context, this.outputSeq, projection)
83874
+ );
83875
+ return { drained: this.drainPendingOutputs() };
83876
+ }
83761
83877
  async replayPendingOutputs() {
83762
83878
  await this.materializePendingUiDelta();
83763
83879
  await this.flushPendingDelta({ force: true });
@@ -83806,17 +83922,18 @@ var AgentBridgeOutputBuffer = class {
83806
83922
  * could attribute a billed call to the preceding turn.
83807
83923
  */
83808
83924
  async emitUsageTurn(context, turnId) {
83809
- this.outputSeq += 1;
83810
- this.enqueueOutput(
83811
- buildUsageTurnOutputEnvelope({
83812
- context,
83813
- outputSeq: this.outputSeq,
83814
- turnId,
83815
- createdAt: now2()
83816
- })
83817
- );
83925
+ this.enqueueOutput(this.nextUsageTurnOutput(context, turnId));
83818
83926
  await this.drainPendingOutputs({ failIfBlocked: true });
83819
83927
  }
83928
+ nextUsageTurnOutput(context, turnId) {
83929
+ this.outputSeq += 1;
83930
+ return buildUsageTurnOutputEnvelope({
83931
+ context,
83932
+ outputSeq: this.outputSeq,
83933
+ turnId,
83934
+ createdAt: now2()
83935
+ });
83936
+ }
83820
83937
  async emitUiMessageChunk(context, projection) {
83821
83938
  await this.flushPendingDelta();
83822
83939
  await this.emitLiveUiMessageChunk(context, projection.chunk);
@@ -84085,6 +84202,13 @@ var AgentBridgeOutputBuffer = class {
84085
84202
  this.deltaFlushTimer = null;
84086
84203
  }
84087
84204
  async flushPendingDelta(options = {}) {
84205
+ if (!this.pendingDelta) {
84206
+ return;
84207
+ }
84208
+ this.materializePendingDelta();
84209
+ await this.drainPendingOutputs(options);
84210
+ }
84211
+ materializePendingDelta() {
84088
84212
  const pendingDelta = this.pendingDelta;
84089
84213
  if (!pendingDelta) {
84090
84214
  return;
@@ -84092,14 +84216,14 @@ var AgentBridgeOutputBuffer = class {
84092
84216
  this.clearDeltaFlushTimer();
84093
84217
  this.pendingDelta = null;
84094
84218
  this.outputSeq += 1;
84095
- const output = buildDeltaOutputEnvelope({
84096
- context: pendingDelta.context,
84097
- outputSeq: this.outputSeq,
84098
- delta: pendingDelta.delta,
84099
- createdAt: pendingDelta.createdAt
84100
- });
84101
- this.enqueueOutput(output);
84102
- await this.drainPendingOutputs(options);
84219
+ this.enqueueOutput(
84220
+ buildDeltaOutputEnvelope({
84221
+ context: pendingDelta.context,
84222
+ outputSeq: this.outputSeq,
84223
+ delta: pendingDelta.delta,
84224
+ createdAt: pendingDelta.createdAt
84225
+ })
84226
+ );
84103
84227
  }
84104
84228
  async emitUntilAcked(output) {
84105
84229
  for (let attempt = 0; ; attempt += 1) {
@@ -84625,7 +84749,7 @@ function buildLivenessOutputEnvelope(input) {
84625
84749
  }
84626
84750
  function buildUsageTurnOutputEnvelope(input) {
84627
84751
  const { context } = input;
84628
- return RuntimeBridgeOutputEnvelopeSchema.parse({
84752
+ return RuntimeBridgeOutputUsageTurnEnvelopeSchema.parse({
84629
84753
  type: "runtime.usage_turn",
84630
84754
  sessionId: context.sessionId,
84631
84755
  runtimeId: context.runtimeId,
@@ -87130,30 +87254,24 @@ var ClaudeCodeCommandHandler = class {
87130
87254
  // original delivery and any redeliveries, so failures travel as values.
87131
87255
  async injectMessageCommand(activeContext, delivery, message, socketId) {
87132
87256
  try {
87133
- const emitStartedAt = Date.now();
87134
- this.input.runtimeLogger?.info(
87135
- "agent_bridge_claude_command_user_entry_emit_started",
87136
- commandLogContext(delivery, { socket_id: socketId })
87137
- );
87138
- await this.emitRequiredBridgeOutput(activeContext, {
87139
- type: "entry",
87140
- entry: {
87141
- messageId: delivery.commandId,
87142
- role: "user",
87143
- kind: "message",
87144
- status: "completed",
87145
- content: {
87146
- parts: [{ type: "text", text: message }]
87147
- }
87257
+ const enqueueStartedAt = Date.now();
87258
+ await this.enqueueUserEntryBridgeOutput(activeContext, {
87259
+ messageId: delivery.commandId,
87260
+ role: "user",
87261
+ kind: "message",
87262
+ status: "completed",
87263
+ content: {
87264
+ parts: [{ type: "text", text: message }]
87148
87265
  }
87149
87266
  });
87150
87267
  this.input.runtimeLogger?.info(
87151
- "agent_bridge_claude_command_user_entry_emit_ready",
87268
+ "agent_bridge_claude_command_user_entry_enqueued",
87152
87269
  commandLogContext(delivery, {
87153
87270
  socket_id: socketId,
87154
- duration_ms: Date.now() - emitStartedAt
87271
+ duration_ms: Date.now() - enqueueStartedAt
87155
87272
  })
87156
87273
  );
87274
+ await this.input.authorizeLease(activeContext);
87157
87275
  const sendStartedAt = Date.now();
87158
87276
  const mode = deliveryMode(delivery);
87159
87277
  this.applySelectionForMessage(delivery);
@@ -87247,18 +87365,16 @@ var ClaudeCodeCommandHandler = class {
87247
87365
  return;
87248
87366
  }
87249
87367
  const message = answerFallbackMessage(answer);
87250
- await this.emitRequiredBridgeOutput(activeContext, {
87251
- type: "entry",
87252
- entry: {
87253
- messageId: delivery.commandId,
87254
- role: "user",
87255
- kind: "message",
87256
- status: "completed",
87257
- content: {
87258
- parts: [{ type: "text", text: message }]
87259
- }
87368
+ await this.enqueueUserEntryBridgeOutput(activeContext, {
87369
+ messageId: delivery.commandId,
87370
+ role: "user",
87371
+ kind: "message",
87372
+ status: "completed",
87373
+ content: {
87374
+ parts: [{ type: "text", text: message }]
87260
87375
  }
87261
87376
  });
87377
+ await this.input.authorizeLease(activeContext);
87262
87378
  await this.ensureAgentSession().sendMessage(message, {
87263
87379
  commandId: delivery.commandId
87264
87380
  });
@@ -87340,7 +87456,13 @@ var ClaudeCodeCommandHandler = class {
87340
87456
  if (!activeContext) {
87341
87457
  throw new Error("Cannot publish usage turn without bridge context");
87342
87458
  }
87343
- await this.outputBuffer.emitUsageTurn(activeContext, turnId);
87459
+ if (turnId) {
87460
+ await this.input.authorizeUsageTurn(
87461
+ this.outputBuffer.nextUsageTurnOutput(activeContext, turnId)
87462
+ );
87463
+ return;
87464
+ }
87465
+ await this.outputBuffer.emitUsageTurn(activeContext, null);
87344
87466
  }
87345
87467
  async emitBridgeOutput(activeContext, projection) {
87346
87468
  try {
@@ -87351,6 +87473,17 @@ var ClaudeCodeCommandHandler = class {
87351
87473
  );
87352
87474
  }
87353
87475
  }
87476
+ async enqueueUserEntryBridgeOutput(activeContext, entry) {
87477
+ const { drained } = await this.outputBuffer.enqueueEntryProjection(
87478
+ activeContext,
87479
+ { type: "entry", entry }
87480
+ );
87481
+ drained.catch((error51) => {
87482
+ this.input.writeOutput?.(
87483
+ `agent_bridge_output_emit_failed error=${error51 instanceof Error ? error51.message : String(error51)}`
87484
+ );
87485
+ });
87486
+ }
87354
87487
  async emitRequiredBridgeOutput(activeContext, projection) {
87355
87488
  const options = {
87356
87489
  discardOnFailure: true,
@@ -90138,6 +90271,8 @@ function createHarnessCommandHandler(input) {
90138
90271
  const { kind, ...claude } = config2;
90139
90272
  return createClaudeCodeCommandHandler({
90140
90273
  ...base,
90274
+ authorizeLease: input.authorizeLease,
90275
+ authorizeUsageTurn: input.authorizeUsageTurn,
90141
90276
  claude,
90142
90277
  readState: fileClaudeReadStateStore(),
90143
90278
  sessionResume: fileClaudeSessionResumeStore()
package/dist/index.js CHANGED
@@ -91158,7 +91158,7 @@ var init_package = __esm({
91158
91158
  "package.json"() {
91159
91159
  package_default = {
91160
91160
  name: "@autohq/cli",
91161
- version: "0.1.600",
91161
+ version: "0.1.601",
91162
91162
  license: "SEE LICENSE IN README.md",
91163
91163
  publishConfig: {
91164
91164
  access: "public"
@@ -102110,7 +102110,9 @@ var RUNTIME_BRIDGE_SOCKET_PATH = "/runtime/socket.io";
102110
102110
  var RUNTIME_BRIDGE_BOOTSTRAP_EVENT = "bridge.bootstrap";
102111
102111
  var RUNTIME_BRIDGE_CONNECTED_EVENT = "bridge.connected";
102112
102112
  var RUNTIME_BRIDGE_COMMAND_EVENT = "runtime.command";
102113
+ var RUNTIME_BRIDGE_LEASE_AUTHORIZATION_EVENT = "runtime.lease_authorization";
102113
102114
  var RUNTIME_BRIDGE_OUTPUT_EVENT = "runtime.output";
102115
+ var RUNTIME_BRIDGE_USAGE_TURN_EVENT = "runtime.usage_turn";
102114
102116
  var AgentBridgeMcpServerConfigSchema = external_exports.object({
102115
102117
  type: external_exports.literal("http"),
102116
102118
  url: external_exports.string().trim().min(1),
@@ -102220,6 +102222,19 @@ var RuntimeBridgeConnectedPayloadSchema = external_exports.object({
102220
102222
  runtimeId: RuntimeIdSchema2,
102221
102223
  bridgeLeaseId: RuntimeBridgeLeaseIdSchema2
102222
102224
  });
102225
+ var RuntimeBridgeLeaseAuthorizationRequestSchema = external_exports.object({
102226
+ sessionId: SessionIdSchema2,
102227
+ runtimeId: RuntimeIdSchema2,
102228
+ bridgeLeaseId: RuntimeBridgeLeaseIdSchema2
102229
+ }).strict();
102230
+ var RuntimeBridgeLeaseAuthorizationAckSchema = external_exports.object({
102231
+ sessionId: SessionIdSchema2,
102232
+ runtimeId: RuntimeIdSchema2,
102233
+ bridgeLeaseId: RuntimeBridgeLeaseIdSchema2,
102234
+ status: external_exports.enum(["authorized", "failed"]),
102235
+ error: external_exports.string().trim().min(1).optional(),
102236
+ at: external_exports.string().datetime()
102237
+ }).strict();
102223
102238
  var RuntimeBridgeCommandDeliverySchema = external_exports.object({
102224
102239
  type: external_exports.literal("command.delivery"),
102225
102240
  deliveryId: external_exports.string().trim().min(1),
@@ -102607,6 +102622,8 @@ async function runAgentBridgeSocket(options) {
102607
102622
  token: options.token,
102608
102623
  onBootstrap: options.onBootstrap,
102609
102624
  createHandler: (bootstrap) => options.createHandler({
102625
+ authorizeLease: (request) => authorizeLeaseWithAck(socket, request, options.runtimeLogger),
102626
+ authorizeUsageTurn: (output) => emitUsageTurnWithAck(socket, output, options.runtimeLogger),
102610
102627
  emitOutput: (output) => emitOutputWithAck(socket, output, options.runtimeLogger),
102611
102628
  onOutputAckProgress: terminalAuthDrain.handleOutputAckProgress,
102612
102629
  cycleSocket: () => {
@@ -102820,19 +102837,109 @@ function createRuntimeBridgeBootstrapListener(input) {
102820
102837
  };
102821
102838
  }
102822
102839
  function emitOutputWithAck(socket, output, runtimeLogger) {
102840
+ return emitRuntimeOutputWithAck({
102841
+ event: RUNTIME_BRIDGE_OUTPUT_EVENT,
102842
+ output,
102843
+ runtimeLogger,
102844
+ socket
102845
+ });
102846
+ }
102847
+ function authorizeLeaseWithAck(socket, request, runtimeLogger) {
102823
102848
  const startedAt = Date.now();
102824
- runtimeLogger?.info(
102849
+ runtimeLogger?.info("agent_bridge_lease_authorization_started", {
102850
+ session_id: request.sessionId,
102851
+ runtime_id: request.runtimeId,
102852
+ bridge_lease_id: request.bridgeLeaseId,
102853
+ socket_id: socket.id
102854
+ });
102855
+ return new Promise((resolve6, reject) => {
102856
+ socket.timeout(AGENT_BRIDGE_OUTPUT_ACK_TIMEOUT_MS).emit(
102857
+ RUNTIME_BRIDGE_LEASE_AUTHORIZATION_EVENT,
102858
+ request,
102859
+ (error51, rawAck) => {
102860
+ if (error51) {
102861
+ runtimeLogger?.warn("agent_bridge_lease_authorization_failed", {
102862
+ session_id: request.sessionId,
102863
+ runtime_id: request.runtimeId,
102864
+ bridge_lease_id: request.bridgeLeaseId,
102865
+ socket_id: socket.id,
102866
+ duration_ms: Date.now() - startedAt,
102867
+ error: error51.message
102868
+ });
102869
+ reject(
102870
+ new AgentBridgeOutputAckTimeoutError(
102871
+ `Bridge lease authorization ack timed out: ${error51.message}`
102872
+ )
102873
+ );
102874
+ return;
102875
+ }
102876
+ const ack = RuntimeBridgeLeaseAuthorizationAckSchema.safeParse(rawAck);
102877
+ if (!ack.success) {
102878
+ runtimeLogger?.warn("agent_bridge_lease_authorization_invalid", {
102879
+ session_id: request.sessionId,
102880
+ runtime_id: request.runtimeId,
102881
+ bridge_lease_id: request.bridgeLeaseId,
102882
+ socket_id: socket.id,
102883
+ duration_ms: Date.now() - startedAt,
102884
+ error: ack.error.message
102885
+ });
102886
+ reject(
102887
+ new Error(
102888
+ `Invalid bridge lease authorization ack: ${ack.error.message}`
102889
+ )
102890
+ );
102891
+ return;
102892
+ }
102893
+ if (ack.data.status === "failed") {
102894
+ runtimeLogger?.warn("agent_bridge_lease_authorization_rejected", {
102895
+ session_id: request.sessionId,
102896
+ runtime_id: request.runtimeId,
102897
+ bridge_lease_id: request.bridgeLeaseId,
102898
+ socket_id: socket.id,
102899
+ duration_ms: Date.now() - startedAt,
102900
+ error: ack.data.error
102901
+ });
102902
+ reject(
102903
+ new Error(
102904
+ ack.data.error ?? "Bridge lease is no longer authorized"
102905
+ )
102906
+ );
102907
+ return;
102908
+ }
102909
+ runtimeLogger?.info("agent_bridge_lease_authorization_ready", {
102910
+ session_id: request.sessionId,
102911
+ runtime_id: request.runtimeId,
102912
+ bridge_lease_id: request.bridgeLeaseId,
102913
+ socket_id: socket.id,
102914
+ duration_ms: Date.now() - startedAt
102915
+ });
102916
+ resolve6(ack.data);
102917
+ }
102918
+ );
102919
+ });
102920
+ }
102921
+ function emitUsageTurnWithAck(socket, output, runtimeLogger) {
102922
+ return emitRuntimeOutputWithAck({
102923
+ event: RUNTIME_BRIDGE_USAGE_TURN_EVENT,
102924
+ output,
102925
+ runtimeLogger,
102926
+ socket
102927
+ });
102928
+ }
102929
+ function emitRuntimeOutputWithAck(input) {
102930
+ const startedAt = Date.now();
102931
+ input.runtimeLogger?.info(
102825
102932
  "agent_bridge_output_emit_started",
102826
- outputLogContext(output, socket.id)
102933
+ outputLogContext(input.output, input.socket.id)
102827
102934
  );
102828
102935
  return new Promise((resolve6, reject) => {
102829
- socket.timeout(AGENT_BRIDGE_OUTPUT_ACK_TIMEOUT_MS).emit(
102830
- RUNTIME_BRIDGE_OUTPUT_EVENT,
102831
- output,
102936
+ input.socket.timeout(AGENT_BRIDGE_OUTPUT_ACK_TIMEOUT_MS).emit(
102937
+ input.event,
102938
+ input.output,
102832
102939
  (error51, rawAck) => {
102833
102940
  if (error51) {
102834
- runtimeLogger?.warn("agent_bridge_output_emit_ack_failed", {
102835
- ...outputLogContext(output, socket.id),
102941
+ input.runtimeLogger?.warn("agent_bridge_output_emit_ack_failed", {
102942
+ ...outputLogContext(input.output, input.socket.id),
102836
102943
  duration_ms: Date.now() - startedAt,
102837
102944
  error: error51.message
102838
102945
  });
@@ -102841,8 +102948,8 @@ function emitOutputWithAck(socket, output, runtimeLogger) {
102841
102948
  }
102842
102949
  const ack = RuntimeBridgeOutputAckSchema.safeParse(rawAck);
102843
102950
  if (!ack.success) {
102844
- runtimeLogger?.warn("agent_bridge_output_emit_ack_invalid", {
102845
- ...outputLogContext(output, socket.id),
102951
+ input.runtimeLogger?.warn("agent_bridge_output_emit_ack_invalid", {
102952
+ ...outputLogContext(input.output, input.socket.id),
102846
102953
  duration_ms: Date.now() - startedAt,
102847
102954
  error: ack.error.message
102848
102955
  });
@@ -102850,8 +102957,8 @@ function emitOutputWithAck(socket, output, runtimeLogger) {
102850
102957
  return;
102851
102958
  }
102852
102959
  if (ack.data.status === "failed") {
102853
- runtimeLogger?.warn("agent_bridge_output_emit_ack_rejected", {
102854
- ...outputLogContext(output, socket.id),
102960
+ input.runtimeLogger?.warn("agent_bridge_output_emit_ack_rejected", {
102961
+ ...outputLogContext(input.output, input.socket.id),
102855
102962
  duration_ms: Date.now() - startedAt,
102856
102963
  ack_status: ack.data.status,
102857
102964
  error: ack.data.error
@@ -102861,8 +102968,8 @@ function emitOutputWithAck(socket, output, runtimeLogger) {
102861
102968
  );
102862
102969
  return;
102863
102970
  }
102864
- runtimeLogger?.info("agent_bridge_output_emit_ack_ready", {
102865
- ...outputLogContext(output, socket.id),
102971
+ input.runtimeLogger?.info("agent_bridge_output_emit_ack_ready", {
102972
+ ...outputLogContext(input.output, input.socket.id),
102866
102973
  duration_ms: Date.now() - startedAt,
102867
102974
  ack_status: ack.data.status,
102868
102975
  cursor: ack.data.cursor
@@ -105191,6 +105298,15 @@ var AgentBridgeOutputBuffer = class {
105191
105298
  await this.flushPendingDelta();
105192
105299
  await this.enqueueProjectionAndDrain(context, projection, options);
105193
105300
  }
105301
+ async enqueueEntryProjection(context, projection) {
105302
+ await this.materializePendingUiDelta();
105303
+ this.materializePendingDelta();
105304
+ this.outputSeq += 1;
105305
+ this.enqueueOutput(
105306
+ buildOutputEnvelope(context, this.outputSeq, projection)
105307
+ );
105308
+ return { drained: this.drainPendingOutputs() };
105309
+ }
105194
105310
  async replayPendingOutputs() {
105195
105311
  await this.materializePendingUiDelta();
105196
105312
  await this.flushPendingDelta({ force: true });
@@ -105239,17 +105355,18 @@ var AgentBridgeOutputBuffer = class {
105239
105355
  * could attribute a billed call to the preceding turn.
105240
105356
  */
105241
105357
  async emitUsageTurn(context, turnId) {
105242
- this.outputSeq += 1;
105243
- this.enqueueOutput(
105244
- buildUsageTurnOutputEnvelope({
105245
- context,
105246
- outputSeq: this.outputSeq,
105247
- turnId,
105248
- createdAt: now2()
105249
- })
105250
- );
105358
+ this.enqueueOutput(this.nextUsageTurnOutput(context, turnId));
105251
105359
  await this.drainPendingOutputs({ failIfBlocked: true });
105252
105360
  }
105361
+ nextUsageTurnOutput(context, turnId) {
105362
+ this.outputSeq += 1;
105363
+ return buildUsageTurnOutputEnvelope({
105364
+ context,
105365
+ outputSeq: this.outputSeq,
105366
+ turnId,
105367
+ createdAt: now2()
105368
+ });
105369
+ }
105253
105370
  async emitUiMessageChunk(context, projection) {
105254
105371
  await this.flushPendingDelta();
105255
105372
  await this.emitLiveUiMessageChunk(context, projection.chunk);
@@ -105518,6 +105635,13 @@ var AgentBridgeOutputBuffer = class {
105518
105635
  this.deltaFlushTimer = null;
105519
105636
  }
105520
105637
  async flushPendingDelta(options = {}) {
105638
+ if (!this.pendingDelta) {
105639
+ return;
105640
+ }
105641
+ this.materializePendingDelta();
105642
+ await this.drainPendingOutputs(options);
105643
+ }
105644
+ materializePendingDelta() {
105521
105645
  const pendingDelta = this.pendingDelta;
105522
105646
  if (!pendingDelta) {
105523
105647
  return;
@@ -105525,14 +105649,14 @@ var AgentBridgeOutputBuffer = class {
105525
105649
  this.clearDeltaFlushTimer();
105526
105650
  this.pendingDelta = null;
105527
105651
  this.outputSeq += 1;
105528
- const output = buildDeltaOutputEnvelope({
105529
- context: pendingDelta.context,
105530
- outputSeq: this.outputSeq,
105531
- delta: pendingDelta.delta,
105532
- createdAt: pendingDelta.createdAt
105533
- });
105534
- this.enqueueOutput(output);
105535
- await this.drainPendingOutputs(options);
105652
+ this.enqueueOutput(
105653
+ buildDeltaOutputEnvelope({
105654
+ context: pendingDelta.context,
105655
+ outputSeq: this.outputSeq,
105656
+ delta: pendingDelta.delta,
105657
+ createdAt: pendingDelta.createdAt
105658
+ })
105659
+ );
105536
105660
  }
105537
105661
  async emitUntilAcked(output) {
105538
105662
  for (let attempt = 0; ; attempt += 1) {
@@ -106058,7 +106182,7 @@ function buildLivenessOutputEnvelope(input) {
106058
106182
  }
106059
106183
  function buildUsageTurnOutputEnvelope(input) {
106060
106184
  const { context } = input;
106061
- return RuntimeBridgeOutputEnvelopeSchema.parse({
106185
+ return RuntimeBridgeOutputUsageTurnEnvelopeSchema.parse({
106062
106186
  type: "runtime.usage_turn",
106063
106187
  sessionId: context.sessionId,
106064
106188
  runtimeId: context.runtimeId,
@@ -108570,30 +108694,24 @@ var ClaudeCodeCommandHandler = class {
108570
108694
  // original delivery and any redeliveries, so failures travel as values.
108571
108695
  async injectMessageCommand(activeContext, delivery, message, socketId) {
108572
108696
  try {
108573
- const emitStartedAt = Date.now();
108574
- this.input.runtimeLogger?.info(
108575
- "agent_bridge_claude_command_user_entry_emit_started",
108576
- commandLogContext(delivery, { socket_id: socketId })
108577
- );
108578
- await this.emitRequiredBridgeOutput(activeContext, {
108579
- type: "entry",
108580
- entry: {
108581
- messageId: delivery.commandId,
108582
- role: "user",
108583
- kind: "message",
108584
- status: "completed",
108585
- content: {
108586
- parts: [{ type: "text", text: message }]
108587
- }
108697
+ const enqueueStartedAt = Date.now();
108698
+ await this.enqueueUserEntryBridgeOutput(activeContext, {
108699
+ messageId: delivery.commandId,
108700
+ role: "user",
108701
+ kind: "message",
108702
+ status: "completed",
108703
+ content: {
108704
+ parts: [{ type: "text", text: message }]
108588
108705
  }
108589
108706
  });
108590
108707
  this.input.runtimeLogger?.info(
108591
- "agent_bridge_claude_command_user_entry_emit_ready",
108708
+ "agent_bridge_claude_command_user_entry_enqueued",
108592
108709
  commandLogContext(delivery, {
108593
108710
  socket_id: socketId,
108594
- duration_ms: Date.now() - emitStartedAt
108711
+ duration_ms: Date.now() - enqueueStartedAt
108595
108712
  })
108596
108713
  );
108714
+ await this.input.authorizeLease(activeContext);
108597
108715
  const sendStartedAt = Date.now();
108598
108716
  const mode = deliveryMode(delivery);
108599
108717
  this.applySelectionForMessage(delivery);
@@ -108687,18 +108805,16 @@ var ClaudeCodeCommandHandler = class {
108687
108805
  return;
108688
108806
  }
108689
108807
  const message = answerFallbackMessage(answer);
108690
- await this.emitRequiredBridgeOutput(activeContext, {
108691
- type: "entry",
108692
- entry: {
108693
- messageId: delivery.commandId,
108694
- role: "user",
108695
- kind: "message",
108696
- status: "completed",
108697
- content: {
108698
- parts: [{ type: "text", text: message }]
108699
- }
108808
+ await this.enqueueUserEntryBridgeOutput(activeContext, {
108809
+ messageId: delivery.commandId,
108810
+ role: "user",
108811
+ kind: "message",
108812
+ status: "completed",
108813
+ content: {
108814
+ parts: [{ type: "text", text: message }]
108700
108815
  }
108701
108816
  });
108817
+ await this.input.authorizeLease(activeContext);
108702
108818
  await this.ensureAgentSession().sendMessage(message, {
108703
108819
  commandId: delivery.commandId
108704
108820
  });
@@ -108780,7 +108896,13 @@ var ClaudeCodeCommandHandler = class {
108780
108896
  if (!activeContext) {
108781
108897
  throw new Error("Cannot publish usage turn without bridge context");
108782
108898
  }
108783
- await this.outputBuffer.emitUsageTurn(activeContext, turnId);
108899
+ if (turnId) {
108900
+ await this.input.authorizeUsageTurn(
108901
+ this.outputBuffer.nextUsageTurnOutput(activeContext, turnId)
108902
+ );
108903
+ return;
108904
+ }
108905
+ await this.outputBuffer.emitUsageTurn(activeContext, null);
108784
108906
  }
108785
108907
  async emitBridgeOutput(activeContext, projection) {
108786
108908
  try {
@@ -108791,6 +108913,17 @@ var ClaudeCodeCommandHandler = class {
108791
108913
  );
108792
108914
  }
108793
108915
  }
108916
+ async enqueueUserEntryBridgeOutput(activeContext, entry) {
108917
+ const { drained } = await this.outputBuffer.enqueueEntryProjection(
108918
+ activeContext,
108919
+ { type: "entry", entry }
108920
+ );
108921
+ drained.catch((error51) => {
108922
+ this.input.writeOutput?.(
108923
+ `agent_bridge_output_emit_failed error=${error51 instanceof Error ? error51.message : String(error51)}`
108924
+ );
108925
+ });
108926
+ }
108794
108927
  async emitRequiredBridgeOutput(activeContext, projection) {
108795
108928
  const options = {
108796
108929
  discardOnFailure: true,
@@ -111583,6 +111716,8 @@ function createHarnessCommandHandler(input) {
111583
111716
  const { kind, ...claude } = config2;
111584
111717
  return createClaudeCodeCommandHandler({
111585
111718
  ...base,
111719
+ authorizeLease: input.authorizeLease,
111720
+ authorizeUsageTurn: input.authorizeUsageTurn,
111586
111721
  claude,
111587
111722
  readState: fileClaudeReadStateStore(),
111588
111723
  sessionResume: fileClaudeSessionResumeStore()
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@autohq/cli",
3
- "version": "0.1.600",
3
+ "version": "0.1.601",
4
4
  "license": "SEE LICENSE IN README.md",
5
5
  "publishConfig": {
6
6
  "access": "public"