llm-provider.wit

  1interface llm-provider {
  2    use http-client.{http-request, http-response-with-status};
  3
  4    /// Information about a language model provider.
  5    record provider-info {
  6        /// Unique identifier for the provider (e.g. "my-extension.my-provider").
  7        id: string,
  8        /// Display name for the provider.
  9        name: string,
 10        /// Path to an SVG icon file relative to the extension root (e.g. "icons/provider.svg").
 11        icon: option<string>,
 12    }
 13
 14    /// Capabilities of a language model.
 15    record model-capabilities {
 16        /// Whether the model supports image inputs.
 17        supports-images: bool,
 18        /// Whether the model supports tool/function calling.
 19        supports-tools: bool,
 20        /// Whether the model supports the "auto" tool choice.
 21        supports-tool-choice-auto: bool,
 22        /// Whether the model supports the "any" tool choice.
 23        supports-tool-choice-any: bool,
 24        /// Whether the model supports the "none" tool choice.
 25        supports-tool-choice-none: bool,
 26        /// Whether the model supports extended thinking/reasoning.
 27        supports-thinking: bool,
 28        /// The format for tool input schemas.
 29        tool-input-format: tool-input-format,
 30    }
 31
 32    /// Format for tool input schemas.
 33    enum tool-input-format {
 34        /// Standard JSON Schema format.
 35        json-schema,
 36        /// A subset of JSON Schema supported by Google AI.
 37        /// See https://ai.google.dev/api/caching#Schema
 38        json-schema-subset,
 39        /// Simplified schema format for certain providers.
 40        simplified,
 41    }
 42
 43    /// Information about a specific model.
 44    record model-info {
 45        /// Unique identifier for the model.
 46        id: string,
 47        /// Display name for the model.
 48        name: string,
 49        /// Maximum input token count.
 50        max-token-count: u64,
 51        /// Maximum output tokens (optional).
 52        max-output-tokens: option<u64>,
 53        /// Model capabilities.
 54        capabilities: model-capabilities,
 55        /// Whether this is the default model for the provider.
 56        is-default: bool,
 57        /// Whether this is the default fast model.
 58        is-default-fast: bool,
 59    }
 60
 61    /// The role of a message participant.
 62    enum message-role {
 63        /// User message.
 64        user,
 65        /// Assistant message.
 66        assistant,
 67        /// System message.
 68        system,
 69    }
 70
 71    /// A message in a completion request.
 72    record request-message {
 73        /// The role of the message sender.
 74        role: message-role,
 75        /// The content of the message.
 76        content: list<message-content>,
 77        /// Whether to cache this message for prompt caching.
 78        cache: bool,
 79    }
 80
 81    /// Content within a message.
 82    variant message-content {
 83        /// Plain text content.
 84        text(string),
 85        /// Image content.
 86        image(image-data),
 87        /// A tool use request from the assistant.
 88        tool-use(tool-use),
 89        /// A tool result from the user.
 90        tool-result(tool-result),
 91        /// Thinking/reasoning content.
 92        thinking(thinking-content),
 93        /// Redacted/encrypted thinking content.
 94        redacted-thinking(string),
 95    }
 96
 97    /// Image data for vision models.
 98    record image-data {
 99        /// Base64-encoded image data.
100        source: string,
101        /// Image width in pixels (optional).
102        width: option<u32>,
103        /// Image height in pixels (optional).
104        height: option<u32>,
105    }
106
107    /// A tool use request from the model.
108    record tool-use {
109        /// Unique identifier for this tool use.
110        id: string,
111        /// The name of the tool being used.
112        name: string,
113        /// JSON string of the tool input arguments.
114        input: string,
115        /// Whether the input JSON is complete (false while streaming, true when done).
116        is-input-complete: bool,
117        /// Thought signature for providers that support it (e.g., Anthropic).
118        thought-signature: option<string>,
119    }
120
121    /// A tool result to send back to the model.
122    record tool-result {
123        /// The ID of the tool use this is a result for.
124        tool-use-id: string,
125        /// The name of the tool.
126        tool-name: string,
127        /// Whether this result represents an error.
128        is-error: bool,
129        /// The content of the result.
130        content: tool-result-content,
131    }
132
133    /// Content of a tool result.
134    variant tool-result-content {
135        /// Text result.
136        text(string),
137        /// Image result.
138        image(image-data),
139    }
140
141    /// Thinking/reasoning content from models that support extended thinking.
142    record thinking-content {
143        /// The thinking text.
144        text: string,
145        /// Signature for the thinking block (provider-specific).
146        signature: option<string>,
147    }
148
149    /// A tool definition for function calling.
150    record tool-definition {
151        /// The name of the tool.
152        name: string,
153        /// Description of what the tool does.
154        description: string,
155        /// JSON Schema for input parameters.
156        input-schema: string,
157    }
158
159    /// Tool choice preference for the model.
160    enum tool-choice {
161        /// Let the model decide whether to use tools.
162        auto,
163        /// Force the model to use at least one tool.
164        any,
165        /// Prevent the model from using tools.
166        none,
167    }
168
169    /// A completion request to send to the model.
170    record completion-request {
171        /// The messages in the conversation.
172        messages: list<request-message>,
173        /// Available tools for the model to use.
174        tools: list<tool-definition>,
175        /// Tool choice preference.
176        tool-choice: option<tool-choice>,
177        /// Stop sequences to end generation.
178        stop-sequences: list<string>,
179        /// Temperature for sampling (0.0-1.0).
180        temperature: option<f32>,
181        /// Whether thinking/reasoning is allowed.
182        thinking-allowed: bool,
183        /// Maximum tokens to generate.
184        max-tokens: option<u64>,
185    }
186
187    /// Events emitted during completion streaming.
188    variant completion-event {
189        /// Completion has started.
190        started,
191        /// Text content chunk.
192        text(string),
193        /// Thinking/reasoning content chunk.
194        thinking(thinking-content),
195        /// Redacted thinking (encrypted) chunk.
196        redacted-thinking(string),
197        /// Tool use request from the model.
198        tool-use(tool-use),
199        /// JSON parse error when parsing tool input.
200        tool-use-json-parse-error(tool-use-json-parse-error),
201        /// Completion stopped.
202        stop(stop-reason),
203        /// Token usage update.
204        usage(token-usage),
205        /// Reasoning details (provider-specific JSON).
206        reasoning-details(string),
207    }
208
209    /// Error information when tool use JSON parsing fails.
210    record tool-use-json-parse-error {
211        /// The tool use ID.
212        id: string,
213        /// The tool name.
214        tool-name: string,
215        /// The raw input that failed to parse.
216        raw-input: string,
217        /// The parse error message.
218        error: string,
219    }
220
221    /// Reason the completion stopped.
222    enum stop-reason {
223        /// The model finished generating.
224        end-turn,
225        /// Maximum tokens reached.
226        max-tokens,
227        /// The model wants to use a tool.
228        tool-use,
229        /// The model refused to respond.
230        refusal,
231    }
232
233    /// Token usage statistics.
234    record token-usage {
235        /// Number of input tokens used.
236        input-tokens: u64,
237        /// Number of output tokens generated.
238        output-tokens: u64,
239        /// Tokens used for cache creation (if supported).
240        cache-creation-input-tokens: option<u64>,
241        /// Tokens read from cache (if supported).
242        cache-read-input-tokens: option<u64>,
243    }
244
245    /// Cache configuration for prompt caching.
246    record cache-configuration {
247        /// Maximum number of cache anchors.
248        max-cache-anchors: u32,
249        /// Whether caching should be applied to tool definitions.
250        should-cache-tool-definitions: bool,
251        /// Minimum token count for a message to be cached.
252        min-total-token-count: u64,
253    }
254
255    /// Configuration for starting an OAuth web authentication flow.
256    record oauth-web-auth-config {
257        /// The URL to open in the user's browser to start authentication.
258        /// This should include client_id, redirect_uri, scope, state, etc.
259        /// Use `{port}` as a placeholder in the URL - it will be replaced with
260        /// the actual localhost port before opening the browser.
261        /// Example: "https://example.com/oauth?redirect_uri=http://127.0.0.1:{port}/callback"
262        auth-url: string,
263        /// The path to listen on for the OAuth callback (e.g., "/callback").
264        /// A localhost server will be started to receive the redirect.
265        callback-path: string,
266        /// Timeout in seconds to wait for the callback (default: 300 = 5 minutes).
267        timeout-secs: option<u32>,
268    }
269
270    /// Result of an OAuth web authentication flow.
271    record oauth-web-auth-result {
272        /// The full callback URL that was received, including query parameters.
273        /// The extension is responsible for parsing the code, state, etc.
274        callback-url: string,
275        /// The port that was used for the localhost callback server.
276        port: u32,
277    }
278
279    /// Get a stored credential for this provider.
280    get-credential: func(provider-id: string) -> option<string>;
281
282    /// Store a credential for this provider.
283    store-credential: func(provider-id: string, value: string) -> result<_, string>;
284
285    /// Delete a stored credential for this provider.
286    delete-credential: func(provider-id: string) -> result<_, string>;
287
288    /// Read an environment variable.
289    get-env-var: func(name: string) -> option<string>;
290
291    /// Start an OAuth web authentication flow.
292    ///
293    /// This will:
294    /// 1. Start a localhost server to receive the OAuth callback
295    /// 2. Open the auth URL in the user's default browser
296    /// 3. Wait for the callback (up to the timeout)
297    /// 4. Return the callback URL with query parameters
298    ///
299    /// The extension is responsible for:
300    /// - Constructing the auth URL with client_id, redirect_uri, scope, state, etc.
301    /// - Parsing the callback URL to extract the authorization code
302    /// - Exchanging the code for tokens using fetch-fallible from http-client
303    oauth-start-web-auth: func(config: oauth-web-auth-config) -> result<oauth-web-auth-result, string>;
304
305    /// Make an HTTP request for OAuth token exchange.
306    ///
307    /// This is a convenience wrapper around http-client's fetch-fallible for OAuth flows.
308    /// Unlike the standard fetch, this does not treat non-2xx responses as errors,
309    /// allowing proper handling of OAuth error responses.
310    oauth-send-http-request: func(request: http-request) -> result<http-response-with-status, string>;
311
312    /// Open a URL in the user's default browser.
313    ///
314    /// Useful for OAuth flows that need to open a browser but handle the
315    /// callback differently (e.g., polling-based flows).
316    oauth-open-browser: func(url: string) -> result<_, string>;
317
318    /// Provider settings from user configuration.
319    /// Extensions can use this to allow custom API URLs, custom models, etc.
320    record provider-settings {
321        /// Custom API URL override (if configured by the user).
322        api-url: option<string>,
323        /// Custom models configured by the user.
324        available-models: list<custom-model-config>,
325    }
326
327    /// Configuration for a custom model defined by the user.
328    record custom-model-config {
329        /// The model's API identifier.
330        name: string,
331        /// Display name for the UI.
332        display-name: option<string>,
333        /// Maximum input token count.
334        max-tokens: u64,
335        /// Maximum output tokens (optional).
336        max-output-tokens: option<u64>,
337        /// Thinking budget for models that support extended thinking (None = auto).
338        thinking-budget: option<u32>,
339    }
340
341    /// Get provider-specific settings configured by the user.
342    /// Returns settings like custom API URLs and custom model configurations.
343    get-provider-settings: func(provider-id: string) -> option<provider-settings>;
344
345    /// Information needed to display the device flow prompt modal to the user.
346    record device-flow-prompt-info {
347        /// The user code to display (e.g., "ABC-123").
348        user-code: string,
349        /// The URL the user needs to visit to authorize (for the "Connect" button).
350        verification-url: string,
351        /// The headline text for the modal (e.g., "Use GitHub Copilot in Zed.").
352        headline: string,
353        /// A description to show below the headline (e.g., "Using Copilot requires an active subscription on GitHub.").
354        description: string,
355        /// Label for the connect button (e.g., "Connect to GitHub").
356        connect-button-label: string,
357        /// Success headline shown when authorization completes.
358        success-headline: string,
359        /// Success message shown when authorization completes.
360        success-message: string,
361    }
362}