feat: update docs to use mermaid (#152)

This commit is contained in:
Carlos Florêncio
2026-02-02 16:54:23 +00:00
committed by GitHub
parent b40615b8d5
commit 6bba1cab9f
6 changed files with 223 additions and 313 deletions
+65 -90
View File
@@ -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<br/>Execute(task)"]
ACP["ACP Session Manager<br/>Create / Prompt / Permission"]
RPC["JSON-RPC Client<br/>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<br/>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)<br/>~/.ssh/ ~/.gitconfig ~/.git-credentials"]
end
Services --> Docker
Creds -.-> Docker
```
**Deployment Methods:**
+51 -76
View File
@@ -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<br/>(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
```
+28 -53
View File
@@ -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<br/>(ACP Streaming)"]
Docker --> Container2["AI Agent Container<br/>(ACP Streaming)"]
Container1 & Container2 -->|"ACP Protocol"| Creds
subgraph Creds["Host Credentials (Mounted)"]
Git["Git Credentials"]
SSH["SSH Keys"]
end
```
### Agent Communication Protocol (ACP)
+10 -14
View File
@@ -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
+24 -44
View File
@@ -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/<operation>
▼
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
+45 -36
View File
@@ -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)