@autohq/cli 0.1.226 → 0.1.228

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.
@@ -23322,7 +23322,7 @@ Object.assign(lookup, {
23322
23322
  // package.json
23323
23323
  var package_default = {
23324
23324
  name: "@autohq/cli",
23325
- version: "0.1.226",
23325
+ version: "0.1.228",
23326
23326
  license: "SEE LICENSE IN README.md",
23327
23327
  publishConfig: {
23328
23328
  access: "public"
@@ -27646,6 +27646,7 @@ var UsageEventRecordSchema = UsageEventSchema.extend({
27646
27646
  });
27647
27647
 
27648
27648
  // src/commands/agent-bridge/harness/output-buffer.ts
27649
+ var AGENT_BRIDGE_OUTPUT_DELTA_FLUSH_MS = 50;
27649
27650
  var AgentBridgeOutputBuffer = class {
27650
27651
  constructor(input) {
27651
27652
  this.input = input;
@@ -27654,26 +27655,23 @@ var AgentBridgeOutputBuffer = class {
27654
27655
  input;
27655
27656
  outputSeq;
27656
27657
  pendingOutputs = /* @__PURE__ */ new Map();
27658
+ pendingDelta = null;
27659
+ deltaFlushTimer = null;
27657
27660
  drainBlocked = false;
27658
27661
  drainPromise = null;
27659
27662
  // ---------------------------------------------------------------------------
27660
27663
  // Public API
27661
27664
  // ---------------------------------------------------------------------------
27662
27665
  async emitProjection(context, projection) {
27663
- this.outputSeq += 1;
27664
- this.pendingOutputs.set(
27665
- this.outputSeq,
27666
- buildOutputEnvelope(context, this.outputSeq, projection)
27667
- );
27668
- this.input.runtimeLogger?.info(
27669
- "agent_bridge_output_buffer_enqueued",
27670
- this.outputLogContext(this.pendingOutputs.get(this.outputSeq), {
27671
- pending_count: this.pendingOutputs.size
27672
- })
27673
- );
27674
- await this.drainPendingOutputs();
27666
+ if (projection.type === "delta") {
27667
+ await this.bufferDelta(context, projection.delta);
27668
+ return;
27669
+ }
27670
+ await this.flushPendingDelta();
27671
+ await this.enqueueProjectionAndDrain(context, projection);
27675
27672
  }
27676
27673
  async replayPendingOutputs() {
27674
+ await this.flushPendingDelta({ force: true });
27677
27675
  await this.drainPendingOutputs({ force: true });
27678
27676
  }
27679
27677
  // ---------------------------------------------------------------------------
@@ -27717,6 +27715,59 @@ var AgentBridgeOutputBuffer = class {
27717
27715
  });
27718
27716
  await this.drainPromise;
27719
27717
  }
27718
+ // ---------------------------------------------------------------------------
27719
+ // Delta coalescing
27720
+ // ---------------------------------------------------------------------------
27721
+ async bufferDelta(context, delta) {
27722
+ if (this.pendingDelta && canCoalesceDelta(this.pendingDelta, context, delta)) {
27723
+ this.pendingDelta = coalesceDelta(this.pendingDelta, delta);
27724
+ return;
27725
+ }
27726
+ await this.flushPendingDelta();
27727
+ this.pendingDelta = { context, delta, createdAt: now2() };
27728
+ this.scheduleDeltaFlush();
27729
+ }
27730
+ scheduleDeltaFlush() {
27731
+ if (this.deltaFlushTimer !== null) {
27732
+ return;
27733
+ }
27734
+ this.deltaFlushTimer = setTimeout(() => {
27735
+ void this.flushPendingDelta().catch((error51) => {
27736
+ this.drainBlocked = true;
27737
+ this.input.runtimeLogger?.warn(
27738
+ "agent_bridge_output_buffer_flush_failed",
27739
+ {
27740
+ error: error51 instanceof Error ? error51.message : String(error51),
27741
+ pending_count: this.pendingOutputs.size
27742
+ }
27743
+ );
27744
+ });
27745
+ }, AGENT_BRIDGE_OUTPUT_DELTA_FLUSH_MS);
27746
+ }
27747
+ clearDeltaFlushTimer() {
27748
+ if (this.deltaFlushTimer === null) {
27749
+ return;
27750
+ }
27751
+ clearTimeout(this.deltaFlushTimer);
27752
+ this.deltaFlushTimer = null;
27753
+ }
27754
+ async flushPendingDelta(options = {}) {
27755
+ const pendingDelta = this.pendingDelta;
27756
+ if (!pendingDelta) {
27757
+ return;
27758
+ }
27759
+ this.clearDeltaFlushTimer();
27760
+ this.pendingDelta = null;
27761
+ this.outputSeq += 1;
27762
+ const output = buildDeltaOutputEnvelope({
27763
+ context: pendingDelta.context,
27764
+ outputSeq: this.outputSeq,
27765
+ delta: pendingDelta.delta,
27766
+ createdAt: pendingDelta.createdAt
27767
+ });
27768
+ this.enqueueOutput(output);
27769
+ await this.drainPendingOutputs(options);
27770
+ }
27720
27771
  async emitUntilAcked(output) {
27721
27772
  const startedAt = Date.now();
27722
27773
  this.input.runtimeLogger?.info(
@@ -27755,6 +27806,22 @@ var AgentBridgeOutputBuffer = class {
27755
27806
  (left, right) => left.outputSeq - right.outputSeq
27756
27807
  )[0] ?? null;
27757
27808
  }
27809
+ async enqueueProjectionAndDrain(context, projection) {
27810
+ this.outputSeq += 1;
27811
+ this.enqueueOutput(
27812
+ buildOutputEnvelope(context, this.outputSeq, projection)
27813
+ );
27814
+ await this.drainPendingOutputs();
27815
+ }
27816
+ enqueueOutput(output) {
27817
+ this.pendingOutputs.set(output.outputSeq, output);
27818
+ this.input.runtimeLogger?.info(
27819
+ "agent_bridge_output_buffer_enqueued",
27820
+ this.outputLogContext(output, {
27821
+ pending_count: this.pendingOutputs.size
27822
+ })
27823
+ );
27824
+ }
27758
27825
  outputLogContext(output, fields = {}) {
27759
27826
  return {
27760
27827
  output_seq: output?.outputSeq,
@@ -27767,20 +27834,27 @@ var AgentBridgeOutputBuffer = class {
27767
27834
  };
27768
27835
  }
27769
27836
  };
27837
+ function canCoalesceDelta(pending, context, delta) {
27838
+ return pending.context.sessionId === context.sessionId && pending.context.runtimeId === context.runtimeId && pending.context.bridgeLeaseId === context.bridgeLeaseId && pending.delta.messageId === delta.messageId && pending.delta.partId === delta.partId && pending.delta.role === delta.role && pending.delta.kind === delta.kind && pending.delta.delta.type === "text" && delta.delta.type === "text";
27839
+ }
27840
+ function coalesceDelta(pending, delta) {
27841
+ return {
27842
+ ...pending,
27843
+ delta: {
27844
+ ...pending.delta,
27845
+ delta: {
27846
+ type: "text",
27847
+ text: pending.delta.delta.text + delta.delta.text
27848
+ }
27849
+ }
27850
+ };
27851
+ }
27770
27852
  function buildOutputEnvelope(context, outputSeq, projection) {
27771
27853
  if (projection.type === "delta") {
27772
- const { delta } = projection;
27773
- return RuntimeBridgeOutputEnvelopeSchema.parse({
27774
- type: "conversation.delta",
27775
- sessionId: context.sessionId,
27776
- runtimeId: context.runtimeId,
27777
- bridgeLeaseId: context.bridgeLeaseId,
27854
+ return buildDeltaOutputEnvelope({
27855
+ context,
27778
27856
  outputSeq,
27779
- messageId: delta.messageId,
27780
- partId: delta.partId,
27781
- role: delta.role,
27782
- kind: delta.kind,
27783
- delta: delta.delta,
27857
+ delta: projection.delta,
27784
27858
  createdAt: now2()
27785
27859
  });
27786
27860
  }
@@ -27802,6 +27876,22 @@ function buildOutputEnvelope(context, outputSeq, projection) {
27802
27876
  ...entry.turnStatus ? { turnStatus: entry.turnStatus } : {}
27803
27877
  });
27804
27878
  }
27879
+ function buildDeltaOutputEnvelope(input) {
27880
+ const { context, delta } = input;
27881
+ return RuntimeBridgeOutputEnvelopeSchema.parse({
27882
+ type: "conversation.delta",
27883
+ sessionId: context.sessionId,
27884
+ runtimeId: context.runtimeId,
27885
+ bridgeLeaseId: context.bridgeLeaseId,
27886
+ outputSeq: input.outputSeq,
27887
+ messageId: delta.messageId,
27888
+ partId: delta.partId,
27889
+ role: delta.role,
27890
+ kind: delta.kind,
27891
+ delta: delta.delta,
27892
+ createdAt: input.createdAt
27893
+ });
27894
+ }
27805
27895
  function isSuccessfulOutputAck(ack) {
27806
27896
  return ack.status === "persisted" || ack.status === "duplicate" || ack.status === "published";
27807
27897
  }
package/dist/index.js CHANGED
@@ -22238,7 +22238,7 @@ var init_package = __esm({
22238
22238
  "package.json"() {
22239
22239
  package_default = {
22240
22240
  name: "@autohq/cli",
22241
- version: "0.1.226",
22241
+ version: "0.1.228",
22242
22242
  license: "SEE LICENSE IN README.md",
22243
22243
  publishConfig: {
22244
22244
  access: "public"
@@ -26371,7 +26371,8 @@ function ConversationView({
26371
26371
  word: pickActivityWord(sessionId)
26372
26372
  });
26373
26373
  const sawLiveTurnActivity = useRef(false);
26374
- const pendingLocalCommand = useRef(false);
26374
+ const pendingLocalCommand = useRef(null);
26375
+ const lastSessionUpdatedAt = useRef(null);
26375
26376
  const awaitingReplyRef = useRef(true);
26376
26377
  const updateAwaitingReply = useCallback((value) => {
26377
26378
  awaitingReplyRef.current = value;
@@ -26397,10 +26398,13 @@ function ConversationView({
26397
26398
  status: session.status,
26398
26399
  runInput: session.input,
26399
26400
  hasConversationActivity: hasConversationActivity.current,
26400
- hasPendingLocalCommand: pendingLocalCommand.current
26401
+ pendingLocalCommand: pendingLocalCommand.current,
26402
+ sessionUpdatedAt: session.updatedAt
26401
26403
  })) {
26404
+ pendingLocalCommand.current = null;
26402
26405
  updateAwaitingReply(false);
26403
26406
  }
26407
+ lastSessionUpdatedAt.current = session.updatedAt;
26404
26408
  },
26405
26409
  [updateAwaitingReply]
26406
26410
  );
@@ -26413,12 +26417,12 @@ function ConversationView({
26413
26417
  return;
26414
26418
  }
26415
26419
  if (event.kind === "question") {
26416
- pendingLocalCommand.current = false;
26420
+ pendingLocalCommand.current = null;
26417
26421
  updateAwaitingReply(false);
26418
26422
  return;
26419
26423
  }
26420
26424
  if (isTurnLifecycleStartEntry(event)) {
26421
- pendingLocalCommand.current = false;
26425
+ pendingLocalCommand.current = null;
26422
26426
  if (!awaitingReplyRef.current) {
26423
26427
  turnRef.current = {
26424
26428
  startedAt: Date.now(),
@@ -26435,7 +26439,7 @@ function ConversationView({
26435
26439
  if (!turnEnd) {
26436
26440
  return;
26437
26441
  }
26438
- pendingLocalCommand.current = false;
26442
+ pendingLocalCommand.current = null;
26439
26443
  updateAwaitingReply(false);
26440
26444
  if (turnEnd === "completed" && sawLiveTurnActivity.current) {
26441
26445
  setCompletedTurn({
@@ -26588,7 +26592,9 @@ function ConversationView({
26588
26592
  setInput("");
26589
26593
  hasConversationActivity.current = true;
26590
26594
  updateAwaitingReply(true);
26591
- pendingLocalCommand.current = true;
26595
+ pendingLocalCommand.current = {
26596
+ previousSessionUpdatedAt: lastSessionUpdatedAt.current
26597
+ };
26592
26598
  turnRef.current = { startedAt: Date.now(), word: pickActivityWord(text) };
26593
26599
  sawLiveTurnActivity.current = false;
26594
26600
  setTurnTokenChars(0);
@@ -26636,7 +26642,7 @@ function ConversationView({
26636
26642
  return next;
26637
26643
  });
26638
26644
  }
26639
- pendingLocalCommand.current = false;
26645
+ pendingLocalCommand.current = null;
26640
26646
  updateAwaitingReply(false);
26641
26647
  throw err;
26642
26648
  } finally {
@@ -26661,7 +26667,9 @@ function ConversationView({
26661
26667
  }
26662
26668
  hasConversationActivity.current = true;
26663
26669
  updateAwaitingReply(true);
26664
- pendingLocalCommand.current = true;
26670
+ pendingLocalCommand.current = {
26671
+ previousSessionUpdatedAt: lastSessionUpdatedAt.current
26672
+ };
26665
26673
  turnRef.current = {
26666
26674
  startedAt: Date.now(),
26667
26675
  word: pickActivityWord(toolCallId)
@@ -26683,7 +26691,7 @@ function ConversationView({
26683
26691
  next.delete(toolCallId);
26684
26692
  return next;
26685
26693
  });
26686
- pendingLocalCommand.current = false;
26694
+ pendingLocalCommand.current = null;
26687
26695
  updateAwaitingReply(false);
26688
26696
  throw err;
26689
26697
  } finally {
@@ -26836,7 +26844,7 @@ function ConversationView({
26836
26844
  /* @__PURE__ */ jsx4(Text4, { dimColor: true, children: "esc to go back" }),
26837
26845
  /* @__PURE__ */ jsx4(Text4, { dimColor: true, children: "\xB7" }),
26838
26846
  /* @__PURE__ */ jsxs4(Text4, { dimColor: true, children: [
26839
- awaitingReply && !isFailed ? "working" : status,
26847
+ footerSessionStatusLabel({ status, awaitingReply }),
26840
26848
  debugActive ? " \xB7 debug" : ""
26841
26849
  ] })
26842
26850
  ] })
@@ -26933,14 +26941,20 @@ function elapsedSeconds(startedAt) {
26933
26941
  return Math.max(0, Math.floor((Date.now() - startedAt) / 1e3));
26934
26942
  }
26935
26943
  function shouldAcceptUserInputFromRunSnapshot(input) {
26936
- if (input.hasPendingLocalCommand) {
26937
- return false;
26938
- }
26939
26944
  if (input.status === "awaiting") {
26940
- return true;
26945
+ return input.pendingLocalCommand === null || input.pendingLocalCommand.previousSessionUpdatedAt === null || input.sessionUpdatedAt !== input.pendingLocalCommand.previousSessionUpdatedAt;
26946
+ }
26947
+ if (input.pendingLocalCommand !== null) {
26948
+ return false;
26941
26949
  }
26942
26950
  return input.status === "running" && !input.hasConversationActivity && isInteractiveRunInputWithoutMessage(input.runInput);
26943
26951
  }
26952
+ function footerSessionStatusLabel(input) {
26953
+ if (input.status === "running" && input.awaitingReply) {
26954
+ return "working";
26955
+ }
26956
+ return input.status;
26957
+ }
26944
26958
  function isInteractiveRunInputWithoutMessage(input) {
26945
26959
  return typeof input === "object" && input !== null && !Array.isArray(input) && "interactive" in input && input.interactive === true && !("message" in input && typeof input.message === "string" && input.message.trim().length > 0);
26946
26960
  }
@@ -32348,6 +32362,7 @@ function errorMessage(error51) {
32348
32362
  init_src();
32349
32363
 
32350
32364
  // src/commands/agent-bridge/harness/output-buffer.ts
32365
+ var AGENT_BRIDGE_OUTPUT_DELTA_FLUSH_MS = 50;
32351
32366
  var AgentBridgeOutputBuffer = class {
32352
32367
  constructor(input) {
32353
32368
  this.input = input;
@@ -32356,26 +32371,23 @@ var AgentBridgeOutputBuffer = class {
32356
32371
  input;
32357
32372
  outputSeq;
32358
32373
  pendingOutputs = /* @__PURE__ */ new Map();
32374
+ pendingDelta = null;
32375
+ deltaFlushTimer = null;
32359
32376
  drainBlocked = false;
32360
32377
  drainPromise = null;
32361
32378
  // ---------------------------------------------------------------------------
32362
32379
  // Public API
32363
32380
  // ---------------------------------------------------------------------------
32364
32381
  async emitProjection(context, projection) {
32365
- this.outputSeq += 1;
32366
- this.pendingOutputs.set(
32367
- this.outputSeq,
32368
- buildOutputEnvelope(context, this.outputSeq, projection)
32369
- );
32370
- this.input.runtimeLogger?.info(
32371
- "agent_bridge_output_buffer_enqueued",
32372
- this.outputLogContext(this.pendingOutputs.get(this.outputSeq), {
32373
- pending_count: this.pendingOutputs.size
32374
- })
32375
- );
32376
- await this.drainPendingOutputs();
32382
+ if (projection.type === "delta") {
32383
+ await this.bufferDelta(context, projection.delta);
32384
+ return;
32385
+ }
32386
+ await this.flushPendingDelta();
32387
+ await this.enqueueProjectionAndDrain(context, projection);
32377
32388
  }
32378
32389
  async replayPendingOutputs() {
32390
+ await this.flushPendingDelta({ force: true });
32379
32391
  await this.drainPendingOutputs({ force: true });
32380
32392
  }
32381
32393
  // ---------------------------------------------------------------------------
@@ -32419,6 +32431,59 @@ var AgentBridgeOutputBuffer = class {
32419
32431
  });
32420
32432
  await this.drainPromise;
32421
32433
  }
32434
+ // ---------------------------------------------------------------------------
32435
+ // Delta coalescing
32436
+ // ---------------------------------------------------------------------------
32437
+ async bufferDelta(context, delta) {
32438
+ if (this.pendingDelta && canCoalesceDelta(this.pendingDelta, context, delta)) {
32439
+ this.pendingDelta = coalesceDelta(this.pendingDelta, delta);
32440
+ return;
32441
+ }
32442
+ await this.flushPendingDelta();
32443
+ this.pendingDelta = { context, delta, createdAt: now2() };
32444
+ this.scheduleDeltaFlush();
32445
+ }
32446
+ scheduleDeltaFlush() {
32447
+ if (this.deltaFlushTimer !== null) {
32448
+ return;
32449
+ }
32450
+ this.deltaFlushTimer = setTimeout(() => {
32451
+ void this.flushPendingDelta().catch((error51) => {
32452
+ this.drainBlocked = true;
32453
+ this.input.runtimeLogger?.warn(
32454
+ "agent_bridge_output_buffer_flush_failed",
32455
+ {
32456
+ error: error51 instanceof Error ? error51.message : String(error51),
32457
+ pending_count: this.pendingOutputs.size
32458
+ }
32459
+ );
32460
+ });
32461
+ }, AGENT_BRIDGE_OUTPUT_DELTA_FLUSH_MS);
32462
+ }
32463
+ clearDeltaFlushTimer() {
32464
+ if (this.deltaFlushTimer === null) {
32465
+ return;
32466
+ }
32467
+ clearTimeout(this.deltaFlushTimer);
32468
+ this.deltaFlushTimer = null;
32469
+ }
32470
+ async flushPendingDelta(options = {}) {
32471
+ const pendingDelta = this.pendingDelta;
32472
+ if (!pendingDelta) {
32473
+ return;
32474
+ }
32475
+ this.clearDeltaFlushTimer();
32476
+ this.pendingDelta = null;
32477
+ this.outputSeq += 1;
32478
+ const output = buildDeltaOutputEnvelope({
32479
+ context: pendingDelta.context,
32480
+ outputSeq: this.outputSeq,
32481
+ delta: pendingDelta.delta,
32482
+ createdAt: pendingDelta.createdAt
32483
+ });
32484
+ this.enqueueOutput(output);
32485
+ await this.drainPendingOutputs(options);
32486
+ }
32422
32487
  async emitUntilAcked(output) {
32423
32488
  const startedAt = Date.now();
32424
32489
  this.input.runtimeLogger?.info(
@@ -32457,6 +32522,22 @@ var AgentBridgeOutputBuffer = class {
32457
32522
  (left, right) => left.outputSeq - right.outputSeq
32458
32523
  )[0] ?? null;
32459
32524
  }
32525
+ async enqueueProjectionAndDrain(context, projection) {
32526
+ this.outputSeq += 1;
32527
+ this.enqueueOutput(
32528
+ buildOutputEnvelope(context, this.outputSeq, projection)
32529
+ );
32530
+ await this.drainPendingOutputs();
32531
+ }
32532
+ enqueueOutput(output) {
32533
+ this.pendingOutputs.set(output.outputSeq, output);
32534
+ this.input.runtimeLogger?.info(
32535
+ "agent_bridge_output_buffer_enqueued",
32536
+ this.outputLogContext(output, {
32537
+ pending_count: this.pendingOutputs.size
32538
+ })
32539
+ );
32540
+ }
32460
32541
  outputLogContext(output, fields = {}) {
32461
32542
  return {
32462
32543
  output_seq: output?.outputSeq,
@@ -32469,20 +32550,27 @@ var AgentBridgeOutputBuffer = class {
32469
32550
  };
32470
32551
  }
32471
32552
  };
32553
+ function canCoalesceDelta(pending, context, delta) {
32554
+ return pending.context.sessionId === context.sessionId && pending.context.runtimeId === context.runtimeId && pending.context.bridgeLeaseId === context.bridgeLeaseId && pending.delta.messageId === delta.messageId && pending.delta.partId === delta.partId && pending.delta.role === delta.role && pending.delta.kind === delta.kind && pending.delta.delta.type === "text" && delta.delta.type === "text";
32555
+ }
32556
+ function coalesceDelta(pending, delta) {
32557
+ return {
32558
+ ...pending,
32559
+ delta: {
32560
+ ...pending.delta,
32561
+ delta: {
32562
+ type: "text",
32563
+ text: pending.delta.delta.text + delta.delta.text
32564
+ }
32565
+ }
32566
+ };
32567
+ }
32472
32568
  function buildOutputEnvelope(context, outputSeq, projection) {
32473
32569
  if (projection.type === "delta") {
32474
- const { delta } = projection;
32475
- return RuntimeBridgeOutputEnvelopeSchema.parse({
32476
- type: "conversation.delta",
32477
- sessionId: context.sessionId,
32478
- runtimeId: context.runtimeId,
32479
- bridgeLeaseId: context.bridgeLeaseId,
32570
+ return buildDeltaOutputEnvelope({
32571
+ context,
32480
32572
  outputSeq,
32481
- messageId: delta.messageId,
32482
- partId: delta.partId,
32483
- role: delta.role,
32484
- kind: delta.kind,
32485
- delta: delta.delta,
32573
+ delta: projection.delta,
32486
32574
  createdAt: now2()
32487
32575
  });
32488
32576
  }
@@ -32504,6 +32592,22 @@ function buildOutputEnvelope(context, outputSeq, projection) {
32504
32592
  ...entry.turnStatus ? { turnStatus: entry.turnStatus } : {}
32505
32593
  });
32506
32594
  }
32595
+ function buildDeltaOutputEnvelope(input) {
32596
+ const { context, delta } = input;
32597
+ return RuntimeBridgeOutputEnvelopeSchema.parse({
32598
+ type: "conversation.delta",
32599
+ sessionId: context.sessionId,
32600
+ runtimeId: context.runtimeId,
32601
+ bridgeLeaseId: context.bridgeLeaseId,
32602
+ outputSeq: input.outputSeq,
32603
+ messageId: delta.messageId,
32604
+ partId: delta.partId,
32605
+ role: delta.role,
32606
+ kind: delta.kind,
32607
+ delta: delta.delta,
32608
+ createdAt: input.createdAt
32609
+ });
32610
+ }
32507
32611
  function isSuccessfulOutputAck(ack) {
32508
32612
  return ack.status === "persisted" || ack.status === "duplicate" || ack.status === "published";
32509
32613
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@autohq/cli",
3
- "version": "0.1.226",
3
+ "version": "0.1.228",
4
4
  "license": "SEE LICENSE IN README.md",
5
5
  "publishConfig": {
6
6
  "access": "public"