@xdxer/dingtalk-agent 0.1.4-beta.9 → 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.
Files changed (118) hide show
  1. package/CHANGELOG.md +198 -0
  2. package/README.en.md +98 -326
  3. package/README.md +95 -673
  4. package/dist/bin/dingtalk-agent.js +200 -18
  5. package/dist/bin/dingtalk-agent.js.map +1 -1
  6. package/dist/src/agent-audit.js +1014 -89
  7. package/dist/src/agent-audit.js.map +1 -1
  8. package/dist/src/agent-enhance.js +41 -8
  9. package/dist/src/agent-enhance.js.map +1 -1
  10. package/dist/src/agent-platform.js +299 -0
  11. package/dist/src/agent-platform.js.map +1 -0
  12. package/dist/src/config.js +1 -7
  13. package/dist/src/config.js.map +1 -1
  14. package/dist/src/development-workspace.js +31 -5
  15. package/dist/src/development-workspace.js.map +1 -1
  16. package/dist/src/doctor.js +74 -15
  17. package/dist/src/doctor.js.map +1 -1
  18. package/dist/src/host-detect.js +146 -0
  19. package/dist/src/host-detect.js.map +1 -0
  20. package/dist/src/instruction-path.js +270 -0
  21. package/dist/src/instruction-path.js.map +1 -0
  22. package/dist/src/map.js +157 -0
  23. package/dist/src/map.js.map +1 -0
  24. package/dist/src/multica-deploy.js +78 -20
  25. package/dist/src/multica-deploy.js.map +1 -1
  26. package/dist/src/multica-provider.js +1 -1
  27. package/dist/src/multica-provider.js.map +1 -1
  28. package/dist/src/opencode-evals.js +710 -225
  29. package/dist/src/opencode-evals.js.map +1 -1
  30. package/dist/src/opencode-isolation.js +124 -0
  31. package/dist/src/opencode-isolation.js.map +1 -0
  32. package/dist/src/opencode-provider.js +1 -0
  33. package/dist/src/opencode-provider.js.map +1 -1
  34. package/dist/src/opencode-workspace.js +21 -10
  35. package/dist/src/opencode-workspace.js.map +1 -1
  36. package/dist/src/remote-state-evals.js +2 -1
  37. package/dist/src/remote-state-evals.js.map +1 -1
  38. package/dist/src/robot-evals.js +2 -1
  39. package/dist/src/robot-evals.js.map +1 -1
  40. package/dist/src/setup.js +6 -5
  41. package/dist/src/setup.js.map +1 -1
  42. package/dist/src/skill-manager.js +141 -12
  43. package/dist/src/skill-manager.js.map +1 -1
  44. package/dist/src/skills.js +2 -1
  45. package/dist/src/skills.js.map +1 -1
  46. package/dist/src/types.js.map +1 -1
  47. package/dist/src/upgrade.js +23 -27
  48. package/dist/src/upgrade.js.map +1 -1
  49. package/dist/src/version.js +73 -0
  50. package/dist/src/version.js.map +1 -0
  51. package/docs/INSTALLATION.md +3 -3
  52. package/docs/assets/agent-delivery-lifecycle.svg +103 -0
  53. package/docs/schemas/agent-platform.schema.json +13 -0
  54. package/docs/schemas/project.schema.json +3 -0
  55. package/docs/schemas/release-readiness.schema.json +2 -1
  56. package/evals/README.md +17 -0
  57. package/lab/README.md +3 -3
  58. package/lab/agent-eval/catalog.json +5 -5
  59. package/lab/agent-eval/classic-failures.json +9 -9
  60. package/lab/agent-eval/completion-gate-regression.json +6 -6
  61. package/lab/agent-eval/remote-state-workspace/opencode.json +1 -1
  62. package/lab/agent-eval/workspace/AGENTS.md +1 -1
  63. package/lab/project-workspace/fake-multica-provider.mjs +17 -6
  64. package/lab/project-workspace/opencode-provider-suite.json +1 -1
  65. package/lab/robot-eval/suite.json +1 -1
  66. package/lab/robot-eval/workspace/AGENTS.md +1 -1
  67. package/lab/schemas/agent-eval-catalog.schema.json +1 -1
  68. package/package.json +13 -12
  69. package/skills/README.md +23 -0
  70. package/skills/core/dingtalk-agent-compose/SKILL.md +151 -0
  71. package/skills/core/dingtalk-agent-compose/assets/AGENTS.template.md +35 -0
  72. package/skills/core/dingtalk-agent-compose/assets/role-skill.template.md +32 -0
  73. package/skills/core/dingtalk-agent-compose/evals/evals.json +129 -0
  74. package/skills/{dingtalk-agent-compose → core/dingtalk-agent-compose}/references/agent-definition-contract.md +3 -3
  75. package/skills/core/dingtalk-agent-compose/references/host-loading-contract.md +58 -0
  76. package/skills/core/dingtalk-agent-compose/references/hosts/claude-code.md +48 -0
  77. package/skills/core/dingtalk-agent-compose/references/hosts/opencode.md +77 -0
  78. package/skills/{dingtalk-agent-eval → core/dingtalk-agent-eval}/SKILL.md +31 -7
  79. package/skills/{dingtalk-agent-eval → core/dingtalk-agent-eval}/assets/eval-catalog.template.json +1 -1
  80. package/skills/{dingtalk-agent-eval → core/dingtalk-agent-eval}/evals/evals.json +22 -0
  81. package/skills/{dingtalk-agent-eval → core/dingtalk-agent-eval}/references/eval-topology.md +14 -0
  82. package/skills/{dingtalk-agent-eval → core/dingtalk-agent-eval}/references/evidence-contract.md +21 -0
  83. package/skills/core/dingtalk-agent-eval/references/failure-to-case.md +35 -0
  84. package/skills/core/dingtalk-agent-eval/references/interactive-debug-channels.md +93 -0
  85. package/skills/core/dingtalk-agent-eval/references/local-connector-smoke.md +75 -0
  86. package/skills/core/dingtalk-basic-behavior/SKILL.md +87 -0
  87. package/skills/{dingtalk-basic-behavior → core/dingtalk-basic-behavior}/references/memory-and-evolution.md +12 -0
  88. package/skills/core/dingtalk-basic-behavior/references/risk-authority-and-privacy.md +62 -0
  89. package/skills/{dingtalk-basic-behavior → core/dingtalk-basic-behavior}/references/task-lifecycle.md +15 -3
  90. package/skills/core/dingtalk-basic-behavior/references/truth-and-recovery.md +65 -0
  91. package/skills/platforms/deap/PLATFORM.md +3 -0
  92. package/skills/platforms/deap/README.md +3 -0
  93. package/skills/platforms/multica-dingtalk/PLATFORM.md +40 -0
  94. package/skills/{dingtalk-agent-boot-multica → platforms/multica-dingtalk/dingtalk-agent-boot-multica}/SKILL.md +4 -4
  95. package/skills/{dingtalk-agent-deploy → platforms/multica-dingtalk/dingtalk-agent-deploy-multica}/SKILL.md +1 -1
  96. package/skills/platforms/multica-dingtalk/multica-external/SKILL.md +282 -0
  97. package/skills/platforms/multica-dingtalk/multica-external/scripts/bootstrap.sh +78 -0
  98. package/skills/platforms/multica-dingtalk/multica-external/scripts/multica_ext.py +1180 -0
  99. package/skills/dingtalk-agent-compose/SKILL.md +0 -110
  100. package/skills/dingtalk-agent-compose/assets/AGENTS.template.md +0 -26
  101. package/skills/dingtalk-agent-compose/assets/role-skill.template.md +0 -24
  102. package/skills/dingtalk-agent-compose/evals/evals.json +0 -94
  103. package/skills/dingtalk-agent-compose/references/opencode-host-contract.md +0 -65
  104. package/skills/dingtalk-basic-behavior/SKILL.md +0 -146
  105. /package/skills/{dingtalk-agent-compose → core/dingtalk-agent-compose}/assets/agent.bindings.dingtalk-doc.template.json +0 -0
  106. /package/skills/{dingtalk-agent-compose → core/dingtalk-agent-compose}/assets/agent.bindings.local.template.json +0 -0
  107. /package/skills/{dingtalk-agent-compose/assets → core/dingtalk-agent-compose/assets/hosts/opencode}/opencode.template.json +0 -0
  108. /package/skills/{dingtalk-agent-compose → core/dingtalk-agent-compose}/references/storage-routing.md +0 -0
  109. /package/skills/{dingtalk-agent-eval → core/dingtalk-agent-eval}/references/scenario-taxonomy.md +0 -0
  110. /package/skills/{dingtalk-agent-eval → core/dingtalk-agent-eval}/references/storage-modes.md +0 -0
  111. /package/skills/{dingtalk-basic-behavior → core/dingtalk-basic-behavior}/assets/memory-candidate-proposal.json +0 -0
  112. /package/skills/{dingtalk-basic-behavior → core/dingtalk-basic-behavior}/assets/task-checkpoint.json +0 -0
  113. /package/skills/{dingtalk-basic-behavior → core/dingtalk-basic-behavior}/references/action-contract.md +0 -0
  114. /package/skills/{dingtalk-basic-behavior → core/dingtalk-basic-behavior}/references/event-to-behavior.md +0 -0
  115. /package/skills/{dingtalk-basic-behavior → core/dingtalk-basic-behavior}/references/perception-and-gates.md +0 -0
  116. /package/skills/{dingtalk-basic-behavior → core/dingtalk-basic-behavior}/references/runtime-modes.md +0 -0
  117. /package/skills/{dingtalk-agent-deploy → platforms/multica-dingtalk/dingtalk-agent-deploy-multica}/references/multica-deployment-contract.md +0 -0
  118. /package/skills/{dingtalk-agent-deploy → platforms/multica-dingtalk/dingtalk-agent-deploy-multica}/references/promotion-observation-contract.md +0 -0
@@ -38,7 +38,8 @@ import { upgradeAgent } from '../src/upgrade.js';
38
38
  import { checkpointTask, showTaskCheckpoint } from '../src/memory/task-checkpoints.js';
39
39
  import { upsertOperationalMemory } from '../src/memory/operational.js';
40
40
  import { proposeMemoryCandidate, publishMemoryCandidate, reviewMemoryCandidate, showMemoryCandidate, } from '../src/memory/candidates.js';
41
- import { installGlobalSkill, skillStatus, uninstallGlobalSkill, upgradeGlobalSkill, } from '../src/skill-manager.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';
42
43
  const PACKAGE_ROOT = resolvePackageRoot(import.meta.url);
43
44
  const PACKAGE_JSON = JSON.parse(readFileSync(join(PACKAGE_ROOT, 'package.json'), 'utf8'));
44
45
  // ROOT = **你的工作区**(当前目录),不是包所在的目录。
@@ -56,16 +57,16 @@ dta —— 给 Agent 安装钉钉员工的基础行为和工作环境
56
57
  · 从本地目录或钉钉文档加载身份、记忆和知识
57
58
 
58
59
  开始使用:
59
- dta setup 首次配置 CLI、DWS 和基础行为 Skill
60
+ dta setup 首次配置 CLI、DWS 和内置 Skill(基础行为 + Agent 装配 + 交付后评测)
60
61
  dta bootstrap --json 为当前 Agent 会话加载工作区
61
62
  dta agent enhance / audit 安全增强已有仓库,再审计定义、存储与 Skill 真加载
62
63
  dta info / dta workspace doctor <name> 查看 Project 并只读诊断 Workspace
63
- dta deploy ... / dta promote ... 预览 Multica 受控部署或已验版本晋级
64
+ dta agent-platform use <platform> → dta deploy / dta promote 声明平台归属并装平台技能包,再受控部署与晋级
64
65
 
65
66
  维护环境:
66
67
  dta doctor 检查哪里没装好,并给出修复提示
67
68
  dta upgrade 自升级,再重新检查完整环境
68
- dta skill status 查看 Claude Code、Codex、OpenCode 能否发现 Skill
69
+ dta skill status 查看内置 Skill 的版本状态与三个客户端能否发现(可加 name 只查一个)
69
70
 
70
71
  接入钉钉事件和可靠外发:dta help runtime
71
72
  `;
@@ -232,6 +233,8 @@ async function main() {
232
233
  return;
233
234
  }
234
235
  if (cmd === 'deploy') {
236
+ const platformForDeploy = requireSupportedAgentPlatform('deploy', PROJECT_START);
237
+ disclosePlatformSkill(platformForDeploy, 'deploy');
235
238
  const { values: o, positionals } = parseArgs({
236
239
  args: argv.slice(1), allowPositionals: true,
237
240
  options: {
@@ -307,6 +310,8 @@ async function main() {
307
310
  return;
308
311
  }
309
312
  if (cmd === 'promote') {
313
+ const platformForPromote = requireSupportedAgentPlatform('promote', PROJECT_START);
314
+ disclosePlatformSkill(platformForPromote, 'deploy');
310
315
  const { values: o, positionals } = parseArgs({
311
316
  args: argv.slice(1), allowPositionals: true,
312
317
  options: {
@@ -366,6 +371,8 @@ async function main() {
366
371
  return;
367
372
  }
368
373
  if (cmd === 'observe') {
374
+ const platformForObserve = requireSupportedAgentPlatform('observe', PROJECT_START);
375
+ disclosePlatformSkill(platformForObserve, 'deploy');
369
376
  const { values: o, positionals } = parseArgs({
370
377
  args: argv.slice(1), allowPositionals: true,
371
378
  options: {
@@ -676,28 +683,112 @@ async function main() {
676
683
  allowPositionals: true,
677
684
  options: {
678
685
  name: { type: 'string' }, 'dry-run': { type: 'boolean' }, json: { type: 'boolean' },
686
+ 'allow-downgrade': { type: 'boolean' },
679
687
  },
680
688
  });
681
689
  if (positionals.length > 1)
682
690
  fail('skill 最多接受一个 Skill name');
683
- const options = { dryRun: o['dry-run'], name: o.name || positionals[0] };
691
+ const name = o.name || positionals[0];
692
+ const dryRun = Boolean(o['dry-run']);
693
+ const allowDowngrade = Boolean(o['allow-downgrade']);
684
694
  let out;
685
- if (sub === 'install')
686
- out = installGlobalSkill(PACKAGE_ROOT, options);
687
- else if (sub === 'status')
688
- out = skillStatus(PACKAGE_ROOT, options);
689
- else if (sub === 'upgrade')
690
- out = upgradeGlobalSkill(PACKAGE_ROOT, options);
691
- else if (sub === 'uninstall')
692
- out = uninstallGlobalSkill(PACKAGE_ROOT, options);
693
- 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 {
694
714
  fail(`不认识的 skill 子命令: ${sub || '(缺失)'}`, 1, `可用命令: dta skill install | status | upgrade | uninstall${suggest(sub || '', ['install', 'status', 'upgrade', 'uninstall'], 'dta skill')}`);
715
+ }
695
716
  if (o.json)
696
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);
697
721
  else
698
- printSkillStatus(out, sub, Boolean(o['dry-run']));
722
+ printSkillStatus(out, sub, dryRun);
699
723
  return;
700
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
+ }
701
792
  // ── bootstrap:当前 Agent Session 按需发现/拉取语义上下文。──
702
793
  if (cmd === 'bootstrap') {
703
794
  const { values: o } = parseArgs({
@@ -1241,7 +1332,8 @@ async function main() {
1241
1332
  return;
1242
1333
  }
1243
1334
  fail(`不认识的命令: ${cmd}`, 1, `运行 dta --help 查看全部命令${suggest(cmd, [
1244
- 'setup', 'upgrade', 'doctor', 'skill', 'bootstrap', 'init', 'prepare', 'run', 'dispatch', 'task', 'memory', 'act',
1335
+ 'setup', 'upgrade', 'doctor', 'skill', 'agent-platform', 'bootstrap', 'init', 'prepare', 'run', 'dispatch', 'task', 'memory', 'act',
1336
+ 'lab', 'listen', 'deploy', 'promote', 'observe',
1245
1337
  'agent',
1246
1338
  'info', 'workspace',
1247
1339
  ])}`);
@@ -1373,14 +1465,84 @@ function printAgentEnhance(out) {
1373
1465
  console.log(` backup=${out.backupRoot}`);
1374
1466
  console.log(` audit=${out.audit.status} missing=${out.audit.missing.join(', ') || '-'}`);
1375
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
+ }
1376
1533
  function printSkillStatus(out, action, dryRun) {
1377
1534
  const prefix = dryRun ? 'DRY-RUN' : '✅';
1378
1535
  const verb = action === 'status' ? '全局 Skill 状态' : `skill ${action}`;
1379
1536
  console.log(`${prefix} ${verb}: ${out.name}`);
1380
1537
  console.log(` manager=${out.manager} bundled=${out.bundled.skillVersion || '-'}`);
1381
1538
  console.log(` canonical=${out.canonical.path}`);
1382
- console.log(` installed=${out.canonical.exists} installedVersion=${out.canonical.installedVersion || '-'} ` +
1383
- `current=${out.canonical.current}`);
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
+ }
1384
1546
  if (out.operation)
1385
1547
  console.log(` delegated: ${out.operation.command}`);
1386
1548
  for (const client of out.clients) {
@@ -1400,12 +1562,32 @@ function printDoctor(out) {
1400
1562
  if (check.fix)
1401
1563
  console.log(` 修复: ${check.fix}`);
1402
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
+ }
1403
1578
  if (out.nextSteps.length) {
1404
1579
  console.log('\n下一步:');
1405
1580
  for (const step of out.nextSteps)
1406
1581
  console.log(` ${step}`);
1407
1582
  }
1408
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
+ }
1409
1591
  function printProjectInfo(out) {
1410
1592
  console.log(`dingtalk-agent Project · ${out.project.name}`);
1411
1593
  console.log(` root=${out.root}`);