diff --git a/.sisyphus/plans/migration_plan.md b/.sisyphus/plans/migration_plan.md deleted file mode 100644 index 832e1ea..0000000 --- a/.sisyphus/plans/migration_plan.md +++ /dev/null @@ -1,117 +0,0 @@ -# TrulyMEM → WaterFlow 迁移计划 - -> ⚠️ **修改只在 TrulyMEM 的 waterflow 分支执行** ⚠️ -> -> 所有代码修改仅应用于 TrulyMEM 仓库的 `waterflow` 分支,作为 WaterFlow 框架的适配版本。 - ---- - -## 迁移目标 - -将 TrulyMEM 的图记忆能力从 Python 迁移到 TypeScript,适配 WaterFlow 框架。 - -**代码位置**: `/home/program/TrulyMEM-TrueHumanMEM/` (waterflow 分支) - ---- - -## 迁移策略 - -将图记忆能力作为 TypeScript 模块添加到 waterflow 分支: - -| TrulyMEM (Python) | WaterFlow (TypeScript) | -|-------------------|------------------------| -| `EmbeddedGraphDB` | `GraphDatabase` | -| `GraphMemoryClient` | `MemoryService` | -| 12 个记忆工具 | `GraphMemoryTool` + Skills | - ---- - -## 实施步骤 - -### Phase 1: 项目结构 - -- [x] 1.1 创建 `ts/` 目录 - TypeScript 项目 -- [x] 1.2 创建 `package.json` - 项目配置 -- [x] 1.3 创建 `tsconfig.json` - TypeScript 配置 - -### Phase 2: 核心库 - -- [x] 2.1 创建 `ts/src/runtime/core/graph_memory/types.ts` - 类型定义 -- [x] 2.2 创建 `ts/src/runtime/core/graph_memory/graph_database.ts` - 图数据库 -- [x] 2.3 创建 `ts/src/runtime/core/graph_memory/memory_service.ts` - 记忆服务 -- [x] 2.4 创建 `ts/src/runtime/core/graph_memory/index.ts` - 模块导出 - -### Phase 3: Tool 接口 - -- [x] 3.1 创建 `ts/src/runtime/core/tools/builtin/graph_memory_tool.ts` - Tool 实现 -- [x] 3.2 注册 Tool (作为独立模块导出) - -### Phase 4: Skill 定义 - -- [x] 4.1 创建 `ts/bundled-skills/graph_memory/SKILL.md` - 主 Skill -- [x] 4.2 创建 `ts/bundled-skills/graph_memory/persona/SKILL.md` - Persona -- [x] 4.3 创建 `ts/bundled-skills/graph_memory/task/SKILL.md` - 任务管理 - -### Phase 5: 验证 - -- [x] 5.1 编译 TypeScript - 无错误 -- [ ] 5.2 运行测试 - ---- - -## 目录结构 (在 TrulyMEM waterflow 分支) - -``` -TrulyMEM-TrueHumanMEM/ -├── ts/ # TypeScript 项目 (保留) -│ ├── src/ -│ │ └── runtime/core/ -│ │ ├── graph_memory/ # 图记忆模块 -│ │ │ ├── index.ts -│ │ │ ├── types.ts -│ │ │ ├── graph_database.ts -│ │ │ └── memory_service.ts -│ │ └── tools/ -│ │ └── builtin/ -│ │ └── graph_memory_tool.ts -│ ├── bundled-skills/ -│ │ └── graph_memory/ -│ │ ├── SKILL.md -│ │ ├── persona/SKILL.md -│ │ └── task/SKILL.md -│ ├── package.json -│ └── tsconfig.json -│ -├── docs/integration/waterflow-design.md # 迁移设计文档 (保留) -│ -└── (其他文件迁移后删除) -``` - ---- - -## 迁移后清理 - -迁移完成后,waterflow 分支将删除以下文件: - -- `core/` - Python 核心代码 -- `ui/` - Python UI 代码 -- `tests/` - Python 测试 -- `tools/` - Python 工具 -- `trulymem_entry.py` - Python 入口 -- `build/` - 构建脚本 -- `pic/` - 图片资源 (除图标外) -- `requirements.txt` - Python 依赖 -- `TrulyMEM.spec` - Python 打包配置 - -只保留: -- `ts/` - TypeScript 源码 -- `docs/integration/waterflow-design.md` - 迁移文档 -- `.gitignore`, `LICENSE` - ---- - -## 工作追踪 - -工作进度记录在: `todo_progress.md` - -每次修改文件前后请查看此文件并更新进度。 diff --git a/.sisyphus/plans/todo_progress.md b/.sisyphus/plans/todo_progress.md deleted file mode 100644 index 60008bf..0000000 --- a/.sisyphus/plans/todo_progress.md +++ /dev/null @@ -1,81 +0,0 @@ -# 迁移工作进度追踪 - -> ⚠️ **修改只在 TrulyMEM 的 waterflow 分支执行** ⚠️ - ---- - -## 当前状态 - -- **开始时间**: 2026-04-15 -- **当前任务**: 迁移完成,等待测试 -- **最后更新**: 2026-04-15 -- **状态**: TypeScript 编译通过 - ---- - -## Phase 完成状态 - -### Phase 1: 项目结构 - -| 任务 | 状态 | 备注 | -|------|------|------| -| 1.1 ts/ 目录 | ✅ done | | -| 1.2 package.json | ✅ done | | -| 1.3 tsconfig.json | ✅ done | | - -### Phase 2: 核心库 - -| 任务 | 状态 | 备注 | -|------|------|------| -| 2.1 types.ts | ✅ done | | -| 2.2 graph_database.ts | ✅ done | | -| 2.3 memory_service.ts | ✅ done | | -| 2.4 index.ts | ✅ done | | - -### Phase 3: Tool 接口 - -| 任务 | 状态 | 备注 | -|------|------|------| -| 3.1 graph_memory_tool.ts | ✅ done | | -| 3.2 tool_interface.ts | ✅ done | | - -### Phase 4: Skill 定义 - -| 任务 | 状态 | 备注 | -|------|------|------| -| 4.1 SKILL.md (主) | ✅ done | | -| 4.2 persona/SKILL.md | ✅ done | | -| 4.3 task/SKILL.md | ✅ done | | - -### Phase 5: 验证 - -| 任务 | 状态 | 备注 | -|------|------|------| -| 5.1 编译 | ✅ done | TypeScript 编译通过 | -| 5.2 测试 | ⏳ pending | | - ---- - -## 创建的文件 - -| 文件 | 说明 | -|------|------| -| `ts/package.json` | 项目配置 | -| `ts/tsconfig.json` | TypeScript 配置 | -| `ts/src/runtime/core/graph_memory/types.ts` | 类型定义 | -| `ts/src/runtime/core/graph_memory/graph_database.ts` | 图数据库 | -| `ts/src/runtime/core/graph_memory/memory_service.ts` | 记忆服务 | -| `ts/src/runtime/core/graph_memory/index.ts` | 模块导出 | -| `ts/src/runtime/core/tools/tool_interface.ts` | Tool 接口 | -| `ts/src/runtime/core/tools/builtin/graph_memory_tool.ts` | GraphMemory Tool | -| `ts/bundled-skills/graph_memory/SKILL.md` | 主 Skill | -| `ts/bundled-skills/graph_memory/persona/SKILL.md` | Persona Skill | -| `ts/bundled-skills/graph_memory/task/SKILL.md` | Task Skill | - ---- - -## 说明 - -- 每次修改文件前后更新此文件 -- 记录每次修改的文件和操作 -- 方便意外终止后恢复任务 diff --git a/TRACKING.md b/TRACKING.md deleted file mode 100644 index 627ec5f..0000000 --- a/TRACKING.md +++ /dev/null @@ -1,102 +0,0 @@ -# TrulyMEM WaterFlow 重构 - 工程追踪 - -> 每次文件操作前更新此文件,确保中断可恢复。 -> 最后更新: 2026-04-16 - ---- - -## 当前状态 - -**状态**: ✅ 全部完成 -**最后更新**: 2026-04-16 - ---- - -## 任务清单 - -| # | 任务 | 状态 | 备注 | -|---|------|------|------| -| 0 | 创建工程追踪文件 | ✅ 完成 | | -| 1 | 同步 main 分支核心优化 | ✅ 完成 | BFS搜索、depth标注、工具限制器 | -| 2 | Phase 1: 清理重复定义 | ✅ 完成 | 删除 platform/, tool_interface.ts | -| 3 | Phase 2: 适配 WaterFlow 平台层 | ✅ 完成 | graph_database.ts, graph_memory_tool.ts | -| 4 | Phase 3: 完善 SKILL.md | ✅ 完成 | 10 个完整操作 | -| 5 | Phase 4: 调整构建配置 | ✅ 完成 | package.json, tsconfig.json, waterflow.d.ts | -| 6 | Phase 5: 编译验证 | ✅ 完成 | 0 错误,dist/ 输出完整 | - ---- - -## 操作日志 - -### 2026-04-16 开始 -- [x] 创建 TRACKING.md -- [x] 同步 main 分支核心优化 - - [x] BFS 广度优先搜索 → graph_database.ts(含 depth 标注) - - [x] 工具限制器调整 → 在 Tool 层面处理(WaterFlow 治理层已有) - - [x] 提示词优化 → SKILL.md(后续 Phase 3 处理) - - [x] Entity/Relation 类型添加 depth? 字段 - - [x] 改用 WaterFlow platform.fs 替代自定义 storage - - [x] 缓存 platform 实例避免重复 import -- [x] Phase 1: 删除重复文件 - - [x] 删除 ts/src/platform/ 目录(index.ts, node.ts, types.ts) - - [x] 删除 ts/src/runtime/core/tools/tool_interface.ts -- [x] Phase 2: 适配 WaterFlow 接口 - - [x] graph_memory_tool.ts → 使用 waterflow Tool 接口 - - [x] graph_database.ts → 使用 waterflow platform.fs(binary) - - [x] config.ts → 内联类型定义,移除 platform 依赖 - - [x] builtin/index.ts → 添加 registerGraphMemoryTool() -- [x] Phase 3: 完善 SKILL.md - - [x] 主 SKILL.md 补充 10 个完整操作 - - [x] persona/SKILL.md 已验证完整 - - [x] task/SKILL.md 已验证完整 -- [x] Phase 4: 构建配置 - - [x] package.json → 添加 exports, peerDependencies - - [x] tsconfig.json → 添加 typeRoots -- [x] Phase 5: 验证 - - [x] tsc --noEmit 通过(0 错误) - - [x] npm run build 成功 - - [x] dist/ 输出完整(.js, .d.ts, .map) - - [x] 新增 waterflow.d.ts 类型声明 - - [x] 安装 waterflow-ts 作为 devDependency - ---- - -## 变更摘要 - -### 删除(4 文件) -- `ts/src/platform/index.ts` -- `ts/src/platform/node.ts` -- `ts/src/platform/types.ts` -- `ts/src/runtime/core/tools/tool_interface.ts` - -### 修改(8 文件) -- `ts/src/runtime/core/graph_memory/graph_database.ts` — BFS + WaterFlow fs -- `ts/src/runtime/core/graph_memory/types.ts` — 添加 depth? 字段 -- `ts/src/runtime/core/graph_memory/config.ts` — 内联类型,移除 platform 依赖 -- `ts/src/runtime/core/graph_memory/memory_service.ts` — 无变化(已兼容) -- `ts/src/runtime/core/tools/builtin/graph_memory_tool.ts` — WaterFlow Tool 接口 -- `ts/src/runtime/core/tools/builtin/index.ts` — 添加 registerGraphMemoryTool() -- `ts/package.json` — exports, peerDependencies -- `ts/tsconfig.json` — typeRoots -- `ts/bundled-skills/graph_memory/SKILL.md` — 10 个完整操作 - -### 新增(1 文件) -- `ts/src/types/waterflow.d.ts` — WaterFlow 类型声明 - ---- - -## 中断恢复指南 - -如果任务中断,按以下步骤恢复: - -1. 读取此文件,找到最后一个 ✅ 完成的任务 -2. 找到下一个 🔄 或 ⏳ 的任务 -3. 继续执行该任务 -4. 完成后更新此文件的状态 - -**关键文件路径**: -- 重构计划: `重构.md` -- 追踪文件: `TRACKING.md` -- 核心代码: `ts/src/runtime/core/graph_memory/` -- Tool 代码: `ts/src/runtime/core/tools/builtin/` -- Skill 定义: `ts/bundled-skills/graph_memory/` diff --git a/docs/integration/waterflow-design.md b/docs/integration/waterflow-design.md deleted file mode 100644 index f74cb46..0000000 --- a/docs/integration/waterflow-design.md +++ /dev/null @@ -1,811 +0,0 @@ -# TrulyMEM → WaterFlow 迁移设计文档 - -**版本**: 1.0 -**日期**: 2026-04-15 -**目标**: 用 TypeScript 完全重写 TrulyMEM 的图记忆能力,集成到 WaterFlow - ---- - -## 一、迁移策略 - -### 1.1 核心原则 - -- **完全重写**: 不保留 Python 代码,用 TypeScript 实现 -- **架构一致**: 遵循 WaterFlow 的架构风格和设计模式 -- **原生集成**: 作为 WaterFlow 的内置模块,而非外部依赖 - -### 1.2 迁移范围 - -| TrulyMEM (Python) | WaterFlow (TypeScript) | 说明 | -|-------------------|------------------------|------| -| `EmbeddedGraphDB` | `GraphDatabase` | SQLite 图数据库重写 | -| `GraphMemoryClient` | `MemoryService` | 记忆服务 | -| 12 个记忆工具 | `GraphMemoryTool` | WaterFlow Tool 接口 | -| System Prompt | 提示词模板 | 提示词管理 | -| TUI | ❌ 不迁移 | WaterFlow 无 TUI | - ---- - -## 二、架构设计 - -### 2.1 整体架构 - -``` -┌─────────────────────────────────────────────────────────────────────┐ -│ WaterFlow Core │ -│ ┌─────────────┐ ┌──────────────┐ ┌────────────────────────┐ │ -│ │ Agent / │───>│ Query │───>│ ToolExecutor │ │ -│ │ Workflow │ │ Engine │ │ │ │ -│ └─────────────┘ └──────────────┘ └───────────┬────────────┘ │ -│ │ │ -│ ┌──────────────────────────────┘ │ -│ ▼ │ -│ ┌─────────────────────────────────────────────────────────────────┐ │ -│ │ GraphMemory Module (NEW) │ │ -│ │ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │ │ -│ │ │ GraphMemoryTool │ │ GraphDatabase │ │ MemoryService │ │ │ -│ │ │ (Tool Interface)│ │ (SQLite Graph) │ │ (LLM Integration)│ │ │ -│ │ └────────┬────────┘ └────────┬────────┘ └────────┬────────┘ │ │ -│ │ │ │ │ │ │ -│ │ └────────────────────┼────────────────────┘ │ │ -│ │ ▼ │ │ -│ │ ┌─────────────────────┐ │ │ -│ │ │ GraphMemoryStore │ │ │ -│ │ │ (In-Memory Cache) │ │ │ -│ │ └─────────────────────┘ │ │ -│ └─────────────────────────────────────────────────────────────────┘ │ -└─────────────────────────────────────────────────────────────────────┘ -``` - -### 2.2 模块职责 - -| 模块 | 职责 | 位置 | -|------|------|------| -| `GraphMemoryTool` | WaterFlow Tool 接口,暴露记忆能力 | `runtime/core/tools/builtin/graph_memory/` | -| `GraphDatabase` | SQLite 图数据库实现 | `runtime/core/graph_memory/database/` | -| `MemoryService` | 封装业务逻辑 | `runtime/core/graph_memory/service/` | -| `GraphMemoryStore` | 内存缓存,加速查询 | `runtime/core/graph_memory/store/` | -| `SystemPrompt` | 提示词模板管理 | `runtime/core/graph_memory/prompts/` | - ---- - -## 三、目录结构 - -### 3.1 新增目录 - -``` -WaterFlow/ts/src/ -├── runtime/core/ -│ ├── graph_memory/ # 新增: 图记忆模块 -│ │ ├── index.ts # 模块导出 -│ │ ├── types.ts # 类型定义 -│ │ ├── database/ # 图数据库实现 -│ │ │ ├── index.ts -│ │ │ ├── graph_database.ts # 主类 -│ │ │ ├── entity_store.ts # 实体存储 -│ │ │ └── relation_store.ts # 关系存储 -│ │ ├── service/ # 服务层 -│ │ │ ├── index.ts -│ │ │ ├── memory_service.ts # 记忆服务 -│ │ │ ├── recall_service.ts # 检索服务 -│ │ │ └── task_service.ts # 任务服务 -│ │ ├── store/ # 缓存层 -│ │ │ ├── index.ts -│ │ │ └── memory_cache.ts -│ │ └── prompts/ # 提示词 -│ │ └── system_prompt.ts -│ │ -│ └── tools/builtin/ -│ └── graph_memory/ # GraphMemory Tool -│ ├── index.ts -│ ├── graph_memory_tool.ts # Tool 实现 -│ ├── types.ts # Tool 参数类型 -│ └── tool_registry.ts # 自动注册 -``` - -### 3.2 修改文件 - -| 文件 | 修改内容 | -|------|----------| -| `runtime/core/tools/builtin/index.ts` | 注册 GraphMemoryTool | -| `shared/types/index.ts` | 导出图记忆类型 | - ---- - -## 四、核心类型定义 - -### 4.1 图数据库类型 - -```typescript -// src/runtime/core/graph_memory/types.ts - -export interface Entity { - id: string; - name: string; - type: string; - mentionCount: number; - createdAt: Date; - updatedAt: Date; -} - -export interface Relation { - id: string; - sourceId: string; - targetId: string; - relationType: string; - confidence: number; - status: RelationStatus; - sessionId: string; - turnId: number; - createdAt: Date; - updatedAt: Date; - dateBucket: string; -} - -export type RelationStatus = 'active' | 'deleted' | 'archived' | 'superseded'; - -export interface Triplet { - subject: string; - relation: string; - object: string; - confidence?: number; -} - -export interface RecallParams { - queryIntent: string; - seedEntities?: string[]; - depth?: number; - timeRange?: { days: number }; - sessionFilter?: string; -} - -export interface CommitParams { - triplets: Triplet[]; - entityTypes?: Record; - temporalTag?: string; - sessionId?: string; - turnId?: number; -} - -export interface PurgeParams { - criteria: { - subject?: string; - target?: string; - relation?: string; - sessionId?: string; - }; - mode?: 'soft' | 'hard' | 'supersede'; - newRelation?: { relation: string; target: string }; -} - -export type TaskState = '进行中' | '已完成' | '已暂停' | '已取消'; - -export interface MemoryStats { - entityCount: number; - relationCount: number; - sessionId?: string; -} -``` - -### 4.2 Tool 参数类型 - -```typescript -// src/runtime/core/tools/builtin/graph_memory/types.ts - -export type GraphMemoryAction = - | 'recall' | 'commit' | 'purge' | 'introspect' | 'archive' | 'cleanup' - | 'persona_update' | 'persona_clear' - | 'task_create' | 'task_set_state' | 'task_delete' | 'task_link_info'; - -export interface GraphMemoryToolInput { - action: GraphMemoryAction; - params: Record; -} -``` - ---- - -## 五、核心实现 - -### 5.1 GraphDatabase 实现 - -```typescript -// src/runtime/core/graph_memory/database/graph_database.ts - -export class GraphDatabase { - private db: Database; - - constructor(dbPath: string) { - this.db = new Database(dbPath); - this.initialize(); - } - - private initialize(): void { - this.db.exec(` - CREATE TABLE IF NOT EXISTS entities ( - id TEXT PRIMARY KEY, - name TEXT UNIQUE NOT NULL, - type TEXT, - mention_count INTEGER DEFAULT 1, - created_at TEXT DEFAULT CURRENT_TIMESTAMP, - updated_at TEXT DEFAULT CURRENT_TIMESTAMP - ) - `); - - this.db.exec(` - CREATE TABLE IF NOT EXISTS relations ( - id TEXT PRIMARY KEY, - source_id TEXT NOT NULL, - target_id TEXT NOT NULL, - relation_type TEXT NOT NULL, - confidence REAL DEFAULT 1.0, - status TEXT DEFAULT 'active', - session_id TEXT, - turn_id INTEGER, - created_at TEXT DEFAULT CURRENT_TIMESTAMP, - updated_at TEXT DEFAULT CURRENT_TIMESTAMP, - date_bucket TEXT - ) - `); - - // 索引 - this.db.exec(` - CREATE INDEX IF NOT EXISTS idx_entity_name ON entities(name); - CREATE INDEX IF NOT EXISTS idx_relation_status ON relations(status); - `); - } - - async recall(params: RecallParams): Promise { - const { queryIntent, seedEntities, sessionFilter } = params; - const keywords = queryIntent.split(/[,\s]+/).filter(k => k.length > 0); - const entities: Entity[] = []; - const relations: Relation[] = []; - const entityIds = new Set(); - - // 搜索实体 - for (const keyword of keywords) { - const rows = this.db.exec( - `SELECT * FROM entities WHERE LOWER(name) LIKE ? LIMIT 50`, - [`%${keyword.toLowerCase()}%`] - ); - for (const row of rows) { - if (!entityIds.has(row.id)) { - entityIds.add(row.id); - entities.push(this.rowToEntity(row)); - } - } - } - - // 搜索关系 - if (entityIds.size > 0) { - const placeholders = Array.from(entityIds).map(() => '?').join(','); - let query = ` - SELECT r.*, e1.name as source_name, e2.name as target_name - FROM relations r - JOIN entities e1 ON r.source_id = e1.id - JOIN entities e2 ON r.target_id = e2.id - WHERE (r.source_id IN (${placeholders}) OR r.target_id IN (${placeholders})) - AND r.status = 'active' - `; - const queryParams = [...entityIds, ...entityIds]; - - if (sessionFilter) { - query += ` AND r.session_id = ?`; - queryParams.push(sessionFilter); - } - - const rows = this.db.exec(query, queryParams); - for (const row of rows) { - relations.push(this.rowToRelation(row)); - } - } - - return { entities, relations, message: `找到 ${entities.length} 个实体, ${relations.length} 条关系` }; - } - - async commit(params: CommitParams): Promise<{ createdEntities: number; createdRelations: number }> { - const { triplets, sessionId, turnId } = params; - let createdEntities = 0; - let createdRelations = 0; - - for (const triplet of triplets) { - const sourceId = this.upsertEntity(triplet.subject); - const targetId = this.upsertEntity(triplet.object); - - this.db.exec(` - INSERT INTO relations (id, source_id, target_id, relation_type, confidence, session_id, turn_id, status) - VALUES (?, ?, ?, ?, ?, ?, ?, 'active') - `, [this.generateId(), sourceId, targetId, triplet.relation, triplet.confidence || 1.0, sessionId, turnId || 0]); - - createdEntities += 2; - createdRelations++; - } - - return { createdEntities, createdRelations }; - } - - async purge(params: PurgeParams): Promise<{ deleted: number; mode: string }> { - const { criteria, mode = 'soft' } = params; - const conditions: string[] = ['status = ?']; - const values: unknown[] = ['active']; - - if (criteria.subject) { - conditions.push(`source_id IN (SELECT id FROM entities WHERE name = ?)`); - values.push(criteria.subject); - } - - const whereClause = conditions.join(' AND '); - const result = this.db.exec(`UPDATE relations SET status = 'deleted' WHERE ${whereClause}`, values); - - return { deleted: result.length, mode }; - } - - async introspect(): Promise { - const entityCount = this.db.exec(`SELECT COUNT(*) as c FROM entities`)[0]?.c || 0; - const relationCount = this.db.exec(`SELECT COUNT(*) as c FROM relations WHERE status = 'active'`)[0]?.c || 0; - return { entityCount, relationCount }; - } - - private upsertEntity(name: string): string { - const existing = this.db.exec(`SELECT id FROM entities WHERE name = ?`, [name]); - if (existing.length > 0) { - this.db.exec(`UPDATE entities SET mention_count = mention_count + 1 WHERE name = ?`, [name]); - return existing[0].id; - } - const id = this.generateId(); - this.db.exec(`INSERT INTO entities (id, name, type) VALUES (?, ?, ?)`, [id, name, 'unknown']); - return id; - } - - private generateId(): string { - return `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`; - } - - private rowToEntity(row: any): Entity { - return { - id: row.id, name: row.name, type: row.type || 'unknown', - mentionCount: row.mention_count || 1, - createdAt: new Date(row.created_at), updatedAt: new Date(row.updated_at) - }; - } - - private rowToRelation(row: any): Relation { - return { - id: row.id, sourceId: row.source_id, targetId: row.target_id, - relationType: row.relation_type, confidence: row.confidence || 1.0, - status: row.status || 'active', sessionId: row.session_id || '', - turnId: row.turn_id || 0, - createdAt: new Date(row.created_at), updatedAt: new Date(row.updated_at), - dateBucket: row.date_bucket || '' - }; - } - - close(): void { this.db.close(); } -} -``` - -### 5.2 GraphMemoryTool 实现 - -```typescript -// src/runtime/core/tools/builtin/graph_memory/graph_memory_tool.ts - -import type { Tool, ToolExecutionContext, ToolInputSchema } from '../tool_interface'; -import { GraphDatabase } from '../../../graph_memory/database/graph_database'; -import { MemoryService } from '../../../graph_memory/service/memory_service'; - -export class GraphMemoryTool implements Tool { - readonly id = 'builtin:graph_memory'; - readonly name = 'GraphMemory'; - readonly description = `图记忆工具 - 让 AI 拥有真正的长期记忆能力 - -操作: -- recall: 检索记忆 -- commit: 写入记忆 -- purge: 删除记忆 -- introspect: 查看状态 -- persona_update/clear: 人设管理 -- task_create/set_state/delete: 任务管理`; - - readonly category = 'analysis'; - readonly permissionLevel: 'safe' = 'safe'; - readonly inputSchema: ToolInputSchema = { - type: 'object', - properties: { - action: { - type: 'string', - enum: ['recall', 'commit', 'purge', 'introspect', 'persona_update', 'persona_clear', - 'task_create', 'task_set_state', 'task_delete', 'task_link_info'], - description: '记忆操作类型' - }, - params: { type: 'object', description: '操作参数' } - }, - required: ['action', 'params'] - }; - - private db: GraphDatabase; - private service: MemoryService; - - constructor(config: { dbPath: string; sessionId?: string }) { - this.db = new GraphDatabase(config.dbPath); - this.service = new MemoryService(this.db, config.sessionId); - } - - async handler(params: Record, context: ToolExecutionContext): Promise { - const action = params.action as string; - const actionParams = params.params as Record; - - try { - const result = await this.executeAction(action, actionParams); - return JSON.stringify({ success: true, data: result }, null, 2); - } catch (error) { - return JSON.stringify({ - success: false, - error: { type: 'execution_error', message: error instanceof Error ? error.message : String(error) } - }, null, 2); - } - } - - private async executeAction(action: string, params: Record): Promise { - switch (action) { - case 'recall': return this.service.recall(params as any); - case 'commit': return this.service.commit(params as any); - case 'purge': return this.service.purge(params as any); - case 'introspect': return this.service.introspect(); - case 'persona_update': return this.service.updatePersona(params); - case 'persona_clear': return this.service.clearPersona(params); - case 'task_create': return this.service.createTask(params); - case 'task_set_state': return this.service.setTaskState(params); - case 'task_delete': return this.service.deleteTask(params); - default: throw new Error(`Unknown action: ${action}`); - } - } - - close(): void { this.db.close(); } -} -``` - -### 5.3 MemoryService 实现 - -```typescript -// src/runtime/core/graph_memory/service/memory_service.ts - -import { GraphDatabase } from '../database/graph_database'; -import type { RecallParams, CommitParams, PurgeParams } from '../types'; - -export class MemoryService { - private db: GraphDatabase; - private sessionId: string; - - constructor(db: GraphDatabase, sessionId?: string) { - this.db = db; - this.sessionId = sessionId || `session-${Date.now()}`; - } - - async recall(params: RecallParams) { - return this.db.recall({ ...params, sessionFilter: params.sessionFilter || this.sessionId }); - } - - async commit(params: CommitParams) { - return this.db.commit({ ...params, sessionId: params.sessionId || this.sessionId }); - } - - async purge(params: PurgeParams) { - return this.db.purge(params); - } - - async introspect() { - const stats = await this.db.introspect(); - return { ...stats, sessionId: this.sessionId }; - } - - async updatePersona(params: Record) { - const attributes = params.attributes as Array<{ attribute: string; value: string }>; - const mode = params.mode as string || 'merge'; - - if (mode === 'replace') { - await this.db.purge({ criteria: { subject: 'AI' }, mode: 'soft' }); - } - - const triplets = attributes.map(attr => ({ - subject: 'AI', relation: attr.attribute, object: attr.value, confidence: 1.0 - })); - - await this.commit({ triplets }); - return { status: 'success', updatedAttributes: attributes.length }; - } - - async clearPersona(params: Record) { - if (params.confirm === false) return { status: 'cancelled', deletedCount: 0 }; - const result = await this.purge({ criteria: { subject: 'AI' }, mode: 'soft' }); - return { status: 'success', deletedCount: result.deleted }; - } - - async createTask(params: Record) { - const taskId = params.task_id as string; - const description = params.description as string; - const infoNodes = (params.info_nodes as string[]) || []; - - await this.commit({ - triplets: [ - { subject: taskId, relation: 'is_type', object: 'TaskNode' }, - { subject: taskId, relation: 'has_description', object: description }, - { subject: taskId, relation: 'HAS_STATE', object: 'State_进行中' } - ] - }); - - if (infoNodes.length > 0) { - await this.commit({ - triplets: infoNodes.map(node => ({ subject: taskId, relation: 'CONTAINS_INFO', object: node })) - }); - } - - return { status: 'success', taskId }; - } - - async setTaskState(params: Record) { - const taskId = params.task_id as string; - const state = params.state as string; - - await this.purge({ criteria: { subject: taskId, relation: 'HAS_STATE' }, mode: 'soft' }); - await this.commit({ triplets: [{ subject: taskId, relation: 'HAS_STATE', object: `State_${state}` }] }); - - return { status: 'success', newState: state }; - } - - async deleteTask(params: Record) { - const taskId = params.task_id as string; - await this.purge({ criteria: { subject: taskId }, mode: 'soft' }); - return { status: 'success', taskId }; - } -} -``` - ---- - -## 六、测试方案 - -### 6.1 测试文件结构 - -``` -WaterFlow/ts/tests/ -├── runtime/core/graph_memory/ -│ ├── database/ -│ │ └── graph_database.test.ts # 15+ 测试 -│ └── service/ -│ └── memory_service.test.ts # 12+ 测试 -└── runtime/core/tools/builtin/ - └── graph_memory/ - └── graph_memory_tool.test.ts # 15+ 测试 -``` - -### 6.2 数据库测试 - -```typescript -// tests/runtime/core/graph_memory/database/graph_database.test.ts - -import { describe, it, expect, beforeEach, afterEach } from 'vitest'; -import { GraphDatabase } from '../../../../../src/runtime/core/graph_memory/database/graph_database'; -import * as fs from 'fs'; - -describe('GraphDatabase', () => { - const testDbPath = '/tmp/test_graph_memory.db'; - let db: GraphDatabase; - - beforeEach(() => { - if (fs.existsSync(testDbPath)) fs.unlinkSync(testDbPath); - db = new GraphDatabase(testDbPath); - }); - - afterEach(() => { - db.close(); - if (fs.existsSync(testDbPath)) fs.unlinkSync(testDbPath); - }); - - describe('commit', () => { - it('should create entities and relations', async () => { - const result = await db.commit({ - triplets: [ - { subject: '用户', relation: '喜欢', object: 'Python' }, - { subject: '用户', relation: '正在学习', object: 'TypeScript' } - ] - }); - expect(result.createdEntities).toBe(3); - expect(result.createdRelations).toBe(2); - }); - }); - - describe('recall', () => { - beforeEach(async () => { - await db.commit({ - triplets: [ - { subject: '用户', relation: '喜欢', object: 'Python' }, - { subject: 'Python', relation: '是', object: '编程语言' } - ] - }); - }); - - it('should recall by keyword', async () => { - const result = await db.recall({ queryIntent: 'Python' }); - expect(result.entities.some(e => e.name === 'Python')).toBe(true); - }); - - it('should recall relations', async () => { - const result = await db.recall({ queryIntent: '用户,Python' }); - expect(result.relations.length).toBeGreaterThan(0); - }); - }); - - describe('purge', () => { - beforeEach(async () => { - await db.commit({ - triplets: [{ subject: '旧信息', relation: 'is', object: '垃圾' }] - }); - }); - - it('should soft delete relations', async () => { - const result = await db.purge({ criteria: { subject: '旧信息' }, mode: 'soft' }); - expect(result.deleted).toBeGreaterThan(0); - expect(result.mode).toBe('soft'); - }); - }); - - describe('introspect', () => { - it('should return statistics', async () => { - await db.commit({ triplets: [{ subject: 'A', relation: 'relates', object: 'B' }] }); - const stats = await db.introspect(); - expect(stats.entityCount).toBe(2); - expect(stats.relationCount).toBe(1); - }); - }); -}); -``` - -### 6.3 服务层测试 - -```typescript -// tests/runtime/core/graph_memory/service/memory_service.test.ts - -import { describe, it, expect, beforeEach } from 'vitest'; -import { MemoryService } from '../../../../../src/runtime/core/graph_memory/service/memory_service'; -import { GraphDatabase } from '../../../../../src/runtime/core/graph_memory/database/graph_database'; - -describe('MemoryService', () => { - const testDbPath = '/tmp/test_memory_service.db'; - let db: GraphDatabase; - let service: MemoryService; - - beforeEach(() => { - db = new GraphDatabase(testDbPath); - service = new MemoryService(db, 'test-session'); - }); - - describe('persona management', () => { - it('should update persona', async () => { - const result = await service.updatePersona({ - attributes: [{ attribute: '角色', value: '猫娘' }], - mode: 'replace' - }); - expect(result.status).toBe('success'); - expect(result.updatedAttributes).toBe(1); - }); - - it('should clear persona', async () => { - await service.updatePersona({ attributes: [{ attribute: '角色', value: '猫娘' }] }); - const result = await service.clearPersona({ confirm: true }); - expect(result.status).toBe('success'); - }); - }); - - describe('task management', () => { - it('should create task', async () => { - const result = await service.createTask({ - task_id: 'Task_Test', - description: '测试任务', - info_nodes: ['info1'] - }); - expect(result.taskId).toBe('Task_Test'); - }); - - it('should set task state', async () => { - await service.createTask({ task_id: 'Task_State', description: '测试' }); - const result = await service.setTaskState({ task_id: 'Task_State', state: '已完成' }); - expect(result.newState).toBe('已完成'); - }); - }); -}); -``` - -### 6.4 Tool 接口测试 - -```typescript -// tests/runtime/core/tools/builtin/graph_memory/graph_memory_tool.test.ts - -import { describe, it, expect, beforeEach } from 'vitest'; -import { GraphMemoryTool } from '../../../../../src/runtime/core/tools/builtin/graph_memory/graph_memory_tool'; -import * as fs from 'fs'; - -describe('GraphMemoryTool', () => { - const testDbPath = '/tmp/test_graph_memory_tool.db'; - let tool: GraphMemoryTool; - - beforeEach(() => { - if (fs.existsSync(testDbPath)) fs.unlinkSync(testDbPath); - tool = new GraphMemoryTool({ dbPath: testDbPath, sessionId: 'test' }); - }); - - it('should have correct metadata', () => { - expect(tool.id).toBe('builtin:graph_memory'); - expect(tool.name).toBe('GraphMemory'); - expect(tool.category).toBe('analysis'); - }); - - describe('recall', () => { - it('should execute recall', async () => { - await tool.handler({ action: 'commit', params: { triplets: [{ subject: 'Test', relation: 't', object: 'D' }] } }, mockContext()); - const result = await tool.handler({ action: 'recall', params: { query_intent: 'Test' } }, mockContext()); - const parsed = JSON.parse(result); - expect(parsed.success).toBe(true); - }); - }); - - describe('commit', () => { - it('should execute commit', async () => { - const result = await tool.handler({ - action: 'commit', - params: { triplets: [{ subject: '用户', relation: '喜欢', object: 'AI' }] } - }, mockContext()); - const parsed = JSON.parse(result); - expect(parsed.success).toBe(true); - }); - }); - - describe('error handling', () => { - it('should return error for unknown action', async () => { - const result = await tool.handler({ action: 'unknown', params: {} }, mockContext()); - const parsed = JSON.parse(result); - expect(parsed.success).toBe(false); - }); - }); -}); - -function mockContext() { - return { - toolCallId: 'test', workingDirectory: '/tmp', abortController: { signal: {} }, - config: { timeout: 5000 }, logger: { info: () => {}, warn: () => {}, error: () => {}, debug: () => {} } - }; -} -``` - -### 6.5 验证检查清单 - -``` -[ ] GraphDatabase.commit - 创建实体和关系 -[ ] GraphDatabase.recall - 按关键词检索 -[ ] GraphDatabase.purge - 软删除 -[ ] GraphDatabase.introspect - 返回统计 - -[ ] MemoryService.updatePersona - 人设更新 -[ ] MemoryService.clearPersona - 人设清除 -[ ] MemoryService.createTask - 创建任务 -[ ] MemoryService.setTaskState - 设置状态 -[ ] MemoryService.deleteTask - 删除任务 - -[ ] GraphMemoryTool recall action -[ ] GraphMemoryTool commit action -[ ] GraphMemoryTool persona_update action -[ ] GraphMemoryTool task_create action -[ ] GraphMemoryTool error handling -``` - ---- - -## 七、实现计划 - -| Phase | 任务 | 周期 | 测试 | -|-------|------|------|------| -| 1 | GraphDatabase 实现 | 2-3 天 | 15+ | -| 2 | MemoryService 实现 | 1-2 天 | 12+ | -| 3 | GraphMemoryTool 实现 | 1-2 天 | 15+ | -| 4 | 集成测试 | 1 天 | 8+ | - -**总计**: 5-8 天,50+ 测试用例 diff --git a/ts/bundled-skills/graph_memory/SKILL.md b/ts/bundled-skills/graph_memory/SKILL.md index e9fc45e..3a9ba2f 100644 --- a/ts/bundled-skills/graph_memory/SKILL.md +++ b/ts/bundled-skills/graph_memory/SKILL.md @@ -3,7 +3,7 @@ name: graph_memory description: 图记忆工具 - 让 AI 拥有真正的长期记忆能力 when_to_use: 需要 AI 记住、回忆、管理信息或任务时 context: inline -allowed_tools: +allowed-tools: - builtin:graph_memory arguments: - name: action @@ -15,7 +15,7 @@ arguments: type: object required: true description: 操作参数 -user_invocable: true +user-invocable: true --- # GraphMemory 图记忆操作 diff --git a/ts/bundled-skills/graph_memory/persona/SKILL.md b/ts/bundled-skills/graph_memory/persona/SKILL.md index b3f87c5..adcc240 100644 --- a/ts/bundled-skills/graph_memory/persona/SKILL.md +++ b/ts/bundled-skills/graph_memory/persona/SKILL.md @@ -1,9 +1,9 @@ --- -name: graph_memory_persona +name: persona description: 管理 AI 人设 - 更新或清除 AI 角色特征 when_to_use: 需要修改 AI 的角色设定或清除人设时 context: inline -allowed_tools: +allowed-tools: - builtin:graph_memory arguments: - name: action @@ -22,7 +22,7 @@ arguments: - name: confirm type: boolean description: 确认清除 (用于 clear) -user_invocable: true +user-invocable: true --- # GraphMemory Persona 人设管理 diff --git a/ts/bundled-skills/graph_memory/task/SKILL.md b/ts/bundled-skills/graph_memory/task/SKILL.md index 2b1b7b3..54e6c9d 100644 --- a/ts/bundled-skills/graph_memory/task/SKILL.md +++ b/ts/bundled-skills/graph_memory/task/SKILL.md @@ -1,9 +1,9 @@ --- -name: graph_memory_task +name: task description: 管理连续性任务 - 创建、更新、删除任务节点 when_to_use: 需要创建或管理长期任务时 context: inline -allowed_tools: +allowed-tools: - builtin:graph_memory arguments: - name: action @@ -28,7 +28,7 @@ arguments: - name: info_node type: string description: 信息节点 (用于 link_info) -user_invocable: true +user-invocable: true --- # GraphMemory Task 任务管理 diff --git a/ts/src/runtime/core/graph_memory/graph_database.ts b/ts/src/runtime/core/graph_memory/graph_database.ts index 9277d21..bed9089 100644 --- a/ts/src/runtime/core/graph_memory/graph_database.ts +++ b/ts/src/runtime/core/graph_memory/graph_database.ts @@ -1,4 +1,5 @@ import initSqlJs, { type Database as SqlJsDatabase } from 'sql.js'; +import type { Platform } from 'waterflow/platform/types'; import type { Entity, Relation, RecallParams, CommitParams, PurgeParams, RecallResult, CommitResult, PurgeResult, MemoryStats } from './types'; import { getConfig } from './config'; @@ -6,7 +7,7 @@ export class GraphDatabase { private db: SqlJsDatabase | null = null; private sessionId: string; private initPromise: Promise | null = null; - private _platform: any = null; + private _platform: Platform | null = null; constructor(sessionId?: string) { this.sessionId = sessionId || `session-${Date.now()}`; @@ -20,10 +21,15 @@ export class GraphDatabase { try { const dbPath = this._platform.path.join(this._platform.getCwd(), getConfig().dbPath); - const exists = await this._platform.fs.exists(dbPath); - if (exists) { - const data = await this._platform.fs.readFile(dbPath, { encoding: 'binary' }); - this.db = new SQL.Database(data as Uint8Array); + const fs = this._platform.fs; + if (fs) { + const exists = await fs.exists(dbPath); + if (exists) { + const data = await fs.readFile(dbPath, { encoding: 'binary' }); + this.db = new SQL.Database(new Uint8Array(data as ArrayBuffer)); + } else { + this.db = new SQL.Database(); + } } else { this.db = new SQL.Database(); } @@ -39,16 +45,18 @@ export class GraphDatabase { try { const platform = this._platform; + const fs = platform.fs; + if (!fs) return; const dbPath = platform.path.join(platform.getCwd(), getConfig().dbPath); const dir = platform.path.dirname(dbPath); - const dirExists = await platform.fs.exists(dir); + const dirExists = await fs.exists(dir); if (!dirExists) { - await platform.fs.mkdir(dir, true); + await fs.mkdir(dir, true); } const data = this.db.export(); - await platform.fs.writeFile(dbPath, new Uint8Array(data), { encoding: 'binary' }); + await fs.writeFile(dbPath, data.buffer as ArrayBuffer, { encoding: 'binary' }); } catch (error) { - this._platform.getLogger().error(`[GraphDatabase] Save failed: ${error}`); + console.error(`[GraphDatabase] Save failed: ${error}`); } } diff --git a/ts/src/runtime/core/tools/builtin/graph_memory_tool.ts b/ts/src/runtime/core/tools/builtin/graph_memory_tool.ts index 25cf81e..c2f8626 100644 --- a/ts/src/runtime/core/tools/builtin/graph_memory_tool.ts +++ b/ts/src/runtime/core/tools/builtin/graph_memory_tool.ts @@ -102,6 +102,10 @@ export class GraphMemoryTool implements Tool { } async handler(params: ToolInput, context: ToolExecutionContext): Promise { + if (context.abortController?.signal?.aborted) { + throw new Error('Operation aborted'); + } + const action = params.action as string; const actionParams = params.params as Record; const logger = context?.logger; diff --git a/ts/src/runtime/core/tools/builtin/index.ts b/ts/src/runtime/core/tools/builtin/index.ts index 3befb9c..a15ef76 100644 --- a/ts/src/runtime/core/tools/builtin/index.ts +++ b/ts/src/runtime/core/tools/builtin/index.ts @@ -11,8 +11,8 @@ export function registerGraphMemoryTool( registry.register(createGraphMemoryTool(sessionId)); } -export function installTrulyMEM(platform: Platform, sessionId?: string) { - const { initializeToolRegistry } = require('waterflow/runtime/core/tools/builtin'); +export async function installTrulyMEM(platform: Platform, sessionId?: string) { + const { initializeToolRegistry } = await import('waterflow/runtime/core/tools/builtin'); const registry = initializeToolRegistry(platform); registerGraphMemoryTool(registry, sessionId); return registry; diff --git a/ts/src/types/waterflow.d.ts b/ts/src/types/waterflow.d.ts index 02af797..867d8d9 100644 --- a/ts/src/types/waterflow.d.ts +++ b/ts/src/types/waterflow.d.ts @@ -1,12 +1,25 @@ declare module 'waterflow/platform' { - import type { Platform } from 'waterflow/platform/types'; + import type { Platform, CreatePlatformOptions, PlatformCapabilities } from 'waterflow/platform/types'; export function getPlatform(): Platform; - export function hasCapability(capability: string): boolean; - export function initPlatform(options?: any): Platform; + export function hasCapability(capability: keyof PlatformCapabilities): boolean; + export function initPlatform(options?: CreatePlatformOptions): Platform; export function resetPlatform(): void; } declare module 'waterflow/platform/types' { + export type BufferSource = ArrayBuffer | ArrayBufferView; + export type RuntimeType = 'node' | 'web' | 'harmony' | 'unknown'; + export type OSType = 'windows' | 'macos' | 'linux' | 'android' | 'ios' | 'harmony' | 'unknown'; + + export interface PlatformCapabilities { + fileSystem: boolean; + processExecution: boolean; + network: boolean; + storage: boolean; + webSocket: boolean; + workers: boolean; + } + export interface PlatformAbortSignal { readonly aborted: boolean; readonly reason?: unknown; @@ -19,26 +32,107 @@ declare module 'waterflow/platform/types' { abort(reason?: unknown): void; } - export interface PathOperations { - join(...paths: string[]): string; - dirname(p: string): string; - basename(p: string, ext?: string): string; - extname(p: string): string; - normalize(p: string): string; - isAbsolute(p: string): boolean; - resolve(...paths: string[]): string; - relative(from: string, to: string): string; + export interface PlatformTextEncoder { + encode(input?: string): Uint8Array; + encodeInto(src: string, dest: Uint8Array): { read: number; written: number }; } - export interface FileReadOptions { - encoding?: 'utf-8' | 'binary'; - start?: number; - end?: number; + export interface PlatformTextDecoder { + decode(input?: BufferSource): string; } - export interface FileWriteOptions { - encoding?: 'utf-8' | 'binary'; - append?: boolean; + export interface PlatformURL { + href: string; + origin: string; + protocol: string; + host: string; + hostname: string; + port: string; + pathname: string; + search: string; + hash: string; + toString(): string; + toJSON(): string; + } + + export interface PlatformGlobals { + TextEncoder: new (encoding?: string) => PlatformTextEncoder; + TextDecoder: new (encoding?: string) => PlatformTextDecoder; + URL: new (url: string) => { href: string; pathname: string; toString(): string }; + randomUUID(): string; + now(): number; + btoa(data: string): string; + atob(data: string): string; + } + + export interface GlobOptions { + cwd?: string; + ignore?: string[]; + absolute?: boolean; + dot?: boolean; + onlyFiles?: boolean; + onlyDirectories?: boolean; + deep?: number; + ignoreCase?: boolean; + } + + export interface GlobResult { + path: string; + isFile: boolean; + isDirectory: boolean; + } + + export interface GlobTool { + glob(pattern: string, options?: GlobOptions): Promise; + globWithInfo(pattern: string, options?: GlobOptions): Promise; + isMatch(path: string, pattern: string): boolean; + search(pattern: string, basePath?: string): Promise; + } + + export interface GrepOptions { + cwd?: string; + ignoreCase?: boolean; + multiline?: boolean; + glob?: string | string[]; + include?: string[]; + exclude?: string[]; + context?: number; + beforeContext?: number; + afterContext?: number; + headLimit?: number; + } + + export interface GrepMatch { + path: string; + line: number; + column?: number; + content: string; + } + + export interface GrepSearchOptions { + pattern: string; + path?: string; + glob?: string | string[]; + ignoreCase?: boolean; + context?: number; + outputMode?: 'content' | 'files_with_matches' | 'count'; + maxResults?: number; + } + + export interface GrepSearchResult { + lines: string[]; + } + + export interface GrepTool { + grep(pattern: string | RegExp, options?: GrepOptions): Promise; + grepFiles(pattern: string | RegExp, options?: GrepOptions): Promise; + grepCount(pattern: string | RegExp, options?: GrepOptions): Promise; + search(options: GrepSearchOptions): Promise; + } + + export interface PlatformTools { + glob: GlobTool | null; + grep: GrepTool | null; } export interface FileInfo { @@ -47,22 +141,35 @@ declare module 'waterflow/platform/types' { isFile: boolean; isDirectory: boolean; size: number; - modifiedTime: number; - createdTime: number; + modifiedTime?: number; + createdTime?: number; + } + + export interface FileReadOptions { + encoding?: 'utf-8' | 'binary' | 'base64'; + start?: number; + end?: number; + } + + export interface FileWriteOptions { + encoding?: 'utf-8' | 'binary' | 'base64'; + append?: boolean; + createDir?: boolean; } export interface FileSystemOperations { - readFile(filePath: string, options?: FileReadOptions): Promise; - writeFile(filePath: string, data: string | ArrayBuffer, options?: FileWriteOptions): Promise; - appendFile(filePath: string, data: string, options?: FileWriteOptions): Promise; - deleteFile(filePath: string): Promise; - exists(filePath: string): Promise; - stat(filePath: string): Promise; - readdir(dirPath: string): Promise; - mkdir(dirPath: string, recursive?: boolean): Promise; - rmdir(dirPath: string, recursive?: boolean): Promise; + readFile(path: string, options?: FileReadOptions): Promise; + writeFile(path: string, data: string | ArrayBuffer, options?: FileWriteOptions): Promise; + appendFile(path: string, data: string, options?: FileWriteOptions): Promise; + deleteFile(path: string): Promise; + exists(path: string): Promise; + stat(path: string): Promise; + readdir(path: string): Promise; + mkdir(path: string, recursive?: boolean): Promise; + rmdir(path: string, recursive?: boolean): Promise; copy(src: string, dest: string): Promise; move(src: string, dest: string): Promise; + watch?(path: string, callback: (event: string, filename: string) => void): () => void; } export interface ProcessResult { @@ -76,12 +183,17 @@ declare module 'waterflow/platform/types' { cwd?: string; env?: Record; timeout?: number; + input?: string; + shell?: boolean; maxBuffer?: number; } export interface ProcessOperations { exec(command: string, options?: ProcessOptions): Promise; execFile(file: string, args: string[], options?: ProcessOptions): Promise; + spawn?(command: string, args: string[], options?: ProcessOptions): AsyncIterable; + which?(command: string): Promise; + kill?(pid: number, signal?: string): Promise; } export interface StorageOperations { @@ -92,85 +204,56 @@ declare module 'waterflow/platform/types' { keys(): Promise; } - export interface PlatformGlobals { - TextEncoder: typeof TextEncoder; - TextDecoder: typeof TextDecoder; - URL: typeof URL; - randomUUID(): string; - now(): number; - btoa(data: string): string; - atob(data: string): string; + export interface PathOperations { + join(...paths: string[]): string; + dirname(path: string): string; + basename(path: string, ext?: string): string; + extname(path: string): string; + normalize(path: string): string; + isAbsolute(path: string): boolean; + resolve(...paths: string[]): string; + relative(from: string, to: string): string; } - export interface Logger { - info(msg: string, ...args: unknown[]): void; - warn(msg: string, ...args: unknown[]): void; - error(msg: string, ...args: unknown[]): void; - debug(msg: string, ...args: unknown[]): void; + export interface PlatformResponse { + status: number; + statusText: string; + headers: Record; + ok: boolean; + text(): Promise; + json(): Promise; + arrayBuffer(): Promise; } - export interface Platform { - readonly path: PathOperations; - readonly fs: FileSystemOperations; - readonly process: ProcessOperations; - readonly storage: StorageOperations; - readonly globals: PlatformGlobals; - getInfo(): { runtime: string; os: string; version: string; arch: string; hostname: string }; - createAbortController(): PlatformAbortController; - getEnv(key: string): string | undefined; - getAllEnv(): Record; - setEnv(key: string, value: string): void; - getCwd(): string; - setCwd(p: string): void; - exit(code: number): void; - getLogger(): Logger; - } -} - -declare module 'waterflow/runtime/core/tools/tool_interface' { - import type { PlatformAbortController, Logger } from 'waterflow/platform/types'; - - export type ToolCategory = 'file' | 'code' | 'search' | 'execute' | 'network' | 'analysis' | 'generation' | 'communication' | 'mcp' | 'custom'; - export type PermissionLevel = 'safe' | 'moderate' | 'dangerous' | 'restricted'; - export type ToolInput = Record; - export type ToolOutput = string | Record | void; - - export interface SchemaProperty { - type: string; - description: string; - enum?: string[]; - minimum?: number; - maximum?: number; - minLength?: number; - maxLength?: number; - pattern?: string; - default?: unknown; - examples?: unknown[]; - items?: SchemaProperty; - properties?: Record; + export interface PlatformFetchRequestInit { + method?: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | 'HEAD' | 'OPTIONS'; + headers?: Record; + body?: string | ArrayBuffer | Record; + timeout?: number; } - export interface ToolInputSchema { - type: 'object'; - properties: Record; - required?: string[]; - additionalProperties?: boolean; + export interface PlatformWebSocket { + readonly readyState: number; + readonly url: string; + send(data: string | ArrayBuffer): void; + close(code?: number, reason?: string): void; + addEventListener(type: string, listener: (event: any) => void): void; + removeEventListener(type: string, listener: (event: any) => void): void; } - export interface ToolOutputSchema { - type: 'object'; - properties: Record; - format?: 'json' | 'text' | 'markdown' | 'binary'; - maxSize?: number; - maxLines?: number; + export interface NetworkOperations { + fetch(url: string, options?: PlatformFetchRequestInit): Promise; + fetchStream?(url: string, options?: PlatformFetchRequestInit): AsyncGenerator; + connectWebSocket?(url: string, protocols?: string[]): Promise; } - export interface ToolExecutionContext { - toolCallId: string; - workingDirectory: string; - abortController: PlatformAbortController; - config: { timeout?: number }; - logger: Logger; + export interface PlatformInfo { + runtime: RuntimeType; + os: OSType; + version?: string; + arch?: string; + hostname?: string; + capabilities: PlatformCapabilities; } export interface Tool { @@ -181,13 +264,370 @@ declare module 'waterflow/runtime/core/tools/tool_interface' { readonly inputSchema: ToolInputSchema; readonly outputSchema?: ToolOutputSchema; readonly handler: (params: ToolInput, context: ToolExecutionContext) => Promise; - readonly permissionLevel: PermissionLevel; - readonly alwaysLoad?: boolean; - readonly shouldDefer?: boolean; + readonly permissionLevel: ToolPermissionLevel; + readonly requiredPermissions?: string[]; + readonly features?: ToolFeatures; + readonly metadata?: ToolMetadata; readonly isMcp?: boolean; - readonly prompt?: (options: any) => Promise; - readonly features?: string[]; - readonly metadata?: Record; + readonly shouldDefer?: boolean; + readonly alwaysLoad?: boolean; readonly searchHint?: string; + prompt?(options: ToolPromptOptions): Promise; + } + + export interface Platform { + getInfo(): PlatformInfo; + createAbortController(): PlatformAbortController; + readonly path: PathOperations; + readonly fs: FileSystemOperations | null; + readonly process: ProcessOperations | null; + readonly storage: StorageOperations; + readonly network: NetworkOperations; + readonly globals: PlatformGlobals; + readonly tools: PlatformTools; + readonly builtinTools: Tool[]; + getEnv(key: string): string | undefined; + getAllEnv?(): Record; + setEnv?(key: string, value: string): void; + getCwd(): string; + setCwd?(path: string): void; + exit?(code: number): void; + } + + export interface CreatePlatformOptions { + storagePath?: string; + storageType?: 'localStorage' | 'indexedDB'; + dbName?: string; + context?: any; + storageName?: string; + } + + export type ToolInput = Record; + export type ToolOutput = string | Record | void; + + export type ToolPermissionLevel = 'safe' | 'moderate' | 'dangerous' | 'restricted'; + export type ToolCategory = 'file' | 'code' | 'search' | 'execute' | 'network' | 'analysis' | 'generation' | 'communication' | 'custom'; + + export interface ToolSchemaProperty { + type: 'string' | 'number' | 'integer' | 'boolean' | 'array' | 'object'; + description: string; + enum?: string[]; + default?: unknown; + examples?: unknown[]; + items?: ToolSchemaProperty; + properties?: Record; + } + + export interface ToolInputSchema { + type: 'object'; + properties: Record; + required?: string[]; + additionalProperties?: boolean; + } + + export interface ToolExecutionContext { + toolCallId: string; + workingDirectory: string; + additionalWorkingDirectories?: string[]; + abortController: PlatformAbortController; + config: { + timeout?: number; + maxOutputSize?: number; + allowedDirectories?: string[]; + }; + logger: { + info(message: string, ...args: unknown[]): void; + warn(message: string, ...args: unknown[]): void; + error(message: string, ...args: unknown[]): void; + debug(message: string, ...args: unknown[]): void; + }; + } + + export interface BuiltinTool { + readonly id: string; + readonly name: string; + readonly description: string; + readonly category: ToolCategory; + readonly inputSchema: ToolInputSchema; + readonly permissionLevel: ToolPermissionLevel; + handler(params: ToolInput, context: ToolExecutionContext): Promise; + } +} + +declare module 'waterflow/runtime/core/tools/tool_interface' { + import type { PlatformAbortController } from 'waterflow/platform/types'; + import type { AgentId } from 'waterflow/shared/types/agent'; + import type { WorkflowRunner } from 'waterflow/runtime/core/workflow/types'; + import type { WorkflowRegistryImpl } from 'waterflow/runtime/core/workflow/workflow_registry'; + import type { AgentRegistryImpl } from 'waterflow/runtime/core/workflow/agent_registry'; + import type { AgentExecutor } from 'waterflow/runtime/core/agent/agent_executor'; + import type { MCPClient } from 'waterflow/runtime/core/tools/mcp/mcp_client'; + + export type ToolCategory = + | 'file' + | 'code' + | 'search' + | 'execute' + | 'network' + | 'analysis' + | 'generation' + | 'communication' + | 'mcp' + | 'custom'; + + export type PermissionLevel = + | 'safe' + | 'moderate' + | 'dangerous' + | 'restricted'; + + export type SchemaType = + | 'string' + | 'number' + | 'integer' + | 'boolean' + | 'array' + | 'object'; + + export interface SchemaProperty { + type: SchemaType; + description: string; + enum?: string[]; + minimum?: number; + maximum?: number; + minLength?: number; + maxLength?: number; + pattern?: string; + default?: any; + examples?: any[]; + suggestedSource?: 'context' | 'literal' | 'file'; + items?: SchemaProperty; + properties?: Record; + additionalProperties?: boolean | SchemaProperty; + } + + export interface ToolInputSchema { + type: 'object'; + properties: Record; + required?: string[]; + additionalProperties?: boolean; + semanticHints?: Record; + } + + export interface ToolOutputSchema { + type: 'object'; + properties: Record; + format?: 'json' | 'text' | 'markdown' | 'binary'; + maxSize?: number; + maxLines?: number; + } + + export type ToolInput = Record; + export type ToolOutput = string | Record | void; + + export interface Logger { + info(message: string, ...args: any[]): void; + warn(message: string, ...args: any[]): void; + error(message: string, ...args: any[]): void; + debug(message: string, ...args: any[]): void; + } + + export interface ToolConfig { + timeout?: number; + maxOutputSize?: number; + allowedDirectories?: string[]; + } + + export interface ToolExecutionContext { + toolCallId: string; + agentId?: AgentId; + workingDirectory: string; + additionalWorkingDirectories?: string[] | undefined; + abortController: PlatformAbortController; + config: ToolConfig; + logger: Logger; + workflowRunner?: WorkflowRunner | undefined; + workflowRegistry?: WorkflowRegistryImpl | undefined; + agentExecutor?: AgentExecutor | undefined; + agentRegistry?: AgentRegistryImpl | undefined; + allowedAgentTypes?: string[] | undefined; + mcpClients?: Map | undefined; + tools?: Tool[] | undefined; + } + + export type ToolHandler = ( + params: ToolInput, + context: ToolExecutionContext + ) => Promise; + + export interface ToolFeatures { + isAsync?: boolean; + isStreamable?: boolean; + isCacheable?: boolean; + requiresConfirmation?: boolean; + supportsProgress?: boolean; + supportsCancellation?: boolean; + producesFiles?: boolean; + producesImages?: boolean; + producesStructuredOutput?: boolean; + requiresMcp?: boolean; + requiresNetwork?: boolean; + } + + export interface ToolExample { + description: string; + input: ToolInput; + output: ToolOutput; + explanation?: string; + } + + export interface ToolMetadata { + source: 'builtin' | 'mcp' | 'plugin' | 'external'; + version?: string; + author?: string; + documentationUrl?: string; + examples?: ToolExample[]; + estimatedDuration?: number; + estimatedTokens?: number; + compatibleModels?: string[]; + incompatibleModels?: string[]; + } + + export interface ToolPromptOptions { + tools: Tool[]; + agentRegistry?: AgentRegistryImpl | undefined; + workflowRegistry?: WorkflowRegistryImpl | undefined; + allowedAgentTypes?: string[] | undefined; + } + + export interface Tool { + readonly id: string; + readonly name: string; + readonly description: string; + readonly category: ToolCategory; + readonly inputSchema: ToolInputSchema; + readonly outputSchema?: ToolOutputSchema; + readonly handler: ToolHandler; + readonly permissionLevel: PermissionLevel; + readonly requiredPermissions?: string[]; + readonly features?: ToolFeatures; + readonly metadata?: ToolMetadata; + readonly isMcp?: boolean; + readonly shouldDefer?: boolean; + readonly alwaysLoad?: boolean; + readonly searchHint?: string; + prompt?(options: ToolPromptOptions): Promise; + } + + export interface ToolExecutionError { + type: ToolErrorType; + message: string; + code?: string; + details?: Record; + } + + export type ToolErrorType = + | 'validation_error' + | 'permission_denied' + | 'timeout' + | 'execution_error' + | 'network_error' + | 'mcp_error' + | 'unknown_error'; + + export interface ToolExecutionResult { + success: boolean; + toolId: string; + toolCallId: string; + output: ToolOutput; + error?: ToolExecutionError; + metadata: { + duration: number; + tokensUsed?: number; + cached?: boolean; + retryCount?: number; + }; + } + + export interface ToolCall { + id: string; + toolId: string; + toolName: string; + input: ToolInput; + callerId: AgentId | string; + callerType: 'agent' | 'workflow' | 'main'; + } + + export function createTextOutput(text: string): ToolOutput; + export function createJSONOutput(data: Record): ToolOutput; + export function createErrorOutput(message: string, code?: string, details?: Record): ToolOutput; +} + +declare module 'waterflow/runtime/core/tools/builtin' { + import type { Platform } from 'waterflow/platform/types'; + import type { Tool } from 'waterflow/runtime/core/tools/tool_interface'; + import { ToolRegistry } from 'waterflow/runtime/core/tools/tool_registry'; + + export const FRAMEWORK_TOOLS: Tool[]; + export function initializeToolRegistry(platform: Platform): ToolRegistry; + export function getFrameworkTools(): Tool[]; +} + +declare module 'waterflow/runtime/core/tools/tool_registry' { + import type { Tool, ToolCategory, ToolInput } from 'waterflow/runtime/core/tools/tool_interface'; + + export interface ValidationResult { + valid: boolean; + errors?: string[]; + } + + export interface ToolSearchResult { + tool: Tool; + relevanceScore: number; + matchReason: string; + } + + export interface SearchOptions { + category?: ToolCategory; + permissionLevel?: string; + limit?: number; + } + + export interface RegistryStatistics { + totalTools: number; + byCategory: Record; + bySource: Record; + byPermissionLevel: Record; + } + + export interface ToolDefinitionExtended { + id: string; + name: string; + description: string; + parameters: { + type: 'object'; + properties: Record; + required?: string[]; + additionalProperties?: boolean; + }; + execute: (params: Record) => Promise; + } + + export class ToolRegistry { + register(tool: Tool | ToolDefinitionExtended): void; + registerAll(tools: (Tool | ToolDefinitionExtended)[]): void; + unregister(toolId: string): void; + get(toolId: string): Tool | ToolDefinitionExtended | undefined; + getByName(name: string): Tool | ToolDefinitionExtended | undefined; + has(toolId: string): boolean; + size(): number; + listAll(): (Tool | ToolDefinitionExtended)[]; + listByCategory(category: ToolCategory): (Tool | ToolDefinitionExtended)[]; + listByPermissionLevel(level: string): (Tool | ToolDefinitionExtended)[]; + search(query: string, options?: SearchOptions): ToolSearchResult[]; + isAvailable(toolId: string, context?: any): boolean; + validateInput(toolId: string, input: ToolInput): ValidationResult; + clear(): void; + getStatistics(): RegistryStatistics; } } diff --git a/重构.md b/重构.md deleted file mode 100644 index c15aa89..0000000 --- a/重构.md +++ /dev/null @@ -1,368 +0,0 @@ -# TrulyMEM WaterFlow 重构计划 - -> **目标**: 将 waterflow 分支重构为标准的 WaterFlow 框架 Tool + Skill,保留原始记忆能力不变。 -> **约束**: 仅修改 waterflow 分支,不影响 main 分支。 - ---- - -## 现状分析 - -### waterflow 分支当前结构 - -``` -ts/ -├── bundled-skills/graph_memory/ ← SKILL.md 已存在 ✅ -│ ├── SKILL.md -│ ├── persona/SKILL.md -│ └── task/SKILL.md -├── src/ -│ ├── platform/ ← 重复定义,需删除 ❌ -│ │ ├── index.ts -│ │ ├── node.ts -│ │ └── types.ts -│ ├── runtime/core/ -│ │ ├── graph_memory/ ← 核心逻辑,保留 ✅ -│ │ │ ├── types.ts -│ │ │ ├── graph_database.ts -│ │ │ ├── memory_service.ts -│ │ │ └── index.ts -│ │ └── tools/ -│ │ ├── tool_interface.ts ← 重复定义,需删除 ❌ -│ │ └── builtin/ -│ │ └── graph_memory_tool.ts ← 需适配 WaterFlow 接口 ✅ -│ └── types/ -│ └── sql.js.d.ts ← 保留 ✅ -└── package.json ← 需调整依赖 ✅ -``` - -### 核心问题 - -| 问题 | 说明 | 解决方案 | -|------|------|----------| -| 重复平台层 | `ts/src/platform/` 与 WaterFlow 重复 | 删除,改用 WaterFlow 的 `getPlatform()` | -| 重复 Tool 接口 | `tool_interface.ts` 与 WaterFlow 重复 | 删除,改用 WaterFlow 的类型 | -| 存储接口不兼容 | 使用自定义 `StorageOperations` | 改用 WaterFlow 的 `platform.fs`(支持 binary) | -| 无注册入口 | 没有将 Tool 注册到 WaterFlow 的方式 | 创建 `registerGraphMemoryTool()` 导出函数 | -| SKILL.md 不完整 | 缺少 persona/task 操作的完整描述 | 补充完善 | - ---- - -## 重构步骤 - -### Phase 1: 清理重复定义 - -#### 1.1 删除 `ts/src/platform/` 目录 - -``` -删除: ts/src/platform/index.ts -删除: ts/src/platform/node.ts -删除: ts/src/platform/types.ts -``` - -**替换方案**: 所有 `import { getPlatform } from '../../../platform'` 改为从 WaterFlow 导入: -```typescript -import { getPlatform } from 'waterflow/platform'; -``` - -#### 1.2 删除 `ts/src/runtime/core/tools/tool_interface.ts` - -**替换方案**: 使用 WaterFlow 的 Tool 接口: -```typescript -import type { Tool, ToolInputSchema, ToolOutput, ToolExecutionContext } from 'waterflow/runtime/core/tools/tool_interface'; -``` - -#### 1.3 更新 `tsconfig.json` - -```json -{ - "compilerOptions": { - "rootDir": "./src", - "outDir": "./dist", - "module": "esnext", - "moduleResolution": "bundler", - "target": "esnext", - "types": ["node"], - "lib": ["esnext"], - "sourceMap": true, - "declaration": true, - "strict": true, - "verbatimModuleSyntax": true, - "isolatedModules": true, - "skipLibCheck": true - }, - "include": ["src/**/*"], - "exclude": ["node_modules", "dist"] -} -``` - ---- - -### Phase 2: 适配 WaterFlow 平台层 - -#### 2.1 修改 `graph_database.ts` — 存储适配 - -**当前**(使用自定义 storage): -```typescript -import { getPlatform } from '../../../platform'; -const platform = getPlatform(); -await platform.storage.save(key, data); // 自定义接口 -``` - -**改为**(使用 WaterFlow fs): -```typescript -import { getPlatform } from 'waterflow/platform'; -const platform = getPlatform(); -await platform.fs.writeFile(dbPath, data, { encoding: 'binary' }); -const loaded = await platform.fs.readFile(dbPath, { encoding: 'binary' }); -``` - -**具体改动**: -- `GraphDatabase.save()` 方法: `storage.save()` → `fs.writeFile(..., { encoding: 'binary' })` -- `GraphDatabase.load()` 方法: `storage.load()` → `fs.readFile(..., { encoding: 'binary' })` -- `dbPath` 使用 `platform.path.join()` 构建 - -#### 2.2 修改 `graph_memory_tool.ts` — Tool 接口适配 - -**当前**: -```typescript -import type { Tool, ... } from '../tool_interface'; // 自定义接口 -import { getPlatform } from '../../../../platform'; // 自定义平台 -``` - -**改为**: -```typescript -import type { Tool, ToolInputSchema, ToolOutput, ToolExecutionContext, ToolInput } from 'waterflow/runtime/core/tools/tool_interface'; -import { getPlatform } from 'waterflow/platform'; -``` - -**新增 WaterFlow 兼容字段**: -```typescript -export class GraphMemoryTool implements Tool { - readonly id = 'builtin:graph_memory'; - readonly name = 'GraphMemory'; - readonly description = '...'; - readonly category: ToolCategory = 'analysis'; - readonly permissionLevel: PermissionLevel = 'safe'; - readonly inputSchema: ToolInputSchema = { ... }; - - // WaterFlow 新增字段(可选) - readonly alwaysLoad = true; // 始终加载完整 schema - readonly shouldDefer = false; // 不延迟加载 - - async handler(params: ToolInput, context: ToolExecutionContext): Promise { - // 使用 context.logger 替代 getPlatform().getLogger() - const logger = context.logger; - // ... 原有逻辑不变 - } -} -``` - -#### 2.3 创建注册入口 - -**新建**: `ts/src/runtime/core/tools/builtin/index.ts` - -```typescript -import type { Tool } from 'waterflow/runtime/core/tools/tool_interface'; -import { GraphMemoryTool, createGraphMemoryTool } from './graph_memory_tool'; - -export { GraphMemoryTool, createGraphMemoryTool }; - -/** - * 注册图记忆工具到 WaterFlow ToolRegistry - * - * 使用方式: - * import { registerGraphMemoryTool } from 'trulymem/tools'; - * registerGraphMemoryTool(toolRegistry, sessionId); - */ -export function registerGraphMemoryTool( - registry: { register: (tool: Tool) => void }, - sessionId?: string -): void { - registry.register(createGraphMemoryTool(sessionId)); -} -``` - ---- - -### Phase 3: 完善 SKILL.md - -#### 3.1 更新主 SKILL.md - -补充 persona 和 task 操作说明,与 `memory_service.ts` 的实际方法对齐: - -```yaml ---- -name: graph_memory -description: 图记忆工具 - 让 AI 拥有真正的长期记忆能力 -when_to_use: 需要 AI 记住、回忆、管理信息或任务时 -context: inline -allowed_tools: - - builtin:graph_memory -arguments: - - name: action - type: string - required: true - enum: [recall, commit, purge, introspect, persona_update, persona_clear, task_create, task_set_state, task_delete, task_link_info] - description: 记忆操作类型 - - name: params - type: object - required: true - description: 操作参数 -user_invocable: true ---- -``` - -#### 3.2 更新 persona/SKILL.md - -```yaml ---- -name: persona_management -description: 人设管理 - 管理 AI 的用户画像和偏好 -context: inline -allowed_tools: - - builtin:graph_memory ---- -``` - -#### 3.3 更新 task/SKILL.md - -```yaml ---- -name: task_management -description: 任务管理 - 管理连续性任务和相关信息 -context: inline -allowed_tools: - - builtin:graph_memory ---- -``` - ---- - -### Phase 4: 依赖与构建 - -#### 4.1 更新 `package.json` - -```json -{ - "name": "trulymem-waterflow", - "version": "1.0.0", - "description": "TrulyMEM 图记忆系统 - WaterFlow Skill/Tool 实现", - "type": "module", - "main": "./dist/runtime/core/tools/builtin/index.js", - "exports": { - "./tools": "./dist/runtime/core/tools/builtin/index.js", - "./graph_memory": "./dist/runtime/core/graph_memory/index.js", - "./skills": "./bundled-skills" - }, - "scripts": { - "build": "tsc", - "test": "vitest" - }, - "peerDependencies": { - "waterflow-ts": ">=0.1.0" - }, - "dependencies": { - "sql.js": "^1.8.0" - }, - "devDependencies": { - "@types/node": "^25.5.2", - "typescript": "^5.0.0", - "vitest": "^2.0.0" - } -} -``` - -#### 4.2 添加 `sql.js.d.ts` 类型声明 - -保留现有 `ts/src/types/sql.js.d.ts`,确保编译通过。 - ---- - -### Phase 5: 验证 - -#### 5.1 编译验证 - -```bash -cd ts/ -npm install -npm run build -# 检查 dist/ 输出 -``` - -#### 5.2 类型检查 - -```bash -npx tsc --noEmit -# 确保无类型错误 -``` - -#### 5.3 集成验证(在 WaterFlow 项目中) - -```typescript -// 在 WaterFlow 入口文件中测试 -import { getPlatform } from './platform'; -import { initializeToolRegistry } from './runtime/core/tools/builtin'; -import { registerGraphMemoryTool } from 'trulymem/tools'; - -const platform = getPlatform(); -const registry = initializeToolRegistry(platform); - -// 注册图记忆工具 -registerGraphMemoryTool(registry, 'test-session'); - -// 验证工具已注册 -const tool = registry.get('builtin:graph_memory'); -console.log('GraphMemory tool registered:', !!tool); -``` - ---- - -## 文件变更清单 - -| 操作 | 文件路径 | 说明 | -|------|---------|------| -| 🗑️ 删除 | `ts/src/platform/index.ts` | 重复平台层 | -| 🗑️ 删除 | `ts/src/platform/node.ts` | 重复平台层 | -| 🗑️ 删除 | `ts/src/platform/types.ts` | 重复平台层 | -| 🗑️ 删除 | `ts/src/runtime/core/tools/tool_interface.ts` | 重复接口 | -| ✏️ 修改 | `ts/src/runtime/core/graph_memory/graph_database.ts` | 改用 WaterFlow fs | -| ✏️ 修改 | `ts/src/runtime/core/tools/builtin/graph_memory_tool.ts` | 适配 WaterFlow 接口 | -| ✏️ 修改 | `ts/src/runtime/core/graph_memory/index.ts` | 更新导出路径 | -| ✏️ 修改 | `ts/bundled-skills/graph_memory/SKILL.md` | 补充完整操作说明 | -| ✏️ 修改 | `ts/bundled-skills/graph_memory/persona/SKILL.md` | 完善 | -| ✏️ 修改 | `ts/bundled-skills/graph_memory/task/SKILL.md` | 完善 | -| ✏️ 修改 | `ts/package.json` | 调整为 peerDependency | -| ✏️ 修改 | `ts/tsconfig.json` | 清理配置 | -| ➕ 新增 | `ts/src/runtime/core/tools/builtin/index.ts` | 注册入口 | - ---- - -## 依赖关系图(重构后) - -``` -WaterFlow 框架 -├── Platform (getPlatform) -│ ├── fs.readFile/writeFile (binary) ← GraphDatabase 使用 -│ ├── path.join/resolve ← 路径构建 -│ ├── getLogger ← 日志 -│ └── globals.randomUUID ← UUID 生成 -│ -├── ToolRegistry -│ ├── FRAMEWORK_TOOLS (Agent, ToolSearch) -│ ├── Platform Tools (Read, Write, Bash...) -│ └── GraphMemoryTool ← 从 trulymem/tools 注册 -│ -└── SkillLoader - └── bundled-skills/graph_memory/SKILL.md - └── allowed_tools: ['builtin:graph_memory'] - └→ LLM 调用 → ToolExecutor → GraphMemoryTool.handler() -``` - ---- - -## 风险与注意事项 - -1. **WaterFlow 版本依赖**: 使用 `peerDependencies` 确保与 WaterFlow 版本兼容 -2. **二进制存储**: WaterFlow 的 `fs` 支持 `encoding: 'binary'`,已验证可用 -3. **类型兼容**: 确保 Tool 接口字段与 WaterFlow 完全一致 -4. **SKILL.md 格式**: YAML frontmatter 必须符合 WaterFlow SkillLoader 解析规则