@code-yeongyu/senpi-ai 2026.11.12 → 2026.11.13

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.
@@ -17,13 +17,11 @@ export type RegisteredApiProvider = {
17
17
  /** Kept by `clearApiProviders()`; removed only through `unregisterApiProviders(sourceId)`. */
18
18
  survivesClear?: boolean;
19
19
  };
20
- /** Browser-neutral shape installed by the node-only provider-scope subpath. */
20
+ /** Browser-neutral shape of the scope object the node-only provider-scope subpath places in the realm's registry. */
21
21
  export interface ProviderScopeAccess {
22
22
  state: "active" | "closed";
23
23
  overlay: Map<string, RegisteredApiProvider>;
24
24
  }
25
- /** Installs the optional node-only scope lookup without importing node APIs here. */
26
- export declare function installProviderScopeAccessor(accessor: () => ProviderScopeAccess | undefined): void;
27
25
  export declare function setProviderScopeStrictMode(enabled: boolean): void;
28
26
  export declare function registerApiProvider<TApi extends Api, TOptions extends StreamOptions>(provider: ApiProvider<TApi, TOptions>, sourceId?: string, options?: {
29
27
  survivesClear?: boolean;
@@ -32,6 +30,12 @@ export declare function registerApiProvider<TApi extends Api, TOptions extends S
32
30
  export declare function registerBuiltinApiProvider<TApi extends Api, TOptions extends StreamOptions>(provider: ApiProvider<TApi, TOptions>): void;
33
31
  export declare function getBuiltinApiProvider(api: Api): ApiProviderInternal | undefined;
34
32
  export declare function getApiProvider(api: Api): ApiProviderInternal | undefined;
33
+ /**
34
+ * `getApiProvider` for the built-in registration a module runs while it evaluates: the same resolution, but it never
35
+ * throws. Strict mode is shared by every copy in the realm, so a copy evaluated while it is on must still load
36
+ * (omo#12965); a closed scope reads as no scope. Every runtime lookup keeps `getApiProvider`.
37
+ */
38
+ export declare function getApiProviderAtEvaluation(api: Api): ApiProviderInternal | undefined;
35
39
  export declare function getApiProviders(): ApiProviderInternal[];
36
40
  export declare function unregisterApiProviders(sourceId: string): void;
37
41
  export declare function clearApiProviders(): void;
@@ -1,22 +1,39 @@
1
+ import { isActiveScopeWith, lookupProviderScopeRegistry } from "./provider-scope-registry.js";
1
2
  import { getRegisteredFauxProvider } from "./providers/faux.js";
2
3
  const apiProviderRegistry = new Map();
3
4
  const builtinApiProviderRegistry = new Map();
4
- let getProviderScope = () => undefined;
5
- let providerScopeStrictMode = false;
6
- /** Installs the optional node-only scope lookup without importing node APIs here. */
7
- export function installProviderScopeAccessor(accessor) {
8
- getProviderScope = accessor;
9
- }
5
+ // Strict mode this copy was given while the realm had no provider-scope instance. It stays in force for this copy
6
+ // until this copy sets it again; once an instance exists, every set goes to the instance (omo#12965).
7
+ let strictModeBeforeRegistry = false;
10
8
  export function setProviderScopeStrictMode(enabled) {
11
- providerScopeStrictMode = enabled;
9
+ const registry = lookupProviderScopeRegistry();
10
+ strictModeBeforeRegistry = registry === undefined && enabled;
11
+ registry?.setStrictMode(enabled);
12
+ }
13
+ function isProviderScopeAccess(scope) {
14
+ return isActiveScopeWith(scope, "overlay");
15
+ }
16
+ /**
17
+ * The active scope any pi-ai copy in this realm entered, read structurally. `"closed"` covers a closed scope and one
18
+ * whose members another copy shaped differently: both refuse.
19
+ */
20
+ function currentProviderScope() {
21
+ const scope = lookupProviderScopeRegistry()?.current();
22
+ if (scope === undefined)
23
+ return undefined;
24
+ return isProviderScopeAccess(scope) ? scope : "closed";
12
25
  }
13
26
  function getActiveProviderScope() {
14
- const scope = getProviderScope();
15
- if (scope?.state === "closed")
27
+ const scope = currentProviderScope();
28
+ if (scope === "closed")
16
29
  throw new Error("Provider scope is closed");
17
- if (!scope && providerScopeStrictMode)
30
+ if (scope !== undefined)
31
+ return scope;
32
+ // A strict mode that is not a boolean (a newer copy's value) reads as on.
33
+ const strict = strictModeBeforeRegistry || (lookupProviderScopeRegistry()?.strictMode() ?? false) !== false;
34
+ if (strict)
18
35
  throw new Error("Provider scope is required in strict mode");
19
- return scope;
36
+ return undefined;
20
37
  }
21
38
  function wrapStream(api, stream) {
22
39
  return (model, context, options) => {
@@ -59,7 +76,18 @@ export function getBuiltinApiProvider(api) {
59
76
  return builtinApiProviderRegistry.get(api)?.provider;
60
77
  }
61
78
  export function getApiProvider(api) {
62
- const scope = getActiveProviderScope();
79
+ return resolveApiProvider(api, getActiveProviderScope());
80
+ }
81
+ /**
82
+ * `getApiProvider` for the built-in registration a module runs while it evaluates: the same resolution, but it never
83
+ * throws. Strict mode is shared by every copy in the realm, so a copy evaluated while it is on must still load
84
+ * (omo#12965); a closed scope reads as no scope. Every runtime lookup keeps `getApiProvider`.
85
+ */
86
+ export function getApiProviderAtEvaluation(api) {
87
+ const scope = currentProviderScope();
88
+ return resolveApiProvider(api, scope === "closed" ? undefined : scope);
89
+ }
90
+ function resolveApiProvider(api, scope) {
63
91
  if (scope)
64
92
  return scope.overlay.get(api)?.provider ?? builtinApiProviderRegistry.get(api)?.provider;
65
93
  const faux = getRegisteredFauxProvider(api);
package/dist/compat.js CHANGED
@@ -54,7 +54,7 @@ export const getModels = getBuiltinModels;
54
54
  /** @deprecated Static catalog read. Use `getBuiltinProviders` from "@earendil-works/pi-ai/providers/all" or `Models.getProviders()`. */
55
55
  export const getProviders = getBuiltinProviders;
56
56
  export { getApiProvider, getApiProviders, registerApiProvider, unregisterApiProviders, } from "./api-registry.js";
57
- import { clearApiProviders, getApiProvider, registerApiProvider, registerBuiltinApiProvider, unregisterApiProviders, } from "./api-registry.js";
57
+ import { clearApiProviders, getApiProvider, getApiProviderAtEvaluation, registerApiProvider, registerBuiltinApiProvider, unregisterApiProviders, } from "./api-registry.js";
58
58
  export function registerFauxProvider(options = {}) {
59
59
  const core = createFauxCore(options);
60
60
  const sourceId = `faux-provider-${Math.random().toString(36).slice(2, 10)}`;
@@ -99,10 +99,11 @@ const builtinApiProviderInstances = new Map();
99
99
  export function registerBuiltInApiProviders() {
100
100
  for (const [api, streams] of BUILTIN_APIS) {
101
101
  registerBuiltinApiProvider({ api, stream: streams.stream, streamSimple: streams.streamSimple });
102
- if (!getApiProvider(api)) {
102
+ // This runs while the module evaluates, so it must not throw for the realm's strict mode (omo#12965).
103
+ if (!getApiProviderAtEvaluation(api)) {
103
104
  registerApiProvider({ api, stream: streams.stream, streamSimple: streams.streamSimple });
104
105
  }
105
- builtinApiProviderInstances.set(api, getApiProvider(api));
106
+ builtinApiProviderInstances.set(api, getApiProviderAtEvaluation(api));
106
107
  }
107
108
  }
108
109
  export function resetApiProviders() {
@@ -12,13 +12,11 @@ export type RegisteredImagesApiProvider = {
12
12
  provider: ImagesApiProviderInternal;
13
13
  sourceId?: string;
14
14
  };
15
- /** Browser-neutral shape installed by the node-only provider-scope subpath. */
15
+ /** Browser-neutral shape of the scope object the node-only provider-scope subpath places in the realm's registry. */
16
16
  export interface ImagesProviderScopeAccess {
17
17
  state: "active" | "closed";
18
18
  imagesOverlay: Map<string, RegisteredImagesApiProvider>;
19
19
  }
20
- /** Installs the optional node-only scope lookup without importing node APIs here. */
21
- export declare function installImagesProviderScopeAccessor(accessor: () => ImagesProviderScopeAccess | undefined): void;
22
20
  export declare function setImagesProviderScopeStrictMode(enabled: boolean): void;
23
21
  export declare function registerImagesApiProvider<TApi extends ImageApi, TOptions extends ImagesOptions>(provider: ImagesApiProvider<TApi, TOptions>, sourceId?: string): void;
24
22
  /** Registers a builtin once, retaining its immutable identity for active scopes. */
@@ -1,21 +1,33 @@
1
+ import { isActiveScopeWith, lookupProviderScopeRegistry } from "./provider-scope-registry.js";
1
2
  const imagesApiProviderRegistry = new Map();
2
3
  const builtinImagesApiProviderRegistry = new Map();
3
- let getImagesProviderScope = () => undefined;
4
- let imagesProviderScopeStrictMode = false;
5
- /** Installs the optional node-only scope lookup without importing node APIs here. */
6
- export function installImagesProviderScopeAccessor(accessor) {
7
- getImagesProviderScope = accessor;
8
- }
4
+ // Strict mode this copy was given while the realm had no provider-scope instance. It stays in force for this copy
5
+ // until this copy sets it again; once an instance exists, every set goes to the instance (omo#12965).
6
+ let strictModeBeforeRegistry = false;
9
7
  export function setImagesProviderScopeStrictMode(enabled) {
10
- imagesProviderScopeStrictMode = enabled;
8
+ const registry = lookupProviderScopeRegistry();
9
+ strictModeBeforeRegistry = registry === undefined && enabled;
10
+ registry?.setImagesStrictMode(enabled);
11
+ }
12
+ function isImagesProviderScopeAccess(scope) {
13
+ return isActiveScopeWith(scope, "imagesOverlay");
11
14
  }
15
+ /**
16
+ * The active scope any pi-ai copy in this realm entered, read structurally: a closed scope and one whose members
17
+ * another copy shaped differently both refuse. Outside a scope, a strict mode that is not a boolean reads as on.
18
+ */
12
19
  function getActiveImagesProviderScope() {
13
- const scope = getImagesProviderScope();
14
- if (scope?.state === "closed")
15
- throw new Error("Provider scope is closed");
16
- if (!scope && imagesProviderScopeStrictMode)
20
+ const registry = lookupProviderScopeRegistry();
21
+ const scope = registry?.current();
22
+ if (scope !== undefined) {
23
+ if (!isImagesProviderScopeAccess(scope))
24
+ throw new Error("Provider scope is closed");
25
+ return scope;
26
+ }
27
+ const strict = strictModeBeforeRegistry || (registry?.imagesStrictMode() ?? false) !== false;
28
+ if (strict)
17
29
  throw new Error("Provider scope is required in strict mode");
18
- return scope;
30
+ return undefined;
19
31
  }
20
32
  function wrapGenerateImages(api, generateImages) {
21
33
  return (model, context, options) => {
@@ -7,7 +7,11 @@ export declare class ProviderScope implements ProviderScopeAccess, ImagesProvide
7
7
  close(): void;
8
8
  }
9
9
  export declare function setProviderScopeStrictMode(enabled: boolean): void;
10
- /** The scope the caller is running in, or undefined outside any scope. */
10
+ /**
11
+ * The scope the caller is running in, or undefined outside any scope. A scope this copy cannot read refuses
12
+ * (`code: "PI_PROVIDER_SCOPE_UNREADABLE"`): it is never taken for "no scope", which would let a caller inside a
13
+ * session go on unscoped (omo#12965).
14
+ */
11
15
  export declare function activeProviderScope(): ProviderScope | undefined;
12
16
  export declare function runWithProviderScope<T>(scope: ProviderScope, fn: () => T): T;
13
17
  export declare function bindToProviderScope<TArgs extends unknown[], TResult>(fn: (...args: TArgs) => TResult): (...args: TArgs) => TResult;
@@ -1,7 +1,27 @@
1
1
  import { AsyncLocalStorage } from "node:async_hooks";
2
- import { installProviderScopeAccessor, setProviderScopeStrictMode as setRegistryProviderScopeStrictMode, } from "../api-registry.js";
3
- import { installImagesProviderScopeAccessor, setImagesProviderScopeStrictMode, } from "../images-api-registry.js";
4
- const providerScopeStorage = new AsyncLocalStorage();
2
+ import { realmRegistry } from "@earendil-works/pi-realm-registry";
3
+ import { setProviderScopeStrictMode as setRegistryProviderScopeStrictMode, } from "../api-registry.js";
4
+ import { setImagesProviderScopeStrictMode } from "../images-api-registry.js";
5
+ import { isActiveScopeWith, isProviderScopeRegistry, PROVIDER_SCOPE_REGISTRY_KEY, } from "../provider-scope-registry.js";
6
+ // The one place that creates the realm's provider-scope instance (omo#12965): the storage and both strict modes live
7
+ // in this closure, and every pi-ai copy in the realm reads them through the instance.
8
+ const providerScopes = realmRegistry(PROVIDER_SCOPE_REGISTRY_KEY, () => {
9
+ const storage = new AsyncLocalStorage();
10
+ let strict = false;
11
+ let imagesStrict = false;
12
+ return {
13
+ strictMode: () => strict,
14
+ setStrictMode: (enabled) => {
15
+ strict = enabled;
16
+ },
17
+ imagesStrictMode: () => imagesStrict,
18
+ setImagesStrictMode: (enabled) => {
19
+ imagesStrict = enabled;
20
+ },
21
+ run: (scope, fn) => storage.run(scope, fn),
22
+ current: () => storage.getStore(),
23
+ };
24
+ }, isProviderScopeRegistry);
5
25
  export class ProviderScope {
6
26
  constructor() {
7
27
  this.overlay = new Map();
@@ -14,25 +34,55 @@ export class ProviderScope {
14
34
  this.imagesOverlay.clear();
15
35
  }
16
36
  }
17
- installProviderScopeAccessor(() => providerScopeStorage.getStore());
18
- installImagesProviderScopeAccessor(() => providerScopeStorage.getStore());
37
+ /** A scope object any pi-ai copy in this realm entered: the same members, whichever copy's class built it. */
38
+ function isProviderScope(scope) {
39
+ if (typeof scope !== "object" || scope === null)
40
+ return false;
41
+ const state = Reflect.get(scope, "state");
42
+ return ((state === "active" || state === "closed") &&
43
+ Reflect.get(scope, "overlay") instanceof Map &&
44
+ Reflect.get(scope, "imagesOverlay") instanceof Map &&
45
+ typeof Reflect.get(scope, "close") === "function");
46
+ }
19
47
  export function setProviderScopeStrictMode(enabled) {
20
48
  setRegistryProviderScopeStrictMode(enabled);
21
49
  setImagesProviderScopeStrictMode(enabled);
22
50
  }
23
- /** The scope the caller is running in, or undefined outside any scope. */
51
+ /** The scope the caller is running in cannot be read: another pi-ai copy in the realm shaped it differently. */
52
+ class ProviderScopeUnreadableError extends Error {
53
+ constructor() {
54
+ super("The active provider scope cannot be read: another pi-ai copy in this process shaped it differently.");
55
+ this.code = "PI_PROVIDER_SCOPE_UNREADABLE";
56
+ this.name = "ProviderScopeUnreadableError";
57
+ }
58
+ }
59
+ /**
60
+ * The scope the caller is running in, or undefined outside any scope. A scope this copy cannot read refuses
61
+ * (`code: "PI_PROVIDER_SCOPE_UNREADABLE"`): it is never taken for "no scope", which would let a caller inside a
62
+ * session go on unscoped (omo#12965).
63
+ */
24
64
  export function activeProviderScope() {
25
- return providerScopeStorage.getStore();
65
+ const scope = providerScopes.current();
66
+ if (scope === undefined)
67
+ return undefined;
68
+ if (!isProviderScope(scope))
69
+ throw new ProviderScopeUnreadableError();
70
+ return scope;
26
71
  }
27
72
  export function runWithProviderScope(scope, fn) {
28
73
  if (scope.state === "closed")
29
74
  throw new Error("Provider scope is closed");
30
- return providerScopeStorage.run(scope, fn);
75
+ return providerScopes.run(scope, fn);
31
76
  }
32
77
  export function bindToProviderScope(fn) {
33
- const scope = providerScopeStorage.getStore();
34
- if (!scope)
78
+ const scope = providerScopes.current();
79
+ if (typeof scope !== "object" || scope === null)
35
80
  throw new Error("No active provider scope to bind");
36
- return (...args) => runWithProviderScope(scope, () => fn(...args));
81
+ return (...args) => {
82
+ // A scope another copy shaped differently refuses, as a closed one does.
83
+ if (!isActiveScopeWith(scope, "overlay"))
84
+ throw new Error("Provider scope is closed");
85
+ return providerScopes.run(scope, () => fn(...args));
86
+ };
37
87
  }
38
88
  //# sourceMappingURL=provider-scope.js.map
@@ -0,0 +1,27 @@
1
+ export declare const PROVIDER_SCOPE_REGISTRY_KEY = "@code-yeongyu/senpi/provider-scope/v1";
2
+ /**
3
+ * Provider strict mode and the active provider scope of every pi-ai copy in this realm (omo#12965).
4
+ *
5
+ * A realm can hold more than one copy of pi-ai (the bundled engine next to the SDK graph a plugin imports). Strict mode
6
+ * set in one copy and a scope entered by one copy must hold in all of them, or a second copy resolves providers from
7
+ * its global registry while the first one refuses. Only `node/provider-scope.ts` creates the instance, because only it
8
+ * may build an `AsyncLocalStorage`; this browser-neutral module looks the instance up and never creates one.
9
+ *
10
+ * Provider entries are not shared: each copy keeps its own maps. Inside a scope the entries live in the scope object,
11
+ * which every copy reads structurally. Values that cross copies are validated by the reader: a scope missing a member
12
+ * reads as closed, and a strict mode that is not a boolean reads as on.
13
+ */
14
+ export interface ProviderScopeRegistry {
15
+ strictMode(): unknown;
16
+ setStrictMode(enabled: boolean): void;
17
+ imagesStrictMode(): unknown;
18
+ setImagesStrictMode(enabled: boolean): void;
19
+ run<T>(scope: object, fn: () => T): T;
20
+ current(): unknown;
21
+ }
22
+ export declare function isProviderScopeRegistry(value: unknown): value is ProviderScopeRegistry;
23
+ /** The realm's instance, or `undefined` while no copy's `node/provider-scope` module has evaluated. */
24
+ export declare function lookupProviderScopeRegistry(): ProviderScopeRegistry | undefined;
25
+ /** Whether a scope object another copy may have placed is active and carries `overlayName` as a `Map`. */
26
+ export declare function isActiveScopeWith(scope: unknown, overlayName: "overlay" | "imagesOverlay"): boolean;
27
+ //# sourceMappingURL=provider-scope-registry.d.ts.map
@@ -0,0 +1,24 @@
1
+ import { hasFunctions, realmRegistryLookup } from "@earendil-works/pi-realm-registry";
2
+ export const PROVIDER_SCOPE_REGISTRY_KEY = "@code-yeongyu/senpi/provider-scope/v1";
3
+ export function isProviderScopeRegistry(value) {
4
+ return hasFunctions(value, [
5
+ "strictMode",
6
+ "setStrictMode",
7
+ "imagesStrictMode",
8
+ "setImagesStrictMode",
9
+ "run",
10
+ "current",
11
+ ]);
12
+ }
13
+ /** The realm's instance, or `undefined` while no copy's `node/provider-scope` module has evaluated. */
14
+ export function lookupProviderScopeRegistry() {
15
+ return realmRegistryLookup(PROVIDER_SCOPE_REGISTRY_KEY, isProviderScopeRegistry);
16
+ }
17
+ /** Whether a scope object another copy may have placed is active and carries `overlayName` as a `Map`. */
18
+ export function isActiveScopeWith(scope, overlayName) {
19
+ return (typeof scope === "object" &&
20
+ scope !== null &&
21
+ Reflect.get(scope, "state") === "active" &&
22
+ Reflect.get(scope, overlayName) instanceof Map);
23
+ }
24
+ //# sourceMappingURL=provider-scope-registry.js.map
@@ -1 +1 @@
1
- {"schemaVersion":6,"generatedAt":"2026-11-12T02:00:55.872Z","structureHash":"154f0202edda506696e15044b183fec757783d5bee24981558cfd53cc456cf2f","files":{"alibaba-token-plan.json":"9f4d42cc765b2a875bcdcaa392bfdc1323c88968309baf9db9f611a26c595c73","amazon-bedrock.json":"bff6e399b377ed5add61402119cc69daed1cfa7084d8e1efa3ae227da34cf323","ant-ling.json":"628feab3ef6c7d80ce96f75999804e1d9f05fec3851e5302e30fff3b69db90f6","anthropic.json":"4e1e3185a5e9c8766d7e3939c26f854e76a7fa95313efeda5c81c31f89a52de8","azure-openai-responses.json":"fd64c6a2a99fa87d768ed2f75f5c7813876df1dbe2f0d1776f7d9bd7ce2e61e4","bai.json":"7e6861aaf27d8af34e1771c6092602194fcec0a0046e6adfab9c3ee54d32b99f","baseten.json":"47d10c8050601eb88757def4fc957cdba769dacec4aeb3b0c3f39c41e442330e","cerebras.json":"2eb969b2956844f9a641d3de52c19f1791293c58f607282fb3b0ebfe85ff66f8","chatgpt-subscription.json":"98320f1d51709d26ca047b3d6e3191cfe2f192f1b27897cbb492f47b0e5a5030","cloudflare-ai-gateway.json":"c5772b2280e868cfe173622fead33ff4db4463de32d3314ea1cdb7f390368904","cloudflare-workers-ai.json":"1b9ad4360bde817f0ea358431020308f1052840e2278a57a93629f1790072d2e","deepseek.json":"10a296fb3e898f7715c80890c8af0af4f5fd58f22dbcd6612fdc5d762157ccdc","fireworks.json":"d4f32ce769130720bde6533ecce65855130166b1407e9cb654222789751d152c","github-copilot.json":"0d493d1d7eccc92f4db617bf5406f9b79dc3bd6a45a990cb7d7fc9274b639ed1","google-vertex.json":"3bc9315b05d3814efe0eabf4d0c06dbc31b78f1c591bb4e4633b8f1a6da67bc9","google.json":"28b61b91ff198289fb76eeac1e55ac8a1f3a98b6c3356b116769a8db6f32ecfc","groq.json":"087df37206e9eed8b10f1e558e4c496289bef60074b7e8afba4f20fb102b4ec2","huggingface.json":"209cdcf205961ef2ff203486da614232a86a069ebe0e98266189a14a235fac8f","meta.json":"5cb9af55aeb384c07afb18ded1eff4cc8aace69556cd019ab758d987afb40495","minimax-cn.json":"70df757e95e9ea2275bf451956b58a746020835f6cbcbd1a644d7fad5b9941d3","minimax.json":"747038b05f4fc24e41405e8bc810f893d7d5121e214e35e6f812f775769a3806","mistral.json":"aafecc66686645b1baa8c90e81c02856115f09999ff507f9bee004d2e1c77a28","moonshotai-cn.json":"a953eace729ef96c91195d477c63c776a1c40aa36085b61236ca1be0fe5b9337","moonshotai.json":"0435f9dc4e532c0764b6d33d8dfa83ce5fccdbcab54224c5ae74ec2d965290f5","nvidia.json":"078fae404fc622ca6461f16a74791fedafe44976a6c3323b6ba779729823d4ff","openai.json":"80845240dd2e4cac670f8040ea7bdda867ca84cc0e4943b6b1b88a1676c0dbc7","opencode-go.json":"cf864a6efd24cc340f53c0ce42d1171a28c5cdbb22dad137aa365e4a4818800d","opencode.json":"9f21d5d64fda4c912ea25026050b18b956ed74221126e4e34de04019f179905a","opengateway.json":"58038304b6677128627b8f21cd8c3f40437f07521ad180a1a00557f7e3a989f4","openrouter.json":"c27fe6f8392567faa3892aca4adf1d1e58dc4390f8125af4383fc6482d4c3c7c","qwen-token-plan-cn.json":"751b18bd443fceb16659ea33013fed90fbf3bbdb4e0ffd7607c93cee2b4cf40d","qwen-token-plan-individual.json":"35ffb0ba1a1ce3f68fc73262dd5e07fbcb5bf5911ad1e6e17bc0621e2894676a","qwen-token-plan.json":"e59b0a45e238578f80d0eea937a093b9cec7cb93751ae20a9e88b16c09eb5cdd","radius.json":"56060b6d6918569597c7a18ace8aceb270dbc7112e2c6de77ec63d47e1e4fa2f","together.json":"8b241bf22b25d8a4bf6d8effe45cebadd193a25a9f0ecc68039d395bf8c6e3bf","typesafe.json":"83409437dbf4c353ac413c0db4e7cf29902fc35e0e0197bdb4eeda2d7f3b07cd","venice.json":"26e2d7aaff893a91ae9efac01827e90c322dc13265ad47c82e9abe7ab6ff7d9f","vercel-ai-gateway.json":"bea147d35648b0c99ac1fa7fc41c9e37fa9037c22fb46a3dc46b7b4b5c683cca","xai.json":"cf3f475fe5a13625f858171900ba3456c4d95ebb0bac5060cc25e29bb31d3457","xiaomi-token-plan-ams.json":"7fa339ba5675460b1ff4e5bca9e8ad0aa60b0277d75a989b1c196aa6ca2af34d","xiaomi-token-plan-cn.json":"ef7917c6ea0d3edc655c8a52082ee5f1330658aa6f10199d8f164eb4605ef0a0","xiaomi-token-plan-sgp.json":"addda93f6b70ba879db97e3cfd2e4f2efc7cda47d7daa78c23c5b0e51162de5c","xiaomi.json":"5a42caf49d3e4d7946d60386e9899c2146bf8e3cbaff4c576ee4f49b398cc11c","zai-coding-cn.json":"2b6f85e04b5c568e320b1bde25b1c1614af9342e4c1ba0e1d5bb248aaf50cfe9","zai.json":"e9cc408e1756de8abc70148d63d89d11a63c65b7ef06ad0661cd1328e4209ba3"}}
1
+ {"schemaVersion":6,"generatedAt":"2026-11-13T14:54:41.572Z","structureHash":"3937c9896419b1216de33b58e4d370c8209da4194eca9a68c2102e62bcabe300","files":{"alibaba-token-plan.json":"9f4d42cc765b2a875bcdcaa392bfdc1323c88968309baf9db9f611a26c595c73","amazon-bedrock.json":"bff6e399b377ed5add61402119cc69daed1cfa7084d8e1efa3ae227da34cf323","ant-ling.json":"628feab3ef6c7d80ce96f75999804e1d9f05fec3851e5302e30fff3b69db90f6","anthropic.json":"4e1e3185a5e9c8766d7e3939c26f854e76a7fa95313efeda5c81c31f89a52de8","azure-openai-responses.json":"fd64c6a2a99fa87d768ed2f75f5c7813876df1dbe2f0d1776f7d9bd7ce2e61e4","bai.json":"7e6861aaf27d8af34e1771c6092602194fcec0a0046e6adfab9c3ee54d32b99f","baseten.json":"47d10c8050601eb88757def4fc957cdba769dacec4aeb3b0c3f39c41e442330e","cerebras.json":"2eb969b2956844f9a641d3de52c19f1791293c58f607282fb3b0ebfe85ff66f8","chatgpt-subscription.json":"98320f1d51709d26ca047b3d6e3191cfe2f192f1b27897cbb492f47b0e5a5030","cloudflare-ai-gateway.json":"307da650bbefbd4654191363672410c7b01c93d825b4f6089ce36d86c9f61bc4","cloudflare-workers-ai.json":"8b3502ff0ba0adb6d1388de33fea839289ad1968faed15161fcef8dc6e140a96","deepseek.json":"10a296fb3e898f7715c80890c8af0af4f5fd58f22dbcd6612fdc5d762157ccdc","fireworks.json":"d4f32ce769130720bde6533ecce65855130166b1407e9cb654222789751d152c","github-copilot.json":"0d493d1d7eccc92f4db617bf5406f9b79dc3bd6a45a990cb7d7fc9274b639ed1","google-vertex.json":"df3ac69f7a22704b75486658bd422e231d345d73c0700f08ea517df1b23397f8","google.json":"5f7a3c61abd19b81a4c926375d4109d4723cd06e36da555a719616abe214eeda","groq.json":"087df37206e9eed8b10f1e558e4c496289bef60074b7e8afba4f20fb102b4ec2","huggingface.json":"209cdcf205961ef2ff203486da614232a86a069ebe0e98266189a14a235fac8f","meta.json":"5cb9af55aeb384c07afb18ded1eff4cc8aace69556cd019ab758d987afb40495","minimax-cn.json":"70df757e95e9ea2275bf451956b58a746020835f6cbcbd1a644d7fad5b9941d3","minimax.json":"747038b05f4fc24e41405e8bc810f893d7d5121e214e35e6f812f775769a3806","mistral.json":"f3c2ed019d2588aa4d1af115be68d0363596dbd7605f44e9a5bc650b3665005a","moonshotai-cn.json":"a953eace729ef96c91195d477c63c776a1c40aa36085b61236ca1be0fe5b9337","moonshotai.json":"0435f9dc4e532c0764b6d33d8dfa83ce5fccdbcab54224c5ae74ec2d965290f5","nvidia.json":"33afb8395f93eb07e88d4026775d471a6457b77134fd45cdb09b822b80cfae08","openai.json":"80845240dd2e4cac670f8040ea7bdda867ca84cc0e4943b6b1b88a1676c0dbc7","opencode-go.json":"cf864a6efd24cc340f53c0ce42d1171a28c5cdbb22dad137aa365e4a4818800d","opencode.json":"bea56d7a0c23e7a022247049c9afcda75088ecb5128addc506f256c37fccb120","opengateway.json":"e813adea9d55c4ee2a3801c9faa69e733d076ca6b797ecfe54392e32911d2c00","openrouter.json":"3ee9e130b6bf36136d083ee624a60eb3cb439933b65c6dff3284da4c666438ff","qwen-token-plan-cn.json":"751b18bd443fceb16659ea33013fed90fbf3bbdb4e0ffd7607c93cee2b4cf40d","qwen-token-plan-individual.json":"35ffb0ba1a1ce3f68fc73262dd5e07fbcb5bf5911ad1e6e17bc0621e2894676a","qwen-token-plan.json":"e59b0a45e238578f80d0eea937a093b9cec7cb93751ae20a9e88b16c09eb5cdd","radius.json":"e95ce559b43ca79301b2e53a8cfb8dca3ae4cebd90201eb7d73e02722cb31c64","together.json":"8b241bf22b25d8a4bf6d8effe45cebadd193a25a9f0ecc68039d395bf8c6e3bf","typesafe.json":"83409437dbf4c353ac413c0db4e7cf29902fc35e0e0197bdb4eeda2d7f3b07cd","venice.json":"6026120c2ead5083299eeaee7cb43ba6ebdae294b442cf42ddcb6b834e62bb60","vercel-ai-gateway.json":"aa68153eb440fcf6a2aaa749ae8d57109087969cdb2260354196a13f64eae769","xai.json":"cf3f475fe5a13625f858171900ba3456c4d95ebb0bac5060cc25e29bb31d3457","xiaomi-token-plan-ams.json":"7fa339ba5675460b1ff4e5bca9e8ad0aa60b0277d75a989b1c196aa6ca2af34d","xiaomi-token-plan-cn.json":"ef7917c6ea0d3edc655c8a52082ee5f1330658aa6f10199d8f164eb4605ef0a0","xiaomi-token-plan-sgp.json":"addda93f6b70ba879db97e3cfd2e4f2efc7cda47d7daa78c23c5b0e51162de5c","xiaomi.json":"5a42caf49d3e4d7946d60386e9899c2146bf8e3cbaff4c576ee4f49b398cc11c","zai-coding-cn.json":"2b6f85e04b5c568e320b1bde25b1c1614af9342e4c1ba0e1d5bb248aaf50cfe9","zai.json":"e9cc408e1756de8abc70148d63d89d11a63c65b7ef06ad0661cd1328e4209ba3"}}