UNPKG

@sema-agent/core

Version:

Stateless, task-oriented AI agent core

31 lines (30 loc) • 2.23 kB
import type { TaskSpec } from "./types.js"; /** Thrown when `overrides` would LOOSEN a safety field `base` already set (a tighten-only violation). */ export declare class TaskSpecTightenError extends Error { constructor(message: string); } /** * Merge `overrides` onto `base` with TIGHTEN-ONLY semantics for the safety-bearing fields. Non-safety fields * follow plain last-wins object spread (`overrides` value wins when present, else `base`). The safety fields * get explicit rules: * * - **`toolPolicy`** — both set ⇒ `combinePolicies(base, override)` (deny-wins; the base's denials survive, * the override can only ADD denials/asks). Either alone ⇒ that one. This is the central fix: a blind spread * would drop the base policy entirely. * - **every row of the clamp table** (`CLAMP_SET`: `handsReadOnly`, `interactiveTools`, `approvalReach`, the two * containment faces, `readDenyPatterns`, `oneShot`, `memoryPersistenceCapable`, `fileHistory`, `promptForm`) — a base carrying the * row's restricting value meeting an override that states a different one ⇒ **throw** (loosening); otherwise the * restricting value wins if either side carries it, an add-only list unions, and an override writing `undefined` * erases nothing. * - **`shellGate`** — one value (`"always"`, the operator floor). Either side set ⇒ the floor stands; it cannot * be loosened because absence is the only other state and an override cannot unset a base value. * - **`onAsk`** — no safe automatic merge (the approver and the policy must be coordinated). Both set to * DIFFERENT values ⇒ **throw**; equal ⇒ keep; one set ⇒ that one. * - **`mods`** — both set ⇒ both ride, base first then override (the task seat is a list and the bus composes it: * a registration only ever adds a handler to the chain; names stay unique, refused at admission otherwise). * One set ⇒ that one. * * @throws {TaskSpecTightenError} when an override would loosen a stricter base safety field, or when two * incompatible safety values are both set and cannot be merged automatically. */ export declare function tightenTaskSpec(base: TaskSpec, overrides: Partial<TaskSpec>): TaskSpec;