UNPKG

@sema-agent/core

Version:

Stateless, task-oriented AI agent core

91 lines (90 loc) • 4.16 kB
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; }