Skip to content

chore: sync upstream fantasy v0.45.5 into coder_2_33 - #72

Merged
ethanndickson merged 160 commits into
coder_2_33from
codagt-1430-upstream-sync
Oct 26, 2026
Merged

ethanndickson merged 160 commits into
coder_2_33from
codagt-1430-upstream-sync

Conversation

@ethanndickson

@ethanndickson ethanndickson commented Oct 26, 2026 •

Copy link
Copy Markdown
Member

This syncs coder_2_33 with upstream charmbracelet/fantasy main at 28d60cb (v0.45.5 plus a kronk bump), which is 85 upstream commits since the last sync in #51. It replaces what this PR used to be, a cherry-pick of charmbracelet#366 and charmbracelet#368, as both are upstream now.

Please merge this with "Create a merge commit", not squash. #51 was squash-merged, same as my sync in #42 (which I then had to fix with #43), so none of the upstream commits it brought in are ancestors of coder_2_33, and git still thinks we last synced at v0.31.0. The first commit is just a -s ours merge of #51's head (d37f122) to put that history back with no file changes. Once this lands, the next sync only has to deal with new upstream commits.

The conflict resolutions are in the merge commit message. The main ones are that upstream's ToolRunBuffer replaces our pendingToolMedia from #64, and newResponsesLanguageModel takes both our reasoning model override (#57) and upstream's header hook (charmbracelet#353).

Upstream has also moved to the official github.com/anthropics/anthropic-sdk-go v1.75 (charmbracelet#336), to github.com/charmbracelet/openai-go (charmbracelet#381) and to Go 1.27.3. The commit after the merge keeps us on what coder/coder ships instead:

  • We still import github.com/charmbracelet/anthropic-sdk-go and github.com/openai/openai-go/v3, which our replaces point at the coder forks. coder/coder replaces github.com/anthropics/anthropic-sdk-go v1.19.0 for aibridge, so that replace would stop applying if fantasy required v1.75. charmbracelet/openai-go only adds an error body fix (fix: return api error instead of decode failure for non-object error bodies openai/openai-go#914), whereas ours has the deferred request serialisation. So I've reverted 111ec83 (the openai-go v3.54 API changes) and adapted the Anthropic provider to the older SDK, e.g. reading the error type from the raw error JSON, as there's no Error.Type().
  • go stays at 1.26.5, as coder/coder is on 1.26.9. kronk v1.31.5 is the last release that builds with Go 1.26, so I've pinned it and reverted 28d60cb's kronk provider changes, which need v1.33.

The last commit fixes a few spots where our Anthropic patches clashed with upstream's. Our message_start and message_delta cases (#50, #41) were swallowing the events upstream now forwards as keepalives, so they forward them too. Claude 5 models get upstream's summarized thinking display on top of our adaptive thinking (#47). Our Anthropic SDK reports a mid-stream error as an untyped error, so upstream's test that it carries a 200 status doesn't apply.

I've also bumped the Go that govulncheck runs with from 1.26.6 to 1.26.10, as it's been failing on every PR since mid-October on standard library vulnerabilities that 1.26.9 and 1.26.10 fix.

When coder/coder picks this up, go mod tidy bumps a few dependencies (otel v1.47, the AWS SDK, google.golang.org/api, etc.). Anthropic streams will also start sending keepalive parts, which chatloop currently counts as the first token for TTFT, so the bump needs to skip those.

I've pointed coder/coder at this PR, and at the top of the stack (#74), and the chatd, aibridge, MCP and chat API tests pass on both, as does a repo-wide go build. The generated swagger docs are also unchanged despite the go-openapi bump. I then ran chatd on a local coderd against our AI gateway on Anthropic, Responses, openai Chat and openaicompat, with parallel tool calls, Anthropic thinking, Responses reasoning and a user-attached PDF, and it all worked.

Part of CODAGT-1430

taciturnaxolotl and others added 30 commits June 16, 2026 11:43
When the agent's final step was tool-only (no text content),
AgentResult.Response copied that empty step, causing callers to see
no output even though earlier steps produced text. finalResponse now
walks backwards to find the most recent step with non-blank text.
Also clarifies that Text() returns the first text block.
Add ReasoningEffortMax constant and handle it in both the openai and
openaicompat provider hooks. Without this, models that accept "max"
(e.g. GLM-5.2 via Neuralwatt) error with "reasoning model `max` not
supported" before the request reaches the API.

Assisted-by: Crush:glm-5.2
…-effort-max

feat(openai): add max reasoning effort
…ning

ReasoningStart was carrying the first reasoning token in its Delta field, which
broke consumers that treat Start as a pure signal (matching TextStart convention).
Split into empty Start + separate ReasoningDelta. Encrypted single-shot blocks
still use atomic Start+Delta+End since they don't stream.

Assisted-by: Crush:qwen3.7-max
Providers that stream tool call arguments across many fragments (e.g.
GLM 5.2) can produce a valid JSON prefix before the full payload
arrives. The old code finalized on the first valid JSON, truncating
the remaining fragments and producing malformed arguments that caused
API rejections and session crashes on the next turn.

Now deltas flow through incrementally for progress visibility, but
ToolInputEnd and ToolCall are emitted only after the stream completes.
Also fixes a stale delta bug in the new-tool-call branch and adds
deterministic index-sorted finalization for parallel tool calls.

💘 Generated with Crush

Assisted-by: Crush:qwen3.7-max
…acelet#290)

When a model generates an invalid tool name (e.g. Kimi putting call
IDs in the function name field), the error message now lists all
available tools so the model can self-correct on the next turn.

Assisted-by: Crush:claude-opus-4-6
Bumps the all group with 2 updates: [github.com/kaptinlin/jsonschema](https://github.com/kaptinlin/jsonschema) and [google.golang.org/genai](https://github.com/googleapis/go-genai).


Updates `github.com/kaptinlin/jsonschema` from 0.8.0 to 0.9.2
- [Release notes](https://github.com/kaptinlin/jsonschema/releases)
- [Commits](kaptinlin/jsonschema@v0.8.0...v0.9.2)

Updates `google.golang.org/genai` from 1.60.0 to 1.61.0
- [Release notes](https://github.com/googleapis/go-genai/releases)
- [Changelog](https://github.com/googleapis/go-genai/blob/main/CHANGELOG.md)
- [Commits](googleapis/go-genai@v1.60.0...v1.61.0)

---
updated-dependencies:
- dependency-name: github.com/kaptinlin/jsonschema
  dependency-version: 0.9.2
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: all
- dependency-name: google.golang.org/genai
  dependency-version: 1.61.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: all
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…mbracelet#292)

Bumps the kronk group with 1 update: [github.com/ardanlabs/kronk](https://github.com/ardanlabs/kronk).


Updates `github.com/ardanlabs/kronk` from 1.27.9 to 1.28.0
- [Release notes](https://github.com/ardanlabs/kronk/releases)
- [Commits](ardanlabs/kronk@v1.27.9...v1.28.0)

---
updated-dependencies:
- dependency-name: github.com/ardanlabs/kronk
  dependency-version: 1.28.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: kronk
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
When a model returns more than one tool call in a single turn, the
streamed output stopped marking where one call ended and the next began.
Anything reading the stream as it arrived would merge the calls together,
producing malformed arguments that the provider rejected on the next turn
(seen with GLM 5.2 on Fireworks).

Each tool call is now fully delimited as it streams, so a reader can tell
the calls apart without waiting for the whole response. The final result
of every call is unchanged.
Parse "Input too long" errors from Vercel AI Gateway to extract token
counts and mark as context-too-large errors.

Assisted-by: Crush:qwen3.7-plus
…mbracelet#301)

Bumps the kronk group with 1 update: [github.com/ardanlabs/kronk](https://github.com/ardanlabs/kronk).


Updates `github.com/ardanlabs/kronk` from 1.28.4 to 1.28.5
- [Release notes](https://github.com/ardanlabs/kronk/releases)
- [Commits](ardanlabs/kronk@v1.28.4...v1.28.5)

---
updated-dependencies:
- dependency-name: github.com/ardanlabs/kronk
  dependency-version: 1.28.5
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: kronk
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps the all group with 2 updates: [github.com/aws/smithy-go](https://github.com/aws/smithy-go) and [google.golang.org/genai](https://github.com/googleapis/go-genai).


Updates `github.com/aws/smithy-go` from 1.27.2 to 1.27.3
- [Release notes](https://github.com/aws/smithy-go/releases)
- [Changelog](https://github.com/aws/smithy-go/blob/main/CHANGELOG.md)
- [Commits](aws/smithy-go@v1.27.2...v1.27.3)

Updates `google.golang.org/genai` from 1.61.0 to 1.62.0
- [Release notes](https://github.com/googleapis/go-genai/releases)
- [Changelog](https://github.com/googleapis/go-genai/blob/main/CHANGELOG.md)
- [Commits](googleapis/go-genai@v1.61.0...v1.62.0)

---
updated-dependencies:
- dependency-name: github.com/aws/smithy-go
  dependency-version: 1.27.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: all
- dependency-name: google.golang.org/genai
  dependency-version: 1.62.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: all
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…r-message cache markers

Some providers (notably Alibaba Qwen 3.6) only cache prompts when each
cached message block is explicitly tagged, unlike providers that cache
automatically. Previously there was no way to attach those tags, so cache
hits were always zero for those models and every request paid full price.

This adds a general way to attach non-standard fields onto individual
message content blocks, mirroring the existing root-level extra-body
mechanism. When such fields are present the message is sent in the array
form the provider requires; otherwise the simpler plain-text form is kept.
The same mechanism covers any future provider extension without further
changes.

💘 Generated with Crush

Assisted-by: Crush:us.anthropic.claude-opus-4-8
Bumps the all group with 3 updates: [github.com/aws/aws-sdk-go-v2](https://github.com/aws/aws-sdk-go-v2), [github.com/aws/aws-sdk-go-v2/config](https://github.com/aws/aws-sdk-go-v2) and [github.com/kaptinlin/jsonschema](https://github.com/kaptinlin/jsonschema).


Updates `github.com/aws/aws-sdk-go-v2` from 1.42.0 to 1.42.1
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Commits](aws/aws-sdk-go-v2@v1.42.0...v1.42.1)

Updates `github.com/aws/aws-sdk-go-v2/config` from 1.32.25 to 1.32.27
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Commits](aws/aws-sdk-go-v2@config/v1.32.25...config/v1.32.27)

Updates `github.com/kaptinlin/jsonschema` from 0.9.2 to 0.9.3
- [Release notes](https://github.com/kaptinlin/jsonschema/releases)
- [Commits](kaptinlin/jsonschema@v0.9.2...v0.9.3)

---
updated-dependencies:
- dependency-name: github.com/aws/aws-sdk-go-v2
  dependency-version: 1.42.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: all
- dependency-name: github.com/aws/aws-sdk-go-v2/config
  dependency-version: 1.32.27
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: all
- dependency-name: github.com/kaptinlin/jsonschema
  dependency-version: 0.9.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: all
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
LarsArtmann and others added 6 commits October 20, 2026 10:16
…flow (charmbracelet#431)

Parasail reports an oversized prompt with "this model's maximum context
length is N tokens, but the prompt contains M input tokens", which was
not matched, so a context overflow looked like a generic provider
failure. Capture the maximum and used token counts so it is handled like
the other providers.

Assisted-by: Crush:prism
Update both modules and adapt the Kronk provider to the typed NUMA strategy and string model metadata. Remove the unsupported per-model offload minimum batch option.

Amp-Thread-ID: https://ampcode.com/threads/T-01a169a1-9771-71c8-a7ed-cf942193f399
Co-authored-by: Amp <amp@ampcode.com>
@linear-code

linear-code Bot commented Oct 26, 2026

Copy link
Copy Markdown

CODAGT-1430

@ethanndickson

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 26, 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-26T04:02:57.544419Z eea77ce 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.

@ethanndickson
ethanndickson added this pull request to stack #75 October 26, 2026 01:52
Squash-merging #51 collapsed the v0.40.0 sync into bb10946, so upstream's
history is not in coder_2_33's ancestry and the merge base with
charmbracelet/fantasy is still v0.31.0. This records the real merge
(d37f122, whose tree matches bb10946) as a parent with no file changes, so
the next upstream merge only surfaces commits after v0.40.0.
Merges charmbracelet/fantasy main at 28d60cb (v0.45.5 plus a kronk bump).

Conflict resolutions:
- providers/openai, providers/openaicompat: take upstream's ToolRunBuffer
  and ToolMessages (charmbracelet#366, charmbracelet#368), which replace the fork's pendingToolMedia
  (#64), and upstream's reasoning_content replay.
- providers/openai: newResponsesLanguageModel takes both the fork's
  reasoning-model override (#57) and upstream's header hook
  (charmbracelet#353). Keep reasoningGenerationPattern.
- providers/anthropic: keep the fork's effort switch (#47);
  emit upstream's still-open tool blocks before the fork's per-request
  usage (#50).
- go.mod, go.sum: take upstream's, keep the fork's SDK replaces. The
  next commits restore the coder SDK forks and Go 1.26.
coder/coder ships the coder forks of anthropic-sdk-go and openai-go and
builds with Go 1.26, so keep both after the upstream sync:

- Import github.com/charmbracelet/anthropic-sdk-go and
  github.com/openai/openai-go/v3 again instead of upstream's
  github.com/anthropics/anthropic-sdk-go v1.75 (charmbracelet#336) and
  github.com/charmbracelet/openai-go (charmbracelet#381). The existing replaces point
  both at the coder forks.
- anthropic: adapt to the older SDK API (anthropic.Model conversion,
  NewThinkingConfigAdaptiveParam) and read the error type from the raw
  error envelope, since the SDK has no Error.Type accessor.
- openai: revert 111ec83 (openai-go v3.54 API adaptation).
- go.mod: go 1.26.5. Pin kronk v1.31.5, the last release that builds with
  Go 1.26, and its jinja v1.8.0 and yzma v1.23.0. Revert 28d60cb's kronk
  provider adaptation (typed NUMA strategy, string model type), which
  needs kronk v1.33.
- examples/go.mod: same Go and kronk pins.
…ing and thinking display

- Forward message_start and message_delta as keepalives. Upstream forwards
  every content-free event as a keepalive (ca3b510), but the fork handles
  both events itself for per-request usage (#50) and refusal
  metadata (#41), so they never reached the catch-all.
- Claude 5 models keep adaptive thinking from the fork's version rule
  (#47) and now also get upstream's summarized display
  default (02d13f0). Update both tests to expect that.
- The coder SDK fork reports a mid-stream error event as an untyped error,
  so drop the upstream test's assertion that it carries status 200. The
  title and retry assertions still hold through wrapStreamError.
@ethanndickson
ethanndickson force-pushed the codagt-1430-upstream-sync branch from 73e8de2 to bedfd1e Compare October 26, 2026 02:47
@ethanndickson ethanndickson changed the title fix: cherry-pick upstream fixes for OpenAI-compatible tool messages chore: sync upstream fantasy v0.45.5 into coder_2_33 Oct 26, 2026
@ethanndickson

Copy link
Copy Markdown
Member Author

@codex review

@ethanndickson
ethanndickson marked this pull request as ready for review October 26, 2026 02:55

@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: bedfd1eb11

ℹ️ 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 providers/kronk/language_model.go
Comment thread providers/kronk/language_model.go
Go 1.26.6 has standard library vulnerabilities that Go 1.26.9 and
1.26.10 fix (GO-2026-6603, -6605, -6607, -6608, -6610, -6611, -6612,
-6613, -6617 and -6809), so govulncheck fails on every PR.
@ethanndickson

Copy link
Copy Markdown
Member Author

@codex review

re: Return synchronous Kronk error finishes as errors
re: Exclude cached tokens from Kronk input usage

Both of these come from upstream, not from the sync. providers/kronk/language_model.go is identical to upstream at 28d60cb: charmbracelet#332 (kronk v1.30.8) stopped Generate from returning an error for FinishReasonError, and added CacheReadTokens without taking the cached tokens out of InputTokens. coder/coder doesn't use the kronk provider, so I'm leaving both as upstream has them rather than diverging the fork in a sync PR.

@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: eea77ce78f

ℹ️ 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 agent.go
Comment thread providers/openai/language_model.go
@ethanndickson

Copy link
Copy Markdown
Member Author

@codex review

re: Map valid streamed stop tool calls to tool-calls

re: Buffer provider tool results with their calls

Both of these come from upstream, not from the sync: agent.go and the flagged block in providers/openai/language_model.go are identical to upstream at 28d60cb. The callback ordering comes from 41a4548 (gating provider-executed OnToolCall on the finish reason), and the stop-with-tool-calls handling comes from charmbracelet#347 and the CHARM-2020 truncation fixes. coder/coder doesn't use the fantasy Agent loop: chatd collects the streamed tool calls itself and runs them regardless of the finish reason, so neither affects us. I'm leaving both as upstream has them rather than diverging the fork in a sync PR.

@ethanndickson

Copy link
Copy Markdown
Member Author

@codex review

re: Map valid streamed stop tool calls to tool-calls

re: Buffer provider tool results with their calls

Both of these come from upstream, not from the sync: agent.go and the flagged block in providers/openai/language_model.go are identical to upstream at 28d60cb. The callback ordering comes from 41a4548 (gating provider-executed OnToolCall on the finish reason), and the stop-with-tool-calls handling comes from charmbracelet#347 and the CHARM-2020 truncation fixes. coder/coder doesn't use the fantasy Agent loop: chatd collects the streamed tool calls itself and runs them regardless of the finish reason, so neither affects us. I'm leaving both as upstream has them rather than diverging the fork in a sync PR.

re: Return synchronous Kronk error finishes as errors
re: Exclude cached tokens from Kronk input usage

Both of these come from upstream, not from the sync. providers/kronk/language_model.go is identical to upstream at 28d60cb: charmbracelet#332 (kronk v1.30.8) stopped Generate from returning an error for FinishReasonError, and added CacheReadTokens without taking the cached tokens out of InputTokens. coder/coder doesn't use the kronk provider, so I'm leaving both as upstream has them rather than diverging the fork in a sync PR.

@chatgpt-codex-connector

Copy link
Copy Markdown

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

Reviewed commit: eea77ce78f

ℹ️ 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 merged commit 85ffbbe into coder_2_33 Oct 26, 2026
6 checks passed
ethanndickson pushed a commit to coder/coder that referenced this pull request Oct 27, 2026
Moves the fantasy pin to the tip of `coder_2_33` (`85ffbbe`). That
commit is coder/fantasy#72, which merges 87 upstream
charmbracelet/fantasy commits, v0.40.0 to v0.45.5. Between the two pins
117 files change. Upstream's own v0.40.0 to v0.45.5 change, without
tests, testdata, examples, `go.sum` and the kronk provider, is 43 files,
+2271/−928.

## What reaches chatd

chatd builds only the `anthropic`, `openai` and `openaicompat` fantasy
clients (`chatprovider.ModelFromConfig`); other vendors reach it through
the AI Gateway on one of those. So the upstream changes to the Google,
Vercel, OpenRouter, Bedrock, Azure and kronk providers, and to the
`fantasy.Agent` loop and its retries, do not run in chatd. These do:

- **Chat Completions and openaicompat streams** keep reasoning on
batched and DeepSeek-shaped chunks, keep `finish_reason: length` when
tool calls are truncated, and stop sending empty reasoning fields.
openaicompat drops assistant turns that hold only reasoning.
- **Token usage.** When an OpenAI-shaped backend reports reasoning
tokens apart from completion tokens (reasoning larger than output),
output tokens now include them, so that backend's reported output tokens
and cost rise. OpenAI's own shape, where reasoning is a subset, is
unchanged.
- **Responses.** A content-filtered turn no longer reads as a tool-call
turn.
- **Context overflow.** Baseten, Fireworks and Parasail prompt-length
errors set `ContextTooLargeErr`, which compaction acts on.
- **Anthropic.** Tool calls whose content block never closes are
reported. For Claude 5 models, thinking defaults to `display:
"summarized"` when the chat config sets none; a configured display still
wins. `TestThinkingDropBlockModel_RetriesWithEffort` now expects the
field in the retry body.
- **Anthropic keepalives.** Fantasy forwards `message_start`,
`message_delta` and unknown events as content-free `keepalive` parts.
The first one arrives before any model output, so this PR makes
`ttft_seconds` and the `time_to_first_token` stage skip them, as they
skip warnings. They still reset the stream silence guard.
`processStepStream` ignores them, and the debug recorder counts them in
its part count but records no content.
- **Tool-result media** now goes through upstream's shared
`ToolRunBuffer`, which replaces coder/fantasy#64 and does the same
thing.

#72 keeps coder's anthropic-sdk-go and openai-go forks, Go 1.26 and
kronk v1.31.5, so upstream's SDK and Go moves do not come along.

`go mod tidy` raises the modules fantasy v0.45.5 requires, among them
otel exporters v1.47, the AWS SDK, `google.golang.org/api` v0.307 and
go-openapi v1. All are upgrades.

The `go.mod` comment now names #72 as the upstream sync.

#29861 stacks on this PR to pin coder/fantasy#62.

<details>
<summary>Verification</summary>

- `go build ./...`.
- `go test` passes on every package that imports fantasy
(`coderd/x/chatd/...`), and `go test ./coderd -run
'TestChat|TestExpChat|TestMCP|TestAIBridge'` passes.
-
`TestGuardedStreamTTFTStage/WarningsAndKeepalivesThenContentObservesOnce`
fails without the TTFT change (TTFT observed 0s instead of 1s) and
passes with it.
- `make pre-commit` passes. The generated Prometheus docs pick up the
metric help change.

Not verified against live backends in this PR: the stream fixes, the
token usage change and the context-overflow patterns have no coder test
against a real provider. coder/fantasy#72 reports a local chatd run
against the AI Gateway on Anthropic, Responses, OpenAI Chat and
openaicompat.

</details>

> 🤖 This PR was created with the help of Coder Agents, and _will be_
reviewed by a human. 🏂🏻
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.