| 67 | * and non-streaming prompt completion. |
| 68 | */ |
| 69 | export class OpencodeGoHandler extends RouterProvider implements SingleCompletionHandler { |
| 70 | /** |
| 71 | * Anthropic SDK client used for Go models that only accept the Anthropic |
| 72 | * Messages wire format (`/v1/messages`). |
| 73 | * |
| 74 | * The SDK appends `/v1/messages` to `baseURL`, so this is set to the Go |
| 75 | * gateway root (`https://opencode.ai/zen/go`) — NOT the `/v1` root used by |
| 76 | * the OpenAI client — to avoid a doubled `/v1` path segment. |
| 77 | */ |
| 78 | private readonly anthropicClient: Anthropic |
| 79 | |
| 80 | /** Creates a new handler bound to the user's Go API key and selected model. */ |
| 81 | constructor(options: ApiHandlerOptions) { |
| 82 | super({ |
| 83 | options, |
| 84 | name: "opencode-go", |
| 85 | baseURL: "https://opencode.ai/zen/go/v1", |
| 86 | apiKey: options.opencodeGoApiKey, |
| 87 | modelId: options.opencodeGoModelId, |
| 88 | defaultModelId: opencodeGoDefaultModelId, |
| 89 | defaultModelInfo: opencodeGoDefaultModelInfo, |
| 90 | }) |
| 91 | |
| 92 | this.anthropicClient = new Anthropic({ |
| 93 | baseURL: "https://opencode.ai/zen/go", |
| 94 | apiKey: options.opencodeGoApiKey, |
| 95 | defaultHeaders: { |
| 96 | ...DEFAULT_HEADERS, |
| 97 | ...(options.openAiHeaders || {}), |
| 98 | }, |
| 99 | }) |
| 100 | } |
| 101 | |
| 102 | /** |
| 103 | * Resolves the configured model and computes model parameters |
| 104 | * (max tokens, temperature, reasoning effort) from the merged model info. |
| 105 | * |
| 106 | * The wire format is derived from the model ID via |
| 107 | * {@link isOpencodeGoAnthropicFormatModel}: Anthropic-format models compute |
| 108 | * parameters with the `anthropic` format so reasoning is mapped to the |
| 109 | * Anthropic-style controls; everything else uses the `openai` format. |
| 110 | * |
| 111 | * Fetches the live model list first so the merged native + `/models` |
| 112 | * metadata (context window, capability flags, pricing) is available before |
| 113 | * parameter computation — mirroring the original `fetchModel()` flow. |
| 114 | */ |
| 115 | private async resolveModel() { |
| 116 | const { id, info } = await this.fetchModel() |
| 117 | const isAnthropic = isOpencodeGoAnthropicFormatModel(id) |
| 118 | // getModelParams is overloaded on a literal `format`, so branch the call |
| 119 | // rather than passing a union — this keeps the returned params typed as a |
| 120 | // single concrete shape per branch. |
| 121 | const params = isAnthropic |
| 122 | ? getModelParams({ |
| 123 | format: "anthropic", |
| 124 | modelId: id, |
| 125 | model: info, |
| 126 | settings: this.options, |
nothing calls this directly
no outgoing calls
no test coverage detected