@sema-agent/core
Version:
Stateless, task-oriented AI agent core
91 lines (90 loc) • 4.16 kB
JavaScript
export const TOOL_SEARCH_DEFAULT_THRESHOLD_PERCENT = 10;
export const TOOL_SEARCH_INVALID_CODE = "config.tool_search_invalid";
export const TOOL_SEARCH_POLICIES = Object.freeze(["always", "never", "auto"]);
export function resolveToolSearch(setting) {
if (setting === undefined)
return { policy: "auto", thresholdPercent: TOOL_SEARCH_DEFAULT_THRESHOLD_PERCENT, fraction: TOOL_SEARCH_DEFAULT_THRESHOLD_PERCENT / 100 };
if (setting === true)
return { policy: "always", fraction: 0 };
if (setting === false)
return { policy: "never", fraction: Number.POSITIVE_INFINITY };
if (typeof setting !== "object" || setting === null) {
throw toolSearchRefusal(`invalid value ${describeRejectedValue(setting)} — expected true, false, {mode:"auto"} or {mode:"auto", thresholdPercent:N}`);
}
let mode;
let percent;
let keys = [];
try {
keys = Object.keys(setting);
mode = setting.mode;
percent = setting.thresholdPercent;
}
catch {
throw toolSearchRefusal(`its members could not be read (a throwing accessor, or a revoked proxy) — expected true, false, {mode:"auto"} or {mode:"auto", thresholdPercent:N}`);
}
if (mode !== "auto") {
throw toolSearchRefusal(`invalid value ${describeRejectedValue(setting)} — expected true, false, {mode:"auto"} or {mode:"auto", thresholdPercent:N}`);
}
const stray = keys.find((k) => k !== "mode" && k !== "thresholdPercent");
if (stray !== undefined) {
throw toolSearchRefusal(`unknown member ${JSON.stringify(stray)} — the object form carries mode and thresholdPercent only`);
}
if (percent === undefined)
return { policy: "auto", thresholdPercent: TOOL_SEARCH_DEFAULT_THRESHOLD_PERCENT, fraction: TOOL_SEARCH_DEFAULT_THRESHOLD_PERCENT / 100 };
if (typeof percent !== "number" || !Number.isFinite(percent) || percent < 0 || percent > 100) {
throw toolSearchRefusal(`thresholdPercent ${describeRejectedValue(percent)} is not a finite percent in [0, 100]`);
}
return { policy: "auto", thresholdPercent: percent, fraction: percent / 100 };
}
export function describeRejectedValue(value) {
try {
switch (typeof value) {
case "bigint":
return `${value}n`;
case "symbol":
return String(value);
case "string":
return JSON.stringify(value);
case "number":
return Object.is(value, -0) ? "-0" : String(value);
case "boolean":
case "undefined":
return String(value);
case "function":
return "a function";
}
if (value === null || value === undefined)
return String(value);
let ctor = "";
try {
const name = value.constructor?.name;
if (typeof name === "string" && name !== "" && name !== "Object" && name !== "Array")
ctor = ` (${name.slice(0, 40)})`;
}
catch {
}
if (Array.isArray(value)) {
const n = value.length;
return `an array${ctor}${typeof n === "number" && Number.isSafeInteger(n) && n >= 0 ? ` of ${n} member(s)` : ""}`;
}
const keys = Object.keys(value);
if (keys.length === 0)
return `an object${ctor} with no keys`;
return `an object${ctor} with keys [${keys.slice(0, 5).map((k) => k.slice(0, 40)).join(", ")}${keys.length > 5 ? ", …" : ""}]`;
}
catch {
return `a value of type ${value === null ? "null" : typeof value} that cannot be described`;
}
}
export function toolSearchSettingOf(resolved) {
if (resolved.policy === "always")
return true;
if (resolved.policy === "never")
return false;
return { mode: "auto", thresholdPercent: resolved.thresholdPercent ?? TOOL_SEARCH_DEFAULT_THRESHOLD_PERCENT };
}
function toolSearchRefusal(problem) {
const e = new Error(`RunnerDeps.toolSearch: ${problem}; a bad value refuses loudly, nothing falls back to the default gate.`);
e.code = TOOL_SEARCH_INVALID_CODE;
return e;
}