mirror of
https://github.com/coder/coder.git
synced 2026-10-24 11:43:39 +08:00
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.
This commit is contained in:
@@ -990,37 +990,6 @@ func (s *SSEAgentReinitReceiver) Receive(ctx context.Context) (*Reinitialization
|
||||
}
|
||||
}
|
||||
|
||||
// AddChatContextRequest is the request body for adding chat context.
|
||||
type AddChatContextRequest struct {
|
||||
// ChatID optionally identifies the chat to add context to.
|
||||
// If empty, auto-detection is used (CODER_CHAT_ID env, the
|
||||
// only active chat, or the only top-level active chat for this
|
||||
// agent).
|
||||
ChatID uuid.UUID `json:"chat_id,omitempty"`
|
||||
// Parts are the context-file and skill parts to add.
|
||||
Parts []codersdk.ChatMessagePart `json:"parts"`
|
||||
}
|
||||
|
||||
// AddChatContextResponse is the response for adding chat context.
|
||||
type AddChatContextResponse struct {
|
||||
ChatID uuid.UUID `json:"chat_id"`
|
||||
Count int `json:"count"`
|
||||
}
|
||||
|
||||
// ClearChatContextRequest is the request body for clearing chat context.
|
||||
type ClearChatContextRequest struct {
|
||||
// ChatID optionally identifies the chat to clear context from.
|
||||
// If empty, auto-detection is used (CODER_CHAT_ID env, the
|
||||
// only active chat, or the only top-level active chat for this
|
||||
// agent).
|
||||
ChatID uuid.UUID `json:"chat_id,omitempty"`
|
||||
}
|
||||
|
||||
// ClearChatContextResponse is the response for clearing chat context.
|
||||
type ClearChatContextResponse struct {
|
||||
ChatID uuid.UUID `json:"chat_id"`
|
||||
}
|
||||
|
||||
// RefreshChatContextResponse is the response for refreshing chat context.
|
||||
type RefreshChatContextResponse struct {
|
||||
// Refreshed is the number of drifted chats that were re-pinned to the
|
||||
@@ -1028,38 +997,6 @@ type RefreshChatContextResponse struct {
|
||||
Refreshed int `json:"refreshed"`
|
||||
}
|
||||
|
||||
// AddChatContext adds context-file and skill parts to an active chat.
|
||||
func (c *Client) AddChatContext(ctx context.Context, req AddChatContextRequest) (AddChatContextResponse, error) {
|
||||
res, err := c.SDK.Request(ctx, http.MethodPost, "/api/v2/workspaceagents/me/experimental/chat-context", req)
|
||||
if err != nil {
|
||||
return AddChatContextResponse{}, xerrors.Errorf("execute request: %w", err)
|
||||
}
|
||||
defer res.Body.Close()
|
||||
|
||||
if res.StatusCode != http.StatusOK {
|
||||
return AddChatContextResponse{}, codersdk.ReadBodyAsError(res)
|
||||
}
|
||||
|
||||
var resp AddChatContextResponse
|
||||
return resp, json.NewDecoder(res.Body).Decode(&resp)
|
||||
}
|
||||
|
||||
// ClearChatContext soft-deletes context-file and skill messages from an active chat.
|
||||
func (c *Client) ClearChatContext(ctx context.Context, req ClearChatContextRequest) (ClearChatContextResponse, error) {
|
||||
res, err := c.SDK.Request(ctx, http.MethodDelete, "/api/v2/workspaceagents/me/experimental/chat-context", req)
|
||||
if err != nil {
|
||||
return ClearChatContextResponse{}, xerrors.Errorf("execute request: %w", err)
|
||||
}
|
||||
defer res.Body.Close()
|
||||
|
||||
if res.StatusCode != http.StatusOK {
|
||||
return ClearChatContextResponse{}, codersdk.ReadBodyAsError(res)
|
||||
}
|
||||
|
||||
var resp ClearChatContextResponse
|
||||
return resp, json.NewDecoder(res.Body).Decode(&resp)
|
||||
}
|
||||
|
||||
// RefreshChatContext re-pins every drifted chat bound to this agent to the
|
||||
// agent's latest context snapshot, clearing their drift markers. It backs
|
||||
// the in-workspace `coder exp chat context refresh` (no chat argument),
|
||||
|
||||
@@ -137,11 +137,6 @@ type Chat struct {
|
||||
// the owner's read cursor, which updates on stream
|
||||
// connect and disconnect.
|
||||
HasUnread bool `json:"has_unread"`
|
||||
// LastInjectedContext holds the most recently persisted
|
||||
// injected context parts (AGENTS.md files and skills). It
|
||||
// is updated only when context changes, on first workspace
|
||||
// attach or agent change.
|
||||
LastInjectedContext []ChatMessagePart `json:"last_injected_context,omitempty"`
|
||||
// Context reports the chat's pinned workspace-context state and
|
||||
// whether it has drifted from the agent's latest pushed snapshot.
|
||||
// Nil when the chat has no pinned context yet.
|
||||
|
||||
Reference in New Issue
Block a user