norns-sdk 0.2.0 → 0.4.0
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/CHANGELOG.md +17 -0
- package/README.md +6 -2
- package/dist/index.cjs +26 -5
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +18 -3
- package/dist/index.d.ts +18 -3
- package/dist/index.js +24 -5
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/agent.ts","../src/client.ts","../src/async-queue.ts","../src/errors.ts","../src/types.ts","../src/logger.ts","../src/models.ts","../src/tool.ts","../src/worker.ts","../src/completed-calls.ts","../src/format.ts","../src/history-cache.ts"],"sourcesContent":["export { jsonSchema } from \"ai\";\nexport {\n type AgentDefinition,\n type AgentMode,\n type AgentOptions,\n type CheckpointPolicy,\n type ContextPolicy,\n type ContextStrategy,\n DEFAULT_MODEL,\n defineAgent,\n type OnFailure,\n type SubagentConversation,\n type SubagentPolicy,\n} from \"./agent.js\";\nexport {\n type AgentRef,\n type ListRunsOptions,\n NornsClient,\n type NornsClientOptions,\n type SendMessageOptions,\n type StreamOptions,\n type WebSocketConstructor,\n} from \"./client.js\";\nexport {\n GardDestroyedError,\n JoinError,\n NornsApiError,\n NornsError,\n NornsTimeoutError,\n NotFoundError,\n StreamClosedError,\n} from \"./errors.js\";\nexport type {\n LlmResult,\n LlmTask,\n NeutralMessage,\n NeutralToolCall,\n ToolResult,\n ToolTask,\n} from \"./format.js\";\nexport { consoleLogger, type Logger, silentLogger } from \"./logger.js\";\nexport {\n inferProvider,\n type ModelResolver,\n type ModelSource,\n type ModelsOption,\n} from \"./models.js\";\nexport {\n type InferToolInput,\n type ToolContext,\n type ToolDefinition,\n type ToolInputSchema,\n type ToolOptions,\n tool,\n} from \"./tool.js\";\nexport type {\n AgentInfo,\n Conversation,\n MessageResult,\n Run,\n RunEvent,\n RunStatus,\n StreamEvent,\n WaitingFor,\n} from \"./types.js\";\nexport {\n type Capability,\n NornsWorker,\n type NornsWorkerOptions,\n type RegisteredPort,\n type RegisterPortOptions,\n} from \"./worker.js\";\n","import type { ToolDefinition } from \"./tool.js\";\n\nexport type AgentMode = \"task\" | \"conversation\";\nexport type CheckpointPolicy = \"every_step\" | \"on_tool_call\" | \"manual\";\nexport type ContextStrategy = \"sliding_window\" | \"none\";\nexport type OnFailure = \"stop\" | \"retry_last_step\";\nexport type SubagentConversation = \"per_launch\" | \"per_parent\";\n\n/** Fold older history into a summary once a response reports `compactAt` input tokens. */\nexport interface ContextPolicy {\n compactAt: number;\n /** Messages kept verbatim after the fold. */\n keep: number;\n}\n\n/** What this agent may do with `launch_agent` and `list_agents`. */\nexport interface SubagentPolicy {\n mode?: \"open\" | \"allowlist\" | \"disabled\";\n allowedAgents?: string[];\n allowListAgents?: boolean;\n maxDepth?: number;\n}\n\nexport interface AgentOptions {\n name: string;\n /** Shown to other agents by `list_agents`. */\n purpose?: string;\n /**\n * The model name as the provider knows it, e.g. `\"claude-sonnet-5\"`,\n * `\"gpt-4o\"`. Prefix it (`\"openai/gpt-4o\"`) to pin the provider.\n */\n model?: string;\n systemPrompt?: string;\n /** What this worker serves for the agent (see `allowedTools` for what it is offered). */\n tools?: ToolDefinition[];\n mode?: AgentMode;\n checkpointPolicy?: CheckpointPolicy;\n contextStrategy?: ContextStrategy;\n contextWindow?: number;\n maxSteps?: number;\n onFailure?: OnFailure;\n /** Pair with `contextStrategy: \"none\"`; the summarisation is served by this worker. */\n contextPolicy?: ContextPolicy;\n /**\n * The ceiling on one response, not on the history. Unset leaves it to the\n * worker (8192). Raise it for an agent whose turns are long.\n */\n maxTokens?: number;\n /**\n * Names from `tools` this agent is offered. Unset offers every tool\n * registered in the tenant, other agents' included. Built-ins (`ask_human`,\n * `wait`, `launch_agent`, `list_agents`) are never filtered.\n */\n allowedTools?: string[];\n subagents?: SubagentPolicy;\n /** When launched by another agent: a fresh conversation per launch, or one per parent. */\n subagentConversation?: SubagentConversation;\n}\n\n/** A complete agent definition: `defineAgent()`'s result. */\nexport interface AgentDefinition {\n readonly name: string;\n readonly purpose: string | undefined;\n readonly model: string;\n readonly systemPrompt: string;\n readonly tools: readonly ToolDefinition[];\n readonly mode: AgentMode;\n readonly checkpointPolicy: CheckpointPolicy;\n readonly contextStrategy: ContextStrategy;\n readonly contextWindow: number;\n readonly maxSteps: number;\n readonly onFailure: OnFailure;\n readonly contextPolicy: ContextPolicy | undefined;\n readonly maxTokens: number | undefined;\n readonly allowedTools: readonly string[] | undefined;\n readonly subagents: SubagentPolicy | undefined;\n readonly subagentConversation: SubagentConversation | undefined;\n}\n\nexport const DEFAULT_MODEL = \"claude-sonnet-5\";\n\nconst SUBAGENT_CONVERSATIONS: readonly string[] = [\"per_launch\", \"per_parent\"];\n\n/**\n * Define an agent. Defaults are filled in and the combination is checked\n * here, so a mistake fails where it was written rather than on the server.\n */\nexport function defineAgent(options: AgentOptions): AgentDefinition {\n const name = options.name?.trim();\n if (!name) throw new Error(\"defineAgent(): name is required\");\n\n const tools = options.tools ?? [];\n const known = new Set(tools.map((t) => t.name));\n if (known.size !== tools.length) {\n throw new Error(`Agent '${name}': tool names must be unique`);\n }\n\n if (options.allowedTools) {\n const unknown = options.allowedTools.filter((n) => !known.has(n));\n if (unknown.length > 0) {\n throw new Error(\n `Agent '${name}': allowedTools names ${JSON.stringify(unknown)} are not in its tools ` +\n `(${JSON.stringify([...known].sort())}); built-ins are always available and need no entry`,\n );\n }\n }\n\n if (\n options.subagentConversation !== undefined &&\n !SUBAGENT_CONVERSATIONS.includes(options.subagentConversation)\n ) {\n throw new Error(\n `Agent '${name}': subagentConversation must be one of ${SUBAGENT_CONVERSATIONS.join(\", \")}`,\n );\n }\n\n if (\n options.maxTokens !== undefined &&\n !(Number.isInteger(options.maxTokens) && options.maxTokens > 0)\n ) {\n throw new Error(`Agent '${name}': maxTokens must be a positive integer`);\n }\n\n return Object.freeze({\n name,\n purpose: options.purpose,\n model: options.model ?? DEFAULT_MODEL,\n systemPrompt: options.systemPrompt ?? \"\",\n tools: Object.freeze([...tools]),\n mode: options.mode ?? \"task\",\n checkpointPolicy: options.checkpointPolicy ?? \"on_tool_call\",\n contextStrategy: options.contextStrategy ?? \"sliding_window\",\n contextWindow: options.contextWindow ?? 20,\n maxSteps: options.maxSteps ?? 50,\n onFailure: options.onFailure ?? \"retry_last_step\",\n contextPolicy: options.contextPolicy,\n maxTokens: options.maxTokens,\n allowedTools: options.allowedTools ? Object.freeze([...options.allowedTools]) : undefined,\n subagents: options.subagents,\n subagentConversation: options.subagentConversation,\n });\n}\n\n/**\n * The REST body that creates or updates the agent. Policies go only when\n * set: the update replaces `model_config` whole, so dropping one from the\n * definition drops it on the server too.\n */\nexport function agentBody(agent: AgentDefinition): Record<string, unknown> {\n const modelConfig: Record<string, unknown> = {\n mode: agent.mode,\n checkpoint_policy: agent.checkpointPolicy,\n context_strategy: agent.contextStrategy,\n context_window: agent.contextWindow,\n on_failure: agent.onFailure,\n context_policy: agent.contextPolicy\n ? { compact_at: agent.contextPolicy.compactAt, keep: agent.contextPolicy.keep }\n : null,\n max_tokens: agent.maxTokens ?? null,\n };\n if (agent.allowedTools) {\n modelConfig.tools = { mode: \"allowlist\", allowed_tools: [...agent.allowedTools] };\n }\n if (agent.subagents) {\n const s = agent.subagents;\n const policy: Record<string, unknown> = {};\n if (s.mode !== undefined) policy.mode = s.mode;\n if (s.allowedAgents !== undefined) policy.allowed_agents = [...s.allowedAgents];\n if (s.allowListAgents !== undefined) policy.allow_list_agents = s.allowListAgents;\n if (s.maxDepth !== undefined) policy.max_depth = s.maxDepth;\n modelConfig.subagents = policy;\n }\n if (agent.subagentConversation) {\n modelConfig.subagent_conversation = agent.subagentConversation;\n }\n\n const body: Record<string, unknown> = {\n name: agent.name,\n system_prompt: agent.systemPrompt,\n status: \"idle\",\n model: agent.model,\n max_steps: agent.maxSteps,\n model_config: modelConfig,\n };\n if (agent.purpose !== undefined) body.purpose = agent.purpose;\n return body;\n}\n\n/**\n * One agent or several, as a list. Names must be unique: the second would\n * overwrite the first on the server.\n */\nexport function agentList(agents: AgentDefinition | AgentDefinition[]): AgentDefinition[] {\n const items = Array.isArray(agents) ? [...agents] : [agents];\n if (items.length === 0) throw new Error(\"A worker needs at least one agent\");\n const seen = new Set<string>();\n const dupes = new Set<string>();\n for (const a of items) {\n if (seen.has(a.name)) dupes.add(a.name);\n seen.add(a.name);\n }\n if (dupes.size > 0) {\n throw new Error(\n `Agent names must be unique on one worker: ${JSON.stringify([...dupes].sort())}`,\n );\n }\n return items;\n}\n\n/**\n * Every agent's tools, one per name. A tool task names only the tool, so\n * two different tools under one name cannot both be served.\n */\nexport function toolsByName(agents: AgentDefinition[]): Map<string, ToolDefinition> {\n const tools = new Map<string, ToolDefinition>();\n const owners = new Map<string, string>();\n for (const agent of agents) {\n for (const t of agent.tools) {\n const existing = tools.get(t.name);\n if (existing === undefined) {\n tools.set(t.name, t);\n owners.set(t.name, agent.name);\n } else if (existing !== t) {\n throw new Error(\n `Agents '${owners.get(t.name)}' and '${agent.name}' have different tools named ` +\n `'${t.name}'; tools are dispatched by name, so share one definition or rename one`,\n );\n }\n }\n }\n return tools;\n}\n","import { Socket, type SocketConnectOption } from \"phoenix\";\nimport { type AgentDefinition, agentBody } from \"./agent.js\";\nimport { AsyncQueue } from \"./async-queue.js\";\nimport {\n NornsApiError,\n NornsError,\n NornsTimeoutError,\n NotFoundError,\n StreamClosedError,\n} from \"./errors.js\";\nimport {\n type AgentInfo,\n type Conversation,\n type MessageResult,\n type Run,\n type RunEvent,\n type RunStatus,\n type StreamEvent,\n TERMINAL_EVENTS,\n type WaitingFor,\n} from \"./types.js\";\n\n/** A class that behaves like the browser `WebSocket`; the global one by default. */\nexport type WebSocketConstructor = new (url: string, protocols?: string | string[]) => object;\n\nexport interface NornsClientOptions {\n /** The Norns base URL. Defaults to `NORNS_URL`. */\n url?: string;\n /** The tenant's bearer token. Defaults to `NORNS_API_KEY`. */\n apiKey?: string;\n /** Replace the global `fetch`, for tests or custom transport. */\n fetch?: typeof globalThis.fetch;\n /** Replace the global `WebSocket` for streams. */\n transport?: WebSocketConstructor;\n /** Extra options for the Phoenix socket that streams use. */\n socketOptions?: Partial<SocketConnectOption>;\n}\n\n/** An agent's id, or its name. */\nexport type AgentRef = number | string;\n\nexport interface SendMessageOptions {\n /** Key for multi-turn conversations, e.g. a Slack user id. */\n conversationKey?: string;\n /** Opaque context stored on the run. */\n context?: Record<string, unknown>;\n /** Pin the run to a gard. */\n gardId?: number;\n /**\n * Poll until the run completes, fails, or parks on a question. A parked\n * agent is waiting on you, so the wait ends there too.\n */\n wait?: boolean;\n /** How long to wait, with `wait`. Default 30 seconds. */\n timeoutMs?: number;\n signal?: AbortSignal;\n}\n\nexport interface StreamOptions {\n conversationKey?: string;\n context?: Record<string, unknown>;\n gardId?: number;\n /** Give up if no event arrives for this long. Default 2 minutes. */\n idleTimeoutMs?: number;\n signal?: AbortSignal;\n}\n\nexport interface ListRunsOptions {\n /** How many the server returns, most recent first. Default 50. */\n limit?: number;\n status?: RunStatus;\n agentId?: number;\n}\n\nconst WAIT_STOPS: ReadonlySet<string> = new Set([\"completed\", \"failed\", \"error\", \"waiting\"]);\n\n/**\n * Talks to Norns from application code: sends messages, reads runs, streams\n * events. For serving an agent, see `NornsWorker`.\n *\n * const client = new NornsClient({ url, apiKey });\n * const result = await client.sendMessage(\"support-bot\", \"Where's my order?\", { wait: true });\n */\nexport class NornsClient {\n readonly url: string;\n readonly #apiKey: string;\n readonly #fetch: typeof globalThis.fetch;\n readonly #transport: WebSocketConstructor | undefined;\n readonly #socketOptions: Partial<SocketConnectOption>;\n\n constructor(options: NornsClientOptions = {}) {\n this.url = resolveUrl(options.url);\n this.#apiKey = resolveApiKey(options.apiKey);\n this.#fetch = options.fetch ?? globalThis.fetch;\n this.#transport = options.transport;\n this.#socketOptions = options.socketOptions ?? {};\n }\n\n // --- Agents ---\n\n readonly agents = {\n list: async (): Promise<AgentInfo[]> => {\n const res = await this.#request<{ data: Record<string, unknown>[] }>(\"GET\", \"/api/v1/agents\");\n return res.data.map(parseAgent);\n },\n\n /** By id, or by name. */\n get: async (agent: AgentRef): Promise<AgentInfo> => {\n if (typeof agent === \"number\") {\n const res = await this.#request<{ data: Record<string, unknown> }>(\n \"GET\",\n `/api/v1/agents/${agent}`,\n );\n return parseAgent(res.data);\n }\n const found = (await this.agents.list()).find((a) => a.name === agent);\n if (!found) throw new NotFoundError(`Agent '${agent}'`);\n return found;\n },\n\n /**\n * Create the agent, or update it to match the definition if it exists,\n * so code changes are always picked up. The worker does this on start.\n */\n ensure: async (definition: AgentDefinition): Promise<AgentInfo> => {\n const body = agentBody(definition);\n const existing = (await this.agents.list()).find((a) => a.name === definition.name);\n if (existing) {\n const res = await this.#request<{ data: Record<string, unknown> }>(\n \"PUT\",\n `/api/v1/agents/${existing.id}`,\n { body },\n );\n return parseAgent(res.data);\n }\n const res = await this.#request<{ data: Record<string, unknown> }>(\"POST\", \"/api/v1/agents\", {\n body,\n });\n return parseAgent(res.data);\n },\n };\n\n // --- Messages ---\n\n /**\n * Send a message to an agent. Returns at once with the run id, or, with\n * `wait`, once the run completes, fails, or parks on a question.\n */\n async sendMessage(\n agent: AgentRef,\n content: string,\n options: SendMessageOptions = {},\n ): Promise<MessageResult> {\n const agentId = await this.#resolveAgentId(agent);\n const runId = await this.#post(agentId, content, options);\n\n if (!options.wait) {\n return {\n runId,\n status: \"accepted\",\n output: null,\n conversationKey: options.conversationKey,\n isWaiting: false,\n waitingFor: null,\n };\n }\n\n const run = await this.#waitForRun(runId, options.timeoutMs ?? 30_000, options.signal);\n return {\n runId,\n status: run.status,\n output: run.output,\n conversationKey: options.conversationKey,\n isWaiting: run.status === \"waiting\",\n waitingFor: run.waitingFor,\n };\n }\n\n /**\n * Send a message and iterate the run's events as they happen, until it\n * completes or errors.\n *\n * for await (const event of client.stream(\"researcher\", \"Summarise this\")) {\n * if (event.type === \"completed\") console.log(event.data.output);\n * }\n */\n async *stream(\n agent: AgentRef,\n content: string,\n options: StreamOptions = {},\n ): AsyncGenerator<StreamEvent, void, undefined> {\n const agentId = await this.#resolveAgentId(agent);\n const runId = await this.#post(agentId, content, options);\n yield* this.#watch(agentId, runId, options);\n }\n\n // --- Runs ---\n\n readonly runs = {\n get: async (runId: number): Promise<Run> => {\n const res = await this.#request<{ data: Record<string, unknown> }>(\n \"GET\",\n `/api/v1/runs/${runId}`,\n );\n return parseRun(res.data);\n },\n\n /**\n * The tenant's runs, most recent first. Use it to find runs nobody holds\n * a handle to, above all the ones parked on an `ask_human` question:\n *\n * for (const run of await client.runs.list({ status: \"waiting\" })) {\n * console.log(run.id, run.waitingFor?.question);\n * }\n *\n * `status` and `agentId` filter the page the server returned, so a\n * narrow filter over a busy tenant may need a larger `limit`.\n */\n list: async (options: ListRunsOptions = {}): Promise<Run[]> => {\n const res = await this.#request<{ data: Record<string, unknown>[] }>(\"GET\", \"/api/v1/runs\", {\n query: { limit: options.limit ?? 50 },\n });\n let runs = res.data.map(parseRun);\n if (options.status) runs = runs.filter((r) => r.status === options.status);\n if (options.agentId !== undefined) runs = runs.filter((r) => r.agentId === options.agentId);\n return runs;\n },\n\n events: async (runId: number): Promise<RunEvent[]> => {\n const res = await this.#request<{ data: Record<string, unknown>[] }>(\n \"GET\",\n `/api/v1/runs/${runId}/events`,\n );\n return res.data.map(parseEvent);\n },\n\n /**\n * Answer a run parked on an `ask_human` question. Sending the agent a\n * normal message does the same and is usually what a chat client wants;\n * this targets one specific run.\n */\n reply: async (runId: number, answer: string): Promise<void> => {\n await this.#request(\"POST\", `/api/v1/runs/${runId}/reply`, { body: { answer } });\n },\n\n /** Re-run a finished or failed run's message. Returns the new run id. */\n retry: async (runId: number): Promise<number> => {\n const res = await this.#request<{ run_id: number }>(\"POST\", `/api/v1/runs/${runId}/retry`);\n return res.run_id;\n },\n\n /** Iterate an existing run's events as they happen, until it finishes. */\n watch: (\n runId: number,\n options: Pick<StreamOptions, \"idleTimeoutMs\" | \"signal\"> = {},\n ): AsyncGenerator<StreamEvent, void, undefined> => {\n const self = this;\n return (async function* () {\n const run = await self.runs.get(runId);\n yield* self.#watch(run.agentId, runId, options);\n })();\n },\n };\n\n // --- Conversations ---\n\n readonly conversations = {\n list: async (agent: AgentRef): Promise<Conversation[]> => {\n const agentId = await this.#resolveAgentId(agent);\n const res = await this.#request<{ data: Record<string, unknown>[] }>(\n \"GET\",\n `/api/v1/agents/${agentId}/conversations`,\n );\n return res.data.map(parseConversation);\n },\n\n get: async (agent: AgentRef, key: string): Promise<Conversation> => {\n const agentId = await this.#resolveAgentId(agent);\n const res = await this.#request<{ data: Record<string, unknown> }>(\n \"GET\",\n `/api/v1/agents/${agentId}/conversations/${encodeURIComponent(key)}`,\n );\n return parseConversation(res.data);\n },\n\n /** Reset a conversation: its history is gone, the next message starts fresh. */\n delete: async (agent: AgentRef, key: string): Promise<void> => {\n const agentId = await this.#resolveAgentId(agent);\n await this.#request(\n \"DELETE\",\n `/api/v1/agents/${agentId}/conversations/${encodeURIComponent(key)}`,\n );\n },\n };\n\n // --- Internals ---\n\n async #resolveAgentId(agent: AgentRef): Promise<number> {\n return typeof agent === \"number\" ? agent : (await this.agents.get(agent)).id;\n }\n\n async #post(\n agentId: number,\n content: string,\n options: {\n conversationKey?: string;\n context?: Record<string, unknown>;\n gardId?: number;\n signal?: AbortSignal;\n },\n ): Promise<number> {\n const body: Record<string, unknown> = { content };\n if (options.conversationKey !== undefined) body.conversation_key = options.conversationKey;\n if (options.context !== undefined) body.context = options.context;\n if (options.gardId !== undefined) body.gard_id = options.gardId;\n const res = await this.#request<{ run_id: number }>(\n \"POST\",\n `/api/v1/agents/${agentId}/messages`,\n {\n body,\n signal: options.signal,\n },\n );\n return res.run_id;\n }\n\n // Poll until the run stops progressing. \"waiting\" is not terminal, but\n // the agent is parked on a question and will not move until someone\n // answers, so it ends the wait too.\n async #waitForRun(runId: number, timeoutMs: number, signal?: AbortSignal): Promise<Run> {\n const deadline = Date.now() + timeoutMs;\n let interval = 500;\n while (Date.now() < deadline) {\n const run = await this.runs.get(runId);\n if (WAIT_STOPS.has(run.status)) return run;\n await sleep(Math.min(interval, Math.max(deadline - Date.now(), 0)), signal);\n interval = Math.min(interval * 1.5, 3000);\n }\n throw new NornsTimeoutError(`Run ${runId} did not complete within ${timeoutMs}ms`);\n }\n\n async *#watch(\n agentId: number,\n runId: number,\n options: Pick<StreamOptions, \"idleTimeoutMs\" | \"signal\">,\n ): AsyncGenerator<StreamEvent, void, undefined> {\n const idle = options.idleTimeoutMs ?? 120_000;\n const queue = new AsyncQueue<StreamEvent>();\n const socket = new Socket(`${wsBase(this.url)}/socket`, {\n params: { token: this.#apiKey },\n ...(this.#transport\n ? { transport: this.#transport as SocketConnectOption[\"transport\"] }\n : {}),\n ...this.#socketOptions,\n });\n\n let timer: ReturnType<typeof setTimeout> | undefined;\n const touch = () => {\n if (timer) clearTimeout(timer);\n timer = setTimeout(\n () => queue.fail(new NornsTimeoutError(`No event for ${idle}ms on run ${runId}`)),\n idle,\n );\n };\n const onAbort = () => queue.fail(options.signal?.reason ?? abortError());\n\n socket.onError((err) => queue.fail(new StreamClosedError(err)));\n socket.onClose((ev) => queue.fail(new StreamClosedError(ev)));\n\n const channel = socket.channel(`agent:${agentId}`, { run_id: runId });\n channel.onMessage = (event: string, payload: Record<string, unknown>) => {\n if (!event.startsWith(\"phx_\") && !event.startsWith(\"chan_reply_\") && event !== \"heartbeat\") {\n // The channel is per agent, so another run's events arrive here too.\n if (payload?.run_id === undefined || payload.run_id === runId) {\n queue.push({ type: event, data: payload } as StreamEvent);\n touch();\n }\n }\n return payload;\n };\n channel\n .join()\n .receive(\"error\", (resp) =>\n queue.fail(new NornsError(`Could not join agent:${agentId}: ${JSON.stringify(resp)}`)),\n )\n .receive(\"timeout\", () =>\n queue.fail(new NornsTimeoutError(`Joining agent:${agentId} timed out`)),\n );\n\n if (options.signal?.aborted) onAbort();\n options.signal?.addEventListener(\"abort\", onAbort, { once: true });\n socket.connect();\n touch();\n\n try {\n for await (const event of queue) {\n yield event;\n if (TERMINAL_EVENTS.has(event.type)) return;\n }\n } finally {\n if (timer) clearTimeout(timer);\n options.signal?.removeEventListener(\"abort\", onAbort);\n queue.close();\n socket.disconnect();\n }\n }\n\n async #request<T = unknown>(\n method: string,\n path: string,\n options: { body?: unknown; query?: Record<string, string | number>; signal?: AbortSignal } = {},\n ): Promise<T> {\n const url = new URL(this.url + path);\n for (const [k, v] of Object.entries(options.query ?? {})) url.searchParams.set(k, String(v));\n\n const headers: Record<string, string> = {\n authorization: `Bearer ${this.#apiKey}`,\n accept: \"application/json\",\n };\n if (options.body !== undefined) headers[\"content-type\"] = \"application/json\";\n\n const res = await this.#fetch(url, {\n method,\n headers,\n body: options.body === undefined ? undefined : JSON.stringify(options.body),\n signal: options.signal,\n });\n\n const text = await res.text();\n const json = text === \"\" ? undefined : safeParse(text);\n if (!res.ok) {\n if (res.status === 404) throw new NotFoundError(`${method} ${path}`, json ?? text);\n throw new NornsApiError(res.status, json ?? text);\n }\n return json as T;\n }\n}\n\n// --- Helpers ---\n\nexport function resolveUrl(url: string | undefined): string {\n const value = url ?? process.env.NORNS_URL;\n if (!value) throw new NornsError(\"Norns URL missing: pass `url` or set NORNS_URL\");\n return value.replace(/\\/+$/, \"\");\n}\n\nexport function resolveApiKey(apiKey: string | undefined): string {\n const value = apiKey ?? process.env.NORNS_API_KEY;\n if (!value) throw new NornsError(\"Norns API key missing: pass `apiKey` or set NORNS_API_KEY\");\n return value;\n}\n\nexport function wsBase(url: string): string {\n return url.replace(/^http:\\/\\//, \"ws://\").replace(/^https:\\/\\//, \"wss://\");\n}\n\nfunction safeParse(text: string): unknown {\n try {\n return JSON.parse(text);\n } catch {\n return text;\n }\n}\n\nfunction abortError(): Error {\n return new DOMException(\"The operation was aborted\", \"AbortError\");\n}\n\nexport function sleep(ms: number, signal?: AbortSignal): Promise<void> {\n return new Promise((resolve, reject) => {\n if (signal?.aborted) return reject(signal.reason ?? abortError());\n const timer = setTimeout(() => {\n signal?.removeEventListener(\"abort\", onAbort);\n resolve();\n }, ms);\n function onAbort() {\n clearTimeout(timer);\n reject(signal?.reason ?? abortError());\n }\n signal?.addEventListener(\"abort\", onAbort, { once: true });\n });\n}\n\n// --- Parsers: wire snake_case → camelCase ---\n\ntype Raw = Record<string, unknown>;\n\nfunction parseWaitingFor(data: unknown): WaitingFor | null {\n if (!data || typeof data !== \"object\") return null;\n const w = data as Raw;\n return {\n question: String(w.question ?? \"\"),\n toolCallId: String(w.tool_call_id ?? \"\"),\n askedAt: typeof w.asked_at === \"string\" ? w.asked_at : undefined,\n };\n}\n\nexport function parseRun(r: Raw): Run {\n return {\n id: r.id as number,\n agentId: r.agent_id as number,\n conversationId: (r.conversation_id as number | null) ?? null,\n parentRunId: (r.parent_run_id as number | null) ?? null,\n gardId: (r.gard_id as number | null) ?? null,\n status: r.status as RunStatus,\n triggerType: (r.trigger_type as string) ?? \"message\",\n input: (r.input as Raw) ?? {},\n output: (r.output as string | null) ?? null,\n waitingFor: parseWaitingFor(r.waiting_for),\n failureMetadata: (r.failure_metadata as Raw) ?? {},\n inputTokens: (r.input_tokens as number) ?? 0,\n outputTokens: (r.output_tokens as number) ?? 0,\n cost: (r.cost as Run[\"cost\"]) ?? null,\n insertedAt: r.inserted_at as string,\n updatedAt: (r.updated_at as string) ?? (r.inserted_at as string),\n };\n}\n\nexport function parseEvent(e: Raw): RunEvent {\n return {\n id: e.id as number,\n sequence: e.sequence as number,\n eventType: e.event_type as string,\n payload: (e.payload as Raw) ?? {},\n source: (e.source as string) ?? \"\",\n insertedAt: e.inserted_at as string,\n };\n}\n\nexport function parseAgent(a: Raw): AgentInfo {\n return {\n id: a.id as number,\n name: a.name as string,\n purpose: (a.purpose as string | null) ?? null,\n status: (a.status as string) ?? \"active\",\n model: (a.model as string) ?? \"\",\n systemPrompt: (a.system_prompt as string) ?? \"\",\n maxSteps: (a.max_steps as number) ?? 50,\n contextStrategy: (a.context_strategy as string) ?? \"sliding_window\",\n contextWindow: (a.context_window as number) ?? 20,\n archivedAt: (a.archived_at as string | null) ?? null,\n insertedAt: a.inserted_at as string,\n updatedAt: (a.updated_at as string) ?? (a.inserted_at as string),\n };\n}\n\nexport function parseConversation(c: Raw): Conversation {\n return {\n id: c.id as number,\n agentId: c.agent_id as number,\n key: c.key as string,\n summary: (c.summary as string | null) ?? null,\n messageCount: (c.message_count as number) ?? 0,\n tokenEstimate: (c.token_estimate as number) ?? 0,\n insertedAt: c.inserted_at as string,\n updatedAt: (c.updated_at as string) ?? (c.inserted_at as string),\n };\n}\n","/**\n * A push-in, pull-out queue that is also an async iterable. Producers push\n * values (or close, or fail); a single consumer iterates. Used to turn a\n * channel's callbacks into `for await`.\n */\nexport class AsyncQueue<T> implements AsyncIterable<T> {\n #values: T[] = [];\n #waiters: Array<{ resolve: (r: IteratorResult<T>) => void; reject: (e: unknown) => void }> = [];\n #done = false;\n #error: unknown = undefined;\n\n push(value: T): void {\n if (this.#done) return;\n const waiter = this.#waiters.shift();\n if (waiter) waiter.resolve({ value, done: false });\n else this.#values.push(value);\n }\n\n close(): void {\n if (this.#done) return;\n this.#done = true;\n for (const w of this.#waiters.splice(0)) w.resolve({ value: undefined, done: true });\n }\n\n fail(error: unknown): void {\n if (this.#done) return;\n this.#done = true;\n this.#error = error;\n for (const w of this.#waiters.splice(0)) w.reject(error);\n }\n\n get closed(): boolean {\n return this.#done;\n }\n\n next(): Promise<IteratorResult<T>> {\n if (this.#values.length > 0) {\n return Promise.resolve({ value: this.#values.shift() as T, done: false });\n }\n if (this.#done) {\n return this.#error !== undefined\n ? Promise.reject(this.#error)\n : Promise.resolve({ value: undefined, done: true });\n }\n return new Promise((resolve, reject) => this.#waiters.push({ resolve, reject }));\n }\n\n [Symbol.asyncIterator](): AsyncIterator<T> {\n return { next: () => this.next() };\n }\n}\n","/** Base class for every error this SDK raises. */\nexport class NornsError extends Error {\n constructor(message: string, options?: { cause?: unknown }) {\n super(message, options);\n this.name = \"NornsError\";\n }\n}\n\n/** The Norns API answered with a non-2xx status. */\nexport class NornsApiError extends NornsError {\n readonly status: number;\n readonly body: unknown;\n\n constructor(status: number, body: unknown, message?: string) {\n super(message ?? `Norns API error ${status}: ${describeBody(body)}`);\n this.name = \"NornsApiError\";\n this.status = status;\n this.body = body;\n }\n}\n\n/** The thing asked for does not exist (404). */\nexport class NotFoundError extends NornsApiError {\n constructor(what: string, body: unknown = undefined) {\n super(404, body, `${what} not found`);\n this.name = \"NotFoundError\";\n }\n}\n\n/** A wait or a stream ran out of time. */\nexport class NornsTimeoutError extends NornsError {\n constructor(message: string) {\n super(message);\n this.name = \"NornsTimeoutError\";\n }\n}\n\n/**\n * The worker's channel join was rejected for a reason a retry cannot fix:\n * a bad claim token, a destroyed or missing gard, an invalid registration.\n */\nexport class JoinError extends NornsError {\n readonly reason: string;\n readonly code: string | undefined;\n\n constructor(reason: string, code?: string) {\n super(`worker join rejected: ${reason}${code ? ` (${code})` : \"\"}`);\n this.name = \"JoinError\";\n this.reason = reason;\n this.code = code;\n }\n}\n\n/** The gard this worker claimed was destroyed while it was connected. */\nexport class GardDestroyedError extends NornsError {\n constructor(gard: string | number | undefined) {\n super(`gard ${gard ?? \"?\"} was destroyed`);\n this.name = \"GardDestroyedError\";\n }\n}\n\n/** A stream's socket closed before the run reached a terminal event. */\nexport class StreamClosedError extends NornsError {\n readonly reason: unknown;\n\n constructor(reason: unknown) {\n super(`stream closed before the run finished: ${describeBody(reason)}`);\n this.name = \"StreamClosedError\";\n this.reason = reason;\n }\n}\n\nfunction describeBody(body: unknown): string {\n if (typeof body === \"string\") return body;\n if (body && typeof body === \"object\" && \"error\" in body) {\n const err = (body as { error: unknown }).error;\n return typeof err === \"string\" ? err : JSON.stringify(err);\n }\n if (body instanceof Error) return body.message;\n try {\n return JSON.stringify(body);\n } catch {\n return String(body);\n }\n}\n\n/** A readable message for anything thrown. */\nexport function errorMessage(err: unknown): string {\n if (err instanceof Error) return err.message;\n return describeBody(err);\n}\n","/** Where a run is: on the way, finished, or parked on a human. */\nexport type RunStatus = \"pending\" | \"running\" | \"waiting\" | \"completed\" | \"failed\" | \"error\";\n\n/** The question a run is parked on when its status is `\"waiting\"`. */\nexport interface WaitingFor {\n question: string;\n toolCallId: string;\n askedAt: string | undefined;\n}\n\nexport interface Run {\n id: number;\n agentId: number;\n conversationId: number | null;\n parentRunId: number | null;\n gardId: number | null;\n status: RunStatus;\n triggerType: string;\n input: Record<string, unknown>;\n output: string | null;\n /** Present when `status` is `\"waiting\"`: answer it with `client.runs.reply()`. */\n waitingFor: WaitingFor | null;\n failureMetadata: Record<string, unknown>;\n inputTokens: number;\n outputTokens: number;\n /** Dollars as a decimal string, so nothing rounds them through a float. */\n cost: { usd: string; unpriced: boolean } | null;\n insertedAt: string;\n updatedAt: string;\n}\n\nexport interface RunEvent {\n id: number;\n sequence: number;\n eventType: string;\n payload: Record<string, unknown>;\n source: string;\n insertedAt: string;\n}\n\n/** An agent as the server describes it. */\nexport interface AgentInfo {\n id: number;\n name: string;\n purpose: string | null;\n status: string;\n model: string;\n systemPrompt: string;\n maxSteps: number;\n contextStrategy: string;\n contextWindow: number;\n archivedAt: string | null;\n insertedAt: string;\n updatedAt: string;\n}\n\nexport interface Conversation {\n id: number;\n agentId: number;\n key: string;\n summary: string | null;\n messageCount: number;\n tokenEstimate: number;\n insertedAt: string;\n updatedAt: string;\n}\n\n/** What `sendMessage()` returns. */\nexport interface MessageResult {\n runId: number;\n /** `\"accepted\"` when not waiting; otherwise the run's status when the wait ended. */\n status: \"accepted\" | RunStatus;\n output: string | null;\n conversationKey: string | undefined;\n /** The agent is parked on a question and will not move until it is answered. */\n isWaiting: boolean;\n waitingFor: WaitingFor | null;\n}\n\n/** Every stream payload carries the run and agent it belongs to. */\ninterface Tagged {\n run_id: number;\n agent_id: number;\n}\n\n/**\n * An event from a run as it happens, keyed by `type`. The two terminal\n * events are `completed` and `error`. Unknown types pass through as\n * `{ type: string, data: object }` so a newer server never breaks a client.\n */\nexport type StreamEvent =\n | { type: \"agent_started\"; data: Tagged }\n | {\n type: \"llm_response\";\n data: Tagged & {\n step: number;\n finish_reason: string;\n content: string;\n tool_calls: Array<{ id: string; name: string; arguments: unknown }> | null;\n };\n }\n | { type: \"tool_call\"; data: Tagged & { name: string; arguments: unknown } }\n | {\n type: \"tool_result\";\n data: Tagged & {\n tool_call_id: string;\n name: string;\n content: string;\n [key: string]: unknown;\n };\n }\n | { type: \"waiting_for_user\"; data: Tagged & { tool_call_id: string; question: string } }\n | { type: \"waiting_timer\"; data: Tagged & { seconds: number; reason: string | null } }\n | { type: \"context_compacted\"; data: Tagged & { step: number; dropped: number; kept: number } }\n | { type: \"completed\"; data: Tagged & { output: string } }\n | { type: \"error\"; data: Tagged & { error: string } }\n | { type: string; data: Tagged & Record<string, unknown> };\n\nexport const TERMINAL_EVENTS: ReadonlySet<string> = new Set([\"completed\", \"error\"]);\n","/**\n * Where the SDK writes what it is doing. Anything with these four methods\n * works: `console`, pino, winston, or your own.\n */\nexport interface Logger {\n debug(message: string, ...rest: unknown[]): void;\n info(message: string, ...rest: unknown[]): void;\n warn(message: string, ...rest: unknown[]): void;\n error(message: string, ...rest: unknown[]): void;\n}\n\n/** Logs info and above to the console, prefixed so it is easy to grep. */\nexport const consoleLogger: Logger = {\n debug() {},\n info: (message, ...rest) => console.log(`[norns] ${message}`, ...rest),\n warn: (message, ...rest) => console.warn(`[norns] ${message}`, ...rest),\n error: (message, ...rest) => console.error(`[norns] ${message}`, ...rest),\n};\n\nexport const silentLogger: Logger = {\n debug() {},\n info() {},\n warn() {},\n error() {},\n};\n\nexport function resolveLogger(logger: Logger | null | undefined): Logger {\n if (logger === null) return silentLogger;\n return logger ?? consoleLogger;\n}\n","import type { LanguageModel } from \"ai\";\n\n/** Turns the model name on an LLM task into something the AI SDK can call. */\nexport type ModelResolver = (modelId: string) => LanguageModel | Promise<LanguageModel>;\n\n/** A provider, or a registry from `createProviderRegistry()`. */\nexport interface ModelSource {\n languageModel(modelId: string): LanguageModel;\n}\n\nexport type ModelsOption = ModelResolver | ModelSource;\n\nconst PROVIDER_PACKAGES: Record<string, string> = {\n anthropic: \"@ai-sdk/anthropic\",\n openai: \"@ai-sdk/openai\",\n google: \"@ai-sdk/google\",\n mistral: \"@ai-sdk/mistral\",\n};\n\n/**\n * Split `\"provider/model\"` (or `\"provider:model\"`) into its parts, inferring\n * the provider from the model's name when there is no prefix.\n */\nexport function inferProvider(model: string): { provider: string; modelId: string } {\n const sep = model.search(/[/:]/);\n if (sep > 0) {\n const provider = model.slice(0, sep);\n if (provider in PROVIDER_PACKAGES || /^[a-z][a-z0-9-]*$/.test(provider)) {\n return { provider, modelId: model.slice(sep + 1) };\n }\n }\n const lower = model.toLowerCase();\n if (lower.startsWith(\"claude\")) return { provider: \"anthropic\", modelId: model };\n if (/^(gpt|o[1-9]|chatgpt|text-)/.test(lower)) return { provider: \"openai\", modelId: model };\n if (lower.startsWith(\"gemini\")) return { provider: \"google\", modelId: model };\n if (/^(mistral|codestral|ministral|pixtral|magistral)/.test(lower)) {\n return { provider: \"mistral\", modelId: model };\n }\n return { provider: \"anthropic\", modelId: model };\n}\n\n/**\n * The default: pick the `@ai-sdk/*` package for the model's provider, load\n * it if it is installed, and ask it for the model. API keys come from the\n * provider's own environment variable (`ANTHROPIC_API_KEY`, `OPENAI_API_KEY`, ...).\n */\nexport function defaultModelResolver(): ModelResolver {\n const cache = new Map<string, Promise<LanguageModel>>();\n return (model) => {\n let pending = cache.get(model);\n if (!pending) {\n pending = loadModel(model);\n cache.set(model, pending);\n pending.catch(() => cache.delete(model));\n }\n return pending;\n };\n}\n\nasync function loadModel(model: string): Promise<LanguageModel> {\n const { provider, modelId } = inferProvider(model);\n const pkg = PROVIDER_PACKAGES[provider] ?? `@ai-sdk/${provider}`;\n\n let mod: Record<string, unknown>;\n try {\n mod = (await import(pkg)) as Record<string, unknown>;\n } catch (err) {\n throw new Error(\n `No provider for model '${model}': install ${pkg} (npm install ${pkg}), ` +\n \"or pass `models` to the worker to resolve models yourself\",\n { cause: err },\n );\n }\n\n const instance = findProvider(mod, provider);\n if (!instance) {\n throw new Error(`${pkg} exports no provider instance; pass \\`models\\` to the worker`);\n }\n return instance(modelId);\n}\n\ntype ProviderFn = ((modelId: string) => LanguageModel) & { languageModel?: unknown };\n\n// Each package exports a default instance named for the provider\n// (`anthropic`, `openai`, ...); fall back to any callable with `languageModel`.\nfunction findProvider(mod: Record<string, unknown>, provider: string): ProviderFn | undefined {\n const named = mod[provider];\n if (typeof named === \"function\") return named as ProviderFn;\n for (const value of Object.values(mod)) {\n if (typeof value === \"function\" && \"languageModel\" in value) return value as ProviderFn;\n }\n return undefined;\n}\n\nexport function toResolver(models: ModelsOption | undefined): ModelResolver {\n if (models === undefined) return defaultModelResolver();\n if (typeof models === \"function\") return models;\n return (id) => models.languageModel(id);\n}\n","import { asSchema, type FlexibleSchema, type JSONSchema7, jsonSchema } from \"ai\";\nimport type { NornsWorker } from \"./worker.js\";\n\n/**\n * What a tool's `execute` is told about the call, besides its input.\n *\n * `signal` aborts when the worker gives up on the call: the socket dropped\n * (Norns re-dispatches the task) or a drain hit its deadline. A long tool\n * should pass it to whatever it waits on.\n */\nexport interface ToolContext {\n taskId: string;\n runId: number | undefined;\n agentId: number | undefined;\n /**\n * Set when Norns considers the call side-effecting. Same run, same step,\n * same tool call, same key, however many times it is dispatched; hand it\n * to a provider that dedupes (most payment APIs take one) and the effect\n * survives this worker dying mid-call too.\n */\n idempotencyKey: string | undefined;\n signal: AbortSignal;\n worker: NornsWorker;\n}\n\n/** A Zod schema, any Standard Schema, an `ai` `Schema`, or raw JSON Schema. */\nexport type ToolInputSchema = FlexibleSchema | JSONSchema7;\n\n/** The argument type `execute` receives for a given `input` schema. */\nexport type InferToolInput<S> = S extends FlexibleSchema<infer T> ? T : Record<string, unknown>;\n\nexport interface ToolOptions<S extends ToolInputSchema = ToolInputSchema> {\n /** What the model calls it by. */\n name: string;\n /** What the model reads to decide when to call it. */\n description: string;\n /**\n * The input shape. A Zod object schema gives a typed, validated `execute`;\n * leave it out for a tool that takes nothing.\n */\n input?: S;\n /**\n * Mark a tool whose call must not happen twice. Norns then names each call\n * with an idempotency key, and a re-dispatched call is answered from the\n * result this worker kept rather than run again.\n */\n sideEffect?: boolean;\n /**\n * The handler. Return a string, or anything JSON-serialisable (it is\n * stringified for the model). Throwing reports an error result; the model\n * sees the message.\n */\n execute: (input: InferToolInput<S>, context: ToolContext) => unknown | Promise<unknown>;\n}\n\nexport type ValidationResult<T> = { success: true; value: T } | { success: false; error: Error };\n\n/** A tool ready to register with a worker: what `tool()` returns. */\nexport interface ToolDefinition<I = unknown> {\n readonly name: string;\n readonly description: string;\n readonly inputSchema: JSONSchema7;\n readonly sideEffect: boolean;\n /** Validates and coerces an input against the schema, when there is one. */\n readonly validate: ((value: unknown) => Promise<ValidationResult<I>>) | undefined;\n // Method syntax on purpose: it is bivariant, so a `ToolDefinition<{ q: string }>`\n // fits a `ToolDefinition[]` without the caller casting.\n execute(input: I, context: ToolContext): Promise<unknown>;\n}\n\nconst EMPTY_SCHEMA: JSONSchema7 = { type: \"object\", properties: {} };\n\n/**\n * Define a tool.\n *\n * const searchDocs = tool({\n * name: \"search_docs\",\n * description: \"Search product documentation.\",\n * input: z.object({ query: z.string() }),\n * execute: async ({ query }) => db.search(query),\n * });\n */\nexport function tool<S extends ToolInputSchema>(\n options: ToolOptions<S>,\n): ToolDefinition<InferToolInput<S>> {\n type I = InferToolInput<S>;\n const name = options.name?.trim();\n if (!name) throw new Error(\"tool(): name is required\");\n if (!options.description?.trim()) throw new Error(`tool('${name}'): description is required`);\n if (typeof options.execute !== \"function\") {\n throw new Error(`tool('${name}'): execute must be a function`);\n }\n\n let inputSchema: JSONSchema7 = EMPTY_SCHEMA;\n let validate: ToolDefinition<I>[\"validate\"];\n\n if (options.input !== undefined) {\n const schema = asSchema(toFlexible(options.input));\n const json = schema.jsonSchema;\n if (isPromiseLike(json)) {\n throw new Error(`tool('${name}'): input schema must resolve synchronously`);\n }\n inputSchema = stripMeta(json);\n if (schema.validate) {\n const run = schema.validate;\n validate = async (value) => {\n const result = await run(value);\n return result.success\n ? { success: true, value: result.value as I }\n : { success: false, error: result.error };\n };\n }\n }\n\n const execute = options.execute;\n return Object.freeze({\n name,\n description: options.description.trim(),\n inputSchema,\n sideEffect: options.sideEffect ?? false,\n validate,\n execute: async (input: I, context: ToolContext) => execute(input, context),\n });\n}\n\n/** The wire form Norns reads at join. */\nexport function toolRegistration(t: ToolDefinition): {\n name: string;\n description: string;\n input_schema: JSONSchema7;\n side_effect: boolean;\n} {\n return {\n name: t.name,\n description: t.description,\n input_schema: t.inputSchema,\n side_effect: t.sideEffect,\n };\n}\n\n/** Turn a tool's output into the string the model reads. */\nexport function stringifyToolOutput(value: unknown): string {\n if (value === undefined || value === null) return \"\";\n if (typeof value === \"string\") return value;\n return JSON.stringify(value);\n}\n\nfunction toFlexible(input: ToolInputSchema): FlexibleSchema {\n if (isRawJsonSchema(input)) return jsonSchema(input);\n return input as FlexibleSchema;\n}\n\n// A plain object is JSON Schema; anything that knows how to validate\n// itself (Zod, Standard Schema, an `ai` Schema) is not.\nfunction isRawJsonSchema(value: unknown): value is JSONSchema7 {\n if (typeof value !== \"object\" || value === null) return false;\n if (\"~standard\" in value || \"_zod\" in value || \"_def\" in value || \"jsonSchema\" in value) {\n return false;\n }\n return true;\n}\n\nfunction isPromiseLike(value: unknown): value is PromiseLike<unknown> {\n return (\n typeof value === \"object\" &&\n value !== null &&\n \"then\" in value &&\n typeof (value as { then: unknown }).then === \"function\"\n );\n}\n\nfunction stripMeta(schema: JSONSchema7): JSONSchema7 {\n const { $schema: _ignored, ...rest } = schema;\n return rest;\n}\n","import { randomBytes } from \"node:crypto\";\nimport { generateText } from \"ai\";\nimport { type Channel, Socket, type SocketConnectOption } from \"phoenix\";\nimport { type AgentDefinition, agentList, toolsByName } from \"./agent.js\";\nimport {\n NornsClient,\n resolveApiKey,\n resolveUrl,\n sleep,\n type WebSocketConstructor,\n wsBase,\n} from \"./client.js\";\nimport { CompletedCalls, completedCallsPath } from \"./completed-calls.js\";\nimport { errorMessage, GardDestroyedError, JoinError, NornsError } from \"./errors.js\";\nimport {\n compactionMessages,\n composeCompactionPrompt,\n composeSystemPrompt,\n finalOutput,\n fromGenerateResult,\n type LlmResult,\n type LlmTask,\n maxTokens,\n messagesForTask,\n type ToolResult,\n type ToolTask,\n toInstructions,\n toModelMessages,\n toToolSet,\n} from \"./format.js\";\nimport { HistoryCache } from \"./history-cache.js\";\nimport { type Logger, resolveLogger } from \"./logger.js\";\nimport { type ModelResolver, type ModelsOption, toResolver } from \"./models.js\";\nimport {\n stringifyToolOutput,\n type ToolContext,\n type ToolDefinition,\n toolRegistration,\n} from \"./tool.js\";\n\nexport type Capability = \"llm\" | \"tools\";\n\nexport interface NornsWorkerOptions {\n /** The agent, or agents, this worker serves. */\n agents: AgentDefinition | AgentDefinition[];\n /** The Norns base URL. Defaults to `NORNS_URL`. */\n url?: string;\n /** The tenant's bearer token. Defaults to `NORNS_API_KEY`. */\n apiKey?: string;\n /**\n * How a model name on an LLM task becomes a model to call: a function, a\n * provider (`anthropic`), or a registry from `createProviderRegistry()`.\n * By default the provider is inferred from the name and its `@ai-sdk/*`\n * package loaded; API keys come from the provider's own env var.\n */\n models?: ModelsOption;\n /** What this worker serves. Default both; `[\"tools\"]` for a worker with no LLM access. */\n capabilities?: Capability[];\n /** A stable identity. Defaults to `NORNS_WORKER_ID`, else a random one. */\n workerId?: string;\n /** Claim a gard (defaults to `NORNS_GARD`); needs `claimToken`. */\n gard?: string | number;\n /** Defaults to `NORNS_GARD_CLAIM_TOKEN`. */\n claimToken?: string;\n /** How long `stop()` waits for in-flight tasks. Default 30 s, or `NORNS_SHUTDOWN_TIMEOUT` (seconds). */\n shutdownTimeoutMs?: number;\n /** Drain on SIGINT/SIGTERM. Default true. */\n handleSignals?: boolean;\n /** Where to log. `null` for silence. Default: the console. */\n logger?: Logger | null;\n /**\n * Where completed side-effecting calls are remembered across restarts.\n * Defaults to `NORNS_STATE_DIR`, else the system temp dir; `null` disables.\n */\n stateDir?: string | null;\n /** Replace the global `fetch` (used to register the agents). */\n fetch?: typeof globalThis.fetch;\n /** Replace the global `WebSocket`. */\n transport?: WebSocketConstructor;\n /** Extra options for the Phoenix socket. */\n socketOptions?: Partial<SocketConnectOption>;\n}\n\nexport interface RegisterPortOptions {\n name?: string;\n url?: string;\n protocol?: string;\n}\n\nexport interface RegisteredPort {\n id: number;\n internalPort: number;\n url: string | null;\n}\n\ntype WorkerState = \"idle\" | \"starting\" | \"running\" | \"draining\" | \"stopped\";\n\ninterface InFlight {\n taskId: string;\n controller: AbortController;\n done: Promise<void>;\n}\n\nconst TOPIC = \"worker:lobby\";\n\n/**\n * Serves agents: connects to Norns, registers their tools, and handles the\n * LLM and tool tasks it is sent.\n *\n * const worker = new NornsWorker({ agents: [supportBot] });\n * await worker.start(); // resolves once joined; Ctrl-C drains and exits\n *\n * `start()` resolves when the worker has joined, so the rest of your program\n * can carry on; the open socket keeps the process alive. `stop()` drains:\n * Norns stops sending work, in-flight tasks finish and report, and the\n * worker leaves. `stopped` settles when that is done.\n */\nexport class NornsWorker {\n readonly url: string;\n readonly workerId: string;\n readonly gard: string | number | undefined;\n\n readonly #apiKey: string;\n readonly #agents: AgentDefinition[];\n readonly #tools: Map<string, ToolDefinition>;\n readonly #capabilities: Capability[];\n readonly #claimToken: string | undefined;\n readonly #shutdownTimeoutMs: number;\n readonly #handleSignals: boolean;\n readonly #logger: Logger;\n readonly #stateDir: string | null | undefined;\n readonly #transport: WebSocketConstructor | undefined;\n readonly #socketOptions: Partial<SocketConnectOption>;\n readonly #client: NornsClient;\n readonly #resolveModel: ModelResolver;\n readonly #inFlight = new Set<InFlight>();\n readonly #history = new HistoryCache();\n\n #state: WorkerState = \"idle\";\n #socket: Socket | undefined;\n #channel: Channel | undefined;\n #completed: CompletedCalls | undefined;\n #starting: Promise<void> | undefined;\n #signalHandler: ((signal: NodeJS.Signals) => void) | undefined;\n readonly #stopped: Promise<void>;\n #settleStopped!: { resolve: () => void; reject: (err: unknown) => void };\n\n constructor(options: NornsWorkerOptions) {\n this.url = resolveUrl(options.url);\n this.#apiKey = resolveApiKey(options.apiKey);\n this.#agents = agentList(options.agents);\n this.#tools = toolsByName(this.#agents);\n this.#capabilities = options.capabilities ?? [\"llm\", \"tools\"];\n if (this.#capabilities.length === 0)\n throw new NornsError(\"A worker needs at least one capability\");\n this.#logger = resolveLogger(options.logger);\n this.#stateDir = options.stateDir;\n this.#transport = options.transport;\n this.#socketOptions = options.socketOptions ?? {};\n this.#handleSignals = options.handleSignals ?? true;\n this.#resolveModel = toResolver(options.models);\n\n // A provisioner (volund) hands the worker its identity and gard through\n // the environment, so scaffolded workers need no code changes.\n this.workerId =\n options.workerId ??\n process.env.NORNS_WORKER_ID ??\n `ts-worker-${randomBytes(4).toString(\"hex\")}`;\n this.gard = options.gard ?? process.env.NORNS_GARD;\n this.#claimToken = options.claimToken ?? process.env.NORNS_GARD_CLAIM_TOKEN;\n\n const envTimeout = Number(process.env.NORNS_SHUTDOWN_TIMEOUT);\n this.#shutdownTimeoutMs =\n options.shutdownTimeoutMs ??\n (Number.isFinite(envTimeout) && envTimeout > 0 ? envTimeout * 1000 : 30_000);\n\n this.#client = new NornsClient({ url: this.url, apiKey: this.#apiKey, fetch: options.fetch });\n\n this.#stopped = new Promise<void>((resolve, reject) => {\n this.#settleStopped = { resolve, reject };\n });\n // Nobody has to await `stopped`; a rejection must not crash the process.\n this.#stopped.catch(() => {});\n }\n\n /** The agents this worker serves. */\n get agents(): readonly AgentDefinition[] {\n return this.#agents;\n }\n\n get state(): WorkerState {\n return this.#state;\n }\n\n /**\n * Settles once the worker has stopped: resolves after a drain, rejects\n * with `JoinError` or `GardDestroyedError` when it was forced off.\n */\n get stopped(): Promise<void> {\n return this.#stopped;\n }\n\n /**\n * Register the agents, connect, and join. Resolves once Norns has accepted\n * the worker; rejects with `JoinError` when it never will (bad claim\n * token, destroyed gard). A server that is down is retried until it is up.\n */\n start(): Promise<void> {\n if (this.#state !== \"idle\") throw new NornsError(\"start() may only be called once\");\n this.#state = \"starting\";\n this.#starting = this.#start().then(\n () => {\n if (this.#state === \"starting\") this.#state = \"running\";\n },\n (err) => {\n this.#fail(err);\n throw err;\n },\n );\n return this.#starting;\n }\n\n async #start(): Promise<void> {\n for (const agent of this.#agents) {\n const info = await this.#client.agents.ensure(agent);\n this.#logger.info(`Registered agent '${agent.name}' (id=${info.id})`);\n }\n\n if (this.#capabilities.includes(\"llm\")) {\n // A model nobody can serve fails here, with a message, not on the first task.\n for (const model of new Set(this.#agents.map((a) => a.model))) {\n await this.#resolveModel(model);\n }\n }\n\n // Keyed by worker id: Norns re-dispatches a lost call to whichever\n // worker comes back under that identity, and this is what it needs to\n // recognise it.\n this.#completed = new CompletedCalls(\n completedCallsPath(this.workerId, this.#stateDir),\n this.#logger,\n );\n\n await this.#connect();\n this.#installSignalHandlers();\n }\n\n #connect(): Promise<void> {\n const socket = new Socket(`${wsBase(this.url)}/worker`, {\n params: { token: this.#apiKey },\n logger: (kind, msg, data) => this.#logger.debug(`phoenix ${kind}: ${msg}`, data),\n ...(this.#transport\n ? { transport: this.#transport as SocketConnectOption[\"transport\"] }\n : {}),\n ...this.#socketOptions,\n });\n this.#socket = socket;\n\n socket.onOpen(() => {\n this.#logger.info(`Connected to ${this.url}`);\n // Norns sends deltas only on the connection it sent the history on, so\n // a new connection starts with nothing to be stale.\n this.#history.clear();\n });\n socket.onError((err) => {\n if (this.#state === \"starting\" || this.#state === \"running\") {\n this.#logger.warn(`Connection error (${errorMessage(err)}); retrying`);\n }\n });\n socket.onClose(() => {\n if (this.#state === \"running\") {\n this.#logger.warn(\"Disconnected from Norns; reconnecting\");\n // In-flight results cannot be delivered on the next connection: Norns\n // re-dispatches on disconnect, and idempotency skips completed side effects.\n this.#abortInFlight(\"socket closed\");\n }\n });\n\n const channel = socket.channel(TOPIC, this.#joinParams());\n this.#channel = channel;\n channel.on(\"llm_task\", (task: LlmTask) =>\n this.#spawn(task.task_id, (s) => this.#runLlm(task, s)),\n );\n channel.on(\"tool_task\", (task: ToolTask) =>\n this.#spawn(task.task_id, (s) => this.#runTool(task, s)),\n );\n channel.on(\"gard_destroyed\", () => {\n this.#logger.error(\"This worker's gard was destroyed; shutting down\");\n this.#fail(new GardDestroyedError(this.gard));\n });\n channel.onError((reason) => {\n if (this.#state === \"running\")\n this.#logger.warn(`Channel error (${errorMessage(reason)}); rejoining`);\n });\n\n return new Promise<void>((resolve, reject) => {\n let joined = false;\n channel\n .join()\n .receive(\"ok\", () => {\n if (joined) {\n this.#logger.info(`Worker ${this.workerId} rejoined`);\n return;\n }\n joined = true;\n this.#logger.info(\n this.gard !== undefined\n ? `Worker ${this.workerId} ready (gard ${this.gard})`\n : `Worker ${this.workerId} ready`,\n );\n resolve();\n })\n .receive(\"error\", (resp: { reason?: string; code?: string } | undefined) => {\n const reason = resp?.reason ?? \"join rejected\";\n // On a quick reconnect the server may not have processed the old\n // connection's disconnect yet; the channel rejoins by itself.\n if (reason === \"already_claimed\") {\n this.#logger.warn(\"Gard claim rejected: already_claimed; retrying\");\n return;\n }\n const err = new JoinError(reason, resp?.code);\n this.#fail(err);\n reject(err);\n })\n .receive(\"timeout\", () => this.#logger.warn(\"Join timed out; retrying\"));\n socket.connect();\n });\n }\n\n #joinParams(): Record<string, unknown> {\n const params: Record<string, unknown> = {\n worker_id: this.workerId,\n tools: [...this.#tools.values()].map(toolRegistration),\n capabilities: this.#capabilities,\n // This worker keeps the history it was last sent per run, so Norns may\n // send later steps as the change only (HistoryCache).\n features: [\"message_cache\"],\n };\n if (this.gard !== undefined) {\n params.gard = this.gard;\n params.claim_token = this.#claimToken ?? null;\n }\n return params;\n }\n\n /**\n * Drain and stop: tell Norns to send no more work, finish the tasks in\n * flight (up to the shutdown timeout), report them, leave. Tasks still\n * running at the deadline are dropped and Norns re-dispatches them.\n */\n async stop(): Promise<void> {\n if (this.#state === \"idle\") {\n this.#state = \"stopped\";\n this.#settleStopped.resolve();\n return;\n }\n if (this.#state === \"starting\") {\n try {\n await this.#starting;\n } catch {\n return;\n }\n }\n if (this.#state !== \"running\") return this.#stopped;\n this.#state = \"draining\";\n\n const channel = this.#channel;\n const socket = this.#socket;\n this.#logger.info(\n `Draining: ${this.#inFlight.size} in-flight task(s), up to ${this.#shutdownTimeoutMs / 1000}s`,\n );\n\n // Norns stops dispatching to us. In-flight tasks stay ours; new ones\n // queue for our replacement.\n if (channel) {\n await new Promise<void>((resolve) => {\n channel\n .push(\"drain\", {}, 5000)\n .receive(\"ok\", () => resolve())\n .receive(\"error\", (resp) => {\n this.#logger.warn(\n `Could not send drain (${errorMessage(resp)}); Norns will re-dispatch on disconnect`,\n );\n resolve();\n })\n .receive(\"timeout\", () => resolve());\n });\n }\n\n // Wait for what we hold, including anything that raced in before the\n // drain took effect, until the deadline.\n const deadline = Date.now() + this.#shutdownTimeoutMs;\n while (this.#inFlight.size > 0 && Date.now() < deadline) {\n await Promise.race([\n Promise.allSettled([...this.#inFlight].map((t) => t.done)),\n sleep(deadline - Date.now()),\n ]);\n }\n if (this.#inFlight.size > 0) {\n this.#logger.warn(\n `${this.#inFlight.size} task(s) still running at the deadline; dropping them, Norns will re-dispatch`,\n );\n this.#abortInFlight(\"shutdown deadline\");\n } else {\n this.#logger.info(\"Drained; leaving\");\n }\n\n if (channel) {\n await new Promise<void>((resolve) => {\n channel\n .leave(5000)\n .receive(\"ok\", () => resolve())\n .receive(\"timeout\", () => resolve());\n });\n }\n if (socket) await new Promise<void>((resolve) => socket.disconnect(() => resolve()));\n\n this.#teardown();\n this.#state = \"stopped\";\n this.#logger.info(\"Worker stopped.\");\n this.#settleStopped.resolve();\n }\n\n /**\n * Expose a service port for the dashboard. Only in a gard: the gard is\n * inferred from the connection. Call it from a tool after starting a\n * service.\n */\n async registerPort(\n internalPort: number,\n options: RegisterPortOptions = {},\n ): Promise<RegisteredPort> {\n if (this.gard === undefined)\n throw new NornsError(\"registerPort requires the worker to be in a gard\");\n const channel = this.#channel;\n if (channel?.state !== \"joined\") {\n throw new NornsError(\"registerPort requires a connected worker\");\n }\n const payload: Record<string, unknown> = {\n internal_port: internalPort,\n name: options.name ?? \"\",\n protocol: options.protocol ?? \"http\",\n };\n if (options.url) payload.url = options.url;\n\n return new Promise((resolve, reject) => {\n channel\n .push(\"register_port\", payload, 10_000)\n .receive(\"ok\", (resp: { id: number; internal_port: number; url: string | null }) =>\n resolve({ id: resp.id, internalPort: resp.internal_port, url: resp.url ?? null }),\n )\n .receive(\"error\", (resp) =>\n reject(new NornsError(`register_port rejected: ${errorMessage(resp?.reason ?? resp)}`)),\n )\n .receive(\"timeout\", () => reject(new NornsError(\"register_port timed out\")));\n });\n }\n\n // --- Tasks ---\n\n // Each task runs on its own: a slow tool or LLM call must not hold up the\n // others on this connection (parallel tool calls, other runs).\n #spawn(taskId: string, run: (signal: AbortSignal) => Promise<LlmResult | ToolResult>): void {\n const controller = new AbortController();\n const entry: InFlight = { taskId, controller, done: Promise.resolve() };\n entry.done = (async () => {\n try {\n const result = await run(controller.signal);\n this.#deliver(taskId, result);\n } catch (err) {\n this.#logger.error(`Task ${taskId} failed unexpectedly: ${errorMessage(err)}`);\n this.#deliver(taskId, { status: \"error\", error: errorMessage(err) });\n } finally {\n this.#inFlight.delete(entry);\n }\n })();\n this.#inFlight.add(entry);\n }\n\n #deliver(taskId: string, result: LlmResult | ToolResult): void {\n const channel = this.#channel;\n if (channel?.state !== \"joined\") {\n this.#logger.warn(\n `Could not deliver result for task ${taskId} (not joined); Norns re-dispatches it on reconnect`,\n );\n return;\n }\n channel\n .push(\"tool_result\", { ...result, task_id: taskId })\n .receive(\"error\", (resp) =>\n this.#logger.warn(`Server rejected result for ${taskId}: ${errorMessage(resp)}`),\n );\n }\n\n async #runLlm(received: LlmTask, signal: AbortSignal): Promise<LlmResult> {\n const task = this.#history.resolve(received);\n if (task === undefined) {\n // The delta was built on a history this worker no longer holds. Norns\n // resends the whole list at the same step; no retry counted.\n this.#logger.info(\n \"LLM task arrived as a delta on an unknown base; asking for the full history\",\n );\n return { status: \"error\", error: \"message_cache_miss\" };\n }\n const model = task.model ?? \"?\";\n const tools = task.tools ?? [];\n this.#logger.info(\n `LLM call → ${model} (${task.messages?.length ?? 0} messages, ${tools.length} tools)`,\n );\n const result = await this.#callModel(task, signal);\n this.#logger.info(\n `LLM done → ${result.status === \"ok\" ? result.finish_reason : `error: ${result.error}`}`,\n );\n return result;\n }\n\n async #callModel(task: LlmTask, signal: AbortSignal): Promise<LlmResult> {\n try {\n const model = await this.#resolveModel(\n task.model ?? this.#agents[0]?.model ?? \"claude-sonnet-5\",\n );\n\n if (task.purpose === \"compact\") {\n // Fold the history into a summary Norns carries forward without reading.\n const result = await generateText({\n model,\n instructions: toInstructions(composeCompactionPrompt(task)),\n messages: toModelMessages(compactionMessages(task)),\n maxOutputTokens: maxTokens(task),\n abortSignal: signal,\n });\n const out = fromGenerateResult(result);\n return {\n status: \"ok\",\n content: out.content,\n finish_reason: \"stop\",\n usage: out.usage,\n model: out.model,\n };\n }\n\n // Norns sends the def's prompt verbatim and never writes prose for the\n // model: the worker composes the prompt, renders kinded messages,\n // elides old tool results, and decides the final output.\n const neutral = messagesForTask(task);\n const toolSet = toToolSet(task.tools ?? []);\n const result = await generateText({\n model,\n instructions: toInstructions(composeSystemPrompt(task)),\n messages: toModelMessages(neutral),\n tools: Object.keys(toolSet).length > 0 ? toolSet : undefined,\n maxOutputTokens: maxTokens(task),\n abortSignal: signal,\n });\n const out = fromGenerateResult(result);\n out.final_output = finalOutput(neutral, out.content);\n return out;\n } catch (err) {\n this.#logger.error(`LLM error: ${errorMessage(err)}`);\n return { status: \"error\", error: errorMessage(err) };\n }\n }\n\n async #runTool(task: ToolTask, signal: AbortSignal): Promise<ToolResult> {\n const name = task.tool_name ?? \"?\";\n this.#logger.info(`Tool call → ${name}`);\n const result = await this.#executeTool(task, signal);\n const preview = (result.status === \"ok\" ? result.result : result.error).slice(0, 80);\n this.#logger.info(`Tool done → ${name}: ${result.status} ${preview}`);\n return result;\n }\n\n // A key on the task means Norns considers the call side-effecting and has\n // named it. It cannot know whether the effect landed, so if the result\n // never reached it, it asks again; this worker answers from what it kept\n // rather than doing the thing twice.\n async #executeTool(task: ToolTask, signal: AbortSignal): Promise<ToolResult> {\n const key = task.idempotency_key;\n const completed = this.#completed;\n if (key && completed?.has(key)) {\n this.#logger.info(`Tool ${task.tool_name}: already done (${key}), reusing the result`);\n return completed.get(key) as ToolResult;\n }\n\n const tool = this.#tools.get(task.tool_name);\n if (!tool) return { status: \"error\", error: `Unknown tool: ${task.tool_name}` };\n\n let input: unknown = task.input ?? {};\n if (tool.validate) {\n const checked = await tool.validate(input);\n if (!checked.success) {\n return {\n status: \"error\",\n error: `Invalid input for ${tool.name}: ${checked.error.message}`,\n };\n }\n input = checked.value;\n }\n\n const context: ToolContext = {\n taskId: task.task_id,\n runId: task.run_id,\n agentId: task.agent_id,\n idempotencyKey: key,\n signal,\n worker: this,\n };\n\n try {\n const output = await tool.execute(input, context);\n const result: ToolResult = { status: \"ok\", result: stringifyToolOutput(output) };\n if (key) completed?.add(key, { ...result, duplicate: true });\n return result;\n } catch (err) {\n this.#logger.error(`Tool ${tool.name} failed: ${errorMessage(err)}`);\n // Failures are not remembered: a retry of something that did not happen should happen.\n return { status: \"error\", error: errorMessage(err) };\n }\n }\n\n // --- Lifecycle plumbing ---\n\n #abortInFlight(reason: string): void {\n for (const t of this.#inFlight) t.controller.abort(new NornsError(reason));\n }\n\n // Forced off: a fatal join, a destroyed gard. Nothing to drain.\n #fail(err: unknown): void {\n if (this.#state === \"stopped\") return;\n this.#state = \"stopped\";\n this.#abortInFlight(\"worker stopped\");\n this.#teardown();\n this.#socket?.disconnect();\n this.#settleStopped.reject(err);\n }\n\n #teardown(): void {\n if (this.#signalHandler) {\n process.off(\"SIGINT\", this.#signalHandler);\n process.off(\"SIGTERM\", this.#signalHandler);\n this.#signalHandler = undefined;\n }\n }\n\n #installSignalHandlers(): void {\n if (!this.#handleSignals) return;\n this.#signalHandler = (signal) => {\n if (this.#state !== \"running\") {\n this.#logger.warn(`Received ${signal} again: exiting now`);\n process.exit(130);\n }\n this.#logger.info(`Received ${signal}: shutting down`);\n void this.stop();\n };\n process.on(\"SIGINT\", this.#signalHandler);\n process.on(\"SIGTERM\", this.#signalHandler);\n }\n}\n","import { mkdirSync, readFileSync, renameSync, writeFileSync } from \"node:fs\";\nimport { tmpdir } from \"node:os\";\nimport { dirname, join } from \"node:path\";\nimport type { Logger } from \"./logger.js\";\n\nexport const MAX_REMEMBERED_RESULTS = 512;\n\n/**\n * What this worker has already done, by idempotency key.\n *\n * Kept on disk, because the case it exists for is the worker dying: Norns\n * re-dispatches the call it was holding, and a worker that came back with\n * an empty head would do the side effect a second time, which is the exact\n * thing the key is supposed to prevent.\n *\n * It is a crash guard, not a ledger. Bounded, best-effort, and never allowed\n * to take a worker down: if the file cannot be read or written, the worker\n * runs with memory alone and says so once.\n */\nexport class CompletedCalls {\n #path: string | undefined;\n readonly #limit: number;\n readonly #entries = new Map<string, Record<string, unknown>>();\n readonly #logger: Logger;\n\n constructor(path: string | undefined, logger: Logger, limit = MAX_REMEMBERED_RESULTS) {\n this.#path = path;\n this.#limit = limit;\n this.#logger = logger;\n this.#load();\n }\n\n get path(): string | undefined {\n return this.#path;\n }\n\n get size(): number {\n return this.#entries.size;\n }\n\n has(key: string): boolean {\n return this.#entries.has(key);\n }\n\n get(key: string): Record<string, unknown> | undefined {\n const entry = this.#entries.get(key);\n return entry ? { ...entry } : undefined;\n }\n\n add(key: string, result: Record<string, unknown>): void {\n this.#entries.delete(key);\n this.#entries.set(key, result);\n while (this.#entries.size > this.#limit) {\n const oldest = this.#entries.keys().next().value;\n if (oldest === undefined) break;\n this.#entries.delete(oldest);\n }\n this.#save();\n }\n\n #load(): void {\n if (!this.#path) return;\n let raw: string;\n try {\n raw = readFileSync(this.#path, \"utf8\");\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code !== \"ENOENT\") {\n this.#logger.warn(\n `Could not read ${this.#path} (${(err as Error).message}); starting with no memory of completed calls`,\n );\n }\n return;\n }\n try {\n const data = JSON.parse(raw) as Record<string, Record<string, unknown>>;\n for (const [key, value] of Object.entries(data)) {\n if (value && typeof value === \"object\") this.#entries.set(key, value);\n }\n } catch (err) {\n this.#logger.warn(\n `Could not parse ${this.#path} (${(err as Error).message}); starting with no memory of completed calls`,\n );\n }\n }\n\n #save(): void {\n if (!this.#path) return;\n try {\n mkdirSync(dirname(this.#path), { recursive: true });\n const tmp = `${this.#path}.tmp`;\n writeFileSync(tmp, JSON.stringify(Object.fromEntries(this.#entries)));\n renameSync(tmp, this.#path);\n } catch (err) {\n this.#logger.warn(\n `Could not write ${this.#path} (${(err as Error).message}); completed calls will not survive a restart`,\n );\n this.#path = undefined;\n }\n }\n}\n\n/**\n * Where a worker keeps what it has already done: `NORNS_STATE_DIR` if set\n * (empty disables), else a directory under the system temp dir. Enough to\n * outlive the process, which is the failure this guards, and nothing a\n * project has to clean up.\n */\nexport function completedCallsPath(\n workerId: string,\n stateDir: string | null | undefined,\n): string | undefined {\n const base = stateDir === undefined ? process.env.NORNS_STATE_DIR : stateDir;\n if (base === \"\" || base === null) return undefined;\n const root = base ?? join(tmpdir(), \"norns-worker-state\");\n const safe = workerId.replace(/[^A-Za-z0-9_.-]/g, \"_\").slice(0, 120);\n return join(root, `${safe}.completed.json`);\n}\n","/**\n * The provider-neutral wire format Norns speaks, and its translation to and\n * from the AI SDK. Also the prose the worker writes for the model: Norns\n * never does (\"Content is opaque\"), so composing the system prompt,\n * rendering kinded messages, eliding old tool results, and choosing the\n * run's final output all happen here.\n */\nimport {\n tool as aiTool,\n type FinishReason,\n type JSONSchema7,\n jsonSchema,\n type LanguageModelUsage,\n type ModelMessage,\n type SystemModelMessage,\n type ToolSet,\n} from \"ai\";\n\n// --- Wire types ---\n\nexport interface NeutralToolCall {\n id: string;\n name: string;\n arguments: unknown;\n}\n\nexport interface NeutralMessage {\n role: \"user\" | \"assistant\" | \"tool\" | \"system\";\n content?: unknown;\n tool_calls?: NeutralToolCall[];\n tool_call_id?: string;\n name?: string;\n is_error?: boolean;\n /** Set on messages Norns resolved itself; the worker renders them. */\n kind?: string;\n data?: Record<string, unknown>;\n}\n\nexport interface NeutralTool {\n name: string;\n description?: string;\n parameters?: JSONSchema7;\n input_schema?: JSONSchema7;\n}\n\nexport interface LlmTask {\n task_id: string;\n purpose?: \"compact\";\n model?: string;\n system_prompt?: string | null;\n summary?: string | null;\n date?: string | null;\n messages?: NeutralMessage[];\n /** In place of `messages` once this worker holds the run's history (see HistoryCache). */\n messages_delta?: { base_count: number; drop: number; append: NeutralMessage[] };\n tools?: NeutralTool[];\n context_policy?: unknown;\n max_tokens?: number | null;\n agent_id?: number;\n run_id?: number;\n step?: number;\n}\n\nexport interface ToolTask {\n task_id: string;\n tool_name: string;\n input?: Record<string, unknown>;\n agent_id?: number;\n run_id?: number;\n idempotency_key?: string;\n}\n\nexport interface Usage {\n input_tokens: number;\n output_tokens: number;\n cache_read_tokens?: number;\n cache_write_tokens?: number;\n}\n\nexport type NeutralFinishReason = \"stop\" | \"tool_call\" | \"length\" | \"error\";\n\nexport type LlmResult =\n | {\n status: \"ok\";\n content: string;\n finish_reason: NeutralFinishReason;\n usage: Usage;\n tool_calls?: NeutralToolCall[];\n model?: string;\n final_output?: string;\n }\n | { status: \"error\"; error: string };\n\nexport type ToolResult =\n | { status: \"ok\"; result: string; duplicate?: true }\n | { status: \"error\"; error: string };\n\n// --- Prompt composition ---\n\n/**\n * The prompt the model sees: the def's prompt verbatim, then the\n * conversation summary and the date the orchestrator put in the envelope.\n */\nexport function composeSystemPrompt(task: LlmTask): string {\n let prompt = task.system_prompt ?? \"\";\n if (typeof task.summary === \"string\" && task.summary !== \"\") {\n prompt += `\\n\\nSummary of earlier conversation: ${task.summary}`;\n }\n if (task.date) prompt += `\\n\\nCurrent date: ${task.date}.`;\n return prompt;\n}\n\n/** The def's prompt (so the summary is written in the agent's voice) plus the earlier summary. */\nexport function composeCompactionPrompt(task: LlmTask): string {\n let prompt = task.system_prompt ?? \"\";\n if (typeof task.summary === \"string\" && task.summary !== \"\") {\n prompt += `\\n\\nSummary of earlier conversation: ${task.summary}`;\n }\n return prompt;\n}\n\nexport const COMPACTION_INSTRUCTION =\n \"Write a summary of the conversation so far for your own future reference. \" +\n \"You will continue the same task with only this summary and the most recent \" +\n \"messages, so keep every fact you would need: the task and its constraints, \" +\n \"decisions made and why, files and identifiers touched, what was tried and \" +\n \"failed, what remains to be done, and anything the user asked for that is not \" +\n \"finished. Fold in the earlier summary if there is one. Write prose or terse \" +\n \"notes, no preamble, no commentary about summarising.\";\n\n/** The folded history, rendered, then the instruction. */\nexport function compactionMessages(task: LlmTask): NeutralMessage[] {\n return [\n ...renderMessages(task.messages ?? []),\n { role: \"user\", content: COMPACTION_INSTRUCTION },\n ];\n}\n\n// --- Kinded messages ---\n\n/** Render a message Norns resolved itself to plain content. Others pass through. */\nexport function renderMessage(msg: NeutralMessage): NeutralMessage {\n if (!msg.kind) return msg;\n const { kind, data, ...rest } = msg;\n return { ...rest, content: renderKind(kind, data ?? {}, msg.content) };\n}\n\nexport function renderMessages(messages: NeutralMessage[]): NeutralMessage[] {\n return messages.map(renderMessage);\n}\n\nfunction renderKind(kind: string, data: Record<string, unknown>, content: unknown): string {\n switch (kind) {\n case \"inherited_context\":\n return `[Inherited context from parent agent]\\n${encode(content)}`;\n case \"timer_completed\":\n return \"Timer completed.\";\n case \"tool_denied\":\n return `Tool '${data.tool_name}' is not in this agent's allowed tools.`;\n case \"subagent_denied\":\n if (data.reason === \"disabled\") return \"This agent is not permitted to launch sub-agents.\";\n if (data.reason === \"max_depth\") {\n return (\n `Sub-agent nesting limit reached (max depth ${data.max_depth}). ` +\n \"Do the work in this agent instead of delegating further.\"\n );\n }\n return `Agent '${data.agent_name}' is not in this agent's allowed sub-agents.`;\n case \"subagent_list_denied\":\n return \"Listing agents is not permitted for this agent.\";\n case \"subagent_not_found\":\n return `Agent '${data.agent_name}' not found`;\n case \"subagent_self\":\n return \"Cannot launch self as a sub-agent\";\n case \"subagent_missing\":\n return `Sub-agent run ${data.run_id} no longer exists, so its result cannot be recovered.`;\n case \"subagent_busy\":\n return (\n `Agent '${data.agent_name}' is still working on an earlier task for this ` +\n \"conversation. Wait for its result before giving it another.\"\n );\n case \"subagent_launch_failed\":\n return `Failed to launch agent '${data.agent_name}': ${data.reason}`;\n case \"subagent_completed\":\n return JSON.stringify({ run_id: data.run_id, status: \"completed\", output: content ?? \"\" });\n case \"subagent_failed\":\n return JSON.stringify({ run_id: data.run_id, status: \"failed\", error: content ?? \"\" });\n case \"list_agents\":\n return JSON.stringify(data.agents ?? []);\n default:\n return content === undefined || content === null || content === \"\"\n ? encode(data)\n : encode(content);\n }\n}\n\nfunction encode(value: unknown): string {\n return typeof value === \"string\" ? value : JSON.stringify(value ?? null);\n}\n\n// --- Context cost ---\n\n/** Chars kept of a tool result once it has aged out of the last two messages. */\nexport const TOOL_RESULT_CAP = 200;\n\n/** Rendered messages, elided unless Norns manages the context itself. */\nexport function messagesForTask(task: LlmTask): NeutralMessage[] {\n const rendered = renderMessages(task.messages ?? []);\n return task.context_policy ? rendered : elideOldToolResults(rendered);\n}\n\n/** Cap tool results older than the last two messages. */\nexport function elideOldToolResults(messages: NeutralMessage[]): NeutralMessage[] {\n if (messages.length <= 4) return messages;\n const old = messages.slice(0, -2);\n const recent = messages.slice(-2);\n return [\n ...old.map((msg) =>\n msg.role === \"tool\" && typeof msg.content === \"string\" && msg.content.length > TOOL_RESULT_CAP\n ? { ...msg, content: `${msg.content.slice(0, TOOL_RESULT_CAP)}...(truncated)` }\n : msg,\n ),\n ...recent,\n ];\n}\n\n/** One response's ceiling when the agent does not set one. */\nexport const DEFAULT_MAX_TOKENS = 8192;\n\nexport function maxTokens(task: LlmTask): number {\n const v = task.max_tokens;\n return typeof v === \"number\" && Number.isInteger(v) && v > 0 ? v : DEFAULT_MAX_TOKENS;\n}\n\n/**\n * The run's output when the model stops. A turn can say something\n * substantive alongside a tool call and then end with an empty \"stop\" turn;\n * fall back to the last non-empty assistant text rather than losing it.\n */\nexport function finalOutput(messages: NeutralMessage[], content: unknown): string {\n const text = typeof content === \"string\" ? content : \"\";\n if (text.trim() !== \"\") return text;\n for (let i = messages.length - 1; i >= 0; i--) {\n const m = messages[i];\n if (m?.role === \"assistant\" && typeof m.content === \"string\" && m.content.trim() !== \"\") {\n return m.content;\n }\n }\n return text;\n}\n\n// --- Neutral → AI SDK ---\n\nconst CACHE_CONTROL = { anthropic: { cacheControl: { type: \"ephemeral\" } } } as const;\n\n/**\n * The system prompt as the call's instructions, with a cache breakpoint:\n * a run's prompt is the same on every step. Providers that do not take the\n * hint ignore it.\n */\nexport function toInstructions(system: string): SystemModelMessage | undefined {\n if (system === \"\") return undefined;\n return { role: \"system\", content: system, providerOptions: CACHE_CONTROL };\n}\n\n/**\n * The model messages for a call. Consecutive tool results are folded into\n * one tool message, as providers expect them.\n *\n * The newest message carries a cache breakpoint: a run's history only\n * grows between steps, so this call's tail is the next call's prefix and is\n * read back at the cached rate.\n */\nexport function toModelMessages(messages: NeutralMessage[]): ModelMessage[] {\n const out: ModelMessage[] = [];\n\n for (const msg of messages) {\n const converted = toModelMessage(msg);\n const last = out[out.length - 1];\n if (converted.role === \"tool\" && last?.role === \"tool\") {\n last.content = [...last.content, ...converted.content];\n } else {\n out.push(converted);\n }\n }\n\n const last = out[out.length - 1];\n if (last) last.providerOptions = CACHE_CONTROL;\n return out;\n}\n\nfunction toModelMessage(msg: NeutralMessage): ModelMessage {\n switch (msg.role) {\n case \"system\":\n return { role: \"system\", content: encode(msg.content ?? \"\") };\n case \"assistant\": {\n const text = typeof msg.content === \"string\" ? msg.content : encode(msg.content ?? \"\");\n const calls = msg.tool_calls ?? [];\n if (calls.length === 0) return { role: \"assistant\", content: text };\n return {\n role: \"assistant\",\n content: [\n ...(text !== \"\" ? [{ type: \"text\" as const, text }] : []),\n ...calls.map((tc) => ({\n type: \"tool-call\" as const,\n toolCallId: tc.id,\n toolName: tc.name,\n input: parseArguments(tc.arguments),\n })),\n ],\n };\n }\n case \"tool\": {\n const value = encode(msg.content ?? \"\");\n return {\n role: \"tool\",\n content: [\n {\n type: \"tool-result\",\n toolCallId: msg.tool_call_id ?? \"\",\n toolName: msg.name ?? \"\",\n output: msg.is_error ? { type: \"error-text\", value } : { type: \"text\", value },\n },\n ],\n };\n }\n default:\n // An opaque block this worker holds no key for, or structured content:\n // send it encoded rather than fail the call.\n return { role: \"user\", content: encode(msg.content ?? \"\") };\n }\n}\n\nfunction parseArguments(args: unknown): unknown {\n if (typeof args !== \"string\") return args ?? {};\n try {\n return JSON.parse(args);\n } catch {\n return { raw: args };\n }\n}\n\n/** The tools the model is offered. None has an `execute`: the worker runs them on dispatch. */\nexport function toToolSet(tools: NeutralTool[]): ToolSet {\n const set: ToolSet = {};\n for (const t of tools) {\n set[t.name] = aiTool({\n description: t.description ?? \"\",\n inputSchema: jsonSchema(t.parameters ?? t.input_schema ?? { type: \"object\", properties: {} }),\n });\n }\n return set;\n}\n\n// --- AI SDK → Neutral ---\n\n/** The slice of a `generateText` result this translation reads. */\nexport interface GenerateLike {\n text: string;\n toolCalls: ReadonlyArray<{ toolCallId: string; toolName: string; input: unknown }>;\n finishReason: FinishReason;\n usage: LanguageModelUsage;\n response: { modelId: string };\n}\n\nexport function fromGenerateResult(result: GenerateLike): Extract<LlmResult, { status: \"ok\" }> {\n const out: Extract<LlmResult, { status: \"ok\" }> = {\n status: \"ok\",\n content: result.text ?? \"\",\n finish_reason: neutralFinishReason(result.finishReason, result.toolCalls.length > 0),\n usage: neutralUsage(result.usage),\n };\n // The model that served the call, so Norns can price it from the event.\n if (result.response?.modelId) out.model = result.response.modelId;\n if (result.toolCalls.length > 0) {\n out.tool_calls = result.toolCalls.map((tc) => ({\n id: tc.toolCallId,\n name: tc.toolName,\n arguments: tc.input ?? {},\n }));\n }\n return out;\n}\n\nfunction neutralFinishReason(reason: FinishReason, hasToolCalls: boolean): NeutralFinishReason {\n if (hasToolCalls) return \"tool_call\";\n switch (reason) {\n case \"tool-calls\":\n return \"tool_call\";\n case \"length\":\n return \"length\";\n case \"error\":\n return \"error\";\n default:\n return \"stop\";\n }\n}\n\n/**\n * Norns counts cache reads and writes inside `input_tokens` and wants to know\n * how many of each, since providers price them differently.\n */\nfunction neutralUsage(usage: LanguageModelUsage | undefined): Usage {\n const details = usage?.inputTokenDetails;\n const read = details?.cacheReadTokens ?? 0;\n const write = details?.cacheWriteTokens ?? 0;\n const total = usage?.inputTokens ?? 0;\n const noCache = details?.noCacheTokens;\n const input = noCache !== undefined ? Math.max(total, noCache + read + write) : total;\n\n const out: Usage = { input_tokens: input, output_tokens: usage?.outputTokens ?? 0 };\n if (read > 0) out.cache_read_tokens = read;\n if (write > 0) out.cache_write_tokens = write;\n return out;\n}\n","import type { LlmTask, NeutralMessage } from \"./format.js\";\n\n/**\n * The message list Norns last sent this worker, per run.\n *\n * Once a worker joins with `features: [\"message_cache\"]`, Norns sends a run's\n * later steps as the change since the last task on this connection:\n * `messages_delta: { base_count, drop, append }` — of the `base_count`\n * messages held, drop the first `drop`, append the rest. A delta against a\n * base this worker does not hold is a miss: the worker answers\n * `message_cache_miss` and Norns resends the whole list at the same step.\n * Bounded by run count; the run used longest ago goes first.\n */\nexport class HistoryCache {\n readonly #runs = new Map<number | string, NeutralMessage[]>();\n readonly #maxRuns: number;\n\n constructor(maxRuns = 256) {\n this.#maxRuns = maxRuns;\n }\n\n /** The task with `messages` filled in, or `undefined` on a miss. */\n resolve(task: LlmTask): LlmTask | undefined {\n // A prefix to summarise, not the history; leaves the cache alone.\n if (task.purpose === \"compact\") return task;\n\n const runId = task.run_id;\n const delta = task.messages_delta;\n\n if (delta === undefined) {\n if (runId !== undefined && Array.isArray(task.messages)) this.#remember(runId, task.messages);\n return task;\n }\n\n const previous = runId === undefined ? undefined : this.#runs.get(runId);\n if (runId === undefined || previous === undefined || previous.length !== delta.base_count) {\n return undefined;\n }\n\n const messages = [...previous.slice(delta.drop), ...delta.append];\n this.#remember(runId, messages);\n const resolved: LlmTask = { ...task, messages };\n delete resolved.messages_delta;\n return resolved;\n }\n\n /** Forget everything: a new connection gets the full history anyway. */\n clear(): void {\n this.#runs.clear();\n }\n\n /** How many runs are held; for tests. */\n get size(): number {\n return this.#runs.size;\n }\n\n #remember(runId: number | string, messages: NeutralMessage[]): void {\n this.#runs.delete(runId);\n this.#runs.set(runId, messages);\n while (this.#runs.size > this.#maxRuns) {\n const oldest = this.#runs.keys().next().value;\n if (oldest === undefined) break;\n this.#runs.delete(oldest);\n }\n }\n}\n"],"mappings":"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","names":["jsonSchema","res","Socket","jsonSchema","last","Socket","result","out","tool"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/agent.ts","../src/client.ts","../src/async-queue.ts","../src/errors.ts","../src/types.ts","../src/logger.ts","../src/models.ts","../src/tool.ts","../src/worker.ts","../src/completed-calls.ts","../src/format.ts","../src/history-cache.ts"],"sourcesContent":["export { jsonSchema } from \"ai\";\nexport {\n type AgentDefinition,\n type AgentMode,\n type AgentOptions,\n type CheckpointPolicy,\n type ContextPolicy,\n type ContextStrategy,\n DEFAULT_MODEL,\n defineAgent,\n type OnFailure,\n type SubagentConversation,\n type SubagentPolicy,\n} from \"./agent.js\";\nexport {\n type AgentRef,\n isScopedKey,\n type ListRunsOptions,\n NornsClient,\n type NornsClientOptions,\n type SendMessageOptions,\n type StreamOptions,\n type WebSocketConstructor,\n} from \"./client.js\";\nexport {\n GardDestroyedError,\n JoinError,\n KeyRevokedError,\n NornsApiError,\n NornsError,\n NornsTimeoutError,\n NotFoundError,\n StreamClosedError,\n} from \"./errors.js\";\nexport type {\n LlmResult,\n LlmTask,\n NeutralMessage,\n NeutralToolCall,\n ToolResult,\n ToolTask,\n} from \"./format.js\";\nexport { consoleLogger, type Logger, silentLogger } from \"./logger.js\";\nexport {\n inferProvider,\n type ModelResolver,\n type ModelSource,\n type ModelsOption,\n} from \"./models.js\";\nexport {\n type InferToolInput,\n type ToolContext,\n type ToolDefinition,\n type ToolInputSchema,\n type ToolOptions,\n tool,\n} from \"./tool.js\";\nexport type {\n AgentInfo,\n Conversation,\n MessageResult,\n Run,\n RunEvent,\n RunStatus,\n StreamEvent,\n WaitingFor,\n} from \"./types.js\";\nexport {\n type Capability,\n NornsWorker,\n type NornsWorkerOptions,\n type RegisteredPort,\n type RegisterPortOptions,\n} from \"./worker.js\";\n","import type { ToolDefinition } from \"./tool.js\";\n\n/** @deprecated Norns never read it; a conversation starts from a `conversationKey` on the message. */\nexport type AgentMode = \"task\" | \"conversation\";\nexport type CheckpointPolicy = \"every_step\" | \"on_tool_call\" | \"manual\";\nexport type ContextStrategy = \"sliding_window\" | \"none\";\nexport type OnFailure = \"stop\" | \"retry_last_step\";\nexport type SubagentConversation = \"per_launch\" | \"per_parent\";\n\n/** Fold older history into a summary once a response reports `compactAt` input tokens. */\nexport interface ContextPolicy {\n compactAt: number;\n /** Messages kept verbatim after the fold. */\n keep: number;\n}\n\n/** What this agent may do with `launch_agent` and `list_agents`. */\nexport interface SubagentPolicy {\n mode?: \"open\" | \"allowlist\" | \"disabled\";\n allowedAgents?: string[];\n allowListAgents?: boolean;\n maxDepth?: number;\n}\n\nexport interface AgentOptions {\n name: string;\n /** Shown to other agents by `list_agents`. */\n purpose?: string;\n /**\n * The model name as the provider knows it, e.g. `\"claude-sonnet-5\"`,\n * `\"gpt-4o\"`. Prefix it (`\"openai/gpt-4o\"`) to pin the provider.\n */\n model?: string;\n systemPrompt?: string;\n /** What this worker serves for the agent (see `allowedTools` for what it is offered). */\n tools?: ToolDefinition[];\n /** @deprecated Ignored. Norns never read it; send a message with a `conversationKey` instead. */\n mode?: AgentMode;\n checkpointPolicy?: CheckpointPolicy;\n contextStrategy?: ContextStrategy;\n contextWindow?: number;\n maxSteps?: number;\n onFailure?: OnFailure;\n /** Pair with `contextStrategy: \"none\"`; the summarisation is served by this worker. */\n contextPolicy?: ContextPolicy;\n /**\n * The ceiling on one response, not on the history. Unset leaves it to the\n * worker (8192). Raise it for an agent whose turns are long.\n */\n maxTokens?: number;\n /**\n * Names from `tools` this agent is offered. Unset offers every tool\n * registered in the tenant, other agents' included. Built-ins (`ask_human`,\n * `wait`, `launch_agent`, `list_agents`) are never filtered.\n */\n allowedTools?: string[];\n subagents?: SubagentPolicy;\n /** When launched by another agent: a fresh conversation per launch, or one per parent. */\n subagentConversation?: SubagentConversation;\n}\n\n/** A complete agent definition: `defineAgent()`'s result. */\nexport interface AgentDefinition {\n readonly name: string;\n readonly purpose: string | undefined;\n readonly model: string;\n readonly systemPrompt: string;\n readonly tools: readonly ToolDefinition[];\n readonly checkpointPolicy: CheckpointPolicy;\n readonly contextStrategy: ContextStrategy;\n readonly contextWindow: number;\n readonly maxSteps: number;\n readonly onFailure: OnFailure;\n readonly contextPolicy: ContextPolicy | undefined;\n readonly maxTokens: number | undefined;\n readonly allowedTools: readonly string[] | undefined;\n readonly subagents: SubagentPolicy | undefined;\n readonly subagentConversation: SubagentConversation | undefined;\n}\n\nexport const DEFAULT_MODEL = \"claude-sonnet-5\";\n\nconst SUBAGENT_CONVERSATIONS: readonly string[] = [\"per_launch\", \"per_parent\"];\n\n/**\n * Define an agent. Defaults are filled in and the combination is checked\n * here, so a mistake fails where it was written rather than on the server.\n */\nexport function defineAgent(options: AgentOptions): AgentDefinition {\n const name = options.name?.trim();\n if (!name) throw new Error(\"defineAgent(): name is required\");\n\n const tools = options.tools ?? [];\n const known = new Set(tools.map((t) => t.name));\n if (known.size !== tools.length) {\n throw new Error(`Agent '${name}': tool names must be unique`);\n }\n\n if (options.allowedTools) {\n const unknown = options.allowedTools.filter((n) => !known.has(n));\n if (unknown.length > 0) {\n throw new Error(\n `Agent '${name}': allowedTools names ${JSON.stringify(unknown)} are not in its tools ` +\n `(${JSON.stringify([...known].sort())}); built-ins are always available and need no entry`,\n );\n }\n }\n\n if (\n options.subagentConversation !== undefined &&\n !SUBAGENT_CONVERSATIONS.includes(options.subagentConversation)\n ) {\n throw new Error(\n `Agent '${name}': subagentConversation must be one of ${SUBAGENT_CONVERSATIONS.join(\", \")}`,\n );\n }\n\n if (\n options.maxTokens !== undefined &&\n !(Number.isInteger(options.maxTokens) && options.maxTokens > 0)\n ) {\n throw new Error(`Agent '${name}': maxTokens must be a positive integer`);\n }\n\n return Object.freeze({\n name,\n purpose: options.purpose,\n model: options.model ?? DEFAULT_MODEL,\n systemPrompt: options.systemPrompt ?? \"\",\n tools: Object.freeze([...tools]),\n checkpointPolicy: options.checkpointPolicy ?? \"on_tool_call\",\n contextStrategy: options.contextStrategy ?? \"sliding_window\",\n contextWindow: options.contextWindow ?? 20,\n maxSteps: options.maxSteps ?? 50,\n onFailure: options.onFailure ?? \"retry_last_step\",\n contextPolicy: options.contextPolicy,\n maxTokens: options.maxTokens,\n allowedTools: options.allowedTools ? Object.freeze([...options.allowedTools]) : undefined,\n subagents: options.subagents,\n subagentConversation: options.subagentConversation,\n });\n}\n\n/**\n * The REST body that creates or updates the agent. Policies go only when\n * set: the update replaces `model_config` whole, so dropping one from the\n * definition drops it on the server too.\n */\nexport function agentBody(agent: AgentDefinition): Record<string, unknown> {\n const modelConfig: Record<string, unknown> = {\n checkpoint_policy: agent.checkpointPolicy,\n context_strategy: agent.contextStrategy,\n context_window: agent.contextWindow,\n on_failure: agent.onFailure,\n context_policy: agent.contextPolicy\n ? { compact_at: agent.contextPolicy.compactAt, keep: agent.contextPolicy.keep }\n : null,\n max_tokens: agent.maxTokens ?? null,\n };\n if (agent.allowedTools) {\n modelConfig.tools = { mode: \"allowlist\", allowed_tools: [...agent.allowedTools] };\n }\n if (agent.subagents) {\n const s = agent.subagents;\n const policy: Record<string, unknown> = {};\n if (s.mode !== undefined) policy.mode = s.mode;\n if (s.allowedAgents !== undefined) policy.allowed_agents = [...s.allowedAgents];\n if (s.allowListAgents !== undefined) policy.allow_list_agents = s.allowListAgents;\n if (s.maxDepth !== undefined) policy.max_depth = s.maxDepth;\n modelConfig.subagents = policy;\n }\n if (agent.subagentConversation) {\n modelConfig.subagent_conversation = agent.subagentConversation;\n }\n\n const body: Record<string, unknown> = {\n name: agent.name,\n system_prompt: agent.systemPrompt,\n status: \"idle\",\n model: agent.model,\n max_steps: agent.maxSteps,\n model_config: modelConfig,\n };\n if (agent.purpose !== undefined) body.purpose = agent.purpose;\n return body;\n}\n\n/**\n * One agent or several, as a list. Names must be unique: the second would\n * overwrite the first on the server.\n */\nexport function agentList(agents: AgentDefinition | AgentDefinition[]): AgentDefinition[] {\n const items = Array.isArray(agents) ? [...agents] : [agents];\n if (items.length === 0) throw new Error(\"A worker needs at least one agent\");\n const seen = new Set<string>();\n const dupes = new Set<string>();\n for (const a of items) {\n if (seen.has(a.name)) dupes.add(a.name);\n seen.add(a.name);\n }\n if (dupes.size > 0) {\n throw new Error(\n `Agent names must be unique on one worker: ${JSON.stringify([...dupes].sort())}`,\n );\n }\n return items;\n}\n\n/**\n * Every agent's tools, one per name. A tool task names only the tool, so\n * two different tools under one name cannot both be served.\n */\nexport function toolsByName(agents: AgentDefinition[]): Map<string, ToolDefinition> {\n const tools = new Map<string, ToolDefinition>();\n const owners = new Map<string, string>();\n for (const agent of agents) {\n for (const t of agent.tools) {\n const existing = tools.get(t.name);\n if (existing === undefined) {\n tools.set(t.name, t);\n owners.set(t.name, agent.name);\n } else if (existing !== t) {\n throw new Error(\n `Agents '${owners.get(t.name)}' and '${agent.name}' have different tools named ` +\n `'${t.name}'; tools are dispatched by name, so share one definition or rename one`,\n );\n }\n }\n }\n return tools;\n}\n","import { Socket, type SocketConnectOption } from \"phoenix\";\nimport { type AgentDefinition, agentBody } from \"./agent.js\";\nimport { AsyncQueue } from \"./async-queue.js\";\nimport {\n NornsApiError,\n NornsError,\n NornsTimeoutError,\n NotFoundError,\n StreamClosedError,\n} from \"./errors.js\";\nimport {\n type AgentInfo,\n type Conversation,\n type MessageResult,\n type Run,\n type RunEvent,\n type RunStatus,\n type StreamEvent,\n TERMINAL_EVENTS,\n type WaitingFor,\n} from \"./types.js\";\n\n/** A class that behaves like the browser `WebSocket`; the global one by default. */\nexport type WebSocketConstructor = new (url: string, protocols?: string | string[]) => object;\n\nexport interface NornsClientOptions {\n /** The Norns base URL. Defaults to `NORNS_URL`. */\n url?: string;\n /** The tenant's bearer token. Defaults to `NORNS_API_KEY`. */\n apiKey?: string;\n /** Replace the global `fetch`, for tests or custom transport. */\n fetch?: typeof globalThis.fetch;\n /** Replace the global `WebSocket` for streams. */\n transport?: WebSocketConstructor;\n /** Extra options for the Phoenix socket that streams use. */\n socketOptions?: Partial<SocketConnectOption>;\n}\n\n/** An agent's id, or its name. */\nexport type AgentRef = number | string;\n\nexport interface SendMessageOptions {\n /** Key for multi-turn conversations, e.g. a Slack user id. */\n conversationKey?: string;\n /** Opaque context stored on the run. */\n context?: Record<string, unknown>;\n /** Pin the run to a gard. */\n gardId?: number;\n /**\n * Poll until the run completes, fails, or parks on a question. A parked\n * agent is waiting on you, so the wait ends there too.\n */\n wait?: boolean;\n /** How long to wait, with `wait`. Default 30 seconds. */\n timeoutMs?: number;\n signal?: AbortSignal;\n}\n\nexport interface StreamOptions {\n conversationKey?: string;\n context?: Record<string, unknown>;\n gardId?: number;\n /** Give up if no event arrives for this long. Default 2 minutes. */\n idleTimeoutMs?: number;\n signal?: AbortSignal;\n}\n\nexport interface ListRunsOptions {\n /** How many the server returns, most recent first. Default 50. */\n limit?: number;\n status?: RunStatus;\n agentId?: number;\n}\n\nconst WAIT_STOPS: ReadonlySet<string> = new Set([\"completed\", \"failed\", \"error\", \"waiting\"]);\n\n/**\n * Talks to Norns from application code: sends messages, reads runs, streams\n * events. For serving an agent, see `NornsWorker`.\n *\n * const client = new NornsClient({ url, apiKey });\n * const result = await client.sendMessage(\"support-bot\", \"Where's my order?\", { wait: true });\n */\nexport class NornsClient {\n readonly url: string;\n readonly #apiKey: string;\n readonly #fetch: typeof globalThis.fetch;\n readonly #transport: WebSocketConstructor | undefined;\n readonly #socketOptions: Partial<SocketConnectOption>;\n\n constructor(options: NornsClientOptions = {}) {\n this.url = resolveUrl(options.url);\n this.#apiKey = resolveApiKey(options.apiKey);\n this.#fetch = options.fetch ?? globalThis.fetch;\n this.#transport = options.transport;\n this.#socketOptions = options.socketOptions ?? {};\n }\n\n // --- Agents ---\n\n readonly agents = {\n list: async (): Promise<AgentInfo[]> => {\n const res = await this.#request<{ data: Record<string, unknown>[] }>(\"GET\", \"/api/v1/agents\");\n return res.data.map(parseAgent);\n },\n\n /** By id, or by name. */\n get: async (agent: AgentRef): Promise<AgentInfo> => {\n if (typeof agent === \"number\") {\n const res = await this.#request<{ data: Record<string, unknown> }>(\n \"GET\",\n `/api/v1/agents/${agent}`,\n );\n return parseAgent(res.data);\n }\n const found = (await this.agents.list()).find((a) => a.name === agent);\n if (!found) throw new NotFoundError(`Agent '${agent}'`);\n return found;\n },\n\n /**\n * Create the agent, or update it to match the definition if it exists,\n * so code changes are always picked up. The worker does this on start.\n */\n ensure: async (definition: AgentDefinition): Promise<AgentInfo> => {\n const body = agentBody(definition);\n const existing = (await this.agents.list()).find((a) => a.name === definition.name);\n if (existing) {\n const res = await this.#request<{ data: Record<string, unknown> }>(\n \"PUT\",\n `/api/v1/agents/${existing.id}`,\n { body },\n );\n return parseAgent(res.data);\n }\n const res = await this.#request<{ data: Record<string, unknown> }>(\"POST\", \"/api/v1/agents\", {\n body,\n });\n return parseAgent(res.data);\n },\n };\n\n // --- Messages ---\n\n /**\n * Send a message to an agent. Returns at once with the run id, or, with\n * `wait`, once the run completes, fails, or parks on a question.\n */\n async sendMessage(\n agent: AgentRef,\n content: string,\n options: SendMessageOptions = {},\n ): Promise<MessageResult> {\n const agentId = await this.#resolveAgentId(agent);\n const runId = await this.#post(agentId, content, options);\n\n if (!options.wait) {\n return {\n runId,\n status: \"accepted\",\n output: null,\n conversationKey: options.conversationKey,\n isWaiting: false,\n waitingFor: null,\n };\n }\n\n const run = await this.#waitForRun(runId, options.timeoutMs ?? 30_000, options.signal);\n return {\n runId,\n status: run.status,\n output: run.output,\n conversationKey: options.conversationKey,\n isWaiting: run.status === \"waiting\",\n waitingFor: run.waitingFor,\n };\n }\n\n /**\n * Send a message and iterate the run's events as they happen, until it\n * completes or errors.\n *\n * for await (const event of client.stream(\"researcher\", \"Summarise this\")) {\n * if (event.type === \"completed\") console.log(event.data.output);\n * }\n */\n async *stream(\n agent: AgentRef,\n content: string,\n options: StreamOptions = {},\n ): AsyncGenerator<StreamEvent, void, undefined> {\n const agentId = await this.#resolveAgentId(agent);\n const runId = await this.#post(agentId, content, options);\n yield* this.#watch(agentId, runId, options);\n }\n\n // --- Runs ---\n\n readonly runs = {\n get: async (runId: number): Promise<Run> => {\n const res = await this.#request<{ data: Record<string, unknown> }>(\n \"GET\",\n `/api/v1/runs/${runId}`,\n );\n return parseRun(res.data);\n },\n\n /**\n * The tenant's runs, most recent first. Use it to find runs nobody holds\n * a handle to, above all the ones parked on an `ask_human` question:\n *\n * for (const run of await client.runs.list({ status: \"waiting\" })) {\n * console.log(run.id, run.waitingFor?.question);\n * }\n *\n * `status` and `agentId` filter the page the server returned, so a\n * narrow filter over a busy tenant may need a larger `limit`.\n */\n list: async (options: ListRunsOptions = {}): Promise<Run[]> => {\n const res = await this.#request<{ data: Record<string, unknown>[] }>(\"GET\", \"/api/v1/runs\", {\n query: { limit: options.limit ?? 50 },\n });\n let runs = res.data.map(parseRun);\n if (options.status) runs = runs.filter((r) => r.status === options.status);\n if (options.agentId !== undefined) runs = runs.filter((r) => r.agentId === options.agentId);\n return runs;\n },\n\n events: async (runId: number): Promise<RunEvent[]> => {\n const res = await this.#request<{ data: Record<string, unknown>[] }>(\n \"GET\",\n `/api/v1/runs/${runId}/events`,\n );\n return res.data.map(parseEvent);\n },\n\n /**\n * Answer a run parked on an `ask_human` question. Sending the agent a\n * normal message does the same and is usually what a chat client wants;\n * this targets one specific run.\n */\n reply: async (runId: number, answer: string): Promise<void> => {\n await this.#request(\"POST\", `/api/v1/runs/${runId}/reply`, { body: { answer } });\n },\n\n /** Re-run a finished or failed run's message. Returns the new run id. */\n retry: async (runId: number): Promise<number> => {\n const res = await this.#request<{ run_id: number }>(\"POST\", `/api/v1/runs/${runId}/retry`);\n return res.run_id;\n },\n\n /** Iterate an existing run's events as they happen, until it finishes. */\n watch: (\n runId: number,\n options: Pick<StreamOptions, \"idleTimeoutMs\" | \"signal\"> = {},\n ): AsyncGenerator<StreamEvent, void, undefined> => {\n const self = this;\n return (async function* () {\n const run = await self.runs.get(runId);\n yield* self.#watch(run.agentId, runId, options);\n })();\n },\n };\n\n // --- Conversations ---\n\n readonly conversations = {\n list: async (agent: AgentRef): Promise<Conversation[]> => {\n const agentId = await this.#resolveAgentId(agent);\n const res = await this.#request<{ data: Record<string, unknown>[] }>(\n \"GET\",\n `/api/v1/agents/${agentId}/conversations`,\n );\n return res.data.map(parseConversation);\n },\n\n get: async (agent: AgentRef, key: string): Promise<Conversation> => {\n const agentId = await this.#resolveAgentId(agent);\n const res = await this.#request<{ data: Record<string, unknown> }>(\n \"GET\",\n `/api/v1/agents/${agentId}/conversations/${encodeURIComponent(key)}`,\n );\n return parseConversation(res.data);\n },\n\n /** Reset a conversation: its history is gone, the next message starts fresh. */\n delete: async (agent: AgentRef, key: string): Promise<void> => {\n const agentId = await this.#resolveAgentId(agent);\n await this.#request(\n \"DELETE\",\n `/api/v1/agents/${agentId}/conversations/${encodeURIComponent(key)}`,\n );\n },\n };\n\n // --- Internals ---\n\n async #resolveAgentId(agent: AgentRef): Promise<number> {\n return typeof agent === \"number\" ? agent : (await this.agents.get(agent)).id;\n }\n\n async #post(\n agentId: number,\n content: string,\n options: {\n conversationKey?: string;\n context?: Record<string, unknown>;\n gardId?: number;\n signal?: AbortSignal;\n },\n ): Promise<number> {\n const body: Record<string, unknown> = { content };\n if (options.conversationKey !== undefined) body.conversation_key = options.conversationKey;\n if (options.context !== undefined) body.context = options.context;\n if (options.gardId !== undefined) body.gard_id = options.gardId;\n const res = await this.#request<{ run_id: number }>(\n \"POST\",\n `/api/v1/agents/${agentId}/messages`,\n {\n body,\n signal: options.signal,\n },\n );\n return res.run_id;\n }\n\n // Poll until the run stops progressing. \"waiting\" is not terminal, but\n // the agent is parked on a question and will not move until someone\n // answers, so it ends the wait too.\n async #waitForRun(runId: number, timeoutMs: number, signal?: AbortSignal): Promise<Run> {\n const deadline = Date.now() + timeoutMs;\n let interval = 500;\n while (Date.now() < deadline) {\n const run = await this.runs.get(runId);\n if (WAIT_STOPS.has(run.status)) return run;\n await sleep(Math.min(interval, Math.max(deadline - Date.now(), 0)), signal);\n interval = Math.min(interval * 1.5, 3000);\n }\n throw new NornsTimeoutError(`Run ${runId} did not complete within ${timeoutMs}ms`);\n }\n\n async *#watch(\n agentId: number,\n runId: number,\n options: Pick<StreamOptions, \"idleTimeoutMs\" | \"signal\">,\n ): AsyncGenerator<StreamEvent, void, undefined> {\n const idle = options.idleTimeoutMs ?? 120_000;\n const queue = new AsyncQueue<StreamEvent>();\n const socket = new Socket(`${wsBase(this.url)}/socket`, {\n params: { token: this.#apiKey },\n ...(this.#transport\n ? { transport: this.#transport as SocketConnectOption[\"transport\"] }\n : {}),\n ...this.#socketOptions,\n });\n\n let timer: ReturnType<typeof setTimeout> | undefined;\n const touch = () => {\n if (timer) clearTimeout(timer);\n timer = setTimeout(\n () => queue.fail(new NornsTimeoutError(`No event for ${idle}ms on run ${runId}`)),\n idle,\n );\n };\n const onAbort = () => queue.fail(options.signal?.reason ?? abortError());\n\n socket.onError((err) => queue.fail(new StreamClosedError(err)));\n socket.onClose((ev) => queue.fail(new StreamClosedError(ev)));\n\n const channel = socket.channel(`agent:${agentId}`, { run_id: runId });\n channel.onMessage = (event: string, payload: Record<string, unknown>) => {\n if (!event.startsWith(\"phx_\") && !event.startsWith(\"chan_reply_\") && event !== \"heartbeat\") {\n // The channel is per agent, so another run's events arrive here too.\n if (payload?.run_id === undefined || payload.run_id === runId) {\n queue.push({ type: event, data: payload } as StreamEvent);\n touch();\n }\n }\n return payload;\n };\n channel\n .join()\n .receive(\"error\", (resp) =>\n queue.fail(new NornsError(`Could not join agent:${agentId}: ${JSON.stringify(resp)}`)),\n )\n .receive(\"timeout\", () =>\n queue.fail(new NornsTimeoutError(`Joining agent:${agentId} timed out`)),\n );\n\n if (options.signal?.aborted) onAbort();\n options.signal?.addEventListener(\"abort\", onAbort, { once: true });\n socket.connect();\n touch();\n\n try {\n for await (const event of queue) {\n yield event;\n if (TERMINAL_EVENTS.has(event.type)) return;\n }\n } finally {\n if (timer) clearTimeout(timer);\n options.signal?.removeEventListener(\"abort\", onAbort);\n queue.close();\n socket.disconnect();\n }\n }\n\n async #request<T = unknown>(\n method: string,\n path: string,\n options: { body?: unknown; query?: Record<string, string | number>; signal?: AbortSignal } = {},\n ): Promise<T> {\n const url = new URL(this.url + path);\n for (const [k, v] of Object.entries(options.query ?? {})) url.searchParams.set(k, String(v));\n\n const headers: Record<string, string> = {\n authorization: `Bearer ${this.#apiKey}`,\n accept: \"application/json\",\n };\n if (options.body !== undefined) headers[\"content-type\"] = \"application/json\";\n\n const res = await this.#fetch(url, {\n method,\n headers,\n body: options.body === undefined ? undefined : JSON.stringify(options.body),\n signal: options.signal,\n });\n\n const text = await res.text();\n const json = text === \"\" ? undefined : safeParse(text);\n if (!res.ok) {\n if (res.status === 404) throw new NotFoundError(`${method} ${path}`, json ?? text);\n throw new NornsApiError(res.status, json ?? text);\n }\n return json as T;\n }\n}\n\n// --- Helpers ---\n\nexport function resolveUrl(url: string | undefined): string {\n const value = url ?? process.env.NORNS_URL;\n if (!value) throw new NornsError(\"Norns URL missing: pass `url` or set NORNS_URL\");\n return value.replace(/\\/+$/, \"\");\n}\n\nexport function resolveApiKey(apiKey: string | undefined): string {\n const value = apiKey ?? process.env.NORNS_API_KEY;\n if (!value) throw new NornsError(\"Norns API key missing: pass `apiKey` or set NORNS_API_KEY\");\n return value;\n}\n\n/**\n * A key issued by `POST /api/v1/api_keys` with a worker scope (`nrnw_...`).\n * It opens the worker socket and nothing else, so a worker holding one must\n * not try the REST API.\n */\nexport function isScopedKey(apiKey: string): boolean {\n return apiKey.startsWith(\"nrnw_\");\n}\n\nexport function wsBase(url: string): string {\n return url.replace(/^http:\\/\\//, \"ws://\").replace(/^https:\\/\\//, \"wss://\");\n}\n\nfunction safeParse(text: string): unknown {\n try {\n return JSON.parse(text);\n } catch {\n return text;\n }\n}\n\nfunction abortError(): Error {\n return new DOMException(\"The operation was aborted\", \"AbortError\");\n}\n\nexport function sleep(ms: number, signal?: AbortSignal): Promise<void> {\n return new Promise((resolve, reject) => {\n if (signal?.aborted) return reject(signal.reason ?? abortError());\n const timer = setTimeout(() => {\n signal?.removeEventListener(\"abort\", onAbort);\n resolve();\n }, ms);\n function onAbort() {\n clearTimeout(timer);\n reject(signal?.reason ?? abortError());\n }\n signal?.addEventListener(\"abort\", onAbort, { once: true });\n });\n}\n\n// --- Parsers: wire snake_case → camelCase ---\n\ntype Raw = Record<string, unknown>;\n\nfunction parseWaitingFor(data: unknown): WaitingFor | null {\n if (!data || typeof data !== \"object\") return null;\n const w = data as Raw;\n return {\n question: String(w.question ?? \"\"),\n toolCallId: String(w.tool_call_id ?? \"\"),\n askedAt: typeof w.asked_at === \"string\" ? w.asked_at : undefined,\n };\n}\n\nexport function parseRun(r: Raw): Run {\n return {\n id: r.id as number,\n agentId: r.agent_id as number,\n conversationId: (r.conversation_id as number | null) ?? null,\n parentRunId: (r.parent_run_id as number | null) ?? null,\n gardId: (r.gard_id as number | null) ?? null,\n status: r.status as RunStatus,\n triggerType: (r.trigger_type as string) ?? \"message\",\n input: (r.input as Raw) ?? {},\n output: (r.output as string | null) ?? null,\n waitingFor: parseWaitingFor(r.waiting_for),\n failureMetadata: (r.failure_metadata as Raw) ?? {},\n inputTokens: (r.input_tokens as number) ?? 0,\n outputTokens: (r.output_tokens as number) ?? 0,\n cost: (r.cost as Run[\"cost\"]) ?? null,\n insertedAt: r.inserted_at as string,\n updatedAt: (r.updated_at as string) ?? (r.inserted_at as string),\n };\n}\n\nexport function parseEvent(e: Raw): RunEvent {\n return {\n id: e.id as number,\n sequence: e.sequence as number,\n eventType: e.event_type as string,\n payload: (e.payload as Raw) ?? {},\n source: (e.source as string) ?? \"\",\n insertedAt: e.inserted_at as string,\n };\n}\n\nexport function parseAgent(a: Raw): AgentInfo {\n return {\n id: a.id as number,\n name: a.name as string,\n purpose: (a.purpose as string | null) ?? null,\n status: (a.status as string) ?? \"active\",\n model: (a.model as string) ?? \"\",\n systemPrompt: (a.system_prompt as string) ?? \"\",\n maxSteps: (a.max_steps as number) ?? 50,\n contextStrategy: (a.context_strategy as string) ?? \"sliding_window\",\n contextWindow: (a.context_window as number) ?? 20,\n archivedAt: (a.archived_at as string | null) ?? null,\n insertedAt: a.inserted_at as string,\n updatedAt: (a.updated_at as string) ?? (a.inserted_at as string),\n };\n}\n\nexport function parseConversation(c: Raw): Conversation {\n return {\n id: c.id as number,\n agentId: c.agent_id as number,\n key: c.key as string,\n summary: (c.summary as string | null) ?? null,\n messageCount: (c.message_count as number) ?? 0,\n tokenEstimate: (c.token_estimate as number) ?? 0,\n insertedAt: c.inserted_at as string,\n updatedAt: (c.updated_at as string) ?? (c.inserted_at as string),\n };\n}\n","/**\n * A push-in, pull-out queue that is also an async iterable. Producers push\n * values (or close, or fail); a single consumer iterates. Used to turn a\n * channel's callbacks into `for await`.\n */\nexport class AsyncQueue<T> implements AsyncIterable<T> {\n #values: T[] = [];\n #waiters: Array<{ resolve: (r: IteratorResult<T>) => void; reject: (e: unknown) => void }> = [];\n #done = false;\n #error: unknown = undefined;\n\n push(value: T): void {\n if (this.#done) return;\n const waiter = this.#waiters.shift();\n if (waiter) waiter.resolve({ value, done: false });\n else this.#values.push(value);\n }\n\n close(): void {\n if (this.#done) return;\n this.#done = true;\n for (const w of this.#waiters.splice(0)) w.resolve({ value: undefined, done: true });\n }\n\n fail(error: unknown): void {\n if (this.#done) return;\n this.#done = true;\n this.#error = error;\n for (const w of this.#waiters.splice(0)) w.reject(error);\n }\n\n get closed(): boolean {\n return this.#done;\n }\n\n next(): Promise<IteratorResult<T>> {\n if (this.#values.length > 0) {\n return Promise.resolve({ value: this.#values.shift() as T, done: false });\n }\n if (this.#done) {\n return this.#error !== undefined\n ? Promise.reject(this.#error)\n : Promise.resolve({ value: undefined, done: true });\n }\n return new Promise((resolve, reject) => this.#waiters.push({ resolve, reject }));\n }\n\n [Symbol.asyncIterator](): AsyncIterator<T> {\n return { next: () => this.next() };\n }\n}\n","/** Base class for every error this SDK raises. */\nexport class NornsError extends Error {\n constructor(message: string, options?: { cause?: unknown }) {\n super(message, options);\n this.name = \"NornsError\";\n }\n}\n\n/** The Norns API answered with a non-2xx status. */\nexport class NornsApiError extends NornsError {\n readonly status: number;\n readonly body: unknown;\n\n constructor(status: number, body: unknown, message?: string) {\n super(message ?? `Norns API error ${status}: ${describeBody(body)}`);\n this.name = \"NornsApiError\";\n this.status = status;\n this.body = body;\n }\n}\n\n/** The thing asked for does not exist (404). */\nexport class NotFoundError extends NornsApiError {\n constructor(what: string, body: unknown = undefined) {\n super(404, body, `${what} not found`);\n this.name = \"NotFoundError\";\n }\n}\n\n/** A wait or a stream ran out of time. */\nexport class NornsTimeoutError extends NornsError {\n constructor(message: string) {\n super(message);\n this.name = \"NornsTimeoutError\";\n }\n}\n\n/**\n * The worker's channel join was rejected for a reason a retry cannot fix:\n * a bad claim token, a destroyed or missing gard, an invalid registration.\n */\nexport class JoinError extends NornsError {\n readonly reason: string;\n readonly code: string | undefined;\n\n constructor(reason: string, code?: string) {\n super(`worker join rejected: ${reason}${code ? ` (${code})` : \"\"}`);\n this.name = \"JoinError\";\n this.reason = reason;\n this.code = code;\n }\n}\n\n/** The gard this worker claimed was destroyed while it was connected. */\nexport class GardDestroyedError extends NornsError {\n constructor(gard: string | number | undefined) {\n super(`gard ${gard ?? \"?\"} was destroyed`);\n this.name = \"GardDestroyedError\";\n }\n}\n\n/** The scoped key this worker joined on was revoked while it was connected. */\nexport class KeyRevokedError extends NornsError {\n constructor() {\n super(\"the worker's scoped key was revoked\");\n this.name = \"KeyRevokedError\";\n }\n}\n\n/** A stream's socket closed before the run reached a terminal event. */\nexport class StreamClosedError extends NornsError {\n readonly reason: unknown;\n\n constructor(reason: unknown) {\n super(`stream closed before the run finished: ${describeBody(reason)}`);\n this.name = \"StreamClosedError\";\n this.reason = reason;\n }\n}\n\nfunction describeBody(body: unknown): string {\n if (typeof body === \"string\") return body;\n if (body && typeof body === \"object\" && \"error\" in body) {\n const err = (body as { error: unknown }).error;\n return typeof err === \"string\" ? err : JSON.stringify(err);\n }\n if (body instanceof Error) return body.message;\n try {\n return JSON.stringify(body);\n } catch {\n return String(body);\n }\n}\n\n/** A readable message for anything thrown. */\nexport function errorMessage(err: unknown): string {\n if (err instanceof Error) return err.message;\n return describeBody(err);\n}\n","/** Where a run is: on the way, finished, or parked on a human. */\nexport type RunStatus = \"pending\" | \"running\" | \"waiting\" | \"completed\" | \"failed\" | \"error\";\n\n/** The question a run is parked on when its status is `\"waiting\"`. */\nexport interface WaitingFor {\n question: string;\n toolCallId: string;\n askedAt: string | undefined;\n}\n\nexport interface Run {\n id: number;\n agentId: number;\n conversationId: number | null;\n parentRunId: number | null;\n gardId: number | null;\n status: RunStatus;\n triggerType: string;\n input: Record<string, unknown>;\n output: string | null;\n /** Present when `status` is `\"waiting\"`: answer it with `client.runs.reply()`. */\n waitingFor: WaitingFor | null;\n failureMetadata: Record<string, unknown>;\n inputTokens: number;\n outputTokens: number;\n /** Dollars as a decimal string, so nothing rounds them through a float. */\n cost: { usd: string; unpriced: boolean } | null;\n insertedAt: string;\n updatedAt: string;\n}\n\nexport interface RunEvent {\n id: number;\n sequence: number;\n eventType: string;\n payload: Record<string, unknown>;\n source: string;\n insertedAt: string;\n}\n\n/** An agent as the server describes it. */\nexport interface AgentInfo {\n id: number;\n name: string;\n purpose: string | null;\n status: string;\n model: string;\n systemPrompt: string;\n maxSteps: number;\n contextStrategy: string;\n contextWindow: number;\n archivedAt: string | null;\n insertedAt: string;\n updatedAt: string;\n}\n\nexport interface Conversation {\n id: number;\n agentId: number;\n key: string;\n summary: string | null;\n messageCount: number;\n tokenEstimate: number;\n insertedAt: string;\n updatedAt: string;\n}\n\n/** What `sendMessage()` returns. */\nexport interface MessageResult {\n runId: number;\n /** `\"accepted\"` when not waiting; otherwise the run's status when the wait ended. */\n status: \"accepted\" | RunStatus;\n output: string | null;\n conversationKey: string | undefined;\n /** The agent is parked on a question and will not move until it is answered. */\n isWaiting: boolean;\n waitingFor: WaitingFor | null;\n}\n\n/** Every stream payload carries the run and agent it belongs to. */\ninterface Tagged {\n run_id: number;\n agent_id: number;\n}\n\n/**\n * An event from a run as it happens, keyed by `type`. The two terminal\n * events are `completed` and `error`. Unknown types pass through as\n * `{ type: string, data: object }` so a newer server never breaks a client.\n */\nexport type StreamEvent =\n | { type: \"agent_started\"; data: Tagged }\n | {\n type: \"llm_response\";\n data: Tagged & {\n step: number;\n finish_reason: string;\n content: string;\n tool_calls: Array<{ id: string; name: string; arguments: unknown }> | null;\n };\n }\n | { type: \"tool_call\"; data: Tagged & { name: string; arguments: unknown } }\n | {\n type: \"tool_result\";\n data: Tagged & {\n tool_call_id: string;\n name: string;\n content: string;\n [key: string]: unknown;\n };\n }\n | { type: \"waiting_for_user\"; data: Tagged & { tool_call_id: string; question: string } }\n | { type: \"waiting_timer\"; data: Tagged & { seconds: number; reason: string | null } }\n | { type: \"context_compacted\"; data: Tagged & { step: number; dropped: number; kept: number } }\n | { type: \"completed\"; data: Tagged & { output: string } }\n | { type: \"error\"; data: Tagged & { error: string } }\n | { type: string; data: Tagged & Record<string, unknown> };\n\nexport const TERMINAL_EVENTS: ReadonlySet<string> = new Set([\"completed\", \"error\"]);\n","/**\n * Where the SDK writes what it is doing. Anything with these four methods\n * works: `console`, pino, winston, or your own.\n */\nexport interface Logger {\n debug(message: string, ...rest: unknown[]): void;\n info(message: string, ...rest: unknown[]): void;\n warn(message: string, ...rest: unknown[]): void;\n error(message: string, ...rest: unknown[]): void;\n}\n\n/** Logs info and above to the console, prefixed so it is easy to grep. */\nexport const consoleLogger: Logger = {\n debug() {},\n info: (message, ...rest) => console.log(`[norns] ${message}`, ...rest),\n warn: (message, ...rest) => console.warn(`[norns] ${message}`, ...rest),\n error: (message, ...rest) => console.error(`[norns] ${message}`, ...rest),\n};\n\nexport const silentLogger: Logger = {\n debug() {},\n info() {},\n warn() {},\n error() {},\n};\n\nexport function resolveLogger(logger: Logger | null | undefined): Logger {\n if (logger === null) return silentLogger;\n return logger ?? consoleLogger;\n}\n","import type { LanguageModel } from \"ai\";\n\n/** Turns the model name on an LLM task into something the AI SDK can call. */\nexport type ModelResolver = (modelId: string) => LanguageModel | Promise<LanguageModel>;\n\n/** A provider, or a registry from `createProviderRegistry()`. */\nexport interface ModelSource {\n languageModel(modelId: string): LanguageModel;\n}\n\nexport type ModelsOption = ModelResolver | ModelSource;\n\nconst PROVIDER_PACKAGES: Record<string, string> = {\n anthropic: \"@ai-sdk/anthropic\",\n openai: \"@ai-sdk/openai\",\n google: \"@ai-sdk/google\",\n mistral: \"@ai-sdk/mistral\",\n};\n\n/**\n * Split `\"provider/model\"` (or `\"provider:model\"`) into its parts, inferring\n * the provider from the model's name when there is no prefix.\n */\nexport function inferProvider(model: string): { provider: string; modelId: string } {\n const sep = model.search(/[/:]/);\n if (sep > 0) {\n const provider = model.slice(0, sep);\n if (provider in PROVIDER_PACKAGES || /^[a-z][a-z0-9-]*$/.test(provider)) {\n return { provider, modelId: model.slice(sep + 1) };\n }\n }\n const lower = model.toLowerCase();\n if (lower.startsWith(\"claude\")) return { provider: \"anthropic\", modelId: model };\n if (/^(gpt|o[1-9]|chatgpt|text-)/.test(lower)) return { provider: \"openai\", modelId: model };\n if (lower.startsWith(\"gemini\")) return { provider: \"google\", modelId: model };\n if (/^(mistral|codestral|ministral|pixtral|magistral)/.test(lower)) {\n return { provider: \"mistral\", modelId: model };\n }\n return { provider: \"anthropic\", modelId: model };\n}\n\n/**\n * The default: pick the `@ai-sdk/*` package for the model's provider, load\n * it if it is installed, and ask it for the model. API keys come from the\n * provider's own environment variable (`ANTHROPIC_API_KEY`, `OPENAI_API_KEY`, ...).\n */\nexport function defaultModelResolver(): ModelResolver {\n const cache = new Map<string, Promise<LanguageModel>>();\n return (model) => {\n let pending = cache.get(model);\n if (!pending) {\n pending = loadModel(model);\n cache.set(model, pending);\n pending.catch(() => cache.delete(model));\n }\n return pending;\n };\n}\n\nasync function loadModel(model: string): Promise<LanguageModel> {\n const { provider, modelId } = inferProvider(model);\n const pkg = PROVIDER_PACKAGES[provider] ?? `@ai-sdk/${provider}`;\n\n let mod: Record<string, unknown>;\n try {\n mod = (await import(pkg)) as Record<string, unknown>;\n } catch (err) {\n throw new Error(\n `No provider for model '${model}': install ${pkg} (npm install ${pkg}), ` +\n \"or pass `models` to the worker to resolve models yourself\",\n { cause: err },\n );\n }\n\n const instance = findProvider(mod, provider);\n if (!instance) {\n throw new Error(`${pkg} exports no provider instance; pass \\`models\\` to the worker`);\n }\n return instance(modelId);\n}\n\ntype ProviderFn = ((modelId: string) => LanguageModel) & { languageModel?: unknown };\n\n// Each package exports a default instance named for the provider\n// (`anthropic`, `openai`, ...); fall back to any callable with `languageModel`.\nfunction findProvider(mod: Record<string, unknown>, provider: string): ProviderFn | undefined {\n const named = mod[provider];\n if (typeof named === \"function\") return named as ProviderFn;\n for (const value of Object.values(mod)) {\n if (typeof value === \"function\" && \"languageModel\" in value) return value as ProviderFn;\n }\n return undefined;\n}\n\nexport function toResolver(models: ModelsOption | undefined): ModelResolver {\n if (models === undefined) return defaultModelResolver();\n if (typeof models === \"function\") return models;\n return (id) => models.languageModel(id);\n}\n","import { asSchema, type FlexibleSchema, type JSONSchema7, jsonSchema } from \"ai\";\nimport type { NornsWorker } from \"./worker.js\";\n\n/**\n * What a tool's `execute` is told about the call, besides its input.\n *\n * `signal` aborts when the worker gives up on the call: the socket dropped\n * (Norns re-dispatches the task) or a drain hit its deadline. A long tool\n * should pass it to whatever it waits on.\n */\nexport interface ToolContext {\n taskId: string;\n runId: number | undefined;\n agentId: number | undefined;\n /**\n * Set when Norns considers the call side-effecting. Same run, same step,\n * same tool call, same key, however many times it is dispatched; hand it\n * to a provider that dedupes (most payment APIs take one) and the effect\n * survives this worker dying mid-call too.\n */\n idempotencyKey: string | undefined;\n signal: AbortSignal;\n worker: NornsWorker;\n}\n\n/** A Zod schema, any Standard Schema, an `ai` `Schema`, or raw JSON Schema. */\nexport type ToolInputSchema = FlexibleSchema | JSONSchema7;\n\n/** The argument type `execute` receives for a given `input` schema. */\nexport type InferToolInput<S> = S extends FlexibleSchema<infer T> ? T : Record<string, unknown>;\n\nexport interface ToolOptions<S extends ToolInputSchema = ToolInputSchema> {\n /** What the model calls it by. */\n name: string;\n /** What the model reads to decide when to call it. */\n description: string;\n /**\n * The input shape. A Zod object schema gives a typed, validated `execute`;\n * leave it out for a tool that takes nothing.\n */\n input?: S;\n /**\n * Mark a tool whose call must not happen twice. Norns then names each call\n * with an idempotency key, and a re-dispatched call is answered from the\n * result this worker kept rather than run again.\n */\n sideEffect?: boolean;\n /**\n * The handler. Return a string, or anything JSON-serialisable (it is\n * stringified for the model). Throwing reports an error result; the model\n * sees the message.\n */\n execute: (input: InferToolInput<S>, context: ToolContext) => unknown | Promise<unknown>;\n}\n\nexport type ValidationResult<T> = { success: true; value: T } | { success: false; error: Error };\n\n/** A tool ready to register with a worker: what `tool()` returns. */\nexport interface ToolDefinition<I = unknown> {\n readonly name: string;\n readonly description: string;\n readonly inputSchema: JSONSchema7;\n readonly sideEffect: boolean;\n /** Validates and coerces an input against the schema, when there is one. */\n readonly validate: ((value: unknown) => Promise<ValidationResult<I>>) | undefined;\n // Method syntax on purpose: it is bivariant, so a `ToolDefinition<{ q: string }>`\n // fits a `ToolDefinition[]` without the caller casting.\n execute(input: I, context: ToolContext): Promise<unknown>;\n}\n\nconst EMPTY_SCHEMA: JSONSchema7 = { type: \"object\", properties: {} };\n\n/**\n * Define a tool.\n *\n * const searchDocs = tool({\n * name: \"search_docs\",\n * description: \"Search product documentation.\",\n * input: z.object({ query: z.string() }),\n * execute: async ({ query }) => db.search(query),\n * });\n */\nexport function tool<S extends ToolInputSchema>(\n options: ToolOptions<S>,\n): ToolDefinition<InferToolInput<S>> {\n type I = InferToolInput<S>;\n const name = options.name?.trim();\n if (!name) throw new Error(\"tool(): name is required\");\n if (!options.description?.trim()) throw new Error(`tool('${name}'): description is required`);\n if (typeof options.execute !== \"function\") {\n throw new Error(`tool('${name}'): execute must be a function`);\n }\n\n let inputSchema: JSONSchema7 = EMPTY_SCHEMA;\n let validate: ToolDefinition<I>[\"validate\"];\n\n if (options.input !== undefined) {\n const schema = asSchema(toFlexible(options.input));\n const json = schema.jsonSchema;\n if (isPromiseLike(json)) {\n throw new Error(`tool('${name}'): input schema must resolve synchronously`);\n }\n inputSchema = stripMeta(json);\n if (schema.validate) {\n const run = schema.validate;\n validate = async (value) => {\n const result = await run(value);\n return result.success\n ? { success: true, value: result.value as I }\n : { success: false, error: result.error };\n };\n }\n }\n\n const execute = options.execute;\n return Object.freeze({\n name,\n description: options.description.trim(),\n inputSchema,\n sideEffect: options.sideEffect ?? false,\n validate,\n execute: async (input: I, context: ToolContext) => execute(input, context),\n });\n}\n\n/** The wire form Norns reads at join. */\nexport function toolRegistration(t: ToolDefinition): {\n name: string;\n description: string;\n input_schema: JSONSchema7;\n side_effect: boolean;\n} {\n return {\n name: t.name,\n description: t.description,\n input_schema: t.inputSchema,\n side_effect: t.sideEffect,\n };\n}\n\n/** Turn a tool's output into the string the model reads. */\nexport function stringifyToolOutput(value: unknown): string {\n if (value === undefined || value === null) return \"\";\n if (typeof value === \"string\") return value;\n return JSON.stringify(value);\n}\n\nfunction toFlexible(input: ToolInputSchema): FlexibleSchema {\n if (isRawJsonSchema(input)) return jsonSchema(input);\n return input as FlexibleSchema;\n}\n\n// A plain object is JSON Schema; anything that knows how to validate\n// itself (Zod, Standard Schema, an `ai` Schema) is not.\nfunction isRawJsonSchema(value: unknown): value is JSONSchema7 {\n if (typeof value !== \"object\" || value === null) return false;\n if (\"~standard\" in value || \"_zod\" in value || \"_def\" in value || \"jsonSchema\" in value) {\n return false;\n }\n return true;\n}\n\nfunction isPromiseLike(value: unknown): value is PromiseLike<unknown> {\n return (\n typeof value === \"object\" &&\n value !== null &&\n \"then\" in value &&\n typeof (value as { then: unknown }).then === \"function\"\n );\n}\n\nfunction stripMeta(schema: JSONSchema7): JSONSchema7 {\n const { $schema: _ignored, ...rest } = schema;\n return rest;\n}\n","import { randomBytes } from \"node:crypto\";\nimport { generateText } from \"ai\";\nimport { type Channel, Socket, type SocketConnectOption } from \"phoenix\";\nimport { type AgentDefinition, agentList, toolsByName } from \"./agent.js\";\nimport {\n isScopedKey,\n NornsClient,\n resolveApiKey,\n resolveUrl,\n sleep,\n type WebSocketConstructor,\n wsBase,\n} from \"./client.js\";\nimport { CompletedCalls, completedCallsPath } from \"./completed-calls.js\";\nimport {\n errorMessage,\n GardDestroyedError,\n JoinError,\n KeyRevokedError,\n NornsError,\n} from \"./errors.js\";\nimport {\n compactionMessages,\n composeCompactionPrompt,\n composeSystemPrompt,\n finalOutput,\n fromGenerateResult,\n type LlmResult,\n type LlmTask,\n maxTokens,\n messagesForTask,\n type ToolResult,\n type ToolTask,\n toInstructions,\n toModelMessages,\n toToolSet,\n} from \"./format.js\";\nimport { HistoryCache } from \"./history-cache.js\";\nimport { type Logger, resolveLogger } from \"./logger.js\";\nimport { type ModelResolver, type ModelsOption, toResolver } from \"./models.js\";\nimport {\n stringifyToolOutput,\n type ToolContext,\n type ToolDefinition,\n toolRegistration,\n} from \"./tool.js\";\n\nexport type Capability = \"llm\" | \"tools\";\n\nexport interface NornsWorkerOptions {\n /** The agent, or agents, this worker serves. */\n agents: AgentDefinition | AgentDefinition[];\n /** The Norns base URL. Defaults to `NORNS_URL`. */\n url?: string;\n /**\n * The bearer token. Defaults to `NORNS_API_KEY`. A scoped worker key\n * (`nrnw_...`) joins without registering the agents, since it cannot reach\n * the REST API; register the definitions with a tenant key.\n */\n apiKey?: string;\n /**\n * How a model name on an LLM task becomes a model to call: a function, a\n * provider (`anthropic`), or a registry from `createProviderRegistry()`.\n * By default the provider is inferred from the name and its `@ai-sdk/*`\n * package loaded; API keys come from the provider's own env var.\n */\n models?: ModelsOption;\n /** What this worker serves. Default both; `[\"tools\"]` for a worker with no LLM access. */\n capabilities?: Capability[];\n /** A stable identity. Defaults to `NORNS_WORKER_ID`, else a random one. */\n workerId?: string;\n /** Claim a gard (defaults to `NORNS_GARD`); needs `claimToken`. */\n gard?: string | number;\n /** Defaults to `NORNS_GARD_CLAIM_TOKEN`. */\n claimToken?: string;\n /** How long `stop()` waits for in-flight tasks. Default 30 s, or `NORNS_SHUTDOWN_TIMEOUT` (seconds). */\n shutdownTimeoutMs?: number;\n /** Drain on SIGINT/SIGTERM. Default true. */\n handleSignals?: boolean;\n /** Where to log. `null` for silence. Default: the console. */\n logger?: Logger | null;\n /**\n * Where completed side-effecting calls are remembered across restarts.\n * Defaults to `NORNS_STATE_DIR`, else the system temp dir; `null` disables.\n */\n stateDir?: string | null;\n /** Replace the global `fetch` (used to register the agents). */\n fetch?: typeof globalThis.fetch;\n /** Replace the global `WebSocket`. */\n transport?: WebSocketConstructor;\n /** Extra options for the Phoenix socket. */\n socketOptions?: Partial<SocketConnectOption>;\n}\n\nexport interface RegisterPortOptions {\n name?: string;\n url?: string;\n protocol?: string;\n}\n\nexport interface RegisteredPort {\n id: number;\n internalPort: number;\n url: string | null;\n}\n\ntype WorkerState = \"idle\" | \"starting\" | \"running\" | \"draining\" | \"stopped\";\n\ninterface InFlight {\n taskId: string;\n controller: AbortController;\n done: Promise<void>;\n}\n\nconst TOPIC = \"worker:lobby\";\n\n/**\n * Serves agents: connects to Norns, registers their tools, and handles the\n * LLM and tool tasks it is sent.\n *\n * const worker = new NornsWorker({ agents: [supportBot] });\n * await worker.start(); // resolves once joined; Ctrl-C drains and exits\n *\n * `start()` resolves when the worker has joined, so the rest of your program\n * can carry on; the open socket keeps the process alive. `stop()` drains:\n * Norns stops sending work, in-flight tasks finish and report, and the\n * worker leaves. `stopped` settles when that is done.\n */\nexport class NornsWorker {\n readonly url: string;\n readonly workerId: string;\n readonly gard: string | number | undefined;\n\n readonly #apiKey: string;\n readonly #agents: AgentDefinition[];\n readonly #tools: Map<string, ToolDefinition>;\n readonly #capabilities: Capability[];\n readonly #claimToken: string | undefined;\n readonly #shutdownTimeoutMs: number;\n readonly #handleSignals: boolean;\n readonly #logger: Logger;\n readonly #stateDir: string | null | undefined;\n readonly #transport: WebSocketConstructor | undefined;\n readonly #socketOptions: Partial<SocketConnectOption>;\n readonly #client: NornsClient;\n readonly #resolveModel: ModelResolver;\n readonly #inFlight = new Set<InFlight>();\n readonly #history = new HistoryCache();\n\n #state: WorkerState = \"idle\";\n #socket: Socket | undefined;\n #channel: Channel | undefined;\n #completed: CompletedCalls | undefined;\n #starting: Promise<void> | undefined;\n #signalHandler: ((signal: NodeJS.Signals) => void) | undefined;\n readonly #stopped: Promise<void>;\n #settleStopped!: { resolve: () => void; reject: (err: unknown) => void };\n\n constructor(options: NornsWorkerOptions) {\n this.url = resolveUrl(options.url);\n this.#apiKey = resolveApiKey(options.apiKey);\n this.#agents = agentList(options.agents);\n this.#tools = toolsByName(this.#agents);\n this.#capabilities = options.capabilities ?? [\"llm\", \"tools\"];\n if (this.#capabilities.length === 0)\n throw new NornsError(\"A worker needs at least one capability\");\n this.#logger = resolveLogger(options.logger);\n this.#stateDir = options.stateDir;\n this.#transport = options.transport;\n this.#socketOptions = options.socketOptions ?? {};\n this.#handleSignals = options.handleSignals ?? true;\n this.#resolveModel = toResolver(options.models);\n\n // A provisioner (volund) hands the worker its identity and gard through\n // the environment, so scaffolded workers need no code changes.\n this.workerId =\n options.workerId ??\n process.env.NORNS_WORKER_ID ??\n `ts-worker-${randomBytes(4).toString(\"hex\")}`;\n this.gard = options.gard ?? process.env.NORNS_GARD;\n this.#claimToken = options.claimToken ?? process.env.NORNS_GARD_CLAIM_TOKEN;\n\n const envTimeout = Number(process.env.NORNS_SHUTDOWN_TIMEOUT);\n this.#shutdownTimeoutMs =\n options.shutdownTimeoutMs ??\n (Number.isFinite(envTimeout) && envTimeout > 0 ? envTimeout * 1000 : 30_000);\n\n this.#client = new NornsClient({ url: this.url, apiKey: this.#apiKey, fetch: options.fetch });\n\n this.#stopped = new Promise<void>((resolve, reject) => {\n this.#settleStopped = { resolve, reject };\n });\n // Nobody has to await `stopped`; a rejection must not crash the process.\n this.#stopped.catch(() => {});\n }\n\n /** The agents this worker serves. */\n get agents(): readonly AgentDefinition[] {\n return this.#agents;\n }\n\n get state(): WorkerState {\n return this.#state;\n }\n\n /**\n * Settles once the worker has stopped: resolves after a drain, rejects\n * with `JoinError` or `GardDestroyedError` when it was forced off.\n */\n get stopped(): Promise<void> {\n return this.#stopped;\n }\n\n /**\n * Register the agents, connect, and join. Resolves once Norns has accepted\n * the worker; rejects with `JoinError` when it never will (bad claim\n * token, destroyed gard). A server that is down is retried until it is up.\n */\n start(): Promise<void> {\n if (this.#state !== \"idle\") throw new NornsError(\"start() may only be called once\");\n this.#state = \"starting\";\n this.#starting = this.#start().then(\n () => {\n if (this.#state === \"starting\") this.#state = \"running\";\n },\n (err) => {\n this.#fail(err);\n throw err;\n },\n );\n return this.#starting;\n }\n\n async #start(): Promise<void> {\n if (isScopedKey(this.#apiKey)) {\n this.#logger.info(\n \"Worker key is scoped (nrnw_): skipping agent registration. Register the agent definitions with a tenant key.\",\n );\n } else {\n for (const agent of this.#agents) {\n const info = await this.#client.agents.ensure(agent);\n this.#logger.info(`Registered agent '${agent.name}' (id=${info.id})`);\n }\n }\n\n if (this.#capabilities.includes(\"llm\")) {\n // A model nobody can serve fails here, with a message, not on the first task.\n for (const model of new Set(this.#agents.map((a) => a.model))) {\n await this.#resolveModel(model);\n }\n }\n\n // Keyed by worker id: Norns re-dispatches a lost call to whichever\n // worker comes back under that identity, and this is what it needs to\n // recognise it.\n this.#completed = new CompletedCalls(\n completedCallsPath(this.workerId, this.#stateDir),\n this.#logger,\n );\n\n await this.#connect();\n this.#installSignalHandlers();\n }\n\n #connect(): Promise<void> {\n const socket = new Socket(`${wsBase(this.url)}/worker`, {\n params: { token: this.#apiKey },\n logger: (kind, msg, data) => this.#logger.debug(`phoenix ${kind}: ${msg}`, data),\n ...(this.#transport\n ? { transport: this.#transport as SocketConnectOption[\"transport\"] }\n : {}),\n ...this.#socketOptions,\n });\n this.#socket = socket;\n\n socket.onOpen(() => {\n this.#logger.info(`Connected to ${this.url}`);\n // Norns sends deltas only on the connection it sent the history on, so\n // a new connection starts with nothing to be stale.\n this.#history.clear();\n });\n socket.onError((err) => {\n if (this.#state === \"starting\" || this.#state === \"running\") {\n this.#logger.warn(`Connection error (${errorMessage(err)}); retrying`);\n }\n });\n socket.onClose(() => {\n if (this.#state === \"running\") {\n this.#logger.warn(\"Disconnected from Norns; reconnecting\");\n // In-flight results cannot be delivered on the next connection: Norns\n // re-dispatches on disconnect, and idempotency skips completed side effects.\n this.#abortInFlight(\"socket closed\");\n }\n });\n\n const channel = socket.channel(TOPIC, this.#joinParams());\n this.#channel = channel;\n channel.on(\"llm_task\", (task: LlmTask) =>\n this.#spawn(task.task_id, (s) => this.#runLlm(task, s)),\n );\n channel.on(\"tool_task\", (task: ToolTask) =>\n this.#spawn(task.task_id, (s) => this.#runTool(task, s)),\n );\n channel.on(\"gard_destroyed\", () => {\n this.#logger.error(\"This worker's gard was destroyed; shutting down\");\n this.#fail(new GardDestroyedError(this.gard));\n });\n channel.on(\"key_revoked\", () => {\n this.#logger.error(\"This worker's key was revoked; shutting down\");\n this.#fail(new KeyRevokedError());\n });\n channel.onError((reason) => {\n if (this.#state === \"running\")\n this.#logger.warn(`Channel error (${errorMessage(reason)}); rejoining`);\n });\n\n return new Promise<void>((resolve, reject) => {\n let joined = false;\n channel\n .join()\n .receive(\"ok\", () => {\n if (joined) {\n this.#logger.info(`Worker ${this.workerId} rejoined`);\n return;\n }\n joined = true;\n this.#logger.info(\n this.gard !== undefined\n ? `Worker ${this.workerId} ready (gard ${this.gard})`\n : `Worker ${this.workerId} ready`,\n );\n resolve();\n })\n .receive(\"error\", (resp: { reason?: string; code?: string } | undefined) => {\n const reason = resp?.reason ?? \"join rejected\";\n // On a quick reconnect the server may not have processed the old\n // connection's disconnect yet; the channel rejoins by itself.\n if (reason === \"already_claimed\") {\n this.#logger.warn(\"Gard claim rejected: already_claimed; retrying\");\n return;\n }\n const err = new JoinError(reason, resp?.code);\n this.#fail(err);\n reject(err);\n })\n .receive(\"timeout\", () => this.#logger.warn(\"Join timed out; retrying\"));\n socket.connect();\n });\n }\n\n #joinParams(): Record<string, unknown> {\n const params: Record<string, unknown> = {\n worker_id: this.workerId,\n tools: [...this.#tools.values()].map(toolRegistration),\n capabilities: this.#capabilities,\n // This worker keeps the history it was last sent per run, so Norns may\n // send later steps as the change only (HistoryCache).\n features: [\"message_cache\"],\n };\n if (this.gard !== undefined) {\n params.gard = this.gard;\n params.claim_token = this.#claimToken ?? null;\n }\n return params;\n }\n\n /**\n * Drain and stop: tell Norns to send no more work, finish the tasks in\n * flight (up to the shutdown timeout), report them, leave. Tasks still\n * running at the deadline are dropped and Norns re-dispatches them.\n */\n async stop(): Promise<void> {\n if (this.#state === \"idle\") {\n this.#state = \"stopped\";\n this.#settleStopped.resolve();\n return;\n }\n if (this.#state === \"starting\") {\n try {\n await this.#starting;\n } catch {\n return;\n }\n }\n if (this.#state !== \"running\") return this.#stopped;\n this.#state = \"draining\";\n\n const channel = this.#channel;\n const socket = this.#socket;\n this.#logger.info(\n `Draining: ${this.#inFlight.size} in-flight task(s), up to ${this.#shutdownTimeoutMs / 1000}s`,\n );\n\n // Norns stops dispatching to us. In-flight tasks stay ours; new ones\n // queue for our replacement.\n if (channel) {\n await new Promise<void>((resolve) => {\n channel\n .push(\"drain\", {}, 5000)\n .receive(\"ok\", () => resolve())\n .receive(\"error\", (resp) => {\n this.#logger.warn(\n `Could not send drain (${errorMessage(resp)}); Norns will re-dispatch on disconnect`,\n );\n resolve();\n })\n .receive(\"timeout\", () => resolve());\n });\n }\n\n // Wait for what we hold, including anything that raced in before the\n // drain took effect, until the deadline.\n const deadline = Date.now() + this.#shutdownTimeoutMs;\n while (this.#inFlight.size > 0 && Date.now() < deadline) {\n await Promise.race([\n Promise.allSettled([...this.#inFlight].map((t) => t.done)),\n sleep(deadline - Date.now()),\n ]);\n }\n if (this.#inFlight.size > 0) {\n this.#logger.warn(\n `${this.#inFlight.size} task(s) still running at the deadline; dropping them, Norns will re-dispatch`,\n );\n this.#abortInFlight(\"shutdown deadline\");\n } else {\n this.#logger.info(\"Drained; leaving\");\n }\n\n if (channel) {\n await new Promise<void>((resolve) => {\n channel\n .leave(5000)\n .receive(\"ok\", () => resolve())\n .receive(\"timeout\", () => resolve());\n });\n }\n if (socket) await new Promise<void>((resolve) => socket.disconnect(() => resolve()));\n\n this.#teardown();\n this.#state = \"stopped\";\n this.#logger.info(\"Worker stopped.\");\n this.#settleStopped.resolve();\n }\n\n /**\n * Expose a service port for the dashboard. Only in a gard: the gard is\n * inferred from the connection. Call it from a tool after starting a\n * service.\n */\n async registerPort(\n internalPort: number,\n options: RegisterPortOptions = {},\n ): Promise<RegisteredPort> {\n if (this.gard === undefined)\n throw new NornsError(\"registerPort requires the worker to be in a gard\");\n const channel = this.#channel;\n if (channel?.state !== \"joined\") {\n throw new NornsError(\"registerPort requires a connected worker\");\n }\n const payload: Record<string, unknown> = {\n internal_port: internalPort,\n name: options.name ?? \"\",\n protocol: options.protocol ?? \"http\",\n };\n if (options.url) payload.url = options.url;\n\n return new Promise((resolve, reject) => {\n channel\n .push(\"register_port\", payload, 10_000)\n .receive(\"ok\", (resp: { id: number; internal_port: number; url: string | null }) =>\n resolve({ id: resp.id, internalPort: resp.internal_port, url: resp.url ?? null }),\n )\n .receive(\"error\", (resp) =>\n reject(new NornsError(`register_port rejected: ${errorMessage(resp?.reason ?? resp)}`)),\n )\n .receive(\"timeout\", () => reject(new NornsError(\"register_port timed out\")));\n });\n }\n\n // --- Tasks ---\n\n // Each task runs on its own: a slow tool or LLM call must not hold up the\n // others on this connection (parallel tool calls, other runs).\n #spawn(taskId: string, run: (signal: AbortSignal) => Promise<LlmResult | ToolResult>): void {\n const controller = new AbortController();\n const entry: InFlight = { taskId, controller, done: Promise.resolve() };\n entry.done = (async () => {\n try {\n const result = await run(controller.signal);\n this.#deliver(taskId, result);\n } catch (err) {\n this.#logger.error(`Task ${taskId} failed unexpectedly: ${errorMessage(err)}`);\n this.#deliver(taskId, { status: \"error\", error: errorMessage(err) });\n } finally {\n this.#inFlight.delete(entry);\n }\n })();\n this.#inFlight.add(entry);\n }\n\n #deliver(taskId: string, result: LlmResult | ToolResult): void {\n const channel = this.#channel;\n if (channel?.state !== \"joined\") {\n this.#logger.warn(\n `Could not deliver result for task ${taskId} (not joined); Norns re-dispatches it on reconnect`,\n );\n return;\n }\n channel\n .push(\"tool_result\", { ...result, task_id: taskId })\n .receive(\"error\", (resp) =>\n this.#logger.warn(`Server rejected result for ${taskId}: ${errorMessage(resp)}`),\n );\n }\n\n async #runLlm(received: LlmTask, signal: AbortSignal): Promise<LlmResult> {\n const task = this.#history.resolve(received);\n if (task === undefined) {\n // The delta was built on a history this worker no longer holds. Norns\n // resends the whole list at the same step; no retry counted.\n this.#logger.info(\n \"LLM task arrived as a delta on an unknown base; asking for the full history\",\n );\n return { status: \"error\", error: \"message_cache_miss\" };\n }\n const model = task.model ?? \"?\";\n const tools = task.tools ?? [];\n this.#logger.info(\n `LLM call → ${model} (${task.messages?.length ?? 0} messages, ${tools.length} tools)`,\n );\n const result = await this.#callModel(task, signal);\n this.#logger.info(\n `LLM done → ${result.status === \"ok\" ? result.finish_reason : `error: ${result.error}`}`,\n );\n return result;\n }\n\n async #callModel(task: LlmTask, signal: AbortSignal): Promise<LlmResult> {\n try {\n const model = await this.#resolveModel(\n task.model ?? this.#agents[0]?.model ?? \"claude-sonnet-5\",\n );\n\n if (task.purpose === \"compact\") {\n // Fold the history into a summary Norns carries forward without reading.\n const result = await generateText({\n model,\n instructions: toInstructions(composeCompactionPrompt(task)),\n messages: toModelMessages(compactionMessages(task)),\n maxOutputTokens: maxTokens(task),\n abortSignal: signal,\n });\n const out = fromGenerateResult(result);\n return {\n status: \"ok\",\n content: out.content,\n finish_reason: \"stop\",\n usage: out.usage,\n model: out.model,\n };\n }\n\n // Norns sends the def's prompt verbatim and never writes prose for the\n // model: the worker composes the prompt, renders kinded messages,\n // elides old tool results, and decides the final output.\n const neutral = messagesForTask(task);\n const toolSet = toToolSet(task.tools ?? []);\n const result = await generateText({\n model,\n instructions: toInstructions(composeSystemPrompt(task)),\n messages: toModelMessages(neutral),\n tools: Object.keys(toolSet).length > 0 ? toolSet : undefined,\n maxOutputTokens: maxTokens(task),\n abortSignal: signal,\n });\n const out = fromGenerateResult(result);\n out.final_output = finalOutput(neutral, out.content);\n return out;\n } catch (err) {\n this.#logger.error(`LLM error: ${errorMessage(err)}`);\n return { status: \"error\", error: errorMessage(err) };\n }\n }\n\n async #runTool(task: ToolTask, signal: AbortSignal): Promise<ToolResult> {\n const name = task.tool_name ?? \"?\";\n this.#logger.info(`Tool call → ${name}`);\n const result = await this.#executeTool(task, signal);\n const preview = (result.status === \"ok\" ? result.result : result.error).slice(0, 80);\n this.#logger.info(`Tool done → ${name}: ${result.status} ${preview}`);\n return result;\n }\n\n // A key on the task means Norns considers the call side-effecting and has\n // named it. It cannot know whether the effect landed, so if the result\n // never reached it, it asks again; this worker answers from what it kept\n // rather than doing the thing twice.\n async #executeTool(task: ToolTask, signal: AbortSignal): Promise<ToolResult> {\n const key = task.idempotency_key;\n const completed = this.#completed;\n if (key && completed?.has(key)) {\n this.#logger.info(`Tool ${task.tool_name}: already done (${key}), reusing the result`);\n return completed.get(key) as ToolResult;\n }\n\n const tool = this.#tools.get(task.tool_name);\n if (!tool) return { status: \"error\", error: `Unknown tool: ${task.tool_name}` };\n\n let input: unknown = task.input ?? {};\n if (tool.validate) {\n const checked = await tool.validate(input);\n if (!checked.success) {\n return {\n status: \"error\",\n error: `Invalid input for ${tool.name}: ${checked.error.message}`,\n };\n }\n input = checked.value;\n }\n\n const context: ToolContext = {\n taskId: task.task_id,\n runId: task.run_id,\n agentId: task.agent_id,\n idempotencyKey: key,\n signal,\n worker: this,\n };\n\n try {\n const output = await tool.execute(input, context);\n const result: ToolResult = { status: \"ok\", result: stringifyToolOutput(output) };\n if (key) completed?.add(key, { ...result, duplicate: true });\n return result;\n } catch (err) {\n this.#logger.error(`Tool ${tool.name} failed: ${errorMessage(err)}`);\n // Failures are not remembered: a retry of something that did not happen should happen.\n return { status: \"error\", error: errorMessage(err) };\n }\n }\n\n // --- Lifecycle plumbing ---\n\n #abortInFlight(reason: string): void {\n for (const t of this.#inFlight) t.controller.abort(new NornsError(reason));\n }\n\n // Forced off: a fatal join, a destroyed gard. Nothing to drain.\n #fail(err: unknown): void {\n if (this.#state === \"stopped\") return;\n this.#state = \"stopped\";\n this.#abortInFlight(\"worker stopped\");\n this.#teardown();\n this.#socket?.disconnect();\n this.#settleStopped.reject(err);\n }\n\n #teardown(): void {\n if (this.#signalHandler) {\n process.off(\"SIGINT\", this.#signalHandler);\n process.off(\"SIGTERM\", this.#signalHandler);\n this.#signalHandler = undefined;\n }\n }\n\n #installSignalHandlers(): void {\n if (!this.#handleSignals) return;\n this.#signalHandler = (signal) => {\n if (this.#state !== \"running\") {\n this.#logger.warn(`Received ${signal} again: exiting now`);\n process.exit(130);\n }\n this.#logger.info(`Received ${signal}: shutting down`);\n void this.stop();\n };\n process.on(\"SIGINT\", this.#signalHandler);\n process.on(\"SIGTERM\", this.#signalHandler);\n }\n}\n","import { mkdirSync, readFileSync, renameSync, writeFileSync } from \"node:fs\";\nimport { tmpdir } from \"node:os\";\nimport { dirname, join } from \"node:path\";\nimport type { Logger } from \"./logger.js\";\n\nexport const MAX_REMEMBERED_RESULTS = 512;\n\n/**\n * What this worker has already done, by idempotency key.\n *\n * Kept on disk, because the case it exists for is the worker dying: Norns\n * re-dispatches the call it was holding, and a worker that came back with\n * an empty head would do the side effect a second time, which is the exact\n * thing the key is supposed to prevent.\n *\n * It is a crash guard, not a ledger. Bounded, best-effort, and never allowed\n * to take a worker down: if the file cannot be read or written, the worker\n * runs with memory alone and says so once.\n */\nexport class CompletedCalls {\n #path: string | undefined;\n readonly #limit: number;\n readonly #entries = new Map<string, Record<string, unknown>>();\n readonly #logger: Logger;\n\n constructor(path: string | undefined, logger: Logger, limit = MAX_REMEMBERED_RESULTS) {\n this.#path = path;\n this.#limit = limit;\n this.#logger = logger;\n this.#load();\n }\n\n get path(): string | undefined {\n return this.#path;\n }\n\n get size(): number {\n return this.#entries.size;\n }\n\n has(key: string): boolean {\n return this.#entries.has(key);\n }\n\n get(key: string): Record<string, unknown> | undefined {\n const entry = this.#entries.get(key);\n return entry ? { ...entry } : undefined;\n }\n\n add(key: string, result: Record<string, unknown>): void {\n this.#entries.delete(key);\n this.#entries.set(key, result);\n while (this.#entries.size > this.#limit) {\n const oldest = this.#entries.keys().next().value;\n if (oldest === undefined) break;\n this.#entries.delete(oldest);\n }\n this.#save();\n }\n\n #load(): void {\n if (!this.#path) return;\n let raw: string;\n try {\n raw = readFileSync(this.#path, \"utf8\");\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code !== \"ENOENT\") {\n this.#logger.warn(\n `Could not read ${this.#path} (${(err as Error).message}); starting with no memory of completed calls`,\n );\n }\n return;\n }\n try {\n const data = JSON.parse(raw) as Record<string, Record<string, unknown>>;\n for (const [key, value] of Object.entries(data)) {\n if (value && typeof value === \"object\") this.#entries.set(key, value);\n }\n } catch (err) {\n this.#logger.warn(\n `Could not parse ${this.#path} (${(err as Error).message}); starting with no memory of completed calls`,\n );\n }\n }\n\n #save(): void {\n if (!this.#path) return;\n try {\n mkdirSync(dirname(this.#path), { recursive: true });\n const tmp = `${this.#path}.tmp`;\n writeFileSync(tmp, JSON.stringify(Object.fromEntries(this.#entries)));\n renameSync(tmp, this.#path);\n } catch (err) {\n this.#logger.warn(\n `Could not write ${this.#path} (${(err as Error).message}); completed calls will not survive a restart`,\n );\n this.#path = undefined;\n }\n }\n}\n\n/**\n * Where a worker keeps what it has already done: `NORNS_STATE_DIR` if set\n * (empty disables), else a directory under the system temp dir. Enough to\n * outlive the process, which is the failure this guards, and nothing a\n * project has to clean up.\n */\nexport function completedCallsPath(\n workerId: string,\n stateDir: string | null | undefined,\n): string | undefined {\n const base = stateDir === undefined ? process.env.NORNS_STATE_DIR : stateDir;\n if (base === \"\" || base === null) return undefined;\n const root = base ?? join(tmpdir(), \"norns-worker-state\");\n const safe = workerId.replace(/[^A-Za-z0-9_.-]/g, \"_\").slice(0, 120);\n return join(root, `${safe}.completed.json`);\n}\n","/**\n * The provider-neutral wire format Norns speaks, and its translation to and\n * from the AI SDK. Also the prose the worker writes for the model: Norns\n * never does (\"Content is opaque\"), so composing the system prompt,\n * rendering kinded messages, eliding old tool results, and choosing the\n * run's final output all happen here.\n */\nimport {\n tool as aiTool,\n type FinishReason,\n type JSONSchema7,\n jsonSchema,\n type LanguageModelUsage,\n type ModelMessage,\n type SystemModelMessage,\n type ToolSet,\n} from \"ai\";\n\n// --- Wire types ---\n\nexport interface NeutralToolCall {\n id: string;\n name: string;\n arguments: unknown;\n}\n\nexport interface NeutralMessage {\n role: \"user\" | \"assistant\" | \"tool\" | \"system\";\n content?: unknown;\n tool_calls?: NeutralToolCall[];\n tool_call_id?: string;\n name?: string;\n is_error?: boolean;\n /** Set on messages Norns resolved itself; the worker renders them. */\n kind?: string;\n data?: Record<string, unknown>;\n}\n\nexport interface NeutralTool {\n name: string;\n description?: string;\n parameters?: JSONSchema7;\n input_schema?: JSONSchema7;\n}\n\nexport interface LlmTask {\n task_id: string;\n purpose?: \"compact\";\n model?: string;\n system_prompt?: string | null;\n summary?: string | null;\n date?: string | null;\n messages?: NeutralMessage[];\n /** In place of `messages` once this worker holds the run's history (see HistoryCache). */\n messages_delta?: { base_count: number; drop: number; append: NeutralMessage[] };\n tools?: NeutralTool[];\n context_policy?: unknown;\n max_tokens?: number | null;\n agent_id?: number;\n run_id?: number;\n step?: number;\n}\n\nexport interface ToolTask {\n task_id: string;\n tool_name: string;\n input?: Record<string, unknown>;\n agent_id?: number;\n run_id?: number;\n idempotency_key?: string;\n}\n\nexport interface Usage {\n input_tokens: number;\n output_tokens: number;\n cache_read_tokens?: number;\n cache_write_tokens?: number;\n}\n\nexport type NeutralFinishReason = \"stop\" | \"tool_call\" | \"length\" | \"error\";\n\nexport type LlmResult =\n | {\n status: \"ok\";\n content: string;\n finish_reason: NeutralFinishReason;\n usage: Usage;\n tool_calls?: NeutralToolCall[];\n model?: string;\n final_output?: string;\n }\n | { status: \"error\"; error: string };\n\nexport type ToolResult =\n | { status: \"ok\"; result: string; duplicate?: true }\n | { status: \"error\"; error: string };\n\n// --- Prompt composition ---\n\n/**\n * The prompt the model sees: the def's prompt verbatim, then the\n * conversation summary and the date the orchestrator put in the envelope.\n */\nexport function composeSystemPrompt(task: LlmTask): string {\n let prompt = task.system_prompt ?? \"\";\n if (typeof task.summary === \"string\" && task.summary !== \"\") {\n prompt += `\\n\\nSummary of earlier conversation: ${task.summary}`;\n }\n if (task.date) prompt += `\\n\\nCurrent date: ${task.date}.`;\n return prompt;\n}\n\n/** The def's prompt (so the summary is written in the agent's voice) plus the earlier summary. */\nexport function composeCompactionPrompt(task: LlmTask): string {\n let prompt = task.system_prompt ?? \"\";\n if (typeof task.summary === \"string\" && task.summary !== \"\") {\n prompt += `\\n\\nSummary of earlier conversation: ${task.summary}`;\n }\n return prompt;\n}\n\nexport const COMPACTION_INSTRUCTION =\n \"Write a summary of the conversation so far for your own future reference. \" +\n \"You will continue the same task with only this summary and the most recent \" +\n \"messages, so keep every fact you would need: the task and its constraints, \" +\n \"decisions made and why, files and identifiers touched, what was tried and \" +\n \"failed, what remains to be done, and anything the user asked for that is not \" +\n \"finished. Fold in the earlier summary if there is one. Write prose or terse \" +\n \"notes, no preamble, no commentary about summarising.\";\n\n/** The folded history, rendered, then the instruction. */\nexport function compactionMessages(task: LlmTask): NeutralMessage[] {\n return [\n ...renderMessages(task.messages ?? []),\n { role: \"user\", content: COMPACTION_INSTRUCTION },\n ];\n}\n\n// --- Kinded messages ---\n\n/** Render a message Norns resolved itself to plain content. Others pass through. */\nexport function renderMessage(msg: NeutralMessage): NeutralMessage {\n if (!msg.kind) return msg;\n const { kind, data, ...rest } = msg;\n return { ...rest, content: renderKind(kind, data ?? {}, msg.content) };\n}\n\nexport function renderMessages(messages: NeutralMessage[]): NeutralMessage[] {\n return messages.map(renderMessage);\n}\n\nfunction renderKind(kind: string, data: Record<string, unknown>, content: unknown): string {\n switch (kind) {\n case \"inherited_context\":\n return `[Inherited context from parent agent]\\n${encode(content)}`;\n case \"timer_completed\":\n return \"Timer completed.\";\n case \"tool_denied\":\n return `Tool '${data.tool_name}' is not in this agent's allowed tools.`;\n case \"subagent_denied\":\n if (data.reason === \"disabled\") return \"This agent is not permitted to launch sub-agents.\";\n if (data.reason === \"max_depth\") {\n return (\n `Sub-agent nesting limit reached (max depth ${data.max_depth}). ` +\n \"Do the work in this agent instead of delegating further.\"\n );\n }\n return `Agent '${data.agent_name}' is not in this agent's allowed sub-agents.`;\n case \"subagent_list_denied\":\n return \"Listing agents is not permitted for this agent.\";\n case \"subagent_not_found\":\n return `Agent '${data.agent_name}' not found`;\n case \"subagent_self\":\n return \"Cannot launch self as a sub-agent\";\n case \"subagent_missing\":\n return `Sub-agent run ${data.run_id} no longer exists, so its result cannot be recovered.`;\n case \"subagent_busy\":\n return (\n `Agent '${data.agent_name}' is still working on an earlier task for this ` +\n \"conversation. Wait for its result before giving it another.\"\n );\n case \"subagent_launch_failed\":\n return `Failed to launch agent '${data.agent_name}': ${data.reason}`;\n case \"subagent_completed\":\n return JSON.stringify({ run_id: data.run_id, status: \"completed\", output: content ?? \"\" });\n case \"subagent_failed\":\n return JSON.stringify({ run_id: data.run_id, status: \"failed\", error: content ?? \"\" });\n case \"list_agents\":\n return JSON.stringify(data.agents ?? []);\n default:\n return content === undefined || content === null || content === \"\"\n ? encode(data)\n : encode(content);\n }\n}\n\nfunction encode(value: unknown): string {\n return typeof value === \"string\" ? value : JSON.stringify(value ?? null);\n}\n\n// --- Context cost ---\n\n/** Chars kept of a tool result once it has aged out of the last two messages. */\nexport const TOOL_RESULT_CAP = 200;\n\n/** Rendered messages, elided unless Norns manages the context itself. */\nexport function messagesForTask(task: LlmTask): NeutralMessage[] {\n const rendered = renderMessages(task.messages ?? []);\n return task.context_policy ? rendered : elideOldToolResults(rendered);\n}\n\n/** Cap tool results older than the last two messages. */\nexport function elideOldToolResults(messages: NeutralMessage[]): NeutralMessage[] {\n if (messages.length <= 4) return messages;\n const old = messages.slice(0, -2);\n const recent = messages.slice(-2);\n return [\n ...old.map((msg) =>\n msg.role === \"tool\" && typeof msg.content === \"string\" && msg.content.length > TOOL_RESULT_CAP\n ? { ...msg, content: `${msg.content.slice(0, TOOL_RESULT_CAP)}...(truncated)` }\n : msg,\n ),\n ...recent,\n ];\n}\n\n/** One response's ceiling when the agent does not set one. */\nexport const DEFAULT_MAX_TOKENS = 8192;\n\nexport function maxTokens(task: LlmTask): number {\n const v = task.max_tokens;\n return typeof v === \"number\" && Number.isInteger(v) && v > 0 ? v : DEFAULT_MAX_TOKENS;\n}\n\n/**\n * The run's output when the model stops. A turn can say something\n * substantive alongside a tool call and then end with an empty \"stop\" turn;\n * fall back to the last non-empty assistant text rather than losing it.\n */\nexport function finalOutput(messages: NeutralMessage[], content: unknown): string {\n const text = typeof content === \"string\" ? content : \"\";\n if (text.trim() !== \"\") return text;\n for (let i = messages.length - 1; i >= 0; i--) {\n const m = messages[i];\n if (m?.role === \"assistant\" && typeof m.content === \"string\" && m.content.trim() !== \"\") {\n return m.content;\n }\n }\n return text;\n}\n\n// --- Neutral → AI SDK ---\n\nconst CACHE_CONTROL = { anthropic: { cacheControl: { type: \"ephemeral\" } } } as const;\n\n/**\n * The system prompt as the call's instructions, with a cache breakpoint:\n * a run's prompt is the same on every step. Providers that do not take the\n * hint ignore it.\n */\nexport function toInstructions(system: string): SystemModelMessage | undefined {\n if (system === \"\") return undefined;\n return { role: \"system\", content: system, providerOptions: CACHE_CONTROL };\n}\n\n/**\n * The model messages for a call. Consecutive tool results are folded into\n * one tool message, as providers expect them.\n *\n * The newest message carries a cache breakpoint: a run's history only\n * grows between steps, so this call's tail is the next call's prefix and is\n * read back at the cached rate.\n */\nexport function toModelMessages(messages: NeutralMessage[]): ModelMessage[] {\n const out: ModelMessage[] = [];\n\n for (const msg of messages) {\n const converted = toModelMessage(msg);\n const last = out[out.length - 1];\n if (converted.role === \"tool\" && last?.role === \"tool\") {\n last.content = [...last.content, ...converted.content];\n } else {\n out.push(converted);\n }\n }\n\n const last = out[out.length - 1];\n if (last) last.providerOptions = CACHE_CONTROL;\n return out;\n}\n\nfunction toModelMessage(msg: NeutralMessage): ModelMessage {\n switch (msg.role) {\n case \"system\":\n return { role: \"system\", content: encode(msg.content ?? \"\") };\n case \"assistant\": {\n const text = typeof msg.content === \"string\" ? msg.content : encode(msg.content ?? \"\");\n const calls = msg.tool_calls ?? [];\n if (calls.length === 0) return { role: \"assistant\", content: text };\n return {\n role: \"assistant\",\n content: [\n ...(text !== \"\" ? [{ type: \"text\" as const, text }] : []),\n ...calls.map((tc) => ({\n type: \"tool-call\" as const,\n toolCallId: tc.id,\n toolName: tc.name,\n input: parseArguments(tc.arguments),\n })),\n ],\n };\n }\n case \"tool\": {\n const value = encode(msg.content ?? \"\");\n return {\n role: \"tool\",\n content: [\n {\n type: \"tool-result\",\n toolCallId: msg.tool_call_id ?? \"\",\n toolName: msg.name ?? \"\",\n output: msg.is_error ? { type: \"error-text\", value } : { type: \"text\", value },\n },\n ],\n };\n }\n default:\n // An opaque block this worker holds no key for, or structured content:\n // send it encoded rather than fail the call.\n return { role: \"user\", content: encode(msg.content ?? \"\") };\n }\n}\n\nfunction parseArguments(args: unknown): unknown {\n if (typeof args !== \"string\") return args ?? {};\n try {\n return JSON.parse(args);\n } catch {\n return { raw: args };\n }\n}\n\n/** The tools the model is offered. None has an `execute`: the worker runs them on dispatch. */\nexport function toToolSet(tools: NeutralTool[]): ToolSet {\n const set: ToolSet = {};\n for (const t of tools) {\n set[t.name] = aiTool({\n description: t.description ?? \"\",\n inputSchema: jsonSchema(t.parameters ?? t.input_schema ?? { type: \"object\", properties: {} }),\n });\n }\n return set;\n}\n\n// --- AI SDK → Neutral ---\n\n/** The slice of a `generateText` result this translation reads. */\nexport interface GenerateLike {\n text: string;\n toolCalls: ReadonlyArray<{ toolCallId: string; toolName: string; input: unknown }>;\n finishReason: FinishReason;\n usage: LanguageModelUsage;\n response: { modelId: string };\n}\n\nexport function fromGenerateResult(result: GenerateLike): Extract<LlmResult, { status: \"ok\" }> {\n const out: Extract<LlmResult, { status: \"ok\" }> = {\n status: \"ok\",\n content: result.text ?? \"\",\n finish_reason: neutralFinishReason(result.finishReason, result.toolCalls.length > 0),\n usage: neutralUsage(result.usage),\n };\n // The model that served the call, so Norns can price it from the event.\n if (result.response?.modelId) out.model = result.response.modelId;\n if (result.toolCalls.length > 0) {\n out.tool_calls = result.toolCalls.map((tc) => ({\n id: tc.toolCallId,\n name: tc.toolName,\n arguments: tc.input ?? {},\n }));\n }\n return out;\n}\n\nfunction neutralFinishReason(reason: FinishReason, hasToolCalls: boolean): NeutralFinishReason {\n if (hasToolCalls) return \"tool_call\";\n switch (reason) {\n case \"tool-calls\":\n return \"tool_call\";\n case \"length\":\n return \"length\";\n case \"error\":\n return \"error\";\n default:\n return \"stop\";\n }\n}\n\n/**\n * Norns counts cache reads and writes inside `input_tokens` and wants to know\n * how many of each, since providers price them differently.\n */\nfunction neutralUsage(usage: LanguageModelUsage | undefined): Usage {\n const details = usage?.inputTokenDetails;\n const read = details?.cacheReadTokens ?? 0;\n const write = details?.cacheWriteTokens ?? 0;\n const total = usage?.inputTokens ?? 0;\n const noCache = details?.noCacheTokens;\n const input = noCache !== undefined ? Math.max(total, noCache + read + write) : total;\n\n const out: Usage = { input_tokens: input, output_tokens: usage?.outputTokens ?? 0 };\n if (read > 0) out.cache_read_tokens = read;\n if (write > 0) out.cache_write_tokens = write;\n return out;\n}\n","import type { LlmTask, NeutralMessage } from \"./format.js\";\n\n/**\n * The message list Norns last sent this worker, per run.\n *\n * Once a worker joins with `features: [\"message_cache\"]`, Norns sends a run's\n * later steps as the change since the last task on this connection:\n * `messages_delta: { base_count, drop, append }` — of the `base_count`\n * messages held, drop the first `drop`, append the rest. A delta against a\n * base this worker does not hold is a miss: the worker answers\n * `message_cache_miss` and Norns resends the whole list at the same step.\n * Bounded by run count; the run used longest ago goes first.\n */\nexport class HistoryCache {\n readonly #runs = new Map<number | string, NeutralMessage[]>();\n readonly #maxRuns: number;\n\n constructor(maxRuns = 256) {\n this.#maxRuns = maxRuns;\n }\n\n /** The task with `messages` filled in, or `undefined` on a miss. */\n resolve(task: LlmTask): LlmTask | undefined {\n // A prefix to summarise, not the history; leaves the cache alone.\n if (task.purpose === \"compact\") return task;\n\n const runId = task.run_id;\n const delta = task.messages_delta;\n\n if (delta === undefined) {\n if (runId !== undefined && Array.isArray(task.messages)) this.#remember(runId, task.messages);\n return task;\n }\n\n const previous = runId === undefined ? undefined : this.#runs.get(runId);\n if (runId === undefined || previous === undefined || previous.length !== delta.base_count) {\n return undefined;\n }\n\n const messages = [...previous.slice(delta.drop), ...delta.append];\n this.#remember(runId, messages);\n const resolved: LlmTask = { ...task, messages };\n delete resolved.messages_delta;\n return resolved;\n }\n\n /** Forget everything: a new connection gets the full history anyway. */\n clear(): void {\n this.#runs.clear();\n }\n\n /** How many runs are held; for tests. */\n get size(): number {\n return this.#runs.size;\n }\n\n #remember(runId: number | string, messages: NeutralMessage[]): void {\n this.#runs.delete(runId);\n this.#runs.set(runId, messages);\n while (this.#runs.size > this.#maxRuns) {\n const oldest = this.#runs.keys().next().value;\n if (oldest === undefined) break;\n this.#runs.delete(oldest);\n }\n }\n}\n"],"mappings":"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","names":["jsonSchema","res","Socket","jsonSchema","last","Socket","result","out","tool"]}
|