Time Compass 系統架構快速導覽¶
用途: 30 秒了解系統構成
對象: 新開發者、架構師、決策者
深入指南: → 各主題參考
C1: System Context(系統邊界)¶
Time Compass 是一個時程調度規劃助手,與三個外部系統通信:
graph TB
User["👤 使用者<br/>(網頁/AI助理)"]
TC["📱 Time Compass<br/>(調度規劃系統)"]
GC["Google Calendar"]
GT["Google Tasks"]
Moodle["Moodle 課程管理系統<br/>(爬蟲)"]
User -->|提問、拖放事件| TC
TC -->|查詢/創建| GC
TC -->|查詢/創建| GT
TC -->|爬蟲取資料| Moodle
GC -->|日程事件| TC
GT -->|工作清單| TC
Moodle -->|課程、截止日期| TC C2: Containers(主要服務)¶
系統採用 MCP-First 並行雙入口架構,同時維持舊 Gradio 容器支援:
graph TB
subgraph "接入層"
MCP["🔌 MCP Server<br/>(新推薦)"]
Gradio["🎨 Gradio Web UI<br/>(遺留)"]
Planner["🎨 Planner Studio<br/>(微前端)"]
end
subgraph "業務邏輯層"
Core["⚙️ async_core<br/>"]
Integration["🔌 Integration Layer<br/>(Google, Moodle)"]
end
subgraph "資料層"
DB["💾 Cache"]
end
external["🌍 外部 API"]
Planner -->|MCP 工具呼叫| MCP
Gradio -->|HTTP Tab 互動| Core
MCP -->|編排工具、觸發任務| Core
Core -->|轉換、一致性檢查| Integration
Integration -->|API 呼叫| external
external -->|回應| Integration
Integration -->|更新| DB
Core -->|查詢| DB 各容器責任¶
| 容器 | 架構地位 | 職責 | 關鍵組件 | 啟動方式 |
|---|---|---|---|---|
| MCP Server | 🟢 推薦 | 暴露 15 個工具給 Claude/Cursor IDE | src/time_compass/mcp/server.py、15 個工具 | uv run time-compass-mcp |
| Gradio Web UI | 🟡 並行支援 | 獨立網頁 Tab 式介面(port 8000) | src/time_compass/interface/server.py、5 個 Tab | uv run time-compass-gradio |
| Planner Studio | 🟢 推薦 | 零框架縮放排程工具 | FullCalendar 6.1 + 自製縮放、衝突 detection | MCP 內 launch_planner_studio() 工具觸發 |
| async_core | 核心 | 編排 DDD、驅動 Prompts、統一錯誤處理 | integrations/async_core.py、Result Monad | - |
| Integration Layer | 核心 | 統一 Google/Moodle API 呼叫、資料轉換管道 | integrations/{google_calendar, google_tasks, moodle}/async_core.py | - |
| Data/Cache | 底層 | 事件、任務、課程資料快取 | 本地或 Google Cloud 存儲 | - |
架構地位說明: - 🟢 推薦:符合現代設計,計劃持續投資 - 🟡 並行支援:仍可用,與推薦並行,但不再主要特性開發 - 🔴 遺留:已停止維護(此系統無此類)
容器選擇指南¶
我是 AI 助理開發者 → 使用 MCP Server
我要手動管理排程 → 使用 Gradio Web UI 或 Planner Studio
我要整合新的資料來源 → 修改 Integration Layer
Gradio Web UI 工作流程(並行容器)¶
Gradio 是同步 Web 介面,提供 5 個互動 Tab,但重點在於與 Orchestrator 的協作。用戶輸入驅動完整的 AI 決策流水線:
graph TB
User["👤 使用者<br/>(瀏覽器輸入)"]
subgraph Gradio["🎨 Gradio Web UI (port 8000)"]
OAuth["🔐 OAuth<br/>Tab 1"]
Debug["🐛 Debug/Test<br/>Tab 2"]
GoogleTasks["✅ Google Tasks<br/>Tab 3"]
Scheduling["📅 Scheduling<br/>Tab 4"]
Moodle["📚 Moodle<br/>Tab 5"]
end
subgraph AI["🧠 AI 決策層 (Orchestrator)"]
Router["Router<br/>(決定流程)"]
Pipeline["Pipeline<br/>(多模組序列)"]
end
subgraph Backend["⚙️ Integration Layer<br/>(並行抓取)"]
Cal["Google Calendar"]
Task["Google Tasks"]
Mood["Moodle"]
end
User -->|提問或請求| Scheduling
Scheduling -->|user_input| Router
Router -->|pipeline決定| Pipeline
Backend -.->|並行抓取<br/>(Summary/Scheduling<br/>讀取)| Pipeline
Pipeline -->|EmotionSupport<br/>Summary<br/>Scheduling| StreamOutput["串流輸出"]
Scheduling -->|寫入<br/>(直接)| Task
StreamOutput -->|更新UI| Scheduling
Scheduling -.->|展示結果| User
OAuth -.->|管理 Token| OAuth
Debug -.->|測試 API| Debug
GoogleTasks -.->|列表檢視| GoogleTasks
Moodle -.->|爬蟲課程| Moodle Gradio 中的 AI 互動流程¶
| 步驟 | 元件 | 職責 |
|---|---|---|
| 1. 用戶輸入 | Scheduling Tab | 接收自由文字提問 |
| 2. 路由決策 | Router Module | 分析意圖,決定要執行的 Pipeline(情緒支持 → 摘要 → 排程等) |
| 3. 並行抓取 | Integration Layer | 同時取 Google Calendar/Tasks/Moodle 資料(背景進行) |
| 4. 資料注入 | Summary/Scheduling 模組 | 將抓取的資料注入 InteractionContext |
| 5. 流程編排 | Pipeline Executor | 依序執行各模組,每個模組讀取 Context 中的資料 |
| 6. 串流回應 | streaming.py | 逐 chunk 推送結果回前端(格式:[Module:field] text) |
| 7. 寫入操作 | Scheduling Tab | 若用戶確認排程,直接寫入 Google Tasks |
| 8. UI 更新 | Gradio ChatInterface | 即時顯示 AI 回應與建議 |
Gradio 的 5 個 Tab¶
| Tab | 功能 | 資料流 | 核心操作 |
|---|---|---|---|
| 🔐 OAuth Login | Google OAuth 授權、token 管理 | 同步 | 初始授權 → Token 刷新 → 帳號切換 |
| 🐛 Debug/Test Request | 直接呼叫 API 測試、查看回應 | 同步 | 構造要求 → 執行 → 檢視原始回應 |
| ✅ Google Tasks | 管理 Google Tasks 工作列表 | 同步 | 列表查看 → 建立任務 → 更新狀態 → 刪除任務 |
| 📅 Scheduling & Planning | AI 輔助排程(核心) | 異步 + Pipeline | 輸入 → Router → Pipeline(讀 Integration 資料) → 寫 Google Tasks |
| 📚 Moodle Integration | 爬蟲取課程資訊、截止日期 | 同步爬蟲 | 帳號登入 → 爬蟲課程 → 檢視課程事件 |
Scheduling Tab 內的 AI 互動細節: - 使用者提問 → Orchestrator.forward(user_input) 呼叫 - 並行背景:Integration Layer 同時抓取 Google Calendar、Google Tasks、Moodle 資料 - Router 模組決定 Pipeline:[EmotionSupport → Summary → Scheduling] 等序列 - 各模組接收 InteractionContext(含歷史、上下文、已抓取的時程資料) - Summary 和 Scheduling 模組從 Context 讀取 Calendar/Tasks/Moodle 資料,無需再次 API 呼叫 - 串流回應逐 chunk yield,格式為 [ModuleName:FieldName] content - 寫入時:用戶確認建議 → 直接呼叫 Google Tasks write API - 前端即時更新 ChatInterface 顯示結果與建議
詳見:docs/time_compass/domain/orchestrator.md
Gradio 與 Integration Layer 的互動¶
Gradio 與 MCP 都是通過 Integration Layer 的統一 API 呼叫資料來源:
讀取操作:
├─ Gradio: async_get_all_tasks() / async_get_all_events() / scrape_moodle_events()
└─ MCP: 相同的 API(無框架耦合)
寫入操作:
├─ Gradio: async_task_insert()(Google Tasks 寫入)
└─ MCP: 相同的 API(透過工具呼叫)
核心相同性:Gradio 與 MCP 都使用 Integration Layer 中的統一 async 函數,無需關心底層 Batch API 細節。
Orchestrator 與 AI 決策層(C3 邏輯編排)¶
Gradio 和 MCP 都透過 Orchestrator 驅動 AI 決策。Orchestrator 的核心職責是協調多個 LLM 模組形成完整的推理流水線:
graph TB
UserInput["使用者輸入<br/>(自由文字)"]
Orch["Orchestrator<br/>(編排器)"]
Router["🧭 Router Module<br/>(意圖分析)"]
Pipeline["📊 Pipeline<br/>(決策序列)"]
Emotion["EmotionSupport<br/>(情緒陪伴)"]
Summary["Summary<br/>(活動回顧)"]
Sched["Scheduling<br>(排程建議)"]
Context["InteractionContext<br>(對話上下文 + 時程資料)"]
Integration["Integration Layer<br>(Google + Moodle 資料)"]
Output["final_reply<br>(整合回應)"]
UserInput -->|user_input| Orch
Orch -->|dialog_history| Router
Router -->|pipeline決定<br>(順序 & 模組)| Pipeline
Pipeline -->|分派| Emotion
Pipeline -->|分派| Summary
Pipeline -->|分派| Sched
Orch -->|構建| Context
Context -->|包含| Integration
Emotion -->|InteractionContext| Pipeline
Summary -->|InteractionContext| Pipeline
Sched -->|InteractionContext| Pipeline
Pipeline -->|聚合輸出| Output Orchestrator 工作流程¶
- Router 分析意圖:根據
user_input決定 Pipeline 序列 -
例:用戶「這週很累」→ Pipeline =
[EmotionSupport → Summary → ask_question] -
構建 InteractionContext:收集對話歷史、時程資料、之前模組的輸出
-
依序執行 Pipeline:每個模組接收完整的 Context,回傳結構化輸出
-
優先級邏輯(由 Router 決策,不同情境不同):
- 純規劃場景 →
[Scheduling] - 迷茫/疲勞場景 →
[EmotionSupport → ask_question → draft_plan] -
總結場景 →
[Summary → draft_plan → draft_action] -
Streaming 輸出(Gradio 特性):邊執行邊 yield chunk,每個 chunk 標記模組與欄位:
[Router:pipeline_description] 我會幫你規劃... [EmotionSupport:output] 聽起來你這週... [Summary:summary_text] 過去三天的活動... [Scheduling:draft_schedule] 建議時段:...
Pipeline 的標準模組¶
| 模組 | 用途 | 輸入 | 輸出 |
|---|---|---|---|
| Router | 意圖分析與流程決策 | user_input, dialog_history | pipeline, pipeline_description |
| EmotionSupport | 心理陪伴(若需要) | InteractionContext | support_text, action_suggestion |
| Summary | 區間活動回顧 | InteractionContext + calendar/tasks 資料 | summary_text, insights |
| Scheduling | 排程建議與衝突檢測 | InteractionContext + 完整時程資料 | draft_schedule, risks, next_steps |
| ask_question | 澄清缺失資訊 | InteractionContext | questions, constraints, follow_up_suggestion |
詳細說明與流程圖:docs/time_compass/domain/orchestrator.md
Gradio 與 MCP 共享的 Orchestrator¶
兩個容器都使用相同的 Orchestrator,區別在: - Gradio:同步 HTTP 請求 → orch.forward(input) → 串流回應 - MCP:工具調用 → get_time_context() + draft_plan_prompt() → 提示回傳
這是「多入口同邏輯」的典型設計。
Integration Layer(C3 實現細節)¶
三個整合模組¶
integrations/
├── common/ ← 共通層
│ ├── exceptions.py (8 種 GoogleError 定義)
│ ├── google_api_dispatcher.py (Batch API 分派器、HTTP Multipart 編碼)
│ └── ...
│
├── google_calendar/ ← Google Calendar 模組
│ ├── async_core.py (取日程、建事件、查詢時段)
│ └── models/
│ ├── models_raw.py (47+欄位,camelCase)
│ ├── models_read.py (datetime 保留,應用層最佳化)
│ └── models_toon.py (索引地點、重複規則、TOON 編碼)
│
├── google_tasks/ ← Google Tasks 模組
│ ├── async_core.py (取清單、建工作、狀態管理)
│ └── models/
│ ├── models_raw.py (18 欄位)
│ ├── models_read.py (Eager-cast 為字串)
│ └── models_toon.py (按狀態分組、TOON 編碼)
│
└── moodle/ ← Moodle 爬蟲模組
├── async_core.py (Web Scraper + OIDC + Selenium)
└── models/
├── models_raw.py (55+ 欄位)
├── models_internal.py (HTML 清洗、時區轉 UTC+8)
├── models_read.py (語意化狀態、8 欄位精簡)
└── ...
四層資料模型¶
每個模組都遵循 Raw → Internal → Read → TOON 轉換:
| 層 | 用途 | 例:Calendar |
|---|---|---|
| Raw | 100% API 映射,無修改 | GoogleEventRaw(47 欄位,camelCase) |
| Internal/Domain | 反腐層,清洗格式 | GoogleEventRead(datetime 物件保留) |
| Read | 應用層最佳化 | ToonCalendar(索引化地點、日期元件化) |
| TOON | 極致壓縮 | TOON 字串格式(Token 節省 83.7%) |
錯誤處理(Railway-Oriented)¶
所有操作返回 Result[T],不拋異常:
Result[ListEventsResponse] = Ok(events) | Err(GoogleAuthError(...))
8 種錯誤分類: - GoogleAuthError (401/403) → 需用戶重新授權 - GoogleNetworkError (timeout) → 指數退避重試 - GoogleParseError (JSON) → 記錄,上報bug - GoogleRateLimitError (429) → 可重試 - GoogleNotFoundError (404) → 忽略或提示用戶 - ...等
詳細說明: → ERROR-HANDLING
資料轉換流水線¶
graph LR
Raw["外部 API JSON<br/>(Raw Layer)"]
Internal["內部轉換<br/>(HTML 清洗、時區轉)<br/>(Internal Layer)"]
Read["讀取模型<br/>(應用層最佳化)<br/>(Read Layer)"]
TOON["TOON 格式<br/>(極致壓縮)<br/>83.7% token 節省"]
Raw -->|from_dict| Internal
Internal -->|to_read| Read
Read -->|safe_encode| TOON 詳細解釋: → DDD-ARCHITECTURE
C3: Integration 層(資料來源通訊)¶
時程規劃系統的關鍵:與三個外部資料源並行通信。
graph TB
subgraph Integration["🔌 Integration Layer"]
Common["共通層<br/>exceptions.py<br/>google_api_dispatcher.py<br/>http_batch_tool.py"]
subgraph Google["Google API (Batch 模式)"]
Cal["Google Calendar<br/>async_get_all_events()"]
Task["Google Tasks<br/>async_get_all_tasks()"]
end
Moodle["Moodle (Web 爬蟲)<br/>scrape_moodle_events()"]
Coord["🔥 頂級協調<br/>async_get_all_information_from_api()"]
end
Common -.->|支援| Google
Common -.->|支援| Moodle
Cal -->|結果| Coord
Task -->|結果| Coord
Moodle -->|結果| Coord
Coord -->|返回| ResourceContext["ResourceContext<br/>(三合一結果)"]
style Common fill:#fff3e0
style Google fill:#f3e5f5
style Moodle fill:#fce4ec
style Coord fill:#e1f5fe Integration 層三大支柱¶
| 支柱 | 技術 | 特點 |
|---|---|---|
| Google APIs | Batch API + 非同步 Generator | 多個日曆/工作列表並行,自動分頁,速度快 |
| Moodle 爬蟲 | OIDC 登入 + Selenium Fallback | 課程資訊抓取,60s 超時保障 |
| 共通層 | Dispatcher + Multipart Builder | 統一例外體系、Type-Safe 回傳、結構化 Batch 請求 |
深入指南: - � 完整 C4 Model 文檔: ../reference/INTEGRATION/C4_MODEL.md(涵蓋 L1-L4 四層)
核心設計原則¶
Railway-Oriented Programming¶
所有操作使用 Result[T] 型別,明確表達成功/失敗,避免例外被吞掉。
深入了解: → ERROR-HANDLING
多源並行抓取¶
Google Calendar、Google Tasks、Moodle 並行執行,每個獨立失敗且有重試機制。
工具手冊: → MCP-TOOLS
零框架前端¶
Vanilla JavaScript,無打包步驟,<500ms 啟動。
實作指南: → FRONTEND
Prompts 系統設計(雙源非 SOT)¶
系統的 Prompt 定義採用非 SOT(Single Source of Truth)設計 - 由 Gradio 時代(domain/)和 MCP 時代(mcp/prompts/)各自維護一份:
domain/ (舊 DSPy/Gradio 時代)
├── summary/prompt/
│ ├── summary_tool.md ( LLM 工具簽名 )
│ └── summary_writer.md ( 活動回顧工具 )
├── schedule/prompt/
│ ├── router.md ( 路由邏輯 )
│ ├── draft_plan.md ( 初步規劃 )
│ ├── draft_action.md ( 可執行排程 )
│ └── ask_question.md ( 澄清問題 )
└── router/prompt/
└── ...
mcp/prompts/ (新 MCP 時代)
├── domain_prompts.py ( 函數定義 + 載入器 )
└── content/
├── summary_writer.md (↑ 對應 domain/ 版本)
├── emotion_support.md (新增,Gradio 無)
├── draft_plan_prompt.md
├── draft_action_prompt.md
├── scheduling_router_prompt.md
└── ...
為什麼非 SOT? - ✅ 獨立演進:Gradio 和 MCP 可各自迭代 Prompt,無需同步 - ✅ 已知差異:系統隨時意識到雙版本可能不同步,監控標記已設置 - ✅ 漸進遷移:無需一次性遷移所有 Prompt,可按需逐步更新
如何同步? 詳見 ADR-0010: 文檔類資源統一架構
想深入某個主題?¶
選擇妳的探索路徑:
| 我想... | 去這裡 |
|---|---|
| 理解四層資料轉換(Raw → Internal → Read → TOON) | DDD-ARCHITECTURE |
| 詳細了解 Integration 層(Google + Moodle 通信) | Integration C4 Model |
| 了解 Orchestrator 與 Router 如何運作 | docs/time_compass/domain/orchestrator.md、router.md |
| 學習各 Pipeline 模組的設計 | emotion.md、summary.md、scheduling/ |
| 了解串流如何工作(Gradio 特性) | docs/time_compass/domain/orchestrator.md |
| 了解錯誤處理怎麼做(為什麼用 Railway?) | ERROR-HANDLING |
| 學習 15 個 MCP 工具的設計與用法 | MCP-TOOLS |
| 看前端零框架怎麼運作(FullCalendar + 縮放) | FRONTEND |
| 查看整個系統的資料流圖 | data-flow.md |
| 了解開發模式設計決策 | DEV_MODE_GUIDE.md |
| 理解 Prompts 為什麼非 SOT 設計 | ADR-0010 |
推薦的新手閱讀順序¶
- 第一遍(15 分鐘):讀本頁,了解 C1-C2 邊界與容器
- 第二遍(30 分鐘):進 reference/README.md 選一個主題深入
- 第三遍(1 小時+):依據工作需要在各主題中深潜
往更上層看¶
想了解為什麼做了這些架構選擇?
→ Architecture Decision Records (ADR) - 從 ADR-0001 開始
想知道團隊的願景?
→ 願景與故事