@hediet/linkrpc-mcp 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +82 -0
- package/dist/chunks/server-Bquqk9Mk.d.ts +248 -0
- package/dist/chunks/server-C4ZM6bfK.js +2530 -0
- package/dist/chunks/server-C4ZM6bfK.js.map +1 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +23 -0
- package/dist/cli.js.map +1 -0
- package/dist/guestMain.d.ts +1 -0
- package/dist/index.d.ts +229 -0
- package/dist/index.js +2 -0
- package/dist/node.d.ts +121 -0
- package/dist/node.js +163 -0
- package/dist/node.js.map +1 -0
- package/dist/src-guest-guestMain.js +168 -0
- package/dist/src-guest-guestMain.js.map +1 -0
- package/package.json +49 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server-C4ZM6bfK.js","names":["spawnCommand","connectionDtsText","SdkMcpServer"],"sources":["../../../../packages-private/linkrpc-client/src/localHub.ts","../../../../packages-private/linkrpc-client/src/connect.ts","../../../../packages-private/linkrpc-client/src/principal.ts","../../../../packages-private/linkrpc-client/src/hubSigning.ts","../../src/connectionPool.ts","../../src/senderProvider.ts","../../src/grants.ts","../../src/connectionDts.ts","../../src/sandbox.ts","../../src/taskRegistry.ts","../../src/explore.ts","../../src/resultPresentation.ts","../../src/server.ts"],"sourcesContent":["import { type Identity, InMemoryManagedIdentity, type IMessageTransport, TransportPair } from '@hediet/linkrpc';\nimport { Hub, HubConnectionAcceptor, anonymousHandler, createHubServiceInterfaces } from '@hediet/linkrpc-hub/hub/server/client';\nimport {\n type AttachedLink,\n registerHubServices,\n registerIdentityServices,\n RootOverlay,\n} from '@hediet/linkrpc-hub/hub/server/client';\nimport { type NodeSocketTransport, SocketServer } from '@hediet/linkrpc-hub/hub/server/node';\nimport type { RootProvision } from '@hediet/linkrpc-hub/hub/server/client';\nimport { type EndpointCommand, loadOrCreateIdentity } from '@hediet/linkrpc/node';\nimport { randomBytes } from 'node:crypto';\nimport * as fs from 'node:fs';\nimport * as os from 'node:os';\nimport * as path from 'node:path';\nimport { spawnCommand } from '@hediet/linkrpc-hub/spawn';\n\n/** Default serviceId namespace the local-hub child may claim (and sees via `hubGrantedServiceId::get`). */\nconst DEFAULT_LOCAL_NAMESPACE = 'local';\n\n/** Re-export for backwards compatibility within the CLI. */\nexport const LOCAL_NAMESPACE = DEFAULT_LOCAL_NAMESPACE;\n\n/** Subfolder (under the linkrpc data dir) holding provisioned identity slots. */\nconst PROVISION_SUBDIR = 'provisioned-identities';\n\n/** Provisioned slots untouched for longer than this are swept on next run. */\nconst PROVISION_MAX_AGE_MS = 30 * 24 * 60 * 60 * 1000; // 30 days\n\n/**\n * A running in-process hub plus the child it spawned. The CLI connects to\n * `socketPath` (presenting `token`) exactly as it would to any socket hub, and\n * calls {@link dispose} to tear the child + server down.\n */\nexport interface LocalHub {\n readonly socketPath: string;\n readonly token: string;\n dispose(): void;\n}\n\nexport interface StartLocalHubOptions {\n /** Command to spawn as the hub participant. */\n readonly command: EndpointCommand;\n /**\n * When set, the hub serves a *persistent* managed identity loaded from this\n * slot id (reused across runs). Omitted → a fresh ephemeral identity.\n */\n readonly provisionSlot: string | undefined;\n /** Extra env vars injected into the child (the hub's LINKRPC_* vars win). */\n readonly env?: Readonly<Record<string, string>>;\n /** Working directory for the spawned child. */\n readonly cwd?: string;\n /** Max time to wait for the child to claim its namespace. Default 30s. */\n readonly readyTimeoutMs?: number;\n}\n\n/**\n * Start an in-process hub on a private socket, spawn `command` as a participant\n * (handing it the socket + token via `LINKRPC_ENDPOINT` / `LINKRPC_TOKEN`), and\n * resolve once the child has registered a service under {@link LOCAL_NAMESPACE}.\n *\n * The hub is single-tenant and local: no claim policy (every well-formed claim\n * is allowed) and no provenance. Identity is either ephemeral (fresh per run)\n * or, when `provisionSlot` is set, a persisted managed identity so the child's\n * HPKE wrap/unwrap keys survive across runs.\n */\nexport async function startLocalHub(opts: StartLocalHubOptions): Promise<LocalHub> {\n const resolveIdentity = _makeIdentityResolver(opts.provisionSlot);\n const grantedNs = DEFAULT_LOCAL_NAMESPACE;\n\n const hub = new Hub();\n createHubServiceInterfaces(hub);\n\n const socketPath = SocketServer.allocSocketPath();\n const token = randomBytes(16).toString('hex');\n\n const socketServer = await SocketServer.start({\n endpoint: socketPath,\n });\n\n const acceptor = new HubConnectionAcceptor<NodeSocketTransport>({\n server: socketServer,\n hub,\n // No policy → allow every well-formed claim (single-tenant local hub).\n // A single anonymous handler admits the child and provisions its granted\n // namespace and (optionally) a persisted managed identity.\n handlers: [\n anonymousHandler({\n grantedServiceIdNamespace: grantedNs,\n ...(resolveIdentity ? { resolveIdentity } : {}),\n } satisfies RootProvision),\n ],\n });\n\n const child = spawnCommand(opts.command, {\n stdio: ['inherit', 'inherit', 'inherit'],\n env: { ...process.env, ...opts.env, LINKRPC_ENDPOINT: socketPath, LINKRPC_TOKEN: token },\n ...(opts.cwd !== undefined ? { cwd: opts.cwd } : {}),\n });\n let childExited = false;\n child.once('exit', () => {\n childExited = true;\n });\n\n const dispose = (): void => {\n if (!child.killed) child.kill();\n acceptor.dispose();\n socketServer.dispose();\n if (process.platform !== 'win32') {\n try {\n fs.unlinkSync(socketPath);\n } catch { /* ignore */ }\n }\n };\n\n try {\n await _waitForClaim(hub, grantedNs, () => childExited, opts.readyTimeoutMs ?? 30_000);\n } catch (e) {\n dispose();\n throw e;\n }\n\n return { socketPath, token, dispose };\n}\n\n/**\n * A **RootOverlay** fronting a spawned `cmd-env` child, without a routing hub.\n * The child's root-form calls (`identity::*`, `hubGrantedServiceId::*`,\n * `hubrpc.directory`, `hubAccess`) are served locally on {@link RootOverlay.root};\n * every prefixed request/response is relayed verbatim over {@link uplink}.\n *\n * This is the tunnel's target front end: the tunnel drives {@link uplink} as the\n * \"parent\" so forwarded requests reach the child directly through the overlay\n * splitter. Unlike {@link startLocalHub} there is no hub, no `hub` service id,\n * and no claim to wait for — a plain service target works without the hub-claim\n * dance — while `--provision-identity` still gets `identity::*` served locally.\n */\nexport interface LocalOverlay {\n /** Transport carrying forwarded (prefixed) traffic to/from the participant. */\n readonly uplink: IMessageTransport;\n dispose(): void;\n}\n\nexport interface StartLocalOverlayOptions {\n /** Command to spawn as the participant. */\n readonly command: EndpointCommand;\n /**\n * When set, `identity::*` is served from a persistent managed identity\n * loaded from this slot (reused across runs). Omitted → no identity served.\n */\n readonly provisionSlot: string | undefined;\n /** Extra env vars injected into the child. */\n readonly env?: Readonly<Record<string, string>>;\n /** Working directory for the spawned child. */\n readonly cwd?: string;\n /**\n * ServiceId namespace surfaced to the child via `hubGrantedServiceId::get`\n * and freely claimable through `hubGrantedServiceId::register`.\n */\n readonly grantedNamespace: string;\n}\n\n/**\n * The overlay's claim front door has no routing table to write: the tunnel owns\n * the real claim on the source hub, and the splitter relays every uplink request\n * to the child regardless. So `hubGrantedServiceId::register` succeeds as a\n * no-op through this stub link.\n */\nconst _noopUpstream: AttachedLink = {\n claimPrefix: () => { },\n releasePrefix: () => false,\n edgeId: 'overlay-uplink',\n dispose: () => { },\n};\n\nexport async function startLocalOverlay(opts: StartLocalOverlayOptions): Promise<LocalOverlay> {\n const resolveIdentity = _makeIdentityResolver(opts.provisionSlot);\n\n const socketPath = SocketServer.allocSocketPath();\n const token = randomBytes(16).toString('hex');\n const socketServer = await SocketServer.start({ endpoint: socketPath });\n\n const accepted = new Promise<NodeSocketTransport>((resolve) => {\n socketServer.setConnectionHandler((t) => resolve(t));\n });\n\n const child = spawnCommand(opts.command, {\n // The child speaks linkrpc over the socket, so its stdio stays free for\n // diagnostics — inherit it so a child that fails to start is visible.\n stdio: ['ignore', 'inherit', 'inherit'],\n env: { ...process.env, ...opts.env, LINKRPC_ENDPOINT: socketPath, LINKRPC_TOKEN: token },\n ...(opts.cwd !== undefined ? { cwd: opts.cwd } : {}),\n });\n\n const pair = new TransportPair();\n const overlay = new RootOverlay({ uplink: pair.a });\n registerHubServices(overlay.root, _noopUpstream, { grantedServiceIdNamespace: opts.grantedNamespace });\n if (resolveIdentity !== undefined) {\n registerIdentityServices(overlay.root, { resolveIdentity });\n }\n\n const dispose = (): void => {\n if (!child.killed) child.kill();\n overlay.dispose();\n pair.a.dispose();\n pair.b.dispose();\n socketServer.dispose();\n if (process.platform !== 'win32') {\n try {\n fs.unlinkSync(socketPath);\n } catch { /* ignore */ }\n }\n };\n\n const childTransport = await Promise.race([\n accepted,\n new Promise<never>((_resolve, reject) => {\n child.once('exit', (code) =>\n reject(new Error(`overlay: cmd-env child exited (code ${code ?? '?'}) before connecting`)),\n );\n }),\n ]).catch((err: unknown) => {\n dispose();\n throw err;\n });\n\n overlay.connectParticipant(childTransport);\n return { uplink: pair.b, dispose };\n}\n\n/**\n * Build the hub's `resolveIdentity`, or `undefined` when no identity should be\n * provided. Without `provisionSlot` the hub serves no identity at all — a child\n * that needs `identity::*` will fail. With it, a single persisted managed\n * identity is shared by all connections (stale slots swept first), so the\n * child's HPKE wrap/unwrap keys survive across runs.\n */\nfunction _makeIdentityResolver(\n provisionSlot: string | undefined,\n): (() => Promise<Identity>) | undefined {\n if (provisionSlot === undefined) {\n return undefined;\n }\n\n const dir = _provisionDir();\n _sweepProvisionedIdentities(dir);\n let shared: Promise<Identity> | undefined;\n return () => {\n if (!shared) {\n shared = (async () => {\n const persisted = await loadOrCreateIdentity({ id: provisionSlot, storeDir: dir });\n return new InMemoryManagedIdentity(persisted.keypair, persisted.wrapKeypair);\n })();\n }\n return shared;\n };\n}\n\n/** Resolve the slot id for a `--provision-identity` / `--provision-identity-slot` run. */\nexport function resolveProvisionSlot(\n explicitSlot: string | undefined,\n provisionIdentity: boolean,\n commandString: string,\n): string | undefined {\n if (explicitSlot !== undefined) {\n return explicitSlot;\n }\n if (provisionIdentity) {\n return JSON.stringify({ cwd: process.cwd(), cmdStr: commandString });\n }\n return undefined;\n}\n\n/** Dedicated provisioned-identity folder (sibling of linkrpc's user identities). */\nfunction _provisionDir(): string {\n const home = os.homedir();\n let base: string;\n if (process.platform === 'win32') {\n base = process.env.APPDATA ?? path.join(home, 'AppData', 'Roaming');\n } else if (process.platform === 'darwin') {\n base = path.join(home, 'Library', 'Application Support');\n } else {\n base = process.env.XDG_CONFIG_HOME ?? path.join(home, '.config');\n }\n return path.join(base, 'linkrpc', PROVISION_SUBDIR);\n}\n\n/** Delete provisioned identity files whose mtime is older than the max age. */\nfunction _sweepProvisionedIdentities(dir: string): void {\n let entries: string[];\n try {\n entries = fs.readdirSync(dir);\n } catch {\n return; // dir absent → nothing to sweep\n }\n const cutoff = Date.now() - PROVISION_MAX_AGE_MS;\n for (const name of entries) {\n if (!name.endsWith('.json')) continue;\n const file = path.join(dir, name);\n try {\n if (fs.statSync(file).mtimeMs < cutoff) fs.unlinkSync(file);\n } catch { /* ignore */ }\n }\n}\n\n/** Resolve once the child claims `prefix` (or a sub-prefix), else reject. */\nfunction _waitForClaim(\n hub: Hub,\n prefix: string,\n childExited: () => boolean,\n timeoutMs: number,\n): Promise<void> {\n const deadline = Date.now() + timeoutMs;\n return new Promise<void>((resolve, reject) => {\n const check = (): void => {\n if (hub.claimedPrefixes().some((p) => p === prefix || p.startsWith(`${prefix}/`))) {\n resolve();\n return;\n }\n if (childExited()) {\n reject(new Error('connect: command exited before registering a service'));\n return;\n }\n if (Date.now() >= deadline) {\n reject(new Error(`connect: timed out waiting for command to register a service under '${prefix}'`));\n return;\n }\n setTimeout(check, 50);\n };\n check();\n });\n}\n","import {\n type CapProvider,\n type Channel,\n type IMessageTransport,\n type MessageTransportTrace,\n type IRequestHandler,\n type IRequestSender,\n JsonRpcChannel,\n type OneShotCapStaging,\n type Principal,\n RpcError,\n type SigningCallCtx,\n SigningSender,\n traceMessageTransport,\n} from '@hediet/linkrpc';\nimport {\n connectNdjson,\n type EndpointCommand,\n openWebSocket,\n runInitializeHandshake,\n WebSocketTransport,\n} from '@hediet/linkrpc/node';\nimport { tapTransport } from '@hediet/linkrpc-hub/hub/server/transit';\nimport { spawnCommand } from '@hediet/linkrpc-hub/spawn';\nimport * as net from 'node:net';\nimport type { ResolvedEndpoint } from './endpoint';\nimport { startLocalHub, startLocalOverlay } from './localHub';\n\n// `spawnCommand` is owned by the shared hub engine; the CLI re-exports it so\n// existing `./connect` import sites keep working. (Socket-path allocation now\n// lives on `SocketServer.allocSocketPath`.)\nexport { spawnCommand };\n\n/**\n * Mutable signing config consulted per-call by the {@link SigningSender}\n * wrapping a {@link CliConnection.channel}. Starts empty; `setupHubSigning`\n * installs a {@link Principal} (identity + persistent caps) and an optional\n * {@link OneShotCapStaging} policy. Mutating a field takes effect on the\n * next outbound call.\n */\nexport interface CliSigning {\n principal?: Principal;\n oneShotCaps?: OneShotCapStaging;\n capProvider?: CapProvider;\n}\n\n/**\n * Tee every JSON-RPC message crossing the connection's transport to a line\n * sink, rendered like the hub's \"Flows\" view. For inspecting a *direct*\n * connection that never routes through a local hub.\n */\nexport interface ConnectLogOptions {\n readonly log?: (line: string) => void;\n /** Edge label for the far end in the rendered path. Default `\"peer\"`. */\n readonly remoteLabel?: string;\n /** Max JSON length per payload before truncation. Default 200. */\n readonly maxPayload?: number;\n /** Raw message trace, attached before any transport handshake. */\n readonly trace?: MessageTransportTrace;\n}\n\n/**\n * A live linkrpc connection plus the underlying child / socket. The CLI\n * owns both so it can wait for the channel to drain before tearing the\n * peer down.\n *\n * `signing` is the mutable holder consulted by the {@link SigningSender}\n * wrapping `channel`. Starts empty (unsigned plain JSON-RPC); populated\n * by `setupHubSigning`. User code with its own signing requirements can\n * mutate it directly.\n */\nexport interface CliConnection {\n readonly channel: IRequestSender<SigningCallCtx>;\n readonly signing: CliSigning;\n /**\n * The underlying signing {@link Channel} (sender + inbound binding seam).\n * Hand this to `new LinkRpcConnection(conn.rpcChannel)` when a command needs\n * to **serve** typed interfaces over the connection (e.g. `mcp-forward`\n * registers `mcpForwardInterface` + `enableReflection`). Constructing a\n * `LinkRpcConnection` from it binds the inbound handler, so do not also use\n * {@link setRequestHandler} on the same connection — they are mutually\n * exclusive inbound modes (last writer wins).\n */\n readonly rpcChannel: Channel<unknown, SigningCallCtx>;\n /**\n * Bind the raw inbound request/notification handler for this connection.\n * Lets a command (e.g. `tunnel`) receive *all* requests the peer routes\n * here, bypassing the typed {@link LinkRpcConnection} dispatch. Pass\n * `undefined` to detach.\n */\n setRequestHandler(handler: IRequestHandler | undefined): void;\n /** Close the transport, reject pending requests, kill the child (cmd) or destroy the socket (hub). */\n close(): void;\n}\n\nexport async function connect(\n endpoint: ResolvedEndpoint,\n log?: ConnectLogOptions,\n): Promise<CliConnection> {\n switch (endpoint.kind) {\n case 'cmd-stdio':\n return _connectCmdStdio(endpoint.command, endpoint.env, endpoint.cwd, log);\n case 'cmd-env':\n return _connectCmdEnv(endpoint.command, endpoint.provisionSlot, endpoint.env, endpoint.cwd, log);\n case 'ws':\n return _connectWs(endpoint, log);\n case 'ws-no-init':\n return _connectWs(endpoint, log);\n case 'socket':\n return _connectSocket(endpoint.path, endpoint.token, log);\n }\n}\n\n/**\n * Spawn a child from a command spec. `{ command }` is run through the OS shell\n * (so quoting / splitting follows the shell's rules); `{ argv }` is run\n * directly (no shell), except on Windows where `.cmd` shims need one.\n */\nasync function _connectCmdStdio(\n command: EndpointCommand,\n env: Readonly<Record<string, string>> | undefined,\n cwd: string | undefined,\n log?: ConnectLogOptions,\n): Promise<CliConnection> {\n const child = spawnCommand(command, {\n stdio: ['pipe', 'pipe', 'inherit'],\n ...(env !== undefined ? { env: { ...process.env, ...env } } : {}),\n ...(cwd !== undefined ? { cwd } : {}),\n });\n if (!child.stdin || !child.stdout) {\n throw new Error('connect: child process exposes no stdio');\n }\n const { transport } = await connectNdjson({\n input: child.stdout,\n output: child.stdin,\n onClose: () => {\n if (!child.killed) child.kill();\n },\n trace: log?.trace,\n });\n return _makeCliConnection(transport, () => {\n if (!child.killed) child.kill();\n }, log);\n}\n\n/**\n * Start a private in-process hub, spawn the child as a participant, then\n * connect to the hub's socket. The child registers its services against the\n * hub exactly as it would against a remote one; we tear the hub + child down\n * when the connection closes.\n */\nasync function _connectCmdEnv(\n command: EndpointCommand,\n provisionSlot: string | undefined,\n env: Readonly<Record<string, string>> | undefined,\n cwd: string | undefined,\n log?: ConnectLogOptions,\n): Promise<CliConnection> {\n return connectViaLocalHub({ command, provisionSlot, env, cwd, log });\n}\n\n/**\n * Spawn a child under an in-process local hub (`startLocalHub`) and connect\n * to that hub over a socket. Backs the standard `cmd-env` endpoint path; the\n * hub + child are torn down when the connection closes.\n */\nexport async function connectViaLocalHub(opts: {\n readonly command: EndpointCommand;\n readonly provisionSlot: string | undefined;\n readonly env?: Readonly<Record<string, string>>;\n readonly cwd?: string;\n readonly log?: ConnectLogOptions;\n}): Promise<CliConnection> {\n const hub = await startLocalHub({\n command: opts.command,\n provisionSlot: opts.provisionSlot,\n env: opts.env,\n ...(opts.cwd !== undefined ? { cwd: opts.cwd } : {}),\n });\n try {\n const conn = await _connectSocket(hub.socketPath, hub.token, opts.log);\n return {\n ...conn,\n close: () => {\n conn.close();\n hub.dispose();\n },\n };\n } catch (e) {\n hub.dispose();\n throw e;\n }\n}\n\n/**\n * Connect to a spawned `cmd-env` child through a {@link startLocalOverlay}\n * RootOverlay instead of a full local hub. Root-form calls (`identity::*`,\n * `hubGrantedServiceId::*`, `hubrpc.directory`, `hubAccess`) are served locally;\n * every prefixed request/response is relayed over the returned connection's\n * channel. Used by `tunnel --target-endpoint-cmd`: the tunnel forwards each\n * claimed request onto this channel and the overlay delivers it to the child —\n * no hub, no `hub` service id, no claim-wait, but `identity::*` still served so\n * `--provision-identity` targets work.\n */\nexport async function connectViaRootOverlay(opts: {\n readonly command: EndpointCommand;\n readonly provisionSlot: string | undefined;\n readonly env?: Readonly<Record<string, string>>;\n readonly cwd?: string;\n readonly grantedNamespace: string;\n readonly log?: ConnectLogOptions;\n}): Promise<CliConnection> {\n const overlay = await startLocalOverlay({\n command: opts.command,\n provisionSlot: opts.provisionSlot,\n ...(opts.env !== undefined ? { env: opts.env } : {}),\n ...(opts.cwd !== undefined ? { cwd: opts.cwd } : {}),\n grantedNamespace: opts.grantedNamespace,\n });\n return _makeCliConnection(overlay.uplink, overlay.dispose, opts.log);\n}\n\nfunction _connectWs(\n endpoint: Extract<ResolvedEndpoint, { kind: 'ws' | 'ws-no-init'; }>,\n log?: ConnectLogOptions,\n): Promise<CliConnection> {\n return openWebSocket(endpoint.url).then(async (ws) => {\n const closeWs = () => {\n try {\n ws.close();\n } catch { /* ignore */ }\n };\n const baseTransport = new WebSocketTransport(ws, closeWs);\n const transport = log?.trace === undefined\n ? baseTransport\n : traceMessageTransport(baseTransport, log.trace);\n if (endpoint.kind === 'ws') {\n try {\n await runInitializeHandshake(transport, {\n kind: 'client',\n token: endpoint.token ?? '',\n });\n } catch (err) {\n transport.dispose();\n closeWs();\n throw err;\n }\n }\n return _makeCliConnection(transport, closeWs, log);\n });\n}\n\nasync function _connectSocket(\n socketPath: string,\n token: string | undefined,\n log?: ConnectLogOptions,\n): Promise<CliConnection> {\n const socket = net.createConnection(socketPath);\n await new Promise<void>((resolve, reject) => {\n const onConnect = () => {\n socket.removeListener('error', onError);\n resolve();\n };\n const onError = (error: Error) => {\n socket.removeListener('connect', onConnect);\n socket.destroy();\n reject(error);\n };\n socket.once('connect', onConnect);\n socket.once('error', onError);\n });\n socket.on('error', () => socket.destroy());\n const { transport } = await connectNdjson({\n input: socket,\n output: socket,\n onClose: () => socket.destroy(),\n initialize: { kind: 'client', token: token ?? '' },\n trace: log?.trace,\n });\n return _makeCliConnection(transport, () => socket.destroy(), log);\n}\n\n/**\n * In-memory connection — for tests. The caller hands us a transport already\n * wired to a server-side channel (typically via `TransportPair`).\n */\nexport function connectViaTransport(transport: IMessageTransport): CliConnection {\n return _makeCliConnection(transport, () => { });\n}\n\nfunction _makeCliConnection(\n transport: IMessageTransport,\n onClose: () => void,\n log?: ConnectLogOptions,\n): CliConnection {\n const tapped = log?.log === undefined\n ? transport\n : tapTransport(transport, {\n log: log.log,\n localLabel: 'cli',\n remoteLabel: log.remoteLabel ?? 'peer',\n ...(log.maxPayload !== undefined ? { maxPayload: log.maxPayload } : {}),\n });\n const signing: CliSigning = {};\n const wrapped = SigningSender.wrapChannel(\n JsonRpcChannel.create(tapped),\n signing,\n );\n const channel = wrapped.sender;\n return {\n channel,\n rpcChannel: wrapped,\n signing,\n setRequestHandler: (handler) => wrapped.setRequestHandler(handler),\n close: () => {\n channel.close();\n onClose();\n },\n };\n}\n\nexport { RpcError };\n","import type { IRequestSender, Principal, SigningCallCtx } from '@hediet/linkrpc';\nimport {\n createManagedPrincipal,\n createSelfManagedPrincipal,\n createSelfManagedPrincipalFromFile,\n} from '@hediet/linkrpc/node';\n\n/**\n * Identity slot the managed-with-fallback default falls back to when the peer\n * does not offer a managed identity overlay (e.g. a plain stdio server). Maps\n * to the same on-disk slot `logout` clears.\n */\nexport const MANAGED_FALLBACK_USER_ID = 'hubrpc-cli';\n\n/**\n * Which identity the CLI signs outbound calls with, parsed from `--principal`:\n * - `managed` — the peer signs for us via its `identity::*` overlay; falls\n * back to a local self-managed `{@link MANAGED_FALLBACK_USER_ID}` keypair\n * when no overlay is available.\n * - `user:<id>` — a local Ed25519 keypair stored in the per-user data dir,\n * keyed by `<id>`.\n * - `file:<path>` — a local Ed25519 keypair stored at exactly `<path>`.\n */\nexport type PrincipalSpec =\n | { readonly kind: 'managed'; }\n | { readonly kind: 'user'; readonly id: string; }\n | { readonly kind: 'file'; readonly path: string; };\n\n/**\n * Parse a `--principal` value. `undefined` and `managed` both yield the\n * managed-with-fallback default. Throws on malformed input.\n */\nexport function parsePrincipalSpec(raw: string | undefined): PrincipalSpec {\n if (raw === undefined || raw === 'managed') return { kind: 'managed' };\n if (raw.startsWith('user:')) {\n const id = raw.slice('user:'.length);\n if (id === '') throw new Error('--principal \"user:<id>\" requires a non-empty id');\n return { kind: 'user', id };\n }\n if (raw.startsWith('file:')) {\n const path = raw.slice('file:'.length);\n if (path === '') throw new Error('--principal \"file:<path>\" requires a non-empty path');\n return { kind: 'file', path };\n }\n throw new Error(\n `invalid --principal \"${raw}\" (expected \"managed\", \"user:<id>\", or \"file:<path>\")`,\n );\n}\n\n/**\n * Which identity actually ended up signing the calls, after resolution. Unlike\n * {@link PrincipalSpec} (what the user asked for), this records what was really\n * used — e.g. whether a `managed` request fell back to a local keypair because\n * the peer offered no identity overlay.\n */\nexport type PrincipalSource =\n | { readonly kind: 'managed'; }\n | { readonly kind: 'managed-fallback'; readonly userId: string; }\n | { readonly kind: 'user'; readonly id: string; }\n | { readonly kind: 'file'; readonly path: string; };\n\n/**\n * A resolved {@link Principal} together with a description of which identity\n * actually ended up signing the calls.\n */\nexport interface ResolvedPrincipal {\n readonly principal: Principal;\n readonly source: PrincipalSource;\n}\n\n/**\n * Resolve a {@link PrincipalSpec} into a concrete {@link Principal}, given the\n * (signed) sender used to bootstrap a managed identity. Cheap/idempotent, so\n * it can be re-derived on each reconnect. Also reports the {@link PrincipalSource}\n * that was actually used, including whether `managed` fell back to a local key.\n */\nexport async function resolvePrincipal(\n spec: PrincipalSpec,\n sender: IRequestSender<SigningCallCtx>,\n): Promise<ResolvedPrincipal> {\n switch (spec.kind) {\n case 'managed':\n try {\n return {\n principal: await createManagedPrincipal(sender),\n source: { kind: 'managed' },\n };\n } catch {\n return {\n principal: await createSelfManagedPrincipal(MANAGED_FALLBACK_USER_ID),\n source: { kind: 'managed-fallback', userId: MANAGED_FALLBACK_USER_ID },\n };\n }\n case 'user':\n return {\n principal: await createSelfManagedPrincipal(spec.id),\n source: { kind: 'user', id: spec.id },\n };\n case 'file':\n return {\n principal: await createSelfManagedPrincipalFromFile(spec.path),\n source: { kind: 'file', path: spec.path },\n };\n }\n}\n\n/**\n * Render a one-line, human-readable description of the identity used to sign\n * calls, e.g. `managed (node abcd012345…)` or\n * `local user:hubrpc-cli (node abcd012345…)`. `nodeId` is truncated to its\n * first 10 characters.\n */\nexport function formatPrincipalSource(source: PrincipalSource, nodeId: string): string {\n const node = `node ${nodeId.slice(0, 10)}…`;\n switch (source.kind) {\n case 'managed':\n return `managed (${node})`;\n case 'managed-fallback':\n return `local user:${source.userId} (managed unavailable) (${node})`;\n case 'user':\n return `local user:${source.id} (${node})`;\n case 'file':\n return `local file:${source.path} (${node})`;\n }\n}\n","import {\n type CapProvider,\n type CapProviderResult,\n type CallTarget,\n permissionMatchesTarget,\n capabilityFreshAt,\n type IRequestSender,\n type Principal,\n type SignedCapability,\n type SigningCallCtx,\n} from '@hediet/linkrpc';\nimport {\n type HubAccessDuration,\n type HubAccessRequest,\n type HubAccessResult,\n} from '@hediet/linkrpc/hub/common';\nimport { hubAccessInterface } from '@hediet/linkrpc/hub/common';\nimport type { CliSigning } from './connect';\nimport { type PrincipalSource, type PrincipalSpec, resolvePrincipal } from './principal';\n\n/** How long before expiry to refresh a capability (2 seconds = transit + skew). */\nconst CAP_FRESHNESS_MARGIN_MS = 2000;\n\n/**\n * The reflection interfaces the CLI walks for `ls` / `schema` / `defaults`\n * / the TUI bus walk. We request all of them, across every service, in a\n * single up-front consent prompt so exploration doesn't re-prompt per\n * service id. See {@link requestReflectionAccess}.\n */\nconst REFLECTION_INTERFACE_IDS = [\n 'hubrpc.directory',\n 'hubrpc.schemas',\n 'hubrpc.defaults',\n] as const;\nconst TOPOLOGY_INTERFACE_ID = 'hubrpc.topology';\n\ntype HubCapProviderResult = Pick<CapProviderResult, 'capabilities' | 'interfaceHash' | 'signedAtMs'>;\n\nexport interface SigningSession {\n /** The identity installed on the channel for this session. */\n readonly principal: Principal;\n /** Which identity actually ended up signing (managed vs. local, etc.). */\n readonly principalSource: PrincipalSource;\n /**\n * The resolved wire method for `hubAccess::requestAccess` on this endpoint\n * (form-3 `<hubServiceId>::hubAccess::requestAccess` for hub endpoints, or\n * the form-2 fallback otherwise).\n */\n readonly hubAccessMethod: string;\n /**\n * Snapshot of the durable capabilities this connection currently holds —\n * the bootstrapped `hubAccess` cap plus anything granted via\n * {@link requestAccess}.\n */\n listGrants(): readonly SignedCapability[];\n /**\n * Explicitly request one or more capabilities from the hub in a single\n * consent prompt. Any durable (non-one-shot) caps the hub mints are added\n * to the connection's cap bag so subsequent calls present them\n * automatically. Use this instead of relying on per-call auto-negotiation.\n */\n requestAccess(req: HubAccessRequest): Promise<HubAccessResult>;\n}\n\n/**\n * Install signing on `signing` for any endpoint. Resolves the\n * {@link PrincipalSpec} into a concrete {@link Principal} (managed-with-\n * fallback, a user slot, or a file-backed keypair) and points the channel's\n * `SigningSender` at it so every outbound call is signed.\n *\n * When `negotiateHubCaps` is set (hub endpoints), it also ensures a persistent\n * `hubAccess` capability is cached on the principal's {@link CapBag} — requesting\n * one with a single signed round-trip on first run / cache miss. For hub\n * endpoints, it also installs a sign-time capability provider.\n *\n * By default (`autoNegotiatePerCall !== false`) that provider negotiates\n * per-call authority lazily using `callIntent` (method + params + nonce +\n * signedAtMs + optional interfaceHash), so one-shot grants can be pinned to the\n * exact call bytes being signed. Set `autoNegotiatePerCall: false` to disable\n * that: the provider then only presents caps already in the bag, and the caller\n * is expected to request access explicitly via\n * {@link SigningSession.requestAccess}.\n */\nexport async function setupSigning(\n channel: IRequestSender<SigningCallCtx>,\n signing: CliSigning,\n principalSpec: PrincipalSpec,\n opts: { negotiateHubCaps: boolean; autoNegotiatePerCall?: boolean; },\n): Promise<SigningSession> {\n const { principal, source: principalSource } = await resolvePrincipal(principalSpec, channel);\n\n signing.principal = principal;\n signing.oneShotCaps = undefined;\n signing.capProvider = undefined;\n\n // The hub serves `hubAccess::*` at the connection root (root form, never\n // forwarded → never gated), so the wire address is simply\n // `hubAccess::requestAccess`. No prefix discovery or bootstrap cap is\n // needed to reach the consent front door.\n const hubAccessMethod = `${hubAccessInterface.info.id}::requestAccess`;\n const consumerPrincipalId = principal.id;\n\n if (opts.negotiateHubCaps) {\n let inAccessNegotiation = false;\n const provider: CapProvider = async ({ method, params, nonce, signedAtMs, interfaceHash }) => {\n let presentCaps = principal.capBag.capabilities;\n // Drop any cached cap that is expired (or expiring within the\n // safety margin) at this call's sign time. Without this, a stale\n // persisted cap from a previous session would be presented and the\n // gate would reject the call with `expired`. Filtering per-cap (not\n // whole-bag) keeps still-valid caps such as the `hubAccess` grant.\n presentCaps = presentCaps.filter((c) =>\n capabilityFreshAt(c, signedAtMs, CAP_FRESHNESS_MARGIN_MS),\n );\n const present: HubCapProviderResult = presentCaps.length > 0 ? { capabilities: presentCaps } : {};\n if (inAccessNegotiation) return {} satisfies HubCapProviderResult;\n\n const call = _wireMethodToCall(method);\n if (!call) return present;\n if (call.serviceId === '' || call.interfaceId === hubAccessInterface.info.id) return present;\n if (_capBagCovers(presentCaps, call)) return present;\n\n // Per-call auto-negotiation is opt-out. When disabled, never trigger\n // a `requestAccess` round-trip behind a call — just present whatever\n // is already in the bag and let the call surface `permissionRequired`\n // if it is gated. The consumer is expected to call\n // `SigningSession.requestAccess` ahead of time.\n if (opts.autoNegotiatePerCall === false) return present;\n\n inAccessNegotiation = true;\n try {\n const granted = await _requestAccessForCall(channel, hubAccessMethod, consumerPrincipalId, {\n call,\n method,\n params,\n nonce,\n signedAtMs,\n interfaceHash,\n });\n\n if (granted.length === 0) return present;\n\n const oneShot = granted.filter(_isOneShotCap);\n const persistent = granted.filter((c) => !_isOneShotCap(c));\n if (persistent.length > 0) await principal.capBag.add(...persistent);\n\n // Re-read the bag and again drop any stale caps so a freshly\n // attached one-shot is never paired with an expired durable cap.\n const durable = principal.capBag.capabilities.filter((c) =>\n capabilityFreshAt(c, signedAtMs, CAP_FRESHNESS_MARGIN_MS),\n );\n if (oneShot.length > 0) {\n return { capabilities: [...durable, ...oneShot] };\n }\n return durable.length > 0\n ? { capabilities: durable }\n : ({} satisfies HubCapProviderResult);\n } catch (err) {\n process.stderr.write(\n `linkrpc: capability negotiation skipped (${(err as Error).message})\\n`,\n );\n return present;\n } finally {\n inAccessNegotiation = false;\n }\n };\n signing.capProvider = provider;\n }\n\n return {\n principal,\n principalSource,\n hubAccessMethod,\n listGrants: () => principal.capBag.capabilities,\n requestAccess: (req) => _sessionRequestAccess(channel, hubAccessMethod, principal, req),\n };\n}\n\n/**\n * Up-front, explicit batched request for reflection access across *every*\n * service: `hubrpc.directory` / `hubrpc.schemas` / `hubrpc.defaults` with a\n * wildcard `serviceId` (`{ prefix: '' }`). One consent prompt covers the whole\n * bus, so `ls` / `schema` / `defaults` / the TUI walk stop re-prompting per\n * service id.\n *\n * Best-effort and fail-soft: a `denied` decision (or an open hub with no access\n * handler that rejects the call) is swallowed. Per-call auto-cap negotiation in\n * {@link setupSigning} then remains the fallback for individual gated calls.\n *\n * Returns the granted status so callers can log it; never throws.\n */\nexport async function requestReflectionAccess(\n session: SigningSession,\n opts: { duration?: HubAccessDuration } = {},\n): Promise<'granted' | 'denied' | 'skipped'> {\n if (REFLECTION_INTERFACE_IDS.every((interfaceId) =>\n _hasInterfaceAccess(session, interfaceId, { prefix: '' })\n )) return 'granted';\n try {\n const result = await session.requestAccess({\n consumer: {\n name: 'linkrpc-cli',\n purpose: 'Reflect on every service exposed by the hub (ls / schema / defaults).',\n },\n permissions: REFLECTION_INTERFACE_IDS.map((id) => ({\n target: {\n serviceId: { prefix: '' },\n interfaceId: { exact: id },\n members: [{ prefix: '' }],\n },\n canInvoke: true,\n })),\n duration: opts.duration ?? 'persistent',\n });\n return result.status === 'granted' ? 'granted' : 'denied';\n } catch {\n // Open hub / no access handler / unreachable consent door: fall back to\n // per-call auto-cap negotiation.\n return 'skipped';\n }\n\n}\n\n/**\n * Request topology access in one consent operation before fan-out begins.\n * Discovery mode needs both directory traversal and topology calls across the\n * bus; fixed-source mode requests topology only for those exact service ids.\n */\nexport async function requestTopologyAccess(\n session: SigningSession,\n opts: {\n readonly sourceServiceIds?: readonly string[];\n readonly duration?: HubAccessDuration;\n } = {},\n): Promise<'granted' | 'denied' | 'skipped'> {\n const sourceServiceIds = opts.sourceServiceIds === undefined\n ? undefined\n : [...new Set(opts.sourceServiceIds)].sort();\n const targets = sourceServiceIds === undefined\n ? [{ prefix: '' } as const]\n : sourceServiceIds.map((serviceId) => ({ exact: serviceId } as const));\n const needsDirectory = sourceServiceIds === undefined;\n const alreadyGranted = (!needsDirectory\n || _hasInterfaceAccess(session, 'hubrpc.directory', { prefix: '' }))\n && targets.every((target) =>\n _hasInterfaceAccess(session, TOPOLOGY_INTERFACE_ID, target));\n if (alreadyGranted) return 'granted';\n\n const permissions: Array<HubAccessRequest['permissions'][number]> = [];\n if (needsDirectory) {\n permissions.push({\n target: {\n serviceId: { prefix: '' },\n interfaceId: { exact: 'hubrpc.directory' },\n members: [{ prefix: '' }],\n },\n canInvoke: true,\n });\n }\n for (const serviceId of targets) {\n permissions.push({\n target: {\n serviceId,\n interfaceId: { exact: TOPOLOGY_INTERFACE_ID },\n members: [{ prefix: '' }],\n },\n canInvoke: true,\n });\n }\n\n try {\n const result = await session.requestAccess({\n consumer: {\n name: 'linkrpc-cli',\n purpose: sourceServiceIds === undefined\n ? 'Discover and inspect the topology exposed by every service on the hub.'\n : 'Inspect topology for the selected services.',\n },\n permissions,\n duration: opts.duration ?? 'persistent',\n });\n return result.status === 'granted' ? 'granted' : 'denied';\n } catch {\n return 'skipped';\n }\n}\n\nfunction _hasInterfaceAccess(\n session: SigningSession,\n interfaceId: string,\n requestedServiceId: { readonly exact: string } | { readonly prefix: '' },\n): boolean {\n const now = Date.now();\n return session.listGrants().some((capability) =>\n capability.audience === session.principal.id\n && capabilityFreshAt(capability, now, CAP_FRESHNESS_MARGIN_MS)\n && capability.permissions.some((permission) => {\n if (\n permission.canInvoke !== true\n || permission.callBind !== undefined\n || permission.params !== undefined\n || permission.target.interfaceHash !== undefined\n || !permission.target.members.some((member) =>\n 'prefix' in member && member.prefix === '')\n ) {\n return false;\n }\n if ('prefix' in requestedServiceId) {\n const grantedServiceId = permission.target.serviceId;\n return 'prefix' in grantedServiceId\n && grantedServiceId.prefix === ''\n && permissionMatchesTarget(\n { serviceId: '', interfaceId, member: '' },\n permission,\n );\n }\n return permissionMatchesTarget(\n { serviceId: requestedServiceId.exact, interfaceId, member: '' },\n permission,\n );\n })\n );\n}\n\n/** Parse a wire method into a {@link CallTarget}, or `undefined` for form-1/2. */\nfunction _wireMethodToCall(wireMethod: string): CallTarget | undefined {\n const parts = wireMethod.split('::');\n if (parts.length !== 3) return undefined;\n const [serviceId, interfaceId, member] = parts;\n return { serviceId, interfaceId, member };\n}\n\n/** A cap is one-shot when any permission is pinned to a single call via `callBind`. */\nfunction _isOneShotCap(sc: SignedCapability): boolean {\n return sc.permissions.some((p) => p.callBind !== undefined);\n}\n\n/** True when a durable (non-one-shot) cap in the bag authorises `target`. */\nfunction _capBagCovers(caps: readonly SignedCapability[], target: CallTarget): boolean {\n return caps.some((sc) => !_isOneShotCap(sc) && sc.permissions.some((p) => permissionMatchesTarget(target, p)));\n}\n\ninterface AccessCallRequest {\n readonly call: CallTarget;\n readonly method: string;\n readonly params: unknown;\n readonly nonce: string;\n readonly signedAtMs: number;\n readonly interfaceHash?: string;\n}\n\nasync function _requestAccessForCall(\n channel: IRequestSender<SigningCallCtx>,\n hubAccessMethod: string,\n consumerPrincipalId: string,\n req: AccessCallRequest,\n): Promise<SignedCapability[]> {\n const result = await _sendRequestAccess(channel, hubAccessMethod, {\n consumer: {\n name: 'linkrpc-cli',\n principal: consumerPrincipalId,\n purpose: `Invoke ${req.method}.`,\n },\n permissions: [{\n target: {\n serviceId: { exact: req.call.serviceId },\n interfaceId: { exact: req.call.interfaceId },\n members: [{ exact: req.call.member }],\n },\n canInvoke: true,\n callIntent: {\n method: req.method,\n params: req.params,\n nonce: req.nonce,\n signedAtMs: req.signedAtMs,\n ...(req.interfaceHash !== undefined ? { interfaceHash: req.interfaceHash } : {}),\n suggestion: 'once' as const,\n },\n }],\n // The hub mints both a once and an always proposal regardless; this\n // only nudges the default selection. The user's choice decides whether\n // the granted cap is one-shot or durable.\n duration: 'once',\n });\n if (result.status !== 'granted') return [];\n return result.capabilities ?? [];\n}\n\nasync function _sendRequestAccess(\n channel: IRequestSender<SigningCallCtx>,\n hubAccessMethod: string,\n params: unknown,\n): Promise<{ status: string; capabilities?: SignedCapability[]; reason?: string; }> {\n const raw = await _awaitWithApprovalNotice(channel.sendRequest(hubAccessMethod, params as never));\n return raw as unknown as {\n status: string;\n capabilities?: SignedCapability[];\n reason?: string;\n };\n}\n\n/** Delay before we tell the user an access request is parked awaiting approval. */\nconst APPROVAL_NOTICE_DELAY_MS = 750;\n\n/**\n * Await a `hubAccess::requestAccess` round-trip, printing a one-line hint to\n * stderr if it doesn't resolve quickly. Access requests park at the hub until a\n * human approver (admin) decides them, so without this notice the CLI looks\n * hung — it blocks with no output until approval. Fast requests (auto-approved\n * / open hub) stay silent because the notice only fires after\n * {@link APPROVAL_NOTICE_DELAY_MS}.\n */\nasync function _awaitWithApprovalNotice<T>(pending: Promise<T>): Promise<T> {\n const timer = setTimeout(() => {\n process.stderr.write(\n 'linkrpc: access request sent — waiting for the hub admin to approve it...\\n',\n );\n }, APPROVAL_NOTICE_DELAY_MS);\n timer.unref?.();\n try {\n return await pending;\n } finally {\n clearTimeout(timer);\n }\n}\n\n/**\n * Backs {@link SigningSession.requestAccess}. Sends a batched\n * `hubAccess::requestAccess`, then adds any durable (non-one-shot) caps the hub\n * minted to the principal's cap bag so later calls present them automatically.\n */\nasync function _sessionRequestAccess(\n channel: IRequestSender<SigningCallCtx>,\n hubAccessMethod: string,\n principal: Principal,\n req: HubAccessRequest,\n): Promise<HubAccessResult> {\n const result = await _sendRequestAccess(channel, hubAccessMethod, {\n consumer: { ...req.consumer, principal: principal.id },\n permissions: req.permissions,\n ...(req.duration !== undefined ? { duration: req.duration } : {}),\n });\n if (result.status === 'granted') {\n const capabilities = result.capabilities ?? [];\n const durable = capabilities.filter((c) => !_isOneShotCap(c));\n if (durable.length > 0) await principal.capBag.add(...durable);\n return { status: 'granted', capabilities, addedDurable: durable.length };\n }\n return { status: result.status, reason: result.reason };\n}\n","import type { IMessageTransport, IRequestSender, SigningCallCtx } from '@hediet/linkrpc';\nimport {\n formatEndpointUri,\n LINKRPC_ENDPOINT_VAR,\n LINKRPC_TOKEN_VAR,\n parseEndpointUri,\n type ResolvedEndpoint,\n} from '@hediet/linkrpc/node';\nimport {\n type CliConnection,\n connect,\n connectViaTransport,\n setupSigning,\n type SigningSession,\n} from '@hediet/linkrpc-client';\nimport type { HubAccessRequest, HubAccessResult } from '@hediet/linkrpc/hub/common';\nimport type { SignedCapability } from '@hediet/linkrpc';\n\n/** Receives one trace line at a time. */\nexport type TraceListener = (line: string) => void;\n\n/**\n * Minimal hub-access surface the MCP tools consume from a connection: read the\n * current grants and request more. Satisfied by both a CLI {@link SigningSession}\n * (endpoint pool) and a {@link import('@hediet/linkrpc/hub/client').HubSigningSender}\n * (consumer-provided sender).\n */\nexport interface HubAccess {\n listGrants(): readonly SignedCapability[];\n requestAccess(req: HubAccessRequest): Promise<HubAccessResult>;\n}\n\n/**\n * One MCP-server-wide live linkrpc connection. We keep a single connection per\n * unique endpoint URI (path/url + token) so repeated tool calls reuse the same\n * socket and the per-connection `lastResultVal` survives across runs.\n */\nexport interface PooledConnection {\n readonly channel: IRequestSender<SigningCallCtx>;\n /** Redacted endpoint URI of this connection, for labels and tool results. */\n readonly endpoint: string;\n /**\n * Canonical endpoint URI (token revealed) — uniquely identifies this\n * connection. Used to key per-connection background tasks so that a new\n * request on the same connection supersedes the previous task.\n */\n readonly key: string;\n /**\n * Hub signing session: signs every outbound call with the connection's\n * identity and exposes the grant surface ({@link HubAccess}). For the\n * endpoint pool this is a CLI `SigningSession`; for a consumer-provided\n * sender it is the sender itself.\n */\n readonly session: HubAccess;\n /** Most recent value returned by `runLinkRpcScript`. Updated after each run. */\n lastResultVal: unknown;\n /**\n * Subscribe `listener` to every JSON-RPC trace line produced while\n * the subscription is live (in addition to the always-on stderr\n * mirror). Returns a disposer that removes the listener. Multiple\n * concurrent listeners are supported — each sees every line —\n * which means concurrent runs on the same pooled connection will\n * see each other's traces. That matches the channel's own\n * concurrency model.\n */\n addTraceListener(listener: TraceListener): () => void;\n /** Emit a trace line on this connection (also writes to stderr). */\n trace(line: string): void;\n /** Close the underlying socket and drop the entry from the pool. */\n dispose(): void;\n}\n\n/**\n * Subset of {@link ConnectionPool} used by the MCP server, extracted so tests\n * can inject a fake pool without standing up a real hub connection.\n */\nexport interface IConnectionPool {\n resolve(endpointUri: string | undefined): Promise<PooledConnection>;\n dispose(): void;\n}\n\n/** Plain JSON-RPC connection descriptor sent by the MCP client. */\nexport interface ConnectionPoolOptions {\n /**\n * Endpoint used when a tool call does not specify a `connection`. When\n * neither the caller nor a default is supplied, the pool falls back to the\n * `LINKRPC_ENDPOINT` / `LINKRPC_TOKEN` environment variables.\n */\n readonly defaultEndpoint?: ResolvedEndpoint;\n /**\n * Opens the **default** connection (the one used when a tool call supplies\n * no `connection` argument) over an in-process transport instead of dialing\n * a socket — typically a leg into an in-process hub participant. When set it\n * takes precedence over {@link defaultEndpoint} / env vars for the\n * no-argument case; explicit `connection` endpoint URIs still dial normally.\n *\n * Called lazily on first use; the returned {@link DefaultTransport.dispose}\n * runs when the pooled connection is disposed.\n */\n readonly defaultTransport?: () => DefaultTransport;\n}\n\n/**\n * An in-process transport supplying the pool's default connection, plus\n * presentation/teardown hooks. The pool wraps {@link transport} in a managed\n * signing connection ({@link connectViaTransport} + `setupSigning`), exactly as\n * it would a dialed socket.\n */\nexport interface DefaultTransport {\n /** In-memory transport whose peer serves the hub (incl. `identity::*`). */\n readonly transport: IMessageTransport;\n /** Human-readable label for traces / tool results. Defaults to `\"inproc\"`. */\n readonly label?: string;\n /** Extra teardown run when the pooled connection is disposed (after `cli.close`). */\n readonly dispose?: () => void;\n}\n\n/**\n * Maintains live hub connections keyed by the canonical endpoint URI (path/url\n * + token). Connections are created lazily on first use and reused for every\n * subsequent call against the same endpoint. Setting up the hub signing session\n * (which may surface a consent modal the first time) happens once per endpoint\n * and the resulting session is cached on the pool entry.\n */\nexport class ConnectionPool implements IConnectionPool {\n private readonly _entries = new Map<string, Promise<PooledConnection>>();\n private readonly _defaultEndpoint: ResolvedEndpoint | undefined;\n private readonly _defaultTransport: (() => DefaultTransport) | undefined;\n\n /** Pool key for the in-process default connection (see {@link ConnectionPoolOptions.defaultTransport}). */\n private static readonly _DEFAULT_INPROC_KEY = '<default-inproc>';\n\n public constructor(options: ConnectionPoolOptions = {}) {\n this._defaultEndpoint = options.defaultEndpoint;\n this._defaultTransport = options.defaultTransport;\n }\n\n /**\n * Resolve a pooled connection for `endpointUri` (a strict endpoint URI such\n * as `unix:/path?token=…`, `npipe://./pipe/…?token=…`, or\n * `wss://host?token=…`). When omitted, an in-process default transport (if\n * configured) is used; otherwise it falls back to the configured default\n * endpoint, then to the `LINKRPC_ENDPOINT` / `LINKRPC_TOKEN` env vars. A token\n * absent from the URI is filled in from `LINKRPC_TOKEN` when present.\n */\n public async resolve(endpointUri: string | undefined): Promise<PooledConnection> {\n if (endpointUri === undefined && this._defaultTransport) {\n return this._resolveCached(\n ConnectionPool._DEFAULT_INPROC_KEY,\n (key) => this._openInProc(this._defaultTransport!(), key),\n );\n }\n const spec = this._resolveSpec(endpointUri);\n // Canonical URI (token revealed) uniquely identifies the connection.\n const key = formatEndpointUri(spec, { revealToken: true });\n return this._resolveCached(key, (k) => this._open(spec, k));\n }\n\n /**\n * Shared cache-or-open: returns the in-flight/cached entry for `key`, or\n * starts `open(key)` and caches the promise so concurrent callers share the\n * same signing setup. On failure the entry is evicted so the next call\n * retries cleanly.\n */\n private _resolveCached(\n key: string,\n open: (key: string) => Promise<PooledConnection>,\n ): Promise<PooledConnection> {\n const existing = this._entries.get(key);\n if (existing) return existing;\n const pending = open(key);\n this._entries.set(key, pending);\n pending.catch(() => this._entries.delete(key));\n return pending;\n }\n\n private _resolveSpec(endpointUri: string | undefined): ResolvedEndpoint {\n if (endpointUri !== undefined) {\n return _withEnvToken(parseEndpointUri(endpointUri));\n }\n return this._defaultEndpoint ?? _resolveFromEnv();\n }\n\n private async _open(\n spec: ResolvedEndpoint,\n key: string,\n ): Promise<PooledConnection> {\n const display = formatEndpointUri(spec);\n const cli: CliConnection = await connect(spec);\n return this._finishOpen(cli, display, key);\n }\n\n private async _openInProc(\n def: DefaultTransport,\n key: string,\n ): Promise<PooledConnection> {\n const cli = connectViaTransport(def.transport);\n return this._finishOpen(cli, def.label ?? 'inproc', key, def.dispose);\n }\n\n /**\n * Wrap an already-open {@link CliConnection} in a managed signing session\n * and build the {@link PooledConnection}. Shared by the dialed-socket and\n * in-process default paths — both sign as a managed principal and bootstrap\n * the `hubAccess` cap, the only difference being how the transport was\n * obtained. `extraDispose` runs on disposal after the connection is closed.\n */\n private async _finishOpen(\n cli: CliConnection,\n display: string,\n key: string,\n extraDispose?: () => void,\n ): Promise<PooledConnection> {\n const traceListeners = new Set<TraceListener>();\n const trace = (line: string): void => {\n process.stderr.write(`${line}\\n`);\n for (const l of traceListeners) {\n try {\n l(line);\n } catch { /* listener errors must not break the wire */ }\n }\n };\n _installTransportTrace(cli.channel, display, trace);\n try {\n trace(\n `linkrpc-mcp[${display}] requesting hub signing session (may prompt for reflection-cap consent on first use)`,\n );\n const session = await setupSigning(\n cli.channel,\n cli.signing,\n { kind: 'managed' },\n { negotiateHubCaps: true, autoNegotiatePerCall: false },\n );\n const entry: PooledConnection = {\n channel: cli.channel,\n endpoint: display,\n key,\n session,\n lastResultVal: undefined,\n addTraceListener: (listener) => {\n traceListeners.add(listener);\n return () => traceListeners.delete(listener);\n },\n trace,\n dispose: () => {\n cli.close();\n extraDispose?.();\n this._entries.delete(key);\n },\n };\n return entry;\n } catch (e) {\n cli.close();\n extraDispose?.();\n throw e;\n }\n }\n\n public dispose(): void {\n for (const pending of this._entries.values()) {\n pending.then(\n (e) => e.dispose(),\n () => {/* failed open, nothing to close */ },\n );\n }\n this._entries.clear();\n }\n}\n\n/**\n * Fill a missing socket/ws token from `LINKRPC_TOKEN` when the URI itself didn't\n * carry one. Command endpoints (`cmd:` / `cmd-stdio:`) carry no token.\n */\nfunction _withEnvToken(spec: ResolvedEndpoint): ResolvedEndpoint {\n if ((spec.kind === 'socket' || spec.kind === 'ws') && spec.token === undefined) {\n const token = process.env[LINKRPC_TOKEN_VAR];\n if (token) return { ...spec, token };\n }\n return spec;\n}\n\nfunction _resolveFromEnv(): ResolvedEndpoint {\n const endpoint = process.env[LINKRPC_ENDPOINT_VAR];\n if (!endpoint) {\n throw new Error(\n `No connection supplied and ${LINKRPC_ENDPOINT_VAR} is not set. ` +\n `Pass a 'connection' endpoint URI (e.g. unix:/path?token=… or ` +\n `wss://host?token=…) to the tool, or run the MCP server inside a ` +\n `VS Code window with the team-tools hub active.`,\n );\n }\n return _withEnvToken(parseEndpointUri(endpoint));\n}\n\n/**\n * Wrap `channel.sendRequest` / `channel.sendNotification` so every\n * outbound JSON-RPC envelope and its outcome is emitted as a trace\n * line. Catches everything the MCP server drives (tool-issued `call` /\n * `notify`, `explore`, and the hub's `hubAccess::requestAccess`\n * permission round-trips).\n *\n * IMPORTANT: the wrappers forward the third `opts` argument verbatim. It\n * carries the per-call {@link SigningCallCtx} (e.g. `signerOverride: null` for\n * the unsigned `identity::*` bootstrap round-trips). Dropping it would make a\n * managed identity's `identity::sign` calls get signed — which recurses\n * (signing a call needs another `identity::sign`), blowing the heap.\n */\nfunction _installTransportTrace(\n channel: IRequestSender<SigningCallCtx>,\n endpoint: string,\n trace: TraceListener,\n): void {\n const send = channel.sendRequest.bind(channel);\n const notify = channel.sendNotification.bind(channel);\n let seq = 0;\n channel.sendRequest = async (method, params, opts) => {\n const id = ++seq;\n trace(`linkrpc-mcp[${endpoint}] → #${id} request ${method} ${_fmt(params)}`);\n try {\n const result = await send(method, params, opts);\n trace(`linkrpc-mcp[${endpoint}] ← #${id} result ${_fmt(result)}`);\n return result;\n } catch (e) {\n trace(`linkrpc-mcp[${endpoint}] ← #${id} error ${(e as Error).message}`);\n throw e;\n }\n };\n channel.sendNotification = async (method, params, opts) => {\n const id = ++seq;\n trace(`linkrpc-mcp[${endpoint}] → #${id} notify ${method} ${_fmt(params)}`);\n await notify(method, params, opts);\n };\n}\n\nconst _MAX_TRACE_PAYLOAD = 2000;\n\nfunction _fmt(v: unknown): string {\n if (v === undefined) return '(no params)';\n let s: string;\n try {\n s = JSON.stringify(v);\n } catch {\n s = String(v);\n }\n if (s === undefined) s = 'undefined';\n return s.length > _MAX_TRACE_PAYLOAD ?\n `${s.slice(0, _MAX_TRACE_PAYLOAD)}…(+${s.length - _MAX_TRACE_PAYLOAD} chars)` :\n s;\n}\n","import type { HubSigningSender } from '@hediet/linkrpc/hub/client';\nimport type { IConnectionPool, PooledConnection, TraceListener } from './connectionPool';\n\n/** Identifies the MCP session a connection is opened for (consumer-provided mode). */\nexport interface McpSessionInfo {\n readonly sessionId?: string;\n readonly authorization?: string;\n}\n\n/**\n * Resolves a {@link HubSigningSender} for an MCP session and an optional\n * `connection` endpoint argument (`undefined` → the provider's default). This is\n * the single injection seam for both identity-provision modes:\n * - package-provisioned: the provider dials an endpoint and signs (managed).\n * - consumer-provisioned: the embedder returns a sender bound to a per-session\n * identity it owns (e.g. an in-process hub participant).\n */\nexport type HubSenderProvider = (\n session: McpSessionInfo | undefined,\n endpoint: string | undefined,\n) => Promise<HubSigningSender>;\n\n/**\n * {@link IConnectionPool} backed by a {@link HubSenderProvider}: caches one\n * {@link HubSigningSender} per distinct `connection` argument and adapts it to\n * the {@link PooledConnection} shape the MCP tools consume. Holds the\n * MCP-layer-only `lastResultVal` and trace fan-out so the sender stays pure.\n */\nexport class ProviderPool implements IConnectionPool {\n private readonly _entries = new Map<string, Promise<PooledConnection>>();\n\n public constructor(\n private readonly _provider: HubSenderProvider,\n private readonly _session?: McpSessionInfo,\n ) { }\n\n public resolve(endpointUri: string | undefined): Promise<PooledConnection> {\n const key = endpointUri ?? '<default>';\n const existing = this._entries.get(key);\n if (existing) return existing;\n const pending = this._open(endpointUri, key);\n this._entries.set(key, pending);\n pending.catch(() => this._entries.delete(key));\n return pending;\n }\n\n private async _open(endpointUri: string | undefined, key: string): Promise<PooledConnection> {\n const sender = await this._provider(this._session, endpointUri);\n const traceListeners = new Set<TraceListener>();\n const entry: PooledConnection = {\n channel: sender,\n endpoint: sender.identity.principal,\n key,\n session: sender,\n lastResultVal: undefined,\n addTraceListener: (listener) => {\n traceListeners.add(listener);\n return () => traceListeners.delete(listener);\n },\n trace: (line) => {\n for (const l of traceListeners) {\n try {\n l(line);\n } catch { /* listener errors must not break the wire */ }\n }\n },\n dispose: () => {\n sender.close();\n this._entries.delete(key);\n },\n };\n return entry;\n }\n\n public dispose(): void {\n for (const pending of this._entries.values()) {\n pending.then(\n (e) => e.dispose(),\n () => { /* failed open, nothing to close */ },\n );\n }\n this._entries.clear();\n }\n}\n","import type { SignedCapability } from '@hediet/linkrpc';\n\n/** A flattened, human-/LLM-readable view of one permission inside a capability. */\nexport interface GrantPermissionSummary {\n readonly serviceId: string;\n readonly interfaceId: string;\n readonly members: readonly string[];\n readonly canInvoke: boolean;\n readonly canDelegate: boolean;\n}\n\n/** A flattened view of a single held capability. */\nexport interface GrantSummary {\n readonly issuer: string;\n readonly audience: string;\n /** Unix ms the cap expires at, when bounded. */\n readonly expiresAtMs?: number;\n /** True when the cap is pinned to a single call (`callBind`); not reusable. */\n readonly oneShot: boolean;\n readonly permissions: readonly GrantPermissionSummary[];\n}\n\n/** The shape returned to the model by `con.grants()`. */\nexport interface GrantsSummary {\n readonly count: number;\n readonly grants: readonly GrantSummary[];\n}\n\n/** Render a single `serviceId` / `interfaceId` / member matcher as a string. */\nfunction _fmtPattern(p: { exact: string } | { prefix: string }): string {\n if ('exact' in p) return p.exact;\n return p.prefix === '' ? '*' : `${p.prefix}*`;\n}\n\n/**\n * Summarise the durable capabilities a connection currently holds into a\n * compact, JSON-friendly shape the model can read to understand what access it\n * already has (and therefore what it still needs to request).\n */\nexport function summarizeGrants(caps: readonly SignedCapability[]): GrantsSummary {\n const grants = caps.map((c): GrantSummary => {\n const oneShot = c.permissions.some((p) => p.callBind !== undefined);\n return {\n issuer: c.issuer,\n audience: c.audience,\n ...(c.expiresAtMs !== undefined ? { expiresAtMs: c.expiresAtMs } : {}),\n oneShot,\n permissions: c.permissions.map((p): GrantPermissionSummary => ({\n serviceId: _fmtPattern(p.target.serviceId),\n interfaceId: _fmtPattern(p.target.interfaceId),\n members: p.target.members.map(_fmtPattern),\n canInvoke: p.canInvoke ?? false,\n canDelegate: p.canDelegate ?? false,\n })),\n };\n });\n return { count: grants.length, grants };\n}\n","/// <reference path=\"./raw.d.ts\" />\nimport connectionDtsText from \"./guest/connection.d.ts?raw\";\n\n/**\n * Documentation that the MCP server exposes as a resource. The text is the\n * single source of truth for what `runLinkRpcScript` sees inside the QuickJS\n * sandbox — it lives as the real declaration file `connection.d.ts` and is\n * embedded here verbatim. Keep `connection.d.ts` in sync with `sandbox.ts`\n * and `explore.ts`.\n */\nexport const CONNECTION_DTS: string = connectionDtsText;\n","import {\n getQuickJS,\n QuickJSHandle,\n Scope,\n type QuickJSContext,\n type QuickJSDeferredPromise,\n type QuickJSRuntime,\n} from \"quickjs-emscripten\";\nimport { readFileSync } from \"node:fs\";\nimport { fileURLToPath } from \"node:url\";\nimport { createRequire } from \"node:module\";\nimport { CONNECTION_DTS } from \"./connectionDts\";\n\n/**\n * The guest runtime (`src/guest/guestMain.ts`) bundled to plain JS, evaluated\n * inside QuickJS before any user code. Authoring it as real TypeScript that is\n * type-checked against `connection.d.ts` is what keeps `con` from drifting out\n * of sync with its declarations.\n *\n * `@vscode/rollup-plugin-esm-url` rewrites the `?esm` URL at build time to the\n * emitted (already-transpiled) chunk next to this module, so the production\n * read returns JS. In dev/test (vite serve, no rewrite) the URL still points\n * at the `.ts` source, so we transpile it on the fly with the `typescript`\n * devDependency — that branch never runs in the shipped `dist`.\n */\nfunction _loadGuestRuntime(): string {\n const filePath = fileURLToPath(new URL(\"./guest/guestMain.ts?esm\", import.meta.url));\n const code = readFileSync(filePath, \"utf8\");\n if (!filePath.endsWith(\".ts\")) {\n return _asGuestScript(code);\n }\n const ts = createRequire(import.meta.url)(\"typescript\") as typeof import(\"typescript\");\n const transpiled = ts.transpileModule(code, {\n compilerOptions: { target: ts.ScriptTarget.ES2022, module: ts.ModuleKind.ESNext },\n }).outputText;\n return _asGuestScript(transpiled);\n}\n\nfunction _asGuestScript(code: string): string {\n return code.replace(/^\\s*export\\s*\\{\\s*\\};?\\s*$/m, \"\");\n}\n\nconst GUEST_RUNTIME_JS = _loadGuestRuntime();\n\n/**\n * Async host functions exposed to the guest. Each returns either:\n * - a JSON-stringified value (the guest will `JSON.parse` it), or\n * - the empty string for `undefined` results (used for `notify`).\n *\n * Host rejections become guest `Error`s with a bounded snapshot of every\n * serializable own data property preserved.\n */\nexport interface SandboxHostApi {\n call(\n method: string,\n paramsJson: string,\n optsJson: string,\n onStreamMessage: (payloadJson: string) => void,\n signal: AbortSignal,\n ): Promise<string>;\n notify(method: string, paramsJson: string): Promise<string>;\n explore(argsJson: string): Promise<string>;\n requestAccess(argsJson: string): Promise<string>;\n grants(argsJson: string): Promise<string>;\n}\n\nexport type SandboxLog = { level: \"log\" | \"warn\" | \"error\"; text: string };\n\n/** Legacy options for {@link runSandboxed} (run-to-completion, no parking). */\nexport interface SandboxOptions {\n /** Foreground budget in ms. Defaults to {@link DEFAULT_FOREGROUND_MS}. */\n readonly timeoutMs?: number;\n readonly memoryLimitBytes?: number;\n}\n\n/** Options for {@link startSandbox} (parking-capable). */\nexport interface StartSandboxOptions {\n /**\n * How long the call may run synchronously before it is parked as a\n * background task. Defaults to {@link DEFAULT_FOREGROUND_MS}.\n */\n readonly foregroundMs?: number;\n /**\n * Absolute lifetime cap for a parked task. After this the task is\n * soft-aborted and settled with an error. Defaults to\n * {@link DEFAULT_MAX_LIFETIME_MS}. Must be `> foregroundMs` for parking\n * to be possible.\n */\n readonly maxLifetimeMs?: number;\n readonly memoryLimitBytes?: number;\n /**\n * Human-readable debug name for the parked task. When omitted, the name\n * is inferred from the in-flight RPC(s) at park time, falling back to the\n * first line of `code`.\n */\n readonly label?: string;\n}\n\n/** Legacy result shape for {@link runSandboxed}. */\nexport interface SandboxRunResult {\n readonly resultJson: string;\n readonly logs: readonly SandboxLog[];\n}\n\n/** Terminal state of a parked task. */\nexport type TaskOutcome =\n | { readonly status: \"completed\"; readonly result: unknown; readonly logs: readonly SandboxLog[] }\n | { readonly status: \"error\"; readonly error: string; readonly logs: readonly SandboxLog[] }\n | { readonly status: \"cancelled\"; readonly logs: readonly SandboxLog[] };\n\n/** Result of the foreground phase of {@link startSandbox}. */\nexport type SandboxOutcome =\n | { readonly status: \"completed\"; readonly result: unknown; readonly logs: readonly SandboxLog[] }\n | { readonly status: \"error\"; readonly error: string; readonly logs: readonly SandboxLog[] }\n | { readonly status: \"parked\"; readonly debugName: string; readonly task: ParkedTask };\n\n/**\n * A live sandbox execution that did not settle within the foreground budget\n * and is now pumping in the background until its in-flight work resolves, it\n * is cancelled, or it hits the max-lifetime guard.\n */\nexport interface ParkedTask {\n /** Labels of the RPC(s) currently in flight (snapshot). */\n inFlight(): string[];\n /** Live view of logs captured so far. */\n readonly logs: readonly SandboxLog[];\n /** Resolves when the task reaches a terminal state. Never rejects. */\n readonly done: Promise<TaskOutcome>;\n /**\n * Soft-abort the task and settle it. Resolves with the terminal outcome\n * (`cancelled`, or `completed`/`error` if the guest settled cleanly\n * within its grace window).\n */\n cancel(): Promise<TaskOutcome>;\n}\n\nconst DEFAULT_FOREGROUND_MS = 5_000;\nconst DEFAULT_MAX_LIFETIME_MS = 120_000;\nconst DEFAULT_MEMORY_LIMIT_BYTES = 32 * 1024 * 1024;\n/**\n * Grace window granted to the guest after a soft abort (cancel / max\n * lifetime) so it can run `catch`/`finally` and return a partial result\n * before the task is force-settled.\n */\nconst SOFT_CANCEL_GRACE_MS = 200;\n\nlet _quickjsPromise: ReturnType<typeof getQuickJS> | undefined;\nfunction _qjs() {\n if (!_quickjsPromise) _quickjsPromise = getQuickJS();\n return _quickjsPromise;\n}\n\nconst _delay = (): Promise<void> => new Promise((r) => setImmediate(r));\n\n/**\n * Internal mutable VM state shared with host-fn callbacks.\n * - `alive` flips false during teardown so late RPC replies don't touch\n * freed memory.\n * - `softAborted` flips true when cancelled / max-lifetime; pending RPCs\n * are rejected with `AbortError` and the guest sees\n * `con.abortSignal.aborted = true`. Subsequent host-fn calls reject\n * immediately while the guest still has its grace window.\n */\ninterface VmState {\n alive: boolean;\n softAborted: boolean;\n softAbortReason: string | undefined;\n}\n\n/**\n * Run-to-completion entry point preserved for callers that just want a result\n * and treat the timeout as a hard wall (the original behaviour). Throws on\n * guest error or deadline; never parks.\n */\nexport async function runSandboxed(\n userCode: string,\n host: SandboxHostApi,\n lastResultVal: unknown,\n options: SandboxOptions = {},\n): Promise<SandboxRunResult> {\n const budget = options.timeoutMs ?? DEFAULT_FOREGROUND_MS;\n const exec = await SandboxExecution.create(userCode, host, lastResultVal, {\n foregroundMs: budget,\n // maxLifetime === foreground disables parking.\n maxLifetimeMs: budget,\n memoryLimitBytes: options.memoryLimitBytes,\n });\n const outcome = await exec.runForeground();\n if (outcome.status === \"completed\") {\n return {\n resultJson: outcome.result === undefined ? \"\" : JSON.stringify(outcome.result),\n logs: outcome.logs,\n };\n }\n if (outcome.status === \"error\") {\n throw new Error(outcome.error);\n }\n // Parking is disabled here, so this branch is unreachable in practice;\n // defend against it anyway so a stray parked task can't leak a VM.\n const final = await outcome.task.cancel();\n throw new Error(\n final.status === \"error\" ? final.error : \"sandbox deadline exceeded\",\n );\n}\n\n/**\n * Parking-capable entry point. Runs `userCode` for up to `foregroundMs`; if it\n * settles in that window the result is returned inline, otherwise the live VM\n * is detached into a {@link ParkedTask} that keeps pumping in the background.\n */\nexport async function startSandbox(\n userCode: string,\n host: SandboxHostApi,\n lastResultVal: unknown,\n options: StartSandboxOptions = {},\n): Promise<SandboxOutcome> {\n const exec = await SandboxExecution.create(userCode, host, lastResultVal, {\n foregroundMs: options.foregroundMs ?? DEFAULT_FOREGROUND_MS,\n maxLifetimeMs: options.maxLifetimeMs ?? DEFAULT_MAX_LIFETIME_MS,\n memoryLimitBytes: options.memoryLimitBytes,\n label: options.label,\n });\n return exec.runForeground();\n}\n\ninterface ResolvedExecOptions {\n foregroundMs: number;\n maxLifetimeMs: number;\n memoryLimitBytes?: number;\n label?: string;\n}\n\ninterface PendingTimer {\n readonly handle: ReturnType<typeof setTimeout>;\n readonly repeat: boolean;\n readonly delayMs: number;\n}\n\n/**\n * Encapsulates one QuickJS context and drives it through a foreground phase\n * and (optionally) a background phase. Only one driver loop runs at a time:\n * `runForeground` runs first and, if it parks, hands off to `_runBackground`.\n * `cancel` cooperates with the background loop rather than starting its own.\n */\nclass SandboxExecution {\n public static async create(\n userCode: string,\n host: SandboxHostApi,\n lastResultVal: unknown,\n options: ResolvedExecOptions,\n ): Promise<SandboxExecution> {\n const QuickJS = await _qjs();\n const exec = new SandboxExecution(userCode, host, lastResultVal, options);\n try {\n exec._init(QuickJS);\n } catch (e) {\n exec._dispose();\n throw e;\n }\n return exec;\n }\n\n private readonly _scope = new Scope();\n private readonly _logs: SandboxLog[] = [];\n /** In-flight host->guest deferreds keyed by a human-readable call label. */\n private readonly _pendingDeferreds = new Map<QuickJSDeferredPromise, string>();\n private readonly _pendingTimers = new Map<number, PendingTimer>();\n private readonly _vmState: VmState = { alive: true, softAborted: false, softAbortReason: undefined };\n private readonly _abortController = new AbortController();\n private readonly _cpuBurstMs: number;\n private readonly _startedAt = Date.now();\n\n private _runtime!: QuickJSRuntime;\n private _vm!: QuickJSContext;\n private _promiseH: QuickJSHandle | undefined;\n /** Deadline for the current synchronous burst; read by the interrupt handler. */\n private _cpuDeadline = 0;\n private _disposed = false;\n private _settled: TaskOutcome | undefined;\n private _backgroundDone: Promise<TaskOutcome> | undefined;\n private _cancelGraceDeadline: number | undefined;\n\n private constructor(\n private readonly _userCode: string,\n private readonly _host: SandboxHostApi,\n private readonly _lastResultVal: unknown,\n private readonly _options: ResolvedExecOptions,\n ) {\n this._cpuBurstMs = Math.max(_options.foregroundMs, 50);\n }\n\n private get _allowPark(): boolean {\n return this._options.maxLifetimeMs > this._options.foregroundMs;\n }\n\n private _init(QuickJS: Awaited<ReturnType<typeof getQuickJS>>): void {\n const runtime = this._scope.manage(QuickJS.newRuntime());\n runtime.setMemoryLimit(this._options.memoryLimitBytes ?? DEFAULT_MEMORY_LIMIT_BYTES);\n // Per-burst CPU guard: any single synchronous chunk that runs past\n // `_cpuDeadline` is interrupted. `_cpuDeadline` is refreshed before\n // every entry into the VM, so cooperative code that yields to I/O can\n // run indefinitely while a `while(true){}` is killed within one burst.\n runtime.setInterruptHandler(() => Date.now() > this._cpuDeadline);\n this._runtime = runtime;\n this._vm = this._scope.manage(runtime.newContext());\n // Arm the CPU budget before any guest code (prelude) runs.\n this._cpuDeadline = Date.now() + this._cpuBurstMs;\n this._installHostApi();\n _evalPrelude(this._vm, this._lastResultVal);\n }\n\n public async runForeground(): Promise<SandboxOutcome> {\n // Compile + start the user IIFE. Syntax errors surface here.\n this._cpuDeadline = Date.now() + this._cpuBurstMs;\n const evalRes = this._vm.evalCode(_wrapUserCode(this._userCode));\n if (evalRes.error) {\n const dumped = this._vm.dump(evalRes.error);\n evalRes.error.dispose();\n this._forceSettle({ status: \"error\", error: _formatGuestError(dumped), logs: this._logs.slice() });\n return this._terminalOutcome();\n }\n this._promiseH = evalRes.value;\n this._pump();\n\n const phase = await this._loopUntil(Date.now() + this._options.foregroundMs);\n if (phase === \"settled\") return this._terminalOutcome();\n\n // Still pending at the foreground deadline.\n if (!this._allowPark) {\n this._triggerSoftAbort(\"sandbox deadline exceeded\");\n await this._loopUntil(Date.now() + SOFT_CANCEL_GRACE_MS);\n if (!this._settled) {\n this._forceSettle({\n status: \"error\",\n error: \"sandbox deadline exceeded\",\n logs: this._logs.slice(),\n });\n }\n return this._terminalOutcome();\n }\n\n const debugName = this._computeDebugName();\n this._backgroundDone = this._runBackground();\n return { status: \"parked\", debugName, task: this._asParkedTask() };\n }\n\n private async _runBackground(): Promise<TaskOutcome> {\n const hardDeadline = this._startedAt + this._options.maxLifetimeMs;\n while (true) {\n if (this._settled || this._checkPromise()) break;\n const now = Date.now();\n if (this._cancelGraceDeadline !== undefined && now > this._cancelGraceDeadline) {\n this._forceSettle({ status: \"cancelled\", logs: this._logs.slice() });\n break;\n }\n if (now > hardDeadline) {\n this._triggerSoftAbort(\"max lifetime exceeded\");\n this._forceSettle({\n status: \"error\",\n error: \"sandbox max lifetime exceeded\",\n logs: this._logs.slice(),\n });\n break;\n }\n await _delay();\n this._pump();\n }\n return this._settled as TaskOutcome;\n }\n\n /** Pump + poll the user promise until it settles or `deadline` passes. */\n private async _loopUntil(deadline: number): Promise<\"settled\" | \"pending\"> {\n while (true) {\n if (this._settled || this._checkPromise()) return \"settled\";\n if (Date.now() > deadline) return \"pending\";\n await _delay();\n this._pump();\n }\n }\n\n /** Returns true once the user promise has settled (and disposes the VM). */\n private _checkPromise(): boolean {\n if (this._settled) return true;\n if (!this._vmState.alive || !this._promiseH) return true;\n const state = this._vm.getPromiseState(this._promiseH);\n if (state.type === \"fulfilled\") {\n let json: string;\n try {\n json = this._vm.getString(state.value);\n } finally {\n state.value.dispose();\n }\n const result = json === \"\" ? undefined : JSON.parse(json);\n this._forceSettle({ status: \"completed\", result, logs: this._logs.slice() });\n return true;\n }\n if (state.type === \"rejected\") {\n const dumped = this._vm.dump(state.error);\n state.error.dispose();\n const e = _toError(dumped);\n this._settleError(e.message, _formatGuestError(dumped));\n return true;\n }\n // Pending: `state.error` is a plain JS placeholder, nothing to dispose.\n return false;\n }\n\n private _settleError(message: string, detail?: string): void {\n // A rejection that arrives after a soft abort is the guest reacting to\n // our `AbortError`; classify it as a clean cancellation rather than a\n // failure so callers see the intent.\n if (this._vmState.softAborted && /abort/i.test(message)) {\n this._forceSettle({ status: \"cancelled\", logs: this._logs.slice() });\n return;\n }\n const normalized = /interrupt/i.test(message) ? \"sandbox deadline exceeded\" : (detail ?? message);\n this._forceSettle({ status: \"error\", error: normalized, logs: this._logs.slice() });\n }\n\n private _forceSettle(outcome: TaskOutcome): void {\n if (this._settled) return;\n this._dispose();\n this._settled = outcome;\n }\n\n private _pump(): void {\n if (!this._vmState.alive || this._disposed) return;\n this._cpuDeadline = Date.now() + this._cpuBurstMs;\n const r = this._runtime.executePendingJobs();\n if (r.error) {\n const dumped = this._vm.dump(r.error);\n r.error.dispose();\n const e = _toError(dumped);\n this._settleError(e.message, _formatGuestError(dumped));\n }\n }\n\n private _computeDebugName(): string {\n if (this._options.label) return this._options.label;\n const inflight = this._inFlight();\n if (inflight.length > 0) return inflight.join(\", \");\n return _firstLine(this._userCode);\n }\n\n private _inFlight(): string[] {\n return [\n ...this._pendingDeferreds.values(),\n ...[...this._pendingTimers.values()].map((timer) =>\n `${timer.repeat ? \"setInterval\" : \"setTimeout\"}(${timer.delayMs}ms)`),\n ];\n }\n\n private _asParkedTask(): ParkedTask {\n return {\n inFlight: () => this._inFlight(),\n logs: this._logs,\n done: this._backgroundDone!,\n cancel: () => this.cancel(),\n };\n }\n\n public async cancel(): Promise<TaskOutcome> {\n if (this._settled) return this._settled;\n this._triggerSoftAbort(\"cancelled\");\n this._cancelGraceDeadline = Date.now() + SOFT_CANCEL_GRACE_MS;\n // The background loop observes the grace deadline and force-settles.\n if (this._backgroundDone) return this._backgroundDone;\n // No background loop yet (cancelled mid-foreground): settle directly.\n this._forceSettle({ status: \"cancelled\", logs: this._logs.slice() });\n return this._settled!;\n }\n\n /**\n * Flip the guest-visible `con.abortSignal.aborted` flag and reject every\n * in-flight host promise with an `AbortError` naming the call.\n */\n private _triggerSoftAbort(reason: string): void {\n if (this._vmState.softAborted || !this._vmState.alive) return;\n this._vmState.softAborted = true;\n this._vmState.softAbortReason = reason;\n this._abortController.abort(reason);\n this._clearAllTimers();\n\n this._cpuDeadline = Date.now() + this._cpuBurstMs;\n const setFlag = this._vm.evalCode(\n `(() => {\n if (globalThis.con && globalThis.con.abortSignal) {\n globalThis.con.abortSignal.aborted = true;\n globalThis.con.abortSignal.reason = ${JSON.stringify(reason)};\n }\n })()`,\n );\n if (setFlag.error) setFlag.error.dispose();\n else setFlag.value.dispose();\n\n const entries = [...this._pendingDeferreds];\n this._pendingDeferreds.clear();\n for (const [d, label] of entries) {\n if (!d.alive) continue;\n this._vm.newError(`AbortError: ${reason} (cancelled in-flight: ${label})`)\n .consume((errH) => d.reject(errH));\n }\n this._pump();\n }\n\n private _dispose(): void {\n if (this._disposed) return;\n this._disposed = true;\n this._vmState.alive = false;\n if (!this._abortController.signal.aborted) {\n this._abortController.abort(\"sandbox disposed\");\n }\n this._clearAllTimers();\n for (const d of this._pendingDeferreds.keys()) {\n if (d.alive) d.dispose();\n }\n this._pendingDeferreds.clear();\n if (this._promiseH && this._promiseH.alive) this._promiseH.dispose();\n this._scope.dispose();\n }\n\n private _terminalOutcome(): SandboxOutcome {\n const o = this._settled;\n if (!o) throw new Error(\"sandbox: terminal outcome requested before settling\");\n if (o.status === \"completed\") return { status: \"completed\", result: o.result, logs: o.logs };\n if (o.status === \"cancelled\") {\n // A foreground (non-parking) run that cancels is reported as an error.\n return { status: \"error\", error: \"sandbox cancelled\", logs: o.logs };\n }\n return { status: \"error\", error: o.error, logs: o.logs };\n }\n\n private _installHostApi(): void {\n this._registerAsyncHostFn(\n \"__hostCall\",\n (method, paramsJson, optsJson, emit) =>\n this._host.call(\n method,\n paramsJson,\n optsJson,\n emit,\n this._abortController.signal,\n ),\n (method) => `con.call(${JSON.stringify(method)})`,\n \"__dispatchHostStream\",\n );\n this._registerAsyncHostFn(\n \"__hostNotify\",\n (m, p) => this._host.notify(m, p),\n (method) => `con.notify(${JSON.stringify(method)})`,\n );\n this._registerAsyncHostFn(\n \"__hostExplore\",\n (a) => this._host.explore(a),\n () => `con.explore(...)`,\n );\n\n this._registerAsyncHostFn(\n \"__hostRequestAccess\",\n (a) => this._host.requestAccess(a),\n () => `con.requestAccess(...)`,\n );\n\n this._registerAsyncHostFn(\n \"__hostGrants\",\n (a) => this._host.grants(a),\n () => `con.grants()`,\n );\n\n this._vm.newFunction(\"__hostLog\", (levelH, textH) => {\n const level = this._vm.getString(levelH) as \"log\" | \"warn\" | \"error\";\n const text = textH ? this._vm.getString(textH) : \"\";\n this._logs.push({ level, text });\n }).consume((fn) => this._vm.setProp(this._vm.global, \"__hostLog\", fn));\n\n this._vm.newFunction(\"__hostSetTimer\", (idH, delayH, repeatH) => {\n this._setTimer(\n this._vm.getNumber(idH),\n this._vm.getNumber(delayH),\n this._vm.getNumber(repeatH) === 1,\n );\n }).consume((fn) => this._vm.setProp(this._vm.global, \"__hostSetTimer\", fn));\n\n this._vm.newFunction(\"__hostClearTimer\", (idH) => {\n this._clearTimer(this._vm.getNumber(idH));\n }).consume((fn) => this._vm.setProp(this._vm.global, \"__hostClearTimer\", fn));\n }\n\n private _setTimer(timerId: number, delayMs: number, repeat: boolean): void {\n this._clearTimer(timerId);\n if (!this._vmState.alive || this._vmState.softAborted) return;\n const normalizedDelay = Math.min(Math.max(0, Math.floor(delayMs)), 2_147_483_647);\n const callback = () => {\n if (!this._vmState.alive || this._disposed) return;\n if (!repeat) this._pendingTimers.delete(timerId);\n this._dispatchGuestFunction(\"__dispatchHostTimer\", timerId);\n };\n const handle = repeat\n ? setInterval(callback, normalizedDelay)\n : setTimeout(callback, normalizedDelay);\n this._pendingTimers.set(timerId, { handle, repeat, delayMs: normalizedDelay });\n }\n\n private _clearTimer(timerId: number): void {\n const timer = this._pendingTimers.get(timerId);\n if (!timer) return;\n if (timer.repeat) clearInterval(timer.handle);\n else clearTimeout(timer.handle);\n this._pendingTimers.delete(timerId);\n }\n\n private _clearAllTimers(): void {\n for (const timerId of [...this._pendingTimers.keys()]) {\n this._clearTimer(timerId);\n }\n }\n\n private _dispatchGuestFunction(name: string, ...args: readonly (string | number)[]): void {\n if (!this._vmState.alive || this._disposed || this._settled) return;\n this._cpuDeadline = Date.now() + this._cpuBurstMs;\n const result = this._vm.evalCode(\n `globalThis[${JSON.stringify(name)}](...${JSON.stringify(args)})`,\n );\n if (result.error) {\n const dumped = this._vm.dump(result.error);\n result.error.dispose();\n const error = _toError(dumped);\n this._settleError(error.message, _formatGuestError(dumped));\n return;\n }\n result.value.dispose();\n this._pump();\n }\n\n private _registerAsyncHostFn(\n name: string,\n impl: (\n a: string,\n b: string,\n c: string,\n emit: (payloadJson: string) => void,\n ) => Promise<string>,\n label: (a: string, b: string, c: string) => string,\n guestEventHandler?: string,\n ): void {\n this._vm.newFunction(name, (aH, bH, cH, eventIdH) => {\n const a = aH ? this._vm.getString(aH) : \"\";\n const b = bH ? this._vm.getString(bH) : \"\";\n const c = cH ? this._vm.getString(cH) : \"\";\n const eventId = eventIdH ? this._vm.getString(eventIdH) : \"\";\n const deferred = this._vm.newPromise();\n if (this._vmState.softAborted) {\n const reason = this._vmState.softAbortReason ?? \"soft deadline reached\";\n this._vm.newError(`AbortError: ${reason} (refused: ${label(a, b, c)})`)\n .consume((errH) => deferred.reject(errH));\n deferred.settled.then(() => this._pump());\n return deferred.handle;\n }\n this._pendingDeferreds.set(deferred, label(a, b, c));\n impl(a, b, c, (payloadJson) => {\n if (guestEventHandler && eventId !== \"\") {\n this._dispatchGuestFunction(guestEventHandler, eventId, payloadJson);\n }\n }).then(\n (value) => {\n this._pendingDeferreds.delete(deferred);\n if (!this._vmState.alive || !deferred.alive) return;\n this._vm.newString(value).consume((sH) => deferred.resolve(sH));\n },\n (err: unknown) => {\n this._pendingDeferreds.delete(deferred);\n if (!this._vmState.alive || !deferred.alive) return;\n this._newGuestHostError(err).consume((errH) => deferred.reject(errH));\n },\n );\n // Pump once the promise settles so the guest continuation runs.\n deferred.settled.then(() => this._pump());\n return deferred.handle;\n }).consume((fn) => this._vm.setProp(this._vm.global, name, fn));\n }\n\n private _newGuestHostError(thrown: unknown): QuickJSHandle {\n const snapshot = _snapshotHostRejection(thrown);\n const source = `(() => {\n const error = new Error(${JSON.stringify(snapshot.summary)});\n const properties = JSON.parse(${JSON.stringify(JSON.stringify(snapshot.properties))});\n for (const [key, value] of Object.entries(properties)) {\n Object.defineProperty(error, key, {\n value,\n writable: true,\n enumerable: true,\n configurable: true,\n });\n }\n return error;\n })()`;\n const result = this._vm.evalCode(source);\n if (result.error) {\n result.error.dispose();\n return this._vm.newError(snapshot.summary);\n }\n return result.value;\n }\n}\n\ninterface HostRejectionSnapshot {\n readonly summary: string;\n readonly properties: Readonly<Record<string, unknown>>;\n}\n\nconst MAX_REJECTION_DEPTH = 8;\nconst MAX_REJECTION_PROPERTIES = 100;\nconst MAX_REJECTION_ARRAY_ITEMS = 100;\nconst MAX_REJECTION_STRING_LENGTH = 20_000;\nconst MAX_REJECTION_NODES = 1_000;\nconst MAX_REJECTION_TOTAL_STRING_LENGTH = 100_000;\n\ninterface SnapshotBudget {\n nodes: number;\n stringChars: number;\n}\n\nfunction _snapshotHostRejection(thrown: unknown): HostRejectionSnapshot {\n return {\n summary: _rejectionSummary(thrown),\n properties: _snapshotOwnDataProperties(thrown),\n };\n}\n\nfunction _rejectionSummary(thrown: unknown): string {\n if (thrown === null) return \"Host operation rejected with null\";\n if (typeof thrown !== \"object\" && typeof thrown !== \"function\") {\n return `Host operation rejected with ${String(thrown)}`;\n }\n return \"Host operation failed\";\n}\n\nfunction _snapshotOwnDataProperties(value: unknown): Readonly<Record<string, unknown>> {\n if ((typeof value !== \"object\" || value === null) && typeof value !== \"function\") {\n return { value: _snapshotBridgeValue(value, new WeakSet(), 0, _newSnapshotBudget()) };\n }\n let descriptors: PropertyDescriptorMap;\n try {\n descriptors = Object.getOwnPropertyDescriptors(value);\n } catch {\n return {};\n }\n const seen = new WeakSet<object>();\n seen.add(value as object);\n const budget = _newSnapshotBudget();\n const result: Record<string, unknown> = {};\n for (const [key, descriptor] of Object.entries(descriptors).slice(0, MAX_REJECTION_PROPERTIES)) {\n if (!(\"value\" in descriptor)) continue;\n result[key] = _snapshotBridgeValue(descriptor.value, seen, 0, budget);\n }\n return result;\n}\n\nfunction _newSnapshotBudget(): SnapshotBudget {\n return {\n nodes: MAX_REJECTION_NODES,\n stringChars: MAX_REJECTION_TOTAL_STRING_LENGTH,\n };\n}\n\nfunction _snapshotBridgeValue(\n value: unknown,\n seen: WeakSet<object>,\n depth: number,\n budget: SnapshotBudget,\n): unknown {\n if (budget.nodes <= 0) return \"[Truncated]\";\n budget.nodes--;\n if (value === null || typeof value === \"boolean\" || typeof value === \"number\") return value;\n if (typeof value === \"string\") {\n const available = Math.min(MAX_REJECTION_STRING_LENGTH, budget.stringChars);\n budget.stringChars -= Math.min(value.length, available);\n return value.length <= available ? value : `${value.slice(0, available)}…`;\n }\n if (typeof value === \"undefined\") return \"[undefined]\";\n if (typeof value === \"bigint\") return `${value}n`;\n if (typeof value === \"symbol\") return String(value);\n if (typeof value === \"function\") return `[Function${value.name ? `: ${value.name}` : \"\"}]`;\n if (depth >= MAX_REJECTION_DEPTH) return \"[Truncated]\";\n if (seen.has(value)) return \"[Circular]\";\n seen.add(value);\n if (Array.isArray(value)) {\n return value\n .slice(0, MAX_REJECTION_ARRAY_ITEMS)\n .map((item) => _snapshotBridgeValue(item, seen, depth + 1, budget));\n }\n let descriptors: PropertyDescriptorMap;\n try {\n descriptors = Object.getOwnPropertyDescriptors(value);\n } catch {\n return \"[Uninspectable]\";\n }\n const result: Record<string, unknown> = {};\n for (const [key, descriptor] of Object.entries(descriptors).slice(0, MAX_REJECTION_PROPERTIES)) {\n if (!(\"value\" in descriptor)) continue;\n result[key] = _snapshotBridgeValue(descriptor.value, seen, depth + 1, budget);\n }\n return result;\n}\n\nfunction _evalPrelude(vm: QuickJSContext, lastResultVal: unknown): void {\n // Per-run globals the bundled guest runtime reads by bare name\n // (`__lastResultVal`, `__docs`). Everything else — `con`, `console`, the\n // host marshalling — lives in `GUEST_RUNTIME_JS` (compiled from\n // `src/guest/guestMain.ts`).\n const header =\n `globalThis.__lastResultVal = JSON.parse(${JSON.stringify(JSON.stringify(lastResultVal ?? null))});\\n` +\n `globalThis.__docs = ${JSON.stringify(CONNECTION_DTS)};\\n`;\n const r = vm.evalCode(header + GUEST_RUNTIME_JS);\n if (r.error) {\n const err = vm.dump(r.error);\n r.error.dispose();\n throw new Error(`sandbox prelude failed: ${JSON.stringify(err)}`);\n }\n r.value.dispose();\n}\n\nfunction _wrapUserCode(userCode: string): string {\n // The user expression must evaluate to a function. We invoke it with\n // `{ con, lastResultVal, mcp }`, await its result, and JSON-stringify so the\n // host sees a plain string.\n return `(async () => {\n const __userFn = (${userCode});\n if (typeof __userFn !== \"function\") {\n throw new Error(\"runLinkRpcScript: \\`code\\` must evaluate to a function, got \" + typeof __userFn);\n }\n const __r = await __userFn({ con, lastResultVal: __lastResultVal, mcp });\n return __r === undefined ? \"\" : JSON.stringify(__r);\n})()`;\n}\n\nfunction _firstLine(code: string): string {\n const line = code.split(\"\\n\", 1)[0].trim();\n return line.length > 80 ? `${line.slice(0, 79)}…` : line;\n}\n\nfunction _toError(dumped: unknown): Error {\n let json: string;\n try { json = JSON.stringify(dumped); } catch { json = String(dumped); }\n if (dumped && typeof dumped === \"object\") {\n const d = dumped as { name?: unknown; message?: unknown; stack?: unknown };\n const hasMsg = typeof d.message === \"string\" && d.message.length > 0;\n const message = hasMsg ? (d.message as string) : `guest error (raw): ${json}`;\n const e = new Error(message);\n if (typeof d.stack === \"string\") (e as { stack?: string }).stack = d.stack;\n return e;\n }\n return new Error(`guest error: ${json}`);\n}\n\n/**\n * Format a dumped guest error as `message` plus its guest stack (when QuickJS\n * provided one). The host only forwards the `error` string to the caller, so\n * folding the stack in here is the only way the guest trace ever reaches them.\n */\nfunction _formatGuestError(dumped: unknown): string {\n const e = _toError(dumped);\n const stack = (e as { stack?: string }).stack;\n if (typeof stack === \"string\" && stack.length > 0) {\n return stack.includes(e.message) ? stack : `${e.message}\\n${stack}`;\n }\n return e.message;\n}\n","import type { ParkedTask, SandboxLog, TaskOutcome } from \"./sandbox\";\n\n/** Snapshot of a live task, returned by {@link TaskRegistry.list}. */\nexport interface TaskInfo {\n readonly taskId: string;\n readonly debugName: string;\n readonly endpoint: string;\n readonly ageMs: number;\n readonly inFlight: readonly string[];\n readonly logCount: number;\n}\n\n/** Result of {@link TaskRegistry.awaitTask} / {@link TaskRegistry.cancel}. */\nexport type AwaitResult =\n | { readonly status: \"running\"; readonly taskId: string; readonly debugName: string; readonly inFlight: readonly string[]; readonly logs: readonly SandboxLog[] }\n | { readonly status: \"completed\"; readonly taskId: string; readonly debugName: string; readonly result: unknown; readonly logs: readonly SandboxLog[] }\n | { readonly status: \"error\"; readonly taskId: string; readonly debugName: string; readonly error: string; readonly logs: readonly SandboxLog[] }\n | { readonly status: \"cancelled\"; readonly taskId: string; readonly debugName: string; readonly logs: readonly SandboxLog[] }\n | { readonly status: \"unknown\"; readonly taskId: string };\n\n/** Info about a task that was superseded by a newer request. */\nexport interface SupersededInfo {\n readonly taskId: string;\n readonly debugName: string;\n readonly outcome: \"cancelled\";\n}\n\ninterface Entry {\n readonly id: string;\n readonly debugName: string;\n readonly endpoint: string;\n readonly startedAt: number;\n readonly task: ParkedTask;\n outcome: TaskOutcome | undefined;\n}\n\n/**\n * Tracks parked sandbox tasks. At most one task is \"live\" at a time across all\n * connections: starting a new one supersedes (cancels) the previous one via\n * {@link cancelLive}. Settled tasks are retained so their result can still be\n * fetched by id, and pruned opportunistically.\n */\nexport class TaskRegistry {\n private readonly _byId = new Map<string, Entry>();\n private _live: Entry | undefined;\n private _seq = 0;\n\n public constructor(private readonly _maxSettledAgeMs = 5 * 60_000) {}\n\n /**\n * Register a freshly parked task. Assigns a task id and wires up settlement\n * bookkeeping. `onComplete` fires with the result when the task completes\n * (used to thread `lastResultVal`).\n */\n public register(\n endpoint: string,\n debugName: string,\n task: ParkedTask,\n onComplete?: (result: unknown) => void,\n ): string {\n this._prune();\n const id = `t${++this._seq}`;\n const entry: Entry = {\n id,\n debugName,\n endpoint,\n startedAt: Date.now(),\n task,\n outcome: undefined,\n };\n this._byId.set(id, entry);\n this._live = entry;\n task.done.then(\n (o) => {\n entry.outcome = o;\n if (this._live === entry) {\n this._live = undefined;\n }\n if (o.status === \"completed\") onComplete?.(o.result);\n },\n () => { /* task.done never rejects */ },\n );\n return id;\n }\n\n /**\n * Cancel the single live task, if any (the supersede path). Resolves once\n * the cancellation settles.\n */\n public async cancelLive(): Promise<SupersededInfo | undefined> {\n const entry = this._live;\n if (!entry) return undefined;\n this._live = undefined;\n await entry.task.cancel();\n return { taskId: entry.id, debugName: entry.debugName, outcome: \"cancelled\" };\n }\n\n /**\n * Wait up to `timeoutMs` for `taskId` to settle. Returns `running` (with a\n * progress snapshot) if it is still going, otherwise its terminal result.\n */\n public async awaitTask(taskId: string, timeoutMs: number): Promise<AwaitResult> {\n const entry = this._byId.get(taskId);\n if (!entry) return { status: \"unknown\", taskId };\n if (!entry.outcome) {\n const timeout = new Promise<\"timeout\">((r) => {\n setTimeout(() => r(\"timeout\"), timeoutMs).unref?.();\n });\n const res = await Promise.race([entry.task.done, timeout]);\n if (res === \"timeout\") {\n return {\n status: \"running\",\n taskId,\n debugName: entry.debugName,\n inFlight: entry.task.inFlight(),\n logs: [...entry.task.logs],\n };\n }\n }\n return this._outcomeResult(entry);\n }\n\n /** Explicitly cancel a task by id. */\n public async cancel(taskId: string): Promise<AwaitResult> {\n const entry = this._byId.get(taskId);\n if (!entry) return { status: \"unknown\", taskId };\n await entry.task.cancel();\n return this._outcomeResult(entry);\n }\n\n /** List live (unsettled) tasks. At most one under the global invariant. */\n public list(): TaskInfo[] {\n const out: TaskInfo[] = [];\n for (const e of this._byId.values()) {\n if (e.outcome) continue;\n out.push({\n taskId: e.id,\n debugName: e.debugName,\n endpoint: e.endpoint,\n ageMs: Date.now() - e.startedAt,\n inFlight: e.task.inFlight(),\n logCount: e.task.logs.length,\n });\n }\n return out;\n }\n\n /** Cancel every live task. */\n public dispose(): void {\n for (const e of this._byId.values()) {\n if (!e.outcome) void e.task.cancel();\n }\n this._byId.clear();\n this._live = undefined;\n }\n\n private _outcomeResult(entry: Entry): AwaitResult {\n const o = entry.outcome;\n if (!o) {\n return {\n status: \"running\",\n taskId: entry.id,\n debugName: entry.debugName,\n inFlight: entry.task.inFlight(),\n logs: [...entry.task.logs],\n };\n }\n if (o.status === \"completed\") {\n return { status: \"completed\", taskId: entry.id, debugName: entry.debugName, result: o.result, logs: o.logs };\n }\n if (o.status === \"cancelled\") {\n return { status: \"cancelled\", taskId: entry.id, debugName: entry.debugName, logs: o.logs };\n }\n return { status: \"error\", taskId: entry.id, debugName: entry.debugName, error: o.error, logs: o.logs };\n }\n\n private _prune(): void {\n const cutoff = Date.now() - this._maxSettledAgeMs;\n for (const [id, e] of this._byId) {\n if (e.outcome && e.startedAt < cutoff) this._byId.delete(id);\n }\n }\n}\n","import type { LinkRpcInterfaceSchema, IRequestSender, SigningCallCtx } from '@hediet/linkrpc';\nimport { generateTsInterface } from '@hediet/linkrpc';\nimport { type DiscoveredListing, fetchSchema, walkHubDetailed } from '@hediet/linkrpc-client';\n\ninterface ExploreCommonArgs {\n /** Exact directory-level filters, applied before browsing or searching. */\n readonly serviceId?: string;\n readonly interfaceId?: string;\n /** Include reflection plumbing such as `hubrpc.directory` and `hubrpc.schemas`. */\n readonly includeInternal?: boolean;\n /** Request one broad reflection grant when a gated directory is encountered. */\n readonly requestPermission?: boolean;\n}\n\nexport interface ExploreBrowseArgs extends ExploreCommonArgs {\n readonly kind: 'browse';\n /** Number of interfaces to return. Defaults to 20; maximum 100. */\n readonly limit?: number;\n /** Opaque continuation cursor returned by a previous browse call. */\n readonly cursor?: string;\n}\n\nexport interface ExploreGrepArgs extends ExploreCommonArgs {\n readonly kind: 'grep';\n /** Pattern searched against the generated `defineInterface` source, one line at a time. */\n readonly pattern: string;\n /** Defaults to `regex`. Both modes are case-insensitive. */\n readonly syntax?: 'regex' | 'literal';\n /** Number of matching virtual documents to return. Defaults to 20; maximum 100. */\n readonly limit?: number;\n /** Opaque continuation cursor returned by a previous grep call. */\n readonly cursor?: string;\n /** Source lines included before and after each match. Defaults to 1; maximum 5. */\n readonly contextLines?: number;\n}\n\nexport interface ExploreInspectArgs extends ExploreCommonArgs {\n readonly kind: 'inspect';\n readonly serviceId: string;\n readonly interfaceId: string;\n /** Generated `defineInterface` source by default; use `schema` for the raw wire schema. */\n readonly format?: 'source' | 'schema';\n}\n\nexport type ExploreArgs = ExploreBrowseArgs | ExploreGrepArgs | ExploreInspectArgs;\n\nexport interface ExploreDeps {\n requestReflectionAccess(): Promise<boolean>;\n}\n\nexport interface ExploreListing {\n readonly serviceId: string;\n readonly serviceDescription?: string;\n readonly interfaceId: string;\n readonly interfaceHash: string;\n readonly documentId: string;\n}\n\nexport interface ExploreGrepMatch {\n /** Matching source plus the requested surrounding context, joined with newlines. */\n readonly searchResult: string;\n /** Inclusive, 1-based line range of `searchResult` in the virtual document. */\n readonly lineRange: readonly [start: number, end: number];\n /** LinkRPC member containing every matched line in this chunk, when unambiguous. */\n readonly member?: string;\n}\n\nexport interface ExploreGrepEntry extends ExploreListing {\n readonly matches: readonly ExploreGrepMatch[];\n /** True when this document contains more matches than were returned. */\n readonly matchesTruncated?: boolean;\n}\n\nexport interface ExploreDocumentError {\n readonly serviceId: string;\n readonly interfaceId: string;\n readonly error: string;\n}\n\nexport interface ExploreInaccessible {\n readonly serviceId: string;\n readonly reason: string;\n readonly hint: string;\n}\n\nexport interface ExploreBrowseResult {\n readonly kind: 'browse';\n readonly total: number;\n readonly entries: readonly ExploreListing[];\n readonly nextCursor?: string;\n readonly inaccessible?: readonly ExploreInaccessible[];\n}\n\nexport interface ExploreGrepResult {\n readonly kind: 'grep';\n readonly pattern: string;\n readonly syntax: 'regex' | 'literal';\n readonly total: number;\n readonly entries: readonly ExploreGrepEntry[];\n readonly nextCursor?: string;\n readonly documentErrors?: readonly ExploreDocumentError[];\n readonly inaccessible?: readonly ExploreInaccessible[];\n}\n\nexport interface ExploreInspectResult extends ExploreListing {\n readonly kind: 'inspect';\n readonly format: 'source' | 'schema';\n readonly source?: string;\n readonly schema?: LinkRpcInterfaceSchema;\n readonly inaccessible?: readonly ExploreInaccessible[];\n}\n\nexport type ExploreResult = ExploreBrowseResult | ExploreGrepResult | ExploreInspectResult;\n\ninterface CachedInterface {\n readonly schema: LinkRpcInterfaceSchema;\n readonly generatedSource: string;\n}\n\ninterface VirtualDocument extends CachedInterface {\n readonly listing: DiscoveredListing;\n readonly source: string;\n}\n\nconst DEFAULT_LIMIT = 20;\nconst MAX_LIMIT = 100;\nconst MAX_MATCHES_PER_DOCUMENT = 20;\nconst interfaceCache = new WeakMap<object, Map<string, Promise<CachedInterface>>>();\n\n/**\n * Browse the reflected directory, grep generated interface source, or inspect\n * one exact virtual document. Generated source is cached by the directory\n * route and interface hash; every call still walks the live directory.\n */\nexport async function explore(\n channel: IRequestSender<SigningCallCtx>,\n args: ExploreArgs,\n deps?: ExploreDeps,\n): Promise<ExploreResult> {\n if (args === undefined || typeof args !== 'object' || !('kind' in args)) {\n throw new Error('explore requires `kind: \"browse\" | \"grep\" | \"inspect\"`.');\n }\n\n const unlockGatedDirectory = args.requestPermission === true && deps !== undefined\n ? (_serviceId: string) => deps.requestReflectionAccess()\n : undefined;\n const walked = await walkHubDetailed(channel, { unlockGatedDirectory });\n const listings = _filterAndSort(walked.listings, args);\n const inaccessible = _inaccessible(walked.inaccessible);\n\n switch (args.kind) {\n case 'browse': {\n const page = _page(listings, args.limit, args.cursor);\n return {\n kind: 'browse',\n total: listings.length,\n entries: page.items.map(_toListing),\n ...(page.nextCursor !== undefined ? { nextCursor: page.nextCursor } : {}),\n ...(inaccessible !== undefined ? { inaccessible } : {}),\n };\n }\n case 'grep': {\n if (typeof args.pattern !== 'string' || args.pattern.length === 0) {\n throw new Error('explore grep requires a non-empty `pattern`.');\n }\n const syntax = args.syntax ?? 'regex';\n const matchesLine = _createLineMatcher(args.pattern, syntax);\n const contextLines = _boundedInteger(args.contextLines ?? 1, 0, 5, 'contextLines');\n const loaded = await Promise.all(listings.map(async (listing) => {\n try {\n return { document: await _loadDocument(channel, listing) };\n } catch (error) {\n return {\n error: {\n serviceId: listing.serviceId,\n interfaceId: listing.interfaceId,\n error: (error as Error).message,\n },\n };\n }\n }));\n const entries: ExploreGrepEntry[] = [];\n const documentErrors: ExploreDocumentError[] = [];\n for (const item of loaded) {\n if (item.error !== undefined) {\n documentErrors.push(item.error);\n continue;\n }\n const document = item.document!;\n const matches = _grepDocument(document, matchesLine, contextLines);\n if (matches.length === 0) continue;\n entries.push({\n ..._toListing(document.listing),\n matches: matches.slice(0, MAX_MATCHES_PER_DOCUMENT),\n ...(matches.length > MAX_MATCHES_PER_DOCUMENT ? { matchesTruncated: true } : {}),\n });\n }\n const page = _page(entries, args.limit, args.cursor);\n return {\n kind: 'grep',\n pattern: args.pattern,\n syntax,\n total: entries.length,\n entries: page.items,\n ...(page.nextCursor !== undefined ? { nextCursor: page.nextCursor } : {}),\n ...(documentErrors.length > 0 ? { documentErrors } : {}),\n ...(inaccessible !== undefined ? { inaccessible } : {}),\n };\n }\n case 'inspect': {\n const listing = listings.find((item) =>\n item.serviceId === args.serviceId && item.interfaceId === args.interfaceId,\n );\n if (listing === undefined) {\n throw new Error(\n `Interface not found: ${args.serviceId}::${args.interfaceId}. `\n + 'Browse first, or set `requestPermission: true` if its directory is gated.',\n );\n }\n const document = await _loadDocument(channel, listing);\n const format = args.format ?? 'source';\n return {\n kind: 'inspect',\n format,\n ..._toListing(listing),\n ...(format === 'source' ? { source: document.source } : { schema: document.schema }),\n ...(inaccessible !== undefined ? { inaccessible } : {}),\n };\n }\n default:\n throw new Error(`Unknown explore kind: ${String((args as { kind?: unknown }).kind)}`);\n }\n}\n\nfunction _filterAndSort(\n listings: readonly DiscoveredListing[],\n args: ExploreArgs,\n): DiscoveredListing[] {\n const includeInternal = args.includeInternal === true\n || (args.interfaceId !== undefined && _isHubrpcInternalInterface(args.interfaceId));\n return listings\n .filter((listing) => {\n if (args.serviceId !== undefined && listing.serviceId !== args.serviceId) return false;\n if (args.interfaceId !== undefined && listing.interfaceId !== args.interfaceId) return false;\n return includeInternal || !_isHubrpcInternalInterface(listing.interfaceId);\n })\n .sort((a, b) =>\n a.serviceId.localeCompare(b.serviceId)\n || a.interfaceId.localeCompare(b.interfaceId)\n || a.hash.localeCompare(b.hash),\n );\n}\n\nfunction _toListing(listing: DiscoveredListing): ExploreListing {\n return {\n serviceId: listing.serviceId,\n ...(listing.serviceDescription !== undefined\n ? { serviceDescription: listing.serviceDescription }\n : {}),\n interfaceId: listing.interfaceId,\n interfaceHash: listing.hash,\n documentId: _documentId(listing),\n };\n}\n\nasync function _loadDocument(\n channel: IRequestSender<SigningCallCtx>,\n listing: DiscoveredListing,\n): Promise<VirtualDocument> {\n let cache = interfaceCache.get(channel as object);\n if (cache === undefined) {\n cache = new Map();\n interfaceCache.set(channel as object, cache);\n }\n const cacheKey = `${listing.discoveredFrom}\\u0000${listing.interfaceId}\\u0000${listing.hash}`;\n let pending = cache.get(cacheKey);\n if (pending === undefined) {\n pending = (async () => {\n const target = listing.discoveredFrom || listing.serviceId || undefined;\n const schema = await fetchSchema(channel, listing.interfaceId, listing.hash, target);\n return { schema, generatedSource: generateTsInterface(schema) };\n })();\n cache.set(cacheKey, pending);\n }\n\n let cached: CachedInterface;\n try {\n cached = await pending;\n } catch (error) {\n if (cache.get(cacheKey) === pending) cache.delete(cacheKey);\n throw error;\n }\n const documentId = _documentId(listing);\n return {\n ...cached,\n listing,\n source: `${_documentHeader(listing, documentId)}\\n${cached.generatedSource}`,\n };\n}\n\nfunction _documentHeader(listing: DiscoveredListing, documentId: string): string {\n return [\n `// virtualDocument: ${JSON.stringify(documentId)}`,\n `// serviceId: ${JSON.stringify(listing.serviceId)}`,\n ...(listing.serviceDescription !== undefined\n ? [`// serviceDescription: ${JSON.stringify(listing.serviceDescription)}`]\n : []),\n `// interfaceId: ${JSON.stringify(listing.interfaceId)}`,\n `// interfaceHash: ${JSON.stringify(listing.hash)}`,\n `// discoveredFrom: ${JSON.stringify(listing.discoveredFrom)}`,\n ].join('\\n');\n}\n\nfunction _documentId(listing: DiscoveredListing): string {\n const service = listing.serviceId === '' ? '$root' : encodeURIComponent(listing.serviceId);\n const interfaceId = encodeURIComponent(listing.interfaceId);\n return `linkrpc://${service}/${interfaceId}@${listing.hash}.ts`;\n}\n\nfunction _grepDocument(\n document: VirtualDocument,\n matchesLine: (line: string) => boolean,\n contextLines: number,\n): ExploreGrepMatch[] {\n const lines = document.source.split('\\n');\n const memberAtLine = _memberMap(lines, document.schema);\n const ranges: Array<{ start: number; end: number; matches: number[] }> = [];\n for (let index = 0; index < lines.length; index++) {\n if (!matchesLine(lines[index])) continue;\n const start = Math.max(0, index - contextLines);\n const end = Math.min(lines.length, index + contextLines + 1);\n const previous = ranges.at(-1);\n if (previous !== undefined && start <= previous.end) {\n previous.end = Math.max(previous.end, end);\n previous.matches.push(index);\n } else {\n ranges.push({ start, end, matches: [index] });\n }\n }\n return ranges.map((range) => {\n const members = new Set(range.matches.map((line) => memberAtLine[line]));\n const member = members.size === 1 ? members.values().next().value : undefined;\n return {\n searchResult: lines.slice(range.start, range.end).join('\\n'),\n lineRange: [range.start + 1, range.end],\n ...(member !== undefined ? { member } : {}),\n };\n });\n}\n\nfunction _memberMap(lines: readonly string[], schema: LinkRpcInterfaceSchema): Array<string | undefined> {\n const starts: Array<{ line: number; member: string }> = [];\n let searchFrom = 0;\n for (const methodName of Object.keys(schema.methods)) {\n const barePrefix = `${methodName}: `;\n const quotedPrefix = `${JSON.stringify(methodName)}: `;\n const line = lines.findIndex((value, index) => index >= searchFrom\n && (value.trimStart().startsWith(barePrefix) || value.trimStart().startsWith(quotedPrefix))\n && (value.includes('requestType(') || value.includes('notificationType(')));\n if (line >= 0) {\n starts.push({ line, member: methodName });\n searchFrom = line + 1;\n }\n }\n\n const result = new Array<string | undefined>(lines.length);\n for (let i = 0; i < starts.length; i++) {\n const end = starts[i + 1]?.line ?? lines.length;\n for (let line = starts[i].line; line < end; line++) result[line] = starts[i].member;\n }\n return result;\n}\n\nfunction _createLineMatcher(\n pattern: string,\n syntax: 'regex' | 'literal',\n): (line: string) => boolean {\n if (syntax === 'literal') {\n const needle = pattern.toLocaleLowerCase();\n return (line) => line.toLocaleLowerCase().includes(needle);\n }\n if (syntax !== 'regex') throw new Error(`Unknown grep syntax: ${String(syntax)}`);\n let regex: RegExp;\n try {\n regex = new RegExp(pattern, 'iu');\n } catch (error) {\n throw new Error(`Invalid grep regular expression: ${(error as Error).message}`);\n }\n return (line) => regex.test(line);\n}\n\nfunction _page<T>(\n items: readonly T[],\n requestedLimit: number | undefined,\n cursor: string | undefined,\n): { items: readonly T[]; nextCursor?: string } {\n const limit = _boundedInteger(requestedLimit ?? DEFAULT_LIMIT, 1, MAX_LIMIT, 'limit');\n const offset = _decodeCursor(cursor);\n const page = items.slice(offset, offset + limit);\n const nextOffset = offset + page.length;\n return {\n items: page,\n ...(nextOffset < items.length ? { nextCursor: String(nextOffset) } : {}),\n };\n}\n\nfunction _decodeCursor(cursor: string | undefined): number {\n if (cursor === undefined) return 0;\n if (!/^\\d+$/.test(cursor)) throw new Error('Invalid explore cursor.');\n return Number(cursor);\n}\n\nfunction _boundedInteger(value: number, min: number, max: number, name: string): number {\n if (!Number.isInteger(value) || value < min || value > max) {\n throw new Error(`explore ${name} must be an integer from ${min} to ${max}.`);\n }\n return value;\n}\n\nfunction _inaccessible(\n directories: readonly { serviceId: string; reason: string }[],\n): ExploreInaccessible[] | undefined {\n if (directories.length === 0) return undefined;\n return directories.map((directory) => ({\n serviceId: directory.serviceId,\n reason: directory.reason,\n hint: 'Repeat this explore call with `requestPermission: true` to search all gated directories.',\n }));\n}\n\nfunction _isHubrpcInternalInterface(interfaceId: string): boolean {\n return interfaceId.startsWith('hubrpc.');\n}\n","import { createHash } from \"crypto\";\nimport {\n ContentBlockSchema,\n type CallToolResult,\n type ContentBlock,\n} from \"@modelcontextprotocol/sdk/types.js\";\n\nexport const MCP_PRESENTATION_TAG = \"__linkrpcMcpPresentationV1\";\n\nexport type ResultPresentationMode = \"auto\" | \"raw\";\n\ninterface PresentationState {\n readonly content: ContentBlock[];\n isError?: boolean;\n meta?: Record<string, unknown>;\n}\n\ninterface AutomaticContent {\n readonly block: ContentBlock;\n readonly metadata?: Readonly<Record<string, unknown>>;\n}\n\ninterface PresentationTag {\n readonly kind: \"raw\" | \"result\" | \"content\";\n readonly value?: unknown;\n readonly content?: unknown;\n readonly structuredContent?: unknown;\n readonly isError?: unknown;\n readonly _meta?: unknown;\n}\n\n/**\n * Convert a JSON tool-result envelope into MCP-native content while preserving a\n * JSON text fallback for clients that only consume text.\n */\nexport function presentToolResult(\n envelope: Readonly<Record<string, unknown>>,\n mode: ResultPresentationMode = \"auto\",\n): CallToolResult {\n if (mode === \"raw\") {\n const rawEnvelope = stripPresentationTags(envelope);\n const resultOptions = findExplicitResultOptions(envelope);\n return {\n content: [{ type: \"text\", text: JSON.stringify(rawEnvelope, null, 2) }],\n structuredContent: rawEnvelope as Record<string, unknown>,\n ...resultOptions,\n };\n }\n\n const state: PresentationState = { content: [] };\n const structuredContent = presentValue(envelope, \"$\", state) as Record<string, unknown>;\n return {\n content: [\n { type: \"text\", text: JSON.stringify(structuredContent, null, 2) },\n ...state.content,\n ],\n structuredContent,\n ...(state.isError !== undefined ? { isError: state.isError } : {}),\n ...(state.meta ? { _meta: state.meta } : {}),\n };\n}\n\n/** Remove presentation-only wrappers before persisting a script result. */\nexport function scriptResultValue(value: unknown): unknown {\n return stripPresentationTags(value);\n}\n\nfunction presentValue(value: unknown, path: string, state: PresentationState): unknown {\n const tag = getPresentationTag(value);\n if (tag?.kind === \"raw\") {\n return stripPresentationTags(tag.value);\n }\n if (tag?.kind === \"result\") {\n if (tag.isError !== undefined) {\n if (typeof tag.isError !== \"boolean\") {\n throw new Error(`Invalid MCP result isError at ${path}: expected boolean`);\n }\n state.isError = tag.isError;\n }\n if (tag._meta !== undefined) {\n if (!isRecord(tag._meta)) {\n throw new Error(`Invalid MCP result _meta at ${path}: expected object`);\n }\n state.meta = tag._meta;\n }\n const selected = Object.hasOwn(tag, \"structuredContent\")\n ? tag.structuredContent\n : Object.hasOwn(tag, \"value\")\n ? tag.value\n : null;\n const presented = presentValue(selected, path, state);\n const content = Array.isArray(tag.content) ? tag.content : [];\n for (let i = 0; i < content.length; i++) {\n addExplicitContent(content[i], `${path}.content[${i}]`, state);\n }\n return presented;\n }\n if (tag?.kind === \"content\") {\n const block = parseExplicitContent(tag.content, path);\n state.content.push(block);\n return describeContent(block, path);\n }\n\n const explicitContent = ContentBlockSchema.safeParse(value);\n if (explicitContent.success) {\n state.content.push(explicitContent.data);\n return describeContentWithMetadata(\n explicitContent.data,\n contentBlockMetadata(value as Record<string, unknown>, explicitContent.data),\n path,\n state,\n );\n }\n\n const automaticContent = detectAutomaticContent(value);\n if (automaticContent) {\n state.content.push(automaticContent.block);\n return describeContentWithMetadata(\n automaticContent.block,\n automaticContent.metadata,\n path,\n state,\n );\n }\n\n if (Array.isArray(value)) {\n return value.map((item, index) => presentValue(item, `${path}[${index}]`, state));\n }\n if (isRecord(value)) {\n const result: Record<string, unknown> = {};\n for (const [key, item] of Object.entries(value)) {\n result[key] = presentValue(item, `${path}.${key}`, state);\n }\n return result;\n }\n return value;\n}\n\nfunction addExplicitContent(value: unknown, path: string, state: PresentationState): void {\n const tag = getPresentationTag(value);\n state.content.push(parseExplicitContent(tag?.kind === \"content\" ? tag.content : value, path));\n}\n\nfunction parseExplicitContent(value: unknown, path: string): ContentBlock {\n const parsed = ContentBlockSchema.safeParse(value);\n if (parsed.success) {\n return parsed.data;\n }\n throw new Error(`Invalid MCP content block at ${path}: ${parsed.error.message}`);\n}\n\nfunction detectAutomaticContent(value: unknown): AutomaticContent | undefined {\n if (typeof value === \"string\") {\n const dataUrl = parseDataUrl(value);\n if (dataUrl) {\n return { block: blockForBinary(dataUrl.data, dataUrl.mimeType) };\n }\n const base64 = normalizeBase64(value);\n if (!base64) {\n return undefined;\n }\n const mimeType = sniffMimeType(base64);\n return mimeType ? { block: blockForBinary(base64, mimeType) } : undefined;\n }\n\n if (!isRecord(value) || typeof value.mimeType !== \"string\") {\n return undefined;\n }\n\n if (typeof value.text === \"string\") {\n return {\n block: {\n type: \"resource\",\n resource: {\n uri: typeof value.uri === \"string\"\n ? value.uri\n : contentUrn(value.mimeType, value.text),\n mimeType: value.mimeType,\n text: value.text,\n },\n },\n metadata: contentMetadata(value),\n };\n }\n\n const encoded = [value.data, value.base64, value.blob]\n .find((candidate): candidate is string => typeof candidate === \"string\");\n if (!encoded) {\n return undefined;\n }\n const dataUrl = parseDataUrl(encoded);\n const data = dataUrl?.data ?? normalizeBase64(encoded);\n if (!data) {\n return undefined;\n }\n const block = blockForBinary(\n data,\n dataUrl?.mimeType ?? value.mimeType,\n typeof value.uri === \"string\" ? value.uri : undefined,\n );\n return { block, metadata: contentMetadata(value) };\n}\n\nfunction blockForBinary(data: string, mimeType: string, uri?: string): ContentBlock {\n if (mimeType.startsWith(\"image/\")) {\n return { type: \"image\", data, mimeType };\n }\n if (mimeType.startsWith(\"audio/\")) {\n return { type: \"audio\", data, mimeType };\n }\n return {\n type: \"resource\",\n resource: {\n uri: uri ?? contentUrn(mimeType, data),\n mimeType,\n blob: data,\n },\n };\n}\n\nfunction describeContent(content: ContentBlock, path: string): unknown {\n switch (content.type) {\n case \"text\":\n return content.text;\n case \"image\":\n case \"audio\":\n return {\n $content: {\n type: content.type,\n mimeType: content.mimeType,\n bytes: base64ByteLength(content.data),\n path,\n },\n };\n case \"resource_link\":\n return {\n $content: {\n type: content.type,\n uri: content.uri,\n name: content.name,\n ...(content.mimeType ? { mimeType: content.mimeType } : {}),\n ...(content.size !== undefined ? { size: content.size } : {}),\n path,\n },\n };\n case \"resource\": {\n const resource = content.resource;\n return {\n $content: {\n type: content.type,\n uri: resource.uri,\n ...(resource.mimeType ? { mimeType: resource.mimeType } : {}),\n ...(\"blob\" in resource\n ? { bytes: base64ByteLength(resource.blob) }\n : { characters: resource.text.length }),\n path,\n },\n };\n }\n }\n}\n\nfunction describeContentWithMetadata(\n content: ContentBlock,\n metadata: Readonly<Record<string, unknown>> | undefined,\n path: string,\n state: PresentationState,\n): unknown {\n const description = describeContent(content, path);\n if (!metadata || Object.keys(metadata).length === 0) {\n return description;\n }\n const presentedMetadata = presentValue(metadata, path, state) as Record<string, unknown>;\n if (isRecord(description)) {\n return { ...presentedMetadata, ...description };\n }\n return {\n ...presentedMetadata,\n $content: {\n type: content.type,\n characters: typeof description === \"string\" ? description.length : undefined,\n path,\n },\n };\n}\n\nfunction stripPresentationTags(value: unknown): unknown {\n const tag = getPresentationTag(value);\n if (tag?.kind === \"raw\") {\n return stripPresentationTags(tag.value);\n }\n if (tag?.kind === \"result\") {\n if (Object.hasOwn(tag, \"value\")) {\n return stripPresentationTags(tag.value);\n }\n if (Object.hasOwn(tag, \"structuredContent\")) {\n return stripPresentationTags(tag.structuredContent);\n }\n return null;\n }\n if (tag?.kind === \"content\") {\n return stripPresentationTags(tag.content);\n }\n if (Array.isArray(value)) {\n return value.map(stripPresentationTags);\n }\n if (isRecord(value)) {\n const result: Record<string, unknown> = {};\n for (const [key, item] of Object.entries(value)) {\n result[key] = stripPresentationTags(item);\n }\n return result;\n }\n return value;\n}\n\nfunction findExplicitResultOptions(value: unknown): Pick<CallToolResult, \"isError\" | \"_meta\"> {\n const tag = getPresentationTag(value);\n if (tag?.kind === \"raw\") {\n return {};\n }\n if (tag?.kind === \"result\") {\n return {\n ...(typeof tag.isError === \"boolean\" ? { isError: tag.isError } : {}),\n ...(isRecord(tag._meta) ? { _meta: tag._meta } : {}),\n };\n }\n if (Array.isArray(value)) {\n for (const item of value) {\n const options = findExplicitResultOptions(item);\n if (options.isError !== undefined || options._meta !== undefined) {\n return options;\n }\n }\n } else if (isRecord(value)) {\n for (const item of Object.values(value)) {\n const options = findExplicitResultOptions(item);\n if (options.isError !== undefined || options._meta !== undefined) {\n return options;\n }\n }\n }\n return {};\n}\n\nfunction getPresentationTag(value: unknown): PresentationTag | undefined {\n if (!isRecord(value) || Object.keys(value).length !== 1) {\n return undefined;\n }\n const candidate = value[MCP_PRESENTATION_TAG];\n if (\n !isRecord(candidate)\n || (candidate.kind !== \"raw\" && candidate.kind !== \"result\" && candidate.kind !== \"content\")\n ) {\n return undefined;\n }\n return candidate as unknown as PresentationTag;\n}\n\nfunction parseDataUrl(value: string): { readonly data: string; readonly mimeType: string } | undefined {\n if (!value.startsWith(\"data:\")) {\n return undefined;\n }\n const comma = value.indexOf(\",\");\n if (comma < 5) {\n return undefined;\n }\n const metadata = value.slice(5, comma);\n const parts = metadata.split(\";\");\n const mimeType = parts[0] || \"text/plain\";\n const payload = value.slice(comma + 1);\n if (parts.includes(\"base64\")) {\n const data = normalizeBase64(payload);\n return data ? { data, mimeType } : undefined;\n }\n try {\n return {\n data: Buffer.from(decodeURIComponent(payload), \"utf8\").toString(\"base64\"),\n mimeType,\n };\n } catch {\n return undefined;\n }\n}\n\nfunction normalizeBase64(value: string): string | undefined {\n const compact = value.replace(/\\s/g, \"\");\n if (compact.length < 8 || compact.length % 4 === 1 || !/^[A-Za-z0-9+/]*={0,2}$/.test(compact)) {\n return undefined;\n }\n const withoutPadding = compact.replace(/=+$/, \"\");\n const padding = (4 - (withoutPadding.length % 4)) % 4;\n return withoutPadding + \"=\".repeat(padding);\n}\n\nfunction sniffMimeType(base64: string): string | undefined {\n const bytes = Buffer.from(base64.slice(0, 256), \"base64\");\n const ascii = bytes.toString(\"ascii\");\n if (startsWith(bytes, [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a])) return \"image/png\";\n if (startsWith(bytes, [0xff, 0xd8, 0xff])) return \"image/jpeg\";\n if (ascii.startsWith(\"GIF87a\") || ascii.startsWith(\"GIF89a\")) return \"image/gif\";\n if (ascii.startsWith(\"RIFF\") && ascii.slice(8, 12) === \"WEBP\") return \"image/webp\";\n if (ascii.startsWith(\"BM\")) return \"image/bmp\";\n if (startsWith(bytes, [0x00, 0x00, 0x01, 0x00])) return \"image/x-icon\";\n if (startsWith(bytes, [0x49, 0x49, 0x2a, 0x00]) || startsWith(bytes, [0x4d, 0x4d, 0x00, 0x2a])) return \"image/tiff\";\n if (/^\\s*(?:<\\?xml[^>]*>\\s*)?<svg[\\s>]/i.test(bytes.toString(\"utf8\"))) return \"image/svg+xml\";\n if (ascii.startsWith(\"RIFF\") && ascii.slice(8, 12) === \"WAVE\") return \"audio/wav\";\n if (ascii.startsWith(\"ID3\") || startsWith(bytes, [0xff, 0xfb]) || startsWith(bytes, [0xff, 0xf3]) || startsWith(bytes, [0xff, 0xf2])) return \"audio/mpeg\";\n if (ascii.startsWith(\"OggS\")) return \"audio/ogg\";\n if (ascii.startsWith(\"fLaC\")) return \"audio/flac\";\n if (startsWith(bytes, [0xff, 0xf1]) || startsWith(bytes, [0xff, 0xf9])) return \"audio/aac\";\n if (ascii.startsWith(\"MThd\")) return \"audio/midi\";\n if (ascii.startsWith(\"%PDF-\")) return \"application/pdf\";\n if (startsWith(bytes, [0x50, 0x4b, 0x03, 0x04])) return \"application/zip\";\n if (startsWith(bytes, [0x1f, 0x8b])) return \"application/gzip\";\n return undefined;\n}\n\nfunction startsWith(value: Buffer, prefix: readonly number[]): boolean {\n return prefix.every((byte, index) => value[index] === byte);\n}\n\nfunction base64ByteLength(value: string): number {\n const normalized = normalizeBase64(value);\n if (!normalized) {\n return 0;\n }\n const padding = normalized.endsWith(\"==\") ? 2 : normalized.endsWith(\"=\") ? 1 : 0;\n return (normalized.length / 4) * 3 - padding;\n}\n\nfunction contentUrn(mimeType: string, value: string): string {\n const digest = createHash(\"sha256\").update(mimeType).update(\"\\0\").update(value).digest(\"base64url\");\n return `urn:linkrpc-mcp:content:${digest}`;\n}\n\nfunction contentMetadata(value: Readonly<Record<string, unknown>>): Record<string, unknown> {\n const metadata: Record<string, unknown> = {};\n for (const [key, item] of Object.entries(value)) {\n if (![\"data\", \"base64\", \"blob\", \"text\", \"mimeType\", \"uri\"].includes(key)) {\n metadata[key] = item;\n }\n }\n return metadata;\n}\n\nfunction contentBlockMetadata(\n value: Readonly<Record<string, unknown>>,\n content: ContentBlock,\n): Record<string, unknown> {\n const standardKeys = content.type === \"text\"\n ? [\"type\", \"text\", \"annotations\", \"_meta\"]\n : content.type === \"image\" || content.type === \"audio\"\n ? [\"type\", \"data\", \"mimeType\", \"annotations\", \"_meta\"]\n : content.type === \"resource\"\n ? [\"type\", \"resource\", \"annotations\", \"_meta\"]\n : [\n \"type\",\n \"uri\",\n \"name\",\n \"title\",\n \"description\",\n \"mimeType\",\n \"size\",\n \"annotations\",\n \"_meta\",\n \"icons\",\n ];\n const metadata: Record<string, unknown> = {};\n for (const [key, item] of Object.entries(value)) {\n if (!standardKeys.includes(key)) {\n metadata[key] = item;\n }\n }\n return metadata;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n","/// <reference path=\"./md.d.ts\" />\nimport { McpServer as SdkMcpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport type { Transport } from \"@modelcontextprotocol/sdk/shared/transport.js\";\nimport { ErrorCode, RpcError } from \"@hediet/linkrpc\";\nimport type { ResolvedEndpoint } from \"@hediet/linkrpc/node\";\nimport { z } from \"zod\";\nimport { ConnectionPool, type DefaultTransport, type HubAccess, type IConnectionPool, type PooledConnection } from \"./connectionPool\";\nimport { type HubSenderProvider, ProviderPool } from \"./senderProvider\";\nimport { summarizeGrants } from \"./grants\";\nimport { startSandbox, type SandboxHostApi } from \"./sandbox\";\nimport { TaskRegistry } from \"./taskRegistry\";\nimport { explore } from \"./explore\";\nimport {\n presentToolResult,\n scriptResultValue,\n type ResultPresentationMode,\n} from \"./resultPresentation\";\n\nexport interface McpToolCall {\n readonly name: string;\n readonly arguments: unknown;\n readonly result: unknown;\n}\n\nexport type McpExploreCall =\n | { readonly arguments: unknown; readonly result: unknown }\n | { readonly arguments: unknown; readonly error: string };\n\nexport interface LinkRpcMcpServerOptions {\n /**\n * Endpoint used when the tool call does not supply a `connection`. When\n * omitted, the server falls back to the `LINKRPC_ENDPOINT` / `LINKRPC_TOKEN`\n * environment variables (the stdio CLI mode).\n */\n readonly defaultEndpoint?: ResolvedEndpoint;\n /**\n * Connection pool to use. Defaults to a real {@link ConnectionPool}.\n * Injectable so tests can supply a fake pool without a live hub.\n */\n readonly pool?: IConnectionPool;\n /**\n * Resolves a signing sender per MCP session / `connection` argument instead\n * of dialing an endpoint. When set (and no explicit `pool` is given), the\n * server uses a {@link ProviderPool} — the consumer-provisioned identity\n * mode. Mutually exclusive with `defaultEndpoint`.\n */\n readonly provider?: HubSenderProvider;\n /**\n * Supplies the **default** connection (used when a tool call omits\n * `connection`) over an in-process transport — typically a leg into an\n * in-process hub participant — instead of dialing a socket. Explicit\n * `connection` endpoint URIs still dial normally. Combine with\n * {@link defaultEndpoint} to additionally set a dialed fallback; mutually\n * exclusive with `pool` / `provider`.\n */\n readonly defaultConnection?: () => DefaultTransport;\n /** Observes completed MCP tool calls exactly as their result is returned to the client. */\n readonly onToolCall?: (call: McpToolCall) => void;\n /** Observes every sandbox `con.explore` call, including calls that fail. */\n readonly onExploreCall?: (call: McpExploreCall) => void;\n}\n\nconst CONNECTION_SCHEMA = z.string().optional().describe(\n \"Endpoint URI of the hub to connect to, e.g. `unix:/run/hub.sock?token=…`, \" +\n \"`npipe://./pipe/vscode-linkrpc-…?token=…`, or `wss://host:port?token=…`. \" +\n \"The token may be embedded as a `token` query param or supplied via the \" +\n \"LINKRPC_TOKEN environment variable. When omitted entirely, the server falls \" +\n \"back to the LINKRPC_ENDPOINT and LINKRPC_TOKEN environment variables.\",\n);\n\nconst PRESENTATION_SCHEMA = z.enum([\"auto\", \"raw\"]).optional().describe(\n \"How to present the returned value. `auto` (default) recognizes MCP content blocks, \" +\n \"data URLs, common base64 media signatures, and `{ data|base64|blob, mimeType }` \" +\n \"objects, emitting native image/audio/resource content while keeping the original \" +\n \"value available to subsequent scripts through `lastResultVal`. `raw` disables \" +\n \"transformation and exposes the original JSON/base64.\",\n);\n\nconst SERVER_NAME = \"linkrpc-mcp\";\nconst SERVER_VERSION = \"0.0.1\";\n\n/**\n * MCP server exposing the `runLinkRpcScript` tool plus task-management helpers.\n *\n * Documentation for the sandbox API (`con`) is reachable from inside the\n * sandbox via `con.getDocs()` rather than an MCP resource — that way the\n * model can pull it in by issuing a one-line `runLinkRpcScript` call.\n *\n * Can be hosted over stdio (CLI mode, via {@link startStdio}) or over any\n * MCP {@link Transport} (e.g. Streamable HTTP, used by the VS Code Team\n * Tools extension which embeds this server in-process).\n */\nexport class LinkRpcMcpServer {\n public static async startStdio(options?: LinkRpcMcpServerOptions): Promise<LinkRpcMcpServer> {\n const server = new LinkRpcMcpServer(options);\n await server.connect(new StdioServerTransport());\n return server;\n }\n\n private readonly _mcp: SdkMcpServer;\n private readonly _pool: IConnectionPool;\n private readonly _tasks = new TaskRegistry();\n private readonly _onToolCall: ((call: McpToolCall) => void) | undefined;\n private readonly _onExploreCall: ((call: McpExploreCall) => void) | undefined;\n\n public constructor(options: LinkRpcMcpServerOptions = {}) {\n this._mcp = new SdkMcpServer({ name: SERVER_NAME, version: SERVER_VERSION });\n this._onToolCall = options.onToolCall;\n this._onExploreCall = options.onExploreCall;\n this._pool = options.pool\n ?? (options.provider\n ? new ProviderPool(options.provider)\n : new ConnectionPool({\n defaultEndpoint: options.defaultEndpoint,\n ...(options.defaultConnection\n ? { defaultTransport: options.defaultConnection }\n : {}),\n }));\n this._registerTools();\n }\n\n public async connect(transport: Transport): Promise<void> {\n await this._mcp.connect(transport);\n }\n\n public dispose(): void {\n this._tasks.dispose();\n this._pool.dispose();\n }\n\n private _registerTools(): void {\n this._mcp.registerTool(\n \"runLinkRpcScript\",\n {\n title: \"Run JS against a linkrpc hub\",\n description:\n \"Evaluate a JS function inside a QuickJS sandbox with `con` (the live hub \" +\n \"connection), `lastResultVal` (previous call's original result), and \" +\n \"`mcp` (optional result-presentation helpers) in scope.\\n\\n\" +\n \"Before composing non-trivial calls, fetch the full sandbox API docs by \" +\n \"running:\\n\" +\n \" `async ({ con }) => con.getDocs()`\\n\" +\n \"That returns the TypeScript declarations for the full script context, \" +\n \"including `con`, `mcp`, sandbox limits, and available console.\\n\\n\" +\n \"`code` MUST be a function expression, e.g.\\n\" +\n \" `({ con }) => con.call(\\\"vscode\\\", \\\"vscode.window\\\", \\\"showInformationMessage\\\", { message: \\\"hi\\\" })`\\n\\n\" +\n \"Set `connection` to a hub endpoint URI (e.g. `unix:/path?token=…` or \" +\n \"`wss://host?token=…`) to target a specific hub, or leave it out to use \" +\n \"the LINKRPC_ENDPOINT / LINKRPC_TOKEN env vars.\\n\\n\" +\n \"ACCESS IS NOT AUTOMATIC: a gated `con.call(...)` is NOT silently \" +\n \"granted. Reflection (`con.explore`) works out of the box, but calling \" +\n \"a service member you have no capability for fails with a permission \" +\n \"error. Inspect what you already hold with `con.grants()`, then ask \" +\n \"the user for access — ideally for MANY members at once — with \" +\n \"`con.requestAccess({ permissions, duration })`. Pick `duration`: `once` for a \" +\n \"one-off, `session` for the rest of this connection, `persistent` to \" +\n \"remember across runs. Batch related permissions into a single request \" +\n \"so the user sees one prompt instead of many.\\n\\n\" +\n \"BACKGROUND TASKS: if the code is still awaiting I/O (an RPC reply, a \" +\n \"user dialog, a stream) when `foregroundMs` elapses, the call does NOT \" +\n \"fail — it is parked as a background task and the result is \" +\n \"`{ status: \\\"running\\\", taskId, debugName, inFlight }`. Use \" +\n \"`awaitLinkRpcTask` to wait for it or `cancelLinkRpcTask` to abandon \" +\n \"it. Set `label` to give the task a \" +\n \"clear debug name. Starting a new `runLinkRpcScript` \" +\n \"cancels any task still parked (reported as `supersededTask`).\\n\\n\" +\n \"RESULT PRESENTATION: returned image/audio/resource data is automatically \" +\n \"emitted as native MCP content when it is a data URL, recognizable base64, \" +\n \"an MCP content block, or an object shaped like \" +\n \"`{ data|base64|blob, mimeType }`. This happens only after the script \" +\n \"finishes: values passed between hub calls and saved in `lastResultVal` \" +\n \"remain original and unmodified. Use `presentation: \\\"raw\\\"` or \" +\n \"`mcp.raw(value)` when the model needs the literal base64. Use `mcp.image`, \" +\n \"`mcp.audio`, `mcp.resource`, `mcp.resourceLink`, or `mcp.result` for \" +\n \"explicit control. Native content always includes JSON text and structured \" +\n \"fallbacks.\\n\\n\" +\n \"The result contains `{ status, result | taskId, logs, endpoint }`. \" +\n \"Pass `trace: true` to also receive a per-call JSON-RPC wire log under \" +\n \"`trace` — useful when a call fails or returns unexpected data.\",\n inputSchema: {\n connection: CONNECTION_SCHEMA,\n code: z.string().describe(\n \"JS function expression. Receives `{ con, lastResultVal, mcp }`. \" +\n \"Sync or async. Return value is JSON-stringified.\",\n ),\n presentation: PRESENTATION_SCHEMA,\n label: z.string().optional().describe(\n \"Human-readable debug name for the task if it gets parked, e.g. \" +\n \"\\\"ask user to confirm deploy\\\". When omitted, the name is inferred \" +\n \"from the in-flight RPC(s) at park time.\",\n ),\n foregroundMs: z.number().int().positive().optional().describe(\n \"How long the call runs synchronously before being parked as a \" +\n \"background task. Defaults to 5000.\",\n ),\n maxLifetimeMs: z.number().int().positive().optional().describe(\n \"Absolute lifetime cap for a parked task before it is cancelled. \" +\n \"Defaults to 120000.\",\n ),\n trace: z.boolean().optional().describe(\n \"When true, include a `trace` array in the result with every \" +\n \"outbound JSON-RPC request / notification, its outcome, and \" +\n \"every permission round-trip. Off by default to keep results small.\",\n ),\n },\n annotations: {\n // LinkRPC performs its own capability checks and consent flow, so MCP\n // clients can skip a redundant outer approval prompt.\n readOnlyHint: true,\n },\n },\n async (args) => this._observeToolCall(\"runLinkRpcScript\", args, async () => {\n let pooled: PooledConnection;\n try {\n pooled = await this._pool.resolve(args.connection);\n } catch (e) {\n return _errorResult(_describeError(e));\n }\n\n // A new request supersedes any task still parked — cancel it\n // before running the new code.\n const superseded = await this._tasks.cancelLive();\n\n // Capture every trace line produced during this run (transport\n // I/O + permission requests). Returned in the tool result so the\n // calling AI can see exactly what hit the wire — stderr only\n // reaches the MCP host's log surface, not the model. Only collected\n // when the caller opts in via `trace: true`, otherwise the listener\n // is never registered and the result stays small.\n const traceEnabled = args.trace === true;\n const trace: string[] = [];\n const disposeTrace = traceEnabled\n ? pooled.addTraceListener((line) => trace.push(line))\n : () => { /* no-op */ };\n\n const host: SandboxHostApi = {\n call: async (method, paramsJson, optsJson, onStreamMessage, signal) => {\n // Most linkrpc schemas validate against `z.object({...})`, which\n // rejects `undefined`. Default omitted params to `{}` so\n // `con.call(s,i,m)` works the same as `con.call(s,i,m,{})`.\n const params = paramsJson === \"\" ? {} : JSON.parse(paramsJson);\n const opts: { readonly requestPermission?: boolean } =\n optsJson === \"\" ? {} : JSON.parse(optsJson);\n const requestPermission = opts.requestPermission === true;\n const send = async () => {\n if (signal.aborted) {\n const error = new Error(`AbortError: ${String(signal.reason ?? \"cancelled\")}`);\n error.name = \"AbortError\";\n throw error;\n }\n const call = pooled.channel.sendRequestWithStream(method, params, {\n onStreamMessage: (payload) =>\n onStreamMessage(JSON.stringify(payload)),\n });\n const cancel = () => {\n const reason = String(signal.reason ?? \"cancelled\");\n call.cancel(reason);\n call.dispose?.(reason);\n };\n signal.addEventListener(\"abort\", cancel, { once: true });\n try {\n return await call.result;\n } finally {\n signal.removeEventListener(\"abort\", cancel);\n }\n };\n // Calls are NOT auto-granted: the channel presents only the\n // caps already in the bag (reflection + explicitly requested\n // grants). A gated form-3 call with no covering cap fails with\n // `permissionRequired`. With `requestPermission`, negotiate a\n // cap for exactly this call and retry once; otherwise rethrow\n // with guidance toward `con.requestAccess(...)`.\n try {\n const result = await send();\n return JSON.stringify(result ?? null);\n } catch (e) {\n if (requestPermission && _isPermissionError(e)) {\n const granted = await _autoRequestAccess(pooled.session, method);\n if (granted) {\n const result = await send();\n return JSON.stringify(result ?? null);\n }\n }\n throw _enrichPermissionError(e, method);\n }\n },\n notify: async (method, paramsJson) => {\n const params = paramsJson === \"\" ? {} : JSON.parse(paramsJson);\n await pooled.channel.sendNotification(method, params);\n return \"\";\n },\n explore: async (argsJson) => {\n const exploreArgs = argsJson === \"\" ? {} : JSON.parse(argsJson);\n // By default `explore` only uses the persistent reflection\n // capabilities cached on the channel by `setupSigning`. With\n // `requestPermission: true`, the first gated directory triggers\n // a single broad reflection grant (`linkrpc.*` on every service)\n // through the same `hubAccess` door `con.call` uses; it's\n // memoized so the whole walk costs at most one consent.\n let reflectionGrant: Promise<boolean> | undefined;\n try {\n const result = await explore(pooled.channel, exploreArgs, {\n requestReflectionAccess: () =>\n (reflectionGrant ??= _requestReflectionAccess(pooled.session)),\n });\n this._observeExploreCall({ arguments: exploreArgs, result });\n return JSON.stringify(result);\n } catch (error) {\n this._observeExploreCall({\n arguments: exploreArgs,\n error: error instanceof Error ? error.message : String(error),\n });\n throw error;\n }\n },\n requestAccess: async (argsJson) => {\n const req = argsJson === \"\" ? {} : JSON.parse(argsJson);\n const result = await pooled.session.requestAccess({\n consumer: { name: \"linkrpc-mcp\", purpose: req.purpose },\n permissions: req.permissions ?? [],\n duration: req.duration,\n });\n return JSON.stringify(result);\n },\n grants: async () => JSON.stringify(summarizeGrants(pooled.session.listGrants())),\n };\n\n try {\n const outcome = await startSandbox(args.code, host, pooled.lastResultVal, {\n foregroundMs: args.foregroundMs,\n maxLifetimeMs: args.maxLifetimeMs,\n label: args.label,\n });\n\n if (outcome.status === \"completed\") {\n pooled.lastResultVal = scriptResultValue(outcome.result);\n return presentToolResult({\n status: \"completed\",\n result: outcome.result,\n logs: outcome.logs,\n ...(traceEnabled ? { trace } : {}),\n endpoint: pooled.endpoint,\n ...(superseded ? { supersededTask: superseded } : {}),\n }, args.presentation);\n }\n\n if (outcome.status === \"error\") {\n return _errorResult(\n `runLinkRpcScript failed: ${outcome.error}`,\n traceEnabled ? trace : undefined,\n );\n }\n\n // Parked: register the task and report it as running. The\n // debug name + in-flight labels come straight from the live\n // sandbox, so they accurately describe what it's waiting on.\n const taskId = this._tasks.register(\n pooled.endpoint,\n outcome.debugName,\n outcome.task,\n (result) => { pooled.lastResultVal = scriptResultValue(result); },\n );\n return presentToolResult({\n status: \"running\",\n taskId,\n debugName: outcome.debugName,\n inFlight: outcome.task.inFlight(),\n logsSoFar: outcome.task.logs,\n ...(traceEnabled ? { traceSoFar: trace } : {}),\n endpoint: pooled.endpoint,\n ...(superseded ? { supersededTask: superseded } : {}),\n }, \"raw\");\n } catch (e) {\n return _errorResult(\n `runLinkRpcScript failed: ${_describeError(e)}`,\n traceEnabled ? trace : undefined,\n );\n } finally {\n disposeTrace();\n }\n }),\n );\n\n this._mcp.registerTool(\n \"awaitLinkRpcTask\",\n {\n title: \"Wait for a parked linkrpc task\",\n description:\n \"Wait up to `timeoutMs` for a background task started by `runLinkRpcScript` \" +\n \"to settle. Returns `{ status: \\\"completed\\\" | \\\"error\\\" | \\\"cancelled\\\" \" +\n \"| \\\"running\\\", … }`. A `running` result means it is still going (with a \" +\n \"progress snapshot) — call again to keep waiting. Does NOT cancel the task.\",\n inputSchema: {\n taskId: z.string().describe(\"Task id returned by `runLinkRpcScript`.\"),\n timeoutMs: z.number().int().positive().optional().describe(\n \"How long to wait before returning a `running` snapshot. Defaults to 30000.\",\n ),\n presentation: PRESENTATION_SCHEMA,\n },\n annotations: { readOnlyHint: true },\n },\n async (args) => this._observeToolCall(\"awaitLinkRpcTask\", args, async () => {\n const res = await this._tasks.awaitTask(args.taskId, args.timeoutMs ?? 30_000);\n if (res.status === \"unknown\") {\n return _errorResult(`No task with id ${args.taskId}`);\n }\n return _presentTaskResult(res, args.presentation);\n }),\n );\n\n this._mcp.registerTool(\n \"cancelLinkRpcTask\",\n {\n title: \"Cancel a parked linkrpc task\",\n description:\n \"Soft-abort a background task started by `runLinkRpcScript` and return its \" +\n \"terminal outcome. The guest gets a short grace window to run cleanup.\",\n inputSchema: {\n taskId: z.string().describe(\"Task id returned by `runLinkRpcScript`.\"),\n presentation: PRESENTATION_SCHEMA,\n },\n // Cancelling only affects a task created through this MCP session.\n annotations: { readOnlyHint: true },\n },\n async (args) => this._observeToolCall(\"cancelLinkRpcTask\", args, async () => {\n const res = await this._tasks.cancel(args.taskId);\n if (res.status === \"unknown\") {\n return _errorResult(`No task with id ${args.taskId}`);\n }\n return _presentTaskResult(res, args.presentation);\n }),\n );\n\n }\n\n private async _observeToolCall<Args, Result>(\n name: string,\n args: Args,\n invoke: () => Promise<Result>,\n ): Promise<Result> {\n const result = await invoke();\n try {\n this._onToolCall?.({ name, arguments: args, result });\n } catch {\n // Observability must not change the tool result.\n }\n return result;\n }\n\n private _observeExploreCall(call: McpExploreCall): void {\n try {\n this._onExploreCall?.(call);\n } catch {\n // Observability must not change exploration behavior.\n }\n }\n}\n\nfunction _presentTaskResult(\n value: Readonly<Record<string, unknown>>,\n mode: ResultPresentationMode | undefined,\n) {\n try {\n return presentToolResult(value, mode);\n } catch (e) {\n return _errorResult(`Failed to present task result: ${_describeError(e)}`);\n }\n}\n\nfunction _errorResult(message: string, trace?: readonly string[]): {\n content: { type: \"text\"; text: string }[];\n isError: true;\n} {\n const body = trace && trace.length > 0\n ? `${message}\\n\\nTrace:\\n${trace.join(\"\\n\")}`\n : message;\n return {\n content: [{ type: \"text\", text: body }],\n isError: true,\n };\n}\n\n/**\n * Render an unknown thrown value as a debuggable string: the error's stack\n * (which already begins with `Name: message`) plus the full `cause` chain. The\n * MCP host only forwards the result text to the model — never a JS stack — so\n * without this every failure collapses to a single bare message line.\n */\nfunction _describeError(e: unknown): string {\n if (!(e instanceof Error)) return String(e);\n let out = typeof e.stack === \"string\" && e.stack.length > 0 ? e.stack : e.message;\n let cause: unknown = (e as { cause?: unknown }).cause;\n while (cause != null) {\n if (cause instanceof Error) {\n out += `\\n\\nCaused by: ${typeof cause.stack === \"string\" && cause.stack.length > 0 ? cause.stack : cause.message\n }`;\n cause = (cause as { cause?: unknown }).cause;\n } else {\n out += `\\n\\nCaused by: ${String(cause)}`;\n break;\n }\n }\n return out;\n}\n\n/**\n * Map a hub `permissionRequired` (-32401) error to an actionable message that\n * points the model at the explicit access flow. Other errors pass through\n * unchanged (re-wrapped as an `Error` when they are not already one).\n */\nfunction _enrichPermissionError(e: unknown, method: string): Error {\n if (_isPermissionError(e)) {\n const { serviceId, interfaceId, member } = _parseMethod(method);\n const original = e instanceof Error ? e.message : String(e);\n return new Error(\n `Permission required for ${method} — no capability is held for this call.\\n` +\n `Inspect current access with con.grants(), then ` +\n `request it with con.requestAccess({ permissions: [{ target: { ` +\n `serviceId: { exact: ${JSON.stringify(serviceId)} }, ` +\n `interfaceId: { exact: ${JSON.stringify(interfaceId)} }, ` +\n `members: [{ exact: ${JSON.stringify(member)} }] }, canInvoke: true }], ` +\n `duration: \"longLived\" }).\\nOriginal error: ${original}`,\n );\n }\n return e instanceof Error ? e : new Error(String(e));\n}\n\n/** True when `e` is a hub `permissionRequired` (-32401) error. */\nfunction _isPermissionError(e: unknown): boolean {\n return e instanceof RpcError\n ? e.code === ErrorCode.permissionRequired\n : (typeof e === \"object\" && e !== null && (e as { code?: unknown }).code === ErrorCode.permissionRequired);\n}\n\n/**\n * Split a JSON-RPC method name into its `(serviceId, interfaceId, member)`\n * parts. Form-3 (`serviceId::interfaceId::member`) keeps the serviceId; form-2\n * (`interfaceId::member`, a root/hub call) reports an empty serviceId.\n */\nfunction _parseMethod(method: string): { serviceId: string; interfaceId: string; member: string } {\n const parts = method.split(\"::\");\n if (parts.length >= 3) {\n return { serviceId: parts[0], interfaceId: parts[1], member: parts.slice(2).join(\"::\") };\n }\n return { serviceId: \"\", interfaceId: parts[0] ?? \"\", member: parts[1] ?? \"\" };\n}\n\n/**\n * Negotiate durable capabilities for the reflection methods the bus walk uses\n * — `hubrpc.directory::list` (enumeration) and `hubrpc.schemas::get` (schema\n * fetch) — across *all* service ids, through the hub's `hubAccess` consent\n * door. One grant unlocks enumeration of every gated directory the walk\n * reaches, so `explore({ requestPermission: true })` only needs a single\n * consent round-trip. Returns `true` when the grant was issued.\n */\nasync function _requestReflectionAccess(session: HubAccess): Promise<boolean> {\n const result = await session.requestAccess({\n consumer: { name: \"linkrpc-mcp\", purpose: \"explore the hub (reflection)\" },\n permissions: [\n {\n target: {\n serviceId: { prefix: \"\" },\n interfaceId: { exact: \"hubrpc.directory\" },\n members: [{ exact: \"list\" }],\n },\n canInvoke: true,\n },\n {\n target: {\n serviceId: { prefix: \"\" },\n interfaceId: { exact: \"hubrpc.schemas\" },\n members: [{ exact: \"get\" }],\n },\n canInvoke: true,\n },\n ],\n duration: \"longLived\",\n });\n return result.status === \"granted\";\n}\n\n/**\n * Negotiate a durable capability for exactly `method` through the hub's\n * `hubAccess` consent door (the `requestPermission: true` path of `con.call`).\n * Returns `true` when the grant was issued — its durable cap joins the\n * connection's bag, so the caller can retry the call.\n */\nasync function _autoRequestAccess(session: HubAccess, method: string): Promise<boolean> {\n const { serviceId, interfaceId, member } = _parseMethod(method);\n const result = await session.requestAccess({\n consumer: { name: \"linkrpc-mcp\", purpose: `invoke ${method}` },\n permissions: [{\n target: {\n serviceId: { exact: serviceId },\n interfaceId: { exact: interfaceId },\n members: [{ exact: member }],\n },\n canInvoke: true,\n }],\n duration: \"longLived\",\n });\n return result.status === \"granted\";\n}\n"],"mappings":"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"}
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {}
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { t as LinkRpcMcpServer } from "./chunks/server-C4ZM6bfK.js";
|
|
3
|
+
//#region src/cli.ts
|
|
4
|
+
async function main() {
|
|
5
|
+
const server = await LinkRpcMcpServer.startStdio();
|
|
6
|
+
const shutdown = () => {
|
|
7
|
+
try {
|
|
8
|
+
server.dispose();
|
|
9
|
+
} finally {
|
|
10
|
+
process.exit(0);
|
|
11
|
+
}
|
|
12
|
+
};
|
|
13
|
+
process.on("SIGINT", shutdown);
|
|
14
|
+
process.on("SIGTERM", shutdown);
|
|
15
|
+
}
|
|
16
|
+
main().catch((err) => {
|
|
17
|
+
process.stderr.write(`linkrpc-mcp: fatal: ${err.stack ?? err}\n`);
|
|
18
|
+
process.exit(1);
|
|
19
|
+
});
|
|
20
|
+
//#endregion
|
|
21
|
+
export {};
|
|
22
|
+
|
|
23
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","names":[],"sources":["../src/cli.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { LinkRpcMcpServer } from \"./server\";\n\nasync function main(): Promise<void> {\n const server = await LinkRpcMcpServer.startStdio();\n const shutdown = () => {\n try { server.dispose(); } finally { process.exit(0); }\n };\n process.on(\"SIGINT\", shutdown);\n process.on(\"SIGTERM\", shutdown);\n}\n\nmain().catch((err: unknown) => {\n // stderr only — stdout is reserved for the MCP transport.\n process.stderr.write(`linkrpc-mcp: fatal: ${(err as Error).stack ?? err}\\n`);\n process.exit(1);\n});\n"],"mappings":";;;AAGA,eAAe,OAAsB;CACjC,MAAM,SAAS,MAAM,iBAAiB,WAAW;CACjD,MAAM,iBAAiB;EACnB,IAAI;GAAE,OAAO,QAAQ;EAAG,UAAU;GAAE,QAAQ,KAAK,CAAC;EAAG;CACzD;CACA,QAAQ,GAAG,UAAU,QAAQ;CAC7B,QAAQ,GAAG,WAAW,QAAQ;AAClC;AAEA,KAAK,CAAC,CAAC,OAAO,QAAiB;CAE3B,QAAQ,OAAO,MAAM,uBAAwB,IAAc,SAAS,IAAI,GAAG;CAC3E,QAAQ,KAAK,CAAC;AAClB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {}
|