import type { CallToolResult } from '@modelcontextprotocol/sdk/types.js'; import type { LapDescribeResponse } from '../protocol.js'; import type { McpForwardedToolDescriptor } from './tools.js'; /** * Shared MCP tool executor. Both agent surfaces — the in-process * `@llui/agent` server-side MCP (`createAgentMcpServer`) and the * `llui-agent` HTTP bridge (`createBridgeServer`) — drive their * forwarded tools and connect flow through this module, parameterized * over a `LapCaller`. Previously each surface hand-rolled the * registration loop, `okResult`/`errorResult`, the connect prefetch, the * describe cache, and the schemaHash invalidation — and they had drifted * (different error phrasing; only the bridge cached describe + short- * circuited `describe_app`). Centralizing here makes both behave * identically. */ /** * `structuredContent` is what current Claude clients (Desktop + Claude * Code) consume preferentially when present — typed JSON instead of a * stringified blob. The `content` array stays as a `text` fallback so * older clients still see something sensible. */ export declare function okResult(body: unknown): CallToolResult; export declare function errorResult(msg: string): CallToolResult; /** Discriminated result of one LAP call, transport-independent. */ export type LapEnvelope = { ok: true; body: unknown; } | { ok: false; status: number; error: unknown; }; /** * Call a LAP endpoint. The server surface routes a synthetic WHATWG * Request through the agent core (`coreRouter`); the bridge surface * POSTs over HTTP (`forwardLap`). Both collapse to this shape. */ export type LapCaller = (path: string, args: object) => Promise; /** * A per-session cache of the app `description`. Populated on connect * (from the `/observe` bundle) and on every `describe_app` / `observe` * call; read to serve `describe_app` from cache and to diff schemaHash * for staleness. Each surface backs this with its own session store * (bridge: `BindingMap`; server: `McpSessionMap`). */ export interface DescribeCache { get(): LapDescribeResponse | null; set(d: LapDescribeResponse): void; } /** * Compare a freshly-fetched app description against the cached one and * decide whether the cached schema is now stale. A changed `schemaHash` * means the app's Msg/State schema was recompiled — cached * affordances/examples/payload shapes may no longer be valid, so the * caller is told to re-read before dispatching. Exported so the * invalidation policy is unit-testable in isolation. */ export declare function detectSchemaChange(prev: LapDescribeResponse | null, next: Pick): { changed: boolean; note: string | null; }; /** * Run one forwarded tool: serve `describe_app` from cache when warm, * otherwise dispatch to LAP, then cache + schemaHash-diff the * description-bearing responses (`describe_app`, `observe`) so a * mid-session recompile is surfaced to the LLM. */ export declare function executeForwardedTool(desc: McpForwardedToolDescriptor, args: object, call: LapCaller, cache: DescribeCache): Promise; /** * Shared tail of `connect_session`, after each surface has recorded its * own binding (bridge: url+token; server: tid+token). Prefetch the * `/observe` bundle so the LLM gets `{state, actions, description, * context}` in one call — no follow-up `observe` / `describe_app` / * `get_state` / `list_actions` on the first turn — cache the * description, and return the connected result. On failure, `onFailure` * unwinds the binding the caller set. */ export declare function executeConnect(call: LapCaller, cache: DescribeCache, onFailure: () => void): Promise; //# sourceMappingURL=executor.d.ts.map