@ai-setting/roy-agent-core 1.5.81 → 1.5.84

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 (34) hide show
  1. package/dist/env/agent/index.js +1 -1
  2. package/dist/env/event-source/index.js +2 -2
  3. package/dist/env/index.js +11 -10
  4. package/dist/env/prompt/index.js +1 -1
  5. package/dist/env/task/index.js +3 -3
  6. package/dist/env/task/plugins/index.js +1 -1
  7. package/dist/env/task/storage/index.js +1 -1
  8. package/dist/env/task/tools/index.js +1 -1
  9. package/dist/env/workflow/index.js +4 -3
  10. package/dist/env/workflow/service/index.js +8 -2
  11. package/dist/env/workflow/storage/index.js +11 -6
  12. package/dist/env/workflow/tools/index.js +15 -1
  13. package/dist/index.js +14 -12
  14. package/dist/shared/@ai-setting/{roy-agent-core-qbgd7bp6.js → roy-agent-core-015vw11k.js} +27 -1
  15. package/dist/shared/@ai-setting/{roy-agent-core-t2q0rwt7.js → roy-agent-core-29fh9mxg.js} +4 -7
  16. package/dist/shared/@ai-setting/roy-agent-core-3sv590cv.js +132 -0
  17. package/dist/shared/@ai-setting/{roy-agent-core-w83v54mj.js → roy-agent-core-7fdzfsm6.js} +42 -135
  18. package/dist/shared/@ai-setting/{roy-agent-core-df3ng0pz.js → roy-agent-core-7nh5h9fn.js} +31 -2
  19. package/dist/shared/@ai-setting/{roy-agent-core-am646wfz.js → roy-agent-core-86d4exyf.js} +5 -2
  20. package/dist/shared/@ai-setting/{roy-agent-core-vgyj2rq9.js → roy-agent-core-akepggsr.js} +150 -6
  21. package/dist/shared/@ai-setting/{roy-agent-core-v3t28k5n.js → roy-agent-core-bt7wezvg.js} +19 -10
  22. package/dist/shared/@ai-setting/roy-agent-core-c67wr8sp.js +11 -0
  23. package/dist/shared/@ai-setting/{roy-agent-core-496zzm5a.js → roy-agent-core-h4h55x4h.js} +183 -3
  24. package/dist/shared/@ai-setting/roy-agent-core-hhrg314p.js +34 -0
  25. package/dist/shared/@ai-setting/{roy-agent-core-r9y8ct0w.js → roy-agent-core-pcdzfwdv.js} +4 -0
  26. package/dist/shared/@ai-setting/{roy-agent-core-p8jv13bm.js → roy-agent-core-qjv8537d.js} +2 -2
  27. package/dist/shared/@ai-setting/roy-agent-core-r5axf0ad.js +751 -0
  28. package/dist/shared/@ai-setting/{roy-agent-core-74cp3zp1.js → roy-agent-core-taxvytzz.js} +4 -1
  29. package/dist/shared/@ai-setting/roy-agent-core-tq9528d3.js +336 -0
  30. package/dist/shared/@ai-setting/{roy-agent-core-j8q8119y.js → roy-agent-core-ya1ayt1k.js} +1 -1
  31. package/package.json +1 -1
  32. package/dist/shared/@ai-setting/roy-agent-core-4t40mkpv.js +0 -206
  33. package/dist/shared/@ai-setting/roy-agent-core-6b57g1zk.js +0 -103
  34. package/dist/shared/@ai-setting/roy-agent-core-a6j7g1qe.js +0 -428
@@ -369,11 +369,11 @@ ${prompt}`;
369
369
  }
370
370
  if (!this._workflowRepo) {
371
371
  try {
372
- const sqlite = await import("./roy-agent-core-74cp3zp1.js");
372
+ const sqlite = await import("./roy-agent-core-taxvytzz.js");
373
373
  this.ensureDataDir();
374
374
  const db = sqlite.getDatabase();
375
375
  sqlite.initializeTables();
376
- const { WorkflowRepository } = await import("./roy-agent-core-am646wfz.js");
376
+ const { WorkflowRepository } = await import("./roy-agent-core-86d4exyf.js");
377
377
  this._workflowRepo = new WorkflowRepository(db);
378
378
  return this._workflowRepo;
379
379
  } catch {
@@ -393,67 +393,11 @@ init_logger();
393
393
  init_decorator();
394
394
  var logger2 = createLogger("AutoTaskPlugin");
395
395
  function createAutoTaskPlugin(config) {
396
- const threshold = config?.threshold ?? 30;
396
+ const threshold = config?.threshold ?? 20;
397
397
  const agentName = config?.agentName ?? "default";
398
- const llmRef = config?.llmComponent ?? null;
399
- const toolRef = config?.toolComponent ?? null;
400
- const toolChoiceModel = config?.model;
401
- const subagentType = config?.subagentType ?? "roy";
398
+ const agentComponent = config?.agentComponent ?? null;
399
+ const subagentType = config?.subagentType ?? "task-agent";
402
400
  let lastProcessedTraceId = "";
403
- let cachedDelegateToolInfo = undefined;
404
- function getDelegateToolInfoImpl() {
405
- if (cachedDelegateToolInfo !== undefined)
406
- return cachedDelegateToolInfo;
407
- if (!toolRef || typeof toolRef.getTool !== "function") {
408
- cachedDelegateToolInfo = null;
409
- return null;
410
- }
411
- const tool = toolRef.getTool("delegate_task");
412
- if (!tool) {
413
- cachedDelegateToolInfo = null;
414
- return null;
415
- }
416
- cachedDelegateToolInfo = {
417
- name: tool.name,
418
- description: tool.description || "",
419
- parameters: tool.parameters ?? {}
420
- };
421
- return cachedDelegateToolInfo;
422
- }
423
- const getDelegateToolInfo = wrapFunction(getDelegateToolInfoImpl, "plugin.auto-task.get-tool-info", { recordParams: false, recordResult: true, log: true });
424
- async function tryInvokeForDelegateImpl(msgs, delegateToolInfo, model, sid) {
425
- const result = await llmRef.invoke({
426
- messages: msgs,
427
- tools: [delegateToolInfo],
428
- model,
429
- context: { sessionId: sid },
430
- skipThresholdCheck: true
431
- });
432
- const toolCalls = result?.output?.toolCalls;
433
- if (!toolCalls || toolCalls.length === 0) {
434
- logger2.warn(`[AutoTaskPlugin] LLM returned no toolCalls (session=${sid.slice(0, 12)}...)`);
435
- return null;
436
- }
437
- for (const tc of toolCalls) {
438
- const tcName = tc.function?.name ?? tc.name;
439
- const rawArgs = tc.function?.arguments ?? tc.arguments;
440
- const rawArgsStr = typeof rawArgs === "string" ? rawArgs : JSON.stringify(rawArgs ?? {});
441
- logger2.debug(`[AutoTaskPlugin] inspecting toolCall name=${tcName ?? "unknown"}, rawArgs=${rawArgsStr.slice(0, 80)} (session=${sid.slice(0, 12)}...)`);
442
- if (tcName !== "delegate_task")
443
- continue;
444
- try {
445
- const args = JSON.parse(typeof rawArgs === "string" ? rawArgs : JSON.stringify(rawArgs ?? {}));
446
- if (args.description && args.prompt) {
447
- return args;
448
- }
449
- logger2.warn(`[AutoTaskPlugin] delegate_task args missing required fields: ${JSON.stringify(args).slice(0, 100)}`);
450
- } catch {
451
- logger2.warn(`[AutoTaskPlugin] Failed to parse delegate_task args: ${String(rawArgs).slice(0, 100)}`);
452
- }
453
- }
454
- return null;
455
- }
456
- const tryInvokeForDelegate = wrapFunction(tryInvokeForDelegateImpl, "plugin.auto-task.invoke-llm", { recordParams: true, recordResult: true, log: true });
457
401
  async function executeImpl(ctx) {
458
402
  try {
459
403
  logger2.debug(`[AutoTaskPlugin] agentName=${ctx.agent.name} (expected=${agentName})`);
@@ -470,90 +414,53 @@ function createAutoTaskPlugin(config) {
470
414
  }
471
415
  lastProcessedTraceId = traceId;
472
416
  logger2.debug(`[AutoTaskPlugin] new query detected (traceId=${traceId.slice(0, 20)}...)`);
473
- if (!llmRef || !toolRef) {
474
- logger2.warn(`[AutoTaskPlugin] llmComponent or toolComponent not provided at creation (session=${sid.slice(0, 12)}...)`);
475
- return { continue: true };
476
- }
477
- const delegateToolInfo = getDelegateToolInfo();
478
- if (!delegateToolInfo) {
479
- logger2.warn(`[AutoTaskPlugin] delegate_task tool not found in toolComponent (session=${sid.slice(0, 12)}...)`);
417
+ if (!agentComponent || typeof agentComponent.run !== "function") {
418
+ logger2.warn(`[AutoTaskPlugin] agentComponent not provided or invalid (session=${sid.slice(0, 12)}...)`);
480
419
  return { continue: true };
481
420
  }
482
- const msgs = [];
483
- for (const m of ctx.messages) {
421
+ let userQuery = "";
422
+ for (let i = ctx.messages.length - 1;i >= 0; i--) {
423
+ const m = ctx.messages[i];
484
424
  if (m.role === "user") {
485
- msgs.push({
486
- role: "user",
487
- content: typeof m.content === "string" ? m.content : JSON.stringify(m.content)
488
- });
489
- } else if (m.role === "assistant") {
490
- const text = typeof m.content === "string" ? m.content : "";
491
- if (text.trim()) {
492
- msgs.push({ role: "assistant", content: text });
493
- }
425
+ userQuery = typeof m.content === "string" ? m.content : JSON.stringify(m.content);
426
+ break;
494
427
  }
495
428
  }
496
- msgs.push({
497
- role: "user",
498
- content: `Based on the conversation above, please call \`delegate_task\` to hand off the current work to a sub-agent.
499
-
500
- Parameters for delegate_task:
501
- - description: A short 3-8 word title describing this work
502
- - prompt: Detailed instructions for the sub-agent to continue the work
503
- - subagent_type: Use "${subagentType}"
504
- - similar_task_ids: []
429
+ if (!userQuery) {
430
+ userQuery = "分析项目结构并执行相关任务";
431
+ }
432
+ logger2.info(`[AutoTaskPlugin] Calling agentComponent.run("${subagentType}") at iteration ${ctx.iteration} (session=${sid.slice(0, 12)}..., persistSession=false)`);
433
+ const shortDesc = typeof userQuery === "string" ? userQuery.slice(0, 50) : "分析需求";
434
+ const beforeMsg = `
505
435
 
506
- Call delegate_task now.`
507
- });
508
- const model = toolChoiceModel ?? ctx.context?.model ?? ctx.agent?.config?.model;
509
- logger2.info(`[AutoTaskPlugin] Invoking LLM (model=${model}) for delegate_task args at iteration ${ctx.iteration} (session=${sid.slice(0, 12)}...)`);
510
- let args = await tryInvokeForDelegate(msgs, delegateToolInfo, model, sid);
511
- if (!args) {
512
- logger2.info(`[AutoTaskPlugin] Retrying with alternative prompt (session=${sid.slice(0, 12)}...)`);
513
- const retryMsgs = [
514
- ...msgs,
515
- {
516
- role: "user",
517
- content: `Please call \`delegate_task\` now with description (short title), prompt (detailed instructions), subagent_type="${subagentType}", and similar_task_ids=[].`
518
- }
519
- ];
520
- args = await tryInvokeForDelegate(retryMsgs, delegateToolInfo, model, sid);
436
+ ---
437
+ ⏳ **${subagentType} 正在执行**: ${shortDesc}(等待结果...)`;
438
+ if (ctx.toolResult?.result?.output !== undefined) {
439
+ ctx.toolResult.result.output += beforeMsg;
521
440
  }
522
- if (!args) {
523
- logger2.warn(`[AutoTaskPlugin] Failed to get delegate_task args after retry (session=${sid.slice(0, 12)}...)`);
524
- return { continue: true };
441
+ let taskAgentFinalText = "";
442
+ try {
443
+ const taskAgentResult = await agentComponent.run(subagentType, userQuery, {
444
+ sessionId: sid,
445
+ traceId,
446
+ persistSession: false
447
+ });
448
+ taskAgentFinalText = taskAgentResult?.finalText || "";
449
+ logger2.info(`[AutoTaskPlugin] task-agent completed (session=${sid.slice(0, 12)}..., finalTextLength=${taskAgentFinalText.length})`);
450
+ } catch (err) {
451
+ logger2.error(`[AutoTaskPlugin] task-agent failed: ${err instanceof Error ? err.message : String(err)}`);
452
+ taskAgentFinalText = `❌ **${subagentType} 执行失败**: ${err instanceof Error ? err.message : String(err)}`;
525
453
  }
526
- logger2.info(`[AutoTaskPlugin] LLM generated delegate_task args: description="${String(args.description).slice(0, 50)}", subagent_type=${args.subagent_type}`);
527
- const execResult = await toolRef.execute({
528
- name: "delegate_task",
529
- args: {
530
- description: args.description,
531
- prompt: args.prompt,
532
- subagent_type: args.subagent_type || subagentType,
533
- similar_task_ids: args.similar_task_ids || []
534
- },
535
- context: {
536
- session_id: sid,
537
- agent: ctx.agent.name
538
- },
539
- skipHooks: true
540
- });
541
- if (execResult.success && ctx.toolResult?.result?.output !== undefined) {
542
- const bgProcessId = execResult.result?.bgProcessId ?? "unknown";
454
+ if (taskAgentFinalText && ctx.toolResult?.result?.output !== undefined) {
543
455
  const injection = `
544
456
 
545
457
  ---
546
- \uD83D\uDE80 **Task Delegated**: 已通过 delegate_task 委托给子 agent(${subagentType})在后台运行。
547
-
548
- ⏳ 请等待后台任务运行结果通知,无需额外操作。
549
-
550
- \uD83D\uDCCB 后台进程 ID: \`${bgProcessId}\`
458
+ ${taskAgentFinalText}
551
459
  ---`;
552
460
  ctx.toolResult.result.output += injection;
553
- logger2.info(`[AutoTaskPlugin] delegate_task called (bgProcessId=${bgProcessId}, session=${sid.slice(0, 12)}...)`);
554
- } else {
555
- const errMsg = execResult?.output || execResult?.error || "unknown error";
556
- logger2.warn(`[AutoTaskPlugin] delegate_task execution failed: success=${execResult?.success}, error=${String(errMsg).slice(0, 200)}`);
461
+ logger2.info(`[AutoTaskPlugin] task-agent finalText injected (session=${sid.slice(0, 12)}...)`);
462
+ } else if (!ctx.toolResult?.result?.output) {
463
+ logger2.warn(`[AutoTaskPlugin] toolResult unavailable for injection`);
557
464
  }
558
465
  return { continue: true };
559
466
  } catch (err) {
@@ -561,15 +468,15 @@ Call delegate_task now.`
561
468
  return { continue: true };
562
469
  }
563
470
  }
564
- const execute = wrapFunction(executeImpl, "plugin.auto-task.tool-call-hook", {
471
+ const execute = wrapFunction(executeImpl, "plugin.auto-task.launch-agent", {
565
472
  recordParams: false,
566
473
  recordResult: true,
567
474
  log: true
568
475
  });
569
476
  return {
570
477
  name: "AutoTaskPlugin",
571
- version: "3.0.0",
572
- description: "ReAct iteration 达到阈值时通过 LLM 生成 delegate_task 入参并直接调用",
478
+ version: "4.5.0",
479
+ description: "ReAct iteration 达到阈值时 await task-agent 执行并提取 delegate_task 结果注入 tool result",
573
480
  hooks: [
574
481
  { point: "agent:after.tool", priority: 50 }
575
482
  ],
@@ -66,7 +66,8 @@ var UpdateTaskToolSchema = z.object({
66
66
  due_date: z.string().optional(),
67
67
  tags: z.array(z.string()).optional(),
68
68
  project_path: z.string().optional().describe("Project path, identifies which project this task belongs to"),
69
- context: z.string().optional().describe("Task context information for storing additional context")
69
+ context: z.string().optional().describe("Task context information for storing additional context"),
70
+ parent_task_id: z.union([z.number(), z.null()]).optional().describe("Parent task ID (set to null to make it a root task)")
70
71
  });
71
72
  var DeleteTaskToolSchema = z.object({
72
73
  task_id: z.number().describe("Task ID")
@@ -446,6 +447,22 @@ function batchDeleteTaskTool(taskComponent) {
446
447
  init_env_context();
447
448
  init_logger();
448
449
  var logger2 = createLogger("tool:update-task");
450
+ async function detectCycle(taskComponent, taskId, newParentId) {
451
+ const visited = new Set;
452
+ let currentId = newParentId;
453
+ while (currentId !== null && currentId !== undefined) {
454
+ if (currentId === taskId)
455
+ return true;
456
+ if (visited.has(currentId))
457
+ break;
458
+ visited.add(currentId);
459
+ const currentTask = await taskComponent.getTask(currentId);
460
+ if (!currentTask)
461
+ break;
462
+ currentId = currentTask.parent_task_id;
463
+ }
464
+ return false;
465
+ }
449
466
  function updateTaskTool(taskComponent) {
450
467
  return {
451
468
  name: "task_update",
@@ -455,6 +472,17 @@ function updateTaskTool(taskComponent) {
455
472
  const params = UpdateTaskToolSchema.parse(args);
456
473
  const sessionId = ctx.session_id || "unknown";
457
474
  try {
475
+ if (params.parent_task_id !== undefined && params.parent_task_id !== null) {
476
+ const hasCycle = await detectCycle(taskComponent, params.task_id, params.parent_task_id);
477
+ if (hasCycle) {
478
+ return {
479
+ success: false,
480
+ output: "",
481
+ error: `Circular reference detected: setting parent_task_id to ${params.parent_task_id} for task #${params.task_id} would create a cycle`,
482
+ metadata: { execution_time_ms: 0 }
483
+ };
484
+ }
485
+ }
458
486
  const task = await taskComponent.updateTask(params.task_id, {
459
487
  title: params.title,
460
488
  description: params.description,
@@ -467,7 +495,8 @@ function updateTaskTool(taskComponent) {
467
495
  due_date: params.due_date,
468
496
  tags: params.tags,
469
497
  project_path: params.project_path,
470
- context: params.context
498
+ context: params.context,
499
+ parent_task_id: params.parent_task_id
471
500
  });
472
501
  if (!task) {
473
502
  return {
@@ -1,14 +1,17 @@
1
1
  import {
2
2
  WorkflowRepository,
3
+ migrateEmptyTagsToDefault,
3
4
  rowToWorkflow
4
- } from "./roy-agent-core-496zzm5a.js";
5
- import"./roy-agent-core-6b57g1zk.js";
5
+ } from "./roy-agent-core-h4h55x4h.js";
6
+ import"./roy-agent-core-3sv590cv.js";
6
7
  import"./roy-agent-core-rvxg1wps.js";
8
+ import"./roy-agent-core-k05v31rc.js";
7
9
  import"./roy-agent-core-shme7set.js";
8
10
  import"./roy-agent-core-7z9b1fm8.js";
9
11
  import"./roy-agent-core-c6592r3c.js";
10
12
  import"./roy-agent-core-fs0mn2jk.js";
11
13
  export {
12
14
  rowToWorkflow,
15
+ migrateEmptyTagsToDefault,
13
16
  WorkflowRepository
14
17
  };
@@ -136,7 +136,8 @@ var builtInPrompts = {
136
136
  - **文件浏览 / 读取**:\`ls -la\`、\`cat file.txt\`、\`head -n 20 file.txt\`、\`tail -n 50 log.txt\`、\`grep "pattern" file.txt\`、\`find . -name "*.ts"\`
137
137
  - **状态查询**:\`pwd\`、\`date\`、\`whoami\`、\`which node\`、\`git status\`、\`git log -5\`、\`git diff\`
138
138
  - **简单测试 / 工具调用**:\`echo "hello"\`、\`node --version\`、\`bun --version\`
139
- - **调用一行 \`roy-agent\` 命令**(如 \`bun packages/cli/dist/bin/roy-agent.js tasks list\`)
139
+ - **调用一行 \`roy-agent\` 命令**(如 \`bun packages/cli/dist/bin/roy-agent.js tasks list\`、\`roy-agent workflow list\`、\`roy-agent workflow tag list\`、\`roy-agent workflow search --keyword xxx\`)
140
+ - workflow 创建流程:\`roy-agent workflow add --name <name> --file <yaml> --tags "tag1,tag2"\`,创建前可用 \`roy-agent workflow validate --file <yaml>\` 验证 YAML 语法
140
141
 
141
142
  **\`bash\` 适合 vs 需要委托的边界:**
142
143
  - ✅ \`ls -la\`、\`cat file.txt\`、\`grep "TODO" src/*.ts\`、\`git status\`、\`find . -name "*.ts"\` — **直接用 \`bash\` 执行**
@@ -245,6 +246,21 @@ delegate_task(
245
246
  4. **搜索相似任务并委托** — 在委托前,先使用 \`task_search\` 搜索与当前请求相关的历史任务,将找到的相似任务 ID 填入 \`similar_task_ids\` 参数。在给子智能体的提示词中,始终包含简要指令,要求将工作视为任务一等公民:创建任务(\`task_create\`)、跟踪进度并完成。
246
247
  5. **汇报结果** — 向用户总结结果
247
248
 
249
+ ## Workflow 创建指南
250
+
251
+ 当收到用户请求**创建/注册 Workflow** 时,必须遵循以下标准流程:
252
+
253
+ ### 流程
254
+ 1. **先查 tag 池** — 调用 \`bash\` 执行 \`roy-agent workflow tag list\` 查看现有 tag,选择语义最匹配的 1-3 个 tag
255
+ 2. **验证 YAML** — 调用 \`bash\` 执行 \`roy-agent workflow validate --file <yaml路径>\` 验证 Workflow 定义语法
256
+ 3. **注册 Workflow** — 确认验证通过后,用 \`roy-agent workflow add --name <name> --file <yaml> --tags "tag1,tag2"\` 注册
257
+ 4. **核实结果** — 用 \`roy-agent workflow get <name>\` 或 \`roy-agent workflow list --tag <tag>\` 确认注册成功
258
+
259
+ ### Tag 选择原则
260
+ - **必选已有 tag**:优先从 \`workflow tag list\` 显示的已有 tag 池中选语义最相似的
261
+ - **新增 tag**:池中确实没有合适 tag 时才新增,以扩展 tag 池
262
+ - **避免膨胀**:已有 \`ci-cd\` 时不新增 \`continuous-integration\`,已有 \`build-publish\` 时不新增 \`release-deploy\`
263
+
248
264
  ## 行为规则
249
265
 
250
266
  1. **复杂任务必须委托** — 不要尝试自己解决复杂任务。使用 \`delegate_task\` 委托给子智能体。
@@ -287,6 +303,37 @@ delegate_task(
287
303
  - 遇到阻塞:尝试绕过或选替代方案,无法绕过的暂停任务等用户回来
288
304
  - 任务完成:记录完整结果,用户回来时统一汇报
289
305
 
306
+
307
+ ## Workflow 操作指南
308
+
309
+ Workflow 是预定义的自动化流程,可以高效解决常见类型的任务。在接手一个复杂任务时,**建议先用 workflow 检索看看有没有现成的解决方案**。
310
+
311
+ ### 如何用 workflow 辅助解决任务
312
+ 1. **查 tag 发现可用 workflow**:\`workflow tag list\` — 查看 tag 池,找与任务领域匹配的 tag
313
+ 2. **按 tag 搜索 workflow**:\`workflow list --tag <tag>\` — 找到相关的 workflow
314
+ 3. **按关键词搜索**:\`workflow search --keyword <key>\` — 用关键词匹配
315
+ 4. **查看详情**:\`workflow get <name>\` — 了解 workflow 的输入参数和节点流程
316
+ 5. **运行 workflow**:\`workflow run <name> --input '{"key":"value"}'\` — 直接执行
317
+
318
+ > \uD83D\uDCA1 **什么时候该用 workflow?**
319
+ > - ✅ 你的任务与现有 workflow 的 tag 或描述高度匹配时 → 优先用 \`workflow run\`
320
+ > - ✅ 现有 workflow 可以作为参考模板 → 参考其设计自行实现
321
+ > - ❌ 找不到匹配的 workflow → **用传统方式解决**(委托子智能体、直接编码等)
322
+
323
+ ### 可用命令速查
324
+ - \`workflow tag list\` — 查看所有 tag
325
+ - \`workflow list --tag <tag>\` — 按 tag 搜索
326
+ - \`workflow search --keyword <key>\` — 按关键词搜索
327
+ - \`workflow get <name>\` — 查看详情
328
+ - \`workflow run <name>\` — 执行 workflow(如果已找到匹配的)
329
+ - \`workflow add --file <path> --tags "a,b,c"\` — 添加新 workflow
330
+ - \`workflow validate --file <path>\` — 验证 workflow 定义
331
+
332
+ ### ⚠️ 重要原则
333
+ - **Workflow 是辅助手段,不是目的**。如果能找到现成 workflow 就使用它;如果找不到或效果不好,**用非 workflow 方式解决**也是完全正确的
334
+ - **不要为了用 workflow 而用**,强行创建一个不合适的 workflow 来套用任务不如直接用传统方式解决
335
+ - **委托子智能体时**:如果认为有 workflow 可能帮助子智能体,可以在 prompt 中提示子智能体先查询 tag 池搜索可用 workflow
336
+
290
337
  ### {{memory}}`,
291
338
  roy: `You are Roy, a versatile AI assistant inspired by Jarvis - intelligent, proactive, and capable.
292
339
 
@@ -337,6 +384,13 @@ roy-agent <command>
337
384
  | Command | Description |
338
385
  |---------|-------------|
339
386
  | \`roy-agent workflow\` | Workflow DAG management and execution |
387
+ | \`roy-agent workflow list\` | List workflows (paginated, supports --tag/--search/--limit/--page) |
388
+ | \`roy-agent workflow get <name>\` | Get workflow definition details |
389
+ | \`roy-agent workflow add\` | Add new workflow (requires --name --file --tags 1-3) |
390
+ | \`roy-agent workflow validate --file <yaml>\` | Validate workflow YAML definition syntax |
391
+ | \`roy-agent workflow tag list\` | List all available tags with usage counts |
392
+ | \`roy-agent workflow tag get <name>\` | Get tag details by name |
393
+ | \`roy-agent workflow search --keyword\` | Search workflows by keyword and/or tags |
340
394
  | \`roy-agent eventsource\` / \`roy-agent es\` | Event source management (lark-cli, timer, websocket) |
341
395
  | \`roy-agent mcp\` | MCP (Model Context Protocol) server management |
342
396
  | \`roy-agent config\` / \`roy-agent cfg\` | Configuration management |
@@ -420,12 +474,55 @@ roy-agent commands list|add|remove|info|dirs
420
474
  #### Workflow Command
421
475
 
422
476
  \`\`\`bash
423
- roy-agent workflow list|add|nodes|get|update|remove|run|pause|resume|stop|status
477
+ roy-agent workflow list|add|search|get|tag|validate|update|remove|run|pause|resume|stop|status|nodes
424
478
  \`\`\`
425
479
 
426
- - \`roy-agent workflow run <name>\` - Run a workflow
427
- - \`roy-agent workflow status <run-id>\` - Check run status
428
- - \`roy-agent workflow pause|resume|stop <run-id>\` - Control workflow execution
480
+ **Subcommands**:
481
+
482
+ | Subcommand | Description |
483
+ |------------|-------------|
484
+ | \`workflow list [--tag] [--search] [--limit N] [--offset N] [--page N]\` | List workflows with pagination (default limit=50). Filter by tag (single or AND multiple). Shows total count + page info + available_tags. |
485
+ | \`workflow add --file <path> --tags "a,b,c"\` | Add a new workflow from YAML/JSON file. ⚠️ **Tags (1-3) required**. See tag guidance below. |
486
+ | \`workflow search --keyword <key>\` | Search workflows by keyword. |
487
+ | \`workflow get <name>\` | Get workflow definition details. |
488
+ | \`workflow tag list [--sort-by name/usage_count/created_at] [--order desc/asc]\` | List all available tags with usage_count. \`\`\` |
489
+ | \`workflow validate --file <path>\` | Validate a workflow YAML/JSON before adding. Always run this BEFORE \`workflow add\`. |
490
+ | \`workflow run <name> [--input JSON] [--sync/--async]\` | Run a workflow. |
491
+ | \`workflow status <run-id>\` | Check workflow run status. |
492
+ | \`workflow pause/resume/stop <run-id>\` | Control workflow execution. |
493
+ | \`workflow update <id> [--tags] [--description]\` | Update workflow metadata. |
494
+ | \`workflow remove <name>\` | Remove a workflow. |
495
+
496
+ **\uD83C\uDFAF Tag Selection Guidance (IMPORTANT)**:
497
+ When adding a workflow via \`workflow add\` or delegating to a sub-agent:
498
+ 1. **Always** check existing tags first: \`roy-agent workflow tag list\`
499
+ 2. **Prefer reusing** existing tags over creating new ones — this keeps the tag pool compact and semantic
500
+ 3. **Only create new tags** when no existing tag matches the workflow's purpose
501
+ 4. **Example**: For a CI/CD workflow, use existing \`ci-cd\` or \`build-publish\` tags, NOT \`continuous-integration\`
502
+
503
+ **✅ Validation Before Add (REQUIRED)**:
504
+ Before calling \`workflow add\`, always run \`workflow validate --file <path>\` to:
505
+ - Check YAML/JSON syntax
506
+ - Verify node references and dependency graph (DAG)
507
+ - Confirm the workflow will load correctly
508
+ Only proceed to \`workflow add\` after validation passes.
509
+
510
+
511
+ ### \uD83D\uDCA1 Using Workflows to Solve Tasks
512
+
513
+ Workflows are pre-built automation pipelines. When tackling a complex task, **consider checking if an existing workflow can help**:
514
+
515
+ 1. **Discover**: \`roy-agent workflow tag list\` — see the tag pool; \`roy-agent workflow list --tag <tag>\` — find workflows by tag
516
+ 2. **Search**: \`roy-agent workflow search --keyword <key>\` — search by keyword
517
+ 3. **Inspect**: \`roy-agent workflow get <name>\` — examine inputs and structure
518
+ 4. **Run**: \`roy-agent workflow run <name> --input '{"key":"value"}'\` — execute
519
+
520
+ > **When to use workflows:**
521
+ > - ✅ Task matches an existing workflow's tag/description → prefer \`workflow run\`
522
+ > - ✅ Existing workflow serves as a reference → borrow its design
523
+ > - ❌ No matching workflow found → **solve it manually** (delegate sub-agent, direct coding, etc.)
524
+
525
+ **Key principle**: Workflows are here to help, not restrict. If no workflow fits, **do NOT force it** — just solve the task directly. This is the correct approach.
429
526
 
430
527
  #### EventSource Command
431
528
 
@@ -930,7 +1027,54 @@ workflow_run(workflow_name="strict-task-agent", input={"task_description": "修
930
1027
  >
931
1028
  > 设计文档:.roy/design/2026-06-29-workflow-subagent-entry-agent-design.md
932
1029
 
933
- 记住:你是 workflow 的"调度员",不是 workflow 本身。`
1030
+ 记住:你是 workflow 的"调度员",不是 workflow 本身。`,
1031
+ "task-agent": `# Task Agent — 任务优先智能体
1032
+
1033
+ ## 你的身份
1034
+ 当主 agent(default)在 ReAct 循环中达到迭代阈值时,你被调用。你的职责:
1035
+ 1. 分析对话历史,理解用户需求
1036
+ 2. task_create 创建任务
1037
+ 3. task_search 搜索相似任务
1038
+ 4. delegate_task 委托给 roy
1039
+
1040
+ ## 工作目录
1041
+
1042
+ **workspace_dir**: {{workspace_dir}}
1043
+
1044
+ ## 可用工具(全部 task 工具 + delegate_task + bash)
1045
+
1046
+ ### 任务查询工具
1047
+ - task_search(keywords=[...]) — 搜索相关任务(返回任务 ID 列表,用于 similar_task_ids)
1048
+ - task_get(task_id=123) — 查看任务详情
1049
+ - task_list(status="active") — 列出任务
1050
+ - task_operation_list(task_id=123) — 查看操作记录
1051
+
1052
+ ### 任务生命周期工具
1053
+ - task_create(title=..., description=..., progress=0, status="active") — 创建新任务
1054
+ - task_update(task_id=..., ...) — 更新任务状态
1055
+ - task_operation_create(task_id=..., ...) — 记录操作记录
1056
+ - task_complete(task_id=...) — 完成任务
1057
+
1058
+ ### 执行工具
1059
+ - delegate_task(description=..., prompt=..., subagent_type="roy", similar_task_ids=[...]) — 委托给子 agent
1060
+ - bash(command=...) — 执行 shell 命令
1061
+
1062
+ ## 工作流程(严格执行)
1063
+ 1. **分析对话** → 理解用户到底需要做什么
1064
+ 2. **task_create** → 创建任务(title 简短 3-8 字,description 详细,progress=0, status="active")
1065
+ 3. **task_operation_create** → 记录"任务已创建,开始搜索相似任务"里程碑
1066
+ 4. **task_search** → 搜索相似任务获取 similar_task_ids
1067
+ 5. **task_get** → 获取相似任务详情(可选,最多 3 个)
1068
+ 6. **delegate_task** → 委托给 roy:
1069
+ - description: 简短标题(3-8 字)
1070
+ - prompt: 详细的委托指令,包含用户原始需求
1071
+ - subagent_type: "roy"
1072
+ - similar_task_ids: 真实搜索到的 ID 列表(最多 3 个)
1073
+
1074
+ ## 重要规则
1075
+ - delegate_task 是后台模式,调用后立即返回 bgProcessId
1076
+ - 调用 delegate_task 后立即停止,不要再做其他操作
1077
+ - 通过 task_operation_create 记录里程碑`
934
1078
  };
935
1079
  function getBuiltInPromptNames() {
936
1080
  return Object.keys(builtInPrompts);
@@ -7,17 +7,20 @@ import {
7
7
  exports_engine,
8
8
  init_engine
9
9
  } from "./roy-agent-core-6b0r2e7j.js";
10
- import {
11
- WorkflowService
12
- } from "./roy-agent-core-4t40mkpv.js";
13
10
  import {
14
11
  askUserTool,
15
12
  createRunWorkflowTool,
13
+ createWorkflowAddTool,
16
14
  createWorkflowGetTool,
17
15
  createWorkflowListTool,
18
16
  createWorkflowRunStatusTool,
19
- createWorkflowRunStopTool
20
- } from "./roy-agent-core-a6j7g1qe.js";
17
+ createWorkflowRunStopTool,
18
+ createWorkflowSearchTool,
19
+ createWorkflowTagListTool
20
+ } from "./roy-agent-core-r5axf0ad.js";
21
+ import {
22
+ WorkflowService
23
+ } from "./roy-agent-core-tq9528d3.js";
21
24
  import {
22
25
  BaseComponent
23
26
  } from "./roy-agent-core-rgckng3p.js";
@@ -128,7 +131,7 @@ class WorkflowComponent extends BaseComponent {
128
131
  registerDecoratorNodeType2(registry);
129
132
  return new WorkflowEngine2(registry, sessionComponentForEngine, options.workflowRepository);
130
133
  };
131
- this.workflowService = new WorkflowService(options.workflowRepository, engineFactory, options.sessionComponent);
134
+ this.workflowService = new WorkflowService(options.workflowRepository, engineFactory, options.sessionComponent, options.tagRepository);
132
135
  return this.workflowService;
133
136
  }
134
137
  async runWorkflow(definition, input, options) {
@@ -164,7 +167,7 @@ class WorkflowComponent extends BaseComponent {
164
167
  if (this.workflowService) {
165
168
  this.workflowService = null;
166
169
  try {
167
- const { closeDatabase } = await import("./roy-agent-core-74cp3zp1.js");
170
+ const { closeDatabase } = await import("./roy-agent-core-taxvytzz.js");
168
171
  closeDatabase();
169
172
  componentLogger.info("[WorkflowComponent] SQLite database closed");
170
173
  } catch (error) {
@@ -214,6 +217,9 @@ class WorkflowComponent extends BaseComponent {
214
217
  const tools = [
215
218
  createWorkflowGetTool(this.workflowService),
216
219
  createWorkflowListTool(this.workflowService),
220
+ createWorkflowAddTool(this.workflowService),
221
+ createWorkflowSearchTool(this.workflowService),
222
+ createWorkflowTagListTool(this.workflowService),
217
223
  createRunWorkflowTool(this.workflowService),
218
224
  createWorkflowRunStatusTool(this.workflowService),
219
225
  createWorkflowRunStopTool(this.workflowService)
@@ -228,11 +234,13 @@ class WorkflowComponent extends BaseComponent {
228
234
  }
229
235
  async initSqliteService() {
230
236
  try {
231
- const { getDatabase, initializeTables } = await import("./roy-agent-core-74cp3zp1.js");
232
- const { WorkflowRepository } = await import("./roy-agent-core-am646wfz.js");
237
+ const { getDatabase, initializeTables } = await import("./roy-agent-core-taxvytzz.js");
238
+ const { WorkflowRepository } = await import("./roy-agent-core-86d4exyf.js");
239
+ const { TagRepository } = await import("./roy-agent-core-c67wr8sp.js");
233
240
  const db = getDatabase();
234
241
  initializeTables();
235
242
  const workflowRepository = new WorkflowRepository(db);
243
+ const tagRepository = new TagRepository(db);
236
244
  const toolComponent = this.toolComponent || this._workflowEnv?.getComponent("tool");
237
245
  const llmComponent = this.llmComponent || this._workflowEnv?.getComponent("llm");
238
246
  const agentComponent = this._workflowEnv?.getComponent("agent");
@@ -245,6 +253,7 @@ class WorkflowComponent extends BaseComponent {
245
253
  }
246
254
  this.createService({
247
255
  workflowRepository,
256
+ tagRepository,
248
257
  toolComponent,
249
258
  llmComponent,
250
259
  env: this._workflowEnv,
@@ -299,7 +308,7 @@ class WorkflowComponent extends BaseComponent {
299
308
  this.workflowService = null;
300
309
  this.nodeRegistry = null;
301
310
  try {
302
- const { closeDatabase } = await import("./roy-agent-core-74cp3zp1.js");
311
+ const { closeDatabase } = await import("./roy-agent-core-taxvytzz.js");
303
312
  closeDatabase();
304
313
  } catch {}
305
314
  this._status = "stopped";
@@ -0,0 +1,11 @@
1
+ import {
2
+ TagRepository
3
+ } from "./roy-agent-core-3sv590cv.js";
4
+ import"./roy-agent-core-k05v31rc.js";
5
+ import"./roy-agent-core-shme7set.js";
6
+ import"./roy-agent-core-7z9b1fm8.js";
7
+ import"./roy-agent-core-c6592r3c.js";
8
+ import"./roy-agent-core-fs0mn2jk.js";
9
+ export {
10
+ TagRepository
11
+ };