@sema-agent/core
Version:
Stateless, task-oriented AI agent core
366 lines (365 loc) • 25 kB
JavaScript
import { isSyntheticApiErrorMessage } from "../../internal/harness.js";
import { createHash } from "node:crypto";
import { childThinkingSeat, deploymentSubagentThinking, deploymentSubagentTierModel, forkGovernanceDenial } from "../../agents/subagent.js";
import { inheritedParentModel } from "../../agents/child-model-seat.js";
import { CROSS_SESSION_CLASSIFIER_RULE } from "../../agents/cross-session-envelope.js";
import { createRunWorkflowTool } from "../../orchestration/run-workflow-tool.js";
import { isSelfOrchestrationActive } from "../../orchestration/workflow-script-runner.js";
import { resolveWorkflowSizeGuideline } from "../../orchestration/workflow-size-guideline.js";
import { autoModeArmingRecipeOf } from "../auto-mode-arming.js";
import { AUTO_MODE_CLASSIFIER_MAX_RETRIES } from "../auto-mode-defaults.js";
import { buildAutoModePrompt, readDenyClassifierRules, renderAutoModeAction, renderAutoModeWindow } from "../auto-mode-prompt.js";
import { autoModeClassifierFallbackOf, createAutoModeDecider, createAutoModeDenialTracker, screenAutoModeKnobs } from "../auto-mode.js";
import { checkpointStoreOfSeat } from "../checkpoint-seat.js";
import { COMPLIANCE_CAPABILITIES, WEB_FETCH_TOOL_NAME, resolveComplianceDenies } from "../compliance.js";
import { createPresentPlanTool, createEnterPlanModeTool } from "../present-plan-tool.js";
import { brainToRuntime } from "../runtime.js";
import { defaultTaskRegistry } from "../task-registry.js";
import { defineTool, isDefineToolProduct, rebindDefineToolCtx } from "../tools.js";
const MOUNT_REMEDY = "author it as a plain-object ToolSpec (own `name` and `execute`), hand the defineTool product itself, or wrap a product through the supported wrapper form (a fresh object re-stamped with `stampDefineToolBrand` whose rebind re-wraps the rebound product)";
import { isAutoModeDenySource } from "../runtime-caps.js";
import { derivedRouteFallsBack } from "./derived-route-fallback.js";
import { CLASSIFIER_ATTEMPT_SUFFIX, CLASSIFIER_THINK_SEAT, announceClassifierRoleDefaulted, classifierLadderRungs, classifierReplyAsksAgain, classifierReplyFailure, classifierReplyVerdictText, classifierRoundObserver, classifierRungSeat, classifierSeatModel } from "./classifier-ladder.js";
import { REPORT_FINDINGS_TOOL_NAME, createReportBlockedTool, createReportFindingsTool } from "./synthetic-tools.js";
import { RosterBuilder, callerMountSource } from "../tool-roster.js";
import { asThrownError, thrownText } from "../thrown-value.js";
function assembleParentCaptureState(o, i, ctl, ancestors) {
const build = (optedOut, indeterminate) => ({
optedOut: optedOut === true,
indeterminate: indeterminate === true,
...(ctl !== undefined ? { controlDir: ctl } : {}),
ancestors,
});
return o instanceof Promise || i instanceof Promise ? Promise.all([o, i]).then(([ov, iv]) => build(ov, iv)) : build(o, i);
}
const RUNTIME_CAP_KEYS = {
allowWorkflows: true,
allowFork: true,
allowObservers: true,
forceDurableGate: true,
autoMode: true,
autoModeDenySource: true,
bypassPermissions: true,
allowMemoryOptOut: true,
};
function snapshotRuntimeCaps(record) {
const out = {};
for (const key of Object.keys(RUNTIME_CAP_KEYS)) {
const v = record[key];
if (v !== undefined)
out[key] = v;
}
return out;
}
function screenAutoModeCap(caps, onError, sessionId) {
if (caps === undefined)
return { caps, faulted: false };
if (typeof caps !== "object" || caps === null || Array.isArray(caps)) {
onError?.(new Error(`runtimeCapsResolver returned a non-record value (${JSON.stringify(caps)}) — read as a resolver fault: every per-principal capability is DENIED for this run (auto mode is not armed; asks flow the original chain). Return a RuntimeCaps object or undefined.`), { phase: "config", sessionId });
return { caps: { allowWorkflows: false, allowFork: false, autoMode: false, bypassPermissions: false }, faulted: true };
}
let record;
try {
record = snapshotRuntimeCaps(caps);
}
catch (err) {
onError?.(new Error(`runtimeCapsResolver's record threw while being read (${thrownText(err)}) — read as a resolver fault: every per-principal capability is DENIED for this run (auto mode is not armed; asks flow the original chain).`), { phase: "config", sessionId });
return { caps: { allowWorkflows: false, allowFork: false, autoMode: false, bypassPermissions: false }, faulted: true };
}
let screened = record;
let faulted = false;
const fault = (message) => {
onError?.(new Error(`runtimeCapsResolver returned ${message}`), { phase: "config", sessionId });
faulted = true;
};
const { autoMode, autoModeDenySource } = record;
if (autoModeDenySource !== undefined && (!isAutoModeDenySource(autoModeDenySource) || autoMode !== false)) {
fault(`autoModeDenySource=${JSON.stringify(autoModeDenySource)} beside autoMode=${JSON.stringify(autoMode)} — read as a resolver fault: auto mode is DENIED for this run (the classifier is not armed; asks flow to the approver / park)`);
const { autoModeDenySource: _refused, ...rest } = screened;
screened = { ...rest, autoMode: false };
}
else if (autoMode !== undefined && typeof autoMode !== "boolean") {
fault(`a non-boolean autoMode (${JSON.stringify(autoMode)}) — read as a resolver fault: auto mode is DENIED for this run (the classifier is not armed; asks flow the same way they do with no auto-mode face)`);
screened = { ...screened, autoMode: false };
}
if (record.bypassPermissions !== undefined && typeof record.bypassPermissions !== "boolean") {
fault(`a non-boolean bypassPermissions (${JSON.stringify(record.bypassPermissions)}) — read as a resolver fault: bypassPermissions is DENIED for this run (a requested bypass folds back to default)`);
screened = { ...screened, bypassPermissions: false };
}
return { caps: screened, faulted };
}
function mintPersistedArming(am, laneRule, classifierSystemPrompt, derivedDenyRules, onError, sessionId) {
const arming = autoModeArmingRecipeOf(laneRule ? { ...am, crossSessionMessagesRule: true } : am, {
promptDigest: `apv1:${createHash("sha256").update(classifierSystemPrompt).digest("hex")}`,
derivedDenyRules,
});
if (arming === undefined) {
onError?.(new Error("RunnerDeps.autoMode.persistArming is set but the auto-mode face did not canonicalize into an arming recipe " +
"(a rule list carrying a non-string, or a non-finite/out-of-range timeoutMs / failureThreshold / window bound) — " +
"NO arming recipe is recorded on this run's parked constraint chain, and a cross-process redemption keeps the " +
"conservative behavior (the ancestor classifier answers unavailable and the inherited ask flows to a human)"), { phase: "config", sessionId });
}
return arming;
}
function autoModeArmReasonOf(intent, facePresent, caps, capsFaulted) {
if (!intent)
return { armed: false, reason: "no_intent" };
if (!facePresent)
return { armed: false, reason: "no_face" };
if (caps?.autoMode === false) {
if (capsFaulted)
return { armed: false, reason: "resolver_fault" };
return { armed: false, reason: "denied", ...(caps.autoModeDenySource !== undefined ? { deniedSource: caps.autoModeDenySource } : {}) };
}
return { armed: true, reason: "armed" };
}
export async function prepareCapsAndWorkflow(input) {
const { spec, deps, parentSpecSeat, checkpointSeat, internals, session, sessionId, runId, hostTaskId, taskScope, taskRootFinal, model, thinking, lockedPreflight, toolEffects, toolFaceSnapshot, promptProfile, resolvedInteractionPosture, harnessRef, frozenOnAsk, carrierReadFace, carrierWriteFace, forwardEvent, inheritedGateForChildren, enrichSpecToolCtx, maybeOffload, requestReview, enterPlanMode, permissionMode, readDenyEntries, peerLaneActive, peerSendMessageBuiltIn, runnerSelf } = input;
const roster = new RosterBuilder(toolEffects);
for (const t of spec.tools ?? []) {
const mounted = mountCallerTool(t);
roster.mount(mounted, { source: callerMountSource(mounted), mountedBy: "scenario" });
}
function specArmCanConstruct(t) {
if (typeof t !== "object" || t === null)
return false;
const name = Object.getOwnPropertyDescriptor(t, "name");
const execute = Object.getOwnPropertyDescriptor(t, "execute");
return name !== undefined && "value" in name && typeof name.value === "string" && name.enumerable === true && execute !== undefined && "value" in execute && typeof execute.value === "function" && execute.enumerable === true;
}
function mountCallerTool(t) {
if (isDefineToolProduct(t))
return maybeOffload(rebindDefineToolCtx(t, enrichSpecToolCtx), t);
if (!specArmCanConstruct(t)) {
const shown = Object.getOwnPropertyDescriptor(t, "name")?.value;
const e = new Error(`spec.tools entry ${typeof shown === "string" ? JSON.stringify(shown) : "(no own name)"}: the ToolSpec arm rebuilds a caller tool from its OWN enumerable members, and this entry does not carry a string \`name\` and a function \`execute\` as own properties (a class instance, a prototype child of a spec or of a defineTool product, a function, or a Proxy over one) — ${MOUNT_REMEDY}`);
e.code = "config.tool_mount_denied";
throw e;
}
return maybeOffload(defineTool({
...t,
execute: (args, ctx) => t.execute(args, enrichSpecToolCtx(ctx)),
}), t);
}
const blockedRef = {};
if (spec.enableBlockedReport !== false) {
roster.mount(createReportBlockedTool(blockedRef), { source: "builtin", mountedBy: "always" });
}
if (!(spec.tools ?? []).some((t) => t.name === REPORT_FINDINGS_TOOL_NAME || t.aliases?.includes(REPORT_FINDINGS_TOOL_NAME))) {
roster.mount(createReportFindingsTool(), { source: "builtin", mountedBy: "always" });
}
if (spec.enablePlanMode === true && spec.interactiveTools !== false) {
const planReviewFace = checkpointStoreOfSeat(checkpointSeat) !== undefined;
if (spec.interactiveTools === true || planReviewFace) {
roster.mount(defineTool(createPresentPlanTool(requestReview)), { source: "builtin", mountedBy: "optional" });
if (planReviewFace) {
roster.mount(defineTool(createEnterPlanModeTool(enterPlanMode)), { source: "builtin", mountedBy: "optional" });
}
}
}
let runtimeCaps;
let runtimeCapsFaulted = false;
if (deps.runtimeCapsResolver) {
try {
runtimeCaps = (await deps.runtimeCapsResolver(spec.principal)) ?? undefined;
}
catch (err) {
deps.onError?.(asThrownError(err), { phase: "config", sessionId });
runtimeCaps = { allowWorkflows: false, allowFork: false, autoMode: false, bypassPermissions: false };
runtimeCapsFaulted = true;
}
const screened = screenAutoModeCap(runtimeCaps, deps.onError, sessionId);
runtimeCaps = screened.caps;
runtimeCapsFaulted ||= screened.faulted;
}
let complianceDenies = new Set();
let complianceDegraded = false;
if (deps.compliancePostureResolver) {
try {
const posture = (await deps.compliancePostureResolver(spec.principal)) ?? undefined;
if (posture !== undefined)
complianceDenies = resolveComplianceDenies(posture);
}
catch (err) {
deps.onError?.(asThrownError(err), { phase: "config", sessionId });
complianceDenies = new Set(COMPLIANCE_CAPABILITIES);
complianceDegraded = true;
}
const complianceRefuse = (capability, requested) => {
const e = new Error(`${requested} is denied for this principal by the compliance posture (capability "${capability}"` +
`${complianceDegraded ? "; the posture resolver is currently failing, so every managed capability is denied fail-closed" : ""}) — ` +
`the task is refused rather than silently narrowed.`);
e.code = complianceDegraded ? "config.compliance_required" : "config.compliance_denied";
throw e;
};
if (complianceDenies.has("mcp_servers") && lockedPreflight.mcp?.length) {
complianceRefuse("mcp_servers", "TaskSpec.mcp (MCP server materialization)");
}
if (complianceDenies.has("workflows") && spec.selfOrchestration === true) {
complianceRefuse("workflows", "TaskSpec.selfOrchestration (workflow self-orchestration)");
}
if (complianceDenies.has("web_fetch")) {
const webTool = (spec.tools ?? []).find((t) => t.name === WEB_FETCH_TOOL_NAME || (t.aliases ?? []).includes(WEB_FETCH_TOOL_NAME));
if (webTool !== undefined) {
complianceRefuse("web_fetch", `TaskSpec.tools["${webTool.name}"] (the WebFetch tool face)`);
}
}
}
const agentForkDenial = forkGovernanceDenial(spec.enableFork, runtimeCaps?.allowFork);
const observersActive = runtimeCaps?.allowObservers === true;
const autoModeDeciderRef = { current: undefined };
const autoModeDenialTrackingRef = { current: undefined };
const autoModeArmingRef = { current: undefined };
const autoModeArmReason = () => autoModeArmReasonOf(permissionMode.declared === "auto", deps.autoMode !== undefined, runtimeCaps, runtimeCapsFaulted);
if (deps.autoMode !== undefined)
screenAutoModeKnobs(deps.autoMode);
const armAutoMode = async () => {
if (autoModeDeciderRef.current !== undefined)
return;
if (permissionMode.declared !== "auto" || deps.autoMode === undefined || runtimeCaps?.autoMode === false)
return;
const am = deps.autoMode;
const classifierSeat = classifierSeatModel({ deps, main: model });
let classifierModel = classifierSeat.model;
if (await derivedRouteFallsBack({ seat: "auto-mode-classifier", derived: classifierModel, primary: model, brain: deps.brain, getApiKeyAndHeaders: spec.getApiKeyAndHeaders, onNotice: deps.onNotice, sessionId, runId, onBrokenPairing: autoModeClassifierFallbackOf(am.classifierFallback) === "none" ? "refuse" : "fall_back" })) {
classifierModel = model;
}
announceClassifierRoleDefaulted({ onNotice: deps.onNotice, seat: { ...classifierSeat, model: classifierModel }, ...(sessionId !== undefined ? { sessionId } : {}), ...(runId !== undefined ? { runId } : {}) });
const classifierLaneRule = peerLaneActive && peerSendMessageBuiltIn;
const table = readDenyEntries();
const derivedDenyRules = readDenyClassifierRules(table.entries, table.ruleRows);
let classifierSystemPromptMemo;
const classifierSystemPrompt = () => (classifierSystemPromptMemo ??= buildAutoModePrompt({ ...am, derivedDenyRules, ...(classifierLaneRule ? { crossSessionMessagesRule: CROSS_SESSION_CLASSIFIER_RULE } : {}) }));
const classifierRuntime = brainToRuntime(deps.brain);
const classifierRungs = classifierLadderRungs(am.classifierFallback, classifierModel, model);
const denialTracking = createAutoModeDenialTracker(am.denialLimit);
const decider = createAutoModeDecider({
...(am.timeoutMs !== undefined ? { timeoutMs: am.timeoutMs } : {}),
candidates: classifierRungs.map((m) => m.id),
onClassified: classifierRoundObserver({ tracer: deps.tracer, onNotice: deps.onNotice, taskId: hostTaskId, seatModelId: classifierModel.id, ...(sessionId !== undefined ? { sessionId } : {}), ...(runId !== undefined ? { runId } : {}) }),
assemble: async (input) => {
const ctx = await session.buildContext();
const known = ctx.messages.filter((m) => !isSyntheticApiErrorMessage(m) && (m.role === "user" || m.role === "assistant" || m.role === "toolResult"));
return renderAutoModeWindow(known, am.window) + renderAutoModeAction(input);
},
classify: async (_input, signal, rung, userPrompt) => {
const rungModel = rung !== undefined ? classifierRungs[rung.index] : undefined;
if (rung === undefined || rungModel === undefined) {
throw new Error(`the auto-mode classifier was asked at ladder position ${JSON.stringify(rung?.index)}, which this arming did not build`);
}
if (userPrompt === undefined) {
throw new Error("the auto-mode classifier was asked with no assembled question, which this arming builds once per classification");
}
const classifierAuth = await spec.getApiKeyAndHeaders?.(rungModel);
const request = async (seat, suffix) => {
const response = await classifierRuntime.completeSimple(rungModel, { systemPrompt: classifierSystemPrompt(), messages: [{ role: "user", content: userPrompt + suffix, timestamp: Date.now() }] }, {
signal,
maxRetries: AUTO_MODE_CLASSIFIER_MAX_RETRIES,
...seat,
...(classifierAuth?.apiKey !== undefined ? { apiKey: classifierAuth.apiKey } : {}),
...(classifierAuth?.headers !== undefined ? { headers: classifierAuth.headers } : {}),
});
const failure = classifierReplyFailure(response);
if (failure !== undefined)
throw failure;
return response;
};
let response = await request(classifierRungSeat(rungModel), CLASSIFIER_ATTEMPT_SUFFIX.first);
if (classifierReplyAsksAgain(response) && signal?.aborted !== true)
response = await request(CLASSIFIER_THINK_SEAT, CLASSIFIER_ATTEMPT_SUFFIX.reask);
return classifierReplyVerdictText(response);
},
});
const arming = am.persistArming === true ? mintPersistedArming(am, classifierLaneRule, classifierSystemPrompt(), derivedDenyRules, deps.onError, sessionId) : undefined;
if (autoModeDeciderRef.current !== undefined)
return;
autoModeDeciderRef.current = decider;
autoModeDenialTrackingRef.current = denialTracking;
autoModeArmingRef.current = arming;
};
permissionMode.bindArming({ caps: runtimeCaps, autoFacePresent: deps.autoMode !== undefined, armAuto: armAutoMode, onArmFault: (e) => deps.onError?.(asThrownError(e), { phase: "config", sessionId }) });
const deploymentWorkflowReady = runnerSelf !== undefined && isSelfOrchestrationActive(spec, deps);
const selfOrchestrationActive = deploymentWorkflowReady && runtimeCaps?.allowWorkflows !== false;
if (deploymentWorkflowReady && runtimeCaps?.allowWorkflows === false) {
deps.onError?.(new Error(`self-orchestration DENIED for principal "${spec.principal ?? ""}" by runtimeCaps.allowWorkflows=false ` +
`(per-principal entitlement governance, not a misconfiguration — the run_workflow tool is not mounted)`), { phase: "config", sessionId });
}
let workflowToolsActive = false;
let workflowSizeGuideline;
if (selfOrchestrationActive && runnerSelf && deps.workflowScriptRunner && deps.workflowGovernanceBaseline) {
workflowToolsActive = true;
const currentSizeGuideline = () => resolveWorkflowSizeGuideline(deps.workflowLimits?.sizeGuideline).size;
workflowSizeGuideline = { legGuideline: currentSizeGuideline(), current: currentSizeGuideline };
roster.mount(await createRunWorkflowTool({
runner: runnerSelf,
scriptRunner: deps.workflowScriptRunner,
governanceBaseline: deps.workflowGovernanceBaseline,
parentExcludeTools: toolFaceSnapshot.exclude,
parentDeferTools: toolFaceSnapshot.defer,
parentAlwaysLoadTools: toolFaceSnapshot.alwaysLoad,
...(toolFaceSnapshot.restoreGated !== undefined ? { parentRestoreGatedTools: toolFaceSnapshot.restoreGated } : {}),
parentPromptProfile: promptProfile,
models: deps.models,
agents: deps.agents,
builtinAgents: deps.builtinAgents,
store: deps.workflowRunStore,
journalStore: deps.workflowJournalStore,
...(deps.onBackgroundChildEvent ? { onBackgroundChildEvent: deps.onBackgroundChildEvent } : {}),
scriptStore: deps.workflowScriptStore,
builtinWorkflows: deps.builtinWorkflows,
onAgentSpawn: deps.onWorkflowAgentSpawn,
scope: taskScope,
notifier: deps.workflowCompletionNotifier,
originatingSessionId: sessionId,
rootSessionId: internals?.rootSessionId ?? sessionId, ...(internals?.placementRoot !== undefined ? { placementRoot: internals.placementRoot } : {}),
taskRegistry: defaultTaskRegistry,
taskNotification: internals?.onTaskNotification,
taskOwner: hostTaskId,
limits: deps.workflowLimits,
sourceTaskId: hostTaskId,
parentModel: () => {
const stated = deploymentSubagentTierModel(runnerSelf.agentCatalog);
if (stated !== undefined)
return stated;
const ref = harnessRef.current?.getModelRef();
const model = inheritedParentModel(ref, runnerSelf.agentCatalog.models);
return model === undefined ? undefined : { model, ...(typeof ref === "string" ? { modelRef: ref } : {}) };
},
...(spec.getApiKeyAndHeaders !== undefined ? { parentGetApiKeyAndHeaders: spec.getApiKeyAndHeaders } : {}),
...(frozenOnAsk !== undefined ? { parentOnAsk: frozenOnAsk } : {}),
...(spec.durableApproval !== undefined ? { parentDurableApproval: { ...spec.durableApproval } } : {}),
...(internals?.workflowParkedResume !== undefined
? { parkedResume: (resumeFromRunId) => {
const mine = internals.workflowParkedResume.filter((d) => d.runId === resumeFromRunId).map(({ runId: _r, ...rest }) => rest);
return mine.length > 0 ? mine : undefined;
} }
: {}),
parentSpecSeat, ...(internals?.questionFaceStripped === true ? { parentQuestionFaceStripped: true } : {}),
...(resolvedInteractionPosture !== undefined ? { parentInteractionPosture: resolvedInteractionPosture } : {}),
parentMemoryCaptureState: () => {
const memoryEngineSession = input.memoryEngineSession();
const ctl = memoryEngineSession?.engine.controlPlaneDir;
const co = memoryEngineSession?.captureOptOut;
return assembleParentCaptureState(co?.optedOut() ?? false, co?.indeterminate() ?? false, ctl, [...(internals?.memoryCaptureAncestors ?? []), { sessionId, ...(ctl !== undefined ? { controlDir: ctl } : {}) }]);
},
autoModeReview: () => (autoModeDeciderRef.current !== undefined ? { decider: autoModeDeciderRef.current } : undefined),
workflowDepth: internals?.workflowDepth,
parentCwd: taskRootFinal,
parentThinking: () => childThinkingSeat(undefined, deploymentSubagentThinking(runnerSelf.agentCatalog?.roles), harnessRef.current?.getThinkingLevel() ?? thinking).thinking,
parentReadFace: () => carrierReadFace(),
parentWriteFace: () => carrierWriteFace(),
parentReadDenyPatterns: () => {
const readDenyAdditionsNormalized = input.readDenyAdditionsNormalized();
return readDenyAdditionsNormalized.length > 0 ? readDenyAdditionsNormalized : undefined;
},
...(spec.handsReadOnly === true ? { parentHandsReadOnly: true } : {}), ...(spec.interactiveTools === false ? { parentInteractiveTools: false } : {}),
onNotice: deps.onNotice,
...(checkpointSeat !== undefined ? { parentCheckpointStore: checkpointSeat } : {}),
parentCenterArtifactDigest: () => input.centerAdoption()?.artifact.artifactDigest,
parentCenterSourceRevision: () => input.centerAdoption()?.sourceRevision,
...(forwardEvent ? { forwardEvent } : {}),
inheritedGateForChildren,
}), { source: "builtin", mountedBy: "workflow" });
}
return { roster, blockedRef, runtimeCaps, runtimeCapsFaulted, complianceDenies, complianceDegraded, agentForkDenial, observersActive, autoModeArmReason, autoModeDeciderRef, autoModeDenialTrackingRef, autoModeArmingRef, armAutoMode, selfOrchestrationActive, workflowToolsActive, workflowSizeGuideline };
}