diff --git a/apps/web/src/app/[locale]/layout.tsx b/apps/web/src/app/[locale]/layout.tsx index 144fff508..811f44ae8 100644 --- a/apps/web/src/app/[locale]/layout.tsx +++ b/apps/web/src/app/[locale]/layout.tsx @@ -1,5 +1,5 @@ import type { Metadata } from 'next' -import { Inter, JetBrains_Mono, VT323 } from 'next/font/google' +import { Syne, DM_Mono, JetBrains_Mono, VT323 } from 'next/font/google' import { notFound } from 'next/navigation' import { NextIntlClientProvider } from 'next-intl' import { getMessages } from 'next-intl/server' @@ -8,17 +8,26 @@ import '../globals.css' import { Providers } from '../providers' import { AutoHealingErrorBoundary } from '@/components/shared/auto-healing-error-boundary' -const inter = Inter({ +// Syne - 標題 / Display(接近 Nothing Ndot 顯示感) +const syne = Syne({ subsets: ['latin'], - variable: '--font-inter', + variable: '--font-heading', }) +// DM Mono - 內文 / 標籤 / UI 文字(乾淨等寬) +const dmMono = DM_Mono({ + weight: ['300', '400', '500'], + subsets: ['latin'], + variable: '--font-body', +}) + +// JetBrains Mono - 程式碼 / Terminal 專用 const jetbrainsMono = JetBrains_Mono({ subsets: ['latin'], variable: '--font-mono', }) -// VT323 點陣字體 - 品牌與 AI 狀態專用 +// VT323 - 點陣像素字體,品牌 AWOOOI 專用 const vt323 = VT323({ weight: '400', subsets: ['latin'], @@ -61,7 +70,7 @@ export default async function LocaleLayout({ return ( diff --git a/apps/web/src/components/ai/openclaw-panel.tsx b/apps/web/src/components/ai/openclaw-panel.tsx index fd59dc7bb..1ab4ede04 100644 --- a/apps/web/src/components/ai/openclaw-panel.tsx +++ b/apps/web/src/components/ai/openclaw-panel.tsx @@ -16,8 +16,6 @@ import { useState, useEffect } from 'react' import { useTranslations } from 'next-intl' import { cn } from '@/lib/utils' -import { Sparkles } from 'lucide-react' -import { NemoNodeAnimation } from './nemo-node-animation' // ============================================================================= // Types @@ -37,6 +35,87 @@ export interface OpenClawPanelProps { className?: string } +// ============================================================================= +// NemoClaw 3D Ceramic SVG Component (Lab-White Style) +// ============================================================================= + +function NemoClaw({ isActive, isPulsing }: { isActive: boolean; isPulsing: boolean }) { + return ( + + + + + + + + + + + + + + + + + + + + + + + {/* Base shadow */} + + {/* Main body - 3D ceramic sphere */} + + {/* Inner ring */} + + {/* Core LED */} + + {isPulsing && } + + + {/* Top arm */} + + + + + + + {/* Left arm */} + + + + + + + {/* Right arm */} + + + + + + + {/* Bottom left arm */} + + + + + + {/* Bottom right arm */} + + + + + + {/* Orbit ring when active */} + {isActive && ( + + )} + + ) +} + // ============================================================================= // Status Messages (Dot Matrix Style) // ============================================================================= @@ -146,9 +225,11 @@ export function OpenClawPanel({ )} - {/* NemoClaw 截圖風格動畫 */} + {/* NemoClaw 3D Ceramic Visualization */}
- +
+ +
{/* 右側文字 */}
diff --git a/apps/web/src/components/layout/sidebar.tsx b/apps/web/src/components/layout/sidebar.tsx index bbb78e68b..e81c4793b 100644 --- a/apps/web/src/components/layout/sidebar.tsx +++ b/apps/web/src/components/layout/sidebar.tsx @@ -168,18 +168,54 @@ export function Sidebar({ )} style={{ zIndex: Z_INDEX.SIDEBAR }} > - {/* Logo 區 - 極簡化 */} + {/* Logo 區 - NemoClaw + 品牌名稱 (VT323 點陣字體) */}
- {collapsed ? ( - - A - - ) : ( - + {/* NemoClaw Mini SVG */} +
+ + + + + + + + + + + + + + {/* Body */} + + + + + + {/* Top arm */} + + + {/* Left arm */} + + + {/* Right arm */} + + + {/* Bottom arms */} + + + {/* Orbit ring */} + + + + +
+ {/* Brand name - VT323 點陣字體 (hidden when collapsed) */} + {!collapsed && ( + {tBrand('name')} )} diff --git a/apps/web/tailwind.config.ts b/apps/web/tailwind.config.ts index b1aa7eb27..ac64a3237 100644 --- a/apps/web/tailwind.config.ts +++ b/apps/web/tailwind.config.ts @@ -59,18 +59,24 @@ const config: Config = { // ==================== Typography ==================== fontFamily: { - display: ['var(--font-mono)', 'JetBrains Mono', 'monospace'], - heading: ['Inter', 'system-ui', 'sans-serif'], - body: ['Inter', 'system-ui', 'sans-serif'], - mono: ['var(--font-mono)', 'JetBrains Mono', 'Fira Code', 'monospace'], + heading: ['var(--font-heading)', 'Syne', 'system-ui', 'sans-serif'], + body: ['var(--font-body)', 'DM Mono', 'monospace'], + display: ['var(--font-heading)', 'Syne', 'system-ui', 'sans-serif'], + mono: ['var(--font-mono)', 'JetBrains Mono', 'monospace'], // DSEG7 點陣字體 - 用於核心指標數字顯示 'dot-matrix': ['DSEG7-Classic', 'var(--font-mono)', 'monospace'], }, - // Nothing.tech 高對比墨水色 + // Nothing.tech 文字層級系統 textColor: { ink: '#111111', 'ink-secondary': '#525252', + // 5層文字層級 + primary: '#111111', // 主標題、最重要資訊 + secondary: '#333333', // 大/中標題、正文 + tertiary: '#525252', // 小標題、說明文字 + muted: '#737373', // 輔助標籤、時間戳 + disabled: '#A3A3A3', // 停用狀態 }, fontSize: { diff --git a/docs/superpowers/specs/2026-04-02-knowledge-base-design.md b/docs/superpowers/specs/2026-04-02-knowledge-base-design.md new file mode 100644 index 000000000..b675b90a5 --- /dev/null +++ b/docs/superpowers/specs/2026-04-02-knowledge-base-design.md @@ -0,0 +1,185 @@ +# Knowledge Base 設計文件 + +> **版本**: v1.0 +> **日期**: 2026-04-02 +> **作者**: ogt + Claude Code +> **狀態**: 已批准,待實作 + +--- + +## 背景與目標 + +打造 AWOOOI 知識庫系統,讓工程師與 AI 管理人員可查閱 SRE 知識,同時作為 OpenClaw 決策的 Context 來源。 + +**已確認決策**: +- 使用者:工程師 + AI 管理人員 +- 知識來源:AI 自動萃取為主,人工審核補充 +- 用途:人工查閱 + AI 自動引用(兩者兼備) +- 資料結構:兩層架構(底層知識條目 + Playbook 為特殊關聯) +- UI:左側分類導航 + 頂部搜尋 + 右側詳情 + +--- + +## 架構決策 + +| 項目 | 決策 | 理由 | +|------|------|------| +| Playbook 邊界 | **分離**,用 `related_playbook_id` 關聯 | 執行語意 ≠ 查閱知識,職責不同 | +| Migration | **K8s Job**(沿用現有方式)| 4 個 table,Alembic 是過度工程 | +| Vector Search | **Phase 1 跳過**,關鍵字 + tag | Phase 2 再評估 pgvector | + +--- + +## 資料模型 + +### KnowledgeEntry(新 PostgreSQL table) + +```sql +CREATE TABLE knowledge_entries ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + title VARCHAR(255) NOT NULL, + content TEXT NOT NULL, -- Markdown + entry_type VARCHAR(50) NOT NULL, -- 'incident_case' | 'runbook' | 'best_practice' | 'postmortem' + category VARCHAR(100) NOT NULL, -- 對應左側分類樹 + tags JSONB DEFAULT '[]', -- string[] + source VARCHAR(20) NOT NULL, -- 'ai_extracted' | 'human' + status VARCHAR(20) NOT NULL DEFAULT 'draft', -- 'draft' | 'review' | 'approved' + related_incident_id UUID REFERENCES incidents(id) ON DELETE SET NULL, + related_playbook_id VARCHAR(255), -- Playbook Redis key(非 FK) + view_count INTEGER DEFAULT 0, + created_by VARCHAR(100), + created_at TIMESTAMPTZ DEFAULT NOW(), + updated_at TIMESTAMPTZ DEFAULT NOW() +); + +CREATE INDEX idx_knowledge_entries_type ON knowledge_entries(entry_type); +CREATE INDEX idx_knowledge_entries_category ON knowledge_entries(category); +CREATE INDEX idx_knowledge_entries_status ON knowledge_entries(status); +``` + +### entry_type 分類 + +| type | 說明 | +|------|------| +| `incident_case` | AI 從 Incident 萃取的案例分析 | +| `runbook` | 手動建立的操作手冊 | +| `best_practice` | 最佳實踐文章 | +| `postmortem` | 事後分析報告 | + +### category 分類樹(左側導航) + +``` +全部 +├── 基礎設施 +│ ├── K8s / K3s +│ ├── 資料庫 +│ └── 網路 +├── 應用層 +│ ├── API 服務 +│ └── 前端 +├── AI 系統 +│ ├── OpenClaw +│ └── Playbook +└── 安全 / 合規 +``` + +--- + +## API 設計 + +Base path: `/api/v1/knowledge` + +| Method | Path | 說明 | +|--------|------|------| +| GET | `/` | 列表(支援 `category`, `type`, `status`, `q` 搜尋, `tags` 篩選)| +| GET | `/{id}` | 單筆(同時 view_count +1)| +| POST | `/` | 建立新條目 | +| PATCH | `/{id}` | 更新(含狀態流轉)| +| POST | `/{id}/approve` | 審核通過(status: draft/review → approved)| +| DELETE | `/{id}` | 軟刪除(status → archived)| +| GET | `/categories` | 取得分類樹(含各類數量)| +| GET | `/search` | 關鍵字搜尋(title + content + tags)| + +--- + +## 後端分層架構 + +遵循 leWOOOgo 積木化原則: + +``` +apps/api/src/ +├── db/models.py # 新增 KnowledgeEntry ORM class +├── models/knowledge.py # Pydantic Schema (Request/Response) +├── repositories/ +│ ├── interfaces.py # 新增 IKnowledgeRepository Protocol +│ └── knowledge_repository.py # PostgreSQL CRUD 實作 +├── services/ +│ └── knowledge_service.py # 業務邏輯(搜尋、狀態流轉、view_count) +└── api/v1/ + └── knowledge.py # Router,prefix /knowledge +``` + +--- + +## 前端設計 + +### 頁面結構 + +``` +/knowledge-base +├── 左側分類導航 (w-52, 固定) +│ ├── 全部 (N) +│ ├── 基礎設施 (N) +│ ├── 應用層 (N) +│ ├── AI 系統 (N) +│ └── 安全/合規 (N) +├── 主區域 +│ ├── 頂部搜尋欄 + 篩選 (type / source / status) +│ ├── 結果列表 +│ │ └── KnowledgeCard (title, type badge, tags, view_count, 相關 Playbook) +│ └── 空態 +└── 右側詳情 Panel (抽屜式,點擊條目開啟) + ├── 標題 + meta + ├── Markdown 渲染 + ├── 相關 Playbook 連結 + └── 審核操作(approve / 回 review) +``` + +### KnowledgeCard + +``` +┌─────────────────────────────────────────┐ +│ [type badge] 標題文字 👁 12 │ +│ category · source · 2026-04-01 │ +│ [tag] [tag] [tag] │ +│ 🔗 相關 Playbook: restart-api-server │ +└─────────────────────────────────────────┘ +``` + +### 狀態標示 + +| status | 顯示 | 顏色 | +|--------|------|------| +| `draft` | 草稿 | gray | +| `review` | 審核中 | warning(黃)| +| `approved` | 已批准 | healthy(綠)| + +--- + +## Migration K8s Job + +參考 `k8s/jobs/migrate-phase18-audit-logs.yaml`,建立: + +``` +k8s/jobs/migrate-knowledge-entries.yaml +``` + +執行 `CREATE TABLE knowledge_entries ...` + index。 + +--- + +## Phase 2(未來) + +- pgvector 語意搜尋 +- OpenClaw 在評估 Incident 時自動 RAG 查詢 Knowledge Base +- Embedding 自動化(建立 entry 時觸發)