@autohq/cli 0.1.334 → 0.1.335

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.334",
23437
+ version: "0.1.335",
23438
23438
  license: "SEE LICENSE IN README.md",
23439
23439
  publishConfig: {
23440
23440
  access: "public"
@@ -43958,6 +43958,95 @@ var _a21;
43958
43958
  _a21 = symbol21;
43959
43959
  var defaultDownload2 = createDownload();
43960
43960
 
43961
+ // src/commands/agent-bridge/harness/envelope-bounds.ts
43962
+ import { Buffer as Buffer2 } from "buffer";
43963
+ var AGENT_BRIDGE_OUTPUT_MAX_ENVELOPE_BYTES = 512 * 1024;
43964
+ var AGENT_BRIDGE_OUTPUT_QUARANTINE_MAX_ENVELOPE_BYTES = 8 * 1024;
43965
+ var MIN_STRING_BUDGET_CHARS = 64;
43966
+ function boundOutputEnvelope(envelope, maxBytes = AGENT_BRIDGE_OUTPUT_MAX_ENVELOPE_BYTES) {
43967
+ const originalBytes = serializedByteLength(envelope);
43968
+ if (originalBytes <= maxBytes) {
43969
+ return { envelope, originalBytes, truncated: false };
43970
+ }
43971
+ for (let budget = initialStringBudget(maxBytes); budget >= MIN_STRING_BUDGET_CHARS; budget = Math.floor(budget / 8)) {
43972
+ const candidate = truncateLongStrings(envelope, budget);
43973
+ if (serializedByteLength(candidate) <= maxBytes) {
43974
+ return {
43975
+ envelope: RuntimeBridgeOutputEnvelopeSchema.parse(candidate),
43976
+ originalBytes,
43977
+ truncated: true
43978
+ };
43979
+ }
43980
+ }
43981
+ return {
43982
+ envelope: RuntimeBridgeOutputEnvelopeSchema.parse(
43983
+ replacePayloadWithMarker(envelope, originalBytes)
43984
+ ),
43985
+ originalBytes,
43986
+ truncated: true
43987
+ };
43988
+ }
43989
+ function serializedByteLength(value2) {
43990
+ return Buffer2.byteLength(JSON.stringify(value2), "utf8");
43991
+ }
43992
+ function initialStringBudget(maxBytes) {
43993
+ return Math.max(MIN_STRING_BUDGET_CHARS, Math.floor(maxBytes / 8));
43994
+ }
43995
+ function truncateLongStrings(value2, budget) {
43996
+ if (typeof value2 === "string") {
43997
+ if (value2.length <= budget) {
43998
+ return value2;
43999
+ }
44000
+ return `${value2.slice(0, budget)}${truncationMarker(value2.length - budget)}`;
44001
+ }
44002
+ if (Array.isArray(value2)) {
44003
+ return value2.map((item) => truncateLongStrings(item, budget));
44004
+ }
44005
+ if (typeof value2 === "object" && value2 !== null) {
44006
+ return Object.fromEntries(
44007
+ Object.entries(value2).map(([key, item]) => [
44008
+ key,
44009
+ truncateLongStrings(item, budget)
44010
+ ])
44011
+ );
44012
+ }
44013
+ return value2;
44014
+ }
44015
+ function truncationMarker(droppedChars) {
44016
+ return `\u2026 [agent-bridge truncated ${droppedChars} chars: output exceeded the bridge envelope size limit]`;
44017
+ }
44018
+ function replacePayloadWithMarker(envelope, originalBytes) {
44019
+ const text2 = `[agent-bridge removed a ${originalBytes}-byte payload: it exceeded the bridge envelope size limit and could not be truncated]`;
44020
+ switch (envelope.type) {
44021
+ case "conversation.entry":
44022
+ return { ...envelope, content: { parts: [{ type: "text", text: text2 }] } };
44023
+ case "conversation.delta":
44024
+ return { ...envelope, delta: { type: "text", text: text2 } };
44025
+ case "ui.message.chunk":
44026
+ return {
44027
+ ...envelope,
44028
+ chunk: {
44029
+ type: "text-delta",
44030
+ id: "agent-bridge-truncation",
44031
+ delta: text2
44032
+ }
44033
+ };
44034
+ case "ui.message.part": {
44035
+ const { messageMetadata: _dropped, ...rest } = envelope;
44036
+ return { ...rest, part: { type: "text", text: text2, state: "done" } };
44037
+ }
44038
+ case "ui.message.completed":
44039
+ return {
44040
+ ...envelope,
44041
+ message: {
44042
+ id: envelope.messageId,
44043
+ role: envelope.role,
44044
+ parts: [{ type: "text", text: text2, state: "done" }]
44045
+ }
44046
+ };
44047
+ }
44048
+ }
44049
+
43961
44050
  // src/commands/agent-bridge/harness/ui-message-part-tracker.ts
43962
44051
  var UiMessagePartTracker = class {
43963
44052
  messageId = null;
@@ -44298,6 +44387,7 @@ function providerMetadataField(providerMetadata) {
44298
44387
  var AGENT_BRIDGE_OUTPUT_DELTA_FLUSH_MS = 50;
44299
44388
  var AGENT_BRIDGE_OUTPUT_UI_DELTA_MAX_CHARS = 32768;
44300
44389
  var AGENT_BRIDGE_OUTPUT_ACK_RETRY_BACKOFF_MS = [250, 1e3];
44390
+ var AGENT_BRIDGE_OUTPUT_QUARANTINE_AFTER_EXHAUSTS = 3;
44301
44391
  var AgentBridgeOutputBuffer = class {
44302
44392
  constructor(input) {
44303
44393
  this.input = input;
@@ -44314,6 +44404,9 @@ var AgentBridgeOutputBuffer = class {
44314
44404
  uiMessagePartTracker = new UiMessagePartTracker();
44315
44405
  drainBlocked = false;
44316
44406
  drainPromise = null;
44407
+ // Ack-retry-ladder exhausts per pending output sequence, for the poison
44408
+ // quarantine; entries clear when the sequence finally acks.
44409
+ ackExhaustsBySeq = /* @__PURE__ */ new Map();
44317
44410
  // ---------------------------------------------------------------------------
44318
44411
  // Public API
44319
44412
  // ---------------------------------------------------------------------------
@@ -44615,6 +44708,7 @@ var AgentBridgeOutputBuffer = class {
44615
44708
  for (let attempt = 0; ; attempt += 1) {
44616
44709
  try {
44617
44710
  await this.emitOnce(output);
44711
+ this.ackExhaustsBySeq.delete(output.outputSeq);
44618
44712
  return;
44619
44713
  } catch (error51) {
44620
44714
  if (!(error51 instanceof AgentBridgeOutputAckTimeoutError)) {
@@ -44630,6 +44724,7 @@ var AgentBridgeOutputBuffer = class {
44630
44724
  pending_count: this.pendingOutputs.size
44631
44725
  })
44632
44726
  );
44727
+ this.quarantineAfterRepeatedExhausts(output);
44633
44728
  this.input.cycleSocket?.();
44634
44729
  throw error51;
44635
44730
  }
@@ -44692,10 +44787,46 @@ var AgentBridgeOutputBuffer = class {
44692
44787
  await this.drainPendingOutputs();
44693
44788
  }
44694
44789
  enqueueOutput(output) {
44695
- this.pendingOutputs.set(output.outputSeq, output);
44790
+ const bounded = boundOutputEnvelope(output);
44791
+ if (bounded.truncated) {
44792
+ this.input.runtimeLogger?.warn(
44793
+ "agent_bridge_output_envelope_truncated",
44794
+ this.outputLogContext(bounded.envelope, {
44795
+ original_bytes: bounded.originalBytes,
44796
+ pending_count: this.pendingOutputs.size
44797
+ })
44798
+ );
44799
+ }
44800
+ this.pendingOutputs.set(bounded.envelope.outputSeq, bounded.envelope);
44696
44801
  this.input.runtimeLogger?.info(
44697
44802
  "agent_bridge_output_buffer_enqueued",
44698
- this.outputLogContext(output, {
44803
+ this.outputLogContext(bounded.envelope, {
44804
+ pending_count: this.pendingOutputs.size
44805
+ })
44806
+ );
44807
+ }
44808
+ // Shrinks a pending envelope to the quarantine size once it has exhausted
44809
+ // the ack-retry ladder AGENT_BRIDGE_OUTPUT_QUARANTINE_AFTER_EXHAUSTS times.
44810
+ // The shrunk envelope keeps its sequence and turn lifecycle fields, so the
44811
+ // drain resumes and the turn still settles; only bulky content is cut.
44812
+ quarantineAfterRepeatedExhausts(output) {
44813
+ const exhausts = (this.ackExhaustsBySeq.get(output.outputSeq) ?? 0) + 1;
44814
+ this.ackExhaustsBySeq.set(output.outputSeq, exhausts);
44815
+ if (exhausts < AGENT_BRIDGE_OUTPUT_QUARANTINE_AFTER_EXHAUSTS) {
44816
+ return;
44817
+ }
44818
+ const bounded = boundOutputEnvelope(
44819
+ output,
44820
+ AGENT_BRIDGE_OUTPUT_QUARANTINE_MAX_ENVELOPE_BYTES
44821
+ );
44822
+ this.pendingOutputs.set(bounded.envelope.outputSeq, bounded.envelope);
44823
+ this.ackExhaustsBySeq.delete(output.outputSeq);
44824
+ this.input.runtimeLogger?.error(
44825
+ "agent_bridge_output_envelope_quarantined",
44826
+ this.outputLogContext(bounded.envelope, {
44827
+ exhausts,
44828
+ original_bytes: bounded.originalBytes,
44829
+ truncated: bounded.truncated,
44699
44830
  pending_count: this.pendingOutputs.size
44700
44831
  })
44701
44832
  );
package/dist/index.js CHANGED
@@ -30435,7 +30435,7 @@ var init_package = __esm({
30435
30435
  "package.json"() {
30436
30436
  package_default = {
30437
30437
  name: "@autohq/cli",
30438
- version: "0.1.334",
30438
+ version: "0.1.335",
30439
30439
  license: "SEE LICENSE IN README.md",
30440
30440
  publishConfig: {
30441
30441
  access: "public"
@@ -41171,6 +41171,95 @@ import { setTimeout as sleep2 } from "timers/promises";
41171
41171
  init_src();
41172
41172
  import { readUIMessageStream } from "ai";
41173
41173
 
41174
+ // src/commands/agent-bridge/harness/envelope-bounds.ts
41175
+ import { Buffer as Buffer2 } from "buffer";
41176
+ var AGENT_BRIDGE_OUTPUT_MAX_ENVELOPE_BYTES = 512 * 1024;
41177
+ var AGENT_BRIDGE_OUTPUT_QUARANTINE_MAX_ENVELOPE_BYTES = 8 * 1024;
41178
+ var MIN_STRING_BUDGET_CHARS = 64;
41179
+ function boundOutputEnvelope(envelope, maxBytes = AGENT_BRIDGE_OUTPUT_MAX_ENVELOPE_BYTES) {
41180
+ const originalBytes = serializedByteLength(envelope);
41181
+ if (originalBytes <= maxBytes) {
41182
+ return { envelope, originalBytes, truncated: false };
41183
+ }
41184
+ for (let budget = initialStringBudget(maxBytes); budget >= MIN_STRING_BUDGET_CHARS; budget = Math.floor(budget / 8)) {
41185
+ const candidate = truncateLongStrings(envelope, budget);
41186
+ if (serializedByteLength(candidate) <= maxBytes) {
41187
+ return {
41188
+ envelope: RuntimeBridgeOutputEnvelopeSchema.parse(candidate),
41189
+ originalBytes,
41190
+ truncated: true
41191
+ };
41192
+ }
41193
+ }
41194
+ return {
41195
+ envelope: RuntimeBridgeOutputEnvelopeSchema.parse(
41196
+ replacePayloadWithMarker(envelope, originalBytes)
41197
+ ),
41198
+ originalBytes,
41199
+ truncated: true
41200
+ };
41201
+ }
41202
+ function serializedByteLength(value) {
41203
+ return Buffer2.byteLength(JSON.stringify(value), "utf8");
41204
+ }
41205
+ function initialStringBudget(maxBytes) {
41206
+ return Math.max(MIN_STRING_BUDGET_CHARS, Math.floor(maxBytes / 8));
41207
+ }
41208
+ function truncateLongStrings(value, budget) {
41209
+ if (typeof value === "string") {
41210
+ if (value.length <= budget) {
41211
+ return value;
41212
+ }
41213
+ return `${value.slice(0, budget)}${truncationMarker(value.length - budget)}`;
41214
+ }
41215
+ if (Array.isArray(value)) {
41216
+ return value.map((item) => truncateLongStrings(item, budget));
41217
+ }
41218
+ if (typeof value === "object" && value !== null) {
41219
+ return Object.fromEntries(
41220
+ Object.entries(value).map(([key, item]) => [
41221
+ key,
41222
+ truncateLongStrings(item, budget)
41223
+ ])
41224
+ );
41225
+ }
41226
+ return value;
41227
+ }
41228
+ function truncationMarker(droppedChars) {
41229
+ return `\u2026 [agent-bridge truncated ${droppedChars} chars: output exceeded the bridge envelope size limit]`;
41230
+ }
41231
+ function replacePayloadWithMarker(envelope, originalBytes) {
41232
+ const text = `[agent-bridge removed a ${originalBytes}-byte payload: it exceeded the bridge envelope size limit and could not be truncated]`;
41233
+ switch (envelope.type) {
41234
+ case "conversation.entry":
41235
+ return { ...envelope, content: { parts: [{ type: "text", text }] } };
41236
+ case "conversation.delta":
41237
+ return { ...envelope, delta: { type: "text", text } };
41238
+ case "ui.message.chunk":
41239
+ return {
41240
+ ...envelope,
41241
+ chunk: {
41242
+ type: "text-delta",
41243
+ id: "agent-bridge-truncation",
41244
+ delta: text
41245
+ }
41246
+ };
41247
+ case "ui.message.part": {
41248
+ const { messageMetadata: _dropped, ...rest } = envelope;
41249
+ return { ...rest, part: { type: "text", text, state: "done" } };
41250
+ }
41251
+ case "ui.message.completed":
41252
+ return {
41253
+ ...envelope,
41254
+ message: {
41255
+ id: envelope.messageId,
41256
+ role: envelope.role,
41257
+ parts: [{ type: "text", text, state: "done" }]
41258
+ }
41259
+ };
41260
+ }
41261
+ }
41262
+
41174
41263
  // src/commands/agent-bridge/harness/ui-message-part-tracker.ts
41175
41264
  init_src();
41176
41265
  var UiMessagePartTracker = class {
@@ -41512,6 +41601,7 @@ function providerMetadataField(providerMetadata) {
41512
41601
  var AGENT_BRIDGE_OUTPUT_DELTA_FLUSH_MS = 50;
41513
41602
  var AGENT_BRIDGE_OUTPUT_UI_DELTA_MAX_CHARS = 32768;
41514
41603
  var AGENT_BRIDGE_OUTPUT_ACK_RETRY_BACKOFF_MS = [250, 1e3];
41604
+ var AGENT_BRIDGE_OUTPUT_QUARANTINE_AFTER_EXHAUSTS = 3;
41515
41605
  var AgentBridgeOutputBuffer = class {
41516
41606
  constructor(input) {
41517
41607
  this.input = input;
@@ -41528,6 +41618,9 @@ var AgentBridgeOutputBuffer = class {
41528
41618
  uiMessagePartTracker = new UiMessagePartTracker();
41529
41619
  drainBlocked = false;
41530
41620
  drainPromise = null;
41621
+ // Ack-retry-ladder exhausts per pending output sequence, for the poison
41622
+ // quarantine; entries clear when the sequence finally acks.
41623
+ ackExhaustsBySeq = /* @__PURE__ */ new Map();
41531
41624
  // ---------------------------------------------------------------------------
41532
41625
  // Public API
41533
41626
  // ---------------------------------------------------------------------------
@@ -41829,6 +41922,7 @@ var AgentBridgeOutputBuffer = class {
41829
41922
  for (let attempt = 0; ; attempt += 1) {
41830
41923
  try {
41831
41924
  await this.emitOnce(output);
41925
+ this.ackExhaustsBySeq.delete(output.outputSeq);
41832
41926
  return;
41833
41927
  } catch (error51) {
41834
41928
  if (!(error51 instanceof AgentBridgeOutputAckTimeoutError)) {
@@ -41844,6 +41938,7 @@ var AgentBridgeOutputBuffer = class {
41844
41938
  pending_count: this.pendingOutputs.size
41845
41939
  })
41846
41940
  );
41941
+ this.quarantineAfterRepeatedExhausts(output);
41847
41942
  this.input.cycleSocket?.();
41848
41943
  throw error51;
41849
41944
  }
@@ -41906,10 +42001,46 @@ var AgentBridgeOutputBuffer = class {
41906
42001
  await this.drainPendingOutputs();
41907
42002
  }
41908
42003
  enqueueOutput(output) {
41909
- this.pendingOutputs.set(output.outputSeq, output);
42004
+ const bounded = boundOutputEnvelope(output);
42005
+ if (bounded.truncated) {
42006
+ this.input.runtimeLogger?.warn(
42007
+ "agent_bridge_output_envelope_truncated",
42008
+ this.outputLogContext(bounded.envelope, {
42009
+ original_bytes: bounded.originalBytes,
42010
+ pending_count: this.pendingOutputs.size
42011
+ })
42012
+ );
42013
+ }
42014
+ this.pendingOutputs.set(bounded.envelope.outputSeq, bounded.envelope);
41910
42015
  this.input.runtimeLogger?.info(
41911
42016
  "agent_bridge_output_buffer_enqueued",
41912
- this.outputLogContext(output, {
42017
+ this.outputLogContext(bounded.envelope, {
42018
+ pending_count: this.pendingOutputs.size
42019
+ })
42020
+ );
42021
+ }
42022
+ // Shrinks a pending envelope to the quarantine size once it has exhausted
42023
+ // the ack-retry ladder AGENT_BRIDGE_OUTPUT_QUARANTINE_AFTER_EXHAUSTS times.
42024
+ // The shrunk envelope keeps its sequence and turn lifecycle fields, so the
42025
+ // drain resumes and the turn still settles; only bulky content is cut.
42026
+ quarantineAfterRepeatedExhausts(output) {
42027
+ const exhausts = (this.ackExhaustsBySeq.get(output.outputSeq) ?? 0) + 1;
42028
+ this.ackExhaustsBySeq.set(output.outputSeq, exhausts);
42029
+ if (exhausts < AGENT_BRIDGE_OUTPUT_QUARANTINE_AFTER_EXHAUSTS) {
42030
+ return;
42031
+ }
42032
+ const bounded = boundOutputEnvelope(
42033
+ output,
42034
+ AGENT_BRIDGE_OUTPUT_QUARANTINE_MAX_ENVELOPE_BYTES
42035
+ );
42036
+ this.pendingOutputs.set(bounded.envelope.outputSeq, bounded.envelope);
42037
+ this.ackExhaustsBySeq.delete(output.outputSeq);
42038
+ this.input.runtimeLogger?.error(
42039
+ "agent_bridge_output_envelope_quarantined",
42040
+ this.outputLogContext(bounded.envelope, {
42041
+ exhausts,
42042
+ original_bytes: bounded.originalBytes,
42043
+ truncated: bounded.truncated,
41913
42044
  pending_count: this.pendingOutputs.size
41914
42045
  })
41915
42046
  );
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@autohq/cli",
3
- "version": "0.1.334",
3
+ "version": "0.1.335",
4
4
  "license": "SEE LICENSE IN README.md",
5
5
  "publishConfig": {
6
6
  "access": "public"