openclaw
Version:
Multi-channel AI gateway with extensible messaging integrations
510 lines (509 loc) • 18.5 kB
JavaScript
import { c as isRecord } from "./record-coerce-TIsquoVR.mjs";
import { t as truncateUtf8Prefix } from "./utf8-truncate-_hf7tp13.mjs";
import { r as jsonUtf8Bytes } from "./json-utf8-bytes-fm9i4b7G.mjs";
import { s as toolResultFitsBudget } from "./tool-result-limits-B-fhY8wF.mjs";
import { a as wrapExternalContent, i as truncateSanitizedExternalContent } from "./external-content-CmQTCbqd.mjs";
//#region src/agents/code-mode-json-fit.ts
function createJsonPrefixFitter(text, maxBytes, overhead) {
const bytes = Buffer.byteLength(text, "utf8");
let encoded;
let completeBytes;
const checkpoints = [];
let nextCheckpoint = 256;
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;
let low = 0;
let high = checkpoints.length - 1;
while (low <= high) {
const middle = low + high >>> 1;
const checkpoint = checkpoints[middle];
if (checkpoint.end <= limit && checkpoint.jsonBytes + overhead(checkpoint.end) <= limit) {
end = checkpoint.end;
jsonBytes = checkpoint.jsonBytes;
low = middle + 1;
} else high = middle - 1;
}
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;
if (end >= nextCheckpoint) {
checkpoints.push({
end,
jsonBytes
});
nextCheckpoint = end + 256;
}
}
return encoded.subarray(0, end).toString("utf8");
};
}
//#endregion
//#region src/agents/code-mode-result-preview.ts
const MAX_REFERENCE_BYTES = 768;
const MAX_VISITS = 128;
const MAX_DEPTH = 5;
const MAX_KEYS = 16;
const MAX_ARRAYS = 8;
function sampleIndices(length) {
return length ? [.../* @__PURE__ */ new Set([
0,
Math.floor(length / 2),
length - 1
])] : [];
}
function kind(value) {
return value === null ? "null" : Array.isArray(value) ? "array" : typeof value;
}
function previewText(value, maxBytes) {
const prefix = truncateUtf8Prefix(value, maxBytes);
return prefix === value ? value : `${prefix}…`;
}
function sampleShape(value) {
if (!isRecord(value)) return kind(value);
const fields = [];
for (const key in value) {
if (!Object.hasOwn(value, key)) continue;
fields.push(`${JSON.stringify(previewText(key, 40))}:${kind(value[key])}`);
if (fields.length === 6) break;
}
return `{${fields.join(",")}}`;
}
function sampledValue(value, depth = 0) {
if (typeof value === "string") return previewText(value, 48);
if (!isRecord(value) && !Array.isArray(value)) return value;
if (depth >= 2) return Array.isArray(value) ? `[array: ${value.length} items]` : "[object]";
if (Array.isArray(value)) return value.slice(0, 2).map((item) => sampledValue(item, depth + 1));
const sample = Object.create(null);
let keys = 0;
for (const key in value) if (Object.hasOwn(value, key)) {
sample[previewText(key, 40)] = sampledValue(value[key], depth + 1);
if (++keys === 6) break;
}
return sample;
}
function envelopeFields(value) {
if (!isRecord(value)) return;
const candidates = [];
let examined = 0;
for (const key in value) {
if (!Object.hasOwn(value, key)) continue;
if (++examined > MAX_KEYS) break;
const item = value[key];
if ((item === null || typeof item !== "object") && (typeof item !== "string" || item.length <= 48)) candidates.push([previewText(key, 40), item]);
}
candidates.sort((a, b) => Number(typeof a[1] === "string") - Number(typeof b[1] === "string"));
const fields = Object.create(null);
let kept = 0;
for (const [key, item] of candidates) {
fields[key] = item;
if (jsonUtf8Bytes(fields) > 96) delete fields[key];
else if (++kept === 4) break;
}
return kept ? fields : void 0;
}
function inspectArrays(value) {
const queue = [{
value,
path: "$",
depth: 0
}];
const arrays = [];
let limited = false;
for (const entry of queue) {
if (!isRecord(entry.value) && !Array.isArray(entry.value)) continue;
if (Array.isArray(entry.value)) {
arrays.push({
path: entry.path,
value: entry.value
});
arrays.sort((a, b) => b.value.length - a.value.length || (a.path < b.path ? -1 : a.path > b.path ? 1 : 0));
if (arrays.length > MAX_ARRAYS) {
arrays.pop();
limited = true;
}
}
if (entry.depth === MAX_DEPTH) {
limited = true;
continue;
}
const enqueue = (child, path) => {
if (queue.length >= MAX_VISITS || Buffer.byteLength(path) > 192) limited = true;
else queue.push({
value: child,
path,
depth: entry.depth + 1
});
};
if (Array.isArray(entry.value)) {
const indices = sampleIndices(entry.value.length);
limited ||= indices.length < entry.value.length;
for (const childIndex of indices) enqueue(entry.value[childIndex], `${entry.path}[${childIndex}]`);
continue;
}
let keys = 0;
for (const key in entry.value) {
if (!Object.hasOwn(entry.value, key)) continue;
if (++keys > MAX_KEYS) {
limited = true;
break;
}
if (key.length > 192) {
limited = true;
continue;
}
const segment = /^[A-Za-z_$][A-Za-z0-9_$]*$/u.test(key) ? `.${key}` : `[${JSON.stringify(key)}]`;
enqueue(entry.value[key], entry.path + segment);
}
}
return {
arrays,
limited
};
}
/** Keep the usable identity intact; only descriptive samples may shrink. */
function fitCodeModeResultReference(reference, maxBytes) {
if (jsonUtf8Bytes(reference) <= maxBytes) return reference;
const minimal = {
...reference,
shape: "",
preview: "",
previewTruncated: true
};
const remaining = maxBytes - jsonUtf8Bytes(minimal);
if (remaining < 0) return;
const shapeBytes = 2 + Math.floor(remaining / 3);
const shape = createJsonPrefixFitter(reference.shape, shapeBytes, () => 0)(shapeBytes);
const previewBytes = 2 + remaining - (jsonUtf8Bytes(shape) - 2);
const preview = createJsonPrefixFitter(reference.preview, previewBytes, () => 0)(previewBytes);
return {
...minimal,
shape,
preview
};
}
function createCodeModeResultReference(id, json, value) {
const { arrays, limited } = inspectArrays(value);
const samples = arrays.map(({ path, value: items }) => {
const indices = sampleIndices(items.length);
const shapes = [...new Set(indices.map((index) => sampleShape(items[index])))];
return {
path,
count: items.length,
observed: `sampled ${indices.length}/${items.length}${shapes.length > 1 ? " heterogeneous" : ""}: ${shapes.join(" | ")}`,
items: indices.map((index) => ({
index,
value: sampledValue(items[index])
}))
};
});
const bytes = Buffer.byteLength(json, "utf8");
const fitted = fitCodeModeResultReference({
id,
bytes,
count: Array.isArray(value) ? value.length : value !== null && typeof value === "object" ? Object.keys(value).length : 1,
shape: `${limited ? "limited traversal; " : ""}${samples.length ? samples.map((sample) => `${sample.path}: ${sample.count} items, ${sample.observed}`).join("; ") : sampleShape(value)}`,
preview: bytes <= 256 ? json : JSON.stringify(samples.length ? {
sampled: true,
traversalLimited: limited,
fields: envelopeFields(value),
arrays: samples.map(({ observed: _observed, ...sample }) => sample)
} : {
sampled: true,
traversalLimited: limited,
value: sampledValue(value)
}),
previewTruncated: bytes > 256
}, MAX_REFERENCE_BYTES);
if (!fitted) throw new Error("Code Mode reference identity exceeds its descriptor allowance.");
return fitted;
}
//#endregion
//#region src/agents/tool-search-control-result.ts
/** Shared by budget fitting and delivery so formatting cannot consume unreserved context. */
function serializeToolSearchControlResult(payload, compact = false) {
return JSON.stringify(payload, null, compact ? void 0 : 2);
}
/** Shared by the source projector and final formatter; no terminal receipts are consumed here. */
function renderToolSearchControlText(text, networkContent) {
if (!networkContent) return {
text,
truncated: false
};
const bounded = text.length <= 2e4 ? truncateSanitizedExternalContent(text, 2e4) : void 0;
const truncated = bounded?.truncated ?? true;
const modelText = !bounded || bounded.truncated ? `${truncateSanitizedExternalContent(text, 19988).text}\n[truncated]` : bounded.text;
return {
text: wrapExternalContent(modelText, { source: "api" }),
truncated
};
}
//#endregion
//#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;
return JSON.parse(stringifyCodeModeJsonSafe(value));
}
/** Serialize once before checking a data allowance; detachment can happen after admission. */
function stringifyCodeModeJsonSafe(value) {
try {
return JSON.stringify(value) ?? "null";
} catch {
if (value instanceof Error) return JSON.stringify({
name: value.name,
message: value.message
});
switch (typeof value) {
case "number": return JSON.stringify(value);
case "bigint":
case "symbol":
case "function": return JSON.stringify(String(value));
default: return JSON.stringify(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, structuredMaxBytes = maxBytes) {
const json = stringifyCodeModeJsonSafe(value);
const allowance = json.startsWith("{") || json.startsWith("[") ? Math.max(maxBytes, structuredMaxBytes) : maxBytes;
return retainSource(json, Buffer.byteLength(json, "utf8"), allowance);
}
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.";
const RETAINED_GUIDANCE = "Full result saved for this run; use results.load(reference.id) in a later exec.";
function retainedMarker(reference, maxBytes) {
const fitted = fitCodeModeResultReference(reference, maxBytes - (jsonUtf8Bytes({
truncated: true,
reference: null,
guidance: RETAINED_GUIDANCE
}) - 4));
return fitted ? {
truncated: true,
reference: fitted,
guidance: RETAINED_GUIDANCE
} : void 0;
}
function createTruncationMarker(source, maxBytes, guidance = TRUNCATION_GUIDANCE) {
const originalBytes = sourceBytes(source);
const marker = {
truncated: true,
omittedBytes: originalBytes,
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
};
};
}
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, retainValue) {
const fit = (channels) => {
const project = this.createProjector(channels);
const fits = (candidate) => {
const rendered = renderToolSearchControlText(serializeToolSearchControlResult({
...metadata,
...candidate.channels
}, true), networkContent);
return !rendered.truncated && toolResultFitsBudget(rendered.text, this.modelBudget);
};
const 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;
}
return best;
}
return projection;
};
const original = fit(params);
if (!original) throw new Error("Model tool-result budget cannot fit Code Mode status; use a larger model context.");
let projection = original;
const fitNonRetention = (guidance) => fit({
...params,
valueGuidance: guidance
}) ?? fit({
...params,
valueGuidance: "Not retained; return less data."
}) ?? original;
if (retainValue && params.value && projection.valueTruncated && (params.value.json.startsWith("{") || params.value.json.startsWith("["))) {
const saved = retainValue(params.value);
if ("reference" in saved) {
let delivered = false;
try {
const retained = fit({
...params,
reference: saved.reference
});
if (retained?.referenceUsed) {
projection = retained;
delivered = true;
} else projection = fitNonRetention("Not retained: reference exceeds output budget. Return less data.");
} finally {
if (!delivered) saved.release();
}
} else projection = fitNonRetention(saved.reason);
}
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, reference } = params;
const outputBytes = count === 0 ? 0 : sourceBytes(source);
const valueBytes = reference ? jsonUtf8Bytes({
truncated: true,
reference,
guidance: RETAINED_GUIDANCE
}) : value === void 0 ? 0 : sourceBytes(value);
const minimumReference = reference ? retainedMarker({
...reference,
shape: "",
preview: "",
previewTruncated: true
}, Infinity) : void 0;
const referenceBytes = minimumReference ? jsonUtf8Bytes(minimumReference) : 0;
const minimumOutputBytes = reference ? Math.min(outputBytes, jsonUtf8Bytes([createTruncationMarker(source, this.maxBytes)(0)])) : 0;
const errorBytes = fullError === void 0 ? 0 : jsonUtf8Bytes(fullError);
let completeOutput;
let completeValue;
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 === fullError ? errorBytes : jsonUtf8Bytes(error));
const valueReservation = Math.max(Math.floor(remaining / 2), remaining >= referenceBytes + minimumOutputBytes ? referenceBytes : 0);
const outputAllowance = remaining - Math.min(valueBytes, valueReservation);
let output;
let chargedOutputBytes;
let receipt;
if (outputBytes <= outputAllowance) {
output = completeOutput ??= 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
};
}
const valueAllowance = remaining - chargedOutputBytes;
const saved = reference ? retainedMarker(reference, valueAllowance) : void 0;
const valueTruncated = value !== void 0 && (reference !== void 0 || value.kind !== "complete" || valueBytes > valueAllowance);
return {
receipt,
valueTruncated,
referenceUsed: saved !== void 0,
channels: {
output,
...value === void 0 ? {} : saved ? { value: saved } : !reference && value.kind === "complete" && valueBytes <= remaining - chargedOutputBytes ? completeValue ??= { value: JSON.parse(value.json) } : { value: (valueMarker ??= createTruncationMarker(value, this.maxBytes, params.valueGuidance))(remaining - chargedOutputBytes) },
...error === void 0 ? {} : { error }
}
};
};
}
};
//#endregion
export { captureCodeModeValue as a, renderToolSearchControlText as c, captureCodeModeOutput as i, serializeToolSearchControlResult as l, EMPTY_CODE_MODE_OUTPUT as n, stringifyCodeModeJsonSafe as o, boundCodeModeError as r, toCodeModeJsonSafe as s, CodeModeOutputState as t, createCodeModeResultReference as u };