@autohq/cli 0.1.326 → 0.1.327

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.
@@ -23434,7 +23434,7 @@ Object.assign(lookup, {
23434
23434
  // package.json
23435
23435
  var package_default = {
23436
23436
  name: "@autohq/cli",
23437
- version: "0.1.326",
23437
+ version: "0.1.327",
23438
23438
  license: "SEE LICENSE IN README.md",
23439
23439
  publishConfig: {
23440
23440
  access: "public"
@@ -42432,6 +42432,7 @@ function providerMetadataField(providerMetadata) {
42432
42432
 
42433
42433
  // src/commands/agent-bridge/harness/output-buffer.ts
42434
42434
  var AGENT_BRIDGE_OUTPUT_DELTA_FLUSH_MS = 50;
42435
+ var AGENT_BRIDGE_OUTPUT_UI_DELTA_MAX_CHARS = 32768;
42435
42436
  var AGENT_BRIDGE_OUTPUT_ACK_RETRY_BACKOFF_MS = [250, 1e3];
42436
42437
  var AgentBridgeOutputBuffer = class {
42437
42438
  constructor(input) {
@@ -42443,6 +42444,8 @@ var AgentBridgeOutputBuffer = class {
42443
42444
  pendingOutputs = /* @__PURE__ */ new Map();
42444
42445
  pendingDelta = null;
42445
42446
  deltaFlushTimer = null;
42447
+ pendingUiDelta = null;
42448
+ uiDeltaFlushTimer = null;
42446
42449
  activeUiMessageAssembler = null;
42447
42450
  uiMessagePartTracker = new UiMessagePartTracker();
42448
42451
  drainBlocked = false;
@@ -42452,6 +42455,12 @@ var AgentBridgeOutputBuffer = class {
42452
42455
  // ---------------------------------------------------------------------------
42453
42456
  async emitProjection(context, projection) {
42454
42457
  if (projection.type === "ui_message_chunk") {
42458
+ const coalescible = coalescibleUiDeltaChunk(projection);
42459
+ if (coalescible) {
42460
+ await this.bufferUiDeltaChunk(context, coalescible);
42461
+ return;
42462
+ }
42463
+ await this.flushPendingUiDelta();
42455
42464
  await this.emitUiMessageChunk(context, projection);
42456
42465
  return;
42457
42466
  }
@@ -42459,10 +42468,12 @@ var AgentBridgeOutputBuffer = class {
42459
42468
  await this.bufferDelta(context, projection.delta);
42460
42469
  return;
42461
42470
  }
42471
+ await this.flushPendingUiDelta();
42462
42472
  await this.flushPendingDelta();
42463
42473
  await this.enqueueProjectionAndDrain(context, projection);
42464
42474
  }
42465
42475
  async replayPendingOutputs() {
42476
+ await this.materializePendingUiDelta();
42466
42477
  await this.flushPendingDelta({ force: true });
42467
42478
  await this.drainPendingOutputs({ force: true });
42468
42479
  }
@@ -42586,10 +42597,15 @@ var AgentBridgeOutputBuffer = class {
42586
42597
  this.drainPromise ??= (async () => {
42587
42598
  while (true) {
42588
42599
  const output = this.nextPendingOutput();
42589
- if (!output) {
42590
- return;
42600
+ if (output) {
42601
+ await this.emitUntilAcked(output);
42602
+ continue;
42591
42603
  }
42592
- await this.emitUntilAcked(output);
42604
+ if (this.pendingUiDelta) {
42605
+ await this.materializePendingUiDelta();
42606
+ continue;
42607
+ }
42608
+ return;
42593
42609
  }
42594
42610
  })().catch((error51) => {
42595
42611
  this.drainBlocked = true;
@@ -42600,6 +42616,85 @@ var AgentBridgeOutputBuffer = class {
42600
42616
  await this.drainPromise;
42601
42617
  }
42602
42618
  // ---------------------------------------------------------------------------
42619
+ // UI chunk delta coalescing
42620
+ // ---------------------------------------------------------------------------
42621
+ async bufferUiDeltaChunk(context, chunk) {
42622
+ const pending = this.pendingUiDelta;
42623
+ if (pending && canCoalesceUiDelta(pending, context, chunk)) {
42624
+ pending.chunk = mergeUiDeltaChunks(pending.chunk, chunk);
42625
+ if (uiDeltaTextLength(pending.chunk) >= AGENT_BRIDGE_OUTPUT_UI_DELTA_MAX_CHARS) {
42626
+ await this.flushPendingUiDelta();
42627
+ }
42628
+ return;
42629
+ }
42630
+ await this.flushPendingUiDelta();
42631
+ this.pendingUiDelta = { context, chunk: { ...chunk }, createdAt: now2() };
42632
+ this.scheduleUiDeltaFlush();
42633
+ }
42634
+ scheduleUiDeltaFlush() {
42635
+ if (this.uiDeltaFlushTimer !== null) {
42636
+ return;
42637
+ }
42638
+ this.uiDeltaFlushTimer = setTimeout(() => {
42639
+ this.uiDeltaFlushTimer = null;
42640
+ if (!this.pendingUiDelta) {
42641
+ return;
42642
+ }
42643
+ if (this.drainPromise) {
42644
+ this.scheduleUiDeltaFlush();
42645
+ return;
42646
+ }
42647
+ void this.flushPendingUiDelta().catch((error51) => {
42648
+ this.drainBlocked = true;
42649
+ this.input.runtimeLogger?.warn(
42650
+ "agent_bridge_output_buffer_flush_failed",
42651
+ {
42652
+ error: error51 instanceof Error ? error51.message : String(error51),
42653
+ pending_count: this.pendingOutputs.size
42654
+ }
42655
+ );
42656
+ });
42657
+ }, AGENT_BRIDGE_OUTPUT_DELTA_FLUSH_MS);
42658
+ }
42659
+ clearUiDeltaFlushTimer() {
42660
+ if (this.uiDeltaFlushTimer === null) {
42661
+ return;
42662
+ }
42663
+ clearTimeout(this.uiDeltaFlushTimer);
42664
+ this.uiDeltaFlushTimer = null;
42665
+ }
42666
+ async flushPendingUiDelta() {
42667
+ if (!this.pendingUiDelta) {
42668
+ return;
42669
+ }
42670
+ await this.materializePendingUiDelta();
42671
+ await this.drainPendingOutputs();
42672
+ }
42673
+ // Turns the parked coalesced chunk into a queued envelope and applies it to
42674
+ // the part tracker and message assembler, exactly as its source chunks would
42675
+ // have applied one by one (delta chunks never settle a part or complete a
42676
+ // message, so tracker/assembler side effects reduce to text accumulation).
42677
+ // Does not drain: the drain loop calls this mid-loop and keeps pulling.
42678
+ async materializePendingUiDelta() {
42679
+ const pending = this.pendingUiDelta;
42680
+ if (!pending) {
42681
+ return;
42682
+ }
42683
+ this.pendingUiDelta = null;
42684
+ this.clearUiDeltaFlushTimer();
42685
+ this.outputSeq += 1;
42686
+ this.enqueueOutput(
42687
+ buildUiMessageChunkOutputEnvelope({
42688
+ context: pending.context,
42689
+ outputSeq: this.outputSeq,
42690
+ chunk: pending.chunk,
42691
+ createdAt: pending.createdAt
42692
+ })
42693
+ );
42694
+ this.uiMessagePartTracker.append(pending.chunk);
42695
+ await this.appendUiChunkToAssembler(pending.chunk);
42696
+ }
42697
+ // ---------------------------------------------------------------------------
42603
42698
  // Delta coalescing
42604
42699
  // ---------------------------------------------------------------------------
42605
42700
  async bufferDelta(context, delta) {
@@ -42905,6 +43000,50 @@ function terminalEntryStatus(projection) {
42905
43000
  }
42906
43001
  return "completed";
42907
43002
  }
43003
+ function coalescibleUiDeltaChunk(projection) {
43004
+ if (projection.statusText !== void 0 || projection.turnStatus !== void 0 || projection.usage !== void 0 || projection.consumedCommandIds !== void 0) {
43005
+ return null;
43006
+ }
43007
+ const chunk = projection.chunk;
43008
+ switch (chunk.type) {
43009
+ case "text-delta":
43010
+ case "reasoning-delta":
43011
+ return chunk.providerMetadata === void 0 ? chunk : null;
43012
+ case "tool-input-delta":
43013
+ return chunk;
43014
+ default:
43015
+ return null;
43016
+ }
43017
+ }
43018
+ function canCoalesceUiDelta(pending, context, chunk) {
43019
+ if (pending.context.sessionId !== context.sessionId || pending.context.runtimeId !== context.runtimeId || pending.context.bridgeLeaseId !== context.bridgeLeaseId || pending.chunk.type !== chunk.type) {
43020
+ return false;
43021
+ }
43022
+ if (pending.chunk.type === "tool-input-delta" && chunk.type === "tool-input-delta") {
43023
+ return pending.chunk.toolCallId === chunk.toolCallId;
43024
+ }
43025
+ if (pending.chunk.type !== "tool-input-delta" && chunk.type !== "tool-input-delta") {
43026
+ return pending.chunk.id === chunk.id;
43027
+ }
43028
+ return false;
43029
+ }
43030
+ function mergeUiDeltaChunks(pending, chunk) {
43031
+ if (pending.type === "tool-input-delta" && chunk.type === "tool-input-delta") {
43032
+ return {
43033
+ ...pending,
43034
+ inputTextDelta: pending.inputTextDelta + chunk.inputTextDelta
43035
+ };
43036
+ }
43037
+ if (pending.type !== "tool-input-delta" && chunk.type !== "tool-input-delta") {
43038
+ return { ...pending, delta: pending.delta + chunk.delta };
43039
+ }
43040
+ throw new Error(
43041
+ `Cannot merge ui delta chunks of kinds ${pending.type} and ${chunk.type}`
43042
+ );
43043
+ }
43044
+ function uiDeltaTextLength(chunk) {
43045
+ return chunk.type === "tool-input-delta" ? chunk.inputTextDelta.length : chunk.delta.length;
43046
+ }
42908
43047
  function canCoalesceDelta(pending, context, delta) {
42909
43048
  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 === delta.delta.type;
42910
43049
  }
package/dist/index.js CHANGED
@@ -28558,7 +28558,7 @@ var init_package = __esm({
28558
28558
  "package.json"() {
28559
28559
  package_default = {
28560
28560
  name: "@autohq/cli",
28561
- version: "0.1.326",
28561
+ version: "0.1.327",
28562
28562
  license: "SEE LICENSE IN README.md",
28563
28563
  publishConfig: {
28564
28564
  access: "public"
@@ -39562,6 +39562,7 @@ function providerMetadataField(providerMetadata) {
39562
39562
 
39563
39563
  // src/commands/agent-bridge/harness/output-buffer.ts
39564
39564
  var AGENT_BRIDGE_OUTPUT_DELTA_FLUSH_MS = 50;
39565
+ var AGENT_BRIDGE_OUTPUT_UI_DELTA_MAX_CHARS = 32768;
39565
39566
  var AGENT_BRIDGE_OUTPUT_ACK_RETRY_BACKOFF_MS = [250, 1e3];
39566
39567
  var AgentBridgeOutputBuffer = class {
39567
39568
  constructor(input) {
@@ -39573,6 +39574,8 @@ var AgentBridgeOutputBuffer = class {
39573
39574
  pendingOutputs = /* @__PURE__ */ new Map();
39574
39575
  pendingDelta = null;
39575
39576
  deltaFlushTimer = null;
39577
+ pendingUiDelta = null;
39578
+ uiDeltaFlushTimer = null;
39576
39579
  activeUiMessageAssembler = null;
39577
39580
  uiMessagePartTracker = new UiMessagePartTracker();
39578
39581
  drainBlocked = false;
@@ -39582,6 +39585,12 @@ var AgentBridgeOutputBuffer = class {
39582
39585
  // ---------------------------------------------------------------------------
39583
39586
  async emitProjection(context, projection) {
39584
39587
  if (projection.type === "ui_message_chunk") {
39588
+ const coalescible = coalescibleUiDeltaChunk(projection);
39589
+ if (coalescible) {
39590
+ await this.bufferUiDeltaChunk(context, coalescible);
39591
+ return;
39592
+ }
39593
+ await this.flushPendingUiDelta();
39585
39594
  await this.emitUiMessageChunk(context, projection);
39586
39595
  return;
39587
39596
  }
@@ -39589,10 +39598,12 @@ var AgentBridgeOutputBuffer = class {
39589
39598
  await this.bufferDelta(context, projection.delta);
39590
39599
  return;
39591
39600
  }
39601
+ await this.flushPendingUiDelta();
39592
39602
  await this.flushPendingDelta();
39593
39603
  await this.enqueueProjectionAndDrain(context, projection);
39594
39604
  }
39595
39605
  async replayPendingOutputs() {
39606
+ await this.materializePendingUiDelta();
39596
39607
  await this.flushPendingDelta({ force: true });
39597
39608
  await this.drainPendingOutputs({ force: true });
39598
39609
  }
@@ -39716,10 +39727,15 @@ var AgentBridgeOutputBuffer = class {
39716
39727
  this.drainPromise ??= (async () => {
39717
39728
  while (true) {
39718
39729
  const output = this.nextPendingOutput();
39719
- if (!output) {
39720
- return;
39730
+ if (output) {
39731
+ await this.emitUntilAcked(output);
39732
+ continue;
39721
39733
  }
39722
- await this.emitUntilAcked(output);
39734
+ if (this.pendingUiDelta) {
39735
+ await this.materializePendingUiDelta();
39736
+ continue;
39737
+ }
39738
+ return;
39723
39739
  }
39724
39740
  })().catch((error51) => {
39725
39741
  this.drainBlocked = true;
@@ -39730,6 +39746,85 @@ var AgentBridgeOutputBuffer = class {
39730
39746
  await this.drainPromise;
39731
39747
  }
39732
39748
  // ---------------------------------------------------------------------------
39749
+ // UI chunk delta coalescing
39750
+ // ---------------------------------------------------------------------------
39751
+ async bufferUiDeltaChunk(context, chunk) {
39752
+ const pending = this.pendingUiDelta;
39753
+ if (pending && canCoalesceUiDelta(pending, context, chunk)) {
39754
+ pending.chunk = mergeUiDeltaChunks(pending.chunk, chunk);
39755
+ if (uiDeltaTextLength(pending.chunk) >= AGENT_BRIDGE_OUTPUT_UI_DELTA_MAX_CHARS) {
39756
+ await this.flushPendingUiDelta();
39757
+ }
39758
+ return;
39759
+ }
39760
+ await this.flushPendingUiDelta();
39761
+ this.pendingUiDelta = { context, chunk: { ...chunk }, createdAt: now2() };
39762
+ this.scheduleUiDeltaFlush();
39763
+ }
39764
+ scheduleUiDeltaFlush() {
39765
+ if (this.uiDeltaFlushTimer !== null) {
39766
+ return;
39767
+ }
39768
+ this.uiDeltaFlushTimer = setTimeout(() => {
39769
+ this.uiDeltaFlushTimer = null;
39770
+ if (!this.pendingUiDelta) {
39771
+ return;
39772
+ }
39773
+ if (this.drainPromise) {
39774
+ this.scheduleUiDeltaFlush();
39775
+ return;
39776
+ }
39777
+ void this.flushPendingUiDelta().catch((error51) => {
39778
+ this.drainBlocked = true;
39779
+ this.input.runtimeLogger?.warn(
39780
+ "agent_bridge_output_buffer_flush_failed",
39781
+ {
39782
+ error: error51 instanceof Error ? error51.message : String(error51),
39783
+ pending_count: this.pendingOutputs.size
39784
+ }
39785
+ );
39786
+ });
39787
+ }, AGENT_BRIDGE_OUTPUT_DELTA_FLUSH_MS);
39788
+ }
39789
+ clearUiDeltaFlushTimer() {
39790
+ if (this.uiDeltaFlushTimer === null) {
39791
+ return;
39792
+ }
39793
+ clearTimeout(this.uiDeltaFlushTimer);
39794
+ this.uiDeltaFlushTimer = null;
39795
+ }
39796
+ async flushPendingUiDelta() {
39797
+ if (!this.pendingUiDelta) {
39798
+ return;
39799
+ }
39800
+ await this.materializePendingUiDelta();
39801
+ await this.drainPendingOutputs();
39802
+ }
39803
+ // Turns the parked coalesced chunk into a queued envelope and applies it to
39804
+ // the part tracker and message assembler, exactly as its source chunks would
39805
+ // have applied one by one (delta chunks never settle a part or complete a
39806
+ // message, so tracker/assembler side effects reduce to text accumulation).
39807
+ // Does not drain: the drain loop calls this mid-loop and keeps pulling.
39808
+ async materializePendingUiDelta() {
39809
+ const pending = this.pendingUiDelta;
39810
+ if (!pending) {
39811
+ return;
39812
+ }
39813
+ this.pendingUiDelta = null;
39814
+ this.clearUiDeltaFlushTimer();
39815
+ this.outputSeq += 1;
39816
+ this.enqueueOutput(
39817
+ buildUiMessageChunkOutputEnvelope({
39818
+ context: pending.context,
39819
+ outputSeq: this.outputSeq,
39820
+ chunk: pending.chunk,
39821
+ createdAt: pending.createdAt
39822
+ })
39823
+ );
39824
+ this.uiMessagePartTracker.append(pending.chunk);
39825
+ await this.appendUiChunkToAssembler(pending.chunk);
39826
+ }
39827
+ // ---------------------------------------------------------------------------
39733
39828
  // Delta coalescing
39734
39829
  // ---------------------------------------------------------------------------
39735
39830
  async bufferDelta(context, delta) {
@@ -40035,6 +40130,50 @@ function terminalEntryStatus(projection) {
40035
40130
  }
40036
40131
  return "completed";
40037
40132
  }
40133
+ function coalescibleUiDeltaChunk(projection) {
40134
+ if (projection.statusText !== void 0 || projection.turnStatus !== void 0 || projection.usage !== void 0 || projection.consumedCommandIds !== void 0) {
40135
+ return null;
40136
+ }
40137
+ const chunk = projection.chunk;
40138
+ switch (chunk.type) {
40139
+ case "text-delta":
40140
+ case "reasoning-delta":
40141
+ return chunk.providerMetadata === void 0 ? chunk : null;
40142
+ case "tool-input-delta":
40143
+ return chunk;
40144
+ default:
40145
+ return null;
40146
+ }
40147
+ }
40148
+ function canCoalesceUiDelta(pending, context, chunk) {
40149
+ if (pending.context.sessionId !== context.sessionId || pending.context.runtimeId !== context.runtimeId || pending.context.bridgeLeaseId !== context.bridgeLeaseId || pending.chunk.type !== chunk.type) {
40150
+ return false;
40151
+ }
40152
+ if (pending.chunk.type === "tool-input-delta" && chunk.type === "tool-input-delta") {
40153
+ return pending.chunk.toolCallId === chunk.toolCallId;
40154
+ }
40155
+ if (pending.chunk.type !== "tool-input-delta" && chunk.type !== "tool-input-delta") {
40156
+ return pending.chunk.id === chunk.id;
40157
+ }
40158
+ return false;
40159
+ }
40160
+ function mergeUiDeltaChunks(pending, chunk) {
40161
+ if (pending.type === "tool-input-delta" && chunk.type === "tool-input-delta") {
40162
+ return {
40163
+ ...pending,
40164
+ inputTextDelta: pending.inputTextDelta + chunk.inputTextDelta
40165
+ };
40166
+ }
40167
+ if (pending.type !== "tool-input-delta" && chunk.type !== "tool-input-delta") {
40168
+ return { ...pending, delta: pending.delta + chunk.delta };
40169
+ }
40170
+ throw new Error(
40171
+ `Cannot merge ui delta chunks of kinds ${pending.type} and ${chunk.type}`
40172
+ );
40173
+ }
40174
+ function uiDeltaTextLength(chunk) {
40175
+ return chunk.type === "tool-input-delta" ? chunk.inputTextDelta.length : chunk.delta.length;
40176
+ }
40038
40177
  function canCoalesceDelta(pending, context, delta) {
40039
40178
  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 === delta.delta.type;
40040
40179
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@autohq/cli",
3
- "version": "0.1.326",
3
+ "version": "0.1.327",
4
4
  "license": "SEE LICENSE IN README.md",
5
5
  "publishConfig": {
6
6
  "access": "public"