@providerprotocol/ai 0.0.9 → 0.0.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -375,7 +375,7 @@ declare function aggregateUsage(usages: TokenUsage[]): TokenUsage;
375
375
  /**
376
376
  * Stream event types
377
377
  */
378
- type StreamEventType = 'text_delta' | 'reasoning_delta' | 'image_delta' | 'audio_delta' | 'video_delta' | 'tool_call_delta' | 'message_start' | 'message_stop' | 'content_block_start' | 'content_block_stop';
378
+ type StreamEventType = 'text_delta' | 'reasoning_delta' | 'image_delta' | 'audio_delta' | 'video_delta' | 'tool_call_delta' | 'tool_execution_start' | 'tool_execution_end' | 'message_start' | 'message_stop' | 'content_block_start' | 'content_block_stop';
379
379
  /**
380
380
  * Event delta data (type-specific)
381
381
  */
@@ -385,6 +385,12 @@ interface EventDelta {
385
385
  toolCallId?: string;
386
386
  toolName?: string;
387
387
  argumentsJson?: string;
388
+ /** Tool execution result (for tool_execution_end) */
389
+ result?: unknown;
390
+ /** Whether tool execution errored (for tool_execution_end) */
391
+ isError?: boolean;
392
+ /** Timestamp in ms (for tool_execution_start/end) */
393
+ timestamp?: number;
388
394
  }
389
395
  /**
390
396
  * A streaming event
package/dist/index.js CHANGED
@@ -123,6 +123,20 @@ function contentBlockStop(index) {
123
123
  delta: {}
124
124
  };
125
125
  }
126
+ function toolExecutionStart(toolCallId, toolName, timestamp, index = 0) {
127
+ return {
128
+ type: "tool_execution_start",
129
+ index,
130
+ delta: { toolCallId, toolName, timestamp }
131
+ };
132
+ }
133
+ function toolExecutionEnd(toolCallId, toolName, result, isError, timestamp, index = 0) {
134
+ return {
135
+ type: "tool_execution_end",
136
+ index,
137
+ delta: { toolCallId, toolName, result, isError, timestamp }
138
+ };
139
+ }
126
140
 
127
141
  // src/core/llm.ts
128
142
  var DEFAULT_MAX_ITERATIONS = 10;
@@ -362,12 +376,17 @@ function executeStream(model, config, system, params, tools, toolStrategy, struc
362
376
  "llm"
363
377
  );
364
378
  }
379
+ const toolEvents = [];
365
380
  const results = await executeTools(
366
381
  response.message,
367
382
  tools,
368
383
  toolStrategy,
369
- toolExecutions
384
+ toolExecutions,
385
+ (event) => toolEvents.push(event)
370
386
  );
387
+ for (const event of toolEvents) {
388
+ yield event;
389
+ }
371
390
  allMessages.push(new ToolResultMessage(results));
372
391
  continue;
373
392
  }
@@ -396,11 +415,11 @@ function executeStream(model, config, system, params, tools, toolStrategy, struc
396
415
  })();
397
416
  return createStreamResult(generateStream(), turnPromise, abortController);
398
417
  }
399
- async function executeTools(message, tools, toolStrategy, executions) {
418
+ async function executeTools(message, tools, toolStrategy, executions, onEvent) {
400
419
  const toolCalls = message.toolCalls ?? [];
401
420
  const results = [];
402
421
  const toolMap = new Map(tools.map((t) => [t.name, t]));
403
- const promises = toolCalls.map(async (call) => {
422
+ const promises = toolCalls.map(async (call, index) => {
404
423
  const tool = toolMap.get(call.toolName);
405
424
  if (!tool) {
406
425
  return {
@@ -410,10 +429,13 @@ async function executeTools(message, tools, toolStrategy, executions) {
410
429
  };
411
430
  }
412
431
  const startTime = Date.now();
432
+ onEvent?.(toolExecutionStart(call.toolCallId, tool.name, startTime, index));
413
433
  await toolStrategy?.onToolCall?.(tool, call.arguments);
414
434
  if (toolStrategy?.onBeforeCall) {
415
435
  const shouldRun = await toolStrategy.onBeforeCall(tool, call.arguments);
416
436
  if (!shouldRun) {
437
+ const endTime = Date.now();
438
+ onEvent?.(toolExecutionEnd(call.toolCallId, tool.name, "Tool execution skipped", true, endTime, index));
417
439
  return {
418
440
  toolCallId: call.toolCallId,
419
441
  result: "Tool execution skipped",
@@ -430,16 +452,18 @@ async function executeTools(message, tools, toolStrategy, executions) {
430
452
  }
431
453
  }
432
454
  if (!approved) {
455
+ const endTime = Date.now();
433
456
  const execution = {
434
457
  toolName: tool.name,
435
458
  toolCallId: call.toolCallId,
436
459
  arguments: call.arguments,
437
460
  result: "Tool execution denied",
438
461
  isError: true,
439
- duration: Date.now() - startTime,
462
+ duration: endTime - startTime,
440
463
  approved: false
441
464
  };
442
465
  executions.push(execution);
466
+ onEvent?.(toolExecutionEnd(call.toolCallId, tool.name, "Tool execution denied by approval handler", true, endTime, index));
443
467
  return {
444
468
  toolCallId: call.toolCallId,
445
469
  result: "Tool execution denied by approval handler",
@@ -448,6 +472,7 @@ async function executeTools(message, tools, toolStrategy, executions) {
448
472
  }
449
473
  try {
450
474
  const result = await tool.run(call.arguments);
475
+ const endTime = Date.now();
451
476
  await toolStrategy?.onAfterCall?.(tool, call.arguments, result);
452
477
  const execution = {
453
478
  toolName: tool.name,
@@ -455,16 +480,18 @@ async function executeTools(message, tools, toolStrategy, executions) {
455
480
  arguments: call.arguments,
456
481
  result,
457
482
  isError: false,
458
- duration: Date.now() - startTime,
483
+ duration: endTime - startTime,
459
484
  approved
460
485
  };
461
486
  executions.push(execution);
487
+ onEvent?.(toolExecutionEnd(call.toolCallId, tool.name, result, false, endTime, index));
462
488
  return {
463
489
  toolCallId: call.toolCallId,
464
490
  result,
465
491
  isError: false
466
492
  };
467
493
  } catch (error) {
494
+ const endTime = Date.now();
468
495
  await toolStrategy?.onError?.(tool, call.arguments, error);
469
496
  const errorMessage = error instanceof Error ? error.message : String(error);
470
497
  const execution = {
@@ -473,10 +500,11 @@ async function executeTools(message, tools, toolStrategy, executions) {
473
500
  arguments: call.arguments,
474
501
  result: errorMessage,
475
502
  isError: true,
476
- duration: Date.now() - startTime,
503
+ duration: endTime - startTime,
477
504
  approved
478
505
  };
479
506
  executions.push(execution);
507
+ onEvent?.(toolExecutionEnd(call.toolCallId, tool.name, errorMessage, true, endTime, index));
480
508
  return {
481
509
  toolCallId: call.toolCallId,
482
510
  result: errorMessage,
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)) {\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":"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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 | 'tool_execution_start'\n | 'tool_execution_end'\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 /** Tool execution result (for tool_execution_end) */\n result?: unknown;\n /** Whether tool execution errored (for tool_execution_end) */\n isError?: boolean;\n /** Timestamp in ms (for tool_execution_start/end) */\n timestamp?: number;\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\n/**\n * Create a tool execution start event\n */\nexport function toolExecutionStart(\n toolCallId: string,\n toolName: string,\n timestamp: number,\n index = 0\n): StreamEvent {\n return {\n type: 'tool_execution_start',\n index,\n delta: { toolCallId, toolName, timestamp },\n };\n}\n\n/**\n * Create a tool execution end event\n */\nexport function toolExecutionEnd(\n toolCallId: string,\n toolName: string,\n result: unknown,\n isError: boolean,\n timestamp: number,\n index = 0\n): StreamEvent {\n return {\n type: 'tool_execution_end',\n index,\n delta: { toolCallId, toolName, result, isError, timestamp },\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 {\n createStreamResult,\n toolExecutionStart,\n toolExecutionEnd,\n} 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 with event emission\n const toolEvents: StreamEvent[] = [];\n const results = await executeTools(\n response.message,\n tools,\n toolStrategy,\n toolExecutions,\n (event) => toolEvents.push(event)\n );\n\n // Yield tool execution events\n for (const event of toolEvents) {\n yield event;\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 onEvent?: (event: StreamEvent) => void\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, index) => {\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 // Emit start event\n onEvent?.(toolExecutionStart(call.toolCallId, tool.name, startTime, index));\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 const endTime = Date.now();\n onEvent?.(toolExecutionEnd(call.toolCallId, tool.name, 'Tool execution skipped', true, endTime, index));\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 endTime = Date.now();\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: endTime - startTime,\n approved: false,\n };\n executions.push(execution);\n\n onEvent?.(toolExecutionEnd(call.toolCallId, tool.name, 'Tool execution denied by approval handler', true, endTime, index));\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 const endTime = Date.now();\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: endTime - startTime,\n approved,\n };\n executions.push(execution);\n\n onEvent?.(toolExecutionEnd(call.toolCallId, tool.name, result, false, endTime, index));\n\n return {\n toolCallId: call.toolCallId,\n result,\n isError: false,\n };\n } catch (error) {\n const endTime = Date.now();\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: endTime - startTime,\n approved,\n };\n executions.push(execution);\n\n onEvent?.(toolExecutionEnd(call.toolCallId, tool.name, errorMessage, true, endTime, index));\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"]}
@@ -10,8 +10,8 @@ interface OpenAIAudioConfig {
10
10
  voice: 'alloy' | 'ash' | 'ballad' | 'coral' | 'echo' | 'sage' | 'shimmer' | 'verse' | 'marin' | 'cedar';
11
11
  }
12
12
  /**
13
- * User location for web search context
14
- * Requires type: 'approximate' with location fields at the same level
13
+ * User location for web search context (Responses API format)
14
+ * Fields are at the same level as type
15
15
  */
16
16
  interface OpenAIWebSearchUserLocation {
17
17
  /** Location type - must be 'approximate' */
@@ -25,8 +25,28 @@ interface OpenAIWebSearchUserLocation {
25
25
  /** IANA timezone (e.g., "America/New_York") */
26
26
  timezone?: string;
27
27
  }
28
+ /**
29
+ * User location for web search context (Chat Completions API format)
30
+ * Fields are nested under 'approximate' object
31
+ */
32
+ interface OpenAICompletionsWebSearchUserLocation {
33
+ /** Location type - must be 'approximate' */
34
+ type: 'approximate';
35
+ /** Approximate location details */
36
+ approximate: {
37
+ /** City name */
38
+ city?: string;
39
+ /** ISO 3166-1 country code (e.g., "US") */
40
+ country?: string;
41
+ /** Region/state name */
42
+ region?: string;
43
+ /** IANA timezone (e.g., "America/New_York") */
44
+ timezone?: string;
45
+ };
46
+ }
28
47
  /**
29
48
  * Web search options for Chat Completions API
49
+ * Use with gpt-5-search-api-* models
30
50
  */
31
51
  interface OpenAIWebSearchOptions {
32
52
  /**
@@ -35,7 +55,7 @@ interface OpenAIWebSearchOptions {
35
55
  */
36
56
  search_context_size?: 'low' | 'medium' | 'high';
37
57
  /** User location for localizing search results */
38
- user_location?: OpenAIWebSearchUserLocation | null;
58
+ user_location?: OpenAICompletionsWebSearchUserLocation | null;
39
59
  }
40
60
  /**
41
61
  * OpenAI Chat Completions API parameters
@@ -591,4 +611,4 @@ interface OpenAIProvider extends Provider<OpenAIProviderOptions> {
591
611
  */
592
612
  declare const openai: OpenAIProvider;
593
613
 
594
- export { type OpenAIAPIMode, type OpenAIAudioConfig, type OpenAIBuiltInTool, type OpenAICodeInterpreterContainer, type OpenAICodeInterpreterTool, type OpenAICompletionsParams, type OpenAIComputerEnvironment, type OpenAIComputerTool, type OpenAIConfig, type OpenAIConversation, type OpenAIFileSearchTool, type OpenAIImageGenerationTool, type OpenAIMcpServerConfig, type OpenAIMcpTool, type OpenAIModelOptions, type OpenAIModelReference, type OpenAIPromptTemplate, type OpenAIResponsesParams, type OpenAIResponsesToolUnion, type OpenAIWebSearchOptions, type OpenAIWebSearchTool, type OpenAIWebSearchUserLocation, codeInterpreterTool, computerTool, fileSearchTool, imageGenerationTool, mcpTool, openai, tools, webSearchTool };
614
+ export { type OpenAIAPIMode, type OpenAIAudioConfig, type OpenAIBuiltInTool, type OpenAICodeInterpreterContainer, type OpenAICodeInterpreterTool, type OpenAICompletionsParams, type OpenAICompletionsWebSearchUserLocation, type OpenAIComputerEnvironment, type OpenAIComputerTool, type OpenAIConfig, type OpenAIConversation, type OpenAIFileSearchTool, type OpenAIImageGenerationTool, type OpenAIMcpServerConfig, type OpenAIMcpTool, type OpenAIModelOptions, type OpenAIModelReference, type OpenAIPromptTemplate, type OpenAIResponsesParams, type OpenAIResponsesToolUnion, type OpenAIWebSearchOptions, type OpenAIWebSearchTool, type OpenAIWebSearchUserLocation, codeInterpreterTool, computerTool, fileSearchTool, imageGenerationTool, mcpTool, openai, tools, webSearchTool };