@code-yeongyu/senpi-ai 2026.10.9 → 2026.10.10-11

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.
Files changed (51) hide show
  1. package/dist/api/anthropic-messages.js +101 -38
  2. package/dist/api/anthropic-tool-references.js +24 -18
  3. package/dist/api/bedrock-converse-stream.js +5 -1
  4. package/dist/api/lazy.js +13 -0
  5. package/dist/api/mistral-conversations.js +18 -3
  6. package/dist/api/openai-codex-responses.js +2 -2
  7. package/dist/api/openai-completions.js +26 -2
  8. package/dist/api/openai-responses.js +2 -2
  9. package/dist/auth/oauth/anthropic.js +4 -3
  10. package/dist/auth/oauth/chatgpt-subscription.js +3 -2
  11. package/dist/auth/oauth/cursor.js +3 -2
  12. package/dist/auth/oauth/devin-token.js +2 -1
  13. package/dist/auth/oauth/github-copilot.js +3 -2
  14. package/dist/auth/oauth/kimi-coding.js +5 -4
  15. package/dist/auth/oauth/openai-chatgpt.js +2 -1
  16. package/dist/auth/oauth/openrouter.js +2 -1
  17. package/dist/auth/oauth/radius.js +5 -5
  18. package/dist/auth/oauth/xai.js +7 -4
  19. package/dist/auth/oauth-refresh.js +10 -0
  20. package/dist/auth/resolve.js +5 -0
  21. package/dist/providers/all.d.ts +1 -1
  22. package/dist/providers/data/.manifest.json +1 -1
  23. package/dist/providers/data/amazon-bedrock.json +1 -1
  24. package/dist/providers/data/anthropic.json +1 -1
  25. package/dist/providers/data/baseten.json +1 -1
  26. package/dist/providers/data/chatgpt-subscription.json +1 -1
  27. package/dist/providers/data/cloudflare-ai-gateway.json +1 -1
  28. package/dist/providers/data/cloudflare-workers-ai.json +1 -1
  29. package/dist/providers/data/github-copilot.json +1 -1
  30. package/dist/providers/data/google-vertex.json +1 -1
  31. package/dist/providers/data/mistral.json +1 -1
  32. package/dist/providers/data/moonshotai-cn.json +1 -1
  33. package/dist/providers/data/moonshotai.json +1 -1
  34. package/dist/providers/data/opencode-go.json +1 -1
  35. package/dist/providers/data/opencode.json +1 -1
  36. package/dist/providers/data/opengateway.json +1 -1
  37. package/dist/providers/data/openrouter.json +1 -1
  38. package/dist/providers/data/radius.json +1 -1
  39. package/dist/providers/data/venice.json +1 -1
  40. package/dist/providers/data/vercel-ai-gateway.json +1 -1
  41. package/dist/providers/kimi-coding.models.d.ts +1 -1
  42. package/dist/providers/kimi-coding.models.js +1 -1
  43. package/dist/providers/opengateway-refresh.js +2 -1
  44. package/dist/utils/oauth-refresh-error.d.ts +16 -0
  45. package/dist/utils/oauth-refresh-error.js +67 -0
  46. package/dist/utils/prompt-cache-ttl.js +3 -1
  47. package/dist/utils/retry.d.ts +6 -0
  48. package/dist/utils/retry.js +10 -0
  49. package/dist/utils/tool-choice-fallback.d.ts +6 -0
  50. package/dist/utils/tool-choice-fallback.js +69 -2
  51. package/package.json +2 -2
@@ -6,6 +6,7 @@
6
6
  * access token authenticates requests to that region's coding API as an
7
7
  * `Authorization: Bearer` header; see kimi-region.ts for the host table.
8
8
  */
9
+ import { OAuthTokenEndpointError } from "../../utils/oauth-refresh-error.js";
9
10
  import { sleep } from "../../utils/sleep.js";
10
11
  import { pollOAuthDeviceCodeFlow } from "./device-code.js";
11
12
  import { kimiCodeIdentityHeaders } from "./kimi-identity.js";
@@ -178,7 +179,7 @@ async function refreshToken(oauthHost, refreshTokenValue, signal) {
178
179
  await sleep(1000 * 2 ** (attempt - 1), signal);
179
180
  }
180
181
  if (signal.aborted) {
181
- throw new Error("Kimi Code token refresh aborted");
182
+ throw new Error("Kimi Code token refresh aborted", { cause: signal.reason });
182
183
  }
183
184
  let response;
184
185
  try {
@@ -208,14 +209,14 @@ async function refreshToken(oauthHost, refreshTokenValue, signal) {
208
209
  // Unauthorized: the stored credential is dead; Models clears it and prompts re-login.
209
210
  if (response.status === 401 || response.status === 403 || json?.error === "invalid_grant") {
210
211
  const description = typeof json?.error_description === "string" ? `: ${json.error_description}` : "";
211
- throw new Error(`Kimi Code token refresh unauthorized (status ${response.status})${description}`);
212
+ throw new OAuthTokenEndpointError(`Kimi Code token refresh unauthorized (status ${response.status})${description}`, response.status);
212
213
  }
213
214
  if (isRetryableRefreshFailure(response) && attempt < REFRESH_MAX_RETRIES) {
214
- lastError = new Error(`Kimi Code token refresh failed with status ${response.status}`);
215
+ lastError = new OAuthTokenEndpointError(`Kimi Code token refresh failed with status ${response.status}`, response.status);
215
216
  continue;
216
217
  }
217
218
  const text = JSON.stringify(json);
218
- throw new Error(`Kimi Code token refresh failed with status ${response.status}${text ? `: ${text}` : ""}`);
219
+ throw new OAuthTokenEndpointError(`Kimi Code token refresh failed with status ${response.status}${text ? `: ${text}` : ""}`, response.status);
219
220
  }
220
221
  throw lastError ?? new Error("Kimi Code token refresh failed");
221
222
  }
@@ -7,6 +7,7 @@
7
7
  import { randomBytes } from "node:crypto";
8
8
  import { createServer } from "node:http";
9
9
  import { oauthErrorHtml, oauthSuccessHtml } from "../../utils/oauth-page.js";
10
+ import { OAuthTokenEndpointError } from "../../utils/oauth-refresh-error.js";
10
11
  import { getProviderEnvValue } from "../../utils/provider-env.js";
11
12
  import { generatePKCE } from "./pkce.js";
12
13
  // every login registers a new client with this ID; OpenAI returns the issued client ID in the callback
@@ -119,7 +120,7 @@ async function requestToken(body, signal) {
119
120
  });
120
121
  if (!response.ok) {
121
122
  const responseBody = await response.text().catch(() => "");
122
- throw new Error(`OpenAI OAuth token request failed (${response.status}): ${responseBody || response.statusText}`);
123
+ throw new OAuthTokenEndpointError(`OpenAI OAuth token request failed (${response.status}): ${responseBody || response.statusText}`, response.status);
123
124
  }
124
125
  const data = await response.json();
125
126
  if (typeof data !== "object" || data === null || Array.isArray(data)) {
@@ -10,6 +10,7 @@
10
10
  * NOTE: This module uses node:http (via callback-server.ts) for the OAuth callback server.
11
11
  * It is only intended for CLI use, not browser environments.
12
12
  */
13
+ import { OAuthTokenEndpointError } from "../../utils/oauth-refresh-error.js";
13
14
  import { getProviderEnvValue } from "../../utils/provider-env.js";
14
15
  import { startOAuthCallbackServer, waitForCallbackOrManualInput } from "./callback-server.js";
15
16
  import { generatePKCE } from "./pkce.js";
@@ -88,7 +89,7 @@ async function exchangeAuthorizationCode(code, verifier, signal) {
88
89
  }
89
90
  if (!response.ok) {
90
91
  const detail = errorDetail(body);
91
- throw new Error(`OpenRouter OAuth key exchange failed (HTTP ${response.status})${detail ? `: ${detail}` : ""}`);
92
+ throw new OAuthTokenEndpointError(`OpenRouter OAuth key exchange failed (HTTP ${response.status})${detail ? `: ${detail}` : ""}`, response.status);
92
93
  }
93
94
  if (typeof body.key !== "string" || body.key.length === 0) {
94
95
  throw new Error('OpenRouter OAuth response carries no "key"');
@@ -9,6 +9,7 @@
9
9
  * It is only intended for CLI use, not browser environments.
10
10
  */
11
11
  import { normalizeRadiusGatewayUrl } from "../../providers/radius-config.js";
12
+ import { OAuthTokenEndpointError } from "../../utils/oauth-refresh-error.js";
12
13
  import { startOAuthCallbackServer } from "./callback-server.js";
13
14
  import { pollOAuthDeviceCodeFlow } from "./device-code.js";
14
15
  import { generatePKCE } from "./pkce.js";
@@ -36,15 +37,14 @@ async function loadRadiusOAuthDiscovery(gateway, signal) {
36
37
  }
37
38
  return { authorizationEndpoint: discovery.authorizationEndpoint };
38
39
  }
39
- class OAuthResponseError extends Error {
40
+ class OAuthResponseError extends OAuthTokenEndpointError {
40
41
  constructor(status, oauthError, description, message) {
41
42
  const detail = oauthError
42
43
  ? description
43
44
  ? `${oauthError}: ${description}`
44
45
  : oauthError
45
46
  : description || String(status);
46
- super(`${message}: ${detail}`);
47
- this.status = status;
47
+ super(`${message}: ${detail}`, status);
48
48
  this.oauthError = oauthError;
49
49
  }
50
50
  }
@@ -76,7 +76,7 @@ async function requestOAuthToken(gateway, body, signal) {
76
76
  }
77
77
  catch (error) {
78
78
  if (signal.aborted) {
79
- throw new Error("Login cancelled");
79
+ throw new Error("Login cancelled", { cause: signal.reason });
80
80
  }
81
81
  throw error;
82
82
  }
@@ -149,7 +149,7 @@ async function requestDeviceAuthorization(gateway, signal) {
149
149
  }
150
150
  catch (error) {
151
151
  if (signal.aborted) {
152
- throw new Error("Login cancelled");
152
+ throw new Error("Login cancelled", { cause: signal.reason });
153
153
  }
154
154
  throw error;
155
155
  }
@@ -1,6 +1,7 @@
1
1
  /**
2
2
  * xAI OAuth device-code flow.
3
3
  */
4
+ import { OAuthTokenEndpointError } from "../../utils/oauth-refresh-error.js";
4
5
  import { pollOAuthDeviceCodeFlow } from "./device-code.js";
5
6
  const XAI_CLIENT_ID = "b1a00492-073a-47ea-816f-4c329264a828";
6
7
  const XAI_SCOPE = "openid profile email offline_access grok-cli:access api:access";
@@ -53,7 +54,7 @@ async function postForm(url, fields, signal) {
53
54
  }
54
55
  catch (error) {
55
56
  if (signal.aborted) {
56
- throw new Error("Login cancelled");
57
+ throw new Error("Login cancelled", { cause: signal.reason });
57
58
  }
58
59
  throw error;
59
60
  }
@@ -64,9 +65,11 @@ async function postForm(url, fields, signal) {
64
65
  }
65
66
  catch {
66
67
  if (signal.aborted) {
67
- throw new Error("Login cancelled");
68
+ throw new Error("Login cancelled", { cause: signal.reason });
68
69
  }
69
- throw new Error(`xAI OAuth returned invalid JSON (HTTP ${response.status})`);
70
+ const message = `xAI OAuth returned invalid JSON (HTTP ${response.status})`;
71
+ // An error page (an HTML 503 from a proxy, say) still carries the status the retry decision needs.
72
+ throw response.ok ? new Error(message) : new OAuthTokenEndpointError(message, response.status);
70
73
  }
71
74
  return {
72
75
  ok: response.ok,
@@ -78,7 +81,7 @@ function requestFailure(action, response) {
78
81
  const error = typeof response.body.error === "string" ? response.body.error : undefined;
79
82
  const description = typeof response.body.error_description === "string" ? response.body.error_description : undefined;
80
83
  const detail = [error, description].filter(Boolean).join(": ");
81
- return new Error(`xAI OAuth ${action} failed (HTTP ${response.status})${detail ? `: ${detail}` : ""}`);
84
+ return new OAuthTokenEndpointError(`xAI OAuth ${action} failed (HTTP ${response.status})${detail ? `: ${detail}` : ""}`, response.status);
82
85
  }
83
86
  function parseDeviceCode(body) {
84
87
  // RFC 8628 allows interval 0 (no minimum wait); fall back to the poller's
@@ -15,6 +15,7 @@
15
15
  * superseded catalog refresh stops waiting but never aborts the exchange.
16
16
  */
17
17
  import { raceWithAbortSignal } from "../utils/abort.js";
18
+ import { oauthRefreshFailureCause } from "../utils/oauth-refresh-error.js";
18
19
  import { mergeRefreshed, mergeRefreshedSlot, projectSlot } from "./pool/slots.js";
19
20
  export const DEFAULT_OAUTH_REFRESH_TIMEOUT_MS = 15_000;
20
21
  /** The provider rejected or timed out the token exchange. */
@@ -103,6 +104,15 @@ async function exchangeAndStore(request, signal) {
103
104
  signal.throwIfAborted();
104
105
  }
105
106
  catch (error) {
107
+ signal.throwIfAborted();
108
+ const causeClass = oauthRefreshFailureCause(error);
109
+ if (causeClass !== undefined) {
110
+ console.warn("OAuth refresh unavailable", JSON.stringify({
111
+ provider: providerId,
112
+ ...(slotName ? { slot: slotName } : {}),
113
+ cause: causeClass,
114
+ }));
115
+ }
106
116
  throw new OAuthRefreshExchangeError(error);
107
117
  }
108
118
  try {
@@ -1,5 +1,6 @@
1
1
  import { operationSignal, raceWithAbortSignal } from "../utils/abort.js";
2
2
  import { ModelsError } from "../utils/models-error.js";
3
+ import { classifyOAuthRefreshFailure, OAuthRefreshUnavailableError } from "../utils/oauth-refresh-error.js";
3
4
  import { OAuthRefreshExchangeError, OAuthRefreshStoreError, projectOAuthSlot, refreshOAuthCredential, } from "./oauth-refresh.js";
4
5
  import { projectSlot } from "./pool/slots.js";
5
6
  export { ModelsError } from "../utils/models-error.js";
@@ -82,6 +83,9 @@ export function oauthRefreshModelsError(error, providerId) {
82
83
  if (error instanceof ModelsError)
83
84
  return error;
84
85
  if (error instanceof OAuthRefreshExchangeError) {
86
+ if (classifyOAuthRefreshFailure(error.cause) === "transient") {
87
+ return new OAuthRefreshUnavailableError(providerId, error.cause);
88
+ }
85
89
  return new ModelsError("oauth", `OAuth refresh failed for ${providerId}`, { cause: error.cause });
86
90
  }
87
91
  const cause = error instanceof OAuthRefreshStoreError ? error.cause : error;
@@ -112,6 +116,7 @@ async function resolveStoredOAuth(credentials, providerId, oauth, stored, authCo
112
116
  });
113
117
  }
114
118
  catch (error) {
119
+ signal.throwIfAborted();
115
120
  throw oauthRefreshModelsError(error, providerId);
116
121
  }
117
122
  if (post?.type !== "oauth")
@@ -50,7 +50,7 @@ declare const FORK_OWNED_CATALOGS: {
50
50
  readonly input: 3;
51
51
  readonly output: 15;
52
52
  readonly cacheRead: 0.3;
53
- readonly cacheWrite: 0;
53
+ readonly cacheWrite: 3;
54
54
  };
55
55
  readonly contextWindow: 1048576;
56
56
  readonly maxTokens: 131072;
@@ -1 +1 @@
1
- {"schemaVersion":6,"generatedAt":"2026-10-04T20:05:22.652Z","structureHash":"ff5f1c5ea3d0a6d7d36208bac83298ca0f7762d9067e289536e1a1e02777e038","files":{"alibaba-token-plan.json":"16b3c6c78d72c73ca34a1e79ce71c0cf36ba409d02e83a17396ce0949a1d5363","amazon-bedrock.json":"e918146642945e9ef5f2ccc04f8de04d5a34b1cc32d0e1b0ddc231254263a656","ant-ling.json":"628feab3ef6c7d80ce96f75999804e1d9f05fec3851e5302e30fff3b69db90f6","anthropic.json":"2c0c4389cd71d21d4553075f399922892078192b0490fead423544e360af1a43","azure-openai-responses.json":"a3e52bd78f0220aa32bce519e13955b8e6e567860416343844cbe19902f4a682","bai.json":"7e6861aaf27d8af34e1771c6092602194fcec0a0046e6adfab9c3ee54d32b99f","baseten.json":"b04d1423d6958bec857ffccc36726f091ec1a8f3a09cf0836b64cc94b0ee697d","cerebras.json":"3eccb58c5de3d0dc7ba49dc6e477ba29f00cb3150ce0a35cc90d59e6b5ab368e","chatgpt-subscription.json":"08f365952647594f5b07337666255f8510ef2e09bfb704530843b63121ed07f4","cloudflare-ai-gateway.json":"2ba4b7f1b0ba8919760c2e9cbd994270edd179bc9d291f271eede738afcbf269","cloudflare-workers-ai.json":"4bf0b488460c2e6cb8a6615bb2f87ca2a31cd9597eb249d5b58cba251330a99a","deepseek.json":"10a296fb3e898f7715c80890c8af0af4f5fd58f22dbcd6612fdc5d762157ccdc","fireworks.json":"c3dc21dc2e95428fc9a38e3840c05bbf90f94e4c25dee0eedf0b385b49ff65a4","github-copilot.json":"9ed67e5c0104ec237e9befcb9a50a18bd7d65e1539cd9f0638d2bc20bd82ef60","google-vertex.json":"40090c680538bc867f2624d986a449f361be4dfa6ba96d7a27402050f036e009","google.json":"c0f5a633e5e5a5044432db3e537f4bc674d4de18df09325c6349547fcc13cabe","groq.json":"910952ad9dad07856983459d63fce0148dba1203edd7b10d801a77c5824f3405","huggingface.json":"1b8604bd31a5e05fe43a40ec1ec6dfc1a51a28b0b020151ef057fab43f57c923","meta.json":"0c7e9a370a7005c5a89dc94f0f93bc67b8935c3f802de324f11af6ff56fff429","minimax-cn.json":"f962c20ee6a6a342820f778e9dc363a18a524bf11998f6e2c57f2989915d62e5","minimax.json":"17a432f80d0ea6dd26eade80a4314250d3a855678601728a5f70dd8fa0d21dd2","mistral.json":"10f33bff9adf1248f7e6848e5890c265399f1f94e5b42cfdc28c109d547af98d","moonshotai-cn.json":"bfb0641eee9587118da525607d86e55840de13310cd934785bc3bdcfeb6f88e3","moonshotai.json":"79ac5b6861a10d592e884c05a546fdd0b58fe383ce3453ecdb32d43926cba9dd","nvidia.json":"a75e963dc81779e3eec01c051b12277c15ec37c5b94ab51ece9e9ccb3b16407c","openai.json":"9104538118053eed57f90852332b6ad274a4e4792389bdbc9cfca1ae400c705a","opencode-go.json":"ba0f2ac7ff7c85db2123979b69f3e58cf5f2c1d89f29c8c7eda8a067d9809481","opencode.json":"ae373c624a66b824f543ef76fb5f1849b4910390952e6ae18b13bdb3e2d63b37","opengateway.json":"2d4275641f1b1154dfc6ffb320bedc1bcb1e33a0d12a4e9fba147ee3edec7d64","openrouter.json":"28f867631a0cea94dd724c459c41c8e8d6fa1256e10256f8934a1c2ac58ecdc9","qwen-token-plan-cn.json":"bd36a6d9cc2048deafacc85f7f0f2e51868c8b7aa09502e3e4e60e3e8b76f690","qwen-token-plan-individual.json":"35ffb0ba1a1ce3f68fc73262dd5e07fbcb5bf5911ad1e6e17bc0621e2894676a","qwen-token-plan.json":"ca27e49e62965221badead8e867b2007035c6b6a15a97c47219bd23d2c83c2b1","radius.json":"a8cf2f2cc7dae90d8bbfdd8a2f8a0e058e7923dbdb3ba2cdaed7dd1aecd25a2a","together.json":"bbd7fad86cacfefe3d3d61f6638f22e9b6f5d575722fd1112a16aafe0485c46d","typesafe.json":"a4429a2f696d5cc5273969af61a7310bda07d6bdcd27bf9ac9c76c534cc43716","venice.json":"a5f06e8297561de8cfcce397f9609a804ec912af007ba7fdbdb1951f2ee97009","vercel-ai-gateway.json":"aa1eabd3ec0d8d7a0e783cd514c085b465a28503515cea6477f4880349d63f5c","xai.json":"d7771a1450b21c1f6aee887ca6fea61b6e7b3fc13b4dee5cf72a71134fe623bc","xiaomi-token-plan-ams.json":"4dd8f838e21d7aa7caf3122d0b0b1e5a02a33bc012b96e6a75bd119334152d7a","xiaomi-token-plan-cn.json":"46414ff49973b95a0c14bd33e8992cc1938a50ce2c7cea9e2e5cc02de8f1df31","xiaomi-token-plan-sgp.json":"f5b3f66bf7bb7238592d4a9667cad983a008d7539a66e9896b02422622800935","xiaomi.json":"8b62c158d55d5a165f35cd72c1fc82ab89ff8e73f08960105fc41b822f236f69","zai-coding-cn.json":"2a7f59d15f588a97d218997883f2506dfc52d3ee320697d39f14213a050fc912","zai.json":"e9cc408e1756de8abc70148d63d89d11a63c65b7ef06ad0661cd1328e4209ba3"}}
1
+ {"schemaVersion":6,"generatedAt":"2026-10-09T14:44:09.112Z","structureHash":"3663f1f5cad5c9cc1deecb3db21134e5d250b29f8ea2b5082d0783f3abdea0fe","files":{"alibaba-token-plan.json":"16b3c6c78d72c73ca34a1e79ce71c0cf36ba409d02e83a17396ce0949a1d5363","amazon-bedrock.json":"4a95e6bf974e5ca967d5c050df580262e13573e42b3186edb448fa11a302f09f","ant-ling.json":"628feab3ef6c7d80ce96f75999804e1d9f05fec3851e5302e30fff3b69db90f6","anthropic.json":"111384e9f5845e0247bd34edf2400ef7720fcbdac140b944cf8878192d8bd6ab","azure-openai-responses.json":"a3e52bd78f0220aa32bce519e13955b8e6e567860416343844cbe19902f4a682","bai.json":"7e6861aaf27d8af34e1771c6092602194fcec0a0046e6adfab9c3ee54d32b99f","baseten.json":"1fcdab8daf2881bd099eb08f9416f7df5bf39975937d2a63b841542bd032f2e6","cerebras.json":"3eccb58c5de3d0dc7ba49dc6e477ba29f00cb3150ce0a35cc90d59e6b5ab368e","chatgpt-subscription.json":"2fbeb0141b29c340542798bce53422b93bef026a13420986e87fca89353e0aa2","cloudflare-ai-gateway.json":"5c8782fdbf2477f620b238da4344b0bcc0948b8c177461e63e7e5ba256f769c7","cloudflare-workers-ai.json":"f351e80493dea7b7a2c31dceb086ee804a88d67c5f8a3c823ea907991fe5d659","deepseek.json":"10a296fb3e898f7715c80890c8af0af4f5fd58f22dbcd6612fdc5d762157ccdc","fireworks.json":"c3dc21dc2e95428fc9a38e3840c05bbf90f94e4c25dee0eedf0b385b49ff65a4","github-copilot.json":"2c5a84983477a7c4f6c001088a1e043ee959ce58c99fea6eb843e0286228664b","google-vertex.json":"96ecc19bf20a706f99ae658b021a0ee5438146119e1e99de5fd824a01fcfd81b","google.json":"c0f5a633e5e5a5044432db3e537f4bc674d4de18df09325c6349547fcc13cabe","groq.json":"910952ad9dad07856983459d63fce0148dba1203edd7b10d801a77c5824f3405","huggingface.json":"1b8604bd31a5e05fe43a40ec1ec6dfc1a51a28b0b020151ef057fab43f57c923","meta.json":"0c7e9a370a7005c5a89dc94f0f93bc67b8935c3f802de324f11af6ff56fff429","minimax-cn.json":"f962c20ee6a6a342820f778e9dc363a18a524bf11998f6e2c57f2989915d62e5","minimax.json":"17a432f80d0ea6dd26eade80a4314250d3a855678601728a5f70dd8fa0d21dd2","mistral.json":"27aa66c71a0504b53dc87ec194286fa7e70b99747fc8df9b709b23b3548afe50","moonshotai-cn.json":"18954b55dc5edecc174d8a07a2c5993416dd9d3ce52e411438035c16ee982e8e","moonshotai.json":"62d08fd5beead025a56d5f2e4227d8516b9c5034275b1b36d761a8625918f2b9","nvidia.json":"a75e963dc81779e3eec01c051b12277c15ec37c5b94ab51ece9e9ccb3b16407c","openai.json":"9104538118053eed57f90852332b6ad274a4e4792389bdbc9cfca1ae400c705a","opencode-go.json":"48ff011f3e171f977cfed2928272667e9361f13a508e5994f00f2241f6a23419","opencode.json":"882b039f64ef266da7b02d30aee9255c191e16f0600ef5494022bc1ef746f749","opengateway.json":"dd4259885ea6045d723b3abaae06657dfcce07b9ce3c2b0300220ac661432859","openrouter.json":"c2b975a6fa78aadb6f0cfa944e99c63dc94b46bb048d3e7ecbca29d91af1bfa7","qwen-token-plan-cn.json":"bd36a6d9cc2048deafacc85f7f0f2e51868c8b7aa09502e3e4e60e3e8b76f690","qwen-token-plan-individual.json":"35ffb0ba1a1ce3f68fc73262dd5e07fbcb5bf5911ad1e6e17bc0621e2894676a","qwen-token-plan.json":"ca27e49e62965221badead8e867b2007035c6b6a15a97c47219bd23d2c83c2b1","radius.json":"8214122385e8e4c4bc2e1d2a7d032f9e4c654da3bfd3ac8c5d4396e1b522e53a","together.json":"bbd7fad86cacfefe3d3d61f6638f22e9b6f5d575722fd1112a16aafe0485c46d","typesafe.json":"a4429a2f696d5cc5273969af61a7310bda07d6bdcd27bf9ac9c76c534cc43716","venice.json":"052c57c962adb3e2460a3ffbe052f376099cafe943e0b26279ece64265a613e8","vercel-ai-gateway.json":"b7bb117d016d500e0e92de7cad3fe1c223924187602eb1e7634ff07a66ed99ec","xai.json":"d7771a1450b21c1f6aee887ca6fea61b6e7b3fc13b4dee5cf72a71134fe623bc","xiaomi-token-plan-ams.json":"4dd8f838e21d7aa7caf3122d0b0b1e5a02a33bc012b96e6a75bd119334152d7a","xiaomi-token-plan-cn.json":"46414ff49973b95a0c14bd33e8992cc1938a50ce2c7cea9e2e5cc02de8f1df31","xiaomi-token-plan-sgp.json":"f5b3f66bf7bb7238592d4a9667cad983a008d7539a66e9896b02422622800935","xiaomi.json":"8b62c158d55d5a165f35cd72c1fc82ab89ff8e73f08960105fc41b822f236f69","zai-coding-cn.json":"2a7f59d15f588a97d218997883f2506dfc52d3ee320697d39f14213a050fc912","zai.json":"e9cc408e1756de8abc70148d63d89d11a63c65b7ef06ad0661cd1328e4209ba3"}}