@providerprotocol/ai 0.0.35 → 0.0.37
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +45 -13
- package/dist/anthropic/index.d.ts +2 -2
- package/dist/anthropic/index.js +12 -10
- package/dist/anthropic/index.js.map +1 -1
- package/dist/cerebras/index.d.ts +2 -2
- package/dist/cerebras/index.js +12 -10
- package/dist/cerebras/index.js.map +1 -1
- package/dist/{chunk-7DXVRILR.js → chunk-2YXFLRQ6.js} +2 -2
- package/dist/chunk-2YXFLRQ6.js.map +1 -0
- package/dist/{chunk-HB4ZIH3T.js → chunk-4RX4VQCB.js} +2 -2
- package/dist/chunk-4RX4VQCB.js.map +1 -0
- package/dist/{chunk-ZI67WIQS.js → chunk-5IWHCXKN.js} +2 -2
- package/dist/chunk-5IWHCXKN.js.map +1 -0
- package/dist/{chunk-UFFJDYCE.js → chunk-7GTWHZY2.js} +2 -2
- package/dist/{chunk-VOEWHQUB.js → chunk-CRP6Y7NF.js} +2 -2
- package/dist/chunk-CRP6Y7NF.js.map +1 -0
- package/dist/{chunk-3GWM5GR3.js → chunk-EPB3GQNL.js} +30 -65
- package/dist/chunk-EPB3GQNL.js.map +1 -0
- package/dist/{chunk-OIEWDFQU.js → chunk-FYSZFIZS.js} +2 -2
- package/dist/chunk-GIDT7C6I.js +37 -0
- package/dist/chunk-GIDT7C6I.js.map +1 -0
- package/dist/{chunk-IDZOVWP3.js → chunk-IK6NRCW5.js} +7 -7
- package/dist/{chunk-VGKZIGVI.js → chunk-LTEMH3CI.js} +2 -2
- package/dist/{chunk-6S222DHN.js → chunk-MJI74VEJ.js} +25 -1
- package/dist/chunk-MJI74VEJ.js.map +1 -0
- package/dist/{chunk-AY55T37A.js → chunk-SBGZJVTJ.js} +4 -30
- package/dist/chunk-SBGZJVTJ.js.map +1 -0
- package/dist/{chunk-A2IM7PGT.js → chunk-TUTYMOBL.js} +2 -2
- package/dist/{chunk-BRP5XJ6Q.js → chunk-WU4U6IHF.js} +2 -2
- package/dist/chunk-WU4U6IHF.js.map +1 -0
- package/dist/{chunk-C4JP64VW.js → chunk-YQLR3XOA.js} +2 -2
- package/dist/chunk-ZKNPQBIE.js +265 -0
- package/dist/chunk-ZKNPQBIE.js.map +1 -0
- package/dist/{chunk-4OGB7JZA.js → chunk-ZRVNAET3.js} +2 -2
- package/dist/{embedding-CW6SaOOz.d.ts → embedding-CwZ1ZNWv.d.ts} +1 -1
- package/dist/google/index.d.ts +2 -2
- package/dist/google/index.js +12 -10
- package/dist/google/index.js.map +1 -1
- package/dist/groq/index.d.ts +2 -2
- package/dist/groq/index.js +12 -10
- package/dist/groq/index.js.map +1 -1
- package/dist/http/index.d.ts +3 -3
- package/dist/http/index.js +2 -1
- package/dist/{image-stream-C0ciACM2.d.ts → image-stream-CeQHtjxS.d.ts} +1 -1
- package/dist/index.d.ts +7 -7
- package/dist/index.js +86 -283
- package/dist/index.js.map +1 -1
- package/dist/{llm-DwbUK7un.d.ts → llm-DS_-l71X.d.ts} +11 -3
- package/dist/middleware/logging/index.d.ts +2 -2
- package/dist/middleware/parsed-object/index.d.ts +2 -2
- package/dist/middleware/parsed-object/index.js +1 -1
- package/dist/middleware/persistence/index.d.ts +128 -0
- package/dist/middleware/persistence/index.js +144 -0
- package/dist/middleware/persistence/index.js.map +1 -0
- package/dist/middleware/pubsub/index.d.ts +27 -34
- package/dist/middleware/pubsub/index.js +49 -119
- package/dist/middleware/pubsub/index.js.map +1 -1
- package/dist/middleware/pubsub/server/express/index.d.ts +24 -10
- package/dist/middleware/pubsub/server/express/index.js +2 -2
- package/dist/middleware/pubsub/server/fastify/index.d.ts +24 -10
- package/dist/middleware/pubsub/server/fastify/index.js +2 -2
- package/dist/middleware/pubsub/server/h3/index.d.ts +23 -9
- package/dist/middleware/pubsub/server/h3/index.js +2 -2
- package/dist/middleware/pubsub/server/index.d.ts +2 -2
- package/dist/middleware/pubsub/server/index.js +5 -5
- package/dist/middleware/pubsub/server/webapi/index.d.ts +23 -13
- package/dist/middleware/pubsub/server/webapi/index.js +2 -2
- package/dist/ollama/index.d.ts +2 -2
- package/dist/ollama/index.js +12 -10
- package/dist/ollama/index.js.map +1 -1
- package/dist/openai/index.d.ts +2 -2
- package/dist/openai/index.js +12 -10
- package/dist/openai/index.js.map +1 -1
- package/dist/openrouter/index.d.ts +2 -2
- package/dist/openrouter/index.js +12 -10
- package/dist/openrouter/index.js.map +1 -1
- package/dist/proxy/index.d.ts +4 -4
- package/dist/proxy/index.js +20 -18
- package/dist/proxy/index.js.map +1 -1
- package/dist/proxy/server/express/index.d.ts +4 -4
- package/dist/proxy/server/express/index.js +3 -3
- package/dist/proxy/server/fastify/index.d.ts +4 -4
- package/dist/proxy/server/fastify/index.js +3 -3
- package/dist/proxy/server/h3/index.d.ts +4 -4
- package/dist/proxy/server/h3/index.js +3 -3
- package/dist/proxy/server/index.d.ts +4 -4
- package/dist/proxy/server/index.js +9 -9
- package/dist/proxy/server/webapi/index.d.ts +4 -4
- package/dist/proxy/server/webapi/index.js +3 -3
- package/dist/responses/index.d.ts +2 -2
- package/dist/responses/index.js +12 -10
- package/dist/responses/index.js.map +1 -1
- package/dist/{retry-YayV42GV.d.ts → retry-CgoBNa51.d.ts} +1 -1
- package/dist/{stream-CecfVCPO.d.ts → stream-sXhBtWjl.d.ts} +21 -6
- package/dist/types-Cr4F0tVy.d.ts +96 -0
- package/dist/xai/index.d.ts +2 -2
- package/dist/xai/index.js +12 -10
- package/dist/xai/index.js.map +1 -1
- package/package.json +6 -1
- package/dist/chunk-3GWM5GR3.js.map +0 -1
- package/dist/chunk-6S222DHN.js.map +0 -1
- package/dist/chunk-7DXVRILR.js.map +0 -1
- package/dist/chunk-AY55T37A.js.map +0 -1
- package/dist/chunk-BRP5XJ6Q.js.map +0 -1
- package/dist/chunk-HB4ZIH3T.js.map +0 -1
- package/dist/chunk-VOEWHQUB.js.map +0 -1
- package/dist/chunk-ZI67WIQS.js.map +0 -1
- package/dist/types-C8Gciizr.d.ts +0 -168
- /package/dist/{chunk-UFFJDYCE.js.map → chunk-7GTWHZY2.js.map} +0 -0
- /package/dist/{chunk-OIEWDFQU.js.map → chunk-FYSZFIZS.js.map} +0 -0
- /package/dist/{chunk-IDZOVWP3.js.map → chunk-IK6NRCW5.js.map} +0 -0
- /package/dist/{chunk-VGKZIGVI.js.map → chunk-LTEMH3CI.js.map} +0 -0
- /package/dist/{chunk-A2IM7PGT.js.map → chunk-TUTYMOBL.js.map} +0 -0
- /package/dist/{chunk-C4JP64VW.js.map → chunk-YQLR3XOA.js.map} +0 -0
- /package/dist/{chunk-4OGB7JZA.js.map → chunk-ZRVNAET3.js.map} +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/providers/cerebras/transform.ts","../../src/providers/cerebras/llm.ts","../../src/providers/cerebras/index.ts"],"sourcesContent":["/**\n * @fileoverview Cerebras API Message Transformers\n *\n * This module provides transformation functions for converting between the\n * Universal Provider Protocol (UPP) message format and Cerebras's Chat Completions\n * API format (OpenAI-compatible). It handles both request transformation (UPP -> Cerebras)\n * and response transformation (Cerebras -> UPP), including streaming event transformation.\n *\n * @module providers/cerebras/transform\n */\n\nimport type { LLMRequest, LLMResponse } from '../../types/llm.ts';\nimport type { Message } from '../../types/messages.ts';\nimport type { StreamEvent } from '../../types/stream.ts';\nimport { StreamEventType } from '../../types/stream.ts';\nimport type { Tool, ToolCall } from '../../types/tool.ts';\nimport type { TokenUsage } from '../../types/turn.ts';\nimport type { ContentBlock, TextBlock } from '../../types/content.ts';\nimport {\n AssistantMessage,\n isUserMessage,\n isAssistantMessage,\n isToolResultMessage,\n} from '../../types/messages.ts';\nimport { UPPError, ErrorCode, ModalityType } from '../../types/errors.ts';\nimport { generateId } from '../../utils/id.ts';\nimport type {\n CerebrasLLMParams,\n CerebrasRequest,\n CerebrasMessage,\n CerebrasUserContent,\n CerebrasTool,\n CerebrasResponse,\n CerebrasStreamChunk,\n CerebrasToolCall,\n} from './types.ts';\n\n/**\n * Normalizes system prompt to string.\n */\nfunction normalizeSystem(system: string | unknown[] | undefined): string | undefined {\n if (system === undefined || system === null) return undefined;\n if (typeof system === 'string') return system;\n if (!Array.isArray(system)) {\n throw new UPPError(\n 'System prompt must be a string or an array of text blocks',\n ErrorCode.InvalidRequest,\n 'cerebras',\n ModalityType.LLM\n );\n }\n\n const texts: string[] = [];\n for (const block of system) {\n if (!block || typeof block !== 'object' || !('text' in block)) {\n throw new UPPError(\n 'System prompt array must contain objects with a text field',\n ErrorCode.InvalidRequest,\n 'cerebras',\n ModalityType.LLM\n );\n }\n const textValue = (block as { text?: unknown }).text;\n if (typeof textValue !== 'string') {\n throw new UPPError(\n 'System prompt text must be a string',\n ErrorCode.InvalidRequest,\n 'cerebras',\n ModalityType.LLM\n );\n }\n if (textValue.length > 0) {\n texts.push(textValue);\n }\n }\n\n return texts.length > 0 ? texts.join('\\n\\n') : undefined;\n}\n\n/**\n * Filters content blocks to only include those with a valid type property.\n */\nfunction filterValidContent<T extends { type?: string }>(content: T[]): T[] {\n return content.filter((c) => c && typeof c.type === 'string');\n}\n\n/**\n * Transforms a UPP content block to Cerebras user content format.\n */\nfunction transformContentBlock(block: ContentBlock): CerebrasUserContent {\n switch (block.type) {\n case 'text':\n return { type: 'text', text: block.text };\n\n case 'image':\n throw new UPPError(\n 'Cerebras does not support image input',\n ErrorCode.InvalidRequest,\n 'cerebras',\n ModalityType.LLM\n );\n\n case 'document':\n throw new UPPError(\n 'Cerebras does not support document input',\n ErrorCode.InvalidRequest,\n 'cerebras',\n ModalityType.LLM\n );\n\n default:\n throw new UPPError(\n `Unsupported content type: ${block.type}`,\n ErrorCode.InvalidRequest,\n 'cerebras',\n ModalityType.LLM\n );\n }\n}\n\n/**\n * Transforms a single UPP message to Cerebras format.\n */\nfunction transformMessage(message: Message): CerebrasMessage | null {\n if (isUserMessage(message)) {\n const validContent = filterValidContent(message.content);\n if (validContent.length === 1 && validContent[0]?.type === 'text') {\n return {\n role: 'user',\n content: (validContent[0] as TextBlock).text,\n };\n }\n return {\n role: 'user',\n content: validContent.map(transformContentBlock),\n };\n }\n\n if (isAssistantMessage(message)) {\n const validContent = filterValidContent(message.content);\n const textContent = validContent\n .filter((c): c is TextBlock => c.type === 'text')\n .map((c) => c.text)\n .join('');\n\n const assistantMessage: CerebrasMessage = {\n role: 'assistant',\n content: textContent || null,\n };\n\n if (message.toolCalls && message.toolCalls.length > 0) {\n (assistantMessage as { tool_calls?: CerebrasToolCall[] }).tool_calls =\n message.toolCalls.map((call) => ({\n id: call.toolCallId,\n type: 'function' as const,\n function: {\n name: call.toolName,\n arguments: JSON.stringify(call.arguments),\n },\n }));\n }\n\n return assistantMessage;\n }\n\n if (isToolResultMessage(message)) {\n const results = message.results.map((result) => ({\n role: 'tool' as const,\n tool_call_id: result.toolCallId,\n content:\n typeof result.result === 'string'\n ? result.result\n : JSON.stringify(result.result),\n }));\n\n return results[0] ?? null;\n }\n\n return null;\n}\n\n/**\n * Transforms tool result messages into multiple Cerebras tool messages.\n */\nexport function transformToolResults(message: Message): CerebrasMessage[] {\n if (!isToolResultMessage(message)) {\n const single = transformMessage(message);\n return single ? [single] : [];\n }\n\n return message.results.map((result) => ({\n role: 'tool' as const,\n tool_call_id: result.toolCallId,\n content:\n typeof result.result === 'string'\n ? result.result\n : JSON.stringify(result.result),\n }));\n}\n\n/**\n * Transforms UPP messages to Cerebras message format.\n *\n * @param messages - Array of UPP messages to transform\n * @param system - Optional system prompt\n * @returns Array of Cerebras-formatted messages\n */\nfunction transformMessages(\n messages: Message[],\n system?: string | unknown[]\n): CerebrasMessage[] {\n const result: CerebrasMessage[] = [];\n const normalizedSystem = normalizeSystem(system);\n\n if (normalizedSystem) {\n result.push({\n role: 'system',\n content: normalizedSystem,\n });\n }\n\n for (const message of messages) {\n if (isToolResultMessage(message)) {\n const toolMessages = transformToolResults(message);\n result.push(...toolMessages);\n } else {\n const transformed = transformMessage(message);\n if (transformed) {\n result.push(transformed);\n }\n }\n }\n\n return result;\n}\n\n/**\n * Extracts Cerebras-specific options from tool metadata.\n */\nfunction extractToolOptions(tool: Tool): { strict?: boolean } {\n const cerebrasMeta = tool.metadata?.cerebras as { strict?: boolean } | undefined;\n return { strict: cerebrasMeta?.strict };\n}\n\n/**\n * Transforms a UPP tool definition to Cerebras function tool format.\n */\nfunction transformTool(tool: Tool): CerebrasTool {\n const { strict } = extractToolOptions(tool);\n\n return {\n type: 'function',\n function: {\n name: tool.name,\n description: tool.description,\n parameters: {\n type: 'object',\n properties: tool.parameters.properties,\n required: tool.parameters.required,\n ...(tool.parameters.additionalProperties !== undefined\n ? { additionalProperties: tool.parameters.additionalProperties }\n : {}),\n },\n ...(strict !== undefined ? { strict } : {}),\n },\n };\n}\n\n/**\n * Transforms a UPP LLM request into Cerebras Chat Completions API format.\n *\n * @param request - The UPP LLM request containing messages, tools, and configuration\n * @param modelId - The Cerebras model identifier (e.g., 'llama-3.3-70b')\n * @returns A Cerebras Chat Completions API request body\n */\nexport function transformRequest(\n request: LLMRequest<CerebrasLLMParams>,\n modelId: string\n): CerebrasRequest {\n const params = request.params ?? ({} as CerebrasLLMParams);\n\n const cerebrasRequest: CerebrasRequest = {\n ...params,\n model: modelId,\n messages: transformMessages(request.messages, request.system),\n };\n\n if (request.tools && request.tools.length > 0) {\n cerebrasRequest.tools = request.tools.map(transformTool);\n }\n\n if (request.structure) {\n const schema: Record<string, unknown> = {\n type: 'object',\n properties: request.structure.properties,\n required: request.structure.required,\n ...(request.structure.additionalProperties !== undefined\n ? { additionalProperties: request.structure.additionalProperties }\n : { additionalProperties: false }),\n };\n if (request.structure.description) {\n schema.description = request.structure.description;\n }\n\n cerebrasRequest.response_format = {\n type: 'json_schema',\n json_schema: {\n name: 'json_response',\n description: request.structure.description,\n schema,\n strict: true,\n },\n };\n }\n\n return cerebrasRequest;\n}\n\n/**\n * Transforms a Cerebras response to UPP LLMResponse format.\n */\nexport function transformResponse(data: CerebrasResponse): LLMResponse {\n const choice = data.choices[0];\n if (!choice) {\n throw new UPPError(\n 'No choices in Cerebras response',\n ErrorCode.InvalidResponse,\n 'cerebras',\n ModalityType.LLM\n );\n }\n\n const textContent: TextBlock[] = [];\n let structuredData: unknown;\n if (choice.message.content) {\n textContent.push({ type: 'text', text: choice.message.content });\n try {\n structuredData = JSON.parse(choice.message.content);\n } catch {\n // Not JSON - expected for non-structured responses\n }\n }\n\n const toolCalls: ToolCall[] = [];\n if (choice.message.tool_calls) {\n for (const call of choice.message.tool_calls) {\n let args: Record<string, unknown> = {};\n try {\n args = JSON.parse(call.function.arguments);\n } catch {\n // Invalid JSON - use empty object\n }\n toolCalls.push({\n toolCallId: call.id,\n toolName: call.function.name,\n arguments: args,\n });\n }\n }\n\n const message = new AssistantMessage(\n textContent,\n toolCalls.length > 0 ? toolCalls : undefined,\n {\n id: data.id || generateId(),\n metadata: {\n cerebras: {\n model: data.model,\n finish_reason: choice.finish_reason,\n system_fingerprint: data.system_fingerprint,\n reasoning: choice.message.reasoning,\n time_info: data.time_info,\n },\n },\n }\n );\n\n const usage: TokenUsage = {\n inputTokens: data.usage.prompt_tokens,\n outputTokens: data.usage.completion_tokens,\n totalTokens: data.usage.total_tokens,\n cacheReadTokens: data.usage.prompt_tokens_details?.cached_tokens ?? 0,\n cacheWriteTokens: 0,\n };\n\n let stopReason = 'end_turn';\n switch (choice.finish_reason) {\n case 'stop':\n stopReason = 'end_turn';\n break;\n case 'length':\n stopReason = 'max_tokens';\n break;\n case 'tool_calls':\n stopReason = 'tool_use';\n break;\n case 'content_filter':\n stopReason = 'content_filter';\n break;\n }\n\n return {\n message,\n usage,\n stopReason,\n data: structuredData,\n };\n}\n\n/**\n * Mutable state object for accumulating data during streaming responses.\n */\nexport interface CerebrasStreamState {\n /** Response ID from the first chunk */\n id: string;\n /** Model identifier */\n model: string;\n /** Accumulated text content */\n text: string;\n /** Accumulated reasoning content */\n reasoning: string;\n /** Map of tool call index to accumulated tool call data */\n toolCalls: Map<number, { id: string; name: string; arguments: string }>;\n /** The finish reason when streaming completes */\n finishReason: string | null;\n /** Input token count (from usage chunk) */\n inputTokens: number;\n /** Output token count (from usage chunk) */\n outputTokens: number;\n /** Number of tokens read from cache */\n cacheReadTokens: number;\n /** Time info from the response */\n timeInfo?: {\n queue_time?: number;\n prompt_time?: number;\n completion_time?: number;\n total_time?: number;\n };\n}\n\n/**\n * Creates a fresh stream state object for a new streaming session.\n */\nexport function createStreamState(): CerebrasStreamState {\n return {\n id: '',\n model: '',\n text: '',\n reasoning: '',\n toolCalls: new Map(),\n finishReason: null,\n inputTokens: 0,\n outputTokens: 0,\n cacheReadTokens: 0,\n };\n}\n\n/**\n * Transforms a Cerebras streaming chunk into UPP stream events.\n */\nexport function transformStreamEvent(\n chunk: CerebrasStreamChunk,\n state: CerebrasStreamState\n): StreamEvent[] {\n const events: StreamEvent[] = [];\n\n if (chunk.id && !state.id) {\n state.id = chunk.id;\n events.push({ type: StreamEventType.MessageStart, index: 0, delta: {} });\n }\n if (chunk.model) {\n state.model = chunk.model;\n }\n\n const choice = chunk.choices[0];\n if (choice) {\n if (choice.delta.content) {\n state.text += choice.delta.content;\n events.push({\n type: StreamEventType.TextDelta,\n index: 0,\n delta: { text: choice.delta.content },\n });\n }\n\n if (choice.delta.reasoning) {\n state.reasoning += choice.delta.reasoning;\n events.push({\n type: StreamEventType.ReasoningDelta,\n index: 0,\n delta: { text: choice.delta.reasoning },\n });\n }\n\n if (choice.delta.tool_calls) {\n for (const toolCallDelta of choice.delta.tool_calls) {\n const index = toolCallDelta.index;\n let toolCall = state.toolCalls.get(index);\n\n if (!toolCall) {\n toolCall = { id: '', name: '', arguments: '' };\n state.toolCalls.set(index, toolCall);\n }\n\n if (toolCallDelta.id) {\n toolCall.id = toolCallDelta.id;\n }\n if (toolCallDelta.function?.name) {\n toolCall.name = toolCallDelta.function.name;\n }\n if (toolCallDelta.function?.arguments) {\n toolCall.arguments += toolCallDelta.function.arguments;\n events.push({\n type: StreamEventType.ToolCallDelta,\n index: index,\n delta: {\n toolCallId: toolCall.id,\n toolName: toolCall.name,\n argumentsJson: toolCallDelta.function.arguments,\n },\n });\n }\n }\n }\n\n if (choice.finish_reason) {\n state.finishReason = choice.finish_reason;\n events.push({ type: StreamEventType.MessageStop, index: 0, delta: {} });\n }\n }\n\n if (chunk.usage) {\n state.inputTokens = chunk.usage.prompt_tokens;\n state.outputTokens = chunk.usage.completion_tokens;\n state.cacheReadTokens = chunk.usage.prompt_tokens_details?.cached_tokens ?? 0;\n }\n\n if (chunk.time_info) {\n state.timeInfo = chunk.time_info;\n }\n\n return events;\n}\n\n/**\n * Builds a complete LLMResponse from accumulated streaming state.\n */\nexport function buildResponseFromState(state: CerebrasStreamState): LLMResponse {\n const textContent: TextBlock[] = [];\n let structuredData: unknown;\n if (state.text) {\n textContent.push({ type: 'text', text: state.text });\n try {\n structuredData = JSON.parse(state.text);\n } catch {\n // Not JSON - expected for non-structured responses\n }\n }\n\n const toolCalls: ToolCall[] = [];\n for (const [, toolCall] of state.toolCalls) {\n let args: Record<string, unknown> = {};\n if (toolCall.arguments) {\n try {\n args = JSON.parse(toolCall.arguments);\n } catch {\n // Invalid JSON - use empty object\n }\n }\n toolCalls.push({\n toolCallId: toolCall.id,\n toolName: toolCall.name,\n arguments: args,\n });\n }\n\n const messageId = state.id || generateId();\n const message = new AssistantMessage(\n textContent,\n toolCalls.length > 0 ? toolCalls : undefined,\n {\n id: messageId,\n metadata: {\n cerebras: {\n model: state.model,\n finish_reason: state.finishReason,\n reasoning: state.reasoning || undefined,\n time_info: state.timeInfo,\n },\n },\n }\n );\n\n const usage: TokenUsage = {\n inputTokens: state.inputTokens,\n outputTokens: state.outputTokens,\n totalTokens: state.inputTokens + state.outputTokens,\n cacheReadTokens: state.cacheReadTokens,\n cacheWriteTokens: 0,\n };\n\n let stopReason = 'end_turn';\n switch (state.finishReason) {\n case 'stop':\n stopReason = 'end_turn';\n break;\n case 'length':\n stopReason = 'max_tokens';\n break;\n case 'tool_calls':\n stopReason = 'tool_use';\n break;\n case 'content_filter':\n stopReason = 'content_filter';\n break;\n }\n\n return {\n message,\n usage,\n stopReason,\n data: structuredData,\n };\n}\n","/**\n * @fileoverview Cerebras Chat Completions API Handler\n *\n * This module implements the LLM handler for Cerebras's Chat Completions API\n * (OpenAI-compatible at `/v1/chat/completions`).\n *\n * @see {@link https://inference-docs.cerebras.ai/introduction Cerebras API Reference}\n * @module providers/cerebras/llm\n */\n\nimport type { BoundLLMModel, LLMRequest, LLMResponse, LLMStreamResult, LLMCapabilities } from '../../types/llm.ts';\nimport type { LLMHandler } from '../../types/provider.ts';\nimport type { StreamEvent } from '../../types/stream.ts';\nimport { StreamEventType, objectDelta } from '../../types/stream.ts';\nimport type { LLMProvider } from '../../types/provider.ts';\nimport { UPPError, ErrorCode, ModalityType } from '../../types/errors.ts';\nimport { resolveApiKey } from '../../http/keys.ts';\nimport { doFetch, doStreamFetch } from '../../http/fetch.ts';\nimport { parseSSEStream } from '../../http/sse.ts';\nimport { normalizeHttpError } from '../../http/errors.ts';\nimport { parseJsonResponse } from '../../http/json.ts';\nimport { toError } from '../../utils/error.ts';\nimport type { CerebrasLLMParams, CerebrasResponse, CerebrasStreamChunk } from './types.ts';\nimport {\n transformRequest,\n transformResponse,\n transformStreamEvent,\n createStreamState,\n buildResponseFromState,\n} from './transform.ts';\n\n/** Base URL for Cerebras's Chat Completions API endpoint */\nconst CEREBRAS_API_URL = 'https://api.cerebras.ai/v1/chat/completions';\n\n/**\n * Capability declaration for the Cerebras Chat Completions API.\n *\n * Defines what features are supported by this handler:\n * - Streaming: Real-time token-by-token response streaming via SSE\n * - Tools: Function calling for structured interactions\n * - Structured Output: JSON schema-based response formatting\n * - Image Input: Not supported\n */\nconst CEREBRAS_CAPABILITIES: LLMCapabilities = {\n streaming: true,\n tools: true,\n structuredOutput: true,\n imageInput: false,\n documentInput: false,\n videoInput: false,\n audioInput: false,\n};\n\n/**\n * Creates an LLM handler for Cerebras's Chat Completions API.\n *\n * This factory function creates a handler that communicates with the\n * `/v1/chat/completions` endpoint. The handler supports both synchronous\n * completion requests and streaming responses.\n *\n * @returns An LLM handler configured for the Cerebras API\n *\n * @example\n * ```typescript\n * const handler = createLLMHandler();\n * const model = handler.bind('llama-3.3-70b');\n *\n * // Synchronous completion\n * const response = await model.complete({\n * messages: [{ role: 'user', content: 'Hello!' }],\n * config: { apiKey: 'csk-...' }\n * });\n *\n * // Streaming completion\n * const stream = model.stream({\n * messages: [{ role: 'user', content: 'Tell me a story' }],\n * config: { apiKey: 'csk-...' }\n * });\n *\n * for await (const event of stream) {\n * if (event.type === StreamEventType.TextDelta) {\n * process.stdout.write(event.delta.text);\n * }\n * }\n * ```\n */\nexport function createLLMHandler(): LLMHandler<CerebrasLLMParams> {\n let providerRef: LLMProvider<CerebrasLLMParams> | null = null;\n\n return {\n _setProvider(provider: LLMProvider<CerebrasLLMParams>) {\n providerRef = provider;\n },\n\n bind(modelId: string): BoundLLMModel<CerebrasLLMParams> {\n if (!providerRef) {\n throw new UPPError(\n 'Provider reference not set. Handler must be used with createProvider() or have _setProvider called.',\n ErrorCode.InvalidRequest,\n 'cerebras',\n ModalityType.LLM\n );\n }\n\n const model: BoundLLMModel<CerebrasLLMParams> = {\n modelId,\n capabilities: CEREBRAS_CAPABILITIES,\n\n get provider(): LLMProvider<CerebrasLLMParams> {\n return providerRef!;\n },\n\n async complete(request: LLMRequest<CerebrasLLMParams>): Promise<LLMResponse> {\n const apiKey = await resolveApiKey(\n request.config,\n 'CEREBRAS_API_KEY',\n 'cerebras',\n 'llm'\n );\n\n const baseUrl = request.config.baseUrl ?? CEREBRAS_API_URL;\n const body = transformRequest(request, modelId);\n\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${apiKey}`,\n };\n\n if (request.config.headers) {\n for (const [key, value] of Object.entries(request.config.headers)) {\n if (value !== undefined) {\n headers[key] = value;\n }\n }\n }\n\n const response = await doFetch(\n baseUrl,\n {\n method: 'POST',\n headers,\n body: JSON.stringify(body),\n signal: request.signal,\n },\n request.config,\n 'cerebras',\n 'llm'\n );\n\n const data = await parseJsonResponse<CerebrasResponse>(response, 'cerebras', 'llm');\n return transformResponse(data);\n },\n\n stream(request: LLMRequest<CerebrasLLMParams>): LLMStreamResult {\n const state = createStreamState();\n let responseResolve: (value: LLMResponse) => void;\n let responseReject: (error: Error) => void;\n\n const responsePromise = new Promise<LLMResponse>((resolve, reject) => {\n responseResolve = resolve;\n responseReject = reject;\n });\n\n async function* generateEvents(): AsyncGenerator<StreamEvent, void, unknown> {\n try {\n const apiKey = await resolveApiKey(\n request.config,\n 'CEREBRAS_API_KEY',\n 'cerebras',\n 'llm'\n );\n\n const baseUrl = request.config.baseUrl ?? CEREBRAS_API_URL;\n const body = transformRequest(request, modelId);\n body.stream = true;\n body.stream_options = { include_usage: true };\n\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${apiKey}`,\n Accept: 'text/event-stream',\n };\n\n if (request.config.headers) {\n for (const [key, value] of Object.entries(request.config.headers)) {\n if (value !== undefined) {\n headers[key] = value;\n }\n }\n }\n\n const response = await doStreamFetch(\n baseUrl,\n {\n method: 'POST',\n headers,\n body: JSON.stringify(body),\n signal: request.signal,\n },\n request.config,\n 'cerebras',\n 'llm'\n );\n\n if (!response.ok) {\n const error = await normalizeHttpError(response, 'cerebras', 'llm');\n responseReject(error);\n throw error;\n }\n\n if (!response.body) {\n const error = new UPPError(\n 'No response body for streaming request',\n ErrorCode.ProviderError,\n 'cerebras',\n ModalityType.LLM\n );\n responseReject(error);\n throw error;\n }\n\n for await (const data of parseSSEStream(response.body)) {\n // Skip [DONE] marker\n if (data === '[DONE]') {\n continue;\n }\n\n // Check for Cerebras error event\n if (typeof data === 'object' && data !== null) {\n const chunk = data as CerebrasStreamChunk;\n\n // Check for error in chunk\n if ('error' in chunk && chunk.error) {\n const errorData = chunk.error as { message?: string; type?: string };\n const error = new UPPError(\n errorData.message ?? 'Unknown error',\n ErrorCode.ProviderError,\n 'cerebras',\n ModalityType.LLM\n );\n responseReject(error);\n throw error;\n }\n\n const uppEvents = transformStreamEvent(chunk, state);\n for (const event of uppEvents) {\n yield event;\n // Also emit ObjectDelta for structured output - gives developers explicit hook\n if (request.structure && event.type === StreamEventType.TextDelta) {\n yield objectDelta(event.delta.text ?? '', event.index);\n }\n }\n }\n }\n\n // Build final response\n responseResolve(buildResponseFromState(state));\n } catch (error) {\n const err = toError(error);\n responseReject(err);\n throw err;\n }\n }\n\n return {\n [Symbol.asyncIterator]() {\n return generateEvents();\n },\n response: responsePromise,\n };\n },\n };\n\n return model;\n },\n };\n}\n","/**\n * @fileoverview Cerebras Provider Factory\n *\n * This module provides the main Cerebras provider implementation for the\n * OpenAI-compatible Chat Completions API. Cerebras offers extremely fast\n * inference with models like Llama, Qwen, and their reasoning models.\n *\n * @module providers/cerebras\n */\n\nimport { createProvider } from '../../core/provider.ts';\nimport { createLLMHandler } from './llm.ts';\n\n/**\n * Configuration options for the Cerebras provider.\n *\n * Currently Cerebras only supports one API endpoint (Chat Completions),\n * so no additional options are needed.\n */\nexport interface CerebrasProviderOptions {\n // Reserved for future use (e.g., if Cerebras adds multiple API modes)\n}\n\n/**\n * The Cerebras provider instance.\n *\n * Use this provider to create model references for Cerebras models like\n * Llama 3.3, Qwen 3, GPT-OSS (reasoning), and other models available on Cerebras.\n *\n * @example Basic usage\n * ```typescript\n * import { cerebras } from './providers/cerebras';\n * import { llm } from './core/llm';\n *\n * const model = llm({\n * model: cerebras('llama-3.3-70b'),\n * params: { max_completion_tokens: 1000 }\n * });\n *\n * const turn = await model.generate('Hello!');\n * console.log(turn.response.text);\n * ```\n *\n * @example With streaming\n * ```typescript\n * const stream = model.stream('Tell me a story');\n *\n * for await (const event of stream) {\n * if (event.type === StreamEventType.TextDelta) {\n * process.stdout.write(event.delta.text ?? '');\n * }\n * }\n *\n * const turn = await stream.turn;\n * console.log('Tokens used:', turn.usage.totalTokens);\n * ```\n *\n * @example With tools\n * ```typescript\n * const calculator = {\n * name: 'calculate',\n * description: 'Calculate a math expression',\n * parameters: {\n * type: 'object',\n * properties: {\n * expression: { type: 'string' }\n * },\n * required: ['expression']\n * },\n * run: async (params: { expression: string }) => {\n * return eval(params.expression);\n * }\n * };\n *\n * const model = llm({\n * model: cerebras('llama-3.3-70b'),\n * tools: [calculator]\n * });\n *\n * const turn = await model.generate('What is 15 + 27?');\n * ```\n *\n * @example With reasoning\n * ```typescript\n * const model = llm({\n * model: cerebras('gpt-oss-120b'),\n * params: {\n * reasoning_effort: 'high',\n * reasoning_format: 'parsed'\n * }\n * });\n *\n * const turn = await model.generate('Solve this complex math problem...');\n * // Reasoning is available in turn.response.metadata.cerebras.reasoning\n * ```\n *\n * @example Available models\n * Production models:\n * - `llama3.1-8b` - Fast Llama 3.1 8B model (~2200 tok/s)\n * - `llama-3.3-70b` - Llama 3.3 70B with tool use (~2100 tok/s)\n * - `qwen-3-32b` - Qwen 3 32B with reasoning support (~2600 tok/s)\n * - `qwen-3-235b-a22b-instruct-2507` - Large Qwen model (~1400 tok/s)\n * - `gpt-oss-120b` - Reasoning model with high performance (~3000 tok/s)\n * - `zai-glm-4.6` - Z.ai GLM model with reasoning (~1000 tok/s)\n * - `zai-glm-4.7` - Z.ai GLM model with reasoning (~1000 tok/s)\n */\nexport const cerebras = createProvider<CerebrasProviderOptions>({\n name: 'cerebras',\n version: '1.0.0',\n handlers: {\n llm: createLLMHandler(),\n },\n});\n\nexport type {\n CerebrasLLMParams,\n CerebrasHeaders,\n CerebrasResponseFormat,\n CerebrasMessage,\n CerebrasRequest,\n CerebrasResponse,\n CerebrasStreamChunk,\n CerebrasTool,\n CerebrasToolCall,\n CerebrasToolChoice,\n CerebrasUsage,\n CerebrasTimeInfo,\n} from './types.ts';\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/providers/cerebras/transform.ts","../../src/providers/cerebras/llm.ts","../../src/providers/cerebras/index.ts"],"sourcesContent":["/**\n * @fileoverview Cerebras API Message Transformers\n *\n * This module provides transformation functions for converting between the\n * Universal Provider Protocol (UPP) message format and Cerebras's Chat Completions\n * API format (OpenAI-compatible). It handles both request transformation (UPP -> Cerebras)\n * and response transformation (Cerebras -> UPP), including streaming event transformation.\n *\n * @module providers/cerebras/transform\n */\n\nimport type { LLMRequest, LLMResponse } from '../../types/llm.ts';\nimport type { Message } from '../../types/messages.ts';\nimport type { StreamEvent } from '../../types/stream.ts';\nimport { StreamEventType } from '../../types/stream.ts';\nimport type { Tool, ToolCall } from '../../types/tool.ts';\nimport type { TokenUsage } from '../../types/turn.ts';\nimport type { ContentBlock, TextBlock } from '../../types/content.ts';\nimport {\n AssistantMessage,\n isUserMessage,\n isAssistantMessage,\n isToolResultMessage,\n} from '../../types/messages.ts';\nimport { UPPError, ErrorCode, ModalityType } from '../../types/errors.ts';\nimport { generateId } from '../../utils/id.ts';\nimport type {\n CerebrasLLMParams,\n CerebrasRequest,\n CerebrasMessage,\n CerebrasUserContent,\n CerebrasTool,\n CerebrasResponse,\n CerebrasStreamChunk,\n CerebrasToolCall,\n} from './types.ts';\n\n/**\n * Normalizes system prompt to string.\n */\nfunction normalizeSystem(system: string | unknown[] | undefined): string | undefined {\n if (system === undefined || system === null) return undefined;\n if (typeof system === 'string') return system;\n if (!Array.isArray(system)) {\n throw new UPPError(\n 'System prompt must be a string or an array of text blocks',\n ErrorCode.InvalidRequest,\n 'cerebras',\n ModalityType.LLM\n );\n }\n\n const texts: string[] = [];\n for (const block of system) {\n if (!block || typeof block !== 'object' || !('text' in block)) {\n throw new UPPError(\n 'System prompt array must contain objects with a text field',\n ErrorCode.InvalidRequest,\n 'cerebras',\n ModalityType.LLM\n );\n }\n const textValue = (block as { text?: unknown }).text;\n if (typeof textValue !== 'string') {\n throw new UPPError(\n 'System prompt text must be a string',\n ErrorCode.InvalidRequest,\n 'cerebras',\n ModalityType.LLM\n );\n }\n if (textValue.length > 0) {\n texts.push(textValue);\n }\n }\n\n return texts.length > 0 ? texts.join('\\n\\n') : undefined;\n}\n\n/**\n * Filters content blocks to only include those with a valid type property.\n */\nfunction filterValidContent<T extends { type?: string }>(content: T[]): T[] {\n return content.filter((c) => c && typeof c.type === 'string');\n}\n\n/**\n * Transforms a UPP content block to Cerebras user content format.\n */\nfunction transformContentBlock(block: ContentBlock): CerebrasUserContent {\n switch (block.type) {\n case 'text':\n return { type: 'text', text: block.text };\n\n case 'image':\n throw new UPPError(\n 'Cerebras does not support image input',\n ErrorCode.InvalidRequest,\n 'cerebras',\n ModalityType.LLM\n );\n\n case 'document':\n throw new UPPError(\n 'Cerebras does not support document input',\n ErrorCode.InvalidRequest,\n 'cerebras',\n ModalityType.LLM\n );\n\n default:\n throw new UPPError(\n `Unsupported content type: ${block.type}`,\n ErrorCode.InvalidRequest,\n 'cerebras',\n ModalityType.LLM\n );\n }\n}\n\n/**\n * Transforms a single UPP message to Cerebras format.\n */\nfunction transformMessage(message: Message): CerebrasMessage | null {\n if (isUserMessage(message)) {\n const validContent = filterValidContent(message.content);\n if (validContent.length === 1 && validContent[0]?.type === 'text') {\n return {\n role: 'user',\n content: (validContent[0] as TextBlock).text,\n };\n }\n return {\n role: 'user',\n content: validContent.map(transformContentBlock),\n };\n }\n\n if (isAssistantMessage(message)) {\n const validContent = filterValidContent(message.content);\n const textContent = validContent\n .filter((c): c is TextBlock => c.type === 'text')\n .map((c) => c.text)\n .join('');\n\n const assistantMessage: CerebrasMessage = {\n role: 'assistant',\n content: textContent || null,\n };\n\n if (message.toolCalls && message.toolCalls.length > 0) {\n (assistantMessage as { tool_calls?: CerebrasToolCall[] }).tool_calls =\n message.toolCalls.map((call) => ({\n id: call.toolCallId,\n type: 'function' as const,\n function: {\n name: call.toolName,\n arguments: JSON.stringify(call.arguments),\n },\n }));\n }\n\n return assistantMessage;\n }\n\n if (isToolResultMessage(message)) {\n const results = message.results.map((result) => ({\n role: 'tool' as const,\n tool_call_id: result.toolCallId,\n content:\n typeof result.result === 'string'\n ? result.result\n : JSON.stringify(result.result),\n }));\n\n return results[0] ?? null;\n }\n\n return null;\n}\n\n/**\n * Transforms tool result messages into multiple Cerebras tool messages.\n */\nexport function transformToolResults(message: Message): CerebrasMessage[] {\n if (!isToolResultMessage(message)) {\n const single = transformMessage(message);\n return single ? [single] : [];\n }\n\n return message.results.map((result) => ({\n role: 'tool' as const,\n tool_call_id: result.toolCallId,\n content:\n typeof result.result === 'string'\n ? result.result\n : JSON.stringify(result.result),\n }));\n}\n\n/**\n * Transforms UPP messages to Cerebras message format.\n *\n * @param messages - Array of UPP messages to transform\n * @param system - Optional system prompt\n * @returns Array of Cerebras-formatted messages\n */\nfunction transformMessages(\n messages: Message[],\n system?: string | unknown[]\n): CerebrasMessage[] {\n const result: CerebrasMessage[] = [];\n const normalizedSystem = normalizeSystem(system);\n\n if (normalizedSystem) {\n result.push({\n role: 'system',\n content: normalizedSystem,\n });\n }\n\n for (const message of messages) {\n if (isToolResultMessage(message)) {\n const toolMessages = transformToolResults(message);\n result.push(...toolMessages);\n } else {\n const transformed = transformMessage(message);\n if (transformed) {\n result.push(transformed);\n }\n }\n }\n\n return result;\n}\n\n/**\n * Extracts Cerebras-specific options from tool metadata.\n */\nfunction extractToolOptions(tool: Tool): { strict?: boolean } {\n const cerebrasMeta = tool.metadata?.cerebras as { strict?: boolean } | undefined;\n return { strict: cerebrasMeta?.strict };\n}\n\n/**\n * Transforms a UPP tool definition to Cerebras function tool format.\n */\nfunction transformTool(tool: Tool): CerebrasTool {\n const { strict } = extractToolOptions(tool);\n\n return {\n type: 'function',\n function: {\n name: tool.name,\n description: tool.description,\n parameters: {\n type: 'object',\n properties: tool.parameters.properties,\n required: tool.parameters.required,\n ...(tool.parameters.additionalProperties !== undefined\n ? { additionalProperties: tool.parameters.additionalProperties }\n : {}),\n },\n ...(strict !== undefined ? { strict } : {}),\n },\n };\n}\n\n/**\n * Transforms a UPP LLM request into Cerebras Chat Completions API format.\n *\n * @param request - The UPP LLM request containing messages, tools, and configuration\n * @param modelId - The Cerebras model identifier (e.g., 'llama-3.3-70b')\n * @returns A Cerebras Chat Completions API request body\n */\nexport function transformRequest(\n request: LLMRequest<CerebrasLLMParams>,\n modelId: string\n): CerebrasRequest {\n const params = request.params ?? ({} as CerebrasLLMParams);\n\n const cerebrasRequest: CerebrasRequest = {\n ...params,\n model: modelId,\n messages: transformMessages(request.messages, request.system),\n };\n\n if (request.tools && request.tools.length > 0) {\n cerebrasRequest.tools = request.tools.map(transformTool);\n }\n\n if (request.structure) {\n const schema: Record<string, unknown> = {\n type: 'object',\n properties: request.structure.properties,\n required: request.structure.required,\n ...(request.structure.additionalProperties !== undefined\n ? { additionalProperties: request.structure.additionalProperties }\n : { additionalProperties: false }),\n };\n if (request.structure.description) {\n schema.description = request.structure.description;\n }\n\n cerebrasRequest.response_format = {\n type: 'json_schema',\n json_schema: {\n name: 'json_response',\n description: request.structure.description,\n schema,\n strict: true,\n },\n };\n }\n\n return cerebrasRequest;\n}\n\n/**\n * Transforms a Cerebras response to UPP LLMResponse format.\n */\nexport function transformResponse(data: CerebrasResponse): LLMResponse {\n const choice = data.choices[0];\n if (!choice) {\n throw new UPPError(\n 'No choices in Cerebras response',\n ErrorCode.InvalidResponse,\n 'cerebras',\n ModalityType.LLM\n );\n }\n\n const textContent: TextBlock[] = [];\n let structuredData: unknown;\n if (choice.message.content) {\n textContent.push({ type: 'text', text: choice.message.content });\n try {\n structuredData = JSON.parse(choice.message.content);\n } catch {\n // Not JSON - expected for non-structured responses\n }\n }\n\n const toolCalls: ToolCall[] = [];\n if (choice.message.tool_calls) {\n for (const call of choice.message.tool_calls) {\n let args: Record<string, unknown> = {};\n try {\n args = JSON.parse(call.function.arguments);\n } catch {\n // Invalid JSON - use empty object\n }\n toolCalls.push({\n toolCallId: call.id,\n toolName: call.function.name,\n arguments: args,\n });\n }\n }\n\n const message = new AssistantMessage(\n textContent,\n toolCalls.length > 0 ? toolCalls : undefined,\n {\n id: data.id || generateId(),\n metadata: {\n cerebras: {\n model: data.model,\n finish_reason: choice.finish_reason,\n system_fingerprint: data.system_fingerprint,\n reasoning: choice.message.reasoning,\n time_info: data.time_info,\n },\n },\n }\n );\n\n const usage: TokenUsage = {\n inputTokens: data.usage.prompt_tokens,\n outputTokens: data.usage.completion_tokens,\n totalTokens: data.usage.total_tokens,\n cacheReadTokens: data.usage.prompt_tokens_details?.cached_tokens ?? 0,\n cacheWriteTokens: 0,\n };\n\n let stopReason = 'end_turn';\n switch (choice.finish_reason) {\n case 'stop':\n stopReason = 'end_turn';\n break;\n case 'length':\n stopReason = 'max_tokens';\n break;\n case 'tool_calls':\n stopReason = 'tool_use';\n break;\n case 'content_filter':\n stopReason = 'content_filter';\n break;\n }\n\n return {\n message,\n usage,\n stopReason,\n data: structuredData,\n };\n}\n\n/**\n * Mutable state object for accumulating data during streaming responses.\n */\nexport interface CerebrasStreamState {\n /** Response ID from the first chunk */\n id: string;\n /** Model identifier */\n model: string;\n /** Accumulated text content */\n text: string;\n /** Accumulated reasoning content */\n reasoning: string;\n /** Map of tool call index to accumulated tool call data */\n toolCalls: Map<number, { id: string; name: string; arguments: string }>;\n /** The finish reason when streaming completes */\n finishReason: string | null;\n /** Input token count (from usage chunk) */\n inputTokens: number;\n /** Output token count (from usage chunk) */\n outputTokens: number;\n /** Number of tokens read from cache */\n cacheReadTokens: number;\n /** Time info from the response */\n timeInfo?: {\n queue_time?: number;\n prompt_time?: number;\n completion_time?: number;\n total_time?: number;\n };\n}\n\n/**\n * Creates a fresh stream state object for a new streaming session.\n */\nexport function createStreamState(): CerebrasStreamState {\n return {\n id: '',\n model: '',\n text: '',\n reasoning: '',\n toolCalls: new Map(),\n finishReason: null,\n inputTokens: 0,\n outputTokens: 0,\n cacheReadTokens: 0,\n };\n}\n\n/**\n * Transforms a Cerebras streaming chunk into UPP stream events.\n */\nexport function transformStreamEvent(\n chunk: CerebrasStreamChunk,\n state: CerebrasStreamState\n): StreamEvent[] {\n const events: StreamEvent[] = [];\n\n if (chunk.id && !state.id) {\n state.id = chunk.id;\n events.push({ type: StreamEventType.MessageStart, index: 0, delta: {} });\n }\n if (chunk.model) {\n state.model = chunk.model;\n }\n\n const choice = chunk.choices[0];\n if (choice) {\n if (choice.delta.content) {\n state.text += choice.delta.content;\n events.push({\n type: StreamEventType.TextDelta,\n index: 0,\n delta: { text: choice.delta.content },\n });\n }\n\n if (choice.delta.reasoning) {\n state.reasoning += choice.delta.reasoning;\n events.push({\n type: StreamEventType.ReasoningDelta,\n index: 0,\n delta: { text: choice.delta.reasoning },\n });\n }\n\n if (choice.delta.tool_calls) {\n for (const toolCallDelta of choice.delta.tool_calls) {\n const index = toolCallDelta.index;\n let toolCall = state.toolCalls.get(index);\n\n if (!toolCall) {\n toolCall = { id: '', name: '', arguments: '' };\n state.toolCalls.set(index, toolCall);\n }\n\n if (toolCallDelta.id) {\n toolCall.id = toolCallDelta.id;\n }\n if (toolCallDelta.function?.name) {\n toolCall.name = toolCallDelta.function.name;\n }\n if (toolCallDelta.function?.arguments) {\n toolCall.arguments += toolCallDelta.function.arguments;\n events.push({\n type: StreamEventType.ToolCallDelta,\n index: index,\n delta: {\n toolCallId: toolCall.id,\n toolName: toolCall.name,\n argumentsJson: toolCallDelta.function.arguments,\n },\n });\n }\n }\n }\n\n if (choice.finish_reason) {\n state.finishReason = choice.finish_reason;\n events.push({ type: StreamEventType.MessageStop, index: 0, delta: {} });\n }\n }\n\n if (chunk.usage) {\n state.inputTokens = chunk.usage.prompt_tokens;\n state.outputTokens = chunk.usage.completion_tokens;\n state.cacheReadTokens = chunk.usage.prompt_tokens_details?.cached_tokens ?? 0;\n }\n\n if (chunk.time_info) {\n state.timeInfo = chunk.time_info;\n }\n\n return events;\n}\n\n/**\n * Builds a complete LLMResponse from accumulated streaming state.\n */\nexport function buildResponseFromState(state: CerebrasStreamState): LLMResponse {\n const textContent: TextBlock[] = [];\n let structuredData: unknown;\n if (state.text) {\n textContent.push({ type: 'text', text: state.text });\n try {\n structuredData = JSON.parse(state.text);\n } catch {\n // Not JSON - expected for non-structured responses\n }\n }\n\n const toolCalls: ToolCall[] = [];\n for (const [, toolCall] of state.toolCalls) {\n let args: Record<string, unknown> = {};\n if (toolCall.arguments) {\n try {\n args = JSON.parse(toolCall.arguments);\n } catch {\n // Invalid JSON - use empty object\n }\n }\n toolCalls.push({\n toolCallId: toolCall.id,\n toolName: toolCall.name,\n arguments: args,\n });\n }\n\n const messageId = state.id || generateId();\n const message = new AssistantMessage(\n textContent,\n toolCalls.length > 0 ? toolCalls : undefined,\n {\n id: messageId,\n metadata: {\n cerebras: {\n model: state.model,\n finish_reason: state.finishReason,\n reasoning: state.reasoning || undefined,\n time_info: state.timeInfo,\n },\n },\n }\n );\n\n const usage: TokenUsage = {\n inputTokens: state.inputTokens,\n outputTokens: state.outputTokens,\n totalTokens: state.inputTokens + state.outputTokens,\n cacheReadTokens: state.cacheReadTokens,\n cacheWriteTokens: 0,\n };\n\n let stopReason = 'end_turn';\n switch (state.finishReason) {\n case 'stop':\n stopReason = 'end_turn';\n break;\n case 'length':\n stopReason = 'max_tokens';\n break;\n case 'tool_calls':\n stopReason = 'tool_use';\n break;\n case 'content_filter':\n stopReason = 'content_filter';\n break;\n }\n\n return {\n message,\n usage,\n stopReason,\n data: structuredData,\n };\n}\n","/**\n * @fileoverview Cerebras Chat Completions API Handler\n *\n * This module implements the LLM handler for Cerebras's Chat Completions API\n * (OpenAI-compatible at `/v1/chat/completions`).\n *\n * @see {@link https://inference-docs.cerebras.ai/introduction Cerebras API Reference}\n * @module providers/cerebras/llm\n */\n\nimport type { BoundLLMModel, LLMRequest, LLMResponse, LLMStreamResult, LLMCapabilities } from '../../types/llm.ts';\nimport type { LLMHandler } from '../../types/provider.ts';\nimport type { StreamEvent } from '../../types/stream.ts';\nimport { StreamEventType, objectDelta } from '../../types/stream.ts';\nimport type { LLMProvider } from '../../types/provider.ts';\nimport { UPPError, ErrorCode, ModalityType } from '../../types/errors.ts';\nimport { resolveApiKey } from '../../http/keys.ts';\nimport { doFetch, doStreamFetch } from '../../http/fetch.ts';\nimport { parseSSEStream } from '../../http/sse.ts';\nimport { normalizeHttpError } from '../../http/errors.ts';\nimport { parseJsonResponse } from '../../http/json.ts';\nimport { toError } from '../../utils/error.ts';\nimport type { CerebrasLLMParams, CerebrasResponse, CerebrasStreamChunk } from './types.ts';\nimport {\n transformRequest,\n transformResponse,\n transformStreamEvent,\n createStreamState,\n buildResponseFromState,\n} from './transform.ts';\n\n/** Base URL for Cerebras's Chat Completions API endpoint */\nconst CEREBRAS_API_URL = 'https://api.cerebras.ai/v1/chat/completions';\n\n/**\n * Capability declaration for the Cerebras Chat Completions API.\n *\n * Defines what features are supported by this handler:\n * - Streaming: Real-time token-by-token response streaming via SSE\n * - Tools: Function calling for structured interactions\n * - Structured Output: JSON schema-based response formatting\n * - Image Input: Not supported\n */\nconst CEREBRAS_CAPABILITIES: LLMCapabilities = {\n streaming: true,\n tools: true,\n structuredOutput: true,\n imageInput: false,\n documentInput: false,\n videoInput: false,\n audioInput: false,\n};\n\n/**\n * Creates an LLM handler for Cerebras's Chat Completions API.\n *\n * This factory function creates a handler that communicates with the\n * `/v1/chat/completions` endpoint. The handler supports both synchronous\n * completion requests and streaming responses.\n *\n * @returns An LLM handler configured for the Cerebras API\n *\n * @example\n * ```typescript\n * const handler = createLLMHandler();\n * const model = handler.bind('llama-3.3-70b');\n *\n * // Synchronous completion\n * const response = await model.complete({\n * messages: [{ role: 'user', content: 'Hello!' }],\n * config: { apiKey: 'csk-...' }\n * });\n *\n * // Streaming completion\n * const stream = model.stream({\n * messages: [{ role: 'user', content: 'Tell me a story' }],\n * config: { apiKey: 'csk-...' }\n * });\n *\n * for await (const event of stream) {\n * if (event.type === StreamEventType.TextDelta) {\n * process.stdout.write(event.delta.text);\n * }\n * }\n * ```\n */\nexport function createLLMHandler(): LLMHandler<CerebrasLLMParams> {\n let providerRef: LLMProvider<CerebrasLLMParams> | null = null;\n\n return {\n _setProvider(provider: LLMProvider<CerebrasLLMParams>) {\n providerRef = provider;\n },\n\n bind(modelId: string): BoundLLMModel<CerebrasLLMParams> {\n if (!providerRef) {\n throw new UPPError(\n 'Provider reference not set. Handler must be used with createProvider() or have _setProvider called.',\n ErrorCode.InvalidRequest,\n 'cerebras',\n ModalityType.LLM\n );\n }\n\n const model: BoundLLMModel<CerebrasLLMParams> = {\n modelId,\n capabilities: CEREBRAS_CAPABILITIES,\n\n get provider(): LLMProvider<CerebrasLLMParams> {\n return providerRef!;\n },\n\n async complete(request: LLMRequest<CerebrasLLMParams>): Promise<LLMResponse> {\n const apiKey = await resolveApiKey(\n request.config,\n 'CEREBRAS_API_KEY',\n 'cerebras',\n 'llm'\n );\n\n const baseUrl = request.config.baseUrl ?? CEREBRAS_API_URL;\n const body = transformRequest(request, modelId);\n\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${apiKey}`,\n };\n\n if (request.config.headers) {\n for (const [key, value] of Object.entries(request.config.headers)) {\n if (value !== undefined) {\n headers[key] = value;\n }\n }\n }\n\n const response = await doFetch(\n baseUrl,\n {\n method: 'POST',\n headers,\n body: JSON.stringify(body),\n signal: request.signal,\n },\n request.config,\n 'cerebras',\n 'llm'\n );\n\n const data = await parseJsonResponse<CerebrasResponse>(response, 'cerebras', 'llm');\n return transformResponse(data);\n },\n\n stream(request: LLMRequest<CerebrasLLMParams>): LLMStreamResult {\n const state = createStreamState();\n let responseResolve: (value: LLMResponse) => void;\n let responseReject: (error: Error) => void;\n\n const responsePromise = new Promise<LLMResponse>((resolve, reject) => {\n responseResolve = resolve;\n responseReject = reject;\n });\n\n async function* generateEvents(): AsyncGenerator<StreamEvent, void, unknown> {\n try {\n const apiKey = await resolveApiKey(\n request.config,\n 'CEREBRAS_API_KEY',\n 'cerebras',\n 'llm'\n );\n\n const baseUrl = request.config.baseUrl ?? CEREBRAS_API_URL;\n const body = transformRequest(request, modelId);\n body.stream = true;\n body.stream_options = { include_usage: true };\n\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${apiKey}`,\n Accept: 'text/event-stream',\n };\n\n if (request.config.headers) {\n for (const [key, value] of Object.entries(request.config.headers)) {\n if (value !== undefined) {\n headers[key] = value;\n }\n }\n }\n\n const response = await doStreamFetch(\n baseUrl,\n {\n method: 'POST',\n headers,\n body: JSON.stringify(body),\n signal: request.signal,\n },\n request.config,\n 'cerebras',\n 'llm'\n );\n\n if (!response.ok) {\n const error = await normalizeHttpError(response, 'cerebras', 'llm');\n responseReject(error);\n throw error;\n }\n\n if (!response.body) {\n const error = new UPPError(\n 'No response body for streaming request',\n ErrorCode.ProviderError,\n 'cerebras',\n ModalityType.LLM\n );\n responseReject(error);\n throw error;\n }\n\n for await (const data of parseSSEStream(response.body)) {\n // Skip [DONE] marker\n if (data === '[DONE]') {\n continue;\n }\n\n // Check for Cerebras error event\n if (typeof data === 'object' && data !== null) {\n const chunk = data as CerebrasStreamChunk;\n\n // Check for error in chunk\n if ('error' in chunk && chunk.error) {\n const errorData = chunk.error as { message?: string; type?: string };\n const error = new UPPError(\n errorData.message ?? 'Unknown error',\n ErrorCode.ProviderError,\n 'cerebras',\n ModalityType.LLM\n );\n responseReject(error);\n throw error;\n }\n\n const uppEvents = transformStreamEvent(chunk, state);\n for (const event of uppEvents) {\n yield event;\n // Also emit ObjectDelta for structured output - gives developers explicit hook\n if (request.structure && event.type === StreamEventType.TextDelta) {\n yield objectDelta(event.delta.text ?? '', event.index);\n }\n }\n }\n }\n\n // Build final response\n responseResolve(buildResponseFromState(state));\n } catch (error) {\n const err = toError(error);\n responseReject(err);\n throw err;\n }\n }\n\n return {\n [Symbol.asyncIterator]() {\n return generateEvents();\n },\n response: responsePromise,\n };\n },\n };\n\n return model;\n },\n };\n}\n","/**\n * @fileoverview Cerebras Provider Factory\n *\n * This module provides the main Cerebras provider implementation for the\n * OpenAI-compatible Chat Completions API. Cerebras offers extremely fast\n * inference with models like Llama, Qwen, and their reasoning models.\n *\n * @module providers/cerebras\n */\n\nimport { createProvider } from '../../core/provider.ts';\nimport { createLLMHandler } from './llm.ts';\n\n/**\n * Configuration options for the Cerebras provider.\n *\n * Currently Cerebras only supports one API endpoint (Chat Completions),\n * so no additional options are needed.\n */\nexport interface CerebrasProviderOptions {\n // Reserved for future use (e.g., if Cerebras adds multiple API modes)\n}\n\n/**\n * The Cerebras provider instance.\n *\n * Use this provider to create model references for Cerebras models like\n * Llama 3.3, Qwen 3, GPT-OSS (reasoning), and other models available on Cerebras.\n *\n * @example Basic usage\n * ```typescript\n * import { cerebras } from './providers/cerebras';\n * import { llm } from './core/llm';\n *\n * const model = llm({\n * model: cerebras('llama-3.3-70b'),\n * params: { max_completion_tokens: 1000 }\n * });\n *\n * const turn = await model.generate('Hello!');\n * console.log(turn.response.text);\n * ```\n *\n * @example With streaming\n * ```typescript\n * const stream = model.stream('Tell me a story');\n *\n * for await (const event of stream) {\n * if (event.type === StreamEventType.TextDelta) {\n * process.stdout.write(event.delta.text ?? '');\n * }\n * }\n *\n * const turn = await stream.turn;\n * console.log('Tokens used:', turn.usage.totalTokens);\n * ```\n *\n * @example With tools\n * ```typescript\n * const calculator = {\n * name: 'calculate',\n * description: 'Calculate a math expression',\n * parameters: {\n * type: 'object',\n * properties: {\n * expression: { type: 'string' }\n * },\n * required: ['expression']\n * },\n * run: async (params: { expression: string }) => {\n * return eval(params.expression);\n * }\n * };\n *\n * const model = llm({\n * model: cerebras('llama-3.3-70b'),\n * tools: [calculator]\n * });\n *\n * const turn = await model.generate('What is 15 + 27?');\n * ```\n *\n * @example With reasoning\n * ```typescript\n * const model = llm({\n * model: cerebras('gpt-oss-120b'),\n * params: {\n * reasoning_effort: 'high',\n * reasoning_format: 'parsed'\n * }\n * });\n *\n * const turn = await model.generate('Solve this complex math problem...');\n * // Reasoning is available in turn.response.metadata.cerebras.reasoning\n * ```\n *\n * @example Available models\n * Production models:\n * - `llama3.1-8b` - Fast Llama 3.1 8B model (~2200 tok/s)\n * - `llama-3.3-70b` - Llama 3.3 70B with tool use (~2100 tok/s)\n * - `qwen-3-32b` - Qwen 3 32B with reasoning support (~2600 tok/s)\n * - `qwen-3-235b-a22b-instruct-2507` - Large Qwen model (~1400 tok/s)\n * - `gpt-oss-120b` - Reasoning model with high performance (~3000 tok/s)\n * - `zai-glm-4.6` - Z.ai GLM model with reasoning (~1000 tok/s)\n * - `zai-glm-4.7` - Z.ai GLM model with reasoning (~1000 tok/s)\n */\nexport const cerebras = createProvider<CerebrasProviderOptions>({\n name: 'cerebras',\n version: '1.0.0',\n handlers: {\n llm: createLLMHandler(),\n },\n});\n\nexport type {\n CerebrasLLMParams,\n CerebrasHeaders,\n CerebrasResponseFormat,\n CerebrasMessage,\n CerebrasRequest,\n CerebrasResponse,\n CerebrasStreamChunk,\n CerebrasTool,\n CerebrasToolCall,\n CerebrasToolChoice,\n CerebrasUsage,\n CerebrasTimeInfo,\n} from './types.ts';\n"],"mappings":"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","names":[]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
runSubscriberStream
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-EPB3GQNL.js";
|
|
4
4
|
|
|
5
5
|
// src/middleware/pubsub/server/webapi.ts
|
|
6
6
|
function createSubscriberStream(streamId, adapter) {
|
|
@@ -46,4 +46,4 @@ export {
|
|
|
46
46
|
createSubscriberStream,
|
|
47
47
|
webapi
|
|
48
48
|
};
|
|
49
|
-
//# sourceMappingURL=chunk-
|
|
49
|
+
//# sourceMappingURL=chunk-2YXFLRQ6.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/middleware/pubsub/server/webapi.ts"],"sourcesContent":["/**\n * @fileoverview Web API adapter for pub-sub stream resumption.\n *\n * Provides utilities for Web API native frameworks (Bun, Deno, Next.js App Router,\n * Cloudflare Workers) to handle stream reconnections.\n *\n * @module middleware/pubsub/server/webapi\n */\n\nimport type { PubSubAdapter } from '../types.ts';\nimport { runSubscriberStream } from './shared.ts';\n\n/**\n * Creates a ReadableStream that replays buffered events and subscribes to live events.\n *\n * Handles reconnection for Web API frameworks (Bun, Deno, Next.js, Cloudflare Workers):\n * 1. Replays buffered events from the adapter\n * 2. Subscribes to live events until completion signal\n * 3. Closes when stream completes or client disconnects\n *\n * @param streamId - The stream ID to subscribe to\n * @param adapter - The pub-sub adapter instance\n * @returns A ReadableStream of SSE-formatted data\n *\n * @example\n * ```typescript\n * import { llm } from '@providerprotocol/ai';\n * import { anthropic } from '@providerprotocol/ai/anthropic';\n * import { pubsubMiddleware, memoryAdapter } from '@providerprotocol/ai/middleware/pubsub';\n * import { webapi } from '@providerprotocol/ai/middleware/pubsub/server';\n *\n * const adapter = memoryAdapter();\n *\n * // Next.js App Router / Bun.serve / Deno.serve\n * export async function POST(req: Request) {\n * const { input, conversationId } = await req.json();\n *\n * if (!await adapter.exists(conversationId)) {\n * const model = llm({\n * model: anthropic('claude-sonnet-4-20250514'),\n * middleware: [pubsubMiddleware({ adapter, streamId: conversationId })],\n * });\n * model.stream(input).then(turn => saveToDatabase(conversationId, turn));\n * }\n *\n * return new Response(webapi.createSubscriberStream(conversationId, adapter), {\n * headers: {\n * 'Content-Type': 'text/event-stream',\n * 'Cache-Control': 'no-cache',\n * },\n * });\n * }\n * ```\n */\nexport function createSubscriberStream(\n streamId: string,\n adapter: PubSubAdapter\n): ReadableStream<Uint8Array> {\n const encoder = new TextEncoder();\n const abortController = new AbortController();\n let closed = false;\n\n return new ReadableStream({\n async start(controller) {\n await runSubscriberStream(\n streamId,\n adapter,\n {\n write: (data: string) => {\n if (closed) {\n return;\n }\n controller.enqueue(encoder.encode(data));\n },\n end: () => {\n if (closed) {\n return;\n }\n closed = true;\n try {\n controller.close();\n } catch {\n // Ignore close errors after cancellation\n }\n },\n },\n { signal: abortController.signal }\n );\n },\n cancel() {\n abortController.abort();\n },\n });\n}\n\n/**\n * Web API adapter namespace for pub-sub server utilities.\n */\nexport const webapi = {\n createSubscriberStream,\n};\n"],"mappings":";;;;;AAsDO,SAAS,uBACd,UACA,SAC4B;AAC5B,QAAM,UAAU,IAAI,YAAY;AAChC,QAAM,kBAAkB,IAAI,gBAAgB;AAC5C,MAAI,SAAS;AAEb,SAAO,IAAI,eAAe;AAAA,IACxB,MAAM,MAAM,YAAY;AACtB,YAAM;AAAA,QACJ;AAAA,QACA;AAAA,QACA;AAAA,UACE,OAAO,CAAC,SAAiB;AACvB,gBAAI,QAAQ;AACV;AAAA,YACF;AACA,uBAAW,QAAQ,QAAQ,OAAO,IAAI,CAAC;AAAA,UACzC;AAAA,UACA,KAAK,MAAM;AACT,gBAAI,QAAQ;AACV;AAAA,YACF;AACA,qBAAS;AACT,gBAAI;AACF,yBAAW,MAAM;AAAA,YACnB,QAAQ;AAAA,YAER;AAAA,UACF;AAAA,QACF;AAAA,QACA,EAAE,QAAQ,gBAAgB,OAAO;AAAA,MACnC;AAAA,IACF;AAAA,IACA,SAAS;AACP,sBAAgB,MAAM;AAAA,IACxB;AAAA,EACF,CAAC;AACH;AAKO,IAAM,SAAS;AAAA,EACpB;AACF;","names":[]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
runSubscriberStream
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-EPB3GQNL.js";
|
|
4
4
|
|
|
5
5
|
// src/middleware/pubsub/server/h3.ts
|
|
6
6
|
async function streamSubscriber(streamId, adapter, event) {
|
|
@@ -28,4 +28,4 @@ export {
|
|
|
28
28
|
streamSubscriber,
|
|
29
29
|
h3
|
|
30
30
|
};
|
|
31
|
-
//# sourceMappingURL=chunk-
|
|
31
|
+
//# sourceMappingURL=chunk-4RX4VQCB.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/middleware/pubsub/server/h3.ts"],"sourcesContent":["/**\n * @fileoverview H3/Nitro/Nuxt adapter for pub-sub stream resumption.\n *\n * Provides utilities for H3-based servers (Nuxt, Nitro, or standalone H3)\n * to handle stream reconnections.\n *\n * @module middleware/pubsub/server/h3\n */\n\nimport type { PubSubAdapter } from '../types.ts';\nimport { runSubscriberStream } from './shared.ts';\n\n/**\n * H3 Event interface (minimal type to avoid dependency).\n */\ninterface H3Event {\n node: {\n res: {\n setHeader(name: string, value: string): void;\n write(chunk: string): boolean;\n end(): void;\n on(event: 'close', listener: () => void): void;\n };\n };\n}\n\n/**\n * Stream buffered and live events to an H3 event response.\n *\n * Handles reconnection for H3/Nuxt routes:\n * 1. Replays buffered events from the adapter\n * 2. Subscribes to live events until completion signal\n * 3. Ends when stream completes or client disconnects\n *\n * @param streamId - The stream ID to subscribe to\n * @param adapter - The pub-sub adapter instance\n * @param event - H3 event object\n *\n * @example\n * ```typescript\n * import { llm } from '@providerprotocol/ai';\n * import { anthropic } from '@providerprotocol/ai/anthropic';\n * import { pubsubMiddleware, memoryAdapter } from '@providerprotocol/ai/middleware/pubsub';\n * import { h3 } from '@providerprotocol/ai/middleware/pubsub/server';\n *\n * const adapter = memoryAdapter();\n *\n * export default defineEventHandler(async (event) => {\n * const { input, conversationId } = await readBody(event);\n *\n * if (!await adapter.exists(conversationId)) {\n * const model = llm({\n * model: anthropic('claude-sonnet-4-20250514'),\n * middleware: [pubsubMiddleware({ adapter, streamId: conversationId })],\n * });\n * model.stream(input).then(turn => saveToDatabase(conversationId, turn));\n * }\n *\n * return h3.streamSubscriber(conversationId, adapter, event);\n * });\n * ```\n */\nexport async function streamSubscriber(\n streamId: string,\n adapter: PubSubAdapter,\n event: H3Event\n): Promise<void> {\n const res = event.node.res;\n res.setHeader('Content-Type', 'text/event-stream');\n res.setHeader('Cache-Control', 'no-cache');\n res.setHeader('Connection', 'keep-alive');\n\n const abortController = new AbortController();\n res.on('close', () => abortController.abort());\n\n await runSubscriberStream(\n streamId,\n adapter,\n {\n write: (data: string) => res.write(data),\n end: () => res.end(),\n },\n { signal: abortController.signal }\n );\n}\n\n/**\n * H3 adapter namespace for pub-sub server utilities.\n */\nexport const h3 = {\n streamSubscriber,\n};\n"],"mappings":";;;;;AA8DA,eAAsB,iBACpB,UACA,SACA,OACe;AACf,QAAM,MAAM,MAAM,KAAK;AACvB,MAAI,UAAU,gBAAgB,mBAAmB;AACjD,MAAI,UAAU,iBAAiB,UAAU;AACzC,MAAI,UAAU,cAAc,YAAY;AAExC,QAAM,kBAAkB,IAAI,gBAAgB;AAC5C,MAAI,GAAG,SAAS,MAAM,gBAAgB,MAAM,CAAC;AAE7C,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,MACE,OAAO,CAAC,SAAiB,IAAI,MAAM,IAAI;AAAA,MACvC,KAAK,MAAM,IAAI,IAAI;AAAA,IACrB;AAAA,IACA,EAAE,QAAQ,gBAAgB,OAAO;AAAA,EACnC;AACF;AAKO,IAAM,KAAK;AAAA,EAChB;AACF;","names":[]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
runSubscriberStream
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-EPB3GQNL.js";
|
|
4
4
|
|
|
5
5
|
// src/middleware/pubsub/server/express.ts
|
|
6
6
|
async function streamSubscriber(streamId, adapter, res) {
|
|
@@ -27,4 +27,4 @@ export {
|
|
|
27
27
|
streamSubscriber,
|
|
28
28
|
express
|
|
29
29
|
};
|
|
30
|
-
//# sourceMappingURL=chunk-
|
|
30
|
+
//# sourceMappingURL=chunk-5IWHCXKN.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/middleware/pubsub/server/express.ts"],"sourcesContent":["/**\n * @fileoverview Express/Connect adapter for pub-sub stream resumption.\n *\n * Provides utilities for Express.js or Connect-based servers\n * to handle stream reconnections.\n *\n * @module middleware/pubsub/server/express\n */\n\nimport type { PubSubAdapter } from '../types.ts';\nimport { runSubscriberStream } from './shared.ts';\n\n/**\n * Express Response interface (minimal type to avoid dependency).\n */\ninterface ExpressResponse {\n setHeader(name: string, value: string): void;\n write(chunk: string): boolean;\n end(): void;\n on(event: 'close', listener: () => void): void;\n}\n\n/**\n * Stream buffered and live events to an Express response.\n *\n * Handles reconnection for Express routes:\n * 1. Replays buffered events from the adapter\n * 2. Subscribes to live events until completion signal\n * 3. Ends when stream completes or client disconnects\n *\n * @param streamId - The stream ID to subscribe to\n * @param adapter - The pub-sub adapter instance\n * @param res - Express response object\n *\n * @example\n * ```typescript\n * import { llm } from '@providerprotocol/ai';\n * import { anthropic } from '@providerprotocol/ai/anthropic';\n * import { pubsubMiddleware, memoryAdapter } from '@providerprotocol/ai/middleware/pubsub';\n * import { express } from '@providerprotocol/ai/middleware/pubsub/server';\n *\n * const adapter = memoryAdapter();\n *\n * app.post('/api/chat', async (req, res) => {\n * const { input, conversationId } = req.body;\n *\n * if (!await adapter.exists(conversationId)) {\n * const model = llm({\n * model: anthropic('claude-sonnet-4-20250514'),\n * middleware: [pubsubMiddleware({ adapter, streamId: conversationId })],\n * });\n * model.stream(input).then(turn => saveToDatabase(conversationId, turn));\n * }\n *\n * return express.streamSubscriber(conversationId, adapter, res);\n * });\n * ```\n */\nexport async function streamSubscriber(\n streamId: string,\n adapter: PubSubAdapter,\n res: ExpressResponse\n): Promise<void> {\n res.setHeader('Content-Type', 'text/event-stream');\n res.setHeader('Cache-Control', 'no-cache');\n res.setHeader('Connection', 'keep-alive');\n\n const abortController = new AbortController();\n res.on('close', () => abortController.abort());\n\n await runSubscriberStream(\n streamId,\n adapter,\n {\n write: (data: string) => res.write(data),\n end: () => res.end(),\n },\n { signal: abortController.signal }\n );\n}\n\n/**\n * Express adapter namespace for pub-sub server utilities.\n */\nexport const express = {\n streamSubscriber,\n};\n"],"mappings":";;;;;AA0DA,eAAsB,iBACpB,UACA,SACA,KACe;AACf,MAAI,UAAU,gBAAgB,mBAAmB;AACjD,MAAI,UAAU,iBAAiB,UAAU;AACzC,MAAI,UAAU,cAAc,YAAY;AAExC,QAAM,kBAAkB,IAAI,gBAAgB;AAC5C,MAAI,GAAG,SAAS,MAAM,gBAAgB,MAAM,CAAC;AAE7C,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,MACE,OAAO,CAAC,SAAiB,IAAI,MAAM,IAAI;AAAA,MACvC,KAAK,MAAM,IAAI,IAAI;AAAA,IACrB;AAAA,IACA,EAAE,QAAQ,gBAAgB,OAAO;AAAA,EACnC;AACF;AAKO,IAAM,UAAU;AAAA,EACrB;AACF;","names":[]}
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
serializeImageStreamEvent,
|
|
5
5
|
serializeStreamEvent,
|
|
6
6
|
serializeTurn
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-YQLR3XOA.js";
|
|
8
8
|
|
|
9
9
|
// src/providers/proxy/server/fastify.ts
|
|
10
10
|
function sendJSON(turn, reply) {
|
|
@@ -91,4 +91,4 @@ export {
|
|
|
91
91
|
sendError,
|
|
92
92
|
fastify
|
|
93
93
|
};
|
|
94
|
-
//# sourceMappingURL=chunk-
|
|
94
|
+
//# sourceMappingURL=chunk-7GTWHZY2.js.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
runSubscriberStream
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-EPB3GQNL.js";
|
|
4
4
|
|
|
5
5
|
// src/middleware/pubsub/server/fastify.ts
|
|
6
6
|
async function streamSubscriber(streamId, adapter, reply) {
|
|
@@ -28,4 +28,4 @@ export {
|
|
|
28
28
|
streamSubscriber,
|
|
29
29
|
fastify
|
|
30
30
|
};
|
|
31
|
-
//# sourceMappingURL=chunk-
|
|
31
|
+
//# sourceMappingURL=chunk-CRP6Y7NF.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/middleware/pubsub/server/fastify.ts"],"sourcesContent":["/**\n * @fileoverview Fastify adapter for pub-sub stream resumption.\n *\n * Provides utilities for Fastify servers to handle stream reconnections.\n *\n * @module middleware/pubsub/server/fastify\n */\n\nimport type { PubSubAdapter } from '../types.ts';\nimport { runSubscriberStream } from './shared.ts';\n\n/**\n * Fastify Reply interface (minimal type to avoid dependency).\n */\ninterface FastifyReply {\n raw: {\n setHeader(name: string, value: string): void;\n write(chunk: string): boolean;\n end(): void;\n on(event: 'close', listener: () => void): void;\n };\n}\n\n/**\n * Stream buffered and live events to a Fastify reply.\n *\n * Handles reconnection for Fastify routes:\n * 1. Replays buffered events from the adapter\n * 2. Subscribes to live events until completion signal\n * 3. Ends when stream completes or client disconnects\n *\n * @param streamId - The stream ID to subscribe to\n * @param adapter - The pub-sub adapter instance\n * @param reply - Fastify reply object\n *\n * @example\n * ```typescript\n * import { llm } from '@providerprotocol/ai';\n * import { anthropic } from '@providerprotocol/ai/anthropic';\n * import { pubsubMiddleware, memoryAdapter } from '@providerprotocol/ai/middleware/pubsub';\n * import { fastify as pubsubFastify } from '@providerprotocol/ai/middleware/pubsub/server';\n *\n * const adapter = memoryAdapter();\n *\n * app.post('/api/chat', async (request, reply) => {\n * const { input, conversationId } = request.body as { input: string; conversationId: string };\n *\n * if (!await adapter.exists(conversationId)) {\n * const model = llm({\n * model: anthropic('claude-sonnet-4-20250514'),\n * middleware: [pubsubMiddleware({ adapter, streamId: conversationId })],\n * });\n * model.stream(input).then(turn => saveToDatabase(conversationId, turn));\n * }\n *\n * return pubsubFastify.streamSubscriber(conversationId, adapter, reply);\n * });\n * ```\n */\nexport async function streamSubscriber(\n streamId: string,\n adapter: PubSubAdapter,\n reply: FastifyReply\n): Promise<void> {\n const res = reply.raw;\n res.setHeader('Content-Type', 'text/event-stream');\n res.setHeader('Cache-Control', 'no-cache');\n res.setHeader('Connection', 'keep-alive');\n\n const abortController = new AbortController();\n res.on('close', () => abortController.abort());\n\n await runSubscriberStream(\n streamId,\n adapter,\n {\n write: (data: string) => res.write(data),\n end: () => res.end(),\n },\n { signal: abortController.signal }\n );\n}\n\n/**\n * Fastify adapter namespace for pub-sub server utilities.\n */\nexport const fastify = {\n streamSubscriber,\n};\n"],"mappings":";;;;;AA2DA,eAAsB,iBACpB,UACA,SACA,OACe;AACf,QAAM,MAAM,MAAM;AAClB,MAAI,UAAU,gBAAgB,mBAAmB;AACjD,MAAI,UAAU,iBAAiB,UAAU;AACzC,MAAI,UAAU,cAAc,YAAY;AAExC,QAAM,kBAAkB,IAAI,gBAAgB;AAC5C,MAAI,GAAG,SAAS,MAAM,gBAAgB,MAAM,CAAC;AAE7C,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,MACE,OAAO,CAAC,SAAiB,IAAI,MAAM,IAAI;AAAA,MACvC,KAAK,MAAM,IAAI,IAAI;AAAA,IACrB;AAAA,IACA,EAAE,QAAQ,gBAAgB,OAAO;AAAA,EACnC;AACF;AAKO,IAAM,UAAU;AAAA,EACrB;AACF;","names":[]}
|
|
@@ -3,66 +3,47 @@ import {
|
|
|
3
3
|
} from "./chunk-ETBFOLQN.js";
|
|
4
4
|
|
|
5
5
|
// src/middleware/pubsub/server/shared.ts
|
|
6
|
-
var DEFAULT_CREATION_TIMEOUT = 5e3;
|
|
7
|
-
var CREATION_POLL_INTERVAL = 50;
|
|
8
6
|
function formatSSE(event) {
|
|
9
7
|
const serialized = serializeStreamEvent(event);
|
|
10
8
|
return `data: ${JSON.stringify(serialized)}
|
|
11
9
|
|
|
12
10
|
`;
|
|
13
11
|
}
|
|
14
|
-
async function waitForStream(streamId, adapter, timeout, signal) {
|
|
15
|
-
const deadline = Date.now() + timeout;
|
|
16
|
-
while (Date.now() < deadline) {
|
|
17
|
-
if (signal?.aborted) return false;
|
|
18
|
-
const exists = await adapter.exists(streamId);
|
|
19
|
-
if (exists) return true;
|
|
20
|
-
await new Promise((resolve) => setTimeout(resolve, CREATION_POLL_INTERVAL));
|
|
21
|
-
}
|
|
22
|
-
return false;
|
|
23
|
-
}
|
|
24
12
|
async function runSubscriberStream(streamId, adapter, writer, options = {}) {
|
|
25
|
-
const { signal
|
|
13
|
+
const { signal } = options;
|
|
26
14
|
if (signal?.aborted) {
|
|
27
15
|
writer.end();
|
|
28
16
|
return;
|
|
29
17
|
}
|
|
30
18
|
try {
|
|
31
|
-
const streamExists = await waitForStream(streamId, adapter, creationTimeout, signal);
|
|
32
19
|
if (signal?.aborted) {
|
|
33
20
|
writer.end();
|
|
34
21
|
return;
|
|
35
22
|
}
|
|
36
|
-
if (!streamExists) {
|
|
37
|
-
writer.write(`data: ${JSON.stringify({ error: "Stream not found" })}
|
|
38
|
-
|
|
39
|
-
`);
|
|
40
|
-
writer.end();
|
|
41
|
-
return;
|
|
42
|
-
}
|
|
43
23
|
const queue = [];
|
|
44
24
|
let resolveWait = null;
|
|
45
|
-
let
|
|
25
|
+
let completed = false;
|
|
46
26
|
let lastSentCursor = -1;
|
|
47
|
-
const
|
|
27
|
+
const onEvent = (event, cursor) => {
|
|
48
28
|
queue.push({ event, cursor: cursor ?? null });
|
|
49
29
|
resolveWait?.();
|
|
50
|
-
}
|
|
30
|
+
};
|
|
31
|
+
const onComplete = () => {
|
|
32
|
+
completed = true;
|
|
33
|
+
resolveWait?.();
|
|
34
|
+
};
|
|
35
|
+
const unsubscribe = adapter.subscribe(streamId, onEvent, onComplete);
|
|
51
36
|
const onAbort = () => {
|
|
52
|
-
|
|
37
|
+
completed = true;
|
|
53
38
|
resolveWait?.();
|
|
54
39
|
};
|
|
55
40
|
signal?.addEventListener("abort", onAbort);
|
|
56
41
|
const drainQueue = () => {
|
|
57
42
|
while (queue.length > 0 && !signal?.aborted) {
|
|
58
43
|
const item = queue.shift();
|
|
59
|
-
if (!item)
|
|
60
|
-
break;
|
|
61
|
-
}
|
|
44
|
+
if (!item) break;
|
|
62
45
|
const { event, cursor } = item;
|
|
63
|
-
if (cursor !== null && cursor <= lastSentCursor)
|
|
64
|
-
continue;
|
|
65
|
-
}
|
|
46
|
+
if (cursor !== null && cursor <= lastSentCursor) continue;
|
|
66
47
|
writer.write(formatSSE(event));
|
|
67
48
|
if (cursor !== null && cursor > lastSentCursor) {
|
|
68
49
|
lastSentCursor = cursor;
|
|
@@ -70,32 +51,30 @@ async function runSubscriberStream(streamId, adapter, writer, options = {}) {
|
|
|
70
51
|
}
|
|
71
52
|
};
|
|
72
53
|
const dropReplayDuplicates = () => {
|
|
73
|
-
if (queue.length === 0)
|
|
74
|
-
return;
|
|
75
|
-
}
|
|
54
|
+
if (queue.length === 0) return;
|
|
76
55
|
const filtered = [];
|
|
77
56
|
for (const item of queue) {
|
|
78
|
-
if (item.cursor !== null && item.cursor <= lastSentCursor)
|
|
79
|
-
continue;
|
|
80
|
-
}
|
|
57
|
+
if (item.cursor !== null && item.cursor <= lastSentCursor) continue;
|
|
81
58
|
filtered.push(item);
|
|
82
59
|
}
|
|
83
60
|
queue.length = 0;
|
|
84
61
|
queue.push(...filtered);
|
|
85
62
|
};
|
|
86
|
-
const
|
|
87
|
-
|
|
88
|
-
|
|
63
|
+
const waitForSignal = () => new Promise((resolve) => {
|
|
64
|
+
let settled = false;
|
|
65
|
+
const settle = () => {
|
|
66
|
+
if (settled) return;
|
|
67
|
+
settled = true;
|
|
68
|
+
resolveWait = null;
|
|
69
|
+
resolve();
|
|
70
|
+
};
|
|
71
|
+
resolveWait = settle;
|
|
72
|
+
if (completed || signal?.aborted || queue.length > 0) {
|
|
73
|
+
settle();
|
|
74
|
+
}
|
|
89
75
|
});
|
|
90
76
|
try {
|
|
91
77
|
const events = await adapter.getEvents(streamId);
|
|
92
|
-
if (!events) {
|
|
93
|
-
writer.write(`data: ${JSON.stringify({ error: "Stream not found" })}
|
|
94
|
-
|
|
95
|
-
`);
|
|
96
|
-
writer.end();
|
|
97
|
-
return;
|
|
98
|
-
}
|
|
99
78
|
for (const event of events) {
|
|
100
79
|
if (signal?.aborted) break;
|
|
101
80
|
writer.write(formatSSE(event));
|
|
@@ -106,24 +85,10 @@ async function runSubscriberStream(streamId, adapter, writer, options = {}) {
|
|
|
106
85
|
writer.end();
|
|
107
86
|
return;
|
|
108
87
|
}
|
|
109
|
-
|
|
110
|
-
if (completed) {
|
|
88
|
+
while (!completed && !signal?.aborted) {
|
|
111
89
|
drainQueue();
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
return;
|
|
115
|
-
}
|
|
116
|
-
while (!done) {
|
|
117
|
-
if (signal?.aborted) break;
|
|
118
|
-
drainQueue();
|
|
119
|
-
if (signal?.aborted) break;
|
|
120
|
-
const isComplete = await adapter.isCompleted(streamId).catch(() => false);
|
|
121
|
-
if (isComplete) {
|
|
122
|
-
done = true;
|
|
123
|
-
break;
|
|
124
|
-
}
|
|
125
|
-
await waitForNewEvents();
|
|
126
|
-
resolveWait = null;
|
|
90
|
+
if (completed || signal?.aborted) break;
|
|
91
|
+
await waitForSignal();
|
|
127
92
|
}
|
|
128
93
|
if (!signal?.aborted) {
|
|
129
94
|
drainQueue();
|
|
@@ -150,4 +115,4 @@ async function runSubscriberStream(streamId, adapter, writer, options = {}) {
|
|
|
150
115
|
export {
|
|
151
116
|
runSubscriberStream
|
|
152
117
|
};
|
|
153
|
-
//# sourceMappingURL=chunk-
|
|
118
|
+
//# sourceMappingURL=chunk-EPB3GQNL.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/middleware/pubsub/server/shared.ts"],"sourcesContent":["/**\n * @fileoverview Shared utilities for pub-sub server adapters.\n *\n * @module middleware/pubsub/server/shared\n * @internal\n */\n\nimport type { StreamEvent } from '../../../types/stream.ts';\nimport type { PubSubAdapter } from '../types.ts';\nimport { serializeStreamEvent } from '../../../stream/serialization.ts';\n\n/**\n * Writer interface for abstracting how data is written to responses.\n * @internal\n */\nexport interface StreamWriter {\n write(data: string): void;\n end(): void;\n}\n\n/**\n * Options for runSubscriberStream.\n * @internal\n */\nexport interface StreamOptions {\n signal?: AbortSignal;\n}\n\n/**\n * Formats a stream event as an SSE data line.\n */\nexport function formatSSE(event: StreamEvent): string {\n const serialized = serializeStreamEvent(event);\n return `data: ${JSON.stringify(serialized)}\\n\\n`;\n}\n\n/**\n * Core subscriber stream logic shared across all adapters.\n *\n * Handles:\n * 1. Subscribing to live events and completion signal\n * 2. Replaying buffered events (empty if stream just started)\n * 3. Processing live events until completion signal\n * 4. Final cleanup\n * 5. Client disconnect via AbortSignal\n *\n * @internal\n */\nexport async function runSubscriberStream(\n streamId: string,\n adapter: PubSubAdapter,\n writer: StreamWriter,\n options: StreamOptions = {}\n): Promise<void> {\n const { signal } = options;\n\n if (signal?.aborted) {\n writer.end();\n return;\n }\n\n try {\n if (signal?.aborted) {\n writer.end();\n return;\n }\n\n const queue: Array<{ event: StreamEvent; cursor: number | null }> = [];\n let resolveWait: (() => void) | null = null;\n let completed = false;\n let lastSentCursor = -1;\n\n const onEvent = (event: StreamEvent, cursor?: number): void => {\n queue.push({ event, cursor: cursor ?? null });\n resolveWait?.();\n };\n\n const onComplete = (): void => {\n completed = true;\n resolveWait?.();\n };\n\n const unsubscribe = adapter.subscribe(streamId, onEvent, onComplete);\n\n const onAbort = (): void => {\n completed = true;\n resolveWait?.();\n };\n signal?.addEventListener('abort', onAbort);\n\n const drainQueue = (): void => {\n while (queue.length > 0 && !signal?.aborted) {\n const item = queue.shift();\n if (!item) break;\n const { event, cursor } = item;\n if (cursor !== null && cursor <= lastSentCursor) continue;\n writer.write(formatSSE(event));\n if (cursor !== null && cursor > lastSentCursor) {\n lastSentCursor = cursor;\n }\n }\n };\n\n const dropReplayDuplicates = (): void => {\n if (queue.length === 0) return;\n const filtered: Array<{ event: StreamEvent; cursor: number | null }> = [];\n for (const item of queue) {\n if (item.cursor !== null && item.cursor <= lastSentCursor) continue;\n filtered.push(item);\n }\n queue.length = 0;\n queue.push(...filtered);\n };\n\n const waitForSignal = (): Promise<void> => new Promise((resolve) => {\n let settled = false;\n\n const settle = (): void => {\n if (settled) return;\n settled = true;\n resolveWait = null;\n resolve();\n };\n\n resolveWait = settle;\n\n if (completed || signal?.aborted || queue.length > 0) {\n settle();\n }\n });\n\n try {\n const events = await adapter.getEvents(streamId);\n\n for (const event of events) {\n if (signal?.aborted) break;\n writer.write(formatSSE(event));\n }\n\n lastSentCursor = events.length - 1;\n dropReplayDuplicates();\n\n if (signal?.aborted) {\n writer.end();\n return;\n }\n\n // Wait for events or completion signal\n while (!completed && !signal?.aborted) {\n drainQueue();\n if (completed || signal?.aborted) break;\n await waitForSignal();\n }\n\n if (!signal?.aborted) {\n drainQueue();\n }\n } finally {\n signal?.removeEventListener('abort', onAbort);\n unsubscribe();\n }\n\n if (!signal?.aborted) {\n writer.write('data: [DONE]\\n\\n');\n }\n writer.end();\n } catch (error) {\n if (!signal?.aborted) {\n const errorMsg = error instanceof Error ? error.message : String(error);\n writer.write(`data: ${JSON.stringify({ error: errorMsg })}\\n\\n`);\n }\n writer.end();\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
serializeImageStreamEvent,
|
|
5
5
|
serializeStreamEvent,
|
|
6
6
|
serializeTurn
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-YQLR3XOA.js";
|
|
8
8
|
|
|
9
9
|
// src/providers/proxy/server/express.ts
|
|
10
10
|
function sendJSON(turn, res) {
|
|
@@ -94,4 +94,4 @@ export {
|
|
|
94
94
|
sendError,
|
|
95
95
|
express
|
|
96
96
|
};
|
|
97
|
-
//# sourceMappingURL=chunk-
|
|
97
|
+
//# sourceMappingURL=chunk-FYSZFIZS.js.map
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ErrorCode,
|
|
3
|
+
UPPError
|
|
4
|
+
} from "./chunk-COS4ON4G.js";
|
|
5
|
+
|
|
6
|
+
// src/utils/error.ts
|
|
7
|
+
function toError(value) {
|
|
8
|
+
if (value instanceof Error) {
|
|
9
|
+
return value;
|
|
10
|
+
}
|
|
11
|
+
if (typeof value === "string") {
|
|
12
|
+
return new Error(value);
|
|
13
|
+
}
|
|
14
|
+
if (typeof value === "object" && value !== null && "message" in value) {
|
|
15
|
+
const message = value.message;
|
|
16
|
+
if (typeof message === "string") {
|
|
17
|
+
return new Error(message);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
return new Error(String(value));
|
|
21
|
+
}
|
|
22
|
+
function isCancelledError(value) {
|
|
23
|
+
if (value instanceof UPPError) {
|
|
24
|
+
return value.code === ErrorCode.Cancelled;
|
|
25
|
+
}
|
|
26
|
+
if (value && typeof value === "object" && "name" in value) {
|
|
27
|
+
const name = value.name;
|
|
28
|
+
return name === "AbortError";
|
|
29
|
+
}
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export {
|
|
34
|
+
toError,
|
|
35
|
+
isCancelledError
|
|
36
|
+
};
|
|
37
|
+
//# sourceMappingURL=chunk-GIDT7C6I.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/utils/error.ts"],"sourcesContent":["/**\n * @fileoverview Error normalization utilities.\n *\n * @module utils/error\n */\n\nimport { ErrorCode, UPPError } from '../types/errors.ts';\n\n/**\n * Converts an unknown thrown value into an Error instance.\n *\n * @param value - Unknown error value\n * @returns An Error instance\n */\nexport function toError(value: unknown): Error {\n if (value instanceof Error) {\n return value;\n }\n if (typeof value === 'string') {\n return new Error(value);\n }\n if (typeof value === 'object' && value !== null && 'message' in value) {\n const message = (value as { message?: unknown }).message;\n if (typeof message === 'string') {\n return new Error(message);\n }\n }\n return new Error(String(value));\n}\n\n/**\n * Checks whether an error represents a cancellation.\n *\n * @param value - Unknown error value\n * @returns True if the error indicates cancellation\n */\nexport function isCancelledError(value: unknown): boolean {\n if (value instanceof UPPError) {\n return value.code === ErrorCode.Cancelled;\n }\n\n if (value && typeof value === 'object' && 'name' in value) {\n const name = (value as { name?: unknown }).name;\n return name === 'AbortError';\n }\n\n return false;\n}\n"],"mappings":";;;;;;AAcO,SAAS,QAAQ,OAAuB;AAC7C,MAAI,iBAAiB,OAAO;AAC1B,WAAO;AAAA,EACT;AACA,MAAI,OAAO,UAAU,UAAU;AAC7B,WAAO,IAAI,MAAM,KAAK;AAAA,EACxB;AACA,MAAI,OAAO,UAAU,YAAY,UAAU,QAAQ,aAAa,OAAO;AACrE,UAAM,UAAW,MAAgC;AACjD,QAAI,OAAO,YAAY,UAAU;AAC/B,aAAO,IAAI,MAAM,OAAO;AAAA,IAC1B;AAAA,EACF;AACA,SAAO,IAAI,MAAM,OAAO,KAAK,CAAC;AAChC;AAQO,SAAS,iBAAiB,OAAyB;AACxD,MAAI,iBAAiB,UAAU;AAC7B,WAAO,MAAM,SAAS,UAAU;AAAA,EAClC;AAEA,MAAI,SAAS,OAAO,UAAU,YAAY,UAAU,OAAO;AACzD,UAAM,OAAQ,MAA6B;AAC3C,WAAO,SAAS;AAAA,EAClB;AAEA,SAAO;AACT;","names":[]}
|
|
@@ -1,15 +1,15 @@
|
|
|
1
|
+
import {
|
|
2
|
+
h3
|
|
3
|
+
} from "./chunk-ZRVNAET3.js";
|
|
1
4
|
import {
|
|
2
5
|
fastify
|
|
3
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-7GTWHZY2.js";
|
|
4
7
|
import {
|
|
5
8
|
webapi
|
|
6
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-LTEMH3CI.js";
|
|
7
10
|
import {
|
|
8
11
|
express
|
|
9
|
-
} from "./chunk-
|
|
10
|
-
import {
|
|
11
|
-
h3
|
|
12
|
-
} from "./chunk-4OGB7JZA.js";
|
|
12
|
+
} from "./chunk-FYSZFIZS.js";
|
|
13
13
|
|
|
14
14
|
// src/providers/proxy/server/index.ts
|
|
15
15
|
var server = {
|
|
@@ -26,4 +26,4 @@ var server = {
|
|
|
26
26
|
export {
|
|
27
27
|
server
|
|
28
28
|
};
|
|
29
|
-
//# sourceMappingURL=chunk-
|
|
29
|
+
//# sourceMappingURL=chunk-IK6NRCW5.js.map
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
serializeImageStreamEvent,
|
|
8
8
|
serializeStreamEvent,
|
|
9
9
|
serializeTurn
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-YQLR3XOA.js";
|
|
11
11
|
|
|
12
12
|
// src/providers/proxy/server/webapi.ts
|
|
13
13
|
function parseBody(body) {
|
|
@@ -219,4 +219,4 @@ export {
|
|
|
219
219
|
bindTools,
|
|
220
220
|
webapi
|
|
221
221
|
};
|
|
222
|
-
//# sourceMappingURL=chunk-
|
|
222
|
+
//# sourceMappingURL=chunk-LTEMH3CI.js.map
|