@botbotgo/agent-harness 0.0.315 → 0.0.316

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.
@@ -1 +1 @@
1
- export declare const AGENT_HARNESS_VERSION = "0.0.314";
1
+ export declare const AGENT_HARNESS_VERSION = "0.0.315";
@@ -1 +1 @@
1
- export const AGENT_HARNESS_VERSION = "0.0.314";
1
+ export const AGENT_HARNESS_VERSION = "0.0.315";
@@ -1,3 +1,7 @@
1
+ const MAX_SNAPSHOT_OUTPUT_CHARS = 4_096;
2
+ const MAX_DATA_EVENT_INLINE_CHARS = 12_000;
3
+ const DATA_EVENT_PREVIEW_CHARS = 2_000;
4
+ const TRUNCATION_SENTINEL = "\n...[truncated]";
1
5
  function createEmptyPlanSummary() {
2
6
  return {
3
7
  total: 0,
@@ -58,6 +62,53 @@ function buildPlanItems(snapshot, planItems) {
58
62
  function buildStepEventKey(input) {
59
63
  return `${input.kind}:${input.id}`;
60
64
  }
65
+ function truncateText(value, maxChars) {
66
+ if (value.length <= maxChars) {
67
+ return value;
68
+ }
69
+ const sliceLength = Math.max(0, maxChars - TRUNCATION_SENTINEL.length);
70
+ return `${value.slice(0, sliceLength)}${TRUNCATION_SENTINEL}`;
71
+ }
72
+ function appendSnapshotOutput(current, delta) {
73
+ if (!delta || current.length >= MAX_SNAPSHOT_OUTPUT_CHARS || current.endsWith(TRUNCATION_SENTINEL)) {
74
+ return current;
75
+ }
76
+ const remaining = MAX_SNAPSHOT_OUTPUT_CHARS - current.length;
77
+ if (delta.length <= remaining) {
78
+ return current + delta;
79
+ }
80
+ return `${current}${truncateText(delta, remaining)}`;
81
+ }
82
+ function summarizeLargeDataEventOutput(output) {
83
+ if (typeof output === "string") {
84
+ if (output.length <= MAX_DATA_EVENT_INLINE_CHARS) {
85
+ return output;
86
+ }
87
+ return {
88
+ truncated: true,
89
+ originalSizeChars: output.length,
90
+ preview: truncateText(output, DATA_EVENT_PREVIEW_CHARS),
91
+ };
92
+ }
93
+ if (typeof output === "number" || typeof output === "boolean" || output === null || output === undefined) {
94
+ return output;
95
+ }
96
+ let serialized;
97
+ try {
98
+ serialized = JSON.stringify(output, null, 2);
99
+ }
100
+ catch {
101
+ serialized = String(output);
102
+ }
103
+ if (serialized.length <= MAX_DATA_EVENT_INLINE_CHARS) {
104
+ return output;
105
+ }
106
+ return {
107
+ truncated: true,
108
+ originalSizeChars: serialized.length,
109
+ preview: truncateText(serialized, DATA_EVENT_PREVIEW_CHARS),
110
+ };
111
+ }
61
112
  function applyPlanState(snapshot, planState) {
62
113
  if (!shouldReplacePlanItems(snapshot.plan.items, planState.items)) {
63
114
  return {
@@ -263,7 +314,7 @@ export function applyRequestStreamItemToSnapshot(snapshot, item) {
263
314
  requestId: item.requestId,
264
315
  updatedAt: now,
265
316
  agentId: item.agentId,
266
- output: snapshot.output + item.content,
317
+ output: appendSnapshotOutput(snapshot.output, item.content),
267
318
  };
268
319
  case "commentary":
269
320
  return {
@@ -327,7 +378,7 @@ export function applyRequestStreamItemToSnapshot(snapshot, item) {
327
378
  updatedAt: now,
328
379
  state: item.result.state,
329
380
  agentId: item.result.agentId ?? snapshot.agentId,
330
- output: item.result.output || snapshot.output,
381
+ output: item.result.output ? truncateText(item.result.output, MAX_SNAPSHOT_OUTPUT_CHARS) : snapshot.output,
331
382
  ...(item.result.contentBlocks ? { contentBlocks: item.result.contentBlocks } : {}),
332
383
  ...(item.result.structuredResponse !== undefined ? { structuredResponse: item.result.structuredResponse } : {}),
333
384
  ...(item.result.interruptContent !== undefined ? { interruptContent: item.result.interruptContent } : {}),
@@ -376,7 +427,7 @@ export function toRequestDataEvent(item) {
376
427
  requestId: item.requestId,
377
428
  agentId: item.agentId,
378
429
  toolName: item.toolName,
379
- output: item.output,
430
+ output: summarizeLargeDataEventOutput(item.output),
380
431
  ...(item.isError !== undefined ? { isError: item.isError } : {}),
381
432
  };
382
433
  case "upstream-event":
@@ -74,7 +74,12 @@ function buildStepLabel(category, status, name) {
74
74
  return status === "started" ? `Running ${displayName}` : `Completed ${displayName}`;
75
75
  }
76
76
  function createProjectionKey(parts) {
77
- return JSON.stringify(parts);
77
+ return JSON.stringify(parts, (_key, value) => {
78
+ if (typeof value === "string" && value.length > 512) {
79
+ return `${value.slice(0, 497)}...[${value.length} chars]`;
80
+ }
81
+ return value;
82
+ });
78
83
  }
79
84
  export function createUpstreamTimelineReducer() {
80
85
  const emittedStepKeys = new Set();
@@ -1,5 +1,5 @@
1
1
  import { sanitizeVisibleText } from "../parsing/output-parsing.js";
2
- import { computeIncrementalOutput, extractInterruptPayload, extractReasoningStreamOutput, extractStateStreamOutput, extractTerminalStreamOutput, extractToolResult, extractVisibleStreamOutput, normalizeTerminalOutputKey, } from "../parsing/stream-event-parsing.js";
2
+ import { computeIncrementalOutput, extractInterruptPayload, extractReasoningStreamOutput, extractStateStreamOutput, extractTerminalStreamOutput, extractToolResult, extractVisibleStreamOutput, normalizeTerminalOutputKey, sanitizeStreamPayload, } from "../parsing/stream-event-parsing.js";
3
3
  import { resolveModelFacingToolName } from "./tool/tool-name-mapping.js";
4
4
  export function createStreamEventProjectionState() {
5
5
  return {
@@ -13,7 +13,7 @@ export function projectRuntimeStreamEvent(params) {
13
13
  const { event, allowVisibleStreamDeltas, includeStateStreamOutput, toolNameMapping, primaryTools, state, } = params;
14
14
  const chunks = [{
15
15
  kind: "upstream-event",
16
- event,
16
+ event: sanitizeStreamPayload(event),
17
17
  }];
18
18
  const interruptPayload = extractInterruptPayload(event);
19
19
  if (interruptPayload) {
@@ -29,7 +29,10 @@ export function createToolResultKey(toolName, output, isError) {
29
29
  catch {
30
30
  serializedOutput = String(output);
31
31
  }
32
- return JSON.stringify([toolName, serializedOutput, isError === true]);
32
+ const preview = serializedOutput.length > 512
33
+ ? `${serializedOutput.slice(0, 497)}...[${serializedOutput.length} chars]`
34
+ : serializedOutput;
35
+ return JSON.stringify([toolName, preview, isError === true]);
33
36
  }
34
37
  export async function dispatchRequestListeners(stream, listeners, options) {
35
38
  const notifyIfPresent = async (listener, value) => {
@@ -23,6 +23,7 @@ export type RuntimeStreamChunk = {
23
23
  kind: "profile";
24
24
  step: RequestExecutionStep;
25
25
  };
26
+ export declare function sanitizeStreamPayload(value: unknown): unknown;
26
27
  export declare function extractTerminalStreamOutput(event: unknown): string;
27
28
  export declare function extractReasoningStreamOutput(event: unknown): string;
28
29
  export declare function extractVisibleStreamOutput(event: unknown): string;
@@ -1,5 +1,80 @@
1
1
  import { isLowSignalTodoContent } from "../adapter/runtime-adapter-support.js";
2
2
  import { extractReasoningText, extractVisibleOutput, hasToolCalls, readTextContent } from "./output-parsing.js";
3
+ const MAX_STREAM_INLINE_TEXT_CHARS = 12_000;
4
+ const STREAM_PREVIEW_TEXT_CHARS = 2_000;
5
+ const MAX_STREAM_OBJECT_KEYS = 64;
6
+ const MAX_STREAM_ARRAY_ITEMS = 64;
7
+ const MAX_STREAM_SANITIZE_DEPTH = 6;
8
+ function truncatePreview(value, maxChars) {
9
+ if (value.length <= maxChars) {
10
+ return value;
11
+ }
12
+ return `${value.slice(0, Math.max(0, maxChars - 15))}\n...[truncated]`;
13
+ }
14
+ function summarizeLargeText(value) {
15
+ if (value.length <= MAX_STREAM_INLINE_TEXT_CHARS) {
16
+ return value;
17
+ }
18
+ return {
19
+ truncated: true,
20
+ originalSizeChars: value.length,
21
+ preview: truncatePreview(value, STREAM_PREVIEW_TEXT_CHARS),
22
+ };
23
+ }
24
+ function sanitizeStreamPayloadValue(value, depth) {
25
+ if (typeof value === "string") {
26
+ return summarizeLargeText(value);
27
+ }
28
+ if (value === null
29
+ || value === undefined
30
+ || typeof value === "number"
31
+ || typeof value === "boolean") {
32
+ return value;
33
+ }
34
+ if (depth >= MAX_STREAM_SANITIZE_DEPTH) {
35
+ let serialized = "";
36
+ try {
37
+ serialized = JSON.stringify(value);
38
+ }
39
+ catch {
40
+ serialized = String(value);
41
+ }
42
+ return {
43
+ truncated: true,
44
+ reason: "max-depth",
45
+ originalSizeChars: serialized.length,
46
+ preview: truncatePreview(serialized, STREAM_PREVIEW_TEXT_CHARS),
47
+ };
48
+ }
49
+ if (Array.isArray(value)) {
50
+ const limited = value
51
+ .slice(0, MAX_STREAM_ARRAY_ITEMS)
52
+ .map((entry) => sanitizeStreamPayloadValue(entry, depth + 1));
53
+ return value.length > MAX_STREAM_ARRAY_ITEMS
54
+ ? {
55
+ items: limited,
56
+ truncated: true,
57
+ originalLength: value.length,
58
+ }
59
+ : limited;
60
+ }
61
+ if (typeof value === "object") {
62
+ const entries = Object.entries(value);
63
+ const limitedEntries = entries.slice(0, MAX_STREAM_OBJECT_KEYS);
64
+ const sanitized = Object.fromEntries(limitedEntries.map(([key, entry]) => [key, sanitizeStreamPayloadValue(entry, depth + 1)]));
65
+ if (entries.length > MAX_STREAM_OBJECT_KEYS) {
66
+ sanitized.__truncatedKeys = {
67
+ truncated: true,
68
+ originalKeyCount: entries.length,
69
+ };
70
+ }
71
+ return sanitized;
72
+ }
73
+ return String(value);
74
+ }
75
+ export function sanitizeStreamPayload(value) {
76
+ return sanitizeStreamPayloadValue(value, 0);
77
+ }
3
78
  function parseMaybeJson(value) {
4
79
  const trimmed = value.trim();
5
80
  if (!trimmed.startsWith("{") && !trimmed.startsWith("[")) {
@@ -146,7 +221,7 @@ export function extractToolResult(event) {
146
221
  }
147
222
  return {
148
223
  toolName,
149
- output: normalizedOutput,
224
+ output: sanitizeStreamPayload(normalizedOutput),
150
225
  isError: isToolError || isErrorLikeToolOutput(normalizedOutput),
151
226
  };
152
227
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@botbotgo/agent-harness",
3
- "version": "0.0.315",
3
+ "version": "0.0.316",
4
4
  "description": "Workspace runtime for multi-agent applications",
5
5
  "license": "MIT",
6
6
  "type": "module",