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,236 @@
1
+ """
2
+ 团队创建工具
3
+ ============
4
+
5
+ 本模块提供 team_create 工具,用于创建多代理协作团队。
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ import json
11
+ import os
12
+ import time
13
+ from uuid import uuid4
14
+
15
+ from pydantic import BaseModel, Field
16
+
17
+ from illusion.state import AppStateStore
18
+ from illusion.swarm.team_helpers import (
19
+ TEAM_LEAD_NAME,
20
+ ensure_tasks_dir,
21
+ get_team_file_path,
22
+ read_team_file,
23
+ register_team_for_session_cleanup,
24
+ reset_task_list,
25
+ sanitize_name,
26
+ write_team_file,
27
+ )
28
+ from illusion.tools.base import BaseTool, ToolExecutionContext, ToolResult
29
+
30
+
31
+ class TeamCreateToolInput(BaseModel):
32
+ """team_create 输入参数。"""
33
+
34
+ team_name: str = Field(description="Name for the new team to create.")
35
+ description: str | None = Field(default=None, description="Team description/purpose.")
36
+ agent_type: str | None = Field(
37
+ default=None,
38
+ description=(
39
+ 'Type/role of the team lead (e.g., "researcher", "test-runner"). '
40
+ "Used for team file and inter-agent coordination."
41
+ ),
42
+ )
43
+
44
+
45
+ def _generate_unique_team_name(provided_name: str) -> str:
46
+ """生成唯一团队名(若已存在则回退到随机 slug)。"""
47
+ if read_team_file(provided_name) is None:
48
+ return provided_name
49
+ return f"team-{uuid4().hex[:8]}"
50
+
51
+
52
+ class TeamCreateTool(BaseTool):
53
+ """创建新的多代理团队。"""
54
+
55
+ name = "team_create"
56
+ description = """# TeamCreate
57
+
58
+ ## When to Use
59
+
60
+ Use this tool proactively whenever:
61
+ - The user explicitly asks to use a team, swarm, or group of agents
62
+ - The user mentions wanting agents to work together, coordinate, or collaborate
63
+ - A task is complex enough that it would benefit from parallel work by multiple agents (e.g., building a full-stack feature with frontend and backend work, refactoring a codebase while keeping tests passing, implementing a multi-step project with research, planning, and coding phases)
64
+
65
+ When in doubt about whether a task warrants a team, prefer spawning a team.
66
+
67
+ ## Choosing Agent Types for Teammates
68
+
69
+ When spawning teammates via the Agent tool, choose the `subagent_type` based on what tools the agent needs for its task. Each agent type has a different set of available tools — match the agent to the work:
70
+
71
+ - **Read-only agents** (e.g., Explore, Plan) cannot edit or write files. Only assign them research, search, or planning tasks. Never assign them implementation work.
72
+ - **Full-capability agents** (e.g., general-purpose) have access to all tools including file editing, writing, and bash. Use these for tasks that require making changes.
73
+ - **Custom agents** defined in `.illusion/agents/` may have their own tool restrictions. Check their descriptions to understand what they can and cannot do.
74
+
75
+ Always review the agent type descriptions and their available tools listed in the Agent tool prompt before selecting a `subagent_type` for a teammate.
76
+
77
+ Create a new team to coordinate multiple agents working on a project. Teams have a 1:1 correspondence with task lists (Team = TaskList).
78
+
79
+ ```json
80
+ {
81
+ "team_name": "my-project",
82
+ "description": "Working on feature X"
83
+ }
84
+ ```
85
+
86
+ This creates:
87
+ - A team file at `~/.illusion/teams/{team-name}/config.json`
88
+ - A corresponding task list directory at `~/.illusion/data/tasks/{team-name}/`
89
+
90
+ **Note**: If a team with the same name already exists, a random suffix is appended to ensure uniqueness (e.g., `my-project` may become `team-a1b2c3d4`). The actual name used is returned in the tool output.
91
+
92
+ ## Team Workflow
93
+
94
+ 1. **Create a team** with TeamCreate - this creates both the team and its task list
95
+ 2. **Create tasks** using the Task tools (TaskCreate, TaskList, etc.) - they automatically use the team's task list
96
+ 3. **Spawn teammates** using the Agent tool with `team_name` and `name` parameters to create teammates that join the team
97
+ 4. **Assign tasks** using TaskUpdate with `owner` to give tasks to idle teammates
98
+ 5. **Teammates work on assigned tasks** and mark them completed via TaskUpdate
99
+ 6. **Teammates go idle between turns** - after each turn, teammates automatically go idle and send a notification. IMPORTANT: Be patient with idle teammates! Don't comment on their idleness until it actually impacts your work.
100
+ 7. **Shutdown your team** - when the task is completed, gracefully shut down your teammates via `SendMessage` with a shutdown request, then call TeamDelete.
101
+
102
+ ## Task Ownership
103
+
104
+ Tasks are assigned using TaskUpdate with the `owner` parameter. Any agent can set or change task ownership via TaskUpdate.
105
+
106
+ ## Automatic Message Delivery
107
+
108
+ **IMPORTANT**: Messages from teammates are automatically delivered to you. You do NOT need to manually check your inbox.
109
+
110
+ When you spawn teammates:
111
+ - They will send you messages when they complete tasks or need help
112
+ - These messages appear automatically as new conversation turns (like user messages)
113
+ - If you're busy (mid-turn), messages are queued and delivered when your turn ends
114
+ - The UI shows a brief notification with the sender's name when messages are waiting
115
+
116
+ Messages will be delivered automatically.
117
+
118
+ When reporting on teammate messages, you do NOT need to quote the original message—it's already rendered to the user.
119
+
120
+ ## Teammate Idle State
121
+
122
+ Teammates go idle after every turn—this is completely normal and expected. A teammate going idle immediately after sending you a message does NOT mean they are done or unavailable. Idle simply means they are waiting for input.
123
+
124
+ - **Idle teammates can receive messages.** Sending a message to an idle teammate wakes them up and they will process it normally.
125
+ - **Idle notifications are automatic.** The system sends an idle notification whenever a teammate's turn ends. You do not need to react to idle notifications unless you want to assign new work or send a follow-up message.
126
+ - **Do not treat idle as an error.** A teammate sending a message and then going idle is the normal flow—they sent their message and are now waiting for a response.
127
+ - **Peer DM visibility.** When a teammate sends a DM to another teammate, a brief summary is included in their idle notification. This gives you visibility into peer collaboration without the full message content. You do not need to respond to these summaries — they are informational.
128
+
129
+ ## Discovering Team Members
130
+
131
+ Teammates can read the team config file to discover other team members:
132
+ - **Team config location**: `~/.illusion/teams/{team-name}/config.json`
133
+
134
+ The config file contains a `members` array with each teammate's:
135
+ - `name`: Human-readable name (**always use this** for messaging and task assignment)
136
+ - `agentId`: Unique identifier (for reference only - do not use for communication)
137
+ - `agentType`: Role/type of the agent
138
+
139
+ **IMPORTANT**: Always refer to teammates by their NAME (e.g., "team-lead", "researcher", "tester"). Names are used for:
140
+ - `to` when sending messages
141
+ - Identifying task owners
142
+
143
+ Example of reading team config:
144
+ ```
145
+ Use the Read tool to read ~/.illusion/teams/{team-name}/config.json
146
+ ```
147
+
148
+ ## Task List Coordination
149
+
150
+ Teams share a task list that all teammates can access at `~/.illusion/data/tasks/{team-name}/`.
151
+
152
+ Teammates should:
153
+ 1. Check TaskList periodically, **especially after completing each task**, to find available work or see newly unblocked tasks
154
+ 2. Claim unassigned, unblocked tasks with TaskUpdate (set `owner` to your name). **Prefer tasks in ID order** (lowest ID first) when multiple tasks are available, as earlier tasks often set up context for later ones
155
+ 3. Create new tasks with `TaskCreate` when identifying additional work
156
+ 4. Mark tasks as completed with `TaskUpdate` when done, then check TaskList for next work
157
+ 5. Coordinate with other teammates by reading the task list status
158
+ 6. If all available tasks are blocked, notify the team lead or help resolve blocking tasks
159
+
160
+ **IMPORTANT notes for communication with your team**:
161
+ - Do not use terminal tools to view your team's activity; always send a message to your teammates (and remember, refer to them by name).
162
+ - Your team cannot hear you if you do not use the SendMessage tool. Always send a message to your teammates if you are responding to them.
163
+ - Do NOT send structured JSON status messages like `{"type":"idle",...}` or `{"type":"task_completed",...}`. Just communicate in plain text when you need to message teammates.
164
+ - Use TaskUpdate to mark tasks completed.
165
+ - If you are an agent in the team, the system will automatically send idle notifications to the team lead when you stop.
166
+ """
167
+ input_model = TeamCreateToolInput
168
+
169
+ async def execute(self, arguments: TeamCreateToolInput, context: ToolExecutionContext) -> ToolResult:
170
+ team_name = arguments.team_name.strip()
171
+ if not team_name:
172
+ return ToolResult(output="team_name is required for team_create", is_error=True)
173
+
174
+ app_state_store = context.metadata.get("app_state_store")
175
+ if isinstance(app_state_store, AppStateStore):
176
+ existing_team = app_state_store.get().team_context
177
+ if isinstance(existing_team, dict) and existing_team.get("teamName"):
178
+ active_team = str(existing_team["teamName"])
179
+ return ToolResult(
180
+ output=(
181
+ f'Already leading team "{active_team}". '
182
+ "A leader can only manage one team at a time. "
183
+ "Use team_delete to end the current team before creating a new one."
184
+ ),
185
+ is_error=True,
186
+ )
187
+
188
+ final_team_name = _generate_unique_team_name(team_name)
189
+ lead_agent_id = f"{TEAM_LEAD_NAME}@{sanitize_name(final_team_name)}"
190
+ lead_agent_type = arguments.agent_type or TEAM_LEAD_NAME
191
+ team_file_path = str(get_team_file_path(final_team_name))
192
+ session_id = str(context.metadata.get("session_id") or "")
193
+
194
+ team_file = {
195
+ "name": final_team_name,
196
+ "description": arguments.description,
197
+ "createdAt": int(time.time() * 1000),
198
+ "leadAgentId": lead_agent_id,
199
+ "leadSessionId": session_id,
200
+ "members": [
201
+ {
202
+ "agentId": lead_agent_id,
203
+ "name": TEAM_LEAD_NAME,
204
+ "agentType": lead_agent_type,
205
+ "joinedAt": int(time.time() * 1000),
206
+ "tmuxPaneId": "",
207
+ "cwd": str(context.cwd),
208
+ "subscriptions": [],
209
+ }
210
+ ],
211
+ }
212
+
213
+ write_team_file(final_team_name, team_file)
214
+ register_team_for_session_cleanup(final_team_name)
215
+
216
+ task_list_id = sanitize_name(final_team_name)
217
+ reset_task_list(task_list_id)
218
+ ensure_tasks_dir(task_list_id)
219
+ os.environ["ILLUSION_TASK_LIST_ID"] = task_list_id
220
+
221
+ if isinstance(app_state_store, AppStateStore):
222
+ app_state_store.set(
223
+ team_context={
224
+ "teamName": final_team_name,
225
+ "teamFilePath": team_file_path,
226
+ "leadAgentId": lead_agent_id,
227
+ }
228
+ )
229
+
230
+ output = {
231
+ "team_name": final_team_name,
232
+ "team_file_path": team_file_path,
233
+ "lead_agent_id": lead_agent_id,
234
+ }
235
+ return ToolResult(output=json.dumps(output, ensure_ascii=False))
236
+
@@ -0,0 +1,104 @@
1
+ """
2
+ 团队删除工具
3
+ ============
4
+
5
+ 本模块提供 team_delete 工具,用于清理团队相关资源。
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ import json
11
+ import os
12
+
13
+ from pydantic import BaseModel
14
+
15
+ from illusion.state import AppStateStore
16
+ from illusion.swarm.team_helpers import (
17
+ TEAM_LEAD_NAME,
18
+ cleanup_team_directories,
19
+ read_team_file,
20
+ unregister_team_for_session_cleanup,
21
+ )
22
+ from illusion.tools.base import BaseTool, ToolExecutionContext, ToolResult
23
+
24
+
25
+ class TeamDeleteToolInput(BaseModel):
26
+ """team_delete 输入参数(无参数)。"""
27
+
28
+
29
+ class TeamDeleteTool(BaseTool):
30
+ """删除当前团队并清理关联目录。"""
31
+
32
+ name = "team_delete"
33
+ description = """# TeamDelete
34
+
35
+ Remove team and task directories when the swarm work is complete.
36
+
37
+ This operation:
38
+ - Removes the team directory (`~/.illusion/teams/{team-name}/`)
39
+ - Removes the task directory (`~/.illusion/data/tasks/{team-name}/`)
40
+ - Clears team context from the current session
41
+
42
+ **IMPORTANT**: TeamDelete will fail if the team still has active members. Gracefully terminate teammates via `SendMessage` first, then call TeamDelete after all teammates have shut down.
43
+
44
+ Use this when all teammates have finished their work and you want to clean up the team resources. The team name is automatically determined from the current session's team context.
45
+ """
46
+ input_model = TeamDeleteToolInput
47
+
48
+ async def execute(self, arguments: TeamDeleteToolInput, context: ToolExecutionContext) -> ToolResult:
49
+ del arguments
50
+ app_state_store = context.metadata.get("app_state_store")
51
+
52
+ team_name: str | None = None
53
+ if isinstance(app_state_store, AppStateStore):
54
+ team_context = app_state_store.get().team_context
55
+ if isinstance(team_context, dict):
56
+ raw = team_context.get("teamName")
57
+ if isinstance(raw, str) and raw.strip():
58
+ team_name = raw
59
+
60
+ if team_name:
61
+ team_file = read_team_file(team_name)
62
+ if team_file:
63
+ members = team_file.get("members", [])
64
+ if isinstance(members, list):
65
+ non_lead_members = [
66
+ member
67
+ for member in members
68
+ if isinstance(member, dict) and member.get("name") != TEAM_LEAD_NAME
69
+ ]
70
+ active_members = [
71
+ member
72
+ for member in non_lead_members
73
+ if member.get("isActive", member.get("is_active", True)) is not False
74
+ ]
75
+ if active_members:
76
+ member_names = ", ".join(str(member.get("name", "")) for member in active_members)
77
+ output = {
78
+ "success": False,
79
+ "message": (
80
+ f"Cannot cleanup team with {len(active_members)} active member(s): "
81
+ f"{member_names}. Use SendMessage to gracefully terminate teammates first."
82
+ ),
83
+ "team_name": team_name,
84
+ }
85
+ return ToolResult(output=json.dumps(output, ensure_ascii=False))
86
+
87
+ cleanup_team_directories(team_name)
88
+ unregister_team_for_session_cleanup(team_name)
89
+ os.environ.pop("ILLUSION_TASK_LIST_ID", None)
90
+
91
+ if isinstance(app_state_store, AppStateStore):
92
+ app_state_store.set(team_context=None)
93
+
94
+ output = {
95
+ "success": True,
96
+ "message": (
97
+ f'Cleaned up directories and worktrees for team "{team_name}"'
98
+ if team_name
99
+ else "No team name found, nothing to clean up"
100
+ ),
101
+ "team_name": team_name,
102
+ }
103
+ return ToolResult(output=json.dumps(output, ensure_ascii=False))
104
+
@@ -0,0 +1,198 @@
1
+ """
2
+ TODO写入工具模块
3
+ ================
4
+
5
+ 本模块提供编码会话结构化任务列表的管理功能。
6
+
7
+ 主要功能:
8
+ - 创建和管理结构化任务列表
9
+ - 跟踪当前编码会话的进度
10
+ - 展示任务的整体进度给用户
11
+
12
+ 类说明:
13
+ - TodoWriteToolInput: TODO写入工具输入参数
14
+ - TodoWriteTool: TODO写入工具类
15
+
16
+ 使用示例:
17
+ >>> # 通过全量替换更新任务列表
18
+ >>> # 工具将任务状态存入执行结果的元数据中
19
+ """
20
+
21
+ from __future__ import annotations
22
+
23
+ from pydantic import BaseModel, Field
24
+
25
+ from illusion.tools.base import BaseTool, ToolExecutionContext, ToolResult
26
+
27
+
28
+ class TodoItem(BaseModel):
29
+ """TODO项数据模型
30
+
31
+ Attributes:
32
+ content: 任务描述(祈使形式)
33
+ status: 任务状态(pending/in_progress/completed)
34
+ activeForm: 执行时显示的进行时形式
35
+ """
36
+
37
+ content: str = Field(min_length=1)
38
+ status: str = Field(pattern=r"^(pending|in_progress|completed)$")
39
+ activeForm: str = Field(min_length=1)
40
+
41
+
42
+ class TodoWriteToolInput(BaseModel):
43
+ """TODO写入工具的参数模型
44
+
45
+ Attributes:
46
+ todos: TODO项列表,每项包含content/status/activeForm
47
+ """
48
+
49
+ todos: list[TodoItem] = Field(description="List of todo items to update")
50
+
51
+
52
+ class TodoWriteTool(BaseTool):
53
+ """创建和管理当前编码会话的结构化任务列表。
54
+
55
+ 通过全量替换的方式更新任务列表,要删除某个任务只需在下一次调用中不再包含它。
56
+ 这有助于您跟踪进度、组织复杂任务,并展示给用户您的周到性。
57
+ 它还帮助用户了解任务进度和整体请求进度。
58
+
59
+ 何时使用此工具:
60
+ 在以下场景中主动使用此工具:
61
+
62
+ 1. 复杂的多步骤任务 - 当任务需要3个或更多不同步骤或操作时
63
+ 2. 非平凡和复杂的任务 - 需要仔细规划或多个操作的任务
64
+ 3. 用户明确请求TODO列表 - 当用户直接要求您使用TODO列表时
65
+ 4. 用户提供多个任务 - 当用户提供要做的事情列表时(用数字或逗号分隔)
66
+ 5. 收到新指令后 - 立即将用户需求捕获为TODO
67
+ 6. 开始任务时 - 在开始工作之前将其标记为in_progress。理想情况下,您应该一次只有一个TODO为in_progress
68
+ 7. 完成任务后 - 立即将其标记为completed,并在实施过程中添加发现的新后续任务
69
+
70
+ 何时不使用此工具:
71
+
72
+ 仅对简单任务跳过使用此工具:
73
+ - 只有单一、直接的任务
74
+ - 任务 trivial,跟踪它没有组织好处
75
+ - 任务可以在3个简单步骤内完成
76
+ - 任务纯粹是对话式或信息性的
77
+
78
+ 注意:如果只有一个简单的任务要处理,您不应该使用此工具。
79
+ 在这种情况下,您最好直接完成任务。
80
+
81
+ 任务状态和管理:
82
+
83
+ 1. **任务状态**:使用这些状态跟踪进度:
84
+ - pending: 任务尚未开始
85
+ - in_progress: 当前正在处理(一次限制为一个任务)
86
+ - completed: 任务成功完成
87
+
88
+ **重要**:任务描述必须有两种形式:
89
+ - content: 描述需要做什么的祈使形式(例如,"运行测试"、"构建项目")
90
+ - activeForm: 执行期间显示的现在进行时形式(例如,"正在运行测试"、"正在构建项目")
91
+
92
+ 2. **任务管理**:
93
+ - 工作时实时更新任务状态
94
+ - 完成后立即标记任务(不要批量完成)
95
+ - 任何时候必须恰好有一个任务为in_progress(不少于,也不多于)
96
+ - 在开始新任务之前完成当前任务
97
+ - 从列表中完全删除不再相关的任务
98
+
99
+ 3. **任务完成要求**:
100
+ - 仅在完全完成时才将任务标记为completed
101
+ - 如果遇到错误、阻塞或无法完成,请保持任务为in_progress
102
+ - 被阻塞时,创建描述需要解决的新任务
103
+ - 永远不要将任务标记为completed如果:
104
+ - 测试失败
105
+ - 实现不完整
106
+ - 遇到未解决的错误
107
+ - 找不到必要的文件或依赖
108
+
109
+ 4. **任务分解**:
110
+ - 创建具体、可操作的项目
111
+ - 将复杂任务分解为更小、可管理的步骤
112
+ - 使用清晰、描述性的任务名称
113
+ - 始终提供两种形式:
114
+ - content: "修复认证bug"
115
+ - activeForm: "正在修复认证bug"
116
+
117
+ 如有疑问,请使用此工具。主动的任务管理展示 attentive 并确保您成功完成所有要求。
118
+ """
119
+
120
+ name = "todo_write"
121
+ description = """Use this tool to create and manage a structured task list for your current coding session. This helps you track progress, organize complex tasks, and demonstrate thoroughness to the user.
122
+ It also helps the user understand the progress of the task and overall progress of their requests.
123
+
124
+ ## When to Use This Tool
125
+ Use this tool proactively in these scenarios:
126
+
127
+ 1. Complex multi-step tasks - When a task requires 3 or more distinct steps or actions
128
+ 2. Non-trivial and complex tasks - Tasks that require careful planning or multiple operations
129
+ 3. User explicitly requests todo list - When the user directly asks you to use the todo list
130
+ 4. User provides multiple tasks - When users provide a list of things to be done (numbered or comma-separated)
131
+ 5. After receiving new instructions - Immediately capture user requirements as todos
132
+ 6. When you start working on a task - Mark it as in_progress BEFORE beginning work. Ideally you should only have one todo as in_progress at a time
133
+ 7. After completing a task - Mark it as completed and add any new follow-up tasks discovered during implementation
134
+
135
+ ## When NOT to Use This Tool
136
+
137
+ Skip using this tool when:
138
+ 1. There is only a single, straightforward task
139
+ 2. The task is trivial and tracking it provides no organizational benefit
140
+ 3. The task can be completed in less than 3 trivial steps
141
+ 4. The task is purely conversational or informational
142
+
143
+ NOTE that you should not use this tool if there is only one trivial task to do. In this case you are better off just doing the task directly.
144
+
145
+ ## Task States and Management
146
+
147
+ 1. **Task States**: Use these states to track progress:
148
+ - pending: Task not yet started
149
+ - in_progress: Currently working on (limit to ONE task at a time)
150
+ - completed: Task finished successfully
151
+
152
+ **IMPORTANT**: Task descriptions must have two forms:
153
+ - content: The imperative form describing what needs to be done (e.g., "Run tests", "Build the project")
154
+ - activeForm: The present continuous form shown during execution (e.g., "Running tests", "Building the project")
155
+
156
+ 2. **Task Management**:
157
+ - Update task status in real-time as you work
158
+ - Mark tasks complete IMMEDIATELY after finishing (don't batch completions)
159
+ - Exactly ONE task must be in_progress at any time (not less, not more)
160
+ - Complete current tasks before starting new ones
161
+ - Remove tasks that are no longer relevant from the list entirely
162
+
163
+ 3. **Task Completion Requirements**:
164
+ - ONLY mark a task as completed when you have FULLY accomplished it
165
+ - If you encounter errors, blockers, or cannot finish, keep the task as in_progress
166
+ - When blocked, create a new task describing what needs to be resolved
167
+ - Never mark a task as completed if:
168
+ - Tests are failing
169
+ - Implementation is partial
170
+ - You encountered unresolved errors
171
+ - You couldn't find necessary files or dependencies
172
+
173
+ 4. **Task Breakdown**:
174
+ - Create specific, actionable items
175
+ - Break complex tasks into smaller, manageable steps
176
+ - Use clear, descriptive task names
177
+ - Always provide both forms:
178
+ - content: "Fix authentication bug"
179
+ - activeForm: "Fixing authentication bug"
180
+
181
+ When in doubt, use this tool. Being proactive with task management demonstrates attentiveness and ensures you complete all requirements successfully."""
182
+ input_model = TodoWriteToolInput
183
+
184
+ async def execute(self, arguments: TodoWriteToolInput, context: ToolExecutionContext) -> ToolResult:
185
+ """执行TODO写入操作
186
+
187
+ Args:
188
+ arguments: 工具输入参数
189
+ context: 工具执行上下文
190
+
191
+ Returns:
192
+ ToolResult: 执行结果
193
+ """
194
+ todos_data = [item.model_dump() for item in arguments.todos]
195
+ all_done = all(item.status == "completed" for item in arguments.todos)
196
+ if all_done and len(arguments.todos) >= 1:
197
+ todos_data = []
198
+ return ToolResult(output="Todos updated", metadata={"todos": todos_data})