Kaynağa Gözat

refactor: knowhub

Talegorithm 1 gün önce
ebeveyn
işleme
51f42b9046
42 değiştirilmiş dosya ile 1540 ekleme ve 954 silme
  1. 296 0
      agent/docs/cognition-log.md
  2. 0 201
      agent/docs/knowledge.md
  3. 416 0
      agent/docs/memory.md
  4. 71 198
      knowhub/README.md
  5. 197 0
      knowhub/docs/api.md
  6. 0 0
      knowhub/docs/archive/agents-readme.md
  7. 0 0
      knowhub/docs/archive/dedup-design.md
  8. 103 53
      knowhub/docs/archive/knowledge-management.md
  9. 0 0
      knowhub/docs/archive/migration-guide.md
  10. 0 0
      knowhub/docs/archive/resource-storage.md
  11. 0 269
      knowhub/docs/feedback-timing-design.md
  12. 0 0
      knowhub/docs/frontend-restructure-plan.md
  13. 152 0
      knowhub/docs/librarian-agent.md
  14. 112 0
      knowhub/docs/processing-pipeline.md
  15. 163 0
      knowhub/docs/schema.md
  16. 30 233
      knowhub/knowhub_db/README.md
  17. 0 0
      knowhub/knowhub_db/migrations/create_tables.py
  18. 0 0
      knowhub/knowhub_db/migrations/fill_cap_relations.py
  19. 0 0
      knowhub/knowhub_db/migrations/fill_cap_tools.py
  20. 0 0
      knowhub/knowhub_db/migrations/fill_embeddings.py
  21. 0 0
      knowhub/knowhub_db/migrations/fill_knowledge_tools.py
  22. 0 0
      knowhub/knowhub_db/migrations/fix_embedding_migration.py
  23. 0 0
      knowhub/knowhub_db/migrations/import_initial_data.py
  24. 0 0
      knowhub/knowhub_db/migrations/import_tool_research_data.py
  25. 0 0
      knowhub/knowhub_db/migrations/migrate_add_implemented_tools.py
  26. 0 0
      knowhub/knowhub_db/migrations/migrate_knowledge.py
  27. 0 0
      knowhub/knowhub_db/migrations/migrate_resources.py
  28. 0 0
      knowhub/knowhub_db/migrations/migrate_tables_v2.py
  29. 0 0
      knowhub/knowhub_db/migrations/migrate_tools.py
  30. 0 0
      knowhub/knowhub_db/migrations/reclassify_tool_knowledge.py
  31. 0 0
      knowhub/knowhub_db/migrations/update_case_knowledge.py
  32. 0 0
      knowhub/knowhub_db/scripts/check_extensions.py
  33. 0 0
      knowhub/knowhub_db/scripts/check_fastann.py
  34. 0 0
      knowhub/knowhub_db/scripts/check_table_structure.py
  35. 0 0
      knowhub/knowhub_db/scripts/clean_invalid_knowledge_refs.py
  36. 0 0
      knowhub/knowhub_db/scripts/clean_resource_knowledge_refs.py
  37. 0 0
      knowhub/knowhub_db/scripts/clean_tool_research_data.py
  38. 0 0
      knowhub/knowhub_db/scripts/clear_locks.py
  39. 0 0
      knowhub/knowhub_db/scripts/kill_db_locks.py
  40. 0 0
      knowhub/knowhub_db/scripts/list_databases.py
  41. 0 0
      knowhub/knowhub_db/scripts/test_imports.py
  42. 0 0
      knowhub/knowhub_db/scripts/test_pg_connection.py

+ 296 - 0
agent/docs/cognition-log.md

@@ -0,0 +1,296 @@
+# Cognition Log 与知识反馈设计
+
+## 文档维护规范
+
+0. **先改文档,再动代码** - 新功能或重大修改需先完成文档更新、并完成审阅后,再进行代码实现;除非改动较小、不被文档涵盖
+1. **文档分层,链接代码** - 重要或复杂设计可以另有详细文档;关键实现需标注代码文件路径;格式:`module/file.py:function_name`
+2. **简洁快照,日志分离** - 只记录最重要的、与代码准确对应的或者明确的已完成的设计的信息,避免推测、建议、决策历史、修改日志、大量代码;决策依据或修改日志若有必要,可在 `knowhub/docs/decisions.md` 另行记录
+
+---
+
+## 概述
+
+每个 trace 维护一个 `cognition_log.json`,按时间顺序记录所有认知事件(知识查询、评估、提取、反思),为知识质量反馈和 Memory 系统的 dream 操作(详见 `agent/docs/memory.md`)提供数据。
+
+> 此文件原名 `knowledge_log.json`,扩展为统一事件流后更名。
+
+---
+
+## Cognition Log 数据结构
+
+**位置**:`.trace/{trace_id}/cognition_log.json`
+
+```json
+{
+  "trace_id": "trace-xxx",
+  "events": [
+    { "type": "query", "sequence": 42, ... },
+    { "type": "evaluation", "sequence": 66, ... },
+    { "type": "extraction", "sequence": 88, ... },
+    { "type": "reflection", "sequence": 120, ... }
+  ]
+}
+```
+
+所有事件按 `sequence` 排列,保持在 trace 中的时间顺序。
+
+---
+
+## 事件类型
+
+### `query`:知识查询
+
+Agent 通过 `POST /api/knowledge/ask` 查询知识时记录。一次查询返回 KM Agent 的整合回答及引用的各 source,作为一个整体记录。
+
+```json
+{
+  "type": "query",
+  "sequence": 42,
+  "goal_id": "1",
+  "query": "goal 的描述文本",
+  "response": "KM Agent 整合后的回答...",
+  "source_ids": ["knowledge-a1b2", "knowledge-c3d4", "knowledge-e5f6"],
+  "sources": [
+    {"id": "knowledge-a1b2", "task": "...", "content": "...(截断500字)"},
+    {"id": "knowledge-c3d4", "task": "...", "content": "..."}
+  ],
+  "timestamp": "2026-03-20T10:00:00"
+}
+```
+
+**写入时机**:`agent/trace/goal_tool.py:inject_knowledge_for_goal`,`POST /api/knowledge/ask` 返回后。
+
+### `evaluation`:知识评估
+
+对某次 query 中各 source 的使用效果评估。通过 `query_sequence` 关联到对应的 query 事件。
+
+```json
+{
+  "type": "evaluation",
+  "sequence": 66,
+  "query_sequence": 42,
+  "trigger": "goal_completion",
+  "assessments": [
+    {"source_id": "knowledge-a1b2", "status": "helpful", "reason": "准确定位了问题"},
+    {"source_id": "knowledge-c3d4", "status": "irrelevant", "reason": "与当前任务无关"},
+    {"source_id": "knowledge-e5f6", "status": "harmful", "reason": "建议的方法已过时"}
+  ],
+  "timestamp": "2026-03-20T10:05:00"
+}
+```
+
+**`status` 可能的值**:
+
+| 状态 | 含义 |
+|---|---|
+| `irrelevant` | 知识与当前任务无关 |
+| `unused` | 知识相关但未被使用 |
+| `helpful` | 知识对任务有实质帮助 |
+| `harmful` | 知识对任务产生负面作用 |
+| `neutral` | 知识相关但无明显影响 |
+
+### `extraction`:知识提取
+
+Agent 通过 reflection 侧分支将知识上传到 KnowHub 时记录。
+
+```json
+{
+  "type": "extraction",
+  "sequence": 88,
+  "trigger": "compression",
+  "items": [
+    {"knowledge_id": "knowledge-new-1", "type": "experience", "task": "...", "content": "...(截断500字)"}
+  ],
+  "timestamp": "2026-03-20T10:10:00"
+}
+```
+
+**写入时机**:reflection 侧分支中 `upload_knowledge` 调用成功后。
+
+### `reflection`:记忆反思
+
+仅 memory-bearing Agent 使用(详见 `agent/docs/memory.md`)。Dream 操作触发的 per-trace 记忆反思。
+
+```json
+{
+  "type": "reflection",
+  "sequence": 120,
+  "reflected_range": [43, 120],
+  "summary": "这次执行中发现用户偏好XX方向...",
+  "timestamp": "2026-04-07T20:00:00"
+}
+```
+
+**写入时机**:dream 操作中 per-trace 反思完成后。
+
+---
+
+## 评估触发机制
+
+评估针对的是未评估的 query 事件(即存在 query 事件但没有对应 evaluation 事件的)。
+
+**判断待评估条件**:查找 cognition_log 中所有 `type: "query"` 事件,检查是否存在 `query_sequence` 指向该 query 的 `type: "evaluation"` 事件。
+
+### 触发点 1:Goal 完成
+
+**时机**:Goal status 变为 `completed` 或 `abandoned`
+
+**触发逻辑**(`agent/trace/store.py:update_goal`):
+
+```
+Goal 完成
+  ↓
+查询 cognition_log 中未评估的 query 事件
+  ↓
+如果有待评估
+  → 设置 trace.context["pending_knowledge_eval"] = true
+  → 设置 trace.context["knowledge_eval_trigger"] = "goal_completion"
+  ↓
+Runner 主循环下一次迭代开头检测到标志(agent/core/runner.py:_agent_loop)
+  → 清除标志
+  → 将 "knowledge_eval" 加入 force_side_branch 队列
+```
+
+### 触发点 2:压缩
+
+**时机**:上下文 token 数超过阈值,即将执行压缩
+
+**触发逻辑**(`agent/core/runner.py:_manage_context_usage`):
+
+```
+压缩条件触发
+  ↓
+查询 cognition_log 中未评估的 query 事件
+  ↓
+如果有待评估
+  → 设置 trace.context["knowledge_eval_trigger"] = "compression"
+  → 侧分支队列:["reflection", "knowledge_eval", "compression"](启用知识提取时)
+  →            或 ["knowledge_eval", "compression"](未启用时)
+  → 返回"需要进入侧分支"信号,暂缓压缩
+```
+
+压缩会删除消息历史,必须在压缩前完成评估。
+
+### 触发点 3:任务结束(兜底)
+
+**时机**:主路径无工具调用,Agent 即将结束
+
+**触发逻辑**(`agent/core/runner.py:_agent_loop`):
+
+```
+任务即将结束
+  ↓
+查询 cognition_log 中未评估的 query 事件
+  ↓
+如果有待评估
+  → 设置 trace.context["knowledge_eval_trigger"] = "task_completion"
+  → 将 ["knowledge_eval"] 加入 force_side_branch 队列
+  → continue(不 break,下一轮执行评估)
+```
+
+---
+
+## 侧分支评估流程
+
+### 侧分支类型
+
+复用 `SideBranchContext` 机制,类型 `"knowledge_eval"`(`agent/trace/models.py:Message.branch_type`)。
+
+### 评估 Prompt 结构
+
+完整实现:`agent/core/runner.py:_build_knowledge_eval_prompt`
+
+```
+你是知识评估助手。请评估以下知识查询结果在本次任务执行中的实际效果。
+
+## 当前任务(Mission)       ← trace.task
+## 当前 Goal                ← goal_tree.current 的 description
+## 待评估知识查询            ← 未评估的 query 事件列表
+  对每个 query:展示 query 文本、整合回答、各 source 的 id/task/content
+## 评估要求                  ← 按 source_id 逐一评估
+## 评估分类                  ← 5 个 status 选项
+## 输出格式                  ← JSON
+```
+
+Prompt 中**不包含消息历史**。LLM 依据对话上下文中已有的执行过程作出判断。
+
+### 评估输出格式
+
+LLM 直接输出 JSON:
+
+```json
+{
+  "evaluations": [
+    {
+      "query_sequence": 42,
+      "assessments": [
+        {"source_id": "knowledge-a1b2", "status": "helpful", "reason": "..."},
+        {"source_id": "knowledge-c3d4", "status": "irrelevant", "reason": "..."}
+      ]
+    }
+  ]
+}
+```
+
+### 即时写入
+
+每次 LLM 回复后立即解析,三种策略降级:整体 JSON → ` ```json ` 代码块 → 正则裸对象。
+
+解析成功 → 为每个 query 写入对应的 `evaluation` 事件到 cognition_log。解析失败记日志,不中断。
+
+---
+
+## 数据流
+
+```
+知识查询(agent/trace/goal_tool.py:inject_knowledge_for_goal)
+  ↓
+POST /api/knowledge/ask → KM Agent 整合回答
+  ↓
+写入 cognition_log: type="query"(含 response + source_ids)
+  ↓
+  ┌─────────────────────────────────────────────┐
+  │  触发点 A:Goal 完成(goal_completion)       │
+  │  触发点 B:压缩执行前(compression)          │
+  │  触发点 C:任务自然结束(task_completion)    │
+  └─────────────────────────────────────────────┘
+  ↓
+Runner 进入 knowledge_eval 侧分支
+  ↓
+LLM 按 query 维度、逐 source 评估,输出 JSON
+  ↓
+写入 cognition_log: type="evaluation"(含 assessments per source)
+  ↓
+侧分支退出 → 恢复主路径
+
+                    ···
+
+知识提取(reflection 侧分支中 upload_knowledge 成功后)
+  ↓
+写入 cognition_log: type="extraction"
+
+                    ···
+
+Dream 触发(memory-bearing Agent,详见 agent/docs/memory.md)
+  ↓
+读取 cognition_log 全部事件 → per-trace 记忆反思
+  ↓
+写入 cognition_log: type="reflection"
+```
+
+---
+
+## 与现有系统的集成点
+
+| 集成位置 | 文件 | 说明 |
+|---|---|---|
+| 知识查询时写 log | `agent/trace/goal_tool.py:inject_knowledge_for_goal` | `goal(focus=...)` 触发 ask → 写入 `query` 事件 |
+| Goal 完成时设置标志 | `agent/trace/store.py:update_goal` | 设置 `trace.context["pending_knowledge_eval"]` |
+| 主循环检测标志 | `agent/core/runner.py:_agent_loop` | 每轮迭代开头检测,触发 `["knowledge_eval"]` |
+| 压缩前触发评估 | `agent/core/runner.py:_manage_context_usage` | 压缩前检查 pending,先评估再压缩 |
+| 任务结束兜底 | `agent/core/runner.py:_agent_loop` | 退出前检查 pending,强制触发评估 |
+| 侧分支类型 | `agent/trace/models.py:Message.branch_type` | Literal 中包含 `"knowledge_eval"` |
+| 即时写入评估 | `agent/core/runner.py:_agent_loop` | 解析 JSON 后写入 `evaluation` 事件 |
+| 知识提取记录 | `agent/core/runner.py` | reflection 侧分支中 upload 成功后写入 `extraction` 事件 |
+| 记忆反思记录 | dream 操作 | per-trace 反思后写入 `reflection` 事件 |
+| Log 文件管理 | `agent/trace/store.py` | 待重构:从 entries[] 改为 events[] |

+ 0 - 201
agent/docs/knowledge.md

@@ -1,201 +0,0 @@
-- 产生知识时区分:人、场景(例如飞书群,可以对应到tags)、业务(还有子业务)
-
-**知识结构**(单条知识)
-    id: 知识唯一标识
-    task: 任务描述,什么场景、在做什么
-
-    type: 知识类型(单选)
-        user_profile:用户画像(偏好、习惯、背景、约束)
-        strategy:具体执行经验,从执行过程中反思获得
-        tool:工具名称,简介,使用方法,优缺点对比,代码示例
-        usecase:用户背景,采用方案,实现步骤,问题,效果
-        definition:概念定义,技术原理,应用场景
-        plan:流程步骤,决策点,某个问题的总结方法论
-
-    tags: 业务标签(可有多个)
-        category: 子类别(如 preference, background, habit, constraint)
-        domain: 领域(如 coding_style, architecture)
-        其他自定义标签
-        scenario
-
-    scopes: 可见范围(可有多个,格式:{entity_type}:{entity_id})
-        user:{user_id}:用户级(个人可见)
-        agent:{agent_id}:Agent 级(特定 Agent 可见)
-        project:{project_id}:项目级(项目组可见)
-        team:{team_id}:团队级(部门可见)
-        org:{org_id}:组织级(全公司可见)
-        public:公开(所有人可见)
-
-    owner: 所有者(格式:{entity_type}:{entity_id},唯一)
-        谁创建的,谁有权修改/删除
-
-    content:
-        基于类型的具体内容,相对完整的一条知识
-
-    source:
-        name: 工具/资源名称(若有)
-        category:paper/exp/skill/book...
-        urls:知识来源的网站
-        agent_id:调用知识查询的agent名称
-        submitted_by:创建本条目的agent负责人名称
-        timestamp: 知识生成时的时间戳
-        trace_id: 来源 Trace ID(若有)
-
-    eval:基于使用反馈
-        helpful: 好用的次数
-        harmful:不好用的次数
-        confidence: 置信度(0-1)
-        helpful_history: [(query+trace_id+outcome), ]用于记录反馈时的调用总结
-        harmful_history: []
-
-知识检索机制
-    检索流程
-        1. 构建可见范围
-            根据执行上下文(user_id, agent_id, project_id, team_id, org_id)
-            构建用户的所有可见 scopes:
-                - user:{user_id}
-                - agent:{agent_id}
-                - project:{project_id}
-                - team:{team_id}
-                - org:{org_id}
-                - public
-
-        2. 向量检索 + 过滤
-            查询条件:
-                - 语义匹配(向量检索)
-                - scopes 过滤(知识的 scopes 与用户的 visible_scopes 有交集)
-                - type 过滤(可选,按知识类型过滤)
-
-        3. 按优先级排序
-            优先级:user > project > agent > team > org > public
-            取知识的 scopes 中优先级最高的进行排序
-
-    触发时机
-        - Agent 启动时:自动检索相关知识
-        - Goal focus 时:检索与当前目标相关的知识
-        - 主动调用:通过 get_knowledge 工具主动查询
-
-    实现位置
-        - agent/tools/builtin/knowledge.py: 知识管理工具(KnowHub API 封装)+ KnowledgeConfig
-        - agent/tools/builtin/knowledge.py: knowledge_search / knowledge_save 工具
-知识提取机制
-    触发时机
-        - 主动表达:用户明确表达偏好、纠正、提供背景信息
-        - 任务完成:任务完成后的反思总结
-        - 压缩消息:在压缩消息节点提取经验
-        - 用户反馈:用户对结果的 helpful/harmful 评价
-
-    提取流程
-        1. 识别知识类型
-            根据内容判断是 user_profile / strategy / tool / definition / plan / usecase
-
-        2. 结构化提取
-            - 提取核心内容
-            - 生成标签(category, domain 等)
-            - 确定 scopes(基于执行上下文)
-            - 设置 owner 和 visibility
-
-        3. 持久化存储
-            - 存入知识库(向量数据库 + 元数据)
-            - 记录来源(trace_id, agent_id, timestamp)
-            - 初始化评价(helpful=1, confidence=0.5)
-
-    实现位置(规划)
-        - agent/trace/compaction.py: 压缩时提取经验
-        - agent/tools/builtin/knowledge.py: knowledge_save 工具
-用户画像特殊处理
-    用户画像是一种特殊的知识类型(type=user_profile),具有以下特点:
-
-    获取方式
-        - 持续性:在整个对话过程中持续积累
-        - 多触发点:主动表达 > 任务完成 > 周期性总结
-        - 渐进式:逐步完善,置信度逐渐提高
-
-    存储特点
-        - type: user_profile
-        - scopes: 通常包含 user:{user_id},可能包含 project:{project_id}
-        - owner: user:{user_id}
-        - tags.category: preference | background | habit | constraint
-
-    检索优先级
-        - 在 Agent 启动时自动加载
-        - 优先级高于其他类型的知识
-        - 按 confidence 和 helpful 评分排序
-
-    示例
-        {
-            "id": "profile_001",
-            "type": "user_profile",
-            "task": "用户编码风格偏好",
-            "tags": {
-                "category": "preference",
-                "domain": "coding_style"
-            },
-            "scopes": ["user:123", "project:456"],
-            "owner": "user:123",
-            "visibility": "shared",
-            "content": "用户偏好使用 TypeScript 而非 JavaScript,注重类型安全",
-            "source": {
-                "agent_id": "general_assistant",
-                "trace_id": "trace-xxx",
-                "timestamp": "2026-03-03"
-            },
-            "eval": {
-                "helpful": 5,
-                "harmful": 0,
-                "confidence": 0.9
-            }
-        }
-存储结构(规划)
-    数据库表结构
-        CREATE TABLE knowledge (
-            id TEXT PRIMARY KEY,
-            type TEXT NOT NULL,              -- user_profile | strategy | tool | ...
-            task TEXT,
-            tags JSON,
-            scopes JSON,                     -- ["user:123", "project:456", ...]
-            owner TEXT NOT NULL,             -- "user:123" | "agent:xxx"
-            visibility TEXT,                 -- private | shared | org | public
-            content TEXT,
-            source JSON,
-            eval JSON,
-            embedding VECTOR(1536),          -- 向量检索
-            created_at TIMESTAMP,
-            updated_at TIMESTAMP
-        );
-
-        -- 索引
-        CREATE INDEX idx_type ON knowledge(type);
-        CREATE INDEX idx_owner ON knowledge(owner);
-        CREATE INDEX idx_visibility ON knowledge(visibility);
-        CREATE INDEX idx_scopes ON knowledge USING GIN(scopes);
-
-    文件系统结构
-        /workspace/knowledge/
-        ├── global/                   # 全局知识
-        │   ├── tools.json
-        │   ├── definitions.json
-        │   └── plans.json
-        │
-        ├── agents/                   # Agent 经验
-        │   ├── general_assistant/
-        │   ├── crawler_ops/
-        │   └── ...
-        │
-        └── users/                    # 用户画像
-            ├── user_123/
-            │   ├── profile.json      # 基础信息
-            │   ├── preferences.json  # 偏好
-            │   ├── habits.json       # 习惯
-            │   └── constraints.json  # 约束
-            └── ...
-
-TODO
-    1. ~~实现知识存储接口~~ → 已通过 KnowHub API 实现(agent/tools/builtin/knowledge.py)
-    2. ~~实现知识检索逻辑~~ → knowledge_search 工具
-    3. ~~实现 knowledge_save 工具~~ → 已实现
-    4. ~~实现 knowledge_search 工具~~ → 已实现
-    5. ~~在 Agent 启动时集成知识检索~~ → 已实现(goal focus 时注入)
-    6. ~~在 Goal focus 时集成知识检索~~ → 已实现(agent/trace/goal_tool.py:inject_knowledge_for_goal)
-    7. ~~在压缩消息时集成知识提取~~ → 已实现(agent/core/runner.py:_run_reflect)
-    8. 实现用户画像的特殊处理逻辑

+ 416 - 0
agent/docs/memory.md

@@ -0,0 +1,416 @@
+# Memory 系统与元思考机制设计
+
+> 状态:设计讨论中,未实现
+
+---
+
+## 概述
+
+本文档设计两个紧密关联的能力:
+
+1. **Memory**:为需要跨任务维持身份的 Agent 提供持久化记忆(Markdown 文件)
+2. **统一元思考机制**:整合现有的知识提取(reflection)、知识评估(knowledge_eval)和新增的记忆反思(dream),形成完整的"Agent 自我认知"能力
+
+---
+
+## 一、现有元思考机制梳理
+
+当前框架已实现两种元思考能力,都基于侧分支(side branch)机制:
+
+### 1.1 知识提取(reflection 侧分支)
+
+**目的**:从执行过程中提取客观知识,保存到 KnowHub(全局共享知识库)。
+
+**触发时机**:
+- 压缩前(`_manage_context_usage`,`runner.py:825-829`)
+- 任务完成后(`runner.py:1834-1838`,`enable_completion_extraction`)
+
+**输出**:调用 `upload_knowledge` 工具,保存 experience/tool/strategy/case 到 KnowHub。
+
+**Prompt**:`REFLECT_PROMPT`(压缩时)和 `COMPLETION_REFLECT_PROMPT`(任务完成后),定义在 `agent/core/prompts/knowledge.py`。
+
+**已知问题**:任务完成时触发的 reflection 使用 `config.knowledge.get_reflect_prompt()`(`runner.py:1249`),没有区分压缩场景和完成场景。应该在完成场景使用 `get_completion_reflect_prompt()`。
+
+### 1.2 知识评估(knowledge_eval 侧分支)
+
+**目的**:评估被注入的知识是否有用,记录到本地 `knowledge_log.json`。
+
+**触发时机**(详见 `knowhub/docs/cognition-log.md`):
+- Goal 完成时(`store.py:update_goal`,设置 `pending_knowledge_eval` 标志)
+- 压缩前(必须在压缩前完成评估,否则执行上下文丢失)
+- 任务结束时(兜底)
+
+**输出**:每条被注入的知识获得评估(irrelevant / unused / helpful / harmful / neutral),写入 `knowledge_log.json`。
+
+**当前局限**:评估结果只存本地,不自动回传 KnowHub。只有用户通过 API 手动反馈才同步。
+
+### 1.3 侧分支队列机制
+
+两种元思考通过 `force_side_branch` 队列协调执行顺序(`runner.py:1198-1207`):
+
+```
+压缩触发时的典型队列:
+  ["reflection", "knowledge_eval", "compression"]
+  
+任务完成时:
+  ["knowledge_eval"](先评估)→ ["reflection"](再提取)
+```
+
+每个侧分支执行完后 pop 队首,继续下一个,直到队列清空回到主路径。
+
+---
+
+## 二、缺失的能力:个人记忆
+
+### 问题
+
+现有的两种元思考都面向**全局共享知识**(KnowHub)。但有一类 Agent 需要维护**主观的、属于自己的长期记忆**:
+
+- 品味偏好、策略判断、风格积累、用户反馈
+- 属于特定 Agent 身份,不是公共知识
+- 需要人类能直接阅读和修改
+- 跨多次 trace 持续积累和演化
+- 可能被同一身份下的多个 Agent run 共享读写
+
+KnowHub 不适合承担这个职责——它是"大众点评",不是"个人日记"。
+
+### 记忆文件
+
+记忆以 Markdown 文件存储在指定目录下。每个文件覆盖一个语义维度。
+
+```
+{base_path}/
+├── taste.md        # 偏好判断
+├── strategy.md     # 当前策略
+├── skills.md       # 积累的技巧
+└── ...
+```
+
+**为什么是 Markdown 文件**:
+- 人类可直接阅读和修改(vim/VS Code 打开就能改)
+- Git 版本控制
+- Agent 用 read_file/write_file 工具即可操作,无需新增工具
+- 文件数量少(几个到十几个),不需要检索能力
+
+**共享读写**:同一身份下的多个 Agent run 可以读写同一组记忆文件。哪个 Agent 该关注哪些文件、怎么更新,由 dream prompt 来定义。
+
+---
+
+## 三、统一元思考模型
+
+### 三种元思考及其定位
+
+| | 知识提取(已有) | 知识评估(已有) | 记忆反思(新增) |
+|---|---|---|---|
+| **回答的问题** | 我学到了什么客观知识? | 给我的知识有没有用? | 这些经历对我的偏好/策略意味着什么? |
+| **输出目的地** | KnowHub(全局共享) | knowledge_log.json(本地) | 记忆文件(Agent 身份私有) |
+| **触发时机** | 压缩前、任务完成后 | Goal 完成、压缩前、任务结束 | Dream 时(见下文) |
+| **时效性要求** | 高(压缩会丢上下文) | 高(压缩会丢上下文) | 低(可以延迟处理) |
+| **实现机制** | reflection 侧分支 | knowledge_eval 侧分支 | dream 操作(新增) |
+
+**关键区分**:知识提取和知识评估必须在上下文丢失前完成(压缩前/任务结束时),所以是侧分支、即时触发。记忆反思可以延迟——甚至应该延迟,因为用户可能还有反馈、Agent 可能继续执行。
+
+### 为什么记忆反思不在 trace 结束时做
+
+trace 结束只意味着 Agent 行动完一个轮次。后续可能发生:
+- 用户在飞书里说"这个方向不对"
+- Agent 被唤醒在同一任务下继续执行
+- 新的 trace 产生了推翻前一个 trace 结论的信息
+
+如果 trace 一结束就做记忆反思,这些后续信息会被忽略。记忆反思的价值在于**综合一段时间的经历**,不是记录每次行动的即时感受。
+
+### 但知识提取仍然在压缩/完成时做
+
+这不矛盾。知识提取保存的是**客观知识**(工具用法、调研结果),这些不会因为后续反馈而失效。而且压缩会删除历史,如果不在压缩前提取,知识就永久丢失了。
+
+---
+
+## 四、Dream:记忆反思的触发与流程
+
+### 什么是 Dream
+
+Dream 是 memory-bearing Agent 的记忆整理操作。它不是一个侧分支(不在某个 trace 的执行过程中插入),而是一个**独立的顶层操作**,回顾多个 trace 的执行历史,更新记忆文件。
+
+### 触发方式
+
+- Agent 主动调用 `dream` 工具("我觉得该整理一下了")
+- 外部调度触发(定时、或人工 CLI 触发)
+- 框架可以在 run 启动时检测距上次 dream 的时间/trace 数量,建议 Agent dream
+
+### 反思状态追踪
+
+```
+Trace 模型新增字段:
+- reflected_at_sequence: Optional[int]    # 上次记忆反思时的最新 message sequence
+                                           # None = 从未被记忆反思处理
+```
+
+反思摘要不存在 Trace 模型中,而是作为 `reflection` 事件写入 `cognition_log.json`(详见 `knowhub/docs/cognition-log.md`)。
+
+- Agent run 产生新 message → `reflected_at_sequence` 自然落后于实际 sequence
+- 记忆反思完成 → 更新 `reflected_at_sequence` 为当前最新 sequence
+- Dream 扫描 `reflected_at_sequence < latest_sequence` 的 trace
+
+### Dream 流程
+
+```
+Dream 触发
+  │
+  ├─ Step 1: 扫描该 Agent 身份下所有 trace
+  │   找到 reflected_at_sequence < latest_sequence 的 trace
+  │
+  ├─ Step 2: Per-trace 记忆反思(逐个 trace)
+  │   对每个需要反思的 trace:
+  │   a. 加载 reflected_at_sequence 之后的消息(增量)
+  │   b. 同时加载该 trace 的 cognition_log.json(查询、评估、提取事件)
+  │   c. 用 reflect_prompt 生成反思摘要
+  │   d. 摘要作为 reflection 事件写入 cognition_log.json
+  │   e. 更新 reflected_at_sequence
+  │
+  ├─ Step 3: 跨 trace 整合
+  │   a. 收集各 trace 的 reflection 事件(cognition_log 中 type="reflection")
+  │   b. 读取当前记忆文件
+  │   c. 汇总 cognition_log 中的评估趋势(多次 harmful/unused 的 source 模式)
+  │   d. 用 dream_prompt 指导 LLM 更新记忆文件
+  │   e. 标记 reflection 事件为已消化
+  │
+  └─ 完成
+```
+
+### Per-trace 反思的输入
+
+反思 prompt 看到的不只是"发生了什么",还包括知识评估结果:
+
+```
+## 执行过程
+[该 trace 中 reflected_at_sequence 之后的消息]
+
+## 知识使用情况(来自 cognition_log.json)
+查询 1(sequence 42):"ControlNet 相关工具知识"
+  → source knowledge-a1b2: helpful — "准确定位了问题"
+  → source knowledge-c3d4: irrelevant — "与当前任务无关"
+  → source knowledge-e5f6: harmful — "建议的方法已过时"
+
+## 请反思
+1. 这次执行中有什么值得记住的经验?
+2. 哪些知识的评估结果反映了我的判断需要调整?
+3. 用户的反馈(如果有)说明了什么?
+```
+
+这样,已有的 knowledge_eval 结果直接成为记忆反思的输入,不需要重复评估。
+
+### Dream 整合的输入
+
+Dream prompt 看到的是:
+
+```
+## 最近的反思摘要
+[各 trace 的 reflect_summary,每份几百 token]
+
+## 知识评估趋势(汇总自各 trace 的 cognition_log)
+- 最近 N 个 trace 中,被评为 harmful 的 source:[列表]
+- 被评为 unused 的高频 source 类型:[统计]
+- 被评为 helpful 的查询模式:[统计]
+
+## 当前记忆文件
+[各文件内容]
+
+## 请更新记忆
+[dream_prompt 的具体指导]
+```
+
+---
+
+## 五、与现有实现的集成
+
+### 不改动的部分
+
+| 现有机制 | 保持不变 | 原因 |
+|---|---|---|
+| reflection 侧分支 | ✅ | 知识提取到 KnowHub,时效性要求高,必须在压缩前做 |
+| knowledge_eval 侧分支 | ✅ | 知识评估,时效性要求高,必须在压缩前做 |
+| force_side_branch 队列 | ✅ | 侧分支排序机制,成熟可靠 |
+| cognition_log.json | ✅ | 统一事件流存储(原 knowledge_log.json 扩展),dream 直接读取 |
+| 三个评估触发点 | ✅ | Goal 完成/压缩前/任务结束 |
+
+### 需要修改的部分
+
+**1. 任务完成时的 reflection prompt 选择**
+
+当前 `runner.py:1249` 始终使用 `get_reflect_prompt()`。应区分场景:
+
+```python
+# runner.py:1248-1249 修改
+if branch_type == "reflection":
+    if break_after_side_branch:  # 任务完成后的反思
+        prompt = config.knowledge.get_completion_reflect_prompt()
+    else:  # 压缩前的反思
+        prompt = config.knowledge.get_reflect_prompt()
+```
+
+这是一个独立的 bug fix,不依赖 Memory 系统。
+
+**2. Trace 模型扩展**
+
+`agent/trace/models.py:Trace` 新增字段:
+
+```python
+reflected_at_sequence: Optional[int] = None    # 上次记忆反思的 sequence
+# 反思摘要存在 cognition_log.json 中(type="reflection" 事件),不在 Trace 模型中
+```
+
+**3. RunConfig 扩展**
+
+`agent/core/runner.py:RunConfig` 新增可选字段:
+
+```python
+memory: Optional[MemoryConfig] = None
+```
+
+### 新增的部分
+
+**1. MemoryConfig**
+
+```python
+@dataclass
+class MemoryConfig:
+    """持久化记忆配置"""
+
+    base_path: str = ""                          # 记忆文件目录
+    files: Optional[Dict[str, str]] = None       # {文件名: 用途说明}
+    dream_prompt: str = ""                       # Dream 整合 prompt(空用默认)
+    reflect_prompt: str = ""                     # Per-trace 反思 prompt(空用默认)
+```
+
+**2. Run 启动时记忆加载**
+
+Memory-bearing Agent 的 run 启动时,框架读取 `base_path` 下所有 `files` 中声明的文件,注入上下文。
+
+**3. Dream 操作**
+
+以 `dream` 工具形式提供,Agent 可主动调用:
+
+```python
+@tool
+async def dream() -> ToolResult:
+    """整理长期记忆。回顾最近的执行历史,更新记忆文件。"""
+    # 1. 扫描需要反思的 trace
+    # 2. 逐个 per-trace 反思
+    # 3. 跨 trace 整合,更新记忆文件
+```
+
+也可以作为 `AgentRunner` 的方法暴露,供外部调度直接调用。
+
+---
+
+## 六、完整的元思考数据流
+
+```
+Agent 执行任务(Trace)
+  │
+  ├─ 知识查询(ask)→ cognition_log: type="query"(含整合回答 + source_ids)
+  │
+  ├─ Goal 完成 → 触发 knowledge_eval 侧分支 → cognition_log: type="evaluation"
+  │
+  ├─ 压缩触发 →
+  │   队列: [reflection, knowledge_eval, compression]
+  │   reflection: 提取客观知识 → upload → KnowHub + cognition_log: type="extraction"
+  │   knowledge_eval: 评估各 source → cognition_log: type="evaluation"
+  │   compression: 压缩上下文
+  │
+  ├─ 任务完成 →
+  │   knowledge_eval(如有 pending)→ cognition_log: type="evaluation"
+  │   reflection → upload → KnowHub + cognition_log: type="extraction"
+  │
+  └─ Trace 状态更新(新消息使 reflected_at_sequence 落后)
+
+         ···时间流逝,可能有多个 trace···
+
+Dream 触发(Agent 主动调用 / 外部调度)
+  │
+  ├─ Per-trace 记忆反思
+  │   输入: 未反思的消息 + cognition_log 中的 query/evaluation/extraction 事件
+  │   输出: cognition_log: type="reflection"
+  │
+  ├─ 跨 trace 整合
+  │   输入: 各 trace 的 reflection 事件 + evaluation 趋势 + 当前记忆文件
+  │   输出: 更新后的记忆文件(taste.md, strategy.md, ...)
+  │
+  └─ 记忆文件被下次 run 加载 → 影响 Agent 行为 → 新的 Trace → ...
+```
+
+### 三种元思考的时间线
+
+```
+Trace 执行中:
+  ──[Goal完成]──knowledge_eval──[压缩]──reflection→knowledge_eval→compression──
+
+Trace 结束后:
+  ──knowledge_eval──reflection(completion)──
+
+之后某个时刻:
+  ──dream──per-trace记忆反思──跨trace整合──更新记忆文件──
+```
+
+即时的元思考(knowledge_eval、reflection)保护信息不被压缩丢失。
+延迟的元思考(dream)在全局视角下更新个人记忆。两者互补。
+
+---
+
+## 七、记忆模型全景
+
+```
+┌─────────────────────────────────────────────────────────────┐
+│ Layer 3: Skills(技能库)                                     │
+│ - Markdown 文件,领域知识和能力描述                            │
+└─────────────────────────────────────────────────────────────┘
+                              ▲
+                              │ 归纳
+┌─────────────────────────────────────────────────────────────┐
+│ Layer 2: Knowledge(知识库)— 全局共享                         │
+│ - KnowHub 数据库,客观知识 + 向量索引                         │
+│ - 来源:reflection 侧分支提取                                │
+│ - 质量信号:knowledge_eval 评估结果                           │
+└─────────────────────────────────────────────────────────────┘
+                              ▲
+                              │ 提取(reflection)/ 评估(knowledge_eval)
+┌─────────────────────────────────────────────────────────────┐
+│ Layer 1.5: Memory(个人记忆)— Agent 身份私有                  │
+│ - Markdown 文件,主观记忆(偏好/策略/反思)                    │
+│ - 来源:dream 操作(per-trace 反思 + 跨 trace 整合)          │
+│ - 人类可直接编辑                                              │
+└─────────────────────────────────────────────────────────────┘
+                              ▲
+                              │ dream 反思
+┌─────────────────────────────────────────────────────────────┐
+│ Layer 1: Trace(任务状态)                                    │
+│ - 当前任务的工作记忆                                          │
+│ - Messages + Goals + cognition_log                           │
+└─────────────────────────────────────────────────────────────┘
+```
+
+---
+
+## 八、两类 Agent
+
+| | 默认 Agent | Memory-bearing Agent |
+|---|---|---|
+| 知识提取(reflection) | ✅ 配置 KnowledgeConfig | ✅ 配置 KnowledgeConfig |
+| 知识评估(knowledge_eval) | ✅ 自动 | ✅ 自动 |
+| 个人记忆 | ❌ | ✅ 配置 MemoryConfig |
+| Dream | ❌ | ✅ 可调用 dream 工具 |
+| Run 启动加载记忆 | ❌ | ✅ 自动注入 |
+
+默认行为不变。Memory 是 opt-in 的增量能力。
+
+---
+
+## 九、待定问题
+
+1. **记忆注入方式**:system prompt 追加 vs 首条消息前插入 vs 作为工具结果注入?需要实验对比效果。
+2. **并发写冲突**:多个 Agent run 同时写同一个记忆文件怎么办?文件锁?还是 dream 统一写、其他 run 只读?
+3. **记忆膨胀**:记忆文件越来越长怎么办?dream prompt 应该包含精简逻辑,但需要观察实际效果。
+4. **Per-trace 反思的成本控制**:很短的 trace 不值得反思。阈值由框架设定(消息数/token数)还是让 dream 过程自己判断?
+5. **Knowledge eval 结果回传 KnowHub**:是否应该自动同步?自动回传可能影响其他 Agent 的检索。
+6. **Dream 中 knowledge_log 趋势的呈现方式**:在 dream prompt 中注入预计算的统计 vs 让 LLM 自己读原始 log?
+7. **Dream 操作的实现形式**:作为 Agent 工具(`dream()`)vs AgentRunner 方法 vs 两者都提供?

+ 71 - 198
knowhub/README.md

@@ -1,241 +1,114 @@
-# KnowHub 设计
+# KnowHub
 
 ## 文档维护规范
 
 0. **先改文档,再动代码** - 新功能或重大修改需先完成文档更新、并完成审阅后,再进行代码实现;除非改动较小、不被文档涵盖
 1. **文档分层,链接代码** - 重要或复杂设计可以另有详细文档;关键实现需标注代码文件路径;格式:`module/file.py:function_name`
-2. **简洁快照,日志分离** - 只记录最重要的、与代码准确对应的或者明确的已完成的设计的信息,避免推测、建议、决策历史、修改日志、大量代码;决策依据或修改日志若有必要,可在`docs/decisions.md`另行记录
+2. **简洁快照,日志分离** - 只记录最重要的、与代码准确对应的或者明确的已完成的设计的信息,避免推测、建议、决策历史、修改日志、大量代码;决策依据或修改日志若有必要,可在 `docs/decisions.md` 另行记录
 
 ---
 
 ## 定位
 
-Agent 集体记忆平台。收集和检索 Agent 的真实使用经验,覆盖工具、知识资源等各类资源。资源发现交给现有生态(Glama、Smithery、PyPI 等),KnowHub 专注于"用了之后怎么样"和按需积累的资源内容。
+Agent 集体记忆平台。收集和检索 Agent 的真实使用经验,覆盖工具、知识资源等各类资源。
 
 核心原则:
 1. 汇总不同 Agent 的真实使用经验(Agent 版大众点评)
-2. 端侧 Agent 负责搜索、评估、总结、提取内容;Server 只做存取和简单聚合
-
-详见 [decisions.md](docs/decisions.md) 的定位推演。
-
-### 数据类型
-
-KnowHub Server 管理两类数据:
-
-| 数据类型 | 内容 | 用途 |
-|---------|------|------|
-| **experiences** | 工具使用经验(任务+资源+结果+建议) | 工具评价、经验分享 |
-| **knowledge** | 任务知识、策略、定义 | 知识积累、检索、进化 |
-
-详见:
-- [知识管理文档](docs/knowledge-management.md) - 知识结构、API、集成方式
+2. 端侧 Agent 负责搜索、评估、总结、提取内容;Server 做存取、去重和简单聚合
 
 ---
 
 ## 架构
 
 ```
-Agent(端侧)                          KnowHub Server
-├── curl GET /api/search 查经验   →    LIKE 检索 + SQL 聚合
-├── curl GET /api/content/{id} 取内容 → SQLite 读取 + 导航计算
-├── 去外部平台找资源(fallback)
-├── 使用资源、总结经验
-├── curl POST /api/experience    →    SQLite 写入
-└── curl POST /api/content       →    SQLite 写入(按需提交内容)
+Agent(端侧)
+├── ask_knowledge 工具     →  POST /api/knowledge/ask(设计中,未实现)
+├── upload_knowledge 工具  →  POST /api/knowledge/upload(设计中,未实现)
+├── knowledge_search 工具  →  GET /api/knowledge/search(当前实现)
+├── knowledge_save 工具    →  POST /api/knowledge(当前实现)
+├── goal focus 自动注入    →  GET /api/knowledge/search(当前实现)
+└── resource 资源引用       →  GET /api/resource/{id}
+                                    │
+                              KnowHub Server(FastAPI)
+                              ├── REST API(36个端点)
+                              ├── 知识处理流水线(去重 + 工具关联分析)
+                              └── Librarian Agent(知识管理Agent,当前通过IM独立运行)
+                                    │
+                              PostgreSQL + pgvector
+                              ├── knowledge(知识表,双向量)
+                              ├── resources(资源表,加密存储)
+                              ├── tool_table(工具表)
+                              ├── atomic_capability(原子能力表)
+                              └── requirement_table(需求表)
 ```
 
-Agent 通过 curl 直接调用 REST API,无需安装客户端。skill.md 提供 API 地址和调用模板。
-
-| 职责 | 执行方 |
-|------|--------|
-| 搜索资源、评估质量、总结经验、提取内容 | Agent(端侧) |
-| 存储 experience 和 content、关键词检索、聚合分数 | Server |
-
-Server 无 LLM 调用、无 embedding、无向量数据库。
-
 ---
 
-## 数据模型
-
-### experiences
-
-一条经验 = 任务 + 资源 + 结果 + 建议。
-
-```sql
-CREATE TABLE experiences (
-    id            INTEGER PRIMARY KEY AUTOINCREMENT,
-    name          TEXT NOT NULL,           -- 资源名称
-    url           TEXT DEFAULT '',         -- 资源规范来源地址
-    category      TEXT DEFAULT '',         -- 资源类型
-    task          TEXT NOT NULL,           -- 具体任务场景
-    score         INTEGER CHECK(score BETWEEN 1 AND 5),
-    outcome       TEXT DEFAULT '',         -- 结果(含优缺点)
-    tips          TEXT DEFAULT '',         -- 最关键的建议
-    content_id    TEXT DEFAULT '',         -- 可选,关联到 contents
-    submitted_by  TEXT DEFAULT '',         -- 可选,提交者标识
-    created_at    TEXT NOT NULL
-);
-```
-
-**字段填写规范**:
-- **name** — 资源的通用名称。工具填包名(`pymupdf`),论文填标题(`Attention Is All You Need`),博客填博客名或文章标题
-- **url** — 资源的规范来源地址(GitHub repo / arXiv / 官方文档),不是随意搜索结果链接
-- **category** — 建议值:`mcp | skill | library | api | paper | blog | book | course`,自由文本
-- **content_id** — 可选,指向 contents 中的任意节点(可以是资源根,也可以是具体章节)
-- **submitted_by** — 可选,建议使用 `git config user.email` 的值
-
-**多资源协作场景**:
-一个任务常需要多个工具/资源配合(如 pymupdf + langchain + openai)。处理方式:为每个关键资源单独提交一条 experience,在 task/tips/outcome 中提及配合使用的其他资源。这样每个资源都能被搜索到和聚合,同时通过文本保留协作信息。
+## 文档索引
 
-搜索使用 LIKE 拆词匹配 task + tips + outcome + name,结果按 name 分组返回。
+### 核心设计
 
-### contents
+| 文档 | 内容 |
+|------|------|
+| [数据模型](docs/schema.md) | 5张表结构、字段定义、表间关联、向量策略 |
+| [REST API](docs/api.md) | 36个API端点的完整参考 |
+| [Librarian Agent](docs/librarian-agent.md) | 知识管理Agent:当前IM架构 + 未来HTTP ask/upload设计 |
 
-按需积累的资源内容。Agent 提交,Markdown 格式。
+### 处理机制
 
-```sql
-CREATE TABLE contents (
-    id            TEXT PRIMARY KEY,        -- 路径式 ID
-    title         TEXT DEFAULT '',
-    body          TEXT NOT NULL,           -- Markdown 格式
-    sort_order    INT DEFAULT 0,           -- 同级排序
-    submitted_by  TEXT DEFAULT '',
-    created_at    TEXT NOT NULL
-);
-```
+| 文档 | 内容 |
+|------|------|
+| [知识处理流水线](docs/processing-pipeline.md) | 去重、工具关联分析、状态流转、LLM关系判断 |
+| [Cognition Log](../agent/docs/cognition-log.md) | Agent侧的认知日志:查询/评估/提取/反思事件流(在 agent/docs/ 中) |
 
-**ID 约定**:路径式,如 `pymupdf` 或 `attention-paper/section-3-2`。`/` 分隔表示层级关系。
+### 前端与用户交互
 
-**内容层级**:扁平二级结构。
-- 根节点(ID 不含 `/`):资源概要或目录。有 children 时 body 为目录/概要,无 children 时 body 为完整内容。
-- 子节点(ID 含 `/`):具体内容段落,body 为实质内容。
+| 文档 | 内容 |
+|------|------|
+| [用户反馈设计](docs/user-feedback-design.md) | 用户反馈UI、API、数据模型 |
+| [Dashboard设计](docs/dashboard-design.md) | 知识库可视化Dashboard |
 
-Children 通过 ID 前缀查询:`WHERE id LIKE '{root_id}/%' ORDER BY sort_order`。
+### 其他
 
-**按需生长**:content 由 agent 在需要时提交。没有 content 的资源只有 experience 层。高频使用的资源自然积累出完整内容。
-
----
-
-## API
-
-基础地址通过环境变量 `KNOWHUB_API` 配置。
-
-### `GET /api/search?q=...&category=...&limit=10`
-
-搜索经验。LIKE 拆词匹配 task + tips + outcome + name,按 name 分组返回。
-
-响应示例:
-
-```json
-{
-  "results": [
-    {
-      "name": "pymupdf",
-      "url": "https://github.com/pymupdf/PyMuPDF",
-      "relevant_experiences": [
-        {"task": "从学术论文提取表格", "score": 4, "tips": "用 page.find_tables()", "content_id": ""}
-      ],
-      "avg_score": 4.5,
-      "experience_count": 2
-    }
-  ]
-}
-```
-
-### `POST /api/experience`
-
-提交经验。
-
-```json
-{
-  "name": "pymupdf",
-  "url": "https://github.com/pymupdf/PyMuPDF",
-  "category": "library",
-  "task": "从学术论文 PDF 提取结构化表格",
-  "score": 4,
-  "outcome": "速度快,标准排版准确,复杂双栏偶尔丢失顺序",
-  "tips": "用 page.find_tables(),双栏论文先 get_text(sort=True)",
-  "content_id": "",
-  "submitted_by": "user@example.com"
-}
-```
-
-### `GET /api/resource/{name}`
-
-查看某资源的所有经验及关联内容。
-
-### `GET /api/content/{content_id:path}`
-
-获取内容节点。响应自动包含导航上下文:
-
-```json
-{
-  "id": "attention-paper/section-3-2",
-  "title": "3.2 Scaled Dot-Product Attention",
-  "body": "## Scaled Dot-Product Attention\n\nAttention(Q,K,V) = softmax(QK^T / √d_k)V\n\n...",
-  "toc": {"id": "attention-paper", "title": "Attention Is All You Need"},
-  "children": [],
-  "prev": {"id": "attention-paper/section-3-1", "title": "3.1 Encoder and Decoder Stacks"},
-  "next": {"id": "attention-paper/section-3-3", "title": "3.3 Multi-Head Attention"}
-}
-```
-
-- 有 children → body 为目录/概要,children 列出子节点(id + title)
-- 无 children → body 为完整内容
-- toc / prev / next 由 server 从 ID 前缀和 sort_order 计算
-
-### `POST /api/content`
-
-提交内容节点。
-
-```json
-{
-  "id": "attention-paper/section-3-2",
-  "title": "3.2 Scaled Dot-Product Attention",
-  "body": "Markdown 内容...",
-  "sort_order": 2
-}
-```
-
----
-
-## skill.md 流程
-
-触发条件:遇到复杂任务、可能超出自身能力、多次失败、可能需要外部资源时。以及使用资源完成任务后。
-
-```
-curl GET /api/search
-  → 有可用结果 → 直接参考(经验里有资源名、URL、使用建议)
-  → 需要深入 → GET /api/content/{id} 获取详细内容
-  → 无可用结果 → 去外部平台自行寻找 → 用完后 POST /api/experience 回报
-```
-
-发现渠道(Smithery、PyPI 等)仅作为无经验时的 fallback。
-
-完整内容见 `skill/knowhub.md`。
+| 文档 | 内容 |
+|------|------|
+| [决策记录](docs/decisions.md) | 设计决策的依据和权衡 |
+| [DB层README](knowhub_db/README.md) | 数据库访问层的封装类和运维脚本 |
 
 ---
 
 ## 项目结构
 
 ```
-KnowHub/
-├── docs/
-│   ├── 
-│   ├── decisions.md       # 决策记录
-│   └── knowledge/         # 调研资料(不发布)
-├── skill/
-│   └── knowhub.md         # Agent 策略指南
-├── CLAUDE.md              # 本文档(架构快照)
-└── server.py              # FastAPI + SQLite(单文件)
+knowhub/
+├── server.py              # FastAPI Server(API + 知识处理流水线)
+├── embeddings.py          # Embedding 生成(OpenRouter)
+├── kb_manage_prompts.py   # LLM Prompt(去重判断、工具分析)
+├── agents/                # Librarian Agent(独立进程)
+├── knowhub_db/            # PostgreSQL 数据库访问层
+│   ├── pg_store.py        # knowledge 表
+│   ├── pg_resource_store.py
+│   ├── pg_tool_store.py
+│   ├── pg_capability_store.py
+│   ├── pg_requirement_store.py
+│   └── *.py               # 迁移和运维脚本
+├── frontend/              # 管理前端
+├── docs/                  # 设计文档
+└── skill/                 # Agent调用指南
 ```
 
 ---
 
-## MVP 边界
+## 环境变量
 
-**做**:经验收集与检索、按需内容积累与导航、LIKE 拆词搜索、按资源聚合、Markdown 内容、skill.md 策略指南
+```bash
+# 数据库
+KNOWHUB_DB          # PostgreSQL 主机
+KNOWHUB_PORT        # 端口(默认 5432)
+KNOWHUB_USER        # 用户名
+KNOWHUB_PASSWORD    # 密码
+KNOWHUB_DB_NAME     # 数据库名
 
-**不做**:CLI 客户端、资源目录、语义搜索/向量/embedding、用户认证、Web 界面、LLM 聚合摘要、内容层与 Resonote 整合
-
-**后续方向**:CLI 客户端(mpk 命令)、MCP Server 接入、LLM 经验摘要(Agent 端)、submitted_by 信誉权重、语义搜索(embedding)、与 Resonote 内容层桥接
+# Embedding
+OPENROUTER_API_KEY  # OpenRouter API Key(用于生成 embedding)
+```

+ 197 - 0
knowhub/docs/api.md

@@ -0,0 +1,197 @@
+# REST API 参考
+
+## 文档维护规范
+
+0. **先改文档,再动代码**
+1. **文档分层,链接代码** — 格式:`module/file.py:function_name`
+2. **简洁快照,日志分离** — 决策依据记录在 `knowhub/docs/decisions.md`
+
+---
+
+实现:`knowhub/server.py`
+
+## Knowledge API
+
+### `GET /api/knowledge/search` — 向量搜索知识
+
+参数:`q`(必填), `top_k`(默认5, 1-20), `min_score`(默认3, 1-5), `types`(逗号分隔, AND), `owner`(逗号分隔, OR)
+
+只返回 status=approved/checked 的知识。向量召回 3×top_k 候选,按余弦距离排序取 top_k。当前跳过 LLM 精排。
+
+响应:`{"results": [...], "count": int, "reranked": false}`
+
+### `POST /api/knowledge` — 创建知识
+
+请求体:task(必填), content(必填), types, tags, scopes, owner, message_id, resource_ids, source, eval, support_capability, tools
+
+自动生成 task_embedding + content_embedding。初始 status=pending,异步触发去重处理(详见 [processing-pipeline.md](processing-pipeline.md))。
+
+### `GET /api/knowledge` — 列表(分页+过滤)
+
+参数:page, page_size(默认20), types, scopes, owner, tags, status(默认 approved,checked)
+
+### `GET /api/knowledge/{knowledge_id}` — 获取单条
+
+### `PUT /api/knowledge/{knowledge_id}` — 更新(含知识进化)
+
+请求体:add_helpful_case, add_harmful_case, update_score, evolve_feedback
+
+`evolve_feedback` 非空时触发 LLM 重写知识内容并更新 task_embedding。
+
+### `PATCH /api/knowledge/{knowledge_id}` — 直接编辑字段
+
+请求体:task, content, types, tags, scopes, owner, support_capability, tools(均可选)
+
+修改 task/content 时自动更新对应 embedding。
+
+### `DELETE /api/knowledge/{knowledge_id}` — 删除
+
+### `POST /api/knowledge/batch_delete` — 批量删除
+
+请求体:`List[str]`(knowledge_ids)
+
+### `POST /api/knowledge/{knowledge_id}/verify` — 验证
+
+请求体:action("approve"/"reject"), verified_by
+
+approve 在 approved ↔ checked 之间切换。reject 设为 rejected。
+
+### `POST /api/knowledge/batch_verify` — 批量验证
+
+请求体:knowledge_ids, action(必须 "approve"), verified_by
+
+### `POST /api/knowledge/batch_update` — 批量反馈
+
+请求体:feedback_list `[{knowledge_id, is_effective, feedback?}]`
+
+is_effective=true + feedback 时触发并发 LLM 知识进化。
+
+### `POST /api/knowledge/slim` — 知识库瘦身
+
+参数:model(默认 gemini-2.5-flash-lite)
+
+LLM 识别可合并项 → 合并 → 重建 embedding。
+
+### `POST /api/extract` — 从对话提取知识
+
+请求体:messages(`[{role, content}]`), agent_id, submitted_by(必填), session_key
+
+LLM 提取结构化知识 → 批量生成 embedding → 入库(pending) → 触发去重。
+
+### `GET /api/knowledge/pending` — 处理队列
+
+返回 status 为 pending/processing/dedup_passed/analyzing 的知识。
+
+### `POST /api/knowledge/process` — 手动触发处理
+
+参数:force(重置卡住的 processing/analyzing 状态)
+
+### `GET /api/knowledge/status/{knowledge_id}` — 查看处理状态
+
+### `GET /api/knowledge/meta/tags` — 获取所有标签
+
+---
+
+## Resource API
+
+### `POST /api/resource` — 创建/更新资源
+
+请求体:id(必填, 路径格式), title, body, secure_body, content_type, metadata, sort_order, submitted_by
+
+secure_body 在有组织密钥时自动加密(AES-256-GCM)。
+
+### `GET /api/resource/{resource_id}` — 获取资源(含导航)
+
+响应包含:toc(根节点), children(子节点), prev/next(同级前后节点)。
+
+### `PATCH /api/resource/{resource_id}` — 更新字段
+
+### `GET /api/resource` — 列表
+
+参数:content_type, limit(默认100)
+
+### `DELETE /api/resource/{resource_id}` — 删除
+
+---
+
+## Tool API
+
+### `POST /api/tool` — 创建/更新工具
+
+请求体:id(必填), name, version, introduction, tutorial, input, output, status, capabilities, tool_knowledge, case_knowledge, process_knowledge, implemented_tool_ids
+
+自动生成 embedding(name + introduction)。
+
+### `GET /api/tool` — 列表
+
+参数:status, limit(默认100), offset
+
+### `GET /api/tool/search` — 向量搜索工具
+
+参数:q(必填), top_k(默认5), status
+
+### `GET /api/tool/{tool_id}` — 获取单个
+
+### `PATCH /api/tool/{tool_id}` — 更新字段
+
+### `DELETE /api/tool/{tool_id}` — 删除
+
+---
+
+## Capability API
+
+### `POST /api/capability` — 创建/更新原子能力
+
+请求体:id(必填), name, criterion, description, requirements, implements, tools, source_knowledge
+
+自动生成 embedding(name + description)。
+
+### `GET /api/capability` — 列表
+
+参数:limit(默认100), offset
+
+### `GET /api/capability/search` — 向量搜索能力
+
+参数:q(必填), top_k(默认5)
+
+### `GET /api/capability/{cap_id}` — 获取单个
+
+### `PATCH /api/capability/{cap_id}` — 更新字段
+
+### `DELETE /api/capability/{cap_id}` — 删除
+
+---
+
+## Requirement API
+
+### `POST /api/requirement` — 创建/更新需求
+
+请求体:id(必填), description, atomics, source_nodes, status(默认 "未满足"), match_result
+
+自动生成 embedding(description)。
+
+### `GET /api/requirement` — 列表
+
+参数:status, limit(默认100), offset
+
+### `GET /api/requirement/search` — 向量搜索需求
+
+参数:q(必填), top_k(默认5)
+
+### `GET /api/requirement/{req_id}` — 获取单个
+
+### `PATCH /api/requirement/{req_id}` — 更新字段
+
+### `DELETE /api/requirement/{req_id}` — 删除
+
+---
+
+## 计划中的 API(设计中,未实现)
+
+### `POST /api/knowledge/ask` — 智能知识查询
+
+同步阻塞。KnowHub 内部启动/续跑 Librarian Agent 处理查询,返回整合回答 + source_ids。详见 [librarian-agent.md](librarian-agent.md)。
+
+### `POST /api/knowledge/upload` — 异步知识上传
+
+校验格式后立即返回 202,Librarian Agent 后台队列处理。详见 [librarian-agent.md](librarian-agent.md)。

+ 0 - 0
knowhub/agents/README.md → knowhub/docs/archive/agents-readme.md


+ 0 - 0
knowhub/docs/dedup-design.md → knowhub/docs/archive/dedup-design.md


+ 103 - 53
knowhub/docs/knowledge-management.md → knowhub/docs/archive/knowledge-management.md

@@ -17,13 +17,20 @@ KnowHub Server 是统一的知识管理服务,包含两个子系统:
 
 ```
 Agent                           KnowHub Server
-├── knowledge_search 工具   →   GET /api/knowledge/search
-├── knowledge_save 工具     →   POST /api/knowledge
+├── ask_knowledge 工具      →   POST /api/knowledge/ask(同步,KM Agent 整合后返回)
+├── upload_knowledge 工具   →   POST /api/knowledge/upload(异步,校验后立即返回,队列处理)
 ├── knowledge_update 工具   →   PUT /api/knowledge/{id}
-├── goal focus 自动注入     →   GET /api/knowledge/search
+├── goal focus 自动注入     →   POST /api/knowledge/ask
 └── resource 资源引用        →   GET /api/resource/{id}
 ```
 
+### Knowledge Manager Agent
+
+KnowHub 内部运行 Knowledge Manager (KM) Agent,负责知识的智能检索整合和上传处理。KM Agent 不再通过 IM 通信,而是作为 KnowHub 的内部实现:
+
+- **ask 请求**:KnowHub 收到 ask 请求后,用调用方的 `trace_id` 查找或创建对应的 KM Agent trace。同一 `trace_id` 的多次 ask 复用同一个 KM Agent(resume trace),使 KM Agent 积累对调用方任务的理解。KM Agent 检索知识库、用 LLM 整合后返回结果。
+- **upload 请求**:KnowHub 校验格式后立即返回,将请求放入消息队列。KM Agent 后台处理去重、整合、入库。
+
 ### 存储架构
 
 KnowHub 采用 Milvus Lite 单一存储架构(详见 `knowhub/docs/decisions.md#13`):
@@ -173,48 +180,45 @@ KnowHub 采用 Milvus Lite 单一存储架构(详见 `knowhub/docs/decisions.m
 
 Agent 通过以下工具与 KnowHub Server 交互。工具只是 API 调用的封装,核心逻辑在 Server 实现。
 
-实现位置:`agent/tools/builtin/knowledge.py`
+实现位置:`agent/tools/builtin/knowledge.py`(待迁移到新 API)
 
-### `knowledge_search`
+### `ask_knowledge`
 
-检索知识
+查询知识,返回 KM Agent 整合后的回答。同步阻塞,调用方等待结果返回后继续
 
 ```python
 @tool()
-async def knowledge_search(
+async def ask_knowledge(
     query: str,
+    trace_id: str,       # 调用方的 trace_id,用于 KM Agent 续跑
     top_k: int = 5,
-    min_score: int = 3,
-    types: Optional[List[str]] = None
 ) -> ToolResult
 ```
 
-调用 `GET /api/knowledge/search?q={query}&top_k={top_k}&min_score={min_score}&types={types}`
+调用 `POST /api/knowledge/ask`
 
-### `knowledge_save`
+返回:整合回答 + source_ids 列表 + 各 source 的原始内容摘要。
 
-保存新知识。
+### `upload_knowledge`
+
+上传知识到知识库。异步,校验格式后立即返回。
 
 ```python
 @tool()
-async def knowledge_save(
-    task: str,
-    content: str,
-    types: List[str],
-    tags: Optional[Dict[str, str]] = None,
-    scopes: Optional[List[str]] = None,
-    owner: Optional[str] = None,
-    source_name: str = "",
-    source_category: str = "exp",
-    urls: List[str] = None,
-    agent_id: str = "research_agent",
-    submitted_by: str = "",
-    score: int = 3,
-    message_id: str = ""
+async def upload_knowledge(
+    data: Dict[str, Any],
+    trace_id: str,       # 调用方的 trace_id
+    finalize: bool = False,
 ) -> ToolResult
 ```
 
-调用 `POST /api/knowledge`
+调用 `POST /api/knowledge/upload`
+
+### 废弃工具
+
+以下工具已废弃,由上述两个工具替代:
+- `knowledge_search` → `ask_knowledge`
+- `knowledge_save` → `upload_knowledge`
 
 **默认值**(在 agent 代码中设置):
 - `scopes`: `["org:cybertogether"]`
@@ -405,30 +409,19 @@ Knowledge 可以通过 `resource_id` 和 `secure_resource_id` 引用 Resource 
 
 ### 注入流程
 
-```python
-# 1. LLM 调用 goal 工具
-goal(action="focus", goal_id="goal-123")
-
-# 2. goal 工具内部自动执行
-current_goal = goal_tree.find("goal-123")
-knowledge_results = await knowledge_search(
-    query=current_goal.description,
-    top_k=3,
-    min_score=3
-)
-
-# 3. 保存到 goal 对象
-current_goal.knowledge = knowledge_results.metadata["items"]
-
-# 4. 持久化到 trace store
-await trace_store.update_goal_tree(trace_id, goal_tree)
-
-# 5. 返回给 LLM
-return ToolResult(
-    title="✅ Goal 已聚焦",
-    output=f"当前 Goal: {current_goal.description}\n\n📚 相关知识 ({len(knowledge_results)} 条):\n..."
-)
 ```
+1. LLM 调用 goal(action="focus", goal_id="goal-123")
+2. goal 工具内部调用 POST /api/knowledge/ask
+   - query = goal.description
+   - trace_id = 调用方的 trace_id(KM Agent 续跑,积累任务理解)
+3. KM Agent 返回整合回答 + source_ids
+4. 保存到 goal.knowledge + 写入 cognition_log
+5. 返回给 LLM
+```
+
+### Cognition Log 记录
+
+每次注入产生一个 `query` 事件,记录完整的问答对(详见 `knowhub/docs/feedback-timing-design.md`)。
 
 ### 知识展示
 
@@ -481,9 +474,65 @@ return ToolResult(
 
 ## KnowHub Server API
 
+### `POST /api/knowledge/ask`
+
+> 状态:设计中,未实现
+
+智能知识查询。KnowHub 内部启动/续跑 KM Agent 处理查询,返回整合回答。同步阻塞。
+
+**请求体**:
+
+```json
+{
+  "query": "ControlNet 相关的工具知识",
+  "trace_id": "caller-trace-xxx",
+  "top_k": 5
+}
+```
+
+**行为**:
+- `trace_id` 首次出现 → 创建新的 KM Agent trace
+- `trace_id` 已存在 → resume 之前的 KM Agent trace(保持上下文连续性)
+- KM Agent 检索知识库 → LLM 整合 → 返回结果
+
+**响应**:
+
+```json
+{
+  "response": "KM Agent 整合后的回答文本...",
+  "source_ids": ["knowledge-xxx", "knowledge-yyy"],
+  "sources": [
+    {"id": "knowledge-xxx", "task": "...", "content": "...(截断500字)"},
+    {"id": "knowledge-yyy", "task": "...", "content": "..."}
+  ]
+}
+```
+
+### `POST /api/knowledge/upload`
+
+> 状态:设计中,未实现
+
+异步知识上传。校验格式后立即返回 202,KM Agent 后台队列处理。
+
+**请求体**:
+
+```json
+{
+  "data": {
+    "knowledge": [...],
+    "resources": [...],
+    "tools": [...]
+  },
+  "trace_id": "caller-trace-xxx",
+  "finalize": false
+}
+```
+
+**响应**:`202 Accepted`
+
 ### `GET /api/knowledge/search`
 
-检索知识。使用向量召回 + LLM 精排策略。
+检索知识。使用向量召回 + LLM 精排策略。直接返回原始结果,不经过 KM Agent 整合。
 
 **参数**:
 - `q`: 查询文本
@@ -648,11 +697,12 @@ return ToolResult(
 | 组件 | 实现位置 |
 |------|---------|
 | KnowHub Server | `knowhub/server.py` |
-| Agent 工具 | `agent/tools/builtin/knowledge.py` |
+| KM Agent | `knowhub/agents/knowledge_manager.py` |
+| Agent 工具 | `agent/tools/builtin/knowledge.py`(待迁移到新 ask/upload API) |
 | goal 工具(知识注入) | `agent/trace/goal_tool.py:focus_goal` |
 | 调研 skill | `agent/skill/skills/research.md` |
 | 去重机制 | `knowhub/server.py:KnowledgeProcessor` → 详见 `dedup-design.md` |
-| 反馈时机 | `agent/trace/store.py`, `agent/core/runner.py` → 详见 `feedback-timing-design.md` |
+| Cognition Log | `agent/trace/store.py` → 详见 `feedback-timing-design.md` |
 
 ---
 

+ 0 - 0
knowhub/docs/migration-guide.md → knowhub/docs/archive/migration-guide.md


+ 0 - 0
knowhub/docs/resource-storage.md → knowhub/docs/archive/resource-storage.md


+ 0 - 269
knowhub/docs/feedback-timing-design.md

@@ -1,269 +0,0 @@
-# 知识反馈时机设计文档
-
-## 文档维护规范
-
-0. **先改文档,再动代码** - 新功能或重大修改需先完成文档更新、并完成审阅后,再进行代码实现;除非改动较小、不被文档涵盖
-1. **文档分层,链接代码** - 重要或复杂设计可以另有详细文档;关键实现需标注代码文件路径;格式:`module/file.py:function_name`
-2. **简洁快照,日志分离** - 只记录最重要的、与代码准确对应的或者明确的已完成的设计的信息,避免推测、建议、决策历史、修改日志、大量代码;决策依据或修改日志若有必要,可在 `knowhub/docs/decisions.md` 另行记录
-
----
-
-## 背景
-
-### 现有反馈机制的缺陷
-
-当前的知识反馈存在以下问题(来自 `feedback-optimization-proposal.md`):
-
-- **反馈时机不明确**:没有明确定义何时、由谁来评估知识的有效性
-- **缺少使用状态追踪**:知识被注入后,无法知道它是否真的被用到了
-- **评估粒度粗糙**:只有 helpful/harmful 计数,缺少"为什么有用/无用"的上下文
-
-### 设计目标
-
-1. 记录每条知识的完整生命周期(注入 → 使用 → 评估)
-2. 在自然的执行节点(Goal 完成、压缩、任务结束)触发评估,不打断主流程
-3. 为后续上报 KnowHub 提供结构化的评估数据
-
----
-
-## 核心概念
-
-### Knowledge Log(知识注入日志)
-
-每个 trace 维护一个 `knowledge_log.json`,记录该 trace 中所有被注入的知识及其评估状态。
-
-**位置**:`.trace/{trace_id}/knowledge_log.json`
-
-**数据结构**:
-
-```json
-{
-  "trace_id": "trace-xxx",
-  "entries": [
-    {
-      "knowledge_id": "knowledge-20260305-a1b2",
-      "goal_id": "1",
-      "injected_at_sequence": 42,
-      "injected_at": "2026-03-20T10:00:00.000000",
-      "task": "知识的原始task描述",
-      "content": "知识内容摘要(截断至500字符)",
-      "eval_result": {
-        "eval_status": "helpful",
-        "reason": "评估理由"
-      },
-      "evaluated_at": "2026-03-20T10:05:00.000000",
-      "evaluated_at_trigger": "goal_completion"
-    }
-  ]
-}
-```
-
-**字段说明**:
-
-| 字段 | 类型 | 说明 |
-|---|---|---|
-| `knowledge_id` | string | KnowHub 中的知识 ID |
-| `goal_id` | string | 注入时的 Goal ID(如 `"1"`, `"2.1"`) |
-| `injected_at_sequence` | int | 注入时的消息序列号 |
-| `injected_at` | datetime | 注入时间(ISO 格式,含毫秒) |
-| `task` | string | 知识的原始 task 描述 |
-| `content` | string | 知识内容(写入时截断至 500 字符) |
-| `eval_result` | object/null | 评估结果对象;未评估时为 `null` |
-| `evaluated_at` | datetime/null | 评估时间;未评估时为 `null` |
-| `evaluated_at_trigger` | string/null | 触发评估的事件(见下表);未评估时为 `null` |
-
-**`evaluated_at_trigger` 可能的值**:
-
-| 值 | 含义 |
-|---|---|
-| `"goal_completion"` | 由 Goal 完成(`completed` 或 `abandoned`)触发 |
-| `"compression"` | 由上下文压缩触发(压缩前必须先评估) |
-| `"task_completion"` | 由任务自然结束触发(主路径无工具调用退出时兜底) |
-
-> 注意:同一个 `knowledge_id` 可能在不同 Goal 中被多次注入,每次产生独立 entry。评估时优先更新最近注入(`injected_at_sequence` 最大)的未评估条目。
-
----
-
-## 评估触发机制
-
-### 触发点 1:Goal 完成
-
-**时机**:Goal status 变为 `completed` 或 `abandoned`
-
-**触发逻辑**(`agent/trace/store.py:update_goal`):
-
-```
-Goal 完成
-  ↓
-查询 knowledge_log 中 eval_result == null 的条目
-  ↓
-如果有待评估条目
-  → 在 trace.context 中设置标志:
-      pending_knowledge_eval = true
-      knowledge_eval_trigger = "goal_completion"
-  ↓
-Runner 主循环下一次迭代开头检测到标志(agent/core/runner.py:_agent_loop)
-  → 清除标志
-  → 将 "knowledge_eval" 加入 force_side_branch 队列
-```
-
-### 触发点 2:压缩(Compression)
-
-**时机**:上下文 token 数超过阈值,即将执行压缩
-
-**触发逻辑**(`agent/core/runner.py:_manage_context_usage`):
-
-```
-压缩条件触发
-  ↓
-查询 knowledge_log 中 eval_result == null 的条目
-  ↓
-如果有待评估条目
-  → 在 trace.context 中设置:
-      knowledge_eval_trigger = "compression"
-  → 将侧分支队列设为:
-      ["reflection", "knowledge_eval", "compression"](启用知识提取时)
-      ["knowledge_eval", "compression"](未启用知识提取时)
-  → 返回"需要进入侧分支"信号,暂缓压缩
-  ↓
-依次执行侧分支队列后再压缩
-```
-
-**原因**:压缩会删除消息历史,必须在压缩前完成评估,否则执行上下文永久丢失。
-
-### 触发点 3:任务结束(兜底)
-
-**时机**:主路径出现无工具调用的回复,Agent 即将结束任务
-
-**触发逻辑**(`agent/core/runner.py:_agent_loop`,无工具调用分支):
-
-```
-主路径无工具调用(任务即将结束)
-  ↓
-查询 knowledge_log 中 eval_result == null 的条目
-  ↓
-如果有待评估条目
-  → 在 trace.context 中设置:
-      knowledge_eval_trigger = "task_completion"
-  → 将 ["knowledge_eval"] 加入 force_side_branch 队列
-  → continue(不 break,下一轮执行评估侧分支)
-  ↓
-评估完成后再退出
-```
-
----
-
-## 评估分类(eval_status)
-
-| 状态 | 含义 |
-|---|---|
-| `irrelevant` | 知识的 task 与当前任务无关 |
-| `unused` | 知识与任务相关,但执行过程中没有被使用 |
-| `helpful` | 知识对当前任务有实质帮助 |
-| `harmful` | 知识对当前任务产生了负面作用 |
-| `neutral` | 知识与任务相关但无明显影响 |
-
----
-
-## 侧分支评估流程
-
-### 侧分支类型
-
-复用现有 `SideBranchContext` 机制,新增 `"knowledge_eval"` 类型(`agent/trace/models.py:Message.branch_type`):
-
-```python
-SideBranchContext(
-    type="knowledge_eval",
-    branch_id=f"knowledge_eval_{uuid.uuid4().hex[:8]}",  # 如 "knowledge_eval_1c5fffaf"
-    max_turns=config.side_branch_max_turns               # 默认 5
-)
-```
-
-`trigger_event` 记录在 `trace.context["active_side_branch"]["trigger_event"]` 中,侧分支退出后写入 `evaluated_at_trigger`。
-
-### 评估 Prompt 结构
-
-完整实现见 `agent/core/runner.py:_build_knowledge_eval_prompt`,结构如下:
-
-```
-你是知识评估助手。请评估以下知识在本次任务执行中的实际效果。
-
-## 当前任务(Mission)       ← trace.task
-## 当前 Goal                ← goal_tree.current 的 description
-## 待评估知识列表            ← 所有 eval_result == null 的条目
-  - knowledge_id / task / content / injected_at_sequence / goal_id
-## 评估维度                  ← helpfulness + relevance
-## 评估分类                  ← 5 个 eval_status 选项
-## 输出格式                  ← JSON
-```
-
-> Prompt 中**不包含消息历史**。LLM 依据对话上下文中已有的执行过程作出判断。
-
-### 评估输出格式
-
-LLM 直接输出 JSON,**无需调用工具**:
-
-```json
-{
-  "evaluations": [
-    {
-      "knowledge_id": "knowledge-20260305-a1b2",
-      "eval_status": "helpful",
-      "reason": "1-2句评估理由"
-    }
-  ]
-}
-```
-
-### 即时写入机制(`agent/core/runner.py:_agent_loop`)
-
-每次 LLM 回复后立即尝试解析,三种策略依次降级:整体解析 → ` ```json ` 代码块 → 正则裸对象。
-
-```
-LLM 输出评估 JSON
-  ↓
-解析成功 → 立即调用 store.update_knowledge_evaluation() 写入每条评估结果
-  ↓
-侧分支达到退出条件(无工具调用 或 超过 max_turns)→ 恢复主路径
-```
-
-解析失败时记录日志,不中断主流程。
-
----
-
-## 数据流
-
-```
-知识注入(agent/trace/goal_tool.py:inject_knowledge_for_goal)
-  ↓
-写入 knowledge_log.json(eval_result=null)
-  ↓
-  ┌─────────────────────────────────────────────┐
-  │  触发点 A:Goal 完成(goal_completion)       │
-  │  触发点 B:压缩执行前(compression)          │
-  │  触发点 C:任务自然结束(task_completion)    │
-  └─────────────────────────────────────────────┘
-  ↓
-Runner 进入 knowledge_eval 侧分支
-  ↓
-LLM 直接输出 JSON 评估结果(无工具调用)
-  ↓
-Runner 每轮即时解析并写入 knowledge_log.json
-  ↓
-侧分支退出 → 恢复主路径
-```
-
----
-
-## 与现有系统的集成点
-
-| 集成位置 | 文件 | 说明 |
-|---|---|---|
-| 知识注入时写 log | `agent/trace/goal_tool.py:inject_knowledge_for_goal` | `goal(focus=...)` 触发知识搜索后写入 `knowledge_log.json` |
-| Goal 完成时设置标志 | `agent/trace/store.py:update_goal` | 设置 `trace.context["pending_knowledge_eval"]` 标志 |
-| 主循环检测 Goal 完成标志 | `agent/core/runner.py:_agent_loop` | 每轮迭代开头检测标志,触发 `["knowledge_eval"]` 侧分支 |
-| 压缩前触发评估 | `agent/core/runner.py:_manage_context_usage` | 压缩前检查 pending,先评估再压缩 |
-| 任务结束兜底 | `agent/core/runner.py:_agent_loop` | 任务退出前检查 pending,强制触发评估 |
-| 侧分支类型扩展 | `agent/trace/models.py:Message.branch_type` | Literal 中包含 `"knowledge_eval"` |
-| 即时写入评估结果 | `agent/core/runner.py:_agent_loop` | 存储 assistant 消息后即时解析 JSON 并写入 |
-| Log 文件管理 | `agent/trace/store.py` | `append_knowledge_entry` / `update_knowledge_evaluation` / `get_pending_knowledge_entries` |

+ 0 - 0
knowhub/knowhub_db/plan.md → knowhub/docs/frontend-restructure-plan.md


+ 152 - 0
knowhub/docs/librarian-agent.md

@@ -0,0 +1,152 @@
+# Librarian Agent
+
+## 文档维护规范
+
+0. **先改文档,再动代码**
+1. **文档分层,链接代码** — 格式:`module/file.py:function_name`
+2. **简洁快照,日志分离** — 决策依据记录在 `knowhub/docs/decisions.md`
+
+---
+
+## 定位
+
+Librarian Agent(原 Knowledge Manager Agent)是 KnowHub 的智能层,负责:
+- 知识查询的整合回答(将散点搜索结果用 LLM 整合为带引用的回答)
+- 知识上传的去重和处理
+- 工具与知识的关联分析
+
+---
+
+## 当前实现:独立进程 + IM 通信
+
+实现:`knowhub/agents/knowledge_manager.py`
+
+### 架构
+
+```
+Agent(端侧)
+  ↓ ask_knowledge / upload_knowledge 工具
+  ↓ IM 消息(WebSocket,[ASK]/[UPLOAD] 前缀)
+IM Server(WebSocket 中继)
+  ↓
+Librarian Agent(独立进程,监听 contact_id="knowledge_manager")
+  ↓ 调用 KnowHub HTTP API
+KnowHub Server
+```
+
+### 启动方式
+
+通过 `start_knowledge_manager()` 启动为异步后台任务,或直接运行 `knowledge_manager.py`。需要 IM Client 连接。
+
+### 消息协议
+
+- `[ASK] {query}` → Librarian Agent 检索知识库 → LLM 整合 → 返回文本回答
+- `[UPLOAD] {json}` → 缓冲,5秒合并多次上传
+- `[UPLOAD:FINALIZE] {json}` → 最终提交入库
+
+### Agent 侧工具
+
+- `ask_knowledge`(`agent/tools/builtin/knowledge_manager.py`):发送 [ASK],同步等待回复(最多30秒),超时降级为直接 `knowledge_search`
+- `upload_knowledge`(`agent/tools/builtin/knowledge_manager.py`):发送 [UPLOAD],异步不等待
+
+### 局限
+
+- 依赖 IM 基础设施(WebSocket Server + Client 初始化)
+- 部署复杂(3个服务)
+- 测试困难(无法简单 HTTP 调用)
+- 超时降级时丢失整合能力
+
+---
+
+## 计划重构:HTTP API + 内部 Agent
+
+> 状态:设计中,未实现
+
+### 目标
+
+去掉 IM 依赖,将 Librarian Agent 作为 KnowHub Server 的内部实现,通过 HTTP API 暴露。
+
+### 新架构
+
+```
+Agent(端侧)
+  ↓ ask_knowledge / upload_knowledge 工具(HTTP 调用)
+KnowHub Server
+  ├── POST /api/knowledge/ask(同步阻塞)
+  │   → 查找/创建 Librarian Agent trace(by caller trace_id)
+  │   → Librarian Agent 检索 + LLM 整合
+  │   → 返回整合回答 + source_ids
+  │
+  └── POST /api/knowledge/upload(异步队列)
+      → 校验格式 → 立即返回 202
+      → 消息队列 → Librarian Agent 后台处理
+```
+
+### ask 接口
+
+```
+POST /api/knowledge/ask
+{
+  "query": "ControlNet 相关的工具知识",
+  "trace_id": "caller-trace-xxx",
+  "top_k": 5
+}
+```
+
+- `trace_id` 用于 Librarian Agent 续跑:同一 trace_id 复用同一个 Agent trace,积累对调用方任务的理解
+- 同步阻塞,调用方等待结果返回后继续执行(逻辑上要求必须复用已有知识)
+
+响应:
+
+```json
+{
+  "response": "整合后的回答文本...",
+  "source_ids": ["knowledge-xxx", "knowledge-yyy"],
+  "sources": [
+    {"id": "knowledge-xxx", "task": "...", "content": "...(截断500字)"}
+  ]
+}
+```
+
+### upload 接口
+
+```
+POST /api/knowledge/upload
+{
+  "data": {"knowledge": [...], "resources": [...], "tools": [...]},
+  "trace_id": "caller-trace-xxx",
+  "finalize": false
+}
+```
+
+立即返回 202 Accepted,后台队列处理。
+
+### Agent 侧改动
+
+`ask_knowledge` 工具从 IM 改为 HTTP:
+
+```python
+@tool
+async def ask_knowledge(query: str, context: ToolContext) -> ToolResult:
+    response = await httpx.post(f"{KNOWHUB_API}/api/knowledge/ask", json={
+        "query": query,
+        "trace_id": context.trace_id,
+    })
+    result = response.json()
+    return ToolResult(
+        output=result["response"],
+        metadata={"source_ids": result["source_ids"], "sources": result["sources"]}
+    )
+```
+
+`inject_knowledge_for_goal` 切换到 ask 接口,记录完整的 query 事件到 cognition_log(详见 [cognition-log.md](cognition-log.md))。
+
+---
+
+## 与 Cognition Log 的关系
+
+ask 接口的每次调用在 Agent 侧产生一个 `query` 事件,记录查询、整合回答和 source_ids。后续评估以 query 为单位,逐 source 评估。详见 [cognition-log.md](cognition-log.md)。
+
+## 与知识处理流水线的关系
+
+upload 提交的知识进入处理流水线(去重、工具关联分析)。当前这部分逻辑在 `server.py:KnowledgeProcessor` 中。详见 [processing-pipeline.md](processing-pipeline.md)。

+ 112 - 0
knowhub/docs/processing-pipeline.md

@@ -0,0 +1,112 @@
+# 知识处理流水线
+
+## 文档维护规范
+
+0. **先改文档,再动代码**
+1. **文档分层,链接代码** — 格式:`module/file.py:function_name`
+2. **简洁快照,日志分离** — 决策依据记录在 `knowhub/docs/decisions.md`
+
+---
+
+## 概述
+
+知识通过 `POST /api/knowledge` 提交后,经过自动化处理流水线完成去重和工具关联分析,最终变为可检索的知识。
+
+实现:`knowhub/server.py:KnowledgeProcessor`
+
+---
+
+## 状态流转
+
+```
+pending → processing → dedup_passed → analyzing → approved
+                ↓                         ↓
+             rejected                  approved
+                                      (跳过分析)
+```
+
+| 状态 | 含义 |
+|---|---|
+| `pending` | 等待处理 |
+| `processing` | 去重判断中(乐观锁,超时自动重置) |
+| `dedup_passed` | 去重通过,等待工具关联分析 |
+| `analyzing` | 工具关联分析中 |
+| `approved` | 通过,可被检索 |
+| `rejected` | 被判定为重复(duplicate/subset) |
+| `checked` | 人工已验证(approved ↔ checked 切换) |
+
+---
+
+## 阶段一:去重判断
+
+实现:`knowhub/server.py:KnowledgeProcessor._process_one`
+
+```
+新知识(status=pending)
+  ↓
+复用入库时已生成的 embedding(不重复调用)
+  ↓
+向量召回 top-10 相似知识(filter: approved/checked)
+  ↓
+相似度预过滤(阈值 0.75)
+  ↓ 无候选 → 直接 dedup_passed
+LLM 关系判断(见下文)
+  ↓
+final_decision=rejected → 旧知识 helpful+1
+final_decision=approved → 双向写入 relationships → dedup_passed
+```
+
+### LLM 关系判断
+
+使用 `google/gemini-2.5-flash-lite` 判断新知识与候选的关系。
+
+**关系类型**(开放,LLM 可自定义):
+
+| 类型 | 含义 | 处理 |
+|---|---|---|
+| `duplicate` | task 和 content 语义完全相同 | rejected,旧知识 helpful+1 |
+| `subset` | 新知识信息被旧知识覆盖 | rejected |
+| `superset` | 新知识比旧知识更全面 | 两条都 approved |
+| `conflict` | 同一 task 下结论矛盾 | 两条都 approved |
+| `complement` | 同一 task 的不同角度 | 两条都 approved |
+| `none` | task 语义不同或无实质关系 | approved,不写关系 |
+
+关系双向写入:A superset B 时,A 记录 `{type: "superset", target: "B"}`,B 记录 `{type: "subset", target: "A"}`。
+
+Prompt 实现:`knowhub/kb_manage_prompts.py`
+
+---
+
+## 阶段二:工具关联分析
+
+实现:`knowhub/server.py:KnowledgeProcessor._analyze_tool_relation`
+
+```
+dedup_passed 的知识
+  ↓
+LLM 分析知识内容 → 识别提及的工具
+  ↓
+匹配 tool_table 中的已有工具
+  ↓
+更新 knowledge.tools[] 和 tool_table.*_knowledge[] 双向关联
+  ↓
+status → approved
+```
+
+使用 `qwen3.5-plus` 模型分析。
+
+---
+
+## 并发控制
+
+- `process_pending()` 使用 asyncio.Lock 防止并发执行
+- 乐观锁:processing 状态通过 updated_at 时间戳锁定,超时(60秒)自动重置为 pending
+- `POST /api/knowledge/process?force=true` 可强制重置卡住的状态
+
+---
+
+## 触发时机
+
+- `POST /api/knowledge` 成功后自动触发(异步后台任务)
+- `POST /api/extract` 成功后自动触发
+- `POST /api/knowledge/process` 手动触发

+ 163 - 0
knowhub/docs/schema.md

@@ -0,0 +1,163 @@
+# 数据模型
+
+## 文档维护规范
+
+0. **先改文档,再动代码** - 新功能或重大修改需先完成文档更新、并完成审阅后,再进行代码实现;除非改动较小、不被文档涵盖
+1. **文档分层,链接代码** - 重要或复杂设计可以另有详细文档;关键实现需标注代码文件路径;格式:`module/file.py:function_name`
+2. **简洁快照,日志分离** - 只记录最重要的、与代码准确对应的或者明确的已完成的设计的信息,避免推测、建议、决策历史、修改日志、大量代码;决策依据或修改日志若有必要,可在 `knowhub/docs/decisions.md` 另行记录
+
+---
+
+## 存储架构
+
+PostgreSQL + pgvector 扩展。所有向量字段为 float4[](1536维),使用余弦距离(`<=>`)检索。
+
+Embedding 模型:`google/gemini-2.5-flash-lite`(通过 OpenRouter)。实现:`knowhub/embeddings.py`。
+
+---
+
+## 表间关系
+
+以 atomic_capability 为中心,连接知识、工具和需求:
+
+```
+                     knowledge(知识表)
+                    ╱         ╲
+        support_capability    tools
+               ╱                ╲
+  atomic_capability  ←────→  tool_table
+    (原子能力表)              (工具表)
+         |                       |
+    requirements            capabilities
+         ↓                       ↓
+  requirement_table ←──────→ atomic_capability
+     (需求表)
+```
+
+所有关联为应用层软关联(JSONB 字段存储 ID 列表/映射),不使用数据库外键。核心关联均双向索引。
+
+---
+
+## knowledge — 知识表
+
+实现:`knowhub_db/pg_store.py:PostgreSQLStore`
+
+| 字段 | 类型 | 说明 |
+|------|------|------|
+| `id` | VARCHAR PK | `"knowledge-{timestamp}-{random}"` |
+| `task_embedding` | float4[] | task 的向量 |
+| `content_embedding` | float4[] | content 的向量 |
+| `message_id` | VARCHAR | 来源 Agent 消息 ID |
+| `task` | VARCHAR | 任务场景描述 |
+| `content` | TEXT | 知识正文 |
+| `types` | ARRAY | 知识类型(多选):工序/用例/工具/经验/定义/User Profile |
+| `tags` | JSONB | 标签键值对 |
+| `tag_keys` | ARRAY | tags 中的键列表(用于过滤) |
+| `scopes` | ARRAY | 作用域,如 `["org:cybertogether"]` |
+| `owner` | VARCHAR | 所有者 |
+| `resource_ids` | ARRAY | 关联的 resource ID 列表 |
+| `source` | JSONB | 来源信息(agent_id, category, urls, submitted_by, timestamp) |
+| `eval` | JSONB | 评估(score, helpful, harmful, confidence, helpful_history, harmful_history) |
+| `created_at` | BIGINT | 创建时间戳(秒) |
+| `updated_at` | BIGINT | 更新时间戳(秒) |
+| `status` | VARCHAR | pending → processing → dedup_passed → analyzing → approved/rejected/checked |
+| `relationships` | JSONB | 与其他知识的关系列表 `[{type, target}]` |
+| `support_capability` | JSONB | 支撑的原子能力 ID 列表 → `atomic_capability.id` |
+| `tools` | JSONB | 关联的工具 ID 列表 → `tool_table.id` |
+
+索引:`knowledge_pkey (id)`、`idx_knowledge_owner`、`idx_knowledge_status`
+
+---
+
+## resources — 资源表
+
+实现:`knowhub_db/pg_resource_store.py:PostgreSQLResourceStore`
+
+| 字段 | 类型 | 说明 |
+|------|------|------|
+| `id` | TEXT PK | 路径格式,如 `"tools/selenium/login"` |
+| `title` | TEXT | 标题 |
+| `body` | TEXT | 公开内容(Markdown/代码) |
+| `secure_body` | TEXT | 敏感内容(AES-256-GCM 加密) |
+| `content_type` | TEXT | text / code / credential / cookie |
+| `metadata` | JSONB | 附加元数据(language, acquired_at, expires_at) |
+| `sort_order` | INTEGER | 同级排序 |
+| `submitted_by` | TEXT | 提交者 |
+| `created_at` | BIGINT | 创建时间戳 |
+| `updated_at` | BIGINT | 更新时间戳 |
+
+路径格式 ID 支持层级导航:根节点(无 `/`)为目录/概要,子节点(含 `/`)为具体内容。API 返回时自动计算 toc/children/prev/next 导航上下文。
+
+加密:`secure_body` 使用 AES-256-GCM,密钥从环境变量 `ORG_KEY_{org}` 读取。加密格式:`encrypted:AES256-GCM:{base64}`。
+
+---
+
+## tool_table — 工具表
+
+实现:`knowhub_db/pg_tool_store.py:PostgreSQLToolStore`
+
+| 字段 | 类型 | 说明 |
+|------|------|------|
+| `id` | VARCHAR PK | 路径格式,如 `"tools/image_gen/midjourney"` |
+| `name` | VARCHAR | 工具名称 |
+| `version` | VARCHAR | 版本号 |
+| `introduction` | TEXT | 功能介绍 |
+| `tutorial` | TEXT | 使用指南 |
+| `input` | JSONB | 输入规格 |
+| `output` | JSONB | 输出规格 |
+| `updated_time` | BIGINT | 更新时间戳 |
+| `status` | VARCHAR | 未接入 / 可用 / 异常 |
+| `capabilities` | JSONB | 关联的原子能力 ID 列表 → `atomic_capability.id` |
+| `tool_knowledge` | JSONB | 工具知识 ID 列表 → `knowledge.id` |
+| `case_knowledge` | JSONB | 用例知识 ID 列表 → `knowledge.id` |
+| `process_knowledge` | JSONB | 工序知识 ID 列表 → `knowledge.id` |
+| `embedding` | float4[] | name + introduction 的向量 |
+| `implemented_tool_ids` | JSONB | 已实现的工具 ID 列表 |
+
+---
+
+## atomic_capability — 原子能力表
+
+实现:`knowhub_db/pg_capability_store.py:PostgreSQLCapabilityStore`
+
+原子能力是从知识中提炼的核心概念,连接工具实现与需求匹配。
+
+| 字段 | 类型 | 说明 |
+|------|------|------|
+| `id` | VARCHAR PK | `"ac-image-gen-001"` |
+| `name` | VARCHAR | 能力名称 |
+| `criterion` | TEXT | 评估标准 |
+| `description` | TEXT | 能力描述 |
+| `requirements` | JSONB | 关联需求 ID 列表 → `requirement_table.id` |
+| `implements` | JSONB | 工具实现映射 `{tool_name: 使用方式描述}` |
+| `tools` | JSONB | 关联工具 ID 列表 → `tool_table.id` |
+| `source_knowledge` | JSONB | 提炼自哪些知识 → `knowledge.id` |
+| `embedding` | float4[] | name + description 的向量 |
+
+---
+
+## requirement_table — 需求表
+
+实现:`knowhub_db/pg_requirement_store.py:PostgreSQLRequirementStore`
+
+| 字段 | 类型 | 说明 |
+|------|------|------|
+| `id` | VARCHAR PK | `"req-001"` |
+| `description` | TEXT | 需求描述 |
+| `atomics` | JSONB | 关联的原子能力 ID 列表 → `atomic_capability.id` |
+| `source_nodes` | JSONB | 来源节点 `[{node_name, posts}]` |
+| `status` | VARCHAR | 已满足 / 未满足 |
+| `match_result` | TEXT | 满足/不足的描述 |
+| `embedding` | float4[] | description 的向量 |
+
+---
+
+## Embedding 策略
+
+| 表 | 向量字段 | Embedding 内容 |
+|---|---|---|
+| knowledge | `task_embedding` | task |
+| knowledge | `content_embedding` | content |
+| tool_table | `embedding` | name + introduction |
+| atomic_capability | `embedding` | name + description |
+| requirement_table | `embedding` | description |

+ 30 - 233
knowhub/knowhub_db/README.md

@@ -1,206 +1,13 @@
-# knowhub/knowhub_db 数据库设计文档
+# knowhub_db — 数据库访问层
 
-## 概述
-
-`knowhub_db` 是 KnowHub 系统的 **PostgreSQL 数据库访问层**,使用远程 PostgreSQL + **fastann/pgvector** 扩展同时支持向量检索和关系型查询。
-
-系统围绕四张核心表构建,以 **原子能力(atomic_capability)** 为中心,连接知识、工具和需求:
-
-```
-                     knowledge(知识表)
-                    ╱         ╲
-        support_capability    tools
-               ╱                ╲
-  atomic_capability  ←────→  tool_table
-    (原子能力表)              (工具表)
-         |                       |
-    requirements            capabilities
-         ↓                       ↓
-  requirement_table ←──────→ atomic_capability
-     (需求表)
-```
-
----
-
-## 数据库表结构
-
-### 1. `atomic_capability` — 原子能力表(新增)
-
-原子能力是系统的核心概念,从知识中提炼而来,连接工具实现与需求匹配。
-
-索引:`atomic_capability_pkey (id)`
-
-| 字段 | 类型 | 说明 | 示例值 |
-|------|------|------|--------|
-| `id` | VARCHAR | 主键 | `"ac-image-gen-001"` |
-| `name` | VARCHAR | 能力名称 | `"文生图"` |
-| `criterion` | TEXT | 评估标准,用于判断该能力是否达成 | `"能根据文本提示生成符合描述的图像"` |
-| `description` | TEXT | 能力描述 | `"通过自然语言描述生成对应视觉内容的能力"` |
-| `requirements` | JSONB | 关联的需求 ID 列表 | `["req-001", "req-002"]` |
-| `implements` | JSONB | 工具实现映射,key 为 tool_name,value 为描述(使用方式、效果、局限) | `{"Midjourney": "通过 /imagine 命令生成图像,效果优秀但不支持中文提示词"}` |
-| `tools` | JSONB | 关联的工具 ID 列表 | `["tools/image_gen/midjourney"]` |
-| `source_knowledge` | JSONB | 该能力提炼自哪些知识条目 | `["knowledge-20260330-030758-8611"]` |
-| `embedding` | float4[] | 1536 维向量,对 name + description 做 embedding | — |
-
-**关联关系:**
-- `tools` → `tool_table.id`
-- `implements` 的 key 为 `tool_table.name`
-- `requirements` → `requirement_table.id`
-- `source_knowledge` → `knowledge.id`
-
----
-
-### 2. `tool_table` — 工具表(变更)
-
-> 相对原表的变更:新增 `capabilities` 字段;知识关联字段重命名为 `tool_knowledge`、`case_knowledge`、`process_knowledge`。
-
-索引:`tool_table_pkey (id)`
-
-| 字段 | 类型 | 说明 | 示例值 |
-|------|------|------|--------|
-| `id` | VARCHAR | 主键,路径格式 | `"tools/image_gen/midjourney"` |
-| `name` | VARCHAR | 工具名称 | `"Midjourney"` |
-| `version` | VARCHAR | 版本号 | `"v5.2"` |
-| `introduction` | TEXT | 功能介绍 | `"AI 图像生成工具,支持文生图、图生图"` |
-| `tutorial` | TEXT | 使用指南 | `"通过 Discord 输入 /imagine 命令..."` |
-| `input` | JSONB | 输入规格 | `"文本提示、参数配置"` |
-| `output` | JSONB | 输出规格 | `"生成图像"` |
-| `updated_time` | BIGINT | 更新时间戳(秒) | `1774570091` |
-| `status` | VARCHAR | 接入状态 | `"未接入"` / `"可用"` / `"异常"` |
-| `capabilities` | JSONB | 关联的原子能力 ID 列表 | `["ac-image-gen-001", "ac-image-edit-002"]` |
-| `tool_knowledge` | JSONB | 关联的工具知识 ID 列表 | `["knowledge-20260327-150915-44a4"]` |
-| `case_knowledge` | JSONB | 关联的用例知识 ID 列表 | `[]` |
-| `process_knowledge` | JSONB | 关联的工序知识 ID 列表 | `[]` |
-| `embedding` | float4[] | 1536 维向量,对 name + introduction 做 embedding | — |
-
-**关联关系:**
-- `capabilities` → `atomic_capability.id`
-- `tool_knowledge` / `case_knowledge` / `process_knowledge` → `knowledge.id`
-
-**相对原表变更说明:**
-- 新增 `capabilities` 字段(JSONB 数组)
-- 新增 `embedding` 字段(float4[],对 name + introduction 做 embedding)
-- 原 `knowledge` 字段重命名为 `tool_knowledge`
-
----
-
-### 3. `knowledge` — 知识表(变更)
-
-> 相对原表的变更:新增 `support_capability`、`tools` 字段;原 `embedding` 拆分为 `task_embedding` + `content_embedding` 双向量;`types` 扩展为六种分类。其余原有字段全部保留。
-
-索引:`knowledge_pkey (id)`、`idx_knowledge_owner`、`idx_knowledge_status`
-
-| 字段 | 类型 | 说明 | 示例值 |
-|------|------|------|--------|
-| `id` | VARCHAR | 主键 | `"knowledge-20260330-030758-8611"` |
-| `task_embedding` | float4[] | 1536 维向量,对 task 做 embedding | — |
-| `content_embedding` | float4[] | 1536 维向量,对 content 做 embedding | — |
-| `message_id` | VARCHAR | 来源的 agent 任务消息 ID | `""` |
-| `task` | VARCHAR | 完成什么任务 | `"调研 AI 图像生成工具的功能特性"` |
-| `content` | TEXT | 知识正文 | `"当调研新兴 AI 工具时..."` |
-| `types` | ARRAY | 知识类型(多选):工序、用例、工具、经验、定义、User Profile | `['工具', '经验']` |
-| `tags` | JSONB | 标签键值对 | `{"intent": "信息调研", "project": "feature_extract"}` |
-| `tag_keys` | ARRAY | tags 中的键列表(用于过滤) | `['intent', 'state', 'project']` |
-| `scopes` | ARRAY | 作用域(组织/用户) | `['org:cybertogether']` |
-| `owner` | VARCHAR | 所有者 | `"srt_feature_extract_1"` |
-| `resource_ids` | ARRAY | 关联的 resource ID 列表 | `['tools/image_gen/midjourney']` |
-| `source` | JSONB | 来源信息 | `{"agent_id": "research_agent", "category": "exp"}` |
-| `eval` | JSONB | 评估信息 | `{"score": 5, "harmful": 0, "helpful": 1, "confidence": 0.5}` |
-| `created_at` | BIGINT | 创建时间戳(秒) | `1774811278` |
-| `updated_at` | BIGINT | 更新时间戳(秒) | `1774943256` |
-| `status` | VARCHAR | 状态 | `"approved"` |
-| `relationships` | JSONB | 关联关系列表 | `[{"type": "complement", "target": "knowledge-..."}]` |
-| `support_capability` | JSONB | 支撑的原子能力 ID 列表(可多个) | `["ac-image-gen-001", "ac-style-transfer-003"]` |
-| `tools` | JSONB | 关联的工具 ID 列表 | `["tools/image_gen/midjourney"]` |
-
-**关联关系:**
-- `support_capability` → `atomic_capability.id`
-- `tools` → `tool_table.id`
-
-**相对原表变更说明:**
-- 新增字段:`support_capability`(JSONB)、`tools`(JSONB)
-- 原 `embedding`(float4[])拆分为 `task_embedding` + `content_embedding` 两个向量字段
-- `types` 可选值更新为:工序、用例、工具、经验、定义、User Profile
-- 所有原有字段保留不变
-
----
-
-### 4. `requirement_table` — 需求表(变更)
-
-> 相对原表的变更:大幅简化,以原子能力 pattern 为核心,替代原来的 source_items/tools/trace/embedding 等字段。
-
-索引:`requirement_table_pkey (id)`
-
-| 字段 | 类型 | 说明 | 示例值 |
-|------|------|------|--------|
-| `id` | VARCHAR | 主键 | `"req-001"` |
-| `description` | TEXT | 需求描述 | `"能够根据用户文本描述生成高质量图像"` |
-| `atomics` | JSONB | 关联的原子能力 ID 列表 | `["ac-image-gen-001", "ac-style-transfer-003"]` |
-| `source_nodes` | JSONB | 来源于内容树的节点,对象数组 | `[{"node_name": "image_gen", "posts": ["post-001", "post-002"]}]` |
-| `status` | VARCHAR | 满足状态 | `"已满足"` / `"未满足"` |
-| `match_result` | TEXT | 满足时描述如何满足;不足时描述缺什么,提供调研方向 | `"通过 Midjourney + ComfyUI 组合可满足,但中文提示词支持不足,需调研替代方案"` |
-| `embedding` | float4[] | 1536 维向量,对 description 做 embedding | — |
-
-**关联关系:**
-- `atomics` → `atomic_capability.id`
-
-**相对原表变更说明:**
-- 删除字段:`task`、`type`、`source_type`、`source_itemset_id`、`source_items`、`tools`、`knowledge`、`case_knowledge`、`process_knowledge`、`trace`、`body`、`embedding`
-- 新增字段:`description`(TEXT)、`atomics`(JSONB)、`source_nodes`(JSONB)、`status`(VARCHAR)、`match_result`(TEXT)
-
----
-
-### 5. `resources` — 文档资源表(未变更)
-
-索引:`resources_pkey (id)`
-
-| 字段 | 类型 | 说明 | 示例值 |
-|------|------|------|--------|
-| `id` | TEXT | 主键,`/` 分隔路径格式 | `"references/python_type_hints"` |
-| `title` | TEXT | 标题 | `"Python Type Hints 权威资源列表"` |
-| `body` | TEXT | 公开内容(Markdown 或代码) | `"Python 类型提示调研的三个核心权威资源..."` |
-| `secure_body` | TEXT | 私有/加密内容 | `""` |
-| `content_type` | TEXT | 内容类型 | `"text"` |
-| `metadata` | JSONB | 附加元数据 | `{"topic": "type_hints", "category": "python"}` |
-| `sort_order` | INTEGER | 排序权重 | `0` |
-| `submitted_by` | TEXT | 提交者 | `""` |
-| `created_at` | BIGINT | 创建时间戳(秒) | `1774259301` |
-| `updated_at` | BIGINT | 更新时间戳(秒) | `1774259301` |
-
----
-
-## 表间关联关系总览
-
-所有关联均为 **应用层软关联**(JSONB 字段存储 ID 列表/映射),不使用数据库外键约束。
-
-```
-atomic_capability.tools[]             ──→  tool_table.id
-atomic_capability.implements{key}     ──→  tool_table.name
-atomic_capability.requirements[]      ──→  requirement_table.id
-atomic_capability.source_knowledge[]  ──→  knowledge.id
-
-tool_table.capabilities[]          ──→  atomic_capability.id
-tool_table.tool_knowledge[]        ──→  knowledge.id
-tool_table.case_knowledge[]        ──→  knowledge.id
-tool_table.process_knowledge[]     ──→  knowledge.id
-
-knowledge.support_capability[]     ──→  atomic_capability.id
-knowledge.tools[]                  ──→  tool_table.id
-
-requirement_table.atomics[]        ──→  atomic_capability.id
-```
-
-**双向关联说明:**
-- `atomic_capability` ↔ `tool_table`:能力的 `implements` 和工具的 `capabilities` 互为反向索引
-- `atomic_capability` ↔ `knowledge`:能力的 `source_knowledge` 和知识的 `support_capability` 互为反向索引
-- `atomic_capability` ↔ `requirement_table`:能力的 `requirements` 和需求的 `atomics` 互为反向索引
+PostgreSQL 数据库的封装层。表结构和数据模型详见 [docs/schema.md](../docs/schema.md)。
 
 ---
 
-## 核心封装类
+## 封装类
 
 ### `PostgreSQLStore` (`pg_store.py`)
-知识条目的 CRUD + 向量检索:
+knowledge 表的 CRUD + 向量检索:
 
 | 方法 | 功能 |
 |------|------|
@@ -214,7 +21,7 @@ requirement_table.atomics[]        ──→  atomic_capability.id
 | `count()` | 统计总数 |
 
 ### `PostgreSQLResourceStore` (`pg_resource_store.py`)
-资源文档的 CRUD + 导航:
+resources 表的 CRUD + 层级导航:
 
 | 方法 | 功能 |
 |------|------|
@@ -225,8 +32,14 @@ requirement_table.atomics[]        ──→  atomic_capability.id
 | `delete(id)` | 删除 |
 | `get_siblings(id)` | 获取前后同级节点 |
 
+### `PostgreSQLToolStore` (`pg_tool_store.py`)
+tool_table 的 CRUD + 向量检索。
+
+### `PostgreSQLCapabilityStore` (`pg_capability_store.py`)
+atomic_capability 表的 CRUD + 向量检索。
+
 ### `PostgreSQLRequirementStore` (`pg_requirement_store.py`)
-需求的 CRUD + 向量检索:
+requirement_table 的 CRUD + 向量检索:
 
 | 方法 | 功能 |
 |------|------|
@@ -238,23 +51,28 @@ requirement_table.atomics[]        ──→  atomic_capability.id
 
 ---
 
-## 运维脚本
+## 目录结构
 
-| 脚本 | 功能 |
-|------|------|
-| `create_tables.py` | 创建/变更数据库表结构 |
-| `migrate_resources.py` | 从 SQLite 迁移资源到 PostgreSQL |
-| `migrate_tools.py` | 从 SQLite 迁移工具数据 |
-| `clean_invalid_knowledge_refs.py` | 清理失效的 knowledge ID 引用 |
-| `clean_resource_knowledge_refs.py` | 清理 resources 中失效的引用 |
-| `test_pg_connection.py` | 测试数据库连接 |
-| `check_extensions.py` | 查看向量扩展 |
-| `check_fastann.py` | 查看 fastann 函数和操作符 |
-| `list_databases.py` | 列出所有数据库 |
+```
+knowhub_db/
+├── pg_store.py                # knowledge 表
+├── pg_resource_store.py       # resources 表
+├── pg_tool_store.py           # tool_table
+├── pg_capability_store.py     # atomic_capability 表
+├── pg_requirement_store.py    # requirement_table
+├── README.md
+├── migrations/                # 一次性迁移脚本(已执行,保留备查)
+└── scripts/                   # 诊断和运维脚本
+    ├── check_table_structure.py   # 查看表结构和行数
+    ├── check_extensions.py        # 查看 PostgreSQL 扩展
+    ├── clear_locks.py             # 清理数据库锁
+    ├── clean_invalid_knowledge_refs.py  # 清理失效引用
+    └── ...
+```
 
 ---
 
-## 环境变量配置
+## 环境变量
 
 ```bash
 KNOWHUB_DB        # 数据库主机
@@ -263,24 +81,3 @@ KNOWHUB_USER      # 用户名
 KNOWHUB_PASSWORD  # 密码
 KNOWHUB_DB_NAME   # 数据库名
 ```
-
----
-
-## 架构特点
-
-1. **原子能力为核心**:`atomic_capability` 作为知识、工具、需求三者之间的桥梁,实现能力的提炼、实现映射和需求匹配。
-2. **全表向量检索**:四张核心表均支持 1536 维 embedding,其中 knowledge 表有双向量(`task_embedding` + `content_embedding`)分别支持任务语义和内容语义检索。
-3. **应用层软关联**:所有表间关系通过 JSONB 字段存储 ID 列表/映射,保持灵活性,需应用层维护一致性。
-4. **双向索引**:核心关联关系均有正反两个方向的索引,方便从任意一端查询关联数据。
-5. **三类工具知识**:工具关联的知识分为工具知识(tool_knowledge)、工序知识(process_knowledge)、用例知识(case_knowledge)三类,形成细粒度的知识图谱。
-6. **资源路径 ID**:`resources.id` 和 `tool_table.id` 均支持 `/` 分隔路径格式,便于层级组织和导航。
-
-### Embedding 策略
-
-| 表 | 向量字段 | Embedding 内容 |
-|------|------|------|
-| `atomic_capability` | `embedding` | name + description |
-| `tool_table` | `embedding` | name + introduction |
-| `knowledge` | `task_embedding` | task |
-| `knowledge` | `content_embedding` | content |
-| `requirement_table` | `embedding` | description |

+ 0 - 0
knowhub/knowhub_db/create_tables.py → knowhub/knowhub_db/migrations/create_tables.py


+ 0 - 0
knowhub/knowhub_db/fill_cap_relations.py → knowhub/knowhub_db/migrations/fill_cap_relations.py


+ 0 - 0
knowhub/knowhub_db/fill_cap_tools.py → knowhub/knowhub_db/migrations/fill_cap_tools.py


+ 0 - 0
knowhub/knowhub_db/fill_embeddings.py → knowhub/knowhub_db/migrations/fill_embeddings.py


+ 0 - 0
knowhub/knowhub_db/fill_knowledge_tools.py → knowhub/knowhub_db/migrations/fill_knowledge_tools.py


+ 0 - 0
knowhub/knowhub_db/fix_embedding_migration.py → knowhub/knowhub_db/migrations/fix_embedding_migration.py


+ 0 - 0
knowhub/knowhub_db/import_initial_data.py → knowhub/knowhub_db/migrations/import_initial_data.py


+ 0 - 0
knowhub/knowhub_db/import_tool_research_data.py → knowhub/knowhub_db/migrations/import_tool_research_data.py


+ 0 - 0
knowhub/knowhub_db/migrate_add_implemented_tools.py → knowhub/knowhub_db/migrations/migrate_add_implemented_tools.py


+ 0 - 0
knowhub/knowhub_db/migrate_knowledge.py → knowhub/knowhub_db/migrations/migrate_knowledge.py


+ 0 - 0
knowhub/knowhub_db/migrate_resources.py → knowhub/knowhub_db/migrations/migrate_resources.py


+ 0 - 0
knowhub/knowhub_db/migrate_tables_v2.py → knowhub/knowhub_db/migrations/migrate_tables_v2.py


+ 0 - 0
knowhub/knowhub_db/migrate_tools.py → knowhub/knowhub_db/migrations/migrate_tools.py


+ 0 - 0
knowhub/knowhub_db/reclassify_tool_knowledge.py → knowhub/knowhub_db/migrations/reclassify_tool_knowledge.py


+ 0 - 0
knowhub/knowhub_db/update_case_knowledge.py → knowhub/knowhub_db/migrations/update_case_knowledge.py


+ 0 - 0
knowhub/knowhub_db/check_extensions.py → knowhub/knowhub_db/scripts/check_extensions.py


+ 0 - 0
knowhub/knowhub_db/check_fastann.py → knowhub/knowhub_db/scripts/check_fastann.py


+ 0 - 0
knowhub/knowhub_db/check_table_structure.py → knowhub/knowhub_db/scripts/check_table_structure.py


+ 0 - 0
knowhub/knowhub_db/clean_invalid_knowledge_refs.py → knowhub/knowhub_db/scripts/clean_invalid_knowledge_refs.py


+ 0 - 0
knowhub/knowhub_db/clean_resource_knowledge_refs.py → knowhub/knowhub_db/scripts/clean_resource_knowledge_refs.py


+ 0 - 0
knowhub/knowhub_db/clean_tool_research_data.py → knowhub/knowhub_db/scripts/clean_tool_research_data.py


+ 0 - 0
knowhub/knowhub_db/clear_locks.py → knowhub/knowhub_db/scripts/clear_locks.py


+ 0 - 0
knowhub/knowhub_db/kill_db_locks.py → knowhub/knowhub_db/scripts/kill_db_locks.py


+ 0 - 0
knowhub/knowhub_db/list_databases.py → knowhub/knowhub_db/scripts/list_databases.py


+ 0 - 0
knowhub/knowhub_db/test_imports.py → knowhub/knowhub_db/scripts/test_imports.py


+ 0 - 0
knowhub/knowhub_db/test_pg_connection.py → knowhub/knowhub_db/scripts/test_pg_connection.py