Chat panel in the garden editor #57

Closed
opened 2026-07-21 04:20:11 +00:00 by steve · 0 comments
Owner

Design: DESIGN.md

Context

The conversational surface, in the editor rather than on its own page. The reason is the feedback loop: watching the canvas change as the agent works is the confirmation, which is exactly what makes "act freely without asking first" tolerable. It also means the agent never has to guess which garden you mean.

Scope

  • Chat panel in the editor, streaming from POST /api/v1/agent/chat (SSE).
  • Show tool calls as they happen, in the app's own vocabulary — "Cleared the garlic bed", "Planted 14 cucumbers" — not raw JSON. This is the difference between the agent feeling like it's doing something and feeling like it's hung.
  • Invalidate /full as changes land so the canvas updates live under the conversation.
  • Undo on the turn. The response carries #48's change set id; one click reverts the whole turn. This is the safety story made visible, and it's the reason the common case never involves the history panel from #49.
  • Multi-turn history, restored on reload from #56's persistence.
  • Handle the disabled case: no API key configured → no panel, no dead button.
  • Errors read as sentences. A model timeout, a refused permission, and a tool failure are three different things and should look like it.

Layout

Three panels now want the editor's right rail: inspector, history (#49), chat. Settle the arrangement in #49 and follow it here rather than each issue inventing its own chrome. Constraints worth holding: selecting an object still lands in the inspector without a click, and the canvas keeps enough width to be worth watching — a panel that squeezes the garden to a sliver defeats the purpose of putting the chat here.

On a phone the rail becomes a sheet; chat with the garden hidden is acceptable there, since the alternative is nothing.

Out of scope

  • Voice input. (Obvious follow-up for standing in an actual garden — deliberately not now.)
  • Cross-garden conversations.
  • Rendering the agent's plan before it acts. That's the confirm-first model, which was explicitly not chosen.

Key files

web/src/pages/GardenEditorPage.tsx · web/src/editor/ · web/src/lib/ (new agent.ts) · web/src/lib/queryClient.ts for invalidation

Dependencies

Blocked by #56. Coordinate rail layout with #49; coordinate the Undo affordance with #49's inline-undo item so there's one implementation, not two.

Acceptance criteria

  • Typing "change the garlic bed to cucumbers this year" shows the tool steps as they run, the canvas updates as they land, and the finished turn offers one-click Undo that restores the garlic.
  • Reloading the page keeps the conversation.
  • With no API key configured, the editor looks exactly as it does today.
  • Works on a phone.
Design: [DESIGN.md](https://gitea.stevedudenhoeffer.com/steve/pansy/src/branch/main/DESIGN.md) ## Context The conversational surface, in the editor rather than on its own page. The reason is the feedback loop: **watching the canvas change as the agent works is the confirmation**, which is exactly what makes "act freely without asking first" tolerable. It also means the agent never has to guess which garden you mean. ## Scope - [ ] Chat panel in the editor, streaming from `POST /api/v1/agent/chat` (SSE). - [ ] Show **tool calls as they happen**, in the app's own vocabulary — "Cleared the garlic bed", "Planted 14 cucumbers" — not raw JSON. This is the difference between the agent feeling like it's doing something and feeling like it's hung. - [ ] Invalidate `/full` as changes land so the canvas updates live under the conversation. - [ ] **Undo on the turn.** The response carries #48's change set id; one click reverts the whole turn. This is the safety story made visible, and it's the reason the common case never involves the history panel from #49. - [ ] Multi-turn history, restored on reload from #56's persistence. - [ ] Handle the disabled case: no API key configured → no panel, no dead button. - [ ] Errors read as sentences. A model timeout, a refused permission, and a tool failure are three different things and should look like it. ## Layout Three panels now want the editor's right rail: inspector, history (#49), chat. **Settle the arrangement in #49 and follow it here** rather than each issue inventing its own chrome. Constraints worth holding: selecting an object still lands in the inspector without a click, and the canvas keeps enough width to be worth watching — a panel that squeezes the garden to a sliver defeats the purpose of putting the chat here. On a phone the rail becomes a sheet; chat with the garden hidden is acceptable there, since the alternative is nothing. ## Out of scope - Voice input. (Obvious follow-up for standing in an actual garden — deliberately not now.) - Cross-garden conversations. - Rendering the agent's plan before it acts. That's the confirm-first model, which was explicitly not chosen. ## Key files `web/src/pages/GardenEditorPage.tsx` · `web/src/editor/` · `web/src/lib/` (new `agent.ts`) · `web/src/lib/queryClient.ts` for invalidation ## Dependencies Blocked by #56. Coordinate rail layout with #49; coordinate the Undo affordance with #49's inline-undo item so there's one implementation, not two. ## Acceptance criteria - Typing "change the garlic bed to cucumbers this year" shows the tool steps as they run, the canvas updates as they land, and the finished turn offers one-click Undo that restores the garlic. - Reloading the page keeps the conversation. - With no API key configured, the editor looks exactly as it does today. - Works on a phone.
steve added the frontendagent labels 2026-07-21 04:20:11 +00:00
steve closed this issue 2026-07-21 06:43:22 +00:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: steve/pansy#57