@providerprotocol/ai 0.0.17 → 0.0.19

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.
Files changed (45) hide show
  1. package/README.md +294 -114
  2. package/dist/anthropic/index.d.ts +1 -1
  3. package/dist/anthropic/index.js +5 -3
  4. package/dist/anthropic/index.js.map +1 -1
  5. package/dist/{chunk-MOU4U3PO.js → chunk-5FEAOEXV.js} +4 -68
  6. package/dist/chunk-5FEAOEXV.js.map +1 -0
  7. package/dist/chunk-DZQHVGNV.js +71 -0
  8. package/dist/chunk-DZQHVGNV.js.map +1 -0
  9. package/dist/chunk-SKY2JLA7.js +59 -0
  10. package/dist/chunk-SKY2JLA7.js.map +1 -0
  11. package/dist/{chunk-SVYROCLD.js → chunk-UMKWXGO3.js} +1 -1
  12. package/dist/chunk-UMKWXGO3.js.map +1 -0
  13. package/dist/chunk-WAKD3OO5.js +224 -0
  14. package/dist/chunk-WAKD3OO5.js.map +1 -0
  15. package/dist/content-DEl3z_W2.d.ts +276 -0
  16. package/dist/google/index.d.ts +3 -1
  17. package/dist/google/index.js +122 -4
  18. package/dist/google/index.js.map +1 -1
  19. package/dist/http/index.d.ts +2 -2
  20. package/dist/http/index.js +2 -1
  21. package/dist/image-Dhq-Yuq4.d.ts +456 -0
  22. package/dist/index.d.ts +59 -1460
  23. package/dist/index.js +89 -267
  24. package/dist/index.js.map +1 -1
  25. package/dist/ollama/index.d.ts +1 -1
  26. package/dist/ollama/index.js +5 -3
  27. package/dist/ollama/index.js.map +1 -1
  28. package/dist/openai/index.d.ts +47 -20
  29. package/dist/openai/index.js +309 -4
  30. package/dist/openai/index.js.map +1 -1
  31. package/dist/openrouter/index.d.ts +1 -1
  32. package/dist/openrouter/index.js +5 -3
  33. package/dist/openrouter/index.js.map +1 -1
  34. package/dist/{provider-D5MO3-pS.d.ts → provider-BBMBZuGn.d.ts} +11 -11
  35. package/dist/proxy/index.d.ts +652 -0
  36. package/dist/proxy/index.js +565 -0
  37. package/dist/proxy/index.js.map +1 -0
  38. package/dist/{retry-DZ4Sqmxp.d.ts → retry-DR7YRJDz.d.ts} +1 -1
  39. package/dist/stream-DRHy6q1a.d.ts +1013 -0
  40. package/dist/xai/index.d.ts +29 -1
  41. package/dist/xai/index.js +118 -4
  42. package/dist/xai/index.js.map +1 -1
  43. package/package.json +6 -1
  44. package/dist/chunk-MOU4U3PO.js.map +0 -1
  45. package/dist/chunk-SVYROCLD.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/types/errors.ts"],"sourcesContent":["/**\n * @fileoverview Error types for the Unified Provider Protocol.\n *\n * Provides normalized error codes and a unified error class for handling\n * errors across different AI providers in a consistent manner.\n *\n * @module types/errors\n */\n\n/**\n * Normalized error codes for cross-provider error handling.\n *\n * These codes provide a consistent way to identify and handle errors\n * regardless of which AI provider generated them.\n *\n * @example\n * ```typescript\n * try {\n * await llm.generate('Hello');\n * } catch (error) {\n * if (error instanceof UPPError) {\n * switch (error.code) {\n * case 'RATE_LIMITED':\n * await delay(error.retryAfter);\n * break;\n * case 'AUTHENTICATION_FAILED':\n * throw new Error('Invalid API key');\n * }\n * }\n * }\n * ```\n */\nexport type ErrorCode =\n /** API key is invalid or expired */\n | 'AUTHENTICATION_FAILED'\n /** Rate limit exceeded, retry after delay */\n | 'RATE_LIMITED'\n /** Input exceeds model's context window */\n | 'CONTEXT_LENGTH_EXCEEDED'\n /** Requested model does not exist */\n | 'MODEL_NOT_FOUND'\n /** Request parameters are malformed */\n | 'INVALID_REQUEST'\n /** Provider returned an unexpected response format */\n | 'INVALID_RESPONSE'\n /** Content was blocked by safety filters */\n | 'CONTENT_FILTERED'\n /** Account quota or credits exhausted */\n | 'QUOTA_EXCEEDED'\n /** Provider-specific error not covered by other codes */\n | 'PROVIDER_ERROR'\n /** Network connectivity issue */\n | 'NETWORK_ERROR'\n /** Request exceeded timeout limit */\n | 'TIMEOUT'\n /** Request was cancelled via AbortSignal */\n | 'CANCELLED';\n\n/**\n * Modality types supported by UPP.\n *\n * Each modality represents a different type of AI capability that\n * can be provided by a UPP-compatible provider.\n */\nexport type Modality =\n /** Large language model for text generation */\n | 'llm'\n /** Text/image embedding model */\n | 'embedding'\n /** Image generation model */\n | 'image'\n /** Audio processing/generation model */\n | 'audio'\n /** Video processing/generation model */\n | 'video';\n\n/**\n * Unified Provider Protocol Error.\n *\n * All provider-specific errors are normalized to this type, providing\n * a consistent interface for error handling across different AI providers.\n *\n * @example\n * ```typescript\n * throw new UPPError(\n * 'API key is invalid',\n * 'AUTHENTICATION_FAILED',\n * 'openai',\n * 'llm',\n * 401\n * );\n * ```\n *\n * @example\n * ```typescript\n * // Wrapping a provider error\n * try {\n * await openai.chat.completions.create({ ... });\n * } catch (err) {\n * throw new UPPError(\n * 'OpenAI request failed',\n * 'PROVIDER_ERROR',\n * 'openai',\n * 'llm',\n * err.status,\n * err\n * );\n * }\n * ```\n */\nexport class UPPError extends Error {\n /** Normalized error code for programmatic handling */\n readonly code: ErrorCode;\n\n /** Name of the provider that generated the error */\n readonly provider: string;\n\n /** The modality that was being used when the error occurred */\n readonly modality: Modality;\n\n /** HTTP status code from the provider's response, if available */\n readonly statusCode?: number;\n\n /** The original error that caused this UPPError, if wrapping another error */\n override readonly cause?: Error;\n\n /** Error class name, always 'UPPError' */\n override readonly name = 'UPPError';\n\n /**\n * Creates a new UPPError instance.\n *\n * @param message - Human-readable error description\n * @param code - Normalized error code for programmatic handling\n * @param provider - Name of the provider that generated the error\n * @param modality - The modality that was being used\n * @param statusCode - HTTP status code from the provider's response\n * @param cause - The original error being wrapped\n */\n constructor(\n message: string,\n code: ErrorCode,\n provider: string,\n modality: Modality,\n statusCode?: number,\n cause?: Error\n ) {\n super(message);\n this.code = code;\n this.provider = provider;\n this.modality = modality;\n this.statusCode = statusCode;\n this.cause = cause;\n\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, UPPError);\n }\n }\n\n /**\n * Creates a string representation of the error.\n *\n * @returns Formatted error string including code, message, provider, and modality\n */\n override toString(): string {\n let str = `UPPError [${this.code}]: ${this.message}`;\n str += ` (provider: ${this.provider}, modality: ${this.modality}`;\n if (this.statusCode) {\n str += `, status: ${this.statusCode}`;\n }\n str += ')';\n return str;\n }\n\n /**\n * Converts the error to a JSON-serializable object.\n *\n * @returns Plain object representation suitable for logging or transmission\n */\n toJSON(): Record<string, unknown> {\n return {\n name: this.name,\n message: this.message,\n code: this.code,\n provider: this.provider,\n modality: this.modality,\n statusCode: this.statusCode,\n cause: this.cause?.message,\n };\n }\n}\n"],"mappings":";AA8GO,IAAM,WAAN,MAAM,kBAAiB,MAAM;AAAA;AAAA,EAEzB;AAAA;AAAA,EAGA;AAAA;AAAA,EAGA;AAAA;AAAA,EAGA;AAAA;AAAA,EAGS;AAAA;AAAA,EAGA,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYzB,YACE,SACA,MACA,UACA,UACA,YACA,OACA;AACA,UAAM,OAAO;AACb,SAAK,OAAO;AACZ,SAAK,WAAW;AAChB,SAAK,WAAW;AAChB,SAAK,aAAa;AAClB,SAAK,QAAQ;AAEb,QAAI,MAAM,mBAAmB;AAC3B,YAAM,kBAAkB,MAAM,SAAQ;AAAA,IACxC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOS,WAAmB;AAC1B,QAAI,MAAM,aAAa,KAAK,IAAI,MAAM,KAAK,OAAO;AAClD,WAAO,eAAe,KAAK,QAAQ,eAAe,KAAK,QAAQ;AAC/D,QAAI,KAAK,YAAY;AACnB,aAAO,aAAa,KAAK,UAAU;AAAA,IACrC;AACA,WAAO;AACP,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,SAAkC;AAChC,WAAO;AAAA,MACL,MAAM,KAAK;AAAA,MACX,SAAS,KAAK;AAAA,MACd,MAAM,KAAK;AAAA,MACX,UAAU,KAAK;AAAA,MACf,UAAU,KAAK;AAAA,MACf,YAAY,KAAK;AAAA,MACjB,OAAO,KAAK,OAAO;AAAA,IACrB;AAAA,EACF;AACF;","names":[]}
@@ -0,0 +1,59 @@
1
+ // src/types/turn.ts
2
+ function createTurn(messages, toolExecutions, usage, cycles, data) {
3
+ const response = messages.filter((m) => m.type === "assistant").pop();
4
+ if (!response) {
5
+ throw new Error("Turn must contain at least one assistant message");
6
+ }
7
+ return {
8
+ messages,
9
+ response,
10
+ toolExecutions,
11
+ usage,
12
+ cycles,
13
+ data
14
+ };
15
+ }
16
+ function emptyUsage() {
17
+ return {
18
+ inputTokens: 0,
19
+ outputTokens: 0,
20
+ totalTokens: 0,
21
+ cacheReadTokens: 0,
22
+ cacheWriteTokens: 0,
23
+ cycles: []
24
+ };
25
+ }
26
+ function aggregateUsage(usages) {
27
+ const cycles = [];
28
+ let inputTokens = 0;
29
+ let outputTokens = 0;
30
+ let cacheReadTokens = 0;
31
+ let cacheWriteTokens = 0;
32
+ for (const usage of usages) {
33
+ inputTokens += usage.inputTokens;
34
+ outputTokens += usage.outputTokens;
35
+ cacheReadTokens += usage.cacheReadTokens;
36
+ cacheWriteTokens += usage.cacheWriteTokens;
37
+ cycles.push({
38
+ inputTokens: usage.inputTokens,
39
+ outputTokens: usage.outputTokens,
40
+ cacheReadTokens: usage.cacheReadTokens,
41
+ cacheWriteTokens: usage.cacheWriteTokens
42
+ });
43
+ }
44
+ return {
45
+ inputTokens,
46
+ outputTokens,
47
+ totalTokens: inputTokens + outputTokens,
48
+ cacheReadTokens,
49
+ cacheWriteTokens,
50
+ cycles
51
+ };
52
+ }
53
+
54
+ export {
55
+ createTurn,
56
+ emptyUsage,
57
+ aggregateUsage
58
+ };
59
+ //# sourceMappingURL=chunk-SKY2JLA7.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/types/turn.ts"],"sourcesContent":["/**\n * @fileoverview Turn types for inference results.\n *\n * A Turn represents the complete result of one inference call, including\n * all messages produced during tool execution loops, token usage, and\n * optional structured output data.\n *\n * @module types/turn\n */\n\nimport type { Message, AssistantMessage } from './messages.ts';\nimport type { ToolExecution } from './tool.ts';\nimport type { MessageJSON } from './thread.ts';\n\n/**\n * Token usage information for an inference request.\n *\n * Tracks input and output tokens across all inference cycles,\n * with optional per-cycle breakdown and cache metrics.\n *\n * @example\n * ```typescript\n * const usage: TokenUsage = {\n * inputTokens: 150,\n * outputTokens: 50,\n * totalTokens: 200,\n * cacheReadTokens: 100,\n * cacheWriteTokens: 50,\n * cycles: [\n * { inputTokens: 100, outputTokens: 30, cacheReadTokens: 0, cacheWriteTokens: 50 },\n * { inputTokens: 50, outputTokens: 20, cacheReadTokens: 100, cacheWriteTokens: 0 }\n * ]\n * };\n * ```\n */\nexport interface TokenUsage {\n /** Total input tokens across all cycles */\n inputTokens: number;\n\n /** Total output tokens across all cycles */\n outputTokens: number;\n\n /** Sum of input and output tokens */\n totalTokens: number;\n\n /**\n * Tokens read from cache (cache hits).\n * Returns 0 for providers that don't support or report cache metrics.\n */\n cacheReadTokens: number;\n\n /**\n * Tokens written to cache (cache misses that were cached).\n * Only Anthropic reports this metric; returns 0 for other providers.\n */\n cacheWriteTokens: number;\n\n /** Per-cycle token breakdown (if multiple cycles occurred) */\n cycles?: Array<{\n inputTokens: number;\n outputTokens: number;\n cacheReadTokens: number;\n cacheWriteTokens: number;\n }>;\n}\n\n/**\n * A Turn represents the complete result of one inference call.\n *\n * Includes all messages produced during tool execution loops,\n * the final assistant response, token usage, and optional\n * structured output data.\n *\n * @typeParam TData - Type of the structured output data\n *\n * @example\n * ```typescript\n * const turn = await instance.generate('Hello');\n * console.log(turn.response.text);\n * console.log(`Used ${turn.usage.totalTokens} tokens in ${turn.cycles} cycles`);\n *\n * // With structured output\n * interface WeatherData { temperature: number; conditions: string; }\n * const turn = await instance.generate<WeatherData>('Get weather');\n * console.log(turn.data?.temperature);\n * ```\n */\nexport interface Turn<TData = unknown> {\n /**\n * All messages produced during this inference, in chronological order.\n * Includes UserMessage, AssistantMessage (may include toolCalls), and ToolResultMessage.\n */\n readonly messages: Message[];\n\n /** The final assistant response (last AssistantMessage in the turn) */\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 a structure schema was provided).\n * Type is inferred from the schema when using TypeScript.\n */\n readonly data?: TData;\n}\n\n/**\n * Turn serialized to JSON format.\n * Messages are converted to MessageJSON, response is omitted (computed from messages).\n */\nexport type TurnJSON = Omit<Turn, 'messages' | 'response'> & {\n messages: MessageJSON[];\n};\n\n/**\n * Creates a Turn from accumulated inference data.\n *\n * @typeParam TData - Type of the structured output data\n * @param messages - All messages produced during the inference\n * @param toolExecutions - Record of all tool executions\n * @param usage - Aggregate token usage\n * @param cycles - Number of inference cycles\n * @param data - Optional structured output data\n * @returns A complete Turn object\n * @throws Error if no assistant message is found in the messages\n *\n * @example\n * ```typescript\n * const turn = createTurn(\n * [userMsg, assistantMsg],\n * [],\n * { inputTokens: 100, outputTokens: 50, totalTokens: 150 },\n * 1\n * );\n * ```\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 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 * Creates an empty TokenUsage object.\n *\n * @returns A TokenUsage with all values set to zero\n *\n * @example\n * ```typescript\n * const usage = emptyUsage();\n * // { inputTokens: 0, outputTokens: 0, totalTokens: 0, cacheReadTokens: 0, cacheWriteTokens: 0, cycles: [] }\n * ```\n */\nexport function emptyUsage(): TokenUsage {\n return {\n inputTokens: 0,\n outputTokens: 0,\n totalTokens: 0,\n cacheReadTokens: 0,\n cacheWriteTokens: 0,\n cycles: [],\n };\n}\n\n/**\n * Aggregates token usage from multiple inference cycles.\n *\n * @param usages - Array of TokenUsage objects to aggregate\n * @returns Combined TokenUsage with per-cycle breakdown\n *\n * @example\n * ```typescript\n * const cycle1 = { inputTokens: 100, outputTokens: 30, totalTokens: 130, cacheReadTokens: 50, cacheWriteTokens: 0 };\n * const cycle2 = { inputTokens: 150, outputTokens: 40, totalTokens: 190, cacheReadTokens: 100, cacheWriteTokens: 0 };\n * const total = aggregateUsage([cycle1, cycle2]);\n * // { inputTokens: 250, outputTokens: 70, totalTokens: 320, cacheReadTokens: 150, cacheWriteTokens: 0, cycles: [...] }\n * ```\n */\nexport function aggregateUsage(usages: TokenUsage[]): TokenUsage {\n const cycles: TokenUsage['cycles'] = [];\n let inputTokens = 0;\n let outputTokens = 0;\n let cacheReadTokens = 0;\n let cacheWriteTokens = 0;\n\n for (const usage of usages) {\n inputTokens += usage.inputTokens;\n outputTokens += usage.outputTokens;\n cacheReadTokens += usage.cacheReadTokens;\n cacheWriteTokens += usage.cacheWriteTokens;\n cycles.push({\n inputTokens: usage.inputTokens,\n outputTokens: usage.outputTokens,\n cacheReadTokens: usage.cacheReadTokens,\n cacheWriteTokens: usage.cacheWriteTokens,\n });\n }\n\n return {\n inputTokens,\n outputTokens,\n totalTokens: inputTokens + outputTokens,\n cacheReadTokens,\n cacheWriteTokens,\n cycles,\n };\n}\n"],"mappings":";AA+IO,SAAS,WACd,UACA,gBACA,OACA,QACA,MACa;AACb,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;AAaO,SAAS,aAAyB;AACvC,SAAO;AAAA,IACL,aAAa;AAAA,IACb,cAAc;AAAA,IACd,aAAa;AAAA,IACb,iBAAiB;AAAA,IACjB,kBAAkB;AAAA,IAClB,QAAQ,CAAC;AAAA,EACX;AACF;AAgBO,SAAS,eAAe,QAAkC;AAC/D,QAAM,SAA+B,CAAC;AACtC,MAAI,cAAc;AAClB,MAAI,eAAe;AACnB,MAAI,kBAAkB;AACtB,MAAI,mBAAmB;AAEvB,aAAW,SAAS,QAAQ;AAC1B,mBAAe,MAAM;AACrB,oBAAgB,MAAM;AACtB,uBAAmB,MAAM;AACzB,wBAAoB,MAAM;AAC1B,WAAO,KAAK;AAAA,MACV,aAAa,MAAM;AAAA,MACnB,cAAc,MAAM;AAAA,MACpB,iBAAiB,MAAM;AAAA,MACvB,kBAAkB,MAAM;AAAA,IAC1B,CAAC;AAAA,EACH;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,aAAa,cAAc;AAAA,IAC3B;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;","names":[]}
@@ -152,4 +152,4 @@ export {
152
152
  isAssistantMessage,
153
153
  isToolResultMessage
154
154
  };
155
- //# sourceMappingURL=chunk-SVYROCLD.js.map
155
+ //# sourceMappingURL=chunk-UMKWXGO3.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/utils/id.ts","../src/types/messages.ts"],"sourcesContent":["/**\n * @fileoverview ID generation utilities for the Universal Provider Protocol.\n *\n * Provides functions for generating unique identifiers used throughout UPP,\n * including message IDs, tool call IDs, and other internal references.\n *\n * @module utils/id\n */\n\n/**\n * Generates a unique UUID v4 identifier.\n *\n * Uses the native `crypto.randomUUID()` when available for cryptographically\n * secure randomness. Falls back to a Math.random-based implementation for\n * environments without Web Crypto API support.\n *\n * @returns A UUID v4 string in the format `xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx`\n *\n * @example\n * ```typescript\n * const messageId = generateId();\n * // => \"f47ac10b-58cc-4372-a567-0e02b2c3d479\"\n * ```\n */\nexport function generateId(): string {\n if (typeof crypto !== 'undefined' && crypto.randomUUID) {\n return crypto.randomUUID();\n }\n\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {\n const r = (Math.random() * 16) | 0;\n const v = c === 'x' ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n}\n\n/**\n * Generates a short alphanumeric identifier.\n *\n * Creates a 12-character random string using alphanumeric characters (a-z, A-Z, 0-9).\n * Useful for tool call IDs and other cases where a full UUID is not required.\n *\n * @param prefix - Optional prefix to prepend to the generated ID\n * @returns A string containing the prefix followed by 12 random alphanumeric characters\n *\n * @example\n * ```typescript\n * const toolCallId = generateShortId('call_');\n * // => \"call_aB3xY9mK2pQr\"\n *\n * const simpleId = generateShortId();\n * // => \"Tz4wN8vL1sHj\"\n * ```\n */\nexport function generateShortId(prefix = ''): string {\n const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';\n let result = prefix;\n for (let i = 0; i < 12; i++) {\n result += chars.charAt(Math.floor(Math.random() * chars.length));\n }\n return result;\n}\n","/**\n * @fileoverview Message types for conversation history.\n *\n * Defines the message classes used to represent conversation turns\n * between users and assistants, including support for multimodal\n * content and tool calls.\n *\n * @module types/messages\n */\n\nimport { generateId } from '../utils/id.ts';\nimport type {\n ContentBlock,\n TextBlock,\n ImageBlock,\n AudioBlock,\n VideoBlock,\n UserContent,\n AssistantContent,\n} from './content.ts';\nimport type { ToolCall, ToolResult } from './tool.ts';\n\n/**\n * Message serialized to JSON format.\n * Picks common fields from Message, converts timestamp to string.\n */\nexport type MessageJSON = Pick<Message, 'id' | 'type' | 'metadata'> & {\n timestamp: string;\n content: ContentBlock[];\n toolCalls?: ToolCall[];\n results?: ToolResult[];\n};\n\n/**\n * Message type discriminator.\n *\n * Used to distinguish between different message types in a conversation.\n */\nexport type MessageType = 'user' | 'assistant' | 'tool_result';\n\n/**\n * Provider-namespaced metadata for messages.\n *\n * Each provider can attach its own metadata under its namespace,\n * preventing conflicts between different providers.\n *\n * @example\n * ```typescript\n * const metadata: MessageMetadata = {\n * openai: { model: 'gpt-4', finishReason: 'stop' },\n * anthropic: { model: 'claude-3', stopReason: 'end_turn' }\n * };\n * ```\n */\nexport interface MessageMetadata {\n [provider: string]: Record<string, unknown> | undefined;\n}\n\n/**\n * Options for constructing messages.\n */\nexport interface MessageOptions {\n /** Custom message ID (auto-generated if not provided) */\n id?: string;\n\n /** Provider-specific metadata */\n metadata?: MessageMetadata;\n}\n\n/**\n * Abstract base class for all message types.\n *\n * Provides common functionality for user, assistant, and tool result\n * messages, including content accessors and metadata handling.\n *\n * @example\n * ```typescript\n * // Access text content from any message\n * const text = message.text;\n *\n * // Access images\n * const images = message.images;\n * ```\n */\nexport abstract class Message {\n /** Unique message identifier */\n readonly id: string;\n\n /** Timestamp when the message was created */\n readonly timestamp: Date;\n\n /** Provider-specific metadata, namespaced by provider name */\n readonly metadata?: MessageMetadata;\n\n /** Message type discriminator (implemented by subclasses) */\n abstract readonly type: MessageType;\n\n /**\n * Returns the content blocks for this message.\n * Implemented by subclasses to provide type-specific content.\n */\n protected abstract getContent(): ContentBlock[];\n\n /**\n * Creates a new message instance.\n *\n * @param options - Optional message ID and metadata\n */\n constructor(options?: MessageOptions) {\n this.id = options?.id ?? generateId();\n this.timestamp = new Date();\n this.metadata = options?.metadata;\n }\n\n /**\n * Concatenated text content from all text blocks.\n * Blocks are joined with double newlines.\n */\n get text(): string {\n return this.getContent()\n .filter((block): block is TextBlock => block.type === 'text')\n .map((block) => block.text)\n .join('\\n\\n');\n }\n\n /**\n * All image content blocks in this message.\n */\n get images(): ImageBlock[] {\n return this.getContent().filter((block): block is ImageBlock => block.type === 'image');\n }\n\n /**\n * All audio content blocks in this message.\n */\n get audio(): AudioBlock[] {\n return this.getContent().filter((block): block is AudioBlock => block.type === 'audio');\n }\n\n /**\n * All video content blocks in this message.\n */\n get video(): VideoBlock[] {\n return this.getContent().filter((block): block is VideoBlock => block.type === 'video');\n }\n}\n\n/**\n * User input message.\n *\n * Represents a message from the user, which can contain text and/or\n * multimodal content like images, audio, or video.\n *\n * @example\n * ```typescript\n * // Simple text message\n * const msg = new UserMessage('Hello, world!');\n *\n * // Multimodal message\n * const msg = new UserMessage([\n * { type: 'text', text: 'What is in this image?' },\n * { type: 'image', source: { type: 'url', url: '...' }, mimeType: 'image/png' }\n * ]);\n * ```\n */\nexport class UserMessage extends Message {\n /** Message type discriminator */\n readonly type = 'user' as const;\n\n /** Content blocks in this message */\n readonly content: UserContent[];\n\n /**\n * Creates a new user message.\n *\n * @param content - String (converted to TextBlock) or array of content blocks\n * @param options - Optional message ID and metadata\n */\n constructor(content: string | UserContent[], options?: MessageOptions) {\n super(options);\n if (typeof content === 'string') {\n this.content = [{ type: 'text', text: content }];\n } else {\n this.content = content;\n }\n }\n\n protected getContent(): ContentBlock[] {\n return this.content;\n }\n}\n\n/**\n * Assistant response message.\n *\n * Represents a response from the AI assistant, which may contain\n * text, media content, and/or tool call requests.\n *\n * @example\n * ```typescript\n * // Simple text response\n * const msg = new AssistantMessage('Hello! How can I help?');\n *\n * // Response with tool calls\n * const msg = new AssistantMessage(\n * 'Let me check the weather...',\n * [{ toolCallId: 'call_1', toolName: 'get_weather', arguments: { location: 'NYC' } }]\n * );\n * ```\n */\nexport class AssistantMessage extends Message {\n /** Message type discriminator */\n readonly type = 'assistant' as const;\n\n /** Content blocks in this message */\n readonly content: AssistantContent[];\n\n /** Tool calls requested by the model (if any) */\n readonly toolCalls?: ToolCall[];\n\n /**\n * Creates a new assistant message.\n *\n * @param content - String (converted to TextBlock) or array of content blocks\n * @param toolCalls - Tool calls requested by the model\n * @param options - Optional message ID and metadata\n */\n constructor(\n content: string | AssistantContent[],\n toolCalls?: ToolCall[],\n options?: MessageOptions\n ) {\n super(options);\n if (typeof content === 'string') {\n this.content = [{ type: 'text', text: content }];\n } else {\n this.content = content;\n }\n this.toolCalls = toolCalls;\n }\n\n protected getContent(): ContentBlock[] {\n return this.content;\n }\n\n /**\n * Whether this message contains tool call requests.\n */\n get hasToolCalls(): boolean {\n return this.toolCalls !== undefined && this.toolCalls.length > 0;\n }\n}\n\n/**\n * Tool execution result message.\n *\n * Contains the results of executing one or more tool calls,\n * sent back to the model for further processing.\n *\n * @example\n * ```typescript\n * const msg = new ToolResultMessage([\n * { toolCallId: 'call_1', result: { temperature: 72, conditions: 'sunny' } },\n * { toolCallId: 'call_2', result: 'File not found', isError: true }\n * ]);\n * ```\n */\nexport class ToolResultMessage extends Message {\n /** Message type discriminator */\n readonly type = 'tool_result' as const;\n\n /** Results from tool executions */\n readonly results: ToolResult[];\n\n /**\n * Creates a new tool result message.\n *\n * @param results - Array of tool execution results\n * @param options - Optional message ID and metadata\n */\n constructor(results: ToolResult[], options?: MessageOptions) {\n super(options);\n this.results = results;\n }\n\n protected getContent(): ContentBlock[] {\n return this.results.map((result) => ({\n type: 'text' as const,\n text:\n typeof result.result === 'string'\n ? result.result\n : JSON.stringify(result.result),\n }));\n }\n}\n\n/**\n * Type guard for UserMessage.\n *\n * @param msg - The message to check\n * @returns True if the message is a UserMessage\n *\n * @example\n * ```typescript\n * if (isUserMessage(msg)) {\n * console.log('User said:', msg.text);\n * }\n * ```\n */\nexport function isUserMessage(msg: Message): msg is UserMessage {\n return msg.type === 'user';\n}\n\n/**\n * Type guard for AssistantMessage.\n *\n * @param msg - The message to check\n * @returns True if the message is an AssistantMessage\n *\n * @example\n * ```typescript\n * if (isAssistantMessage(msg)) {\n * console.log('Assistant said:', msg.text);\n * if (msg.hasToolCalls) {\n * console.log('Tool calls:', msg.toolCalls);\n * }\n * }\n * ```\n */\nexport function isAssistantMessage(msg: Message): msg is AssistantMessage {\n return msg.type === 'assistant';\n}\n\n/**\n * Type guard for ToolResultMessage.\n *\n * @param msg - The message to check\n * @returns True if the message is a ToolResultMessage\n *\n * @example\n * ```typescript\n * if (isToolResultMessage(msg)) {\n * for (const result of msg.results) {\n * console.log(`Tool ${result.toolCallId}:`, result.result);\n * }\n * }\n * ```\n */\nexport function isToolResultMessage(msg: Message): msg is ToolResultMessage {\n return msg.type === 'tool_result';\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,224 @@
1
+ // src/core/media/Image.ts
2
+ var Image = class _Image {
3
+ /** The underlying image source (bytes, base64, or URL) */
4
+ source;
5
+ /** MIME type of the image (e.g., 'image/jpeg', 'image/png') */
6
+ mimeType;
7
+ /** Image width in pixels, if known */
8
+ width;
9
+ /** Image height in pixels, if known */
10
+ height;
11
+ constructor(source, mimeType, width, height) {
12
+ this.source = source;
13
+ this.mimeType = mimeType;
14
+ this.width = width;
15
+ this.height = height;
16
+ }
17
+ /**
18
+ * Whether this image has data loaded in memory.
19
+ *
20
+ * Returns `false` for URL-sourced images that reference external resources.
21
+ * These must be fetched before their data can be accessed.
22
+ */
23
+ get hasData() {
24
+ return this.source.type !== "url";
25
+ }
26
+ /**
27
+ * Converts the image to a base64-encoded string.
28
+ *
29
+ * @returns The image data as a base64 string
30
+ * @throws {Error} When the source is a URL (data must be fetched first)
31
+ */
32
+ toBase64() {
33
+ if (this.source.type === "base64") {
34
+ return this.source.data;
35
+ }
36
+ if (this.source.type === "bytes") {
37
+ return btoa(
38
+ Array.from(this.source.data).map((b) => String.fromCharCode(b)).join("")
39
+ );
40
+ }
41
+ throw new Error("Cannot convert URL image to base64. Fetch the image first.");
42
+ }
43
+ /**
44
+ * Converts the image to a data URL suitable for embedding in HTML or CSS.
45
+ *
46
+ * @returns A data URL in the format `data:{mimeType};base64,{data}`
47
+ * @throws {Error} When the source is a URL (data must be fetched first)
48
+ */
49
+ toDataUrl() {
50
+ const base64 = this.toBase64();
51
+ return `data:${this.mimeType};base64,${base64}`;
52
+ }
53
+ /**
54
+ * Gets the image data as raw bytes.
55
+ *
56
+ * @returns The image data as a Uint8Array
57
+ * @throws {Error} When the source is a URL (data must be fetched first)
58
+ */
59
+ toBytes() {
60
+ if (this.source.type === "bytes") {
61
+ return this.source.data;
62
+ }
63
+ if (this.source.type === "base64") {
64
+ const binaryString = atob(this.source.data);
65
+ const bytes = new Uint8Array(binaryString.length);
66
+ for (let i = 0; i < binaryString.length; i++) {
67
+ bytes[i] = binaryString.charCodeAt(i);
68
+ }
69
+ return bytes;
70
+ }
71
+ throw new Error("Cannot get bytes from URL image. Fetch the image first.");
72
+ }
73
+ /**
74
+ * Gets the URL for URL-sourced images.
75
+ *
76
+ * @returns The image URL
77
+ * @throws {Error} When the source is not a URL
78
+ */
79
+ toUrl() {
80
+ if (this.source.type === "url") {
81
+ return this.source.url;
82
+ }
83
+ throw new Error("This image does not have a URL source.");
84
+ }
85
+ /**
86
+ * Converts this Image to an ImageBlock for use in UPP messages.
87
+ *
88
+ * @returns An ImageBlock that can be included in message content arrays
89
+ */
90
+ toBlock() {
91
+ return {
92
+ type: "image",
93
+ source: this.source,
94
+ mimeType: this.mimeType,
95
+ width: this.width,
96
+ height: this.height
97
+ };
98
+ }
99
+ /**
100
+ * Creates an Image by reading a file from disk.
101
+ *
102
+ * The file is read into memory as bytes. MIME type is automatically
103
+ * detected from the file extension.
104
+ *
105
+ * @param path - Path to the image file
106
+ * @returns Promise resolving to an Image with the file contents
107
+ *
108
+ * @example
109
+ * ```typescript
110
+ * const image = await Image.fromPath('./photos/vacation.jpg');
111
+ * ```
112
+ */
113
+ static async fromPath(path) {
114
+ const { readFile } = await import("fs/promises");
115
+ const data = await readFile(path);
116
+ const mimeType = detectMimeType(path);
117
+ return new _Image(
118
+ { type: "bytes", data: new Uint8Array(data) },
119
+ mimeType
120
+ );
121
+ }
122
+ /**
123
+ * Creates an Image from a URL reference.
124
+ *
125
+ * The URL is stored as a reference and not fetched. Providers will handle
126
+ * URL-to-data conversion if needed. MIME type is detected from the URL
127
+ * path if not provided.
128
+ *
129
+ * @param url - URL pointing to the image
130
+ * @param mimeType - Optional MIME type override
131
+ * @returns An Image referencing the URL
132
+ *
133
+ * @example
134
+ * ```typescript
135
+ * const image = Image.fromUrl('https://example.com/logo.png');
136
+ * ```
137
+ */
138
+ static fromUrl(url, mimeType) {
139
+ const detected = mimeType || detectMimeTypeFromUrl(url);
140
+ return new _Image({ type: "url", url }, detected);
141
+ }
142
+ /**
143
+ * Creates an Image from raw byte data.
144
+ *
145
+ * @param data - The image data as a Uint8Array
146
+ * @param mimeType - The MIME type of the image
147
+ * @returns An Image containing the byte data
148
+ *
149
+ * @example
150
+ * ```typescript
151
+ * const image = Image.fromBytes(pngData, 'image/png');
152
+ * ```
153
+ */
154
+ static fromBytes(data, mimeType) {
155
+ return new _Image({ type: "bytes", data }, mimeType);
156
+ }
157
+ /**
158
+ * Creates an Image from a base64-encoded string.
159
+ *
160
+ * @param base64 - The base64-encoded image data (without data URL prefix)
161
+ * @param mimeType - The MIME type of the image
162
+ * @returns An Image containing the base64 data
163
+ *
164
+ * @example
165
+ * ```typescript
166
+ * const image = Image.fromBase64(base64String, 'image/jpeg');
167
+ * ```
168
+ */
169
+ static fromBase64(base64, mimeType) {
170
+ return new _Image({ type: "base64", data: base64 }, mimeType);
171
+ }
172
+ /**
173
+ * Creates an Image from an existing ImageBlock.
174
+ *
175
+ * Useful for converting content blocks received from providers back
176
+ * into Image instances for further processing.
177
+ *
178
+ * @param block - An ImageBlock from message content
179
+ * @returns An Image with the block's source and metadata
180
+ */
181
+ static fromBlock(block) {
182
+ return new _Image(
183
+ block.source,
184
+ block.mimeType,
185
+ block.width,
186
+ block.height
187
+ );
188
+ }
189
+ };
190
+ function detectMimeType(path) {
191
+ const ext = path.split(".").pop()?.toLowerCase();
192
+ switch (ext) {
193
+ case "jpg":
194
+ case "jpeg":
195
+ return "image/jpeg";
196
+ case "png":
197
+ return "image/png";
198
+ case "gif":
199
+ return "image/gif";
200
+ case "webp":
201
+ return "image/webp";
202
+ case "svg":
203
+ return "image/svg+xml";
204
+ case "bmp":
205
+ return "image/bmp";
206
+ case "ico":
207
+ return "image/x-icon";
208
+ default:
209
+ return "application/octet-stream";
210
+ }
211
+ }
212
+ function detectMimeTypeFromUrl(url) {
213
+ try {
214
+ const pathname = new URL(url).pathname;
215
+ return detectMimeType(pathname);
216
+ } catch {
217
+ return "application/octet-stream";
218
+ }
219
+ }
220
+
221
+ export {
222
+ Image
223
+ };
224
+ //# sourceMappingURL=chunk-WAKD3OO5.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/core/media/Image.ts"],"sourcesContent":["/**\n * @fileoverview Image content handling for the Universal Provider Protocol.\n *\n * Provides a unified Image class for working with images across different sources\n * (file paths, URLs, raw bytes, base64). Supports conversion between formats and\n * integration with UPP message content blocks.\n *\n * @module core/media/Image\n */\n\nimport type { ImageSource, ImageBlock } from '../../types/content.ts';\n\n/**\n * Represents an image that can be used in UPP messages.\n *\n * Images can be created from various sources (files, URLs, bytes, base64) and\n * converted to different formats as needed by providers. The class provides\n * a unified interface regardless of the underlying source type.\n *\n * @example\n * ```typescript\n * // Load from file\n * const fileImage = await Image.fromPath('./photo.jpg');\n *\n * // Reference by URL\n * const urlImage = Image.fromUrl('https://example.com/image.png');\n *\n * // From raw bytes\n * const bytesImage = Image.fromBytes(uint8Array, 'image/png');\n *\n * // Use in a message\n * const message = new UserMessage([image.toBlock()]);\n * ```\n */\nexport class Image {\n /** The underlying image source (bytes, base64, or URL) */\n readonly source: ImageSource;\n /** MIME type of the image (e.g., 'image/jpeg', 'image/png') */\n readonly mimeType: string;\n /** Image width in pixels, if known */\n readonly width?: number;\n /** Image height in pixels, if known */\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 * Whether this image has data loaded in memory.\n *\n * Returns `false` for URL-sourced images that reference external resources.\n * These must be fetched before their data can be accessed.\n */\n get hasData(): boolean {\n return this.source.type !== 'url';\n }\n\n /**\n * Converts the image to a base64-encoded string.\n *\n * @returns The image data as a base64 string\n * @throws {Error} When the source is a URL (data must be fetched first)\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 * Converts the image to a data URL suitable for embedding in HTML or CSS.\n *\n * @returns A data URL in the format `data:{mimeType};base64,{data}`\n * @throws {Error} When the source is a URL (data must be fetched first)\n */\n toDataUrl(): string {\n const base64 = this.toBase64();\n return `data:${this.mimeType};base64,${base64}`;\n }\n\n /**\n * Gets the image data as raw bytes.\n *\n * @returns The image data as a Uint8Array\n * @throws {Error} When the source is a URL (data must be fetched first)\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 * Gets the URL for URL-sourced images.\n *\n * @returns The image URL\n * @throws {Error} When the source is not a URL\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 * Converts this Image to an ImageBlock for use in UPP messages.\n *\n * @returns An ImageBlock that can be included in message content arrays\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 * Creates an Image by reading a file from disk.\n *\n * The file is read into memory as bytes. MIME type is automatically\n * detected from the file extension.\n *\n * @param path - Path to the image file\n * @returns Promise resolving to an Image with the file contents\n *\n * @example\n * ```typescript\n * const image = await Image.fromPath('./photos/vacation.jpg');\n * ```\n */\n static async fromPath(path: string): Promise<Image> {\n // Dynamic import to avoid bundling fs in browser builds\n const { readFile } = await import('node:fs/promises');\n const data = await readFile(path);\n const mimeType = detectMimeType(path);\n\n return new Image(\n { type: 'bytes', data: new Uint8Array(data) },\n mimeType\n );\n }\n\n /**\n * Creates an Image from a URL reference.\n *\n * The URL is stored as a reference and not fetched. Providers will handle\n * URL-to-data conversion if needed. MIME type is detected from the URL\n * path if not provided.\n *\n * @param url - URL pointing to the image\n * @param mimeType - Optional MIME type override\n * @returns An Image referencing the URL\n *\n * @example\n * ```typescript\n * const image = Image.fromUrl('https://example.com/logo.png');\n * ```\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 * Creates an Image from raw byte data.\n *\n * @param data - The image data as a Uint8Array\n * @param mimeType - The MIME type of the image\n * @returns An Image containing the byte data\n *\n * @example\n * ```typescript\n * const image = Image.fromBytes(pngData, 'image/png');\n * ```\n */\n static fromBytes(data: Uint8Array, mimeType: string): Image {\n return new Image({ type: 'bytes', data }, mimeType);\n }\n\n /**\n * Creates an Image from a base64-encoded string.\n *\n * @param base64 - The base64-encoded image data (without data URL prefix)\n * @param mimeType - The MIME type of the image\n * @returns An Image containing the base64 data\n *\n * @example\n * ```typescript\n * const image = Image.fromBase64(base64String, 'image/jpeg');\n * ```\n */\n static fromBase64(base64: string, mimeType: string): Image {\n return new Image({ type: 'base64', data: base64 }, mimeType);\n }\n\n /**\n * Creates an Image from an existing ImageBlock.\n *\n * Useful for converting content blocks received from providers back\n * into Image instances for further processing.\n *\n * @param block - An ImageBlock from message content\n * @returns An Image with the block's source and metadata\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 * Detects the MIME type of an image based on its file extension.\n *\n * Supports common web image formats: JPEG, PNG, GIF, WebP, SVG, BMP, ICO.\n * Returns 'application/octet-stream' for unknown extensions.\n *\n * @param path - File path or filename with extension\n * @returns The detected MIME type string\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 * Detects the MIME type of an image from its URL.\n *\n * Extracts the pathname from the URL and delegates to `detectMimeType`.\n * Returns 'application/octet-stream' if the URL cannot be parsed.\n *\n * @param url - Full URL pointing to an image\n * @returns The detected MIME type string\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"],"mappings":"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","names":[]}
@@ -0,0 +1,276 @@
1
+ /**
2
+ * @fileoverview Content block types for multimodal messages.
3
+ *
4
+ * Defines the various content block types that can be included in
5
+ * user and assistant messages, supporting text, images, audio, video,
6
+ * and arbitrary binary data.
7
+ *
8
+ * @module types/content
9
+ */
10
+ /**
11
+ * Image source variants for ImageBlock.
12
+ *
13
+ * Images can be provided as base64-encoded strings, URLs, or raw bytes.
14
+ *
15
+ * @example
16
+ * ```typescript
17
+ * // Base64 encoded image
18
+ * const base64Source: ImageSource = {
19
+ * type: 'base64',
20
+ * data: 'iVBORw0KGgo...'
21
+ * };
22
+ *
23
+ * // URL reference
24
+ * const urlSource: ImageSource = {
25
+ * type: 'url',
26
+ * url: 'https://example.com/image.png'
27
+ * };
28
+ *
29
+ * // Raw bytes
30
+ * const bytesSource: ImageSource = {
31
+ * type: 'bytes',
32
+ * data: new Uint8Array([...])
33
+ * };
34
+ * ```
35
+ */
36
+ type ImageSource = {
37
+ type: 'base64';
38
+ data: string;
39
+ } | {
40
+ type: 'url';
41
+ url: string;
42
+ } | {
43
+ type: 'bytes';
44
+ data: Uint8Array;
45
+ };
46
+ /**
47
+ * Text content block.
48
+ *
49
+ * The most common content block type, containing plain text content.
50
+ *
51
+ * @example
52
+ * ```typescript
53
+ * const textBlock: TextBlock = {
54
+ * type: 'text',
55
+ * text: 'Hello, world!'
56
+ * };
57
+ * ```
58
+ */
59
+ interface TextBlock {
60
+ /** Discriminator for text blocks */
61
+ type: 'text';
62
+ /** The text content */
63
+ text: string;
64
+ }
65
+ /**
66
+ * Image content block.
67
+ *
68
+ * Contains an image with its source data and metadata.
69
+ *
70
+ * @example
71
+ * ```typescript
72
+ * const imageBlock: ImageBlock = {
73
+ * type: 'image',
74
+ * source: { type: 'url', url: 'https://example.com/photo.jpg' },
75
+ * mimeType: 'image/jpeg',
76
+ * width: 1920,
77
+ * height: 1080
78
+ * };
79
+ * ```
80
+ */
81
+ interface ImageBlock {
82
+ /** Discriminator for image blocks */
83
+ type: 'image';
84
+ /** The image data source */
85
+ source: ImageSource;
86
+ /** MIME type of the image (e.g., 'image/png', 'image/jpeg') */
87
+ mimeType: string;
88
+ /** Image width in pixels */
89
+ width?: number;
90
+ /** Image height in pixels */
91
+ height?: number;
92
+ }
93
+ /**
94
+ * Audio content block.
95
+ *
96
+ * Contains audio data with its metadata.
97
+ *
98
+ * @example
99
+ * ```typescript
100
+ * const audioBlock: AudioBlock = {
101
+ * type: 'audio',
102
+ * data: audioBytes,
103
+ * mimeType: 'audio/mp3',
104
+ * duration: 120.5
105
+ * };
106
+ * ```
107
+ */
108
+ interface AudioBlock {
109
+ /** Discriminator for audio blocks */
110
+ type: 'audio';
111
+ /** Raw audio data */
112
+ data: Uint8Array;
113
+ /** MIME type of the audio (e.g., 'audio/mp3', 'audio/wav') */
114
+ mimeType: string;
115
+ /** Duration in seconds */
116
+ duration?: number;
117
+ }
118
+ /**
119
+ * Video content block.
120
+ *
121
+ * Contains video data with its metadata.
122
+ *
123
+ * @example
124
+ * ```typescript
125
+ * const videoBlock: VideoBlock = {
126
+ * type: 'video',
127
+ * data: videoBytes,
128
+ * mimeType: 'video/mp4',
129
+ * duration: 30,
130
+ * width: 1920,
131
+ * height: 1080
132
+ * };
133
+ * ```
134
+ */
135
+ interface VideoBlock {
136
+ /** Discriminator for video blocks */
137
+ type: 'video';
138
+ /** Raw video data */
139
+ data: Uint8Array;
140
+ /** MIME type of the video (e.g., 'video/mp4', 'video/webm') */
141
+ mimeType: string;
142
+ /** Duration in seconds */
143
+ duration?: number;
144
+ /** Video width in pixels */
145
+ width?: number;
146
+ /** Video height in pixels */
147
+ height?: number;
148
+ }
149
+ /**
150
+ * Binary content block for arbitrary data.
151
+ *
152
+ * A generic block type for data that doesn't fit other categories.
153
+ *
154
+ * @example
155
+ * ```typescript
156
+ * const binaryBlock: BinaryBlock = {
157
+ * type: 'binary',
158
+ * data: pdfBytes,
159
+ * mimeType: 'application/pdf',
160
+ * metadata: { filename: 'document.pdf', pages: 10 }
161
+ * };
162
+ * ```
163
+ */
164
+ interface BinaryBlock {
165
+ /** Discriminator for binary blocks */
166
+ type: 'binary';
167
+ /** Raw binary data */
168
+ data: Uint8Array;
169
+ /** MIME type of the data */
170
+ mimeType: string;
171
+ /** Additional metadata about the binary content */
172
+ metadata?: Record<string, unknown>;
173
+ }
174
+ /**
175
+ * Union of all content block types.
176
+ *
177
+ * Used when a function or property can accept any type of content block.
178
+ */
179
+ type ContentBlock = TextBlock | ImageBlock | AudioBlock | VideoBlock | BinaryBlock;
180
+ /**
181
+ * Content types allowed in user messages.
182
+ *
183
+ * Users can send any type of content block including binary data.
184
+ */
185
+ type UserContent = TextBlock | ImageBlock | AudioBlock | VideoBlock | BinaryBlock;
186
+ /**
187
+ * Content types allowed in assistant messages.
188
+ *
189
+ * Assistants can generate text and media but not arbitrary binary data.
190
+ */
191
+ type AssistantContent = TextBlock | ImageBlock | AudioBlock | VideoBlock;
192
+ /**
193
+ * Creates a text content block from a string.
194
+ *
195
+ * @param content - The text content
196
+ * @returns A TextBlock containing the provided text
197
+ *
198
+ * @example
199
+ * ```typescript
200
+ * const block = text('Hello, world!');
201
+ * // { type: 'text', text: 'Hello, world!' }
202
+ * ```
203
+ */
204
+ declare function text(content: string): TextBlock;
205
+ /**
206
+ * Type guard for TextBlock.
207
+ *
208
+ * @param block - The content block to check
209
+ * @returns True if the block is a TextBlock
210
+ *
211
+ * @example
212
+ * ```typescript
213
+ * if (isTextBlock(block)) {
214
+ * console.log(block.text);
215
+ * }
216
+ * ```
217
+ */
218
+ declare function isTextBlock(block: ContentBlock): block is TextBlock;
219
+ /**
220
+ * Type guard for ImageBlock.
221
+ *
222
+ * @param block - The content block to check
223
+ * @returns True if the block is an ImageBlock
224
+ *
225
+ * @example
226
+ * ```typescript
227
+ * if (isImageBlock(block)) {
228
+ * console.log(block.mimeType, block.width, block.height);
229
+ * }
230
+ * ```
231
+ */
232
+ declare function isImageBlock(block: ContentBlock): block is ImageBlock;
233
+ /**
234
+ * Type guard for AudioBlock.
235
+ *
236
+ * @param block - The content block to check
237
+ * @returns True if the block is an AudioBlock
238
+ *
239
+ * @example
240
+ * ```typescript
241
+ * if (isAudioBlock(block)) {
242
+ * console.log(block.mimeType, block.duration);
243
+ * }
244
+ * ```
245
+ */
246
+ declare function isAudioBlock(block: ContentBlock): block is AudioBlock;
247
+ /**
248
+ * Type guard for VideoBlock.
249
+ *
250
+ * @param block - The content block to check
251
+ * @returns True if the block is a VideoBlock
252
+ *
253
+ * @example
254
+ * ```typescript
255
+ * if (isVideoBlock(block)) {
256
+ * console.log(block.mimeType, block.duration);
257
+ * }
258
+ * ```
259
+ */
260
+ declare function isVideoBlock(block: ContentBlock): block is VideoBlock;
261
+ /**
262
+ * Type guard for BinaryBlock.
263
+ *
264
+ * @param block - The content block to check
265
+ * @returns True if the block is a BinaryBlock
266
+ *
267
+ * @example
268
+ * ```typescript
269
+ * if (isBinaryBlock(block)) {
270
+ * console.log(block.mimeType, block.metadata);
271
+ * }
272
+ * ```
273
+ */
274
+ declare function isBinaryBlock(block: ContentBlock): block is BinaryBlock;
275
+
276
+ export { type AssistantContent as A, type BinaryBlock as B, type ContentBlock as C, type ImageBlock as I, type TextBlock as T, type UserContent as U, type VideoBlock as V, type AudioBlock as a, type ImageSource as b, isImageBlock as c, isAudioBlock as d, isVideoBlock as e, isBinaryBlock as f, isTextBlock as i, text as t };
@@ -1,4 +1,4 @@
1
- import { d as Provider } from '../provider-D5MO3-pS.js';
1
+ import { d as Provider } from '../provider-BBMBZuGn.js';
2
2
 
3
3
  /**
4
4
  * Provider-specific parameters for Google Gemini API requests.
@@ -864,6 +864,8 @@ interface GoogleEmbedParams {
864
864
  title?: string;
865
865
  /** Output dimensionality */
866
866
  outputDimensionality?: number;
867
+ /** Whether to automatically truncate inputs exceeding token limits (default: true) */
868
+ autoTruncate?: boolean;
867
869
  }
868
870
 
869
871
  /**