Replace the codex-substring heuristic with the empirically verified
allow/disallow lists plus the >5.4 version rule; the ChatGPT backend
rejects models like gpt-5.3-codex that the substring rule admitted.
The catalog treated any native model api with empty settings and no url as
a placeholder inheriting the provider api, which stomped plugin-assigned
native packages (ChatGPT codex retargeting) back to aisdk. A native api
carrying a package is explicitly targeted and now survives projection.
Provider packages are now the only module-level model constructors; the
protocol-level model wrappers added earlier on this branch had one call
site each and duplicated the Settings vocabulary, so packages call
route.with(...).model({id}) directly. Deletes provider facades with no
importers outside llm tests; configure stays for V1 native-request.
Provider packages in @opencode-ai/llm/providers/* now implement a uniform
ProviderPackage contract: model(modelID, settings) => Model. SessionRunnerModel
becomes provider-agnostic: it resolves a package specifier, folds catalog
settings, credentials, and transport overlays into one Settings object, and
delegates request construction to the package.
- llm: add ProviderPackage (Settings, Definition, define), flat model(id,
config) constructors on the openai-responses, anthropic-messages, and
openai-compatible-chat protocols, contract-shaped model exports on the
openai, anthropic, and openai-compatible providers, and a new
providers/openai/codex entry point that targets the ChatGPT codex backend
and sets the chatgpt-account-id header from settings.accountID.
- schema: Provider.Native gains optional package.
- core: SessionRunnerModel loads packages through a static built-in map
(dynamic import for foreign specifiers) and applies one settings fold;
the ChatGPT conditional is deleted from the runner. The OpenAI plugin's
catalog transform now assigns the codex package to eligible models when a
ChatGPT connection is active, alongside the existing eligibility and cost
rewrites.
- llm schema: hoist ToolResultValue union out of its Object.assign self
reference; the previous shape only typechecked under lucky check ordering
and broke under core's typecheck with the new import graph.
Closes#34765