molecule-core/docs/frontend/canvas.md
Hongming Wang eec4ea2e7d chore: delete TeamHandler.Collapse + docs cleanup (closes #2864)
Multi-model retrospective review of #2856 (Phase 1 Expand removal)
flagged that TeamHandler.Collapse is unreachable from the canvas UI:
the "Collapse Team" button calls PATCH /workspaces/:id { collapsed }
(visual flag toggle on canvas_layouts), NOT POST /workspaces/:id/collapse.
The destructive POST route — which stops EC2s, marks children removed,
and deletes layouts — has zero UI callers (verified via grep across
canvas/, scripts/, and the MCP tool registry; only docs referenced it).

Two semantically different operations had been sharing the word
"Collapse":

- Visual collapse (canvas) → PATCH { collapsed: true }. Hides
  children visually. Reversible. UI-only.
- Destructive collapse (POST /collapse) → Stops + marks removed.
  Irreversible. No caller.

Deleting the destructive one + its supporting machinery:

- workspace-server/internal/handlers/team.go (entirely)
- workspace-server/internal/handlers/team_test.go (entirely)
- POST /collapse route + teamh init in router.go
- findTemplateDirByName helper (zero non-test callers after Expand
  was deleted in #2856; package-private so no out-of-package consumers)
- NewTeamHandler constructor (no callers after route removed)

Plus stale doc references (the most dangerous was the MCP wrapper
mapping in mcp-server-setup.md — anyone generating MCP tool wrappers
from that table was wiring a 404):

- docs/agent-runtime/team-expansion.md (deleted entirely — whole
  guide taught the deleted flow)
- docs/api-reference.md (dropped two team.go rows)
- docs/api-protocol/platform-api.md (dropped /expand + /collapse
  rows)
- docs/architecture/molecule-technical-doc.md (dropped /expand +
  /collapse rows)
- docs/guides/mcp-server-setup.md (dropped expand_team +
  collapse_team MCP wrapper mappings)
- docs/glossary.md (dropped "(org template expand_team)"
  parenthetical)
- docs/frontend/canvas.md (dropped broken link to deleted
  team-expansion.md)

Kept: docs/architecture/backends.md mention of "TeamHandler.Expand
(#2367) bypassed routing on Start" — correct historical context for
the AST gate's existence, no live route reference.

Visual-collapse path unaffected:
  canvas/src/components/ContextMenu.tsx:227 → api.patch — unchanged
  canvas/src/components/WorkspaceNode.tsx:128 → api.patch — unchanged

go vet ./... clean. go test ./internal/handlers/ -count 1 — all green
(4.3s, no regression).

Net: -388/+10 = ~378 lines removed.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-05 11:59:43 -07:00

189 lines
6.2 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Canvas UI (Next.js Frontend)
The canvas is Molecule AI's operational UI. It is not just a graph viewer. It is the place where teams deploy workspaces, inspect live state, configure runtimes, browse files, watch activity, and chat with agents.
## Stack
- Next.js 15
- React Flow (`@xyflow/react`)
- Zustand
- WebSocket for live updates
## What The Canvas Represents
Each node is a **workspace role**, not a task node.
The node surface includes:
- workspace name
- tier
- status
- runtime/skill summary from the Agent Card
- current task / active work indicators
Molecule AI deliberately avoids explicit edge drawing. The hierarchy comes from `parent_id`, and nested rendering makes the org chart visible directly.
## First-Run Experience
Fresh canvases currently use two onboarding surfaces:
### Empty state
The center panel shows:
- up to six template cards from `GET /templates`
- a `+ Create blank workspace` action
Creating from this panel auto-selects the new workspace and opens the `Chat` tab.
### Onboarding wizard
A dismissible bottom-left wizard walks first-time users through:
1. creating a workspace
2. opening `Config`
3. setting an API key
4. opening `Chat`
The wizard tracks completion in local storage.
## Core Interactions
### Drag to nest
Users create hierarchy by dragging one node over another:
- overlap detection happens during drag
- valid targets highlight
- dropping updates `parent_id`
- dropping back on empty canvas removes the parent
This is how Molecule AI encodes teams: by hierarchy, not manually drawn edges.
### Right-click actions
Workspace context menu actions include:
- open `Details`, `Chat`, or `Terminal`
- restart
- duplicate
- export bundle
- expand to team / collapse team
- extract from team
- delete
### Template palette
The left palette lists templates from `GET /templates` and supports importing an agent folder as a new template.
### Bundle workflow
The canvas supports:
- bundle export
- bundle import by drag-and-drop
- duplicate via export + re-import
## Real-Time Model
The frontend uses a hybrid model:
1. initial hydration over HTTP
2. incremental updates over WebSocket
Important live event flows:
- structure events update the canvas store
- `TASK_UPDATED` updates task banners
- `AGENT_CARD_UPDATED` refreshes capability badges
- `A2A_RESPONSE` delivers browser-initiated chat responses instantly
Chat is now **WebSocket-first**, with polling kept as a recovery fallback instead of the primary response path.
## Side Panel
Selecting a workspace opens the right-side panel. The panel is resizable and currently includes **10 tabs**:
| Tab | Current role |
|---|---|
| `Chat` | Two sub-tabs: **My Chat** (user↔agent, `source=canvas`) and **Agent Comms** (agent↔agent A2A traffic, `source=agent`). WebSocket response delivery, activity-based history |
| `Activity` | Rich activity feed for A2A send/receive, task updates, logs, skill promotion, and full-trace entry points |
| `Details` | Basic metadata, runtime/skill summary, restart, peer list, delete |
| `Skills` | Read-only skill and capability display from the Agent Card |
| `Terminal` | WebSocket shell into the running workspace container |
| `Config` | Structured editor for `config.yaml`, runtime, skills, A2A, delegation, sandbox, secrets, and raw YAML |
| `Files` | Workspace file browser/editor for `/configs`, `/workspace`, `/home`, and `/plugins` |
| `Memory` | Key/value workspace memory view with TTL-capable entries |
| `Traces` | Langfuse traces |
| `Events` | Workspace-scoped structure events |
### Panel banners
The panel header area can show:
- **Needs Restart** when config/files/secrets changed but the workspace has not restarted yet
- **Current Task** when the runtime heartbeat reports in-flight work
## Config And Secrets UX
The `Config` tab now reflects the current platform model more closely than older docs did:
- structured sections for general config, runtime, skills/tools, A2A, delegation, and sandbox
- raw YAML toggle for direct editing
- merged workspace/global secrets view
- explicit `This Workspace` vs `Global (All Workspaces)` secret scopes
- workspace-level overrides over global keys
- editable Agent Card JSON
This is one of the most important recent UX shifts: global provider keys are no longer just a backend concept, they are visible and manageable from the panel.
## Files UX
The `Files` tab supports multiple roots: `/configs`, `/workspace`, `/home`, `/plugins`.
`/configs` is the main editable path. When the container is offline, the platform falls back to the host-side template/config directory when possible.
### Lazy Loading
The file tree uses **lazy loading** to avoid fetching the entire filesystem at once:
- Initial load: `GET /workspaces/:id/files?root=/workspace&depth=1` — returns only top-level entries
- Expanding a folder: `GET ...&path=.claude&depth=1` — fetches that folder's immediate children on demand
- A loading indicator ("…") shows on the folder arrow while fetching
- Expanded grandchildren are preserved when re-loading a parent directory
- The `buildTree()` utility deduplicates directory nodes when both a dir entry and its nested children exist in the flat file list
### Input Validation
- `path` parameter is validated against path traversal (`../` blocked)
- `depth` must be 15 (invalid values return 400)
- Shell arguments are quoted to handle paths with spaces or special characters
## Team Visualization
Expanded teams render as embedded child cards inside the parent node:
- children are hidden as top-level React Flow nodes
- nested cards show status, tier, skill summary, and descendant counts
- child cards are selectable
- children can be extracted back out of the team
This keeps the visual model aligned with Molecule AI's main idea: the org chart is the topology.
## Error Handling
The canvas includes:
- an application-wide React error boundary
- a hydration error banner with retry
- reconnecting WebSocket behavior
- toast notifications for user actions
So the UI now exposes more operational failure state directly instead of silently failing on first load.
## Related Docs
- [Quickstart](../quickstart.md)
- [Platform API](../api-protocol/platform-api.md)
- [Workspace Runtime](../agent-runtime/workspace-runtime.md)