@xdxer/dingtalk-agent 0.1.4-beta.6 → 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 +12 -2
- package/dist/bin/dingtalk-agent.js +60 -333
- 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/dist/src/upgrade.js +137 -0
- package/dist/src/upgrade.js.map +1 -0
- package/docs/INSTALLATION.md +24 -0
- 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 -327
- 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 -1125
- 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
|
@@ -62,6 +62,16 @@ dta --version
|
|
|
62
62
|
dta doctor
|
|
63
63
|
```
|
|
64
64
|
|
|
65
|
+
之后升级不再重复安装步骤,直接运行:
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
dta upgrade # beta 版默认继续跟随 beta
|
|
69
|
+
dta upgrade --channel latest # 显式切换稳定通道
|
|
70
|
+
dta upgrade --dry-run # 只查看目标版本和将执行的命令
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
升级完成后,新的 CLI 会自动重新执行 setup,复核 PATH、DWS、Skill 与三个 Agent 客户端。
|
|
74
|
+
|
|
65
75
|
安装后推荐使用短命令 `dta`;完整名称 `dingtalk-agent` 与它完全等价。错误会同时输出原因和一条可复制的 `提示:`,命令或子命令拼错时会给出最接近的建议。
|
|
66
76
|
|
|
67
77
|
安装后,Skill 只有一份 canonical copy:
|
|
@@ -243,7 +253,6 @@ dingtalk-agent init
|
|
|
243
253
|
dingtalk-agent prepare --event-file event.json --json
|
|
244
254
|
dingtalk-agent help runtime
|
|
245
255
|
dingtalk-agent help adapters
|
|
246
|
-
dingtalk-agent eval contract
|
|
247
256
|
```
|
|
248
257
|
|
|
249
258
|
`listen` 是可选的开发联调 Adapter,不是 Agent 主进程。云端 Driver、Claude Code 插件或本地 DWS 都可以提供事件,并从标准化事件之后复用同一 Session / Run / Action 内核。
|
|
@@ -256,11 +265,12 @@ npm run typecheck
|
|
|
256
265
|
npm run eval:contract
|
|
257
266
|
```
|
|
258
267
|
|
|
259
|
-
当前确定性合同包含 **
|
|
268
|
+
当前确定性合同包含 **31 个场景**,覆盖:
|
|
260
269
|
|
|
261
270
|
- 通过 `npx skills` 委托全局 Skill 安装、发现、重装和卸载;
|
|
262
271
|
- 首次 setup、用户级 PATH、DWS 版本/认证和三端客户端发现;
|
|
263
272
|
- `dta` 短命令安装,以及命令、子命令和参数错误的可恢复提示;
|
|
273
|
+
- CLI 自升级、新 binary 版本校验和升级后 setup 复核;
|
|
264
274
|
- 无 init bootstrap、本地/远端 Storage 与类型闸门;
|
|
265
275
|
- Direct Session 外发边界;
|
|
266
276
|
- Session continuation、Wait、幂等和目标防篡改;
|
|
@@ -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';
|
|
@@ -25,6 +21,7 @@ import { resolvePackageRoot } from '../src/package-root.js';
|
|
|
25
21
|
import { bootstrap } from '../src/bootstrap.js';
|
|
26
22
|
import { doctor } from '../src/doctor.js';
|
|
27
23
|
import { setup } from '../src/setup.js';
|
|
24
|
+
import { upgradeAgent } from '../src/upgrade.js';
|
|
28
25
|
import { installGlobalSkill, skillStatus, uninstallGlobalSkill, upgradeGlobalSkill, } from '../src/skill-manager.js';
|
|
29
26
|
const PACKAGE_ROOT = resolvePackageRoot(import.meta.url);
|
|
30
27
|
const PACKAGE_JSON = JSON.parse(readFileSync(join(PACKAGE_ROOT, 'package.json'), 'utf8'));
|
|
@@ -34,45 +31,23 @@ const ROOT = process.env.DTA_ROOT
|
|
|
34
31
|
? resolve(process.env.DTA_ROOT)
|
|
35
32
|
: (cfgmod.findRoot(process.cwd()) || process.cwd());
|
|
36
33
|
const HELP = `
|
|
37
|
-
dta
|
|
34
|
+
dta —— 给 Agent 安装钉钉员工的基础行为和工作环境
|
|
38
35
|
|
|
39
|
-
|
|
40
|
-
|
|
36
|
+
装好后,Agent 可以:
|
|
37
|
+
· 判断 @、单聊和群消息是否应该回应
|
|
38
|
+
· 通过 DWS 回复消息、协作并使用钉钉标准产品
|
|
39
|
+
· 从本地目录或钉钉文档加载身份、记忆和知识
|
|
41
40
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
setup 用户级安装 CLI、修复 PATH、安装 Skill、检查 DWS
|
|
46
|
-
doctor 检查 PATH / Node / DWS / Skill / Agent 客户端
|
|
41
|
+
开始使用:
|
|
42
|
+
dta setup 首次配置 CLI、DWS 和基础行为 Skill
|
|
43
|
+
dta bootstrap --json 为当前 Agent 会话加载工作区
|
|
47
44
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
skill
|
|
52
|
-
skill uninstall 通过 npx skills 卸载全局 Skill
|
|
53
|
-
通用: [--dry-run] [--json];安装生命周期委托给 npx skills
|
|
45
|
+
维护环境:
|
|
46
|
+
dta doctor 检查哪里没装好,并给出修复提示
|
|
47
|
+
dta upgrade 自升级,再重新检查完整环境
|
|
48
|
+
dta skill status 查看 Claude Code、Codex、OpenCode 能否发现 Skill
|
|
54
49
|
|
|
55
|
-
|
|
56
|
-
bootstrap 发现当前本地 Workspace;不修改项目文件
|
|
57
|
-
[--storage <uri>] local-dir:<path> | dingtalk-doc:<node-or-url>
|
|
58
|
-
[--state-dir <path>] 远端文档只读快照目录
|
|
59
|
-
[--profile <dws-profile>] [--json]
|
|
60
|
-
|
|
61
|
-
可信事件模式(可选;需要一次 init)
|
|
62
|
-
init [--context-id X] 仅为 Prepared Run 建最小 Workspace
|
|
63
|
-
prepare --event-file <file|-> 事件 → Session → Run
|
|
64
|
-
act ack 对原消息贴「收到」;不代表接单
|
|
65
|
-
act reply --text "…" 引用回复原消息
|
|
66
|
-
act ask --text "…" 只问一个真正阻塞的问题
|
|
67
|
-
act silence [--reason "…"] 不外发,但留下行为回执
|
|
68
|
-
通用: [--run <path>] [--dry-run] [--json]
|
|
69
|
-
|
|
70
|
-
smoke 极简本地验收(不写钉钉)
|
|
71
|
-
eval contract / behavior 完整合同或模型行为评测
|
|
72
|
-
|
|
73
|
-
help runtime 事件宿主与 controller 命令
|
|
74
|
-
help adapters 可选 DWS listen 适配器
|
|
75
|
-
help legacy 查看兼容的本体、KB、值班与进化命令
|
|
50
|
+
接入钉钉事件和可靠外发:dta help runtime
|
|
76
51
|
`;
|
|
77
52
|
const RUNTIME_HELP = `
|
|
78
53
|
dingtalk-agent 可信事件运行时(可选宿主能力)
|
|
@@ -95,17 +70,6 @@ dingtalk-agent 可选 Driver / 开发联调适配器
|
|
|
95
70
|
|
|
96
71
|
listen 不是 Agent 主入口。Claude Code、DWS 云端或其他宿主都可以直接提供事件。
|
|
97
72
|
`;
|
|
98
|
-
const LEGACY_HELP = `
|
|
99
|
-
dingtalk-agent 兼容命令(不属于 P0 四对象主链)
|
|
100
|
-
|
|
101
|
-
boot
|
|
102
|
-
kb mount|list|sync|search
|
|
103
|
-
duty --check|--run|--list
|
|
104
|
-
todo
|
|
105
|
-
log / feedback / runs / evolve
|
|
106
|
-
|
|
107
|
-
这些能力继续可用,但新增 Agent 应先安装全局 Skill;只有可信事件宿主才需要 runtime。
|
|
108
|
-
`;
|
|
109
73
|
function fail(msg, code = 1, hint = '') {
|
|
110
74
|
console.error(`错误: ${msg}`);
|
|
111
75
|
if (hint)
|
|
@@ -124,10 +88,6 @@ catch (e) {
|
|
|
124
88
|
fail(message, Number(error?.exitCode) || 2, errorHint(message));
|
|
125
89
|
}
|
|
126
90
|
async function main() {
|
|
127
|
-
if (cmd === 'help' && sub === 'legacy') {
|
|
128
|
-
console.log(LEGACY_HELP);
|
|
129
|
-
return;
|
|
130
|
-
}
|
|
131
91
|
if (cmd === 'help' && sub === 'runtime') {
|
|
132
92
|
console.log(RUNTIME_HELP);
|
|
133
93
|
return;
|
|
@@ -136,6 +96,9 @@ async function main() {
|
|
|
136
96
|
console.log(ADAPTER_HELP);
|
|
137
97
|
return;
|
|
138
98
|
}
|
|
99
|
+
if (cmd === 'help' && sub) {
|
|
100
|
+
fail(`不认识的帮助主题: ${sub}`, 1, '运行 dta --help 回到产品入口;事件宿主可用 dta help runtime。');
|
|
101
|
+
}
|
|
139
102
|
if (!cmd || cmd === '--help' || cmd === '-h' || cmd === 'help') {
|
|
140
103
|
console.log(HELP);
|
|
141
104
|
return;
|
|
@@ -144,7 +107,7 @@ async function main() {
|
|
|
144
107
|
console.log(PACKAGE_JSON.version);
|
|
145
108
|
return;
|
|
146
109
|
}
|
|
147
|
-
// ── setup / doctor
|
|
110
|
+
// ── setup / upgrade / doctor:机器级安装与环境闭环。──
|
|
148
111
|
if (cmd === 'setup') {
|
|
149
112
|
const { values: o } = parseArgs({
|
|
150
113
|
args: argv.slice(1),
|
|
@@ -181,6 +144,27 @@ async function main() {
|
|
|
181
144
|
process.exitCode = 2;
|
|
182
145
|
return;
|
|
183
146
|
}
|
|
147
|
+
if (cmd === 'upgrade') {
|
|
148
|
+
const { values: o } = parseArgs({
|
|
149
|
+
args: argv.slice(1),
|
|
150
|
+
options: {
|
|
151
|
+
channel: { type: 'string' }, version: { type: 'string' }, prefix: { type: 'string' },
|
|
152
|
+
'dry-run': { type: 'boolean' }, force: { type: 'boolean' }, json: { type: 'boolean' },
|
|
153
|
+
},
|
|
154
|
+
});
|
|
155
|
+
const out = upgradeAgent(PACKAGE_ROOT, {
|
|
156
|
+
channel: o.channel,
|
|
157
|
+
version: o.version, prefix: o.prefix,
|
|
158
|
+
dryRun: o['dry-run'], force: o.force,
|
|
159
|
+
});
|
|
160
|
+
if (o.json)
|
|
161
|
+
console.log(JSON.stringify(out, null, 2));
|
|
162
|
+
else
|
|
163
|
+
printUpgrade(out);
|
|
164
|
+
if (!out.dryRun && !out.ready)
|
|
165
|
+
process.exitCode = 2;
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
184
168
|
// ── skill:唯一一次性的主入口;完全不依赖 Workspace。──
|
|
185
169
|
if (cmd === 'skill') {
|
|
186
170
|
const { values: o } = parseArgs({
|
|
@@ -426,285 +410,8 @@ async function main() {
|
|
|
426
410
|
process.exitCode = 2;
|
|
427
411
|
return;
|
|
428
412
|
}
|
|
429
|
-
// ── eval:宿主评测入口;shadow 永不调用 act / DWS。──
|
|
430
|
-
if (cmd === 'eval') {
|
|
431
|
-
const script = sub === 'contract'
|
|
432
|
-
? join(PACKAGE_ROOT, 'evals', 'run-contract-evals.mjs')
|
|
433
|
-
: sub === 'shadow'
|
|
434
|
-
? join(PACKAGE_ROOT, 'evals', 'runners', 'claude-shadow.mjs')
|
|
435
|
-
: sub === 'behavior'
|
|
436
|
-
? join(PACKAGE_ROOT, 'evals', 'run-shadow-evals.mjs')
|
|
437
|
-
: '';
|
|
438
|
-
if (!script)
|
|
439
|
-
fail('eval 的子命令: contract / shadow / behavior');
|
|
440
|
-
const childEnv = { ...process.env };
|
|
441
|
-
// 合同评测会创建隔离工作区;继承宿主 DTA_ROOT 会让 Action Gate 错读外层 control store。
|
|
442
|
-
delete childEnv.DTA_ROOT;
|
|
443
|
-
const child = spawnSync(process.execPath, [script, ...argv.slice(2)], {
|
|
444
|
-
cwd: ROOT,
|
|
445
|
-
env: childEnv,
|
|
446
|
-
stdio: 'inherit',
|
|
447
|
-
});
|
|
448
|
-
if (child.error)
|
|
449
|
-
throw child.error;
|
|
450
|
-
if (child.signal)
|
|
451
|
-
throw new Error(`评测进程被 ${child.signal} 终止`);
|
|
452
|
-
process.exitCode = child.status ?? 2;
|
|
453
|
-
return;
|
|
454
|
-
}
|
|
455
|
-
if (cmd === 'smoke') {
|
|
456
|
-
const script = join(PACKAGE_ROOT, 'evals', 'run-contract-evals.mjs');
|
|
457
|
-
const childEnv = { ...process.env };
|
|
458
|
-
delete childEnv.DTA_ROOT;
|
|
459
|
-
const child = spawnSync(process.execPath, [script, '--smoke'], {
|
|
460
|
-
cwd: ROOT, env: childEnv, stdio: 'inherit',
|
|
461
|
-
});
|
|
462
|
-
if (child.error)
|
|
463
|
-
throw child.error;
|
|
464
|
-
if (child.signal)
|
|
465
|
-
throw new Error(`Smoke 被 ${child.signal} 终止`);
|
|
466
|
-
process.exitCode = child.status ?? 2;
|
|
467
|
-
return;
|
|
468
|
-
}
|
|
469
|
-
// ── kb ──
|
|
470
|
-
if (cmd === 'kb') {
|
|
471
|
-
const cfg = cfgmod.must(ROOT);
|
|
472
|
-
const { values: o } = parseArgs({
|
|
473
|
-
args: argv.slice(2), allowPositionals: true,
|
|
474
|
-
options: {
|
|
475
|
-
name: { type: 'string' }, from: { type: 'string' }, own: { type: 'string' },
|
|
476
|
-
sync: { type: 'string' }, local: { type: 'string' }, force: { type: 'boolean' },
|
|
477
|
-
},
|
|
478
|
-
});
|
|
479
|
-
if (sub === 'mount') {
|
|
480
|
-
if (!o.name || !o.from)
|
|
481
|
-
fail('要 --name 和 --from。源的写法见 --help');
|
|
482
|
-
kbmod.parseSource(o.from); // 写错了当场炸
|
|
483
|
-
const own = o.own || kbmod.EXTERNAL;
|
|
484
|
-
const sync = o.sync || (own === kbmod.OWNED ? kbmod.PUSH : kbmod.PULL);
|
|
485
|
-
if (own === kbmod.OWNED && sync === kbmod.PULL) {
|
|
486
|
-
fail('owned 的真值在 Git,不该 pull —— 那会把远端的东西覆盖到本地。\n' +
|
|
487
|
-
' **所有权决定真值方向。** owned → push;external → pull。');
|
|
488
|
-
}
|
|
489
|
-
const local = o.local || join('.cache/kb', o.name);
|
|
490
|
-
cfg.kb = (cfg.kb || []).filter((k) => k.name !== o.name);
|
|
491
|
-
cfg.kb.push({ name: o.name, from: o.from, own, sync, local });
|
|
492
|
-
cfgmod.save(ROOT, cfg);
|
|
493
|
-
console.log(`✅ 挂上「${o.name}」 ${o.from}`);
|
|
494
|
-
console.log(` 所有权=${own} · 同步=${sync} · 落在 ${local}`);
|
|
495
|
-
console.log(own === kbmod.OWNED
|
|
496
|
-
? ' (真值在 Git,钉钉是暴露层。人在钉钉里改了 → sync 时会【停下来问】,不盲覆盖。)'
|
|
497
|
-
: ' (真值在钉钉,本地只是【可丢弃的缓存】。过期了 kb search 会警告。)');
|
|
498
|
-
return;
|
|
499
|
-
}
|
|
500
|
-
if (sub === 'list') {
|
|
501
|
-
if (!cfg.kb?.length)
|
|
502
|
-
return console.log('一个都没挂。 kb mount --help');
|
|
503
|
-
for (const kb of cfg.kb) {
|
|
504
|
-
const s = kbmod.stale(kb);
|
|
505
|
-
console.log(` ${s ? '⚠️' : '·'} ${kb.name.padEnd(14)} ${kb.own.padEnd(9)} ${kb.sync.padEnd(5)} ${kb.from}`);
|
|
506
|
-
console.log(` 落在 ${kb.local} 上次同步 ${kb._syncedAt || '从未'}${s ? ' ← **过期了,不许拿来回答**' : ''}`);
|
|
507
|
-
}
|
|
508
|
-
return;
|
|
509
|
-
}
|
|
510
|
-
if (sub === 'sync') {
|
|
511
|
-
const targets = (cfg.kb || []).filter((k) => !o.name || k.name === o.name);
|
|
512
|
-
if (!targets.length)
|
|
513
|
-
fail('没有这个知识库。 kb list');
|
|
514
|
-
for (const kb of targets) {
|
|
515
|
-
if (kb.sync === kbmod.NONE) {
|
|
516
|
-
console.log(` skip ${kb.name}(sync=none)`);
|
|
517
|
-
continue;
|
|
518
|
-
}
|
|
519
|
-
if (kb.sync === kbmod.PULL)
|
|
520
|
-
kbmod.pull(kb, ROOT, o.force);
|
|
521
|
-
else
|
|
522
|
-
kbmod.push(kb, ROOT, o.force);
|
|
523
|
-
}
|
|
524
|
-
cfgmod.save(ROOT, cfg);
|
|
525
|
-
return;
|
|
526
|
-
}
|
|
527
|
-
if (sub === 'search') {
|
|
528
|
-
const kw = argv[2];
|
|
529
|
-
if (!kw)
|
|
530
|
-
fail('要给关键词。 kb search "<关键词>"');
|
|
531
|
-
kbmod.search(cfg, ROOT, kw);
|
|
532
|
-
return;
|
|
533
|
-
}
|
|
534
|
-
fail('kb 的子命令: mount / list / sync / search');
|
|
535
|
-
}
|
|
536
|
-
// ── boot ──
|
|
537
|
-
if (cmd === 'boot') {
|
|
538
|
-
boot(cfgmod.must(ROOT), ROOT);
|
|
539
|
-
return;
|
|
540
|
-
}
|
|
541
|
-
// ── duty ──
|
|
542
|
-
if (cmd === 'duty') {
|
|
543
|
-
const cfg = cfgmod.must(ROOT);
|
|
544
|
-
const { values: o } = parseArgs({
|
|
545
|
-
args: argv.slice(1), allowPositionals: true,
|
|
546
|
-
options: { check: { type: 'boolean' }, run: { type: 'string' },
|
|
547
|
-
list: { type: 'boolean' }, force: { type: 'boolean' } },
|
|
548
|
-
});
|
|
549
|
-
const duties = dutymod.loadDuties(cfg, ROOT);
|
|
550
|
-
if (o.list) {
|
|
551
|
-
const ks = Object.keys(duties);
|
|
552
|
-
console.log(ks.length ? ks.join('\n')
|
|
553
|
-
: '(值班表是空的 —— 母体出厂如此,这是【正确】的。在 .dingtalk-agent/config.json 的 duties 里加。)');
|
|
554
|
-
return;
|
|
555
|
-
}
|
|
556
|
-
if (o.run) {
|
|
557
|
-
const fn = duties[o.run];
|
|
558
|
-
if (!fn)
|
|
559
|
-
fail(`没有这个值班: ${o.run}(有: ${Object.keys(duties).join('、') || '无'})`);
|
|
560
|
-
const s = fn();
|
|
561
|
-
if (s.kind === '交付' && !dutymod.inDeliver() && !o.force) {
|
|
562
|
-
return console.log(`⏸ 「${o.run}」是外发动作,静默时段顺延,**不打扰第三方**。`);
|
|
563
|
-
}
|
|
564
|
-
if (s.done)
|
|
565
|
-
return console.log(`✅ 「${o.run}」已完成,本拍无需执行。${s.detail}`);
|
|
566
|
-
console.log(`【${o.run}】该做了。${s.gap}`);
|
|
567
|
-
console.log(` 剧本: ${s.playbook || '(没写剧本 —— 这个值班不合格)'}`);
|
|
568
|
-
console.log(` ⚠️ 送达【回读确认】之后才准记 pass。没送达就写 pass = 自己骗自己。`);
|
|
569
|
-
return;
|
|
570
|
-
}
|
|
571
|
-
// --check(默认)
|
|
572
|
-
console.log('值班表(**完成状态在数据里,不在记忆里**;幂等,漏拍下一拍自愈)');
|
|
573
|
-
console.log(` 现在 ${runsmod.now().slice(11, 16)} · ${dutymod.inNight() ? '夜间窗口(重活可跑)' : '白天(重活挂起)'} · 外发窗口${dutymod.inDeliver() ? '开' : '关'}`);
|
|
574
|
-
const ids = Object.keys(duties);
|
|
575
|
-
if (!ids.length) {
|
|
576
|
-
console.log('\n (值班表是空的 —— 母体出厂如此。)');
|
|
577
|
-
return;
|
|
578
|
-
}
|
|
579
|
-
const todo = [];
|
|
580
|
-
for (const id of ids) {
|
|
581
|
-
const s = duties[id]();
|
|
582
|
-
const mark = s.done ? '✅ 已完成' : (s.due ? '⬜ 待补齐' : '⏸ 不在窗口');
|
|
583
|
-
console.log(` ${s.id.padEnd(8)} [${s.kind}] ${mark} ${s.detail}${s.gap ? ' → ' + s.gap : ''}`);
|
|
584
|
-
if (!s.done && s.due)
|
|
585
|
-
todo.push(s.id);
|
|
586
|
-
}
|
|
587
|
-
if (todo.length) {
|
|
588
|
-
console.log(`\n本拍要做: ${todo.map((t) => 'duty --run ' + t).join('、')}`);
|
|
589
|
-
process.exit(1);
|
|
590
|
-
}
|
|
591
|
-
console.log('\n全部补齐,静默即可(**不要为此打扰主人**)');
|
|
592
|
-
return;
|
|
593
|
-
}
|
|
594
|
-
// ── 留痕与进化 ──
|
|
595
|
-
if (cmd === 'log' || cmd === 'logq') {
|
|
596
|
-
const { values: o } = parseArgs({
|
|
597
|
-
args: argv.slice(1),
|
|
598
|
-
options: { did: { type: 'string' }, asked: { type: 'string' }, kind: { type: 'string' },
|
|
599
|
-
secs: { type: 'string' }, r: { type: 'string' }, ev: { type: 'string' },
|
|
600
|
-
ch: { type: 'string' }, issue: { type: 'string' },
|
|
601
|
-
conv: { type: 'string' }, msg: { type: 'string' } },
|
|
602
|
-
});
|
|
603
|
-
if (!o.did)
|
|
604
|
-
fail('要 --did(我怎么答的)');
|
|
605
|
-
const t = runsmod.logq(ROOT, {
|
|
606
|
-
...o, did: o.did, secs: +(o.secs || 0), r: o.r || 'pass',
|
|
607
|
-
});
|
|
608
|
-
console.log(`运行记录已落: runs/${runsmod.today()}.md @${t}`);
|
|
609
|
-
if (!o.conv)
|
|
610
|
-
console.log(' ⚠️ 没带 --conv —— 事后【拉不出对话流】,这一条基本没有训练价值。');
|
|
611
|
-
return;
|
|
612
|
-
}
|
|
613
|
-
if (cmd === 'feedback') {
|
|
614
|
-
const { values: o } = parseArgs({
|
|
615
|
-
args: argv.slice(1),
|
|
616
|
-
options: { kind: { type: 'string' }, text: { type: 'string' },
|
|
617
|
-
conv: { type: 'string' }, at: { type: 'string' } },
|
|
618
|
-
});
|
|
619
|
-
if (!o.kind || ![runsmod.FB_OK, runsmod.FB_MORE, runsmod.FB_FIX].includes(o.kind)) {
|
|
620
|
-
fail('--kind 只能是 认可 / 追问 / 纠正');
|
|
621
|
-
}
|
|
622
|
-
const day = runsmod.today();
|
|
623
|
-
const rows = runsmod.read(ROOT, day);
|
|
624
|
-
let cand = rows.filter((r) => r.asked);
|
|
625
|
-
if (o.conv)
|
|
626
|
-
cand = cand.filter((r) => r.conv === o.conv);
|
|
627
|
-
if (!cand.length)
|
|
628
|
-
fail(`今天没有可回填的问答行 —— **是不是答完忘了 logq?**`);
|
|
629
|
-
const tgt = o.at ? cand.find((r) => r.t === o.at) : cand[cand.length - 1];
|
|
630
|
-
if (!tgt)
|
|
631
|
-
fail(`找不到 t=${o.at} 的行`);
|
|
632
|
-
tgt.fb = o.kind;
|
|
633
|
-
if (o.text)
|
|
634
|
-
tgt.fbt = o.text.slice(0, 600);
|
|
635
|
-
runsmod.write(ROOT, day, rows);
|
|
636
|
-
console.log(`已回填: ${day} @${tgt.t} → 「${o.kind}」(原问: ${(tgt.asked || '').slice(0, 40)})`);
|
|
637
|
-
return;
|
|
638
|
-
}
|
|
639
|
-
if (cmd === 'runs') {
|
|
640
|
-
const { values: o } = parseArgs({
|
|
641
|
-
args: argv.slice(1),
|
|
642
|
-
options: { days: { type: 'string' }, conv: { type: 'string' },
|
|
643
|
-
issue: { type: 'string' }, top: { type: 'string' } },
|
|
644
|
-
});
|
|
645
|
-
let rows = runsmod.scan(ROOT, +(o.days || 1));
|
|
646
|
-
if (o.conv) {
|
|
647
|
-
rows = rows.filter((r) => r.conv === o.conv);
|
|
648
|
-
console.log(`【对话流】会话 ${o.conv} · ${rows.length} 条 —— **这就是训练素材**`);
|
|
649
|
-
for (const r of rows) {
|
|
650
|
-
console.log(` ── ${r._day} ${r.t} issue=${r.issue || '-'} msg=${r.msg || '-'}`);
|
|
651
|
-
if (r.asked)
|
|
652
|
-
console.log(` 主人: ${r.asked}`);
|
|
653
|
-
console.log(` 我 : ${r.did} [${r.r}]`);
|
|
654
|
-
if (r.fb)
|
|
655
|
-
console.log(` 反馈: ${r.fb}${r.fbt ? ` 「${r.fbt}」` : ''}`);
|
|
656
|
-
}
|
|
657
|
-
if (!rows.length)
|
|
658
|
-
console.log(' (空 —— 这个会话没留痕。**没留痕 = 这些交互等于没发生过。**)');
|
|
659
|
-
return;
|
|
660
|
-
}
|
|
661
|
-
if (o.issue) {
|
|
662
|
-
const issue = o.issue;
|
|
663
|
-
rows = rows.filter((r) => (r.issue || '').startsWith(issue));
|
|
664
|
-
}
|
|
665
|
-
console.log(`运行记录 runs/ · ${rows.length} 条`);
|
|
666
|
-
for (const r of rows.slice(-(+(o.top || 30)))) {
|
|
667
|
-
console.log(` ${r._day} ${r.t} [${(r.r || '').padEnd(11)}] ${(r.ch || '').padEnd(6)} ${(r.did || '').slice(0, 30)} ${r.fb ? '← ' + r.fb : ''}`);
|
|
668
|
-
}
|
|
669
|
-
return;
|
|
670
|
-
}
|
|
671
|
-
if (cmd === 'evolve') {
|
|
672
|
-
const { values: o } = parseArgs({ args: argv.slice(1), options: { days: { type: 'string' } } });
|
|
673
|
-
const rows = runsmod.scan(ROOT, +(o.days || 7));
|
|
674
|
-
const ans = rows.filter((r) => r.asked);
|
|
675
|
-
const bad = ans.filter((r) => [runsmod.FB_FIX, runsmod.FB_MORE].includes(r.fb || ''));
|
|
676
|
-
const unk = ans.filter((r) => !r.fb);
|
|
677
|
-
const failed = rows.filter((r) => ['fail', 'unsupported', 'degraded'].includes(r.r));
|
|
678
|
-
console.log(`【进化清单】近 ${o.days || 7} 天`);
|
|
679
|
-
console.log(` 面向主人的回答 ${ans.length} 条 · 被【打回】${bad.length} 条 · 引擎层没答出来 ${failed.length} 条`);
|
|
680
|
-
if (unk.length)
|
|
681
|
-
console.log(` ⚠️ ${unk.length} 条【没收到反馈就结案了】—— 答完没回填,这次交互等于白跑。`);
|
|
682
|
-
if (bad.length) {
|
|
683
|
-
console.log('\n── 主人打回的(**直接就是这周该改什么**)──');
|
|
684
|
-
for (const r of bad) {
|
|
685
|
-
console.log(` ${r._day} ${r.t} [${r.fb}] 会话=${r.conv || '-'}`);
|
|
686
|
-
console.log(` 主人问: ${(r.asked || '').slice(0, 60)}`);
|
|
687
|
-
console.log(` 我答 : ${(r.did || '').slice(0, 60)}`);
|
|
688
|
-
console.log(` 他说 : ${r.fbt || '(没记下来)'}`);
|
|
689
|
-
console.log(` 复盘 : dingtalk-agent runs --conv ${r.conv || '<会话id>'}`);
|
|
690
|
-
}
|
|
691
|
-
}
|
|
692
|
-
if (!bad.length && !failed.length) {
|
|
693
|
-
console.log('\n (没有打回,也没有失败 —— 要么真的都对,要么【没人回填反馈】。看上面那行。)');
|
|
694
|
-
}
|
|
695
|
-
return;
|
|
696
|
-
}
|
|
697
|
-
// ── todo:把待办拉全(心跳收件用)──
|
|
698
|
-
if (cmd === 'todo') {
|
|
699
|
-
const dws = await import('../src/dws.js');
|
|
700
|
-
const all = dws.todosAll('false');
|
|
701
|
-
console.log(`未完成待办 ${all.length} 条(**已翻页拉全** —— 只看第一页会漏掉循环件)`);
|
|
702
|
-
for (const t of all)
|
|
703
|
-
console.log(` ${t.taskId} ${(t.subject || '').slice(0, 60)}`);
|
|
704
|
-
return;
|
|
705
|
-
}
|
|
706
413
|
fail(`不认识的命令: ${cmd}`, 1, `运行 dta --help 查看全部命令${suggest(cmd, [
|
|
707
|
-
'setup', 'doctor', 'skill', 'bootstrap', 'init', 'prepare', '
|
|
414
|
+
'setup', 'upgrade', 'doctor', 'skill', 'bootstrap', 'init', 'prepare', 'run', 'dispatch', 'act',
|
|
708
415
|
])}`);
|
|
709
416
|
}
|
|
710
417
|
function errorHint(message) {
|
|
@@ -720,6 +427,9 @@ function errorHint(message) {
|
|
|
720
427
|
if (/skills CLI|\bnpx\b/.test(message)) {
|
|
721
428
|
return '确认 node、npm、npx 在 PATH 中;也可以复制错误中的 npx skills 命令单独执行。';
|
|
722
429
|
}
|
|
430
|
+
if (/升级目标|CLI 升级|npm view|npm install/.test(message)) {
|
|
431
|
+
return '检查 npm registry 与网络后重试 dta upgrade;可先运行 dta upgrade --dry-run 查看目标和完整命令。';
|
|
432
|
+
}
|
|
723
433
|
if (/Workspace|Field|Storage|contextId/.test(message)) {
|
|
724
434
|
return '先运行 dta bootstrap --json 查看当前上下文;确实需要持久 Workspace 时再运行 dta init。';
|
|
725
435
|
}
|
|
@@ -807,4 +517,21 @@ function printSetup(out) {
|
|
|
807
517
|
printDoctor(out.doctor);
|
|
808
518
|
console.log(`\n开始使用: ${out.nextCommand}`);
|
|
809
519
|
}
|
|
520
|
+
function printUpgrade(out) {
|
|
521
|
+
const mark = out.dryRun ? 'DRY-RUN' : out.ready ? '✅' : '⚠️';
|
|
522
|
+
const relation = out.changed ? `${out.currentVersion} → ${out.targetVersion}` : `${out.targetVersion}(已是当前版本)`;
|
|
523
|
+
console.log(`${mark} dta upgrade: ${relation}`);
|
|
524
|
+
console.log(` target=${out.target}`);
|
|
525
|
+
console.log(` CLI=${out.executable}`);
|
|
526
|
+
if (out.dryRun) {
|
|
527
|
+
console.log(` 将执行: ${out.commands.install}`);
|
|
528
|
+
console.log(` 将复核: ${out.commands.verify}`);
|
|
529
|
+
}
|
|
530
|
+
else if (out.ready) {
|
|
531
|
+
console.log(' setup / DWS / Skill / Claude Code / Codex / OpenCode 全部 ready');
|
|
532
|
+
}
|
|
533
|
+
else {
|
|
534
|
+
console.log(` CLI 已更新;环境复核未完全 ready,请运行: ${out.commands.verify}`);
|
|
535
|
+
}
|
|
536
|
+
}
|
|
810
537
|
//# sourceMappingURL=dingtalk-agent.js.map
|