mindforge-memory 6.4.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- MindForge.py +20 -0
- mindforge/__init__.py +111 -0
- mindforge/adapters/__init__.py +18 -0
- mindforge/adapters/claude_adapter.py +84 -0
- mindforge/adapters/crewai_memory.py +76 -0
- mindforge/adapters/generic_api.py +183 -0
- mindforge/adapters/langgraph_store.py +463 -0
- mindforge/adapters/openclaw_adapter.py +91 -0
- mindforge/api/__init__.py +1 -0
- mindforge/api/server.py +1567 -0
- mindforge/cli/__init__.py +1 -0
- mindforge/cli/main.py +13607 -0
- mindforge/core/__init__.py +37 -0
- mindforge/core/embedding.py +847 -0
- mindforge/core/encryption.py +597 -0
- mindforge/core/indexer.py +363 -0
- mindforge/core/mindforge.py +6298 -0
- mindforge/core/paths.py +43 -0
- mindforge/core/query.py +501 -0
- mindforge/core/storage.py +18656 -0
- mindforge/core/types.py +314 -0
- mindforge/core/version.py +56 -0
- mindforge/daemon/__init__.py +0 -0
- mindforge/daemon/server.py +277 -0
- mindforge/mcp/__init__.py +4 -0
- mindforge/mcp/server.py +2559 -0
- mindforge/modules/__init__.py +138 -0
- mindforge/modules/categorizer.py +151 -0
- mindforge/modules/conflict_detector.py +356 -0
- mindforge/modules/connectors.py +331 -0
- mindforge/modules/context_window.py +337 -0
- mindforge/modules/event_bus.py +572 -0
- mindforge/modules/evolution.py +210 -0
- mindforge/modules/experience.py +402 -0
- mindforge/modules/federated.py +722 -0
- mindforge/modules/federated_acl.py +393 -0
- mindforge/modules/follow_up.py +315 -0
- mindforge/modules/hybrid_search.py +565 -0
- mindforge/modules/importer.py +374 -0
- mindforge/modules/integrator.py +196 -0
- mindforge/modules/intent_router.py +359 -0
- mindforge/modules/knowledge_graph.py +395 -0
- mindforge/modules/memory_compressor.py +592 -0
- mindforge/modules/memory_decay.py +474 -0
- mindforge/modules/memory_passport.py +250 -0
- mindforge/modules/multi_agent.py +534 -0
- mindforge/modules/multimodal.py +304 -0
- mindforge/modules/outcome_learning.py +186 -0
- mindforge/modules/personality.py +275 -0
- mindforge/modules/principled_forgetting.py +258 -0
- mindforge/modules/privacy.py +736 -0
- mindforge/modules/recall.py +263 -0
- mindforge/modules/session_focus.py +305 -0
- mindforge/modules/share_conflict.py +521 -0
- mindforge/modules/skill_extractor.py +340 -0
- mindforge/modules/skill_pack.py +205 -0
- mindforge/modules/timeline_viz.py +206 -0
- mindforge/modules/v6.py +931 -0
- mindforge_memory-6.4.1.dist-info/METADATA +281 -0
- mindforge_memory-6.4.1.dist-info/RECORD +64 -0
- mindforge_memory-6.4.1.dist-info/WHEEL +5 -0
- mindforge_memory-6.4.1.dist-info/entry_points.txt +3 -0
- mindforge_memory-6.4.1.dist-info/licenses/LICENSE +21 -0
- mindforge_memory-6.4.1.dist-info/top_level.txt +2 -0
MindForge.py
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
"""
|
|
3
|
+
MindForge - AI Agent 终身记忆系统
|
|
4
|
+
=======================================
|
|
5
|
+
四层记忆架构 · 知识图谱引擎 · 多模态支持 · 人格化记忆 · 联邦网络 · AI短剧记忆
|
|
6
|
+
|
|
7
|
+
兼容入口(自 v5.8.13 起):全部源码已迁入 `mindforge.*` 命名空间,
|
|
8
|
+
本文件仅为向后兼容保留,使 `from MindForge import MindForge` 在 pip install
|
|
9
|
+
后仍然可用。新代码请统一使用 `from mindforge import MindForge`。
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from mindforge import * # noqa: F401,F403
|
|
13
|
+
from mindforge import ( # noqa: F401
|
|
14
|
+
__version__,
|
|
15
|
+
VERSION_INFO,
|
|
16
|
+
NEXT_MAJOR_TARGET,
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
__author__ = "MindForge Project"
|
|
20
|
+
__license__ = "MIT"
|
mindforge/__init__.py
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
"""
|
|
3
|
+
MindForge — AI Agent 终身记忆系统
|
|
4
|
+
|
|
5
|
+
四层记忆架构 · 知识图谱引擎 · 多模态支持 · 人格化记忆 · 联邦网络 · AI短剧记忆
|
|
6
|
+
|
|
7
|
+
包入口(mindforge.* 命名空间):自 v5.8.13 起全部源码统一位于 mindforge/
|
|
8
|
+
子包下,不再以 core/modules/mcp/api/cli/adapters 等顶层名称安装进
|
|
9
|
+
site-packages,避免与其它库冲突。旧式 `from MindForge import ...` 仍可通过
|
|
10
|
+
仓库根目录的 MindForge.py 兼容模块使用(不推荐新代码使用)。
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
from .core import (
|
|
14
|
+
MindForge,
|
|
15
|
+
MemoryEntry,
|
|
16
|
+
MemoryLayer,
|
|
17
|
+
PrivacyLevel,
|
|
18
|
+
Importance,
|
|
19
|
+
MemoryType,
|
|
20
|
+
MemoryConfig,
|
|
21
|
+
StorageEngine,
|
|
22
|
+
EncryptionEngine,
|
|
23
|
+
IndexEngine,
|
|
24
|
+
QueryEngine,
|
|
25
|
+
AuditRecord,
|
|
26
|
+
MemoryChunk,
|
|
27
|
+
RecallResult,
|
|
28
|
+
VectorIndex,
|
|
29
|
+
init_engine,
|
|
30
|
+
get_engine,
|
|
31
|
+
)
|
|
32
|
+
from .modules import (
|
|
33
|
+
RecallEngine,
|
|
34
|
+
RecallConfig,
|
|
35
|
+
KnowledgeGraph,
|
|
36
|
+
MemoryEvolution,
|
|
37
|
+
PersonalityEngine,
|
|
38
|
+
MultimodalMemory,
|
|
39
|
+
FederatedMemory,
|
|
40
|
+
TaxonomyManager,
|
|
41
|
+
PrivacyEngine,
|
|
42
|
+
MemoryIntegrator,
|
|
43
|
+
# v6.0.0 扩展端口预留(默认不启用,仅暴露发现/注册入口)
|
|
44
|
+
V6_TARGET_VERSION,
|
|
45
|
+
V6Capability,
|
|
46
|
+
V6Status,
|
|
47
|
+
V6Port,
|
|
48
|
+
MultiAgentCollaborationPort,
|
|
49
|
+
MultiAgentAdapterPort,
|
|
50
|
+
MemoryPreviewPort,
|
|
51
|
+
create_multi_agent_adapter,
|
|
52
|
+
register_v6_port,
|
|
53
|
+
get_v6_port,
|
|
54
|
+
list_v6_ports,
|
|
55
|
+
v6_status,
|
|
56
|
+
)
|
|
57
|
+
from .modules.event_bus import EventBus
|
|
58
|
+
from .modules.experience import ExperienceCase, SkillStore
|
|
59
|
+
from .core.version import __version__, VERSION_INFO, NEXT_MAJOR_TARGET
|
|
60
|
+
|
|
61
|
+
__author__ = "MindForge Project"
|
|
62
|
+
__license__ = "MIT"
|
|
63
|
+
|
|
64
|
+
__all__ = [
|
|
65
|
+
"MindForge",
|
|
66
|
+
"MemoryEntry",
|
|
67
|
+
"MemoryLayer",
|
|
68
|
+
"PrivacyLevel",
|
|
69
|
+
"Importance",
|
|
70
|
+
"MemoryType",
|
|
71
|
+
"MemoryConfig",
|
|
72
|
+
"StorageEngine",
|
|
73
|
+
"EncryptionEngine",
|
|
74
|
+
"IndexEngine",
|
|
75
|
+
"QueryEngine",
|
|
76
|
+
"AuditRecord",
|
|
77
|
+
"MemoryChunk",
|
|
78
|
+
"RecallResult",
|
|
79
|
+
"VectorIndex",
|
|
80
|
+
"init_engine",
|
|
81
|
+
"get_engine",
|
|
82
|
+
"RecallEngine",
|
|
83
|
+
"RecallConfig",
|
|
84
|
+
"KnowledgeGraph",
|
|
85
|
+
"MemoryEvolution",
|
|
86
|
+
"PersonalityEngine",
|
|
87
|
+
"MultimodalMemory",
|
|
88
|
+
"FederatedMemory",
|
|
89
|
+
"TaxonomyManager",
|
|
90
|
+
"PrivacyEngine",
|
|
91
|
+
"MemoryIntegrator",
|
|
92
|
+
"EventBus",
|
|
93
|
+
"ExperienceCase",
|
|
94
|
+
"SkillStore",
|
|
95
|
+
"__version__",
|
|
96
|
+
"VERSION_INFO",
|
|
97
|
+
"NEXT_MAJOR_TARGET",
|
|
98
|
+
# v6.0.0 端口预留
|
|
99
|
+
"V6_TARGET_VERSION",
|
|
100
|
+
"V6Capability",
|
|
101
|
+
"V6Status",
|
|
102
|
+
"V6Port",
|
|
103
|
+
"MultiAgentCollaborationPort",
|
|
104
|
+
"MultiAgentAdapterPort",
|
|
105
|
+
"MemoryPreviewPort",
|
|
106
|
+
"create_multi_agent_adapter",
|
|
107
|
+
"register_v6_port",
|
|
108
|
+
"get_v6_port",
|
|
109
|
+
"list_v6_ports",
|
|
110
|
+
"v6_status",
|
|
111
|
+
]
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"""
|
|
2
|
+
MindForge v5.0 适配器
|
|
3
|
+
OpenClaw · Claude Code · 通用 API · LangGraph Store · CrewAI Memory
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from .openclaw_adapter import OpenClawAdapter
|
|
7
|
+
from .generic_api import GenericAPIAdapter
|
|
8
|
+
from .claude_adapter import ClaudeCodeAdapter
|
|
9
|
+
from .langgraph_store import MindForgeStore
|
|
10
|
+
from .crewai_memory import CrewAIMemory
|
|
11
|
+
|
|
12
|
+
__all__ = [
|
|
13
|
+
"OpenClawAdapter",
|
|
14
|
+
"GenericAPIAdapter",
|
|
15
|
+
"ClaudeCodeAdapter",
|
|
16
|
+
"MindForgeStore",
|
|
17
|
+
"CrewAIMemory",
|
|
18
|
+
]
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
"""
|
|
2
|
+
MindForge v5.0 Claude Code 适配器
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import os
|
|
6
|
+
from typing import List, Dict, Optional
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class ClaudeCodeAdapter:
|
|
10
|
+
"""Claude Code 记忆适配器"""
|
|
11
|
+
|
|
12
|
+
def __init__(self, MindForge):
|
|
13
|
+
self.cm = MindForge
|
|
14
|
+
self.session_id = os.environ.get("CLAUDE_SESSION_ID", "claude")
|
|
15
|
+
self.agent_id = "claude_code"
|
|
16
|
+
|
|
17
|
+
@classmethod
|
|
18
|
+
def from_env(cls):
|
|
19
|
+
"""从环境变量创建"""
|
|
20
|
+
from mindforge.core import MindForge, MemoryConfig
|
|
21
|
+
|
|
22
|
+
db_path = os.environ.get("MindForge_DB_PATH", "./data/memory.db")
|
|
23
|
+
key_file = os.environ.get("MindForge_KEY_FILE", "./data/.key")
|
|
24
|
+
encrypted = os.environ.get("MindForge_ENCRYPTED", "true").lower() == "true"
|
|
25
|
+
|
|
26
|
+
config = MemoryConfig(
|
|
27
|
+
db_path=db_path,
|
|
28
|
+
key_file=key_file,
|
|
29
|
+
encrypted=encrypted,
|
|
30
|
+
)
|
|
31
|
+
cm = MindForge(config=config)
|
|
32
|
+
return cls(cm)
|
|
33
|
+
|
|
34
|
+
def remember(self, content: str, tags: Optional[List[str]] = None) -> str:
|
|
35
|
+
"""记住某件事"""
|
|
36
|
+
entry = self.cm.add(
|
|
37
|
+
content=content,
|
|
38
|
+
tags=tags or [],
|
|
39
|
+
source_agent=self.agent_id,
|
|
40
|
+
source_session=self.session_id,
|
|
41
|
+
)
|
|
42
|
+
return entry.id
|
|
43
|
+
|
|
44
|
+
def recall(self, query: str, limit: int = 5) -> List[str]:
|
|
45
|
+
"""回忆相关内容"""
|
|
46
|
+
result = self.cm.search(
|
|
47
|
+
query=query,
|
|
48
|
+
max_results=limit,
|
|
49
|
+
agent_id=self.agent_id,
|
|
50
|
+
session_id=self.session_id,
|
|
51
|
+
)
|
|
52
|
+
return [chunk.content for chunk in result.chunks]
|
|
53
|
+
|
|
54
|
+
def forget(self, memory_id: str) -> bool:
|
|
55
|
+
"""忘记某件事"""
|
|
56
|
+
return self.cm.delete(memory_id, self.agent_id, self.session_id)
|
|
57
|
+
|
|
58
|
+
def get_context(self, current_task: str, limit: int = 10) -> str:
|
|
59
|
+
"""获取相关上下文"""
|
|
60
|
+
result = self.cm.search(
|
|
61
|
+
query=current_task,
|
|
62
|
+
max_results=limit,
|
|
63
|
+
agent_id=self.agent_id,
|
|
64
|
+
session_id=self.session_id,
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
context_parts = ["# Relevant Memory\n"]
|
|
68
|
+
for i, chunk in enumerate(result.chunks, 1):
|
|
69
|
+
context_parts.append(f"## Memory {i} ({chunk.category})\n")
|
|
70
|
+
context_parts.append(f"{chunk.content}\n")
|
|
71
|
+
|
|
72
|
+
return "\n".join(context_parts)
|
|
73
|
+
|
|
74
|
+
def learn_user_preference(self, user_message: str, response: str):
|
|
75
|
+
"""学习用户偏好"""
|
|
76
|
+
from mindforge.modules.personality import PersonalityEngine
|
|
77
|
+
pe = PersonalityEngine(self.cm.storage)
|
|
78
|
+
pe.learn_from_interaction("default", user_message, response)
|
|
79
|
+
|
|
80
|
+
def get_user_style(self) -> Dict:
|
|
81
|
+
"""获取用户风格偏好"""
|
|
82
|
+
from mindforge.modules.personality import PersonalityEngine
|
|
83
|
+
pe = PersonalityEngine(self.cm.storage)
|
|
84
|
+
return pe.get_recommended_style()
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
"""CrewAI Memory 适配器(v5.8.4 新增)
|
|
3
|
+
|
|
4
|
+
把 MindForge 包装为 CrewAI 生态的长期记忆后端(Memory 接口):
|
|
5
|
+
|
|
6
|
+
from mindforge.adapters.crewai_memory import CrewAIMemory
|
|
7
|
+
|
|
8
|
+
memory = CrewAIMemory(mindforge, namespace="crew_travel")
|
|
9
|
+
memory.save("用户偏好靠窗座位", metadata={"trip": "tokyo"})
|
|
10
|
+
memory.search("座位偏好", limit=3)
|
|
11
|
+
|
|
12
|
+
设计要点:
|
|
13
|
+
- 零硬依赖:未安装 crewai 时类仍可导入(基类回退 object)。
|
|
14
|
+
- 写:save() -> MindForge add(),namespace 编码进 category,metadata 扁平为 tags;
|
|
15
|
+
- 读:search() -> MindForge 混合检索(mf.search().chunks 解密明文路径);
|
|
16
|
+
- reset() 仅清空本 namespace 条目(list 定位 id 后逐条 delete),不影响其他应用。
|
|
17
|
+
"""
|
|
18
|
+
from __future__ import annotations
|
|
19
|
+
|
|
20
|
+
from typing import Any, Dict, List, Optional
|
|
21
|
+
|
|
22
|
+
try:
|
|
23
|
+
from crewai.memory.memory import Memory as _CrewMemory # type: ignore
|
|
24
|
+
_CREWAI_AVAILABLE = True
|
|
25
|
+
except Exception: # pragma: no cover - 无 crewai 环境回退
|
|
26
|
+
_CrewMemory = object # type: ignore
|
|
27
|
+
_CREWAI_AVAILABLE = False
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class CrewAIMemory(_CrewMemory):
|
|
31
|
+
"""CrewAI Memory 协议的 MindForge 后端(v5.8.4)。"""
|
|
32
|
+
|
|
33
|
+
def __init__(self, mindforge, namespace: str = "crewai"):
|
|
34
|
+
self.mf = mindforge
|
|
35
|
+
self.namespace = namespace
|
|
36
|
+
|
|
37
|
+
def save(self, value: Any, metadata: Optional[Dict[str, Any]] = None) -> None:
|
|
38
|
+
"""保存一条记忆。value 序列化为文本,metadata 扁平为 tags。"""
|
|
39
|
+
metadata = metadata or {}
|
|
40
|
+
tags = ["%s:%s" % (k, v) for k, v in metadata.items()
|
|
41
|
+
if isinstance(v, (str, int, float, bool))]
|
|
42
|
+
self.mf.add(
|
|
43
|
+
str(value),
|
|
44
|
+
category=self.namespace,
|
|
45
|
+
tags=tags,
|
|
46
|
+
source_agent="crewai",
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
def search(self, query: str, limit: int = 3,
|
|
50
|
+
filters: Optional[Dict[str, Any]] = None) -> List[Dict[str, Any]]:
|
|
51
|
+
"""搜索记忆,返回 CrewAI 风格 list[dict](context 为解密明文)。"""
|
|
52
|
+
rr = self.mf.search(query, max_results=limit,
|
|
53
|
+
categories=[self.namespace])
|
|
54
|
+
results: List[Dict[str, Any]] = []
|
|
55
|
+
for c in (rr.chunks or []):
|
|
56
|
+
results.append({
|
|
57
|
+
"context": getattr(c, "content", "") or "",
|
|
58
|
+
"metadata": {
|
|
59
|
+
"id": getattr(c, "memory_id", ""),
|
|
60
|
+
"category": getattr(c, "category", self.namespace),
|
|
61
|
+
"tags": getattr(c, "tags", []),
|
|
62
|
+
},
|
|
63
|
+
})
|
|
64
|
+
return results
|
|
65
|
+
|
|
66
|
+
def reset(self) -> None:
|
|
67
|
+
"""清空本 namespace 的全部记忆(不影响其他应用)。循环删直到空。"""
|
|
68
|
+
for _ in range(100): # 安全上限,防意外死循环
|
|
69
|
+
rows = self.mf.list(category=self.namespace, limit=500) or []
|
|
70
|
+
if not rows:
|
|
71
|
+
return
|
|
72
|
+
for h in rows:
|
|
73
|
+
self.mf.delete(getattr(h, "id", ""))
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
__all__ = ["CrewAIMemory", "_CREWAI_AVAILABLE"]
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
"""
|
|
2
|
+
MindForge v5.0 通用 API 适配器
|
|
3
|
+
REST API / SDK 风格接口
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from typing import List, Dict, Optional, Callable, Any
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class GenericAPIAdapter:
|
|
10
|
+
"""通用 API 适配器"""
|
|
11
|
+
|
|
12
|
+
def __init__(self, MindForge):
|
|
13
|
+
self.cm = MindForge
|
|
14
|
+
self._handlers: Dict[str, Callable] = {}
|
|
15
|
+
self._register_default_handlers()
|
|
16
|
+
|
|
17
|
+
def _register_default_handlers(self):
|
|
18
|
+
self._handlers = {
|
|
19
|
+
"memory.add": self._handle_add,
|
|
20
|
+
"memory.get": self._handle_get,
|
|
21
|
+
"memory.search": self._handle_search,
|
|
22
|
+
"memory.list": self._handle_list,
|
|
23
|
+
"memory.update": self._handle_update,
|
|
24
|
+
"memory.delete": self._handle_delete,
|
|
25
|
+
"stats.get": self._handle_stats,
|
|
26
|
+
"graph.stats": self._handle_graph_stats,
|
|
27
|
+
"graph.related": self._handle_graph_related,
|
|
28
|
+
"personality.profile": self._handle_personality,
|
|
29
|
+
"evolution.consolidate": self._handle_consolidate,
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
def handle_request(self, request: Dict) -> Dict:
|
|
33
|
+
"""处理 API 请求
|
|
34
|
+
|
|
35
|
+
P2 #19 修复:
|
|
36
|
+
- 校验 request 结构(action 必选且为字符串)
|
|
37
|
+
- 异常信息脱敏,不暴露内部调用栈细节
|
|
38
|
+
"""
|
|
39
|
+
if not isinstance(request, dict):
|
|
40
|
+
return {"success": False, "error": "Invalid request format"}
|
|
41
|
+
|
|
42
|
+
action = request.get("action", "")
|
|
43
|
+
params = request.get("params", {})
|
|
44
|
+
|
|
45
|
+
if not action or not isinstance(action, str):
|
|
46
|
+
return {"success": False, "error": "Missing required field: action"}
|
|
47
|
+
if not isinstance(params, dict):
|
|
48
|
+
return {"success": False, "error": "Invalid params format"}
|
|
49
|
+
|
|
50
|
+
handler = self._handlers.get(action)
|
|
51
|
+
if not handler:
|
|
52
|
+
return {
|
|
53
|
+
"success": False,
|
|
54
|
+
"error": f"Unknown action: {action}",
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
try:
|
|
58
|
+
result = handler(params)
|
|
59
|
+
return {
|
|
60
|
+
"success": True,
|
|
61
|
+
"data": result,
|
|
62
|
+
}
|
|
63
|
+
except (ValueError, TypeError) as e:
|
|
64
|
+
# 预期内的错误:返回消息(用户输入类)
|
|
65
|
+
return {
|
|
66
|
+
"success": False,
|
|
67
|
+
"error": str(e),
|
|
68
|
+
}
|
|
69
|
+
except Exception as e:
|
|
70
|
+
# 未预期的错误:脱敏返回,防止内部细节泄露
|
|
71
|
+
import logging as _logging
|
|
72
|
+
_logging.getLogger(__name__).exception("API handler error: %s", action)
|
|
73
|
+
return {
|
|
74
|
+
"success": False,
|
|
75
|
+
"error": "Internal error",
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
@staticmethod
|
|
79
|
+
def _require(params: Dict, field: str, error_msg: str = "") -> Any:
|
|
80
|
+
"""校验必需字段,缺失时返回友好错误"""
|
|
81
|
+
if field not in params:
|
|
82
|
+
raise ValueError(error_msg or f"Missing required field: {field}")
|
|
83
|
+
return params[field]
|
|
84
|
+
|
|
85
|
+
def _handle_add(self, params: Dict) -> Dict:
|
|
86
|
+
entry = self.cm.add(
|
|
87
|
+
content=self._require(params, "content"),
|
|
88
|
+
category=params.get("category", "general"),
|
|
89
|
+
tags=params.get("tags", []),
|
|
90
|
+
source_agent=params.get("agent", "api"),
|
|
91
|
+
source_session=params.get("session", "api"),
|
|
92
|
+
)
|
|
93
|
+
return entry.to_dict()
|
|
94
|
+
|
|
95
|
+
def _handle_get(self, params: Dict) -> Optional[Dict]:
|
|
96
|
+
entry = self.cm.get(
|
|
97
|
+
self._require(params, "id"),
|
|
98
|
+
actor=params.get("actor", ""), # v5.7.3:未传 actor 视同本机内部调用
|
|
99
|
+
session_id=params.get("session_id", ""),
|
|
100
|
+
)
|
|
101
|
+
return entry.to_dict() if entry else None
|
|
102
|
+
|
|
103
|
+
def _handle_search(self, params: Dict) -> Dict:
|
|
104
|
+
result = self.cm.search(
|
|
105
|
+
query=params["query"],
|
|
106
|
+
max_results=params.get("limit", 10),
|
|
107
|
+
categories=params.get("categories"),
|
|
108
|
+
agent_id=params.get("actor", ""), # v5.7.3:未传 actor 视同本机内部调用
|
|
109
|
+
session_id=params.get("session_id", ""),
|
|
110
|
+
)
|
|
111
|
+
return {
|
|
112
|
+
"total": result.total_found,
|
|
113
|
+
"time_ms": result.query_time_ms,
|
|
114
|
+
"results": [
|
|
115
|
+
{
|
|
116
|
+
"id": c.memory_id,
|
|
117
|
+
"content": c.content,
|
|
118
|
+
"category": c.category,
|
|
119
|
+
"relevance": c.relevance_score,
|
|
120
|
+
}
|
|
121
|
+
for c in result.chunks
|
|
122
|
+
],
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
def _handle_list(self, params: Dict) -> List[Dict]:
|
|
126
|
+
# F1 修复:适配器列表入口接入隐私过滤(params.actor / params.session_id)。
|
|
127
|
+
# 未传 actor 时保持原有"返回全部"语义,兼容既有集成方。
|
|
128
|
+
entries = self.cm.list(
|
|
129
|
+
category=params.get("category"),
|
|
130
|
+
limit=params.get("limit", 50),
|
|
131
|
+
offset=params.get("offset", 0),
|
|
132
|
+
actor=str(params.get("actor") or ""),
|
|
133
|
+
session_id=str(params.get("session_id") or ""),
|
|
134
|
+
)
|
|
135
|
+
return [e.to_dict() for e in entries]
|
|
136
|
+
|
|
137
|
+
def _handle_update(self, params: Dict) -> bool:
|
|
138
|
+
return self.cm.update(
|
|
139
|
+
memory_id=self._require(params, "id"),
|
|
140
|
+
content=params.get("content"),
|
|
141
|
+
category=params.get("category"),
|
|
142
|
+
tags=params.get("tags"),
|
|
143
|
+
actor=params.get("actor", ""), # v5.7.3:未传 actor 视同本机内部调用
|
|
144
|
+
session_id=params.get("session_id", ""),
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
def _handle_delete(self, params: Dict) -> bool:
|
|
148
|
+
return self.cm.delete(
|
|
149
|
+
self._require(params, "id"),
|
|
150
|
+
actor=params.get("actor", ""), # v5.7.3:未传 actor 视同本机内部调用
|
|
151
|
+
session_id=params.get("session_id", ""),
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
def _handle_stats(self, params: Dict) -> Dict:
|
|
155
|
+
return self.cm.stats()
|
|
156
|
+
|
|
157
|
+
def _handle_graph_stats(self, params: Dict) -> Dict:
|
|
158
|
+
from mindforge.modules.knowledge_graph import KnowledgeGraph
|
|
159
|
+
kg = KnowledgeGraph(storage=self.cm.storage)
|
|
160
|
+
return kg.get_entity_stats()
|
|
161
|
+
|
|
162
|
+
def _handle_graph_related(self, params: Dict) -> List:
|
|
163
|
+
from mindforge.modules.knowledge_graph import KnowledgeGraph
|
|
164
|
+
kg = KnowledgeGraph(storage=self.cm.storage)
|
|
165
|
+
related = kg.get_related_entities(
|
|
166
|
+
self._require(params, "entity"),
|
|
167
|
+
depth=params.get("depth", 2),
|
|
168
|
+
)
|
|
169
|
+
return [{"name": n, "relation": r, "weight": w} for n, r, w in related]
|
|
170
|
+
|
|
171
|
+
def _handle_personality(self, params: Dict) -> Dict:
|
|
172
|
+
from mindforge.modules.personality import PersonalityEngine
|
|
173
|
+
pe = PersonalityEngine(self.cm.storage)
|
|
174
|
+
return pe.get_recommended_style(params.get("user_id", "default"))
|
|
175
|
+
|
|
176
|
+
def _handle_consolidate(self, params: Dict) -> Dict:
|
|
177
|
+
from mindforge.modules.evolution import MemoryEvolution
|
|
178
|
+
evo = MemoryEvolution(self.cm.storage)
|
|
179
|
+
return evo.consolidate()
|
|
180
|
+
|
|
181
|
+
def register_handler(self, action: str, handler: Callable):
|
|
182
|
+
"""注册自定义处理器"""
|
|
183
|
+
self._handlers[action] = handler
|