This repository has been archived on 2026-07-17. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
codespace/plan.md
T
tao.chen 79292c9f38 docs: update plan.md
Remove completed sections (shadcn migration, ACP panel integration, all
related out-of-scope items that landed in v1). Add the new task
'AcpPanel tool-call block UI (session/update tool_call type)' as the
next phase: forward tool_call events through the stream, store them
in history, render them as collapsible blocks above the agent's
text bubble.
2026-07-06 17:19:28 +08:00

82 lines
5.6 KiB
Markdown

# Plan
Roadmap for the next phases of the codespace web IDE.
## Next: AcpPanel tool-call block UI
When the agent invokes a tool (e.g. reads a file, runs a command, edits a buffer) it emits a `session/update` notification with `sessionUpdate: "tool_call"`. Currently the client silently drops these in `handleNotification` (debug log only), so the user has no visibility into what the agent is doing while the reply streams in. Render them as discrete blocks under the agent bubble so the user can see "the agent read foo.go, ran `git status`, is now editing bar.go…".
### Why
Without tool-call visibility, the streamed agent reply is just text. The user has to guess what the agent is doing. Real coding agents (Claude Code, Cursor, Zed) show tool invocations inline so the user can:
- See which files the agent touched.
- Catch mistakes early (agent edited the wrong file).
- Trust the agent's progress during long-running work.
### Scope
1. **Backend: forward tool_call events through the stream**
- In `internal/acp/handleNotification`, when `sessionUpdate == "tool_call"`, emit a `StreamEvent` to all active stream consumers:
```go
case StreamEvent{Type: "tool_call", ToolCallID: ..., Kind: ..., Title: ..., Status: ..., Content: ...}
```
- Also append a stable representation of the tool call to history so the next `GET /acp/history` returns it (so reloading the panel shows past tool calls). The `Message` model gains an optional `Kind: string` and `ToolCallID: string` field; `Role` stays as "agent" for v1 (or add a new role "tool" — TBD).
- The `Update` struct in `internal/acp/messages.go` already carries `ToolCallID string`. Capture the full `up.Update` payload for the history entry.
2. **Frontend: ToolCallBlock component**
- New `web/src/components/acp/ToolCallBlock.tsx`.
- Props: `{ kind, title, status, content? }` where:
- `kind` is the tool name (e.g. "read", "edit", "bash", "fetch", "grep").
- `title` is a short human-readable summary (the agent's intent).
- `status` is one of "pending" | "running" | "completed" | "failed" (the ACP `tool_call` update lifecycle — pending → running → completed/failed). Map to icons: `Loader2` (spinning) for running, `Circle` for pending, `CheckCircle2` for completed, `XCircle` for failed.
- `content` is optional: for `kind: read` the file path or first lines; for `kind: edit` the diff; for `kind: bash` the command. Rendered as a small monospace block (collapsed by default, expand on click).
- Visual: small card, ~border + ~bg-muted, ~rounded-md, ~text-xs. Distinct from message bubbles so it's clear the agent did something, not said something.
- When `content` is large (e.g. a long file), truncate to a preview and show "show more".
3. **Frontend: integrate into AcpPanel**
- Streaming events with `type: "tool_call"` append a ToolCallBlock to a per-prompt list.
- The list is shown ABOVE the in-flight agent bubble (so tool calls appear first, then the agent's reply references them). On `complete`, the list is "committed" alongside the agent message.
- History endpoint returns tool calls; the AcpPanel render path coalesces: history messages + a per-message array of `ToolCall` items that appeared during that turn.
- When clicking a ToolCallBlock with a file path, optionally open the file in the editor (nice-to-have, defer to v2 if time-pressed).
4. **Data model**
- Extend `AcpMessage` / `internal/acp/history.go` `Message`:
```go
type Message struct {
Role string // "user" | "agent"
Text string
Time time.Time
MessageID string
ToolCalls []ToolCall // NEW: tool calls that occurred during this agent turn
}
type ToolCall struct {
ToolCallID string
Kind string
Title string
Status string
Content string
}
```
- The `session/update` with `sessionUpdate: "tool_call"` updates the tool call's status (pending → running → completed/failed). Correlate by `toolCallId`.
5. **Tests**
- `internal/acp/client_test.go`: extend `TestClientStreamEmitsChunkAndComplete` (or add a new test) that drives a fake tool_call sequence (pending → running → completed) and asserts the history contains the merged tool calls.
- `internal/acp/history_test.go` (new) or `client_test.go`: verify `AppendOrCreate` on tool calls works (or add a separate `History.SetToolCalls(role, messageId, calls)` method).
- Frontend: no new test infra; rely on visual verification in the dev server.
### Out of scope (deferred to v2)
- Tool-call approval UI (the agent runs everything; no interrupt-and-confirm dialog).
- Re-running a tool call.
- Diff visualization for `edit` calls (just show the raw content for v1).
- Streaming partial tool-call content.
- Multiple agents / agent switching.
- Cross-workspace agent memory.
- Authentication.
- ACP session persistence across opencode restarts.
### Open questions to resolve before implementation
- Should the in-memory history distinguish "agent text" from "tool calls" by message type, or are tool calls an array on the agent message? — Default: array on the agent message (one agent turn can have many tool calls).
- What's the shape of the `content` field for non-trivial tool calls? — For `read`, the file content; for `edit`, a diff; for `bash`, the output. Inspect a real `session/update` payload before settling the field name (`content` vs `output` vs `result`).
- Status transitions: does the agent send multiple `tool_call` updates with the same `toolCallId` (pending → running → completed), or just one final update? — Likely multiple; need to verify against a real opencode acp session.