@dudousxd/nestjs-agent-opencode 0.0.0-stage → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +169 -2
- package/dist/durable/index.cjs +3138 -0
- package/dist/durable/index.cjs.map +1 -0
- package/dist/durable/index.d.cts +75 -0
- package/dist/durable/index.d.ts +75 -0
- package/dist/durable/index.js +3109 -0
- package/dist/durable/index.js.map +1 -0
- package/dist/engine-Bij6AdoF.d.cts +849 -0
- package/dist/engine-Bij6AdoF.d.ts +849 -0
- package/dist/index.cjs +2938 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +124 -0
- package/dist/index.d.ts +124 -0
- package/dist/index.js +2889 -0
- package/dist/index.js.map +1 -0
- package/package.json +93 -3
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/durable/index.ts","../../src/engine.ts","../../src/host.ts","../../src/mcp.controller.ts","../../src/tokens.ts","../../src/mcp.ts","../../src/turn.ts","../../src/forms.ts","../../src/runner.ts","../../src/turns.ts","../../src/event-hub.ts","../../src/durable/runner.ts","../../src/durable/workflow.ts"],"sourcesContent":["import type { AgentEngine } from '@dudousxd/nestjs-agent';\nimport { type OpenCodeEngineOptions, openCodeControllers, openCodeProviders } from '../engine.js';\nimport { OPENCODE_TURNS } from '../tokens.js';\nimport { OpenCodeTurns } from '../turns.js';\nimport { DurableOpenCodeAgentRunner } from './runner.js';\nimport { OpenCodeRunWorkflow } from './workflow.js';\n\n/**\n * `openCode()` whose turns are durable workflows — `AgentModule.forRoot({ engine:\n * openCodeDurable({ host }) })` next to a configured `DurableModule`. A turn waiting on a person\n * survives restarts and is resumed by whichever process receives the decision.\n */\nexport function openCodeDurable(options: OpenCodeEngineOptions): AgentEngine {\n return {\n name: 'opencode-durable',\n providers: [...openCodeProviders(options), OpenCodeRunWorkflow, DurableOpenCodeAgentRunner],\n runner: DurableOpenCodeAgentRunner,\n exports: [OpenCodeTurns, OPENCODE_TURNS],\n controllers: openCodeControllers(options),\n };\n}\n\nexport { DurableOpenCodeAgentRunner } from './runner.js';\nexport { OPENCODE_RUN_WORKFLOW, OpenCodeRunWorkflow, decisionToken } from './workflow.js';\n","import type { AgentEngine } from '@dudousxd/nestjs-agent';\nimport { type InjectionToken, Logger, type Provider, type Type } from '@nestjs/common';\nimport {\n InMemoryOpenCodeSessionStore,\n type OpenCodeHost,\n type OpenCodeSessionStore,\n} from './host.js';\nimport { OpenCodeMcpController } from './mcp.controller.js';\nimport { OpenCodeMcpEndpoint, OpenCodeToolsTokens } from './mcp.js';\nimport { OpenCodeAgentRunner } from './runner.js';\nimport {\n OPENCODE_HOST,\n OPENCODE_MCP_ENDPOINT,\n OPENCODE_OPTIONS,\n OPENCODE_SESSIONS,\n OPENCODE_TOOLS_TOKENS,\n OPENCODE_TURNS,\n} from './tokens.js';\nimport { type OpenCodeEngineSettings, OpenCodeTurns } from './turns.js';\n\nexport interface OpenCodeEngineOptions extends OpenCodeEngineSettings {\n /**\n * The host: an {@link OpenCodeHost} instance, or a provider class / token resolved from DI (so it\n * can inject the services that know where the server is and how to set sessions up). A class is\n * registered as a provider; a token must be provided by a module the agent module can see.\n */\n host: OpenCodeHost | Type<OpenCodeHost> | InjectionToken;\n /** Where each thread's session is kept. Same forms as `host`. Omit → in memory. */\n sessions?: OpenCodeSessionStore | Type<OpenCodeSessionStore> | InjectionToken;\n}\n\nfunction isInstance<T extends object>(value: unknown, method: keyof T): value is T {\n return typeof value === 'object' && value !== null && typeof (value as T)[method] === 'function';\n}\n\nfunction bind<T extends object>(\n token: symbol,\n value: T | Type<T> | InjectionToken,\n method: keyof T,\n): Provider[] {\n if (isInstance<T>(value, method)) return [{ provide: token, useValue: value }];\n if (typeof value === 'function') {\n return [value as Type<T>, { provide: token, useExisting: value }];\n }\n return [{ provide: token, useExisting: value }];\n}\n\n/**\n * Run the agent's turns on OpenCode 2 — `AgentModule.forRoot({ engine: openCode({ host }) })`.\n * The routes, threads, stream protocol, approvals and queue stay the library's; OpenCode runs the\n * model, the tools, skills and the context, on the server and sessions the host provides.\n */\nexport function openCode(options: OpenCodeEngineOptions): AgentEngine {\n return {\n name: 'opencode',\n providers: [...openCodeProviders(options), OpenCodeAgentRunner],\n runner: OpenCodeAgentRunner,\n exports: [OpenCodeTurns, OPENCODE_TURNS],\n controllers: openCodeControllers(options),\n };\n}\n\n/** The engine's own controllers: the tools endpoint, when `tools` is set. */\nexport function openCodeControllers(options: OpenCodeEngineSettings): Type<object>[] {\n return options.tools !== undefined ? [OpenCodeMcpController] : [];\n}\n\nconst DEFAULT_TOOLS_TTL_MS = 7 * 24 * 60 * 60_000;\n\nfunction toolsTokens(settings: OpenCodeEngineSettings): OpenCodeToolsTokens | null {\n const tools = settings.tools;\n if (tools === undefined) return null;\n if (tools.secret === undefined) {\n new Logger('OpenCodeEngine').warn(\n '`tools` has no `secret`: the tools endpoint signs its tokens with a per-process secret, so it only works with one process (and sessions lose their tools on a restart until their next turn).',\n );\n }\n return new OpenCodeToolsTokens(tools.secret, tools.ttlMs ?? DEFAULT_TOOLS_TTL_MS);\n}\n\n/** The providers every OpenCode engine needs: host, session store, settings and the turn steps. */\nexport function openCodeProviders(options: OpenCodeEngineOptions): Provider[] {\n const { host, sessions, ...settings } = options;\n return [\n ...bind<OpenCodeHost>(OPENCODE_HOST, host, 'server'),\n ...bind<OpenCodeSessionStore>(\n OPENCODE_SESSIONS,\n sessions ?? new InMemoryOpenCodeSessionStore(),\n 'get',\n ),\n { provide: OPENCODE_OPTIONS, useValue: settings },\n { provide: OPENCODE_TOOLS_TOKENS, useFactory: () => toolsTokens(settings) },\n OpenCodeTurns,\n { provide: OPENCODE_TURNS, useExisting: OpenCodeTurns },\n {\n provide: OPENCODE_MCP_ENDPOINT,\n useFactory: (turns: OpenCodeTurns, tokens: OpenCodeToolsTokens | null) =>\n tokens === null ? null : new OpenCodeMcpEndpoint(turns, tokens),\n inject: [OpenCodeTurns, OPENCODE_TOOLS_TOKENS],\n },\n ];\n}\n","import type {\n Actor,\n AgentRunInput,\n AgentUiComponent,\n StoredMessage,\n} from '@dudousxd/nestjs-agent-core';\nimport type { OpenCodeClient, OpenCodePromptFile, OpenCodeSessionCreate } from './client.js';\nimport type { PendingAsk, TurnOutcome } from './turn.js';\n\n/**\n * Where a turn runs and how its OpenCode session is set up — the part only the host knows. The\n * engine owns everything between the library and OpenCode (sessions per thread, the event stream,\n * the turn's frames, approvals and questions, cancel); the host answers these questions.\n */\nexport interface OpenCodeHost {\n /**\n * The OpenCode server this actor's turns run on — one per tenant in a sandbox, one for the whole\n * deployment, anything. Asked once per turn, so a server that restarted is picked up.\n */\n server(actor: Actor): Promise<OpenCodeServer>;\n\n /**\n * How to create a session for a thread: location, model, OpenCode agent, permission rules.\n * Asked only when the thread has no live session on this server (its first turn, or the server\n * restarted since). `input.model` is the model the caller picked for this turn, when it picked one.\n */\n session(context: OpenCodeTurnContext): Promise<OpenCodeSessionCreate>;\n\n /**\n * Instructions entries refreshed on every turn (key → text), on top of the agent's own prompt\n * (`@SystemPrompt` and the contributors, under `aviary.system`). Profile, memories, the project\n * a chat is about… An entry that disappears is not cleared: put an empty value to drop it.\n */\n instructions?(\n context: OpenCodeTurnContext & { sessionId: string },\n ): Promise<Record<string, string>>;\n\n /**\n * What the session is prompted with, when it is more than the user message: documents read into\n * the text, images as files the model can see. Omit → the user message, and `files`.\n */\n promptFor?(\n context: OpenCodeTurnContext & { sessionId: string },\n ): Promise<{ text: string; files?: OpenCodePromptFile[] }>;\n\n /**\n * The user message's attachments (`input.attachments`) in the form `session.prompt` takes them.\n * Omit → attachments are not sent to OpenCode. Not asked when `promptFor` answers.\n */\n files?(context: OpenCodeTurnContext): Promise<OpenCodePromptFile[]>;\n\n /**\n * Anything else to do on a NEW session before its first prompt — register MCP servers\n * (`client.mcp.add`), write skill files… Runs right after `session` and before `instructions`.\n */\n prepare?(\n context: OpenCodeTurnContext & { sessionId: string; client: OpenCodeClient },\n ): Promise<void>;\n\n /**\n * `openCodeDurable()` only: the turn's workflow start options (tags, search attributes, a\n * concurrency quota) — like `settings.durable.start`, from a host that has its services in DI.\n */\n startOptions?(input: AgentRunInput, runId: string): Promise<Record<string, unknown>>;\n\n /** `openCodeDurable()` only: what a refused start becomes (e.g. a concurrency limit → a 429). */\n startError?(error: unknown, input: AgentRunInput): unknown;\n\n /**\n * May this turn keep the thread's session? Asked when the session is still on its server; `false`\n * opens a new one (told the conversation so far) — e.g. the person the session's tools act for\n * changed. Omit → always reuse.\n */\n reuse?(context: OpenCodeTurnContext & { session: OpenCodeSessionRef }): Promise<boolean>;\n\n /**\n * Every turn, once the session is known (`created`: opened for this turn) and before the prompt:\n * bring it up to date — the turn's model, permission rules that changed, tools, skills.\n */\n beforePrompt?(\n context: OpenCodeTurnContext & { sessionId: string; client: OpenCodeClient; created: boolean },\n ): Promise<void>;\n\n /**\n * A person was asked something (an approval or a question form): post it where else they are —\n * a Slack thread, a Teams chat — or wake whoever waits on the run. May run again for the same ask\n * after a restart: make it idempotent.\n */\n onAsk?(context: OpenCodeTurnContext & { sessionId: string; ask: PendingAsk }): Promise<void>;\n\n /** A tool pushed a component into the run (`ctx.emitUi` over MCP). */\n onUi?(context: OpenCodeTurnContext & { component: AgentUiComponent }): Promise<void>;\n\n /**\n * The run is over and about to settle: the last word on the answer — components appended to it\n * (a guardrail notice), and for a failed run the error the person reads instead of OpenCode's.\n */\n beforeSettle?(result: OpenCodeRunResult): Promise<OpenCodeAmendment | undefined>;\n\n /**\n * The run settled (the stream ended, the thread moved on): deliver the answer elsewhere, record\n * spend and telemetry. Errors are logged, never the run's.\n */\n onSettled?(result: OpenCodeRunResult): Promise<void>;\n}\n\n/** What a run produced, as the host's settle hooks see it. */\nexport interface OpenCodeRunResult {\n runId: string;\n input: AgentRunInput;\n outcome: TurnOutcome;\n /** The run's answer: its assistant messages' text, in order. */\n text: string;\n /** The run's assistant messages, as stored. */\n messages: StoredMessage[];\n usage: { inputTokens: number; outputTokens: number; costUsd: number };\n durationMs: number;\n}\n\n/** See {@link OpenCodeHost.beforeSettle}. */\nexport interface OpenCodeAmendment {\n ui?: AgentUiComponent[];\n /** For a failed run: what the person reads. */\n error?: string;\n}\n\nexport interface OpenCodeServer {\n client: OpenCodeClient;\n /** Identifies the server across turns; sessions are only reused on the server that holds them. */\n key: string;\n /**\n * Changes whenever the server restarts and loses its sessions (a sandbox boot id). Omit for a\n * server whose sessions outlive restarts.\n */\n bootId?: string;\n}\n\nexport interface OpenCodeTurnContext {\n input: AgentRunInput;\n runId: string;\n}\n\n/** The session a thread talks to, and where it lives. */\nexport interface OpenCodeSessionRef {\n sessionId: string;\n serverKey: string;\n bootId?: string;\n /** The session's directory (`location.directory`), when it has one. */\n directory?: string;\n /**\n * The agent (and persona id) the thread's latest turn ran as — what the tools endpoint checks a\n * call against when it lands on a process that is not following the turn.\n */\n agentName?: string;\n persona?: string;\n}\n\n/**\n * Which OpenCode session each thread uses. The default keeps it in memory, which is enough for one\n * process; a deployment with several replicas (or that wants sessions to survive a restart of its\n * own) persists it — on the thread row, typically.\n */\nexport interface OpenCodeSessionStore {\n get(threadId: string): Promise<OpenCodeSessionRef | null>;\n set(threadId: string, ref: OpenCodeSessionRef): Promise<void>;\n}\n\nexport class InMemoryOpenCodeSessionStore implements OpenCodeSessionStore {\n private readonly refs = new Map<string, OpenCodeSessionRef>();\n\n async get(threadId: string): Promise<OpenCodeSessionRef | null> {\n return this.refs.get(threadId) ?? null;\n }\n\n async set(threadId: string, ref: OpenCodeSessionRef): Promise<void> {\n this.refs.set(threadId, ref);\n }\n}\n\n/** The two calls of a key-value store a session store needs — an ioredis or node-redis client fits. */\nexport interface OpenCodeKeyValue {\n get(key: string): Promise<string | null | undefined>;\n set(key: string, value: string): Promise<unknown>;\n}\n\n/**\n * Sessions kept in a shared key-value store (Redis…), so every process of a deployment finds the\n * session a thread already has — what running more than one process needs, alongside a\n * cross-process `TokenStreamSink`. Keys are `<prefix><threadId>`.\n */\nexport function keyValueOpenCodeSessionStore(\n kv: OpenCodeKeyValue,\n prefix = 'aviary:opencode:session:',\n): OpenCodeSessionStore {\n return {\n async get(threadId) {\n const raw = await kv.get(`${prefix}${threadId}`);\n if (raw === null || raw === undefined) return null;\n try {\n const ref = JSON.parse(raw) as OpenCodeSessionRef;\n return typeof ref.sessionId === 'string' && typeof ref.serverKey === 'string' ? ref : null;\n } catch {\n return null;\n }\n },\n async set(threadId, ref) {\n await kv.set(`${prefix}${threadId}`, JSON.stringify(ref));\n },\n };\n}\n","import type { IncomingMessage, ServerResponse } from 'node:http';\nimport { Body, Controller, Delete, Get, Inject, Post, Req, Res } from '@nestjs/common';\nimport type { OpenCodeMcpEndpoint } from './mcp.js';\nimport { OPENCODE_MCP_ENDPOINT } from './tokens.js';\n\nfunction notAllowed(res: ServerResponse): void {\n res.statusCode = 405;\n res.setHeader('allow', 'POST');\n res.setHeader('content-type', 'application/json');\n res.end(JSON.stringify({ error: 'method not allowed' }));\n}\n\n/**\n * `POST <agent path>/opencode/mcp` — the endpoint the engine registers in every OpenCode session\n * (`mcp.add`) when `tools` is set. It authenticates its callers itself (the bearer token the engine\n * minted for the session), so the module's `guards` are not applied to it. Stateless: no\n * server-sent stream to resume, no session to close.\n */\n@Controller('opencode/mcp')\nexport class OpenCodeMcpController {\n constructor(@Inject(OPENCODE_MCP_ENDPOINT) private readonly endpoint: OpenCodeMcpEndpoint) {}\n\n @Post()\n async post(\n @Req() req: IncomingMessage,\n @Res() res: ServerResponse,\n @Body() body: unknown,\n ): Promise<void> {\n await this.endpoint.handle(req, res, body);\n }\n\n @Get()\n get(@Res() res: ServerResponse): void {\n notAllowed(res);\n }\n\n @Delete()\n delete(@Res() res: ServerResponse): void {\n notAllowed(res);\n }\n}\n","// `Symbol.for`: the main and the `/durable` bundles each carry their own copy of this module (and of\n// the classes), so tokens must be the same symbol in both — a host resolves the engine's services\n// through these, never by class.\n\n/** The host's {@link import('./host.js').OpenCodeHost}. */\nexport const OPENCODE_HOST = Symbol.for('@dudousxd/nestjs-agent-opencode:host');\n/** Where each thread's session is kept ({@link import('./host.js').OpenCodeSessionStore}). */\nexport const OPENCODE_SESSIONS = Symbol.for('@dudousxd/nestjs-agent-opencode:sessions');\n/** The engine's {@link import('./turns.js').OpenCodeEngineSettings}. */\nexport const OPENCODE_OPTIONS = Symbol.for('@dudousxd/nestjs-agent-opencode:options');\n/**\n * The engine's turn steps ({@link import('./turns.js').OpenCodeTurns}): `callContext` for the MCP\n * surface, `pushToSession`, `liveRuns`. Inject this token, not the class — the class a host imports\n * from the main bundle is not the one `openCodeDurable()` (`/durable`) registers.\n */\nexport const OPENCODE_TURNS = Symbol.for('@dudousxd/nestjs-agent-opencode:turns');\n/** The engine's tools endpoint ({@link import('./mcp.js').OpenCodeMcpEndpoint}), when `tools` is set. */\nexport const OPENCODE_MCP_ENDPOINT = Symbol.for('@dudousxd/nestjs-agent-opencode:mcp-endpoint');\n/** Mints and checks the tools endpoint's bearer tokens ({@link import('./mcp.js').OpenCodeToolsTokens}). */\nexport const OPENCODE_TOOLS_TOKENS = Symbol.for('@dudousxd/nestjs-agent-opencode:tools-tokens');\n","import { createHash, createHmac, randomBytes, timingSafeEqual } from 'node:crypto';\nimport type { IncomingMessage, ServerResponse } from 'node:http';\nimport {\n type Actor,\n REMEMBER_TOOL_DESCRIPTION,\n REMEMBER_TOOL_NAME,\n type RememberToolInput,\n ToolNotFoundError,\n rememberInputSchema,\n schemaExtensionOf,\n} from '@dudousxd/nestjs-agent-core';\nimport { Server } from '@modelcontextprotocol/sdk/server/index.js';\nimport { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';\nimport type { AnyObjectSchema } from '@modelcontextprotocol/sdk/server/zod-compat.js';\nimport { toJsonSchemaCompat } from '@modelcontextprotocol/sdk/server/zod-json-schema-compat.js';\nimport type { Transport } from '@modelcontextprotocol/sdk/shared/transport.js';\nimport {\n CallToolRequestSchema,\n ListToolsRequestSchema,\n type Tool,\n} from '@modelcontextprotocol/sdk/types.js';\nimport type { StandardSchemaV1 } from '@standard-schema/spec';\nimport { errorText } from './turn.js';\nimport type { OpenCodeCallContext, OpenCodeTurns } from './turns.js';\n\n/** What a tools token says: whose turns it may serve, on which OpenCode server, until when. */\nexport interface OpenCodeToolsClaims {\n v: 1;\n actor: Actor;\n /** The OpenCode server key (`OpenCodeServer.key`) the token was registered on. */\n server: string;\n /** Epoch ms after which the token is refused. */\n exp: number;\n}\n\n/** Kinds the LOOP serves (delegation, `ask`, `skill`, `remember`): never served over MCP. */\nexport const LOOP_SERVED_KINDS: ReadonlySet<string> = new Set(['agent', 'ask', 'skill', 'memory']);\n\nconst b64url = (data: Buffer | string) => Buffer.from(data).toString('base64url');\n\n/**\n * Signs and checks the bearer tokens the engine registers its tools endpoint with (`mcp.add`). A\n * token names an actor and an OpenCode server, and expires; it is HMAC-SHA256 over its claims with\n * a key derived from `tools.secret`.\n *\n * A token on its own runs nothing: the endpoint also needs the call to come from a session that is\n * running a turn of that actor right now (see `OpenCodeTurns.callContext`), and an `action` tool\n * needs an approval the turn granted (see `OpenCodeTurns.spendApproval`).\n */\nexport class OpenCodeToolsTokens {\n private readonly key: Buffer;\n\n constructor(\n secret: string | undefined,\n readonly ttlMs: number,\n ) {\n this.key = createHash('sha256')\n .update('aviary:opencode:tools\\0')\n .update(secret ?? randomBytes(32).toString('hex'))\n .digest();\n }\n\n mint(actor: Actor, server: string, now = Date.now()): string {\n const claims: OpenCodeToolsClaims = { v: 1, actor, server, exp: now + this.ttlMs };\n const body = b64url(JSON.stringify(claims));\n return `${body}.${this.sign(body)}`;\n }\n\n verify(token: string, now = Date.now()): OpenCodeToolsClaims | null {\n const [body, signature, extra] = token.split('.');\n if (body === undefined || signature === undefined || extra !== undefined) return null;\n const expected = Buffer.from(this.sign(body));\n const given = Buffer.from(signature);\n if (expected.length !== given.length || !timingSafeEqual(expected, given)) return null;\n try {\n const claims = JSON.parse(Buffer.from(body, 'base64url').toString('utf8')) as\n | Partial<OpenCodeToolsClaims>\n | undefined;\n if (\n claims?.v !== 1 ||\n typeof claims.server !== 'string' ||\n typeof claims.exp !== 'number' ||\n typeof claims.actor?.id !== 'string' ||\n claims.exp <= now\n ) {\n return null;\n }\n return claims as OpenCodeToolsClaims;\n } catch {\n return null;\n }\n }\n\n private sign(body: string): string {\n return createHmac('sha256', this.key).update(body).digest('base64url');\n }\n}\n\n/** True for a Zod schema (its Standard Schema props say `vendor: 'zod'`). */\nfunction isZodSchema(schema: StandardSchemaV1): schema is StandardSchemaV1 & AnyObjectSchema {\n return schema['~standard'].vendor === 'zod';\n}\n\n/** A tool's input schema as the JSON Schema MCP clients read — as `AgentMcpServerModule` does. */\nfunction toInputSchema(schema: StandardSchemaV1): Tool['inputSchema'] {\n const extension = schemaExtensionOf(schema);\n if (extension !== undefined) {\n const base = toInputSchema(extension.base);\n const properties = { ...(base.properties ?? {}), ...extension.properties };\n return { ...base, properties: properties as Record<string, object> };\n }\n let converted: Record<string, unknown> | undefined;\n if (isZodSchema(schema)) converted = toJsonSchemaCompat(schema) as Record<string, unknown>;\n else {\n const converter = (schema['~standard'] as { jsonSchema?: { input?: unknown } }).jsonSchema;\n if (typeof converter?.input === 'function')\n converted = (converter.input as () => Record<string, unknown>)();\n }\n if (converted === undefined)\n return { type: 'object', properties: {}, additionalProperties: true };\n const { type: _type, ...rest } = converted;\n return { ...rest, type: 'object' } as Tool['inputSchema'];\n}\n\nconst asText = (output: unknown) => (typeof output === 'string' ? output : JSON.stringify(output));\n\n/** A call this endpoint will not run, said to the model as the tool's error. */\nexport class OpenCodeToolRefusedError extends Error {\n override readonly name = 'OpenCodeToolRefusedError';\n}\n\n/**\n * The MCP endpoint OpenCode sessions reach the module's tools through — `POST <agent path>/opencode/mcp`,\n * mounted by the engine when `tools` is set. Stateless Streamable HTTP (one server per request), so\n * any process answers.\n *\n * - `tools/list`: the registry's tools the token's actor may reach (roles, `enabled`, `canUse`), the\n * kinds only the loop serves left out; with `_meta` naming a running turn, its agent's (and\n * persona's) allow-list too. Plus `remember`, when the memory provider writes — served HERE only,\n * never registered in the module's shared registry.\n * - `tools/call`: only for a call `_meta` ties to a turn of the token's actor running on that\n * session, on the token's server; the turn's allow-list and the registry's own checks apply, an\n * `action` runs only against an approval the turn granted (one call per approval), and the tool's\n * `ctx` is the turn's (thread, run, `emitUi` into its stream and message).\n */\nexport class OpenCodeMcpEndpoint {\n constructor(\n private readonly turns: OpenCodeTurns,\n private readonly tokens: OpenCodeToolsTokens,\n ) {}\n\n /** The claims of a request's bearer token, or `null`. */\n authenticate(authorization: string | string[] | undefined): OpenCodeToolsClaims | null {\n const header = Array.isArray(authorization) ? authorization[0] : authorization;\n const match = /^Bearer\\s+(.+)$/i.exec(header ?? '');\n const token = match?.[1]?.trim();\n return token ? this.tokens.verify(token) : null;\n }\n\n async handle(req: IncomingMessage, res: ServerResponse, body: unknown): Promise<void> {\n const claims = this.authenticate(req.headers.authorization);\n if (claims === null) {\n res.statusCode = 401;\n res.setHeader('WWW-Authenticate', 'Bearer error=\"invalid_token\"');\n res.setHeader('content-type', 'application/json');\n res.end(JSON.stringify({ error: 'unauthorized' }));\n return;\n }\n const server = this.server(claims);\n // No `sessionIdGenerator`: stateless, so any process answers any request.\n const transport = new StreamableHTTPServerTransport({ enableJsonResponse: true });\n res.on('close', () => {\n void transport.close();\n void server.close();\n });\n try {\n await server.connect(transport as Transport);\n await transport.handleRequest(req, res, body);\n } catch (error) {\n if (!res.headersSent) {\n res.statusCode = 500;\n res.setHeader('content-type', 'application/json');\n res.end(\n JSON.stringify({\n jsonrpc: '2.0',\n error: { code: -32603, message: errorText(error, 'Internal error') },\n id: null,\n }),\n );\n }\n }\n }\n\n /** One MCP server for one request, answering as the token's actor. */\n server(claims: OpenCodeToolsClaims): Server {\n const server = new Server(\n { name: 'aviary-opencode', version: '1.0.0' },\n { capabilities: { tools: {} } },\n );\n const { actor } = claims;\n const call = (meta: unknown, requestId: unknown) =>\n this.turns.callContext({\n actor,\n serverKey: claims.server,\n requestId: String(requestId ?? ''),\n meta: meta as Readonly<Record<string, unknown>> | undefined,\n });\n\n server.setRequestHandler(ListToolsRequestSchema, async (request, extra) => {\n const turn = await call(request.params?._meta, extra.requestId);\n const input = turn?.input ?? {};\n const allowed = turn !== undefined ? this.turns.allowedTools(turn.input) : undefined;\n const definitions = (\n await this.turns.registry.definitionsFor(actor, this.turns.rolesPolicyFor(input), allowed)\n ).filter((definition) => !LOOP_SERVED_KINDS.has(definition.kind));\n const tools: Tool[] = definitions.map((definition) => ({\n name: definition.name,\n description: definition.description,\n inputSchema: toInputSchema(definition.inputSchema),\n annotations: { readOnlyHint: definition.kind === 'read' },\n }));\n if (this.turns.memoryWritable()) {\n tools.push({\n name: REMEMBER_TOOL_NAME,\n description: REMEMBER_TOOL_DESCRIPTION,\n inputSchema: toInputSchema(rememberInputSchema),\n annotations: { readOnlyHint: false },\n });\n }\n return { tools };\n });\n\n server.setRequestHandler(CallToolRequestSchema, async (request, extra) => {\n const { name, arguments: args } = request.params;\n try {\n const turn = await call(request.params._meta, extra.requestId);\n if (turn === undefined) {\n throw new OpenCodeToolRefusedError(\n 'This endpoint serves OpenCode turns: no turn of yours is running on this session.',\n );\n }\n const output =\n name === REMEMBER_TOOL_NAME && this.turns.memoryWritable()\n ? await this.remember(turn, args)\n : await this.invoke(turn, actor, name, args, String(extra.requestId ?? ''));\n return { content: [{ type: 'text' as const, text: asText(output) }] };\n } catch (error) {\n return {\n content: [{ type: 'text' as const, text: errorText(error, 'the tool failed') }],\n isError: true,\n };\n }\n });\n return server;\n }\n\n private async invoke(\n turn: OpenCodeCallContext,\n actor: Actor,\n name: string,\n args: unknown,\n requestId: string,\n ): Promise<unknown> {\n const { registry } = this.turns;\n const spec = registry.spec(name);\n if (spec === undefined || LOOP_SERVED_KINDS.has(spec.kind)) throw new ToolNotFoundError(name);\n const allowed = this.turns.allowedTools(turn.input);\n if (allowed !== undefined && !allowed.includes(name)) throw new ToolNotFoundError(name);\n if (spec.kind === 'action' && !(await this.turns.spendApproval(turn.runId, name, turn.input))) {\n throw new OpenCodeToolRefusedError(\n `\"${name}\" is an action and nobody approved this call; ask for the permission first.`,\n );\n }\n return registry.invoke(\n name,\n args ?? {},\n {\n actor,\n threadId: turn.ctx.threadId,\n runId: turn.runId,\n requestId: `mcp:${turn.runId}:${requestId}`,\n emitUi: turn.ctx.emitUi,\n ...(turn.input.agentName !== undefined ? { agentName: turn.input.agentName } : {}),\n ...(turn.input.persona !== undefined ? { persona: turn.input.persona } : {}),\n ...(turn.input.pageContext !== undefined ? { pageContext: turn.input.pageContext } : {}),\n },\n this.turns.rolesPolicyFor(turn.input),\n allowed !== undefined ? { allowedTools: allowed } : {},\n );\n }\n\n /** `remember`: one fact, at the actor's own scope only — as the loop serves it. */\n private async remember(turn: OpenCodeCallContext, args: unknown): Promise<string> {\n const parsed = await rememberInputSchema['~standard'].validate(args ?? {});\n if (parsed.issues !== undefined) {\n throw new OpenCodeToolRefusedError(\n `remember: ${parsed.issues.map((issue) => issue.message).join('; ')}`,\n );\n }\n return this.turns.remember(parsed.value as RememberToolInput, turn);\n }\n}\n","import {\n type AgentRunInput,\n type AgentStore,\n type AgentStreamEvent,\n type AgentUiComponent,\n type ApprovalRequirement,\n type Decision,\n type ElicitationReply,\n type ElicitationRequest,\n type HumanReply,\n type MessageUsage,\n type SinkWriter,\n type ToolCallRequest,\n type ToolResult,\n encodeStreamEvent,\n settleElicitation,\n} from '@dudousxd/nestjs-agent-core';\nimport { ConflictException, type Logger } from '@nestjs/common';\nimport type {\n OpenCodeClient,\n OpenCodeEvent,\n OpenCodeForm,\n OpenCodePermissionRequest,\n} from './client.js';\nimport { toElicitation, toFormAnswer } from './forms.js';\n\n/** How an OpenCode execution ended. */\nexport type TurnOutcome =\n | { status: 'succeeded' }\n | { status: 'failed'; error: string }\n | { status: 'interrupted' };\n\n/**\n * Something the turn put to a person, with everything needed to hand the answer back to OpenCode\n * later — serializable, so a durable run journals it and replies from another process.\n */\nexport type PendingAsk =\n | {\n kind: 'approval';\n /** The OpenCode permission request id — also the tool-call id the decision is signalled under. */\n id: string;\n action: string;\n approver: string;\n expiresAt?: string;\n /** The assistant message the call hangs on (absent for a request recovered after a restart). */\n messageId?: string;\n }\n | {\n kind: 'form';\n id: string;\n form: OpenCodeForm;\n request: ElicitationRequest;\n messageId?: string;\n };\n\n/** Where a turn stands: it needs a person, or it is over. */\nexport type Milestone =\n | { kind: 'ask'; ask: PendingAsk; timeoutMs?: number }\n | { kind: 'finished'; outcome: TurnOutcome };\n\nexport interface OpenCodeTurnArgs {\n runId: string;\n input: AgentRunInput;\n client: OpenCodeClient;\n sessionId: string;\n writer: SinkWriter;\n store: AgentStore;\n /** What an action needs before it runs (the module's `ApprovalPolicy`). */\n approvalFor: (action: string) => Promise<ApprovalRequirement>;\n /** The model label usage is recorded under. */\n modelLabel: string;\n logger: Logger;\n /**\n * An action OpenCode was allowed to run (a person approved it, or the policy did): the approval\n * the tools endpoint spends when OpenCode calls it. Called BEFORE OpenCode is told yes.\n */\n onGranted?: (action: string, permissionId: string) => void;\n}\n\nconst ASK_TOOL_NAME = 'ask';\nconst FAILED_STATUSES = new Set(['error', 'failed', 'denied', 'cancelled']);\n\ninterface ToolState {\n name: string;\n announced: boolean;\n available: boolean;\n settled: boolean;\n input: Record<string, unknown>;\n innerAnnounced: Set<number>;\n innerSettled: Set<number>;\n}\n\n/** One message's worth of the turn, persisted when a person is asked something and at the end. */\ninterface Segment {\n text: string;\n reasoning: string;\n reasoningMs: number;\n calls: ToolCallRequest[];\n results: ToolResult[];\n /** Components tools pushed (`ctx.emitUi`), last props per id. */\n ui: AgentUiComponent[];\n}\n\nfunction emptySegment(): Segment {\n return { text: '', reasoning: '', reasoningMs: 0, calls: [], results: [], ui: [] };\n}\n\nexport function isDecision(reply: HumanReply): reply is Decision {\n return typeof (reply as Decision).approved === 'boolean';\n}\n\n/**\n * Answers (a form reply, a skip) sent to a call waiting for an approve/reject. They say nothing\n * about whether the action should run — and treating them as a \"no\" would record a rejection the\n * person never made — so the reply is refused (409) and the call keeps waiting.\n */\nexport class OpenCodeReplyMismatchError extends ConflictException {\n constructor(\n readonly runId: string,\n readonly toolCallId: string,\n ) {\n super(\n `Tool call \"${toolCallId}\" on run \"${runId}\" is waiting for an approve/reject, not for answers`,\n );\n this.name = 'OpenCodeReplyMismatchError';\n }\n}\n\n/**\n * The arguments of the call a permission is about. OpenCode puts a built-in tool's arguments\n * straight in `metadata` (`webfetch` → `{ url, format }`); calls that wrap others nest them under\n * `input` or `args`.\n */\nfunction permissionArgs(req: OpenCodePermissionRequest): Record<string, unknown> {\n const metadata = req.metadata ?? {};\n const nested = metadata.input ?? metadata.args;\n if (nested !== null && typeof nested === 'object') return nested as Record<string, unknown>;\n return metadata;\n}\n\n/**\n * OpenCode tools the stream does not show as calls: the question tool IS the form, which streams as\n * an `elicitation` of its own.\n */\nconst HIDDEN_TOOLS = new Set(['question']);\n\nexport function errorText(error: unknown, fallback: string): string {\n if (typeof error === 'string' && error.length > 0) return error;\n const message = (error as { message?: unknown } | undefined)?.message;\n return typeof message === 'string' && message.length > 0 ? message : fallback;\n}\n\n/**\n * One turn of an OpenCode session, as the library's stream and store see it. Fed the session's\n * events in order, it writes the protocol's frames (`docs/stream-protocol.md`) and persists what the\n * loop would have — the assistant messages with their tool calls and results, the calls put to a\n * person (so the approve/answer routes find their run), usage per model step — and reports\n * {@link Milestone}s: a person was asked something, or the execution ended.\n *\n * The turn does not wait for people itself. Whoever drives it (`OpenCodeTurns`, under an in-memory\n * or a durable runner) takes the `ask` milestone, waits however it waits, and hands the answer back\n * with {@link decide} — which is what lets a durable run wait across a restart and reply from\n * another process, with a fresh turn object fed the journaled {@link PendingAsk}.\n */\nexport class OpenCodeTurn {\n /** Serializes the handling of events, so frames and rows land in the order OpenCode sent them. */\n private chain: Promise<void> = Promise.resolve();\n private segment = emptySegment();\n private readonly tools = new Map<string, ToolState>();\n /** Results already persisted per message, so a late settlement adds to them rather than replacing. */\n private readonly messageResults = new Map<string, ToolResult[]>();\n private readonly asked = new Set<string>();\n /** Calls of {@link HIDDEN_TOOLS}, by id. */\n private readonly hidden = new Set<string>();\n private readonly milestones: Milestone[] = [];\n private waiting: ((m: Milestone) => void) | undefined;\n private readonly usage: MessageUsage = { inputTokens: 0, outputTokens: 0 };\n private costUsd: number | undefined;\n private stepOpen = false;\n private sawText = false;\n private separator = false;\n private reasoningSince: number | undefined;\n private wroteMessage = false;\n private ended = false;\n private stepError: string | undefined;\n\n constructor(private readonly a: OpenCodeTurnArgs) {}\n\n get sessionId(): string {\n return this.a.sessionId;\n }\n\n get finished(): boolean {\n return this.ended;\n }\n\n /** Feed one of the session's events. */\n handle(event: OpenCodeEvent): void {\n this.enqueue(() => this.onEvent(event));\n }\n\n /** End the turn as failed without an event (the prompt was refused, the stream is gone). */\n fail(error: string): void {\n this.enqueue(() => this.end({ status: 'failed', error }));\n }\n\n /**\n * A component a tool pushed (`ctx.emitUi`, through the MCP surface): streamed as a `ui` frame and\n * persisted on the message being written, in the order it arrived. Pushing the same id again\n * replaces it.\n */\n pushUi(component: AgentUiComponent): Promise<void> {\n return new Promise((resolve, reject) => {\n this.chain = this.chain\n .then(async () => {\n await this.step();\n const ui = this.segment.ui;\n const at = ui.findIndex((c) => c.id === component.id);\n if (at >= 0) ui[at] = component;\n else ui.push(component);\n await this.write({ kind: 'ui', ...component });\n })\n .then(resolve, reject);\n });\n }\n\n /** The next milestone: one already reached, or the next one to come. */\n next(): Promise<Milestone> {\n const ready = this.milestones.shift();\n if (ready !== undefined) return Promise.resolve(ready);\n return new Promise((resolve) => {\n this.waiting = resolve;\n });\n }\n\n /** Whether a milestone is waiting to be taken. */\n hasMilestone(): boolean {\n return this.milestones.length > 0;\n }\n\n /**\n * Requests OpenCode raised while nobody listened (this process started after them, or the event\n * stream dropped): its open permissions and forms, handled as if their events had just arrived.\n * One already recorded in the store is reported without being recorded or streamed again.\n */\n async catchUp(): Promise<void> {\n const { client, sessionId } = this.a;\n const permissions = (await client.permission.list?.({ sessionID: sessionId })) ?? [];\n const forms = (await client.session.form.list?.({ sessionID: sessionId })) ?? [];\n await new Promise<void>((resolve) => {\n this.enqueue(async () => {\n for (const p of permissions) await this.onPermission(p, true);\n for (const f of forms) await this.onForm(f, true);\n resolve();\n });\n });\n }\n\n /**\n * Hand a person's answer to what the turn asked, and let OpenCode go on. `tellOpenCode: false`\n * only settles the call (stream and store): the request died with a restarted server, and the\n * new session is told the answer in its prompt instead.\n */\n decide(ask: PendingAsk, reply: HumanReply, opts: { tellOpenCode?: boolean } = {}): Promise<void> {\n const tell = opts.tellOpenCode ?? true;\n return new Promise((resolve, reject) => {\n this.chain = this.chain\n .then(() =>\n ask.kind === 'approval'\n ? this.decided(ask, reply, tell)\n : this.answered(ask, reply, tell),\n )\n .then(resolve, reject);\n });\n }\n\n private reach(milestone: Milestone): void {\n const waiting = this.waiting;\n if (waiting !== undefined) {\n this.waiting = undefined;\n waiting(milestone);\n } else {\n this.milestones.push(milestone);\n }\n }\n\n private enqueue(work: () => Promise<void>): void {\n this.chain = this.chain.then(work).catch((error: unknown) => {\n this.a.logger.error(`run ${this.a.runId}: ${errorText(error, 'event handling failed')}`);\n // A turn whose bookkeeping broke can't be trusted to finish on its own.\n if (!this.ended) {\n this.ended = true;\n this.reach({\n kind: 'finished',\n outcome: { status: 'failed', error: errorText(error, 'event handling failed') },\n });\n }\n });\n }\n\n private async write(event: AgentStreamEvent): Promise<void> {\n await this.a.writer.write(encodeStreamEvent(event));\n }\n\n private async step(): Promise<void> {\n if (this.stepOpen) return;\n this.stepOpen = true;\n await this.write({ kind: 'step-start' });\n }\n\n private endReasoning(): void {\n if (this.reasoningSince === undefined) return;\n this.segment.reasoningMs += Date.now() - this.reasoningSince;\n this.reasoningSince = undefined;\n }\n\n private tool(id: string, name = 'tool'): ToolState {\n let state = this.tools.get(id);\n if (state === undefined) {\n state = {\n name,\n announced: false,\n available: false,\n settled: false,\n input: {},\n innerAnnounced: new Set(),\n innerSettled: new Set(),\n };\n this.tools.set(id, state);\n this.segment.calls.push({ id, name, input: state.input, kind: 'read' });\n }\n return state;\n }\n\n private async announce(id: string, name: string): Promise<ToolState> {\n const state = this.tool(id, name);\n if (!state.announced) {\n state.announced = true;\n await this.write({ kind: 'tool-input-start', id, name: state.name, toolKind: 'read' });\n }\n return state;\n }\n\n private async makeAvailable(id: string): Promise<ToolState> {\n const state = await this.announce(id, this.tools.get(id)?.name ?? 'tool');\n if (!state.available) {\n state.available = true;\n await this.write({\n kind: 'tool-input-available',\n id,\n name: state.name,\n input: state.input,\n toolKind: 'read',\n });\n }\n return state;\n }\n\n private setInput(id: string, input: unknown, name?: string): void {\n const state = this.tool(id, name);\n if (input === null || typeof input !== 'object') return;\n Object.assign(state.input, input as Record<string, unknown>);\n }\n\n private async innerCalls(parentId: string, raw: unknown): Promise<void> {\n if (!Array.isArray(raw)) return;\n const parent = this.tool(parentId);\n for (const [index, call] of raw.entries()) {\n const id = `${parentId}.${index}`;\n const name = String(call?.tool ?? 'tool');\n const input =\n call?.input !== null && typeof call?.input === 'object'\n ? (call.input as Record<string, unknown>)\n : {};\n if (!parent.innerAnnounced.has(index)) {\n parent.innerAnnounced.add(index);\n this.segment.calls.push({ id, name, input, kind: 'read', parentId });\n await this.write({\n kind: 'tool-input-available',\n id,\n name,\n input,\n toolKind: 'read',\n parentId,\n });\n }\n const status = String(call?.status ?? '').toLowerCase();\n if (\n parent.innerSettled.has(index) ||\n status === 'running' ||\n status === 'pending' ||\n !status\n ) {\n continue;\n }\n parent.innerSettled.add(index);\n if (FAILED_STATUSES.has(status)) {\n this.segment.results.push({ id, name, output: { status }, error: status });\n await this.write({ kind: 'tool-output-error', id, error: status });\n } else {\n this.segment.results.push({ id, name, output: { status } });\n await this.write({ kind: 'tool-output', id, output: { status } });\n }\n }\n }\n\n private async onEvent(e: OpenCodeEvent): Promise<void> {\n if (this.ended) return;\n const d = e.data ?? {};\n switch (e.type) {\n case 'session.text.delta': {\n const delta = typeof d.delta === 'string' ? d.delta : '';\n if (!delta) return;\n this.endReasoning();\n // Whitespace before anything was said is noise.\n if (!this.sawText && !delta.trim()) return;\n await this.step();\n const text = this.separator && this.sawText ? `\\n\\n${delta}` : delta;\n this.separator = false;\n this.sawText = true;\n this.segment.text += text;\n await this.write({ kind: 'text', text });\n return;\n }\n case 'session.text.ended':\n // The next step's text starts a new paragraph.\n this.separator = true;\n return;\n case 'session.reasoning.delta': {\n const delta = typeof d.delta === 'string' ? d.delta : '';\n if (!delta) return;\n this.reasoningSince ??= Date.now();\n await this.step();\n this.segment.reasoning += delta;\n await this.write({ kind: 'reasoning', text: delta });\n return;\n }\n case 'session.tool.input.started':\n this.endReasoning();\n if (HIDDEN_TOOLS.has(String(d.name))) {\n this.hidden.add(String(d.id));\n return;\n }\n await this.step();\n await this.announce(String(d.id), String(d.name ?? 'tool'));\n return;\n case 'session.tool.called':\n if (this.hidden.has(String(d.id))) return;\n await this.step();\n this.setInput(String(d.id), d.input, typeof d.name === 'string' ? d.name : undefined);\n await this.makeAvailable(String(d.id));\n return;\n case 'session.skill.activated': {\n const name = String(d.id ?? d.name ?? 'skill');\n const id = `skill:${name}:${this.tools.size}`;\n await this.step();\n await this.announce(id, 'skill');\n this.setInput(id, { name });\n await this.makeAvailable(id);\n await this.settleTool(id, true);\n return;\n }\n case 'session.tool.progress':\n if (this.hidden.has(String(d.id))) return;\n await this.step();\n await this.makeAvailable(String(d.id));\n await this.innerCalls(String(d.id), d.metadata?.toolCalls);\n return;\n case 'session.tool.success':\n case 'session.tool.failed': {\n const id = String(d.id);\n if (this.hidden.has(id)) return;\n await this.step();\n await this.makeAvailable(id);\n await this.innerCalls(id, d.metadata?.toolCalls);\n await this.settleTool(\n id,\n e.type === 'session.tool.success',\n errorText(d.error, 'tool failed'),\n );\n return;\n }\n case 'session.step.ended':\n this.endReasoning();\n await this.stepEnded(d);\n return;\n case 'session.step.failed':\n this.stepError = errorText(d.error, 'the model call failed');\n return;\n case 'session.renamed':\n if (typeof d.title === 'string' && d.title.trim()) {\n await this.a.store.setTitle(this.a.input.threadId, d.title.trim());\n await this.write({ kind: 'title', title: d.title.trim() });\n }\n return;\n case 'permission.asked':\n await this.onPermission(d as OpenCodePermissionRequest, false);\n return;\n case 'form.created':\n await this.onForm((d.form ?? d) as OpenCodeForm, false);\n return;\n case 'session.execution.succeeded':\n await this.end({ status: 'succeeded' });\n return;\n case 'session.execution.failed':\n await this.end({\n status: 'failed',\n error: errorText(d.error, this.stepError ?? 'the execution failed'),\n });\n return;\n case 'session.execution.interrupted':\n await this.end({ status: 'interrupted' });\n return;\n default:\n return;\n }\n }\n\n private async settleTool(id: string, ok: boolean, error = 'failed'): Promise<void> {\n const state = this.tool(id);\n if (state.settled) return;\n state.settled = true;\n if (ok) {\n this.segment.results.push({ id, name: state.name, output: { ok: true } });\n await this.write({ kind: 'tool-output', id, output: { ok: true } });\n } else {\n this.segment.results.push({ id, name: state.name, output: { ok: false }, error });\n await this.write({ kind: 'tool-output-error', id, error });\n }\n }\n\n private async stepEnded(d: Record<string, any>): Promise<void> {\n const usage: MessageUsage = {\n inputTokens: Number(d.tokens?.input) || 0,\n outputTokens: Number(d.tokens?.output) || 0,\n ...(Number(d.tokens?.cache?.read) ? { cacheReadTokens: Number(d.tokens.cache.read) } : {}),\n ...(Number(d.tokens?.cache?.write) ? { cacheWriteTokens: Number(d.tokens.cache.write) } : {}),\n };\n const costUsd = typeof d.cost === 'number' ? d.cost : undefined;\n this.usage.inputTokens += usage.inputTokens;\n this.usage.outputTokens += usage.outputTokens;\n if (costUsd !== undefined) this.costUsd = (this.costUsd ?? 0) + costUsd;\n await this.a.store.recordUsage({\n threadId: this.a.input.threadId,\n actorRef: this.a.input.actor.id,\n modelId: this.a.modelLabel,\n purpose: 'chat',\n usage,\n ...(costUsd !== undefined ? { costUsd } : {}),\n });\n if (!this.stepOpen) return;\n this.stepOpen = false;\n await this.write({\n kind: 'step-finish',\n usage,\n costUsd: costUsd ?? null,\n ...(this.segment.reasoningMs > 0 ? { reasoningMs: this.segment.reasoningMs } : {}),\n model: this.a.modelLabel,\n });\n }\n\n /**\n * Persist what the turn produced since the last flush as one assistant message — the message a\n * call put to a person hangs on, or the turn's last one. Returns its id.\n */\n private async flush(final: boolean): Promise<string | undefined> {\n this.endReasoning();\n const s = this.segment;\n const empty = !s.text && !s.reasoning && s.calls.length === 0 && s.ui.length === 0;\n // A turn always leaves an answer behind, even an empty one, so the thread reads as answered.\n if (empty && !(final && !this.wroteMessage)) return undefined;\n this.segment = emptySegment();\n const message = await this.a.store.appendMessage({\n threadId: this.a.input.threadId,\n role: 'assistant',\n content: s.text,\n runId: this.a.runId,\n ...(final\n ? {\n usage: {\n ...this.usage,\n ...(this.costUsd !== undefined ? { costUsd: this.costUsd } : {}),\n },\n }\n : {}),\n ...(this.a.input.agentName !== undefined ? { agentName: this.a.input.agentName } : {}),\n ...(this.a.input.persona !== undefined ? { persona: this.a.input.persona } : {}),\n ...(s.reasoning ? { reasoning: s.reasoning, reasoningMs: s.reasoningMs } : {}),\n ...(s.calls.length > 0 ? { toolCalls: s.calls } : {}),\n ...(s.results.length > 0 ? { toolResults: s.results } : {}),\n ...(s.ui.length > 0 ? { ui: s.ui } : {}),\n });\n this.wroteMessage = true;\n this.messageResults.set(message.id, [...s.results]);\n return message.id;\n }\n\n /** A request recorded by an earlier process (a turn resumed after a restart). */\n private async alreadyRecorded(id: string): Promise<boolean> {\n return ((await this.a.store.toolCallApproval?.(id)) ?? null) !== null;\n }\n\n /** The persisted assistant message carrying call `id`, so its result lands on the same message. */\n private async messageOf(id: string): Promise<string | undefined> {\n const thread = await this.a.store.getThread(this.a.input.threadId);\n return thread?.messages.find((m) => m.toolCalls?.some((call) => call.id === id))?.id;\n }\n\n private async onPermission(req: OpenCodePermissionRequest, recovering: boolean): Promise<void> {\n if (this.asked.has(req.id)) return;\n this.asked.add(req.id);\n const { client, sessionId, input, store } = this.a;\n const action = String(req.action);\n const args = permissionArgs(req);\n\n if (recovering && (await this.alreadyRecorded(req.id))) {\n const state = await store.toolCallApproval?.(req.id);\n const messageId = await this.messageOf(req.id);\n this.reach({\n kind: 'ask',\n ask: {\n kind: 'approval',\n id: req.id,\n action,\n approver: state?.approver ?? 'requester',\n ...(state?.expiresAt ? { expiresAt: state.expiresAt } : {}),\n ...(messageId !== undefined ? { messageId } : {}),\n },\n ...(state?.expiresAt\n ? { timeoutMs: Math.max(0, Date.parse(state.expiresAt) - Date.now()) }\n : {}),\n });\n return;\n }\n\n await this.step();\n const requirement = await this.a.approvalFor(action);\n const remembered = requirement.required\n ? ((await store.rememberedApprovals?.(input.threadId)) ?? []).includes(action)\n : false;\n // No one needs to decide: the policy does not require it, or it was approved \"for this\n // conversation\" earlier. OpenCode asked because a rule said `ask`; the answer is yes.\n if (!requirement.required || remembered) {\n this.a.onGranted?.(action, req.id);\n await client.permission.reply({ sessionID: sessionId, requestID: req.id, decision: 'once' });\n this.segment.calls.push({ id: req.id, name: action, input: args, kind: 'action' });\n this.segment.results.push({ id: req.id, name: action, output: { approved: true } });\n await this.write({\n kind: 'tool-input-available',\n id: req.id,\n name: action,\n input: args,\n toolKind: 'action',\n });\n await this.write({\n kind: 'approval-settled',\n id: req.id,\n status: 'approved',\n approver: requirement.approver,\n decidedVia: remembered ? 'remembered' : 'policy',\n ...(remembered ? { remember: true } : {}),\n });\n await this.write({ kind: 'tool-output', id: req.id, output: { approved: true } });\n return;\n }\n\n const ttlMs =\n requirement.ttlMs !== undefined && Number.isFinite(requirement.ttlMs) && requirement.ttlMs > 0\n ? Math.floor(requirement.ttlMs)\n : undefined;\n const expiresAt = ttlMs !== undefined ? new Date(Date.now() + ttlMs).toISOString() : undefined;\n this.segment.calls.push({ id: req.id, name: action, input: args, kind: 'action' });\n const messageId = (await this.flush(false)) as string;\n await store.recordToolCall({\n toolCallId: req.id,\n messageId,\n toolName: action,\n toolType: 'action',\n input: args,\n status: 'pending_approval',\n runId: this.a.runId,\n approver: requirement.approver,\n ...(expiresAt !== undefined ? { expiresAt } : {}),\n });\n await this.write({\n kind: 'tool-input-available',\n id: req.id,\n name: action,\n input: args,\n toolKind: 'action',\n });\n await this.write({\n kind: 'approval-requested',\n id: req.id,\n approver: requirement.approver,\n ...(expiresAt !== undefined ? { expiresAt } : {}),\n });\n this.reach({\n kind: 'ask',\n ask: {\n kind: 'approval',\n id: req.id,\n action,\n approver: requirement.approver,\n messageId,\n ...(expiresAt !== undefined ? { expiresAt } : {}),\n },\n ...(ttlMs !== undefined ? { timeoutMs: ttlMs } : {}),\n });\n }\n\n private async decided(\n ask: Extract<PendingAsk, { kind: 'approval' }>,\n reply: HumanReply,\n tell: boolean,\n ) {\n // Answers are not a decision: the runners refuse them before they get here.\n if (!isDecision(reply)) throw new OpenCodeReplyMismatchError(this.a.runId, ask.id);\n const decision: Decision = reply;\n const { client, sessionId, store } = this.a;\n const { id, action } = ask;\n const status = decision.approved ? 'approved' : decision.expired ? 'expired' : 'rejected';\n if (decision.approved) this.a.onGranted?.(action, id);\n if (tell)\n await client.permission.reply({\n sessionID: sessionId,\n requestID: id,\n decision: decision.approved ? 'once' : 'reject',\n ...(decision.approved\n ? {}\n : {\n message: decision.expired\n ? 'Nobody approved this action in time, so it was not run.'\n : `The user denied this action${decision.reason ? `: ${decision.reason}` : ''}. Do not retry it; tell the user what you would have done.`,\n }),\n });\n const result: ToolResult = decision.approved\n ? { id, name: action, output: { approved: true } }\n : {\n id,\n name: action,\n output: { rejected: true, ...(decision.reason ? { reason: decision.reason } : {}) },\n error: decision.expired ? 'approval expired' : 'rejected by the user',\n denied: true,\n ...(decision.expired ? { expired: true } : {}),\n };\n await store.updateToolCall({\n toolCallId: id,\n status: decision.approved ? 'executed' : status === 'expired' ? 'expired' : 'rejected',\n output: result.output,\n ...(result.error !== undefined ? { error: result.error } : {}),\n ...(decision.executedByRef !== undefined ? { executedByRef: decision.executedByRef } : {}),\n ...(decision.remember === true ? { remember: true } : {}),\n ...(decision.decidedVia !== undefined ? { decidedVia: decision.decidedVia } : {}),\n });\n await this.addResult(ask.messageId, result);\n await this.write({\n kind: 'approval-settled',\n id,\n status,\n approver: ask.approver,\n ...(decision.executedByRef !== undefined ? { decidedBy: decision.executedByRef } : {}),\n ...(decision.decidedVia !== undefined ? { decidedVia: decision.decidedVia } : {}),\n ...(decision.remember === true ? { remember: true } : {}),\n ...(decision.reason !== undefined ? { reason: decision.reason } : {}),\n });\n if (decision.approved)\n await this.write({ kind: 'tool-output', id, output: { approved: true } });\n else\n await this.write({\n kind: 'tool-output-denied',\n id,\n ...(decision.expired\n ? { reason: 'approval expired' }\n : decision.reason\n ? { reason: decision.reason }\n : {}),\n });\n }\n\n private async onForm(form: OpenCodeForm, recovering: boolean): Promise<void> {\n if (this.asked.has(form.id)) return;\n this.asked.add(form.id);\n const request = toElicitation(form.id, form);\n if (recovering && (await this.alreadyRecorded(form.id))) {\n const messageId = await this.messageOf(form.id);\n this.reach({\n kind: 'ask',\n ask: {\n kind: 'form',\n id: form.id,\n form,\n request,\n ...(messageId !== undefined ? { messageId } : {}),\n },\n });\n return;\n }\n const input = {\n ...(request.preamble !== undefined ? { preamble: request.preamble } : {}),\n questions: request.questions,\n };\n await this.step();\n this.segment.calls.push({ id: form.id, name: ASK_TOOL_NAME, input, kind: 'ask' });\n const messageId = (await this.flush(false)) as string;\n // The store knows read/action only: a question waiting on a person is what `action` +\n // `pending_approval` already mean (the loop records its own questions the same way).\n await this.a.store.recordToolCall({\n toolCallId: form.id,\n messageId,\n toolName: ASK_TOOL_NAME,\n toolType: 'action',\n input,\n status: 'pending_approval',\n runId: this.a.runId,\n });\n await this.write({ kind: 'elicitation', id: form.id, request });\n this.reach({ kind: 'ask', ask: { kind: 'form', id: form.id, form, request, messageId } });\n }\n\n private async answered(\n ask: Extract<PendingAsk, { kind: 'form' }>,\n reply: HumanReply,\n tell: boolean,\n ) {\n const { client, sessionId } = this.a;\n const { form, request } = ask;\n const answer: ElicitationReply = isDecision(reply) ? { answers: {}, skipped: true } : reply;\n if (!tell) {\n // The form died with the server; the new session is told the answer.\n } else if (answer.skipped === true) {\n await client.session.form.cancel({ sessionID: sessionId, formID: form.id });\n } else {\n await client.session.form.reply({\n sessionID: sessionId,\n formID: form.id,\n answer: toFormAnswer(form, answer.answers),\n });\n }\n const result = settleElicitation(request, answer);\n await this.a.store.updateToolCall({\n toolCallId: form.id,\n status: result.skipped ? 'rejected' : 'executed',\n output: result,\n ...(result.skipped ? { error: 'skipped by the user' } : {}),\n ...(answer.answeredByRef !== undefined ? { executedByRef: answer.answeredByRef } : {}),\n ...(answer.answeredVia !== undefined ? { decidedVia: answer.answeredVia } : {}),\n });\n await this.addResult(ask.messageId, { id: form.id, name: ASK_TOOL_NAME, output: result });\n await this.write({ kind: 'tool-output', id: form.id, output: result });\n }\n\n private async addResult(messageId: string | undefined, result: ToolResult): Promise<void> {\n if (messageId === undefined) return;\n // A message persisted by an earlier process: its results are in the store, not in this map.\n let known = this.messageResults.get(messageId);\n if (known === undefined) {\n const thread = await this.a.store.getThread(this.a.input.threadId);\n known = [...(thread?.messages.find((m) => m.id === messageId)?.toolResults ?? [])];\n }\n const results = [...known.filter((r) => r.id !== result.id), result];\n this.messageResults.set(messageId, results);\n await this.a.store.setMessageToolResults(messageId, results);\n }\n\n private async end(outcome: TurnOutcome): Promise<void> {\n if (this.ended) return;\n this.ended = true;\n if (\n outcome.status !== 'failed' ||\n this.segment.text ||\n this.segment.calls.length > 0 ||\n this.segment.ui.length > 0\n ) {\n await this.flush(true);\n }\n if (this.stepOpen) {\n this.stepOpen = false;\n await this.write({ kind: 'step-finish' });\n }\n this.reach({ kind: 'finished', outcome });\n }\n}\n","import {\n type ElicitationQuestion,\n type ElicitationRequest,\n validateElicitationAnswer,\n} from '@dudousxd/nestjs-agent-core';\nimport type { OpenCodeForm, OpenCodeFormField, OpenCodeFormValue } from './client.js';\n\n/** An OpenCode form field as a stream-protocol question (`docs/stream-protocol.md`, *Asking the user*). */\nexport function toQuestion(field: OpenCodeFormField): ElicitationQuestion {\n const required = field.required === true ? { required: true } : {};\n const base = {\n id: field.key,\n prompt: field.title || field.key,\n ...(field.description && field.description !== field.title\n ? { description: field.description }\n : {}),\n };\n if (field.options !== undefined && field.options.length > 0) {\n return {\n ...base,\n options: field.options.map((o) => ({\n value: String(o.value),\n label: String(o.label ?? o.value),\n })),\n input: { type: 'select', ...required },\n ...(field.type === 'array' ? { multiple: true } : {}),\n ...(field.custom === true ? { allowFreeText: true } : {}),\n };\n }\n const type =\n field.type === 'number' || field.type === 'integer'\n ? 'number'\n : field.type === 'boolean'\n ? 'boolean'\n : 'text';\n return { ...base, input: { type, ...required } };\n}\n\n/** The fields of a form, skipping anything that is not one. */\nexport function formFields(form: Pick<OpenCodeForm, 'fields'>): OpenCodeFormField[] {\n return (form.fields ?? []).filter(\n (f): f is OpenCodeFormField => typeof f === 'object' && f !== null && typeof f.key === 'string',\n );\n}\n\n/** The elicitation an OpenCode form streams as, under `id` (the tool-call id it is answered through). */\nexport function toElicitation(id: string, form: OpenCodeForm): ElicitationRequest {\n const questions = formFields(form).map(toQuestion);\n const first = questions[0];\n // OpenCode titles a one-question form after the question (or just \"Questions\"): not a preamble.\n const title = form.title;\n const preamble =\n title && title !== 'Questions' && title !== first?.prompt && title !== first?.description\n ? title\n : undefined;\n return { id, source: 'ask', ...(preamble ? { preamble } : {}), questions };\n}\n\nexport class FormAnswerError extends Error {}\n\n/**\n * The protocol's answers (question id → canonical strings) as OpenCode's form reply: numbers as\n * numbers, booleans as booleans, multiple choice as a list. Questions left out take their defaults;\n * a value a question can't take throws {@link FormAnswerError}.\n */\nexport function toFormAnswer(\n form: OpenCodeForm,\n answers: Record<string, string[]> = {},\n): Record<string, OpenCodeFormValue> {\n const out: Record<string, OpenCodeFormValue> = {};\n for (const field of formFields(form)) {\n const question = toQuestion(field);\n const values = answers[field.key] ?? question.defaults ?? [];\n const problem = validateElicitationAnswer(question, values);\n if (problem) throw new FormAnswerError(`answers[\"${field.key}\"] ${problem}`);\n const present = values.filter((v) => v !== '');\n const [value] = present;\n if (value === undefined) continue;\n if (question.multiple) out[field.key] = present;\n else if (question.input?.type === 'number') out[field.key] = Number(value);\n else if (question.input?.type === 'boolean') out[field.key] = value === 'true';\n else out[field.key] = value;\n }\n return out;\n}\n","import {\n type AgentRunInput,\n type AgentRunStartOptions,\n type AgentRunner,\n type Decision,\n type HumanReply,\n RunCancelledError,\n} from '@dudousxd/nestjs-agent-core';\nimport { Inject, Injectable } from '@nestjs/common';\nimport { OPENCODE_OPTIONS } from './tokens.js';\nimport { OpenCodeReplyMismatchError, errorText, isDecision } from './turn.js';\nimport { type OpenCodeEngineSettings, OpenCodeTurns } from './turns.js';\n\n/**\n * Runs OpenCode turns in this process: `begin → prompt → [observe → wait for a person → reply]* →\n * settle`, with the waits on people held in memory. Like `InlineAgentRunner`, a run parked on a\n * person lives in this process, so deploy it single-replica — or use `openCodeDurable()`\n * (`@dudousxd/nestjs-agent-opencode/durable`), which checkpoints every step and waits on a durable\n * signal.\n */\n@Injectable()\nexport class OpenCodeAgentRunner implements AgentRunner {\n private readonly live = new Set<string>();\n private readonly cancelled = new Set<string>();\n private readonly pending = new Map<\n string,\n {\n on: 'approval' | 'answers';\n resolve: (reply: HumanReply) => void;\n reject: (error: unknown) => void;\n }\n >();\n\n constructor(\n private readonly turns: OpenCodeTurns,\n @Inject(OPENCODE_OPTIONS) private readonly settings: OpenCodeEngineSettings,\n ) {\n turns.startNext = (next, runId) => this.start(next, { runId });\n }\n\n runIdFor(input: AgentRunInput): string {\n return this.settings.runId?.(input) ?? crypto.randomUUID();\n }\n\n async isRunActive(runId: string): Promise<boolean> {\n if (this.live.has(runId)) return true;\n for (const key of this.pending.keys()) if (key.startsWith(`${runId}:`)) return true;\n return false;\n }\n\n async start(\n input: AgentRunInput,\n options: AgentRunStartOptions = {},\n ): Promise<{ runId: string }> {\n const runId = options.runId ?? this.runIdFor(input);\n this.live.add(runId);\n void this.run(runId, input).finally(() => {\n this.live.delete(runId);\n this.cancelled.delete(runId);\n for (const key of [...this.pending.keys()])\n if (key.startsWith(`${runId}:`)) this.pending.delete(key);\n });\n return { runId };\n }\n\n /**\n * Deliver a person's reply. Answers addressed at an approval are refused\n * ({@link OpenCodeReplyMismatchError}, a 409) and the approval keeps waiting: they say nothing\n * about whether the action should run.\n */\n async signal(runId: string, toolCallId: string, reply: HumanReply): Promise<void> {\n const key = `${runId}:${toolCallId}`;\n const waiter = this.pending.get(key);\n if (waiter === undefined) return;\n if (waiter.on === 'approval' && !isDecision(reply)) {\n throw new OpenCodeReplyMismatchError(runId, toolCallId);\n }\n this.pending.delete(key);\n waiter.resolve(reply);\n }\n\n /**\n * Stop the run: what it waits on a person for is dropped, and OpenCode is interrupted — it answers\n * `session.execution.interrupted`, which settles the run as cancelled.\n */\n async cancel(runId: string): Promise<void> {\n this.cancelled.add(runId);\n for (const [key, waiter] of [...this.pending]) {\n if (!key.startsWith(`${runId}:`)) continue;\n this.pending.delete(key);\n waiter.reject(new RunCancelledError());\n }\n const input = this.inputs.get(runId);\n if (input !== undefined) await this.turns.interrupt(input).catch(() => undefined);\n }\n\n private readonly inputs = new Map<string, AgentRunInput>();\n\n private async run(runId: string, input: AgentRunInput): Promise<void> {\n const started = Date.now();\n this.inputs.set(runId, input);\n try {\n let handle = await this.turns.begin(runId, input);\n if (this.cancelled.has(runId)) throw new RunCancelledError();\n await this.turns.prompt(runId, input, handle);\n for (;;) {\n const milestone = await this.turns.observe(runId, input, handle);\n if (milestone.kind === 'finished') {\n await this.turns.settle(runId, input, milestone.outcome, Date.now() - started);\n return;\n }\n const reply = await this.park(\n runId,\n milestone.ask.id,\n milestone.ask.kind === 'approval' ? 'approval' : 'answers',\n milestone.timeoutMs,\n );\n handle = await this.turns.reply(runId, input, handle, milestone.ask, reply);\n }\n } catch (error) {\n if (error instanceof RunCancelledError) {\n await this.turns.interrupt(input).catch(() => undefined);\n await this.turns.settle(runId, input, { status: 'interrupted' }, Date.now() - started);\n return;\n }\n await this.turns.settleFailed(runId, input, errorText(error, 'the turn failed'));\n } finally {\n this.inputs.delete(runId);\n }\n }\n\n /** Wait for a person's answer; a lapsed approval answers itself as expired. */\n private park(\n runId: string,\n toolCallId: string,\n on: 'approval' | 'answers',\n timeoutMs?: number,\n ): Promise<HumanReply> {\n const key = `${runId}:${toolCallId}`;\n const waiting = new Promise<HumanReply>((resolve, reject) => {\n this.pending.set(key, { on, resolve, reject });\n });\n if (timeoutMs === undefined) return waiting;\n let timer: ReturnType<typeof setTimeout> | undefined;\n const lapse = new Promise<Decision>((resolve) => {\n timer = setTimeout(() => {\n if (!this.pending.has(key)) return;\n this.pending.delete(key);\n resolve({ approved: false, expired: true });\n }, timeoutMs);\n timer.unref?.();\n });\n return Promise.race([waiting, lapse]).finally(() => clearTimeout(timer));\n }\n}\n","import { randomUUID } from 'node:crypto';\nimport {\n AGENT_CHAT_QUEUE,\n type AgentDepsFactory,\n type ChatQueueService,\n} from '@dudousxd/nestjs-agent';\nimport {\n AGENT_DEPS_FACTORY,\n AGENT_MEMORY,\n AGENT_SINK,\n AGENT_SKILLS,\n AGENT_STORE,\n AGENT_TOOL_REGISTRY,\n type Actor,\n type AgentRunInput,\n type AgentStore,\n type AgentUiComponent,\n type AiToolCtx,\n type ApprovalRequirement,\n DEFAULT_MAX_FACT_CHARS,\n DefaultApprovalPolicy,\n type HumanReply,\n type MemoryConfig,\n type PromptContext,\n RUN_ENDED_BEFORE_TOOL_CALL,\n type RememberToolInput,\n type RolesPolicy,\n type ScopeContext,\n type SkillsConfig,\n type StoredMessage,\n type TokenStreamSink,\n type ToolRegistry,\n actorScope,\n buildMemoryBlock,\n defaultScopeResolver,\n encodeStreamEvent,\n memoryWriteVerdict,\n publishAgentRunFailed,\n releaseThreadRun,\n resolveMemoryDigest,\n resolveSkillCatalog,\n streamFailure,\n} from '@dudousxd/nestjs-agent-core';\nimport { Inject, Injectable, Logger, type OnApplicationShutdown, Optional } from '@nestjs/common';\nimport type { OpenCodeClient, OpenCodePermissionRule } from './client.js';\nimport { OpenCodeEventHub } from './event-hub.js';\nimport type {\n OpenCodeAmendment,\n OpenCodeHost,\n OpenCodeRunResult,\n OpenCodeServer,\n OpenCodeSessionRef,\n OpenCodeSessionStore,\n} from './host.js';\nimport { LOOP_SERVED_KINDS, type OpenCodeToolsTokens } from './mcp.js';\nimport {\n OPENCODE_HOST,\n OPENCODE_OPTIONS,\n OPENCODE_SESSIONS,\n OPENCODE_TOOLS_TOKENS,\n} from './tokens.js';\nimport {\n type Milestone,\n OpenCodeTurn,\n type PendingAsk,\n type TurnOutcome,\n errorText,\n} from './turn.js';\n\n/**\n * The module's `@AiTool`s, served to sessions over the engine's own MCP endpoint\n * (`POST <agent path>/opencode/mcp`, mounted by the engine — not `AgentMcpServerModule`).\n */\nexport interface OpenCodeToolsOptions {\n /**\n * The URL the OpenCode server calls that endpoint at, passed to it verbatim (no default, nothing\n * derived). It is resolved from where OpenCode runs, not from the app: e.g.\n * `http://127.0.0.1:3000/agent/opencode/mcp` on the same machine, the app's Compose service or\n * Kubernetes Service name otherwise. `/agent` is `AgentModule`'s `path`; it must reach a process\n * that mounts controllers (not `surface: 'engine'`).\n */\n url: string;\n /** The MCP server's name in OpenCode; its tools are `<server>.<tool>` / `<server>_<tool>`. Default `'aviary'`. */\n server?: string;\n /**\n * The secret the endpoint's bearer tokens are signed with — the same in every process that serves\n * the agent. Omit → a random per-process secret (one process only; a warning says so).\n */\n secret?: string;\n /**\n * How long a token OpenCode is given stays valid. A token only ever reaches a turn of its own\n * actor that is running on the session that calls, and it is re-issued on a kept session's turns\n * once it is half-way through. Default 7 days.\n */\n ttlMs?: number;\n}\n\nexport interface OpenCodeEngineSettings {\n /** The id a run gets (e.g. a tenant prefix your durable store partitions by). Default: a random UUID. */\n runId?: (input: AgentRunInput) => string;\n /**\n * `openCodeDurable()` only: how each turn's workflow run starts — tags, search attributes, a\n * concurrency quota (`WorkflowService.start` options) — and what a refused start becomes (e.g. a\n * concurrency limit → a 429 for the person sending).\n */\n durable?: {\n start?: (\n input: AgentRunInput,\n runId: string,\n ) => Record<string, unknown> | Promise<Record<string, unknown>>;\n startError?: (error: unknown, input: AgentRunInput) => unknown;\n };\n /** How many earlier messages a NEW session is told about (a thread whose session was lost). Default 20. */\n historyMessages?: number;\n /** The instructions key the agent's own prompt is put under. Default `'aviary.system'`. */\n systemKey?: string;\n /** Serve the module's `@AiTool`s to the sessions. Omit → the session has the host's tools only. */\n tools?: OpenCodeToolsOptions;\n /** Where skills are written, relative to the session's directory. Default `'.opencode/skills'`. */\n skillsDir?: string;\n /**\n * How long `observe` waits for a milestone before failing the turn. Default 30 minutes. A turn\n * parked on a person is not observing: this bounds one stretch of OpenCode working on its own.\n */\n turnTimeoutMs?: number;\n}\n\n/** A thread's session, as the steps of a turn pass it along (and a durable run journals it). */\nexport interface SessionHandle {\n sessionId: string;\n serverKey: string;\n bootId?: string;\n directory?: string;\n}\n\n/** What the engine's MCP endpoint tells the turns about the call it is serving. */\nexport interface OpenCodeToolCall {\n actor: Actor;\n /** The OpenCode server the endpoint's token was issued for. */\n serverKey: string;\n /** The MCP request id, so two calls' unnamed components stay apart. */\n requestId?: string;\n /** The call's `_meta` — OpenCode names its session there (`ai.opencode/sessionID`). */\n meta: Readonly<Record<string, unknown>> | undefined;\n}\n\n/** The turn a tool call over MCP belongs to — see {@link OpenCodeTurns.callContext}. */\nexport interface OpenCodeCallContext {\n input: AgentRunInput;\n runId: string;\n ctx: Pick<AiToolCtx, 'threadId' | 'runId' | 'emitUi'>;\n}\n\ninterface LiveTurn {\n turn: OpenCodeTurn;\n input: AgentRunInput;\n handle: SessionHandle;\n client: OpenCodeClient;\n stop: () => void;\n}\n\n/** One action OpenCode was allowed to run in a run: an approval the MCP endpoint may spend. */\ninterface Grant {\n id: string;\n action: string;\n}\n\nconst DEFAULT_TURN_TIMEOUT_MS = 30 * 60_000;\nconst DEFAULT_TOOLS_TTL_MS = 7 * 24 * 60 * 60_000;\n\n/**\n * The steps of an OpenCode turn — `begin` (thread, session, instructions), `prompt`, `observe`\n * (until a person is asked something or the execution ends), `reply`, `settle` — so an in-memory\n * runner can run them in a row and a durable one can checkpoint each. A step may run in a process\n * that did not run the one before (a durable run resumed elsewhere): the live turn is rebuilt from\n * the session, catching up on what OpenCode asked while nobody listened.\n */\n@Injectable()\nexport class OpenCodeTurns implements OnApplicationShutdown {\n private readonly logger = new Logger('OpenCodeTurns');\n private readonly events = new OpenCodeEventHub();\n private readonly live = new Map<string, LiveTurn>();\n /** Actions approved per run, and the approvals the MCP endpoint already spent. */\n private readonly grants = new Map<string, Grant[]>();\n private readonly spent = new Set<string>();\n /** When the tools endpoint was last registered for a location (`server|boot|directory|actor`). */\n private readonly toolsIssued = new Map<string, number>();\n\n constructor(\n @Inject(OPENCODE_HOST) private readonly host: OpenCodeHost,\n @Inject(OPENCODE_SESSIONS) private readonly sessions: OpenCodeSessionStore,\n @Inject(OPENCODE_OPTIONS) private readonly settings: OpenCodeEngineSettings,\n @Inject(AGENT_STORE) private readonly store: AgentStore,\n @Inject(AGENT_SINK) private readonly sink: TokenStreamSink,\n @Inject(AGENT_DEPS_FACTORY) private readonly deps: AgentDepsFactory,\n @Inject(AGENT_TOOL_REGISTRY) readonly registry: ToolRegistry,\n @Optional() @Inject(AGENT_SKILLS) private readonly skills?: SkillsConfig,\n @Optional() @Inject(AGENT_MEMORY) private readonly memory?: MemoryConfig,\n @Optional() @Inject(AGENT_CHAT_QUEUE) private readonly queue?: ChatQueueService,\n @Optional()\n @Inject(OPENCODE_TOOLS_TOKENS)\n private readonly toolsTokens?: OpenCodeToolsTokens | null,\n ) {}\n\n /** The tools server's name in OpenCode. */\n get toolsServer(): string {\n return this.settings.tools?.server ?? 'aviary';\n }\n\n /** The roles policy a turn's tools are gated by (the agent's own). */\n rolesPolicyFor(input: Pick<AgentRunInput, 'agentName'>): RolesPolicy {\n return this.deps.forAgent(input.agentName).rolesPolicy;\n }\n\n /** The tools a turn may reach: the agent's allow-list, narrowed by its persona's. */\n allowedTools(input: Pick<AgentRunInput, 'agentName' | 'persona'>): string[] | undefined {\n const deps = this.deps.forAgent(input.agentName);\n const agent = deps.toolAllowList;\n const persona =\n input.persona !== undefined\n ? deps.personas?.find((p) => p.id === input.persona)?.allowedTools\n : undefined;\n if (agent === undefined) return persona === undefined ? undefined : [...persona];\n if (persona === undefined) return [...agent];\n return agent.filter((name) => persona.includes(name));\n }\n\n /**\n * Whether the tools endpoint serves `remember`: the module's tools are served and the memory\n * provider writes. Served by the engine's own endpoint only — never put in the module's shared\n * registry, where every MCP client and the `/tools` catalog would see it.\n */\n memoryWritable(): boolean {\n return this.settings.tools !== undefined && this.memory?.provider.write !== undefined;\n }\n\n /** `remember` for a turn: one fact, at the actor's own scope only — as the loop serves it. */\n async remember(input: RememberToolInput, turn: OpenCodeCallContext): Promise<string> {\n const memory = this.memory;\n const write = memory?.provider.write?.bind(memory.provider);\n if (memory === undefined || write === undefined) return 'Memory is read-only here.';\n const max = memory.maxFactChars ?? DEFAULT_MAX_FACT_CHARS;\n if (input.fact.length > max) return `Not recorded: a fact is at most ${max} characters.`;\n const actor = turn.input.actor;\n const scopeCtx = {\n actor,\n threadId: turn.ctx.threadId,\n ...(turn.input.agentName !== undefined ? { agentName: turn.input.agentName } : {}),\n };\n const scopes = await (memory.scopes ?? defaultScopeResolver).resolve(scopeCtx);\n const scope = actorScope(actor);\n const verdict = memoryWriteVerdict({ scope, scopes, actor, author: { kind: 'agent' } });\n if (!verdict.allowed) return `Not recorded: ${verdict.reason}`;\n await write({\n key: input.key,\n text: input.fact,\n scope,\n origin: {\n author: 'agent',\n actorRef: actor.id,\n threadId: turn.ctx.threadId,\n runId: turn.runId,\n },\n ctx: scopeCtx,\n });\n return `Recorded \"${input.key}\".`;\n }\n\n /**\n * The turn a tool call over the engine's MCP endpoint belongs to, or `undefined` when it belongs\n * to none — which the endpoint refuses: it exists only to serve turns. OpenCode names its session in\n * every call's `_meta` (`ai.opencode/sessionID`); the call is that session's running turn's, and\n * only when the endpoint's caller is the person that turn runs for, on the server the token was\n * issued for. A session this process is not following is found through OpenCode (`session.get` →\n * the thread it was created for → the thread's running turn); its components still reach the\n * stream, as a message of their own.\n */\n async callContext(call: OpenCodeToolCall): Promise<OpenCodeCallContext | undefined> {\n const sessionId = sessionOfMeta(call.meta);\n if (sessionId === undefined) return undefined;\n const scope = (runId: string) => `${runId}:${call.requestId || randomUUID()}`;\n for (const [runId, live] of this.live) {\n if (live.handle.sessionId !== sessionId) continue;\n if (live.input.actor.id !== call.actor.id || live.handle.serverKey !== call.serverKey) {\n return undefined;\n }\n return {\n input: live.input,\n runId,\n ctx: {\n threadId: live.input.threadId,\n runId,\n emitUi: uiEmitter(scope(runId), async (component) => {\n await live.turn.pushUi(component);\n await this.uiPushed(live.input, runId, component);\n }),\n },\n };\n }\n const threadId = await this.threadOfSession(call.actor, sessionId);\n if (threadId === undefined) return undefined;\n if ((await this.store.ownerOfThread(threadId)) !== call.actor.id) return undefined;\n const known = await this.sessions.get(threadId);\n if (known === null || known.sessionId !== sessionId || known.serverKey !== call.serverKey) {\n return undefined;\n }\n const runId = await this.activeRun(threadId);\n if (runId === null) return undefined;\n // Followed elsewhere: what this call knows of the run.\n const input: AgentRunInput = {\n threadId,\n actor: call.actor,\n userText: '',\n ...(known.agentName !== undefined ? { agentName: known.agentName } : {}),\n ...(known.persona !== undefined ? { persona: known.persona } : {}),\n };\n return {\n input,\n runId,\n ctx: {\n threadId,\n runId,\n emitUi: uiEmitter(scope(runId), async (component) => {\n const writer = await this.sink.open(runId);\n await writer.write(encodeStreamEvent({ kind: 'ui', ...component }));\n await this.store.appendMessage({\n threadId,\n role: 'assistant',\n content: '',\n runId,\n ui: [component],\n });\n await this.uiPushed(input, runId, component);\n }),\n },\n };\n }\n\n /**\n * Spend one approval of `tool` in `runId` — what the MCP endpoint asks before it runs an `action`.\n * OpenCode asks the person (or the policy answers) before it calls an action tool; the endpoint\n * runs it only against an approval this engine saw granted, so a caller that skipped OpenCode's\n * permission rules (a model in code mode that read the endpoint's headers, anything else that got\n * hold of the token) cannot run an action unapproved. One approval, one call. The approval is the\n * run's own: live in this process, else read off the run's persisted calls (spent marks are kept\n * per process).\n */\n async spendApproval(\n runId: string,\n tool: string,\n input: Pick<AgentRunInput, 'threadId'>,\n ): Promise<boolean> {\n const names = new Set([tool, `${this.toolsServer}.${tool}`, `${this.toolsServer}_${tool}`]);\n const local = (this.grants.get(runId) ?? []).find(\n (grant) => names.has(grant.action) && !this.spent.has(grant.id),\n );\n if (local !== undefined) {\n this.spent.add(local.id);\n return true;\n }\n const thread = await this.store.getThread(input.threadId);\n for (const message of thread?.messages ?? []) {\n if (message.runId !== runId) continue;\n for (const call of message.toolCalls ?? []) {\n if (!names.has(call.name) || this.spent.has(call.id)) continue;\n const result = message.toolResults?.find((r) => r.id === call.id);\n const approved = (result?.output as { approved?: unknown } | undefined)?.approved === true;\n if (approved) {\n this.spent.add(call.id);\n return true;\n }\n }\n }\n return false;\n }\n\n private async activeRun(threadId: string): Promise<string | null> {\n if (this.store.activeRunForThread !== undefined) return this.store.activeRunForThread(threadId);\n return (await this.store.getThread(threadId))?.activeRunId ?? null;\n }\n\n private async uiPushed(input: AgentRunInput, runId: string, component: AgentUiComponent) {\n await this.host.onUi?.({ input, runId, component }).catch((error: unknown) => {\n this.logger.warn(`onUi failed: ${errorText(error, 'error')}`);\n });\n }\n\n /**\n * Push a component into the run an OpenCode session is serving, for the host's own trusted\n * callers (no caller check — {@link callContext} is the one for MCP requests). `false` when no run\n * is live on that session.\n */\n async pushToSession(sessionId: string, component: AgentUiComponent): Promise<boolean> {\n for (const [runId, live] of this.live) {\n if (live.handle.sessionId !== sessionId) continue;\n await live.turn.pushUi(component);\n await this.uiPushed(live.input, runId, component);\n return true;\n }\n return false;\n }\n\n /** The runs this process is following now (an updater drains on it). */\n liveRuns(): string[] {\n return [...this.live.keys()];\n }\n\n private async threadOfSession(\n actor: AiToolCtx['actor'],\n sessionId: string,\n ): Promise<string | undefined> {\n try {\n const server = await this.host.server(actor);\n const info = await server.client.session.get?.({ sessionID: sessionId });\n const threadId = info?.metadata?.threadId;\n return typeof threadId === 'string' ? threadId : undefined;\n } catch {\n return undefined;\n }\n }\n\n onApplicationShutdown(): void {\n for (const live of this.live.values()) live.stop();\n this.live.clear();\n this.events.close();\n }\n\n // ---- begin ---------------------------------------------------------------------------------\n\n /**\n * Persist the user message (or rewind the thread for a regenerate), find or create the thread's\n * session, and refresh what the session is told this turn. Safe to run again for the same run (a\n * durable `begin` re-run after a crash): the run's user message is written once.\n */\n async begin(runId: string, input: AgentRunInput): Promise<SessionHandle> {\n const earlier = await this.prepareThread(runId, input);\n const server = await this.host.server(input.actor);\n const known = await this.sessions.get(input.threadId);\n const reusable =\n known !== null &&\n known.serverKey === server.key &&\n known.bootId === server.bootId &&\n ((await this.host.reuse?.({ input, runId, session: known })) ?? true);\n let handle: SessionHandle;\n let created = false;\n if (known !== null && reusable) {\n handle = {\n sessionId: known.sessionId,\n serverKey: known.serverKey,\n ...(known.bootId !== undefined ? { bootId: known.bootId } : {}),\n ...(known.directory !== undefined ? { directory: known.directory } : {}),\n };\n if (input.regenerate === true) await this.revertLastExchange(server.client, handle.sessionId);\n await this.addTools(input, server, handle.directory, false);\n } else {\n handle = await this.createSession(runId, input, server, earlier);\n created = true;\n }\n if (created || known?.agentName !== input.agentName || known?.persona !== input.persona) {\n await this.sessions.set(input.threadId, {\n ...handle,\n ...(input.agentName !== undefined ? { agentName: input.agentName } : {}),\n ...(input.persona !== undefined ? { persona: input.persona } : {}),\n });\n }\n await this.host.beforePrompt?.({\n input,\n runId,\n sessionId: handle.sessionId,\n client: server.client,\n created,\n });\n await this.refreshInstructions(runId, input, server.client, handle.sessionId);\n return handle;\n }\n\n private async createSession(\n runId: string,\n input: AgentRunInput,\n server: OpenCodeServer,\n earlier: StoredMessage[],\n note?: string,\n ): Promise<SessionHandle> {\n const { client } = server;\n const context = { input, runId };\n const spec = await this.host.session(context);\n const directory = spec.location?.directory;\n const skills = await this.writeSkills(input, client, directory);\n const sessionId = (\n await client.session.create({\n ...spec,\n permissions: [\n ...(spec.permissions ?? []),\n ...this.toolRules(input),\n ...skills.map(\n (name): OpenCodePermissionRule => ({\n action: 'skill',\n resource: name,\n effect: 'allow',\n }),\n ),\n ],\n metadata: { ...(spec.metadata ?? {}), threadId: input.threadId },\n })\n ).id;\n const handle: SessionHandle = {\n sessionId,\n serverKey: server.key,\n ...(server.bootId !== undefined ? { bootId: server.bootId } : {}),\n ...(directory !== undefined ? { directory } : {}),\n };\n await this.sessions.set(input.threadId, handle satisfies OpenCodeSessionRef);\n await this.addTools(input, server, directory, true);\n await this.host.prepare?.({ ...context, sessionId, client });\n const transcript = transcriptOf(earlier, this.settings.historyMessages ?? 20);\n if (transcript || note) {\n await client.session.instructions.entry.put({\n sessionID: sessionId,\n key: 'aviary.history',\n value: [\n transcript\n ? `The conversation so far (continue it; do not repeat it):\\n${transcript}`\n : '',\n note ?? '',\n ]\n .filter(Boolean)\n .join('\\n\\n'),\n });\n }\n return handle;\n }\n\n /** The user message, as the loop persists it (or, on a regenerate, the thread rewound to it). */\n private async prepareThread(runId: string, input: AgentRunInput): Promise<StoredMessage[]> {\n const thread = await this.store.getThread(input.threadId);\n const messages = thread?.messages ?? [];\n if (input.regenerate === true) {\n let lastUser = -1;\n for (let i = messages.length - 1; i >= 0; i -= 1)\n if (messages[i]?.role === 'user') {\n lastUser = i;\n break;\n }\n const firstDropped = messages[lastUser + 1];\n if (firstDropped !== undefined)\n await this.store.truncateFrom(input.threadId, firstDropped.id);\n return messages.slice(0, Math.max(lastUser, 0));\n }\n // Already written by an earlier attempt at this step (a durable `begin` re-run after a crash):\n // the run's user message is keyed by its run id, and what came before it is the history.\n const mine = messages.findIndex((m) => m.role === 'user' && m.runId === runId);\n if (mine >= 0) return messages.slice(0, mine);\n await this.store.appendMessage({\n threadId: input.threadId,\n role: 'user',\n content: input.userText,\n runId,\n ...(input.persona !== undefined ? { persona: input.persona } : {}),\n ...(input.attachments !== undefined ? { attachments: input.attachments } : {}),\n });\n if (thread !== null && (thread.title === '' || thread.title === 'New chat')) {\n await this.store.setTitle(input.threadId, titleOf(input.userText));\n }\n return messages;\n }\n\n /** Rewind the session to before its last user message, so the regenerated answer replaces it. */\n private async revertLastExchange(client: OpenCodeClient, sessionId: string): Promise<void> {\n if (client.message === undefined || client.session.revert === undefined) return;\n const page = await client.message.list({ sessionID: sessionId, order: 'desc', limit: 50 });\n const last = page.data.find((m) => m.type === 'user');\n if (last === undefined) return;\n await client.session.revert.stage({ sessionID: sessionId, messageID: last.id, files: false });\n await client.session.revert.commit({ sessionID: sessionId });\n }\n\n /** The agent's prompt, the memory block and the host's entries — refreshed every turn. */\n private async refreshInstructions(\n runId: string,\n input: AgentRunInput,\n client: OpenCodeClient,\n sessionId: string,\n ): Promise<void> {\n const memory = await this.memoryBlock(input);\n const entries: Record<string, string> = {\n [this.settings.systemKey ?? 'aviary.system']: await this.systemPrompt(input),\n ...(memory !== undefined ? { 'aviary.memory': memory } : {}),\n ...((await this.host.instructions?.({ input, runId, sessionId })) ?? {}),\n };\n for (const [key, value] of Object.entries(entries)) {\n await client.session.instructions.entry.put({ sessionID: sessionId, key, value });\n }\n }\n\n /** The agent's base prompt (`@Agent({ systemPrompt })` / `@SystemPrompt()`) and the contributors. */\n private async systemPrompt(input: AgentRunInput): Promise<string> {\n const deps = this.deps.forAgent(input.agentName);\n const ctx: PromptContext = {\n actor: input.actor,\n agentName: input.agentName ?? 'default',\n ...(input.pageContext !== undefined ? { pageContext: input.pageContext } : {}),\n ...(input.uiCapabilities !== undefined ? { uiCapabilities: input.uiCapabilities } : {}),\n };\n const base =\n typeof deps.systemPrompt === 'function' ? await deps.systemPrompt(ctx) : deps.systemPrompt;\n const sections = [base];\n for (const contribute of deps.promptContributors) {\n const section = await contribute(ctx);\n if (section) sections.push(section);\n }\n return sections.filter(Boolean).join('\\n\\n');\n }\n\n private scopeContext(input: AgentRunInput): ScopeContext {\n return {\n actor: input.actor,\n threadId: input.threadId,\n ...(input.agentName !== undefined ? { agentName: input.agentName } : {}),\n ...(input.pageContext !== undefined ? { pageContext: input.pageContext } : {}),\n };\n }\n\n /** What is on file about the actor (`forRoot({ memory })`); writable when `remember` is served. */\n private async memoryBlock(input: AgentRunInput): Promise<string | undefined> {\n const memory = this.memory;\n if (memory === undefined) return undefined;\n const ctx = this.scopeContext(input);\n const scopes = await (memory.scopes ?? defaultScopeResolver).resolve(ctx);\n const records = await memory.provider.list({ scopes, ctx });\n const digest = resolveMemoryDigest({\n records,\n scopes,\n ...(memory.maxMemories !== undefined ? { maxMemories: memory.maxMemories } : {}),\n });\n if (digest.entries.length === 0) return undefined;\n return buildMemoryBlock({\n entries: digest.entries,\n writable: this.memoryWritable(),\n partial: digest.omitted > 0,\n });\n }\n\n /**\n * The module's skills (`forRoot({ skills })` / `@Skill`) as `SKILL.md` files under the session's\n * directory, where OpenCode's own `skill` tool finds them. Returns the names written.\n */\n private async writeSkills(\n input: AgentRunInput,\n client: OpenCodeClient,\n directory: string | undefined,\n ): Promise<string[]> {\n const skills = this.skills;\n if (skills === undefined || client.file === undefined || directory === undefined) return [];\n const ctx = this.scopeContext(input);\n const scopes = await (skills.scopes ?? defaultScopeResolver).resolve(ctx);\n const summaries = await skills.provider.list({ scopes, ctx });\n const { entries } = resolveSkillCatalog(summaries, scopes, skills.maxSkills);\n const dir = this.settings.skillsDir ?? '.opencode/skills';\n const written: string[] = [];\n for (const entry of entries) {\n const body = await skills.provider.load({ name: entry.name, scope: entry.scope, ctx });\n if (body === null) continue;\n const file = `---\\nname: ${entry.name}\\ndescription: ${JSON.stringify(entry.description)}\\n---\\n\\n${body}\\n`;\n await client.file.write({\n location: { directory },\n path: `${dir}/${entry.name}/SKILL.md`,\n payload: new TextEncoder().encode(file),\n });\n written.push(entry.name);\n }\n return written;\n }\n\n /**\n * Permission rules for the module's tools: the MCP server allowed as a whole (OpenCode offers a\n * server's tools only when the server itself is allowed), then each `action` tool asked — the last\n * matching rule wins, so an action still lands on an approval card. Tools outside the agent's\n * (and persona's) allow-list, and the kinds only the loop serves, are denied. The endpoint enforces\n * all of it again on every call: these rules are what OpenCode offers, not what keeps a call out.\n */\n private toolRules(input: AgentRunInput): OpenCodePermissionRule[] {\n if (this.settings.tools === undefined) return [];\n const server = this.toolsServer;\n const allow = this.allowedTools(input);\n const both = (name: string) => [`${server}.${name}`, `${server}_${name}`];\n const rules: OpenCodePermissionRule[] = [\n { action: `${server}*`, resource: '*', effect: 'allow' },\n ];\n for (const spec of this.registry.allSpecs()) {\n const offered =\n (allow === undefined || allow.includes(spec.name)) && !LOOP_SERVED_KINDS.has(spec.kind);\n if (offered && spec.kind === 'read') continue;\n const effect = offered && spec.kind === 'action' ? 'ask' : 'deny';\n for (const action of both(spec.name)) rules.push({ action, resource: '*', effect });\n }\n return rules;\n }\n\n /**\n * Register the tools endpoint at the session's location, with a bearer token for the turn's actor\n * on this server. On a new session always; on a kept one when this process has not registered it\n * yet or its token is half-way through its life.\n */\n private async addTools(\n input: AgentRunInput,\n server: OpenCodeServer,\n directory: string | undefined,\n fresh: boolean,\n ): Promise<void> {\n const tools = this.settings.tools;\n const tokens = this.toolsTokens;\n if (tools === undefined || tokens == null) return;\n const { client } = server;\n if (client.mcp === undefined) {\n this.logger.warn('`tools` is set but the OpenCode client cannot add MCP servers (`mcp.add`)');\n return;\n }\n const key = `${server.key}|${server.bootId ?? ''}|${directory ?? ''}|${input.actor.id}`;\n const issued = this.toolsIssued.get(key);\n const ttl = tools.ttlMs ?? DEFAULT_TOOLS_TTL_MS;\n if (!fresh && issued !== undefined && Date.now() - issued < ttl / 2) return;\n await client.mcp.add({\n server: this.toolsServer,\n ...(directory !== undefined ? { location: { directory } } : {}),\n config: {\n type: 'remote',\n url: tools.url,\n headers: { Authorization: `Bearer ${tokens.mint(input.actor, server.key)}` },\n oauth: false,\n },\n });\n this.toolsIssued.set(key, Date.now());\n }\n\n // ---- prompt / observe / reply --------------------------------------------------------------\n\n /** Start listening to the session (so nothing it says is missed), then send the user message. */\n async prompt(runId: string, input: AgentRunInput, handle: SessionHandle): Promise<void> {\n const live = await this.ensureLive(runId, input, handle, false);\n try {\n const prompt = (await this.host.promptFor?.({\n input,\n runId,\n sessionId: handle.sessionId,\n })) ?? {\n text: input.userText,\n ...(input.attachments?.length && this.host.files\n ? { files: await this.host.files({ input, runId }) }\n : {}),\n };\n await live.client.session.prompt({\n sessionID: handle.sessionId,\n text: prompt.text,\n ...(prompt.files?.length ? { files: prompt.files } : {}),\n });\n } catch (error) {\n live.turn.fail(`OpenCode refused the message: ${(error as Error).message}`);\n }\n }\n\n /**\n * Wait for the turn's next milestone. In a process that was not following the turn (a resumed\n * durable run), the turn is rebuilt and first catches up on requests OpenCode raised meanwhile;\n * `session.wait` is the safety net for a terminal event that was missed.\n */\n async observe(runId: string, input: AgentRunInput, handle: SessionHandle): Promise<Milestone> {\n const live = await this.ensureLive(runId, input, handle, true);\n const { turn, client } = live;\n if (turn.hasMilestone()) return this.reached(runId, input, handle, await turn.next());\n // Set once this observation has its milestone: the safety nets below only act while it waits.\n let done = false;\n const next = turn.next().then((milestone) => {\n done = true;\n return milestone;\n });\n const timeoutMs = this.settings.turnTimeoutMs ?? DEFAULT_TURN_TIMEOUT_MS;\n const timer = setTimeout(() => {\n if (!done) turn.fail('Timed out waiting for OpenCode.');\n }, timeoutMs);\n timer.unref?.();\n if (client.session.wait !== undefined) {\n void client.session\n .wait({ sessionID: handle.sessionId })\n .then(() => new Promise((resolve) => setTimeout(resolve, 2_000)))\n .then(async () => {\n if (done || turn.finished) return;\n await turn.catchUp().catch(() => undefined);\n // Let a milestone the catch-up reached settle this observation first.\n await new Promise((resolve) => setImmediate(resolve));\n // Idle with nothing open: the execution ended while its last events were lost.\n if (!done && !turn.finished)\n turn.handle({\n type: 'session.execution.succeeded',\n data: { sessionID: handle.sessionId },\n });\n })\n .catch(() => undefined);\n }\n try {\n return await this.reached(runId, input, handle, await next);\n } finally {\n clearTimeout(timer);\n }\n }\n\n /**\n * Hand a person's answer back to OpenCode. When the server restarted while the turn waited, the\n * request is gone with it: a new session is opened, told what the person decided, and prompted\n * to go on.\n */\n async reply(\n runId: string,\n input: AgentRunInput,\n handle: SessionHandle,\n ask: PendingAsk,\n reply: HumanReply,\n ): Promise<SessionHandle> {\n const server = await this.host.server(input.actor);\n if (server.key !== handle.serverKey || server.bootId !== handle.bootId) {\n return this.continueAfterRestart(runId, input, server, ask, reply);\n }\n const live = await this.ensureLive(runId, input, handle, false);\n await live.turn.decide(ask, reply);\n return handle;\n }\n\n private async continueAfterRestart(\n runId: string,\n input: AgentRunInput,\n server: OpenCodeServer,\n ask: PendingAsk,\n reply: HumanReply,\n ): Promise<SessionHandle> {\n const approved = 'approved' in reply && reply.approved === true;\n const note =\n ask.kind === 'approval'\n ? approved\n ? `The user approved the action ${ask.action} you asked permission for. Continue the task.`\n : `The user did not approve the action ${ask.action}. Continue without it and explain.`\n : `The user answered your question: ${JSON.stringify('answers' in reply ? reply.answers : {})}. Continue.`;\n const thread = await this.store.getThread(input.threadId);\n const handle = await this.createSession(runId, input, server, thread?.messages ?? [], note);\n await this.refreshInstructions(runId, input, server.client, handle.sessionId);\n this.drop(runId);\n const live = await this.ensureLive(runId, input, handle, false);\n // The old request's card settles as decided; OpenCode is told in the note.\n await live.turn.decide(ask, reply, { tellOpenCode: false });\n await live.client.session.prompt({ sessionID: handle.sessionId, text: note });\n return handle;\n }\n\n /** Interrupt the thread's session (cancel). */\n async interrupt(input: AgentRunInput): Promise<void> {\n const known = await this.sessions.get(input.threadId);\n if (known === null) return;\n const server = await this.host.server(input.actor);\n if (server.key !== known.serverKey || server.bootId !== known.bootId) return;\n await server.client.session.interrupt({ sessionID: known.sessionId });\n }\n\n private async ensureLive(\n runId: string,\n input: AgentRunInput,\n handle: SessionHandle,\n catchUp: boolean,\n ): Promise<LiveTurn> {\n const current = this.live.get(runId);\n if (current !== undefined && current.handle.sessionId === handle.sessionId) return current;\n current?.stop();\n const server = await this.host.server(input.actor);\n const deps = this.deps.forAgent(input.agentName);\n const policy = deps.approvalPolicy ?? new DefaultApprovalPolicy();\n const writer = await this.sink.open(input.sinkRunId ?? runId);\n const turn = new OpenCodeTurn({\n runId,\n input,\n client: server.client,\n sessionId: handle.sessionId,\n writer,\n store: this.store,\n approvalFor: async (action): Promise<ApprovalRequirement> =>\n policy.requirementFor({ name: action, kind: 'action' }, input.actor, {\n threadId: input.threadId,\n runId,\n ...(input.agentName !== undefined ? { agentName: input.agentName } : {}),\n }),\n modelLabel: input.model ?? 'opencode',\n logger: this.logger,\n onGranted: (action, id) => {\n const grants = this.grants.get(runId) ?? [];\n grants.push({ action, id });\n this.grants.set(runId, grants);\n },\n });\n const stop = await this.events.listen(server.key, server.client, handle.sessionId, (event) =>\n turn.handle(event),\n );\n const live: LiveTurn = { turn, input, handle, client: server.client, stop };\n this.live.set(runId, live);\n if (catchUp && current === undefined) await turn.catchUp().catch(() => undefined);\n return live;\n }\n\n /** Stop following a run in this process. */\n drop(runId: string): void {\n this.live.get(runId)?.stop();\n this.live.delete(runId);\n }\n\n /** Stop following a run and drop the approvals it was granted: it is over. */\n private forget(runId: string): void {\n this.drop(runId);\n for (const grant of this.grants.get(runId) ?? []) this.spent.delete(grant.id);\n this.grants.delete(runId);\n }\n\n // ---- settle --------------------------------------------------------------------------------\n\n /** A person was asked something: tell the host (cards in other channels, wake-ups). */\n private async reached(\n runId: string,\n input: AgentRunInput,\n handle: SessionHandle,\n milestone: Milestone,\n ): Promise<Milestone> {\n if (milestone.kind === 'ask' && this.host.onAsk !== undefined) {\n await this.host\n .onAsk({ input, runId, sessionId: handle.sessionId, ask: milestone.ask })\n .catch((error: unknown) => this.logger.warn(`onAsk failed: ${errorText(error, 'error')}`));\n }\n return milestone;\n }\n\n /** What the run produced, as the host's settle hooks see it. */\n private async runResult(\n runId: string,\n input: AgentRunInput,\n outcome: TurnOutcome,\n durationMs: number,\n ): Promise<OpenCodeRunResult> {\n const thread = await this.store.getThread(input.threadId);\n const messages = (thread?.messages ?? []).filter(\n (m) => m.role === 'assistant' && m.runId === runId,\n );\n const usage = { inputTokens: 0, outputTokens: 0, costUsd: 0 };\n for (const m of messages) {\n usage.inputTokens += m.usage?.inputTokens ?? 0;\n usage.outputTokens += m.usage?.outputTokens ?? 0;\n usage.costUsd += m.usage?.costUsd ?? 0;\n }\n return {\n runId,\n input,\n outcome,\n text: messages\n .map((m) => m.content)\n .filter(Boolean)\n .join('\\n\\n'),\n messages,\n usage,\n durationMs,\n };\n }\n\n /**\n * The host's last word on the answer before the stream ends: components to append (a guardrail\n * notice), or, for a failed run, the error the person reads instead of OpenCode's.\n */\n private async amend(\n writer: { write(chunk: Uint8Array): void | Promise<void> },\n result: OpenCodeRunResult,\n ) {\n if (this.host.beforeSettle === undefined) return {};\n let amendment: OpenCodeAmendment = {};\n try {\n amendment = (await this.host.beforeSettle(result)) ?? {};\n } catch (error) {\n this.logger.warn(`beforeSettle failed: ${errorText(error, 'error')}`);\n }\n const ui = amendment.ui ?? [];\n const last = result.messages.at(-1);\n if (ui.length > 0) {\n for (const component of ui)\n await writer.write(encodeStreamEvent({ kind: 'ui', ...component }));\n if (last !== undefined) await this.store.setMessageUi?.(last.id, [...(last.ui ?? []), ...ui]);\n }\n return amendment;\n }\n\n /** Delivery, telemetry, spend: after the run settled. Errors are the host's, never the run's. */\n private async settled(result: OpenCodeRunResult): Promise<void> {\n try {\n await this.host.onSettled?.(result);\n } catch (error) {\n this.logger.warn(`onSettled failed: ${errorText(error, 'error')}`);\n }\n }\n\n /** End the run's stream and bookkeeping for how its execution ended. */\n async settle(runId: string, input: AgentRunInput, outcome: TurnOutcome, durationMs: number) {\n if (outcome.status === 'failed') {\n await this.settleFailed(runId, input, outcome.error, durationMs);\n return;\n }\n this.forget(runId);\n const writer = await this.sink.open(runId);\n const result = await this.runResult(runId, input, outcome, durationMs);\n await this.amend(writer, result);\n if (outcome.status === 'interrupted') {\n this.logger.log(`agent run ${runId} cancelled`);\n await Promise.resolve(\n this.store.failUnsettledToolCalls?.(runId, RUN_ENDED_BEFORE_TOOL_CALL),\n ).catch(() => 0);\n await this.handoff(writer, input, runId, 'cancelled');\n await releaseThreadRun(this.store, input.threadId, runId);\n await writer.write(encodeStreamEvent({ kind: 'cancelled' }));\n await writer.end();\n await this.store.recordRunEnd?.({ runId, status: 'cancelled', durationMs });\n } else {\n await this.handoff(writer, input, runId, 'completed');\n await releaseThreadRun(this.store, input.threadId, runId);\n await writer.end();\n await this.store.recordRunEnd?.({ runId, status: 'completed', durationMs });\n }\n await this.settled(result);\n }\n\n async settleFailed(\n runId: string,\n input: AgentRunInput,\n error: string,\n durationMs = 0,\n ): Promise<void> {\n this.forget(runId);\n const writer = await this.sink.open(runId);\n const result = await this.runResult(runId, input, { status: 'failed', error }, durationMs);\n const worded = (await this.amend(writer, result)).error;\n // The host's wording is for the person and shown as is. OpenCode's own error follows the\n // library's rule for a provider's: logged and on the run row everywhere, on the stream only\n // outside production (or with `exposeStreamErrorDetails(true)`).\n const message = worded ?? streamFailure(new Error(error)).message;\n this.logger.error(`agent run ${runId} failed: ${error}`);\n publishAgentRunFailed({ runId, code: 'opencode_failed', message: error });\n await this.store.recordRunEnd?.({\n runId,\n status: 'failed',\n errorCode: 'opencode_failed',\n errorMessage: error,\n });\n await Promise.resolve(\n this.store.failUnsettledToolCalls?.(runId, RUN_ENDED_BEFORE_TOOL_CALL),\n ).catch(() => 0);\n await this.handoff(writer, input, runId, 'failed', error);\n await releaseThreadRun(this.store, input.threadId, runId);\n await writer.fail({ code: 'opencode_failed', message });\n await this.settled({ ...result, outcome: { status: 'failed', error: worded ?? error } });\n }\n\n /** Starts the next queued message of the thread; set by the runner (it owns `start`). */\n startNext: ((next: AgentRunInput, runId: string) => Promise<unknown>) | undefined;\n\n /** As `InlineAgentRunner`: hand the thread to its next queued message, and say so on the stream. */\n private async handoff(\n writer: { write(chunk: Uint8Array): void | Promise<void> },\n input: AgentRunInput,\n runId: string,\n outcome: 'completed' | 'failed' | 'cancelled',\n error?: string,\n ): Promise<void> {\n const queue = this.queue;\n const startNext = this.startNext;\n if (queue === undefined || !queue.supported || startNext === undefined) return;\n if (input.sinkRunId !== undefined || input.deliverTo !== undefined) return;\n try {\n const frame = await queue.handoff(\n { threadId: input.threadId, runId, outcome, ...(error !== undefined ? { error } : {}) },\n (next, nextRunId) => startNext(next, nextRunId),\n );\n if (frame !== undefined) await writer.write(encodeStreamEvent(frame));\n } catch (failure) {\n this.logger.error(\n `could not advance the queue of thread ${input.threadId} after run ${runId}: ${\n failure instanceof Error ? failure.message : String(failure)\n }`,\n );\n }\n }\n}\n\nfunction titleOf(text: string): string {\n const trimmed = text.trim().replace(/\\s+/g, ' ');\n return trimmed.length > 60 ? `${trimmed.slice(0, 57)}...` : trimmed || 'New chat';\n}\n\nfunction transcriptOf(messages: StoredMessage[], limit: number): string {\n return messages\n .filter((m) => (m.role === 'user' || m.role === 'assistant') && m.content.trim())\n .slice(-limit)\n .map((m) => `${m.role === 'user' ? 'User' : 'Assistant'}: ${m.content.slice(0, 2000)}`)\n .join('\\n');\n}\n\n/** The `_meta` key OpenCode names its session with on every MCP call. */\nconst SESSION_META_KEY = 'ai.opencode/sessionID';\n\nfunction sessionOfMeta(meta: Readonly<Record<string, unknown>> | undefined): string | undefined {\n const value = meta?.[SESSION_META_KEY];\n return typeof value === 'string' && value.length > 0 ? value : undefined;\n}\n\n/** `ctx.emitUi` over `push`, with the library's id and snapshot rules. */\nfunction uiEmitter(\n scope: string,\n push: (component: AgentUiComponent) => Promise<void>,\n): AiToolCtx['emitUi'] {\n let next = 0;\n return async (component, props, options = {}) => {\n if (typeof component !== 'string' || component.length === 0) {\n throw new Error('emitUi: component must be a non-empty string');\n }\n if (typeof props !== 'object' || props === null || Array.isArray(props)) {\n throw new Error('emitUi: props must be a JSON object');\n }\n const id = options.id ?? `${scope}:ui:${next++}`;\n await push({\n id,\n component,\n props: JSON.parse(JSON.stringify(props)) as Record<string, unknown>,\n ...(options.version !== undefined ? { version: options.version } : {}),\n });\n return { id };\n };\n}\n","import { Logger } from '@nestjs/common';\nimport type { OpenCodeClient, OpenCodeEvent } from './client.js';\n\ntype Listener = (event: OpenCodeEvent) => void;\n\ninterface Stream {\n client: OpenCodeClient;\n controller: AbortController;\n listeners: Map<string, Set<Listener>>;\n /**\n * Resolves once the server has sent the stream's first event (OpenCode opens every subscription\n * with `server.connected`), so a turn never prompts before the server can deliver the answer.\n */\n ready: Promise<void>;\n}\n\n/** The session an event belongs to. Form events carry it inside the form. */\nexport function sessionOf(event: OpenCodeEvent): string | undefined {\n const id = event.data?.sessionID ?? event.data?.form?.sessionID;\n return typeof id === 'string' ? id : undefined;\n}\n\n/** How long `listen` waits for a new stream's first event before it lets the turn go on anyway. */\nconst DEFAULT_CONNECT_TIMEOUT_MS = 10_000;\n\n/**\n * One event subscription per OpenCode server, fanned out to the turns listening on its sessions. A\n * server's stream closes when its last listener leaves; a stream that drops reconnects with backoff.\n *\n * `subscribe()` only describes the request: the client connects when the stream is first iterated,\n * and the server registers the subscriber some time after that. A stream is therefore open when its\n * first event arrives, not when it was asked for — events a prompt causes before then would be lost\n * (the catch-up recovers permissions and forms, not text, tools or the end of the execution).\n */\nexport class OpenCodeEventHub {\n private readonly logger = new Logger(OpenCodeEventHub.name);\n private readonly streams = new Map<string, Stream>();\n\n constructor(private readonly options: { connectTimeoutMs?: number } = {}) {}\n\n /**\n * Listen to one session's events on a server. Resolves once the server's stream is open (its first\n * event arrived), or after the connect timeout — the turn's safety nets cover a stream that is\n * slow to open.\n */\n async listen(\n serverKey: string,\n client: OpenCodeClient,\n sessionId: string,\n listener: Listener,\n ): Promise<() => void> {\n const stream = this.streamFor(serverKey, client);\n let set = stream.listeners.get(sessionId);\n if (set === undefined) {\n set = new Set();\n stream.listeners.set(sessionId, set);\n }\n set.add(listener);\n await stream.ready;\n return () => {\n // The server's stream now — it may have moved to a new client since this listener joined.\n const live = this.streams.get(serverKey) ?? stream;\n const current = live.listeners.get(sessionId);\n current?.delete(listener);\n if (current?.size === 0) live.listeners.delete(sessionId);\n if (live.listeners.size === 0 && this.streams.get(serverKey) === live) {\n live.controller.abort();\n this.streams.delete(serverKey);\n }\n };\n }\n\n close(): void {\n for (const stream of this.streams.values()) stream.controller.abort();\n this.streams.clear();\n }\n\n /**\n * The server's stream, opened on `client`. A different client for a known key (the host\n * replaced the connection, e.g. a new sandbox under the same key) moves every listener to a stream\n * on the new one: the old connection may be dead, and its sessions would never hear back.\n */\n private streamFor(serverKey: string, client: OpenCodeClient): Stream {\n const existing = this.streams.get(serverKey);\n if (existing !== undefined && existing.client === client) return existing;\n existing?.controller.abort();\n const controller = new AbortController();\n let opened!: () => void;\n const ready = new Promise<void>((resolve) => {\n opened = resolve;\n });\n const timeoutMs = this.options.connectTimeoutMs ?? DEFAULT_CONNECT_TIMEOUT_MS;\n const timer = setTimeout(() => {\n this.logger.warn(`event stream of ${serverKey} not open after ${timeoutMs}ms; going on`);\n opened();\n }, timeoutMs);\n timer.unref?.();\n void ready.then(() => clearTimeout(timer));\n // A stream closed before it opened has nothing to wait for.\n controller.signal.addEventListener('abort', () => opened(), { once: true });\n const stream: Stream = {\n client,\n controller,\n listeners: existing?.listeners ?? new Map(),\n ready,\n };\n this.streams.set(serverKey, stream);\n void this.pump(serverKey, stream, client, opened);\n return stream;\n }\n\n private async pump(\n serverKey: string,\n stream: Stream,\n client: OpenCodeClient,\n opened: () => void,\n ): Promise<void> {\n let backoff = 500;\n while (!stream.controller.signal.aborted) {\n try {\n const events = client.event.subscribe({ signal: stream.controller.signal });\n for await (const event of events) {\n // The first event (`server.connected`) says the server is delivering to this stream.\n opened();\n backoff = 500;\n const sessionId = sessionOf(event);\n if (sessionId === undefined) continue;\n for (const listener of stream.listeners.get(sessionId) ?? []) {\n try {\n listener(event);\n } catch (error) {\n this.logger.error(`listener failed: ${(error as Error).message}`);\n }\n }\n }\n } catch (error) {\n if (stream.controller.signal.aborted) return;\n this.logger.warn(`event stream of ${serverKey} dropped: ${(error as Error).message}`);\n }\n if (stream.controller.signal.aborted) return;\n await new Promise((resolve) => setTimeout(resolve, backoff).unref?.());\n backoff = Math.min(backoff * 2, 10_000);\n }\n }\n}\n","import { randomUUID } from 'node:crypto';\nimport {\n AGENT_STORE,\n type AgentRunInput,\n type AgentRunStartOptions,\n type AgentRunner,\n type AgentStore,\n type HumanReply,\n} from '@dudousxd/nestjs-agent-core';\nimport { RUN_GATEWAY, WorkflowService } from '@dudousxd/nestjs-durable';\nimport { type RunGateway, isWorkflowControlFlowSignal } from '@dudousxd/nestjs-durable-core';\nimport { Inject, Injectable, Logger } from '@nestjs/common';\nimport type { OpenCodeHost } from '../host.js';\nimport { OPENCODE_HOST, OPENCODE_OPTIONS } from '../tokens.js';\nimport { OpenCodeReplyMismatchError, isDecision } from '../turn.js';\nimport { type OpenCodeEngineSettings, OpenCodeTurns } from '../turns.js';\nimport { OpenCodeRunWorkflow, decisionToken } from './workflow.js';\n\nfunction isRunInput(value: unknown): value is AgentRunInput {\n return (\n typeof value === 'object' &&\n value !== null &&\n typeof (value as AgentRunInput).threadId === 'string' &&\n typeof (value as AgentRunInput).actor === 'object'\n );\n}\n\n/**\n * Runs OpenCode turns as `@dudousxd/nestjs-durable` workflows ({@link OpenCodeRunWorkflow}): a\n * person's decision is a durable signal, so a turn waiting on one survives restarts and is resumed\n * by whichever process receives it. Needs a cross-process `TokenStreamSink` when more than one\n * process serves the agent.\n */\n@Injectable()\nexport class DurableOpenCodeAgentRunner implements AgentRunner {\n private readonly logger = new Logger(DurableOpenCodeAgentRunner.name);\n\n constructor(\n private readonly workflows: WorkflowService,\n @Inject(RUN_GATEWAY) private readonly runs: RunGateway,\n private readonly turns: OpenCodeTurns,\n @Inject(OPENCODE_OPTIONS) private readonly settings: OpenCodeEngineSettings,\n @Inject(OPENCODE_HOST) private readonly host: OpenCodeHost,\n @Inject(AGENT_STORE) private readonly store: AgentStore,\n ) {\n turns.startNext = (next, runId) => this.start(next, { runId });\n }\n\n runIdFor(input: AgentRunInput): string {\n return this.settings.runId?.(input) ?? randomUUID();\n }\n\n async start(\n input: AgentRunInput,\n options: AgentRunStartOptions = {},\n ): Promise<{ runId: string }> {\n const runId = options.runId ?? this.runIdFor(input);\n const durable = this.settings.durable;\n const startOptions = {\n ...((await durable?.start?.(input, runId)) ?? {}),\n ...((await this.host.startOptions?.(input, runId)) ?? {}),\n };\n try {\n await this.workflows.start(\n OpenCodeRunWorkflow,\n input,\n runId,\n startOptions as Parameters<WorkflowService['start']>[3],\n );\n } catch (error) {\n // A run that suspends on its first step under a driving dispatcher surfaces the runtime's\n // suspend signal here: the run is persisted and will be resumed, not failed.\n if (isWorkflowControlFlowSignal(error)) return { runId };\n throw this.host.startError?.(error, input) ?? durable?.startError?.(error, input) ?? error;\n }\n return { runId };\n }\n\n async isRunActive(runId: string): Promise<boolean> {\n try {\n const status = (await this.runs.getRunDetail(runId))?.run.status;\n return !(\n status === 'completed' ||\n status === 'failed' ||\n status === 'cancelled' ||\n status === 'dead'\n );\n } catch {\n return true;\n }\n }\n\n /**\n * Signal a person's reply into the run. Answers addressed at an approval (a call recorded with an\n * approver; questions have none) are refused ({@link OpenCodeReplyMismatchError}, a 409) before\n * they reach the workflow, which would otherwise spend its wait on them.\n */\n async signal(runId: string, toolCallId: string, reply: HumanReply): Promise<void> {\n if (!isDecision(reply)) {\n const call = await this.store.toolCallApproval?.(toolCallId);\n if (call != null && call.approver !== null) {\n throw new OpenCodeReplyMismatchError(runId, toolCallId);\n }\n }\n await this.workflows.signal(decisionToken(runId, toolCallId), reply);\n }\n\n /**\n * Interrupt OpenCode, cancel the run in the runtime (a run parked on a person never runs its body\n * again), and settle it here: the queue, the thread, the `cancelled` frame and the run row.\n */\n async cancel(runId: string): Promise<void> {\n this.logger.log(`cancelling agent run ${runId}`);\n const input = await this.runs\n .getRunDetail(runId)\n .then((detail) => detail?.run.input)\n .catch(() => undefined);\n if (isRunInput(input)) await this.turns.interrupt(input).catch(() => undefined);\n await this.runs.cancel(runId, { compensate: true });\n if (isRunInput(input)) await this.turns.settle(runId, input, { status: 'interrupted' }, 0);\n }\n}\n","import type { AgentRunInput, Decision, HumanReply } from '@dudousxd/nestjs-agent-core';\nimport { RUN_GATEWAY, Workflow } from '@dudousxd/nestjs-durable';\nimport {\n type RunGateway,\n SignalTimeoutError,\n type WorkflowCtx,\n isWorkflowControlFlowSignal,\n} from '@dudousxd/nestjs-durable-core';\nimport { Inject, Injectable, Optional } from '@nestjs/common';\nimport { errorText } from '../turn.js';\nimport { OpenCodeTurns, type SessionHandle } from '../turns.js';\n\nexport const OPENCODE_RUN_WORKFLOW = 'agent.opencode.run';\n\n/** The token a person's answer to `toolCallId` is signalled under — the library's own convention. */\nexport function decisionToken(runId: string, toolCallId: string): string {\n return `tool:${runId}:${toolCallId}`;\n}\n\n/**\n * An OpenCode turn as a durable workflow:\n *\n * begin → prompt → observe:0 → [ wait for a person (signal `tool:<run>:<call>`) → reply:n → observe:n+1 ]* → finish\n *\n * Every step is checkpointed. A turn parked on a person is a suspended run with a signal waiter: an\n * API restart loses nothing, and the decision resumes it on whichever process takes it — replaying\n * the steps from their checkpoints and replying to OpenCode from there (`OpenCodeTurns` rebuilds the\n * live turn, and re-prompts a fresh session when OpenCode itself restarted meanwhile). A process\n * that dies while OpenCode works re-runs that `observe` step, which catches up on what OpenCode\n * asked while nobody listened.\n */\n@Injectable()\n@Workflow({ name: OPENCODE_RUN_WORKFLOW, version: '1' })\nexport class OpenCodeRunWorkflow {\n constructor(\n private readonly turns: OpenCodeTurns,\n @Optional() @Inject(RUN_GATEWAY) private readonly runs?: RunGateway,\n ) {}\n\n async run(ctx: WorkflowCtx, input: AgentRunInput): Promise<{ outcome: string }> {\n try {\n const begun = await ctx.localStep('begin', async () => ({\n handle: await this.turns.begin(ctx.runId, input),\n startedAt: Date.now(),\n }));\n let handle: SessionHandle = begun.handle;\n await ctx.localStep('prompt', async () => {\n await this.turns.prompt(ctx.runId, input, handle);\n return true;\n });\n for (let n = 0; ; n += 1) {\n const milestone = await ctx.localStep(`observe:${n}`, () =>\n this.turns.observe(ctx.runId, input, handle),\n );\n if (milestone.kind === 'finished') {\n await ctx.localStep('finish', async () => {\n // A cancel settles the run itself (it may be parked where no step runs again).\n if (await this.cancelled(ctx.runId)) this.turns.drop(ctx.runId);\n else\n await this.turns.settle(\n ctx.runId,\n input,\n milestone.outcome,\n Date.now() - begun.startedAt,\n );\n return true;\n });\n return { outcome: milestone.outcome.status };\n }\n let reply: HumanReply;\n try {\n reply = await ctx.waitForSignal<HumanReply>(\n decisionToken(ctx.runId, milestone.ask.id),\n milestone.timeoutMs !== undefined ? { timeoutMs: milestone.timeoutMs } : undefined,\n );\n } catch (error) {\n if (!(error instanceof SignalTimeoutError)) throw error;\n reply = { approved: false, expired: true } satisfies Decision;\n }\n const ask = milestone.ask;\n handle = await ctx.localStep(`reply:${n}`, () =>\n this.turns.reply(ctx.runId, input, handle, ask, reply),\n );\n }\n } catch (error) {\n if (isWorkflowControlFlowSignal(error)) throw error;\n await ctx.localStep('fail', async () => {\n await this.turns.settleFailed(ctx.runId, input, errorText(error, 'the turn failed'));\n return true;\n });\n return { outcome: 'failed' };\n }\n }\n\n private async cancelled(runId: string): Promise<boolean> {\n try {\n const status = (await this.runs?.getRunDetail(runId))?.run.status;\n return status === 'cancelling' || status === 'cancelled';\n } catch {\n return false;\n }\n }\n}\n"],"mappings":"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","names":["import_common","InMemoryOpenCodeSessionStore","refs","Map","get","threadId","set","ref","OPENCODE_HOST","Symbol","for","OPENCODE_SESSIONS","OPENCODE_OPTIONS","OPENCODE_TURNS","OPENCODE_MCP_ENDPOINT","OPENCODE_TOOLS_TOKENS","notAllowed","res","statusCode","setHeader","end","JSON","stringify","error","OpenCodeMcpController","endpoint","post","req","body","handle","get","delete","import_nestjs_agent_core","import_nestjs_agent_core","import_common","toQuestion","field","required","base","id","key","prompt","title","description","options","undefined","length","map","o","value","String","label","input","type","multiple","custom","allowFreeText","formFields","form","fields","filter","f","toElicitation","questions","first","preamble","source","FormAnswerError","Error","toFormAnswer","answers","out","question","values","defaults","problem","validateElicitationAnswer","present","v","Number","ASK_TOOL_NAME","FAILED_STATUSES","Set","emptySegment","text","reasoning","reasoningMs","calls","results","ui","isDecision","reply","approved","OpenCodeReplyMismatchError","ConflictException","runId","toolCallId","name","permissionArgs","req","metadata","nested","input","args","HIDDEN_TOOLS","errorText","error","fallback","length","message","OpenCodeTurn","chain","Promise","resolve","segment","tools","Map","messageResults","asked","hidden","milestones","waiting","usage","inputTokens","outputTokens","costUsd","stepOpen","sawText","separator","reasoningSince","wroteMessage","ended","stepError","a","sessionId","finished","handle","event","enqueue","onEvent","fail","end","status","pushUi","component","reject","then","step","at","findIndex","c","id","push","write","kind","next","ready","shift","undefined","hasMilestone","catchUp","client","permissions","permission","list","sessionID","forms","session","form","p","onPermission","f","onForm","decide","ask","opts","tell","tellOpenCode","decided","answered","reach","milestone","work","catch","logger","outcome","writer","encodeStreamEvent","endReasoning","Date","now","tool","state","get","announced","available","settled","innerAnnounced","innerSettled","set","announce","toolKind","makeAvailable","setInput","Object","assign","innerCalls","parentId","raw","Array","isArray","parent","index","call","entries","String","has","add","toLowerCase","output","e","d","data","type","delta","trim","size","settleTool","toolCalls","stepEnded","title","store","setTitle","threadId","ok","Number","tokens","cache","read","cacheReadTokens","cacheWriteTokens","cost","recordUsage","actorRef","actor","modelId","modelLabel","purpose","model","flush","final","s","empty","appendMessage","role","content","agentName","persona","toolResults","alreadyRecorded","toolCallApproval","messageOf","thread","getThread","messages","find","m","some","recovering","action","messageId","approver","expiresAt","timeoutMs","Math","max","parse","requirement","approvalFor","remembered","required","rememberedApprovals","includes","onGranted","requestID","decision","decidedVia","remember","ttlMs","isFinite","floor","toISOString","recordToolCall","toolName","toolType","expired","reason","result","rejected","denied","updateToolCall","executedByRef","addResult","decidedBy","request","toElicitation","preamble","questions","answer","answers","skipped","cancel","formID","toFormAnswer","settleElicitation","answeredByRef","answeredVia","known","filter","r","setMessageToolResults","LOOP_SERVED_KINDS","Set","b64url","data","Buffer","from","toString","OpenCodeToolsTokens","key","secret","ttlMs","createHash","update","randomBytes","digest","mint","actor","server","now","Date","claims","v","exp","body","JSON","stringify","sign","verify","token","signature","extra","split","undefined","expected","given","length","timingSafeEqual","parse","id","createHmac","isZodSchema","schema","vendor","toInputSchema","extension","schemaExtensionOf","base","properties","converted","toJsonSchemaCompat","converter","jsonSchema","input","type","additionalProperties","_type","rest","asText","output","OpenCodeToolRefusedError","Error","name","OpenCodeMcpEndpoint","turns","tokens","authenticate","authorization","header","Array","isArray","match","exec","trim","handle","req","res","headers","statusCode","setHeader","end","error","transport","StreamableHTTPServerTransport","enableJsonResponse","on","close","connect","handleRequest","headersSent","jsonrpc","code","message","errorText","Server","version","capabilities","tools","call","meta","requestId","callContext","serverKey","String","setRequestHandler","ListToolsRequestSchema","request","turn","params","_meta","allowed","allowedTools","definitions","registry","definitionsFor","rolesPolicyFor","filter","definition","has","kind","map","description","inputSchema","annotations","readOnlyHint","memoryWritable","push","REMEMBER_TOOL_NAME","REMEMBER_TOOL_DESCRIPTION","rememberInputSchema","CallToolRequestSchema","arguments","args","remember","invoke","content","text","isError","spec","ToolNotFoundError","includes","spendApproval","runId","threadId","ctx","emitUi","agentName","persona","pageContext","parsed","validate","issues","issue","join","value","import_nestjs_agent_core","import_common","import_node_crypto","import_nestjs_agent_core","import_common","import_common","sessionOf","event","id","data","sessionID","form","undefined","DEFAULT_CONNECT_TIMEOUT_MS","OpenCodeEventHub","logger","Logger","name","streams","Map","options","listen","serverKey","client","sessionId","listener","stream","streamFor","set","listeners","get","Set","add","ready","live","current","delete","size","controller","abort","close","values","clear","existing","AbortController","opened","Promise","resolve","timeoutMs","connectTimeoutMs","timer","setTimeout","warn","unref","then","clearTimeout","signal","addEventListener","once","pump","backoff","aborted","events","subscribe","error","message","Math","min","DEFAULT_TURN_TIMEOUT_MS","DEFAULT_TOOLS_TTL_MS","OpenCodeTurns","logger","Logger","events","OpenCodeEventHub","live","Map","grants","spent","Set","toolsIssued","host","sessions","settings","store","sink","deps","registry","skills","memory","queue","toolsTokens","toolsServer","tools","server","rolesPolicyFor","input","forAgent","agentName","rolesPolicy","allowedTools","agent","toolAllowList","persona","undefined","personas","find","p","id","filter","name","includes","memoryWritable","provider","write","remember","turn","bind","max","maxFactChars","DEFAULT_MAX_FACT_CHARS","fact","length","actor","scopeCtx","threadId","ctx","scopes","defaultScopeResolver","resolve","scope","actorScope","verdict","memoryWriteVerdict","author","kind","allowed","reason","key","text","origin","actorRef","runId","callContext","call","sessionId","sessionOfMeta","meta","requestId","randomUUID","handle","serverKey","emitUi","uiEmitter","component","pushUi","uiPushed","threadOfSession","ownerOfThread","known","get","activeRun","userText","writer","open","encodeStreamEvent","appendMessage","role","content","ui","spendApproval","tool","names","local","grant","has","action","add","thread","getThread","message","messages","toolCalls","result","toolResults","r","approved","output","activeRunForThread","activeRunId","onUi","catch","error","warn","errorText","pushToSession","liveRuns","keys","info","client","session","sessionID","metadata","onApplicationShutdown","values","stop","clear","close","begin","earlier","prepareThread","reusable","bootId","reuse","created","directory","regenerate","revertLastExchange","addTools","createSession","set","beforePrompt","refreshInstructions","note","context","spec","location","writeSkills","create","permissions","toolRules","map","resource","effect","prepare","transcript","transcriptOf","historyMessages","instructions","entry","put","value","Boolean","join","lastUser","i","firstDropped","truncateFrom","slice","Math","mine","findIndex","m","attachments","title","setTitle","titleOf","revert","page","list","order","limit","last","data","type","stage","messageID","files","commit","memoryBlock","entries","systemKey","systemPrompt","Object","pageContext","uiCapabilities","base","sections","contribute","promptContributors","section","push","scopeContext","records","digest","resolveMemoryDigest","maxMemories","buildMemoryBlock","writable","partial","omitted","file","summaries","resolveSkillCatalog","maxSkills","dir","skillsDir","written","body","load","JSON","stringify","description","path","payload","TextEncoder","encode","allow","both","rules","allSpecs","offered","LOOP_SERVED_KINDS","fresh","tokens","mcp","issued","ttl","ttlMs","Date","now","config","url","headers","Authorization","mint","oauth","prompt","ensureLive","promptFor","fail","observe","hasMilestone","reached","next","done","then","milestone","timeoutMs","turnTimeoutMs","timer","setTimeout","unref","wait","Promise","finished","catchUp","setImmediate","clearTimeout","reply","ask","continueAfterRestart","decide","answers","drop","tellOpenCode","interrupt","current","policy","approvalPolicy","DefaultApprovalPolicy","sinkRunId","OpenCodeTurn","approvalFor","requirementFor","modelLabel","model","onGranted","listen","event","delete","forget","onAsk","runResult","outcome","durationMs","usage","inputTokens","outputTokens","costUsd","amend","beforeSettle","amendment","at","setMessageUi","settled","onSettled","settle","status","settleFailed","log","failUnsettledToolCalls","RUN_ENDED_BEFORE_TOOL_CALL","handoff","releaseThreadRun","end","recordRunEnd","worded","streamFailure","Error","publishAgentRunFailed","code","errorCode","errorMessage","startNext","supported","deliverTo","frame","nextRunId","failure","String","trimmed","trim","replace","SESSION_META_KEY","props","options","Array","isArray","parse","version","OpenCodeAgentRunner","live","Set","cancelled","pending","Map","turns","settings","startNext","next","runId","start","runIdFor","input","crypto","randomUUID","isRunActive","has","key","keys","startsWith","options","add","run","finally","delete","signal","toolCallId","reply","waiter","get","undefined","on","isDecision","OpenCodeReplyMismatchError","resolve","cancel","reject","RunCancelledError","inputs","interrupt","catch","started","Date","now","set","handle","begin","prompt","milestone","observe","kind","settle","outcome","park","ask","id","timeoutMs","error","status","settleFailed","errorText","waiting","Promise","timer","lapse","setTimeout","approved","expired","unref","race","clearTimeout","isInstance","value","method","bind","token","provide","useValue","useExisting","openCodeControllers","options","tools","undefined","OpenCodeMcpController","DEFAULT_TOOLS_TTL_MS","toolsTokens","settings","secret","Logger","warn","OpenCodeToolsTokens","ttlMs","openCodeProviders","host","sessions","bind","OPENCODE_HOST","OPENCODE_SESSIONS","InMemoryOpenCodeSessionStore","provide","OPENCODE_OPTIONS","useValue","OPENCODE_TOOLS_TOKENS","useFactory","OpenCodeTurns","OPENCODE_TURNS","useExisting","OPENCODE_MCP_ENDPOINT","turns","tokens","OpenCodeMcpEndpoint","inject","import_node_crypto","import_nestjs_agent_core","import_nestjs_durable","import_nestjs_durable_core","import_common","import_common","OPENCODE_RUN_WORKFLOW","decisionToken","runId","toolCallId","OpenCodeRunWorkflow","turns","runs","run","ctx","input","begun","localStep","handle","begin","startedAt","Date","now","prompt","n","milestone","observe","kind","cancelled","drop","settle","outcome","status","reply","waitForSignal","ask","id","timeoutMs","undefined","error","SignalTimeoutError","approved","expired","isWorkflowControlFlowSignal","settleFailed","errorText","getRunDetail","name","version","isRunInput","value","threadId","actor","DurableOpenCodeAgentRunner","logger","Logger","name","workflows","runs","turns","settings","host","store","startNext","next","runId","start","runIdFor","input","randomUUID","options","durable","startOptions","OpenCodeRunWorkflow","error","isWorkflowControlFlowSignal","startError","isRunActive","status","getRunDetail","run","signal","toolCallId","reply","isDecision","call","toolCallApproval","approver","OpenCodeReplyMismatchError","decisionToken","cancel","log","then","detail","catch","undefined","interrupt","compensate","settle","openCodeDurable","options","name","providers","openCodeProviders","OpenCodeRunWorkflow","DurableOpenCodeAgentRunner","runner","exports","OpenCodeTurns","OPENCODE_TURNS","controllers","openCodeControllers"]}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { AgentEngine } from '@dudousxd/nestjs-agent';
|
|
2
|
+
import { O as OpenCodeTurns, a as OpenCodeEngineSettings, b as OpenCodeHost, c as OpenCodeEngineOptions } from '../engine-Bij6AdoF.cjs';
|
|
3
|
+
import { AgentRunner, AgentStore, AgentRunInput, AgentRunStartOptions, HumanReply } from '@dudousxd/nestjs-agent-core';
|
|
4
|
+
import { WorkflowService } from '@dudousxd/nestjs-durable';
|
|
5
|
+
import { RunGateway, WorkflowCtx } from '@dudousxd/nestjs-durable-core';
|
|
6
|
+
import '@nestjs/common';
|
|
7
|
+
import 'node:http';
|
|
8
|
+
import '@modelcontextprotocol/sdk/server/index.js';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Runs OpenCode turns as `@dudousxd/nestjs-durable` workflows ({@link OpenCodeRunWorkflow}): a
|
|
12
|
+
* person's decision is a durable signal, so a turn waiting on one survives restarts and is resumed
|
|
13
|
+
* by whichever process receives it. Needs a cross-process `TokenStreamSink` when more than one
|
|
14
|
+
* process serves the agent.
|
|
15
|
+
*/
|
|
16
|
+
declare class DurableOpenCodeAgentRunner implements AgentRunner {
|
|
17
|
+
private readonly workflows;
|
|
18
|
+
private readonly runs;
|
|
19
|
+
private readonly turns;
|
|
20
|
+
private readonly settings;
|
|
21
|
+
private readonly host;
|
|
22
|
+
private readonly store;
|
|
23
|
+
private readonly logger;
|
|
24
|
+
constructor(workflows: WorkflowService, runs: RunGateway, turns: OpenCodeTurns, settings: OpenCodeEngineSettings, host: OpenCodeHost, store: AgentStore);
|
|
25
|
+
runIdFor(input: AgentRunInput): string;
|
|
26
|
+
start(input: AgentRunInput, options?: AgentRunStartOptions): Promise<{
|
|
27
|
+
runId: string;
|
|
28
|
+
}>;
|
|
29
|
+
isRunActive(runId: string): Promise<boolean>;
|
|
30
|
+
/**
|
|
31
|
+
* Signal a person's reply into the run. Answers addressed at an approval (a call recorded with an
|
|
32
|
+
* approver; questions have none) are refused ({@link OpenCodeReplyMismatchError}, a 409) before
|
|
33
|
+
* they reach the workflow, which would otherwise spend its wait on them.
|
|
34
|
+
*/
|
|
35
|
+
signal(runId: string, toolCallId: string, reply: HumanReply): Promise<void>;
|
|
36
|
+
/**
|
|
37
|
+
* Interrupt OpenCode, cancel the run in the runtime (a run parked on a person never runs its body
|
|
38
|
+
* again), and settle it here: the queue, the thread, the `cancelled` frame and the run row.
|
|
39
|
+
*/
|
|
40
|
+
cancel(runId: string): Promise<void>;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
declare const OPENCODE_RUN_WORKFLOW = "agent.opencode.run";
|
|
44
|
+
/** The token a person's answer to `toolCallId` is signalled under — the library's own convention. */
|
|
45
|
+
declare function decisionToken(runId: string, toolCallId: string): string;
|
|
46
|
+
/**
|
|
47
|
+
* An OpenCode turn as a durable workflow:
|
|
48
|
+
*
|
|
49
|
+
* begin → prompt → observe:0 → [ wait for a person (signal `tool:<run>:<call>`) → reply:n → observe:n+1 ]* → finish
|
|
50
|
+
*
|
|
51
|
+
* Every step is checkpointed. A turn parked on a person is a suspended run with a signal waiter: an
|
|
52
|
+
* API restart loses nothing, and the decision resumes it on whichever process takes it — replaying
|
|
53
|
+
* the steps from their checkpoints and replying to OpenCode from there (`OpenCodeTurns` rebuilds the
|
|
54
|
+
* live turn, and re-prompts a fresh session when OpenCode itself restarted meanwhile). A process
|
|
55
|
+
* that dies while OpenCode works re-runs that `observe` step, which catches up on what OpenCode
|
|
56
|
+
* asked while nobody listened.
|
|
57
|
+
*/
|
|
58
|
+
declare class OpenCodeRunWorkflow {
|
|
59
|
+
private readonly turns;
|
|
60
|
+
private readonly runs?;
|
|
61
|
+
constructor(turns: OpenCodeTurns, runs?: RunGateway | undefined);
|
|
62
|
+
run(ctx: WorkflowCtx, input: AgentRunInput): Promise<{
|
|
63
|
+
outcome: string;
|
|
64
|
+
}>;
|
|
65
|
+
private cancelled;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* `openCode()` whose turns are durable workflows — `AgentModule.forRoot({ engine:
|
|
70
|
+
* openCodeDurable({ host }) })` next to a configured `DurableModule`. A turn waiting on a person
|
|
71
|
+
* survives restarts and is resumed by whichever process receives the decision.
|
|
72
|
+
*/
|
|
73
|
+
declare function openCodeDurable(options: OpenCodeEngineOptions): AgentEngine;
|
|
74
|
+
|
|
75
|
+
export { DurableOpenCodeAgentRunner, OPENCODE_RUN_WORKFLOW, OpenCodeRunWorkflow, decisionToken, openCodeDurable };
|