UNPKG

@sema-agent/core

Version:

Stateless, task-oriented AI agent core

531 lines (530 loc) • 36 kB
import { Type, type Static, type TSchema } from "typebox"; import type { AgentTool } from "../internal/harness-types.js"; import { type ToolFamily, type ToolRosterPathTarget, type ToolMountTag, type ToolPathTarget, type ToolRenderHints, type ToolRuleFace } from "./tool-face.js"; import type { ToolContentOrigin, ToolEffect } from "./tool-spec.js"; export declare const ROSTER_SOURCES: readonly ["builtin", "caller", "host", "mcp", "a2a", "external", "synthetic"]; export type RosterSource = (typeof ROSTER_SOURCES)[number]; export declare const ToolRosterRenderHints: Type.TObject<{ userFacingName: Type.TOptional<Type.TString>; activity: Type.TOptional<Type.TString>; summaryParams: Type.TOptional<Type.TArray<Type.TString>>; resultCards: Type.TOptional<Type.TArray<Type.TString>>; approvalCard: Type.TOptional<Type.TUnion<[Type.TLiteral<"file-edit">, Type.TLiteral<"file-write">, Type.TLiteral<"notebook-edit">, Type.TLiteral<"shell">, Type.TLiteral<"fetch">, Type.TLiteral<"plan">, Type.TLiteral<"question">, Type.TLiteral<"generic">]>>; }>; export declare const ToolRosterEntry: Type.TObject<{ name: Type.TString; /** Always present (empty when the tool answers to no other name). */ aliases: Type.TArray<Type.TString>; source: Type.TUnion<[Type.TLiteral<"builtin">, Type.TLiteral<"caller">, Type.TLiteral<"host">, Type.TLiteral<"mcp">, Type.TLiteral<"a2a">, Type.TLiteral<"external">, Type.TLiteral<"synthetic">]>; /** Present iff `source` ∈ {mcp, a2a, external} (run-time validated at the mint). */ origin: Type.TOptional<Type.TObject<{ peer: Type.TString; declaredBy: Type.TOptional<Type.TUnion<[Type.TLiteral<"center">, Type.TLiteral<"file">, Type.TLiteral<"request">]>>; }>>; /** Undeclared ⇒ `legacy:<shapeDigest>` / `unversioned`. */ contract: Type.TObject<{ contractId: Type.TString; implementationRevision: Type.TString; }>; shapeDigest: Type.TString; wireSchemaDigest: Type.TString; /** `builtin:<name>` | `caller:<contractId>` | `mcp:<peer>/<tool>` | `a2a:<peer>/<skill>` | `external:<contractId>`. */ cardId: Type.TString; /** ENGINE-minted: sha256 prefix over the canonical tuple {source, peer, name, contractId}; unique per leg. */ capabilityId: Type.TString; /** The materialized schema's top-level properties (name + coarse type). */ inputKeys: Type.TArray<Type.TObject<{ name: Type.TString; type: Type.TUnion<[Type.TLiteral<"string">, Type.TLiteral<"number">, Type.TLiteral<"integer">, Type.TLiteral<"boolean">, Type.TLiteral<"object">, Type.TLiteral<"array">, Type.TLiteral<"null">, Type.TLiteral<"mixed">]>; }>>; effect: Type.TUnion<[Type.TLiteral<"read">, Type.TLiteral<"write">, Type.TLiteral<"idempotent">]>; effectProvenance: Type.TUnion<[Type.TLiteral<"declared">, Type.TLiteral<"caller">, Type.TLiteral<"synthetic">, Type.TLiteral<"default">]>; offload: Type.TBoolean; offloadThresholdChars: Type.TOptional<Type.TInteger>; compactable: Type.TBoolean; budgetExempt: Type.TBoolean; egress: Type.TBoolean; egressProvenance: Type.TUnion<[Type.TLiteral<"declared">, Type.TLiteral<"caller">, Type.TLiteral<"default">]>; irreversibility: Type.TOptional<Type.TUnion<[Type.TLiteral<"never">, Type.TLiteral<"maybe">, Type.TLiteral<"always">]>>; reversibilityProbe: Type.TBoolean; contentOrigin: Type.TUnion<[Type.TLiteral<"local">, Type.TLiteral<"execution">, Type.TLiteral<"external">]>; contentOriginProvenance: Type.TUnion<[Type.TLiteral<"declared">, Type.TLiteral<"server">, Type.TLiteral<"exempted">, Type.TLiteral<"default">]>; family: Type.TUnion<[Type.TLiteral<"shell">, Type.TLiteral<"file-read">, Type.TLiteral<"file-write">, Type.TLiteral<"search">, Type.TLiteral<"web">, Type.TLiteral<"delegate">, Type.TLiteral<"plan">, Type.TLiteral<"scaffold">, Type.TLiteral<"memory">, Type.TLiteral<"protocol">, Type.TLiteral<"other">]>; pathTarget: Type.TOptional<Type.TObject<{ param: Type.TString; aliases: Type.TArray<Type.TString>; access: Type.TUnion<[Type.TLiteral<"read">, Type.TLiteral<"create">, Type.TLiteral<"edit">]>; skillScopeEligible: Type.TBoolean; base: Type.TOptional<Type.TUnion<[Type.TLiteral<"cwd">, Type.TLiteral<"root">]>>; absent: Type.TOptional<Type.TUnion<[Type.TLiteral<"none">, Type.TLiteral<"base">]>>; patternParam: Type.TOptional<Type.TString>; }>>; ruleFace: Type.TObject<{ primaryParams: Type.TArray<Type.TString>; params: Type.TArray<Type.TString>; }>; approvalPreview: Type.TBoolean; validateInput: Type.TBoolean; deferred: Type.TBoolean; alwaysLoad: Type.TBoolean; /** Present iff the definition carries a model-gate class and survived the gate. */ modelGate: Type.TOptional<Type.TString>; renderHints: Type.TOptional<Type.TObject<{ userFacingName: Type.TOptional<Type.TString>; activity: Type.TOptional<Type.TString>; summaryParams: Type.TOptional<Type.TArray<Type.TString>>; resultCards: Type.TOptional<Type.TArray<Type.TString>>; approvalCard: Type.TOptional<Type.TUnion<[Type.TLiteral<"file-edit">, Type.TLiteral<"file-write">, Type.TLiteral<"notebook-edit">, Type.TLiteral<"shell">, Type.TLiteral<"fetch">, Type.TLiteral<"plan">, Type.TLiteral<"question">, Type.TLiteral<"generic">]>>; }>>; /** The ONE mount condition that fired for this instance. */ mountedBy: Type.TUnion<[Type.TLiteral<"hands">, Type.TLiteral<"backgroundTasks">, Type.TLiteral<"workflow">, Type.TLiteral<"delegation">, Type.TLiteral<"hostInternals">, Type.TLiteral<"peerLane">, Type.TLiteral<"scheduler">, Type.TLiteral<"memory">, Type.TLiteral<"scenario">, Type.TLiteral<"always">, Type.TLiteral<"optional">]>; }>; export type ToolRosterEntry = Static<typeof ToolRosterEntry>; export declare const ToolRoster: Type.TObject<{ schemaVersion: Type.TLiteral<1>; /** Run-time asserted equal to `entries.length`. */ count: Type.TInteger; /** Declaration order = the model's `tools[]` order; names unique (run-time asserted). */ entries: Type.TArray<Type.TObject<{ name: Type.TString; /** Always present (empty when the tool answers to no other name). */ aliases: Type.TArray<Type.TString>; source: Type.TUnion<[Type.TLiteral<"builtin">, Type.TLiteral<"caller">, Type.TLiteral<"host">, Type.TLiteral<"mcp">, Type.TLiteral<"a2a">, Type.TLiteral<"external">, Type.TLiteral<"synthetic">]>; /** Present iff `source` ∈ {mcp, a2a, external} (run-time validated at the mint). */ origin: Type.TOptional<Type.TObject<{ peer: Type.TString; declaredBy: Type.TOptional<Type.TUnion<[Type.TLiteral<"center">, Type.TLiteral<"file">, Type.TLiteral<"request">]>>; }>>; /** Undeclared ⇒ `legacy:<shapeDigest>` / `unversioned`. */ contract: Type.TObject<{ contractId: Type.TString; implementationRevision: Type.TString; }>; shapeDigest: Type.TString; wireSchemaDigest: Type.TString; /** `builtin:<name>` | `caller:<contractId>` | `mcp:<peer>/<tool>` | `a2a:<peer>/<skill>` | `external:<contractId>`. */ cardId: Type.TString; /** ENGINE-minted: sha256 prefix over the canonical tuple {source, peer, name, contractId}; unique per leg. */ capabilityId: Type.TString; /** The materialized schema's top-level properties (name + coarse type). */ inputKeys: Type.TArray<Type.TObject<{ name: Type.TString; type: Type.TUnion<[Type.TLiteral<"string">, Type.TLiteral<"number">, Type.TLiteral<"integer">, Type.TLiteral<"boolean">, Type.TLiteral<"object">, Type.TLiteral<"array">, Type.TLiteral<"null">, Type.TLiteral<"mixed">]>; }>>; effect: Type.TUnion<[Type.TLiteral<"read">, Type.TLiteral<"write">, Type.TLiteral<"idempotent">]>; effectProvenance: Type.TUnion<[Type.TLiteral<"declared">, Type.TLiteral<"caller">, Type.TLiteral<"synthetic">, Type.TLiteral<"default">]>; offload: Type.TBoolean; offloadThresholdChars: Type.TOptional<Type.TInteger>; compactable: Type.TBoolean; budgetExempt: Type.TBoolean; egress: Type.TBoolean; egressProvenance: Type.TUnion<[Type.TLiteral<"declared">, Type.TLiteral<"caller">, Type.TLiteral<"default">]>; irreversibility: Type.TOptional<Type.TUnion<[Type.TLiteral<"never">, Type.TLiteral<"maybe">, Type.TLiteral<"always">]>>; reversibilityProbe: Type.TBoolean; contentOrigin: Type.TUnion<[Type.TLiteral<"local">, Type.TLiteral<"execution">, Type.TLiteral<"external">]>; contentOriginProvenance: Type.TUnion<[Type.TLiteral<"declared">, Type.TLiteral<"server">, Type.TLiteral<"exempted">, Type.TLiteral<"default">]>; family: Type.TUnion<[Type.TLiteral<"shell">, Type.TLiteral<"file-read">, Type.TLiteral<"file-write">, Type.TLiteral<"search">, Type.TLiteral<"web">, Type.TLiteral<"delegate">, Type.TLiteral<"plan">, Type.TLiteral<"scaffold">, Type.TLiteral<"memory">, Type.TLiteral<"protocol">, Type.TLiteral<"other">]>; pathTarget: Type.TOptional<Type.TObject<{ param: Type.TString; aliases: Type.TArray<Type.TString>; access: Type.TUnion<[Type.TLiteral<"read">, Type.TLiteral<"create">, Type.TLiteral<"edit">]>; skillScopeEligible: Type.TBoolean; base: Type.TOptional<Type.TUnion<[Type.TLiteral<"cwd">, Type.TLiteral<"root">]>>; absent: Type.TOptional<Type.TUnion<[Type.TLiteral<"none">, Type.TLiteral<"base">]>>; patternParam: Type.TOptional<Type.TString>; }>>; ruleFace: Type.TObject<{ primaryParams: Type.TArray<Type.TString>; params: Type.TArray<Type.TString>; }>; approvalPreview: Type.TBoolean; validateInput: Type.TBoolean; deferred: Type.TBoolean; alwaysLoad: Type.TBoolean; /** Present iff the definition carries a model-gate class and survived the gate. */ modelGate: Type.TOptional<Type.TString>; renderHints: Type.TOptional<Type.TObject<{ userFacingName: Type.TOptional<Type.TString>; activity: Type.TOptional<Type.TString>; summaryParams: Type.TOptional<Type.TArray<Type.TString>>; resultCards: Type.TOptional<Type.TArray<Type.TString>>; approvalCard: Type.TOptional<Type.TUnion<[Type.TLiteral<"file-edit">, Type.TLiteral<"file-write">, Type.TLiteral<"notebook-edit">, Type.TLiteral<"shell">, Type.TLiteral<"fetch">, Type.TLiteral<"plan">, Type.TLiteral<"question">, Type.TLiteral<"generic">]>>; }>>; /** The ONE mount condition that fired for this instance. */ mountedBy: Type.TUnion<[Type.TLiteral<"hands">, Type.TLiteral<"backgroundTasks">, Type.TLiteral<"workflow">, Type.TLiteral<"delegation">, Type.TLiteral<"hostInternals">, Type.TLiteral<"peerLane">, Type.TLiteral<"scheduler">, Type.TLiteral<"memory">, Type.TLiteral<"scenario">, Type.TLiteral<"always">, Type.TLiteral<"optional">]>; }>>; /** sha256 prefix over the canonical COMPLETE rows — any axis / hint / contract / alias change moves it. */ digest: Type.TString; }>; export type ToolRoster = Static<typeof ToolRoster>; export declare const ToolRosterDelta: Type.TObject<{ /** The digest the consumer is expected to hold. A mismatch is NOT a rejection: the carried `roster` is the * new state regardless, only `summary` becomes unusable (the consumer records a skew and re-syncs). */ fromDigest: Type.TString; /** The whole post-change roster; positions come from it, never from the summary. */ roster: Type.TObject<{ schemaVersion: Type.TLiteral<1>; /** Run-time asserted equal to `entries.length`. */ count: Type.TInteger; /** Declaration order = the model's `tools[]` order; names unique (run-time asserted). */ entries: Type.TArray<Type.TObject<{ name: Type.TString; /** Always present (empty when the tool answers to no other name). */ aliases: Type.TArray<Type.TString>; source: Type.TUnion<[Type.TLiteral<"builtin">, Type.TLiteral<"caller">, Type.TLiteral<"host">, Type.TLiteral<"mcp">, Type.TLiteral<"a2a">, Type.TLiteral<"external">, Type.TLiteral<"synthetic">]>; /** Present iff `source` ∈ {mcp, a2a, external} (run-time validated at the mint). */ origin: Type.TOptional<Type.TObject<{ peer: Type.TString; declaredBy: Type.TOptional<Type.TUnion<[Type.TLiteral<"center">, Type.TLiteral<"file">, Type.TLiteral<"request">]>>; }>>; /** Undeclared ⇒ `legacy:<shapeDigest>` / `unversioned`. */ contract: Type.TObject<{ contractId: Type.TString; implementationRevision: Type.TString; }>; shapeDigest: Type.TString; wireSchemaDigest: Type.TString; /** `builtin:<name>` | `caller:<contractId>` | `mcp:<peer>/<tool>` | `a2a:<peer>/<skill>` | `external:<contractId>`. */ cardId: Type.TString; /** ENGINE-minted: sha256 prefix over the canonical tuple {source, peer, name, contractId}; unique per leg. */ capabilityId: Type.TString; /** The materialized schema's top-level properties (name + coarse type). */ inputKeys: Type.TArray<Type.TObject<{ name: Type.TString; type: Type.TUnion<[Type.TLiteral<"string">, Type.TLiteral<"number">, Type.TLiteral<"integer">, Type.TLiteral<"boolean">, Type.TLiteral<"object">, Type.TLiteral<"array">, Type.TLiteral<"null">, Type.TLiteral<"mixed">]>; }>>; effect: Type.TUnion<[Type.TLiteral<"read">, Type.TLiteral<"write">, Type.TLiteral<"idempotent">]>; effectProvenance: Type.TUnion<[Type.TLiteral<"declared">, Type.TLiteral<"caller">, Type.TLiteral<"synthetic">, Type.TLiteral<"default">]>; offload: Type.TBoolean; offloadThresholdChars: Type.TOptional<Type.TInteger>; compactable: Type.TBoolean; budgetExempt: Type.TBoolean; egress: Type.TBoolean; egressProvenance: Type.TUnion<[Type.TLiteral<"declared">, Type.TLiteral<"caller">, Type.TLiteral<"default">]>; irreversibility: Type.TOptional<Type.TUnion<[Type.TLiteral<"never">, Type.TLiteral<"maybe">, Type.TLiteral<"always">]>>; reversibilityProbe: Type.TBoolean; contentOrigin: Type.TUnion<[Type.TLiteral<"local">, Type.TLiteral<"execution">, Type.TLiteral<"external">]>; contentOriginProvenance: Type.TUnion<[Type.TLiteral<"declared">, Type.TLiteral<"server">, Type.TLiteral<"exempted">, Type.TLiteral<"default">]>; family: Type.TUnion<[Type.TLiteral<"shell">, Type.TLiteral<"file-read">, Type.TLiteral<"file-write">, Type.TLiteral<"search">, Type.TLiteral<"web">, Type.TLiteral<"delegate">, Type.TLiteral<"plan">, Type.TLiteral<"scaffold">, Type.TLiteral<"memory">, Type.TLiteral<"protocol">, Type.TLiteral<"other">]>; pathTarget: Type.TOptional<Type.TObject<{ param: Type.TString; aliases: Type.TArray<Type.TString>; access: Type.TUnion<[Type.TLiteral<"read">, Type.TLiteral<"create">, Type.TLiteral<"edit">]>; skillScopeEligible: Type.TBoolean; base: Type.TOptional<Type.TUnion<[Type.TLiteral<"cwd">, Type.TLiteral<"root">]>>; absent: Type.TOptional<Type.TUnion<[Type.TLiteral<"none">, Type.TLiteral<"base">]>>; patternParam: Type.TOptional<Type.TString>; }>>; ruleFace: Type.TObject<{ primaryParams: Type.TArray<Type.TString>; params: Type.TArray<Type.TString>; }>; approvalPreview: Type.TBoolean; validateInput: Type.TBoolean; deferred: Type.TBoolean; alwaysLoad: Type.TBoolean; /** Present iff the definition carries a model-gate class and survived the gate. */ modelGate: Type.TOptional<Type.TString>; renderHints: Type.TOptional<Type.TObject<{ userFacingName: Type.TOptional<Type.TString>; activity: Type.TOptional<Type.TString>; summaryParams: Type.TOptional<Type.TArray<Type.TString>>; resultCards: Type.TOptional<Type.TArray<Type.TString>>; approvalCard: Type.TOptional<Type.TUnion<[Type.TLiteral<"file-edit">, Type.TLiteral<"file-write">, Type.TLiteral<"notebook-edit">, Type.TLiteral<"shell">, Type.TLiteral<"fetch">, Type.TLiteral<"plan">, Type.TLiteral<"question">, Type.TLiteral<"generic">]>>; }>>; /** The ONE mount condition that fired for this instance. */ mountedBy: Type.TUnion<[Type.TLiteral<"hands">, Type.TLiteral<"backgroundTasks">, Type.TLiteral<"workflow">, Type.TLiteral<"delegation">, Type.TLiteral<"hostInternals">, Type.TLiteral<"peerLane">, Type.TLiteral<"scheduler">, Type.TLiteral<"memory">, Type.TLiteral<"scenario">, Type.TLiteral<"always">, Type.TLiteral<"optional">]>; }>>; /** sha256 prefix over the canonical COMPLETE rows — any axis / hint / contract / alias change moves it. */ digest: Type.TString; }>; /** Three pairwise-disjoint name lists; a `changed` name's new row is in `roster`. */ summary: Type.TObject<{ added: Type.TArray<Type.TString>; removed: Type.TArray<Type.TString>; changed: Type.TArray<Type.TString>; }>; }>; export type ToolRosterDelta = Static<typeof ToolRosterDelta>; /** The ONE name→row resolution every per-call reader shares (the call face, the park identity): the wire name first, * then an alias — the same order the dispatcher resolves a model's call. */ export declare function rosterEntryNamed(roster: ToolRoster, toolName: string): ToolRosterEntry | undefined; /** * The ONE tool-name canonicalization: the wire name of the row `name` resolves to on the roster ({@link rosterEntryNamed} * — the wire name first, then an alias, the dispatcher's order), or `name` itself when no row answers to it. The gate * reads a call's name through it before any policy runs, and a rule's tool name reaches a call exactly when it * canonicalizes to the same wire name (`ToolCallFace.names` is that set, minted here) — so a rule written against * an alias and one written against the wire name are one rule. */ export declare function rosterToolName(roster: ToolRoster | undefined, name: string): string; export { ruleNamesOf } from "./tool-name-readings.js"; /** design/388 B6 — the per-call face a gated request carries, read off a roster snapshot by name (aliases resolve). * `names` leads with the name the face was minted under (the model's spelling at the gate), then the wire name and the * other aliases — the ONE order of a call's names: a reader that must pick one of them by position (a `member` seat) * picks the spelling first, as the same call was judged before name resolution. */ export declare function toolCallFaceOf(roster: ToolRoster | undefined, toolName: string): import("./tool-policy.js").ToolCallFace | undefined; /** design/388 B18 — the identity members a park row carries, read off a roster snapshot by name; an empty object when * the name is not on the snapshot (the row then reads pre-identity and the resume takes the name-only path). */ export declare function parkedToolIdentity(roster: ToolRoster | undefined, toolName: string): { capabilityId?: string; contractId?: string; shapeDigest?: string; implementationRevision?: string; rosterDigest?: string; }; /** design/388 B6 × B18 — the FACE members a park row carries beside its identity: the display family, the declared * path target and the names the parked call was judged under. `names` is copied from the face the gate stamped on the * request (the model's spelling first — the row carries the judged fact, it is not re-derived); a request with no face * takes the roster's names for its row. A recheck that runs before the leg's roster exists (the pre-CAS resume-edit * re-adjudication) rebuilds the call face from the row through {@link parkedCallFaceOf}, so it judges the same object * the live gate judged. An empty object when the name is not on the snapshot (the row then reads pre-face and the * recheck falls to the catalog for the name). */ export declare function parkedToolFace(roster: ToolRoster | undefined, req: { readonly toolName: string; readonly face?: { readonly names?: readonly string[]; } | undefined; }): { family?: ToolFamily; pathTarget?: ToolRosterEntry["pathTarget"]; names?: readonly string[]; }; /** The live face a resumed park row is re-judged under: minted under the row's recorded spelling (`names[0]`) when that * spelling still resolves to the row's own tool on this roster, else under the row's wire name — a spelling that no * longer resolves, or that another row now owns, never lends the row another tool's face. */ export declare function parkedRowLiveFace(roster: ToolRoster | undefined, row: { readonly toolName: string; readonly names?: readonly string[]; }): import("./tool-policy.js").ToolCallFace | undefined; /** The call face a park row carries — present iff the row was minted with BOTH its face members and its four * identity members (one mint writes all of them; a row missing any is pre-388 and yields undefined, never a * partial face). This is the face every recheck of the row judges under, roster or no roster. */ export declare function parkedCallFaceOf(pending: { family?: ToolFamily; pathTarget?: ToolRosterPathTarget; names?: readonly string[]; capabilityId?: string; contractId?: string; shapeDigest?: string; implementationRevision?: string; }): import("./tool-policy.js").ToolCallFace | undefined; /** The optional `face` seat of a ToolCallRequest: present iff a face was read (a bare request carries no key). */ export declare function callFaceSeat(face: import("./tool-policy.js").ToolCallFace | undefined): { face?: import("./tool-policy.js").ToolCallFace; }; /** The four-tuple that decides "still the same tool" across a park (design/388 §2.5 boundary ②). */ export interface ToolIdentity { capabilityId: string; contractId: string; shapeDigest: string; implementationRevision: string; } export declare function toolIdentityOf(entry: ToolRosterEntry): ToolIdentity; /** The engine-minted capability identity: a STRUCTURED tuple (never a joined string — `a:b`+`c` and `a`+`b:c` * must not collide). Stable across legs for the same source/peer/name/contract. */ export declare function mintCapabilityId(t: { source: RosterSource; peer: string | null; name: string; contractId: string; }): string; export declare function rosterDigestOf(entries: readonly ToolRosterEntry[]): string; /** The materialized schema's top-level properties, in declaration order. */ export declare function inputKeysOf(schema: TSchema | undefined): { keys: ToolRosterEntry["inputKeys"]; scalar: Set<string>; }; /** The roster's KEY bounds over a schema (design/388 B20): a problem sentence, or undefined when every top-level key fits. * Shared by the caller declaration door (typed refusal) and the MCP intake (disclosed drop) — a key is never truncated. */ export declare function schemaKeyBoundProblem(schema: TSchema | undefined): string | undefined; /** The identity members of one roster row the wire bounds hold, as a DECLARATION (the door) or a MINTED row hands them. */ export interface RosterBoundMembers { name: string; aliases?: readonly string[]; /** An MCP/A2A mount's peer (the row's `origin.peer`) — a NAME on the roster, held to the wire name bound. */ peer?: string; contractId?: string; implementationRevision?: string; modelGate?: string; cardId?: string; } /** The typed refusal a member over its bound mints — the door's two codes, and the mint's own for the members no * declaration door names (`modelGate`, the derived `cardId`). Spelled out as literals (a consumer's tooling reads * the words); each is a member of {@link ToolDeclarationCode}, which every mint below satisfies. */ export type RosterBoundCode = "config.tool_name_too_long" | "config.tool_contract_too_long" | "config.tool_roster_bound"; /** * design/388 B20 / #626 ① — the ONE bound judge over a row's identity members: a problem `{ code, message }`, or * undefined when every member fits. Read by the declaration door (a `TaskSpec.tools` entry, refused before session * acquire) and by the row mint (every source — an MCP/A2A peer, a definition that reached the mint by a route the * door does not cover — refused before the row exists). A member over its bound is NEVER truncated onto the row: a * truncated identity is a different identity (`judgeParkedToolIdentity` compares it across a park; the card * namespace door reads it), and the schema's own bounds would then describe a row the mint never made. */ export declare function rosterMemberBoundProblem(m: RosterBoundMembers): { code: RosterBoundCode; message: string; } | undefined; /** * The rule vocabulary of ONE mounted instance (design/388 §2.2 ③ / D-3): DERIVED = the scalar top-level * keys ∪ the path target's `param` + aliases; a declared `params` list can only NARROW it (a declared * name outside the derived set is dropped — the L6 gate names it for a built-in); `primaryParams` = * declared, else the path target's `param` + aliases. */ export declare function ruleFaceOfInstance(schema: TSchema | undefined, declared: ToolRuleFace | undefined, pathTarget: ToolPathTarget | undefined): { primaryParams: string[]; params: string[]; }; /** What a mount site knows that the instance does not: where the tool came from and which condition fired. */ export interface RosterMountMeta { source: RosterSource; mountedBy: ToolMountTag; /** Required for `mcp` / `a2a` / `external`; refused otherwise. */ origin?: { peer: string; declaredBy?: "center" | "file" | "request"; }; } /** The face a mounted instance carries (forwarded by `defineTool`; read here by the same untyped-carry convention * every other axis reader in the runner uses). */ export interface MountedToolFace { effect?: ToolEffect; egress?: true; irreversibility?: "never" | "maybe" | "always"; reversibilityProbe?: unknown; contentOrigin?: ToolContentOrigin; offload?: boolean; offloadThresholdChars?: number; defer?: boolean; alwaysLoad?: boolean; mcpAlwaysLoad?: boolean; family?: ToolFamily; pathTarget?: ToolPathTarget; ruleFace?: ToolRuleFace; renderHints?: ToolRenderHints; compactable?: true; budgetExempt?: true; modelGate?: string; } export declare const faceOf: (t: AgentTool) => MountedToolFace; /** The leg facts the snapshot reads beside the instances — the safety scan's folds and the per-task knobs. */ export interface RosterSnapshotFacts { /** The leg's by-name effect map (the builder is its mount-time writer; the protocol folds also write it). */ effects: ReadonlyMap<string, ToolEffect>; egress: ReadonlySet<string>; irreversibilityTier: ReadonlyMap<string, "never" | "maybe" | "always">; reversibilityProbes: ReadonlyMap<string, unknown>; /** Names the defer classification ships as placeholders. */ deferred: ReadonlySet<string>; /** `TaskSpec.memory.trustedTools` — the exemption channel for an undeclared content class. */ trustedTools: ReadonlySet<string>; } export declare class RosterBuilder { #private; constructor(effects: Map<string, ToolEffect>); /** The mount array as a READ face. The order is the wire order. */ get tools(): readonly AgentTool[]; get length(): number; metaOf(tool: AgentTool): RosterMountMeta | undefined; /** Mount one instance at the tail. An instance that DECLARES an effect writes it into the leg's effect map — * the later mount under a name is the one the harness dispatches to (`snapshot`'s yield rule), so its * declaration is the map's truth for that name; a pre-mount registration (the hand band, the plan pair, an * MCP axis) stands only for names no mounted instance declares. ONE lane is different by construction: the * `scenario` lane's declarations were latched by the safety scan BEFORE any mount, on the synchronous * doors+scan stretch (a microtask cannot flip them) — so a scenario mount never re-reads its instance's * effect over a registered name; an engine lane's mount under that name still displaces it. */ mount(tool: AgentTool, meta: RosterMountMeta): void; /** An ENGINE-INJECTED instance the harness list carries outside the mount array (the ToolSearch lane): a roster * row — the model can call it — never a mount-array element (the disclosure lane owns that list and appends the * instance itself). Its row follows the mount array's rows in the snapshot; the same admission rules apply. */ mountEngineLane(tool: AgentTool, meta: RosterMountMeta): void; mountAll(tools: readonly AgentTool[], meta: RosterMountMeta): void; /** Remove every instance the predicate selects; returns them in mount order. */ unmountWhere(pred: (tool: AgentTool, index: number) => boolean): AgentTool[]; /** Swap the instance at `index` for another object standing for the SAME mount (a presentation re-render, a * wrapper): the mount meta carries over. */ replaceAt(index: number, tool: AgentTool): void; /** * Re-insert a NAME-PREFIX domain in place (the RefreshMcpTools seam): every instance whose name starts with * `prefix` is removed and `fresh` is spliced in at the domain's lowest former index (the wire prefix a * provider cache reads stays put); a domain that was not mounted appends at the tail. */ replaceDomain(prefix: string, fresh: readonly AgentTool[], meta: RosterMountMeta): { anchor: number; }; /** Mint the roster: one row per mounted NAME, in order. Two mounted instances under one name follow the * harness's own yield (the LATER mount is the one the model dispatches to — design/141 Q4, the * `auditToolCollisions` "yield" record): the roster carries the surviving instance's row at the * yielded instance's position and never a row per object. */ snapshot(facts: RosterSnapshotFacts): ToolRoster; } /** * The roster's one declaration rule on engine names: a row whose names (its wire name and the aliases that resolve to it, * {@link namesResolvingTo}) belong to TWO or more engine tools is refused — one tool answering as two engine tools would * have every per-call seat keyed on engine names choose between two definitions of the call. A row answering to one engine * tool under several of that tool's names, and an alias another row owns, are not counted twice. Undefined ⇒ none. */ export declare function rosterEngineNamesProblem(roster: ToolRoster): string | undefined; /** Which source a `TaskSpec.tools` entry mounts as: a definition carrying a CORE contract is a built-in the host chose * to mount; anything else is the caller's own tool. Identity follows the object, never the name. */ export declare function callerMountSource(tool: AgentTool): RosterSource; /** The card namespace a roster row owns (design/388 §2.2 ④) — ONE mint, read by the row and by the prepare door that * judges a caller's `renderHints.resultCards` against it: `builtin:<name>` for engine-owned definitions, * `<mcp|a2a>:<peer>/<tool>` for protocol tools, `<caller|external>:<contractId>` for everything the caller mounts. */ export declare function rosterCardId(source: RosterSource, toolName: string, peer: string | null, protocolTool: string, contractId: string): string; /** The card namespace a `TaskSpec.tools` entry will own once mounted — the same mint the row makes, so the prepare * door and the roster row cannot disagree about which namespace a caller card must live under. */ export declare function callerCardIdOf(tool: Pick<AgentTool, "name" | "parameters">): string; /** One row (design/388 §2.5). Every axis is read off the instance or the leg facts; nothing off a name table. */ export declare function mintRosterEntry(tool: AgentTool, meta: RosterMountMeta, facts: RosterSnapshotFacts): ToolRosterEntry; /** * The run-time delta seat: armed with the leg's minted roster and a re-snapshot closure at prepare, it * re-mints the roster after every run-time roster change (the RefreshMcpTools seam), diffs it against the * last published one and hands the delta to the stream (`tool_roster_delta`). Deltas published before a * sink subscribes are buffered (bounded) and flushed at subscription, so the first consumer sees them. */ export declare class ToolRosterDeltaSeat { #private; arm(current: ToolRoster, snapshot: () => ToolRoster): void; /** The last minted roster (the prepared one until a run-time change re-mints it). */ get current(): ToolRoster | undefined; /** Re-mint after a run-time change; publishes and returns the delta (undefined before arming). A * byte-identical re-mint still publishes: the consumer's summary is empty and its digest unchanged. */ republish(): ToolRosterDelta | undefined; /** Install the stream sink; anything published before is flushed in order. */ subscribe(sink: (delta: ToolRosterDelta) => void): void; /** The leg ended: drop the sink so a late republish never reaches a closed stream (it buffers, bounded, unread). */ unsubscribe(): void; /** Take the buffered deltas (a consumer that polls instead of subscribing). */ drain(): ToolRosterDelta[]; } /** * design/388 B15 — the rule-face resolver a leg hands the rule compiler: every roster row answers with its * derived vocabulary, the carried-but-non-scalar keys (so `Edit(edits:x)` reads `param_non_scalar`, not * `param_unknown`) and whether it names a path target; a name off the roster answers undefined. */ export declare function ruleFacesFromRoster(roster: ToolRoster): (toolName: string) => { primaryParams: readonly string[]; params: readonly string[]; nonScalar: readonly string[]; pathTargeting: boolean; } | undefined; /** The delta between two snapshots (design/388 §2.5): the whole `next` roster plus the name summary. */ export declare function diffToolRoster(prev: ToolRoster, next: ToolRoster): ToolRosterDelta; /** * The resume-side identity judgement (design/388 §2.5 boundary ②, B18/B19): a parked action carrying the * four identity members is redeemed only against a same-name row whose four members ALL match; a row * whose contract / shape / revision / source-peer moved is a replacement wearing the name, and the * resume refuses it (`resume.tool_contract_mismatch`, same family and disposition as * `resume.tool_unavailable`). A parked action minted BEFORE the identity members existed (all four absent) * follows the name-only path and is never widened by their absence. */ export declare function judgeParkedToolIdentity(pending: { capabilityId?: string; contractId?: string; shapeDigest?: string; implementationRevision?: string; }, row: ToolRosterEntry | undefined): "match" | "mismatch" | "name_only" | "absent"; /** The card-namespace check a CALLER declaration must pass at prepare (design/388 §2.2 ④): a `resultCards` * entry must live under the tool's own `cardId`; naming an engine card (`builtin:*`, or a bare engine card * type) is refused. Returns the offending entry, or undefined. */ export declare function offendingResultCard(hints: ToolRenderHints | undefined, cardId: string, engineCards: ReadonlySet<string>): string | undefined;