mirror of
https://github.com/coder/coder.git
synced 2026-09-21 20:51:01 +08:00
e044a4265d2e96b24816f54abd81dc2a7a130623
14976
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
e044a4265d |
fix(coderd): only send prebuild claim reinit for the claim build (#26548)
## Problem #23108 made prebuild claim delivery durable: when an agent connects to `/api/v2/workspaceagents/me/reinit?wait=true`, the handler checks whether the workspace's first build was created by the prebuilds system user and whether its latest build succeeded, and if so pre-seeds a `prebuild_claimed` reinitialization event in case the original pubsub event was missed. The check does not verify that the latest build is the claim build, so it keeps firing for the rest of the workspace's life. Any workspace that was claimed from a prebuild receives a spurious "prebuild claimed" reinit every time its agent (re)opens the `/reinit` connection: after every agent restart, every coderd deploy or replica restart, and every dropped SSE connection. Each one shuts the agent down and reinitializes it, killing SSH/IDE sessions and re-running startup scripts. In our deployment, where most workspaces are claimed from prebuilds, this caused fleet-wide "agent disconnected" blips whenever a coderd replica restarted, and a few workspaces whose container exits when the agent restarts went into a restart loop every 15-60 minutes. The agent-side dedup (`lastOwnerID` in `cli/agent.go`) only suppresses the second event within one agent process, so every new agent process takes at least one spurious restart. ## Fix Only seed the reinitialization event while the latest build is the claim build itself, determined from the build job's input (`prebuilt_workspace_stage`), the same signal `provisionerdserver` uses when publishing the claim event: - Latest build is the claim build: behavior unchanged (seed when the job succeeded, 409 when it failed permanently, wait on pubsub while it is in progress). - Latest build is still a prebuilds-initiated build (claim build not created yet): fall through to the pubsub subscription, which delivers the claim event when the claim build completes. - Latest build is any later user-initiated build: the claim was already handled, so return 409 and the agent stops polling, the same as a regular workspace. `dbfake` gains a `MarkPrebuiltWorkspaceClaim()` builder option so tests can model claim builds' job input, and the existing `TestReinit` claim subtests now use it. A new subtest covers the long-claimed workspace case. One deliberate behavior change worth calling out: if a claim build fails and the owner retries with another start build, the handler now returns 409 for that retry build rather than seeding a reinit. This matches the existing treatment of failed claim builds as terminal for the reinit poller. ## Verification - `go test ./coderd/ -run TestReinit` against Postgres 17: all subtests pass, including the new `workspace claimed in the past gets 409` case. - `gofmt`, `go vet`, and `golangci-lint` (v1.64.8) are clean on the touched packages. - The fix mirrors behavior validated by hand against an affected deployment: for a long-claimed workspace, `/reinit?wait=true` returned the seeded `prebuild_claimed` event on every connection before the change and a 409 afterwards. Note: this branch was prepared in an environment without the full local toolchain, so the repo's pre-commit hook (`make pre-commit`) was not run locally; relying on CI for the full gen/fmt/lint suite. Opening as a draft mainly to report the issue and propose a fix; happy to rework it to the maintainers' preferred approach. --------- Co-authored-by: Sas Swart <sas.swart.cdk@gmail.com> |
||
|
|
eb4bea6e94 |
chore: bump github.com/coreos/go-oidc/v3 from 3.18.0 to 3.19.0 (#26608)
Bumps [github.com/coreos/go-oidc/v3](https://github.com/coreos/go-oidc) from 3.18.0 to 3.19.0. <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/coreos/go-oidc/releases">github.com/coreos/go-oidc/v3's releases</a>.</em></p> <blockquote> <h2>v3.19.0</h2> <h2>What's Changed</h2> <ul> <li>fix: Key refresh should set <code>no-cache</code> to get most up to date keys by <a href="https://github.com/Yanni8"><code>@Yanni8</code></a> in <a href="https://redirect.github.com/coreos/go-oidc/pull/485">coreos/go-oidc#485</a></li> <li>oidc: add support for validating back-channel logout tokens by <a href="https://github.com/ericchiang"><code>@ericchiang</code></a> in <a href="https://redirect.github.com/coreos/go-oidc/pull/486">coreos/go-oidc#486</a></li> </ul> <h2>New Contributors</h2> <ul> <li><a href="https://github.com/Yanni8"><code>@Yanni8</code></a> made their first contribution in <a href="https://redirect.github.com/coreos/go-oidc/pull/485">coreos/go-oidc#485</a></li> </ul> <p><strong>Full Changelog</strong>: <a href="https://github.com/coreos/go-oidc/compare/v3.18.0...v3.19.0">https://github.com/coreos/go-oidc/compare/v3.18.0...v3.19.0</a></p> </blockquote> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/coreos/go-oidc/commit/4204f0b2b0f903070de5f51a459fe5e23faca113"><code>4204f0b</code></a> oidc: add support for validating back-channel logout tokens</li> <li><a href="https://github.com/coreos/go-oidc/commit/f77e01c50994c6ad4f4c3a6ed3e2380bab1f1ff2"><code>f77e01c</code></a> fix: Key refresh should set no-cache to get most up to date keys</li> <li>See full diff in <a href="https://github.com/coreos/go-oidc/compare/v3.18.0...v3.19.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> |
||
|
|
e2333ebd29 |
chore: bump github.com/prometheus/common from 0.68.1 to 0.69.0 (#26607)
Bumps [github.com/prometheus/common](https://github.com/prometheus/common) from 0.68.1 to 0.69.0. <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/prometheus/common/releases">github.com/prometheus/common's releases</a>.</em></p> <blockquote> <h2>v0.69.0</h2> <h2>What's Changed</h2> <ul> <li>config: strip credentials on cross-host redirects by <a href="https://github.com/roidelapluie"><code>@roidelapluie</code></a> in <a href="https://redirect.github.com/prometheus/common/pull/901">prometheus/common#901</a></li> <li>Modernize Go by <a href="https://github.com/SuperQ"><code>@SuperQ</code></a> in <a href="https://redirect.github.com/prometheus/common/pull/919">prometheus/common#919</a></li> <li>config: make isCrossHostRedirect sticky across the redirect chain by <a href="https://github.com/roidelapluie"><code>@roidelapluie</code></a> in <a href="https://redirect.github.com/prometheus/common/pull/920">prometheus/common#920</a></li> <li>config: check cross-host redirect before OAuth2 token fetch by <a href="https://github.com/roidelapluie"><code>@roidelapluie</code></a> in <a href="https://redirect.github.com/prometheus/common/pull/921">prometheus/common#921</a></li> <li>expfmt: fix nil pointer panic when parsing empty braces "{}" by <a href="https://github.com/roidelapluie"><code>@roidelapluie</code></a> in <a href="https://redirect.github.com/prometheus/common/pull/922">prometheus/common#922</a></li> <li>model: reduce allocations in Time.UnmarshalJSON by <a href="https://github.com/bboreham"><code>@bboreham</code></a> in <a href="https://redirect.github.com/prometheus/common/pull/918">prometheus/common#918</a></li> <li>config: resolve LoadHTTPConfigFile paths relative to the config file by <a href="https://github.com/roidelapluie"><code>@roidelapluie</code></a> in <a href="https://redirect.github.com/prometheus/common/pull/925">prometheus/common#925</a></li> </ul> <p><strong>Full Changelog</strong>: <a href="https://github.com/prometheus/common/compare/v0.68.1...v0.69.0">https://github.com/prometheus/common/compare/v0.68.1...v0.69.0</a></p> </blockquote> </details> <details> <summary>Changelog</summary> <p><em>Sourced from <a href="https://github.com/prometheus/common/blob/main/CHANGELOG.md">github.com/prometheus/common's changelog</a>.</em></p> <blockquote> <h2>v0.69.0 / 2026-06-17</h2> <h3>Security / behavior changes</h3> <ul> <li><strong>config: credentials are no longer forwarded across cross-host redirects.</strong> When <code>FollowRedirects</code> is enabled, the HTTP client now strips <code>Authorization</code>, <code>Cookie</code>, <code>Proxy-Authorization</code> and other sensitive headers, and skips basic-auth, bearer-token and OAuth2 credentials, when a redirect points to a different host. This aligns with Go's <code>net/http</code> behavior. Callers that relied on credentials being sent to a redirect target on another host will need to target that host directly. <a href="https://redirect.github.com/prometheus/common/issues/901">#901</a> <a href="https://redirect.github.com/prometheus/common/issues/920">#920</a> <a href="https://redirect.github.com/prometheus/common/issues/921">#921</a></li> <li>config: <code>LoadHTTPConfigFile</code> now resolves relative file paths (e.g. <code>*_file</code> credentials, <code>http_headers</code> files) against the config file's own directory instead of its parent directory. Configs that worked around the old behavior by prefixing paths with the config's directory name must drop that prefix. <a href="https://redirect.github.com/prometheus/common/issues/925">#925</a></li> </ul> <h3>Bugfixes</h3> <ul> <li>expfmt: fix nil pointer panic when parsing empty braces <code>{}</code>. <a href="https://redirect.github.com/prometheus/common/issues/922">#922</a></li> <li>model: fix <code>Time.UnmarshalJSON</code> for larger negative numbers. <a href="https://redirect.github.com/prometheus/common/issues/918">#918</a></li> </ul> <h3>Performance</h3> <ul> <li>model: reduce allocations in <code>Time.UnmarshalJSON</code>. <a href="https://redirect.github.com/prometheus/common/issues/918">#918</a></li> </ul> <h3>Internal</h3> <ul> <li>Synchronize common files from prometheus/prometheus. <a href="https://redirect.github.com/prometheus/common/issues/917">#917</a></li> <li>Modernize Go. <a href="https://redirect.github.com/prometheus/common/issues/919">#919</a></li> </ul> <p><strong>Full Changelog</strong>: <a href="https://github.com/prometheus/common/compare/v0.68.1...v0.69.0">https://github.com/prometheus/common/compare/v0.68.1...v0.69.0</a></p> <h2>v0.67.2 / 2025-10-28</h2> <h2>What's Changed</h2> <ul> <li>config: Fix panic in <code>tlsRoundTripper</code> when CA file is absent by <a href="https://github.com/ndk"><code>@ndk</code></a> in <a href="https://redirect.github.com/prometheus/common/pull/792">prometheus/common#792</a></li> <li>Cleanup linting issues by <a href="https://github.com/SuperQ"><code>@SuperQ</code></a> in <a href="https://redirect.github.com/prometheus/common/pull/860">prometheus/common#860</a></li> </ul> <h2>New Contributors</h2> <ul> <li><a href="https://github.com/ndk"><code>@ndk</code></a> made their first contribution in <a href="https://redirect.github.com/prometheus/common/pull/792">prometheus/common#792</a></li> </ul> <p><strong>Full Changelog</strong>: <a href="https://github.com/prometheus/common/compare/v0.67.1...v0.67.2">https://github.com/prometheus/common/compare/v0.67.1...v0.67.2</a></p> <h2>v0.67.1 / 2025-10-07</h2> <h2>What's Changed</h2> <ul> <li>Remove VERSION file to avoid Go conflict error in <a href="https://redirect.github.com/prometheus/common/pull/853">prometheus/common#853</a></li> </ul> <p><strong>Full Changelog</strong>: <a href="https://github.com/prometheus/common/compare/v0.67.0...v0.67.1">https://github.com/prometheus/common/compare/v0.67.0...v0.67.1</a></p> <h2>v0.67.0 / 2025-10-07</h2> <h2>What's Changed</h2> <ul> <li>Create CHANGELOG.md for easier communication of library changes, especially possible breaking changes. by <a href="https://github.com/ywwg"><code>@ywwg</code></a> in <a href="https://redirect.github.com/prometheus/common/pull/833">prometheus/common#833</a></li> <li>model: New test for validation with dots by <a href="https://github.com/m1k1o"><code>@m1k1o</code></a> in <a href="https://redirect.github.com/prometheus/common/pull/759">prometheus/common#759</a></li> <li>expfmt: document NewTextParser as required by <a href="https://github.com/burgerdev"><code>@burgerdev</code></a> in <a href="https://redirect.github.com/prometheus/common/pull/842">prometheus/common#842</a></li> <li>expfmt: Add support for float histograms and gauge histograms by <a href="https://github.com/beorn7"><code>@beorn7</code></a> in <a href="https://redirect.github.com/prometheus/common/pull/843">prometheus/common#843</a></li> <li>Updated minimum Go version to 1.24.0, updated Go dependecies by <a href="https://github.com/SuperQ"><code>@SuperQ</code></a> in <a href="https://redirect.github.com/prometheus/common/pull/849">prometheus/common#849</a></li> </ul> <!-- raw HTML omitted --> </blockquote> <p>... (truncated)</p> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/prometheus/common/commit/e3c14a039d494d866242b36ac253dfecf9c7210b"><code>e3c14a0</code></a> Merge pull request <a href="https://redirect.github.com/prometheus/common/issues/925">#925</a> from roidelapluie/roidelapluie/fix-loadhttpconfigfile...</li> <li><a href="https://github.com/prometheus/common/commit/a7b791d0a0cd8e7be164d7f3fdb33450c1868b1c"><code>a7b791d</code></a> config: resolve LoadHTTPConfigFile paths relative to the config file</li> <li><a href="https://github.com/prometheus/common/commit/f84efec4e4deb31a8afd39c4f4f7ba2b30f39df3"><code>f84efec</code></a> Merge pull request <a href="https://redirect.github.com/prometheus/common/issues/918">#918</a> from prometheus/time-split</li> <li><a href="https://github.com/prometheus/common/commit/2269d3d1af9a40c9324bb523087f7704fabe7f1d"><code>2269d3d</code></a> Merge pull request <a href="https://redirect.github.com/prometheus/common/issues/922">#922</a> from roidelapluie/roidelapluie/fix-textparse-empty-br...</li> <li><a href="https://github.com/prometheus/common/commit/a1600af967b7eaa77360339b402b447855c24915"><code>a1600af</code></a> expfmt: fix nil pointer panic when parsing empty braces "{}"</li> <li><a href="https://github.com/prometheus/common/commit/56fe3954537fa60da94055f19172fafa25347948"><code>56fe395</code></a> Merge pull request <a href="https://redirect.github.com/prometheus/common/issues/921">#921</a> from roidelapluie/roidelapluie/oauth2-cross-host-check</li> <li><a href="https://github.com/prometheus/common/commit/0fcda471410c91d285776092b7d768d8ac199bc9"><code>0fcda47</code></a> Merge pull request <a href="https://redirect.github.com/prometheus/common/issues/920">#920</a> from roidelapluie/roidelapluie/cross-host-sticky</li> <li><a href="https://github.com/prometheus/common/commit/30ba470f4f55107af9dbe7fbe9c95c0617c13f43"><code>30ba470</code></a> Merge pull request <a href="https://redirect.github.com/prometheus/common/issues/919">#919</a> from prometheus/superq/modernize</li> <li><a href="https://github.com/prometheus/common/commit/2b55b3e9e7e899f2cbcbcb7afdcb55c2db6a1754"><code>2b55b3e</code></a> config: check cross-host redirect before OAuth2 token fetch</li> <li><a href="https://github.com/prometheus/common/commit/428856f9a5d0d790dacdf03e789c2ef87b03fc40"><code>428856f</code></a> config: make isCrossHostRedirect sticky across the redirect chain</li> <li>Additional commits viewable in <a href="https://github.com/prometheus/common/compare/v0.68.1...v0.69.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> |
||
|
|
8cf394d145 |
chore: bump google.golang.org/api from 0.284.0 to 0.286.0 (#26606)
Bumps [google.golang.org/api](https://github.com/googleapis/google-api-go-client) from 0.284.0 to 0.286.0. <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/googleapis/google-api-go-client/releases">google.golang.org/api's releases</a>.</em></p> <blockquote> <h2>v0.286.0</h2> <h2><a href="https://github.com/googleapis/google-api-go-client/compare/v0.285.0...v0.286.0">0.286.0</a> (2026-06-22)</h2> <h3>Features</h3> <ul> <li><strong>all:</strong> Auto-regenerate discovery clients (<a href="https://redirect.github.com/googleapis/google-api-go-client/issues/3629">#3629</a>) (<a href="https://github.com/googleapis/google-api-go-client/commit/f25a08b7bd916e0719cc9e0d003454a8aaa8caf9">f25a08b</a>)</li> <li><strong>all:</strong> Auto-regenerate discovery clients (<a href="https://redirect.github.com/googleapis/google-api-go-client/issues/3631">#3631</a>) (<a href="https://github.com/googleapis/google-api-go-client/commit/b3bb97ff046401ce738b4e6830642b2e6c712536">b3bb97f</a>)</li> <li><strong>all:</strong> Auto-regenerate discovery clients (<a href="https://redirect.github.com/googleapis/google-api-go-client/issues/3632">#3632</a>) (<a href="https://github.com/googleapis/google-api-go-client/commit/7332dd74f142bba59a27778f115eac98cc254bfb">7332dd7</a>)</li> <li><strong>all:</strong> Auto-regenerate discovery clients (<a href="https://redirect.github.com/googleapis/google-api-go-client/issues/3634">#3634</a>) (<a href="https://github.com/googleapis/google-api-go-client/commit/36081a00df42df1ca3e3228067737839aa905c9e">36081a0</a>)</li> </ul> <h2>v0.285.0</h2> <h2><a href="https://github.com/googleapis/google-api-go-client/compare/v0.284.0...v0.285.0">0.285.0</a> (2026-06-16)</h2> <h3>Features</h3> <ul> <li><strong>all:</strong> Auto-regenerate discovery clients (<a href="https://redirect.github.com/googleapis/google-api-go-client/issues/3618">#3618</a>) (<a href="https://github.com/googleapis/google-api-go-client/commit/5c008a7963c278aff6be6c839cbf20bd0b8ae231">5c008a7</a>)</li> <li><strong>all:</strong> Auto-regenerate discovery clients (<a href="https://redirect.github.com/googleapis/google-api-go-client/issues/3620">#3620</a>) (<a href="https://github.com/googleapis/google-api-go-client/commit/21a12ed9dc47cb8d9b9aa4e1f5759ac2044063a5">21a12ed</a>)</li> <li><strong>all:</strong> Auto-regenerate discovery clients (<a href="https://redirect.github.com/googleapis/google-api-go-client/issues/3622">#3622</a>) (<a href="https://github.com/googleapis/google-api-go-client/commit/17394ca1afffb6d740e134a0bc148d79106c4c80">17394ca</a>)</li> <li><strong>all:</strong> Auto-regenerate discovery clients (<a href="https://redirect.github.com/googleapis/google-api-go-client/issues/3623">#3623</a>) (<a href="https://github.com/googleapis/google-api-go-client/commit/087611c9a9b2c0e68f429641a012a43396afb4ce">087611c</a>)</li> <li><strong>all:</strong> Auto-regenerate discovery clients (<a href="https://redirect.github.com/googleapis/google-api-go-client/issues/3624">#3624</a>) (<a href="https://github.com/googleapis/google-api-go-client/commit/72b67889b20325f1a09222d62b3184a68ad30ee2">72b6788</a>)</li> <li><strong>all:</strong> Auto-regenerate discovery clients (<a href="https://redirect.github.com/googleapis/google-api-go-client/issues/3626">#3626</a>) (<a href="https://github.com/googleapis/google-api-go-client/commit/4f1d165677d35c4caecd7faf93eec27cb2fd25cd">4f1d165</a>)</li> <li><strong>all:</strong> Auto-regenerate discovery clients (<a href="https://redirect.github.com/googleapis/google-api-go-client/issues/3628">#3628</a>) (<a href="https://github.com/googleapis/google-api-go-client/commit/894cccb170d1ea81f8bf49ddd072a3ef52df3d25">894cccb</a>)</li> </ul> </blockquote> </details> <details> <summary>Changelog</summary> <p><em>Sourced from <a href="https://github.com/googleapis/google-api-go-client/blob/main/CHANGES.md">google.golang.org/api's changelog</a>.</em></p> <blockquote> <h2><a href="https://github.com/googleapis/google-api-go-client/compare/v0.285.0...v0.286.0">0.286.0</a> (2026-06-22)</h2> <h3>Features</h3> <ul> <li><strong>all:</strong> Auto-regenerate discovery clients (<a href="https://redirect.github.com/googleapis/google-api-go-client/issues/3629">#3629</a>) (<a href="https://github.com/googleapis/google-api-go-client/commit/f25a08b7bd916e0719cc9e0d003454a8aaa8caf9">f25a08b</a>)</li> <li><strong>all:</strong> Auto-regenerate discovery clients (<a href="https://redirect.github.com/googleapis/google-api-go-client/issues/3631">#3631</a>) (<a href="https://github.com/googleapis/google-api-go-client/commit/b3bb97ff046401ce738b4e6830642b2e6c712536">b3bb97f</a>)</li> <li><strong>all:</strong> Auto-regenerate discovery clients (<a href="https://redirect.github.com/googleapis/google-api-go-client/issues/3632">#3632</a>) (<a href="https://github.com/googleapis/google-api-go-client/commit/7332dd74f142bba59a27778f115eac98cc254bfb">7332dd7</a>)</li> <li><strong>all:</strong> Auto-regenerate discovery clients (<a href="https://redirect.github.com/googleapis/google-api-go-client/issues/3634">#3634</a>) (<a href="https://github.com/googleapis/google-api-go-client/commit/36081a00df42df1ca3e3228067737839aa905c9e">36081a0</a>)</li> </ul> <h2><a href="https://github.com/googleapis/google-api-go-client/compare/v0.284.0...v0.285.0">0.285.0</a> (2026-06-16)</h2> <h3>Features</h3> <ul> <li><strong>all:</strong> Auto-regenerate discovery clients (<a href="https://redirect.github.com/googleapis/google-api-go-client/issues/3618">#3618</a>) (<a href="https://github.com/googleapis/google-api-go-client/commit/5c008a7963c278aff6be6c839cbf20bd0b8ae231">5c008a7</a>)</li> <li><strong>all:</strong> Auto-regenerate discovery clients (<a href="https://redirect.github.com/googleapis/google-api-go-client/issues/3620">#3620</a>) (<a href="https://github.com/googleapis/google-api-go-client/commit/21a12ed9dc47cb8d9b9aa4e1f5759ac2044063a5">21a12ed</a>)</li> <li><strong>all:</strong> Auto-regenerate discovery clients (<a href="https://redirect.github.com/googleapis/google-api-go-client/issues/3622">#3622</a>) (<a href="https://github.com/googleapis/google-api-go-client/commit/17394ca1afffb6d740e134a0bc148d79106c4c80">17394ca</a>)</li> <li><strong>all:</strong> Auto-regenerate discovery clients (<a href="https://redirect.github.com/googleapis/google-api-go-client/issues/3623">#3623</a>) (<a href="https://github.com/googleapis/google-api-go-client/commit/087611c9a9b2c0e68f429641a012a43396afb4ce">087611c</a>)</li> <li><strong>all:</strong> Auto-regenerate discovery clients (<a href="https://redirect.github.com/googleapis/google-api-go-client/issues/3624">#3624</a>) (<a href="https://github.com/googleapis/google-api-go-client/commit/72b67889b20325f1a09222d62b3184a68ad30ee2">72b6788</a>)</li> <li><strong>all:</strong> Auto-regenerate discovery clients (<a href="https://redirect.github.com/googleapis/google-api-go-client/issues/3626">#3626</a>) (<a href="https://github.com/googleapis/google-api-go-client/commit/4f1d165677d35c4caecd7faf93eec27cb2fd25cd">4f1d165</a>)</li> <li><strong>all:</strong> Auto-regenerate discovery clients (<a href="https://redirect.github.com/googleapis/google-api-go-client/issues/3628">#3628</a>) (<a href="https://github.com/googleapis/google-api-go-client/commit/894cccb170d1ea81f8bf49ddd072a3ef52df3d25">894cccb</a>)</li> </ul> </blockquote> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/googleapis/google-api-go-client/commit/94e4ed985051ce54267a5f938e57b8d77963c101"><code>94e4ed9</code></a> chore(main): release 0.286.0 (<a href="https://redirect.github.com/googleapis/google-api-go-client/issues/3630">#3630</a>)</li> <li><a href="https://github.com/googleapis/google-api-go-client/commit/36081a00df42df1ca3e3228067737839aa905c9e"><code>36081a0</code></a> feat(all): auto-regenerate discovery clients (<a href="https://redirect.github.com/googleapis/google-api-go-client/issues/3634">#3634</a>)</li> <li><a href="https://github.com/googleapis/google-api-go-client/commit/7332dd74f142bba59a27778f115eac98cc254bfb"><code>7332dd7</code></a> feat(all): auto-regenerate discovery clients (<a href="https://redirect.github.com/googleapis/google-api-go-client/issues/3632">#3632</a>)</li> <li><a href="https://github.com/googleapis/google-api-go-client/commit/b3bb97ff046401ce738b4e6830642b2e6c712536"><code>b3bb97f</code></a> feat(all): auto-regenerate discovery clients (<a href="https://redirect.github.com/googleapis/google-api-go-client/issues/3631">#3631</a>)</li> <li><a href="https://github.com/googleapis/google-api-go-client/commit/f25a08b7bd916e0719cc9e0d003454a8aaa8caf9"><code>f25a08b</code></a> feat(all): auto-regenerate discovery clients (<a href="https://redirect.github.com/googleapis/google-api-go-client/issues/3629">#3629</a>)</li> <li><a href="https://github.com/googleapis/google-api-go-client/commit/182ae992632d7ba19b5d3c60c71bda28fbfabca1"><code>182ae99</code></a> chore(main): release 0.285.0 (<a href="https://redirect.github.com/googleapis/google-api-go-client/issues/3619">#3619</a>)</li> <li><a href="https://github.com/googleapis/google-api-go-client/commit/894cccb170d1ea81f8bf49ddd072a3ef52df3d25"><code>894cccb</code></a> feat(all): auto-regenerate discovery clients (<a href="https://redirect.github.com/googleapis/google-api-go-client/issues/3628">#3628</a>)</li> <li><a href="https://github.com/googleapis/google-api-go-client/commit/50adedd746e19a1fa5302c5b47dbd6f269bd8c14"><code>50adedd</code></a> chore(all): update all (<a href="https://redirect.github.com/googleapis/google-api-go-client/issues/3625">#3625</a>)</li> <li><a href="https://github.com/googleapis/google-api-go-client/commit/4f1d165677d35c4caecd7faf93eec27cb2fd25cd"><code>4f1d165</code></a> feat(all): auto-regenerate discovery clients (<a href="https://redirect.github.com/googleapis/google-api-go-client/issues/3626">#3626</a>)</li> <li><a href="https://github.com/googleapis/google-api-go-client/commit/72b67889b20325f1a09222d62b3184a68ad30ee2"><code>72b6788</code></a> feat(all): auto-regenerate discovery clients (<a href="https://redirect.github.com/googleapis/google-api-go-client/issues/3624">#3624</a>)</li> <li>Additional commits viewable in <a href="https://github.com/googleapis/google-api-go-client/compare/v0.284.0...v0.286.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> |
||
|
|
970bd73691 |
feat: add /api/v2/ai-gateway API route aliases (#26475)
## Description Registers `/api/v2/ai-gateway/*` as the new API path for AI Gateway, replacing `/api/v2/aibridge/*`. Both prefixes share the same route builder (`aiBridgeRoutes`) backed by a single in-memory handler, so existing `/aibridge` endpoints continue to work. New endpoints must be registered on the enterprise API handler under `/api/v2/ai-gateway` only. Swagger annotations now point to `/api/v2/ai-gateway` paths with a backward-compatibility note referencing `/aibridge`. The legacy `/aibridge` routes are skipped in the swagger documentation test. ## Changes - Store one raw handler (`aiGatewayHandler`) instead of two prefix-stripped handlers - Register `/ai-gateway` and `/ai-gateway/proxy` route aliases alongside legacy `/aibridge` routes - Move `/aibridge/keys` to `/ai-gateway/keys` - Update in-process transport to use `/api/v2/ai-gateway` prefix - Update SDK client URLs and proxy forwarding URL - Swap `@Router` and `@Tags` annotations from `aibridge`/`AI Bridge` to `ai-gateway`/`AI Gateway` - Rename user-facing error messages from "AI Bridge" to "AI Gateway" - Define consts for route prefixes (`AIGatewayRootPath`, `AIBridgeRootPath`) - Update tests and comments to use new paths Note: the following will be addressed in follow-up PRs: - Frontend API URLs - Frontend routes and redirects - Dogfood main.tf updates - Hand-written documentation URL updates - aibridge internal comments and nits - Scale tests path updates Refs https://linear.app/coder/issue/AIGOV-230 > Generated with the assistance of Coder Agents (@ssncferreira) |
||
|
|
4691ef39cd |
feat(site): clarify why secret name is disabled when editing (#26553)
Adds helper text under the disabled `Name` field in the Edit secret
dialog so users understand why it can't be changed:
> Unique identifier (can’t be changed).
Matches the existing pattern used elsewhere (e.g. AI settings). The
secret name is the resource identifier in the API path (`PATCH
/api/v2/users/{user}/secrets/{name}`) and `UpdateUserSecretRequest` has
no `name` field, so rename isn't supported server-side.
Created on behalf of @matifali.
---------
Co-authored-by: blink-so[bot] <211532188+blink-so[bot]@users.noreply.github.com>
|
||
|
|
a1ec9df345 |
test(agent/agentcontext): use resolved temp dirs in symlink tests (#26602)
These symlink resolver tests build expected paths from `t.TempDir()`, but the resolver canonicalizes symlink targets with `filepath.EvalSymlinks`. On macOS, `/var` resolves to `/private/var`, so the raw temp dir path can disagree with the resolver output and flake. Use `testutil.TempDirResolved` in the symlink-sensitive tests so the expectations are canonicalized the same way. Closes https://github.com/coder/internal/issues/1574 Closes ENG-2849 |
||
|
|
e88f2a3485 |
feat(site): add bouncy pop animation to inbox notification badge (#26057)
> 🤖 This PR was written by Coder Agents on behalf of Jake Howell. Replaces the basic `animate-in fade-in zoom-in duration-200` on the inbox unread badge with a bouncier pop using an overshoot easing. The badge now pops in from `scale(0)` with `cubic-bezier(0.34, 1.36, 0.64, 1)` over 500ms, giving it an elastic overshoot that makes it feel alive. Uses `tailwindcss-animate` utilities (`animate-in zoom-in-0 fade-in-0`) with just one arbitrary property for the easing. Conditional rendering is preserved as before. Also adds a `BadgeTransition` story with toggle buttons for easy visual verification. <img width="150" height="150" alt="preview-notification-animation" src="https://github.com/user-attachments/assets/70331cd2-c2e2-4fd7-8f9e-edfe876e2bab" /> |
||
|
|
27ecd17991 |
refactor: consolidate agent MCP onto a single persistent engine (#26599)
Two MCP code paths both spawned the servers declared in a workspace's `.mcp.json`: the persistent engine in `agent/x/agentmcp` (which owns tool-call execution via `CallTool`) and an ephemeral one-shot runner in `agent/agentcontext` (`mcprunner.go`) that connected, listed tools, and immediately closed each server purely for discovery. Every declared server was launched twice, and the discovery path duplicated the engine's `.mcp.json` parse, transport-build, env-resolve, and connect logic. This makes `agent/x/agentmcp` the single persistent MCP engine. The `agentcontext` manager now reads that engine's per-server catalog in-process through an injected `MCPCatalog` option and surfaces each server as a `KindMCPServer` resource. The engine wires `SetOnReload` to the manager's `Trigger`, so a reload (startup connect or `.mcp.json` edit) re-resolves and re-pushes the pinned resources. Tool-call execution is unchanged: it still flows through the engine's `CallTool` over `POST /api/v0/mcp/call-tool`. The now-dead HTTP discovery surface is removed: the agent `GET /api/v0/mcp/tools` route with `agentmcp.API.handleListTools`, and `workspacesdk.AgentConn.ListMCPTools` with `ListMCPToolsResponse` (mock regenerated). The change nets roughly `-1370` lines, mostly the deleted duplicate runner and its tests. <details> <summary>Decision log</summary> The merge of #26585 made pinned `chat_context_resources` the sole source of workspace context, which surfaced the duplicate spawning. Two options were considered: - **Option A + dependency injection (chosen):** keep `agent/x/agentmcp` as the single persistent engine; `agentcontext` consumes its catalog in-process and stays the orchestrator/owner at the API boundary (it still pushes `KindMCPServer` resources). This is low-risk because `agentcontext` already exposed the `resolver.MCPResources` seam, so the change just rebinds it from the ephemeral runner to the shared engine. - **Option B (rejected):** reimplement persistent pooling, reconnect, singleflight, and race handling inside `agentcontext` and delete `agentmcp`. Too broad, and it discards the engine's tested lifecycle for no behavioral gain. `agentcontext`'s discovery was never what kept servers alive; its runner closed each server immediately after listing tools. The component holding persistent connections was always `agentmcp`, which is why execution already lived there. Consolidating onto it removes the duplicated stack rather than a whole package: both packages survive with distinct roles (`agentmcp` is the engine, `agentcontext` is the orchestrator/owner). </details> Coder Agents generated on behalf of @kylecarbs |
||
|
|
0f37522e6f |
refactor(agent/agentcontext): fixed-location shallow context discovery (#26596)
## Problem
`agent/agentcontext` resolved workspace context by walking the working
directory recursively (depth 8) and matching files by basename. This
over-injected context:
- Instruction-file matching was case-insensitive, so the generated
`docs/reference/api/agents.md` was treated as an instruction file.
- Symlinked instruction files (`CLAUDE.md`, `.cursorrules` ->
`AGENTS.md`) shipped as duplicate resources.
- Nested `AGENTS.md` (e.g. `site/AGENTS.md`) were collected from
anywhere in the tree.
- Skills were discovered from *any* `skills/` directory anywhere in the
tree, and `.mcp.json` from any depth.
Resolving the repo root produced six instruction sources for what was
effectively one file of guidance, plus skills/MCP found by an open-ended
walk.
## What changed
Replace the recursive scan with **fixed-location, shallow** discovery.
Each scan root is inspected at its top level only: the resolver never
descends into subdirectories and never climbs to a parent. Additional
directories are added explicitly as sources (HTTP API) or via the
`CODER_AGENT_EXP_*_DIRS` seeding env vars.
- **Single working-dir scan root.** The working directory is one scan
root. Instruction files and `.mcp.json` are read only at its top level.
- **Fixed-location skills.** Skills are discovered only from `skills`,
`.agents/skills`, `.claude/skills`, `.codex/skills` (one skill per
immediate subdir with a `SKILL.md`), not from arbitrary `skills/`
directories.
- **Case-sensitive instruction names.** Exact
`AGENTS.md`/`CLAUDE.md`/`.cursorrules`; a lower-case `agents.md` is
ignored.
- **Symlink dedup.** Resources are attributed to their resolved target,
so symlinked `CLAUDE.md`/`.cursorrules` collapse into the single
`AGENTS.md`.
- **Watcher** mirrors the same fixed-location set instead of recursively
watching every scan root (no more walking `node_modules`).
- The recursive `walkDir`, `skipDirNames`, `MaxScanDepth`, and
`isSkillsContainer` are removed.
Resolving the repo root now yields `AGENTS.md`, `.mcp.json`, and the
`.agents/skills`/`.claude/skills` skills, with no nested
instruction-file noise.
## Behavior change
`site/AGENTS.md` is no longer auto-injected when the working dir is the
repo root. It loads when the working dir **is** `site/` (its top level),
or when `site/` is added as an explicit source. There is intentionally
**no walk-up** to a `.git` project root: an agent started in a
subdirectory does not auto-inherit ancestor `AGENTS.md`; those
directories are added explicitly.
<details>
<summary>Verification & decision log</summary>
**codex research (confirmed via source).** Instruction files: codex
walks up to the first `.git` ancestor and reads root->cwd, one file
per directory, exact-cased names (`codex-rs/core/src/agents_md.rs`).
Skills: fixed roots (`.agents/skills`, `.codex/skills`,
`$CODEX_HOME/skills`, ...) with bounded in-root recursion
(`core-skills/src/loader.rs`). MCP: `.codex/config.toml` via walk-up; a
project `.mcp.json` is not a runtime source in codex. No resource type
triggers an unbounded downward walk.
**Decisions.**
- Adopt codex's fixed-location, shallow discovery (case-sensitive names,
symlink dedup, top-level-only files, container-only skills).
- **Deliberately omit codex's walk-up to the `.git` project root.** In
Coder the working dir is the scan root and extra directories are added
explicitly (HTTP API / `CODER_AGENT_EXP_*_DIRS`), so the implicit
ancestor climb added surprise without benefit (e.g. `context add ./site`
should scan `./site`, not the repo root).
- Keep `.mcp.json` (codex uses `config.toml`, intentionally not added).
- Include `.claude/skills` and `.codex/skills` in the container list so
the repo's existing `.claude/skills` skills are not regressed; skills
recurse one level inside a container.
**Tests.** `TestManager_WorkingDirScannedShallow` (working dir read at
top level; ancestor root and nested subdir both excluded);
`TestResolver_SkillsOnlyFromFixedContainers`,
`TestResolver_MCPConfigOnlyAtScanRoot`,
`TestResolver_SymlinkedInstructionFilesDeduplicated`,
`TestResolver_InstructionFilesOnlyAtScanRoot`,
`TestResolver_InstructionNamesAreCaseSensitive`. Cap tests use multiple
scan roots.
**Local checks.** `gofmt`, `go vet`, `golangci-lint`, `go test -race`,
and `make lint/emdash` pass for the package.
</details>
---
🤖 Generated by Coder Agents on behalf of @kylecarbs.
|
||
|
|
688ee63f9d |
feat(site/src/pages/AgentsPage): group context indicator resources by directory (#26598)
## What
Groups the **Skills** and **Context files** lists in the context-usage
popover (`ContextUsageIndicator`) by their parent directory. Resources
pulled from different roots, for example a repo-root `AGENTS.md` and a
nested `site/AGENTS.md`, or same-named skills from `.coder/skills` vs
`.agents/skills`, previously collapsed to identical basenames and lost
their provenance. Each group now renders a dimmed directory header with
a folder icon, and its items are indented beneath it.
## Why
`ChatContextResource.source` carries the real path for instruction files
and skill directories, but the popover only rendered the basename, so
multiple context roots were indistinguishable.
## Notes
- The directory header shows even for a single root, so provenance is
always visible.
- MCP is intentionally left flat for now: an `mcp_server`'s `source` is
a server name (not a path) and the row carries no reference to the
`mcp_config` that declared it, so it does not fit the directory model
without a backend change.
- Adds a `getPathDirname` helper (with tests) and switches the skill
list `key` from `skill.name` to `skill.source` to avoid collisions
across roots.
## Test plan
- `ContextUsageIndicator.stories.tsx`: new `MultipleContextRoots` story
(files + skills across several directories); `Clean` story updated to
assert the single-root header. Storybook play tests pass (4/4).
- `path.test.ts`: added `getPathDirname` cases (unit pass).
- `biome check`, `tsc -p .`, and `make pre-commit` all pass.
<details>
<summary>Design decision log</summary>
- **Header gating:** started by only showing the directory header when a
section spanned more than one directory; changed to **always show**
because the provenance is useful even for a single root.
- **Presentation:** chose a grouped layout (dimmed directory header +
folder icon, items indented beneath) over an inline dimmed path prefix,
since there is typically a lot of shared structure to convey.
- **Directory labels** currently render the full path (dimmed, truncated
with a `title` tooltip). Open follow-ups: collapse `$HOME` to `~` or
show fewer path segments if the labels feel long.
- **MCP:** evaluated applying the same grouping. An `mcp_server` is
keyed by name and has no link to its `mcp_config` (confirmed in
`codersdk.ChatContextResource` and the `pinnedContextResources`
builder), so grouping servers under a config would require a backend
data change. Left flat for this PR.
</details>
---
🤖 This PR was created by Coder Agents on behalf of @kylecarbs.
|
||
|
|
0b856ef637 |
fix(site/src/pages/AgentsPage/components/DiffViewer): dedupe diff files to prevent CodeView duplicate id crash (#26597)
Viewing a git diff on `/agents` could crash the whole diff view with `CodeView.addItem: duplicate id "agent/x/agentmcp/api_internal_test.go"`. When a diff body lists the same post-image path in more than one `diff --git` section, `parsePatchFiles` returns one `FileDiffMetadata` per section. `DiffViewer` then maps each file to a `CodeView` item keyed by `file.name` (the file tree is likewise keyed by path), so the repeated path produced two items with the same id and `CodeView.addItem` threw, tearing down the entire view. Deduplicate the parsed files by path in `useParsedDiff`, keeping the first occurrence, so both the `CodeView` and the file tree always receive unique ids. `useParsedDiff` is the single source feeding both panels, so a malformed diff now degrades gracefully and logs one warning instead of crashing. <details> <summary>Root cause and verification</summary> Confirmed against `@pierre/diffs` `parsePatchFiles` that a single patch with two `diff --git` sections for one path yields `patchCount: 1`, `fileCount: 2` with both entries named `agent/x/agentmcp/api_internal_test.go`. That is the exact input that made `CodeView.addItem` throw. Dropping (rather than merging) duplicates matches the renderer's model, which can only show one item per id anyway. Verified on the branch: `pnpm test` (DiffViewer suite, including the new `dedupeFilesByName` tests), `tsc -p .`, and the full `pnpm lint` (biome, types, circular-deps, React Compiler, knip) all pass. </details> > Opened by Coder Agents on behalf of @kylecarbs. |
||
|
|
cd56ab9e33 |
refactor: remove legacy live-read and injected-history chat context paths (#26585)
This PR makes the agent-pushed pinned snapshot (`chat_context_resources`) the sole source of workspace context for chats, completing the "Release 5" cleanup. It removes legacy mechanisms now superseded by the snapshot that agents push over dRPC (`PushContextState`) and refresh via `chat-context/refresh`. Removed: - **Live-read at turn time.** MCP tool discovery, skill live-body reads, and the instruction/skill history fallback that dialed the workspace on every turn. - **Context injected as message history.** The `persist_workspace_context` generation action and its decision-loop guard. - **The legacy write path.** `POST`/`DELETE /api/v2/workspaceagents/me/experimental/chat-context`, the agentsdk `AddChatContext`/`ClearChatContext` methods, and the CLI one-shot writer. - **The `chats.last_injected_context` column** and all of its plumbing (migration `000529`, queries, `db2sdk`, `dbauthz`, audit table, and the frontend `ContextUsageIndicator` fallback). Subagent context inheritance no longer copies parent context messages; children now hydrate the parent's pinned `chat_context_resources` on create, which yields an identical pin for the same workspace and agent. What stays (still served by the live agent connection, not the snapshot): `read_skill_file` supporting-file reads, `read_skill` supporting-file listing, and MCP tool execution. > [!NOTE] > Migration `000529` drops `chats.last_injected_context` and recreates the `chats_expanded` view without it. The down migration restores both. <details> <summary>Decision log (D1-D5)</summary> - **D1 (subagent inheritance):** Re-point inheritance from the legacy message copy to a pinned hydrate. Children call `hydrateChatContextOnCreate` instead of copying parent context messages. - **D2 (`persist_workspace_context`):** Remove the generation action entirely along with the decision-loop guard it existed to satisfy, since context is never injected into history anymore. - **D3 (legacy HTTP + CLI):** Remove the experimental `chat-context` POST/DELETE endpoints, the agentsdk methods, and the CLI one-shot. The dRPC push + `chat-context/refresh` replace them. - **D4 (frontend fallback):** Remove the `last_injected_context` fallback in `ContextUsageIndicator`; pinned `resources` are the sole source. - **D5 (sequencing):** Ship as a single PR rather than a stacked pair. </details> --- Coder Agents generated on behalf of @kylecarbs. |
||
|
|
ce190b3e62 |
chore: bump the coder-modules group across 2 directories with 2 updates (#26593)
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> |
||
|
|
fbf31f2b2d |
chore(site): swap AI add-on table icons (em-dash + plain check) (#26467)
Updates the icons in the **AI add-on** column for the admin tables on `/deployment/users` and `/organizations/.../members`. - Not consuming a seat: `XIcon` → muted em-dash (`text-content-disabled`). - Consuming a seat: `CircleCheckIcon` → plain `CheckIcon` from `lucide-react` (no circle, still `text-content-success`). Both tables share `site/src/modules/users/AISeatCell.tsx`, so the single-file change covers `UsersTable.tsx` and `OrganizationMembersTable.tsx`. ## Screenshot Users admin table on a local dogfood build of this branch (`/deployment/users`): <!-- Drag-and-drop the screenshot here to attach it to the PR. --> <details> <summary>Notes</summary> - The em-dash is rendered via the JSX entity `—` rather than a literal `U+2014` character, so it does not trip `make lint/emdash` (see `AGENTS.md` / `scripts/check_emdash.sh`). The browser still renders an em-dash. - Kept the existing `aria-label`s (`Consuming AI seat` / `Not consuming AI seat`) and added `role="img"` on the em-dash span so screen readers still announce the state. - No callers other than `UsersTable.tsx` and `OrganizationMembersTable.tsx` use `AISeatCell` (verified via search). </details> > Opened by Coder Agents on behalf of @tracyjohnsonux. |
||
|
|
ed908ed019 |
fix(docs): repoint 7 broken external and anchor links (DOCS-415) (#26572)
Closes [DOCS-415](https://linear.app/codercom/issue/DOCS-415). ## TL;DR Repoints 7 broken links across 5 docs files that the 2026-06-22 weekly `check-docs.yml` Linkspector run flagged. Two other links from the same run (the dead `nix` ref and the dead `reflectoring.io` ref in `CONTRIBUTING.md`) were already folded into [#26341](https://github.com/coder/coder/pull/26341). ## Why Broken external and anchor links degrade reader trust, leak SEO juice, and make the docs look stale. The weekly `check-docs` job exists precisely to catch this kind of rot before customers do; the surfacing-to-fix turnaround on these 7 is one PR. Run that surfaced them: [actions/runs/27948011619 job 82697664858](https://github.com/coder/coder/actions/runs/27948011619/job/82697664858). ## Scope | File | Line(s) | Old target | New target | Why | |------|---------|-----------|------------|-----| | `docs/tutorials/best-practices/organizations.md` | 62 | anchor `#update-template-metadata-by-id` | `#update-template-settings-by-id` | API endpoint renamed in [#19228](https://github.com/coder/coder/pull/19228) (Aug 2025). New heading at line 1105 of `docs/reference/api/templates.md`. | | `docs/install/registry-mirror-artifactory.md` | 197 | JFrog `terraform-registry` | `terraform-opentofu-and-terraform-backend-repositories` | JFrog consolidated their Terraform / OpenTofu / Backend docs into a single page. | | `docs/admin/templates/extending-templates/modules.md` | 76, 206 | JFrog `set-up-a-terraform-module/provider-registry` and `terraform-registry` | same consolidated JFrog page (root, no anchor) | Same JFrog consolidation. Anchor dropped, see decision log. | | `docs/admin/integrations/dx-data-cloud.md` | 84 | `https://help.getdx.com/en/` | `https://docs.getdx.com/` | DX migrated their help center to a separate docs domain. | | `docs/about/contributing/frontend.md` | 37, 71 | `https://reactrouter.com/en/main` | `https://reactrouter.com/` | React Router dropped the `/en/main` prefix. | ## Validation - All 7 replacement URLs return HTTP 200 (manual `curl -L -o /dev/null -w '%{http_code}'` per URL; linkspector's puppeteer crashed in the agent env, so it was run case-by-case) - `make lint/markdown lint/emdash` clean locally - Pre-commit hook (`scripts/githooks/pre-commit` -> `make pre-commit-light`) clean - No `/docs/` route changes; pure markdown content ## Not triggering `/coder-agents-review` Docs-only markdown edit, no CI or build config changes; per `AGENTS.md` the bot review is reserved for product / CI changes. `doc-check` handles this category. ## Pre-mortem | Concern | Mitigation | |---|---| | Replacement URL also turns out to be broken later | All 7 verified HTTP 200 today; next weekly `check-docs` run will catch any future regression. | | JFrog anchor drop on `modules.md` (76, 206) loses navigation context | Verified the consolidated JFrog page has no clean section anchor for the original target; linking the root page is the honest fix. If JFrog ships a better TOC anchor later, a follow-up can reattach. | | Anchor rename in `organizations.md` was actually a different rename | Confirmed via PR #19228 (Aug 2025) which is the exact rename that produced `## Update template settings by ID`. | <details> <summary>Decision log</summary> **Why drop the anchor on the JFrog `modules.md` links (76 + 206)**: JFrog's new consolidated page (`/terraform-opentofu-and-terraform-backend-repositories`) doesn't expose the original `set-up-a-terraform-module/provider-registry` section as a fragment-link target. The honest fix is to link the page root; readers can scroll. The `registry-mirror-artifactory.md:197` reference uses the same root link for symmetry. **Why DX `docs.getdx.com` over `help.getdx.com`**: DX's help center at `help.getdx.com/en/` now returns 404. They moved to a separate `docs.getdx.com` domain with a different content structure. Linking the docs root is the closest analog to the original "browse our docs" intent. **Why React Router root over `/en/main`**: React Router unified their docs under the root URL. The `/en/main` prefix is no longer routable. The root URL is the canonical successor. </details> <details> <summary>CI: <code>audit-docs-paths</code> failure (pre-existing, unrelated)</summary> The `audit-docs-paths` job in `.github/workflows/weekly-docs.yaml` fails on this PR because its `Fetch redirects.json` step issues an unauthenticated `curl` to a file in private `coder/coder.com` and gets a 404 (exit code 22). Same failure on every recent PR in this repo. Tracked in [DOCS-409](https://linear.app/codercom/issue/DOCS-409) and fixed in [#26571](https://github.com/coder/coder/pull/26571), which authenticates the fetch through the Contents API. My changes are docs-content only (5 markdown files, 7 line changes) and don't touch the TS/TSX paths or `redirects.json` that the audit examines, so this is a pre-existing CI break, not a regression introduced here. </details> --- *Generated by Coder Agents on @nickvigilante's behalf.* |
||
|
|
9b6dc4ab41 |
fix: left-align module names in SelectionSummary (#26583)
fixes DEVEX-514, which I accidentally introduced in #26531 |
||
|
|
73acb2d5b4 |
test: accept 0 duration in TestAwaitDeliveryExactCount (#26582)
fixes https://github.com/coder/internal/issues/1603 On Windows you can get 0 duration from subsequent time.Now() calls. |
||
|
|
c13dd06d2f |
ci(.github/workflows): disable audit-docs-paths pending cross-repo auth (#26571)
The `audit-docs-paths` job in `weekly-docs.yaml` fetches a config file from a private upstream source. An anonymous read returns 404 and the job fails on every weekly run, firing a misleading "Stale docs paths found in site/src/" Slack notification (a pre-existing bug in the notification copy, tracked separately). We originally tried to authenticate the fetch with the existing CI token used for cross-repo work (the same one used by `contrib.yaml`), but that token does not have read access to the upstream source. The proper fix is a GitHub App scoped to cross-repo `Contents: Read`; the docs team is tracking the App provisioning internally. Until the App is provisioned, this PR disables the job behind a `vars.AUDIT_DOCS_PATHS_ENABLED` repository variable. The variable is unset, so the job skips on the weekly cron and on `workflow_dispatch`. The other two jobs in this workflow (`prepare-linkspector-browser`, `check-docs`) keep running normally, so docs PRs still get link-checked. Re-enabling once the App is provisioned is a one-line change: set `AUDIT_DOCS_PATHS_ENABLED` to `'true'` on this repo, no workflow edit required. <details> <summary>Investigation log (why the App is needed)</summary> Initial attempt (commits `5cca548`, `fc0ff59`, now discarded) authenticated the fetch via the GitHub Contents API with `Accept: application/vnd.github.raw` and an existing CI token already used for cross-repo writes. `coder-agents-review` approved that approach in Round 2 ([review 4546533491](https://github.com/coder/coder/pull/26571#pullrequestreview-4546533491)), and all 29 CI checks passed. Validation via `workflow_dispatch` (run [27973114839](https://github.com/coder/coder/actions/runs/27973114839)) failed at the fetch step with `curl: (22) The requested URL returned error: 404`. The bare `curl` against the same URL with a personal access token returned HTTP 200 and valid JSON, so the call shape was correct; the CI token just lacks the necessary scope on the upstream source. The Contents API returns 404 (not 403) when a token cannot see a private repository, which is why the original failure mode was hard to attribute. Options considered: 1. **Extend the existing CI token** to include the missing read access. Cheapest in lines of code, but the token is org-CI-owned and changing its scope has blast radius beyond this job. 2. **New fine-grained PAT.** Tightest scope, but PATs are user-owned. If the issuing user leaves the org, the token auto-revokes and the audit silently breaks again, which is exactly the failure mode this PR is trying to make less likely. 3. **GitHub App owned by the org.** Tied to the org, not a user; survives staff turnover; least-privileged per repo. Heaviest setup because creation, installation, and secret provisioning all need org admin. Option 3 is the right long-term answer but is not same-day. Disabling the job is the smallest change that stops the noise immediately, and the feature-flag variable keeps the re-enable path to one step. </details> <details> <summary>Validation</summary> * `actionlint` clean on `.github/workflows/weekly-docs.yaml`. * Branch passed all 29 CI checks under the previous authentication approach; this revision is strictly smaller (one job-level `if` guard + comments), no new failure surface introduced. * The disable cannot be tested end-to-end without merging, since the affected job runs on `schedule` / `workflow_dispatch` against `main`. Once merged: confirm the next weekly run (or a manual `workflow_dispatch`) shows `audit-docs-paths` as skipped, with no Slack notification. </details> --- > Generated by [Coder Agents](https://coder.com) on behalf of @nickvigilante. |
||
|
|
78c5ab96c9 |
feat(coderd/x/chatd): serve workspace MCP tools and read_skill from pinned context (#26581)
This wires the last two consumer-side gaps of the agent-pushed workspace
context refactor. coderd already hydrates each chat's pinned context
(`chat_context_resources`), and `resolveTurnWorkspaceContext` already
prefers the pin for instruction files and skill metadata. This change
extends that preference to workspace MCP tools and the `read_skill`
body.
Workspace MCP tools are now built from the chat's pinned `mcp_server`
resources instead of a live `ListMCPTools` pull.
`resolveWorkspaceMCPTools` prefers the pin and falls back to live
discovery for chats whose agent has not reported context yet, gated the
same way as the instruction/skills pin: the pin wins whenever the chat
has any pinned rows, so a workspace with no MCP servers contributes no
tools rather than resurrecting stale ones. Because the agent reports
tool names unprefixed, each tool is re-prefixed to the
`{server}__{tool}` form and the pushed JSON Schema is split into
`properties` and `required` so the result matches what live discovery
produced. Calls still proxy through the workspace agent connection; the
snapshot carries tool definitions, not a way to execute them.
`read_skill` now serves a workspace skill's `SKILL.md` body from the
pinned snapshot (`SkillMeta.Meta`) instead of dialing the agent, so a
pinned chat keeps returning the same instructions even when the
workspace is unreachable. The supporting-file list stays a best-effort
live lookup, since the snapshot carries only the meta file per the agent
push contract.
The legacy live paths remain as the fallback for agents that have not
pushed context; RFC Release-5 cleanup of those paths is out of scope
here.
<details>
<summary>Implementation plan and decisions</summary>
### Background
The agentcontext refactor is mostly shipped across earlier PRs (#25983,
#26526, #26533, #26577, #26570, #26573): the agent resolves instruction
files, skills, and MCP servers into a snapshot, pushes it via
`PushContextState`, and coderd hydrates each chat's pinned context
(`chat_context_resources`). This PR closes the two remaining
consumer-side gaps.
### Key facts established from the code
- Pushed MCP tool names are **unprefixed** (`mcprunner` stores
`tool.Name`); the agent MCP proxy and `CallMCPTool` expect the
`{server}__{tool}` form (`agentmcp.ToolNameSep`). The pinned path
reconstructs the prefix for execution, matching the model-facing names
the legacy path produced.
- Legacy `agentmcp` sets `MCPToolInfo.Schema = InputSchema.Properties`
and `Required = InputSchema.Required` separately. The pushed
`input_schema` is the full JSON Schema object, so the pinned builder
extracts `properties` and `required` to match that shape.
- `SkillMetaBody.meta` is the verbatim SKILL.md. The supporting-file
list is **not** in the snapshot, so it is fetched live on demand
(best-effort).
- Gating mirrors `resolveTurnWorkspaceContext`: the pin wins when the
chat has any pinned rows; otherwise the live path is used.
### Changes
1. `chattool/skill.go`: add `SkillMeta.Meta []byte`; extract
`listSkillFiles` from `LoadSkillBody`; in `readWorkspaceSkillBody`, when
`Meta` is present, parse the body from it without dialing and list files
best-effort, else use the legacy live read.
2. `context_prompt.go`: populate `SkillMeta.Meta` in
`contextResourcesToPrompt`; add `workspaceMCPToolInfosFromResources`
(pinned `mcp_server` rows to `[]workspacesdk.MCPToolInfo` with prefixed
names and split properties/required) and `splitMCPInputSchema`.
3. `chatd.go`: add `pinnedWorkspaceMCPTools` (build tools from the pin,
ok-gated) and `resolveWorkspaceMCPTools` (pin-first, fall back to
`discoverWorkspaceMCPTools`).
4. `generation_preparer.go`: call `resolveWorkspaceMCPTools` instead of
`discoverWorkspaceMCPTools`.
### Tests
- `chattool/skill_test.go`: read_skill serves the pinned body without
dialing, lists files via LS, and still returns the body when the
workspace is unreachable.
- `context_prompt_internal_test.go`: `SkillMeta.Meta` is populated;
`workspaceMCPToolInfosFromResources` prefixing/properties/required/skip
behavior; `pinnedWorkspaceMCPTools` ok-gating and fallback dispatch.
</details>
---
*Opened by Coder Agents on behalf of @kylecarbs.*
|
||
|
|
3fb402cd82 |
chore: bump github.com/gohugoio/hugo from 0.163.0 to 0.163.3 (#26579)
Bumps [github.com/gohugoio/hugo](https://github.com/gohugoio/hugo) from 0.163.0 to 0.163.3. <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.163.3</h2> <h2>What's Changed</h2> <ul> <li>markup/highlight: Escape lang in default code block rendering ce1a7e0b <a href="https://github.com/bep"><code>@bep</code></a> thanks to <a href="https://github.com/k0ngj1"><code>@k0ngj1</code></a> for reporting this issue.</li> <li>parser/pageparser: Preserve non-ASCII whitespace after e.g. summary divider 70a9068a <a href="https://github.com/bep"><code>@bep</code></a></li> <li>resources: Support babel/postcss config variants 9d66d513 <a href="https://github.com/jmooring"><code>@jmooring</code></a> <a href="https://redirect.github.com/gohugoio/hugo/issues/15039">#15039</a> <a href="https://redirect.github.com/gohugoio/hugo/issues/15040">#15040</a> <a href="https://redirect.github.com/gohugoio/hugo/issues/15043">#15043</a></li> <li>hugolib: Fix page/section name collision regression f0133466 <a href="https://github.com/jmooring"><code>@jmooring</code></a> <a href="https://redirect.github.com/gohugoio/hugo/issues/15046">#15046</a></li> </ul> <h2>v0.163.2</h2> <h2>What's Changed</h2> <ul> <li>Continue resolving on ERR_ACCESS_DENIED in Node's resolver 134674f0 <a href="https://github.com/bep"><code>@bep</code></a> <a href="https://redirect.github.com/gohugoio/hugo/issues/15041">#15041</a></li> <li>markup: Standardize behavior when external converters are missing 147f605f <a href="https://github.com/jmooring"><code>@jmooring</code></a> <a href="https://redirect.github.com/gohugoio/hugo/issues/14222">#14222</a></li> </ul> <h2>v0.163.1</h2> <p>The majority of the fixes in this release are security related (including the upstream fix in 93c8c7d3 (golang.org/x/image)). Thanks to <a href="https://github.com/vnth4nhnt"><code>@vnth4nhnt</code></a> for finding the issues fixed in a00b5c72 and cf9c8f93 (I will do the CVE work on this later). There has been a uptick in security reports lately, which doesn't mean that Hugo has gotten less secure, this is mostly the work of the new and powerful AI tools using Hugo's restrictive <a href="https://gohugo.io/about/security/">security model</a> as their baseline. Just take a look at Go's recent <a href="https://github.com/golang/go/issues?q=is%3Aissue%20label%3ASecurity">security issue list</a> to see a demonstration of this.</p> <h2>What's Changed</h2> <ul> <li>build(deps): bump golang.org/x/image from 0.41.0 to 0.42.0 93c8c7d3 <a href="https://github.com/dependabot"><code>@dependabot</code></a>[bot]</li> <li>Fix multi --renderSegments merge behavior 95e5e9f4 <a href="https://github.com/bep"><code>@bep</code></a> <a href="https://redirect.github.com/gohugoio/hugo/issues/15024">#15024</a></li> <li>security: Normalize integer IPv4 host encodings in http.urls check a00b5c72 <a href="https://github.com/bep"><code>@bep</code></a></li> <li>Drop symlinks in os.ReadDir, os.ReadFile, os.Stat and os.FileExists cf9c8f93 <a href="https://github.com/bep"><code>@bep</code></a> <a href="https://redirect.github.com/gohugoio/hugo/issues/15019">#15019</a></li> <li>commands: Fix convert command 2602796c <a href="https://github.com/jmooring"><code>@jmooring</code></a> <a href="https://redirect.github.com/gohugoio/hugo/issues/15012">#15012</a></li> </ul> </blockquote> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/gohugoio/hugo/commit/4d22555aebf458d5d150500c9ac4bee5b24cf0d3"><code>4d22555</code></a> releaser: Bump versions for release of 0.163.3</li> <li><a href="https://github.com/gohugoio/hugo/commit/ce1a7e0bce3713af40496ded3c2c0ceeed49231d"><code>ce1a7e0</code></a> markup/highlight: Escape lang in default code block rendering</li> <li><a href="https://github.com/gohugoio/hugo/commit/e8988c31412249897a2e6805b61c37ed5c82a10c"><code>e8988c3</code></a> Merge commit 'c86d9f4aa8a58931f52df6516f10b67c807505fb'</li> <li><a href="https://github.com/gohugoio/hugo/commit/c86d9f4aa8a58931f52df6516f10b67c807505fb"><code>c86d9f4</code></a> Squashed 'docs/' changes from 1f8ddb8a52..e17426e2b6</li> <li><a href="https://github.com/gohugoio/hugo/commit/70a9068aa67c67a9eb2ab5fe062faf5a99e6b650"><code>70a9068</code></a> parser/pageparser: Preserve non-ASCII whitespace after e.g. summary divider</li> <li><a href="https://github.com/gohugoio/hugo/commit/9d66d513cee02e77c96c78059d5c3ae6b1c5dde9"><code>9d66d51</code></a> resources: Support babel/postcss config variants</li> <li><a href="https://github.com/gohugoio/hugo/commit/f01334666790f328e222f67c278396ee77003021"><code>f013346</code></a> hugolib: Fix page/section name collision regression</li> <li><a href="https://github.com/gohugoio/hugo/commit/96e06e1ab8484327dcbb521b8445a52d0c022cf3"><code>96e06e1</code></a> releaser: Prepare repository for 0.164.0-DEV</li> <li><a href="https://github.com/gohugoio/hugo/commit/19a5cec0b9618163bb519487382e861d29edf383"><code>19a5cec</code></a> releaser: Bump versions for release of 0.163.2</li> <li><a href="https://github.com/gohugoio/hugo/commit/134674f00df2c2c0db24f0674de2263298d33eb7"><code>134674f</code></a> Continue resolving on ERR_ACCESS_DENIED in Node's resolver</li> <li>Additional commits viewable in <a href="https://github.com/gohugoio/hugo/compare/v0.163.0...v0.163.3">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) You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/coder/coder/network/alerts). </details> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> |
||
|
|
116a220ff6 | fix(coderd): let admins change their own workspace sharing role (#26559) | ||
|
|
966dd89537 |
feat: add chat context source CLI and agent-token refresh (#26577)
Adds the `coder exp chat context` CLI for managing workspace context sources, plus the agent-token refresh endpoint the in-workspace refresh relies on. Part of breaking the "Workspace Context Sources for Coder Agents" RFC (#26466) into small, reviewable PRs. ## What this adds **CLI (`coder exp chat context`)**, talking to the agent's local IPC socket from inside the workspace: - `list` lists the registered scan roots (built-in defaults are not shown). - `show <path>` shows a source and the resources the agent resolves from it, including failures. - `add <path>` registers a path as an additional context source. With `--chat`, it keeps the legacy one-shot behavior (read context from the path once and inject it into a single chat). - `remove <path>` unregisters a source. - `refresh [<chat>]` re-pins chat context to the agent's latest snapshot. **Agent-token refresh path** for the no-argument `refresh`: - `refresh <chat>` uses the existing user-facing `ExperimentalClient.RefreshChatContext` (already on main) and works from anywhere. - `refresh` with no argument runs inside the workspace: it re-resolves the agent's sources over the context socket (catching freshly-cloned repos and startup-script writes), then asks the agent, authenticating with its own token, to re-pin every drifted chat. No `coder login` required. - This adds `agentsdk.RefreshChatContext` and `POST /api/v2/workspaceagents/me/experimental/chat-context/refresh` (`workspaceAgentRefreshChatContext`), mirroring the existing clear endpoint's agent-token auth model. ## Testing - `go test ./cli` (`TestExpChatContextAdd`, `TestParseChatID`, `TestResolveContextSourcePath`) - `go test ./coderd/x/chatd -run TestChatContextRefreshFromAgentToken` (end-to-end: echo-provisioned agent pushes a snapshot, drifts a bound chat, the agent-token refresh re-pins it, and an agent-less chat stays untouched) - `go build ./...`, `go vet`, `golangci-lint`, `make gen` (no generated changes; experimental commands are excluded from CLI golden/doc generation) <details> <summary>Design notes</summary> This is **Split 4** of #26466. Split sequence: 1. #26558 - prompt pin consumption (merged) 2. #26570 - `codersdk` context resource types (merged) 3. #26573 - the context indicator UI (merged) 4. **This PR** - the CLI + agent-token refresh. 5. The context diff (`changes`, `ChatContextResourceChange`, the changes dialog, `buildContentPatch`) - last. Key points: - The agent-local context subsystem (`agent/agentsocket` IPC for source CRUD, snapshot, resync), the user-facing `ExperimentalClient.RefreshChatContext`, and the per-chat `chatd.RefreshChatContext` all already exist on main, so this split is the CLI surface plus the small agent-token refresh endpoint that fans out per-chat refresh across an agent's drifted chats. - `add <path>` resolves relative paths to absolute before handing them to the agent (which requires canonical paths) but preserves a leading `~` for the agent to expand against its own home. `TestResolveContextSourcePath` covers this. - The agent endpoint is annotated `@x-apidocgen {"skip": true}`, matching the other agent-token chat-context endpoints. - No diff/changes rendering is involved; that lands in the final split. </details> *This PR was created by Coder Agents on behalf of @kylecarbs.* |
||
|
|
ee3572ab9a |
feat: wire Vale prose linter into docs CI (#25467)
Wires Vale into docs CI as an advisory (non-blocking) prose-lint step. Closes [DOCS-40](https://linear.app/codercom/issue/DOCS-40). > **Integration update (rebased onto `main`).** Since this branch was opened, `main` consolidated docs linting into the **required** `lint-docs` job in `ci.yaml` and removed the standalone `docs-ci.yaml` ([#25608](https://github.com/coder/coder/pull/25608)). This PR adds Vale to that `lint-docs` job instead of resurrecting `docs-ci.yaml`, and the `docs/.style/` scaffold defers to the merged [#25466](https://github.com/coder/coder/pull/25466) (DOCS-180). Vale stays advisory. > **Post-review refactor.** Following the Coder Agents review, Vale is now invoked through `mise exec "aqua:errata-ai/vale"` (the same pattern as `actionlint`/`zizmor`) instead of a bespoke `curl`/`tar` download. This removed the GNU-only `grep -oP` version extraction and `uname`/arch mapping that broke on macOS BSD grep, and the prose step now skips paths a PR deletes. See the resolved review threads for CRF-17/19/20/21/22. A sample of what this check does is as follows: <img width="1443" height="1293" alt="image" src="https://github.com/user-attachments/assets/cf68dbf9-d9df-49ba-8dbf-200875bc289e" /> ## What changes - `.vale.ini` at the repo root: Google base + Coder (custom, empty in v1) + curated write-good. `alex` rules are pulled in a la carte. Inline comments justify every enable/disable. - `mise.toml`: pin Vale `3.7.1` via aqua. `mise.lock`: lock that pin across all platforms so `mise install --locked` (used by `build_image`) resolves it. - `Makefile`: a `docs/.style/.vale-synced` sentinel that gates `vale sync`, and a `lint/prose` target that runs `vale --no-exit`. Both invoke Vale via `mise exec "aqua:errata-ai/vale" -- vale ...`, so mise owns the version and the OS/arch download (no hand-rolled install path). - `.github/workflows/ci.yaml`: append Vale steps to the existing required `lint-docs` job: `Detect changed Markdown`, `Restore Vale styles`, `Prepare Vale styles` (`make docs/.style/.vale-synced`), `Vale prose lint`, and a default-branch-only `Save Vale styles`. They lint only changed Markdown under `docs/` that still exists on disk, with a problem matcher for inline PR annotations. - `.github/vale-problem-matcher.json`: parses `vale --output=line` so alerts surface as annotations on the Files Changed tab. - `.gitignore` and the workflow cache `path:`: use `docs/.style/styles/*` plus a `!docs/.style/styles/Coder` negation so adding a package does not require parallel edits. - `.markdownlint-cli2.jsonc`: ignore the synced styles so `make lint/markdown` does not lint upstream READMEs. Scaffold prose under `docs/.style/` and `.claude/docs/DOCS_STYLE_GUIDE.md` / `AGENTS.md` come from the merged DOCS-180; this PR no longer touches them. Net diff against `main` is the 8 Vale-wiring files only. ## Severity policy (v1) Rule severity reflects two things together: the rule's false-positive rate against real Coder docs and the gravity of the rule. Low FPs plus high gravity argues for `error`; lower gravity or more judgment calls argue for `warning` or `suggestion`. v1 lands most rules at `warning` and the wordiness rules at `suggestion`. A rule promotes to `error` only when (a) its false-positive rate against real content is effectively zero and (b) the existing-content violation count for that rule is also zero. Vale exits non-zero only on error-level alerts regardless of `MinAlertLevel`; the Makefile and CI invoke Vale with `--no-exit` so the baseline error count from un-overridden Google rules does not fail the build while real failures (bad config, missing files) still propagate. ## CI integration Vale runs as steps appended to the required `lint-docs` job in `ci.yaml`, gated on changed Markdown: 1. **`Detect changed Markdown`** (`tj-actions/changed-files`) scopes to changed `**.md`; the prose step re-filters to `docs/` (the `docs/**.md` glob silently skips dot-prefixed dirs and would miss `docs/.style/style-guide.md`). 2. **`Restore Vale styles`** (`actions/cache/restore`), keyed off `hashFiles('.vale.ini', 'mise.toml', 'docs/.style/styles/Coder/**')`. mise manages the Vale binary, so only the synced styles are cached. 3. **`Prepare Vale styles`** runs `make docs/.style/.vale-synced` (`mise exec ... vale sync`). 4. **`Vale prose lint`** filters the changed set to `docs/` paths still present on disk, then runs `mise exec ... vale --no-exit --output=line`, emitting inline annotations via the problem matcher. 5. **`Save Vale styles`** writes the cache, gated to `refs/heads/main` only so PR runs cannot poison the cache other branches restore from (the zizmor `cache-poisoning` concern). **Every Vale step is `continue-on-error: true`.** This is a deliberate change from the original standalone-workflow design: now that Vale lives inside the *required* `lint-docs` job, a transient `vale sync` network failure (or first-use `mise` install blip) would otherwise block merges. `continue-on-error` keeps Vale advisory, so only the markdownlint / table-formatter checks above (`pnpm check-docs`) remain merge-blocking. `vale --no-exit` additionally keeps the baseline error count from un-overridden Google rules from failing the step. ## Verification - `actionlint` clean on `ci.yaml` (local + `make lint/actions/actionlint`); `zizmor --persona regular` reports no findings. - `make lint/prose` on the full `docs/` corpus: ~406 errors, ~5,346 warnings, ~7,928 suggestions across 461 files, exit 0 (`--no-exit`), Vale `3.7.1` installed by mise. - Net diff vs `main` is the 8 Vale-wiring files only; the `docs/.style/` scaffold already matches `main`. <details> <summary>Implementation plan and decision log</summary> ### Why this rule set The Vale evaluation against the full docs corpus (measured 2026-05-18) produced ~43,940 raw violations across six candidate base styles. The selection here drops Microsoft and RedHat (overlap with Google, and RedHat's Spacing rule hammers technical IDs), and proselint (Annotations rule treats `> [!NOTE]` admonitions as TODO markers). Within the kept styles: - **Google** is the base. Disables: `EmDash` (conflicts with `make lint/emdash`), `Latin` (i.e./e.g. are fine for our audience), `Spacing` (4,500 errors on `codersdk.SomeType` patterns in the auto-generated API reference). Softened: `Parens` to `suggestion`, `WordList` to `warning`. - **write-good** is the base, with `Passive` and `E-Prime` off. `TooWordy` and `ThereIs` are suggestions; `Weasel` is a warning. - **alex** is cherry-picked (not in `BasedOnStyles`): `Ablist`, `Condescending`, `LGBTQ`, `ProfanityLikely`, `Race`, `Suicide` at warning. The `ProfanityMaybe`/`ProfanityUnlikely` rules trip on `execute`, `kill`, `failed`, and `attack`, which read as technical vocabulary in our context. - **Coder** is in `BasedOnStyles` but the directory is empty in v1. Rules land through the per-rule tickets in the [Docs style guide](https://linear.app/codercom/project/docs-style-guide-7828445b9afc) project. ### Why `mise exec` instead of a download block Vale is pinned in `mise.toml` like `actionlint` and `zizmor`, so invoking it via `mise exec "aqua:errata-ai/vale" -- vale ...` makes the pin the single source of truth and lets mise handle the OS/arch-specific download. This replaced an earlier ~30-line `curl`/`tar` block whose GNU-only `grep -oP ...\K` version extraction returned empty on macOS BSD grep. Note: the bare `vale` short name in `mise exec` ignores the pin and resolves to the latest release, so the full aqua key is required. ### Why `vale sync` instead of vendoring The three style packages weigh ~272 KB combined, so vendoring is cheap. But Vale's ecosystem treats `Packages = ` + `vale sync` as canonical, the upstream LICENSE files are not in the package tarballs (would need to be added manually), and the CI cache makes the sync nearly free after the first run. Sticking with the canonical pattern keeps the repo lean and the upgrade path obvious. ### Why `lint/prose` is not in `lint:` or `lint-light:` Vale on the full docs corpus takes ~20s on cold caches. Forcing every pre-commit through that would be aggressive for a feature that ships as warnings. `make lint/typos` follows the same pattern (it is in `lint-light` but not `lint`; CI invokes it directly). v1 keeps Vale opt-in locally and CI-only by default; promote to `lint:` once the rule set stabilizes. ### Exit-code handling Two mechanisms combine, and the choice changed when the step moved into the required `lint-docs` job: - `vale --no-exit` suppresses Vale's non-zero exit on alerts, so the baseline error-level violations from un-overridden Google rules do not fail the step while the cleanup PRs land. Real failures (config invalid, file missing) still exit non-zero. - `continue-on-error: true` on every Vale step. Because the steps now run inside the *required* `lint-docs` job, a `vale sync` download/network blip must not block merges. The original (standalone, non-required) design rejected `continue-on-error` for showing a misleading yellow badge; in a required job that tradeoff flips, and advisory-yellow is strictly preferable to merge-blocking-red on an infrastructure flake. `|| true` in the Makefile was also rejected: it swallows missing-config failures indiscriminately. ### Pre-mortem - **Generated docs noise**: `docs/reference/` is dominated by auto-generated content (clidocgen, apidocgen, auditdocgen, metricsdocgen). The architectural decision is to fix the generators, not exclude paths in Vale. Google.Spacing is the only rule silenced specifically to defer the generator fix; everything else surfaces as warnings. - **First-run cost**: `mise` installs the pinned Vale (a single small binary) and `vale sync` pulls the style packages on a cold run. The Actions cache keyed off `hashFiles('.vale.ini', 'mise.toml', 'docs/.style/styles/Coder/**')` makes subsequent runs near-instant; the `Coder/**` hash is defense-in-depth against [actions/toolkit#713](https://github.com/actions/toolkit/issues/713) so a future cache release that regresses path-negation cannot serve a stale `Coder/` from cache. - **Required-job blast radius**: moving Vale into the required `lint-docs` job means any Vale step failure would gate merges. Mitigated by `continue-on-error` on all Vale steps plus a clean skip when no changed `docs/` Markdown remains on disk, so only `pnpm check-docs` stays blocking. - **Cross-platform install**: handled by mise (aqua backend) rather than a hand-rolled `uname`/arch map, which removes the macOS BSD-grep break the review flagged. - **Deleted files**: `all_changed_files` is ACMRD and lists paths a PR removes; the prose step filters to files still present on disk so Vale does not error on a missing file. - **Local-vs-CI parity**: CI lints changed files only; local `make lint/prose` lints the full tree. This mirrors `make lint/markdown` (full tree) vs the changed-files CI step. Acceptable for v1. </details> --- *Filed via [Coder Agents](https://coder.com/docs/ai-coder/agents) on Nick's behalf.* |
||
|
|
917dbde439 |
fix: regen feature stage docs from HEAD & enforce generation (#26528)
Generate the experimental and beta tables in docs/install/releases/feature-stages.md from the current source tree instead of release tags + GitHub API because we found the table of beta features was stale in recent release(s). This approach works now that Coder publishes per-release docs. This change was assisted by Coder Agents. |
||
|
|
e6a9b59abe |
feat(site/src): surface pinned chat workspace context in the UI (#26573)
Adds the workspace-context indicator UI for agent chats, part of breaking the "Workspace Context Sources for Coder Agents" RFC (#26466) into small, reviewable PRs. ## What this adds - **Pinned context popover**: the context-usage indicator now lists the chat's pinned resources, instruction files, skills, and MCP servers with their tools. Unusable resources (invalid skill, unreadable/oversize file) are surfaced in an "Issues" section with their error rather than dropped silently. - **Drift and error states**: when the pinned context differs from the agent's latest snapshot, the ring shows a warning marker and the popover explains the drift. A snapshot-level error gets a distinct treatment. - **Refresh context**: a button re-pins the chat to the agent's latest snapshot via `PUT /api/experimental/chats/{id}/context`. - **Live updates**: `context_dirty` watch events apply the lightweight dirty flags across the cached chat lists and refetch the open chat so the full pinned detail loads. ## Not included The context **changes/diff** view (the "View changes" affordance and its dialog) is intentionally deferred to a later split, so this PR contains no diff rendering. ## Testing - `pnpm lint` (types, biome, circular deps, React Compiler, knip) - `pnpm test src/api/queries/chats.test.ts` (cache-merge unit tests, including the new `context_dirty` cases) - `pnpm test:storybook src/pages/AgentsPage/components/ContextUsageIndicator.stories.tsx` (4 stories) - `pnpm format` <details> <summary>Design notes</summary> This is **Split 3** of #26466. Split sequence: 1. #26558 - prompt pin consumption (merged) 2. #26570 - `codersdk` context resource types (merged). During review the type was renamed `ChatContextMCPTool` -> `ChatContextTool` and the field `mcp_tools` -> `tools`; this PR consumes those merged names. 3. **This PR** - the UI. 4. CLI `coder exp chat context` source CRUD + `refresh` (next). 5. The context diff (`changes`, `ChatContextResourceChange`, the changes dialog, and `buildContentPatch`) - last. Key decisions: - The backend already publishes `ChatWatchEventKindContextDirty` and exposes the refresh endpoint (#26389). Watch/pubsub payloads stay lightweight: they carry only the `dirty`/`dirty_since`/`error` flags and omit `resources`. So `mergeWatchedChatSummary` merges (not replaces) the cached context to preserve the pinned `resources` a single-chat GET populated, and the `AgentsPage` watch handler refetches only the open chat to pull the full pinned detail. - The indicator prefers the chat's pinned `resources`; while they have not loaded it falls back to the agent's `last_injected_context`, skipping the empty context-file placeholder so it never renders a nameless row. - All diff/changes rendering is excluded here and lands in the final split to keep this PR focused on the read-only pinned view and the refresh action. </details> *This PR was created by Coder Agents on behalf of @kylecarbs.* |
||
|
|
c0f854c289 |
feat: report pinned chat context resources on chat API (#26570)
Surfaces a chat's pinned workspace-context resources on the single-chat GET and refresh responses, so clients can show *what* context the prompt was built from, not just whether it drifted. ## What's included - **codersdk**: `ChatContextResource` (plus `ChatContextResourceKind` and `ChatContextResourceStatus`) and `ChatContextMCPTool`, and a new `Chat.Context.Resources` field (metadata only, no bodies). It is populated only on the single-chat GET/refresh response; list and watch payloads stay nil to remain lightweight. - **coderd/x/chatd**: `Server.ContextResources`, which builds the metadata-only list from the chat's pinned `chat_context_resources` rows. Non-OK resources (invalid / unreadable / oversize / excluded) are reported with their status and error so the UI can explain why a resource was dropped from the prompt instead of silently omitting it. The shared protojson body decoders are extracted so the prompt and detail paths reuse them. - **coderd**: `getChat` and `refreshChatContext` enrich the response with the resource list. Failures are non-fatal (the chat stays usable without the detail). ## Scope / what's deferred This is an incremental split from #26466. This PR reports only the **resource inventory**. The pinned-context drift *diff* (the per-source `changes` set and the "View changes" dialog) is intentionally deferred to a later split; the existing `dirty` bit already signals that context changed. MCP resources are reported for display only; they are not injected into the prompt (a future RFC item). <details> <summary>Design notes</summary> - The resource list is the chat's full pinned inventory (instruction files, skills, and MCP configs/servers), preserving the query's `source ASC` order. OK-but-empty instruction files, OK skills with no name, and untracked kinds (reserved plugin/hook/subagent/command) are skipped. - MCP tool names are reported with the agent's `"<server>__"` prefix stripped so they read as the server exposes them. - The detail is computed on read and attached only on the single-chat GET and refresh responses; list and watch payloads omit it to stay lightweight. - `refreshChatContext` enriches its own response (mirroring `getChat`) so the client reflects a refresh immediately, without a full reload. </details> <details> <summary>Testing</summary> - `go test ./coderd/x/chatd/ -run 'TestPinnedContextResources|TestContextResources|TestChatContextDirtyFromAgentPush'` (unit + integration on embedded Postgres) passes. The integration test exercises the GET and refresh enrichment end-to-end. - `go build`, `go vet`, `golangci-lint`, and `gofmt` are clean. - `make gen` regenerated `apidoc`, `swagger.json`, `docs/reference/api/*`, and `typesGenerated.ts`. </details> --- *This PR was created by Coder Agents on behalf of @kylecarbs.* |
||
|
|
401aa58eeb | feat: add schema changes for autostop notification (#26417) | ||
|
|
bd893a4504 |
docs: restore Bedrock static credentials walkthrough (#26563)
## Summary Restores the step-by-step "Obtaining static Bedrock credentials" walkthrough that was present on the v2.32.6 `ai-bridge/setup` page but missing from the current `ai-gateway/providers` page. The current page mentions static credentials in a single line but no longer explains how to create the IAM user and access key in the AWS console. This PR brings back that walkthrough, adapted to the current database/dashboard-managed provider flow. ## Changes - Add an `#### Obtaining static Bedrock credentials` subsection under the Amazon Bedrock provider section in `docs/ai-coder/ai-gateway/providers.md`. - Keep the AWS console steps (choose region, generate API keys, create access key) from v2.32.6. - Replace the deprecated `CODER_AIBRIDGE_BEDROCK_*` environment-variable configuration step with guidance to enter the credentials when adding/editing the provider via the dashboard or AI Providers API, matching the post-v2.34 database-managed model. <details> <summary>Context and decisions</summary> - Source: [`docs/ai-coder/ai-bridge/setup.md` at v2.32.6](https://coder.com/docs/@v2.32.6/ai-coder/ai-bridge/setup) "Obtaining Bedrock credentials" section. - The old flow set provider config via environment variables, which are deprecated since v2.34 (providers are now stored in the database and managed via dashboard/API). The restored content keeps the AWS-side credential-creation steps but routes the final configuration step through the current provider management flow rather than env vars. - Open questions from [AIGOV-432](https://linear.app/codercom/issue/AIGOV-432/restore-bedrock-static-credentials-docs-from-v2326) (whether other pages also need this, and whether the content needs further accuracy updates) are left for review. </details> Closes [AIGOV-432](https://linear.app/codercom/issue/AIGOV-432/restore-bedrock-static-credentials-docs-from-v2326). > [!NOTE] > This PR was generated by Coder Agents on behalf of @dannykopping. --------- Co-authored-by: Nick Vigilante <nickvigilante@users.noreply.github.com> |
||
|
|
e458692cb8 |
refactor(docs): convert absolute coder/coder blob/tree/main links to relative (DOCS-351) (#26341)
Closes [DOCS-351](https://linear.app/codercom/issue/DOCS-351). > [!WARNING] > **DO NOT MERGE** until [DOCS-349](https://linear.app/codercom/issue/DOCS-349) ([coder.com#877](https://github.com/coder/coder.com/pull/877)) has shipped to production and baked for at least one Vercel cycle. > > Without DOCS-349, the relative links in this PR resolve to broken docs-route URLs (`/docs/helm/coder/values.yaml` -> 404) instead of GitHub URLs tagged with the displayed docs version. DOCS-349 fixes the rewriter to classify these as GitHub blob/tree URLs with the page's resolved ref. ## TL;DR Converts 121 absolute `https://github.com/coder/coder/(blob|tree)/main/<path>` links across 39 docs markdown files to relative paths. After this lands AND DOCS-349 deploys, every one of these links will follow the displayed docs version (mainline tag on bare URLs, explicit tag on `/@vX.Y.Z/`, `main` on `/@main/`) instead of always pointing to `main`. ## Why Today a reader on `/docs/@v2.30.0/install/docker` follows a `compose.yaml` link and arrives at `main`'s `compose.yaml`, which doesn't necessarily match what the docs page describes. Helm values, Terraform templates, and source-code references in particular drift across versions. The fix is to let the coder.com rewriter substitute the page's resolved ref into the URL; that only works on relative links. ## Example payoff (post-DOCS-349) | URL | Today (absolute, always `main`) | After (relative + rewriter) | |---|---|---| | `/docs/install/docker` | `https://github.com/coder/coder/blob/main/compose.yaml` | `https://github.com/coder/coder/blob/v2.34.1/compose.yaml` (today's mainline) | | `/docs/@v2.30.0/install/docker` | same as above | `https://github.com/coder/coder/blob/v2.30.0/compose.yaml` | | `/docs/@main/install/docker` | same as above | `https://github.com/coder/coder/blob/main/compose.yaml` | ## Scope - **121 conversions** across **39 files**. - Verb breakdown: `tree/main` (directories) and `blob/main` (files), both flipped to relative paths. - Line anchors (`#L23-L24`) and query strings preserved verbatim. - Conversion is mechanical: relative path computed from the doc file's directory to the target via `os.path.relpath`. Any path starting at the same directory or below gets a `./` prefix; otherwise `../` chains. ## Rebased on main The branch was rebased onto `main` after the DOCS-350 hotfix ([#26339](https://github.com/coder/coder/pull/26339)) merged. The hotfix repointed 3 `docs-backend-contrib-guide` refs in `backend.md` to `main`, which then needed the same `main` -> relative conversion this PR is doing for the other 121 links. The conflict was resolved by reapplying the mechanical conversion to `backend.md` after taking the hotfix's content. Net result: those 3 links land here as relative, same as everything else. New HEAD `3f501cb622`. ## Inline fix folded in: dead `nix` link - `docs/about/contributing/CONTRIBUTING.md:7` -> `../../../nix` The original absolute URL `https://github.com/coder/coder/tree/main/nix` already returned 404 today. Repointed to `flake.nix` (modern Nix entrypoint, what the prose "Nix environment" semantically refers to). Closes [DOCS-357](https://linear.app/codercom/issue/DOCS-357) here since the `check-docs` Linkspector job surfaced it during rebase; cheaper to fix inline than in a separate single-line PR. ## Out of scope (filed separately) - [DOCS-350](https://linear.app/codercom/issue/DOCS-350): 3 dead `docs-backend-contrib-guide` branch refs in `backend.md` ([#26339](https://github.com/coder/coder/pull/26339), merged). - [DOCS-352](https://linear.app/codercom/issue/DOCS-352): 10 SHA-pinned `(blob|tree)/<sha>` links pending intent review. - [DOCS-355](https://linear.app/codercom/issue/DOCS-355): code-server analog (4 absolute `(blob|tree)/main` links in `coder/code-server`). - [DOCS-356](https://linear.app/codercom/issue/DOCS-356): 2 upstream content bugs in `coder/code-server/docs/CONTRIBUTING.md` (independent of this PR). ## Not triggering `/coder-agents-review` Docs-only edit; per `AGENTS.md` the bot review is reserved for product/CI changes. ## Pre-mortem | Concern | Mitigation | |---|---| | Merging before DOCS-349 deploys regresses ~120 currently-working links into 404s on coder.com | Clear DO-NOT-MERGE banner; tracked as blocker in Linear. | | Relative path computed incorrectly (off-by-one `..`) | Verified all 114 newly-relative non-md/non-image paths resolve to existing files in the repo (only exception is the pre-existing dead `nix` link above). | | Line anchors stripped during conversion | Preserved by the substitution regex; verified `#L<n>-L<m>` cases in `airgap.md` and `speed-up-templates.md`. | | Future code reorgs change file locations | Relative links will start pointing to nothing. Same failure mode as absolute links pointing to renamed files; can be caught with a future link-checker job. | ## Validation ``` $ grep -rE 'github\.com/coder/coder/(blob|tree)/main' docs --include="*.md" | wc -l 0 $ git diff --stat origin/main | tail -1 39 files changed, 118 insertions(+), 118 deletions(-) ``` 114 newly-relative paths verified to resolve to existing repo files (Python `os.path.exists` check on each computed target). <details> <summary>Decision log + planning context</summary> **Why relative over `(blob|tree)/{{currentDocsVersion}}/...` templating**: relative paths require zero markdown-system support and zero upstream churn beyond this one PR. Templating would require a preprocessor on `coder.com` side AND a convention upstream authors have to remember; relative paths just work in a plain editor and `github.com`'s own renderer too. **Why `./` prefix on same-directory targets**: makes the conversion grep-able later (`grep -E '\((\.\./|\./)'`). **Why preserve `#L<n>-L<m>` anchors verbatim**: the anchor is meaningful to the linked file's content, not to the URL form; keeping it as-is preserves authorial intent. If the file later changes such that the line range drifts, that's a different problem the SHA-pin audit ([DOCS-352](https://linear.app/codercom/issue/DOCS-352)) will surface. </details> --- *Generated by Coder Agents on @nickvigilante's behalf.* ## Drive-by external link fix folded in `docs/about/contributing/CONTRIBUTING.md:296` cited `https://reflectoring.io/meaningful-commit-messages/` which is returning HTTP 503 (the host appears to be down site-wide right now). `check-docs` Linkspector flagged it after the rebase. Replaced with `https://cbea.ms/git-commit/` (Chris Beams' canonical "If applied, this commit will..." article, confirmed 200), which is the original source of the rule the prose recites anyway. |
||
|
|
46916bf899 |
feat(coderd/x/chatd): consume the pinned chat context in prompt generation (#26558)
## What `prepareGeneration` now builds the system-prompt instruction block and workspace skills from a chat's **pinned context copy** (`chat_context_resources`, populated in #26438) instead of re-scanning per-turn history, when the chat has a pinned copy. This is the first production reader of the pin. Selection is **presence-based, no experiment**: a chat with pinned rows builds its prompt from the pin; a chat without them falls back to the existing per-turn history path. The two paths are mutually exclusive, so older agents that never report context keep their current behavior and the per-turn pull stays as the fallback. ## How - `contextResourcesToPrompt` maps the protojson resource bodies (instruction files and skills) into the instruction block and skill metadata, skipping non-OK statuses, non-prompt body kinds, and malformed bodies (the malformed count is logged so a proto/encoding regression cannot silently drop context). - `pinnedWorkspaceContext` reads the pin and reports `ok=false` (history fallback) when there are no pinned rows; read errors propagate. The bound agent only decorates the instruction header with OS and directory, so the pin still resolves when the workspace is unreachable. - `resolveTurnWorkspaceContext` dispatches between the pinned and history paths; `prepareGeneration` calls it. ## Testing - `go test ./coderd/x/chatd/` for `TestContextResourcesToPrompt`, `TestPinnedWorkspaceContext` (incl. `...FromHydratedPin` against real Postgres), and `TestResolveTurnWorkspaceContext`: pass. - `make gen` (no drift), `golangci-lint`, `gofmt`, emdash scan, and `go build`/`go vet` on `./coderd/x/chatd/...`: all clean. ## Scope This is the foundational backend slice split from #26466 (the full-stack staging PR). It changes no API surface, schema, proto, or generated files. The remaining pieces land as follow-ups in dependency order: 1. `ChatContext` drift/diff API (`resources` + `changes`, `ContextDetail`). This also extracts the body decoders inlined here so they are shared with the diff path. 2. Context-ring drift indicator, changes dialog, and refresh (UI). 3. In-workspace `coder exp chat context` source CRUD and `refresh` (CLI). <details> <summary>Why this is the first split</summary> The coderd hydration, the `PUT /chats/{id}/context` refresh endpoint (#26389), the `chat_context_resources` table (#26430), and the copy-into-pin logic (#26438) are already merged, as is the agent-side push (#26526, #26533). Consuming the pin in prompt building is the step #26438 explicitly deferred, and it is the bottom of the remaining dependency stack: the drift/diff API, the UI indicator, and the CLI are only meaningful once the chat actually builds its prompt from the pin. Keeping it presence-based means it is independently revertable and leaves the per-turn pull intact as a fallback, matching the RFC's Release 3 rollout. The files are taken verbatim from the reviewed #26466 boundary commit (before the diff-API work began), so the deep-review feedback already applied there (CRF-1 through CRF-10) is preserved. </details> --- *This PR was created by Coder Agents on behalf of @kylecarbs.* Split from #26466. |
||
|
|
f5cb2e547e |
feat: include rotated agent logs in support bundles (#26055)
Support bundles previously captured only the active coder-agent.log, losing history across agent restarts. Add an optional `after` filter to the agent's /debug/logs endpoint: without it the endpoint is unchanged (active log only, 10 MiB cap); with it the response includes the active log plus rotated coder-agent-*.log files modified after the cutoff, newest first. Support bundles request the last 24h. Closes #25395 |
||
|
|
adad5bdd49 |
feat: surface agent firewall correlation in AI Bridge sessions API (#26416)
Add `agent_firewall_session_id` and `agent_firewall_sequence_number`
fields to `AIBridgeThread` in the `GET
/api/v2/aibridge/sessions/{session_id}` response. These fields link each
thread to its agent firewall confinement session so the frontend can
discover the boundary session and compute sequence ranges for
interleaving firewall events within the thread timeline.
The database columns already exist on `aibridge_interceptions`
(migration 000520) and are already selected by
`ListAIBridgeSessionThreads`. This PR surfaces them through the SDK type
and the `db2sdk` conversion.
Depends on #24814
**Naming note:** The RFC uses `boundary_session_id` /
`boundary_sequence_number`, but the codebase standardized on
`agent_firewall_*` naming in the DB migration. The API fields follow the
existing convention.
</details>
> [!NOTE]
> This PR was authored by Coder Agents.
|
||
|
|
335d6bda1b |
feat: add GET /api/v2/agent-firewall/sessions/{id}/logs endpoint (#24816)
Add a `GET /api/v2/agent-firewall/sessions/{id}/logs` endpoint that
returns agent firewall audit logs for a given session, sorted by
sequence number ascending.
The endpoint supports `seq_after` and `seq_before` (exclusive bounds)
and `limit` query parameters. This enables the frontend to fetch exactly
the firewall events that fall between two AI Bridge interceptions within
a thread, as described in FR 4 of the Boundary/Bridge correlation RFC.
Authorization reuses the `boundary_log` RBAC resource (owner and auditor
can read; members cannot). Returns 404 for unauthorized users to avoid
leaking existence information.
The endpoint is enterprise-only, gated behind `FeatureBoundary`
entitlement, matching the session endpoint from #24814.
Depends on #24814
> [!NOTE]
> This PR was authored by Coder Agents.
|
||
|
|
c0b8fa9418 |
feat(site): add user AI budget override UI (#26402)
Add a per-user AI budget override dialog in the group members menu, scoped to the group's organization. Refs AIGOV-295 |
||
|
|
4f8acfaeff |
docs: add Codex WebSocket fallback troubleshooting (#26565)
## Summary Adds a Troubleshooting section to the Codex CLI AI Gateway client docs covering the WebSocket-to-HTTPS transport fallback. Recent Codex CLI versions default to the WebSocket runtime for the Responses API. AI Gateway does not support WebSocket transport, so each request attempts a WebSocket connection, fails, and falls back to HTTPS, surfacing: ```text Falling back from WebSockets to HTTPS transport. ``` The doc explains the cause and the fix: set `supports_websockets = false` in the `[model_providers.ai_gateway]` block in `~/.codex/config.toml` to force HTTPS directly and remove the fallback delay. Closes [AIGOV-453](https://linear.app/codercom/issue/AIGOV-453/document-codex-cli-websocket-fallback-workaround). <details> <summary>Note on the config value</summary> The original request and the Linear issue referenced enabling websocket support / `support_websockets = false`. The authoritative Codex CLI [config reference](https://developers.openai.com/codex/config-reference) confirms: - The key is `supports_websockets` (trailing "s"). - It declares whether a provider supports the Responses API WebSocket transport. - Setting it to `false` is the documented workaround to force HTTPS and stop the fallback attempts. Since AI Gateway does not support WebSockets, `supports_websockets = false` is the correct value. `= true` would assert support that does not exist and keep the fallback happening. </details> --- This PR was generated by Coder Agents on behalf of @dannykopping. |
||
|
|
8b970e7ff3 |
docs: clarify Agents vs Chats API reference pages (#26021)
## Problem The REST API reference page at [`/docs/reference/api/agents`](https://coder.com/docs/reference/api/agents) is confusing: by the name alone, a reader looking for the *AI Coder Agents* programmatic API would assume this is the right page. In fact, those endpoints are for the *workspace agent daemon* (the `coder_agent` Terraform resource / `workspaceagent` daemon). The actual AI Coder Agents API is documented at [`/docs/reference/api/chats`](https://coder.com/docs/reference/api/chats). Both pages compound the confusion by being rendered with a bare `# Agents` / `# Chats` heading and no descriptive intro. The sidebar entries are similarly ambiguous (`Agents` and `Chats` with no descriptions). ## Root cause The reference pages are generated by `scripts/apidocgen/generate.sh` (swag → widdershins → postprocess). The widdershins template (`scripts/apidocgen/markdown-template/main.dot`) already renders `data.resource.description` directly under each section heading: ``` <!-- APIDOCGEN: BEGIN SECTION --> {{= data.tags.section }}# {{= r}} {{? data.resource.description }}{{= data.resource.description}}{{?}} ``` …but the swag annotations in `coderd/coderd.go` never declared `@tag.name` / `@tag.description` for any tag, so the descriptions were always empty. ## Changes - `coderd/coderd.go`: add `@tag.name Agents` / `@tag.description …` and `@tag.name Chats` / `@tag.description …` annotations next to the existing `@title` / `@version` block. - `docs/manifest.json`: rename the sidebar entry `Agents` → `Workspace Agents` and add `description` fields to both API sidebar entries (every other top-level section in the manifest has descriptions; the API children did not). - Regenerate `coderd/apidoc/swagger.json`, `coderd/apidoc/docs.go`, `docs/reference/api/agents.md`, and `docs/reference/api/chats.md` via `scripts/apidocgen/generate.sh` + `pnpm exec markdownlint-cli2 --fix` + `pnpm exec markdown-table-formatter` + `scripts/biome_format.sh` (matching the Makefile's `coderd/apidoc/.gen` pipeline). Resulting diff is intentionally minimal — 6 files, 35 insertions / 3 deletions. ## After this PR The Agents page will render: > # Agents > > Workspace agent endpoints. These power the workspace agent daemon defined by the `coder_agent` Terraform resource (sometimes called the workspace daemon). This API is NOT the AI Coder Agents API. For programmatic access to AI Coder Agents (formerly Tasks), see the Chats API. The Chats page will render: > # Chats > > Programmatic API for Coder AI Agents (the user-facing "Coder Agents" / "Chats" product). Experimental. Use these endpoints to create, list, and manage AI coding agent sessions. For background and migration from the Tasks API, see the AI Coder docs. And the sidebar entry for the workspace-agent endpoints becomes `Workspace Agents` instead of `Agents`. ## Out of scope (potential follow-ups) - `docs/reference/api/chat.md` is a 7-byte stub — likely dead. Could be deleted in a follow-up. - Larger rename of the `Agents` Swagger tag (and/or the `coder_agent` Terraform resource) to something like `Workspace Agents` / `workspace_daemon` would more thoroughly fix the naming collision, but that's a much bigger change. Created on behalf of @mattvollmer. --------- Co-authored-by: blink-so[bot] <211532188+blink-so[bot]@users.noreply.github.com> Co-authored-by: Matt Vollmer <matthewjvollmer@outlook.com> Co-authored-by: Atif Ali <atif@coder.com> |
||
|
|
bc9cc8cb08 |
fix(enterprise/coderd): allow deleting external-agent workspaces (#26501)
I stumbled on this while manually testing another workspace change: if a license expires after an external-agent workspace exists, deleting that workspace is rejected because `CheckBuildUsage` enforces the external-agent entitlement for every workspace transition. I assume this is unintentional from a product POV. This PR narrows the external-agent entitlement check to start builds. Creating or rebuilding external-agent workspaces still requires the feature entitlement, but stop and delete transitions stay available as cleanup paths. That matches the managed-agent entitlement precedent (i.e. the usage billing check) in the same `CheckBuildUsage` path, where license enforcement is scoped to start transitions instead of trapping users with resources they can no longer remove. |
||
|
|
2f8bba792a |
feat: push MCP server context and tools from agentcontext (#26533)
## What Live MCP servers and their tools now flow into the `agentcontext` snapshot and are pushed to coderd via `PushContextState`, stored alongside instruction files and skills. Previously the resolver's MCP seam was unimplemented, so live MCP tool lists never reached the pushed snapshot. `agentcontext` is now **fully self-contained** for MCP: it connects to the MCP servers declared in the `.mcp.json` files its own watcher already discovers, lists their tools, and emits `KindMCPServer` resources. It does **not** depend on or modify `agent/x/agentmcp` — that package is left pristine and keeps serving the agent's MCP HTTP API. The two MCP paths run independently, which means the legacy package can be deleted later without touching this code. ## How - **Self-contained runner** (`agentcontext/mcprunner.go`): a one-shot MCP client (connect → initialize → list tools → close) with its own `.mcp.json` parser. A Manager goroutine (`runMCPSync`) reloads it whenever the discovered `KindMCPConfig` `path:contenthash` set changes, then re-resolves so the new tools are published. Per-server connects run in parallel (bounded) with a per-server timeout; a server that fails to connect is recorded as a failure rather than aborting the batch. Each connect also force-kills its subprocess on close, because mcp-go's stdio `Close()` closes stdin and then blocks on `cmd.Wait()` with no kill — a server that ignores stdin-close would otherwise stall the whole reload loop. - **Resource production** (`agentcontext/mcp.go`): `buildMCPServerResources` turns the runner's non-blocking per-server snapshot into `KindMCPServer` resources. Connected servers carry their sorted tools (`StatusOK`); failed servers surface as `StatusUnreadable` issues instead of vanishing; connected-but-no-tools-yet are skipped until a later reload. The content hash is tool-set sensitive. The resolver consumes this through a plain `MCPResources func() []Resource` field (no `MCPProvider` interface). - **Tool names**: emitted exactly as the server reports them. Flattening into a single namespace (e.g. `server__tool`) is left to the control plane in the next step, since each resource already carries the server name. - **Drift**: MCP resources are excluded from the snapshot aggregate/drift hash (`driftResources`). MCP servers connect asynchronously after boot; without this, a server finishing its connect would dirty every hydrated chat even though nothing the user pinned changed. - **Wiring** (`agent.go`): the manager is given `ManagerOptions.MCPExecer`/`MCPUpdateEnv`; `agent/x/agentmcp` is untouched. - **Config validation**: a structurally broken `.mcp.json` surfaces as `StatusInvalid` rather than silently dropping all its servers. coderd already persists `mcp_server`/`mcp_config` resource bodies (including tools), so no coderd or proto changes were required. ## Testing - **Unit**: `buildMCPServerResources` (grouping/sort/skip/failed/hash sensitivity), MCP resources applied via the resolver seam, MCP exclusion from the aggregate hash, `.mcp.json` parsing (transport inference, env expansion), `toolInputSchema`, and `mcpConfigSet` change detection. - **Proto serialization** (`TestDRPCPusher_HappyPathSerializesAllFields`): a `KindMCPServer` resource (tools + input schema) round-trips through `PushContextState` into the `MCPServerBody` wire form, asserting the server name, tool name/description, and the decoded `input_schema`. - **Manager-level, real subprocess** (`TestManager_MCPServerToolsInSnapshot`): a `.mcp.json` points at a re-exec'd fake stdio MCP server; the runner connects it and its `echo` tool surfaces as a `KindMCPServer` resource in the Manager snapshot — the same snapshot pushed to coderd — exercising `runMCPSync` and the resolver wiring end to end. - **Regression** (`TestManager_MCPServerHangingCloseDoesNotStall`): the fake server ignores stdin-close; the test asserts its tool still surfaces, proving the runner force-kills the subprocess instead of stalling the reload. Verified to fail without the fix. - All pass under `-race`; `go build ./...`, `go vet`, and `golangci-lint` are clean on the touched packages. ## Scope / follow-ups This is the agent-side production+push half. The chatd consumer (reading the pinned MCP resources for prompt/tool injection, including any server-prefix flattening of tool names) and removing the legacy `workspaceMCPToolsCache` pull path remain follow-ups, per the RFC rollout. While both `agent/x/agentmcp` and `agentcontext` exist, stdio MCP servers are spawned by both; this is intentional and temporary until `agentmcp` is removed. <details> <summary>Implementation plan and decisions</summary> **Goal:** produce live MCP server resources (with tools) from `agentcontext` and push them to coderd. **Starting state (main):** proto (`PushContextState`, `MCPServerBody`, `MCPTool`), the drpc adapter, coderd storage (`workspace_agent_context_resources`, body kind `mcp_server`), and the resolver's MCP seam already existed; nothing implemented the seam or fed live tools into the snapshot. **Decision (agentcontext fully separate from agentmcp):** `agentcontext` starts and lists its own MCP servers using only the connect-and-list half of an mcp-go client, driven by the `.mcp.json` files its existing watcher discovers. It shares no state with `agent/x/agentmcp` and does not import it. Two earlier revisions of this branch were discarded: (1) relocating `agentmcp` into `agentcontext` (rejected — it duplicates config parsing and file watching `agentcontext` already does); (2) reading `agentmcp`'s cached server snapshot via new accessors (rejected — unnecessary coupling between two packages that should simply run independently while one is being retired). The temporary double-spawn of stdio servers is the accepted cost of keeping the two paths cleanly separated until `agentmcp` is removed. **Decision (no tool-name prefixing, no MCPProvider interface):** the agent pushes raw, unflattened data — server name plus verbatim tool names — and lets the control plane own any `server__tool` flattening. With a single self-contained producer, the `MCPProvider` interface was collapsed into a `func() []Resource` field on the resolver. **Invariants held:** no secrets (env/headers) in pushed resources, only server/tool metadata; MCP excluded from the drift hash; the seam is non-blocking so the resolver never stalls on MCP I/O. </details> --- *This PR was created by Coder Agents on behalf of @kylecarbs.* |
||
|
|
d5ec26beac |
chore: replace testing.Testing with flag lookup (#26552)
In our codebase we have an existing convention of using
`flag.Lookup("test.v")` instead of `testing.Testing()`. This avoids
pulling in the entire `testing` package. Another consequence: some of
our custom linters trigger upon import of the `testing` package which
can lead to unexpected linter errors.
|
||
|
|
befa1176b9 |
chore(dogfood): tighten template dormancy settings (#26421)
Tightens dormancy settings for all templates managed in this repo to 30 days / 30 days for time till dormancy and dormancy autodeletion, respectively. This was apparently done manually previously but ended up being automatically reverted. |
||
|
|
6186532cec |
fix: negative metric counter increment from token arithmetic (#26547)
_Disclosure: produced using Claude Opus 4.8_ Closes [AIGOV-452](https://linear.app/codercom/issue/AIGOV-452/prevent-control-plane-panic-on-negative-cached-tokens) Also addresses a similar shortcoming in `aibridge/intercept/responses/base.go` and aligns token recording approach for chatcompletions with other implementations --------- Signed-off-by: Danny Kopping <danny@coder.com> |
||
|
|
a12b051834 |
chore: skip failing azureidentity test while under investigation (#26545)
Skips the failing azureidentity test while under investigation. Ref: https://github.com/coder/internal/issues/1602 |
||
|
|
fc83d77189 | ci: correct location of redirects.json in weekly-docs workflow (#26542) | ||
|
|
a2b680ab29 |
fix: sanitize MCP tool names to satisfy LLM provider constraints (#26539)
Fixes #26325 |
||
|
|
4aa2482e93 |
fix: alias coder testutil to resolve import collision (#26540)
PRs https://github.com/coder/coder/pull/26092 and https://github.com/coder/coder/pull/26519 both landed on main and the circuit breaker test file ended up importing both `aibridge/internal/testutil` and `coder/v2/testutil` under the same name, causing a redeclaration error and breaking `make lint`. Alias the latter as `codertestutil`, matching the convention already used in `passthrough_internal_test.go` and `keyfailover_test.go`. |
||
|
|
b0b698c643 |
fix(aibridge): increase circuit breaker test timeout to prevent flake (#26519)
`TestCircuitBreaker_FullRecoveryCycle/OpenAI` flaked once on macOS CI. The most likely cause is that the circuit breaker `Timeout` (open-to-half-open transition) was too short relative to the time between test phases. On a slow runner, the breaker could transition to half-open before the test verified it was still open, so the request went through as a half-open probe instead of being rejected. Increases `Timeout` to `testutil.IntervalMedium` (250ms) across all circuit breaker integration tests. **Note:** Ideally, these tests would use a mock clock for deterministic timing, but https://github.com/sony/gobreaker (the library used for circuit breaker logic) uses real time internally and doesn't expose a clock interface. Closes https://linear.app/codercom/issue/AIGOV-438 > Generated with [Coder Agents](https://coder.com/agents) on behalf of @ssncferreira |
||
|
|
fec21e1a28 |
refactor(aibridge): apply key pool failover follow-ups (#26130)
Applies follow-ups from the key pool failover work: - Add a test verifying key pool state is shared across bridged and passthrough routes. - Refactor the key failover and passthrough tests to use the shared `MockUpstream` helper. - Simplify how the request body option is passed through the Anthropic messages interceptor. - Make `ResponseErrorFromKeyPool` nil-safe and cover it with a test. Closes: https://linear.app/codercom/issue/AIGOV-398/small-follow-up-cleanups-for-key-failover > [!NOTE] > Initially generated by Claude Opus 4.7, modified and reviewed by @ssncferreira |
||
|
|
19aa9f5616 |
refactor: separate aibridge provider and interceptor configs (#26092)
## Description Separates the aibridge provider configuration from the per-request configuration an interceptor actually needs, and introduces a single `Credential` type that each provider resolves per request. Previously a provider handed its full config to the interceptor (including fields the interceptor didn't use) while other request data was passed as loose arguments, and authentication was spread across config fields and arguments. ## Changes - Add `intercept.Config`: the per-request, provider-agnostic configuration an interceptor needs (`ProviderName`, `BaseURL`, `APIDumpDir`, `SendActorHeaders`). - Introduce a single `Credential` interface (`BYOK` and `Centralized`) that each provider resolves per request in `resolveCredential`, and have interceptors route on the credential kind. - Fail fast with `ErrNoCredential` when a request is neither BYOK nor backed by a centralized key pool. - Remove unused provider config fields (`Key`, `BYOKBearerToken`, `ExtraHeaders`). Closes: coder/aibridge#266 Closes: https://linear.app/codercom/issue/AIGOV-221/refactor-separate-provider-and-interceptor-configs > [!NOTE] > Initially generated by Claude Opus 4.7, modified and reviewed by @ssncferreira |
||
|
|
0d573587e8 |
feat(site): align ModuleSelection icon with top line when text wraps (#26531)
<img width="1840" height="1191" alt="image" src="https://github.com/user-attachments/assets/3095d1a7-0f34-4a9a-9dbd-7b9cc524af84" /> Do you think we should also top-align the deselect button that displays on hover? |