@ai-setting/roy-agent-core 1.5.87 → 1.5.89
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.
- package/dist/env/agent/index.js +6 -6
- package/dist/env/event-source/index.js +6 -2
- package/dist/env/index.js +17 -12
- package/dist/env/prompt/index.js +2 -1
- package/dist/env/session/index.js +1 -2
- package/dist/env/task/delegate/index.js +3 -2
- package/dist/env/task/index.js +5 -4
- package/dist/env/task/plugins/index.js +7 -4
- package/dist/env/task/tools/index.js +1 -1
- package/dist/env/tool/built-in/index.js +2 -1
- package/dist/env/tool/index.js +11 -8
- package/dist/env/workflow/engine/index.js +4 -2
- package/dist/env/workflow/index.js +5 -3
- package/dist/env/workflow/tools/index.js +7 -1
- package/dist/env/workflow/utils/index.js +5 -0
- package/dist/index.js +32 -25
- package/dist/shared/@ai-setting/{roy-agent-core-6mk0m4t3.js → roy-agent-core-2q7cshpm.js} +1 -1
- package/dist/shared/@ai-setting/{roy-agent-core-0y64qaac.js → roy-agent-core-32m0nb9j.js} +119 -30
- package/dist/shared/@ai-setting/{roy-agent-core-9y09xfav.js → roy-agent-core-3f6k060j.js} +5 -417
- package/dist/shared/@ai-setting/roy-agent-core-4yq23m5g.js +421 -0
- package/dist/shared/@ai-setting/{roy-agent-core-mmkyydw7.js → roy-agent-core-83d035pp.js} +91 -579
- package/dist/shared/@ai-setting/roy-agent-core-8wd3qwx5.js +35 -0
- package/dist/shared/@ai-setting/{roy-agent-core-29fh9mxg.js → roy-agent-core-bwjpte58.js} +1 -2
- package/dist/shared/@ai-setting/{roy-agent-core-r1adqgaa.js → roy-agent-core-ewr1nw7t.js} +7 -8
- package/dist/shared/@ai-setting/{roy-agent-core-yx0vw1aw.js → roy-agent-core-fgpnv7dt.js} +31 -4
- package/dist/shared/@ai-setting/{roy-agent-core-jymz9fzp.js → roy-agent-core-fvfc7f6v.js} +64 -33
- package/dist/shared/@ai-setting/{roy-agent-core-9vwyj29a.js → roy-agent-core-h5867smx.js} +16 -22
- package/dist/shared/@ai-setting/roy-agent-core-hvdfgvfz.js +114 -0
- package/dist/shared/@ai-setting/{roy-agent-core-3arrpf7n.js → roy-agent-core-hxsbegfc.js} +229 -9
- package/dist/shared/@ai-setting/{roy-agent-core-7fdzfsm6.js → roy-agent-core-m3dkyprg.js} +35 -211
- package/dist/shared/@ai-setting/{roy-agent-core-bgw4dq11.js → roy-agent-core-mw4ty0ba.js} +44 -5
- package/dist/shared/@ai-setting/{roy-agent-core-7z4xtrmw.js → roy-agent-core-nqzt9ne4.js} +53 -0
- package/dist/shared/@ai-setting/roy-agent-core-pt7as39r.js +0 -0
- package/dist/shared/@ai-setting/{roy-agent-core-6n7xwv4v.js → roy-agent-core-qbq3jgrn.js} +5 -3
- package/dist/shared/@ai-setting/roy-agent-core-w6bmrgap.js +581 -0
- package/dist/shared/@ai-setting/{roy-agent-core-qhjb153z.js → roy-agent-core-xnxyzaw4.js} +27 -4
- package/dist/shared/@ai-setting/roy-agent-core-yanpq5gb.js +116 -0
- package/package.json +1 -1
- package/dist/shared/@ai-setting/roy-agent-core-x3gtyqax.js +0 -378
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import {
|
|
2
|
+
DAGManager,
|
|
3
|
+
init_dag_manager
|
|
4
|
+
} from "./roy-agent-core-4yq23m5g.js";
|
|
5
|
+
|
|
6
|
+
// src/env/workflow/utils/validate-workflow-definition.ts
|
|
7
|
+
init_dag_manager();
|
|
8
|
+
function validateWorkflowDefinition(definition) {
|
|
9
|
+
if (!definition || typeof definition !== "object") {
|
|
10
|
+
return {
|
|
11
|
+
valid: false,
|
|
12
|
+
errors: ["Workflow definition must be an object"]
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
const def = definition;
|
|
16
|
+
if (!Array.isArray(def.nodes)) {
|
|
17
|
+
return {
|
|
18
|
+
valid: false,
|
|
19
|
+
errors: ["Workflow definition must have a 'nodes' array"]
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
try {
|
|
23
|
+
const dag = new DAGManager(definition, { allowCycles: false });
|
|
24
|
+
return dag.validate();
|
|
25
|
+
} catch (error) {
|
|
26
|
+
return {
|
|
27
|
+
valid: false,
|
|
28
|
+
errors: [
|
|
29
|
+
`Validation error: ${error instanceof Error ? error.message : String(error)}`
|
|
30
|
+
]
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export { validateWorkflowDefinition };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
createAutoTaskPlugin
|
|
3
|
-
} from "./roy-agent-core-
|
|
3
|
+
} from "./roy-agent-core-yanpq5gb.js";
|
|
4
4
|
import {
|
|
5
5
|
ContextError,
|
|
6
6
|
ErrorCodes
|
|
@@ -158,7 +158,6 @@ class BaseEnvironment extends BaseComponent {
|
|
|
158
158
|
"echo",
|
|
159
159
|
"glob",
|
|
160
160
|
"grep",
|
|
161
|
-
"read_file",
|
|
162
161
|
"write_file",
|
|
163
162
|
"edit_file",
|
|
164
163
|
"task_create",
|
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
BackgroundTaskManager,
|
|
6
6
|
createDelegateTool,
|
|
7
7
|
createStopTool
|
|
8
|
-
} from "./roy-agent-core-
|
|
8
|
+
} from "./roy-agent-core-mw4ty0ba.js";
|
|
9
9
|
import {
|
|
10
10
|
SQLiteTaskStore,
|
|
11
11
|
getDefaultTaskDbPath
|
|
@@ -20,7 +20,7 @@ import {
|
|
|
20
20
|
listTasksTool,
|
|
21
21
|
searchTasksTool,
|
|
22
22
|
updateTaskTool
|
|
23
|
-
} from "./roy-agent-core-
|
|
23
|
+
} from "./roy-agent-core-h5867smx.js";
|
|
24
24
|
import {
|
|
25
25
|
createOperationTool,
|
|
26
26
|
deleteOperationTool,
|
|
@@ -358,12 +358,11 @@ class TaskComponent extends BaseComponent {
|
|
|
358
358
|
}
|
|
359
359
|
async createTask(options) {
|
|
360
360
|
const sessionId = options.sessionId;
|
|
361
|
-
if (options.parent_task_id
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
throw new Error(`Parent task #${options.parent_task_id} not found. ` + "Please provide a valid parent_task_id. Use task_list(depth=0) to see all root tasks.");
|
|
361
|
+
if (options.parent_task_id !== undefined && options.parent_task_id !== null) {
|
|
362
|
+
const parentTask = await this.store.getTask(options.parent_task_id);
|
|
363
|
+
if (!parentTask) {
|
|
364
|
+
throw new Error(`Parent task #${options.parent_task_id} not found. ` + "Please provide a valid parent_task_id. Use task_list(depth=0) to see all root tasks.");
|
|
365
|
+
}
|
|
367
366
|
}
|
|
368
367
|
const createCtx = {
|
|
369
368
|
options: { ...options },
|
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
import {
|
|
2
2
|
withTimeout
|
|
3
3
|
} from "./roy-agent-core-r0m0at3x.js";
|
|
4
|
+
import {
|
|
5
|
+
truncateOutputInline
|
|
6
|
+
} from "./roy-agent-core-hxsbegfc.js";
|
|
4
7
|
import {
|
|
5
8
|
AskUserError,
|
|
6
9
|
init_workflow_hil
|
|
7
10
|
} from "./roy-agent-core-e25xkv53.js";
|
|
8
11
|
import {
|
|
9
12
|
AgentRegistry
|
|
10
|
-
} from "./roy-agent-core-
|
|
13
|
+
} from "./roy-agent-core-nqzt9ne4.js";
|
|
11
14
|
import {
|
|
12
15
|
ContextError
|
|
13
16
|
} from "./roy-agent-core-ctdhjv68.js";
|
|
@@ -303,6 +306,12 @@ class AgentComponent extends BaseComponent {
|
|
|
303
306
|
logger.info("[AgentComponent] Registered built-in workflow-agent");
|
|
304
307
|
this.registry.registerJsonExtractAgent();
|
|
305
308
|
logger.info("[AgentComponent] Registered built-in json-extract agent");
|
|
309
|
+
this.registry.registerWorkflowExtractAgent();
|
|
310
|
+
logger.info("[AgentComponent] Registered built-in workflow-extract agent");
|
|
311
|
+
this.registry.registerCompactAgent();
|
|
312
|
+
logger.info("[AgentComponent] Registered built-in compact agent");
|
|
313
|
+
this.registry.registerCompactHintAgent();
|
|
314
|
+
logger.info("[AgentComponent] Registered built-in compact-hint agent");
|
|
306
315
|
for (const agentDef of this.registry.list()) {
|
|
307
316
|
if (!this.agents.has(agentDef.name)) {
|
|
308
317
|
const systemPrompt = await this.registry.getSystemPrompt(agentDef.name);
|
|
@@ -504,7 +513,7 @@ class AgentComponent extends BaseComponent {
|
|
|
504
513
|
const allowedTools = context?.allowedTools ?? agent.config.allowedTools;
|
|
505
514
|
const deniedTools = context?.deniedTools ?? agent.config.deniedTools;
|
|
506
515
|
logger.debug(`[getAvailableTools] Filtering: allowed=${allowedTools}, denied=${deniedTools}`);
|
|
507
|
-
if (allowedTools
|
|
516
|
+
if (allowedTools !== undefined && allowedTools !== null) {
|
|
508
517
|
tools = tools.filter((t) => allowedTools.includes(t.name));
|
|
509
518
|
logger.debug(`[getAvailableTools] After allowedTools filter: ${tools.length} tools`, {
|
|
510
519
|
toolNames: tools.map((t) => t.name)
|
|
@@ -1062,7 +1071,8 @@ ${additionInfo}`
|
|
|
1062
1071
|
sessionId: ctx.context.sessionId,
|
|
1063
1072
|
messageId: ctx.context.messageId
|
|
1064
1073
|
},
|
|
1065
|
-
abortSignal: ctx.context.abort
|
|
1074
|
+
abortSignal: ctx.context.abort,
|
|
1075
|
+
skipThresholdCheck: ctx.context.agentType === "sub"
|
|
1066
1076
|
});
|
|
1067
1077
|
const result = await withTimeout(llmPromise, 300000, "LLM invocation timeout after 300s");
|
|
1068
1078
|
logger.debug("[invokeLLM] LLMComponent.invoke returned successfully");
|
|
@@ -1148,6 +1158,7 @@ ${additionInfo}`
|
|
|
1148
1158
|
} else {
|
|
1149
1159
|
result = await withTimeout(toolPromise, 120000, `Tool '${toolName}' execution timeout after 120s`);
|
|
1150
1160
|
}
|
|
1161
|
+
result = truncateOutputInline(result, undefined, undefined, toolName);
|
|
1151
1162
|
} else if (this.toolComponent?.execute) {
|
|
1152
1163
|
const toolPromise = this.toolComponent.execute(request);
|
|
1153
1164
|
if (isLongRunningTool) {
|
|
@@ -1163,6 +1174,7 @@ ${additionInfo}`
|
|
|
1163
1174
|
} else {
|
|
1164
1175
|
result = await withTimeout(toolPromise, 120000, `Tool '${toolName}' execution timeout after 120s`);
|
|
1165
1176
|
}
|
|
1177
|
+
result = truncateOutputInline(result, undefined, undefined, toolName);
|
|
1166
1178
|
}
|
|
1167
1179
|
this.pushEnvEvent({
|
|
1168
1180
|
type: "tool.result",
|
|
@@ -1375,4 +1387,19 @@ __legacyDecorateClassTS([
|
|
|
1375
1387
|
__legacyDecorateClassTS([
|
|
1376
1388
|
TracedAs("agent.component.getConversationHistory", { recordParams: true, recordResult: true, log: true })
|
|
1377
1389
|
], AgentComponent.prototype, "getConversationHistory", null);
|
|
1378
|
-
|
|
1390
|
+
// src/env/agent/summary-agent.ts
|
|
1391
|
+
class SummaryAgent {
|
|
1392
|
+
llmComponent;
|
|
1393
|
+
config;
|
|
1394
|
+
constructor(_promptComponent, llmComponent, config) {
|
|
1395
|
+
this.llmComponent = llmComponent;
|
|
1396
|
+
this.config = {
|
|
1397
|
+
type: "summary",
|
|
1398
|
+
promptName: "session/compact",
|
|
1399
|
+
maxIterations: 1,
|
|
1400
|
+
model: undefined,
|
|
1401
|
+
...config
|
|
1402
|
+
};
|
|
1403
|
+
}
|
|
1404
|
+
}
|
|
1405
|
+
export { AgentComponentConfigSchema, AgentComponent, SummaryAgent };
|
|
@@ -7,9 +7,6 @@ import {
|
|
|
7
7
|
MemorySessionStore,
|
|
8
8
|
SQLiteSessionStore
|
|
9
9
|
} from "./roy-agent-core-q7sqeax6.js";
|
|
10
|
-
import {
|
|
11
|
-
SummaryAgent
|
|
12
|
-
} from "./roy-agent-core-x3gtyqax.js";
|
|
13
10
|
import {
|
|
14
11
|
envKeyToConfigKey
|
|
15
12
|
} from "./roy-agent-core-qxhq8ven.js";
|
|
@@ -67,6 +64,7 @@ var SESSION_CONFIG_REGISTRATION = {
|
|
|
67
64
|
// src/env/session/session-component.ts
|
|
68
65
|
init_search_query_parser();
|
|
69
66
|
import path from "path";
|
|
67
|
+
import { z } from "zod";
|
|
70
68
|
var logger = createLogger("session");
|
|
71
69
|
|
|
72
70
|
class SessionComponent extends BaseComponent {
|
|
@@ -78,9 +76,6 @@ class SessionComponent extends BaseComponent {
|
|
|
78
76
|
hooksConfig = {};
|
|
79
77
|
configComponent;
|
|
80
78
|
configWatcher;
|
|
81
|
-
summaryAgent;
|
|
82
|
-
promptComponent;
|
|
83
|
-
llmComponent;
|
|
84
79
|
constructor() {
|
|
85
80
|
super();
|
|
86
81
|
}
|
|
@@ -398,19 +393,6 @@ class SessionComponent extends BaseComponent {
|
|
|
398
393
|
const date = new Date().toISOString().replace("T", " ").substring(0, 19);
|
|
399
394
|
return template.replace("{date}", date);
|
|
400
395
|
}
|
|
401
|
-
setSummaryComponents(promptComponent, llmComponent) {
|
|
402
|
-
this.promptComponent = promptComponent;
|
|
403
|
-
this.llmComponent = llmComponent;
|
|
404
|
-
this.summaryAgent = new SummaryAgent(promptComponent, llmComponent);
|
|
405
|
-
}
|
|
406
|
-
ensureSummaryAgent() {
|
|
407
|
-
if (!this.summaryAgent) {
|
|
408
|
-
if (!this.promptComponent || !this.llmComponent) {
|
|
409
|
-
throw new Error("SummaryAgent components not initialized. Call setSummaryComponents() first.");
|
|
410
|
-
}
|
|
411
|
-
this.summaryAgent = new SummaryAgent(this.promptComponent, this.llmComponent);
|
|
412
|
-
}
|
|
413
|
-
}
|
|
414
396
|
async generateCompactHint(sessionId) {
|
|
415
397
|
const session = await this.get(sessionId);
|
|
416
398
|
if (!session) {
|
|
@@ -424,16 +406,33 @@ class SessionComponent extends BaseComponent {
|
|
|
424
406
|
logger.warn("[SessionComponent] Not enough messages for hint generation");
|
|
425
407
|
return "";
|
|
426
408
|
}
|
|
427
|
-
this.
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
409
|
+
const agentComponent = this.env.getComponent("agent");
|
|
410
|
+
let hintData;
|
|
411
|
+
const submitTool = {
|
|
412
|
+
name: "workflow_submit_output",
|
|
413
|
+
description: "Submit the final result. Call this with your guidance_prompt.",
|
|
414
|
+
parameters: z.object({
|
|
415
|
+
guidance_prompt: z.string().describe("The compact guidance prompt (3-4 sentences)")
|
|
416
|
+
}),
|
|
417
|
+
execute: async (args) => {
|
|
418
|
+
const parsed = z.object({
|
|
419
|
+
guidance_prompt: z.string()
|
|
420
|
+
}).parse(args);
|
|
421
|
+
hintData = parsed;
|
|
422
|
+
return { success: true, output: "OK" };
|
|
423
|
+
}
|
|
424
|
+
};
|
|
425
|
+
await agentComponent.run("compact-hint", "Analyze this conversation and generate a compact guidance prompt for checkpoint generation.", {
|
|
426
|
+
sessionId,
|
|
427
|
+
persistSession: false,
|
|
428
|
+
extraTools: [submitTool]
|
|
431
429
|
});
|
|
430
|
+
const hint = hintData?.guidance_prompt || "[Hint extraction failed]";
|
|
432
431
|
logger.info("[SessionComponent] Compact hint generated", {
|
|
433
432
|
sessionId,
|
|
434
|
-
hintLength:
|
|
433
|
+
hintLength: hint.length
|
|
435
434
|
});
|
|
436
|
-
return
|
|
435
|
+
return hint;
|
|
437
436
|
}
|
|
438
437
|
async compact(sessionId, options) {
|
|
439
438
|
const session = await this.get(sessionId);
|
|
@@ -448,20 +447,52 @@ class SessionComponent extends BaseComponent {
|
|
|
448
447
|
throw new Error("Not enough messages to compact (minimum 3 required)");
|
|
449
448
|
}
|
|
450
449
|
const recentMessages = this.extractRecentMessages(messages, 2);
|
|
451
|
-
this.ensureSummaryAgent();
|
|
452
450
|
await this.executeBeforeHooks("compact", { session, options });
|
|
453
451
|
let summaryResult;
|
|
454
452
|
try {
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
453
|
+
const userQuery = options?.scenarioHint ? options.scenarioHint : "Generate a checkpoint from this conversation.";
|
|
454
|
+
let checkpointData;
|
|
455
|
+
const submitTool = {
|
|
456
|
+
name: "workflow_submit_output",
|
|
457
|
+
description: "Submit the checkpoint result with title, processKeyPoints, currentState, nextSteps, userIntents.",
|
|
458
|
+
parameters: z.object({
|
|
459
|
+
title: z.string().describe("Brief checkpoint title (max 30 chars)"),
|
|
460
|
+
processKeyPoints: z.array(z.string()).describe("Key discoveries or decisions"),
|
|
461
|
+
currentState: z.string().describe("Current progress and status"),
|
|
462
|
+
nextSteps: z.array(z.string()).describe("Follow-up items"),
|
|
463
|
+
userIntents: z.array(z.string()).describe("User's core intents (2-5 items)")
|
|
464
|
+
}),
|
|
465
|
+
execute: async (args) => {
|
|
466
|
+
const parsed = z.object({
|
|
467
|
+
title: z.string(),
|
|
468
|
+
processKeyPoints: z.array(z.string()),
|
|
469
|
+
currentState: z.string(),
|
|
470
|
+
nextSteps: z.array(z.string()),
|
|
471
|
+
userIntents: z.array(z.string())
|
|
472
|
+
}).parse(args);
|
|
473
|
+
checkpointData = parsed;
|
|
474
|
+
return { success: true, output: "OK" };
|
|
475
|
+
}
|
|
476
|
+
};
|
|
477
|
+
const agentComponent = this.env.getComponent("agent");
|
|
478
|
+
await agentComponent.run("compact", userQuery, {
|
|
479
|
+
sessionId,
|
|
480
|
+
persistSession: false,
|
|
481
|
+
extraTools: [submitTool]
|
|
460
482
|
});
|
|
483
|
+
const data = checkpointData || {};
|
|
484
|
+
summaryResult = {
|
|
485
|
+
title: data.title || "Untitled Checkpoint",
|
|
486
|
+
processKeyPoints: data.processKeyPoints || [],
|
|
487
|
+
currentState: data.currentState || "",
|
|
488
|
+
nextSteps: data.nextSteps || [],
|
|
489
|
+
userIntents: data.userIntents || [],
|
|
490
|
+
rawResponse: JSON.stringify(data)
|
|
491
|
+
};
|
|
461
492
|
} catch (error) {
|
|
462
493
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
463
|
-
logger.error(`[SessionComponent]
|
|
464
|
-
throw new Error(`Session compaction failed:
|
|
494
|
+
logger.error(`[SessionComponent] Compact agent failed: ${errorMessage}`);
|
|
495
|
+
throw new Error(`Session compaction failed: ${errorMessage}`);
|
|
465
496
|
}
|
|
466
497
|
const checkpointId = `cp_${Date.now().toString(36)}_${Math.random().toString(36).substring(2, 8)}`;
|
|
467
498
|
const checkpoint = {
|
|
@@ -18,15 +18,13 @@ var CreateTaskToolSchema = z.object({
|
|
|
18
18
|
due_date: z.string().optional().describe("Due date (ISO format)"),
|
|
19
19
|
tags: z.array(z.string()).optional().describe("Task tags (for search, stored in task.tags JSON field)"),
|
|
20
20
|
project_path: z.string().describe("Project root path for task positioning. " + "Used to locate the project space for this task. " + "Use 'unknown' if unknown."),
|
|
21
|
-
parent_task_id: z.number().describe(`父任务 ID
|
|
22
|
-
` +
|
|
23
|
-
` + ` 1. 任务聚类:将相关任务聚合到同一父任务下,便于管理和追踪
|
|
24
|
-
` + ` 2. 维护任务树:保持根任务数量可控(≤10个),深度适中(≤5层)
|
|
21
|
+
parent_task_id: z.union([z.number(), z.null()]).optional().describe(`父任务 ID(可选)。不传或传 null 时,创建根任务(root task)。
|
|
22
|
+
` + `如需将任务挂载到某个父任务下,传入对应父任务 ID。
|
|
25
23
|
` + `如何选择合适的父任务:
|
|
26
24
|
` + ` 1. 使用 task_list(depth=0) 查看当前所有根任务
|
|
27
25
|
` + ` 2. 使用 task_search 搜索与当前任务相关的父任务
|
|
28
26
|
` + ` 3. 按主题归类:将相似主题的任务挂载到同一个父任务下
|
|
29
|
-
` + "
|
|
27
|
+
` + "如果确实找不到合适的父任务,可以直接创建根任务(不传 parent_task_id)。"),
|
|
30
28
|
context: z.string().describe("JSON string with time-space positioning information for task continuity. " + "This field is crucial for Agent task handoff. " + "Core fields: worktree_path (git worktree path), branch (current branch), type (feature/bug/refactor/chore). " + 'Example for coding: {"worktree_path": "/path/worktree", "branch": "feature/xyz", "type": "feature"}. ' + 'Example for other: {"type": "general"}. ' + `If unknown, use '{}' or '{"type":"unknown"}'. ` + "IMPORTANT: Must be a valid JSON string!")
|
|
31
29
|
});
|
|
32
30
|
var GetTaskToolSchema = z.object({
|
|
@@ -124,32 +122,28 @@ function createTaskTool(taskComponent) {
|
|
|
124
122
|
|
|
125
123
|
**DO NOT leave this as plain text** - it must be valid JSON!
|
|
126
124
|
|
|
127
|
-
##
|
|
125
|
+
## parent_task_id is OPTIONAL
|
|
128
126
|
|
|
129
|
-
|
|
127
|
+
Creating a root task (top-level task) is allowed and common. To create a root task,
|
|
128
|
+
simply **omit** \`parent_task_id\` (or pass \`null\`).
|
|
130
129
|
|
|
131
|
-
|
|
132
|
-
maintaining a clean hierarchy (根任务 ≤10, 深度 ≤5).
|
|
133
|
-
|
|
134
|
-
2. **Task Clustering**: Related tasks are grouped under the same parent,
|
|
135
|
-
making it easy to track progress and find related work.
|
|
136
|
-
|
|
137
|
-
**How to choose a parent task:**
|
|
130
|
+
To create a child task, provide an existing parent's \`parent_task_id\`. Best practices:
|
|
138
131
|
|
|
139
132
|
1. First, use \`task_list(depth=0)\` to see all root tasks (top-level tasks).
|
|
140
133
|
2. Use \`task_search\` with relevant keywords to find existing tasks
|
|
141
134
|
that could serve as the parent.
|
|
142
135
|
3. Group by topic: put similar tasks under the same parent.
|
|
143
|
-
4. If no suitable parent exists, create a
|
|
144
|
-
then create the child task with that
|
|
136
|
+
4. If no suitable parent exists, create a root task first (omit \`parent_task_id\`),
|
|
137
|
+
then create the child task with that root task's id.
|
|
145
138
|
|
|
146
|
-
**
|
|
147
|
-
-
|
|
148
|
-
|
|
149
|
-
id as \`parent_task_id\` — do NOT hardcode a specific id; the root task id varies
|
|
150
|
-
across deployments and resets.
|
|
151
|
-
- Then: task_create(title="New feature", parent_task_id=<root_task_id>, ...)
|
|
139
|
+
**Examples:**
|
|
140
|
+
- Root task: \`task_create(title="New project", ...)\` (no parent_task_id)
|
|
141
|
+
- Child task: \`task_create(title="New feature", parent_task_id=<root_task_id>, ...)\`
|
|
152
142
|
where \`<root_task_id>\` is the id returned by task_list, NOT a hardcoded number.
|
|
143
|
+
|
|
144
|
+
**Hierarchy guidance** (not enforced):
|
|
145
|
+
- 根任务 ≤10 (keep root tasks manageable)
|
|
146
|
+
- 深度 ≤5 (avoid deep nesting)
|
|
153
147
|
`,
|
|
154
148
|
parameters: CreateTaskToolSchema,
|
|
155
149
|
execute: async (args, ctx) => {
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
// src/env/task/delegate/process-registry.ts
|
|
2
|
+
import { AsyncLocalStorage } from "async_hooks";
|
|
3
|
+
|
|
4
|
+
// src/util/process/process-tree-killer.ts
|
|
5
|
+
import { spawn as _childProcessSpawn } from "child_process";
|
|
6
|
+
var spawnInjector;
|
|
7
|
+
function spawn(cmd, args, opts) {
|
|
8
|
+
if (spawnInjector)
|
|
9
|
+
return spawnInjector(cmd, args, opts);
|
|
10
|
+
return _childProcessSpawn(cmd, args, opts);
|
|
11
|
+
}
|
|
12
|
+
var platformOverride;
|
|
13
|
+
function currentPlatform() {
|
|
14
|
+
return platformOverride ?? process.platform;
|
|
15
|
+
}
|
|
16
|
+
function killProcessTree(pid, options) {
|
|
17
|
+
if (!Number.isInteger(pid) || pid <= 0) {
|
|
18
|
+
throw new Error(`Invalid PID: ${pid} (must be a positive integer)`);
|
|
19
|
+
}
|
|
20
|
+
const platform = currentPlatform();
|
|
21
|
+
const signal = options?.signal ?? "SIGKILL";
|
|
22
|
+
if (platform === "win32") {
|
|
23
|
+
return killOnWindows(pid);
|
|
24
|
+
}
|
|
25
|
+
return killOnPosix(pid, signal);
|
|
26
|
+
}
|
|
27
|
+
function killOnWindows(pid) {
|
|
28
|
+
try {
|
|
29
|
+
spawn("taskkill", ["/pid", String(pid), "/f", "/t"], {
|
|
30
|
+
stdio: "ignore",
|
|
31
|
+
windowsHide: true
|
|
32
|
+
});
|
|
33
|
+
return {
|
|
34
|
+
pid,
|
|
35
|
+
platform: "win32",
|
|
36
|
+
signal: "taskkill /f /t",
|
|
37
|
+
success: true
|
|
38
|
+
};
|
|
39
|
+
} catch {
|
|
40
|
+
return {
|
|
41
|
+
pid,
|
|
42
|
+
platform: "win32",
|
|
43
|
+
signal: "taskkill /f /t",
|
|
44
|
+
success: false
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
function killOnPosix(pid, signal) {
|
|
49
|
+
const platform = currentPlatform();
|
|
50
|
+
try {
|
|
51
|
+
process.kill(-pid, signal);
|
|
52
|
+
return {
|
|
53
|
+
pid,
|
|
54
|
+
platform,
|
|
55
|
+
signal,
|
|
56
|
+
success: true
|
|
57
|
+
};
|
|
58
|
+
} catch (err) {
|
|
59
|
+
const code = err.code;
|
|
60
|
+
if (code === "ESRCH" || code === "EPERM") {
|
|
61
|
+
return {
|
|
62
|
+
pid,
|
|
63
|
+
platform,
|
|
64
|
+
signal,
|
|
65
|
+
success: true
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
return {
|
|
69
|
+
pid,
|
|
70
|
+
platform,
|
|
71
|
+
signal,
|
|
72
|
+
success: false
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// src/env/task/delegate/process-registry.ts
|
|
78
|
+
class ProcessRegistry {
|
|
79
|
+
pids = new Set;
|
|
80
|
+
register(pid) {
|
|
81
|
+
if (!Number.isInteger(pid) || pid <= 0) {
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
this.pids.add(pid);
|
|
85
|
+
}
|
|
86
|
+
unregister(pid) {
|
|
87
|
+
if (!Number.isInteger(pid)) {
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
this.pids.delete(pid);
|
|
91
|
+
}
|
|
92
|
+
size() {
|
|
93
|
+
return this.pids.size;
|
|
94
|
+
}
|
|
95
|
+
killAll() {
|
|
96
|
+
if (this.pids.size === 0)
|
|
97
|
+
return;
|
|
98
|
+
for (const pid of Array.from(this.pids)) {
|
|
99
|
+
try {
|
|
100
|
+
killProcessTree(pid);
|
|
101
|
+
} catch {}
|
|
102
|
+
}
|
|
103
|
+
this.pids.clear();
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
var processRegistryStorage = new AsyncLocalStorage;
|
|
107
|
+
function runWithProcessRegistryAsync(registry, fn) {
|
|
108
|
+
return processRegistryStorage.run(registry, fn);
|
|
109
|
+
}
|
|
110
|
+
function getCurrentProcessRegistry() {
|
|
111
|
+
return processRegistryStorage.getStore();
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export { killProcessTree, ProcessRegistry, runWithProcessRegistryAsync, getCurrentProcessRegistry };
|