@xdxer/dingtalk-agent 0.1.4-beta.9 → 0.1.5-beta.1

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 (129) hide show
  1. package/CHANGELOG.md +229 -0
  2. package/README.en.md +89 -324
  3. package/README.md +88 -674
  4. package/dist/bin/dingtalk-agent.js +207 -21
  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/multica-deploy.js +78 -20
  23. package/dist/src/multica-deploy.js.map +1 -1
  24. package/dist/src/multica-provider.js +1 -1
  25. package/dist/src/multica-provider.js.map +1 -1
  26. package/dist/src/opencode-evals.js +710 -225
  27. package/dist/src/opencode-evals.js.map +1 -1
  28. package/dist/src/opencode-isolation.js +124 -0
  29. package/dist/src/opencode-isolation.js.map +1 -0
  30. package/dist/src/opencode-provider.js +1 -0
  31. package/dist/src/opencode-provider.js.map +1 -1
  32. package/dist/src/opencode-workspace.js +21 -10
  33. package/dist/src/opencode-workspace.js.map +1 -1
  34. package/dist/src/remote-state-evals.js +2 -1
  35. package/dist/src/remote-state-evals.js.map +1 -1
  36. package/dist/src/robot-evals.js +2 -1
  37. package/dist/src/robot-evals.js.map +1 -1
  38. package/dist/src/setup.js +6 -5
  39. package/dist/src/setup.js.map +1 -1
  40. package/dist/src/skill-manager.js +141 -12
  41. package/dist/src/skill-manager.js.map +1 -1
  42. package/dist/src/skills.js +2 -1
  43. package/dist/src/skills.js.map +1 -1
  44. package/dist/src/types.js.map +1 -1
  45. package/dist/src/upgrade.js +23 -27
  46. package/dist/src/upgrade.js.map +1 -1
  47. package/dist/src/version.js +73 -0
  48. package/dist/src/version.js.map +1 -0
  49. package/docs/ARCHITECTURE.md +232 -0
  50. package/docs/INSTALLATION.md +3 -3
  51. package/docs/PRIOR-ART.md +122 -0
  52. package/docs/SELF-TEST.md +182 -0
  53. package/docs/assets/agent-delivery-lifecycle.svg +103 -0
  54. package/docs/schemas/agent-platform.schema.json +13 -0
  55. package/docs/schemas/project.schema.json +3 -0
  56. package/docs/schemas/release-readiness.schema.json +2 -1
  57. package/evals/README.md +17 -0
  58. package/examples/agents/README.md +43 -0
  59. package/examples/agents/fde-coach/AGENTS.md +26 -17
  60. package/examples/agents/release-manager/AGENTS.md +26 -17
  61. package/lab/README.md +3 -3
  62. package/lab/agent-eval/catalog.json +5 -5
  63. package/lab/agent-eval/classic-failures.json +9 -9
  64. package/lab/agent-eval/completion-gate-regression.json +6 -6
  65. package/lab/agent-eval/remote-state-workspace/opencode.json +1 -1
  66. package/lab/agent-eval/workspace/AGENTS.md +1 -1
  67. package/lab/project-workspace/fake-multica-provider.mjs +17 -6
  68. package/lab/project-workspace/opencode-provider-suite.json +2 -2
  69. package/lab/robot-eval/suite.json +1 -1
  70. package/lab/robot-eval/workspace/AGENTS.md +1 -1
  71. package/lab/schemas/agent-eval-catalog.schema.json +1 -1
  72. package/package.json +18 -13
  73. package/skills/README.md +23 -0
  74. package/skills/core/dingtalk-agent-compose/SKILL.md +151 -0
  75. package/skills/core/dingtalk-agent-compose/assets/AGENTS.template.md +35 -0
  76. package/skills/core/dingtalk-agent-compose/assets/role-skill.template.md +32 -0
  77. package/skills/core/dingtalk-agent-compose/evals/evals.json +129 -0
  78. package/skills/{dingtalk-agent-compose → core/dingtalk-agent-compose}/references/agent-definition-contract.md +3 -3
  79. package/skills/core/dingtalk-agent-compose/references/host-loading-contract.md +58 -0
  80. package/skills/core/dingtalk-agent-compose/references/hosts/claude-code.md +48 -0
  81. package/skills/core/dingtalk-agent-compose/references/hosts/opencode.md +77 -0
  82. package/skills/{dingtalk-agent-eval → core/dingtalk-agent-eval}/SKILL.md +57 -8
  83. package/skills/{dingtalk-agent-eval → core/dingtalk-agent-eval}/assets/eval-catalog.template.json +1 -1
  84. package/skills/{dingtalk-agent-eval → core/dingtalk-agent-eval}/evals/evals.json +22 -0
  85. package/skills/{dingtalk-agent-eval → core/dingtalk-agent-eval}/references/eval-topology.md +14 -0
  86. package/skills/{dingtalk-agent-eval → core/dingtalk-agent-eval}/references/evidence-contract.md +21 -0
  87. package/skills/core/dingtalk-agent-eval/references/failure-to-case.md +35 -0
  88. package/skills/core/dingtalk-agent-eval/references/interactive-debug-channels.md +93 -0
  89. package/skills/core/dingtalk-agent-eval/references/local-connector-smoke.md +75 -0
  90. package/skills/core/dingtalk-basic-behavior/SKILL.md +87 -0
  91. package/skills/{dingtalk-basic-behavior → core/dingtalk-basic-behavior}/references/memory-and-evolution.md +12 -0
  92. package/skills/core/dingtalk-basic-behavior/references/risk-authority-and-privacy.md +62 -0
  93. package/skills/{dingtalk-basic-behavior → core/dingtalk-basic-behavior}/references/task-lifecycle.md +15 -3
  94. package/skills/core/dingtalk-basic-behavior/references/truth-and-recovery.md +65 -0
  95. package/skills/platforms/deap/PLATFORM.md +3 -0
  96. package/skills/platforms/multica-dingtalk/PLATFORM.md +40 -0
  97. package/skills/{dingtalk-agent-boot-multica → platforms/multica-dingtalk/dingtalk-agent-boot-multica}/SKILL.md +4 -4
  98. package/skills/{dingtalk-agent-deploy → platforms/multica-dingtalk/dingtalk-agent-deploy-multica}/SKILL.md +1 -1
  99. package/skills/platforms/multica-dingtalk/multica-external/SKILL.md +282 -0
  100. package/skills/platforms/multica-dingtalk/multica-external/scripts/bootstrap.sh +78 -0
  101. package/skills/platforms/multica-dingtalk/multica-external/scripts/multica_ext.py +1180 -0
  102. package/docs/SECOND-AGENT-ACCEPTANCE.md +0 -62
  103. package/docs/architecture/agent-memory-topology.png +0 -0
  104. package/docs/architecture/agent-memory-topology.svg +0 -132
  105. package/docs/architecture/dingtalk-agent-blueprint.png +0 -0
  106. package/docs/architecture/durable-async-agent-runtime.png +0 -0
  107. package/docs/architecture/general-agent-kernel-topology.png +0 -0
  108. package/docs/architecture/provider-bound-development-workspace.png +0 -0
  109. package/docs/architecture/task-completion-gate.png +0 -0
  110. package/skills/dingtalk-agent-compose/SKILL.md +0 -110
  111. package/skills/dingtalk-agent-compose/assets/AGENTS.template.md +0 -26
  112. package/skills/dingtalk-agent-compose/assets/role-skill.template.md +0 -24
  113. package/skills/dingtalk-agent-compose/evals/evals.json +0 -94
  114. package/skills/dingtalk-agent-compose/references/opencode-host-contract.md +0 -65
  115. package/skills/dingtalk-basic-behavior/SKILL.md +0 -146
  116. /package/skills/{dingtalk-agent-compose → core/dingtalk-agent-compose}/assets/agent.bindings.dingtalk-doc.template.json +0 -0
  117. /package/skills/{dingtalk-agent-compose → core/dingtalk-agent-compose}/assets/agent.bindings.local.template.json +0 -0
  118. /package/skills/{dingtalk-agent-compose/assets → core/dingtalk-agent-compose/assets/hosts/opencode}/opencode.template.json +0 -0
  119. /package/skills/{dingtalk-agent-compose → core/dingtalk-agent-compose}/references/storage-routing.md +0 -0
  120. /package/skills/{dingtalk-agent-eval → core/dingtalk-agent-eval}/references/scenario-taxonomy.md +0 -0
  121. /package/skills/{dingtalk-agent-eval → core/dingtalk-agent-eval}/references/storage-modes.md +0 -0
  122. /package/skills/{dingtalk-basic-behavior → core/dingtalk-basic-behavior}/assets/memory-candidate-proposal.json +0 -0
  123. /package/skills/{dingtalk-basic-behavior → core/dingtalk-basic-behavior}/assets/task-checkpoint.json +0 -0
  124. /package/skills/{dingtalk-basic-behavior → core/dingtalk-basic-behavior}/references/action-contract.md +0 -0
  125. /package/skills/{dingtalk-basic-behavior → core/dingtalk-basic-behavior}/references/event-to-behavior.md +0 -0
  126. /package/skills/{dingtalk-basic-behavior → core/dingtalk-basic-behavior}/references/perception-and-gates.md +0 -0
  127. /package/skills/{dingtalk-basic-behavior → core/dingtalk-basic-behavior}/references/runtime-modes.md +0 -0
  128. /package/skills/{dingtalk-agent-deploy → platforms/multica-dingtalk/dingtalk-agent-deploy-multica}/references/multica-deployment-contract.md +0 -0
  129. /package/skills/{dingtalk-agent-deploy → platforms/multica-dingtalk/dingtalk-agent-deploy-multica}/references/promotion-observation-contract.md +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"upgrade.js","sourceRoot":"","sources":["../../src/upgrade.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync, readFileSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { delimiter, join } from 'node:path'\nimport { spawnSync } from 'node:child_process'\n\nconst PACKAGE_NAME = '@xdxer/dingtalk-agent'\nconst REGISTRY = 'https://registry.npmjs.org'\n\nexport interface UpgradeOptions {\n home?: string\n env?: NodeJS.ProcessEnv\n prefix?: string\n channel?: 'beta' | 'latest'\n version?: string\n dryRun?: boolean\n force?: boolean\n}\n\nexport interface UpgradeResult {\n $schema: 'dingtalk-agent/upgrade@1'\n currentVersion: string\n targetVersion: string\n target: string\n prefix: string\n executable: string\n changed: boolean\n dryRun: boolean\n ready: boolean\n setup: Record<string, any> | null\n commands: { install: string; verify: string }\n}\n\nexport function upgradeAgent(packageRoot: string, options: UpgradeOptions = {}): UpgradeResult {\n const home = options.home || homedir()\n const env = { ...process.env, ...(options.env || {}) }\n const pkg = JSON.parse(readFileSync(join(packageRoot, 'package.json'), 'utf8'))\n const currentVersion = String(pkg.version || '')\n const prefix = options.prefix || join(home, '.local')\n const binDir = process.platform === 'win32' ? prefix : join(prefix, 'bin')\n const executable = join(binDir, process.platform === 'win32' ? 'dta.cmd' : 'dta')\n\n if (options.channel && options.version) {\n throw new Error('upgrade 的 --channel 与 --version 不能同时使用')\n }\n const channel = options.channel || (currentVersion.includes('-') ? 'beta' : 'latest')\n if (!['beta', 'latest'].includes(channel)) {\n throw new Error(`不支持的升级通道: ${channel};只能是 beta 或 latest`)\n }\n const requested = cleanVersion(options.version) || channel\n const packageSource = env.DTA_UPGRADE_PACKAGE_SOURCE || `${PACKAGE_NAME}@${requested}`\n const targetVersion = env.DTA_UPGRADE_TARGET_VERSION || resolveTargetVersion(packageSource, env)\n if (compareVersions(targetVersion, currentVersion) < 0 && !(options.version && options.force)) {\n throw new Error(\n `升级目标 ${targetVersion} 低于当前版本 ${currentVersion},拒绝自动降级;` +\n '如确需降级,请同时使用 --version 与 --force',\n )\n }\n const installArgs = [\n 'install', '--global', '--prefix', prefix, '--registry', REGISTRY, packageSource,\n ]\n const installCommand = ['npm', ...installArgs].map(shellQuote).join(' ')\n const verifyCommand = `${shellQuote(executable)} setup --skip-cli-install`\n const changed = options.force || targetVersion !== currentVersion\n\n if (options.dryRun) {\n return {\n $schema: 'dingtalk-agent/upgrade@1', currentVersion, targetVersion,\n target: packageSource, prefix, executable, changed, dryRun: true,\n ready: false, setup: null,\n commands: { install: installCommand, verify: verifyCommand },\n }\n }\n\n if (changed) {\n const install = spawnSync('npm', installArgs, { encoding: 'utf8', env, timeout: 120_000 })\n const output = [install.stdout, install.stderr].filter(Boolean).join('\\n').trim()\n if (install.error || install.status !== 0) {\n throw new Error(\n `CLI 升级失败: ${install.error?.message || output || `退出码 ${install.status}`}\\n` +\n `可手动执行: ${installCommand}`,\n )\n }\n }\n if (!existsSync(executable)) {\n throw new Error(`npm 升级完成但找不到新 CLI: ${executable}\\n可手动执行: ${installCommand}`)\n }\n const effectiveEnv = {\n ...env,\n HOME: home,\n PATH: [binDir, env.PATH || ''].filter(Boolean).join(delimiter),\n }\n const versionRun = spawnSync(executable, ['--version'], {\n encoding: 'utf8', env: effectiveEnv, timeout: 8_000,\n })\n const installedVersion = String(versionRun.stdout || '').trim()\n if (versionRun.status !== 0 || installedVersion !== targetVersion) {\n throw new Error(\n `新 CLI 版本校验失败: expected=${targetVersion}, actual=${installedVersion || 'unknown'}\\n` +\n `可重试: ${installCommand}`,\n )\n }\n const setupRun = spawnSync(executable, ['setup', '--skip-cli-install', '--json'], {\n encoding: 'utf8', env: effectiveEnv, timeout: 180_000,\n })\n let setup: Record<string, any> | null = null\n try { setup = setupRun.stdout ? JSON.parse(setupRun.stdout) : null } catch { /* reported below */ }\n if (!setup) {\n throw new Error(\n `CLI 已升级到 ${installedVersion},但 setup 输出无法解析: ` +\n `${String(setupRun.stderr || setupRun.stdout).trim() || `退出码 ${setupRun.status}`}\\n` +\n `可手动执行: ${verifyCommand}`,\n )\n }\n return {\n $schema: 'dingtalk-agent/upgrade@1', currentVersion, targetVersion,\n target: packageSource, prefix, executable, changed, dryRun: false,\n ready: setupRun.status === 0 && setup.doctor?.ready === true,\n setup,\n commands: { install: installCommand, verify: verifyCommand },\n }\n}\n\nfunction resolveTargetVersion(packageSource: string, env: NodeJS.ProcessEnv): string {\n const run = spawnSync('npm', ['view', packageSource, 'version', '--json', '--registry', REGISTRY], {\n encoding: 'utf8', env, timeout: 30_000,\n })\n const output = String(run.stdout || '').trim()\n if (run.error || run.status !== 0) {\n throw new Error(\n `无法解析升级目标 ${packageSource}: ` +\n `${run.error?.message || String(run.stderr || '').trim() || `退出码 ${run.status}`}`,\n )\n }\n try {\n const value = JSON.parse(output)\n if (typeof value === 'string' && value) return value\n } catch { /* fall through */ }\n if (output) return output.replace(/^['\"]|['\"]$/g, '')\n throw new Error(`npm view 没有返回 ${packageSource} 的版本`)\n}\n\nfunction cleanVersion(value = ''): string {\n const clean = value.trim().replace(/^v/, '')\n if (!clean) return ''\n if (!/^\\d+\\.\\d+\\.\\d+(?:-[0-9A-Za-z.-]+)?$/.test(clean)) {\n throw new Error(`非法版本号: ${value}`)\n }\n return clean\n}\n\nfunction compareVersions(a: string, b: string): number {\n const parse = (value: string) => {\n const [core, prerelease = ''] = value.replace(/^v/, '').split('-', 2)\n return { core: core.split('.').map((part) => Number.parseInt(part, 10) || 0), prerelease }\n }\n const left = parse(a)\n const right = parse(b)\n for (let index = 0; index < 3; index += 1) {\n if ((left.core[index] || 0) !== (right.core[index] || 0)) {\n return (left.core[index] || 0) > (right.core[index] || 0) ? 1 : -1\n }\n }\n if (!left.prerelease && right.prerelease) return 1\n if (left.prerelease && !right.prerelease) return -1\n return left.prerelease.localeCompare(right.prerelease, undefined, { numeric: true })\n}\n\nfunction shellQuote(value: string): string {\n return /^[A-Za-z0-9_./:=@\"$-]+$/.test(value) ? value : `'${value.replace(/'/g, `'\"'\"'`)}'`\n}\n"]}
1
+ {"version":3,"file":"upgrade.js","sourceRoot":"","sources":["../../src/upgrade.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync, readFileSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { delimiter, join } from 'node:path'\nimport { spawnSync } from 'node:child_process'\nimport { cleanVersion, compareVersions } from './version.js'\nimport { skillSuiteStatus } from './skill-manager.js'\n\nconst PACKAGE_NAME = '@xdxer/dingtalk-agent'\nconst REGISTRY = 'https://registry.npmjs.org'\n\nexport interface UpgradeOptions {\n home?: string\n env?: NodeJS.ProcessEnv\n prefix?: string\n channel?: 'beta' | 'latest'\n version?: string\n dryRun?: boolean\n force?: boolean\n}\n\nexport interface UpgradeResult {\n $schema: 'dingtalk-agent/upgrade@1'\n currentVersion: string\n targetVersion: string\n target: string\n prefix: string\n executable: string\n changed: boolean\n dryRun: boolean\n ready: boolean\n setup: Record<string, any> | null\n skills: UpgradeSkillReport[]\n commands: { install: string; verify: string }\n}\n\n/** 升级前后各 Skill 的版本核对;`after` 为 null 表示 dry-run 尚未执行。 */\nexport interface UpgradeSkillReport {\n name: string\n before: string\n after: string | null\n bundled: string\n state: string\n changed: boolean\n}\n\nexport function upgradeAgent(packageRoot: string, options: UpgradeOptions = {}): UpgradeResult {\n const home = options.home || homedir()\n const env = { ...process.env, ...(options.env || {}) }\n const pkg = JSON.parse(readFileSync(join(packageRoot, 'package.json'), 'utf8'))\n const currentVersion = String(pkg.version || '')\n const prefix = options.prefix || join(home, '.local')\n const binDir = process.platform === 'win32' ? prefix : join(prefix, 'bin')\n const executable = join(binDir, process.platform === 'win32' ? 'dta.cmd' : 'dta')\n // 升级前先冻结本机 Skill 版本,否则重装之后无从核对到底动了什么。\n const skillsBefore = skillSuiteStatus(packageRoot, { home }).skills\n\n if (options.channel && options.version) {\n throw new Error('upgrade 的 --channel 与 --version 不能同时使用')\n }\n const channel = options.channel || (currentVersion.includes('-') ? 'beta' : 'latest')\n if (!['beta', 'latest'].includes(channel)) {\n throw new Error(`不支持的升级通道: ${channel};只能是 beta 或 latest`)\n }\n const requested = cleanVersion(options.version) || channel\n const packageSource = env.DTA_UPGRADE_PACKAGE_SOURCE || `${PACKAGE_NAME}@${requested}`\n const targetVersion = env.DTA_UPGRADE_TARGET_VERSION || resolveTargetVersion(packageSource, env)\n if (compareVersions(targetVersion, currentVersion) < 0 && !(options.version && options.force)) {\n throw new Error(\n `升级目标 ${targetVersion} 低于当前版本 ${currentVersion},拒绝自动降级;` +\n '如确需降级,请同时使用 --version 与 --force',\n )\n }\n const installArgs = [\n 'install', '--global', '--prefix', prefix, '--registry', REGISTRY, packageSource,\n ]\n const installCommand = ['npm', ...installArgs].map(shellQuote).join(' ')\n const verifyCommand = `${shellQuote(executable)} setup --skip-cli-install`\n const changed = options.force || targetVersion !== currentVersion\n\n if (options.dryRun) {\n return {\n $schema: 'dingtalk-agent/upgrade@1', currentVersion, targetVersion,\n target: packageSource, prefix, executable, changed, dryRun: true,\n ready: false, setup: null,\n skills: skillsBefore.map((item) => ({\n name: item.name,\n before: item.canonical.installedVersion,\n after: null,\n bundled: item.bundled.skillVersion,\n state: item.canonical.state,\n changed: item.canonical.state !== 'current',\n })),\n commands: { install: installCommand, verify: verifyCommand },\n }\n }\n\n if (changed) {\n const install = spawnSync('npm', installArgs, { encoding: 'utf8', env, timeout: 120_000 })\n const output = [install.stdout, install.stderr].filter(Boolean).join('\\n').trim()\n if (install.error || install.status !== 0) {\n throw new Error(\n `CLI 升级失败: ${install.error?.message || output || `退出码 ${install.status}`}\\n` +\n `可手动执行: ${installCommand}`,\n )\n }\n }\n if (!existsSync(executable)) {\n throw new Error(`npm 升级完成但找不到新 CLI: ${executable}\\n可手动执行: ${installCommand}`)\n }\n const effectiveEnv = {\n ...env,\n HOME: home,\n PATH: [binDir, env.PATH || ''].filter(Boolean).join(delimiter),\n }\n const versionRun = spawnSync(executable, ['--version'], {\n encoding: 'utf8', env: effectiveEnv, timeout: 8_000,\n })\n const installedVersion = String(versionRun.stdout || '').trim()\n if (versionRun.status !== 0 || installedVersion !== targetVersion) {\n throw new Error(\n `新 CLI 版本校验失败: expected=${targetVersion}, actual=${installedVersion || 'unknown'}\\n` +\n `可重试: ${installCommand}`,\n )\n }\n const setupRun = spawnSync(executable, ['setup', '--skip-cli-install', '--json'], {\n encoding: 'utf8', env: effectiveEnv, timeout: 180_000,\n })\n let setup: Record<string, any> | null = null\n try { setup = setupRun.stdout ? JSON.parse(setupRun.stdout) : null } catch { /* reported below */ }\n if (!setup) {\n throw new Error(\n `CLI 已升级到 ${installedVersion},但 setup 输出无法解析: ` +\n `${String(setupRun.stderr || setupRun.stdout).trim() || `退出码 ${setupRun.status}`}\\n` +\n `可手动执行: ${verifyCommand}`,\n )\n }\n return {\n $schema: 'dingtalk-agent/upgrade@1', currentVersion, targetVersion,\n target: packageSource, prefix, executable, changed, dryRun: false,\n ready: setupRun.status === 0 && setup.doctor?.ready === true,\n setup,\n skills: skillsBefore.map((item) => {\n const after = (setup?.skills || []).find((entry: any) => entry?.name === item.name)\n return {\n name: item.name,\n before: item.canonical.installedVersion,\n after: after?.canonical?.installedVersion ?? null,\n bundled: after?.bundled?.skillVersion ?? item.bundled.skillVersion,\n state: after?.canonical?.state ?? 'unknown',\n changed: (after?.canonical?.installedVersion ?? '') !== item.canonical.installedVersion,\n }\n }),\n commands: { install: installCommand, verify: verifyCommand },\n }\n}\n\nfunction resolveTargetVersion(packageSource: string, env: NodeJS.ProcessEnv): string {\n const run = spawnSync('npm', ['view', packageSource, 'version', '--json', '--registry', REGISTRY], {\n encoding: 'utf8', env, timeout: 30_000,\n })\n const output = String(run.stdout || '').trim()\n if (run.error || run.status !== 0) {\n throw new Error(\n `无法解析升级目标 ${packageSource}: ` +\n `${run.error?.message || String(run.stderr || '').trim() || `退出码 ${run.status}`}`,\n )\n }\n try {\n const value = JSON.parse(output)\n if (typeof value === 'string' && value) return value\n } catch { /* fall through */ }\n if (output) return output.replace(/^['\"]|['\"]$/g, '')\n throw new Error(`npm view 没有返回 ${packageSource} 的版本`)\n}\n\nfunction shellQuote(value: string): string {\n return /^[A-Za-z0-9_./:=@\"$-]+$/.test(value) ? value : `'${value.replace(/'/g, `'\"'\"'`)}'`\n}\n"]}
@@ -0,0 +1,73 @@
1
+ // 版本号解析与比较。npm 包版本与 Skill frontmatter 版本共用同一实现,避免两套排序规则。
2
+ // 比较结果只用于报告与门禁,不用于跳过执行:安装/升级始终由上游 skills CLI 无条件覆盖。
3
+ /** 归一化版本号;空串表示"未声明",非法格式直接抛错。 */
4
+ export function cleanVersion(value = '') {
5
+ const clean = value.trim().replace(/^v/, '');
6
+ if (!clean)
7
+ return '';
8
+ if (!/^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/.test(clean)) {
9
+ throw new Error(`非法版本号: ${value}`);
10
+ }
11
+ return clean;
12
+ }
13
+ /** 版本号是否合法且非空。用于把"用户手改坏了"与"格式正确"分开处理。 */
14
+ export function isValidVersion(value = '') {
15
+ try {
16
+ return Boolean(cleanVersion(value));
17
+ }
18
+ catch {
19
+ return false;
20
+ }
21
+ }
22
+ /**
23
+ * semver 比较:core 三段按数值,prerelease 按 dot-identifier 逐段。
24
+ * 数字段按数值比较,数字段低于非数字段,段数少者在前缀相同时更小(semver §11)。
25
+ */
26
+ export function compareVersions(a, b) {
27
+ const parse = (value) => {
28
+ const [core, prerelease = ''] = value.replace(/^v/, '').split('-', 2);
29
+ return { core: core.split('.').map((part) => Number.parseInt(part, 10) || 0), prerelease };
30
+ };
31
+ const left = parse(a);
32
+ const right = parse(b);
33
+ for (let index = 0; index < 3; index += 1) {
34
+ if ((left.core[index] || 0) !== (right.core[index] || 0)) {
35
+ return (left.core[index] || 0) > (right.core[index] || 0) ? 1 : -1;
36
+ }
37
+ }
38
+ // 有 prerelease 者小于无 prerelease 者。
39
+ if (!left.prerelease && right.prerelease)
40
+ return 1;
41
+ if (left.prerelease && !right.prerelease)
42
+ return -1;
43
+ if (!left.prerelease && !right.prerelease)
44
+ return 0;
45
+ return comparePrerelease(left.prerelease, right.prerelease);
46
+ }
47
+ function comparePrerelease(a, b) {
48
+ const left = a.split('.');
49
+ const right = b.split('.');
50
+ for (let index = 0; index < Math.max(left.length, right.length); index += 1) {
51
+ const l = left[index];
52
+ const r = right[index];
53
+ if (l === undefined)
54
+ return -1;
55
+ if (r === undefined)
56
+ return 1;
57
+ const lNumeric = /^\d+$/.test(l);
58
+ const rNumeric = /^\d+$/.test(r);
59
+ if (lNumeric && rNumeric) {
60
+ const diff = Number.parseInt(l, 10) - Number.parseInt(r, 10);
61
+ if (diff !== 0)
62
+ return diff > 0 ? 1 : -1;
63
+ continue;
64
+ }
65
+ // 数字段永远低于非数字段。
66
+ if (lNumeric !== rNumeric)
67
+ return lNumeric ? -1 : 1;
68
+ if (l !== r)
69
+ return l > r ? 1 : -1;
70
+ }
71
+ return 0;
72
+ }
73
+ //# sourceMappingURL=version.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version.js","sourceRoot":"","sources":["../../src/version.ts"],"names":[],"mappings":"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","sourcesContent":["// 版本号解析与比较。npm 包版本与 Skill frontmatter 版本共用同一实现,避免两套排序规则。\n// 比较结果只用于报告与门禁,不用于跳过执行:安装/升级始终由上游 skills CLI 无条件覆盖。\n\n/** 归一化版本号;空串表示\"未声明\",非法格式直接抛错。 */\nexport function cleanVersion(value = ''): string {\n const clean = value.trim().replace(/^v/, '')\n if (!clean) return ''\n if (!/^\\d+\\.\\d+\\.\\d+(?:-[0-9A-Za-z.-]+)?$/.test(clean)) {\n throw new Error(`非法版本号: ${value}`)\n }\n return clean\n}\n\n/** 版本号是否合法且非空。用于把\"用户手改坏了\"与\"格式正确\"分开处理。 */\nexport function isValidVersion(value = ''): boolean {\n try { return Boolean(cleanVersion(value)) } catch { return false }\n}\n\n/**\n * semver 比较:core 三段按数值,prerelease 按 dot-identifier 逐段。\n * 数字段按数值比较,数字段低于非数字段,段数少者在前缀相同时更小(semver §11)。\n */\nexport function compareVersions(a: string, b: string): number {\n const parse = (value: string) => {\n const [core, prerelease = ''] = value.replace(/^v/, '').split('-', 2)\n return { core: core.split('.').map((part) => Number.parseInt(part, 10) || 0), prerelease }\n }\n const left = parse(a)\n const right = parse(b)\n for (let index = 0; index < 3; index += 1) {\n if ((left.core[index] || 0) !== (right.core[index] || 0)) {\n return (left.core[index] || 0) > (right.core[index] || 0) ? 1 : -1\n }\n }\n // 有 prerelease 者小于无 prerelease 者。\n if (!left.prerelease && right.prerelease) return 1\n if (left.prerelease && !right.prerelease) return -1\n if (!left.prerelease && !right.prerelease) return 0\n return comparePrerelease(left.prerelease, right.prerelease)\n}\n\nfunction comparePrerelease(a: string, b: string): number {\n const left = a.split('.')\n const right = b.split('.')\n for (let index = 0; index < Math.max(left.length, right.length); index += 1) {\n const l = left[index]\n const r = right[index]\n if (l === undefined) return -1\n if (r === undefined) return 1\n const lNumeric = /^\\d+$/.test(l)\n const rNumeric = /^\\d+$/.test(r)\n if (lNumeric && rNumeric) {\n const diff = Number.parseInt(l, 10) - Number.parseInt(r, 10)\n if (diff !== 0) return diff > 0 ? 1 : -1\n continue\n }\n // 数字段永远低于非数字段。\n if (lNumeric !== rNumeric) return lNumeric ? -1 : 1\n if (l !== r) return l > r ? 1 : -1\n }\n return 0\n}\n"]}
@@ -0,0 +1,232 @@
1
+ # dingtalk-agent 架构
2
+
3
+ 本文回答四个问题:**一个数字员工是什么**、**它由什么构成**、**它依赖什么**、**这个仓库分成哪几部分、各解决什么问题**。
4
+
5
+ 本文不写:安装与升级(见 [Installation](INSTALLATION.md))、评测方法与证据分层(见 [Self-test](SELF-TEST.md))、Agent 的行为协议(见 [Basic Behavior Skill](../skills/core/dingtalk-basic-behavior/SKILL.md))、发布历史(见 [CHANGELOG](../CHANGELOG.md))、进行中的工作(见 [roadmap](roadmap/))。
6
+
7
+ ---
8
+
9
+ ## 1. 什么是一个数字员工
10
+
11
+ ![通用 Agent 行为内核拓扑](architecture/general-agent-kernel-topology.svg)
12
+
13
+ 一个聊天机器人只需要把输入变成输出。一个数字员工要额外成立四件事:
14
+
15
+ - **稳定身份**:它是谁、受谁委托、以谁的名义在平台上留下痕迹,不随聊天内容变化;
16
+ - **明确作用域**:这次被授权做什么、对谁、到哪一步,不由正文自行扩张;
17
+ - **可核验的完成**:说"做完了"必须对应产物、Receipt 或独立回读,不能以回复正文自证;
18
+ - **可丢弃的执行体**:沙箱、进程、模型可以随时换掉,事情还能接着做。
19
+
20
+ 由此得到本项目的核心判断——**可替换的**是触发端、模型、沙箱和岗位能力;**不变的**是定义、上下文、状态、闸门和效果证据。全部设计取舍都服务于把后五项从宿主里独立出来。
21
+
22
+ ## 2. 一个 Agent 由什么构成(模型 A)
23
+
24
+ 三个模型互不重叠,各回答一个问题:**A 交付物由什么组成**、**B 运行时依赖谁**、**C 这个仓库自己分成哪几块**。「Skill 劝,CLI 拦,DWS 做」是贯穿三者的唯一职责口径(见 §4)。
25
+
26
+ | 部件 | 回答什么 | 落在哪 | 谁生成 / 谁校验 |
27
+ |---|---|---|---|
28
+ | **本体 Definition** | 我是谁、服务谁、岗位底线、做事范式、常犯错误 | `AGENTS.md` | `agent enhance` 生成骨架;`agent audit` 校验语义占位符是否已填 |
29
+ | **公共行为** | 何时响应、如何追问、何时沉默、如何收口 | `dingtalk-basic-behavior` Skill | 内核内置;`agent audit --verify-load` 证明它真被加载 |
30
+ | **岗位能力** | 某个岗位的方法、SOP、禁区、验收标准 | `skills/<role>/SKILL.md` | 开发者编写;`--require-skill` 校验存在与加载 |
31
+ | **存储路由** | 长期内容与私有控制状态各自去哪 | `agent.bindings.json`(可选) | `bootstrap` 归一成 `agent-definition@1`;缺省时按宿主 context > 环境变量 > Workspace manifest > 目录约定依次解析 |
32
+
33
+ 这四项不是设计出来的分类,而是从 `agent-definition@1` 直接读出来的字段(`src/agent-definition.ts`)。一个 Agent 的最小目录形态:
34
+
35
+ ```text
36
+ my-agent/
37
+ ├── AGENTS.md 本体:角色宪法 + Basic 继承锚点
38
+ ├── agent.bindings.json 存储路由与 DWS authority(可选,见下)
39
+ ├── skills/<role>/SKILL.md 岗位能力的版本化来源
40
+ ├── .agents/skills/ Host 可发现的 Skill 物化位置
41
+ └── .dingtalk-agent/ 私有状态、证据与 Receipt(gitignored)
42
+ ```
43
+
44
+ "文件存在"不是继承证据。`agent audit --verify-load` 把真实加载结果绑定到 Definition/Skill hash、Host 与模型版本、隔离探针和原始 run/export;任何一项漂移,旧证据即失效。
45
+
46
+ ## 3. 一个 Agent 依赖什么(模型 B)
47
+
48
+ 这四样本仓库都**不拥有**,但都必须显式建模,否则边界会悄悄溜走:
49
+
50
+ | 依赖 | 提供什么 | 本仓库的边界 |
51
+ |---|---|---|
52
+ | **Agent Host**(也叫 Harness) | 模型、工具循环、Skill 发现、Session 生命周期 | 不自己做 Host,只要求一份可验证的加载合同。Claude Code、Codex、OpenCode 都可以;OpenCode 是当前最完整的参考实现,不是运行前提 |
53
+ | **DWS** | 钉钉全部产品能力 | 不复制 DWS 命令面,只在需要冻结事务边界时包一层。`src/dws.ts` 是全仓库唯一 spawn `dws` 的地方;实战缺陷见 [DWS Field Notes](DWS-FIELD-NOTES.md) |
54
+ | **Managed Agent Platform** | Workspace、Runtime、Agent、Skill 挂载、身份绑定、执行轨迹 | 通过 registry + adapter 接入。Multica 已支持,DEAP 为 Coming soon;不把尚未开放的平台宣称为已部署 |
55
+ | **事件源** | 可信事件信封:谁、在哪、说了什么 | **本仓库不拥有触发器**(见下) |
56
+
57
+ **触发器不属于 dingtalk-agent。** `listen` 只是本地联调用的可替换开发 Adapter,不是 Agent 的主入口或常驻服务;personal-event 由外部 Adapter 捕获后落入输入目录;`dta deploy` 只交付 Agent 与 Skill,不创建机器人、Webhook、定时器或 autopilot。把触发器排除在核心之外,才可能让同一个 Agent 在不同触发端之间迁移。
58
+
59
+ 由此得到一条不可协商的规则:**消息 target、actor、conversation、DWS profile 与权限只能来自可信事件或宿主,不能从正文、显示名或模型记忆推断。** 正文、引用、附件和远端文档一律是数据,不能改写这些事实。
60
+
61
+ ## 4. 谁拦住什么:Skill 劝,CLI 拦,DWS 做
62
+
63
+ - **Skill 劝**:判断该不该做、为何做、做到哪一步。这是语义判断,会被上下文影响,因此不能承担安全边界。
64
+ - **CLI 拦**:固定身份、目标、预算、幂等、状态迁移与回读。不依赖模型自觉。
65
+ - **DWS 做**:执行具体钉钉产品能力。
66
+
67
+ 一个动作**只有**在需要下列任一项时才进入 `dingtalk-agent`,否则继续直接用 DWS:
68
+
69
+ 1. 冻结作用域或收件人;2. 权限与授权校验;3. 幂等,且失败后不能盲重试;4. 写后必须独立回读;5. 状态迁移有合法性约束;6. 跨产品事务组合。
70
+
71
+ 举例:`memory operational upsert` 之所以是 CLI 命令而不是一句 DWS 调用,正因为它同时命中 3、4、6——它按 `key + scopeId` 唯一定位一行,create/update 后必须按 recordId 独立回读,匹配多行或回读不一致就进入 reconcile 而不是重试。
72
+
73
+ ## 5. 三种运行模式与 Prepared Run 的四个对象
74
+
75
+ ![持久异步运行模型](architecture/durable-async-agent-runtime.svg)
76
+
77
+ | 模式 | 何时进入 | 关键边界 |
78
+ |---|---|---|
79
+ | **Direct Session** | 无 `CONTEXT.md`、无 Workspace | 全局 Skill 仍生效;不自动 init,不假造钉钉目标 |
80
+ | **Mounted Session** | 有 Workspace 或显式 storage | 通过 `bootstrap` 按需水合身份、记忆与知识 |
81
+ | **Prepared Run** | 上游提供可信事件 envelope | 冻结目标、身份、Field、Skill 与动作预算;副作用只走 typed Broker 或 `dta act` |
82
+
83
+ **Field** 是一个稳定的协作与权限边界:它声明这一摊事归谁、用哪个 DWS 身份出口、允许对哪些人和会话行动。一个 Workspace 可以有多个 Field;Session 创建时从中取走冻结副本,正文和在线 Run 都改不了它。默认模板见 `templates/fields/default/field.json`。
84
+
85
+ 三种模式的判定顺序与检测流程由 [Basic Behavior](../skills/core/dingtalk-basic-behavior/SKILL.md) 拥有;`init` 与 `bootstrap`、`setup` 的分工见 [Installation](INSTALLATION.md)。
86
+
87
+ Prepared Run 只有四个公开对象:
88
+
89
+ | 对象 | 生命周期 | 物理形态 | 作用 |
90
+ |---|---|---|---|
91
+ | Workspace | 长期、可选 | 一个目录或远端语义挂载 | 身份、内容、Field 和 Skill 清单 |
92
+ | Session | 一件事 | `.dingtalk-agent/sessions/.../<sessionId>` | 工作记忆、Skill 绑定、跨消息延续 |
93
+ | Run | 一次信号 | `Session/runs/<runId>` | 冻结输入;每次可启动新沙箱 |
94
+ | Action | 一次效果 | intent + attempt + receipt | `ack` / `reply` / `ask` / `silence` |
95
+
96
+ 四个动作的语义、何时用哪一个,由 Basic Behavior 拥有,本文不复述。Wait、Event Journal、dispatch outbox 和 reply target 是宿主内部实现,不要求 Agent 学习。
97
+
98
+ **Task checkpoint 是 Session 的可选业务投影,不是第五个控制对象。** 只在跨 Run、等待依赖、已产生副作用或需要换手时创建;Prepared Run 写 `$DTA_SESSION/memory/task.json`,用 revision CAS 加 durable lease 防并发覆盖,原子写后必须回读。它不接管锁、事件去重或 Receipt。
99
+
100
+ 与异步进程模型的对应关系:
101
+
102
+ | 进程隐喻 | 实体 |
103
+ |---|---|
104
+ | Heap | Field/Workspace 的身份、知识、Skill |
105
+ | Stack | Session working memory 与事项状态 |
106
+ | 一次函数调用 | Run |
107
+ | syscall | Action |
108
+ | await continuation | 宿主内部 Wait |
109
+ | interrupt | 新事件、心跳、显式取消 |
110
+
111
+ `ask` 之后当前 Run 结束、沙箱释放;匹配事件产生新 Run 并回到原 Session。系统恢复的是显式 checkpoint 和外部成果,不序列化 JavaScript/LLM 隐藏栈。
112
+
113
+ 一个具体读法——FDE 教练实例:
114
+
115
+ | 对象 | 在 FDE 教练里是什么 |
116
+ |---|---|
117
+ | Workspace | 菲迪身份、评价原则、学员资料 |
118
+ | Role Skill | 生成评价、等待确认、调整、发布的方法 |
119
+ | Session | "给张三本轮评价并等确认"这一件事 |
120
+ | Run | 每条新信号唤醒的一次沙箱 |
121
+ | Action | 收到、回复、追问、沉默 |
122
+
123
+ FDE 的评价模板和发布流程不进入全局 Basic Behavior;否则任何钉钉员工都会被污染成教练。
124
+
125
+ ### 双半闸门
126
+
127
+ Response Gate 是**生成前**的安全半闸门:mention/DM 获得处理 origin 的资格,ambient group 固定 silent,heartbeat 只 inspect。Perception Enricher 是**贴心**半闸门——所谓"贴心"是指补齐 Agent 本该看见的现场(而不是放宽权限):宿主可提供可信 quote、recent messages 和 identity,内核按 conversation/actor/时间窗验证后生成 `EnrichedInvocation`;缺失、越界和截断必须显式记录。
128
+
129
+ 同一 eventId 的 perception input hash 是 durable 路由的一部分,重放时不能变化。Run 中的 `response-gate.json` 与 `enriched-invocation.json` 都进入 event-index 权威快照,Action Gate 产生副作用前复验。identity 的姓名、部门、职务只用于语境,权限仍取 Invocation/Definition 的可信 ID。
130
+
131
+ ## 6. 语义内容与控制状态必须分开
132
+
133
+ | 可放 Markdown / 钉钉文档 | 必须留在宿主 state store |
134
+ |---|---|
135
+ | 身份、长期记忆、知识、Skill 候选、业务 task checkpoint | EventIndex、Wait、锁、generation、幂等键、Action intent/receipt |
136
+
137
+ **Why:Markdown 没有可靠 CAS。** 请求超时也不能证明写失败,因此它不能承担并发控制。这是本仓库文档中该规则的唯一出处;违反它的表现形式包括把钉钉文档当锁、当幂等存储或当 Receipt。
138
+
139
+ 公开 Storage Provider:
140
+
141
+ ```text
142
+ local-dir:<path> 直接挂载已有目录,不复制
143
+ local-md:<path> Workspace manifest 的单文件挂载
144
+ dingtalk-doc:<node-or-url> DWS 拉取在线文档的只读快照
145
+ ```
146
+
147
+ 远端文档先用 `doc info` probe,只有 `ALIDOC/adoc` 才用 `doc read` 拉为隐藏只读快照。`bootstrap` 用 Storage canonical identity 派生内部 `scopeId`;`contextId` 只保留为 Prepared Run 的兼容字段。
148
+
149
+ ## 7. dingtalk-agent 分成哪几部分(模型 C)
150
+
151
+ 这是一个**划分**而不是叙事:`src/` 的每个文件各归一处,没有重叠也没有遗漏。行数为近似值,用于表达重心分布。
152
+
153
+ | 部分 | 解决什么问题 | `src/` 模块 | 主要 CLI | 关联 Skill | ≈行数 |
154
+ |---|---|---|---|---|---|
155
+ | **1 行为内核** | 把一个外部事件变成"能不能回应、回应给谁、这次允许做什么"的确定性判断,并保证同一事件不被处理两次 | `events` `invocation` `perception` `response-gate` `sessions` `waits` `actions` `fields` `config` `lease` `driver` `workspace` `skills` `types` | `prepare` `run` `dispatch` `act` `listen` | — | 4.0k |
156
+ | **2 装配与审计** | 让一个仓库、文件夹或钉钉文档变成可 hash、可继承的 Agent,并证明 Skill 真被加载而不只是文件存在 | `agent-definition` `agent-bindings` `bootstrap` `agent-audit` `agent-enhance` `instruction-path` | `bootstrap` `agent enhance` `agent audit` `info` | `dingtalk-agent-compose` | 3.4k |
157
+ | **3 交付链** | 把本地通过的版本,在不改身份和权限的前提下受控放上托管平台,每一步都能独立回读 | `development-workspace` `opencode-*` `multica-*` `promotion` `agent-platform` | `agent-platform` `workspace *` `deploy` `promote` `observe` | multica 平台包 ×3 | 6.4k |
158
+ | **4 评测与证据** | 在花钱、外发和上线之前,用最低成本的层级证明它真会做事;失败沉淀成可复跑场景而不是一次口头修正 | `lab` `robot-evals` `opencode-evals` `remote-state-evals` `remote-semantic-state-*` `personal-event-evals` `storage-evals` `eval-evidence` | `lab *` `workspace eval` | `dingtalk-agent-eval` | 6.2k |
159
+ | **5 状态与记忆** | 让 Run 崩了、沙箱没了、进程换了之后,事情还能接着做;同时不让 Markdown 承担它承担不了的并发控制 | `memory/*` | `task show/checkpoint` `memory operational` `memory candidate` | — | 2.6k |
160
+ | **6 机器与分发** | 一台新机器一条命令拿到 CLI、PATH、DWS 检查和 core Skill 套装,升级不产生第二份副本;并探测本机有哪些 Coding Agent Host 以及 Skill 对它们是否可见 | `setup` `doctor` `host-detect` `upgrade` `init` `skill-manager` `version` `package-root` | `setup` `doctor` `upgrade` `skill *` `init` | — | 1.4k |
161
+ | **平台适配** | 全仓库唯一 spawn `dws` 的地方 | `dws` | — | — | 0.5k |
162
+
163
+ 重心分布本身是个结论:交付链与评测各占约四分之一,合计超过一半。这个项目的难点从来不是"让模型说话",而是**证明它真的装好了、真的做对了、真的上线了**。
164
+
165
+ 两处接缝值得诚实标注,不糊弄过去:
166
+
167
+ - `init.ts` 按模块归第 6 部分,但 CLI `init` 是第 1 部分的可选前置——机器安装与 Workspace 初始化是两件事。
168
+ - 模型 A 的"公共行为"是**交付物**,不是本仓库的一个部分。它以 Skill 形式随包分发,由第 6 部分安装、第 2 部分校验加载、第 4 部分回归。这正是过去两张"四层表"打架的根因:一个在数交付物,一个在数代码分工。
169
+
170
+ 各部分的模块依赖由 TypeScript import 关系直接表达,不在此维护一张会漂移的手绘边图。
171
+
172
+ ## 8. 从定义到上线
173
+
174
+ | 阶段 | 关键产物 | 门禁 |
175
+ |---|---|---|
176
+ | **创建** | `AGENTS.md`、Basic、Role Skills、bindings | 占位符未补全时保持 `partial` |
177
+ | **测试** | 隔离 Workspace、load probe、行为评测、多面证据 | Definition/Skills 没有真实加载就不能 ready |
178
+ | **发布** | 平台预检、部署 Receipt、远端 readback | 指定 Eval 未通过或身份链不完整就不能 promote |
179
+ | **运行** | 数字员工账号或机器人入口、task trace | 无证据不声称写入、送达或完成 |
180
+
181
+ Agent Project 与 Development Workspace 的基数关系:
182
+
183
+ ```text
184
+ 1 Agent Project ── 0..N Development Workspaces
185
+ 1 Workspace ── 1 Host Provider
186
+ 1 Workspace ── N Storage Bindings
187
+ 1 Workspace ── 0..N Sessions ── 0..N Runs
188
+ ```
189
+
190
+ `dingtalk-agent.json` 是进入 Git 的期望状态;`.dingtalk-agent/state/workspaces/<name>.json` 是 Provider 回读事实。Secret、Token、cookie 和凭据不得进入任何一层,环境字段只保留 `env:VAR` 来源。
191
+
192
+ **Host Provider 与 Storage Provider 正交**:OpenCode/Multica 决定"在哪里运行",`local-md`/`local-dir`/`dingtalk-doc` 决定"语义内容放在哪里"。因此缺少某个平台 CLI 只会让对应 Workspace 变 `partial`,不会污染其它 Workspace;state 中 Provider 与声明不一致、desired hash 漂移或非 ready 状态则一律 fail closed。
193
+
194
+ 所有远端写入都需要明确目标、当前 `planId` 和显式确认;所有计划默认零写入。设计推演见 [Provider-bound Development Workspace](roadmap/provider-bound-development-workspace.md)。
195
+
196
+ ## 9. Agent 如何演进:只产生候选,不热改
197
+
198
+ 在线 Run 可以提出候选,但**不能热修改身份、权限、已启用 Skill 或当前 Run 的策略**。这条规则在本仓库有两个同形状的实现,它们共享同一套治理结构:
199
+
200
+ | 通道 | 谁提出 | 落到哪 | 谁决定 |
201
+ |---|---|---|---|
202
+ | `memory candidate` | 在线 Run 从一次纠正中提取 | 绑定 scope/Run/Event/Definition hash 的候选 | 离线 reviewer,用 revision CAS approve/reject |
203
+ | `dta observe` | 已 promote 的部署反馈 | gitignored、`proposed`、不可直接发布的 eval candidate | 人工评审后才可能进入 Eval suite |
204
+
205
+ 两者都:只写候选、不改本体;都要求 provenance 与 scope;都用 revision CAS 或 expected hash 防止评审期间目标漂移;发布后都只影响**后续新 Session**,不改变当前 Run。
206
+
207
+ 本地/Git 发布使用 target expected hash、durable lease、原子替换和回读,CLI 不自动 commit/push。钉钉文档只追加唯一 marker 并全文回读——因为 Markdown 没有可靠 CAS(§6),其回执必须显式声明 `best-effort-read-check-append` 的并发语义。
208
+
209
+ ## 10. 当前明确不做
210
+
211
+ - 不把 `listen` 或任何触发器做成 Agent 主进程;
212
+ - 不自动 init 任意代码仓库;
213
+ - 不把整个 DWS 复制成另一套 CLI;
214
+ - 不把钉钉文档当锁或事务数据库;
215
+ - 不序列化语言运行时栈;
216
+ - 不允许在线 Run 自动扩大身份、权限或启用 Skill;
217
+ - 不把本项目变成巨型 Prompt。
218
+
219
+ ## 11. 延伸阅读
220
+
221
+ | 想做什么 | 去哪 |
222
+ |---|---|
223
+ | 安装、升级与排障 | [Installation](INSTALLATION.md) |
224
+ | 评测方法、证据分层与晋级门禁 | [Self-test](SELF-TEST.md) |
225
+ | 创建或审计一个 Agent | [Compose Skill](../skills/core/dingtalk-agent-compose/SKILL.md) |
226
+ | 测试或调试已交付的 Agent | [Eval Skill](../skills/core/dingtalk-agent-eval/SKILL.md) |
227
+ | 公共行为协议本身 | [Basic Behavior Skill](../skills/core/dingtalk-basic-behavior/SKILL.md) |
228
+ | DWS 与钉钉 API 的实战缺陷 | [DWS Field Notes](DWS-FIELD-NOTES.md) |
229
+ | 借鉴了哪些开源项目、各自取了什么 | [Prior Art](PRIOR-ART.md) |
230
+ | 尚未完成的工作 | [roadmap](roadmap/) |
231
+
232
+ 在本仓库工作的 Coding Agent 请先读 [AGENTS.md](../AGENTS.md),验证命令以那里为准。
@@ -69,7 +69,7 @@ npm 全局命令会被链接到 `{prefix}/bin`,但不同 Node 版本管理器
69
69
  npm install → dta setup
70
70
  → 安装当前版本到 ~/.local/bin
71
71
  → 检查并幂等补充 ~/.zshrc / ~/.bashrc PATH
72
- → 安装 canonical Basic Behavior Skill
72
+ → 安装 canonical 内置 Skill(Basic Behavior、Compose、Eval)
73
73
  → 暴露给 Claude Code,验证 Codex/OpenCode 共享发现
74
74
  → 检查 DWS 版本和认证
75
75
  → 给出唯一下一条命令
@@ -124,7 +124,7 @@ dws auth login
124
124
 
125
125
  ```bash
126
126
  npx --yes --registry=https://registry.npmjs.org --package=skills@latest -- skills add \
127
- <package>/skills/dingtalk-basic-behavior \
127
+ <package>/skills/core/dingtalk-basic-behavior \
128
128
  --global --yes --agent claude-code codex opencode
129
129
  ```
130
130
 
@@ -159,7 +159,7 @@ npx skills add D1-2004/dingtalk-agent \
159
159
  --agent claude-code --agent codex --agent opencode
160
160
 
161
161
  # 本地 checkout
162
- npx skills add ./skills/dingtalk-basic-behavior \
162
+ npx skills add ./skills/core/dingtalk-basic-behavior \
163
163
  --global --yes --agent claude-code --agent codex --agent opencode
164
164
  ```
165
165
 
@@ -0,0 +1,122 @@
1
+ # 开源蓝本的差异、共同点与迁移决策
2
+
3
+ 调研最初基于 2026-07-14 各仓库源码,并在 2026-07-16 增补 `google/agents-cli`。结论不是 fork 某一个项目,而是 clean-room 组合:agents-cli 作为开发生命周期和 Coding-Agent-first CLI 的主要蓝本;其它项目分别提供社交行为、记忆、运行内核、人格或 Skill 包装。没有一个项目可以原样解决钉钉真实事件、DWS 权限和员工行为。
4
+
5
+ ## 开发生命周期的主要蓝本:google/agents-cli
6
+
7
+ [`google/agents-cli`](https://github.com/google/agents-cli) 是 dta 后续 Project、Workspace、Eval、Deploy 和 Provider 设计的首要参考。重点迁移的不是 Google Cloud 产品命令,而是这些结构:
8
+
9
+ 1. **Coding Agent first**:Skill 负责阶段判断和领域指导,CLI 同时可以被人或 Coding Agent 稳定调用;
10
+ 2. **生命周期分相**:spec/workflow、scaffold/enhance、build、eval、deploy、publish、observe 各有清晰边界;
11
+ 3. **项目 Manifest + `info --json`**:从任意子目录解析项目,报告 CLI/项目版本、目标和已安装 Skill;
12
+ 4. **保护已有项目**:`scaffold enhance` 先预览、备份和 smart merge,不把生成模板覆盖到用户代码上;
13
+ 5. **部署控制面**:`--dry-run`、显式确认、`--list`、`--status`、`--no-wait`、远端回读和部署 metadata;
14
+ 6. **认证分层**:Coding Agent、模型和部署身份彼此独立。dta 在此基础上再增加 DWS 执行身份;
15
+ 7. **闭环而非一次发布**:评测结果约束部署,线上 trace/反馈再进入下一轮评测候选。
16
+
17
+ dta 不迁移 ADK、Terraform、Cloud Run、GKE 或 Gemini Enterprise 的产品实现。对应关系是:Agent Project 保存可移植本体,Development Workspace 绑定一个 OpenCode/Multica Host Provider,Storage Provider 继续独立,Trigger Adapter 继续留在核心之外。详细推演见 [Provider-bound Development Workspace](roadmap/provider-bound-development-workspace.md)。
18
+
19
+ ## 哪份提示词最值得参考
20
+
21
+ - **行为事实的第一基线**:Claude Tag 官方的 [How it works](https://claude.com/docs/claude-tag/concepts/how-it-works) 与 [Good habits](https://claude.com/docs/claude-tag/users/good-habits)。官方没有公开完整 system prompt,但明确了 thread=session、sandbox 可丢弃、长任务 checklist、原 thread 交付、definition of done 和 durable artifact。
22
+ - **只选一份“完整开源同事 Prompt”基线**:[`open-tag/src/daemon/prompt.ts`](https://github.com/fancyboi999/open-tag/blob/main/src/daemon/prompt.ts)。它覆盖原频道/线程回复、task claim、避免重复汇报、freshness hold、私密范围、长任务提醒、睡眠/唤醒和压缩前记忆。
23
+ - **最接近中文 IM 数字同事、最便于迁移内容**:AWS 样例的 [`prompts.py`](https://github.com/aws-samples/sample-claude-tag-in-lark/blob/main/larkclaudetag/app/larktag/prompts.py)。它对“当前消息与背景分离、工具成功后才能宣称完成、两阶段遗忘、定时任务确认、文件交付”写得最具体。
24
+ - **最好的单一事件剧本**:用户提供的 [Claude Tag onboarding gist](https://gist.github.com/coco98/c8ef8e2f02b1ef82dea0cd0e95283b97)。它只描述 `agent.joined` 一次 wake,不是完整系统提示词。
25
+
26
+ 所以不会复制一段“万能 Prompt”:官方资料约束真实产品行为,`open-tag` 提供社交协议,gist 提供事件剧本写法,AWS 提供工具诚实性与记忆规则;目标、权限、幂等和回执全部下沉到 CLI/宿主。
27
+
28
+ ## 核心差异
29
+
30
+ | 项目 | 核心抽象 | 强项 | 不能直接照搬 | 本项目迁移 |
31
+ |---|---|---|---|---|
32
+ | [google/agents-cli](https://github.com/google/agents-cli) | Coding Agent + lifecycle Skills + project manifest + CLI | spec→scaffold/enhance→eval→deploy→publish→observe;dry-run/status;认证和部署目标分层 | 绑定 ADK/Google Cloud,Terraform 与容器不是 dta 的核心;事件触发可与运行时同体 | Project/Workspace/Provider、`info`、enhance、Eval gate、可选 deploy 与 observed-state Receipt |
33
+ | [Claude Tag 官方行为](https://claude.com/docs/claude-tag/concepts/how-it-works) | 一个 thread 一个 working session;每次活跃期构建 sandbox | 五步生命周期、可编辑 checklist、原 thread steer/交付、显式 definition of done、sandbox 与 durable state 分离 | 没有公开完整 Prompt 或运行源码;Slack 的 thread/权限模型不能直接等同钉钉 | Session/Run 映射、任务承接协议、checkpoint 与长期记忆分离 |
34
+ | [AWS Claude Tag in Lark](https://github.com/aws-samples/sample-claude-tag-in-lark) | 一个群一个共享上下文;薄 webhook + AgentCore runtime | 可运行的飞书链路;按群记忆、显式/自动记忆、两阶段遗忘、Skill、定时任务、旁听 | 仓库明确是 sample;Agent 使用 `bypassPermissions`;全局 Skill 当场生效不符合强治理 | 当前消息/背景分离、工具结果诚实、记忆分层、候选式进化 |
35
+ | [Anil Open Claude Tag](https://github.com/Anil-matcha/open-claude-tag) | `(workspace_id, channel_id)` 一个 Agent;`CHANNEL.md + MEMORY.md + skills + tools.toml` | Workspace 文件结构、共享频道上下文、记忆整理 turn | 当前 README 中多项记忆/Skill/ambient 能力仍在 roadmap;进程内锁和直接工具循环不足以做可靠运行内核 | Workspace 目录、按需 Skill、记忆 curation 思路,不以其 roadmap 当现成功能 |
36
+ | [TagIt](https://github.com/liliang-cn/tagit) | IM → daemon/queue → coding agent → Git worktree | CLI、事件存储、lease、恢复/重放、worktree、策略 broker、多 Agent 执行 | 本质是代码任务编排,不是通用社交员工;部分危险信号是事后文本分类;不迁移其高权限默认 | durable inbox/outbox、Run 管理、执行闸门和沙箱思想 |
37
+ | [open-tag](https://github.com/fancyboi999/open-tag) | 自建完整协作平台;持久 Agent workspace + wake/sleep + channels/DM/tasks | 最完整的同事协议、task claim、freshness hold、原线程汇报、prepare→human commit | 它替代 Slack/钉钉,而本项目必须适配真实钉钉;prompt 暴露通用消息 target,不适合作为 DWS 安全边界 | 社交协议、任务状态、忙时通知、freshness 再判断;目标改由宿主冻结 |
38
+ | [ElizaOS](https://github.com/elizaOS/eliza/blob/develop/packages/core/src/schemas/character.ts) | Character + room/world + action/provider | `bio/messageExamples/postExamples/style/topics` 人格建模;结构化 should-respond/action | Character 不能承担 ACL、目标、幂等和审批 | Identity/Voice/Examples 层,可作为 Field 的人格插件 |
39
+ | [Agent Skills](https://agentskills.io/specification) | `SKILL.md + scripts/references/assets` | 便携能力包、渐进披露、跨 Agent 复用 | 不定义事件、Session、记忆、权限或 Receipt | 标准 Skill 目录;Session 绑定 snapshot/hash,每个 Run 使用其投影 |
40
+
41
+ 需要特别注意:此前所说 `CHANNEL.md + MEMORY.md + tools.toml` 指的是
42
+ [`Anil-matcha/open-claude-tag`](https://github.com/Anil-matcha/open-claude-tag),不要与其它同名仓库混淆。
43
+
44
+ ## gist 里真正可迁移的内容
45
+
46
+ 该 gist 的结构是 `<wake reason="dispatch">` + `<channel …>` + 带 `trust="principal"` 的系统消息。最有价值的不是具体英文文案,而是:
47
+
48
+ 1. **信号与正文分层**:可信 wake 元数据决定当前是什么事件,普通消息不能升级权限。
49
+ 2. **先分类协作场域**:PERSONAL / TEAM / BROADCAST 对应不同 response eligibility;广播场域默认安静。
50
+ 3. **动作序列与预算显式化**:先做什么、最多读几次、错误是否重试、何时退出都写进事件合同。
51
+ 4. **建议必须有证据**:主动提出的 pickup 要指向真的看过且仍未关闭的工作,不虚构待办或 permalink。
52
+ 5. **offer 不等于 commitment**:先说“我可以接”,获得授权后才承诺执行。
53
+ 6. **观察不等于插话**:默认在后台,只有被点名或配置的主动信号才发言。
54
+
55
+ 不能迁移的是“TEAM/PERSONAL 永远发三条消息”。它是 onboarding 的产品剧本,放到普通钉钉消息会制造噪声。gist 也没有证明事件持久化、Session、身份核验、工具审批、幂等、送达回读或 Skill 发布治理。
56
+
57
+ ## 新任务协议的来源组合
58
+
59
+ ```text
60
+ UNDERSTAND / PLAN / checklist / original-thread delivery
61
+ ← Claude Tag 官方公开生命周期
62
+
63
+ 当前消息与背景分离 / 工具成功后才宣称完成
64
+ ← AWS Lark sample prompts.py
65
+
66
+ task claim / freshness hold / 阶段更新 / 人工验收
67
+ ← open-tag prompt.ts
68
+
69
+ Field 分类 / offer 不等于 commitment / 工具预算
70
+ ← onboarding gist(仅作为未验证的逆向样本)
71
+ ```
72
+
73
+ 最终落成 `UNDERSTAND → CLARIFY → PLAN → EXECUTE → WAIT → VERIFY → COMPLETE`。其中 CLARIFY 是内部缺口判断,不是固定先问人;简单任务直接完成,多步或跨 Run 的任务才建立 checklist/checkpoint。
74
+
75
+ ## 所有有效实现的共同点
76
+
77
+ 1. 稳定作用域绑定频道、房间或 workspace,不绑定一次模型会话。
78
+ 2. “感知到”与“应该发言”分离,先做 response eligibility。
79
+ 3. 回复回到原频道/线程/DM,并区分确认、进度和结果。
80
+ 4. 当前运行可以短暂,事件、任务、记忆、Skill 和审计必须外部持久化。
81
+ 5. 上下文分层加载:身份/政策 → 当前事件 → 当前线程/任务 → 记忆 → 相关 Skill。
82
+ 6. 记忆选择性写入并带作用域;旁听不等于自动记忆,更不等于自动插话。
83
+ 7. 长任务需要队列、lease、恢复、重放、提醒和审计。
84
+ 8. ID、ACL、审批、预算、幂等、外发和 Receipt 应由宿主强制,而不是要求模型“自觉”。
85
+ 9. 新 Skill 先做 candidate,经评测和审批再发布;不能在当前 Run 热改规则。
86
+ 10. 多个事件级行为合同,比一个超长 System Prompt 更可靠。
87
+
88
+ ## dingtalk-agent 与它们的本质差异
89
+
90
+ ```text
91
+ 它们常见的抽象:一个频道 = 一个长期 Agent / 模型会话
92
+
93
+ dingtalk-agent:
94
+ Workspace(稳定 Context / 权限 / 知识 / 人格边界)
95
+ └── Session(同一件事,tenant + conversation + causal key)
96
+ └── Run(一次信号,可启动一次可丢弃沙箱)
97
+ └── ActionRequest(无 target)
98
+ └── Host Gate + DWS + Receipt
99
+ ```
100
+
101
+ P0 中 Workspace 与 Field 一对一,可以对应一个群、一个 DM、一个项目或一组明确 selector,但不强制等于频道。Session 也不等于 conversation:同一个钉钉群里可以同时有多件事。沙箱只是一次 Run 的执行尝试,长期记忆和权限不放在里面。
102
+
103
+ 最终组合是:
104
+
105
+ ```text
106
+ Behavior Contract
107
+ = open-tag 社交协议
108
+ + gist 事件剧本
109
+ + AWS 工具诚实性/记忆规则
110
+ + ElizaOS 人格与结构化响应
111
+
112
+ Runtime Kernel
113
+ = Workspace / Session / Run / Action
114
+ + 宿主私有 Event Journal / Continuation / Receipt
115
+ + TagIt 的队列、恢复、重放思想
116
+ + open-tag 的 freshness hold 与 prepare/commit
117
+
118
+ Capability Package
119
+ = Agent Skills 规范
120
+ + Session 级 Skill snapshot/hash + Run 投影
121
+ + candidate → eval → approval → publish
122
+ ```