openclaw
Version:
Multi-channel AI gateway with extensible messaging integrations
115 lines (114 loc) • 5.38 kB
JavaScript
import { r as truncateUtf16Safe } from "./utf16-slice-D_ngcYKd.mjs";
import { y as redactToolDetail } from "./redact-BEIE6NCT.mjs";
import "./utils-DUAwk2p5.mjs";
import { t as formatFencedCodeBlock } from "./markdown-code-Buzx6wvi.mjs";
import { t as formatToolAggregate } from "./tool-meta-C8eh5Nql.mjs";
//#region src/agents/harness/projection-tool-output.ts
const TOOL_PROGRESS_OUTPUT_MAX_CHARS = 8e3;
const MAX_TOOL_OUTPUT_DELTA_MESSAGES_PER_ITEM = 20;
const TOOL_TRANSCRIPT_OUTPUT_MAX_CHARS = 1e4;
var NativeToolOutputAccumulator = class {
constructor(nativeToolLabel) {
this.nativeToolLabel = nativeToolLabel;
this.prefixByItem = /* @__PURE__ */ new Map();
this.originalLengthByItem = /* @__PURE__ */ new Map();
this.trimStateByItem = /* @__PURE__ */ new Map();
this.truncatedItemIds = /* @__PURE__ */ new Set();
this.textByItem = /* @__PURE__ */ new Map();
}
isTruncated(itemId) {
return this.truncatedItemIds.has(itemId);
}
append(itemId, delta) {
const originalLength = (this.originalLengthByItem.get(itemId) ?? this.textByItem.get(itemId)?.length ?? 0) + delta.length;
this.originalLengthByItem.set(itemId, originalLength);
const normalizedLength = updateToolOutputTrimState(this.trimStateByItem, itemId, delta);
const next = appendBoundedToolTranscriptText(this.prefixByItem.get(itemId) ?? this.textByItem.get(itemId) ?? "", this.truncatedItemIds.has(itemId) ? "" : delta, originalLength, this.nativeToolLabel);
this.prefixByItem.set(itemId, next.rawPrefix);
this.textByItem.set(itemId, next.text);
if (originalLength > 1e4) this.truncatedItemIds.add(itemId);
return {
text: next.text,
originalLength,
normalizedLength,
rawPrefix: next.rawPrefix
};
}
};
function truncateNativeToolTranscriptText(text, nativeToolLabel, originalLength = text.length) {
if (originalLength <= 1e4 && text.length <= 1e4) return text;
const notice = toolTranscriptTruncationNotice(originalLength, nativeToolLabel);
if (notice.length >= 1e4) return notice.slice(1, 10001);
const textBudget = TOOL_TRANSCRIPT_OUTPUT_MAX_CHARS - notice.length;
return `${truncateUtf16Safe(text, textBudget)}${notice}`;
}
function formatNativeToolSummary(toolName, meta) {
const trimmedMeta = meta?.trim();
return formatToolAggregate(toolName, trimmedMeta ? [trimmedMeta] : void 0, { markdown: true });
}
function formatNativeToolOutput(toolName, meta, output) {
const formattedOutput = formatToolProgressOutput(output);
if (!formattedOutput) return formatNativeToolSummary(toolName, meta);
return `${formatNativeToolSummary(toolName, meta)}\n${formatFencedCodeBlock(formattedOutput, "txt")}`;
}
/**
* Prepare verbose tool output for user-facing progress messages.
*/
function formatToolProgressOutput(output, options) {
const trimmed = output.replace(/\r\n/g, "\n").replace(/\r/g, "\n").trim();
if (!trimmed) return;
const redacted = redactToolDetail(trimmed);
const maxChars = options?.maxChars ?? 8e3;
if (redacted.length <= maxChars) return redacted;
return `${truncateUtf16Safe(redacted, maxChars)}\n...(truncated)...`;
}
function updateToolOutputTrimState(trimStateByItem, itemId, delta) {
const state = trimStateByItem.get(itemId) ?? {
totalLength: 0,
leadingWhitespaceLength: 0,
trailingWhitespaceLength: 0,
sawNonWhitespace: false
};
state.totalLength += delta.length;
const firstNonWhitespace = delta.search(/\S/u);
if (firstNonWhitespace === -1) {
if (!state.sawNonWhitespace) state.leadingWhitespaceLength += delta.length;
state.trailingWhitespaceLength += delta.length;
trimStateByItem.set(itemId, state);
return state.sawNonWhitespace ? state.totalLength - state.leadingWhitespaceLength - state.trailingWhitespaceLength : 0;
}
if (!state.sawNonWhitespace) {
state.leadingWhitespaceLength += firstNonWhitespace;
state.sawNonWhitespace = true;
}
state.trailingWhitespaceLength = delta.match(/\s*$/u)?.[0].length ?? 0;
trimStateByItem.set(itemId, state);
return state.totalLength - state.leadingWhitespaceLength - state.trailingWhitespaceLength;
}
function appendBoundedToolTranscriptText(currentPrefix, delta, originalLength, nativeToolLabel) {
if (originalLength <= 1e4) {
const rawPrefix = currentPrefix + delta;
return {
text: rawPrefix,
rawPrefix
};
}
const notice = toolTranscriptTruncationNotice(originalLength, nativeToolLabel);
if (notice.length >= 1e4) return {
text: notice.slice(0, TOOL_TRANSCRIPT_OUTPUT_MAX_CHARS),
rawPrefix: ""
};
const textBudget = TOOL_TRANSCRIPT_OUTPUT_MAX_CHARS - notice.length;
const remaining = Math.max(0, textBudget - currentPrefix.length);
const prefix = remaining > 0 ? `${currentPrefix}${truncateUtf16Safe(delta, remaining)}` : currentPrefix;
const rawPrefix = truncateUtf16Safe(prefix, textBudget);
return {
text: `${rawPrefix}${notice}`,
rawPrefix
};
}
function toolTranscriptTruncationNotice(originalLength, nativeToolLabel) {
return `\n${`...(OpenClaw truncated ${nativeToolLabel} native tool output: original ${originalLength} chars, showing ${TOOL_TRANSCRIPT_OUTPUT_MAX_CHARS}; rerun with narrower args.)`}`;
}
//#endregion
export { formatNativeToolOutput as a, truncateNativeToolTranscriptText as c, TOOL_TRANSCRIPT_OUTPUT_MAX_CHARS as i, NativeToolOutputAccumulator as n, formatNativeToolSummary as o, TOOL_PROGRESS_OUTPUT_MAX_CHARS as r, formatToolProgressOutput as s, MAX_TOOL_OUTPUT_DELTA_MESSAGES_PER_ITEM as t };