@gitlab/gitlab-ai-provider 3.4.0 → 3.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/gitlab-anthropic-language-model.ts","../src/gitlab-direct-access.ts","../src/gitlab-error.ts","../src/gitlab-openai-language-model.ts","../src/model-mappings.ts","../src/gitlab-oauth-types.ts","../src/gitlab-oauth-manager.ts","../src/version.ts","../src/gitlab-provider.ts","../src/gitlab-project-detector.ts","../src/gitlab-project-cache.ts"],"sourcesContent":["// Main exports\nexport { createGitLab, gitlab } from './gitlab-provider';\nexport { VERSION } from './version';\nexport type {\n GitLabProvider,\n GitLabProviderSettings,\n GitLabAgenticOptions,\n} from './gitlab-provider';\n\n// Model exports\nexport { GitLabAnthropicLanguageModel } from './gitlab-anthropic-language-model';\nexport type { GitLabAnthropicConfig } from './gitlab-anthropic-language-model';\nexport { GitLabOpenAILanguageModel } from './gitlab-openai-language-model';\nexport type { GitLabOpenAIConfig } from './gitlab-openai-language-model';\n\n// Model mappings exports\nexport {\n MODEL_MAPPINGS,\n MODEL_ID_TO_ANTHROPIC_MODEL,\n getModelMapping,\n getProviderForModelId,\n getValidModelsForProvider,\n getAnthropicModelForModelId,\n getOpenAIModelForModelId,\n getOpenAIApiType,\n isResponsesApiModel,\n} from './model-mappings';\nexport type { ModelProvider, ModelMapping, OpenAIApiType } from './model-mappings';\n\n// Error exports\nexport { GitLabError } from './gitlab-error';\nexport type { GitLabErrorOptions } from './gitlab-error';\n\n// API types exports\nexport type { GitLabOAuthTokenResponse } from './gitlab-api-types';\n\n// OAuth exports\nexport { GitLabOAuthManager } from './gitlab-oauth-manager';\nexport type {\n GitLabOAuthTokens,\n OpenCodeAuth,\n OpenCodeAuthOAuth,\n OpenCodeAuthApi,\n} from './gitlab-oauth-types';\nexport {\n BUNDLED_CLIENT_ID,\n GITLAB_COM_URL,\n TOKEN_EXPIRY_SKEW_MS,\n OAUTH_SCOPES,\n} from './gitlab-oauth-types';\n\n// Project detection exports\nexport { GitLabProjectDetector } from './gitlab-project-detector';\nexport type { GitLabProjectDetectorConfig } from './gitlab-project-detector';\nexport { GitLabProjectCache } from './gitlab-project-cache';\nexport type { GitLabProject } from './gitlab-project-cache';\n\n// Direct access exports\nexport { GitLabDirectAccessClient, DEFAULT_AI_GATEWAY_URL } from './gitlab-direct-access';\nexport type { GitLabDirectAccessConfig, DirectAccessToken } from './gitlab-direct-access';\n","import Anthropic from '@anthropic-ai/sdk';\nimport type { Tool } from '@anthropic-ai/sdk/resources/messages';\nimport { GitLabDirectAccessClient } from './gitlab-direct-access';\nimport { GitLabError } from './gitlab-error';\n\nimport type {\n LanguageModelV2,\n LanguageModelV2CallOptions,\n LanguageModelV2StreamPart,\n LanguageModelV2FinishReason,\n LanguageModelV2CallWarning,\n LanguageModelV2Content,\n LanguageModelV2Usage,\n LanguageModelV2FunctionTool,\n LanguageModelV2Message,\n LanguageModelV2ToolChoice,\n} from '@ai-sdk/provider';\n\nexport interface GitLabAnthropicConfig {\n provider: string;\n instanceUrl: string;\n getHeaders: () => Record<string, string>;\n fetch?: typeof fetch;\n\n /**\n * Optional callback to refresh the API key when a 401 error occurs.\n * Should clear cached credentials and re-fetch from auth provider.\n */\n refreshApiKey?: () => Promise<void>;\n\n /**\n * The Anthropic model to use (e.g., 'claude-sonnet-4-5-20250929')\n * @default 'claude-sonnet-4-5-20250929'\n */\n anthropicModel?: string;\n\n /**\n * Maximum tokens to generate\n * @default 8192\n */\n maxTokens?: number;\n\n /**\n * Feature flags to pass to the GitLab API\n * @default { DuoAgentPlatformNext: true }\n */\n featureFlags?: {\n DuoAgentPlatformNext: true;\n } & Record<string, boolean>;\n\n /**\n * AI Gateway URL for the Anthropic proxy.\n * Can also be set via GITLAB_AI_GATEWAY_URL environment variable.\n * @default 'https://cloud.gitlab.com'\n */\n aiGatewayUrl?: string;\n\n /**\n * Custom headers for AI Gateway Anthropic proxy requests.\n * Merged with headers from direct_access token response.\n */\n aiGatewayHeaders?: Record<string, string>;\n}\n\n/**\n * GitLab Anthropic Language Model\n *\n * This model uses GitLab's Anthropic proxy to provide native tool calling support\n * for the duo-chat model. It connects to Claude through GitLab's cloud proxy\n * at https://cloud.gitlab.com/ai/v1/proxy/anthropic/\n */\nexport class GitLabAnthropicLanguageModel implements LanguageModelV2 {\n readonly specificationVersion = 'v2' as const;\n readonly modelId: string;\n readonly supportedUrls: Record<string, RegExp[]> = {};\n\n private readonly config: GitLabAnthropicConfig;\n private readonly directAccessClient: GitLabDirectAccessClient;\n private anthropicClient: Anthropic | null = null;\n\n constructor(modelId: string, config: GitLabAnthropicConfig) {\n this.modelId = modelId;\n this.config = config;\n\n this.directAccessClient = new GitLabDirectAccessClient({\n instanceUrl: config.instanceUrl,\n getHeaders: config.getHeaders,\n refreshApiKey: config.refreshApiKey,\n fetch: config.fetch,\n featureFlags: config.featureFlags,\n aiGatewayUrl: config.aiGatewayUrl,\n });\n }\n\n get provider(): string {\n return this.config.provider;\n }\n\n /**\n * Get or create an Anthropic client with valid credentials\n * @param forceRefresh - If true, forces a token refresh before creating the client\n */\n private async getAnthropicClient(forceRefresh: boolean = false): Promise<Anthropic> {\n // Get token from GitLab (will use cache unless forceRefresh is true)\n const tokenData = await this.directAccessClient.getDirectAccessToken(forceRefresh);\n\n // Create new client with the token\n // GitLab's proxy expects:\n // - authToken: sets Authorization: Bearer header (NOT apiKey which sets x-api-key)\n // - defaultHeaders: additional headers from the direct access response\n // Filter out x-api-key from headers if present - we use authToken for Bearer auth\n const { 'x-api-key': _removed, ...filteredHeaders } = tokenData.headers;\n\n // Merge: tokenData headers < custom aiGatewayHeaders\n const mergedHeaders = {\n ...filteredHeaders,\n ...this.config.aiGatewayHeaders,\n };\n\n this.anthropicClient = new Anthropic({\n apiKey: null,\n authToken: tokenData.token,\n baseURL: this.directAccessClient.getAnthropicProxyUrl(),\n defaultHeaders: mergedHeaders,\n });\n\n return this.anthropicClient;\n }\n\n /**\n * Check if an error is a token-related authentication error that can be retried\n */\n private isTokenError(error: unknown): boolean {\n if (error instanceof Anthropic.APIError) {\n // 401 Unauthorized - token expired or revoked\n if (error.status === 401) {\n return true;\n }\n // Check for token-related error messages\n const message = error.message?.toLowerCase() || '';\n if (\n message.includes('token') &&\n (message.includes('expired') || message.includes('revoked') || message.includes('invalid'))\n ) {\n return true;\n }\n }\n return false;\n }\n\n /**\n * Convert AI SDK tools to Anthropic tool format\n */\n private convertTools(tools?: LanguageModelV2CallOptions['tools']): Tool[] | undefined {\n if (!tools || tools.length === 0) {\n return undefined;\n }\n\n return tools\n .filter((tool): tool is LanguageModelV2FunctionTool => tool.type === 'function')\n .map((tool) => {\n const schema = tool.inputSchema as { properties?: object; required?: string[] } | undefined;\n return {\n name: tool.name,\n description: tool.description || '',\n input_schema: {\n type: 'object' as const,\n properties: schema?.properties || {},\n required: schema?.required || [],\n },\n };\n });\n }\n\n /**\n * Convert AI SDK tool choice to Anthropic format\n */\n private convertToolChoice(\n toolChoice?: LanguageModelV2ToolChoice\n ): Anthropic.MessageCreateParams['tool_choice'] {\n if (!toolChoice) {\n return undefined;\n }\n\n switch (toolChoice.type) {\n case 'auto':\n return { type: 'auto' };\n case 'none':\n // Anthropic doesn't have a direct 'none' - we handle this by not sending tools\n return undefined;\n case 'required':\n return { type: 'any' };\n case 'tool':\n return { type: 'tool', name: toolChoice.toolName };\n default:\n return undefined;\n }\n }\n\n /**\n * Convert AI SDK prompt to Anthropic messages format\n */\n private convertPrompt(prompt: LanguageModelV2Message[]): {\n system?: string;\n messages: Anthropic.MessageParam[];\n } {\n let systemMessage: string | undefined;\n const messages: Anthropic.MessageParam[] = [];\n\n for (const message of prompt) {\n if (message.role === 'system') {\n systemMessage = message.content;\n continue;\n }\n\n if (message.role === 'user') {\n const content: Anthropic.ContentBlockParam[] = [];\n\n for (const part of message.content) {\n if (part.type === 'text') {\n content.push({ type: 'text', text: part.text });\n } else if (part.type === 'file') {\n // Handle file/image content if needed\n // For now, skip non-text content\n }\n }\n\n if (content.length > 0) {\n messages.push({ role: 'user', content });\n }\n } else if (message.role === 'assistant') {\n const content: Anthropic.ContentBlockParam[] = [];\n\n for (const part of message.content) {\n if (part.type === 'text') {\n content.push({ type: 'text', text: part.text });\n } else if (part.type === 'tool-call') {\n content.push({\n type: 'tool_use',\n id: part.toolCallId,\n name: part.toolName,\n input: typeof part.input === 'string' ? JSON.parse(part.input) : part.input,\n });\n }\n }\n\n if (content.length > 0) {\n messages.push({ role: 'assistant', content });\n }\n } else if (message.role === 'tool') {\n // Tool results need to be sent as user messages with tool_result content\n const content: Anthropic.ToolResultBlockParam[] = [];\n\n for (const part of message.content) {\n if (part.type === 'tool-result') {\n let resultContent: string;\n\n // Convert tool result output to string\n if (part.output.type === 'text') {\n resultContent = part.output.value;\n } else if (part.output.type === 'json') {\n resultContent = JSON.stringify(part.output.value);\n } else if (part.output.type === 'error-text') {\n resultContent = part.output.value;\n } else if (part.output.type === 'error-json') {\n resultContent = JSON.stringify(part.output.value);\n } else {\n resultContent = JSON.stringify(part.output);\n }\n\n content.push({\n type: 'tool_result',\n tool_use_id: part.toolCallId,\n content: resultContent,\n is_error: part.output.type.startsWith('error'),\n });\n }\n }\n\n if (content.length > 0) {\n messages.push({ role: 'user', content });\n }\n }\n }\n\n return { system: systemMessage, messages };\n }\n\n /**\n * Convert Anthropic finish reason to AI SDK format\n */\n private convertFinishReason(stopReason: string | null): LanguageModelV2FinishReason {\n switch (stopReason) {\n case 'end_turn':\n return 'stop';\n case 'stop_sequence':\n return 'stop';\n case 'max_tokens':\n return 'length';\n case 'tool_use':\n return 'tool-calls';\n default:\n return 'unknown';\n }\n }\n\n async doGenerate(options: LanguageModelV2CallOptions): Promise<{\n content: LanguageModelV2Content[];\n finishReason: LanguageModelV2FinishReason;\n usage: LanguageModelV2Usage;\n warnings: LanguageModelV2CallWarning[];\n }> {\n return this.doGenerateWithRetry(options, false);\n }\n\n private async doGenerateWithRetry(\n options: LanguageModelV2CallOptions,\n isRetry: boolean\n ): Promise<{\n content: LanguageModelV2Content[];\n finishReason: LanguageModelV2FinishReason;\n usage: LanguageModelV2Usage;\n warnings: LanguageModelV2CallWarning[];\n }> {\n const client = await this.getAnthropicClient(isRetry);\n const { system, messages } = this.convertPrompt(options.prompt);\n const tools = this.convertTools(options.tools);\n const toolChoice =\n options.toolChoice?.type !== 'none' ? this.convertToolChoice(options.toolChoice) : undefined;\n\n const anthropicModel = this.config.anthropicModel || 'claude-sonnet-4-5-20250929';\n const maxTokens = options.maxOutputTokens || this.config.maxTokens || 8192;\n\n try {\n const response = await client.messages.create({\n model: anthropicModel,\n max_tokens: maxTokens,\n system: system,\n messages: messages,\n tools: tools,\n tool_choice: tools ? toolChoice : undefined,\n temperature: options.temperature,\n top_p: options.topP,\n stop_sequences: options.stopSequences,\n });\n\n const content: LanguageModelV2Content[] = [];\n\n for (const block of response.content) {\n if (block.type === 'text') {\n content.push({\n type: 'text',\n text: block.text,\n });\n } else if (block.type === 'tool_use') {\n content.push({\n type: 'tool-call',\n toolCallId: block.id,\n toolName: block.name,\n input: JSON.stringify(block.input),\n });\n }\n }\n\n const usage: LanguageModelV2Usage = {\n inputTokens: response.usage.input_tokens,\n outputTokens: response.usage.output_tokens,\n totalTokens: response.usage.input_tokens + response.usage.output_tokens,\n };\n\n return {\n content,\n finishReason: this.convertFinishReason(response.stop_reason),\n usage,\n warnings: [],\n };\n } catch (error) {\n // If this is a token error and we haven't retried yet, refresh token and retry\n if (!isRetry && this.isTokenError(error)) {\n this.directAccessClient.invalidateToken();\n return this.doGenerateWithRetry(options, true);\n }\n\n if (error instanceof Anthropic.APIError) {\n throw new GitLabError({\n message: `Anthropic API error: ${error.message}`,\n cause: error,\n });\n }\n throw error;\n }\n }\n\n async doStream(options: LanguageModelV2CallOptions): Promise<{\n stream: ReadableStream<LanguageModelV2StreamPart>;\n request?: { body?: unknown };\n response?: { headers?: Record<string, string> };\n }> {\n return this.doStreamWithRetry(options, false);\n }\n\n private async doStreamWithRetry(\n options: LanguageModelV2CallOptions,\n isRetry: boolean\n ): Promise<{\n stream: ReadableStream<LanguageModelV2StreamPart>;\n request?: { body?: unknown };\n response?: { headers?: Record<string, string> };\n }> {\n const client = await this.getAnthropicClient(isRetry);\n const { system, messages } = this.convertPrompt(options.prompt);\n const tools = this.convertTools(options.tools);\n const toolChoice =\n options.toolChoice?.type !== 'none' ? this.convertToolChoice(options.toolChoice) : undefined;\n\n const anthropicModel = this.config.anthropicModel || 'claude-sonnet-4-5-20250929';\n const maxTokens = options.maxOutputTokens || this.config.maxTokens || 8192;\n\n const requestBody = {\n model: anthropicModel,\n max_tokens: maxTokens,\n system: system,\n messages: messages,\n tools: tools,\n tool_choice: tools ? toolChoice : undefined,\n temperature: options.temperature,\n top_p: options.topP,\n stop_sequences: options.stopSequences,\n stream: true as const,\n };\n\n // Reference to this for use in the stream callback\n // eslint-disable-next-line @typescript-eslint/no-this-alias\n const self = this;\n\n const stream = new ReadableStream<LanguageModelV2StreamPart>({\n start: async (controller) => {\n const contentBlocks: Record<\n number,\n | { type: 'text'; id: string }\n | { type: 'tool-call'; toolCallId: string; toolName: string; input: string }\n > = {};\n\n const usage: LanguageModelV2Usage = {\n inputTokens: 0,\n outputTokens: 0,\n totalTokens: 0,\n };\n let finishReason: LanguageModelV2FinishReason = 'unknown';\n\n try {\n const anthropicStream = client.messages.stream(requestBody, {\n signal: options.abortSignal,\n });\n\n // Stream start\n controller.enqueue({\n type: 'stream-start',\n warnings: [],\n });\n\n // Use event-based approach instead of for-await to ensure all events are received\n await new Promise<void>((resolve, reject) => {\n anthropicStream.on('streamEvent', (event) => {\n try {\n switch (event.type) {\n case 'message_start':\n if (event.message.usage) {\n usage.inputTokens = event.message.usage.input_tokens;\n }\n controller.enqueue({\n type: 'response-metadata',\n id: event.message.id,\n modelId: event.message.model,\n });\n break;\n\n case 'content_block_start':\n if (event.content_block.type === 'text') {\n const textId = `text-${event.index}`;\n contentBlocks[event.index] = { type: 'text', id: textId };\n controller.enqueue({\n type: 'text-start',\n id: textId,\n });\n } else if (event.content_block.type === 'tool_use') {\n contentBlocks[event.index] = {\n type: 'tool-call',\n toolCallId: event.content_block.id,\n toolName: event.content_block.name,\n input: '',\n };\n controller.enqueue({\n type: 'tool-input-start',\n id: event.content_block.id,\n toolName: event.content_block.name,\n });\n }\n break;\n\n case 'content_block_delta': {\n const block = contentBlocks[event.index];\n if (event.delta.type === 'text_delta' && block?.type === 'text') {\n controller.enqueue({\n type: 'text-delta',\n id: block.id,\n delta: event.delta.text,\n });\n } else if (\n event.delta.type === 'input_json_delta' &&\n block?.type === 'tool-call'\n ) {\n block.input += event.delta.partial_json;\n controller.enqueue({\n type: 'tool-input-delta',\n id: block.toolCallId,\n delta: event.delta.partial_json,\n });\n }\n break;\n }\n\n case 'content_block_stop': {\n const block = contentBlocks[event.index];\n if (block?.type === 'text') {\n controller.enqueue({\n type: 'text-end',\n id: block.id,\n });\n } else if (block?.type === 'tool-call') {\n controller.enqueue({\n type: 'tool-input-end',\n id: block.toolCallId,\n });\n\n controller.enqueue({\n type: 'tool-call',\n toolCallId: block.toolCallId,\n toolName: block.toolName,\n input: block.input === '' ? '{}' : block.input,\n });\n }\n delete contentBlocks[event.index];\n break;\n }\n\n case 'message_delta':\n if (event.usage) {\n usage.outputTokens = event.usage.output_tokens;\n usage.totalTokens = (usage.inputTokens || 0) + event.usage.output_tokens;\n }\n if (event.delta.stop_reason) {\n finishReason = self.convertFinishReason(event.delta.stop_reason);\n }\n break;\n\n case 'message_stop': {\n controller.enqueue({\n type: 'finish',\n finishReason,\n usage,\n });\n break;\n }\n }\n } catch {\n // Ignore errors processing individual events\n }\n });\n\n anthropicStream.on('end', () => {\n resolve();\n });\n\n anthropicStream.on('error', (error) => {\n reject(error);\n });\n });\n\n // Emit any pending tool calls if stream ended without content_block_stop\n for (const [, block] of Object.entries(contentBlocks)) {\n if (block.type === 'tool-call') {\n controller.enqueue({\n type: 'tool-input-end',\n id: block.toolCallId,\n });\n controller.enqueue({\n type: 'tool-call',\n toolCallId: block.toolCallId,\n toolName: block.toolName,\n input: block.input === '' ? '{}' : block.input,\n });\n }\n }\n\n controller.close();\n } catch (error) {\n // Emit any pending tool calls before handling the error\n for (const [, block] of Object.entries(contentBlocks)) {\n if (block.type === 'tool-call') {\n controller.enqueue({\n type: 'tool-input-end',\n id: block.toolCallId,\n });\n controller.enqueue({\n type: 'tool-call',\n toolCallId: block.toolCallId,\n toolName: block.toolName,\n input: block.input === '' ? '{}' : block.input,\n });\n }\n }\n\n // If this is a token error and we haven't retried yet, we need to signal retry\n // For streaming, we close this stream with an error and the caller should retry\n if (!isRetry && self.isTokenError(error)) {\n self.directAccessClient.invalidateToken();\n // Signal that a retry is needed with a special error\n controller.enqueue({\n type: 'error',\n error: new GitLabError({\n message: 'TOKEN_REFRESH_NEEDED',\n cause: error,\n }),\n });\n controller.close();\n return;\n }\n\n if (error instanceof Anthropic.APIError) {\n controller.enqueue({\n type: 'error',\n error: new GitLabError({\n message: `Anthropic API error: ${error.message}`,\n cause: error,\n }),\n });\n } else {\n controller.enqueue({\n type: 'error',\n error,\n });\n }\n controller.close();\n }\n },\n });\n\n return {\n stream,\n request: { body: requestBody },\n };\n }\n}\n","import { z } from 'zod';\nimport { GitLabError } from './gitlab-error';\n\n/**\n * Response from /api/v4/ai/third_party_agents/direct_access\n */\nexport const directAccessTokenSchema = z.object({\n headers: z.record(z.string()),\n token: z.string(),\n});\n\nexport type DirectAccessToken = z.infer<typeof directAccessTokenSchema>;\n\nexport const DEFAULT_AI_GATEWAY_URL = 'https://cloud.gitlab.com';\n\nexport interface GitLabDirectAccessConfig {\n instanceUrl: string;\n getHeaders: () => Record<string, string>;\n fetch?: typeof fetch;\n /**\n * Optional callback to refresh the API key when a 401 error occurs.\n * Should clear cached credentials and re-fetch from auth provider.\n */\n refreshApiKey?: () => Promise<void>;\n /**\n * Feature flags to pass to the GitLab API\n */\n featureFlags?: Record<string, boolean>;\n /**\n * AI Gateway URL for the Anthropic proxy.\n * Can also be set via GITLAB_AI_GATEWAY_URL environment variable.\n * @default 'https://cloud.gitlab.com'\n */\n aiGatewayUrl?: string;\n}\n\n/**\n * Client for GitLab's third-party agents direct access API.\n * This allows routing requests through GitLab's proxy to Anthropic.\n */\nexport class GitLabDirectAccessClient {\n private readonly config: GitLabDirectAccessConfig;\n private readonly fetchFn: typeof fetch;\n private readonly aiGatewayUrl: string;\n private cachedToken: DirectAccessToken | null = null;\n private tokenExpiresAt: number = 0;\n\n constructor(config: GitLabDirectAccessConfig) {\n this.config = config;\n this.fetchFn = config.fetch ?? fetch;\n this.aiGatewayUrl =\n config.aiGatewayUrl || process.env['GITLAB_AI_GATEWAY_URL'] || DEFAULT_AI_GATEWAY_URL;\n }\n\n /**\n * Get a direct access token for the Anthropic proxy.\n * Tokens are cached for 25 minutes (they expire after 30 minutes).\n * @param forceRefresh - If true, ignores the cache and fetches a new token\n */\n async getDirectAccessToken(forceRefresh: boolean = false): Promise<DirectAccessToken> {\n // Check if we have a valid cached token (unless force refresh is requested)\n const now = Date.now();\n if (!forceRefresh && this.cachedToken && this.tokenExpiresAt > now) {\n return this.cachedToken;\n }\n\n // Clear cache if forcing refresh\n if (forceRefresh) {\n this.invalidateToken();\n }\n\n const url = `${this.config.instanceUrl}/api/v4/ai/third_party_agents/direct_access`;\n\n // Prepare request body with feature flags if provided\n const requestBody: Record<string, unknown> = {};\n if (this.config.featureFlags && Object.keys(this.config.featureFlags).length > 0) {\n requestBody.feature_flags = this.config.featureFlags;\n }\n\n try {\n const response = await this.fetchFn(url, {\n method: 'POST',\n headers: {\n ...this.config.getHeaders(),\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(requestBody),\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n\n // If we get a 401 and have a refresh callback, try refreshing the API key once\n if (response.status === 401 && this.config.refreshApiKey && !forceRefresh) {\n try {\n // Refresh the API key (this should clear cached credentials and re-fetch from auth)\n await this.config.refreshApiKey();\n\n // Retry the request with the refreshed credentials\n return await this.getDirectAccessToken(true);\n } catch (refreshError) {\n // If refresh fails, throw the original 401 error\n throw new GitLabError({\n message: `Failed to get direct access token: ${response.status} ${response.statusText} - ${errorText}`,\n statusCode: response.status,\n responseBody: errorText,\n });\n }\n }\n\n // Provide helpful error message for 403 errors (common with self-hosted instances)\n if (response.status === 403) {\n throw new GitLabError({\n message:\n `Access denied to GitLab AI features (${this.config.instanceUrl}). ` +\n `This may indicate that: (1) GitLab Duo is not enabled on this instance, ` +\n `(2) Your account does not have access to AI features, or ` +\n `(3) The third-party agents feature is not available. ` +\n `Original error: ${response.status} ${response.statusText} - ${errorText}`,\n statusCode: response.status,\n responseBody: errorText,\n });\n }\n\n throw new GitLabError({\n message: `Failed to get direct access token: ${response.status} ${response.statusText} - ${errorText}`,\n statusCode: response.status,\n responseBody: errorText,\n });\n }\n\n const data = await response.json();\n const token = directAccessTokenSchema.parse(data);\n\n // Cache the token for 25 minutes (tokens expire after 30 minutes)\n this.cachedToken = token;\n this.tokenExpiresAt = now + 25 * 60 * 1000;\n\n return token;\n } catch (error) {\n if (error instanceof GitLabError) {\n throw error;\n }\n throw new GitLabError({\n message: `Failed to get direct access token: ${error}`,\n cause: error,\n });\n }\n }\n\n /**\n * Get the Anthropic proxy base URL\n */\n getAnthropicProxyUrl(): string {\n const baseUrl = this.aiGatewayUrl.replace(/\\/$/, '');\n return `${baseUrl}/ai/v1/proxy/anthropic/`;\n }\n\n /**\n * Get the OpenAI proxy base URL\n * Note: The OpenAI SDK expects a base URL like https://api.openai.com/v1\n * and appends paths like /chat/completions. So we need /v1 at the end.\n */\n getOpenAIProxyUrl(): string {\n const baseUrl = this.aiGatewayUrl.replace(/\\/$/, '');\n return `${baseUrl}/ai/v1/proxy/openai/v1`;\n }\n\n /**\n * Invalidate the cached token\n */\n invalidateToken(): void {\n this.cachedToken = null;\n this.tokenExpiresAt = 0;\n }\n}\n","export interface GitLabErrorOptions {\n message: string;\n statusCode?: number;\n responseBody?: string;\n cause?: unknown;\n}\n\nexport class GitLabError extends Error {\n readonly statusCode?: number;\n readonly responseBody?: string;\n readonly cause?: unknown;\n\n constructor(options: GitLabErrorOptions) {\n super(options.message);\n this.name = 'GitLabError';\n this.statusCode = options.statusCode;\n this.responseBody = options.responseBody;\n this.cause = options.cause;\n\n // Maintain proper stack trace for where error was thrown (only available on V8)\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, GitLabError);\n }\n }\n\n static fromResponse(response: Response, body: string): GitLabError {\n return new GitLabError({\n message: `GitLab API error: ${response.status} ${response.statusText}`,\n statusCode: response.status,\n responseBody: body,\n });\n }\n\n isAuthError(): boolean {\n return this.statusCode === 401;\n }\n\n isRateLimitError(): boolean {\n return this.statusCode === 429;\n }\n\n isForbiddenError(): boolean {\n return this.statusCode === 403;\n }\n\n isServerError(): boolean {\n return this.statusCode !== undefined && this.statusCode >= 500;\n }\n}\n","import OpenAI from 'openai';\nimport { GitLabDirectAccessClient } from './gitlab-direct-access';\nimport { GitLabError } from './gitlab-error';\nimport { isResponsesApiModel } from './model-mappings';\n\nimport type {\n LanguageModelV2,\n LanguageModelV2CallOptions,\n LanguageModelV2StreamPart,\n LanguageModelV2FinishReason,\n LanguageModelV2CallWarning,\n LanguageModelV2Content,\n LanguageModelV2Usage,\n LanguageModelV2FunctionTool,\n LanguageModelV2Message,\n LanguageModelV2ToolChoice,\n} from '@ai-sdk/provider';\n\nexport interface GitLabOpenAIConfig {\n provider: string;\n instanceUrl: string;\n getHeaders: () => Record<string, string>;\n fetch?: typeof fetch;\n refreshApiKey?: () => Promise<void>;\n openaiModel?: string;\n maxTokens?: number;\n featureFlags?: {\n DuoAgentPlatformNext: true;\n } & Record<string, boolean>;\n aiGatewayUrl?: string;\n /** Whether to use the Responses API instead of Chat Completions API */\n useResponsesApi?: boolean;\n /**\n * Custom headers for AI Gateway OpenAI proxy requests.\n * Merged with headers from direct_access token response.\n */\n aiGatewayHeaders?: Record<string, string>;\n}\n\nexport class GitLabOpenAILanguageModel implements LanguageModelV2 {\n readonly specificationVersion = 'v2' as const;\n readonly modelId: string;\n readonly supportedUrls: Record<string, RegExp[]> = {};\n\n private readonly config: GitLabOpenAIConfig;\n private readonly directAccessClient: GitLabDirectAccessClient;\n private readonly useResponsesApi: boolean;\n private openaiClient: OpenAI | null = null;\n\n constructor(modelId: string, config: GitLabOpenAIConfig) {\n this.modelId = modelId;\n this.config = config;\n this.useResponsesApi = config.useResponsesApi ?? isResponsesApiModel(modelId);\n\n this.directAccessClient = new GitLabDirectAccessClient({\n instanceUrl: config.instanceUrl,\n getHeaders: config.getHeaders,\n refreshApiKey: config.refreshApiKey,\n fetch: config.fetch,\n featureFlags: config.featureFlags,\n aiGatewayUrl: config.aiGatewayUrl,\n });\n }\n\n get provider(): string {\n return this.config.provider;\n }\n\n private async getOpenAIClient(forceRefresh: boolean = false): Promise<OpenAI> {\n const tokenData = await this.directAccessClient.getDirectAccessToken(forceRefresh);\n const { 'x-api-key': _removed, ...filteredHeaders } = tokenData.headers;\n\n // Merge: tokenData headers < custom aiGatewayHeaders\n const mergedHeaders = {\n ...filteredHeaders,\n ...this.config.aiGatewayHeaders,\n };\n\n this.openaiClient = new OpenAI({\n apiKey: tokenData.token,\n baseURL: this.directAccessClient.getOpenAIProxyUrl(),\n defaultHeaders: mergedHeaders,\n });\n\n return this.openaiClient;\n }\n\n private isTokenError(error: unknown): boolean {\n if (error instanceof OpenAI.APIError) {\n if (error.status === 401) {\n return true;\n }\n const message = error.message?.toLowerCase() || '';\n if (\n message.includes('token') &&\n (message.includes('expired') || message.includes('revoked') || message.includes('invalid'))\n ) {\n return true;\n }\n }\n return false;\n }\n\n private convertTools(\n tools?: LanguageModelV2CallOptions['tools']\n ): OpenAI.ChatCompletionTool[] | undefined {\n if (!tools || tools.length === 0) {\n return undefined;\n }\n\n return tools\n .filter((tool): tool is LanguageModelV2FunctionTool => tool.type === 'function')\n .map((tool) => {\n const schema = tool.inputSchema as Record<string, unknown>;\n return {\n type: 'function' as const,\n function: {\n name: tool.name,\n description: tool.description || '',\n // Ensure the schema has type: 'object' as OpenAI requires it\n parameters: {\n type: 'object',\n ...schema,\n },\n },\n };\n });\n }\n\n private convertToolChoice(\n toolChoice?: LanguageModelV2ToolChoice\n ): OpenAI.ChatCompletionToolChoiceOption | undefined {\n if (!toolChoice) {\n return undefined;\n }\n\n switch (toolChoice.type) {\n case 'auto':\n return 'auto';\n case 'none':\n return 'none';\n case 'required':\n return 'required';\n case 'tool':\n return { type: 'function', function: { name: toolChoice.toolName } };\n default:\n return undefined;\n }\n }\n\n private convertPrompt(prompt: LanguageModelV2Message[]): OpenAI.ChatCompletionMessageParam[] {\n const messages: OpenAI.ChatCompletionMessageParam[] = [];\n\n for (const message of prompt) {\n if (message.role === 'system') {\n messages.push({ role: 'system', content: message.content });\n continue;\n }\n\n if (message.role === 'user') {\n const textParts = message.content\n .filter((part) => part.type === 'text')\n .map((part) => part.text);\n if (textParts.length > 0) {\n messages.push({ role: 'user', content: textParts.join('\\n') });\n }\n } else if (message.role === 'assistant') {\n const textParts: string[] = [];\n const toolCalls: OpenAI.ChatCompletionMessageToolCall[] = [];\n\n for (const part of message.content) {\n if (part.type === 'text') {\n textParts.push(part.text);\n } else if (part.type === 'tool-call') {\n toolCalls.push({\n id: part.toolCallId,\n type: 'function',\n function: {\n name: part.toolName,\n arguments: typeof part.input === 'string' ? part.input : JSON.stringify(part.input),\n },\n });\n }\n }\n\n const assistantMessage: OpenAI.ChatCompletionAssistantMessageParam = {\n role: 'assistant',\n content: textParts.length > 0 ? textParts.join('\\n') : null,\n };\n if (toolCalls.length > 0) {\n assistantMessage.tool_calls = toolCalls;\n }\n messages.push(assistantMessage);\n } else if (message.role === 'tool') {\n for (const part of message.content) {\n if (part.type === 'tool-result') {\n let resultContent: string;\n if (part.output.type === 'text') {\n resultContent = part.output.value;\n } else if (part.output.type === 'json') {\n resultContent = JSON.stringify(part.output.value);\n } else if (part.output.type === 'error-text') {\n resultContent = part.output.value;\n } else if (part.output.type === 'error-json') {\n resultContent = JSON.stringify(part.output.value);\n } else {\n resultContent = JSON.stringify(part.output);\n }\n messages.push({\n role: 'tool',\n tool_call_id: part.toolCallId,\n content: resultContent,\n });\n }\n }\n }\n }\n\n return messages;\n }\n\n private convertFinishReason(\n finishReason: string | null | undefined\n ): LanguageModelV2FinishReason {\n switch (finishReason) {\n case 'stop':\n return 'stop';\n case 'length':\n return 'length';\n case 'tool_calls':\n return 'tool-calls';\n case 'content_filter':\n return 'content-filter';\n default:\n return 'unknown';\n }\n }\n\n /**\n * Convert tools to Responses API format\n */\n private convertToolsForResponses(\n tools?: LanguageModelV2CallOptions['tools']\n ): OpenAI.Responses.FunctionTool[] | undefined {\n if (!tools || tools.length === 0) {\n return undefined;\n }\n\n return tools\n .filter((tool): tool is LanguageModelV2FunctionTool => tool.type === 'function')\n .map((tool) => {\n // Clone schema and remove $schema field which can confuse the model\n // Zod 4's toJSONSchema() adds \"$schema\": \"https://json-schema.org/draft/2020-12/schema\"\n const schema = { ...(tool.inputSchema as Record<string, unknown>) };\n delete schema['$schema'];\n\n return {\n type: 'function' as const,\n name: tool.name,\n description: tool.description || '',\n parameters: schema,\n strict: false,\n };\n });\n }\n\n /**\n * Convert prompt to Responses API input format\n */\n private convertPromptForResponses(\n prompt: LanguageModelV2Message[]\n ): OpenAI.Responses.ResponseInput {\n const items: OpenAI.Responses.ResponseInputItem[] = [];\n\n for (const message of prompt) {\n if (message.role === 'system') {\n // System messages become instructions, handled separately\n continue;\n }\n\n if (message.role === 'user') {\n const textParts = message.content\n .filter((part) => part.type === 'text')\n .map((part) => part.text);\n if (textParts.length > 0) {\n items.push({\n type: 'message',\n role: 'user',\n content: textParts.map((text) => ({ type: 'input_text' as const, text })),\n } as OpenAI.Responses.ResponseInputItem);\n }\n } else if (message.role === 'assistant') {\n // Handle text content as output message\n const textParts: string[] = [];\n for (const part of message.content) {\n if (part.type === 'text') {\n textParts.push(part.text);\n } else if (part.type === 'tool-call') {\n // Tool calls are function_call items in Responses API\n items.push({\n type: 'function_call',\n call_id: part.toolCallId,\n name: part.toolName,\n arguments: typeof part.input === 'string' ? part.input : JSON.stringify(part.input),\n } as OpenAI.Responses.ResponseInputItem);\n }\n }\n\n if (textParts.length > 0) {\n items.push({\n type: 'message',\n role: 'assistant',\n content: [{ type: 'output_text', text: textParts.join('\\n'), annotations: [] }],\n } as OpenAI.Responses.ResponseInputItem);\n }\n } else if (message.role === 'tool') {\n for (const part of message.content) {\n if (part.type === 'tool-result') {\n let resultContent: string;\n if (part.output.type === 'text') {\n resultContent = part.output.value;\n } else if (part.output.type === 'json') {\n resultContent = JSON.stringify(part.output.value);\n } else if (part.output.type === 'error-text') {\n resultContent = part.output.value;\n } else if (part.output.type === 'error-json') {\n resultContent = JSON.stringify(part.output.value);\n } else {\n resultContent = JSON.stringify(part.output);\n }\n items.push({\n type: 'function_call_output',\n call_id: part.toolCallId,\n output: resultContent,\n } as OpenAI.Responses.ResponseInputItem);\n }\n }\n }\n }\n\n return items;\n }\n\n /**\n * Extract system instructions from prompt\n */\n private extractSystemInstructions(prompt: LanguageModelV2Message[]): string | undefined {\n const systemMessages = prompt\n .filter((m) => m.role === 'system')\n .map((m) => m.content)\n .join('\\n');\n return systemMessages || undefined;\n }\n\n /**\n * Convert Responses API status to finish reason\n * Note: Responses API returns 'completed' even when making tool calls,\n * so we need to check the content for tool calls separately.\n */\n private convertResponsesStatus(\n status: string | undefined,\n hasToolCalls: boolean = false\n ): LanguageModelV2FinishReason {\n // If we have tool calls, return 'tool-calls' regardless of status\n if (hasToolCalls) {\n return 'tool-calls';\n }\n\n switch (status) {\n case 'completed':\n return 'stop';\n case 'incomplete':\n return 'length';\n case 'cancelled':\n return 'stop';\n case 'failed':\n return 'error';\n default:\n return 'unknown';\n }\n }\n\n async doGenerate(options: LanguageModelV2CallOptions): Promise<{\n content: LanguageModelV2Content[];\n finishReason: LanguageModelV2FinishReason;\n usage: LanguageModelV2Usage;\n warnings: LanguageModelV2CallWarning[];\n }> {\n if (this.useResponsesApi) {\n return this.doGenerateWithResponsesApi(options, false);\n }\n return this.doGenerateWithChatApi(options, false);\n }\n\n private async doGenerateWithChatApi(\n options: LanguageModelV2CallOptions,\n isRetry: boolean\n ): Promise<{\n content: LanguageModelV2Content[];\n finishReason: LanguageModelV2FinishReason;\n usage: LanguageModelV2Usage;\n warnings: LanguageModelV2CallWarning[];\n }> {\n const client = await this.getOpenAIClient(isRetry);\n const messages = this.convertPrompt(options.prompt);\n const tools = this.convertTools(options.tools);\n const toolChoice =\n options.toolChoice?.type !== 'none' ? this.convertToolChoice(options.toolChoice) : undefined;\n\n const openaiModel = this.config.openaiModel || 'gpt-4o';\n const maxTokens = options.maxOutputTokens || this.config.maxTokens || 8192;\n\n try {\n const response = await client.chat.completions.create({\n model: openaiModel,\n max_completion_tokens: maxTokens,\n messages: messages,\n tools: tools,\n tool_choice: tools ? toolChoice : undefined,\n temperature: options.temperature,\n top_p: options.topP,\n stop: options.stopSequences,\n });\n\n const choice = response.choices[0];\n const content: LanguageModelV2Content[] = [];\n\n if (choice?.message.content) {\n content.push({ type: 'text', text: choice.message.content });\n }\n\n if (choice?.message.tool_calls) {\n for (const toolCall of choice.message.tool_calls) {\n if (toolCall.type === 'function') {\n content.push({\n type: 'tool-call',\n toolCallId: toolCall.id,\n toolName: toolCall.function.name,\n input: toolCall.function.arguments,\n });\n }\n }\n }\n\n const usage: LanguageModelV2Usage = {\n inputTokens: response.usage?.prompt_tokens || 0,\n outputTokens: response.usage?.completion_tokens || 0,\n totalTokens: response.usage?.total_tokens || 0,\n };\n\n return {\n content,\n finishReason: this.convertFinishReason(choice?.finish_reason),\n usage,\n warnings: [],\n };\n } catch (error) {\n if (!isRetry && this.isTokenError(error)) {\n this.directAccessClient.invalidateToken();\n return this.doGenerateWithChatApi(options, true);\n }\n\n if (error instanceof OpenAI.APIError) {\n throw new GitLabError({\n message: `OpenAI API error: ${error.message}`,\n cause: error,\n });\n }\n throw error;\n }\n }\n\n private async doGenerateWithResponsesApi(\n options: LanguageModelV2CallOptions,\n isRetry: boolean\n ): Promise<{\n content: LanguageModelV2Content[];\n finishReason: LanguageModelV2FinishReason;\n usage: LanguageModelV2Usage;\n warnings: LanguageModelV2CallWarning[];\n }> {\n const client = await this.getOpenAIClient(isRetry);\n const input = this.convertPromptForResponses(options.prompt);\n const tools = this.convertToolsForResponses(options.tools);\n const instructions = this.extractSystemInstructions(options.prompt);\n\n const openaiModel = this.config.openaiModel || 'gpt-5-codex';\n const maxTokens = options.maxOutputTokens || this.config.maxTokens || 8192;\n\n try {\n const response = await client.responses.create({\n model: openaiModel,\n input,\n instructions,\n tools,\n max_output_tokens: maxTokens,\n temperature: options.temperature,\n top_p: options.topP,\n store: false,\n });\n\n const content: LanguageModelV2Content[] = [];\n let hasToolCalls = false;\n\n // Process output items\n for (const item of response.output || []) {\n if (item.type === 'message' && item.role === 'assistant') {\n for (const contentItem of item.content || []) {\n if (contentItem.type === 'output_text') {\n content.push({ type: 'text', text: contentItem.text });\n }\n }\n } else if (item.type === 'function_call') {\n hasToolCalls = true;\n content.push({\n type: 'tool-call',\n toolCallId: item.call_id,\n toolName: item.name,\n input: item.arguments,\n });\n }\n }\n\n const usage: LanguageModelV2Usage = {\n inputTokens: response.usage?.input_tokens || 0,\n outputTokens: response.usage?.output_tokens || 0,\n totalTokens: response.usage?.total_tokens || 0,\n };\n\n return {\n content,\n finishReason: this.convertResponsesStatus(response.status, hasToolCalls),\n usage,\n warnings: [],\n };\n } catch (error) {\n if (!isRetry && this.isTokenError(error)) {\n this.directAccessClient.invalidateToken();\n return this.doGenerateWithResponsesApi(options, true);\n }\n\n if (error instanceof OpenAI.APIError) {\n throw new GitLabError({\n message: `OpenAI API error: ${error.message}`,\n cause: error,\n });\n }\n throw error;\n }\n }\n\n async doStream(options: LanguageModelV2CallOptions): Promise<{\n stream: ReadableStream<LanguageModelV2StreamPart>;\n request?: { body?: unknown };\n response?: { headers?: Record<string, string> };\n }> {\n if (this.useResponsesApi) {\n return this.doStreamWithResponsesApi(options, false);\n }\n return this.doStreamWithChatApi(options, false);\n }\n\n private async doStreamWithChatApi(\n options: LanguageModelV2CallOptions,\n isRetry: boolean\n ): Promise<{\n stream: ReadableStream<LanguageModelV2StreamPart>;\n request?: { body?: unknown };\n response?: { headers?: Record<string, string> };\n }> {\n const client = await this.getOpenAIClient(isRetry);\n const messages = this.convertPrompt(options.prompt);\n const tools = this.convertTools(options.tools);\n const toolChoice =\n options.toolChoice?.type !== 'none' ? this.convertToolChoice(options.toolChoice) : undefined;\n\n const openaiModel = this.config.openaiModel || 'gpt-4o';\n const maxTokens = options.maxOutputTokens || this.config.maxTokens || 8192;\n\n const requestBody = {\n model: openaiModel,\n max_completion_tokens: maxTokens,\n messages: messages,\n tools: tools,\n tool_choice: tools ? toolChoice : undefined,\n temperature: options.temperature,\n top_p: options.topP,\n stop: options.stopSequences,\n stream: true as const,\n stream_options: { include_usage: true },\n };\n\n // eslint-disable-next-line @typescript-eslint/no-this-alias\n const self = this;\n\n const stream = new ReadableStream<LanguageModelV2StreamPart>({\n start: async (controller) => {\n const toolCalls: Record<number, { id: string; name: string; arguments: string }> = {};\n\n const usage: LanguageModelV2Usage = {\n inputTokens: 0,\n outputTokens: 0,\n totalTokens: 0,\n };\n let finishReason: LanguageModelV2FinishReason = 'unknown';\n let textStarted = false;\n const textId = 'text-0';\n\n try {\n const openaiStream = await client.chat.completions.create({\n ...requestBody,\n stream: true,\n });\n\n controller.enqueue({ type: 'stream-start', warnings: [] });\n\n for await (const chunk of openaiStream) {\n const choice = chunk.choices?.[0];\n\n if (chunk.id && !textStarted) {\n controller.enqueue({\n type: 'response-metadata',\n id: chunk.id,\n modelId: chunk.model,\n });\n }\n\n if (choice?.delta?.content) {\n if (!textStarted) {\n controller.enqueue({ type: 'text-start', id: textId });\n textStarted = true;\n }\n controller.enqueue({\n type: 'text-delta',\n id: textId,\n delta: choice.delta.content,\n });\n }\n\n if (choice?.delta?.tool_calls) {\n for (const tc of choice.delta.tool_calls) {\n const idx = tc.index;\n if (!toolCalls[idx]) {\n toolCalls[idx] = {\n id: tc.id || '',\n name: tc.function?.name || '',\n arguments: '',\n };\n controller.enqueue({\n type: 'tool-input-start',\n id: toolCalls[idx].id,\n toolName: toolCalls[idx].name,\n });\n }\n if (tc.function?.arguments) {\n toolCalls[idx].arguments += tc.function.arguments;\n controller.enqueue({\n type: 'tool-input-delta',\n id: toolCalls[idx].id,\n delta: tc.function.arguments,\n });\n }\n }\n }\n\n if (choice?.finish_reason) {\n finishReason = self.convertFinishReason(choice.finish_reason);\n }\n\n if (chunk.usage) {\n usage.inputTokens = chunk.usage.prompt_tokens || 0;\n usage.outputTokens = chunk.usage.completion_tokens || 0;\n usage.totalTokens = chunk.usage.total_tokens || 0;\n }\n }\n\n if (textStarted) {\n controller.enqueue({ type: 'text-end', id: textId });\n }\n\n for (const [, tc] of Object.entries(toolCalls)) {\n controller.enqueue({ type: 'tool-input-end', id: tc.id });\n controller.enqueue({\n type: 'tool-call',\n toolCallId: tc.id,\n toolName: tc.name,\n input: tc.arguments || '{}',\n });\n }\n\n controller.enqueue({ type: 'finish', finishReason, usage });\n controller.close();\n } catch (error) {\n if (!isRetry && self.isTokenError(error)) {\n self.directAccessClient.invalidateToken();\n controller.enqueue({\n type: 'error',\n error: new GitLabError({ message: 'TOKEN_REFRESH_NEEDED', cause: error }),\n });\n controller.close();\n return;\n }\n\n if (error instanceof OpenAI.APIError) {\n controller.enqueue({\n type: 'error',\n error: new GitLabError({\n message: `OpenAI API error: ${error.message}`,\n cause: error,\n }),\n });\n } else {\n controller.enqueue({ type: 'error', error });\n }\n controller.close();\n }\n },\n });\n\n return { stream, request: { body: requestBody } };\n }\n\n private async doStreamWithResponsesApi(\n options: LanguageModelV2CallOptions,\n isRetry: boolean\n ): Promise<{\n stream: ReadableStream<LanguageModelV2StreamPart>;\n request?: { body?: unknown };\n response?: { headers?: Record<string, string> };\n }> {\n const client = await this.getOpenAIClient(isRetry);\n const input = this.convertPromptForResponses(options.prompt);\n const tools = this.convertToolsForResponses(options.tools);\n const instructions = this.extractSystemInstructions(options.prompt);\n\n const openaiModel = this.config.openaiModel || 'gpt-5-codex';\n const maxTokens = options.maxOutputTokens || this.config.maxTokens || 8192;\n\n const requestBody = {\n model: openaiModel,\n input,\n instructions,\n tools,\n max_output_tokens: maxTokens,\n temperature: options.temperature,\n top_p: options.topP,\n store: false,\n stream: true as const,\n };\n\n // eslint-disable-next-line @typescript-eslint/no-this-alias\n const self = this;\n\n const stream = new ReadableStream<LanguageModelV2StreamPart>({\n start: async (controller) => {\n // Use output_index as key (like OpenCode does) to track tool calls across events\n const toolCalls: Record<number, { callId: string; name: string; arguments: string }> = {};\n const usage: LanguageModelV2Usage = {\n inputTokens: 0,\n outputTokens: 0,\n totalTokens: 0,\n };\n let finishReason: LanguageModelV2FinishReason = 'unknown';\n let textStarted = false;\n const textId = 'text-0';\n\n try {\n const openaiStream = await client.responses.create({\n ...requestBody,\n stream: true,\n });\n\n controller.enqueue({ type: 'stream-start', warnings: [] });\n\n for await (const event of openaiStream) {\n // Handle different event types from Responses API streaming\n if (event.type === 'response.created') {\n controller.enqueue({\n type: 'response-metadata',\n id: event.response.id,\n modelId: event.response.model,\n });\n } else if (event.type === 'response.output_item.added') {\n // Track function calls when they start, keyed by output_index\n if (event.item.type === 'function_call') {\n const outputIndex = event.output_index;\n const callId = event.item.call_id;\n toolCalls[outputIndex] = {\n callId,\n name: event.item.name,\n arguments: '',\n };\n controller.enqueue({\n type: 'tool-input-start',\n id: callId,\n toolName: event.item.name,\n });\n }\n } else if (event.type === 'response.output_text.delta') {\n if (!textStarted) {\n controller.enqueue({ type: 'text-start', id: textId });\n textStarted = true;\n }\n controller.enqueue({\n type: 'text-delta',\n id: textId,\n delta: event.delta,\n });\n } else if (event.type === 'response.function_call_arguments.delta') {\n // Use output_index to find the tool call (like OpenCode)\n const outputIndex = event.output_index;\n const tc = toolCalls[outputIndex];\n if (tc) {\n tc.arguments += event.delta;\n controller.enqueue({\n type: 'tool-input-delta',\n id: tc.callId,\n delta: event.delta,\n });\n }\n } else if (event.type === 'response.function_call_arguments.done') {\n const outputIndex = event.output_index;\n const tc = toolCalls[outputIndex];\n if (tc) {\n tc.arguments = event.arguments;\n }\n } else if (event.type === 'response.completed') {\n // Check if there are tool calls to determine finish reason\n const hasToolCalls = Object.keys(toolCalls).length > 0;\n finishReason = self.convertResponsesStatus(event.response.status, hasToolCalls);\n if (event.response.usage) {\n usage.inputTokens = event.response.usage.input_tokens || 0;\n usage.outputTokens = event.response.usage.output_tokens || 0;\n usage.totalTokens = event.response.usage.total_tokens || 0;\n }\n }\n }\n\n if (textStarted) {\n controller.enqueue({ type: 'text-end', id: textId });\n }\n\n // Check if we have tool calls to set the correct finish reason\n const hasToolCalls = Object.keys(toolCalls).length > 0;\n if (hasToolCalls && finishReason === 'stop') {\n finishReason = 'tool-calls';\n }\n\n for (const tc of Object.values(toolCalls)) {\n controller.enqueue({ type: 'tool-input-end', id: tc.callId });\n controller.enqueue({\n type: 'tool-call',\n toolCallId: tc.callId,\n toolName: tc.name,\n input: tc.arguments || '{}',\n });\n }\n\n controller.enqueue({ type: 'finish', finishReason, usage });\n controller.close();\n } catch (error) {\n if (!isRetry && self.isTokenError(error)) {\n self.directAccessClient.invalidateToken();\n controller.enqueue({\n type: 'error',\n error: new GitLabError({ message: 'TOKEN_REFRESH_NEEDED', cause: error }),\n });\n controller.close();\n return;\n }\n\n if (error instanceof OpenAI.APIError) {\n controller.enqueue({\n type: 'error',\n error: new GitLabError({\n message: `OpenAI API error: ${error.message}`,\n cause: error,\n }),\n });\n } else {\n controller.enqueue({ type: 'error', error });\n }\n controller.close();\n }\n },\n });\n\n return { stream, request: { body: requestBody } };\n }\n}\n","export type ModelProvider = 'anthropic' | 'openai';\n\nexport type OpenAIApiType = 'chat' | 'responses';\n\nexport interface ModelMapping {\n provider: ModelProvider;\n model: string;\n /** For OpenAI models, which API to use: 'chat' for /v1/chat/completions, 'responses' for /v1/responses */\n openaiApiType?: OpenAIApiType;\n}\n\nexport const MODEL_MAPPINGS: Record<string, ModelMapping> = {\n // Anthropic models\n 'duo-chat-opus-4-5': { provider: 'anthropic', model: 'claude-opus-4-5-20251101' },\n 'duo-chat-sonnet-4-5': { provider: 'anthropic', model: 'claude-sonnet-4-5-20250929' },\n 'duo-chat-haiku-4-5': { provider: 'anthropic', model: 'claude-haiku-4-5-20251001' },\n\n // OpenAI models - Chat Completions API\n 'duo-chat-gpt-5-1': { provider: 'openai', model: 'gpt-5.1-2025-11-13', openaiApiType: 'chat' },\n 'duo-chat-gpt-5-2': { provider: 'openai', model: 'gpt-5.2-2025-12-11', openaiApiType: 'chat' },\n 'duo-chat-gpt-5-mini': {\n provider: 'openai',\n model: 'gpt-5-mini-2025-08-07',\n openaiApiType: 'chat',\n },\n\n // OpenAI models - Responses API (Codex models)\n 'duo-chat-gpt-5-codex': { provider: 'openai', model: 'gpt-5-codex', openaiApiType: 'responses' },\n 'duo-chat-gpt-5-2-codex': {\n provider: 'openai',\n model: 'gpt-5.2-codex',\n openaiApiType: 'responses',\n },\n};\n\nexport function getModelMapping(modelId: string): ModelMapping | undefined {\n return MODEL_MAPPINGS[modelId];\n}\n\nexport function getProviderForModelId(modelId: string): ModelProvider | undefined {\n return MODEL_MAPPINGS[modelId]?.provider;\n}\n\nexport function getValidModelsForProvider(provider: ModelProvider): string[] {\n return Object.values(MODEL_MAPPINGS)\n .filter((m) => m.provider === provider)\n .map((m) => m.model);\n}\n\nexport function getAnthropicModelForModelId(modelId: string): string | undefined {\n const mapping = MODEL_MAPPINGS[modelId];\n return mapping?.provider === 'anthropic' ? mapping.model : undefined;\n}\n\nexport function getOpenAIModelForModelId(modelId: string): string | undefined {\n const mapping = MODEL_MAPPINGS[modelId];\n return mapping?.provider === 'openai' ? mapping.model : undefined;\n}\n\nexport function getOpenAIApiType(modelId: string): OpenAIApiType {\n const mapping = MODEL_MAPPINGS[modelId];\n return mapping?.openaiApiType ?? 'chat';\n}\n\nexport function isResponsesApiModel(modelId: string): boolean {\n return getOpenAIApiType(modelId) === 'responses';\n}\n\nexport const MODEL_ID_TO_ANTHROPIC_MODEL: Record<string, string> = Object.fromEntries(\n Object.entries(MODEL_MAPPINGS)\n .filter(([, v]) => v.provider === 'anthropic')\n .map(([k, v]) => [k, v.model])\n);\n","/**\n * OAuth types and constants for GitLab authentication\n * Based on gitlab-vscode-extension and gitlab-lsp patterns\n */\n\nexport interface GitLabOAuthTokens {\n accessToken: string;\n refreshToken: string;\n expiresAt: number; // Unix timestamp in milliseconds\n instanceUrl: string;\n}\n\nexport interface OpenCodeAuthOAuth {\n type: 'oauth';\n refresh: string;\n access: string;\n expires: number; // Unix timestamp in milliseconds\n instanceUrl?: string;\n}\n\nexport interface OpenCodeAuthApi {\n type: 'api';\n key: string;\n}\n\nexport type OpenCodeAuth = OpenCodeAuthOAuth | OpenCodeAuthApi;\n\n/**\n * Bundled OAuth client ID for GitLab.com\n * Same as used in gitlab-vscode-extension\n */\nexport const BUNDLED_CLIENT_ID = '36f2a70cddeb5a0889d4fd8295c241b7e9848e89cf9e599d0eed2d8e5350fbf5';\n\n/**\n * GitLab.com URL constant\n */\nexport const GITLAB_COM_URL = 'https://gitlab.com';\n\n/**\n * Token expiry skew in milliseconds (5 minutes)\n * Refresh tokens this many milliseconds before they expire\n */\nexport const TOKEN_EXPIRY_SKEW_MS = 5 * 60 * 1000;\n\n/**\n * OAuth scopes to request\n */\nexport const OAUTH_SCOPES = ['api'];\n","/**\n * GitLab OAuth Manager\n * Handles OAuth token management, refresh, and exchange\n * Based on gitlab-vscode-extension TokenExchangeService and gitlab-lsp OAuthClientProvider\n */\n\nimport { GitLabError } from './gitlab-error';\nimport type { GitLabOAuthTokenResponse } from './gitlab-api-types';\nimport {\n type GitLabOAuthTokens,\n TOKEN_EXPIRY_SKEW_MS,\n BUNDLED_CLIENT_ID,\n GITLAB_COM_URL,\n} from './gitlab-oauth-types';\n\nexport interface TokenExchangeParams {\n instanceUrl: string;\n clientId?: string;\n redirectUri?: string;\n}\n\nexport interface AuthorizationCodeParams extends TokenExchangeParams {\n code: string;\n codeVerifier: string;\n}\n\nexport interface RefreshTokenParams extends TokenExchangeParams {\n refreshToken: string;\n}\n\nexport class GitLabOAuthManager {\n private fetch: typeof fetch;\n\n constructor(fetchImpl: typeof fetch = fetch) {\n this.fetch = fetchImpl;\n }\n\n /**\n * Check if a token is expired\n */\n isTokenExpired(expiresAt: number): boolean {\n return Date.now() >= expiresAt;\n }\n\n /**\n * Check if a token needs refresh (within skew window)\n */\n needsRefresh(expiresAt: number): boolean {\n return Date.now() >= expiresAt - TOKEN_EXPIRY_SKEW_MS;\n }\n\n /**\n * Refresh tokens if needed\n * Returns the same tokens if refresh is not needed, or new tokens if refreshed\n */\n async refreshIfNeeded(tokens: GitLabOAuthTokens, clientId?: string): Promise<GitLabOAuthTokens> {\n if (!this.needsRefresh(tokens.expiresAt)) {\n return tokens;\n }\n\n if (this.isTokenExpired(tokens.expiresAt)) {\n throw new GitLabError({\n message: 'OAuth token has expired and cannot be used',\n });\n }\n\n return this.exchangeRefreshToken({\n instanceUrl: tokens.instanceUrl,\n refreshToken: tokens.refreshToken,\n clientId,\n });\n }\n\n /**\n * Exchange authorization code for tokens\n * Based on gitlab-vscode-extension createOAuthAccountFromCode\n */\n async exchangeAuthorizationCode(params: AuthorizationCodeParams): Promise<GitLabOAuthTokens> {\n const { instanceUrl, code, codeVerifier, clientId, redirectUri } = params;\n\n const tokenResponse = await this.exchangeToken({\n instanceUrl,\n grantType: 'authorization_code',\n code,\n codeVerifier,\n clientId: clientId || this.getClientId(instanceUrl),\n redirectUri,\n });\n\n return this.createTokensFromResponse(tokenResponse, instanceUrl);\n }\n\n /**\n * Exchange refresh token for new tokens\n * Based on gitlab-vscode-extension TokenExchangeService\n */\n async exchangeRefreshToken(params: RefreshTokenParams): Promise<GitLabOAuthTokens> {\n const { instanceUrl, refreshToken, clientId } = params;\n\n const tokenResponse = await this.exchangeToken({\n instanceUrl,\n grantType: 'refresh_token',\n refreshToken,\n clientId: clientId || this.getClientId(instanceUrl),\n });\n\n return this.createTokensFromResponse(tokenResponse, instanceUrl);\n }\n\n /**\n * Get the OAuth client ID for an instance\n */\n private getClientId(instanceUrl: string): string {\n // Use bundled client ID for GitLab.com\n if (instanceUrl === GITLAB_COM_URL) {\n return BUNDLED_CLIENT_ID;\n }\n\n throw new GitLabError({\n message: `No OAuth client ID configured for instance ${instanceUrl}. Please provide a clientId parameter.`,\n });\n }\n\n /**\n * Exchange token with GitLab OAuth endpoint\n * Based on gitlab-vscode-extension GitLabService.exchangeToken\n */\n private async exchangeToken(params: {\n instanceUrl: string;\n grantType: 'authorization_code' | 'refresh_token';\n code?: string;\n codeVerifier?: string;\n refreshToken?: string;\n clientId: string;\n redirectUri?: string;\n }): Promise<GitLabOAuthTokenResponse> {\n const { instanceUrl, grantType, code, codeVerifier, refreshToken, clientId, redirectUri } =\n params;\n\n const body: Record<string, string> = {\n client_id: clientId,\n grant_type: grantType,\n };\n\n if (grantType === 'authorization_code') {\n if (!code || !codeVerifier || !redirectUri) {\n throw new GitLabError({\n message:\n 'Authorization code, code verifier, and redirect URI are required for authorization_code grant',\n });\n }\n body.code = code;\n body.code_verifier = codeVerifier;\n body.redirect_uri = redirectUri;\n } else if (grantType === 'refresh_token') {\n if (!refreshToken) {\n throw new GitLabError({\n message: 'Refresh token is required for refresh_token grant',\n });\n }\n body.refresh_token = refreshToken;\n }\n\n const url = `${instanceUrl}/oauth/token`;\n\n try {\n const response = await this.fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n },\n body: new URLSearchParams(body).toString(),\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new GitLabError({\n message: `OAuth token exchange failed: ${response.status} ${response.statusText}`,\n cause: new Error(errorText),\n });\n }\n\n const data = await response.json();\n return data as GitLabOAuthTokenResponse;\n } catch (error) {\n if (error instanceof GitLabError) {\n throw error;\n }\n throw new GitLabError({\n message: `Failed to exchange OAuth token: ${error instanceof Error ? error.message : String(error)}`,\n cause: error instanceof Error ? error : undefined,\n });\n }\n }\n\n /**\n * Create GitLabOAuthTokens from token response\n */\n private createTokensFromResponse(\n response: GitLabOAuthTokenResponse,\n instanceUrl: string\n ): GitLabOAuthTokens {\n const expiresAt = this.createExpiresTimestamp(response);\n\n return {\n accessToken: response.access_token,\n refreshToken: response.refresh_token || '',\n expiresAt,\n instanceUrl,\n };\n }\n\n /**\n * Create expiry timestamp from token response\n * Based on gitlab-vscode-extension createExpiresTimestamp\n */\n private createExpiresTimestamp(response: GitLabOAuthTokenResponse): number {\n // GitLab returns created_at (Unix timestamp in seconds) and expires_in (seconds)\n const createdAt = response.created_at * 1000; // Convert to milliseconds\n const expiresIn = response.expires_in * 1000; // Convert to milliseconds\n return createdAt + expiresIn;\n }\n}\n","// Version string of this package injected at build time.\ndeclare const __PACKAGE_VERSION__: string | undefined;\nexport const VERSION: string =\n typeof __PACKAGE_VERSION__ !== 'undefined' ? __PACKAGE_VERSION__ : '0.0.0-dev';\n","import { GitLabAnthropicLanguageModel } from './gitlab-anthropic-language-model';\nimport { GitLabOpenAILanguageModel } from './gitlab-openai-language-model';\nimport { GitLabError } from './gitlab-error';\nimport type { LanguageModelV2 } from '@ai-sdk/provider';\nimport { GitLabOAuthManager } from './gitlab-oauth-manager';\nimport type { OpenCodeAuth } from './gitlab-oauth-types';\nimport { getModelMapping, getValidModelsForProvider } from './model-mappings';\nimport { VERSION } from './version';\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport * as os from 'os';\n\nexport interface GitLabProvider {\n (modelId: string): LanguageModelV2;\n readonly specificationVersion: 'v2';\n languageModel(modelId: string): LanguageModelV2;\n chat(modelId: string): LanguageModelV2;\n /**\n * Create an agentic chat model with tool calling support\n *\n * @param modelId - GitLab model identifier. Some IDs automatically map to specific Anthropic models.\n * @param options - Configuration options for the agentic model\n * @returns A language model with native tool calling support via Anthropic\n *\n * @example\n * // Automatic model mapping\n * const model = gitlab.agenticChat('duo-chat-opus-4-5');\n * // Uses claude-opus-4-5-20251101\n *\n * @example\n * // Explicit model override\n * const model = gitlab.agenticChat('duo-chat', {\n * anthropicModel: 'claude-sonnet-4-5-20250929'\n * });\n */\n agenticChat(modelId: string, options?: GitLabAgenticOptions): GitLabAnthropicLanguageModel;\n textEmbeddingModel(modelId: string): never;\n imageModel(modelId: string): never;\n}\n\nexport interface GitLabAgenticOptions {\n /**\n * Override the provider-specific model (optional).\n * Must be a valid model for the detected provider.\n *\n * For Anthropic models:\n * - 'claude-opus-4-5-20251101'\n * - 'claude-sonnet-4-5-20250929'\n * - 'claude-haiku-4-5-20251001'\n *\n * For OpenAI models:\n * - 'gpt-5.1-2025-11-13'\n * - 'gpt-5-mini-2025-08-07'\n * - 'gpt-5-codex'\n * - 'gpt-5.2-codex'\n *\n * @example\n * // Override with explicit model\n * const model = gitlab.agenticChat('duo-chat-opus-4-5', {\n * providerModel: 'claude-sonnet-4-5-20250929'\n * });\n */\n providerModel?: string;\n\n /**\n * Maximum tokens to generate\n * @default 8192\n */\n maxTokens?: number;\n\n /**\n * Feature flags to pass to the GitLab API\n */\n featureFlags?: Record<string, boolean>;\n\n /**\n * Custom headers for AI Gateway requests (per-model override).\n * These headers are sent to the Anthropic/OpenAI proxy endpoints.\n * Merged with provider-level aiGatewayHeaders (model-level takes precedence).\n */\n aiGatewayHeaders?: Record<string, string>;\n}\n\nexport interface GitLabProviderSettings {\n /**\n * GitLab instance URL (e.g., 'https://gitlab.com')\n * @default 'https://gitlab.com'\n */\n instanceUrl?: string;\n\n /**\n * API token (Personal Access Token or OAuth access token)\n * Can also be set via GITLAB_TOKEN environment variable\n */\n apiKey?: string;\n\n /**\n * OAuth refresh token (optional, for OAuth flow)\n */\n refreshToken?: string;\n\n /**\n * OAuth client ID (required for OAuth flow)\n */\n clientId?: string;\n\n /**\n * OAuth redirect URI (required for OAuth flow)\n */\n redirectUri?: string;\n\n /**\n * Custom headers to include in requests\n */\n headers?: Record<string, string>;\n\n /**\n * Custom fetch implementation\n */\n fetch?: typeof fetch;\n\n /**\n * Provider name override\n */\n name?: string;\n\n /**\n * Default feature flags to pass to the GitLab API for all agentic chat models\n */\n featureFlags?: Record<string, boolean>;\n\n /**\n * AI Gateway URL for the Anthropic proxy.\n * Can also be set via GITLAB_AI_GATEWAY_URL environment variable.\n * @default 'https://cloud.gitlab.com'\n */\n aiGatewayUrl?: string;\n\n /**\n * Custom headers to include in AI Gateway requests (Anthropic/OpenAI proxy).\n * These headers are merged with the default headers from direct_access response.\n * Default User-Agent: gitlab-ai-provider/{version}\n */\n aiGatewayHeaders?: Record<string, string>;\n}\n\n/**\n * Get OpenCode auth file path\n * Uses XDG Base Directory specification\n */\nfunction getOpenCodeAuthPath(): string {\n const homeDir = os.homedir();\n\n // Check XDG_DATA_HOME first (Linux/Mac standard)\n const xdgDataHome = process.env.XDG_DATA_HOME;\n if (xdgDataHome) {\n return path.join(xdgDataHome, 'opencode', 'auth.json');\n }\n\n // Fallback to ~/.local/share/opencode/auth.json (XDG default)\n if (process.platform !== 'win32') {\n return path.join(homeDir, '.local', 'share', 'opencode', 'auth.json');\n }\n\n // Windows fallback\n return path.join(homeDir, '.opencode', 'auth.json');\n}\n\n/**\n * Load OpenCode auth.json file\n */\nasync function loadOpenCodeAuth(instanceUrl: string): Promise<OpenCodeAuth | undefined> {\n try {\n const authPath = getOpenCodeAuthPath();\n\n if (!fs.existsSync(authPath)) {\n return undefined;\n }\n\n const authData = JSON.parse(fs.readFileSync(authPath, 'utf-8'));\n\n // Priority 1: Check 'gitlab' key (used by opencode-gitlab-auth plugin)\n if (authData.gitlab?.type === 'oauth') {\n const gitlabAuth = authData.gitlab;\n // Verify it matches the requested instance URL\n if (\n gitlabAuth.enterpriseUrl === instanceUrl ||\n gitlabAuth.enterpriseUrl === instanceUrl.replace(/\\/$/, '')\n ) {\n return gitlabAuth as OpenCodeAuth;\n }\n }\n\n // Priority 2: Try to find auth for this instance by URL\n // Check both with and without trailing slash\n const normalizedUrl = instanceUrl.replace(/\\/$/, '');\n const auth = authData[normalizedUrl] || authData[`${normalizedUrl}/`];\n\n return auth as OpenCodeAuth | undefined;\n } catch (error) {\n // Silently fail if we can't read auth.json\n return undefined;\n }\n}\n\n/**\n * Load GitLab API key with OAuth support\n * Priority: explicit apiKey > OAuth token > env var\n */\nasync function loadApiKey(\n options: {\n apiKey?: string;\n environmentVariableName: string;\n description: string;\n },\n instanceUrl: string,\n clientId?: string\n): Promise<string> {\n // Priority 1: Explicit apiKey\n if (options.apiKey) {\n return options.apiKey;\n }\n\n // Priority 2: OAuth token from OpenCode auth.json\n const auth = await loadOpenCodeAuth(instanceUrl);\n if (auth?.type === 'oauth') {\n const oauthManager = new GitLabOAuthManager();\n\n // Check if token needs refresh\n if (oauthManager.needsRefresh(auth.expires)) {\n try {\n const refreshed = await oauthManager.exchangeRefreshToken({\n instanceUrl,\n refreshToken: auth.refresh,\n clientId,\n });\n\n // Update stored token\n const authPath = getOpenCodeAuthPath();\n const authData = JSON.parse(fs.readFileSync(authPath, 'utf-8'));\n const normalizedUrl = instanceUrl.replace(/\\/$/, '');\n\n authData[normalizedUrl] = {\n type: 'oauth',\n refresh: refreshed.refreshToken,\n access: refreshed.accessToken,\n expires: refreshed.expiresAt,\n instanceUrl,\n };\n\n fs.writeFileSync(authPath, JSON.stringify(authData, null, 2));\n\n return refreshed.accessToken;\n } catch (error) {\n // If refresh fails, fall through to env var\n console.warn(\n `Failed to refresh OAuth token: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n } else {\n return auth.access;\n }\n }\n\n // Priority 3: Environment variable\n const apiKey = process.env[options.environmentVariableName];\n\n if (!apiKey) {\n throw new GitLabError({\n message: `${options.description} API key is missing. Pass it as the 'apiKey' parameter, set the ${options.environmentVariableName} environment variable, or authenticate with 'opencode auth login gitlab'.`,\n });\n }\n\n return apiKey;\n}\n\nfunction withUserAgentSuffix(\n headers: Record<string, string>,\n suffix: string\n): Record<string, string> {\n const userAgent = headers['User-Agent'];\n return {\n ...headers,\n 'User-Agent': userAgent ? `${userAgent} ${suffix}` : suffix,\n };\n}\n\nexport function createGitLab(options: GitLabProviderSettings = {}): GitLabProvider {\n const instanceUrl = options.instanceUrl ?? 'https://gitlab.com';\n const providerName = options.name ?? 'gitlab';\n\n // Cache for the API key - loaded lazily on first use\n let cachedApiKey: string | undefined;\n let apiKeyPromise: Promise<string> | undefined;\n\n const getApiKey = async (): Promise<string> => {\n if (cachedApiKey) {\n return cachedApiKey;\n }\n\n if (apiKeyPromise) {\n return apiKeyPromise;\n }\n\n apiKeyPromise = loadApiKey(\n {\n apiKey: options.apiKey,\n environmentVariableName: 'GITLAB_TOKEN',\n description: 'GitLab',\n },\n instanceUrl,\n options.clientId\n );\n\n cachedApiKey = await apiKeyPromise;\n apiKeyPromise = undefined;\n return cachedApiKey;\n };\n\n /**\n * Refresh the API key by clearing the cache and re-fetching from auth provider.\n * This is called when a 401 error occurs to trigger OAuth token refresh.\n */\n const refreshApiKey = async (): Promise<void> => {\n // Clear the cached API key to force a refresh\n cachedApiKey = undefined;\n apiKeyPromise = undefined;\n\n // Re-fetch the API key (this will trigger the auth plugin's loader() which handles token refresh)\n cachedApiKey = await getApiKey();\n };\n\n const getHeaders = () => {\n // For synchronous access, we need to have the key already loaded\n // or fall back to env var/explicit key\n const apiKey = cachedApiKey || options.apiKey || process.env['GITLAB_TOKEN'] || '';\n\n if (!apiKey) {\n throw new GitLabError({\n message:\n \"GitLab API key is missing. Pass it as the 'apiKey' parameter, set the GITLAB_TOKEN environment variable, or authenticate with 'opencode auth login gitlab'.\",\n });\n }\n\n return withUserAgentSuffix(\n {\n Authorization: `Bearer ${apiKey}`,\n 'Content-Type': 'application/json',\n ...options.headers,\n },\n `ai-sdk-gitlab/${VERSION}`\n );\n };\n\n // Pre-load the API key asynchronously\n getApiKey().catch(() => {\n // Silently fail - will be caught when getHeaders is called\n });\n\n const createAgenticChatModel = (modelId: string, agenticOptions?: GitLabAgenticOptions) => {\n const mapping = getModelMapping(modelId);\n\n if (!mapping) {\n throw new GitLabError({\n message: `Unknown model ID: ${modelId}. Model must be registered in MODEL_MAPPINGS.`,\n });\n }\n\n if (agenticOptions?.providerModel) {\n const validModels = getValidModelsForProvider(mapping.provider);\n if (!validModels.includes(agenticOptions.providerModel)) {\n throw new GitLabError({\n message: `Invalid providerModel '${agenticOptions.providerModel}' for provider '${mapping.provider}'. Valid models: ${validModels.join(', ')}`,\n });\n }\n }\n\n const featureFlags = {\n DuoAgentPlatformNext: true as const,\n ...options.featureFlags,\n ...agenticOptions?.featureFlags,\n };\n\n const defaultAiGatewayHeaders = {\n 'User-Agent': `gitlab-ai-provider/${VERSION}`,\n };\n\n const aiGatewayHeaders = {\n ...defaultAiGatewayHeaders,\n ...options.aiGatewayHeaders,\n ...agenticOptions?.aiGatewayHeaders,\n };\n\n const baseConfig = {\n provider: `${providerName}.agentic`,\n instanceUrl,\n getHeaders,\n refreshApiKey,\n fetch: options.fetch,\n maxTokens: agenticOptions?.maxTokens,\n featureFlags,\n aiGatewayUrl: options.aiGatewayUrl,\n aiGatewayHeaders,\n };\n\n if (mapping.provider === 'openai') {\n return new GitLabOpenAILanguageModel(modelId, {\n ...baseConfig,\n openaiModel: agenticOptions?.providerModel ?? mapping.model,\n });\n }\n\n return new GitLabAnthropicLanguageModel(modelId, {\n ...baseConfig,\n anthropicModel: agenticOptions?.providerModel ?? mapping.model,\n });\n };\n\n // Default model factory - uses Anthropic backend for tool support\n const createDefaultModel = (modelId: string): LanguageModelV2 => {\n // Use Anthropic-based model by default for all models to get tool support\n return createAgenticChatModel(modelId);\n };\n\n const provider = Object.assign((modelId: string) => createDefaultModel(modelId), {\n specificationVersion: 'v2' as const,\n languageModel: createDefaultModel,\n chat: createDefaultModel,\n agenticChat: createAgenticChatModel,\n }) as GitLabProvider;\n\n // Unsupported model types\n provider.textEmbeddingModel = (modelId: string) => {\n throw new GitLabError({\n message: `GitLab provider does not support text embedding models. Model ID: ${modelId}`,\n });\n };\n\n provider.imageModel = (modelId: string) => {\n throw new GitLabError({\n message: `GitLab provider does not support image models. Model ID: ${modelId}`,\n });\n };\n\n return provider;\n}\n\n/**\n * Default GitLab Duo provider instance\n *\n * @example\n * ```typescript\n * import { gitlab } from '@ai-sdk/gitlab';\n *\n * const model = gitlab('duo-chat');\n * ```\n */\nexport const gitlab = createGitLab();\n","import { spawn } from 'child_process';\nimport * as path from 'path';\nimport { GitLabProjectCache, type GitLabProject } from './gitlab-project-cache';\nimport { GitLabError } from './gitlab-error';\n\n// Noop debug function (workflow debug removed)\nconst debugLog = (..._args: unknown[]) => {};\n\nexport interface GitLabProjectDetectorConfig {\n instanceUrl: string;\n getHeaders: () => Record<string, string>;\n fetch?: typeof fetch;\n cache?: GitLabProjectCache;\n gitTimeout?: number;\n}\n\n/**\n * Detects GitLab project information from git remote URLs\n *\n * This class provides functionality to:\n * - Parse git remote URLs (SSH, HTTPS, custom domains)\n * - Execute git commands to get remote URLs\n * - Fetch project details from GitLab API\n * - Cache project information to avoid repeated API calls\n */\nexport class GitLabProjectDetector {\n private readonly config: GitLabProjectDetectorConfig;\n private readonly fetchFn: typeof fetch;\n private readonly cache: GitLabProjectCache;\n\n constructor(config: GitLabProjectDetectorConfig) {\n this.config = {\n gitTimeout: 5000, // 5 seconds default\n ...config,\n };\n this.fetchFn = config.fetch ?? fetch;\n this.cache = config.cache ?? new GitLabProjectCache();\n }\n\n /**\n * Auto-detect GitLab project from git remote in the working directory\n *\n * @param workingDirectory - The directory to check for git remote\n * @param remoteName - The git remote name to use (default: 'origin')\n * @returns The detected project or null if detection fails\n */\n async detectProject(\n workingDirectory: string,\n remoteName: string = 'origin'\n ): Promise<GitLabProject | null> {\n // 1. Check cache first\n const cacheKey = path.resolve(workingDirectory);\n const cached = this.cache.get(cacheKey);\n if (cached) {\n return cached;\n }\n\n try {\n // 2. Get git remote URL\n debugLog(`[GitLabProjectDetector] Getting git remote URL from: ${workingDirectory}`);\n const remoteUrl = await this.getGitRemoteUrl(workingDirectory, remoteName);\n if (!remoteUrl) {\n debugLog(`[GitLabProjectDetector] No git remote URL found`);\n return null; // Not a git repo or no remote\n }\n debugLog(`[GitLabProjectDetector] Git remote URL: ${remoteUrl}`);\n\n // 3. Parse project path from URL\n debugLog(\n `[GitLabProjectDetector] Parsing project path from URL (instance: ${this.config.instanceUrl})`\n );\n const projectPath = this.parseGitRemoteUrl(remoteUrl, this.config.instanceUrl);\n if (!projectPath) {\n debugLog(\n `[GitLabProjectDetector] Could not parse project path from URL (remote doesn't match instance)`\n );\n return null; // Remote doesn't match instance\n }\n debugLog(`[GitLabProjectDetector] Parsed project path: ${projectPath}`);\n\n // 4. Fetch project from GitLab API\n debugLog(`[GitLabProjectDetector] Fetching project from GitLab API: ${projectPath}`);\n const project = await this.getProjectByPath(projectPath);\n debugLog(`[GitLabProjectDetector] ✓ Project fetched successfully:`, project);\n\n // 5. Cache the result\n this.cache.set(cacheKey, project);\n\n return project;\n } catch (error) {\n // Log error but don't throw - graceful degradation\n if (error instanceof GitLabError) {\n // GitLab API errors are expected (e.g., project not found)\n debugLog(`[GitLabProjectDetector] GitLab API error:`, error.message || error);\n return null;\n }\n // Log unexpected errors for debugging\n debugLog(`[GitLabProjectDetector] Unexpected error:`, error);\n console.warn(`Failed to auto-detect GitLab project: ${error}`);\n return null;\n }\n }\n\n /**\n * Parse a git remote URL to extract the project path\n *\n * Supports:\n * - SSH: git@gitlab.com:namespace/project.git\n * - HTTPS: https://gitlab.com/namespace/project.git\n * - HTTP: http://gitlab.local/namespace/project.git\n * - Custom domains and ports\n *\n * @param remoteUrl - The git remote URL\n * @param instanceUrl - The GitLab instance URL to match against\n * @returns The project path (e.g., \"namespace/project\") or null if parsing fails\n */\n parseGitRemoteUrl(remoteUrl: string, instanceUrl: string): string | null {\n try {\n // Extract hostname from instanceUrl\n const instanceHost = new URL(instanceUrl).hostname;\n\n // SSH format: git@host:path.git or git@host:port/path.git\n const sshMatch = remoteUrl.match(/^git@([^:]+):(.+?)(?:\\.git)?$/);\n if (sshMatch) {\n const [, host, pathPart] = sshMatch;\n // Handle port in SSH URLs (git@host:port/path)\n const hostWithoutPort = host.split(':')[0];\n if (hostWithoutPort === instanceHost) {\n // Remove port from path if present\n const cleanPath = pathPart.replace(/^\\d+\\//, '');\n return cleanPath.endsWith('.git') ? cleanPath.slice(0, -4) : cleanPath;\n }\n }\n\n // HTTPS/HTTP format: https://host/path.git or https://host:port/path.git\n const httpsMatch = remoteUrl.match(/^(https?):\\/\\/([^/]+)\\/(.+?)(?:\\.git)?$/);\n if (httpsMatch) {\n const [, , hostWithPort, pathPart] = httpsMatch;\n const host = hostWithPort.split(':')[0];\n if (host === instanceHost) {\n return pathPart.endsWith('.git') ? pathPart.slice(0, -4) : pathPart;\n }\n }\n\n return null;\n } catch (error) {\n // URL parsing failed\n return null;\n }\n }\n\n /**\n * Get the git remote URL from a working directory\n *\n * @param workingDirectory - The directory to check\n * @param remoteName - The git remote name (default: 'origin')\n * @returns The remote URL or null if not found\n */\n async getGitRemoteUrl(\n workingDirectory: string,\n remoteName: string = 'origin'\n ): Promise<string | null> {\n return new Promise((resolve) => {\n const child = spawn('git', ['config', '--get', `remote.${remoteName}.url`], {\n cwd: workingDirectory,\n timeout: this.config.gitTimeout,\n });\n\n let stdout = '';\n let _stderr = '';\n\n child.stdout?.on('data', (data) => {\n stdout += data.toString();\n });\n\n child.stderr?.on('data', (data) => {\n _stderr += data.toString();\n });\n\n child.on('close', (exitCode) => {\n if (exitCode === 0 && stdout.trim()) {\n resolve(stdout.trim());\n } else {\n resolve(null);\n }\n });\n\n child.on('error', () => {\n // Git not available or command failed\n resolve(null);\n });\n });\n }\n\n /**\n * Fetch project details from GitLab API by project path\n *\n * @param projectPath - The project path (e.g., \"namespace/project\")\n * @returns The project details\n * @throws GitLabError if the API call fails\n */\n async getProjectByPath(projectPath: string): Promise<GitLabProject> {\n // URL-encode the project path\n const encodedPath = encodeURIComponent(projectPath);\n const url = `${this.config.instanceUrl}/api/v4/projects/${encodedPath}`;\n\n try {\n const response = await this.fetchFn(url, {\n method: 'GET',\n headers: this.config.getHeaders(),\n });\n\n if (!response.ok) {\n throw new GitLabError({\n message: `Failed to fetch project '${projectPath}': ${response.status} ${response.statusText}`,\n });\n }\n\n const data = (await response.json()) as {\n id: number;\n path: string;\n path_with_namespace: string;\n name: string;\n namespace?: { id: number };\n };\n\n return {\n id: data.id,\n path: data.path,\n pathWithNamespace: data.path_with_namespace,\n name: data.name,\n namespaceId: data.namespace?.id,\n };\n } catch (error) {\n if (error instanceof GitLabError) {\n throw error;\n }\n throw new GitLabError({\n message: `Failed to fetch project '${projectPath}': ${error}`,\n cause: error,\n });\n }\n }\n\n /**\n * Clear the project cache\n */\n clearCache(): void {\n this.cache.clear();\n }\n\n /**\n * Get the cache instance (useful for testing)\n */\n getCache(): GitLabProjectCache {\n return this.cache;\n }\n}\n","/**\n * Simple in-memory cache for GitLab project information\n * Used to avoid repeated API calls when detecting projects from git remotes\n */\n\nexport interface GitLabProject {\n id: number;\n path: string;\n pathWithNamespace: string;\n name: string;\n namespaceId?: number;\n}\n\ninterface CacheEntry {\n project: GitLabProject;\n expiresAt: number;\n}\n\n/**\n * In-memory cache for GitLab project information with TTL support\n */\nexport class GitLabProjectCache {\n private cache = new Map<string, CacheEntry>();\n private defaultTTL: number;\n\n /**\n * Create a new project cache\n * @param defaultTTL - Default time-to-live in milliseconds (default: 5 minutes)\n */\n constructor(defaultTTL: number = 5 * 60 * 1000) {\n this.defaultTTL = defaultTTL;\n }\n\n /**\n * Get a cached project by key\n * @param key - Cache key (typically the working directory path)\n * @returns The cached project or null if not found or expired\n */\n get(key: string): GitLabProject | null {\n const entry = this.cache.get(key);\n if (!entry) {\n return null;\n }\n\n // Check if entry has expired\n if (Date.now() > entry.expiresAt) {\n this.cache.delete(key);\n return null;\n }\n\n return entry.project;\n }\n\n /**\n * Store a project in the cache\n * @param key - Cache key (typically the working directory path)\n * @param project - The project to cache\n * @param ttl - Optional custom TTL in milliseconds\n */\n set(key: string, project: GitLabProject, ttl?: number): void {\n this.cache.set(key, {\n project,\n expiresAt: Date.now() + (ttl ?? this.defaultTTL),\n });\n }\n\n /**\n * Check if a key exists in the cache (and is not expired)\n * @param key - Cache key to check\n * @returns true if the key exists and is not expired\n */\n has(key: string): boolean {\n return this.get(key) !== null;\n }\n\n /**\n * Remove a specific entry from the cache\n * @param key - Cache key to remove\n */\n delete(key: string): void {\n this.cache.delete(key);\n }\n\n /**\n * Clear all entries from the cache\n */\n clear(): void {\n this.cache.clear();\n }\n\n /**\n * Get the number of entries in the cache (including expired ones)\n */\n get size(): number {\n return this.cache.size;\n }\n\n /**\n * Clean up expired entries from the cache\n * This is useful for long-running processes to prevent memory leaks\n */\n cleanup(): void {\n const now = Date.now();\n for (const [key, entry] of this.cache.entries()) {\n if (now > entry.expiresAt) {\n this.cache.delete(key);\n }\n }\n }\n}\n"],"mappings":"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","names":["Anthropic","resolve","OpenAI","hasToolCalls","path","resolve"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/gitlab-anthropic-language-model.ts","../src/gitlab-direct-access.ts","../src/gitlab-error.ts","../src/gitlab-openai-language-model.ts","../src/model-mappings.ts","../src/gitlab-oauth-types.ts","../src/gitlab-oauth-manager.ts","../src/version.ts","../src/gitlab-provider.ts","../src/gitlab-project-detector.ts","../src/gitlab-project-cache.ts"],"sourcesContent":["// Main exports\nexport { createGitLab, gitlab } from './gitlab-provider';\nexport { VERSION } from './version';\nexport type {\n GitLabProvider,\n GitLabProviderSettings,\n GitLabAgenticOptions,\n} from './gitlab-provider';\n\n// Model exports\nexport { GitLabAnthropicLanguageModel } from './gitlab-anthropic-language-model';\nexport type { GitLabAnthropicConfig } from './gitlab-anthropic-language-model';\nexport { GitLabOpenAILanguageModel } from './gitlab-openai-language-model';\nexport type { GitLabOpenAIConfig } from './gitlab-openai-language-model';\n\n// Model mappings exports\nexport {\n MODEL_MAPPINGS,\n MODEL_ID_TO_ANTHROPIC_MODEL,\n getModelMapping,\n getProviderForModelId,\n getValidModelsForProvider,\n getAnthropicModelForModelId,\n getOpenAIModelForModelId,\n getOpenAIApiType,\n isResponsesApiModel,\n} from './model-mappings';\nexport type { ModelProvider, ModelMapping, OpenAIApiType } from './model-mappings';\n\n// Error exports\nexport { GitLabError } from './gitlab-error';\nexport type { GitLabErrorOptions } from './gitlab-error';\n\n// API types exports\nexport type { GitLabOAuthTokenResponse } from './gitlab-api-types';\n\n// OAuth exports\nexport { GitLabOAuthManager } from './gitlab-oauth-manager';\nexport type {\n GitLabOAuthTokens,\n OpenCodeAuth,\n OpenCodeAuthOAuth,\n OpenCodeAuthApi,\n} from './gitlab-oauth-types';\nexport {\n BUNDLED_CLIENT_ID,\n GITLAB_COM_URL,\n TOKEN_EXPIRY_SKEW_MS,\n OAUTH_SCOPES,\n} from './gitlab-oauth-types';\n\n// Project detection exports\nexport { GitLabProjectDetector } from './gitlab-project-detector';\nexport type { GitLabProjectDetectorConfig } from './gitlab-project-detector';\nexport { GitLabProjectCache } from './gitlab-project-cache';\nexport type { GitLabProject } from './gitlab-project-cache';\n\n// Direct access exports\nexport { GitLabDirectAccessClient, DEFAULT_AI_GATEWAY_URL } from './gitlab-direct-access';\nexport type { GitLabDirectAccessConfig, DirectAccessToken } from './gitlab-direct-access';\n","import Anthropic from '@anthropic-ai/sdk';\nimport type { Tool } from '@anthropic-ai/sdk/resources/messages';\nimport { GitLabDirectAccessClient } from './gitlab-direct-access';\nimport { GitLabError } from './gitlab-error';\n\nimport type {\n LanguageModelV2,\n LanguageModelV2CallOptions,\n LanguageModelV2StreamPart,\n LanguageModelV2FinishReason,\n LanguageModelV2CallWarning,\n LanguageModelV2Content,\n LanguageModelV2Usage,\n LanguageModelV2FunctionTool,\n LanguageModelV2Message,\n LanguageModelV2ToolChoice,\n} from '@ai-sdk/provider';\n\nexport interface GitLabAnthropicConfig {\n provider: string;\n instanceUrl: string;\n getHeaders: () => Record<string, string>;\n fetch?: typeof fetch;\n\n /**\n * Optional callback to refresh the API key when a 401 error occurs.\n * Should clear cached credentials and re-fetch from auth provider.\n */\n refreshApiKey?: () => Promise<void>;\n\n /**\n * The Anthropic model to use (e.g., 'claude-sonnet-4-5-20250929')\n * @default 'claude-sonnet-4-5-20250929'\n */\n anthropicModel?: string;\n\n /**\n * Maximum tokens to generate\n * @default 8192\n */\n maxTokens?: number;\n\n /**\n * Feature flags to pass to the GitLab API\n * @default { DuoAgentPlatformNext: true }\n */\n featureFlags?: {\n DuoAgentPlatformNext: true;\n } & Record<string, boolean>;\n\n /**\n * AI Gateway URL for the Anthropic proxy.\n * Can also be set via GITLAB_AI_GATEWAY_URL environment variable.\n * @default 'https://cloud.gitlab.com'\n */\n aiGatewayUrl?: string;\n\n /**\n * Custom headers for AI Gateway Anthropic proxy requests.\n * Merged with headers from direct_access token response.\n */\n aiGatewayHeaders?: Record<string, string>;\n}\n\n/**\n * GitLab Anthropic Language Model\n *\n * This model uses GitLab's Anthropic proxy to provide native tool calling support\n * for the duo-chat model. It connects to Claude through GitLab's cloud proxy\n * at https://cloud.gitlab.com/ai/v1/proxy/anthropic/\n */\nexport class GitLabAnthropicLanguageModel implements LanguageModelV2 {\n readonly specificationVersion = 'v2' as const;\n readonly modelId: string;\n readonly supportedUrls: Record<string, RegExp[]> = {};\n\n private readonly config: GitLabAnthropicConfig;\n private readonly directAccessClient: GitLabDirectAccessClient;\n private anthropicClient: Anthropic | null = null;\n\n constructor(modelId: string, config: GitLabAnthropicConfig) {\n this.modelId = modelId;\n this.config = config;\n\n this.directAccessClient = new GitLabDirectAccessClient({\n instanceUrl: config.instanceUrl,\n getHeaders: config.getHeaders,\n refreshApiKey: config.refreshApiKey,\n fetch: config.fetch,\n featureFlags: config.featureFlags,\n aiGatewayUrl: config.aiGatewayUrl,\n });\n }\n\n get provider(): string {\n return this.config.provider;\n }\n\n /**\n * Get or create an Anthropic client with valid credentials\n * @param forceRefresh - If true, forces a token refresh before creating the client\n */\n private async getAnthropicClient(forceRefresh: boolean = false): Promise<Anthropic> {\n // Get token from GitLab (will use cache unless forceRefresh is true)\n const tokenData = await this.directAccessClient.getDirectAccessToken(forceRefresh);\n\n // Create new client with the token\n // GitLab's proxy expects:\n // - authToken: sets Authorization: Bearer header (NOT apiKey which sets x-api-key)\n // - defaultHeaders: additional headers from the direct access response\n // Filter out x-api-key from headers if present - we use authToken for Bearer auth\n const { 'x-api-key': _removed, ...filteredHeaders } = tokenData.headers;\n\n // Merge: tokenData headers < custom aiGatewayHeaders\n const mergedHeaders = {\n ...filteredHeaders,\n ...this.config.aiGatewayHeaders,\n };\n\n this.anthropicClient = new Anthropic({\n apiKey: null,\n authToken: tokenData.token,\n baseURL: this.directAccessClient.getAnthropicProxyUrl(),\n defaultHeaders: mergedHeaders,\n });\n\n return this.anthropicClient;\n }\n\n /**\n * Check if an error is a token-related authentication error that can be retried\n */\n private isTokenError(error: unknown): boolean {\n if (error instanceof Anthropic.APIError) {\n // 401 Unauthorized - token expired or revoked\n if (error.status === 401) {\n return true;\n }\n // Check for token-related error messages\n const message = error.message?.toLowerCase() || '';\n if (\n message.includes('token') &&\n (message.includes('expired') || message.includes('revoked') || message.includes('invalid'))\n ) {\n return true;\n }\n }\n return false;\n }\n\n /**\n * Check if an error is a context overflow error (prompt too long)\n * These should NOT trigger token refresh and should be reported to the user.\n */\n private isContextOverflowError(error: unknown): boolean {\n if (error instanceof Anthropic.APIError) {\n // 400 Bad Request with prompt too long message\n if (error.status === 400) {\n const message = error.message?.toLowerCase() || '';\n if (\n message.includes('prompt is too long') ||\n message.includes('prompt too long') ||\n (message.includes('tokens') && message.includes('maximum'))\n ) {\n return true;\n }\n }\n }\n return false;\n }\n\n /**\n * Convert AI SDK tools to Anthropic tool format\n */\n private convertTools(tools?: LanguageModelV2CallOptions['tools']): Tool[] | undefined {\n if (!tools || tools.length === 0) {\n return undefined;\n }\n\n return tools\n .filter((tool): tool is LanguageModelV2FunctionTool => tool.type === 'function')\n .map((tool) => {\n const schema = tool.inputSchema as { properties?: object; required?: string[] } | undefined;\n return {\n name: tool.name,\n description: tool.description || '',\n input_schema: {\n type: 'object' as const,\n properties: schema?.properties || {},\n required: schema?.required || [],\n },\n };\n });\n }\n\n /**\n * Convert AI SDK tool choice to Anthropic format\n */\n private convertToolChoice(\n toolChoice?: LanguageModelV2ToolChoice\n ): Anthropic.MessageCreateParams['tool_choice'] {\n if (!toolChoice) {\n return undefined;\n }\n\n switch (toolChoice.type) {\n case 'auto':\n return { type: 'auto' };\n case 'none':\n // Anthropic doesn't have a direct 'none' - we handle this by not sending tools\n return undefined;\n case 'required':\n return { type: 'any' };\n case 'tool':\n return { type: 'tool', name: toolChoice.toolName };\n default:\n return undefined;\n }\n }\n\n /**\n * Convert AI SDK prompt to Anthropic messages format\n */\n private convertPrompt(prompt: LanguageModelV2Message[]): {\n system?: string;\n messages: Anthropic.MessageParam[];\n } {\n let systemMessage: string | undefined;\n const messages: Anthropic.MessageParam[] = [];\n\n for (const message of prompt) {\n if (message.role === 'system') {\n systemMessage = message.content;\n continue;\n }\n\n if (message.role === 'user') {\n const content: Anthropic.ContentBlockParam[] = [];\n\n for (const part of message.content) {\n if (part.type === 'text') {\n content.push({ type: 'text', text: part.text });\n } else if (part.type === 'file') {\n // Handle file/image content if needed\n // For now, skip non-text content\n }\n }\n\n if (content.length > 0) {\n messages.push({ role: 'user', content });\n }\n } else if (message.role === 'assistant') {\n const content: Anthropic.ContentBlockParam[] = [];\n\n for (const part of message.content) {\n if (part.type === 'text') {\n content.push({ type: 'text', text: part.text });\n } else if (part.type === 'tool-call') {\n content.push({\n type: 'tool_use',\n id: part.toolCallId,\n name: part.toolName,\n input: typeof part.input === 'string' ? JSON.parse(part.input) : part.input,\n });\n }\n }\n\n if (content.length > 0) {\n messages.push({ role: 'assistant', content });\n }\n } else if (message.role === 'tool') {\n // Tool results need to be sent as user messages with tool_result content\n const content: Anthropic.ToolResultBlockParam[] = [];\n\n for (const part of message.content) {\n if (part.type === 'tool-result') {\n let resultContent: string;\n\n // Convert tool result output to string\n if (part.output.type === 'text') {\n resultContent = part.output.value;\n } else if (part.output.type === 'json') {\n resultContent = JSON.stringify(part.output.value);\n } else if (part.output.type === 'error-text') {\n resultContent = part.output.value;\n } else if (part.output.type === 'error-json') {\n resultContent = JSON.stringify(part.output.value);\n } else {\n resultContent = JSON.stringify(part.output);\n }\n\n content.push({\n type: 'tool_result',\n tool_use_id: part.toolCallId,\n content: resultContent,\n is_error: part.output.type.startsWith('error'),\n });\n }\n }\n\n if (content.length > 0) {\n messages.push({ role: 'user', content });\n }\n }\n }\n\n return { system: systemMessage, messages };\n }\n\n /**\n * Convert Anthropic finish reason to AI SDK format\n */\n private convertFinishReason(stopReason: string | null): LanguageModelV2FinishReason {\n switch (stopReason) {\n case 'end_turn':\n return 'stop';\n case 'stop_sequence':\n return 'stop';\n case 'max_tokens':\n return 'length';\n case 'tool_use':\n return 'tool-calls';\n default:\n return 'unknown';\n }\n }\n\n async doGenerate(options: LanguageModelV2CallOptions): Promise<{\n content: LanguageModelV2Content[];\n finishReason: LanguageModelV2FinishReason;\n usage: LanguageModelV2Usage;\n warnings: LanguageModelV2CallWarning[];\n }> {\n return this.doGenerateWithRetry(options, false);\n }\n\n private async doGenerateWithRetry(\n options: LanguageModelV2CallOptions,\n isRetry: boolean\n ): Promise<{\n content: LanguageModelV2Content[];\n finishReason: LanguageModelV2FinishReason;\n usage: LanguageModelV2Usage;\n warnings: LanguageModelV2CallWarning[];\n }> {\n const client = await this.getAnthropicClient(isRetry);\n const { system, messages } = this.convertPrompt(options.prompt);\n const tools = this.convertTools(options.tools);\n const toolChoice =\n options.toolChoice?.type !== 'none' ? this.convertToolChoice(options.toolChoice) : undefined;\n\n const anthropicModel = this.config.anthropicModel || 'claude-sonnet-4-5-20250929';\n const maxTokens = options.maxOutputTokens || this.config.maxTokens || 8192;\n\n try {\n const response = await client.messages.create({\n model: anthropicModel,\n max_tokens: maxTokens,\n system: system,\n messages: messages,\n tools: tools,\n tool_choice: tools ? toolChoice : undefined,\n temperature: options.temperature,\n top_p: options.topP,\n stop_sequences: options.stopSequences,\n });\n\n const content: LanguageModelV2Content[] = [];\n\n for (const block of response.content) {\n if (block.type === 'text') {\n content.push({\n type: 'text',\n text: block.text,\n });\n } else if (block.type === 'tool_use') {\n content.push({\n type: 'tool-call',\n toolCallId: block.id,\n toolName: block.name,\n input: JSON.stringify(block.input),\n });\n }\n }\n\n const usage: LanguageModelV2Usage = {\n inputTokens: response.usage.input_tokens,\n outputTokens: response.usage.output_tokens,\n totalTokens: response.usage.input_tokens + response.usage.output_tokens,\n };\n\n return {\n content,\n finishReason: this.convertFinishReason(response.stop_reason),\n usage,\n warnings: [],\n };\n } catch (error) {\n // Check for context overflow FIRST - these should NOT trigger token refresh\n if (this.isContextOverflowError(error)) {\n const apiError = error as InstanceType<typeof Anthropic.APIError>;\n throw new GitLabError({\n message: `Context overflow: ${apiError.message}. Please start a new session or use /compact to reduce context.`,\n statusCode: 400,\n cause: error,\n });\n }\n\n // If this is a token error and we haven't retried yet, refresh token and retry\n if (!isRetry && this.isTokenError(error)) {\n this.directAccessClient.invalidateToken();\n return this.doGenerateWithRetry(options, true);\n }\n\n if (error instanceof Anthropic.APIError) {\n throw new GitLabError({\n message: `Anthropic API error: ${error.message}`,\n statusCode: error.status,\n cause: error,\n });\n }\n throw error;\n }\n }\n\n async doStream(options: LanguageModelV2CallOptions): Promise<{\n stream: ReadableStream<LanguageModelV2StreamPart>;\n request?: { body?: unknown };\n response?: { headers?: Record<string, string> };\n }> {\n return this.doStreamWithRetry(options, false);\n }\n\n private async doStreamWithRetry(\n options: LanguageModelV2CallOptions,\n isRetry: boolean\n ): Promise<{\n stream: ReadableStream<LanguageModelV2StreamPart>;\n request?: { body?: unknown };\n response?: { headers?: Record<string, string> };\n }> {\n const client = await this.getAnthropicClient(isRetry);\n const { system, messages } = this.convertPrompt(options.prompt);\n const tools = this.convertTools(options.tools);\n const toolChoice =\n options.toolChoice?.type !== 'none' ? this.convertToolChoice(options.toolChoice) : undefined;\n\n const anthropicModel = this.config.anthropicModel || 'claude-sonnet-4-5-20250929';\n const maxTokens = options.maxOutputTokens || this.config.maxTokens || 8192;\n\n const requestBody = {\n model: anthropicModel,\n max_tokens: maxTokens,\n system: system,\n messages: messages,\n tools: tools,\n tool_choice: tools ? toolChoice : undefined,\n temperature: options.temperature,\n top_p: options.topP,\n stop_sequences: options.stopSequences,\n stream: true as const,\n };\n\n // Reference to this for use in the stream callback\n // eslint-disable-next-line @typescript-eslint/no-this-alias\n const self = this;\n\n const stream = new ReadableStream<LanguageModelV2StreamPart>({\n start: async (controller) => {\n const contentBlocks: Record<\n number,\n | { type: 'text'; id: string }\n | { type: 'tool-call'; toolCallId: string; toolName: string; input: string }\n > = {};\n\n const usage: LanguageModelV2Usage = {\n inputTokens: 0,\n outputTokens: 0,\n totalTokens: 0,\n };\n let finishReason: LanguageModelV2FinishReason = 'unknown';\n\n try {\n const anthropicStream = client.messages.stream(requestBody, {\n signal: options.abortSignal,\n });\n\n // Stream start\n controller.enqueue({\n type: 'stream-start',\n warnings: [],\n });\n\n // Use event-based approach instead of for-await to ensure all events are received\n await new Promise<void>((resolve, reject) => {\n anthropicStream.on('streamEvent', (event) => {\n try {\n switch (event.type) {\n case 'message_start':\n if (event.message.usage) {\n usage.inputTokens = event.message.usage.input_tokens;\n }\n controller.enqueue({\n type: 'response-metadata',\n id: event.message.id,\n modelId: event.message.model,\n });\n break;\n\n case 'content_block_start':\n if (event.content_block.type === 'text') {\n const textId = `text-${event.index}`;\n contentBlocks[event.index] = { type: 'text', id: textId };\n controller.enqueue({\n type: 'text-start',\n id: textId,\n });\n } else if (event.content_block.type === 'tool_use') {\n contentBlocks[event.index] = {\n type: 'tool-call',\n toolCallId: event.content_block.id,\n toolName: event.content_block.name,\n input: '',\n };\n controller.enqueue({\n type: 'tool-input-start',\n id: event.content_block.id,\n toolName: event.content_block.name,\n });\n }\n break;\n\n case 'content_block_delta': {\n const block = contentBlocks[event.index];\n if (event.delta.type === 'text_delta' && block?.type === 'text') {\n controller.enqueue({\n type: 'text-delta',\n id: block.id,\n delta: event.delta.text,\n });\n } else if (\n event.delta.type === 'input_json_delta' &&\n block?.type === 'tool-call'\n ) {\n block.input += event.delta.partial_json;\n controller.enqueue({\n type: 'tool-input-delta',\n id: block.toolCallId,\n delta: event.delta.partial_json,\n });\n }\n break;\n }\n\n case 'content_block_stop': {\n const block = contentBlocks[event.index];\n if (block?.type === 'text') {\n controller.enqueue({\n type: 'text-end',\n id: block.id,\n });\n } else if (block?.type === 'tool-call') {\n controller.enqueue({\n type: 'tool-input-end',\n id: block.toolCallId,\n });\n\n controller.enqueue({\n type: 'tool-call',\n toolCallId: block.toolCallId,\n toolName: block.toolName,\n input: block.input === '' ? '{}' : block.input,\n });\n }\n delete contentBlocks[event.index];\n break;\n }\n\n case 'message_delta':\n if (event.usage) {\n usage.outputTokens = event.usage.output_tokens;\n usage.totalTokens = (usage.inputTokens || 0) + event.usage.output_tokens;\n }\n if (event.delta.stop_reason) {\n finishReason = self.convertFinishReason(event.delta.stop_reason);\n }\n break;\n\n case 'message_stop': {\n controller.enqueue({\n type: 'finish',\n finishReason,\n usage,\n });\n break;\n }\n }\n } catch {\n // Ignore errors processing individual events\n }\n });\n\n anthropicStream.on('end', () => {\n resolve();\n });\n\n anthropicStream.on('error', (error) => {\n reject(error);\n });\n });\n\n // Emit any pending tool calls if stream ended without content_block_stop\n for (const [, block] of Object.entries(contentBlocks)) {\n if (block.type === 'tool-call') {\n controller.enqueue({\n type: 'tool-input-end',\n id: block.toolCallId,\n });\n controller.enqueue({\n type: 'tool-call',\n toolCallId: block.toolCallId,\n toolName: block.toolName,\n input: block.input === '' ? '{}' : block.input,\n });\n }\n }\n\n controller.close();\n } catch (error) {\n // Emit any pending tool calls before handling the error\n for (const [, block] of Object.entries(contentBlocks)) {\n if (block.type === 'tool-call') {\n controller.enqueue({\n type: 'tool-input-end',\n id: block.toolCallId,\n });\n controller.enqueue({\n type: 'tool-call',\n toolCallId: block.toolCallId,\n toolName: block.toolName,\n input: block.input === '' ? '{}' : block.input,\n });\n }\n }\n\n // Check for context overflow FIRST - these should NOT trigger token refresh\n if (self.isContextOverflowError(error)) {\n const apiError = error as InstanceType<typeof Anthropic.APIError>;\n controller.enqueue({\n type: 'error',\n error: new GitLabError({\n message: `Context overflow: ${apiError.message}. Please start a new session or use /compact to reduce context.`,\n statusCode: 400,\n cause: error,\n }),\n });\n controller.close();\n return;\n }\n\n // If this is a token error and we haven't retried yet, we need to signal retry\n // For streaming, we close this stream with an error and the caller should retry\n if (!isRetry && self.isTokenError(error)) {\n self.directAccessClient.invalidateToken();\n // Signal that a retry is needed with a special error\n controller.enqueue({\n type: 'error',\n error: new GitLabError({\n message: 'TOKEN_REFRESH_NEEDED',\n cause: error,\n }),\n });\n controller.close();\n return;\n }\n\n if (error instanceof Anthropic.APIError) {\n controller.enqueue({\n type: 'error',\n error: new GitLabError({\n message: `Anthropic API error: ${error.message}`,\n statusCode: error.status,\n cause: error,\n }),\n });\n } else {\n controller.enqueue({\n type: 'error',\n error,\n });\n }\n controller.close();\n }\n },\n });\n\n return {\n stream,\n request: { body: requestBody },\n };\n }\n}\n","import { z } from 'zod';\nimport { GitLabError } from './gitlab-error';\n\n/**\n * Response from /api/v4/ai/third_party_agents/direct_access\n */\nexport const directAccessTokenSchema = z.object({\n headers: z.record(z.string()),\n token: z.string(),\n});\n\nexport type DirectAccessToken = z.infer<typeof directAccessTokenSchema>;\n\nexport const DEFAULT_AI_GATEWAY_URL = 'https://cloud.gitlab.com';\n\nexport interface GitLabDirectAccessConfig {\n instanceUrl: string;\n getHeaders: () => Record<string, string>;\n fetch?: typeof fetch;\n /**\n * Optional callback to refresh the API key when a 401 error occurs.\n * Should clear cached credentials and re-fetch from auth provider.\n */\n refreshApiKey?: () => Promise<void>;\n /**\n * Feature flags to pass to the GitLab API\n */\n featureFlags?: Record<string, boolean>;\n /**\n * AI Gateway URL for the Anthropic proxy.\n * Can also be set via GITLAB_AI_GATEWAY_URL environment variable.\n * @default 'https://cloud.gitlab.com'\n */\n aiGatewayUrl?: string;\n}\n\n/**\n * Client for GitLab's third-party agents direct access API.\n * This allows routing requests through GitLab's proxy to Anthropic.\n */\nexport class GitLabDirectAccessClient {\n private readonly config: GitLabDirectAccessConfig;\n private readonly fetchFn: typeof fetch;\n private readonly aiGatewayUrl: string;\n private cachedToken: DirectAccessToken | null = null;\n private tokenExpiresAt: number = 0;\n\n constructor(config: GitLabDirectAccessConfig) {\n this.config = config;\n this.fetchFn = config.fetch ?? fetch;\n this.aiGatewayUrl =\n config.aiGatewayUrl || process.env['GITLAB_AI_GATEWAY_URL'] || DEFAULT_AI_GATEWAY_URL;\n }\n\n /**\n * Get a direct access token for the Anthropic proxy.\n * Tokens are cached for 25 minutes (they expire after 30 minutes).\n * @param forceRefresh - If true, ignores the cache and fetches a new token\n */\n async getDirectAccessToken(forceRefresh: boolean = false): Promise<DirectAccessToken> {\n // Check if we have a valid cached token (unless force refresh is requested)\n const now = Date.now();\n if (!forceRefresh && this.cachedToken && this.tokenExpiresAt > now) {\n return this.cachedToken;\n }\n\n // Clear cache if forcing refresh\n if (forceRefresh) {\n this.invalidateToken();\n }\n\n const url = `${this.config.instanceUrl}/api/v4/ai/third_party_agents/direct_access`;\n\n // Prepare request body with feature flags if provided\n const requestBody: Record<string, unknown> = {};\n if (this.config.featureFlags && Object.keys(this.config.featureFlags).length > 0) {\n requestBody.feature_flags = this.config.featureFlags;\n }\n\n try {\n const response = await this.fetchFn(url, {\n method: 'POST',\n headers: {\n ...this.config.getHeaders(),\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(requestBody),\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n\n // If we get a 401 and have a refresh callback, try refreshing the API key once\n if (response.status === 401 && this.config.refreshApiKey && !forceRefresh) {\n try {\n // Refresh the API key (this should clear cached credentials and re-fetch from auth)\n await this.config.refreshApiKey();\n\n // Retry the request with the refreshed credentials\n return await this.getDirectAccessToken(true);\n } catch (refreshError) {\n // If refresh fails, throw the original 401 error\n throw new GitLabError({\n message: `Failed to get direct access token: ${response.status} ${response.statusText} - ${errorText}`,\n statusCode: response.status,\n responseBody: errorText,\n });\n }\n }\n\n // Provide helpful error message for 403 errors (common with self-hosted instances)\n if (response.status === 403) {\n throw new GitLabError({\n message:\n `Access denied to GitLab AI features (${this.config.instanceUrl}). ` +\n `This may indicate that: (1) GitLab Duo is not enabled on this instance, ` +\n `(2) Your account does not have access to AI features, or ` +\n `(3) The third-party agents feature is not available. ` +\n `Original error: ${response.status} ${response.statusText} - ${errorText}`,\n statusCode: response.status,\n responseBody: errorText,\n });\n }\n\n throw new GitLabError({\n message: `Failed to get direct access token: ${response.status} ${response.statusText} - ${errorText}`,\n statusCode: response.status,\n responseBody: errorText,\n });\n }\n\n const data = await response.json();\n const token = directAccessTokenSchema.parse(data);\n\n // Cache the token for 25 minutes (tokens expire after 30 minutes)\n this.cachedToken = token;\n this.tokenExpiresAt = now + 25 * 60 * 1000;\n\n return token;\n } catch (error) {\n if (error instanceof GitLabError) {\n throw error;\n }\n throw new GitLabError({\n message: `Failed to get direct access token: ${error}`,\n cause: error,\n });\n }\n }\n\n /**\n * Get the Anthropic proxy base URL\n */\n getAnthropicProxyUrl(): string {\n const baseUrl = this.aiGatewayUrl.replace(/\\/$/, '');\n return `${baseUrl}/ai/v1/proxy/anthropic/`;\n }\n\n /**\n * Get the OpenAI proxy base URL\n * Note: The OpenAI SDK expects a base URL like https://api.openai.com/v1\n * and appends paths like /chat/completions. So we need /v1 at the end.\n */\n getOpenAIProxyUrl(): string {\n const baseUrl = this.aiGatewayUrl.replace(/\\/$/, '');\n return `${baseUrl}/ai/v1/proxy/openai/v1`;\n }\n\n /**\n * Invalidate the cached token\n */\n invalidateToken(): void {\n this.cachedToken = null;\n this.tokenExpiresAt = 0;\n }\n}\n","export interface GitLabErrorOptions {\n message: string;\n statusCode?: number;\n responseBody?: string;\n cause?: unknown;\n}\n\nexport class GitLabError extends Error {\n readonly statusCode?: number;\n readonly responseBody?: string;\n readonly cause?: unknown;\n\n constructor(options: GitLabErrorOptions) {\n super(options.message);\n this.name = 'GitLabError';\n this.statusCode = options.statusCode;\n this.responseBody = options.responseBody;\n this.cause = options.cause;\n\n // Maintain proper stack trace for where error was thrown (only available on V8)\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, GitLabError);\n }\n }\n\n static fromResponse(response: Response, body: string): GitLabError {\n return new GitLabError({\n message: `GitLab API error: ${response.status} ${response.statusText}`,\n statusCode: response.status,\n responseBody: body,\n });\n }\n\n isAuthError(): boolean {\n return this.statusCode === 401;\n }\n\n isRateLimitError(): boolean {\n return this.statusCode === 429;\n }\n\n isForbiddenError(): boolean {\n return this.statusCode === 403;\n }\n\n isServerError(): boolean {\n return this.statusCode !== undefined && this.statusCode >= 500;\n }\n\n /**\n * Check if this error is a context overflow error (prompt too long).\n * These errors occur when the conversation exceeds the model's token limit.\n */\n isContextOverflowError(): boolean {\n if (this.statusCode !== 400) {\n return false;\n }\n const message = this.message?.toLowerCase() || '';\n return (\n message.includes('context overflow') ||\n message.includes('prompt is too long') ||\n message.includes('prompt too long') ||\n (message.includes('tokens') && message.includes('maximum'))\n );\n }\n}\n","import OpenAI from 'openai';\nimport { GitLabDirectAccessClient } from './gitlab-direct-access';\nimport { GitLabError } from './gitlab-error';\nimport { isResponsesApiModel } from './model-mappings';\n\nimport type {\n LanguageModelV2,\n LanguageModelV2CallOptions,\n LanguageModelV2StreamPart,\n LanguageModelV2FinishReason,\n LanguageModelV2CallWarning,\n LanguageModelV2Content,\n LanguageModelV2Usage,\n LanguageModelV2FunctionTool,\n LanguageModelV2Message,\n LanguageModelV2ToolChoice,\n} from '@ai-sdk/provider';\n\nexport interface GitLabOpenAIConfig {\n provider: string;\n instanceUrl: string;\n getHeaders: () => Record<string, string>;\n fetch?: typeof fetch;\n refreshApiKey?: () => Promise<void>;\n openaiModel?: string;\n maxTokens?: number;\n featureFlags?: {\n DuoAgentPlatformNext: true;\n } & Record<string, boolean>;\n aiGatewayUrl?: string;\n /** Whether to use the Responses API instead of Chat Completions API */\n useResponsesApi?: boolean;\n /**\n * Custom headers for AI Gateway OpenAI proxy requests.\n * Merged with headers from direct_access token response.\n */\n aiGatewayHeaders?: Record<string, string>;\n}\n\nexport class GitLabOpenAILanguageModel implements LanguageModelV2 {\n readonly specificationVersion = 'v2' as const;\n readonly modelId: string;\n readonly supportedUrls: Record<string, RegExp[]> = {};\n\n private readonly config: GitLabOpenAIConfig;\n private readonly directAccessClient: GitLabDirectAccessClient;\n private readonly useResponsesApi: boolean;\n private openaiClient: OpenAI | null = null;\n\n constructor(modelId: string, config: GitLabOpenAIConfig) {\n this.modelId = modelId;\n this.config = config;\n this.useResponsesApi = config.useResponsesApi ?? isResponsesApiModel(modelId);\n\n this.directAccessClient = new GitLabDirectAccessClient({\n instanceUrl: config.instanceUrl,\n getHeaders: config.getHeaders,\n refreshApiKey: config.refreshApiKey,\n fetch: config.fetch,\n featureFlags: config.featureFlags,\n aiGatewayUrl: config.aiGatewayUrl,\n });\n }\n\n get provider(): string {\n return this.config.provider;\n }\n\n private async getOpenAIClient(forceRefresh: boolean = false): Promise<OpenAI> {\n const tokenData = await this.directAccessClient.getDirectAccessToken(forceRefresh);\n const { 'x-api-key': _removed, ...filteredHeaders } = tokenData.headers;\n\n // Merge: tokenData headers < custom aiGatewayHeaders\n const mergedHeaders = {\n ...filteredHeaders,\n ...this.config.aiGatewayHeaders,\n };\n\n this.openaiClient = new OpenAI({\n apiKey: tokenData.token,\n baseURL: this.directAccessClient.getOpenAIProxyUrl(),\n defaultHeaders: mergedHeaders,\n });\n\n return this.openaiClient;\n }\n\n private isTokenError(error: unknown): boolean {\n if (error instanceof OpenAI.APIError) {\n if (error.status === 401) {\n return true;\n }\n const message = error.message?.toLowerCase() || '';\n if (\n message.includes('token') &&\n (message.includes('expired') || message.includes('revoked') || message.includes('invalid'))\n ) {\n return true;\n }\n }\n return false;\n }\n\n /**\n * Check if an error is a context overflow error (prompt too long)\n * These should NOT trigger token refresh and should be reported to the user.\n */\n private isContextOverflowError(error: unknown): boolean {\n if (error instanceof OpenAI.APIError) {\n // 400 Bad Request with prompt too long message\n if (error.status === 400) {\n const message = error.message?.toLowerCase() || '';\n if (\n message.includes('prompt is too long') ||\n message.includes('prompt too long') ||\n (message.includes('tokens') && message.includes('maximum'))\n ) {\n return true;\n }\n }\n }\n return false;\n }\n\n private convertTools(\n tools?: LanguageModelV2CallOptions['tools']\n ): OpenAI.ChatCompletionTool[] | undefined {\n if (!tools || tools.length === 0) {\n return undefined;\n }\n\n return tools\n .filter((tool): tool is LanguageModelV2FunctionTool => tool.type === 'function')\n .map((tool) => {\n const schema = tool.inputSchema as Record<string, unknown>;\n return {\n type: 'function' as const,\n function: {\n name: tool.name,\n description: tool.description || '',\n // Ensure the schema has type: 'object' as OpenAI requires it\n parameters: {\n type: 'object',\n ...schema,\n },\n },\n };\n });\n }\n\n private convertToolChoice(\n toolChoice?: LanguageModelV2ToolChoice\n ): OpenAI.ChatCompletionToolChoiceOption | undefined {\n if (!toolChoice) {\n return undefined;\n }\n\n switch (toolChoice.type) {\n case 'auto':\n return 'auto';\n case 'none':\n return 'none';\n case 'required':\n return 'required';\n case 'tool':\n return { type: 'function', function: { name: toolChoice.toolName } };\n default:\n return undefined;\n }\n }\n\n private convertPrompt(prompt: LanguageModelV2Message[]): OpenAI.ChatCompletionMessageParam[] {\n const messages: OpenAI.ChatCompletionMessageParam[] = [];\n\n for (const message of prompt) {\n if (message.role === 'system') {\n messages.push({ role: 'system', content: message.content });\n continue;\n }\n\n if (message.role === 'user') {\n const textParts = message.content\n .filter((part) => part.type === 'text')\n .map((part) => part.text);\n if (textParts.length > 0) {\n messages.push({ role: 'user', content: textParts.join('\\n') });\n }\n } else if (message.role === 'assistant') {\n const textParts: string[] = [];\n const toolCalls: OpenAI.ChatCompletionMessageToolCall[] = [];\n\n for (const part of message.content) {\n if (part.type === 'text') {\n textParts.push(part.text);\n } else if (part.type === 'tool-call') {\n toolCalls.push({\n id: part.toolCallId,\n type: 'function',\n function: {\n name: part.toolName,\n arguments: typeof part.input === 'string' ? part.input : JSON.stringify(part.input),\n },\n });\n }\n }\n\n const assistantMessage: OpenAI.ChatCompletionAssistantMessageParam = {\n role: 'assistant',\n content: textParts.length > 0 ? textParts.join('\\n') : null,\n };\n if (toolCalls.length > 0) {\n assistantMessage.tool_calls = toolCalls;\n }\n messages.push(assistantMessage);\n } else if (message.role === 'tool') {\n for (const part of message.content) {\n if (part.type === 'tool-result') {\n let resultContent: string;\n if (part.output.type === 'text') {\n resultContent = part.output.value;\n } else if (part.output.type === 'json') {\n resultContent = JSON.stringify(part.output.value);\n } else if (part.output.type === 'error-text') {\n resultContent = part.output.value;\n } else if (part.output.type === 'error-json') {\n resultContent = JSON.stringify(part.output.value);\n } else {\n resultContent = JSON.stringify(part.output);\n }\n messages.push({\n role: 'tool',\n tool_call_id: part.toolCallId,\n content: resultContent,\n });\n }\n }\n }\n }\n\n return messages;\n }\n\n private convertFinishReason(\n finishReason: string | null | undefined\n ): LanguageModelV2FinishReason {\n switch (finishReason) {\n case 'stop':\n return 'stop';\n case 'length':\n return 'length';\n case 'tool_calls':\n return 'tool-calls';\n case 'content_filter':\n return 'content-filter';\n default:\n return 'unknown';\n }\n }\n\n /**\n * Convert tools to Responses API format\n */\n private convertToolsForResponses(\n tools?: LanguageModelV2CallOptions['tools']\n ): OpenAI.Responses.FunctionTool[] | undefined {\n if (!tools || tools.length === 0) {\n return undefined;\n }\n\n return tools\n .filter((tool): tool is LanguageModelV2FunctionTool => tool.type === 'function')\n .map((tool) => {\n // Clone schema and remove $schema field which can confuse the model\n // Zod 4's toJSONSchema() adds \"$schema\": \"https://json-schema.org/draft/2020-12/schema\"\n const schema = { ...(tool.inputSchema as Record<string, unknown>) };\n delete schema['$schema'];\n\n return {\n type: 'function' as const,\n name: tool.name,\n description: tool.description || '',\n parameters: schema,\n strict: false,\n };\n });\n }\n\n /**\n * Convert prompt to Responses API input format\n */\n private convertPromptForResponses(\n prompt: LanguageModelV2Message[]\n ): OpenAI.Responses.ResponseInput {\n const items: OpenAI.Responses.ResponseInputItem[] = [];\n\n for (const message of prompt) {\n if (message.role === 'system') {\n // System messages become instructions, handled separately\n continue;\n }\n\n if (message.role === 'user') {\n const textParts = message.content\n .filter((part) => part.type === 'text')\n .map((part) => part.text);\n if (textParts.length > 0) {\n items.push({\n type: 'message',\n role: 'user',\n content: textParts.map((text) => ({ type: 'input_text' as const, text })),\n } as OpenAI.Responses.ResponseInputItem);\n }\n } else if (message.role === 'assistant') {\n // Handle text content as output message\n const textParts: string[] = [];\n for (const part of message.content) {\n if (part.type === 'text') {\n textParts.push(part.text);\n } else if (part.type === 'tool-call') {\n // Tool calls are function_call items in Responses API\n items.push({\n type: 'function_call',\n call_id: part.toolCallId,\n name: part.toolName,\n arguments: typeof part.input === 'string' ? part.input : JSON.stringify(part.input),\n } as OpenAI.Responses.ResponseInputItem);\n }\n }\n\n if (textParts.length > 0) {\n items.push({\n type: 'message',\n role: 'assistant',\n content: [{ type: 'output_text', text: textParts.join('\\n'), annotations: [] }],\n } as OpenAI.Responses.ResponseInputItem);\n }\n } else if (message.role === 'tool') {\n for (const part of message.content) {\n if (part.type === 'tool-result') {\n let resultContent: string;\n if (part.output.type === 'text') {\n resultContent = part.output.value;\n } else if (part.output.type === 'json') {\n resultContent = JSON.stringify(part.output.value);\n } else if (part.output.type === 'error-text') {\n resultContent = part.output.value;\n } else if (part.output.type === 'error-json') {\n resultContent = JSON.stringify(part.output.value);\n } else {\n resultContent = JSON.stringify(part.output);\n }\n items.push({\n type: 'function_call_output',\n call_id: part.toolCallId,\n output: resultContent,\n } as OpenAI.Responses.ResponseInputItem);\n }\n }\n }\n }\n\n return items;\n }\n\n /**\n * Extract system instructions from prompt\n */\n private extractSystemInstructions(prompt: LanguageModelV2Message[]): string | undefined {\n const systemMessages = prompt\n .filter((m) => m.role === 'system')\n .map((m) => m.content)\n .join('\\n');\n return systemMessages || undefined;\n }\n\n /**\n * Convert Responses API status to finish reason\n * Note: Responses API returns 'completed' even when making tool calls,\n * so we need to check the content for tool calls separately.\n */\n private convertResponsesStatus(\n status: string | undefined,\n hasToolCalls: boolean = false\n ): LanguageModelV2FinishReason {\n // If we have tool calls, return 'tool-calls' regardless of status\n if (hasToolCalls) {\n return 'tool-calls';\n }\n\n switch (status) {\n case 'completed':\n return 'stop';\n case 'incomplete':\n return 'length';\n case 'cancelled':\n return 'stop';\n case 'failed':\n return 'error';\n default:\n return 'unknown';\n }\n }\n\n async doGenerate(options: LanguageModelV2CallOptions): Promise<{\n content: LanguageModelV2Content[];\n finishReason: LanguageModelV2FinishReason;\n usage: LanguageModelV2Usage;\n warnings: LanguageModelV2CallWarning[];\n }> {\n if (this.useResponsesApi) {\n return this.doGenerateWithResponsesApi(options, false);\n }\n return this.doGenerateWithChatApi(options, false);\n }\n\n private async doGenerateWithChatApi(\n options: LanguageModelV2CallOptions,\n isRetry: boolean\n ): Promise<{\n content: LanguageModelV2Content[];\n finishReason: LanguageModelV2FinishReason;\n usage: LanguageModelV2Usage;\n warnings: LanguageModelV2CallWarning[];\n }> {\n const client = await this.getOpenAIClient(isRetry);\n const messages = this.convertPrompt(options.prompt);\n const tools = this.convertTools(options.tools);\n const toolChoice =\n options.toolChoice?.type !== 'none' ? this.convertToolChoice(options.toolChoice) : undefined;\n\n const openaiModel = this.config.openaiModel || 'gpt-4o';\n const maxTokens = options.maxOutputTokens || this.config.maxTokens || 8192;\n\n try {\n const response = await client.chat.completions.create({\n model: openaiModel,\n max_completion_tokens: maxTokens,\n messages: messages,\n tools: tools,\n tool_choice: tools ? toolChoice : undefined,\n temperature: options.temperature,\n top_p: options.topP,\n stop: options.stopSequences,\n });\n\n const choice = response.choices[0];\n const content: LanguageModelV2Content[] = [];\n\n if (choice?.message.content) {\n content.push({ type: 'text', text: choice.message.content });\n }\n\n if (choice?.message.tool_calls) {\n for (const toolCall of choice.message.tool_calls) {\n if (toolCall.type === 'function') {\n content.push({\n type: 'tool-call',\n toolCallId: toolCall.id,\n toolName: toolCall.function.name,\n input: toolCall.function.arguments,\n });\n }\n }\n }\n\n const usage: LanguageModelV2Usage = {\n inputTokens: response.usage?.prompt_tokens || 0,\n outputTokens: response.usage?.completion_tokens || 0,\n totalTokens: response.usage?.total_tokens || 0,\n };\n\n return {\n content,\n finishReason: this.convertFinishReason(choice?.finish_reason),\n usage,\n warnings: [],\n };\n } catch (error) {\n // Check for context overflow FIRST - these should NOT trigger token refresh\n if (this.isContextOverflowError(error)) {\n const apiError = error as InstanceType<typeof OpenAI.APIError>;\n throw new GitLabError({\n message: `Context overflow: ${apiError.message}. Please start a new session or use /compact to reduce context.`,\n statusCode: 400,\n cause: error,\n });\n }\n\n if (!isRetry && this.isTokenError(error)) {\n this.directAccessClient.invalidateToken();\n return this.doGenerateWithChatApi(options, true);\n }\n\n if (error instanceof OpenAI.APIError) {\n throw new GitLabError({\n message: `OpenAI API error: ${error.message}`,\n statusCode: error.status,\n cause: error,\n });\n }\n throw error;\n }\n }\n\n private async doGenerateWithResponsesApi(\n options: LanguageModelV2CallOptions,\n isRetry: boolean\n ): Promise<{\n content: LanguageModelV2Content[];\n finishReason: LanguageModelV2FinishReason;\n usage: LanguageModelV2Usage;\n warnings: LanguageModelV2CallWarning[];\n }> {\n const client = await this.getOpenAIClient(isRetry);\n const input = this.convertPromptForResponses(options.prompt);\n const tools = this.convertToolsForResponses(options.tools);\n const instructions = this.extractSystemInstructions(options.prompt);\n\n const openaiModel = this.config.openaiModel || 'gpt-5-codex';\n const maxTokens = options.maxOutputTokens || this.config.maxTokens || 8192;\n\n try {\n const response = await client.responses.create({\n model: openaiModel,\n input,\n instructions,\n tools,\n max_output_tokens: maxTokens,\n temperature: options.temperature,\n top_p: options.topP,\n store: false,\n });\n\n const content: LanguageModelV2Content[] = [];\n let hasToolCalls = false;\n\n // Process output items\n for (const item of response.output || []) {\n if (item.type === 'message' && item.role === 'assistant') {\n for (const contentItem of item.content || []) {\n if (contentItem.type === 'output_text') {\n content.push({ type: 'text', text: contentItem.text });\n }\n }\n } else if (item.type === 'function_call') {\n hasToolCalls = true;\n content.push({\n type: 'tool-call',\n toolCallId: item.call_id,\n toolName: item.name,\n input: item.arguments,\n });\n }\n }\n\n const usage: LanguageModelV2Usage = {\n inputTokens: response.usage?.input_tokens || 0,\n outputTokens: response.usage?.output_tokens || 0,\n totalTokens: response.usage?.total_tokens || 0,\n };\n\n return {\n content,\n finishReason: this.convertResponsesStatus(response.status, hasToolCalls),\n usage,\n warnings: [],\n };\n } catch (error) {\n // Check for context overflow FIRST - these should NOT trigger token refresh\n if (this.isContextOverflowError(error)) {\n const apiError = error as InstanceType<typeof OpenAI.APIError>;\n throw new GitLabError({\n message: `Context overflow: ${apiError.message}. Please start a new session or use /compact to reduce context.`,\n statusCode: 400,\n cause: error,\n });\n }\n\n if (!isRetry && this.isTokenError(error)) {\n this.directAccessClient.invalidateToken();\n return this.doGenerateWithResponsesApi(options, true);\n }\n\n if (error instanceof OpenAI.APIError) {\n throw new GitLabError({\n message: `OpenAI API error: ${error.message}`,\n statusCode: error.status,\n cause: error,\n });\n }\n throw error;\n }\n }\n\n async doStream(options: LanguageModelV2CallOptions): Promise<{\n stream: ReadableStream<LanguageModelV2StreamPart>;\n request?: { body?: unknown };\n response?: { headers?: Record<string, string> };\n }> {\n if (this.useResponsesApi) {\n return this.doStreamWithResponsesApi(options, false);\n }\n return this.doStreamWithChatApi(options, false);\n }\n\n private async doStreamWithChatApi(\n options: LanguageModelV2CallOptions,\n isRetry: boolean\n ): Promise<{\n stream: ReadableStream<LanguageModelV2StreamPart>;\n request?: { body?: unknown };\n response?: { headers?: Record<string, string> };\n }> {\n const client = await this.getOpenAIClient(isRetry);\n const messages = this.convertPrompt(options.prompt);\n const tools = this.convertTools(options.tools);\n const toolChoice =\n options.toolChoice?.type !== 'none' ? this.convertToolChoice(options.toolChoice) : undefined;\n\n const openaiModel = this.config.openaiModel || 'gpt-4o';\n const maxTokens = options.maxOutputTokens || this.config.maxTokens || 8192;\n\n const requestBody = {\n model: openaiModel,\n max_completion_tokens: maxTokens,\n messages: messages,\n tools: tools,\n tool_choice: tools ? toolChoice : undefined,\n temperature: options.temperature,\n top_p: options.topP,\n stop: options.stopSequences,\n stream: true as const,\n stream_options: { include_usage: true },\n };\n\n // eslint-disable-next-line @typescript-eslint/no-this-alias\n const self = this;\n\n const stream = new ReadableStream<LanguageModelV2StreamPart>({\n start: async (controller) => {\n const toolCalls: Record<number, { id: string; name: string; arguments: string }> = {};\n\n const usage: LanguageModelV2Usage = {\n inputTokens: 0,\n outputTokens: 0,\n totalTokens: 0,\n };\n let finishReason: LanguageModelV2FinishReason = 'unknown';\n let textStarted = false;\n const textId = 'text-0';\n\n try {\n const openaiStream = await client.chat.completions.create({\n ...requestBody,\n stream: true,\n });\n\n controller.enqueue({ type: 'stream-start', warnings: [] });\n\n for await (const chunk of openaiStream) {\n const choice = chunk.choices?.[0];\n\n if (chunk.id && !textStarted) {\n controller.enqueue({\n type: 'response-metadata',\n id: chunk.id,\n modelId: chunk.model,\n });\n }\n\n if (choice?.delta?.content) {\n if (!textStarted) {\n controller.enqueue({ type: 'text-start', id: textId });\n textStarted = true;\n }\n controller.enqueue({\n type: 'text-delta',\n id: textId,\n delta: choice.delta.content,\n });\n }\n\n if (choice?.delta?.tool_calls) {\n for (const tc of choice.delta.tool_calls) {\n const idx = tc.index;\n if (!toolCalls[idx]) {\n toolCalls[idx] = {\n id: tc.id || '',\n name: tc.function?.name || '',\n arguments: '',\n };\n controller.enqueue({\n type: 'tool-input-start',\n id: toolCalls[idx].id,\n toolName: toolCalls[idx].name,\n });\n }\n if (tc.function?.arguments) {\n toolCalls[idx].arguments += tc.function.arguments;\n controller.enqueue({\n type: 'tool-input-delta',\n id: toolCalls[idx].id,\n delta: tc.function.arguments,\n });\n }\n }\n }\n\n if (choice?.finish_reason) {\n finishReason = self.convertFinishReason(choice.finish_reason);\n }\n\n if (chunk.usage) {\n usage.inputTokens = chunk.usage.prompt_tokens || 0;\n usage.outputTokens = chunk.usage.completion_tokens || 0;\n usage.totalTokens = chunk.usage.total_tokens || 0;\n }\n }\n\n if (textStarted) {\n controller.enqueue({ type: 'text-end', id: textId });\n }\n\n for (const [, tc] of Object.entries(toolCalls)) {\n controller.enqueue({ type: 'tool-input-end', id: tc.id });\n controller.enqueue({\n type: 'tool-call',\n toolCallId: tc.id,\n toolName: tc.name,\n input: tc.arguments || '{}',\n });\n }\n\n controller.enqueue({ type: 'finish', finishReason, usage });\n controller.close();\n } catch (error) {\n // Check for context overflow FIRST - these should NOT trigger token refresh\n if (self.isContextOverflowError(error)) {\n const apiError = error as InstanceType<typeof OpenAI.APIError>;\n controller.enqueue({\n type: 'error',\n error: new GitLabError({\n message: `Context overflow: ${apiError.message}. Please start a new session or use /compact to reduce context.`,\n statusCode: 400,\n cause: error,\n }),\n });\n controller.close();\n return;\n }\n\n if (!isRetry && self.isTokenError(error)) {\n self.directAccessClient.invalidateToken();\n controller.enqueue({\n type: 'error',\n error: new GitLabError({ message: 'TOKEN_REFRESH_NEEDED', cause: error }),\n });\n controller.close();\n return;\n }\n\n if (error instanceof OpenAI.APIError) {\n controller.enqueue({\n type: 'error',\n error: new GitLabError({\n message: `OpenAI API error: ${error.message}`,\n statusCode: error.status,\n cause: error,\n }),\n });\n } else {\n controller.enqueue({ type: 'error', error });\n }\n controller.close();\n }\n },\n });\n\n return { stream, request: { body: requestBody } };\n }\n\n private async doStreamWithResponsesApi(\n options: LanguageModelV2CallOptions,\n isRetry: boolean\n ): Promise<{\n stream: ReadableStream<LanguageModelV2StreamPart>;\n request?: { body?: unknown };\n response?: { headers?: Record<string, string> };\n }> {\n const client = await this.getOpenAIClient(isRetry);\n const input = this.convertPromptForResponses(options.prompt);\n const tools = this.convertToolsForResponses(options.tools);\n const instructions = this.extractSystemInstructions(options.prompt);\n\n const openaiModel = this.config.openaiModel || 'gpt-5-codex';\n const maxTokens = options.maxOutputTokens || this.config.maxTokens || 8192;\n\n const requestBody = {\n model: openaiModel,\n input,\n instructions,\n tools,\n max_output_tokens: maxTokens,\n temperature: options.temperature,\n top_p: options.topP,\n store: false,\n stream: true as const,\n };\n\n // eslint-disable-next-line @typescript-eslint/no-this-alias\n const self = this;\n\n const stream = new ReadableStream<LanguageModelV2StreamPart>({\n start: async (controller) => {\n // Use output_index as key (like OpenCode does) to track tool calls across events\n const toolCalls: Record<number, { callId: string; name: string; arguments: string }> = {};\n const usage: LanguageModelV2Usage = {\n inputTokens: 0,\n outputTokens: 0,\n totalTokens: 0,\n };\n let finishReason: LanguageModelV2FinishReason = 'unknown';\n let textStarted = false;\n const textId = 'text-0';\n\n try {\n const openaiStream = await client.responses.create({\n ...requestBody,\n stream: true,\n });\n\n controller.enqueue({ type: 'stream-start', warnings: [] });\n\n for await (const event of openaiStream) {\n // Handle different event types from Responses API streaming\n if (event.type === 'response.created') {\n controller.enqueue({\n type: 'response-metadata',\n id: event.response.id,\n modelId: event.response.model,\n });\n } else if (event.type === 'response.output_item.added') {\n // Track function calls when they start, keyed by output_index\n if (event.item.type === 'function_call') {\n const outputIndex = event.output_index;\n const callId = event.item.call_id;\n toolCalls[outputIndex] = {\n callId,\n name: event.item.name,\n arguments: '',\n };\n controller.enqueue({\n type: 'tool-input-start',\n id: callId,\n toolName: event.item.name,\n });\n }\n } else if (event.type === 'response.output_text.delta') {\n if (!textStarted) {\n controller.enqueue({ type: 'text-start', id: textId });\n textStarted = true;\n }\n controller.enqueue({\n type: 'text-delta',\n id: textId,\n delta: event.delta,\n });\n } else if (event.type === 'response.function_call_arguments.delta') {\n // Use output_index to find the tool call (like OpenCode)\n const outputIndex = event.output_index;\n const tc = toolCalls[outputIndex];\n if (tc) {\n tc.arguments += event.delta;\n controller.enqueue({\n type: 'tool-input-delta',\n id: tc.callId,\n delta: event.delta,\n });\n }\n } else if (event.type === 'response.function_call_arguments.done') {\n const outputIndex = event.output_index;\n const tc = toolCalls[outputIndex];\n if (tc) {\n tc.arguments = event.arguments;\n }\n } else if (event.type === 'response.completed') {\n // Check if there are tool calls to determine finish reason\n const hasToolCalls = Object.keys(toolCalls).length > 0;\n finishReason = self.convertResponsesStatus(event.response.status, hasToolCalls);\n if (event.response.usage) {\n usage.inputTokens = event.response.usage.input_tokens || 0;\n usage.outputTokens = event.response.usage.output_tokens || 0;\n usage.totalTokens = event.response.usage.total_tokens || 0;\n }\n }\n }\n\n if (textStarted) {\n controller.enqueue({ type: 'text-end', id: textId });\n }\n\n // Check if we have tool calls to set the correct finish reason\n const hasToolCalls = Object.keys(toolCalls).length > 0;\n if (hasToolCalls && finishReason === 'stop') {\n finishReason = 'tool-calls';\n }\n\n for (const tc of Object.values(toolCalls)) {\n controller.enqueue({ type: 'tool-input-end', id: tc.callId });\n controller.enqueue({\n type: 'tool-call',\n toolCallId: tc.callId,\n toolName: tc.name,\n input: tc.arguments || '{}',\n });\n }\n\n controller.enqueue({ type: 'finish', finishReason, usage });\n controller.close();\n } catch (error) {\n // Check for context overflow FIRST - these should NOT trigger token refresh\n if (self.isContextOverflowError(error)) {\n const apiError = error as InstanceType<typeof OpenAI.APIError>;\n controller.enqueue({\n type: 'error',\n error: new GitLabError({\n message: `Context overflow: ${apiError.message}. Please start a new session or use /compact to reduce context.`,\n statusCode: 400,\n cause: error,\n }),\n });\n controller.close();\n return;\n }\n\n if (!isRetry && self.isTokenError(error)) {\n self.directAccessClient.invalidateToken();\n controller.enqueue({\n type: 'error',\n error: new GitLabError({ message: 'TOKEN_REFRESH_NEEDED', cause: error }),\n });\n controller.close();\n return;\n }\n\n if (error instanceof OpenAI.APIError) {\n controller.enqueue({\n type: 'error',\n error: new GitLabError({\n message: `OpenAI API error: ${error.message}`,\n statusCode: error.status,\n cause: error,\n }),\n });\n } else {\n controller.enqueue({ type: 'error', error });\n }\n controller.close();\n }\n },\n });\n\n return { stream, request: { body: requestBody } };\n }\n}\n","export type ModelProvider = 'anthropic' | 'openai';\n\nexport type OpenAIApiType = 'chat' | 'responses';\n\nexport interface ModelMapping {\n provider: ModelProvider;\n model: string;\n /** For OpenAI models, which API to use: 'chat' for /v1/chat/completions, 'responses' for /v1/responses */\n openaiApiType?: OpenAIApiType;\n}\n\nexport const MODEL_MAPPINGS: Record<string, ModelMapping> = {\n // Anthropic models\n 'duo-chat-opus-4-5': { provider: 'anthropic', model: 'claude-opus-4-5-20251101' },\n 'duo-chat-sonnet-4-5': { provider: 'anthropic', model: 'claude-sonnet-4-5-20250929' },\n 'duo-chat-haiku-4-5': { provider: 'anthropic', model: 'claude-haiku-4-5-20251001' },\n\n // OpenAI models - Chat Completions API\n 'duo-chat-gpt-5-1': { provider: 'openai', model: 'gpt-5.1-2025-11-13', openaiApiType: 'chat' },\n 'duo-chat-gpt-5-2': { provider: 'openai', model: 'gpt-5.2-2025-12-11', openaiApiType: 'chat' },\n 'duo-chat-gpt-5-mini': {\n provider: 'openai',\n model: 'gpt-5-mini-2025-08-07',\n openaiApiType: 'chat',\n },\n\n // OpenAI models - Responses API (Codex models)\n 'duo-chat-gpt-5-codex': { provider: 'openai', model: 'gpt-5-codex', openaiApiType: 'responses' },\n 'duo-chat-gpt-5-2-codex': {\n provider: 'openai',\n model: 'gpt-5.2-codex',\n openaiApiType: 'responses',\n },\n};\n\nexport function getModelMapping(modelId: string): ModelMapping | undefined {\n return MODEL_MAPPINGS[modelId];\n}\n\nexport function getProviderForModelId(modelId: string): ModelProvider | undefined {\n return MODEL_MAPPINGS[modelId]?.provider;\n}\n\nexport function getValidModelsForProvider(provider: ModelProvider): string[] {\n return Object.values(MODEL_MAPPINGS)\n .filter((m) => m.provider === provider)\n .map((m) => m.model);\n}\n\nexport function getAnthropicModelForModelId(modelId: string): string | undefined {\n const mapping = MODEL_MAPPINGS[modelId];\n return mapping?.provider === 'anthropic' ? mapping.model : undefined;\n}\n\nexport function getOpenAIModelForModelId(modelId: string): string | undefined {\n const mapping = MODEL_MAPPINGS[modelId];\n return mapping?.provider === 'openai' ? mapping.model : undefined;\n}\n\nexport function getOpenAIApiType(modelId: string): OpenAIApiType {\n const mapping = MODEL_MAPPINGS[modelId];\n return mapping?.openaiApiType ?? 'chat';\n}\n\nexport function isResponsesApiModel(modelId: string): boolean {\n return getOpenAIApiType(modelId) === 'responses';\n}\n\nexport const MODEL_ID_TO_ANTHROPIC_MODEL: Record<string, string> = Object.fromEntries(\n Object.entries(MODEL_MAPPINGS)\n .filter(([, v]) => v.provider === 'anthropic')\n .map(([k, v]) => [k, v.model])\n);\n","/**\n * OAuth types and constants for GitLab authentication\n * Based on gitlab-vscode-extension and gitlab-lsp patterns\n */\n\nexport interface GitLabOAuthTokens {\n accessToken: string;\n refreshToken: string;\n expiresAt: number; // Unix timestamp in milliseconds\n instanceUrl: string;\n}\n\nexport interface OpenCodeAuthOAuth {\n type: 'oauth';\n refresh: string;\n access: string;\n expires: number; // Unix timestamp in milliseconds\n instanceUrl?: string;\n}\n\nexport interface OpenCodeAuthApi {\n type: 'api';\n key: string;\n}\n\nexport type OpenCodeAuth = OpenCodeAuthOAuth | OpenCodeAuthApi;\n\n/**\n * Bundled OAuth client ID for GitLab.com\n * Same as used in gitlab-vscode-extension\n */\nexport const BUNDLED_CLIENT_ID = '36f2a70cddeb5a0889d4fd8295c241b7e9848e89cf9e599d0eed2d8e5350fbf5';\n\n/**\n * GitLab.com URL constant\n */\nexport const GITLAB_COM_URL = 'https://gitlab.com';\n\n/**\n * Token expiry skew in milliseconds (5 minutes)\n * Refresh tokens this many milliseconds before they expire\n */\nexport const TOKEN_EXPIRY_SKEW_MS = 5 * 60 * 1000;\n\n/**\n * OAuth scopes to request\n */\nexport const OAUTH_SCOPES = ['api'];\n","/**\n * GitLab OAuth Manager\n * Handles OAuth token management, refresh, and exchange\n * Based on gitlab-vscode-extension TokenExchangeService and gitlab-lsp OAuthClientProvider\n */\n\nimport { GitLabError } from './gitlab-error';\nimport type { GitLabOAuthTokenResponse } from './gitlab-api-types';\nimport {\n type GitLabOAuthTokens,\n TOKEN_EXPIRY_SKEW_MS,\n BUNDLED_CLIENT_ID,\n GITLAB_COM_URL,\n} from './gitlab-oauth-types';\n\nexport interface TokenExchangeParams {\n instanceUrl: string;\n clientId?: string;\n redirectUri?: string;\n}\n\nexport interface AuthorizationCodeParams extends TokenExchangeParams {\n code: string;\n codeVerifier: string;\n}\n\nexport interface RefreshTokenParams extends TokenExchangeParams {\n refreshToken: string;\n}\n\nexport class GitLabOAuthManager {\n private fetch: typeof fetch;\n\n constructor(fetchImpl: typeof fetch = fetch) {\n this.fetch = fetchImpl;\n }\n\n /**\n * Check if a token is expired\n */\n isTokenExpired(expiresAt: number): boolean {\n return Date.now() >= expiresAt;\n }\n\n /**\n * Check if a token needs refresh (within skew window)\n */\n needsRefresh(expiresAt: number): boolean {\n return Date.now() >= expiresAt - TOKEN_EXPIRY_SKEW_MS;\n }\n\n /**\n * Refresh tokens if needed\n * Returns the same tokens if refresh is not needed, or new tokens if refreshed\n */\n async refreshIfNeeded(tokens: GitLabOAuthTokens, clientId?: string): Promise<GitLabOAuthTokens> {\n if (!this.needsRefresh(tokens.expiresAt)) {\n return tokens;\n }\n\n if (this.isTokenExpired(tokens.expiresAt)) {\n throw new GitLabError({\n message: 'OAuth token has expired and cannot be used',\n });\n }\n\n return this.exchangeRefreshToken({\n instanceUrl: tokens.instanceUrl,\n refreshToken: tokens.refreshToken,\n clientId,\n });\n }\n\n /**\n * Exchange authorization code for tokens\n * Based on gitlab-vscode-extension createOAuthAccountFromCode\n */\n async exchangeAuthorizationCode(params: AuthorizationCodeParams): Promise<GitLabOAuthTokens> {\n const { instanceUrl, code, codeVerifier, clientId, redirectUri } = params;\n\n const tokenResponse = await this.exchangeToken({\n instanceUrl,\n grantType: 'authorization_code',\n code,\n codeVerifier,\n clientId: clientId || this.getClientId(instanceUrl),\n redirectUri,\n });\n\n return this.createTokensFromResponse(tokenResponse, instanceUrl);\n }\n\n /**\n * Exchange refresh token for new tokens\n * Based on gitlab-vscode-extension TokenExchangeService\n */\n async exchangeRefreshToken(params: RefreshTokenParams): Promise<GitLabOAuthTokens> {\n const { instanceUrl, refreshToken, clientId } = params;\n\n const tokenResponse = await this.exchangeToken({\n instanceUrl,\n grantType: 'refresh_token',\n refreshToken,\n clientId: clientId || this.getClientId(instanceUrl),\n });\n\n return this.createTokensFromResponse(tokenResponse, instanceUrl);\n }\n\n /**\n * Get the OAuth client ID for an instance\n */\n private getClientId(instanceUrl: string): string {\n // Use bundled client ID for GitLab.com\n if (instanceUrl === GITLAB_COM_URL) {\n return BUNDLED_CLIENT_ID;\n }\n\n throw new GitLabError({\n message: `No OAuth client ID configured for instance ${instanceUrl}. Please provide a clientId parameter.`,\n });\n }\n\n /**\n * Exchange token with GitLab OAuth endpoint\n * Based on gitlab-vscode-extension GitLabService.exchangeToken\n */\n private async exchangeToken(params: {\n instanceUrl: string;\n grantType: 'authorization_code' | 'refresh_token';\n code?: string;\n codeVerifier?: string;\n refreshToken?: string;\n clientId: string;\n redirectUri?: string;\n }): Promise<GitLabOAuthTokenResponse> {\n const { instanceUrl, grantType, code, codeVerifier, refreshToken, clientId, redirectUri } =\n params;\n\n const body: Record<string, string> = {\n client_id: clientId,\n grant_type: grantType,\n };\n\n if (grantType === 'authorization_code') {\n if (!code || !codeVerifier || !redirectUri) {\n throw new GitLabError({\n message:\n 'Authorization code, code verifier, and redirect URI are required for authorization_code grant',\n });\n }\n body.code = code;\n body.code_verifier = codeVerifier;\n body.redirect_uri = redirectUri;\n } else if (grantType === 'refresh_token') {\n if (!refreshToken) {\n throw new GitLabError({\n message: 'Refresh token is required for refresh_token grant',\n });\n }\n body.refresh_token = refreshToken;\n }\n\n const url = `${instanceUrl}/oauth/token`;\n\n try {\n const response = await this.fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n },\n body: new URLSearchParams(body).toString(),\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new GitLabError({\n message: `OAuth token exchange failed: ${response.status} ${response.statusText}`,\n cause: new Error(errorText),\n });\n }\n\n const data = await response.json();\n return data as GitLabOAuthTokenResponse;\n } catch (error) {\n if (error instanceof GitLabError) {\n throw error;\n }\n throw new GitLabError({\n message: `Failed to exchange OAuth token: ${error instanceof Error ? error.message : String(error)}`,\n cause: error instanceof Error ? error : undefined,\n });\n }\n }\n\n /**\n * Create GitLabOAuthTokens from token response\n */\n private createTokensFromResponse(\n response: GitLabOAuthTokenResponse,\n instanceUrl: string\n ): GitLabOAuthTokens {\n const expiresAt = this.createExpiresTimestamp(response);\n\n return {\n accessToken: response.access_token,\n refreshToken: response.refresh_token || '',\n expiresAt,\n instanceUrl,\n };\n }\n\n /**\n * Create expiry timestamp from token response\n * Based on gitlab-vscode-extension createExpiresTimestamp\n */\n private createExpiresTimestamp(response: GitLabOAuthTokenResponse): number {\n // GitLab returns created_at (Unix timestamp in seconds) and expires_in (seconds)\n const createdAt = response.created_at * 1000; // Convert to milliseconds\n const expiresIn = response.expires_in * 1000; // Convert to milliseconds\n return createdAt + expiresIn;\n }\n}\n","// Version string of this package injected at build time.\ndeclare const __PACKAGE_VERSION__: string | undefined;\nexport const VERSION: string =\n typeof __PACKAGE_VERSION__ !== 'undefined' ? __PACKAGE_VERSION__ : '0.0.0-dev';\n","import { GitLabAnthropicLanguageModel } from './gitlab-anthropic-language-model';\nimport { GitLabOpenAILanguageModel } from './gitlab-openai-language-model';\nimport { GitLabError } from './gitlab-error';\nimport type { LanguageModelV2 } from '@ai-sdk/provider';\nimport { GitLabOAuthManager } from './gitlab-oauth-manager';\nimport type { OpenCodeAuth } from './gitlab-oauth-types';\nimport { getModelMapping, getValidModelsForProvider } from './model-mappings';\nimport { VERSION } from './version';\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport * as os from 'os';\n\nexport interface GitLabProvider {\n (modelId: string): LanguageModelV2;\n readonly specificationVersion: 'v2';\n languageModel(modelId: string): LanguageModelV2;\n chat(modelId: string): LanguageModelV2;\n /**\n * Create an agentic chat model with tool calling support\n *\n * @param modelId - GitLab model identifier. Some IDs automatically map to specific Anthropic models.\n * @param options - Configuration options for the agentic model\n * @returns A language model with native tool calling support via Anthropic\n *\n * @example\n * // Automatic model mapping\n * const model = gitlab.agenticChat('duo-chat-opus-4-5');\n * // Uses claude-opus-4-5-20251101\n *\n * @example\n * // Explicit model override\n * const model = gitlab.agenticChat('duo-chat', {\n * anthropicModel: 'claude-sonnet-4-5-20250929'\n * });\n */\n agenticChat(modelId: string, options?: GitLabAgenticOptions): GitLabAnthropicLanguageModel;\n textEmbeddingModel(modelId: string): never;\n imageModel(modelId: string): never;\n}\n\nexport interface GitLabAgenticOptions {\n /**\n * Override the provider-specific model (optional).\n * Must be a valid model for the detected provider.\n *\n * For Anthropic models:\n * - 'claude-opus-4-5-20251101'\n * - 'claude-sonnet-4-5-20250929'\n * - 'claude-haiku-4-5-20251001'\n *\n * For OpenAI models:\n * - 'gpt-5.1-2025-11-13'\n * - 'gpt-5-mini-2025-08-07'\n * - 'gpt-5-codex'\n * - 'gpt-5.2-codex'\n *\n * @example\n * // Override with explicit model\n * const model = gitlab.agenticChat('duo-chat-opus-4-5', {\n * providerModel: 'claude-sonnet-4-5-20250929'\n * });\n */\n providerModel?: string;\n\n /**\n * Maximum tokens to generate\n * @default 8192\n */\n maxTokens?: number;\n\n /**\n * Feature flags to pass to the GitLab API\n */\n featureFlags?: Record<string, boolean>;\n\n /**\n * Custom headers for AI Gateway requests (per-model override).\n * These headers are sent to the Anthropic/OpenAI proxy endpoints.\n * Merged with provider-level aiGatewayHeaders (model-level takes precedence).\n */\n aiGatewayHeaders?: Record<string, string>;\n}\n\nexport interface GitLabProviderSettings {\n /**\n * GitLab instance URL (e.g., 'https://gitlab.com')\n * @default 'https://gitlab.com'\n */\n instanceUrl?: string;\n\n /**\n * API token (Personal Access Token or OAuth access token)\n * Can also be set via GITLAB_TOKEN environment variable\n */\n apiKey?: string;\n\n /**\n * OAuth refresh token (optional, for OAuth flow)\n */\n refreshToken?: string;\n\n /**\n * OAuth client ID (required for OAuth flow)\n */\n clientId?: string;\n\n /**\n * OAuth redirect URI (required for OAuth flow)\n */\n redirectUri?: string;\n\n /**\n * Custom headers to include in requests\n */\n headers?: Record<string, string>;\n\n /**\n * Custom fetch implementation\n */\n fetch?: typeof fetch;\n\n /**\n * Provider name override\n */\n name?: string;\n\n /**\n * Default feature flags to pass to the GitLab API for all agentic chat models\n */\n featureFlags?: Record<string, boolean>;\n\n /**\n * AI Gateway URL for the Anthropic proxy.\n * Can also be set via GITLAB_AI_GATEWAY_URL environment variable.\n * @default 'https://cloud.gitlab.com'\n */\n aiGatewayUrl?: string;\n\n /**\n * Custom headers to include in AI Gateway requests (Anthropic/OpenAI proxy).\n * These headers are merged with the default headers from direct_access response.\n * Default User-Agent: gitlab-ai-provider/{version}\n */\n aiGatewayHeaders?: Record<string, string>;\n}\n\n/**\n * Get OpenCode auth file path\n * Uses XDG Base Directory specification\n */\nfunction getOpenCodeAuthPath(): string {\n const homeDir = os.homedir();\n\n // Check XDG_DATA_HOME first (Linux/Mac standard)\n const xdgDataHome = process.env.XDG_DATA_HOME;\n if (xdgDataHome) {\n return path.join(xdgDataHome, 'opencode', 'auth.json');\n }\n\n // Fallback to ~/.local/share/opencode/auth.json (XDG default)\n if (process.platform !== 'win32') {\n return path.join(homeDir, '.local', 'share', 'opencode', 'auth.json');\n }\n\n // Windows fallback\n return path.join(homeDir, '.opencode', 'auth.json');\n}\n\n/**\n * Load OpenCode auth.json file\n */\nasync function loadOpenCodeAuth(instanceUrl: string): Promise<OpenCodeAuth | undefined> {\n try {\n const authPath = getOpenCodeAuthPath();\n\n if (!fs.existsSync(authPath)) {\n return undefined;\n }\n\n const authData = JSON.parse(fs.readFileSync(authPath, 'utf-8'));\n\n // Priority 1: Check 'gitlab' key (used by opencode-gitlab-auth plugin)\n if (authData.gitlab?.type === 'oauth') {\n const gitlabAuth = authData.gitlab;\n // Verify it matches the requested instance URL\n if (\n gitlabAuth.enterpriseUrl === instanceUrl ||\n gitlabAuth.enterpriseUrl === instanceUrl.replace(/\\/$/, '')\n ) {\n return gitlabAuth as OpenCodeAuth;\n }\n }\n\n // Priority 2: Try to find auth for this instance by URL\n // Check both with and without trailing slash\n const normalizedUrl = instanceUrl.replace(/\\/$/, '');\n const auth = authData[normalizedUrl] || authData[`${normalizedUrl}/`];\n\n return auth as OpenCodeAuth | undefined;\n } catch (error) {\n // Silently fail if we can't read auth.json\n return undefined;\n }\n}\n\n/**\n * Load GitLab API key with OAuth support\n * Priority: explicit apiKey > OAuth token > env var\n */\nasync function loadApiKey(\n options: {\n apiKey?: string;\n environmentVariableName: string;\n description: string;\n },\n instanceUrl: string,\n clientId?: string\n): Promise<string> {\n // Priority 1: Explicit apiKey\n if (options.apiKey) {\n return options.apiKey;\n }\n\n // Priority 2: OAuth token from OpenCode auth.json\n const auth = await loadOpenCodeAuth(instanceUrl);\n if (auth?.type === 'oauth') {\n const oauthManager = new GitLabOAuthManager();\n\n // Check if token needs refresh\n if (oauthManager.needsRefresh(auth.expires)) {\n try {\n const refreshed = await oauthManager.exchangeRefreshToken({\n instanceUrl,\n refreshToken: auth.refresh,\n clientId,\n });\n\n // Update stored token\n const authPath = getOpenCodeAuthPath();\n const authData = JSON.parse(fs.readFileSync(authPath, 'utf-8'));\n const normalizedUrl = instanceUrl.replace(/\\/$/, '');\n\n authData[normalizedUrl] = {\n type: 'oauth',\n refresh: refreshed.refreshToken,\n access: refreshed.accessToken,\n expires: refreshed.expiresAt,\n instanceUrl,\n };\n\n fs.writeFileSync(authPath, JSON.stringify(authData, null, 2));\n\n return refreshed.accessToken;\n } catch (error) {\n // If refresh fails, fall through to env var\n console.warn(\n `Failed to refresh OAuth token: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n } else {\n return auth.access;\n }\n }\n\n // Priority 3: Environment variable\n const apiKey = process.env[options.environmentVariableName];\n\n if (!apiKey) {\n throw new GitLabError({\n message: `${options.description} API key is missing. Pass it as the 'apiKey' parameter, set the ${options.environmentVariableName} environment variable, or authenticate with 'opencode auth login gitlab'.`,\n });\n }\n\n return apiKey;\n}\n\nfunction withUserAgentSuffix(\n headers: Record<string, string>,\n suffix: string\n): Record<string, string> {\n const userAgent = headers['User-Agent'];\n return {\n ...headers,\n 'User-Agent': userAgent ? `${userAgent} ${suffix}` : suffix,\n };\n}\n\nexport function createGitLab(options: GitLabProviderSettings = {}): GitLabProvider {\n const instanceUrl = options.instanceUrl ?? 'https://gitlab.com';\n const providerName = options.name ?? 'gitlab';\n\n // Cache for the API key - loaded lazily on first use\n let cachedApiKey: string | undefined;\n let apiKeyPromise: Promise<string> | undefined;\n\n const getApiKey = async (): Promise<string> => {\n if (cachedApiKey) {\n return cachedApiKey;\n }\n\n if (apiKeyPromise) {\n return apiKeyPromise;\n }\n\n apiKeyPromise = loadApiKey(\n {\n apiKey: options.apiKey,\n environmentVariableName: 'GITLAB_TOKEN',\n description: 'GitLab',\n },\n instanceUrl,\n options.clientId\n );\n\n cachedApiKey = await apiKeyPromise;\n apiKeyPromise = undefined;\n return cachedApiKey;\n };\n\n /**\n * Refresh the API key by clearing the cache and re-fetching from auth provider.\n * This is called when a 401 error occurs to trigger OAuth token refresh.\n */\n const refreshApiKey = async (): Promise<void> => {\n // Clear the cached API key to force a refresh\n cachedApiKey = undefined;\n apiKeyPromise = undefined;\n\n // Re-fetch the API key (this will trigger the auth plugin's loader() which handles token refresh)\n cachedApiKey = await getApiKey();\n };\n\n const getHeaders = () => {\n // For synchronous access, we need to have the key already loaded\n // or fall back to env var/explicit key\n const apiKey = cachedApiKey || options.apiKey || process.env['GITLAB_TOKEN'] || '';\n\n if (!apiKey) {\n throw new GitLabError({\n message:\n \"GitLab API key is missing. Pass it as the 'apiKey' parameter, set the GITLAB_TOKEN environment variable, or authenticate with 'opencode auth login gitlab'.\",\n });\n }\n\n return withUserAgentSuffix(\n {\n Authorization: `Bearer ${apiKey}`,\n 'Content-Type': 'application/json',\n ...options.headers,\n },\n `ai-sdk-gitlab/${VERSION}`\n );\n };\n\n // Pre-load the API key asynchronously\n getApiKey().catch(() => {\n // Silently fail - will be caught when getHeaders is called\n });\n\n const createAgenticChatModel = (modelId: string, agenticOptions?: GitLabAgenticOptions) => {\n const mapping = getModelMapping(modelId);\n\n if (!mapping) {\n throw new GitLabError({\n message: `Unknown model ID: ${modelId}. Model must be registered in MODEL_MAPPINGS.`,\n });\n }\n\n if (agenticOptions?.providerModel) {\n const validModels = getValidModelsForProvider(mapping.provider);\n if (!validModels.includes(agenticOptions.providerModel)) {\n throw new GitLabError({\n message: `Invalid providerModel '${agenticOptions.providerModel}' for provider '${mapping.provider}'. Valid models: ${validModels.join(', ')}`,\n });\n }\n }\n\n const featureFlags = {\n DuoAgentPlatformNext: true as const,\n ...options.featureFlags,\n ...agenticOptions?.featureFlags,\n };\n\n const defaultAiGatewayHeaders = {\n 'User-Agent': `gitlab-ai-provider/${VERSION}`,\n };\n\n const aiGatewayHeaders = {\n ...defaultAiGatewayHeaders,\n ...options.aiGatewayHeaders,\n ...agenticOptions?.aiGatewayHeaders,\n };\n\n const baseConfig = {\n provider: `${providerName}.agentic`,\n instanceUrl,\n getHeaders,\n refreshApiKey,\n fetch: options.fetch,\n maxTokens: agenticOptions?.maxTokens,\n featureFlags,\n aiGatewayUrl: options.aiGatewayUrl,\n aiGatewayHeaders,\n };\n\n if (mapping.provider === 'openai') {\n return new GitLabOpenAILanguageModel(modelId, {\n ...baseConfig,\n openaiModel: agenticOptions?.providerModel ?? mapping.model,\n });\n }\n\n return new GitLabAnthropicLanguageModel(modelId, {\n ...baseConfig,\n anthropicModel: agenticOptions?.providerModel ?? mapping.model,\n });\n };\n\n // Default model factory - uses Anthropic backend for tool support\n const createDefaultModel = (modelId: string): LanguageModelV2 => {\n // Use Anthropic-based model by default for all models to get tool support\n return createAgenticChatModel(modelId);\n };\n\n const provider = Object.assign((modelId: string) => createDefaultModel(modelId), {\n specificationVersion: 'v2' as const,\n languageModel: createDefaultModel,\n chat: createDefaultModel,\n agenticChat: createAgenticChatModel,\n }) as GitLabProvider;\n\n // Unsupported model types\n provider.textEmbeddingModel = (modelId: string) => {\n throw new GitLabError({\n message: `GitLab provider does not support text embedding models. Model ID: ${modelId}`,\n });\n };\n\n provider.imageModel = (modelId: string) => {\n throw new GitLabError({\n message: `GitLab provider does not support image models. Model ID: ${modelId}`,\n });\n };\n\n return provider;\n}\n\n/**\n * Default GitLab Duo provider instance\n *\n * @example\n * ```typescript\n * import { gitlab } from '@ai-sdk/gitlab';\n *\n * const model = gitlab('duo-chat');\n * ```\n */\nexport const gitlab = createGitLab();\n","import { spawn } from 'child_process';\nimport * as path from 'path';\nimport { GitLabProjectCache, type GitLabProject } from './gitlab-project-cache';\nimport { GitLabError } from './gitlab-error';\n\n// Noop debug function (workflow debug removed)\nconst debugLog = (..._args: unknown[]) => {};\n\nexport interface GitLabProjectDetectorConfig {\n instanceUrl: string;\n getHeaders: () => Record<string, string>;\n fetch?: typeof fetch;\n cache?: GitLabProjectCache;\n gitTimeout?: number;\n}\n\n/**\n * Detects GitLab project information from git remote URLs\n *\n * This class provides functionality to:\n * - Parse git remote URLs (SSH, HTTPS, custom domains)\n * - Execute git commands to get remote URLs\n * - Fetch project details from GitLab API\n * - Cache project information to avoid repeated API calls\n */\nexport class GitLabProjectDetector {\n private readonly config: GitLabProjectDetectorConfig;\n private readonly fetchFn: typeof fetch;\n private readonly cache: GitLabProjectCache;\n\n constructor(config: GitLabProjectDetectorConfig) {\n this.config = {\n gitTimeout: 5000, // 5 seconds default\n ...config,\n };\n this.fetchFn = config.fetch ?? fetch;\n this.cache = config.cache ?? new GitLabProjectCache();\n }\n\n /**\n * Auto-detect GitLab project from git remote in the working directory\n *\n * @param workingDirectory - The directory to check for git remote\n * @param remoteName - The git remote name to use (default: 'origin')\n * @returns The detected project or null if detection fails\n */\n async detectProject(\n workingDirectory: string,\n remoteName: string = 'origin'\n ): Promise<GitLabProject | null> {\n // 1. Check cache first\n const cacheKey = path.resolve(workingDirectory);\n const cached = this.cache.get(cacheKey);\n if (cached) {\n return cached;\n }\n\n try {\n // 2. Get git remote URL\n debugLog(`[GitLabProjectDetector] Getting git remote URL from: ${workingDirectory}`);\n const remoteUrl = await this.getGitRemoteUrl(workingDirectory, remoteName);\n if (!remoteUrl) {\n debugLog(`[GitLabProjectDetector] No git remote URL found`);\n return null; // Not a git repo or no remote\n }\n debugLog(`[GitLabProjectDetector] Git remote URL: ${remoteUrl}`);\n\n // 3. Parse project path from URL\n debugLog(\n `[GitLabProjectDetector] Parsing project path from URL (instance: ${this.config.instanceUrl})`\n );\n const projectPath = this.parseGitRemoteUrl(remoteUrl, this.config.instanceUrl);\n if (!projectPath) {\n debugLog(\n `[GitLabProjectDetector] Could not parse project path from URL (remote doesn't match instance)`\n );\n return null; // Remote doesn't match instance\n }\n debugLog(`[GitLabProjectDetector] Parsed project path: ${projectPath}`);\n\n // 4. Fetch project from GitLab API\n debugLog(`[GitLabProjectDetector] Fetching project from GitLab API: ${projectPath}`);\n const project = await this.getProjectByPath(projectPath);\n debugLog(`[GitLabProjectDetector] ✓ Project fetched successfully:`, project);\n\n // 5. Cache the result\n this.cache.set(cacheKey, project);\n\n return project;\n } catch (error) {\n // Log error but don't throw - graceful degradation\n if (error instanceof GitLabError) {\n // GitLab API errors are expected (e.g., project not found)\n debugLog(`[GitLabProjectDetector] GitLab API error:`, error.message || error);\n return null;\n }\n // Log unexpected errors for debugging\n debugLog(`[GitLabProjectDetector] Unexpected error:`, error);\n console.warn(`Failed to auto-detect GitLab project: ${error}`);\n return null;\n }\n }\n\n /**\n * Parse a git remote URL to extract the project path\n *\n * Supports:\n * - SSH: git@gitlab.com:namespace/project.git\n * - HTTPS: https://gitlab.com/namespace/project.git\n * - HTTP: http://gitlab.local/namespace/project.git\n * - Custom domains and ports\n *\n * @param remoteUrl - The git remote URL\n * @param instanceUrl - The GitLab instance URL to match against\n * @returns The project path (e.g., \"namespace/project\") or null if parsing fails\n */\n parseGitRemoteUrl(remoteUrl: string, instanceUrl: string): string | null {\n try {\n // Extract hostname from instanceUrl\n const instanceHost = new URL(instanceUrl).hostname;\n\n // SSH format: git@host:path.git or git@host:port/path.git\n const sshMatch = remoteUrl.match(/^git@([^:]+):(.+?)(?:\\.git)?$/);\n if (sshMatch) {\n const [, host, pathPart] = sshMatch;\n // Handle port in SSH URLs (git@host:port/path)\n const hostWithoutPort = host.split(':')[0];\n if (hostWithoutPort === instanceHost) {\n // Remove port from path if present\n const cleanPath = pathPart.replace(/^\\d+\\//, '');\n return cleanPath.endsWith('.git') ? cleanPath.slice(0, -4) : cleanPath;\n }\n }\n\n // HTTPS/HTTP format: https://host/path.git or https://host:port/path.git\n const httpsMatch = remoteUrl.match(/^(https?):\\/\\/([^/]+)\\/(.+?)(?:\\.git)?$/);\n if (httpsMatch) {\n const [, , hostWithPort, pathPart] = httpsMatch;\n const host = hostWithPort.split(':')[0];\n if (host === instanceHost) {\n return pathPart.endsWith('.git') ? pathPart.slice(0, -4) : pathPart;\n }\n }\n\n return null;\n } catch (error) {\n // URL parsing failed\n return null;\n }\n }\n\n /**\n * Get the git remote URL from a working directory\n *\n * @param workingDirectory - The directory to check\n * @param remoteName - The git remote name (default: 'origin')\n * @returns The remote URL or null if not found\n */\n async getGitRemoteUrl(\n workingDirectory: string,\n remoteName: string = 'origin'\n ): Promise<string | null> {\n return new Promise((resolve) => {\n const child = spawn('git', ['config', '--get', `remote.${remoteName}.url`], {\n cwd: workingDirectory,\n timeout: this.config.gitTimeout,\n });\n\n let stdout = '';\n let _stderr = '';\n\n child.stdout?.on('data', (data) => {\n stdout += data.toString();\n });\n\n child.stderr?.on('data', (data) => {\n _stderr += data.toString();\n });\n\n child.on('close', (exitCode) => {\n if (exitCode === 0 && stdout.trim()) {\n resolve(stdout.trim());\n } else {\n resolve(null);\n }\n });\n\n child.on('error', () => {\n // Git not available or command failed\n resolve(null);\n });\n });\n }\n\n /**\n * Fetch project details from GitLab API by project path\n *\n * @param projectPath - The project path (e.g., \"namespace/project\")\n * @returns The project details\n * @throws GitLabError if the API call fails\n */\n async getProjectByPath(projectPath: string): Promise<GitLabProject> {\n // URL-encode the project path\n const encodedPath = encodeURIComponent(projectPath);\n const url = `${this.config.instanceUrl}/api/v4/projects/${encodedPath}`;\n\n try {\n const response = await this.fetchFn(url, {\n method: 'GET',\n headers: this.config.getHeaders(),\n });\n\n if (!response.ok) {\n throw new GitLabError({\n message: `Failed to fetch project '${projectPath}': ${response.status} ${response.statusText}`,\n });\n }\n\n const data = (await response.json()) as {\n id: number;\n path: string;\n path_with_namespace: string;\n name: string;\n namespace?: { id: number };\n };\n\n return {\n id: data.id,\n path: data.path,\n pathWithNamespace: data.path_with_namespace,\n name: data.name,\n namespaceId: data.namespace?.id,\n };\n } catch (error) {\n if (error instanceof GitLabError) {\n throw error;\n }\n throw new GitLabError({\n message: `Failed to fetch project '${projectPath}': ${error}`,\n cause: error,\n });\n }\n }\n\n /**\n * Clear the project cache\n */\n clearCache(): void {\n this.cache.clear();\n }\n\n /**\n * Get the cache instance (useful for testing)\n */\n getCache(): GitLabProjectCache {\n return this.cache;\n }\n}\n","/**\n * Simple in-memory cache for GitLab project information\n * Used to avoid repeated API calls when detecting projects from git remotes\n */\n\nexport interface GitLabProject {\n id: number;\n path: string;\n pathWithNamespace: string;\n name: string;\n namespaceId?: number;\n}\n\ninterface CacheEntry {\n project: GitLabProject;\n expiresAt: number;\n}\n\n/**\n * In-memory cache for GitLab project information with TTL support\n */\nexport class GitLabProjectCache {\n private cache = new Map<string, CacheEntry>();\n private defaultTTL: number;\n\n /**\n * Create a new project cache\n * @param defaultTTL - Default time-to-live in milliseconds (default: 5 minutes)\n */\n constructor(defaultTTL: number = 5 * 60 * 1000) {\n this.defaultTTL = defaultTTL;\n }\n\n /**\n * Get a cached project by key\n * @param key - Cache key (typically the working directory path)\n * @returns The cached project or null if not found or expired\n */\n get(key: string): GitLabProject | null {\n const entry = this.cache.get(key);\n if (!entry) {\n return null;\n }\n\n // Check if entry has expired\n if (Date.now() > entry.expiresAt) {\n this.cache.delete(key);\n return null;\n }\n\n return entry.project;\n }\n\n /**\n * Store a project in the cache\n * @param key - Cache key (typically the working directory path)\n * @param project - The project to cache\n * @param ttl - Optional custom TTL in milliseconds\n */\n set(key: string, project: GitLabProject, ttl?: number): void {\n this.cache.set(key, {\n project,\n expiresAt: Date.now() + (ttl ?? this.defaultTTL),\n });\n }\n\n /**\n * Check if a key exists in the cache (and is not expired)\n * @param key - Cache key to check\n * @returns true if the key exists and is not expired\n */\n has(key: string): boolean {\n return this.get(key) !== null;\n }\n\n /**\n * Remove a specific entry from the cache\n * @param key - Cache key to remove\n */\n delete(key: string): void {\n this.cache.delete(key);\n }\n\n /**\n * Clear all entries from the cache\n */\n clear(): void {\n this.cache.clear();\n }\n\n /**\n * Get the number of entries in the cache (including expired ones)\n */\n get size(): number {\n return this.cache.size;\n }\n\n /**\n * Clean up expired entries from the cache\n * This is useful for long-running processes to prevent memory leaks\n */\n cleanup(): void {\n const now = Date.now();\n for (const [key, entry] of this.cache.entries()) {\n if (now > entry.expiresAt) {\n this.cache.delete(key);\n }\n }\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,iBAAsB;;;ACAtB,iBAAkB;;;ACOX,IAAM,cAAN,MAAM,qBAAoB,MAAM;AAAA,EAC5B;AAAA,EACA;AAAA,EACA;AAAA,EAET,YAAY,SAA6B;AACvC,UAAM,QAAQ,OAAO;AACrB,SAAK,OAAO;AACZ,SAAK,aAAa,QAAQ;AAC1B,SAAK,eAAe,QAAQ;AAC5B,SAAK,QAAQ,QAAQ;AAGrB,QAAI,MAAM,mBAAmB;AAC3B,YAAM,kBAAkB,MAAM,YAAW;AAAA,IAC3C;AAAA,EACF;AAAA,EAEA,OAAO,aAAa,UAAoB,MAA2B;AACjE,WAAO,IAAI,aAAY;AAAA,MACrB,SAAS,qBAAqB,SAAS,MAAM,IAAI,SAAS,UAAU;AAAA,MACpE,YAAY,SAAS;AAAA,MACrB,cAAc;AAAA,IAChB,CAAC;AAAA,EACH;AAAA,EAEA,cAAuB;AACrB,WAAO,KAAK,eAAe;AAAA,EAC7B;AAAA,EAEA,mBAA4B;AAC1B,WAAO,KAAK,eAAe;AAAA,EAC7B;AAAA,EAEA,mBAA4B;AAC1B,WAAO,KAAK,eAAe;AAAA,EAC7B;AAAA,EAEA,gBAAyB;AACvB,WAAO,KAAK,eAAe,UAAa,KAAK,cAAc;AAAA,EAC7D;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,yBAAkC;AAChC,QAAI,KAAK,eAAe,KAAK;AAC3B,aAAO;AAAA,IACT;AACA,UAAM,UAAU,KAAK,SAAS,YAAY,KAAK;AAC/C,WACE,QAAQ,SAAS,kBAAkB,KACnC,QAAQ,SAAS,oBAAoB,KACrC,QAAQ,SAAS,iBAAiB,KACjC,QAAQ,SAAS,QAAQ,KAAK,QAAQ,SAAS,SAAS;AAAA,EAE7D;AACF;;;AD3DO,IAAM,0BAA0B,aAAE,OAAO;AAAA,EAC9C,SAAS,aAAE,OAAO,aAAE,OAAO,CAAC;AAAA,EAC5B,OAAO,aAAE,OAAO;AAClB,CAAC;AAIM,IAAM,yBAAyB;AA2B/B,IAAM,2BAAN,MAA+B;AAAA,EACnB;AAAA,EACA;AAAA,EACA;AAAA,EACT,cAAwC;AAAA,EACxC,iBAAyB;AAAA,EAEjC,YAAY,QAAkC;AAC5C,SAAK,SAAS;AACd,SAAK,UAAU,OAAO,SAAS;AAC/B,SAAK,eACH,OAAO,gBAAgB,QAAQ,IAAI,uBAAuB,KAAK;AAAA,EACnE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,qBAAqB,eAAwB,OAAmC;AAEpF,UAAM,MAAM,KAAK,IAAI;AACrB,QAAI,CAAC,gBAAgB,KAAK,eAAe,KAAK,iBAAiB,KAAK;AAClE,aAAO,KAAK;AAAA,IACd;AAGA,QAAI,cAAc;AAChB,WAAK,gBAAgB;AAAA,IACvB;AAEA,UAAM,MAAM,GAAG,KAAK,OAAO,WAAW;AAGtC,UAAM,cAAuC,CAAC;AAC9C,QAAI,KAAK,OAAO,gBAAgB,OAAO,KAAK,KAAK,OAAO,YAAY,EAAE,SAAS,GAAG;AAChF,kBAAY,gBAAgB,KAAK,OAAO;AAAA,IAC1C;AAEA,QAAI;AACF,YAAM,WAAW,MAAM,KAAK,QAAQ,KAAK;AAAA,QACvC,QAAQ;AAAA,QACR,SAAS;AAAA,UACP,GAAG,KAAK,OAAO,WAAW;AAAA,UAC1B,gBAAgB;AAAA,QAClB;AAAA,QACA,MAAM,KAAK,UAAU,WAAW;AAAA,MAClC,CAAC;AAED,UAAI,CAAC,SAAS,IAAI;AAChB,cAAM,YAAY,MAAM,SAAS,KAAK;AAGtC,YAAI,SAAS,WAAW,OAAO,KAAK,OAAO,iBAAiB,CAAC,cAAc;AACzE,cAAI;AAEF,kBAAM,KAAK,OAAO,cAAc;AAGhC,mBAAO,MAAM,KAAK,qBAAqB,IAAI;AAAA,UAC7C,SAAS,cAAc;AAErB,kBAAM,IAAI,YAAY;AAAA,cACpB,SAAS,sCAAsC,SAAS,MAAM,IAAI,SAAS,UAAU,MAAM,SAAS;AAAA,cACpG,YAAY,SAAS;AAAA,cACrB,cAAc;AAAA,YAChB,CAAC;AAAA,UACH;AAAA,QACF;AAGA,YAAI,SAAS,WAAW,KAAK;AAC3B,gBAAM,IAAI,YAAY;AAAA,YACpB,SACE,wCAAwC,KAAK,OAAO,WAAW,4MAI5C,SAAS,MAAM,IAAI,SAAS,UAAU,MAAM,SAAS;AAAA,YAC1E,YAAY,SAAS;AAAA,YACrB,cAAc;AAAA,UAChB,CAAC;AAAA,QACH;AAEA,cAAM,IAAI,YAAY;AAAA,UACpB,SAAS,sCAAsC,SAAS,MAAM,IAAI,SAAS,UAAU,MAAM,SAAS;AAAA,UACpG,YAAY,SAAS;AAAA,UACrB,cAAc;AAAA,QAChB,CAAC;AAAA,MACH;AAEA,YAAM,OAAO,MAAM,SAAS,KAAK;AACjC,YAAM,QAAQ,wBAAwB,MAAM,IAAI;AAGhD,WAAK,cAAc;AACnB,WAAK,iBAAiB,MAAM,KAAK,KAAK;AAEtC,aAAO;AAAA,IACT,SAAS,OAAO;AACd,UAAI,iBAAiB,aAAa;AAChC,cAAM;AAAA,MACR;AACA,YAAM,IAAI,YAAY;AAAA,QACpB,SAAS,sCAAsC,KAAK;AAAA,QACpD,OAAO;AAAA,MACT,CAAC;AAAA,IACH;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,uBAA+B;AAC7B,UAAM,UAAU,KAAK,aAAa,QAAQ,OAAO,EAAE;AACnD,WAAO,GAAG,OAAO;AAAA,EACnB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,oBAA4B;AAC1B,UAAM,UAAU,KAAK,aAAa,QAAQ,OAAO,EAAE;AACnD,WAAO,GAAG,OAAO;AAAA,EACnB;AAAA;AAAA;AAAA;AAAA,EAKA,kBAAwB;AACtB,SAAK,cAAc;AACnB,SAAK,iBAAiB;AAAA,EACxB;AACF;;;ADxGO,IAAM,+BAAN,MAA8D;AAAA,EAC1D,uBAAuB;AAAA,EACvB;AAAA,EACA,gBAA0C,CAAC;AAAA,EAEnC;AAAA,EACA;AAAA,EACT,kBAAoC;AAAA,EAE5C,YAAY,SAAiB,QAA+B;AAC1D,SAAK,UAAU;AACf,SAAK,SAAS;AAEd,SAAK,qBAAqB,IAAI,yBAAyB;AAAA,MACrD,aAAa,OAAO;AAAA,MACpB,YAAY,OAAO;AAAA,MACnB,eAAe,OAAO;AAAA,MACtB,OAAO,OAAO;AAAA,MACd,cAAc,OAAO;AAAA,MACrB,cAAc,OAAO;AAAA,IACvB,CAAC;AAAA,EACH;AAAA,EAEA,IAAI,WAAmB;AACrB,WAAO,KAAK,OAAO;AAAA,EACrB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAc,mBAAmB,eAAwB,OAA2B;AAElF,UAAM,YAAY,MAAM,KAAK,mBAAmB,qBAAqB,YAAY;AAOjF,UAAM,EAAE,aAAa,UAAU,GAAG,gBAAgB,IAAI,UAAU;AAGhE,UAAM,gBAAgB;AAAA,MACpB,GAAG;AAAA,MACH,GAAG,KAAK,OAAO;AAAA,IACjB;AAEA,SAAK,kBAAkB,IAAI,WAAAA,QAAU;AAAA,MACnC,QAAQ;AAAA,MACR,WAAW,UAAU;AAAA,MACrB,SAAS,KAAK,mBAAmB,qBAAqB;AAAA,MACtD,gBAAgB;AAAA,IAClB,CAAC;AAED,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAKQ,aAAa,OAAyB;AAC5C,QAAI,iBAAiB,WAAAA,QAAU,UAAU;AAEvC,UAAI,MAAM,WAAW,KAAK;AACxB,eAAO;AAAA,MACT;AAEA,YAAM,UAAU,MAAM,SAAS,YAAY,KAAK;AAChD,UACE,QAAQ,SAAS,OAAO,MACvB,QAAQ,SAAS,SAAS,KAAK,QAAQ,SAAS,SAAS,KAAK,QAAQ,SAAS,SAAS,IACzF;AACA,eAAO;AAAA,MACT;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,uBAAuB,OAAyB;AACtD,QAAI,iBAAiB,WAAAA,QAAU,UAAU;AAEvC,UAAI,MAAM,WAAW,KAAK;AACxB,cAAM,UAAU,MAAM,SAAS,YAAY,KAAK;AAChD,YACE,QAAQ,SAAS,oBAAoB,KACrC,QAAQ,SAAS,iBAAiB,KACjC,QAAQ,SAAS,QAAQ,KAAK,QAAQ,SAAS,SAAS,GACzD;AACA,iBAAO;AAAA,QACT;AAAA,MACF;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKQ,aAAa,OAAiE;AACpF,QAAI,CAAC,SAAS,MAAM,WAAW,GAAG;AAChC,aAAO;AAAA,IACT;AAEA,WAAO,MACJ,OAAO,CAAC,SAA8C,KAAK,SAAS,UAAU,EAC9E,IAAI,CAAC,SAAS;AACb,YAAM,SAAS,KAAK;AACpB,aAAO;AAAA,QACL,MAAM,KAAK;AAAA,QACX,aAAa,KAAK,eAAe;AAAA,QACjC,cAAc;AAAA,UACZ,MAAM;AAAA,UACN,YAAY,QAAQ,cAAc,CAAC;AAAA,UACnC,UAAU,QAAQ,YAAY,CAAC;AAAA,QACjC;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACL;AAAA;AAAA;AAAA;AAAA,EAKQ,kBACN,YAC8C;AAC9C,QAAI,CAAC,YAAY;AACf,aAAO;AAAA,IACT;AAEA,YAAQ,WAAW,MAAM;AAAA,MACvB,KAAK;AACH,eAAO,EAAE,MAAM,OAAO;AAAA,MACxB,KAAK;AAEH,eAAO;AAAA,MACT,KAAK;AACH,eAAO,EAAE,MAAM,MAAM;AAAA,MACvB,KAAK;AACH,eAAO,EAAE,MAAM,QAAQ,MAAM,WAAW,SAAS;AAAA,MACnD;AACE,eAAO;AAAA,IACX;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,cAAc,QAGpB;AACA,QAAI;AACJ,UAAM,WAAqC,CAAC;AAE5C,eAAW,WAAW,QAAQ;AAC5B,UAAI,QAAQ,SAAS,UAAU;AAC7B,wBAAgB,QAAQ;AACxB;AAAA,MACF;AAEA,UAAI,QAAQ,SAAS,QAAQ;AAC3B,cAAM,UAAyC,CAAC;AAEhD,mBAAW,QAAQ,QAAQ,SAAS;AAClC,cAAI,KAAK,SAAS,QAAQ;AACxB,oBAAQ,KAAK,EAAE,MAAM,QAAQ,MAAM,KAAK,KAAK,CAAC;AAAA,UAChD,WAAW,KAAK,SAAS,QAAQ;AAAA,UAGjC;AAAA,QACF;AAEA,YAAI,QAAQ,SAAS,GAAG;AACtB,mBAAS,KAAK,EAAE,MAAM,QAAQ,QAAQ,CAAC;AAAA,QACzC;AAAA,MACF,WAAW,QAAQ,SAAS,aAAa;AACvC,cAAM,UAAyC,CAAC;AAEhD,mBAAW,QAAQ,QAAQ,SAAS;AAClC,cAAI,KAAK,SAAS,QAAQ;AACxB,oBAAQ,KAAK,EAAE,MAAM,QAAQ,MAAM,KAAK,KAAK,CAAC;AAAA,UAChD,WAAW,KAAK,SAAS,aAAa;AACpC,oBAAQ,KAAK;AAAA,cACX,MAAM;AAAA,cACN,IAAI,KAAK;AAAA,cACT,MAAM,KAAK;AAAA,cACX,OAAO,OAAO,KAAK,UAAU,WAAW,KAAK,MAAM,KAAK,KAAK,IAAI,KAAK;AAAA,YACxE,CAAC;AAAA,UACH;AAAA,QACF;AAEA,YAAI,QAAQ,SAAS,GAAG;AACtB,mBAAS,KAAK,EAAE,MAAM,aAAa,QAAQ,CAAC;AAAA,QAC9C;AAAA,MACF,WAAW,QAAQ,SAAS,QAAQ;AAElC,cAAM,UAA4C,CAAC;AAEnD,mBAAW,QAAQ,QAAQ,SAAS;AAClC,cAAI,KAAK,SAAS,eAAe;AAC/B,gBAAI;AAGJ,gBAAI,KAAK,OAAO,SAAS,QAAQ;AAC/B,8BAAgB,KAAK,OAAO;AAAA,YAC9B,WAAW,KAAK,OAAO,SAAS,QAAQ;AACtC,8BAAgB,KAAK,UAAU,KAAK,OAAO,KAAK;AAAA,YAClD,WAAW,KAAK,OAAO,SAAS,cAAc;AAC5C,8BAAgB,KAAK,OAAO;AAAA,YAC9B,WAAW,KAAK,OAAO,SAAS,cAAc;AAC5C,8BAAgB,KAAK,UAAU,KAAK,OAAO,KAAK;AAAA,YAClD,OAAO;AACL,8BAAgB,KAAK,UAAU,KAAK,MAAM;AAAA,YAC5C;AAEA,oBAAQ,KAAK;AAAA,cACX,MAAM;AAAA,cACN,aAAa,KAAK;AAAA,cAClB,SAAS;AAAA,cACT,UAAU,KAAK,OAAO,KAAK,WAAW,OAAO;AAAA,YAC/C,CAAC;AAAA,UACH;AAAA,QACF;AAEA,YAAI,QAAQ,SAAS,GAAG;AACtB,mBAAS,KAAK,EAAE,MAAM,QAAQ,QAAQ,CAAC;AAAA,QACzC;AAAA,MACF;AAAA,IACF;AAEA,WAAO,EAAE,QAAQ,eAAe,SAAS;AAAA,EAC3C;AAAA;AAAA;AAAA;AAAA,EAKQ,oBAAoB,YAAwD;AAClF,YAAQ,YAAY;AAAA,MAClB,KAAK;AACH,eAAO;AAAA,MACT,KAAK;AACH,eAAO;AAAA,MACT,KAAK;AACH,eAAO;AAAA,MACT,KAAK;AACH,eAAO;AAAA,MACT;AACE,eAAO;AAAA,IACX;AAAA,EACF;AAAA,EAEA,MAAM,WAAW,SAKd;AACD,WAAO,KAAK,oBAAoB,SAAS,KAAK;AAAA,EAChD;AAAA,EAEA,MAAc,oBACZ,SACA,SAMC;AACD,UAAM,SAAS,MAAM,KAAK,mBAAmB,OAAO;AACpD,UAAM,EAAE,QAAQ,SAAS,IAAI,KAAK,cAAc,QAAQ,MAAM;AAC9D,UAAM,QAAQ,KAAK,aAAa,QAAQ,KAAK;AAC7C,UAAM,aACJ,QAAQ,YAAY,SAAS,SAAS,KAAK,kBAAkB,QAAQ,UAAU,IAAI;AAErF,UAAM,iBAAiB,KAAK,OAAO,kBAAkB;AACrD,UAAM,YAAY,QAAQ,mBAAmB,KAAK,OAAO,aAAa;AAEtE,QAAI;AACF,YAAM,WAAW,MAAM,OAAO,SAAS,OAAO;AAAA,QAC5C,OAAO;AAAA,QACP,YAAY;AAAA,QACZ;AAAA,QACA;AAAA,QACA;AAAA,QACA,aAAa,QAAQ,aAAa;AAAA,QAClC,aAAa,QAAQ;AAAA,QACrB,OAAO,QAAQ;AAAA,QACf,gBAAgB,QAAQ;AAAA,MAC1B,CAAC;AAED,YAAM,UAAoC,CAAC;AAE3C,iBAAW,SAAS,SAAS,SAAS;AACpC,YAAI,MAAM,SAAS,QAAQ;AACzB,kBAAQ,KAAK;AAAA,YACX,MAAM;AAAA,YACN,MAAM,MAAM;AAAA,UACd,CAAC;AAAA,QACH,WAAW,MAAM,SAAS,YAAY;AACpC,kBAAQ,KAAK;AAAA,YACX,MAAM;AAAA,YACN,YAAY,MAAM;AAAA,YAClB,UAAU,MAAM;AAAA,YAChB,OAAO,KAAK,UAAU,MAAM,KAAK;AAAA,UACnC,CAAC;AAAA,QACH;AAAA,MACF;AAEA,YAAM,QAA8B;AAAA,QAClC,aAAa,SAAS,MAAM;AAAA,QAC5B,cAAc,SAAS,MAAM;AAAA,QAC7B,aAAa,SAAS,MAAM,eAAe,SAAS,MAAM;AAAA,MAC5D;AAEA,aAAO;AAAA,QACL;AAAA,QACA,cAAc,KAAK,oBAAoB,SAAS,WAAW;AAAA,QAC3D;AAAA,QACA,UAAU,CAAC;AAAA,MACb;AAAA,IACF,SAAS,OAAO;AAEd,UAAI,KAAK,uBAAuB,KAAK,GAAG;AACtC,cAAM,WAAW;AACjB,cAAM,IAAI,YAAY;AAAA,UACpB,SAAS,qBAAqB,SAAS,OAAO;AAAA,UAC9C,YAAY;AAAA,UACZ,OAAO;AAAA,QACT,CAAC;AAAA,MACH;AAGA,UAAI,CAAC,WAAW,KAAK,aAAa,KAAK,GAAG;AACxC,aAAK,mBAAmB,gBAAgB;AACxC,eAAO,KAAK,oBAAoB,SAAS,IAAI;AAAA,MAC/C;AAEA,UAAI,iBAAiB,WAAAA,QAAU,UAAU;AACvC,cAAM,IAAI,YAAY;AAAA,UACpB,SAAS,wBAAwB,MAAM,OAAO;AAAA,UAC9C,YAAY,MAAM;AAAA,UAClB,OAAO;AAAA,QACT,CAAC;AAAA,MACH;AACA,YAAM;AAAA,IACR;AAAA,EACF;AAAA,EAEA,MAAM,SAAS,SAIZ;AACD,WAAO,KAAK,kBAAkB,SAAS,KAAK;AAAA,EAC9C;AAAA,EAEA,MAAc,kBACZ,SACA,SAKC;AACD,UAAM,SAAS,MAAM,KAAK,mBAAmB,OAAO;AACpD,UAAM,EAAE,QAAQ,SAAS,IAAI,KAAK,cAAc,QAAQ,MAAM;AAC9D,UAAM,QAAQ,KAAK,aAAa,QAAQ,KAAK;AAC7C,UAAM,aACJ,QAAQ,YAAY,SAAS,SAAS,KAAK,kBAAkB,QAAQ,UAAU,IAAI;AAErF,UAAM,iBAAiB,KAAK,OAAO,kBAAkB;AACrD,UAAM,YAAY,QAAQ,mBAAmB,KAAK,OAAO,aAAa;AAEtE,UAAM,cAAc;AAAA,MAClB,OAAO;AAAA,MACP,YAAY;AAAA,MACZ;AAAA,MACA;AAAA,MACA;AAAA,MACA,aAAa,QAAQ,aAAa;AAAA,MAClC,aAAa,QAAQ;AAAA,MACrB,OAAO,QAAQ;AAAA,MACf,gBAAgB,QAAQ;AAAA,MACxB,QAAQ;AAAA,IACV;AAIA,UAAM,OAAO;AAEb,UAAM,SAAS,IAAI,eAA0C;AAAA,MAC3D,OAAO,OAAO,eAAe;AAC3B,cAAM,gBAIF,CAAC;AAEL,cAAM,QAA8B;AAAA,UAClC,aAAa;AAAA,UACb,cAAc;AAAA,UACd,aAAa;AAAA,QACf;AACA,YAAI,eAA4C;AAEhD,YAAI;AACF,gBAAM,kBAAkB,OAAO,SAAS,OAAO,aAAa;AAAA,YAC1D,QAAQ,QAAQ;AAAA,UAClB,CAAC;AAGD,qBAAW,QAAQ;AAAA,YACjB,MAAM;AAAA,YACN,UAAU,CAAC;AAAA,UACb,CAAC;AAGD,gBAAM,IAAI,QAAc,CAACC,UAAS,WAAW;AAC3C,4BAAgB,GAAG,eAAe,CAAC,UAAU;AAC3C,kBAAI;AACF,wBAAQ,MAAM,MAAM;AAAA,kBAClB,KAAK;AACH,wBAAI,MAAM,QAAQ,OAAO;AACvB,4BAAM,cAAc,MAAM,QAAQ,MAAM;AAAA,oBAC1C;AACA,+BAAW,QAAQ;AAAA,sBACjB,MAAM;AAAA,sBACN,IAAI,MAAM,QAAQ;AAAA,sBAClB,SAAS,MAAM,QAAQ;AAAA,oBACzB,CAAC;AACD;AAAA,kBAEF,KAAK;AACH,wBAAI,MAAM,cAAc,SAAS,QAAQ;AACvC,4BAAM,SAAS,QAAQ,MAAM,KAAK;AAClC,oCAAc,MAAM,KAAK,IAAI,EAAE,MAAM,QAAQ,IAAI,OAAO;AACxD,iCAAW,QAAQ;AAAA,wBACjB,MAAM;AAAA,wBACN,IAAI;AAAA,sBACN,CAAC;AAAA,oBACH,WAAW,MAAM,cAAc,SAAS,YAAY;AAClD,oCAAc,MAAM,KAAK,IAAI;AAAA,wBAC3B,MAAM;AAAA,wBACN,YAAY,MAAM,cAAc;AAAA,wBAChC,UAAU,MAAM,cAAc;AAAA,wBAC9B,OAAO;AAAA,sBACT;AACA,iCAAW,QAAQ;AAAA,wBACjB,MAAM;AAAA,wBACN,IAAI,MAAM,cAAc;AAAA,wBACxB,UAAU,MAAM,cAAc;AAAA,sBAChC,CAAC;AAAA,oBACH;AACA;AAAA,kBAEF,KAAK,uBAAuB;AAC1B,0BAAM,QAAQ,cAAc,MAAM,KAAK;AACvC,wBAAI,MAAM,MAAM,SAAS,gBAAgB,OAAO,SAAS,QAAQ;AAC/D,iCAAW,QAAQ;AAAA,wBACjB,MAAM;AAAA,wBACN,IAAI,MAAM;AAAA,wBACV,OAAO,MAAM,MAAM;AAAA,sBACrB,CAAC;AAAA,oBACH,WACE,MAAM,MAAM,SAAS,sBACrB,OAAO,SAAS,aAChB;AACA,4BAAM,SAAS,MAAM,MAAM;AAC3B,iCAAW,QAAQ;AAAA,wBACjB,MAAM;AAAA,wBACN,IAAI,MAAM;AAAA,wBACV,OAAO,MAAM,MAAM;AAAA,sBACrB,CAAC;AAAA,oBACH;AACA;AAAA,kBACF;AAAA,kBAEA,KAAK,sBAAsB;AACzB,0BAAM,QAAQ,cAAc,MAAM,KAAK;AACvC,wBAAI,OAAO,SAAS,QAAQ;AAC1B,iCAAW,QAAQ;AAAA,wBACjB,MAAM;AAAA,wBACN,IAAI,MAAM;AAAA,sBACZ,CAAC;AAAA,oBACH,WAAW,OAAO,SAAS,aAAa;AACtC,iCAAW,QAAQ;AAAA,wBACjB,MAAM;AAAA,wBACN,IAAI,MAAM;AAAA,sBACZ,CAAC;AAED,iCAAW,QAAQ;AAAA,wBACjB,MAAM;AAAA,wBACN,YAAY,MAAM;AAAA,wBAClB,UAAU,MAAM;AAAA,wBAChB,OAAO,MAAM,UAAU,KAAK,OAAO,MAAM;AAAA,sBAC3C,CAAC;AAAA,oBACH;AACA,2BAAO,cAAc,MAAM,KAAK;AAChC;AAAA,kBACF;AAAA,kBAEA,KAAK;AACH,wBAAI,MAAM,OAAO;AACf,4BAAM,eAAe,MAAM,MAAM;AACjC,4BAAM,eAAe,MAAM,eAAe,KAAK,MAAM,MAAM;AAAA,oBAC7D;AACA,wBAAI,MAAM,MAAM,aAAa;AAC3B,qCAAe,KAAK,oBAAoB,MAAM,MAAM,WAAW;AAAA,oBACjE;AACA;AAAA,kBAEF,KAAK,gBAAgB;AACnB,+BAAW,QAAQ;AAAA,sBACjB,MAAM;AAAA,sBACN;AAAA,sBACA;AAAA,oBACF,CAAC;AACD;AAAA,kBACF;AAAA,gBACF;AAAA,cACF,QAAQ;AAAA,cAER;AAAA,YACF,CAAC;AAED,4BAAgB,GAAG,OAAO,MAAM;AAC9B,cAAAA,SAAQ;AAAA,YACV,CAAC;AAED,4BAAgB,GAAG,SAAS,CAAC,UAAU;AACrC,qBAAO,KAAK;AAAA,YACd,CAAC;AAAA,UACH,CAAC;AAGD,qBAAW,CAAC,EAAE,KAAK,KAAK,OAAO,QAAQ,aAAa,GAAG;AACrD,gBAAI,MAAM,SAAS,aAAa;AAC9B,yBAAW,QAAQ;AAAA,gBACjB,MAAM;AAAA,gBACN,IAAI,MAAM;AAAA,cACZ,CAAC;AACD,yBAAW,QAAQ;AAAA,gBACjB,MAAM;AAAA,gBACN,YAAY,MAAM;AAAA,gBAClB,UAAU,MAAM;AAAA,gBAChB,OAAO,MAAM,UAAU,KAAK,OAAO,MAAM;AAAA,cAC3C,CAAC;AAAA,YACH;AAAA,UACF;AAEA,qBAAW,MAAM;AAAA,QACnB,SAAS,OAAO;AAEd,qBAAW,CAAC,EAAE,KAAK,KAAK,OAAO,QAAQ,aAAa,GAAG;AACrD,gBAAI,MAAM,SAAS,aAAa;AAC9B,yBAAW,QAAQ;AAAA,gBACjB,MAAM;AAAA,gBACN,IAAI,MAAM;AAAA,cACZ,CAAC;AACD,yBAAW,QAAQ;AAAA,gBACjB,MAAM;AAAA,gBACN,YAAY,MAAM;AAAA,gBAClB,UAAU,MAAM;AAAA,gBAChB,OAAO,MAAM,UAAU,KAAK,OAAO,MAAM;AAAA,cAC3C,CAAC;AAAA,YACH;AAAA,UACF;AAGA,cAAI,KAAK,uBAAuB,KAAK,GAAG;AACtC,kBAAM,WAAW;AACjB,uBAAW,QAAQ;AAAA,cACjB,MAAM;AAAA,cACN,OAAO,IAAI,YAAY;AAAA,gBACrB,SAAS,qBAAqB,SAAS,OAAO;AAAA,gBAC9C,YAAY;AAAA,gBACZ,OAAO;AAAA,cACT,CAAC;AAAA,YACH,CAAC;AACD,uBAAW,MAAM;AACjB;AAAA,UACF;AAIA,cAAI,CAAC,WAAW,KAAK,aAAa,KAAK,GAAG;AACxC,iBAAK,mBAAmB,gBAAgB;AAExC,uBAAW,QAAQ;AAAA,cACjB,MAAM;AAAA,cACN,OAAO,IAAI,YAAY;AAAA,gBACrB,SAAS;AAAA,gBACT,OAAO;AAAA,cACT,CAAC;AAAA,YACH,CAAC;AACD,uBAAW,MAAM;AACjB;AAAA,UACF;AAEA,cAAI,iBAAiB,WAAAD,QAAU,UAAU;AACvC,uBAAW,QAAQ;AAAA,cACjB,MAAM;AAAA,cACN,OAAO,IAAI,YAAY;AAAA,gBACrB,SAAS,wBAAwB,MAAM,OAAO;AAAA,gBAC9C,YAAY,MAAM;AAAA,gBAClB,OAAO;AAAA,cACT,CAAC;AAAA,YACH,CAAC;AAAA,UACH,OAAO;AACL,uBAAW,QAAQ;AAAA,cACjB,MAAM;AAAA,cACN;AAAA,YACF,CAAC;AAAA,UACH;AACA,qBAAW,MAAM;AAAA,QACnB;AAAA,MACF;AAAA,IACF,CAAC;AAED,WAAO;AAAA,MACL;AAAA,MACA,SAAS,EAAE,MAAM,YAAY;AAAA,IAC/B;AAAA,EACF;AACF;;;AG7rBA,oBAAmB;;;ACWZ,IAAM,iBAA+C;AAAA;AAAA,EAE1D,qBAAqB,EAAE,UAAU,aAAa,OAAO,2BAA2B;AAAA,EAChF,uBAAuB,EAAE,UAAU,aAAa,OAAO,6BAA6B;AAAA,EACpF,sBAAsB,EAAE,UAAU,aAAa,OAAO,4BAA4B;AAAA;AAAA,EAGlF,oBAAoB,EAAE,UAAU,UAAU,OAAO,sBAAsB,eAAe,OAAO;AAAA,EAC7F,oBAAoB,EAAE,UAAU,UAAU,OAAO,sBAAsB,eAAe,OAAO;AAAA,EAC7F,uBAAuB;AAAA,IACrB,UAAU;AAAA,IACV,OAAO;AAAA,IACP,eAAe;AAAA,EACjB;AAAA;AAAA,EAGA,wBAAwB,EAAE,UAAU,UAAU,OAAO,eAAe,eAAe,YAAY;AAAA,EAC/F,0BAA0B;AAAA,IACxB,UAAU;AAAA,IACV,OAAO;AAAA,IACP,eAAe;AAAA,EACjB;AACF;AAEO,SAAS,gBAAgB,SAA2C;AACzE,SAAO,eAAe,OAAO;AAC/B;AAEO,SAAS,sBAAsB,SAA4C;AAChF,SAAO,eAAe,OAAO,GAAG;AAClC;AAEO,SAAS,0BAA0B,UAAmC;AAC3E,SAAO,OAAO,OAAO,cAAc,EAChC,OAAO,CAAC,MAAM,EAAE,aAAa,QAAQ,EACrC,IAAI,CAAC,MAAM,EAAE,KAAK;AACvB;AAEO,SAAS,4BAA4B,SAAqC;AAC/E,QAAM,UAAU,eAAe,OAAO;AACtC,SAAO,SAAS,aAAa,cAAc,QAAQ,QAAQ;AAC7D;AAEO,SAAS,yBAAyB,SAAqC;AAC5E,QAAM,UAAU,eAAe,OAAO;AACtC,SAAO,SAAS,aAAa,WAAW,QAAQ,QAAQ;AAC1D;AAEO,SAAS,iBAAiB,SAAgC;AAC/D,QAAM,UAAU,eAAe,OAAO;AACtC,SAAO,SAAS,iBAAiB;AACnC;AAEO,SAAS,oBAAoB,SAA0B;AAC5D,SAAO,iBAAiB,OAAO,MAAM;AACvC;AAEO,IAAM,8BAAsD,OAAO;AAAA,EACxE,OAAO,QAAQ,cAAc,EAC1B,OAAO,CAAC,CAAC,EAAE,CAAC,MAAM,EAAE,aAAa,WAAW,EAC5C,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC;AACjC;;;ADjCO,IAAM,4BAAN,MAA2D;AAAA,EACvD,uBAAuB;AAAA,EACvB;AAAA,EACA,gBAA0C,CAAC;AAAA,EAEnC;AAAA,EACA;AAAA,EACA;AAAA,EACT,eAA8B;AAAA,EAEtC,YAAY,SAAiB,QAA4B;AACvD,SAAK,UAAU;AACf,SAAK,SAAS;AACd,SAAK,kBAAkB,OAAO,mBAAmB,oBAAoB,OAAO;AAE5E,SAAK,qBAAqB,IAAI,yBAAyB;AAAA,MACrD,aAAa,OAAO;AAAA,MACpB,YAAY,OAAO;AAAA,MACnB,eAAe,OAAO;AAAA,MACtB,OAAO,OAAO;AAAA,MACd,cAAc,OAAO;AAAA,MACrB,cAAc,OAAO;AAAA,IACvB,CAAC;AAAA,EACH;AAAA,EAEA,IAAI,WAAmB;AACrB,WAAO,KAAK,OAAO;AAAA,EACrB;AAAA,EAEA,MAAc,gBAAgB,eAAwB,OAAwB;AAC5E,UAAM,YAAY,MAAM,KAAK,mBAAmB,qBAAqB,YAAY;AACjF,UAAM,EAAE,aAAa,UAAU,GAAG,gBAAgB,IAAI,UAAU;AAGhE,UAAM,gBAAgB;AAAA,MACpB,GAAG;AAAA,MACH,GAAG,KAAK,OAAO;AAAA,IACjB;AAEA,SAAK,eAAe,IAAI,cAAAE,QAAO;AAAA,MAC7B,QAAQ,UAAU;AAAA,MAClB,SAAS,KAAK,mBAAmB,kBAAkB;AAAA,MACnD,gBAAgB;AAAA,IAClB,CAAC;AAED,WAAO,KAAK;AAAA,EACd;AAAA,EAEQ,aAAa,OAAyB;AAC5C,QAAI,iBAAiB,cAAAA,QAAO,UAAU;AACpC,UAAI,MAAM,WAAW,KAAK;AACxB,eAAO;AAAA,MACT;AACA,YAAM,UAAU,MAAM,SAAS,YAAY,KAAK;AAChD,UACE,QAAQ,SAAS,OAAO,MACvB,QAAQ,SAAS,SAAS,KAAK,QAAQ,SAAS,SAAS,KAAK,QAAQ,SAAS,SAAS,IACzF;AACA,eAAO;AAAA,MACT;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,uBAAuB,OAAyB;AACtD,QAAI,iBAAiB,cAAAA,QAAO,UAAU;AAEpC,UAAI,MAAM,WAAW,KAAK;AACxB,cAAM,UAAU,MAAM,SAAS,YAAY,KAAK;AAChD,YACE,QAAQ,SAAS,oBAAoB,KACrC,QAAQ,SAAS,iBAAiB,KACjC,QAAQ,SAAS,QAAQ,KAAK,QAAQ,SAAS,SAAS,GACzD;AACA,iBAAO;AAAA,QACT;AAAA,MACF;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA,EAEQ,aACN,OACyC;AACzC,QAAI,CAAC,SAAS,MAAM,WAAW,GAAG;AAChC,aAAO;AAAA,IACT;AAEA,WAAO,MACJ,OAAO,CAAC,SAA8C,KAAK,SAAS,UAAU,EAC9E,IAAI,CAAC,SAAS;AACb,YAAM,SAAS,KAAK;AACpB,aAAO;AAAA,QACL,MAAM;AAAA,QACN,UAAU;AAAA,UACR,MAAM,KAAK;AAAA,UACX,aAAa,KAAK,eAAe;AAAA;AAAA,UAEjC,YAAY;AAAA,YACV,MAAM;AAAA,YACN,GAAG;AAAA,UACL;AAAA,QACF;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACL;AAAA,EAEQ,kBACN,YACmD;AACnD,QAAI,CAAC,YAAY;AACf,aAAO;AAAA,IACT;AAEA,YAAQ,WAAW,MAAM;AAAA,MACvB,KAAK;AACH,eAAO;AAAA,MACT,KAAK;AACH,eAAO;AAAA,MACT,KAAK;AACH,eAAO;AAAA,MACT,KAAK;AACH,eAAO,EAAE,MAAM,YAAY,UAAU,EAAE,MAAM,WAAW,SAAS,EAAE;AAAA,MACrE;AACE,eAAO;AAAA,IACX;AAAA,EACF;AAAA,EAEQ,cAAc,QAAuE;AAC3F,UAAM,WAAgD,CAAC;AAEvD,eAAW,WAAW,QAAQ;AAC5B,UAAI,QAAQ,SAAS,UAAU;AAC7B,iBAAS,KAAK,EAAE,MAAM,UAAU,SAAS,QAAQ,QAAQ,CAAC;AAC1D;AAAA,MACF;AAEA,UAAI,QAAQ,SAAS,QAAQ;AAC3B,cAAM,YAAY,QAAQ,QACvB,OAAO,CAAC,SAAS,KAAK,SAAS,MAAM,EACrC,IAAI,CAAC,SAAS,KAAK,IAAI;AAC1B,YAAI,UAAU,SAAS,GAAG;AACxB,mBAAS,KAAK,EAAE,MAAM,QAAQ,SAAS,UAAU,KAAK,IAAI,EAAE,CAAC;AAAA,QAC/D;AAAA,MACF,WAAW,QAAQ,SAAS,aAAa;AACvC,cAAM,YAAsB,CAAC;AAC7B,cAAM,YAAoD,CAAC;AAE3D,mBAAW,QAAQ,QAAQ,SAAS;AAClC,cAAI,KAAK,SAAS,QAAQ;AACxB,sBAAU,KAAK,KAAK,IAAI;AAAA,UAC1B,WAAW,KAAK,SAAS,aAAa;AACpC,sBAAU,KAAK;AAAA,cACb,IAAI,KAAK;AAAA,cACT,MAAM;AAAA,cACN,UAAU;AAAA,gBACR,MAAM,KAAK;AAAA,gBACX,WAAW,OAAO,KAAK,UAAU,WAAW,KAAK,QAAQ,KAAK,UAAU,KAAK,KAAK;AAAA,cACpF;AAAA,YACF,CAAC;AAAA,UACH;AAAA,QACF;AAEA,cAAM,mBAA+D;AAAA,UACnE,MAAM;AAAA,UACN,SAAS,UAAU,SAAS,IAAI,UAAU,KAAK,IAAI,IAAI;AAAA,QACzD;AACA,YAAI,UAAU,SAAS,GAAG;AACxB,2BAAiB,aAAa;AAAA,QAChC;AACA,iBAAS,KAAK,gBAAgB;AAAA,MAChC,WAAW,QAAQ,SAAS,QAAQ;AAClC,mBAAW,QAAQ,QAAQ,SAAS;AAClC,cAAI,KAAK,SAAS,eAAe;AAC/B,gBAAI;AACJ,gBAAI,KAAK,OAAO,SAAS,QAAQ;AAC/B,8BAAgB,KAAK,OAAO;AAAA,YAC9B,WAAW,KAAK,OAAO,SAAS,QAAQ;AACtC,8BAAgB,KAAK,UAAU,KAAK,OAAO,KAAK;AAAA,YAClD,WAAW,KAAK,OAAO,SAAS,cAAc;AAC5C,8BAAgB,KAAK,OAAO;AAAA,YAC9B,WAAW,KAAK,OAAO,SAAS,cAAc;AAC5C,8BAAgB,KAAK,UAAU,KAAK,OAAO,KAAK;AAAA,YAClD,OAAO;AACL,8BAAgB,KAAK,UAAU,KAAK,MAAM;AAAA,YAC5C;AACA,qBAAS,KAAK;AAAA,cACZ,MAAM;AAAA,cACN,cAAc,KAAK;AAAA,cACnB,SAAS;AAAA,YACX,CAAC;AAAA,UACH;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA,EAEQ,oBACN,cAC6B;AAC7B,YAAQ,cAAc;AAAA,MACpB,KAAK;AACH,eAAO;AAAA,MACT,KAAK;AACH,eAAO;AAAA,MACT,KAAK;AACH,eAAO;AAAA,MACT,KAAK;AACH,eAAO;AAAA,MACT;AACE,eAAO;AAAA,IACX;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,yBACN,OAC6C;AAC7C,QAAI,CAAC,SAAS,MAAM,WAAW,GAAG;AAChC,aAAO;AAAA,IACT;AAEA,WAAO,MACJ,OAAO,CAAC,SAA8C,KAAK,SAAS,UAAU,EAC9E,IAAI,CAAC,SAAS;AAGb,YAAM,SAAS,EAAE,GAAI,KAAK,YAAwC;AAClE,aAAO,OAAO,SAAS;AAEvB,aAAO;AAAA,QACL,MAAM;AAAA,QACN,MAAM,KAAK;AAAA,QACX,aAAa,KAAK,eAAe;AAAA,QACjC,YAAY;AAAA,QACZ,QAAQ;AAAA,MACV;AAAA,IACF,CAAC;AAAA,EACL;AAAA;AAAA;AAAA;AAAA,EAKQ,0BACN,QACgC;AAChC,UAAM,QAA8C,CAAC;AAErD,eAAW,WAAW,QAAQ;AAC5B,UAAI,QAAQ,SAAS,UAAU;AAE7B;AAAA,MACF;AAEA,UAAI,QAAQ,SAAS,QAAQ;AAC3B,cAAM,YAAY,QAAQ,QACvB,OAAO,CAAC,SAAS,KAAK,SAAS,MAAM,EACrC,IAAI,CAAC,SAAS,KAAK,IAAI;AAC1B,YAAI,UAAU,SAAS,GAAG;AACxB,gBAAM,KAAK;AAAA,YACT,MAAM;AAAA,YACN,MAAM;AAAA,YACN,SAAS,UAAU,IAAI,CAAC,UAAU,EAAE,MAAM,cAAuB,KAAK,EAAE;AAAA,UAC1E,CAAuC;AAAA,QACzC;AAAA,MACF,WAAW,QAAQ,SAAS,aAAa;AAEvC,cAAM,YAAsB,CAAC;AAC7B,mBAAW,QAAQ,QAAQ,SAAS;AAClC,cAAI,KAAK,SAAS,QAAQ;AACxB,sBAAU,KAAK,KAAK,IAAI;AAAA,UAC1B,WAAW,KAAK,SAAS,aAAa;AAEpC,kBAAM,KAAK;AAAA,cACT,MAAM;AAAA,cACN,SAAS,KAAK;AAAA,cACd,MAAM,KAAK;AAAA,cACX,WAAW,OAAO,KAAK,UAAU,WAAW,KAAK,QAAQ,KAAK,UAAU,KAAK,KAAK;AAAA,YACpF,CAAuC;AAAA,UACzC;AAAA,QACF;AAEA,YAAI,UAAU,SAAS,GAAG;AACxB,gBAAM,KAAK;AAAA,YACT,MAAM;AAAA,YACN,MAAM;AAAA,YACN,SAAS,CAAC,EAAE,MAAM,eAAe,MAAM,UAAU,KAAK,IAAI,GAAG,aAAa,CAAC,EAAE,CAAC;AAAA,UAChF,CAAuC;AAAA,QACzC;AAAA,MACF,WAAW,QAAQ,SAAS,QAAQ;AAClC,mBAAW,QAAQ,QAAQ,SAAS;AAClC,cAAI,KAAK,SAAS,eAAe;AAC/B,gBAAI;AACJ,gBAAI,KAAK,OAAO,SAAS,QAAQ;AAC/B,8BAAgB,KAAK,OAAO;AAAA,YAC9B,WAAW,KAAK,OAAO,SAAS,QAAQ;AACtC,8BAAgB,KAAK,UAAU,KAAK,OAAO,KAAK;AAAA,YAClD,WAAW,KAAK,OAAO,SAAS,cAAc;AAC5C,8BAAgB,KAAK,OAAO;AAAA,YAC9B,WAAW,KAAK,OAAO,SAAS,cAAc;AAC5C,8BAAgB,KAAK,UAAU,KAAK,OAAO,KAAK;AAAA,YAClD,OAAO;AACL,8BAAgB,KAAK,UAAU,KAAK,MAAM;AAAA,YAC5C;AACA,kBAAM,KAAK;AAAA,cACT,MAAM;AAAA,cACN,SAAS,KAAK;AAAA,cACd,QAAQ;AAAA,YACV,CAAuC;AAAA,UACzC;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKQ,0BAA0B,QAAsD;AACtF,UAAM,iBAAiB,OACpB,OAAO,CAAC,MAAM,EAAE,SAAS,QAAQ,EACjC,IAAI,CAAC,MAAM,EAAE,OAAO,EACpB,KAAK,IAAI;AACZ,WAAO,kBAAkB;AAAA,EAC3B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,uBACN,QACA,eAAwB,OACK;AAE7B,QAAI,cAAc;AAChB,aAAO;AAAA,IACT;AAEA,YAAQ,QAAQ;AAAA,MACd,KAAK;AACH,eAAO;AAAA,MACT,KAAK;AACH,eAAO;AAAA,MACT,KAAK;AACH,eAAO;AAAA,MACT,KAAK;AACH,eAAO;AAAA,MACT;AACE,eAAO;AAAA,IACX;AAAA,EACF;AAAA,EAEA,MAAM,WAAW,SAKd;AACD,QAAI,KAAK,iBAAiB;AACxB,aAAO,KAAK,2BAA2B,SAAS,KAAK;AAAA,IACvD;AACA,WAAO,KAAK,sBAAsB,SAAS,KAAK;AAAA,EAClD;AAAA,EAEA,MAAc,sBACZ,SACA,SAMC;AACD,UAAM,SAAS,MAAM,KAAK,gBAAgB,OAAO;AACjD,UAAM,WAAW,KAAK,cAAc,QAAQ,MAAM;AAClD,UAAM,QAAQ,KAAK,aAAa,QAAQ,KAAK;AAC7C,UAAM,aACJ,QAAQ,YAAY,SAAS,SAAS,KAAK,kBAAkB,QAAQ,UAAU,IAAI;AAErF,UAAM,cAAc,KAAK,OAAO,eAAe;AAC/C,UAAM,YAAY,QAAQ,mBAAmB,KAAK,OAAO,aAAa;AAEtE,QAAI;AACF,YAAM,WAAW,MAAM,OAAO,KAAK,YAAY,OAAO;AAAA,QACpD,OAAO;AAAA,QACP,uBAAuB;AAAA,QACvB;AAAA,QACA;AAAA,QACA,aAAa,QAAQ,aAAa;AAAA,QAClC,aAAa,QAAQ;AAAA,QACrB,OAAO,QAAQ;AAAA,QACf,MAAM,QAAQ;AAAA,MAChB,CAAC;AAED,YAAM,SAAS,SAAS,QAAQ,CAAC;AACjC,YAAM,UAAoC,CAAC;AAE3C,UAAI,QAAQ,QAAQ,SAAS;AAC3B,gBAAQ,KAAK,EAAE,MAAM,QAAQ,MAAM,OAAO,QAAQ,QAAQ,CAAC;AAAA,MAC7D;AAEA,UAAI,QAAQ,QAAQ,YAAY;AAC9B,mBAAW,YAAY,OAAO,QAAQ,YAAY;AAChD,cAAI,SAAS,SAAS,YAAY;AAChC,oBAAQ,KAAK;AAAA,cACX,MAAM;AAAA,cACN,YAAY,SAAS;AAAA,cACrB,UAAU,SAAS,SAAS;AAAA,cAC5B,OAAO,SAAS,SAAS;AAAA,YAC3B,CAAC;AAAA,UACH;AAAA,QACF;AAAA,MACF;AAEA,YAAM,QAA8B;AAAA,QAClC,aAAa,SAAS,OAAO,iBAAiB;AAAA,QAC9C,cAAc,SAAS,OAAO,qBAAqB;AAAA,QACnD,aAAa,SAAS,OAAO,gBAAgB;AAAA,MAC/C;AAEA,aAAO;AAAA,QACL;AAAA,QACA,cAAc,KAAK,oBAAoB,QAAQ,aAAa;AAAA,QAC5D;AAAA,QACA,UAAU,CAAC;AAAA,MACb;AAAA,IACF,SAAS,OAAO;AAEd,UAAI,KAAK,uBAAuB,KAAK,GAAG;AACtC,cAAM,WAAW;AACjB,cAAM,IAAI,YAAY;AAAA,UACpB,SAAS,qBAAqB,SAAS,OAAO;AAAA,UAC9C,YAAY;AAAA,UACZ,OAAO;AAAA,QACT,CAAC;AAAA,MACH;AAEA,UAAI,CAAC,WAAW,KAAK,aAAa,KAAK,GAAG;AACxC,aAAK,mBAAmB,gBAAgB;AACxC,eAAO,KAAK,sBAAsB,SAAS,IAAI;AAAA,MACjD;AAEA,UAAI,iBAAiB,cAAAA,QAAO,UAAU;AACpC,cAAM,IAAI,YAAY;AAAA,UACpB,SAAS,qBAAqB,MAAM,OAAO;AAAA,UAC3C,YAAY,MAAM;AAAA,UAClB,OAAO;AAAA,QACT,CAAC;AAAA,MACH;AACA,YAAM;AAAA,IACR;AAAA,EACF;AAAA,EAEA,MAAc,2BACZ,SACA,SAMC;AACD,UAAM,SAAS,MAAM,KAAK,gBAAgB,OAAO;AACjD,UAAM,QAAQ,KAAK,0BAA0B,QAAQ,MAAM;AAC3D,UAAM,QAAQ,KAAK,yBAAyB,QAAQ,KAAK;AACzD,UAAM,eAAe,KAAK,0BAA0B,QAAQ,MAAM;AAElE,UAAM,cAAc,KAAK,OAAO,eAAe;AAC/C,UAAM,YAAY,QAAQ,mBAAmB,KAAK,OAAO,aAAa;AAEtE,QAAI;AACF,YAAM,WAAW,MAAM,OAAO,UAAU,OAAO;AAAA,QAC7C,OAAO;AAAA,QACP;AAAA,QACA;AAAA,QACA;AAAA,QACA,mBAAmB;AAAA,QACnB,aAAa,QAAQ;AAAA,QACrB,OAAO,QAAQ;AAAA,QACf,OAAO;AAAA,MACT,CAAC;AAED,YAAM,UAAoC,CAAC;AAC3C,UAAI,eAAe;AAGnB,iBAAW,QAAQ,SAAS,UAAU,CAAC,GAAG;AACxC,YAAI,KAAK,SAAS,aAAa,KAAK,SAAS,aAAa;AACxD,qBAAW,eAAe,KAAK,WAAW,CAAC,GAAG;AAC5C,gBAAI,YAAY,SAAS,eAAe;AACtC,sBAAQ,KAAK,EAAE,MAAM,QAAQ,MAAM,YAAY,KAAK,CAAC;AAAA,YACvD;AAAA,UACF;AAAA,QACF,WAAW,KAAK,SAAS,iBAAiB;AACxC,yBAAe;AACf,kBAAQ,KAAK;AAAA,YACX,MAAM;AAAA,YACN,YAAY,KAAK;AAAA,YACjB,UAAU,KAAK;AAAA,YACf,OAAO,KAAK;AAAA,UACd,CAAC;AAAA,QACH;AAAA,MACF;AAEA,YAAM,QAA8B;AAAA,QAClC,aAAa,SAAS,OAAO,gBAAgB;AAAA,QAC7C,cAAc,SAAS,OAAO,iBAAiB;AAAA,QAC/C,aAAa,SAAS,OAAO,gBAAgB;AAAA,MAC/C;AAEA,aAAO;AAAA,QACL;AAAA,QACA,cAAc,KAAK,uBAAuB,SAAS,QAAQ,YAAY;AAAA,QACvE;AAAA,QACA,UAAU,CAAC;AAAA,MACb;AAAA,IACF,SAAS,OAAO;AAEd,UAAI,KAAK,uBAAuB,KAAK,GAAG;AACtC,cAAM,WAAW;AACjB,cAAM,IAAI,YAAY;AAAA,UACpB,SAAS,qBAAqB,SAAS,OAAO;AAAA,UAC9C,YAAY;AAAA,UACZ,OAAO;AAAA,QACT,CAAC;AAAA,MACH;AAEA,UAAI,CAAC,WAAW,KAAK,aAAa,KAAK,GAAG;AACxC,aAAK,mBAAmB,gBAAgB;AACxC,eAAO,KAAK,2BAA2B,SAAS,IAAI;AAAA,MACtD;AAEA,UAAI,iBAAiB,cAAAA,QAAO,UAAU;AACpC,cAAM,IAAI,YAAY;AAAA,UACpB,SAAS,qBAAqB,MAAM,OAAO;AAAA,UAC3C,YAAY,MAAM;AAAA,UAClB,OAAO;AAAA,QACT,CAAC;AAAA,MACH;AACA,YAAM;AAAA,IACR;AAAA,EACF;AAAA,EAEA,MAAM,SAAS,SAIZ;AACD,QAAI,KAAK,iBAAiB;AACxB,aAAO,KAAK,yBAAyB,SAAS,KAAK;AAAA,IACrD;AACA,WAAO,KAAK,oBAAoB,SAAS,KAAK;AAAA,EAChD;AAAA,EAEA,MAAc,oBACZ,SACA,SAKC;AACD,UAAM,SAAS,MAAM,KAAK,gBAAgB,OAAO;AACjD,UAAM,WAAW,KAAK,cAAc,QAAQ,MAAM;AAClD,UAAM,QAAQ,KAAK,aAAa,QAAQ,KAAK;AAC7C,UAAM,aACJ,QAAQ,YAAY,SAAS,SAAS,KAAK,kBAAkB,QAAQ,UAAU,IAAI;AAErF,UAAM,cAAc,KAAK,OAAO,eAAe;AAC/C,UAAM,YAAY,QAAQ,mBAAmB,KAAK,OAAO,aAAa;AAEtE,UAAM,cAAc;AAAA,MAClB,OAAO;AAAA,MACP,uBAAuB;AAAA,MACvB;AAAA,MACA;AAAA,MACA,aAAa,QAAQ,aAAa;AAAA,MAClC,aAAa,QAAQ;AAAA,MACrB,OAAO,QAAQ;AAAA,MACf,MAAM,QAAQ;AAAA,MACd,QAAQ;AAAA,MACR,gBAAgB,EAAE,eAAe,KAAK;AAAA,IACxC;AAGA,UAAM,OAAO;AAEb,UAAM,SAAS,IAAI,eAA0C;AAAA,MAC3D,OAAO,OAAO,eAAe;AAC3B,cAAM,YAA6E,CAAC;AAEpF,cAAM,QAA8B;AAAA,UAClC,aAAa;AAAA,UACb,cAAc;AAAA,UACd,aAAa;AAAA,QACf;AACA,YAAI,eAA4C;AAChD,YAAI,cAAc;AAClB,cAAM,SAAS;AAEf,YAAI;AACF,gBAAM,eAAe,MAAM,OAAO,KAAK,YAAY,OAAO;AAAA,YACxD,GAAG;AAAA,YACH,QAAQ;AAAA,UACV,CAAC;AAED,qBAAW,QAAQ,EAAE,MAAM,gBAAgB,UAAU,CAAC,EAAE,CAAC;AAEzD,2BAAiB,SAAS,cAAc;AACtC,kBAAM,SAAS,MAAM,UAAU,CAAC;AAEhC,gBAAI,MAAM,MAAM,CAAC,aAAa;AAC5B,yBAAW,QAAQ;AAAA,gBACjB,MAAM;AAAA,gBACN,IAAI,MAAM;AAAA,gBACV,SAAS,MAAM;AAAA,cACjB,CAAC;AAAA,YACH;AAEA,gBAAI,QAAQ,OAAO,SAAS;AAC1B,kBAAI,CAAC,aAAa;AAChB,2BAAW,QAAQ,EAAE,MAAM,cAAc,IAAI,OAAO,CAAC;AACrD,8BAAc;AAAA,cAChB;AACA,yBAAW,QAAQ;AAAA,gBACjB,MAAM;AAAA,gBACN,IAAI;AAAA,gBACJ,OAAO,OAAO,MAAM;AAAA,cACtB,CAAC;AAAA,YACH;AAEA,gBAAI,QAAQ,OAAO,YAAY;AAC7B,yBAAW,MAAM,OAAO,MAAM,YAAY;AACxC,sBAAM,MAAM,GAAG;AACf,oBAAI,CAAC,UAAU,GAAG,GAAG;AACnB,4BAAU,GAAG,IAAI;AAAA,oBACf,IAAI,GAAG,MAAM;AAAA,oBACb,MAAM,GAAG,UAAU,QAAQ;AAAA,oBAC3B,WAAW;AAAA,kBACb;AACA,6BAAW,QAAQ;AAAA,oBACjB,MAAM;AAAA,oBACN,IAAI,UAAU,GAAG,EAAE;AAAA,oBACnB,UAAU,UAAU,GAAG,EAAE;AAAA,kBAC3B,CAAC;AAAA,gBACH;AACA,oBAAI,GAAG,UAAU,WAAW;AAC1B,4BAAU,GAAG,EAAE,aAAa,GAAG,SAAS;AACxC,6BAAW,QAAQ;AAAA,oBACjB,MAAM;AAAA,oBACN,IAAI,UAAU,GAAG,EAAE;AAAA,oBACnB,OAAO,GAAG,SAAS;AAAA,kBACrB,CAAC;AAAA,gBACH;AAAA,cACF;AAAA,YACF;AAEA,gBAAI,QAAQ,eAAe;AACzB,6BAAe,KAAK,oBAAoB,OAAO,aAAa;AAAA,YAC9D;AAEA,gBAAI,MAAM,OAAO;AACf,oBAAM,cAAc,MAAM,MAAM,iBAAiB;AACjD,oBAAM,eAAe,MAAM,MAAM,qBAAqB;AACtD,oBAAM,cAAc,MAAM,MAAM,gBAAgB;AAAA,YAClD;AAAA,UACF;AAEA,cAAI,aAAa;AACf,uBAAW,QAAQ,EAAE,MAAM,YAAY,IAAI,OAAO,CAAC;AAAA,UACrD;AAEA,qBAAW,CAAC,EAAE,EAAE,KAAK,OAAO,QAAQ,SAAS,GAAG;AAC9C,uBAAW,QAAQ,EAAE,MAAM,kBAAkB,IAAI,GAAG,GAAG,CAAC;AACxD,uBAAW,QAAQ;AAAA,cACjB,MAAM;AAAA,cACN,YAAY,GAAG;AAAA,cACf,UAAU,GAAG;AAAA,cACb,OAAO,GAAG,aAAa;AAAA,YACzB,CAAC;AAAA,UACH;AAEA,qBAAW,QAAQ,EAAE,MAAM,UAAU,cAAc,MAAM,CAAC;AAC1D,qBAAW,MAAM;AAAA,QACnB,SAAS,OAAO;AAEd,cAAI,KAAK,uBAAuB,KAAK,GAAG;AACtC,kBAAM,WAAW;AACjB,uBAAW,QAAQ;AAAA,cACjB,MAAM;AAAA,cACN,OAAO,IAAI,YAAY;AAAA,gBACrB,SAAS,qBAAqB,SAAS,OAAO;AAAA,gBAC9C,YAAY;AAAA,gBACZ,OAAO;AAAA,cACT,CAAC;AAAA,YACH,CAAC;AACD,uBAAW,MAAM;AACjB;AAAA,UACF;AAEA,cAAI,CAAC,WAAW,KAAK,aAAa,KAAK,GAAG;AACxC,iBAAK,mBAAmB,gBAAgB;AACxC,uBAAW,QAAQ;AAAA,cACjB,MAAM;AAAA,cACN,OAAO,IAAI,YAAY,EAAE,SAAS,wBAAwB,OAAO,MAAM,CAAC;AAAA,YAC1E,CAAC;AACD,uBAAW,MAAM;AACjB;AAAA,UACF;AAEA,cAAI,iBAAiB,cAAAA,QAAO,UAAU;AACpC,uBAAW,QAAQ;AAAA,cACjB,MAAM;AAAA,cACN,OAAO,IAAI,YAAY;AAAA,gBACrB,SAAS,qBAAqB,MAAM,OAAO;AAAA,gBAC3C,YAAY,MAAM;AAAA,gBAClB,OAAO;AAAA,cACT,CAAC;AAAA,YACH,CAAC;AAAA,UACH,OAAO;AACL,uBAAW,QAAQ,EAAE,MAAM,SAAS,MAAM,CAAC;AAAA,UAC7C;AACA,qBAAW,MAAM;AAAA,QACnB;AAAA,MACF;AAAA,IACF,CAAC;AAED,WAAO,EAAE,QAAQ,SAAS,EAAE,MAAM,YAAY,EAAE;AAAA,EAClD;AAAA,EAEA,MAAc,yBACZ,SACA,SAKC;AACD,UAAM,SAAS,MAAM,KAAK,gBAAgB,OAAO;AACjD,UAAM,QAAQ,KAAK,0BAA0B,QAAQ,MAAM;AAC3D,UAAM,QAAQ,KAAK,yBAAyB,QAAQ,KAAK;AACzD,UAAM,eAAe,KAAK,0BAA0B,QAAQ,MAAM;AAElE,UAAM,cAAc,KAAK,OAAO,eAAe;AAC/C,UAAM,YAAY,QAAQ,mBAAmB,KAAK,OAAO,aAAa;AAEtE,UAAM,cAAc;AAAA,MAClB,OAAO;AAAA,MACP;AAAA,MACA;AAAA,MACA;AAAA,MACA,mBAAmB;AAAA,MACnB,aAAa,QAAQ;AAAA,MACrB,OAAO,QAAQ;AAAA,MACf,OAAO;AAAA,MACP,QAAQ;AAAA,IACV;AAGA,UAAM,OAAO;AAEb,UAAM,SAAS,IAAI,eAA0C;AAAA,MAC3D,OAAO,OAAO,eAAe;AAE3B,cAAM,YAAiF,CAAC;AACxF,cAAM,QAA8B;AAAA,UAClC,aAAa;AAAA,UACb,cAAc;AAAA,UACd,aAAa;AAAA,QACf;AACA,YAAI,eAA4C;AAChD,YAAI,cAAc;AAClB,cAAM,SAAS;AAEf,YAAI;AACF,gBAAM,eAAe,MAAM,OAAO,UAAU,OAAO;AAAA,YACjD,GAAG;AAAA,YACH,QAAQ;AAAA,UACV,CAAC;AAED,qBAAW,QAAQ,EAAE,MAAM,gBAAgB,UAAU,CAAC,EAAE,CAAC;AAEzD,2BAAiB,SAAS,cAAc;AAEtC,gBAAI,MAAM,SAAS,oBAAoB;AACrC,yBAAW,QAAQ;AAAA,gBACjB,MAAM;AAAA,gBACN,IAAI,MAAM,SAAS;AAAA,gBACnB,SAAS,MAAM,SAAS;AAAA,cAC1B,CAAC;AAAA,YACH,WAAW,MAAM,SAAS,8BAA8B;AAEtD,kBAAI,MAAM,KAAK,SAAS,iBAAiB;AACvC,sBAAM,cAAc,MAAM;AAC1B,sBAAM,SAAS,MAAM,KAAK;AAC1B,0BAAU,WAAW,IAAI;AAAA,kBACvB;AAAA,kBACA,MAAM,MAAM,KAAK;AAAA,kBACjB,WAAW;AAAA,gBACb;AACA,2BAAW,QAAQ;AAAA,kBACjB,MAAM;AAAA,kBACN,IAAI;AAAA,kBACJ,UAAU,MAAM,KAAK;AAAA,gBACvB,CAAC;AAAA,cACH;AAAA,YACF,WAAW,MAAM,SAAS,8BAA8B;AACtD,kBAAI,CAAC,aAAa;AAChB,2BAAW,QAAQ,EAAE,MAAM,cAAc,IAAI,OAAO,CAAC;AACrD,8BAAc;AAAA,cAChB;AACA,yBAAW,QAAQ;AAAA,gBACjB,MAAM;AAAA,gBACN,IAAI;AAAA,gBACJ,OAAO,MAAM;AAAA,cACf,CAAC;AAAA,YACH,WAAW,MAAM,SAAS,0CAA0C;AAElE,oBAAM,cAAc,MAAM;AAC1B,oBAAM,KAAK,UAAU,WAAW;AAChC,kBAAI,IAAI;AACN,mBAAG,aAAa,MAAM;AACtB,2BAAW,QAAQ;AAAA,kBACjB,MAAM;AAAA,kBACN,IAAI,GAAG;AAAA,kBACP,OAAO,MAAM;AAAA,gBACf,CAAC;AAAA,cACH;AAAA,YACF,WAAW,MAAM,SAAS,yCAAyC;AACjE,oBAAM,cAAc,MAAM;AAC1B,oBAAM,KAAK,UAAU,WAAW;AAChC,kBAAI,IAAI;AACN,mBAAG,YAAY,MAAM;AAAA,cACvB;AAAA,YACF,WAAW,MAAM,SAAS,sBAAsB;AAE9C,oBAAMC,gBAAe,OAAO,KAAK,SAAS,EAAE,SAAS;AACrD,6BAAe,KAAK,uBAAuB,MAAM,SAAS,QAAQA,aAAY;AAC9E,kBAAI,MAAM,SAAS,OAAO;AACxB,sBAAM,cAAc,MAAM,SAAS,MAAM,gBAAgB;AACzD,sBAAM,eAAe,MAAM,SAAS,MAAM,iBAAiB;AAC3D,sBAAM,cAAc,MAAM,SAAS,MAAM,gBAAgB;AAAA,cAC3D;AAAA,YACF;AAAA,UACF;AAEA,cAAI,aAAa;AACf,uBAAW,QAAQ,EAAE,MAAM,YAAY,IAAI,OAAO,CAAC;AAAA,UACrD;AAGA,gBAAM,eAAe,OAAO,KAAK,SAAS,EAAE,SAAS;AACrD,cAAI,gBAAgB,iBAAiB,QAAQ;AAC3C,2BAAe;AAAA,UACjB;AAEA,qBAAW,MAAM,OAAO,OAAO,SAAS,GAAG;AACzC,uBAAW,QAAQ,EAAE,MAAM,kBAAkB,IAAI,GAAG,OAAO,CAAC;AAC5D,uBAAW,QAAQ;AAAA,cACjB,MAAM;AAAA,cACN,YAAY,GAAG;AAAA,cACf,UAAU,GAAG;AAAA,cACb,OAAO,GAAG,aAAa;AAAA,YACzB,CAAC;AAAA,UACH;AAEA,qBAAW,QAAQ,EAAE,MAAM,UAAU,cAAc,MAAM,CAAC;AAC1D,qBAAW,MAAM;AAAA,QACnB,SAAS,OAAO;AAEd,cAAI,KAAK,uBAAuB,KAAK,GAAG;AACtC,kBAAM,WAAW;AACjB,uBAAW,QAAQ;AAAA,cACjB,MAAM;AAAA,cACN,OAAO,IAAI,YAAY;AAAA,gBACrB,SAAS,qBAAqB,SAAS,OAAO;AAAA,gBAC9C,YAAY;AAAA,gBACZ,OAAO;AAAA,cACT,CAAC;AAAA,YACH,CAAC;AACD,uBAAW,MAAM;AACjB;AAAA,UACF;AAEA,cAAI,CAAC,WAAW,KAAK,aAAa,KAAK,GAAG;AACxC,iBAAK,mBAAmB,gBAAgB;AACxC,uBAAW,QAAQ;AAAA,cACjB,MAAM;AAAA,cACN,OAAO,IAAI,YAAY,EAAE,SAAS,wBAAwB,OAAO,MAAM,CAAC;AAAA,YAC1E,CAAC;AACD,uBAAW,MAAM;AACjB;AAAA,UACF;AAEA,cAAI,iBAAiB,cAAAD,QAAO,UAAU;AACpC,uBAAW,QAAQ;AAAA,cACjB,MAAM;AAAA,cACN,OAAO,IAAI,YAAY;AAAA,gBACrB,SAAS,qBAAqB,MAAM,OAAO;AAAA,gBAC3C,YAAY,MAAM;AAAA,gBAClB,OAAO;AAAA,cACT,CAAC;AAAA,YACH,CAAC;AAAA,UACH,OAAO;AACL,uBAAW,QAAQ,EAAE,MAAM,SAAS,MAAM,CAAC;AAAA,UAC7C;AACA,qBAAW,MAAM;AAAA,QACnB;AAAA,MACF;AAAA,IACF,CAAC;AAED,WAAO,EAAE,QAAQ,SAAS,EAAE,MAAM,YAAY,EAAE;AAAA,EAClD;AACF;;;AEr6BO,IAAM,oBAAoB;AAK1B,IAAM,iBAAiB;AAMvB,IAAM,uBAAuB,IAAI,KAAK;AAKtC,IAAM,eAAe,CAAC,KAAK;;;ACjB3B,IAAM,qBAAN,MAAyB;AAAA,EACtB;AAAA,EAER,YAAY,YAA0B,OAAO;AAC3C,SAAK,QAAQ;AAAA,EACf;AAAA;AAAA;AAAA;AAAA,EAKA,eAAe,WAA4B;AACzC,WAAO,KAAK,IAAI,KAAK;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA,EAKA,aAAa,WAA4B;AACvC,WAAO,KAAK,IAAI,KAAK,YAAY;AAAA,EACnC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,gBAAgB,QAA2B,UAA+C;AAC9F,QAAI,CAAC,KAAK,aAAa,OAAO,SAAS,GAAG;AACxC,aAAO;AAAA,IACT;AAEA,QAAI,KAAK,eAAe,OAAO,SAAS,GAAG;AACzC,YAAM,IAAI,YAAY;AAAA,QACpB,SAAS;AAAA,MACX,CAAC;AAAA,IACH;AAEA,WAAO,KAAK,qBAAqB;AAAA,MAC/B,aAAa,OAAO;AAAA,MACpB,cAAc,OAAO;AAAA,MACrB;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,0BAA0B,QAA6D;AAC3F,UAAM,EAAE,aAAa,MAAM,cAAc,UAAU,YAAY,IAAI;AAEnE,UAAM,gBAAgB,MAAM,KAAK,cAAc;AAAA,MAC7C;AAAA,MACA,WAAW;AAAA,MACX;AAAA,MACA;AAAA,MACA,UAAU,YAAY,KAAK,YAAY,WAAW;AAAA,MAClD;AAAA,IACF,CAAC;AAED,WAAO,KAAK,yBAAyB,eAAe,WAAW;AAAA,EACjE;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,qBAAqB,QAAwD;AACjF,UAAM,EAAE,aAAa,cAAc,SAAS,IAAI;AAEhD,UAAM,gBAAgB,MAAM,KAAK,cAAc;AAAA,MAC7C;AAAA,MACA,WAAW;AAAA,MACX;AAAA,MACA,UAAU,YAAY,KAAK,YAAY,WAAW;AAAA,IACpD,CAAC;AAED,WAAO,KAAK,yBAAyB,eAAe,WAAW;AAAA,EACjE;AAAA;AAAA;AAAA;AAAA,EAKQ,YAAY,aAA6B;AAE/C,QAAI,gBAAgB,gBAAgB;AAClC,aAAO;AAAA,IACT;AAEA,UAAM,IAAI,YAAY;AAAA,MACpB,SAAS,8CAA8C,WAAW;AAAA,IACpE,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAc,cAAc,QAQU;AACpC,UAAM,EAAE,aAAa,WAAW,MAAM,cAAc,cAAc,UAAU,YAAY,IACtF;AAEF,UAAM,OAA+B;AAAA,MACnC,WAAW;AAAA,MACX,YAAY;AAAA,IACd;AAEA,QAAI,cAAc,sBAAsB;AACtC,UAAI,CAAC,QAAQ,CAAC,gBAAgB,CAAC,aAAa;AAC1C,cAAM,IAAI,YAAY;AAAA,UACpB,SACE;AAAA,QACJ,CAAC;AAAA,MACH;AACA,WAAK,OAAO;AACZ,WAAK,gBAAgB;AACrB,WAAK,eAAe;AAAA,IACtB,WAAW,cAAc,iBAAiB;AACxC,UAAI,CAAC,cAAc;AACjB,cAAM,IAAI,YAAY;AAAA,UACpB,SAAS;AAAA,QACX,CAAC;AAAA,MACH;AACA,WAAK,gBAAgB;AAAA,IACvB;AAEA,UAAM,MAAM,GAAG,WAAW;AAE1B,QAAI;AACF,YAAM,WAAW,MAAM,KAAK,MAAM,KAAK;AAAA,QACrC,QAAQ;AAAA,QACR,SAAS;AAAA,UACP,gBAAgB;AAAA,QAClB;AAAA,QACA,MAAM,IAAI,gBAAgB,IAAI,EAAE,SAAS;AAAA,MAC3C,CAAC;AAED,UAAI,CAAC,SAAS,IAAI;AAChB,cAAM,YAAY,MAAM,SAAS,KAAK;AACtC,cAAM,IAAI,YAAY;AAAA,UACpB,SAAS,gCAAgC,SAAS,MAAM,IAAI,SAAS,UAAU;AAAA,UAC/E,OAAO,IAAI,MAAM,SAAS;AAAA,QAC5B,CAAC;AAAA,MACH;AAEA,YAAM,OAAO,MAAM,SAAS,KAAK;AACjC,aAAO;AAAA,IACT,SAAS,OAAO;AACd,UAAI,iBAAiB,aAAa;AAChC,cAAM;AAAA,MACR;AACA,YAAM,IAAI,YAAY;AAAA,QACpB,SAAS,mCAAmC,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;AAAA,QAClG,OAAO,iBAAiB,QAAQ,QAAQ;AAAA,MAC1C,CAAC;AAAA,IACH;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,yBACN,UACA,aACmB;AACnB,UAAM,YAAY,KAAK,uBAAuB,QAAQ;AAEtD,WAAO;AAAA,MACL,aAAa,SAAS;AAAA,MACtB,cAAc,SAAS,iBAAiB;AAAA,MACxC;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,uBAAuB,UAA4C;AAEzE,UAAM,YAAY,SAAS,aAAa;AACxC,UAAM,YAAY,SAAS,aAAa;AACxC,WAAO,YAAY;AAAA,EACrB;AACF;;;AC5NO,IAAM,UACX,OAA6C,UAAsB;;;ACKrE,SAAoB;AACpB,WAAsB;AACtB,SAAoB;AA4IpB,SAAS,sBAA8B;AACrC,QAAM,UAAa,WAAQ;AAG3B,QAAM,cAAc,QAAQ,IAAI;AAChC,MAAI,aAAa;AACf,WAAY,UAAK,aAAa,YAAY,WAAW;AAAA,EACvD;AAGA,MAAI,QAAQ,aAAa,SAAS;AAChC,WAAY,UAAK,SAAS,UAAU,SAAS,YAAY,WAAW;AAAA,EACtE;AAGA,SAAY,UAAK,SAAS,aAAa,WAAW;AACpD;AAKA,eAAe,iBAAiB,aAAwD;AACtF,MAAI;AACF,UAAM,WAAW,oBAAoB;AAErC,QAAI,CAAI,cAAW,QAAQ,GAAG;AAC5B,aAAO;AAAA,IACT;AAEA,UAAM,WAAW,KAAK,MAAS,gBAAa,UAAU,OAAO,CAAC;AAG9D,QAAI,SAAS,QAAQ,SAAS,SAAS;AACrC,YAAM,aAAa,SAAS;AAE5B,UACE,WAAW,kBAAkB,eAC7B,WAAW,kBAAkB,YAAY,QAAQ,OAAO,EAAE,GAC1D;AACA,eAAO;AAAA,MACT;AAAA,IACF;AAIA,UAAM,gBAAgB,YAAY,QAAQ,OAAO,EAAE;AACnD,UAAM,OAAO,SAAS,aAAa,KAAK,SAAS,GAAG,aAAa,GAAG;AAEpE,WAAO;AAAA,EACT,SAAS,OAAO;AAEd,WAAO;AAAA,EACT;AACF;AAMA,eAAe,WACb,SAKA,aACA,UACiB;AAEjB,MAAI,QAAQ,QAAQ;AAClB,WAAO,QAAQ;AAAA,EACjB;AAGA,QAAM,OAAO,MAAM,iBAAiB,WAAW;AAC/C,MAAI,MAAM,SAAS,SAAS;AAC1B,UAAM,eAAe,IAAI,mBAAmB;AAG5C,QAAI,aAAa,aAAa,KAAK,OAAO,GAAG;AAC3C,UAAI;AACF,cAAM,YAAY,MAAM,aAAa,qBAAqB;AAAA,UACxD;AAAA,UACA,cAAc,KAAK;AAAA,UACnB;AAAA,QACF,CAAC;AAGD,cAAM,WAAW,oBAAoB;AACrC,cAAM,WAAW,KAAK,MAAS,gBAAa,UAAU,OAAO,CAAC;AAC9D,cAAM,gBAAgB,YAAY,QAAQ,OAAO,EAAE;AAEnD,iBAAS,aAAa,IAAI;AAAA,UACxB,MAAM;AAAA,UACN,SAAS,UAAU;AAAA,UACnB,QAAQ,UAAU;AAAA,UAClB,SAAS,UAAU;AAAA,UACnB;AAAA,QACF;AAEA,QAAG,iBAAc,UAAU,KAAK,UAAU,UAAU,MAAM,CAAC,CAAC;AAE5D,eAAO,UAAU;AAAA,MACnB,SAAS,OAAO;AAEd,gBAAQ;AAAA,UACN,kCAAkC,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;AAAA,QAC1F;AAAA,MACF;AAAA,IACF,OAAO;AACL,aAAO,KAAK;AAAA,IACd;AAAA,EACF;AAGA,QAAM,SAAS,QAAQ,IAAI,QAAQ,uBAAuB;AAE1D,MAAI,CAAC,QAAQ;AACX,UAAM,IAAI,YAAY;AAAA,MACpB,SAAS,GAAG,QAAQ,WAAW,mEAAmE,QAAQ,uBAAuB;AAAA,IACnI,CAAC;AAAA,EACH;AAEA,SAAO;AACT;AAEA,SAAS,oBACP,SACA,QACwB;AACxB,QAAM,YAAY,QAAQ,YAAY;AACtC,SAAO;AAAA,IACL,GAAG;AAAA,IACH,cAAc,YAAY,GAAG,SAAS,IAAI,MAAM,KAAK;AAAA,EACvD;AACF;AAEO,SAAS,aAAa,UAAkC,CAAC,GAAmB;AACjF,QAAM,cAAc,QAAQ,eAAe;AAC3C,QAAM,eAAe,QAAQ,QAAQ;AAGrC,MAAI;AACJ,MAAI;AAEJ,QAAM,YAAY,YAA6B;AAC7C,QAAI,cAAc;AAChB,aAAO;AAAA,IACT;AAEA,QAAI,eAAe;AACjB,aAAO;AAAA,IACT;AAEA,oBAAgB;AAAA,MACd;AAAA,QACE,QAAQ,QAAQ;AAAA,QAChB,yBAAyB;AAAA,QACzB,aAAa;AAAA,MACf;AAAA,MACA;AAAA,MACA,QAAQ;AAAA,IACV;AAEA,mBAAe,MAAM;AACrB,oBAAgB;AAChB,WAAO;AAAA,EACT;AAMA,QAAM,gBAAgB,YAA2B;AAE/C,mBAAe;AACf,oBAAgB;AAGhB,mBAAe,MAAM,UAAU;AAAA,EACjC;AAEA,QAAM,aAAa,MAAM;AAGvB,UAAM,SAAS,gBAAgB,QAAQ,UAAU,QAAQ,IAAI,cAAc,KAAK;AAEhF,QAAI,CAAC,QAAQ;AACX,YAAM,IAAI,YAAY;AAAA,QACpB,SACE;AAAA,MACJ,CAAC;AAAA,IACH;AAEA,WAAO;AAAA,MACL;AAAA,QACE,eAAe,UAAU,MAAM;AAAA,QAC/B,gBAAgB;AAAA,QAChB,GAAG,QAAQ;AAAA,MACb;AAAA,MACA,iBAAiB,OAAO;AAAA,IAC1B;AAAA,EACF;AAGA,YAAU,EAAE,MAAM,MAAM;AAAA,EAExB,CAAC;AAED,QAAM,yBAAyB,CAAC,SAAiB,mBAA0C;AACzF,UAAM,UAAU,gBAAgB,OAAO;AAEvC,QAAI,CAAC,SAAS;AACZ,YAAM,IAAI,YAAY;AAAA,QACpB,SAAS,qBAAqB,OAAO;AAAA,MACvC,CAAC;AAAA,IACH;AAEA,QAAI,gBAAgB,eAAe;AACjC,YAAM,cAAc,0BAA0B,QAAQ,QAAQ;AAC9D,UAAI,CAAC,YAAY,SAAS,eAAe,aAAa,GAAG;AACvD,cAAM,IAAI,YAAY;AAAA,UACpB,SAAS,0BAA0B,eAAe,aAAa,mBAAmB,QAAQ,QAAQ,oBAAoB,YAAY,KAAK,IAAI,CAAC;AAAA,QAC9I,CAAC;AAAA,MACH;AAAA,IACF;AAEA,UAAM,eAAe;AAAA,MACnB,sBAAsB;AAAA,MACtB,GAAG,QAAQ;AAAA,MACX,GAAG,gBAAgB;AAAA,IACrB;AAEA,UAAM,0BAA0B;AAAA,MAC9B,cAAc,sBAAsB,OAAO;AAAA,IAC7C;AAEA,UAAM,mBAAmB;AAAA,MACvB,GAAG;AAAA,MACH,GAAG,QAAQ;AAAA,MACX,GAAG,gBAAgB;AAAA,IACrB;AAEA,UAAM,aAAa;AAAA,MACjB,UAAU,GAAG,YAAY;AAAA,MACzB;AAAA,MACA;AAAA,MACA;AAAA,MACA,OAAO,QAAQ;AAAA,MACf,WAAW,gBAAgB;AAAA,MAC3B;AAAA,MACA,cAAc,QAAQ;AAAA,MACtB;AAAA,IACF;AAEA,QAAI,QAAQ,aAAa,UAAU;AACjC,aAAO,IAAI,0BAA0B,SAAS;AAAA,QAC5C,GAAG;AAAA,QACH,aAAa,gBAAgB,iBAAiB,QAAQ;AAAA,MACxD,CAAC;AAAA,IACH;AAEA,WAAO,IAAI,6BAA6B,SAAS;AAAA,MAC/C,GAAG;AAAA,MACH,gBAAgB,gBAAgB,iBAAiB,QAAQ;AAAA,IAC3D,CAAC;AAAA,EACH;AAGA,QAAM,qBAAqB,CAAC,YAAqC;AAE/D,WAAO,uBAAuB,OAAO;AAAA,EACvC;AAEA,QAAM,WAAW,OAAO,OAAO,CAAC,YAAoB,mBAAmB,OAAO,GAAG;AAAA,IAC/E,sBAAsB;AAAA,IACtB,eAAe;AAAA,IACf,MAAM;AAAA,IACN,aAAa;AAAA,EACf,CAAC;AAGD,WAAS,qBAAqB,CAAC,YAAoB;AACjD,UAAM,IAAI,YAAY;AAAA,MACpB,SAAS,qEAAqE,OAAO;AAAA,IACvF,CAAC;AAAA,EACH;AAEA,WAAS,aAAa,CAAC,YAAoB;AACzC,UAAM,IAAI,YAAY;AAAA,MACpB,SAAS,4DAA4D,OAAO;AAAA,IAC9E,CAAC;AAAA,EACH;AAEA,SAAO;AACT;AAYO,IAAM,SAAS,aAAa;;;ACzcnC,2BAAsB;AACtB,IAAAE,QAAsB;;;ACoBf,IAAM,qBAAN,MAAyB;AAAA,EACtB,QAAQ,oBAAI,IAAwB;AAAA,EACpC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMR,YAAY,aAAqB,IAAI,KAAK,KAAM;AAC9C,SAAK,aAAa;AAAA,EACpB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,IAAI,KAAmC;AACrC,UAAM,QAAQ,KAAK,MAAM,IAAI,GAAG;AAChC,QAAI,CAAC,OAAO;AACV,aAAO;AAAA,IACT;AAGA,QAAI,KAAK,IAAI,IAAI,MAAM,WAAW;AAChC,WAAK,MAAM,OAAO,GAAG;AACrB,aAAO;AAAA,IACT;AAEA,WAAO,MAAM;AAAA,EACf;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,IAAI,KAAa,SAAwB,KAAoB;AAC3D,SAAK,MAAM,IAAI,KAAK;AAAA,MAClB;AAAA,MACA,WAAW,KAAK,IAAI,KAAK,OAAO,KAAK;AAAA,IACvC,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,IAAI,KAAsB;AACxB,WAAO,KAAK,IAAI,GAAG,MAAM;AAAA,EAC3B;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OAAO,KAAmB;AACxB,SAAK,MAAM,OAAO,GAAG;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA,EAKA,QAAc;AACZ,SAAK,MAAM,MAAM;AAAA,EACnB;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,OAAe;AACjB,WAAO,KAAK,MAAM;AAAA,EACpB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,UAAgB;AACd,UAAM,MAAM,KAAK,IAAI;AACrB,eAAW,CAAC,KAAK,KAAK,KAAK,KAAK,MAAM,QAAQ,GAAG;AAC/C,UAAI,MAAM,MAAM,WAAW;AACzB,aAAK,MAAM,OAAO,GAAG;AAAA,MACvB;AAAA,IACF;AAAA,EACF;AACF;;;ADvGA,IAAM,WAAW,IAAI,UAAqB;AAAC;AAmBpC,IAAM,wBAAN,MAA4B;AAAA,EAChB;AAAA,EACA;AAAA,EACA;AAAA,EAEjB,YAAY,QAAqC;AAC/C,SAAK,SAAS;AAAA,MACZ,YAAY;AAAA;AAAA,MACZ,GAAG;AAAA,IACL;AACA,SAAK,UAAU,OAAO,SAAS;AAC/B,SAAK,QAAQ,OAAO,SAAS,IAAI,mBAAmB;AAAA,EACtD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,cACJ,kBACA,aAAqB,UACU;AAE/B,UAAM,WAAgB,cAAQ,gBAAgB;AAC9C,UAAM,SAAS,KAAK,MAAM,IAAI,QAAQ;AACtC,QAAI,QAAQ;AACV,aAAO;AAAA,IACT;AAEA,QAAI;AAEF,eAAS,wDAAwD,gBAAgB,EAAE;AACnF,YAAM,YAAY,MAAM,KAAK,gBAAgB,kBAAkB,UAAU;AACzE,UAAI,CAAC,WAAW;AACd,iBAAS,iDAAiD;AAC1D,eAAO;AAAA,MACT;AACA,eAAS,2CAA2C,SAAS,EAAE;AAG/D;AAAA,QACE,oEAAoE,KAAK,OAAO,WAAW;AAAA,MAC7F;AACA,YAAM,cAAc,KAAK,kBAAkB,WAAW,KAAK,OAAO,WAAW;AAC7E,UAAI,CAAC,aAAa;AAChB;AAAA,UACE;AAAA,QACF;AACA,eAAO;AAAA,MACT;AACA,eAAS,gDAAgD,WAAW,EAAE;AAGtE,eAAS,6DAA6D,WAAW,EAAE;AACnF,YAAM,UAAU,MAAM,KAAK,iBAAiB,WAAW;AACvD,eAAS,gEAA2D,OAAO;AAG3E,WAAK,MAAM,IAAI,UAAU,OAAO;AAEhC,aAAO;AAAA,IACT,SAAS,OAAO;AAEd,UAAI,iBAAiB,aAAa;AAEhC,iBAAS,6CAA6C,MAAM,WAAW,KAAK;AAC5E,eAAO;AAAA,MACT;AAEA,eAAS,6CAA6C,KAAK;AAC3D,cAAQ,KAAK,yCAAyC,KAAK,EAAE;AAC7D,aAAO;AAAA,IACT;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAeA,kBAAkB,WAAmB,aAAoC;AACvE,QAAI;AAEF,YAAM,eAAe,IAAI,IAAI,WAAW,EAAE;AAG1C,YAAM,WAAW,UAAU,MAAM,+BAA+B;AAChE,UAAI,UAAU;AACZ,cAAM,CAAC,EAAE,MAAM,QAAQ,IAAI;AAE3B,cAAM,kBAAkB,KAAK,MAAM,GAAG,EAAE,CAAC;AACzC,YAAI,oBAAoB,cAAc;AAEpC,gBAAM,YAAY,SAAS,QAAQ,UAAU,EAAE;AAC/C,iBAAO,UAAU,SAAS,MAAM,IAAI,UAAU,MAAM,GAAG,EAAE,IAAI;AAAA,QAC/D;AAAA,MACF;AAGA,YAAM,aAAa,UAAU,MAAM,yCAAyC;AAC5E,UAAI,YAAY;AACd,cAAM,CAAC,EAAE,EAAE,cAAc,QAAQ,IAAI;AACrC,cAAM,OAAO,aAAa,MAAM,GAAG,EAAE,CAAC;AACtC,YAAI,SAAS,cAAc;AACzB,iBAAO,SAAS,SAAS,MAAM,IAAI,SAAS,MAAM,GAAG,EAAE,IAAI;AAAA,QAC7D;AAAA,MACF;AAEA,aAAO;AAAA,IACT,SAAS,OAAO;AAEd,aAAO;AAAA,IACT;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,gBACJ,kBACA,aAAqB,UACG;AACxB,WAAO,IAAI,QAAQ,CAACC,aAAY;AAC9B,YAAM,YAAQ,4BAAM,OAAO,CAAC,UAAU,SAAS,UAAU,UAAU,MAAM,GAAG;AAAA,QAC1E,KAAK;AAAA,QACL,SAAS,KAAK,OAAO;AAAA,MACvB,CAAC;AAED,UAAI,SAAS;AACb,UAAI,UAAU;AAEd,YAAM,QAAQ,GAAG,QAAQ,CAAC,SAAS;AACjC,kBAAU,KAAK,SAAS;AAAA,MAC1B,CAAC;AAED,YAAM,QAAQ,GAAG,QAAQ,CAAC,SAAS;AACjC,mBAAW,KAAK,SAAS;AAAA,MAC3B,CAAC;AAED,YAAM,GAAG,SAAS,CAAC,aAAa;AAC9B,YAAI,aAAa,KAAK,OAAO,KAAK,GAAG;AACnC,UAAAA,SAAQ,OAAO,KAAK,CAAC;AAAA,QACvB,OAAO;AACL,UAAAA,SAAQ,IAAI;AAAA,QACd;AAAA,MACF,CAAC;AAED,YAAM,GAAG,SAAS,MAAM;AAEtB,QAAAA,SAAQ,IAAI;AAAA,MACd,CAAC;AAAA,IACH,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,iBAAiB,aAA6C;AAElE,UAAM,cAAc,mBAAmB,WAAW;AAClD,UAAM,MAAM,GAAG,KAAK,OAAO,WAAW,oBAAoB,WAAW;AAErE,QAAI;AACF,YAAM,WAAW,MAAM,KAAK,QAAQ,KAAK;AAAA,QACvC,QAAQ;AAAA,QACR,SAAS,KAAK,OAAO,WAAW;AAAA,MAClC,CAAC;AAED,UAAI,CAAC,SAAS,IAAI;AAChB,cAAM,IAAI,YAAY;AAAA,UACpB,SAAS,4BAA4B,WAAW,MAAM,SAAS,MAAM,IAAI,SAAS,UAAU;AAAA,QAC9F,CAAC;AAAA,MACH;AAEA,YAAM,OAAQ,MAAM,SAAS,KAAK;AAQlC,aAAO;AAAA,QACL,IAAI,KAAK;AAAA,QACT,MAAM,KAAK;AAAA,QACX,mBAAmB,KAAK;AAAA,QACxB,MAAM,KAAK;AAAA,QACX,aAAa,KAAK,WAAW;AAAA,MAC/B;AAAA,IACF,SAAS,OAAO;AACd,UAAI,iBAAiB,aAAa;AAChC,cAAM;AAAA,MACR;AACA,YAAM,IAAI,YAAY;AAAA,QACpB,SAAS,4BAA4B,WAAW,MAAM,KAAK;AAAA,QAC3D,OAAO;AAAA,MACT,CAAC;AAAA,IACH;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,aAAmB;AACjB,SAAK,MAAM,MAAM;AAAA,EACnB;AAAA;AAAA;AAAA;AAAA,EAKA,WAA+B;AAC7B,WAAO,KAAK;AAAA,EACd;AACF;","names":["Anthropic","resolve","OpenAI","hasToolCalls","path","resolve"]}