{"version":3,"sources":["../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-workflow-client.ts","../src/version.ts","../src/gitlab-workflow-types.ts","../src/gitlab-workflow-builtins.ts","../src/gitlab-workflow-token-client.ts","../src/gitlab-project-detector.ts","../src/gitlab-project-cache.ts","../src/gitlab-model-discovery.ts","../src/gitlab-model-cache.ts","../src/gitlab-workflow-language-model.ts","../src/gitlab-oauth-types.ts","../src/gitlab-oauth-manager.ts","../src/gitlab-provider.ts"],"sourcesContent":["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 = systemMessage ? `${systemMessage}\\n${message.content}` : 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 (error) {\n                controller.enqueue({\n                  type: 'error',\n                  error: error instanceof Error ? error : new Error(String(error)),\n                });\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' | 'workflow';\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-6': { provider: 'anthropic', model: 'claude-opus-4-6' },\n  'duo-chat-sonnet-4-6': { provider: 'anthropic', model: 'claude-sonnet-4-6' },\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  'duo-chat-gpt-5-3-codex': {\n    provider: 'openai',\n    model: 'gpt-5.3-codex',\n    openaiApiType: 'responses',\n  },\n\n  // Duo Agent Platform model (server-side agentic via DWS WebSocket).\n  // This is the single user-facing model ID. The actual underlying model ref\n  // is resolved dynamically at runtime via GitLabModelDiscovery.\n  'duo-workflow': { provider: 'workflow', model: 'default' },\n\n  // Internal model refs — kept for backwards compatibility and direct use.\n  // Not intended as user-facing model IDs.\n  'duo-workflow-default': { provider: 'workflow', model: 'default' },\n  'duo-workflow-sonnet-4-5': {\n    provider: 'workflow',\n    model: 'anthropic/claude-sonnet-4-5-20250929',\n  },\n  'duo-workflow-sonnet-4-6': { provider: 'workflow', model: 'claude_sonnet_4_6' },\n  'duo-workflow-opus-4-5': {\n    provider: 'workflow',\n    model: 'anthropic/claude-opus-4-5-20251101',\n  },\n  'duo-workflow-haiku-4-5': { provider: 'workflow', model: 'claude_haiku_4_5_20251001' },\n  'duo-workflow-opus-4-6': { provider: 'workflow', model: 'claude_opus_4_6_20260205' },\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 function isWorkflowModel(modelId: string): boolean {\n  return MODEL_MAPPINGS[modelId]?.provider === 'workflow';\n}\n\nexport function getWorkflowModelRef(modelId: string): string | undefined {\n  const mapping = MODEL_MAPPINGS[modelId];\n  return mapping?.provider === 'workflow' ? mapping.model : undefined;\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 * WebSocket client for the GitLab Duo Agent Platform (DWS).\n *\n * Handles:\n * - WebSocket connection to `wss://{instance}/api/v4/ai/duo_workflows/ws`\n * - Sending ClientEvent messages (startRequest, actionResponse, stopWorkflow)\n * - Receiving WorkflowAction messages (newCheckpoint, runMcpTool, built-in tools)\n * - Dual heartbeat: ws.ping(45s) + JSON heartbeat(60s) — matching gitlab-lsp\n * - No reconnection on drop (matches gitlab-lsp behavior)\n */\n\nimport WebSocket from 'isomorphic-ws';\nimport { VERSION } from './version';\nimport type {\n  ClientEvent,\n  WorkflowAction,\n  StartRequest,\n  ActionResponsePayload,\n  WorkflowClientEvent,\n} from './gitlab-workflow-types';\nimport {\n  WS_KEEPALIVE_PING_INTERVAL_MS,\n  WS_HEARTBEAT_INTERVAL_MS,\n  STOP_REASON_USER,\n} from './gitlab-workflow-types';\n\nexport interface WorkflowWebSocketOptions {\n  /** GitLab instance URL */\n  instanceUrl: string;\n  /** Model reference for DWS (e.g. 'anthropic/claude-sonnet-4-5-20250929' or 'default') */\n  modelRef: string;\n  /** Auth headers — must include Authorization */\n  headers: Record<string, string>;\n  /** Optional correlation ID */\n  requestId?: string;\n  /** Optional project context */\n  projectId?: string;\n  namespaceId?: string;\n  rootNamespaceId?: string;\n}\n\ntype EventCallback = (event: WorkflowClientEvent) => void;\n\nexport class GitLabWorkflowClient {\n  private socket: WebSocket | null = null;\n  private keepaliveInterval: ReturnType<typeof setInterval> | null = null;\n  private heartbeatInterval: ReturnType<typeof setInterval> | null = null;\n  private eventCallback: EventCallback | null = null;\n  private closed = false;\n  private lastSendTime = 0;\n\n  /**\n   * Connect to the DWS WebSocket and start listening for events.\n   *\n   * @param options - Connection parameters\n   * @param onEvent - Callback invoked for each WorkflowClientEvent\n   * @returns Promise that resolves when the connection is open\n   */\n  connect(options: WorkflowWebSocketOptions, onEvent: EventCallback): Promise<void> {\n    this.validateOptions(options);\n    this.eventCallback = onEvent;\n    this.closed = false;\n    this.cleanedUp = false;\n\n    return new Promise<void>((resolve, reject) => {\n      const wsUrl = this.buildWebSocketUrl(options);\n      const wsHeaders = this.buildWebSocketHeaders(options);\n\n      this.socket = new WebSocket(wsUrl, { headers: wsHeaders });\n      let resolved = false;\n\n      this.socket.onopen = () => {\n        resolved = true;\n        this.startKeepalive();\n        this.startHeartbeat();\n        resolve();\n      };\n\n      this.socket.onmessage = (event: WebSocket.MessageEvent) => {\n        try {\n          const data = typeof event.data === 'string' ? event.data : event.data.toString();\n          const action = JSON.parse(data) as WorkflowAction;\n\n          // Basic validation of message structure\n          if (!action || typeof action !== 'object') {\n            throw new Error('Invalid message structure: expected object');\n          }\n\n          this.handleAction(action);\n        } catch (error) {\n          this.emit({\n            type: 'failed',\n            error: error instanceof Error ? error : new Error(String(error)),\n          });\n        }\n      };\n\n      this.socket.onerror = (event: WebSocket.ErrorEvent) => {\n        const error = new Error(`WebSocket error: ${event.message || 'unknown'}`);\n        if (!resolved) {\n          reject(error);\n        } else {\n          this.emit({ type: 'failed', error });\n        }\n      };\n\n      this.socket.onclose = (event: WebSocket.CloseEvent) => {\n        this.cleanup();\n        if (!resolved) {\n          reject(\n            new Error(\n              `WebSocket closed before open: code=${event.code} reason=${event.reason || ''}`\n            )\n          );\n          return;\n        }\n        if (!this.closed) {\n          this.emit({\n            type: 'closed',\n            code: event.code,\n            reason: event.reason || '',\n          });\n        }\n      };\n    });\n  }\n\n  /**\n   * Send a startRequest to begin the workflow.\n   */\n  sendStartRequest(request: StartRequest): void {\n    this.send({ startRequest: request });\n  }\n\n  /**\n   * Send an actionResponse (tool result) back to DWS.\n   */\n  sendActionResponse(requestID: string, response: string, error?: string | null): void {\n    this.sendHeartbeatIfNeeded();\n    const payload: ActionResponsePayload = {\n      requestID,\n      plainTextResponse: {\n        response,\n        error: error ?? null,\n      },\n    };\n    this.send({ actionResponse: payload });\n  }\n\n  /**\n   * Stop the workflow gracefully.\n   */\n  stop(): void {\n    this.send({ stopWorkflow: { reason: STOP_REASON_USER } });\n    this.closed = true;\n  }\n\n  /**\n   * Close the WebSocket connection.\n   */\n  close(): void {\n    // Set closed flag first to prevent race conditions\n    if (this.closed) return;\n    this.closed = true;\n\n    this.cleanup();\n    const sock = this.socket;\n    this.socket = null;\n    if (sock) {\n      if (sock.readyState === WebSocket.OPEN || sock.readyState === WebSocket.CONNECTING) {\n        sock.close(1000, 'Client closing');\n      }\n    }\n  }\n\n  /**\n   * Check if the WebSocket is currently connected.\n   */\n  get isConnected(): boolean {\n    return this.socket?.readyState === WebSocket.OPEN;\n  }\n\n  // ---------------------------------------------------------------------------\n  // Private\n  // ---------------------------------------------------------------------------\n\n  private validateOptions(options: WorkflowWebSocketOptions): void {\n    if (!options.instanceUrl || typeof options.instanceUrl !== 'string') {\n      throw new Error('instanceUrl is required');\n    }\n    const parsed = new URL(options.instanceUrl);\n    if (parsed.protocol !== 'https:' && parsed.protocol !== 'http:') {\n      throw new Error(`Invalid instanceUrl protocol: ${parsed.protocol}`);\n    }\n    if (parsed.username || parsed.password) {\n      throw new Error(\n        'instanceUrl must not contain authentication credentials (username/password)'\n      );\n    }\n    if (!options.headers || typeof options.headers !== 'object') {\n      throw new Error('headers are required');\n    }\n    if (options.modelRef && typeof options.modelRef !== 'string') {\n      throw new Error('modelRef must be a string');\n    }\n  }\n\n  private buildWebSocketUrl(options: WorkflowWebSocketOptions): string {\n    // Match gitlab-lsp URL construction exactly:\n    // - NO workflow_id in URL (it goes in startRequest.workflowID instead)\n    // - Only user_selected_model_identifier as query param\n    const baseUrl = new URL(options.instanceUrl.replace(/\\/?$/, '/'));\n    const url = new URL('./api/v4/ai/duo_workflows/ws', baseUrl);\n    url.protocol = url.protocol === 'https:' ? 'wss:' : 'ws:';\n    if (options.modelRef && options.modelRef !== 'default') {\n      // URL.searchParams.set() automatically encodes the value\n      url.searchParams.set('user_selected_model_identifier', options.modelRef);\n    }\n    return url.toString();\n  }\n\n  private buildWebSocketHeaders(options: WorkflowWebSocketOptions): Record<string, string> {\n    // Normalize incoming headers to lowercase keys to avoid duplicates\n    const headers: Record<string, string> = {};\n    for (const [key, value] of Object.entries(options.headers)) {\n      headers[key.toLowerCase()] = value;\n    }\n\n    // Remove Content-Type — WebSocket upgrade (RFC 6455 §4.1) uses no body;\n    // sending Content-Type can confuse proxies and fails some server checks.\n    delete headers['content-type'];\n\n    headers['x-gitlab-client-type'] = 'node-websocket';\n\n    // Origin header — required by gitlab-lsp, validates WebSocket security\n    // The origin is derived from the validated instanceUrl (already checked in validateOptions)\n    const parsedUrl = new URL(options.instanceUrl);\n    const origin = parsedUrl.origin;\n    headers['origin'] = origin;\n\n    if (options.requestId) {\n      headers['x-request-id'] = options.requestId;\n    }\n    if (options.projectId) {\n      headers['x-gitlab-project-id'] = options.projectId;\n    }\n    if (options.namespaceId) {\n      headers['x-gitlab-namespace-id'] = options.namespaceId;\n    }\n    if (options.rootNamespaceId) {\n      headers['x-gitlab-root-namespace-id'] = options.rootNamespaceId;\n    }\n\n    // User-Agent — set only if not already provided\n    if (!headers['user-agent']) {\n      headers['user-agent'] = `gitlab-ai-provider/${VERSION}`;\n    }\n\n    return headers;\n  }\n\n  private handleAction(action: WorkflowAction): void {\n    // Checkpoint (text/status from LLM)\n    if (action.newCheckpoint) {\n      const checkpoint = action.newCheckpoint;\n\n      this.emit({ type: 'checkpoint', data: checkpoint });\n\n      if (checkpoint.status === 'FINISHED' || checkpoint.status === 'COMPLETED') {\n        this.emit({ type: 'completed' });\n      } else if (checkpoint.status === 'FAILED') {\n        this.emit({\n          type: 'failed',\n          error: new Error(checkpoint.content || 'Workflow failed'),\n        });\n      } else if (checkpoint.status === 'STOPPED' || checkpoint.status === 'CANCELLED') {\n        this.emit({ type: 'completed' });\n      }\n      return;\n    }\n\n    // MCP tool invocation\n    if (action.runMCPTool && action.requestID) {\n      this.emit({\n        type: 'tool-request',\n        requestID: action.requestID,\n        data: action.runMCPTool,\n      });\n      return;\n    }\n\n    // Built-in tool invocations — field names match DWS protobuf wire format\n    const builtinTools: Array<[string, unknown]> = [\n      ['runReadFile', action.runReadFile],\n      ['runReadFiles', action.runReadFiles],\n      ['runWriteFile', action.runWriteFile],\n      ['runShellCommand', action.runShellCommand],\n      ['runEditFile', action.runEditFile],\n      ['listDirectory', action.listDirectory],\n      ['findFiles', action.findFiles],\n      ['grep', action.grep],\n      ['mkdir', action.mkdir],\n      ['runCommand', action.runCommand],\n      ['runGitCommand', action.runGitCommand],\n      ['runHTTPRequest', action.runHTTPRequest],\n    ];\n\n    for (const [toolName, data] of builtinTools) {\n      if (data && action.requestID) {\n        this.emit({\n          type: 'builtin-tool-request',\n          requestID: action.requestID,\n          toolName,\n          data: data as Record<string, unknown>,\n        });\n        return;\n      }\n    }\n  }\n\n  private send(event: ClientEvent): void {\n    if (this.socket?.readyState === WebSocket.OPEN) {\n      const json = JSON.stringify(event);\n      this.socket.send(json);\n      this.lastSendTime = Date.now();\n    }\n  }\n\n  private sendHeartbeatIfNeeded(): void {\n    const elapsed = Date.now() - this.lastSendTime;\n    if (elapsed >= WS_HEARTBEAT_INTERVAL_MS / 2) {\n      this.send({ heartbeat: { timestamp: Date.now() } });\n    }\n  }\n\n  private emit(event: WorkflowClientEvent): void {\n    this.eventCallback?.(event);\n  }\n\n  /**\n   * Start ws.ping() keepalive (45s interval).\n   * Keeps TCP connection alive through proxies/load balancers.\n   */\n  private startKeepalive(): void {\n    this.keepaliveInterval = setInterval(() => {\n      if (this.socket?.readyState === WebSocket.OPEN) {\n        // ws-specific ping (not available in browser WebSocket, but\n        // isomorphic-ws in Node.js delegates to the ws library)\n        try {\n          (this.socket as unknown as { ping: () => void }).ping();\n        } catch {\n          // Browser WebSocket doesn't have ping — silently skip\n        }\n      }\n    }, WS_KEEPALIVE_PING_INTERVAL_MS);\n  }\n\n  /**\n   * Start application-level heartbeat (60s interval).\n   * Prevents DWS from timing out the workflow.\n   */\n  private startHeartbeat(): void {\n    this.heartbeatInterval = setInterval(() => {\n      this.send({ heartbeat: { timestamp: Date.now() } });\n    }, WS_HEARTBEAT_INTERVAL_MS);\n  }\n\n  private cleanedUp = false;\n\n  /**\n   * Clean up intervals. Idempotent — safe to call multiple times.\n   */\n  private cleanup(): void {\n    if (this.cleanedUp) return;\n    this.cleanedUp = true;\n\n    if (this.keepaliveInterval) {\n      clearInterval(this.keepaliveInterval);\n      this.keepaliveInterval = null;\n    }\n    if (this.heartbeatInterval) {\n      clearInterval(this.heartbeatInterval);\n      this.heartbeatInterval = null;\n    }\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","/**\n * Types for the GitLab Duo Agent Platform (DWS) protocol.\n *\n * DWS uses a WebSocket-based bidirectional protocol where:\n * - Client sends `ClientEvent` messages (startRequest, actionResponse, stopWorkflow, heartbeat)\n * - Server sends `WorkflowAction` messages (newCheckpoint, runMcpTool, built-in tools)\n *\n * Message format is JSON-serialized protobuf with camelCase field names.\n */\n\n// ---------------------------------------------------------------------------\n// Token / workflow creation responses\n// ---------------------------------------------------------------------------\n\nexport interface GenerateTokenResponse {\n  gitlab_rails: {\n    base_url: string;\n    token: string;\n    token_expires_at: string;\n  };\n  duo_workflow_service: {\n    base_url: string;\n    token: string;\n    secure: boolean;\n    token_expires_at: number;\n    headers: Record<string, string>;\n  };\n  duo_workflow_executor: {\n    executor_binary_url: string;\n    version: string;\n  };\n}\n\nexport interface CreateWorkflowResponse {\n  id: string;\n}\n\n// ---------------------------------------------------------------------------\n// MCP tool definitions (sent in startRequest)\n// ---------------------------------------------------------------------------\n\nexport interface McpToolDefinition {\n  name: string;\n  description: string;\n  inputSchema: string;\n}\n\n// ---------------------------------------------------------------------------\n// Client → Server messages (ClientEvent)\n// ---------------------------------------------------------------------------\n\nexport interface AdditionalContext {\n  category: string;\n  id?: string;\n  content?: string;\n  metadata?: string;\n}\n\nexport interface StartRequest {\n  workflowID: string;\n  clientVersion: string;\n  workflowDefinition: string;\n  goal: string;\n  workflowMetadata?: string;\n  additional_context?: AdditionalContext[];\n  clientCapabilities?: string[];\n  mcpTools?: McpToolDefinition[];\n  preapproved_tools?: string[];\n  flowConfig?: unknown;\n  flowConfigSchemaVersion?: string;\n}\n\nexport interface ActionResponsePayload {\n  requestID: string;\n  plainTextResponse: {\n    response: string;\n    error: string | null;\n  };\n}\n\nexport interface StopWorkflow {\n  reason: string;\n}\n\nexport interface Heartbeat {\n  timestamp: number;\n}\n\n/**\n * Client → Server event union.\n * Exactly one of the fields should be set per message.\n */\nexport type ClientEvent =\n  | { startRequest: StartRequest }\n  | { actionResponse: ActionResponsePayload }\n  | { stopWorkflow: StopWorkflow }\n  | { heartbeat: Heartbeat };\n\n// ---------------------------------------------------------------------------\n// Server → Client messages (WorkflowAction)\n// ---------------------------------------------------------------------------\n\nexport type WorkflowStatus =\n  | 'CREATED'\n  | 'RUNNING'\n  | 'FINISHED'\n  | 'COMPLETED'\n  | 'FAILED'\n  | 'STOPPED'\n  | 'CANCELLED'\n  | 'PAUSED'\n  | 'INPUT_REQUIRED'\n  | 'PLAN_APPROVAL_REQUIRED'\n  | 'TOOL_CALL_APPROVAL_REQUIRED'\n  | 'UNKNOWN';\n\nexport interface NewCheckpoint {\n  status: WorkflowStatus;\n  goal?: string;\n  /** Raw checkpoint JSON string from DWS (contains channel_values.ui_chat_log) */\n  checkpoint?: string;\n  /** Legacy content field (may be empty — text is in checkpoint.ui_chat_log) */\n  content?: string;\n}\n\n// ---------------------------------------------------------------------------\n// Checkpoint parsing types (based on gitlab-lsp ui_chat_log.ts)\n// ---------------------------------------------------------------------------\n\nexport interface UiChatLogEntry {\n  message_type: 'user' | 'agent' | 'tool' | 'request';\n  message_sub_type: string | null;\n  content: string;\n  message_id?: string;\n  timestamp: string;\n  status: string | null;\n  correlation_id: string | null;\n  tool_info: UiChatLogToolInfo | null;\n  additional_context: unknown;\n}\n\nexport interface UiChatLogToolInfo {\n  name: string;\n  args: Record<string, unknown>;\n  tool_response?: UiChatLogToolResponse | string;\n}\n\nexport interface UiChatLogToolResponse {\n  content: string;\n  type: string;\n  name: string;\n  id: string | null;\n  tool_call_id: string;\n  status: string;\n}\n\nexport interface CheckpointData {\n  channel_values: {\n    ui_chat_log?: UiChatLogEntry[];\n    plan?: { steps: unknown[] };\n    status?: string;\n    [key: string]: unknown;\n  };\n}\n\nexport interface RunMcpTool {\n  name: string;\n  args: string;\n}\n\nexport interface ReadFileAction {\n  filepath: string;\n}\n\nexport interface ReadFilesAction {\n  filepaths: string[];\n}\n\nexport interface WriteFileAction {\n  filepath: string;\n  contents: string;\n}\n\nexport interface ShellCommandAction {\n  command: string;\n}\n\nexport interface EditFileAction {\n  filepath: string;\n  oldString: string;\n  newString: string;\n}\n\nexport interface ListDirectoryAction {\n  directory: string;\n}\n\nexport interface FindFilesAction {\n  name_pattern: string;\n}\n\nexport interface GrepAction {\n  pattern: string;\n  search_directory?: string;\n  case_insensitive?: boolean;\n}\n\nexport interface MkdirAction {\n  directory_path: string;\n}\n\nexport interface RunCommandAction {\n  program: string;\n  flags?: string[];\n  arguments?: string[];\n}\n\nexport interface RunGitCommandAction {\n  command: string;\n  arguments?: string[];\n  repository_url?: string;\n}\n\nexport interface GitLabApiRequestAction {\n  method: string;\n  path: string;\n  body?: string;\n}\n\n/**\n * Server → Client action union.\n * Field names match the DWS protobuf camelCase wire format exactly.\n * Each message has an optional `requestID` (required for tool invocations\n * that need an `actionResponse` back).\n */\nexport interface WorkflowAction {\n  requestID?: string;\n\n  newCheckpoint?: NewCheckpoint;\n\n  runMCPTool?: RunMcpTool;\n\n  runReadFile?: ReadFileAction;\n  runReadFiles?: ReadFilesAction;\n  runWriteFile?: WriteFileAction;\n  runShellCommand?: ShellCommandAction;\n  runEditFile?: EditFileAction;\n  listDirectory?: ListDirectoryAction;\n  findFiles?: FindFilesAction;\n  grep?: GrepAction;\n  mkdir?: MkdirAction;\n  runCommand?: RunCommandAction;\n  runGitCommand?: RunGitCommandAction;\n  runHTTPRequest?: GitLabApiRequestAction;\n}\n\n// ---------------------------------------------------------------------------\n// Provider options\n// ---------------------------------------------------------------------------\n\n/**\n * Options for creating a workflow chat model via `provider.workflowChat()`.\n */\nexport interface GitLabWorkflowOptions {\n  /**\n   * Workflow definition type.\n   * @default 'chat'\n   */\n  workflowDefinition?: string;\n\n  /**\n   * Root namespace ID for the GitLab group/project.\n   * Used for token scoping and model discovery.\n   */\n  rootNamespaceId?: string;\n\n  /**\n   * GitLab project ID (numeric or path).\n   * Sent as `x-gitlab-project-id` header on WebSocket.\n   */\n  projectId?: string;\n\n  /**\n   * GitLab namespace ID.\n   * Sent as `x-gitlab-namespace-id` header on WebSocket.\n   */\n  namespaceId?: string;\n\n  /**\n   * MCP tool definitions to expose to the workflow.\n   * These are sent in `startRequest.mcpTools`.\n   */\n  mcpTools?: McpToolDefinition[];\n\n  /**\n   * Client capabilities to advertise.\n   * @default ['shell_command']\n   */\n  clientCapabilities?: string[];\n\n  /**\n   * Tool names that are pre-approved for execution without user confirmation.\n   * Sent in `startRequest.preapproved_tools`.\n   */\n  preapprovedTools?: string[];\n\n  /**\n   * Additional context items to send with the first request.\n   * Used for conversation history continuity.\n   */\n  additionalContext?: AdditionalContext[];\n\n  /**\n   * Feature flags to pass to the GitLab API.\n   */\n  featureFlags?: Record<string, boolean>;\n\n  /**\n   * Working directory for auto-detecting GitLab project from git remote.\n   * Used to resolve `projectId` when not explicitly set.\n   * Defaults to `process.cwd()`.\n   */\n  workingDirectory?: string;\n\n  /**\n   * Flow configuration (parsed YAML object) to send to DWS.\n   * Controls agent behavior, intermediate text generation, etc.\n   * Sent as `startRequest.flowConfig`.\n   */\n  flowConfig?: unknown;\n\n  /**\n   * Schema version for the flow configuration.\n   * Sent as `startRequest.flowConfigSchemaVersion`.\n   */\n  flowConfigSchemaVersion?: string;\n\n  /**\n   * Callback invoked when multiple workflow models are available for the\n   * workspace and model switching is enabled by the instance admin.\n   *\n   * The provider calls this before starting the workflow so the host can\n   * present a model picker to the user. Return the `ref` of the chosen\n   * model, or `null`/`undefined` to fall back to the workspace default.\n   *\n   * If the returned ref is not in the list of selectable models it is\n   * ignored and the workspace default is used instead.\n   *\n   * Not called when the admin has pinned a model — in that case the\n   * pinned model is always used regardless of user preference.\n   *\n   * @param models - List of models the user can select from\n   * @returns The selected model ref, or null/undefined for default\n   */\n  onSelectModel?: (\n    models: import('./gitlab-model-discovery').AiModel[]\n  ) => Promise<string | null | undefined>;\n}\n\n// ---------------------------------------------------------------------------\n// WebSocket client configuration\n// ---------------------------------------------------------------------------\n\nexport interface GitLabWorkflowClientConfig {\n  /** GitLab instance URL (e.g., 'https://gitlab.com') */\n  instanceUrl: string;\n\n  /** Function to get current auth headers */\n  getHeaders: () => Record<string, string>;\n\n  /**\n   * Optional callback to refresh the API key when a 401 error occurs.\n   */\n  refreshApiKey?: () => Promise<void>;\n\n  /** Custom fetch implementation */\n  fetch?: typeof fetch;\n\n  /** Feature flags for the token request */\n  featureFlags?: Record<string, boolean>;\n\n  /**\n   * AI Gateway URL.\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// WebSocket event types (emitted by GitLabWorkflowClient)\n// ---------------------------------------------------------------------------\n\nexport type WorkflowClientEvent =\n  | { type: 'checkpoint'; data: NewCheckpoint }\n  | { type: 'tool-request'; requestID: string; data: RunMcpTool }\n  | {\n      type: 'builtin-tool-request';\n      requestID: string;\n      toolName: string;\n      data: Record<string, unknown>;\n    }\n  | { type: 'completed' }\n  | { type: 'failed'; error: Error }\n  | { type: 'closed'; code: number; reason: string };\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\n/**\n * Workflow type enum — matches gitlab-lsp WorkflowType.\n *\n * - CHAT: Shared token across sessions, tokens NOT revoked on completion\n * - SOFTWARE_DEVELOPMENT: Per-workflow token, tokens revoked on completion\n */\nexport enum WorkflowType {\n  CHAT = 'chat',\n  SOFTWARE_DEVELOPMENT = 'software_development',\n}\n\n/** WebSocket ping interval (TCP keepalive) — 45s matching gitlab-lsp */\nexport const WS_KEEPALIVE_PING_INTERVAL_MS = 45_000;\n\n/** Application heartbeat interval — 60s matching gitlab-lsp */\nexport const WS_HEARTBEAT_INTERVAL_MS = 60_000;\n\n/** Default workflow definition — uses CHAT for agentic chat (matches gitlab-lsp) */\nexport const DEFAULT_WORKFLOW_DEFINITION = WorkflowType.CHAT;\n\n/** Default client capabilities */\nexport const DEFAULT_CLIENT_CAPABILITIES = ['shell_command'];\n\n/** Client version sent in startRequest */\nexport const CLIENT_VERSION = '1.0';\n\n/** Stop reason for user-initiated stop */\nexport const STOP_REASON_USER = 'USER_ACTION_TRIGGERED_STOP';\n\n/**\n * Agent privileges for workflow creation.\n * Matches gitlab-lsp AGENT_PRIVILEGES enum.\n */\nexport const AGENT_PRIVILEGES = {\n  READ_WRITE_FILES: 1,\n  READ_ONLY_GITLAB: 2,\n  READ_WRITE_GITLAB: 3,\n  RUN_COMMANDS: 4,\n  USE_GIT: 5,\n  RUN_MCP_TOOLS: 6,\n} as const;\n\n/** Default agent privileges — matches gitlab-lsp defaults */\nexport const DEFAULT_AGENT_PRIVILEGES = [\n  AGENT_PRIVILEGES.READ_WRITE_FILES,\n  AGENT_PRIVILEGES.READ_ONLY_GITLAB,\n  AGENT_PRIVILEGES.READ_WRITE_GITLAB,\n  AGENT_PRIVILEGES.RUN_COMMANDS,\n  AGENT_PRIVILEGES.RUN_MCP_TOOLS,\n  AGENT_PRIVILEGES.USE_GIT,\n];\n\n/** Workflow execution environment */\nexport const WORKFLOW_ENVIRONMENT = 'ide' as const;\n","/**\n * DWS built-in tool mapping and shared security utilities.\n *\n * Extracted into a standalone module so both production code\n * (gitlab-workflow-language-model.ts) and tests can reference the\n * same implementation — preventing drift between a test shim and\n * the real logic.\n *\n * @internal — not part of the public API surface.\n */\n\n/**\n * Reject strings containing shell metacharacters.\n * Used as a defence-in-depth check before shellEscape.\n */\nexport function validateNoShellMetachars(value: string, fieldName: string): void {\n  const dangerousChars = /[;&|`$()<>]/;\n  if (dangerousChars.test(value)) {\n    throw new Error(\n      `Invalid ${fieldName}: contains shell metacharacters. Use structured arguments instead.`\n    );\n  }\n}\n\n/**\n * Wrap a value in single quotes for safe use as a single shell argument.\n * Embedded single quotes are escaped with the '\\'' idiom.\n */\nexport function shellEscape(arg: string): string {\n  return \"'\" + String(arg).replace(/'/g, \"'\\\\''\") + \"'\";\n}\n\nconst ALLOWED_URL_SCHEMES = ['http:', 'https:'];\n\n/**\n * Redact credential-like patterns from error messages before they are\n * forwarded to the stream or surfaced in UI.\n *\n * Patterns covered:\n *   - Bearer / token header values\n *   - GitLab PAT / CI tokens (glpat-*, glcbt-*, etc.)\n *   - URL query parameters: private_token, access_token, token\n *   - Basic auth in URLs: http://user:PASSWORD@host\n *   - Additional GitLab token prefixes (gldt, gloas, glrt, glsoat, glffct, glsapat)\n */\nexport function sanitizeErrorMessage(message: string): string {\n  if (!message) return '';\n\n  return message\n    .replace(/\\bBearer\\s+[A-Za-z0-9\\-_.~+/]+=*/gi, 'Bearer [REDACTED]')\n    .replace(/\\bgl(?:pat|oat|cbt|dt|oas|rt|soat|ffct|sapat)-[A-Za-z0-9_-]+/g, '[REDACTED]')\n    .replace(/([?&](?:private_token|access_token|token)=)[^&\\s\"']*/gi, '$1[REDACTED]')\n    .replace(/:\\/\\/([^:@/\\s]+):([^@/\\s]+)@/g, '://$1:[REDACTED]@');\n}\n\n/**\n * Map DWS built-in tool names and arguments to the corresponding\n * consumer tool names and argument formats.\n *\n * DWS uses protobuf-style tool names (runReadFile, runShellCommand, etc.)\n * while consumers like OpenCode use different names (read, bash, write, etc.)\n *\n * IMPORTANT: The returned `args` are structured objects passed to the host's\n * `toolExecutor` callback — they are NOT executed as raw shell commands by\n * this library. The host (e.g., OpenCode) is responsible for safely executing\n * the mapped tool through its own permission-gated tool system.\n */\nexport function mapBuiltinTool(\n  dwsToolName: string,\n  data: Record<string, unknown>\n): { toolName: string; args: Record<string, unknown> } {\n  switch (dwsToolName) {\n    case 'runReadFile':\n      return { toolName: 'read', args: { filePath: data.filepath } };\n    case 'runReadFiles': {\n      const paths = (data.filepaths as string[]) ?? [];\n      if (paths.length <= 1) {\n        return { toolName: 'read', args: { filePath: paths[0] ?? '' } };\n      }\n      return {\n        toolName: 'read',\n        args: { filePaths: paths },\n      };\n    }\n    case 'runWriteFile':\n      return {\n        toolName: 'write',\n        args: { filePath: data.filepath, content: data.contents },\n      };\n    case 'runEditFile':\n      return {\n        toolName: 'edit',\n        args: {\n          filePath: data.filepath,\n          oldString: data.oldString ?? data.old_string,\n          newString: data.newString ?? data.new_string,\n        },\n      };\n    case 'runShellCommand': {\n      const command = data.command as string;\n      if (!command || typeof command !== 'string') {\n        throw new Error('runShellCommand: command is required and must be a string');\n      }\n      if (command.length > 10000) {\n        throw new Error('runShellCommand: command exceeds maximum length of 10000 characters');\n      }\n      return {\n        toolName: 'bash',\n        args: { command, description: 'DWS shell command' },\n      };\n    }\n    case 'runCommand': {\n      const program = data.program as string;\n      if (!program || typeof program !== 'string') {\n        throw new Error('runCommand: program is required and must be a string');\n      }\n      validateNoShellMetachars(program, 'program');\n\n      const flags = (data.flags as string[]) ?? [];\n      const cmdArgs = (data.arguments as string[]) ?? [];\n\n      for (const flag of flags) {\n        if (typeof flag === 'string') {\n          validateNoShellMetachars(flag, 'flag');\n        }\n      }\n      for (const arg of cmdArgs) {\n        if (typeof arg === 'string') {\n          validateNoShellMetachars(arg, 'argument');\n        }\n      }\n\n      return {\n        toolName: 'bash',\n        args: {\n          command: [program, ...flags, ...cmdArgs].map((a) => shellEscape(String(a))).join(' '),\n          description: `DWS run: ${program}`,\n        },\n      };\n    }\n    case 'runGitCommand': {\n      const gitCmd = data.command as string;\n      if (!gitCmd || typeof gitCmd !== 'string') {\n        throw new Error('runGitCommand: command is required and must be a string');\n      }\n      validateNoShellMetachars(gitCmd, 'git command');\n\n      const gitArgs = (data.arguments as string[]) ?? [];\n      for (const arg of gitArgs) {\n        if (typeof arg === 'string') {\n          validateNoShellMetachars(arg, 'git argument');\n        }\n      }\n      return {\n        toolName: 'bash',\n        args: {\n          command: ['git', gitCmd, ...gitArgs].map((a) => shellEscape(String(a))).join(' '),\n          description: `DWS git: ${gitCmd}`,\n        },\n      };\n    }\n    case 'listDirectory':\n      return { toolName: 'read', args: { filePath: data.directory ?? '.' } };\n    case 'findFiles':\n      return { toolName: 'glob', args: { pattern: data.name_pattern ?? data.namePattern } };\n    case 'grep':\n      return {\n        toolName: 'grep',\n        args: {\n          pattern: data.pattern,\n          path: data.search_directory ?? data.searchDirectory,\n        },\n      };\n    case 'mkdir': {\n      const dirPath = String(data.directory_path ?? data.directoryPath ?? '');\n      if (!dirPath) {\n        throw new Error('mkdir: directory_path is required');\n      }\n      if (dirPath.includes('\\0')) {\n        throw new Error('mkdir: directory_path contains null bytes');\n      }\n      return {\n        toolName: 'bash',\n        args: {\n          command: `mkdir -p ${shellEscape(dirPath)}`,\n          description: 'DWS mkdir',\n        },\n      };\n    }\n    case 'runHTTPRequest': {\n      const methodRaw = String(data.method ?? 'GET').toUpperCase();\n      const allowedMethods = ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS'];\n      if (!allowedMethods.includes(methodRaw)) {\n        throw new Error(`runHTTPRequest: invalid HTTP method '${methodRaw}'`);\n      }\n\n      const urlPath = String(data.path ?? '');\n      if (!urlPath) {\n        throw new Error('runHTTPRequest: path is required');\n      }\n\n      try {\n        const parsedUrl = new URL(urlPath);\n        if (!ALLOWED_URL_SCHEMES.includes(parsedUrl.protocol)) {\n          throw new Error(\n            `runHTTPRequest: only http:// and https:// schemes are allowed, got '${parsedUrl.protocol}'`\n          );\n        }\n      } catch (e) {\n        if (e instanceof Error && e.message.startsWith('runHTTPRequest:')) throw e;\n        // Relative path or non-URL string — allow through (curl handles these)\n      }\n\n      const method = shellEscape(methodRaw);\n      const escapedPath = shellEscape(urlPath);\n      const bodyArg = data.body ? ` -d ${shellEscape(String(data.body))}` : '';\n      return {\n        toolName: 'bash',\n        args: {\n          command: `curl -s -X ${method} -- ${escapedPath}${bodyArg}`,\n          description: `DWS HTTP ${methodRaw}`,\n        },\n      };\n    }\n    default:\n      return { toolName: dwsToolName, args: data };\n  }\n}\n","/**\n * Token management for the GitLab Duo Agent Platform (DWS).\n *\n * Handles two API calls:\n * 1. POST /api/v4/ai/duo_workflows/direct_access  → GenerateTokenResponse (workflow token)\n * 2. POST /api/v4/ai/duo_workflows/workflows       → CreateWorkflowResponse (workflow ID)\n *\n * Tokens are cached for 25 minutes (they expire after ~30 minutes).\n * On 401, optionally triggers an API key refresh callback and retries once.\n * On 403, throws a clear error explaining GitLab Duo Enterprise requirements.\n */\n\nimport { GitLabError } from './gitlab-error';\nimport { sanitizeErrorMessage } from './gitlab-workflow-builtins';\nimport type {\n  GenerateTokenResponse,\n  CreateWorkflowResponse,\n  GitLabWorkflowClientConfig,\n} from './gitlab-workflow-types';\n\nimport {\n  DEFAULT_WORKFLOW_DEFINITION,\n  DEFAULT_AGENT_PRIVILEGES,\n  WORKFLOW_ENVIRONMENT,\n  WorkflowType,\n} from './gitlab-workflow-types';\n\n/** Cache duration: 25 minutes (tokens expire at ~30 minutes) */\nconst TOKEN_CACHE_DURATION_MS = 25 * 60 * 1000;\n\nconst MAX_ERROR_TEXT_LENGTH = 500;\n\nfunction sanitizeErrorText(text: string): string {\n  const truncated =\n    text.length > MAX_ERROR_TEXT_LENGTH ? text.slice(0, MAX_ERROR_TEXT_LENGTH) + '...' : text;\n  return sanitizeErrorMessage(truncated);\n}\n\n/**\n * Shared token cache key for CHAT workflows.\n * CHAT tokens are shared across all sessions (matching gitlab-lsp behavior).\n */\nconst CHAT_SHARED_TOKEN_KEY = '__chat_shared__';\n\ninterface CachedToken {\n  token: GenerateTokenResponse;\n  expiresAt: number;\n}\n\nexport class GitLabWorkflowTokenClient {\n  private readonly config: GitLabWorkflowClientConfig;\n  private readonly fetchFn: typeof fetch;\n\n  /**\n   * Token cache keyed by workflow definition type.\n   *\n   * - CHAT workflows use a shared key (CHAT_SHARED_TOKEN_KEY) so tokens\n   *   are reused across ALL chat sessions (matching gitlab-lsp behavior).\n   * - SOFTWARE_DEVELOPMENT workflows would use per-workflow-id keys,\n   *   but since we fetch tokens before creating workflows, we key by type.\n   */\n  private tokenCache = new Map<string, CachedToken>();\n\n  constructor(config: GitLabWorkflowClientConfig) {\n    this.config = config;\n    this.fetchFn = config.fetch ?? fetch;\n  }\n\n  /**\n   * Resolve the cache key for a given workflow definition.\n   * CHAT workflows share a single token per namespace; other types get per-type keys.\n   */\n  private getCacheKey(workflowDefinition: string, rootNamespaceId?: string): string {\n    const base =\n      workflowDefinition === WorkflowType.CHAT ? CHAT_SHARED_TOKEN_KEY : workflowDefinition;\n    return rootNamespaceId ? `${base}:${rootNamespaceId}` : base;\n  }\n\n  /**\n   * Get a DWS token, using cached value if still valid.\n   *\n   * Token caching strategy (matches gitlab-lsp):\n   * - CHAT workflows: shared token across all sessions\n   * - Other workflows: per-type token\n   *\n   * @param workflowDefinition - Workflow type (default: 'chat')\n   * @param rootNamespaceId - Optional root namespace for scoping\n   * @param forceRefresh - Bypass cache\n   */\n  async getToken(\n    workflowDefinition: string = DEFAULT_WORKFLOW_DEFINITION,\n    rootNamespaceId?: string,\n    forceRefresh: boolean = false\n  ): Promise<GenerateTokenResponse> {\n    const now = Date.now();\n    const cacheKey = this.getCacheKey(workflowDefinition, rootNamespaceId);\n\n    const cached = this.tokenCache.get(cacheKey);\n    if (!forceRefresh && cached && cached.expiresAt > now) {\n      return cached.token;\n    }\n\n    if (forceRefresh) {\n      this.tokenCache.delete(cacheKey);\n    }\n\n    const url = `${this.config.instanceUrl}/api/v4/ai/duo_workflows/direct_access`;\n\n    const body: Record<string, unknown> = {\n      workflow_definition: workflowDefinition,\n    };\n    if (rootNamespaceId) {\n      body.root_namespace_id = rootNamespaceId;\n    }\n    if (this.config.featureFlags && Object.keys(this.config.featureFlags).length > 0) {\n      body.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(body),\n      });\n\n      if (!response.ok) {\n        const errorText = await response.text();\n        const safeError = sanitizeErrorText(errorText);\n\n        // 401 — try refreshing the API key once\n        if (response.status === 401 && this.config.refreshApiKey && !forceRefresh) {\n          try {\n            await this.config.refreshApiKey();\n            return await this.getToken(workflowDefinition, rootNamespaceId, true);\n          } catch {\n            throw new GitLabError({\n              message: `Failed to get workflow token: ${response.status} ${response.statusText} - ${safeError}`,\n              statusCode: response.status,\n              responseBody: safeError,\n            });\n          }\n        }\n\n        // 403 — fail fast with clear message about requirements\n        if (response.status === 403) {\n          throw new GitLabError({\n            message:\n              `GitLab Duo Agent Platform access denied. ` +\n              `GitLab Duo Agent Platform requires GitLab Ultimate with Duo Enterprise add-on. ` +\n              `Ensure: (1) Your instance has GitLab Ultimate, ` +\n              `(2) Duo Enterprise add-on is enabled, ` +\n              `(3) Your account has access to AI features.`,\n            statusCode: response.status,\n            responseBody: safeError,\n          });\n        }\n\n        throw new GitLabError({\n          message: `Failed to get workflow token: ${response.status} ${response.statusText} - ${safeError}`,\n          statusCode: response.status,\n          responseBody: safeError,\n        });\n      }\n\n      const data = (await response.json()) as GenerateTokenResponse;\n\n      // Cache for 25 minutes\n      this.tokenCache.set(cacheKey, {\n        token: data,\n        expiresAt: now + TOKEN_CACHE_DURATION_MS,\n      });\n\n      return data;\n    } catch (error) {\n      if (error instanceof GitLabError) throw error;\n      throw new GitLabError({\n        message: `Failed to get workflow token: ${error}`,\n        cause: error,\n      });\n    }\n  }\n\n  /**\n   * Create a new workflow on the GitLab instance.\n   *\n   * @param goal - The user's message / goal for this workflow\n   * @param options - Additional workflow creation options\n   * @returns The created workflow's ID\n   */\n  async createWorkflow(\n    goal: string,\n    options?: {\n      projectId?: string;\n      namespaceId?: string;\n      workflowDefinition?: string;\n      agentPrivileges?: number[];\n      environment?: string;\n      allowAgentToRequestUser?: boolean;\n    }\n  ): Promise<string> {\n    // Validate goal parameter\n    if (!goal || typeof goal !== 'string') {\n      throw new GitLabError({ message: 'goal is required and must be a non-empty string' });\n    }\n    if (goal.length > 10000) {\n      throw new GitLabError({ message: 'goal exceeds maximum length of 10000 characters' });\n    }\n\n    const url = `${this.config.instanceUrl}/api/v4/ai/duo_workflows/workflows`;\n\n    const body: Record<string, unknown> = {\n      goal,\n      project_id: options?.projectId,\n      namespace_id: options?.namespaceId,\n      workflow_definition: options?.workflowDefinition ?? DEFAULT_WORKFLOW_DEFINITION,\n      agent_privileges: options?.agentPrivileges ?? DEFAULT_AGENT_PRIVILEGES,\n      environment: options?.environment ?? WORKFLOW_ENVIRONMENT,\n      allow_agent_to_request_user: options?.allowAgentToRequestUser ?? true,\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(body),\n      });\n\n      if (!response.ok) {\n        const errorText = await response.text();\n        const safeError = sanitizeErrorText(errorText);\n        throw new GitLabError({\n          message: `Failed to create workflow: ${response.status} ${response.statusText} - ${safeError}`,\n          statusCode: response.status,\n          responseBody: safeError,\n        });\n      }\n\n      const data = (await response.json()) as CreateWorkflowResponse;\n      return data.id.toString();\n    } catch (error) {\n      if (error instanceof GitLabError) throw error;\n      throw new GitLabError({\n        message: `Failed to create workflow: ${error}`,\n        cause: error,\n      });\n    }\n  }\n\n  /**\n   * Invalidate cached tokens.\n   *\n   * @param workflowDefinition - If provided, only invalidate for this type.\n   *                             If omitted, clears ALL cached tokens.\n   */\n  invalidateToken(workflowDefinition?: string, rootNamespaceId?: string): void {\n    if (workflowDefinition) {\n      this.tokenCache.delete(this.getCacheKey(workflowDefinition, rootNamespaceId));\n    } else {\n      this.tokenCache.clear();\n    }\n  }\n}\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\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 not a git repo / no matching remote\n   * @throws GitLabError if the API call or an unexpected error occurs\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      const remoteUrl = await this.getGitRemoteUrl(workingDirectory, remoteName);\n      if (!remoteUrl) {\n        return null; // Not a git repo or no remote\n      }\n\n      // 3. Parse project path from URL\n      const projectPath = this.parseGitRemoteUrl(remoteUrl, this.config.instanceUrl);\n      if (!projectPath) {\n        return null; // Remote doesn't match instance\n      }\n\n      // 4. Fetch project from GitLab API\n      const project = await this.getProjectByPath(projectPath);\n\n      // 5. Cache the result\n      this.cache.set(cacheKey, project);\n\n      return project;\n    } catch (error) {\n      throw error instanceof GitLabError\n        ? error\n        : new GitLabError({\n            message: `Project detection failed: ${error}`,\n            cause: error,\n          });\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","/**\n * Dynamic model discovery via GitLab GraphQL API.\n *\n * Queries `aiChatAvailableModels` to discover which models are available\n * for a given GitLab namespace. Used to dynamically populate `duo-workflow-*`\n * model IDs at runtime.\n *\n * Requires GitLab 18.4+ (18.5+ for pinned model support).\n */\n\nimport { GitLabError } from './gitlab-error';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface AiModel {\n  /** Display name (e.g., 'Claude Sonnet 4.6') */\n  name: string;\n  /** Model reference for API use (e.g., 'claude_sonnet_4_6' or 'anthropic/claude-sonnet-4-5-20250929') */\n  ref: string;\n}\n\nexport interface AiChatAvailableModels {\n  defaultModel: AiModel | null;\n  selectableModels: AiModel[];\n  pinnedModel: AiModel | null;\n}\n\nexport interface DiscoveredModels {\n  /** The effective model (pinned > user-selected > default) */\n  defaultModel: AiModel | null;\n  /** All models the user can select from */\n  selectableModels: AiModel[];\n  /** Admin-pinned model (overrides everything) */\n  pinnedModel: AiModel | null;\n  /** Whether the ai_user_model_switching feature flag is enabled */\n  modelSwitchingEnabled: boolean;\n  /** GitLab instance version */\n  instanceVersion: string | null;\n}\n\nexport interface ModelDiscoveryConfig {\n  /** GitLab instance URL */\n  instanceUrl: string;\n  /** Function returning auth headers */\n  getHeaders: () => Record<string, string>;\n  /** Custom fetch */\n  fetch?: typeof fetch;\n}\n\n// ---------------------------------------------------------------------------\n// GraphQL query (inlined — no need for graphql-request gql tag)\n// ---------------------------------------------------------------------------\n\nconst AI_CHAT_AVAILABLE_MODELS_QUERY = `\n  query aiChatAvailableModels($rootNamespaceId: GroupID!) {\n    metadata {\n      featureFlags(names: [\"ai_user_model_switching\"]) {\n        enabled\n        name\n      }\n      version\n    }\n\n    aiChatAvailableModels(rootNamespaceId: $rootNamespaceId) {\n      defaultModel {\n        name\n        ref\n      }\n      selectableModels {\n        name\n        ref\n      }\n      pinnedModel {\n        name\n        ref\n      }\n    }\n  }\n`;\n\n// ---------------------------------------------------------------------------\n// Client\n// ---------------------------------------------------------------------------\n\nconst DISCOVERY_CACHE_TTL_MS = 10 * 60 * 1000;\n\ninterface CachedDiscovery {\n  data: DiscoveredModels;\n  expiresAt: number;\n}\n\nexport class GitLabModelDiscovery {\n  private readonly config: ModelDiscoveryConfig;\n  private readonly fetchFn: typeof fetch;\n  private cache = new Map<string, CachedDiscovery>();\n\n  constructor(config: ModelDiscoveryConfig) {\n    this.config = config;\n    this.fetchFn = config.fetch ?? fetch;\n  }\n\n  /**\n   * Discover available models for a given root namespace.\n   *\n   * Results are cached per `rootNamespaceId` with a 10-minute TTL.\n   * Use `invalidateCache()` to force an immediate refresh.\n   *\n   * @param rootNamespaceId - GitLab group ID (e.g., 'gid://gitlab/Group/12345')\n   */\n  async discover(rootNamespaceId: string): Promise<DiscoveredModels> {\n    const cached = this.cache.get(rootNamespaceId);\n    if (cached && cached.expiresAt > Date.now()) {\n      return cached.data;\n    }\n\n    const url = `${this.config.instanceUrl}/api/graphql`;\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({\n          query: AI_CHAT_AVAILABLE_MODELS_QUERY,\n          variables: { rootNamespaceId },\n        }),\n      });\n\n      if (!response.ok) {\n        const errorText = await response.text();\n        throw new GitLabError({\n          message: `Model discovery GraphQL request failed: ${response.status} ${response.statusText} - ${errorText}`,\n          statusCode: response.status,\n          responseBody: errorText,\n        });\n      }\n\n      const json = (await response.json()) as {\n        data?: {\n          aiChatAvailableModels?: AiChatAvailableModels | null;\n          metadata?: {\n            featureFlags?: Array<{ name: string; enabled: boolean }>;\n            version?: string;\n          } | null;\n        };\n        errors?: Array<{ message: string }>;\n      };\n\n      if (json.errors && json.errors.length > 0) {\n        throw new GitLabError({\n          message: `Model discovery GraphQL errors: ${json.errors.map((e) => e.message).join(', ')}`,\n        });\n      }\n\n      const models = json.data?.aiChatAvailableModels;\n      const metadata = json.data?.metadata;\n\n      const modelSwitchingEnabled =\n        metadata?.featureFlags?.find((f) => f.name === 'ai_user_model_switching')?.enabled ?? false;\n\n      const result: DiscoveredModels = {\n        defaultModel: models?.defaultModel ?? null,\n        selectableModels: models?.selectableModels ?? [],\n        pinnedModel: models?.pinnedModel ?? null,\n        modelSwitchingEnabled,\n        instanceVersion: metadata?.version ?? null,\n      };\n\n      this.cache.set(rootNamespaceId, {\n        data: result,\n        expiresAt: Date.now() + DISCOVERY_CACHE_TTL_MS,\n      });\n      return result;\n    } catch (error) {\n      if (error instanceof GitLabError) throw error;\n      throw new GitLabError({\n        message: `Model discovery failed: ${error}`,\n        cause: error,\n      });\n    }\n  }\n\n  /**\n   * Get the effective model ref to use for a workflow.\n   *\n   * Priority: pinned > user-selected > default.\n   *\n   * @param rootNamespaceId - GitLab group ID\n   * @param userSelectedRef - Optional user preference\n   */\n  async getEffectiveModelRef(\n    rootNamespaceId: string,\n    userSelectedRef?: string\n  ): Promise<string | null> {\n    const discovered = await this.discover(rootNamespaceId);\n\n    // Pinned model always wins\n    if (discovered.pinnedModel) {\n      return discovered.pinnedModel.ref;\n    }\n\n    // User selection (if model switching is enabled)\n    if (userSelectedRef && discovered.modelSwitchingEnabled) {\n      const isValid = discovered.selectableModels.some((m) => m.ref === userSelectedRef);\n      if (isValid) {\n        return userSelectedRef;\n      }\n    }\n\n    // Default\n    return discovered.defaultModel?.ref ?? null;\n  }\n\n  /**\n   * Invalidate the cached discovery results.\n   */\n  invalidateCache(): void {\n    this.cache.clear();\n  }\n}\n","/**\n * File-based cache for workflow model discovery results and user selection.\n *\n * A single cache file is stored at\n * `~/.cache/opencode/gitlab-workflow-model-cache.json`\n * (or `$XDG_CACHE_HOME/opencode/...` when set).\n *\n * The file contains a JSON object keyed by a truncated SHA-256 hash of the\n * workspace directory path combined with the GitLab instance URL. This ensures\n * that switching instances for the same workspace invalidates the cache.\n * Each value holds:\n *   - `discovery`: The full DiscoveredModels JSON from the last successful discovery\n *   - `selectedModelRef`: The model ref the user last selected\n *   - `selectedModelName`: Human-readable name of the selected model\n *   - `updatedAt`: ISO timestamp of the last write\n */\n\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport * as os from 'os';\nimport * as crypto from 'crypto';\nimport type { DiscoveredModels } from './gitlab-model-discovery';\n\nexport interface ModelCacheEntry {\n  discovery: DiscoveredModels | null;\n  selectedModelRef: string | null;\n  selectedModelName: string | null;\n  updatedAt: string;\n}\n\ntype CacheFile = Record<string, ModelCacheEntry>;\n\nfunction getCacheFilePath(): string {\n  const cacheHome = process.env.XDG_CACHE_HOME || path.join(os.homedir(), '.cache');\n  return path.join(cacheHome, 'opencode', 'gitlab-workflow-model-cache.json');\n}\n\nfunction computeCacheKey(workDir: string, instanceUrl?: string): string {\n  const normalizedUrl = (instanceUrl || 'https://gitlab.com').replace(/\\/$/, '');\n  return crypto\n    .createHash('sha256')\n    .update(`${workDir}\\0${normalizedUrl}`)\n    .digest('hex')\n    .slice(0, 12);\n}\n\nexport class GitLabModelCache {\n  private readonly filePath: string;\n  private readonly key: string;\n\n  constructor(workDir: string, instanceUrl?: string) {\n    this.filePath = getCacheFilePath();\n    this.key = computeCacheKey(workDir, instanceUrl);\n  }\n\n  private readAll(): CacheFile {\n    try {\n      if (!fs.existsSync(this.filePath)) {\n        return {};\n      }\n      const raw = fs.readFileSync(this.filePath, 'utf-8');\n      return JSON.parse(raw) as CacheFile;\n    } catch {\n      return {};\n    }\n  }\n\n  private writeAll(data: CacheFile): void {\n    try {\n      const dir = path.dirname(this.filePath);\n      fs.mkdirSync(dir, { recursive: true, mode: 0o700 });\n      fs.writeFileSync(this.filePath, JSON.stringify(data, null, 2), { mode: 0o600 });\n    } catch {\n      // Best-effort — cache write failures are non-fatal\n    }\n  }\n\n  /**\n   * Load the cached entry for this workspace.\n   * Returns null if no cache exists or is unreadable.\n   */\n  load(): ModelCacheEntry | null {\n    return this.readAll()[this.key] ?? null;\n  }\n\n  /**\n   * Persist the full cache entry to disk.\n   */\n  save(entry: ModelCacheEntry): void {\n    const data = this.readAll();\n    data[this.key] = entry;\n    this.writeAll(data);\n  }\n\n  /**\n   * Update only the discovery portion of the cache, preserving selection.\n   */\n  saveDiscovery(discovery: DiscoveredModels): void {\n    const existing = this.load();\n    this.save({\n      discovery,\n      selectedModelRef: existing?.selectedModelRef ?? null,\n      selectedModelName: existing?.selectedModelName ?? null,\n      updatedAt: new Date().toISOString(),\n    });\n  }\n\n  /**\n   * Update only the selected model, preserving the discovery data.\n   */\n  saveSelection(ref: string | null, name: string | null): void {\n    const existing = this.load();\n    this.save({\n      discovery: existing?.discovery ?? null,\n      selectedModelRef: ref,\n      selectedModelName: name,\n      updatedAt: new Date().toISOString(),\n    });\n  }\n\n  /**\n   * Remove the entry for this workspace from the cache file.\n   */\n  clear(): void {\n    const data = this.readAll();\n    delete data[this.key];\n    if (Object.keys(data).length === 0) {\n      try {\n        if (fs.existsSync(this.filePath)) {\n          fs.unlinkSync(this.filePath);\n        }\n      } catch {\n        // Best-effort\n      }\n    } else {\n      this.writeAll(data);\n    }\n  }\n\n  /**\n   * Convenience: get the cached selected model ref (or null).\n   */\n  getSelectedModelRef(): string | null {\n    return this.load()?.selectedModelRef ?? null;\n  }\n\n  /**\n   * Convenience: get the cached selected model name (or null).\n   */\n  getSelectedModelName(): string | null {\n    return this.load()?.selectedModelName ?? null;\n  }\n\n  /**\n   * Convenience: get the cached discovery result (or null).\n   */\n  getDiscovery(): DiscoveredModels | null {\n    return this.load()?.discovery ?? null;\n  }\n}\n","/**\n * LanguageModelV2 adapter for GitLab Duo Agent Platform (DWS).\n *\n * Maps DWS WebSocket events to the Vercel AI SDK streaming protocol:\n *   newCheckpoint (text)  → text-delta\n *   runMcpTool             → tool-call (emitted for UI visibility)\n *   workflow COMPLETED     → finish(stop)\n *   workflow FAILED        → error\n *\n * IMPORTANT: Tool execution architecture\n * =======================================\n * DWS drives the agentic loop server-side. When DWS requests a tool via\n * `runMcpTool`, we execute it ourselves using the AI SDK tools passed in\n * `options.tools`, send the result back to DWS via WebSocket `actionResponse`,\n * and keep streaming. The stream stays open until DWS sends COMPLETED/FAILED.\n *\n * This means the AI SDK's outer tool loop (which would call doStream() again\n * with tool results in messages) is NOT used for workflow models. The entire\n * agentic conversation happens within a single doStream() call.\n *\n * We still emit `tool-call` stream parts so the UI can show tool usage,\n * but finishReason is always 'stop' (never 'tool-calls').\n *\n * Lifecycle per doStream() call:\n *   1. Get workflow token  (POST /duo_workflows/direct_access)\n *   2. Create workflow     (POST /duo_workflows/workflows)\n *   3. Connect WebSocket   (wss://.../duo_workflows/ws)\n *   4. Send startRequest   (with goal, tools, context)\n *   5. Stream events       (checkpoint → text, tool request → execute → respond)\n *   6. Close on finish     (COMPLETED/FAILED/CANCELLED)\n *\n * SECURITY MODEL — Tool Execution\n * =================================\n * This library acts as a **bridge** between DWS (server) and the host's tool\n * system (e.g., OpenCode).  It does NOT execute host-OS commands itself except\n * for the read-only `git` calls inside `getGitInfo()` (fixed argument lists,\n * no user-controlled data, via `execFile`).\n *\n * Built-in tool mapping (`mapBuiltinTool`)\n * -----------------------------------------\n * DWS built-in tools are mapped to structured host-tool invocations that the\n * host's `toolExecutor` callback then executes through its own permission\n * system.  For tools that ultimately produce shell commands the following\n * defences are applied:\n *\n *   • `shellEscape()` — wraps every argument in single quotes and escapes\n *     embedded single quotes, preventing metacharacter injection for all\n *     argument-based tools (runCommand, runGitCommand, mkdir, runHTTPRequest).\n *\n *   • `validateNoShellMetachars()` — rejects program names and git sub-commands\n *     containing `;`, `&`, `|`, `` ` ``, `$`, `(`, `)`, `<`, `>` before they\n *     reach shellEscape, providing a defence-in-depth check.\n *\n *   • `runShellCommand` — intentionally passes the command string through\n *     **without sanitization** because it is a deliberately raw shell tool.\n *     The host's `toolExecutor` / permission system is the final gate and must\n *     decide whether to allow it.  A length cap (10 000 chars) limits DoS via\n *     oversized payloads.\n *\n *   • `runHTTPRequest` — only `http://` and `https://` URL schemes are allowed\n *     (allowlist); all others (file://, gopher://, ftp://, etc.) are rejected.\n *     A `--` separator before the URL prevents flag injection via paths like\n *     `--output /tmp/evil`.\n *\n *   • `mkdir` — rejects null bytes in the directory path.\n *\n * Error sanitization\n * -------------------\n * All error messages forwarded into the stream (tool catch blocks, failed\n * events, WebSocket close reasons) are passed through `sanitizeErrorMessage()`\n * which redacts Bearer tokens, GitLab PAT/CI tokens, and URL credential query\n * parameters before they are surfaced to callers or logged.\n *\n * Trust boundary\n * ---------------\n * DWS is treated as a **trusted server** for the purpose of tool invocation —\n * it controls which tools are called and with what arguments.  Consumers MUST\n * implement their own authorization layer in the `toolExecutor` callback\n * (e.g., user confirmation prompts, allow-lists) for any tool that can cause\n * side effects on the user's machine.\n */\n\nimport { GitLabWorkflowClient } from './gitlab-workflow-client';\nimport { GitLabWorkflowTokenClient } from './gitlab-workflow-token-client';\nimport { GitLabProjectDetector } from './gitlab-project-detector';\nimport { GitLabError } from './gitlab-error';\nimport { getWorkflowModelRef } from './model-mappings';\nimport { GitLabModelDiscovery } from './gitlab-model-discovery';\nimport { GitLabModelCache } from './gitlab-model-cache';\nimport { mapBuiltinTool, sanitizeErrorMessage } from './gitlab-workflow-builtins';\n\nimport type {\n  LanguageModelV2,\n  LanguageModelV2CallOptions,\n  LanguageModelV2StreamPart,\n  LanguageModelV2FinishReason,\n  LanguageModelV2CallWarning,\n  LanguageModelV2Content,\n  LanguageModelV2Usage,\n  LanguageModelV2Message,\n  LanguageModelV2FunctionTool,\n} from '@ai-sdk/provider';\n\nimport type {\n  GitLabWorkflowOptions,\n  GitLabWorkflowClientConfig,\n  McpToolDefinition,\n  AdditionalContext,\n  StartRequest,\n  WorkflowClientEvent,\n  CheckpointData,\n  UiChatLogEntry,\n  NewCheckpoint,\n} from './gitlab-workflow-types';\n\ninterface StreamState {\n  streamClosed: boolean;\n  streamedInputChars: number;\n  streamedOutputChars: number;\n  pendingToolCount: number;\n  deferredClose: (() => void) | null;\n  activeTextBlockId: string | null;\n  agentMessageEmitted: Map<string, number>;\n  currentAgentMessageId: string;\n  activeClient: GitLabWorkflowClient | null;\n}\n\nimport {\n  DEFAULT_WORKFLOW_DEFINITION,\n  DEFAULT_CLIENT_CAPABILITIES,\n  CLIENT_VERSION,\n} from './gitlab-workflow-types';\n\nexport interface GitLabWorkflowLanguageModelConfig extends GitLabWorkflowClientConfig {\n  /** Provider name (e.g., 'gitlab.workflow') */\n  provider: string;\n}\n\n// ---------------------------------------------------------------------------\n// Payload size utilities\n// ---------------------------------------------------------------------------\n\nfunction simplifySchemaObj(schema: Record<string, unknown>): Record<string, unknown> {\n  if (!schema || typeof schema !== 'object') return schema;\n\n  const result: Record<string, unknown> = {};\n  for (const [key, value] of Object.entries(schema)) {\n    if (key === 'description' || key === 'examples' || key === 'default') {\n      continue;\n    }\n    if (key === 'properties' && typeof value === 'object' && value !== null) {\n      const props: Record<string, unknown> = {};\n      for (const [propName, propValue] of Object.entries(value as Record<string, unknown>)) {\n        if (typeof propValue === 'object' && propValue !== null) {\n          props[propName] = simplifySchemaObj(propValue as Record<string, unknown>);\n        } else {\n          props[propName] = propValue;\n        }\n      }\n      result[key] = props;\n    } else if (key === 'items' && typeof value === 'object' && value !== null) {\n      result[key] = simplifySchemaObj(value as Record<string, unknown>);\n    } else {\n      result[key] = value;\n    }\n  }\n  return result;\n}\n\nfunction simplifySchema(schemaStr: string): string {\n  try {\n    return JSON.stringify(simplifySchemaObj(JSON.parse(schemaStr)));\n  } catch {\n    return schemaStr;\n  }\n}\n\nfunction minimalSchemaObj(schema: Record<string, unknown>): Record<string, unknown> {\n  if (!schema || typeof schema !== 'object') return schema;\n\n  const result: Record<string, unknown> = { type: schema.type || 'object' };\n  if (schema.required) {\n    result.required = schema.required;\n  }\n  if (schema.properties && typeof schema.properties === 'object') {\n    const props: Record<string, unknown> = {};\n    for (const [propName, propValue] of Object.entries(\n      schema.properties as Record<string, unknown>\n    )) {\n      if (typeof propValue === 'object' && propValue !== null) {\n        const pv = propValue as Record<string, unknown>;\n        props[propName] = { type: pv.type || 'string' };\n      } else {\n        props[propName] = { type: 'string' };\n      }\n    }\n    result.properties = props;\n  }\n  return result;\n}\n\nfunction minimalSchema(schemaStr: string): string {\n  try {\n    return JSON.stringify(minimalSchemaObj(JSON.parse(schemaStr)));\n  } catch {\n    return schemaStr;\n  }\n}\n\n/**\n * Callback for executing a tool requested by DWS.\n * Provided by the consumer (e.g., OpenCode) to bridge DWS tool requests\n * to the host's tool execution system.\n *\n * @param toolName - Name of the tool DWS wants to execute\n * @param args - JSON-encoded arguments\n * @returns Tool execution result as a string, or throws on error\n */\nexport type WorkflowToolExecutor = (\n  toolName: string,\n  args: string,\n  requestID: string\n) => Promise<{ result: string; error?: string | null }>;\n\n// mapBuiltinTool, sanitizeErrorMessage, shellEscape, validateNoShellMetachars\n// are imported from './gitlab-workflow-builtins' (shared module).\n\n/**\n * GitLab Duo Agent Platform Language Model.\n *\n * Implements LanguageModelV2 by bridging the DWS WebSocket protocol\n * to the Vercel AI SDK stream part format.\n */\nexport class GitLabWorkflowLanguageModel implements LanguageModelV2 {\n  readonly specificationVersion = 'v2' as const;\n  readonly modelId: string;\n  readonly supportedUrls: Record<string, RegExp[]> = {};\n\n  private readonly config: GitLabWorkflowLanguageModelConfig;\n  private readonly workflowOptions: GitLabWorkflowOptions;\n  private readonly tokenClient: GitLabWorkflowTokenClient;\n  private readonly projectDetector: GitLabProjectDetector;\n  private readonly modelDiscovery: GitLabModelDiscovery;\n  private readonly modelCache: GitLabModelCache;\n\n  // Cached detected project path\n  private detectedProjectPath: string | null = null;\n\n  // Workflow ID persisted across turns for multi-turn conversations.\n  // When DWS sends INPUT_REQUIRED, the workflow stays alive server-side.\n  // On the next doStream() call we reuse this ID (skip createWorkflow).\n  private currentWorkflowId: string | null = null;\n\n  // Persisted across turns so that cumulative DWS chat logs don't re-emit\n  // messages that were already streamed in a previous doStream() call.\n  private persistedAgentEmitted = new Map<string, number>();\n\n  // Track all active stream clients so stopWorkflow() can stop them all.\n  private readonly activeClients = new Set<GitLabWorkflowClient>();\n\n  // Cache resolved values to avoid redundant GraphQL calls\n  private _selectedModelRef?: string;\n  private _selectedModelName?: string;\n  private _rootNamespaceId?: string;\n  private _discoveryPromise?: Promise<string>;\n\n  /**\n   * Get the cached selected model ref.\n   */\n  get selectedModelRef(): string | null {\n    return this._selectedModelRef ?? null;\n  }\n\n  /**\n   * Set the selected model ref (e.g., from an eager discover call).\n   * This will be used by resolveModelRef() to skip the picker.\n   * Also persists to the file-based workspace cache.\n   */\n  set selectedModelRef(ref: string | null) {\n    this._selectedModelRef = ref ?? undefined;\n    this.modelCache.saveSelection(ref, this._selectedModelName ?? null);\n  }\n\n  /**\n   * Get the cached selected model display name.\n   */\n  get selectedModelName(): string | null {\n    return this._selectedModelName ?? null;\n  }\n\n  /**\n   * Set the selected model display name.\n   * Also persists to the file-based workspace cache.\n   */\n  set selectedModelName(name: string | null) {\n    this._selectedModelName = name ?? undefined;\n    this.modelCache.saveSelection(this._selectedModelRef ?? null, name);\n  }\n\n  /**\n   * Optional external tool executor. When set, this is called for tool\n   * requests instead of looking up tools from `options.tools`.\n   * This allows the consumer (OpenCode) to wire in its permission system.\n   *\n   * The executor is automatically bound to the async context at the time\n   * it is set, so that AsyncLocalStorage-based contexts (like Instance)\n   * remain available when the executor is invoked from WebSocket callbacks.\n   */\n  private _toolExecutor: WorkflowToolExecutor | null = null;\n\n  /**\n   * Optional callback invoked with intermediate token usage estimates\n   * after each tool execution completes. This allows the consumer to\n   * display live token counts during long-running DWS workflows, since\n   * the AI SDK only surfaces usage via finish-step at stream end.\n   */\n  onUsageUpdate: ((usage: { inputTokens: number; outputTokens: number }) => void) | null = null;\n\n  /**\n   * Optional callback invoked when multiple workflow models are available\n   * and the user should pick one. Set per-stream by the host (e.g., OpenCode)\n   * alongside `toolExecutor`. Takes precedence over `workflowOptions.onSelectModel`.\n   */\n  onSelectModel:\n    | ((models: import('./gitlab-model-discovery').AiModel[]) => Promise<string | null | undefined>)\n    | null = null;\n\n  get toolExecutor(): WorkflowToolExecutor | null {\n    return this._toolExecutor;\n  }\n\n  set toolExecutor(executor: WorkflowToolExecutor | null) {\n    if (executor) {\n      try {\n        // eslint-disable-next-line @typescript-eslint/no-var-requires\n        const { AsyncResource } = require('node:async_hooks');\n        this._toolExecutor = AsyncResource.bind(executor);\n      } catch {\n        this._toolExecutor = executor;\n      }\n    } else {\n      this._toolExecutor = null;\n    }\n  }\n\n  constructor(\n    modelId: string,\n    config: GitLabWorkflowLanguageModelConfig,\n    workflowOptions: GitLabWorkflowOptions = {}\n  ) {\n    this.modelId = modelId;\n    this.config = config;\n    this.workflowOptions = workflowOptions;\n\n    const workDir = workflowOptions.workingDirectory ?? process.cwd();\n    this.modelCache = new GitLabModelCache(workDir, config.instanceUrl);\n\n    const cached = this.modelCache.load();\n    if (cached?.selectedModelRef) {\n      this._selectedModelRef = cached.selectedModelRef;\n    }\n    if (cached?.selectedModelName) {\n      this._selectedModelName = cached.selectedModelName;\n    }\n\n    this.tokenClient = new GitLabWorkflowTokenClient({\n      instanceUrl: config.instanceUrl,\n      getHeaders: config.getHeaders,\n      refreshApiKey: config.refreshApiKey,\n      fetch: config.fetch,\n      featureFlags: config.featureFlags,\n    });\n\n    this.projectDetector = new GitLabProjectDetector({\n      instanceUrl: config.instanceUrl,\n      getHeaders: config.getHeaders,\n      fetch: config.fetch,\n    });\n\n    this.modelDiscovery = new GitLabModelDiscovery({\n      instanceUrl: config.instanceUrl,\n      getHeaders: config.getHeaders,\n      fetch: config.fetch,\n    });\n  }\n\n  get provider(): string {\n    return this.config.provider;\n  }\n\n  /**\n   * Resolve the project ID (path) to use for workflow creation.\n   * Priority: explicit option > auto-detected from git remote > undefined.\n   */\n  private async resolveProjectId(): Promise<string | undefined> {\n    if (this.workflowOptions.projectId) {\n      return this.workflowOptions.projectId;\n    }\n\n    if (this.detectedProjectPath) {\n      return this.detectedProjectPath;\n    }\n\n    const workDir = this.workflowOptions.workingDirectory ?? process.cwd();\n    const project = await this.projectDetector.detectProject(workDir);\n    if (project) {\n      this.detectedProjectPath = project.pathWithNamespace;\n      return project.pathWithNamespace;\n    }\n\n    return undefined;\n  }\n\n  /**\n   * Resolve the root namespace GID to use for model discovery.\n   *\n   * Priority:\n   *   1. Explicit `rootNamespaceId` in workflowOptions (caller-provided GID)\n   *   2. Auto-detected from git remote via project detector (namespace.id → GID)\n   *   3. Cached from previous call\n   */\n  private async resolveRootNamespaceId(): Promise<string | null> {\n    if (this.workflowOptions.rootNamespaceId) {\n      return this.workflowOptions.rootNamespaceId;\n    }\n\n    // Return cached value if available\n    if (this._rootNamespaceId !== undefined) {\n      return this._rootNamespaceId;\n    }\n\n    const workDir = this.workflowOptions.workingDirectory ?? process.cwd();\n    const project = await this.projectDetector.detectProject(workDir);\n    if (project?.namespaceId) {\n      const gid = `gid://gitlab/Group/${project.namespaceId}`;\n      this._rootNamespaceId = gid;\n      return gid;\n    }\n\n    this._rootNamespaceId = null;\n    return null;\n  }\n\n  /**\n   * Resolve the effective DWS model ref to use for this stream.\n   * Deduplicates concurrent calls via a shared promise.\n   *\n   * Priority for the canonical `duo-workflow` model ID:\n   *   1. Admin-pinned model (from GitLabModelDiscovery) — always wins\n   *   2. User selection via onSelectModel callback (if model switching enabled)\n   *   3. Workspace default model\n   *   4. File-cached discovery/selection — used when live discovery fails\n   *   5. Hard-coded 'default' (DWS decides) — fallback when discovery fails\n   *\n   * For all other `duo-workflow-*` model IDs the static mapping is used as-is.\n   */\n  private async resolveModelRef(): Promise<string> {\n    const staticRef = getWorkflowModelRef(this.modelId);\n\n    if (this.modelId !== 'duo-workflow') {\n      return staticRef ?? 'default';\n    }\n\n    if (this._selectedModelRef) {\n      return this._selectedModelRef;\n    }\n\n    if (!this._discoveryPromise) {\n      this._discoveryPromise = this.doResolveModelRef();\n      this._discoveryPromise.finally(() => {\n        this._discoveryPromise = undefined;\n      });\n    }\n    return this._discoveryPromise;\n  }\n\n  private async doResolveModelRef(): Promise<string> {\n    const rootNamespaceId = await this.resolveRootNamespaceId();\n\n    if (!rootNamespaceId) {\n      this._selectedModelRef = 'default';\n      return 'default';\n    }\n\n    try {\n      const discovered = await this.modelDiscovery.discover(rootNamespaceId);\n      this.modelCache.saveDiscovery(discovered);\n\n      if (discovered.pinnedModel) {\n        this._selectedModelRef = discovered.pinnedModel.ref;\n        this._selectedModelName = discovered.pinnedModel.name;\n        this.modelCache.saveSelection(discovered.pinnedModel.ref, discovered.pinnedModel.name);\n        return discovered.pinnedModel.ref;\n      }\n\n      const selectFn = this.onSelectModel ?? this.workflowOptions.onSelectModel;\n      if (discovered.selectableModels.length > 0 && selectFn) {\n        const selected = await selectFn(discovered.selectableModels);\n        if (selected) {\n          const match = discovered.selectableModels.find((m) => m.ref === selected);\n          if (match) {\n            this._selectedModelRef = match.ref;\n            this._selectedModelName = match.name;\n            this.modelCache.saveSelection(match.ref, match.name);\n            return match.ref;\n          }\n        }\n      }\n\n      if (discovered.defaultModel) {\n        this._selectedModelRef = discovered.defaultModel.ref;\n        this._selectedModelName = discovered.defaultModel.name;\n        this.modelCache.saveSelection(discovered.defaultModel.ref, discovered.defaultModel.name);\n        return discovered.defaultModel.ref;\n      }\n    } catch {\n      const cachedEntry = this.modelCache.load();\n      if (cachedEntry?.selectedModelRef) {\n        this._selectedModelRef = cachedEntry.selectedModelRef;\n        this._selectedModelName = cachedEntry.selectedModelName ?? undefined;\n        return cachedEntry.selectedModelRef;\n      }\n    }\n\n    this._selectedModelRef = 'default';\n    return 'default';\n  }\n\n  /**\n   * Pre-fetch available models for the workspace.\n   * Call this early (e.g., on IDE startup) to avoid blocking the first stream.\n   * Results are persisted to the workspace model cache.\n   *\n   * @param rootNamespaceId - GitLab group ID (e.g., 'gid://gitlab/Group/12345')\n   * @returns Discovered models with default, selectable, and pinned models\n   */\n  async discoverModels(\n    rootNamespaceId: string\n  ): Promise<import('./gitlab-model-discovery').DiscoveredModels> {\n    const result = await this.modelDiscovery.discover(rootNamespaceId);\n    this.modelCache.saveDiscovery(result);\n    return result;\n  }\n\n  /**\n   * Get the file-based model cache instance for this workspace.\n   * Useful for consumers that need direct cache access (e.g., the discover route).\n   */\n  getModelCache(): GitLabModelCache {\n    return this.modelCache;\n  }\n\n  /**\n   * Stop the active workflow.\n   */\n  stopWorkflow(): void {\n    for (const client of this.activeClients) {\n      if (client.isConnected) {\n        client.stop();\n      }\n    }\n  }\n\n  /**\n   * Reset the workflow state, forcing a new workflow to be created on the\n   * next doStream() call. Call this when starting a new conversation.\n   */\n  resetWorkflow(): void {\n    this.currentWorkflowId = null;\n    this.persistedAgentEmitted.clear();\n  }\n\n  /**\n   * Get the current workflow ID (if any).\n   * Useful for consumers that need to track workflow state.\n   */\n  get workflowId(): string | null {\n    return this.currentWorkflowId;\n  }\n\n  // ---------------------------------------------------------------------------\n  // LanguageModelV2 — doGenerate (non-streaming)\n  // ---------------------------------------------------------------------------\n\n  async doGenerate(options: LanguageModelV2CallOptions): Promise<{\n    content: LanguageModelV2Content[];\n    finishReason: LanguageModelV2FinishReason;\n    usage: LanguageModelV2Usage;\n    warnings: LanguageModelV2CallWarning[];\n  }> {\n    // DWS is inherently streaming. Collect the full stream into a single result.\n    const { stream } = await this.doStream(options);\n    const reader = stream.getReader();\n\n    const textParts: string[] = [];\n    const toolCalls: LanguageModelV2Content[] = [];\n    let finishReason: LanguageModelV2FinishReason = 'unknown';\n    const usage: LanguageModelV2Usage = { inputTokens: 0, outputTokens: 0, totalTokens: 0 };\n\n    try {\n      // eslint-disable-next-line no-constant-condition\n      while (true) {\n        const { done, value } = await reader.read();\n        if (done) break;\n\n        switch (value.type) {\n          case 'text-delta':\n            textParts.push(value.delta);\n            break;\n          case 'tool-call':\n            toolCalls.push({\n              type: 'tool-call',\n              toolCallId: value.toolCallId,\n              toolName: value.toolName,\n              input: value.input,\n            });\n            break;\n          case 'finish':\n            finishReason = value.finishReason;\n            if (value.usage) {\n              usage.inputTokens = value.usage.inputTokens ?? 0;\n              usage.outputTokens = value.usage.outputTokens ?? 0;\n              usage.totalTokens = value.usage.totalTokens ?? 0;\n            }\n            break;\n          case 'error':\n            throw value.error;\n        }\n      }\n    } finally {\n      reader.releaseLock();\n    }\n\n    const content: LanguageModelV2Content[] = [];\n    const fullText = textParts.join('');\n    if (fullText) {\n      content.push({ type: 'text', text: fullText });\n    }\n    content.push(...toolCalls);\n\n    return { content, finishReason, usage, warnings: [] };\n  }\n\n  // ---------------------------------------------------------------------------\n  // LanguageModelV2 — doStream (streaming)\n  // ---------------------------------------------------------------------------\n\n  async doStream(options: LanguageModelV2CallOptions): Promise<{\n    stream: ReadableStream<LanguageModelV2StreamPart>;\n    request?: { body?: unknown };\n  }> {\n    // Extract the user's goal from the prompt\n    const goal = this.extractGoalFromPrompt(options.prompt);\n\n    // Get the model ref for WebSocket URL — resolved dynamically for 'duo-workflow'.\n    const modelRef = await this.resolveModelRef();\n\n    // Extract MCP tools from options.tools (AI SDK tools → DWS mcpTools)\n    const mcpTools = this.extractMcpTools(options);\n\n    // Merge preapproved tools — all tool names if options provided\n    const preapprovedTools = this.workflowOptions.preapprovedTools ?? mcpTools.map((t) => t.name);\n\n    // Build additional context from conversation history.\n    const additionalContext = this.buildAdditionalContext(options.prompt);\n\n    const toolExecutor = this.toolExecutor ?? null;\n\n    // Step 1: Warm the token cache — createWorkflow() below requires a valid\n    // session, and getToken() caches the result for subsequent API calls.\n    // The DWS token itself is used server-side; the WebSocket authenticates\n    // via the GitLab PAT/OAuth token in headers.\n    await this.tokenClient.getToken(\n      this.workflowOptions.workflowDefinition ?? DEFAULT_WORKFLOW_DEFINITION,\n      this.workflowOptions.rootNamespaceId\n    );\n\n    // Step 1b: Resolve project ID (auto-detect from git remote if needed)\n    const projectId = await this.resolveProjectId();\n\n    let workflowId: string;\n    if (this.currentWorkflowId) {\n      workflowId = this.currentWorkflowId;\n    } else {\n      workflowId = await this.tokenClient.createWorkflow(goal, {\n        projectId,\n        namespaceId: this.workflowOptions.namespaceId,\n        workflowDefinition: this.workflowOptions.workflowDefinition,\n      });\n      this.currentWorkflowId = workflowId;\n    }\n\n    // Step 3: Create WebSocket client\n    const wsClient = new GitLabWorkflowClient();\n    this.activeClients.add(wsClient);\n\n    let textBlockCounter = 0;\n\n    // Per-stream state — isolated so parallel streams don't corrupt each other.\n    // Seed agentMessageEmitted from the persisted map so that cumulative DWS\n    // chat logs don't re-emit messages already streamed in a prior turn.\n    const ss: StreamState = {\n      streamClosed: false,\n      streamedInputChars: 0,\n      streamedOutputChars: 0,\n      pendingToolCount: 0,\n      deferredClose: null,\n      activeTextBlockId: null,\n      agentMessageEmitted: new Map(this.persistedAgentEmitted),\n      currentAgentMessageId: '',\n      activeClient: wsClient,\n    };\n\n    for (const msg of options.prompt) {\n      if (msg.role === 'system') {\n        ss.streamedInputChars += msg.content.length;\n      } else if (msg.role === 'user') {\n        for (const part of msg.content) {\n          if (part.type === 'text') {\n            ss.streamedInputChars += (part as { text: string }).text.length;\n          }\n        }\n      }\n    }\n\n    const stream = new ReadableStream<LanguageModelV2StreamPart>({\n      start: async (controller) => {\n        try {\n          // Connect WebSocket\n          await wsClient.connect(\n            {\n              instanceUrl: this.config.instanceUrl,\n              modelRef,\n              headers: this.config.getHeaders(),\n              projectId: this.workflowOptions.projectId,\n              namespaceId: this.workflowOptions.namespaceId,\n              rootNamespaceId: this.workflowOptions.rootNamespaceId,\n            },\n            (event: WorkflowClientEvent) => {\n              this.handleWorkflowEvent(\n                ss,\n                event,\n                controller,\n                wsClient,\n                toolExecutor,\n                () => `text-${textBlockCounter++}`\n              );\n            }\n          );\n\n          const workflowDef =\n            this.workflowOptions.workflowDefinition ?? DEFAULT_WORKFLOW_DEFINITION;\n          const capabilities =\n            this.workflowOptions.clientCapabilities ?? DEFAULT_CLIENT_CAPABILITIES;\n          const workflowMetadata = await this.buildWorkflowMetadata();\n          const metadataStr = JSON.stringify(workflowMetadata);\n\n          const basePayload = {\n            workflowID: workflowId,\n            clientVersion: CLIENT_VERSION,\n            workflowDefinition: workflowDef,\n            goal,\n            workflowMetadata: metadataStr,\n            clientCapabilities: capabilities,\n            preapproved_tools: preapprovedTools,\n          };\n          const baseSize = JSON.stringify(basePayload).length + 100;\n\n          const trimmed = this.trimPayload(mcpTools, additionalContext, baseSize);\n\n          const trimmedPreapproved = preapprovedTools.filter((name) =>\n            trimmed.mcpTools.some((t) => t.name === name)\n          );\n\n          const startReq: StartRequest = {\n            workflowID: workflowId,\n            clientVersion: CLIENT_VERSION,\n            workflowDefinition: workflowDef,\n            goal,\n            workflowMetadata: metadataStr,\n            additional_context: trimmed.additionalContext,\n            clientCapabilities: capabilities,\n            mcpTools: trimmed.mcpTools,\n            preapproved_tools: trimmedPreapproved,\n          };\n\n          if (this.workflowOptions.flowConfig) {\n            startReq.flowConfig = this.workflowOptions.flowConfig;\n          }\n          if (this.workflowOptions.flowConfigSchemaVersion) {\n            startReq.flowConfigSchemaVersion = this.workflowOptions.flowConfigSchemaVersion;\n          }\n\n          wsClient.sendStartRequest(startReq);\n\n          // Emit stream-start\n          controller.enqueue({\n            type: 'stream-start',\n            warnings: [],\n          });\n\n          // Emit response metadata\n          controller.enqueue({\n            type: 'response-metadata',\n            id: workflowId,\n            modelId: modelRef,\n          });\n        } catch (error) {\n          if (!ss.streamClosed) {\n            controller.enqueue({\n              type: 'error',\n              error:\n                error instanceof GitLabError\n                  ? error\n                  : new GitLabError({\n                      message: `Workflow connection failed: ${error}`,\n                      cause: error,\n                    }),\n            });\n            ss.streamClosed = true;\n            controller.close();\n          }\n        }\n      },\n      cancel: (_reason) => {\n        wsClient.stop();\n        wsClient.close();\n        this.activeClients.delete(wsClient);\n        ss.activeClient = null;\n        this.currentWorkflowId = null;\n      },\n    });\n\n    return {\n      stream,\n      request: {\n        body: { workflowId, modelRef, goal },\n      },\n    };\n  }\n\n  // ---------------------------------------------------------------------------\n  // Event handling\n  // ---------------------------------------------------------------------------\n\n  private handleWorkflowEvent(\n    ss: StreamState,\n    event: WorkflowClientEvent,\n    controller: ReadableStreamDefaultController<LanguageModelV2StreamPart>,\n    wsClient: GitLabWorkflowClient,\n    toolExecutor: WorkflowToolExecutor | null,\n    nextTextId: () => string\n  ): void {\n    if (ss.streamClosed) {\n      return;\n    }\n\n    switch (event.type) {\n      case 'checkpoint': {\n        this.processCheckpoint(ss, event.data, controller, nextTextId);\n        break;\n      }\n\n      case 'tool-request': {\n        const { requestID, data } = event;\n        let parsedArgs: string;\n        try {\n          JSON.parse(data.args);\n          parsedArgs = data.args;\n        } catch {\n          parsedArgs = data.args || '{}';\n        }\n\n        if (ss.activeTextBlockId) {\n          controller.enqueue({ type: 'text-end', id: ss.activeTextBlockId });\n          ss.activeTextBlockId = null;\n        }\n\n        controller.enqueue({\n          type: 'tool-input-start',\n          id: requestID,\n          toolName: data.name,\n          providerExecuted: true,\n        });\n        controller.enqueue({\n          type: 'tool-input-delta',\n          id: requestID,\n          delta: parsedArgs,\n        });\n        controller.enqueue({\n          type: 'tool-input-end',\n          id: requestID,\n        });\n        controller.enqueue({\n          type: 'tool-call',\n          toolCallId: requestID,\n          toolName: data.name,\n          input: parsedArgs,\n          providerExecuted: true,\n        });\n\n        this.executeToolAndRespond(\n          ss,\n          wsClient,\n          controller,\n          requestID,\n          data.name,\n          parsedArgs,\n          toolExecutor\n        ).catch(() => {});\n        break;\n      }\n\n      case 'builtin-tool-request': {\n        const mapped = mapBuiltinTool(event.toolName, event.data);\n        const mappedArgs = JSON.stringify(mapped.args);\n\n        if (ss.activeTextBlockId) {\n          controller.enqueue({ type: 'text-end', id: ss.activeTextBlockId });\n          ss.activeTextBlockId = null;\n        }\n\n        controller.enqueue({\n          type: 'tool-input-start',\n          id: event.requestID,\n          toolName: mapped.toolName,\n          providerExecuted: true,\n        });\n        controller.enqueue({\n          type: 'tool-input-delta',\n          id: event.requestID,\n          delta: mappedArgs,\n        });\n        controller.enqueue({\n          type: 'tool-input-end',\n          id: event.requestID,\n        });\n        controller.enqueue({\n          type: 'tool-call',\n          toolCallId: event.requestID,\n          toolName: mapped.toolName,\n          input: mappedArgs,\n          providerExecuted: true,\n        });\n\n        this.executeToolAndRespond(\n          ss,\n          wsClient,\n          controller,\n          event.requestID,\n          mapped.toolName,\n          mappedArgs,\n          toolExecutor\n        ).catch(() => {});\n        break;\n      }\n\n      case 'completed': {\n        if (ss.activeTextBlockId) {\n          controller.enqueue({ type: 'text-end', id: ss.activeTextBlockId });\n          ss.activeTextBlockId = null;\n        }\n\n        const doCompleteClose = () => {\n          if (ss.streamClosed) return;\n          // Approximate token counts (1 token ≈ 4 chars). DWS does not expose\n          // actual token usage; these are estimates for AI SDK compatibility only.\n          const inputTokens = Math.ceil(ss.streamedInputChars / 4);\n          const outputTokens = Math.ceil(ss.streamedOutputChars / 4);\n          controller.enqueue({\n            type: 'finish',\n            finishReason: 'stop',\n            usage: { inputTokens, outputTokens, totalTokens: inputTokens + outputTokens },\n          });\n          ss.streamClosed = true;\n          controller.close();\n          this.cleanupClient(ss);\n        };\n\n        if (ss.pendingToolCount > 0) {\n          ss.deferredClose = doCompleteClose;\n        } else {\n          ss.deferredClose = null;\n          doCompleteClose();\n        }\n        break;\n      }\n\n      case 'failed': {\n        if (ss.activeTextBlockId) {\n          controller.enqueue({ type: 'text-end', id: ss.activeTextBlockId });\n          ss.activeTextBlockId = null;\n        }\n        controller.enqueue({\n          type: 'error',\n          error: new GitLabError({\n            message: `Workflow failed: ${sanitizeErrorMessage(event.error.message)}`,\n            cause: event.error,\n          }),\n        });\n        ss.streamClosed = true;\n        controller.close();\n        this.cleanupClient(ss, true);\n        break;\n      }\n\n      case 'closed': {\n        if (ss.streamClosed) {\n          break;\n        }\n        if (ss.activeTextBlockId) {\n          controller.enqueue({ type: 'text-end', id: ss.activeTextBlockId });\n          ss.activeTextBlockId = null;\n        }\n\n        const doClose = () => {\n          if (ss.streamClosed) return;\n          if (event.code !== 1000) {\n            controller.enqueue({\n              type: 'error',\n              error: new GitLabError({\n                message: `WebSocket closed unexpectedly: code=${event.code} reason=${sanitizeErrorMessage(event.reason)}`,\n                statusCode: event.code,\n              }),\n            });\n            ss.streamClosed = true;\n            controller.close();\n            this.cleanupClient(ss, true);\n          } else {\n            const inTok = Math.ceil(ss.streamedInputChars / 4);\n            const outTok = Math.ceil(ss.streamedOutputChars / 4);\n            controller.enqueue({\n              type: 'finish',\n              finishReason: 'stop',\n              usage: { inputTokens: inTok, outputTokens: outTok, totalTokens: inTok + outTok },\n            });\n            ss.streamClosed = true;\n            controller.close();\n            this.cleanupClient(ss);\n          }\n        };\n\n        if (ss.pendingToolCount > 0) {\n          ss.deferredClose = doClose;\n        } else {\n          ss.deferredClose = null;\n          doClose();\n        }\n        break;\n      }\n    }\n  }\n\n  // ---------------------------------------------------------------------------\n  // Checkpoint content extraction\n  // ---------------------------------------------------------------------------\n\n  private processCheckpoint(\n    ss: StreamState,\n    checkpoint: NewCheckpoint,\n    controller: ReadableStreamDefaultController<LanguageModelV2StreamPart>,\n    nextTextId: () => string\n  ): void {\n    if (!checkpoint.checkpoint) {\n      if (checkpoint.content) {\n        if (!ss.activeTextBlockId) {\n          ss.activeTextBlockId = nextTextId();\n          controller.enqueue({ type: 'text-start', id: ss.activeTextBlockId });\n        }\n        controller.enqueue({\n          type: 'text-delta',\n          id: ss.activeTextBlockId,\n          delta: checkpoint.content,\n        });\n        ss.streamedOutputChars += checkpoint.content.length;\n      }\n      return;\n    }\n\n    let parsed: CheckpointData;\n    try {\n      parsed = JSON.parse(checkpoint.checkpoint);\n    } catch (e) {\n      return;\n    }\n\n    const chatLog = parsed.channel_values?.ui_chat_log;\n    if (!chatLog || !Array.isArray(chatLog) || chatLog.length === 0) {\n      return;\n    }\n\n    if (\n      checkpoint.status !== 'RUNNING' &&\n      checkpoint.status !== 'INPUT_REQUIRED' &&\n      checkpoint.status !== 'FINISHED' &&\n      checkpoint.status !== 'COMPLETED'\n    ) {\n      return;\n    }\n\n    for (let i = 0; i < chatLog.length; i++) {\n      const entry = chatLog[i] as UiChatLogEntry;\n      if (entry.message_type !== 'agent') continue;\n\n      const content = entry.content || '';\n      const msgId = entry.message_id || `idx-${i}`;\n      const emittedLen = ss.agentMessageEmitted.get(msgId) ?? 0;\n\n      if (content.length <= emittedLen) continue;\n\n      const delta = content.slice(emittedLen);\n      const isSameMsg = msgId === ss.currentAgentMessageId;\n\n      if (!isSameMsg && ss.activeTextBlockId) {\n        controller.enqueue({ type: 'text-end', id: ss.activeTextBlockId });\n        ss.activeTextBlockId = null;\n      }\n\n      if (!ss.activeTextBlockId) {\n        ss.activeTextBlockId = nextTextId();\n        controller.enqueue({ type: 'text-start', id: ss.activeTextBlockId });\n      }\n      controller.enqueue({\n        type: 'text-delta',\n        id: ss.activeTextBlockId,\n        delta,\n      });\n      ss.streamedOutputChars += delta.length;\n\n      ss.agentMessageEmitted.set(msgId, content.length);\n      this.persistedAgentEmitted.set(msgId, content.length);\n      ss.currentAgentMessageId = msgId;\n    }\n  }\n\n  private async executeToolAndRespond(\n    ss: StreamState,\n    wsClient: GitLabWorkflowClient,\n    controller: ReadableStreamDefaultController<LanguageModelV2StreamPart>,\n    requestID: string,\n    toolName: string,\n    argsJson: string,\n    toolExecutor: WorkflowToolExecutor | null\n  ): Promise<void> {\n    ss.pendingToolCount++;\n\n    const safeEnqueue = (part: LanguageModelV2StreamPart): void => {\n      if (ss.streamClosed) {\n        return;\n      }\n      try {\n        controller.enqueue(part);\n      } catch {\n        // Stream may have been closed between the check and enqueue\n      }\n    };\n\n    try {\n      if (toolExecutor) {\n        const result = await toolExecutor(toolName, argsJson, requestID);\n        wsClient.sendActionResponse(requestID, result.result, result.error);\n\n        // Track tool call tokens (args as input, result as output)\n        ss.streamedInputChars += argsJson.length;\n        ss.streamedOutputChars += result.result.length;\n\n        let toolOutput = result.result;\n        let toolTitle = `${toolName} result`;\n        let toolMetadata: Record<string, unknown> = { output: result.result };\n        try {\n          const parsed = JSON.parse(result.result);\n          if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {\n            if (typeof parsed.output === 'string') {\n              toolOutput = parsed.output;\n            } else if (parsed.output != null) {\n              toolOutput = JSON.stringify(parsed.output);\n            }\n            if (typeof parsed.title === 'string') toolTitle = parsed.title;\n            if (parsed.metadata && typeof parsed.metadata === 'object') {\n              toolMetadata = {} as Record<string, unknown>;\n              for (const [k, v] of Object.entries(parsed.metadata as Record<string, unknown>)) {\n                toolMetadata[k] = typeof v === 'string' ? v : JSON.stringify(v);\n              }\n              if (!('output' in toolMetadata)) {\n                toolMetadata.output = toolOutput;\n              }\n            }\n          } else if (Array.isArray(parsed)) {\n            toolOutput = JSON.stringify(parsed);\n            toolMetadata = { output: toolOutput };\n          }\n        } catch {\n          // result is plain text, use as-is\n        }\n\n        if (result.error) {\n          let errorText: string;\n          if (typeof result.error === 'string') {\n            errorText = result.error;\n          } else if (result.error && typeof result.error === 'object') {\n            errorText = JSON.stringify(result.error);\n          } else {\n            errorText = String(result.error);\n          }\n          const errorOutput = toolOutput || errorText;\n          safeEnqueue({\n            type: 'tool-result',\n            toolCallId: requestID,\n            toolName,\n            result: {\n              output: errorOutput,\n              title: toolTitle,\n              metadata: { ...toolMetadata, error: errorText },\n            },\n            isError: true,\n            providerExecuted: true,\n          });\n        } else {\n          safeEnqueue({\n            type: 'tool-result',\n            toolCallId: requestID,\n            toolName,\n            result: {\n              output: toolOutput,\n              title: toolTitle,\n              metadata: toolMetadata,\n            },\n            isError: false,\n            providerExecuted: true,\n          });\n        }\n      } else {\n        const errorMsg = `Tool executor not configured for tool: ${toolName}`;\n        wsClient.sendActionResponse(requestID, '', errorMsg);\n\n        safeEnqueue({\n          type: 'tool-result',\n          toolCallId: requestID,\n          toolName,\n          result: {\n            output: errorMsg,\n            title: `${toolName} error`,\n            metadata: { output: errorMsg },\n          },\n          isError: true,\n          providerExecuted: true,\n        });\n      }\n    } catch (error) {\n      const rawMsg = error instanceof Error ? error.message : String(error);\n      const errorMsg = sanitizeErrorMessage(rawMsg);\n      wsClient.sendActionResponse(requestID, '', errorMsg);\n\n      safeEnqueue({\n        type: 'tool-result',\n        toolCallId: requestID,\n        toolName,\n        result: {\n          output: errorMsg,\n          title: `${toolName} error`,\n          metadata: { output: errorMsg },\n        },\n        isError: true,\n        providerExecuted: true,\n      });\n    } finally {\n      ss.pendingToolCount--;\n\n      if (this.onUsageUpdate) {\n        try {\n          this.onUsageUpdate({\n            inputTokens: Math.ceil(ss.streamedInputChars / 4),\n            outputTokens: Math.ceil(ss.streamedOutputChars / 4),\n          });\n        } catch {\n          // ignore callback errors\n        }\n      }\n\n      if (ss.pendingToolCount <= 0 && ss.deferredClose) {\n        const close = ss.deferredClose;\n        ss.deferredClose = null;\n        close();\n      }\n    }\n  }\n\n  private cleanupClient(ss: StreamState, clearWorkflow = false): void {\n    if (ss.activeClient) {\n      ss.activeClient.close();\n      this.activeClients.delete(ss.activeClient);\n      ss.activeClient = null;\n    }\n    if (clearWorkflow) {\n      this.currentWorkflowId = null;\n      this.persistedAgentEmitted.clear();\n    }\n  }\n\n  // ---------------------------------------------------------------------------\n  // Workflow metadata\n  // ---------------------------------------------------------------------------\n\n  private async buildWorkflowMetadata(): Promise<Record<string, unknown>> {\n    const metadata: Record<string, unknown> = {\n      extended_logging: false,\n    };\n\n    try {\n      const workDir = this.workflowOptions.workingDirectory ?? process.cwd();\n      const gitInfo = await this.getGitInfo(workDir);\n      if (gitInfo.url) metadata.git_url = gitInfo.url;\n      if (gitInfo.sha) metadata.git_sha = gitInfo.sha;\n      if (gitInfo.branch) metadata.git_branch = gitInfo.branch;\n    } catch {\n      // Git info is best-effort\n    }\n\n    return metadata;\n  }\n\n  private async getGitInfo(\n    workDir: string\n  ): Promise<{ url?: string; sha?: string; branch?: string }> {\n    const { execFile } = await import('child_process');\n    const { promisify } = await import('util');\n    const execFileAsync = promisify(execFile);\n    const opts = { cwd: workDir, timeout: 3000 };\n\n    const run = async (cmd: string, args: string[]): Promise<string | undefined> => {\n      try {\n        const { stdout } = await execFileAsync(cmd, args, opts);\n        return stdout.trim() || undefined;\n      } catch {\n        return undefined;\n      }\n    };\n\n    const [url, sha, branch] = await Promise.all([\n      run('git', ['remote', 'get-url', 'origin']),\n      run('git', ['rev-parse', 'HEAD']),\n      run('git', ['rev-parse', '--abbrev-ref', 'HEAD']),\n    ]);\n\n    return { url, sha, branch };\n  }\n\n  // ---------------------------------------------------------------------------\n  // Prompt / tool extraction helpers\n  // ---------------------------------------------------------------------------\n\n  /**\n   * Extract the user's goal (last user message) from the AI SDK prompt.\n   */\n  private extractGoalFromPrompt(prompt: LanguageModelV2Message[]): string {\n    for (let i = prompt.length - 1; i >= 0; i--) {\n      const message = prompt[i];\n      if (message.role === 'user') {\n        const textParts = message.content\n          .filter((part) => part.type === 'text')\n          .map((part) => (part as { type: 'text'; text: string }).text);\n        if (textParts.length > 0) {\n          return textParts.join('\\n');\n        }\n      }\n    }\n    return '';\n  }\n\n  /**\n   * Convert AI SDK tools to DWS McpToolDefinition format.\n   */\n  private extractMcpTools(options: LanguageModelV2CallOptions): McpToolDefinition[] {\n    if (this.workflowOptions.mcpTools && this.workflowOptions.mcpTools.length > 0) {\n      return this.workflowOptions.mcpTools;\n    }\n\n    if (!options.tools || options.tools.length === 0) {\n      return [];\n    }\n\n    return options.tools\n      .filter((tool): tool is LanguageModelV2FunctionTool => tool.type === 'function')\n      .map((tool) => ({\n        name: tool.name,\n        description: tool.description || '',\n        inputSchema: JSON.stringify(tool.inputSchema || { type: 'object', properties: {} }),\n      }));\n  }\n\n  // ---------------------------------------------------------------------------\n  // Payload size management\n  // ---------------------------------------------------------------------------\n\n  private static readonly MAX_START_REQUEST_BYTES = 4 * 1024 * 1024;\n\n  /**\n   * Trim mcpTools and additionalContext to fit within the DWS 4MB gRPC\n   * message size limit (`MAX_MESSAGE_SIZE` in duo_workflow_service/server.py).\n   *\n   * DWS has no per-field limits on tool descriptions, schemas, or context items.\n   * The only hard constraint is the total serialized message size.\n   *\n   * Strategy (progressive, only if over budget):\n   * 1. Send everything as-is\n   * 2. Simplify tool input schemas (strip descriptions from properties)\n   * 3. Strip schemas to minimal form (type + property names only)\n   * 4. Drop tools from the end until it fits\n   */\n  private trimPayload(\n    mcpTools: McpToolDefinition[],\n    additionalContext: AdditionalContext[],\n    basePayloadSize: number\n  ): { mcpTools: McpToolDefinition[]; additionalContext: AdditionalContext[] } {\n    const budget = GitLabWorkflowLanguageModel.MAX_START_REQUEST_BYTES - basePayloadSize;\n    const contextJson = JSON.stringify(additionalContext);\n\n    const toolsJson = JSON.stringify(mcpTools);\n    const totalSize = toolsJson.length + contextJson.length;\n\n    if (totalSize <= budget) {\n      return { mcpTools, additionalContext };\n    }\n\n    const simplifiedTools = mcpTools.map((tool) => ({\n      name: tool.name,\n      description: tool.description,\n      inputSchema: simplifySchema(tool.inputSchema),\n    }));\n\n    const simpSize = JSON.stringify(simplifiedTools).length + contextJson.length;\n    if (simpSize <= budget) {\n      return { mcpTools: simplifiedTools, additionalContext };\n    }\n\n    const minTools = simplifiedTools.map((tool) => ({\n      name: tool.name,\n      description: tool.description,\n      inputSchema: minimalSchema(tool.inputSchema),\n    }));\n\n    const minSize = JSON.stringify(minTools).length + contextJson.length;\n    if (minSize <= budget) {\n      return { mcpTools: minTools, additionalContext };\n    }\n\n    const keptTools = [...minTools];\n    while (keptTools.length > 0) {\n      const currentSize = JSON.stringify(keptTools).length + contextJson.length;\n      if (currentSize <= budget) break;\n      keptTools.pop();\n    }\n\n    return { mcpTools: keptTools, additionalContext };\n  }\n\n  private buildAdditionalContext(prompt: LanguageModelV2Message[]): AdditionalContext[] {\n    const context: AdditionalContext[] = [];\n\n    if (this.workflowOptions.additionalContext) {\n      context.push(...this.workflowOptions.additionalContext);\n    }\n\n    for (const message of prompt) {\n      if (message.role === 'system') {\n        context.push({\n          category: 'system_prompt',\n          content: message.content,\n          metadata: JSON.stringify({ role: 'system' }),\n        });\n      } else if (message.role === 'assistant') {\n        const textContent = message.content\n          .filter((part) => part.type === 'text')\n          .map((part) => (part as { type: 'text'; text: string }).text)\n          .join('\\n');\n        if (textContent) {\n          context.push({\n            category: 'conversation',\n            content: textContent,\n            metadata: JSON.stringify({ role: 'assistant' }),\n          });\n        }\n      }\n    }\n\n    return context;\n  }\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  /** @deprecated Use enterpriseUrl instead. Kept for backwards compatibility with older auth.json files. */\n  instanceUrl?: string;\n  /** Instance URL as written by opencode-gitlab-auth plugin (e.g. 'https://gitlab.com') */\n  enterpriseUrl?: string;\n}\n\nexport interface OpenCodeAuthApi {\n  type: 'api';\n  key: string;\n}\n\nexport type OpenCodeAuth = OpenCodeAuthOAuth | OpenCodeAuthApi;\n\n/**\n * Default OAuth client ID for GitLab.com\n * This is the same client ID used by opencode-gitlab-auth plugin.\n * The GITLAB_OAUTH_CLIENT_ID env var takes precedence if set.\n * Note: VS Code extension uses a different client ID ('36f2a70c...') but we use the opencode plugin's ID\n * to ensure token refresh works correctly with tokens created by the auth plugin.\n */\nexport const OPENCODE_GITLAB_AUTH_CLIENT_ID =\n  '1d89f9fdb23ee96d4e603201f6861dab6e143c5c3c00469a018a2d94bdc03d4e';\n\n/**\n * @deprecated Use OPENCODE_GITLAB_AUTH_CLIENT_ID instead. This is the VS Code extension's client ID\n * and will cause refresh failures if used with tokens created by opencode-gitlab-auth.\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  OPENCODE_GITLAB_AUTH_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   * Priority: env var > opencode-gitlab-auth default (for GitLab.com).\n   * Note: callers (e.g. exchangeRefreshToken) may pass an explicit clientId\n   * that bypasses this method entirely.\n   */\n  private getClientId(instanceUrl: string): string {\n    // Priority 1: Environment variable (allows overriding at runtime)\n    const envClientId = process.env['GITLAB_OAUTH_CLIENT_ID'];\n    if (envClientId) {\n      return envClientId;\n    }\n\n    // Priority 2: Use opencode-gitlab-auth's client ID for GitLab.com\n    // This ensures refresh works with tokens created by the auth plugin\n    if (instanceUrl === GITLAB_COM_URL) {\n      return OPENCODE_GITLAB_AUTH_CLIENT_ID;\n    }\n\n    throw new GitLabError({\n      message: `No OAuth client ID configured for instance ${instanceUrl}. Please provide a clientId parameter or set GITLAB_OAUTH_CLIENT_ID environment variable.`,\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","import { GitLabAnthropicLanguageModel } from './gitlab-anthropic-language-model';\nimport { GitLabOpenAILanguageModel } from './gitlab-openai-language-model';\nimport { GitLabWorkflowLanguageModel } from './gitlab-workflow-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, isWorkflowModel } from './model-mappings';\nimport type { GitLabWorkflowOptions } from './gitlab-workflow-types';\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  /**\n   * Create a workflow chat model using GitLab Duo Agent Platform.\n   *\n   * Workflow models use a server-side agentic loop where GitLab's DWS drives\n   * the LLM, requests tool executions from the client via WebSocket, and\n   * streams text/status back.\n   *\n   * Requires GitLab Ultimate with Duo Enterprise add-on.\n   *\n   * @param modelId - Workflow model identifier (e.g., 'duo-workflow-sonnet-4-6')\n   * @param options - Workflow-specific configuration\n   * @returns A language model backed by the DWS WebSocket protocol\n   *\n   * @example\n   * const model = gitlab.workflowChat('duo-workflow-sonnet-4-6', {\n   *   mcpTools: [...],\n   *   preapprovedTools: ['read_file', 'write_file'],\n   * });\n   */\n  workflowChat(modelId: string, options?: GitLabWorkflowOptions): GitLabWorkflowLanguageModel;\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-6'\n   * - 'claude-sonnet-4-6'\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   * Can also be set via GITLAB_INSTANCE_URL environment variable.\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    throw new Error(`Failed to load auth.json: ${error instanceof Error ? error.message : error}`);\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 under 'gitlab' key (same format as opencode-gitlab-auth plugin)\n        const authPath = getOpenCodeAuthPath();\n        const authData = JSON.parse(fs.readFileSync(authPath, 'utf-8'));\n\n        authData.gitlab = {\n          type: 'oauth',\n          refresh: refreshed.refreshToken,\n          access: refreshed.accessToken,\n          expires: refreshed.expiresAt,\n          enterpriseUrl: instanceUrl, // Use enterpriseUrl to match auth plugin format\n        };\n\n        fs.writeFileSync(authPath, JSON.stringify(authData, null, 2), { mode: 0o600 });\n\n        return refreshed.accessToken;\n      } catch (error) {\n        // If refresh fails, fall through to env var but remember the error\n        const refreshErrorMsg = error instanceof Error ? error.message : String(error);\n        // Silently handle refresh failure — avoid stdout output that interferes with TUI\n\n        // Priority 3: Environment variable (fallback when refresh fails)\n        const envApiKey = process.env[options.environmentVariableName];\n        if (envApiKey) {\n          return envApiKey;\n        }\n\n        // No env var fallback — throw with the refresh failure context\n        throw new GitLabError({\n          message:\n            `OAuth token refresh failed and no fallback ${options.environmentVariableName} environment variable is set. ` +\n            `Refresh error: ${refreshErrorMsg}. ` +\n            `Re-authenticate with 'opencode auth login gitlab' or set ${options.environmentVariableName}.`,\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 =\n    options.instanceUrl ?? process.env['GITLAB_INSTANCE_URL'] ?? '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, but don't pass the stale options.apiKey\n    // This forces loadApiKey to read from auth.json and potentially refresh the OAuth token\n    cachedApiKey = await loadApiKey(\n      {\n        apiKey: undefined, // Bypass stale options.apiKey to force auth.json read\n        environmentVariableName: 'GITLAB_TOKEN',\n        description: 'GitLab',\n      },\n      instanceUrl,\n      options.clientId\n    );\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  const createWorkflowChatModel = (\n    modelId: string,\n    workflowOptions?: GitLabWorkflowOptions\n  ): GitLabWorkflowLanguageModel => {\n    const mapping = getModelMapping(modelId);\n\n    if (!mapping || mapping.provider !== 'workflow') {\n      throw new GitLabError({\n        message: `Unknown workflow model ID: ${modelId}. Use 'duo-workflow' or a 'duo-workflow-*' model ID.`,\n      });\n    }\n\n    return new GitLabWorkflowLanguageModel(\n      modelId,\n      {\n        provider: `${providerName}.workflow`,\n        instanceUrl,\n        getHeaders,\n        refreshApiKey,\n        fetch: options.fetch,\n        featureFlags: {\n          ...options.featureFlags,\n          ...workflowOptions?.featureFlags,\n        },\n        aiGatewayUrl: options.aiGatewayUrl,\n      },\n      workflowOptions\n    );\n  };\n\n  // Default model factory - uses Anthropic backend for tool support\n  const createDefaultModel = (modelId: string): LanguageModelV2 => {\n    // Route workflow models to the workflow backend\n    if (isWorkflowModel(modelId)) {\n      return createWorkflowChatModel(modelId);\n    }\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    workflowChat: createWorkflowChatModel,\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"],"mappings":"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","names":["resolve","hasToolCalls","WorkflowType","resolve","resolve","path","fs","path","os"]}