diff options
Diffstat (limited to 'src/config_file.zig')
| -rw-r--r-- | src/config_file.zig | 35 |
1 files changed, 33 insertions, 2 deletions
diff --git a/src/config_file.zig b/src/config_file.zig index 8f6725c..a70a832 100644 --- a/src/config_file.zig +++ b/src/config_file.zig @@ -35,8 +35,10 @@ //! currently resolved. An `anthropic_messages` provider may also set //! `prompt_cache = <bool>` (default true) to control the advancing //! `cache_control` breakpoint; it is ignored for `openai_chat` -//! providers. `extra_headers` (a table of string headers) rides on the -//! model request. +//! providers. `model_catalog_name = <string>` optionally maps the +//! provider to an external model catalog key (sync tooling otherwise +//! falls back to the provider name). `extra_headers` (a table of string +//! headers) rides on the model request. //! - `defaults.model` is parsed as `<provider_name>:<model_alias>`. //! - `tools` / `extensions` allow- and deny-lists are captured verbatim //! (as glob pattern lists). A pattern appearing in both allow and deny @@ -84,6 +86,9 @@ pub const Provider = struct { base_url: []const u8, /// The `auth.<name>` session this provider draws its credential from. auth_name: []const u8, + /// Optional external model-catalog provider key (e.g. `github-copilot` + /// on models.dev). Absent => sync tooling falls back to `name`. + model_catalog_name: ?[]const u8 = null, /// anthropic_messages only. Place one advancing `cache_control` /// breakpoint on each request. Defaults to the library default (true); /// ignored for `openai_chat` providers. @@ -97,6 +102,7 @@ pub const Provider = struct { if (self.dialect) |d| alloc.free(d); alloc.free(self.base_url); alloc.free(self.auth_name); + if (self.model_catalog_name) |m| alloc.free(m); // `extra_headers` lives in the Config auth arena; not freed here. } }; @@ -708,6 +714,8 @@ fn resolveProvider( const auth_name = (val.get("auth") orelse return error.MissingProviderAuth).asString() orelse return error.MissingProviderAuth; + const model_catalog_name = tomlStr(val, "model_catalog_name"); + // anthropic_messages only; absent => library default (true). const prompt_cache: bool = blk: { if (val.get("prompt_cache")) |pc| { @@ -724,6 +732,7 @@ fn resolveProvider( .dialect = if (dialect) |d| try allocator.dupe(u8, d) else null, .base_url = try allocator.dupe(u8, base_url), .auth_name = try allocator.dupe(u8, auth_name), + .model_catalog_name = if (model_catalog_name) |m| try allocator.dupe(u8, m) else null, .prompt_cache = prompt_cache, .extra_headers = extra_headers, }; @@ -1254,6 +1263,28 @@ test "resolve: provider extra_headers flow into the built provider config" { try testing.expectEqualStrings("tok", pc.openai_chat.api_key); } +test "resolve: provider model_catalog_name is captured" { + const a = testing.allocator; + var env = emptyEnv(a); + defer env.deinit(); + const src = + \\[providers.copilot] + \\style = "openai_chat" + \\base_url = "https://api.individual.githubcopilot.com" + \\auth = "k" + \\model_catalog_name = "github-copilot" + \\ + \\[auth.k] + \\key = "tok" + ; + const doc = try parseDoc(a, src); + defer doc.deinit(); + var cfg = try resolve(a, &env, doc.root); + defer cfg.deinit(); + + try testing.expectEqualStrings("github-copilot", cfg.provider("copilot").?.model_catalog_name.?); +} + test "resolve: openai_responses codex dialect maps to internal API style" { const a = testing.allocator; var env = emptyEnv(a); |
