@xdxer/dingtalk-agent 0.1.4-beta.8 → 0.1.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 +233 -0
- package/README.en.md +167 -0
- package/README.md +101 -248
- package/dist/bin/dingtalk-agent.js +1255 -25
- package/dist/bin/dingtalk-agent.js.map +1 -1
- package/dist/src/actions.js +98 -14
- package/dist/src/actions.js.map +1 -1
- package/dist/src/agent-audit.js +1385 -0
- package/dist/src/agent-audit.js.map +1 -0
- package/dist/src/agent-bindings.js +132 -0
- package/dist/src/agent-bindings.js.map +1 -0
- package/dist/src/agent-definition.js +182 -0
- package/dist/src/agent-definition.js.map +1 -0
- package/dist/src/agent-enhance.js +711 -0
- package/dist/src/agent-enhance.js.map +1 -0
- package/dist/src/agent-platform.js +299 -0
- package/dist/src/agent-platform.js.map +1 -0
- package/dist/src/bootstrap.js +125 -17
- package/dist/src/bootstrap.js.map +1 -1
- package/dist/src/config.js +1 -7
- package/dist/src/config.js.map +1 -1
- package/dist/src/development-workspace.js +755 -0
- package/dist/src/development-workspace.js.map +1 -0
- package/dist/src/doctor.js +74 -15
- package/dist/src/doctor.js.map +1 -1
- package/dist/src/dws.js +145 -0
- package/dist/src/dws.js.map +1 -1
- package/dist/src/eval-evidence.js +193 -0
- package/dist/src/eval-evidence.js.map +1 -0
- package/dist/src/host-detect.js +146 -0
- package/dist/src/host-detect.js.map +1 -0
- package/dist/src/instruction-path.js +270 -0
- package/dist/src/instruction-path.js.map +1 -0
- package/dist/src/invocation.js +36 -0
- package/dist/src/invocation.js.map +1 -0
- package/dist/src/lab.js +679 -0
- package/dist/src/lab.js.map +1 -0
- package/dist/src/lease.js +100 -0
- package/dist/src/lease.js.map +1 -0
- package/dist/src/map.js +157 -0
- package/dist/src/map.js.map +1 -0
- package/dist/src/memory/candidates.js +451 -0
- package/dist/src/memory/candidates.js.map +1 -0
- package/dist/src/memory/completion-evidence.js +536 -0
- package/dist/src/memory/completion-evidence.js.map +1 -0
- package/dist/src/memory/operational.js +263 -0
- package/dist/src/memory/operational.js.map +1 -0
- package/dist/src/memory/remote-state.js +478 -0
- package/dist/src/memory/remote-state.js.map +1 -0
- package/dist/src/memory/task-checkpoints.js +204 -0
- package/dist/src/memory/task-checkpoints.js.map +1 -0
- package/dist/src/multica-deploy.js +1538 -0
- package/dist/src/multica-deploy.js.map +1 -0
- package/dist/src/multica-provider.js +685 -0
- package/dist/src/multica-provider.js.map +1 -0
- package/dist/src/opencode-evals.js +1547 -0
- package/dist/src/opencode-evals.js.map +1 -0
- package/dist/src/opencode-isolation.js +124 -0
- package/dist/src/opencode-isolation.js.map +1 -0
- package/dist/src/opencode-provider.js +532 -0
- package/dist/src/opencode-provider.js.map +1 -0
- package/dist/src/opencode-workspace.js +208 -0
- package/dist/src/opencode-workspace.js.map +1 -0
- package/dist/src/perception.js +225 -0
- package/dist/src/perception.js.map +1 -0
- package/dist/src/personal-event-evals.js +595 -0
- package/dist/src/personal-event-evals.js.map +1 -0
- package/dist/src/promotion.js +786 -0
- package/dist/src/promotion.js.map +1 -0
- package/dist/src/remote-semantic-state-live-evals.js +888 -0
- package/dist/src/remote-semantic-state-live-evals.js.map +1 -0
- package/dist/src/remote-semantic-state-worker.js +38 -0
- package/dist/src/remote-semantic-state-worker.js.map +1 -0
- package/dist/src/remote-state-evals.js +502 -0
- package/dist/src/remote-state-evals.js.map +1 -0
- package/dist/src/response-gate.js +51 -0
- package/dist/src/response-gate.js.map +1 -0
- package/dist/src/robot-evals.js +771 -0
- package/dist/src/robot-evals.js.map +1 -0
- package/dist/src/sessions.js +66 -105
- package/dist/src/sessions.js.map +1 -1
- package/dist/src/setup.js +6 -5
- package/dist/src/setup.js.map +1 -1
- package/dist/src/skill-manager.js +162 -24
- package/dist/src/skill-manager.js.map +1 -1
- package/dist/src/skills.js +2 -1
- package/dist/src/skills.js.map +1 -1
- package/dist/src/storage-evals.js +26 -0
- package/dist/src/storage-evals.js.map +1 -0
- package/dist/src/types.js.map +1 -1
- package/dist/src/upgrade.js +23 -27
- package/dist/src/upgrade.js.map +1 -1
- package/dist/src/version.js +73 -0
- package/dist/src/version.js.map +1 -0
- package/dist/src/waits.js +5 -1
- package/dist/src/waits.js.map +1 -1
- package/dist/src/workspace.js +28 -3
- package/dist/src/workspace.js.map +1 -1
- package/docs/INSTALLATION.md +50 -3
- package/docs/SECOND-AGENT-ACCEPTANCE.md +62 -0
- package/docs/architecture/agent-memory-topology.png +0 -0
- package/docs/architecture/agent-memory-topology.svg +132 -0
- package/docs/architecture/general-agent-kernel-topology.png +0 -0
- package/docs/architecture/general-agent-kernel-topology.svg +149 -0
- package/docs/architecture/provider-bound-development-workspace.png +0 -0
- package/docs/architecture/provider-bound-development-workspace.svg +141 -0
- package/docs/architecture/task-completion-gate.png +0 -0
- package/docs/architecture/task-completion-gate.svg +191 -0
- package/docs/assets/agent-delivery-lifecycle.svg +103 -0
- package/docs/schemas/agent-audit-load-evidence.schema.json +14 -0
- package/docs/schemas/agent-audit.schema.json +92 -0
- package/docs/schemas/agent-bindings.schema.json +54 -0
- package/docs/schemas/agent-definition.schema.json +78 -0
- package/docs/schemas/agent-enhancement-plan.schema.json +88 -0
- package/docs/schemas/agent-enhancement-receipt.schema.json +37 -0
- package/docs/schemas/agent-platform.schema.json +13 -0
- package/docs/schemas/enriched-invocation.schema.json +46 -0
- package/docs/schemas/eval-candidate-plan.schema.json +28 -0
- package/docs/schemas/eval-candidate-result.schema.json +20 -0
- package/docs/schemas/eval-candidate.schema.json +30 -0
- package/docs/schemas/invocation.schema.json +19 -0
- package/docs/schemas/memory-candidate-proposal.schema.json +18 -0
- package/docs/schemas/memory-candidate.schema.json +76 -0
- package/docs/schemas/memory-publish-target.schema.json +25 -0
- package/docs/schemas/multica-deployment-list.schema.json +29 -0
- package/docs/schemas/multica-deployment-operation.schema.json +51 -0
- package/docs/schemas/multica-deployment-plan.schema.json +70 -0
- package/docs/schemas/multica-deployment-receipt.schema.json +87 -0
- package/docs/schemas/multica-deployment-status.schema.json +23 -0
- package/docs/schemas/multica-workspace-inspection.schema.json +77 -0
- package/docs/schemas/multica-workspace-plan.schema.json +68 -0
- package/docs/schemas/multica-workspace-resource-list.schema.json +27 -0
- package/docs/schemas/multica-workspace-status.schema.json +34 -0
- package/docs/schemas/observation.schema.json +21 -0
- package/docs/schemas/operational-memory-provider.schema.json +36 -0
- package/docs/schemas/operational-memory-record.schema.json +24 -0
- package/docs/schemas/perception-input.schema.json +56 -0
- package/docs/schemas/project.schema.json +115 -0
- package/docs/schemas/promotion-list.schema.json +36 -0
- package/docs/schemas/promotion-plan.schema.json +60 -0
- package/docs/schemas/promotion-policy.schema.json +29 -0
- package/docs/schemas/promotion-receipt.schema.json +43 -0
- package/docs/schemas/promotion-status.schema.json +23 -0
- package/docs/schemas/release-readiness.schema.json +66 -0
- package/docs/schemas/remote-semantic-state-live-eval.schema.json +60 -0
- package/docs/schemas/remote-semantic-state-manifest.schema.json +79 -0
- package/docs/schemas/remote-semantic-state-provider.schema.json +98 -0
- package/docs/schemas/response-gate.schema.json +20 -0
- package/docs/schemas/task-checkpoint.schema.json +71 -0
- package/docs/schemas/task-completion-evidence.schema.json +154 -0
- package/docs/schemas/workspace-doctor.schema.json +56 -0
- package/docs/schemas/workspace-state.schema.json +39 -0
- package/evals/README.md +17 -0
- package/evals/baselines/2026-07-16/opencode-basic-010-completion-summary.json +123 -0
- package/evals/baselines/2026-07-16/opencode-basic-skill-required-summary.json +69 -0
- package/evals/baselines/2026-07-16/opencode-multi-surface-summary.json +63 -0
- package/evals/baselines/2026-07-16/remote-state-live-summary.json +70 -0
- package/evals/baselines/2026-07-17/agent-enhance-opencode-dogfood-summary.json +98 -0
- package/evals/baselines/2026-07-17/personal-event-live-readiness-summary.json +68 -0
- package/examples/agents/fde-coach/AGENTS.md +26 -0
- package/examples/agents/fde-coach/MEMORY.md +3 -0
- package/examples/agents/fde-coach/fields/default/field.json +24 -0
- package/examples/agents/fde-coach/knowledge/INDEX.md +4 -0
- package/examples/agents/fde-coach/skills/fde-coach/SKILL.md +13 -0
- package/examples/agents/release-manager/AGENTS.md +26 -0
- package/examples/agents/release-manager/MEMORY.md +3 -0
- package/examples/agents/release-manager/fields/default/field.json +24 -0
- package/examples/agents/release-manager/knowledge/INDEX.md +4 -0
- package/examples/agents/release-manager/skills/release-manager/SKILL.md +13 -0
- package/lab/README.md +109 -0
- package/lab/agent-eval/catalog.json +91 -0
- package/lab/agent-eval/classic-failures.json +177 -0
- package/lab/agent-eval/completion-gate-regression.json +99 -0
- package/lab/agent-eval/personal-event-live.example.json +94 -0
- package/lab/agent-eval/remote-semantic-state-live.example.json +70 -0
- package/lab/agent-eval/remote-semantic-state-provider.fixture.json +47 -0
- package/lab/agent-eval/remote-state-workspace/AGENTS.md +8 -0
- package/lab/agent-eval/remote-state-workspace/opencode.json +7 -0
- package/lab/agent-eval/remote-state-workspace/skills/remote-state-operator/SKILL.md +13 -0
- package/lab/agent-eval/remote-state.example.json +31 -0
- package/lab/agent-eval/workspace/AGENTS.md +7 -0
- package/lab/agent-eval/workspace/MEMORY.md +4 -0
- package/lab/agent-eval/workspace/artifacts/pending-review.md +3 -0
- package/lab/agent-eval/workspace/knowledge/INDEX.md +4 -0
- package/lab/agent-eval/workspace/opencode.json +20 -0
- package/lab/manifest.example.json +27 -0
- package/lab/manifest.personal-event.example.json +27 -0
- package/lab/project-workspace/README.md +11 -0
- package/lab/project-workspace/fake-multica-provider.mjs +277 -0
- package/lab/project-workspace/multica-deploy.fixture.json +29 -0
- package/lab/project-workspace/multica-readonly.fixture.json +69 -0
- package/lab/project-workspace/observation.fixture.json +14 -0
- package/lab/project-workspace/opencode-provider-suite.json +65 -0
- package/lab/project-workspace/project.fixture.json +44 -0
- package/lab/project-workspace/promotion-policy.fixture.json +15 -0
- package/lab/robot-eval/pool.example.json +30 -0
- package/lab/robot-eval/suite.json +123 -0
- package/lab/robot-eval/workspace/AGENTS.md +21 -0
- package/lab/robot-eval/workspace/MEMORY.md +3 -0
- package/lab/robot-eval/workspace/knowledge/INDEX.md +5 -0
- package/lab/robot-eval/workspace/opencode.json +22 -0
- package/lab/schemas/agent-eval-catalog.schema.json +47 -0
- package/lab/schemas/lab-manifest.schema.json +70 -0
- package/lab/schemas/personal-event-eval.schema.json +91 -0
- package/lab/schemas/remote-state-eval.schema.json +66 -0
- package/lab/schemas/robot-eval-suite.schema.json +184 -0
- package/lab/schemas/robot-pool.schema.json +56 -0
- package/package.json +28 -9
- package/skills/README.md +23 -0
- package/skills/core/dingtalk-agent-compose/SKILL.md +151 -0
- package/skills/core/dingtalk-agent-compose/assets/AGENTS.template.md +35 -0
- package/skills/core/dingtalk-agent-compose/assets/agent.bindings.dingtalk-doc.template.json +13 -0
- package/skills/core/dingtalk-agent-compose/assets/agent.bindings.local.template.json +13 -0
- package/skills/core/dingtalk-agent-compose/assets/hosts/opencode/opencode.template.json +12 -0
- package/skills/core/dingtalk-agent-compose/assets/role-skill.template.md +32 -0
- package/skills/core/dingtalk-agent-compose/evals/evals.json +129 -0
- package/skills/core/dingtalk-agent-compose/references/agent-definition-contract.md +55 -0
- package/skills/core/dingtalk-agent-compose/references/host-loading-contract.md +58 -0
- package/skills/core/dingtalk-agent-compose/references/hosts/claude-code.md +48 -0
- package/skills/core/dingtalk-agent-compose/references/hosts/opencode.md +77 -0
- package/skills/core/dingtalk-agent-compose/references/storage-routing.md +20 -0
- package/skills/core/dingtalk-agent-eval/SKILL.md +140 -0
- package/skills/core/dingtalk-agent-eval/assets/eval-catalog.template.json +18 -0
- package/skills/core/dingtalk-agent-eval/evals/evals.json +83 -0
- package/skills/core/dingtalk-agent-eval/references/eval-topology.md +48 -0
- package/skills/core/dingtalk-agent-eval/references/evidence-contract.md +52 -0
- package/skills/core/dingtalk-agent-eval/references/failure-to-case.md +35 -0
- package/skills/core/dingtalk-agent-eval/references/interactive-debug-channels.md +93 -0
- package/skills/core/dingtalk-agent-eval/references/local-connector-smoke.md +75 -0
- package/skills/core/dingtalk-agent-eval/references/scenario-taxonomy.md +25 -0
- package/skills/core/dingtalk-agent-eval/references/storage-modes.md +75 -0
- package/skills/core/dingtalk-basic-behavior/SKILL.md +87 -0
- package/skills/core/dingtalk-basic-behavior/assets/memory-candidate-proposal.json +10 -0
- package/skills/{dingtalk-basic-behavior/assets/task-checkpoint.md → core/dingtalk-basic-behavior/assets/task-checkpoint.json} +2 -21
- package/skills/{dingtalk-basic-behavior → core/dingtalk-basic-behavior}/references/action-contract.md +2 -0
- package/skills/core/dingtalk-basic-behavior/references/memory-and-evolution.md +53 -0
- package/skills/core/dingtalk-basic-behavior/references/perception-and-gates.md +28 -0
- package/skills/core/dingtalk-basic-behavior/references/risk-authority-and-privacy.md +62 -0
- package/skills/{dingtalk-basic-behavior → core/dingtalk-basic-behavior}/references/task-lifecycle.md +47 -10
- package/skills/core/dingtalk-basic-behavior/references/truth-and-recovery.md +65 -0
- package/skills/platforms/deap/PLATFORM.md +3 -0
- package/skills/platforms/deap/README.md +3 -0
- package/skills/platforms/multica-dingtalk/PLATFORM.md +40 -0
- package/skills/platforms/multica-dingtalk/dingtalk-agent-boot-multica/SKILL.md +40 -0
- package/skills/platforms/multica-dingtalk/dingtalk-agent-deploy-multica/SKILL.md +60 -0
- package/skills/platforms/multica-dingtalk/dingtalk-agent-deploy-multica/references/multica-deployment-contract.md +49 -0
- package/skills/platforms/multica-dingtalk/dingtalk-agent-deploy-multica/references/promotion-observation-contract.md +49 -0
- package/skills/platforms/multica-dingtalk/multica-external/SKILL.md +282 -0
- package/skills/platforms/multica-dingtalk/multica-external/scripts/bootstrap.sh +78 -0
- package/skills/platforms/multica-dingtalk/multica-external/scripts/multica_ext.py +1180 -0
- package/skills/dingtalk-basic-behavior/SKILL.md +0 -86
- package/skills/dingtalk-basic-behavior/references/memory-and-evolution.md +0 -27
- /package/skills/{dingtalk-basic-behavior → core/dingtalk-basic-behavior}/references/event-to-behavior.md +0 -0
- /package/skills/{dingtalk-basic-behavior → core/dingtalk-basic-behavior}/references/runtime-modes.md +0 -0
|
@@ -9,8 +9,8 @@
|
|
|
9
9
|
//
|
|
10
10
|
// 因为:文档会被漏读、误读、自我说服;**撞到闸门上就没得商量。**
|
|
11
11
|
import { parseArgs } from 'node:util';
|
|
12
|
-
import { join, resolve } from 'node:path';
|
|
13
|
-
import { readFileSync } from 'node:fs';
|
|
12
|
+
import { join, relative, resolve } from 'node:path';
|
|
13
|
+
import { existsSync, readFileSync, realpathSync } from 'node:fs';
|
|
14
14
|
import { spawn, spawnSync } from 'node:child_process';
|
|
15
15
|
import * as cfgmod from '../src/config.js';
|
|
16
16
|
import { init } from '../src/init.js';
|
|
@@ -19,10 +19,27 @@ import { readEventFile, consumeNdjson, heartbeatEvent } from '../src/driver.js';
|
|
|
19
19
|
import { findRun, previewAction, executeAction } from '../src/actions.js';
|
|
20
20
|
import { resolvePackageRoot } from '../src/package-root.js';
|
|
21
21
|
import { bootstrap } from '../src/bootstrap.js';
|
|
22
|
+
import { loadAgentBindings } from '../src/agent-bindings.js';
|
|
23
|
+
import { auditAgent } from '../src/agent-audit.js';
|
|
24
|
+
import { applyAgentEnhancement, planAgentEnhancement, } from '../src/agent-enhance.js';
|
|
25
|
+
import { doctorLab, runLab, teardownLab, verifyLab } from '../src/lab.js';
|
|
26
|
+
import { runRobotEvaluation } from '../src/robot-evals.js';
|
|
27
|
+
import { runOpenCodeEvaluation } from '../src/opencode-evals.js';
|
|
28
|
+
import { runStorageEvaluation } from '../src/storage-evals.js';
|
|
29
|
+
import { runPersonalEventEvaluation } from '../src/personal-event-evals.js';
|
|
22
30
|
import { doctor } from '../src/doctor.js';
|
|
31
|
+
import { doctorDevelopmentWorkspace, inspectAgentProject, showDevelopmentWorkspace, } from '../src/development-workspace.js';
|
|
32
|
+
import { applyOpenCodeWorkspace, evalOpenCodeWorkspace, planOpenCodeWorkspace, runOpenCodeWorkspace, useOpenCodeWorkspace, } from '../src/opencode-provider.js';
|
|
33
|
+
import { inspectMulticaWorkspace, listMulticaWorkspaceResources, planMulticaWorkspace, statusMulticaWorkspace, } from '../src/multica-provider.js';
|
|
34
|
+
import { applyMulticaDeployment, listMulticaDeployments, planMulticaDeployment, statusMulticaDeployment, } from '../src/multica-deploy.js';
|
|
35
|
+
import { applyObservation, applyPromotion, listPromotions, planObservation, planPromotion, statusPromotion, } from '../src/promotion.js';
|
|
23
36
|
import { setup } from '../src/setup.js';
|
|
24
37
|
import { upgradeAgent } from '../src/upgrade.js';
|
|
25
|
-
import {
|
|
38
|
+
import { checkpointTask, showTaskCheckpoint } from '../src/memory/task-checkpoints.js';
|
|
39
|
+
import { upsertOperationalMemory } from '../src/memory/operational.js';
|
|
40
|
+
import { proposeMemoryCandidate, publishMemoryCandidate, reviewMemoryCandidate, showMemoryCandidate, } from '../src/memory/candidates.js';
|
|
41
|
+
import { installBundledSkills, installGlobalSkill, skillStatus, skillSuiteStatus, uninstallBundledSkills, uninstallGlobalSkill, upgradeBundledSkills, upgradeGlobalSkill, } from '../src/skill-manager.js';
|
|
42
|
+
import { agentPlatformReadiness, MANAGED_AGENT_PLATFORMS, multicaTargets, platformDocPath, platformSkillForRole, requireSupportedAgentPlatform, resolveAgentPlatform, resolveEndpoint, statusLabel as platformStatusLabel, useAgentPlatform, } from '../src/agent-platform.js';
|
|
26
43
|
const PACKAGE_ROOT = resolvePackageRoot(import.meta.url);
|
|
27
44
|
const PACKAGE_JSON = JSON.parse(readFileSync(join(PACKAGE_ROOT, 'package.json'), 'utf8'));
|
|
28
45
|
// ROOT = **你的工作区**(当前目录),不是包所在的目录。
|
|
@@ -30,6 +47,7 @@ const PACKAGE_JSON = JSON.parse(readFileSync(join(PACKAGE_ROOT, 'package.json'),
|
|
|
30
47
|
const ROOT = process.env.DTA_ROOT
|
|
31
48
|
? resolve(process.env.DTA_ROOT)
|
|
32
49
|
: (cfgmod.findRoot(process.cwd()) || process.cwd());
|
|
50
|
+
const PROJECT_START = process.env.DTA_ROOT ? resolve(process.env.DTA_ROOT) : process.cwd();
|
|
33
51
|
const HELP = `
|
|
34
52
|
dta —— 给 Agent 安装钉钉员工的基础行为和工作环境
|
|
35
53
|
|
|
@@ -39,13 +57,16 @@ dta —— 给 Agent 安装钉钉员工的基础行为和工作环境
|
|
|
39
57
|
· 从本地目录或钉钉文档加载身份、记忆和知识
|
|
40
58
|
|
|
41
59
|
开始使用:
|
|
42
|
-
dta setup 首次配置 CLI、DWS
|
|
60
|
+
dta setup 首次配置 CLI、DWS 和内置 Skill(基础行为 + Agent 装配 + 交付后评测)
|
|
43
61
|
dta bootstrap --json 为当前 Agent 会话加载工作区
|
|
62
|
+
dta agent enhance / audit 安全增强已有仓库,再审计定义、存储与 Skill 真加载
|
|
63
|
+
dta info / dta workspace doctor <name> 查看 Project 并只读诊断 Workspace
|
|
64
|
+
dta agent-platform use <platform> → dta deploy / dta promote 声明平台归属并装平台技能包,再受控部署与晋级
|
|
44
65
|
|
|
45
66
|
维护环境:
|
|
46
67
|
dta doctor 检查哪里没装好,并给出修复提示
|
|
47
68
|
dta upgrade 自升级,再重新检查完整环境
|
|
48
|
-
dta skill status
|
|
69
|
+
dta skill status 查看内置 Skill 的版本状态与三个客户端能否发现(可加 name 只查一个)
|
|
49
70
|
|
|
50
71
|
接入钉钉事件和可靠外发:dta help runtime
|
|
51
72
|
`;
|
|
@@ -53,10 +74,14 @@ const RUNTIME_HELP = `
|
|
|
53
74
|
dingtalk-agent 可信事件运行时(可选宿主能力)
|
|
54
75
|
|
|
55
76
|
init [--context-id X] [--memory <uri>] [--knowledge <uri>]
|
|
56
|
-
prepare --event-file <file|->
|
|
77
|
+
prepare --event-file <file|-> [--perception-file <file>]
|
|
57
78
|
run --stdin | --event-file <file> | --heartbeat
|
|
58
79
|
dispatch pending
|
|
59
80
|
dispatch ack --event-id X --run-id X
|
|
81
|
+
task show --json
|
|
82
|
+
task checkpoint --input checkpoint.json --expect-revision N
|
|
83
|
+
memory operational upsert --provider provider.json --input record.json [--live --yes]
|
|
84
|
+
memory candidate propose|show|review|publish
|
|
60
85
|
act ack|reply|ask|silence
|
|
61
86
|
|
|
62
87
|
这些命令负责目标冻结、Session/Run、Wait、幂等和回执;普通 Agent Session 不必使用。
|
|
@@ -70,6 +95,86 @@ dingtalk-agent 可选 Driver / 开发联调适配器
|
|
|
70
95
|
|
|
71
96
|
listen 不是 Agent 主入口。Claude Code、DWS 云端或其他宿主都可以直接提供事件。
|
|
72
97
|
`;
|
|
98
|
+
const LAB_HELP = `
|
|
99
|
+
dingtalk-agent 真实世界联调控制面
|
|
100
|
+
|
|
101
|
+
lab doctor --manifest lab/manifest.local.json
|
|
102
|
+
lab run --manifest <file> --event-file <file> --case-id <id> [--reply <text>]
|
|
103
|
+
lab verify --evidence <run-dir>
|
|
104
|
+
lab teardown --manifest <file> --evidence <run-dir>
|
|
105
|
+
lab eval --pool <pool.local.json> --suite <suite.json> [--lanes stateless,stateful]
|
|
106
|
+
lab eval --engine opencode --workspace <agent-dir> --suite <suite.json> [--cases id1,id2] [--runs 3] [--previous-skill <dir>]
|
|
107
|
+
lab eval --engine storage --workspace <agent-dir> --suite <remote-state.json> [--execute --live --yes]
|
|
108
|
+
lab eval --engine personal-event --workspace <agent-dir> --suite <suite.json> [--execute --live --yes]
|
|
109
|
+
|
|
110
|
+
mock-integration 还要求 DTA_LAB_FAKE_DWS=1;robot/personal Live 必须显式 --live --yes。
|
|
111
|
+
lab eval 默认只输出计划;Robot Live 用 --live --yes,OpenCode A/B 用 --execute --yes。
|
|
112
|
+
Remote State 用 --execute --yes 读取 DWS/调用模型,再加 --live 才执行唯一写探针。
|
|
113
|
+
OpenCode 对照强制验证每个 Basic Skill 的 load probe;提供 --previous-skill 时运行 current/previous,不连接 DWS。
|
|
114
|
+
Lab 只管理 allowlist、预算、marker、证据和清理;事件触发器仍在外部。
|
|
115
|
+
`;
|
|
116
|
+
const AGENT_HELP = `
|
|
117
|
+
dingtalk-agent 开发者装配验收
|
|
118
|
+
|
|
119
|
+
agent audit [--bindings agent.bindings.json] [--require-skill <name>]
|
|
120
|
+
agent audit [--bindings <file>] [--require-skill <name>] --verify-load --yes
|
|
121
|
+
agent audit [--bindings <file>] --load-report <agent-audit-load-evidence.json> [--remote-report <report.json>]
|
|
122
|
+
agent enhance --role-skill <name>[,<name>] [--project-name <name>] [--dry-run] [--json]
|
|
123
|
+
agent enhance --role-skill <name>[,<name>] --plan-id <current-plan-id> --yes [--json]
|
|
124
|
+
|
|
125
|
+
默认只做本地静态审计,不访问 DWS、不调用模型;状态为 partial 时返回退出码 2。
|
|
126
|
+
--verify-load --yes 会运行隔离的 OpenCode load probe,但仍不访问钉钉。
|
|
127
|
+
远端语义状态由 storage eval 独立验收,再通过 --remote-report 绑定证据。
|
|
128
|
+
`;
|
|
129
|
+
const WORKSPACE_HELP = `
|
|
130
|
+
dingtalk-agent Project / Development Workspace
|
|
131
|
+
|
|
132
|
+
info [--json]
|
|
133
|
+
workspace list [--json]
|
|
134
|
+
workspace show <name> [--json]
|
|
135
|
+
workspace doctor <name> [--json]
|
|
136
|
+
workspace plan <multica-name> [--json]
|
|
137
|
+
workspace inspect <multica-name> [--execute --yes] [--json]
|
|
138
|
+
workspace remote-list <multica-name> [--execute --yes] [--json]
|
|
139
|
+
workspace status <multica-name> [--json]
|
|
140
|
+
workspace create <name> [--dry-run | --yes] [--json]
|
|
141
|
+
workspace use <name> [--json]
|
|
142
|
+
workspace run <name> --prompt-file <file> [--execute --yes] [--json]
|
|
143
|
+
workspace eval <name> --suite <file> [--execute --yes] [--runs N] [--json]
|
|
144
|
+
|
|
145
|
+
命令会从当前目录向上发现 dingtalk-agent.json;旧 workspace@1 只读显示为 legacy-prepared。
|
|
146
|
+
Multica plan/status 默认不调用 Provider;inspect/remote-list 只有 --execute --yes 才读取当前 profile 和远端 scope。
|
|
147
|
+
Multica readback 只保存脱敏事实,不执行 create/update/apply/deploy;OpenCode create 只物化本地环境。
|
|
148
|
+
这些命令都不访问 DWS;Multica 远端写入只通过 dta deploy 的冻结 plan 闸门。
|
|
149
|
+
`;
|
|
150
|
+
const DEPLOY_HELP = `
|
|
151
|
+
dingtalk-agent Multica 受控部署
|
|
152
|
+
|
|
153
|
+
deploy --workspace <name> --dry-run [--json]
|
|
154
|
+
deploy --workspace <name> --plan-id <id> --yes [--no-wait] [--json]
|
|
155
|
+
deploy --workspace <name> --status [--operation-id <id>] [--json]
|
|
156
|
+
deploy --workspace <name> --status --operation-id <id> --execute --yes [--json]
|
|
157
|
+
deploy --workspace <name> --list [--json]
|
|
158
|
+
deploy --workspace <name> --retire --dry-run [--json]
|
|
159
|
+
deploy --workspace <name> --retire --plan-id <id> --yes [--json]
|
|
160
|
+
|
|
161
|
+
dry-run 不启动 Multica。apply/retire 必须携带当前 planId;scope 或源码漂移会在写入前拒绝。
|
|
162
|
+
status 默认只验本地脱敏 operation/Receipt;--execute --yes 才做远端独立回读。
|
|
163
|
+
deploy 只管理 Agent、完整 Skill tree、assignment 和 load smoke,不创建机器人、Webhook、Autopilot 或定时 Trigger。
|
|
164
|
+
`;
|
|
165
|
+
const PROMOTION_HELP = `
|
|
166
|
+
dingtalk-agent 已验版本晋级与反馈候选
|
|
167
|
+
|
|
168
|
+
promote --policy <file> --route <id> --dry-run [--json]
|
|
169
|
+
promote --policy <file> --route <id> --plan-id <id> --yes [--no-wait] [--json]
|
|
170
|
+
promote --status [--promotion-id <id>] [--json]
|
|
171
|
+
promote --list [--json]
|
|
172
|
+
observe --promotion-id <id> --input <observation.json> --dry-run [--json]
|
|
173
|
+
observe --promotion-id <id> --input <observation.json> --yes [--json]
|
|
174
|
+
|
|
175
|
+
Promotion 只接受指定 suite 的 load/hard/surface gate 与精确 W2 evidence hash,并委托 W4 deploy。
|
|
176
|
+
Observe 只写 gitignored、proposed、不可直接发布的 Eval candidate;不修改 AGENTS.md、Prompt、Skill 或 Trigger。
|
|
177
|
+
`;
|
|
73
178
|
function fail(msg, code = 1, hint = '') {
|
|
74
179
|
console.error(`错误: ${msg}`);
|
|
75
180
|
if (hint)
|
|
@@ -96,6 +201,26 @@ async function main() {
|
|
|
96
201
|
console.log(ADAPTER_HELP);
|
|
97
202
|
return;
|
|
98
203
|
}
|
|
204
|
+
if (cmd === 'help' && sub === 'lab') {
|
|
205
|
+
console.log(LAB_HELP);
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
208
|
+
if (cmd === 'help' && sub === 'agent') {
|
|
209
|
+
console.log(AGENT_HELP);
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
if (cmd === 'help' && sub === 'workspace') {
|
|
213
|
+
console.log(WORKSPACE_HELP);
|
|
214
|
+
return;
|
|
215
|
+
}
|
|
216
|
+
if (cmd === 'help' && sub === 'deploy') {
|
|
217
|
+
console.log(DEPLOY_HELP);
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
if (cmd === 'help' && ['promote', 'observe'].includes(sub || '')) {
|
|
221
|
+
console.log(PROMOTION_HELP);
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
99
224
|
if (cmd === 'help' && sub) {
|
|
100
225
|
fail(`不认识的帮助主题: ${sub}`, 1, '运行 dta --help 回到产品入口;事件宿主可用 dta help runtime。');
|
|
101
226
|
}
|
|
@@ -107,6 +232,392 @@ async function main() {
|
|
|
107
232
|
console.log(PACKAGE_JSON.version);
|
|
108
233
|
return;
|
|
109
234
|
}
|
|
235
|
+
if (cmd === 'deploy') {
|
|
236
|
+
const platformForDeploy = requireSupportedAgentPlatform('deploy', PROJECT_START);
|
|
237
|
+
disclosePlatformSkill(platformForDeploy, 'deploy');
|
|
238
|
+
const { values: o, positionals } = parseArgs({
|
|
239
|
+
args: argv.slice(1), allowPositionals: true,
|
|
240
|
+
options: {
|
|
241
|
+
workspace: { type: 'string' }, json: { type: 'boolean' },
|
|
242
|
+
'dry-run': { type: 'boolean' }, yes: { type: 'boolean' },
|
|
243
|
+
'plan-id': { type: 'string' }, 'no-wait': { type: 'boolean' },
|
|
244
|
+
status: { type: 'boolean' }, list: { type: 'boolean' },
|
|
245
|
+
execute: { type: 'boolean' }, 'operation-id': { type: 'string' },
|
|
246
|
+
timeout: { type: 'string' }, 'smoke-timeout': { type: 'string' },
|
|
247
|
+
retire: { type: 'boolean' },
|
|
248
|
+
},
|
|
249
|
+
});
|
|
250
|
+
if (positionals.length)
|
|
251
|
+
fail('deploy 不接受位置参数;使用 --workspace <name>');
|
|
252
|
+
if (!o.workspace)
|
|
253
|
+
fail('deploy 必须显式传 --workspace <name>');
|
|
254
|
+
const modes = [
|
|
255
|
+
Boolean(o.status), Boolean(o.list), Boolean(o['dry-run']), Boolean(o.yes && !o.status),
|
|
256
|
+
]
|
|
257
|
+
.filter(Boolean).length;
|
|
258
|
+
if (modes !== 1) {
|
|
259
|
+
fail('deploy 必须且只能选择 --dry-run、--yes、--status 或 --list 之一');
|
|
260
|
+
}
|
|
261
|
+
const timeoutMs = parseOptionalTimeout(o.timeout, '--timeout');
|
|
262
|
+
const smokeTimeoutMs = parseOptionalTimeout(o['smoke-timeout'], '--smoke-timeout');
|
|
263
|
+
let out;
|
|
264
|
+
if (o.list) {
|
|
265
|
+
if (o.execute || o['operation-id'] || o.retire || o['plan-id'] || o['no-wait'] ||
|
|
266
|
+
o.timeout || o['smoke-timeout']) {
|
|
267
|
+
fail('deploy --list 只接受 --workspace 和 --json');
|
|
268
|
+
}
|
|
269
|
+
out = listMulticaDeployments(PROJECT_START, o.workspace, PACKAGE_JSON.version);
|
|
270
|
+
}
|
|
271
|
+
else if (o.status) {
|
|
272
|
+
if (o.retire || o['plan-id'] || o['no-wait'] || o['dry-run'] || o['smoke-timeout']) {
|
|
273
|
+
fail('deploy --status 不接受 retire/plan-id/no-wait/dry-run/smoke-timeout');
|
|
274
|
+
}
|
|
275
|
+
if (Boolean(o.execute) !== Boolean(o.yes)) {
|
|
276
|
+
fail('deploy --status 远端 reconcile 必须同时传 --execute --yes');
|
|
277
|
+
}
|
|
278
|
+
out = statusMulticaDeployment(PROJECT_START, o.workspace, {
|
|
279
|
+
execute: o.execute, yes: o.yes, operationId: o['operation-id'], timeoutMs,
|
|
280
|
+
cliVersion: PACKAGE_JSON.version,
|
|
281
|
+
});
|
|
282
|
+
}
|
|
283
|
+
else if (o['dry-run']) {
|
|
284
|
+
if (o.execute || o['operation-id'] || o['plan-id'] || o['no-wait'] ||
|
|
285
|
+
o.timeout || o['smoke-timeout']) {
|
|
286
|
+
fail('deploy --dry-run 不接受 execute/operation-id/plan-id/no-wait/timeout/smoke-timeout');
|
|
287
|
+
}
|
|
288
|
+
out = planMulticaDeployment(PROJECT_START, o.workspace, {
|
|
289
|
+
action: o.retire ? 'retire' : 'apply', cliVersion: PACKAGE_JSON.version,
|
|
290
|
+
});
|
|
291
|
+
}
|
|
292
|
+
else {
|
|
293
|
+
if (o.execute || o['operation-id'] || o.status || o.list || o['dry-run']) {
|
|
294
|
+
fail('deploy apply 不接受 execute/operation-id/status/list/dry-run');
|
|
295
|
+
}
|
|
296
|
+
if (o.retire && (o['no-wait'] || o['smoke-timeout'])) {
|
|
297
|
+
fail('deploy --retire 不接受 no-wait/smoke-timeout');
|
|
298
|
+
}
|
|
299
|
+
out = applyMulticaDeployment(PROJECT_START, o.workspace, {
|
|
300
|
+
yes: o.yes, planId: o['plan-id'], noWait: o['no-wait'],
|
|
301
|
+
timeoutMs, smokeTimeoutMs, cliVersion: PACKAGE_JSON.version,
|
|
302
|
+
}, o.retire ? 'retire' : 'apply');
|
|
303
|
+
}
|
|
304
|
+
if (o.json)
|
|
305
|
+
console.log(JSON.stringify(out, null, 2));
|
|
306
|
+
else
|
|
307
|
+
printMulticaDeployment(out);
|
|
308
|
+
if ('passed' in out && out.passed === false && out.status !== 'verifying')
|
|
309
|
+
process.exitCode = 2;
|
|
310
|
+
return;
|
|
311
|
+
}
|
|
312
|
+
if (cmd === 'promote') {
|
|
313
|
+
const platformForPromote = requireSupportedAgentPlatform('promote', PROJECT_START);
|
|
314
|
+
disclosePlatformSkill(platformForPromote, 'deploy');
|
|
315
|
+
const { values: o, positionals } = parseArgs({
|
|
316
|
+
args: argv.slice(1), allowPositionals: true,
|
|
317
|
+
options: {
|
|
318
|
+
policy: { type: 'string' }, route: { type: 'string' },
|
|
319
|
+
'dry-run': { type: 'boolean' }, yes: { type: 'boolean' }, json: { type: 'boolean' },
|
|
320
|
+
'plan-id': { type: 'string' }, status: { type: 'boolean' }, list: { type: 'boolean' },
|
|
321
|
+
'promotion-id': { type: 'string' }, 'no-wait': { type: 'boolean' },
|
|
322
|
+
timeout: { type: 'string' }, 'smoke-timeout': { type: 'string' },
|
|
323
|
+
},
|
|
324
|
+
});
|
|
325
|
+
if (positionals.length)
|
|
326
|
+
fail('promote 不接受位置参数');
|
|
327
|
+
const modes = [Boolean(o['dry-run']), Boolean(o.yes), Boolean(o.status), Boolean(o.list)]
|
|
328
|
+
.filter(Boolean).length;
|
|
329
|
+
if (modes !== 1)
|
|
330
|
+
fail('promote 必须且只能选择 --dry-run、--yes、--status 或 --list 之一');
|
|
331
|
+
let out;
|
|
332
|
+
if (o.list) {
|
|
333
|
+
if (o.policy || o.route || o['plan-id'] || o['promotion-id'] || o['no-wait'] ||
|
|
334
|
+
o.timeout || o['smoke-timeout'])
|
|
335
|
+
fail('promote --list 只接受 --json');
|
|
336
|
+
out = listPromotions(PROJECT_START);
|
|
337
|
+
}
|
|
338
|
+
else if (o.status) {
|
|
339
|
+
if (o.policy || o.route || o['plan-id'] || o['no-wait'] || o.timeout || o['smoke-timeout']) {
|
|
340
|
+
fail('promote --status 只接受 --promotion-id 和 --json');
|
|
341
|
+
}
|
|
342
|
+
out = statusPromotion(PROJECT_START, o['promotion-id'] || '');
|
|
343
|
+
}
|
|
344
|
+
else {
|
|
345
|
+
if (!o.policy || !o.route)
|
|
346
|
+
fail('promote dry-run/apply 必须传 --policy <file> --route <id>');
|
|
347
|
+
if (o['promotion-id'])
|
|
348
|
+
fail('promote dry-run/apply 不接受 --promotion-id');
|
|
349
|
+
if (o['dry-run']) {
|
|
350
|
+
if (o['plan-id'] || o['no-wait'] || o.timeout || o['smoke-timeout']) {
|
|
351
|
+
fail('promote --dry-run 不接受 plan-id/no-wait/timeout/smoke-timeout');
|
|
352
|
+
}
|
|
353
|
+
out = planPromotion(PROJECT_START, o.policy, o.route, { cliVersion: PACKAGE_JSON.version });
|
|
354
|
+
}
|
|
355
|
+
else {
|
|
356
|
+
out = applyPromotion(PROJECT_START, o.policy, o.route, {
|
|
357
|
+
yes: true, planId: o['plan-id'], noWait: o['no-wait'],
|
|
358
|
+
timeoutMs: parseOptionalTimeout(o.timeout, '--timeout'),
|
|
359
|
+
smokeTimeoutMs: parseOptionalTimeout(o['smoke-timeout'], '--smoke-timeout'),
|
|
360
|
+
cliVersion: PACKAGE_JSON.version,
|
|
361
|
+
});
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
if (o.json)
|
|
365
|
+
console.log(JSON.stringify(out, null, 2));
|
|
366
|
+
else
|
|
367
|
+
printPromotion(out);
|
|
368
|
+
if ('passed' in out && out.passed === false && out.status !== 'verifying' && out.status !== 'missing') {
|
|
369
|
+
process.exitCode = 2;
|
|
370
|
+
}
|
|
371
|
+
return;
|
|
372
|
+
}
|
|
373
|
+
if (cmd === 'observe') {
|
|
374
|
+
const platformForObserve = requireSupportedAgentPlatform('observe', PROJECT_START);
|
|
375
|
+
disclosePlatformSkill(platformForObserve, 'deploy');
|
|
376
|
+
const { values: o, positionals } = parseArgs({
|
|
377
|
+
args: argv.slice(1), allowPositionals: true,
|
|
378
|
+
options: {
|
|
379
|
+
'promotion-id': { type: 'string' }, input: { type: 'string' },
|
|
380
|
+
'dry-run': { type: 'boolean' }, yes: { type: 'boolean' }, json: { type: 'boolean' },
|
|
381
|
+
},
|
|
382
|
+
});
|
|
383
|
+
if (positionals.length)
|
|
384
|
+
fail('observe 不接受位置参数');
|
|
385
|
+
if (!o['promotion-id'] || !o.input) {
|
|
386
|
+
fail('observe 必须传 --promotion-id <id> --input <observation.json>');
|
|
387
|
+
}
|
|
388
|
+
if (Boolean(o['dry-run']) === Boolean(o.yes)) {
|
|
389
|
+
fail('observe 必须且只能选择 --dry-run 或 --yes');
|
|
390
|
+
}
|
|
391
|
+
const out = o['dry-run']
|
|
392
|
+
? planObservation(PROJECT_START, o['promotion-id'], o.input)
|
|
393
|
+
: applyObservation(PROJECT_START, o['promotion-id'], o.input, { yes: true });
|
|
394
|
+
if (o.json)
|
|
395
|
+
console.log(JSON.stringify(out, null, 2));
|
|
396
|
+
else
|
|
397
|
+
printPromotion(out);
|
|
398
|
+
return;
|
|
399
|
+
}
|
|
400
|
+
// ── Project / Development Workspace:W1 只读发现、状态与 Provider 诊断。──
|
|
401
|
+
if (cmd === 'info') {
|
|
402
|
+
const { values: o } = parseArgs({
|
|
403
|
+
args: argv.slice(1), options: { json: { type: 'boolean' } },
|
|
404
|
+
});
|
|
405
|
+
const out = inspectAgentProject(PROJECT_START, PACKAGE_JSON.version);
|
|
406
|
+
if (o.json)
|
|
407
|
+
console.log(JSON.stringify(out, null, 2));
|
|
408
|
+
else
|
|
409
|
+
printProjectInfo(out);
|
|
410
|
+
return;
|
|
411
|
+
}
|
|
412
|
+
if (cmd === 'workspace') {
|
|
413
|
+
const { values: o, positionals } = parseArgs({
|
|
414
|
+
args: argv.slice(2), allowPositionals: true,
|
|
415
|
+
options: {
|
|
416
|
+
json: { type: 'boolean' }, yes: { type: 'boolean' },
|
|
417
|
+
'dry-run': { type: 'boolean' }, execute: { type: 'boolean' },
|
|
418
|
+
'prompt-file': { type: 'string' }, suite: { type: 'string' },
|
|
419
|
+
cases: { type: 'string' }, lanes: { type: 'string' }, runs: { type: 'string' },
|
|
420
|
+
out: { type: 'string' }, timeout: { type: 'string' },
|
|
421
|
+
'previous-skill': { type: 'string' },
|
|
422
|
+
},
|
|
423
|
+
});
|
|
424
|
+
if (sub === 'list') {
|
|
425
|
+
rejectWorkspaceOptions(o, ['json'], 'workspace list');
|
|
426
|
+
if (positionals.length)
|
|
427
|
+
fail('workspace list 不接受 Workspace name');
|
|
428
|
+
const info = inspectAgentProject(PROJECT_START, PACKAGE_JSON.version);
|
|
429
|
+
const out = {
|
|
430
|
+
$schema: 'dingtalk-agent/workspace-list@1',
|
|
431
|
+
root: info.root,
|
|
432
|
+
currentWorkspace: info.currentWorkspace,
|
|
433
|
+
workspaces: info.workspaces,
|
|
434
|
+
sideEffect: false,
|
|
435
|
+
dingtalkSideEffect: false,
|
|
436
|
+
};
|
|
437
|
+
if (o.json)
|
|
438
|
+
console.log(JSON.stringify(out, null, 2));
|
|
439
|
+
else
|
|
440
|
+
printWorkspaceList(info);
|
|
441
|
+
return;
|
|
442
|
+
}
|
|
443
|
+
if (sub === 'show') {
|
|
444
|
+
rejectWorkspaceOptions(o, ['json'], 'workspace show');
|
|
445
|
+
if (positionals.length !== 1)
|
|
446
|
+
fail('workspace show 需要且只接受一个 Workspace name');
|
|
447
|
+
const workspace = showDevelopmentWorkspace(PROJECT_START, positionals[0], PACKAGE_JSON.version);
|
|
448
|
+
const out = {
|
|
449
|
+
$schema: 'dingtalk-agent/development-workspace@1',
|
|
450
|
+
...workspace,
|
|
451
|
+
sideEffect: false,
|
|
452
|
+
dingtalkSideEffect: false,
|
|
453
|
+
};
|
|
454
|
+
if (o.json)
|
|
455
|
+
console.log(JSON.stringify(out, null, 2));
|
|
456
|
+
else
|
|
457
|
+
printDevelopmentWorkspace(workspace);
|
|
458
|
+
return;
|
|
459
|
+
}
|
|
460
|
+
if (sub === 'doctor') {
|
|
461
|
+
rejectWorkspaceOptions(o, ['json'], 'workspace doctor');
|
|
462
|
+
if (positionals.length !== 1)
|
|
463
|
+
fail('workspace doctor 需要且只接受一个 Workspace name');
|
|
464
|
+
const out = doctorDevelopmentWorkspace(PROJECT_START, positionals[0], {
|
|
465
|
+
cliVersion: PACKAGE_JSON.version,
|
|
466
|
+
});
|
|
467
|
+
if (o.json)
|
|
468
|
+
console.log(JSON.stringify(out, null, 2));
|
|
469
|
+
else
|
|
470
|
+
printDevelopmentWorkspaceDoctor(out);
|
|
471
|
+
if (!out.ready)
|
|
472
|
+
process.exitCode = 2;
|
|
473
|
+
return;
|
|
474
|
+
}
|
|
475
|
+
if (sub === 'plan') {
|
|
476
|
+
rejectWorkspaceOptions(o, ['json', 'dry-run'], 'workspace plan');
|
|
477
|
+
if (positionals.length !== 1)
|
|
478
|
+
fail('workspace plan 需要且只接受一个 Multica Workspace name');
|
|
479
|
+
const out = planMulticaWorkspace(PROJECT_START, positionals[0], {
|
|
480
|
+
cliVersion: PACKAGE_JSON.version,
|
|
481
|
+
});
|
|
482
|
+
if (o.json)
|
|
483
|
+
console.log(JSON.stringify(out, null, 2));
|
|
484
|
+
else
|
|
485
|
+
printMulticaWorkspaceOperation(out);
|
|
486
|
+
if (out.blocking.length)
|
|
487
|
+
process.exitCode = 2;
|
|
488
|
+
return;
|
|
489
|
+
}
|
|
490
|
+
if (sub === 'inspect') {
|
|
491
|
+
rejectWorkspaceOptions(o, ['json', 'execute', 'yes', 'out', 'timeout'], 'workspace inspect');
|
|
492
|
+
if (positionals.length !== 1)
|
|
493
|
+
fail('workspace inspect 需要且只接受一个 Multica Workspace name');
|
|
494
|
+
if (Boolean(o.execute) !== Boolean(o.yes)) {
|
|
495
|
+
fail('workspace inspect 读取远端时必须同时传 --execute --yes');
|
|
496
|
+
}
|
|
497
|
+
const timeoutMs = o.timeout === undefined ? undefined : Number(o.timeout);
|
|
498
|
+
const out = inspectMulticaWorkspace(PROJECT_START, positionals[0], {
|
|
499
|
+
execute: o.execute, yes: o.yes, out: o.out, timeoutMs,
|
|
500
|
+
cliVersion: PACKAGE_JSON.version,
|
|
501
|
+
});
|
|
502
|
+
if (o.json)
|
|
503
|
+
console.log(JSON.stringify(out, null, 2));
|
|
504
|
+
else
|
|
505
|
+
printMulticaWorkspaceOperation(out);
|
|
506
|
+
if (o.execute && 'passed' in out && !out.passed)
|
|
507
|
+
process.exitCode = 2;
|
|
508
|
+
return;
|
|
509
|
+
}
|
|
510
|
+
if (sub === 'remote-list') {
|
|
511
|
+
rejectWorkspaceOptions(o, ['json', 'execute', 'yes', 'timeout'], 'workspace remote-list');
|
|
512
|
+
if (positionals.length !== 1)
|
|
513
|
+
fail('workspace remote-list 需要且只接受一个 Multica Workspace name');
|
|
514
|
+
if (Boolean(o.execute) !== Boolean(o.yes)) {
|
|
515
|
+
fail('workspace remote-list 读取远端时必须同时传 --execute --yes');
|
|
516
|
+
}
|
|
517
|
+
const timeoutMs = o.timeout === undefined ? undefined : Number(o.timeout);
|
|
518
|
+
const out = listMulticaWorkspaceResources(PROJECT_START, positionals[0], {
|
|
519
|
+
execute: o.execute, yes: o.yes, timeoutMs, cliVersion: PACKAGE_JSON.version,
|
|
520
|
+
});
|
|
521
|
+
if (o.json)
|
|
522
|
+
console.log(JSON.stringify(out, null, 2));
|
|
523
|
+
else
|
|
524
|
+
printMulticaWorkspaceOperation(out);
|
|
525
|
+
if (o.execute && 'passed' in out && !out.passed)
|
|
526
|
+
process.exitCode = 2;
|
|
527
|
+
return;
|
|
528
|
+
}
|
|
529
|
+
if (sub === 'status') {
|
|
530
|
+
rejectWorkspaceOptions(o, ['json'], 'workspace status');
|
|
531
|
+
if (positionals.length !== 1)
|
|
532
|
+
fail('workspace status 需要且只接受一个 Multica Workspace name');
|
|
533
|
+
const out = statusMulticaWorkspace(PROJECT_START, positionals[0], PACKAGE_JSON.version);
|
|
534
|
+
if (o.json)
|
|
535
|
+
console.log(JSON.stringify(out, null, 2));
|
|
536
|
+
else
|
|
537
|
+
printMulticaWorkspaceOperation(out);
|
|
538
|
+
if (!out.readyForApply)
|
|
539
|
+
process.exitCode = 2;
|
|
540
|
+
return;
|
|
541
|
+
}
|
|
542
|
+
if (sub === 'create') {
|
|
543
|
+
rejectWorkspaceOptions(o, ['json', 'yes', 'dry-run'], 'workspace create');
|
|
544
|
+
if (positionals.length !== 1)
|
|
545
|
+
fail('workspace create 需要且只接受一个 Workspace name');
|
|
546
|
+
if (o.yes && o['dry-run'])
|
|
547
|
+
fail('workspace create 的 --dry-run 与 --yes 不能同时使用');
|
|
548
|
+
const out = o.yes
|
|
549
|
+
? applyOpenCodeWorkspace(PROJECT_START, positionals[0], {
|
|
550
|
+
yes: true, cliVersion: PACKAGE_JSON.version,
|
|
551
|
+
})
|
|
552
|
+
: planOpenCodeWorkspace(PROJECT_START, positionals[0], PACKAGE_JSON.version);
|
|
553
|
+
if (o.json)
|
|
554
|
+
console.log(JSON.stringify(out, null, 2));
|
|
555
|
+
else
|
|
556
|
+
printOpenCodeWorkspaceOperation(out);
|
|
557
|
+
return;
|
|
558
|
+
}
|
|
559
|
+
if (sub === 'use') {
|
|
560
|
+
rejectWorkspaceOptions(o, ['json'], 'workspace use');
|
|
561
|
+
if (positionals.length !== 1)
|
|
562
|
+
fail('workspace use 需要且只接受一个 Workspace name');
|
|
563
|
+
const out = useOpenCodeWorkspace(PROJECT_START, positionals[0], PACKAGE_JSON.version);
|
|
564
|
+
if (o.json)
|
|
565
|
+
console.log(JSON.stringify(out, null, 2));
|
|
566
|
+
else
|
|
567
|
+
console.log(`✅ current workspace: ${out.previous || '-'} → ${out.current}`);
|
|
568
|
+
return;
|
|
569
|
+
}
|
|
570
|
+
if (sub === 'run') {
|
|
571
|
+
rejectWorkspaceOptions(o, ['json', 'yes', 'execute', 'prompt-file', 'out', 'timeout'], 'workspace run');
|
|
572
|
+
if (positionals.length !== 1 || !o['prompt-file']) {
|
|
573
|
+
fail('workspace run 需要一个 Workspace name 和 --prompt-file <file>');
|
|
574
|
+
}
|
|
575
|
+
const timeoutMs = o.timeout === undefined ? undefined : Number(o.timeout);
|
|
576
|
+
const prompt = readProjectText(PROJECT_START, o['prompt-file'], 'workspace run prompt');
|
|
577
|
+
const out = runOpenCodeWorkspace(PROJECT_START, positionals[0], prompt, {
|
|
578
|
+
execute: o.execute, yes: o.yes, timeoutMs, out: o.out,
|
|
579
|
+
});
|
|
580
|
+
if (o.json)
|
|
581
|
+
console.log(JSON.stringify(out, null, 2));
|
|
582
|
+
else if (out.$schema === 'dingtalk-agent/opencode-workspace-run-plan@1') {
|
|
583
|
+
console.log(`DRY-RUN workspace=${out.workspace} model=${out.model} prompt=${out.promptHash}`);
|
|
584
|
+
}
|
|
585
|
+
else {
|
|
586
|
+
console.log(`${out.passed ? '✅' : '❌'} workspace run ${out.runId}`);
|
|
587
|
+
if (out.execution?.answer)
|
|
588
|
+
console.log(out.execution.answer);
|
|
589
|
+
if (out.evidencePath)
|
|
590
|
+
console.log(`evidence=${out.evidencePath}`);
|
|
591
|
+
}
|
|
592
|
+
if (o.execute && !out.passed)
|
|
593
|
+
process.exitCode = 2;
|
|
594
|
+
return;
|
|
595
|
+
}
|
|
596
|
+
if (sub === 'eval') {
|
|
597
|
+
rejectWorkspaceOptions(o, ['json', 'yes', 'execute', 'suite', 'cases', 'lanes', 'runs', 'out', 'previous-skill'], 'workspace eval');
|
|
598
|
+
if (positionals.length !== 1 || !o.suite) {
|
|
599
|
+
fail('workspace eval 需要一个 Workspace name 和 --suite <file>');
|
|
600
|
+
}
|
|
601
|
+
const lanes = String(o.lanes || '').split(',').map((item) => item.trim()).filter(Boolean);
|
|
602
|
+
const invalid = lanes.filter((item) => !['stateless', 'stateful', 'role'].includes(item));
|
|
603
|
+
if (invalid.length)
|
|
604
|
+
fail(`workspace eval lanes 非法: ${invalid.join(',')}`);
|
|
605
|
+
const cases = String(o.cases || '').split(',').map((item) => item.trim()).filter(Boolean);
|
|
606
|
+
const runs = o.runs === undefined ? undefined : Number(o.runs);
|
|
607
|
+
const out = evalOpenCodeWorkspace(PROJECT_START, positionals[0], o.suite, {
|
|
608
|
+
lanes: lanes, caseIds: cases, runs, out: o.out,
|
|
609
|
+
previousSkill: o['previous-skill'], execute: o.execute, yes: o.yes,
|
|
610
|
+
});
|
|
611
|
+
if (o.json)
|
|
612
|
+
console.log(JSON.stringify(out, null, 2));
|
|
613
|
+
else
|
|
614
|
+
printLab(out.report || out);
|
|
615
|
+
if (o.execute && !out.passed)
|
|
616
|
+
process.exitCode = 2;
|
|
617
|
+
return;
|
|
618
|
+
}
|
|
619
|
+
fail(`不认识的 workspace 子命令: ${sub || '(缺失)'}`, 1, `可用命令: dta workspace list | show | doctor | plan | inspect | remote-list | status | create | use | run | eval${suggest(sub || '', ['list', 'show', 'doctor', 'plan', 'inspect', 'remote-list', 'status', 'create', 'use', 'run', 'eval'], 'dta workspace')}`);
|
|
620
|
+
}
|
|
110
621
|
// ── setup / upgrade / doctor:机器级安装与环境闭环。──
|
|
111
622
|
if (cmd === 'setup') {
|
|
112
623
|
const { values: o } = parseArgs({
|
|
@@ -167,47 +678,143 @@ async function main() {
|
|
|
167
678
|
}
|
|
168
679
|
// ── skill:唯一一次性的主入口;完全不依赖 Workspace。──
|
|
169
680
|
if (cmd === 'skill') {
|
|
170
|
-
const { values: o } = parseArgs({
|
|
681
|
+
const { values: o, positionals } = parseArgs({
|
|
171
682
|
args: argv.slice(2),
|
|
683
|
+
allowPositionals: true,
|
|
172
684
|
options: {
|
|
173
|
-
'dry-run': { type: 'boolean' }, json: { type: 'boolean' },
|
|
685
|
+
name: { type: 'string' }, 'dry-run': { type: 'boolean' }, json: { type: 'boolean' },
|
|
686
|
+
'allow-downgrade': { type: 'boolean' },
|
|
174
687
|
},
|
|
175
688
|
});
|
|
176
|
-
|
|
689
|
+
if (positionals.length > 1)
|
|
690
|
+
fail('skill 最多接受一个 Skill name');
|
|
691
|
+
const name = o.name || positionals[0];
|
|
692
|
+
const dryRun = Boolean(o['dry-run']);
|
|
693
|
+
const allowDowngrade = Boolean(o['allow-downgrade']);
|
|
177
694
|
let out;
|
|
178
|
-
if (sub === 'install')
|
|
179
|
-
out =
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
else
|
|
695
|
+
if (sub === 'install') {
|
|
696
|
+
out = name
|
|
697
|
+
? installGlobalSkill(PACKAGE_ROOT, { dryRun, name, allowDowngrade })
|
|
698
|
+
: installBundledSkills(PACKAGE_ROOT, { dryRun, allowDowngrade });
|
|
699
|
+
}
|
|
700
|
+
else if (sub === 'status') {
|
|
701
|
+
out = name ? skillStatus(PACKAGE_ROOT, { dryRun, name }) : skillSuiteStatus(PACKAGE_ROOT, { dryRun });
|
|
702
|
+
}
|
|
703
|
+
else if (sub === 'upgrade') {
|
|
704
|
+
out = name
|
|
705
|
+
? upgradeGlobalSkill(PACKAGE_ROOT, { dryRun, name, allowDowngrade })
|
|
706
|
+
: upgradeBundledSkills(PACKAGE_ROOT, { dryRun, allowDowngrade });
|
|
707
|
+
}
|
|
708
|
+
else if (sub === 'uninstall') {
|
|
709
|
+
out = name
|
|
710
|
+
? uninstallGlobalSkill(PACKAGE_ROOT, { dryRun, name })
|
|
711
|
+
: uninstallBundledSkills(PACKAGE_ROOT, { dryRun });
|
|
712
|
+
}
|
|
713
|
+
else {
|
|
187
714
|
fail(`不认识的 skill 子命令: ${sub || '(缺失)'}`, 1, `可用命令: dta skill install | status | upgrade | uninstall${suggest(sub || '', ['install', 'status', 'upgrade', 'uninstall'], 'dta skill')}`);
|
|
715
|
+
}
|
|
188
716
|
if (o.json)
|
|
189
717
|
console.log(JSON.stringify(out, null, 2));
|
|
718
|
+
else if ('skills' in out)
|
|
719
|
+
for (const item of out.skills)
|
|
720
|
+
printSkillStatus(item, sub, dryRun);
|
|
190
721
|
else
|
|
191
|
-
printSkillStatus(out, sub,
|
|
722
|
+
printSkillStatus(out, sub, dryRun);
|
|
192
723
|
return;
|
|
193
724
|
}
|
|
725
|
+
// ── agent-platform:工作区归属的 managed agent platform;平台工具包按选择惰性安装。──
|
|
726
|
+
if (cmd === 'agent-platform') {
|
|
727
|
+
const { values: o, positionals } = parseArgs({
|
|
728
|
+
args: argv.slice(2),
|
|
729
|
+
allowPositionals: true,
|
|
730
|
+
options: { json: { type: 'boolean' }, 'no-install': { type: 'boolean' } },
|
|
731
|
+
});
|
|
732
|
+
if (sub === 'list') {
|
|
733
|
+
if (positionals.length)
|
|
734
|
+
fail('agent-platform list 不接受位置参数');
|
|
735
|
+
const out = { $schema: 'dingtalk-agent/agent-platform-list@1', platforms: MANAGED_AGENT_PLATFORMS };
|
|
736
|
+
if (o.json)
|
|
737
|
+
console.log(JSON.stringify(out, null, 2));
|
|
738
|
+
else
|
|
739
|
+
for (const platform of MANAGED_AGENT_PLATFORMS)
|
|
740
|
+
printAgentPlatform(platform);
|
|
741
|
+
return;
|
|
742
|
+
}
|
|
743
|
+
if (sub === 'show') {
|
|
744
|
+
if (positionals.length)
|
|
745
|
+
fail('agent-platform show 不接受位置参数');
|
|
746
|
+
const out = resolveAgentPlatform(PROJECT_START);
|
|
747
|
+
const readiness = out.definition ? agentPlatformReadiness(out.definition.name, process.env, undefined, PROJECT_START) : [];
|
|
748
|
+
const targets = out.definition?.name === 'multica-dingtalk' ? multicaTargets() : [];
|
|
749
|
+
const endpoint = out.definition ? resolveEndpoint(out.definition.name, PROJECT_START) : null;
|
|
750
|
+
const doc = out.definition ? platformDocPath(PACKAGE_ROOT, out.definition.name) : null;
|
|
751
|
+
if (o.json)
|
|
752
|
+
console.log(JSON.stringify({ ...out, endpoint, readiness, targets, doc }, null, 2));
|
|
753
|
+
else {
|
|
754
|
+
printAgentPlatformResolution(out);
|
|
755
|
+
printEndpoint(endpoint);
|
|
756
|
+
printAgentPlatformReadiness(readiness);
|
|
757
|
+
printMulticaTargets(targets);
|
|
758
|
+
printPlatformDoc(out.definition?.name);
|
|
759
|
+
}
|
|
760
|
+
return;
|
|
761
|
+
}
|
|
762
|
+
if (sub === 'use') {
|
|
763
|
+
if (positionals.length !== 1)
|
|
764
|
+
fail('agent-platform use 需要且只接受一个 platform name');
|
|
765
|
+
const out = useAgentPlatform(PROJECT_START, positionals[0], {
|
|
766
|
+
packageRoot: PACKAGE_ROOT, installSkills: !o['no-install'],
|
|
767
|
+
});
|
|
768
|
+
const readiness = out.definition ? agentPlatformReadiness(out.definition.name, process.env, undefined, PROJECT_START) : [];
|
|
769
|
+
const targets = out.definition?.name === 'multica-dingtalk' ? multicaTargets() : [];
|
|
770
|
+
const endpoint = out.definition ? resolveEndpoint(out.definition.name, PROJECT_START) : null;
|
|
771
|
+
const doc = out.definition ? platformDocPath(PACKAGE_ROOT, out.definition.name) : null;
|
|
772
|
+
if (o.json)
|
|
773
|
+
console.log(JSON.stringify({ ...out, endpoint, readiness, targets, doc }, null, 2));
|
|
774
|
+
else {
|
|
775
|
+
console.log(`✅ 工作区已归属 ${out.definition?.label}(写入 ${out.written})`);
|
|
776
|
+
for (const install of out.skillInstalls)
|
|
777
|
+
printSkillStatus(install, 'install', false);
|
|
778
|
+
if (!out.skillInstalls.length) {
|
|
779
|
+
console.log(out.definition?.skills.length
|
|
780
|
+
? ` 已跳过平台技能包安装(--no-install):${out.definition.skills.map((item) => item.name).join(', ')}`
|
|
781
|
+
: ' 该平台无需额外技能包。');
|
|
782
|
+
}
|
|
783
|
+
printEndpoint(endpoint);
|
|
784
|
+
printAgentPlatformReadiness(readiness);
|
|
785
|
+
printMulticaTargets(targets);
|
|
786
|
+
printPlatformDoc(out.definition?.name);
|
|
787
|
+
}
|
|
788
|
+
return;
|
|
789
|
+
}
|
|
790
|
+
fail(`不认识的 agent-platform 子命令: ${sub || '(缺失)'}`, 1, `可用命令: dta agent-platform list | show | use <platform>${suggest(sub || '', ['list', 'show', 'use'], 'dta agent-platform')}`);
|
|
791
|
+
}
|
|
194
792
|
// ── bootstrap:当前 Agent Session 按需发现/拉取语义上下文。──
|
|
195
793
|
if (cmd === 'bootstrap') {
|
|
196
794
|
const { values: o } = parseArgs({
|
|
197
795
|
args: argv.slice(1),
|
|
198
796
|
options: {
|
|
199
|
-
|
|
200
|
-
|
|
797
|
+
agent: { type: 'string' }, storage: { type: 'string' },
|
|
798
|
+
memory: { type: 'string' }, knowledge: { type: 'string' },
|
|
799
|
+
skills: { type: 'string' }, artifacts: { type: 'string' },
|
|
800
|
+
'state-dir': { type: 'string' }, profile: { type: 'string' },
|
|
801
|
+
'expected-user-id': { type: 'string' }, bindings: { type: 'string' },
|
|
802
|
+
json: { type: 'boolean' },
|
|
201
803
|
},
|
|
202
804
|
});
|
|
805
|
+
const loaded = loadConventionalBindings(o.bindings);
|
|
203
806
|
const out = bootstrap(ROOT, {
|
|
204
|
-
|
|
807
|
+
agent: o.agent, storage: o.storage,
|
|
808
|
+
memory: o.memory, knowledge: o.knowledge, skills: o.skills,
|
|
809
|
+
artifacts: o.artifacts, stateDir: o['state-dir'], profile: o.profile,
|
|
810
|
+
expectedUserId: o['expected-user-id'], context: loaded?.context,
|
|
205
811
|
});
|
|
206
812
|
if (o.json)
|
|
207
813
|
console.log(JSON.stringify(out, null, 2));
|
|
208
814
|
else {
|
|
209
815
|
console.log(`✅ ${out.mode === 'workspace' ? '已装载 Workspace' : '直接会话模式'}`);
|
|
210
816
|
console.log(` scope=${out.scopeId} initialized=${out.initialized}`);
|
|
817
|
+
console.log(` agent=${out.definition.id} definition=${out.definition.status}`);
|
|
211
818
|
if (!out.mounts.length)
|
|
212
819
|
console.log(' 没有发现持久上下文;这不是错误,也不需要自动 init。');
|
|
213
820
|
for (const mount of out.mounts)
|
|
@@ -216,6 +823,189 @@ async function main() {
|
|
|
216
823
|
}
|
|
217
824
|
return;
|
|
218
825
|
}
|
|
826
|
+
// ── agent audit:本地定义、Host exposure、真加载与存储证据的稳定验收面。──
|
|
827
|
+
if (cmd === 'agent') {
|
|
828
|
+
if (!['audit', 'enhance'].includes(sub || ''))
|
|
829
|
+
fail(`不认识的 agent 子命令: ${sub || '(缺失)'}`, 1, `可用命令: dta agent audit / dta agent enhance${suggest(sub || '', ['audit', 'enhance'], 'dta agent')}`);
|
|
830
|
+
if (sub === 'enhance') {
|
|
831
|
+
const { values: o } = parseArgs({
|
|
832
|
+
args: argv.slice(2),
|
|
833
|
+
options: {
|
|
834
|
+
bindings: { type: 'string' }, 'project-name': { type: 'string' },
|
|
835
|
+
'role-skill': { type: 'string' }, model: { type: 'string' },
|
|
836
|
+
memory: { type: 'string' }, knowledge: { type: 'string' },
|
|
837
|
+
artifacts: { type: 'string' }, 'state-dir': { type: 'string' },
|
|
838
|
+
profile: { type: 'string' }, 'expected-user-id': { type: 'string' },
|
|
839
|
+
'plan-id': { type: 'string' }, 'dry-run': { type: 'boolean' },
|
|
840
|
+
yes: { type: 'boolean' }, json: { type: 'boolean' },
|
|
841
|
+
},
|
|
842
|
+
});
|
|
843
|
+
if (o.yes && o['dry-run'])
|
|
844
|
+
fail('agent enhance 的 --dry-run 与 --yes 不能同时使用');
|
|
845
|
+
if (!o.yes && o['plan-id'])
|
|
846
|
+
fail('agent enhance plan 不接受 --plan-id;它由 dry-run 生成');
|
|
847
|
+
const options = {
|
|
848
|
+
bindings: o.bindings, projectName: o['project-name'],
|
|
849
|
+
roleSkills: o['role-skill']?.split(','), model: o.model,
|
|
850
|
+
memory: o.memory, knowledge: o.knowledge, artifacts: o.artifacts,
|
|
851
|
+
stateDir: o['state-dir'], profile: o.profile,
|
|
852
|
+
expectedUserId: o['expected-user-id'], cliVersion: PACKAGE_JSON.version,
|
|
853
|
+
planId: o['plan-id'], yes: o.yes,
|
|
854
|
+
};
|
|
855
|
+
const out = o.yes
|
|
856
|
+
? applyAgentEnhancement(ROOT, options)
|
|
857
|
+
: planAgentEnhancement(ROOT, options);
|
|
858
|
+
if (o.json)
|
|
859
|
+
console.log(JSON.stringify(out, null, 2));
|
|
860
|
+
else
|
|
861
|
+
printAgentEnhance(out);
|
|
862
|
+
if ('$schema' in out && out.$schema === 'dingtalk-agent/agent-enhancement-plan@1' && !out.ready) {
|
|
863
|
+
process.exitCode = 2;
|
|
864
|
+
}
|
|
865
|
+
return;
|
|
866
|
+
}
|
|
867
|
+
const { values: o } = parseArgs({
|
|
868
|
+
args: argv.slice(2),
|
|
869
|
+
options: {
|
|
870
|
+
bindings: { type: 'string' }, agent: { type: 'string' }, storage: { type: 'string' },
|
|
871
|
+
memory: { type: 'string' }, knowledge: { type: 'string' },
|
|
872
|
+
skills: { type: 'string' }, artifacts: { type: 'string' },
|
|
873
|
+
'state-dir': { type: 'string' }, profile: { type: 'string' },
|
|
874
|
+
'expected-user-id': { type: 'string' }, 'require-skill': { type: 'string' },
|
|
875
|
+
'verify-load': { type: 'boolean' }, yes: { type: 'boolean' },
|
|
876
|
+
model: { type: 'string' }, out: { type: 'string' },
|
|
877
|
+
'load-report': { type: 'string' }, 'remote-report': { type: 'string' },
|
|
878
|
+
json: { type: 'boolean' },
|
|
879
|
+
},
|
|
880
|
+
});
|
|
881
|
+
const loaded = loadConventionalBindings(o.bindings);
|
|
882
|
+
const out = auditAgent(ROOT, {
|
|
883
|
+
bootstrap: {
|
|
884
|
+
agent: o.agent, storage: o.storage,
|
|
885
|
+
memory: o.memory, knowledge: o.knowledge, skills: o.skills,
|
|
886
|
+
artifacts: o.artifacts, stateDir: o['state-dir'], profile: o.profile,
|
|
887
|
+
expectedUserId: o['expected-user-id'], context: loaded?.context,
|
|
888
|
+
},
|
|
889
|
+
bindings: loaded ? { path: loaded.path, hash: loaded.hash } : undefined,
|
|
890
|
+
requiredSkills: o['require-skill']?.split(','),
|
|
891
|
+
verifyLoad: o['verify-load'], yes: o.yes, model: o.model, out: o.out,
|
|
892
|
+
loadReport: o['load-report'], remoteReport: o['remote-report'],
|
|
893
|
+
});
|
|
894
|
+
if (o.json)
|
|
895
|
+
console.log(JSON.stringify(out, null, 2));
|
|
896
|
+
else
|
|
897
|
+
printAgentAudit(out);
|
|
898
|
+
if (!out.ready)
|
|
899
|
+
process.exitCode = 2;
|
|
900
|
+
return;
|
|
901
|
+
}
|
|
902
|
+
// ── lab:测试控制面;默认无副作用,Live 必须 manifest + --live --yes。──
|
|
903
|
+
if (cmd === 'lab') {
|
|
904
|
+
const { values: o } = parseArgs({
|
|
905
|
+
args: argv.slice(2),
|
|
906
|
+
options: {
|
|
907
|
+
manifest: { type: 'string' }, evidence: { type: 'string' },
|
|
908
|
+
'event-file': { type: 'string' }, 'case-id': { type: 'string' },
|
|
909
|
+
pool: { type: 'string' }, suite: { type: 'string' }, lanes: { type: 'string' },
|
|
910
|
+
cases: { type: 'string' },
|
|
911
|
+
engine: { type: 'string' }, workspace: { type: 'string' }, model: { type: 'string' },
|
|
912
|
+
runs: { type: 'string' }, out: { type: 'string' },
|
|
913
|
+
'previous-skill': { type: 'string' }, execute: { type: 'boolean' },
|
|
914
|
+
reply: { type: 'string' }, input: { type: 'string' },
|
|
915
|
+
live: { type: 'boolean' }, yes: { type: 'boolean' }, json: { type: 'boolean' },
|
|
916
|
+
},
|
|
917
|
+
});
|
|
918
|
+
let out;
|
|
919
|
+
if (sub === 'doctor') {
|
|
920
|
+
if (!o.manifest)
|
|
921
|
+
fail('lab doctor 需要 --manifest <file>');
|
|
922
|
+
out = doctorLab(ROOT, o.manifest);
|
|
923
|
+
if (!out.ready)
|
|
924
|
+
process.exitCode = 2;
|
|
925
|
+
}
|
|
926
|
+
else if (sub === 'run') {
|
|
927
|
+
if (!o.manifest || !o['case-id'])
|
|
928
|
+
fail('lab run 需要 --manifest 和 --case-id');
|
|
929
|
+
const rawEvent = o['event-file']
|
|
930
|
+
? readEventFile(o['event-file']) : null;
|
|
931
|
+
out = runLab(ROOT, cfgmod.must(ROOT), o.manifest, rawEvent, {
|
|
932
|
+
caseId: o['case-id'], replyText: o.reply, inputText: o.input,
|
|
933
|
+
live: o.live, yes: o.yes,
|
|
934
|
+
});
|
|
935
|
+
}
|
|
936
|
+
else if (sub === 'verify') {
|
|
937
|
+
if (!o.evidence)
|
|
938
|
+
fail('lab verify 需要 --evidence <run-dir>');
|
|
939
|
+
out = verifyLab(ROOT, o.evidence);
|
|
940
|
+
if (!out.passed)
|
|
941
|
+
process.exitCode = 2;
|
|
942
|
+
}
|
|
943
|
+
else if (sub === 'teardown') {
|
|
944
|
+
if (!o.manifest || !o.evidence)
|
|
945
|
+
fail('lab teardown 需要 --manifest 和 --evidence');
|
|
946
|
+
out = teardownLab(ROOT, o.manifest, o.evidence, { live: o.live, yes: o.yes });
|
|
947
|
+
}
|
|
948
|
+
else if (sub === 'eval') {
|
|
949
|
+
if (!o.suite)
|
|
950
|
+
fail('lab eval 需要 --suite');
|
|
951
|
+
const lanes = String(o.lanes || '').split(',').map((item) => item.trim()).filter(Boolean);
|
|
952
|
+
const invalid = lanes.filter((item) => !['stateless', 'stateful', 'role'].includes(item));
|
|
953
|
+
if (invalid.length)
|
|
954
|
+
fail(`lab eval lanes 非法: ${invalid.join(',')}`);
|
|
955
|
+
const cases = String(o.cases || '').split(',').map((item) => item.trim()).filter(Boolean);
|
|
956
|
+
const engine = o.engine || 'robot';
|
|
957
|
+
if (engine === 'opencode') {
|
|
958
|
+
if (!o.workspace)
|
|
959
|
+
fail('OpenCode eval 需要 --workspace <agent-dir>');
|
|
960
|
+
const runs = o.runs === undefined ? undefined : Number(o.runs);
|
|
961
|
+
out = runOpenCodeEvaluation(ROOT, o.workspace, o.suite, {
|
|
962
|
+
lanes: lanes, model: o.model, runs,
|
|
963
|
+
caseIds: cases, previousSkill: o['previous-skill'],
|
|
964
|
+
execute: o.execute, yes: o.yes, out: o.out,
|
|
965
|
+
});
|
|
966
|
+
if (o.execute && !out.passed)
|
|
967
|
+
process.exitCode = 2;
|
|
968
|
+
}
|
|
969
|
+
else if (engine === 'storage') {
|
|
970
|
+
if (!o.workspace)
|
|
971
|
+
fail('Remote State eval 需要 --workspace <agent-dir>');
|
|
972
|
+
out = runStorageEvaluation(ROOT, o.workspace, o.suite, {
|
|
973
|
+
model: o.model, execute: o.execute, live: o.live, yes: o.yes, out: o.out,
|
|
974
|
+
});
|
|
975
|
+
if (o.execute && !out.passed)
|
|
976
|
+
process.exitCode = 2;
|
|
977
|
+
}
|
|
978
|
+
else if (engine === 'personal-event') {
|
|
979
|
+
if (!o.workspace)
|
|
980
|
+
fail('Personal Event eval 需要 --workspace <agent-dir>');
|
|
981
|
+
out = runPersonalEventEvaluation(ROOT, o.workspace, o.suite, {
|
|
982
|
+
execute: o.execute, live: o.live, yes: o.yes, out: o.out,
|
|
983
|
+
});
|
|
984
|
+
if (o.execute && !out.passed)
|
|
985
|
+
process.exitCode = 2;
|
|
986
|
+
}
|
|
987
|
+
else if (engine === 'robot') {
|
|
988
|
+
if (!o.pool)
|
|
989
|
+
fail('Robot eval 需要 --pool <pool.local.json>');
|
|
990
|
+
out = runRobotEvaluation(ROOT, o.pool, o.suite, {
|
|
991
|
+
lanes: lanes, live: o.live, yes: o.yes,
|
|
992
|
+
});
|
|
993
|
+
if (o.live && !out.passed)
|
|
994
|
+
process.exitCode = 2;
|
|
995
|
+
}
|
|
996
|
+
else {
|
|
997
|
+
fail(`lab eval engine 非法: ${engine};只支持 robot、opencode、storage 或 personal-event`);
|
|
998
|
+
}
|
|
999
|
+
}
|
|
1000
|
+
else {
|
|
1001
|
+
fail(`不认识的 lab 子命令: ${sub || '(缺失)'}`, 1, '可用命令: dta lab doctor | run | verify | teardown | eval;详见 dta help lab。');
|
|
1002
|
+
}
|
|
1003
|
+
if (o.json)
|
|
1004
|
+
console.log(JSON.stringify(out, null, 2));
|
|
1005
|
+
else
|
|
1006
|
+
printLab(out);
|
|
1007
|
+
return;
|
|
1008
|
+
}
|
|
219
1009
|
// ── init ──
|
|
220
1010
|
if (cmd === 'init') {
|
|
221
1011
|
const { values: o } = parseArgs({
|
|
@@ -240,6 +1030,7 @@ async function main() {
|
|
|
240
1030
|
options: {
|
|
241
1031
|
'event-file': { type: 'string' }, field: { type: 'string' },
|
|
242
1032
|
'session-key': { type: 'string' }, 'context-id': { type: 'string' },
|
|
1033
|
+
'perception-file': { type: 'string' },
|
|
243
1034
|
json: { type: 'boolean' },
|
|
244
1035
|
},
|
|
245
1036
|
});
|
|
@@ -248,6 +1039,7 @@ async function main() {
|
|
|
248
1039
|
fail('prepare 需要 --event-file <file|->');
|
|
249
1040
|
const out = prepareSession(ROOT, cfg, readEventFile(file), {
|
|
250
1041
|
fieldId: o.field, sessionKey: o['session-key'], contextId: o['context-id'],
|
|
1042
|
+
perception: o['perception-file'] ? readEventFile(o['perception-file']) : undefined,
|
|
251
1043
|
});
|
|
252
1044
|
printDispatch(out, o.json);
|
|
253
1045
|
return;
|
|
@@ -261,12 +1053,14 @@ async function main() {
|
|
|
261
1053
|
stdin: { type: 'boolean' }, 'event-file': { type: 'string' },
|
|
262
1054
|
field: { type: 'string' }, 'session-key': { type: 'string' },
|
|
263
1055
|
'context-id': { type: 'string' },
|
|
1056
|
+
'perception-file': { type: 'string' },
|
|
264
1057
|
heartbeat: { type: 'boolean' }, 'heartbeat-key': { type: 'string' },
|
|
265
1058
|
'heartbeat-event-id': { type: 'string' },
|
|
266
1059
|
},
|
|
267
1060
|
});
|
|
268
1061
|
const options = {
|
|
269
1062
|
fieldId: o.field, sessionKey: o['session-key'], contextId: o['context-id'],
|
|
1063
|
+
perception: o['perception-file'] ? readEventFile(o['perception-file']) : undefined,
|
|
270
1064
|
};
|
|
271
1065
|
const modes = [Boolean(o.stdin), Boolean(o.heartbeat), Boolean(o['event-file'] || positionals[0])];
|
|
272
1066
|
if (modes.filter(Boolean).length !== 1) {
|
|
@@ -378,6 +1172,133 @@ async function main() {
|
|
|
378
1172
|
}
|
|
379
1173
|
fail('dispatch 的子命令: pending / ack');
|
|
380
1174
|
}
|
|
1175
|
+
// ── task:Session 语义 checkpoint;revision CAS,不承担 Wait/锁/Receipt。──
|
|
1176
|
+
if (cmd === 'task') {
|
|
1177
|
+
const cfg = cfgmod.must(ROOT);
|
|
1178
|
+
const { values: o } = parseArgs({
|
|
1179
|
+
args: argv.slice(2),
|
|
1180
|
+
options: {
|
|
1181
|
+
input: { type: 'string' }, session: { type: 'string' },
|
|
1182
|
+
'expect-revision': { type: 'string' }, json: { type: 'boolean' },
|
|
1183
|
+
},
|
|
1184
|
+
});
|
|
1185
|
+
let out;
|
|
1186
|
+
if (sub === 'show') {
|
|
1187
|
+
out = showTaskCheckpoint(ROOT, cfg, {
|
|
1188
|
+
sessionPath: o.session || process.env.DTA_SESSION,
|
|
1189
|
+
runPath: process.env.DTA_RUN,
|
|
1190
|
+
});
|
|
1191
|
+
}
|
|
1192
|
+
else if (sub === 'checkpoint') {
|
|
1193
|
+
if (!o.input || o['expect-revision'] === undefined) {
|
|
1194
|
+
fail('task checkpoint 需要 --input 和 --expect-revision');
|
|
1195
|
+
}
|
|
1196
|
+
const expectedRevision = Number(o['expect-revision']);
|
|
1197
|
+
out = checkpointTask(ROOT, cfg, readEventFile(o.input), expectedRevision, {
|
|
1198
|
+
sessionPath: o.session || process.env.DTA_SESSION,
|
|
1199
|
+
runPath: process.env.DTA_RUN,
|
|
1200
|
+
});
|
|
1201
|
+
}
|
|
1202
|
+
else {
|
|
1203
|
+
fail('task 的子命令: show / checkpoint');
|
|
1204
|
+
}
|
|
1205
|
+
if (o.json)
|
|
1206
|
+
console.log(JSON.stringify(out, null, 2));
|
|
1207
|
+
else if (!out.found)
|
|
1208
|
+
console.log('当前 Session 尚无 Task checkpoint。');
|
|
1209
|
+
else {
|
|
1210
|
+
console.log(`✅ Task ${out.checkpoint.taskId} · ${out.checkpoint.status}`);
|
|
1211
|
+
console.log(` revision=${out.checkpoint.revision} hash=${out.hash}`);
|
|
1212
|
+
console.log(` next=${out.checkpoint.nextAction || '-'}`);
|
|
1213
|
+
}
|
|
1214
|
+
return;
|
|
1215
|
+
}
|
|
1216
|
+
// ── memory:Provider-neutral 语义路由;当前首个远端事实源是 AI 表格。──
|
|
1217
|
+
if (cmd === 'memory') {
|
|
1218
|
+
const action = argv[2];
|
|
1219
|
+
if (sub === 'operational' && action === 'upsert') {
|
|
1220
|
+
const { values: o } = parseArgs({
|
|
1221
|
+
args: argv.slice(3),
|
|
1222
|
+
options: {
|
|
1223
|
+
provider: { type: 'string' }, input: { type: 'string' },
|
|
1224
|
+
live: { type: 'boolean' }, yes: { type: 'boolean' }, json: { type: 'boolean' },
|
|
1225
|
+
},
|
|
1226
|
+
});
|
|
1227
|
+
const providerPath = o.provider || process.env.DTA_OPERATIONAL_MEMORY_PROVIDER;
|
|
1228
|
+
if (!providerPath || !o.input) {
|
|
1229
|
+
fail('memory operational upsert 需要 --provider(或 DTA_OPERATIONAL_MEMORY_PROVIDER)和 --input');
|
|
1230
|
+
}
|
|
1231
|
+
const out = upsertOperationalMemory(readEventFile(providerPath), readEventFile(o.input), { execute: Boolean(o.live), yes: Boolean(o.yes) });
|
|
1232
|
+
if (o.json || !o.live)
|
|
1233
|
+
console.log(JSON.stringify(out, null, 2));
|
|
1234
|
+
else {
|
|
1235
|
+
console.log(`${out.verified ? '✅' : '⚠️'} Operational Memory · ${out.mode}`);
|
|
1236
|
+
console.log(` record=${out.recordId || '-'} verification=${out.verification}`);
|
|
1237
|
+
}
|
|
1238
|
+
if (out.mode === 'uncertain')
|
|
1239
|
+
process.exitCode = 2;
|
|
1240
|
+
return;
|
|
1241
|
+
}
|
|
1242
|
+
if (sub === 'candidate') {
|
|
1243
|
+
const { values: o } = parseArgs({
|
|
1244
|
+
args: argv.slice(3),
|
|
1245
|
+
options: {
|
|
1246
|
+
input: { type: 'string' }, id: { type: 'string' }, target: { type: 'string' },
|
|
1247
|
+
decision: { type: 'string' }, reviewer: { type: 'string' }, reason: { type: 'string' },
|
|
1248
|
+
'state-dir': { type: 'string' }, 'expect-revision': { type: 'string' },
|
|
1249
|
+
'expect-target-hash': { type: 'string' },
|
|
1250
|
+
live: { type: 'boolean' }, yes: { type: 'boolean' }, json: { type: 'boolean' },
|
|
1251
|
+
},
|
|
1252
|
+
});
|
|
1253
|
+
const options = { stateDir: o['state-dir'], runPath: process.env.DTA_RUN };
|
|
1254
|
+
let out;
|
|
1255
|
+
if (action === 'propose') {
|
|
1256
|
+
if (!o.input)
|
|
1257
|
+
fail('memory candidate propose 需要 --input');
|
|
1258
|
+
out = proposeMemoryCandidate(ROOT, readEventFile(o.input), options);
|
|
1259
|
+
}
|
|
1260
|
+
else if (action === 'show') {
|
|
1261
|
+
if (!o.id)
|
|
1262
|
+
fail('memory candidate show 需要 --id');
|
|
1263
|
+
out = showMemoryCandidate(ROOT, o.id, options);
|
|
1264
|
+
}
|
|
1265
|
+
else if (action === 'review') {
|
|
1266
|
+
if (!o.id || !o.decision || !o.reviewer || !o.reason ||
|
|
1267
|
+
o['expect-revision'] === undefined) {
|
|
1268
|
+
fail('memory candidate review 需要 --id/--decision/--reviewer/--reason/--expect-revision');
|
|
1269
|
+
}
|
|
1270
|
+
out = reviewMemoryCandidate(ROOT, o.id, o.decision, o.reviewer, o.reason, Number(o['expect-revision']), options);
|
|
1271
|
+
}
|
|
1272
|
+
else if (action === 'publish') {
|
|
1273
|
+
if (!o.id || !o.target || o['expect-revision'] === undefined) {
|
|
1274
|
+
fail('memory candidate publish 需要 --id/--target/--expect-revision');
|
|
1275
|
+
}
|
|
1276
|
+
out = publishMemoryCandidate(ROOT, o.id, readEventFile(o.target), Number(o['expect-revision']), o['expect-target-hash'] || '', {
|
|
1277
|
+
...options,
|
|
1278
|
+
execute: Boolean(o.yes || o.live),
|
|
1279
|
+
yes: Boolean(o.yes),
|
|
1280
|
+
live: Boolean(o.live),
|
|
1281
|
+
});
|
|
1282
|
+
}
|
|
1283
|
+
else {
|
|
1284
|
+
fail('memory candidate 的子命令: propose / show / review / publish');
|
|
1285
|
+
}
|
|
1286
|
+
if (o.json)
|
|
1287
|
+
console.log(JSON.stringify(out, null, 2));
|
|
1288
|
+
else if (action === 'publish') {
|
|
1289
|
+
console.log(`${out.verified ? '✅' : out.mode === 'dry-run' ? '🔎' : '⚠️'} Candidate ${o.id}`);
|
|
1290
|
+
console.log(` mode=${out.mode} targetHash=${out.currentTargetHash}`);
|
|
1291
|
+
}
|
|
1292
|
+
else {
|
|
1293
|
+
console.log(`✅ Candidate ${out.candidate.id} · ${out.candidate.status}`);
|
|
1294
|
+
console.log(` revision=${out.candidate.revision} path=${out.path}`);
|
|
1295
|
+
}
|
|
1296
|
+
if (action === 'publish' && out.mode === 'uncertain')
|
|
1297
|
+
process.exitCode = 2;
|
|
1298
|
+
return;
|
|
1299
|
+
}
|
|
1300
|
+
fail('memory 当前支持: operational upsert / candidate propose|show|review|publish');
|
|
1301
|
+
}
|
|
381
1302
|
// ── act:元语化动作;目标/身份/预算/状态转移都由 Run 固定 ──
|
|
382
1303
|
if (cmd === 'act') {
|
|
383
1304
|
const kind = sub;
|
|
@@ -411,9 +1332,17 @@ async function main() {
|
|
|
411
1332
|
return;
|
|
412
1333
|
}
|
|
413
1334
|
fail(`不认识的命令: ${cmd}`, 1, `运行 dta --help 查看全部命令${suggest(cmd, [
|
|
414
|
-
'setup', 'upgrade', 'doctor', 'skill', 'bootstrap', 'init', 'prepare', 'run', 'dispatch', 'act',
|
|
1335
|
+
'setup', 'upgrade', 'doctor', 'skill', 'agent-platform', 'bootstrap', 'init', 'prepare', 'run', 'dispatch', 'task', 'memory', 'act',
|
|
1336
|
+
'lab', 'listen', 'deploy', 'promote', 'observe',
|
|
1337
|
+
'agent',
|
|
1338
|
+
'info', 'workspace',
|
|
415
1339
|
])}`);
|
|
416
1340
|
}
|
|
1341
|
+
function loadConventionalBindings(input) {
|
|
1342
|
+
const conventional = 'agent.bindings.json';
|
|
1343
|
+
const selected = input || (existsSync(resolve(ROOT, conventional)) ? conventional : '');
|
|
1344
|
+
return selected ? loadAgentBindings(ROOT, selected) : null;
|
|
1345
|
+
}
|
|
417
1346
|
function errorHint(message) {
|
|
418
1347
|
if (/unknown option|未知选项|unexpected argument/i.test(message)) {
|
|
419
1348
|
return '检查参数拼写;运行 dta --help 查看当前版本支持的参数。';
|
|
@@ -421,9 +1350,18 @@ function errorHint(message) {
|
|
|
421
1350
|
if (/找不到当前 Run|必须由能访问 DTA_ROOT 的宿主侧执行/.test(message)) {
|
|
422
1351
|
return 'act 只能用于可信事件 Run;先由宿主执行 dta prepare --event-file <file>,再进入返回的 cwd。';
|
|
423
1352
|
}
|
|
1353
|
+
if (/OpenCode/.test(message)) {
|
|
1354
|
+
return '检查 OpenCode 版本、模型认证与项目 Skill/config;运行 dta workspace doctor <name> 查看精确缺口。';
|
|
1355
|
+
}
|
|
1356
|
+
if (/Multica|multica/.test(message)) {
|
|
1357
|
+
return '先运行 dta workspace plan <name> 和 doctor;确认 profile/ID 来源后,再用 inspect --execute --yes 做只读回读。';
|
|
1358
|
+
}
|
|
424
1359
|
if (/\bDWS\b|\bdws\b/.test(message)) {
|
|
425
1360
|
return '运行 dta doctor 检查 DWS 路径、版本和认证;需要登录时执行 dws auth login。';
|
|
426
1361
|
}
|
|
1362
|
+
if (/dingtalk-agent\.json|Project 未声明|current-workspace|Development Workspace/.test(message)) {
|
|
1363
|
+
return '在 Agent Project 内运行 dta info;用 dta workspace list/show/doctor 检查声明和漂移。';
|
|
1364
|
+
}
|
|
427
1365
|
if (/skills CLI|\bnpx\b/.test(message)) {
|
|
428
1366
|
return '确认 node、npm、npx 在 PATH 中;也可以复制错误中的 npx skills 命令单独执行。';
|
|
429
1367
|
}
|
|
@@ -471,14 +1409,140 @@ function printDispatch(out, json = false) {
|
|
|
471
1409
|
console.log(` allowed=${out.allowedActions.join(', ')} default=${out.defaultAction}`);
|
|
472
1410
|
console.log(' Local 模式可直接用 cwd/env;生产模式由宿主 Broker 保留 DWS 与 control 权限。');
|
|
473
1411
|
}
|
|
1412
|
+
function printLab(out) {
|
|
1413
|
+
const passed = out.ready ?? out.passed ?? out.assertions?.passed;
|
|
1414
|
+
console.log(`${passed === false ? '❌' : '✅'} ${out.$schema || 'dingtalk-agent/lab'}`);
|
|
1415
|
+
if (out.mode)
|
|
1416
|
+
console.log(` mode=${out.mode}`);
|
|
1417
|
+
if (out.marker)
|
|
1418
|
+
console.log(` marker=${out.marker}`);
|
|
1419
|
+
if (out.evidencePath)
|
|
1420
|
+
console.log(` evidence=${out.evidencePath}`);
|
|
1421
|
+
if (Array.isArray(out.checks)) {
|
|
1422
|
+
for (const check of out.checks) {
|
|
1423
|
+
console.log(` ${check.passed ? 'PASS' : 'FAIL'} ${check.id}: ${check.detail}`);
|
|
1424
|
+
}
|
|
1425
|
+
}
|
|
1426
|
+
}
|
|
1427
|
+
function printAgentAudit(out) {
|
|
1428
|
+
console.log(`dingtalk-agent agent audit · ${out.ready ? 'READY' : 'PARTIAL'}`);
|
|
1429
|
+
console.log(` definition=${out.definition.hash} storage=${out.storageMode}`);
|
|
1430
|
+
console.log(` dingtalkSideEffect=${out.dingtalkSideEffect} sideEffect=${out.sideEffect}`);
|
|
1431
|
+
for (const check of out.checks) {
|
|
1432
|
+
const mark = check.level === 'pass' ? 'PASS' : check.level === 'warn' ? 'WARN' : 'FAIL';
|
|
1433
|
+
console.log(` ${mark} ${check.id}: ${check.summary}`);
|
|
1434
|
+
}
|
|
1435
|
+
if (out.repairs.length) {
|
|
1436
|
+
console.log('\n修复建议:');
|
|
1437
|
+
for (const repair of out.repairs) {
|
|
1438
|
+
console.log(` ${repair.id}: ${repair.why}`);
|
|
1439
|
+
for (const action of repair.actions)
|
|
1440
|
+
console.log(` - ${action}`);
|
|
1441
|
+
}
|
|
1442
|
+
}
|
|
1443
|
+
}
|
|
1444
|
+
function printAgentEnhance(out) {
|
|
1445
|
+
if (out.$schema === 'dingtalk-agent/agent-enhancement-plan@1') {
|
|
1446
|
+
console.log(`dingtalk-agent agent enhance · ${out.ready ? 'READY PLAN' : 'BLOCKED'}`);
|
|
1447
|
+
console.log(` planId=${out.planId} project=${out.projectName}`);
|
|
1448
|
+
console.log(` sideEffect=${out.sideEffect} dingtalkSideEffect=${out.dingtalkSideEffect}`);
|
|
1449
|
+
for (const operation of out.operations) {
|
|
1450
|
+
console.log(` ${operation.kind.toUpperCase()} ${operation.path}: ${operation.reason}`);
|
|
1451
|
+
}
|
|
1452
|
+
if (out.semanticReview.required) {
|
|
1453
|
+
console.log(` REVIEW ${out.semanticReview.files.join(', ')}: ${out.semanticReview.why}`);
|
|
1454
|
+
}
|
|
1455
|
+
for (const blocker of out.blockers)
|
|
1456
|
+
console.log(` BLOCK ${blocker}`);
|
|
1457
|
+
if (out.ready)
|
|
1458
|
+
console.log(`\nApply:\n ${out.apply.command}`);
|
|
1459
|
+
return;
|
|
1460
|
+
}
|
|
1461
|
+
console.log('dingtalk-agent agent enhance · APPLIED');
|
|
1462
|
+
console.log(` operation=${out.operationId} planId=${out.planId}`);
|
|
1463
|
+
console.log(` changes=${out.changes.length} idempotent=${out.idempotent}`);
|
|
1464
|
+
if (out.backupRoot)
|
|
1465
|
+
console.log(` backup=${out.backupRoot}`);
|
|
1466
|
+
console.log(` audit=${out.audit.status} missing=${out.audit.missing.join(', ') || '-'}`);
|
|
1467
|
+
}
|
|
1468
|
+
function printAgentPlatform(platform) {
|
|
1469
|
+
console.log(`${platform.status === 'supported' ? '✅' : '⏳'} ${platform.name} · ${platform.label} · ${platformStatusLabel(platform.status)}`);
|
|
1470
|
+
console.log(` ${platform.description}`);
|
|
1471
|
+
for (const skill of platform.skills)
|
|
1472
|
+
console.log(` 技能[${skill.role}] ${skill.name} —— ${skill.purpose}`);
|
|
1473
|
+
if (platform.commands.length)
|
|
1474
|
+
console.log(` 平台命令: ${platform.commands.map((item) => `dta ${item}`).join(' · ')}`);
|
|
1475
|
+
}
|
|
1476
|
+
function printAgentPlatformResolution(out) {
|
|
1477
|
+
if (!out.platform) {
|
|
1478
|
+
console.log('⚠️ 当前工作区未声明 managed agent platform');
|
|
1479
|
+
console.log(' 运行 `dta agent-platform use multica-dingtalk`,或设置 DTA_AGENT_PLATFORM 环境变量。');
|
|
1480
|
+
return;
|
|
1481
|
+
}
|
|
1482
|
+
const known = out.definition;
|
|
1483
|
+
console.log(`${known ? '✅' : '❌'} 当前 platform: ${out.platform}${known ? ` · ${known.label} · ${platformStatusLabel(known.status)}` : '(未知)'}`);
|
|
1484
|
+
console.log(` 来源: ${out.source}${out.file ? ` · ${out.file}` : ''}`);
|
|
1485
|
+
for (const skill of known?.skills || [])
|
|
1486
|
+
console.log(` 技能[${skill.role}] ${skill.name} —— ${skill.purpose}`);
|
|
1487
|
+
}
|
|
1488
|
+
// 披露:dta 层平台命令关联到平台内确切的 Skill(诊断信息走 stderr,不污染 --json stdout)。
|
|
1489
|
+
function disclosePlatformSkill(resolution, role) {
|
|
1490
|
+
const skillName = resolution.definition ? platformSkillForRole(resolution.definition.name, role) : null;
|
|
1491
|
+
if (skillName)
|
|
1492
|
+
console.error(`提示: 平台 ${resolution.definition.name} 的该命令方法学由 Skill ${skillName} 承载`);
|
|
1493
|
+
}
|
|
1494
|
+
function printEndpoint(endpoint) {
|
|
1495
|
+
if (!endpoint)
|
|
1496
|
+
return;
|
|
1497
|
+
if (endpoint.source === 'ambiguous') {
|
|
1498
|
+
console.log(` Endpoint: 多个已登录目标未选定(${endpoint.candidates.join(' / ')})——` +
|
|
1499
|
+
`用 ${endpoint.envVar} 或指定 profile 明确选择`);
|
|
1500
|
+
return;
|
|
1501
|
+
}
|
|
1502
|
+
if (!endpoint.endpoint) {
|
|
1503
|
+
console.log(` Endpoint: 未解析——设 ${endpoint.envVar} 或登录 multica 后生效`);
|
|
1504
|
+
return;
|
|
1505
|
+
}
|
|
1506
|
+
const mark = endpoint.confirmed ? '✅' : '⚠️';
|
|
1507
|
+
const note = endpoint.confirmed ? '' : '(建议/未确认,deploy 前需显式确认是预发还是生产)';
|
|
1508
|
+
console.log(` ${mark} Endpoint: ${endpoint.endpoint} · 来源: ${endpoint.source}${note}`);
|
|
1509
|
+
console.log(` (切换:设 ${endpoint.envVar}=<url>、写 dingtalk-agent.json#multicaEndpoint、或登录对应 profile;无需改代码)`);
|
|
1510
|
+
}
|
|
1511
|
+
function printPlatformDoc(platformName) {
|
|
1512
|
+
if (!platformName)
|
|
1513
|
+
return;
|
|
1514
|
+
const path = platformDocPath(PACKAGE_ROOT, platformName);
|
|
1515
|
+
if (path)
|
|
1516
|
+
console.log(` 平台说明: ${path}\n (切换到该平台后请阅读,了解各技能用途与交付链)`);
|
|
1517
|
+
}
|
|
1518
|
+
function printMulticaTargets(targets) {
|
|
1519
|
+
if (!targets.length)
|
|
1520
|
+
return;
|
|
1521
|
+
console.log(' 本机 Multica 登录目标(发布前必须与用户确认 endpoint 与 workspace):');
|
|
1522
|
+
for (const target of targets) {
|
|
1523
|
+
console.log(` - profile=${target.profile} · ${target.serverUrl}${target.workspaceId ? ` · workspace=${target.workspaceId}` : ''}`);
|
|
1524
|
+
}
|
|
1525
|
+
}
|
|
1526
|
+
function printAgentPlatformReadiness(checks) {
|
|
1527
|
+
for (const check of checks) {
|
|
1528
|
+
console.log(` ${check.ok ? '✅' : '⚠️'} ${check.summary}`);
|
|
1529
|
+
if (check.hint)
|
|
1530
|
+
console.log(` ${check.hint}`);
|
|
1531
|
+
}
|
|
1532
|
+
}
|
|
474
1533
|
function printSkillStatus(out, action, dryRun) {
|
|
475
1534
|
const prefix = dryRun ? 'DRY-RUN' : '✅';
|
|
476
1535
|
const verb = action === 'status' ? '全局 Skill 状态' : `skill ${action}`;
|
|
477
1536
|
console.log(`${prefix} ${verb}: ${out.name}`);
|
|
478
1537
|
console.log(` manager=${out.manager} bundled=${out.bundled.skillVersion || '-'}`);
|
|
479
1538
|
console.log(` canonical=${out.canonical.path}`);
|
|
480
|
-
console.log(` installed=${out.canonical.exists}
|
|
481
|
-
|
|
1539
|
+
console.log(` installed=${out.canonical.exists} ` +
|
|
1540
|
+
`${out.canonical.installedVersion || '—'} → ${out.bundled.skillVersion} ` +
|
|
1541
|
+
`state=${out.canonical.state}`);
|
|
1542
|
+
if (out.operation?.after) {
|
|
1543
|
+
console.log(` ${out.operation.before.installedVersion || '—'}(${out.operation.before.state})` +
|
|
1544
|
+
` → ${out.operation.after.installedVersion}(${out.operation.after.state})`);
|
|
1545
|
+
}
|
|
482
1546
|
if (out.operation)
|
|
483
1547
|
console.log(` delegated: ${out.operation.command}`);
|
|
484
1548
|
for (const client of out.clients) {
|
|
@@ -498,12 +1562,178 @@ function printDoctor(out) {
|
|
|
498
1562
|
if (check.fix)
|
|
499
1563
|
console.log(` 修复: ${check.fix}`);
|
|
500
1564
|
}
|
|
1565
|
+
if (out.hosts.length) {
|
|
1566
|
+
// Host 面回答"本地能在哪跑",不改变上面的 ready 结论。
|
|
1567
|
+
console.log('\n本机 Coding Agent:');
|
|
1568
|
+
const width = Math.max(...out.hosts.map((host) => displayWidth(host.label)));
|
|
1569
|
+
for (const host of out.hosts) {
|
|
1570
|
+
const label = host.label + ' '.repeat(width - displayWidth(host.label));
|
|
1571
|
+
const where = host.cli.found
|
|
1572
|
+
? [host.cli.path, host.cli.version].filter(Boolean).join(' ')
|
|
1573
|
+
: `未找到 ${host.cli.command}`;
|
|
1574
|
+
console.log(` ${host.cli.found ? '✅' : '❌'} ${label} ${where}`);
|
|
1575
|
+
console.log(` Skill 可见性: ${host.skillExposure.exists ? '已暴露' : '未暴露'} · ${host.skillExposureRoot}`);
|
|
1576
|
+
}
|
|
1577
|
+
}
|
|
501
1578
|
if (out.nextSteps.length) {
|
|
502
1579
|
console.log('\n下一步:');
|
|
503
1580
|
for (const step of out.nextSteps)
|
|
504
1581
|
console.log(` ${step}`);
|
|
505
1582
|
}
|
|
506
1583
|
}
|
|
1584
|
+
/** 全角字符按两列计宽,避免中英混排的 Host 列表错位。 */
|
|
1585
|
+
function displayWidth(text) {
|
|
1586
|
+
let width = 0;
|
|
1587
|
+
for (const char of text)
|
|
1588
|
+
width += /[ᄀ-ᅟ⺀-가-힣豈-︰--⦆¢-₩]/.test(char) ? 2 : 1;
|
|
1589
|
+
return width;
|
|
1590
|
+
}
|
|
1591
|
+
function printProjectInfo(out) {
|
|
1592
|
+
console.log(`dingtalk-agent Project · ${out.project.name}`);
|
|
1593
|
+
console.log(` root=${out.root}`);
|
|
1594
|
+
console.log(` source=${out.source} manifest=${out.manifest || '(synthetic legacy)'}`);
|
|
1595
|
+
console.log(` hash=${out.manifestHash} dta=${out.project.dtaVersion}`);
|
|
1596
|
+
console.log(` current=${out.currentWorkspace || '(not selected)'}`);
|
|
1597
|
+
for (const workspace of out.workspaces) {
|
|
1598
|
+
console.log(` ${workspace.current ? '*' : '-'} ${workspace.name} · ${workspace.provider.kind} · ${workspace.status}`);
|
|
1599
|
+
}
|
|
1600
|
+
}
|
|
1601
|
+
function printWorkspaceList(out) {
|
|
1602
|
+
console.log(`dingtalk-agent workspaces · ${out.project.name}`);
|
|
1603
|
+
if (!out.workspaces.length)
|
|
1604
|
+
console.log(' 尚未声明 Development Workspace。');
|
|
1605
|
+
for (const workspace of out.workspaces) {
|
|
1606
|
+
console.log(` ${workspace.current ? '*' : '-'} ${workspace.name} provider=${workspace.provider.kind} ` +
|
|
1607
|
+
`stage=${workspace.stage} status=${workspace.status}`);
|
|
1608
|
+
}
|
|
1609
|
+
}
|
|
1610
|
+
function printDevelopmentWorkspace(out) {
|
|
1611
|
+
console.log(`dingtalk-agent workspace · ${out.name}`);
|
|
1612
|
+
console.log(` provider=${out.provider.kind} stage=${out.stage} status=${out.status}`);
|
|
1613
|
+
console.log(` desired=${out.desiredHash} observed=${out.observedHash || '-'}`);
|
|
1614
|
+
console.log(` current=${out.current} legacy=${out.legacy}`);
|
|
1615
|
+
for (const [slot, route] of Object.entries(out.storage))
|
|
1616
|
+
console.log(` ${slot}=${route}`);
|
|
1617
|
+
for (const source of out.configSources)
|
|
1618
|
+
console.log(` source=${source}`);
|
|
1619
|
+
}
|
|
1620
|
+
function printDevelopmentWorkspaceDoctor(out) {
|
|
1621
|
+
console.log(`dingtalk-agent workspace doctor · ${out.workspace} · ${out.ready ? 'READY' : 'PARTIAL'}`);
|
|
1622
|
+
console.log(` provider=${out.provider} status=${out.status}`);
|
|
1623
|
+
console.log(` sideEffect=${out.sideEffect} dingtalkSideEffect=${out.dingtalkSideEffect}`);
|
|
1624
|
+
for (const check of out.checks) {
|
|
1625
|
+
const mark = check.level === 'pass' ? 'PASS' : check.level === 'warn' ? 'WARN' : 'FAIL';
|
|
1626
|
+
console.log(` ${mark} ${check.id}: ${check.summary}`);
|
|
1627
|
+
if (check.fix && check.level !== 'pass')
|
|
1628
|
+
console.log(` fix: ${check.fix}`);
|
|
1629
|
+
}
|
|
1630
|
+
}
|
|
1631
|
+
function printOpenCodeWorkspaceOperation(out) {
|
|
1632
|
+
const applied = out.$schema === 'dingtalk-agent/opencode-workspace-apply@1';
|
|
1633
|
+
console.log(`${applied ? out.applied ? '✅' : '↩️' : 'DRY-RUN'} OpenCode Workspace ${out.workspace}`);
|
|
1634
|
+
console.log(` action=${out.action} model=${out.model}`);
|
|
1635
|
+
console.log(` desired=${out.desiredHash} observed=${out.observedHash || '-'}`);
|
|
1636
|
+
console.log(` managed=${out.managedPath}`);
|
|
1637
|
+
if (!applied && out.writes?.length)
|
|
1638
|
+
console.log(` writes=${out.writes.join(', ')}`);
|
|
1639
|
+
}
|
|
1640
|
+
function printMulticaWorkspaceOperation(out) {
|
|
1641
|
+
const passed = out.passed ?? out.readyForApply ?? out.blocking?.length === 0;
|
|
1642
|
+
const mode = out.remoteRead ? 'REMOTE-READ' : 'DRY-RUN';
|
|
1643
|
+
console.log(`${passed ? '✅' : '⚠️'} ${mode} Multica Workspace ${out.workspace}`);
|
|
1644
|
+
console.log(` schema=${out.$schema} profile=${out.profile || '-'}`);
|
|
1645
|
+
if (out.planId)
|
|
1646
|
+
console.log(` plan=${out.planId}`);
|
|
1647
|
+
if (out.inspectionId)
|
|
1648
|
+
console.log(` inspection=${out.inspectionId}`);
|
|
1649
|
+
if (out.desiredHash)
|
|
1650
|
+
console.log(` desired=${out.desiredHash}`);
|
|
1651
|
+
if (out.observedHash)
|
|
1652
|
+
console.log(` observed=${out.observedHash}`);
|
|
1653
|
+
if (out.diff?.length)
|
|
1654
|
+
console.log(` diff=${out.diff.join(', ')}`);
|
|
1655
|
+
if (out.blocking?.length)
|
|
1656
|
+
console.log(` blocking=${out.blocking.join(', ')}`);
|
|
1657
|
+
if (out.failures?.length)
|
|
1658
|
+
console.log(` failures=${out.failures.join(', ')}`);
|
|
1659
|
+
if (out.evidencePath)
|
|
1660
|
+
console.log(` evidence=${out.evidencePath}`);
|
|
1661
|
+
console.log(` remoteWrite=${out.remoteWrite} dingtalkSideEffect=${out.dingtalkSideEffect}`);
|
|
1662
|
+
}
|
|
1663
|
+
function printMulticaDeployment(out) {
|
|
1664
|
+
console.log(`Multica deploy: ${out.workspace || '<unknown>'}`);
|
|
1665
|
+
if (out.planId)
|
|
1666
|
+
console.log(` plan: ${out.planId}`);
|
|
1667
|
+
if (out.operationId)
|
|
1668
|
+
console.log(` operation: ${out.operationId}`);
|
|
1669
|
+
if (out.receiptId)
|
|
1670
|
+
console.log(` receipt: ${out.receiptId}`);
|
|
1671
|
+
if (out.action)
|
|
1672
|
+
console.log(` action: ${out.action}`);
|
|
1673
|
+
if (out.status)
|
|
1674
|
+
console.log(` status: ${out.status}`);
|
|
1675
|
+
if (typeof out.providerReady === 'boolean')
|
|
1676
|
+
console.log(` provider ready: ${out.providerReady}`);
|
|
1677
|
+
if (Array.isArray(out.blocking) && out.blocking.length) {
|
|
1678
|
+
console.log(` blocking: ${out.blocking.join(', ')}`);
|
|
1679
|
+
}
|
|
1680
|
+
if (Array.isArray(out.failures) && out.failures.length) {
|
|
1681
|
+
console.log(` failures: ${out.failures.join(', ')}`);
|
|
1682
|
+
}
|
|
1683
|
+
if (out.triggerWrite === false)
|
|
1684
|
+
console.log(' triggers: unchanged');
|
|
1685
|
+
}
|
|
1686
|
+
function printPromotion(out) {
|
|
1687
|
+
console.log(`Promotion: ${out.promotionId || out.candidateId || out.candidate?.candidateId || '<none>'}`);
|
|
1688
|
+
if (out.planId)
|
|
1689
|
+
console.log(` plan: ${out.planId}`);
|
|
1690
|
+
if (out.routeId)
|
|
1691
|
+
console.log(` route: ${out.routeId}`);
|
|
1692
|
+
if (out.status)
|
|
1693
|
+
console.log(` status: ${out.status}`);
|
|
1694
|
+
if (out.target?.observedHash)
|
|
1695
|
+
console.log(` observed: ${out.target.observedHash}`);
|
|
1696
|
+
if (out.candidatePath)
|
|
1697
|
+
console.log(` candidate: ${out.candidatePath}`);
|
|
1698
|
+
if (out.candidate?.evidencePath)
|
|
1699
|
+
console.log(` candidate: ${out.candidate.evidencePath}`);
|
|
1700
|
+
if (Array.isArray(out.blocking) && out.blocking.length)
|
|
1701
|
+
console.log(` blocking: ${out.blocking.join(', ')}`);
|
|
1702
|
+
if (out.triggerWrite === false)
|
|
1703
|
+
console.log(' triggers: unchanged');
|
|
1704
|
+
}
|
|
1705
|
+
function parseOptionalTimeout(value, label) {
|
|
1706
|
+
if (value === undefined)
|
|
1707
|
+
return undefined;
|
|
1708
|
+
const parsed = Number(value);
|
|
1709
|
+
if (!Number.isInteger(parsed) || parsed < 100 || parsed > 300_000) {
|
|
1710
|
+
fail(`${label} 必须是 100..300000 的整数毫秒`);
|
|
1711
|
+
}
|
|
1712
|
+
return parsed;
|
|
1713
|
+
}
|
|
1714
|
+
function readProjectText(start, ref, label) {
|
|
1715
|
+
const root = inspectAgentProject(start, PACKAGE_JSON.version).root;
|
|
1716
|
+
const candidate = resolve(root, ref);
|
|
1717
|
+
const lexical = relative(root, candidate);
|
|
1718
|
+
if (lexical === '..' || lexical.startsWith(`..${process.platform === 'win32' ? '\\' : '/'}`)) {
|
|
1719
|
+
throw new Error(`${label} 必须位于 Agent Project 内: ${ref}`);
|
|
1720
|
+
}
|
|
1721
|
+
if (!existsSync(candidate))
|
|
1722
|
+
throw new Error(`${label} 不存在: ${ref}`);
|
|
1723
|
+
const actual = realpathSync(candidate);
|
|
1724
|
+
const resolved = relative(root, actual);
|
|
1725
|
+
if (resolved === '..' || resolved.startsWith(`..${process.platform === 'win32' ? '\\' : '/'}`)) {
|
|
1726
|
+
throw new Error(`${label} 真实路径越出 Agent Project: ${ref}`);
|
|
1727
|
+
}
|
|
1728
|
+
return readFileSync(actual, 'utf8');
|
|
1729
|
+
}
|
|
1730
|
+
function rejectWorkspaceOptions(values, allowed, command) {
|
|
1731
|
+
const extras = Object.entries(values)
|
|
1732
|
+
.filter(([key, value]) => !allowed.includes(key) && value !== undefined && value !== false)
|
|
1733
|
+
.map(([key]) => `--${key}`);
|
|
1734
|
+
if (extras.length)
|
|
1735
|
+
fail(`${command} 不接受参数: ${extras.join(', ')}`);
|
|
1736
|
+
}
|
|
507
1737
|
function printSetup(out) {
|
|
508
1738
|
console.log(`${out.dryRun ? 'DRY-RUN' : '✅'} dingtalk-agent setup`);
|
|
509
1739
|
console.log(` CLI: ${out.cli.executable}`);
|