UNPKG

@sema-agent/core

Version:

Stateless, task-oriented AI agent core

56 lines (55 loc) • 2.92 kB
import { isRemoteExecutionEnv } from "../remote-env.js"; import { deliverEngineNotice } from "../engine-notice.js"; const BOOLEAN_CAPABILITY_KEYS = ["isolation", "suspendable", "canonicalPathAuthoritative"]; const OPTIONAL_METHOD_KEYS = ["writeFileExclusive", "writeFileGuarded", "setFileMode", "readLink", "canonicalChain", "fileIdentity", "openBound"]; export function malformedCapabilityDeclarations(env) { const out = []; for (const key of OPTIONAL_METHOD_KEYS) { let value; try { value = Reflect.get(env, key); } catch { out.push({ key, valueType: "unreadable", expected: "function" }); continue; } if (value === undefined || typeof value === "function") continue; out.push({ key, valueType: value === null ? "null" : typeof value, expected: "function" }); } let caps; try { if (!isRemoteExecutionEnv(env)) return out; caps = env.capabilities; } catch { out.push({ key: "capabilities", valueType: "unreadable", expected: "boolean" }); return out; } for (const key of BOOLEAN_CAPABILITY_KEYS) { let value; try { value = caps[key]; } catch { out.push({ key, valueType: "unreadable", expected: "boolean" }); continue; } if (value === undefined || typeof value === "boolean") continue; out.push({ key, valueType: value === null ? "null" : typeof value, expected: "boolean" }); } return out; } export function announceMalformedCapabilities(env, onNotice) { for (const { key, valueType, expected } of malformedCapabilityDeclarations(env)) { deliverEngineNotice(onNotice, { code: "config.execution_env_capability_invalid", message: expected === "function" ? `The execution environment declares ${key} as a ${valueType}, not a function. This seat is declared by being present as a callable method and undeclared by being absent, so every reader takes the absent reading — the reach the adapter meant to declare is silently the old one. Fix the adapter — this is a wiring fault, not a supported way to leave the seat unset.` : `The execution environment declares capabilities.${key} as a ${valueType}, not a boolean. What a reader makes of that is the reader's own business and differs between them — the containment readers take only the boolean, so this reads as undeclared, while the suspend reader takes any truthy value, so a non-empty string reads as TRUE. That is why a declaration of the wrong shape cannot pass quietly: the engine may act on something other than what the adapter meant. Fix the adapter — this is a wiring fault, not a supported way to leave the capability unset.`, detail: { key, valueType }, }); } }