@xdxer/dingtalk-agent 0.1.5-beta.3 → 0.1.5-beta.4
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 +21 -0
- package/README.en.md +92 -65
- package/README.md +92 -65
- package/dist/bin/dingtalk-agent.js +142 -15
- package/dist/bin/dingtalk-agent.js.map +1 -1
- package/dist/src/agent-platform.js +1 -0
- package/dist/src/agent-platform.js.map +1 -1
- package/dist/src/development-workspace.js +66 -3
- package/dist/src/development-workspace.js.map +1 -1
- package/dist/src/multica-deploy.js +101 -9
- package/dist/src/multica-deploy.js.map +1 -1
- package/dist/src/multica-provider.js +157 -2
- package/dist/src/multica-provider.js.map +1 -1
- package/dist/src/schedule-plan.js +105 -0
- package/dist/src/schedule-plan.js.map +1 -0
- package/docs/ARCHITECTURE.md +133 -18
- package/docs/PRIOR-ART.md +4 -0
- package/docs/SELF-TEST.md +1 -1
- package/docs/architecture/agent-platform-connection-layer.svg +120 -0
- package/docs/architecture/digital-employee-composition.svg +92 -0
- package/docs/architecture/dingtalk-agent-architecture.svg +125 -0
- package/docs/assets/digital-employee-at-work.svg +77 -0
- package/docs/schemas/multica-workspace-run.schema.json +150 -33
- package/docs/schemas/project.schema.json +22 -0
- package/docs/schemas/workspace-scaffold.schema.json +37 -0
- package/examples/agents/README.md +1 -1
- package/lab/project-workspace/fake-multica-provider.mjs +18 -2
- package/lab/project-workspace/opencode-provider-suite.json +1 -1
- package/lab/robot-eval/suite.json +1 -1
- package/package.json +2 -2
- package/skills/core/dingtalk-agent-compose/SKILL.md +4 -3
- package/skills/core/dingtalk-agent-compose/assets/AGENTS.template.md +1 -1
- package/skills/core/dingtalk-agent-compose/references/drive-and-schedules.md +124 -0
- package/skills/core/dingtalk-basic-behavior/SKILL.md +5 -4
- package/skills/core/dingtalk-basic-behavior/references/event-to-behavior.md +15 -1
- package/skills/core/dingtalk-basic-behavior/references/perception-and-gates.md +3 -0
- package/skills/core/dingtalk-basic-behavior/references/risk-authority-and-privacy.md +12 -0
- package/skills/platforms/deap/PLATFORM.md +30 -1
- package/skills/platforms/multica-dingtalk/PLATFORM.md +25 -0
- package/skills/platforms/multica-dingtalk/dingtalk-agent-deploy-multica/SKILL.md +3 -2
- package/skills/platforms/multica-dingtalk/multica-external/SKILL.md +15 -0
- package/docs/assets/agent-delivery-lifecycle.svg +0 -103
|
@@ -33,9 +33,10 @@ import { runStorageEvaluation } from '../src/storage-evals.js';
|
|
|
33
33
|
import { runPersonalEventEvaluation } from '../src/personal-event-evals.js';
|
|
34
34
|
import { doctor } from '../src/doctor.js';
|
|
35
35
|
import { doctorDevelopmentWorkspace, inspectAgentProject, showDevelopmentWorkspace, } from '../src/development-workspace.js';
|
|
36
|
+
import { buildScheduleShow, buildSchedulePlan } from '../src/schedule-plan.js';
|
|
36
37
|
import { applyOpenCodeWorkspace, evalOpenCodeWorkspace, planOpenCodeWorkspace, runOpenCodeWorkspace, useOpenCodeWorkspace, } from '../src/opencode-provider.js';
|
|
37
|
-
import { inspectMulticaWorkspace, listMulticaWorkspaceResources, planMulticaWorkspace, statusMulticaWorkspace, } from '../src/multica-provider.js';
|
|
38
|
-
import { applyMulticaDeployment, listMulticaDeployments, planMulticaDeployment, runMulticaWorkspaceIssue, statusMulticaDeployment, } from '../src/multica-deploy.js';
|
|
38
|
+
import { inspectMulticaWorkspace, listMulticaWorkspaceResources, planMulticaWorkspace, scaffoldMulticaWorkspace, statusMulticaWorkspace, } from '../src/multica-provider.js';
|
|
39
|
+
import { applyMulticaDeployment, listMulticaDeployments, planMulticaDeployment, runMulticaWorkspaceIssue, statusMulticaDeployment, statusMulticaWorkspaceRun, } from '../src/multica-deploy.js';
|
|
39
40
|
import { applyObservation, applyPromotion, listPromotions, planObservation, planPromotion, statusPromotion, } from '../src/promotion.js';
|
|
40
41
|
import { setup } from '../src/setup.js';
|
|
41
42
|
import { upgradeAgent } from '../src/upgrade.js';
|
|
@@ -65,6 +66,7 @@ dta —— 给 Agent 安装钉钉员工的基础行为和工作环境
|
|
|
65
66
|
dta bootstrap --json 为当前 Agent 会话加载工作区
|
|
66
67
|
dta agent enhance / audit 安全增强已有仓库,再审计定义、存储与 Skill 真加载
|
|
67
68
|
dta info / dta workspace doctor <name> 查看 Project 并只读诊断 Workspace
|
|
69
|
+
dta schedule show / plan --workspace <name> 查看声明的常驻节律并生成 provider 部署计划
|
|
68
70
|
dta agent-platform use <platform> → dta deploy / dta promote 声明平台归属并装平台技能包,再受控部署与晋级
|
|
69
71
|
|
|
70
72
|
维护环境:
|
|
@@ -155,7 +157,7 @@ const DEPLOY_HELP = `
|
|
|
155
157
|
dingtalk-agent Multica 受控部署
|
|
156
158
|
|
|
157
159
|
deploy --workspace <name> --dry-run [--json]
|
|
158
|
-
deploy --workspace <name> --plan-id <id> --yes [--no-wait] [--json]
|
|
160
|
+
deploy --workspace <name> --plan-id <id> --yes [--wait | --no-wait] [--json]
|
|
159
161
|
deploy --workspace <name> --status [--operation-id <id>] [--json]
|
|
160
162
|
deploy --workspace <name> --status --operation-id <id> --execute --yes [--json]
|
|
161
163
|
deploy --workspace <name> --list [--json]
|
|
@@ -163,6 +165,9 @@ dingtalk-agent Multica 受控部署
|
|
|
163
165
|
deploy --workspace <name> --retire --plan-id <id> --yes [--json]
|
|
164
166
|
|
|
165
167
|
dry-run 不启动 Multica。apply/retire 必须携带当前 planId;scope 或源码漂移会在写入前拒绝。
|
|
168
|
+
apply 默认在同一条命令内等 load smoke 到 ~30 秒;云端 runtime 冷启常超 30 秒会返回 verifying,
|
|
169
|
+
再用 --status --operation-id 独立 reconcile。加 --wait 把等待预算放宽到 4 分钟,一条命令直接到 ready;
|
|
170
|
+
--no-wait 立即返回 verifying(异步/CI)。--smoke-timeout <ms> 精确覆盖等待预算(上限 5 分钟)。
|
|
166
171
|
status 默认只验本地脱敏 operation/Receipt;--execute --yes 才做远端独立回读。
|
|
167
172
|
deploy 只管理 Agent、完整 Skill tree、assignment 和 load smoke,不创建机器人、Webhook、Autopilot 或定时 Trigger。
|
|
168
173
|
`;
|
|
@@ -245,6 +250,7 @@ async function main() {
|
|
|
245
250
|
workspace: { type: 'string' }, json: { type: 'boolean' },
|
|
246
251
|
'dry-run': { type: 'boolean' }, yes: { type: 'boolean' },
|
|
247
252
|
'plan-id': { type: 'string' }, 'no-wait': { type: 'boolean' },
|
|
253
|
+
wait: { type: 'boolean' },
|
|
248
254
|
status: { type: 'boolean' }, list: { type: 'boolean' },
|
|
249
255
|
execute: { type: 'boolean' }, 'operation-id': { type: 'string' },
|
|
250
256
|
timeout: { type: 'string' }, 'smoke-timeout': { type: 'string' },
|
|
@@ -265,16 +271,18 @@ async function main() {
|
|
|
265
271
|
const timeoutMs = parseOptionalTimeout(o.timeout, '--timeout');
|
|
266
272
|
const smokeTimeoutMs = parseOptionalTimeout(o['smoke-timeout'], '--smoke-timeout');
|
|
267
273
|
let out;
|
|
274
|
+
if (o.wait && o['no-wait'])
|
|
275
|
+
fail('deploy --wait 与 --no-wait 互斥');
|
|
268
276
|
if (o.list) {
|
|
269
|
-
if (o.execute || o['operation-id'] || o.retire || o['plan-id'] || o['no-wait'] ||
|
|
277
|
+
if (o.execute || o['operation-id'] || o.retire || o['plan-id'] || o['no-wait'] || o.wait ||
|
|
270
278
|
o.timeout || o['smoke-timeout']) {
|
|
271
279
|
fail('deploy --list 只接受 --workspace 和 --json');
|
|
272
280
|
}
|
|
273
281
|
out = listMulticaDeployments(PROJECT_START, o.workspace, PACKAGE_JSON.version);
|
|
274
282
|
}
|
|
275
283
|
else if (o.status) {
|
|
276
|
-
if (o.retire || o['plan-id'] || o['no-wait'] || o['dry-run'] || o['smoke-timeout']) {
|
|
277
|
-
fail('deploy --status 不接受 retire/plan-id/no-wait/dry-run/smoke-timeout');
|
|
284
|
+
if (o.retire || o['plan-id'] || o['no-wait'] || o.wait || o['dry-run'] || o['smoke-timeout']) {
|
|
285
|
+
fail('deploy --status 不接受 retire/plan-id/no-wait/wait/dry-run/smoke-timeout');
|
|
278
286
|
}
|
|
279
287
|
if (Boolean(o.execute) !== Boolean(o.yes)) {
|
|
280
288
|
fail('deploy --status 远端 reconcile 必须同时传 --execute --yes');
|
|
@@ -285,9 +293,9 @@ async function main() {
|
|
|
285
293
|
});
|
|
286
294
|
}
|
|
287
295
|
else if (o['dry-run']) {
|
|
288
|
-
if (o.execute || o['operation-id'] || o['plan-id'] || o['no-wait'] ||
|
|
296
|
+
if (o.execute || o['operation-id'] || o['plan-id'] || o['no-wait'] || o.wait ||
|
|
289
297
|
o.timeout || o['smoke-timeout']) {
|
|
290
|
-
fail('deploy --dry-run 不接受 execute/operation-id/plan-id/no-wait/timeout/smoke-timeout');
|
|
298
|
+
fail('deploy --dry-run 不接受 execute/operation-id/plan-id/no-wait/wait/timeout/smoke-timeout');
|
|
291
299
|
}
|
|
292
300
|
out = planMulticaDeployment(PROJECT_START, o.workspace, {
|
|
293
301
|
action: o.retire ? 'retire' : 'apply', cliVersion: PACKAGE_JSON.version,
|
|
@@ -297,12 +305,16 @@ async function main() {
|
|
|
297
305
|
if (o.execute || o['operation-id'] || o.status || o.list || o['dry-run']) {
|
|
298
306
|
fail('deploy apply 不接受 execute/operation-id/status/list/dry-run');
|
|
299
307
|
}
|
|
300
|
-
if (o.retire && (o['no-wait'] || o['smoke-timeout'])) {
|
|
301
|
-
fail('deploy --retire 不接受 no-wait/smoke-timeout');
|
|
308
|
+
if (o.retire && (o['no-wait'] || o.wait || o['smoke-timeout'])) {
|
|
309
|
+
fail('deploy --retire 不接受 no-wait/wait/smoke-timeout');
|
|
302
310
|
}
|
|
311
|
+
// --wait widens the in-band smoke-wait budget so one command reaches ready across a
|
|
312
|
+
// cold-start runtime; an explicit --smoke-timeout still wins. Default stays ~30s.
|
|
313
|
+
const effectiveSmokeTimeoutMs = smokeTimeoutMs !== undefined
|
|
314
|
+
? smokeTimeoutMs : o.wait ? 240_000 : undefined;
|
|
303
315
|
out = applyMulticaDeployment(PROJECT_START, o.workspace, {
|
|
304
316
|
yes: o.yes, planId: o['plan-id'], noWait: o['no-wait'],
|
|
305
|
-
timeoutMs, smokeTimeoutMs, cliVersion: PACKAGE_JSON.version,
|
|
317
|
+
timeoutMs, smokeTimeoutMs: effectiveSmokeTimeoutMs, cliVersion: PACKAGE_JSON.version,
|
|
306
318
|
}, o.retire ? 'retire' : 'apply');
|
|
307
319
|
}
|
|
308
320
|
if (o.json)
|
|
@@ -413,6 +425,65 @@ async function main() {
|
|
|
413
425
|
printProjectInfo(out);
|
|
414
426
|
return;
|
|
415
427
|
}
|
|
428
|
+
if (cmd === 'schedule') {
|
|
429
|
+
const sub = argv[1];
|
|
430
|
+
const { values: o, positionals } = parseArgs({
|
|
431
|
+
args: argv.slice(2), allowPositionals: true,
|
|
432
|
+
options: { json: { type: 'boolean' }, workspace: { type: 'string' } },
|
|
433
|
+
});
|
|
434
|
+
if (sub === 'show') {
|
|
435
|
+
const out = buildScheduleShow(PROJECT_START, PACKAGE_JSON.version);
|
|
436
|
+
if (o.json) {
|
|
437
|
+
console.log(JSON.stringify(out, null, 2));
|
|
438
|
+
return;
|
|
439
|
+
}
|
|
440
|
+
if (out.count === 0) {
|
|
441
|
+
console.log('本 Project 未声明任何常驻节律(schedules)。');
|
|
442
|
+
return;
|
|
443
|
+
}
|
|
444
|
+
console.log(`声明的常驻节律(internalized cron) · ${out.count} 条`);
|
|
445
|
+
for (const s of out.schedules) {
|
|
446
|
+
console.log(`\n ${s.name} ${s.cron} ${s.timezone} [${s.mode}]`);
|
|
447
|
+
if (s.wake)
|
|
448
|
+
console.log(` 唤醒 ${s.wake}`);
|
|
449
|
+
if (s.completion)
|
|
450
|
+
console.log(` ②判据 ${s.completion}`);
|
|
451
|
+
}
|
|
452
|
+
if (!out.minutesDistinct) {
|
|
453
|
+
console.log(`\n⚠️ 分钟位冲突: ${out.collidingMinutes.join(', ')} —— 外发类同分钟并发会重复送,请错开`);
|
|
454
|
+
process.exitCode = 2;
|
|
455
|
+
}
|
|
456
|
+
else {
|
|
457
|
+
console.log('\n✓ 各节律分钟位互不相同(外发防重复的静态前提满足)');
|
|
458
|
+
}
|
|
459
|
+
return;
|
|
460
|
+
}
|
|
461
|
+
if (sub === 'plan') {
|
|
462
|
+
const workspaceName = o.workspace || positionals[0];
|
|
463
|
+
if (!workspaceName)
|
|
464
|
+
fail('schedule plan 需要 --workspace <name>');
|
|
465
|
+
const info = inspectAgentProject(PROJECT_START, PACKAGE_JSON.version);
|
|
466
|
+
const plan = buildSchedulePlan(info, workspaceName);
|
|
467
|
+
if (o.json) {
|
|
468
|
+
console.log(JSON.stringify(plan, null, 2));
|
|
469
|
+
return;
|
|
470
|
+
}
|
|
471
|
+
console.log(`schedule 部署计划 · workspace=${plan.workspace} · provider=${plan.provider}`);
|
|
472
|
+
if (!plan.supported) {
|
|
473
|
+
console.log(`\n✗ 不支持: ${plan.reason}`);
|
|
474
|
+
console.log(` ${plan.reconcile}`);
|
|
475
|
+
process.exitCode = 2;
|
|
476
|
+
return;
|
|
477
|
+
}
|
|
478
|
+
console.log(` ${plan.count} 条声明 → provider ops:\n`);
|
|
479
|
+
for (const s of plan.schedules)
|
|
480
|
+
console.log(` # ${s.name}\n ${s.applyCommand}\n`);
|
|
481
|
+
console.log(`执行: ${plan.reconcile}`);
|
|
482
|
+
return;
|
|
483
|
+
}
|
|
484
|
+
fail(`可用: dta schedule show | plan --workspace <name>${suggest(sub || '', ['show', 'plan'], 'dta schedule')}`);
|
|
485
|
+
return;
|
|
486
|
+
}
|
|
416
487
|
if (cmd === 'workspace') {
|
|
417
488
|
const { values: o, positionals } = parseArgs({
|
|
418
489
|
args: argv.slice(2), allowPositionals: true,
|
|
@@ -423,6 +494,8 @@ async function main() {
|
|
|
423
494
|
cases: { type: 'string' }, lanes: { type: 'string' }, runs: { type: 'string' },
|
|
424
495
|
out: { type: 'string' }, timeout: { type: 'string' },
|
|
425
496
|
'previous-skill': { type: 'string' },
|
|
497
|
+
status: { type: 'boolean' }, 'run-id': { type: 'string' },
|
|
498
|
+
provider: { type: 'string' }, stage: { type: 'string' }, profile: { type: 'string' },
|
|
426
499
|
},
|
|
427
500
|
});
|
|
428
501
|
if (sub === 'list') {
|
|
@@ -544,16 +617,46 @@ async function main() {
|
|
|
544
617
|
return;
|
|
545
618
|
}
|
|
546
619
|
if (sub === 'create') {
|
|
547
|
-
rejectWorkspaceOptions(o, ['json', 'yes', 'dry-run'], 'workspace create');
|
|
548
620
|
if (positionals.length !== 1)
|
|
549
621
|
fail('workspace create 需要且只接受一个 Workspace name');
|
|
550
622
|
if (o.yes && o['dry-run'])
|
|
551
623
|
fail('workspace create 的 --dry-run 与 --yes 不能同时使用');
|
|
624
|
+
const wsName = positionals[0];
|
|
625
|
+
// Resolve the provider kind to scaffold/build: explicit --provider wins, else an already
|
|
626
|
+
// declared Workspace keeps its kind, else the attributed platform's provider (registry-
|
|
627
|
+
// driven so deap inherits it), else opencode. multica has no local host — create authors
|
|
628
|
+
// its config entry; opencode keeps building the managed host.
|
|
629
|
+
if (o.provider && !['opencode', 'multica'].includes(String(o.provider))) {
|
|
630
|
+
fail('workspace create --provider 只支持 opencode 或 multica');
|
|
631
|
+
}
|
|
632
|
+
const declaredWs = inspectAgentProject(PROJECT_START, PACKAGE_JSON.version)
|
|
633
|
+
.workspaces.find((item) => item.name === wsName);
|
|
634
|
+
const platformProvider = resolveAgentPlatform(PROJECT_START).definition?.provider;
|
|
635
|
+
const kind = String(o.provider || declaredWs?.provider.kind || platformProvider || 'opencode');
|
|
636
|
+
if (declaredWs && o.provider && declaredWs.provider.kind !== kind) {
|
|
637
|
+
fail(`Workspace ${wsName} 已声明为 ${declaredWs.provider.kind},与 --provider ${kind} 冲突`);
|
|
638
|
+
}
|
|
639
|
+
if (kind === 'multica') {
|
|
640
|
+
rejectWorkspaceOptions(o, ['json', 'yes', 'dry-run', 'provider', 'stage', 'profile'], 'workspace create');
|
|
641
|
+
const out = scaffoldMulticaWorkspace(PROJECT_START, wsName, {
|
|
642
|
+
stage: o.stage, profile: o.profile, apply: o.yes, cliVersion: PACKAGE_JSON.version,
|
|
643
|
+
});
|
|
644
|
+
if (o.json)
|
|
645
|
+
console.log(JSON.stringify(out, null, 2));
|
|
646
|
+
else {
|
|
647
|
+
const tag = out.alreadyDeclared ? '已存在' : out.applied ? '已写入' : 'DRY-RUN';
|
|
648
|
+
console.log(`${tag} workspace ${out.workspace} · provider=multica · profile=${out.profile}`);
|
|
649
|
+
for (const step of out.nextSteps)
|
|
650
|
+
console.log(` ${step}`);
|
|
651
|
+
}
|
|
652
|
+
return;
|
|
653
|
+
}
|
|
654
|
+
rejectWorkspaceOptions(o, ['json', 'yes', 'dry-run', 'provider'], 'workspace create');
|
|
552
655
|
const out = o.yes
|
|
553
|
-
? applyOpenCodeWorkspace(PROJECT_START,
|
|
656
|
+
? applyOpenCodeWorkspace(PROJECT_START, wsName, {
|
|
554
657
|
yes: true, cliVersion: PACKAGE_JSON.version,
|
|
555
658
|
})
|
|
556
|
-
: planOpenCodeWorkspace(PROJECT_START,
|
|
659
|
+
: planOpenCodeWorkspace(PROJECT_START, wsName, PACKAGE_JSON.version);
|
|
557
660
|
if (o.json)
|
|
558
661
|
console.log(JSON.stringify(out, null, 2));
|
|
559
662
|
else
|
|
@@ -572,11 +675,35 @@ async function main() {
|
|
|
572
675
|
return;
|
|
573
676
|
}
|
|
574
677
|
if (sub === 'run') {
|
|
678
|
+
const timeoutMs = o.timeout === undefined ? undefined : Number(o.timeout);
|
|
679
|
+
if (o.status) {
|
|
680
|
+
// Resume a timed-out multica run by re-reading the SAME Issue; no new Issue is created.
|
|
681
|
+
rejectWorkspaceOptions(o, ['json', 'yes', 'execute', 'out', 'timeout', 'status', 'run-id'], 'workspace run --status');
|
|
682
|
+
if (positionals.length !== 1)
|
|
683
|
+
fail('workspace run --status 需要一个 Workspace name');
|
|
684
|
+
if (o['prompt-file'])
|
|
685
|
+
fail('workspace run --status 不接受 --prompt-file;用 --run-id 续读');
|
|
686
|
+
if (!o['run-id'])
|
|
687
|
+
fail('workspace run --status 需要 --run-id <上次 run 的 runId>');
|
|
688
|
+
const out = statusMulticaWorkspaceRun(PROJECT_START, positionals[0], {
|
|
689
|
+
runId: o['run-id'], execute: o.execute, yes: o.yes, timeoutMs, out: o.out,
|
|
690
|
+
cliVersion: PACKAGE_JSON.version,
|
|
691
|
+
});
|
|
692
|
+
if (o.json)
|
|
693
|
+
console.log(JSON.stringify(out, null, 2));
|
|
694
|
+
else {
|
|
695
|
+
console.log(`${out.passed ? '✅' : '❌'} workspace run ${out.runId} (resumed)`);
|
|
696
|
+
if (out.answer)
|
|
697
|
+
console.log(out.answer);
|
|
698
|
+
}
|
|
699
|
+
if (!out.passed)
|
|
700
|
+
process.exitCode = 2;
|
|
701
|
+
return;
|
|
702
|
+
}
|
|
575
703
|
rejectWorkspaceOptions(o, ['json', 'yes', 'execute', 'prompt-file', 'out', 'timeout'], 'workspace run');
|
|
576
704
|
if (positionals.length !== 1 || !o['prompt-file']) {
|
|
577
705
|
fail('workspace run 需要一个 Workspace name 和 --prompt-file <file>');
|
|
578
706
|
}
|
|
579
|
-
const timeoutMs = o.timeout === undefined ? undefined : Number(o.timeout);
|
|
580
707
|
const prompt = readProjectText(PROJECT_START, o['prompt-file'], 'workspace run prompt');
|
|
581
708
|
const workspace = showDevelopmentWorkspace(PROJECT_START, positionals[0], PACKAGE_JSON.version);
|
|
582
709
|
const out = workspace.provider.kind === 'multica'
|