@migor/cli 0.9.4 → 0.10.0
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/CHANGELOG.md +1280 -4
- package/dist/AGENTS.md +330 -45
- package/dist/cli.js +14 -2
- package/dist/dev-machine.js +5 -0
- package/dist/dev.js +3 -0
- package/dist/export.js +276 -0
- package/dist/templates/package.json +2 -2
- package/package.json +4 -1
package/dist/cli.js
CHANGED
|
@@ -12,6 +12,7 @@ import { addPackage } from './add.js';
|
|
|
12
12
|
import { reportCommand, USAGE as REPORT_USAGE } from './report.js';
|
|
13
13
|
import { harvestCommand, USAGE as HARVEST_USAGE } from './harvest.js';
|
|
14
14
|
import { diffCommand, USAGE as DIFF_USAGE } from './diff.js';
|
|
15
|
+
import { exportCommand, USAGE as EXPORT_USAGE } from './export.js';
|
|
15
16
|
const USAGE = `agentia —— Agentia 框架命令行工具
|
|
16
17
|
|
|
17
18
|
用法:
|
|
@@ -26,13 +27,15 @@ const USAGE = `agentia —— Agentia 框架命令行工具
|
|
|
26
27
|
agentia harvest <trace.jsonl> 把线上 trace 翻成 eval 用例骨架
|
|
27
28
|
([--out <file.ts>] [--force] [--failed] [--limit N])
|
|
28
29
|
agentia diff <a.jsonl> <b.jsonl> [--json] 两条 trace 的调用树 A/B 比对(有差异时退出码 1)
|
|
30
|
+
agentia export <trace.jsonl> trace 落盘文件 → 训练数据集(JSONL,一行一份 messages)
|
|
31
|
+
([--out <file>] [--ok-only] [--min-score n])
|
|
29
32
|
agentia add <pkg> 安装第三方能力包并登记到 src/registry.ts
|
|
30
33
|
agentia --help 显示本帮助
|
|
31
34
|
agentia --version 显示版本(等价 -v)
|
|
32
35
|
|
|
33
36
|
--json:report / diff / doctor 的机器可读输出 —— stdout 只有一个 JSON 文档、无人类装饰,
|
|
34
|
-
便于脚本与 CI 串接;出错仍走 stderr + 退出码 1。(harvest 没有 --json
|
|
35
|
-
|
|
37
|
+
便于脚本与 CI 串接;出错仍走 stderr + 退出码 1。(harvest / export 没有 --json:它们的 stdout
|
|
38
|
+
本身就是产物 —— eval 文件源码 / 训练数据 JSONL。)
|
|
36
39
|
name 规则:小写字母开头的小写 kebab-case(如 hello、doc-reviewer)
|
|
37
40
|
`;
|
|
38
41
|
// 各子命令自己的用法串 —— 同时供 fail() 与「子命令级 --help」使用(单源,不写两遍)。
|
|
@@ -50,6 +53,7 @@ const SUB_USAGE = {
|
|
|
50
53
|
report: REPORT_USAGE,
|
|
51
54
|
harvest: HARVEST_USAGE,
|
|
52
55
|
diff: DIFF_USAGE,
|
|
56
|
+
export: EXPORT_USAGE,
|
|
53
57
|
add: ADD_USAGE,
|
|
54
58
|
};
|
|
55
59
|
function fail(message) {
|
|
@@ -173,6 +177,14 @@ function main(argv) {
|
|
|
173
177
|
});
|
|
174
178
|
return 0;
|
|
175
179
|
}
|
|
180
|
+
if (command === 'export') {
|
|
181
|
+
// 异步命令(读文件/写文件):同 report 的受理模式
|
|
182
|
+
void exportCommand(rest).catch((e) => {
|
|
183
|
+
console.error(`错误:${e.message}`);
|
|
184
|
+
process.exitCode = 1;
|
|
185
|
+
});
|
|
186
|
+
return 0;
|
|
187
|
+
}
|
|
176
188
|
if (command === 'add') {
|
|
177
189
|
const [pkg, ...extra] = rest;
|
|
178
190
|
if (pkg === undefined || extra.length > 0) {
|
package/dist/dev-machine.js
CHANGED
|
@@ -378,6 +378,11 @@ export function update(state, ev) {
|
|
|
378
378
|
// 兜底计时器只可能在 aborting 相位到点;否则是已被 disarm 的残余(防御性忽略)
|
|
379
379
|
if (state.run !== 'aborting')
|
|
380
380
|
return { state, effects: [] };
|
|
381
|
+
// ⚠️ 相位语义在此处有意弱化:相位随 restart 效果**发出**就落 idle(受理闸随之打开),
|
|
382
|
+
// 不等 stopChild 真把旧子进程停掉 —— 旧代码是「关到真停」。之所以安全:此刻 restart 链
|
|
383
|
+
// 必为空(aborting 只可能从 running 进,launching 期闸在 409 挡着;file-changed 在飞时
|
|
384
|
+
// 只记 pendingRestart 不排队),且派发的效果链在微任务内连跑到 stopChild,HTTP 请求
|
|
385
|
+
// 插不进这个窗口。哪天链上插进了会先 await 的环节,先重审这句再动。
|
|
381
386
|
return {
|
|
382
387
|
state: {
|
|
383
388
|
...state,
|
package/dist/dev.js
CHANGED
|
@@ -571,6 +571,9 @@ export function devServer(argv = []) {
|
|
|
571
571
|
* 没有面板侧超时(用户可能慢慢选);进程退出时由 `killActivePickers()` 收编。
|
|
572
572
|
*/
|
|
573
573
|
const pickFolder = async () => {
|
|
574
|
+
// ui-pick-requested 发出的 pick-folder 效果是**纯标记**:它没有任何执行器,
|
|
575
|
+
// SPECIAL_ONLY 的作用只是让它万一走到通用执行器时响亮失败 —— 真 spawn 就是下面
|
|
576
|
+
// 这行 pickFolderNative()。机器只负责把 picking 相位立起来(串行化闸),不碰进程。
|
|
574
577
|
const r = update(state, { type: 'ui-pick-requested' });
|
|
575
578
|
state = r.state;
|
|
576
579
|
throwIfRejected(r.effects);
|
package/dist/export.js
ADDED
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `agentia export <file.jsonl>` —— trace 落盘文件 → 训练数据集(JSONL,一行一份
|
|
3
|
+
* `{ messages, meta }`)(R8-P3b:质量闭环的另一半 —— harvest 产 eval 用例,这里产训练数据)。
|
|
4
|
+
*
|
|
5
|
+
* 读 trace 落盘文件(裸 Trace 或含 result.trace / trace 的记录,同 `agentia report` 的
|
|
6
|
+
* 输入),每条翻成一份 Anthropic Messages 形状的训练记录。缺省写 stdout(它**就是**产物,
|
|
7
|
+
* 与 harvest 同款 —— 刻意没有 --json);`--out <file>` 落盘并在 stderr 打一行汇总。
|
|
8
|
+
*
|
|
9
|
+
* 过滤:`--ok-only`(只要 status ok 的 run);`--min-score <n>`(run 根 score 事件的
|
|
10
|
+
* 最大值 ≥ n 才保留 —— 没带分数的 run 在此过滤下**被排除**:它们是没判过的,不是及格)。
|
|
11
|
+
*
|
|
12
|
+
* ⚠️ 生成器与框架侧 `src/eval/export.ts` 的 `exportRun` **同源同形** —— CLI 零运行时
|
|
13
|
+
* 依赖、不能 import 框架,此处是去类型移植(正文逐行相同;本地镜像类型用可选字段 +
|
|
14
|
+
* `?? []` / `?? ''` 兜底,与 harvest 移植同款)。**产物**逐字一致由
|
|
15
|
+
* packages/cli/test/export.test.mjs 的对拍守着(改生成格式必须两边同步)。
|
|
16
|
+
*/
|
|
17
|
+
import { readFile, writeFile } from 'node:fs/promises';
|
|
18
|
+
import { extractTrace } from './report.js';
|
|
19
|
+
/** 原始输入占位(trace 不记 run 的原始输入 —— 与框架侧同一个词) */
|
|
20
|
+
const INPUT_PLACEHOLDER = '[export] 原始输入未入 trace —— 训练前请补写真实用户输入';
|
|
21
|
+
/** 任意值 → 字符串(core/json.ts stringifySafe 的移植) */
|
|
22
|
+
function stringifySafe(x) {
|
|
23
|
+
if (typeof x === 'string')
|
|
24
|
+
return x;
|
|
25
|
+
try {
|
|
26
|
+
return JSON.stringify(x) ?? String(x);
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
return String(x);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
function toolEvents(turn, name) {
|
|
33
|
+
const out = [];
|
|
34
|
+
for (const e of turn.events ?? []) {
|
|
35
|
+
if (e.name !== name)
|
|
36
|
+
continue;
|
|
37
|
+
const b = (e.body ?? {});
|
|
38
|
+
// 缺 `tool` 的事件跳过、不回填占位名(与框架侧 src/eval/export.ts 逐字同步):
|
|
39
|
+
// 伪造的 'unknown' 会变成一个训练必然「学会」的假工具调用。
|
|
40
|
+
if (typeof b.tool !== 'string')
|
|
41
|
+
continue;
|
|
42
|
+
out.push({
|
|
43
|
+
tool: b.tool,
|
|
44
|
+
toolUseId: typeof b.tool_use_id === 'string' ? b.tool_use_id : undefined,
|
|
45
|
+
input: b.input === undefined ? undefined : stringifySafe(b.input),
|
|
46
|
+
ok: typeof b.ok === 'boolean' ? b.ok : undefined,
|
|
47
|
+
content: b.content === undefined ? undefined : stringifySafe(b.content),
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
return out;
|
|
51
|
+
}
|
|
52
|
+
/** 入参还原:尝试 JSON.parse 回对象,失败(或非 object)包 {_raw}(tool_use.input 必须是 object) */
|
|
53
|
+
function parseToolInput(raw) {
|
|
54
|
+
const s = raw ?? '';
|
|
55
|
+
try {
|
|
56
|
+
const parsed = JSON.parse(s);
|
|
57
|
+
return typeof parsed === 'object' && parsed !== null
|
|
58
|
+
? parsed
|
|
59
|
+
: { _raw: s };
|
|
60
|
+
}
|
|
61
|
+
catch {
|
|
62
|
+
return { _raw: s };
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
/** 导出一条 trace 为训练数据记录(与框架侧 exportRun 逐字同形;形状与纪律见其文件头)。 */
|
|
66
|
+
export function exportRun(trace) {
|
|
67
|
+
const spans = trace.spans ?? [];
|
|
68
|
+
const root = spans.find((s) => s.spanId === trace.rootSpanId);
|
|
69
|
+
const mainTurns = spans
|
|
70
|
+
.filter((s) => s.kind === 'llm.turn' && s.parentSpanId === trace.rootSpanId)
|
|
71
|
+
.sort((a, b) => (a.startedAt ?? 0) - (b.startedAt ?? 0));
|
|
72
|
+
const nestedTurns = spans.filter((s) => s.kind === 'llm.turn' && s.parentSpanId !== trace.rootSpanId).length;
|
|
73
|
+
const incomplete = ['input']; // 首条 user 恒为占位(trace 不记原始输入)
|
|
74
|
+
let droppedOutputs = 0;
|
|
75
|
+
let tuSeq = 0;
|
|
76
|
+
// 「本 run 压根没开 traceContent」是 run 根上的 ground truth(loop.ts 写入)。它不能直接
|
|
77
|
+
// 用来标缺口(合成 / 老 trace 可能没有这个属性,却真的有正文),只在**收尾**时与
|
|
78
|
+
// 「整棵 trace 一行正文都没有」合取使用,见下面那段。
|
|
79
|
+
const textRecorded = root?.attributes?.['config.traceContent'] === 'full';
|
|
80
|
+
let anyTextRecorded = false;
|
|
81
|
+
const messages = [{ role: 'user', content: INPUT_PLACEHOLDER }];
|
|
82
|
+
for (const turn of mainTurns) {
|
|
83
|
+
const content = [];
|
|
84
|
+
// assistant 文本:只记真值(output.text,R8-P3a);缺了不造占位(占位文本进训练数据是投毒)。
|
|
85
|
+
// 缺口判定:纯 tool_use 回合**本来就没文本**(引擎只在文本非空时记 output.text),
|
|
86
|
+
// 不算缺口;没有 tool_use 又没有文本的回合(终端回合)缺文本才是真缺口。
|
|
87
|
+
const inputs = toolEvents(turn, 'tool.input');
|
|
88
|
+
const text = turn.attributes?.['output.text'];
|
|
89
|
+
if (typeof text === 'string' && text !== '') {
|
|
90
|
+
anyTextRecorded = true;
|
|
91
|
+
content.push({ type: 'text', text });
|
|
92
|
+
}
|
|
93
|
+
else if (inputs.length === 0 && !incomplete.includes('assistant-text')) {
|
|
94
|
+
incomplete.push('assistant-text');
|
|
95
|
+
}
|
|
96
|
+
const usedIds = [];
|
|
97
|
+
for (const e of inputs) {
|
|
98
|
+
const id = e.toolUseId ?? `export_tu_${++tuSeq}`; // 老 trace 无 id 时合成(replay 同款)
|
|
99
|
+
usedIds.push(id);
|
|
100
|
+
content.push({ type: 'tool_use', id, name: e.tool, input: parseToolInput(e.input) });
|
|
101
|
+
}
|
|
102
|
+
if (content.length > 0)
|
|
103
|
+
messages.push({ role: 'assistant', content });
|
|
104
|
+
// tool_result 配对:按 tool_use_id 配本回合的 tool.output;缺输出的补 is_error 占位
|
|
105
|
+
// (协议要求每个 tool_use 都有配对 tool_result —— 残缺历史喂训练是静音投毒)
|
|
106
|
+
if (usedIds.length > 0) {
|
|
107
|
+
const outputs = toolEvents(turn, 'tool.output');
|
|
108
|
+
const byId = new Map(outputs.map((o) => [o.toolUseId, o]));
|
|
109
|
+
const results = [];
|
|
110
|
+
for (const [i, id] of usedIds.entries()) {
|
|
111
|
+
const out = byId.get(id) ?? (outputs[i]?.toolUseId === undefined ? outputs[i] : undefined);
|
|
112
|
+
if (out === undefined) {
|
|
113
|
+
results.push({
|
|
114
|
+
type: 'tool_result',
|
|
115
|
+
tool_use_id: id,
|
|
116
|
+
is_error: true,
|
|
117
|
+
content: '[export] 该 tool_use 的输出未入 trace(失败/截断的 run 段)',
|
|
118
|
+
});
|
|
119
|
+
continue;
|
|
120
|
+
}
|
|
121
|
+
results.push({
|
|
122
|
+
type: 'tool_result',
|
|
123
|
+
tool_use_id: id,
|
|
124
|
+
...(out.ok === false ? { is_error: true } : {}),
|
|
125
|
+
content: out.content ?? '',
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
// 有输出却没配上本回合任何 tool_use(id 对不上):跳过并计数,不静默丢
|
|
129
|
+
droppedOutputs += outputs.filter((o) => o.toolUseId !== undefined && !usedIds.includes(o.toolUseId)).length;
|
|
130
|
+
messages.push({ role: 'user', content: results });
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
// 收尾判定(2026-09-27 ⑪):整棵 trace 一行正文都没有、且本 run 没开 traceContent
|
|
134
|
+
// ⇒ 缺的不只是「终端回合那句话」:**混合回合**(模型先说一句再调工具)的真实正文同样
|
|
135
|
+
// 不在 trace 里,而只看「本回合有没有 tool_use」是判不出来的(那种回合按定义就是
|
|
136
|
+
// 「本来没文本」)。两条合取才成立:有正文就不标(合成 / 老 trace 也照顾到),
|
|
137
|
+
// 开了 traceContent 而没正文也不标(那是模型确实没说话,不是记录缺口)。
|
|
138
|
+
if (!anyTextRecorded && !textRecorded && !incomplete.includes('assistant-text')) {
|
|
139
|
+
incomplete.push('assistant-text');
|
|
140
|
+
}
|
|
141
|
+
// SFT 形状(2026-09-27 ⑫):末条是 user ⇒ 这条样本**没有 loss 目标**(训练器会静默
|
|
142
|
+
// 丢掉它),而它恰恰是「run 没有终答」的形状(半截 run / 只剩工具往返)。标注出来,
|
|
143
|
+
// 别让下游以为每条都能直接用:`--ok-only` 挡不住它 —— status ok ≠ 有终答。
|
|
144
|
+
if (messages[messages.length - 1]?.role === 'user' &&
|
|
145
|
+
!incomplete.includes('no-final-assistant')) {
|
|
146
|
+
incomplete.push('no-final-assistant');
|
|
147
|
+
}
|
|
148
|
+
const scores = [];
|
|
149
|
+
for (const e of root?.events ?? []) {
|
|
150
|
+
if (e.name !== 'score')
|
|
151
|
+
continue;
|
|
152
|
+
const b = (e.body ?? {});
|
|
153
|
+
if (typeof b.name === 'string' && typeof b.value === 'number') {
|
|
154
|
+
scores.push({ name: b.name, value: b.value });
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
return {
|
|
158
|
+
messages,
|
|
159
|
+
meta: {
|
|
160
|
+
traceId: trace.traceId ?? '',
|
|
161
|
+
model: typeof root?.attributes?.model === 'string' ? root.attributes.model : undefined,
|
|
162
|
+
stopReason: typeof root?.attributes?.stop_reason === 'string' ? root.attributes.stop_reason : undefined,
|
|
163
|
+
status: trace.status ?? '',
|
|
164
|
+
scores,
|
|
165
|
+
nestedTurns,
|
|
166
|
+
droppedOutputs,
|
|
167
|
+
incomplete,
|
|
168
|
+
},
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
/* ── CLI 薄壳(框架侧没有对应物:文件读写与过滤是宿主动作)────────────────── */
|
|
172
|
+
/** 用法串(cli.ts 的子命令 `--help` 也从这里取,避免两处各写一份) */
|
|
173
|
+
export const USAGE = '用法:agentia export <trace.jsonl> [--out <file>] [--ok-only] [--min-score <n>]';
|
|
174
|
+
/** score 过滤:run 根 score 事件的最大值 >= min 才保留(没带分数的 run 被排除 —— 没判过 ≠ 及格) */
|
|
175
|
+
function passScore(rec, min) {
|
|
176
|
+
if (min === undefined)
|
|
177
|
+
return true;
|
|
178
|
+
if (rec.meta.scores.length === 0)
|
|
179
|
+
return false;
|
|
180
|
+
return Math.max(...rec.meta.scores.map((s) => s.value)) >= min;
|
|
181
|
+
}
|
|
182
|
+
export async function exportCommand(args) {
|
|
183
|
+
let file;
|
|
184
|
+
let out;
|
|
185
|
+
let okOnly = false;
|
|
186
|
+
let minScore;
|
|
187
|
+
for (let i = 0; i < args.length; i += 1) {
|
|
188
|
+
const a = args[i];
|
|
189
|
+
if (a === '--ok-only') {
|
|
190
|
+
okOnly = true;
|
|
191
|
+
}
|
|
192
|
+
else if (a === '--out') {
|
|
193
|
+
out = args[i + 1];
|
|
194
|
+
if (out === undefined)
|
|
195
|
+
throw new Error(`--out 需要一个文件参数\n${USAGE}`);
|
|
196
|
+
i += 1;
|
|
197
|
+
}
|
|
198
|
+
else if (a === '--min-score') {
|
|
199
|
+
const raw = args[i + 1];
|
|
200
|
+
minScore = Number(raw);
|
|
201
|
+
if (raw === undefined || !Number.isFinite(minScore)) {
|
|
202
|
+
throw new Error(`--min-score 需要一个数值\n${USAGE}`);
|
|
203
|
+
}
|
|
204
|
+
i += 1;
|
|
205
|
+
}
|
|
206
|
+
else if (a.startsWith('--')) {
|
|
207
|
+
throw new Error(`未知参数:${a}\n${USAGE}`);
|
|
208
|
+
}
|
|
209
|
+
else if (file === undefined) {
|
|
210
|
+
file = a;
|
|
211
|
+
}
|
|
212
|
+
else {
|
|
213
|
+
throw new Error(USAGE);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
if (file === undefined)
|
|
217
|
+
throw new Error(USAGE);
|
|
218
|
+
let raw;
|
|
219
|
+
try {
|
|
220
|
+
raw = await readFile(file, 'utf8');
|
|
221
|
+
}
|
|
222
|
+
catch (e) {
|
|
223
|
+
throw new Error(`读不到文件 ${file}(${e.message})`);
|
|
224
|
+
}
|
|
225
|
+
const records = [];
|
|
226
|
+
let badLines = 0;
|
|
227
|
+
let filtered = 0;
|
|
228
|
+
for (const line of raw.split('\n')) {
|
|
229
|
+
const s = line.trim();
|
|
230
|
+
if (!s)
|
|
231
|
+
continue;
|
|
232
|
+
try {
|
|
233
|
+
const t = extractTrace(JSON.parse(s));
|
|
234
|
+
if (!t) {
|
|
235
|
+
badLines += 1;
|
|
236
|
+
continue;
|
|
237
|
+
}
|
|
238
|
+
const rec = exportRun(t);
|
|
239
|
+
if (okOnly && rec.meta.status !== 'ok') {
|
|
240
|
+
filtered += 1;
|
|
241
|
+
continue;
|
|
242
|
+
}
|
|
243
|
+
if (!passScore(rec, minScore)) {
|
|
244
|
+
filtered += 1;
|
|
245
|
+
continue;
|
|
246
|
+
}
|
|
247
|
+
records.push(rec);
|
|
248
|
+
}
|
|
249
|
+
catch {
|
|
250
|
+
badLines += 1;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
if (records.length === 0) {
|
|
254
|
+
throw new Error(`${file} 里没有符合过滤条件的 run` +
|
|
255
|
+
(filtered > 0 ? `(${filtered} 条被过滤)` : '') +
|
|
256
|
+
(badLines > 0 ? `;另有 ${badLines} 行无法解析` : ''));
|
|
257
|
+
}
|
|
258
|
+
const body = `${records.map((r) => JSON.stringify(r)).join('\n')}\n`;
|
|
259
|
+
if (out !== undefined) {
|
|
260
|
+
await writeFile(out, body, 'utf8');
|
|
261
|
+
// 汇总走 stderr:stdout 是产物的纪律在 --out 形态下同样成立(管道里不混人读文本)
|
|
262
|
+
console.error(`已写出 ${records.length} 条训练记录 → ${out}` +
|
|
263
|
+
(filtered > 0 ? `(过滤掉 ${filtered} 条)` : '') +
|
|
264
|
+
(badLines > 0 ? `;跳过无法解析 ${badLines} 行` : ''));
|
|
265
|
+
}
|
|
266
|
+
else {
|
|
267
|
+
process.stdout.write(body);
|
|
268
|
+
// 汇总**也**走 stderr:stdout 是产物的纪律没变,但「跳过了几行」不许静默 ——
|
|
269
|
+
// `--out` 形态会报、既有的 `report` 在 stdout 形态也报,只有这里此前一声不吭
|
|
270
|
+
// ⇒ `agentia export x.jsonl > dataset.jsonl` 静默丢数据(2026-09-27 实测)。
|
|
271
|
+
console.error(`已写出 ${records.length} 条训练记录 → stdout` +
|
|
272
|
+
(filtered > 0 ? `(过滤掉 ${filtered} 条)` : '') +
|
|
273
|
+
(badLines > 0 ? `;跳过无法解析 ${badLines} 行` : ''));
|
|
274
|
+
}
|
|
275
|
+
return 0;
|
|
276
|
+
}
|
|
@@ -9,10 +9,10 @@
|
|
|
9
9
|
"typecheck": "tsc --noEmit -p tsconfig.json"
|
|
10
10
|
},
|
|
11
11
|
"dependencies": {
|
|
12
|
-
"@migor/agentia": "^0.
|
|
12
|
+
"@migor/agentia": "^0.10.0"
|
|
13
13
|
},
|
|
14
14
|
"devDependencies": {
|
|
15
|
-
"@migor/cli": "^0.
|
|
15
|
+
"@migor/cli": "^0.10.0",
|
|
16
16
|
"tsx": "^4.19.0",
|
|
17
17
|
"typescript": "^7.0.2",
|
|
18
18
|
"@types/node": "^22.0.0"
|
package/package.json
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@migor/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.0",
|
|
4
4
|
"description": "Agentia 框架命令行工具:create 脚手架 + g 能力生成 + dev 本地可观测面板(trace inspector)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
7
|
"agentia": "./dist/cli.js"
|
|
8
8
|
},
|
|
9
|
+
"exports": {
|
|
10
|
+
"./package.json": "./package.json"
|
|
11
|
+
},
|
|
9
12
|
"files": [
|
|
10
13
|
"dist",
|
|
11
14
|
"CHANGELOG.md"
|