@jacobbd/relay-ai 0.9.7 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-BJ4AE3PS.js → chunk-2NXLK3O6.js} +174 -20
- package/dist/chunk-2NXLK3O6.js.map +1 -0
- package/dist/{chunk-NYKVDBQC.js → chunk-P4IS6537.js} +7 -1
- package/dist/chunk-P4IS6537.js.map +1 -0
- package/dist/cli.js +67 -13
- package/dist/cli.js.map +1 -1
- package/dist/core/index.d.ts +8 -0
- package/dist/core/index.js +510 -4
- package/dist/core/index.js.map +1 -1
- package/dist/{provider-templates-CGWE66TD.js → provider-templates-7M24FAAI.js} +2 -2
- package/dist/{ui-command-NM4MNZLO.js → ui-command-6ZMM5K5K.js} +4 -4
- package/package.json +1 -1
- package/dist/chunk-BJ4AE3PS.js.map +0 -1
- package/dist/chunk-NYKVDBQC.js.map +0 -1
- /package/dist/{provider-templates-CGWE66TD.js.map → provider-templates-7M24FAAI.js.map} +0 -0
- /package/dist/{ui-command-NM4MNZLO.js.map → ui-command-6ZMM5K5K.js.map} +0 -0
package/dist/core/index.d.ts
CHANGED
|
@@ -16,6 +16,13 @@ type RelayCoreErrorCode = 'INVALID_ROUTE_ID' | 'ROUTE_NOT_FOUND' | 'PROVIDER_DIS
|
|
|
16
16
|
*/
|
|
17
17
|
type RelayReasoningLevel = 'off' | 'none' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh' | 'max';
|
|
18
18
|
interface CreateRelayModelOptions {
|
|
19
|
+
/**
|
|
20
|
+
* Optional stable conversation identifier for OpenCode Go. Relay sends this
|
|
21
|
+
* as `x-opencode-session` on every upstream model call for the returned model.
|
|
22
|
+
* The value is treated as opaque and bounded to OpenCode's 256-character
|
|
23
|
+
* header limit. Per-call `headers` supplied to the AI SDK take precedence.
|
|
24
|
+
*/
|
|
25
|
+
sessionId?: string;
|
|
19
26
|
/**
|
|
20
27
|
* Optional sanitized transport diagnostics. Messages contain event types,
|
|
21
28
|
* field names, counts, and lengths — never credentials, prompts, or bodies.
|
|
@@ -37,6 +44,7 @@ interface RelayModelDescriptor {
|
|
|
37
44
|
routeId: RelayRouteId;
|
|
38
45
|
providerId: string;
|
|
39
46
|
providerName: string;
|
|
47
|
+
providerShortName: string;
|
|
40
48
|
modelId: string;
|
|
41
49
|
upstreamModelId: string;
|
|
42
50
|
displayName: string;
|
package/dist/core/index.js
CHANGED
|
@@ -50,7 +50,7 @@ import { join as join2 } from "path";
|
|
|
50
50
|
// package.json
|
|
51
51
|
var package_default = {
|
|
52
52
|
name: "@jacobbd/relay-ai",
|
|
53
|
-
version: "0.
|
|
53
|
+
version: "0.10.0",
|
|
54
54
|
publishConfig: {
|
|
55
55
|
access: "public"
|
|
56
56
|
},
|
|
@@ -1739,6 +1739,431 @@ function saveRegistry(registry, path = getProvidersPath()) {
|
|
|
1739
1739
|
renameSync2(tmp, path);
|
|
1740
1740
|
}
|
|
1741
1741
|
|
|
1742
|
+
// src/provider-templates.ts
|
|
1743
|
+
var PROVIDER_TEMPLATES = [
|
|
1744
|
+
{
|
|
1745
|
+
id: "cline-pass",
|
|
1746
|
+
name: "ClinePass",
|
|
1747
|
+
authType: "api",
|
|
1748
|
+
authMethods: ["api", "oauth"],
|
|
1749
|
+
npm: "@ai-sdk/openai-compatible",
|
|
1750
|
+
defaultBaseUrl: "https://api.cline.bot/api/v1",
|
|
1751
|
+
signupUrl: "https://app.cline.bot",
|
|
1752
|
+
modelSource: "cline-recommended",
|
|
1753
|
+
headers: { "HTTP-Referer": "https://cline.bot", "X-Title": "Cline" },
|
|
1754
|
+
supported: true,
|
|
1755
|
+
subscriptionRisk: true
|
|
1756
|
+
},
|
|
1757
|
+
{
|
|
1758
|
+
id: "groq",
|
|
1759
|
+
name: "Groq",
|
|
1760
|
+
authType: "api",
|
|
1761
|
+
npm: "@ai-sdk/groq",
|
|
1762
|
+
defaultBaseUrl: "https://api.groq.com/openai/v1",
|
|
1763
|
+
signupUrl: "https://console.groq.com/keys",
|
|
1764
|
+
modelSource: "api-list",
|
|
1765
|
+
supported: true
|
|
1766
|
+
},
|
|
1767
|
+
{
|
|
1768
|
+
id: "nvidia",
|
|
1769
|
+
name: "Nvidia",
|
|
1770
|
+
authType: "api",
|
|
1771
|
+
npm: "@ai-sdk/openai-compatible",
|
|
1772
|
+
defaultBaseUrl: "https://integrate.api.nvidia.com/v1",
|
|
1773
|
+
signupUrl: "https://build.nvidia.com",
|
|
1774
|
+
modelSource: "api-list",
|
|
1775
|
+
supported: true
|
|
1776
|
+
},
|
|
1777
|
+
{
|
|
1778
|
+
id: "mistral",
|
|
1779
|
+
name: "Mistral",
|
|
1780
|
+
authType: "api",
|
|
1781
|
+
npm: "@ai-sdk/mistral",
|
|
1782
|
+
defaultBaseUrl: "https://api.mistral.ai/v1",
|
|
1783
|
+
signupUrl: "https://console.mistral.ai/api-keys",
|
|
1784
|
+
modelSource: "api-list",
|
|
1785
|
+
supported: true
|
|
1786
|
+
},
|
|
1787
|
+
{
|
|
1788
|
+
id: "togetherai",
|
|
1789
|
+
name: "Together AI",
|
|
1790
|
+
authType: "api",
|
|
1791
|
+
npm: "@ai-sdk/togetherai",
|
|
1792
|
+
defaultBaseUrl: "https://api.together.xyz/v1",
|
|
1793
|
+
signupUrl: "https://api.together.xyz/settings/api-keys",
|
|
1794
|
+
modelSource: "api-list",
|
|
1795
|
+
supported: true
|
|
1796
|
+
},
|
|
1797
|
+
{
|
|
1798
|
+
id: "cerebras",
|
|
1799
|
+
name: "Cerebras",
|
|
1800
|
+
authType: "api",
|
|
1801
|
+
npm: "@ai-sdk/cerebras",
|
|
1802
|
+
defaultBaseUrl: "https://api.cerebras.ai/v1",
|
|
1803
|
+
signupUrl: "https://cloud.cerebras.ai",
|
|
1804
|
+
modelSource: "api-list",
|
|
1805
|
+
supported: true
|
|
1806
|
+
},
|
|
1807
|
+
{
|
|
1808
|
+
id: "deepinfra",
|
|
1809
|
+
name: "DeepInfra",
|
|
1810
|
+
authType: "api",
|
|
1811
|
+
npm: "@ai-sdk/deepinfra",
|
|
1812
|
+
defaultBaseUrl: "https://api.deepinfra.com/v1/openai",
|
|
1813
|
+
signupUrl: "https://deepinfra.com/dash/api_keys",
|
|
1814
|
+
modelSource: "api-list",
|
|
1815
|
+
supported: true
|
|
1816
|
+
},
|
|
1817
|
+
{
|
|
1818
|
+
id: "deepseek",
|
|
1819
|
+
name: "DeepSeek",
|
|
1820
|
+
authType: "api",
|
|
1821
|
+
npm: "@ai-sdk/openai-compatible",
|
|
1822
|
+
defaultBaseUrl: "https://api.deepseek.com/v1",
|
|
1823
|
+
signupUrl: "https://platform.deepseek.com",
|
|
1824
|
+
modelSource: "api-list",
|
|
1825
|
+
supported: true
|
|
1826
|
+
},
|
|
1827
|
+
{
|
|
1828
|
+
id: "zhipu",
|
|
1829
|
+
name: "Zhipu AI (GLM)",
|
|
1830
|
+
authType: "api",
|
|
1831
|
+
npm: "@ai-sdk/openai-compatible",
|
|
1832
|
+
defaultBaseUrl: "https://open.bigmodel.cn/api/paas/v4",
|
|
1833
|
+
signupUrl: "https://open.bigmodel.cn",
|
|
1834
|
+
modelSource: "api-list",
|
|
1835
|
+
supported: true
|
|
1836
|
+
},
|
|
1837
|
+
{
|
|
1838
|
+
id: "moonshot",
|
|
1839
|
+
name: "Moonshot (Kimi)",
|
|
1840
|
+
authType: "api",
|
|
1841
|
+
npm: "@ai-sdk/openai-compatible",
|
|
1842
|
+
defaultBaseUrl: "https://api.moonshot.cn/v1",
|
|
1843
|
+
signupUrl: "https://platform.moonshot.cn",
|
|
1844
|
+
modelSource: "api-list",
|
|
1845
|
+
supported: true
|
|
1846
|
+
},
|
|
1847
|
+
{
|
|
1848
|
+
id: "moonshot-global",
|
|
1849
|
+
name: "Moonshot Global (kimi.ai)",
|
|
1850
|
+
authType: "api",
|
|
1851
|
+
npm: "@ai-sdk/openai-compatible",
|
|
1852
|
+
defaultBaseUrl: "https://api.moonshot.ai/v1",
|
|
1853
|
+
signupUrl: "https://platform.kimi.ai",
|
|
1854
|
+
modelSource: "api-list",
|
|
1855
|
+
supported: true
|
|
1856
|
+
},
|
|
1857
|
+
{
|
|
1858
|
+
id: "kimi-code",
|
|
1859
|
+
name: "Kimi Code (Subscription Required)",
|
|
1860
|
+
authType: "api",
|
|
1861
|
+
npm: "@ai-sdk/openai-compatible",
|
|
1862
|
+
defaultBaseUrl: "https://api.kimi.com/coding/v1",
|
|
1863
|
+
modelSource: "static-seed",
|
|
1864
|
+
staticModels: [
|
|
1865
|
+
{ id: "kimi-for-coding", name: "Kimi Code K2.7 (Unified)" }
|
|
1866
|
+
],
|
|
1867
|
+
supported: true
|
|
1868
|
+
},
|
|
1869
|
+
{
|
|
1870
|
+
id: "xai",
|
|
1871
|
+
name: "xAI",
|
|
1872
|
+
authType: "api",
|
|
1873
|
+
npm: "@ai-sdk/xai",
|
|
1874
|
+
defaultBaseUrl: "https://api.x.ai/v1",
|
|
1875
|
+
signupUrl: "https://console.x.ai",
|
|
1876
|
+
modelSource: "api-list",
|
|
1877
|
+
supported: true
|
|
1878
|
+
},
|
|
1879
|
+
{
|
|
1880
|
+
id: "perplexity",
|
|
1881
|
+
name: "Perplexity",
|
|
1882
|
+
authType: "api",
|
|
1883
|
+
npm: "@ai-sdk/perplexity",
|
|
1884
|
+
defaultBaseUrl: "https://api.perplexity.ai",
|
|
1885
|
+
signupUrl: "https://www.perplexity.ai/settings/api",
|
|
1886
|
+
modelSource: "api-list",
|
|
1887
|
+
supported: true
|
|
1888
|
+
},
|
|
1889
|
+
{
|
|
1890
|
+
id: "cohere",
|
|
1891
|
+
name: "Cohere",
|
|
1892
|
+
authType: "api",
|
|
1893
|
+
npm: "@ai-sdk/cohere",
|
|
1894
|
+
defaultBaseUrl: "https://api.cohere.com/compatibility/v1",
|
|
1895
|
+
signupUrl: "https://dashboard.cohere.com/api-keys",
|
|
1896
|
+
modelSource: "api-list",
|
|
1897
|
+
supported: true
|
|
1898
|
+
},
|
|
1899
|
+
{
|
|
1900
|
+
id: "openai",
|
|
1901
|
+
name: "OpenAI",
|
|
1902
|
+
authType: "api",
|
|
1903
|
+
npm: "@ai-sdk/openai",
|
|
1904
|
+
defaultBaseUrl: "https://api.openai.com/v1",
|
|
1905
|
+
signupUrl: "https://platform.openai.com/api-keys",
|
|
1906
|
+
modelSource: "api-list",
|
|
1907
|
+
supported: true
|
|
1908
|
+
},
|
|
1909
|
+
{
|
|
1910
|
+
id: "google",
|
|
1911
|
+
name: "Google Gemini",
|
|
1912
|
+
authType: "api",
|
|
1913
|
+
npm: "@ai-sdk/google",
|
|
1914
|
+
defaultBaseUrl: "https://generativelanguage.googleapis.com/v1beta/openai",
|
|
1915
|
+
signupUrl: "https://aistudio.google.com/apikey",
|
|
1916
|
+
modelSource: "api-list",
|
|
1917
|
+
supported: true
|
|
1918
|
+
},
|
|
1919
|
+
{
|
|
1920
|
+
id: "alibaba",
|
|
1921
|
+
name: "Alibaba DashScope (China)",
|
|
1922
|
+
authType: "api",
|
|
1923
|
+
npm: "@ai-sdk/alibaba",
|
|
1924
|
+
defaultBaseUrl: "https://dashscope.aliyuncs.com/compatible-mode/v1",
|
|
1925
|
+
signupUrl: "https://dashscope.console.aliyun.com/apiKey",
|
|
1926
|
+
modelSource: "api-list",
|
|
1927
|
+
supported: true
|
|
1928
|
+
},
|
|
1929
|
+
{
|
|
1930
|
+
id: "qwen-cloud-token-plan",
|
|
1931
|
+
name: "Qwen Cloud (Token Plan)",
|
|
1932
|
+
shortName: "Qwen Cloud",
|
|
1933
|
+
authType: "api",
|
|
1934
|
+
npm: "@ai-sdk/alibaba",
|
|
1935
|
+
defaultBaseUrl: "https://token-plan.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1",
|
|
1936
|
+
signupUrl: "https://home.qwencloud.com/api-keys",
|
|
1937
|
+
modelSource: "api-list",
|
|
1938
|
+
supported: true
|
|
1939
|
+
},
|
|
1940
|
+
{
|
|
1941
|
+
id: "qwen-cloud-payg",
|
|
1942
|
+
name: "Qwen Cloud (Pay-As-You-Go)",
|
|
1943
|
+
shortName: "Qwen Cloud",
|
|
1944
|
+
authType: "api",
|
|
1945
|
+
npm: "@ai-sdk/alibaba",
|
|
1946
|
+
defaultBaseUrl: "https://dashscope-intl.aliyuncs.com/compatible-mode/v1",
|
|
1947
|
+
signupUrl: "https://home.qwencloud.com/api-keys",
|
|
1948
|
+
modelSource: "api-list",
|
|
1949
|
+
supported: true
|
|
1950
|
+
},
|
|
1951
|
+
{
|
|
1952
|
+
id: "openrouter",
|
|
1953
|
+
name: "OpenRouter",
|
|
1954
|
+
authType: "api",
|
|
1955
|
+
npm: "@openrouter/ai-sdk-provider",
|
|
1956
|
+
defaultBaseUrl: "https://openrouter.ai/api/v1",
|
|
1957
|
+
signupUrl: "https://openrouter.ai/keys",
|
|
1958
|
+
modelSource: "api-list",
|
|
1959
|
+
supported: true
|
|
1960
|
+
},
|
|
1961
|
+
{
|
|
1962
|
+
id: "kilo",
|
|
1963
|
+
name: "Kilo Code",
|
|
1964
|
+
authType: "api",
|
|
1965
|
+
npm: "@ai-sdk/openai-compatible",
|
|
1966
|
+
defaultBaseUrl: "https://api.kilo.ai/api/gateway",
|
|
1967
|
+
modelsPath: "/models",
|
|
1968
|
+
signupUrl: "https://app.kilo.ai",
|
|
1969
|
+
apiKeyOptional: true,
|
|
1970
|
+
anonymousFreeModels: true,
|
|
1971
|
+
modelSource: "api-list",
|
|
1972
|
+
supported: true
|
|
1973
|
+
},
|
|
1974
|
+
{
|
|
1975
|
+
id: "ollama",
|
|
1976
|
+
name: "Ollama",
|
|
1977
|
+
authType: "api",
|
|
1978
|
+
npm: "@ai-sdk/openai-compatible",
|
|
1979
|
+
defaultBaseUrl: "http://127.0.0.1:11434/v1",
|
|
1980
|
+
urlPrompt: "Ollama API Base URL:",
|
|
1981
|
+
apiKeyOptional: true,
|
|
1982
|
+
modelSource: "api-list",
|
|
1983
|
+
supported: true
|
|
1984
|
+
},
|
|
1985
|
+
{
|
|
1986
|
+
id: "lmstudio",
|
|
1987
|
+
name: "LM Studio",
|
|
1988
|
+
authType: "api",
|
|
1989
|
+
npm: "@ai-sdk/openai-compatible",
|
|
1990
|
+
defaultBaseUrl: "http://127.0.0.1:1234/v1",
|
|
1991
|
+
urlPrompt: "LM Studio API Base URL:",
|
|
1992
|
+
apiKeyOptional: true,
|
|
1993
|
+
modelSource: "api-list",
|
|
1994
|
+
supported: true
|
|
1995
|
+
},
|
|
1996
|
+
{
|
|
1997
|
+
id: "venice",
|
|
1998
|
+
name: "Venice AI",
|
|
1999
|
+
authType: "api",
|
|
2000
|
+
npm: "venice-ai-sdk-provider",
|
|
2001
|
+
defaultBaseUrl: "https://api.venice.ai/api/v1",
|
|
2002
|
+
signupUrl: "https://venice.ai/settings/api",
|
|
2003
|
+
modelSource: "api-list",
|
|
2004
|
+
supported: true
|
|
2005
|
+
},
|
|
2006
|
+
{
|
|
2007
|
+
id: "cloudflare",
|
|
2008
|
+
name: "Cloudflare Workers AI",
|
|
2009
|
+
authType: "api",
|
|
2010
|
+
npm: "@ai-sdk/openai-compatible",
|
|
2011
|
+
defaultBaseUrl: "https://api.cloudflare.com/client/v4/accounts/{ACCOUNT_ID}/ai/v1",
|
|
2012
|
+
modelsPath: "/models/search?task=Text%20Generation",
|
|
2013
|
+
signupUrl: "https://dash.cloudflare.com",
|
|
2014
|
+
accountIdPrompt: "Cloudflare Account ID:",
|
|
2015
|
+
modelSource: "api-list",
|
|
2016
|
+
supported: true
|
|
2017
|
+
},
|
|
2018
|
+
{
|
|
2019
|
+
id: "anthropic",
|
|
2020
|
+
name: "Anthropic",
|
|
2021
|
+
authType: "api",
|
|
2022
|
+
npm: "@ai-sdk/anthropic",
|
|
2023
|
+
defaultBaseUrl: "https://api.anthropic.com",
|
|
2024
|
+
signupUrl: "https://console.anthropic.com/settings/keys",
|
|
2025
|
+
modelSource: "api-list",
|
|
2026
|
+
supported: true
|
|
2027
|
+
},
|
|
2028
|
+
{
|
|
2029
|
+
id: "bedrock",
|
|
2030
|
+
name: "Amazon Bedrock",
|
|
2031
|
+
authType: "api",
|
|
2032
|
+
npm: "@ai-sdk/amazon-bedrock",
|
|
2033
|
+
modelSource: "manual-only",
|
|
2034
|
+
supported: false,
|
|
2035
|
+
unsupportedReason: "Not supported yet (requires AWS credentials). Optional: relay-ai providers import if already set up in OpenCode CLI."
|
|
2036
|
+
},
|
|
2037
|
+
{
|
|
2038
|
+
id: "azure",
|
|
2039
|
+
name: "Azure OpenAI",
|
|
2040
|
+
authType: "api",
|
|
2041
|
+
npm: "@ai-sdk/azure",
|
|
2042
|
+
modelSource: "manual-only",
|
|
2043
|
+
supported: false,
|
|
2044
|
+
unsupportedReason: "Not supported yet (requires Azure deployment URLs). Optional: relay-ai providers import if already set up in OpenCode CLI."
|
|
2045
|
+
},
|
|
2046
|
+
{
|
|
2047
|
+
id: "vertex",
|
|
2048
|
+
name: "Google Vertex AI",
|
|
2049
|
+
authType: "none",
|
|
2050
|
+
npm: "@ai-sdk/google-vertex",
|
|
2051
|
+
modelSource: "manual-only",
|
|
2052
|
+
supported: false,
|
|
2053
|
+
unsupportedReason: "Uses gcloud Application Default Credentials \u2014 use relay-ai server --vertex, not an API key."
|
|
2054
|
+
},
|
|
2055
|
+
{
|
|
2056
|
+
id: "opencode-cloud",
|
|
2057
|
+
name: "OpenCode Zen / Go",
|
|
2058
|
+
authType: "api",
|
|
2059
|
+
npm: "@ai-sdk/openai-compatible",
|
|
2060
|
+
signupUrl: "https://opencode.ai/auth",
|
|
2061
|
+
modelSource: "zen-go-api",
|
|
2062
|
+
supported: true
|
|
2063
|
+
},
|
|
2064
|
+
{
|
|
2065
|
+
id: "zen",
|
|
2066
|
+
name: "OpenCode Zen",
|
|
2067
|
+
authType: "api",
|
|
2068
|
+
npm: "@ai-sdk/openai-compatible",
|
|
2069
|
+
signupUrl: "https://opencode.ai/auth",
|
|
2070
|
+
modelSource: "zen-go-api",
|
|
2071
|
+
supported: true,
|
|
2072
|
+
addable: false
|
|
2073
|
+
},
|
|
2074
|
+
{
|
|
2075
|
+
id: "go",
|
|
2076
|
+
name: "OpenCode Go",
|
|
2077
|
+
authType: "api",
|
|
2078
|
+
npm: "@ai-sdk/openai-compatible",
|
|
2079
|
+
signupUrl: "https://opencode.ai/auth",
|
|
2080
|
+
modelSource: "zen-go-api",
|
|
2081
|
+
supported: true,
|
|
2082
|
+
addable: false
|
|
2083
|
+
},
|
|
2084
|
+
// Subscription OAuth providers — Authorization Code + PKCE (browser redirect)
|
|
2085
|
+
// ⚠️ These extract tokens from paid subscriptions. Account risk — see plan docs.
|
|
2086
|
+
{
|
|
2087
|
+
id: "claude-code",
|
|
2088
|
+
name: "Claude Code (Anthropic subscription)",
|
|
2089
|
+
shortName: "Claude Code",
|
|
2090
|
+
authType: "oauth",
|
|
2091
|
+
npm: "@ai-sdk/anthropic",
|
|
2092
|
+
defaultBaseUrl: "https://api.anthropic.com",
|
|
2093
|
+
signupUrl: "https://claude.ai",
|
|
2094
|
+
modelSource: "api-list",
|
|
2095
|
+
supported: true,
|
|
2096
|
+
hidden: true,
|
|
2097
|
+
subscriptionRisk: true
|
|
2098
|
+
},
|
|
2099
|
+
{
|
|
2100
|
+
id: "antigravity",
|
|
2101
|
+
name: "Cloud Code Assist OAuth (Google)",
|
|
2102
|
+
shortName: "Cloud Code Assist",
|
|
2103
|
+
authType: "oauth",
|
|
2104
|
+
npm: "@ai-sdk/openai-compatible",
|
|
2105
|
+
signupUrl: "https://antigravity.google",
|
|
2106
|
+
modelSource: "api-list",
|
|
2107
|
+
supported: true,
|
|
2108
|
+
hidden: true,
|
|
2109
|
+
subscriptionRisk: true
|
|
2110
|
+
},
|
|
2111
|
+
// OAuth-gated subscription providers — device code or broker sign-in
|
|
2112
|
+
{
|
|
2113
|
+
id: "xai-oauth",
|
|
2114
|
+
name: "xAI Grok (SuperGrok)",
|
|
2115
|
+
shortName: "xAI Grok",
|
|
2116
|
+
authType: "oauth",
|
|
2117
|
+
npm: "@ai-sdk/xai",
|
|
2118
|
+
signupUrl: "https://x.ai",
|
|
2119
|
+
modelSource: "api-list",
|
|
2120
|
+
supported: true
|
|
2121
|
+
},
|
|
2122
|
+
{
|
|
2123
|
+
id: "openai-oauth",
|
|
2124
|
+
name: "OpenAI (ChatGPT)",
|
|
2125
|
+
shortName: "OpenAI",
|
|
2126
|
+
authType: "oauth",
|
|
2127
|
+
npm: "@ai-sdk/openai",
|
|
2128
|
+
signupUrl: "https://chatgpt.com",
|
|
2129
|
+
modelSource: "api-list",
|
|
2130
|
+
supported: true
|
|
2131
|
+
},
|
|
2132
|
+
{
|
|
2133
|
+
id: "github-copilot",
|
|
2134
|
+
name: "GitHub Copilot",
|
|
2135
|
+
authType: "oauth",
|
|
2136
|
+
npm: "@ai-sdk/openai-compatible",
|
|
2137
|
+
defaultBaseUrl: "https://api.githubcopilot.com",
|
|
2138
|
+
modelsPath: "/models",
|
|
2139
|
+
signupUrl: "https://github.com/features/copilot",
|
|
2140
|
+
modelSource: "api-list",
|
|
2141
|
+
headers: { "Editor-Version": "vscode/1.85.1" },
|
|
2142
|
+
supported: true
|
|
2143
|
+
}
|
|
2144
|
+
];
|
|
2145
|
+
function getTemplateById(id) {
|
|
2146
|
+
return PROVIDER_TEMPLATES.find((t) => t.id === id);
|
|
2147
|
+
}
|
|
2148
|
+
|
|
2149
|
+
// src/registry/resolve-template.ts
|
|
2150
|
+
var TEMPLATE_ID_ALIASES = {
|
|
2151
|
+
"google-vertex": "vertex"
|
|
2152
|
+
};
|
|
2153
|
+
function resolveProviderTemplate(provider) {
|
|
2154
|
+
const candidates = [
|
|
2155
|
+
TEMPLATE_ID_ALIASES[provider.templateId],
|
|
2156
|
+
provider.templateId,
|
|
2157
|
+
TEMPLATE_ID_ALIASES[provider.id],
|
|
2158
|
+
provider.id
|
|
2159
|
+
].filter(Boolean);
|
|
2160
|
+
for (const id of candidates) {
|
|
2161
|
+
const template = getTemplateById(id);
|
|
2162
|
+
if (template) return template;
|
|
2163
|
+
}
|
|
2164
|
+
return void 0;
|
|
2165
|
+
}
|
|
2166
|
+
|
|
1742
2167
|
// src/core/errors.ts
|
|
1743
2168
|
var DEFAULT_RETRYABLE = {
|
|
1744
2169
|
INVALID_ROUTE_ID: false,
|
|
@@ -1779,6 +2204,55 @@ function isRelayCoreError(err) {
|
|
|
1779
2204
|
return err instanceof RelayCoreError;
|
|
1780
2205
|
}
|
|
1781
2206
|
|
|
2207
|
+
// src/opencode-session.ts
|
|
2208
|
+
import { randomUUID as randomUUID2 } from "crypto";
|
|
2209
|
+
var OPENCODE_SESSION_HEADER = "x-opencode-session";
|
|
2210
|
+
var MAX_OPENCODE_SESSION_LENGTH = 256;
|
|
2211
|
+
var RELAY_USER_AGENT = `relay-ai/${VERSION}`;
|
|
2212
|
+
function sanitizeSessionId(value) {
|
|
2213
|
+
if (typeof value !== "string") return void 0;
|
|
2214
|
+
const normalized = value.trim();
|
|
2215
|
+
if (!normalized || normalized.length > MAX_OPENCODE_SESSION_LENGTH) return void 0;
|
|
2216
|
+
if (/[\u0000-\u001f\u007f\r\n]/.test(normalized)) return void 0;
|
|
2217
|
+
return normalized;
|
|
2218
|
+
}
|
|
2219
|
+
function isOpenCodeGoEndpoint(providerId, endpoint) {
|
|
2220
|
+
const id = providerId?.trim().toLowerCase();
|
|
2221
|
+
if (id === "go" || id === "opencode-go") return true;
|
|
2222
|
+
if (!endpoint) return false;
|
|
2223
|
+
try {
|
|
2224
|
+
const url = new URL(endpoint);
|
|
2225
|
+
if (url.hostname.toLowerCase() !== "opencode.ai") return false;
|
|
2226
|
+
return url.pathname.split("/").some((segment) => segment.toLowerCase() === "go");
|
|
2227
|
+
} catch {
|
|
2228
|
+
return false;
|
|
2229
|
+
}
|
|
2230
|
+
}
|
|
2231
|
+
function mergeHeaders(base, overrides) {
|
|
2232
|
+
const result = {};
|
|
2233
|
+
for (const [key, value] of Object.entries(base ?? {})) {
|
|
2234
|
+
if (typeof value === "string") result[key] = value;
|
|
2235
|
+
}
|
|
2236
|
+
for (const [key, value] of Object.entries(overrides ?? {})) {
|
|
2237
|
+
for (const existing of Object.keys(result)) {
|
|
2238
|
+
if (existing.toLowerCase() === key.toLowerCase()) delete result[existing];
|
|
2239
|
+
}
|
|
2240
|
+
result[key] = value;
|
|
2241
|
+
}
|
|
2242
|
+
return result;
|
|
2243
|
+
}
|
|
2244
|
+
function openCodeGoHeaders(providerId, endpoint, sessionId, baseHeaders, options) {
|
|
2245
|
+
if (!isOpenCodeGoEndpoint(providerId, endpoint)) return void 0;
|
|
2246
|
+
let normalizedSessionId = sanitizeSessionId(sessionId);
|
|
2247
|
+
if (!normalizedSessionId && (options?.generateFallbackSession ?? true)) {
|
|
2248
|
+
normalizedSessionId = `relay-${randomUUID2()}`;
|
|
2249
|
+
}
|
|
2250
|
+
return mergeHeaders(baseHeaders, {
|
|
2251
|
+
"User-Agent": RELAY_USER_AGENT,
|
|
2252
|
+
...normalizedSessionId ? { [OPENCODE_SESSION_HEADER]: normalizedSessionId } : {}
|
|
2253
|
+
});
|
|
2254
|
+
}
|
|
2255
|
+
|
|
1782
2256
|
// src/core/reasoning.ts
|
|
1783
2257
|
var RELAY_REASONING_LEVELS = [
|
|
1784
2258
|
"off",
|
|
@@ -1852,6 +2326,22 @@ async function withReasoningProviderOptions(model, providerOptions) {
|
|
|
1852
2326
|
}
|
|
1853
2327
|
});
|
|
1854
2328
|
}
|
|
2329
|
+
async function withRequestHeaders(model, headers) {
|
|
2330
|
+
const { wrapLanguageModel: wrapLanguageModel2 } = await import("ai");
|
|
2331
|
+
return wrapLanguageModel2({
|
|
2332
|
+
model,
|
|
2333
|
+
middleware: {
|
|
2334
|
+
specificationVersion: "v3",
|
|
2335
|
+
transformParams: async ({ params }) => ({
|
|
2336
|
+
...params,
|
|
2337
|
+
headers: mergeHeaders(
|
|
2338
|
+
headers,
|
|
2339
|
+
params.headers
|
|
2340
|
+
)
|
|
2341
|
+
})
|
|
2342
|
+
}
|
|
2343
|
+
});
|
|
2344
|
+
}
|
|
1855
2345
|
|
|
1856
2346
|
// src/core/route-id.ts
|
|
1857
2347
|
var SEPARATOR = "::";
|
|
@@ -1928,10 +2418,12 @@ function favoriteKey(providerId, modelId) {
|
|
|
1928
2418
|
}
|
|
1929
2419
|
function toDescriptor(provider, model, favorites) {
|
|
1930
2420
|
const upstreamModelId = model.upstreamModelId ?? model.id;
|
|
2421
|
+
const providerShortName = resolveProviderTemplate(provider)?.shortName ?? provider.name;
|
|
1931
2422
|
return {
|
|
1932
2423
|
routeId: toRelayRouteId(provider.id, model.id),
|
|
1933
2424
|
providerId: provider.id,
|
|
1934
2425
|
providerName: provider.name,
|
|
2426
|
+
providerShortName,
|
|
1935
2427
|
modelId: model.id,
|
|
1936
2428
|
upstreamModelId,
|
|
1937
2429
|
displayName: model.name,
|
|
@@ -3082,7 +3574,7 @@ function providerRefreshToken(providerId, authType, authRef) {
|
|
|
3082
3574
|
}
|
|
3083
3575
|
|
|
3084
3576
|
// src/core/antigravity-model.ts
|
|
3085
|
-
import { randomUUID as
|
|
3577
|
+
import { randomUUID as randomUUID3 } from "crypto";
|
|
3086
3578
|
var CLOUD_CODE_BASES = ANTIGRAVITY_BASE_URLS.map((base) => base.replace(/\/+$/, ""));
|
|
3087
3579
|
var CLOUD_CODE_BASE = CLOUD_CODE_BASES[0];
|
|
3088
3580
|
var STREAM_URLS = CLOUD_CODE_BASES.map((base) => `${base}/${ANTIGRAVITY_API_VERSION}:streamGenerateContent?alt=sse`);
|
|
@@ -3169,7 +3661,7 @@ function createCloudCodeFetch(options, fetchImpl) {
|
|
|
3169
3661
|
const geminiBody = await readJsonBody(input, init);
|
|
3170
3662
|
const envelope = {
|
|
3171
3663
|
project: options.projectId,
|
|
3172
|
-
requestId:
|
|
3664
|
+
requestId: randomUUID3(),
|
|
3173
3665
|
model: options.modelId,
|
|
3174
3666
|
userAgent: ANTIGRAVITY_USER_AGENT,
|
|
3175
3667
|
requestType: "agent",
|
|
@@ -3364,7 +3856,21 @@ async function createRelayModel(routeId, options) {
|
|
|
3364
3856
|
const registry = loadCoreRegistry();
|
|
3365
3857
|
const { provider, model } = findRoute(registry, providerId, modelId, routeId);
|
|
3366
3858
|
const reasoningOptions = options?.reasoning === void 0 ? void 0 : resolveReasoningProviderOptions(options.reasoning, provider, model, routeId);
|
|
3367
|
-
const
|
|
3859
|
+
const transportHeaders = openCodeGoHeaders(
|
|
3860
|
+
provider.id,
|
|
3861
|
+
model.apiUrl ?? provider.api.url,
|
|
3862
|
+
options?.sessionId,
|
|
3863
|
+
provider.api.headers,
|
|
3864
|
+
// The returned model may be reused across conversations, so never fabricate a
|
|
3865
|
+
// session here — a baked-in id would blend histories. The host passes sessionId.
|
|
3866
|
+
{ generateFallbackSession: false }
|
|
3867
|
+
);
|
|
3868
|
+
const finish = async (built) => {
|
|
3869
|
+
let finished = built;
|
|
3870
|
+
if (reasoningOptions) finished = await withReasoningProviderOptions(finished, reasoningOptions);
|
|
3871
|
+
if (transportHeaders) finished = await withRequestHeaders(finished, transportHeaders);
|
|
3872
|
+
return finished;
|
|
3873
|
+
};
|
|
3368
3874
|
if (isAntigravityCloudCodeRoute(provider, model)) {
|
|
3369
3875
|
const apiKey2 = await resolveCredential(provider, routeId);
|
|
3370
3876
|
const providerData2 = await resolveProviderOAuthProviderData(provider.authRef);
|