@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.
@@ -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;
@@ -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.9.7",
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 randomUUID2 } from "crypto";
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: randomUUID2(),
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 finish = (built) => reasoningOptions ? withReasoningProviderOptions(built, reasoningOptions) : Promise.resolve(built);
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);