@codeworksh/aikit 0.11.0 → 0.12.0-canary.47.1.g3f60acd1
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/cli.mjs +3 -3
- package/{copilot-JLgwmznn.mjs → copilot-DvUXC6Kx.mjs} +2 -2
- package/{copilot-JLgwmznn.mjs.map → copilot-DvUXC6Kx.mjs.map} +1 -1
- package/{copilot-headers-BvQ3FFn-.mjs → copilot-headers-BLnBaJyp.mjs} +2 -2
- package/{copilot-headers-BvQ3FFn-.mjs.map → copilot-headers-BLnBaJyp.mjs.map} +1 -1
- package/{github-copilot-C7oJ2Tfp.mjs → github-copilot-BcmOr0jd.mjs} +2 -2
- package/{github-copilot-C7oJ2Tfp.mjs.map → github-copilot-BcmOr0jd.mjs.map} +1 -1
- package/github-copilot-llyP2NK4.mjs +3 -0
- package/index.d.mts +3 -3
- package/index.mjs +5 -5
- package/index.mjs.map +1 -1
- package/model-Cjp-Dr8V.mjs +13955 -0
- package/model-Cjp-Dr8V.mjs.map +1 -0
- package/{model-DCfjY0fS.d.mts → model-D3wc9-u4.d.mts} +42 -19
- package/modelgen-BdiCqi-R.mjs +730 -0
- package/modelgen-BdiCqi-R.mjs.map +1 -0
- package/modelgen.d.mts +20 -3
- package/modelgen.mjs +61 -2
- package/modelgen.mjs.map +1 -0
- package/oauth/github/copilot.mjs +1 -1
- package/{openai-codex-Dj0oh0UV.mjs → openai-codex-C1Yb02kM.mjs} +2 -2
- package/{openai-codex-Dj0oh0UV.mjs.map → openai-codex-C1Yb02kM.mjs.map} +1 -1
- package/openai-codex-CHxShIN3.mjs +2 -0
- package/package.json +10 -10
- package/{registry-CfGgGfSs.mjs → registry-u49t0S4S.mjs} +4 -4
- package/{registry-CfGgGfSs.mjs.map → registry-u49t0S4S.mjs.map} +1 -1
- package/github-copilot-CLJx-bcP.mjs +0 -3
- package/model-D-FoGzVN.mjs +0 -522
- package/model-D-FoGzVN.mjs.map +0 -1
- package/modelgen-D6UBM1fq.mjs +0 -561
- package/modelgen-D6UBM1fq.mjs.map +0 -1
- package/openai-codex-CIBVNhQx.mjs +0 -2
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"modelgen-BdiCqi-R.mjs","names":["Model.effortThinkingLevels","Model.normalizeInput","OpenRouter.BASE_URL","OpenRouter.PROVIDER_ID","Filesystem.readJson","Model.effortThinkingLevels","Model.isAnthropicAdaptiveThinkingModel","OpenRouter.catalog","path","ModelCatalog.path","Filesystem.writeJsonAtomic","Model.normalizeInput"],"sources":["../../src/model/openrouter.ts","../../src/cli/modelgen.ts"],"sourcesContent":["/*\n * @file OpenRouter's own model listing, read two ways.\n *\n * The generator builds the `openrouter` catalog from the public `GET /models` (pi): it carries\n * the reasoning efforts each model accepts, which models.dev only covers for some. At runtime\n * `GET /models/user` narrows that catalog to what one key may use, with that key's limits and\n * prices. Both go through the same field readers.\n */\nimport * as Model from \"./model.ts\";\n\nexport const PROVIDER_ID = \"openrouter\";\nexport const BASE_URL = \"https://openrouter.ai/api/v1\";\nconst NPM = \"@openrouter/ai-sdk-provider\";\nconst USER_MODELS_TIMEOUT_MS = 15_000;\n\n/** OpenRouter's per-token prices, as decimal strings. */\ninterface Pricing {\n\tprompt?: string;\n\tcompletion?: string;\n\tinput_cache_read?: string;\n\tinput_cache_write?: string;\n\t/** Conditional prices: `min_prompt_tokens` selects prompt-length pricing, `utc_*` time-of-day pricing. */\n\toverrides?: Array<{\n\t\tmin_prompt_tokens?: number;\n\t\tutc_start?: number;\n\t\tutc_end?: number;\n\t\tutc_days?: string[];\n\t\tprompt?: string;\n\t\tcompletion?: string;\n\t\tinput_cache_read?: string;\n\t\tinput_cache_write?: string;\n\t}>;\n}\n\n/** The fields read from an entry of `GET /models` and `GET /models/user`. */\nexport interface Entry {\n\tid: string;\n\tname?: string;\n\tcontext_length?: number | null;\n\ttop_provider?: { context_length?: number | null; max_completion_tokens?: number | null };\n\tpricing?: Pricing;\n\tsupported_parameters?: string[];\n\tarchitecture?: { input_modalities?: string[] };\n\treasoning?: {\n\t\tmandatory?: boolean;\n\t\tsupported_efforts?: string[];\n\t} | null;\n}\n\n/**\n * $/token to $/1M tokens. Missing, invalid and negative prices use the fallback: OpenRouter\n * reports -1 for router models such as `openrouter/auto`, whose price depends on the model it picks.\n */\nfunction perMillion(value: string | undefined, fallback: number): number {\n\tconst perToken = Number.parseFloat(value ?? \"\");\n\treturn perToken >= 0 ? Number((perToken * 1_000_000).toFixed(6)) : fallback;\n}\n\n/**\n * Prompt-length overrides become request-wide tiers; a rate a tier does not list keeps the base\n * price. Time-of-day overrides are skipped: the cost model cannot express them.\n */\nexport function cost(pricing: Pricing | undefined): Model.Info[\"cost\"] {\n\tconst base = {\n\t\tinput: perMillion(pricing?.prompt, 0),\n\t\toutput: perMillion(pricing?.completion, 0),\n\t\tcacheRead: perMillion(pricing?.input_cache_read, 0),\n\t\tcacheWrite: perMillion(pricing?.input_cache_write, 0),\n\t};\n\tconst tiers = (pricing?.overrides ?? []).flatMap((override) => {\n\t\tif (\n\t\t\toverride.min_prompt_tokens === undefined ||\n\t\t\toverride.utc_start !== undefined ||\n\t\t\toverride.utc_end !== undefined ||\n\t\t\toverride.utc_days !== undefined\n\t\t) {\n\t\t\treturn [];\n\t\t}\n\t\treturn [\n\t\t\t{\n\t\t\t\tinputTokensAbove: override.min_prompt_tokens,\n\t\t\t\tinput: perMillion(override.prompt, base.input),\n\t\t\t\toutput: perMillion(override.completion, base.output),\n\t\t\t\tcacheRead: perMillion(override.input_cache_read, base.cacheRead),\n\t\t\t\tcacheWrite: perMillion(override.input_cache_write, base.cacheWrite),\n\t\t\t},\n\t\t];\n\t});\n\treturn tiers.length > 0 ? { ...base, tiers } : base;\n}\n\n/**\n * `supported_efforts` uses models.dev's effort vocabulary. Off maps to `none` unless reasoning is\n * mandatory; a mandatory model without listed efforts can only refuse off.\n */\nexport function thinkingLevels(reasoning: Entry[\"reasoning\"]): Model.ThinkingLevelMap | undefined {\n\tif (!reasoning) return undefined;\n\tconst map = Model.effortThinkingLevels(reasoning.supported_efforts ?? []);\n\tif (!map) return reasoning.mandatory === true ? { off: null } : undefined;\n\treturn { ...map, off: reasoning.mandatory === true ? null : \"none\" };\n}\n\n/**\n * The catalog entry for one listed model, or undefined for one an agent cannot use: no tool\n * calling, or a `:batch` variant, whose asynchronous pricing an interactive turn never gets.\n */\nexport function toModel(entry: Entry): Model.Info | undefined {\n\tif (!entry.supported_parameters?.includes(\"tools\") || entry.id.endsWith(\":batch\")) return undefined;\n\tconst thinkingLevelMap = thinkingLevels(entry.reasoning);\n\treturn {\n\t\tid: entry.id,\n\t\tname: entry.name ?? entry.id,\n\t\tprovider: { id: PROVIDER_ID, name: \"OpenRouter\", source: \"api\", env: [\"OPENROUTER_API_KEY\"] },\n\t\tbaseUrl: BASE_URL,\n\t\treasoning: entry.supported_parameters.includes(\"reasoning\"),\n\t\t...(thinkingLevelMap ? { thinkingLevelMap } : {}),\n\t\tinput: Model.normalizeInput(entry.architecture?.input_modalities),\n\t\tcost: cost(entry.pricing),\n\t\t// `||`: OpenRouter reports a missing limit as absent, null or 0.\n\t\tcontextWindow: entry.top_provider?.context_length || entry.context_length || 4096,\n\t\tmaxTokens: entry.top_provider?.max_completion_tokens || 4096,\n\t\tnpm: NPM,\n\t\tapi: { id: entry.id, url: BASE_URL, method: Model.APIMethodEnum.languageModel },\n\t\tproviderOptionsKey: PROVIDER_ID,\n\t\tprotocol: Model.KnownProviderEnum.openrouter,\n\t};\n}\n\nfunction entries(body: unknown): Entry[] {\n\tif (typeof body !== \"object\" || body === null || !(\"data\" in body) || !Array.isArray(body.data)) {\n\t\tthrow new Error(\"invalid OpenRouter model list\");\n\t}\n\treturn body.data.filter(\n\t\t(entry: unknown): entry is Entry =>\n\t\t\ttypeof entry === \"object\" && entry !== null && \"id\" in entry && typeof entry.id === \"string\",\n\t);\n}\n\n/** The public `GET /models`, built into catalog entries keyed by id. */\nexport function catalog(body: unknown): Record<string, Model.Info> {\n\tconst models: Record<string, Model.Info> = {};\n\tfor (const entry of entries(body)) {\n\t\tconst model = toModel(entry);\n\t\tif (model) models[model.id] = model;\n\t}\n\treturn models;\n}\n\n/**\n * Restrict OpenRouter models to those `key` may use, with the key's limits and prices from\n * `GET /models/user` (pi). A missing limit keeps the catalog value. When the endpoint rejects the\n * key (401/403) or does not exist (404), or allows nothing, the models come back unchanged.\n */\nexport async function personalize(\n\tmodels: Record<string, Model.Info>,\n\tkey: string,\n\toptions: { readonly baseUrl?: string; readonly signal?: AbortSignal } = {},\n): Promise<Record<string, Model.Info>> {\n\tconst signal = AbortSignal.timeout(USER_MODELS_TIMEOUT_MS);\n\tconst response = await fetch(`${(options.baseUrl ?? BASE_URL).replace(/\\/+$/, \"\")}/models/user`, {\n\t\theaders: { accept: \"application/json\", authorization: `Bearer ${key}` },\n\t\tsignal: options.signal ? AbortSignal.any([options.signal, signal]) : signal,\n\t});\n\tif (response.status === 401 || response.status === 403 || response.status === 404) return models;\n\tif (!response.ok) throw new Error(`OpenRouter model list request failed: ${response.status}`);\n\tconst allowed = new Map(entries(await response.json()).map((entry) => [entry.id, entry]));\n\n\tconst personal: Record<string, Model.Info> = {};\n\tfor (const [id, model] of Object.entries(models)) {\n\t\tconst entry = allowed.get(id);\n\t\tif (!entry) continue;\n\t\tpersonal[id] = {\n\t\t\t...model,\n\t\t\tcontextWindow: entry.top_provider?.context_length || entry.context_length || model.contextWindow,\n\t\t\tmaxTokens: entry.top_provider?.max_completion_tokens || model.maxTokens,\n\t\t\tcost: entry.pricing ? cost(entry.pricing) : model.cost,\n\t\t};\n\t}\n\treturn Object.keys(personal).length > 0 ? personal : models;\n}\n\nexport * as OpenRouter from \"./openrouter.ts\";\n","import { resolve } from \"node:path\";\nimport { mapValues, pick, pickBy, pipe } from \"remeda\";\nimport type { CommandModule } from \"yargs\";\nimport { DEFAULT_AI_SDK_FALLBACK, isAISDKPackage, protocolForPackage } from \"../llm/registry.ts\";\nimport * as ModelCatalog from \"../model/catalog.ts\";\nimport * as Model from \"../model/model.ts\";\nimport { OpenRouter } from \"../model/openrouter.ts\";\nimport { GITHUB_COPILOT_STATIC_HEADERS } from \"../providers/github-copilot/copilot-headers.ts\";\nimport * as Filesystem from \"../utils/filesystem.ts\";\n\nconst DEFAULT_PROVIDER_BASE_URLS: Partial<Record<Model.KnownProviderEnum, string>> = {\n\t[Model.KnownProviderEnum.anthropic]: \"https://api.anthropic.com/v1\",\n\t[Model.KnownProviderEnum.openai]: \"https://api.openai.com/v1\",\n\t[Model.KnownProviderEnum.openrouter]: OpenRouter.BASE_URL,\n\t[Model.KnownProviderEnum.xai]: \"https://api.x.ai/v1\",\n};\n\ninterface ModelsDevCost {\n\tinput?: number;\n\toutput?: number;\n\tcache_read?: number;\n\tcache_write?: number;\n}\n\ninterface ModelsDevModel {\n\tid: string;\n\tname: string;\n\tfamily: string;\n\tattachment: boolean;\n\treasoning?: boolean;\n\ttool_call?: boolean;\n\ttemperature?: boolean;\n\tknowledge?: string | boolean;\n\trelease_date: string;\n\tlast_updated: string;\n\tmodalities: {\n\t\tinput?: string[];\n\t\toutput: string[];\n\t};\n\topen_weights: boolean;\n\tbaseUrl?: string;\n\theaders?: Record<string, string>;\n\tcost?: ModelsDevCost & {\n\t\ttiers?: Array<ModelsDevCost & { tier?: { type?: string; size?: number } }>;\n\t};\n\treasoning_options?: Array<{\n\t\ttype?: string;\n\t\tvalues?: Array<string | null>;\n\t\tmin?: number;\n\t\tmax?: number;\n\t}>;\n\tstatus?: string;\n\tlimit?: {\n\t\tcontext?: number;\n\t\toutput?: number;\n\t};\n\tstructured_output?: boolean;\n\tprovider?: {\n\t\tnpm?: string;\n\t\tapi?: string;\n\t\theaders?: Record<string, string>;\n\t};\n\t/** Request variants such as OpenAI's `service_tier: \"priority\"`, each with its own price. */\n\texperimental?: {\n\t\tmodes?: Record<string, { cost?: ModelsDevCost; provider?: { body?: Record<string, unknown> } }>;\n\t};\n}\n\ninterface ModelsDevProvider {\n\tid: string;\n\tenv: string[];\n\tnpm?: string;\n\tapi?: string;\n\tname: string;\n\tdoc?: string; // reference documentation link\n\tkey?: string; // runtime placeholder for api/oauth key\n\theaders?: Record<string, string>; // custom overrides at provider level\n\tmodels: Record<string, ModelsDevModel>;\n}\n\nexport type BuiltInModels = Model.BuiltInModels;\n\n// Doesn't represent the full spec from models.dev.\n// Represents the provider entries on a best-effort basis.\ntype ModelsDevCatalog = Record<string, ModelsDevProvider>;\n\n/** The catalog's sources, fetched: models.dev, and OpenRouter's own listing when it answered. */\nexport interface Sources {\n\treadonly modelsDev: ModelsDevCatalog;\n\treadonly openRouter?: unknown;\n}\n\n/** Providers bundled with aikit as the baseline catalog, read until a generated one exists. */\nexport const BASELINE_PROVIDERS = [\"anthropic\", \"openai\", OpenRouter.PROVIDER_ID] as const;\n\nfunction modelsDevURL(): string {\n\treturn process.env.CODEWORK_MODELS_DEV_URL || \"https://models.dev\";\n}\n\nfunction modelsDevPath(): string | undefined {\n\treturn process.env.CODEWORK_MODELS_DEV_FILE;\n}\n\nasync function pullModelsDevData(): Promise<ModelsDevCatalog> {\n\tconst path = modelsDevPath();\n\tif (path) {\n\t\tconst result = await Filesystem.readJson<ModelsDevCatalog>(path).catch(() => undefined);\n\t\tif (result) return result;\n\t}\n\n\tconst response = await fetch(`${modelsDevURL()}/api.json`);\n\tif (!response.ok) throw new Error(`models.dev responded ${response.status} ${response.statusText}`);\n\treturn (await response.json()) as ModelsDevCatalog;\n}\n\n/** OpenRouter's public listing, or undefined when it cannot be had: models.dev's copy stands in. */\nasync function pullOpenRouterData(): Promise<unknown> {\n\ttry {\n\t\tconst response = await fetch(`${OpenRouter.BASE_URL}/models`, { signal: AbortSignal.timeout(30_000) });\n\t\treturn response.ok ? await response.json() : undefined;\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\nfunction toModelValue(providerId: string, provider: ModelsDevProvider, model: ModelsDevModel): Model.Info | undefined {\n\treturn applyModification(providerId, provider, model);\n}\n\n// models.dev lists this alias, but OpenAI's APIs do not accept it (pi).\nconst MODELS_DEV_UNSUPPORTED_MODEL_IDS = new Set([\"openai/gpt-5.6\"]);\n\nfunction usable(providerId: string, provider: ModelsDevProvider, model: ModelsDevModel): boolean {\n\treturn (\n\t\tBoolean(model.tool_call) &&\n\t\t!MODELS_DEV_UNSUPPORTED_MODEL_IDS.has(`${providerId}/${model.id}`) &&\n\t\t// If `resolveModelNpm` fallbacks to `@ai-sdk/openai-compatible`\n\t\t// isAISDKPakage will be truthy, modify resolveModelNpm for custom logic if needed.\n\t\t// Keep `isAISDKPackage` as readonly for supported implemenatations key check\n\t\tisAISDKPackage(resolveModelNpm(provider, model))\n\t);\n}\n\nfunction loadBuiltInFromModelsDev(catalog: ModelsDevCatalog) {\n\treturn pipe(\n\t\tcatalog,\n\t\tpickBy((provider, providerId) =>\n\t\t\tObject.values(provider.models).some((model) => usable(providerId, provider, model)),\n\t\t),\n\t\tmapValues((provider, providerId) =>\n\t\t\tpipe(\n\t\t\t\tprovider.models,\n\t\t\t\tpickBy((model) => usable(providerId, provider, model)),\n\t\t\t\tmapValues((model) => toModelValue(providerId, provider, model)),\n\t\t\t\tpickBy((model): model is Model.Info => model !== undefined),\n\t\t\t),\n\t\t),\n\t) as BuiltInModels;\n}\n\ntype ThinkingLevelMap = NonNullable<Model.Info[\"thinkingLevelMap\"]>;\n\nfunction resolveModelNpm(provider: ModelsDevProvider, model: ModelsDevModel): string {\n\treturn model.provider?.npm ?? provider.npm ?? DEFAULT_AI_SDK_FALLBACK;\n}\n\nfunction resolveModelBaseUrl(provider: ModelsDevProvider, model: ModelsDevModel): string {\n\tconst npm = resolveModelNpm(provider, model);\n\tconst protocol = protocolForPackage(npm);\n\treturn model.baseUrl ?? model.provider?.api ?? provider.api ?? DEFAULT_PROVIDER_BASE_URLS[protocol] ?? \"\";\n}\n\nfunction resolveModelAPIMethod(npm: string): Model.APIMethodEnum {\n\tconst protocol = protocolForPackage(npm);\n\t// `By default, xai(modelId) uses the Chat API.\n\t// To use the Responses API with server-side agentic tools, explicitly use xai.responses(modelId).`\n\t// References: https://ai-sdk.dev/providers/ai-sdk-providers/xai\n\tif (protocol === Model.KnownProviderEnum.openai || protocol === Model.KnownProviderEnum.xai) {\n\t\treturn Model.APIMethodEnum.responses;\n\t}\n\treturn Model.APIMethodEnum.languageModel;\n}\n\nfunction resolveProviderOptionsKey(protocol: Model.KnownProviderEnum): string {\n\tif (protocol === Model.KnownProviderEnum.openaiCompatible) return \"openai-compatible\";\n\tif (protocol === Model.KnownProviderEnum.googleVertex) return \"google-vertex\";\n\tif (protocol === Model.KnownProviderEnum.googleVertexAnthropic) return \"google-vertex-anthropic\";\n\treturn protocol;\n}\n\nfunction roundCost(value: number): number {\n\treturn Number(value.toFixed(6));\n}\n\n/** models.dev prices, with its context tiers; a rate a tier does not list keeps the base price (pi). */\nfunction modelsDevCost(cost: ModelsDevModel[\"cost\"]): Model.Info[\"cost\"] {\n\tconst base = {\n\t\tinput: cost?.input ?? 0,\n\t\toutput: cost?.output ?? 0,\n\t\tcacheRead: cost?.cache_read ?? 0,\n\t\tcacheWrite: cost?.cache_write ?? 0,\n\t};\n\tconst tiers = cost?.tiers?.flatMap((tier) => {\n\t\tconst context = tier.tier;\n\t\tif (context?.type !== \"context\" || context.size === undefined) return [];\n\t\treturn [\n\t\t\t{\n\t\t\t\tinputTokensAbove: context.size,\n\t\t\t\tinput: tier.input ?? base.input,\n\t\t\t\toutput: tier.output ?? base.output,\n\t\t\t\tcacheRead: tier.cache_read ?? base.cacheRead,\n\t\t\t\tcacheWrite: tier.cache_write ?? base.cacheWrite,\n\t\t\t},\n\t\t];\n\t});\n\treturn tiers && tiers.length > 0 ? { ...base, tiers } : base;\n}\n\n/** The efforts models.dev verified for a model, or undefined when it lists none. */\nfunction modelsDevEfforts(model: ModelsDevModel | undefined): Array<string | null> | undefined {\n\tconst efforts = model?.reasoning_options?.flatMap((option) =>\n\t\toption.type === \"effort\" && Array.isArray(option.values) ? option.values : [],\n\t);\n\treturn efforts && efforts.length > 0 ? efforts : undefined;\n}\n\nfunction mergeThinkingLevelMap(model: Model.Info, map: ThinkingLevelMap): void {\n\tmodel.thinkingLevelMap = { ...model.thinkingLevelMap, ...map };\n}\n\nfunction mergeCompat(model: Model.Info, compat: Model.Compatibility): void {\n\tmodel.compat = { ...model.compat, ...compat };\n}\n\n/** Merge the level map models.dev's verified efforts give, when it lists any. */\nfunction applyEffortThinkingLevels(model: Model.Info, source: ModelsDevModel | undefined): void {\n\tconst efforts = modelsDevEfforts(source);\n\tconst map = efforts ? Model.effortThinkingLevels(efforts) : undefined;\n\tif (map) mergeThinkingLevelMap(model, map);\n}\n\n//\n// OpenAI (pi).\nconst OPENAI_LONG_CONTEXT_INPUT_THRESHOLD = 272_000;\nconst OPENAI_MAX_TOKENS = 128_000;\n\nconst OPENAI_RESPONSES_NONE_REASONING_MODELS = new Set([\n\t\"gpt-5.1\",\n\t\"gpt-5.2\",\n\t\"gpt-5.3-codex\",\n\t\"gpt-5.4\",\n\t\"gpt-5.4-mini\",\n\t\"gpt-5.4-nano\",\n\t\"gpt-5.5\",\n\t\"gpt-5.6-luna\",\n\t\"gpt-5.6-sol\",\n\t\"gpt-5.6-terra\",\n\t\"gpt-6-luna\",\n\t\"gpt-6-sol\",\n]);\n\n// Every GPT-6 model takes low through max and rejects \"minimal\"; Astra and 6.1 Sol also reject \"none\".\nconst OPENAI_GPT6_MODELS = new Set([\"gpt-6-astra\", \"gpt-6-luna\", \"gpt-6-sol\", \"gpt-6.1-sol\"]);\nconst OPENAI_GPT6_NO_NONE_MODELS = new Set([\"gpt-6-astra\", \"gpt-6.1-sol\"]);\n\n// Checked live against the Responses and Codex APIs: these families reject\n// reasoning.effort \"minimal\".\nconst OPENAI_NO_MINIMAL_REASONING = /gpt-5\\.[456]|gpt-6/;\n\n// Direct requests stay in the short-context price tier by default; the long-context price stays in\n// `cost.tiers` for a settings entry that opts into the full window.\nconst OPENAI_SHORT_CONTEXT_CAPPED_MODELS = new Set([\n\t\"gpt-5.4\",\n\t\"gpt-5.5\",\n\t\"gpt-5.6-luna\",\n\t\"gpt-5.6-sol\",\n\t\"gpt-5.6-terra\",\n\t\"gpt-6-astra\",\n\t\"gpt-6-luna\",\n\t\"gpt-6-sol\",\n\t\"gpt-6.1-sol\",\n]);\n\n// Models billed at 2x input / 1.5x output above the threshold, when models.dev has no tier for them.\nconst OPENAI_LONG_CONTEXT_PRICING_MODELS = new Set([\n\t...OPENAI_SHORT_CONTEXT_CAPPED_MODELS,\n\t\"gpt-5.4-pro\",\n\t\"gpt-5.5-pro\",\n]);\n\nfunction isOpenAiResponses(model: Model.Info): boolean {\n\treturn model.protocol === Model.KnownProviderEnum.openai || model.protocol === Model.KnownProviderEnum.openaiCodex;\n}\n\nfunction isOpenAiDirect(model: Model.Info): boolean {\n\treturn model.protocol === Model.KnownProviderEnum.openai && model.provider.id === \"openai\";\n}\n\nfunction supportsOpenAiXhigh(model: Model.Info): boolean {\n\treturn /gpt-5\\.[2-6]|gpt-6/.test(model.id);\n}\n\nfunction supportsOpenAiMax(model: Model.Info): boolean {\n\treturn isOpenAiResponses(model) && /gpt-5\\.6|gpt-6/.test(model.id);\n}\n\nfunction withOpenAiLongContextPricing(cost: Model.Info[\"cost\"]): Model.Info[\"cost\"] {\n\treturn {\n\t\t...cost,\n\t\ttiers: [\n\t\t\t{\n\t\t\t\tinputTokensAbove: OPENAI_LONG_CONTEXT_INPUT_THRESHOLD,\n\t\t\t\tinput: roundCost(cost.input * 2),\n\t\t\t\toutput: roundCost(cost.output * 1.5),\n\t\t\t\tcacheRead: roundCost(cost.cacheRead * 2),\n\t\t\t\tcacheWrite: roundCost(cost.cacheWrite * 2),\n\t\t\t},\n\t\t],\n\t};\n}\n\n/**\n * Price multipliers per service tier: models.dev's modes that set `service_tier` (fast is\n * `priority`), over OpenAI's flex 0.5x / priority 2x list defaults.\n */\nfunction serviceTierMultipliers(model: Model.Info, source: ModelsDevModel | undefined): Record<string, number> {\n\tconst multipliers: Record<string, number> = { flex: 0.5, priority: 2 };\n\tfor (const mode of Object.values(source?.experimental?.modes ?? {})) {\n\t\tconst tier = mode.provider?.body?.service_tier;\n\t\tconst input = mode.cost?.input;\n\t\tif (typeof tier !== \"string\" || input === undefined || model.cost.input <= 0) continue;\n\t\tmultipliers[tier] = roundCost(input / model.cost.input);\n\t}\n\treturn multipliers;\n}\n\nfunction applyOpenAiMetadata(model: Model.Info, source: ModelsDevModel | undefined): void {\n\tconst id = model.id;\n\tif (isOpenAiDirect(model)) {\n\t\tif (OPENAI_SHORT_CONTEXT_CAPPED_MODELS.has(id)) {\n\t\t\tmodel.contextWindow = OPENAI_LONG_CONTEXT_INPUT_THRESHOLD;\n\t\t\tmodel.maxTokens = OPENAI_MAX_TOKENS;\n\t\t}\n\t\tif (OPENAI_LONG_CONTEXT_PRICING_MODELS.has(id) && !model.cost.tiers) {\n\t\t\tmodel.cost = withOpenAiLongContextPricing(model.cost);\n\t\t}\n\t\t// models.dev reports the input sub-limit as gpt-5-pro's output.\n\t\tif (id === \"gpt-5-pro\") model.maxTokens = OPENAI_MAX_TOKENS;\n\t}\n\tmodel.cost.serviceTierMultipliers = serviceTierMultipliers(model, source);\n\n\t// models.dev's verified efforts first, then the corrections checked against the API.\n\tapplyEffortThinkingLevels(model, source);\n\tif (model.protocol === Model.KnownProviderEnum.openai && id.startsWith(\"gpt-5\")) {\n\t\tmergeThinkingLevelMap(model, { off: null });\n\t}\n\tif (OPENAI_GPT6_MODELS.has(id)) {\n\t\tmergeThinkingLevelMap(model, {\n\t\t\toff: OPENAI_GPT6_NO_NONE_MODELS.has(id) ? null : \"none\",\n\t\t\tminimal: null,\n\t\t\tlow: \"low\",\n\t\t\tmedium: \"medium\",\n\t\t\thigh: \"high\",\n\t\t\txhigh: \"xhigh\",\n\t\t\tmax: \"max\",\n\t\t});\n\t}\n\tif (isOpenAiDirect(model) && OPENAI_RESPONSES_NONE_REASONING_MODELS.has(id)) {\n\t\tmergeThinkingLevelMap(model, { off: \"none\" });\n\t}\n\tif (supportsOpenAiMax(model)) mergeThinkingLevelMap(model, { max: \"max\" });\n\tif (OPENAI_NO_MINIMAL_REASONING.test(id)) mergeThinkingLevelMap(model, { minimal: null });\n\tif (id.endsWith(\"gpt-5.5-pro\")) mergeThinkingLevelMap(model, { off: null, minimal: null, low: null });\n}\n\n//\n// Anthropic (pi).\nfunction isAnthropicMessages(model: Model.Info): boolean {\n\treturn (\n\t\tmodel.protocol === Model.KnownProviderEnum.anthropic ||\n\t\tmodel.protocol === Model.KnownProviderEnum.googleVertexAnthropic\n\t);\n}\n\n// The Messages API rejects `temperature` on these.\nconst ANTHROPIC_NO_TEMPERATURE = /opus-4[-.][78]|opus-5|(sonnet|haiku)-5[-.]5/;\n\n// Checked live against the Messages API: effort levels each adaptive family\n// accepts, the 5.5 and Fable models that reject `thinking: {type: \"disabled\"}`, and\n// Sonnet 4.5's window, which is 1M only behind a beta header.\nfunction applyAnthropicMetadata(model: Model.Info): void {\n\tconst id = model.id;\n\tif (/sonnet-4[-.]5/.test(id)) model.contextWindow = 200_000;\n\t// Not models.dev's efforts: Anthropic disables thinking by a toggle, not an effort of \"none\" (pi).\n\tif (Model.isAnthropicAdaptiveThinkingModel(id)) mergeCompat(model, { forceAdaptiveThinking: true });\n\tif (/(opus|sonnet)-4[-.]6/.test(id)) {\n\t\tmergeThinkingLevelMap(model, { max: \"max\" });\n\t}\n\tif (/opus-4[-.][78]|(opus|sonnet|fable|haiku)-5/.test(id)) {\n\t\tmergeThinkingLevelMap(model, { xhigh: \"xhigh\", max: \"max\" });\n\t}\n\tif (/(opus|sonnet|haiku)-5[-.]5/.test(id)) {\n\t\t// Haiku 5.5 accepts disabled thinking; Opus 5.5 and Sonnet 5.5 reject it.\n\t\tmergeThinkingLevelMap(model, {\n\t\t\t...(id.includes(\"haiku\") ? {} : { off: null }),\n\t\t\tminimal: null,\n\t\t\tlow: \"low\",\n\t\t\tmedium: \"medium\",\n\t\t\thigh: \"high\",\n\t\t\txhigh: \"xhigh\",\n\t\t\tmax: \"max\",\n\t\t});\n\t}\n\tif (/fable-5/.test(id)) {\n\t\tmergeThinkingLevelMap(model, { off: null });\n\t}\n\tif (ANTHROPIC_NO_TEMPERATURE.test(id)) mergeCompat(model, { supportsTemperature: false });\n}\n\n//\n// Google.\nfunction applyGoogleThinkingMetadata(model: Model.Info): void {\n\tconst id = model.id.toLowerCase();\n\tconst supportsThinkingLevel =\n\t\t/gemini-3(?:\\.\\d+)?-(?:pro|flash)|gemma-?4/.test(id) ||\n\t\tid === \"gemini-flash-latest\" ||\n\t\tid === \"gemini-flash-lite-latest\";\n\tmergeCompat(model, { supportsThinkingLevel });\n\tif (supportsThinkingLevel) return;\n\n\t// Unknown budget-based families ask the provider to size thinking dynamically.\n\tconst defaults: Array<[string, Model.ThinkingBudgets]> = [\n\t\t[\"2.5-pro\", { minimal: 128, low: 2048, medium: 8192, high: 32768 }],\n\t\t[\"2.5-flash-lite\", { minimal: 512, low: 2048, medium: 8192, high: 24576 }],\n\t\t[\"2.5-flash\", { minimal: 128, low: 2048, medium: 8192, high: 24576 }],\n\t];\n\tmodel.thinkingBudgets = defaults.find(([family]) => id.includes(family))?.[1] ?? {\n\t\tminimal: -1,\n\t\tlow: -1,\n\t\tmedium: -1,\n\t\thigh: -1,\n\t};\n}\n\nfunction applyModelMetadata(model: Model.Info, source: ModelsDevModel | undefined): void {\n\tconst isGoogle =\n\t\tmodel.protocol === Model.KnownProviderEnum.google || model.protocol === Model.KnownProviderEnum.googleVertex;\n\tif (isGoogle) {\n\t\tapplyGoogleThinkingMetadata(model);\n\t\tif (/gemini-3(?:\\.\\d+)?-pro|gemini-3\\.[78]-flash/.test(model.id.toLowerCase())) {\n\t\t\t// These models cannot disable thinking or accept minimal. Expose supported\n\t\t\t// levels to callers and let the shared clamp promote minimal to low.\n\t\t\tmergeThinkingLevelMap(model, { off: \"low\", minimal: null });\n\t\t}\n\t}\n\t// Proxied Claude ids (Copilot) keep the effort aliases the Messages API takes.\n\tif (model.id.includes(\"opus-4-6\") || model.id.includes(\"opus-4.6\")) {\n\t\tmergeThinkingLevelMap(model, { xhigh: \"max\" });\n\t}\n\tif (model.id.includes(\"opus-4-7\") || model.id.includes(\"opus-4.7\")) {\n\t\tmergeThinkingLevelMap(model, { xhigh: \"xhigh\" });\n\t}\n\tif (isOpenAiResponses(model)) applyOpenAiMetadata(model, source);\n\t// By id, for every provider serving these GPT models (pi).\n\tif (supportsOpenAiXhigh(model)) mergeThinkingLevelMap(model, { xhigh: \"xhigh\" });\n\tif (isAnthropicMessages(model)) applyAnthropicMetadata(model);\n}\n\n//\n// OpenAI Codex (ChatGPT OAuth) models.\n// Built from the OpenAI entries: Codex serves the same models at the same list prices, so only\n// which models it offers, its window and its tool support are its own. Context windows are the\n// observed server limits (400s above them), not marketing numbers.\nconst OPENAI_CODEX_PROVIDER_ID = \"openai-codex\";\nconst OPENAI_CODEX_NPM = \"@codeworksh/ai-sdk-openai-codex\";\nconst OPENAI_CODEX_BASE_URL = \"https://chatgpt.com/backend-api\";\nconst OPENAI_CODEX_CONTEXT = 272_000;\nconst OPENAI_CODEX_MODELS: ReadonlyArray<{ readonly id: string; readonly contextWindow?: number }> = [\n\t{ id: \"gpt-5.3-codex-spark\", contextWindow: 128_000 },\n\t{ id: \"gpt-5.6-luna\" },\n\t{ id: \"gpt-5.6-sol\" },\n\t{ id: \"gpt-5.6-terra\" },\n\t{ id: \"gpt-6-astra\" },\n\t{ id: \"gpt-6-luna\" },\n\t{ id: \"gpt-6-sol\" },\n\t{ id: \"gpt-6.1-sol\", contextWindow: 500_000 },\n];\nconst OPENAI_CODEX_ADDITIONAL_TOOLS_MODEL_IDS = new Set([\n\t\"gpt-5.6-luna\",\n\t\"gpt-5.6-sol\",\n\t\"gpt-5.6-terra\",\n\t\"gpt-6-astra\",\n\t\"gpt-6-luna\",\n\t\"gpt-6-sol\",\n\t\"gpt-6.1-sol\",\n]);\n// Checked live: the Codex backend accepts reasoning.effort \"none\" for these.\nconst OPENAI_CODEX_NONE_REASONING_MODEL_IDS = new Set([\"gpt-5.6-luna\", \"gpt-6-luna\", \"gpt-6-sol\"]);\n\n/** The Codex models, from the generated `openai` entries; one models.dev does not list is skipped. */\nexport function openAICodexBuiltInModels(openai: Record<string, Model.Info>): Record<string, Model.Info> {\n\tconst models: Record<string, Model.Info> = {};\n\tfor (const seed of OPENAI_CODEX_MODELS) {\n\t\tconst base = openai[seed.id];\n\t\tif (!base) continue;\n\t\tconst info: Model.Info = {\n\t\t\t...base,\n\t\t\tprovider: {\n\t\t\t\tid: OPENAI_CODEX_PROVIDER_ID,\n\t\t\t\tname: \"OpenAI Codex (ChatGPT)\",\n\t\t\t\tsource: \"custom\",\n\t\t\t\tenv: [\"OPENAI_CODEX_API_KEY\"],\n\t\t\t},\n\t\t\tbaseUrl: OPENAI_CODEX_BASE_URL,\n\t\t\treasoning: true,\n\t\t\tthinkingLevelMap: {\n\t\t\t\t...base.thinkingLevelMap,\n\t\t\t\t// Codex models reason unless verified to accept \"none\".\n\t\t\t\toff: OPENAI_CODEX_NONE_REASONING_MODEL_IDS.has(seed.id) ? \"none\" : null,\n\t\t\t\t// The backend takes \"low\" where the API would reject \"minimal\" (pi).\n\t\t\t\t...(supportsOpenAiXhigh(base) ? { minimal: \"low\" } : {}),\n\t\t\t},\n\t\t\tcontextWindow: seed.contextWindow ?? OPENAI_CODEX_CONTEXT,\n\t\t\tmaxTokens: OPENAI_MAX_TOKENS,\n\t\t\tnpm: OPENAI_CODEX_NPM,\n\t\t\tapi: {\n\t\t\t\tid: seed.id,\n\t\t\t\turl: OPENAI_CODEX_BASE_URL,\n\t\t\t\tmethod: Model.APIMethodEnum.responses,\n\t\t\t},\n\t\t\tproviderOptionsKey: OPENAI_CODEX_PROVIDER_ID,\n\t\t\tcompat: {\n\t\t\t\tsupportsOpenAIGrammarTools: true,\n\t\t\t\t...(OPENAI_CODEX_ADDITIONAL_TOOLS_MODEL_IDS.has(seed.id)\n\t\t\t\t\t? { supportsToolSearch: true, supportsAdditionalTools: true }\n\t\t\t\t\t: {}),\n\t\t\t},\n\t\t\tprotocol: Model.KnownProviderEnum.openaiCodex,\n\t\t};\n\t\tdelete info.headers;\n\t\tmodels[seed.id] = info;\n\t}\n\treturn models;\n}\n\n//\n// GitHub Copilot models.\n// Sourced from models.dev, then rewritten onto the bundled provider: one\n// `github-copilot` protocol whose `api.method` selects between Chat\n// Completions, Responses, and Anthropic Messages.\nconst GITHUB_COPILOT_PROVIDER_ID = \"github-copilot\";\nconst GITHUB_COPILOT_NPM = \"@codeworksh/ai-sdk-github-copilot\";\nconst GITHUB_COPILOT_BASE_URL = \"https://api.githubcopilot.com\";\nconst GITHUB_COPILOT_EXTENDED_CONTEXT = 1_000_000;\n\n// GitHub's \"Models with extended capabilities\" table lists these Copilot\n// models as supporting the extended 1 million token context window (pi).\nconst GITHUB_COPILOT_EXTENDED_CONTEXT_MODELS = new Set([\n\t\"claude-fable-5\",\n\t\"claude-opus-4.6\",\n\t\"claude-opus-4.7\",\n\t\"claude-opus-4.8\",\n\t\"claude-opus-5\",\n\t\"claude-sonnet-4.6\",\n\t\"claude-sonnet-5\",\n\t\"gpt-5.3-codex\",\n\t\"gpt-5.4\",\n\t\"gpt-5.5\",\n]);\n\n// Checked manually against the authenticated GitHub Copilot /models endpoint\n// (pi). Narrow corrections over models.dev metadata, not a catalog snapshot.\nconst GITHUB_COPILOT_THINKING_LEVEL_OVERRIDES: Record<string, ThinkingLevelMap> = {\n\t\"claude-opus-4.7\": { minimal: \"low\" },\n\t\"claude-opus-4.8\": { minimal: \"low\" },\n\t\"claude-opus-5\": { minimal: \"low\" },\n\t\"claude-sonnet-4.6\": { minimal: \"low\", max: \"max\" },\n};\n\n/**\n * The offline routing approximation (pi). The live `/models` response's\n * `supported_endpoints` is authoritative at runtime.\n *\n * - `claude-(haiku|sonnet|opus|fable)-[45]` → Anthropic Messages\n * - `gpt-*`, `grok-*`, `oswe*`, `mai-*` → OpenAI Responses\n * - everything else → OpenAI Chat Completions\n */\nexport function githubCopilotApiMethod(modelId: string): Model.APIMethodEnum {\n\tif (/^claude-(haiku|sonnet|opus|fable)-[45]([.-]|$)/.test(modelId)) {\n\t\treturn Model.APIMethodEnum.messages;\n\t}\n\tconst gpt = /^gpt-(\\d+)/.exec(modelId);\n\tif (\n\t\t(gpt !== null && Number(gpt[1]) >= 5) ||\n\t\tmodelId.startsWith(\"grok-\") ||\n\t\tmodelId.startsWith(\"oswe\") ||\n\t\tmodelId.startsWith(\"mai-\")\n\t) {\n\t\treturn Model.APIMethodEnum.responses;\n\t}\n\treturn Model.APIMethodEnum.chat;\n}\n\n/**\n * Derive the level map from models.dev `reasoning_options`: a level maps to\n * itself only when the endpoint actually advertises it. `minimal` degrades to\n * `low` — the lowest effort every reasoning model accepts.\n */\nfunction githubCopilotThinkingLevels(model: ModelsDevModel, method: Model.APIMethodEnum): ThinkingLevelMap | undefined {\n\tconst listed = modelsDevEfforts(model);\n\tconst efforts = listed ? new Set(listed) : undefined;\n\tconst map: ThinkingLevelMap = {};\n\t// Copilot rejects `reasoningEffort: \"none\"` (pi), and the chat route has no\n\t// reasoning control, so only Messages models can disable thinking.\n\tif (method !== Model.APIMethodEnum.messages) map.off = null;\n\tif (!efforts) return Object.keys(map).length > 0 ? map : undefined;\n\n\tif (efforts.has(\"minimal\")) map.minimal = \"minimal\";\n\telse if (efforts.has(\"low\")) map.minimal = \"low\";\n\tfor (const level of [\"low\", \"medium\", \"high\", \"xhigh\", \"max\"] as const) {\n\t\tmap[level] = efforts.has(level) ? level : null;\n\t}\n\treturn map;\n}\n\nexport function githubCopilotBuiltInModels(provider: ModelsDevProvider | undefined): Record<string, Model.Info> {\n\tconst models: Record<string, Model.Info> = {};\n\tif (!provider) return models;\n\tfor (const [id, source] of Object.entries(provider.models)) {\n\t\tif (source.tool_call !== true) continue;\n\t\tif (source.status === \"deprecated\") continue;\n\t\t// The chat-latest alias races the Responses route for gpt-5 models.\n\t\tif (id === \"gpt-5-chat-latest\") continue;\n\n\t\tconst base = applyModification(GITHUB_COPILOT_PROVIDER_ID, provider, source);\n\t\tif (!base) continue;\n\n\t\tconst method = githubCopilotApiMethod(id);\n\t\tconst info: Model.Info = {\n\t\t\t...base,\n\t\t\tprovider: {\n\t\t\t\tid: GITHUB_COPILOT_PROVIDER_ID,\n\t\t\t\tname: \"GitHub Copilot\",\n\t\t\t\tsource: \"custom\",\n\t\t\t\tenv: [\"COPILOT_GITHUB_TOKEN\"],\n\t\t\t},\n\t\t\tbaseUrl: GITHUB_COPILOT_BASE_URL,\n\t\t\theaders: { ...GITHUB_COPILOT_STATIC_HEADERS },\n\t\t\tnpm: GITHUB_COPILOT_NPM,\n\t\t\tapi: { id, url: GITHUB_COPILOT_BASE_URL, method },\n\t\t\tproviderOptionsKey: GITHUB_COPILOT_PROVIDER_ID,\n\t\t\tprotocol: Model.KnownProviderEnum.githubCopilot,\n\t\t\t// Copilot's Responses route requires store=false + encrypted reasoning\n\t\t\t// content for thinking to round-trip.\n\t\t\t...(method === Model.APIMethodEnum.responses\n\t\t\t\t? {\n\t\t\t\t\t\tproviderOptions: {\n\t\t\t\t\t\t\t...base.providerOptions,\n\t\t\t\t\t\t\t[GITHUB_COPILOT_PROVIDER_ID]: {\n\t\t\t\t\t\t\t\tstore: false,\n\t\t\t\t\t\t\t\tinclude: [\"reasoning.encrypted_content\"],\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t}\n\t\t\t\t: {}),\n\t\t};\n\n\t\tif (GITHUB_COPILOT_EXTENDED_CONTEXT_MODELS.has(id)) info.contextWindow = GITHUB_COPILOT_EXTENDED_CONTEXT;\n\t\tif (method === Model.APIMethodEnum.messages && Model.isAnthropicAdaptiveThinkingModel(id)) {\n\t\t\tmergeCompat(info, { forceAdaptiveThinking: true });\n\t\t}\n\t\t// Copilot's Responses endpoint passes OpenAI custom grammar tools through\n\t\t// for GPT-5+ (verified by pi).\n\t\tconst gpt = /^gpt-(\\d+)/.exec(id);\n\t\tif (method === Model.APIMethodEnum.responses && gpt !== null && Number(gpt[1]) >= 5) {\n\t\t\tmergeCompat(info, { supportsOpenAIGrammarTools: true });\n\t\t}\n\t\tif (id.startsWith(\"gpt-5\")) mergeThinkingLevelMap(info, { off: null, minimal: \"low\" });\n\t\tif (id.includes(\"fable-5\")) mergeThinkingLevelMap(info, { off: null, xhigh: \"xhigh\", max: \"max\" });\n\n\t\tconst levels = githubCopilotThinkingLevels(source, method);\n\t\tif (levels) mergeThinkingLevelMap(info, levels);\n\t\tconst override = GITHUB_COPILOT_THINKING_LEVEL_OVERRIDES[id];\n\t\tif (override) mergeThinkingLevelMap(info, override);\n\n\t\tmodels[id] = info;\n\t}\n\treturn models;\n}\n\n/** OpenRouter's listing as catalog entries, or undefined when it is missing or unreadable. */\nfunction openRouterModels(listing: unknown): Record<string, Model.Info> | undefined {\n\tif (listing === undefined) return undefined;\n\ttry {\n\t\tconst models = OpenRouter.catalog(listing);\n\t\treturn Object.keys(models).length > 0 ? models : undefined;\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\n/** Object keys in order at every level, so identical content serializes to identical bytes. */\nfunction sortKeys(value: unknown): unknown {\n\tif (Array.isArray(value)) return value.map(sortKeys);\n\tif (typeof value !== \"object\" || value === null) return value;\n\treturn Object.fromEntries(\n\t\tObject.entries(value)\n\t\t\t.sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0))\n\t\t\t.map(([key, entry]) => [key, sortKeys(entry)]),\n\t);\n}\n\n/**\n * The catalog from fetched sources, keys sorted so identical content serializes to identical\n * bytes. OpenRouter's own listing replaces models.dev's copy of it.\n */\nexport function buildCatalog(sources: Sources): BuiltInModels {\n\tconst modelsDev = loadBuiltInFromModelsDev(sources.modelsDev);\n\tconst openrouter = openRouterModels(sources.openRouter);\n\tconst copilotProvider = sources.modelsDev[GITHUB_COPILOT_PROVIDER_ID];\n\treturn sortKeys({\n\t\t...modelsDev,\n\t\t...(openrouter ? { [OpenRouter.PROVIDER_ID]: openrouter } : {}),\n\t\t[OPENAI_CODEX_PROVIDER_ID]: openAICodexBuiltInModels(modelsDev.openai ?? {}),\n\t\t...(copilotProvider ? { [GITHUB_COPILOT_PROVIDER_ID]: githubCopilotBuiltInModels(copilotProvider) } : {}),\n\t}) as BuiltInModels;\n}\n\nexport interface GenerateOptions {\n\t/** Output file; defaults to `CODEWORK_MODELS_FILE` or `./models.gen.json`. */\n\treadonly path?: string | undefined;\n\t/** Keep only {@link BASELINE_PROVIDERS}, for the catalog bundled with aikit. */\n\treadonly baseline?: boolean | undefined;\n}\n\nexport async function generateModels(args: GenerateOptions = {}): Promise<string> {\n\tconst path = resolve(args.path ?? ModelCatalog.path());\n\tconst [modelsDev, openRouter] = await Promise.all([pullModelsDevData(), pullOpenRouterData()]);\n\tconst catalog = buildCatalog({ modelsDev, openRouter });\n\tawait Filesystem.writeJsonAtomic(path, args.baseline ? pick(catalog, BASELINE_PROVIDERS) : catalog);\n\treturn path;\n}\n\n//\n// CLI entry\nexport const ModelgenCommand: CommandModule<object, { path?: string | undefined; baseline?: boolean | undefined }> = {\n\tcommand: \"modelgen [path]\",\n\tdescribe: \"generate models.gen.json\",\n\tbuilder: (yargs) =>\n\t\tyargs\n\t\t\t.positional(\"path\", {\n\t\t\t\ttype: \"string\",\n\t\t\t\tdescribe: \"output path (defaults to CODEWORK_MODELS_FILE or ./models.gen.json)\",\n\t\t\t})\n\t\t\t.option(\"baseline\", {\n\t\t\t\ttype: \"boolean\",\n\t\t\t\tdescribe: `keep only the bundled baseline providers (${BASELINE_PROVIDERS.join(\", \")})`,\n\t\t\t}),\n\thandler: async (args) => {\n\t\tconst path = await generateModels(args);\n\t\tconsole.log(`Generated model catalog at ${path}`);\n\t},\n};\n\nexport function applyModification(\n\tproviderId: string,\n\tprovider: ModelsDevProvider,\n\tmodel: ModelsDevModel,\n): Model.Info | undefined {\n\tconst npm = resolveModelNpm(provider, model);\n\tif (!isAISDKPackage(npm)) return;\n\n\tconst protocol = protocolForPackage(npm);\n\tconst baseUrl = resolveModelBaseUrl(provider, model);\n\tconst providerInfo: Model.ProviderInfo = {\n\t\tid: providerId,\n\t\tname: provider.name,\n\t\tsource: \"api\",\n\t\tenv: provider.env,\n\t};\n\tif (provider.key) providerInfo.key = provider.key;\n\tconst api: Model.APIMetadata = {\n\t\tid: model.id,\n\t\tmethod: resolveModelAPIMethod(npm),\n\t};\n\tif (baseUrl) api.url = baseUrl;\n\n\tconst info: Model.Info = {\n\t\tid: model.id,\n\t\tname: model.name,\n\t\tprovider: providerInfo,\n\t\tbaseUrl,\n\t\treasoning: Boolean(model.reasoning),\n\t\tinput: Model.normalizeInput(model.modalities.input),\n\t\tcost: modelsDevCost(model.cost),\n\t\tcontextWindow: model.limit?.context ?? 4096,\n\t\tmaxTokens: model.limit?.output ?? 4096,\n\t\theaders: {\n\t\t\t...provider.headers,\n\t\t\t...model.provider?.headers,\n\t\t\t...model.headers,\n\t\t},\n\t\tnpm,\n\t\tapi,\n\t\tproviderOptionsKey: resolveProviderOptionsKey(protocol),\n\t\tprotocol,\n\t};\n\tif (Object.keys(info.headers ?? {}).length === 0) delete info.headers;\n\tapplyModelMetadata(info, model);\n\treturn info;\n}\n"],"mappings":"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"}
|
package/modelgen.d.mts
CHANGED
|
@@ -1,8 +1,25 @@
|
|
|
1
|
-
import "./model-
|
|
1
|
+
import "./model-D3wc9-u4.mjs";
|
|
2
2
|
import "yargs";
|
|
3
3
|
//#region src/cli/modelgen.d.ts
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
interface GenerateOptions {
|
|
5
|
+
/** Output file; defaults to `CODEWORK_MODELS_FILE` or `./models.gen.json`. */
|
|
6
|
+
readonly path?: string | undefined;
|
|
7
|
+
/** Keep only {@link BASELINE_PROVIDERS}, for the catalog bundled with aikit. */
|
|
8
|
+
readonly baseline?: boolean | undefined;
|
|
9
|
+
}
|
|
10
|
+
export declare function generateModels(args?: GenerateOptions): Promise<string>;
|
|
11
|
+
//#endregion
|
|
12
|
+
//#region src/model/remote.d.ts
|
|
13
|
+
/** The published catalog; `CODEWORK_CATALOG_URL` points elsewhere, a `file:` URL at a local copy. */
|
|
14
|
+
export declare function catalogURL(): string;
|
|
15
|
+
/**
|
|
16
|
+
* Download the published catalog to `path`, narrowing OpenRouter to the models `openRouterKey` may
|
|
17
|
+
* use. A failed download throws and leaves `path` as it was.
|
|
18
|
+
*/
|
|
19
|
+
export declare function downloadCatalog(options: {
|
|
20
|
+
readonly path: string;
|
|
21
|
+
readonly url?: string | undefined;
|
|
22
|
+
readonly openRouterKey?: string | undefined;
|
|
6
23
|
}): Promise<string>;
|
|
7
24
|
//#endregion
|
|
8
25
|
//# sourceMappingURL=modelgen.d.mts.map
|
package/modelgen.mjs
CHANGED
|
@@ -1,2 +1,61 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import { T as writeJsonAtomic, i as KnownProviderEnum, t as APIMethodEnum, w as writeAtomic } from "./model-Cjp-Dr8V.mjs";
|
|
2
|
+
import { i as personalize, n as generateModels, r as PROVIDER_ID } from "./modelgen-BdiCqi-R.mjs";
|
|
3
|
+
import { dirname, join, resolve } from "node:path";
|
|
4
|
+
import { createHash } from "node:crypto";
|
|
5
|
+
import { readFile } from "node:fs/promises";
|
|
6
|
+
import { fileURLToPath } from "node:url";
|
|
7
|
+
//#region src/model/remote.ts
|
|
8
|
+
const DEFAULT_URL = "https://catalog.codework.sh/v1/models.json";
|
|
9
|
+
/** The downloaded bytes, kept beside the catalog for the next conditional request. */
|
|
10
|
+
const DOWNLOAD_FILENAME = "models.download.json";
|
|
11
|
+
/** The published catalog; `CODEWORK_CATALOG_URL` points elsewhere, a `file:` URL at a local copy. */
|
|
12
|
+
function catalogURL() {
|
|
13
|
+
return process.env.CODEWORK_CATALOG_URL || DEFAULT_URL;
|
|
14
|
+
}
|
|
15
|
+
/** The catalog's bytes: `previous` again when the server says they have not changed. */
|
|
16
|
+
async function fetchCatalog(url, previous) {
|
|
17
|
+
if (url.startsWith("file:")) return readFile(fileURLToPath(url));
|
|
18
|
+
const etag = previous ? `"${createHash("md5").update(previous).digest("hex")}"` : void 0;
|
|
19
|
+
const response = await fetch(url, {
|
|
20
|
+
headers: {
|
|
21
|
+
accept: "application/json",
|
|
22
|
+
...etag ? { "if-none-match": etag } : {}
|
|
23
|
+
},
|
|
24
|
+
signal: AbortSignal.timeout(3e4)
|
|
25
|
+
});
|
|
26
|
+
if (response.status === 304 && previous) return previous;
|
|
27
|
+
if (!response.ok) throw new Error(`model catalog responded ${response.status} ${response.statusText}`);
|
|
28
|
+
return Buffer.from(await response.arrayBuffer());
|
|
29
|
+
}
|
|
30
|
+
const knownProtocols = new Set(Object.values(KnownProviderEnum));
|
|
31
|
+
const knownMethods = new Set(Object.values(APIMethodEnum));
|
|
32
|
+
/**
|
|
33
|
+
* Whether this aikit can call the model. A catalog published by a newer aikit can name a protocol
|
|
34
|
+
* or API method this one does not know; such a model is left out rather than failing at call time.
|
|
35
|
+
*/
|
|
36
|
+
function callable(model) {
|
|
37
|
+
return knownProtocols.has(model.protocol) && (model.api?.method === void 0 || knownMethods.has(model.api.method));
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Download the published catalog to `path`, narrowing OpenRouter to the models `openRouterKey` may
|
|
41
|
+
* use. A failed download throws and leaves `path` as it was.
|
|
42
|
+
*/
|
|
43
|
+
async function downloadCatalog(options) {
|
|
44
|
+
const path = resolve(options.path);
|
|
45
|
+
const downloaded = join(dirname(path), DOWNLOAD_FILENAME);
|
|
46
|
+
const previous = await readFile(downloaded).catch(() => void 0);
|
|
47
|
+
const bytes = await fetchCatalog(options.url ?? catalogURL(), previous);
|
|
48
|
+
const parsed = JSON.parse(bytes.toString("utf8"));
|
|
49
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) throw new Error("model catalog is not a JSON object");
|
|
50
|
+
if (bytes !== previous) await writeAtomic(downloaded, bytes);
|
|
51
|
+
const catalog = {};
|
|
52
|
+
for (const [provider, models] of Object.entries(parsed)) catalog[provider] = Object.fromEntries(Object.entries(models ?? {}).filter(([, model]) => callable(model)));
|
|
53
|
+
const openrouter = catalog[PROVIDER_ID];
|
|
54
|
+
if (options.openRouterKey && openrouter) catalog[PROVIDER_ID] = await personalize(openrouter, options.openRouterKey).catch(() => openrouter);
|
|
55
|
+
await writeJsonAtomic(path, catalog);
|
|
56
|
+
return path;
|
|
57
|
+
}
|
|
58
|
+
//#endregion
|
|
59
|
+
export { catalogURL, downloadCatalog, generateModels };
|
|
60
|
+
|
|
61
|
+
//# sourceMappingURL=modelgen.mjs.map
|
package/modelgen.mjs.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"modelgen.mjs","names":["Model.KnownProviderEnum","Model.APIMethodEnum","Filesystem.writeAtomic","OpenRouter.PROVIDER_ID","OpenRouter.personalize","Filesystem.writeJsonAtomic"],"sources":["../../src/model/remote.ts"],"sourcesContent":["/*\n * @file The published model catalog, downloaded.\n *\n * CI publishes what `aikit modelgen` builds to https://catalog.codework.sh/v1/models.json\n * (`.github/workflows/catalog.yml`). A client keeps the bytes it downloaded beside its catalog and\n * asks with their MD5, R2's ETag for them, so an unchanged catalog costs a 304. OpenRouter is\n * narrowed to the caller's key after download, which is why those bytes are kept apart from the\n * catalog the client reads.\n */\nimport { createHash } from \"node:crypto\";\nimport { readFile } from \"node:fs/promises\";\nimport { dirname, join, resolve } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport * as Filesystem from \"../utils/filesystem.ts\";\nimport * as Model from \"./model.ts\";\nimport { OpenRouter } from \"./openrouter.ts\";\n\nconst DEFAULT_URL = \"https://catalog.codework.sh/v1/models.json\";\n/** The downloaded bytes, kept beside the catalog for the next conditional request. */\nconst DOWNLOAD_FILENAME = \"models.download.json\";\n\n/** The published catalog; `CODEWORK_CATALOG_URL` points elsewhere, a `file:` URL at a local copy. */\nexport function catalogURL(): string {\n\treturn process.env.CODEWORK_CATALOG_URL || DEFAULT_URL;\n}\n\n/** The catalog's bytes: `previous` again when the server says they have not changed. */\nasync function fetchCatalog(url: string, previous: Buffer | undefined): Promise<Buffer> {\n\tif (url.startsWith(\"file:\")) return readFile(fileURLToPath(url));\n\tconst etag = previous ? `\"${createHash(\"md5\").update(previous).digest(\"hex\")}\"` : undefined;\n\tconst response = await fetch(url, {\n\t\theaders: { accept: \"application/json\", ...(etag ? { \"if-none-match\": etag } : {}) },\n\t\tsignal: AbortSignal.timeout(30_000),\n\t});\n\tif (response.status === 304 && previous) return previous;\n\tif (!response.ok) throw new Error(`model catalog responded ${response.status} ${response.statusText}`);\n\treturn Buffer.from(await response.arrayBuffer());\n}\n\nconst knownProtocols: ReadonlySet<string> = new Set(Object.values(Model.KnownProviderEnum));\nconst knownMethods: ReadonlySet<string> = new Set(Object.values(Model.APIMethodEnum));\n\n/**\n * Whether this aikit can call the model. A catalog published by a newer aikit can name a protocol\n * or API method this one does not know; such a model is left out rather than failing at call time.\n */\nfunction callable(model: Model.Info): boolean {\n\treturn knownProtocols.has(model.protocol) && (model.api?.method === undefined || knownMethods.has(model.api.method));\n}\n\n/**\n * Download the published catalog to `path`, narrowing OpenRouter to the models `openRouterKey` may\n * use. A failed download throws and leaves `path` as it was.\n */\nexport async function downloadCatalog(options: {\n\treadonly path: string;\n\treadonly url?: string | undefined;\n\treadonly openRouterKey?: string | undefined;\n}): Promise<string> {\n\tconst path = resolve(options.path);\n\tconst downloaded = join(dirname(path), DOWNLOAD_FILENAME);\n\tconst previous = await readFile(downloaded).catch(() => undefined);\n\tconst bytes = await fetchCatalog(options.url ?? catalogURL(), previous);\n\n\tconst parsed: unknown = JSON.parse(bytes.toString(\"utf8\"));\n\tif (typeof parsed !== \"object\" || parsed === null || Array.isArray(parsed)) {\n\t\tthrow new Error(\"model catalog is not a JSON object\");\n\t}\n\tif (bytes !== previous) await Filesystem.writeAtomic(downloaded, bytes);\n\n\tconst catalog: Model.BuiltInModels = {};\n\tfor (const [provider, models] of Object.entries(parsed as Model.BuiltInModels)) {\n\t\tcatalog[provider] = Object.fromEntries(Object.entries(models ?? {}).filter(([, model]) => callable(model)));\n\t}\n\tconst openrouter = catalog[OpenRouter.PROVIDER_ID];\n\tif (options.openRouterKey && openrouter) {\n\t\t// The shared listing still beats none when OpenRouter cannot say what the key may use.\n\t\tcatalog[OpenRouter.PROVIDER_ID] = await OpenRouter.personalize(openrouter, options.openRouterKey).catch(\n\t\t\t() => openrouter,\n\t\t);\n\t}\n\tawait Filesystem.writeJsonAtomic(path, catalog);\n\treturn path;\n}\n"],"mappings":";;;;;;;AAiBA,MAAM,cAAc;;AAEpB,MAAM,oBAAoB;;AAG1B,SAAgB,aAAqB;CACpC,OAAO,QAAQ,IAAI,wBAAwB;AAC5C;;AAGA,eAAe,aAAa,KAAa,UAA+C;CACvF,IAAI,IAAI,WAAW,OAAO,GAAG,OAAO,SAAS,cAAc,GAAG,CAAC;CAC/D,MAAM,OAAO,WAAW,IAAI,WAAW,KAAK,CAAC,CAAC,OAAO,QAAQ,CAAC,CAAC,OAAO,KAAK,EAAE,KAAK,KAAA;CAClF,MAAM,WAAW,MAAM,MAAM,KAAK;EACjC,SAAS;GAAE,QAAQ;GAAoB,GAAI,OAAO,EAAE,iBAAiB,KAAK,IAAI,CAAC;EAAG;EAClF,QAAQ,YAAY,QAAQ,GAAM;CACnC,CAAC;CACD,IAAI,SAAS,WAAW,OAAO,UAAU,OAAO;CAChD,IAAI,CAAC,SAAS,IAAI,MAAM,IAAI,MAAM,2BAA2B,SAAS,OAAO,GAAG,SAAS,YAAY;CACrG,OAAO,OAAO,KAAK,MAAM,SAAS,YAAY,CAAC;AAChD;AAEA,MAAM,iBAAsC,IAAI,IAAI,OAAO,OAAOA,iBAAuB,CAAC;AAC1F,MAAM,eAAoC,IAAI,IAAI,OAAO,OAAOC,aAAmB,CAAC;;;;;AAMpF,SAAS,SAAS,OAA4B;CAC7C,OAAO,eAAe,IAAI,MAAM,QAAQ,MAAM,MAAM,KAAK,WAAW,KAAA,KAAa,aAAa,IAAI,MAAM,IAAI,MAAM;AACnH;;;;;AAMA,eAAsB,gBAAgB,SAIlB;CACnB,MAAM,OAAO,QAAQ,QAAQ,IAAI;CACjC,MAAM,aAAa,KAAK,QAAQ,IAAI,GAAG,iBAAiB;CACxD,MAAM,WAAW,MAAM,SAAS,UAAU,CAAC,CAAC,YAAY,KAAA,CAAS;CACjE,MAAM,QAAQ,MAAM,aAAa,QAAQ,OAAO,WAAW,GAAG,QAAQ;CAEtE,MAAM,SAAkB,KAAK,MAAM,MAAM,SAAS,MAAM,CAAC;CACzD,IAAI,OAAO,WAAW,YAAY,WAAW,QAAQ,MAAM,QAAQ,MAAM,GACxE,MAAM,IAAI,MAAM,oCAAoC;CAErD,IAAI,UAAU,UAAU,MAAMC,YAAuB,YAAY,KAAK;CAEtE,MAAM,UAA+B,CAAC;CACtC,KAAK,MAAM,CAAC,UAAU,WAAW,OAAO,QAAQ,MAA6B,GAC5E,QAAQ,YAAY,OAAO,YAAY,OAAO,QAAQ,UAAU,CAAC,CAAC,CAAC,CAAC,QAAQ,GAAG,WAAW,SAAS,KAAK,CAAC,CAAC;CAE3G,MAAM,aAAa,QAAQC;CAC3B,IAAI,QAAQ,iBAAiB,YAE5B,QAAQA,eAA0B,MAAMC,YAAuB,YAAY,QAAQ,aAAa,CAAC,CAAC,YAC3F,UACP;CAED,MAAMC,gBAA2B,MAAM,OAAO;CAC9C,OAAO;AACR"}
|
package/oauth/github/copilot.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as createGitHubCopilotDeviceFlow, c as fetchGitHubCopilotUser, d as gitHubCopilotBaseUrl, f as gitHubCopilotEntitlementError, h as pollGitHubCopilotDeviceToken, i as JsonGitHubCopilotAuthStorage, l as getGitHubCopilotApiKey, m as normalizeGitHubDomain, n as GITHUB_COPILOT_PROVIDER_ID, o as enableGitHubCopilotModels, p as gitHubCopilotHeaders, r as GitHubCopilotOAuthClient, s as fetchGitHubCopilotModels, t as GITHUB_COPILOT_API_KEY_ENV, u as gitHubApiDomain } from "../../copilot-
|
|
1
|
+
import { a as createGitHubCopilotDeviceFlow, c as fetchGitHubCopilotUser, d as gitHubCopilotBaseUrl, f as gitHubCopilotEntitlementError, h as pollGitHubCopilotDeviceToken, i as JsonGitHubCopilotAuthStorage, l as getGitHubCopilotApiKey, m as normalizeGitHubDomain, n as GITHUB_COPILOT_PROVIDER_ID, o as enableGitHubCopilotModels, p as gitHubCopilotHeaders, r as GitHubCopilotOAuthClient, s as fetchGitHubCopilotModels, t as GITHUB_COPILOT_API_KEY_ENV, u as gitHubApiDomain } from "../../copilot-DvUXC6Kx.mjs";
|
|
2
2
|
export { GITHUB_COPILOT_API_KEY_ENV, GITHUB_COPILOT_PROVIDER_ID, GitHubCopilotOAuthClient, JsonGitHubCopilotAuthStorage, createGitHubCopilotDeviceFlow, enableGitHubCopilotModels, fetchGitHubCopilotModels, fetchGitHubCopilotUser, getGitHubCopilotApiKey, gitHubApiDomain, gitHubCopilotBaseUrl, gitHubCopilotEntitlementError, gitHubCopilotHeaders, normalizeGitHubDomain, pollGitHubCopilotDeviceToken };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.mjs";
|
|
2
2
|
import { a as FailureSchema } from "./schema-rXSoWhic.mjs";
|
|
3
|
-
import { a as KnownProviderEnumSchema, c as ThinkingLevel, o as ProviderInfo } from "./model-
|
|
3
|
+
import { a as KnownProviderEnumSchema, c as ThinkingLevel, o as ProviderInfo } from "./model-Cjp-Dr8V.mjs";
|
|
4
4
|
import { s as getOpenAICodexAccountId } from "./codex-CLDBTrFm.mjs";
|
|
5
5
|
import Type$1 from "typebox";
|
|
6
6
|
import { uuidv7 } from "uuidv7";
|
|
@@ -1629,4 +1629,4 @@ const openaiCodex = createOpenAICodex();
|
|
|
1629
1629
|
//#endregion
|
|
1630
1630
|
export { ToolCallSchema as C, transformMessages as E, AssistantMessageSchema as S, message_exports as T, appendOpenAICodexGrammarInputJsonDelta as _, OpenAICodexLanguageModel as a, resolveOpenAICodexDeferredToolsMode as b, convertOpenAICodexUsage as c, convertToOpenAICodexPrompt as d, joinToolCallId as f, shortHash as g, openAICodexErrorMessage as h, OPENAI_CODEX_DEFAULT_BASE_URL as i, mapOpenAICodexFinishReason as l, createOpenAICodexAPICallError as m, createOpenAICodex as n, clampOpenAICodexPromptCacheKey as o, splitToolCallId as p, openaiCodex as r, resolveOpenAICodexUrl as s, OPENAI_CODEX_API_KEY_ENV as t, collectOpenAICodexDeferredToolNames as u, openAICodexTools as v, createAssistantMessage as w, resolveOpenAICodexToolConstraint as x, prepareOpenAICodexTools as y };
|
|
1631
1631
|
|
|
1632
|
-
//# sourceMappingURL=openai-codex-
|
|
1632
|
+
//# sourceMappingURL=openai-codex-C1Yb02kM.mjs.map
|