From f2761cf28ee62d421a6baa9d935a16269c71a72c Mon Sep 17 00:00:00 2001 From: Mark Davison <6168730+markdavison@users.noreply.github.com> Date: Tue, 11 Aug 2026 17:50:14 +0100 Subject: [PATCH 1/9] Add gm provider with frontier model catalog --- providers/gm/logo.svg | 4 ++++ providers/gm/models/claude-fable-5.toml | 11 +++++++++++ providers/gm/models/claude-haiku-4-5.toml | 11 +++++++++++ providers/gm/models/claude-opus-4-7.toml | 11 +++++++++++ providers/gm/models/claude-opus-4-8.toml | 11 +++++++++++ providers/gm/models/claude-opus-5.toml | 11 +++++++++++ providers/gm/models/claude-sonnet-4-6.toml | 15 +++++++++++++++ providers/gm/models/claude-sonnet-5.toml | 16 ++++++++++++++++ providers/gm/models/gemini-2.5-flash-lite.toml | 16 ++++++++++++++++ providers/gm/models/gemini-2.5-flash.toml | 16 ++++++++++++++++ providers/gm/models/gemini-2.5-pro.toml | 12 ++++++++++++ providers/gm/models/gemini-3.1-pro-preview.toml | 11 +++++++++++ providers/gm/models/gemini-3.5-flash.toml | 11 +++++++++++ providers/gm/models/gpt-5.4-mini.toml | 11 +++++++++++ providers/gm/models/gpt-5.4-nano.toml | 11 +++++++++++ providers/gm/models/gpt-5.4.toml | 11 +++++++++++ providers/gm/models/gpt-5.5-pro.toml | 11 +++++++++++ providers/gm/models/gpt-5.5.toml | 11 +++++++++++ providers/gm/models/gpt-5.6-luna.toml | 11 +++++++++++ providers/gm/models/gpt-5.6-sol.toml | 11 +++++++++++ providers/gm/models/gpt-5.6-terra.toml | 11 +++++++++++ providers/gm/models/gpt-5.6.toml | 12 ++++++++++++ providers/gm/models/o3.toml | 11 +++++++++++ providers/gm/models/o4-mini.toml | 11 +++++++++++ providers/gm/provider.toml | 5 +++++ 25 files changed, 283 insertions(+) create mode 100644 providers/gm/logo.svg create mode 100644 providers/gm/models/claude-fable-5.toml create mode 100644 providers/gm/models/claude-haiku-4-5.toml create mode 100644 providers/gm/models/claude-opus-4-7.toml create mode 100644 providers/gm/models/claude-opus-4-8.toml create mode 100644 providers/gm/models/claude-opus-5.toml create mode 100644 providers/gm/models/claude-sonnet-4-6.toml create mode 100644 providers/gm/models/claude-sonnet-5.toml create mode 100644 providers/gm/models/gemini-2.5-flash-lite.toml create mode 100644 providers/gm/models/gemini-2.5-flash.toml create mode 100644 providers/gm/models/gemini-2.5-pro.toml create mode 100644 providers/gm/models/gemini-3.1-pro-preview.toml create mode 100644 providers/gm/models/gemini-3.5-flash.toml create mode 100644 providers/gm/models/gpt-5.4-mini.toml create mode 100644 providers/gm/models/gpt-5.4-nano.toml create mode 100644 providers/gm/models/gpt-5.4.toml create mode 100644 providers/gm/models/gpt-5.5-pro.toml create mode 100644 providers/gm/models/gpt-5.5.toml create mode 100644 providers/gm/models/gpt-5.6-luna.toml create mode 100644 providers/gm/models/gpt-5.6-sol.toml create mode 100644 providers/gm/models/gpt-5.6-terra.toml create mode 100644 providers/gm/models/gpt-5.6.toml create mode 100644 providers/gm/models/o3.toml create mode 100644 providers/gm/models/o4-mini.toml create mode 100644 providers/gm/provider.toml diff --git a/providers/gm/logo.svg b/providers/gm/logo.svg new file mode 100644 index 00000000000..497f15af61b --- /dev/null +++ b/providers/gm/logo.svg @@ -0,0 +1,4 @@ + + + + diff --git a/providers/gm/models/claude-fable-5.toml b/providers/gm/models/claude-fable-5.toml new file mode 100644 index 00000000000..fee61c53146 --- /dev/null +++ b/providers/gm/models/claude-fable-5.toml @@ -0,0 +1,11 @@ +# Source: gm live /v1/models catalog 2026-08-07 (USD/MTok). +base_model = "anthropic/claude-fable-5" + +[[reasoning_options]] +type = "effort" +values = ["low", "medium", "high", "xhigh", "max"] + +[cost] +input = 10.00 +output = 50.00 +cache_read = 1.00 diff --git a/providers/gm/models/claude-haiku-4-5.toml b/providers/gm/models/claude-haiku-4-5.toml new file mode 100644 index 00000000000..80f540c6d0b --- /dev/null +++ b/providers/gm/models/claude-haiku-4-5.toml @@ -0,0 +1,11 @@ +# Source: gm live /v1/models catalog 2026-08-07 (USD/MTok). +base_model = "anthropic/claude-haiku-4-5" + +[[reasoning_options]] +type = "budget_tokens" +min = 1_024 + +[cost] +input = 1.00 +output = 5.00 +cache_read = 0.10 diff --git a/providers/gm/models/claude-opus-4-7.toml b/providers/gm/models/claude-opus-4-7.toml new file mode 100644 index 00000000000..21a5b0eb372 --- /dev/null +++ b/providers/gm/models/claude-opus-4-7.toml @@ -0,0 +1,11 @@ +# Source: gm live /v1/models catalog 2026-08-07 (USD/MTok). +base_model = "anthropic/claude-opus-4-7" + +[[reasoning_options]] +type = "effort" +values = ["low", "medium", "high", "xhigh", "max"] + +[cost] +input = 5.00 +output = 25.00 +cache_read = 0.50 diff --git a/providers/gm/models/claude-opus-4-8.toml b/providers/gm/models/claude-opus-4-8.toml new file mode 100644 index 00000000000..c758260b948 --- /dev/null +++ b/providers/gm/models/claude-opus-4-8.toml @@ -0,0 +1,11 @@ +# Source: gm live /v1/models catalog 2026-08-07 (USD/MTok). +base_model = "anthropic/claude-opus-4-8" + +[[reasoning_options]] +type = "effort" +values = ["low", "medium", "high", "xhigh", "max"] + +[cost] +input = 5.00 +output = 25.00 +cache_read = 0.50 diff --git a/providers/gm/models/claude-opus-5.toml b/providers/gm/models/claude-opus-5.toml new file mode 100644 index 00000000000..5e98c889b3d --- /dev/null +++ b/providers/gm/models/claude-opus-5.toml @@ -0,0 +1,11 @@ +# Source: gm live /v1/models catalog 2026-08-07 (USD/MTok). +base_model = "anthropic/claude-opus-5" + +[[reasoning_options]] +type = "effort" +values = ["low", "medium", "high", "xhigh", "max"] + +[cost] +input = 5.00 +output = 25.00 +cache_read = 0.50 diff --git a/providers/gm/models/claude-sonnet-4-6.toml b/providers/gm/models/claude-sonnet-4-6.toml new file mode 100644 index 00000000000..320fade3362 --- /dev/null +++ b/providers/gm/models/claude-sonnet-4-6.toml @@ -0,0 +1,15 @@ +# Source: gm live /v1/models catalog 2026-08-07 (USD/MTok). +base_model = "anthropic/claude-sonnet-4-6" + +[[reasoning_options]] +type = "effort" +values = ["low", "medium", "high", "max"] + +[[reasoning_options]] +type = "budget_tokens" +min = 1_024 + +[cost] +input = 3.00 +output = 10.00 +cache_read = 0.30 diff --git a/providers/gm/models/claude-sonnet-5.toml b/providers/gm/models/claude-sonnet-5.toml new file mode 100644 index 00000000000..4deb1ee0d84 --- /dev/null +++ b/providers/gm/models/claude-sonnet-5.toml @@ -0,0 +1,16 @@ +# Source: gm live /v1/models catalog 2026-08-07 (USD/MTok). +# Toggle: thinking.type = enabled|disabled (Anthropic Messages wire; gm mirrors upstream) +# Effort: output_config.effort = low|medium|high|xhigh|max +base_model = "anthropic/claude-sonnet-5" + +[[reasoning_options]] +type = "toggle" + +[[reasoning_options]] +type = "effort" +values = ["low", "medium", "high", "xhigh", "max"] + +[cost] +input = 3.00 +output = 10.00 +cache_read = 0.30 diff --git a/providers/gm/models/gemini-2.5-flash-lite.toml b/providers/gm/models/gemini-2.5-flash-lite.toml new file mode 100644 index 00000000000..e11dd55adea --- /dev/null +++ b/providers/gm/models/gemini-2.5-flash-lite.toml @@ -0,0 +1,16 @@ +# Source: gm live /v1/models catalog 2026-08-07 (USD/MTok). +# Toggle: thinking budget 0 disables thinking (Google thinkingConfig.thinkingBudget) +base_model = "google/gemini-2.5-flash-lite" + +[[reasoning_options]] +type = "toggle" + +[[reasoning_options]] +type = "budget_tokens" +min = 512 +max = 24_576 + +[cost] +input = 0.10 +output = 0.40 +cache_read = 0.01 diff --git a/providers/gm/models/gemini-2.5-flash.toml b/providers/gm/models/gemini-2.5-flash.toml new file mode 100644 index 00000000000..3f24c3b65ab --- /dev/null +++ b/providers/gm/models/gemini-2.5-flash.toml @@ -0,0 +1,16 @@ +# Source: gm live /v1/models catalog 2026-08-07 (USD/MTok). +# Toggle: thinking budget 0 disables thinking (Google thinkingConfig.thinkingBudget) +base_model = "google/gemini-2.5-flash" + +[[reasoning_options]] +type = "toggle" + +[[reasoning_options]] +type = "budget_tokens" +min = 0 +max = 24_576 + +[cost] +input = 0.30 +output = 2.50 +cache_read = 0.03 diff --git a/providers/gm/models/gemini-2.5-pro.toml b/providers/gm/models/gemini-2.5-pro.toml new file mode 100644 index 00000000000..8d7cd04db04 --- /dev/null +++ b/providers/gm/models/gemini-2.5-pro.toml @@ -0,0 +1,12 @@ +# Source: gm live /v1/models catalog 2026-08-07 (USD/MTok). +base_model = "google/gemini-2.5-pro" + +[[reasoning_options]] +type = "budget_tokens" +min = 128 +max = 32_768 + +[cost] +input = 1.25 +output = 10.00 +cache_read = 0.125 diff --git a/providers/gm/models/gemini-3.1-pro-preview.toml b/providers/gm/models/gemini-3.1-pro-preview.toml new file mode 100644 index 00000000000..824a0cec0ff --- /dev/null +++ b/providers/gm/models/gemini-3.1-pro-preview.toml @@ -0,0 +1,11 @@ +# Source: gm live /v1/models catalog 2026-08-07 (USD/MTok). +base_model = "google/gemini-3.1-pro-preview" + +[[reasoning_options]] +type = "effort" +values = ["low", "medium", "high"] + +[cost] +input = 2.00 +output = 12.00 +cache_read = 0.20 diff --git a/providers/gm/models/gemini-3.5-flash.toml b/providers/gm/models/gemini-3.5-flash.toml new file mode 100644 index 00000000000..a3970204686 --- /dev/null +++ b/providers/gm/models/gemini-3.5-flash.toml @@ -0,0 +1,11 @@ +# Source: gm live /v1/models catalog 2026-08-07 (USD/MTok). +base_model = "google/gemini-3.5-flash" + +[[reasoning_options]] +type = "effort" +values = ["minimal", "low", "medium", "high"] + +[cost] +input = 1.50 +output = 9.00 +cache_read = 0.15 diff --git a/providers/gm/models/gpt-5.4-mini.toml b/providers/gm/models/gpt-5.4-mini.toml new file mode 100644 index 00000000000..539df3376d1 --- /dev/null +++ b/providers/gm/models/gpt-5.4-mini.toml @@ -0,0 +1,11 @@ +# Source: gm live /v1/models catalog 2026-08-07 (USD/MTok). +base_model = "openai/gpt-5.4-mini" + +[[reasoning_options]] +type = "effort" +values = ["none", "low", "medium", "high", "xhigh"] + +[cost] +input = 0.75 +output = 4.50 +cache_read = 0.075 diff --git a/providers/gm/models/gpt-5.4-nano.toml b/providers/gm/models/gpt-5.4-nano.toml new file mode 100644 index 00000000000..3616af572d8 --- /dev/null +++ b/providers/gm/models/gpt-5.4-nano.toml @@ -0,0 +1,11 @@ +# Source: gm live /v1/models catalog 2026-08-07 (USD/MTok). +base_model = "openai/gpt-5.4-nano" + +[[reasoning_options]] +type = "effort" +values = ["none", "low", "medium", "high", "xhigh"] + +[cost] +input = 0.20 +output = 1.25 +cache_read = 0.02 diff --git a/providers/gm/models/gpt-5.4.toml b/providers/gm/models/gpt-5.4.toml new file mode 100644 index 00000000000..3fd379904e4 --- /dev/null +++ b/providers/gm/models/gpt-5.4.toml @@ -0,0 +1,11 @@ +# Source: gm live /v1/models catalog 2026-08-07 (USD/MTok). +base_model = "openai/gpt-5.4" + +[[reasoning_options]] +type = "effort" +values = ["none", "low", "medium", "high", "xhigh"] + +[cost] +input = 2.50 +output = 15.00 +cache_read = 0.25 diff --git a/providers/gm/models/gpt-5.5-pro.toml b/providers/gm/models/gpt-5.5-pro.toml new file mode 100644 index 00000000000..122aa6b0ab1 --- /dev/null +++ b/providers/gm/models/gpt-5.5-pro.toml @@ -0,0 +1,11 @@ +# Source: gm live /v1/models catalog 2026-08-07 (USD/MTok). +base_model = "openai/gpt-5.5-pro" + +[[reasoning_options]] +type = "effort" +values = ["medium", "high", "xhigh"] + +[cost] +input = 30.00 +output = 180.00 +cache_read = 3.00 diff --git a/providers/gm/models/gpt-5.5.toml b/providers/gm/models/gpt-5.5.toml new file mode 100644 index 00000000000..d00f55c06f8 --- /dev/null +++ b/providers/gm/models/gpt-5.5.toml @@ -0,0 +1,11 @@ +# Source: gm live /v1/models catalog 2026-08-07 (USD/MTok). +base_model = "openai/gpt-5.5" + +[[reasoning_options]] +type = "effort" +values = ["none", "low", "medium", "high", "xhigh"] + +[cost] +input = 5.00 +output = 30.00 +cache_read = 0.50 diff --git a/providers/gm/models/gpt-5.6-luna.toml b/providers/gm/models/gpt-5.6-luna.toml new file mode 100644 index 00000000000..3e9f1d15bc2 --- /dev/null +++ b/providers/gm/models/gpt-5.6-luna.toml @@ -0,0 +1,11 @@ +# Source: gm live /v1/models catalog 2026-08-07 (USD/MTok). +base_model = "openai/gpt-5.6-luna" + +[[reasoning_options]] +type = "effort" +values = ["none", "low", "medium", "high", "xhigh", "max"] + +[cost] +input = 0.20 +output = 1.20 +cache_read = 0.02 diff --git a/providers/gm/models/gpt-5.6-sol.toml b/providers/gm/models/gpt-5.6-sol.toml new file mode 100644 index 00000000000..cffa80e30cf --- /dev/null +++ b/providers/gm/models/gpt-5.6-sol.toml @@ -0,0 +1,11 @@ +# Source: gm live /v1/models catalog 2026-08-07 (USD/MTok). +base_model = "openai/gpt-5.6-sol" + +[[reasoning_options]] +type = "effort" +values = ["none", "low", "medium", "high", "xhigh", "max"] + +[cost] +input = 5.00 +output = 30.00 +cache_read = 0.50 diff --git a/providers/gm/models/gpt-5.6-terra.toml b/providers/gm/models/gpt-5.6-terra.toml new file mode 100644 index 00000000000..b591c9b6e20 --- /dev/null +++ b/providers/gm/models/gpt-5.6-terra.toml @@ -0,0 +1,11 @@ +# Source: gm live /v1/models catalog 2026-08-07 (USD/MTok). +base_model = "openai/gpt-5.6-terra" + +[[reasoning_options]] +type = "effort" +values = ["none", "low", "medium", "high", "xhigh", "max"] + +[cost] +input = 2.00 +output = 12.00 +cache_read = 0.20 diff --git a/providers/gm/models/gpt-5.6.toml b/providers/gm/models/gpt-5.6.toml new file mode 100644 index 00000000000..67fa78620c8 --- /dev/null +++ b/providers/gm/models/gpt-5.6.toml @@ -0,0 +1,12 @@ +# Source: gm live /v1/models catalog 2026-08-07 (USD/MTok). gm mirrors upstream gpt-5.6 limits. +base_model = "openai/gpt-5.6-sol" +name = "GPT-5.6" + +[[reasoning_options]] +type = "effort" +values = ["none", "low", "medium", "high", "xhigh", "max"] + +[cost] +input = 5.00 +output = 30.00 +cache_read = 0.50 diff --git a/providers/gm/models/o3.toml b/providers/gm/models/o3.toml new file mode 100644 index 00000000000..5adb67fe808 --- /dev/null +++ b/providers/gm/models/o3.toml @@ -0,0 +1,11 @@ +# Source: gm live /v1/models catalog 2026-08-07 (USD/MTok). +base_model = "openai/o3" + +[[reasoning_options]] +type = "effort" +values = ["low", "medium", "high"] + +[cost] +input = 2.00 +output = 8.00 +cache_read = 0.50 diff --git a/providers/gm/models/o4-mini.toml b/providers/gm/models/o4-mini.toml new file mode 100644 index 00000000000..f23c7a50596 --- /dev/null +++ b/providers/gm/models/o4-mini.toml @@ -0,0 +1,11 @@ +# Source: gm live /v1/models catalog 2026-08-07 (USD/MTok). +base_model = "openai/o4-mini" + +[[reasoning_options]] +type = "effort" +values = ["low", "medium", "high"] + +[cost] +input = 1.10 +output = 4.40 +cache_read = 0.275 diff --git a/providers/gm/provider.toml b/providers/gm/provider.toml new file mode 100644 index 00000000000..1e8e3edce20 --- /dev/null +++ b/providers/gm/provider.toml @@ -0,0 +1,5 @@ +name = "gm" +npm = "@ai-sdk/openai-compatible" +env = ["GM_API_KEY"] +api = "https://api.saygm.com/v1" +doc = "https://saygm.com" From c22a4eded3f3dc69c6dc86fdc85bd05250612b77 Mon Sep 17 00:00:00 2001 From: Mark Davison <6168730+markdavison@users.noreply.github.com> Date: Tue, 11 Aug 2026 17:50:14 +0100 Subject: [PATCH 2/9] Trim gm provider to currently available models --- providers/gm/models/gemini-2.5-flash-lite.toml | 16 ---------------- providers/gm/models/gemini-2.5-flash.toml | 16 ---------------- providers/gm/models/gemini-2.5-pro.toml | 12 ------------ providers/gm/models/gemini-3.1-pro-preview.toml | 11 ----------- providers/gm/models/gemini-3.5-flash.toml | 11 ----------- providers/gm/models/gpt-5.6.toml | 12 ------------ 6 files changed, 78 deletions(-) delete mode 100644 providers/gm/models/gemini-2.5-flash-lite.toml delete mode 100644 providers/gm/models/gemini-2.5-flash.toml delete mode 100644 providers/gm/models/gemini-2.5-pro.toml delete mode 100644 providers/gm/models/gemini-3.1-pro-preview.toml delete mode 100644 providers/gm/models/gemini-3.5-flash.toml delete mode 100644 providers/gm/models/gpt-5.6.toml diff --git a/providers/gm/models/gemini-2.5-flash-lite.toml b/providers/gm/models/gemini-2.5-flash-lite.toml deleted file mode 100644 index e11dd55adea..00000000000 --- a/providers/gm/models/gemini-2.5-flash-lite.toml +++ /dev/null @@ -1,16 +0,0 @@ -# Source: gm live /v1/models catalog 2026-08-07 (USD/MTok). -# Toggle: thinking budget 0 disables thinking (Google thinkingConfig.thinkingBudget) -base_model = "google/gemini-2.5-flash-lite" - -[[reasoning_options]] -type = "toggle" - -[[reasoning_options]] -type = "budget_tokens" -min = 512 -max = 24_576 - -[cost] -input = 0.10 -output = 0.40 -cache_read = 0.01 diff --git a/providers/gm/models/gemini-2.5-flash.toml b/providers/gm/models/gemini-2.5-flash.toml deleted file mode 100644 index 3f24c3b65ab..00000000000 --- a/providers/gm/models/gemini-2.5-flash.toml +++ /dev/null @@ -1,16 +0,0 @@ -# Source: gm live /v1/models catalog 2026-08-07 (USD/MTok). -# Toggle: thinking budget 0 disables thinking (Google thinkingConfig.thinkingBudget) -base_model = "google/gemini-2.5-flash" - -[[reasoning_options]] -type = "toggle" - -[[reasoning_options]] -type = "budget_tokens" -min = 0 -max = 24_576 - -[cost] -input = 0.30 -output = 2.50 -cache_read = 0.03 diff --git a/providers/gm/models/gemini-2.5-pro.toml b/providers/gm/models/gemini-2.5-pro.toml deleted file mode 100644 index 8d7cd04db04..00000000000 --- a/providers/gm/models/gemini-2.5-pro.toml +++ /dev/null @@ -1,12 +0,0 @@ -# Source: gm live /v1/models catalog 2026-08-07 (USD/MTok). -base_model = "google/gemini-2.5-pro" - -[[reasoning_options]] -type = "budget_tokens" -min = 128 -max = 32_768 - -[cost] -input = 1.25 -output = 10.00 -cache_read = 0.125 diff --git a/providers/gm/models/gemini-3.1-pro-preview.toml b/providers/gm/models/gemini-3.1-pro-preview.toml deleted file mode 100644 index 824a0cec0ff..00000000000 --- a/providers/gm/models/gemini-3.1-pro-preview.toml +++ /dev/null @@ -1,11 +0,0 @@ -# Source: gm live /v1/models catalog 2026-08-07 (USD/MTok). -base_model = "google/gemini-3.1-pro-preview" - -[[reasoning_options]] -type = "effort" -values = ["low", "medium", "high"] - -[cost] -input = 2.00 -output = 12.00 -cache_read = 0.20 diff --git a/providers/gm/models/gemini-3.5-flash.toml b/providers/gm/models/gemini-3.5-flash.toml deleted file mode 100644 index a3970204686..00000000000 --- a/providers/gm/models/gemini-3.5-flash.toml +++ /dev/null @@ -1,11 +0,0 @@ -# Source: gm live /v1/models catalog 2026-08-07 (USD/MTok). -base_model = "google/gemini-3.5-flash" - -[[reasoning_options]] -type = "effort" -values = ["minimal", "low", "medium", "high"] - -[cost] -input = 1.50 -output = 9.00 -cache_read = 0.15 diff --git a/providers/gm/models/gpt-5.6.toml b/providers/gm/models/gpt-5.6.toml deleted file mode 100644 index 67fa78620c8..00000000000 --- a/providers/gm/models/gpt-5.6.toml +++ /dev/null @@ -1,12 +0,0 @@ -# Source: gm live /v1/models catalog 2026-08-07 (USD/MTok). gm mirrors upstream gpt-5.6 limits. -base_model = "openai/gpt-5.6-sol" -name = "GPT-5.6" - -[[reasoning_options]] -type = "effort" -values = ["none", "low", "medium", "high", "xhigh", "max"] - -[cost] -input = 5.00 -output = 30.00 -cache_read = 0.50 From 00acb3419f0057354e269101b03e28026e768c31 Mon Sep 17 00:00:00 2001 From: Mark Davison <6168730+markdavison@users.noreply.github.com> Date: Tue, 11 Aug 2026 17:50:14 +0100 Subject: [PATCH 3/9] Fix gm adapter routing: claude via anthropic, gpt-5.5-pro via responses --- providers/gm/models/claude-fable-5.toml | 4 ++++ providers/gm/models/claude-haiku-4-5.toml | 4 ++++ providers/gm/models/claude-opus-4-7.toml | 4 ++++ providers/gm/models/claude-opus-4-8.toml | 4 ++++ providers/gm/models/claude-opus-5.toml | 4 ++++ providers/gm/models/claude-sonnet-4-6.toml | 4 ++++ providers/gm/models/claude-sonnet-5.toml | 4 ++++ providers/gm/models/gpt-5.5-pro.toml | 6 ++++++ 8 files changed, 34 insertions(+) diff --git a/providers/gm/models/claude-fable-5.toml b/providers/gm/models/claude-fable-5.toml index fee61c53146..d735c4bfb7a 100644 --- a/providers/gm/models/claude-fable-5.toml +++ b/providers/gm/models/claude-fable-5.toml @@ -9,3 +9,7 @@ values = ["low", "medium", "high", "xhigh", "max"] input = 10.00 output = 50.00 cache_read = 1.00 + +[provider] +npm = "@ai-sdk/anthropic" +api = "https://api.saygm.com/v1" diff --git a/providers/gm/models/claude-haiku-4-5.toml b/providers/gm/models/claude-haiku-4-5.toml index 80f540c6d0b..699f04def0e 100644 --- a/providers/gm/models/claude-haiku-4-5.toml +++ b/providers/gm/models/claude-haiku-4-5.toml @@ -9,3 +9,7 @@ min = 1_024 input = 1.00 output = 5.00 cache_read = 0.10 + +[provider] +npm = "@ai-sdk/anthropic" +api = "https://api.saygm.com/v1" diff --git a/providers/gm/models/claude-opus-4-7.toml b/providers/gm/models/claude-opus-4-7.toml index 21a5b0eb372..6be2d00db8f 100644 --- a/providers/gm/models/claude-opus-4-7.toml +++ b/providers/gm/models/claude-opus-4-7.toml @@ -9,3 +9,7 @@ values = ["low", "medium", "high", "xhigh", "max"] input = 5.00 output = 25.00 cache_read = 0.50 + +[provider] +npm = "@ai-sdk/anthropic" +api = "https://api.saygm.com/v1" diff --git a/providers/gm/models/claude-opus-4-8.toml b/providers/gm/models/claude-opus-4-8.toml index c758260b948..05273bc635b 100644 --- a/providers/gm/models/claude-opus-4-8.toml +++ b/providers/gm/models/claude-opus-4-8.toml @@ -9,3 +9,7 @@ values = ["low", "medium", "high", "xhigh", "max"] input = 5.00 output = 25.00 cache_read = 0.50 + +[provider] +npm = "@ai-sdk/anthropic" +api = "https://api.saygm.com/v1" diff --git a/providers/gm/models/claude-opus-5.toml b/providers/gm/models/claude-opus-5.toml index 5e98c889b3d..8afbf7f02f7 100644 --- a/providers/gm/models/claude-opus-5.toml +++ b/providers/gm/models/claude-opus-5.toml @@ -9,3 +9,7 @@ values = ["low", "medium", "high", "xhigh", "max"] input = 5.00 output = 25.00 cache_read = 0.50 + +[provider] +npm = "@ai-sdk/anthropic" +api = "https://api.saygm.com/v1" diff --git a/providers/gm/models/claude-sonnet-4-6.toml b/providers/gm/models/claude-sonnet-4-6.toml index 320fade3362..ff792615f72 100644 --- a/providers/gm/models/claude-sonnet-4-6.toml +++ b/providers/gm/models/claude-sonnet-4-6.toml @@ -13,3 +13,7 @@ min = 1_024 input = 3.00 output = 10.00 cache_read = 0.30 + +[provider] +npm = "@ai-sdk/anthropic" +api = "https://api.saygm.com/v1" diff --git a/providers/gm/models/claude-sonnet-5.toml b/providers/gm/models/claude-sonnet-5.toml index 4deb1ee0d84..970a306e2c5 100644 --- a/providers/gm/models/claude-sonnet-5.toml +++ b/providers/gm/models/claude-sonnet-5.toml @@ -14,3 +14,7 @@ values = ["low", "medium", "high", "xhigh", "max"] input = 3.00 output = 10.00 cache_read = 0.30 + +[provider] +npm = "@ai-sdk/anthropic" +api = "https://api.saygm.com/v1" diff --git a/providers/gm/models/gpt-5.5-pro.toml b/providers/gm/models/gpt-5.5-pro.toml index 122aa6b0ab1..1988021cf69 100644 --- a/providers/gm/models/gpt-5.5-pro.toml +++ b/providers/gm/models/gpt-5.5-pro.toml @@ -1,4 +1,5 @@ # Source: gm live /v1/models catalog 2026-08-07 (USD/MTok). +# Served only on the Responses API (gm /v1/models api_shapes = ["responses"]). base_model = "openai/gpt-5.5-pro" [[reasoning_options]] @@ -9,3 +10,8 @@ values = ["medium", "high", "xhigh"] input = 30.00 output = 180.00 cache_read = 3.00 + +[provider] +npm = "@ai-sdk/openai" +api = "https://api.saygm.com/v1" +shape = "responses" From 5635bc4689d41ce3cd811d7a6bdb1b7cdfecf9e0 Mon Sep 17 00:00:00 2001 From: Mark Davison <6168730+markdavison@users.noreply.github.com> Date: Tue, 11 Aug 2026 17:50:14 +0100 Subject: [PATCH 4/9] Rename gm provider to SayGM --- providers/{gm => saygm}/logo.svg | 0 providers/{gm => saygm}/models/claude-fable-5.toml | 2 +- providers/{gm => saygm}/models/claude-haiku-4-5.toml | 2 +- providers/{gm => saygm}/models/claude-opus-4-7.toml | 2 +- providers/{gm => saygm}/models/claude-opus-4-8.toml | 2 +- providers/{gm => saygm}/models/claude-opus-5.toml | 2 +- providers/{gm => saygm}/models/claude-sonnet-4-6.toml | 2 +- providers/{gm => saygm}/models/claude-sonnet-5.toml | 4 ++-- providers/{gm => saygm}/models/gpt-5.4-mini.toml | 2 +- providers/{gm => saygm}/models/gpt-5.4-nano.toml | 2 +- providers/{gm => saygm}/models/gpt-5.4.toml | 2 +- providers/{gm => saygm}/models/gpt-5.5-pro.toml | 4 ++-- providers/{gm => saygm}/models/gpt-5.5.toml | 2 +- providers/{gm => saygm}/models/gpt-5.6-luna.toml | 2 +- providers/{gm => saygm}/models/gpt-5.6-sol.toml | 2 +- providers/{gm => saygm}/models/gpt-5.6-terra.toml | 2 +- providers/{gm => saygm}/models/o3.toml | 2 +- providers/{gm => saygm}/models/o4-mini.toml | 2 +- providers/{gm => saygm}/provider.toml | 4 ++-- 19 files changed, 21 insertions(+), 21 deletions(-) rename providers/{gm => saygm}/logo.svg (100%) rename providers/{gm => saygm}/models/claude-fable-5.toml (80%) rename providers/{gm => saygm}/models/claude-haiku-4-5.toml (78%) rename providers/{gm => saygm}/models/claude-opus-4-7.toml (80%) rename providers/{gm => saygm}/models/claude-opus-4-8.toml (80%) rename providers/{gm => saygm}/models/claude-opus-5.toml (80%) rename providers/{gm => saygm}/models/claude-sonnet-4-6.toml (82%) rename providers/{gm => saygm}/models/claude-sonnet-5.toml (81%) rename providers/{gm => saygm}/models/gpt-5.4-mini.toml (74%) rename providers/{gm => saygm}/models/gpt-5.4-nano.toml (73%) rename providers/{gm => saygm}/models/gpt-5.4.toml (73%) rename providers/{gm => saygm}/models/gpt-5.5-pro.toml (63%) rename providers/{gm => saygm}/models/gpt-5.5.toml (73%) rename providers/{gm => saygm}/models/gpt-5.6-luna.toml (74%) rename providers/{gm => saygm}/models/gpt-5.6-sol.toml (74%) rename providers/{gm => saygm}/models/gpt-5.6-terra.toml (74%) rename providers/{gm => saygm}/models/o3.toml (70%) rename providers/{gm => saygm}/models/o4-mini.toml (71%) rename providers/{gm => saygm}/provider.toml (70%) diff --git a/providers/gm/logo.svg b/providers/saygm/logo.svg similarity index 100% rename from providers/gm/logo.svg rename to providers/saygm/logo.svg diff --git a/providers/gm/models/claude-fable-5.toml b/providers/saygm/models/claude-fable-5.toml similarity index 80% rename from providers/gm/models/claude-fable-5.toml rename to providers/saygm/models/claude-fable-5.toml index d735c4bfb7a..409738b53a3 100644 --- a/providers/gm/models/claude-fable-5.toml +++ b/providers/saygm/models/claude-fable-5.toml @@ -1,4 +1,4 @@ -# Source: gm live /v1/models catalog 2026-08-07 (USD/MTok). +# Source: SayGM live /v1/models catalog 2026-08-07 (USD/MTok). base_model = "anthropic/claude-fable-5" [[reasoning_options]] diff --git a/providers/gm/models/claude-haiku-4-5.toml b/providers/saygm/models/claude-haiku-4-5.toml similarity index 78% rename from providers/gm/models/claude-haiku-4-5.toml rename to providers/saygm/models/claude-haiku-4-5.toml index 699f04def0e..46538056c59 100644 --- a/providers/gm/models/claude-haiku-4-5.toml +++ b/providers/saygm/models/claude-haiku-4-5.toml @@ -1,4 +1,4 @@ -# Source: gm live /v1/models catalog 2026-08-07 (USD/MTok). +# Source: SayGM live /v1/models catalog 2026-08-07 (USD/MTok). base_model = "anthropic/claude-haiku-4-5" [[reasoning_options]] diff --git a/providers/gm/models/claude-opus-4-7.toml b/providers/saygm/models/claude-opus-4-7.toml similarity index 80% rename from providers/gm/models/claude-opus-4-7.toml rename to providers/saygm/models/claude-opus-4-7.toml index 6be2d00db8f..fdf48ecb2e6 100644 --- a/providers/gm/models/claude-opus-4-7.toml +++ b/providers/saygm/models/claude-opus-4-7.toml @@ -1,4 +1,4 @@ -# Source: gm live /v1/models catalog 2026-08-07 (USD/MTok). +# Source: SayGM live /v1/models catalog 2026-08-07 (USD/MTok). base_model = "anthropic/claude-opus-4-7" [[reasoning_options]] diff --git a/providers/gm/models/claude-opus-4-8.toml b/providers/saygm/models/claude-opus-4-8.toml similarity index 80% rename from providers/gm/models/claude-opus-4-8.toml rename to providers/saygm/models/claude-opus-4-8.toml index 05273bc635b..5f8ad18a255 100644 --- a/providers/gm/models/claude-opus-4-8.toml +++ b/providers/saygm/models/claude-opus-4-8.toml @@ -1,4 +1,4 @@ -# Source: gm live /v1/models catalog 2026-08-07 (USD/MTok). +# Source: SayGM live /v1/models catalog 2026-08-07 (USD/MTok). base_model = "anthropic/claude-opus-4-8" [[reasoning_options]] diff --git a/providers/gm/models/claude-opus-5.toml b/providers/saygm/models/claude-opus-5.toml similarity index 80% rename from providers/gm/models/claude-opus-5.toml rename to providers/saygm/models/claude-opus-5.toml index 8afbf7f02f7..f4cf7b48617 100644 --- a/providers/gm/models/claude-opus-5.toml +++ b/providers/saygm/models/claude-opus-5.toml @@ -1,4 +1,4 @@ -# Source: gm live /v1/models catalog 2026-08-07 (USD/MTok). +# Source: SayGM live /v1/models catalog 2026-08-07 (USD/MTok). base_model = "anthropic/claude-opus-5" [[reasoning_options]] diff --git a/providers/gm/models/claude-sonnet-4-6.toml b/providers/saygm/models/claude-sonnet-4-6.toml similarity index 82% rename from providers/gm/models/claude-sonnet-4-6.toml rename to providers/saygm/models/claude-sonnet-4-6.toml index ff792615f72..61bf2cab656 100644 --- a/providers/gm/models/claude-sonnet-4-6.toml +++ b/providers/saygm/models/claude-sonnet-4-6.toml @@ -1,4 +1,4 @@ -# Source: gm live /v1/models catalog 2026-08-07 (USD/MTok). +# Source: SayGM live /v1/models catalog 2026-08-07 (USD/MTok). base_model = "anthropic/claude-sonnet-4-6" [[reasoning_options]] diff --git a/providers/gm/models/claude-sonnet-5.toml b/providers/saygm/models/claude-sonnet-5.toml similarity index 81% rename from providers/gm/models/claude-sonnet-5.toml rename to providers/saygm/models/claude-sonnet-5.toml index 970a306e2c5..f0f08f3e003 100644 --- a/providers/gm/models/claude-sonnet-5.toml +++ b/providers/saygm/models/claude-sonnet-5.toml @@ -1,5 +1,5 @@ -# Source: gm live /v1/models catalog 2026-08-07 (USD/MTok). -# Toggle: thinking.type = enabled|disabled (Anthropic Messages wire; gm mirrors upstream) +# Source: SayGM live /v1/models catalog 2026-08-07 (USD/MTok). +# Toggle: thinking.type = enabled|disabled (Anthropic Messages wire; SayGM mirrors upstream) # Effort: output_config.effort = low|medium|high|xhigh|max base_model = "anthropic/claude-sonnet-5" diff --git a/providers/gm/models/gpt-5.4-mini.toml b/providers/saygm/models/gpt-5.4-mini.toml similarity index 74% rename from providers/gm/models/gpt-5.4-mini.toml rename to providers/saygm/models/gpt-5.4-mini.toml index 539df3376d1..20971a4dea7 100644 --- a/providers/gm/models/gpt-5.4-mini.toml +++ b/providers/saygm/models/gpt-5.4-mini.toml @@ -1,4 +1,4 @@ -# Source: gm live /v1/models catalog 2026-08-07 (USD/MTok). +# Source: SayGM live /v1/models catalog 2026-08-07 (USD/MTok). base_model = "openai/gpt-5.4-mini" [[reasoning_options]] diff --git a/providers/gm/models/gpt-5.4-nano.toml b/providers/saygm/models/gpt-5.4-nano.toml similarity index 73% rename from providers/gm/models/gpt-5.4-nano.toml rename to providers/saygm/models/gpt-5.4-nano.toml index 3616af572d8..0576a19e08a 100644 --- a/providers/gm/models/gpt-5.4-nano.toml +++ b/providers/saygm/models/gpt-5.4-nano.toml @@ -1,4 +1,4 @@ -# Source: gm live /v1/models catalog 2026-08-07 (USD/MTok). +# Source: SayGM live /v1/models catalog 2026-08-07 (USD/MTok). base_model = "openai/gpt-5.4-nano" [[reasoning_options]] diff --git a/providers/gm/models/gpt-5.4.toml b/providers/saygm/models/gpt-5.4.toml similarity index 73% rename from providers/gm/models/gpt-5.4.toml rename to providers/saygm/models/gpt-5.4.toml index 3fd379904e4..754d1bc5189 100644 --- a/providers/gm/models/gpt-5.4.toml +++ b/providers/saygm/models/gpt-5.4.toml @@ -1,4 +1,4 @@ -# Source: gm live /v1/models catalog 2026-08-07 (USD/MTok). +# Source: SayGM live /v1/models catalog 2026-08-07 (USD/MTok). base_model = "openai/gpt-5.4" [[reasoning_options]] diff --git a/providers/gm/models/gpt-5.5-pro.toml b/providers/saygm/models/gpt-5.5-pro.toml similarity index 63% rename from providers/gm/models/gpt-5.5-pro.toml rename to providers/saygm/models/gpt-5.5-pro.toml index 1988021cf69..e6ebea7d2de 100644 --- a/providers/gm/models/gpt-5.5-pro.toml +++ b/providers/saygm/models/gpt-5.5-pro.toml @@ -1,5 +1,5 @@ -# Source: gm live /v1/models catalog 2026-08-07 (USD/MTok). -# Served only on the Responses API (gm /v1/models api_shapes = ["responses"]). +# Source: SayGM live /v1/models catalog 2026-08-07 (USD/MTok). +# Served only on the Responses API (SayGM /v1/models api_shapes = ["responses"]). base_model = "openai/gpt-5.5-pro" [[reasoning_options]] diff --git a/providers/gm/models/gpt-5.5.toml b/providers/saygm/models/gpt-5.5.toml similarity index 73% rename from providers/gm/models/gpt-5.5.toml rename to providers/saygm/models/gpt-5.5.toml index d00f55c06f8..5aa603c46fc 100644 --- a/providers/gm/models/gpt-5.5.toml +++ b/providers/saygm/models/gpt-5.5.toml @@ -1,4 +1,4 @@ -# Source: gm live /v1/models catalog 2026-08-07 (USD/MTok). +# Source: SayGM live /v1/models catalog 2026-08-07 (USD/MTok). base_model = "openai/gpt-5.5" [[reasoning_options]] diff --git a/providers/gm/models/gpt-5.6-luna.toml b/providers/saygm/models/gpt-5.6-luna.toml similarity index 74% rename from providers/gm/models/gpt-5.6-luna.toml rename to providers/saygm/models/gpt-5.6-luna.toml index 3e9f1d15bc2..d07dbebc511 100644 --- a/providers/gm/models/gpt-5.6-luna.toml +++ b/providers/saygm/models/gpt-5.6-luna.toml @@ -1,4 +1,4 @@ -# Source: gm live /v1/models catalog 2026-08-07 (USD/MTok). +# Source: SayGM live /v1/models catalog 2026-08-07 (USD/MTok). base_model = "openai/gpt-5.6-luna" [[reasoning_options]] diff --git a/providers/gm/models/gpt-5.6-sol.toml b/providers/saygm/models/gpt-5.6-sol.toml similarity index 74% rename from providers/gm/models/gpt-5.6-sol.toml rename to providers/saygm/models/gpt-5.6-sol.toml index cffa80e30cf..2dafb9451bb 100644 --- a/providers/gm/models/gpt-5.6-sol.toml +++ b/providers/saygm/models/gpt-5.6-sol.toml @@ -1,4 +1,4 @@ -# Source: gm live /v1/models catalog 2026-08-07 (USD/MTok). +# Source: SayGM live /v1/models catalog 2026-08-07 (USD/MTok). base_model = "openai/gpt-5.6-sol" [[reasoning_options]] diff --git a/providers/gm/models/gpt-5.6-terra.toml b/providers/saygm/models/gpt-5.6-terra.toml similarity index 74% rename from providers/gm/models/gpt-5.6-terra.toml rename to providers/saygm/models/gpt-5.6-terra.toml index b591c9b6e20..59a12ea449b 100644 --- a/providers/gm/models/gpt-5.6-terra.toml +++ b/providers/saygm/models/gpt-5.6-terra.toml @@ -1,4 +1,4 @@ -# Source: gm live /v1/models catalog 2026-08-07 (USD/MTok). +# Source: SayGM live /v1/models catalog 2026-08-07 (USD/MTok). base_model = "openai/gpt-5.6-terra" [[reasoning_options]] diff --git a/providers/gm/models/o3.toml b/providers/saygm/models/o3.toml similarity index 70% rename from providers/gm/models/o3.toml rename to providers/saygm/models/o3.toml index 5adb67fe808..9d954cd0622 100644 --- a/providers/gm/models/o3.toml +++ b/providers/saygm/models/o3.toml @@ -1,4 +1,4 @@ -# Source: gm live /v1/models catalog 2026-08-07 (USD/MTok). +# Source: SayGM live /v1/models catalog 2026-08-07 (USD/MTok). base_model = "openai/o3" [[reasoning_options]] diff --git a/providers/gm/models/o4-mini.toml b/providers/saygm/models/o4-mini.toml similarity index 71% rename from providers/gm/models/o4-mini.toml rename to providers/saygm/models/o4-mini.toml index f23c7a50596..17d1b0c3ab9 100644 --- a/providers/gm/models/o4-mini.toml +++ b/providers/saygm/models/o4-mini.toml @@ -1,4 +1,4 @@ -# Source: gm live /v1/models catalog 2026-08-07 (USD/MTok). +# Source: SayGM live /v1/models catalog 2026-08-07 (USD/MTok). base_model = "openai/o4-mini" [[reasoning_options]] diff --git a/providers/gm/provider.toml b/providers/saygm/provider.toml similarity index 70% rename from providers/gm/provider.toml rename to providers/saygm/provider.toml index 1e8e3edce20..4b5786a9bc1 100644 --- a/providers/gm/provider.toml +++ b/providers/saygm/provider.toml @@ -1,5 +1,5 @@ -name = "gm" +name = "SayGM" npm = "@ai-sdk/openai-compatible" -env = ["GM_API_KEY"] +env = ["SAYGM_API_KEY"] api = "https://api.saygm.com/v1" doc = "https://saygm.com" From 0e40b3d02f42cdec84f2a13d1855846a8cc06767 Mon Sep 17 00:00:00 2001 From: Mark Davison <6168730+markdavison@users.noreply.github.com> Date: Tue, 11 Aug 2026 17:50:14 +0100 Subject: [PATCH 5/9] fix: correct SayGM integration metadata --- providers/saygm/logo.svg | 9 ++++++--- providers/saygm/models/claude-fable-5.toml | 7 +------ providers/saygm/models/claude-haiku-4-5.toml | 7 +------ providers/saygm/models/claude-opus-4-7.toml | 7 +------ providers/saygm/models/claude-opus-4-8.toml | 7 +------ providers/saygm/models/claude-opus-5.toml | 7 +------ providers/saygm/models/claude-sonnet-4-6.toml | 7 +------ providers/saygm/models/claude-sonnet-5.toml | 7 +------ providers/saygm/models/gpt-5.4-mini.toml | 7 +------ providers/saygm/models/gpt-5.4-nano.toml | 7 +------ providers/saygm/models/gpt-5.4.toml | 7 +------ providers/saygm/models/gpt-5.5-pro.toml | 7 +------ providers/saygm/models/gpt-5.5.toml | 7 +------ providers/saygm/models/gpt-5.6-luna.toml | 7 +------ providers/saygm/models/gpt-5.6-sol.toml | 7 +------ providers/saygm/models/gpt-5.6-terra.toml | 7 +------ providers/saygm/models/o3.toml | 7 +------ providers/saygm/models/o4-mini.toml | 7 +------ 18 files changed, 23 insertions(+), 105 deletions(-) diff --git a/providers/saygm/logo.svg b/providers/saygm/logo.svg index 497f15af61b..699db3d3cc0 100644 --- a/providers/saygm/logo.svg +++ b/providers/saygm/logo.svg @@ -1,4 +1,7 @@ - - - + + + + + + diff --git a/providers/saygm/models/claude-fable-5.toml b/providers/saygm/models/claude-fable-5.toml index 409738b53a3..e615f05e65a 100644 --- a/providers/saygm/models/claude-fable-5.toml +++ b/providers/saygm/models/claude-fable-5.toml @@ -1,15 +1,10 @@ -# Source: SayGM live /v1/models catalog 2026-08-07 (USD/MTok). base_model = "anthropic/claude-fable-5" +base_model_omit = ["cost"] [[reasoning_options]] type = "effort" values = ["low", "medium", "high", "xhigh", "max"] -[cost] -input = 10.00 -output = 50.00 -cache_read = 1.00 - [provider] npm = "@ai-sdk/anthropic" api = "https://api.saygm.com/v1" diff --git a/providers/saygm/models/claude-haiku-4-5.toml b/providers/saygm/models/claude-haiku-4-5.toml index 46538056c59..3a3c06bd9bd 100644 --- a/providers/saygm/models/claude-haiku-4-5.toml +++ b/providers/saygm/models/claude-haiku-4-5.toml @@ -1,15 +1,10 @@ -# Source: SayGM live /v1/models catalog 2026-08-07 (USD/MTok). base_model = "anthropic/claude-haiku-4-5" +base_model_omit = ["cost"] [[reasoning_options]] type = "budget_tokens" min = 1_024 -[cost] -input = 1.00 -output = 5.00 -cache_read = 0.10 - [provider] npm = "@ai-sdk/anthropic" api = "https://api.saygm.com/v1" diff --git a/providers/saygm/models/claude-opus-4-7.toml b/providers/saygm/models/claude-opus-4-7.toml index fdf48ecb2e6..2af3fdc1e18 100644 --- a/providers/saygm/models/claude-opus-4-7.toml +++ b/providers/saygm/models/claude-opus-4-7.toml @@ -1,15 +1,10 @@ -# Source: SayGM live /v1/models catalog 2026-08-07 (USD/MTok). base_model = "anthropic/claude-opus-4-7" +base_model_omit = ["cost"] [[reasoning_options]] type = "effort" values = ["low", "medium", "high", "xhigh", "max"] -[cost] -input = 5.00 -output = 25.00 -cache_read = 0.50 - [provider] npm = "@ai-sdk/anthropic" api = "https://api.saygm.com/v1" diff --git a/providers/saygm/models/claude-opus-4-8.toml b/providers/saygm/models/claude-opus-4-8.toml index 5f8ad18a255..ba93d19677b 100644 --- a/providers/saygm/models/claude-opus-4-8.toml +++ b/providers/saygm/models/claude-opus-4-8.toml @@ -1,15 +1,10 @@ -# Source: SayGM live /v1/models catalog 2026-08-07 (USD/MTok). base_model = "anthropic/claude-opus-4-8" +base_model_omit = ["cost"] [[reasoning_options]] type = "effort" values = ["low", "medium", "high", "xhigh", "max"] -[cost] -input = 5.00 -output = 25.00 -cache_read = 0.50 - [provider] npm = "@ai-sdk/anthropic" api = "https://api.saygm.com/v1" diff --git a/providers/saygm/models/claude-opus-5.toml b/providers/saygm/models/claude-opus-5.toml index f4cf7b48617..277e5bb4eb8 100644 --- a/providers/saygm/models/claude-opus-5.toml +++ b/providers/saygm/models/claude-opus-5.toml @@ -1,15 +1,10 @@ -# Source: SayGM live /v1/models catalog 2026-08-07 (USD/MTok). base_model = "anthropic/claude-opus-5" +base_model_omit = ["cost"] [[reasoning_options]] type = "effort" values = ["low", "medium", "high", "xhigh", "max"] -[cost] -input = 5.00 -output = 25.00 -cache_read = 0.50 - [provider] npm = "@ai-sdk/anthropic" api = "https://api.saygm.com/v1" diff --git a/providers/saygm/models/claude-sonnet-4-6.toml b/providers/saygm/models/claude-sonnet-4-6.toml index 61bf2cab656..ea3a500495a 100644 --- a/providers/saygm/models/claude-sonnet-4-6.toml +++ b/providers/saygm/models/claude-sonnet-4-6.toml @@ -1,5 +1,5 @@ -# Source: SayGM live /v1/models catalog 2026-08-07 (USD/MTok). base_model = "anthropic/claude-sonnet-4-6" +base_model_omit = ["cost"] [[reasoning_options]] type = "effort" @@ -9,11 +9,6 @@ values = ["low", "medium", "high", "max"] type = "budget_tokens" min = 1_024 -[cost] -input = 3.00 -output = 10.00 -cache_read = 0.30 - [provider] npm = "@ai-sdk/anthropic" api = "https://api.saygm.com/v1" diff --git a/providers/saygm/models/claude-sonnet-5.toml b/providers/saygm/models/claude-sonnet-5.toml index f0f08f3e003..2a619b98fa9 100644 --- a/providers/saygm/models/claude-sonnet-5.toml +++ b/providers/saygm/models/claude-sonnet-5.toml @@ -1,7 +1,7 @@ -# Source: SayGM live /v1/models catalog 2026-08-07 (USD/MTok). # Toggle: thinking.type = enabled|disabled (Anthropic Messages wire; SayGM mirrors upstream) # Effort: output_config.effort = low|medium|high|xhigh|max base_model = "anthropic/claude-sonnet-5" +base_model_omit = ["cost"] [[reasoning_options]] type = "toggle" @@ -10,11 +10,6 @@ type = "toggle" type = "effort" values = ["low", "medium", "high", "xhigh", "max"] -[cost] -input = 3.00 -output = 10.00 -cache_read = 0.30 - [provider] npm = "@ai-sdk/anthropic" api = "https://api.saygm.com/v1" diff --git a/providers/saygm/models/gpt-5.4-mini.toml b/providers/saygm/models/gpt-5.4-mini.toml index 20971a4dea7..faf487973e9 100644 --- a/providers/saygm/models/gpt-5.4-mini.toml +++ b/providers/saygm/models/gpt-5.4-mini.toml @@ -1,11 +1,6 @@ -# Source: SayGM live /v1/models catalog 2026-08-07 (USD/MTok). base_model = "openai/gpt-5.4-mini" +base_model_omit = ["cost"] [[reasoning_options]] type = "effort" values = ["none", "low", "medium", "high", "xhigh"] - -[cost] -input = 0.75 -output = 4.50 -cache_read = 0.075 diff --git a/providers/saygm/models/gpt-5.4-nano.toml b/providers/saygm/models/gpt-5.4-nano.toml index 0576a19e08a..17c1b7a1add 100644 --- a/providers/saygm/models/gpt-5.4-nano.toml +++ b/providers/saygm/models/gpt-5.4-nano.toml @@ -1,11 +1,6 @@ -# Source: SayGM live /v1/models catalog 2026-08-07 (USD/MTok). base_model = "openai/gpt-5.4-nano" +base_model_omit = ["cost"] [[reasoning_options]] type = "effort" values = ["none", "low", "medium", "high", "xhigh"] - -[cost] -input = 0.20 -output = 1.25 -cache_read = 0.02 diff --git a/providers/saygm/models/gpt-5.4.toml b/providers/saygm/models/gpt-5.4.toml index 754d1bc5189..8d2d86e7283 100644 --- a/providers/saygm/models/gpt-5.4.toml +++ b/providers/saygm/models/gpt-5.4.toml @@ -1,11 +1,6 @@ -# Source: SayGM live /v1/models catalog 2026-08-07 (USD/MTok). base_model = "openai/gpt-5.4" +base_model_omit = ["cost"] [[reasoning_options]] type = "effort" values = ["none", "low", "medium", "high", "xhigh"] - -[cost] -input = 2.50 -output = 15.00 -cache_read = 0.25 diff --git a/providers/saygm/models/gpt-5.5-pro.toml b/providers/saygm/models/gpt-5.5-pro.toml index e6ebea7d2de..1c0688dd50a 100644 --- a/providers/saygm/models/gpt-5.5-pro.toml +++ b/providers/saygm/models/gpt-5.5-pro.toml @@ -1,16 +1,11 @@ -# Source: SayGM live /v1/models catalog 2026-08-07 (USD/MTok). # Served only on the Responses API (SayGM /v1/models api_shapes = ["responses"]). base_model = "openai/gpt-5.5-pro" +base_model_omit = ["cost"] [[reasoning_options]] type = "effort" values = ["medium", "high", "xhigh"] -[cost] -input = 30.00 -output = 180.00 -cache_read = 3.00 - [provider] npm = "@ai-sdk/openai" api = "https://api.saygm.com/v1" diff --git a/providers/saygm/models/gpt-5.5.toml b/providers/saygm/models/gpt-5.5.toml index 5aa603c46fc..2859b97f1d9 100644 --- a/providers/saygm/models/gpt-5.5.toml +++ b/providers/saygm/models/gpt-5.5.toml @@ -1,11 +1,6 @@ -# Source: SayGM live /v1/models catalog 2026-08-07 (USD/MTok). base_model = "openai/gpt-5.5" +base_model_omit = ["cost"] [[reasoning_options]] type = "effort" values = ["none", "low", "medium", "high", "xhigh"] - -[cost] -input = 5.00 -output = 30.00 -cache_read = 0.50 diff --git a/providers/saygm/models/gpt-5.6-luna.toml b/providers/saygm/models/gpt-5.6-luna.toml index d07dbebc511..85556d59e51 100644 --- a/providers/saygm/models/gpt-5.6-luna.toml +++ b/providers/saygm/models/gpt-5.6-luna.toml @@ -1,11 +1,6 @@ -# Source: SayGM live /v1/models catalog 2026-08-07 (USD/MTok). base_model = "openai/gpt-5.6-luna" +base_model_omit = ["cost"] [[reasoning_options]] type = "effort" values = ["none", "low", "medium", "high", "xhigh", "max"] - -[cost] -input = 0.20 -output = 1.20 -cache_read = 0.02 diff --git a/providers/saygm/models/gpt-5.6-sol.toml b/providers/saygm/models/gpt-5.6-sol.toml index 2dafb9451bb..c561356545b 100644 --- a/providers/saygm/models/gpt-5.6-sol.toml +++ b/providers/saygm/models/gpt-5.6-sol.toml @@ -1,11 +1,6 @@ -# Source: SayGM live /v1/models catalog 2026-08-07 (USD/MTok). base_model = "openai/gpt-5.6-sol" +base_model_omit = ["cost"] [[reasoning_options]] type = "effort" values = ["none", "low", "medium", "high", "xhigh", "max"] - -[cost] -input = 5.00 -output = 30.00 -cache_read = 0.50 diff --git a/providers/saygm/models/gpt-5.6-terra.toml b/providers/saygm/models/gpt-5.6-terra.toml index 59a12ea449b..a6f78be44bb 100644 --- a/providers/saygm/models/gpt-5.6-terra.toml +++ b/providers/saygm/models/gpt-5.6-terra.toml @@ -1,11 +1,6 @@ -# Source: SayGM live /v1/models catalog 2026-08-07 (USD/MTok). base_model = "openai/gpt-5.6-terra" +base_model_omit = ["cost"] [[reasoning_options]] type = "effort" values = ["none", "low", "medium", "high", "xhigh", "max"] - -[cost] -input = 2.00 -output = 12.00 -cache_read = 0.20 diff --git a/providers/saygm/models/o3.toml b/providers/saygm/models/o3.toml index 9d954cd0622..7d088ec56fd 100644 --- a/providers/saygm/models/o3.toml +++ b/providers/saygm/models/o3.toml @@ -1,11 +1,6 @@ -# Source: SayGM live /v1/models catalog 2026-08-07 (USD/MTok). base_model = "openai/o3" +base_model_omit = ["cost"] [[reasoning_options]] type = "effort" values = ["low", "medium", "high"] - -[cost] -input = 2.00 -output = 8.00 -cache_read = 0.50 diff --git a/providers/saygm/models/o4-mini.toml b/providers/saygm/models/o4-mini.toml index 17d1b0c3ab9..3658f9b2918 100644 --- a/providers/saygm/models/o4-mini.toml +++ b/providers/saygm/models/o4-mini.toml @@ -1,11 +1,6 @@ -# Source: SayGM live /v1/models catalog 2026-08-07 (USD/MTok). base_model = "openai/o4-mini" +base_model_omit = ["cost"] [[reasoning_options]] type = "effort" values = ["low", "medium", "high"] - -[cost] -input = 1.10 -output = 4.40 -cache_read = 0.275 From e8e2086331eab6d7034b0faaec114b6eac4f2fd0 Mon Sep 17 00:00:00 2001 From: Mark Davison <6168730+markdavison@users.noreply.github.com> Date: Tue, 11 Aug 2026 17:50:14 +0100 Subject: [PATCH 6/9] fix: use exact SayGM logo asset --- providers/saygm/logo.svg | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/providers/saygm/logo.svg b/providers/saygm/logo.svg index 699db3d3cc0..a7f15946624 100644 --- a/providers/saygm/logo.svg +++ b/providers/saygm/logo.svg @@ -1,7 +1,7 @@ - - - + + + From bc30b904e9324dfed132182746895dc70ed61c3e Mon Sep 17 00:00:00 2001 From: Mark Davison <6168730+markdavison@users.noreply.github.com> Date: Tue, 11 Aug 2026 17:50:14 +0100 Subject: [PATCH 7/9] fix(saygm): use theme-compatible provider mark --- providers/saygm/logo.svg | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/providers/saygm/logo.svg b/providers/saygm/logo.svg index a7f15946624..64b29067084 100644 --- a/providers/saygm/logo.svg +++ b/providers/saygm/logo.svg @@ -1,7 +1,6 @@ - - - + + From 2352968b31e3bbe5b55f4f07cc4372b1c57d7de7 Mon Sep 17 00:00:00 2001 From: Mark Davison <6168730+markdavison@users.noreply.github.com> Date: Thu, 13 Aug 2026 13:56:38 +0100 Subject: [PATCH 8/9] feat(sync): update SayGM retail pricing --- package.json | 1 + packages/core/src/sync/index.ts | 5 +- packages/core/src/sync/providers/saygm.ts | 154 ++++++++++++++++++ packages/core/test/sync.test.ts | 101 ++++++++++++ providers/saygm/models/claude-fable-5.toml | 6 + providers/saygm/models/claude-haiku-4-5.toml | 6 + providers/saygm/models/claude-opus-4-7.toml | 6 + providers/saygm/models/claude-opus-4-8.toml | 6 + providers/saygm/models/claude-opus-5.toml | 6 + providers/saygm/models/claude-sonnet-4-6.toml | 6 + providers/saygm/models/claude-sonnet-5.toml | 6 + providers/saygm/models/gpt-5.4-mini.toml | 5 + providers/saygm/models/gpt-5.4-nano.toml | 5 + providers/saygm/models/gpt-5.4.toml | 10 ++ providers/saygm/models/gpt-5.5-pro.toml | 5 + providers/saygm/models/gpt-5.5.toml | 10 ++ providers/saygm/models/gpt-5.6-luna.toml | 10 ++ providers/saygm/models/gpt-5.6-sol.toml | 10 ++ providers/saygm/models/gpt-5.6-terra.toml | 10 ++ providers/saygm/models/o3.toml | 5 + providers/saygm/models/o4-mini.toml | 5 + 21 files changed, 377 insertions(+), 1 deletion(-) create mode 100644 packages/core/src/sync/providers/saygm.ts diff --git a/package.json b/package.json index cb013bfc0b2..0f497320e25 100644 --- a/package.json +++ b/package.json @@ -29,6 +29,7 @@ "kilo:sync": "bun ./packages/core/script/sync-models.ts kilo", "llmgateway:sync": "bun ./packages/core/script/sync-models.ts llmgateway", "requesty:sync": "bun ./packages/core/script/sync-models.ts requesty", + "saygm:sync": "bun ./packages/core/script/sync-models.ts saygm", "merge-gateway:sync": "bun ./packages/core/script/sync-models.ts merge-gateway", "nano-gpt:sync": "bun ./packages/core/script/sync-models.ts nano-gpt", "venice:sync": "bun ./packages/core/script/sync-models.ts venice", diff --git a/packages/core/src/sync/index.ts b/packages/core/src/sync/index.ts index 34691c06c5f..bcea9831783 100644 --- a/packages/core/src/sync/index.ts +++ b/packages/core/src/sync/index.ts @@ -30,6 +30,7 @@ import { openrouter } from "./providers/openrouter.js"; import { ovhcloud } from "./providers/ovhcloud.js"; import { pioneer } from "./providers/pioneer.js"; import { requesty } from "./providers/requesty.js"; +import { saygm } from "./providers/saygm.js"; import { tinfoil } from "./providers/tinfoil.js"; import { vercel } from "./providers/vercel.js"; import { venice } from "./providers/venice.js"; @@ -139,6 +140,7 @@ export const providers: { ovhcloud: SyncProvider; pioneer: SyncProvider; requesty: SyncProvider; + saygm: SyncProvider; tinfoil: SyncProvider; vercel: SyncProvider; venice: SyncProvider; @@ -170,6 +172,7 @@ export const providers: { ovhcloud, pioneer, requesty, + saygm, tinfoil, vercel, venice, @@ -194,7 +197,7 @@ export const groups = { "vercel", ], cloudflare: ["cloudflare-workers-ai"], - direct: ["ambient", "anthropic", "baseten", "chutes", "cortecs", "deepinfra", "digitalocean", "google", "hyper", "openai", "ovhcloud", "pioneer", "tinfoil", "venice", "wandb", "xai"], + direct: ["ambient", "anthropic", "baseten", "chutes", "cortecs", "deepinfra", "digitalocean", "google", "hyper", "openai", "ovhcloud", "pioneer", "saygm", "tinfoil", "venice", "wandb", "xai"], } as const; type ProviderID = keyof typeof providers; diff --git a/packages/core/src/sync/providers/saygm.ts b/packages/core/src/sync/providers/saygm.ts new file mode 100644 index 00000000000..ecf3a0f6a8a --- /dev/null +++ b/packages/core/src/sync/providers/saygm.ts @@ -0,0 +1,154 @@ +import { z } from "zod"; + +import type { ExistingModel, SyncProvider, SyncedModel } from "../index.js"; + +const API_ENDPOINT = "https://api.saygm.com/v1/models"; +const NDOLLARS_PER_DOLLAR = 1_000_000_000; + +const NanoDollars = z.number().int().nonnegative().max(Number.MAX_SAFE_INTEGER); + +const PriceDimensions = z.object({ + input_per_mtok_ndollars: NanoDollars, + output_per_mtok_ndollars: NanoDollars, + cache_read_per_mtok_ndollars: NanoDollars.optional(), + cache_write_5m_per_mtok_ndollars: NanoDollars.optional(), + cache_write_1h_per_mtok_ndollars: NanoDollars.optional(), + audio_input_per_mtok_ndollars: NanoDollars.optional(), + audio_output_per_mtok_ndollars: NanoDollars.optional(), + long_context_threshold_tokens: z.number().int().positive().max(Number.MAX_SAFE_INTEGER).optional(), + long_context_input_per_mtok_ndollars: NanoDollars.optional(), + long_context_output_per_mtok_ndollars: NanoDollars.optional(), +}).passthrough().superRefine((dimensions, context) => { + const longContext = [ + dimensions.long_context_threshold_tokens, + dimensions.long_context_input_per_mtok_ndollars, + dimensions.long_context_output_per_mtok_ndollars, + ]; + const present = longContext.filter((value) => value !== undefined).length; + if (present !== 0 && present !== longContext.length) { + context.addIssue({ + code: z.ZodIssueCode.custom, + message: "Long-context pricing requires a threshold plus input and output prices", + }); + } +}); + +const RetailCeiling = z.object({ + basis: z.literal("published_retail"), + dimensions: PriceDimensions, +}).passthrough(); + +export const SaygmModel = z.object({ + id: z.string().min(1), + object: z.literal("model"), + available: z.boolean(), + api_shapes: z.array(z.string().min(1)), + price_range: z.object({ + unit: z.literal("ndollars_per_mtok"), + currency: z.literal("USD"), + ceiling: RetailCeiling, + }).passthrough().optional(), +}).passthrough(); + +export const SaygmResponse = z.object({ + object: z.literal("list"), + data: z.array(SaygmModel), +}).passthrough(); + +export type SaygmModel = z.infer; + +export const saygm = { + id: "saygm", + name: "SayGM", + modelsDir: "providers/saygm/models", + // The live inventory can change with miner supply. Until the API publishes + // durable supply depth, only update models that were reviewed into the + // catalog and retain them through temporary outages. + skipCreates: true, + deleteMissing: false, + trackMissingModels: false, + sourceID(model) { + return model.id; + }, + skippedNotice(ids) { + if (ids.length === 0) return []; + return [ + `${ids.length} SayGM models were not created because this sync is update-only until the public API exposes durable miner depth.`, + `Skipped remote IDs: ${ids.map((id) => `\`${id}\``).join(", ")}`, + ]; + }, + missingNotice(paths) { + if (paths.length === 0) return []; + return [ + `${paths.length} reviewed SayGM models were retained despite being absent from the current live response.`, + `Retained local models: ${paths.map((item) => `\`${item.replace(/\.toml$/, "")}\``).join(", ")}`, + ]; + }, + async fetchModels() { + return fetchSaygmModels(); + }, + parseModels(raw) { + return SaygmResponse.parse(raw).data; + }, + translateModel(model, context) { + if (context.existing(model.id) === undefined) return undefined; + const authored = context.authored(model.id); + if (authored === undefined) { + throw new Error(`SayGM model ${model.id} has no authored catalog entry`); + } + return { + id: model.id, + model: buildSaygmModel(model, authored), + }; + }, +} satisfies SyncProvider; + +export async function fetchSaygmModels(fetcher: typeof fetch = fetch) { + const response = await fetcher(API_ENDPOINT); + if (!response.ok) { + throw new Error(`SayGM models request failed: ${response.status} ${response.statusText}`); + } + return SaygmResponse.parse(await response.json()); +} + +export function buildSaygmModel(model: SaygmModel, existing: ExistingModel): SyncedModel { + const ceiling = model.price_range?.ceiling; + if (ceiling === undefined) { + throw new Error(`SayGM model ${model.id} has no published retail ceiling`); + } + + const dimensions = ceiling.dimensions; + const cost: NonNullable = { + input: usdPerMtok(dimensions.input_per_mtok_ndollars), + output: usdPerMtok(dimensions.output_per_mtok_ndollars), + cache_read: optionalUsdPerMtok(dimensions.cache_read_per_mtok_ndollars), + // models.dev has one cache-write field; its provider catalogs conventionally + // use Anthropic's standard five-minute write rate. + cache_write: optionalUsdPerMtok(dimensions.cache_write_5m_per_mtok_ndollars), + input_audio: optionalUsdPerMtok(dimensions.audio_input_per_mtok_ndollars), + output_audio: optionalUsdPerMtok(dimensions.audio_output_per_mtok_ndollars), + }; + + if (dimensions.long_context_threshold_tokens !== undefined) { + const longInput = dimensions.long_context_input_per_mtok_ndollars; + const longOutput = dimensions.long_context_output_per_mtok_ndollars; + if (longInput === undefined || longOutput === undefined) { + throw new Error(`SayGM model ${model.id} has incomplete long-context pricing`); + } + cost.tiers = [{ + tier: { type: "context", size: dimensions.long_context_threshold_tokens }, + input: usdPerMtok(longInput), + output: usdPerMtok(longOutput), + }]; + } + + return { ...existing, cost } as SyncedModel; +} + +export function usdPerMtok(ndollars: number) { + return ndollars / NDOLLARS_PER_DOLLAR; +} + +function optionalUsdPerMtok(ndollars: number | undefined) { + return ndollars === undefined ? undefined : usdPerMtok(ndollars); +} diff --git a/packages/core/test/sync.test.ts b/packages/core/test/sync.test.ts index 454a2036580..d2a9206ce22 100644 --- a/packages/core/test/sync.test.ts +++ b/packages/core/test/sync.test.ts @@ -75,6 +75,13 @@ import { import { openai, parseOpenAIModels } from "../src/sync/providers/openai.js"; import { ofox } from "../src/sync/providers/ofox.js"; import { pioneer } from "../src/sync/providers/pioneer.js"; +import { + buildSaygmModel, + saygm, + SaygmResponse, + type SaygmModel, + usdPerMtok, +} from "../src/sync/providers/saygm.js"; import { google, shouldTrackGoogleModel } from "../src/sync/providers/google.js"; import { buildTinfoilModel, tinfoil, type TinfoilModel } from "../src/sync/providers/tinfoil.js"; import { resolveVeniceBaseModel } from "../src/sync/providers/venice.js"; @@ -198,6 +205,100 @@ function readyInceptronModel(overrides: Partial = {}): ReadyInce })[0]!; } +function saygmModel(overrides: Partial = {}): SaygmModel { + return { + id: "gpt-5.4", + object: "model", + available: true, + api_shapes: ["chat.completions", "responses"], + price_range: { + unit: "ndollars_per_mtok", + currency: "USD", + ceiling: { + basis: "published_retail", + dimensions: { + input_per_mtok_ndollars: 2_500_000_000, + output_per_mtok_ndollars: 15_000_000_000, + cache_read_per_mtok_ndollars: 250_000_000, + long_context_threshold_tokens: 272_000, + long_context_input_per_mtok_ndollars: 5_000_000_000, + long_context_output_per_mtok_ndollars: 22_500_000_000, + }, + }, + }, + ...overrides, + }; +} + +test("converts SayGM retail nanodollars into models.dev USD per Mtok costs", () => { + const built = buildSaygmModel(saygmModel(), { + base_model: "openai/gpt-5.4", + base_model_omit: ["cost"], + reasoning_options: [{ type: "effort", values: ["none", "low", "high"] }], + }); + + expect(built).toMatchObject({ + base_model: "openai/gpt-5.4", + base_model_omit: ["cost"], + cost: { + input: 2.5, + output: 15, + cache_read: 0.25, + tiers: [{ tier: { type: "context", size: 272_000 }, input: 5, output: 22.5 }], + }, + }); + expect(usdPerMtok(1)).toBe(0.000000001); +}); + +test("uses SayGM's five-minute cache-write rate for models.dev", () => { + const built = buildSaygmModel(saygmModel({ + id: "claude-haiku-4-5", + api_shapes: ["messages"], + price_range: { + unit: "ndollars_per_mtok", + currency: "USD", + ceiling: { + basis: "published_retail", + dimensions: { + input_per_mtok_ndollars: 1_000_000_000, + output_per_mtok_ndollars: 5_000_000_000, + cache_read_per_mtok_ndollars: 100_000_000, + cache_write_5m_per_mtok_ndollars: 1_250_000_000, + cache_write_1h_per_mtok_ndollars: 2_000_000_000, + }, + }, + }, + }), { base_model: "anthropic/claude-haiku-4-5", base_model_omit: ["cost"] }); + + expect(built).toMatchObject({ + cost: { input: 1, output: 5, cache_read: 0.1, cache_write: 1.25 }, + }); +}); + +test("rejects incomplete or non-retail SayGM pricing", () => { + const valid = saygmModel(); + const missingLongOutput = structuredClone(valid); + delete missingLongOutput.price_range!.ceiling.dimensions.long_context_output_per_mtok_ndollars; + expect(() => SaygmResponse.parse({ object: "list", data: [missingLongOutput] })).toThrow( + "Long-context pricing requires a threshold plus input and output prices", + ); + + const floorOnly = { + ...valid, + price_range: { + ...valid.price_range!, + ceiling: { ...valid.price_range!.ceiling, basis: "cheapest_eligible_offer" }, + }, + }; + expect(() => SaygmResponse.parse({ object: "list", data: [floorOnly] })).toThrow(); +}); + +test("keeps SayGM model lifecycle changes review-only", () => { + expect(saygm.skipCreates).toBe(true); + expect(saygm.deleteMissing).toBe(false); + expect(saygm.trackMissingModels).toBe(false); +}); + test("builds current Inceptron models from explicit base metadata", () => { const models = parseInceptronModels({ object: "list", diff --git a/providers/saygm/models/claude-fable-5.toml b/providers/saygm/models/claude-fable-5.toml index e615f05e65a..f40f2cea432 100644 --- a/providers/saygm/models/claude-fable-5.toml +++ b/providers/saygm/models/claude-fable-5.toml @@ -5,6 +5,12 @@ base_model_omit = ["cost"] type = "effort" values = ["low", "medium", "high", "xhigh", "max"] +[cost] +input = 10 +output = 50 +cache_read = 1 +cache_write = 12.5 + [provider] npm = "@ai-sdk/anthropic" api = "https://api.saygm.com/v1" diff --git a/providers/saygm/models/claude-haiku-4-5.toml b/providers/saygm/models/claude-haiku-4-5.toml index 3a3c06bd9bd..8bfd8a33326 100644 --- a/providers/saygm/models/claude-haiku-4-5.toml +++ b/providers/saygm/models/claude-haiku-4-5.toml @@ -5,6 +5,12 @@ base_model_omit = ["cost"] type = "budget_tokens" min = 1_024 +[cost] +input = 1 +output = 5 +cache_read = 0.1 +cache_write = 1.25 + [provider] npm = "@ai-sdk/anthropic" api = "https://api.saygm.com/v1" diff --git a/providers/saygm/models/claude-opus-4-7.toml b/providers/saygm/models/claude-opus-4-7.toml index 2af3fdc1e18..dbdfe4581cc 100644 --- a/providers/saygm/models/claude-opus-4-7.toml +++ b/providers/saygm/models/claude-opus-4-7.toml @@ -5,6 +5,12 @@ base_model_omit = ["cost"] type = "effort" values = ["low", "medium", "high", "xhigh", "max"] +[cost] +input = 5 +output = 25 +cache_read = 0.5 +cache_write = 6.25 + [provider] npm = "@ai-sdk/anthropic" api = "https://api.saygm.com/v1" diff --git a/providers/saygm/models/claude-opus-4-8.toml b/providers/saygm/models/claude-opus-4-8.toml index ba93d19677b..753cb7b9fa2 100644 --- a/providers/saygm/models/claude-opus-4-8.toml +++ b/providers/saygm/models/claude-opus-4-8.toml @@ -5,6 +5,12 @@ base_model_omit = ["cost"] type = "effort" values = ["low", "medium", "high", "xhigh", "max"] +[cost] +input = 5 +output = 25 +cache_read = 0.5 +cache_write = 6.25 + [provider] npm = "@ai-sdk/anthropic" api = "https://api.saygm.com/v1" diff --git a/providers/saygm/models/claude-opus-5.toml b/providers/saygm/models/claude-opus-5.toml index 277e5bb4eb8..002457c77d4 100644 --- a/providers/saygm/models/claude-opus-5.toml +++ b/providers/saygm/models/claude-opus-5.toml @@ -5,6 +5,12 @@ base_model_omit = ["cost"] type = "effort" values = ["low", "medium", "high", "xhigh", "max"] +[cost] +input = 5 +output = 25 +cache_read = 0.5 +cache_write = 6.25 + [provider] npm = "@ai-sdk/anthropic" api = "https://api.saygm.com/v1" diff --git a/providers/saygm/models/claude-sonnet-4-6.toml b/providers/saygm/models/claude-sonnet-4-6.toml index ea3a500495a..31f8dcdc1c2 100644 --- a/providers/saygm/models/claude-sonnet-4-6.toml +++ b/providers/saygm/models/claude-sonnet-4-6.toml @@ -9,6 +9,12 @@ values = ["low", "medium", "high", "max"] type = "budget_tokens" min = 1_024 +[cost] +input = 3 +output = 10 +cache_read = 0.3 +cache_write = 3.75 + [provider] npm = "@ai-sdk/anthropic" api = "https://api.saygm.com/v1" diff --git a/providers/saygm/models/claude-sonnet-5.toml b/providers/saygm/models/claude-sonnet-5.toml index 2a619b98fa9..6b903cd0006 100644 --- a/providers/saygm/models/claude-sonnet-5.toml +++ b/providers/saygm/models/claude-sonnet-5.toml @@ -10,6 +10,12 @@ type = "toggle" type = "effort" values = ["low", "medium", "high", "xhigh", "max"] +[cost] +input = 3 +output = 10 +cache_read = 0.3 +cache_write = 3.75 + [provider] npm = "@ai-sdk/anthropic" api = "https://api.saygm.com/v1" diff --git a/providers/saygm/models/gpt-5.4-mini.toml b/providers/saygm/models/gpt-5.4-mini.toml index faf487973e9..d0aacdb0756 100644 --- a/providers/saygm/models/gpt-5.4-mini.toml +++ b/providers/saygm/models/gpt-5.4-mini.toml @@ -4,3 +4,8 @@ base_model_omit = ["cost"] [[reasoning_options]] type = "effort" values = ["none", "low", "medium", "high", "xhigh"] + +[cost] +input = 0.75 +output = 4.5 +cache_read = 0.075 diff --git a/providers/saygm/models/gpt-5.4-nano.toml b/providers/saygm/models/gpt-5.4-nano.toml index 17c1b7a1add..3608e243996 100644 --- a/providers/saygm/models/gpt-5.4-nano.toml +++ b/providers/saygm/models/gpt-5.4-nano.toml @@ -4,3 +4,8 @@ base_model_omit = ["cost"] [[reasoning_options]] type = "effort" values = ["none", "low", "medium", "high", "xhigh"] + +[cost] +input = 0.2 +output = 1.25 +cache_read = 0.02 diff --git a/providers/saygm/models/gpt-5.4.toml b/providers/saygm/models/gpt-5.4.toml index 8d2d86e7283..8d95de1d546 100644 --- a/providers/saygm/models/gpt-5.4.toml +++ b/providers/saygm/models/gpt-5.4.toml @@ -4,3 +4,13 @@ base_model_omit = ["cost"] [[reasoning_options]] type = "effort" values = ["none", "low", "medium", "high", "xhigh"] + +[cost] +input = 2.5 +output = 15 +cache_read = 0.25 + +[[cost.tiers]] +tier = { type = "context", size = 272_000 } +input = 5 +output = 22.5 diff --git a/providers/saygm/models/gpt-5.5-pro.toml b/providers/saygm/models/gpt-5.5-pro.toml index 1c0688dd50a..36f96511c67 100644 --- a/providers/saygm/models/gpt-5.5-pro.toml +++ b/providers/saygm/models/gpt-5.5-pro.toml @@ -6,6 +6,11 @@ base_model_omit = ["cost"] type = "effort" values = ["medium", "high", "xhigh"] +[cost] +input = 30 +output = 180 +cache_read = 3 + [provider] npm = "@ai-sdk/openai" api = "https://api.saygm.com/v1" diff --git a/providers/saygm/models/gpt-5.5.toml b/providers/saygm/models/gpt-5.5.toml index 2859b97f1d9..84e6fd006dd 100644 --- a/providers/saygm/models/gpt-5.5.toml +++ b/providers/saygm/models/gpt-5.5.toml @@ -4,3 +4,13 @@ base_model_omit = ["cost"] [[reasoning_options]] type = "effort" values = ["none", "low", "medium", "high", "xhigh"] + +[cost] +input = 5 +output = 30 +cache_read = 0.5 + +[[cost.tiers]] +tier = { type = "context", size = 272_000 } +input = 10 +output = 45 diff --git a/providers/saygm/models/gpt-5.6-luna.toml b/providers/saygm/models/gpt-5.6-luna.toml index 85556d59e51..2839464fa51 100644 --- a/providers/saygm/models/gpt-5.6-luna.toml +++ b/providers/saygm/models/gpt-5.6-luna.toml @@ -4,3 +4,13 @@ base_model_omit = ["cost"] [[reasoning_options]] type = "effort" values = ["none", "low", "medium", "high", "xhigh", "max"] + +[cost] +input = 0.2 +output = 1.2 +cache_read = 0.02 + +[[cost.tiers]] +tier = { type = "context", size = 272_000 } +input = 0.4 +output = 1.8 diff --git a/providers/saygm/models/gpt-5.6-sol.toml b/providers/saygm/models/gpt-5.6-sol.toml index c561356545b..6efa7c1184a 100644 --- a/providers/saygm/models/gpt-5.6-sol.toml +++ b/providers/saygm/models/gpt-5.6-sol.toml @@ -4,3 +4,13 @@ base_model_omit = ["cost"] [[reasoning_options]] type = "effort" values = ["none", "low", "medium", "high", "xhigh", "max"] + +[cost] +input = 5 +output = 30 +cache_read = 0.5 + +[[cost.tiers]] +tier = { type = "context", size = 272_000 } +input = 10 +output = 45 diff --git a/providers/saygm/models/gpt-5.6-terra.toml b/providers/saygm/models/gpt-5.6-terra.toml index a6f78be44bb..519d848c810 100644 --- a/providers/saygm/models/gpt-5.6-terra.toml +++ b/providers/saygm/models/gpt-5.6-terra.toml @@ -4,3 +4,13 @@ base_model_omit = ["cost"] [[reasoning_options]] type = "effort" values = ["none", "low", "medium", "high", "xhigh", "max"] + +[cost] +input = 2 +output = 12 +cache_read = 0.2 + +[[cost.tiers]] +tier = { type = "context", size = 272_000 } +input = 4 +output = 18 diff --git a/providers/saygm/models/o3.toml b/providers/saygm/models/o3.toml index 7d088ec56fd..0f19c302bfc 100644 --- a/providers/saygm/models/o3.toml +++ b/providers/saygm/models/o3.toml @@ -4,3 +4,8 @@ base_model_omit = ["cost"] [[reasoning_options]] type = "effort" values = ["low", "medium", "high"] + +[cost] +input = 2 +output = 8 +cache_read = 0.5 diff --git a/providers/saygm/models/o4-mini.toml b/providers/saygm/models/o4-mini.toml index 3658f9b2918..aafaa1af170 100644 --- a/providers/saygm/models/o4-mini.toml +++ b/providers/saygm/models/o4-mini.toml @@ -4,3 +4,8 @@ base_model_omit = ["cost"] [[reasoning_options]] type = "effort" values = ["low", "medium", "high"] + +[cost] +input = 1.1 +output = 4.4 +cache_read = 0.275 From 9ddf36e95ef763d92cf3a4fb1eb86df1c20ec551 Mon Sep 17 00:00:00 2001 From: Mark Davison <6168730+markdavison@users.noreply.github.com> Date: Thu, 13 Aug 2026 14:47:43 +0100 Subject: [PATCH 9/9] fix(saygm): retain authored pricing in generated catalog --- packages/core/test/sync.test.ts | 4 +--- providers/saygm/models/claude-fable-5.toml | 1 - providers/saygm/models/claude-haiku-4-5.toml | 1 - providers/saygm/models/claude-opus-4-7.toml | 1 - providers/saygm/models/claude-opus-4-8.toml | 1 - providers/saygm/models/claude-opus-5.toml | 1 - providers/saygm/models/claude-sonnet-4-6.toml | 1 - providers/saygm/models/claude-sonnet-5.toml | 1 - providers/saygm/models/gpt-5.4-mini.toml | 1 - providers/saygm/models/gpt-5.4-nano.toml | 1 - providers/saygm/models/gpt-5.4.toml | 1 - providers/saygm/models/gpt-5.5-pro.toml | 1 - providers/saygm/models/gpt-5.5.toml | 1 - providers/saygm/models/gpt-5.6-luna.toml | 1 - providers/saygm/models/gpt-5.6-sol.toml | 1 - providers/saygm/models/gpt-5.6-terra.toml | 1 - providers/saygm/models/o3.toml | 1 - providers/saygm/models/o4-mini.toml | 1 - 18 files changed, 1 insertion(+), 20 deletions(-) diff --git a/packages/core/test/sync.test.ts b/packages/core/test/sync.test.ts index d2a9206ce22..1bb2a57e8e8 100644 --- a/packages/core/test/sync.test.ts +++ b/packages/core/test/sync.test.ts @@ -233,13 +233,11 @@ function saygmModel(overrides: Partial = {}): SaygmModel { test("converts SayGM retail nanodollars into models.dev USD per Mtok costs", () => { const built = buildSaygmModel(saygmModel(), { base_model: "openai/gpt-5.4", - base_model_omit: ["cost"], reasoning_options: [{ type: "effort", values: ["none", "low", "high"] }], }); expect(built).toMatchObject({ base_model: "openai/gpt-5.4", - base_model_omit: ["cost"], cost: { input: 2.5, output: 15, @@ -268,7 +266,7 @@ test("uses SayGM's five-minute cache-write rate for models.dev", () => { }, }, }, - }), { base_model: "anthropic/claude-haiku-4-5", base_model_omit: ["cost"] }); + }), { base_model: "anthropic/claude-haiku-4-5" }); expect(built).toMatchObject({ cost: { input: 1, output: 5, cache_read: 0.1, cache_write: 1.25 }, diff --git a/providers/saygm/models/claude-fable-5.toml b/providers/saygm/models/claude-fable-5.toml index f40f2cea432..3f2aa5d48dc 100644 --- a/providers/saygm/models/claude-fable-5.toml +++ b/providers/saygm/models/claude-fable-5.toml @@ -1,5 +1,4 @@ base_model = "anthropic/claude-fable-5" -base_model_omit = ["cost"] [[reasoning_options]] type = "effort" diff --git a/providers/saygm/models/claude-haiku-4-5.toml b/providers/saygm/models/claude-haiku-4-5.toml index 8bfd8a33326..cc3760232b5 100644 --- a/providers/saygm/models/claude-haiku-4-5.toml +++ b/providers/saygm/models/claude-haiku-4-5.toml @@ -1,5 +1,4 @@ base_model = "anthropic/claude-haiku-4-5" -base_model_omit = ["cost"] [[reasoning_options]] type = "budget_tokens" diff --git a/providers/saygm/models/claude-opus-4-7.toml b/providers/saygm/models/claude-opus-4-7.toml index dbdfe4581cc..a9780cb2673 100644 --- a/providers/saygm/models/claude-opus-4-7.toml +++ b/providers/saygm/models/claude-opus-4-7.toml @@ -1,5 +1,4 @@ base_model = "anthropic/claude-opus-4-7" -base_model_omit = ["cost"] [[reasoning_options]] type = "effort" diff --git a/providers/saygm/models/claude-opus-4-8.toml b/providers/saygm/models/claude-opus-4-8.toml index 753cb7b9fa2..b0110c1cb8c 100644 --- a/providers/saygm/models/claude-opus-4-8.toml +++ b/providers/saygm/models/claude-opus-4-8.toml @@ -1,5 +1,4 @@ base_model = "anthropic/claude-opus-4-8" -base_model_omit = ["cost"] [[reasoning_options]] type = "effort" diff --git a/providers/saygm/models/claude-opus-5.toml b/providers/saygm/models/claude-opus-5.toml index 002457c77d4..66637ab80a9 100644 --- a/providers/saygm/models/claude-opus-5.toml +++ b/providers/saygm/models/claude-opus-5.toml @@ -1,5 +1,4 @@ base_model = "anthropic/claude-opus-5" -base_model_omit = ["cost"] [[reasoning_options]] type = "effort" diff --git a/providers/saygm/models/claude-sonnet-4-6.toml b/providers/saygm/models/claude-sonnet-4-6.toml index 31f8dcdc1c2..5d7c4e5c1c0 100644 --- a/providers/saygm/models/claude-sonnet-4-6.toml +++ b/providers/saygm/models/claude-sonnet-4-6.toml @@ -1,5 +1,4 @@ base_model = "anthropic/claude-sonnet-4-6" -base_model_omit = ["cost"] [[reasoning_options]] type = "effort" diff --git a/providers/saygm/models/claude-sonnet-5.toml b/providers/saygm/models/claude-sonnet-5.toml index 6b903cd0006..944f699e5aa 100644 --- a/providers/saygm/models/claude-sonnet-5.toml +++ b/providers/saygm/models/claude-sonnet-5.toml @@ -1,7 +1,6 @@ # Toggle: thinking.type = enabled|disabled (Anthropic Messages wire; SayGM mirrors upstream) # Effort: output_config.effort = low|medium|high|xhigh|max base_model = "anthropic/claude-sonnet-5" -base_model_omit = ["cost"] [[reasoning_options]] type = "toggle" diff --git a/providers/saygm/models/gpt-5.4-mini.toml b/providers/saygm/models/gpt-5.4-mini.toml index d0aacdb0756..0744ddc0397 100644 --- a/providers/saygm/models/gpt-5.4-mini.toml +++ b/providers/saygm/models/gpt-5.4-mini.toml @@ -1,5 +1,4 @@ base_model = "openai/gpt-5.4-mini" -base_model_omit = ["cost"] [[reasoning_options]] type = "effort" diff --git a/providers/saygm/models/gpt-5.4-nano.toml b/providers/saygm/models/gpt-5.4-nano.toml index 3608e243996..8d6d5218295 100644 --- a/providers/saygm/models/gpt-5.4-nano.toml +++ b/providers/saygm/models/gpt-5.4-nano.toml @@ -1,5 +1,4 @@ base_model = "openai/gpt-5.4-nano" -base_model_omit = ["cost"] [[reasoning_options]] type = "effort" diff --git a/providers/saygm/models/gpt-5.4.toml b/providers/saygm/models/gpt-5.4.toml index 8d95de1d546..bda43f57d60 100644 --- a/providers/saygm/models/gpt-5.4.toml +++ b/providers/saygm/models/gpt-5.4.toml @@ -1,5 +1,4 @@ base_model = "openai/gpt-5.4" -base_model_omit = ["cost"] [[reasoning_options]] type = "effort" diff --git a/providers/saygm/models/gpt-5.5-pro.toml b/providers/saygm/models/gpt-5.5-pro.toml index 36f96511c67..ccd3238408b 100644 --- a/providers/saygm/models/gpt-5.5-pro.toml +++ b/providers/saygm/models/gpt-5.5-pro.toml @@ -1,6 +1,5 @@ # Served only on the Responses API (SayGM /v1/models api_shapes = ["responses"]). base_model = "openai/gpt-5.5-pro" -base_model_omit = ["cost"] [[reasoning_options]] type = "effort" diff --git a/providers/saygm/models/gpt-5.5.toml b/providers/saygm/models/gpt-5.5.toml index 84e6fd006dd..197bb4ccc5f 100644 --- a/providers/saygm/models/gpt-5.5.toml +++ b/providers/saygm/models/gpt-5.5.toml @@ -1,5 +1,4 @@ base_model = "openai/gpt-5.5" -base_model_omit = ["cost"] [[reasoning_options]] type = "effort" diff --git a/providers/saygm/models/gpt-5.6-luna.toml b/providers/saygm/models/gpt-5.6-luna.toml index 2839464fa51..628385cddcb 100644 --- a/providers/saygm/models/gpt-5.6-luna.toml +++ b/providers/saygm/models/gpt-5.6-luna.toml @@ -1,5 +1,4 @@ base_model = "openai/gpt-5.6-luna" -base_model_omit = ["cost"] [[reasoning_options]] type = "effort" diff --git a/providers/saygm/models/gpt-5.6-sol.toml b/providers/saygm/models/gpt-5.6-sol.toml index 6efa7c1184a..16e77d90fd9 100644 --- a/providers/saygm/models/gpt-5.6-sol.toml +++ b/providers/saygm/models/gpt-5.6-sol.toml @@ -1,5 +1,4 @@ base_model = "openai/gpt-5.6-sol" -base_model_omit = ["cost"] [[reasoning_options]] type = "effort" diff --git a/providers/saygm/models/gpt-5.6-terra.toml b/providers/saygm/models/gpt-5.6-terra.toml index 519d848c810..2ae2aa742e2 100644 --- a/providers/saygm/models/gpt-5.6-terra.toml +++ b/providers/saygm/models/gpt-5.6-terra.toml @@ -1,5 +1,4 @@ base_model = "openai/gpt-5.6-terra" -base_model_omit = ["cost"] [[reasoning_options]] type = "effort" diff --git a/providers/saygm/models/o3.toml b/providers/saygm/models/o3.toml index 0f19c302bfc..977bf918256 100644 --- a/providers/saygm/models/o3.toml +++ b/providers/saygm/models/o3.toml @@ -1,5 +1,4 @@ base_model = "openai/o3" -base_model_omit = ["cost"] [[reasoning_options]] type = "effort" diff --git a/providers/saygm/models/o4-mini.toml b/providers/saygm/models/o4-mini.toml index aafaa1af170..75807e417c1 100644 --- a/providers/saygm/models/o4-mini.toml +++ b/providers/saygm/models/o4-mini.toml @@ -1,5 +1,4 @@ base_model = "openai/o4-mini" -base_model_omit = ["cost"] [[reasoning_options]] type = "effort"