Skip to content

🤖 feat: generalize Coder AI Gateway integration to arbitrary provider instances - #3844

Open
ThomasK33 wants to merge 48 commits into
mainfrom
ai-gateway-d226
Open

🤖 feat: generalize Coder AI Gateway integration to arbitrary provider instances#3844
ThomasK33 wants to merge 48 commits into
mainfrom
ai-gateway-d226

Conversation

@ThomasK33

Copy link
Copy Markdown
Member

Summary

Generalizes the Coder AI Gateway integration from two hardcoded provider names (anthropic, openai) to arbitrary server-side provider instances: dynamic provider discovery, type-based wire-protocol routing for coder:<provider>/<model> strings, and a "Refresh models" action that re-discovers without a re-login.

Background

Coder AI Gateway deployments configure N provider instances with arbitrary names and types (openai, anthropic, azure, google, openai-compat, openrouter, vercel, bedrock, copilot), each mounted at /api/v2/aibridge/<name>/. Mux previously:

  • probed only the two default routes at discovery time, so every other configured provider was invisible;
  • rejected any coder:<x>/<model> string where x was not exactly anthropic or openai, so other providers were unroutable even manually;
  • ran discovery exactly once, at OAuth login — new server-side models/providers required a full re-login.

This made the integration borderline unusable on real multi-provider deployments.

Implementation

  • Discovery (coderOauthService.ts): first tries GET /api/v2/ai/providers (authoritative {name, type, enabled} list). That endpoint requires site-wide AIProvider read, so on 403/404 it falls back to probing the default type-named routes plus any previously known instances (discoveredProviders ∪ user-managed additionalProviders). Catalog writes are per-provider conclusive: ok replaces that provider's entries, 404 clears them, and transient errors carry the previous entries forward — one provider whose upstream rejects /v1/models (e.g. AWS Bedrock behind the passthrough) can no longer poison the whole catalog write. Existing invariants are preserved: policy-unfiltered durable catalog, manual entries and removedModels honored, credential-pinned locked writes so stale discovery can't commit over a disconnect/re-login.
  • Routing (providerModelFactory.ts): coder:<name>/<model> splits on the first slash; the name resolves through additionalProvidersdiscoveredProviders → the name === type default. The resolved type picks the wire: anthropic/bedrock → Anthropic messages, openai → OpenAI Responses, other OpenAI-wire types → chat completions (compat upstreams don't reliably support /v1/responses). copilot is rejected with a clear error (needs client-minted request-time tokens).
  • Anthropic version header: /v1/models is a gateway passthrough and Anthropic 400s without anthropic-version; discovery now sends it for Anthropic-wire instances (found live on dev.coder.com — without it, every Anthropic model was hidden).
  • Staleness: new coderOauth.refreshModels IPC + Settings "Refresh models" button + command palette action.
  • Schema: discoveredProviders (discovery-written metadata, never a routing gate) and additionalProviders (user escape hatch for custom-named instances on deployments where members cannot list providers) on the coder provider config.

Known follow-ups (out of scope): canonical→gateway auto-routing (anthropic:x via Coder) still assumes default-named instances; additionalProviders has no Settings UI yet (documented hand-edit).

Validation

  • Unit: new tests for authoritative-listing discovery with custom names, member-403 probe fallback, per-provider transient carry-forward, additionalProviders probing/routing, wire-protocol mapping (incl. bedrock→anthropic and copilot rejection), and the anthropic-version header split.
  • Mock deployment e2e (dev-server sandbox + agent-browser): full OAuth login against a mock coderd with custom-named instances (prod-anthropic, llm-proxy/openai-compat), catalog + provider metadata persisted, chats routed through /aibridge/llm-proxy/v1/chat/completions and /aibridge/prod-anthropic/v1/messages, and the Refresh button picking up server-side catalog growth without re-login.
  • Live e2e against dev.coder.com (session token injected as stored credential): providers listing 403 → probe fallback discovered anthropic/openai/openai-compat (278 models); real completions verified on all three wires (coder:anthropic/claude-sonnet-4-5-20250929, coder:openai/gpt-5.2, coder:openai-compat/gpt-4.1-mini) with usage/cost tracking.

Risks

  • Coder-provider routing/discovery is rewritten; regressions would affect existing default-named deployments (the exact previously-working setups). Mitigations: name === type fallback keeps coder:anthropic/.../coder:openai/... routable with no metadata at all, discovery invariants are covered by the pre-existing test suite (all green), and both wires were re-verified live.
  • Probe fallback issues up to 8 catalog requests per refresh instead of 2 (login/refresh only, bounded + concurrent; absent routes 404 fast).
  • discoveredProviders is additive config; older builds ignore it (upgrade↔downgrade safe).

Generated with mux • Model: anthropic:claude-fable-5 • Thinking: xhigh • Cost: $92.30

…nstances

The Coder integration previously hardcoded two provider names
(anthropic, openai) for both model discovery and request routing, while
AI Gateway deployments configure N provider instances with arbitrary
names and types (openai, anthropic, azure, google, openai-compat,
openrouter, vercel, bedrock, copilot), each mounted at
/api/v2/aibridge/<name>/. Any other provider was undiscoverable and
unroutable, and discovery only ever ran once at login.

- Discovery now lists the deployment's configured providers via
  GET /api/v2/ai/providers (authoritative: name, type, enabled) and, when
  that admin-only endpoint is 403/404, falls back to probing the default
  type-named routes plus any previously known instances.
- Catalog writes are per-provider conclusive: ok replaces, 404 clears,
  transient errors carry the provider's previous entries forward - one
  provider whose upstream rejects /models (e.g. Bedrock) can no longer
  poison every other provider's refresh.
- Routing resolves coder:<name>/<model> through persisted provider
  metadata (discoveredProviders, then the user-managed
  additionalProviders escape hatch for custom names members cannot list,
  then the name === type default) and picks the wire protocol by type:
  anthropic/bedrock speak Anthropic messages, openai speaks the
  Responses API, other OpenAI-wire types speak chat completions. Copilot
  instances are rejected as unsupported (they need client-minted
  request-time tokens).
- New coderOauth.refreshModels IPC, a Settings 'Refresh models' button,
  and a command palette action re-run discovery without a re-login.
…y catalogs

Found while dogfooding against dev.coder.com: /v1/models is a gateway
passthrough, and Anthropic rejects requests without the required
anthropic-version header with a conclusive 400 — which discovery read
as 'no models', hiding every Anthropic model. Send the header for
anthropic- and bedrock-type provider instances only.
@mintlify

mintlify Bot commented Aug 13, 2026

Copy link
Copy Markdown

Preview deployment for your docs. Learn more about Mintlify Previews.

Project Status Preview Updated (UTC)
Mux 🟢 Ready View Preview Aug 13, 2026, 12:45 PM

💡 Tip: Enable Workflows to automatically generate PRs for you.

@ThomasK33

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 4d46a948cc

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/node/services/coderOauthService.ts Outdated
…iently

Codex P2: on a fresh login (discoveredModels absent) the per-provider
carry-forward has nothing to carry for a transiently-failed provider, so
persisting the other providers' lists would flip routing from fail-open
to an authoritative partial catalog that blocks the failed provider's
models. Skip the write (and surface an error from refreshModels) when
the prior catalog is unknown and any provider errored; known catalogs
keep the per-provider merge.
@ThomasK33

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 3de90766d9

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/node/services/coderOauthService.ts Outdated
…g stays unknown

Codex P2 round 2: the fresh-unknown guard also discarded the
authoritative /api/v2/ai/providers listing, leaving custom-named
instances unresolvable (manual models unroutable) until every catalog
request succeeded. The listing is conclusive independently of the
catalog fetches: persist discoveredProviders while keeping
discoveredModels absent (fail-open). Probe-derived fallback metadata is
just the name===type default routing already applies, so the
inconclusive probe path still skips all persistence.
@ThomasK33

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 549fa6981f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/node/services/coderOauthService.ts Outdated
Comment thread src/node/services/coderOauthService.ts Outdated
Two findings on the same root cause — carry-forward requires prior state
for the errored provider, not just a present catalog:

1. All-fetches-failed guard ran before the locked write, discarding a
   conclusive authoritative listing. The early return is gone; the write
   predicate now handles every case, persisting discoveredProviders when
   the listing is authoritative even if no catalog was fetched.
2. A KNOWN catalog + an admin-added provider whose first fetch errors
   persisted a partial catalog that blocked the new provider's models.
   An errored provider without prior state (no prior metadata and no
   prior entries under its prefix) now flips the whole catalog to
   UNKNOWN (fail-open), preserving manual entries and the authoritative
   listing; the next successful refresh rebuilds the catalog.
@ThomasK33

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 22ba4d11a7

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/node/services/providerModelFactory.ts
Comment thread src/node/services/providerModelFactory.ts
…icalize options (Codex round 4)

- fromCoderGatewayModelId only canonicalizes default-named anthropic/openai
  instances; coder:google/x etc. stay gateway-scoped so routing never
  bypasses the gateway
- resolveCoderWireCanonicalModel derives the wire origin from the instance
  type; buildProviderOptions/buildRequestHeaders use it so custom-named
  instances emit identical thinking/cache options and 1M beta headers
- expose discoveredProviders/additionalProviders through provider IPC
@ThomasK33

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6b6874d531

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/common/utils/ai/providerOptions.ts Outdated
An instance can use a canonical route name with a different type (e.g.
{name: "openai", type: "anthropic"}); normalizeToCanonical rewrote
coder:openai/<model> to openai:<model> from the name alone, so option and
header building never reached the metadata-aware wire resolution and
emitted OpenAI options for an Anthropic-wire request. Inspect the raw
Coder identity first (mirroring resolveAndCreateModel's raw-prefix shadow
check) so metadata wins over the name convention.
@ThomasK33

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f53453f405

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/node/services/providerModelFactory.ts
Comment thread src/node/services/coderOauthService.ts
…ry-forward (Codex round 6)

- resolveAndCreateModel returns wireProviderName resolved from the RAW
  coder:<instance>/<model> prefix (metadata wins over name convention);
  aiService keys prepareProviderRequestMessages, prepareMessagesForProvider,
  and the providerOptions namespace key on it so Anthropic-only reasoning
  transforms, PDF-filename sanitization, and extras merging run against the
  wire the request actually speaks. canonicalProviderName remains the config
  identity for providers.jsonc modelParameters lookups and telemetry.
- Coder catalog carry-forward on transient /models failures now requires the
  authoritative listing's type to match the prior provider type; a type
  change flips the catalog to inconclusive instead of leaving the old type's
  model IDs selectable on the new wire.
@ThomasK33

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 91c6188fd6

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/common/constants/providers.ts

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 91c6188fd6

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/common/constants/providers.ts
…ex round 7)

Gateway-scoped coder:<instance>/<model> strings carried no catalog
identity: resolveModelForMetadata/getModelStatsResolved missed known
models, so budgeted goals rejected them as unpriced, context limits were
unknown (no limit-driven compaction), and custom Anthropic instances
failed supportsAnthropicCache.

- resolveCoderMetadataCanonicalModel maps an instance's type to the
  canonical catalog model (anthropic/openai/google/azure/bedrock/
  openrouter:<model>, vercel vendor/model; openai-compat/copilot stay
  gateway-scoped). Routing identity unaffected.
- resolveModelForMetadata applies it after explicit mappedToModel
  overrides and never for a custom provider shadowing the coder prefix.
- supportsAnthropicCache accepts providersConfig and resolves Coder
  wires from instance metadata first (raw identity, before name-based
  normalization); cache-control entry points thread the config through
  streamManager and messagePipeline.
@ThomasK33

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 5124d2d198

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/node/services/aiService.ts Outdated
Comment thread src/node/services/providerModelFactory.ts
…fig merge (Codex round 8)

- The refusal-fallback rebuild now passes the RAW nextModelString to
  prepareMessagesForProvider, buildProviderOptions, buildRequestHeaders,
  and the mid-turn thinking rebuild closure (matching the main path's raw
  modelString). Canonicalization rewrites cross-typed Coder instances
  (coder:openai/x, type anthropic) to a direct-provider string, hiding
  instance metadata from cache/option/header builders.
- _createModelCore classifies Coder models as Anthropic-routed by their
  resolved WIRE type (instance metadata, shadow-guarded), not the route
  name: custom-named Anthropic instances now honor the backend's
  authoritative disableBetaFeatures/cacheTtl, and cross-typed
  anthropic-named instances no longer receive Anthropic-only config.
@ThomasK33

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 18b5035bd6

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/node/services/providerModelFactory.ts Outdated
Comment thread src/node/services/aiService.ts Outdated
…llback-away requests

Round 39 Codex review fixes:
- resolveAndCreateModel now fails (api_key_not_found / provider_disabled)
  when a known-but-unmappable coder selection cannot use the gateway,
  instead of letting createModel's gateway-string re-resolution
  name-canonicalize e.g. {name: "anthropic", type: "openai-compat"} to
  direct Anthropic.
- resolveAndCreateModel returns coderSelectedInstance (raw selection's
  instance snapshot, present even on fallback-away routes) and aiService's
  pinCoderInstanceProvidersConfig pins it into the request snapshot keyed
  on the RAW model string, so builders resolving the raw coder: identity
  cannot see a concurrently retagged instance type.
@ThomasK33

Copy link
Copy Markdown
Member Author

@codex review

Please take another look.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 2a56479693

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/node/services/aiService.ts
…g falls away

Round 40 Codex review fix: a Coder selection whose routing fell away from
the gateway (e.g. coder:google/gemini-* -> passthrough mux-gateway) still
passed the raw coder: string to buildProviderOptions/buildRequestHeaders,
which resolved the pinned instance's OpenAI-chat wire and emitted OpenAI
options instead of native Google options (dropping thinkingConfig). Both
builders (main path, mid-turn rebuild closures, and the refusal-fallback
path) now use the effective-route identity already computed for tool
assembly when the raw selection is coder: but the effective route is not.
@ThomasK33

Copy link
Copy Markdown
Member Author

@codex review

Please take another look.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 676eec29a8

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/browser/features/RightSidebar/CostsTab.tsx Outdated
Round 41 Codex review fix: live usage (context + cumulative cost) re-resolved
the raw coder: model against the browser's freshly refreshed providers
config, so an instance removed/retagged mid-stream priced the live row
differently from the backend ledger and CostsTab could split it into a
second bucket. The backend now stamps the request-pinned metadataModel on
stream-start; the aggregator carries it on the active-stream context, the
WorkspaceStore prefers it for live pricing and exposes liveMetadataModel,
and CostsTab keys live coder: rows on it (mirroring the stream-end delta
keying). Red-checked store test included.
@ThomasK33

Copy link
Copy Markdown
Member Author

@codex review

Please take another look.

@chatgpt-codex-connector

This comment has been minimized.

@ThomasK33

Copy link
Copy Markdown
Member Author

@codex review

Please take another look.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 2953f0dc65

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/common/constants/providers.ts
Round 43 Codex review fix: TaskService.resolveTaskAISettings normalized the
task model with normalizeToCanonical, so a cross-typed canonical-name Coder
instance (coder:openai/<claude>, type anthropic) persisted openai:<claude>
into child workspace aiSettings — queued follow-ups and plan→exec
continuations then bypassed the gateway (or failed without direct
credentials). Task settings now use gateway-preserving
normalizeSelectedModel (same rule as ThinkingContext and startup recovery),
including the queued-task relaunch fallback and the workspace-turn thinking
ladder resolution (type-derived via resolveModelForMetadata).
@ThomasK33

Copy link
Copy Markdown
Member Author

@codex review

Please take another look.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6c5e32c44d

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/common/constants/providers.ts
Comment thread src/node/services/aiService.ts
…pinned snapshot

Round 44 Codex review fixes:
- workspaceService goal-continuation kickoff, idle compaction, and heartbeat
  send builders now normalize persisted models with normalizeSelectedModel,
  so cross-typed Coder selections stay gateway-scoped instead of rewriting
  to direct name-alike providers.
- aiService resolves the FINAL effectiveThinkingLevel from the pinned
  requestProvidersConfig (post-factory); the pre-factory resolution remains
  only as the preliminary input to the factory's xAI variant swap, which
  never depends on Coder metadata. A concurrent instance retag can no
  longer leave the thinking level derived from one type while options and
  message preparation build for the other's wire.
@ThomasK33

Copy link
Copy Markdown
Member Author

@codex review

Please take another look.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: eee2fbff92

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/node/services/aiService.ts
Comment thread src/node/services/aiService.ts Outdated
…n time

Round 45 Codex review fixes:
- resolveModelParameterOverrides now receives a raw providers.jsonc view
  pinned to the factory-resolved instance (pinCoderInstanceRawProvidersConfig)
  on both the primary and fallback paths: the helper resolves mappedToModel
  aliases and sampling gates via resolveModelForMetadata internally, so a
  live raw load raced concurrent instance retags.
- Advisor tool usage now records under the CREATION-TIME metadata identity:
  the tool-runtime createModel wrapper captures
  resolveModelForMetadata(model) alongside the costs-included flag, and
  reportModelUsage uses it for pricing, history metadataModel, and the
  coder-model ledger key (mirroring StreamManager.recordSessionUsage).
@ThomasK33

Copy link
Copy Markdown
Member Author

@codex review

Please take another look.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 79b9542558

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/node/services/aiService.ts Outdated
Comment thread src/node/services/streamManager.ts
…ng keys

Round 46 Codex review fixes:
- The advisor createModel wrapper now loads ONE providers.jsonc snapshot and
  passes it to both SDK model creation (factory providersConfig option) and
  the pinned creation-time pricing identity, so a catalog refresh landing
  between two reads can no longer run the request on one wire while
  recording usage under another type. AIService.createModel widened to pass
  the snapshot through.
- SessionTimingService.handleStreamStart keys coder: models on the emitted
  request-pinned metadataModel (mirroring the session-usage ledger), so a
  cross-typed instance no longer merges its latency/throughput stats into
  the name-alike direct provider's rows.
@ThomasK33

Copy link
Copy Markdown
Member Author

@codex review

Please take another look.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 928a80e678

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/node/services/aiService.ts
Comment thread src/node/services/streamManager.ts
… metadataModel

Round 47 Codex review fixes:
- The refusal-fallback prepare path now computes only a PRELIMINARY thinking
  level pre-factory (xAI variant swap input, never Coder-metadata-dependent)
  and recomputes the FINAL nextMinThinkingLevel/nextThinkingLevel from the
  pinned nextProvidersConfig, mirroring the main path's split, so message
  and option builders agree with the wire the fallback SDK model was
  created for.
- CompactionHandler.performCompaction carries the compaction stream's
  request-pinned metadataModel into the persisted summary metadata, so
  session-usage rebuilds after a catalog retag key/reprice the compaction
  request from the pinned identity instead of mutable current metadata.
@ThomasK33

Copy link
Copy Markdown
Member Author

@codex review

Please take another look.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 363813b804

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/node/services/aiService.ts
Comment thread src/common/constants/providers.ts
…compaction defaults

Round 48 Codex review fixes:
- The advisor runtime's createModel now returns the wire-resolved
  optionsModelString derived from the SAME snapshot that created the model
  (mirroring resolveOptionsCanonicalModel's shadow + wire rules), and the
  advisor tool builds providerOptions inside execute from that identity.
  coder:prod-anthropic/... now gets Anthropic reasoning options, and a
  cross-typed coder:openai/... (type anthropic) no longer gets
  OpenAI-namespaced options.
- AgentSession.getPreferredCompactionSettings normalizes the configured
  compaction default with gateway-preserving normalizeSelectedModel, so a
  cross-typed Coder compaction model no longer persists as the direct
  name-alike provider.
@ThomasK33

Copy link
Copy Markdown
Member Author

@codex review

Please take another look.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e950c37e9a

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +252 to +255
const canonicalModel =
modelString.startsWith("coder:") && options?.metadataModel
? options.metadataModel
: normalizeUsageModelKey(modelString, this.getProvidersConfig());

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Pin metadata for every headless Coder request

When a Coder instance is removed or retagged while a headless request is active, this fallback resolves both the ledger key and pricing identity from the new live config rather than the snapshot that created the SDK model. The memory consolidation/harvest callers in memoryConsolidationService.ts:471-508,624-652 and the workspace-status caller in agentStatusService.ts:357-366 never supply the new metadataModel option, so their sidecar and ledger rows can still be attributed to an unknown or different upstream. Capture the creation-time identity for these model creations and pass it through to recordHeadlessUsage().

Useful? React with 👍 / 👎.

Comment on lines +85 to +87
return parsed != null &&
(CODER_CANONICAL_GATEWAY_ROUTES as readonly string[]).includes(parsed.origin)
? parsed

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Keep Coder thinking-floor keys gateway-scoped

When discovery reports a cross-typed canonical-name instance such as {name: "openai", type: "anthropic"}, this still makes normalizeToCanonical("coder:openai/<model>") return openai:<model>. The minimum-thinking configuration paths use that normalizer as their persisted lookup key (useMinThinkingLevels.ts:100-118, config.ts:405-415, agentSession.ts:4027-4033, and the fallback path in aiService.ts:3134-3182), so the explicit Coder model and a direct OpenAI model with the same ID share one floor: changing or clearing either setting changes the other request's behavior. Preserve the raw gateway identity for per-model thinking-floor keys, as the fallback configuration now does.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant