tnega 0.3.0 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/llm.js CHANGED
@@ -236,7 +236,9 @@ function anthropicMessagesAdapter(config = {}) {
236
236
  }
237
237
  let sawEvent = false;
238
238
  try {
239
- for await (const event of parseAnthropicStream(response.body)) {
239
+ const contentType = response.headers.get("content-type")?.split(";")[0]?.trim().toLowerCase();
240
+ const events = contentType === "application/json" ? parseJSONCompletionStream(response) : parseAnthropicStream(response.body);
241
+ for await (const event of events) {
240
242
  sawEvent = true;
241
243
  yield event;
242
244
  }
@@ -277,7 +279,7 @@ function buildRequest(messages, tools, config, signal, stream = false) {
277
279
  headers: {
278
280
  "content-type": "application/json",
279
281
  "anthropic-version": ANTHROPIC_VERSION,
280
- ...config.apiKey ? { "x-api-key": config.apiKey } : {}
282
+ ...config.apiKey ? { [config.apiKeyHeader ?? "x-api-key"]: config.apiKey } : {}
281
283
  },
282
284
  body: JSON.stringify(body),
283
285
  ...signal ? { signal } : {}
@@ -569,6 +571,26 @@ async function* parseAnthropicStream(body) {
569
571
  function toIndex(block) {
570
572
  return typeof block.index === "number" ? block.index : 0;
571
573
  }
574
+ async function* parseJSONCompletionStream(response) {
575
+ const payload = await parseJson(response);
576
+ const completion = parseCompletion(payload);
577
+ const record = payload;
578
+ const id = typeof record?.id === "string" && record.id ? record.id : randomUUID();
579
+ const model = typeof record?.model === "string" && record.model ? record.model : void 0;
580
+ yield { type: "message_start", id, ...model ? { model } : {} };
581
+ if (completion.content) yield { type: "message_delta", id, delta: completion.content };
582
+ for (const [index, call] of (completion.toolCalls ?? []).entries()) {
583
+ yield { type: "toolcall_start", id: call.id, index, name: call.name };
584
+ yield {
585
+ type: "toolcall_end",
586
+ id: call.id,
587
+ index,
588
+ name: call.name,
589
+ arguments: call.arguments
590
+ };
591
+ }
592
+ yield { type: "message_stop", id, finishReason: completion.finishReason };
593
+ }
572
594
  function toStreamError(error, timeoutMs) {
573
595
  if (isAbortLike(error)) {
574
596
  return new OpenAICompatibleError(
@@ -657,7 +679,9 @@ function openaiCompatAdapter(config = {}) {
657
679
  }
658
680
  let sawEvent = false;
659
681
  try {
660
- for await (const event of parseOpenAIStream(response.body)) {
682
+ const contentType = response.headers.get("content-type")?.split(";")[0]?.trim().toLowerCase();
683
+ const events = contentType === "application/json" ? parseJSONCompletionStream2(response) : parseOpenAIStream(response.body);
684
+ for await (const event of events) {
661
685
  sawEvent = true;
662
686
  yield event;
663
687
  }
@@ -875,6 +899,26 @@ async function* parseOpenAIStream(body) {
875
899
  }
876
900
  yield* finalizeStreamEvents(messageId, content, calls, finishReason);
877
901
  }
902
+ async function* parseJSONCompletionStream2(response) {
903
+ const payload = await parseJson(response);
904
+ const completion = parseCompletion2(payload);
905
+ const record = payload;
906
+ const id = typeof record?.id === "string" && record.id ? record.id : randomUUID2();
907
+ const model = typeof record?.model === "string" && record.model ? record.model : void 0;
908
+ yield { type: "message_start", id, ...model ? { model } : {} };
909
+ if (completion.content) yield { type: "message_delta", id, delta: completion.content };
910
+ for (const [index, call] of (completion.toolCalls ?? []).entries()) {
911
+ yield { type: "toolcall_start", id: call.id, index, name: call.name };
912
+ yield {
913
+ type: "toolcall_end",
914
+ id: call.id,
915
+ index,
916
+ name: call.name,
917
+ arguments: call.arguments
918
+ };
919
+ }
920
+ yield { type: "message_stop", id, finishReason: completion.finishReason };
921
+ }
878
922
  function processStreamChunk(payload, state, progress, calls) {
879
923
  const record = payload;
880
924
  const events = [];
package/dist/llm.js.map CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../packages/llm/src/anthropic-messages.ts", "../packages/llm/src/errors.ts", "../packages/llm/src/models.ts", "../packages/llm/src/shared.ts", "../packages/llm/src/openai.ts", "../packages/llm/src/provider.ts"],
4
- "sourcesContent": ["import { randomUUID } from 'node:crypto'\nimport type {\n AgentFinishReason,\n LLMAdapter,\n LLMCompletion,\n LLMStreamEvent,\n LLMToolCall,\n} from '@tnega/agent'\nimport type { ModelMessage } from '@tnega/session'\nimport type { ToolDefinition } from '@tnega/tools'\nimport { OpenAICompatibleError } from './errors.js'\nimport { DEFAULT_MODEL } from './models.js'\nimport {\n assertOk,\n combineSignal,\n DEFAULT_LLM_MAX_RETRIES,\n DEFAULT_LLM_RETRY_DELAY_MS,\n DEFAULT_LLM_TIMEOUT_MS,\n errorMessage,\n isAbortLike,\n isExternalAbort,\n isRetryableStatus,\n normalizeBaseUrl,\n parseArguments,\n parseJson,\n sleep,\n} from './shared.js'\nimport type { LlmConfig } from './types.js'\n\nexport type AnthropicMessagesConfig = LlmConfig\n\ninterface AnthropicContentBlock {\n type?: unknown\n id?: unknown\n name?: unknown\n text?: unknown\n input?: unknown\n partial_json?: unknown\n tool_use_id?: unknown\n content?: unknown\n is_error?: unknown\n index?: unknown\n}\n\ninterface AnthropicMessagePayload {\n id?: unknown\n model?: unknown\n content?: unknown\n stop_reason?: unknown\n error?: { message?: unknown }\n type?: unknown\n}\n\ninterface AnthropicToolCallState {\n index: number\n id: string\n name: string\n rawArguments: string\n emitted: boolean\n finalized: boolean\n}\n\ninterface RequestPayload {\n url: string\n init: RequestInit\n}\n\nconst ANTHROPIC_VERSION = '2023-06-01'\n\nexport function anthropicMessagesAdapter(\n config: AnthropicMessagesConfig = {},\n): LLMAdapter {\n return {\n async complete(messages, tools, options) {\n const timeoutMs = config.timeoutMs ?? DEFAULT_LLM_TIMEOUT_MS\n const maxRetries = config.maxRetries ?? DEFAULT_LLM_MAX_RETRIES\n const retryDelayMs = config.retryDelayMs ?? DEFAULT_LLM_RETRY_DELAY_MS\n for (let attempt = 0; attempt <= maxRetries; attempt += 1) {\n const request = buildRequest(\n messages,\n tools,\n config,\n combineSignal(options.signal, timeoutMs),\n )\n try {\n const response = await fetch(request.url, request.init)\n if (!isRetryableStatus(response.status) || attempt >= maxRetries) {\n return parseResponse(response, config.apiKey)\n }\n await response.body?.cancel()\n } catch (error) {\n if (isExternalAbort(error, options.signal)) {\n throw new OpenAICompatibleError(\n 0,\n `LLM request aborted: ${errorMessage(error)}`,\n )\n }\n if (attempt >= maxRetries) {\n throw toRequestError(error, timeoutMs)\n }\n }\n await sleep(retryDelayMs * 2 ** attempt)\n }\n throw new OpenAICompatibleError(0, 'LLM request failed')\n },\n async *stream(messages, tools, options) {\n const timeoutMs = config.timeoutMs ?? DEFAULT_LLM_TIMEOUT_MS\n const maxRetries = config.maxRetries ?? DEFAULT_LLM_MAX_RETRIES\n const retryDelayMs = config.retryDelayMs ?? DEFAULT_LLM_RETRY_DELAY_MS\n for (let attempt = 0; ; attempt += 1) {\n const request = buildRequest(\n messages,\n tools,\n config,\n combineSignal(options.signal, timeoutMs),\n true,\n )\n let response: Response\n try {\n response = await fetch(request.url, request.init)\n } catch (error) {\n if (isExternalAbort(error, options.signal)) {\n throw new OpenAICompatibleError(\n 0,\n `LLM stream aborted: ${errorMessage(error)}`,\n )\n }\n if (attempt >= maxRetries) {\n throw toStreamError(error, timeoutMs)\n }\n await sleep(retryDelayMs * 2 ** attempt)\n continue\n }\n\n if (!response.ok || !response.body) {\n if (isRetryableStatus(response.status) && attempt < maxRetries) {\n await response.body?.cancel()\n await sleep(retryDelayMs * 2 ** attempt)\n continue\n }\n if (!response.ok) await assertOk(response, config.apiKey)\n throw new OpenAICompatibleError(\n response.status,\n 'LLM stream response had no body',\n )\n }\n\n let sawEvent = false\n try {\n for await (const event of parseAnthropicStream(response.body)) {\n sawEvent = true\n yield event\n }\n return\n } catch (error) {\n if (isExternalAbort(error, options.signal)) {\n throw new OpenAICompatibleError(\n 0,\n `LLM stream aborted: ${errorMessage(error)}`,\n )\n }\n if (sawEvent || attempt >= maxRetries) {\n throw toStreamError(error, timeoutMs)\n }\n await sleep(retryDelayMs * 2 ** attempt)\n }\n }\n },\n }\n}\n\nfunction buildRequest(\n messages: readonly ModelMessage[],\n tools: readonly ToolDefinition[],\n config: AnthropicMessagesConfig,\n signal: AbortSignal | undefined,\n stream = false,\n): RequestPayload {\n const body: Record<string, unknown> = {\n model: config.model ?? DEFAULT_MODEL,\n max_tokens: config.maxTokens ?? 4096,\n messages: toAnthropicMessages(messages),\n }\n if (stream) body.stream = true\n const system = systemPrompt(messages)\n if (system) body.system = system\n if (tools.length) {\n body.tools = tools.map(toAnthropicTool)\n }\n if (config.temperature !== undefined) body.temperature = config.temperature\n\n return {\n url: anthropicMessagesUrl(config.baseUrl),\n init: {\n method: 'POST',\n headers: {\n 'content-type': 'application/json',\n 'anthropic-version': ANTHROPIC_VERSION,\n ...(config.apiKey ? { 'x-api-key': config.apiKey } : {}),\n },\n body: JSON.stringify(body),\n ...(signal ? { signal } : {}),\n },\n }\n}\n\nfunction anthropicMessagesUrl(baseUrl: string | undefined): string {\n const normalized = normalizeBaseUrl(baseUrl)\n return normalized.endsWith('/messages') ? normalized : `${normalized}/messages`\n}\n\nfunction systemPrompt(messages: readonly ModelMessage[]): string {\n return messages\n .filter(message => message.role === 'system')\n .map(message => String(message.content ?? ''))\n .join('\\n\\n')\n}\n\nfunction toAnthropicMessages(messages: readonly ModelMessage[]): unknown[] {\n const result: unknown[] = []\n for (const message of messages) {\n if (message.role === 'system') continue\n if (message.role === 'tool') {\n const toolResult: Record<string, unknown> = {\n type: 'tool_result',\n tool_use_id: message.tool_call_id ?? '',\n content: String(message.content ?? ''),\n }\n if (message.toolError) toolResult.is_error = true\n result.push({\n role: 'user',\n content: [toolResult],\n })\n continue\n }\n if (message.role === 'assistant' && message.tool_calls?.length) {\n result.push({\n role: 'assistant',\n content: [\n ...(message.content ? [{ type: 'text', text: message.content }] : []),\n ...message.tool_calls.map(call => ({\n type: 'tool_use',\n id: call.id,\n name: call.name,\n input: typeof call.arguments === 'object' && call.arguments !== null\n ? call.arguments\n : parseArguments(String(call.arguments ?? '')),\n })),\n ],\n })\n continue\n }\n result.push({\n role: message.role,\n content: String(message.content ?? ''),\n })\n }\n return result\n}\n\nfunction toAnthropicTool(tool: ToolDefinition): Record<string, unknown> {\n return {\n name: tool.schema.name,\n ...(tool.schema.description ? { description: tool.schema.description } : {}),\n input_schema: tool.schema.parameters ?? { type: 'object', properties: {} },\n }\n}\n\nasync function parseResponse(\n response: Response,\n apiKey: string | undefined,\n): Promise<LLMCompletion> {\n await assertOk(response, apiKey)\n const payload = await parseJson(response)\n return parseCompletion(payload)\n}\n\nfunction parseCompletion(payload: unknown): LLMCompletion {\n const record = payload as AnthropicMessagePayload | null\n const blocks = Array.isArray(record?.content)\n ? record.content as AnthropicContentBlock[]\n : []\n const text = blocks\n .filter(block => block.type === 'text' && typeof block.text === 'string')\n .map(block => block.text as string)\n .join('')\n const toolCalls = parseToolCalls(blocks)\n const finishReason = toFinishReason(\n record?.stop_reason,\n text,\n toolCalls.length > 0,\n )\n const completion: LLMCompletion = { finishReason }\n if (text) completion.content = text\n if (toolCalls.length) completion.toolCalls = toolCalls\n return completion\n}\n\nfunction parseToolCalls(blocks: AnthropicContentBlock[]): LLMToolCall[] {\n const calls: LLMToolCall[] = []\n for (const block of blocks) {\n if (block.type !== 'tool_use') continue\n const name = typeof block.name === 'string' ? block.name : ''\n if (!name) continue\n const id = typeof block.id === 'string' && block.id\n ? block.id\n : `toolu_${calls.length + 1}`\n calls.push({\n id,\n name,\n arguments: block.input ?? {},\n })\n }\n return calls\n}\n\nfunction toFinishReason(\n raw: unknown,\n content: string,\n hasToolCalls: boolean,\n): AgentFinishReason {\n if (raw === 'end_turn' || raw === 'stop_sequence') return 'stop'\n if (raw === 'max_tokens') return 'length'\n if (raw === 'tool_use' || hasToolCalls) return 'tool_calls'\n if (content) return 'stop'\n return 'error'\n}\n\nfunction toRequestError(error: unknown, timeoutMs: number): OpenAICompatibleError {\n if (isAbortLike(error)) {\n return new OpenAICompatibleError(\n 0,\n `LLM request timed out after ${timeoutMs}ms`,\n )\n }\n return new OpenAICompatibleError(0, `LLM request failed: ${errorMessage(error)}`)\n}\n\nasync function* parseAnthropicStream(\n body: ReadableStream<Uint8Array>,\n): AsyncGenerator<LLMStreamEvent> {\n const reader = body.getReader()\n const decoder = new TextDecoder()\n let buffer = ''\n let messageId: string = randomUUID()\n let model: string | undefined\n let messageStarted = false\n let text = ''\n let stopReason: unknown\n let stopped = false\n let textBlockIndex: number | undefined\n const calls = new Map<number, AnthropicToolCallState>()\n\n try {\n while (true) {\n const { done, value } = await reader.read()\n if (done) break\n buffer += decoder.decode(value, { stream: true })\n let newlineIndex: number\n while ((newlineIndex = buffer.indexOf('\\n')) >= 0) {\n const line = buffer.slice(0, newlineIndex).replace(/\\r$/, '')\n buffer = buffer.slice(newlineIndex + 1)\n if (line.startsWith('data:')) {\n const data = line.slice(5).trim()\n if (!data) continue\n let payload: unknown\n try {\n payload = JSON.parse(data) as unknown\n } catch {\n continue\n }\n const record = payload as AnthropicMessagePayload | null\n if (record?.type === 'error') {\n const message = typeof record.error?.message === 'string'\n ? record.error.message\n : 'LLM stream returned an error event'\n throw new OpenAICompatibleError(0, `LLM stream failed: ${message}`)\n }\n if (record?.type === 'ping') continue\n if (record?.type === 'message_start') {\n const start = record as { message?: AnthropicMessagePayload }\n messageId = typeof start.message?.id === 'string' && start.message.id\n ? start.message.id\n : randomUUID()\n model = typeof start.message?.model === 'string'\n ? start.message.model\n : undefined\n messageStarted = true\n yield {\n type: 'message_start',\n id: messageId,\n ...(model ? { model } : {}),\n }\n continue\n }\n if (record?.type === 'content_block_start') {\n const block = (record as { content_block?: AnthropicContentBlock })\n .content_block\n const index = toIndex(record)\n if (block?.type === 'text') {\n textBlockIndex = index\n if (typeof block.text === 'string' && block.text) {\n text += block.text\n yield { type: 'message_delta', id: messageId, delta: block.text }\n }\n } else if (block?.type === 'tool_use') {\n const call = calls.get(index) ?? {\n index,\n id: typeof block.id === 'string' ? block.id : '',\n name: typeof block.name === 'string' ? block.name : '',\n rawArguments: typeof block.partial_json === 'string'\n ? block.partial_json\n : '',\n emitted: false,\n finalized: false,\n }\n calls.set(index, call)\n if (!call.emitted && call.id && call.name) {\n call.emitted = true\n yield {\n type: 'toolcall_start',\n id: call.id,\n index,\n name: call.name,\n }\n }\n }\n continue\n }\n if (record?.type === 'content_block_delta') {\n const block = (record as { delta?: AnthropicContentBlock }).delta\n const index = toIndex(record)\n if (block?.type === 'text_delta' && typeof block.text === 'string') {\n if (textBlockIndex === undefined) textBlockIndex = index\n if (textBlockIndex === index && block.text) {\n text += block.text\n yield { type: 'message_delta', id: messageId, delta: block.text }\n }\n } else if (block?.type === 'input_json_delta') {\n const call = calls.get(index)\n if (call && typeof block.partial_json === 'string') {\n call.rawArguments += block.partial_json\n }\n }\n continue\n }\n if (record?.type === 'content_block_stop') {\n const block = record as AnthropicContentBlock\n const index = toIndex(block)\n const call = calls.get(index)\n if (call && !call.finalized) {\n call.finalized = true\n if (!call.name) {\n const partial = parseArguments(call.rawArguments)\n if (partial && typeof partial === 'object') {\n const name = (partial as { name?: unknown }).name\n if (typeof name === 'string') call.name = name\n }\n }\n if (!call.emitted && call.id && call.name) {\n call.emitted = true\n yield {\n type: 'toolcall_start',\n id: call.id,\n index,\n name: call.name,\n }\n }\n yield {\n type: 'toolcall_end',\n id: call.id || `toolu_${index + 1}`,\n index,\n name: call.name,\n arguments: parseArguments(call.rawArguments),\n }\n }\n continue\n }\n if (record?.type === 'message_delta') {\n const delta = (record as { delta?: { stop_reason?: unknown } }).delta\n if (delta?.stop_reason !== undefined) {\n stopReason = delta.stop_reason\n }\n continue\n }\n if (record?.type === 'message_stop') {\n if (!messageStarted) {\n messageStarted = true\n yield {\n type: 'message_start',\n id: messageId,\n ...(model ? { model } : {}),\n }\n }\n stopped = true\n yield {\n type: 'message_stop',\n id: messageId,\n finishReason: toFinishReason(stopReason, text, calls.size > 0),\n }\n continue\n }\n }\n }\n }\n } finally {\n if (reader.releaseLock) {\n try {\n reader.releaseLock()\n } catch {\n // stream may already be closed by abort\n }\n }\n }\n\n if (!messageStarted) {\n yield {\n type: 'message_start',\n id: messageId,\n ...(model ? { model } : {}),\n }\n }\n if (!stopped) {\n yield {\n type: 'message_stop',\n id: messageId,\n finishReason: toFinishReason(stopReason, text, calls.size > 0),\n }\n }\n}\n\nfunction toIndex(block: AnthropicContentBlock): number {\n return typeof block.index === 'number' ? block.index : 0\n}\n\nfunction toStreamError(error: unknown, timeoutMs: number): OpenAICompatibleError {\n if (isAbortLike(error)) {\n return new OpenAICompatibleError(\n 0,\n `LLM stream timed out after ${timeoutMs}ms`,\n )\n }\n return new OpenAICompatibleError(0, `LLM stream failed: ${errorMessage(error)}`)\n}\n", "export class OpenAICompatibleError extends Error {\n override name = 'OpenAICompatibleError'\n\n constructor(\n readonly status: number,\n message: string,\n readonly detail?: string,\n ) {\n super(message)\n }\n}\n", "export type LlmProtocol = 'openai' | 'anthropic'\n\nexport interface ModelPricing {\n /** USD per 1M input tokens */\n input: number\n /** USD per 1M output tokens */\n output: number\n /** USD per 1M cached input tokens, when the provider publishes a rate */\n cachedRead?: number\n}\n\nexport interface ModelPricingMeta {\n /** USD per 1M tokens for peak / off-peak tiers */\n rates: ModelPricing | {\n offPeak: ModelPricing\n peak: ModelPricing\n }\n /** USD usage allowance included in the OpenCode Go subscription */\n monthlyUsage: number\n}\n\nexport interface ModelDefinition {\n id: string\n provider: 'opencode-go'\n protocol: LlmProtocol\n contextWindow: number\n pricing: ModelPricingMeta\n}\n\nexport const DEFAULT_MODEL = 'deepseek-v4-flash'\nexport const DEFAULT_DEEPSEEK_MODEL = 'deepseek-v4-flash'\n\nexport const MODEL_CATALOG: readonly ModelDefinition[] = [\n {\n id: 'minimax-m3',\n provider: 'opencode-go',\n protocol: 'anthropic',\n contextWindow: 1_000_000,\n pricing: {\n rates: {\n input: 0.3,\n output: 1.2,\n cachedRead: 0.06,\n },\n monthlyUsage: 60,\n },\n },\n {\n id: 'deepseek-v4-flash',\n provider: 'opencode-go',\n protocol: 'openai',\n contextWindow: 1_000_000,\n pricing: {\n rates: {\n offPeak: {\n input: 0.22,\n output: 0.66,\n cachedRead: 0.007,\n },\n peak: {\n input: 0.44,\n output: 1.32,\n cachedRead: 0.014,\n },\n },\n monthlyUsage: 30,\n },\n },\n {\n id: 'deepseek-v4-pro',\n provider: 'opencode-go',\n protocol: 'openai',\n contextWindow: 1_000_000,\n pricing: {\n rates: {\n offPeak: {\n input: 0.66,\n output: 1.98,\n cachedRead: 0.022,\n },\n peak: {\n input: 1.32,\n output: 3.96,\n cachedRead: 0.044,\n },\n },\n monthlyUsage: 15,\n },\n },\n]\n\nexport function lookupModel(id: string | undefined): ModelDefinition | undefined {\n if (!id) return undefined\n const normalized = id.trim().toLowerCase()\n return MODEL_CATALOG.find(model => model.id === normalized)\n}\n", "import { OpenAICompatibleError } from './errors.js'\n\nexport const DEFAULT_OPENCODE_GO_BASE_URL = 'https://opencode.ai/zen/go/v1'\nexport const DEFAULT_LLM_TIMEOUT_MS = 120_000\nexport const DEFAULT_LLM_MAX_RETRIES = 2\nexport const DEFAULT_LLM_RETRY_DELAY_MS = 500\n\nexport function combineSignal(\n signal: AbortSignal | undefined,\n timeoutMs: number,\n): AbortSignal {\n const timeoutSignal = AbortSignal.timeout(timeoutMs)\n return signal ? AbortSignal.any([signal, timeoutSignal]) : timeoutSignal\n}\n\nexport function isRetryableStatus(status: number): boolean {\n return status === 408 || status === 425 || status === 429 || status >= 500\n}\n\nexport function isExternalAbort(\n error: unknown,\n signal: AbortSignal | undefined,\n): boolean {\n return Boolean(signal?.aborted && isAbortLike(error))\n}\n\nexport function isAbortLike(error: unknown): boolean {\n if (!error || typeof error !== 'object') return false\n const name = (error as { name?: unknown }).name\n return name === 'AbortError' || name === 'TimeoutError'\n}\n\nexport function errorMessage(error: unknown): string {\n if (error instanceof Error) return error.message\n return String(error)\n}\n\nexport function sleep(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms))\n}\n\nexport function normalizeBaseUrl(baseUrl: string | undefined): string {\n return (baseUrl ?? DEFAULT_OPENCODE_GO_BASE_URL).replace(/\\/+$/, '')\n}\n\nexport function stringifyArguments(value: unknown): string {\n if (typeof value === 'string') return value\n try {\n return JSON.stringify(value) ?? '{}'\n } catch {\n return '{}'\n }\n}\n\nexport function parseArguments(raw: string): unknown {\n const text = raw.trim()\n if (!text) return {}\n try {\n return JSON.parse(text) as unknown\n } catch {\n return raw\n }\n}\n\nexport async function assertOk(\n response: Response,\n redact?: string,\n): Promise<void> {\n if (response.ok) return\n let detail: string | undefined\n try {\n const text = await response.text()\n if (text.trim()) {\n const preview = text.slice(0, 2000)\n detail = redact && preview.includes(redact)\n ? preview.replaceAll(redact, '[redacted]')\n : preview\n }\n } catch {\n detail = undefined\n }\n throw new OpenAICompatibleError(\n response.status,\n `LLM request failed with status ${response.status}`,\n detail,\n )\n}\n\nexport async function parseJson(response: Response): Promise<unknown> {\n try {\n return await response.json()\n } catch {\n throw new OpenAICompatibleError(\n response.status,\n 'LLM response was not valid JSON',\n )\n }\n}\n", "import { randomUUID } from 'node:crypto'\nimport type {\n AgentFinishReason,\n LLMAdapter,\n LLMCompletion,\n LLMStreamEvent,\n LLMToolCall,\n} from '@tnega/agent'\nimport type { ModelMessage } from '@tnega/session'\nimport type { ToolDefinition } from '@tnega/tools'\nimport { OpenAICompatibleError } from './errors.js'\nimport { DEFAULT_DEEPSEEK_MODEL } from './models.js'\nimport {\n assertOk,\n combineSignal,\n DEFAULT_LLM_MAX_RETRIES,\n DEFAULT_LLM_RETRY_DELAY_MS,\n DEFAULT_LLM_TIMEOUT_MS,\n errorMessage,\n isAbortLike,\n isExternalAbort,\n isRetryableStatus,\n normalizeBaseUrl,\n parseArguments,\n parseJson,\n sleep,\n stringifyArguments,\n} from './shared.js'\nimport type { OpenAICompatibleConfig } from './types.js'\n\ninterface OpenAICompatibleToolCall {\n id?: unknown\n type?: unknown\n function?: {\n name?: unknown\n arguments?: unknown\n }\n}\n\ninterface OpenAICompatibleChoice {\n message?: {\n content?: string | null\n tool_calls?: unknown\n }\n finish_reason?: string | null\n}\n\ninterface OpenAICompatiblePayload {\n choices?: unknown\n data?: unknown\n}\n\ninterface OpenAIStreamChoice {\n delta?: {\n content?: string | null\n tool_calls?: unknown\n }\n finish_reason?: string | null\n}\n\ninterface OpenAIStreamToolCall {\n index?: unknown\n id?: unknown\n function?: {\n name?: unknown\n arguments?: unknown\n }\n}\n\ninterface RequestPayload {\n url: string\n init: RequestInit\n}\n\nexport function openaiCompatAdapter(config: OpenAICompatibleConfig = {}): LLMAdapter {\n return {\n async complete(messages, tools, options) {\n const timeoutMs = config.timeoutMs ?? DEFAULT_LLM_TIMEOUT_MS\n const maxRetries = config.maxRetries ?? DEFAULT_LLM_MAX_RETRIES\n const retryDelayMs = config.retryDelayMs ?? DEFAULT_LLM_RETRY_DELAY_MS\n for (let attempt = 0; attempt <= maxRetries; attempt += 1) {\n const request = buildRequest(\n messages,\n tools,\n config,\n combineSignal(options.signal, timeoutMs),\n )\n try {\n const response = await fetch(request.url, request.init)\n if (!isRetryableStatus(response.status) || attempt >= maxRetries) {\n return parseResponse(response, config.apiKey)\n }\n await response.body?.cancel()\n } catch (error) {\n if (isExternalAbort(error, options.signal)) {\n throw new OpenAICompatibleError(\n 0,\n `LLM request aborted: ${errorMessage(error)}`,\n )\n }\n if (attempt >= maxRetries) {\n throw toRequestError(error, timeoutMs)\n }\n }\n await sleep(retryDelayMs * 2 ** attempt)\n }\n throw new OpenAICompatibleError(0, 'LLM request failed')\n },\n async *stream(messages, tools, options) {\n const timeoutMs = config.timeoutMs ?? DEFAULT_LLM_TIMEOUT_MS\n const maxRetries = config.maxRetries ?? DEFAULT_LLM_MAX_RETRIES\n const retryDelayMs = config.retryDelayMs ?? DEFAULT_LLM_RETRY_DELAY_MS\n for (let attempt = 0; ; attempt += 1) {\n const request = buildRequest(\n messages,\n tools,\n config,\n combineSignal(options.signal, timeoutMs),\n true,\n )\n let response: Response\n try {\n response = await fetch(request.url, request.init)\n } catch (error) {\n if (isExternalAbort(error, options.signal)) {\n throw new OpenAICompatibleError(\n 0,\n `LLM stream aborted: ${errorMessage(error)}`,\n )\n }\n if (attempt >= maxRetries) {\n throw toStreamError(error, timeoutMs)\n }\n await sleep(retryDelayMs * 2 ** attempt)\n continue\n }\n\n if (!response.ok || !response.body) {\n if (isRetryableStatus(response.status) && attempt < maxRetries) {\n await response.body?.cancel()\n await sleep(retryDelayMs * 2 ** attempt)\n continue\n }\n if (!response.ok) await assertOk(response, config.apiKey)\n throw new OpenAICompatibleError(\n response.status,\n 'LLM stream response had no body',\n )\n }\n\n let sawEvent = false\n try {\n for await (const event of parseOpenAIStream(response.body)) {\n sawEvent = true\n yield event\n }\n return\n } catch (error) {\n if (isExternalAbort(error, options.signal)) {\n throw new OpenAICompatibleError(\n 0,\n `LLM stream aborted: ${errorMessage(error)}`,\n )\n }\n if (sawEvent || attempt >= maxRetries) {\n throw toStreamError(error, timeoutMs)\n }\n await sleep(retryDelayMs * 2 ** attempt)\n }\n }\n },\n }\n}\n\nexport async function listModels(config: OpenAICompatibleConfig = {}): Promise<string[]> {\n const baseUrl = normalizeBaseUrl(config.baseUrl)\n const headers = authHeaders(config.apiKey)\n let response: Response\n try {\n response = await fetch(`${baseUrl}/models`, { headers })\n } catch (error) {\n throw new OpenAICompatibleError(\n 0,\n `model list request failed: ${errorMessage(error)}`,\n )\n }\n await assertOk(response)\n const payload = await parseJson(response)\n const data = (payload as OpenAICompatiblePayload | null)?.data\n if (!Array.isArray(data)) {\n throw new OpenAICompatibleError(\n response.status,\n 'model list response did not contain an array in data',\n )\n }\n return data\n .map((entry) => {\n const record = entry as { id?: unknown } | null\n return typeof record?.id === 'string' ? record.id : ''\n })\n .filter(Boolean)\n}\n\nfunction buildRequest(\n messages: readonly ModelMessage[],\n tools: readonly ToolDefinition[],\n config: OpenAICompatibleConfig,\n signal: AbortSignal | undefined,\n stream = false,\n): RequestPayload {\n const body: Record<string, unknown> = {\n model: config.model ?? DEFAULT_DEEPSEEK_MODEL,\n messages: messages.map(toOpenAIMessage),\n }\n if (stream) body.stream = true\n if (tools.length) {\n body.tools = tools.map(toOpenAITool)\n }\n if (config.temperature !== undefined) body.temperature = config.temperature\n if (config.maxTokens !== undefined) body.max_tokens = config.maxTokens\n\n return {\n url: `${normalizeBaseUrl(config.baseUrl)}/chat/completions`,\n init: {\n method: 'POST',\n headers: {\n 'content-type': 'application/json',\n ...authHeaders(config.apiKey),\n },\n body: JSON.stringify(body),\n ...(signal ? { signal } : {}),\n },\n }\n}\n\nfunction authHeaders(apiKey: string | undefined): Record<string, string> {\n return apiKey ? { authorization: `Bearer ${apiKey}` } : {}\n}\n\nfunction toOpenAIMessage(message: ModelMessage): Record<string, unknown> {\n const payload: Record<string, unknown> = {\n role: message.role,\n content: message.content,\n }\n if (message.role === 'tool' && message.name) payload.name = message.name\n if (message.tool_call_id) payload.tool_call_id = message.tool_call_id\n if (message.tool_calls?.length) {\n payload.tool_calls = message.tool_calls.map(call => ({\n id: call.id,\n type: 'function',\n function: {\n name: call.name,\n arguments: stringifyArguments(call.arguments),\n },\n }))\n }\n return payload\n}\n\nfunction toOpenAITool(tool: ToolDefinition): Record<string, unknown> {\n return {\n type: 'function',\n function: {\n name: tool.schema.name,\n description: tool.schema.description,\n parameters: tool.schema.parameters ?? { type: 'object', properties: {} },\n },\n }\n}\n\nasync function parseResponse(\n response: Response,\n apiKey: string | undefined,\n): Promise<LLMCompletion> {\n await assertOk(response, apiKey)\n const payload = await parseJson(response)\n return parseCompletion(payload)\n}\n\nfunction parseCompletion(payload: unknown): LLMCompletion {\n const record = payload as OpenAICompatiblePayload | null\n const choices = Array.isArray(record?.choices)\n ? record.choices as OpenAICompatibleChoice[]\n : []\n const choice = choices[0]\n const rawContent = choice?.message?.content\n const content = typeof rawContent === 'string' ? rawContent : undefined\n const toolCalls = parseToolCalls(choice?.message?.tool_calls)\n const finishReason = toFinishReason(\n choice?.finish_reason,\n content,\n toolCalls !== undefined,\n )\n const completion: LLMCompletion = {\n finishReason,\n }\n if (content !== undefined) completion.content = content\n if (toolCalls !== undefined) completion.toolCalls = toolCalls\n return completion\n}\n\nfunction parseToolCalls(value: unknown): LLMToolCall[] | undefined {\n if (!Array.isArray(value)) return undefined\n const calls: LLMToolCall[] = []\n for (const entry of value) {\n if (!entry || typeof entry !== 'object') continue\n const item = entry as OpenAICompatibleToolCall\n const name = typeof item.function?.name === 'string' ? item.function.name : ''\n if (!name) continue\n const id = typeof item.id === 'string' && item.id\n ? item.id\n : `call_${calls.length + 1}`\n const rawArguments = typeof item.function?.arguments === 'string'\n ? item.function.arguments\n : ''\n calls.push({\n id,\n name,\n arguments: parseArguments(rawArguments),\n })\n }\n return calls.length ? calls : undefined\n}\n\nfunction toFinishReason(\n raw: string | null | undefined,\n content: string | undefined,\n hasToolCalls: boolean,\n): AgentFinishReason {\n if (raw === 'stop' || (raw === undefined && content !== undefined && !hasToolCalls)) {\n return 'stop'\n }\n if (raw === 'length') return 'length'\n if (raw === 'tool_calls' || hasToolCalls) return 'tool_calls'\n return 'error'\n}\n\nfunction toRequestError(error: unknown, timeoutMs: number): OpenAICompatibleError {\n if (isAbortLike(error)) {\n return new OpenAICompatibleError(\n 0,\n `LLM request timed out after ${timeoutMs}ms`,\n )\n }\n return new OpenAICompatibleError(0, `LLM request failed: ${errorMessage(error)}`)\n}\n\nasync function* parseOpenAIStream(\n body: ReadableStream<Uint8Array>,\n): AsyncGenerator<LLMStreamEvent> {\n const reader = body.getReader()\n const decoder = new TextDecoder()\n let buffer = ''\n let content = ''\n let messageId: string = randomUUID()\n let model: string | undefined\n let messageStarted = false\n let finishReason: string | null | undefined\n const calls = new Map<number, {\n index: number\n id: string\n name: string\n arguments: string\n emitted: boolean\n }>()\n\n try {\n while (true) {\n const { done, value } = await reader.read()\n if (done) break\n buffer += decoder.decode(value, { stream: true })\n let newlineIndex: number\n while ((newlineIndex = buffer.indexOf('\\n')) >= 0) {\n const line = buffer.slice(0, newlineIndex).replace(/\\r$/, '')\n buffer = buffer.slice(newlineIndex + 1)\n if (!line.startsWith('data:')) continue\n const data = line.slice(5).trim()\n if (!data) continue\n if (data === '[DONE]') {\n yield* finalizeStreamEvents(messageId, content, calls, finishReason)\n return\n }\n let payload: unknown\n try {\n payload = JSON.parse(data) as unknown\n } catch {\n continue\n }\n const events = processStreamChunk(\n payload,\n { messageId, model, messageStarted },\n { content, finishReason },\n calls,\n )\n messageId = events.messageId\n model = events.model\n messageStarted = true\n content = events.content\n finishReason = events.finishReason\n for (const event of events.events) yield event\n }\n }\n } finally {\n if (reader.releaseLock) {\n try {\n reader.releaseLock()\n } catch {\n // stream may already be closed by abort\n }\n }\n }\n\n yield* finalizeStreamEvents(messageId, content, calls, finishReason)\n}\n\ninterface StreamChunkState {\n messageId: string\n model: string | undefined\n messageStarted: boolean\n content: string\n finishReason: string | null | undefined\n}\n\nfunction processStreamChunk(\n payload: unknown,\n state: Pick<StreamChunkState, 'messageId' | 'model' | 'messageStarted'>,\n progress: Pick<StreamChunkState, 'content' | 'finishReason'>,\n calls: Map<number, {\n index: number\n id: string\n name: string\n arguments: string\n emitted: boolean\n }>,\n): StreamChunkState & { events: LLMStreamEvent[] } {\n const record = payload as {\n id?: unknown\n model?: unknown\n choices?: unknown\n } | null\n const events: LLMStreamEvent[] = []\n let messageId = state.messageId\n let model = state.model\n let messageStarted = state.messageStarted\n let content = progress.content\n let finishReason = progress.finishReason\n\n if (typeof record?.id === 'string' && record.id) messageId = record.id\n if (typeof record?.model === 'string' && record.model) model = record.model\n if (!messageStarted) {\n messageStarted = true\n const start = {\n type: 'message_start' as const,\n id: messageId,\n ...(model ? { model } : {}),\n }\n events.push(start)\n }\n\n const choices = Array.isArray(record?.choices)\n ? record.choices as OpenAIStreamChoice[]\n : []\n const choice = choices[0]\n if (choice?.finish_reason !== undefined && choice.finish_reason !== null) {\n finishReason = choice.finish_reason\n }\n const delta = choice?.delta\n if (typeof delta?.content === 'string' && delta.content) {\n content += delta.content\n events.push({ type: 'message_delta', id: messageId, delta: delta.content })\n }\n if (Array.isArray(delta?.tool_calls)) {\n for (const entry of delta.tool_calls as OpenAIStreamToolCall[]) {\n const index = typeof entry.index === 'number' ? entry.index : 0\n let call = calls.get(index)\n if (!call) {\n call = { index, id: '', name: '', arguments: '', emitted: false }\n calls.set(index, call)\n }\n if (typeof entry.id === 'string' && entry.id) call.id = entry.id\n if (typeof entry.function?.name === 'string' && entry.function.name) {\n call.name = entry.function.name\n }\n if (typeof entry.function?.arguments === 'string') {\n call.arguments += entry.function.arguments\n }\n if (!call.emitted && call.id && call.name) {\n call.emitted = true\n events.push({\n type: 'toolcall_start',\n id: call.id,\n index,\n name: call.name,\n })\n }\n }\n }\n\n return {\n messageId,\n model,\n messageStarted,\n content,\n finishReason,\n events,\n }\n}\n\nfunction finalizeStreamEvents(\n messageId: string,\n content: string,\n calls: Map<number, {\n index: number\n id: string\n name: string\n arguments: string\n emitted: boolean\n }>,\n finishReason: string | null | undefined,\n): LLMStreamEvent[] {\n const events: LLMStreamEvent[] = []\n const toolCalls: LLMToolCall[] = []\n for (const call of calls.values()) {\n if (!call.emitted) continue\n events.push({\n type: 'toolcall_end',\n id: call.id,\n index: call.index,\n name: call.name,\n arguments: parseArguments(call.arguments),\n })\n toolCalls.push({\n id: call.id,\n name: call.name,\n arguments: parseArguments(call.arguments),\n })\n }\n events.push({\n type: 'message_stop',\n id: messageId,\n finishReason: toFinishReason(finishReason, content, toolCalls.length > 0),\n })\n return events\n}\n\nfunction toStreamError(error: unknown, timeoutMs: number): OpenAICompatibleError {\n if (isAbortLike(error)) {\n return new OpenAICompatibleError(\n 0,\n `LLM stream timed out after ${timeoutMs}ms`,\n )\n }\n return new OpenAICompatibleError(0, `LLM stream failed: ${errorMessage(error)}`)\n}\n", "import { anthropicMessagesAdapter } from './anthropic-messages.js'\r\nimport { lookupModel } from './models.js'\r\nimport { openaiCompatAdapter } from './openai.js'\r\nimport type { LlmConfig } from './types.js'\r\n\r\nexport function createLlmAdapter(config: LlmConfig): ReturnType<typeof openaiCompatAdapter> {\r\n if (config.protocol === 'anthropic') {\r\n return anthropicMessagesAdapter(config)\r\n }\r\n if (config.protocol === 'openai') {\r\n return openaiCompatAdapter(config)\r\n }\r\n if (lookupModel(config.model)?.protocol === 'anthropic') {\r\n return anthropicMessagesAdapter(config)\r\n }\r\n return openaiCompatAdapter(config)\r\n}\r\n"],
5
- "mappings": "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",
6
- "names": ["randomUUID", "buildRequest", "parseResponse", "toRequestError", "toStreamError", "parseCompletion", "parseToolCalls", "toFinishReason", "randomUUID"]
4
+ "sourcesContent": ["import { randomUUID } from 'node:crypto'\r\nimport type {\r\n AgentFinishReason,\r\n LLMAdapter,\r\n LLMCompletion,\r\n LLMStreamEvent,\r\n LLMToolCall,\r\n} from '@tnega/agent'\r\nimport type { ModelMessage } from '@tnega/session'\r\nimport type { ToolDefinition } from '@tnega/tools'\r\nimport { OpenAICompatibleError } from './errors.js'\r\nimport { DEFAULT_MODEL } from './models.js'\r\nimport {\r\n assertOk,\r\n combineSignal,\r\n DEFAULT_LLM_MAX_RETRIES,\r\n DEFAULT_LLM_RETRY_DELAY_MS,\r\n DEFAULT_LLM_TIMEOUT_MS,\r\n errorMessage,\r\n isAbortLike,\r\n isExternalAbort,\r\n isRetryableStatus,\r\n normalizeBaseUrl,\r\n parseArguments,\r\n parseJson,\r\n sleep,\r\n} from './shared.js'\r\nimport type { LlmConfig } from './types.js'\r\n\r\nexport type AnthropicMessagesConfig = LlmConfig\r\n\r\ninterface AnthropicContentBlock {\r\n type?: unknown\r\n id?: unknown\r\n name?: unknown\r\n text?: unknown\r\n input?: unknown\r\n partial_json?: unknown\r\n tool_use_id?: unknown\r\n content?: unknown\r\n is_error?: unknown\r\n index?: unknown\r\n}\r\n\r\ninterface AnthropicMessagePayload {\r\n id?: unknown\r\n model?: unknown\r\n content?: unknown\r\n stop_reason?: unknown\r\n error?: { message?: unknown }\r\n type?: unknown\r\n}\r\n\r\ninterface AnthropicToolCallState {\r\n index: number\r\n id: string\r\n name: string\r\n rawArguments: string\r\n emitted: boolean\r\n finalized: boolean\r\n}\r\n\r\ninterface RequestPayload {\r\n url: string\r\n init: RequestInit\r\n}\r\n\r\nconst ANTHROPIC_VERSION = '2023-06-01'\r\n\r\nexport function anthropicMessagesAdapter(\r\n config: AnthropicMessagesConfig = {},\r\n): LLMAdapter {\r\n return {\r\n async complete(messages, tools, options) {\r\n const timeoutMs = config.timeoutMs ?? DEFAULT_LLM_TIMEOUT_MS\r\n const maxRetries = config.maxRetries ?? DEFAULT_LLM_MAX_RETRIES\r\n const retryDelayMs = config.retryDelayMs ?? DEFAULT_LLM_RETRY_DELAY_MS\r\n for (let attempt = 0; attempt <= maxRetries; attempt += 1) {\r\n const request = buildRequest(\r\n messages,\r\n tools,\r\n config,\r\n combineSignal(options.signal, timeoutMs),\r\n )\r\n try {\r\n const response = await fetch(request.url, request.init)\r\n if (!isRetryableStatus(response.status) || attempt >= maxRetries) {\r\n return parseResponse(response, config.apiKey)\r\n }\r\n await response.body?.cancel()\r\n } catch (error) {\r\n if (isExternalAbort(error, options.signal)) {\r\n throw new OpenAICompatibleError(\r\n 0,\r\n `LLM request aborted: ${errorMessage(error)}`,\r\n )\r\n }\r\n if (attempt >= maxRetries) {\r\n throw toRequestError(error, timeoutMs)\r\n }\r\n }\r\n await sleep(retryDelayMs * 2 ** attempt)\r\n }\r\n throw new OpenAICompatibleError(0, 'LLM request failed')\r\n },\r\n async *stream(messages, tools, options) {\r\n const timeoutMs = config.timeoutMs ?? DEFAULT_LLM_TIMEOUT_MS\r\n const maxRetries = config.maxRetries ?? DEFAULT_LLM_MAX_RETRIES\r\n const retryDelayMs = config.retryDelayMs ?? DEFAULT_LLM_RETRY_DELAY_MS\r\n for (let attempt = 0; ; attempt += 1) {\r\n const request = buildRequest(\r\n messages,\r\n tools,\r\n config,\r\n combineSignal(options.signal, timeoutMs),\r\n true,\r\n )\r\n let response: Response\r\n try {\r\n response = await fetch(request.url, request.init)\r\n } catch (error) {\r\n if (isExternalAbort(error, options.signal)) {\r\n throw new OpenAICompatibleError(\r\n 0,\r\n `LLM stream aborted: ${errorMessage(error)}`,\r\n )\r\n }\r\n if (attempt >= maxRetries) {\r\n throw toStreamError(error, timeoutMs)\r\n }\r\n await sleep(retryDelayMs * 2 ** attempt)\r\n continue\r\n }\r\n\r\n if (!response.ok || !response.body) {\r\n if (isRetryableStatus(response.status) && attempt < maxRetries) {\r\n await response.body?.cancel()\r\n await sleep(retryDelayMs * 2 ** attempt)\r\n continue\r\n }\r\n if (!response.ok) await assertOk(response, config.apiKey)\r\n throw new OpenAICompatibleError(\r\n response.status,\r\n 'LLM stream response had no body',\r\n )\r\n }\r\n\r\n let sawEvent = false\r\n try {\r\n const contentType = response.headers.get('content-type')?.split(';')[0]?.trim().toLowerCase()\r\n const events = contentType === 'application/json'\r\n ? parseJSONCompletionStream(response)\r\n : parseAnthropicStream(response.body)\r\n for await (const event of events) {\r\n sawEvent = true\r\n yield event\r\n }\r\n return\r\n } catch (error) {\r\n if (isExternalAbort(error, options.signal)) {\r\n throw new OpenAICompatibleError(\r\n 0,\r\n `LLM stream aborted: ${errorMessage(error)}`,\r\n )\r\n }\r\n if (sawEvent || attempt >= maxRetries) {\r\n throw toStreamError(error, timeoutMs)\r\n }\r\n await sleep(retryDelayMs * 2 ** attempt)\r\n }\r\n }\r\n },\r\n }\r\n}\r\n\r\nfunction buildRequest(\r\n messages: readonly ModelMessage[],\r\n tools: readonly ToolDefinition[],\r\n config: AnthropicMessagesConfig,\r\n signal: AbortSignal | undefined,\r\n stream = false,\r\n): RequestPayload {\r\n const body: Record<string, unknown> = {\r\n model: config.model ?? DEFAULT_MODEL,\r\n max_tokens: config.maxTokens ?? 4096,\r\n messages: toAnthropicMessages(messages),\r\n }\r\n if (stream) body.stream = true\r\n const system = systemPrompt(messages)\r\n if (system) body.system = system\r\n if (tools.length) {\r\n body.tools = tools.map(toAnthropicTool)\r\n }\r\n if (config.temperature !== undefined) body.temperature = config.temperature\r\n\r\n return {\r\n url: anthropicMessagesUrl(config.baseUrl),\r\n init: {\r\n method: 'POST',\r\n headers: {\r\n 'content-type': 'application/json',\r\n 'anthropic-version': ANTHROPIC_VERSION,\r\n ...(config.apiKey ? { [config.apiKeyHeader ?? 'x-api-key']: config.apiKey } : {}),\n },\r\n body: JSON.stringify(body),\r\n ...(signal ? { signal } : {}),\r\n },\r\n }\r\n}\r\n\r\nfunction anthropicMessagesUrl(baseUrl: string | undefined): string {\r\n const normalized = normalizeBaseUrl(baseUrl)\r\n return normalized.endsWith('/messages') ? normalized : `${normalized}/messages`\r\n}\r\n\r\nfunction systemPrompt(messages: readonly ModelMessage[]): string {\r\n return messages\r\n .filter(message => message.role === 'system')\r\n .map(message => String(message.content ?? ''))\r\n .join('\\n\\n')\r\n}\r\n\r\nfunction toAnthropicMessages(messages: readonly ModelMessage[]): unknown[] {\r\n const result: unknown[] = []\r\n for (const message of messages) {\r\n if (message.role === 'system') continue\r\n if (message.role === 'tool') {\r\n const toolResult: Record<string, unknown> = {\r\n type: 'tool_result',\r\n tool_use_id: message.tool_call_id ?? '',\r\n content: String(message.content ?? ''),\r\n }\r\n if (message.toolError) toolResult.is_error = true\r\n result.push({\r\n role: 'user',\r\n content: [toolResult],\r\n })\r\n continue\r\n }\r\n if (message.role === 'assistant' && message.tool_calls?.length) {\r\n result.push({\r\n role: 'assistant',\r\n content: [\r\n ...(message.content ? [{ type: 'text', text: message.content }] : []),\r\n ...message.tool_calls.map(call => ({\r\n type: 'tool_use',\r\n id: call.id,\r\n name: call.name,\r\n input: typeof call.arguments === 'object' && call.arguments !== null\r\n ? call.arguments\r\n : parseArguments(String(call.arguments ?? '')),\r\n })),\r\n ],\r\n })\r\n continue\r\n }\r\n result.push({\r\n role: message.role,\r\n content: String(message.content ?? ''),\r\n })\r\n }\r\n return result\r\n}\r\n\r\nfunction toAnthropicTool(tool: ToolDefinition): Record<string, unknown> {\r\n return {\r\n name: tool.schema.name,\r\n ...(tool.schema.description ? { description: tool.schema.description } : {}),\r\n input_schema: tool.schema.parameters ?? { type: 'object', properties: {} },\r\n }\r\n}\r\n\r\nasync function parseResponse(\r\n response: Response,\r\n apiKey: string | undefined,\r\n): Promise<LLMCompletion> {\r\n await assertOk(response, apiKey)\r\n const payload = await parseJson(response)\r\n return parseCompletion(payload)\r\n}\r\n\r\nfunction parseCompletion(payload: unknown): LLMCompletion {\r\n const record = payload as AnthropicMessagePayload | null\r\n const blocks = Array.isArray(record?.content)\r\n ? record.content as AnthropicContentBlock[]\r\n : []\r\n const text = blocks\r\n .filter(block => block.type === 'text' && typeof block.text === 'string')\r\n .map(block => block.text as string)\r\n .join('')\r\n const toolCalls = parseToolCalls(blocks)\r\n const finishReason = toFinishReason(\r\n record?.stop_reason,\r\n text,\r\n toolCalls.length > 0,\r\n )\r\n const completion: LLMCompletion = { finishReason }\r\n if (text) completion.content = text\r\n if (toolCalls.length) completion.toolCalls = toolCalls\r\n return completion\r\n}\r\n\r\nfunction parseToolCalls(blocks: AnthropicContentBlock[]): LLMToolCall[] {\r\n const calls: LLMToolCall[] = []\r\n for (const block of blocks) {\r\n if (block.type !== 'tool_use') continue\r\n const name = typeof block.name === 'string' ? block.name : ''\r\n if (!name) continue\r\n const id = typeof block.id === 'string' && block.id\r\n ? block.id\r\n : `toolu_${calls.length + 1}`\r\n calls.push({\r\n id,\r\n name,\r\n arguments: block.input ?? {},\r\n })\r\n }\r\n return calls\r\n}\r\n\r\nfunction toFinishReason(\r\n raw: unknown,\r\n content: string,\r\n hasToolCalls: boolean,\r\n): AgentFinishReason {\r\n if (raw === 'end_turn' || raw === 'stop_sequence') return 'stop'\r\n if (raw === 'max_tokens') return 'length'\r\n if (raw === 'tool_use' || hasToolCalls) return 'tool_calls'\r\n if (content) return 'stop'\r\n return 'error'\r\n}\r\n\r\nfunction toRequestError(error: unknown, timeoutMs: number): OpenAICompatibleError {\r\n if (isAbortLike(error)) {\r\n return new OpenAICompatibleError(\r\n 0,\r\n `LLM request timed out after ${timeoutMs}ms`,\r\n )\r\n }\r\n return new OpenAICompatibleError(0, `LLM request failed: ${errorMessage(error)}`)\r\n}\r\n\r\nasync function* parseAnthropicStream(\r\n body: ReadableStream<Uint8Array>,\r\n): AsyncGenerator<LLMStreamEvent> {\r\n const reader = body.getReader()\r\n const decoder = new TextDecoder()\r\n let buffer = ''\r\n let messageId: string = randomUUID()\r\n let model: string | undefined\r\n let messageStarted = false\r\n let text = ''\r\n let stopReason: unknown\r\n let stopped = false\r\n let textBlockIndex: number | undefined\r\n const calls = new Map<number, AnthropicToolCallState>()\r\n\r\n try {\r\n while (true) {\r\n const { done, value } = await reader.read()\r\n if (done) break\r\n buffer += decoder.decode(value, { stream: true })\r\n let newlineIndex: number\r\n while ((newlineIndex = buffer.indexOf('\\n')) >= 0) {\r\n const line = buffer.slice(0, newlineIndex).replace(/\\r$/, '')\r\n buffer = buffer.slice(newlineIndex + 1)\r\n if (line.startsWith('data:')) {\r\n const data = line.slice(5).trim()\r\n if (!data) continue\r\n let payload: unknown\r\n try {\r\n payload = JSON.parse(data) as unknown\r\n } catch {\r\n continue\r\n }\r\n const record = payload as AnthropicMessagePayload | null\r\n if (record?.type === 'error') {\r\n const message = typeof record.error?.message === 'string'\r\n ? record.error.message\r\n : 'LLM stream returned an error event'\r\n throw new OpenAICompatibleError(0, `LLM stream failed: ${message}`)\r\n }\r\n if (record?.type === 'ping') continue\r\n if (record?.type === 'message_start') {\r\n const start = record as { message?: AnthropicMessagePayload }\r\n messageId = typeof start.message?.id === 'string' && start.message.id\r\n ? start.message.id\r\n : randomUUID()\r\n model = typeof start.message?.model === 'string'\r\n ? start.message.model\r\n : undefined\r\n messageStarted = true\r\n yield {\r\n type: 'message_start',\r\n id: messageId,\r\n ...(model ? { model } : {}),\r\n }\r\n continue\r\n }\r\n if (record?.type === 'content_block_start') {\r\n const block = (record as { content_block?: AnthropicContentBlock })\r\n .content_block\r\n const index = toIndex(record)\r\n if (block?.type === 'text') {\r\n textBlockIndex = index\r\n if (typeof block.text === 'string' && block.text) {\r\n text += block.text\r\n yield { type: 'message_delta', id: messageId, delta: block.text }\r\n }\r\n } else if (block?.type === 'tool_use') {\r\n const call = calls.get(index) ?? {\r\n index,\r\n id: typeof block.id === 'string' ? block.id : '',\r\n name: typeof block.name === 'string' ? block.name : '',\r\n rawArguments: typeof block.partial_json === 'string'\r\n ? block.partial_json\r\n : '',\r\n emitted: false,\r\n finalized: false,\r\n }\r\n calls.set(index, call)\r\n if (!call.emitted && call.id && call.name) {\r\n call.emitted = true\r\n yield {\r\n type: 'toolcall_start',\r\n id: call.id,\r\n index,\r\n name: call.name,\r\n }\r\n }\r\n }\r\n continue\r\n }\r\n if (record?.type === 'content_block_delta') {\r\n const block = (record as { delta?: AnthropicContentBlock }).delta\r\n const index = toIndex(record)\r\n if (block?.type === 'text_delta' && typeof block.text === 'string') {\r\n if (textBlockIndex === undefined) textBlockIndex = index\r\n if (textBlockIndex === index && block.text) {\r\n text += block.text\r\n yield { type: 'message_delta', id: messageId, delta: block.text }\r\n }\r\n } else if (block?.type === 'input_json_delta') {\r\n const call = calls.get(index)\r\n if (call && typeof block.partial_json === 'string') {\r\n call.rawArguments += block.partial_json\r\n }\r\n }\r\n continue\r\n }\r\n if (record?.type === 'content_block_stop') {\r\n const block = record as AnthropicContentBlock\r\n const index = toIndex(block)\r\n const call = calls.get(index)\r\n if (call && !call.finalized) {\r\n call.finalized = true\r\n if (!call.name) {\r\n const partial = parseArguments(call.rawArguments)\r\n if (partial && typeof partial === 'object') {\r\n const name = (partial as { name?: unknown }).name\r\n if (typeof name === 'string') call.name = name\r\n }\r\n }\r\n if (!call.emitted && call.id && call.name) {\r\n call.emitted = true\r\n yield {\r\n type: 'toolcall_start',\r\n id: call.id,\r\n index,\r\n name: call.name,\r\n }\r\n }\r\n yield {\r\n type: 'toolcall_end',\r\n id: call.id || `toolu_${index + 1}`,\r\n index,\r\n name: call.name,\r\n arguments: parseArguments(call.rawArguments),\r\n }\r\n }\r\n continue\r\n }\r\n if (record?.type === 'message_delta') {\r\n const delta = (record as { delta?: { stop_reason?: unknown } }).delta\r\n if (delta?.stop_reason !== undefined) {\r\n stopReason = delta.stop_reason\r\n }\r\n continue\r\n }\r\n if (record?.type === 'message_stop') {\r\n if (!messageStarted) {\r\n messageStarted = true\r\n yield {\r\n type: 'message_start',\r\n id: messageId,\r\n ...(model ? { model } : {}),\r\n }\r\n }\r\n stopped = true\r\n yield {\r\n type: 'message_stop',\r\n id: messageId,\r\n finishReason: toFinishReason(stopReason, text, calls.size > 0),\r\n }\r\n continue\r\n }\r\n }\r\n }\r\n }\r\n } finally {\r\n if (reader.releaseLock) {\r\n try {\r\n reader.releaseLock()\r\n } catch {\r\n // stream may already be closed by abort\r\n }\r\n }\r\n }\r\n\r\n if (!messageStarted) {\r\n yield {\r\n type: 'message_start',\r\n id: messageId,\r\n ...(model ? { model } : {}),\r\n }\r\n }\r\n if (!stopped) {\r\n yield {\r\n type: 'message_stop',\r\n id: messageId,\r\n finishReason: toFinishReason(stopReason, text, calls.size > 0),\r\n }\r\n }\r\n}\r\n\r\nfunction toIndex(block: AnthropicContentBlock): number {\r\n return typeof block.index === 'number' ? block.index : 0\r\n}\r\n\r\nasync function* parseJSONCompletionStream(response: Response): AsyncGenerator<LLMStreamEvent> {\r\n const payload = await parseJson(response)\r\n const completion = parseCompletion(payload)\r\n const record = payload as AnthropicMessagePayload | null\r\n const id = typeof record?.id === 'string' && record.id ? record.id : randomUUID()\r\n const model = typeof record?.model === 'string' && record.model ? record.model : undefined\r\n yield { type: 'message_start', id, ...(model ? { model } : {}) }\r\n if (completion.content) yield { type: 'message_delta', id, delta: completion.content }\r\n for (const [index, call] of (completion.toolCalls ?? []).entries()) {\r\n yield { type: 'toolcall_start', id: call.id, index, name: call.name }\r\n yield {\r\n type: 'toolcall_end',\r\n id: call.id,\r\n index,\r\n name: call.name,\r\n arguments: call.arguments,\r\n }\r\n }\r\n yield { type: 'message_stop', id, finishReason: completion.finishReason }\r\n}\r\n\r\nfunction toStreamError(error: unknown, timeoutMs: number): OpenAICompatibleError {\r\n if (isAbortLike(error)) {\r\n return new OpenAICompatibleError(\r\n 0,\r\n `LLM stream timed out after ${timeoutMs}ms`,\r\n )\r\n }\r\n return new OpenAICompatibleError(0, `LLM stream failed: ${errorMessage(error)}`)\r\n}\r\n", "export class OpenAICompatibleError extends Error {\n override name = 'OpenAICompatibleError'\n\n constructor(\n readonly status: number,\n message: string,\n readonly detail?: string,\n ) {\n super(message)\n }\n}\n", "export type LlmProtocol = 'openai' | 'anthropic'\n\nexport interface ModelPricing {\n /** USD per 1M input tokens */\n input: number\n /** USD per 1M output tokens */\n output: number\n /** USD per 1M cached input tokens, when the provider publishes a rate */\n cachedRead?: number\n}\n\nexport interface ModelPricingMeta {\n /** USD per 1M tokens for peak / off-peak tiers */\n rates: ModelPricing | {\n offPeak: ModelPricing\n peak: ModelPricing\n }\n /** USD usage allowance included in the OpenCode Go subscription */\n monthlyUsage: number\n}\n\nexport interface ModelDefinition {\n id: string\n provider: 'opencode-go'\n protocol: LlmProtocol\n contextWindow: number\n pricing: ModelPricingMeta\n}\n\nexport const DEFAULT_MODEL = 'deepseek-v4-flash'\nexport const DEFAULT_DEEPSEEK_MODEL = 'deepseek-v4-flash'\n\nexport const MODEL_CATALOG: readonly ModelDefinition[] = [\n {\n id: 'minimax-m3',\n provider: 'opencode-go',\n protocol: 'anthropic',\n contextWindow: 1_000_000,\n pricing: {\n rates: {\n input: 0.3,\n output: 1.2,\n cachedRead: 0.06,\n },\n monthlyUsage: 60,\n },\n },\n {\n id: 'deepseek-v4-flash',\n provider: 'opencode-go',\n protocol: 'openai',\n contextWindow: 1_000_000,\n pricing: {\n rates: {\n offPeak: {\n input: 0.22,\n output: 0.66,\n cachedRead: 0.007,\n },\n peak: {\n input: 0.44,\n output: 1.32,\n cachedRead: 0.014,\n },\n },\n monthlyUsage: 30,\n },\n },\n {\n id: 'deepseek-v4-pro',\n provider: 'opencode-go',\n protocol: 'openai',\n contextWindow: 1_000_000,\n pricing: {\n rates: {\n offPeak: {\n input: 0.66,\n output: 1.98,\n cachedRead: 0.022,\n },\n peak: {\n input: 1.32,\n output: 3.96,\n cachedRead: 0.044,\n },\n },\n monthlyUsage: 15,\n },\n },\n]\n\nexport function lookupModel(id: string | undefined): ModelDefinition | undefined {\n if (!id) return undefined\n const normalized = id.trim().toLowerCase()\n return MODEL_CATALOG.find(model => model.id === normalized)\n}\n", "import { OpenAICompatibleError } from './errors.js'\n\nexport const DEFAULT_OPENCODE_GO_BASE_URL = 'https://opencode.ai/zen/go/v1'\nexport const DEFAULT_LLM_TIMEOUT_MS = 120_000\nexport const DEFAULT_LLM_MAX_RETRIES = 2\nexport const DEFAULT_LLM_RETRY_DELAY_MS = 500\n\nexport function combineSignal(\n signal: AbortSignal | undefined,\n timeoutMs: number,\n): AbortSignal {\n const timeoutSignal = AbortSignal.timeout(timeoutMs)\n return signal ? AbortSignal.any([signal, timeoutSignal]) : timeoutSignal\n}\n\nexport function isRetryableStatus(status: number): boolean {\n return status === 408 || status === 425 || status === 429 || status >= 500\n}\n\nexport function isExternalAbort(\n error: unknown,\n signal: AbortSignal | undefined,\n): boolean {\n return Boolean(signal?.aborted && isAbortLike(error))\n}\n\nexport function isAbortLike(error: unknown): boolean {\n if (!error || typeof error !== 'object') return false\n const name = (error as { name?: unknown }).name\n return name === 'AbortError' || name === 'TimeoutError'\n}\n\nexport function errorMessage(error: unknown): string {\n if (error instanceof Error) return error.message\n return String(error)\n}\n\nexport function sleep(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms))\n}\n\nexport function normalizeBaseUrl(baseUrl: string | undefined): string {\n return (baseUrl ?? DEFAULT_OPENCODE_GO_BASE_URL).replace(/\\/+$/, '')\n}\n\nexport function stringifyArguments(value: unknown): string {\n if (typeof value === 'string') return value\n try {\n return JSON.stringify(value) ?? '{}'\n } catch {\n return '{}'\n }\n}\n\nexport function parseArguments(raw: string): unknown {\n const text = raw.trim()\n if (!text) return {}\n try {\n return JSON.parse(text) as unknown\n } catch {\n return raw\n }\n}\n\nexport async function assertOk(\n response: Response,\n redact?: string,\n): Promise<void> {\n if (response.ok) return\n let detail: string | undefined\n try {\n const text = await response.text()\n if (text.trim()) {\n const preview = text.slice(0, 2000)\n detail = redact && preview.includes(redact)\n ? preview.replaceAll(redact, '[redacted]')\n : preview\n }\n } catch {\n detail = undefined\n }\n throw new OpenAICompatibleError(\n response.status,\n `LLM request failed with status ${response.status}`,\n detail,\n )\n}\n\nexport async function parseJson(response: Response): Promise<unknown> {\n try {\n return await response.json()\n } catch {\n throw new OpenAICompatibleError(\n response.status,\n 'LLM response was not valid JSON',\n )\n }\n}\n", "import { randomUUID } from 'node:crypto'\r\nimport type {\r\n AgentFinishReason,\r\n LLMAdapter,\r\n LLMCompletion,\r\n LLMStreamEvent,\r\n LLMToolCall,\r\n} from '@tnega/agent'\r\nimport type { ModelMessage } from '@tnega/session'\r\nimport type { ToolDefinition } from '@tnega/tools'\r\nimport { OpenAICompatibleError } from './errors.js'\r\nimport { DEFAULT_DEEPSEEK_MODEL } from './models.js'\r\nimport {\r\n assertOk,\r\n combineSignal,\r\n DEFAULT_LLM_MAX_RETRIES,\r\n DEFAULT_LLM_RETRY_DELAY_MS,\r\n DEFAULT_LLM_TIMEOUT_MS,\r\n errorMessage,\r\n isAbortLike,\r\n isExternalAbort,\r\n isRetryableStatus,\r\n normalizeBaseUrl,\r\n parseArguments,\r\n parseJson,\r\n sleep,\r\n stringifyArguments,\r\n} from './shared.js'\r\nimport type { OpenAICompatibleConfig } from './types.js'\r\n\r\ninterface OpenAICompatibleToolCall {\r\n id?: unknown\r\n type?: unknown\r\n function?: {\r\n name?: unknown\r\n arguments?: unknown\r\n }\r\n}\r\n\r\ninterface OpenAICompatibleChoice {\r\n message?: {\r\n content?: string | null\r\n tool_calls?: unknown\r\n }\r\n finish_reason?: string | null\r\n}\r\n\r\ninterface OpenAICompatiblePayload {\r\n id?: unknown\r\n model?: unknown\r\n choices?: unknown\r\n data?: unknown\r\n}\r\n\r\ninterface OpenAIStreamChoice {\r\n delta?: {\r\n content?: string | null\r\n tool_calls?: unknown\r\n }\r\n finish_reason?: string | null\r\n}\r\n\r\ninterface OpenAIStreamToolCall {\r\n index?: unknown\r\n id?: unknown\r\n function?: {\r\n name?: unknown\r\n arguments?: unknown\r\n }\r\n}\r\n\r\ninterface RequestPayload {\r\n url: string\r\n init: RequestInit\r\n}\r\n\r\nexport function openaiCompatAdapter(config: OpenAICompatibleConfig = {}): LLMAdapter {\r\n return {\r\n async complete(messages, tools, options) {\r\n const timeoutMs = config.timeoutMs ?? DEFAULT_LLM_TIMEOUT_MS\r\n const maxRetries = config.maxRetries ?? DEFAULT_LLM_MAX_RETRIES\r\n const retryDelayMs = config.retryDelayMs ?? DEFAULT_LLM_RETRY_DELAY_MS\r\n for (let attempt = 0; attempt <= maxRetries; attempt += 1) {\r\n const request = buildRequest(\r\n messages,\r\n tools,\r\n config,\r\n combineSignal(options.signal, timeoutMs),\r\n )\r\n try {\r\n const response = await fetch(request.url, request.init)\r\n if (!isRetryableStatus(response.status) || attempt >= maxRetries) {\r\n return parseResponse(response, config.apiKey)\r\n }\r\n await response.body?.cancel()\r\n } catch (error) {\r\n if (isExternalAbort(error, options.signal)) {\r\n throw new OpenAICompatibleError(\r\n 0,\r\n `LLM request aborted: ${errorMessage(error)}`,\r\n )\r\n }\r\n if (attempt >= maxRetries) {\r\n throw toRequestError(error, timeoutMs)\r\n }\r\n }\r\n await sleep(retryDelayMs * 2 ** attempt)\r\n }\r\n throw new OpenAICompatibleError(0, 'LLM request failed')\r\n },\r\n async *stream(messages, tools, options) {\r\n const timeoutMs = config.timeoutMs ?? DEFAULT_LLM_TIMEOUT_MS\r\n const maxRetries = config.maxRetries ?? DEFAULT_LLM_MAX_RETRIES\r\n const retryDelayMs = config.retryDelayMs ?? DEFAULT_LLM_RETRY_DELAY_MS\r\n for (let attempt = 0; ; attempt += 1) {\r\n const request = buildRequest(\r\n messages,\r\n tools,\r\n config,\r\n combineSignal(options.signal, timeoutMs),\r\n true,\r\n )\r\n let response: Response\r\n try {\r\n response = await fetch(request.url, request.init)\r\n } catch (error) {\r\n if (isExternalAbort(error, options.signal)) {\r\n throw new OpenAICompatibleError(\r\n 0,\r\n `LLM stream aborted: ${errorMessage(error)}`,\r\n )\r\n }\r\n if (attempt >= maxRetries) {\r\n throw toStreamError(error, timeoutMs)\r\n }\r\n await sleep(retryDelayMs * 2 ** attempt)\r\n continue\r\n }\r\n\r\n if (!response.ok || !response.body) {\r\n if (isRetryableStatus(response.status) && attempt < maxRetries) {\r\n await response.body?.cancel()\r\n await sleep(retryDelayMs * 2 ** attempt)\r\n continue\r\n }\r\n if (!response.ok) await assertOk(response, config.apiKey)\r\n throw new OpenAICompatibleError(\r\n response.status,\r\n 'LLM stream response had no body',\r\n )\r\n }\r\n\r\n let sawEvent = false\r\n try {\r\n const contentType = response.headers.get('content-type')?.split(';')[0]?.trim().toLowerCase()\r\n const events = contentType === 'application/json'\r\n ? parseJSONCompletionStream(response)\r\n : parseOpenAIStream(response.body)\r\n for await (const event of events) {\r\n sawEvent = true\r\n yield event\r\n }\r\n return\r\n } catch (error) {\r\n if (isExternalAbort(error, options.signal)) {\r\n throw new OpenAICompatibleError(\r\n 0,\r\n `LLM stream aborted: ${errorMessage(error)}`,\r\n )\r\n }\r\n if (sawEvent || attempt >= maxRetries) {\r\n throw toStreamError(error, timeoutMs)\r\n }\r\n await sleep(retryDelayMs * 2 ** attempt)\r\n }\r\n }\r\n },\r\n }\r\n}\r\n\r\nexport async function listModels(config: OpenAICompatibleConfig = {}): Promise<string[]> {\r\n const baseUrl = normalizeBaseUrl(config.baseUrl)\r\n const headers = authHeaders(config.apiKey)\r\n let response: Response\r\n try {\r\n response = await fetch(`${baseUrl}/models`, { headers })\r\n } catch (error) {\r\n throw new OpenAICompatibleError(\r\n 0,\r\n `model list request failed: ${errorMessage(error)}`,\r\n )\r\n }\r\n await assertOk(response)\r\n const payload = await parseJson(response)\r\n const data = (payload as OpenAICompatiblePayload | null)?.data\r\n if (!Array.isArray(data)) {\r\n throw new OpenAICompatibleError(\r\n response.status,\r\n 'model list response did not contain an array in data',\r\n )\r\n }\r\n return data\r\n .map((entry) => {\r\n const record = entry as { id?: unknown } | null\r\n return typeof record?.id === 'string' ? record.id : ''\r\n })\r\n .filter(Boolean)\r\n}\r\n\r\nfunction buildRequest(\r\n messages: readonly ModelMessage[],\r\n tools: readonly ToolDefinition[],\r\n config: OpenAICompatibleConfig,\r\n signal: AbortSignal | undefined,\r\n stream = false,\r\n): RequestPayload {\r\n const body: Record<string, unknown> = {\r\n model: config.model ?? DEFAULT_DEEPSEEK_MODEL,\r\n messages: messages.map(toOpenAIMessage),\r\n }\r\n if (stream) body.stream = true\r\n if (tools.length) {\r\n body.tools = tools.map(toOpenAITool)\r\n }\r\n if (config.temperature !== undefined) body.temperature = config.temperature\r\n if (config.maxTokens !== undefined) body.max_tokens = config.maxTokens\r\n\r\n return {\r\n url: `${normalizeBaseUrl(config.baseUrl)}/chat/completions`,\r\n init: {\r\n method: 'POST',\r\n headers: {\r\n 'content-type': 'application/json',\r\n ...authHeaders(config.apiKey),\r\n },\r\n body: JSON.stringify(body),\r\n ...(signal ? { signal } : {}),\r\n },\r\n }\r\n}\r\n\r\nfunction authHeaders(apiKey: string | undefined): Record<string, string> {\r\n return apiKey ? { authorization: `Bearer ${apiKey}` } : {}\r\n}\r\n\r\nfunction toOpenAIMessage(message: ModelMessage): Record<string, unknown> {\r\n const payload: Record<string, unknown> = {\r\n role: message.role,\r\n content: message.content,\r\n }\r\n if (message.role === 'tool' && message.name) payload.name = message.name\r\n if (message.tool_call_id) payload.tool_call_id = message.tool_call_id\r\n if (message.tool_calls?.length) {\r\n payload.tool_calls = message.tool_calls.map(call => ({\r\n id: call.id,\r\n type: 'function',\r\n function: {\r\n name: call.name,\r\n arguments: stringifyArguments(call.arguments),\r\n },\r\n }))\r\n }\r\n return payload\r\n}\r\n\r\nfunction toOpenAITool(tool: ToolDefinition): Record<string, unknown> {\r\n return {\r\n type: 'function',\r\n function: {\r\n name: tool.schema.name,\r\n description: tool.schema.description,\r\n parameters: tool.schema.parameters ?? { type: 'object', properties: {} },\r\n },\r\n }\r\n}\r\n\r\nasync function parseResponse(\r\n response: Response,\r\n apiKey: string | undefined,\r\n): Promise<LLMCompletion> {\r\n await assertOk(response, apiKey)\r\n const payload = await parseJson(response)\r\n return parseCompletion(payload)\r\n}\r\n\r\nfunction parseCompletion(payload: unknown): LLMCompletion {\r\n const record = payload as OpenAICompatiblePayload | null\r\n const choices = Array.isArray(record?.choices)\r\n ? record.choices as OpenAICompatibleChoice[]\r\n : []\r\n const choice = choices[0]\r\n const rawContent = choice?.message?.content\r\n const content = typeof rawContent === 'string' ? rawContent : undefined\r\n const toolCalls = parseToolCalls(choice?.message?.tool_calls)\r\n const finishReason = toFinishReason(\r\n choice?.finish_reason,\r\n content,\r\n toolCalls !== undefined,\r\n )\r\n const completion: LLMCompletion = {\r\n finishReason,\r\n }\r\n if (content !== undefined) completion.content = content\r\n if (toolCalls !== undefined) completion.toolCalls = toolCalls\r\n return completion\r\n}\r\n\r\nfunction parseToolCalls(value: unknown): LLMToolCall[] | undefined {\r\n if (!Array.isArray(value)) return undefined\r\n const calls: LLMToolCall[] = []\r\n for (const entry of value) {\r\n if (!entry || typeof entry !== 'object') continue\r\n const item = entry as OpenAICompatibleToolCall\r\n const name = typeof item.function?.name === 'string' ? item.function.name : ''\r\n if (!name) continue\r\n const id = typeof item.id === 'string' && item.id\r\n ? item.id\r\n : `call_${calls.length + 1}`\r\n const rawArguments = typeof item.function?.arguments === 'string'\r\n ? item.function.arguments\r\n : ''\r\n calls.push({\r\n id,\r\n name,\r\n arguments: parseArguments(rawArguments),\r\n })\r\n }\r\n return calls.length ? calls : undefined\r\n}\r\n\r\nfunction toFinishReason(\r\n raw: string | null | undefined,\r\n content: string | undefined,\r\n hasToolCalls: boolean,\r\n): AgentFinishReason {\r\n if (raw === 'stop' || (raw === undefined && content !== undefined && !hasToolCalls)) {\r\n return 'stop'\r\n }\r\n if (raw === 'length') return 'length'\r\n if (raw === 'tool_calls' || hasToolCalls) return 'tool_calls'\r\n return 'error'\r\n}\r\n\r\nfunction toRequestError(error: unknown, timeoutMs: number): OpenAICompatibleError {\r\n if (isAbortLike(error)) {\r\n return new OpenAICompatibleError(\r\n 0,\r\n `LLM request timed out after ${timeoutMs}ms`,\r\n )\r\n }\r\n return new OpenAICompatibleError(0, `LLM request failed: ${errorMessage(error)}`)\r\n}\r\n\r\nasync function* parseOpenAIStream(\r\n body: ReadableStream<Uint8Array>,\r\n): AsyncGenerator<LLMStreamEvent> {\r\n const reader = body.getReader()\r\n const decoder = new TextDecoder()\r\n let buffer = ''\r\n let content = ''\r\n let messageId: string = randomUUID()\r\n let model: string | undefined\r\n let messageStarted = false\r\n let finishReason: string | null | undefined\r\n const calls = new Map<number, {\r\n index: number\r\n id: string\r\n name: string\r\n arguments: string\r\n emitted: boolean\r\n }>()\r\n\r\n try {\r\n while (true) {\r\n const { done, value } = await reader.read()\r\n if (done) break\r\n buffer += decoder.decode(value, { stream: true })\r\n let newlineIndex: number\r\n while ((newlineIndex = buffer.indexOf('\\n')) >= 0) {\r\n const line = buffer.slice(0, newlineIndex).replace(/\\r$/, '')\r\n buffer = buffer.slice(newlineIndex + 1)\r\n if (!line.startsWith('data:')) continue\r\n const data = line.slice(5).trim()\r\n if (!data) continue\r\n if (data === '[DONE]') {\r\n yield* finalizeStreamEvents(messageId, content, calls, finishReason)\r\n return\r\n }\r\n let payload: unknown\r\n try {\r\n payload = JSON.parse(data) as unknown\r\n } catch {\r\n continue\r\n }\r\n const events = processStreamChunk(\r\n payload,\r\n { messageId, model, messageStarted },\r\n { content, finishReason },\r\n calls,\r\n )\r\n messageId = events.messageId\r\n model = events.model\r\n messageStarted = true\r\n content = events.content\r\n finishReason = events.finishReason\r\n for (const event of events.events) yield event\r\n }\r\n }\r\n } finally {\r\n if (reader.releaseLock) {\r\n try {\r\n reader.releaseLock()\r\n } catch {\r\n // stream may already be closed by abort\r\n }\r\n }\r\n }\r\n\r\n yield* finalizeStreamEvents(messageId, content, calls, finishReason)\r\n}\r\n\r\nasync function* parseJSONCompletionStream(response: Response): AsyncGenerator<LLMStreamEvent> {\r\n const payload = await parseJson(response)\r\n const completion = parseCompletion(payload)\r\n const record = payload as OpenAICompatiblePayload | null\r\n const id = typeof record?.id === 'string' && record.id ? record.id : randomUUID()\r\n const model = typeof record?.model === 'string' && record.model ? record.model : undefined\r\n yield { type: 'message_start', id, ...(model ? { model } : {}) }\r\n if (completion.content) yield { type: 'message_delta', id, delta: completion.content }\r\n for (const [index, call] of (completion.toolCalls ?? []).entries()) {\r\n yield { type: 'toolcall_start', id: call.id, index, name: call.name }\r\n yield {\r\n type: 'toolcall_end',\r\n id: call.id,\r\n index,\r\n name: call.name,\r\n arguments: call.arguments,\r\n }\r\n }\r\n yield { type: 'message_stop', id, finishReason: completion.finishReason }\r\n}\r\n\r\ninterface StreamChunkState {\r\n messageId: string\r\n model: string | undefined\r\n messageStarted: boolean\r\n content: string\r\n finishReason: string | null | undefined\r\n}\r\n\r\nfunction processStreamChunk(\r\n payload: unknown,\r\n state: Pick<StreamChunkState, 'messageId' | 'model' | 'messageStarted'>,\r\n progress: Pick<StreamChunkState, 'content' | 'finishReason'>,\r\n calls: Map<number, {\r\n index: number\r\n id: string\r\n name: string\r\n arguments: string\r\n emitted: boolean\r\n }>,\r\n): StreamChunkState & { events: LLMStreamEvent[] } {\r\n const record = payload as {\r\n id?: unknown\r\n model?: unknown\r\n choices?: unknown\r\n } | null\r\n const events: LLMStreamEvent[] = []\r\n let messageId = state.messageId\r\n let model = state.model\r\n let messageStarted = state.messageStarted\r\n let content = progress.content\r\n let finishReason = progress.finishReason\r\n\r\n if (typeof record?.id === 'string' && record.id) messageId = record.id\r\n if (typeof record?.model === 'string' && record.model) model = record.model\r\n if (!messageStarted) {\r\n messageStarted = true\r\n const start = {\r\n type: 'message_start' as const,\r\n id: messageId,\r\n ...(model ? { model } : {}),\r\n }\r\n events.push(start)\r\n }\r\n\r\n const choices = Array.isArray(record?.choices)\r\n ? record.choices as OpenAIStreamChoice[]\r\n : []\r\n const choice = choices[0]\r\n if (choice?.finish_reason !== undefined && choice.finish_reason !== null) {\r\n finishReason = choice.finish_reason\r\n }\r\n const delta = choice?.delta\r\n if (typeof delta?.content === 'string' && delta.content) {\r\n content += delta.content\r\n events.push({ type: 'message_delta', id: messageId, delta: delta.content })\r\n }\r\n if (Array.isArray(delta?.tool_calls)) {\r\n for (const entry of delta.tool_calls as OpenAIStreamToolCall[]) {\r\n const index = typeof entry.index === 'number' ? entry.index : 0\r\n let call = calls.get(index)\r\n if (!call) {\r\n call = { index, id: '', name: '', arguments: '', emitted: false }\r\n calls.set(index, call)\r\n }\r\n if (typeof entry.id === 'string' && entry.id) call.id = entry.id\r\n if (typeof entry.function?.name === 'string' && entry.function.name) {\r\n call.name = entry.function.name\r\n }\r\n if (typeof entry.function?.arguments === 'string') {\r\n call.arguments += entry.function.arguments\r\n }\r\n if (!call.emitted && call.id && call.name) {\r\n call.emitted = true\r\n events.push({\r\n type: 'toolcall_start',\r\n id: call.id,\r\n index,\r\n name: call.name,\r\n })\r\n }\r\n }\r\n }\r\n\r\n return {\r\n messageId,\r\n model,\r\n messageStarted,\r\n content,\r\n finishReason,\r\n events,\r\n }\r\n}\r\n\r\nfunction finalizeStreamEvents(\r\n messageId: string,\r\n content: string,\r\n calls: Map<number, {\r\n index: number\r\n id: string\r\n name: string\r\n arguments: string\r\n emitted: boolean\r\n }>,\r\n finishReason: string | null | undefined,\r\n): LLMStreamEvent[] {\r\n const events: LLMStreamEvent[] = []\r\n const toolCalls: LLMToolCall[] = []\r\n for (const call of calls.values()) {\r\n if (!call.emitted) continue\r\n events.push({\r\n type: 'toolcall_end',\r\n id: call.id,\r\n index: call.index,\r\n name: call.name,\r\n arguments: parseArguments(call.arguments),\r\n })\r\n toolCalls.push({\r\n id: call.id,\r\n name: call.name,\r\n arguments: parseArguments(call.arguments),\r\n })\r\n }\r\n events.push({\r\n type: 'message_stop',\r\n id: messageId,\r\n finishReason: toFinishReason(finishReason, content, toolCalls.length > 0),\r\n })\r\n return events\r\n}\r\n\r\nfunction toStreamError(error: unknown, timeoutMs: number): OpenAICompatibleError {\r\n if (isAbortLike(error)) {\r\n return new OpenAICompatibleError(\r\n 0,\r\n `LLM stream timed out after ${timeoutMs}ms`,\r\n )\r\n }\r\n return new OpenAICompatibleError(0, `LLM stream failed: ${errorMessage(error)}`)\r\n}\r\n", "import { anthropicMessagesAdapter } from './anthropic-messages.js'\r\nimport { lookupModel } from './models.js'\r\nimport { openaiCompatAdapter } from './openai.js'\r\nimport type { LlmConfig } from './types.js'\r\n\r\nexport function createLlmAdapter(config: LlmConfig): ReturnType<typeof openaiCompatAdapter> {\r\n if (config.protocol === 'anthropic') {\r\n return anthropicMessagesAdapter(config)\r\n }\r\n if (config.protocol === 'openai') {\r\n return openaiCompatAdapter(config)\r\n }\r\n if (lookupModel(config.model)?.protocol === 'anthropic') {\r\n return anthropicMessagesAdapter(config)\r\n }\r\n return openaiCompatAdapter(config)\r\n}\r\n"],
5
+ "mappings": "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",
6
+ "names": ["randomUUID", "buildRequest", "parseResponse", "toRequestError", "toStreamError", "parseJSONCompletionStream", "parseCompletion", "parseToolCalls", "toFinishReason", "randomUUID"]
7
7
  }
package/dist/session.js CHANGED
@@ -104,17 +104,88 @@ function checkMonotonicSeq(events) {
104
104
  }
105
105
  return failures;
106
106
  }
107
+ function isRecord(value) {
108
+ return typeof value === "object" && value !== null && (Object.getPrototypeOf(value) === Object.prototype || Object.getPrototypeOf(value) === null);
109
+ }
110
+ function isNonNegativeInteger(value) {
111
+ return typeof value === "number" && Number.isSafeInteger(value) && value >= 0;
112
+ }
113
+ function isJsonValue(value, ancestors = /* @__PURE__ */ new Set()) {
114
+ if (value === null || typeof value === "string" || typeof value === "boolean") return true;
115
+ if (typeof value === "number") return Number.isFinite(value);
116
+ if (typeof value !== "object" || ancestors.has(value)) return false;
117
+ if (!Array.isArray(value) && Object.getPrototypeOf(value) !== Object.prototype && Object.getPrototypeOf(value) !== null) return false;
118
+ ancestors.add(value);
119
+ const valid = (Array.isArray(value) ? Array.from(value) : Object.values(value)).every((member) => isJsonValue(member, ancestors));
120
+ ancestors.delete(value);
121
+ return valid;
122
+ }
123
+ function isStreamRecord(value) {
124
+ if (!isRecord(value) || !isNonNegativeInteger(value.time) || !isRecord(value.chunk)) return false;
125
+ const chunk = value.chunk;
126
+ if (chunk.type === "stream_error") {
127
+ return isRecord(chunk.error) && typeof chunk.error.message === "string" && (chunk.error.name === void 0 || typeof chunk.error.name === "string") && (chunk.error.stack === void 0 || typeof chunk.error.stack === "string");
128
+ }
129
+ if (typeof chunk.id !== "string") return false;
130
+ switch (chunk.type) {
131
+ case "message_start":
132
+ return chunk.model === void 0 || typeof chunk.model === "string";
133
+ case "message_delta":
134
+ return typeof chunk.delta === "string";
135
+ case "toolcall_start":
136
+ case "toolcall_end":
137
+ return isNonNegativeInteger(chunk.index) && typeof chunk.name === "string" && (chunk.type === "toolcall_start" || isJsonValue(chunk.arguments));
138
+ case "message_stop":
139
+ return chunk.finishReason === "stop" || chunk.finishReason === "tool_calls" || chunk.finishReason === "length" || chunk.finishReason === "max_turns" || chunk.finishReason === "max_steps" || chunk.finishReason === "error" || chunk.finishReason === "cancelled";
140
+ default:
141
+ return false;
142
+ }
143
+ }
144
+ function checkAssistantAttempts(events) {
145
+ const turns = /* @__PURE__ */ new Set();
146
+ const steps = /* @__PURE__ */ new Map();
147
+ const failures = [];
148
+ for (const event of events) {
149
+ if (event.type === "turn/start") turns.add(event.payload.turn);
150
+ if (event.type === "turn/end") {
151
+ turns.delete(event.payload.turn);
152
+ for (const [key, turn] of steps) {
153
+ if (turn === event.payload.turn) steps.delete(key);
154
+ }
155
+ }
156
+ if (event.type === "step/start" && turns.has(event.payload.turn)) {
157
+ steps.set(`${event.payload.turn}:${event.payload.step}`, event.payload.turn);
158
+ }
159
+ if (event.type === "step/end") steps.delete(`${event.payload.turn}:${event.payload.step}`);
160
+ if (event.type !== "assistant/attempt") continue;
161
+ const payload = event.payload;
162
+ if (!isRecord(payload) || !isNonNegativeInteger(payload.turn) || !isNonNegativeInteger(payload.step) || !turns.has(payload.turn) || !steps.has(`${payload.turn}:${payload.step}`)) {
163
+ failures.push({
164
+ name: "assistant/attempt-without-open-step",
165
+ detail: `assistant/attempt at seq ${event.seq} has no matching open turn and step`
166
+ });
167
+ }
168
+ if (!isRecord(payload) || !Array.isArray(payload.stream) || !payload.stream.every(isStreamRecord)) {
169
+ failures.push({
170
+ name: "assistant/attempt-invalid-stream",
171
+ detail: `assistant/attempt at seq ${event.seq} must contain an ordered array of normalized stream records`
172
+ });
173
+ }
174
+ }
175
+ return failures;
176
+ }
107
177
  function checkSessionInvariants(events) {
108
178
  return [
109
179
  ...checkBalancedTurns(events),
110
180
  ...checkBalancedSteps(events),
111
181
  ...checkBalancedToolCalls(events),
112
- ...checkMonotonicSeq(events)
182
+ ...checkMonotonicSeq(events),
183
+ ...checkAssistantAttempts(events)
113
184
  ];
114
185
  }
115
186
 
116
187
  // packages/session/src/index.ts
117
- var SESSION_FORMAT_VERSION = 7;
188
+ var SESSION_FORMAT_VERSION = 10;
118
189
  var SessionFormatError = class extends Error {
119
190
  name = "SessionFormatError";
120
191
  };
@@ -134,6 +205,12 @@ function isSessionEvent(value) {
134
205
  const record = value;
135
206
  return typeof record.id === "string" && typeof record.seq === "number" && typeof record.ts === "number" && typeof record.type === "string" && "payload" in record;
136
207
  }
208
+ function assistantStreams(events) {
209
+ return events.flatMap((event) => {
210
+ if (event.type !== "assistant/message" && event.type !== "assistant/attempt") return [];
211
+ return event.payload.stream === void 0 ? [] : [clone(event.payload.stream)];
212
+ });
213
+ }
137
214
  function clone(value) {
138
215
  return structuredClone(value);
139
216
  }
@@ -289,7 +366,7 @@ function transcriptEvents(events) {
289
366
  const structure = events.filter((event) => !inSkeleton.has(event.id)).filter((event) => event.type !== "compaction/start" && event.type !== "compaction/end").filter((event) => event.type !== "checkpoint").filter((event) => !(event.type === "tool/call" && declaredCalls.has(event.payload.id)));
290
367
  const ordered = [...skeleton];
291
368
  for (const event of structure) {
292
- let index = ordered.length;
369
+ let index = 0;
293
370
  for (let cursor = ordered.length - 1; cursor >= 0; cursor -= 1) {
294
371
  if (ordered[cursor].seq <= event.seq) {
295
372
  index = cursor + 1;
@@ -389,6 +466,7 @@ function estimateEventTokens(event) {
389
466
  return Math.ceil(raw.length / 4);
390
467
  }
391
468
  case "plan":
469
+ case "assistant/attempt":
392
470
  return 0;
393
471
  case "checkpoint":
394
472
  return estimateMessageTokens(event.payload.messages);
@@ -545,9 +623,15 @@ function estimateContextUsage(messages, limit = DEFAULT_CONTEXT_LIMIT) {
545
623
  };
546
624
  }
547
625
  var SessionLog = class {
548
- constructor(file, _broadcast) {
626
+ constructor(file, _broadcast, publicationContext) {
549
627
  this.file = file;
550
628
  this._broadcast = _broadcast;
629
+ if (!this._broadcast && publicationContext) {
630
+ this._broadcast = (type, payload) => {
631
+ if (type === "event") publicationContext.emit("session/event", payload);
632
+ else publicationContext.emit("session/flush", payload);
633
+ };
634
+ }
551
635
  }
552
636
  file;
553
637
  _broadcast;
@@ -716,7 +800,7 @@ var SessionLog = class {
716
800
  selected.push(clone(event));
717
801
  continue;
718
802
  }
719
- if (event.type === "meta" || event.type === "llm/retry" || event.type === "llm/retry-started" || event.type.startsWith("turn/") || event.type.startsWith("step/")) {
803
+ if (event.type === "meta" || event.type === "llm/retry" || event.type === "llm/retry-started" || event.type === "assistant/attempt" || event.type.startsWith("turn/") || event.type.startsWith("step/")) {
720
804
  continue;
721
805
  }
722
806
  if (event.type === "checkpoint") {
@@ -1015,6 +1099,8 @@ export {
1015
1099
  SESSION_FORMAT_VERSION,
1016
1100
  SessionFormatError,
1017
1101
  SessionLog,
1102
+ assistantStreams,
1103
+ checkAssistantAttempts,
1018
1104
  checkBalancedSteps,
1019
1105
  checkBalancedToolCalls,
1020
1106
  checkBalancedTurns,