openclaw
Version:
Multi-channel AI gateway with extensible messaging integrations
225 lines (224 loc) • 8.36 kB
JavaScript
import { t as truncateUtf8Prefix } from "./utf8-truncate-CCgJrv8A.js";
import { r as jsonUtf8Bytes } from "./json-utf8-bytes-fm9i4b7G.js";
import { s as toolResultFitsBudget } from "./tool-result-limits-CFk9DkYv.js";
import { t as renderToolSearchControlText } from "./tool-search-control-result-Dr6yxXnu.js";
//#region src/agents/code-mode-json.ts
function toCodeModeJsonSafe(value) {
if (value === void 0) return null;
if (value === null || typeof value === "string" || typeof value === "boolean") return value;
try {
const serialized = JSON.stringify(value);
return serialized === void 0 ? null : JSON.parse(serialized);
} catch {
if (value instanceof Error) return {
name: value.name,
message: value.message
};
switch (typeof value) {
case "number": return value;
case "bigint":
case "symbol":
case "function": return String(value);
default: return Object.prototype.toString.call(value);
}
}
}
const EMPTY_CODE_MODE_OUTPUT = {
count: 0,
source: {
kind: "complete",
json: "[]"
}
};
function sourceBytes(source) {
return source.kind === "prefix" ? source.originalBytes : Buffer.byteLength(source.json, "utf8");
}
function retainSource(json, originalBytes, maxBytes) {
return originalBytes <= maxBytes ? {
kind: "complete",
json
} : {
kind: "prefix",
json: truncateUtf8Prefix(json, maxBytes),
originalBytes
};
}
/** Capture after guest conversion, before any public projection discards source facts. */
function captureCodeModeValue(value, maxBytes) {
const json = JSON.stringify(toCodeModeJsonSafe(value)) ?? "null";
return retainSource(json, Buffer.byteLength(json, "utf8"), maxBytes);
}
function captureCodeModeOutput(output, maxBytes) {
if (output.length === 0) return EMPTY_CODE_MODE_OUTPUT;
const json = JSON.stringify(output.map(toCodeModeJsonSafe));
return {
count: output.length,
source: retainSource(json, Buffer.byteLength(json, "utf8"), maxBytes)
};
}
const TRUNCATION_GUIDANCE = "Output truncated; rerun with narrower args.";
function createJsonPrefixFitter(text, maxBytes, overhead) {
const bytes = Buffer.byteLength(text, "utf8");
let encoded;
let completeBytes;
return (limit) => {
if (limit <= 0) return "";
if (bytes <= limit && (completeBytes ??= jsonUtf8Bytes(text)) + overhead(bytes) <= limit) return text;
encoded ??= Buffer.from(text.slice(0, Math.ceil(Math.min(bytes, maxBytes))));
let end = 0;
let jsonBytes = 2;
while (end < encoded.byteLength) {
const byte = encoded[end];
const width = byte < 128 ? 1 : byte < 224 ? 2 : byte < 240 ? 3 : 4;
const next = end + width;
if (next >= bytes || next > limit) break;
jsonBytes += byte === 34 || byte === 92 || byte === 8 || byte === 9 || byte === 10 || byte === 12 || byte === 13 ? 2 : byte < 32 ? 6 : width;
if (jsonBytes + overhead(next) > limit) break;
end = next;
}
return encoded.subarray(0, end).toString("utf8");
};
}
function createTruncationMarker(source, maxBytes) {
const originalBytes = sourceBytes(source);
const marker = {
truncated: true,
omittedBytes: originalBytes,
guidance: TRUNCATION_GUIDANCE,
prefix: ""
};
const fixedBytes = jsonUtf8Bytes(marker) - 2 - String(originalBytes).length;
const fit = createJsonPrefixFitter(source.json, maxBytes, (prefixBytes) => fixedBytes + String(originalBytes - prefixBytes).length);
return (limit) => {
const prefix = fit(limit);
return {
...marker,
omittedBytes: originalBytes - Buffer.byteLength(prefix, "utf8"),
prefix
};
};
}
/** Nested bridge markers are ordinary guest data when later emitted or returned. */
function boundCodeModeValue(value, maxBytes) {
const source = captureCodeModeValue(value, maxBytes);
return source.kind === "complete" && sourceBytes(source) <= maxBytes ? JSON.parse(source.json) : createTruncationMarker(source, maxBytes)(maxBytes);
}
function createErrorFitter(error, maxBytes) {
const suffix = " [error truncated]";
const fit = createJsonPrefixFitter(error, maxBytes, () => 18);
return (limit) => `${fit(limit)}${suffix}`;
}
function boundCodeModeError(error, maxBytes) {
return jsonUtf8Bytes(error) <= maxBytes ? error : createErrorFitter(error, maxBytes)(maxBytes);
}
/** One bounded cumulative source and delivery receipt, shared across every worker leg. */
var CodeModeOutputState = class {
constructor(maxBytes, modelBudget) {
this.maxBytes = maxBytes;
this.modelBudget = modelBudget;
this.source = EMPTY_CODE_MODE_OUTPUT;
this.delivered = {
kind: "entries",
count: 0
};
}
append(leg) {
if (leg.count === 0) return;
if (this.source.count === 0) {
this.source = leg;
return;
}
const previous = this.source.source;
const originalBytes = sourceBytes(previous) + sourceBytes(leg.source) - 1;
const json = previous.kind === "prefix" ? previous.json : previous.json.slice(0, -1) + "," + leg.source.json.slice(1);
this.source = {
count: this.source.count + leg.count,
source: retainSource(json, originalBytes, this.maxBytes)
};
}
take(params = {}) {
return this.takeResult({}, params);
}
takeResult(metadata, params = {}, networkContent = false) {
const project = this.createProjector(params);
const fits = (candidate) => {
const rendered = renderToolSearchControlText(JSON.stringify({
...metadata,
...candidate.channels
}, null, 2), networkContent);
return !rendered.truncated && toolResultFitsBudget(rendered.text, this.modelBudget);
};
let projection = project(this.maxBytes);
if ((this.modelBudget || networkContent) && !fits(projection)) {
let low = 0;
let high = this.maxBytes - 1;
let best;
while (low <= high) {
const middle = Math.floor((low + high) / 2);
const candidate = project(middle);
if (fits(candidate)) {
best = candidate;
low = middle + 1;
} else high = middle - 1;
}
if (!best) throw new Error("Model tool-result budget cannot fit Code Mode status; use a larger model context.");
projection = best;
}
const prior = this.delivered;
const { channels, receipt } = projection;
this.delivered = receipt;
const output = receipt.kind === "entries" ? channels.output.slice(prior.kind === "entries" ? prior.count : 0) : prior.kind === "summary" && prior.originalBytes === receipt.originalBytes && prior.prefixBytes === receipt.prefixBytes ? [] : channels.output;
return {
...metadata,
...channels,
output
};
}
createProjector(params) {
const { count, source } = this.source;
const { value, error: fullError } = params;
const outputBytes = count === 0 ? 0 : sourceBytes(source);
const valueBytes = value === void 0 ? 0 : sourceBytes(value);
const errorBytes = fullError === void 0 ? 0 : jsonUtf8Bytes(fullError);
let outputMarker;
let valueMarker;
let errorFitter;
return (maxBytes) => {
const errorAllowance = maxBytes - Math.min(outputBytes + valueBytes, Math.floor(maxBytes / 2));
const error = fullError === void 0 || errorBytes <= errorAllowance ? fullError : (errorFitter ??= createErrorFitter(fullError, this.maxBytes))(errorAllowance);
const remaining = maxBytes - (error === void 0 ? 0 : jsonUtf8Bytes(error));
const outputAllowance = remaining - Math.min(valueBytes, Math.floor(remaining / 2));
let output;
let chargedOutputBytes;
let receipt;
if (outputBytes <= outputAllowance) {
output = JSON.parse(source.json);
chargedOutputBytes = outputBytes;
receipt = {
kind: "entries",
count
};
} else {
const marker = (outputMarker ??= createTruncationMarker(source, this.maxBytes))(outputAllowance - 2);
const prefixBytes = Buffer.byteLength(marker.prefix, "utf8");
output = [marker];
chargedOutputBytes = jsonUtf8Bytes([marker]);
receipt = {
kind: "summary",
originalBytes: outputBytes,
prefixBytes
};
}
return {
receipt,
channels: {
output,
...value === void 0 ? {} : { value: value.kind === "complete" && valueBytes <= remaining - chargedOutputBytes ? JSON.parse(value.json) : (valueMarker ??= createTruncationMarker(value, this.maxBytes))(remaining - chargedOutputBytes) },
...error === void 0 ? {} : { error }
}
};
};
}
};
//#endregion
export { captureCodeModeOutput as a, boundCodeModeValue as i, EMPTY_CODE_MODE_OUTPUT as n, captureCodeModeValue as o, boundCodeModeError as r, toCodeModeJsonSafe as s, CodeModeOutputState as t };