@sema-agent/core
Version:
Stateless, task-oriented AI agent core
115 lines (114 loc) • 7.85 kB
TypeScript
/**
* 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 {};