minimal-agent 0.3.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md
CHANGED
|
@@ -258,9 +258,13 @@ YAML DAG workflow 执行器,支持 7 种 step:
|
|
|
258
258
|
|
|
259
259
|
```bash
|
|
260
260
|
/workflow youtube-shorts --input topic="猫咪赛博朋克城市探险"
|
|
261
|
+
/workflow youtube-shorts "猫咪赛博朋克城市探险" # 位置参数:按 inputs 声明顺序映射,.yaml 后缀可省
|
|
261
262
|
/workflows # 列出所有 workflow
|
|
262
263
|
```
|
|
263
264
|
|
|
265
|
+
> ⚠ **位置参数依赖 yaml 文件 `inputs:` 数组的声明顺序**。重排 inputs 顺序会破坏所有现有 CLI 位置参数调用(位置参数会映射到错误的 input)。
|
|
266
|
+
> 多 input workflow 推荐使用 `--input key=value` 显式 KV 形式,更稳。
|
|
267
|
+
|
|
264
268
|
### 写自己的插件
|
|
265
269
|
|
|
266
270
|
参考 `plugins/HOW-TO-WRITE-A-PLUGIN.md`。两种契约任选其一即可生效:
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "minimal-agent",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"description": "最小化 Agent 系统 —— 10 工具 + 插件系统 + workflow DSL + 自动压缩 + OpenAI 兼容 + Ink TUI;NodeNext + tsc 原地编译,dev 用 Bun .ts、install 用 Node .js(学习/教学用)",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE",
|
|
6
6
|
"author": "Bill Wang <leiwang0359@gmail.com>",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: 运行 YAML 工作流(DAG
|
|
3
|
-
argument-hint: <name> [--input key=value ...]
|
|
2
|
+
description: 运行 YAML 工作流(DAG 执行器)。位置参数按 inputs 声明顺序映射,或用 --input k=v 显式传参
|
|
3
|
+
argument-hint: <name> [val ...] [--input key=value ...]
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# /workflow
|
|
@@ -10,6 +10,16 @@ argument-hint: <name> [--input key=value ...]
|
|
|
10
10
|
|
|
11
11
|
用法示例:
|
|
12
12
|
|
|
13
|
-
/workflow hello-workflow
|
|
13
|
+
/workflow hello-workflow alice 位置参数:直接传 inputs 声明里第一个 input
|
|
14
|
+
/workflow hello-workflow alice zh 多个位置参数:按 inputs 顺序填
|
|
15
|
+
/workflow hello-workflow.yaml alice .yaml 后缀可省(带也认)
|
|
16
|
+
/workflow hello-workflow --input name=alice --input lang=zh 显式 KV
|
|
17
|
+
/workflow hello-workflow alice --input lang=zh 混用:位置填 name,--input 填 lang
|
|
18
|
+
|
|
19
|
+
规则:
|
|
20
|
+
- 位置参数按 yaml 文件 `inputs:` 数组的**声明顺序**映射(不是字段名顺序)。多 input workflow 推荐 `--input key=value` 显式 KV,不易出错
|
|
21
|
+
- `--input k=v` 显式 KV 优先级高于位置参数;位置参数对应的 input 已被 KV 占位时,位置参数被丢弃并 stderr 打 warning
|
|
22
|
+
- 多余的位置参数(超过 inputs 声明数量)被丢弃并 stderr 打 warning,不影响 workflow 执行
|
|
23
|
+
- 值含空格时用引号:`/workflow xxx "AI 教程 进阶"`
|
|
14
24
|
|
|
15
25
|
输入 /workflows 查看可用工作流列表。
|
|
@@ -13,15 +13,17 @@
|
|
|
13
13
|
import { findWorkflowByName, listWorkflows } from './loader.js';
|
|
14
14
|
import { runWorkflow } from './runner.js';
|
|
15
15
|
/**
|
|
16
|
-
* 把 "/workflow <name> --input k=v
|
|
16
|
+
* 把 "/workflow <name> [pos1 pos2 ...] [--input k=v ...]" 拆成 name + 显式 inputs + 位置参数。
|
|
17
17
|
* 简单解析器(不依赖第三方):
|
|
18
|
-
* - 第一个非 flag token = name
|
|
19
|
-
* -
|
|
20
|
-
* -
|
|
18
|
+
* - 第一个非 flag token = name;末尾 ".yaml" / ".yml" 自动剥(便于直接用文件名)
|
|
19
|
+
* - 之后所有非 flag token 收进 positional[],由调用方按 def.inputs 声明顺序映射
|
|
20
|
+
* - --input k=v 显式 KV,优先级高于位置参数(同名 input 不会被位置参数覆盖)
|
|
21
|
+
* - 不识别其他 flag(保守跳过其后一个 token)
|
|
21
22
|
*/
|
|
22
23
|
export function parseWorkflowArgs(rawArgs) {
|
|
23
24
|
const tokens = tokenizeArgs(rawArgs);
|
|
24
25
|
const inputs = {};
|
|
26
|
+
const positional = [];
|
|
25
27
|
let name = null;
|
|
26
28
|
for (let i = 0; i < tokens.length; i++) {
|
|
27
29
|
const t = tokens[i];
|
|
@@ -42,10 +44,13 @@ export function parseWorkflowArgs(rawArgs) {
|
|
|
42
44
|
continue;
|
|
43
45
|
}
|
|
44
46
|
if (name === null) {
|
|
45
|
-
name = t;
|
|
47
|
+
name = t.replace(/\.ya?ml$/i, '');
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
positional.push(t);
|
|
46
51
|
}
|
|
47
52
|
}
|
|
48
|
-
return { name, inputs };
|
|
53
|
+
return { name, inputs, positional };
|
|
49
54
|
}
|
|
50
55
|
/** 简单 token 化:双引号包裹的整体当一个 token;其它按空白切。 */
|
|
51
56
|
function tokenizeArgs(s) {
|
|
@@ -119,13 +124,13 @@ function coerceInputs(raw, defs) {
|
|
|
119
124
|
}
|
|
120
125
|
return out;
|
|
121
126
|
}
|
|
122
|
-
/** /workflow <name> [--input k=v] —— 主入口,由 pluginRunner 调用。 */
|
|
127
|
+
/** /workflow <name> [pos...] [--input k=v] —— 主入口,由 pluginRunner 调用。 */
|
|
123
128
|
export async function* runWorkflowFromCommand(rawArgs, opts) {
|
|
124
|
-
const { name, inputs: rawInputs } = parseWorkflowArgs(rawArgs);
|
|
129
|
+
const { name, inputs: rawInputs, positional } = parseWorkflowArgs(rawArgs);
|
|
125
130
|
if (!name) {
|
|
126
131
|
yield {
|
|
127
132
|
type: 'error',
|
|
128
|
-
error: '/workflow 用法: /workflow <name> [--input key=val ...]\n输入 /workflows 查看可用工作流。',
|
|
133
|
+
error: '/workflow 用法: /workflow <name> [val ...] [--input key=val ...]\n输入 /workflows 查看可用工作流。',
|
|
129
134
|
};
|
|
130
135
|
return;
|
|
131
136
|
}
|
|
@@ -137,6 +142,40 @@ export async function* runWorkflowFromCommand(rawArgs, opts) {
|
|
|
137
142
|
};
|
|
138
143
|
return;
|
|
139
144
|
}
|
|
145
|
+
// 位置参数严格按"第 i 个位置参数 ↔ def.inputs[i]"对应。
|
|
146
|
+
// --input k=v 显式优先:已显式的 input 不被位置参数覆盖(对应的位置参数被丢弃,会 warn)。
|
|
147
|
+
// 多余的位置参数(超过 def.inputs 数量)也被丢弃(会 warn)。
|
|
148
|
+
const overriddenByKV = [];
|
|
149
|
+
if (positional.length > 0 && def.inputs) {
|
|
150
|
+
const max = Math.min(positional.length, def.inputs.length);
|
|
151
|
+
for (let i = 0; i < max; i++) {
|
|
152
|
+
const inputDef = def.inputs[i];
|
|
153
|
+
if (inputDef.name in rawInputs) {
|
|
154
|
+
// 已被 --input 占位,位置参数被丢弃
|
|
155
|
+
if (rawInputs[inputDef.name] !== positional[i]) {
|
|
156
|
+
overriddenByKV.push(`${inputDef.name}=${JSON.stringify(rawInputs[inputDef.name])} (位置参数 ${JSON.stringify(positional[i])} 被忽略)`);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
else {
|
|
160
|
+
rawInputs[inputDef.name] = positional[i];
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
// warn:超量位置参数(用户写多了,提示一下)
|
|
165
|
+
if (def.inputs && positional.length > def.inputs.length) {
|
|
166
|
+
const dropped = positional.slice(def.inputs.length);
|
|
167
|
+
yield {
|
|
168
|
+
type: 'workflow_warning',
|
|
169
|
+
message: `⚠ 忽略了 ${dropped.length} 个多余位置参数: ${dropped.map((d) => JSON.stringify(d)).join(' ')}(workflow "${name}" 只声明了 ${def.inputs.length} 个 input)`,
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
// warn:位置参数被 --input 覆盖
|
|
173
|
+
if (overriddenByKV.length > 0) {
|
|
174
|
+
yield {
|
|
175
|
+
type: 'workflow_warning',
|
|
176
|
+
message: `⚠ --input 优先级高于位置参数,以下位置参数被覆盖:${overriddenByKV.join('; ')}`,
|
|
177
|
+
};
|
|
178
|
+
}
|
|
140
179
|
let coerced;
|
|
141
180
|
try {
|
|
142
181
|
coerced = coerceInputs(rawInputs, def.inputs);
|
|
@@ -168,7 +207,10 @@ export async function* runWorkflowsList() {
|
|
|
168
207
|
lines.push(` /workflow ${w.name} — ${w.description.split('\n')[0].trim()}`);
|
|
169
208
|
}
|
|
170
209
|
lines.push('');
|
|
171
|
-
lines.push('运行示例:
|
|
210
|
+
lines.push('运行示例:');
|
|
211
|
+
lines.push(' /workflow <name> <val> 位置参数(按 inputs 声明顺序,第一个 input 直接写值)');
|
|
212
|
+
lines.push(' /workflow <name>.yaml <val> .yaml 后缀可省');
|
|
213
|
+
lines.push(' /workflow <name> --input k=v 显式 KV(多 input 或想跳过中间 input 时用)');
|
|
172
214
|
yield { type: 'text', delta: lines.join('\n') + '\n' };
|
|
173
215
|
yield { type: 'turn_done' };
|
|
174
216
|
}
|
package/src/cli/print.js
CHANGED
|
@@ -102,7 +102,7 @@ export async function runPrintMode(provider, args, initialHistory, options) {
|
|
|
102
102
|
history,
|
|
103
103
|
signal: abortController.signal,
|
|
104
104
|
})) {
|
|
105
|
-
// event 是 LoopEvent | PluginEvent
|
|
105
|
+
// event 是 LoopEvent | PluginEvent;handleEvent 识别 LoopEvent + workflow_warning,其它走 default 静默忽略
|
|
106
106
|
const result = handleEvent(event, output, options.verbose);
|
|
107
107
|
if (result.exitCode !== undefined) {
|
|
108
108
|
await saveContext(history);
|
|
@@ -153,6 +153,11 @@ export function handleEvent(event, output, verbose) {
|
|
|
153
153
|
process.stderr.write(`📝 压缩完成: ${event.before} → ${event.after} tokens\n`);
|
|
154
154
|
}
|
|
155
155
|
return {};
|
|
156
|
+
case 'workflow_warning':
|
|
157
|
+
// workflow 引擎警告(如多余位置参数、--input 覆盖位置参数等)始终走 stderr,
|
|
158
|
+
// 不受 verbose 控制 —— 这是用户必须看到的信号,避免静默丢弃语义被忽略。
|
|
159
|
+
process.stderr.write(`${event.message}\n`);
|
|
160
|
+
return {};
|
|
156
161
|
case 'turn_done':
|
|
157
162
|
if (!verbose)
|
|
158
163
|
console.log(output.buffer);
|