mirror of
https://github.com/coder/coder.git
synced 2026-09-22 21:22:17 +08:00
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.
55 lines
1.4 KiB
Go
55 lines
1.4 KiB
Go
package chatd
|
|
|
|
import (
|
|
"strings"
|
|
|
|
"github.com/coder/coder/v2/codersdk"
|
|
)
|
|
|
|
// formatSystemInstructions builds the <workspace-context> block from
|
|
// agent metadata and zero or more context-file parts. Non-context-file
|
|
// parts in the slice are silently skipped.
|
|
func formatSystemInstructions(
|
|
operatingSystem, directory string,
|
|
parts []codersdk.ChatMessagePart,
|
|
) string {
|
|
hasContent := false
|
|
for _, part := range parts {
|
|
if part.Type == codersdk.ChatMessagePartTypeContextFile && part.ContextFileContent != "" {
|
|
hasContent = true
|
|
break
|
|
}
|
|
}
|
|
if !hasContent && operatingSystem == "" && directory == "" {
|
|
return ""
|
|
}
|
|
|
|
var b strings.Builder
|
|
_, _ = b.WriteString("<workspace-context>\n")
|
|
if operatingSystem != "" {
|
|
_, _ = b.WriteString("Operating System: ")
|
|
_, _ = b.WriteString(operatingSystem)
|
|
_, _ = b.WriteString("\n")
|
|
}
|
|
if directory != "" {
|
|
_, _ = b.WriteString("Working Directory: ")
|
|
_, _ = b.WriteString(directory)
|
|
_, _ = b.WriteString("\n")
|
|
}
|
|
for _, part := range parts {
|
|
if part.Type != codersdk.ChatMessagePartTypeContextFile || part.ContextFileContent == "" {
|
|
continue
|
|
}
|
|
_, _ = b.WriteString("\nSource: ")
|
|
_, _ = b.WriteString(part.ContextFilePath)
|
|
if part.ContextFileTruncated {
|
|
_, _ = b.WriteString(" (truncated to 64KiB)")
|
|
}
|
|
_, _ = b.WriteString("\n")
|
|
_, _ = b.WriteString(part.ContextFileContent)
|
|
_, _ = b.WriteString("\n")
|
|
}
|
|
_, _ = b.WriteString("</workspace-context>")
|
|
return b.String()
|
|
}
|