@providerprotocol/ai 0.0.4 → 0.0.5
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/README.md +19 -0
- package/dist/index.js +5 -1
- package/dist/index.js.map +1 -1
- package/dist/xai/index.d.ts +282 -0
- package/dist/xai/index.js +1812 -0
- package/dist/xai/index.js.map +1 -0
- package/package.json +9 -1
- package/src/core/llm.ts +6 -1
- package/src/providers/xai/index.ts +218 -0
- package/src/providers/xai/llm.completions.ts +201 -0
- package/src/providers/xai/llm.messages.ts +195 -0
- package/src/providers/xai/llm.responses.ts +211 -0
- package/src/providers/xai/transform.completions.ts +617 -0
- package/src/providers/xai/transform.messages.ts +467 -0
- package/src/providers/xai/transform.responses.ts +717 -0
- package/src/providers/xai/types.ts +908 -0
- package/src/xai/index.ts +39 -0
package/README.md
CHANGED
|
@@ -17,6 +17,7 @@ import { openai } from '@providerprotocol/ai/openai';
|
|
|
17
17
|
import { google } from '@providerprotocol/ai/google';
|
|
18
18
|
import { ollama } from '@providerprotocol/ai/ollama';
|
|
19
19
|
import { openrouter } from '@providerprotocol/ai/openrouter';
|
|
20
|
+
import { xai } from '@providerprotocol/ai/xai';
|
|
20
21
|
|
|
21
22
|
// Simple generation
|
|
22
23
|
const claude = llm({ model: anthropic('claude-sonnet-4-20250514') });
|
|
@@ -65,6 +66,24 @@ console.log(turn.data); // { name: 'John', age: 30 }
|
|
|
65
66
|
| Google | `@providerprotocol/ai/google` |
|
|
66
67
|
| Ollama | `@providerprotocol/ai/ollama` |
|
|
67
68
|
| OpenRouter | `@providerprotocol/ai/openrouter` |
|
|
69
|
+
| xAI (Grok) | `@providerprotocol/ai/xai` |
|
|
70
|
+
|
|
71
|
+
### xAI API Modes
|
|
72
|
+
|
|
73
|
+
xAI supports three API modes:
|
|
74
|
+
|
|
75
|
+
```typescript
|
|
76
|
+
import { xai } from '@providerprotocol/ai/xai';
|
|
77
|
+
|
|
78
|
+
// Chat Completions API (OpenAI-compatible, default)
|
|
79
|
+
const grok = llm({ model: xai('grok-3-fast') });
|
|
80
|
+
|
|
81
|
+
// Responses API (stateful, OpenAI Responses-compatible)
|
|
82
|
+
const grok = llm({ model: xai('grok-3-fast', { api: 'responses' }) });
|
|
83
|
+
|
|
84
|
+
// Messages API (Anthropic-compatible)
|
|
85
|
+
const grok = llm({ model: xai('grok-3-fast', { api: 'messages' }) });
|
|
86
|
+
```
|
|
68
87
|
|
|
69
88
|
## Configuration
|
|
70
89
|
|
package/dist/index.js
CHANGED
|
@@ -216,7 +216,11 @@ function parseInputs(historyOrInput, inputs) {
|
|
|
216
216
|
const newMessages2 = inputs.map(inputToMessage);
|
|
217
217
|
return { history: [...thread.messages], messages: newMessages2 };
|
|
218
218
|
}
|
|
219
|
-
if (Array.isArray(historyOrInput)
|
|
219
|
+
if (Array.isArray(historyOrInput)) {
|
|
220
|
+
if (historyOrInput.length === 0) {
|
|
221
|
+
const newMessages2 = inputs.map(inputToMessage);
|
|
222
|
+
return { history: [], messages: newMessages2 };
|
|
223
|
+
}
|
|
220
224
|
const first = historyOrInput[0];
|
|
221
225
|
if (isMessageInstance(first)) {
|
|
222
226
|
const newMessages2 = inputs.map(inputToMessage);
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/types/turn.ts","../src/types/stream.ts","../src/core/llm.ts","../src/core/image.ts","../src/types/content.ts","../src/types/thread.ts","../src/index.ts"],"sourcesContent":["import type { Message, AssistantMessage } from './messages.ts';\nimport type { ToolExecution } from './tool.ts';\n\n/**\n * Token usage information\n */\nexport interface TokenUsage {\n /** Input tokens across all cycles */\n inputTokens: number;\n\n /** Output tokens across all cycles */\n outputTokens: number;\n\n /** Total tokens */\n totalTokens: number;\n\n /** Per-cycle breakdown (if available) */\n cycles?: Array<{\n inputTokens: number;\n outputTokens: number;\n }>;\n}\n\n/**\n * A Turn represents the complete result of one inference call,\n * including all messages produced during tool execution loops.\n */\nexport interface Turn<TData = unknown> {\n /**\n * All messages produced during this inference, in chronological order.\n * Types: UserMessage, AssistantMessage (may include toolCalls), ToolResultMessage\n */\n readonly messages: Message[];\n\n /** The final assistant response (convenience accessor) */\n readonly response: AssistantMessage;\n\n /** Tool executions that occurred during this turn */\n readonly toolExecutions: ToolExecution[];\n\n /** Aggregate token usage for the entire turn */\n readonly usage: TokenUsage;\n\n /** Total number of inference cycles (1 + number of tool rounds) */\n readonly cycles: number;\n\n /**\n * Structured output data (if structure was provided).\n * Type is inferred from the schema when using TypeScript.\n */\n readonly data?: TData;\n}\n\n/**\n * Create a Turn from accumulated data\n */\nexport function createTurn<TData = unknown>(\n messages: Message[],\n toolExecutions: ToolExecution[],\n usage: TokenUsage,\n cycles: number,\n data?: TData\n): Turn<TData> {\n // Find the last assistant message as the response\n const response = messages\n .filter((m): m is AssistantMessage => m.type === 'assistant')\n .pop();\n\n if (!response) {\n throw new Error('Turn must contain at least one assistant message');\n }\n\n return {\n messages,\n response,\n toolExecutions,\n usage,\n cycles,\n data,\n };\n}\n\n/**\n * Create empty token usage\n */\nexport function emptyUsage(): TokenUsage {\n return {\n inputTokens: 0,\n outputTokens: 0,\n totalTokens: 0,\n cycles: [],\n };\n}\n\n/**\n * Aggregate token usage from multiple cycles\n */\nexport function aggregateUsage(usages: TokenUsage[]): TokenUsage {\n const cycles: TokenUsage['cycles'] = [];\n let inputTokens = 0;\n let outputTokens = 0;\n\n for (const usage of usages) {\n inputTokens += usage.inputTokens;\n outputTokens += usage.outputTokens;\n cycles.push({\n inputTokens: usage.inputTokens,\n outputTokens: usage.outputTokens,\n });\n }\n\n return {\n inputTokens,\n outputTokens,\n totalTokens: inputTokens + outputTokens,\n cycles,\n };\n}\n","import type { Turn } from './turn.ts';\n\n/**\n * Stream event types\n */\nexport type StreamEventType =\n | 'text_delta'\n | 'reasoning_delta'\n | 'image_delta'\n | 'audio_delta'\n | 'video_delta'\n | 'tool_call_delta'\n | 'message_start'\n | 'message_stop'\n | 'content_block_start'\n | 'content_block_stop';\n\n/**\n * Event delta data (type-specific)\n */\nexport interface EventDelta {\n text?: string;\n data?: Uint8Array;\n toolCallId?: string;\n toolName?: string;\n argumentsJson?: string;\n}\n\n/**\n * A streaming event\n */\nexport interface StreamEvent {\n /** Event type */\n type: StreamEventType;\n\n /** Index of the content block this event belongs to */\n index: number;\n\n /** Event data (type-specific) */\n delta: EventDelta;\n}\n\n/**\n * Stream result - async iterable that also provides final turn\n */\nexport interface StreamResult<TData = unknown>\n extends AsyncIterable<StreamEvent> {\n /**\n * Get the complete Turn after streaming finishes.\n * Resolves when the stream completes.\n */\n readonly turn: Promise<Turn<TData>>;\n\n /** Abort the stream */\n abort(): void;\n}\n\n/**\n * Create a stream result from an async generator and completion promise\n */\nexport function createStreamResult<TData = unknown>(\n generator: AsyncGenerator<StreamEvent, void, unknown>,\n turnPromise: Promise<Turn<TData>>,\n abortController: AbortController\n): StreamResult<TData> {\n return {\n [Symbol.asyncIterator]() {\n return generator;\n },\n turn: turnPromise,\n abort() {\n abortController.abort();\n },\n };\n}\n\n/**\n * Create a text delta event\n */\nexport function textDelta(text: string, index = 0): StreamEvent {\n return {\n type: 'text_delta',\n index,\n delta: { text },\n };\n}\n\n/**\n * Create a tool call delta event\n */\nexport function toolCallDelta(\n toolCallId: string,\n toolName: string,\n argumentsJson: string,\n index = 0\n): StreamEvent {\n return {\n type: 'tool_call_delta',\n index,\n delta: { toolCallId, toolName, argumentsJson },\n };\n}\n\n/**\n * Create a message start event\n */\nexport function messageStart(): StreamEvent {\n return {\n type: 'message_start',\n index: 0,\n delta: {},\n };\n}\n\n/**\n * Create a message stop event\n */\nexport function messageStop(): StreamEvent {\n return {\n type: 'message_stop',\n index: 0,\n delta: {},\n };\n}\n\n/**\n * Create a content block start event\n */\nexport function contentBlockStart(index: number): StreamEvent {\n return {\n type: 'content_block_start',\n index,\n delta: {},\n };\n}\n\n/**\n * Create a content block stop event\n */\nexport function contentBlockStop(index: number): StreamEvent {\n return {\n type: 'content_block_stop',\n index,\n delta: {},\n };\n}\n","import type {\n LLMOptions,\n LLMInstance,\n LLMRequest,\n LLMResponse,\n InferenceInput,\n BoundLLMModel,\n LLMCapabilities,\n} from '../types/llm.ts';\nimport type { UserMessage, AssistantMessage } from '../types/messages.ts';\nimport type { ContentBlock, TextBlock } from '../types/content.ts';\nimport type { Tool, ToolExecution, ToolResult } from '../types/tool.ts';\nimport type { Turn, TokenUsage } from '../types/turn.ts';\nimport type { StreamResult, StreamEvent } from '../types/stream.ts';\nimport type { Thread } from '../types/thread.ts';\nimport type { ProviderConfig } from '../types/provider.ts';\nimport { UPPError } from '../types/errors.ts';\nimport {\n Message,\n UserMessage as UserMessageClass,\n ToolResultMessage,\n isUserMessage,\n isAssistantMessage,\n} from '../types/messages.ts';\nimport { createTurn, aggregateUsage, emptyUsage } from '../types/turn.ts';\nimport { createStreamResult } from '../types/stream.ts';\nimport { generateShortId } from '../utils/id.ts';\n\n/**\n * Default maximum iterations for tool execution\n */\nconst DEFAULT_MAX_ITERATIONS = 10;\n\n/**\n * Create an LLM instance\n */\nexport function llm<TParams = unknown>(\n options: LLMOptions<TParams>\n): LLMInstance<TParams> {\n const { model: modelRef, config = {}, params, system, tools, toolStrategy, structure } = options;\n\n // Validate that the provider supports LLM\n const provider = modelRef.provider;\n if (!provider.modalities.llm) {\n throw new UPPError(\n `Provider '${provider.name}' does not support LLM modality`,\n 'INVALID_REQUEST',\n provider.name,\n 'llm'\n );\n }\n\n // Bind the model\n const boundModel = provider.modalities.llm.bind(modelRef.modelId) as BoundLLMModel<TParams>;\n\n // Validate capabilities at bind time\n const capabilities = boundModel.capabilities;\n\n // Check for structured output capability\n if (structure && !capabilities.structuredOutput) {\n throw new UPPError(\n `Provider '${provider.name}' does not support structured output`,\n 'INVALID_REQUEST',\n provider.name,\n 'llm'\n );\n }\n\n // Check for tools capability\n if (tools && tools.length > 0 && !capabilities.tools) {\n throw new UPPError(\n `Provider '${provider.name}' does not support tools`,\n 'INVALID_REQUEST',\n provider.name,\n 'llm'\n );\n }\n\n // Build the instance\n const instance: LLMInstance<TParams> = {\n model: boundModel,\n system,\n params,\n capabilities,\n\n async generate(\n historyOrInput: Message[] | Thread | InferenceInput,\n ...inputs: InferenceInput[]\n ): Promise<Turn> {\n const { history, messages } = parseInputs(historyOrInput, inputs);\n return executeGenerate(\n boundModel,\n config,\n system,\n params,\n tools,\n toolStrategy,\n structure,\n history,\n messages\n );\n },\n\n stream(\n historyOrInput: Message[] | Thread | InferenceInput,\n ...inputs: InferenceInput[]\n ): StreamResult {\n // Check streaming capability\n if (!capabilities.streaming) {\n throw new UPPError(\n `Provider '${provider.name}' does not support streaming`,\n 'INVALID_REQUEST',\n provider.name,\n 'llm'\n );\n }\n const { history, messages } = parseInputs(historyOrInput, inputs);\n return executeStream(\n boundModel,\n config,\n system,\n params,\n tools,\n toolStrategy,\n structure,\n history,\n messages\n );\n },\n };\n\n return instance;\n}\n\n/**\n * Type guard to check if a value is a Message instance.\n * Uses instanceof for class instances, with fallback to timestamp check\n * for deserialized/reconstructed Message objects.\n */\nfunction isMessageInstance(value: unknown): value is Message {\n if (value instanceof Message) {\n return true;\n }\n // Fallback for deserialized Messages that aren't class instances:\n // Messages have 'timestamp' (Date), ContentBlocks don't\n if (\n typeof value === 'object' &&\n value !== null &&\n 'timestamp' in value &&\n 'type' in value &&\n 'id' in value\n ) {\n const obj = value as Record<string, unknown>;\n // Message types are 'user', 'assistant', 'tool_result'\n // ContentBlock types are 'text', 'image', 'audio', 'video', 'binary'\n const messageTypes = ['user', 'assistant', 'tool_result'];\n return messageTypes.includes(obj.type as string);\n }\n return false;\n}\n\n/**\n * Parse inputs to determine history and new messages\n */\nfunction parseInputs(\n historyOrInput: Message[] | Thread | InferenceInput,\n inputs: InferenceInput[]\n): { history: Message[]; messages: Message[] } {\n // Check if it's a Thread first (has 'messages' array property)\n if (\n typeof historyOrInput === 'object' &&\n historyOrInput !== null &&\n 'messages' in historyOrInput &&\n Array.isArray((historyOrInput as Thread).messages)\n ) {\n const thread = historyOrInput as Thread;\n const newMessages = inputs.map(inputToMessage);\n return { history: [...thread.messages], messages: newMessages };\n }\n\n // Check if first arg is Message[] (history)\n if (Array.isArray(historyOrInput) && historyOrInput.length > 0) {\n const first = historyOrInput[0];\n if (isMessageInstance(first)) {\n // It's history (Message[])\n const newMessages = inputs.map(inputToMessage);\n return { history: historyOrInput as Message[], messages: newMessages };\n }\n }\n\n // It's input (no history) - could be string, single Message, or ContentBlock\n const allInputs = [historyOrInput as InferenceInput, ...inputs];\n const newMessages = allInputs.map(inputToMessage);\n return { history: [], messages: newMessages };\n}\n\n/**\n * Convert an InferenceInput to a Message\n */\nfunction inputToMessage(input: InferenceInput): Message {\n if (typeof input === 'string') {\n return new UserMessageClass(input);\n }\n\n // It's already a Message\n if ('type' in input && 'id' in input && 'timestamp' in input) {\n return input as Message;\n }\n\n // It's a ContentBlock - wrap in UserMessage\n const block = input as ContentBlock;\n if (block.type === 'text') {\n return new UserMessageClass((block as TextBlock).text);\n }\n\n return new UserMessageClass([block as any]);\n}\n\n/**\n * Execute a non-streaming generate call with tool loop\n */\nasync function executeGenerate<TParams>(\n model: BoundLLMModel<TParams>,\n config: ProviderConfig,\n system: string | undefined,\n params: TParams | undefined,\n tools: Tool[] | undefined,\n toolStrategy: LLMOptions<TParams>['toolStrategy'],\n structure: LLMOptions<TParams>['structure'],\n history: Message[],\n newMessages: Message[]\n): Promise<Turn> {\n // Validate media capabilities for all input messages\n validateMediaCapabilities(\n [...history, ...newMessages],\n model.capabilities,\n model.provider.name\n );\n const maxIterations = toolStrategy?.maxIterations ?? DEFAULT_MAX_ITERATIONS;\n const allMessages: Message[] = [...history, ...newMessages];\n const toolExecutions: ToolExecution[] = [];\n const usages: TokenUsage[] = [];\n let cycles = 0;\n\n // Track structured data from responses (providers handle extraction)\n let structuredData: unknown;\n\n // Tool loop\n while (cycles < maxIterations + 1) {\n cycles++;\n\n const request: LLMRequest<TParams> = {\n messages: allMessages,\n system,\n params,\n tools,\n structure,\n config,\n };\n\n const response = await model.complete(request);\n usages.push(response.usage);\n allMessages.push(response.message);\n\n // Track structured data from provider (if present)\n if (response.data !== undefined) {\n structuredData = response.data;\n }\n\n // Check for tool calls\n if (response.message.hasToolCalls && tools && tools.length > 0) {\n // If provider already extracted structured data, don't try to execute tool calls\n // (some providers use tool calls internally for structured output)\n if (response.data !== undefined) {\n break;\n }\n\n // Check if we've hit max iterations (subtract 1 because we already incremented)\n if (cycles >= maxIterations) {\n await toolStrategy?.onMaxIterations?.(maxIterations);\n throw new UPPError(\n `Tool execution exceeded maximum iterations (${maxIterations})`,\n 'INVALID_REQUEST',\n model.provider.name,\n 'llm'\n );\n }\n\n // Execute tools\n const results = await executeTools(\n response.message,\n tools,\n toolStrategy,\n toolExecutions\n );\n\n // Add tool results\n allMessages.push(new ToolResultMessage(results));\n\n continue;\n }\n\n // No tool calls - we're done\n break;\n }\n\n // Use structured data from provider if structure was requested\n const data = structure ? structuredData : undefined;\n\n return createTurn(\n allMessages.slice(history.length), // Only messages from this turn\n toolExecutions,\n aggregateUsage(usages),\n cycles,\n data\n );\n}\n\n/**\n * Execute a streaming generate call with tool loop\n */\nfunction executeStream<TParams>(\n model: BoundLLMModel<TParams>,\n config: ProviderConfig,\n system: string | undefined,\n params: TParams | undefined,\n tools: Tool[] | undefined,\n toolStrategy: LLMOptions<TParams>['toolStrategy'],\n structure: LLMOptions<TParams>['structure'],\n history: Message[],\n newMessages: Message[]\n): StreamResult {\n // Validate media capabilities for all input messages\n validateMediaCapabilities(\n [...history, ...newMessages],\n model.capabilities,\n model.provider.name\n );\n\n const abortController = new AbortController();\n\n // Shared state between generator and turn promise\n const allMessages: Message[] = [...history, ...newMessages];\n const toolExecutions: ToolExecution[] = [];\n const usages: TokenUsage[] = [];\n let cycles = 0;\n let generatorError: Error | null = null;\n let structuredData: unknown; // Providers extract this\n\n // Deferred to signal when generator completes\n let resolveGenerator: () => void;\n let rejectGenerator: (error: Error) => void;\n const generatorDone = new Promise<void>((resolve, reject) => {\n resolveGenerator = resolve;\n rejectGenerator = reject;\n });\n\n const maxIterations = toolStrategy?.maxIterations ?? DEFAULT_MAX_ITERATIONS;\n\n // Create the async generator - this is the ONLY place that calls the API\n async function* generateStream(): AsyncGenerator<StreamEvent, void, unknown> {\n try {\n while (cycles < maxIterations + 1) {\n cycles++;\n\n const request: LLMRequest<TParams> = {\n messages: allMessages,\n system,\n params,\n tools,\n structure,\n config,\n signal: abortController.signal,\n };\n\n const streamResult = model.stream(request);\n\n // Forward stream events\n for await (const event of streamResult) {\n yield event;\n }\n\n // Get the response\n const response = await streamResult.response;\n usages.push(response.usage);\n allMessages.push(response.message);\n\n // Track structured data from provider (if present)\n if (response.data !== undefined) {\n structuredData = response.data;\n }\n\n // Check for tool calls\n if (response.message.hasToolCalls && tools && tools.length > 0) {\n // If provider already extracted structured data, don't try to execute tool calls\n // (some providers use tool calls internally for structured output)\n if (response.data !== undefined) {\n break;\n }\n\n if (cycles >= maxIterations) {\n await toolStrategy?.onMaxIterations?.(maxIterations);\n throw new UPPError(\n `Tool execution exceeded maximum iterations (${maxIterations})`,\n 'INVALID_REQUEST',\n model.provider.name,\n 'llm'\n );\n }\n\n // Execute tools\n const results = await executeTools(\n response.message,\n tools,\n toolStrategy,\n toolExecutions\n );\n\n // Add tool results\n allMessages.push(new ToolResultMessage(results));\n\n continue;\n }\n\n break;\n }\n resolveGenerator();\n } catch (error) {\n generatorError = error as Error;\n rejectGenerator(error as Error);\n throw error;\n }\n }\n\n // Turn promise waits for the generator to complete, then builds the Turn\n const turnPromise = (async (): Promise<Turn> => {\n await generatorDone;\n\n if (generatorError) {\n throw generatorError;\n }\n\n // Use structured data from provider if structure was requested\n const data = structure ? structuredData : undefined;\n\n return createTurn(\n allMessages.slice(history.length),\n toolExecutions,\n aggregateUsage(usages),\n cycles,\n data\n );\n })();\n\n return createStreamResult(generateStream(), turnPromise, abortController);\n}\n\n/**\n * Execute tools from an assistant message\n */\nasync function executeTools(\n message: AssistantMessage,\n tools: Tool[],\n toolStrategy: LLMOptions<unknown>['toolStrategy'],\n executions: ToolExecution[]\n): Promise<ToolResult[]> {\n const toolCalls = message.toolCalls ?? [];\n const results: ToolResult[] = [];\n\n // Build tool map\n const toolMap = new Map(tools.map((t) => [t.name, t]));\n\n // Execute tools (in parallel)\n const promises = toolCalls.map(async (call) => {\n const tool = toolMap.get(call.toolName);\n if (!tool) {\n return {\n toolCallId: call.toolCallId,\n result: `Tool '${call.toolName}' not found`,\n isError: true,\n };\n }\n\n const startTime = Date.now();\n\n // Notify strategy\n await toolStrategy?.onToolCall?.(tool, call.arguments);\n\n // Check before call\n if (toolStrategy?.onBeforeCall) {\n const shouldRun = await toolStrategy.onBeforeCall(tool, call.arguments);\n if (!shouldRun) {\n return {\n toolCallId: call.toolCallId,\n result: 'Tool execution skipped',\n isError: true,\n };\n }\n }\n\n // Check approval\n let approved = true;\n if (tool.approval) {\n try {\n approved = await tool.approval(call.arguments);\n } catch (error) {\n // Approval threw - propagate\n throw error;\n }\n }\n\n if (!approved) {\n const execution: ToolExecution = {\n toolName: tool.name,\n toolCallId: call.toolCallId,\n arguments: call.arguments,\n result: 'Tool execution denied',\n isError: true,\n duration: Date.now() - startTime,\n approved: false,\n };\n executions.push(execution);\n\n return {\n toolCallId: call.toolCallId,\n result: 'Tool execution denied by approval handler',\n isError: true,\n };\n }\n\n // Execute tool\n try {\n const result = await tool.run(call.arguments);\n\n await toolStrategy?.onAfterCall?.(tool, call.arguments, result);\n\n const execution: ToolExecution = {\n toolName: tool.name,\n toolCallId: call.toolCallId,\n arguments: call.arguments,\n result,\n isError: false,\n duration: Date.now() - startTime,\n approved,\n };\n executions.push(execution);\n\n return {\n toolCallId: call.toolCallId,\n result,\n isError: false,\n };\n } catch (error) {\n await toolStrategy?.onError?.(tool, call.arguments, error as Error);\n\n const errorMessage = error instanceof Error ? error.message : String(error);\n\n const execution: ToolExecution = {\n toolName: tool.name,\n toolCallId: call.toolCallId,\n arguments: call.arguments,\n result: errorMessage,\n isError: true,\n duration: Date.now() - startTime,\n approved,\n };\n executions.push(execution);\n\n return {\n toolCallId: call.toolCallId,\n result: errorMessage,\n isError: true,\n };\n }\n });\n\n results.push(...(await Promise.all(promises)));\n return results;\n}\n\n/**\n * Check if messages contain media that requires specific capabilities\n */\nfunction validateMediaCapabilities(\n messages: Message[],\n capabilities: LLMCapabilities,\n providerName: string\n): void {\n for (const msg of messages) {\n if (!isUserMessage(msg)) continue;\n\n for (const block of msg.content) {\n if (block.type === 'image' && !capabilities.imageInput) {\n throw new UPPError(\n `Provider '${providerName}' does not support image input`,\n 'INVALID_REQUEST',\n providerName,\n 'llm'\n );\n }\n if (block.type === 'video' && !capabilities.videoInput) {\n throw new UPPError(\n `Provider '${providerName}' does not support video input`,\n 'INVALID_REQUEST',\n providerName,\n 'llm'\n );\n }\n if (block.type === 'audio' && !capabilities.audioInput) {\n throw new UPPError(\n `Provider '${providerName}' does not support audio input`,\n 'INVALID_REQUEST',\n providerName,\n 'llm'\n );\n }\n }\n }\n}\n","import type { ImageSource, ImageBlock } from '../types/content.ts';\n\n/**\n * Image class for handling images in UPP\n */\nexport class Image {\n readonly source: ImageSource;\n readonly mimeType: string;\n readonly width?: number;\n readonly height?: number;\n\n private constructor(\n source: ImageSource,\n mimeType: string,\n width?: number,\n height?: number\n ) {\n this.source = source;\n this.mimeType = mimeType;\n this.width = width;\n this.height = height;\n }\n\n /**\n * Check if this image has data loaded (false for URL sources)\n */\n get hasData(): boolean {\n return this.source.type !== 'url';\n }\n\n /**\n * Convert to base64 string (throws if source is URL)\n */\n toBase64(): string {\n if (this.source.type === 'base64') {\n return this.source.data;\n }\n\n if (this.source.type === 'bytes') {\n return btoa(\n Array.from(this.source.data)\n .map((b) => String.fromCharCode(b))\n .join('')\n );\n }\n\n throw new Error('Cannot convert URL image to base64. Fetch the image first.');\n }\n\n /**\n * Convert to data URL (throws if source is URL)\n */\n toDataUrl(): string {\n const base64 = this.toBase64();\n return `data:${this.mimeType};base64,${base64}`;\n }\n\n /**\n * Get raw bytes (throws if source is URL)\n */\n toBytes(): Uint8Array {\n if (this.source.type === 'bytes') {\n return this.source.data;\n }\n\n if (this.source.type === 'base64') {\n const binaryString = atob(this.source.data);\n const bytes = new Uint8Array(binaryString.length);\n for (let i = 0; i < binaryString.length; i++) {\n bytes[i] = binaryString.charCodeAt(i);\n }\n return bytes;\n }\n\n throw new Error('Cannot get bytes from URL image. Fetch the image first.');\n }\n\n /**\n * Get the URL (only for URL sources)\n */\n toUrl(): string {\n if (this.source.type === 'url') {\n return this.source.url;\n }\n\n throw new Error('This image does not have a URL source.');\n }\n\n /**\n * Convert to ImageBlock for use in messages\n */\n toBlock(): ImageBlock {\n return {\n type: 'image',\n source: this.source,\n mimeType: this.mimeType,\n width: this.width,\n height: this.height,\n };\n }\n\n /**\n * Create from file path (reads file into memory)\n */\n static async fromPath(path: string): Promise<Image> {\n const file = Bun.file(path);\n const data = await file.arrayBuffer();\n const mimeType = file.type || detectMimeType(path);\n\n return new Image(\n { type: 'bytes', data: new Uint8Array(data) },\n mimeType\n );\n }\n\n /**\n * Create from URL reference (does not fetch - providers handle URL conversion)\n */\n static fromUrl(url: string, mimeType?: string): Image {\n const detected = mimeType || detectMimeTypeFromUrl(url);\n return new Image({ type: 'url', url }, detected);\n }\n\n /**\n * Create from raw bytes\n */\n static fromBytes(data: Uint8Array, mimeType: string): Image {\n return new Image({ type: 'bytes', data }, mimeType);\n }\n\n /**\n * Create from base64 string\n */\n static fromBase64(base64: string, mimeType: string): Image {\n return new Image({ type: 'base64', data: base64 }, mimeType);\n }\n\n /**\n * Create from an existing ImageBlock\n */\n static fromBlock(block: ImageBlock): Image {\n return new Image(\n block.source,\n block.mimeType,\n block.width,\n block.height\n );\n }\n}\n\n/**\n * Detect MIME type from file extension\n */\nfunction detectMimeType(path: string): string {\n const ext = path.split('.').pop()?.toLowerCase();\n\n switch (ext) {\n case 'jpg':\n case 'jpeg':\n return 'image/jpeg';\n case 'png':\n return 'image/png';\n case 'gif':\n return 'image/gif';\n case 'webp':\n return 'image/webp';\n case 'svg':\n return 'image/svg+xml';\n case 'bmp':\n return 'image/bmp';\n case 'ico':\n return 'image/x-icon';\n default:\n return 'application/octet-stream';\n }\n}\n\n/**\n * Detect MIME type from URL\n */\nfunction detectMimeTypeFromUrl(url: string): string {\n try {\n const pathname = new URL(url).pathname;\n return detectMimeType(pathname);\n } catch {\n return 'application/octet-stream';\n }\n}\n","/**\n * Content block types for messages\n */\n\n/**\n * Image source types\n */\nexport type ImageSource =\n | { type: 'base64'; data: string }\n | { type: 'url'; url: string }\n | { type: 'bytes'; data: Uint8Array };\n\n/**\n * Text content block\n */\nexport interface TextBlock {\n type: 'text';\n text: string;\n}\n\n/**\n * Image content block\n */\nexport interface ImageBlock {\n type: 'image';\n source: ImageSource;\n mimeType: string;\n width?: number;\n height?: number;\n}\n\n/**\n * Audio content block\n */\nexport interface AudioBlock {\n type: 'audio';\n data: Uint8Array;\n mimeType: string;\n duration?: number;\n}\n\n/**\n * Video content block\n */\nexport interface VideoBlock {\n type: 'video';\n data: Uint8Array;\n mimeType: string;\n duration?: number;\n width?: number;\n height?: number;\n}\n\n/**\n * Binary content block for arbitrary data\n */\nexport interface BinaryBlock {\n type: 'binary';\n data: Uint8Array;\n mimeType: string;\n metadata?: Record<string, unknown>;\n}\n\n/**\n * All content block types\n */\nexport type ContentBlock =\n | TextBlock\n | ImageBlock\n | AudioBlock\n | VideoBlock\n | BinaryBlock;\n\n/**\n * Content types allowed in user messages\n */\nexport type UserContent =\n | TextBlock\n | ImageBlock\n | AudioBlock\n | VideoBlock\n | BinaryBlock;\n\n/**\n * Content types allowed in assistant messages\n */\nexport type AssistantContent =\n | TextBlock\n | ImageBlock\n | AudioBlock\n | VideoBlock;\n\n/**\n * Helper to create a text block\n */\nexport function text(content: string): TextBlock {\n return { type: 'text', text: content };\n}\n\n/**\n * Type guard for TextBlock\n */\nexport function isTextBlock(block: ContentBlock): block is TextBlock {\n return block.type === 'text';\n}\n\n/**\n * Type guard for ImageBlock\n */\nexport function isImageBlock(block: ContentBlock): block is ImageBlock {\n return block.type === 'image';\n}\n\n/**\n * Type guard for AudioBlock\n */\nexport function isAudioBlock(block: ContentBlock): block is AudioBlock {\n return block.type === 'audio';\n}\n\n/**\n * Type guard for VideoBlock\n */\nexport function isVideoBlock(block: ContentBlock): block is VideoBlock {\n return block.type === 'video';\n}\n\n/**\n * Type guard for BinaryBlock\n */\nexport function isBinaryBlock(block: ContentBlock): block is BinaryBlock {\n return block.type === 'binary';\n}\n","import { generateId } from '../utils/id.ts';\nimport {\n Message,\n UserMessage,\n AssistantMessage,\n ToolResultMessage,\n} from './messages.ts';\nimport type { MessageType, MessageMetadata } from './messages.ts';\nimport type { ContentBlock, UserContent, AssistantContent } from './content.ts';\nimport type { Turn } from './turn.ts';\nimport type { ToolCall, ToolResult } from './tool.ts';\n\n/**\n * Serialized message format\n */\nexport interface MessageJSON {\n id: string;\n type: MessageType;\n content: ContentBlock[];\n toolCalls?: ToolCall[];\n results?: ToolResult[];\n metadata?: MessageMetadata;\n timestamp: string;\n}\n\n/**\n * Serialized thread format\n */\nexport interface ThreadJSON {\n id: string;\n messages: MessageJSON[];\n createdAt: string;\n updatedAt: string;\n}\n\n/**\n * Thread - A utility class for managing conversation history\n * Users control their own history; Thread is optional\n */\nexport class Thread {\n /** Unique thread identifier */\n readonly id: string;\n\n /** Internal message storage */\n private _messages: Message[];\n\n /** Creation timestamp */\n private _createdAt: Date;\n\n /** Last update timestamp */\n private _updatedAt: Date;\n\n /**\n * Create a new thread, optionally with initial messages\n */\n constructor(messages?: Message[]) {\n this.id = generateId();\n this._messages = messages ? [...messages] : [];\n this._createdAt = new Date();\n this._updatedAt = new Date();\n }\n\n /** All messages in the thread (readonly) */\n get messages(): readonly Message[] {\n return this._messages;\n }\n\n /** Number of messages */\n get length(): number {\n return this._messages.length;\n }\n\n /**\n * Append messages from a turn\n */\n append(turn: Turn): this {\n this._messages.push(...turn.messages);\n this._updatedAt = new Date();\n return this;\n }\n\n /**\n * Add raw messages\n */\n push(...messages: Message[]): this {\n this._messages.push(...messages);\n this._updatedAt = new Date();\n return this;\n }\n\n /**\n * Add a user message\n */\n user(content: string | UserContent[]): this {\n this._messages.push(new UserMessage(content));\n this._updatedAt = new Date();\n return this;\n }\n\n /**\n * Add an assistant message\n */\n assistant(content: string | AssistantContent[]): this {\n this._messages.push(new AssistantMessage(content));\n this._updatedAt = new Date();\n return this;\n }\n\n /**\n * Get messages by type\n */\n filter(type: MessageType): Message[] {\n return this._messages.filter((m) => m.type === type);\n }\n\n /**\n * Get the last N messages\n */\n tail(count: number): Message[] {\n return this._messages.slice(-count);\n }\n\n /**\n * Create a new thread with a subset of messages\n */\n slice(start?: number, end?: number): Thread {\n return new Thread(this._messages.slice(start, end));\n }\n\n /**\n * Clear all messages\n */\n clear(): this {\n this._messages = [];\n this._updatedAt = new Date();\n return this;\n }\n\n /**\n * Convert to plain message array\n */\n toMessages(): Message[] {\n return [...this._messages];\n }\n\n /**\n * Serialize to JSON\n */\n toJSON(): ThreadJSON {\n return {\n id: this.id,\n messages: this._messages.map((m) => this.messageToJSON(m)),\n createdAt: this._createdAt.toISOString(),\n updatedAt: this._updatedAt.toISOString(),\n };\n }\n\n /**\n * Deserialize from JSON\n */\n static fromJSON(json: ThreadJSON): Thread {\n const messages = json.messages.map((m) => Thread.messageFromJSON(m));\n const thread = new Thread(messages);\n // Override the generated id with the serialized one\n (thread as { id: string }).id = json.id;\n thread._createdAt = new Date(json.createdAt);\n thread._updatedAt = new Date(json.updatedAt);\n return thread;\n }\n\n /**\n * Iterate over messages\n */\n [Symbol.iterator](): Iterator<Message> {\n return this._messages[Symbol.iterator]();\n }\n\n /**\n * Convert a message to JSON\n */\n private messageToJSON(m: Message): MessageJSON {\n const base: MessageJSON = {\n id: m.id,\n type: m.type,\n content: [],\n metadata: m.metadata,\n timestamp: m.timestamp.toISOString(),\n };\n\n if (m instanceof UserMessage) {\n base.content = m.content;\n } else if (m instanceof AssistantMessage) {\n base.content = m.content;\n base.toolCalls = m.toolCalls;\n } else if (m instanceof ToolResultMessage) {\n base.results = m.results;\n }\n\n return base;\n }\n\n /**\n * Reconstruct a message from JSON\n */\n private static messageFromJSON(json: MessageJSON): Message {\n const options = {\n id: json.id,\n metadata: json.metadata,\n };\n\n switch (json.type) {\n case 'user':\n return new UserMessage(json.content as UserContent[], options);\n case 'assistant':\n return new AssistantMessage(\n json.content as AssistantContent[],\n json.toolCalls,\n options\n );\n case 'tool_result':\n return new ToolResultMessage(json.results ?? [], options);\n default:\n throw new Error(`Unknown message type: ${json.type}`);\n }\n }\n}\n","// Core entry points\nexport { llm } from './core/llm.ts';\nexport { createProvider } from './core/provider.ts';\nexport { Image } from './core/image.ts';\n\n// Namespace object for alternative import style\nimport { llm } from './core/llm.ts';\n\n/**\n * UPP namespace object\n * Provides ai.llm(), ai.embedding(), ai.image() style access\n */\nexport const ai = {\n llm,\n // embedding, // Coming soon\n // image, // Coming soon\n};\n\n// Re-export all types from types/index.ts\nexport * from './types/index.ts';\n\n// Re-export HTTP utilities\nexport {\n RoundRobinKeys,\n WeightedKeys,\n DynamicKey,\n ExponentialBackoff,\n LinearBackoff,\n NoRetry,\n TokenBucket,\n RetryAfterStrategy,\n} from './http/index.ts';\n"],"mappings":"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","names":["text","newMessages"]}
|
|
1
|
+
{"version":3,"sources":["../src/types/turn.ts","../src/types/stream.ts","../src/core/llm.ts","../src/core/image.ts","../src/types/content.ts","../src/types/thread.ts","../src/index.ts"],"sourcesContent":["import type { Message, AssistantMessage } from './messages.ts';\nimport type { ToolExecution } from './tool.ts';\n\n/**\n * Token usage information\n */\nexport interface TokenUsage {\n /** Input tokens across all cycles */\n inputTokens: number;\n\n /** Output tokens across all cycles */\n outputTokens: number;\n\n /** Total tokens */\n totalTokens: number;\n\n /** Per-cycle breakdown (if available) */\n cycles?: Array<{\n inputTokens: number;\n outputTokens: number;\n }>;\n}\n\n/**\n * A Turn represents the complete result of one inference call,\n * including all messages produced during tool execution loops.\n */\nexport interface Turn<TData = unknown> {\n /**\n * All messages produced during this inference, in chronological order.\n * Types: UserMessage, AssistantMessage (may include toolCalls), ToolResultMessage\n */\n readonly messages: Message[];\n\n /** The final assistant response (convenience accessor) */\n readonly response: AssistantMessage;\n\n /** Tool executions that occurred during this turn */\n readonly toolExecutions: ToolExecution[];\n\n /** Aggregate token usage for the entire turn */\n readonly usage: TokenUsage;\n\n /** Total number of inference cycles (1 + number of tool rounds) */\n readonly cycles: number;\n\n /**\n * Structured output data (if structure was provided).\n * Type is inferred from the schema when using TypeScript.\n */\n readonly data?: TData;\n}\n\n/**\n * Create a Turn from accumulated data\n */\nexport function createTurn<TData = unknown>(\n messages: Message[],\n toolExecutions: ToolExecution[],\n usage: TokenUsage,\n cycles: number,\n data?: TData\n): Turn<TData> {\n // Find the last assistant message as the response\n const response = messages\n .filter((m): m is AssistantMessage => m.type === 'assistant')\n .pop();\n\n if (!response) {\n throw new Error('Turn must contain at least one assistant message');\n }\n\n return {\n messages,\n response,\n toolExecutions,\n usage,\n cycles,\n data,\n };\n}\n\n/**\n * Create empty token usage\n */\nexport function emptyUsage(): TokenUsage {\n return {\n inputTokens: 0,\n outputTokens: 0,\n totalTokens: 0,\n cycles: [],\n };\n}\n\n/**\n * Aggregate token usage from multiple cycles\n */\nexport function aggregateUsage(usages: TokenUsage[]): TokenUsage {\n const cycles: TokenUsage['cycles'] = [];\n let inputTokens = 0;\n let outputTokens = 0;\n\n for (const usage of usages) {\n inputTokens += usage.inputTokens;\n outputTokens += usage.outputTokens;\n cycles.push({\n inputTokens: usage.inputTokens,\n outputTokens: usage.outputTokens,\n });\n }\n\n return {\n inputTokens,\n outputTokens,\n totalTokens: inputTokens + outputTokens,\n cycles,\n };\n}\n","import type { Turn } from './turn.ts';\n\n/**\n * Stream event types\n */\nexport type StreamEventType =\n | 'text_delta'\n | 'reasoning_delta'\n | 'image_delta'\n | 'audio_delta'\n | 'video_delta'\n | 'tool_call_delta'\n | 'message_start'\n | 'message_stop'\n | 'content_block_start'\n | 'content_block_stop';\n\n/**\n * Event delta data (type-specific)\n */\nexport interface EventDelta {\n text?: string;\n data?: Uint8Array;\n toolCallId?: string;\n toolName?: string;\n argumentsJson?: string;\n}\n\n/**\n * A streaming event\n */\nexport interface StreamEvent {\n /** Event type */\n type: StreamEventType;\n\n /** Index of the content block this event belongs to */\n index: number;\n\n /** Event data (type-specific) */\n delta: EventDelta;\n}\n\n/**\n * Stream result - async iterable that also provides final turn\n */\nexport interface StreamResult<TData = unknown>\n extends AsyncIterable<StreamEvent> {\n /**\n * Get the complete Turn after streaming finishes.\n * Resolves when the stream completes.\n */\n readonly turn: Promise<Turn<TData>>;\n\n /** Abort the stream */\n abort(): void;\n}\n\n/**\n * Create a stream result from an async generator and completion promise\n */\nexport function createStreamResult<TData = unknown>(\n generator: AsyncGenerator<StreamEvent, void, unknown>,\n turnPromise: Promise<Turn<TData>>,\n abortController: AbortController\n): StreamResult<TData> {\n return {\n [Symbol.asyncIterator]() {\n return generator;\n },\n turn: turnPromise,\n abort() {\n abortController.abort();\n },\n };\n}\n\n/**\n * Create a text delta event\n */\nexport function textDelta(text: string, index = 0): StreamEvent {\n return {\n type: 'text_delta',\n index,\n delta: { text },\n };\n}\n\n/**\n * Create a tool call delta event\n */\nexport function toolCallDelta(\n toolCallId: string,\n toolName: string,\n argumentsJson: string,\n index = 0\n): StreamEvent {\n return {\n type: 'tool_call_delta',\n index,\n delta: { toolCallId, toolName, argumentsJson },\n };\n}\n\n/**\n * Create a message start event\n */\nexport function messageStart(): StreamEvent {\n return {\n type: 'message_start',\n index: 0,\n delta: {},\n };\n}\n\n/**\n * Create a message stop event\n */\nexport function messageStop(): StreamEvent {\n return {\n type: 'message_stop',\n index: 0,\n delta: {},\n };\n}\n\n/**\n * Create a content block start event\n */\nexport function contentBlockStart(index: number): StreamEvent {\n return {\n type: 'content_block_start',\n index,\n delta: {},\n };\n}\n\n/**\n * Create a content block stop event\n */\nexport function contentBlockStop(index: number): StreamEvent {\n return {\n type: 'content_block_stop',\n index,\n delta: {},\n };\n}\n","import type {\n LLMOptions,\n LLMInstance,\n LLMRequest,\n LLMResponse,\n InferenceInput,\n BoundLLMModel,\n LLMCapabilities,\n} from '../types/llm.ts';\nimport type { UserMessage, AssistantMessage } from '../types/messages.ts';\nimport type { ContentBlock, TextBlock } from '../types/content.ts';\nimport type { Tool, ToolExecution, ToolResult } from '../types/tool.ts';\nimport type { Turn, TokenUsage } from '../types/turn.ts';\nimport type { StreamResult, StreamEvent } from '../types/stream.ts';\nimport type { Thread } from '../types/thread.ts';\nimport type { ProviderConfig } from '../types/provider.ts';\nimport { UPPError } from '../types/errors.ts';\nimport {\n Message,\n UserMessage as UserMessageClass,\n ToolResultMessage,\n isUserMessage,\n isAssistantMessage,\n} from '../types/messages.ts';\nimport { createTurn, aggregateUsage, emptyUsage } from '../types/turn.ts';\nimport { createStreamResult } from '../types/stream.ts';\nimport { generateShortId } from '../utils/id.ts';\n\n/**\n * Default maximum iterations for tool execution\n */\nconst DEFAULT_MAX_ITERATIONS = 10;\n\n/**\n * Create an LLM instance\n */\nexport function llm<TParams = unknown>(\n options: LLMOptions<TParams>\n): LLMInstance<TParams> {\n const { model: modelRef, config = {}, params, system, tools, toolStrategy, structure } = options;\n\n // Validate that the provider supports LLM\n const provider = modelRef.provider;\n if (!provider.modalities.llm) {\n throw new UPPError(\n `Provider '${provider.name}' does not support LLM modality`,\n 'INVALID_REQUEST',\n provider.name,\n 'llm'\n );\n }\n\n // Bind the model\n const boundModel = provider.modalities.llm.bind(modelRef.modelId) as BoundLLMModel<TParams>;\n\n // Validate capabilities at bind time\n const capabilities = boundModel.capabilities;\n\n // Check for structured output capability\n if (structure && !capabilities.structuredOutput) {\n throw new UPPError(\n `Provider '${provider.name}' does not support structured output`,\n 'INVALID_REQUEST',\n provider.name,\n 'llm'\n );\n }\n\n // Check for tools capability\n if (tools && tools.length > 0 && !capabilities.tools) {\n throw new UPPError(\n `Provider '${provider.name}' does not support tools`,\n 'INVALID_REQUEST',\n provider.name,\n 'llm'\n );\n }\n\n // Build the instance\n const instance: LLMInstance<TParams> = {\n model: boundModel,\n system,\n params,\n capabilities,\n\n async generate(\n historyOrInput: Message[] | Thread | InferenceInput,\n ...inputs: InferenceInput[]\n ): Promise<Turn> {\n const { history, messages } = parseInputs(historyOrInput, inputs);\n return executeGenerate(\n boundModel,\n config,\n system,\n params,\n tools,\n toolStrategy,\n structure,\n history,\n messages\n );\n },\n\n stream(\n historyOrInput: Message[] | Thread | InferenceInput,\n ...inputs: InferenceInput[]\n ): StreamResult {\n // Check streaming capability\n if (!capabilities.streaming) {\n throw new UPPError(\n `Provider '${provider.name}' does not support streaming`,\n 'INVALID_REQUEST',\n provider.name,\n 'llm'\n );\n }\n const { history, messages } = parseInputs(historyOrInput, inputs);\n return executeStream(\n boundModel,\n config,\n system,\n params,\n tools,\n toolStrategy,\n structure,\n history,\n messages\n );\n },\n };\n\n return instance;\n}\n\n/**\n * Type guard to check if a value is a Message instance.\n * Uses instanceof for class instances, with fallback to timestamp check\n * for deserialized/reconstructed Message objects.\n */\nfunction isMessageInstance(value: unknown): value is Message {\n if (value instanceof Message) {\n return true;\n }\n // Fallback for deserialized Messages that aren't class instances:\n // Messages have 'timestamp' (Date), ContentBlocks don't\n if (\n typeof value === 'object' &&\n value !== null &&\n 'timestamp' in value &&\n 'type' in value &&\n 'id' in value\n ) {\n const obj = value as Record<string, unknown>;\n // Message types are 'user', 'assistant', 'tool_result'\n // ContentBlock types are 'text', 'image', 'audio', 'video', 'binary'\n const messageTypes = ['user', 'assistant', 'tool_result'];\n return messageTypes.includes(obj.type as string);\n }\n return false;\n}\n\n/**\n * Parse inputs to determine history and new messages\n */\nfunction parseInputs(\n historyOrInput: Message[] | Thread | InferenceInput,\n inputs: InferenceInput[]\n): { history: Message[]; messages: Message[] } {\n // Check if it's a Thread first (has 'messages' array property)\n if (\n typeof historyOrInput === 'object' &&\n historyOrInput !== null &&\n 'messages' in historyOrInput &&\n Array.isArray((historyOrInput as Thread).messages)\n ) {\n const thread = historyOrInput as Thread;\n const newMessages = inputs.map(inputToMessage);\n return { history: [...thread.messages], messages: newMessages };\n }\n\n // Check if first arg is Message[] (history)\n if (Array.isArray(historyOrInput)) {\n // Empty array is empty history\n if (historyOrInput.length === 0) {\n const newMessages = inputs.map(inputToMessage);\n return { history: [], messages: newMessages };\n }\n const first = historyOrInput[0];\n if (isMessageInstance(first)) {\n // It's history (Message[])\n const newMessages = inputs.map(inputToMessage);\n return { history: historyOrInput as Message[], messages: newMessages };\n }\n }\n\n // It's input (no history) - could be string, single Message, or ContentBlock\n const allInputs = [historyOrInput as InferenceInput, ...inputs];\n const newMessages = allInputs.map(inputToMessage);\n return { history: [], messages: newMessages };\n}\n\n/**\n * Convert an InferenceInput to a Message\n */\nfunction inputToMessage(input: InferenceInput): Message {\n if (typeof input === 'string') {\n return new UserMessageClass(input);\n }\n\n // It's already a Message\n if ('type' in input && 'id' in input && 'timestamp' in input) {\n return input as Message;\n }\n\n // It's a ContentBlock - wrap in UserMessage\n const block = input as ContentBlock;\n if (block.type === 'text') {\n return new UserMessageClass((block as TextBlock).text);\n }\n\n return new UserMessageClass([block as any]);\n}\n\n/**\n * Execute a non-streaming generate call with tool loop\n */\nasync function executeGenerate<TParams>(\n model: BoundLLMModel<TParams>,\n config: ProviderConfig,\n system: string | undefined,\n params: TParams | undefined,\n tools: Tool[] | undefined,\n toolStrategy: LLMOptions<TParams>['toolStrategy'],\n structure: LLMOptions<TParams>['structure'],\n history: Message[],\n newMessages: Message[]\n): Promise<Turn> {\n // Validate media capabilities for all input messages\n validateMediaCapabilities(\n [...history, ...newMessages],\n model.capabilities,\n model.provider.name\n );\n const maxIterations = toolStrategy?.maxIterations ?? DEFAULT_MAX_ITERATIONS;\n const allMessages: Message[] = [...history, ...newMessages];\n const toolExecutions: ToolExecution[] = [];\n const usages: TokenUsage[] = [];\n let cycles = 0;\n\n // Track structured data from responses (providers handle extraction)\n let structuredData: unknown;\n\n // Tool loop\n while (cycles < maxIterations + 1) {\n cycles++;\n\n const request: LLMRequest<TParams> = {\n messages: allMessages,\n system,\n params,\n tools,\n structure,\n config,\n };\n\n const response = await model.complete(request);\n usages.push(response.usage);\n allMessages.push(response.message);\n\n // Track structured data from provider (if present)\n if (response.data !== undefined) {\n structuredData = response.data;\n }\n\n // Check for tool calls\n if (response.message.hasToolCalls && tools && tools.length > 0) {\n // If provider already extracted structured data, don't try to execute tool calls\n // (some providers use tool calls internally for structured output)\n if (response.data !== undefined) {\n break;\n }\n\n // Check if we've hit max iterations (subtract 1 because we already incremented)\n if (cycles >= maxIterations) {\n await toolStrategy?.onMaxIterations?.(maxIterations);\n throw new UPPError(\n `Tool execution exceeded maximum iterations (${maxIterations})`,\n 'INVALID_REQUEST',\n model.provider.name,\n 'llm'\n );\n }\n\n // Execute tools\n const results = await executeTools(\n response.message,\n tools,\n toolStrategy,\n toolExecutions\n );\n\n // Add tool results\n allMessages.push(new ToolResultMessage(results));\n\n continue;\n }\n\n // No tool calls - we're done\n break;\n }\n\n // Use structured data from provider if structure was requested\n const data = structure ? structuredData : undefined;\n\n return createTurn(\n allMessages.slice(history.length), // Only messages from this turn\n toolExecutions,\n aggregateUsage(usages),\n cycles,\n data\n );\n}\n\n/**\n * Execute a streaming generate call with tool loop\n */\nfunction executeStream<TParams>(\n model: BoundLLMModel<TParams>,\n config: ProviderConfig,\n system: string | undefined,\n params: TParams | undefined,\n tools: Tool[] | undefined,\n toolStrategy: LLMOptions<TParams>['toolStrategy'],\n structure: LLMOptions<TParams>['structure'],\n history: Message[],\n newMessages: Message[]\n): StreamResult {\n // Validate media capabilities for all input messages\n validateMediaCapabilities(\n [...history, ...newMessages],\n model.capabilities,\n model.provider.name\n );\n\n const abortController = new AbortController();\n\n // Shared state between generator and turn promise\n const allMessages: Message[] = [...history, ...newMessages];\n const toolExecutions: ToolExecution[] = [];\n const usages: TokenUsage[] = [];\n let cycles = 0;\n let generatorError: Error | null = null;\n let structuredData: unknown; // Providers extract this\n\n // Deferred to signal when generator completes\n let resolveGenerator: () => void;\n let rejectGenerator: (error: Error) => void;\n const generatorDone = new Promise<void>((resolve, reject) => {\n resolveGenerator = resolve;\n rejectGenerator = reject;\n });\n\n const maxIterations = toolStrategy?.maxIterations ?? DEFAULT_MAX_ITERATIONS;\n\n // Create the async generator - this is the ONLY place that calls the API\n async function* generateStream(): AsyncGenerator<StreamEvent, void, unknown> {\n try {\n while (cycles < maxIterations + 1) {\n cycles++;\n\n const request: LLMRequest<TParams> = {\n messages: allMessages,\n system,\n params,\n tools,\n structure,\n config,\n signal: abortController.signal,\n };\n\n const streamResult = model.stream(request);\n\n // Forward stream events\n for await (const event of streamResult) {\n yield event;\n }\n\n // Get the response\n const response = await streamResult.response;\n usages.push(response.usage);\n allMessages.push(response.message);\n\n // Track structured data from provider (if present)\n if (response.data !== undefined) {\n structuredData = response.data;\n }\n\n // Check for tool calls\n if (response.message.hasToolCalls && tools && tools.length > 0) {\n // If provider already extracted structured data, don't try to execute tool calls\n // (some providers use tool calls internally for structured output)\n if (response.data !== undefined) {\n break;\n }\n\n if (cycles >= maxIterations) {\n await toolStrategy?.onMaxIterations?.(maxIterations);\n throw new UPPError(\n `Tool execution exceeded maximum iterations (${maxIterations})`,\n 'INVALID_REQUEST',\n model.provider.name,\n 'llm'\n );\n }\n\n // Execute tools\n const results = await executeTools(\n response.message,\n tools,\n toolStrategy,\n toolExecutions\n );\n\n // Add tool results\n allMessages.push(new ToolResultMessage(results));\n\n continue;\n }\n\n break;\n }\n resolveGenerator();\n } catch (error) {\n generatorError = error as Error;\n rejectGenerator(error as Error);\n throw error;\n }\n }\n\n // Turn promise waits for the generator to complete, then builds the Turn\n const turnPromise = (async (): Promise<Turn> => {\n await generatorDone;\n\n if (generatorError) {\n throw generatorError;\n }\n\n // Use structured data from provider if structure was requested\n const data = structure ? structuredData : undefined;\n\n return createTurn(\n allMessages.slice(history.length),\n toolExecutions,\n aggregateUsage(usages),\n cycles,\n data\n );\n })();\n\n return createStreamResult(generateStream(), turnPromise, abortController);\n}\n\n/**\n * Execute tools from an assistant message\n */\nasync function executeTools(\n message: AssistantMessage,\n tools: Tool[],\n toolStrategy: LLMOptions<unknown>['toolStrategy'],\n executions: ToolExecution[]\n): Promise<ToolResult[]> {\n const toolCalls = message.toolCalls ?? [];\n const results: ToolResult[] = [];\n\n // Build tool map\n const toolMap = new Map(tools.map((t) => [t.name, t]));\n\n // Execute tools (in parallel)\n const promises = toolCalls.map(async (call) => {\n const tool = toolMap.get(call.toolName);\n if (!tool) {\n return {\n toolCallId: call.toolCallId,\n result: `Tool '${call.toolName}' not found`,\n isError: true,\n };\n }\n\n const startTime = Date.now();\n\n // Notify strategy\n await toolStrategy?.onToolCall?.(tool, call.arguments);\n\n // Check before call\n if (toolStrategy?.onBeforeCall) {\n const shouldRun = await toolStrategy.onBeforeCall(tool, call.arguments);\n if (!shouldRun) {\n return {\n toolCallId: call.toolCallId,\n result: 'Tool execution skipped',\n isError: true,\n };\n }\n }\n\n // Check approval\n let approved = true;\n if (tool.approval) {\n try {\n approved = await tool.approval(call.arguments);\n } catch (error) {\n // Approval threw - propagate\n throw error;\n }\n }\n\n if (!approved) {\n const execution: ToolExecution = {\n toolName: tool.name,\n toolCallId: call.toolCallId,\n arguments: call.arguments,\n result: 'Tool execution denied',\n isError: true,\n duration: Date.now() - startTime,\n approved: false,\n };\n executions.push(execution);\n\n return {\n toolCallId: call.toolCallId,\n result: 'Tool execution denied by approval handler',\n isError: true,\n };\n }\n\n // Execute tool\n try {\n const result = await tool.run(call.arguments);\n\n await toolStrategy?.onAfterCall?.(tool, call.arguments, result);\n\n const execution: ToolExecution = {\n toolName: tool.name,\n toolCallId: call.toolCallId,\n arguments: call.arguments,\n result,\n isError: false,\n duration: Date.now() - startTime,\n approved,\n };\n executions.push(execution);\n\n return {\n toolCallId: call.toolCallId,\n result,\n isError: false,\n };\n } catch (error) {\n await toolStrategy?.onError?.(tool, call.arguments, error as Error);\n\n const errorMessage = error instanceof Error ? error.message : String(error);\n\n const execution: ToolExecution = {\n toolName: tool.name,\n toolCallId: call.toolCallId,\n arguments: call.arguments,\n result: errorMessage,\n isError: true,\n duration: Date.now() - startTime,\n approved,\n };\n executions.push(execution);\n\n return {\n toolCallId: call.toolCallId,\n result: errorMessage,\n isError: true,\n };\n }\n });\n\n results.push(...(await Promise.all(promises)));\n return results;\n}\n\n/**\n * Check if messages contain media that requires specific capabilities\n */\nfunction validateMediaCapabilities(\n messages: Message[],\n capabilities: LLMCapabilities,\n providerName: string\n): void {\n for (const msg of messages) {\n if (!isUserMessage(msg)) continue;\n\n for (const block of msg.content) {\n if (block.type === 'image' && !capabilities.imageInput) {\n throw new UPPError(\n `Provider '${providerName}' does not support image input`,\n 'INVALID_REQUEST',\n providerName,\n 'llm'\n );\n }\n if (block.type === 'video' && !capabilities.videoInput) {\n throw new UPPError(\n `Provider '${providerName}' does not support video input`,\n 'INVALID_REQUEST',\n providerName,\n 'llm'\n );\n }\n if (block.type === 'audio' && !capabilities.audioInput) {\n throw new UPPError(\n `Provider '${providerName}' does not support audio input`,\n 'INVALID_REQUEST',\n providerName,\n 'llm'\n );\n }\n }\n }\n}\n","import type { ImageSource, ImageBlock } from '../types/content.ts';\n\n/**\n * Image class for handling images in UPP\n */\nexport class Image {\n readonly source: ImageSource;\n readonly mimeType: string;\n readonly width?: number;\n readonly height?: number;\n\n private constructor(\n source: ImageSource,\n mimeType: string,\n width?: number,\n height?: number\n ) {\n this.source = source;\n this.mimeType = mimeType;\n this.width = width;\n this.height = height;\n }\n\n /**\n * Check if this image has data loaded (false for URL sources)\n */\n get hasData(): boolean {\n return this.source.type !== 'url';\n }\n\n /**\n * Convert to base64 string (throws if source is URL)\n */\n toBase64(): string {\n if (this.source.type === 'base64') {\n return this.source.data;\n }\n\n if (this.source.type === 'bytes') {\n return btoa(\n Array.from(this.source.data)\n .map((b) => String.fromCharCode(b))\n .join('')\n );\n }\n\n throw new Error('Cannot convert URL image to base64. Fetch the image first.');\n }\n\n /**\n * Convert to data URL (throws if source is URL)\n */\n toDataUrl(): string {\n const base64 = this.toBase64();\n return `data:${this.mimeType};base64,${base64}`;\n }\n\n /**\n * Get raw bytes (throws if source is URL)\n */\n toBytes(): Uint8Array {\n if (this.source.type === 'bytes') {\n return this.source.data;\n }\n\n if (this.source.type === 'base64') {\n const binaryString = atob(this.source.data);\n const bytes = new Uint8Array(binaryString.length);\n for (let i = 0; i < binaryString.length; i++) {\n bytes[i] = binaryString.charCodeAt(i);\n }\n return bytes;\n }\n\n throw new Error('Cannot get bytes from URL image. Fetch the image first.');\n }\n\n /**\n * Get the URL (only for URL sources)\n */\n toUrl(): string {\n if (this.source.type === 'url') {\n return this.source.url;\n }\n\n throw new Error('This image does not have a URL source.');\n }\n\n /**\n * Convert to ImageBlock for use in messages\n */\n toBlock(): ImageBlock {\n return {\n type: 'image',\n source: this.source,\n mimeType: this.mimeType,\n width: this.width,\n height: this.height,\n };\n }\n\n /**\n * Create from file path (reads file into memory)\n */\n static async fromPath(path: string): Promise<Image> {\n const file = Bun.file(path);\n const data = await file.arrayBuffer();\n const mimeType = file.type || detectMimeType(path);\n\n return new Image(\n { type: 'bytes', data: new Uint8Array(data) },\n mimeType\n );\n }\n\n /**\n * Create from URL reference (does not fetch - providers handle URL conversion)\n */\n static fromUrl(url: string, mimeType?: string): Image {\n const detected = mimeType || detectMimeTypeFromUrl(url);\n return new Image({ type: 'url', url }, detected);\n }\n\n /**\n * Create from raw bytes\n */\n static fromBytes(data: Uint8Array, mimeType: string): Image {\n return new Image({ type: 'bytes', data }, mimeType);\n }\n\n /**\n * Create from base64 string\n */\n static fromBase64(base64: string, mimeType: string): Image {\n return new Image({ type: 'base64', data: base64 }, mimeType);\n }\n\n /**\n * Create from an existing ImageBlock\n */\n static fromBlock(block: ImageBlock): Image {\n return new Image(\n block.source,\n block.mimeType,\n block.width,\n block.height\n );\n }\n}\n\n/**\n * Detect MIME type from file extension\n */\nfunction detectMimeType(path: string): string {\n const ext = path.split('.').pop()?.toLowerCase();\n\n switch (ext) {\n case 'jpg':\n case 'jpeg':\n return 'image/jpeg';\n case 'png':\n return 'image/png';\n case 'gif':\n return 'image/gif';\n case 'webp':\n return 'image/webp';\n case 'svg':\n return 'image/svg+xml';\n case 'bmp':\n return 'image/bmp';\n case 'ico':\n return 'image/x-icon';\n default:\n return 'application/octet-stream';\n }\n}\n\n/**\n * Detect MIME type from URL\n */\nfunction detectMimeTypeFromUrl(url: string): string {\n try {\n const pathname = new URL(url).pathname;\n return detectMimeType(pathname);\n } catch {\n return 'application/octet-stream';\n }\n}\n","/**\n * Content block types for messages\n */\n\n/**\n * Image source types\n */\nexport type ImageSource =\n | { type: 'base64'; data: string }\n | { type: 'url'; url: string }\n | { type: 'bytes'; data: Uint8Array };\n\n/**\n * Text content block\n */\nexport interface TextBlock {\n type: 'text';\n text: string;\n}\n\n/**\n * Image content block\n */\nexport interface ImageBlock {\n type: 'image';\n source: ImageSource;\n mimeType: string;\n width?: number;\n height?: number;\n}\n\n/**\n * Audio content block\n */\nexport interface AudioBlock {\n type: 'audio';\n data: Uint8Array;\n mimeType: string;\n duration?: number;\n}\n\n/**\n * Video content block\n */\nexport interface VideoBlock {\n type: 'video';\n data: Uint8Array;\n mimeType: string;\n duration?: number;\n width?: number;\n height?: number;\n}\n\n/**\n * Binary content block for arbitrary data\n */\nexport interface BinaryBlock {\n type: 'binary';\n data: Uint8Array;\n mimeType: string;\n metadata?: Record<string, unknown>;\n}\n\n/**\n * All content block types\n */\nexport type ContentBlock =\n | TextBlock\n | ImageBlock\n | AudioBlock\n | VideoBlock\n | BinaryBlock;\n\n/**\n * Content types allowed in user messages\n */\nexport type UserContent =\n | TextBlock\n | ImageBlock\n | AudioBlock\n | VideoBlock\n | BinaryBlock;\n\n/**\n * Content types allowed in assistant messages\n */\nexport type AssistantContent =\n | TextBlock\n | ImageBlock\n | AudioBlock\n | VideoBlock;\n\n/**\n * Helper to create a text block\n */\nexport function text(content: string): TextBlock {\n return { type: 'text', text: content };\n}\n\n/**\n * Type guard for TextBlock\n */\nexport function isTextBlock(block: ContentBlock): block is TextBlock {\n return block.type === 'text';\n}\n\n/**\n * Type guard for ImageBlock\n */\nexport function isImageBlock(block: ContentBlock): block is ImageBlock {\n return block.type === 'image';\n}\n\n/**\n * Type guard for AudioBlock\n */\nexport function isAudioBlock(block: ContentBlock): block is AudioBlock {\n return block.type === 'audio';\n}\n\n/**\n * Type guard for VideoBlock\n */\nexport function isVideoBlock(block: ContentBlock): block is VideoBlock {\n return block.type === 'video';\n}\n\n/**\n * Type guard for BinaryBlock\n */\nexport function isBinaryBlock(block: ContentBlock): block is BinaryBlock {\n return block.type === 'binary';\n}\n","import { generateId } from '../utils/id.ts';\nimport {\n Message,\n UserMessage,\n AssistantMessage,\n ToolResultMessage,\n} from './messages.ts';\nimport type { MessageType, MessageMetadata } from './messages.ts';\nimport type { ContentBlock, UserContent, AssistantContent } from './content.ts';\nimport type { Turn } from './turn.ts';\nimport type { ToolCall, ToolResult } from './tool.ts';\n\n/**\n * Serialized message format\n */\nexport interface MessageJSON {\n id: string;\n type: MessageType;\n content: ContentBlock[];\n toolCalls?: ToolCall[];\n results?: ToolResult[];\n metadata?: MessageMetadata;\n timestamp: string;\n}\n\n/**\n * Serialized thread format\n */\nexport interface ThreadJSON {\n id: string;\n messages: MessageJSON[];\n createdAt: string;\n updatedAt: string;\n}\n\n/**\n * Thread - A utility class for managing conversation history\n * Users control their own history; Thread is optional\n */\nexport class Thread {\n /** Unique thread identifier */\n readonly id: string;\n\n /** Internal message storage */\n private _messages: Message[];\n\n /** Creation timestamp */\n private _createdAt: Date;\n\n /** Last update timestamp */\n private _updatedAt: Date;\n\n /**\n * Create a new thread, optionally with initial messages\n */\n constructor(messages?: Message[]) {\n this.id = generateId();\n this._messages = messages ? [...messages] : [];\n this._createdAt = new Date();\n this._updatedAt = new Date();\n }\n\n /** All messages in the thread (readonly) */\n get messages(): readonly Message[] {\n return this._messages;\n }\n\n /** Number of messages */\n get length(): number {\n return this._messages.length;\n }\n\n /**\n * Append messages from a turn\n */\n append(turn: Turn): this {\n this._messages.push(...turn.messages);\n this._updatedAt = new Date();\n return this;\n }\n\n /**\n * Add raw messages\n */\n push(...messages: Message[]): this {\n this._messages.push(...messages);\n this._updatedAt = new Date();\n return this;\n }\n\n /**\n * Add a user message\n */\n user(content: string | UserContent[]): this {\n this._messages.push(new UserMessage(content));\n this._updatedAt = new Date();\n return this;\n }\n\n /**\n * Add an assistant message\n */\n assistant(content: string | AssistantContent[]): this {\n this._messages.push(new AssistantMessage(content));\n this._updatedAt = new Date();\n return this;\n }\n\n /**\n * Get messages by type\n */\n filter(type: MessageType): Message[] {\n return this._messages.filter((m) => m.type === type);\n }\n\n /**\n * Get the last N messages\n */\n tail(count: number): Message[] {\n return this._messages.slice(-count);\n }\n\n /**\n * Create a new thread with a subset of messages\n */\n slice(start?: number, end?: number): Thread {\n return new Thread(this._messages.slice(start, end));\n }\n\n /**\n * Clear all messages\n */\n clear(): this {\n this._messages = [];\n this._updatedAt = new Date();\n return this;\n }\n\n /**\n * Convert to plain message array\n */\n toMessages(): Message[] {\n return [...this._messages];\n }\n\n /**\n * Serialize to JSON\n */\n toJSON(): ThreadJSON {\n return {\n id: this.id,\n messages: this._messages.map((m) => this.messageToJSON(m)),\n createdAt: this._createdAt.toISOString(),\n updatedAt: this._updatedAt.toISOString(),\n };\n }\n\n /**\n * Deserialize from JSON\n */\n static fromJSON(json: ThreadJSON): Thread {\n const messages = json.messages.map((m) => Thread.messageFromJSON(m));\n const thread = new Thread(messages);\n // Override the generated id with the serialized one\n (thread as { id: string }).id = json.id;\n thread._createdAt = new Date(json.createdAt);\n thread._updatedAt = new Date(json.updatedAt);\n return thread;\n }\n\n /**\n * Iterate over messages\n */\n [Symbol.iterator](): Iterator<Message> {\n return this._messages[Symbol.iterator]();\n }\n\n /**\n * Convert a message to JSON\n */\n private messageToJSON(m: Message): MessageJSON {\n const base: MessageJSON = {\n id: m.id,\n type: m.type,\n content: [],\n metadata: m.metadata,\n timestamp: m.timestamp.toISOString(),\n };\n\n if (m instanceof UserMessage) {\n base.content = m.content;\n } else if (m instanceof AssistantMessage) {\n base.content = m.content;\n base.toolCalls = m.toolCalls;\n } else if (m instanceof ToolResultMessage) {\n base.results = m.results;\n }\n\n return base;\n }\n\n /**\n * Reconstruct a message from JSON\n */\n private static messageFromJSON(json: MessageJSON): Message {\n const options = {\n id: json.id,\n metadata: json.metadata,\n };\n\n switch (json.type) {\n case 'user':\n return new UserMessage(json.content as UserContent[], options);\n case 'assistant':\n return new AssistantMessage(\n json.content as AssistantContent[],\n json.toolCalls,\n options\n );\n case 'tool_result':\n return new ToolResultMessage(json.results ?? [], options);\n default:\n throw new Error(`Unknown message type: ${json.type}`);\n }\n }\n}\n","// Core entry points\nexport { llm } from './core/llm.ts';\nexport { createProvider } from './core/provider.ts';\nexport { Image } from './core/image.ts';\n\n// Namespace object for alternative import style\nimport { llm } from './core/llm.ts';\n\n/**\n * UPP namespace object\n * Provides ai.llm(), ai.embedding(), ai.image() style access\n */\nexport const ai = {\n llm,\n // embedding, // Coming soon\n // image, // Coming soon\n};\n\n// Re-export all types from types/index.ts\nexport * from './types/index.ts';\n\n// Re-export HTTP utilities\nexport {\n RoundRobinKeys,\n WeightedKeys,\n DynamicKey,\n ExponentialBackoff,\n LinearBackoff,\n NoRetry,\n TokenBucket,\n RetryAfterStrategy,\n} from './http/index.ts';\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAwDO,SAAS,WACd,UACA,gBACA,OACA,QACA,MACa;AAEb,QAAM,WAAW,SACd,OAAO,CAAC,MAA6B,EAAE,SAAS,WAAW,EAC3D,IAAI;AAEP,MAAI,CAAC,UAAU;AACb,UAAM,IAAI,MAAM,kDAAkD;AAAA,EACpE;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAKO,SAAS,aAAyB;AACvC,SAAO;AAAA,IACL,aAAa;AAAA,IACb,cAAc;AAAA,IACd,aAAa;AAAA,IACb,QAAQ,CAAC;AAAA,EACX;AACF;AAKO,SAAS,eAAe,QAAkC;AAC/D,QAAM,SAA+B,CAAC;AACtC,MAAI,cAAc;AAClB,MAAI,eAAe;AAEnB,aAAW,SAAS,QAAQ;AAC1B,mBAAe,MAAM;AACrB,oBAAgB,MAAM;AACtB,WAAO,KAAK;AAAA,MACV,aAAa,MAAM;AAAA,MACnB,cAAc,MAAM;AAAA,IACtB,CAAC;AAAA,EACH;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,aAAa,cAAc;AAAA,IAC3B;AAAA,EACF;AACF;;;ACzDO,SAAS,mBACd,WACA,aACA,iBACqB;AACrB,SAAO;AAAA,IACL,CAAC,OAAO,aAAa,IAAI;AACvB,aAAO;AAAA,IACT;AAAA,IACA,MAAM;AAAA,IACN,QAAQ;AACN,sBAAgB,MAAM;AAAA,IACxB;AAAA,EACF;AACF;AAKO,SAAS,UAAUA,OAAc,QAAQ,GAAgB;AAC9D,SAAO;AAAA,IACL,MAAM;AAAA,IACN;AAAA,IACA,OAAO,EAAE,MAAAA,MAAK;AAAA,EAChB;AACF;AAKO,SAAS,cACd,YACA,UACA,eACA,QAAQ,GACK;AACb,SAAO;AAAA,IACL,MAAM;AAAA,IACN;AAAA,IACA,OAAO,EAAE,YAAY,UAAU,cAAc;AAAA,EAC/C;AACF;AAKO,SAAS,eAA4B;AAC1C,SAAO;AAAA,IACL,MAAM;AAAA,IACN,OAAO;AAAA,IACP,OAAO,CAAC;AAAA,EACV;AACF;AAKO,SAAS,cAA2B;AACzC,SAAO;AAAA,IACL,MAAM;AAAA,IACN,OAAO;AAAA,IACP,OAAO,CAAC;AAAA,EACV;AACF;AAKO,SAAS,kBAAkB,OAA4B;AAC5D,SAAO;AAAA,IACL,MAAM;AAAA,IACN;AAAA,IACA,OAAO,CAAC;AAAA,EACV;AACF;AAKO,SAAS,iBAAiB,OAA4B;AAC3D,SAAO;AAAA,IACL,MAAM;AAAA,IACN;AAAA,IACA,OAAO,CAAC;AAAA,EACV;AACF;;;AClHA,IAAM,yBAAyB;AAKxB,SAAS,IACd,SACsB;AACtB,QAAM,EAAE,OAAO,UAAU,SAAS,CAAC,GAAG,QAAQ,QAAQ,OAAO,cAAc,UAAU,IAAI;AAGzF,QAAM,WAAW,SAAS;AAC1B,MAAI,CAAC,SAAS,WAAW,KAAK;AAC5B,UAAM,IAAI;AAAA,MACR,aAAa,SAAS,IAAI;AAAA,MAC1B;AAAA,MACA,SAAS;AAAA,MACT;AAAA,IACF;AAAA,EACF;AAGA,QAAM,aAAa,SAAS,WAAW,IAAI,KAAK,SAAS,OAAO;AAGhE,QAAM,eAAe,WAAW;AAGhC,MAAI,aAAa,CAAC,aAAa,kBAAkB;AAC/C,UAAM,IAAI;AAAA,MACR,aAAa,SAAS,IAAI;AAAA,MAC1B;AAAA,MACA,SAAS;AAAA,MACT;AAAA,IACF;AAAA,EACF;AAGA,MAAI,SAAS,MAAM,SAAS,KAAK,CAAC,aAAa,OAAO;AACpD,UAAM,IAAI;AAAA,MACR,aAAa,SAAS,IAAI;AAAA,MAC1B;AAAA,MACA,SAAS;AAAA,MACT;AAAA,IACF;AAAA,EACF;AAGA,QAAM,WAAiC;AAAA,IACrC,OAAO;AAAA,IACP;AAAA,IACA;AAAA,IACA;AAAA,IAEA,MAAM,SACJ,mBACG,QACY;AACf,YAAM,EAAE,SAAS,SAAS,IAAI,YAAY,gBAAgB,MAAM;AAChE,aAAO;AAAA,QACL;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAAA,IAEA,OACE,mBACG,QACW;AAEd,UAAI,CAAC,aAAa,WAAW;AAC3B,cAAM,IAAI;AAAA,UACR,aAAa,SAAS,IAAI;AAAA,UAC1B;AAAA,UACA,SAAS;AAAA,UACT;AAAA,QACF;AAAA,MACF;AACA,YAAM,EAAE,SAAS,SAAS,IAAI,YAAY,gBAAgB,MAAM;AAChE,aAAO;AAAA,QACL;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAOA,SAAS,kBAAkB,OAAkC;AAC3D,MAAI,iBAAiB,SAAS;AAC5B,WAAO;AAAA,EACT;AAGA,MACE,OAAO,UAAU,YACjB,UAAU,QACV,eAAe,SACf,UAAU,SACV,QAAQ,OACR;AACA,UAAM,MAAM;AAGZ,UAAM,eAAe,CAAC,QAAQ,aAAa,aAAa;AACxD,WAAO,aAAa,SAAS,IAAI,IAAc;AAAA,EACjD;AACA,SAAO;AACT;AAKA,SAAS,YACP,gBACA,QAC6C;AAE7C,MACE,OAAO,mBAAmB,YAC1B,mBAAmB,QACnB,cAAc,kBACd,MAAM,QAAS,eAA0B,QAAQ,GACjD;AACA,UAAM,SAAS;AACf,UAAMC,eAAc,OAAO,IAAI,cAAc;AAC7C,WAAO,EAAE,SAAS,CAAC,GAAG,OAAO,QAAQ,GAAG,UAAUA,aAAY;AAAA,EAChE;AAGA,MAAI,MAAM,QAAQ,cAAc,GAAG;AAEjC,QAAI,eAAe,WAAW,GAAG;AAC/B,YAAMA,eAAc,OAAO,IAAI,cAAc;AAC7C,aAAO,EAAE,SAAS,CAAC,GAAG,UAAUA,aAAY;AAAA,IAC9C;AACA,UAAM,QAAQ,eAAe,CAAC;AAC9B,QAAI,kBAAkB,KAAK,GAAG;AAE5B,YAAMA,eAAc,OAAO,IAAI,cAAc;AAC7C,aAAO,EAAE,SAAS,gBAA6B,UAAUA,aAAY;AAAA,IACvE;AAAA,EACF;AAGA,QAAM,YAAY,CAAC,gBAAkC,GAAG,MAAM;AAC9D,QAAM,cAAc,UAAU,IAAI,cAAc;AAChD,SAAO,EAAE,SAAS,CAAC,GAAG,UAAU,YAAY;AAC9C;AAKA,SAAS,eAAe,OAAgC;AACtD,MAAI,OAAO,UAAU,UAAU;AAC7B,WAAO,IAAI,YAAiB,KAAK;AAAA,EACnC;AAGA,MAAI,UAAU,SAAS,QAAQ,SAAS,eAAe,OAAO;AAC5D,WAAO;AAAA,EACT;AAGA,QAAM,QAAQ;AACd,MAAI,MAAM,SAAS,QAAQ;AACzB,WAAO,IAAI,YAAkB,MAAoB,IAAI;AAAA,EACvD;AAEA,SAAO,IAAI,YAAiB,CAAC,KAAY,CAAC;AAC5C;AAKA,eAAe,gBACb,OACA,QACA,QACA,QACA,OACA,cACA,WACA,SACA,aACe;AAEf;AAAA,IACE,CAAC,GAAG,SAAS,GAAG,WAAW;AAAA,IAC3B,MAAM;AAAA,IACN,MAAM,SAAS;AAAA,EACjB;AACA,QAAM,gBAAgB,cAAc,iBAAiB;AACrD,QAAM,cAAyB,CAAC,GAAG,SAAS,GAAG,WAAW;AAC1D,QAAM,iBAAkC,CAAC;AACzC,QAAM,SAAuB,CAAC;AAC9B,MAAI,SAAS;AAGb,MAAI;AAGJ,SAAO,SAAS,gBAAgB,GAAG;AACjC;AAEA,UAAM,UAA+B;AAAA,MACnC,UAAU;AAAA,MACV;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAEA,UAAM,WAAW,MAAM,MAAM,SAAS,OAAO;AAC7C,WAAO,KAAK,SAAS,KAAK;AAC1B,gBAAY,KAAK,SAAS,OAAO;AAGjC,QAAI,SAAS,SAAS,QAAW;AAC/B,uBAAiB,SAAS;AAAA,IAC5B;AAGA,QAAI,SAAS,QAAQ,gBAAgB,SAAS,MAAM,SAAS,GAAG;AAG9D,UAAI,SAAS,SAAS,QAAW;AAC/B;AAAA,MACF;AAGA,UAAI,UAAU,eAAe;AAC3B,cAAM,cAAc,kBAAkB,aAAa;AACnD,cAAM,IAAI;AAAA,UACR,+CAA+C,aAAa;AAAA,UAC5D;AAAA,UACA,MAAM,SAAS;AAAA,UACf;AAAA,QACF;AAAA,MACF;AAGA,YAAM,UAAU,MAAM;AAAA,QACpB,SAAS;AAAA,QACT;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAGA,kBAAY,KAAK,IAAI,kBAAkB,OAAO,CAAC;AAE/C;AAAA,IACF;AAGA;AAAA,EACF;AAGA,QAAM,OAAO,YAAY,iBAAiB;AAE1C,SAAO;AAAA,IACL,YAAY,MAAM,QAAQ,MAAM;AAAA;AAAA,IAChC;AAAA,IACA,eAAe,MAAM;AAAA,IACrB;AAAA,IACA;AAAA,EACF;AACF;AAKA,SAAS,cACP,OACA,QACA,QACA,QACA,OACA,cACA,WACA,SACA,aACc;AAEd;AAAA,IACE,CAAC,GAAG,SAAS,GAAG,WAAW;AAAA,IAC3B,MAAM;AAAA,IACN,MAAM,SAAS;AAAA,EACjB;AAEA,QAAM,kBAAkB,IAAI,gBAAgB;AAG5C,QAAM,cAAyB,CAAC,GAAG,SAAS,GAAG,WAAW;AAC1D,QAAM,iBAAkC,CAAC;AACzC,QAAM,SAAuB,CAAC;AAC9B,MAAI,SAAS;AACb,MAAI,iBAA+B;AACnC,MAAI;AAGJ,MAAI;AACJ,MAAI;AACJ,QAAM,gBAAgB,IAAI,QAAc,CAAC,SAAS,WAAW;AAC3D,uBAAmB;AACnB,sBAAkB;AAAA,EACpB,CAAC;AAED,QAAM,gBAAgB,cAAc,iBAAiB;AAGrD,kBAAgB,iBAA6D;AAC3E,QAAI;AACF,aAAO,SAAS,gBAAgB,GAAG;AACjC;AAEA,cAAM,UAA+B;AAAA,UACnC,UAAU;AAAA,UACV;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA,QAAQ,gBAAgB;AAAA,QAC1B;AAEA,cAAM,eAAe,MAAM,OAAO,OAAO;AAGzC,yBAAiB,SAAS,cAAc;AACtC,gBAAM;AAAA,QACR;AAGA,cAAM,WAAW,MAAM,aAAa;AACpC,eAAO,KAAK,SAAS,KAAK;AAC1B,oBAAY,KAAK,SAAS,OAAO;AAGjC,YAAI,SAAS,SAAS,QAAW;AAC/B,2BAAiB,SAAS;AAAA,QAC5B;AAGA,YAAI,SAAS,QAAQ,gBAAgB,SAAS,MAAM,SAAS,GAAG;AAG9D,cAAI,SAAS,SAAS,QAAW;AAC/B;AAAA,UACF;AAEA,cAAI,UAAU,eAAe;AAC3B,kBAAM,cAAc,kBAAkB,aAAa;AACnD,kBAAM,IAAI;AAAA,cACR,+CAA+C,aAAa;AAAA,cAC5D;AAAA,cACA,MAAM,SAAS;AAAA,cACf;AAAA,YACF;AAAA,UACF;AAGA,gBAAM,UAAU,MAAM;AAAA,YACpB,SAAS;AAAA,YACT;AAAA,YACA;AAAA,YACA;AAAA,UACF;AAGA,sBAAY,KAAK,IAAI,kBAAkB,OAAO,CAAC;AAE/C;AAAA,QACF;AAEA;AAAA,MACF;AACA,uBAAiB;AAAA,IACnB,SAAS,OAAO;AACd,uBAAiB;AACjB,sBAAgB,KAAc;AAC9B,YAAM;AAAA,IACR;AAAA,EACF;AAGA,QAAM,eAAe,YAA2B;AAC9C,UAAM;AAEN,QAAI,gBAAgB;AAClB,YAAM;AAAA,IACR;AAGA,UAAM,OAAO,YAAY,iBAAiB;AAE1C,WAAO;AAAA,MACL,YAAY,MAAM,QAAQ,MAAM;AAAA,MAChC;AAAA,MACA,eAAe,MAAM;AAAA,MACrB;AAAA,MACA;AAAA,IACF;AAAA,EACF,GAAG;AAEH,SAAO,mBAAmB,eAAe,GAAG,aAAa,eAAe;AAC1E;AAKA,eAAe,aACb,SACA,OACA,cACA,YACuB;AACvB,QAAM,YAAY,QAAQ,aAAa,CAAC;AACxC,QAAM,UAAwB,CAAC;AAG/B,QAAM,UAAU,IAAI,IAAI,MAAM,IAAI,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;AAGrD,QAAM,WAAW,UAAU,IAAI,OAAO,SAAS;AAC7C,UAAM,OAAO,QAAQ,IAAI,KAAK,QAAQ;AACtC,QAAI,CAAC,MAAM;AACT,aAAO;AAAA,QACL,YAAY,KAAK;AAAA,QACjB,QAAQ,SAAS,KAAK,QAAQ;AAAA,QAC9B,SAAS;AAAA,MACX;AAAA,IACF;AAEA,UAAM,YAAY,KAAK,IAAI;AAG3B,UAAM,cAAc,aAAa,MAAM,KAAK,SAAS;AAGrD,QAAI,cAAc,cAAc;AAC9B,YAAM,YAAY,MAAM,aAAa,aAAa,MAAM,KAAK,SAAS;AACtE,UAAI,CAAC,WAAW;AACd,eAAO;AAAA,UACL,YAAY,KAAK;AAAA,UACjB,QAAQ;AAAA,UACR,SAAS;AAAA,QACX;AAAA,MACF;AAAA,IACF;AAGA,QAAI,WAAW;AACf,QAAI,KAAK,UAAU;AACjB,UAAI;AACF,mBAAW,MAAM,KAAK,SAAS,KAAK,SAAS;AAAA,MAC/C,SAAS,OAAO;AAEd,cAAM;AAAA,MACR;AAAA,IACF;AAEA,QAAI,CAAC,UAAU;AACb,YAAM,YAA2B;AAAA,QAC/B,UAAU,KAAK;AAAA,QACf,YAAY,KAAK;AAAA,QACjB,WAAW,KAAK;AAAA,QAChB,QAAQ;AAAA,QACR,SAAS;AAAA,QACT,UAAU,KAAK,IAAI,IAAI;AAAA,QACvB,UAAU;AAAA,MACZ;AACA,iBAAW,KAAK,SAAS;AAEzB,aAAO;AAAA,QACL,YAAY,KAAK;AAAA,QACjB,QAAQ;AAAA,QACR,SAAS;AAAA,MACX;AAAA,IACF;AAGA,QAAI;AACF,YAAM,SAAS,MAAM,KAAK,IAAI,KAAK,SAAS;AAE5C,YAAM,cAAc,cAAc,MAAM,KAAK,WAAW,MAAM;AAE9D,YAAM,YAA2B;AAAA,QAC/B,UAAU,KAAK;AAAA,QACf,YAAY,KAAK;AAAA,QACjB,WAAW,KAAK;AAAA,QAChB;AAAA,QACA,SAAS;AAAA,QACT,UAAU,KAAK,IAAI,IAAI;AAAA,QACvB;AAAA,MACF;AACA,iBAAW,KAAK,SAAS;AAEzB,aAAO;AAAA,QACL,YAAY,KAAK;AAAA,QACjB;AAAA,QACA,SAAS;AAAA,MACX;AAAA,IACF,SAAS,OAAO;AACd,YAAM,cAAc,UAAU,MAAM,KAAK,WAAW,KAAc;AAElE,YAAM,eAAe,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAE1E,YAAM,YAA2B;AAAA,QAC/B,UAAU,KAAK;AAAA,QACf,YAAY,KAAK;AAAA,QACjB,WAAW,KAAK;AAAA,QAChB,QAAQ;AAAA,QACR,SAAS;AAAA,QACT,UAAU,KAAK,IAAI,IAAI;AAAA,QACvB;AAAA,MACF;AACA,iBAAW,KAAK,SAAS;AAEzB,aAAO;AAAA,QACL,YAAY,KAAK;AAAA,QACjB,QAAQ;AAAA,QACR,SAAS;AAAA,MACX;AAAA,IACF;AAAA,EACF,CAAC;AAED,UAAQ,KAAK,GAAI,MAAM,QAAQ,IAAI,QAAQ,CAAE;AAC7C,SAAO;AACT;AAKA,SAAS,0BACP,UACA,cACA,cACM;AACN,aAAW,OAAO,UAAU;AAC1B,QAAI,CAAC,cAAc,GAAG,EAAG;AAEzB,eAAW,SAAS,IAAI,SAAS;AAC/B,UAAI,MAAM,SAAS,WAAW,CAAC,aAAa,YAAY;AACtD,cAAM,IAAI;AAAA,UACR,aAAa,YAAY;AAAA,UACzB;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAAA,MACF;AACA,UAAI,MAAM,SAAS,WAAW,CAAC,aAAa,YAAY;AACtD,cAAM,IAAI;AAAA,UACR,aAAa,YAAY;AAAA,UACzB;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAAA,MACF;AACA,UAAI,MAAM,SAAS,WAAW,CAAC,aAAa,YAAY;AACtD,cAAM,IAAI;AAAA,UACR,aAAa,YAAY;AAAA,UACzB;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;;;AC1mBO,IAAM,QAAN,MAAM,OAAM;AAAA,EACR;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAED,YACN,QACA,UACA,OACA,QACA;AACA,SAAK,SAAS;AACd,SAAK,WAAW;AAChB,SAAK,QAAQ;AACb,SAAK,SAAS;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,UAAmB;AACrB,WAAO,KAAK,OAAO,SAAS;AAAA,EAC9B;AAAA;AAAA;AAAA;AAAA,EAKA,WAAmB;AACjB,QAAI,KAAK,OAAO,SAAS,UAAU;AACjC,aAAO,KAAK,OAAO;AAAA,IACrB;AAEA,QAAI,KAAK,OAAO,SAAS,SAAS;AAChC,aAAO;AAAA,QACL,MAAM,KAAK,KAAK,OAAO,IAAI,EACxB,IAAI,CAAC,MAAM,OAAO,aAAa,CAAC,CAAC,EACjC,KAAK,EAAE;AAAA,MACZ;AAAA,IACF;AAEA,UAAM,IAAI,MAAM,4DAA4D;AAAA,EAC9E;AAAA;AAAA;AAAA;AAAA,EAKA,YAAoB;AAClB,UAAM,SAAS,KAAK,SAAS;AAC7B,WAAO,QAAQ,KAAK,QAAQ,WAAW,MAAM;AAAA,EAC/C;AAAA;AAAA;AAAA;AAAA,EAKA,UAAsB;AACpB,QAAI,KAAK,OAAO,SAAS,SAAS;AAChC,aAAO,KAAK,OAAO;AAAA,IACrB;AAEA,QAAI,KAAK,OAAO,SAAS,UAAU;AACjC,YAAM,eAAe,KAAK,KAAK,OAAO,IAAI;AAC1C,YAAM,QAAQ,IAAI,WAAW,aAAa,MAAM;AAChD,eAAS,IAAI,GAAG,IAAI,aAAa,QAAQ,KAAK;AAC5C,cAAM,CAAC,IAAI,aAAa,WAAW,CAAC;AAAA,MACtC;AACA,aAAO;AAAA,IACT;AAEA,UAAM,IAAI,MAAM,yDAAyD;AAAA,EAC3E;AAAA;AAAA;AAAA;AAAA,EAKA,QAAgB;AACd,QAAI,KAAK,OAAO,SAAS,OAAO;AAC9B,aAAO,KAAK,OAAO;AAAA,IACrB;AAEA,UAAM,IAAI,MAAM,wCAAwC;AAAA,EAC1D;AAAA;AAAA;AAAA;AAAA,EAKA,UAAsB;AACpB,WAAO;AAAA,MACL,MAAM;AAAA,MACN,QAAQ,KAAK;AAAA,MACb,UAAU,KAAK;AAAA,MACf,OAAO,KAAK;AAAA,MACZ,QAAQ,KAAK;AAAA,IACf;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,aAAa,SAAS,MAA8B;AAClD,UAAM,OAAO,IAAI,KAAK,IAAI;AAC1B,UAAM,OAAO,MAAM,KAAK,YAAY;AACpC,UAAM,WAAW,KAAK,QAAQ,eAAe,IAAI;AAEjD,WAAO,IAAI;AAAA,MACT,EAAE,MAAM,SAAS,MAAM,IAAI,WAAW,IAAI,EAAE;AAAA,MAC5C;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,QAAQ,KAAa,UAA0B;AACpD,UAAM,WAAW,YAAY,sBAAsB,GAAG;AACtD,WAAO,IAAI,OAAM,EAAE,MAAM,OAAO,IAAI,GAAG,QAAQ;AAAA,EACjD;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,UAAU,MAAkB,UAAyB;AAC1D,WAAO,IAAI,OAAM,EAAE,MAAM,SAAS,KAAK,GAAG,QAAQ;AAAA,EACpD;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,WAAW,QAAgB,UAAyB;AACzD,WAAO,IAAI,OAAM,EAAE,MAAM,UAAU,MAAM,OAAO,GAAG,QAAQ;AAAA,EAC7D;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,UAAU,OAA0B;AACzC,WAAO,IAAI;AAAA,MACT,MAAM;AAAA,MACN,MAAM;AAAA,MACN,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AAAA,EACF;AACF;AAKA,SAAS,eAAe,MAAsB;AAC5C,QAAM,MAAM,KAAK,MAAM,GAAG,EAAE,IAAI,GAAG,YAAY;AAE/C,UAAQ,KAAK;AAAA,IACX,KAAK;AAAA,IACL,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT;AACE,aAAO;AAAA,EACX;AACF;AAKA,SAAS,sBAAsB,KAAqB;AAClD,MAAI;AACF,UAAM,WAAW,IAAI,IAAI,GAAG,EAAE;AAC9B,WAAO,eAAe,QAAQ;AAAA,EAChC,QAAQ;AACN,WAAO;AAAA,EACT;AACF;;;AC5FO,SAAS,KAAK,SAA4B;AAC/C,SAAO,EAAE,MAAM,QAAQ,MAAM,QAAQ;AACvC;AAKO,SAAS,YAAY,OAAyC;AACnE,SAAO,MAAM,SAAS;AACxB;AAKO,SAAS,aAAa,OAA0C;AACrE,SAAO,MAAM,SAAS;AACxB;AAKO,SAAS,aAAa,OAA0C;AACrE,SAAO,MAAM,SAAS;AACxB;AAKO,SAAS,aAAa,OAA0C;AACrE,SAAO,MAAM,SAAS;AACxB;AAKO,SAAS,cAAc,OAA2C;AACvE,SAAO,MAAM,SAAS;AACxB;;;AC7FO,IAAM,SAAN,MAAM,QAAO;AAAA;AAAA,EAET;AAAA;AAAA,EAGD;AAAA;AAAA,EAGA;AAAA;AAAA,EAGA;AAAA;AAAA;AAAA;AAAA,EAKR,YAAY,UAAsB;AAChC,SAAK,KAAK,WAAW;AACrB,SAAK,YAAY,WAAW,CAAC,GAAG,QAAQ,IAAI,CAAC;AAC7C,SAAK,aAAa,oBAAI,KAAK;AAC3B,SAAK,aAAa,oBAAI,KAAK;AAAA,EAC7B;AAAA;AAAA,EAGA,IAAI,WAA+B;AACjC,WAAO,KAAK;AAAA,EACd;AAAA;AAAA,EAGA,IAAI,SAAiB;AACnB,WAAO,KAAK,UAAU;AAAA,EACxB;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,MAAkB;AACvB,SAAK,UAAU,KAAK,GAAG,KAAK,QAAQ;AACpC,SAAK,aAAa,oBAAI,KAAK;AAC3B,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,QAAQ,UAA2B;AACjC,SAAK,UAAU,KAAK,GAAG,QAAQ;AAC/B,SAAK,aAAa,oBAAI,KAAK;AAC3B,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,KAAK,SAAuC;AAC1C,SAAK,UAAU,KAAK,IAAI,YAAY,OAAO,CAAC;AAC5C,SAAK,aAAa,oBAAI,KAAK;AAC3B,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,UAAU,SAA4C;AACpD,SAAK,UAAU,KAAK,IAAI,iBAAiB,OAAO,CAAC;AACjD,SAAK,aAAa,oBAAI,KAAK;AAC3B,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,MAA8B;AACnC,WAAO,KAAK,UAAU,OAAO,CAAC,MAAM,EAAE,SAAS,IAAI;AAAA,EACrD;AAAA;AAAA;AAAA;AAAA,EAKA,KAAK,OAA0B;AAC7B,WAAO,KAAK,UAAU,MAAM,CAAC,KAAK;AAAA,EACpC;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,OAAgB,KAAsB;AAC1C,WAAO,IAAI,QAAO,KAAK,UAAU,MAAM,OAAO,GAAG,CAAC;AAAA,EACpD;AAAA;AAAA;AAAA;AAAA,EAKA,QAAc;AACZ,SAAK,YAAY,CAAC;AAClB,SAAK,aAAa,oBAAI,KAAK;AAC3B,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,aAAwB;AACtB,WAAO,CAAC,GAAG,KAAK,SAAS;AAAA,EAC3B;AAAA;AAAA;AAAA;AAAA,EAKA,SAAqB;AACnB,WAAO;AAAA,MACL,IAAI,KAAK;AAAA,MACT,UAAU,KAAK,UAAU,IAAI,CAAC,MAAM,KAAK,cAAc,CAAC,CAAC;AAAA,MACzD,WAAW,KAAK,WAAW,YAAY;AAAA,MACvC,WAAW,KAAK,WAAW,YAAY;AAAA,IACzC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,SAAS,MAA0B;AACxC,UAAM,WAAW,KAAK,SAAS,IAAI,CAAC,MAAM,QAAO,gBAAgB,CAAC,CAAC;AACnE,UAAM,SAAS,IAAI,QAAO,QAAQ;AAElC,IAAC,OAA0B,KAAK,KAAK;AACrC,WAAO,aAAa,IAAI,KAAK,KAAK,SAAS;AAC3C,WAAO,aAAa,IAAI,KAAK,KAAK,SAAS;AAC3C,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,CAAC,OAAO,QAAQ,IAAuB;AACrC,WAAO,KAAK,UAAU,OAAO,QAAQ,EAAE;AAAA,EACzC;AAAA;AAAA;AAAA;AAAA,EAKQ,cAAc,GAAyB;AAC7C,UAAM,OAAoB;AAAA,MACxB,IAAI,EAAE;AAAA,MACN,MAAM,EAAE;AAAA,MACR,SAAS,CAAC;AAAA,MACV,UAAU,EAAE;AAAA,MACZ,WAAW,EAAE,UAAU,YAAY;AAAA,IACrC;AAEA,QAAI,aAAa,aAAa;AAC5B,WAAK,UAAU,EAAE;AAAA,IACnB,WAAW,aAAa,kBAAkB;AACxC,WAAK,UAAU,EAAE;AACjB,WAAK,YAAY,EAAE;AAAA,IACrB,WAAW,aAAa,mBAAmB;AACzC,WAAK,UAAU,EAAE;AAAA,IACnB;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,OAAe,gBAAgB,MAA4B;AACzD,UAAM,UAAU;AAAA,MACd,IAAI,KAAK;AAAA,MACT,UAAU,KAAK;AAAA,IACjB;AAEA,YAAQ,KAAK,MAAM;AAAA,MACjB,KAAK;AACH,eAAO,IAAI,YAAY,KAAK,SAA0B,OAAO;AAAA,MAC/D,KAAK;AACH,eAAO,IAAI;AAAA,UACT,KAAK;AAAA,UACL,KAAK;AAAA,UACL;AAAA,QACF;AAAA,MACF,KAAK;AACH,eAAO,IAAI,kBAAkB,KAAK,WAAW,CAAC,GAAG,OAAO;AAAA,MAC1D;AACE,cAAM,IAAI,MAAM,yBAAyB,KAAK,IAAI,EAAE;AAAA,IACxD;AAAA,EACF;AACF;;;ACrNO,IAAM,KAAK;AAAA,EAChB;AAAA;AAAA;AAGF;","names":["text","newMessages"]}
|
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
import { b as Provider, M as ModelReference, a as LLMHandler } from '../provider-CUJWjgNl.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* xAI-specific LLM parameters
|
|
5
|
+
* These are passed through to the relevant xAI APIs (Completions, Responses, Messages)
|
|
6
|
+
*
|
|
7
|
+
* xAI's APIs are compatible with OpenAI and Anthropic SDKs, supporting three API modes:
|
|
8
|
+
* - Chat Completions API (OpenAI-compatible)
|
|
9
|
+
* - Responses API (OpenAI Responses-compatible, with stateful conversations)
|
|
10
|
+
* - Messages API (Anthropic-compatible)
|
|
11
|
+
*/
|
|
12
|
+
interface XAILLMParams {
|
|
13
|
+
/** Maximum number of tokens to generate */
|
|
14
|
+
max_tokens?: number;
|
|
15
|
+
/** Maximum completion tokens (Chat Completions API) */
|
|
16
|
+
max_completion_tokens?: number;
|
|
17
|
+
/** Maximum output tokens (Responses API) */
|
|
18
|
+
max_output_tokens?: number;
|
|
19
|
+
/** Temperature for randomness (0.0 - 2.0) */
|
|
20
|
+
temperature?: number;
|
|
21
|
+
/** Top-p (nucleus) sampling (0.0 - 1.0) */
|
|
22
|
+
top_p?: number;
|
|
23
|
+
/** Top-k sampling (Messages API only) */
|
|
24
|
+
top_k?: number;
|
|
25
|
+
/** Frequency penalty (-2.0 - 2.0) */
|
|
26
|
+
frequency_penalty?: number;
|
|
27
|
+
/** Presence penalty (-2.0 - 2.0) */
|
|
28
|
+
presence_penalty?: number;
|
|
29
|
+
/** Custom stop sequences */
|
|
30
|
+
stop?: string | string[];
|
|
31
|
+
/** Stop sequences (Messages API) */
|
|
32
|
+
stop_sequences?: string[];
|
|
33
|
+
/** Number of completions to generate */
|
|
34
|
+
n?: number;
|
|
35
|
+
/** Enable logprobs */
|
|
36
|
+
logprobs?: boolean;
|
|
37
|
+
/** Number of top logprobs to return (0-20) */
|
|
38
|
+
top_logprobs?: number;
|
|
39
|
+
/** Seed for deterministic sampling */
|
|
40
|
+
seed?: number;
|
|
41
|
+
/** User identifier for abuse detection */
|
|
42
|
+
user?: string;
|
|
43
|
+
/** Logit bias map (Chat Completions API) */
|
|
44
|
+
logit_bias?: Record<string, number>;
|
|
45
|
+
/** Whether to enable parallel tool calls */
|
|
46
|
+
parallel_tool_calls?: boolean;
|
|
47
|
+
/**
|
|
48
|
+
* Reasoning effort for Grok 3 Mini models
|
|
49
|
+
* Note: Only 'low' and 'high' are supported by xAI
|
|
50
|
+
* Grok 4 does not support this parameter
|
|
51
|
+
*/
|
|
52
|
+
reasoning_effort?: 'low' | 'high';
|
|
53
|
+
/** Reasoning configuration (Responses API) */
|
|
54
|
+
reasoning?: {
|
|
55
|
+
effort?: 'low' | 'high';
|
|
56
|
+
/** Include encrypted reasoning content for continuation */
|
|
57
|
+
encrypted_content?: boolean;
|
|
58
|
+
};
|
|
59
|
+
/** Truncation strategy (Responses API) */
|
|
60
|
+
truncation?: 'auto' | 'disabled';
|
|
61
|
+
/** Fields to include in Responses API output */
|
|
62
|
+
include?: string[];
|
|
63
|
+
/** Continue from a previous response (Responses API) */
|
|
64
|
+
previous_response_id?: string;
|
|
65
|
+
/** Store response for continuation (Responses API) */
|
|
66
|
+
store?: boolean;
|
|
67
|
+
/** Store messages on xAI servers (default: true for Responses API) */
|
|
68
|
+
store_messages?: boolean;
|
|
69
|
+
/** Metadata key-value pairs */
|
|
70
|
+
metadata?: Record<string, string>;
|
|
71
|
+
/** Response format for structured output (Chat Completions API only) */
|
|
72
|
+
response_format?: XAIResponseFormat;
|
|
73
|
+
/**
|
|
74
|
+
* Live Search parameters (deprecated, will be removed Dec 15, 2025)
|
|
75
|
+
* Use Agent Tools API instead for new implementations
|
|
76
|
+
*/
|
|
77
|
+
search_parameters?: XAISearchParameters;
|
|
78
|
+
/**
|
|
79
|
+
* Server-side agentic tools (Agent Tools API)
|
|
80
|
+
* These are executed server-side by xAI
|
|
81
|
+
*/
|
|
82
|
+
agent_tools?: XAIAgentTool[];
|
|
83
|
+
/** Metadata for the request (Messages API) */
|
|
84
|
+
messages_metadata?: {
|
|
85
|
+
user_id?: string;
|
|
86
|
+
};
|
|
87
|
+
/** Extended thinking configuration (Messages API) */
|
|
88
|
+
thinking?: {
|
|
89
|
+
type: 'enabled';
|
|
90
|
+
budget_tokens: number;
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* API mode for xAI provider
|
|
95
|
+
*/
|
|
96
|
+
type XAIAPIMode = 'completions' | 'responses' | 'messages';
|
|
97
|
+
/**
|
|
98
|
+
* Model options when creating a model reference
|
|
99
|
+
*/
|
|
100
|
+
interface XAIModelOptions {
|
|
101
|
+
/** Which API to use */
|
|
102
|
+
api?: XAIAPIMode;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Model reference with xAI-specific options
|
|
106
|
+
*/
|
|
107
|
+
interface XAIModelReference {
|
|
108
|
+
modelId: string;
|
|
109
|
+
options?: XAIModelOptions;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* xAI provider configuration
|
|
113
|
+
*/
|
|
114
|
+
interface XAIConfig {
|
|
115
|
+
/** Which API to use: 'completions', 'responses', or 'messages' */
|
|
116
|
+
api?: XAIAPIMode;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Live Search parameters (deprecated)
|
|
120
|
+
*/
|
|
121
|
+
interface XAISearchParameters {
|
|
122
|
+
/** Search mode */
|
|
123
|
+
mode?: 'auto' | 'on' | 'off';
|
|
124
|
+
/** Limit search to specific date range */
|
|
125
|
+
from_date?: string;
|
|
126
|
+
/** End date for search range */
|
|
127
|
+
to_date?: string;
|
|
128
|
+
/** Sources to search */
|
|
129
|
+
sources?: Array<'web' | 'x' | 'news' | 'rss'>;
|
|
130
|
+
/** Maximum number of search results */
|
|
131
|
+
max_search_results?: number;
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Server-side agentic tools
|
|
135
|
+
*/
|
|
136
|
+
interface XAIAgentTool {
|
|
137
|
+
type: 'web_search' | 'x_search' | 'code_execution';
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Response format
|
|
141
|
+
*/
|
|
142
|
+
type XAIResponseFormat = {
|
|
143
|
+
type: 'text';
|
|
144
|
+
} | {
|
|
145
|
+
type: 'json_object';
|
|
146
|
+
} | {
|
|
147
|
+
type: 'json_schema';
|
|
148
|
+
json_schema: {
|
|
149
|
+
name: string;
|
|
150
|
+
description?: string;
|
|
151
|
+
schema: Record<string, unknown>;
|
|
152
|
+
strict?: boolean;
|
|
153
|
+
};
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* xAI provider options
|
|
158
|
+
*/
|
|
159
|
+
interface XAIProviderOptions {
|
|
160
|
+
/**
|
|
161
|
+
* Which API to use:
|
|
162
|
+
* - 'completions': Chat Completions API (OpenAI-compatible, default)
|
|
163
|
+
* - 'responses': Responses API (OpenAI Responses-compatible, stateful)
|
|
164
|
+
* - 'messages': Messages API (Anthropic-compatible)
|
|
165
|
+
*/
|
|
166
|
+
api?: XAIAPIMode;
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* xAI provider with configurable API mode
|
|
170
|
+
*
|
|
171
|
+
* xAI's APIs are compatible with OpenAI and Anthropic SDKs, supporting three API modes:
|
|
172
|
+
* - Chat Completions API (OpenAI-compatible) - default, recommended
|
|
173
|
+
* - Responses API (OpenAI Responses-compatible) - stateful conversations
|
|
174
|
+
* - Messages API (Anthropic-compatible) - for migration from Anthropic
|
|
175
|
+
*
|
|
176
|
+
* @example
|
|
177
|
+
* // Using the Chat Completions API (default)
|
|
178
|
+
* const model = xai('grok-4');
|
|
179
|
+
*
|
|
180
|
+
* @example
|
|
181
|
+
* // Using the Responses API (stateful)
|
|
182
|
+
* const model = xai('grok-4', { api: 'responses' });
|
|
183
|
+
*
|
|
184
|
+
* @example
|
|
185
|
+
* // Using the Messages API (Anthropic-compatible)
|
|
186
|
+
* const model = xai('grok-4', { api: 'messages' });
|
|
187
|
+
*/
|
|
188
|
+
interface XAIProvider extends Provider<XAIProviderOptions> {
|
|
189
|
+
/**
|
|
190
|
+
* Create a model reference
|
|
191
|
+
* @param modelId - The model identifier (e.g., 'grok-4', 'grok-4.1-fast', 'grok-3-mini')
|
|
192
|
+
* @param options - Provider options including API selection
|
|
193
|
+
*/
|
|
194
|
+
(modelId: string, options?: XAIProviderOptions): ModelReference<XAIProviderOptions>;
|
|
195
|
+
/** Provider name */
|
|
196
|
+
readonly name: 'xai';
|
|
197
|
+
/** Provider version */
|
|
198
|
+
readonly version: string;
|
|
199
|
+
/** Supported modalities */
|
|
200
|
+
readonly modalities: {
|
|
201
|
+
llm: LLMHandler<XAILLMParams>;
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* xAI provider
|
|
206
|
+
*
|
|
207
|
+
* Supports three API modes:
|
|
208
|
+
* - Chat Completions API (default, OpenAI-compatible)
|
|
209
|
+
* - Responses API (stateful, OpenAI Responses-compatible)
|
|
210
|
+
* - Messages API (Anthropic-compatible)
|
|
211
|
+
*
|
|
212
|
+
* xAI's Grok models support:
|
|
213
|
+
* - Real-time search via Live Search API (deprecated Dec 2025) or Agent Tools API
|
|
214
|
+
* - Reasoning with `reasoning_effort` parameter (for Grok 3 Mini)
|
|
215
|
+
* - Tool/function calling
|
|
216
|
+
* - Image input
|
|
217
|
+
* - Streaming responses
|
|
218
|
+
* - Structured output (JSON mode)
|
|
219
|
+
*
|
|
220
|
+
* @example
|
|
221
|
+
* ```ts
|
|
222
|
+
* import { xai } from './providers/xai';
|
|
223
|
+
* import { llm } from './core/llm';
|
|
224
|
+
*
|
|
225
|
+
* // Using Chat Completions API (default, recommended)
|
|
226
|
+
* const model = llm({
|
|
227
|
+
* model: xai('grok-4'),
|
|
228
|
+
* params: { max_tokens: 1000 }
|
|
229
|
+
* });
|
|
230
|
+
*
|
|
231
|
+
* // Using Responses API (stateful conversations)
|
|
232
|
+
* const statefulModel = llm({
|
|
233
|
+
* model: xai('grok-4', { api: 'responses' }),
|
|
234
|
+
* params: {
|
|
235
|
+
* max_output_tokens: 1000,
|
|
236
|
+
* store: true, // Enable stateful storage
|
|
237
|
+
* }
|
|
238
|
+
* });
|
|
239
|
+
*
|
|
240
|
+
* // Continue a previous conversation
|
|
241
|
+
* const continuedModel = llm({
|
|
242
|
+
* model: xai('grok-4', { api: 'responses' }),
|
|
243
|
+
* params: {
|
|
244
|
+
* previous_response_id: 'resp_123...',
|
|
245
|
+
* }
|
|
246
|
+
* });
|
|
247
|
+
*
|
|
248
|
+
* // Using Messages API (Anthropic-compatible)
|
|
249
|
+
* const anthropicModel = llm({
|
|
250
|
+
* model: xai('grok-4', { api: 'messages' }),
|
|
251
|
+
* params: { max_tokens: 1000 }
|
|
252
|
+
* });
|
|
253
|
+
*
|
|
254
|
+
* // Using reasoning effort (Grok 3 Mini only)
|
|
255
|
+
* const reasoningModel = llm({
|
|
256
|
+
* model: xai('grok-3-mini'),
|
|
257
|
+
* params: {
|
|
258
|
+
* max_tokens: 1000,
|
|
259
|
+
* reasoning_effort: 'high', // 'low' or 'high'
|
|
260
|
+
* }
|
|
261
|
+
* });
|
|
262
|
+
*
|
|
263
|
+
* // Using Live Search (deprecated Dec 2025)
|
|
264
|
+
* const searchModel = llm({
|
|
265
|
+
* model: xai('grok-4'),
|
|
266
|
+
* params: {
|
|
267
|
+
* max_tokens: 1000,
|
|
268
|
+
* search_parameters: {
|
|
269
|
+
* mode: 'auto',
|
|
270
|
+
* sources: ['web', 'x', 'news'],
|
|
271
|
+
* }
|
|
272
|
+
* }
|
|
273
|
+
* });
|
|
274
|
+
*
|
|
275
|
+
* // Generate
|
|
276
|
+
* const turn = await model.generate('Hello!');
|
|
277
|
+
* console.log(turn.response.text);
|
|
278
|
+
* ```
|
|
279
|
+
*/
|
|
280
|
+
declare const xai: XAIProvider;
|
|
281
|
+
|
|
282
|
+
export { type XAIAPIMode, type XAIAgentTool, type XAIConfig, type XAILLMParams, type XAIModelOptions, type XAIModelReference, type XAIProvider, type XAIProviderOptions, type XAISearchParameters, xai };
|