@ai-setting/roy-agent-core 1.5.15-test → 1.5.17-beta.1

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 (141) hide show
  1. package/dist/config/index.d.ts +1250 -0
  2. package/dist/config/index.js +32 -0
  3. package/dist/env/agent/index.d.ts +2279 -0
  4. package/dist/env/agent/index.js +24 -0
  5. package/dist/env/commands/index.d.ts +1131 -0
  6. package/dist/env/commands/index.js +14 -0
  7. package/dist/env/debug/formatters/index.d.ts +236 -0
  8. package/dist/env/debug/formatters/index.js +11 -0
  9. package/dist/env/debug/index.d.ts +1652 -0
  10. package/dist/env/debug/index.js +26 -0
  11. package/dist/env/hook/index.d.ts +279 -0
  12. package/dist/env/hook/index.js +29 -0
  13. package/dist/env/index.d.ts +3481 -0
  14. package/dist/env/index.js +82 -0
  15. package/dist/env/llm/index.d.ts +1760 -0
  16. package/dist/env/llm/index.js +40 -0
  17. package/dist/env/log-trace/index.d.ts +1574 -0
  18. package/dist/env/log-trace/index.js +83 -0
  19. package/dist/env/mcp/index.d.ts +1331 -0
  20. package/dist/env/mcp/index.js +39 -0
  21. package/dist/env/mcp/tool/index.d.ts +183 -0
  22. package/dist/env/mcp/tool/index.js +14 -0
  23. package/dist/env/memory/built-in/index.d.ts +232 -0
  24. package/dist/env/memory/built-in/index.js +11 -0
  25. package/dist/env/memory/index.d.ts +1799 -0
  26. package/dist/env/memory/index.js +56 -0
  27. package/dist/env/memory/plugin/index.d.ts +747 -0
  28. package/dist/env/memory/plugin/index.js +36 -0
  29. package/dist/env/prompt/index.d.ts +1164 -0
  30. package/dist/env/prompt/index.js +20 -0
  31. package/dist/env/session/index.d.ts +1908 -0
  32. package/dist/env/session/index.js +25 -0
  33. package/dist/env/session/storage/index.d.ts +564 -0
  34. package/dist/env/session/storage/index.js +18 -0
  35. package/dist/env/skill/index.d.ts +1266 -0
  36. package/dist/env/skill/index.js +34 -0
  37. package/dist/env/skill/tool/index.d.ts +193 -0
  38. package/dist/env/skill/tool/index.js +9 -0
  39. package/dist/env/task/delegate/index.d.ts +1612 -0
  40. package/dist/env/task/delegate/index.js +18 -0
  41. package/dist/env/task/events/index.d.ts +171 -0
  42. package/dist/env/task/events/index.js +7 -0
  43. package/dist/env/task/hooks/index.d.ts +624 -0
  44. package/dist/env/task/hooks/index.js +7 -0
  45. package/dist/env/task/index.d.ts +1553 -0
  46. package/dist/env/task/index.js +34 -0
  47. package/dist/env/task/plugins/index.d.ts +466 -0
  48. package/dist/env/task/plugins/index.js +23 -0
  49. package/dist/env/task/storage/index.d.ts +241 -0
  50. package/dist/env/task/storage/index.js +14 -0
  51. package/dist/env/task/tools/index.d.ts +1485 -0
  52. package/dist/env/task/tools/index.js +17 -0
  53. package/dist/env/task/tools/operation/index.d.ts +1484 -0
  54. package/dist/env/task/tools/operation/index.js +15 -0
  55. package/dist/env/tool/built-in/index.d.ts +218 -0
  56. package/dist/env/tool/built-in/index.js +25 -0
  57. package/dist/env/tool/index.d.ts +1396 -0
  58. package/dist/env/tool/index.js +39 -0
  59. package/dist/env/workflow/decorators/index.d.ts +2161 -0
  60. package/dist/env/workflow/decorators/index.js +27 -0
  61. package/dist/env/workflow/engine/index.d.ts +3453 -0
  62. package/dist/env/workflow/engine/index.js +28 -0
  63. package/dist/env/workflow/index.d.ts +3546 -0
  64. package/dist/env/workflow/index.js +136 -0
  65. package/dist/env/workflow/nodes/index.d.ts +2092 -0
  66. package/dist/env/workflow/nodes/index.js +19 -0
  67. package/dist/env/workflow/service/index.d.ts +227 -0
  68. package/dist/env/workflow/service/index.js +13 -0
  69. package/dist/env/workflow/storage/index.d.ts +165 -0
  70. package/dist/env/workflow/storage/index.js +27 -0
  71. package/dist/env/workflow/tools/index.d.ts +416 -0
  72. package/dist/env/workflow/tools/index.js +159 -0
  73. package/dist/env/workflow/types/index.d.ts +2255 -0
  74. package/dist/env/workflow/types/index.js +98 -0
  75. package/dist/env/workflow/utils/index.d.ts +2031 -0
  76. package/dist/env/workflow/utils/index.js +637 -0
  77. package/dist/index.d.ts +7858 -0
  78. package/dist/index.js +399 -0
  79. package/dist/shared/@ai-setting/roy-agent-core-0rtxwr28.js +258 -0
  80. package/dist/shared/@ai-setting/roy-agent-core-0vbdz0x7.js +36 -0
  81. package/dist/shared/@ai-setting/roy-agent-core-1akcqxj9.js +349 -0
  82. package/dist/shared/@ai-setting/roy-agent-core-1ce3fqrk.js +117 -0
  83. package/dist/shared/@ai-setting/roy-agent-core-2dhd60aw.js +11 -0
  84. package/dist/shared/@ai-setting/roy-agent-core-3jywqmdd.js +393 -0
  85. package/dist/shared/@ai-setting/roy-agent-core-3rr5k71j.js +200 -0
  86. package/dist/shared/@ai-setting/roy-agent-core-44hnfb02.js +299 -0
  87. package/dist/shared/@ai-setting/roy-agent-core-4t40mkpv.js +206 -0
  88. package/dist/shared/@ai-setting/roy-agent-core-4txzpsbt.js +393 -0
  89. package/dist/shared/@ai-setting/roy-agent-core-5x94xmt6.js +350 -0
  90. package/dist/shared/@ai-setting/roy-agent-core-69jskqjg.js +180 -0
  91. package/dist/shared/@ai-setting/roy-agent-core-6kvtahqv.js +408 -0
  92. package/dist/shared/@ai-setting/roy-agent-core-7fgf85wc.js +284 -0
  93. package/dist/shared/@ai-setting/roy-agent-core-81w1963m.js +762 -0
  94. package/dist/shared/@ai-setting/roy-agent-core-8gxth0eh.js +10 -0
  95. package/dist/shared/@ai-setting/roy-agent-core-92z6t4he.js +14 -0
  96. package/dist/shared/@ai-setting/roy-agent-core-93zfb3r1.js +922 -0
  97. package/dist/shared/@ai-setting/roy-agent-core-9yxb3ty9.js +15 -0
  98. package/dist/shared/@ai-setting/roy-agent-core-b0x5dda6.js +1130 -0
  99. package/dist/shared/@ai-setting/roy-agent-core-bcbqy27c.js +14 -0
  100. package/dist/shared/@ai-setting/roy-agent-core-bvr1761x.js +653 -0
  101. package/dist/shared/@ai-setting/roy-agent-core-ctdhjv68.js +93 -0
  102. package/dist/shared/@ai-setting/roy-agent-core-d7cyjkf7.js +872 -0
  103. package/dist/shared/@ai-setting/roy-agent-core-dh9d7a3m.js +11 -0
  104. package/dist/shared/@ai-setting/roy-agent-core-e25xkv53.js +64 -0
  105. package/dist/shared/@ai-setting/roy-agent-core-eajcvp4e.js +378 -0
  106. package/dist/shared/@ai-setting/roy-agent-core-f7q2x5z6.js +492 -0
  107. package/dist/shared/@ai-setting/roy-agent-core-fs0mn2jk.js +52 -0
  108. package/dist/shared/@ai-setting/roy-agent-core-g1s2h0e5.js +171 -0
  109. package/dist/shared/@ai-setting/roy-agent-core-g99pxzn5.js +862 -0
  110. package/dist/shared/@ai-setting/roy-agent-core-gbqcyegm.js +1387 -0
  111. package/dist/shared/@ai-setting/roy-agent-core-gjq1yk68.js +208 -0
  112. package/dist/shared/@ai-setting/roy-agent-core-gq20wsgv.js +139 -0
  113. package/dist/shared/@ai-setting/roy-agent-core-gwc4h96n.js +534 -0
  114. package/dist/shared/@ai-setting/roy-agent-core-jfh9q2qh.js +204 -0
  115. package/dist/shared/@ai-setting/roy-agent-core-jvatggbb.js +603 -0
  116. package/dist/shared/@ai-setting/roy-agent-core-kkbwepqb.js +97 -0
  117. package/dist/shared/@ai-setting/roy-agent-core-pjr12nnd.js +587 -0
  118. package/dist/shared/@ai-setting/roy-agent-core-psv4v63c.js +176 -0
  119. package/dist/shared/@ai-setting/roy-agent-core-psvxt4c9.js +60 -0
  120. package/dist/shared/@ai-setting/roy-agent-core-qqceba6k.js +442 -0
  121. package/dist/shared/@ai-setting/roy-agent-core-qxhq8ven.js +57 -0
  122. package/dist/shared/@ai-setting/roy-agent-core-qxnbvgwe.js +66 -0
  123. package/dist/shared/@ai-setting/roy-agent-core-r9ezzemr.js +10 -0
  124. package/dist/shared/@ai-setting/roy-agent-core-rhmtwnw1.js +267 -0
  125. package/dist/shared/@ai-setting/roy-agent-core-rvv6ydff.js +584 -0
  126. package/dist/shared/@ai-setting/roy-agent-core-rvxg1wps.js +102 -0
  127. package/dist/shared/@ai-setting/roy-agent-core-satmq6sh.js +549 -0
  128. package/dist/shared/@ai-setting/roy-agent-core-sx7wsvnn.js +15 -0
  129. package/dist/shared/@ai-setting/roy-agent-core-t94ktchq.js +213 -0
  130. package/dist/shared/@ai-setting/roy-agent-core-vf215qfv.js +812 -0
  131. package/dist/shared/@ai-setting/roy-agent-core-vkz81f7v.js +1316 -0
  132. package/dist/shared/@ai-setting/roy-agent-core-vn2bc59q.js +1205 -0
  133. package/dist/shared/@ai-setting/roy-agent-core-wa1kzqky.js +328 -0
  134. package/dist/shared/@ai-setting/roy-agent-core-wft9ra24.js +20 -0
  135. package/dist/shared/@ai-setting/roy-agent-core-wrcy0h6z.js +2098 -0
  136. package/dist/shared/@ai-setting/roy-agent-core-xq8hhqb8.js +419 -0
  137. package/dist/shared/@ai-setting/roy-agent-core-xs5rsgat.js +368 -0
  138. package/dist/shared/@ai-setting/roy-agent-core-zbkpc41z.js +377 -0
  139. package/dist/shared/@ai-setting/roy-agent-core-zgypchmt.js +172 -0
  140. package/dist/shared/@ai-setting/roy-agent-core-zpn0bqa8.js +103 -0
  141. package/package.json +29 -8
@@ -0,0 +1,812 @@
1
+ import {
2
+ TaskHookPoints
3
+ } from "./roy-agent-core-92z6t4he.js";
4
+ import {
5
+ globalHookManager
6
+ } from "./roy-agent-core-gjq1yk68.js";
7
+ import {
8
+ createLogger,
9
+ init_logger
10
+ } from "./roy-agent-core-44hnfb02.js";
11
+
12
+ // src/env/task/delegate/delegate-tool.ts
13
+ init_logger();
14
+ import { z } from "zod";
15
+ var logger = createLogger("task:delegate");
16
+ var BackgroundTaskEventTypes = {
17
+ STARTED: "task.background.started",
18
+ PROGRESS: "task.background.progress",
19
+ COMPLETED: "task.background.completed",
20
+ FAILED: "task.background.failed",
21
+ TIMEOUT: "task.background.timeout",
22
+ STOPPED: "task.background.stopped"
23
+ };
24
+ var builtInSubAgents = [
25
+ {
26
+ id: "general",
27
+ name: "general",
28
+ mode: "subagent",
29
+ description: "General-purpose agent for researching complex questions and executing multi-step tasks.",
30
+ promptOverride: `You are a subagent created by the main agent to handle a specific task.
31
+
32
+ ## Your Role
33
+ - You were created to handle: {task_description}
34
+ - Complete this task. That's your entire purpose.
35
+ - You are NOT the main agent. Don't try to be.
36
+
37
+ ## Task Context Awareness (Required Behavior)
38
+
39
+ **IMPORTANT: Before starting any work, you MUST gather task context to avoid working with outdated or missing information.**
40
+
41
+ 1. **Read task details first**: Use \`task_get\` to read the task's:
42
+ - \`description\`: Detailed description of what needs to be done
43
+ - \`goals_and_expected_deliverables\`: Clear success criteria and expected outputs
44
+ - \`current_status\`: Current work progress
45
+ - \`parent_task_id\`: If exists, this is a sub-task
46
+
47
+ 2. **Read recent operations**: Use \`task_operation_list\` to get the last ~15 operation records
48
+ - These provide history, progress, decisions, and context from previous work
49
+
50
+ 3. **Read parent task context** (if \`parent_task_id\` exists):
51
+ - Use \`task_get\` to read the parent task's description and goals
52
+ - Use \`task_operation_list\` to get parent's recent operations
53
+ - This forms the overall task background and ensures alignment
54
+
55
+ **Why this matters**:
56
+ - The main agent may have made critical decisions recorded in operations
57
+ - Parent task goals provide the broader context for your sub-task
58
+ - Without this context, you risk working on wrong/outdated goals
59
+
60
+ ## Rules
61
+ 1. **Gather context first** - Always read task details and operations before starting
62
+ 2. **Stay focused** - Do your assigned task, nothing else
63
+ 3. **Complete the task** - Your final message will be automatically reported to the main agent
64
+ 4. **Don't initiate** - No heartbeats, no proactive actions, no side quests
65
+ 5. **Be ephemeral** - You may be terminated after task completion. That's fine.
66
+ 6. **No nested delegation** - Do NOT use delegate_task or stop_task tools. Complete the task yourself.
67
+
68
+ ## Execution
69
+ - Use the available tools to complete the task
70
+ - If you need more information, ask the main agent through the result
71
+ - Return a clear summary of what you did and the results`,
72
+ deniedTools: ["delegate_task", "stop_task"]
73
+ },
74
+ {
75
+ id: "explore",
76
+ name: "explore",
77
+ mode: "subagent",
78
+ description: "Fast agent specialized for exploring codebases, finding files, and searching for patterns.",
79
+ allowedTools: ["glob", "grep", "read", "bash"],
80
+ deniedTools: ["delegate_task", "stop_task"]
81
+ },
82
+ {
83
+ id: "file_agent",
84
+ name: "file_agent",
85
+ mode: "subagent",
86
+ description: "File operation expert, skilled at reading, writing, searching and organizing files.",
87
+ allowedTools: ["file_read", "file_write", "file_glob", "grep", "glob", "read"],
88
+ deniedTools: ["delegate_task", "stop_task"]
89
+ },
90
+ {
91
+ id: "web_search_agent",
92
+ name: "web_search_agent",
93
+ mode: "subagent",
94
+ description: "Web search expert, using Exa search engine to get latest information.",
95
+ allowedTools: ["exa_web_search_exa"],
96
+ deniedTools: ["delegate_task", "stop_task"]
97
+ }
98
+ ];
99
+ function getSubAgentSpec(id) {
100
+ return builtInSubAgents.find((agent) => agent.id === id);
101
+ }
102
+ function getSubAgentToolDescription() {
103
+ return builtInSubAgents.map((agent) => `- ${agent.id}: ${agent.description}`).join(`
104
+ `);
105
+ }
106
+ function ensureSubAgentRegistered(agentComponent, subagentType, basePrompt, subAgent, deniedTools) {
107
+ let agentInstance = agentComponent.getAgent(subagentType);
108
+ if (!agentInstance) {
109
+ const agentConfig = {
110
+ type: "sub",
111
+ systemPrompt: basePrompt
112
+ };
113
+ if (subAgent?.allowedTools && subAgent.allowedTools.length > 0) {
114
+ agentConfig.allowedTools = subAgent.allowedTools;
115
+ }
116
+ if (deniedTools.length > 0) {
117
+ agentConfig.deniedTools = deniedTools;
118
+ }
119
+ agentInstance = agentComponent.registerAgent(subagentType, agentConfig);
120
+ logger.debug(`[delegate] Registered subagent: ${subagentType}`);
121
+ }
122
+ return agentInstance;
123
+ }
124
+ var DelegateToolParameters = z.object({
125
+ description: z.string().describe("A short (3-5 words) description of the task"),
126
+ prompt: z.string().describe("The task for the agent to perform"),
127
+ subagent_type: z.string().describe("The type of specialized agent to use for this task").default("general"),
128
+ background: z.boolean().describe("Whether to run the task in background. If true, returns immediately and notifies when complete (default: false)").default(false),
129
+ timeout: z.number().describe("Task timeout in milliseconds. If set, task will be terminated after timeout (optional)").optional(),
130
+ cleanup: z.enum(["delete", "keep"]).describe("Whether to delete sub session after completion. 'delete' removes the session, 'keep' retains it (default: keep)").default("keep").optional(),
131
+ task_id: z.number().describe("Optional task ID to associate with this delegate task, for tracking in operation records").optional(),
132
+ reason: z.string().describe("Brief reason for calling this tool (max 30 chars, e.g., 'Delegate refactor task')").optional()
133
+ });
134
+ var DEFAULT_TIMEOUT = 900000;
135
+ var PROGRESS_INTERVAL = 120000;
136
+
137
+ class BackgroundTaskManager {
138
+ env;
139
+ tasks = new Map;
140
+ abortControllers = new Map;
141
+ progressTimers = new Map;
142
+ constructor(env) {
143
+ this.env = env;
144
+ }
145
+ getSessionComponent() {
146
+ return this.env?.getComponent?.("session");
147
+ }
148
+ publishBackgroundEvent(type, payload, parentSessionId) {
149
+ if (this.env?.pushEnvEvent) {
150
+ this.env.pushEnvEvent({
151
+ type,
152
+ payload,
153
+ metadata: {
154
+ source: "task.background",
155
+ trigger_session_id: parentSessionId
156
+ }
157
+ });
158
+ logger.info(`[BackgroundTaskManager] Event published: ${type}`);
159
+ }
160
+ }
161
+ async createTask(options) {
162
+ const { parentSessionId, description, prompt, subagentType, timeout, cleanup, taskId } = options;
163
+ const taskIdGen = `task_${Date.now()}_${Math.random().toString(36).slice(2, 11)}`;
164
+ const sessionComponent = this.getSessionComponent();
165
+ if (!sessionComponent) {
166
+ throw new Error("SessionComponent not found");
167
+ }
168
+ const parentSession = await sessionComponent.get(parentSessionId);
169
+ if (!parentSession) {
170
+ throw new Error(`Parent session not found: ${parentSessionId}`);
171
+ }
172
+ const metadata = {
173
+ subagent_type: subagentType,
174
+ created_by: "subagent",
175
+ task_description: description
176
+ };
177
+ if (taskId) {
178
+ metadata.task_id = taskId;
179
+ }
180
+ const subSession = await sessionComponent.create({
181
+ title: `${description} (@${subagentType} subagent)`,
182
+ metadata
183
+ });
184
+ if (!subSession) {
185
+ throw new Error("Failed to create sub-session");
186
+ }
187
+ const abortController = new AbortController;
188
+ const task = {
189
+ id: taskIdGen,
190
+ subSessionId: subSession.id,
191
+ parentSessionId,
192
+ description,
193
+ subagentType,
194
+ status: "pending",
195
+ createdAt: Date.now(),
196
+ abortController,
197
+ taskId
198
+ };
199
+ this.tasks.set(taskIdGen, task);
200
+ this.abortControllers.set(taskIdGen, abortController);
201
+ const startedPayload = {
202
+ backgroundTaskId: taskIdGen,
203
+ subSessionId: subSession.id,
204
+ parentSessionId,
205
+ description,
206
+ subagentType,
207
+ associatedTaskId: taskId
208
+ };
209
+ this.publishBackgroundEvent(BackgroundTaskEventTypes.STARTED, startedPayload, parentSessionId);
210
+ this.executeTask(taskIdGen, prompt, timeout, cleanup, parentSessionId).catch((err) => {
211
+ logger.error(`[BackgroundTaskManager] executeTask unhandled rejection`, {
212
+ taskId: taskIdGen,
213
+ error: err instanceof Error ? err.message : String(err)
214
+ });
215
+ });
216
+ return { taskId: taskIdGen, subSessionId: subSession.id };
217
+ }
218
+ async executeTask(taskId, prompt, timeout, cleanup, parentSessionId) {
219
+ const task = this.tasks.get(taskId);
220
+ if (!task) {
221
+ logger.warn(`[BackgroundTaskManager] executeTask: Task not found`, { taskId });
222
+ return;
223
+ }
224
+ task.status = "running";
225
+ task.startedAt = Date.now();
226
+ const timeoutMs = timeout || DEFAULT_TIMEOUT;
227
+ const abortController = this.abortControllers.get(taskId);
228
+ this.startProgressReporter(taskId, parentSessionId || task.parentSessionId);
229
+ try {
230
+ const sessionComponent = this.getSessionComponent();
231
+ const subSession = await sessionComponent.get(task.subSessionId);
232
+ if (!subSession) {
233
+ throw new Error(`Sub session not found: ${task.subSessionId}`);
234
+ }
235
+ const result = await this.executeWithAbort(subSession, prompt, timeoutMs, abortController?.signal);
236
+ if (abortController?.signal.aborted) {
237
+ logger.info(`[BackgroundTaskManager] Task was aborted`, { taskId });
238
+ return;
239
+ }
240
+ task.status = "completed";
241
+ task.completedAt = Date.now();
242
+ task.result = result;
243
+ const executionTimeMs = task.completedAt - task.startedAt;
244
+ const completedPayload = {
245
+ backgroundTaskId: task.id,
246
+ subSessionId: task.subSessionId,
247
+ parentSessionId: parentSessionId || task.parentSessionId,
248
+ status: "completed",
249
+ result: task.result,
250
+ description: task.description,
251
+ executionTimeMs,
252
+ associatedTaskId: task.taskId
253
+ };
254
+ this.publishBackgroundEvent(BackgroundTaskEventTypes.COMPLETED, completedPayload, parentSessionId || task.parentSessionId);
255
+ logger.info(`[BackgroundTaskManager] Task completed successfully`, {
256
+ taskId,
257
+ executionTimeMs
258
+ });
259
+ } catch (error) {
260
+ const errorMessage = error instanceof Error ? error.message : String(error);
261
+ const isStoppedError = errorMessage.toLowerCase().includes("stopped") || errorMessage.toLowerCase().includes("aborted");
262
+ const executionTimeMs = task.startedAt ? Date.now() - task.startedAt : 0;
263
+ if (isStoppedError) {
264
+ task.status = "stopped";
265
+ const stoppedPayload = {
266
+ backgroundTaskId: task.id,
267
+ subSessionId: task.subSessionId,
268
+ parentSessionId: parentSessionId || task.parentSessionId,
269
+ status: "stopped",
270
+ description: task.description,
271
+ error: errorMessage,
272
+ executionTimeMs,
273
+ associatedTaskId: task.taskId
274
+ };
275
+ this.publishBackgroundEvent(BackgroundTaskEventTypes.STOPPED, stoppedPayload, parentSessionId || task.parentSessionId);
276
+ } else if (errorMessage.includes("timeout")) {
277
+ task.status = "timeout";
278
+ const timeoutPayload = {
279
+ backgroundTaskId: task.id,
280
+ subSessionId: task.subSessionId,
281
+ parentSessionId: parentSessionId || task.parentSessionId,
282
+ status: "timeout",
283
+ description: task.description,
284
+ error: errorMessage,
285
+ executionTimeMs,
286
+ associatedTaskId: task.taskId
287
+ };
288
+ this.publishBackgroundEvent(BackgroundTaskEventTypes.TIMEOUT, timeoutPayload, parentSessionId || task.parentSessionId);
289
+ } else {
290
+ task.status = "failed";
291
+ const failedPayload = {
292
+ backgroundTaskId: task.id,
293
+ subSessionId: task.subSessionId,
294
+ parentSessionId: parentSessionId || task.parentSessionId,
295
+ status: "failed",
296
+ description: task.description,
297
+ error: errorMessage,
298
+ executionTimeMs,
299
+ associatedTaskId: task.taskId
300
+ };
301
+ this.publishBackgroundEvent(BackgroundTaskEventTypes.FAILED, failedPayload, parentSessionId || task.parentSessionId);
302
+ }
303
+ task.error = errorMessage;
304
+ task.completedAt = Date.now();
305
+ logger.error(`[BackgroundTaskManager] Task execution error`, {
306
+ taskId,
307
+ status: task.status,
308
+ error: errorMessage
309
+ });
310
+ } finally {
311
+ this.stopProgressReporter(taskId);
312
+ }
313
+ }
314
+ startProgressReporter(taskId, parentSessionId) {
315
+ const timer = setInterval(() => {
316
+ const task = this.tasks.get(taskId);
317
+ if (!task || task.status !== "running") {
318
+ this.stopProgressReporter(taskId);
319
+ return;
320
+ }
321
+ if (task.startedAt) {
322
+ const elapsedMs = Date.now() - task.startedAt;
323
+ task.progress = Math.min(95, Math.floor(elapsedMs / PROGRESS_INTERVAL * 100));
324
+ }
325
+ const progressPayload = {
326
+ backgroundTaskId: taskId,
327
+ subSessionId: task.subSessionId,
328
+ parentSessionId,
329
+ status: task.status,
330
+ progress: task.progress
331
+ };
332
+ this.publishBackgroundEvent(BackgroundTaskEventTypes.PROGRESS, progressPayload, parentSessionId);
333
+ }, PROGRESS_INTERVAL);
334
+ this.progressTimers.set(taskId, timer);
335
+ }
336
+ stopProgressReporter(taskId) {
337
+ const timer = this.progressTimers.get(taskId);
338
+ if (timer) {
339
+ clearInterval(timer);
340
+ this.progressTimers.delete(taskId);
341
+ }
342
+ }
343
+ async executeWithAbort(subSession, prompt, timeoutMs, signal) {
344
+ return new Promise((resolve, reject) => {
345
+ const timer = setTimeout(() => {
346
+ reject(new Error(`Task execution timeout after ${timeoutMs}ms`));
347
+ }, timeoutMs);
348
+ signal?.addEventListener("abort", () => {
349
+ clearTimeout(timer);
350
+ reject(new Error("Task execution stopped"));
351
+ });
352
+ const metadata = subSession.info?.metadata || {};
353
+ const taskId = metadata.task_id;
354
+ const taskDescription = metadata.task_description || "";
355
+ const sessionId = subSession.id;
356
+ const subagentType = metadata.subagent_type || "general";
357
+ const subAgent = getSubAgentSpec(subagentType);
358
+ let basePrompt = subAgent?.promptOverride || `You are a subagent. Complete this task: {task_description}`;
359
+ const deniedTools = subAgent?.deniedTools || [];
360
+ let fullPrompt = basePrompt.replace(/{task_description}/g, taskDescription || "N/A");
361
+ fullPrompt += `
362
+
363
+ ---
364
+
365
+ # Session Info
366
+ - task_id: ${taskId || "N/A"}
367
+ - session_id: ${sessionId}
368
+
369
+ ---
370
+
371
+ ## 用户指令
372
+ ${prompt}
373
+
374
+ ---
375
+
376
+ ## 执行规范
377
+ - 使用可用工具完成任务
378
+ - 返回清晰的任务执行结果摘要
379
+ - 适时调用 task_operation_create 记录进展`;
380
+ const agentComponent = this.env?.getComponent?.("agent");
381
+ if (!agentComponent) {
382
+ clearTimeout(timer);
383
+ reject(new Error("AgentComponent not found"));
384
+ return;
385
+ }
386
+ ensureSubAgentRegistered(agentComponent, subagentType, basePrompt, subAgent, deniedTools);
387
+ this.env.handle_query?.(fullPrompt, {
388
+ sessionId,
389
+ deniedTools: deniedTools.length > 0 ? deniedTools : undefined,
390
+ agentType: subagentType
391
+ }).then((result) => {
392
+ clearTimeout(timer);
393
+ resolve(result);
394
+ }).catch((error) => {
395
+ clearTimeout(timer);
396
+ reject(error);
397
+ });
398
+ });
399
+ }
400
+ stopTask(taskId) {
401
+ const task = this.tasks.get(taskId);
402
+ if (!task) {
403
+ return { success: false, message: "Task not found" };
404
+ }
405
+ if (task.status === "completed" || task.status === "failed" || task.status === "stopped" || task.status === "timeout") {
406
+ return {
407
+ success: false,
408
+ task,
409
+ message: `Cannot stop task with status: ${task.status}`
410
+ };
411
+ }
412
+ task.status = "stopped";
413
+ task.abortController?.abort();
414
+ task.completedAt = Date.now();
415
+ const stoppedPayload = {
416
+ backgroundTaskId: task.id,
417
+ subSessionId: task.subSessionId,
418
+ parentSessionId: task.parentSessionId,
419
+ status: "stopped",
420
+ description: task.description,
421
+ error: "Task stopped by user",
422
+ executionTimeMs: task.startedAt ? task.completedAt - task.startedAt : 0,
423
+ associatedTaskId: task.taskId
424
+ };
425
+ this.publishBackgroundEvent(BackgroundTaskEventTypes.STOPPED, stoppedPayload, task.parentSessionId);
426
+ return { success: true, task, message: "Task has been stopped" };
427
+ }
428
+ getTask(taskId) {
429
+ return this.tasks.get(taskId);
430
+ }
431
+ listTasks() {
432
+ return Array.from(this.tasks.values());
433
+ }
434
+ dispose() {
435
+ for (const [taskId, controller] of this.abortControllers) {
436
+ controller.abort();
437
+ logger.debug(`[BackgroundTaskManager] Aborted task: ${taskId}`);
438
+ }
439
+ this.abortControllers.clear();
440
+ this.tasks.clear();
441
+ logger.info(`[BackgroundTaskManager] Disposed`);
442
+ }
443
+ }
444
+ function createDelegateTool(taskComponent) {
445
+ const env = taskComponent.env;
446
+ const backgroundTaskManager = new BackgroundTaskManager(env);
447
+ taskComponent._backgroundTaskManager = backgroundTaskManager;
448
+ const tool = {
449
+ name: "delegate_task",
450
+ description: `Launch a new sub-agent to handle complex, multistep tasks autonomously.
451
+
452
+ Available agent types:
453
+ ${getSubAgentToolDescription()}
454
+
455
+ When using the delegate_task tool, you must specify a subagent_type parameter to select which agent type to use.
456
+
457
+ ## When to use delegate_task:
458
+ - When you need to perform complex, multi-step tasks that require independent execution
459
+ - When you need to explore a codebase thoroughly (use "explore" subagent)
460
+ - When you need to run long-running tasks without blocking the main agent (use background=true)
461
+
462
+ ## Parameters:
463
+ - **description**: A short (3-5 words) description of the task
464
+ - **prompt**: The task for the agent to perform
465
+ - **subagent_type**: The type of specialized agent to use (e.g., "general", "explore")
466
+ - **background**: Whether to run in background (default: false)
467
+ - **timeout**: Task timeout in milliseconds (optional)
468
+ - **task_id**: Optional task ID to associate with this delegate task
469
+
470
+ ## Synchronous vs Background mode:
471
+ **Synchronous mode (default)**: Waits for subagent to complete and returns result directly
472
+ **Background mode (background=true)**: Returns immediately with "accepted" status, runs independently`,
473
+ parameters: DelegateToolParameters,
474
+ execute: async (args, ctx) => {
475
+ const startTime = Date.now();
476
+ const params = DelegateToolParameters.parse(args);
477
+ const { description, prompt, subagent_type = "general", background = false, timeout, cleanup, task_id, reason } = params;
478
+ const parentSessionId = ctx.session_id || "default";
479
+ logger.info(`[delegate_task] Called: description=${description}, subagent_type=${subagent_type}, background=${background}, task_id=${task_id}`);
480
+ const subAgent = getSubAgentSpec(subagent_type);
481
+ if (!subAgent) {
482
+ return {
483
+ success: false,
484
+ output: "",
485
+ error: `Unknown subagent type: ${subagent_type}`,
486
+ metadata: { execution_time_ms: Date.now() - startTime }
487
+ };
488
+ }
489
+ const tagService = taskComponent.getTagService();
490
+ let promptWithTaskInfo = prompt;
491
+ const delegateCtx = {
492
+ taskId: task_id,
493
+ prompt: promptWithTaskInfo,
494
+ subagentType: subagent_type,
495
+ background,
496
+ timeout,
497
+ cleanup,
498
+ reason,
499
+ tagService
500
+ };
501
+ const hookCtx = {
502
+ component: { name: "task", version: "1.0.0" },
503
+ data: delegateCtx,
504
+ metadata: { sessionId: parentSessionId },
505
+ phase: "before",
506
+ hookPoint: TaskHookPoints.DELEGATE_BEFORE
507
+ };
508
+ await globalHookManager.execute(TaskHookPoints.DELEGATE_BEFORE, hookCtx, { sessionId: parentSessionId });
509
+ promptWithTaskInfo = delegateCtx.prompt;
510
+ if (background) {
511
+ return await handleBackgroundTask(taskComponent, backgroundTaskManager, parentSessionId, description, promptWithTaskInfo, delegateCtx.subagentType, delegateCtx.timeout, delegateCtx.cleanup, delegateCtx.taskId);
512
+ } else {
513
+ return await handleSyncTask(taskComponent, parentSessionId, description, promptWithTaskInfo, delegateCtx.subagentType, delegateCtx.timeout, delegateCtx.taskId);
514
+ }
515
+ }
516
+ };
517
+ return tool;
518
+ }
519
+ async function handleSyncTask(taskComponent, parentSessionId, description, prompt, subagentType, timeout, taskId) {
520
+ const startTime = Date.now();
521
+ try {
522
+ const sessionComponent = taskComponent.env?.getComponent?.("session");
523
+ if (!sessionComponent) {
524
+ return {
525
+ success: false,
526
+ output: "",
527
+ error: "SessionComponent not found",
528
+ metadata: { execution_time_ms: Date.now() - startTime }
529
+ };
530
+ }
531
+ const parentSession = await sessionComponent.get(parentSessionId);
532
+ if (!parentSession) {
533
+ return {
534
+ success: false,
535
+ output: "",
536
+ error: `Parent session not found: ${parentSessionId}`,
537
+ metadata: { execution_time_ms: Date.now() - startTime }
538
+ };
539
+ }
540
+ const metadata = {
541
+ subagent_type: subagentType,
542
+ created_by: "subagent",
543
+ task_description: description
544
+ };
545
+ if (taskId) {
546
+ metadata.task_id = taskId;
547
+ }
548
+ const subSession = await sessionComponent.create({
549
+ parentID: parentSessionId,
550
+ title: `${description} (@${subagentType} subagent)`,
551
+ metadata
552
+ });
553
+ if (!subSession) {
554
+ return {
555
+ success: false,
556
+ output: "",
557
+ error: "Failed to create sub-session",
558
+ metadata: { execution_time_ms: Date.now() - startTime }
559
+ };
560
+ }
561
+ const subAgent = getSubAgentSpec(subagentType);
562
+ let basePrompt = subAgent?.promptOverride || `You are a subagent. Complete this task: {task_description}`;
563
+ const deniedTools = subAgent?.deniedTools || [];
564
+ let fullPrompt = basePrompt.replace(/{task_description}/g, description || "N/A");
565
+ fullPrompt += `
566
+
567
+ ---
568
+
569
+ # Session Info
570
+ - task_id: ${taskId || "N/A"}
571
+ - session_id: ${subSession.id}
572
+
573
+ ---
574
+
575
+ ## 用户指令
576
+ ${prompt}
577
+
578
+ ---
579
+
580
+ ## 执行规范
581
+ - 使用可用工具完成任务
582
+ - 返回清晰的任务执行结果摘要
583
+ - 适时调用 task_operation_create 记录进展`;
584
+ const agentComponent = taskComponent.env?.getComponent?.("agent");
585
+ if (!agentComponent) {
586
+ return {
587
+ success: false,
588
+ output: "",
589
+ error: "AgentComponent not found",
590
+ metadata: { execution_time_ms: Date.now() - startTime }
591
+ };
592
+ }
593
+ ensureSubAgentRegistered(agentComponent, subagentType, basePrompt, subAgent, deniedTools);
594
+ const timeoutMs = timeout || DEFAULT_TIMEOUT;
595
+ let result;
596
+ try {
597
+ result = await Promise.race([
598
+ taskComponent.env?.handle_query?.(fullPrompt, {
599
+ sessionId: subSession.id,
600
+ deniedTools: deniedTools.length > 0 ? deniedTools : undefined,
601
+ agentType: subagentType
602
+ }),
603
+ new Promise((_, reject) => setTimeout(() => reject(new Error(`Task execution timeout after ${timeoutMs}ms`)), timeoutMs))
604
+ ]);
605
+ } catch (error) {
606
+ result = error instanceof Error ? error.message : String(error);
607
+ }
608
+ await sessionComponent.addMessage(subSession.id, {
609
+ role: "assistant",
610
+ content: result
611
+ });
612
+ return {
613
+ success: true,
614
+ output: result + `
615
+
616
+ ` + [
617
+ "<task_metadata>",
618
+ `session_id: ${subSession.id}`,
619
+ `subagent_type: ${subagentType}`,
620
+ "</task_metadata>"
621
+ ].join(`
622
+ `),
623
+ metadata: {
624
+ execution_time_ms: Date.now() - startTime,
625
+ sessionId: subSession.id
626
+ }
627
+ };
628
+ } catch (error) {
629
+ return {
630
+ success: false,
631
+ output: "",
632
+ error: error instanceof Error ? error.message : String(error),
633
+ metadata: { execution_time_ms: Date.now() - startTime }
634
+ };
635
+ }
636
+ }
637
+ async function handleBackgroundTask(taskComponent, backgroundTaskManager, parentSessionId, description, prompt, subagentType, timeout, cleanup, taskId) {
638
+ const startTime = Date.now();
639
+ try {
640
+ let associatedTaskId = taskId;
641
+ if (!associatedTaskId) {
642
+ const newTask = await taskComponent.createTask({
643
+ title: description,
644
+ description: `Background task delegated to ${subagentType} subagent`,
645
+ priority: "medium",
646
+ goals_and_expected_deliverables: prompt,
647
+ sessionId: parentSessionId,
648
+ project_path: "unknown",
649
+ context: "unknown"
650
+ });
651
+ associatedTaskId = newTask.id;
652
+ await taskComponent.createOperation({
653
+ taskId: associatedTaskId,
654
+ sessionId: parentSessionId,
655
+ actionType: "create",
656
+ actionTitle: `Delegated to ${subagentType} subagent`,
657
+ actionDescription: `Background task started: ${description}`
658
+ });
659
+ } else {
660
+ await taskComponent.updateTask(associatedTaskId, {
661
+ status: "active",
662
+ current_status: `Running ${subagentType} subagent`
663
+ });
664
+ await taskComponent.createOperation({
665
+ taskId: associatedTaskId,
666
+ sessionId: parentSessionId,
667
+ actionType: "progress",
668
+ actionTitle: `Started ${subagentType} subagent`,
669
+ actionDescription: `Background task: ${description}`
670
+ });
671
+ }
672
+ const { taskId: bgTaskId, subSessionId } = await backgroundTaskManager.createTask({
673
+ parentSessionId,
674
+ description,
675
+ prompt,
676
+ subagentType,
677
+ timeout,
678
+ cleanup,
679
+ taskId: associatedTaskId
680
+ });
681
+ const output = [
682
+ `✅ Background task accepted`,
683
+ "",
684
+ `\uD83D\uDCCB Task ID: ${bgTaskId}`,
685
+ `\uD83D\uDCDD Description: ${description}`,
686
+ `\uD83E\uDD16 Sub-agent: ${subagentType}`,
687
+ associatedTaskId ? `\uD83D\uDCCC Associated Task: #${associatedTaskId}` : "",
688
+ `⏱️ Timeout: ${(timeout || DEFAULT_TIMEOUT) / 1000}s`,
689
+ "",
690
+ `Use stop_task with task_id="${bgTaskId}" to cancel this task.`
691
+ ].filter(Boolean).join(`
692
+ `);
693
+ return {
694
+ success: true,
695
+ output,
696
+ metadata: {
697
+ execution_time_ms: Date.now() - startTime,
698
+ sessionId: subSessionId,
699
+ background: true,
700
+ status: "accepted",
701
+ task_id: associatedTaskId,
702
+ bgTaskId
703
+ }
704
+ };
705
+ } catch (error) {
706
+ return {
707
+ success: false,
708
+ output: "",
709
+ error: error instanceof Error ? error.message : String(error),
710
+ metadata: { execution_time_ms: Date.now() - startTime }
711
+ };
712
+ }
713
+ }
714
+ // src/env/task/delegate/stop-tool.ts
715
+ import { z as z2 } from "zod";
716
+ var StopTaskToolParameters = z2.object({
717
+ task_id: z2.string().describe("The ID of the background task to stop")
718
+ });
719
+ var STOP_TASK_DESCRIPTION = `Stop a running background task.
720
+
721
+ Use this tool to stop a background task that is currently running. This is useful when:
722
+ - The user wants to cancel a long-running task
723
+ - The task is taking too long and needs to be stopped
724
+ - The user wants to change direction and doesn't need the task result anymore
725
+
726
+ When stopped, the task will be terminated immediately and you will receive a confirmation.
727
+
728
+ Parameters:
729
+ - task_id: The ID of the background task to stop (obtained from the delegate_task response)`;
730
+ function formatDuration(ms) {
731
+ const seconds = Math.floor(ms / 1000);
732
+ const minutes = Math.floor(seconds / 60);
733
+ const hours = Math.floor(minutes / 60);
734
+ if (hours > 0) {
735
+ return `${hours}h ${minutes % 60}m ${seconds % 60}s`;
736
+ } else if (minutes > 0) {
737
+ return `${minutes}m ${seconds % 60}s`;
738
+ } else {
739
+ return `${seconds}s`;
740
+ }
741
+ }
742
+ function createStopTool(taskManager) {
743
+ return {
744
+ name: "stop_task",
745
+ description: STOP_TASK_DESCRIPTION,
746
+ parameters: StopTaskToolParameters,
747
+ execute: async (args, ctx) => {
748
+ const startTime = Date.now();
749
+ const params = StopTaskToolParameters.parse(args);
750
+ const { task_id } = params;
751
+ const result = taskManager.stopTask(task_id);
752
+ if (result.success) {
753
+ const task = result.task;
754
+ const elapsedMs = task.startedAt ? Date.now() - task.startedAt : Date.now() - task.createdAt;
755
+ const output = [
756
+ `✅ Task stopped successfully`,
757
+ "",
758
+ `\uD83D\uDCCB Task ID: ${task_id}`,
759
+ `\uD83D\uDCDD Description: ${task.description}`,
760
+ `\uD83D\uDD04 Status: ${task.status} → stopped`,
761
+ `⏱️ Elapsed Time: ${formatDuration(elapsedMs)}`,
762
+ "",
763
+ result.message
764
+ ].join(`
765
+ `);
766
+ return {
767
+ success: true,
768
+ output,
769
+ metadata: {
770
+ execution_time_ms: Date.now() - startTime,
771
+ task_id,
772
+ previous_status: task.status
773
+ }
774
+ };
775
+ } else {
776
+ const task = result.task;
777
+ let output;
778
+ if (task) {
779
+ output = [
780
+ `⚠️ Cannot stop task`,
781
+ "",
782
+ `\uD83D\uDCCB Task ID: ${task_id}`,
783
+ `\uD83D\uDCDD Description: ${task.description}`,
784
+ `\uD83D\uDD04 Current Status: ${task.status}`,
785
+ "",
786
+ result.message
787
+ ].join(`
788
+ `);
789
+ } else {
790
+ output = [
791
+ `❌ Task not found`,
792
+ "",
793
+ `\uD83D\uDCCB Task ID: ${task_id}`,
794
+ "",
795
+ result.message
796
+ ].join(`
797
+ `);
798
+ }
799
+ return {
800
+ success: false,
801
+ output,
802
+ error: result.message,
803
+ metadata: {
804
+ execution_time_ms: Date.now() - startTime,
805
+ task_id
806
+ }
807
+ };
808
+ }
809
+ }
810
+ };
811
+ }
812
+ export { BackgroundTaskEventTypes, BackgroundTaskManager, createDelegateTool, createStopTool };