@coder/ai-sdk-agent 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/agent/coder-agent.ts","../src/errors.ts","../src/coder/types.ts","../src/coder/ws.ts","../src/coder/client.ts","../src/model/prompt.ts","../src/model/translate.ts","../src/model/language-model.ts"],"sourcesContent":["import {\n type Agent,\n type StopCondition,\n stepCountIs,\n type SystemModelMessage,\n type ToolChoice,\n ToolLoopAgent,\n type ToolSet,\n} from \"ai\";\nimport { CoderChatClient, type CoderChatClientOptions } from \"../coder/client.js\";\nimport { CoderAgentError } from \"../errors.js\";\nimport { CoderLanguageModel } from \"../model/language-model.js\";\n\ntype InnerAgent<TOOLS extends ToolSet> = ToolLoopAgent<never, TOOLS, never>;\n\n/** Default step ceiling. Each \"step\" is one client-tool round-trip; chatd caps\n * its own server-side loop at 1200 steps independently. */\nconst DEFAULT_STOP = stepCountIs(64);\n\nexport interface CoderAgentSettings<TOOLS extends ToolSet = {}> {\n // --- connection (provide a client, or baseUrl + token) ---\n /** A pre-built {@link CoderChatClient}. Mutually exclusive with baseUrl/token. */\n client?: CoderChatClient;\n /** Coder deployment base URL, e.g. `https://dev.coder.com`. */\n baseUrl?: string;\n /** Coder API/session token (sent as `Coder-Session-Token`). */\n token?: string;\n fetch?: CoderChatClientOptions[\"fetch\"];\n webSocketFactory?: CoderChatClientOptions[\"webSocketFactory\"];\n\n // --- Coder chat configuration ---\n /** Organization UUID that owns the chat (required). */\n organizationId: string;\n /** Model hint: UUID, `provider:model`, model id, or display-name substring. */\n model?: string;\n /** Bind the chat to a Coder workspace (enables workspace-scoped tools). */\n workspaceId?: string;\n /** chatd-side MCP servers to enable for this chat. */\n mcpServerIds?: string[];\n /** chatd plan mode. */\n planMode?: \"\" | \"plan\";\n /** Resume an existing chat (session) instead of creating a new one. */\n chatId?: string;\n\n // --- agent configuration ---\n /** Stable agent id (exposed as {@link CoderAgent.id}). */\n id?: string;\n /** System instructions → chatd `system_prompt`. */\n instructions?: string | SystemModelMessage | Array<SystemModelMessage>;\n /** Custom (client-executed) tools. Each should have an `execute` for scripting. */\n tools?: TOOLS;\n toolChoice?: ToolChoice<NoInfer<TOOLS>>;\n /** Stop condition(s) for the AI SDK loop. Default `stepCountIs(64)`. */\n stopWhen?: StopCondition<NoInfer<TOOLS>> | Array<StopCondition<NoInfer<TOOLS>>>;\n /**\n * SDK-level retries. Default `0`: this agent owns server-side chat state, so\n * SDK retries could duplicate a turn. Override with care.\n */\n maxRetries?: number;\n}\n\n/**\n * An AI SDK-compliant agent backed by a remote Coder `chatd` agent runtime.\n *\n * `new CoderAgent({ ... })` returns an object that implements the AI SDK\n * `Agent` interface (`generate()`/`stream()`), so it composes with the rest of\n * the AI SDK ecosystem. Internally it wraps a {@link ToolLoopAgent} whose model\n * is a {@link CoderLanguageModel}; chatd runs the actual agent loop server-side.\n *\n * One `CoderAgent` instance corresponds to one chatd chat (\"session\"): the chat\n * is created on the first `generate()`/`stream()` and reused for subsequent\n * turns. Use {@link CoderAgent.resetSession} to start a fresh chat.\n */\nexport class CoderAgent<TOOLS extends ToolSet = {}> implements Agent<never, TOOLS, never> {\n readonly version = \"agent-v1\" as const;\n\n readonly #client: CoderChatClient;\n readonly #model: CoderLanguageModel;\n readonly #inner: InnerAgent<TOOLS>;\n\n constructor(settings: CoderAgentSettings<TOOLS>) {\n if (settings.client) {\n this.#client = settings.client;\n } else if (settings.baseUrl && settings.token) {\n this.#client = new CoderChatClient({\n baseUrl: settings.baseUrl,\n token: settings.token,\n fetch: settings.fetch,\n webSocketFactory: settings.webSocketFactory,\n });\n } else {\n throw new CoderAgentError(\n \"CoderAgent requires either `client` or both `baseUrl` and `token`.\",\n );\n }\n\n this.#model = new CoderLanguageModel({\n client: this.#client,\n organizationId: settings.organizationId,\n model: settings.model,\n workspaceId: settings.workspaceId,\n mcpServerIds: settings.mcpServerIds,\n planMode: settings.planMode,\n chatId: settings.chatId,\n });\n\n this.#inner = new ToolLoopAgent<never, TOOLS, never>({\n model: this.#model,\n id: settings.id,\n instructions: settings.instructions,\n tools: settings.tools,\n toolChoice: settings.toolChoice,\n stopWhen: settings.stopWhen ?? DEFAULT_STOP,\n maxRetries: settings.maxRetries ?? 0,\n });\n }\n\n get id(): string | undefined {\n return this.#inner.id;\n }\n\n get tools(): TOOLS {\n return this.#inner.tools;\n }\n\n /** The underlying chatd client. */\n get client(): CoderChatClient {\n return this.#client;\n }\n\n /** The current chatd chat id, once a turn has started. */\n get chatId(): string | undefined {\n return this.#model.chatId;\n }\n\n generate(\n options: Parameters<InnerAgent<TOOLS>[\"generate\"]>[0],\n ): ReturnType<InnerAgent<TOOLS>[\"generate\"]> {\n return this.#inner.generate(options);\n }\n\n stream(\n options: Parameters<InnerAgent<TOOLS>[\"stream\"]>[0],\n ): ReturnType<InnerAgent<TOOLS>[\"stream\"]> {\n return this.#inner.stream(options);\n }\n\n // --- session helpers ------------------------------------------------------\n\n /** Start a fresh chatd chat on the next turn. */\n resetSession(): void {\n this.#model.resetSession();\n }\n\n /** Interrupt the in-flight generation, if any. */\n async interrupt(): Promise<void> {\n const id = this.#model.chatId;\n if (id) await this.#client.interruptChat(id);\n }\n\n /** Archive the underlying chat (safe cleanup; hides it from listings). */\n async archive(): Promise<void> {\n const id = this.#model.chatId;\n if (id) await this.#client.archiveChat(id);\n }\n}\n","import type { ChatErrorPayload } from \"./coder/types.js\";\n\n/** Base error for all `@coder/ai-sdk-agent` failures. */\nexport class CoderAgentError extends Error {\n override name = \"CoderAgentError\";\n constructor(message: string, options?: { cause?: unknown }) {\n super(message, options);\n }\n}\n\n/** An HTTP request to the Coder API failed. */\nexport class CoderApiError extends CoderAgentError {\n override name = \"CoderApiError\";\n readonly status: number;\n readonly detail: string | undefined;\n readonly method: string;\n readonly path: string;\n constructor(args: {\n status: number;\n method: string;\n path: string;\n message: string;\n detail?: string;\n }) {\n super(\n `Coder API ${args.method} ${args.path} failed (${args.status}): ${args.message}` +\n (args.detail ? ` — ${args.detail}` : \"\"),\n );\n this.status = args.status;\n this.detail = args.detail;\n this.method = args.method;\n this.path = args.path;\n }\n}\n\n/** A chat generation ended in an error status. */\nexport class CoderChatError extends CoderAgentError {\n override name = \"CoderChatError\";\n readonly kind: string | undefined;\n readonly provider: string | undefined;\n readonly retryable: boolean;\n readonly statusCode: number | undefined;\n constructor(payload: ChatErrorPayload) {\n super(payload.detail ? `${payload.message}: ${payload.detail}` : payload.message);\n this.kind = payload.kind;\n this.provider = payload.provider;\n this.retryable = payload.retryable ?? false;\n this.statusCode = payload.status_code;\n }\n}\n","/**\n * Wire types for Coder's experimental `chatd` chat API\n * (`/api/experimental/chats`). These mirror the Go types in\n * `coder/coder`'s `codersdk/chats.go` (JSON shapes), restricted to the subset\n * this client uses. Field names use snake_case to match the wire format.\n *\n * NOTE: The chatd API is experimental and may change between Coder releases.\n */\n\n// ---------------------------------------------------------------------------\n// Input (client -> server)\n// ---------------------------------------------------------------------------\n\nexport type ChatInputPartType = \"text\" | \"file\" | \"file-reference\";\n\nexport interface ChatInputPart {\n type: ChatInputPartType;\n text?: string;\n file_id?: string;\n file_name?: string;\n start_line?: number;\n end_line?: number;\n content?: string;\n}\n\nexport type ChatClientType = \"ui\" | \"api\";\nexport type ChatPlanMode = \"\" | \"plan\";\nexport type ChatBusyBehavior = \"queue\" | \"interrupt\";\n\n/**\n * A client-executed (\"dynamic\") tool definition. chatd never executes these;\n * when the model calls one, the chat enters `requires_action` and the client\n * must execute it and submit results via {@link SubmitToolResultsRequest}.\n *\n * NOTE: the JSON key is `input_schema` (snake_case), per chatd.\n */\nexport interface DynamicTool {\n name: string;\n description?: string;\n /** A JSON Schema object describing the tool input. */\n input_schema: unknown;\n}\n\nexport interface CreateChatRequest {\n organization_id: string;\n content: ChatInputPart[];\n system_prompt?: string;\n workspace_id?: string;\n model_config_id?: string;\n mcp_server_ids?: string[];\n labels?: Record<string, string>;\n unsafe_dynamic_tools?: DynamicTool[];\n plan_mode?: ChatPlanMode;\n client_type?: ChatClientType;\n}\n\nexport interface CreateChatMessageRequest {\n content: ChatInputPart[];\n model_config_id?: string;\n mcp_server_ids?: string[];\n busy_behavior?: ChatBusyBehavior;\n plan_mode?: ChatPlanMode;\n}\n\n/** Result of a single client-executed tool call. */\nexport interface ToolResult {\n tool_call_id: string;\n /** JSON-serializable tool output. */\n output: unknown;\n is_error?: boolean;\n}\n\nexport interface SubmitToolResultsRequest {\n results: ToolResult[];\n}\n\nexport interface UpdateChatRequest {\n title?: string;\n archived?: boolean;\n}\n\n// ---------------------------------------------------------------------------\n// Output (server -> client)\n// ---------------------------------------------------------------------------\n\nexport type ChatStatus =\n | \"waiting\"\n | \"pending\"\n | \"running\"\n | \"paused\"\n | \"completed\"\n | \"error\"\n | \"requires_action\"\n | \"interrupting\";\n\nexport type ChatMessageRole = \"system\" | \"user\" | \"assistant\" | \"tool\";\n\nexport type ChatMessagePartType =\n | \"text\"\n | \"reasoning\"\n | \"tool-call\"\n | \"tool-result\"\n | \"source\"\n | \"file\"\n | \"file-reference\"\n | \"context-file\"\n | \"skill\";\n\n/**\n * A part of a chat message. chatd models this as a single flat struct with a\n * `type` discriminator and many optional fields (see `codersdk.ChatMessagePart`),\n * so we mirror that shape rather than a strict discriminated union.\n */\nexport interface ChatMessagePart {\n type: ChatMessagePartType;\n\n // text / reasoning\n text?: string;\n signature?: string;\n\n // tool-call / tool-result\n tool_call_id?: string;\n tool_name?: string;\n mcp_server_config_id?: string | null;\n /** tool-call: complete arguments (JSON value). */\n args?: unknown;\n /** tool-call: incremental argument text chunk during streaming. */\n args_delta?: string;\n parsed_commands?: string[][];\n /** tool-result: complete result (JSON value). */\n result?: unknown;\n /** tool-result: incremental result text chunk during streaming. */\n result_delta?: string;\n result_reset?: boolean;\n is_error?: boolean;\n is_media?: boolean;\n provider_executed?: boolean;\n created_at?: string;\n completed_at?: string;\n\n // source\n source_id?: string;\n url?: string;\n title?: string;\n\n // file\n media_type?: string;\n name?: string;\n file_id?: string | null;\n\n // file-reference\n file_name?: string;\n start_line?: number;\n end_line?: number;\n content?: string;\n\n // skill\n skill_name?: string;\n skill_description?: string;\n}\n\nexport interface ChatMessageUsage {\n input_tokens?: number;\n output_tokens?: number;\n total_tokens?: number;\n reasoning_tokens?: number;\n cache_creation_tokens?: number;\n cache_read_tokens?: number;\n context_limit?: number;\n}\n\nexport interface ChatMessage {\n id: number;\n chat_id: string;\n created_by?: string;\n model_config_id?: string;\n created_at: string;\n role: ChatMessageRole;\n content?: ChatMessagePart[];\n usage?: ChatMessageUsage;\n}\n\nexport interface ChatErrorPayload {\n message: string;\n detail?: string;\n kind?: string;\n provider?: string;\n retryable?: boolean;\n status_code?: number;\n}\n\nexport interface Chat {\n id: string;\n organization_id: string;\n owner_id: string;\n owner_username?: string;\n workspace_id?: string | null;\n agent_id?: string | null;\n parent_chat_id?: string | null;\n root_chat_id?: string | null;\n last_model_config_id?: string;\n title: string;\n status: ChatStatus;\n plan_mode?: ChatPlanMode;\n last_error?: ChatErrorPayload | null;\n created_at: string;\n updated_at: string;\n archived: boolean;\n mcp_server_ids?: string[];\n client_type?: ChatClientType;\n}\n\nexport interface ChatQueuedMessage {\n id: number;\n chat_id: string;\n content: ChatMessagePart[];\n created_at: string;\n}\n\nexport interface CreateChatMessageResponse {\n message?: ChatMessage;\n queued_message?: ChatQueuedMessage;\n queued: boolean;\n warnings?: string[];\n}\n\nexport interface ChatMessagesResponse {\n messages: ChatMessage[];\n queued_messages: ChatQueuedMessage[];\n has_more: boolean;\n}\n\nexport interface ChatModelConfig {\n id: string;\n provider: string;\n ai_provider_id?: string;\n model: string;\n display_name: string;\n enabled?: boolean;\n is_default?: boolean;\n context_limit?: number;\n compression_threshold?: number;\n}\n\n// ---------------------------------------------------------------------------\n// Stream events (WebSocket `/stream`)\n// ---------------------------------------------------------------------------\n\nexport type ChatStreamEventType =\n | \"message_part\"\n | \"message\"\n | \"status\"\n | \"error\"\n | \"queue_update\"\n | \"retry\"\n | \"action_required\"\n | \"preview_reset\"\n | \"history_reset\";\n\nexport interface ChatStreamMessagePart {\n role?: ChatMessageRole;\n part: ChatMessagePart;\n history_version?: number;\n generation_attempt?: number;\n seq?: number;\n}\n\nexport interface ChatStreamStatus {\n status: ChatStatus;\n}\n\nexport interface ChatStreamToolCall {\n tool_call_id: string;\n tool_name: string;\n /** JSON string of the tool-call arguments. */\n args: string;\n}\n\nexport interface ChatStreamActionRequired {\n tool_calls: ChatStreamToolCall[];\n}\n\nexport interface ChatStreamRetry {\n attempt: number;\n delay_ms: number;\n error: string;\n kind?: string;\n provider?: string;\n status_code?: number;\n retrying_at: string;\n}\n\nexport interface ChatStreamEvent {\n type: ChatStreamEventType;\n chat_id: string;\n message?: ChatMessage;\n message_part?: ChatStreamMessagePart;\n status?: ChatStreamStatus;\n error?: ChatErrorPayload;\n retry?: ChatStreamRetry;\n queued_messages?: ChatQueuedMessage[];\n action_required?: ChatStreamActionRequired;\n}\n\n/** Terminal statuses: the chat has stopped generating for this turn. */\nexport const TERMINAL_STATUSES: ReadonlySet<ChatStatus> = new Set<ChatStatus>([\n \"waiting\",\n \"completed\",\n \"error\",\n \"requires_action\",\n]);\n","import NodeWebSocket from \"ws\";\nimport { CoderAgentError } from \"../errors.js\";\nimport type { ChatStreamEvent } from \"./types.js\";\n\n/**\n * A minimal WebSocket factory abstraction so the stream reader can run on\n * Node (via the `ws` package, with header auth) or in environments that\n * provide a global `WebSocket` (browsers, where auth must go in the query\n * string). Node is the default target.\n */\nexport interface WebSocketLike {\n send(data: string): void;\n close(code?: number): void;\n addEventListener(type: \"open\", cb: () => void): void;\n addEventListener(type: \"message\", cb: (ev: { data: unknown }) => void): void;\n addEventListener(type: \"error\", cb: (ev: unknown) => void): void;\n addEventListener(type: \"close\", cb: (ev: { code?: number; reason?: string }) => void): void;\n removeEventListener(type: \"open\", cb: () => void): void;\n removeEventListener(type: \"message\", cb: (ev: { data: unknown }) => void): void;\n removeEventListener(type: \"error\", cb: (ev: unknown) => void): void;\n removeEventListener(type: \"close\", cb: (ev: { code?: number; reason?: string }) => void): void;\n}\n\nexport type WebSocketFactory = (\n url: string,\n protocols: { headers: Record<string, string> },\n) => WebSocketLike;\n\nconst defaultFactory: WebSocketFactory = (url, { headers }) => {\n // `ws` accepts custom handshake headers, which lets us authenticate with the\n // `Coder-Session-Token` header instead of leaking the token into the URL.\n return new NodeWebSocket(url, { headers }) as unknown as WebSocketLike;\n};\n\nfunction httpToWs(baseUrl: string): string {\n if (baseUrl.startsWith(\"https://\")) return `wss://${baseUrl.slice(\"https://\".length)}`;\n if (baseUrl.startsWith(\"http://\")) return `ws://${baseUrl.slice(\"http://\".length)}`;\n return baseUrl;\n}\n\nexport interface StreamChatEventsOptions {\n baseUrl: string;\n token: string;\n chatId: string;\n /** Only stream events for messages with id greater than this. */\n afterId?: number;\n signal?: AbortSignal;\n webSocketFactory?: WebSocketFactory;\n}\n\n/**\n * Opens the chatd `/stream` WebSocket and yields decoded {@link ChatStreamEvent}s\n * as an async iterable. Each text frame from chatd is a JSON array of events;\n * we flatten them into a single stream.\n *\n * The chat stream is a live subscription that stays open after a turn settles,\n * so callers should `break` out of the loop once they observe a terminal status\n * — that triggers generator cleanup, which closes the socket.\n */\nexport async function* streamChatEvents(\n options: StreamChatEventsOptions,\n): AsyncGenerator<ChatStreamEvent, void, void> {\n const { baseUrl, token, chatId, afterId, signal } = options;\n const factory = options.webSocketFactory ?? defaultFactory;\n\n const wsBase = httpToWs(baseUrl);\n const query = afterId !== undefined ? `?after_id=${afterId}` : \"\";\n const url = `${wsBase}/api/experimental/chats/${chatId}/stream${query}`;\n\n const queue: ChatStreamEvent[] = [];\n let resolveNext: (() => void) | undefined;\n let finished = false;\n let failure: Error | undefined;\n\n const wake = () => {\n resolveNext?.();\n resolveNext = undefined;\n };\n\n const ws = factory(url, { headers: { \"Coder-Session-Token\": token } });\n\n const onAbort = () => {\n finished = true;\n try {\n ws.close(1000);\n } catch {\n /* ignore */\n }\n wake();\n };\n let abortListenerAdded = false;\n if (signal) {\n if (signal.aborted) onAbort();\n else {\n signal.addEventListener(\"abort\", onAbort, { once: true });\n abortListenerAdded = true;\n }\n }\n\n const onMessage = (ev: { data: unknown }): void => {\n if (finished) return;\n let batch: unknown;\n try {\n const data = typeof ev.data === \"string\" ? ev.data : String(ev.data);\n batch = JSON.parse(data);\n } catch (err) {\n failure = new CoderAgentError(\"failed to parse chat stream frame\", { cause: err });\n finished = true;\n wake();\n return;\n }\n if (Array.isArray(batch)) {\n for (const e of batch) queue.push(e as ChatStreamEvent);\n } else if (batch && typeof batch === \"object\") {\n queue.push(batch as ChatStreamEvent);\n }\n wake();\n };\n const onError = (ev: unknown): void => {\n if (finished) return;\n const message =\n ev && typeof ev === \"object\" && \"message\" in ev\n ? String((ev as { message: unknown }).message)\n : \"chat stream socket error\";\n failure = new CoderAgentError(message);\n finished = true;\n wake();\n };\n const onClose = (): void => {\n finished = true;\n wake();\n };\n ws.addEventListener(\"message\", onMessage);\n ws.addEventListener(\"error\", onError);\n ws.addEventListener(\"close\", onClose);\n\n try {\n while (true) {\n while (queue.length > 0) {\n const next = queue.shift() as ChatStreamEvent;\n yield next;\n }\n if (failure) throw failure;\n if (finished) return;\n await new Promise<void>((resolve) => {\n resolveNext = resolve;\n });\n }\n } finally {\n finished = true;\n if (signal && abortListenerAdded) signal.removeEventListener(\"abort\", onAbort);\n ws.removeEventListener(\"message\", onMessage);\n ws.removeEventListener(\"error\", onError);\n ws.removeEventListener(\"close\", onClose);\n try {\n ws.close(1000);\n } catch {\n /* ignore */\n }\n }\n}\n","import { CoderApiError } from \"../errors.js\";\nimport {\n type Chat,\n type ChatMessagesResponse,\n type ChatModelConfig,\n type ChatStreamEvent,\n type CreateChatMessageRequest,\n type CreateChatMessageResponse,\n type CreateChatRequest,\n type SubmitToolResultsRequest,\n type UpdateChatRequest,\n} from \"./types.js\";\nimport { streamChatEvents, type WebSocketFactory } from \"./ws.js\";\n\nexport interface CoderChatClientOptions {\n /** Base URL of the Coder deployment, e.g. `https://dev.coder.com`. */\n baseUrl: string;\n /** Coder API token or session token (sent as `Coder-Session-Token`). */\n token: string;\n /** Custom fetch implementation (defaults to global `fetch`). */\n fetch?: typeof globalThis.fetch;\n /** Custom WebSocket factory (defaults to the `ws` package on Node). */\n webSocketFactory?: WebSocketFactory;\n}\n\nconst API_PREFIX = \"/api/experimental/chats\";\n\n/**\n * A thin, typed client for Coder's experimental `chatd` API. This is a\n * TypeScript port of the chat surface of `codersdk.ExperimentalClient`.\n */\nexport class CoderChatClient {\n readonly baseUrl: string;\n readonly #token: string;\n readonly #fetch: typeof globalThis.fetch;\n readonly #webSocketFactory: WebSocketFactory | undefined;\n\n constructor(options: CoderChatClientOptions) {\n // Normalize: strip a single trailing slash.\n this.baseUrl = options.baseUrl.replace(/\\/$/, \"\");\n this.#token = options.token;\n this.#fetch = options.fetch ?? globalThis.fetch.bind(globalThis);\n this.#webSocketFactory = options.webSocketFactory;\n }\n\n async #request<T>(\n method: string,\n path: string,\n body?: unknown,\n signal?: AbortSignal,\n ): Promise<T> {\n const headers: Record<string, string> = { \"Coder-Session-Token\": this.#token };\n if (body !== undefined) headers[\"Content-Type\"] = \"application/json\";\n\n const res = await this.#fetch(`${this.baseUrl}${path}`, {\n method,\n headers,\n body: body === undefined ? undefined : JSON.stringify(body),\n signal,\n });\n\n const text = await res.text();\n let parsed: unknown;\n try {\n parsed = text.length > 0 ? JSON.parse(text) : undefined;\n } catch {\n parsed = undefined;\n }\n\n if (!res.ok) {\n const errObj = (parsed ?? {}) as { message?: string; detail?: string };\n throw new CoderApiError({\n status: res.status,\n method,\n path,\n message: errObj.message ?? res.statusText ?? \"request failed\",\n detail: errObj.detail,\n });\n }\n return parsed as T;\n }\n\n // --- REST -----------------------------------------------------------------\n\n listModelConfigs(signal?: AbortSignal): Promise<ChatModelConfig[]> {\n return this.#request<ChatModelConfig[]>(\n \"GET\",\n `${API_PREFIX}/model-configs`,\n undefined,\n signal,\n );\n }\n\n createChat(req: CreateChatRequest, signal?: AbortSignal): Promise<Chat> {\n return this.#request<Chat>(\"POST\", API_PREFIX, req, signal);\n }\n\n getChat(chatId: string, signal?: AbortSignal): Promise<Chat> {\n return this.#request<Chat>(\"GET\", `${API_PREFIX}/${chatId}`, undefined, signal);\n }\n\n createChatMessage(\n chatId: string,\n req: CreateChatMessageRequest,\n signal?: AbortSignal,\n ): Promise<CreateChatMessageResponse> {\n return this.#request<CreateChatMessageResponse>(\n \"POST\",\n `${API_PREFIX}/${chatId}/messages`,\n req,\n signal,\n );\n }\n\n getMessages(\n chatId: string,\n opts?: { before_id?: number; after_id?: number; limit?: number },\n signal?: AbortSignal,\n ): Promise<ChatMessagesResponse> {\n const params = new URLSearchParams();\n if (opts?.before_id !== undefined) params.set(\"before_id\", String(opts.before_id));\n if (opts?.after_id !== undefined) params.set(\"after_id\", String(opts.after_id));\n if (opts?.limit !== undefined) params.set(\"limit\", String(opts.limit));\n const q = params.toString();\n return this.#request<ChatMessagesResponse>(\n \"GET\",\n `${API_PREFIX}/${chatId}/messages${q ? `?${q}` : \"\"}`,\n undefined,\n signal,\n );\n }\n\n submitToolResults(\n chatId: string,\n req: SubmitToolResultsRequest,\n signal?: AbortSignal,\n ): Promise<void> {\n return this.#request<void>(\"POST\", `${API_PREFIX}/${chatId}/tool-results`, req, signal);\n }\n\n interruptChat(chatId: string, signal?: AbortSignal): Promise<Chat> {\n return this.#request<Chat>(\"POST\", `${API_PREFIX}/${chatId}/interrupt`, undefined, signal);\n }\n\n updateChat(chatId: string, req: UpdateChatRequest, signal?: AbortSignal): Promise<void> {\n return this.#request<void>(\"PATCH\", `${API_PREFIX}/${chatId}`, req, signal);\n }\n\n /** Convenience: archive a chat (soft-hide; safe for cleanup). */\n archiveChat(chatId: string, signal?: AbortSignal): Promise<void> {\n return this.updateChat(chatId, { archived: true }, signal);\n }\n\n // --- Streaming ------------------------------------------------------------\n\n streamEvents(\n chatId: string,\n opts?: { afterId?: number; signal?: AbortSignal },\n ): AsyncGenerator<ChatStreamEvent, void, void> {\n return streamChatEvents({\n baseUrl: this.baseUrl,\n token: this.#token,\n chatId,\n afterId: opts?.afterId,\n signal: opts?.signal,\n webSocketFactory: this.#webSocketFactory,\n });\n }\n\n // --- Helpers --------------------------------------------------------------\n\n /**\n * Resolves a user-friendly model hint to a model-config UUID.\n *\n * Accepts: a config UUID (returned as-is), a `provider:model` id\n * (e.g. `anthropic:claude-haiku-4-5-20251001`), a bare model id, or a\n * display-name substring (case-insensitive). Returns `undefined` if no\n * match is found, in which case the caller should let chatd pick the default.\n */\n async resolveModelConfigId(hint: string, signal?: AbortSignal): Promise<string | undefined> {\n const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\n if (UUID_RE.test(hint)) return hint;\n\n const configs = await this.listModelConfigs(signal);\n const lower = hint.toLowerCase();\n // `provider:model` form.\n const colon = hint.indexOf(\":\");\n const provider = colon >= 0 ? hint.slice(0, colon).toLowerCase() : undefined;\n const model = colon >= 0 ? hint.slice(colon + 1).toLowerCase() : lower;\n\n const candidates = configs.filter((c) => c.enabled !== false);\n const pool = candidates.length > 0 ? candidates : configs;\n\n const exact = pool.find(\n (c) =>\n c.model.toLowerCase() === model &&\n (provider === undefined || c.provider.toLowerCase() === provider),\n );\n if (exact) return exact.id;\n\n const byModel = pool.find((c) => c.model.toLowerCase() === model);\n if (byModel) return byModel.id;\n\n const byDisplay = pool.find((c) => c.display_name.toLowerCase().includes(lower));\n if (byDisplay) return byDisplay.id;\n\n const byModelSubstring = pool.find((c) => c.model.toLowerCase().includes(model));\n return byModelSubstring?.id;\n }\n}\n","import type {\n LanguageModelV3CallOptions,\n LanguageModelV3Message,\n LanguageModelV3Prompt,\n LanguageModelV3ToolResultOutput,\n} from \"@ai-sdk/provider\";\nimport type { ChatInputPart, DynamicTool, ToolResult } from \"../coder/types.js\";\n\n/** Concatenated system messages, mapped to chatd's `system_prompt`. */\nexport function extractSystemPrompt(prompt: LanguageModelV3Prompt): string | undefined {\n const parts = prompt.filter(\n (m): m is Extract<LanguageModelV3Message, { role: \"system\" }> => m.role === \"system\",\n );\n if (parts.length === 0) return undefined;\n const joined = parts\n .map((m) => m.content)\n .join(\"\\n\\n\")\n .trim();\n return joined.length > 0 ? joined : undefined;\n}\n\nfunction userContentToInputParts(\n message: Extract<LanguageModelV3Message, { role: \"user\" }>,\n): ChatInputPart[] {\n const out: ChatInputPart[] = [];\n for (const part of message.content) {\n if (part.type === \"text\" && part.text.length > 0) {\n out.push({ type: \"text\", text: part.text });\n }\n // NOTE: file/image input parts are not yet forwarded to chatd.\n }\n return out;\n}\n\nfunction toolResultOutputToChatd(output: LanguageModelV3ToolResultOutput): {\n value: unknown;\n isError: boolean;\n} {\n switch (output.type) {\n case \"text\":\n return { value: output.value, isError: false };\n case \"json\":\n return { value: output.value, isError: false };\n case \"error-text\":\n return { value: output.value, isError: true };\n case \"error-json\":\n return { value: output.value, isError: true };\n case \"execution-denied\":\n return { value: { execution_denied: true, reason: output.reason }, isError: true };\n case \"content\":\n return { value: output.value, isError: false };\n default:\n return { value: output, isError: false };\n }\n}\n\nexport type TurnAction =\n | { kind: \"new-turn\"; content: ChatInputPart[] }\n | { kind: \"resume\"; toolResults: ToolResult[] }\n | { kind: \"noop\" };\n\n/**\n * Decides what to do with a fresh `doStream`/`doGenerate` prompt:\n * - trailing `tool` message(s) → resume the in-flight chatd turn by submitting\n * those tool results (the AI SDK executed a client tool between steps);\n * - otherwise the trailing `user` message → a new turn.\n */\nexport function classifyTurnAction(prompt: LanguageModelV3Prompt): TurnAction {\n if (prompt.length === 0) return { kind: \"noop\" };\n const last = prompt[prompt.length - 1];\n if (!last) return { kind: \"noop\" };\n\n if (last.role === \"tool\") {\n const toolResults: ToolResult[] = [];\n // Collect from all trailing consecutive tool messages.\n for (let i = prompt.length - 1; i >= 0; i--) {\n const m = prompt[i];\n if (!m || m.role !== \"tool\") break;\n for (const part of m.content) {\n if (part.type !== \"tool-result\") continue;\n const { value, isError } = toolResultOutputToChatd(part.output);\n toolResults.unshift({ tool_call_id: part.toolCallId, output: value, is_error: isError });\n }\n }\n return { kind: \"resume\", toolResults };\n }\n\n if (last.role === \"user\") {\n return { kind: \"new-turn\", content: userContentToInputParts(last) };\n }\n\n return { kind: \"noop\" };\n}\n\n/** Maps AI SDK function tools to chatd client-executed (\"dynamic\") tools. */\nexport function toolsToDynamicTools(tools: LanguageModelV3CallOptions[\"tools\"]): DynamicTool[] {\n if (!tools) return [];\n const out: DynamicTool[] = [];\n for (const tool of tools) {\n if (tool.type !== \"function\") continue; // provider tools are not forwarded\n out.push({\n name: tool.name,\n description: tool.description,\n input_schema: tool.inputSchema,\n });\n }\n return out;\n}\n\n/** The set of tool names the AI SDK side owns (i.e. client-executed). */\nexport function dynamicToolNames(tools: LanguageModelV3CallOptions[\"tools\"]): Set<string> {\n const names = new Set<string>();\n for (const tool of tools ?? []) {\n if (tool.type === \"function\") names.add(tool.name);\n }\n return names;\n}\n","import type {\n LanguageModelV3FinishReason,\n LanguageModelV3StreamPart,\n LanguageModelV3Usage,\n} from \"@ai-sdk/provider\";\nimport { CoderChatError } from \"../errors.js\";\nimport {\n type ChatErrorPayload,\n type ChatMessage,\n type ChatMessagePart,\n type ChatMessageUsage,\n type ChatStatus,\n type ChatStreamEvent,\n TERMINAL_STATUSES,\n} from \"../coder/types.js\";\n\nfunction mapUsage(u: ChatMessageUsage | undefined): LanguageModelV3Usage {\n return {\n inputTokens: {\n total: u?.input_tokens,\n noCache: undefined,\n cacheRead: u?.cache_read_tokens,\n cacheWrite: u?.cache_creation_tokens,\n },\n outputTokens: {\n total: u?.output_tokens,\n text: undefined,\n reasoning: u?.reasoning_tokens,\n },\n };\n}\n\nfunction jsonResult(value: unknown): NonNullable<unknown> {\n // chatd tool results are arbitrary JSON; the V3 tool-result `result` must be\n // a non-null JSON value.\n return (value ?? {}) as NonNullable<unknown>;\n}\n\n/**\n * Translates one chatd turn's {@link ChatStreamEvent} stream into a sequence of\n * `LanguageModelV3StreamPart`s for the AI SDK.\n *\n * Two text/reasoning modes, decided per turn from the wire behavior:\n * - **delta mode** — chatd streamed `message_part` deltas; we emit those and\n * treat the trailing full `message` snapshot as a no-op for text/reasoning.\n * - **snapshot mode** — fast turns where only full `message` snapshots arrive;\n * we diff each snapshot's full text against what we've already emitted.\n * Both paths track an emitted-length cursor, so neither double-counts.\n *\n * Client (custom) tool calls are emitted from the reliable `action_required`\n * event and left for the AI SDK to execute. chatd's own server-side tools are\n * surfaced best-effort as `providerExecuted` tool calls/results.\n */\nexport class TurnTranslator {\n readonly #dynamicToolNames: ReadonlySet<string>;\n\n #seq = 0;\n #text = { id: undefined as string | undefined, len: 0, sawDelta: false };\n #reasoning = { id: undefined as string | undefined, len: 0, sawDelta: false };\n #currentAssistantId: number | undefined;\n\n #serverToolCalls = new Set<string>();\n #serverToolResults = new Set<string>();\n #clientToolCalls = new Set<string>();\n #clientToolCallSeen = false;\n\n #usage: ChatMessageUsage | undefined;\n #error: ChatErrorPayload | undefined;\n #terminalStatus: ChatStatus | undefined;\n #maxMessageId = 0;\n\n constructor(opts: { dynamicToolNames: ReadonlySet<string> }) {\n this.#dynamicToolNames = opts.dynamicToolNames;\n }\n\n get terminalStatus(): ChatStatus | undefined {\n return this.#terminalStatus;\n }\n /** Whether a client (custom) tool call has been emitted this turn. */\n get clientToolCallSeen(): boolean {\n return this.#clientToolCallSeen;\n }\n get maxMessageId(): number {\n return this.#maxMessageId;\n }\n get error(): ChatErrorPayload | undefined {\n return this.#error;\n }\n\n // --- block helpers --------------------------------------------------------\n\n #openText(out: LanguageModelV3StreamPart[]): void {\n if (this.#reasoning.id) this.#closeReasoning(out);\n if (!this.#text.id) {\n this.#text.id = `text-${++this.#seq}`;\n this.#text.len = 0;\n out.push({ type: \"text-start\", id: this.#text.id });\n }\n }\n #closeText(out: LanguageModelV3StreamPart[]): void {\n if (this.#text.id) {\n out.push({ type: \"text-end\", id: this.#text.id });\n this.#text.id = undefined;\n this.#text.len = 0;\n }\n }\n #openReasoning(out: LanguageModelV3StreamPart[]): void {\n if (this.#text.id) this.#closeText(out);\n if (!this.#reasoning.id) {\n this.#reasoning.id = `reasoning-${++this.#seq}`;\n this.#reasoning.len = 0;\n out.push({ type: \"reasoning-start\", id: this.#reasoning.id });\n }\n }\n #closeReasoning(out: LanguageModelV3StreamPart[]): void {\n if (this.#reasoning.id) {\n out.push({ type: \"reasoning-end\", id: this.#reasoning.id });\n this.#reasoning.id = undefined;\n this.#reasoning.len = 0;\n }\n }\n\n #emitTextUpTo(out: LanguageModelV3StreamPart[], full: string): void {\n if (full.length <= this.#text.len && this.#text.id) return;\n this.#openText(out);\n if (full.length > this.#text.len) {\n out.push({\n type: \"text-delta\",\n id: this.#text.id as string,\n delta: full.slice(this.#text.len),\n });\n this.#text.len = full.length;\n }\n }\n #emitReasoningUpTo(out: LanguageModelV3StreamPart[], full: string): void {\n if (full.length <= this.#reasoning.len && this.#reasoning.id) return;\n this.#openReasoning(out);\n if (full.length > this.#reasoning.len) {\n out.push({\n type: \"reasoning-delta\",\n id: this.#reasoning.id as string,\n delta: full.slice(this.#reasoning.len),\n });\n this.#reasoning.len = full.length;\n }\n }\n\n // --- tool helpers ---------------------------------------------------------\n\n #isClientTool(name: string | undefined): boolean {\n return name !== undefined && this.#dynamicToolNames.has(name);\n }\n\n #emitServerToolCall(out: LanguageModelV3StreamPart[], part: ChatMessagePart): void {\n const id = part.tool_call_id;\n const name = part.tool_name;\n if (!id || !name) return;\n if (part.args === undefined) return; // wait for complete args (snapshot)\n if (this.#serverToolCalls.has(id)) return;\n this.#serverToolCalls.add(id);\n out.push({ type: \"tool-input-start\", id, toolName: name, providerExecuted: true });\n out.push({ type: \"tool-input-end\", id });\n out.push({\n type: \"tool-call\",\n toolCallId: id,\n toolName: name,\n input: typeof part.args === \"string\" ? part.args : JSON.stringify(part.args),\n providerExecuted: true,\n });\n }\n\n #emitServerToolResult(out: LanguageModelV3StreamPart[], part: ChatMessagePart): void {\n const id = part.tool_call_id;\n const name = part.tool_name;\n if (!id || !name) return;\n if (part.result === undefined) return;\n if (this.#serverToolResults.has(id)) return;\n this.#serverToolResults.add(id);\n out.push({\n type: \"tool-result\",\n toolCallId: id,\n toolName: name,\n result: jsonResult(part.result),\n isError: part.is_error ?? false,\n });\n }\n\n // --- ingest ---------------------------------------------------------------\n\n ingest(ev: ChatStreamEvent): LanguageModelV3StreamPart[] {\n const out: LanguageModelV3StreamPart[] = [];\n switch (ev.type) {\n case \"message_part\":\n this.#ingestMessagePart(out, ev);\n break;\n case \"message\":\n if (ev.message) this.#ingestMessage(out, ev.message);\n break;\n case \"action_required\":\n for (const tc of ev.action_required?.tool_calls ?? []) {\n if (this.#clientToolCalls.has(tc.tool_call_id)) continue;\n this.#closeText(out);\n this.#closeReasoning(out);\n this.#clientToolCalls.add(tc.tool_call_id);\n this.#clientToolCallSeen = true;\n out.push({ type: \"tool-input-start\", id: tc.tool_call_id, toolName: tc.tool_name });\n out.push({ type: \"tool-input-end\", id: tc.tool_call_id });\n out.push({\n type: \"tool-call\",\n toolCallId: tc.tool_call_id,\n toolName: tc.tool_name,\n input: tc.args,\n });\n }\n break;\n case \"error\":\n if (ev.error) {\n this.#error = ev.error;\n out.push({ type: \"error\", error: new CoderChatError(ev.error) });\n }\n break;\n case \"status\":\n if (ev.status && TERMINAL_STATUSES.has(ev.status.status)) {\n this.#terminalStatus = ev.status.status;\n }\n break;\n default:\n break; // retry / queue_update / preview_reset / history_reset\n }\n return out;\n }\n\n #ingestMessagePart(out: LanguageModelV3StreamPart[], ev: ChatStreamEvent): void {\n const mp = ev.message_part;\n if (!mp || (mp.role !== \"assistant\" && mp.role !== \"tool\")) return;\n const part = mp.part;\n switch (part.type) {\n case \"text\":\n this.#text.sawDelta = true;\n this.#openText(out);\n if (part.text) {\n out.push({ type: \"text-delta\", id: this.#text.id as string, delta: part.text });\n this.#text.len += part.text.length;\n }\n break;\n case \"reasoning\":\n this.#reasoning.sawDelta = true;\n this.#openReasoning(out);\n if (part.text) {\n out.push({ type: \"reasoning-delta\", id: this.#reasoning.id as string, delta: part.text });\n this.#reasoning.len += part.text.length;\n }\n break;\n case \"tool-call\":\n this.#closeText(out);\n this.#closeReasoning(out);\n if (!this.#isClientTool(part.tool_name)) this.#emitServerToolCall(out, part);\n break;\n case \"tool-result\":\n if (!this.#isClientTool(part.tool_name)) this.#emitServerToolResult(out, part);\n break;\n default:\n break;\n }\n }\n\n #ingestMessage(out: LanguageModelV3StreamPart[], message: ChatMessage): void {\n if (message.id > this.#maxMessageId) this.#maxMessageId = message.id;\n if (message.usage && (message.role === \"assistant\" || message.role === \"tool\")) {\n this.#usage = message.usage;\n }\n const content = message.content ?? [];\n\n if (message.role === \"assistant\") {\n // New assistant message boundary: close prior blocks and reset cursors.\n if (this.#currentAssistantId !== undefined && this.#currentAssistantId !== message.id) {\n this.#closeText(out);\n this.#closeReasoning(out);\n this.#text.sawDelta = false;\n this.#reasoning.sawDelta = false;\n }\n this.#currentAssistantId = message.id;\n\n if (!this.#text.sawDelta) {\n const full = content\n .filter((p) => p.type === \"text\")\n .map((p) => p.text ?? \"\")\n .join(\"\");\n if (full.length > 0) this.#emitTextUpTo(out, full);\n }\n if (!this.#reasoning.sawDelta) {\n const full = content\n .filter((p) => p.type === \"reasoning\")\n .map((p) => p.text ?? \"\")\n .join(\"\");\n if (full.length > 0) this.#emitReasoningUpTo(out, full);\n }\n for (const part of content) {\n if (part.type === \"tool-call\" && !this.#isClientTool(part.tool_name))\n this.#emitServerToolCall(out, part);\n else if (part.type === \"tool-result\" && !this.#isClientTool(part.tool_name))\n this.#emitServerToolResult(out, part);\n }\n } else if (message.role === \"tool\") {\n for (const part of content) {\n if (part.type === \"tool-result\" && !this.#isClientTool(part.tool_name))\n this.#emitServerToolResult(out, part);\n }\n }\n }\n\n // --- finish ---------------------------------------------------------------\n\n finish(): LanguageModelV3StreamPart[] {\n const out: LanguageModelV3StreamPart[] = [];\n this.#closeText(out);\n this.#closeReasoning(out);\n\n let unified: LanguageModelV3FinishReason[\"unified\"];\n if (this.#error || this.#terminalStatus === \"error\") unified = \"error\";\n else if (this.#clientToolCallSeen || this.#terminalStatus === \"requires_action\")\n unified = \"tool-calls\";\n else unified = \"stop\";\n\n out.push({\n type: \"finish\",\n usage: mapUsage(this.#usage),\n finishReason: { unified, raw: this.#terminalStatus },\n });\n return out;\n }\n}\n","import type {\n LanguageModelV3,\n LanguageModelV3CallOptions,\n LanguageModelV3Content,\n LanguageModelV3GenerateResult,\n LanguageModelV3StreamPart,\n LanguageModelV3StreamResult,\n LanguageModelV3Usage,\n} from \"@ai-sdk/provider\";\nimport { CoderAgentError, CoderChatError } from \"../errors.js\";\nimport { CoderChatClient } from \"../coder/client.js\";\nimport type { CreateChatRequest } from \"../coder/types.js\";\nimport {\n classifyTurnAction,\n dynamicToolNames,\n extractSystemPrompt,\n toolsToDynamicTools,\n} from \"./prompt.js\";\nimport { TurnTranslator } from \"./translate.js\";\n\nconst EMPTY_USAGE: LanguageModelV3Usage = {\n inputTokens: {\n total: undefined,\n noCache: undefined,\n cacheRead: undefined,\n cacheWrite: undefined,\n },\n outputTokens: { total: undefined, text: undefined, reasoning: undefined },\n};\n\nexport interface CoderLanguageModelConfig {\n client: CoderChatClient;\n organizationId: string;\n /** Model hint (UUID, `provider:model`, model id, or display-name substring). */\n model?: string;\n /** Bind the chat to a Coder workspace (enables workspace tools). */\n workspaceId?: string;\n /** chatd-side MCP servers to enable. */\n mcpServerIds?: string[];\n planMode?: \"\" | \"plan\";\n /** Resume an existing chat instead of creating a new one. */\n chatId?: string;\n}\n\n/**\n * A {@link LanguageModelV3} that is backed by a remote Coder `chatd` agent\n * runtime instead of a raw LLM. One model instance owns one chatd chat\n * (a \"session\"): the chat is created lazily on the first turn and reused for\n * subsequent turns and for client-tool resume steps.\n *\n * The chatd server runs the agent loop (model calls, server-side tools,\n * compaction) itself. This model therefore represents *one chatd segment* per\n * `doStream` call — it advances the chat until it settles (`waiting`/\n * `completed`) or pauses for a client tool (`requires_action`). When the AI SDK\n * executes a client tool and calls `doStream` again with the tool result, this\n * model resumes the same chat. The two loops mesh at the client-tool boundary.\n *\n * NOTE: a single model instance is single-flight — do not run concurrent\n * generations against the same instance/session.\n */\nexport class CoderLanguageModel implements LanguageModelV3 {\n readonly specificationVersion = \"v3\" as const;\n readonly provider = \"coder.chatd\";\n readonly modelId: string;\n readonly supportedUrls: Record<string, RegExp[]> = {};\n\n readonly #config: CoderLanguageModelConfig;\n #chatId: string | undefined;\n #lastSeenMessageId = 0;\n #resolvedModelConfigId: string | undefined;\n #modelResolved = false;\n readonly #submittedToolCallIds = new Set<string>();\n #inFlight = false;\n\n constructor(config: CoderLanguageModelConfig) {\n this.#config = config;\n this.modelId = config.model ?? \"chatd\";\n this.#chatId = config.chatId;\n }\n\n get chatId(): string | undefined {\n return this.#chatId;\n }\n\n /** Drops the current session so the next turn creates a fresh chat. */\n resetSession(): void {\n this.#chatId = undefined;\n this.#lastSeenMessageId = 0;\n this.#submittedToolCallIds.clear();\n }\n\n async #resolveModelConfigId(signal?: AbortSignal): Promise<string | undefined> {\n if (this.#modelResolved) return this.#resolvedModelConfigId;\n if (this.#config.model) {\n this.#resolvedModelConfigId = await this.#config.client.resolveModelConfigId(\n this.#config.model,\n signal,\n );\n }\n this.#modelResolved = true;\n return this.#resolvedModelConfigId;\n }\n\n async *#runTurn(\n options: LanguageModelV3CallOptions,\n ): AsyncGenerator<LanguageModelV3StreamPart, void, void> {\n // A single model instance owns one chatd session's mutable state, so it is\n // single-flight: reject overlapping turns rather than silently corrupting\n // chatId / lastSeenMessageId / submitted tool-call tracking.\n if (this.#inFlight) {\n throw new CoderAgentError(\n \"A generation is already in flight on this CoderAgent (single-flight). Use a separate CoderAgent instance for concurrent sessions.\",\n );\n }\n this.#inFlight = true;\n try {\n const { prompt, abortSignal: signal } = options;\n yield { type: \"stream-start\", warnings: [] };\n\n const action = classifyTurnAction(prompt);\n if (action.kind === \"noop\") {\n throw new CoderAgentError(\n \"CoderAgent received a prompt with no user message or tool results to act on.\",\n );\n }\n\n const translator = new TurnTranslator({ dynamicToolNames: dynamicToolNames(options.tools) });\n let afterId: number | undefined;\n\n if (action.kind === \"new-turn\") {\n const modelConfigId = await this.#resolveModelConfigId(signal);\n if (!this.#chatId) {\n const req: CreateChatRequest = {\n organization_id: this.#config.organizationId,\n content: action.content,\n client_type: \"api\",\n };\n const system = extractSystemPrompt(prompt);\n if (system) req.system_prompt = system;\n const tools = toolsToDynamicTools(options.tools);\n if (tools.length > 0) req.unsafe_dynamic_tools = tools;\n if (modelConfigId) req.model_config_id = modelConfigId;\n if (this.#config.workspaceId) req.workspace_id = this.#config.workspaceId;\n if (this.#config.mcpServerIds?.length) req.mcp_server_ids = this.#config.mcpServerIds;\n if (this.#config.planMode) req.plan_mode = this.#config.planMode;\n const chat = await this.#config.client.createChat(req, signal);\n this.#chatId = chat.id;\n afterId = this.#lastSeenMessageId > 0 ? this.#lastSeenMessageId : undefined;\n } else {\n const resp = await this.#config.client.createChatMessage(\n this.#chatId,\n {\n content: action.content,\n ...(modelConfigId ? { model_config_id: modelConfigId } : {}),\n },\n signal,\n );\n afterId = resp.message?.id ?? this.#lastSeenMessageId;\n }\n } else {\n // resume\n if (!this.#chatId)\n throw new CoderChatError({ message: \"cannot submit tool results before a chat exists\" });\n const fresh = action.toolResults.filter(\n (r) => !this.#submittedToolCallIds.has(r.tool_call_id),\n );\n if (fresh.length > 0) {\n await this.#config.client.submitToolResults(this.#chatId, { results: fresh }, signal);\n for (const r of fresh) this.#submittedToolCallIds.add(r.tool_call_id);\n }\n afterId = this.#lastSeenMessageId;\n }\n\n const chatId = this.#chatId as string;\n // chatd emits the `requires_action` status BEFORE the `action_required`\n // event that carries the pending tool calls, so for that status we keep\n // reading until the client tool calls have actually been emitted (bounded\n // by a safety counter, since the stream is a live subscription).\n let sinceRequiresAction = 0;\n for await (const ev of this.#config.client.streamEvents(chatId, { afterId, signal })) {\n for (const part of translator.ingest(ev)) yield part;\n const status = translator.terminalStatus;\n if (status) {\n if (status !== \"requires_action\") break;\n if (translator.clientToolCallSeen) break;\n if (++sinceRequiresAction > 200) break;\n }\n }\n\n if (signal?.aborted && !translator.terminalStatus) {\n throw signal.reason ?? new DOMException(\"The operation was aborted.\", \"AbortError\");\n }\n\n for (const part of translator.finish()) yield part;\n if (translator.maxMessageId > this.#lastSeenMessageId)\n this.#lastSeenMessageId = translator.maxMessageId;\n } finally {\n this.#inFlight = false;\n }\n }\n\n async doStream(options: LanguageModelV3CallOptions): Promise<LanguageModelV3StreamResult> {\n const gen = this.#runTurn(options);\n const stream = new ReadableStream<LanguageModelV3StreamPart>({\n async pull(controller) {\n try {\n const { value, done } = await gen.next();\n if (done) controller.close();\n else controller.enqueue(value);\n } catch (err) {\n controller.error(err);\n }\n },\n async cancel() {\n await gen.return();\n },\n });\n return { stream };\n }\n\n async doGenerate(options: LanguageModelV3CallOptions): Promise<LanguageModelV3GenerateResult> {\n const content: LanguageModelV3Content[] = [];\n const textBuf = new Map<string, string>();\n const reasoningBuf = new Map<string, string>();\n let usage: LanguageModelV3Usage = EMPTY_USAGE;\n let finishReason: LanguageModelV3GenerateResult[\"finishReason\"] = {\n unified: \"stop\",\n raw: undefined,\n };\n const warnings: LanguageModelV3GenerateResult[\"warnings\"] = [];\n\n for await (const part of this.#runTurn(options)) {\n switch (part.type) {\n case \"stream-start\":\n warnings.push(...part.warnings);\n break;\n case \"text-start\":\n textBuf.set(part.id, \"\");\n break;\n case \"text-delta\":\n textBuf.set(part.id, (textBuf.get(part.id) ?? \"\") + part.delta);\n break;\n case \"text-end\": {\n const t = textBuf.get(part.id) ?? \"\";\n if (t.length > 0) content.push({ type: \"text\", text: t });\n textBuf.delete(part.id);\n break;\n }\n case \"reasoning-start\":\n reasoningBuf.set(part.id, \"\");\n break;\n case \"reasoning-delta\":\n reasoningBuf.set(part.id, (reasoningBuf.get(part.id) ?? \"\") + part.delta);\n break;\n case \"reasoning-end\": {\n const t = reasoningBuf.get(part.id) ?? \"\";\n if (t.length > 0) content.push({ type: \"reasoning\", text: t });\n reasoningBuf.delete(part.id);\n break;\n }\n case \"tool-call\":\n case \"tool-result\":\n case \"source\":\n case \"file\":\n content.push(part);\n break;\n case \"finish\":\n usage = part.usage;\n finishReason = part.finishReason;\n break;\n case \"error\":\n throw part.error instanceof Error\n ? part.error\n : new CoderChatError({ message: String(part.error) });\n default:\n break;\n }\n }\n\n return { content, finishReason, usage, warnings };\n }\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/agent/coder-agent.ts","../src/errors.ts","../src/files.ts","../src/coder/types.ts","../src/coder/ws.ts","../src/coder/client.ts","../src/model/prompt.ts","../src/model/translate.ts","../src/model/language-model.ts"],"sourcesContent":["import {\n type Agent,\n type FilePart,\n type StopCondition,\n stepCountIs,\n type SystemModelMessage,\n type ToolChoice,\n ToolLoopAgent,\n type ToolSet,\n} from \"ai\";\nimport {\n type ChatFileInput,\n CoderChatClient,\n type CoderChatClientOptions,\n type UploadedChatFile,\n} from \"../coder/client.js\";\nimport type { ChatModelConfig } from \"../coder/types.js\";\nimport { CoderAgentError } from \"../errors.js\";\nimport type { FileContent } from \"../files.js\";\nimport { CoderLanguageModel } from \"../model/language-model.js\";\nimport { CODER_PROVIDER_OPTIONS } from \"../model/prompt.js\";\nimport type { WorkspaceFileStore, WorkspacePlacement } from \"../workspace-files.js\";\n\ntype InnerAgent<TOOLS extends ToolSet> = ToolLoopAgent<never, TOOLS, never>;\n\n/** A handle to a file uploaded as a chat attachment (see {@link CoderAgent.attach}). */\nexport interface ChatAttachment extends UploadedChatFile {\n /**\n * A native AI SDK `file` part that references this upload by id. Drop it into\n * a user message's `content` to reuse the file across turns without\n * re-uploading — the agent recognizes the id and skips the upload.\n *\n * The reference travels in `providerOptions.coder.fileId`; if you persist the\n * part through a store that strips `providerOptions`, the reference is lost\n * (re-`attach()` instead of persisting the handle).\n */\n toFilePart(): FilePart;\n}\n\nfunction makeChatAttachment(file: UploadedChatFile): ChatAttachment {\n return {\n ...file,\n toFilePart: () => ({\n type: \"file\",\n // Bytes are unused: the reference travels in providerOptions.coder.fileId.\n data: \"\",\n mediaType: file.mediaType,\n ...(file.name ? { filename: file.name } : {}),\n providerOptions: { [CODER_PROVIDER_OPTIONS]: { fileId: file.id } },\n }),\n };\n}\n\n/** Default step ceiling. Each \"step\" is one client-tool round-trip; chatd caps\n * its own server-side loop at 1200 steps independently. */\nconst DEFAULT_STOP = stepCountIs(64);\n\nexport interface CoderAgentSettings<TOOLS extends ToolSet = {}> {\n // --- connection (provide a client, or baseUrl + token) ---\n /** A pre-built {@link CoderChatClient}. Mutually exclusive with baseUrl/token. */\n client?: CoderChatClient;\n /** Coder deployment base URL, e.g. `https://dev.coder.com`. */\n baseUrl?: string;\n /** Coder API/session token (sent as `Coder-Session-Token`). */\n token?: string;\n fetch?: CoderChatClientOptions[\"fetch\"];\n webSocketFactory?: CoderChatClientOptions[\"webSocketFactory\"];\n\n // --- Coder chat configuration ---\n /** Organization UUID that owns the chat (required). */\n organizationId: string;\n /** Model hint: UUID, `provider:model`, model id, or display-name substring. */\n model?: string;\n /** Bind the chat to a Coder workspace (enables workspace-scoped tools). */\n workspaceId?: string;\n /**\n * Adapter for writing files onto a workspace filesystem, enabling\n * {@link CoderAgent.uploadToWorkspace}. Supply one backed by a workspace\n * connection (e.g. a `@coder/ai-sdk-eve-sandbox` session).\n */\n workspaceFiles?: WorkspaceFileStore;\n /** chatd-side MCP servers to enable for this chat. */\n mcpServerIds?: string[];\n /** chatd plan mode. */\n planMode?: \"\" | \"plan\";\n /** Resume an existing chat (session) instead of creating a new one. */\n chatId?: string;\n\n // --- agent configuration ---\n /** Stable agent id (exposed as {@link CoderAgent.id}). */\n id?: string;\n /** System instructions → chatd `system_prompt`. */\n instructions?: string | SystemModelMessage | Array<SystemModelMessage>;\n /** Custom (client-executed) tools. Each should have an `execute` for scripting. */\n tools?: TOOLS;\n toolChoice?: ToolChoice<NoInfer<TOOLS>>;\n /** Stop condition(s) for the AI SDK loop. Default `stepCountIs(64)`. */\n stopWhen?: StopCondition<NoInfer<TOOLS>> | Array<StopCondition<NoInfer<TOOLS>>>;\n /**\n * SDK-level retries. Default `0`: this agent owns server-side chat state, so\n * SDK retries could duplicate a turn. Override with care.\n */\n maxRetries?: number;\n /**\n * Per-segment time budget in milliseconds, applied to each model round-trip\n * (chat creation / message / tool-result submission plus the server run until\n * it settles). If a segment runs longer (e.g. the server is wedged or a\n * workspace can't be scheduled), the run is interrupted server-side and the\n * call rejects with a retryable {@link CoderChatError} (`kind: \"timeout\"`)\n * instead of hanging. A multi-step `generate()` driving client tools makes\n * several segments, so this bounds each one — to cap total wall-clock for the\n * whole call, pass `abortSignal: AbortSignal.timeout(ms)`. Unset or\n * non-positive means no limit.\n */\n requestTimeoutMs?: number;\n}\n\n/**\n * An AI SDK-compliant agent backed by a remote Coder `chatd` agent runtime.\n *\n * `new CoderAgent({ ... })` returns an object that implements the AI SDK\n * `Agent` interface (`generate()`/`stream()`), so it composes with the rest of\n * the AI SDK ecosystem. Internally it wraps a {@link ToolLoopAgent} whose model\n * is a {@link CoderLanguageModel}; chatd runs the actual agent loop server-side.\n *\n * One `CoderAgent` instance corresponds to one chatd chat (\"session\"): the chat\n * is created on the first `generate()`/`stream()` and reused for subsequent\n * turns. Use {@link CoderAgent.resetSession} to start a fresh chat.\n */\nexport class CoderAgent<TOOLS extends ToolSet = {}> implements Agent<never, TOOLS, never> {\n readonly version = \"agent-v1\" as const;\n\n readonly #client: CoderChatClient;\n readonly #model: CoderLanguageModel;\n readonly #inner: InnerAgent<TOOLS>;\n readonly #organizationId: string;\n readonly #workspaceFiles: WorkspaceFileStore | undefined;\n\n constructor(settings: CoderAgentSettings<TOOLS>) {\n if (settings.client) {\n this.#client = settings.client;\n } else if (settings.baseUrl && settings.token) {\n this.#client = new CoderChatClient({\n baseUrl: settings.baseUrl,\n token: settings.token,\n fetch: settings.fetch,\n webSocketFactory: settings.webSocketFactory,\n });\n } else {\n throw new CoderAgentError(\n \"CoderAgent requires either `client` or both `baseUrl` and `token`.\",\n );\n }\n\n this.#organizationId = settings.organizationId;\n this.#workspaceFiles = settings.workspaceFiles;\n\n // A file written to one workspace isn't visible to a chat bound to another.\n if (\n settings.workspaceFiles &&\n settings.workspaceId &&\n settings.workspaceFiles.workspaceId !== settings.workspaceId\n ) {\n throw new CoderAgentError(\n `workspaceFiles.workspaceId (${settings.workspaceFiles.workspaceId}) does not match the ` +\n `agent's workspaceId (${settings.workspaceId}); the chat's tools would not see uploaded files.`,\n );\n }\n\n this.#model = new CoderLanguageModel({\n client: this.#client,\n organizationId: settings.organizationId,\n model: settings.model,\n workspaceId: settings.workspaceId,\n mcpServerIds: settings.mcpServerIds,\n planMode: settings.planMode,\n chatId: settings.chatId,\n requestTimeoutMs: settings.requestTimeoutMs,\n });\n\n this.#inner = new ToolLoopAgent<never, TOOLS, never>({\n model: this.#model,\n id: settings.id,\n instructions: settings.instructions,\n tools: settings.tools,\n toolChoice: settings.toolChoice,\n stopWhen: settings.stopWhen ?? DEFAULT_STOP,\n maxRetries: settings.maxRetries ?? 0,\n });\n }\n\n get id(): string | undefined {\n return this.#inner.id;\n }\n\n get tools(): TOOLS {\n return this.#inner.tools;\n }\n\n /** The underlying chatd client. */\n get client(): CoderChatClient {\n return this.#client;\n }\n\n /** The current chatd chat id, once a turn has started. */\n get chatId(): string | undefined {\n return this.#model.chatId;\n }\n\n generate(\n options: Parameters<InnerAgent<TOOLS>[\"generate\"]>[0],\n ): ReturnType<InnerAgent<TOOLS>[\"generate\"]> {\n return this.#inner.generate(options);\n }\n\n stream(\n options: Parameters<InnerAgent<TOOLS>[\"stream\"]>[0],\n ): ReturnType<InnerAgent<TOOLS>[\"stream\"]> {\n return this.#inner.stream(options);\n }\n\n // --- session helpers ------------------------------------------------------\n\n /**\n * List the model configs available on the deployment. Use this to discover\n * valid values for the `model` hint instead of guessing ids — match on\n * `id`, `provider`/`model`, or `display_name`.\n */\n listModels(signal?: AbortSignal): Promise<ChatModelConfig[]> {\n return this.#client.listModelConfigs(signal);\n }\n\n /** Start a fresh chatd chat on the next turn. */\n resetSession(): void {\n this.#model.resetSession();\n }\n\n /** Interrupt the in-flight generation, if any. */\n async interrupt(): Promise<void> {\n const id = this.#model.chatId;\n if (id) await this.#client.interruptChat(id);\n }\n\n /** Archive the underlying chat (safe cleanup; hides it from listings). */\n async archive(): Promise<void> {\n const id = this.#model.chatId;\n if (id) await this.#client.archiveChat(id);\n }\n\n /**\n * Clean up the chat when the agent leaves an `await using` scope, so cleanup\n * rides scope exit instead of a separate call you have to remember in a\n * `finally`. Interrupts any in-flight server run, then archives the chat.\n * Best-effort: disposal errors are swallowed so they can't mask the scope's\n * own error.\n *\n * @example\n * ```ts\n * await using agent = new CoderAgent({ ... });\n * const { text } = await agent.generate({ prompt: \"…\" });\n * // agent.interrupt() + agent.archive() run automatically here.\n * ```\n */\n async [Symbol.asyncDispose](): Promise<void> {\n // archive() only soft-hides the chat; it does not stop a generation. If the\n // scope exits mid-turn (e.g. generate() threw, or an early return), interrupt\n // first so chatd stops generating and releases the workspace, then archive.\n try {\n await this.interrupt();\n } catch {\n /* best-effort cleanup */\n }\n try {\n await this.archive();\n } catch {\n /* best-effort cleanup */\n }\n }\n\n // --- files ----------------------------------------------------------------\n\n /**\n * Upload a file as a chat attachment — content for the model to *read* (a PDF,\n * image, CSV, …). Returns a handle you can reference from a later turn via\n * {@link ChatAttachment.toFilePart} (no re-upload). Validated against the chat\n * allowlist and 10 MiB cap up front.\n *\n * You usually don't need this: a native AI SDK `file` part dropped into a\n * message's `content` is uploaded transparently. Reach for `attach()` to\n * pre-upload, to reuse one file across turns, or to validate before sending.\n *\n * For large or non-allowlisted files (zips, datasets, binaries) — material for\n * the agent to *operate on* — use {@link CoderAgent.uploadToWorkspace}.\n */\n async attach(file: ChatFileInput, signal?: AbortSignal): Promise<ChatAttachment> {\n const uploaded = await this.#client.uploadChatFile(this.#organizationId, file, signal);\n return makeChatAttachment(uploaded);\n }\n\n /**\n * Write a file onto the bound workspace's filesystem for the agent to operate\n * on (extract, build, read with its tools). Requires a {@link WorkspaceFileStore}\n * via the `workspaceFiles` setting. The file is written as-is — no unpacking;\n * instruct the agent to `unzip`/`tar -x`, or extract over your own connection.\n *\n * The chat should be bound to the same workspace (`workspaceId`) so the agent's\n * server-side tools can see the file.\n */\n async uploadToWorkspace(file: {\n content: FileContent;\n /** Destination path inside the workspace (the adapter may resolve relatives). */\n path: string;\n signal?: AbortSignal;\n }): Promise<WorkspacePlacement> {\n if (!this.#workspaceFiles) {\n throw new CoderAgentError(\n \"uploadToWorkspace requires a `workspaceFiles` adapter. Construct the agent with \" +\n \"`workspaceFiles` (e.g. backed by a @coder/ai-sdk-eve-sandbox session) to enable it.\",\n );\n }\n const { path } = await this.#workspaceFiles.write({\n content: file.content,\n path: file.path,\n signal: file.signal,\n });\n return { workspaceId: this.#workspaceFiles.workspaceId, path };\n }\n}\n","import type { ChatErrorPayload } from \"./coder/types.js\";\n\n/** Base error for all `@coder/ai-sdk-agent` failures. */\nexport class CoderAgentError extends Error {\n override name = \"CoderAgentError\";\n constructor(message: string, options?: { cause?: unknown }) {\n super(message, options);\n }\n}\n\n/** An HTTP request to the Coder API failed. */\nexport class CoderApiError extends CoderAgentError {\n override name = \"CoderApiError\";\n readonly status: number;\n readonly detail: string | undefined;\n readonly method: string;\n readonly path: string;\n constructor(args: {\n status: number;\n method: string;\n path: string;\n message: string;\n detail?: string;\n }) {\n super(\n `Coder API ${args.method} ${args.path} failed (${args.status}): ${args.message}` +\n (args.detail ? ` — ${args.detail}` : \"\"),\n );\n this.status = args.status;\n this.detail = args.detail;\n this.method = args.method;\n this.path = args.path;\n }\n}\n\n/** A chat generation ended in an error status. */\nexport class CoderChatError extends CoderAgentError {\n override name = \"CoderChatError\";\n readonly kind: string | undefined;\n readonly provider: string | undefined;\n readonly retryable: boolean;\n readonly statusCode: number | undefined;\n constructor(payload: ChatErrorPayload) {\n super(payload.detail ? `${payload.message}: ${payload.detail}` : payload.message);\n this.kind = payload.kind;\n this.provider = payload.provider;\n this.retryable = payload.retryable ?? false;\n this.statusCode = payload.status_code;\n }\n}\n","import type { LanguageModelV3DataContent } from \"@ai-sdk/provider\";\nimport { CoderAgentError } from \"./errors.js\";\n\n/**\n * Bytes to upload, in any convenient shape.\n *\n * `Blob`/`File` is the recommended form: it is lazy (not forced fully into\n * memory), carries its own size (so the 10 MiB chat cap can fail fast and a\n * `Content-Length` can be sent), is re-readable (so a failed upload can be\n * retried), and works both in Node (`fs.openAsBlob(\"./x.pdf\")`) and the browser\n * (an `<input type=file>` yields a `File`). A `ReadableStream` is accepted for\n * genuinely unbounded sources, but its size is unknown up front — the chat size\n * cap can then only be enforced server-side.\n */\nexport type FileContent = Blob | ReadableStream<Uint8Array> | Uint8Array | ArrayBuffer;\n\n/** A {@link FileContent} normalized for upload: a fetch-ready body plus derived metadata. */\nexport interface ResolvedFile {\n /**\n * Body to hand to `fetch`. Raw bytes are wrapped in a `Blob` so the body is\n * always a clean `BodyInit` (and bytes get a `Content-Length` for free).\n */\n body: Blob | ReadableStream<Uint8Array>;\n /** Resolved IANA media type. */\n mediaType: string;\n /** Original filename, if known. */\n name: string | undefined;\n /** Byte length, if known up front (undefined for streams). */\n size: number | undefined;\n}\n\nfunction isBlob(v: unknown): v is Blob {\n return typeof Blob !== \"undefined\" && v instanceof Blob;\n}\nfunction isReadableStream(v: unknown): v is ReadableStream<Uint8Array> {\n return typeof ReadableStream !== \"undefined\" && v instanceof ReadableStream;\n}\n\n/**\n * Normalize {@link FileContent} into a fetch-ready body and derive its media\n * type, name, and (when known) size. `Blob`/`File` supply their own\n * `type`/`name`/`size`; for raw bytes or a stream, `mediaType` must be provided\n * by the caller. Explicit `opts.mediaType`/`opts.name` always win.\n */\nexport function resolveFileContent(\n content: FileContent,\n opts?: { mediaType?: string; name?: string },\n): ResolvedFile {\n let mediaType = opts?.mediaType;\n let name = opts?.name;\n let body: ResolvedFile[\"body\"];\n let size: number | undefined;\n\n if (isBlob(content)) {\n body = content;\n size = content.size;\n if (!mediaType && content.type) mediaType = content.type;\n // `File` extends `Blob` with a `name`; read it structurally so we don't\n // depend on the `File` global type existing.\n const maybeName = (content as { name?: unknown }).name;\n if (!name && typeof maybeName === \"string\") name = maybeName;\n } else if (isReadableStream(content)) {\n body = content;\n size = undefined;\n } else if (content instanceof Uint8Array || content instanceof ArrayBuffer) {\n size = content.byteLength;\n body = new Blob([content as BlobPart]);\n } else {\n throw new CoderAgentError(\n \"Unsupported file content: expected a Blob/File, ReadableStream, Uint8Array, or ArrayBuffer.\",\n );\n }\n\n if (!mediaType) {\n throw new CoderAgentError(\n \"Could not determine the file's media type. Pass `mediaType`, or provide a Blob/File that carries its own `type`.\",\n );\n }\n\n return { body, mediaType, name, size };\n}\n\n/** Decode a base64 string to bytes (Node `Buffer` or browser `atob`). */\nfunction base64ToBytes(b64: string): Uint8Array {\n // `Buffer` is already a `Uint8Array`; return it directly (no extra copy).\n if (typeof Buffer !== \"undefined\") return Buffer.from(b64, \"base64\");\n const bin = atob(b64);\n const bytes = new Uint8Array(bin.length);\n for (let i = 0; i < bin.length; i++) bytes[i] = bin.charCodeAt(i);\n return bytes;\n}\n\n/**\n * Convert an AI SDK file-part `data` value into {@link FileContent} for upload.\n * The provider receives bytes or a base64 string (and, rarely, a URL). URLs are\n * not expected: this model declares no `supportedUrls`, so the SDK downloads\n * them to bytes before calling us — a URL here is therefore an error.\n */\nexport function dataContentToFileContent(data: LanguageModelV3DataContent): FileContent {\n if (data instanceof Uint8Array) return data;\n if (typeof data === \"string\") return base64ToBytes(data);\n throw new CoderAgentError(\n \"File parts referencing a URL are not supported; provide the file bytes instead.\",\n );\n}\n","/**\n * Wire types for Coder's experimental `chatd` chat API\n * (`/api/experimental/chats`). These mirror the Go types in\n * `coder/coder`'s `codersdk/chats.go` (JSON shapes), restricted to the subset\n * this client uses. Field names use snake_case to match the wire format.\n *\n * NOTE: The chatd API is experimental and may change between Coder releases.\n */\n\n// ---------------------------------------------------------------------------\n// Input (client -> server)\n// ---------------------------------------------------------------------------\n\nexport type ChatInputPartType = \"text\" | \"file\" | \"file-reference\";\n\nexport interface ChatInputPart {\n type: ChatInputPartType;\n text?: string;\n file_id?: string;\n file_name?: string;\n start_line?: number;\n end_line?: number;\n content?: string;\n}\n\n/**\n * Media types accepted by the chat-file upload endpoint\n * (`POST /api/experimental/chats/files`). The server allowlist is intentionally\n * narrow — anything else (zip, tarball, binaries, …) is not a chat attachment\n * and belongs on the workspace filesystem instead. Mirrors\n * `codersdk.AllChatAttachmentMediaTypes`.\n */\nexport type ChatAttachmentMediaType =\n | \"application/json\"\n | \"application/pdf\"\n | \"image/gif\"\n | \"image/jpeg\"\n | \"image/png\"\n | \"image/webp\"\n | \"text/csv\"\n | \"text/markdown\"\n | \"text/plain\";\n\n/** The chat-attachment media-type allowlist, as a runtime-checkable set. */\nexport const CHAT_ATTACHMENT_MEDIA_TYPES: ReadonlySet<string> = new Set<ChatAttachmentMediaType>([\n \"application/json\",\n \"application/pdf\",\n \"image/gif\",\n \"image/jpeg\",\n \"image/png\",\n \"image/webp\",\n \"text/csv\",\n \"text/markdown\",\n \"text/plain\",\n]);\n\n/** Per-file size cap enforced by the chat-file upload endpoint (10 MiB). */\nexport const MAX_CHAT_FILE_SIZE_BYTES = 10 * 1024 * 1024;\n\nexport type ChatClientType = \"ui\" | \"api\";\nexport type ChatPlanMode = \"\" | \"plan\";\nexport type ChatBusyBehavior = \"queue\" | \"interrupt\";\n\n/**\n * A client-executed (\"dynamic\") tool definition. chatd never executes these;\n * when the model calls one, the chat enters `requires_action` and the client\n * must execute it and submit results via {@link SubmitToolResultsRequest}.\n *\n * NOTE: the JSON key is `input_schema` (snake_case), per chatd.\n */\nexport interface DynamicTool {\n name: string;\n description?: string;\n /** A JSON Schema object describing the tool input. */\n input_schema: unknown;\n}\n\nexport interface CreateChatRequest {\n organization_id: string;\n content: ChatInputPart[];\n system_prompt?: string;\n workspace_id?: string;\n model_config_id?: string;\n mcp_server_ids?: string[];\n labels?: Record<string, string>;\n unsafe_dynamic_tools?: DynamicTool[];\n plan_mode?: ChatPlanMode;\n client_type?: ChatClientType;\n}\n\nexport interface CreateChatMessageRequest {\n content: ChatInputPart[];\n model_config_id?: string;\n mcp_server_ids?: string[];\n busy_behavior?: ChatBusyBehavior;\n plan_mode?: ChatPlanMode;\n}\n\n/** Result of a single client-executed tool call. */\nexport interface ToolResult {\n tool_call_id: string;\n /** JSON-serializable tool output. */\n output: unknown;\n is_error?: boolean;\n}\n\nexport interface SubmitToolResultsRequest {\n results: ToolResult[];\n}\n\nexport interface UpdateChatRequest {\n title?: string;\n archived?: boolean;\n}\n\n// ---------------------------------------------------------------------------\n// Output (server -> client)\n// ---------------------------------------------------------------------------\n\nexport type ChatStatus =\n | \"waiting\"\n | \"pending\"\n | \"running\"\n | \"paused\"\n | \"completed\"\n | \"error\"\n | \"requires_action\"\n | \"interrupting\";\n\nexport type ChatMessageRole = \"system\" | \"user\" | \"assistant\" | \"tool\";\n\nexport type ChatMessagePartType =\n | \"text\"\n | \"reasoning\"\n | \"tool-call\"\n | \"tool-result\"\n | \"source\"\n | \"file\"\n | \"file-reference\"\n | \"context-file\"\n | \"skill\";\n\n/**\n * A part of a chat message. chatd models this as a single flat struct with a\n * `type` discriminator and many optional fields (see `codersdk.ChatMessagePart`),\n * so we mirror that shape rather than a strict discriminated union.\n */\nexport interface ChatMessagePart {\n type: ChatMessagePartType;\n\n // text / reasoning\n text?: string;\n signature?: string;\n\n // tool-call / tool-result\n tool_call_id?: string;\n tool_name?: string;\n mcp_server_config_id?: string | null;\n /** tool-call: complete arguments (JSON value). */\n args?: unknown;\n /** tool-call: incremental argument text chunk during streaming. */\n args_delta?: string;\n parsed_commands?: string[][];\n /** tool-result: complete result (JSON value). */\n result?: unknown;\n /** tool-result: incremental result text chunk during streaming. */\n result_delta?: string;\n result_reset?: boolean;\n is_error?: boolean;\n is_media?: boolean;\n provider_executed?: boolean;\n created_at?: string;\n completed_at?: string;\n\n // source\n source_id?: string;\n url?: string;\n title?: string;\n\n // file\n media_type?: string;\n name?: string;\n file_id?: string | null;\n\n // file-reference\n file_name?: string;\n start_line?: number;\n end_line?: number;\n content?: string;\n\n // skill\n skill_name?: string;\n skill_description?: string;\n}\n\nexport interface ChatMessageUsage {\n input_tokens?: number;\n output_tokens?: number;\n total_tokens?: number;\n reasoning_tokens?: number;\n cache_creation_tokens?: number;\n cache_read_tokens?: number;\n context_limit?: number;\n}\n\nexport interface ChatMessage {\n id: number;\n chat_id: string;\n created_by?: string;\n model_config_id?: string;\n created_at: string;\n role: ChatMessageRole;\n content?: ChatMessagePart[];\n usage?: ChatMessageUsage;\n}\n\nexport interface ChatErrorPayload {\n message: string;\n detail?: string;\n kind?: string;\n provider?: string;\n retryable?: boolean;\n status_code?: number;\n}\n\nexport interface Chat {\n id: string;\n organization_id: string;\n owner_id: string;\n owner_username?: string;\n workspace_id?: string | null;\n agent_id?: string | null;\n parent_chat_id?: string | null;\n root_chat_id?: string | null;\n last_model_config_id?: string;\n title: string;\n status: ChatStatus;\n plan_mode?: ChatPlanMode;\n last_error?: ChatErrorPayload | null;\n created_at: string;\n updated_at: string;\n archived: boolean;\n mcp_server_ids?: string[];\n client_type?: ChatClientType;\n}\n\nexport interface ChatQueuedMessage {\n id: number;\n chat_id: string;\n content: ChatMessagePart[];\n created_at: string;\n}\n\nexport interface CreateChatMessageResponse {\n message?: ChatMessage;\n queued_message?: ChatQueuedMessage;\n queued: boolean;\n warnings?: string[];\n}\n\nexport interface ChatMessagesResponse {\n messages: ChatMessage[];\n queued_messages: ChatQueuedMessage[];\n has_more: boolean;\n}\n\n/** Response from `POST /api/experimental/chats/files`: the uploaded file's id. */\nexport interface UploadChatFileResponse {\n id: string;\n}\n\nexport interface ChatModelConfig {\n id: string;\n provider: string;\n ai_provider_id?: string;\n model: string;\n display_name: string;\n enabled?: boolean;\n is_default?: boolean;\n context_limit?: number;\n compression_threshold?: number;\n}\n\n// ---------------------------------------------------------------------------\n// Stream events (WebSocket `/stream`)\n// ---------------------------------------------------------------------------\n\nexport type ChatStreamEventType =\n | \"message_part\"\n | \"message\"\n | \"status\"\n | \"error\"\n | \"queue_update\"\n | \"retry\"\n | \"action_required\"\n | \"preview_reset\"\n | \"history_reset\";\n\nexport interface ChatStreamMessagePart {\n role?: ChatMessageRole;\n part: ChatMessagePart;\n history_version?: number;\n generation_attempt?: number;\n seq?: number;\n}\n\nexport interface ChatStreamStatus {\n status: ChatStatus;\n}\n\nexport interface ChatStreamToolCall {\n tool_call_id: string;\n tool_name: string;\n /** JSON string of the tool-call arguments. */\n args: string;\n}\n\nexport interface ChatStreamActionRequired {\n tool_calls: ChatStreamToolCall[];\n}\n\nexport interface ChatStreamRetry {\n attempt: number;\n delay_ms: number;\n error: string;\n kind?: string;\n provider?: string;\n status_code?: number;\n retrying_at: string;\n}\n\nexport interface ChatStreamEvent {\n type: ChatStreamEventType;\n chat_id: string;\n message?: ChatMessage;\n message_part?: ChatStreamMessagePart;\n status?: ChatStreamStatus;\n error?: ChatErrorPayload;\n retry?: ChatStreamRetry;\n queued_messages?: ChatQueuedMessage[];\n action_required?: ChatStreamActionRequired;\n}\n\n/** Terminal statuses: the chat has stopped generating for this turn. */\nexport const TERMINAL_STATUSES: ReadonlySet<ChatStatus> = new Set<ChatStatus>([\n \"waiting\",\n \"completed\",\n \"error\",\n \"requires_action\",\n]);\n","import NodeWebSocket from \"ws\";\nimport { CoderAgentError } from \"../errors.js\";\nimport type { ChatStreamEvent } from \"./types.js\";\n\n/**\n * A minimal WebSocket factory abstraction so the stream reader can run on\n * Node (via the `ws` package, with header auth) or in environments that\n * provide a global `WebSocket` (browsers, where auth must go in the query\n * string). Node is the default target.\n */\nexport interface WebSocketLike {\n send(data: string): void;\n close(code?: number): void;\n addEventListener(type: \"open\", cb: () => void): void;\n addEventListener(type: \"message\", cb: (ev: { data: unknown }) => void): void;\n addEventListener(type: \"error\", cb: (ev: unknown) => void): void;\n addEventListener(type: \"close\", cb: (ev: { code?: number; reason?: string }) => void): void;\n removeEventListener(type: \"open\", cb: () => void): void;\n removeEventListener(type: \"message\", cb: (ev: { data: unknown }) => void): void;\n removeEventListener(type: \"error\", cb: (ev: unknown) => void): void;\n removeEventListener(type: \"close\", cb: (ev: { code?: number; reason?: string }) => void): void;\n}\n\nexport type WebSocketFactory = (\n url: string,\n protocols: { headers: Record<string, string> },\n) => WebSocketLike;\n\nconst defaultFactory: WebSocketFactory = (url, { headers }) => {\n // `ws` accepts custom handshake headers, which lets us authenticate with the\n // `Coder-Session-Token` header instead of leaking the token into the URL.\n return new NodeWebSocket(url, { headers }) as unknown as WebSocketLike;\n};\n\nfunction httpToWs(baseUrl: string): string {\n if (baseUrl.startsWith(\"https://\")) return `wss://${baseUrl.slice(\"https://\".length)}`;\n if (baseUrl.startsWith(\"http://\")) return `ws://${baseUrl.slice(\"http://\".length)}`;\n return baseUrl;\n}\n\nexport interface StreamChatEventsOptions {\n baseUrl: string;\n token: string;\n chatId: string;\n /** Only stream events for messages with id greater than this. */\n afterId?: number;\n signal?: AbortSignal;\n webSocketFactory?: WebSocketFactory;\n}\n\n/**\n * Opens the chatd `/stream` WebSocket and yields decoded {@link ChatStreamEvent}s\n * as an async iterable. Each text frame from chatd is a JSON array of events;\n * we flatten them into a single stream.\n *\n * The chat stream is a live subscription that stays open after a turn settles,\n * so callers should `break` out of the loop once they observe a terminal status\n * — that triggers generator cleanup, which closes the socket.\n */\nexport async function* streamChatEvents(\n options: StreamChatEventsOptions,\n): AsyncGenerator<ChatStreamEvent, void, void> {\n const { baseUrl, token, chatId, afterId, signal } = options;\n const factory = options.webSocketFactory ?? defaultFactory;\n\n const wsBase = httpToWs(baseUrl);\n const query = afterId !== undefined ? `?after_id=${afterId}` : \"\";\n const url = `${wsBase}/api/experimental/chats/${chatId}/stream${query}`;\n\n const queue: ChatStreamEvent[] = [];\n let resolveNext: (() => void) | undefined;\n let finished = false;\n let failure: Error | undefined;\n\n const wake = () => {\n resolveNext?.();\n resolveNext = undefined;\n };\n\n const ws = factory(url, { headers: { \"Coder-Session-Token\": token } });\n\n const onAbort = () => {\n finished = true;\n try {\n ws.close(1000);\n } catch {\n /* ignore */\n }\n wake();\n };\n let abortListenerAdded = false;\n if (signal) {\n if (signal.aborted) onAbort();\n else {\n signal.addEventListener(\"abort\", onAbort, { once: true });\n abortListenerAdded = true;\n }\n }\n\n const onMessage = (ev: { data: unknown }): void => {\n if (finished) return;\n let batch: unknown;\n try {\n const data = typeof ev.data === \"string\" ? ev.data : String(ev.data);\n batch = JSON.parse(data);\n } catch (err) {\n failure = new CoderAgentError(\"failed to parse chat stream frame\", { cause: err });\n finished = true;\n wake();\n return;\n }\n if (Array.isArray(batch)) {\n for (const e of batch) queue.push(e as ChatStreamEvent);\n } else if (batch && typeof batch === \"object\") {\n queue.push(batch as ChatStreamEvent);\n }\n wake();\n };\n const onError = (ev: unknown): void => {\n if (finished) return;\n const message =\n ev && typeof ev === \"object\" && \"message\" in ev\n ? String((ev as { message: unknown }).message)\n : \"chat stream socket error\";\n failure = new CoderAgentError(message);\n finished = true;\n wake();\n };\n const onClose = (): void => {\n finished = true;\n wake();\n };\n ws.addEventListener(\"message\", onMessage);\n ws.addEventListener(\"error\", onError);\n ws.addEventListener(\"close\", onClose);\n\n try {\n while (true) {\n while (queue.length > 0) {\n const next = queue.shift() as ChatStreamEvent;\n yield next;\n }\n if (failure) throw failure;\n if (finished) return;\n await new Promise<void>((resolve) => {\n resolveNext = resolve;\n });\n }\n } finally {\n finished = true;\n if (signal && abortListenerAdded) signal.removeEventListener(\"abort\", onAbort);\n ws.removeEventListener(\"message\", onMessage);\n ws.removeEventListener(\"error\", onError);\n ws.removeEventListener(\"close\", onClose);\n try {\n ws.close(1000);\n } catch {\n /* ignore */\n }\n }\n}\n","import { CoderAgentError, CoderApiError } from \"../errors.js\";\nimport { type FileContent, resolveFileContent } from \"../files.js\";\nimport {\n type Chat,\n CHAT_ATTACHMENT_MEDIA_TYPES,\n type ChatMessagesResponse,\n type ChatModelConfig,\n type ChatStreamEvent,\n type CreateChatMessageRequest,\n type CreateChatMessageResponse,\n type CreateChatRequest,\n MAX_CHAT_FILE_SIZE_BYTES,\n type SubmitToolResultsRequest,\n type UpdateChatRequest,\n type UploadChatFileResponse,\n} from \"./types.js\";\nimport { streamChatEvents, type WebSocketFactory } from \"./ws.js\";\n\n/** A file to upload as a chat attachment. */\nexport interface ChatFileInput {\n content: FileContent;\n /**\n * Media type. Required unless `content` is a Blob/File with a non-empty `type`\n * — note `fs.openAsBlob()` returns a Blob with no type, so pass it explicitly there.\n */\n mediaType?: string;\n /** Original filename, surfaced to the model and UI. Defaults to a File's `name`. */\n name?: string;\n}\n\n/** A file that has been uploaded to chat-file storage. */\nexport interface UploadedChatFile {\n /** Server-assigned file id, referenced from message content via a `file` part. */\n id: string;\n mediaType: string;\n name?: string;\n}\n\nexport interface CoderChatClientOptions {\n /** Base URL of the Coder deployment, e.g. `https://dev.coder.com`. */\n baseUrl: string;\n /** Coder API token or session token (sent as `Coder-Session-Token`). */\n token: string;\n /** Custom fetch implementation (defaults to global `fetch`). */\n fetch?: typeof globalThis.fetch;\n /** Custom WebSocket factory (defaults to the `ws` package on Node). */\n webSocketFactory?: WebSocketFactory;\n}\n\nconst API_PREFIX = \"/api/experimental/chats\";\n\n/**\n * A thin, typed client for Coder's experimental `chatd` API. This is a\n * TypeScript port of the chat surface of `codersdk.ExperimentalClient`.\n */\nexport class CoderChatClient {\n readonly baseUrl: string;\n readonly #token: string;\n readonly #fetch: typeof globalThis.fetch;\n readonly #webSocketFactory: WebSocketFactory | undefined;\n\n constructor(options: CoderChatClientOptions) {\n // Normalize: strip a single trailing slash.\n this.baseUrl = options.baseUrl.replace(/\\/$/, \"\");\n this.#token = options.token;\n this.#fetch = options.fetch ?? globalThis.fetch.bind(globalThis);\n this.#webSocketFactory = options.webSocketFactory;\n }\n\n /**\n * Issue a request and return the raw `Response` on success (body unread). On a\n * non-2xx status the body is consumed to build a {@link CoderApiError}. Shared\n * by JSON requests and the raw upload/download endpoints.\n */\n async #send(\n method: string,\n path: string,\n opts?: { body?: BodyInit; headers?: Record<string, string>; signal?: AbortSignal },\n ): Promise<Response> {\n const headers: Record<string, string> = {\n \"Coder-Session-Token\": this.#token,\n ...opts?.headers,\n };\n const init: RequestInit = { method, headers, body: opts?.body, signal: opts?.signal };\n // A streaming request body requires half-duplex mode on Node's fetch (undici).\n if (typeof ReadableStream !== \"undefined\" && opts?.body instanceof ReadableStream) {\n (init as RequestInit & { duplex?: \"half\" }).duplex = \"half\";\n }\n\n const res = await this.#fetch(`${this.baseUrl}${path}`, init);\n if (!res.ok) {\n const errObj = (await this.#json<{ message?: string; detail?: string }>(res)) ?? {};\n throw new CoderApiError({\n status: res.status,\n method,\n path,\n message: errObj.message ?? res.statusText ?? \"request failed\",\n detail: errObj.detail,\n });\n }\n return res;\n }\n\n /** Read a response body as JSON, tolerating an unreadable/empty/malformed body (→ undefined). */\n async #json<T>(res: Response): Promise<T | undefined> {\n const text = await res.text().catch(() => \"\");\n if (text.length === 0) return undefined;\n try {\n return JSON.parse(text) as T;\n } catch {\n return undefined;\n }\n }\n\n async #request<T>(\n method: string,\n path: string,\n body?: unknown,\n signal?: AbortSignal,\n ): Promise<T> {\n const res = await this.#send(method, path, {\n body: body === undefined ? undefined : JSON.stringify(body),\n headers: body === undefined ? undefined : { \"Content-Type\": \"application/json\" },\n signal,\n });\n return (await this.#json<T>(res)) as T;\n }\n\n // --- REST -----------------------------------------------------------------\n\n listModelConfigs(signal?: AbortSignal): Promise<ChatModelConfig[]> {\n return this.#request<ChatModelConfig[]>(\n \"GET\",\n `${API_PREFIX}/model-configs`,\n undefined,\n signal,\n );\n }\n\n createChat(req: CreateChatRequest, signal?: AbortSignal): Promise<Chat> {\n return this.#request<Chat>(\"POST\", API_PREFIX, req, signal);\n }\n\n getChat(chatId: string, signal?: AbortSignal): Promise<Chat> {\n return this.#request<Chat>(\"GET\", `${API_PREFIX}/${chatId}`, undefined, signal);\n }\n\n createChatMessage(\n chatId: string,\n req: CreateChatMessageRequest,\n signal?: AbortSignal,\n ): Promise<CreateChatMessageResponse> {\n return this.#request<CreateChatMessageResponse>(\n \"POST\",\n `${API_PREFIX}/${chatId}/messages`,\n req,\n signal,\n );\n }\n\n getMessages(\n chatId: string,\n opts?: { before_id?: number; after_id?: number; limit?: number },\n signal?: AbortSignal,\n ): Promise<ChatMessagesResponse> {\n const params = new URLSearchParams();\n if (opts?.before_id !== undefined) params.set(\"before_id\", String(opts.before_id));\n if (opts?.after_id !== undefined) params.set(\"after_id\", String(opts.after_id));\n if (opts?.limit !== undefined) params.set(\"limit\", String(opts.limit));\n const q = params.toString();\n return this.#request<ChatMessagesResponse>(\n \"GET\",\n `${API_PREFIX}/${chatId}/messages${q ? `?${q}` : \"\"}`,\n undefined,\n signal,\n );\n }\n\n submitToolResults(\n chatId: string,\n req: SubmitToolResultsRequest,\n signal?: AbortSignal,\n ): Promise<void> {\n return this.#request<void>(\"POST\", `${API_PREFIX}/${chatId}/tool-results`, req, signal);\n }\n\n interruptChat(chatId: string, signal?: AbortSignal): Promise<Chat> {\n return this.#request<Chat>(\"POST\", `${API_PREFIX}/${chatId}/interrupt`, undefined, signal);\n }\n\n updateChat(chatId: string, req: UpdateChatRequest, signal?: AbortSignal): Promise<void> {\n return this.#request<void>(\"PATCH\", `${API_PREFIX}/${chatId}`, req, signal);\n }\n\n /** Convenience: archive a chat (soft-hide; safe for cleanup). */\n archiveChat(chatId: string, signal?: AbortSignal): Promise<void> {\n return this.updateChat(chatId, { archived: true }, signal);\n }\n\n // --- Files ----------------------------------------------------------------\n\n /**\n * Upload a file as a durable chat attachment, returning its id (referenced\n * from message content via a `file` input part). The server enforces a narrow\n * media-type allowlist and a 10 MiB cap; both are checked client-side first so\n * unsupported files fail fast with a clear error instead of an opaque 4xx.\n *\n * The body is sent raw (not multipart): `Content-Type` carries the media type\n * and `Content-Disposition` the filename, mirroring `codersdk`.\n */\n async uploadChatFile(\n organizationId: string,\n file: ChatFileInput,\n signal?: AbortSignal,\n ): Promise<UploadedChatFile> {\n const resolved = resolveFileContent(file.content, {\n mediaType: file.mediaType,\n name: file.name,\n });\n // Match the allowlist on the media type alone, ignoring parameters such as\n // `; charset=utf-8` that a Blob/File commonly carries.\n const mediaType = (resolved.mediaType.split(\";\")[0] ?? resolved.mediaType).trim().toLowerCase();\n if (!CHAT_ATTACHMENT_MEDIA_TYPES.has(mediaType)) {\n throw new CoderAgentError(\n `Media type \"${mediaType}\" is not allowed for chat attachments ` +\n `(allowed: ${[...CHAT_ATTACHMENT_MEDIA_TYPES].join(\", \")}). ` +\n `Write other file types to a workspace instead.`,\n );\n }\n if (resolved.size !== undefined && resolved.size > MAX_CHAT_FILE_SIZE_BYTES) {\n throw new CoderAgentError(\n `File is ${resolved.size} bytes, over the ${MAX_CHAT_FILE_SIZE_BYTES}-byte ` +\n `(10 MiB) chat attachment limit. Write large files to a workspace instead.`,\n );\n }\n\n const headers: Record<string, string> = { \"Content-Type\": mediaType };\n if (resolved.name) {\n // RFC 6266: a sanitized ASCII `filename` plus an RFC 5987 `filename*` that\n // preserves the exact name. Both are pure ASCII, so a non-Latin-1 name\n // (CJK, emoji, accents) can't trip fetch's ByteString header check, and\n // CR/LF/quote/backslash are encoded away rather than breaking the header.\n const ascii = resolved.name.replace(/[^\\x20-\\x7e]/g, \"_\").replace(/([\"\\\\])/g, \"\\\\$1\");\n const utf8 = encodeURIComponent(resolved.name).replace(\n /['()*]/g,\n (c) => `%${c.charCodeAt(0).toString(16).toUpperCase()}`,\n );\n headers[\"Content-Disposition\"] = `attachment; filename=\"${ascii}\"; filename*=UTF-8''${utf8}`;\n }\n const res = await this.#send(\n \"POST\",\n `${API_PREFIX}/files?organization=${encodeURIComponent(organizationId)}`,\n { body: resolved.body, headers, signal },\n );\n const parsed = await this.#json<UploadChatFileResponse>(res);\n if (!parsed?.id) {\n throw new CoderApiError({\n status: res.status,\n method: \"POST\",\n path: `${API_PREFIX}/files`,\n message: \"upload succeeded but the response contained no file id\",\n });\n }\n return { id: parsed.id, mediaType, name: resolved.name };\n }\n\n /** Download a chat file's bytes and media type by id. */\n async getChatFile(\n fileId: string,\n signal?: AbortSignal,\n ): Promise<{ bytes: Uint8Array; mediaType: string }> {\n const res = await this.#send(\"GET\", `${API_PREFIX}/files/${fileId}`, { signal });\n const buf = await res.arrayBuffer();\n return {\n bytes: new Uint8Array(buf),\n mediaType: res.headers.get(\"Content-Type\") ?? \"application/octet-stream\",\n };\n }\n\n // --- Streaming ------------------------------------------------------------\n\n streamEvents(\n chatId: string,\n opts?: { afterId?: number; signal?: AbortSignal },\n ): AsyncGenerator<ChatStreamEvent, void, void> {\n return streamChatEvents({\n baseUrl: this.baseUrl,\n token: this.#token,\n chatId,\n afterId: opts?.afterId,\n signal: opts?.signal,\n webSocketFactory: this.#webSocketFactory,\n });\n }\n\n // --- Helpers --------------------------------------------------------------\n\n /**\n * Resolves a user-friendly model hint to a model-config UUID.\n *\n * Accepts: a config UUID (returned as-is), a `provider:model` id\n * (e.g. `anthropic:claude-haiku-4-5-20251001`), a bare model id, or a\n * display-name substring (case-insensitive). Returns `undefined` if no\n * match is found, in which case the caller should let chatd pick the default.\n */\n async resolveModelConfigId(hint: string, signal?: AbortSignal): Promise<string | undefined> {\n const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\n if (UUID_RE.test(hint)) return hint;\n\n const configs = await this.listModelConfigs(signal);\n const lower = hint.toLowerCase();\n // `provider:model` form.\n const colon = hint.indexOf(\":\");\n const provider = colon >= 0 ? hint.slice(0, colon).toLowerCase() : undefined;\n const model = colon >= 0 ? hint.slice(colon + 1).toLowerCase() : lower;\n\n const candidates = configs.filter((c) => c.enabled !== false);\n const pool = candidates.length > 0 ? candidates : configs;\n\n const exact = pool.find(\n (c) =>\n c.model.toLowerCase() === model &&\n (provider === undefined || c.provider.toLowerCase() === provider),\n );\n if (exact) return exact.id;\n\n const byModel = pool.find((c) => c.model.toLowerCase() === model);\n if (byModel) return byModel.id;\n\n const byDisplay = pool.find((c) => c.display_name.toLowerCase().includes(lower));\n if (byDisplay) return byDisplay.id;\n\n const byModelSubstring = pool.find((c) => c.model.toLowerCase().includes(model));\n return byModelSubstring?.id;\n }\n}\n","import type {\n LanguageModelV3CallOptions,\n LanguageModelV3DataContent,\n LanguageModelV3Message,\n LanguageModelV3Prompt,\n LanguageModelV3ToolResultOutput,\n} from \"@ai-sdk/provider\";\nimport type { ChatInputPart, DynamicTool, ToolResult } from \"../coder/types.js\";\n\n/** Namespace key for this package's options on AI SDK message-part `providerOptions`. */\nexport const CODER_PROVIDER_OPTIONS = \"coder\";\n\n/** Shape of this package's `providerOptions.coder` payload on a file part. */\nexport interface CoderFileProviderOptions {\n /** A pre-uploaded chat-file id to reuse instead of uploading the part's bytes. */\n fileId?: string;\n}\n\n/** Concatenated system messages, mapped to chatd's `system_prompt`. */\nexport function extractSystemPrompt(prompt: LanguageModelV3Prompt): string | undefined {\n const parts = prompt.filter(\n (m): m is Extract<LanguageModelV3Message, { role: \"system\" }> => m.role === \"system\",\n );\n if (parts.length === 0) return undefined;\n const joined = parts\n .map((m) => m.content)\n .join(\"\\n\\n\")\n .trim();\n return joined.length > 0 ? joined : undefined;\n}\n\n/** The content array of a user message (text and file parts). */\nexport type UserContent = Extract<LanguageModelV3Message, { role: \"user\" }>[\"content\"];\n\n/**\n * Uploads a file part's bytes and resolves to its chatd file id. Supplied by\n * the language model (which holds the client + organization id); kept abstract\n * here so {@link userContentToInputParts} stays pure and testable.\n */\nexport type FilePartUploader = (file: {\n data: LanguageModelV3DataContent;\n mediaType: string;\n filename?: string;\n}) => Promise<string>;\n\n/** Reads a pre-uploaded file id from a file part's `providerOptions.coder.fileId`. */\nfunction coderFileId(providerOptions: unknown): string | undefined {\n const ns = (providerOptions as Record<string, CoderFileProviderOptions> | undefined)?.[\n CODER_PROVIDER_OPTIONS\n ];\n // Require a non-empty id: an empty string is not a usable reference, so fall\n // back to uploading rather than emitting `file_id: \"\"`.\n return typeof ns?.fileId === \"string\" && ns.fileId.length > 0 ? ns.fileId : undefined;\n}\n\n/**\n * Maps a user message's content to chatd input parts. Text passes through;\n * file parts are turned into `file` parts referencing an uploaded file id —\n * either reused from `providerOptions.coder.fileId` (a pre-uploaded handle) or\n * uploaded on the fly via {@link FilePartUploader}.\n */\nexport async function userContentToInputParts(\n content: UserContent,\n uploadFile: FilePartUploader,\n): Promise<ChatInputPart[]> {\n // Uploads are independent, so run them concurrently; `map` preserves order.\n const parts = await Promise.all(\n content.map(async (part): Promise<ChatInputPart | null> => {\n if (part.type === \"text\") {\n return part.text.length > 0 ? { type: \"text\", text: part.text } : null;\n }\n if (part.type === \"file\") {\n const fileId =\n coderFileId(part.providerOptions) ??\n (await uploadFile({\n data: part.data,\n mediaType: part.mediaType,\n filename: part.filename,\n }));\n return { type: \"file\", file_id: fileId };\n }\n return null;\n }),\n );\n return parts.filter((p): p is ChatInputPart => p !== null);\n}\n\nfunction toolResultOutputToChatd(output: LanguageModelV3ToolResultOutput): {\n value: unknown;\n isError: boolean;\n} {\n switch (output.type) {\n case \"text\":\n return { value: output.value, isError: false };\n case \"json\":\n return { value: output.value, isError: false };\n case \"error-text\":\n return { value: output.value, isError: true };\n case \"error-json\":\n return { value: output.value, isError: true };\n case \"execution-denied\":\n return { value: { execution_denied: true, reason: output.reason }, isError: true };\n case \"content\":\n return { value: output.value, isError: false };\n default:\n return { value: output, isError: false };\n }\n}\n\nexport type TurnAction =\n | { kind: \"new-turn\"; content: UserContent }\n | { kind: \"resume\"; toolResults: ToolResult[] }\n | { kind: \"noop\" };\n\n/**\n * Decides what to do with a fresh `doStream`/`doGenerate` prompt:\n * - trailing `tool` message(s) → resume the in-flight chatd turn by submitting\n * those tool results (the AI SDK executed a client tool between steps);\n * - otherwise the trailing `user` message → a new turn.\n */\nexport function classifyTurnAction(prompt: LanguageModelV3Prompt): TurnAction {\n if (prompt.length === 0) return { kind: \"noop\" };\n const last = prompt[prompt.length - 1];\n if (!last) return { kind: \"noop\" };\n\n if (last.role === \"tool\") {\n const toolResults: ToolResult[] = [];\n // Collect from all trailing consecutive tool messages.\n for (let i = prompt.length - 1; i >= 0; i--) {\n const m = prompt[i];\n if (!m || m.role !== \"tool\") break;\n for (const part of m.content) {\n if (part.type !== \"tool-result\") continue;\n const { value, isError } = toolResultOutputToChatd(part.output);\n toolResults.unshift({ tool_call_id: part.toolCallId, output: value, is_error: isError });\n }\n }\n return { kind: \"resume\", toolResults };\n }\n\n if (last.role === \"user\") {\n return { kind: \"new-turn\", content: last.content };\n }\n\n return { kind: \"noop\" };\n}\n\n/** Maps AI SDK function tools to chatd client-executed (\"dynamic\") tools. */\nexport function toolsToDynamicTools(tools: LanguageModelV3CallOptions[\"tools\"]): DynamicTool[] {\n if (!tools) return [];\n const out: DynamicTool[] = [];\n for (const tool of tools) {\n if (tool.type !== \"function\") continue; // provider tools are not forwarded\n out.push({\n name: tool.name,\n description: tool.description,\n input_schema: tool.inputSchema,\n });\n }\n return out;\n}\n\n/** The set of tool names the AI SDK side owns (i.e. client-executed). */\nexport function dynamicToolNames(tools: LanguageModelV3CallOptions[\"tools\"]): Set<string> {\n const names = new Set<string>();\n for (const tool of tools ?? []) {\n if (tool.type === \"function\") names.add(tool.name);\n }\n return names;\n}\n","import type {\n LanguageModelV3FinishReason,\n LanguageModelV3StreamPart,\n LanguageModelV3Usage,\n} from \"@ai-sdk/provider\";\nimport { CoderChatError } from \"../errors.js\";\nimport {\n type ChatErrorPayload,\n type ChatMessage,\n type ChatMessagePart,\n type ChatMessageUsage,\n type ChatStatus,\n type ChatStreamEvent,\n TERMINAL_STATUSES,\n} from \"../coder/types.js\";\n\nfunction mapUsage(u: ChatMessageUsage | undefined): LanguageModelV3Usage {\n return {\n inputTokens: {\n total: u?.input_tokens,\n noCache: undefined,\n cacheRead: u?.cache_read_tokens,\n cacheWrite: u?.cache_creation_tokens,\n },\n outputTokens: {\n total: u?.output_tokens,\n text: undefined,\n reasoning: u?.reasoning_tokens,\n },\n };\n}\n\nfunction jsonResult(value: unknown): NonNullable<unknown> {\n // chatd tool results are arbitrary JSON; the V3 tool-result `result` must be\n // a non-null JSON value.\n return (value ?? {}) as NonNullable<unknown>;\n}\n\n/**\n * Translates one chatd turn's {@link ChatStreamEvent} stream into a sequence of\n * `LanguageModelV3StreamPart`s for the AI SDK.\n *\n * Two text/reasoning modes, decided per turn from the wire behavior:\n * - **delta mode** — chatd streamed `message_part` deltas; we emit those and\n * treat the trailing full `message` snapshot as a no-op for text/reasoning.\n * - **snapshot mode** — fast turns where only full `message` snapshots arrive;\n * we diff each snapshot's full text against what we've already emitted.\n * Both paths track an emitted-length cursor, so neither double-counts.\n *\n * Client (custom) tool calls are emitted from the reliable `action_required`\n * event and left for the AI SDK to execute. chatd's own server-side tools are\n * surfaced best-effort as `providerExecuted` tool calls/results.\n */\nexport class TurnTranslator {\n readonly #dynamicToolNames: ReadonlySet<string>;\n\n #seq = 0;\n #text = { id: undefined as string | undefined, len: 0, sawDelta: false };\n #reasoning = { id: undefined as string | undefined, len: 0, sawDelta: false };\n #currentAssistantId: number | undefined;\n\n #serverToolCalls = new Set<string>();\n #serverToolResults = new Set<string>();\n #clientToolCalls = new Set<string>();\n #clientToolCallSeen = false;\n\n #usage: ChatMessageUsage | undefined;\n #error: ChatErrorPayload | undefined;\n #terminalStatus: ChatStatus | undefined;\n #maxMessageId = 0;\n\n constructor(opts: { dynamicToolNames: ReadonlySet<string> }) {\n this.#dynamicToolNames = opts.dynamicToolNames;\n }\n\n get terminalStatus(): ChatStatus | undefined {\n return this.#terminalStatus;\n }\n /** Whether a client (custom) tool call has been emitted this turn. */\n get clientToolCallSeen(): boolean {\n return this.#clientToolCallSeen;\n }\n get maxMessageId(): number {\n return this.#maxMessageId;\n }\n get error(): ChatErrorPayload | undefined {\n return this.#error;\n }\n\n // --- block helpers --------------------------------------------------------\n\n #openText(out: LanguageModelV3StreamPart[]): void {\n if (this.#reasoning.id) this.#closeReasoning(out);\n if (!this.#text.id) {\n this.#text.id = `text-${++this.#seq}`;\n this.#text.len = 0;\n out.push({ type: \"text-start\", id: this.#text.id });\n }\n }\n #closeText(out: LanguageModelV3StreamPart[]): void {\n if (this.#text.id) {\n out.push({ type: \"text-end\", id: this.#text.id });\n this.#text.id = undefined;\n this.#text.len = 0;\n }\n }\n #openReasoning(out: LanguageModelV3StreamPart[]): void {\n if (this.#text.id) this.#closeText(out);\n if (!this.#reasoning.id) {\n this.#reasoning.id = `reasoning-${++this.#seq}`;\n this.#reasoning.len = 0;\n out.push({ type: \"reasoning-start\", id: this.#reasoning.id });\n }\n }\n #closeReasoning(out: LanguageModelV3StreamPart[]): void {\n if (this.#reasoning.id) {\n out.push({ type: \"reasoning-end\", id: this.#reasoning.id });\n this.#reasoning.id = undefined;\n this.#reasoning.len = 0;\n }\n }\n\n #emitTextUpTo(out: LanguageModelV3StreamPart[], full: string): void {\n if (full.length <= this.#text.len && this.#text.id) return;\n this.#openText(out);\n if (full.length > this.#text.len) {\n out.push({\n type: \"text-delta\",\n id: this.#text.id as string,\n delta: full.slice(this.#text.len),\n });\n this.#text.len = full.length;\n }\n }\n #emitReasoningUpTo(out: LanguageModelV3StreamPart[], full: string): void {\n if (full.length <= this.#reasoning.len && this.#reasoning.id) return;\n this.#openReasoning(out);\n if (full.length > this.#reasoning.len) {\n out.push({\n type: \"reasoning-delta\",\n id: this.#reasoning.id as string,\n delta: full.slice(this.#reasoning.len),\n });\n this.#reasoning.len = full.length;\n }\n }\n\n // --- tool helpers ---------------------------------------------------------\n\n #isClientTool(name: string | undefined): boolean {\n return name !== undefined && this.#dynamicToolNames.has(name);\n }\n\n #emitServerToolCall(out: LanguageModelV3StreamPart[], part: ChatMessagePart): void {\n const id = part.tool_call_id;\n const name = part.tool_name;\n if (!id || !name) return;\n if (part.args === undefined) return; // wait for complete args (snapshot)\n if (this.#serverToolCalls.has(id)) return;\n this.#serverToolCalls.add(id);\n out.push({ type: \"tool-input-start\", id, toolName: name, providerExecuted: true });\n out.push({ type: \"tool-input-end\", id });\n out.push({\n type: \"tool-call\",\n toolCallId: id,\n toolName: name,\n input: typeof part.args === \"string\" ? part.args : JSON.stringify(part.args),\n providerExecuted: true,\n });\n }\n\n #emitServerToolResult(out: LanguageModelV3StreamPart[], part: ChatMessagePart): void {\n const id = part.tool_call_id;\n const name = part.tool_name;\n if (!id || !name) return;\n if (part.result === undefined) return;\n if (this.#serverToolResults.has(id)) return;\n this.#serverToolResults.add(id);\n out.push({\n type: \"tool-result\",\n toolCallId: id,\n toolName: name,\n result: jsonResult(part.result),\n isError: part.is_error ?? false,\n });\n }\n\n // --- ingest ---------------------------------------------------------------\n\n ingest(ev: ChatStreamEvent): LanguageModelV3StreamPart[] {\n const out: LanguageModelV3StreamPart[] = [];\n switch (ev.type) {\n case \"message_part\":\n this.#ingestMessagePart(out, ev);\n break;\n case \"message\":\n if (ev.message) this.#ingestMessage(out, ev.message);\n break;\n case \"action_required\":\n for (const tc of ev.action_required?.tool_calls ?? []) {\n if (this.#clientToolCalls.has(tc.tool_call_id)) continue;\n this.#closeText(out);\n this.#closeReasoning(out);\n this.#clientToolCalls.add(tc.tool_call_id);\n this.#clientToolCallSeen = true;\n out.push({ type: \"tool-input-start\", id: tc.tool_call_id, toolName: tc.tool_name });\n out.push({ type: \"tool-input-end\", id: tc.tool_call_id });\n out.push({\n type: \"tool-call\",\n toolCallId: tc.tool_call_id,\n toolName: tc.tool_name,\n input: tc.args,\n });\n }\n break;\n case \"error\":\n if (ev.error) {\n this.#error = ev.error;\n out.push({ type: \"error\", error: new CoderChatError(ev.error) });\n }\n break;\n case \"status\":\n if (ev.status && TERMINAL_STATUSES.has(ev.status.status)) {\n this.#terminalStatus = ev.status.status;\n }\n break;\n default:\n break; // retry / queue_update / preview_reset / history_reset\n }\n return out;\n }\n\n #ingestMessagePart(out: LanguageModelV3StreamPart[], ev: ChatStreamEvent): void {\n const mp = ev.message_part;\n if (!mp || (mp.role !== \"assistant\" && mp.role !== \"tool\")) return;\n const part = mp.part;\n switch (part.type) {\n case \"text\":\n this.#text.sawDelta = true;\n this.#openText(out);\n if (part.text) {\n out.push({ type: \"text-delta\", id: this.#text.id as string, delta: part.text });\n this.#text.len += part.text.length;\n }\n break;\n case \"reasoning\":\n this.#reasoning.sawDelta = true;\n this.#openReasoning(out);\n if (part.text) {\n out.push({ type: \"reasoning-delta\", id: this.#reasoning.id as string, delta: part.text });\n this.#reasoning.len += part.text.length;\n }\n break;\n case \"tool-call\":\n this.#closeText(out);\n this.#closeReasoning(out);\n if (!this.#isClientTool(part.tool_name)) this.#emitServerToolCall(out, part);\n break;\n case \"tool-result\":\n if (!this.#isClientTool(part.tool_name)) this.#emitServerToolResult(out, part);\n break;\n default:\n break;\n }\n }\n\n #ingestMessage(out: LanguageModelV3StreamPart[], message: ChatMessage): void {\n if (message.id > this.#maxMessageId) this.#maxMessageId = message.id;\n if (message.usage && (message.role === \"assistant\" || message.role === \"tool\")) {\n this.#usage = message.usage;\n }\n const content = message.content ?? [];\n\n if (message.role === \"assistant\") {\n // New assistant message boundary: close prior blocks and reset cursors.\n if (this.#currentAssistantId !== undefined && this.#currentAssistantId !== message.id) {\n this.#closeText(out);\n this.#closeReasoning(out);\n this.#text.sawDelta = false;\n this.#reasoning.sawDelta = false;\n }\n this.#currentAssistantId = message.id;\n\n if (!this.#text.sawDelta) {\n const full = content\n .filter((p) => p.type === \"text\")\n .map((p) => p.text ?? \"\")\n .join(\"\");\n if (full.length > 0) this.#emitTextUpTo(out, full);\n }\n if (!this.#reasoning.sawDelta) {\n const full = content\n .filter((p) => p.type === \"reasoning\")\n .map((p) => p.text ?? \"\")\n .join(\"\");\n if (full.length > 0) this.#emitReasoningUpTo(out, full);\n }\n for (const part of content) {\n if (part.type === \"tool-call\" && !this.#isClientTool(part.tool_name))\n this.#emitServerToolCall(out, part);\n else if (part.type === \"tool-result\" && !this.#isClientTool(part.tool_name))\n this.#emitServerToolResult(out, part);\n }\n } else if (message.role === \"tool\") {\n for (const part of content) {\n if (part.type === \"tool-result\" && !this.#isClientTool(part.tool_name))\n this.#emitServerToolResult(out, part);\n }\n }\n }\n\n // --- finish ---------------------------------------------------------------\n\n finish(): LanguageModelV3StreamPart[] {\n const out: LanguageModelV3StreamPart[] = [];\n this.#closeText(out);\n this.#closeReasoning(out);\n\n let unified: LanguageModelV3FinishReason[\"unified\"];\n if (this.#error || this.#terminalStatus === \"error\") unified = \"error\";\n else if (this.#clientToolCallSeen || this.#terminalStatus === \"requires_action\")\n unified = \"tool-calls\";\n else unified = \"stop\";\n\n out.push({\n type: \"finish\",\n usage: mapUsage(this.#usage),\n finishReason: { unified, raw: this.#terminalStatus },\n });\n return out;\n }\n}\n","import type {\n LanguageModelV3,\n LanguageModelV3CallOptions,\n LanguageModelV3Content,\n LanguageModelV3GenerateResult,\n LanguageModelV3StreamPart,\n LanguageModelV3StreamResult,\n LanguageModelV3Usage,\n SharedV3Warning,\n} from \"@ai-sdk/provider\";\nimport { CoderAgentError, CoderApiError, CoderChatError } from \"../errors.js\";\nimport { CoderChatClient } from \"../coder/client.js\";\nimport type { ChatInputPart, CreateChatRequest } from \"../coder/types.js\";\nimport { dataContentToFileContent } from \"../files.js\";\nimport {\n classifyTurnAction,\n dynamicToolNames,\n extractSystemPrompt,\n type FilePartUploader,\n toolsToDynamicTools,\n type UserContent,\n userContentToInputParts,\n} from \"./prompt.js\";\nimport { TurnTranslator } from \"./translate.js\";\n\nconst EMPTY_USAGE: LanguageModelV3Usage = {\n inputTokens: {\n total: undefined,\n noCache: undefined,\n cacheRead: undefined,\n cacheWrite: undefined,\n },\n outputTokens: { total: undefined, text: undefined, reasoning: undefined },\n};\n\nexport interface CoderLanguageModelConfig {\n client: CoderChatClient;\n organizationId: string;\n /** Model hint (UUID, `provider:model`, model id, or display-name substring). */\n model?: string;\n /** Bind the chat to a Coder workspace (enables workspace tools). */\n workspaceId?: string;\n /** chatd-side MCP servers to enable. */\n mcpServerIds?: string[];\n planMode?: \"\" | \"plan\";\n /** Resume an existing chat instead of creating a new one. */\n chatId?: string;\n /**\n * Per-segment time budget in milliseconds, applied to each model round-trip\n * (one `doStream`/`doGenerate` call: chat creation or message/tool-result\n * submission, plus the server-side run until it settles or pauses for a client\n * tool). If exceeded, the run is interrupted server-side and the call rejects\n * with a retryable {@link CoderChatError} (`kind: \"timeout\"`). A multi-step\n * `generate()` that drives client tools makes several segments, so this bounds\n * each segment, not the whole call — to cap total wall-clock, pass\n * `abortSignal: AbortSignal.timeout(ms)`. Unset or non-positive means no limit.\n */\n requestTimeoutMs?: number;\n}\n\n/**\n * A {@link LanguageModelV3} that is backed by a remote Coder `chatd` agent\n * runtime instead of a raw LLM. One model instance owns one chatd chat\n * (a \"session\"): the chat is created lazily on the first turn and reused for\n * subsequent turns and for client-tool resume steps.\n *\n * The chatd server runs the agent loop (model calls, server-side tools,\n * compaction) itself. This model therefore represents *one chatd segment* per\n * `doStream` call — it advances the chat until it settles (`waiting`/\n * `completed`) or pauses for a client tool (`requires_action`). When the AI SDK\n * executes a client tool and calls `doStream` again with the tool result, this\n * model resumes the same chat. The two loops mesh at the client-tool boundary.\n *\n * NOTE: a single model instance is single-flight — do not run concurrent\n * generations against the same instance/session.\n */\nexport class CoderLanguageModel implements LanguageModelV3 {\n readonly specificationVersion = \"v3\" as const;\n readonly provider = \"coder.chatd\";\n readonly modelId: string;\n readonly supportedUrls: Record<string, RegExp[]> = {};\n\n readonly #config: CoderLanguageModelConfig;\n #chatId: string | undefined;\n #lastSeenMessageId = 0;\n #resolvedModelConfigId: string | undefined;\n #modelResolved = false;\n readonly #submittedToolCallIds = new Set<string>();\n #inFlight = false;\n\n constructor(config: CoderLanguageModelConfig) {\n this.#config = config;\n this.modelId = config.model ?? \"chatd\";\n this.#chatId = config.chatId;\n }\n\n get chatId(): string | undefined {\n return this.#chatId;\n }\n\n /** Drops the current session so the next turn creates a fresh chat. */\n resetSession(): void {\n this.#chatId = undefined;\n this.#lastSeenMessageId = 0;\n this.#submittedToolCallIds.clear();\n }\n\n async #resolveModelConfigId(signal?: AbortSignal): Promise<string | undefined> {\n if (this.#modelResolved) return this.#resolvedModelConfigId;\n if (this.#config.model) {\n this.#resolvedModelConfigId = await this.#config.client.resolveModelConfigId(\n this.#config.model,\n signal,\n );\n }\n this.#modelResolved = true;\n return this.#resolvedModelConfigId;\n }\n\n /**\n * Resolve a user message's content to chatd input parts, uploading any file\n * parts to chat-file storage (the upload endpoint needs only the organization\n * id, so this runs before the chat exists). Pre-uploaded files carried via\n * `providerOptions.coder.fileId` are referenced without re-uploading.\n */\n #buildContent(content: UserContent, signal?: AbortSignal): Promise<ChatInputPart[]> {\n const uploadFile: FilePartUploader = async (f) => {\n const uploaded = await this.#config.client.uploadChatFile(\n this.#config.organizationId,\n { content: dataContentToFileContent(f.data), mediaType: f.mediaType, name: f.filename },\n signal,\n );\n return uploaded.id;\n };\n return userContentToInputParts(content, uploadFile);\n }\n\n async *#runTurn(\n options: LanguageModelV3CallOptions,\n ): AsyncGenerator<LanguageModelV3StreamPart, void, void> {\n // A single model instance owns one chatd session's mutable state, so it is\n // single-flight: reject overlapping turns rather than silently corrupting\n // chatId / lastSeenMessageId / submitted tool-call tracking.\n if (this.#inFlight) {\n throw new CoderAgentError(\n \"A generation is already in flight on this CoderAgent (single-flight). Use a separate CoderAgent instance for concurrent sessions.\",\n );\n }\n this.#inFlight = true;\n\n // Combine the caller's abort signal with an optional per-turn timeout into a\n // single signal (the platform composes and cleans these up for us). When\n // there's neither a caller signal nor a timeout, `signal` stays undefined and\n // there is no per-turn setup. Keep a reference to our *own* timeout signal so\n // a timeout stays distinguishable from a caller abort — even when the caller's\n // own signal is itself an `AbortSignal.timeout` (whose reason is a TimeoutError\n // too, so reason-sniffing alone would misclassify it).\n const externalSignal = options.abortSignal;\n const timeoutMs = this.#config.requestTimeoutMs;\n const timeoutSignal =\n timeoutMs !== undefined && timeoutMs > 0 ? AbortSignal.timeout(timeoutMs) : undefined;\n const sources = [externalSignal, timeoutSignal].filter(\n (s): s is AbortSignal => s !== undefined,\n );\n const signal: AbortSignal | undefined =\n sources.length > 0 ? AbortSignal.any(sources) : undefined;\n\n // Translator is hoisted so `finally` can read whether the turn settled.\n const translator = new TurnTranslator({ dynamicToolNames: dynamicToolNames(options.tools) });\n\n // Interrupting the *server* run (not just closing the WebSocket) is what frees\n // the chat's workspace/resources. Fire it at most once — on abort/timeout, and\n // on teardown of an unsettled turn (see `finally`), which also covers stream\n // `cancel()` and premature close, neither of which aborts the signal. A chat\n // whose id we never received (createChat aborted mid-flight) can't be reached.\n let interruptSent = false;\n const interrupt = (): void => {\n const id = this.#chatId;\n if (interruptSent || !id) return;\n interruptSent = true;\n void this.#config.client.interruptChat(id).catch(() => {});\n };\n signal?.addEventListener(\"abort\", interrupt, { once: true });\n\n // Map an abort of the combined signal to the right error. Our own\n // `timeoutSignal` having fired means a per-turn timeout; otherwise it's a\n // caller abort, re-thrown as the caller's reason (preserving AbortError so the\n // AI SDK still recognizes the cancellation).\n const throwIfAborted = (): void => {\n if (timeoutSignal?.aborted) {\n throw new CoderChatError({\n message: `Coder Agent turn exceeded its ${timeoutMs}ms requestTimeoutMs budget.`,\n kind: \"timeout\",\n retryable: true,\n });\n }\n if (signal?.aborted) {\n throw (\n externalSignal?.reason ?? new DOMException(\"The operation was aborted.\", \"AbortError\")\n );\n }\n };\n\n try {\n const { prompt } = options;\n\n // chatd does not constrain output to a JSON schema server-side, so a\n // `responseFormat: json` request can't be honored. Warn rather than\n // silently mislead — schema-constrained output should go through the\n // provider (@coder/ai-sdk-provider) instead.\n const warnings: SharedV3Warning[] = [];\n if (options.responseFormat?.type === \"json\") {\n warnings.push({\n type: \"unsupported\",\n feature: \"responseFormat\",\n details:\n \"Coder Agents does not enforce a JSON schema server-side, so structured output is best-effort (not schema-constrained). For reliable structured output, use @coder/ai-sdk-provider (createCoder) with generateObject / Output.object.\",\n });\n }\n yield { type: \"stream-start\", warnings };\n\n const action = classifyTurnAction(prompt);\n if (action.kind === \"noop\") {\n throw new CoderAgentError(\n \"CoderAgent received a prompt with no user message or tool results to act on.\",\n );\n }\n\n let afterId: number | undefined;\n\n if (action.kind === \"new-turn\") {\n // Resolve the model config and upload any file parts concurrently — they\n // are independent round-trips. (Uploads run before the chat exists and\n // resolve file parts to `file` input parts referencing their uploaded ids.)\n const [modelConfigId, content] = await Promise.all([\n this.#resolveModelConfigId(signal),\n this.#buildContent(action.content, signal),\n ]);\n if (!this.#chatId) {\n const req: CreateChatRequest = {\n organization_id: this.#config.organizationId,\n content,\n client_type: \"api\",\n };\n const system = extractSystemPrompt(prompt);\n if (system) req.system_prompt = system;\n const tools = toolsToDynamicTools(options.tools);\n if (tools.length > 0) req.unsafe_dynamic_tools = tools;\n if (modelConfigId) req.model_config_id = modelConfigId;\n if (this.#config.workspaceId) req.workspace_id = this.#config.workspaceId;\n if (this.#config.mcpServerIds?.length) req.mcp_server_ids = this.#config.mcpServerIds;\n if (this.#config.planMode) req.plan_mode = this.#config.planMode;\n const chat = await this.#config.client.createChat(req, signal);\n this.#chatId = chat.id;\n afterId = this.#lastSeenMessageId > 0 ? this.#lastSeenMessageId : undefined;\n } else {\n const resp = await this.#config.client.createChatMessage(\n this.#chatId,\n {\n content,\n ...(modelConfigId ? { model_config_id: modelConfigId } : {}),\n },\n signal,\n );\n afterId = resp.message?.id ?? this.#lastSeenMessageId;\n }\n } else {\n // resume\n if (!this.#chatId)\n throw new CoderChatError({ message: \"cannot submit tool results before a chat exists\" });\n const fresh = action.toolResults.filter(\n (r) => !this.#submittedToolCallIds.has(r.tool_call_id),\n );\n if (fresh.length > 0) {\n await this.#config.client.submitToolResults(this.#chatId, { results: fresh }, signal);\n for (const r of fresh) this.#submittedToolCallIds.add(r.tool_call_id);\n }\n afterId = this.#lastSeenMessageId;\n }\n\n const chatId = this.#chatId as string;\n // chatd emits the `requires_action` status BEFORE the `action_required`\n // event that carries the pending tool calls, so for that status we keep\n // reading until the client tool calls have actually been emitted (bounded\n // by a safety counter, since the stream is a live subscription).\n let sinceRequiresAction = 0;\n try {\n for await (const ev of this.#config.client.streamEvents(chatId, { afterId, signal })) {\n for (const part of translator.ingest(ev)) yield part;\n const status = translator.terminalStatus;\n if (status) {\n if (status !== \"requires_action\") break;\n if (translator.clientToolCallSeen) break;\n if (++sinceRequiresAction > 200) break;\n }\n }\n } catch (err) {\n // Abort surfaces here only if the reader threw instead of closing cleanly;\n // prefer the abort/timeout classification.\n throwIfAborted();\n // The reader only throws transport-level CoderAgentErrors (socket error /\n // unparseable frame). Surface them as a retryable stream failure so a\n // caller's `CoderChatError && retryable` retry path catches a dropped\n // connection instead of seeing a bare, non-retryable error.\n if (\n err instanceof CoderAgentError &&\n !(err instanceof CoderApiError) &&\n !(err instanceof CoderChatError)\n ) {\n throw new CoderChatError({\n message: `Coder chat stream failed mid-turn: ${err.message}`,\n kind: \"stream_closed\",\n retryable: true,\n });\n }\n throw err;\n }\n\n // The stream loop exits cleanly when the socket closes on abort, so classify\n // an abort/timeout here before treating the end as a normal/closed turn.\n throwIfAborted();\n\n // No terminal status: the stream ended before the turn settled. If an\n // `error` event arrived (without a trailing `status: error`), fall through to\n // finish() so the real error surfaces (unified:\"error\" + the error part),\n // consistent with the `status: error` path; otherwise it's a genuine\n // premature close — surface it rather than a clean (truncated) `stop`.\n if (!translator.terminalStatus && !translator.error) {\n throw new CoderChatError({\n message:\n \"Coder chat stream ended before the turn settled (connection closed or the server ended the stream without a terminal status).\",\n kind: \"stream_closed\",\n retryable: true,\n });\n }\n\n for (const part of translator.finish()) yield part;\n } catch (err) {\n // A timeout/caller abort during the REST phase (createChat / message /\n // tool-results / model resolution) rejects the fetch before the stream loop;\n // reclassify so the documented retryable timeout/abort contract still holds.\n throwIfAborted();\n throw err;\n } finally {\n // Advance the cursor on every exit (success, abort, error) so resuming the\n // same chat doesn't re-read messages already streamed this turn.\n if (translator.maxMessageId > this.#lastSeenMessageId)\n this.#lastSeenMessageId = translator.maxMessageId;\n signal?.removeEventListener(\"abort\", interrupt);\n // Teardown of an unsettled turn — stream cancel(), premature close, or an\n // abort the listener didn't cover — interrupt the server so it stops.\n if (!translator.terminalStatus) interrupt();\n this.#inFlight = false;\n }\n }\n\n async doStream(options: LanguageModelV3CallOptions): Promise<LanguageModelV3StreamResult> {\n // A consumer can tear the stream down via ReadableStream.cancel() without\n // aborting options.abortSignal. Route cancel through an abort so the turn\n // interrupts the server run and the blocked stream reader unblocks — a bare\n // gen.return() would deadlock on a pending socket read and never reach the\n // interrupt, leaking the workspace.\n const cancelController = new AbortController();\n const abortSignal = options.abortSignal\n ? AbortSignal.any([options.abortSignal, cancelController.signal])\n : cancelController.signal;\n const gen = this.#runTurn({ ...options, abortSignal });\n const stream = new ReadableStream<LanguageModelV3StreamPart>({\n async pull(controller) {\n try {\n const { value, done } = await gen.next();\n if (done) controller.close();\n else controller.enqueue(value);\n } catch (err) {\n // A consumer-initiated cancel aborts the turn (to interrupt the server\n // and unblock the reader); that surfaces here as the turn's AbortError,\n // but it's an intentional teardown, so end the stream cleanly rather\n // than erroring it. A caller's own abortSignal still errors as usual.\n if (cancelController.signal.aborted) controller.close();\n else controller.error(err);\n }\n },\n async cancel() {\n cancelController.abort();\n await gen.return().catch(() => {});\n },\n });\n return { stream };\n }\n\n async doGenerate(options: LanguageModelV3CallOptions): Promise<LanguageModelV3GenerateResult> {\n const content: LanguageModelV3Content[] = [];\n const textBuf = new Map<string, string>();\n const reasoningBuf = new Map<string, string>();\n let usage: LanguageModelV3Usage = EMPTY_USAGE;\n let finishReason: LanguageModelV3GenerateResult[\"finishReason\"] = {\n unified: \"stop\",\n raw: undefined,\n };\n const warnings: LanguageModelV3GenerateResult[\"warnings\"] = [];\n\n for await (const part of this.#runTurn(options)) {\n switch (part.type) {\n case \"stream-start\":\n warnings.push(...part.warnings);\n break;\n case \"text-start\":\n textBuf.set(part.id, \"\");\n break;\n case \"text-delta\":\n textBuf.set(part.id, (textBuf.get(part.id) ?? \"\") + part.delta);\n break;\n case \"text-end\": {\n const t = textBuf.get(part.id) ?? \"\";\n if (t.length > 0) content.push({ type: \"text\", text: t });\n textBuf.delete(part.id);\n break;\n }\n case \"reasoning-start\":\n reasoningBuf.set(part.id, \"\");\n break;\n case \"reasoning-delta\":\n reasoningBuf.set(part.id, (reasoningBuf.get(part.id) ?? \"\") + part.delta);\n break;\n case \"reasoning-end\": {\n const t = reasoningBuf.get(part.id) ?? \"\";\n if (t.length > 0) content.push({ type: \"reasoning\", text: t });\n reasoningBuf.delete(part.id);\n break;\n }\n case \"tool-call\":\n case \"tool-result\":\n case \"source\":\n case \"file\":\n content.push(part);\n break;\n case \"finish\":\n usage = part.usage;\n finishReason = part.finishReason;\n break;\n case \"error\":\n throw part.error instanceof Error\n ? part.error\n : new CoderChatError({ message: String(part.error) });\n default:\n break;\n }\n }\n\n return { content, finishReason, usage, warnings };\n }\n}\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@coder/ai-sdk-agent",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "A Vercel AI SDK-compliant agent backed by Coder Agents, Coder's server-side agent runtime. `new CoderAgent()` returns a real AI SDK Agent (generate/stream).",
5
5
  "keywords": [
6
6
  "agent",
@@ -78,6 +78,7 @@
78
78
  "example:generate": "tsx examples/01-generate.ts",
79
79
  "example:stream": "tsx examples/02-stream.ts",
80
80
  "example:tool": "tsx examples/03-custom-tool.ts",
81
- "example:multi-turn": "tsx examples/04-multi-turn.ts"
81
+ "example:multi-turn": "tsx examples/04-multi-turn.ts",
82
+ "example:file": "tsx examples/05-file-upload.ts"
82
83
  }
83
84
  }