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
@@ -0,0 +1,83 @@
1
+ """
2
+ 记忆搜索模块
3
+ ===========
4
+
5
+ 本模块提供基于启发式的记忆文件搜索功能。
6
+
7
+ 主要功能:
8
+ - 支持多语言token提取 (ASCII + 汉字)
9
+ - 根据元数据和内容相关性评分排序
10
+
11
+ 函数说明:
12
+ - find_relevant_memories: 查找相关记忆文件
13
+ - _tokenize: 提取搜索token
14
+
15
+ 使用示例:
16
+ >>> from illusion.memory import find_relevant_memories
17
+ >>> results = find_relevant_memories("测试查询", cwd=".", max_results=5)
18
+ """
19
+
20
+ from __future__ import annotations
21
+
22
+ import re
23
+ from pathlib import Path
24
+
25
+ from illusion.memory.scan import scan_memory_files
26
+ from illusion.memory.types import MemoryHeader
27
+
28
+
29
+ def find_relevant_memories(
30
+ query: str,
31
+ cwd: str | Path,
32
+ *,
33
+ max_results: int = 5,
34
+ ) -> list[MemoryHeader]:
35
+ """查找与查询相关的记忆文件
36
+
37
+ 评分权重:元数据匹配 2x,body内容匹配 1x,确保标注良好的记忆优先返回。
38
+
39
+ Args:
40
+ query: 搜索查询字符串
41
+ cwd: 当前工作目录
42
+ max_results: 最大返回结果数量
43
+
44
+ Returns:
45
+ list[MemoryHeader]: 按相关性排序的记忆文件列表
46
+ """
47
+ tokens = _tokenize(query) # 提取搜索token
48
+ if not tokens: # 无有效token则返回空列表
49
+ return []
50
+
51
+ scored: list[tuple[float, MemoryHeader]] = [] # 评分结果列表
52
+ for header in scan_memory_files(cwd, max_files=100): # 扫描记忆文件
53
+ meta = f"{header.title} {header.description}".lower() # 元数据文本
54
+ body = header.body_preview.lower() # 内容预览文本
55
+
56
+ # 元数据匹配权重2x,内容匹配权重1x
57
+ meta_hits = sum(1 for t in tokens if t in meta) # 元数据命中数
58
+ body_hits = sum(1 for t in tokens if t in body) # body命中数
59
+ score = meta_hits * 2.0 + body_hits # 计算总分
60
+ if score > 0: # 有匹配则加入评分列表
61
+ scored.append((score, header))
62
+
63
+ scored.sort(key=lambda item: (-item[0], -item[1].modified_at)) # 按分数和时间排序
64
+ return [header for _, header in scored[:max_results]] # 返回Top N结果
65
+
66
+
67
+ def _tokenize(text: str) -> set[str]:
68
+ """从文本中提取搜索token,同时处理ASCII和汉字
69
+
70
+ - ASCII单词token (3字符及以上)
71
+ - 汉字单字 (每个汉字独立表示含义)
72
+
73
+ Args:
74
+ text: 输入文本
75
+
76
+ Returns:
77
+ set[str]: token集合
78
+ """
79
+ # ASCII单词token (3+字符)
80
+ ascii_tokens = {t for t in re.findall(r"[A-Za-z0-9_]+", text.lower()) if len(t) >= 3}
81
+ # 汉字字符 (每个字符独立表达含义)
82
+ han_chars = set(re.findall(r"[\u4e00-\u9fff\u3400-\u4dbf]", text))
83
+ return ascii_tokens | han_chars # 返回合并后的token集合
@@ -0,0 +1,43 @@
1
+ """
2
+ 记忆数据类型模块
3
+ ==============
4
+
5
+ 本模块定义 IllusionCode 记忆系统的数据类型。
6
+
7
+ 主要功能:
8
+ - 定义记忆文件的元数据结构
9
+ - 支持 YAML frontmatter 解析
10
+
11
+ 类说明:
12
+ - MemoryHeader: 记忆文件元数据
13
+
14
+ 使用示例:
15
+ >>> from illusion.memory import MemoryHeader
16
+ >>> header = MemoryHeader(path=Path("test.md"), title="Test", description="A test", modified_at=1234567890.0)
17
+ """
18
+
19
+ from __future__ import annotations
20
+
21
+ from dataclasses import dataclass
22
+ from pathlib import Path
23
+
24
+
25
+ @dataclass(frozen=True)
26
+ class MemoryHeader:
27
+ """记忆文件的元数据信息
28
+
29
+ Attributes:
30
+ path: 记忆文件的路径
31
+ title: 记忆文件标题
32
+ description: 记忆文件描述
33
+ modified_at: 最后修改时间戳
34
+ memory_type: 记忆类型 (可选)
35
+ body_preview: 内容预览文本 (可选)
36
+ """
37
+
38
+ path: Path # 记忆文件路径
39
+ title: str # 标题
40
+ description: str # 描述
41
+ modified_at: float # 修改时间戳
42
+ memory_type: str = "" # 记忆类型
43
+ body_preview: str = "" # 内容预览
@@ -0,0 +1,15 @@
1
+ """
2
+ 输出样式模块导出
3
+ ============
4
+
5
+ 本模块导出 output_styles 子目录中的公共接口。
6
+
7
+ 导出内容:
8
+ - OutputStyle: 输出样式数据类
9
+ - get_output_styles_dir: 获取自定义输出样式目录
10
+ - load_output_styles: 加载输出样式
11
+ """
12
+
13
+ from illusion.output_styles.loader import OutputStyle, get_output_styles_dir, load_output_styles
14
+
15
+ __all__ = ["OutputStyle", "get_output_styles_dir", "load_output_styles"]
@@ -0,0 +1,64 @@
1
+ """
2
+ 输出样式加载模块
3
+ =============
4
+
5
+ 本模块提供输出样式的加载功能。
6
+
7
+ 主要功能:
8
+ - 获取自定义输出样式目录
9
+ - 加载内置和自定义输出样式
10
+
11
+ 类说明:
12
+ - OutputStyle: 命名输出样式数据类
13
+ - get_output_styles_dir: 获取自定义输出样式目录
14
+ - load_output_styles: 加载内置和自定义输出样式
15
+
16
+ 使用示例:
17
+ >>> from illusion.output_styles import load_output_styles
18
+ >>> # 加载输出样式
19
+ >>> styles = load_output_styles()
20
+ >>> for style in styles:
21
+ >>> print(style.name, style.source)
22
+ """
23
+
24
+ from __future__ import annotations
25
+
26
+ from dataclasses import dataclass
27
+ from pathlib import Path
28
+
29
+ from illusion.config.paths import get_config_dir
30
+
31
+
32
+ @dataclass(frozen=True)
33
+ class OutputStyle:
34
+ """命名输出样式。"""
35
+
36
+ name: str
37
+ content: str
38
+ source: str
39
+
40
+
41
+ def get_output_styles_dir() -> Path:
42
+ """返回自定义输出样式目录。"""
43
+ path = get_config_dir() / "output_styles"
44
+ path.mkdir(parents=True, exist_ok=True)
45
+ return path
46
+
47
+
48
+ def load_output_styles() -> list[OutputStyle]:
49
+ """加载内置和自定义输出样式。"""
50
+ # 内置样式
51
+ styles = [
52
+ OutputStyle(name="default", content="Standard rich console output.", source="builtin"),
53
+ OutputStyle(name="minimal", content="Very terse plain-text output.", source="builtin"),
54
+ ]
55
+ # 加载自定义样式
56
+ for path in sorted(get_output_styles_dir().glob("*.md")):
57
+ styles.append(
58
+ OutputStyle(
59
+ name=path.stem,
60
+ content=path.read_text(encoding="utf-8"),
61
+ source="user",
62
+ )
63
+ )
64
+ return styles
@@ -0,0 +1,39 @@
1
+ """
2
+ 权限模块
3
+ ========
4
+
5
+ 本模块提供 IllusionCode 权限检查和管理功能。
6
+
7
+ 主要组件:
8
+ - PermissionChecker: 权限检查器
9
+ - PermissionDecision: 权限决策
10
+ - PermissionMode: 权限模式
11
+
12
+ 使用示例:
13
+ >>> from illusion.permissions import PermissionChecker, PermissionMode
14
+ """
15
+
16
+ from __future__ import annotations
17
+
18
+ from typing import TYPE_CHECKING
19
+
20
+ if TYPE_CHECKING: # pragma: no cover
21
+ from illusion.permissions.checker import PermissionChecker, PermissionDecision
22
+ from illusion.permissions.modes import PermissionMode
23
+
24
+ __all__ = ["PermissionChecker", "PermissionDecision", "PermissionMode"]
25
+
26
+
27
+ def __getattr__(name: str):
28
+ if name in {"PermissionChecker", "PermissionDecision"}:
29
+ from illusion.permissions.checker import PermissionChecker, PermissionDecision
30
+
31
+ return {
32
+ "PermissionChecker": PermissionChecker,
33
+ "PermissionDecision": PermissionDecision,
34
+ }[name]
35
+ if name == "PermissionMode":
36
+ from illusion.permissions.modes import PermissionMode
37
+
38
+ return PermissionMode
39
+ raise AttributeError(name)
@@ -0,0 +1,174 @@
1
+ """
2
+ 权限检查模块
3
+ ============
4
+
5
+ 本模块实现权限检查功能,用于控制工具执行的权限。
6
+
7
+ 主要功能:
8
+ - 检查工具是否允许执行
9
+ - 支持路径级别的权限规则
10
+ - 支持命令级别的权限规则
11
+ - 根据权限模式决定是否需要用户确认
12
+
13
+ 类说明:
14
+ - PermissionDecision: 权限决策结果
15
+ - PathRule: 路径权限规则
16
+ - PermissionChecker: 权限检查器
17
+
18
+ 使用示例:
19
+ >>> from illusion.permissions import PermissionChecker, PermissionDecision, PermissionMode
20
+ >>> from illusion.config.settings import PermissionSettings
21
+ >>> checker = PermissionChecker(settings)
22
+ >>> decision = checker.evaluate("Bash", is_read_only=False, file_path="/path/to/file")
23
+ """
24
+
25
+ from __future__ import annotations
26
+
27
+ import fnmatch
28
+ import logging
29
+ from dataclasses import dataclass
30
+
31
+ from illusion.config.settings import PermissionSettings
32
+ from illusion.permissions.modes import PermissionMode
33
+
34
+ log = logging.getLogger(__name__)
35
+
36
+
37
+ @dataclass(frozen=True)
38
+ class PermissionDecision:
39
+ """权限决策结果
40
+
41
+ 表示检查工具调用是否允许执行的结果。
42
+
43
+ Attributes:
44
+ allowed: 是否允许执行该工具
45
+ requires_confirmation: 是否需要用户确认
46
+ reason: 决策原因说明
47
+ auto_blocked: 是否为系统自动阻止(如计划模式),而非用户显式拒绝
48
+ """
49
+
50
+ allowed: bool # 是否允许执行
51
+ requires_confirmation: bool = False # 是否需要用户确认
52
+ reason: str = "" # 决策原因
53
+ auto_blocked: bool = False # 系统自动阻止(计划模式等)
54
+
55
+
56
+ @dataclass(frozen=True)
57
+ class PathRule:
58
+ """基于 glob 模式的路径权限规则
59
+
60
+ 用于控制对特定路径的访问权限。
61
+
62
+ Attributes:
63
+ pattern: glob 模式字符串
64
+ allow: True 表示允许,False 表示拒绝
65
+ """
66
+
67
+ pattern: str # glob 模式
68
+ allow: bool # True = 允许, False = 拒绝
69
+
70
+
71
+ class PermissionChecker:
72
+ """权限检查器
73
+
74
+ 根据配置的权限模式和规则评估工具使用权限。
75
+
76
+ Attributes:
77
+ _settings: 权限设置对象
78
+ _path_rules: 解析后的路径规则列表
79
+
80
+ 使用示例:
81
+ >>> checker = PermissionChecker(settings)
82
+ >>> decision = checker.evaluate("Read", is_read_only=True)
83
+ """
84
+
85
+ def __init__(self, settings: PermissionSettings) -> None:
86
+ """初始化权限检查器
87
+
88
+ Args:
89
+ settings: 权限设置对象
90
+ """
91
+ self._settings = settings
92
+ # 从设置中解析路径规则
93
+ self._path_rules: list[PathRule] = []
94
+ for rule in getattr(settings, "path_rules", []):
95
+ pattern = getattr(rule, "pattern", None) or (rule.get("pattern") if isinstance(rule, dict) else None)
96
+ allow = getattr(rule, "allow", True) if not isinstance(rule, dict) else rule.get("allow", True)
97
+ if isinstance(pattern, str) and pattern.strip():
98
+ self._path_rules.append(PathRule(pattern=pattern.strip(), allow=allow))
99
+ else:
100
+ log.warning(
101
+ "跳过路径规则,pattern 字段缺失为空或非字符串: %r",
102
+ rule,
103
+ )
104
+
105
+ def evaluate(
106
+ self,
107
+ tool_name: str,
108
+ *,
109
+ is_read_only: bool,
110
+ file_path: str | None = None,
111
+ command: str | None = None,
112
+ ) -> PermissionDecision:
113
+ """评估工具是否允许执行
114
+
115
+ 根据权限模式和规则检查工具是否可以立即执行。
116
+
117
+ Args:
118
+ tool_name: 工具名称
119
+ is_read_only: 是否为只读工具
120
+ file_path: 相关的文件路径
121
+ command: 执行的命令字符串
122
+
123
+ Returns:
124
+ PermissionDecision: 权限决策结果
125
+ """
126
+ # 显式的工具拒绝列表
127
+ if tool_name in self._settings.denied_tools:
128
+ return PermissionDecision(allowed=False, reason=f"{tool_name} is explicitly denied")
129
+
130
+ # 显式的工具允许列表
131
+ if tool_name in self._settings.allowed_tools:
132
+ return PermissionDecision(allowed=True, reason=f"{tool_name} is explicitly allowed")
133
+
134
+ # 检查路径级别规则
135
+ if file_path and self._path_rules:
136
+ for rule in self._path_rules:
137
+ if fnmatch.fnmatch(file_path, rule.pattern):
138
+ if not rule.allow:
139
+ return PermissionDecision(
140
+ allowed=False,
141
+ reason=f"Path {file_path} matches deny rule: {rule.pattern}",
142
+ )
143
+
144
+ # 检查命令拒绝模式(例如拒绝 "rm -rf /")
145
+ if command:
146
+ for pattern in getattr(self._settings, "denied_commands", []):
147
+ if isinstance(pattern, str) and fnmatch.fnmatch(command, pattern):
148
+ return PermissionDecision(
149
+ allowed=False,
150
+ reason=f"Command matches deny pattern: {pattern}",
151
+ )
152
+
153
+ # 完全自动模式:允许一切
154
+ if self._settings.mode == PermissionMode.FULL_AUTO:
155
+ return PermissionDecision(allowed=True, reason="Auto mode allows all tools")
156
+
157
+ # 只读工具始终允许
158
+ if is_read_only:
159
+ return PermissionDecision(allowed=True, reason="read-only tools are allowed")
160
+
161
+ # 计划模式:阻止变更工具(自动阻止,不终止查询循环)
162
+ if self._settings.mode == PermissionMode.PLAN:
163
+ return PermissionDecision(
164
+ allowed=False,
165
+ reason="Plan mode blocks mutating tools until the user exits plan mode",
166
+ auto_blocked=True,
167
+ )
168
+
169
+ # 默认模式:变更工具需要确认
170
+ return PermissionDecision(
171
+ allowed=False,
172
+ requires_confirmation=True,
173
+ reason="Mutating tools require user confirmation in default mode",
174
+ )
@@ -0,0 +1,38 @@
1
+ """
2
+ 权限模式定义模块
3
+ ================
4
+
5
+ 本模块定义 IllusionCode 支持的权限模式。
6
+
7
+ 主要功能:
8
+ - DEFAULT 模式:变更工具需要用户确认
9
+ - PLAN 模式:阻止所有变更工具执行
10
+ - FULL_AUTO 模式:允许所有工具自动执行
11
+
12
+ 类说明:
13
+ - PermissionMode: 权限模式枚举
14
+
15
+ 使用示例:
16
+ >>> from illusion.permissions.modes import PermissionMode
17
+ >>> mode = PermissionMode.FULL_AUTO
18
+ """
19
+
20
+ from __future__ import annotations
21
+
22
+ from enum import Enum
23
+
24
+
25
+ class PermissionMode(str, Enum):
26
+ """权限模式枚举
27
+
28
+ 定义 Agent 执行工具时的权限级别。
29
+
30
+ Attributes:
31
+ DEFAULT: 默认模式,变更工具需要用户确认
32
+ PLAN: 计划模式,阻止所有变更工具
33
+ FULL_AUTO: 完全自动模式,允许所有工具
34
+ """
35
+
36
+ DEFAULT = "default" # 默认模式,变更工具需要用户确认
37
+ PLAN = "plan" # 计划模式,阻止所有变更工具
38
+ FULL_AUTO = "full_auto" # 完全自动模式
illusion/platforms.py ADDED
@@ -0,0 +1,148 @@
1
+ """
2
+ 平台和功能检测模块
3
+ =================
4
+
5
+ 本模块提供平台检测和功能能力查询功能。
6
+
7
+ 主要功能:
8
+ - 检测当前运行平台(macOS、Linux、Windows、WSL)
9
+ - 查询平台支持的功能特性
10
+
11
+ 类型说明:
12
+ - PlatformName: 平台名称字面量类型
13
+ - PlatformCapabilities: 平台功能能力数据类
14
+
15
+ 使用示例:
16
+ >>> from illusion.platforms import get_platform, get_platform_capabilities
17
+ >>> platform = get_platform()
18
+ >>> caps = get_platform_capabilities(platform)
19
+ >>> print(f"支持 POSIX shell: {caps.supports_posix_shell}")
20
+ """
21
+
22
+ from __future__ import annotations
23
+
24
+ import os # 操作系统相关功能
25
+ import platform # 平台信息获取
26
+ from dataclasses import dataclass # 数据类装饰器
27
+ from functools import lru_cache # 缓存装饰器
28
+ from typing import Literal, Mapping # 类型注解
29
+
30
+ # 平台名称类型定义
31
+ PlatformName = Literal["macos", "linux", "windows", "wsl", "unknown"]
32
+
33
+
34
+ @dataclass(frozen=True)
35
+ class PlatformCapabilities:
36
+ """平台功能能力数据类
37
+
38
+ 存储影响 shell、swarm 和沙箱决策的平台功能特性。
39
+
40
+ Attributes:
41
+ name: 平台名称
42
+ supports_posix_shell: 是否支持 POSIX shell(bash、zsh 等)
43
+ supports_native_windows_shell: 是否支持原生 Windows shell(PowerShell、CMD)
44
+ supports_tmux: 是否支持 tmux 会话管理
45
+ supports_swarm_mailbox: 是否支持 swarm 邮箱功能
46
+ supports_sandbox_runtime: 是否支持沙箱运行时
47
+ """
48
+
49
+ name: PlatformName # 平台名称
50
+ supports_posix_shell: bool # 是否支持 POSIX shell
51
+ supports_native_windows_shell: bool # 是否支持原生 Windows shell
52
+ supports_tmux: bool # 是否支持 tmux
53
+ supports_swarm_mailbox: bool # 是否支持 swarm 邮箱
54
+ supports_sandbox_runtime: bool # 是否支持沙箱运行时
55
+
56
+
57
+ def detect_platform(
58
+ *,
59
+ system_name: str | None = None,
60
+ release: str | None = None,
61
+ env: Mapping[str, str] | None = None,
62
+ ) -> PlatformName:
63
+ """检测并返回标准化平台名称
64
+
65
+ 通过检测系统信息判断当前运行平台,支持覆盖参数用于测试。
66
+
67
+ Args:
68
+ system_name: 系统名称覆盖(可选),默认自动检测
69
+ release: 内核版本覆盖(可选),默认自动检测
70
+ env: 环境变量映射(可选),默认使用 os.environ
71
+
72
+ Returns:
73
+ PlatformName: 标准化后的平台名称(macos、linux、windows、wsl、unknown)
74
+ """
75
+ env_map = env or os.environ # 获取环境变量映射
76
+ system = (system_name or platform.system()).lower() # 获取系统名称并转小写
77
+ kernel_release = (release or platform.release()).lower() # 获取内核版本并转小写
78
+
79
+ # Darwin 系统返回 macOS
80
+ if system == "darwin":
81
+ return "macos"
82
+ # Windows 系统返回 windows
83
+ if system == "windows":
84
+ return "windows"
85
+ # Linux 系统检测 WSL
86
+ if system == "linux":
87
+ # 检测 WSL 特征:microsoft 字符串或 WSL 环境变量
88
+ if "microsoft" in kernel_release or env_map.get("WSL_DISTRO_NAME") or env_map.get("WSL_INTEROP"):
89
+ return "wsl"
90
+ return "linux"
91
+ # 未知平台
92
+ return "unknown"
93
+
94
+
95
+ @lru_cache(maxsize=1)
96
+ def get_platform() -> PlatformName:
97
+ """返回当前进程的检测平台
98
+
99
+ 使用 LRU 缓存优化重复调用性能,缓存大小为 1。
100
+
101
+ Returns:
102
+ PlatformName: 检测到的平台名称
103
+ """
104
+ return detect_platform() # 调用平台检测函数
105
+
106
+
107
+ def get_platform_capabilities(platform_name: PlatformName | None = None) -> PlatformCapabilities:
108
+ """返回指定平台的功能能力矩阵
109
+
110
+ 根据平台名称返回对应的功能能力,包括 shell 支持、tmux 支持等信息。
111
+
112
+ Args:
113
+ platform_name: 平台名称(可选),默认自动检测当前平台
114
+
115
+ Returns:
116
+ PlatformCapabilities: 平台功能能力对象
117
+ """
118
+ name = platform_name or get_platform() # 获取平台名称,未指定则自动检测
119
+ # POSIX 平台(macOS、Linux、WSL)
120
+ if name in {"macos", "linux", "wsl"}:
121
+ return PlatformCapabilities(
122
+ name=name, # 平台名称
123
+ supports_posix_shell=True, # 支持 POSIX shell
124
+ supports_native_windows_shell=False, # 不支持原生 Windows shell
125
+ supports_tmux=True, # 支持 tmux
126
+ supports_swarm_mailbox=True, # 支持 swarm 邮箱
127
+ supports_sandbox_runtime=True, # 支持沙箱运行时
128
+ )
129
+ # Windows 平台
130
+ if name == "windows":
131
+ return PlatformCapabilities(
132
+ name=name, # 平台名称
133
+ supports_posix_shell=False, # 不支持 POSIX shell
134
+ supports_native_windows_shell=True, # 支持原生 Windows shell
135
+ supports_tmux=False, # 不支持 tmux
136
+ supports_swarm_mailbox=False, # 不支持 swarm 邮箱
137
+ supports_sandbox_runtime=False, # 不支持沙箱运行时
138
+ )
139
+ # 未知平台
140
+ return PlatformCapabilities(
141
+ name=name, # 平台名称
142
+ supports_posix_shell=False, # 不支持 POSIX shell
143
+ supports_native_windows_shell=False, # 不支持原生 Windows shell
144
+ supports_tmux=False, # 不支持 tmux
145
+ supports_swarm_mailbox=False, # 不支持 swarm 邮箱
146
+ supports_sandbox_runtime=False, # 不支持沙箱运行时
147
+ )
148
+
@@ -0,0 +1,71 @@
1
+ """
2
+ 插件模块
3
+ ========
4
+
5
+ 本模块提供 IllusionCode 插件系统的加载和管理功能。
6
+
7
+ 主要组件:
8
+ - PluginManifest: 插件清单
9
+ - LoadedPlugin: 已加载插件
10
+ - discover_plugin_paths: 发现插件路径
11
+ - get_project_plugins_dir: 获取项目插件目录
12
+ - get_user_plugins_dir: 获取用户插件目录
13
+ - load_plugins: 加载插件
14
+ - install_plugin_from_path: 从路径安装插件
15
+ - uninstall_plugin: 卸载插件
16
+
17
+ 使用示例:
18
+ >>> from illusion.plugins import load_plugins, get_user_plugins_dir
19
+ """
20
+
21
+ from __future__ import annotations
22
+
23
+ from typing import TYPE_CHECKING
24
+
25
+ if TYPE_CHECKING: # pragma: no cover
26
+ from illusion.plugins.schemas import PluginManifest
27
+ from illusion.plugins.types import LoadedPlugin
28
+
29
+ __all__ = [
30
+ "LoadedPlugin",
31
+ "PluginManifest",
32
+ "discover_plugin_paths",
33
+ "get_project_plugins_dir",
34
+ "get_user_plugins_dir",
35
+ "install_plugin_from_path",
36
+ "load_plugins",
37
+ "uninstall_plugin",
38
+ ]
39
+
40
+
41
+ def __getattr__(name: str):
42
+ if name in {"discover_plugin_paths", "get_project_plugins_dir", "get_user_plugins_dir", "load_plugins"}:
43
+ from illusion.plugins.loader import (
44
+ discover_plugin_paths,
45
+ get_project_plugins_dir,
46
+ get_user_plugins_dir,
47
+ load_plugins,
48
+ )
49
+
50
+ return {
51
+ "discover_plugin_paths": discover_plugin_paths,
52
+ "get_project_plugins_dir": get_project_plugins_dir,
53
+ "get_user_plugins_dir": get_user_plugins_dir,
54
+ "load_plugins": load_plugins,
55
+ }[name]
56
+ if name in {"install_plugin_from_path", "uninstall_plugin"}:
57
+ from illusion.plugins.installer import install_plugin_from_path, uninstall_plugin
58
+
59
+ return {
60
+ "install_plugin_from_path": install_plugin_from_path,
61
+ "uninstall_plugin": uninstall_plugin,
62
+ }[name]
63
+ if name == "PluginManifest":
64
+ from illusion.plugins.schemas import PluginManifest
65
+
66
+ return PluginManifest
67
+ if name == "LoadedPlugin":
68
+ from illusion.plugins.types import LoadedPlugin
69
+
70
+ return LoadedPlugin
71
+ raise AttributeError(name)
File without changes