lemura 1.0.0 → 1.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/CHANGELOG.md CHANGED
@@ -5,6 +5,44 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [1.2.0] - 2026-03-12
9
+
10
+ ### Added
11
+ - **MCP Support** (`MCPClient.ts`, `MCPRegistry.ts`): Model Context Protocol support integrated. You can now register tools from remote MCP servers.
12
+ - **Improved Traces & Observability**: Session traces now include detailed metadata for token usage, execution budget consumption, and planning states for every turn.
13
+ - **Tool Firewall — fully wired** (`ToolFirewall.ts`): The ask/accept/deny policy layer is now fully integrated into the `SessionManager` ReAct loop. Parallel batches respect firewall decisions per-call. No external dependencies.
14
+ - **Standalone JSON Schema Validator** (`SchemaValidator.ts`): Tool parameter validation now enforces the tool's JSON Schema at runtime before execution. Supports `type`, `required`, `properties`, `additionalProperties`, `enum`, `const`, `minLength`/`maxLength`/`pattern` (string), `minimum`/`maximum`/`exclusiveMinimum`/`exclusiveMaximum` (number), `minItems`/`maxItems`/`items` (array), `minProperties`/`maxProperties` (object), and `allOf`/`anyOf`/`oneOf`/`not` composition — zero external dependencies.
15
+ - **Tool execution timeout enforcement**: Every `ToolRegistry.execute()` call now races against a configurable timeout (`toolRegistryTimeoutMs`, default 30 s) via `Promise.race`. Throws `LemuraToolTimeoutError` on expiry.
16
+ - **Tool execution budget** (`ToolExecutionBudget` type + wired in `SessionManager`): Per-session and per-tool call quotas (`maxCallsPerSession`, `maxCallsPerTool`) and a concurrency cap (`maxConcurrentCalls`) are now enforced in the ReAct loop.
17
+ - **Parallel tool calls** (`parallelToolCalls: boolean`): When enabled, independent tool calls within a single assistant turn are executed in parallel via `Promise.all`, batched by `maxConcurrentCalls`. Falls back to sequential execution when disabled (default).
18
+ - **maxSteps guard wired**: `StepCounter` is now active in the ReAct loop. When `toolCallCount >= maxSteps`, tool definitions are removed from the provider payload and a forced-conclusion prompt + `FinalResponseFormatter` structure is injected.
19
+ - **Tool Response Compression wired**: `ToolResponseProcessor` is now applied to every tool result in the loop. Large/oversized responses are compressed before being appended to the context.
20
+ - **Goal Injection wired** (`enableGoalPlanning: true`): When enabled, a `GoalInjector` is initialised on the first `run()` call and injects the `[CURRENT GOAL]` block into the system prompt (or as a `pre_turn` message) on every iteration.
21
+ - **`SessionManager.stream()`**: New `AsyncIterable<string>` method streams the final LLM response token-by-token. Tool calls within the loop are completed synchronously before streaming the conclusion.
22
+ - **`SessionManager.reset()`**: New method clears conversation history, resets iteration counters, and clears tool execution budget tallies without losing the adapter or config.
23
+ - **`ToolRegistry.unregister()`**: New method to remove a registered tool by name at runtime.
24
+ - **`ToolRegistry.executeParallel()`**: New method for executing a batch of named tool calls in parallel with per-call error isolation.
25
+
26
+ ### Changed
27
+ - `ToolRegistry.execute()` — now validates params, enforces timeout, and wraps errors in `LemuraError` subclasses instead of raw `Error`.
28
+ - `ToolRegistry` constructor — accepts an optional `ToolRegistryOptions` second argument (`defaultTimeoutMs`).
29
+ - `SessionConfig` — new fields: `toolExecutionBudget`, `parallelToolCalls`, `toolRegistryTimeoutMs`.
30
+ - `ToolFirewallRule` and `ToolFirewallConfig` — all fields now have TSDoc inline documentation.
31
+
32
+ ### Fixed
33
+ - Tool errors in the ReAct loop now correctly distinguish timeout (`LemuraToolTimeoutError`) from execution failures, with accurate structured log output and hints.
34
+ - `any`-typed variables in `ToolRegistry.execute()` replaced with typed `LemuraError` subclasses for full strict-mode compliance.
35
+
36
+ ## [1.1.0] - 2026-03-08
37
+
38
+ ### Added
39
+ - `MediaBridge` — unified API for ASR, TTS, Vision, and Image Generation over `IProviderAdapter`.
40
+ - Built-in media tools (`media_transcribe`, `media_synthesize`, `media_describe_image`, `media_generate_image`) enabled via `SessionConfig.media.enableTools`.
41
+ - `ToolFirewall` — ask/accept/deny rule-based gating for tool calls (`SessionConfig.toolFirewall`).
42
+ - Advanced execution classes: `StepCounter`, `GoalInjector`, `ContinuationPlanner`, `FinalResponseFormatter`, `ToolResponseProcessor` (in `src/agent/execution/`).
43
+ - `ToolExecutionBudget` type for per-session and per-tool call quotas.
44
+
45
+
8
46
  ## [1.0.0] - 2026-03-07
9
47
 
10
48
  ### Added
package/README.md CHANGED
@@ -5,7 +5,8 @@
5
5
  **A provider-agnostic, premium agentic AI runtime for the modern web.**
6
6
 
7
7
  [![npm version](https://img.shields.io/npm/v/lemura.svg?style=flat-square)](https://www.npmjs.com/package/lemura)
8
- [![license](https://img.shields.io/npm/l/lemura.svg?style=flat-square)](https://github.com/rzafiamy/lemura/blob/main/LICENSE)
8
+ e[![license](https://img.shields.io/npm/l/lemura.svg?style=flat-square)](./LICENSE)
9
+ [![docs](https://img.shields.io/badge/docs-lemura.makix.fr-blue?style=flat-square)](https://lemura.makix.fr)
9
10
  [![build](https://img.shields.io/github/actions/workflow/status/lemura-ai/lemura/ci.yml?branch=main&style=flat-square)](https://github.com/rzafiamy/lemura/actions)
10
11
  [![coverage](https://img.shields.io/codecov/c/github/lemura-ai/lemura?style=flat-square)](https://codecov.io/gh/lemura-ai/lemura)
11
12
 
@@ -13,6 +14,16 @@
13
14
 
14
15
  `lemura` is a robust, provider-agnostic npm package designed to encapsulate a full agentic AI runtime. It simplifies the complex orchestration of LLMs, tools, and context management into a single, cohesive interface.
15
16
 
17
+ ### ✨ Key Features in v1.2.0
18
+ - **🔌 MCP Support**: Native Model Context Protocol integration for connecting to external tool servers.
19
+ - **🛡️ Tool Firewall**: Fully integrated ask/accept/deny policy layer.
20
+ - **✅ JSON Schema Validation**: Zero-dependency runtime parameter validation.
21
+ - **⚡ Parallel Tool Calls**: Execute independent tools concurrently for speed.
22
+ - **📊 Enhanced Traces**: Improved observability with detailed token and budget tracking.
23
+ - **⏱️ Execution Timeouts**: Per-tool execution limits for reliability.
24
+ - **🎯 Goal Injection**: Persistent goal awareness across the agent loop.
25
+ - **🌊 Streaming**: Native support for token-by-token completion streaming.
26
+
16
27
  ## 🚀 Install
17
28
 
18
29
  ```bash
@@ -76,12 +87,13 @@ main();
76
87
 
77
88
  ## 🧠 Core Concepts
78
89
 
79
- Explore the architecture and advanced capabilities of `lemura`:
90
+ Explore the architecture and advanced capabilities of `lemura` at [lemura.makix.fr](https://lemura.makix.fr) or browse the local guides:
80
91
 
81
92
  - 🏁 [**Getting Started**](./docs/guides/getting-started.md) — Fundamental setup and concepts.
82
93
  - 🧹 [**Context Management**](./docs/guides/context-management.md) — Advanced compression strategies.
83
94
  - 🔌 [**Adapters**](./docs/guides/adapters.md) — Connecting to OpenAI, Groq, Anthropic, and more.
84
95
  - 🛠️ [**Tools and Skills**](./docs/guides/tools-and-skills.md) — Extending agent capabilities.
96
+ - 🎛️ [**Media Bridge**](./docs/guides/media-bridge.md) — ASR, TTS, vision, and image generation.
85
97
  - ⚡ [**Advanced Execution**](./docs/guides/advanced-execution.md) — Goal planning and continuation.
86
98
 
87
99
  ## 📦 API Overview
@@ -1,5 +1,4 @@
1
- import { e as IProviderAdapter, c as CompletionRequest, d as CompletionResponse, b as CompletionChunk, M as ModelInfo, k as TranscriptionRequest, l as TranscriptionResponse, S as SynthesisRequest, A as AudioChunk, V as VisionRequest, m as VisionResponse, f as ImageGenRequest, g as ImageGenResponse } from '../adapters-BnG0LEYD.mjs';
2
- import '../storage-DMcliVVj.mjs';
1
+ import { a as IProviderAdapter, k as CompletionRequest, l as CompletionResponse, j as CompletionChunk, M as ModelInfo, T as TranscriptionRequest, c as TranscriptionResponse, d as SynthesisRequest, A as AudioChunk, V as VisionRequest, e as VisionResponse, f as ImageGenRequest, g as ImageGenResponse } from '../storage-CG3nTa6o.mjs';
3
2
  import '../rag-La_Bo-J8.mjs';
4
3
  import '../logger-DxvKliuk.mjs';
5
4
 
@@ -20,7 +19,7 @@ interface OpenAICompatibleAdapterConfig {
20
19
  */
21
20
  declare class OpenAICompatibleAdapter implements IProviderAdapter {
22
21
  readonly name = "openai_compatible";
23
- readonly version = "1.0.0";
22
+ readonly version = "1.2.0";
24
23
  private baseUrl;
25
24
  private apiKey;
26
25
  private defaultModel;
@@ -1,5 +1,4 @@
1
- import { e as IProviderAdapter, c as CompletionRequest, d as CompletionResponse, b as CompletionChunk, M as ModelInfo, k as TranscriptionRequest, l as TranscriptionResponse, S as SynthesisRequest, A as AudioChunk, V as VisionRequest, m as VisionResponse, f as ImageGenRequest, g as ImageGenResponse } from '../adapters-BSkhv5ac.js';
2
- import '../storage-BGu4Loao.js';
1
+ import { a as IProviderAdapter, k as CompletionRequest, l as CompletionResponse, j as CompletionChunk, M as ModelInfo, T as TranscriptionRequest, c as TranscriptionResponse, d as SynthesisRequest, A as AudioChunk, V as VisionRequest, e as VisionResponse, f as ImageGenRequest, g as ImageGenResponse } from '../storage-DBt_q0wO.js';
3
2
  import '../rag-La_Bo-J8.js';
4
3
  import '../logger-DxvKliuk.js';
5
4
 
@@ -20,7 +19,7 @@ interface OpenAICompatibleAdapterConfig {
20
19
  */
21
20
  declare class OpenAICompatibleAdapter implements IProviderAdapter {
22
21
  readonly name = "openai_compatible";
23
- readonly version = "1.0.0";
22
+ readonly version = "1.2.0";
24
23
  private baseUrl;
25
24
  private apiKey;
26
25
  private defaultModel;
@@ -28,7 +28,7 @@ var LemuraAdapterError = class extends LemuraError {
28
28
  // src/adapters/OpenAICompatibleAdapter.ts
29
29
  var OpenAICompatibleAdapter = class {
30
30
  name = "openai_compatible";
31
- version = "1.0.0";
31
+ version = "1.2.0";
32
32
  baseUrl;
33
33
  apiKey;
34
34
  defaultModel;
@@ -277,7 +277,7 @@ var OpenAICompatibleAdapter = class {
277
277
  const blob = new Blob([bytes], { type: request.mimeType });
278
278
  const formData = new FormData();
279
279
  formData.append("file", blob, "audio.webm");
280
- formData.append("model", "whisper-1");
280
+ formData.append("model", request.model || "whisper-1");
281
281
  if (request.language) formData.append("language", request.language);
282
282
  const response = await this.fetchWithRetry(`${this.baseUrl}/audio/transcriptions`, {
283
283
  method: "POST",
@@ -298,7 +298,7 @@ var OpenAICompatibleAdapter = class {
298
298
  const response = await this.fetchWithRetry(`${this.baseUrl}/audio/speech`, {
299
299
  method: "POST",
300
300
  body: JSON.stringify({
301
- model: "tts-1",
301
+ model: request.model || "tts-1",
302
302
  input: request.text,
303
303
  voice: request.voiceId || "alloy",
304
304
  response_format: request.format || "mp3"
@@ -321,7 +321,7 @@ var OpenAICompatibleAdapter = class {
321
321
  }
322
322
  async describeImage(request) {
323
323
  const payload = {
324
- model: this.defaultModel,
324
+ model: request.model || this.defaultModel,
325
325
  messages: [
326
326
  {
327
327
  role: "user",
@@ -353,7 +353,7 @@ var OpenAICompatibleAdapter = class {
353
353
  method: "POST",
354
354
  body: JSON.stringify({
355
355
  prompt: request.prompt,
356
- model: "dall-e-3",
356
+ model: request.model || "dall-e-3",
357
357
  n: 1,
358
358
  size: request.dimensions || "1024x1024"
359
359
  })
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/types/errors.ts","../../src/adapters/OpenAICompatibleAdapter.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Base class for all custom errors thrown by lemura.\n *\n * @example\n * throw new LemuraError('Something went wrong', 'UNKNOWN_ERROR');\n */\nexport class LemuraError extends Error {\n /**\n * @param message - The error message\n * @param code - The error code for programmatic handling\n * @param problem - A clear description of the problem for the end user\n * @param hints - A list of suggestions to resolve the issue\n */\n constructor(\n message: string,\n public readonly code: string,\n public readonly problem?: string,\n public readonly hints: string[] = []\n ) {\n super(message);\n this.name = 'LemuraError';\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/** Error thrown when context exceeds max tokens and cannot be compressed further */\nexport class LemuraContextOverflowError extends LemuraError {\n constructor(message: string) {\n super(message, 'CONTEXT_OVERFLOW');\n this.name = 'LemuraContextOverflowError';\n }\n}\n\n/** Error thrown when a requested tool is not found in the registry */\nexport class LemuraToolNotFoundError extends LemuraError {\n constructor(message: string) {\n super(message, 'TOOL_NOT_FOUND');\n this.name = 'LemuraToolNotFoundError';\n }\n}\n\n/** Error thrown when an adapter encounters an API or formatting issue */\nexport class LemuraAdapterError extends LemuraError {\n constructor(\n message: string,\n code = 'ADAPTER_ERROR',\n public cause?: any,\n problem?: string,\n hints: string[] = []\n ) {\n super(message, code, problem, hints);\n this.name = 'LemuraAdapterError';\n }\n}\n\n/** Error thrown when a skill cannot be parsed or injected */\nexport class LemuraSkillInjectionError extends LemuraError {\n constructor(message: string) {\n super(message, 'SKILL_INJECTION_FAILED');\n this.name = 'LemuraSkillInjectionError';\n }\n}\n\n/** Error thrown when the ReAct loop exceeds the configured max iterations */\nexport class LemuraMaxIterationsError extends LemuraError {\n constructor(message: string) {\n super(message, 'MAX_ITERATIONS_EXCEEDED');\n this.name = 'LemuraMaxIterationsError';\n }\n}\n\n/** Error thrown when tool parameters fail JSON schema validation */\nexport class LemuraToolValidationError extends LemuraError {\n constructor(message: string) {\n super(message, 'TOOL_VALIDATION_FAILED');\n this.name = 'LemuraToolValidationError';\n }\n}\n\n/** Error thrown when a tool execute function exceeds its timeout */\nexport class LemuraToolTimeoutError extends LemuraError {\n constructor(message: string) {\n super(message, 'TOOL_TIMEOUT');\n this.name = 'LemuraToolTimeoutError';\n }\n}\n","import {\n IProviderAdapter,\n CompletionRequest,\n CompletionResponse,\n CompletionChunk,\n TranscriptionRequest,\n TranscriptionResponse,\n SynthesisRequest,\n AudioChunk,\n VisionRequest,\n VisionResponse,\n ImageGenRequest,\n ImageGenResponse,\n ModelInfo,\n LemuraAdapterError,\n} from '../types/index.js';\n\nexport interface RetryConfig {\n maxRetries: number;\n baseDelayMs: number;\n}\n\nexport interface OpenAICompatibleAdapterConfig {\n baseUrl?: string;\n apiKey?: string;\n defaultModel?: string;\n defaultHeaders?: Record<string, string>;\n timeout?: number;\n retry?: RetryConfig;\n}\n\n/**\n * Reference implementation of an OpenAI-compatible provider adapter.\n */\nexport class OpenAICompatibleAdapter implements IProviderAdapter {\n readonly name = 'openai_compatible';\n readonly version = '1.0.0';\n\n private baseUrl: string;\n private apiKey: string;\n private defaultModel: string;\n private defaultHeaders: Record<string, string>;\n private timeoutMs: number;\n private retryConfig: RetryConfig;\n\n constructor(config: OpenAICompatibleAdapterConfig = {}) {\n this.baseUrl = (\n config.baseUrl ??\n process.env.LEMURA_BASE_URL ??\n process.env.OPENAI_BASE_URL ??\n 'https://api.openai.com/v1'\n ).replace(/\\/$/, '');\n\n this.apiKey = config.apiKey ?? process.env.LEMURA_API_KEY ?? process.env.OPENAI_API_KEY ?? '';\n this.defaultModel = config.defaultModel ?? process.env.LEMURA_MODEL ?? process.env.OPENAI_MODEL ?? 'gpt-3.5-turbo';\n\n this.defaultHeaders = config.defaultHeaders || {};\n this.timeoutMs = config.timeout || 30000;\n this.retryConfig = config.retry || { maxRetries: 2, baseDelayMs: 1000 };\n }\n\n private async fetchWithRetry(url: string, init: RequestInit): Promise<Response> {\n let attempts = 0;\n while (attempts <= this.retryConfig.maxRetries) {\n try {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeoutMs);\n\n const headers: Record<string, string> = {\n 'Authorization': `Bearer ${this.apiKey}`,\n ...this.defaultHeaders,\n };\n\n if (init.headers) {\n Object.assign(headers, init.headers);\n }\n\n // Don't set Content-Type if it's 'unset' (for FormData)\n if (headers['Content-Type'] === 'unset') {\n delete headers['Content-Type'];\n } else if (!headers['Content-Type']) {\n headers['Content-Type'] = 'application/json';\n }\n\n const response = await fetch(url, {\n ...init,\n signal: controller.signal,\n headers,\n });\n\n clearTimeout(timeoutId);\n\n if (response.ok) return response;\n\n // Retry on 429 and 503\n if ((response.status === 429 || response.status === 503) && attempts < this.retryConfig.maxRetries) {\n attempts++;\n const delay = this.retryConfig.baseDelayMs * Math.pow(2, attempts - 1);\n await new Promise(resolve => setTimeout(resolve, delay));\n continue;\n }\n\n const errorText = await response.text().catch(() => '');\n let problem = 'The server replied with an error during the API call.';\n let hints = ['Check the API documentation for the provider you are using.'];\n\n if (response.status === 401) {\n problem = 'Authentication failed. The API key is invalid or missing.';\n hints = [\n 'Ensure your API key is correctly configured in the adapter or environment variables.',\n 'Check if the API key has expired or been revoked.'\n ];\n } else if (response.status === 404) {\n problem = 'The requested resource or model was not found.';\n hints = [\n 'Verify that the baseUrl is correct (e.g., https://api.openai.com/v1).',\n 'Check if the model name is correct and available for your account.',\n 'Ensure you are not appending extra paths to the baseUrl.'\n ];\n } else if (response.status === 429) {\n problem = 'Rate limit exceeded.';\n hints = [\n 'Wait a few seconds before retrying.',\n 'Check your usage limits and billing status on the provider dashboard.'\n ];\n }\n\n throw new LemuraAdapterError(\n `HTTP ${response.status}: ${errorText}`,\n 'HTTP_ERROR',\n { status: response.status, body: errorText },\n problem,\n hints\n );\n } catch (err) {\n if (err instanceof LemuraAdapterError) throw err;\n\n if (attempts < this.retryConfig.maxRetries) {\n attempts++;\n const delay = this.retryConfig.baseDelayMs * Math.pow(2, attempts - 1);\n await new Promise(resolve => setTimeout(resolve, delay));\n continue;\n }\n\n throw new LemuraAdapterError(\n `Network request failed: ${err instanceof Error ? err.message : String(err)}`,\n 'NETWORK_ERROR',\n err,\n 'A network error occurred while connecting to the provider.',\n [\n 'Check your internet connection.',\n 'Verify that the baseUrl is reachable from your network.',\n 'Check for proxy or firewall settings that might block the request.'\n ]\n );\n }\n }\n throw new LemuraAdapterError(\n 'Max retries exceeded',\n 'MAX_RETRIES',\n undefined,\n 'The request failed after multiple retry attempts.',\n ['Check if the provider service is down or experiencing high load.']\n );\n }\n\n private mapFinishReason(reason: string | null): CompletionResponse['finishReason'] {\n if (!reason) return 'stop';\n const r = reason.toLowerCase();\n if (r === 'tool_calls' || r === 'tool_call') return 'tool_call';\n if (r === 'length' || r === 'max_tokens') return 'max_tokens';\n if (r === 'content_filter' || r === 'error') return 'error';\n return 'stop';\n }\n\n private buildPayload(request: CompletionRequest): unknown {\n const payload: Record<string, unknown> = {\n model: request.model || this.defaultModel,\n messages: request.messages,\n };\n if (request.maxTokens !== undefined) payload.max_tokens = request.maxTokens;\n if (request.temperature !== undefined) payload.temperature = request.temperature;\n if (request.stopSequences?.length) payload.stop = request.stopSequences;\n if (request.stream) payload.stream = true;\n\n if (request.tools && request.tools.length > 0) {\n payload.tools = request.tools.map(t => ({\n type: 'function',\n function: {\n name: t.name,\n description: t.description,\n parameters: t.parameters,\n }\n }));\n }\n\n return payload;\n }\n\n async complete(request: CompletionRequest): Promise<CompletionResponse> {\n const payload = this.buildPayload(request);\n\n const response = await this.fetchWithRetry(`${this.baseUrl}/chat/completions`, {\n method: 'POST',\n body: JSON.stringify(payload)\n });\n\n const data = await response.json();\n const choice = data.choices?.[0];\n if (!choice) {\n throw new LemuraAdapterError('Invalid response format: missing choices', 'INVALID_RESPONSE', data);\n }\n\n const message = choice.message;\n let toolCalls;\n\n if (message.tool_calls && message.tool_calls.length > 0) {\n toolCalls = message.tool_calls.map((tc: any) => ({\n id: tc.id,\n name: tc.function.name,\n arguments: tc.function.arguments,\n }));\n }\n\n return {\n content: message.content || '',\n toolCalls,\n finishReason: this.mapFinishReason(choice.finish_reason),\n usage: {\n promptTokens: data.usage?.prompt_tokens || 0,\n completionTokens: data.usage?.completion_tokens || 0,\n totalTokens: data.usage?.total_tokens || 0,\n },\n rawResponse: data\n };\n }\n\n async *stream(request: CompletionRequest): AsyncIterable<CompletionChunk> {\n const payload = this.buildPayload({ ...request, stream: true });\n\n const response = await this.fetchWithRetry(`${this.baseUrl}/chat/completions`, {\n method: 'POST',\n body: JSON.stringify(payload)\n });\n\n if (!response.body) {\n throw new LemuraAdapterError('Response body is null', 'STREAM_ERROR');\n }\n\n const reader = response.body.getReader();\n const decoder = new TextDecoder('utf-8');\n let buffer = '';\n\n try {\n while (true) {\n const { value, done } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split('\\n');\n buffer = lines.pop() || '';\n\n for (const line of lines) {\n const trimmed = line.trim();\n if (!trimmed || trimmed === 'data: [DONE]') continue;\n if (trimmed.startsWith('data: ')) {\n const jsonStr = trimmed.slice(6);\n let data;\n try {\n data = JSON.parse(jsonStr);\n } catch (err) {\n continue;\n }\n\n const choice = data.choices?.[0];\n if (!choice) continue;\n\n const delta = choice.delta?.content || '';\n const toolCallBlock = choice.delta?.tool_calls?.[0];\n let toolCallDelta;\n\n if (toolCallBlock) {\n toolCallDelta = {\n id: toolCallBlock.id,\n name: toolCallBlock.function?.name,\n arguments: toolCallBlock.function?.arguments,\n };\n }\n\n const isFinished = choice.finish_reason !== null && choice.finish_reason !== undefined;\n\n yield {\n delta,\n finished: isFinished,\n ...(toolCallDelta && { toolCallDelta }),\n ...(isFinished && { finishReason: this.mapFinishReason(choice.finish_reason) })\n };\n }\n }\n }\n } finally {\n reader.releaseLock();\n }\n }\n\n estimateTokens(text: string): number {\n return Math.ceil(text.length / 4);\n }\n\n getModelInfo(): ModelInfo {\n return {\n supportsVision: true,\n supportsTools: true,\n contextWindow: 128000\n };\n }\n\n async healthCheck(): Promise<boolean> {\n try {\n const resp = await this.fetchWithRetry(`${this.baseUrl}/models`, { method: 'GET' });\n return resp.ok;\n } catch {\n return false;\n }\n }\n\n async transcribe(request: TranscriptionRequest): Promise<TranscriptionResponse> {\n const binaryString = atob(request.audioBase64);\n const bytes = new Uint8Array(binaryString.length);\n for (let i = 0; i < binaryString.length; i++) {\n bytes[i] = binaryString.charCodeAt(i);\n }\n const blob = new Blob([bytes], { type: request.mimeType });\n const formData = new FormData();\n formData.append('file', blob, 'audio.webm');\n formData.append('model', 'whisper-1');\n if (request.language) formData.append('language', request.language);\n\n const response = await this.fetchWithRetry(`${this.baseUrl}/audio/transcriptions`, {\n method: 'POST',\n body: formData,\n headers: {\n 'Content-Type': 'unset'\n }\n });\n\n const data = await response.json();\n return {\n transcript: data.text,\n confidence: 1.0, // OpenAI doesn't return confidence in standard response\n language: data.language || request.language || 'en'\n };\n }\n\n async *synthesize(request: SynthesisRequest): AsyncIterable<AudioChunk> {\n const response = await this.fetchWithRetry(`${this.baseUrl}/audio/speech`, {\n method: 'POST',\n body: JSON.stringify({\n model: 'tts-1',\n input: request.text,\n voice: request.voiceId || 'alloy',\n response_format: request.format || 'mp3'\n })\n });\n\n if (!response.body) throw new LemuraAdapterError('No response body for TTS', 'STREAM_ERROR');\n\n const reader = response.body.getReader();\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n if (value) {\n const binary = new TextDecoder('latin1').decode(value);\n yield { audioBase64: btoa(binary) };\n }\n }\n } finally {\n reader.releaseLock();\n }\n }\n\n async describeImage(request: VisionRequest): Promise<VisionResponse> {\n const payload = {\n model: this.defaultModel,\n messages: [\n {\n role: 'user',\n content: [\n { type: 'text', text: request.prompt || 'Describe this image' },\n {\n type: 'image_url',\n image_url: {\n url: `data:image/jpeg;base64,${request.imageBase64}`\n }\n }\n ]\n }\n ]\n };\n\n const response = await this.fetchWithRetry(`${this.baseUrl}/chat/completions`, {\n method: 'POST',\n body: JSON.stringify(payload)\n });\n\n const data = await response.json();\n return {\n description: data.choices[0].message.content,\n objects: [] // OpenAI doesn't return structured objects in standard vision call\n };\n }\n\n async generateImage(request: ImageGenRequest): Promise<ImageGenResponse> {\n const response = await this.fetchWithRetry(`${this.baseUrl}/images/generations`, {\n method: 'POST',\n body: JSON.stringify({\n prompt: request.prompt,\n model: 'dall-e-3',\n n: 1,\n size: request.dimensions || '1024x1024'\n })\n });\n\n const data = await response.json();\n return {\n imageUrl: data.data[0].url,\n revisedPrompt: data.data[0].revised_prompt\n };\n }\n}\n"]}
1
+ {"version":3,"sources":["../../src/types/errors.ts","../../src/adapters/OpenAICompatibleAdapter.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Base class for all custom errors thrown by lemura.\n *\n * @example\n * throw new LemuraError('Something went wrong', 'UNKNOWN_ERROR');\n */\nexport class LemuraError extends Error {\n /**\n * @param message - The error message\n * @param code - The error code for programmatic handling\n * @param problem - A clear description of the problem for the end user\n * @param hints - A list of suggestions to resolve the issue\n */\n constructor(\n message: string,\n public readonly code: string,\n public readonly problem?: string,\n public readonly hints: string[] = []\n ) {\n super(message);\n this.name = 'LemuraError';\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/** Error thrown when context exceeds max tokens and cannot be compressed further */\nexport class LemuraContextOverflowError extends LemuraError {\n constructor(message: string) {\n super(message, 'CONTEXT_OVERFLOW');\n this.name = 'LemuraContextOverflowError';\n }\n}\n\n/** Error thrown when a requested tool is not found in the registry */\nexport class LemuraToolNotFoundError extends LemuraError {\n constructor(message: string) {\n super(message, 'TOOL_NOT_FOUND');\n this.name = 'LemuraToolNotFoundError';\n }\n}\n\n/** Error thrown when an adapter encounters an API or formatting issue */\nexport class LemuraAdapterError extends LemuraError {\n constructor(\n message: string,\n code = 'ADAPTER_ERROR',\n public cause?: any,\n problem?: string,\n hints: string[] = []\n ) {\n super(message, code, problem, hints);\n this.name = 'LemuraAdapterError';\n }\n}\n\n/** Error thrown when a skill cannot be parsed or injected */\nexport class LemuraSkillInjectionError extends LemuraError {\n constructor(message: string) {\n super(message, 'SKILL_INJECTION_FAILED');\n this.name = 'LemuraSkillInjectionError';\n }\n}\n\n/** Error thrown when the ReAct loop exceeds the configured max iterations */\nexport class LemuraMaxIterationsError extends LemuraError {\n constructor(message: string) {\n super(message, 'MAX_ITERATIONS_EXCEEDED');\n this.name = 'LemuraMaxIterationsError';\n }\n}\n\n/** Error thrown when tool parameters fail JSON schema validation */\nexport class LemuraToolValidationError extends LemuraError {\n constructor(message: string) {\n super(message, 'TOOL_VALIDATION_FAILED');\n this.name = 'LemuraToolValidationError';\n }\n}\n\n/** Error thrown when a tool execute function exceeds its timeout */\nexport class LemuraToolTimeoutError extends LemuraError {\n constructor(message: string) {\n super(message, 'TOOL_TIMEOUT');\n this.name = 'LemuraToolTimeoutError';\n }\n}\n\n/** Base error thrown for any MCP server communication failure */\nexport class LemuraMCPError extends LemuraError {\n constructor(message: string, code = 'MCP_ERROR', problem?: string, hints: string[] = []) {\n super(message, code, problem, hints);\n this.name = 'LemuraMCPError';\n }\n}\n\n/** Error thrown when an MCP server cannot be connected to (spawn failure, network error, init failure) */\nexport class LemuraMCPConnectionError extends LemuraMCPError {\n constructor(message: string, problem?: string, hints: string[] = []) {\n super(message, 'MCP_CONNECTION_FAILED', problem, hints);\n this.name = 'LemuraMCPConnectionError';\n }\n}\n\n/** Error thrown when a call to an MCP server tool exceeds the configured timeout */\nexport class LemuraMCPTimeoutError extends LemuraMCPError {\n constructor(message: string) {\n super(message, 'MCP_TOOL_TIMEOUT');\n this.name = 'LemuraMCPTimeoutError';\n }\n}\n","import {\n IProviderAdapter,\n CompletionRequest,\n CompletionResponse,\n CompletionChunk,\n TranscriptionRequest,\n TranscriptionResponse,\n SynthesisRequest,\n AudioChunk,\n VisionRequest,\n VisionResponse,\n ImageGenRequest,\n ImageGenResponse,\n ModelInfo,\n LemuraAdapterError,\n} from '../types/index.js';\n\nexport interface RetryConfig {\n maxRetries: number;\n baseDelayMs: number;\n}\n\nexport interface OpenAICompatibleAdapterConfig {\n baseUrl?: string;\n apiKey?: string;\n defaultModel?: string;\n defaultHeaders?: Record<string, string>;\n timeout?: number;\n retry?: RetryConfig;\n}\n\n/**\n * Reference implementation of an OpenAI-compatible provider adapter.\n */\nexport class OpenAICompatibleAdapter implements IProviderAdapter {\n readonly name = 'openai_compatible';\n readonly version = '1.2.0';\n\n private baseUrl: string;\n private apiKey: string;\n private defaultModel: string;\n private defaultHeaders: Record<string, string>;\n private timeoutMs: number;\n private retryConfig: RetryConfig;\n\n constructor(config: OpenAICompatibleAdapterConfig = {}) {\n this.baseUrl = (\n config.baseUrl ??\n process.env.LEMURA_BASE_URL ??\n process.env.OPENAI_BASE_URL ??\n 'https://api.openai.com/v1'\n ).replace(/\\/$/, '');\n\n this.apiKey = config.apiKey ?? process.env.LEMURA_API_KEY ?? process.env.OPENAI_API_KEY ?? '';\n this.defaultModel = config.defaultModel ?? process.env.LEMURA_MODEL ?? process.env.OPENAI_MODEL ?? 'gpt-3.5-turbo';\n\n this.defaultHeaders = config.defaultHeaders || {};\n this.timeoutMs = config.timeout || 30000;\n this.retryConfig = config.retry || { maxRetries: 2, baseDelayMs: 1000 };\n }\n\n private async fetchWithRetry(url: string, init: RequestInit): Promise<Response> {\n let attempts = 0;\n while (attempts <= this.retryConfig.maxRetries) {\n try {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeoutMs);\n\n const headers: Record<string, string> = {\n 'Authorization': `Bearer ${this.apiKey}`,\n ...this.defaultHeaders,\n };\n\n if (init.headers) {\n Object.assign(headers, init.headers);\n }\n\n // Don't set Content-Type if it's 'unset' (for FormData)\n if (headers['Content-Type'] === 'unset') {\n delete headers['Content-Type'];\n } else if (!headers['Content-Type']) {\n headers['Content-Type'] = 'application/json';\n }\n\n const response = await fetch(url, {\n ...init,\n signal: controller.signal,\n headers,\n });\n\n clearTimeout(timeoutId);\n\n if (response.ok) return response;\n\n // Retry on 429 and 503\n if ((response.status === 429 || response.status === 503) && attempts < this.retryConfig.maxRetries) {\n attempts++;\n const delay = this.retryConfig.baseDelayMs * Math.pow(2, attempts - 1);\n await new Promise(resolve => setTimeout(resolve, delay));\n continue;\n }\n\n const errorText = await response.text().catch(() => '');\n let problem = 'The server replied with an error during the API call.';\n let hints = ['Check the API documentation for the provider you are using.'];\n\n if (response.status === 401) {\n problem = 'Authentication failed. The API key is invalid or missing.';\n hints = [\n 'Ensure your API key is correctly configured in the adapter or environment variables.',\n 'Check if the API key has expired or been revoked.'\n ];\n } else if (response.status === 404) {\n problem = 'The requested resource or model was not found.';\n hints = [\n 'Verify that the baseUrl is correct (e.g., https://api.openai.com/v1).',\n 'Check if the model name is correct and available for your account.',\n 'Ensure you are not appending extra paths to the baseUrl.'\n ];\n } else if (response.status === 429) {\n problem = 'Rate limit exceeded.';\n hints = [\n 'Wait a few seconds before retrying.',\n 'Check your usage limits and billing status on the provider dashboard.'\n ];\n }\n\n throw new LemuraAdapterError(\n `HTTP ${response.status}: ${errorText}`,\n 'HTTP_ERROR',\n { status: response.status, body: errorText },\n problem,\n hints\n );\n } catch (err) {\n if (err instanceof LemuraAdapterError) throw err;\n\n if (attempts < this.retryConfig.maxRetries) {\n attempts++;\n const delay = this.retryConfig.baseDelayMs * Math.pow(2, attempts - 1);\n await new Promise(resolve => setTimeout(resolve, delay));\n continue;\n }\n\n throw new LemuraAdapterError(\n `Network request failed: ${err instanceof Error ? err.message : String(err)}`,\n 'NETWORK_ERROR',\n err,\n 'A network error occurred while connecting to the provider.',\n [\n 'Check your internet connection.',\n 'Verify that the baseUrl is reachable from your network.',\n 'Check for proxy or firewall settings that might block the request.'\n ]\n );\n }\n }\n throw new LemuraAdapterError(\n 'Max retries exceeded',\n 'MAX_RETRIES',\n undefined,\n 'The request failed after multiple retry attempts.',\n ['Check if the provider service is down or experiencing high load.']\n );\n }\n\n private mapFinishReason(reason: string | null): CompletionResponse['finishReason'] {\n if (!reason) return 'stop';\n const r = reason.toLowerCase();\n if (r === 'tool_calls' || r === 'tool_call') return 'tool_call';\n if (r === 'length' || r === 'max_tokens') return 'max_tokens';\n if (r === 'content_filter' || r === 'error') return 'error';\n return 'stop';\n }\n\n private buildPayload(request: CompletionRequest): unknown {\n const payload: Record<string, unknown> = {\n model: request.model || this.defaultModel,\n messages: request.messages,\n };\n if (request.maxTokens !== undefined) payload.max_tokens = request.maxTokens;\n if (request.temperature !== undefined) payload.temperature = request.temperature;\n if (request.stopSequences?.length) payload.stop = request.stopSequences;\n if (request.stream) payload.stream = true;\n\n if (request.tools && request.tools.length > 0) {\n payload.tools = request.tools.map(t => ({\n type: 'function',\n function: {\n name: t.name,\n description: t.description,\n parameters: t.parameters,\n }\n }));\n }\n\n return payload;\n }\n\n async complete(request: CompletionRequest): Promise<CompletionResponse> {\n const payload = this.buildPayload(request);\n\n const response = await this.fetchWithRetry(`${this.baseUrl}/chat/completions`, {\n method: 'POST',\n body: JSON.stringify(payload)\n });\n\n const data = await response.json();\n const choice = data.choices?.[0];\n if (!choice) {\n throw new LemuraAdapterError('Invalid response format: missing choices', 'INVALID_RESPONSE', data);\n }\n\n const message = choice.message;\n let toolCalls;\n\n if (message.tool_calls && message.tool_calls.length > 0) {\n toolCalls = message.tool_calls.map((tc: any) => ({\n id: tc.id,\n name: tc.function.name,\n arguments: tc.function.arguments,\n }));\n }\n\n return {\n content: message.content || '',\n toolCalls,\n finishReason: this.mapFinishReason(choice.finish_reason),\n usage: {\n promptTokens: data.usage?.prompt_tokens || 0,\n completionTokens: data.usage?.completion_tokens || 0,\n totalTokens: data.usage?.total_tokens || 0,\n },\n rawResponse: data\n };\n }\n\n async *stream(request: CompletionRequest): AsyncIterable<CompletionChunk> {\n const payload = this.buildPayload({ ...request, stream: true });\n\n const response = await this.fetchWithRetry(`${this.baseUrl}/chat/completions`, {\n method: 'POST',\n body: JSON.stringify(payload)\n });\n\n if (!response.body) {\n throw new LemuraAdapterError('Response body is null', 'STREAM_ERROR');\n }\n\n const reader = response.body.getReader();\n const decoder = new TextDecoder('utf-8');\n let buffer = '';\n\n try {\n while (true) {\n const { value, done } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split('\\n');\n buffer = lines.pop() || '';\n\n for (const line of lines) {\n const trimmed = line.trim();\n if (!trimmed || trimmed === 'data: [DONE]') continue;\n if (trimmed.startsWith('data: ')) {\n const jsonStr = trimmed.slice(6);\n let data;\n try {\n data = JSON.parse(jsonStr);\n } catch (err) {\n continue;\n }\n\n const choice = data.choices?.[0];\n if (!choice) continue;\n\n const delta = choice.delta?.content || '';\n const toolCallBlock = choice.delta?.tool_calls?.[0];\n let toolCallDelta;\n\n if (toolCallBlock) {\n toolCallDelta = {\n id: toolCallBlock.id,\n name: toolCallBlock.function?.name,\n arguments: toolCallBlock.function?.arguments,\n };\n }\n\n const isFinished = choice.finish_reason !== null && choice.finish_reason !== undefined;\n\n yield {\n delta,\n finished: isFinished,\n ...(toolCallDelta && { toolCallDelta }),\n ...(isFinished && { finishReason: this.mapFinishReason(choice.finish_reason) })\n };\n }\n }\n }\n } finally {\n reader.releaseLock();\n }\n }\n\n estimateTokens(text: string): number {\n return Math.ceil(text.length / 4);\n }\n\n getModelInfo(): ModelInfo {\n return {\n supportsVision: true,\n supportsTools: true,\n contextWindow: 128000\n };\n }\n\n async healthCheck(): Promise<boolean> {\n try {\n const resp = await this.fetchWithRetry(`${this.baseUrl}/models`, { method: 'GET' });\n return resp.ok;\n } catch {\n return false;\n }\n }\n\n async transcribe(request: TranscriptionRequest): Promise<TranscriptionResponse> {\n const binaryString = atob(request.audioBase64);\n const bytes = new Uint8Array(binaryString.length);\n for (let i = 0; i < binaryString.length; i++) {\n bytes[i] = binaryString.charCodeAt(i);\n }\n const blob = new Blob([bytes], { type: request.mimeType });\n const formData = new FormData();\n formData.append('file', blob, 'audio.webm');\n formData.append('model', request.model || 'whisper-1');\n if (request.language) formData.append('language', request.language);\n\n const response = await this.fetchWithRetry(`${this.baseUrl}/audio/transcriptions`, {\n method: 'POST',\n body: formData,\n headers: {\n 'Content-Type': 'unset'\n }\n });\n\n const data = await response.json();\n return {\n transcript: data.text,\n confidence: 1.0, // OpenAI doesn't return confidence in standard response\n language: data.language || request.language || 'en'\n };\n }\n\n async *synthesize(request: SynthesisRequest): AsyncIterable<AudioChunk> {\n const response = await this.fetchWithRetry(`${this.baseUrl}/audio/speech`, {\n method: 'POST',\n body: JSON.stringify({\n model: request.model || 'tts-1',\n input: request.text,\n voice: request.voiceId || 'alloy',\n response_format: request.format || 'mp3'\n })\n });\n\n if (!response.body) throw new LemuraAdapterError('No response body for TTS', 'STREAM_ERROR');\n\n const reader = response.body.getReader();\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n if (value) {\n const binary = new TextDecoder('latin1').decode(value);\n yield { audioBase64: btoa(binary) };\n }\n }\n } finally {\n reader.releaseLock();\n }\n }\n\n async describeImage(request: VisionRequest): Promise<VisionResponse> {\n const payload = {\n model: request.model || this.defaultModel,\n messages: [\n {\n role: 'user',\n content: [\n { type: 'text', text: request.prompt || 'Describe this image' },\n {\n type: 'image_url',\n image_url: {\n url: `data:image/jpeg;base64,${request.imageBase64}`\n }\n }\n ]\n }\n ]\n };\n\n const response = await this.fetchWithRetry(`${this.baseUrl}/chat/completions`, {\n method: 'POST',\n body: JSON.stringify(payload)\n });\n\n const data = await response.json();\n return {\n description: data.choices[0].message.content,\n objects: [] // OpenAI doesn't return structured objects in standard vision call\n };\n }\n\n async generateImage(request: ImageGenRequest): Promise<ImageGenResponse> {\n const response = await this.fetchWithRetry(`${this.baseUrl}/images/generations`, {\n method: 'POST',\n body: JSON.stringify({\n prompt: request.prompt,\n model: request.model || 'dall-e-3',\n n: 1,\n size: request.dimensions || '1024x1024'\n })\n });\n\n const data = await response.json();\n return {\n imageUrl: data.data[0].url,\n revisedPrompt: data.data[0].revised_prompt\n };\n }\n}\n"]}
@@ -26,7 +26,7 @@ var LemuraAdapterError = class extends LemuraError {
26
26
  // src/adapters/OpenAICompatibleAdapter.ts
27
27
  var OpenAICompatibleAdapter = class {
28
28
  name = "openai_compatible";
29
- version = "1.0.0";
29
+ version = "1.2.0";
30
30
  baseUrl;
31
31
  apiKey;
32
32
  defaultModel;
@@ -275,7 +275,7 @@ var OpenAICompatibleAdapter = class {
275
275
  const blob = new Blob([bytes], { type: request.mimeType });
276
276
  const formData = new FormData();
277
277
  formData.append("file", blob, "audio.webm");
278
- formData.append("model", "whisper-1");
278
+ formData.append("model", request.model || "whisper-1");
279
279
  if (request.language) formData.append("language", request.language);
280
280
  const response = await this.fetchWithRetry(`${this.baseUrl}/audio/transcriptions`, {
281
281
  method: "POST",
@@ -296,7 +296,7 @@ var OpenAICompatibleAdapter = class {
296
296
  const response = await this.fetchWithRetry(`${this.baseUrl}/audio/speech`, {
297
297
  method: "POST",
298
298
  body: JSON.stringify({
299
- model: "tts-1",
299
+ model: request.model || "tts-1",
300
300
  input: request.text,
301
301
  voice: request.voiceId || "alloy",
302
302
  response_format: request.format || "mp3"
@@ -319,7 +319,7 @@ var OpenAICompatibleAdapter = class {
319
319
  }
320
320
  async describeImage(request) {
321
321
  const payload = {
322
- model: this.defaultModel,
322
+ model: request.model || this.defaultModel,
323
323
  messages: [
324
324
  {
325
325
  role: "user",
@@ -351,7 +351,7 @@ var OpenAICompatibleAdapter = class {
351
351
  method: "POST",
352
352
  body: JSON.stringify({
353
353
  prompt: request.prompt,
354
- model: "dall-e-3",
354
+ model: request.model || "dall-e-3",
355
355
  n: 1,
356
356
  size: request.dimensions || "1024x1024"
357
357
  })
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/types/errors.ts","../../src/adapters/OpenAICompatibleAdapter.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["/**\n * Base class for all custom errors thrown by lemura.\n *\n * @example\n * throw new LemuraError('Something went wrong', 'UNKNOWN_ERROR');\n */\nexport class LemuraError extends Error {\n /**\n * @param message - The error message\n * @param code - The error code for programmatic handling\n * @param problem - A clear description of the problem for the end user\n * @param hints - A list of suggestions to resolve the issue\n */\n constructor(\n message: string,\n public readonly code: string,\n public readonly problem?: string,\n public readonly hints: string[] = []\n ) {\n super(message);\n this.name = 'LemuraError';\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/** Error thrown when context exceeds max tokens and cannot be compressed further */\nexport class LemuraContextOverflowError extends LemuraError {\n constructor(message: string) {\n super(message, 'CONTEXT_OVERFLOW');\n this.name = 'LemuraContextOverflowError';\n }\n}\n\n/** Error thrown when a requested tool is not found in the registry */\nexport class LemuraToolNotFoundError extends LemuraError {\n constructor(message: string) {\n super(message, 'TOOL_NOT_FOUND');\n this.name = 'LemuraToolNotFoundError';\n }\n}\n\n/** Error thrown when an adapter encounters an API or formatting issue */\nexport class LemuraAdapterError extends LemuraError {\n constructor(\n message: string,\n code = 'ADAPTER_ERROR',\n public cause?: any,\n problem?: string,\n hints: string[] = []\n ) {\n super(message, code, problem, hints);\n this.name = 'LemuraAdapterError';\n }\n}\n\n/** Error thrown when a skill cannot be parsed or injected */\nexport class LemuraSkillInjectionError extends LemuraError {\n constructor(message: string) {\n super(message, 'SKILL_INJECTION_FAILED');\n this.name = 'LemuraSkillInjectionError';\n }\n}\n\n/** Error thrown when the ReAct loop exceeds the configured max iterations */\nexport class LemuraMaxIterationsError extends LemuraError {\n constructor(message: string) {\n super(message, 'MAX_ITERATIONS_EXCEEDED');\n this.name = 'LemuraMaxIterationsError';\n }\n}\n\n/** Error thrown when tool parameters fail JSON schema validation */\nexport class LemuraToolValidationError extends LemuraError {\n constructor(message: string) {\n super(message, 'TOOL_VALIDATION_FAILED');\n this.name = 'LemuraToolValidationError';\n }\n}\n\n/** Error thrown when a tool execute function exceeds its timeout */\nexport class LemuraToolTimeoutError extends LemuraError {\n constructor(message: string) {\n super(message, 'TOOL_TIMEOUT');\n this.name = 'LemuraToolTimeoutError';\n }\n}\n","import {\n IProviderAdapter,\n CompletionRequest,\n CompletionResponse,\n CompletionChunk,\n TranscriptionRequest,\n TranscriptionResponse,\n SynthesisRequest,\n AudioChunk,\n VisionRequest,\n VisionResponse,\n ImageGenRequest,\n ImageGenResponse,\n ModelInfo,\n LemuraAdapterError,\n} from '../types/index.js';\n\nexport interface RetryConfig {\n maxRetries: number;\n baseDelayMs: number;\n}\n\nexport interface OpenAICompatibleAdapterConfig {\n baseUrl?: string;\n apiKey?: string;\n defaultModel?: string;\n defaultHeaders?: Record<string, string>;\n timeout?: number;\n retry?: RetryConfig;\n}\n\n/**\n * Reference implementation of an OpenAI-compatible provider adapter.\n */\nexport class OpenAICompatibleAdapter implements IProviderAdapter {\n readonly name = 'openai_compatible';\n readonly version = '1.0.0';\n\n private baseUrl: string;\n private apiKey: string;\n private defaultModel: string;\n private defaultHeaders: Record<string, string>;\n private timeoutMs: number;\n private retryConfig: RetryConfig;\n\n constructor(config: OpenAICompatibleAdapterConfig = {}) {\n this.baseUrl = (\n config.baseUrl ??\n process.env.LEMURA_BASE_URL ??\n process.env.OPENAI_BASE_URL ??\n 'https://api.openai.com/v1'\n ).replace(/\\/$/, '');\n\n this.apiKey = config.apiKey ?? process.env.LEMURA_API_KEY ?? process.env.OPENAI_API_KEY ?? '';\n this.defaultModel = config.defaultModel ?? process.env.LEMURA_MODEL ?? process.env.OPENAI_MODEL ?? 'gpt-3.5-turbo';\n\n this.defaultHeaders = config.defaultHeaders || {};\n this.timeoutMs = config.timeout || 30000;\n this.retryConfig = config.retry || { maxRetries: 2, baseDelayMs: 1000 };\n }\n\n private async fetchWithRetry(url: string, init: RequestInit): Promise<Response> {\n let attempts = 0;\n while (attempts <= this.retryConfig.maxRetries) {\n try {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeoutMs);\n\n const headers: Record<string, string> = {\n 'Authorization': `Bearer ${this.apiKey}`,\n ...this.defaultHeaders,\n };\n\n if (init.headers) {\n Object.assign(headers, init.headers);\n }\n\n // Don't set Content-Type if it's 'unset' (for FormData)\n if (headers['Content-Type'] === 'unset') {\n delete headers['Content-Type'];\n } else if (!headers['Content-Type']) {\n headers['Content-Type'] = 'application/json';\n }\n\n const response = await fetch(url, {\n ...init,\n signal: controller.signal,\n headers,\n });\n\n clearTimeout(timeoutId);\n\n if (response.ok) return response;\n\n // Retry on 429 and 503\n if ((response.status === 429 || response.status === 503) && attempts < this.retryConfig.maxRetries) {\n attempts++;\n const delay = this.retryConfig.baseDelayMs * Math.pow(2, attempts - 1);\n await new Promise(resolve => setTimeout(resolve, delay));\n continue;\n }\n\n const errorText = await response.text().catch(() => '');\n let problem = 'The server replied with an error during the API call.';\n let hints = ['Check the API documentation for the provider you are using.'];\n\n if (response.status === 401) {\n problem = 'Authentication failed. The API key is invalid or missing.';\n hints = [\n 'Ensure your API key is correctly configured in the adapter or environment variables.',\n 'Check if the API key has expired or been revoked.'\n ];\n } else if (response.status === 404) {\n problem = 'The requested resource or model was not found.';\n hints = [\n 'Verify that the baseUrl is correct (e.g., https://api.openai.com/v1).',\n 'Check if the model name is correct and available for your account.',\n 'Ensure you are not appending extra paths to the baseUrl.'\n ];\n } else if (response.status === 429) {\n problem = 'Rate limit exceeded.';\n hints = [\n 'Wait a few seconds before retrying.',\n 'Check your usage limits and billing status on the provider dashboard.'\n ];\n }\n\n throw new LemuraAdapterError(\n `HTTP ${response.status}: ${errorText}`,\n 'HTTP_ERROR',\n { status: response.status, body: errorText },\n problem,\n hints\n );\n } catch (err) {\n if (err instanceof LemuraAdapterError) throw err;\n\n if (attempts < this.retryConfig.maxRetries) {\n attempts++;\n const delay = this.retryConfig.baseDelayMs * Math.pow(2, attempts - 1);\n await new Promise(resolve => setTimeout(resolve, delay));\n continue;\n }\n\n throw new LemuraAdapterError(\n `Network request failed: ${err instanceof Error ? err.message : String(err)}`,\n 'NETWORK_ERROR',\n err,\n 'A network error occurred while connecting to the provider.',\n [\n 'Check your internet connection.',\n 'Verify that the baseUrl is reachable from your network.',\n 'Check for proxy or firewall settings that might block the request.'\n ]\n );\n }\n }\n throw new LemuraAdapterError(\n 'Max retries exceeded',\n 'MAX_RETRIES',\n undefined,\n 'The request failed after multiple retry attempts.',\n ['Check if the provider service is down or experiencing high load.']\n );\n }\n\n private mapFinishReason(reason: string | null): CompletionResponse['finishReason'] {\n if (!reason) return 'stop';\n const r = reason.toLowerCase();\n if (r === 'tool_calls' || r === 'tool_call') return 'tool_call';\n if (r === 'length' || r === 'max_tokens') return 'max_tokens';\n if (r === 'content_filter' || r === 'error') return 'error';\n return 'stop';\n }\n\n private buildPayload(request: CompletionRequest): unknown {\n const payload: Record<string, unknown> = {\n model: request.model || this.defaultModel,\n messages: request.messages,\n };\n if (request.maxTokens !== undefined) payload.max_tokens = request.maxTokens;\n if (request.temperature !== undefined) payload.temperature = request.temperature;\n if (request.stopSequences?.length) payload.stop = request.stopSequences;\n if (request.stream) payload.stream = true;\n\n if (request.tools && request.tools.length > 0) {\n payload.tools = request.tools.map(t => ({\n type: 'function',\n function: {\n name: t.name,\n description: t.description,\n parameters: t.parameters,\n }\n }));\n }\n\n return payload;\n }\n\n async complete(request: CompletionRequest): Promise<CompletionResponse> {\n const payload = this.buildPayload(request);\n\n const response = await this.fetchWithRetry(`${this.baseUrl}/chat/completions`, {\n method: 'POST',\n body: JSON.stringify(payload)\n });\n\n const data = await response.json();\n const choice = data.choices?.[0];\n if (!choice) {\n throw new LemuraAdapterError('Invalid response format: missing choices', 'INVALID_RESPONSE', data);\n }\n\n const message = choice.message;\n let toolCalls;\n\n if (message.tool_calls && message.tool_calls.length > 0) {\n toolCalls = message.tool_calls.map((tc: any) => ({\n id: tc.id,\n name: tc.function.name,\n arguments: tc.function.arguments,\n }));\n }\n\n return {\n content: message.content || '',\n toolCalls,\n finishReason: this.mapFinishReason(choice.finish_reason),\n usage: {\n promptTokens: data.usage?.prompt_tokens || 0,\n completionTokens: data.usage?.completion_tokens || 0,\n totalTokens: data.usage?.total_tokens || 0,\n },\n rawResponse: data\n };\n }\n\n async *stream(request: CompletionRequest): AsyncIterable<CompletionChunk> {\n const payload = this.buildPayload({ ...request, stream: true });\n\n const response = await this.fetchWithRetry(`${this.baseUrl}/chat/completions`, {\n method: 'POST',\n body: JSON.stringify(payload)\n });\n\n if (!response.body) {\n throw new LemuraAdapterError('Response body is null', 'STREAM_ERROR');\n }\n\n const reader = response.body.getReader();\n const decoder = new TextDecoder('utf-8');\n let buffer = '';\n\n try {\n while (true) {\n const { value, done } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split('\\n');\n buffer = lines.pop() || '';\n\n for (const line of lines) {\n const trimmed = line.trim();\n if (!trimmed || trimmed === 'data: [DONE]') continue;\n if (trimmed.startsWith('data: ')) {\n const jsonStr = trimmed.slice(6);\n let data;\n try {\n data = JSON.parse(jsonStr);\n } catch (err) {\n continue;\n }\n\n const choice = data.choices?.[0];\n if (!choice) continue;\n\n const delta = choice.delta?.content || '';\n const toolCallBlock = choice.delta?.tool_calls?.[0];\n let toolCallDelta;\n\n if (toolCallBlock) {\n toolCallDelta = {\n id: toolCallBlock.id,\n name: toolCallBlock.function?.name,\n arguments: toolCallBlock.function?.arguments,\n };\n }\n\n const isFinished = choice.finish_reason !== null && choice.finish_reason !== undefined;\n\n yield {\n delta,\n finished: isFinished,\n ...(toolCallDelta && { toolCallDelta }),\n ...(isFinished && { finishReason: this.mapFinishReason(choice.finish_reason) })\n };\n }\n }\n }\n } finally {\n reader.releaseLock();\n }\n }\n\n estimateTokens(text: string): number {\n return Math.ceil(text.length / 4);\n }\n\n getModelInfo(): ModelInfo {\n return {\n supportsVision: true,\n supportsTools: true,\n contextWindow: 128000\n };\n }\n\n async healthCheck(): Promise<boolean> {\n try {\n const resp = await this.fetchWithRetry(`${this.baseUrl}/models`, { method: 'GET' });\n return resp.ok;\n } catch {\n return false;\n }\n }\n\n async transcribe(request: TranscriptionRequest): Promise<TranscriptionResponse> {\n const binaryString = atob(request.audioBase64);\n const bytes = new Uint8Array(binaryString.length);\n for (let i = 0; i < binaryString.length; i++) {\n bytes[i] = binaryString.charCodeAt(i);\n }\n const blob = new Blob([bytes], { type: request.mimeType });\n const formData = new FormData();\n formData.append('file', blob, 'audio.webm');\n formData.append('model', 'whisper-1');\n if (request.language) formData.append('language', request.language);\n\n const response = await this.fetchWithRetry(`${this.baseUrl}/audio/transcriptions`, {\n method: 'POST',\n body: formData,\n headers: {\n 'Content-Type': 'unset'\n }\n });\n\n const data = await response.json();\n return {\n transcript: data.text,\n confidence: 1.0, // OpenAI doesn't return confidence in standard response\n language: data.language || request.language || 'en'\n };\n }\n\n async *synthesize(request: SynthesisRequest): AsyncIterable<AudioChunk> {\n const response = await this.fetchWithRetry(`${this.baseUrl}/audio/speech`, {\n method: 'POST',\n body: JSON.stringify({\n model: 'tts-1',\n input: request.text,\n voice: request.voiceId || 'alloy',\n response_format: request.format || 'mp3'\n })\n });\n\n if (!response.body) throw new LemuraAdapterError('No response body for TTS', 'STREAM_ERROR');\n\n const reader = response.body.getReader();\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n if (value) {\n const binary = new TextDecoder('latin1').decode(value);\n yield { audioBase64: btoa(binary) };\n }\n }\n } finally {\n reader.releaseLock();\n }\n }\n\n async describeImage(request: VisionRequest): Promise<VisionResponse> {\n const payload = {\n model: this.defaultModel,\n messages: [\n {\n role: 'user',\n content: [\n { type: 'text', text: request.prompt || 'Describe this image' },\n {\n type: 'image_url',\n image_url: {\n url: `data:image/jpeg;base64,${request.imageBase64}`\n }\n }\n ]\n }\n ]\n };\n\n const response = await this.fetchWithRetry(`${this.baseUrl}/chat/completions`, {\n method: 'POST',\n body: JSON.stringify(payload)\n });\n\n const data = await response.json();\n return {\n description: data.choices[0].message.content,\n objects: [] // OpenAI doesn't return structured objects in standard vision call\n };\n }\n\n async generateImage(request: ImageGenRequest): Promise<ImageGenResponse> {\n const response = await this.fetchWithRetry(`${this.baseUrl}/images/generations`, {\n method: 'POST',\n body: JSON.stringify({\n prompt: request.prompt,\n model: 'dall-e-3',\n n: 1,\n size: request.dimensions || '1024x1024'\n })\n });\n\n const data = await response.json();\n return {\n imageUrl: data.data[0].url,\n revisedPrompt: data.data[0].revised_prompt\n };\n }\n}\n"]}
1
+ {"version":3,"sources":["../../src/types/errors.ts","../../src/adapters/OpenAICompatibleAdapter.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["/**\n * Base class for all custom errors thrown by lemura.\n *\n * @example\n * throw new LemuraError('Something went wrong', 'UNKNOWN_ERROR');\n */\nexport class LemuraError extends Error {\n /**\n * @param message - The error message\n * @param code - The error code for programmatic handling\n * @param problem - A clear description of the problem for the end user\n * @param hints - A list of suggestions to resolve the issue\n */\n constructor(\n message: string,\n public readonly code: string,\n public readonly problem?: string,\n public readonly hints: string[] = []\n ) {\n super(message);\n this.name = 'LemuraError';\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/** Error thrown when context exceeds max tokens and cannot be compressed further */\nexport class LemuraContextOverflowError extends LemuraError {\n constructor(message: string) {\n super(message, 'CONTEXT_OVERFLOW');\n this.name = 'LemuraContextOverflowError';\n }\n}\n\n/** Error thrown when a requested tool is not found in the registry */\nexport class LemuraToolNotFoundError extends LemuraError {\n constructor(message: string) {\n super(message, 'TOOL_NOT_FOUND');\n this.name = 'LemuraToolNotFoundError';\n }\n}\n\n/** Error thrown when an adapter encounters an API or formatting issue */\nexport class LemuraAdapterError extends LemuraError {\n constructor(\n message: string,\n code = 'ADAPTER_ERROR',\n public cause?: any,\n problem?: string,\n hints: string[] = []\n ) {\n super(message, code, problem, hints);\n this.name = 'LemuraAdapterError';\n }\n}\n\n/** Error thrown when a skill cannot be parsed or injected */\nexport class LemuraSkillInjectionError extends LemuraError {\n constructor(message: string) {\n super(message, 'SKILL_INJECTION_FAILED');\n this.name = 'LemuraSkillInjectionError';\n }\n}\n\n/** Error thrown when the ReAct loop exceeds the configured max iterations */\nexport class LemuraMaxIterationsError extends LemuraError {\n constructor(message: string) {\n super(message, 'MAX_ITERATIONS_EXCEEDED');\n this.name = 'LemuraMaxIterationsError';\n }\n}\n\n/** Error thrown when tool parameters fail JSON schema validation */\nexport class LemuraToolValidationError extends LemuraError {\n constructor(message: string) {\n super(message, 'TOOL_VALIDATION_FAILED');\n this.name = 'LemuraToolValidationError';\n }\n}\n\n/** Error thrown when a tool execute function exceeds its timeout */\nexport class LemuraToolTimeoutError extends LemuraError {\n constructor(message: string) {\n super(message, 'TOOL_TIMEOUT');\n this.name = 'LemuraToolTimeoutError';\n }\n}\n\n/** Base error thrown for any MCP server communication failure */\nexport class LemuraMCPError extends LemuraError {\n constructor(message: string, code = 'MCP_ERROR', problem?: string, hints: string[] = []) {\n super(message, code, problem, hints);\n this.name = 'LemuraMCPError';\n }\n}\n\n/** Error thrown when an MCP server cannot be connected to (spawn failure, network error, init failure) */\nexport class LemuraMCPConnectionError extends LemuraMCPError {\n constructor(message: string, problem?: string, hints: string[] = []) {\n super(message, 'MCP_CONNECTION_FAILED', problem, hints);\n this.name = 'LemuraMCPConnectionError';\n }\n}\n\n/** Error thrown when a call to an MCP server tool exceeds the configured timeout */\nexport class LemuraMCPTimeoutError extends LemuraMCPError {\n constructor(message: string) {\n super(message, 'MCP_TOOL_TIMEOUT');\n this.name = 'LemuraMCPTimeoutError';\n }\n}\n","import {\n IProviderAdapter,\n CompletionRequest,\n CompletionResponse,\n CompletionChunk,\n TranscriptionRequest,\n TranscriptionResponse,\n SynthesisRequest,\n AudioChunk,\n VisionRequest,\n VisionResponse,\n ImageGenRequest,\n ImageGenResponse,\n ModelInfo,\n LemuraAdapterError,\n} from '../types/index.js';\n\nexport interface RetryConfig {\n maxRetries: number;\n baseDelayMs: number;\n}\n\nexport interface OpenAICompatibleAdapterConfig {\n baseUrl?: string;\n apiKey?: string;\n defaultModel?: string;\n defaultHeaders?: Record<string, string>;\n timeout?: number;\n retry?: RetryConfig;\n}\n\n/**\n * Reference implementation of an OpenAI-compatible provider adapter.\n */\nexport class OpenAICompatibleAdapter implements IProviderAdapter {\n readonly name = 'openai_compatible';\n readonly version = '1.2.0';\n\n private baseUrl: string;\n private apiKey: string;\n private defaultModel: string;\n private defaultHeaders: Record<string, string>;\n private timeoutMs: number;\n private retryConfig: RetryConfig;\n\n constructor(config: OpenAICompatibleAdapterConfig = {}) {\n this.baseUrl = (\n config.baseUrl ??\n process.env.LEMURA_BASE_URL ??\n process.env.OPENAI_BASE_URL ??\n 'https://api.openai.com/v1'\n ).replace(/\\/$/, '');\n\n this.apiKey = config.apiKey ?? process.env.LEMURA_API_KEY ?? process.env.OPENAI_API_KEY ?? '';\n this.defaultModel = config.defaultModel ?? process.env.LEMURA_MODEL ?? process.env.OPENAI_MODEL ?? 'gpt-3.5-turbo';\n\n this.defaultHeaders = config.defaultHeaders || {};\n this.timeoutMs = config.timeout || 30000;\n this.retryConfig = config.retry || { maxRetries: 2, baseDelayMs: 1000 };\n }\n\n private async fetchWithRetry(url: string, init: RequestInit): Promise<Response> {\n let attempts = 0;\n while (attempts <= this.retryConfig.maxRetries) {\n try {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeoutMs);\n\n const headers: Record<string, string> = {\n 'Authorization': `Bearer ${this.apiKey}`,\n ...this.defaultHeaders,\n };\n\n if (init.headers) {\n Object.assign(headers, init.headers);\n }\n\n // Don't set Content-Type if it's 'unset' (for FormData)\n if (headers['Content-Type'] === 'unset') {\n delete headers['Content-Type'];\n } else if (!headers['Content-Type']) {\n headers['Content-Type'] = 'application/json';\n }\n\n const response = await fetch(url, {\n ...init,\n signal: controller.signal,\n headers,\n });\n\n clearTimeout(timeoutId);\n\n if (response.ok) return response;\n\n // Retry on 429 and 503\n if ((response.status === 429 || response.status === 503) && attempts < this.retryConfig.maxRetries) {\n attempts++;\n const delay = this.retryConfig.baseDelayMs * Math.pow(2, attempts - 1);\n await new Promise(resolve => setTimeout(resolve, delay));\n continue;\n }\n\n const errorText = await response.text().catch(() => '');\n let problem = 'The server replied with an error during the API call.';\n let hints = ['Check the API documentation for the provider you are using.'];\n\n if (response.status === 401) {\n problem = 'Authentication failed. The API key is invalid or missing.';\n hints = [\n 'Ensure your API key is correctly configured in the adapter or environment variables.',\n 'Check if the API key has expired or been revoked.'\n ];\n } else if (response.status === 404) {\n problem = 'The requested resource or model was not found.';\n hints = [\n 'Verify that the baseUrl is correct (e.g., https://api.openai.com/v1).',\n 'Check if the model name is correct and available for your account.',\n 'Ensure you are not appending extra paths to the baseUrl.'\n ];\n } else if (response.status === 429) {\n problem = 'Rate limit exceeded.';\n hints = [\n 'Wait a few seconds before retrying.',\n 'Check your usage limits and billing status on the provider dashboard.'\n ];\n }\n\n throw new LemuraAdapterError(\n `HTTP ${response.status}: ${errorText}`,\n 'HTTP_ERROR',\n { status: response.status, body: errorText },\n problem,\n hints\n );\n } catch (err) {\n if (err instanceof LemuraAdapterError) throw err;\n\n if (attempts < this.retryConfig.maxRetries) {\n attempts++;\n const delay = this.retryConfig.baseDelayMs * Math.pow(2, attempts - 1);\n await new Promise(resolve => setTimeout(resolve, delay));\n continue;\n }\n\n throw new LemuraAdapterError(\n `Network request failed: ${err instanceof Error ? err.message : String(err)}`,\n 'NETWORK_ERROR',\n err,\n 'A network error occurred while connecting to the provider.',\n [\n 'Check your internet connection.',\n 'Verify that the baseUrl is reachable from your network.',\n 'Check for proxy or firewall settings that might block the request.'\n ]\n );\n }\n }\n throw new LemuraAdapterError(\n 'Max retries exceeded',\n 'MAX_RETRIES',\n undefined,\n 'The request failed after multiple retry attempts.',\n ['Check if the provider service is down or experiencing high load.']\n );\n }\n\n private mapFinishReason(reason: string | null): CompletionResponse['finishReason'] {\n if (!reason) return 'stop';\n const r = reason.toLowerCase();\n if (r === 'tool_calls' || r === 'tool_call') return 'tool_call';\n if (r === 'length' || r === 'max_tokens') return 'max_tokens';\n if (r === 'content_filter' || r === 'error') return 'error';\n return 'stop';\n }\n\n private buildPayload(request: CompletionRequest): unknown {\n const payload: Record<string, unknown> = {\n model: request.model || this.defaultModel,\n messages: request.messages,\n };\n if (request.maxTokens !== undefined) payload.max_tokens = request.maxTokens;\n if (request.temperature !== undefined) payload.temperature = request.temperature;\n if (request.stopSequences?.length) payload.stop = request.stopSequences;\n if (request.stream) payload.stream = true;\n\n if (request.tools && request.tools.length > 0) {\n payload.tools = request.tools.map(t => ({\n type: 'function',\n function: {\n name: t.name,\n description: t.description,\n parameters: t.parameters,\n }\n }));\n }\n\n return payload;\n }\n\n async complete(request: CompletionRequest): Promise<CompletionResponse> {\n const payload = this.buildPayload(request);\n\n const response = await this.fetchWithRetry(`${this.baseUrl}/chat/completions`, {\n method: 'POST',\n body: JSON.stringify(payload)\n });\n\n const data = await response.json();\n const choice = data.choices?.[0];\n if (!choice) {\n throw new LemuraAdapterError('Invalid response format: missing choices', 'INVALID_RESPONSE', data);\n }\n\n const message = choice.message;\n let toolCalls;\n\n if (message.tool_calls && message.tool_calls.length > 0) {\n toolCalls = message.tool_calls.map((tc: any) => ({\n id: tc.id,\n name: tc.function.name,\n arguments: tc.function.arguments,\n }));\n }\n\n return {\n content: message.content || '',\n toolCalls,\n finishReason: this.mapFinishReason(choice.finish_reason),\n usage: {\n promptTokens: data.usage?.prompt_tokens || 0,\n completionTokens: data.usage?.completion_tokens || 0,\n totalTokens: data.usage?.total_tokens || 0,\n },\n rawResponse: data\n };\n }\n\n async *stream(request: CompletionRequest): AsyncIterable<CompletionChunk> {\n const payload = this.buildPayload({ ...request, stream: true });\n\n const response = await this.fetchWithRetry(`${this.baseUrl}/chat/completions`, {\n method: 'POST',\n body: JSON.stringify(payload)\n });\n\n if (!response.body) {\n throw new LemuraAdapterError('Response body is null', 'STREAM_ERROR');\n }\n\n const reader = response.body.getReader();\n const decoder = new TextDecoder('utf-8');\n let buffer = '';\n\n try {\n while (true) {\n const { value, done } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split('\\n');\n buffer = lines.pop() || '';\n\n for (const line of lines) {\n const trimmed = line.trim();\n if (!trimmed || trimmed === 'data: [DONE]') continue;\n if (trimmed.startsWith('data: ')) {\n const jsonStr = trimmed.slice(6);\n let data;\n try {\n data = JSON.parse(jsonStr);\n } catch (err) {\n continue;\n }\n\n const choice = data.choices?.[0];\n if (!choice) continue;\n\n const delta = choice.delta?.content || '';\n const toolCallBlock = choice.delta?.tool_calls?.[0];\n let toolCallDelta;\n\n if (toolCallBlock) {\n toolCallDelta = {\n id: toolCallBlock.id,\n name: toolCallBlock.function?.name,\n arguments: toolCallBlock.function?.arguments,\n };\n }\n\n const isFinished = choice.finish_reason !== null && choice.finish_reason !== undefined;\n\n yield {\n delta,\n finished: isFinished,\n ...(toolCallDelta && { toolCallDelta }),\n ...(isFinished && { finishReason: this.mapFinishReason(choice.finish_reason) })\n };\n }\n }\n }\n } finally {\n reader.releaseLock();\n }\n }\n\n estimateTokens(text: string): number {\n return Math.ceil(text.length / 4);\n }\n\n getModelInfo(): ModelInfo {\n return {\n supportsVision: true,\n supportsTools: true,\n contextWindow: 128000\n };\n }\n\n async healthCheck(): Promise<boolean> {\n try {\n const resp = await this.fetchWithRetry(`${this.baseUrl}/models`, { method: 'GET' });\n return resp.ok;\n } catch {\n return false;\n }\n }\n\n async transcribe(request: TranscriptionRequest): Promise<TranscriptionResponse> {\n const binaryString = atob(request.audioBase64);\n const bytes = new Uint8Array(binaryString.length);\n for (let i = 0; i < binaryString.length; i++) {\n bytes[i] = binaryString.charCodeAt(i);\n }\n const blob = new Blob([bytes], { type: request.mimeType });\n const formData = new FormData();\n formData.append('file', blob, 'audio.webm');\n formData.append('model', request.model || 'whisper-1');\n if (request.language) formData.append('language', request.language);\n\n const response = await this.fetchWithRetry(`${this.baseUrl}/audio/transcriptions`, {\n method: 'POST',\n body: formData,\n headers: {\n 'Content-Type': 'unset'\n }\n });\n\n const data = await response.json();\n return {\n transcript: data.text,\n confidence: 1.0, // OpenAI doesn't return confidence in standard response\n language: data.language || request.language || 'en'\n };\n }\n\n async *synthesize(request: SynthesisRequest): AsyncIterable<AudioChunk> {\n const response = await this.fetchWithRetry(`${this.baseUrl}/audio/speech`, {\n method: 'POST',\n body: JSON.stringify({\n model: request.model || 'tts-1',\n input: request.text,\n voice: request.voiceId || 'alloy',\n response_format: request.format || 'mp3'\n })\n });\n\n if (!response.body) throw new LemuraAdapterError('No response body for TTS', 'STREAM_ERROR');\n\n const reader = response.body.getReader();\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n if (value) {\n const binary = new TextDecoder('latin1').decode(value);\n yield { audioBase64: btoa(binary) };\n }\n }\n } finally {\n reader.releaseLock();\n }\n }\n\n async describeImage(request: VisionRequest): Promise<VisionResponse> {\n const payload = {\n model: request.model || this.defaultModel,\n messages: [\n {\n role: 'user',\n content: [\n { type: 'text', text: request.prompt || 'Describe this image' },\n {\n type: 'image_url',\n image_url: {\n url: `data:image/jpeg;base64,${request.imageBase64}`\n }\n }\n ]\n }\n ]\n };\n\n const response = await this.fetchWithRetry(`${this.baseUrl}/chat/completions`, {\n method: 'POST',\n body: JSON.stringify(payload)\n });\n\n const data = await response.json();\n return {\n description: data.choices[0].message.content,\n objects: [] // OpenAI doesn't return structured objects in standard vision call\n };\n }\n\n async generateImage(request: ImageGenRequest): Promise<ImageGenResponse> {\n const response = await this.fetchWithRetry(`${this.baseUrl}/images/generations`, {\n method: 'POST',\n body: JSON.stringify({\n prompt: request.prompt,\n model: request.model || 'dall-e-3',\n n: 1,\n size: request.dimensions || '1024x1024'\n })\n });\n\n const data = await response.json();\n return {\n imageUrl: data.data[0].url,\n revisedPrompt: data.data[0].revised_prompt\n };\n }\n}\n"]}