From 6bba1cab9f64789754709a9ca500d75248a1d97a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Flor=C3=AAncio?= Date: Mon, 2 Feb 2026 16:54:23 +0000 Subject: [PATCH] feat: update docs to use mermaid (#152) --- docs/ARCHITECTURE.md | 155 ++++++++++++---------------- docs/GIT_WORKTREE_IMPLEMENTATION.md | 127 +++++++++-------------- docs/IMPLEMENTATION_PLAN.md | 81 +++++---------- docs/WEBSOCKET_API.md | 24 ++--- docs/git-operations.md | 68 +++++------- docs/session-page-data-flow.md | 81 ++++++++------- 6 files changed, 223 insertions(+), 313 deletions(-) diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index 46ae587f54..9a105ca0fc 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -26,34 +26,24 @@ Kandev uses an event-driven architecture with **Agent Communication Protocol (AC ## Current Architecture (Unified Binary) -``` -┌─────────────────────────────────────────────────────────┐ -│ Kandev Binary │ -│ (Port 8080) │ -│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────┐ │ -│ │ Task │ │ Agent │ │ Orchestrator │ │ -│ │ Service │ │ Manager │ │ Service │ │ -│ └──────┬──────┘ └──────┬──────┘ └────────┬────────┘ │ -│ │ │ │ │ -│ └───────────────┴──────────────────┘ │ -│ │ │ -│ ┌──────────┴──────────┐ │ -│ │ In-Memory Event Bus │ │ -│ └──────────┬──────────┘ │ -│ │ │ -│ ┌──────────┴──────────┐ │ -│ │ SQLite Database │ │ -│ │ (kandev.db) │ │ -│ └─────────────────────┘ │ -└─────────────────────────────────────────────────────────┘ - │ - Docker Engine (Agent Containers) - │ - ┌───────────┴───────────┐ - │ Augment Agent │ - │ Container │ - │ (ACP via stdout) │ - └───────────────────────┘ +```mermaid +flowchart TB + subgraph Binary["Kandev Binary (Port 8080)"] + Task["Task Service"] + Agent["Agent Manager"] + Orch["Orchestrator Service"] + + Task & Agent & Orch --> EventBus["In-Memory Event Bus"] + EventBus --> DB["SQLite Database (kandev.db)"] + end + + Binary --> Docker["Docker Engine"] + + subgraph Container["Augment Agent Container"] + ACP["ACP via stdout"] + end + + Docker --> Container ``` --- @@ -498,38 +488,26 @@ The backend implements full ACP support with: ### ACP Flow Through System (Current Implementation) -``` -┌─────────────────────────────────────────────────────────────────┐ -│ Kandev Backend │ -│ │ -│ ┌──────────────┐ ┌──────────────┐ ┌─────────────────┐ │ -│ │ Orchestrator │───▶│ ACP Session │───▶│ JSON-RPC Client │ │ -│ │ │ │ Manager │ │ │ │ -│ │ Execute(task)│ │ │ │ - Send requests │ │ -│ └──────────────┘ │ - Create │ │ - Handle resp │ │ -│ │ - Prompt │ │ - Handle notif │ │ -│ │ - Permission │ │ - Handle req │ │ -│ └──────────────┘ └────────┬────────┘ │ -│ │ │ -└───────────────────────────────────────────────────┼─────────────┘ - │ - Docker attach (stdin/stdout) - │ -┌───────────────────────────────────────────────────┼─────────────┐ -│ Agent Container ▼ │ -│ │ -│ ┌──────────────────────────────────────────────────────────┐ │ -│ │ Auggie CLI (--acp) │ │ -│ │ │ │ -│ │ stdin ◀────── JSON-RPC requests from client │ │ -│ │ stdout ─────▶ JSON-RPC responses/notifications/requests │ │ -│ │ │ │ -│ │ Notifications: session/update (progress, results) │ │ -│ │ Requests: session/request_permission │ │ -│ └──────────────────────────────────────────────────────────┘ │ -│ │ -│ /workspace ◀──── Mounted from host (repository_url) │ -└──────────────────────────────────────────────────────────────────┘ +```mermaid +flowchart TB + subgraph Backend["Kandev Backend"] + Orch["Orchestrator
Execute(task)"] + ACP["ACP Session Manager
Create / Prompt / Permission"] + RPC["JSON-RPC Client
Send requests / Handle responses"] + Orch --> ACP --> RPC + end + + RPC <-->|"Docker attach (stdin/stdout)"| Agent + + subgraph Agent["Agent Container"] + CLI["Auggie CLI (--acp)"] + stdin["stdin ← JSON-RPC requests"] + stdout["stdout → responses/notifications"] + CLI --- stdin + CLI --- stdout + end + + Workspace["/workspace
Mounted from host"] --> Agent ``` ### Initial Agent Types @@ -596,36 +574,33 @@ The backend implements full ACP support with: The system is designed for deployment on **client machines** (developer workstations, local servers) with direct access to user credentials. **Architecture:** -``` -┌─────────────────────────────────────────────────────┐ -│ User's Local Machine │ -│ │ -│ ┌──────────────┐ ┌──────────────┐ │ -│ │ PostgreSQL │ │ NATS Server │ │ -│ │ (Docker) │ │ (Docker) │ │ -│ └──────────────┘ └──────────────┘ │ -│ │ -│ ┌──────────────────────────────────────────────┐ │ -│ │ Kandev Backend Services │ │ -│ │ (Native binaries or Docker) │ │ -│ │ │ │ -│ │ API Gateway | Task Service | Orchestrator │ │ -│ │ Agent Manager │ │ -│ └──────────────────────────────────────────────┘ │ -│ │ -│ ┌──────────────────────────────────────────────┐ │ -│ │ Docker Engine (Agent Containers) │ │ -│ │ ┌──────────┐ ┌──────────┐ │ │ -│ │ │ Auggie │ │ Gemini │ ... │ │ -│ │ │ Agent │ │ Agent │ │ │ -│ │ └──────────┘ └──────────┘ │ │ -│ └──────────────────────────────────────────────┘ │ -│ │ -│ ┌──────────────────────────────────────────────┐ │ -│ │ Host Credentials (Mounted Read-Only) │ │ -│ │ ~/.ssh/ ~/.gitconfig ~/.git-credentials │ │ -│ └──────────────────────────────────────────────┘ │ -└─────────────────────────────────────────────────────┘ + +```mermaid +flowchart TB + subgraph Machine["User's Local Machine"] + subgraph Infra["Infrastructure (Docker)"] + PG["PostgreSQL"] + NATS["NATS Server"] + end + + subgraph Services["Kandev Backend Services"] + Gateway["API Gateway"] + TaskSvc["Task Service"] + OrchSvc["Orchestrator"] + AgentMgr["Agent Manager"] + end + + subgraph Docker["Docker Engine"] + Auggie["Auggie Agent"] + Gemini["Gemini Agent"] + More["..."] + end + + Creds["Host Credentials (Read-Only)
~/.ssh/ ~/.gitconfig ~/.git-credentials"] + end + + Services --> Docker + Creds -.-> Docker ``` **Deployment Methods:** diff --git a/docs/GIT_WORKTREE_IMPLEMENTATION.md b/docs/GIT_WORKTREE_IMPLEMENTATION.md index f678a15e67..5c03bdbdcd 100644 --- a/docs/GIT_WORKTREE_IMPLEMENTATION.md +++ b/docs/GIT_WORKTREE_IMPLEMENTATION.md @@ -101,58 +101,36 @@ KANDEV_WORKTREE_ENABLED=true ### Lifecycle Diagram -``` -┌─────────────────────────────────────────────────────────────────────────────┐ -│ WORKTREE LIFECYCLE │ -│ (Tied to Task Lifetime) │ -├─────────────────────────────────────────────────────────────────────────────┤ -│ │ -│ TASK CREATED │ -│ │ │ -│ ▼ │ -│ ┌─────────────────────────────────────────────────────────────────────────┐│ -│ │ FIRST AGENT LAUNCH ││ -│ │ ││ -│ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ││ -│ │ │ Check if │────▶│ Create new │────▶│ Mount into │ ││ -│ │ │ worktree │ No │ worktree & │ │ container │ ││ -│ │ │ exists │ │ branch │ │ │ ││ -│ │ └─────────────┘ └─────────────┘ └─────────────┘ ││ -│ │ │ Yes │ ││ -│ │ ▼ ▼ ││ -│ │ ┌─────────────┐ ┌─────────────┐ ││ -│ │ │ Reuse │────────────────────────▶│ Agent │ ││ -│ │ │ existing │ │ Running │ ││ -│ │ │ worktree │ └─────────────┘ ││ -│ │ └─────────────┘ │ ││ -│ │ ▼ ││ -│ │ ┌─────────────┐ ││ -│ │ │ Agent │ ││ -│ │ │ Completes │ ││ -│ │ └─────────────┘ ││ -│ │ │ ││ -│ │ ┌─────────────┴─────────────┐ ││ -│ │ ▼ ▼ ││ -│ │ ┌─────────────┐ ┌─────────────┐ ││ -│ │ │ Worktree │ │ User sends │ ││ -│ │ │ PERSISTS │◀────────────│ follow-up │ ││ -│ │ │ (changes │ Relaunch │ prompt │ ││ -│ │ │ preserved) │ └─────────────┘ ││ -│ │ └─────────────┘ ││ -│ └─────────────────────────────────────────────────────────────────────────┘│ -│ │ │ -│ ▼ │ -│ ┌─────────────────────────────────────────────────────────────────────────┐│ -│ │ TASK CLOSED/DELETED BY USER ││ -│ │ ││ -│ │ User chooses one of: ││ -│ │ ├── Merge → merge worktree branch to base, then cleanup ││ -│ │ ├── Discard → cleanup worktree and branch without merging ││ -│ │ └── Keep Branch → cleanup worktree, keep branch for manual merge ││ -│ │ ││ -│ │ OR: Task deleted directly → cleanup worktree and branch ││ -│ └─────────────────────────────────────────────────────────────────────────┘│ -└─────────────────────────────────────────────────────────────────────────────┘ +```mermaid +flowchart TD + subgraph Lifecycle["WORKTREE LIFECYCLE (Tied to Task Lifetime)"] + + TaskCreated["Task Created"] --> AgentLaunch + + subgraph AgentLaunch["First Agent Launch"] + Check{"Worktree exists?"} + Check -->|No| Create["Create new worktree & branch"] + Check -->|Yes| Reuse["Reuse existing worktree"] + Create --> Mount["Mount into container"] + Reuse --> Mount + Mount --> Running["Agent Running"] + Running --> Completes["Agent Completes"] + end + + Completes --> Persists["Worktree PERSISTS
(changes preserved)"] + Completes --> Followup["User sends follow-up"] + Followup -->|Relaunch| Mount + + Persists --> TaskClosed + + subgraph TaskClosed["Task Closed/Deleted"] + Options["User chooses:"] + Merge["Merge → merge branch to base, cleanup"] + Discard["Discard → cleanup without merging"] + Keep["Keep Branch → cleanup worktree, keep branch"] + Delete["Task deleted → cleanup worktree and branch"] + end + end ``` ### 2.1 Creation Timing @@ -956,29 +934,26 @@ git worktree unlock /tmp/kandev/worktrees/task-123 ## Appendix B: Sequence Diagram - Agent Launch with Worktree -``` -Client Orchestrator Executor LifecycleManager WorktreeManager Docker - │ │ │ │ │ │ - │ orchestrator.start │ │ │ │ - ├────────────────►│ │ │ │ │ - │ │ ExecuteTask │ │ │ │ - │ ├─────────────────►│ │ │ │ - │ │ │ LaunchAgent │ │ │ - │ │ ├─────────────────►│ │ │ - │ │ │ │ Create() │ │ - │ │ │ ├─────────────────►│ │ - │ │ │ │ │ git worktree add - │ │ │ │ ├──────────────►│ - │ │ │ │ │◄──────────────┤ - │ │ │ │◄─────────────────┤ │ - │ │ │ │ worktree.Path │ │ - │ │ │ │ │ │ - │ │ │ │ CreateContainer (mount worktree)│ - │ │ │ ├──────────────────────────────────► - │ │ │ │◄────────────────────────────────── - │ │ │◄─────────────────┤ │ │ - │ │◄─────────────────┤ │ │ │ - │◄────────────────┤ │ │ │ │ - │ response │ │ │ │ │ +```mermaid +sequenceDiagram + participant Client + participant Orchestrator + participant Executor + participant LifecycleManager + participant WorktreeManager + participant Docker + + Client->>Orchestrator: orchestrator.start + Orchestrator->>Executor: ExecuteTask + Executor->>LifecycleManager: LaunchAgent + LifecycleManager->>WorktreeManager: Create() + WorktreeManager->>Docker: git worktree add + Docker-->>WorktreeManager: done + WorktreeManager-->>LifecycleManager: worktree.Path + LifecycleManager->>Docker: CreateContainer (mount worktree) + Docker-->>LifecycleManager: container created + LifecycleManager-->>Executor: agent launched + Executor-->>Orchestrator: task executing + Orchestrator-->>Client: response ``` diff --git a/docs/IMPLEMENTATION_PLAN.md b/docs/IMPLEMENTATION_PLAN.md index 4db0b8bf7a..a1221ce621 100644 --- a/docs/IMPLEMENTATION_PLAN.md +++ b/docs/IMPLEMENTATION_PLAN.md @@ -11,59 +11,34 @@ ## 1. System Architecture Overview ### High-Level Architecture -``` -┌─────────────────┐ -│ Frontend UI │ (Out of scope - connects via WebSocket) -└────────┬────────┘ - │ Single WebSocket Connection - │ ws://localhost:8080/ws - ▼ -┌─────────────────────────────────────────┐ -│ API Gateway Service │ -│ - WebSocket connection management │ -│ - Message routing & dispatching │ -│ - Authentication & Authorization │ -│ - Rate limiting │ -└────────┬────────────────────────────────┘ - │ WebSocket Messages - ┌────┴────┬──────────────┬─────────────┐ - ▼ ▼ ▼ ▼ -┌────────┐ ┌──────────┐ ┌─────────┐ ┌──────────┐ -│ Task │ │Orchestr- │ │ Agent │ │ Event │ -│Service │ │ator │ │ Manager │ │ Bus │ -│ │ │ Service │ │ Service │ │ (NATS) │ -│ │ │+ ACP │ │+ ACP │ │ │ -└───┬────┘ └────┬─────┘ └────┬────┘ └────┬─────┘ - │ │ │ │ - └───────────┴────────────┴───────────┘ - │ - ┌──────┴──────┐ - ▼ ▼ - ┌─────────┐ ┌──────────────┐ - │PostgreSQL│ │Docker Engine │ - │Database │ │ │ - └──────────┘ └──────┬───────┘ - │ - ┌──────────┴──────────┐ - ▼ ▼ - ┌──────────┐ ┌──────────┐ - │AI Agent │ │AI Agent │ - │Container │ ... │Container │ - │(ACP │ │(ACP │ - │Streaming)│ │Streaming)│ - └──────────┘ └──────────┘ - │ │ - └──────────┬──────────┘ - │ - ACP Protocol (Streaming) - │ - ┌──────────┴──────────┐ - ▼ ▼ - ┌──────────┐ ┌──────────┐ - │Host Git │ │Host SSH │ - │Credentials│ │Keys │ - │(Mounted) │ │(Mounted) │ - └──────────┘ └──────────┘ + +```mermaid +flowchart TB + Frontend["Frontend UI"] -->|"WebSocket ws://localhost:8080/ws"| Gateway + + subgraph Gateway["API Gateway Service"] + gw1["WebSocket management"] + gw2["Message routing"] + gw3["Auth & Rate limiting"] + end + + Gateway --> Task["Task Service"] + Gateway --> Orch["Orchestrator + ACP"] + Gateway --> Agent["Agent Manager + ACP"] + Gateway --> NATS["Event Bus (NATS)"] + + Task & Orch & Agent & NATS --> DB["PostgreSQL"] + Agent --> Docker["Docker Engine"] + + Docker --> Container1["AI Agent Container
(ACP Streaming)"] + Docker --> Container2["AI Agent Container
(ACP Streaming)"] + + Container1 & Container2 -->|"ACP Protocol"| Creds + + subgraph Creds["Host Credentials (Mounted)"] + Git["Git Credentials"] + SSH["SSH Keys"] + end ``` ### Agent Communication Protocol (ACP) diff --git a/docs/WEBSOCKET_API.md b/docs/WEBSOCKET_API.md index 40b0fd3b17..7fa3b09261 100644 --- a/docs/WEBSOCKET_API.md +++ b/docs/WEBSOCKET_API.md @@ -56,20 +56,16 @@ All messages follow this JSON envelope format: ## System Flow -``` -┌─────────────┐ WebSocket ┌─────────────────────────────────────────────┐ -│ Client │◄──────────────────►│ Kandev Server │ -│ (Browser) │ Single Connection │ │ -└─────────────┘ │ ┌─────────┐ ┌─────────┐ ┌──────────────┐ │ - │ │ Task │ │ Agent │ │ Orchestrator │ │ - │ │ Service │ │ Manager │ │ Service │ │ - │ └─────────┘ └─────────┘ └──────────────┘ │ - │ │ │ - │ ┌──────▼──────┐ │ - │ │ Docker │ │ - │ │ Containers │ │ - │ └─────────────┘ │ - └─────────────────────────────────────────────┘ +```mermaid +flowchart LR + Client["Client (Browser)"] <-->|"WebSocket"| Server + + subgraph Server["Kandev Server"] + Task["Task Service"] + Agent["Agent Manager"] + Orch["Orchestrator Service"] + Agent --> Docker["Docker Containers"] + end ``` ### Typical Workflow diff --git a/docs/git-operations.md b/docs/git-operations.md index c4fdcc92b8..c250b62b86 100644 --- a/docs/git-operations.md +++ b/docs/git-operations.md @@ -20,56 +20,36 @@ Git operations are executed **in agentctl**, not in the backend. This ensures co ### Request Flow -``` -Frontend UI (Git Actions Dropdown) - │ - ▼ -WebSocket Client - │ worktree.pull / worktree.push / worktree.rebase / worktree.merge - ▼ -Backend WebSocket Gateway - │ - ▼ -Git Handlers (internal/agent/handlers/git_handlers.go) - │ GetExecutionBySessionID(sessionID) - ▼ -Lifecycle Manager → AgentExecution → agentctl.Client - │ - │ HTTP POST /api/v1/git/ - ▼ -agentctl HTTP API (server/api/git.go) - │ - ▼ -Git Command Execution (server/process/git.go) - │ exec.Command("git", ...) in worktree directory - ▼ -HTTP Response → Backend Handler → WebSocket Response → Frontend +```mermaid +flowchart TD + A["Frontend UI (Git Actions Dropdown)"] --> B["WebSocket Client"] + B -->|"worktree.pull/push/rebase/merge"| C["Backend WebSocket Gateway"] + C --> D["Git Handlers"] + D -->|"GetExecutionBySessionID"| E["Lifecycle Manager"] + E --> F["AgentExecution"] + F --> G["agentctl.Client"] + G -->|"HTTP POST /api/v1/git/op"| H["agentctl HTTP API"] + H --> I["Git Command Execution"] + I -->|"exec.Command git"| J["Worktree Directory"] + J --> K["HTTP Response"] + K --> L["Backend Handler"] + L --> M["WebSocket Response"] + M --> N["Frontend"] ``` ### Notification Flow (Git Status Updates) After any git operation, the workspace state changes. Updates flow through the event bus: -``` -agentctl WorkspaceTracker (detects git status change) - │ workspace stream: git_status message - ▼ -Backend StreamManager (OnGitStatus callback) - │ - ▼ -EventPublisher.PublishGitStatus() - │ - ▼ -Event Bus - │ - ▼ -TaskNotificationBridge - │ - ▼ -Hub.BroadcastToSession(sessionID) - │ - ▼ -Frontend WebSocket → Zustand Store update +```mermaid +flowchart TD + A["agentctl WorkspaceTracker"] -->|"git_status message"| B["Backend StreamManager"] + B -->|"OnGitStatus callback"| C["EventPublisher.PublishGitStatus"] + C --> D["Event Bus"] + D --> E["TaskNotificationBridge"] + E --> F["Hub.BroadcastToSession"] + F --> G["Frontend WebSocket"] + G --> H["Zustand Store update"] ``` ## agentctl API diff --git a/docs/session-page-data-flow.md b/docs/session-page-data-flow.md index 346d545e92..e738c13e20 100644 --- a/docs/session-page-data-flow.md +++ b/docs/session-page-data-flow.md @@ -22,14 +22,14 @@ Hydration: ## Client Composition -``` -TaskSessionPage (SSR) - └─ TaskPageClient - ├─ TaskTopBar - └─ TaskLayout - ├─ TaskSessionSidebar (left) - ├─ TaskCenterPanel (chat/changes/notes) - └─ TaskRightPanel (files + terminal) +```mermaid +flowchart TD + A["TaskSessionPage (SSR)"] --> B["TaskPageClient"] + B --> C["TaskTopBar"] + B --> D["TaskLayout"] + D --> E["TaskSessionSidebar (left)"] + D --> F["TaskCenterPanel (chat/changes/notes)"] + D --> G["TaskRightPanel (files + terminal)"] ``` ## Active Selection (Store) @@ -116,37 +116,46 @@ Handlers (global router): - `gitStatus` keyed by active task - No direct WS subscriptions. -## ASCII Diagram (Current) +## Data Flow Diagram -``` -SSR -┌──────────────────────────────────────────────────────────────┐ -│ /task/:id/:sessionId │ -│ fetchTask + snapshot + agents + repos + sessions + messages │ -│ StateHydrator -> store (activeTaskId + activeSessionId) │ -└──────────────────────────────────────────────────────────────┘ +```mermaid +flowchart TB + subgraph SSR["SSR: /task/:id/:sessionId"] + fetch["fetchTask + snapshot + agents + repos + sessions + messages"] + hydrate["StateHydrator → store"] + end -Client -┌─────────────────────────────── TaskPageClient ──────────────────────────────┐ -│ setActiveSession(taskId, sessionId) │ -│ subscribe(board tasks) + listen task_session.state_changed │ -│ │ -│ ┌─ TaskSessionSidebar (sessions + tasks) │ -│ ├─ TaskCenterPanel │ -│ │ └─ TaskChatPanel │ -│ │ ├─ useTaskSession(sessionId) │ -│ │ ├─ useTaskMessages(taskId, sessionId) │ -│ │ └─ useLazyLoadMessages(sessionId) │ -│ └─ TaskRightPanel │ -│ └─ ShellTerminal (shell.output + session state) │ -└──────────────────────────────────────────────────────────────────────────────┘ + subgraph Client["TaskPageClient"] + setActive["setActiveSession(taskId, sessionId)"] + subscribe["subscribe(board tasks)"] -WS - task.subscribe -> deduped in client - message.added/updated -> messages.bySession - task_session.state_changed -> taskSessions + taskSessionStatesByTaskId - git.status -> gitStatus (task) - shell.output -> shell.outputs[task] + subgraph Components + sidebar["TaskSessionSidebar"] + center["TaskCenterPanel"] + right["TaskRightPanel"] + end + + subgraph ChatPanel["TaskChatPanel"] + useSession["useTaskSession(sessionId)"] + useMessages["useTaskMessages(taskId, sessionId)"] + useLazy["useLazyLoadMessages(sessionId)"] + end + + shell["ShellTerminal"] + end + + subgraph WS["WebSocket Events"] + ws1["task.subscribe → deduped"] + ws2["message.added/updated → messages.bySession"] + ws3["task_session.state_changed → taskSessions"] + ws4["git.status → gitStatus"] + ws5["shell.output → shell.outputs"] + end + + SSR --> Client + center --> ChatPanel + right --> shell + WS --> Client ``` ## Hooks Review (Granularity + Reuse)