@sema-agent/core
Version:
Stateless, task-oriented AI agent core
92 lines (91 loc) • 5.28 kB
JavaScript
import { types } from "node:util";
import { dispositionsOfRow, SHELL_READ_FINDINGS } from "../tools/fs/shell-read-judge.js";
import { receiveContract } from "./decision-receipt.js";
import { egressThrownText } from "./untrusted-egress.js";
import { receive } from "./mods/kernel/receive.js";
const DISPOSITIONS = ["refuse", "mandated", "ordinary", "vouch"];
const MEMBER_KINDS = {
disposition: "word",
finding: "word",
environmentSilent: "mark",
rowsUnread: "mark",
face: "face",
sentence: "word",
details: "record",
readRootCandidate: "record",
unestablished: "mark",
writesPlaced: "mark",
writeProtected: "mark",
targetUnresolved: "mark",
unplacedOptions: "record",
admit: "admission",
};
const VERDICT_MEMBERS = Object.keys(MEMBER_KINDS);
const OWNED_DATA_MODE = Object.freeze({ accessors: "refuse", depth: 8, others: "refuse", isProxy: (v) => types.isProxy(v) });
function receivedAnswer(answer, call) {
if (typeof answer !== "object" || answer === null)
return undefined;
const outer = receiveContract(answer, VERDICT_MEMBERS, "");
if (outer.kind !== "held")
return undefined;
const out = {};
for (const [member, kind] of Object.entries(MEMBER_KINDS)) {
let v = outer.held[member];
if (v === undefined)
continue;
if (kind === "word" ? typeof v !== "string" : kind === "mark" ? v !== true : kind === "face" ? v !== "write" : kind === "admission" ? typeof v !== "function" || types.isProxy(v) : false)
return undefined;
if (kind === "record") {
const data = receive(v, OWNED_DATA_MODE);
if (!data.ok || typeof data.value !== "object" || data.value === null || Array.isArray(data.value))
return undefined;
v = data.value;
}
if (kind === "admission") {
const admission = v;
v = () => {
try {
Reflect.apply(admission, undefined, []);
}
catch (e) {
call.report?.(new Error(`shell read station's admission threw for tool "${call.toolName}"${call.toolCallId !== undefined ? ` (toolCallId ${call.toolCallId})` : ""} — nothing was admitted: ${egressThrownText("same-principal", e)}`));
}
};
}
Object.defineProperty(out, member, { value: v, enumerable: true, writable: true, configurable: true });
}
return out;
}
export function readStationAnswer(answer, call) {
const verdict = receivedAnswer(answer, call);
if (verdict?.disposition === "refuse")
return { kind: "refuse", verdict };
if (verdict !== undefined && (verdict.finding === "unanswered" || (verdict.finding === "none" && (verdict.environmentSilent === true || verdict.rowsUnread === true))))
return { kind: "silence", verdict };
if (verdict !== undefined && DISPOSITIONS.includes(verdict.disposition) && dispositionsOfRow(verdict.finding).has(verdict.disposition))
return { kind: verdict.disposition, verdict };
const word = (w, set) => (w !== undefined && set.includes(w) ? `"${w}"` : "a word outside its closed set");
const sentence = verdict === undefined
? `tool "${call.toolName}" was refused: the read station's answer is not one the engine can receive (an ordinary object holding its members as its own data properties, each of its kind), so it is not believed (denied fail-closed)`
: `tool "${call.toolName}" was refused: the read station answered ${word(verdict.disposition, DISPOSITIONS)} beside the finding ${word(verdict.finding, SHELL_READ_FINDINGS)}, an answer the read decision table never gives that finding — the station's answer contradicts its own finding and is not believed (denied fail-closed)`;
call.report?.(new Error(`shell read station answered out of its contract for tool "${call.toolName}"${call.toolCallId !== undefined ? ` (toolCallId ${call.toolCallId})` : ""} — ${sentence}`));
return { kind: "refuse", verdict: { disposition: "refuse", finding: "none", sentence }, unbelieved: true };
}
export function silencedBy(verdict, d) {
const environment = verdict.environmentSilent === true || (verdict.finding === "unanswered" && verdict.rowsUnread !== true);
const rows = verdict.rowsUnread === true && d.ruleUnreadable === undefined ? { ruleUnreadable: "persisted_rows" } : {};
const guards = environment && d.guards?.includes("unverifiable_shell_text") !== true ? { guards: [...(d.guards ?? []), "unverifiable_shell_text"] } : {};
return environment || verdict.rowsUnread === true ? { ...rows, ...guards, requiresRealApproval: true } : {};
}
export function applyUnansweredSilence(pass, verdict, ask) {
if (verdict.details !== undefined)
pass.shellReadDetails = verdict.details;
if (pass.decision.action === "ask") {
pass.decision = { ...pass.decision, ...silencedBy(verdict, pass.decision) };
return;
}
if (pass.decision.action !== "allow")
return;
pass.decision = { action: "ask", message: ask.message, decisionReason: "safety", ...silencedBy(verdict, {}), ...(ask.account !== undefined ? { probeReason: ask.account } : {}) };
pass.tightenedBy = ask.tightenedBy;
}