Post

17-diagrams

17-diagrams

架构与流程图

本文档中的图用 Mermaid 编写,可在支持 Mermaid 的 Markdown 预览器中查看。

1. 总体框架图

flowchart LR
  User[Human user] --> Web[apps/web<br/>Next.js]
  User --> Desktop[apps/desktop<br/>Electron]
  User --> Mobile[apps/mobile<br/>Expo RN]
  User --> CLI[server/cmd/multica<br/>CLI]

  Web --> Core[packages/core<br/>API/Query/Store]
  Desktop --> Core
  Mobile -. shares types/pure funcs .-> Core
  Web --> Views[packages/views<br/>Shared business UI]
  Desktop --> Views
  Views --> Core
  Views --> UI[packages/ui<br/>Atomic UI]

  Core --> API[Go API server<br/>server/cmd/server]
  CLI --> API
  Desktop --> Daemon[Local daemon<br/>server/internal/daemon]
  CLI --> Daemon

  API --> DB[(PostgreSQL + pgvector)]
  API --> Redis[(Redis optional)]
  API --> S3[S3 or local storage]
  API --> Cloud[Cloud runtime / billing upstream]
  API --> Integrations[Lark / Slack / GitHub / Stripe]

  Daemon --> AgentCLI[Agent CLIs<br/>Claude/Codex/OpenCode/etc.]
  Daemon --> API
  API -- WebSocket events --> Core
  API -- daemon WS wakeup --> Daemon

2. Monorepo 分层图

flowchart TB
  subgraph Apps
    WebApp[apps/web<br/>Next.js routing/platform]
    DesktopApp[apps/desktop<br/>Electron routing/IPC]
    MobileApp[apps/mobile<br/>Expo independent UI]
    DocsApp[apps/docs<br/>Docs site]
  end

  subgraph Packages
    ViewsPkg[packages/views<br/>Business pages/components]
    CorePkg[packages/core<br/>API, Query, stores, types]
    UIPkg[packages/ui<br/>Atomic components/tokens]
    TSCfg[packages/tsconfig]
    ESLint[packages/eslint-config]
  end

  WebApp --> ViewsPkg
  DesktopApp --> ViewsPkg
  ViewsPkg --> CorePkg
  ViewsPkg --> UIPkg
  WebApp --> CorePkg
  DesktopApp --> CorePkg
  MobileApp -. type/pure imports only .-> CorePkg

  WebApp --> TSCfg
  DesktopApp --> TSCfg
  CorePkg --> TSCfg
  ViewsPkg --> TSCfg
  UIPkg --> TSCfg

3. 后端组件图

flowchart TB
  Main[server/cmd/server/main.go] --> Router[NewRouterWithOptions<br/>server/cmd/server/router.go]
  Main --> Bus[events.Bus]
  Main --> Hub[realtime.Hub]
  Main --> DaemonHub[daemonws.Hub]
  Main --> Scheduler[scheduler.Manager]
  Main --> Sweeper[Runtime sweeper]
  Main --> Metrics[metrics server]

  Router --> Middleware[Auth / DaemonAuth / Workspace / CORS / RateLimit]
  Router --> Handler[handler.Handler]
  Handler --> Queries[sqlc Queries]
  Handler --> TaskSvc[TaskService]
  Handler --> IssueSvc[IssueService]
  Handler --> AutopilotSvc[AutopilotService]
  Handler --> Storage[Storage S3/local]
  Handler --> Channel[Channel engine<br/>Lark/Slack]
  Handler --> Bus

  TaskSvc --> Queries
  IssueSvc --> Queries
  AutopilotSvc --> Queries
  TaskSvc --> Bus
  IssueSvc --> Bus
  AutopilotSvc --> Bus

  Queries --> DB[(PostgreSQL)]
  Bus --> Listeners[server/cmd/server/*_listeners.go]
  Listeners --> Hub
  Listeners --> Queries
  Hub --> WSClients[Web/Desktop WS clients]
  DaemonHub --> Daemon[Local daemon]

4. Server 启动流程图

flowchart TD
  A[main()] --> B[Init logger and env defaults]
  B --> C[Load feature flags]
  C --> D[Create pgxpool and ping DB]
  D --> E[Create events.Bus + realtime.Hub + daemonws.Hub]
  E --> F{REDIS_URL set?}
  F -- no --> G[Use in-memory hub single-node mode]
  F -- yes --> H[Create Redis clients]
  H --> I{REALTIME_RELAY_MODE}
  I --> I1[legacy relay]
  I --> I2[sharded relay]
  I --> I3[dual mirrored relay]
  G --> J[register realtime listener]
  I1 --> J
  I2 --> J
  I3 --> J
  J --> K[Create analytics, queries, authorizer]
  K --> L[Register subscriber/activity/notification listeners]
  L --> M[Build metrics registry optional]
  M --> N[Create heartbeat scheduler]
  N --> O[NewRouterWithOptions]
  O --> P[Create TaskService and AutopilotService]
  P --> Q[Register autopilot listeners]
  Q --> R[Start sweepers, scheduler, channel supervisor]
  R --> S[Start HTTP server]
  S --> T[Wait SIGINT/SIGTERM]
  T --> U[Graceful shutdown HTTP, workers, metrics, relay]

5. HTTP 请求处理时序图

sequenceDiagram
  participant UI as Web/Desktop UI
  participant Core as packages/core ApiClient
  participant Router as Chi Router
  participant MW as Auth + Workspace middleware
  participant H as Handler
  participant S as Service/sqlc
  participant DB as PostgreSQL
  participant Bus as events.Bus
  participant WS as realtime.Hub

  UI->>Core: call query/mutation hook
  Core->>Router: HTTP request with auth, CSRF, workspace slug, request id
  Router->>MW: global + auth + workspace middleware
  MW->>H: request with X-User-ID and workspace context
  H->>S: validate input, call service or Queries
  S->>DB: read/write via sqlc
  DB-->>S: rows/results
  S-->>H: domain result
  H->>Bus: Publish domain event
  Bus->>WS: registerListeners broadcasts event
  WS-->>UI: WebSocket frame
  H-->>Core: JSON response
  Core-->>UI: parsed data or ApiError

6. Issue 更新后的事件副作用

flowchart LR
  Update[Update issue handler/service] --> DB[(Update DB)]
  Update --> Publish[Bus.Publish issue:updated]

  Publish --> Sub[registerSubscriberListeners]
  Sub --> SubDB[(issue_subscriber)]
  Sub --> SubEvent[subscriber:added]

  Publish --> Act[registerActivityListeners]
  Act --> ActDB[(activity_log)]
  Act --> ActEvent[activity:created]

  Publish --> Notif[registerNotificationListeners]
  Notif --> InboxDB[(inbox_item)]
  Notif --> InboxEvent[inbox:new / inbox:batch-*]

  Publish --> AP[registerAutopilotListeners]
  AP --> APDB[(autopilot_run sync if needed)]

  Publish --> RT[registerListeners]
  SubEvent --> RT
  ActEvent --> RT
  InboxEvent --> RT
  RT --> WS[Workspace/user WebSocket delivery]
  WS --> FE[useRealtimeSync<br/>patch/invalidate Query cache]

7. Realtime 架构图

flowchart TB
  Producer[Handler / Service] --> Bus[events.Bus]
  Bus --> Listener[registerListeners]
  Listener --> Broadcaster{Broadcaster}
  Broadcaster -- no Redis --> Hub[realtime.Hub]
  Broadcaster -- Redis enabled --> Dual[DualWriteBroadcaster]
  Dual --> Hub
  Dual --> Relay[Redis relay]
  Relay --> Streams[(Redis streams)]
  Streams --> RelayReaders[Other API node relay readers]
  RelayReaders --> Hub2[Other node realtime.Hub]

  Hub --> WS1[Client WS connections]
  Hub2 --> WS2[Client WS connections]
  WS1 --> Core1[WSClient]
  WS2 --> Core2[WSClient]
  Core1 --> Sync1[useRealtimeSync]
  Core2 --> Sync2[useRealtimeSync]
  Sync1 --> Cache1[React Query cache]
  Sync2 --> Cache2[React Query cache]

8. Agent 任务执行时序图

sequenceDiagram
  participant User as User/UI/Autopilot/Channel
  participant API as Go API
  participant TaskSvc as TaskService
  participant DB as PostgreSQL
  participant Wake as daemonws/Redis wakeup
  participant D as Local daemon
  participant Agent as Agent CLI backend
  participant WS as WebSocket clients

  User->>API: Create/update issue, comment @agent, chat, or autopilot trigger
  API->>TaskSvc: Enqueue task
  TaskSvc->>DB: INSERT agent_task_queue status=queued
  TaskSvc->>WS: Publish task:queued
  TaskSvc->>Wake: NotifyTaskAvailable(runtime_id, task_id)
  Wake-->>D: wake runtime poller
  D->>API: POST /api/daemon/runtimes/{runtimeId}/tasks/claim
  API->>DB: ClaimAgentTask -> dispatched
  API-->>D: task payload + context
  D->>API: POST /api/daemon/tasks/{taskId}/start
  API->>TaskSvc: StartTask -> running
  TaskSvc-->>WS: task:running
  D->>Agent: Execute(prompt, ExecOptions)
  loop streaming
    Agent-->>D: message/progress/status/usage
    D->>API: ReportTaskMessages / ReportProgress / ReportUsage
    API-->>WS: task/chat/message events
  end
  Agent-->>D: final Result
  alt success
    D->>API: POST /complete
    API->>TaskSvc: CompleteTask
    TaskSvc->>DB: status=completed
    TaskSvc-->>WS: task:completed
  else failure
    D->>API: POST /fail
    API->>TaskSvc: FailTask
    TaskSvc->>DB: status=failed
    TaskSvc-->>WS: task:failed
  end

9. Frontend Boot 和数据流

flowchart TD
  subgraph Web
    WRoot[apps/web/app/layout.tsx]
    WProviders[WebProviders]
    WWorkspace[workspaceSlug layout]
  end

  subgraph Desktop
    DApp[renderer App.tsx]
    DesktopCore[CoreProvider]
    DRoutes[routes.tsx memory routers]
    DDaemon[daemon IPC bridge]
  end

  subgraph Core
    CoreProvider[packages/core CoreProvider]
    APIClient[ApiClient singleton]
    Auth[Auth store]
    Query[QueryProvider / React Query]
    WSProvider[WSProvider]
    Realtime[useRealtimeSync]
    WorkspaceStore[workspace-storage singleton]
  end

  WRoot --> WProviders --> CoreProvider
  WWorkspace --> WorkspaceStore
  DApp --> DesktopCore --> CoreProvider
  DApp --> DRoutes
  DApp --> DDaemon
  CoreProvider --> APIClient
  CoreProvider --> Auth
  CoreProvider --> Query
  CoreProvider --> WSProvider
  WSProvider --> Realtime
  APIClient --> Backend[Go API]
  Realtime --> Query

10. Web 与 Desktop 页面复用图

flowchart LR
  WebRoute[apps/web page.tsx] --> SharedPage[packages/views/<domain> page]
  DesktopRoute[apps/desktop routes.tsx] --> SharedPage
  SharedPage --> CoreHooks[packages/core queries/mutations]
  SharedPage --> UIComponents[packages/ui components]
  CoreHooks --> API[ApiClient]
  API --> Backend[Go API]
  WebRoute --> WebPlatform[apps/web/platform navigation]
  DesktopRoute --> DesktopPlatform[apps/desktop renderer platform navigation]
  SharedPage --> NavAdapter[NavigationAdapter]
  NavAdapter --> WebPlatform
  NavAdapter --> DesktopPlatform

11. 数据关系简图

erDiagram
  USER ||--o{ MEMBER : joins
  WORKSPACE ||--o{ MEMBER : has
  WORKSPACE ||--o{ AGENT : owns
  WORKSPACE ||--o{ ISSUE : owns
  WORKSPACE ||--o{ PROJECT : owns
  WORKSPACE ||--o{ SKILL : owns
  WORKSPACE ||--o{ AGENT_RUNTIME : has
  WORKSPACE ||--o{ INBOX_ITEM : has
  WORKSPACE ||--o{ ACTIVITY_LOG : has

  AGENT_RUNTIME ||--o{ AGENT : assigned_to
  AGENT ||--o{ AGENT_TASK_QUEUE : runs
  ISSUE ||--o{ AGENT_TASK_QUEUE : triggers
  ISSUE ||--o{ COMMENT : has
  ISSUE ||--o{ ACTIVITY_LOG : logs
  ISSUE ||--o{ INBOX_ITEM : notifies
  PROJECT ||--o{ ISSUE : groups

  SKILL ||--o{ SKILL_FILE : contains
  AGENT ||--o{ AGENT_SKILL : uses
  SKILL ||--o{ AGENT_SKILL : assigned

  CHAT_SESSION ||--o{ CHAT_MESSAGE : has
  CHAT_SESSION ||--o{ AGENT_TASK_QUEUE : triggers

  AUTOPILOT ||--o{ AUTOPILOT_TRIGGER : has
  AUTOPILOT ||--o{ AUTOPILOT_RUN : creates
  AUTOPILOT_RUN ||--o| ISSUE : creates
  AUTOPILOT_RUN ||--o| AGENT_TASK_QUEUE : runs

  SQUAD ||--o{ SQUAD_MEMBER : has
  AGENT ||--o{ SQUAD : leads

12. API 分组图

flowchart TB
  Root[Chi Router] --> Health[/health, /readyz, /healthz/]
  Root --> WS[/ws/]
  Root --> AuthPublic[/auth/*/]
  Root --> PublicAPI[/api/config, contact-sales/]
  Root --> Webhooks[/api/webhooks/*/]
  Root --> Daemon[/api/daemon/*<br/>DaemonAuth/]
  Root --> AuthGroup[Auth group]

  AuthGroup --> UserAPI[/api/me, cli-token, upload-file, invitations, tokens/]
  AuthGroup --> Workspaces[/api/workspaces/*/]
  AuthGroup --> Billing[/api/cloud-billing/*<br/>human actor only/]
  AuthGroup --> WorkspaceGroup[RequireWorkspaceMember]

  WorkspaceGroup --> Issues[/api/issues/*/]
  WorkspaceGroup --> Projects[/api/projects/*/]
  WorkspaceGroup --> Agents[/api/agents/*/]
  WorkspaceGroup --> Skills[/api/skills/*/]
  WorkspaceGroup --> Runtimes[/api/runtimes/*/]
  WorkspaceGroup --> Chat[/api/chat/*/]
  WorkspaceGroup --> Inbox[/api/inbox/*/]
  WorkspaceGroup --> Autopilots[/api/autopilots/*/]
  WorkspaceGroup --> Squads[/api/squads/*/]
  WorkspaceGroup --> Dashboard[/api/dashboard/*/]

13. 文档站产品心智模型

flowchart LR
  subgraph Collaboration["协作层:Server"]
    Workspace[Workspace<br/>工作区]
    Issue[Issue<br/>工作项]
    Comment[Comment<br/>评论/mention]
    Project[Project<br/>项目/资源]
    Agent[Agent<br/>智能体配置]
    Task[Task Queue<br/>agent_task_queue]
    Inbox[Inbox/Activity<br/>通知和时间线]
  end

  subgraph Execution["执行层:用户本机"]
    Daemon[Multica daemon]
    Runtime[Runtime<br/>daemon x provider x workspace]
    Provider[Provider CLI<br/>Codex/Claude/Cursor/etc.]
    Code[Code/API keys/local dirs<br/>留在本机]
  end

  Workspace --> Issue
  Workspace --> Agent
  Workspace --> Project
  Issue --> Comment
  Project --> Issue
  Agent --> Task
  Issue --> Task
  Comment --> Task
  Task --> Runtime
  Runtime --> Daemon
  Daemon --> Provider
  Provider --> Code
  Task --> Inbox

14. 四种智能体触发方式

flowchart TB
  A[把 issue 分配给 agent/squad] --> A1{issue status = backlog?}
  A1 -- yes --> A2[只保存 assignee<br/>暂不入队]
  A1 -- no --> T[创建 task queued]

  B[评论创建,包含 mention://agent 或 mention://squad] --> B1[保存 comment]
  B1 --> B2[ParseMentions + 私有/归档/runtime/pending/self-loop 检查]
  B2 --> T

  C[Chat 发送消息] --> C1[保存 chat_message]
  C1 --> C2[创建 chat task<br/>issue_id = null]
  C2 --> T

  D[Autopilot schedule/manual/webhook] --> D1{execution_mode}
  D1 -- create_issue --> D2[创建 issue<br/>origin_type=autopilot]
  D2 --> T
  D1 -- run_only --> D3[直接创建 autopilot task]
  D3 --> T

  T --> Wake[发布 task:queued<br/>唤醒 daemon]

15. ACME-42 分配给 CodeSmith 的完整时序

sequenceDiagram
  participant Chen as Chen<br/>chen@example.com
  participant UI as Web/Desktop UI
  participant API as Go API
  participant IssueSvc as IssueService
  participant TaskSvc as TaskService
  participant DB as PostgreSQL
  participant WS as WebSocket
  participant D as macbook-pro-chen daemon
  participant Codex as Codex CLI

  Chen->>UI: 创建 ACME-42 并分配给 CodeSmith
  UI->>API: POST /api/issues
  API->>IssueSvc: Create(workspace=acme-ai, assignee=agt_codesmith)
  IssueSvc->>DB: INSERT issue iss_42
  IssueSvc->>WS: issue:created
  IssueSvc->>TaskSvc: EnqueueTaskForIssue(iss_42)
  TaskSvc->>DB: INSERT task_9001 status=queued runtime=rt_mac_01
  TaskSvc->>WS: task:queued
  TaskSvc-->>D: daemon wakeup
  D->>API: claim task for rt_mac_01
  API->>DB: task_9001 queued -> dispatched
  D->>API: start task_9001
  API->>TaskSvc: StartTask
  TaskSvc->>DB: task_9001 dispatched -> running
  TaskSvc->>WS: task:running
  D->>Codex: Execute(prompt + project resources + skills)
  Codex-->>D: messages/progress/usage
  D->>API: report messages/progress/usage
  API->>WS: task/chat/comment events
  Codex-->>D: final result
  D->>API: complete task_9001
  API->>TaskSvc: CompleteTask
  TaskSvc->>DB: task_9001 running -> completed
  TaskSvc->>WS: task:completed

16. 评论 Mention 触发链路

flowchart TD
  Editor[TipTap/RN editor] --> Markdown["[@CodeSmith](mention://agent/agt_codesmith) ..."]
  Markdown --> API[POST /api/issues/iss_42/comments]
  API --> Save[CreateComment<br/>保存 Markdown 原文]
  Save --> Publish[comment:created]
  Save --> Trigger[triggerTasksForComment]
  Trigger --> Parse[util.ParseMentions]
  Parse --> AgentMention{mention type}
  AgentMention -- agent --> CheckA[检查 agent 可访问/未归档/有 runtime/无 pending]
  AgentMention -- squad --> CheckS[解析 squad leader 并检查 readiness]
  AgentMention -- member/issue/all --> NoTask[不创建 agent task]
  CheckA --> Enqueue[EnqueueTaskForMention]
  CheckS --> Leader[EnqueueTaskForSquadLeader]
  Enqueue --> Task[task queued<br/>trigger_comment_id=cmt_501]
  Leader --> Task

17. Chat 沙盒链路

sequenceDiagram
  participant User as Chen
  participant ChatUI as Chat UI
  participant API as Handler.SendChatMessage
  participant DB as PostgreSQL
  participant TaskSvc as TaskService
  participant D as Daemon
  participant Agent as Provider CLI

  User->>ChatUI: 发送私人消息
  ChatUI->>API: POST /api/chat/sessions/chat_100/messages
  API->>DB: INSERT chat_message(role=user)
  API->>TaskSvc: EnqueueChatTask(chat_100)
  TaskSvc->>DB: INSERT task(issue_id=null, chat_session_id=chat_100)
  TaskSvc-->>D: wake runtime
  D->>API: claim chat task
  D->>Agent: prompt 只包含 chat 上下文和用户消息
  Agent-->>D: assistant reply
  D->>API: report/complete
  API->>DB: INSERT chat_message(role=assistant)

18. Autopilot Schedule/Webhook 流程

flowchart TB
  Schedule[DB scheduler<br/>cron due] --> Dispatch[AutopilotService.DispatchAutopilot]
  Manual[POST /api/autopilots/{id}/trigger] --> Dispatch
  Webhook[POST /api/webhooks/autopilots/awt_xxx] --> WH[限流/token/body/event filter/delivery]
  WH --> Dispatch

  Dispatch --> Run[INSERT autopilot_run]
  Run --> Mode{execution_mode}
  Mode -- create_issue --> Issue[CreateIssueWithOrigin<br/>origin_type=autopilot]
  Issue --> Link[run.status=issue_created<br/>run.issue_id=...]
  Link --> IssueTask[EnqueueTaskForIssue<br/>或 EnqueueTaskForSquadLeader]
  Mode -- run_only --> DirectTask[CreateAutopilotTask<br/>run.task_id=...]
  IssueTask --> Daemon[daemon claim and execute]
  DirectTask --> Daemon
  Daemon --> Sync[SyncRunFromIssue/SyncRunFromTask]
  Sync --> Done[autopilot_run completed/failed/skipped]

19. Project Resource 进入执行环境

flowchart TD
  Project[Project Web App] --> R1[github_repo<br/>https://github.com/acme/web-app]
  Project --> R2[local_directory<br/>/Users/chen/code/web-app<br/>daemon=macbook-pro-chen]
  Issue[ACME-42 belongs to Project] --> Claim[Daemon claims task]
  Claim --> Match{local_directory matches daemon?}
  Match -- yes --> Validate[daemon 校验路径存在/目录/读写/黑名单]
  Validate --> Lock[按真实路径加目录锁]
  Lock --> LocalWork[WorkDir = 用户本地目录]
  Match -- no --> Worktree[WorkDir = 隔离 worktree/envRoot]
  R1 --> Context[.multica/project/resources.json<br/>Project Context prompt]
  R2 --> Context
  LocalWork --> Context
  Worktree --> Context
  Context --> Agent[Provider CLI 执行]

20. 认证与 Token 使用范围

flowchart LR
  Browser[Browser Web UI] --> Cookie[JWT Cookie<br/>multica_auth<br/>30 days]
  CLI[CLI / scripts] --> PAT[PAT<br/>mul_...]
  Daemon[Daemon] --> MDT[Daemon Token<br/>mdt_...]

  Cookie --> UserAPI[/api/user + workspace APIs]
  Cookie --> WS[/ws cookie auth]
  PAT --> UserAPI
  PAT --> DaemonAPI[/api/daemon bootstrap/control]
  PAT --> WS2[/ws token auth]
  MDT --> DaemonAPI

  DaemonAPI --> Limited[注册 runtime<br/>心跳<br/>claim task<br/>上报结果]
  UserAPI --> Full[代表完整用户身份]

21. GitHub PR 自动关联

sequenceDiagram
  participant GH as GitHub
  participant API as /api/webhooks/github
  participant DB as PostgreSQL
  participant Bus as events.Bus
  participant UI as Issue UI

  GH->>API: pull_request webhook<br/>branch/title/body contains ACME-42
  API->>API: verify X-Hub-Signature-256
  API->>DB: upsert github_pull_request
  API->>API: extract issue key by workspace prefix
  API->>DB: upsert issue_pull_request(iss_42, pr, close_intent?)
  alt PR merged/closed and auto-close gate passes
    API->>DB: update issue ACME-42 -> done unless cancelled
    API->>Bus: issue:updated actor=system
    Bus-->>UI: WebSocket update
  else PR open/sync
    API-->>UI: PR sidebar updates via realtime/cache refresh
  end

22. 飞书/Lark Bot 到 Chat/Issue

flowchart TB
  LarkMsg[飞书私聊或群 @ Bot] --> Inbound[Lark connector/channel engine]
  Inbound --> Bind{飞书身份已绑定<br/>且是 workspace member?}
  Bind -- no --> Drop[丢弃或返回绑定卡片<br/>不保存消息内容]
  Bind -- yes --> Kind{消息类型}
  Kind -- 普通消息 --> Chat[创建/复用 chat_session<br/>写 chat_message]
  Chat --> ChatTask[EnqueueChatTask]
  ChatTask --> AgentRun[daemon + provider 执行]
  AgentRun --> Done[chat:done]
  Done --> LarkReply[飞书卡片/文本回复]
  Kind -- /issue --> Issue[IssueService.Create]
  Issue --> Board[Multica issue 看板]
This post is licensed under CC BY 4.0 by the author.