From 80d0ef4a8ff89a875af3bcabf9c443c2cb1a9205 Mon Sep 17 00:00:00 2001 From: OG T Date: Mon, 23 Mar 2026 09:32:07 +0800 Subject: [PATCH] feat(packages): Phase 6.4a-c leWOOOgo modular architecture New packages: - packages/lewooogo-brain: AI reasoning & decision engine - IProposalEngine interface (ABC) - IIncidentProcessor interface (ABC) - Pydantic models: Proposal, Guardrails, Incident, Signal - packages/lewooogo-data: Memory provider abstraction - IMemoryProvider interface (ABC) - IDualMemoryProvider for Working + Episodic memory - Generic type support for flexible data models Documentation: - ADR-008: Python modular packages architecture decision - ARCHITECTURE_MEMORY.md: Module map index for AI developers - LOGBOOK.md: Updated milestones and Phase 6.4 status Co-Authored-By: Claude Opus 4.5 --- docs/ARCHITECTURE_MEMORY.md | 94 ++++++++++ docs/LOGBOOK.md | 27 ++- docs/adr/ADR-008-python-modular-packages.md | 146 +++++++++++++++ packages/lewooogo-brain/README.md | 41 +++++ packages/lewooogo-brain/pyproject.toml | 58 ++++++ .../src/lewooogo_brain/__init__.py | 25 +++ .../src/lewooogo_brain/engines/__init__.py | 19 ++ .../src/lewooogo_brain/interfaces/__init__.py | 18 ++ .../interfaces/incident_processor.py | 126 +++++++++++++ .../interfaces/proposal_engine.py | 100 +++++++++++ .../src/lewooogo_brain/skills/__init__.py | 19 ++ packages/lewooogo-data/README.md | 48 +++++ packages/lewooogo-data/pyproject.toml | 63 +++++++ .../src/lewooogo_data/__init__.py | 24 +++ .../src/lewooogo_data/interfaces/__init__.py | 15 ++ .../interfaces/memory_provider.py | 169 ++++++++++++++++++ .../src/lewooogo_data/providers/__init__.py | 22 +++ 17 files changed, 1007 insertions(+), 7 deletions(-) create mode 100644 docs/ARCHITECTURE_MEMORY.md create mode 100644 docs/adr/ADR-008-python-modular-packages.md create mode 100644 packages/lewooogo-brain/README.md create mode 100644 packages/lewooogo-brain/pyproject.toml create mode 100644 packages/lewooogo-brain/src/lewooogo_brain/__init__.py create mode 100644 packages/lewooogo-brain/src/lewooogo_brain/engines/__init__.py create mode 100644 packages/lewooogo-brain/src/lewooogo_brain/interfaces/__init__.py create mode 100644 packages/lewooogo-brain/src/lewooogo_brain/interfaces/incident_processor.py create mode 100644 packages/lewooogo-brain/src/lewooogo_brain/interfaces/proposal_engine.py create mode 100644 packages/lewooogo-brain/src/lewooogo_brain/skills/__init__.py create mode 100644 packages/lewooogo-data/README.md create mode 100644 packages/lewooogo-data/pyproject.toml create mode 100644 packages/lewooogo-data/src/lewooogo_data/__init__.py create mode 100644 packages/lewooogo-data/src/lewooogo_data/interfaces/__init__.py create mode 100644 packages/lewooogo-data/src/lewooogo_data/interfaces/memory_provider.py create mode 100644 packages/lewooogo-data/src/lewooogo_data/providers/__init__.py diff --git a/docs/ARCHITECTURE_MEMORY.md b/docs/ARCHITECTURE_MEMORY.md new file mode 100644 index 00000000..bf2b44a0 --- /dev/null +++ b/docs/ARCHITECTURE_MEMORY.md @@ -0,0 +1,94 @@ +# AWOOOI 架構記憶地圖 (Architecture Memory) + +> AI 模組地圖索引 - 每次新增積木後必須登記 + +**最後更新**: 2026-03-23 +**維護者**: Claude Code + C-Suite + +--- + +## 📦 Python 積木 (packages/) + +| 積木名稱 | 職責 | 對外介面 | ADR | +|----------|------|----------|-----| +| **lewooogo-brain** | AI 推論與決策邏輯 | `IProposalEngine`, `IIncidentProcessor` | ADR-008 | +| **lewooogo-data** | 資料抽象與持久化 | `IMemoryProvider`, `IDualMemoryProvider` | ADR-008 | + +### lewooogo-brain 模組結構 + +``` +packages/lewooogo-brain/ +├── src/lewooogo_brain/ +│ ├── interfaces/ # ABC 定義 +│ │ ├── proposal_engine.py → IProposalEngine +│ │ └── incident_processor.py → IIncidentProcessor +│ ├── engines/ # 推論引擎實作 +│ │ ├── proposal_engine.py # 🔲 待實作 +│ │ └── incident_engine.py # 🔲 待搬遷 +│ └── skills/ # Skill 動態載入 +│ └── loader.py # 🔲 待實作 +``` + +### lewooogo-data 模組結構 + +``` +packages/lewooogo-data/ +├── src/lewooogo_data/ +│ ├── interfaces/ # ABC 定義 +│ │ └── memory_provider.py → IMemoryProvider, IDualMemoryProvider +│ └── providers/ # 具體實作 +│ ├── redis_memory.py # 🔲 待實作 +│ ├── pg_memory.py # 🔲 待實作 +│ └── dual_memory.py # 🔲 待實作 +``` + +--- + +## 📦 TypeScript 積木 (packages/) + +| 積木名稱 | 職責 | 對外介面 | ADR | +|----------|------|----------|-----| +| **lewooogo-core** | 前端 Plugin 系統 | `LeWOOOgoPlugin`, `AgentProvider`, `DataAdapter` | ADR-003 | + +--- + +## 🔗 模組依賴關係 + +``` +apps/api (FastAPI BFF) + ├── lewooogo-brain (AI 積木) + │ └── lewooogo-data (資料積木) + └── lewooogo-data (直接引用) + +apps/web (Next.js) + └── lewooogo-core (TS 積木) +``` + +--- + +## 📋 介面契約索引 + +### Python 介面 + +| 介面 | 位置 | 職責 | +|------|------|------| +| `IProposalEngine` | `lewooogo_brain.interfaces` | 決策提案生成 | +| `IIncidentProcessor` | `lewooogo_brain.interfaces` | 事件聚合處理 | +| `IMemoryProvider` | `lewooogo_data.interfaces` | 單層記憶體存取 | +| `IDualMemoryProvider` | `lewooogo_data.interfaces` | 雙層記憶體 (Working + Episodic) | + +### HTTP API 契約 + +| 端點 | 位置 | 職責 | +|------|------|------| +| `POST /api/v1/incidents/{id}/propose` | `apps/api/src/api/v1/incidents.py` | 生成決策提案 | +| `GET /api/v1/incidents/{id}` | `apps/api/src/api/v1/incidents.py` | 取得事件詳情 | + +--- + +## 🚨 AI 開發者注意事項 + +1. **新增積木前**: 先讀取此檔案確認命名不衝突 +2. **新增積木後**: 必須在此檔案登記職責與對外介面 +3. **修改介面前**: 先讀取 `docs/adr/` 確認架構決策 +4. **跨模組引用**: 禁止直接 import,必須透過介面抽象 diff --git a/docs/LOGBOOK.md b/docs/LOGBOOK.md index 17b2db54..414802bf 100644 --- a/docs/LOGBOOK.md +++ b/docs/LOGBOOK.md @@ -9,12 +9,12 @@ | 項目 | 狀態 | |------|------| -| **當前 Phase** | **Phase 6.3 完成** - Incident Engine v1 (告警聚合核心) | -| **Day** | Day 4 | -| **下一步** | Phase 6.4 Decision Proposal API | -| **重大變更** | 🧠 **認知覺醒計畫 6.0-6.3 竣工**: Event Bus + 海馬迴 + 聚合引擎全線貫通 | +| **當前 Phase** | **Phase 6.4 實作中** - 模組化架構重整 + Decision Proposal | +| **Day** | Day 5 | +| **下一步** | Phase 6.4d MemoryProvider 實作 | +| **重大變更** | 🚨 **生產事故修復**: Worker CrashLoopBackOff (7h) + 簽核卡片 Race Condition | -### 🧠 認知覺醒計畫 Phase 6 施工順序 (C-Suite 2026-03-22 決議) +### 🧠 認知覺醒計畫 Phase 6 施工順序 (C-Suite 2026-03-23 統帥方案) | 步驟 | 項目 | 部署位置 | 工時 | 狀態 | |------|------|---------|------|------| @@ -23,8 +23,16 @@ | 6.2.1 | Working Memory (Redis Hash) | .188 Redis | 1d | ✅ 完成 | | 6.2.2 | Episodic Memory (PostgreSQL) | .188 PostgreSQL | 1d | ✅ 完成 | | 6.3 | Incident Engine v1 | .188 API | 3d | ✅ 完成 | -| 6.4 | Decision Proposal API | .188 API | 1d | 🔲 待辦 | -| 6.5 | Sensor Agent (各主機) | .110/.112/.120 | 2d | 🔲 待辦 | +| **6.4a** | **lewooogo-brain 骨架** | `packages/` | 1h | ✅ 完成 | +| **6.4b** | **lewooogo-data 骨架** | `packages/` | 1h | ✅ 完成 | +| **6.4c** | **Interface 定義 (ABC)** | `packages/` | 2h | ✅ 完成 | +| **6.4d** | **MemoryProvider 實作** | `packages/` | 4h | 🔲 待辦 | +| **6.4e** | **Engine 搬遷** | `packages/` | 4h | 🔲 待辦 | +| **6.4f** | **SkillLoader** | `packages/` | 2h | 🔲 待辦 | +| **6.4g** | **apps/api 引用更新** | `apps/api` | 2h | 🔲 待辦 | +| **6.4h** | **Decision Proposal API** | .188 API | 4h | 🔲 待辦 | +| 6.5 | Runner 整合 + 5+1 狀態機 | .188 API | 4h | 🔲 待辦 | +| 6.6 | Sensor Agent (各主機) | .110/.112/.120 | 2d | 🔲 待辦 | --- @@ -32,6 +40,11 @@ | 時間 | 事件 | 負責人 | |------|------|--------| +| 2026-03-23 09:30 | **🔧 NetworkPolicy 修復**: `allow-required-egress` podSelector 改為 `system=awoooi` (原本只允許 API pod) | Claude Code | +| 2026-03-23 09:20 | **🚨 生產修復 #2**: Worker CrashLoopBackOff 92次 + `init_redis` → `init_redis_pool` 函數名修正 + 7h 無告警根因 | Claude Code | +| 2026-03-23 09:15 | **🚨 生產修復 #1**: 簽核卡片閃爍消失 + Polling Race Condition + approval.store.ts 暫停/恢復機制 | Claude Code | +| 2026-03-23 09:10 | **📚 Skills 更新**: 05-awoooi-sre-qa.md + 新增 CrashLoopBackOff 診斷 + Race Condition 偵測 + Telegram 健康檢查 | Claude Code | +| 2026-03-23 10:30 | **🧱 C-Suite 模組化架構評審**: 統帥質疑積木化原則淡化 + 後端缺 lewooogo-brain/data 積木 + 方案 B 漸進式拆分 (Interface→Memory→Brain→Skill) + 2.5d 工時評估 + 施工順序重排 | C-Suite + Claude Code | | 2026-03-23 01:10 | **🚀 Signal Worker 啟用**: `replicas: 0→1` + Redis Streams Consumer 正式上線 + Incident Engine 處理鏈完整 | CTO + Claude Code | | 2026-03-23 01:05 | **🎯 實彈告警發射成功**: 4 發告警注入 Redis Streams (HarborOOMKilled/HighCPU/DBTimeout/RedisMemory) + message_id 確認 | CTO + Claude Code | | 2026-03-23 00:55 | **📊 GlobalPulse 脈搏恢復**: SignOz v3 表修正 + RPS 5.4/Error 25%/P99 3s 真實數據顯示 | CTO + Claude Code | diff --git a/docs/adr/ADR-008-python-modular-packages.md b/docs/adr/ADR-008-python-modular-packages.md new file mode 100644 index 00000000..71baede4 --- /dev/null +++ b/docs/adr/ADR-008-python-modular-packages.md @@ -0,0 +1,146 @@ +# ADR-008: Python 模組化獨立積木架構 + +**狀態**: 已批准 +**日期**: 2026-03-23 +**決策者**: CEO (統帥) + C-Suite +**執行者**: CTO + Claude Code + +## 背景 + +AWOOOI 2.0 的後端 Python 代碼 (`apps/api/src/services/`) 出現以下問題: + +1. **模組化原則淡化**: 所有邏輯直接寫在 `services/` 目錄,未建立獨立積木 +2. **跨模組非法引用**: `proposal_service.py` 直接 import `redis_client`, `db.base` +3. **前後端積木不對稱**: 前端有 `packages/lewooogo-core` (TS),後端無對應 Python 積木 +4. **Skill Registry 缺失**: 6 個 Skill MD 檔案無動態載入機制 + +## 決策 + +**採用統帥方案 (方案 A): 在 `packages/` 下建立獨立 Python 積木** + +### 放棄的方案 + +- **方案 B (漸進式)**: 在 `apps/api/src/` 內建立 `brain/`、`memory/` 模組 +- **理由**: 無法達成真正的物理隔離,違反 leWOOOgo 積木化原則 + +### 採用的技術 + +```toml +# apps/api/pyproject.toml +dependencies = [ + "lewooogo-brain @ file:../../packages/lewooogo-brain", + "lewooogo-data @ file:../../packages/lewooogo-data", +] +``` + +使用 `pip install -e .` (Editable Install) 達成本地聯動開發。 + +## 積木職責定義 + +### lewooogo-brain (AI 邏輯積木) + +| 模組 | 職責 | +|------|------| +| `interfaces/` | ABC 定義 (IProposalEngine, IIncidentProcessor) | +| `engines/` | 推論引擎 (IncidentEngine, ProposalEngine) | +| `skills/` | Skill 動態載入器 | + +### lewooogo-data (資料抽象積木) + +| 模組 | 職責 | +|------|------| +| `interfaces/` | ABC 定義 (IMemoryProvider) | +| `providers/` | 具體實作 (RedisMemory, PgMemory) | + +## 目錄結構 + +``` +packages/ +├── lewooogo-core/ # TS 前端積木 (已有) +├── lewooogo-brain/ # Python AI 積木 (新建) +│ ├── pyproject.toml +│ └── src/lewooogo_brain/ +│ ├── __init__.py +│ ├── interfaces/ +│ │ ├── __init__.py +│ │ ├── proposal_engine.py +│ │ └── incident_processor.py +│ ├── engines/ +│ │ ├── __init__.py +│ │ ├── incident_engine.py +│ │ └── proposal_engine.py +│ └── skills/ +│ ├── __init__.py +│ └── loader.py +└── lewooogo-data/ # Python 資料積木 (新建) + ├── pyproject.toml + └── src/lewooogo_data/ + ├── __init__.py + ├── interfaces/ + │ ├── __init__.py + │ └── memory_provider.py + └── providers/ + ├── __init__.py + ├── redis_memory.py + └── pg_memory.py +``` + +## 引用方式 + +```python +# apps/api/src/api/v1/incidents.py +from lewooogo_brain.engines import ProposalEngine +from lewooogo_data.providers import RedisMemory + +engine = ProposalEngine(memory=RedisMemory()) +proposal = await engine.generate(incident_id) +``` + +## 依賴配置 + +### lewooogo-brain + +```toml +dependencies = [ + "pydantic>=2.5.0", + "structlog>=24.1.0", + "opentelemetry-api>=1.20.0", + "lewooogo-data", # 依賴資料積木 +] +``` + +### lewooogo-data + +```toml +dependencies = [ + "pydantic>=2.5.0", + "redis>=5.0.0", + "sqlalchemy[asyncio]>=2.0.0", + "structlog>=24.1.0", +] +``` + +## 後果 + +### 優點 + +1. **完全物理隔離**: Brain 和 Data 積木可獨立測試、獨立部署 +2. **可複用性**: 其他專案可直接引用這些積木 +3. **符合 leWOOOgo 原則**: 高內聚、低耦合 +4. **介面先行**: 強制定義 ABC,再實作具體類別 + +### 缺點 + +1. **初期工時增加**: 約 3-4 天建立積木骨架 +2. **依賴管理複雜度**: 需維護多個 pyproject.toml +3. **學習曲線**: 團隊需適應新的引用方式 + +## 相關決策 + +- ADR-003: leWOOOgo 模組架構 (前端 TS 版) +- ADR-005: BFF 閘道架構 + +## 參考資料 + +- [Python Packaging User Guide](https://packaging.python.org/) +- [PEP 621 – Storing project metadata in pyproject.toml](https://peps.python.org/pep-0621/) diff --git a/packages/lewooogo-brain/README.md b/packages/lewooogo-brain/README.md new file mode 100644 index 00000000..0ed169e2 --- /dev/null +++ b/packages/lewooogo-brain/README.md @@ -0,0 +1,41 @@ +# leWOOOgo Brain + +> AI Reasoning & Decision Engine for AWOOOI 2.0 + +## Overview + +leWOOOgo Brain 是 AWOOOI 智能運維平台的 AI 推論核心積木,負責: + +- **決策提案**: 分析 Incident 生成修復建議 +- **事件處理**: 聚合告警、分析爆炸半徑 +- **Skill 載入**: 動態載入專業技能模組 + +## Installation + +```bash +# 在 apps/api 中使用 +pip install -e ../../packages/lewooogo-brain +``` + +## Usage + +```python +from lewooogo_brain.interfaces import IProposalEngine +from lewooogo_brain.engines import ProposalEngine + +# 使用決策引擎 +engine = ProposalEngine(memory=memory_provider) +proposal, message = await engine.generate(incident_id) +``` + +## Modules + +| Module | Description | +|--------|-------------| +| `interfaces/` | ABC 定義 | +| `engines/` | 推論引擎 | +| `skills/` | Skill 載入器 | + +## ADR Reference + +- [ADR-008: Python 模組化獨立積木架構](../../docs/adr/ADR-008-python-modular-packages.md) diff --git a/packages/lewooogo-brain/pyproject.toml b/packages/lewooogo-brain/pyproject.toml new file mode 100644 index 00000000..4cc57b89 --- /dev/null +++ b/packages/lewooogo-brain/pyproject.toml @@ -0,0 +1,58 @@ +[project] +name = "lewooogo-brain" +version = "0.1.0" +description = "leWOOOgo Brain - AI Reasoning & Decision Engine for AWOOOI" +readme = "README.md" +requires-python = ">=3.11" +license = {text = "MIT"} +authors = [ + {name = "AWOOOI Team", email = "team@awoooi.dev"}, +] +keywords = ["awoooi", "lewooogo", "aiops", "decision-engine"] +classifiers = [ + "Development Status :: 3 - Alpha", + "Intended Audience :: Developers", + "License :: OSI Approved :: MIT License", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", +] + +dependencies = [ + "pydantic>=2.5.0", + "structlog>=24.1.0", + "opentelemetry-api>=1.20.0", +] + +[project.optional-dependencies] +dev = [ + "pytest>=7.4.0", + "pytest-asyncio>=0.23.0", + "pytest-cov>=4.1.0", + "ruff>=0.1.0", + "mypy>=1.8.0", +] + +[build-system] +requires = ["hatchling"] +build-backend = "hatchling.build" + +[tool.hatch.build.targets.wheel] +packages = ["src/lewooogo_brain"] + +[tool.ruff] +target-version = "py311" +line-length = 88 +select = ["E", "W", "F", "I", "B", "C4", "UP"] +ignore = ["E501"] + +[tool.ruff.isort] +known-first-party = ["lewooogo_brain"] + +[tool.mypy] +python_version = "3.11" +strict = true +ignore_missing_imports = true + +[tool.pytest.ini_options] +asyncio_mode = "auto" +testpaths = ["tests"] diff --git a/packages/lewooogo-brain/src/lewooogo_brain/__init__.py b/packages/lewooogo-brain/src/lewooogo_brain/__init__.py new file mode 100644 index 00000000..d8fc8e06 --- /dev/null +++ b/packages/lewooogo-brain/src/lewooogo_brain/__init__.py @@ -0,0 +1,25 @@ +""" +leWOOOgo Brain - AI Reasoning & Decision Engine +================================================ + +AWOOOI 2.0 的 AI 推論核心積木 + +模組結構: +- interfaces/ ABC 定義 (IProposalEngine, IIncidentProcessor) +- engines/ 推論引擎 (IncidentEngine, ProposalEngine) +- skills/ Skill 動態載入器 + +使用方式: + from lewooogo_brain.engines import ProposalEngine + from lewooogo_brain.interfaces import IProposalEngine + +統帥鐵律: +- 所有引擎必須實作對應的 Interface (ABC) +- 禁止直接引用外部模組,必須透過依賴注入 +- 所有決策必須可稽核 (AIDecisionChain) +""" + +__version__ = "0.1.0" +__all__ = [ + "__version__", +] diff --git a/packages/lewooogo-brain/src/lewooogo_brain/engines/__init__.py b/packages/lewooogo-brain/src/lewooogo_brain/engines/__init__.py new file mode 100644 index 00000000..3c0847cd --- /dev/null +++ b/packages/lewooogo-brain/src/lewooogo_brain/engines/__init__.py @@ -0,0 +1,19 @@ +""" +leWOOOgo Brain Engines - 推論引擎 +================================== + +具體實作 IProposalEngine 和 IIncidentProcessor + +引擎列表: +- ProposalEngine: 決策提案引擎 +- IncidentEngine: 事件處理引擎 +""" + +# TODO: Phase 6.4e 搬遷後啟用 +# from lewooogo_brain.engines.proposal_engine import ProposalEngine +# from lewooogo_brain.engines.incident_engine import IncidentEngine + +__all__: list[str] = [ + # "ProposalEngine", + # "IncidentEngine", +] diff --git a/packages/lewooogo-brain/src/lewooogo_brain/interfaces/__init__.py b/packages/lewooogo-brain/src/lewooogo_brain/interfaces/__init__.py new file mode 100644 index 00000000..2dd6e52e --- /dev/null +++ b/packages/lewooogo-brain/src/lewooogo_brain/interfaces/__init__.py @@ -0,0 +1,18 @@ +""" +leWOOOgo Brain Interfaces - ABC 定義 +===================================== + +所有引擎必須實作這些抽象介面 + +介面列表: +- IProposalEngine: 決策提案引擎介面 +- IIncidentProcessor: 事件處理器介面 +""" + +from lewooogo_brain.interfaces.proposal_engine import IProposalEngine +from lewooogo_brain.interfaces.incident_processor import IIncidentProcessor + +__all__ = [ + "IProposalEngine", + "IIncidentProcessor", +] diff --git a/packages/lewooogo-brain/src/lewooogo_brain/interfaces/incident_processor.py b/packages/lewooogo-brain/src/lewooogo_brain/interfaces/incident_processor.py new file mode 100644 index 00000000..c9221836 --- /dev/null +++ b/packages/lewooogo-brain/src/lewooogo_brain/interfaces/incident_processor.py @@ -0,0 +1,126 @@ +""" +IIncidentProcessor - 事件處理器介面 +=================================== + +定義 Incident 處理的標準介面 + +統帥鐵律: +- 禁止告警風暴 (相關告警必須聚合) +- 禁止 O(N) 掃描 (所有查詢必須 O(1)) +- 禁止 Race Condition (所有寫入必須原子操作) +""" + +from abc import ABC, abstractmethod +from datetime import datetime +from enum import Enum +from typing import Any +from pydantic import BaseModel, Field +from uuid import UUID + + +class IncidentStatus(str, Enum): + """事件狀態""" + INVESTIGATING = "investigating" + MITIGATING = "mitigating" + RESOLVED = "resolved" + CLOSED = "closed" + + +class Severity(str, Enum): + """嚴重等級""" + P0 = "P0" # Critical + P1 = "P1" # High + P2 = "P2" # Warning + P3 = "P3" # Info + + +class Signal(BaseModel): + """告警信號""" + alert_name: str + severity: Severity + source: str + fired_at: datetime + labels: dict[str, str] = {} + annotations: dict[str, str] = {} + fingerprint: str | None = None + + +class Incident(BaseModel): + """事件資料結構""" + incident_id: str + status: IncidentStatus = IncidentStatus.INVESTIGATING + severity: Severity = Severity.P2 + signals: list[Signal] = [] + affected_services: list[str] = [] + proposal_ids: list[UUID] = [] + created_at: datetime = Field(default_factory=datetime.utcnow) + updated_at: datetime = Field(default_factory=datetime.utcnow) + resolved_at: datetime | None = None + closed_at: datetime | None = None + + +class IIncidentProcessor(ABC): + """ + 事件處理器介面 + + 職責: + 1. 聚合相關告警到同一 Incident + 2. 分析爆炸半徑 (透過 GraphRAG) + 3. 雙層持久化 (Working + Episodic Memory) + + 使用方式: + class MyIncidentProcessor(IIncidentProcessor): + async def process_signal(self, signal_data: dict) -> Incident | None: + # 實作邏輯 + pass + """ + + @abstractmethod + async def process_signal( + self, + signal_data: dict[str, Any], + ) -> Incident | None: + """ + 處理告警信號 + + Args: + signal_data: 告警資料 (來自 Redis Streams) + + Returns: + Incident | None: 處理後的事件 (可能是新建或聚合) + """ + ... + + @abstractmethod + async def get_incident( + self, + incident_id: str, + ) -> Incident | None: + """ + 取得事件 + + Args: + incident_id: 事件 ID + + Returns: + Incident | None + """ + ... + + @abstractmethod + async def update_status( + self, + incident_id: str, + status: IncidentStatus, + ) -> bool: + """ + 更新事件狀態 + + Args: + incident_id: 事件 ID + status: 新狀態 + + Returns: + bool: 是否成功 + """ + ... diff --git a/packages/lewooogo-brain/src/lewooogo_brain/interfaces/proposal_engine.py b/packages/lewooogo-brain/src/lewooogo_brain/interfaces/proposal_engine.py new file mode 100644 index 00000000..647046ac --- /dev/null +++ b/packages/lewooogo-brain/src/lewooogo_brain/interfaces/proposal_engine.py @@ -0,0 +1,100 @@ +""" +IProposalEngine - 決策提案引擎介面 +================================== + +定義 Proposal 生成的標準介面 + +統帥鐵律: +- 所有 Proposal 必須包含 Guardrails +- 禁止跳過 TrustEngine 評估 +- 所有決策必須可稽核 +""" + +from abc import ABC, abstractmethod +from typing import Any, Protocol +from pydantic import BaseModel + + +class Proposal(BaseModel): + """決策提案資料結構""" + proposal_id: str + incident_id: str + action: str + description: str + risk_level: str + guardrails: dict[str, Any] + metadata: dict[str, Any] = {} + + +class Guardrails(BaseModel): + """安全護欄配置""" + require_dry_run: bool = True + allowed_namespace: list[str] = ["awoooi-prod"] + forbidden_commands: list[str] = ["rm -rf", "drop table", "kubectl delete ns"] + max_retries: int = 1 + timeout_sec: int = 60 + audit_log: str = "mandatory" + rollback_window_sec: int = 300 + + +class IMemoryProvider(Protocol): + """記憶體提供者協定 (來自 lewooogo_data)""" + async def load_incident(self, incident_id: str) -> Any | None: ... + async def save_incident(self, incident: Any) -> None: ... + + +class IProposalEngine(ABC): + """ + 決策提案引擎介面 + + 職責: + 1. 分析 Incident 生成修復建議 + 2. 評估風險等級 + 3. 建立 ApprovalRequest + 4. 更新 Incident 狀態 + + 使用方式: + class MyProposalEngine(IProposalEngine): + async def generate(self, incident_id: str) -> tuple[Proposal | None, str]: + # 實作邏輯 + pass + """ + + @abstractmethod + async def generate( + self, + incident_id: str, + ) -> tuple[Proposal | None, str]: + """ + 生成決策提案 + + Args: + incident_id: 事件 ID + + Returns: + (Proposal, message) 或 (None, error_message) + """ + ... + + @abstractmethod + async def generate_with_skill( + self, + incident_id: str, + skill_id: str, + ) -> tuple[Proposal | None, str]: + """ + 使用指定 Skill 生成決策提案 + + Args: + incident_id: 事件 ID + skill_id: Skill 識別碼 (e.g., "04-awoooi-devops-commander") + + Returns: + (Proposal, message) 或 (None, error_message) + """ + ... + + @abstractmethod + def get_default_guardrails(self) -> Guardrails: + """取得預設安全護欄配置""" + ... diff --git a/packages/lewooogo-brain/src/lewooogo_brain/skills/__init__.py b/packages/lewooogo-brain/src/lewooogo_brain/skills/__init__.py new file mode 100644 index 00000000..d81f7d21 --- /dev/null +++ b/packages/lewooogo-brain/src/lewooogo_brain/skills/__init__.py @@ -0,0 +1,19 @@ +""" +leWOOOgo Brain Skills - Skill 動態載入 +======================================= + +動態載入 .agents/skills/*.md 並注入到推論引擎 + +模組列表: +- SkillLoader: Skill 載入器 +- SkillRegistry: Skill → Incident 類型對映 +""" + +# TODO: Phase 6.4f 實作後啟用 +# from lewooogo_brain.skills.loader import SkillLoader +# from lewooogo_brain.skills.registry import SkillRegistry + +__all__: list[str] = [ + # "SkillLoader", + # "SkillRegistry", +] diff --git a/packages/lewooogo-data/README.md b/packages/lewooogo-data/README.md new file mode 100644 index 00000000..c579367d --- /dev/null +++ b/packages/lewooogo-data/README.md @@ -0,0 +1,48 @@ +# leWOOOgo Data + +> Memory Provider Abstraction Layer for AWOOOI 2.0 + +## Overview + +leWOOOgo Data 是 AWOOOI 智能運維平台的資料抽象層積木,負責: + +- **Working Memory**: Redis 快取 (7 天 TTL) +- **Episodic Memory**: PostgreSQL/SQLite 永久保存 +- **Dual Memory**: 雙層同步寫入 + +## Installation + +```bash +# 在 apps/api 中使用 +pip install -e ../../packages/lewooogo-data + +# 如需 PostgreSQL 支援 +pip install -e "../../packages/lewooogo-data[pg]" +``` + +## Usage + +```python +from lewooogo_data.interfaces import IMemoryProvider +from lewooogo_data.providers import RedisMemory, PgMemory, DualMemory + +# 使用雙層記憶體 +memory = DualMemory( + working=RedisMemory(redis_url="redis://localhost:6379"), + episodic=PgMemory(database_url="postgresql://...") +) + +# 載入 Incident +incident = await memory.load(f"incident:{incident_id}") +``` + +## Modules + +| Module | Description | +|--------|-------------| +| `interfaces/` | ABC 定義 | +| `providers/` | 具體實作 | + +## ADR Reference + +- [ADR-008: Python 模組化獨立積木架構](../../docs/adr/ADR-008-python-modular-packages.md) diff --git a/packages/lewooogo-data/pyproject.toml b/packages/lewooogo-data/pyproject.toml new file mode 100644 index 00000000..0bf242eb --- /dev/null +++ b/packages/lewooogo-data/pyproject.toml @@ -0,0 +1,63 @@ +[project] +name = "lewooogo-data" +version = "0.1.0" +description = "leWOOOgo Data - Memory Provider Abstraction Layer for AWOOOI" +readme = "README.md" +requires-python = ">=3.11" +license = {text = "MIT"} +authors = [ + {name = "AWOOOI Team", email = "team@awoooi.dev"}, +] +keywords = ["awoooi", "lewooogo", "data", "memory-provider", "redis", "postgresql"] +classifiers = [ + "Development Status :: 3 - Alpha", + "Intended Audience :: Developers", + "License :: OSI Approved :: MIT License", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", +] + +dependencies = [ + "pydantic>=2.5.0", + "structlog>=24.1.0", + "redis>=5.0.0", + "sqlalchemy[asyncio]>=2.0.0", + "aiosqlite>=0.19.0", +] + +[project.optional-dependencies] +dev = [ + "pytest>=7.4.0", + "pytest-asyncio>=0.23.0", + "pytest-cov>=4.1.0", + "ruff>=0.1.0", + "mypy>=1.8.0", +] +pg = [ + "asyncpg>=0.29.0", +] + +[build-system] +requires = ["hatchling"] +build-backend = "hatchling.build" + +[tool.hatch.build.targets.wheel] +packages = ["src/lewooogo_data"] + +[tool.ruff] +target-version = "py311" +line-length = 88 +select = ["E", "W", "F", "I", "B", "C4", "UP"] +ignore = ["E501"] + +[tool.ruff.isort] +known-first-party = ["lewooogo_data"] + +[tool.mypy] +python_version = "3.11" +strict = true +ignore_missing_imports = true + +[tool.pytest.ini_options] +asyncio_mode = "auto" +testpaths = ["tests"] diff --git a/packages/lewooogo-data/src/lewooogo_data/__init__.py b/packages/lewooogo-data/src/lewooogo_data/__init__.py new file mode 100644 index 00000000..87aa83a7 --- /dev/null +++ b/packages/lewooogo-data/src/lewooogo_data/__init__.py @@ -0,0 +1,24 @@ +""" +leWOOOgo Data - Memory Provider Abstraction Layer +================================================== + +AWOOOI 2.0 的資料抽象層積木 + +模組結構: +- interfaces/ ABC 定義 (IMemoryProvider) +- providers/ 具體實作 (RedisMemory, PgMemory) + +使用方式: + from lewooogo_data.providers import RedisMemory + from lewooogo_data.interfaces import IMemoryProvider + +統帥鐵律: +- 所有 Provider 必須實作 IMemoryProvider +- Working Memory (Redis): TTL 7 天 +- Episodic Memory (PG/SQLite): 永久保存 +""" + +__version__ = "0.1.0" +__all__ = [ + "__version__", +] diff --git a/packages/lewooogo-data/src/lewooogo_data/interfaces/__init__.py b/packages/lewooogo-data/src/lewooogo_data/interfaces/__init__.py new file mode 100644 index 00000000..afcc1c3a --- /dev/null +++ b/packages/lewooogo-data/src/lewooogo_data/interfaces/__init__.py @@ -0,0 +1,15 @@ +""" +leWOOOgo Data Interfaces - ABC 定義 +==================================== + +所有 Provider 必須實作這些抽象介面 + +介面列表: +- IMemoryProvider: 記憶體提供者介面 +""" + +from lewooogo_data.interfaces.memory_provider import IMemoryProvider + +__all__ = [ + "IMemoryProvider", +] diff --git a/packages/lewooogo-data/src/lewooogo_data/interfaces/memory_provider.py b/packages/lewooogo-data/src/lewooogo_data/interfaces/memory_provider.py new file mode 100644 index 00000000..282cf254 --- /dev/null +++ b/packages/lewooogo-data/src/lewooogo_data/interfaces/memory_provider.py @@ -0,0 +1,169 @@ +""" +IMemoryProvider - 記憶體提供者介面 +=================================== + +定義資料存取的標準介面 + +記憶層級: +- Working Memory (Redis): 7 天 TTL,快速存取 +- Episodic Memory (PG/SQLite): 永久保存,可查詢 + +統帥鐵律: +- 禁止直接存取底層資料庫 +- 所有存取必須透過 Provider 抽象 +- 雙層寫入:Working + Episodic 同步 +""" + +from abc import ABC, abstractmethod +from typing import Any, TypeVar, Generic +from pydantic import BaseModel + + +T = TypeVar("T", bound=BaseModel) + + +class IMemoryProvider(ABC, Generic[T]): + """ + 記憶體提供者介面 + + 職責: + 1. 提供統一的資料存取抽象 + 2. 隱藏底層實作細節 (Redis/PG/SQLite) + 3. 支援 TTL 與永久保存 + + 使用方式: + class RedisMemory(IMemoryProvider[Incident]): + async def load(self, key: str) -> Incident | None: + # 實作 Redis 存取 + pass + + class PgMemory(IMemoryProvider[Incident]): + async def load(self, key: str) -> Incident | None: + # 實作 PostgreSQL 存取 + pass + """ + + @abstractmethod + async def load(self, key: str) -> T | None: + """ + 載入資料 + + Args: + key: 資料鍵值 + + Returns: + T | None: 資料物件或 None + """ + ... + + @abstractmethod + async def save(self, key: str, data: T, ttl_seconds: int | None = None) -> bool: + """ + 儲存資料 + + Args: + key: 資料鍵值 + data: 資料物件 + ttl_seconds: 過期時間 (秒),None 表示永久 + + Returns: + bool: 是否成功 + """ + ... + + @abstractmethod + async def delete(self, key: str) -> bool: + """ + 刪除資料 + + Args: + key: 資料鍵值 + + Returns: + bool: 是否成功 + """ + ... + + @abstractmethod + async def exists(self, key: str) -> bool: + """ + 檢查資料是否存在 + + Args: + key: 資料鍵值 + + Returns: + bool: 是否存在 + """ + ... + + @abstractmethod + async def update(self, key: str, updates: dict[str, Any]) -> bool: + """ + 部分更新資料 + + Args: + key: 資料鍵值 + updates: 要更新的欄位 + + Returns: + bool: 是否成功 + """ + ... + + +class IDualMemoryProvider(ABC, Generic[T]): + """ + 雙層記憶體提供者介面 + + 統帥鐵律:Working + Episodic 同步寫入 + + 使用方式: + class DualMemory(IDualMemoryProvider[Incident]): + def __init__(self): + self.working = RedisMemory() + self.episodic = PgMemory() + + async def save(self, key: str, data: Incident) -> bool: + # 同時寫入 Redis + PG + pass + """ + + @property + @abstractmethod + def working(self) -> IMemoryProvider[T]: + """Working Memory Provider (Redis)""" + ... + + @property + @abstractmethod + def episodic(self) -> IMemoryProvider[T]: + """Episodic Memory Provider (PG/SQLite)""" + ... + + @abstractmethod + async def load(self, key: str) -> T | None: + """ + 載入資料 (Working 優先,Episodic 備援) + + Args: + key: 資料鍵值 + + Returns: + T | None: 資料物件或 None + """ + ... + + @abstractmethod + async def save(self, key: str, data: T) -> bool: + """ + 雙層儲存 (Working + Episodic 同步) + + Args: + key: 資料鍵值 + data: 資料物件 + + Returns: + bool: 是否成功 + """ + ... diff --git a/packages/lewooogo-data/src/lewooogo_data/providers/__init__.py b/packages/lewooogo-data/src/lewooogo_data/providers/__init__.py new file mode 100644 index 00000000..b7ba57fc --- /dev/null +++ b/packages/lewooogo-data/src/lewooogo_data/providers/__init__.py @@ -0,0 +1,22 @@ +""" +leWOOOgo Data Providers - 具體實作 +=================================== + +IMemoryProvider 的具體實作 + +Provider 列表: +- RedisMemory: Working Memory (7 天 TTL) +- PgMemory: Episodic Memory (永久) +- DualMemory: 雙層記憶體 (Working + Episodic) +""" + +# TODO: Phase 6.4d 實作後啟用 +# from lewooogo_data.providers.redis_memory import RedisMemory +# from lewooogo_data.providers.pg_memory import PgMemory +# from lewooogo_data.providers.dual_memory import DualMemory + +__all__: list[str] = [ + # "RedisMemory", + # "PgMemory", + # "DualMemory", +]