mirror of
https://github.com/coder/coder.git
synced 2026-09-22 05:05:20 +08:00
f1d160c7f44b97fdd721e15cbdddcd49f442ce3d
14243
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
f1d160c7f4 |
fix: allow changing model when editing earlier chat message (#25084)
Editing a previous user message and selecting a different model in the
picker silently kept using the original model: the selection was dropped
on the frontend, in the SDK, and in the backend, so both the replacement
user message and the assistant turn that followed ran against the old
model.
Plumb the selected model through all three layers (`AgentChatPage`,
`codersdk.EditChatMessageRequest`, `chatd.EditMessageOptions` /
`Server.EditMessage`), defaulting to the original message's model when
the client does not specify one. The existing `InsertChatMessages` CTE
already advances `chats.last_model_config_id` when the inserted
message's model differs, so the assistant turn picks up the new
selection without further changes. The new model is validated inside the
transaction, so an unknown ID rolls the edit back and returns a 400
`Invalid model config ID.`, mirroring the `SendMessage` path.
Refs: CODAGT-345
This change was generated by a Coder agent.
<details>
<summary>Implementation plan</summary>
# CODAGT-345: Editing an earlier message cannot change model
## Problem
When editing a previous user message in a chat, the user can change the
model in the model picker, but the backend keeps using the original
message's model. The model selection is dropped at three layers:
1. **Frontend:** `AgentChatPage.tsx`'s edit branch builds an
`EditChatMessageRequest` that omits `model_config_id`. The new-message
branch (a few lines below) does include it.
2. **SDK:** `codersdk.EditChatMessageRequest` has no `ModelConfigID`
field at all.
3. **Backend:** `chatd.EditMessageOptions` has no model field, and
`Server.EditMessage` always copies the original message's
`ModelConfigID` into the replacement message.
Once the replacement user message is inserted with the original model,
the `InsertChatMessages` CTE leaves `chats.last_model_config_id`
unchanged, so the assistant turn that follows runs against the old
model.
## Fix
Plumb the selected model through all three layers, defaulting to the
original message's model when the client doesn't override it. This
mirrors the `SendMessage` path, which already accepts a
`model_config_id` and validates it via
`resolveSendMessageModelConfigID`.
### Backend
- `codersdk/chats.go`: add `ModelConfigID *uuid.UUID` to
`EditChatMessageRequest`.
- `coderd/x/chatd/chatd.go`:
- Add `ModelConfigID uuid.UUID` to `EditMessageOptions`.
- In `EditMessage`, after fetching the edited message, resolve the
model: if `opts.ModelConfigID != uuid.Nil`, validate it exists with
`tx.GetChatModelConfigByID` (using `chatdModelConfigLookupContext`),
otherwise keep `editedMsg.ModelConfigID.UUID`. Pass the resolved ID into
`newChatMessage(...)`.
- Reuse the existing `ErrInvalidModelConfigID` sentinel.
- `coderd/exp_chats.go` (`patchChatMessage`):
- Read `req.ModelConfigID` (nil-safe), pass into
`chatd.EditMessageOptions`.
- Add a `case xerrors.Is(editErr, chatd.ErrInvalidModelConfigID)` arm
returning 400 `Invalid model config ID.`, matching the
`postChatMessages` handler.
### Frontend
- `site/src/pages/AgentsPage/AgentChatPage.tsx`:
- In the edit branch, set `model_config_id: effectiveSelectedModel ||
undefined` on the `EditChatMessageRequest`.
- On success, persist the chosen model to `lastModelConfigIDStorageKey`
so the next chat from this browser keeps the same default. Mirrors the
new-message branch.
### Generated
- `make site/src/api/typesGenerated.ts` and `make
coderd/apidoc/swagger.json` produce the updated `EditChatMessageRequest`
schema in `typesGenerated.ts`, `coderd/apidoc/{docs.go,swagger.json}`,
and `docs/reference/api/{chats.md,schemas.md}`.
## Tests
- `coderd/x/chatd/chatd_test.go`:
- `TestEditMessageWithModelConfigOverride`: edit with a different model
-> replacement message and `chats.LastModelConfigID` use the new model.
- `TestEditMessagePreservesModelConfigByDefault`: edit without
`ModelConfigID` -> original model preserved.
- `TestEditMessageRejectsUnknownModelConfig`: passes a random UUID ->
`ErrInvalidModelConfigID`, original message still present,
`LastModelConfigID` unchanged (rollback).
- `coderd/exp_chats_test.go` (under `TestPatchChatMessage`):
- `ChangesModel`: end-to-end via SDK; `edited.Message.ModelConfigID` and
`chat.LastModelConfigID` both match the new model.
- `InvalidModelConfigID`: random UUID -> 400 `Invalid model config ID.`.
</details>
|
||
|
|
f847ff3731 |
test(coderd/x/chatd): skip stale notification flakes (#25177)
Skip the chatd tests that currently flake because the control notification flow cannot distinguish stale wake/status NOTIFY payloads from real interrupt requests. Each skipped test includes a TODO to re-enable it after the chatd notification flow refactor handles stale notifications correctly. Supersedes #25133, #25134, #25135, and #25139. Refs [CODAGT-353](https://linear.app/coder/issue/CODAGT-353), [CODAGT-356](https://linear.app/coder/issue/CODAGT-356), [CODAGT-360](https://linear.app/coder/issue/CODAGT-360), and [CODAGT-361](https://linear.app/coder/issue/CODAGT-361). > Mux working on behalf of Mike. |
||
|
|
4e08543ace |
test(coderd): centralize chat test harness and stabilize flakes (#25171)
Chat tests previously constructed a real `openai` provider with a fake API key and no `BaseURL`, so background title generation hit `api.openai.com` and timed out under `-race`. The same root cause produced several distinct flakes: title regeneration races with synchronous `UpdateChat`/`ProposeChatTitle`, and pagination races against `updated_at` bumps from real-network processing. This moves the fake OpenAI-compatible provider and the chat-settle wait into first-class `coderdtest` capabilities. `coderd.Options.ChatProviderAPIKeys` is the new seam tests use to redirect chat traffic to a local `httptest.Server`. `coderdtest.WaitForChatSettled` replaces per-test waiters and drains tracked chat-daemon work after the chat row leaves `pending`/`running`. The `newChatClient*` constructors funnel through one options builder that installs the fake provider before the coderd test server so cleanup ordering is deterministic. Closes https://github.com/coder/internal/issues/1528 & Closes ENG-2659 Closes https://github.com/coder/internal/issues/1480 & Closes CODAGT-359 Closes https://github.com/coder/internal/issues/1507 & Closes CODAGT-368 Relates to https://github.com/coder/internal/issues/1397 & Relates to CODAGT-374 |
||
|
|
8ba24e0e54 |
feat(site): add collapsible agent sections (#25173)
closes CODAGT-395 <img width="426" height="480" alt="Screenshot 2026-05-12 at 19 04 03" src="https://github.com/user-attachments/assets/ba336ecf-3e90-48b0-b5d3-b10499909953" /> Adds collapsible section headers to the Agents sidebar, including visible counts and chevrons for pinned and time-grouped chats. The section header toggle keeps nested chat expansion state independent, preserves the existing filter dropdown behavior, and adds Storybook coverage for counts, collapse or expand interactions, and filter menu behavior. |
||
|
|
a55430b8fd | fix(site/src/pages/AgentsPage): suppress last-message spacer during active stream (#25120) | ||
|
|
caabb3c4ab |
fix(site): show Organizations in admin dropdown for single-org OSS deployments (#25175)
Fixes https://linear.app/codercom/issue/CODAGT-350 On OSS or no-license single-org deployments, the Organizations admin link was hidden because `canViewOrganizationSettings` was gated on `showOrganizations`, which requires either a multi-org entitlement or >1 org. The page was still reachable via direct URL, but the members view displayed a raw "Template RBAC is a Premium feature. Contact sales!" error from the groups API. Two fixes: 1. Always render the Organizations link inside the `DeploymentDropdown`. The dropdown itself is only shown to users with admin-level permissions, so Organizations is effectively gated on having admin access. 2. Remove `groupsByUserIdQuery.error` from the error chain on the members page. The groups endpoint is gated behind `templateRBACEnabledMW` on enterprise, returning a 403 on OSS. The groups data is already optional, so the page renders fine without it. > Generated by Coder Agents |
||
|
|
5c3b59151e |
feat: add Cmd/Ctrl+Enter send setting (#25062)
Adds an Agents General setting to require Cmd/Ctrl+Enter before sending
chat messages. When enabled, plain Enter inserts a newline in agent chat
inputs while the send button remains available.
The preference is now persisted server-side through
`/api/v2/users/{user}/preferences`, alongside the existing user
preference settings, and is applied to both the create-agent input and
existing chat composer. Storybook and API coverage verify the setting,
keyboard behavior, validation, and persistence.
<details>
<summary>Coder Agents notes</summary>
Generated by Coder Agents from a Slack request. Dogfooded with
agent-browser against the Storybook settings and chat input stories.
</details>
|
||
|
|
376fc80451 |
fix(coderd/x/chatd): discover workspace MCP tools mid-turn after create_workspace (#25169)
## Problem In `coderd/x/chatd/chatd.go` `runChat`, workspace MCP discovery is gated on `chat.WorkspaceID.Valid` at the start of each turn. New chats that bind their workspace mid-turn (via `create_workspace` or `start_workspace`) get an empty workspace tool list on the first step, and the model falls back to `execute` (bash) because no workspace MCP tools are advertised. **Repro:** new chat → "create a workspace and use MCP tools". No `/api/v0/mcp/tools` request hits the agent on turn 1; turn 2 in the same chat works fine. ## Fix - Add a `PrepareTools` callback to `chatloop.RunOptions`, analogous to `PrepareMessages`. It is invoked once before each LLM step with the current tool list. When it returns non-nil, the chatloop replaces `opts.Tools`, rebuilds the per-step tool definitions, and appends new tool names to `opts.ActiveTools` so newly injected tools are callable immediately. - Wire `PrepareTools` in `runChat` to trigger workspace MCP discovery the first time the chat snapshot reports a valid `WorkspaceID`. The previous top-of-turn discovery path is unchanged for chats that start with a workspace. - Extract the discovery logic into `Server.discoverWorkspaceMCPTools` so the top-of-turn and mid-turn paths share identical behavior (cache, agent resolution, `ListMCPTools` timeout, invalidation). Mid-turn discovery stays disabled in plan-mode turns and Explore subagents, matching the existing top-of-turn gate. The `workspaceMCPDiscovered` flag prevents redundant dials after the first successful discovery. ## Tests - `coderd/x/chatd/chatloop/chatloop_test.go`: two new `TestRun_PrepareTools*` cases covering injection on the next step and active-set merging when `ActiveTools` is non-empty. - `coderd/x/chatd/chatd_test.go`: `TestRunChat_WorkspaceMCPDiscoveryAfterMidTurnCreateWorkspace` drives `runChat` through a `create_workspace` tool call against a real Postgres + mocked agent conn and asserts the second streamed LLM request advertises the workspace MCP tool. Verified that the test fails (and pinpoints the missing tool) when the `PrepareTools` wiring is disabled. ## Validation ``` go test ./coderd/x/chatd/chatloop/... -count=1 go test ./coderd/x/chatd/... -count=1 make lint/emdash ``` <details> <summary>Decision log</summary> - Chose a per-step `PrepareTools` callback over mutating `opts.Tools` in place because `chatloop.Run` builds the `fantasy.Tool` definitions once at start; a hook is required to let the LLM see new tools on the next step. - Returned `[]fantasy.AgentTool` (not also active-tool-names) and let the chatloop derive name merges via `mergeNewToolNames`. This avoids leaking plan-mode gating decisions into the callback contract. - Kept the existing top-of-turn discovery path so chats that already have a workspace at turn start pay no extra latency. - Skipped reusing `ReloadMessages` (history reload) since this is purely a tool-availability concern; coupling it to a history reload would defeat the chatloop cache prefix optimizations. </details> --- _This pull request was generated by Coder Agents._ |
||
|
|
5a5cd79c4c | fix: drop buffered chat parts after their durable message commits (#25164) | ||
|
|
07ff3b3f90 | fix(coderd/exp_chats_test.go): stabilize TestListChats/Pagination by inserting chats directly (#25137) | ||
|
|
d8ca626aec | chore(dogfood): use default rustup profile (#25165) | ||
|
|
592e45dcfb |
chore: bump coder-guts dependency (#25154)
Bump coder/guts to v1.7.0. Related PR: https://github.com/coder/guts/pull/81 |
||
|
|
7a7b196b21 |
fix(site/src/pages/AgentsPage/components/Sidebar): keep subtitle in sync during streaming lifecycle (#25144)
The Agents sidebar shows the per-chat turn-end summary as a subtitle,
but the cached `last_turn_summary` is not always in sync with the live
status:
- **Resuming a turn**: when a chat goes back to `running` or `pending`,
the sidebar would keep displaying the previous turn-end label (e.g.,
"Chat is idle") while the agent is already streaming again.
- **Stream end → next summary**: status flips to `waiting`
synchronously, but the new `last_turn_summary` is generated by an async
finalizer that calls the model. For a beat, the row still carries the
previous turn's summary text, which would briefly flash before the new
text arrives.
This PR addresses both:
1. Override the subtitle with `{model} streaming…` while `chat.status`
is `running` or `pending`, matching the same `isStreaming` definition
`ChatPageContent` uses. Errors still take precedence so failure context
is not hidden.
2. Capture the cached summary observed during streaming and suppress an
exact match on the post-stream renders until the new summary lands.
State is adjusted during render so the first post-stream paint already
hides the stale string instead of flashing it for a frame. A 10s timeout
safety net releases the suppression in the corner case where the
regenerated summary equals the previous one byte-for-byte.
<details>
<summary>Decision log</summary>
- **Frontend-only fix**: the server intentionally does not bump
`updated_at` when it writes the new `last_turn_summary` (see
`UpdateChatLastTurnSummary` in `coderd/database/queries/chats.sql`), and
SSE delivers the status flip ahead of the new label. The sidebar knows
the live status, so the rendering layer is the right place to mask the
inconsistency.
- **`isStreaming = running || pending`** mirrors `ChatPageContent.tsx`
so subagents and queued continuations also flip to the live label.
- **State, not refs**, for the suppression bookkeeping: the React
Compiler rejects ref writes during render, and React's "adjust state
during render" pattern is purpose-built for storing information from
previous renders (state setters in render bail out and re-render
synchronously before paint).
- **10s timeout** is a safety net for the rare byte-for-byte equality
case; the equality-based release handles every other shape of update.
- Added Storybook stories covering both fixes
(`ChatStreamingOverridesTurnSummary` and
`StaleTurnSummaryAfterStreamingIsSuppressed`). All existing legacy
subtitle stories still pass because they use terminal statuses.
</details>
> This PR was created by Coder Agents on behalf of @ibetitsmike.
|
||
|
|
566dace1bc |
fix(scripts/releaser): use last stable release as changelog base for .0 releases (#24988)
When releasing a `.0` version (e.g. `v2.33.0`) from a release branch, the release notes diff was comparing against the most recent RC (e.g. `v2.33.0-rc.3`) instead of the last stable release from the previous minor series (e.g. `v2.32.X`). ## The bug `prevVersion` is set to the latest tag matching the branch's `major.minor` from merged tags. For a `.0` release, this is the latest RC (e.g. `v2.33.0-rc.3`). The commit range for release notes then becomes `v2.33.0-rc.3..HEAD` instead of `v2.32.X..HEAD`, so the notes only show the delta from the last RC rather than all changes since the previous real release. The compare link also points to `v2.33.0-rc.3...v2.33.0`. ## The fix After all semver sanity checks have run (so version suggestion and validation are unaffected), when the new version is a `.0` release and `prevVersion` is an RC, override `prevVersion` with the last stable release from the previous minor series. This makes both the commit range and compare link use the correct base (e.g. `v2.32.X..HEAD` and `v2.32.X...v2.33.0`). > Generated with [Coder Agents](https://coder.com/agents) --------- Co-authored-by: Zach <3724288+zedkipp@users.noreply.github.com> |
||
|
|
bb8c40e764 |
feat: stream go test failure summary and drop raw json artifact (#25146)
This follows up on https://github.com/coder/coder/actions/runs/25684936801/job/75406131184?pr=25139 by replacing the large raw Go test JSON artifact with inline structured summaries and a compact failures-only artifact. ## What changed - Added `scripts/gotestsummary`, a streaming Go tool that reads gotestsum JSON and renders failed tests as Markdown. - Updated the three Go test jobs to publish per-test `<details>` sections in the job summary. - Removed upload of the raw `go-test.json` artifact. - Added upload of `go-test-failures-*.ndjson` with compact failure records for deeper inspection. - Deleted the old bash and `jq` summary script. ## Why - The previous raw artifact was about 35 MB compressed and 445 MB raw in the linked run. - Passing-test output made the artifact noisy and slow to inspect. - The old summary truncated output to 600 characters. - The new path keeps streaming, bounded output and writes structured diagnostics for only final failed tests. ## Validation - `gofmt -w scripts/gotestsummary` - `gofmt -l scripts/gotestsummary` - `go test ./scripts/gotestsummary/...` - `go vet ./scripts/gotestsummary/...` - `grep -rn 'go-test-failure-summary.sh' . || true` - `grep -rn 'go-test-failure-summary.sh\|go-test.json\|go-test-json-' .claude .agents docs AGENTS.md || true` - `make lint/agents` - `make lint/emdash` - `make lint/markdown` - `make lint/shellcheck` - `git diff --check origin/main..HEAD` > This PR was prepared by Mux working on Mike's behalf. |
||
|
|
aed43d9b61 |
fix: update coder/tailscale to 85c03fc8fb2a (#24824)
Updates `coder/tailscale` fork to [`85c03fc8fb2a`](https://github.com/coder/tailscale/commit/85c03fc8fb2ad8fdf5b9328be5d277aaa83afdff), which includes the DNS resilience fix from https://github.com/coder/tailscale/pull/114 (preserve NRPT rules on startup and improve hosts file retry). --- > Generated by Coder Agents |
||
|
|
0ed57ee343 | fix(coderd/x/chatd): checkpoint buffered message_parts to avoid stale replay (#25145) | ||
|
|
81561454d6 |
revert: "fix(site): enlarge checkbox click target in workspace and task tables" (#25159)
Reverts coder/coder#24739 |
||
|
|
3e46c7986f |
feat: event driven agent connection metric (#24355)
Moves the `coderd_agents_first_connection_seconds` histogram from the polling-based `prometheusmetrics.Agents()` loop to the event-driven `agentConnectionMonitor.init()` path. The metric is now recorded exactly once when an agent first connects over the RPC websocket, instead of being retroactively computed each polling tick. The `username` and `workspace_name` labels are removed to reduce cardinality; only `template_name` and `agent_name` are retained. Adds unit tests covering both the happy path (first connection recorded) and the negative-duration guard (clock skew logs a warning, no sample emitted). |
||
|
|
e56381eb61 |
feat: stream advisor tool output (#25032)
Stream advisor output into the advisor tool card while the nested advisor call is still running. This keeps the advisor implementation intentionally advisor-specific: the parent model still receives the same final structured tool result, while the frontend receives transient `tool-result.result_delta` parts to render partial advisor text in the expanded card. The final persisted chat history remains unchanged. Refs CODAGT-322. Generated by Coder Agents. <details> <summary>Implementation plan</summary> - Publish advisor text deltas from the nested `chatloop.Run` via `RunAdvisorOptions.OnAdviceDelta`. - Forward those deltas through `chatadvisor.Tool` with the parent advisor tool call ID. - Emit transient `ChatMessagePartTypeToolResult` websocket parts with `ResultDelta` from `chatd`. - Add `result_delta` to the generated tool-result TypeScript variant. - Accumulate tool result deltas in frontend stream state and keep the tool running until the final result arrives. - Render streamed advisor advice in the existing advisor card using streaming markdown mode, while retaining the updated advisor UI. </details> |
||
|
|
6bb88775ab |
test(coderd/x/chatd): pin TestGetWorkspaceConn_StatusCheck to mock clock (#25130)
The `TimedOutAgentCacheHit`, `CacheHitHealthyAgent`, and `CacheHitDBError` subtests of `TestGetWorkspaceConn_StatusCheck` built their `WorkspaceAgent` timestamps with `time.Now()` in the parent test's slice literal and then ran the actual check against the server's real wall clock (`quartz.NewReal()`). On slow Windows CI runners, more than `agentInactiveDisconnectTimeout` (30s) of wall time can elapse between slice construction and the parallel subtest body. In that window, the cached "healthy" agent gets reclassified as disconnected by `agentDisconnectedFor`, and `CacheHitHealthyAgent` fails with `errChatAgentDisconnected` instead of returning the cached connection. Build each agent inside the subtest with `quartz.NewMock(t)` and feed the same clock into the `Server` so the agent timestamps and the status math share a single frozen `now`. This matches the pattern already used by `TestGetWorkspaceConn_DialTimeoutDisconnectedRecoveryThreshold` in the same file. Closes https://github.com/coder/internal/issues/1522 <details> <summary>Verification</summary> Inserting `time.Sleep(35 * time.Second)` at the top of each subtest's body reliably reproduces the original failure (`errChatAgentDisconnected` on `CacheHitHealthyAgent`) on the parent commit and passes with this change. After removing the synthetic sleep, `go test ./coderd/x/chatd -run TestGetWorkspaceConn_StatusCheck -count=50` passes cleanly. </details> > Generated by Coder Agents on behalf of the assignee. Co-authored-by: Coder Agents <noreply@coder.com> |
||
|
|
e3db203011 |
fix(coderd/azureidentity): set explicit roots to avoid macOS system verifier (#25136)
Fixes [CODAGT-372](https://linear.app/codercom/issue/CODAGT-372/coderdazureidentity-testvalidateregular-fails-on-macos). Closes coder/internal#101. ## Problem `coderd/azureidentity TestValidate/regular` fails on macOS with: ``` verify signature: github.com/coder/coder/v2/coderd/azureidentity.Validate /Users/runner/work/coder/coder/coderd/azureidentity/azureidentity.go:75 - x509: “metadata.azure.com” certificate is not standards compliant ``` When `crypto/x509.VerifyOptions.Roots` is `nil`, Go's verifier on macOS/iOS falls back to the system verifier (`systemVerify` in `crypto/x509/root_darwin.go`), which delegates to Apple's `SecTrustEvaluateWithError`. Apple's framework enforces stricter standards-compliance checks than Go's pure-Go verifier and rejects some otherwise valid Azure instance-identity leaf certificates with `errSecCertificateIsNotStandardsCompliant`, surfaced as the `not standards compliant` error. The test had been skipped on darwin since #12979 (April 2024) as a workaround. ## Fix - Embed the three root CAs that Azure instance-identity certificates ultimately chain to: - DigiCert Global Root G2 - DigiCert Global Root G3 - Baltimore CyberTrust Root (kept for historical chains via `Microsoft RSA TLS CA 01/02`) - In `Validate`, populate `options.Roots` from those embedded roots when the caller does not supply its own pool. Because `Roots != nil`, Go no longer takes the `systemVerify` path on darwin and uses the pure-Go verifier on all platforms. - Remove the `runtime.GOOS == "darwin"` skip from `TestValidate`. - Add `TestEmbeddedRoots` to guard against future regressions in the embedded root list (parses each PEM, asserts self-signed, requires all three named roots). The caller's existing `Intermediates` handling is unchanged. Tests that pass their own `Roots` (e.g. `coderdtest.NewAzureInstanceIdentity`) are unaffected. ## Verification On Linux: ``` $ go test ./coderd/azureidentity/ -race -count=1 -v === RUN TestValidate === RUN TestValidate/regular === RUN TestValidate/govcloud === RUN TestValidate/rsa --- PASS: TestValidate (0.00s) --- PASS: TestValidate/regular (0.00s) --- PASS: TestValidate/rsa (0.00s) --- PASS: TestValidate/govcloud (0.00s) === RUN TestEmbeddedRoots --- PASS: TestEmbeddedRoots (0.00s) === RUN TestExpiresSoon --- SKIP: TestExpiresSoon (0.00s) PASS ok github.com/coder/coder/v2/coderd/azureidentity 1.020s ``` The `test-go-pg` job on `macos-latest` in CI is the authoritative confirmation of the fix on macOS; previously it would have failed `TestValidate/regular` had the skip been removed. <details> <summary>Why this is the correct fix</summary> From `/usr/local/go/src/crypto/x509/verify.go`: ```go // Use platform verifiers, where available, if Roots is from SystemCertPool. if runtime.GOOS == "windows" || runtime.GOOS == "darwin" || runtime.GOOS == "ios" { systemPool := systemRootsPool() if opts.Roots == nil && (systemPool == nil || systemPool.systemPool) { return c.systemVerify(&opts) } ... } ``` Setting `opts.Roots` to any non-nil, non-system pool deterministically routes verification through Go's pure-Go verifier, bypassing Apple's stricter compliance checks. The embedded roots are sufficient to validate every chain we currently care about, since every intermediate in `Certificates` ultimately issues to one of the three embedded roots. </details> > Generated by Coder Agents. Reviewed manually. |
||
|
|
60779ad2ec |
test(coderd/x/chatd): stop waking acquireLoop in TestResolveExploreToolSnapshot (#25129)
Fixes [CODAGT-367](https://linear.app/codercom/issue/CODAGT-367). `TestResolveExploreToolSnapshot/*` flaked on CI (Linux and Windows) with `context deadline exceeded` on the `GetMCPServerConfigsByIDs` call inside `resolveExploreToolSnapshot`. Each test setup called `server.CreateChat` twice with `MCPServerIDs` set to fake `.example.com` URLs. `CreateChat` marks the chat pending and calls `signalWake`, which causes the chatd background `acquireLoop` to pick the chat up. That goroutine then dialed the fake MCP URLs (NXDOMAIN, slower on Windows) and made an OpenAI request with the dbgen default test key (401). Under CI load, that activity racing the 4 parallel subtests' `GetMCPServerConfigsByIDs` calls was enough to exceed the 25s test context deadline. The failure logs in the issue showed both side effects firing in the same job. `resolveExploreToolSnapshot` only reads `ID`, `MCPServerIDs`, `PlanMode`, `ParentChatID`, and `Mode` off the parent argument, so the chats do not need to be persisted. Build them as in-memory `database.Chat` values instead. The MCP server configs remain in the DB because the function still queries them via `GetMCPServerConfigsByIDs`. Verified locally with `go test ./coderd/x/chatd -run TestResolveExploreToolSnapshot -count=100 -race` (passes, ~5s total) and the surrounding `TestResolve*` / `TestCreateChildSubagentChat*` / `TestSpawnAgent_Explore*` tests. --- _Made by Coder Agents on behalf of @ibetitsmike. [Linear session](https://linear.app/codercom/issue/CODAGT-367/flake-testresolveexploretoolsnapshot#agent-session-0730f3fe)._ |
||
|
|
19573e8aee |
feat!: patchTemplateMeta to use optional fields (#24984)
Closes https://github.com/coder/coder/issues/13112 **Breaking Change**: Removed status code `StatusNotModified` when no diffs occur in a patch. Now the patch is always applied and a template is always returned. |
||
|
|
3986aa8a51 |
feat(agent/agentfiles): add post-fail diagnostic hints for edit_files (#25092)
When fuzzyReplace exhausts its passes, append a hint to the generic "search string not found" error. Inversion: if search did not match but replace does, list the lines where replace appears. Miscount: when a search line agrees with a file line except for the count of one repeated rune, name the codepoint and counts. Miscount takes precedence; both firing could direct an agent to swap fields and corrupt the inversion anchor. Did you swap "search" and "replace"? Your replace string appears at line 12, 47, 89. Your search has 32 "─" (U+2500); the file has 37 at line 182. Closes CODAGT-330 |
||
|
|
6cf95366ed |
docs(.agents/skills/pull-requests): warn against hard-wrapping PR bodies (#25141)
PR bodies copied from a commit message body keep their 72/80-column hard wraps, and GitHub renders those as ragged-right line breaks instead of soft-wrapped paragraphs (e.g. the original body of #25130, fixed in this branch). The rule already exists in `.claude/docs/PR_STYLE_GUIDE.md`, but it is buried in a 200-line style guide and easy to miss when an agent is mechanically running `gh pr create`. This change adds a short "Body Formatting" section directly to `.agents/skills/pull-requests/SKILL.md`, which is the proximate context loaded at PR-write time, and explicitly tells callers to unwrap commit-message paragraphs before reusing them as a PR body. > Generated by Coder Agents on behalf of the assignee. |
||
|
|
645b8cc63d |
fix(coderd/x/chatd/chaterror): deflake TestClassify_ParsesRetryAfterHTTPDate (#25128)
The test built a `Retry-After` HTTP-date with `time.Now().Add(3*time.Second).UTC().Format(http.TimeFormat)`, then asserted that the parsed `RetryAfter` was `>= 2s`. `http.TimeFormat` has second precision, so `Format()` truncates up to ~1s. Combined with the small elapsed time between formatting in the test and `time.Until()` in production, the value could land just under `offset-1s` (1.997s observed in CI), failing the lower bound. Round the formatted target up to the next whole second so the parsed deadline is never earlier than `now+offset`, and assert against a symmetric `[offset-1s, offset+1s]` window. Closes [CODAGT-365](https://linear.app/codercom/issue/CODAGT-365/flake-testclassify-parsesretryafterhttpdate) Refs https://github.com/coder/internal/issues/1512 <sub>Created by [Coder Agents](https://coder.com/docs/agent).</sub> Co-authored-by: Coder Agents <coderagents@coder.com> |
||
|
|
56941a1600 |
chore: bump next from 15.5.16 to 15.5.18 in /offlinedocs (#25138)
Bumps [next](https://github.com/vercel/next.js) from 15.5.16 to 15.5.18. <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/vercel/next.js/releases">next's releases</a>.</em></p> <blockquote> <h2>v15.5.18</h2> <p>This release contains security fixes for the following advisories:</p> <p>High:</p> <ul> <li><a href="https://github.com/vercel/next.js/security/advisories/GHSA-8h8q-6873-q5fj">GHSA-8h8q-6873-q5fj: Denial of Service with Server Components</a></li> <li><a href="https://github.com/vercel/next.js/security/advisories/GHSA-267c-6grr-h53f">GHSA-267c-6grr-h53f: Middleware / Proxy bypass in App Router applications via segment-prefetch routes</a></li> <li><a href="https://github.com/vercel/next.js/security/advisories/GHSA-26hh-7cqf-hhc6">GHSA-26hh-7cqf-hhc6: Middleware / Proxy bypass in App Router applications via segment-prefetch routes - Incomplete Fix Follow-Up</a></li> <li><a href="https://github.com/vercel/next.js/security/advisories/GHSA-mg66-mrh9-m8jx">GHSA-mg66-mrh9-m8jx: Denial of Service via connection exhaustion in applications using Cache Components</a></li> <li><a href="https://github.com/vercel/next.js/security/advisories/GHSA-492v-c6pp-mqqv">GHSA-492v-c6pp-mqqv: Middleware / Proxy bypass through dynamic route parameter injection</a></li> <li><a href="https://github.com/vercel/next.js/security/advisories/GHSA-c4j6-fc7j-m34r">GHSA-c4j6-fc7j-m34r: Server-side request forgery in applications using WebSocket upgrades</a></li> <li><a href="https://github.com/vercel/next.js/security/advisories/GHSA-36qx-fr4f-26g5">GHSA-36qx-fr4f-26g5: Middleware / Proxy bypass in Pages Router applications using i18n</a></li> </ul> <p>Moderate:</p> <ul> <li><a href="https://github.com/vercel/next.js/security/advisories/GHSA-ffhc-5mcf-pf4q">GHSA-ffhc-5mcf-pf4q: Cross-site scripting in App Router applications using CSP nonces</a></li> <li><a href="https://github.com/vercel/next.js/security/advisories/GHSA-gx5p-jg67-6x7h">GHSA-gx5p-jg67-6x7h: Cross-site scripting in beforeInteractive scripts with untrusted input</a></li> <li><a href="https://github.com/vercel/next.js/security/advisories/GHSA-h64f-5h5j-jqjh">GHSA-h64f-5h5j-jqjh: Denial of Service in the Image Optimization API</a></li> <li><a href="https://github.com/vercel/next.js/security/advisories/GHSA-wfc6-r584-vfw7">GHSA-wfc6-r584-vfw7: Cache poisoning in React Server Component responses</a></li> </ul> <p>Low:</p> <ul> <li><a href="https://github.com/vercel/next.js/security/advisories/GHSA-vfv6-92ff-j949">GHSA-vfv6-92ff-j949: Cache poisoning via collisions in React Server Component cache-busting</a></li> <li><a href="https://github.com/vercel/next.js/security/advisories/GHSA-3g8h-86w9-wvmq">GHSA-3g8h-86w9-wvmq: Middleware / Proxy redirects can be cache-poisoned</a></li> </ul> </blockquote> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/vercel/next.js/commit/9ff92cebcaa6ba4e7463b6fd037a8510ba9b81ec"><code>9ff92ce</code></a> v15.5.18</li> <li><a href="https://github.com/vercel/next.js/commit/00ebe23562bd7eb32dd78730984bfadb47138bcf"><code>00ebe23</code></a> [backport] Disable build caches for production/staging/force-preview deploys ...</li> <li><a href="https://github.com/vercel/next.js/commit/62c97ab0b5825e2cbc15f6b682d8286a8dd6a038"><code>62c97ab</code></a> v15.5.17</li> <li><a href="https://github.com/vercel/next.js/commit/423623ae38c106273085b66946ee5bf9aab77f2c"><code>423623a</code></a> Turbopack: Match proxy matchers with webpack implementation (<a href="https://redirect.github.com/vercel/next.js/issues/93594">#93594</a>)</li> <li><a href="https://github.com/vercel/next.js/commit/fa787399b38d9aa702118f9bd23a8315b9f0ecc6"><code>fa78739</code></a> Turbopack: Fix middleware matcher suffix (<a href="https://redirect.github.com/vercel/next.js/issues/93590">#93590</a>)</li> <li><a href="https://github.com/vercel/next.js/commit/36e62c6eb7813e42d409eb487f93b829f4ad77e8"><code>36e62c6</code></a> [backport] Turbopack: more strict vergen setup (<a href="https://redirect.github.com/vercel/next.js/issues/93588">#93588</a>)</li> <li><a href="https://github.com/vercel/next.js/commit/36589b5db512b7704cdadd873cbe49b6dbcc9261"><code>36589b5</code></a> [backport][test] Pin package manager to patch versions (<a href="https://redirect.github.com/vercel/next.js/issues/93596">#93596</a>)</li> <li>See full diff in <a href="https://github.com/vercel/next.js/compare/v15.5.16...v15.5.18">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> |
||
|
|
e8508b2d90 |
fix: recover chatd from poisoned chain anchor on retry (#25097)
When OpenAI's Responses API returns `Previous response with id ... not found` for a chained turn, classify it as a `ChainBroken` retry, clear `previous_response_id`, exit chain mode, reload full history, and let `chatretry` retry. Self-heals chats whose anchor was poisoned before #25074 stopped truncated streams from being persisted as a successful turn with a stored response id. The new state is exposed via the existing `coderd_chatd_stream_retries_total` counter as a `chain_broken="true"|"false"` label. Aggregating queries (`sum`, `rate` over `provider`/`model`/`kind`) keep working without changes; raw-series matchers without aggregation will now see two series per `(provider, model, kind)` where they previously saw one. The metric is internal-only so the blast radius should be small, but if you have dashboards that index by exact label matchers without aggregation they will need an extra `sum` or an explicit `chain_broken` selector. > 🤖 This PR was created with the help of Coder Agents, and was reviewed by a human 🧑💻 |
||
|
|
c2dfaa406a |
fix(site): enlarge checkbox click target in workspace and task tables (#24739)
Fixes a UX issue where clicking near (but not exactly on) the bulk-action checkbox in the Workspaces or Tasks table would navigate to the workspace/task page instead of toggling the checkbox. Clicking back then clears all previous selections. ## Changes Wraps each row checkbox in a `div` that: - Calls `e.stopPropagation()` on `click` and `keydown` so near-miss clicks toggle the checkbox instead of navigating. - Uses `h-[72px]` to fill the full row height for vertical coverage. - Uses `pr-4 -mr-4` to extend the safe zone to the right without shifting layout. - Sets `cursor-default` so the pointer hand does not appear in the safe zone. Applied to both: - `WorkspacesTable.tsx` (workspaces page) - `TasksTable.tsx` (tasks page) > This PR was authored by Coder Agents. |
||
|
|
0a17660691 |
chore: bump next from 15.5.15 to 15.5.16 in /offlinedocs (#25131)
Bumps [next](https://github.com/vercel/next.js) from 15.5.15 to 15.5.16. <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/vercel/next.js/releases">next's releases</a>.</em></p> <blockquote> <h2>v15.5.16</h2> <p>This release contains security fixes for the following advisories:</p> <p>High:</p> <ul> <li><a href="https://github.com/vercel/next.js/security/advisories/GHSA-8h8q-6873-q5fj">GHSA-8h8q-6873-q5fj: Denial of Service with Server Components</a></li> <li><a href="https://github.com/vercel/next.js/security/advisories/GHSA-267c-6grr-h53f">GHSA-267c-6grr-h53f: Middleware / Proxy bypass in App Router applications via segment-prefetch routes</a></li> <li><a href="https://github.com/vercel/next.js/security/advisories/GHSA-mg66-mrh9-m8jx">GHSA-mg66-mrh9-m8jx: Denial of Service via connection exhaustion in applications using Cache Components</a></li> <li><a href="https://github.com/vercel/next.js/security/advisories/GHSA-492v-c6pp-mqqv">GHSA-492v-c6pp-mqqv: Middleware / Proxy bypass through dynamic route parameter injection</a></li> <li><a href="https://github.com/vercel/next.js/security/advisories/GHSA-c4j6-fc7j-m34r">GHSA-c4j6-fc7j-m34r: Server-side request forgery in applications using WebSocket upgrades</a></li> <li><a href="https://github.com/vercel/next.js/security/advisories/GHSA-36qx-fr4f-26g5">GHSA-36qx-fr4f-26g5: Middleware / Proxy bypass in Pages Router applications using i18n</a></li> </ul> <p>Moderate:</p> <ul> <li><a href="https://github.com/vercel/next.js/security/advisories/GHSA-ffhc-5mcf-pf4q">GHSA-ffhc-5mcf-pf4q: Cross-site scripting in App Router applications using CSP nonces</a></li> <li><a href="https://github.com/vercel/next.js/security/advisories/GHSA-gx5p-jg67-6x7h">GHSA-gx5p-jg67-6x7h: Cross-site scripting in beforeInteractive scripts with untrusted input</a></li> <li><a href="https://github.com/vercel/next.js/security/advisories/GHSA-h64f-5h5j-jqjh">GHSA-h64f-5h5j-jqjh: Denial of Service in the Image Optimization API</a></li> <li><a href="https://github.com/vercel/next.js/security/advisories/GHSA-wfc6-r584-vfw7">GHSA-wfc6-r584-vfw7: Cache poisoning in React Server Component responses</a></li> </ul> <p>Low:</p> <ul> <li><a href="https://github.com/vercel/next.js/security/advisories/GHSA-vfv6-92ff-j949">GHSA-vfv6-92ff-j949: Cache poisoning via collisions in React Server Component cache-busting</a></li> <li><a href="https://github.com/vercel/next.js/security/advisories/GHSA-3g8h-86w9-wvmq">GHSA-3g8h-86w9-wvmq: Middleware / Proxy redirects can be cache-poisoned</a></li> </ul> </blockquote> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/vercel/next.js/commit/ad6fd4e50e5aba20b60d283c42b89273a3167ccd"><code>ad6fd4e</code></a> v15.5.16</li> <li><a href="https://github.com/vercel/next.js/commit/79d7dff1448483f0c8f187f98887b31019f6e494"><code>79d7dff</code></a> Ignore malformed CSP nonce headers (<a href="https://redirect.github.com/vercel/next.js/issues/103">#103</a>)</li> <li><a href="https://github.com/vercel/next.js/commit/c4f69086cc8dcbd81b1dbc321c98ea874d90d6f8"><code>c4f6908</code></a> router-server: guard upgrade proxy against absolute-url SSRF (<a href="https://redirect.github.com/vercel/next.js/issues/77">#77</a>) (<a href="https://redirect.github.com/vercel/next.js/issues/102">#102</a>)</li> <li><a href="https://github.com/vercel/next.js/commit/6c72e0b4ee096643b42c742f35e0de84c41d190d"><code>6c72e0b</code></a> Fix i18n middleware matching for default-locale data routes (<a href="https://redirect.github.com/vercel/next.js/issues/82">#82</a>) (<a href="https://redirect.github.com/vercel/next.js/issues/100">#100</a>)</li> <li><a href="https://github.com/vercel/next.js/commit/3e247110b33f3bee3d05cfbac342581051cdf405"><code>3e24711</code></a> fix: add explicit checks for RSC header (<a href="https://redirect.github.com/vercel/next.js/issues/83">#83</a>) (<a href="https://redirect.github.com/vercel/next.js/issues/99">#99</a>)</li> <li><a href="https://github.com/vercel/next.js/commit/25926510f8d3223a447f2e37a56a7686f9190ef2"><code>2592651</code></a> fix proxy matching for segment prefetch URLs (<a href="https://redirect.github.com/vercel/next.js/issues/89">#89</a>) (<a href="https://redirect.github.com/vercel/next.js/issues/97">#97</a>)</li> <li><a href="https://github.com/vercel/next.js/commit/73de04589560027c14d6ab579392297828ceec71"><code>73de045</code></a> Strip next-resume header from incoming requests (<a href="https://redirect.github.com/vercel/next.js/issues/93">#93</a>)</li> <li><a href="https://github.com/vercel/next.js/commit/086dfa7f8fd284646266d8c757c9ab59b2ce1a43"><code>086dfa7</code></a> Escape properties for beforeInteractive scripts (15.5) (<a href="https://redirect.github.com/vercel/next.js/issues/87">#87</a>)</li> <li><a href="https://github.com/vercel/next.js/commit/87080764c96f5416decccd43f4c434545fd5d4e1"><code>8708076</code></a> fix: skip internal param normalization in unsupported environments</li> <li><a href="https://github.com/vercel/next.js/commit/ebc1a54e7c0692486b69ea0760afea8508d110a6"><code>ebc1a54</code></a> [15.x] Type hardening and performance improvements (<a href="https://redirect.github.com/vercel/next.js/issues/81">#81</a>)</li> <li>Additional commits viewable in <a href="https://github.com/vercel/next.js/compare/v15.5.15...v15.5.16">compare view</a></li> </ul> </details> <details> <summary>Maintainer changes</summary> <p>This version was pushed to npm by <a href="https://www.npmjs.com/~GitHub%20Actions">GitHub Actions</a>, a new releaser for next since your current version.</p> </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> |
||
|
|
c1c3b9784e |
chore: bump github.com/go-git/go-git/v5 from 5.18.0 to 5.19.0 (#25124)
Bumps [github.com/go-git/go-git/v5](https://github.com/go-git/go-git) from 5.18.0 to 5.19.0. <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/go-git/go-git/releases">github.com/go-git/go-git/v5's releases</a>.</em></p> <blockquote> <h2>v5.19.0</h2> <h2>What's Changed</h2> <ul> <li>build: Update module github.com/go-git/go-git/v5 to v5.18.0 [SECURITY] (releases/v5.x) by <a href="https://github.com/go-git-renovate"><code>@go-git-renovate</code></a>[bot] in <a href="https://redirect.github.com/go-git/go-git/pull/2010">go-git/go-git#2010</a></li> <li>v5: Bump sha1cd and go-billy by <a href="https://github.com/pjbgf"><code>@pjbgf</code></a> in <a href="https://redirect.github.com/go-git/go-git/pull/2060">go-git/go-git#2060</a></li> <li>v5: Align object encoding with upstream by <a href="https://github.com/pjbgf"><code>@pjbgf</code></a> in <a href="https://redirect.github.com/go-git/go-git/pull/2065">go-git/go-git#2065</a></li> </ul> <p><strong>Full Changelog</strong>: <a href="https://github.com/go-git/go-git/compare/v5.18.0...v5.19.0">https://github.com/go-git/go-git/compare/v5.18.0...v5.19.0</a></p> </blockquote> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/go-git/go-git/commit/bc930f4cbe095a3e1d49273655f73fcef7d41a42"><code>bc930f4</code></a> Merge pull request <a href="https://redirect.github.com/go-git/go-git/issues/2065">#2065</a> from go-git/commit-v5</li> <li><a href="https://github.com/go-git/go-git/commit/d315264343cead712aa9eb56475c2ec96f5ecef1"><code>d315264</code></a> plumbing: object, Reset object before decode</li> <li><a href="https://github.com/go-git/go-git/commit/6e1d34890a4dae8a0df738e531234bd60b7e9b66"><code>6e1d348</code></a> plumbing: object, Align Tree handling with upstream</li> <li><a href="https://github.com/go-git/go-git/commit/e134ba34cf95ed0167e5b1df36a933d7bde9d02d"><code>e134ba3</code></a> tests: Skip double checks in Git v2.11</li> <li><a href="https://github.com/go-git/go-git/commit/1971422f6b1bec9176061b3293306981cfff981e"><code>1971422</code></a> tests: Add git conformance tests for signing verification</li> <li><a href="https://github.com/go-git/go-git/commit/a387aa8857a8fbba8e74b7f5485e9e030669ab5d"><code>a387aa8</code></a> plumbing: object, Add ErrMalformedTag</li> <li><a href="https://github.com/go-git/go-git/commit/f415670d906b5c6169d1fdc64f3f9f1d33eb6f9c"><code>f415670</code></a> plumbing: object, Decode Tag headers via a state machine</li> <li><a href="https://github.com/go-git/go-git/commit/5b0cd38a62e2336bb5f1a2ad0eb8ac8f9e7b740e"><code>5b0cd38</code></a> plumbing: object, Reject multi-signature commits at Verify</li> <li><a href="https://github.com/go-git/go-git/commit/fe8ed6223a6079d9fd84d853362a996e7df175fb"><code>fe8ed62</code></a> plumbing: object, Align Tag.EncodeWithoutSignature with Commit</li> <li><a href="https://github.com/go-git/go-git/commit/98e337d5bdc4c0536a40ab7381b2231f7e0b15cd"><code>98e337d</code></a> plumbing: object, Add support for Tag.SignatureSHA256</li> <li>Additional commits viewable in <a href="https://github.com/go-git/go-git/compare/v5.18.0...v5.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) 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> |
||
|
|
85792d08bc |
feat: add harness engineering layer for agent workflows (#24791)
This PR adds an opinionated harness-engineering layer for agent-driven workflows: a small set of agent-readable docs, mechanical structure checks, structured CI failure summaries, an architecture-lint umbrella, and per-worktree dev-server isolation. The goal is to make local dev, tests, and CI mechanically inspectable by agents without changing app runtime behavior. ## What landed **Agent docs and navigation** - `.claude/docs/OBSERVABILITY.md`, `.claude/docs/DEV_ISOLATION.md`, `.claude/docs/AGENT_FAILURES.md`: task-oriented guides for logs, tracing, Prometheus, dev-server isolation, and a seeded failure catalog. - `AGENTS.md`: added an `Agent navigation` block, then trimmed the file from 375 to 229 lines by migrating duplicated detail into `WORKFLOWS.md`, `GO.md`, `TESTING.md`, and `DATABASE.md`. The user-managed custom-instructions block is preserved. - `.agents/docs`: symlink mirror of `.claude/docs` for agent runtimes that look under `.agents`. **Mechanical checks** - `scripts/check_agents_structure.sh`: validates `@...` references in tracked `AGENTS.md` files and warns when root grows past 600 lines. Wired as `make lint/agents` and into `make lint`. - `scripts/audit-agent-readiness.sh`: report-first audit of harness readiness. Currently `10 ok, 0 warn, 0 fail`. - `scripts/check_architecture.sh` / `make lint/architecture`: umbrella architecture-lint target. Consolidates the existing `check_enterprise_imports.sh` and `check_codersdk_imports.sh` so they run exactly once via the umbrella. Slot is open for new high-confidence rules. **Structured CI failure summaries** - `scripts/playwright-failure-summary.sh`: parses `site/test-results/results.json` and writes Markdown to `$GITHUB_STEP_SUMMARY` on failure. Wired into the `test-e2e` matrix job. - `scripts/go-test-failure-summary.sh`: parses `go test -json` line-delimited output the same way. Wired into `test-go-pg`, `test-go-pg-17`, and `test-go-race-pg` by injecting `gotestsum --jsonfile` in the workflow without touching `Makefile`. JSON also uploaded as a CI artifact on failure. - `site/e2e/playwright.config.ts`: enables `screenshot: only-on-failure`, `trace: retain-on-failure`, JSON reporter, and HTML reporter alongside existing reporters. - `.github/workflows/ci.yaml`: failure artifact uploads for Playwright now use `if: failure()` and predictable names (`playwright-artifacts-<variant>-<sha>`). **Per-worktree dev-server isolation** (`scripts/develop/main.go`) - Deterministic FNV-64a hash of the worktree path produces a port offset in `[0, 1000)` (50 buckets, step 20 to avoid API/proxy overlap across adjacent buckets). - Offset is applied only to defaults; both env vars (`CODER_DEV_PORT`, `CODER_DEV_WEB_PORT`, `CODER_DEV_PROXY_PORT`, `CODER_DEV_PROMETHEUS_PORT`) and CLI flags retain priority. - Hardcoded ports `9090` (embedded Prometheus UI) and `12345` (Delve) are unchanged by design. - Startup banner shows each port's source: `default`, `offset`, or `explicit`. - Unit tests in `scripts/develop/main_test.go` cover determinism, bounds, no-overlap across the four ports, and explicit-skip behavior. - State (`.coderv2/`) was already worktree-isolated via `os.Getwd()`, so no state-dir changes were needed. ## Validation `make lint/agents`, `make lint/architecture`, `make lint/emdash`, `bash scripts/audit-agent-readiness.sh` (10 ok, 0 warn, 0 fail), `shellcheck` on all 5 new scripts, `go test ./scripts/develop/...`, and `js-yaml` parse of `ci.yaml` all pass. Synthetic fixtures verify both failure-summary scripts handle empty/missing input (silent exit 0), ANSI-stripped output, and parent/subtest formatting. ## Known follow-ups (deferred) - Frontend Storybook/Vitest failure summary: lowest-leverage slice of the failure-summary work. Skipping until observed pain. - Architecture lint currently only delegates to existing import checks; new rules (`InTx` outer-store detection, swagger-annotation lint) plug in as needed. - 50 port-offset buckets means two worktree paths can occasionally collide. The DEV_ISOLATION doc tells users to set the relevant env var when this happens. > Mux opened this PR on Mike's behalf. |
||
|
|
915956460a |
feat(coderd/x/chatd): add compact turn status labels (#25043)
> Mux is acting on Mike's behalf. Changes chat turn-end summaries into compact status labels for the cached `last_turn_summary` and successful web push body. Uses a structured-output model call for successful turns, requiring a 2-5 word `label` and validating it to reject agent-centric phrasing. Pending and requires-action states keep deterministic status labels. Removes the earlier deterministic tool-signal pipeline in favor of the smaller structured-output path. |
||
|
|
b221632615 |
fix: wipe user secrets when user is soft-deleted (#24985)
Extend the delete_deleted_user_resources() trigger so that secrets belonging to a soft-deleted user are removed in the same transaction as the existing api_keys and user_links cleanup. user_secrets.user_id has ON DELETE CASCADE, but Coder soft-deletes users by flipping users.deleted rather than removing the row, so the foreign key cascade never fires and secrets would otherwise survive deletion. Assisted by Coder Agents. |
||
|
|
81e2be69e9 |
test: use typed atomics in test files (#25071)
Use typed atomics (atomic.Int64, atomic.Int32, etc.) in test files to prevent mixing atomic and non-atomic access on the same value, guarantee 64-bit alignment on 32-bit platforms, and provide a cleaner API. |
||
|
|
a1dbd758bc | feat: add template builder deployment config and telemetry types (#25082) | ||
|
|
67aa625579 |
chore: add coder-agents-review skill (#25121)
## Summary - Adds the `coder-agents-review` agent skill that drives PRs through the `coder-agents-review` GitHub app review loop - The skill automates: triggering review, waiting for feedback, fixing issues, validating, and re-requesting until approved ## Test plan - [ ] Verify the skill file is well-formed and the loop instructions are correct - [ ] Test triggering the skill on a PR with `/coder-agents-review` Made with [Cursor](https://cursor.com) --------- Co-authored-by: Cursor <cursoragent@cursor.com> |
||
|
|
abe9f44e03 |
chore: add coder agents review (#25088)
Added a coder-agents-review skill covering: - when to request review - how to paginate app activity before deriving state - how to require exact app identity and explicit approval evidence > Mux is acting on Mike's behalf. |
||
|
|
ca6450cf94 |
fix(agent): gate MCP tool discovery on startup (#25034)
The first `/mcp/tools` request could race workspace startup and return an empty tool list before startup scripts had a chance to write `.mcp.json`. Chatd may only discover tools once for a turn, so that empty response could hide workspace MCP tools even though the agent loaded them later. Make the manager wait for startup to settle before treating missing MCP config files as a real empty state. Tool listing now goes through one manager-owned path that starts reload work independently of caller cancellation; caller contexts only bound that caller's wait. After the first reload body settles, transient reload errors return cached tools with the error so the HTTP handler can degrade to the last known tool set instead of returning `[]`. The handler is intentionally thin: it asks the manager for tools, logs any degraded path, and still returns the tool response shape callers already expect. Tests cover startup gating, caller-canceled waits, manager close, reload timeout via quartz, and cached-tool fallback after a later reload error. |
||
|
|
4a6756a3e8 | fix: isolate test HTTP clients (#25038) | ||
|
|
febabfb8b2 |
feat: add request/response dump support to aibridgeproxyd (#24837)
Closes https://github.com/coder/coder/issues/24335 |
||
|
|
fb60bb0c08 |
chore(coderd/x/chatd): instrument PromoteQueued + stream subscriber for ENG-2645 (#25085)
TestPromoteQueuedWhileRequiresActionMixedTools has flaked three times across Windows and Ubuntu CI runners since 2026-05-06; local repro on the dev workspace has not surfaced it. The May 8 Ubuntu log shows all four PromoteQueued post-TX pubsub publishes reaching pg_notify, yet the test still times out 25s later, so the failure is downstream between the subscriber's listener and the test's events channel. Adds three Debug-level markers in chatd.go (no logic change) plus two t.Logf markers in the test's reader so the next CI occurrence pins down exactly which step failed. Closes ENG-2645 Closes coder/internal#1523 |
||
|
|
063c06ca5f |
test: prevent expired contexts in chatd parallel subtests (#25107)
Parallel subtests in `coderd/x/chatd` reused a parent test context with a `testutil.WaitLong` deadline, so the context could expire before a subtest was scheduled under load. That made the subagent lifecycle tools return plain-text context errors instead of the expected JSON payload, causing flaky JSON unmarshal failures. Create fresh `chatdTestContext` values inside the affected parallel subtests and add `chatdTestContext` to the `paralleltestctx` custom function list so this pattern is caught by `make lint`. Closes https://github.com/coder/internal/issues/1494 |
||
|
|
bd6cc1aaf2 |
feat(coderd): add stop_workspace chatd tool and recovery classification (#24997)
## Summary Adds a `stop_workspace` tool to chatd so the model can recover from the "workspace running but agent dead" failure mode (e.g. an OOM that leaves the workspace running but the agent unreachable) by stopping and then starting the workspace. <img width="924" height="742" alt="image" src="https://github.com/user-attachments/assets/279dedb6-6e29-4fe1-8754-3a1f01e538bf" /> ## What changed **New `stop_workspace` chatd tool** (`coderd/x/chatd/chattool/stopworkspace.go`). Mirrors `start_workspace`: shares `WorkspaceMu` to serialize with create/start, waits for any in-progress build before issuing a stop, and is idempotent only after a successful Stop transition. Failed stop builds re-attempt rather than reporting success. **New `chatStopWorkspace` coderd hook** (`coderd/exp_chats.go`). Mirrors `chatStartWorkspace` minus the `RequireActiveVersion` gate. Stop should not be blocked by template version policy. **Differentiated recovery sentinels** (`coderd/x/chatd/chatd.go`). `errChatAgentDisconnected` instructs the model to call `stop_workspace` then `start_workspace`. `errChatDialTimeout` instructs a single retry, then user escalation if it repeats. The previous single message conflated transient and persistent failures. **Two-signal recovery gate.** Recovery is only surfaced when a tool call times out *and* a fresh DB read of the latest workspace agent says `Disconnected`. The previous draft escalated on the DB read alone, which would fire on a 30-second heartbeat blip (e.g. agent respawn) and prompt a destructive stop/start unnecessarily. **Cache-hit disconnected handling** now clears the cache and retries a fresh dial before escalating, rather than returning the recovery sentinel immediately. Latest-agent classification uses `GetWorkspaceAgentsInLatestBuildByWorkspaceID` instead of the chat's bound `AgentID`, so stale bindings after a rebuild don't misclassify. **Shared chattool helpers** in `coderd/x/chatd/chattool/chattool.go`: `latestWorkspaceBuildAndJob`, `publishBuildBinding`, `provisionerJobTerminal`. Applied to both `start_workspace` and `stop_workspace`. ## Notes - Reverts an earlier draft that widened `ask_user_question` to root standard turns. Plan-mode-only behavior is restored. - The `stop_workspace` tool currently renders via the generic chat tool-call UI. A follow-up frontend PR will prettify the `stop_workspace` tool and style it like the `start_workspace` tool. - Never-connected (`Timeout` status) agents are intentionally excluded from recovery. They indicate template or startup failure, not the running-but-dead case this PR targets. Closes CODAGT-315 |
||
|
|
cee504e8a0 |
docs: remove reference to defunct template creation wizard permission feature (#25104)
#11918 took away advanced settings during template creation however it did not clean up the documentation of a reference to customising the template permissions during template creation - https://coder.com/docs/admin/templates/template-permissions > By default the Everyone group is assigned to each template meaning any Coder user can use the template to create a workspace. To prevent this, disable the Allow everyone to use the template setting when creating a template. This setting is no longer present in Coder, so removing it from the docs. |
||
|
|
aaa0dacdb3 |
fix: infer workspace claim time from build history for /agents delete dialog (#25057)
Closes [CODAGT-317](https://linear.app/codercom/issue/CODAGT-317/pr-workspaces-sometimes-require-name-confirmation-to-delete). ## Problem The `/agents` archive-and-delete molly-guard (typing the workspace name) was firing for chats that had clearly created their own workspace. The heuristic in `resolveArchiveAndDeleteAction` decides whether confirmation is needed by comparing the workspace's `created_at` against the chat's `created_at`: ```ts return new Date(workspaceCreatedAt) >= new Date(chatCreatedAt); ``` That assumption breaks for **prebuilt workspaces**. `ClaimPrebuiltWorkspace` rewrites `owner_id`, `name`, `updated_at`, `last_used_at`, etc., but **never touches `created_at`**, which still reflects when the prebuild was provisioned by the reconciler, often hours before the chat exists. Result: every prebuild-claimed workspace looks pre-existing, so the molly-guard fires. Concrete example from a real chat: | Field | Value | |---|---| | `chat.created_at` | `2026-05-07T15:12:23Z` | | `workspace.created_at` (provision) | `2026-05-07T14:22:24Z` | | `latest_build.created_at` (claim) | `2026-05-07T15:19:09Z` | `14:22:24 < 15:12:23` so `isWorkspaceAutoCreated` returned false even though the chat issued the claim. ## Fix (frontend-only) Derive the moment a workspace was acquired from existing build history rather than relying on `workspace.created_at`: - Build #1 initiator = prebuilds system user → workspace was a prebuild → use `build_2.created_at` (the claim build) as the acquisition time. - Build #1 initiator = real user → workspace was created from scratch → use `workspace.created_at` (unchanged behavior). - Unclaimed prebuild or no build history → return `null` (force confirmation; safe degradation for a destructive flow). The resolver fetches the build list via the existing `getWorkspaceBuilds` endpoint when the dialog might fire. No new column, no migration, no schema change. Works retroactively for all existing claimed prebuilds; no backfill needed. The prebuilds system user UUID is exposed via `codersdk.PrebuildsSystemUserID` and typegen'd to `typesGenerated.ts`. `coderd/database.PrebuildsSystemUserID` parses that constant via `uuid.MustParse` so the two cannot drift; if the codersdk literal ever changes, package init fails fast. ## History The first draft of this PR added a `workspaces.claimed_at` column populated by `ClaimPrebuiltWorkspace`. After review feedback from @johnstcn pointing out that the same fact is already implicit in build history, I pivoted to the frontend-only approach. Subsequent review notes consolidated the prebuilds system user UUID into a single typegen'd constant. ## Why not the other open PRs - **#25055** (`chatKey` cache fallback) only fixes a different cache-miss path; it explicitly notes it does not address `created_at < chat.created_at`. - **#25053** (`chats.workspace_auto_created` boolean) puts the truth on the wrong side of the schema: "this workspace was claimed at time T" is a property of the workspace, not the chat. The MCP plumbing it adds is also unnecessary now that the same answer is available from build history. ## Test plan - `pnpm vitest run --project=unit src/pages/AgentsPage/utils/agentWorkspaceUtils.test.ts` — 40/40 pass; new cases cover prebuild claim before/after chat, unclaimed prebuild, missing-build-history fallback, and the fetch-skip when the chat is not in cache. - `pnpm lint:types`, `pnpm check`, `make pre-commit`. <details> <summary>Disclosure</summary> Opened on behalf of @kylecarbs by [Coder Agents](https://coder.com/coder-agents). </details> |
||
|
|
4124d1137d |
feat: add ai_model_prices table (#24932)
# Summary Implements https://linear.app/codercom/issue/AIGOV-282/add-ai-model-price-table-and-seed-generator This PR lays the groundwork for AI Bridge cost controls (per the AI Governance RFC). It adds the foundation needed for future cost tracking: a place to store per-model token prices, a way to keep those prices in sync with upstream pricing data, and a startup mechanism that ensures every deployment has prices loaded before AI Bridge starts processing requests. The price data comes from [models.dev](https://models.dev/), a community-maintained catalogue of AI provider pricing. A generator script fetches the latest prices, filters to Anthropic and OpenAI for now, and produces a seed file checked into the repository. On every server startup the seed is applied to the database, so new releases automatically pick up any price corrections that landed since the previous one. Existing rows are overwritten with the latest prices; rows for models no longer in the seed are left untouched. # Batching the AI model price seed: three approaches Context: at server startup we seed the `ai_model_prices` table from an embedded JSON price book (~70 rows today, will grow as we add providers, potentially 4000+). Each row is: ```text (provider, model, input_price, output_price, cache_read_price, cache_write_price) ``` Any of the four price columns can be: - `NULL` → “price unknown for this dimension” - explicit `0` → “free” The batch must be an UPSERT so re-running is idempotent and existing rows pick up new prices. We considered three implementations. --- ## Approach 1 — Per-row UPSERT in a Go loop ```go for _, row := range rows { if err := db.UpsertAIModelPrice(ctx, database.UpsertAIModelPriceParams{ Provider: row.Provider, Model: row.Model, InputPrice: nullInt64(row.InputPrice), // ... }); err != nil { return err } } ``` ### Pros - Trivial. - NULL handling falls out naturally from `sql.NullInt64`. ### Cons - `N` round-trips per seed. - With ~70 rows that means ~70 statement executions on every startup, even inside a transaction. - Doesn't scale gracefully as the price book grows, potentially 4000+. --- ## Approach 2 — `UNNEST` with parallel arrays Pass each column as a separate Go slice. Postgres unnests them in parallel into a virtual table, then `INSERT ... SELECT`. ```sql INSERT INTO ai_model_prices ( provider, model, input_price, output_price, cache_read_price, cache_write_price ) SELECT UNNEST(@providers::text[]), UNNEST(@models::text[]), NULLIF(UNNEST(@input_prices::bigint[]), -1), NULLIF(UNNEST(@output_prices::bigint[]), -1), NULLIF(UNNEST(@cache_read_prices::bigint[]), -1), NULLIF(UNNEST(@cache_write_prices::bigint[]), -1) ON CONFLICT (provider, model) DO UPDATE SET input_price = EXCLUDED.input_price, output_price = EXCLUDED.output_price, cache_read_price = EXCLUDED.cache_read_price, cache_write_price = EXCLUDED.cache_write_price, updated_at = NOW(); ``` Go side: flatten rows into six parallel slices. Use a sentinel (`-1`) for “missing”, since `lib/pq` can't encode `NULL` into a `bigint[]` element. ```go providers := make([]string, len(rows)) models := make([]string, len(rows)) inputs := make([]int64, len(rows)) outputs := make([]int64, len(rows)) cacheR := make([]int64, len(rows)) cacheW := make([]int64, len(rows)) for i, r := range rows { providers[i] = r.Provider models[i] = r.Model inputs[i] = -1 if r.InputPrice != nil { inputs[i] = *r.InputPrice } outputs[i] = -1 if r.OutputPrice != nil { outputs[i] = *r.OutputPrice } cacheR[i] = -1 if r.CacheReadPrice != nil { cacheR[i] = *r.CacheReadPrice } cacheW[i] = -1 if r.CacheWritePrice != nil { cacheW[i] = *r.CacheWritePrice } } return db.UpsertAIModelPrices(ctx, database.UpsertAIModelPricesParams{ Providers: providers, Models: models, InputPrices: inputs, OutputPrices: outputs, CacheReadPrices: cacheR, CacheWritePrices: cacheW, }) ``` ### Pros - Single round-trip. ### Cons - The generated `sqlc` params become plain `[]int64`, which can't represent `NULL`. --- ## Approach 3 — `jsonb_array_elements` over a single `@seed::jsonb` (chosen) Pass the raw seed JSON as one parameter; let Postgres expand and parse it. ```sql INSERT INTO ai_model_prices ( provider, model, input_price, output_price, cache_read_price, cache_write_price ) SELECT elem->>'provider', elem->>'model', (elem->>'input_price')::bigint, (elem->>'output_price')::bigint, (elem->>'cache_read_price')::bigint, (elem->>'cache_write_price')::bigint FROM jsonb_array_elements(@seed::jsonb) AS elem ON CONFLICT (provider, model) DO UPDATE SET input_price = EXCLUDED.input_price, output_price = EXCLUDED.output_price, cache_read_price = EXCLUDED.cache_read_price, cache_write_price = EXCLUDED.cache_write_price, updated_at = NOW(); ``` Go side reduces to: ```go return db.UpsertAIModelPrices(ctx, seedJSON) ``` ### Pros - Single round-trip. - NULLs fall out naturally: - `(elem->>'cache_write_price')::bigint` becomes `NULL` - no sentinels - The seed is already JSON: - Existing precedent: - `jsonb_array_elements` is already used elsewhere in the codebase ### Cons - Less type-safe at the SQL boundary than `UNNEST` - Slightly less standard than `UNNEST` - Readers need familiarity with: - `jsonb_array_elements` - `->>` extraction syntax - Postgres pays JSON parse cost - negligible at our scale --- --- # Decision We picked Approach 3. It collapses the round-trips like `UNNEST` does, but without: - nullable-array workarounds - sentinel values |
||
|
|
638e2220e9 |
chore: refactor BuildIcon and remove useClassName (#25017)
|
||
|
|
8d919e5411 | chore: add storybook mcp (#25094) |