mirror of
https://github.com/coder/coder.git
synced 2026-09-23 05:43:53 +08:00
Adds the agent half of the workspace context sources RFC. The agent now resolves instruction files, skills, and MCP configs into a typed `Snapshot`, watches the relevant paths recursively, exposes the source list over a workspace-agent HTTP API, and pushes each `Snapshot` to coderd over a new `PushContextState` RPC on Agent API v2.10. The coderd-side handler is a stub returning `Unimplemented` for now. Real persistence to `workspace_agent_context`, chatd hydration on dirty events, and the `KindMCPServer` MCP provider are tracked by [CODAGT-569](https://linear.app/codercom/issue/CODAGT-569/enable-agent-api-v210-pushcontextstate-bump-currentminor-wire-coderd). This matches the pattern used for v2.7 `ReportBoundaryLogs` in [#21293](https://github.com/coder/coder/pull/21293), which bumped the version and shipped a stub server so the wire and client could iterate before the persistence layer landed. ## What ships ### agent/agentcontext (new package) - `Source`, `Resource` (kinds `instruction_file`, `skill`, `mcp_config`, `mcp_server` plus reserved `plugin`/`hook`/`subagent`/`command`), `ResourceStatus`, `Snapshot`, `ComputeAggregateHash`. - `Manager` owns the in-memory source list, performs the initial resolve synchronously in `NewManager`, runs a re-resolve/watcher loop in `Run`, exposes `AddSource`/`RemoveSource`/`Sources`/`HasSource`/`Snapshot`/`SubscribeChanges`/`Resync`/`SeedSources`/`Close`. - `Resolver` walks scan roots, classifies recognized files, enforces 64 KiB per-resource, 2 MiB aggregate, and 500-resource caps with `StatusOversize`/`StatusExcluded`/`StatusUnreadable`/`StatusInvalid` outcomes, skips `node_modules`/`vendor`/etc., validates symlink targets stay inside the scan root, stamps `SourcePath` on user-derived resources, and optionally pulls MCP server tool lists via an `MCPProvider` interface. MCP config resources ship metadata only (size, hash) so secrets in env blocks never leave the agent. - `Watcher` is a recursive `fsnotify` wrapper with a 250 ms debounce, dynamic arming of newly created directories, and an ENOSPC-tolerant degraded mode that no-ops further syncs until the manager resyncs explicitly. - HTTP API for `GET/POST /sources`, `GET/DELETE /sources/{path}`, `POST /resync` mounted at `/api/v0/context`. - `Pusher` interface plus `RunPush` goroutine with exponential backoff capped at 30 s. `DRPCPusher` adapts the generated `DRPCAgentClient210` to `Pusher` and translates `drpcerr.Unimplemented` to `ErrPushUnimplemented` so the push loop exits cleanly when talking to coderd deployments that have not enabled the real handler. ### agent/proto (v2.10) - New messages `ContextResource`, `PushContextStateRequest`, `PushContextStateResponse` and the `PushContextState` RPC on `service Agent`. - Generated `DRPCAgentClient210` interface and `codersdk/agentsdk.Client.ConnectRPC210` / `ConnectRPC210WithRole`. - `tailnet/proto.CurrentMinor` bumped from `9` to `10`. ### Agent wiring - `agent.Options.Client` declares both v2.9 and v2.10 connectors; `run()` dials with `ConnectRPC210WithRole`. - `apiConnRoutineManager` holds a `DRPCAgentClient210`. Existing v2.8 routines keep their narrower `DRPCAgentClient28` signature thanks to interface embedding. - `startAgentAPI210` is the v2.10 counterpart to `startAgentAPI` for routines that need the new client. The push context state routine uses it. - A `contextManager` is constructed in `agent.init()`, seeded from the existing `CODER_AGENT_EXP_*_DIRS` env vars, started in its own goroutine under `gracefulCtx`, and closed in `agent.Close`. - `handleManifest` calls `Manager.SeedSources` for sources rooted at the manifest directory, then `Resync` after `manifest.Swap`, so the snapshot reflects the workspace working directory immediately instead of waiting for the next filesystem event. - HTTP routes mounted at `/api/v0/context` when the manager is up. ### Coderd stub `coderd/agentapi/context.go` returns `drpcerr.Unimplemented` for `PushContextState`. The real handler that persists `workspace_agent_context` rows, hydrates chats, and emits dirty events lives in CODAGT-569. ## Tests 24 tests across `agent/agentcontext` cover types, paths, resolver behavior with file caps, skill containers, MCP secret omission, symlink target validation, the recursive watcher firing on real fsnotify events, manager source CRUD / `Resync` / `SeedSources` / `Run` lifetime, the HTTP API, the DRPC adapter, and the push retry / initial-flag / unimplemented paths. Passes `go test -race -count=2`. `TestAgent_ContextStatePushed` boots a full agent against `agenttest.FakeAgentAPI` (which now records `PushContextState` traffic) and asserts the seeded `AGENTS.md` appears in a snapshot push with `schema_version = 1`. <details> <summary>Notes for reviewers</summary> - Source CRUD is workspace-agent-token only; coderd is not in the path for source mutation. - Per-resource cap 64 KiB, aggregate 2 MiB, count cap 500; resources past the cap ship with `StatusExcluded` and an empty payload so the aggregate hash still detects content edits. MCP-emitted resources enforce both a per-provider count cap and the aggregate byte cap. - Symlinks inside the scan root are followed; symlinks pointing outside (or broken) are rejected with `StatusExcluded` so credentials reachable via a stray symlink stay off the wire. - The initial push gates `lifecycle = ready` in the eventual full design. For this PR the `SeedSources` plus `handleManifest`-driven `Resync` keeps the snapshot fresh; the live push loop ships now and DRPCPusher translates the coderd `Unimplemented` stub into a clean exit. - The `PLUGIN`/`HOOK`/`SUBAGENT`/`COMMAND` kinds are reserved in proto and Go enums but unused; the Claude Code plugin resolver ships in a follow-up that does not need a schema migration. - Two follow-ups remain, both tracked by [CODAGT-569](https://linear.app/codercom/issue/CODAGT-569/enable-agent-api-v210-pushcontextstate-bump-currentminor-wire-coderd): (1) the chatd-side handler that persists snapshots and dirties chats; (2) the `coder exp chat context` CLI command set for `list`/`show`/`add`/`remove`/`refresh`. </details> _This PR was authored by Coder Agents on Kyle Carberry's behalf._
90 lines
3.3 KiB
Go
90 lines
3.3 KiB
Go
package proto
|
|
|
|
import (
|
|
"github.com/coder/coder/v2/apiversion"
|
|
)
|
|
|
|
// Version history:
|
|
//
|
|
// API v1:
|
|
// - retroactively applied name for the HTTP Rest APIs for the Agent and the
|
|
// JSON over websocket coordination and DERP Map APIs for Tailnet
|
|
//
|
|
// API v2.0:
|
|
// - Shipped in Coder v2.8.0
|
|
// - first dRPC over yamux over websocket APIs for tailnet and agent
|
|
//
|
|
// API v2.1:
|
|
// - Shipped in Coder v2.12.0
|
|
// - Added support for multiple banners via the GetAnnouncementBanners RPC on
|
|
// the Agent API.
|
|
// - No changes to the Tailnet API.
|
|
//
|
|
// API v2.2:
|
|
// - Shipped in Coder v2.13.0
|
|
// - Added support for network telemetry via the PostTelemetry RPC on the
|
|
// Tailnet API.
|
|
// - No changes to the Agent API.
|
|
//
|
|
// API v2.3:
|
|
// - Shipped in Coder v2.18.0
|
|
// - Added support for client Resume Tokens on the Tailnet API via the
|
|
// RefreshResumeToken RPC. (This actually shipped in Coder v2.15.0, but we
|
|
// forgot to increment the API version. If you dial for API v2.2, you MAY
|
|
// be connected to a server that supports RefreshResumeToken, but be
|
|
// prepared to process "unsupported" errors.)
|
|
// - Added support for WorkspaceUpdates RPC on the Tailnet API.
|
|
// - Added support for ScriptCompleted RPC on the Agent API. (This actually
|
|
// shipped in Coder v2.16.0, but we forgot to increment the API version. If
|
|
// you dial for API v2.2, you MAY be connected to a server that supports
|
|
// ScriptCompleted, but be prepared to process "unsupported" errors.)
|
|
//
|
|
// API v2.4:
|
|
// - Shipped in Coder v2.20.0
|
|
// - Added support for GetResourcesMonitoringConfiguration and
|
|
// PushResourcesMonitoringUsage RPCs on the Agent API.
|
|
// - Added support for reporting connection events for auditing via the
|
|
// ReportConnection RPC on the Agent API.
|
|
//
|
|
// API v2.5:
|
|
// - Shipped in Coder v2.23.0
|
|
// - Added `ParentId` to the agent manifest.
|
|
//
|
|
// API v2.6:
|
|
// - Shipped in Coder v2.24.0
|
|
// - Added support for CreateSubAgent RPC on the Agent API.
|
|
// - Added support for DeleteSubAgent RPC on the Agent API.
|
|
// - Added support for ListSubAgents RPC on the Agent API.
|
|
// - Add ORGANIZATION SharingLevel
|
|
//
|
|
// API v2.7:
|
|
// - Added support for ReportBoundaryLogs RPC on the Agent API for forwarding
|
|
// boundary audit logs to coderd.
|
|
//
|
|
// API v2.8:
|
|
// - Added support for pre-created sub agents on the Agent API.
|
|
// - Added support for UpdateAppStatus on the Agent API.
|
|
//
|
|
// API v2.9:
|
|
// - Added session_id and confined_process fields to
|
|
// ReportBoundaryLogsRequest on the Agent API.
|
|
// - Added sequence_number field to BoundaryLog on the Agent API.
|
|
//
|
|
// API v2.10:
|
|
// - Added PushContextState RPC on the Agent API for pushing
|
|
// resolved workspace context snapshots (instruction files,
|
|
// skills, MCP configs, MCP server tool lists) from the
|
|
// agent to coderd. Adds ContextResource, PushContextStateRequest,
|
|
// and PushContextStateResponse messages. The coderd handler
|
|
// ships as a stub returning Unimplemented; the agent push
|
|
// loop shuts down cleanly on that response so older coderd
|
|
// deployments remain interoperable. Real persistence,
|
|
// KindMCPServer provider, and chatd hydration land in
|
|
// CODAGT-569.
|
|
const (
|
|
CurrentMajor = 2
|
|
CurrentMinor = 10
|
|
)
|
|
|
|
var CurrentVersion = apiversion.New(CurrentMajor, CurrentMinor)
|