From ab7556e355779c303292d6b687ee6a68308ce28a Mon Sep 17 00:00:00 2001 From: claude-code-best Date: Sat, 4 Apr 2026 16:28:09 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20auto=20dream=20=E5=BC=80=E5=90=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- DEV-LOG.md | 26 +++ README.md | 1 + docs/features/auto-dream.md | 182 ++++++++++++++++++ mint.json | 3 +- .../tasks/src/tasks/DreamTask/DreamTask.ts | 10 +- src/skills/bundled/dream.ts | 44 +++++ src/skills/bundled/index.ts | 8 +- 7 files changed, 264 insertions(+), 10 deletions(-) create mode 100644 docs/features/auto-dream.md create mode 100644 src/skills/bundled/dream.ts diff --git a/DEV-LOG.md b/DEV-LOG.md index 349e499a2..166824173 100644 --- a/DEV-LOG.md +++ b/DEV-LOG.md @@ -1,5 +1,30 @@ # DEV-LOG +## /dream 手动触发 + DreamTask 类型补全 (2026-04-04) + +将 `/dream` 命令从 KAIROS feature gate 中解耦,作为 bundled skill 无条件注册;补全 DreamTask 类型存根。 + +**新增文件:** + +| 文件 | 说明 | +|------|------| +| `src/skills/bundled/dream.ts` | `/dream` skill 注册,调用 `buildConsolidationPrompt()` 生成整理提示词 | + +**修改文件:** + +| 文件 | 变更 | +|------|------| +| `src/skills/bundled/index.ts` | 导入并注册 `registerDreamSkill()` | +| `src/components/tasks/src/tasks/DreamTask/DreamTask.ts` | `any` 存根 → 从 `src/tasks/DreamTask/DreamTask.js` 重新导出完整类型 | + +**新增文档:** + +| 文件 | 说明 | +|------|------| +| `docs/features/auto-dream.md` | Auto Dream 原理、触发机制、使用场景完整说明 | + +--- + ## Computer Use Windows 增强:窗口绑定截图 + UI Automation + OCR (2026-04-03) 在三平台基础实现之上,利用 Windows 原生 API 增强 Computer Use 的 Windows 专属能力。 @@ -413,3 +438,4 @@ GrowthBook 功能开关系统原为 Anthropic 内部构建设计,硬编码 SDK ``` 非空字段才写入,保存后立即生效(`onDone()` 触发 `onChangeAPIKey()` 刷新 API 客户端)。 + diff --git a/README.md b/README.md index 8908cbdd9..1f281d04c 100644 --- a/README.md +++ b/README.md @@ -45,6 +45,7 @@ - [x] Mac 上可以用这个项目 [computer-use-mcp](https://github.com/domdomegg/computer-use-mcp) - 注意这个库的命名方式与官方冲突了, 需要改为 `claude mcp add --scope user --transport stdio computer-use-mcp -- npx -y computer-use-mcp` - [x] /voice 支持 @amDosion + - [x] /dream 记忆整理命令(手动 + 自动后台触发) [文档](https://ccb.agent-aura.top/docs/features/auto-dream) - [ ] V6 大规模重构石山代码, 全面模块分包 - [ ] V6 将会为全新分支, 届时 main 分支将会封存为历史版本 diff --git a/docs/features/auto-dream.md b/docs/features/auto-dream.md new file mode 100644 index 000000000..7ef15df8b --- /dev/null +++ b/docs/features/auto-dream.md @@ -0,0 +1,182 @@ +# Auto Dream — 自动记忆整理 + +## 概述 + +Auto Dream 是 Claude Code 的后台记忆整合机制。它在会话间自动审查、组织和修剪持久化记忆文件,确保未来会话能快速获得准确的上下文。 + +记忆系统存储在文件系统中(默认 `~/.claude/projects//memory/`),由 `MEMORY.md` 索引文件和若干主题文件(如 `user_language.md`、`project_overview.md`)组成。随着会话积累,记忆会变得过时、冗余或矛盾——Dream 负责清理这些堆积。 + +## 架构 + +### 核心模块 + +| 模块 | 路径 | 职责 | +|------|------|------| +| 调度器 | `src/services/autoDream/autoDream.ts` | 时间/会话/锁三重门控,触发 forked agent | +| 配置 | `src/services/autoDream/config.ts` | 读取 `isAutoDreamEnabled()` 开关 | +| 提示词 | `src/services/autoDream/consolidationPrompt.ts` | 构建 4 阶段整理提示词 | +| 锁文件 | `src/services/autoDream/consolidationLock.ts` | PID 锁 + mtime 作为 `lastConsolidatedAt` | +| 任务 UI | `src/tasks/DreamTask/DreamTask.ts` | 后台任务注册,footer pill + Shift+Down 可见 | +| 手动入口 | `src/skills/bundled/dream.ts` | `/dream` 命令,无条件可用 | + +### 记忆路径解析 + +优先级(`src/memdir/paths.ts`): + +1. `CLAUDE_COWORK_MEMORY_PATH_OVERRIDE` 环境变量(完整路径覆盖) +2. `autoMemoryDirectory` 设置项(`settings.json`,支持 `~/` 展开) +3. 默认:`/projects//memory/` + +其中 `memoryBase` = `CLAUDE_CODE_REMOTE_MEMORY_DIR` 或 `~/.claude`。 + +## 触发机制 + +### 自动触发(Auto Dream) + +每个对话轮次结束后,`executeAutoDream()` 按顺序检查三重门控: + +``` +┌─────────────────────────────────────────────────────┐ +│ Gate 1: 全局开关 │ +│ isAutoMemoryEnabled() && isAutoDreamEnabled() │ +│ 排除: KAIROS 模式 / Remote 模式 │ +├─────────────────────────────────────────────────────┤ +│ Gate 2: 时间门控 │ +│ hoursSince(lastConsolidatedAt) >= minHours │ +│ 默认: 24 小时 │ +├─────────────────────────────────────────────────────┤ +│ Gate 3: 会话门控 │ +│ sessionsTouchedSince(lastConsolidatedAt) >= minSessions │ +│ 默认: 5 个会话(排除当前会话) │ +├─────────────────────────────────────────────────────┤ +│ Lock: PID 锁文件 │ +│ .consolidate-lock (mtime = lastConsolidatedAt) │ +│ 死进程检测 + 1 小时过期 │ +└─────────────────────────────────────────────────────┘ +``` + +全部通过后,以 **forked agent**(受限子代理)方式运行整理任务: + +- Bash 工具限制为只读命令(`ls`、`grep`、`cat` 等) +- 只能读写记忆目录内的文件 +- 用户可在 Shift+Down 后台任务面板中查看进度或终止 + +### 手动触发(`/dream` 命令) + +通过 `/dream` 命令随时触发,无门控限制: + +- 在主循环中运行(非 forked agent),拥有完整工具权限 +- 用户可实时观察操作过程 +- 执行前自动更新锁文件 mtime + +### 配置开关 + +| 开关 | 位置 | 作用 | +|------|------|------| +| `autoDreamEnabled` | `settings.json` | `true`/`false` 显式开关 | +| `autoMemoryEnabled` | `settings.json` | 总开关,关闭后所有记忆功能禁用 | +| `CLAUDE_CODE_DISABLE_AUTO_MEMORY` | 环境变量 | `1`/`true` 关闭所有记忆功能 | +| `tengu_onyx_plover` | GrowthBook | 官方远程配置,控制 `enabled`/`minHours`/`minSessions` | + +默认值(无 GrowthBook 连接时): + +```typescript +minHours: 24 // 距上次整理至少 24 小时 +minSessions: 5 // 至少有 5 个新会话 +``` + +## 整理流程(4 阶段) + +Dream agent 执行的提示词包含 4 个阶段: + +### Phase 1 — 定位(Orient) + +- `ls` 记忆目录,查看现有文件 +- 读取 `MEMORY.md` 索引 +- 浏览现有主题文件,避免重复创建 + +### Phase 2 — 采集信号(Gather) + +按优先级收集新信息: + +1. **日志文件**(`logs/YYYY/MM/YYYY-MM-DD.md`,KAIROS 模式下的追加式日志) +2. **过时记忆** — 与当前代码库状态矛盾的事实 +3. **会话记录** — 窄关键词 grep JSONL 文件(不全文读取) + +### Phase 3 — 整合(Consolidate) + +- 合并新信号到现有主题文件,而非创建近似重复 +- 将相对日期("昨天"、"上周")转为绝对日期 +- 删除被推翻的事实 + +### Phase 4 — 修剪与索引(Prune) + +- `MEMORY.md` 保持在 200 行以内、25KB 以内 +- 每条索引项一行,不超过 150 字符 +- 移除过时/错误/被取代的指针 + +## 记忆类型 + +记忆系统使用 4 种类型(`src/memdir/memoryTypes.ts`): + +| 类型 | 用途 | 示例 | +|------|------|------| +| `user` | 用户角色、偏好、知识 | 用户是高级后端工程师,偏好中文交流 | +| `feedback` | 工作方式指导 | 不要 mock 数据库测试;代码审查用 bundled PR | +| `project` | 项目上下文(非代码可推导的) | 合并冻结从 3 月 5 日开始;认证重写是合规需求 | +| `reference` | 外部系统指针 | Linear INGEST 项目跟踪 pipeline bugs | + +**不保存的内容**:代码模式、架构、文件路径(可从代码推导);Git 历史(`git log` 权威);调试方案(代码中已有)。 + +## 锁文件机制 + +`.consolidate-lock` 文件位于记忆目录内: + +- **文件内容**:持有者 PID +- **mtime**:即 `lastConsolidatedAt` 时间戳 +- **过期**:1 小时(防 PID 复用) +- **竞态处理**:双进程同时写入时,后读验证 PID,失败者退出 +- **回滚**:forked agent 失败或被用户终止时,mtime 回退到获取前的值 + +## 使用场景 + +### 场景 1:日常开发中的自动整理 + +开发者连续多天使用 Claude Code 处理不同任务。Auto Dream 在积累 5+ 个会话且距上次整理 24 小时后自动触发,整合分散在多次会话中的用户偏好和项目决策。 + +### 场景 2:手动整理记忆 + +用户发现 Claude 重复犯相同错误或遗忘之前的决策。输入 `/dream` 立即触发整理,无需等待自动触发周期。 + +### 场景 3:新会话快速上下文 + +新会话启动时,`MEMORY.md` 被加载到上下文中。经过 Dream 整理的记忆文件结构清晰、信息准确,让 Claude 快速了解用户和项目。 + +### 场景 4:KAIROS 模式下的日志蒸馏 + +KAIROS(长驻助手模式)中,agent 以追加方式写入日期日志文件。Dream 负责将这些日志蒸馏为主题文件和 `MEMORY.md` 索引。 + +## 与其他系统的关系 + +``` +┌─────────────┐ ┌──────────────┐ ┌───────────────┐ +│ 会话交互 │────▶│ 记忆写入 │────▶│ MEMORY.md │ +│ (主 agent) │ │ (即时保存) │ │ + 主题文件 │ +└─────────────┘ └──────────────┘ └───────┬───────┘ + │ + ┌───────────────────────────────────────┘ + ▼ +┌──────────────┐ ┌──────────────┐ +│ Auto Dream │────▶│ 整理/修剪 │ +│ (后台触发) │ │ 去重/纠错 │ +└──────────────┘ └──────────────┘ + ▲ +┌──────────────┐ +│ /dream 命令 │ +│ (手动触发) │ +└──────────────┘ +``` + +- **extractMemories**(`src/services/extractMemories/`):每轮次结束时从对话中提取新记忆并写入。Dream 不负责提取,只负责整理。 +- **CLAUDE.md**:项目级指令文件,加载到上下文中但不属于记忆系统。 +- **Team Memory**(`TEAMMEM` feature):团队共享记忆目录,与个人记忆使用相同的 Dream 机制。 diff --git a/mint.json b/mint.json index e72c94b62..4d015459f 100644 --- a/mint.json +++ b/mint.json @@ -152,7 +152,8 @@ "pages": [ "docs/features/token-budget", "docs/features/context-collapse", - "docs/features/workflow-scripts" + "docs/features/workflow-scripts", + "docs/features/auto-dream" ] }, "docs/features/tier3-stubs" diff --git a/src/components/tasks/src/tasks/DreamTask/DreamTask.ts b/src/components/tasks/src/tasks/DreamTask/DreamTask.ts index 446e8cf22..1bb986a93 100644 --- a/src/components/tasks/src/tasks/DreamTask/DreamTask.ts +++ b/src/components/tasks/src/tasks/DreamTask/DreamTask.ts @@ -1,3 +1,7 @@ -// Auto-generated type stub — replace with real implementation -export type DreamTask = any; -export type DreamTaskState = any; +// Type re-exports for DreamTask — bridges the component tree to the task registry. +// The real implementation lives in src/tasks/DreamTask/DreamTask.ts. +// Note: Currently unused — BackgroundTasksDialog.tsx imports directly from +// src/tasks/DreamTask/DreamTask.js. Kept for decompilation completeness. + +export type { DreamTaskState, DreamPhase, DreamTurn } from '../../../../../tasks/DreamTask/DreamTask.js' +export { isDreamTask, registerDreamTask, addDreamTurn, completeDreamTask, failDreamTask, DreamTask } from '../../../../../tasks/DreamTask/DreamTask.js' diff --git a/src/skills/bundled/dream.ts b/src/skills/bundled/dream.ts new file mode 100644 index 000000000..87cc37b4e --- /dev/null +++ b/src/skills/bundled/dream.ts @@ -0,0 +1,44 @@ +// Manual /dream skill — runs the memory consolidation prompt interactively. +// Extracted from the KAIROS feature gate so it's available unconditionally +// whenever auto-memory is enabled. + +import { getAutoMemPath, isAutoMemoryEnabled } from '../../memdir/paths.js' +import { buildConsolidationPrompt } from '../../services/autoDream/consolidationPrompt.js' +import { recordConsolidation } from '../../services/autoDream/consolidationLock.js' +import { getOriginalCwd } from '../../bootstrap/state.js' +import { getProjectDir } from '../../utils/sessionStorage.js' +import { registerBundledSkill } from '../bundledSkills.js' + +const DREAM_PROMPT_PREFIX = `# Dream: Memory Consolidation (manual run) + +You are performing a manual dream — a reflective pass over your memory files. Unlike the automatic background dream, this run has full tool permissions and the user is watching. Synthesize what you've learned recently into durable, well-organized memories so that future sessions can orient quickly. + +` + +export function registerDreamSkill(): void { + registerBundledSkill({ + name: 'dream', + description: + 'Manually trigger memory consolidation — review, organize, and prune your auto-memory files.', + whenToUse: + 'Use when the user says /dream or wants to manually consolidate memories, organize memory files, or clean up stale entries.', + userInvocable: true, + isEnabled: () => isAutoMemoryEnabled(), + async getPromptForCommand(args) { + const memoryRoot = getAutoMemPath() + const transcriptDir = getProjectDir(getOriginalCwd()) + + // Stamp the consolidation lock optimistically (same as the KAIROS path). + await recordConsolidation() + + const basePrompt = buildConsolidationPrompt(memoryRoot, transcriptDir, '') + let prompt = DREAM_PROMPT_PREFIX + basePrompt + + if (args) { + prompt += `\n\n## Additional context from user\n\n${args}` + } + + return [{ type: 'text', text: prompt }] + }, + }) +} diff --git a/src/skills/bundled/index.ts b/src/skills/bundled/index.ts index a02cf99de..3b49c53fd 100644 --- a/src/skills/bundled/index.ts +++ b/src/skills/bundled/index.ts @@ -10,6 +10,7 @@ import { registerSimplifySkill } from './simplify.js' import { registerSkillifySkill } from './skillify.js' import { registerStuckSkill } from './stuck.js' import { registerLoopSkill } from './loop.js' +import { registerDreamSkill } from './dream.js' import { registerUpdateConfigSkill } from './updateConfig.js' import { registerVerifySkill } from './verify.js' @@ -34,12 +35,7 @@ export function initBundledSkills(): void { registerBatchSkill() registerStuckSkill() registerLoopSkill() - if (feature('KAIROS') || feature('KAIROS_DREAM')) { - /* eslint-disable @typescript-eslint/no-require-imports */ - const { registerDreamSkill } = require('./dream.js') - /* eslint-enable @typescript-eslint/no-require-imports */ - registerDreamSkill() - } + registerDreamSkill() if (feature('REVIEW_ARTIFACT')) { /* eslint-disable @typescript-eslint/no-require-imports */ const { registerHunterSkill } = require('./hunter.js')