UNPKG

@sema-agent/core

Version:

Stateless, task-oriented AI agent core

115 lines (114 loc) • 7.85 kB
/** * The MCP surface a run mounts, as a delegation tool reads it at spawn: per declared server, the tools of it that are mounted * right now (the wire name and the name the server itself knows the tool by), and the names of the aggregate tools no server * owns (the cross-server resource readers). Read off the run's LIVE roster, so a refresh that added or removed a server's * tools is what a child spawned after it inherits. * * The run fills it on `ToolExecuteContext.mountedMcp`; the delegation tool puts the same universe through the child's lists * and declares the child the servers they leave. */ import type { McpServerSpec } from "./mcp-server-spec.js"; import type { ToolContentOrigin } from "./tool-spec.js"; import type { McpConnectionPool } from "./mcp-connection-pool.js"; import type { McpInstructionsEntry } from "./prompt-section-seat.js"; /** The two names a server's `allowTools` carries to let the cross-server resource readers reach its resources (a server whose allowlist omits one is left out of that reader). */ export declare const MCP_RESOURCE_LIST_ALLOW = "list_resources"; export declare const MCP_RESOURCE_READ_ALLOW = "read_resource"; /** The canonical names of the resource tools (the trio: list-all / read-one / list-under-a-directory). They belong to no one server: each aggregates the resources of every connected server that advertises them. */ export declare const LIST_MCP_RESOURCES = "ListMcpResourcesTool"; export declare const READ_MCP_RESOURCE = "ReadMcpResourceTool"; export declare const READ_MCP_RESOURCE_DIR = "ReadMcpResourceDirTool"; /** Does the valve (`leaves`: its one predicate) leave at least one of the cross-server resource tools? While it does, a connected server may contribute to them whatever it lists. */ export declare function resourceFacesLeft(leaves: (tool: { readonly name: string; }) => boolean): boolean; /** * Are a server's instructions about something the run holds? Yes when the run's roster (`held`) holds a tool of the server's prefix * domain the valve leaves, or a cross-server resource tool the valve leaves (the aggregates exist only if some connected server * advertised resources, and which one is not recorded, so a held face keeps the instructions of every server); a server whose own * listing (`listed` — any superset of it) has no tool at all (instructions only) is taught while any resource face is left. Read off * the roster, a tool the deployment's `toolFaces` overlay refused counts as what it is — not held. A server the run holds nothing of * is not taught: its instructions describe tools the model will not hold. * * The one answer to "should the model be taught them": the initial instructions block and the delta lane's adds after a roster change read * it. Whether the model HOLDS them is the ledger's ({@link instructionsTold}), which the disconnect line reads. */ export declare function instructionsTaught(leaves: (tool: { readonly name: string; readonly aliases?: readonly string[]; }) => boolean, serverName: string, held: ReadonlyArray<{ readonly name: string; readonly aliases?: readonly string[]; }>, listed: ReadonlyArray<{ readonly name: string; }>): boolean; /** A materialization's instructions delta lane (`MaterializedMcp.instructionsDelta`): what the run drains at its next boundary. */ export interface InstructionsLane { pendingAdds: McpInstructionsEntry[]; pendingRemovals: string[]; } /** Are this server's instructions in the model's context now? */ export declare function instructionsTold(lane: InstructionsLane, server: string): boolean; /** A dial's default: the server's instructions are taught (a materialization alone takes every entry it returns as taught, until a run states its block). */ export declare function toldOnDial(lane: InstructionsLane, server: string): void; /** The run's start: the stable block is what the model is told. A removal already queued for a server outside the block names instructions the model * never held, so it is withdrawn; a server inside the block with a removal queued is not in context (the frame will retract it). */ export declare function toldAtStart(lane: InstructionsLane, servers: ReadonlySet<string>): void; /** Take this server's unread adds off the lane; a first copy that never reached the model leaves the ledger with it. */ export declare function withdrawInstructionAdds(lane: InstructionsLane, server: string): void; /** Queue this server's current text (superseding an unread copy). In context already ⇒ stays so; otherwise a first copy, queued. */ export declare function tellInstructions(lane: InstructionsLane, entry: McpInstructionsEntry): void; /** The server's connection is gone: unread adds are withdrawn, and the model is told its instructions no longer apply only if it holds them. */ export declare function retractInstructions(lane: InstructionsLane, server: string): void; /** A re-dial that connected: a retraction still unread never reached the model, so it is withdrawn and the text the model holds stands. */ export declare function unretractInstructions(lane: InstructionsLane, server: string): void; /** One declared MCP server and its mounted tools. */ export interface MountedMcpServer { readonly server: McpServerSpec; readonly tools: ReadonlyArray<{ readonly name: string; readonly remoteName: string; }>; } /** What a run mounts of MCP: its servers, and the aggregate tool names that belong to none of them. */ export interface MountedMcp { readonly servers: ReadonlyArray<MountedMcpServer>; readonly aggregate: ReadonlyArray<string>; /** The run tree's connection pool: a child that inherits the mount leases its connections from it. */ readonly pool?: McpConnectionPool; } /** A roster entry as far as this reading goes. */ interface RosterEntry { readonly name: string; readonly mcpRemoteName?: string; } /** * The names among `names` that belong to the declared server `serverName`: those under its prefix domain (`mcp__<server>__`), which * is the roster's own definition of a server's tools (the live roster swaps a server's tools by it). Handed a roster's names, it is * the ONE answer to "how many tools of this server does the run hold" — the re-dial's receipt and notice, the content-class * declaration line, the wiring manifest's per-server count and {@link mountedMcpOf} all read it, so no two of them can count * differently. Handed a server's own listing it answers what the server offers, which is not a mount count. */ export declare function toolNamesOfServer(names: Iterable<string>, serverName: string): string[]; /** * Read the run's MCP surface off its roster. `declared` is the run's frozen server declarations; `aggregateNames` the names of the * tools its materialization minted that no server owns. A tool is a server's when its wire name sits under the server's prefix * domain and carries the remote name the mint recorded on it; a tool of a server that failed to connect is simply not mounted, * so that server has no tools here and a child is not declared it. */ export declare function mountedMcpOf(input: { readonly declared: ReadonlyArray<McpServerSpec> | undefined; readonly roster: ReadonlyArray<RosterEntry>; readonly aggregateNames: ReadonlySet<string>; readonly pool?: McpConnectionPool; }): MountedMcp; /** * The MCP tools of a mount as pool rows (name and the server's declared content class) — what the memory content-origin face adds to * a delegation tool's pool when its children inherit the mount. The rows are the universe the spawn's lists are read over, so * "can the child reach an MCP tool" has one answer. */ export declare function mountedMcpPoolRows(mounted: MountedMcp): Array<{ name: string; contentOrigin?: ToolContentOrigin; }>; export {};