@ai-setting/roy-agent-core 1.4.13 → 1.4.14

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