@sema-agent/core
Version:
Stateless, task-oriented AI agent core
56 lines (55 loc) • 2.91 kB
JavaScript
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"];
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 },
});
}
}