状态:规划中,待逐项确认后提升为正式文档(目标位置:项目根目录,与 CLAUDE.md 并列)
定义三个最脆弱系统的不可破坏约束。不是描述现状(ARCHITECTURE.md 干这个),而是告诉 AI 和人"这些不能碰、这样必须保持"。
只记录:我们的特定选择、模型不知道的信息、已选定需要强调的方案。通用常识不记。
待确认:以下原则需要你明确
- 信息密度偏好——紧凑高密度(VSCode 风格)还是留白舒适(Linear 风格)?代码现状偏紧凑(
text-xs多、gap-1~2),但没有明确原则 - 色彩主张——primary 紫蓝色(
oklch(0.546 0.245 262.881))是品牌色还是临时选的? - 对话 vs UI 的关系——"对话是主角,UI 退后"?还是"UI 和对话并重"?
- 组件新建判断标准——什么时候允许新建组件?(AI 特别喜欢新建)
| 维度 | 选择 | 不允许 |
|---|---|---|
| CSS 框架 | Tailwind CSS 4 | 不引入 styled-components / CSS Modules |
| 组件基础 | Radix UI 原语 + CVA variants | 不引入 Ant Design / MUI / Chakra |
| 图标 | Phosphor Icons (@phosphor-icons/react) |
不引入 Lucide / Heroicons / 其他图标库 |
| 字体 | Geist Sans + Geist Mono (next/font/google) | 不换字体 |
| 暗色模式 | next-themes + .dark class + SQLite 持久化 |
不用 media query 方案 |
| 主题切换 | CSS 变量 + data-theme-family 属性 |
|
| 状态标记 | data-slot="component-name" 属性 |
所有颜色使用 OKLCH 色彩空间,通过 CSS 变量定义,light/dark 双套值。
核心语义色:
| 变量 | Light | Dark | 用途 |
|---|---|---|---|
--background |
oklch(1 0 0) |
oklch(0.147 0.004 49.25) |
页面背景 |
--foreground |
oklch(0.147 0.004 49.25) |
oklch(0.985 0.001 106.423) |
主文字 |
--primary |
oklch(0.546 0.245 262.881) |
oklch(0.623 0.214 259.815) |
品牌主色 |
--muted |
oklch(0.97 0.001 106.424) |
— | 次要背景 |
--muted-foreground |
oklch(0.553 0.013 58.071) |
— | 次要文字 |
--destructive |
oklch(0.577 0.245 27.325) |
oklch(0.704 0.191 22.216) |
危险/错误 |
--border |
oklch(0.923 0.003 48.717) |
oklch(1 0 0 / 10%) |
边框 |
--user-bubble |
oklch(0.22 0.005 250) |
oklch(0.90 0.003 106) |
用户消息气泡 |
另有:success / warning / info / chart(5色) / sidebar / terminal 系列变量。
约束:新增颜色必须用 OKLCH,必须同时定义 light + dark 值,必须使用语义变量名。
| 档位 | 尺寸 | 用途 |
|---|---|---|
text-xs |
10-11px | 小标签、token 计数 |
text-sm |
14px | 默认正文、菜单项 |
text-base |
16px | 输入框 |
text-lg |
18px | Dialog 标题 |
text-xl |
20px | 页面标题 |
text-2xl |
24px | 大标题 |
字重:400(正文) / 500(按钮/标签) / 600(标题)。行高:正文 1.5,prose 1.7。
圆角基准:--radius: 0.75rem(12px),所有圆角从此计算。
按钮尺寸档位(已锁定):
| 档位 | 高度 | 用途 |
|---|---|---|
| xs | h-6 (24px) | 紧凑内联操作 |
| sm | h-8 (32px) | 次要按钮 |
| default | h-9 (36px) | 标准按钮 |
| lg | h-10 (40px) | 强调按钮 |
| icon | size-9 (36px) | 图标按钮 |
输入框:h-9 default, h-8 sm, h-10 lg。与按钮对齐。
图标尺寸:sm=14 / md=16 / lg=20 / xl=24,集中定义在 icon.tsx。
间距常用值:gap-1 / gap-1.5 / gap-2 / gap-3 / gap-4 / gap-6。
目录结构:
src/components/ui/— 基础层(Radix 封装),不含业务逻辑src/components/{功能}/— 业务组件(chat / settings / layout / bridge 等)
新建 vs 复用判断:
- 如果
ui/里已有类似组件 → 复用或扩展 variant,不新建 - 如果是纯 UI 模式(无业务逻辑) → 放
ui/ - 如果是特定功能的组合组件 → 放对应功能目录
- 禁止在
ui/里引入业务逻辑 - 禁止创建只用一次的 wrapper 组件
设置页:
- 左侧栏 w-52,图标+文字按钮,active=
bg-accent text-accent-foreground - 右侧内容 flex-1,overflow-auto
- 内容用 SettingsCard(
rounded-lg border border-border/50 p-4 space-y-4) - 表单行用 FieldRow(
flex items-center justify-between gap-4)
聊天页:
- 主区域
max-w-3xl px-4 py-6 gap-6 - use-stick-to-bottom 自动滚动
- UnifiedTopBar(标题编辑 + 分支指示 + 面板切换)
App Shell:
- ChatListPanel(左侧栏 180-300px)
- 主内容区
- PanelZone(右侧面板:文件树/Git/Dashboard)
- 响应式断点:
lg(1024px)
- 标准过渡:200ms ease-in-out
- Sheet 关闭:300ms / 打开:500ms
- 自定义 shimmer:2s infinite,水平渐变滑动
最后更新:2026-04-02(V3.1 上下文管理体系)
System Prompt 组成(按注入顺序,静态内容在前以优化 prompt cache):
[STATIC PREFIX — 跨 turn 稳定,可被 prompt cache 缓存]
1. WIDGET_SYSTEM_PROMPT ← 编译期常量,最稳定
2. session.system_prompt ← 会话级,创建后不变
3. Workspace Identity ← 仅助理模式
├─ claude.md(永不丢弃)
├─ soul.md / user.md
└─ (memory/daily/root docs 已改为 MCP 按需检索,不再注入 prompt)
[VOLATILE SUFFIX — 每 turn 可变]
4. Memory Hint ← 每天变(最近日记日期列表)
5. Assistant Instructions ← 状态依赖(onboarding/heartbeat/buddy personality)
6. Dashboard Context ← 仅 Desktop,widget 增删时变
7. systemPromptAppend ← 每次请求(image agent mode、skills 等)
CLI Tools Prompt 已从 assembler 移出,在 claude-client.ts 中随 MCP 一起条件注入。
| 能力 | 实现 | 位置 |
|---|---|---|
| Token 估算 | roughTokenEstimate() — 4B/tok, JSON 2B/tok |
context-estimator.ts |
| 自动压缩 | 80% 阈值触发,用 SDK 子进程调 LLM 生成摘要 | context-compressor.ts + route.ts |
| 手动压缩 | /compact 命令 |
route.ts /compact handler |
| PTL 自动重试 | 后端检测 CONTEXT_TOO_LONG → 压缩 → 重试一次 | claude-client.ts catch block |
| Fallback 质量 | token 预算截断 + 工具摘要保留 + session summary 骨架 | claude-client.ts buildFallbackContext |
| Microcompaction | 按消息年龄裁剪:近期 5K chars,30 轮前 1K chars | message-normalizer.ts microCompactMessage |
| 熔断器 | 连续 3 次压缩失败后停止 | context-compressor.ts |
| UI 指标 | ContextUsageIndicator 双指标 + warning/critical 状态 | ContextUsageIndicator.tsx |
| 1M 支持 | getContextWindow(model, { context1m: true }) → 1M |
model-context.ts |
| DB 存储 | context_summary + context_summary_updated_at 列 |
db.ts |
| 参数 | 值 | 位置 |
|---|---|---|
| Workspace 总预算 | 40,000 chars | assistant-workspace.ts |
| 单文件上限 | 8,000 chars | 同上 |
| 截断 head | 6,000 chars | 同上 |
| 截断 tail | 1,800 chars | 同上 |
| 对话历史 fallback | 200 条消息(按 token 预算截断) | route.ts |
| Fallback token 预算 | 上下文窗口 × 0.7 - system prompt | route.ts |
| 自动压缩阈值 | 上下文窗口 × 0.8 | context-compressor.ts |
| 近期消息裁剪上限 | 5,000 chars | message-normalizer.ts |
| 旧消息裁剪上限 | 1,000 chars(>30 轮前) | 同上 |
| Dashboard 摘要 | 500 chars | context-assembler.ts |
| Summary 最小长度 | 10 chars | context-compressor.ts |
| 层 | Desktop | Bridge | 未来: floating | 未来: friend_channel |
|---|---|---|---|---|
| Workspace | ✅(如果是助理项目) | ✅(如果是助理项目) | ✅ | ❌ |
| Session prompt | ✅ | ✅ | ✅ | ✅(受限) |
| Assistant instructions | ✅ | ✅ | ❌ | ❌ |
| CLI tools | ✅(关键词门控,在 claude-client.ts) | ✅(关键词门控) | ❌ | ❌ |
| Widget | ✅(关键词门控,在 claude-client.ts) | ❌ | ❌ | ❌ |
| Dashboard | ✅ | ❌ | ❌ | ❌ |
Bridge 额外约束:thinking=disabled,effort=medium,generativeUI=false。
- claude.md 永不丢弃——即使 workspace 预算溢出也强制保留
- 静态前缀顺序不可改——WIDGET_SYSTEM_PROMPT → session_prompt → identity files
- Bridge 不注入 widget/dashboard——IM 渲染不了 iframe
- MCP 关键词门控必须保留——避免 SDK tool discovery 的 ~1s 开销
- system prompt 用
preset: 'claude_code' + append模式——保留 SDK 自带的 skills/cwd 感知 - 压缩用 SDK 子进程——
generateTextViaSdk(),不用@ai-sdk/anthropicstreamText(第三方代理兼容性) - Memory 通过 MCP 按需检索——不在 system prompt 中全量注入
所有 Provider 调用必须走以下三个函数之一:
| 函数 | 用途 | 消费者 |
|---|---|---|
resolveProvider(opts?) |
通用解析 | 设置页、模型选择器、能力缓存、诊断 |
resolveForClaudeCode(provider?, opts?) |
SDK 子进程启动 | claude-client、speech、checkin、onboarding |
toAiSdkConfig(resolved, model?) |
Vercel AI SDK 调用 | text-generator、image-generator |
约束:禁止直接调用任何 Provider 的原生 SDK。新增消费者必须走这三个入口。
| 协议 | 认证方式 | 代表服务商 |
|---|---|---|
anthropic |
api_key / auth_token | Anthropic 官方、智谱、Kimi、MiniMax、火山、百川、小米 |
openai-compatible |
api_key | LiteLLM |
openrouter |
api_key | OpenRouter |
bedrock |
env_only (AWS credentials) | AWS Bedrock |
vertex |
env_only (GCP credentials) | Google Vertex |
google |
api_key | Google Generative AI |
gemini-image |
api_key | Gemini 图片生成 |
修改模型名称、接入方式、API 地址前,必须先查对应服务商的文档确认最新信息。
| 服务商 | 文档 URL | 用途 |
|---|---|---|
| Anthropic | https://docs.anthropic.com/en/docs/about-claude/models | 模型名称、能力、API 版本 |
| OpenRouter | https://openrouter.ai/models | 可用模型列表、定价 |
| 智谱 GLM | https://open.bigmodel.cn/dev/api/ | 模型 ID、API 兼容性 |
| Kimi | https://platform.moonshot.cn/docs/ | Coding Plan 接入规范 |
| MiniMax | https://platform.minimaxi.com/document/ | API 格式、模型能力 |
| 火山引擎 | https://www.volcengine.com/docs/82379 | Ark API 接入 |
| 百炼 | https://help.aliyun.com/zh/model-studio/ | 模型列表、Anthropic 兼容层 |
| AWS Bedrock | https://docs.aws.amazon.com/bedrock/ | 可用模型、区域 |
| Google Vertex | https://cloud.google.com/vertex-ai/docs | 模型版本、API |
规则:这张表需要持续维护。新增服务商时必须同时添加文档 URL。
toClaudeCodeEnv() 在注入新 Provider 环境变量前,先清理所有托管变量:
清理列表:API_TIMEOUT_MS, CLAUDE_CODE_USE_BEDROCK, CLAUDE_CODE_USE_VERTEX,
AWS_REGION, AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_SESSION_TOKEN,
CLOUD_ML_REGION, ANTHROPIC_PROJECT_ID, GEMINI_API_KEY, ...
约束:切换 Provider 时必须走 toClaudeCodeEnv(),禁止手动拼环境变量。
provider_models 表有 capabilities_json 字段,但大部分是空的。
规则:新增服务商时必须填写能力声明:
{
"reasoning": true, // 是否支持 thinking/extended thinking
"toolUse": true, // 是否支持工具调用
"vision": true, // 是否支持图片输入
"pdf": false, // 是否支持 PDF 输入
"contextWindow": 200000 // 上下文窗口大小
}不声明能力的模型 → 功能降级(关闭 thinking、不传图片),而不是让 SDK 去试错报错。
19 类错误分类(error-classifier.ts):
CLI_NOT_FOUND / NO_CREDENTIALS / AUTH_REJECTED / AUTH_FORBIDDEN / AUTH_STYLE_MISMATCH / RATE_LIMITED / NETWORK_UNREACHABLE / ENDPOINT_NOT_FOUND / MODEL_NOT_AVAILABLE / CONTEXT_TOO_LONG / UNSUPPORTED_FEATURE / CLI_VERSION_TOO_OLD / CLI_INSTALL_CONFLICT / MISSING_GIT_BASH / RESUME_FAILED / SESSION_STATE_ERROR / PROVIDER_NOT_APPLIED / PROCESS_CRASH / UNKNOWN
其中 RATE_LIMITED / NETWORK_UNREACHABLE / SESSION_STATE_ERROR 可自动重试。
5 探针诊断(provider-doctor.ts):
- CLI 探针:二进制存在性、版本、多安装检测
- Auth 探针:凭证存在性、认证风格冲突
- Provider 探针:默认 Provider、base_url、模型配置
- Features 探针:thinking/context_1m 兼容性、过期 session ID
- Network 探针:各 Provider base_url 可达性
5 种修复动作:set-default-provider / apply-provider-to-session / clear-stale-resume / switch-auth-style / reimport-env-config
- 模型信息自动探测——是否在启动时调服务商 API 拉取最新模型列表?还是保持手动维护 + 文档 URL 核查?
- capabilities_json 补全——现有服务商的能力声明大部分是空的,是否需要一次性补全?
- API key 加密存储——目前是 SQLite 明文存储,是否需要改用 Electron safeStorage / OS keychain?
质量专项 Phase 6-9 未完成:
| Phase | 内容 | 状态 |
|---|---|---|
| 6 | 4 个 ESLint error 修复 | 未做(MessageItem.tsx hooks 条件调用、ChatView impure render、GalleryDetail setState in effect) |
| 7 | Smoke 测试进 CI | 未做(需 dev server) |
| 8 | E2E 覆盖核心业务流程 | 未做(框架就位,零用例) |
| 9 | PR 截图对比 | 未做(依赖 7/8) |
这三份核心文档定义的是"什么是对的",质量保障验证的是"怎么确保不破坏"。两者互补。