mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
aa5ec0bfcccdab37f2b57e7f9d15e96bea52a051
13512
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
aa5ec0bfcc |
feat(site/src/pages/AgentsPage): add copy button to ProposePlanTool (#23940)
Reuse the CopyButton component to let users copy plan content from the propose_plan tool output. Follows the same pattern used by the assistant message copy button. |
||
|
|
16add93908 |
fix(coderd/x/chatd): stabilize subagent pubsub completion test (#23944)
- stabilize `TestAwaitSubagentCompletion/CompletesViaPubsub` by waiting
for durable completion state before sending the synthetic pubsub wake
- add coverage for successful subagent completion with an empty report
> 🤖 Written by a Coder Agent. Reviewed by a human.
|
||
|
|
fe13fd065c |
chore: downgrade log level for unauthenticated HEAD requests (#23923)
Some clients (e.g. Claude) send a HEAD request without credentials as a connectivity check before making actual API calls. This was logging at `Warn` level, creating noise. Downgrade to Info for unauthenticated HEAD requests and add the HTTP method to the logger for better observability. Related to internal slack thread: https://codercom.slack.com/archives/C0AEHQGLW22/p1775045200997309 |
||
|
|
fb788530b3 |
feat: add provider_name column to aibridge interceptions (#23960)
## Description Adds `provider_name` to aibridge interceptions to store the provider instance name alongside the provider type. This allows distinguishing between multiple instances of the same provider type (e.g. `copilot` vs `copilot-business`). ## Changes * Add `provider_name` column to `aibridge_interceptions` table with backfill from `provider`. * Add `provider_name` field to the proto `RecordInterceptionRequest` message. * Add `ProviderName` to the `codersdk.AIBridgeInterception` API response. _Disclaimer: initially produced by Claude Opus 4.6, modified and reviewed by @ssncferreira ._ |
||
|
|
f4dc8f6b11 |
test: use non-monitoring RPC role in apptest setup (#23953)
Closes https://github.com/coder/internal/issues/1432 Closes https://github.com/coder/internal/issues/1399 The test setup in `createWorkspaceWithApps` opens a short-lived RPC connection to fetch the agent manifest before starting the real agent. This connection used `ConnectRPC()` which sends no `role` parameter, so the server treated it as a real agent connection and enabled connection monitoring. When the helper closed, its monitor asynchronously wrote `disconnectedAt` to the DB — racing with the real agent's monitor and transiently marking the agent as disconnected. The fix uses `ConnectRPCWithRole(ctx, "apptest-manifest")` so the helper doesn't trigger connection monitoring. The server already has this role-based distinction for non-agent clients like `coder-logstream-kube`; the test helper just wasn't using it. Both issues share this codepath: `setupProxyTest` → `createWorkspaceWithApps` → the `ConnectRPC` call at `setup.go:518`. Both test configurations have a non-empty `PrimaryAppHost`, so both enter the affected block. This is not masking a product issue — the "disconnected" state was caused by two competing monitors writing to the same agent DB row, a scenario that only exists in this test setup. No assertions were weakened; the proxy still checks real agent connectivity on every request. |
||
|
|
bbeff0d4b5 |
fix(site/src/pages/AgentsPage): hide copy button during active turn (#23962)
The copy button on the last assistant message was showing even while the turn was still in progress (agent streaming or running tool calls). The content is not final at that point, so the button should be suppressed until the turn completes. The `lastAssistantPerTurnIds` computation unconditionally included the trailing assistant message. Now it checks a new `isTurnActive` prop derived from `isActiveChatStatus(chatStatus) || hasStreamState` and skips the trailing ID when the turn is active. Completed turns (those followed by a user message) are unaffected. |
||
|
|
78fa8094cc |
chore: bump github.com/gohugoio/hugo from 0.158.0 to 0.159.2 (#23957)
Bumps [github.com/gohugoio/hugo](https://github.com/gohugoio/hugo) from 0.158.0 to 0.159.2. <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/gohugoio/hugo/releases">github.com/gohugoio/hugo's releases</a>.</em></p> <blockquote> <h2>v0.159.2</h2> <p>Note that the security fix below is not a potential threat if you either:</p> <ul> <li>Trust your Markdown content files.</li> <li>Have custom <a href="https://gohugo.io/render-hooks/">render hook template</a> for links and images.</li> </ul> <p>EDIT IN: This release also adds release archives for non-extended-withdeploy builds.</p> <h2>What's Changed</h2> <ul> <li>Fix potential content XSS by escaping dangerous URLs in Markdown links and images 479fe6c6 <a href="https://github.com/bep"><code>@bep</code></a></li> <li>resources/page: Fix shared reader in Source.ValueAsOpenReadSeekCloser df520e31 <a href="https://github.com/jmooring"><code>@jmooring</code></a> <a href="https://redirect.github.com/gohugoio/hugo/issues/14684">#14684</a></li> </ul> <h2>v0.159.1</h2> <p>The regression fixed in this release isn't new, but it's so subtle that we thought we'd release this sooner rather than later. For some time now, the minifier we use have stripped namespaced attributes in SVGs, which broke dynamic constructs using e.g. <a href="https://alpinejs.dev/directives/bind">AlpineJS' x-bind:</a> namespace (library used by Hugo's <a href="https://gohugo.io/">documentation site</a>).</p> <p>To fix this, the upstream library has hadded a <code>keepNamespaces</code> slice option. It was not possible to find a default that would make all happy, so we opted for an option that at least would make AlpineJS sites work out of the box:</p> <pre lang="toml"><code> [minify.tdewolff.svg] keepNamespaces = ['', 'x-bind'] </code></pre> <h2>What's Changed</h2> <ul> <li>minifiers: Keep x-bind and blank namespace in SVG minification 42289d76 <a href="https://github.com/bep"><code>@bep</code></a> <a href="https://redirect.github.com/gohugoio/hugo/issues/14669">#14669</a></li> </ul> <h2>v0.159.0</h2> <p>This release greatly improves and simplifies management of Node.js/npm dependencies in a multi-module setup. See <a href="https://gohugo.io/hugo-modules/nodejs-dependencies/">this page</a> for more information.</p> <h2>Note</h2> <ul> <li>Replace deprecated site.Data with hugo.Data in tests a8fca598 <a href="https://github.com/bep"><code>@bep</code></a></li> <li>Replace deprecated excludeFiles and includeFiles with files in tests 182b1045 <a href="https://github.com/bep"><code>@bep</code></a></li> <li>Replace deprecated :filename with :contentbasename in the permalinks test eb11c3d0 <a href="https://github.com/bep"><code>@bep</code></a></li> </ul> <h2>Bug fixes</h2> <ul> <li>tpl/tplimpl: Fix Vimeo shortcode test eaf4c751 <a href="https://github.com/jmooring"><code>@jmooring</code></a> <a href="https://redirect.github.com/gohugoio/hugo/issues/14649">#14649</a></li> </ul> <h2>Improvements</h2> <ul> <li>create: Return error instead of panic when page not found 807cae1d <a href="https://github.com/mango766"><code>@mango766</code></a> <a href="https://redirect.github.com/gohugoio/hugo/issues/14112">#14112</a></li> <li>commands: Preserve non-content files in convert output c4fb61d9 <a href="https://github.com/xndvaz"><code>@xndvaz</code></a> <a href="https://redirect.github.com/gohugoio/hugo/issues/4621">#4621</a></li> <li>npm: Use workspaces to simplify <code>hugo mod npm pack</code> d88a29e0 <a href="https://github.com/bep"><code>@bep</code></a></li> </ul> <!-- raw HTML omitted --> </blockquote> <p>... (truncated)</p> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/gohugoio/hugo/commit/5f4646acaad89e1166aac118e118b0d28013f460"><code>5f4646a</code></a> releaser: Bump versions for release of 0.159.2</li> <li><a href="https://github.com/gohugoio/hugo/commit/479fe6c654937a850b65e74551dc4e857d52898f"><code>479fe6c</code></a> Fix potential content XSS by escaping dangerous URLs in links and images</li> <li><a href="https://github.com/gohugoio/hugo/commit/81a5cdca0788ca39574a17d444c9db29d0b19e27"><code>81a5cdc</code></a> releaser: Add standard withdeploy release assets</li> <li><a href="https://github.com/gohugoio/hugo/commit/df520e315087210e069050a873fb5e208659af91"><code>df520e3</code></a> resources/page: Fix shared reader in Source.ValueAsOpenReadSeekCloser</li> <li><a href="https://github.com/gohugoio/hugo/commit/b55d452e46e81369a65978459a0683efa484c11b"><code>b55d452</code></a> testing: Simplify line ending handling in tests</li> <li><a href="https://github.com/gohugoio/hugo/commit/ea7eac65589a7c6e138a2dfba12615335b29bef3"><code>ea7eac6</code></a> readme: Update Go version to 1.25.0</li> <li><a href="https://github.com/gohugoio/hugo/commit/458ebdd448492d82113b0149886f2b5f8e7b91a4"><code>458ebdd</code></a> releaser: Prepare repository for 0.160.0-DEV</li> <li><a href="https://github.com/gohugoio/hugo/commit/86c7d3afacab79dc53325602d77ef884b7570268"><code>86c7d3a</code></a> releaser: Bump versions for release of 0.159.1</li> <li><a href="https://github.com/gohugoio/hugo/commit/42289d76f9ccac052c22b84d7024e64cfb0a683b"><code>42289d7</code></a> minifiers: Keep x-bind and blank namespace in SVG minification</li> <li><a href="https://github.com/gohugoio/hugo/commit/0c013c2326be1bbebba9a9f89d27072074fc6cc4"><code>0c013c2</code></a> Adjust depreceated syntax in tests</li> <li>Additional commits viewable in <a href="https://github.com/gohugoio/hugo/compare/v0.158.0...v0.159.2">compare view</a></li> </ul> </details> <br /> [](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) --- <details> <summary>Dependabot commands and options</summary> <br /> You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) </details> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> |
||
|
|
a85e00eed0 |
chore: bump google.golang.org/grpc from 1.79.3 to 1.80.0 (#23956)
Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.79.3 to 1.80.0. <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/grpc/grpc-go/releases">google.golang.org/grpc's releases</a>.</em></p> <blockquote> <h2>Release 1.80.0</h2> <h1>Behavior Changes</h1> <ul> <li>balancer: log a warning if a balancer is registered with uppercase letters, as balancer names should be lowercase. In a future release, balancer names will be treated as case-insensitive; see <a href="https://redirect.github.com/grpc/grpc-go/issues/5288">#5288</a> for details. (<a href="https://redirect.github.com/grpc/grpc-go/issues/8837">#8837</a>)</li> <li>xds: update resource error handling and re-resolution logic (<a href="https://redirect.github.com/grpc/grpc-go/issues/8907">#8907</a>) <ul> <li>Re-resolve all <code>LOGICAL_DNS</code> clusters simultaneously when re-resolution is requested.</li> <li>Fail all in-flight RPCs immediately upon receipt of listener or route resource errors, instead of allowing them to complete.</li> </ul> </li> </ul> <h1>Bug Fixes</h1> <ul> <li>xds: support the LB policy configured in <code>LOGICAL_DNS</code> cluster resources instead of defaulting to <code>pick_first</code>. (<a href="https://redirect.github.com/grpc/grpc-go/issues/8733">#8733</a>)</li> <li>credentials/tls: perform per-RPC authority validation against the leaf certificate instead of the entire peer certificate chain. (<a href="https://redirect.github.com/grpc/grpc-go/issues/8831">#8831</a>)</li> <li>xds: enabling A76 ring hash endpoint keys no longer causes EDS resources with invalid proxy metadata to be NACKed when HTTP CONNECT (gRFC A86) is disabled. (<a href="https://redirect.github.com/grpc/grpc-go/issues/8875">#8875</a>)</li> <li>xds: validate that the sum of endpoint weights in a locality does not exceed the maximum <code>uint32</code> value. (<a href="https://redirect.github.com/grpc/grpc-go/issues/8899">#8899</a>) <ul> <li>Special Thanks: <a href="https://github.com/RAVEYUS"><code>@RAVEYUS</code></a></li> </ul> </li> <li>xds: fix incorrect proto field access in the weighted round robin (WRR) configuration where <code>blackout_period</code> was used instead of <code>weight_expiration_period</code>. (<a href="https://redirect.github.com/grpc/grpc-go/issues/8915">#8915</a>) <ul> <li>Special Thanks: <a href="https://github.com/gregbarasch"><code>@gregbarasch</code></a></li> </ul> </li> <li>xds/rbac: handle addresses with ports in IP matchers. (<a href="https://redirect.github.com/grpc/grpc-go/issues/8990">#8990</a>)</li> </ul> <h1>New Features</h1> <ul> <li>ringhash: enable gRFC A76 (endpoint hash keys and request hash headers) by default. (<a href="https://redirect.github.com/grpc/grpc-go/issues/8922">#8922</a>)</li> </ul> <h1>Performance Improvements</h1> <ul> <li>credentials/alts: pool write buffers to reduce memory allocations and usage. (<a href="https://redirect.github.com/grpc/grpc-go/issues/8919">#8919</a>)</li> <li>grpc: enable the use of pooled write buffers for buffering HTTP/2 frame writes by default. This reduces memory usage when connections are idle. Use the <a href="https://pkg.go.dev/google.golang.org/grpc#WithSharedWriteBuffer">WithSharedWriteBuffer</a> dial option or the <a href="https://pkg.go.dev/google.golang.org/grpc#SharedWriteBuffer">SharedWriteBuffer</a> server option to disable this feature. (<a href="https://redirect.github.com/grpc/grpc-go/issues/8957">#8957</a>)</li> <li>xds/priority: stop caching child LB policies removed from the configuration. This will help reduce memory and cpu usage when localities are constantly switching between priorities. (<a href="https://redirect.github.com/grpc/grpc-go/issues/8997">#8997</a>)</li> <li>mem: add a faster tiered buffer pool; use the experimental <a href="https://pkg.go.dev/google.golang.org/grpc/mem@master#NewBinaryTieredBufferPool">mem.NewBinaryTieredBufferPool</a> function to create such pools. (<a href="https://redirect.github.com/grpc/grpc-go/issues/8775">#8775</a>)</li> </ul> </blockquote> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/grpc/grpc-go/commit/397e45edaa68f8763773bbaaf539cf7894169cd2"><code>397e45e</code></a> Change version to 1.80.0 (<a href="https://redirect.github.com/grpc/grpc-go/issues/8948">#8948</a>)</li> <li><a href="https://github.com/grpc/grpc-go/commit/64ebf0a600005838970e6ba1eb0a9e46e528ed73"><code>64ebf0a</code></a> Cherry-pick <a href="https://redirect.github.com/grpc/grpc-go/issues/8997">#8997</a> to v1.80.x (<a href="https://redirect.github.com/grpc/grpc-go/issues/9027">#9027</a>)</li> <li><a href="https://github.com/grpc/grpc-go/commit/e45ed241865981b6973cdd0dd69571456d570282"><code>e45ed24</code></a> xds/rbac: add additional handling for addresses with ports (<a href="https://redirect.github.com/grpc/grpc-go/issues/8990">#8990</a>) (<a href="https://redirect.github.com/grpc/grpc-go/issues/9022">#9022</a>)</li> <li><a href="https://github.com/grpc/grpc-go/commit/c78d26e03e129f5cb357b757037fcded2333b74e"><code>c78d26e</code></a> Cherry-pick <a href="https://redirect.github.com/grpc/grpc-go/issues/8957">#8957</a> to v1.80.x (<a href="https://redirect.github.com/grpc/grpc-go/issues/9007">#9007</a>)</li> <li><a href="https://github.com/grpc/grpc-go/commit/bd7cd3c1abbd27fb751275a58886444d52103482"><code>bd7cd3c</code></a> grpc: enforce strict path checking for incoming requests on the server (<a href="https://redirect.github.com/grpc/grpc-go/issues/8987">#8987</a>)</li> <li><a href="https://github.com/grpc/grpc-go/commit/b6597b3d328c1ed6b003f9a23b942af7148352ca"><code>b6597b3</code></a> xds/clusterimpl: use xdsConfig for updates and remove redundant fields from L...</li> <li><a href="https://github.com/grpc/grpc-go/commit/1d4fa8a7b772553e82137b059ad4a8f632a1c522"><code>1d4fa8a</code></a> xds: change cdsbalancer to use update from dependency manager (<a href="https://redirect.github.com/grpc/grpc-go/issues/8907">#8907</a>)</li> <li><a href="https://github.com/grpc/grpc-go/commit/8f47d364511c8eb0517b47e1a39f13a1370c6a10"><code>8f47d36</code></a> attributes: Replace internal map with linked list (<a href="https://redirect.github.com/grpc/grpc-go/issues/8933">#8933</a>)</li> <li><a href="https://github.com/grpc/grpc-go/commit/22e1ee8085952b4bdadf2928c187d665f6daff99"><code>22e1ee8</code></a> xds: add panic recovery in xdsclient resource unmarshalling. (<a href="https://redirect.github.com/grpc/grpc-go/issues/8895">#8895</a>)</li> <li><a href="https://github.com/grpc/grpc-go/commit/7136e99ee323c26984174eb3cec85c201fef9946"><code>7136e99</code></a> credentials/alts: Pool write buffers (<a href="https://redirect.github.com/grpc/grpc-go/issues/8919">#8919</a>)</li> <li>Additional commits viewable in <a href="https://github.com/grpc/grpc-go/compare/v1.79.3...v1.80.0">compare view</a></li> </ul> </details> <br /> [](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) --- <details> <summary>Dependabot commands and options</summary> <br /> You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) </details> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> |
||
|
|
da50a34414 |
ci: bump the github-actions group with 2 updates (#23958)
Bumps the github-actions group with 2 updates: [azure/setup-helm](https://github.com/azure/setup-helm) and [chromaui/action](https://github.com/chromaui/action). Updates `azure/setup-helm` from 4.3.1 to 5.0.0 <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/azure/setup-helm/releases">azure/setup-helm's releases</a>.</em></p> <blockquote> <h2>v5.0.0</h2> <h3>Changed</h3> <ul> <li><a href="https://redirect.github.com/azure/setup-helm/issues/259">#259</a> <a href="https://redirect.github.com/Azure/setup-helm/pull/259">Update Node.js runtime from node20 to node24</a></li> <li><a href="https://redirect.github.com/azure/setup-helm/issues/263">#263</a> <a href="https://redirect.github.com/Azure/setup-helm/pull/263">Bump undici</a></li> <li><a href="https://redirect.github.com/azure/setup-helm/issues/257">#257</a> <a href="https://redirect.github.com/Azure/setup-helm/pull/257">Bump undici and <code>@actions/http-client</code></a></li> <li><a href="https://redirect.github.com/azure/setup-helm/issues/256">#256</a> <a href="https://redirect.github.com/Azure/setup-helm/pull/256">Bump minimatch</a></li> <li><a href="https://redirect.github.com/azure/setup-helm/issues/248">#248</a> <a href="https://redirect.github.com/Azure/setup-helm/pull/248">Bump the actions group with 2 updates</a></li> <li><a href="https://redirect.github.com/azure/setup-helm/issues/247">#247</a> <a href="https://redirect.github.com/Azure/setup-helm/pull/247">Bump the actions group with 3 updates</a></li> <li><a href="https://redirect.github.com/azure/setup-helm/issues/246">#246</a> <a href="https://redirect.github.com/Azure/setup-helm/pull/246">Bump <code>@types/node</code> from 25.0.2 to 25.0.3 in the actions group</a></li> <li><a href="https://redirect.github.com/azure/setup-helm/issues/245">#245</a> <a href="https://redirect.github.com/Azure/setup-helm/pull/245">Bump the actions group with 3 updates</a></li> <li><a href="https://redirect.github.com/azure/setup-helm/issues/243">#243</a> <a href="https://redirect.github.com/Azure/setup-helm/pull/243">Bump the actions group with 2 updates</a></li> <li><a href="https://redirect.github.com/azure/setup-helm/issues/240">#240</a> <a href="https://redirect.github.com/Azure/setup-helm/pull/240">Bump prettier from 3.6.2 to 3.7.3 in the actions group</a></li> <li><a href="https://redirect.github.com/azure/setup-helm/issues/229">#229</a> <a href="https://redirect.github.com/Azure/setup-helm/pull/229">Bump the actions group across 1 directory with 3 updates</a></li> <li><a href="https://redirect.github.com/azure/setup-helm/issues/231">#231</a> <a href="https://redirect.github.com/Azure/setup-helm/pull/231">Bump js-yaml from 3.14.1 to 3.14.2</a></li> <li><a href="https://redirect.github.com/azure/setup-helm/issues/234">#234</a> <a href="https://redirect.github.com/Azure/setup-helm/pull/234">Bump glob from 10.4.5 to 10.5.0</a></li> <li><a href="https://redirect.github.com/azure/setup-helm/issues/225">#225</a> <a href="https://redirect.github.com/Azure/setup-helm/pull/225">Fix build error</a></li> <li><a href="https://redirect.github.com/azure/setup-helm/issues/222">#222</a> <a href="https://redirect.github.com/Azure/setup-helm/pull/222">Bump <code>@types/node</code> from 24.7.2 to 24.8.1 in the actions group</a></li> <li><a href="https://redirect.github.com/azure/setup-helm/issues/220">#220</a> <a href="https://redirect.github.com/Azure/setup-helm/pull/220">Bump the actions group across 1 directory with 4 updates</a></li> <li><a href="https://redirect.github.com/azure/setup-helm/issues/216">#216</a> <a href="https://redirect.github.com/Azure/setup-helm/pull/216">Bump the actions group across 1 directory with 4 updates</a></li> <li><a href="https://redirect.github.com/azure/setup-helm/issues/213">#213</a> <a href="https://redirect.github.com/Azure/setup-helm/pull/213">Bump the actions group with 2 updates</a></li> <li><a href="https://redirect.github.com/azure/setup-helm/issues/211">#211</a> <a href="https://redirect.github.com/Azure/setup-helm/pull/211">Bump undici</a></li> <li><a href="https://redirect.github.com/azure/setup-helm/issues/212">#212</a> <a href="https://redirect.github.com/Azure/setup-helm/pull/212">Bump jest from 30.0.5 to 30.1.2 in the actions group</a></li> <li><a href="https://redirect.github.com/azure/setup-helm/issues/210">#210</a> <a href="https://redirect.github.com/Azure/setup-helm/pull/210">Bump <code>@types/node</code> from 24.2.1 to 24.3.0 in the actions group</a></li> </ul> </blockquote> </details> <details> <summary>Changelog</summary> <p><em>Sourced from <a href="https://github.com/Azure/setup-helm/blob/main/CHANGELOG.md">azure/setup-helm's changelog</a>.</em></p> <blockquote> <h1>Change Log</h1> <h2>[5.0.0] - 2026-03-23</h2> <h3>Changed</h3> <ul> <li><a href="https://redirect.github.com/azure/setup-helm/issues/259">#259</a> <a href="https://redirect.github.com/Azure/setup-helm/pull/259">Update Node.js runtime from node20 to node24</a></li> <li><a href="https://redirect.github.com/azure/setup-helm/issues/263">#263</a> <a href="https://redirect.github.com/Azure/setup-helm/pull/263">Bump undici</a></li> <li><a href="https://redirect.github.com/azure/setup-helm/issues/257">#257</a> <a href="https://redirect.github.com/Azure/setup-helm/pull/257">Bump undici and <code>@actions/http-client</code></a></li> <li><a href="https://redirect.github.com/azure/setup-helm/issues/256">#256</a> <a href="https://redirect.github.com/Azure/setup-helm/pull/256">Bump minimatch</a></li> <li><a href="https://redirect.github.com/azure/setup-helm/issues/248">#248</a> <a href="https://redirect.github.com/Azure/setup-helm/pull/248">Bump the actions group with 2 updates</a></li> <li><a href="https://redirect.github.com/azure/setup-helm/issues/247">#247</a> <a href="https://redirect.github.com/Azure/setup-helm/pull/247">Bump the actions group with 3 updates</a></li> <li><a href="https://redirect.github.com/azure/setup-helm/issues/246">#246</a> <a href="https://redirect.github.com/Azure/setup-helm/pull/246">Bump <code>@types/node</code> from 25.0.2 to 25.0.3 in the actions group</a></li> <li><a href="https://redirect.github.com/azure/setup-helm/issues/245">#245</a> <a href="https://redirect.github.com/Azure/setup-helm/pull/245">Bump the actions group with 3 updates</a></li> <li><a href="https://redirect.github.com/azure/setup-helm/issues/243">#243</a> <a href="https://redirect.github.com/Azure/setup-helm/pull/243">Bump the actions group with 2 updates</a></li> <li><a href="https://redirect.github.com/azure/setup-helm/issues/240">#240</a> <a href="https://redirect.github.com/Azure/setup-helm/pull/240">Bump prettier from 3.6.2 to 3.7.3 in the actions group</a></li> <li><a href="https://redirect.github.com/azure/setup-helm/issues/229">#229</a> <a href="https://redirect.github.com/Azure/setup-helm/pull/229">Bump the actions group across 1 directory with 3 updates</a></li> <li><a href="https://redirect.github.com/azure/setup-helm/issues/231">#231</a> <a href="https://redirect.github.com/Azure/setup-helm/pull/231">Bump js-yaml from 3.14.1 to 3.14.2</a></li> <li><a href="https://redirect.github.com/azure/setup-helm/issues/234">#234</a> <a href="https://redirect.github.com/Azure/setup-helm/pull/234">Bump glob from 10.4.5 to 10.5.0</a></li> <li><a href="https://redirect.github.com/azure/setup-helm/issues/225">#225</a> <a href="https://redirect.github.com/Azure/setup-helm/pull/225">Fix build error</a></li> <li><a href="https://redirect.github.com/azure/setup-helm/issues/222">#222</a> <a href="https://redirect.github.com/Azure/setup-helm/pull/222">Bump <code>@types/node</code> from 24.7.2 to 24.8.1 in the actions group</a></li> <li><a href="https://redirect.github.com/azure/setup-helm/issues/220">#220</a> <a href="https://redirect.github.com/Azure/setup-helm/pull/220">Bump the actions group across 1 directory with 4 updates</a></li> <li><a href="https://redirect.github.com/azure/setup-helm/issues/216">#216</a> <a href="https://redirect.github.com/Azure/setup-helm/pull/216">Bump the actions group across 1 directory with 4 updates</a></li> <li><a href="https://redirect.github.com/azure/setup-helm/issues/213">#213</a> <a href="https://redirect.github.com/Azure/setup-helm/pull/213">Bump the actions group with 2 updates</a></li> <li><a href="https://redirect.github.com/azure/setup-helm/issues/211">#211</a> <a href="https://redirect.github.com/Azure/setup-helm/pull/211">Bump undici</a></li> <li><a href="https://redirect.github.com/azure/setup-helm/issues/212">#212</a> <a href="https://redirect.github.com/Azure/setup-helm/pull/212">Bump jest from 30.0.5 to 30.1.2 in the actions group</a></li> <li><a href="https://redirect.github.com/azure/setup-helm/issues/210">#210</a> <a href="https://redirect.github.com/Azure/setup-helm/pull/210">Bump <code>@types/node</code> from 24.2.1 to 24.3.0 in the actions group</a></li> </ul> <h2>[4.3.1] - 2025-08-12</h2> <h3>Changed</h3> <ul> <li><a href="https://redirect.github.com/azure/setup-helm/issues/167">#167</a> <a href="https://redirect.github.com/Azure/setup-helm/pull/167">Pinning Action Dependencies for Security and Reliability</a></li> <li><a href="https://redirect.github.com/azure/setup-helm/issues/181">#181</a> <a href="https://redirect.github.com/Azure/setup-helm/pull/181">Fix types, and update node version.</a></li> <li><a href="https://redirect.github.com/azure/setup-helm/issues/191">#191</a> <a href="https://redirect.github.com/Azure/setup-helm/pull/191">chore(tests): Mock arch to make tests pass on arm host</a></li> <li><a href="https://redirect.github.com/azure/setup-helm/issues/192">#192</a> <a href="https://redirect.github.com/Azure/setup-helm/pull/192">chore: remove unnecessary prebuild script</a></li> <li><a href="https://redirect.github.com/azure/setup-helm/issues/203">#203</a> <a href="https://redirect.github.com/Azure/setup-helm/pull/203">Update helm version retrieval to use JSON output for latest version</a></li> <li><a href="https://redirect.github.com/azure/setup-helm/issues/207">#207</a> <a href="https://redirect.github.com/Azure/setup-helm/pull/207">ci(workflows): update helm version to v3.18.4 and add matrix for tests</a></li> </ul> <h3>Added</h3> <ul> <li><a href="https://redirect.github.com/azure/setup-helm/issues/197">#197</a> <a href="https://redirect.github.com/Azure/setup-helm/pull/197">Add pre-commit hook</a></li> </ul> <h2>[4.3.0] - 2025-02-15</h2> <ul> <li><a href="https://redirect.github.com/azure/setup-helm/issues/152">#152</a> feat: log when restoring from cache</li> <li><a href="https://redirect.github.com/azure/setup-helm/issues/157">#157</a> Dependencies Update</li> <li><a href="https://redirect.github.com/azure/setup-helm/issues/137">#137</a> Add dependabot</li> </ul> <h2>[4.2.0] - 2024-04-15</h2> <!-- raw HTML omitted --> </blockquote> <p>... (truncated)</p> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/Azure/setup-helm/commit/dda3372f752e03dde6b3237bc9431cdc2f7a02a2"><code>dda3372</code></a> build</li> <li><a href="https://github.com/Azure/setup-helm/commit/3894c84c36e1df49b57e75c2c2c70dc6cf18c2bb"><code>3894c84</code></a> chore(release): v5.0.0 (<a href="https://redirect.github.com/azure/setup-helm/issues/265">#265</a>)</li> <li><a href="https://github.com/Azure/setup-helm/commit/ca66f3880d072ee3ace311d70cd267faa2ce7c73"><code>ca66f38</code></a> Update Node.js runtime from node20 to node24 (<a href="https://redirect.github.com/azure/setup-helm/issues/259">#259</a>)</li> <li><a href="https://github.com/Azure/setup-helm/commit/316ed5ab42b09c96cccd063ecc054a7c0f1dc207"><code>316ed5a</code></a> Bump undici (<a href="https://redirect.github.com/azure/setup-helm/issues/263">#263</a>)</li> <li><a href="https://github.com/Azure/setup-helm/commit/bc9bc0ca28599851490e89b2629b3e181c4d1209"><code>bc9bc0c</code></a> Bump undici and <code>@actions/http-client</code> (<a href="https://redirect.github.com/azure/setup-helm/issues/257">#257</a>)</li> <li><a href="https://github.com/Azure/setup-helm/commit/16e3094bcbb6e98d8a39a05e244dd020c0a68a74"><code>16e3094</code></a> Bump minimatch (<a href="https://redirect.github.com/azure/setup-helm/issues/256">#256</a>)</li> <li><a href="https://github.com/Azure/setup-helm/commit/6e427537330e9c850849a06695599f9d298c46cc"><code>6e42753</code></a> Bump actions/stale in /.github/workflows in the actions group (<a href="https://redirect.github.com/azure/setup-helm/issues/255">#255</a>)</li> <li><a href="https://github.com/Azure/setup-helm/commit/9651d9df522c20a9f1fef182b439689e91e24103"><code>9651d9d</code></a> Bump actions/checkout in /.github/workflows in the actions group (<a href="https://redirect.github.com/azure/setup-helm/issues/251">#251</a>)</li> <li><a href="https://github.com/Azure/setup-helm/commit/658bff9449986fae55b983dd9dbb242943fb9513"><code>658bff9</code></a> Bump the actions group with 2 updates (<a href="https://redirect.github.com/azure/setup-helm/issues/248">#248</a>)</li> <li><a href="https://github.com/Azure/setup-helm/commit/331c81409ca70b46d873b7b6655b7ed3e9d7c2b6"><code>331c814</code></a> Bump the actions group with 3 updates (<a href="https://redirect.github.com/azure/setup-helm/issues/247">#247</a>)</li> <li>Additional commits viewable in <a href="https://github.com/azure/setup-helm/compare/1a275c3b69536ee54be43f2070a358922e12c8d4...dda3372f752e03dde6b3237bc9431cdc2f7a02a2">compare view</a></li> </ul> </details> <br /> Updates `chromaui/action` from 13.3.5 to 16.0.0 <details> <summary>Changelog</summary> <p><em>Sourced from <a href="https://github.com/chromaui/action/blob/main/CHANGELOG.md">chromaui/action's changelog</a>.</em></p> <blockquote> <h1>v16.0.0 (Mon Mar 23 2026)</h1> <h4>💥 Breaking Change</h4> <ul> <li>Drop support for Node 18 and update GitHub Action to Node 24 <a href="https://redirect.github.com/chromaui/chromatic-cli/pull/1251">#1251</a> (<a href="https://github.com/codykaup"><code>@codykaup</code></a>)</li> </ul> <h4>Authors: 1</h4> <ul> <li>Cody Kaup (<a href="https://github.com/codykaup"><code>@codykaup</code></a>)</li> </ul> <hr /> <h1>v15.3.1 (Mon Mar 23 2026)</h1> <h4>🐛 Bug Fix</h4> <ul> <li>Properly timeout process tree in shell commands <a href="https://redirect.github.com/chromaui/chromatic-cli/pull/1254">#1254</a> (<a href="https://github.com/codykaup"><code>@codykaup</code></a>)</li> </ul> <h4>Authors: 1</h4> <ul> <li>Cody Kaup (<a href="https://github.com/codykaup"><code>@codykaup</code></a>)</li> </ul> <hr /> <h1>v15.3.0 (Mon Mar 16 2026)</h1> <h4>🚀 Enhancement</h4> <ul> <li>Integrate manifest generation script <a href="https://redirect.github.com/chromaui/chromatic-cli/pull/1244">#1244</a> (<a href="https://github.com/codykaup"><code>@codykaup</code></a>)</li> </ul> <h4>Authors: 1</h4> <ul> <li>Cody Kaup (<a href="https://github.com/codykaup"><code>@codykaup</code></a>)</li> </ul> <hr /> <h1>v15.2.0 (Mon Feb 23 2026)</h1> <h4>🚀 Enhancement</h4> <ul> <li>❇️ Add input parameter chromaticSha. <a href="https://redirect.github.com/chromaui/chromatic-cli/pull/1241">#1241</a> (<a href="https://github.com/jwir3"><code>@jwir3</code></a>)</li> </ul> <h4>Authors: 1</h4> <ul> <li>Scott Johnson (<a href="https://github.com/jwir3"><code>@jwir3</code></a>)</li> </ul> <hr /> <h1>v15.1.1 (Tue Feb 17 2026)</h1> <!-- raw HTML omitted --> </blockquote> <p>... (truncated)</p> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/chromaui/action/commit/f191a0224b10e1a38b2091cefb7b7a2337009116"><code>f191a02</code></a> v16.0.0</li> <li><a href="https://github.com/chromaui/action/commit/eea1606238fd97a70b5af723d103953d1f40967b"><code>eea1606</code></a> v15.3.1</li> <li><a href="https://github.com/chromaui/action/commit/0794e6939fe40ce46a88963f818092afc427da5b"><code>0794e69</code></a> v15.3.0</li> <li><a href="https://github.com/chromaui/action/commit/5ec258af08deb3e8c36653bd618cb7fe52090031"><code>5ec258a</code></a> v15.2.0</li> <li><a href="https://github.com/chromaui/action/commit/93712e37669f856c4828136f9cb535dbfa60b50c"><code>93712e3</code></a> v15.1.1</li> <li><a href="https://github.com/chromaui/action/commit/a8ce9c58f59be5cc7090cadfc8f130fb08fcf0c3"><code>a8ce9c5</code></a> v15.1.0</li> <li><a href="https://github.com/chromaui/action/commit/f1f9e3277eb1eaa8cba4c6bcebc9809291ee29ea"><code>f1f9e32</code></a> v15.0.0</li> <li><a href="https://github.com/chromaui/action/commit/9f1ad414f2e282aeff674364a9098b328382103f"><code>9f1ad41</code></a> v14.0.0</li> <li>See full diff in <a href="https://github.com/chromaui/action/compare/07791f8243f4cb2698bf4d00426baf4b2d1cb7e0...f191a0224b10e1a38b2091cefb7b7a2337009116">compare view</a></li> </ul> </details> <br /> Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) --- <details> <summary>Dependabot commands and options</summary> <br /> You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore <dependency name> major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore <dependency name> minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore <dependency name>` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore <dependency name>` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore <dependency name> <ignore condition>` will remove the ignore condition of the specified dependency and ignore conditions </details> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> |
||
|
|
cd784c755a |
fix(agent): exorcise data race haunting contextConfigAPI on reconnect (#23946)
Fixes: coder/internal#1441 - Move `contextConfigAPI` init from `handleManifest` to `init()`, matching all other API fields - Change `agentcontextconfig.NewAPI` to accept `func() string` closure (lazy directory evaluation) - `Config()` and HTTP handler now compute on demand via `a.manifest.Load().Directory` - Widen `TestAgent_Reconnect` to loop 5 reconnections with a non-empty manifest directory - Add `TestContextConfigAPI_InitOnce` internal test verifying lazy eval across manifest changes - Add `TestNewAPI_LazyDirectory` unit test for the lazy contract > 🤖 Written by a Coder Agent. Reviewed by a human. |
||
|
|
eb4860aac3 |
chore: bump the coder-modules group across 2 directories with 2 updates (#23955)
Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) --- <details> <summary>Dependabot commands and options</summary> <br /> You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore <dependency name> major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore <dependency name> minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore <dependency name>` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore <dependency name>` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore <dependency name> <ignore condition>` will remove the ignore condition of the specified dependency and ignore conditions </details> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> |
||
|
|
07fbe8ca7d |
chore: bump ubuntu from ce4a593 to 5e5b128 in /dogfood/coder (#23954)
Bumps ubuntu from `ce4a593` to `5e5b128`. [](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) --- <details> <summary>Dependabot commands and options</summary> <br /> You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) </details> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> |
||
|
|
ba0a64d483 |
chore: move to using radix-ui over @radix-ui/react-* (#23911)
This pull-request moves using to using the plain `radix-ui` package over `@radix-ui/react-*` packages. Put simply, now we're not going to run into issues with inconsistent radix dependencies. This will have no effect to how the code is built, but will give us a single place to import from. |
||
|
|
7757cd8e08 |
refactor(coderd/x/chatd): insert chats directly as pending on creation (#23888)
Previously, `CreateChat` inserted the `chats` row with the DB default status (`waiting`), then updated it to `pending` in the same transaction via `setChatPendingWithStore`. This wasted two extra queries per chat creation (`GetChatByID` + `UpdateChatStatus`) and rewrote the same row immediately after inserting it. Now `CreateChat` passes the status directly to `InsertChat`, so the row is written once in its final create-time state. The `setChatPendingWithStore` helper is removed entirely. `InsertChat` now requires an explicit `status` parameter at all callsites instead of relying on a DB column default. ## Motivation On an experimental branch we're trialing firing all chatd notifications from plpgsql triggers. The old two-step insert made that awkward: in an `AFTER INSERT` trigger, `NEW` only contained the insert-time row (`waiting`), not the final committed state (`pending`). To emit the correct event payload the trigger had to be deferred and re-read the row from `chats` at commit time. With this change, `NEW` already contains the correct row to publish — no deferred trigger, no extra `SELECT`, simpler and cheaper trigger logic. That said, this seems like a worthwhile change regardless of the trigger experiment: writing the final row state once removes unnecessary DB work on every chat creation and makes the create path easier to reason about. |
||
|
|
fc1e0beb3b |
fix(coderd/x/chatd): use structured output for chat title generation (#23909)
Chat title generation used free-form text completion, which let models respond conversationally instead of producing a title. Review chats started with GitHub URLs were especially affected — models would say "I don't have the ability to browse external links" and that string became the persisted title. Replace the raw-text `generateShortText` path with structured output via `object.Generate[generatedTitle]`. Both auto-title and manual retitle now go through the same typed contract: the model must return a JSON object with a `title` field, validated and normalized before persistence. Invalid outputs (empty, too long) are rejected and retried through the existing candidate-model fallback loop. |
||
|
|
3a4a0b7270 |
fix: rename "Add member" to "Add" on template permissions page (#23943)
The "Add member" button on the template permissions page is used to add both **users and groups**, so the label is misleading when adding a group. <img width="1238" height="672" alt="image" src="https://github.com/user-attachments/assets/dbdfc79e-9e2e-4f26-9258-418f2038511e" /> |
||
|
|
11c1afb5e9 |
chore: add support for tailnet updates to Tunneler FSM (#23875)
<!-- If you have used AI to produce some or all of this PR, please ensure you have read our [AI Contribution guidelines](https://coder.com/docs/about/contributing/AI_CONTRIBUTING) before submitting. --> relates to GRU-18 Adds support for tailnet updates to Tunneler FSM. |
||
|
|
be2e641162 |
feat: add release candidate (RC) support to release tooling (#23600)
This adds full RC release support to the release scripts and GitHub Actions workflow. Previously, the tooling only supported stable and mainline releases with strict vMAJOR.MINOR.PATCH semver tags. Changes: - scripts/releaser/version.go: Add Pre field to version struct for prerelease suffixes (e.g. "rc.0"), update regex, parsing, String(), comparison methods, and add IsRC()/rcNumber() helpers. - scripts/releaser/release.go: Detect RC branches (release/X.Y-rc.N), suggest RC version numbers, auto-set "rc" channel (skipping stable/mainline prompt), add RC advisory to release notes, skip docs update for RC releases. - .github/workflows/release.yaml: Add "rc" channel option, fix branch derivation for RC tags (v2.32.0-rc.0 -> release/2.32-rc.0 instead of broken release/2.32.0-rc), skip homebrew/winget/package publishing for RC releases. - scripts/release/publish.sh: Add --rc flag, pass --prerelease to gh release create for RC releases. - scripts/releaser/version_test.go: Add comprehensive unit tests for version parsing, string formatting, IsRC, rcNumber, GreaterThan, and Equal with RC versions. <!-- If you have used AI to produce some or all of this PR, please ensure you have read our [AI Contribution guidelines](https://coder.com/docs/about/contributing/AI_CONTRIBUTING) before submitting. --> |
||
|
|
83e2699914 |
chore: add support for app updates to Tunneler FSM (#23874)
<!-- If you have used AI to produce some or all of this PR, please ensure you have read our [AI Contribution guidelines](https://coder.com/docs/about/contributing/AI_CONTRIBUTING) before submitting. --> relates to GRU-18 Adds support for network application (e.g. SSH) updates to Tunneler. |
||
|
|
515ba209fd | ci: fix weekly-docs check failing on pnpm cache save (#23937) | ||
|
|
d15bfc2cb0 |
fix(install.sh): filter pre-release tags from mainline version resolution (#23939)
The `echo_latest_mainline_version()` function fetches all GitHub releases and sorts by version number to find the latest mainline release. It did not filter out pre-release tags (e.g. `v2.32.0-rc.0`), so publishing an RC release caused `coder.com/install.sh` to resolve the RC as the latest mainline version instead of the actual mainline release. Adds a `grep` filter for strict semver (`MAJOR.MINOR.PATCH`) before sorting, so tags with pre-release suffixes like `-rc.0` are excluded from version resolution. |
||
|
|
308053b0e4 |
fix: stop workspace before starting with new parameters (#23541)
This is required to prevent the agent from becoming unhealthy. Since we are stopping the workspace now, also add a confirmation dialog. Also add stories to test the new behavior and make a tweak to the permissions query in support of that. |
||
|
|
7c29355e84 |
fix: specify allowed hosts for storybook dev server (#23938)
We recently upgraded storybook and vite in #23485 which bumped our `storybook` version from 10.2.10 to 10.3.3. In 10.2.16, storybookjs/storybook#34045 was merged that changes the list of default allowed hosts to an empty array. This means if you have custom DNS set up (like through the Coder desktop app) your `.coder` domain will no longer be able to reach storybook and you'll get an `Invalid host` response. This is a breaking change, but storybook didn't treat it as such. This PR adds the `core.allowedHosts` config to our storybook dev server. I'm not sure this has the same effect for build so I left the other `viteFinal` `server.allowedHosts` config, but it may be defunct |
||
|
|
7c048d8eb4 |
fix(site): fix "Thinking..." indicator disappearing prematurely (#23933)
The "Thinking..." indicator flickered or failed to appear when the user
sent a message.
## Problem
The server sends `status:pending` before `status:running` when
processing a new message. `selectIsAwaitingFirstStreamChunk` only
accepted `"running"`, so during the pending window the indicator was
hidden. When the optimistic `setChatStatus("running")` from `handleSend`
was overridden by the WS `status:pending` event, the indicator would
flash and disappear.
Secondarily, `StreamingOutput` hid the indicator as soon as
`streamState` became non-null, even when no text/reasoning blocks
existed yet (e.g. only tool-call parts or whitespace-only deltas had
arrived).
## Fix
1. **`chatStore.ts`** — `selectIsAwaitingFirstStreamChunk` now also
accepts `chatStatus === "pending"` when the latest durable message is a
user message (fresh send). Tool-call cycles (where latest =
assistant/tool) remain unaffected.
2. **`StreamingOutput.tsx`** — During streaming, the component keeps
showing "Thinking..." until a text or reasoning block appears, bridging
the visual gap between the startup placeholder and the first visible
content.
3. **`streamState.ts`** — Changed the early-return guard for
text/reasoning parts from `!part.text` to `!part.text?.trim()` so
whitespace-only deltas don't create a non-null `StreamState` with empty
blocks.
<details><summary>Decision log</summary>
- Including `"pending"` in `isAwaitingFirstStreamChunk` was previously
rejected because it caused the 15-second "startup taking longer" warning
during tool-call cycles. The `latestMessage?.role === "user"` guard now
prevents that — during tool cycles the latest durable message is
assistant/tool, not user.
- The `StreamingOutput` streaming-thinking check uses a synthetic
`"starting"` status for `ChatStatusCallout` rather than adding a new
phase to `LiveStatusModel`, keeping the status model clean.
- The whitespace trim fix in `streamState.ts` is defense-in-depth — the
`StreamingOutput` fix handles the rendering gap, but preventing
empty-block `StreamState` creation is the correct behavior at the
source.
</details>
v2.33.0-rc.0
|
||
|
|
e81275a91c |
feat: cleanup <Tabs /> component (#23839)
This refactors `<Tabs />` into two clearer patterns: link tabs for route navigation and Radix tabs for stateful tab panels. That gives us proper accessibility semantics where we need them without overloading simple navigation tabs. As part of that split, this updates several consumers, adds coverage for both variants, and cleans up some nearby styling. - introduce Radix-backed tabs primitives for tabbed content - move router-based tabs to `LinkTabs` - update notifications, IdP sync, and workspace build pages to use semantic tabs - preserve route navigation tabs for groups and templates - add stories/tests for both tab implementations - simplify related layout and styling in touched components |
||
|
|
4a363b0d85 |
fix: resolve <Alert /> button poor visibility (#22597)
Closes #22244 This pull-request makes our `<Alert />`'s more inline with the Figma style-system, we're looking to ensure that these are vertically rendered now and not horizontal WCAG nightmares. --------- Co-authored-by: Danielle Maywood <danielle@themaywoods.com> |
||
|
|
7dc81bdef1 |
fix(site): fix sticky user message clipping and fade-in behavior (#23928)
The sticky user message in the chat timeline had two visual issues: 1. **Dead space during scroll** — the clipping calculation subtracted 48px prematurely (`fullHeight - scrolledPast - 48`), causing the message to shrink before its content had actually left the viewport. Removed the offset so clipping begins exactly when content scrolls out of view. 2. **Blur/gradient popping in abruptly** — the `--fade-opacity` variable was a binary 0/1 toggle. Now it ramps 0→1 over the last 40px before `MIN_HEIGHT`, so the blur and bottom gradient only appear when the message is fully compressed. Also added a longer (~25 line) user message to the `WithMessageHistory` story to make the sticky behavior easier to test visually. |
||
|
|
ee855f9618 |
feat: make agent context paths configurable via env vars (#23878)
Replace hardcoded paths for instruction files, skills, and MCP config
with
values read from `CODER_AGENT_EXP_*` environment variables. Template
authors
configure paths via the existing `coder_agent` `env` block. The agent
resolves `~`, relative, and absolute paths locally, then serves the
resolved config over `GET /api/v0/context-config`. `chatd` fetches this
once per workspace attach and falls back to today's defaults for older
agents.
All path env vars are comma-separated, allowing multiple directories:
| Env Var | Default | Controls |
|---|---|---|
| `CODER_AGENT_EXP_INSTRUCTIONS_DIRS` | `~/.coder` | Dirs containing the
instruction file |
| `CODER_AGENT_EXP_INSTRUCTIONS_FILE` | `AGENTS.md` | Instruction file
name |
| `CODER_AGENT_EXP_SKILLS_DIRS` | `.agents/skills` | Skills directories
|
| `CODER_AGENT_EXP_SKILL_META_FILE` | `SKILL.md` | Skill metadata file
name |
| `CODER_AGENT_EXP_MCP_CONFIG_FILES` | `.mcp.json` | MCP config files |
### Example
```hcl
resource "coder_agent" "main" {
os = "linux"
arch = "amd64"
env = {
CODER_AGENT_EXP_INSTRUCTIONS_DIRS = "/opt/company/agent-config,~/.coder"
CODER_AGENT_EXP_INSTRUCTIONS_FILE = "CLAUDE.md"
CODER_AGENT_EXP_SKILLS_DIRS = "/opt/company/ai-skills,.agents/skills"
CODER_AGENT_EXP_MCP_CONFIG_FILES = "/opt/company/mcp.json,.mcp.json"
}
}
```
<details>
<summary>Implementation Details</summary>
### Architecture
Follows the same pattern as MCP tool discovery:
agent resolves locally → exposes via HTTP → chatd consumes.
**Agent-side** (`agent/agentcontextconfig/`):
- `ResolvePath` / `ResolvePaths` handle `~`, relative, and absolute path
forms; returns `""` for relative paths when baseDir is empty
- `Config` reads env vars, falls back to defaults, resolves all paths
- `GET /api/v0/context-config` serves the resolved config as JSON
**chatd-side** (`coderd/x/chatd/`):
- Calls `conn.ContextConfig()` once on first workspace attach
- Falls back to hardcoded defaults on 404 (older agents)
- Iterates instruction dirs, skills dirs using resolved absolute paths
- `LSRelativityRoot` everywhere — no more home/root juggling
### Key design decisions
- **`EXP_` prefix**: env vars use `CODER_AGENT_EXP_*` to indicate
experimental status
- **Plural names**: comma-separated vars use plural names (`DIRS`,
`FILES`); single-value vars use singular (`FILE`)
- **Defaults in `workspacesdk`**: default constants live in
`codersdk/workspacesdk/` so both agent and server reference them without
cross-layer imports
- **`skillMetaFile` persistence**: stored on context-file parts via
`ContextFileSkillMetaFile` and restored on subsequent chat turns so
custom values survive across turns
- **Working dir dedup**: `slices.Contains` guard prevents reading the
same instruction file from both `InstructionsDirs` and the working
directory
- **MCP server dedup**: first-occurrence-wins dedup prevents leaking
duplicate connections from overlapping config files
- **ResolvePath safety**: returns `""` for relative paths when `baseDir`
is empty, so `ResolvePaths` filters them out
### Files changed
| File | Change |
|---|---|
| `agent/agentcontextconfig/` | New package — path resolution + HTTP
endpoint |
| `codersdk/workspacesdk/agentconn.go` | `ContextConfigResponse` type,
default constants, client method |
| `agent/agent.go` + `agent/api.go` | Wire up endpoint, pass config to
MCP |
| `agent/x/agentmcp/manager.go` | Accept `[]string` MCP config paths,
dedup by name |
| `coderd/x/chatd/chatd.go` | Fetch config, thread through, named
returns |
| `coderd/x/chatd/instruction.go` | Accept configurable dir + file name,
`skillMetaFileFromParts` |
| `coderd/x/chatd/chattool/skill.go` | Accept configurable dirs + meta
file |
| `codersdk/chats.go` | `ContextFileSkillMetaFile` field for persistence
|
### Test coverage
- `TestConfig` (4 cases): defaults, custom env vars, whitespace
trimming, comma-separated dirs
- `TestResolvePath` / `TestResolvePaths`: including empty baseDir edge
case
- `TestPersistInstructionFilesFallbackOnOlderAgent`: backward-compat
path when `ContextConfig` returns 404
- `TestChatMessagePartVariantTags`: updated exclusion list for new
internal field
### Backward compatibility
Older agents return 404 for the new endpoint. `chatd` catches this and
falls back to today's defaults via `readHomeInstructionFile` (using
`LSRelativityHome`). Existing workspaces work with no changes.
</details>
|
||
|
|
b1c42bb630 |
fix(site/src/pages/AgentsPage): use chat ID as terminal reconnection token (#23926)
The terminal panel in the agents sidebar generated a fresh
`reconnectionToken` via `crypto.randomUUID()` on every mount. Navigating
between chats or reloading the page orphaned the PTY session.
- Use the chat ID (`agentId`) as the reconnection token for
`TerminalPanel`
- Add optional `chatId` prop to `TerminalPanel`, falling back to a
random UUID when not provided
- Thread `agentId` from `AgentChatPageView` to `TerminalPanel`
This mirrors how the dedicated Terminal page persists sessions via a
URL-stored token.
> 🤖 Written by a Coder Agent. Reviewed by a human.
|
||
|
|
c048a4093e | fix(site/src/pages/AgentsPage): persist file-reference chips across chat navigation (#23854) | ||
|
|
1cc23a3144 |
fix(cli): allow multiple depends-on args in coder exp sync want (#23869)
Previously the command required exactly two arguments, forcing users to run it multiple times to declare multiple dependencies for a single unit. This accepts variadic depends-on arguments so all dependencies can be declared in one call: ``` coder exp sync want my-unit dep-1 dep-2 dep-3 ``` --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Co-authored-by: Marcin Tojek <mtojek@users.noreply.github.com> |
||
|
|
dee5ec51c0 | fix(site): prevent WebSocket events from cancelling sidebar pagination fetches (#23845) | ||
|
|
e3c59c00cd | fix(site): clear stream state atomically with durable message commit (#23924) | ||
|
|
ba734f8b10 |
fix(site/src/pages/AgentsPage): fix copy button toolbar regression and add missing story coverage (#23912)
Move !isSavingMessage to the outer toolbar guard so the gradient container does not mount empty during save. Remove the now-redundant inner guard. Add flex to the assistant copy button wrapper div. The plain block wrapper with an inline-flex button created a line box whose height depended on the inherited non-integer line-height (14px * 1.625 = 22.75px strut). Sub-pixel rounding during hover repaints caused a 1px jitter. Making it a flex container eliminates the strut. Add behavioral assertions to UserMessageCopyButton: click edit and assert onEditUserMessage fires, click copy and assert writeText is called with the raw markdown. Add MultiAssistantTurnCopyButton regression story for the isLastAssistantMessage fix. Refs #23850 |
||
|
|
28062862a0 | chore(site): upgrade to Vite 8 (#23485) | ||
|
|
129e3509a3 |
fix(site): address post-merge review comments on kyleosophy chimes (#23896)
Fixes issues found in post-merge review of #23891 and #23892. - **P2:** Export `_resetForTesting()` from `chime.ts` to break cross-test cache dependency; call in `beforeEach` - **P2:** Add `KylesophyToggle` and `TogglesKyleosophy` Storybook stories - **P3:** Fix JSDoc on `maybePlayChime` — terminal states are `waiting|pending`, not `waiting|error` - **P3:** Rename `setKylesophyLocal` back to `setLocalKyleosophy` to match `setLocal*` convention - Preserve original `location` property descriptor in `isKylesophyForced` tests to avoid leaking mutated descriptors across test suites (#23892 review) > 🤖 Written by a Coder Agent. Reviewed by a human. |
||
|
|
53a1b6d67e | ci: fix Linear release tracking and move complete step to release workflow (#23771) | ||
|
|
8c8b307b97 | fix: persist session cookie to disk to prevent PWA logout (#23746) | ||
|
|
12f87acad6 |
feat(site): add terminal panel to chat sidebar (#23231)
## Add terminal panel to chat sidebar Extract the reusable terminal runtime from `TerminalPage` into `modules/terminal/` and wire it into the agents chat right sidebar as a new **Terminal** tab. ### Changes - **`modules/terminal/WorkspaceTerminal.tsx`** — Shared xterm + websocket terminal component (container-sized, no route dependency) - **`modules/terminal/WorkspaceTerminalAlerts.tsx`** — Moved from `TerminalPage/` to shared module - **`pages/AgentsPage/TerminalPanel.tsx`** — Sidebar wrapper around `WorkspaceTerminal` - **`pages/AgentsPage/AgentDetailView.tsx`** — Terminal tab added (gated on `hasWorkspace`) - **`pages/TerminalPage/TerminalPage.tsx`** — Slimmed to page-shell using shared component ### Demo [dogfood-terminal-demo.webm](https://github.com/user-attachments/assets/359200dc-f8e4-4a9a-b00b-923f142dc228) ### Behavior - Terminal tab appears only when the chat has a workspace with a connected agent - Connects via the existing workspace agent PTY websocket - Resizes correctly on panel width changes, expand/collapse, and viewport resize - `fitAddon.fit()` guarded against pre-renderer crashes (fixes proxy access) - Tab switching unmounts/remounts cleanly (reconnects via session token) - No changes to Git or Desktop panel behavior --- _Generated with [`mux`](https://github.com/coder/mux) • Model: `anthropic:claude-opus-4-6` • Thinking: `xhigh`_ |
||
|
|
7198f9040d |
fix: rename user-facing 'chats' to 'Coder Agents' (#23905)
Refs #23897 - Rename user-facing "chats" to "Coder Agents" (feature name) or "conversations" (individual instances) - Covers UI strings, docs prose, Storybook stories, and aria labels - API paths, internal code identifiers, and the "Chats API" docs page name are intentionally left unchanged - TaskPage / AI Tasks are out of scope > 🤖 Written by a Coder Agent. Will be reviewed by a human. |
||
|
|
ddafdbcbce |
fix(site): use imperative setValue for chat message editing instead of key-based remount (#23799)
Sometimes clicking **Edit** on a chat message does not populate the
composer with the message text, and the edit flow had a few timing bugs
around Lexical hydration. The composer was relying on
`key={initialValue}` on `LexicalComposer`, so re-editing the same text
could produce no state change, no remount, and an empty editor.
This PR keeps the editor mounted and switches edit flows to an
imperative `setValue()` API on `ChatMessageInputRef`. It also hardens
that API so draft reads and writes stay correct across initial
hydration: canceling edit no longer refocuses on mobile, pre-edit draft
snapshots preserve persisted drafts, early `setValue()` calls buffer
until the editor is ready, and `getValue()` falls back before readiness
but reads live editor state after attach.
|
||
|
|
196dc51edf |
feat(site/src/pages/AgentsPage): add copy message button to chat messages (#23850)
Add a hover-reveal copy button to both user and assistant messages in the agents chat. Copies raw markdown to the clipboard, preserving formatting for pasting into markdown-aware editors. The button uses the existing useClipboard hook and matches the visual pattern established by the edit button on user messages (opacity-0 with group-hover reveal and focus-visible support). For assistant messages, the button sits below the response content. For user messages, it sits inline alongside the edit button. Messages with no copyable text content (e.g. tool-only messages) do not show the button. |
||
|
|
2a51687ff3 |
fix: stop amputating RC suffixes from docs URLs (#23903)
Fixes #23897 (docs link only — naming rename is in #23905) - Fix version stripping logic in both Go (`codersdk/deployment.go`) and TypeScript (`site/src/utils/docs.ts`) to preserve `-rc.X` suffixes instead of amputating them along with `-devel` - Add `v0.0.0` fallback in the TS frontend to match Go backend behavior for dev builds - Add tests covering RC, devel, and plain release version strings > 🤖 Written by a Coder Agent. Will be reviewed by a human. |
||
|
|
19e44f4136 |
fix: target specific chat in MarkStale instead of broadcasting to all workspace chats (#23883)
## Problem Subagent chats were receiving git context (branch, remote origin, PR status) from their parent or sibling chats' git operations. When a git operation triggers external auth, the workspace agent sends `chat_id` identifying which chat initiated it — but this was broken at two levels: 1. **Agent side:** `CODER_CHAT_ID` was never injected into process environments. `chatd` sets `Coder-Chat-Id` HTTP headers and the agent extracts them for process isolation, but never propagated `CODER_CHAT_ID` to `cmd.Env`. So `gitaskpass` always sent an empty `chat_id`. 2. **Server side:** `workspaceAgentsExternalAuth` ignored the `chat_id` query param. `MarkStale` broadcast git context to **all** chats on the workspace via `filterChatsByWorkspaceID`. ## Fix - Inject `CODER_CHAT_ID` into `cmd.Env` in `agentproc` when the chat ID is known, so `gitaskpass` can read and forward it. - Read `chat_id` from query params in `workspaceAgentsExternalAuth` and thread it through `chatGitRef`. - Refactor `MarkStale` to accept a `MarkStaleParams` struct. When `ChatID` is provided, target only that specific chat. When empty (legacy agents, non-chat git operations), fall back to the existing workspace-wide broadcast. - Extract `markStaleSingle` helper to deduplicate the upsert+publish logic. <details><summary>Investigation notes</summary> ### Data flow before fix ``` chatd → sets Coder-Chat-Id header on agent conn agent → extracts chatID, stores on process struct agent → does NOT set CODER_CHAT_ID in cmd.Env ← gap 1 gitaskpass → reads CODER_CHAT_ID (always empty), sends chat_id="" server handler → ignores chat_id query param ← gap 2 MarkStale → broadcasts to ALL workspace chats ``` ### Data flow after fix ``` chatd → sets Coder-Chat-Id header on agent conn agent → extracts chatID, stores on process struct agent → sets CODER_CHAT_ID in cmd.Env gitaskpass → reads CODER_CHAT_ID, sends chat_id=<uuid> server handler → reads chat_id, passes to MarkStale MarkStale → targets only that specific chat ``` </details> |
||
|
|
2ea89e1f1b |
fix(site/src/pages/AgentsPage): show Thinking indicator immediately after sending a message (#23904)
After sending a message, `handleSend` clears stream state and inserts the user message but did not set `chatStatus` to `"running"`. Combined with #23805 narrowing `selectIsAwaitingFirstStreamChunk` to only match `chatStatus === "running"` (instead of `isActiveChatStatus` which included `"pending"`), the "Thinking..." indicator could not appear until the WebSocket delivered `status:running` — a 50–500ms+ gap. Optimistically set `chatStatus` to `"running"` in both the send and edit paths after the POST returns (non-queued). The WebSocket `status:running` event no-ops via the `setChatStatus` guard; error/pending events override the optimistic value. <details><summary>Investigation & decision log</summary> ### Root cause chain 1. **PR #23805** (`953c3bdc0`) changed `selectIsAwaitingFirstStreamChunk` from `isActiveChatStatus(state.chatStatus)` → `state.chatStatus === "running"`. Valid fix: during `"pending"`, `shouldApplyMessagePart()` drops stream parts, so `streamState` stays null and the 15s "startup taking too long" warning fired spuriously during multi-turn tool-call cycles. 2. **PR #23884** (`4b5265695`) fixed event ordering within a WebSocket batch so both `[message_part, status:running]` and `[status:running, message_part]` orderings show "Thinking...". Correct fix, but only operates **after** `chatStatus` reaches `"running"`. 3. `handleSend` never set `chatStatus` optimistically — it relied entirely on the WebSocket `status:running` event. After #23805 narrowed the selector, the gap between POST completion and WebSocket event became visible. ### Why this fix is safe - Non-queued POST = server accepted the message → `"running"` is the correct next state. - `setChatStatus("running")` guard: `if (state.chatStatus === status) return` makes the subsequent WebSocket confirmation a no-op. - If the server transitions to error/pending instead, the WebSocket event overrides the optimistic value. - `shouldApplyMessagePart()` returns `true` for `"running"`, so early stream parts arriving before the WebSocket `status:running` will not be silently dropped. ### What was NOT regressed by PR #23884 PR #23884's `setTimeout(0)` deferred flush is correct. Both event orderings now produce a render cycle where `chatStatus === "running"` and `streamState === null`, allowing "Thinking..." to appear. The `setTimeout(0)` fires in a separate macrotask, giving the browser a paint opportunity. </details> |
||
|
|
faa5db0cf0 | refactor(site/src/pages/AgentsPage): replace ScrollAnchoredContainer with useStickToBottom (#23846) | ||
|
|
3758b02595 |
fix: resolve <WorkspacePage /> colors (#23902)
This pull-request ensures that our borders and content are all inline with the design-system, whilst also ripping out the old Material UI based design system. Furthermore, we're enforcing the background gradient to always be showing regardless of if `<ResourceMetadata />` has content. | Old | New | | --- | --- | | <img width="1624" height="1061" alt="image" src="https://github.com/user-attachments/assets/0accc324-b012-43e4-bb13-ec3629fbc909" /> | <img width="1624" height="1061" alt="image" src="https://github.com/user-attachments/assets/e89c752a-057c-4256-9f8e-728d1f89a1fd" /> | |
||
|
|
7861fcf1f6 |
perf(coderd): stop inline-resolving diff status on every GetChat call (#23901)
## Problem
Every `GET /api/experimental/chats/{chatID}` call was blocking for
200-800ms because the `getChat` handler called `resolveChatDiffStatus`,
which unconditionally hit the git provider API (e.g. GitHub's `GET
/repos/{owner}/{repo}/pulls?head=...`) via `ResolveBranchPullRequest` —
even when the cached diff status was fresh.
This made every chat page load at `/agents/{id}` noticeably slow.
## Root cause
The call chain was:
1. `getChat` → `resolveChatDiffStatus`
2. `resolveChatDiffStatus` → `resolveChatDiffReference` →
`gp.ResolveBranchPullRequest(...)` **(external HTTP call)**
3. Only **after** the external call: `chatDiffStatusIsStale(status,
now)` check
The staleness check happened after the expensive work, so every request
paid the cost regardless of cache freshness.
## Fix
`getChat` now returns the cached `chat_diff_statuses` row directly from
the database. The background `gitsync` worker already keeps these rows
fresh (every `DiffStatusTTL = 120s`), so inline resolution was
redundant.
The `resolveChatDiffContents` endpoint (which fetches actual diff
content) still uses the full resolution path since it needs to make
provider API calls by design.
## Changes
- `getChat` reads cached diff status from DB instead of calling
`resolveChatDiffStatus`
- Remove `resolveChatDiffStatus` (dead code — no production callers)
- Remove `chatDiffStatusIsStale` and `chatDiffStatusTTL` (dead code)
- Remove `RefreshesStaleStatusWithExternalAuth` test (tested the removed
inline refresh path)
<details><summary>Decision log</summary>
- **Why not just add a staleness gate?** The background worker already
handles refreshes on the same schedule. Adding an early-return-if-fresh
would work but leaves dead code for the stale path that's never
exercised in production (the worker gets there first). Removing the
inline path entirely is simpler and eliminates the external API
dependency from the read path.
- **Why keep `resolveChatDiffContents` unchanged?** That endpoint's job
is to fetch the actual diff content from the provider, so external API
calls are inherent to its purpose.
</details>
|
||
|
|
4b52656958 |
fix(site): ensure Thinking indicator appears regardless of WebSocket event ordering (#23884)
The "Thinking..." indicator intermittently failed to render after submitting a message. The behavior depended on the order of events within a single WebSocket frame. ## Root Cause `flushMessageParts()` was called before **all** non-`message_part` events in the batch loop. When the server sent `[message_part, status:"running"]` in the same SSE chunk: 1. `message_part` → pushed to `partsBuf` 2. `status:"running"` → `flushMessageParts()` applied parts **first** → `streamState` became non-null → then `chatStatus` set to `"running"` 3. Subscriber saw `streamState != null && chatStatus == "running"` → `selectIsAwaitingFirstStreamChunk` returned `false` → no "Thinking..." When events arrived in the reverse order (`[status:"running", message_part]`), the indicator worked because the status was set before parts were applied. ## Fix - Move `flushMessageParts()` to only fire before `message` and `error` events (which need prior parts visible) - Add `discardBufferedParts()` for events that clear stream state (`status:"pending"/"waiting"`, `retry`) so the deferred `setTimeout(0)` flush doesn't re-populate cleared state - Status changes are now always applied before parts within a batch, and the deferred flush gives React one render cycle to show "Thinking..." | Event | Flush? | Rationale | |---|---|---| | `message` | YES | Durable commit must include all stream parts | | `error` | YES | Partial output should be visible alongside error | | `status` | NO | Status must be set before parts so "starting" phase renders | | `retry` | DISCARD | Retry clears stream state; flushing would re-populate it | | `queue_update` | NO | Doesn't interact with stream state | ## Tests (written first, failing before fix) 1. **"shows starting phase when message_part arrives before status:running in same batch"** — the exact bug scenario 2. **"shows starting phase when status:running arrives before message_part in same batch"** — verifies the "good" order still works 3. **"discards buffered parts when status transitions to pending"** — verifies parts don't leak through pending transitions All tests are deterministic (fake timers, no race conditions). <details><summary>Implementation plan & decision log</summary> ### Why not reorder events within the batch? Reordering would change the semantic ordering of events from the server, which could have subtle side effects. The simpler approach is to be selective about when parts are flushed. ### Why discard (not flush) before pending/waiting/retry? These events clear `streamState`. If parts were flushed before the clear, they'd be visible for one frame then disappear. If the deferred flush ran after the clear, it would re-populate the state. Discarding is the only correct behavior. ### Why keep flush before error? Errors should surface partial output so the user can see what the agent was doing when it failed. </details> |
||
|
|
f5b98aa12d | fix: stabilize flaky visual stories (#23893) |