illusion-code 0.1.0__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.
Files changed (214) hide show
  1. illusion/__init__.py +24 -0
  2. illusion/__main__.py +15 -0
  3. illusion/_frontend/dist/index.mjs +39208 -0
  4. illusion/_frontend/package.json +27 -0
  5. illusion/_frontend/src/App.tsx +624 -0
  6. illusion/_frontend/src/components/CommandPicker.tsx +98 -0
  7. illusion/_frontend/src/components/Composer.tsx +55 -0
  8. illusion/_frontend/src/components/ComposerController.tsx +128 -0
  9. illusion/_frontend/src/components/ConversationView.tsx +750 -0
  10. illusion/_frontend/src/components/Footer.tsx +25 -0
  11. illusion/_frontend/src/components/MarkdownContent.tsx +537 -0
  12. illusion/_frontend/src/components/MarkdownTable.tsx +245 -0
  13. illusion/_frontend/src/components/ModalHost.tsx +425 -0
  14. illusion/_frontend/src/components/MultilineTextInput.tsx +250 -0
  15. illusion/_frontend/src/components/PromptInput.tsx +64 -0
  16. illusion/_frontend/src/components/SelectModal.tsx +78 -0
  17. illusion/_frontend/src/components/SidePanel.tsx +175 -0
  18. illusion/_frontend/src/components/Spinner.tsx +77 -0
  19. illusion/_frontend/src/components/StatusBar.tsx +142 -0
  20. illusion/_frontend/src/components/SwarmPanel.tsx +141 -0
  21. illusion/_frontend/src/components/TodoPanel.tsx +126 -0
  22. illusion/_frontend/src/components/ToolCallDisplay.tsx +202 -0
  23. illusion/_frontend/src/components/TranscriptPane.tsx +79 -0
  24. illusion/_frontend/src/components/WelcomeBanner.tsx +37 -0
  25. illusion/_frontend/src/hooks/useBackendSession.ts +468 -0
  26. illusion/_frontend/src/hooks/useTerminalSize.ts +9 -0
  27. illusion/_frontend/src/i18n.ts +78 -0
  28. illusion/_frontend/src/index.tsx +42 -0
  29. illusion/_frontend/src/theme/ThemeContext.tsx +19 -0
  30. illusion/_frontend/src/theme/builtinThemes.ts +89 -0
  31. illusion/_frontend/src/types.ts +110 -0
  32. illusion/_frontend/src/utils/markdown.ts +33 -0
  33. illusion/_frontend/src/utils/thinking.ts +191 -0
  34. illusion/_frontend/tsconfig.json +13 -0
  35. illusion/_web_dist/assets/index-BseIw-ik.css +10 -0
  36. illusion/_web_dist/assets/index-C_0ZWMuW.js +82 -0
  37. illusion/_web_dist/index.html +16 -0
  38. illusion/api/__init__.py +36 -0
  39. illusion/api/client.py +568 -0
  40. illusion/api/codex_client.py +563 -0
  41. illusion/api/compat.py +138 -0
  42. illusion/api/effort.py +128 -0
  43. illusion/api/errors.py +57 -0
  44. illusion/api/openai_client.py +819 -0
  45. illusion/api/provider.py +148 -0
  46. illusion/api/registry.py +479 -0
  47. illusion/api/usage.py +45 -0
  48. illusion/auth/__init__.py +50 -0
  49. illusion/auth/copilot.py +419 -0
  50. illusion/auth/external.py +612 -0
  51. illusion/auth/flows.py +58 -0
  52. illusion/auth/manager.py +214 -0
  53. illusion/auth/storage.py +372 -0
  54. illusion/bridge/__init__.py +38 -0
  55. illusion/bridge/manager.py +190 -0
  56. illusion/bridge/session_runner.py +84 -0
  57. illusion/bridge/types.py +113 -0
  58. illusion/bridge/work_secret.py +131 -0
  59. illusion/cli.py +1228 -0
  60. illusion/commands/__init__.py +32 -0
  61. illusion/commands/registry.py +1934 -0
  62. illusion/config/__init__.py +39 -0
  63. illusion/config/i18n.py +522 -0
  64. illusion/config/paths.py +259 -0
  65. illusion/config/settings.py +564 -0
  66. illusion/coordinator/__init__.py +41 -0
  67. illusion/coordinator/agent_definitions.py +1093 -0
  68. illusion/coordinator/coordinator_mode.py +127 -0
  69. illusion/engine/__init__.py +95 -0
  70. illusion/engine/cost_tracker.py +55 -0
  71. illusion/engine/messages.py +369 -0
  72. illusion/engine/query.py +632 -0
  73. illusion/engine/query_engine.py +343 -0
  74. illusion/engine/stream_events.py +169 -0
  75. illusion/hooks/__init__.py +67 -0
  76. illusion/hooks/events.py +43 -0
  77. illusion/hooks/executor.py +397 -0
  78. illusion/hooks/hot_reload.py +74 -0
  79. illusion/hooks/loader.py +133 -0
  80. illusion/hooks/schemas.py +121 -0
  81. illusion/hooks/types.py +86 -0
  82. illusion/mcp/__init__.py +104 -0
  83. illusion/mcp/client.py +377 -0
  84. illusion/mcp/config.py +140 -0
  85. illusion/mcp/types.py +175 -0
  86. illusion/memory/__init__.py +36 -0
  87. illusion/memory/manager.py +94 -0
  88. illusion/memory/memdir.py +58 -0
  89. illusion/memory/paths.py +57 -0
  90. illusion/memory/scan.py +120 -0
  91. illusion/memory/search.py +83 -0
  92. illusion/memory/types.py +43 -0
  93. illusion/output_styles/__init__.py +15 -0
  94. illusion/output_styles/loader.py +64 -0
  95. illusion/permissions/__init__.py +39 -0
  96. illusion/permissions/checker.py +174 -0
  97. illusion/permissions/modes.py +38 -0
  98. illusion/platforms.py +148 -0
  99. illusion/plugins/__init__.py +71 -0
  100. illusion/plugins/bundled/__init__.py +0 -0
  101. illusion/plugins/installer.py +59 -0
  102. illusion/plugins/loader.py +301 -0
  103. illusion/plugins/schemas.py +51 -0
  104. illusion/plugins/types.py +56 -0
  105. illusion/prompts/__init__.py +29 -0
  106. illusion/prompts/claudemd.py +74 -0
  107. illusion/prompts/context.py +187 -0
  108. illusion/prompts/environment.py +189 -0
  109. illusion/prompts/system_prompt.py +155 -0
  110. illusion/py.typed +0 -0
  111. illusion/sandbox/__init__.py +29 -0
  112. illusion/sandbox/adapter.py +174 -0
  113. illusion/services/__init__.py +59 -0
  114. illusion/services/compact/__init__.py +1015 -0
  115. illusion/services/cron.py +338 -0
  116. illusion/services/cron_scheduler.py +715 -0
  117. illusion/services/file_history.py +258 -0
  118. illusion/services/lsp/__init__.py +455 -0
  119. illusion/services/session_storage.py +237 -0
  120. illusion/services/token_estimation.py +72 -0
  121. illusion/skills/__init__.py +60 -0
  122. illusion/skills/bundled/__init__.py +110 -0
  123. illusion/skills/bundled/content/batch.md +86 -0
  124. illusion/skills/bundled/content/coding-guidelines.md +70 -0
  125. illusion/skills/bundled/content/debug.md +38 -0
  126. illusion/skills/bundled/content/loop.md +82 -0
  127. illusion/skills/bundled/content/remember.md +105 -0
  128. illusion/skills/bundled/content/simplify.md +53 -0
  129. illusion/skills/bundled/content/skillify.md +113 -0
  130. illusion/skills/bundled/content/stuck.md +54 -0
  131. illusion/skills/bundled/content/update-config.md +329 -0
  132. illusion/skills/bundled/content/verify.md +74 -0
  133. illusion/skills/loader.py +219 -0
  134. illusion/skills/registry.py +40 -0
  135. illusion/skills/types.py +24 -0
  136. illusion/state/__init__.py +18 -0
  137. illusion/state/app_state.py +67 -0
  138. illusion/state/store.py +93 -0
  139. illusion/swarm/__init__.py +71 -0
  140. illusion/swarm/agent_executor.py +857 -0
  141. illusion/swarm/in_process.py +259 -0
  142. illusion/swarm/subprocess_backend.py +136 -0
  143. illusion/swarm/team_helpers.py +123 -0
  144. illusion/swarm/types.py +159 -0
  145. illusion/swarm/worktree.py +347 -0
  146. illusion/tasks/__init__.py +33 -0
  147. illusion/tasks/local_agent_task.py +42 -0
  148. illusion/tasks/local_shell_task.py +27 -0
  149. illusion/tasks/manager.py +377 -0
  150. illusion/tasks/stop_task.py +21 -0
  151. illusion/tasks/types.py +88 -0
  152. illusion/tools/__init__.py +126 -0
  153. illusion/tools/agent_tool.py +388 -0
  154. illusion/tools/ask_user_question_tool.py +186 -0
  155. illusion/tools/base.py +149 -0
  156. illusion/tools/bash_tool.py +413 -0
  157. illusion/tools/config_tool.py +90 -0
  158. illusion/tools/cron_tool.py +473 -0
  159. illusion/tools/enter_plan_mode_tool.py +147 -0
  160. illusion/tools/enter_worktree_tool.py +188 -0
  161. illusion/tools/exit_plan_mode_tool.py +69 -0
  162. illusion/tools/exit_worktree_tool.py +225 -0
  163. illusion/tools/file_edit_tool.py +283 -0
  164. illusion/tools/file_read_tool.py +294 -0
  165. illusion/tools/file_write_tool.py +184 -0
  166. illusion/tools/glob_tool.py +165 -0
  167. illusion/tools/grep_tool.py +190 -0
  168. illusion/tools/list_mcp_resources_tool.py +80 -0
  169. illusion/tools/lsp_tool.py +333 -0
  170. illusion/tools/mcp_auth_tool.py +100 -0
  171. illusion/tools/mcp_tool.py +75 -0
  172. illusion/tools/notebook_edit_tool.py +242 -0
  173. illusion/tools/powershell_tool.py +334 -0
  174. illusion/tools/read_mcp_resource_tool.py +63 -0
  175. illusion/tools/repl_tool.py +100 -0
  176. illusion/tools/send_message_tool.py +112 -0
  177. illusion/tools/shell_common.py +187 -0
  178. illusion/tools/skill_tool.py +86 -0
  179. illusion/tools/sleep_tool.py +62 -0
  180. illusion/tools/structured_output_tool.py +58 -0
  181. illusion/tools/task_create_tool.py +98 -0
  182. illusion/tools/task_get_tool.py +94 -0
  183. illusion/tools/task_list_tool.py +94 -0
  184. illusion/tools/task_output_tool.py +55 -0
  185. illusion/tools/task_stop_tool.py +52 -0
  186. illusion/tools/task_update_tool.py +224 -0
  187. illusion/tools/team_create_tool.py +236 -0
  188. illusion/tools/team_delete_tool.py +104 -0
  189. illusion/tools/todo_write_tool.py +198 -0
  190. illusion/tools/tool_search_tool.py +156 -0
  191. illusion/tools/web_fetch_tool.py +264 -0
  192. illusion/tools/web_search_tool.py +186 -0
  193. illusion/ui/__init__.py +23 -0
  194. illusion/ui/app.py +258 -0
  195. illusion/ui/backend_host.py +1180 -0
  196. illusion/ui/input.py +86 -0
  197. illusion/ui/output.py +363 -0
  198. illusion/ui/permission_dialog.py +47 -0
  199. illusion/ui/permission_store.py +99 -0
  200. illusion/ui/protocol.py +384 -0
  201. illusion/ui/react_launcher.py +280 -0
  202. illusion/ui/runtime.py +787 -0
  203. illusion/ui/textual_app.py +603 -0
  204. illusion/ui/web/__init__.py +10 -0
  205. illusion/ui/web/server.py +87 -0
  206. illusion/ui/web/ws_host.py +1197 -0
  207. illusion/utils/__init__.py +0 -0
  208. illusion/utils/ripgrep.py +299 -0
  209. illusion/utils/shell.py +248 -0
  210. illusion_code-0.1.0.dist-info/METADATA +1159 -0
  211. illusion_code-0.1.0.dist-info/RECORD +214 -0
  212. illusion_code-0.1.0.dist-info/WHEEL +4 -0
  213. illusion_code-0.1.0.dist-info/entry_points.txt +2 -0
  214. illusion_code-0.1.0.dist-info/licenses/LICENSE +21 -0
illusion/mcp/config.py ADDED
@@ -0,0 +1,140 @@
1
+ """
2
+ MCP 服务器配置加载模块
3
+ =====================
4
+
5
+ 本模块提供从设置、插件和项目目录加载 MCP 服务器配置的功能。
6
+
7
+ 主要功能:
8
+ - 从全局设置中加载 MCP 服务器配置
9
+ - 从已加载的插件中合并 MCP 服务器配置
10
+ - 从项目级配置目录加载 MCP 服务器配置
11
+ - 插件配置优先级高于全局设置(同名配置)
12
+
13
+ 函数说明:
14
+ - load_mcp_server_configs: 加载并合并 MCP 服务器配置
15
+ - load_project_mcp_configs: 从项目目录加载 MCP 配置
16
+
17
+ 使用示例:
18
+ >>> from illusion.mcp.config import load_mcp_server_configs
19
+ >>> configs = load_mcp_server_configs(settings, plugins, cwd="/path/to/project")
20
+ """
21
+
22
+ from __future__ import annotations
23
+
24
+ import json
25
+ import logging
26
+ from pathlib import Path
27
+
28
+ from illusion.plugins.types import LoadedPlugin
29
+
30
+ logger = logging.getLogger(__name__)
31
+
32
+
33
+ def load_project_mcp_configs(cwd: str | Path) -> dict[str, object]:
34
+ """
35
+ 从项目目录加载 MCP 服务器配置
36
+
37
+ 扫描 <project>/.illusion/mcp/ 目录下的所有 JSON 文件,
38
+ 每个文件可以包含一个或多个 MCP 服务器配置。
39
+
40
+ 文件格式支持:
41
+ 1. 单个服务器配置(文件名作为服务器名):
42
+ {"type": "stdio", "command": "python", "args": ["server.py"]}
43
+
44
+ 2. 多个服务器配置(使用 mcpServers 键):
45
+ {"mcpServers": {"server1": {...}, "server2": {...}}}
46
+
47
+ Args:
48
+ cwd: 当前工作目录
49
+
50
+ Returns:
51
+ dict[str, object]: 服务器名称到配置的映射字典
52
+ """
53
+ from pydantic import TypeAdapter
54
+
55
+ from illusion.config.paths import get_project_mcp_dir
56
+ from illusion.mcp.types import McpJsonConfig, McpServerConfig
57
+
58
+ _server_adapter = TypeAdapter(McpServerConfig)
59
+ servers: dict[str, object] = {}
60
+ mcp_dir = get_project_mcp_dir(cwd)
61
+
62
+ if not mcp_dir.exists():
63
+ return servers
64
+
65
+ for json_file in sorted(mcp_dir.glob("*.json")):
66
+ try:
67
+ raw = json.loads(json_file.read_text(encoding="utf-8"))
68
+ except (json.JSONDecodeError, OSError) as exc:
69
+ logger.warning("Failed to read MCP config %s: %s", json_file, exc)
70
+ continue
71
+
72
+ # 兼容 mcp_servers(snake_case)键
73
+ if "mcp_servers" in raw and "mcpServers" not in raw:
74
+ raw["mcpServers"] = raw.pop("mcp_servers")
75
+
76
+ # 尝试解析为多服务器格式(mcpServers 键)
77
+ if "mcpServers" in raw:
78
+ try:
79
+ parsed = McpJsonConfig.model_validate(raw)
80
+ for name, config in parsed.mcpServers.items():
81
+ if getattr(config, "enabled", True):
82
+ servers[name] = config
83
+ except Exception as exc:
84
+ logger.warning("Failed to parse MCP config %s: %s", json_file, exc)
85
+ continue
86
+
87
+ # 尝试解析为单服务器格式(文件名作为服务器名)
88
+ try:
89
+ config = _server_adapter.validate_python(raw)
90
+ if getattr(config, "enabled", True):
91
+ server_name = json_file.stem
92
+ servers[server_name] = config
93
+ except Exception as exc:
94
+ logger.warning("Failed to parse MCP config %s: %s", json_file, exc)
95
+
96
+ return servers
97
+
98
+
99
+ def load_mcp_server_configs(settings, plugins: list[LoadedPlugin], cwd: str | Path | None = None) -> dict[str, object]:
100
+ """
101
+ 加载 MCP 服务器配置
102
+
103
+ 从全局设置、项目目录和已加载的插件中合并 MCP 服务器配置。
104
+ 优先级(从高到低):插件 > 项目级 > 全局设置
105
+
106
+ Args:
107
+ settings: 全局设置对象,包含 mcp_servers 属性
108
+ plugins: 已加载的插件列表,每个插件包含 mcp_servers 属性
109
+ cwd: 当前工作目录,用于加载项目级配置
110
+
111
+ Returns:
112
+ dict[str, object]: 服务器名称到配置的映射字典
113
+ 键的格式为 "插件名:服务器名"(来自插件)或仅"服务器名"(来自其他来源)
114
+
115
+ 使用示例:
116
+ >>> configs = load_mcp_server_configs(settings, plugins, cwd="/path/to/project")
117
+ >>> for name, config in configs.items():
118
+ ... print(f"{name}: {config}")
119
+ """
120
+ # 从全局设置中获取 MCP 服务器配置(跳过已禁用的服务器)
121
+ servers = {name: cfg for name, cfg in settings.mcp_servers.items()
122
+ if getattr(cfg, "enabled", True)}
123
+
124
+ # 从项目目录加载 MCP 配置(覆盖全局设置)
125
+ if cwd is not None:
126
+ project_configs = load_project_mcp_configs(cwd)
127
+ servers.update(project_configs)
128
+
129
+ # 遍历所有已加载的插件
130
+ for plugin in plugins:
131
+ # 跳过未启用的插件
132
+ if not plugin.enabled:
133
+ continue
134
+ # 将插件的 MCP 服务器配置合并到结果中(跳过已禁用的服务器)
135
+ for name, config in plugin.mcp_servers.items():
136
+ if not getattr(config, "enabled", True):
137
+ continue
138
+ # 使用 "插件名:服务器名" 格式作为键,避免与全局设置冲突
139
+ servers.setdefault(f"{plugin.manifest.name}:{name}", config)
140
+ return servers
illusion/mcp/types.py ADDED
@@ -0,0 +1,175 @@
1
+ """
2
+ MCP 配置和状态模型
3
+ ==================
4
+
5
+ 本模块定义 MCP(Model Context Protocol)相关的配置和数据类型。
6
+
7
+ 主要功能:
8
+ - 定义 MCP 服务器配置(STDIO、HTTP、WebSocket)
9
+ - 定义 MCP 工具和资源信息
10
+ - 定义 MCP 连接状态
11
+
12
+ 类说明:
13
+ - McpStdioServerConfig: STDIO 类型 MCP 服务器配置
14
+ - McpHttpServerConfig: HTTP 类型 MCP 服务器配置
15
+ - McpWebSocketServerConfig: WebSocket 类型 MCP 服务器配置
16
+ - McpServerConfig: MCP 服务器配置联合类型
17
+ - McpJsonConfig: 配置文件格式(用于插件和项目文件)
18
+ - McpToolInfo: MCP 工具元数据
19
+ - McpResourceInfo: MCP 资源元数据
20
+ - McpConnectionStatus: MCP 服务器运行时状态
21
+
22
+ 使用示例:
23
+ >>> from illusion.mcp.types import McpStdioServerConfig
24
+ >>> config = McpStdioServerConfig(command="node", args=["server.js"])
25
+ """
26
+
27
+ from __future__ import annotations
28
+
29
+ from dataclasses import dataclass, field
30
+ from typing import Literal
31
+
32
+ from pydantic import BaseModel, Field
33
+
34
+
35
+ class McpStdioServerConfig(BaseModel):
36
+ """
37
+ STDIO 类型 MCP 服务器配置
38
+
39
+ 通过标准输入输出流与 MCP 服务器通信的配置。
40
+
41
+ Attributes:
42
+ type: 服务器类型,固定为 "stdio"
43
+ command: 要执行的命令
44
+ args: 命令参数列表
45
+ env: 环境变量字典
46
+ cwd: 工作目录
47
+ log_file: stderr 日志重定向文件路径,设置后 MCP 服务器的 stderr 输出将写入该文件
48
+ """
49
+
50
+ type: Literal["stdio"] = "stdio"
51
+ command: str
52
+ args: list[str] = Field(default_factory=list)
53
+ env: dict[str, str] | None = None
54
+ cwd: str | None = None
55
+ log_file: str | None = None
56
+ enabled: bool = True
57
+
58
+
59
+ class McpHttpServerConfig(BaseModel):
60
+ """
61
+ HTTP 类型 MCP 服务器配置
62
+
63
+ 通过 HTTP 协议与 MCP 服务器通信的配置。
64
+
65
+ Attributes:
66
+ type: 服务器类型,固定为 "http"
67
+ url: 服务器 URL 地址
68
+ headers: HTTP 请求头字典
69
+ """
70
+
71
+ type: Literal["http"] = "http"
72
+ url: str
73
+ headers: dict[str, str] = Field(default_factory=dict)
74
+ enabled: bool = True
75
+
76
+
77
+ class McpWebSocketServerConfig(BaseModel):
78
+ """
79
+ WebSocket 类型 MCP 服务器配置
80
+
81
+ 通过 WebSocket 协议与 MCP 服务器通信的配置。
82
+
83
+ Attributes:
84
+ type: 服务器类型,固定为 "ws"
85
+ url: 服务器 WebSocket URL 地址
86
+ headers: WebSocket 连接请求头字典
87
+ """
88
+
89
+ type: Literal["ws"] = "ws"
90
+ url: str
91
+ headers: dict[str, str] = Field(default_factory=dict)
92
+ enabled: bool = True
93
+
94
+
95
+ # MCP 服务器配置联合类型,支持 STDIO、HTTP、WebSocket 三种传输方式
96
+ McpServerConfig = McpStdioServerConfig | McpHttpServerConfig | McpWebSocketServerConfig
97
+
98
+
99
+ class McpJsonConfig(BaseModel):
100
+ """
101
+ MCP 配置文件格式
102
+
103
+ 用于插件和项目文件中的 MCP 服务器配置格式。
104
+
105
+ Attributes:
106
+ mcp_servers: MCP 服务器名称到配置的映射字典
107
+ """
108
+
109
+ mcpServers: dict[str, McpServerConfig] = Field(default_factory=dict)
110
+
111
+
112
+ @dataclass(frozen=True)
113
+ class McpToolInfo:
114
+ """
115
+ MCP 工具信息
116
+
117
+ MCP 服务器暴露的工具元数据,包含工具名称、描述和输入模式。
118
+
119
+ Attributes:
120
+ server_name: 所属服务器名称
121
+ name: 工具名称
122
+ description: 工具描述
123
+ input_schema: 工具输入参数的 JSON Schema 定义
124
+ """
125
+
126
+ server_name: str
127
+ name: str
128
+ description: str
129
+ input_schema: dict[str, object]
130
+
131
+
132
+ @dataclass(frozen=True)
133
+ class McpResourceInfo:
134
+ """
135
+ MCP 资源信息
136
+
137
+ MCP 服务器暴露的资源元数据,包含资源名称、URI 和描述。
138
+
139
+ Attributes:
140
+ server_name: 所属服务器名称
141
+ name: 资源名称
142
+ uri: 资源统一标识符
143
+ description: 资源描述
144
+ """
145
+
146
+ server_name: str
147
+ name: str
148
+ uri: str
149
+ description: str = ""
150
+
151
+
152
+ @dataclass
153
+ class McpConnectionStatus:
154
+ """
155
+ MCP 连接状态
156
+
157
+ MCP 服务器的运行时状态信息,包含连接状态、传输类型、认证配置、工具和资源列表。
158
+
159
+ Attributes:
160
+ name: 服务器名称
161
+ state: 连接状态(connected/failed/pending/disabled)
162
+ detail: 状态详情或错误信息
163
+ transport: 传输类型(stdio/http/ws)
164
+ auth_configured: 是否配置了认证
165
+ tools: 该服务器提供的工具列表
166
+ resources: 该服务器提供的资源列表
167
+ """
168
+
169
+ name: str
170
+ state: Literal["connected", "failed", "pending", "disabled"]
171
+ detail: str = ""
172
+ transport: str = "unknown"
173
+ auth_configured: bool = False
174
+ tools: list[McpToolInfo] = field(default_factory=list)
175
+ resources: list[McpResourceInfo] = field(default_factory=list)
@@ -0,0 +1,36 @@
1
+ """
2
+ 记忆模块
3
+ ========
4
+
5
+ 本模块提供 IllusionCode 记忆/上下文管理功能。
6
+
7
+ 主要组件:
8
+ - add_memory_entry: 添加记忆条目
9
+ - find_relevant_memories: 查找相关记忆
10
+ - get_memory_entrypoint: 获取记忆入口点
11
+ - get_project_memory_dir: 获取项目记忆目录
12
+ - list_memory_files: 列出记忆文件
13
+ - load_memory_prompt: 加载记忆提示词
14
+ - remove_memory_entry: 移除记忆条目
15
+ - scan_memory_files: 扫描记忆文件
16
+
17
+ 使用示例:
18
+ >>> from illusion.memory import add_memory_entry, find_relevant_memories
19
+ """
20
+
21
+ from illusion.memory.memdir import load_memory_prompt
22
+ from illusion.memory.manager import add_memory_entry, list_memory_files, remove_memory_entry
23
+ from illusion.memory.paths import get_memory_entrypoint, get_project_memory_dir
24
+ from illusion.memory.scan import scan_memory_files
25
+ from illusion.memory.search import find_relevant_memories
26
+
27
+ __all__ = [
28
+ "add_memory_entry",
29
+ "find_relevant_memories",
30
+ "get_memory_entrypoint",
31
+ "get_project_memory_dir",
32
+ "list_memory_files",
33
+ "load_memory_prompt",
34
+ "remove_memory_entry",
35
+ "scan_memory_files",
36
+ ]
@@ -0,0 +1,94 @@
1
+ """
2
+ 记忆管理模块
3
+ ==========
4
+
5
+ 本模块提供记忆文件的管理操作功能。
6
+
7
+ 主要功能:
8
+ - 列出项目记忆文件
9
+ - 添加/移除记忆条目
10
+
11
+ 函数说明:
12
+ - list_memory_files: 列出记忆文件
13
+ - add_memory_entry: 添加记忆条目
14
+ - remove_memory_entry: 移除记忆条目
15
+
16
+ 使用示例:
17
+ >>> from illusion.memory import list_memory_files, add_memory_entry, remove_memory_entry
18
+ >>> files = list_memory_files(".")
19
+ >>> path = add_memory_entry(".", "Test", "# Test memory content")
20
+ >>> remove_memory_entry(".", "test")
21
+ """
22
+
23
+ from __future__ import annotations
24
+
25
+ from pathlib import Path
26
+ from re import sub
27
+
28
+ from illusion.memory.paths import get_memory_entrypoint, get_project_memory_dir
29
+
30
+
31
+ def list_memory_files(cwd: str | Path) -> list[Path]:
32
+ """列出项目的所有记忆markdown文件
33
+
34
+ Args:
35
+ cwd: 当前工作目录
36
+
37
+ Returns:
38
+ list[Path]: 排序后的记忆文件路径列表
39
+ """
40
+ memory_dir = get_project_memory_dir(cwd) # 获取记忆目录
41
+ return sorted(path for path in memory_dir.glob("*.md")) # 返回排序后的文件列表
42
+
43
+
44
+ def add_memory_entry(cwd: str | Path, title: str, content: str) -> Path:
45
+ """创建记忆文件并添加到MEMORY.md索引
46
+
47
+ Args:
48
+ cwd: 当前工作目录
49
+ title: 记忆标题
50
+ content: 记忆内容
51
+
52
+ Returns:
53
+ Path: 创建的记忆文件路径
54
+ """
55
+ memory_dir = get_project_memory_dir(cwd) # 获取记忆目录
56
+ slug = sub(r"[^a-zA-Z0-9]+", "_", title.strip().lower()).strip("_") or "memory" # 转换为slug
57
+ path = memory_dir / f"{slug}.md" # 构建文件路径
58
+ path.write_text(content.strip() + "\n", encoding="utf-8") # 写入内容
59
+
60
+ entrypoint = get_memory_entrypoint(cwd) # 获取入口点
61
+ existing = entrypoint.read_text(encoding="utf-8") if entrypoint.exists() else "# Memory Index\n" # 读取现有内容
62
+ if path.name not in existing: # 如果不存在
63
+ existing = existing.rstrip() + f"\n- [{title}]({path.name})\n" # 添加索引条目
64
+ entrypoint.write_text(existing, encoding="utf-8") # 写入索引
65
+ return path # 返回创建的文件路径
66
+
67
+
68
+ def remove_memory_entry(cwd: str | Path, name: str) -> bool:
69
+ """删除记忆文件及其在MEMORY.md中的索引条目
70
+
71
+ Args:
72
+ cwd: 当前工作目录
73
+ name: 记忆文件名称 (不带.md扩展名)
74
+
75
+ Returns:
76
+ bool: 是否成功删除
77
+ """
78
+ memory_dir = get_project_memory_dir(cwd) # 获取记忆目录
79
+ matches = [path for path in memory_dir.glob("*.md") if path.stem == name or path.name == name] # 查找匹配文件
80
+ if not matches: # 没有匹配
81
+ return False
82
+ path = matches[0] # 取第一个匹配
83
+ if path.exists(): # 文件存在
84
+ path.unlink() # 删除文件
85
+
86
+ entrypoint = get_memory_entrypoint(cwd) # 获取入口点
87
+ if entrypoint.exists(): # 入口点存在
88
+ lines = [
89
+ line # 保留的行
90
+ for line in entrypoint.read_text(encoding="utf-8").splitlines()
91
+ if path.name not in line # 排除包含删除文件名的行
92
+ ]
93
+ entrypoint.write_text("\n".join(lines).rstrip() + "\n", encoding="utf-8") # 重写入口点
94
+ return True # 返回成功
@@ -0,0 +1,58 @@
1
+ """
2
+ 记忆提示词模块
3
+ =============
4
+
5
+ 本模块提供记忆相关的提示词构建功能。
6
+
7
+ 主要功能:
8
+ - 加载项目记忆提示词段落
9
+ - 格式化记忆目录信息
10
+
11
+ 函数说明:
12
+ - load_memory_prompt: 加载记忆提示词
13
+
14
+ 使用示例:
15
+ >>> from illusion.memory import load_memory_prompt
16
+ >>> prompt = load_memory_prompt(".", max_entrypoint_lines=200)
17
+ """
18
+
19
+ from __future__ import annotations
20
+
21
+ from pathlib import Path
22
+
23
+ from illusion.memory.paths import get_memory_entrypoint, get_project_memory_dir
24
+
25
+
26
+ def load_memory_prompt(cwd: str | Path, *, max_entrypoint_lines: int = 200) -> str | None:
27
+ """构建当前项目的记忆提示词段落
28
+
29
+ Args:
30
+ cwd: 当前工作目录
31
+ max_entrypoint_lines: 入口点文件最大行数
32
+
33
+ Returns:
34
+ str | None: 格式化后的记忆提示词,如果失败返回None
35
+ """
36
+ memory_dir = get_project_memory_dir(cwd) # 获取记忆目录
37
+ entrypoint = get_memory_entrypoint(cwd) # 获取入口点文件
38
+ lines = [
39
+ "# Memory", # 标题
40
+ f"- Persistent memory directory: {memory_dir}", # 记忆目录
41
+ "- Use this directory to store durable user or project context that should survive future sessions.", # 说明1
42
+ "- Prefer concise topic files plus an index entry in MEMORY.md.", # 说明2
43
+ ]
44
+
45
+ if entrypoint.exists(): # 入口点文件存在
46
+ content_lines = entrypoint.read_text(encoding="utf-8").splitlines()[:max_entrypoint_lines] # 读取内容
47
+ if content_lines: # 有内容
48
+ lines.extend(["", "## MEMORY.md", "```md", *content_lines, "```"]) # 添加到提示词
49
+ else: # 入口点不存在
50
+ lines.extend(
51
+ [
52
+ "", # 空行
53
+ "## MEMORY.md", # 标题
54
+ "(not created yet)", # 提示未创建
55
+ ]
56
+ )
57
+
58
+ return "\n".join(lines) # 返回合并后的字符串
@@ -0,0 +1,57 @@
1
+ """
2
+ 记忆路径模块
3
+ ==========
4
+
5
+ 本模块提供持久化项目记忆的路径管理功能。
6
+
7
+ 主要功能:
8
+ - 生成基于项目路径的唯一记忆目录
9
+ - 管理MEMORY.md入口点文件
10
+
11
+ 函数说明:
12
+ - get_project_memory_dir: 获取项目记忆目录
13
+ - get_memory_entrypoint: 获取记忆入口点文件
14
+
15
+ 使用示例:
16
+ >>> from illusion.memory import get_project_memory_dir, get_memory_entrypoint
17
+ >>> mem_dir = get_project_memory_dir(".")
18
+ >>> entrypoint = get_memory_entrypoint(".")
19
+ """
20
+
21
+ from __future__ import annotations
22
+
23
+ from hashlib import sha1
24
+ from pathlib import Path
25
+
26
+ from illusion.config.paths import get_data_dir
27
+
28
+
29
+ def get_project_memory_dir(cwd: str | Path) -> Path:
30
+ """获取项目持久化记忆目录
31
+
32
+ 目录名格式: {项目名}-{sha1哈希前12位}
33
+ 使用项目路径的哈希确保唯一性
34
+
35
+ Args:
36
+ cwd: 当前工作目录
37
+
38
+ Returns:
39
+ Path: 记忆目录的Path对象
40
+ """
41
+ path = Path(cwd).resolve() # 解析为绝对路径
42
+ digest = sha1(str(path).encode("utf-8")).hexdigest()[:12] # 计算哈希
43
+ memory_dir = get_data_dir() / "memory" / f"{path.name}-{digest}" # 构建目录路径
44
+ memory_dir.mkdir(parents=True, exist_ok=True) # 创建目录
45
+ return memory_dir # 返回目录
46
+
47
+
48
+ def get_memory_entrypoint(cwd: str | Path) -> Path:
49
+ """获取项目记忆入口点文件
50
+
51
+ Args:
52
+ cwd: 当前工作目录
53
+
54
+ Returns:
55
+ Path: MEMORY.md文件的Path对象
56
+ """
57
+ return get_project_memory_dir(cwd) / "MEMORY.md" # 返回入口点文件路径
@@ -0,0 +1,120 @@
1
+ """
2
+ 记忆文件扫描模块
3
+ ================
4
+
5
+ 本模块提供记忆文件的扫描和解析功能。
6
+
7
+ 主要功能:
8
+ - 扫描项目中的记忆Markdown文件
9
+ - 解析YAML frontmatter提取元数据
10
+ - 按修改时间排序返回记忆列表
11
+
12
+ 函数说明:
13
+ - scan_memory_files: 扫描记忆文件
14
+ - _parse_memory_file: 解析单个记忆文件
15
+
16
+ 使用示例:
17
+ >>> from illusion.memory import scan_memory_files
18
+ >>> headers = scan_memory_files(".", max_files=50)
19
+ """
20
+
21
+ from __future__ import annotations
22
+
23
+ from pathlib import Path
24
+
25
+ from illusion.memory.paths import get_project_memory_dir
26
+ from illusion.memory.types import MemoryHeader
27
+
28
+
29
+ def scan_memory_files(cwd: str | Path, *, max_files: int = 50) -> list[MemoryHeader]:
30
+ """扫描并返回记忆文件头,按最新修改时间排序
31
+
32
+ Args:
33
+ cwd: 当前工作目录
34
+ max_files: 最大返回文件数量
35
+
36
+ Returns:
37
+ list[MemoryHeader]: 按修改时间倒序排列的记忆头列表
38
+ """
39
+ memory_dir = get_project_memory_dir(cwd) # 获取记忆目录
40
+ headers: list[MemoryHeader] = [] # 初始化头列表
41
+ for path in memory_dir.glob("*.md"): # 遍历所有md文件
42
+ if path.name == "MEMORY.md": # 跳过索引文件
43
+ continue
44
+ try:
45
+ text = path.read_text(encoding="utf-8") # 读取文件内容
46
+ except OSError: # 读取失败则跳过
47
+ continue
48
+ header = _parse_memory_file(path, text) # 解析文件
49
+ headers.append(header) # 添加到列表
50
+ headers.sort(key=lambda item: item.modified_at, reverse=True) # 按时间倒序排序
51
+ return headers[:max_files] # 返回Top N结果
52
+
53
+
54
+ def _parse_memory_file(path: Path, content: str) -> MemoryHeader:
55
+ """解析记忆文件,提取YAML frontmatter中的元数据
56
+
57
+ 支持从frontmatter提取: name, description, type
58
+ 如果没有frontmatter,使用第一行非空非标题行作为description
59
+
60
+ Args:
61
+ path: 文件路径
62
+ content: 文件内容
63
+
64
+ Returns:
65
+ MemoryHeader: 解析后的记忆头
66
+ """
67
+ lines = content.splitlines() # 分割行
68
+ title = path.stem # 默认使用文件名作为标题
69
+ description = "" # 描述
70
+ memory_type = "" # 记忆类型
71
+ body_start = 0 # 内容起始行索引
72
+
73
+ # 解析YAML frontmatter (--- ... ---)
74
+ if lines and lines[0].strip() == "---": # 检查是否有frontmatter
75
+ for i, line in enumerate(lines[1:], 1): # 遍历内容行
76
+ if line.strip() == "---": # 找到结束标记
77
+ for fm_line in lines[1:i]: # 解析frontmatter
78
+ key, _, value = fm_line.partition(":") # 分割键值对
79
+ key = key.strip() # 清理键
80
+ value = value.strip().strip("'\"") # 清理值
81
+ if not value: # 跳过空值
82
+ continue
83
+ if key == "name": # 名称字段
84
+ title = value
85
+ elif key == "description": # 描述字段
86
+ description = value
87
+ elif key == "type": # 类型字段
88
+ memory_type = value
89
+ body_start = i + 1 # 内容从结束标记后开始
90
+ break
91
+
92
+ # 后备方案:第一行非空非frontmatter非标题行作为描述
93
+ desc_line_idx: int | None = None # 描述行索引
94
+ if not description: # 如果没有描述
95
+ for idx, line in enumerate(lines[body_start:body_start + 10], body_start): # 遍历前10���
96
+ stripped = line.strip() # 去除空白
97
+ if stripped and stripped != "---" and not stripped.startswith("#"): # 非空非标记非标题
98
+ description = stripped[:200] # 截取前200字符
99
+ desc_line_idx = idx # 记录行索引
100
+ break
101
+
102
+ # 从frontmatter之后的内容构建body preview
103
+ # 排除已用作description的行以保持搜索评分一致性
104
+ body_lines = [
105
+ line.strip() # 去除空白
106
+ for idx, line in enumerate(lines[body_start:], body_start)
107
+ if line.strip() # 非空行
108
+ and not line.strip().startswith("#") # 非标题行
109
+ and idx != desc_line_idx # 排除描述行
110
+ ]
111
+ body_preview = " ".join(body_lines)[:300] # 合并并截断
112
+
113
+ return MemoryHeader(
114
+ path=path, # 文件路径
115
+ title=title, # 标题
116
+ description=description, # 描述
117
+ modified_at=path.stat().st_mtime, # 修改时间
118
+ memory_type=memory_type, # 记忆类型
119
+ body_preview=body_preview, # 内容预览
120
+ )