@xdxer/dingtalk-agent 0.1.4-beta.7 → 0.1.4-beta.8
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 +1 -2
- package/dist/bin/dingtalk-agent.js +17 -334
- package/dist/bin/dingtalk-agent.js.map +1 -1
- package/dist/src/init.js +1 -1
- package/dist/src/init.js.map +1 -1
- package/package.json +10 -12
- package/dist/src/boot.js +0 -70
- package/dist/src/boot.js.map +0 -1
- package/dist/src/duty.js +0 -74
- package/dist/src/duty.js.map +0 -1
- package/dist/src/kb.js +0 -240
- package/dist/src/kb.js.map +0 -1
- package/dist/src/runs.js +0 -79
- package/dist/src/runs.js.map +0 -1
- package/docs/ARCHITECTURE.md +0 -219
- package/docs/MINIMAL-WORKSPACE-V1.md +0 -172
- package/docs/OPEN-SOURCE-REFERENCES.md +0 -107
- package/docs/SELF-TEST.md +0 -252
- package/docs//345/206/205/347/275/221/345/256/236/347/233/270.md +0 -77
- package/evals/baselines/2026-07-14/behavior-summary.json +0 -28
- package/evals/baselines/2026-07-14/contract-summary.json +0 -18
- package/evals/baselines/2026-07-14/live-canary-summary.json +0 -25
- package/evals/baselines/2026-07-15/dingtalk-basic-behavior-0.3.0/SKILL.md +0 -72
- package/evals/baselines/2026-07-15/dingtalk-basic-behavior-0.3.0/references/action-contract.md +0 -31
- package/evals/baselines/2026-07-15/dingtalk-basic-behavior-0.3.0/references/event-to-behavior.md +0 -22
- package/evals/baselines/2026-07-15/dingtalk-basic-behavior-0.3.0/references/memory-and-evolution.md +0 -25
- package/evals/baselines/2026-07-15/dingtalk-basic-behavior-0.3.0/references/runtime-modes.md +0 -34
- package/evals/baselines/2026-07-15/task-lifecycle-summary.json +0 -50
- package/evals/evals.json +0 -339
- package/evals/fixtures/dm-ambiguous-send.json +0 -4
- package/evals/fixtures/dm-blocked.json +0 -4
- package/evals/fixtures/dm-clear.json +0 -4
- package/evals/fixtures/dm-discussion.json +0 -4
- package/evals/fixtures/dm-doc-write-no-tool.json +0 -4
- package/evals/fixtures/dm-long-task-ack.json +0 -4
- package/evals/fixtures/dm-nonblocking-gap.json +0 -4
- package/evals/fixtures/dm-structured-task.json +0 -4
- package/evals/fixtures/group.json +0 -10
- package/evals/fixtures/mentioned.json +0 -3
- package/evals/run-contract-evals.mjs +0 -1169
- package/evals/run-shadow-evals.mjs +0 -267
- package/evals/runners/README.md +0 -66
- package/evals/runners/claude-shadow.mjs +0 -533
- package/evals/schemas/action-request.schema.json +0 -77
- package/evals/shadow-evals.json +0 -133
- package/skills/AGENTS.md +0 -104
- package/skills//344/273/273/345/212/241.md +0 -48
- package/skills//345/237/272/347/241/200/350/241/214/344/270/272.md +0 -44
- package/skills//345/277/203/350/267/263.md +0 -79
- package/skills//346/266/210/346/201/257.md +0 -50
- package/skills//347/237/245/350/257/206.md +0 -55
- package/skills//350/257/204/346/265/213.md +0 -62
- package/skills//351/222/211/351/222/211.md +0 -64
- package/templates/ontology/index.md +0 -24
- package/templates/ontology/self/access.md +0 -38
- package/templates/ontology/self/role-spec.md +0 -34
- package/templates/ontology/self/workspace.md +0 -41
package/README.md
CHANGED
|
@@ -253,7 +253,6 @@ dingtalk-agent init
|
|
|
253
253
|
dingtalk-agent prepare --event-file event.json --json
|
|
254
254
|
dingtalk-agent help runtime
|
|
255
255
|
dingtalk-agent help adapters
|
|
256
|
-
dingtalk-agent eval contract
|
|
257
256
|
```
|
|
258
257
|
|
|
259
258
|
`listen` 是可选的开发联调 Adapter,不是 Agent 主进程。云端 Driver、Claude Code 插件或本地 DWS 都可以提供事件,并从标准化事件之后复用同一 Session / Run / Action 内核。
|
|
@@ -266,7 +265,7 @@ npm run typecheck
|
|
|
266
265
|
npm run eval:contract
|
|
267
266
|
```
|
|
268
267
|
|
|
269
|
-
当前确定性合同包含 **
|
|
268
|
+
当前确定性合同包含 **31 个场景**,覆盖:
|
|
270
269
|
|
|
271
270
|
- 通过 `npx skills` 委托全局 Skill 安装、发现、重装和卸载;
|
|
272
271
|
- 首次 setup、用户级 PATH、DWS 版本/认证和三端客户端发现;
|
|
@@ -13,10 +13,6 @@ import { join, resolve } from 'node:path';
|
|
|
13
13
|
import { readFileSync } from 'node:fs';
|
|
14
14
|
import { spawn, spawnSync } from 'node:child_process';
|
|
15
15
|
import * as cfgmod from '../src/config.js';
|
|
16
|
-
import * as kbmod from '../src/kb.js';
|
|
17
|
-
import * as runsmod from '../src/runs.js';
|
|
18
|
-
import * as dutymod from '../src/duty.js';
|
|
19
|
-
import { boot } from '../src/boot.js';
|
|
20
16
|
import { init } from '../src/init.js';
|
|
21
17
|
import { ackDispatch, listPendingDispatches, prepareSession } from '../src/sessions.js';
|
|
22
18
|
import { readEventFile, consumeNdjson, heartbeatEvent } from '../src/driver.js';
|
|
@@ -35,47 +31,23 @@ const ROOT = process.env.DTA_ROOT
|
|
|
35
31
|
? resolve(process.env.DTA_ROOT)
|
|
36
32
|
: (cfgmod.findRoot(process.cwd()) || process.cwd());
|
|
37
33
|
const HELP = `
|
|
38
|
-
dta
|
|
34
|
+
dta —— 给 Agent 安装钉钉员工的基础行为和工作环境
|
|
39
35
|
|
|
40
|
-
|
|
41
|
-
|
|
36
|
+
装好后,Agent 可以:
|
|
37
|
+
· 判断 @、单聊和群消息是否应该回应
|
|
38
|
+
· 通过 DWS 回复消息、协作并使用钉钉标准产品
|
|
39
|
+
· 从本地目录或钉钉文档加载身份、记忆和知识
|
|
42
40
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
setup 用户级安装 CLI、修复 PATH、安装 Skill、检查 DWS
|
|
47
|
-
upgrade 自升级 CLI,并重新执行 setup 与完整 doctor
|
|
48
|
-
[--channel beta|latest] [--version X] [--dry-run] [--force] [--json]
|
|
49
|
-
doctor 检查 PATH / Node / DWS / Skill / Agent 客户端
|
|
41
|
+
开始使用:
|
|
42
|
+
dta setup 首次配置 CLI、DWS 和基础行为 Skill
|
|
43
|
+
dta bootstrap --json 为当前 Agent 会话加载工作区
|
|
50
44
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
skill
|
|
55
|
-
skill uninstall 通过 npx skills 卸载全局 Skill
|
|
56
|
-
通用: [--dry-run] [--json];安装生命周期委托给 npx skills
|
|
45
|
+
维护环境:
|
|
46
|
+
dta doctor 检查哪里没装好,并给出修复提示
|
|
47
|
+
dta upgrade 自升级,再重新检查完整环境
|
|
48
|
+
dta skill status 查看 Claude Code、Codex、OpenCode 能否发现 Skill
|
|
57
49
|
|
|
58
|
-
|
|
59
|
-
bootstrap 发现当前本地 Workspace;不修改项目文件
|
|
60
|
-
[--storage <uri>] local-dir:<path> | dingtalk-doc:<node-or-url>
|
|
61
|
-
[--state-dir <path>] 远端文档只读快照目录
|
|
62
|
-
[--profile <dws-profile>] [--json]
|
|
63
|
-
|
|
64
|
-
可信事件模式(可选;需要一次 init)
|
|
65
|
-
init [--context-id X] 仅为 Prepared Run 建最小 Workspace
|
|
66
|
-
prepare --event-file <file|-> 事件 → Session → Run
|
|
67
|
-
act ack 对原消息贴「收到」;不代表接单
|
|
68
|
-
act reply --text "…" 引用回复原消息
|
|
69
|
-
act ask --text "…" 只问一个真正阻塞的问题
|
|
70
|
-
act silence [--reason "…"] 不外发,但留下行为回执
|
|
71
|
-
通用: [--run <path>] [--dry-run] [--json]
|
|
72
|
-
|
|
73
|
-
smoke 极简本地验收(不写钉钉)
|
|
74
|
-
eval contract / behavior 完整合同或模型行为评测
|
|
75
|
-
|
|
76
|
-
help runtime 事件宿主与 controller 命令
|
|
77
|
-
help adapters 可选 DWS listen 适配器
|
|
78
|
-
help legacy 查看兼容的本体、KB、值班与进化命令
|
|
50
|
+
接入钉钉事件和可靠外发:dta help runtime
|
|
79
51
|
`;
|
|
80
52
|
const RUNTIME_HELP = `
|
|
81
53
|
dingtalk-agent 可信事件运行时(可选宿主能力)
|
|
@@ -98,17 +70,6 @@ dingtalk-agent 可选 Driver / 开发联调适配器
|
|
|
98
70
|
|
|
99
71
|
listen 不是 Agent 主入口。Claude Code、DWS 云端或其他宿主都可以直接提供事件。
|
|
100
72
|
`;
|
|
101
|
-
const LEGACY_HELP = `
|
|
102
|
-
dingtalk-agent 兼容命令(不属于 P0 四对象主链)
|
|
103
|
-
|
|
104
|
-
boot
|
|
105
|
-
kb mount|list|sync|search
|
|
106
|
-
duty --check|--run|--list
|
|
107
|
-
todo
|
|
108
|
-
log / feedback / runs / evolve
|
|
109
|
-
|
|
110
|
-
这些能力继续可用,但新增 Agent 应先安装全局 Skill;只有可信事件宿主才需要 runtime。
|
|
111
|
-
`;
|
|
112
73
|
function fail(msg, code = 1, hint = '') {
|
|
113
74
|
console.error(`错误: ${msg}`);
|
|
114
75
|
if (hint)
|
|
@@ -127,10 +88,6 @@ catch (e) {
|
|
|
127
88
|
fail(message, Number(error?.exitCode) || 2, errorHint(message));
|
|
128
89
|
}
|
|
129
90
|
async function main() {
|
|
130
|
-
if (cmd === 'help' && sub === 'legacy') {
|
|
131
|
-
console.log(LEGACY_HELP);
|
|
132
|
-
return;
|
|
133
|
-
}
|
|
134
91
|
if (cmd === 'help' && sub === 'runtime') {
|
|
135
92
|
console.log(RUNTIME_HELP);
|
|
136
93
|
return;
|
|
@@ -139,6 +96,9 @@ async function main() {
|
|
|
139
96
|
console.log(ADAPTER_HELP);
|
|
140
97
|
return;
|
|
141
98
|
}
|
|
99
|
+
if (cmd === 'help' && sub) {
|
|
100
|
+
fail(`不认识的帮助主题: ${sub}`, 1, '运行 dta --help 回到产品入口;事件宿主可用 dta help runtime。');
|
|
101
|
+
}
|
|
142
102
|
if (!cmd || cmd === '--help' || cmd === '-h' || cmd === 'help') {
|
|
143
103
|
console.log(HELP);
|
|
144
104
|
return;
|
|
@@ -450,285 +410,8 @@ async function main() {
|
|
|
450
410
|
process.exitCode = 2;
|
|
451
411
|
return;
|
|
452
412
|
}
|
|
453
|
-
// ── eval:宿主评测入口;shadow 永不调用 act / DWS。──
|
|
454
|
-
if (cmd === 'eval') {
|
|
455
|
-
const script = sub === 'contract'
|
|
456
|
-
? join(PACKAGE_ROOT, 'evals', 'run-contract-evals.mjs')
|
|
457
|
-
: sub === 'shadow'
|
|
458
|
-
? join(PACKAGE_ROOT, 'evals', 'runners', 'claude-shadow.mjs')
|
|
459
|
-
: sub === 'behavior'
|
|
460
|
-
? join(PACKAGE_ROOT, 'evals', 'run-shadow-evals.mjs')
|
|
461
|
-
: '';
|
|
462
|
-
if (!script)
|
|
463
|
-
fail('eval 的子命令: contract / shadow / behavior');
|
|
464
|
-
const childEnv = { ...process.env };
|
|
465
|
-
// 合同评测会创建隔离工作区;继承宿主 DTA_ROOT 会让 Action Gate 错读外层 control store。
|
|
466
|
-
delete childEnv.DTA_ROOT;
|
|
467
|
-
const child = spawnSync(process.execPath, [script, ...argv.slice(2)], {
|
|
468
|
-
cwd: ROOT,
|
|
469
|
-
env: childEnv,
|
|
470
|
-
stdio: 'inherit',
|
|
471
|
-
});
|
|
472
|
-
if (child.error)
|
|
473
|
-
throw child.error;
|
|
474
|
-
if (child.signal)
|
|
475
|
-
throw new Error(`评测进程被 ${child.signal} 终止`);
|
|
476
|
-
process.exitCode = child.status ?? 2;
|
|
477
|
-
return;
|
|
478
|
-
}
|
|
479
|
-
if (cmd === 'smoke') {
|
|
480
|
-
const script = join(PACKAGE_ROOT, 'evals', 'run-contract-evals.mjs');
|
|
481
|
-
const childEnv = { ...process.env };
|
|
482
|
-
delete childEnv.DTA_ROOT;
|
|
483
|
-
const child = spawnSync(process.execPath, [script, '--smoke'], {
|
|
484
|
-
cwd: ROOT, env: childEnv, stdio: 'inherit',
|
|
485
|
-
});
|
|
486
|
-
if (child.error)
|
|
487
|
-
throw child.error;
|
|
488
|
-
if (child.signal)
|
|
489
|
-
throw new Error(`Smoke 被 ${child.signal} 终止`);
|
|
490
|
-
process.exitCode = child.status ?? 2;
|
|
491
|
-
return;
|
|
492
|
-
}
|
|
493
|
-
// ── kb ──
|
|
494
|
-
if (cmd === 'kb') {
|
|
495
|
-
const cfg = cfgmod.must(ROOT);
|
|
496
|
-
const { values: o } = parseArgs({
|
|
497
|
-
args: argv.slice(2), allowPositionals: true,
|
|
498
|
-
options: {
|
|
499
|
-
name: { type: 'string' }, from: { type: 'string' }, own: { type: 'string' },
|
|
500
|
-
sync: { type: 'string' }, local: { type: 'string' }, force: { type: 'boolean' },
|
|
501
|
-
},
|
|
502
|
-
});
|
|
503
|
-
if (sub === 'mount') {
|
|
504
|
-
if (!o.name || !o.from)
|
|
505
|
-
fail('要 --name 和 --from。源的写法见 --help');
|
|
506
|
-
kbmod.parseSource(o.from); // 写错了当场炸
|
|
507
|
-
const own = o.own || kbmod.EXTERNAL;
|
|
508
|
-
const sync = o.sync || (own === kbmod.OWNED ? kbmod.PUSH : kbmod.PULL);
|
|
509
|
-
if (own === kbmod.OWNED && sync === kbmod.PULL) {
|
|
510
|
-
fail('owned 的真值在 Git,不该 pull —— 那会把远端的东西覆盖到本地。\n' +
|
|
511
|
-
' **所有权决定真值方向。** owned → push;external → pull。');
|
|
512
|
-
}
|
|
513
|
-
const local = o.local || join('.cache/kb', o.name);
|
|
514
|
-
cfg.kb = (cfg.kb || []).filter((k) => k.name !== o.name);
|
|
515
|
-
cfg.kb.push({ name: o.name, from: o.from, own, sync, local });
|
|
516
|
-
cfgmod.save(ROOT, cfg);
|
|
517
|
-
console.log(`✅ 挂上「${o.name}」 ${o.from}`);
|
|
518
|
-
console.log(` 所有权=${own} · 同步=${sync} · 落在 ${local}`);
|
|
519
|
-
console.log(own === kbmod.OWNED
|
|
520
|
-
? ' (真值在 Git,钉钉是暴露层。人在钉钉里改了 → sync 时会【停下来问】,不盲覆盖。)'
|
|
521
|
-
: ' (真值在钉钉,本地只是【可丢弃的缓存】。过期了 kb search 会警告。)');
|
|
522
|
-
return;
|
|
523
|
-
}
|
|
524
|
-
if (sub === 'list') {
|
|
525
|
-
if (!cfg.kb?.length)
|
|
526
|
-
return console.log('一个都没挂。 kb mount --help');
|
|
527
|
-
for (const kb of cfg.kb) {
|
|
528
|
-
const s = kbmod.stale(kb);
|
|
529
|
-
console.log(` ${s ? '⚠️' : '·'} ${kb.name.padEnd(14)} ${kb.own.padEnd(9)} ${kb.sync.padEnd(5)} ${kb.from}`);
|
|
530
|
-
console.log(` 落在 ${kb.local} 上次同步 ${kb._syncedAt || '从未'}${s ? ' ← **过期了,不许拿来回答**' : ''}`);
|
|
531
|
-
}
|
|
532
|
-
return;
|
|
533
|
-
}
|
|
534
|
-
if (sub === 'sync') {
|
|
535
|
-
const targets = (cfg.kb || []).filter((k) => !o.name || k.name === o.name);
|
|
536
|
-
if (!targets.length)
|
|
537
|
-
fail('没有这个知识库。 kb list');
|
|
538
|
-
for (const kb of targets) {
|
|
539
|
-
if (kb.sync === kbmod.NONE) {
|
|
540
|
-
console.log(` skip ${kb.name}(sync=none)`);
|
|
541
|
-
continue;
|
|
542
|
-
}
|
|
543
|
-
if (kb.sync === kbmod.PULL)
|
|
544
|
-
kbmod.pull(kb, ROOT, o.force);
|
|
545
|
-
else
|
|
546
|
-
kbmod.push(kb, ROOT, o.force);
|
|
547
|
-
}
|
|
548
|
-
cfgmod.save(ROOT, cfg);
|
|
549
|
-
return;
|
|
550
|
-
}
|
|
551
|
-
if (sub === 'search') {
|
|
552
|
-
const kw = argv[2];
|
|
553
|
-
if (!kw)
|
|
554
|
-
fail('要给关键词。 kb search "<关键词>"');
|
|
555
|
-
kbmod.search(cfg, ROOT, kw);
|
|
556
|
-
return;
|
|
557
|
-
}
|
|
558
|
-
fail('kb 的子命令: mount / list / sync / search');
|
|
559
|
-
}
|
|
560
|
-
// ── boot ──
|
|
561
|
-
if (cmd === 'boot') {
|
|
562
|
-
boot(cfgmod.must(ROOT), ROOT);
|
|
563
|
-
return;
|
|
564
|
-
}
|
|
565
|
-
// ── duty ──
|
|
566
|
-
if (cmd === 'duty') {
|
|
567
|
-
const cfg = cfgmod.must(ROOT);
|
|
568
|
-
const { values: o } = parseArgs({
|
|
569
|
-
args: argv.slice(1), allowPositionals: true,
|
|
570
|
-
options: { check: { type: 'boolean' }, run: { type: 'string' },
|
|
571
|
-
list: { type: 'boolean' }, force: { type: 'boolean' } },
|
|
572
|
-
});
|
|
573
|
-
const duties = dutymod.loadDuties(cfg, ROOT);
|
|
574
|
-
if (o.list) {
|
|
575
|
-
const ks = Object.keys(duties);
|
|
576
|
-
console.log(ks.length ? ks.join('\n')
|
|
577
|
-
: '(值班表是空的 —— 母体出厂如此,这是【正确】的。在 .dingtalk-agent/config.json 的 duties 里加。)');
|
|
578
|
-
return;
|
|
579
|
-
}
|
|
580
|
-
if (o.run) {
|
|
581
|
-
const fn = duties[o.run];
|
|
582
|
-
if (!fn)
|
|
583
|
-
fail(`没有这个值班: ${o.run}(有: ${Object.keys(duties).join('、') || '无'})`);
|
|
584
|
-
const s = fn();
|
|
585
|
-
if (s.kind === '交付' && !dutymod.inDeliver() && !o.force) {
|
|
586
|
-
return console.log(`⏸ 「${o.run}」是外发动作,静默时段顺延,**不打扰第三方**。`);
|
|
587
|
-
}
|
|
588
|
-
if (s.done)
|
|
589
|
-
return console.log(`✅ 「${o.run}」已完成,本拍无需执行。${s.detail}`);
|
|
590
|
-
console.log(`【${o.run}】该做了。${s.gap}`);
|
|
591
|
-
console.log(` 剧本: ${s.playbook || '(没写剧本 —— 这个值班不合格)'}`);
|
|
592
|
-
console.log(` ⚠️ 送达【回读确认】之后才准记 pass。没送达就写 pass = 自己骗自己。`);
|
|
593
|
-
return;
|
|
594
|
-
}
|
|
595
|
-
// --check(默认)
|
|
596
|
-
console.log('值班表(**完成状态在数据里,不在记忆里**;幂等,漏拍下一拍自愈)');
|
|
597
|
-
console.log(` 现在 ${runsmod.now().slice(11, 16)} · ${dutymod.inNight() ? '夜间窗口(重活可跑)' : '白天(重活挂起)'} · 外发窗口${dutymod.inDeliver() ? '开' : '关'}`);
|
|
598
|
-
const ids = Object.keys(duties);
|
|
599
|
-
if (!ids.length) {
|
|
600
|
-
console.log('\n (值班表是空的 —— 母体出厂如此。)');
|
|
601
|
-
return;
|
|
602
|
-
}
|
|
603
|
-
const todo = [];
|
|
604
|
-
for (const id of ids) {
|
|
605
|
-
const s = duties[id]();
|
|
606
|
-
const mark = s.done ? '✅ 已完成' : (s.due ? '⬜ 待补齐' : '⏸ 不在窗口');
|
|
607
|
-
console.log(` ${s.id.padEnd(8)} [${s.kind}] ${mark} ${s.detail}${s.gap ? ' → ' + s.gap : ''}`);
|
|
608
|
-
if (!s.done && s.due)
|
|
609
|
-
todo.push(s.id);
|
|
610
|
-
}
|
|
611
|
-
if (todo.length) {
|
|
612
|
-
console.log(`\n本拍要做: ${todo.map((t) => 'duty --run ' + t).join('、')}`);
|
|
613
|
-
process.exit(1);
|
|
614
|
-
}
|
|
615
|
-
console.log('\n全部补齐,静默即可(**不要为此打扰主人**)');
|
|
616
|
-
return;
|
|
617
|
-
}
|
|
618
|
-
// ── 留痕与进化 ──
|
|
619
|
-
if (cmd === 'log' || cmd === 'logq') {
|
|
620
|
-
const { values: o } = parseArgs({
|
|
621
|
-
args: argv.slice(1),
|
|
622
|
-
options: { did: { type: 'string' }, asked: { type: 'string' }, kind: { type: 'string' },
|
|
623
|
-
secs: { type: 'string' }, r: { type: 'string' }, ev: { type: 'string' },
|
|
624
|
-
ch: { type: 'string' }, issue: { type: 'string' },
|
|
625
|
-
conv: { type: 'string' }, msg: { type: 'string' } },
|
|
626
|
-
});
|
|
627
|
-
if (!o.did)
|
|
628
|
-
fail('要 --did(我怎么答的)');
|
|
629
|
-
const t = runsmod.logq(ROOT, {
|
|
630
|
-
...o, did: o.did, secs: +(o.secs || 0), r: o.r || 'pass',
|
|
631
|
-
});
|
|
632
|
-
console.log(`运行记录已落: runs/${runsmod.today()}.md @${t}`);
|
|
633
|
-
if (!o.conv)
|
|
634
|
-
console.log(' ⚠️ 没带 --conv —— 事后【拉不出对话流】,这一条基本没有训练价值。');
|
|
635
|
-
return;
|
|
636
|
-
}
|
|
637
|
-
if (cmd === 'feedback') {
|
|
638
|
-
const { values: o } = parseArgs({
|
|
639
|
-
args: argv.slice(1),
|
|
640
|
-
options: { kind: { type: 'string' }, text: { type: 'string' },
|
|
641
|
-
conv: { type: 'string' }, at: { type: 'string' } },
|
|
642
|
-
});
|
|
643
|
-
if (!o.kind || ![runsmod.FB_OK, runsmod.FB_MORE, runsmod.FB_FIX].includes(o.kind)) {
|
|
644
|
-
fail('--kind 只能是 认可 / 追问 / 纠正');
|
|
645
|
-
}
|
|
646
|
-
const day = runsmod.today();
|
|
647
|
-
const rows = runsmod.read(ROOT, day);
|
|
648
|
-
let cand = rows.filter((r) => r.asked);
|
|
649
|
-
if (o.conv)
|
|
650
|
-
cand = cand.filter((r) => r.conv === o.conv);
|
|
651
|
-
if (!cand.length)
|
|
652
|
-
fail(`今天没有可回填的问答行 —— **是不是答完忘了 logq?**`);
|
|
653
|
-
const tgt = o.at ? cand.find((r) => r.t === o.at) : cand[cand.length - 1];
|
|
654
|
-
if (!tgt)
|
|
655
|
-
fail(`找不到 t=${o.at} 的行`);
|
|
656
|
-
tgt.fb = o.kind;
|
|
657
|
-
if (o.text)
|
|
658
|
-
tgt.fbt = o.text.slice(0, 600);
|
|
659
|
-
runsmod.write(ROOT, day, rows);
|
|
660
|
-
console.log(`已回填: ${day} @${tgt.t} → 「${o.kind}」(原问: ${(tgt.asked || '').slice(0, 40)})`);
|
|
661
|
-
return;
|
|
662
|
-
}
|
|
663
|
-
if (cmd === 'runs') {
|
|
664
|
-
const { values: o } = parseArgs({
|
|
665
|
-
args: argv.slice(1),
|
|
666
|
-
options: { days: { type: 'string' }, conv: { type: 'string' },
|
|
667
|
-
issue: { type: 'string' }, top: { type: 'string' } },
|
|
668
|
-
});
|
|
669
|
-
let rows = runsmod.scan(ROOT, +(o.days || 1));
|
|
670
|
-
if (o.conv) {
|
|
671
|
-
rows = rows.filter((r) => r.conv === o.conv);
|
|
672
|
-
console.log(`【对话流】会话 ${o.conv} · ${rows.length} 条 —— **这就是训练素材**`);
|
|
673
|
-
for (const r of rows) {
|
|
674
|
-
console.log(` ── ${r._day} ${r.t} issue=${r.issue || '-'} msg=${r.msg || '-'}`);
|
|
675
|
-
if (r.asked)
|
|
676
|
-
console.log(` 主人: ${r.asked}`);
|
|
677
|
-
console.log(` 我 : ${r.did} [${r.r}]`);
|
|
678
|
-
if (r.fb)
|
|
679
|
-
console.log(` 反馈: ${r.fb}${r.fbt ? ` 「${r.fbt}」` : ''}`);
|
|
680
|
-
}
|
|
681
|
-
if (!rows.length)
|
|
682
|
-
console.log(' (空 —— 这个会话没留痕。**没留痕 = 这些交互等于没发生过。**)');
|
|
683
|
-
return;
|
|
684
|
-
}
|
|
685
|
-
if (o.issue) {
|
|
686
|
-
const issue = o.issue;
|
|
687
|
-
rows = rows.filter((r) => (r.issue || '').startsWith(issue));
|
|
688
|
-
}
|
|
689
|
-
console.log(`运行记录 runs/ · ${rows.length} 条`);
|
|
690
|
-
for (const r of rows.slice(-(+(o.top || 30)))) {
|
|
691
|
-
console.log(` ${r._day} ${r.t} [${(r.r || '').padEnd(11)}] ${(r.ch || '').padEnd(6)} ${(r.did || '').slice(0, 30)} ${r.fb ? '← ' + r.fb : ''}`);
|
|
692
|
-
}
|
|
693
|
-
return;
|
|
694
|
-
}
|
|
695
|
-
if (cmd === 'evolve') {
|
|
696
|
-
const { values: o } = parseArgs({ args: argv.slice(1), options: { days: { type: 'string' } } });
|
|
697
|
-
const rows = runsmod.scan(ROOT, +(o.days || 7));
|
|
698
|
-
const ans = rows.filter((r) => r.asked);
|
|
699
|
-
const bad = ans.filter((r) => [runsmod.FB_FIX, runsmod.FB_MORE].includes(r.fb || ''));
|
|
700
|
-
const unk = ans.filter((r) => !r.fb);
|
|
701
|
-
const failed = rows.filter((r) => ['fail', 'unsupported', 'degraded'].includes(r.r));
|
|
702
|
-
console.log(`【进化清单】近 ${o.days || 7} 天`);
|
|
703
|
-
console.log(` 面向主人的回答 ${ans.length} 条 · 被【打回】${bad.length} 条 · 引擎层没答出来 ${failed.length} 条`);
|
|
704
|
-
if (unk.length)
|
|
705
|
-
console.log(` ⚠️ ${unk.length} 条【没收到反馈就结案了】—— 答完没回填,这次交互等于白跑。`);
|
|
706
|
-
if (bad.length) {
|
|
707
|
-
console.log('\n── 主人打回的(**直接就是这周该改什么**)──');
|
|
708
|
-
for (const r of bad) {
|
|
709
|
-
console.log(` ${r._day} ${r.t} [${r.fb}] 会话=${r.conv || '-'}`);
|
|
710
|
-
console.log(` 主人问: ${(r.asked || '').slice(0, 60)}`);
|
|
711
|
-
console.log(` 我答 : ${(r.did || '').slice(0, 60)}`);
|
|
712
|
-
console.log(` 他说 : ${r.fbt || '(没记下来)'}`);
|
|
713
|
-
console.log(` 复盘 : dingtalk-agent runs --conv ${r.conv || '<会话id>'}`);
|
|
714
|
-
}
|
|
715
|
-
}
|
|
716
|
-
if (!bad.length && !failed.length) {
|
|
717
|
-
console.log('\n (没有打回,也没有失败 —— 要么真的都对,要么【没人回填反馈】。看上面那行。)');
|
|
718
|
-
}
|
|
719
|
-
return;
|
|
720
|
-
}
|
|
721
|
-
// ── todo:把待办拉全(心跳收件用)──
|
|
722
|
-
if (cmd === 'todo') {
|
|
723
|
-
const dws = await import('../src/dws.js');
|
|
724
|
-
const all = dws.todosAll('false');
|
|
725
|
-
console.log(`未完成待办 ${all.length} 条(**已翻页拉全** —— 只看第一页会漏掉循环件)`);
|
|
726
|
-
for (const t of all)
|
|
727
|
-
console.log(` ${t.taskId} ${(t.subject || '').slice(0, 60)}`);
|
|
728
|
-
return;
|
|
729
|
-
}
|
|
730
413
|
fail(`不认识的命令: ${cmd}`, 1, `运行 dta --help 查看全部命令${suggest(cmd, [
|
|
731
|
-
'setup', 'upgrade', 'doctor', 'skill', 'bootstrap', 'init', 'prepare', '
|
|
414
|
+
'setup', 'upgrade', 'doctor', 'skill', 'bootstrap', 'init', 'prepare', 'run', 'dispatch', 'act',
|
|
732
415
|
])}`);
|
|
733
416
|
}
|
|
734
417
|
function errorHint(message) {
|