minimal-agent 0.6.5 → 0.6.6

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.
@@ -0,0 +1,72 @@
1
+ /**
2
+ * ============================================================
3
+ * plugins/workflow-runner/src/stepExecutors/agent.ts —— agent step 执行
4
+ * ------------------------------------------------------------
5
+ * 「受工作流指导的 TAOR」一等公民。作者在 yaml 里 inline 描述一步开放任务
6
+ * (agent: "..."),本执行器起一个**有界 TAOR agent**(miniReAct)随机应变完成:
7
+ * 思考 → 用工具 → 观察 → 反思 → 再来,直到把这一步要的结果做出来。
8
+ *
9
+ * 与 skill: 节点的分工:
10
+ * - skill: 跑一个**外部 SKILL.md 定义的、可复用的**完整 agent(runQuery,maxTurns 50,流式)
11
+ * - agent: 跑一个**inline 描述的、一次性的**有界 agent(miniReAct,白名单工具 + output_schema
12
+ * + 验证闸门),轻、收敛快、产出受验证
13
+ *
14
+ * 与 onError:'recover' 共享 agentCommon 的系统提示词纪律与验证闸门——同一个脑子。
15
+ *
16
+ * 失败语义:agent 放弃 / 空产出 → interpretMiniReActResult 判 ok:false → 本执行器 throw,
17
+ * 走 dispatchActionStep 的正常失败路径,由 step.onError 接管(halt/continue/recover)。
18
+ * —— 与其它动作 step 完全一致:agent 节点自己也能声明 onError:'recover' 被再救一次。
19
+ *
20
+ * 流式:execAgentStep 是 AsyncGenerator,`yield* runMiniReAct(...)` 把子 agent 的
21
+ * text / reasoning / tool_start / tool_end 事件透传到 runWorkflow → UI,内层思考实时可见。
22
+ * ============================================================
23
+ */
24
+ import { ALL_TOOLS } from '../../../../src/plugin-sdk.js';
25
+ import { buildWorkflowAgentSystem, describeCaptureContract, interpretMiniReActResult, } from '../agentCommon.js';
26
+ import { interpolate } from '../expressions.js';
27
+ import { runMiniReAct } from '../miniReAct.js';
28
+ const AGENT_OPENING = `你是一名资深工程师。一个工作流把其中**一步开放任务**交给你自主完成。
29
+ 你受工作流的总目标与已知上下文指导,但具体怎么做由你用工具随机应变决定——把这一步要的结果真正做出来。`;
30
+ const AGENT_NODE_SYSTEM = buildWorkflowAgentSystem(AGENT_OPENING);
31
+ export async function* execAgentStep(step, vars, ctx) {
32
+ if (typeof step.agent !== 'string') {
33
+ throw new Error(`step ${step.id}: 缺少 agent 字段`);
34
+ }
35
+ const task = interpolate(step.agent, vars);
36
+ const goalLine = ctx.goal ? `工作流总目标:${ctx.goal}\n\n` : '';
37
+ const captureLine = describeCaptureContract(step);
38
+ // 可选 context_files:列出 path + hint,让 agent 用 Read 按需取(不 inline 内容)。
39
+ let filesLine = '';
40
+ if (step.context_files && step.context_files.length > 0) {
41
+ const list = step.context_files
42
+ .map((f) => `- ${interpolate(f.path, vars)}${f.hint ? ` — ${f.hint}` : ''}`)
43
+ .join('\n');
44
+ filesLine = `\n\n以下文件可用,按需用 Read 读取:\n${list}`;
45
+ }
46
+ const userMsg = `${goalLine}` +
47
+ `你这一步要完成的任务:\n${task}` +
48
+ `${filesLine}${captureLine}\n\n` +
49
+ `请用工具把它做出来;确实做不成就按约定输出放弃标记。`;
50
+ // 工具集:默认全量 ALL_TOOLS(真 agency);step.allowed_tools 收窄。
51
+ const allowed = step.allowed_tools;
52
+ const tools = allowed && allowed.length > 0
53
+ ? ALL_TOOLS.filter((t) => allowed.includes(t.name))
54
+ : ALL_TOOLS;
55
+ const result = yield* runMiniReAct({
56
+ messages: [
57
+ { role: 'system', content: AGENT_NODE_SYSTEM },
58
+ { role: 'user', content: userMsg },
59
+ ],
60
+ tools,
61
+ output_schema: step.output_schema,
62
+ provider: ctx.provider,
63
+ signal: ctx.signal,
64
+ maxTurns: step.maxTurns ?? 12,
65
+ });
66
+ const outcome = interpretMiniReActResult(result, step.output_schema !== undefined);
67
+ if (!outcome.ok) {
68
+ // 放弃 / 空产出 → 抛错,交给 dispatchActionStep 的失败路径 + step.onError 处置。
69
+ throw new Error(`agent 未完成任务:${outcome.reason}`);
70
+ }
71
+ return outcome.value;
72
+ }
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * ============================================================
3
- * src/workflows/stepExecutors/llm.ts —— llm step 执行
3
+ * plugins/workflow-runner/src/stepExecutors/llm.ts —— llm step 执行
4
4
  * ------------------------------------------------------------
5
5
  * 单轮 LLM 生成。关键设计:
6
6
  * - tools: [] —— 不开任何工具(工具调用应该写成 tool: step)
@@ -54,7 +54,7 @@ export async function* execLlmStep(step, vars, ctx) {
54
54
  if (allowedTools.length === 0) {
55
55
  throw new Error(`step ${step.id}: context_files 启用但 allowed_tools=${JSON.stringify(allowedNames)} 没有匹配的可用工具`);
56
56
  }
57
- return await runMiniReAct({
57
+ return yield* runMiniReAct({
58
58
  messages: [
59
59
  { role: 'system', content: LLM_STEP_SYSTEM_WITH_TOOLS },
60
60
  { role: 'user', content: augmented },
@@ -0,0 +1,41 @@
1
+ name: adaptive-research
2
+ description: |
3
+ 演示「受工作流指导的 TAOR」:确定性骨架 + 两处随机应变。
4
+ - research 步是 agent: 节点 —— 把一个开放任务(调研主题、整理笔记落盘)交给有界子 agent
5
+ 自主用工具完成(思考→搜→写→自我验证)。
6
+ - count_lines 步是确定性 tool,但声明 onError: recover —— 万一路径/前置不对,
7
+ 不整条崩,临时起恢复 agent 把这一步救回。
8
+ 最后 assert 守门。这就是「指导 + 随机应变」按节点滑动的旋钮。
9
+ version: "0.1"
10
+
11
+ inputs:
12
+ - name: topic
13
+ type: string
14
+ required: true
15
+ description: "调研主题"
16
+
17
+ steps:
18
+ # 1. agent 节点:开放式调研,自主决定怎么做,产出笔记并自我验证
19
+ - id: research
20
+ agent: |
21
+ 调研主题「${inputs.topic}」:用你手上的工具搜集 3-5 个关键要点,
22
+ 整理成简洁的中文 markdown,写到 ./out/notes.md(目录不存在就先创建)。
23
+ 写完后用 Read 自检文件确实写好了再收尾。
24
+ capture:
25
+ content: notes
26
+
27
+ # 2. 确定性工具,但带 onError: recover —— 出意外就地自愈,而非崩停
28
+ - id: count_lines
29
+ tool: Bash
30
+ args:
31
+ command: "wc -l ./out/notes.md"
32
+ onError: recover
33
+ recover_hint: "文件不存在或路径不对,就先用 Glob/Read 定位 notes.md 再统计行数"
34
+ capture:
35
+ content: line_report
36
+
37
+ # 3. 守门 assert
38
+ - id: verify
39
+ type: assert
40
+ condition: 'fileExists("./out/notes.md")'
41
+ onFail: "调研笔记 ./out/notes.md 未生成,检查 research 步"