Skip to content

refactor(coderd/x/chatd): inline the model config provider identity - #31000

Open
ibetitsmike wants to merge 1 commit into
mike/chatprompt-retire-legacy-codecfrom
mike/chatd-inline-provider-identity
Open

ibetitsmike wants to merge 1 commit into
mike/chatprompt-retire-legacy-codecfrom
mike/chatd-inline-provider-identity

Conversation

@ibetitsmike

@ibetitsmike ibetitsmike commented Oct 18, 2026 •

Copy link
Copy Markdown
Collaborator

This PR deletes modelConfigProviderIdentity and its test table; both callers now use AIProviderID.UUID.String() directly. The helper fell back to the provider type name for model configs without an ai_provider_id. It changes no behavior, because no such config reaches either caller: the chat_model_configs_ai_provider_required_when_active check constraint allows a NULL ai_provider_id only on deleted configs, and both callers reject such a config before they read the identity.

  • Turn preparation resolves the chat's config through gatewayProviderForConfig, which returns "AI Gateway routing requires AI provider metadata" for a config without a provider ID.
  • History sanitization resolves each row's origin config through resolveNormalizedProviderForModelConfig, which returns sql.ErrNoRows. The sanitizer treats that origin as unavailable and strips the row's provider-specific state (fail closed), as before.

Why it is safe

The deleted table tested the helper. Its live contract is that identity is the provider instance UUID, so two providers of the same type are distinct. I mutated the two inlined lines and ran ./coderd/x/chatd/ with go test -overlay. The tests catch all three mutants:

  • Turn target identity set to the provider type: TestActiveServer_AnthropicProviderToolPreRequestGuard, TestOpenAIResponsesFullReplayPairsReasoningAndWebSearch and others fail.
  • Origin identity set to the normalized type: the same tests fail.
  • Both sites set to the type, so they agree: TestOpenAIResponsesReasoningNotReplayedAfterModelConfigChange/ProviderMoved and TestProviderSwitchSanitizesAndRestoresPEToolHistory fail.

git grep modelConfigProviderIdentity finds no references left in the repository, including site/, enterprise/, cli/ and docs/.

Review focus

sanitizeForeignProviderStateRows now discards the normalized provider name that resolveModelConfigAndNormalizedProvider returns. It still calls that function, because the function also checks that the config is enabled and its provider is valid.

Validation

  • go test ./coderd/x/chatd/ -count=1 -p 4 -parallel 4: ok
  • go vet ./coderd/x/chatd/ and golangci-lint run --fix=false ./coderd/x/chatd/...: clean
  • pre-commit hook: passed

Stack

This stack retires chatd compatibility paths for chat data that older Coder versions stored.

  1. test(coderd): stamp chat message fixtures with the current content version #30996 stamp chat message fixtures with the current content version
  2. test(coderd/x/chatd/chatprompt): drop tests of the legacy content codec #30997 drop tests of the legacy content codec
  3. refactor(coderd)!: retire the V0 chat message content decoder #30998 retire the V0 chat message content decoder
  4. refactor(coderd/x/chatd): inline the model config provider identity #31000 inline the model config provider identity (this PR)
  5. refactor(coderd/x/chatd)!: retire the close_agent tool alias #31005 retire the close_agent tool alias

Xum, an AI agent, opened this PR for @ibetitsmike and wrote this description.

@ibetitsmike

Copy link
Copy Markdown
Collaborator Author

@codex review

Xum, an AI agent, posted this comment for @ibetitsmike.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 18, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-26T18:14:06.406679Z 825f14a Manual request
ℹ️ 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" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Bravo.

Reviewed commit: 817c96dcba

ℹ️ 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".

@ibetitsmike

Copy link
Copy Markdown
Collaborator Author

@codex review

Xum, an AI agent, posted this comment for @ibetitsmike.

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. 🎉

Reviewed commit: ce72f1f249

ℹ️ 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".

@ibetitsmike

Copy link
Copy Markdown
Collaborator Author

@codex review

Xum, an AI agent, posted this comment for @ibetitsmike.

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. What shall we delve into next?

Reviewed commit: 52343877b2

ℹ️ 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".

@ibetitsmike

Copy link
Copy Markdown
Collaborator Author

@codex review

Xum, an AI agent, posted this comment for @ibetitsmike.

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Hooray!

Reviewed commit: 14ee83c794

ℹ️ 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".

@ibetitsmike

Copy link
Copy Markdown
Collaborator Author

@codex review

Xum, an AI agent, posted this comment for @ibetitsmike.

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Nice work!

Reviewed commit: 03d7fde859

ℹ️ 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".

@linear-code

linear-code Bot commented Oct 21, 2026

Copy link
Copy Markdown

CODAGT-1445

@ibetitsmike

Copy link
Copy Markdown
Collaborator Author

@codex review

Xum, an AI agent, posted this comment for @ibetitsmike.

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. More of your lovely PRs please.

Reviewed commit: e26a46a186

ℹ️ 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".

@ibetitsmike

Copy link
Copy Markdown
Collaborator Author

@codex review

Xum, an AI agent, posted this comment for @ibetitsmike.

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. 🎉

Reviewed commit: 825f14a182

ℹ️ 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".

@ethanndickson

ethanndickson commented Oct 28, 2026 •

Copy link
Copy Markdown
Member

This is fine to land as is. Heads up though: I'm going to look at improving how the provider switch filter works out which provider produced a row, as part of the OpenAI web search replay work (coder/fantasy#78, coder/fantasy#77, #31355). Right now it re-reads each row's model config every turn and compares exact provider rows, which is probably stricter than it needs to be for web search blocks. That'll likely touch these same lines, and will probably come after this is merged.

Generated by an agent on behalf of the user

ibetitsmike added a commit that referenced this pull request Oct 28, 2026
…rsion (#30996)

Chat prompt tests built most of their stored-message fixtures in the
legacy content format (`content_version` 0), so they exercised the
legacy decoder instead of the current one. This PR changes tests only:
it stamps those fixtures with `ContentVersionV1` and builds them with
`MarshalParts`, so they keep passing after the legacy decoder is removed
later in this stack. Tests of the version 0 decoder itself keep their
version 0 rows until the layers above remove that decoder.

**Why it is safe**

- `mustMarshalContent` and `mustMarshalToolResult` now build current
parts (`PartFromContent`, `ChatMessageToolResult`) and encode them with
`MarshalParts`, the production write path.
- `TestMixedFormatConversation` becomes
`TestConvertMessagesWithFiles_Conversation` and uses current-format rows
only.
- `TestParseContent_BackwardCompat` does not change. Migration 000434
stamped every existing row with version 0, so its six cases of
current-format parts in version 0 rows still cover the version 0
heuristics. #30998 moves those six cases to version 1 rows when it
removes that decoder.
- `TestProviderExecutedResult_LegacyToolRow` calls the legacy writers
(`MarshalContent`, `MarshalToolResult`) directly, so its
provider-executed tool row still goes through the legacy tool-row
decoder.
- `TestParseContent_ErrorPaths` runs its malformed-input cases on
version 1 rows, and runs the same input on version 0 rows of each role
(`v0/<role>/malformed_json`), so a version 0 parser that accepts
malformed content still fails the suite. #30998 deletes the version 0
cases with that decoder.
- I ran the 17 mutants listed below, each a `go test -overlay` edit of
the current decode and prompt-conversion code in `chatprompt.go`,
against the `chatprompt` and `db2sdk` tests on `main` and on this
branch. Every mutant `main` catches is still caught. Two more are caught
here: mutant 3, because
`TestParseContent_ErrorPaths/system/malformed_json` used to hit the
legacy system decoder, and mutant 14, by the new JSON `null` case of
`TestConvertMessagesWithFiles_NormalizesAssistantToolCallInput`. Mutants
4 and 8 survive those tests on both. The `chatd` test
`TestOrganizationSkillsFollowChatOwnerAccess` catches mutant 4, so 8 is
an existing gap.
- Mutants of the version 0 decoder fail on `main` and on this branch:
version 0 assistant or user rows always take the envelope path, their
current-format parts are dropped, legacy tool rows lose
`provider_executed`, or a version 0 parser accepts malformed JSON.
- With the version 0 case removed from `ParseContent` by an overlay,
only tests of version 0 rows fail. #30997 deletes them, except the six
`TestParseContent_BackwardCompat` cases, which #30998 moves, and the
version 0 cases of `TestParseContent_ErrorPaths`, which #30998 deletes.

<details>
<summary>The 17 mutants</summary>

1. `ParseContent` returns no parts for a V1 row.
2. V1 decoding skips NUL restoration (`decodeNulInParts`).
3. The V1 parse error says "decode" instead of "parse".
4. Tool error string extraction is off (`toolResultPartToMessagePart`).
Only a `chatd` test catches it.
5. Tool call input is dropped.
6. Tool call `ProviderExecuted` is dropped when reading.
7. Resolved file data is dropped.
8. The file media type fallback is dropped (`partsToMessageParts`).
Survives.
9. User file IDs are not collected for resolution.
10. Text provider metadata is dropped.
11. File reference text is replaced by the raw content.
12. System messages are dropped.
13. Tool call `ProviderExecuted` is dropped when writing
(`PartFromContent`).
14. `normalizeToolCallInput` keeps a JSON `null` input instead of `{}`.
Survives on `main` only.
15. Text tool result `ProviderExecuted` is dropped.
16. Tool result IDs are dropped.
17. Assistant file IDs are resolved like user file IDs.

</details>

**Review focus**

The rewritten conversation test in `chatprompt_test.go`. It checks the
same prompt shape as before, but every row is in the current format. In
the same file, `TestProviderExecutedResult_LegacyToolRow` keeps its
legacy rows, `TestParseContent_ErrorPaths` checks malformed input on
both content versions, and the input normalization table gains a JSON
`null` case. The other changed test files only switch fixtures to the
current format: `coderd/x/chatd/chatprompt/file_inline_test.go`
(+4/-16), `coderd/database/db2sdk/db2sdk_test.go` (+11/-13),
`coderd/x/chatd/message_conversion_test.go` (+3/-2) and
`coderd/x/chatd/quickgen_internal_test.go` (+1).

**Validation**

- `go test ./coderd/x/chatd/... ./coderd/database/db2sdk/ -count=1 -p 4
-parallel 4`: ok
- `go vet` on the touched packages and `golangci-lint run --fix=false
./coderd/x/chatd/chatprompt/...`: clean
- pre-commit hook: passed

**Stack**

This stack retires chatd compatibility paths for chat data that older
Coder versions stored.

1. #30996 stamp chat message fixtures with the current content version
(this PR)
2. #30997 drop tests of the legacy content codec
3. #30998 retire the V0 chat message content decoder
4. #31000 inline the model config provider identity
5. #31005 retire the `close_agent` tool alias

> Xum, an AI agent, opened this PR for @ibetitsmike and wrote this
description.
@ibetitsmike
ibetitsmike force-pushed the mike/chatd-inline-provider-identity branch from 825f14a to 7b3e5b4 Compare October 29, 2026 22:57

This branch has not been deployed

No deployments
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.

2 participants