@xdxer/dingtalk-agent 0.1.4-beta.1 → 0.1.4-beta.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -7
- package/dist/bin/dingtalk-agent.js +67 -22
- package/dist/bin/dingtalk-agent.js.map +1 -1
- package/dist/src/doctor.js +18 -7
- package/dist/src/doctor.js.map +1 -1
- package/dist/src/setup.js +10 -9
- package/dist/src/setup.js.map +1 -1
- package/dist/src/skill-manager.js +80 -192
- package/dist/src/skill-manager.js.map +1 -1
- package/docs/ARCHITECTURE.md +1 -1
- package/docs/INSTALLATION.md +38 -8
- package/evals/evals.json +21 -10
- package/evals/run-contract-evals.mjs +54 -36
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"skill-manager.js","sourceRoot":"","sources":["../../src/skill-manager.ts"],"names":[],"mappings":"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","sourcesContent":["// 全局 Skill 生命周期:一个 canonical copy,按 Agent 客户端暴露。\n//\n// canonical: ~/.agents/skills/dingtalk-basic-behavior\n// Claude: ~/.claude/skills/dingtalk-basic-behavior -> canonical\n//\n// 不链接 npm/node_modules:包升级、卸载或 npx cache 清理都不应让 Skill 断掉。\n\nimport {\n cpSync, existsSync, lstatSync, mkdirSync, readFileSync, readlinkSync,\n readdirSync, renameSync, rmSync, symlinkSync, writeFileSync,\n} from 'node:fs'\nimport { createHash, randomUUID } from 'node:crypto'\nimport { homedir } from 'node:os'\nimport { dirname, join, relative, resolve } from 'node:path'\n\nexport const GLOBAL_SKILL_NAME = 'dingtalk-basic-behavior'\nconst MARKER = '.dingtalk-agent-install.json'\nconst MANAGER = '@xdxer/dingtalk-agent'\n\ninterface InstallMarker {\n $schema: 'dingtalk-agent/managed-skill@1'\n manager: typeof MANAGER\n packageVersion: string\n skillVersion: string\n sourceHash: string\n installedAt: string\n exposure: { claude: 'symlink' }\n}\n\nexport interface SkillManagerOptions {\n home?: string\n dryRun?: boolean\n discardLocalChanges?: boolean\n}\n\nexport interface GlobalSkillStatus {\n $schema: 'dingtalk-agent/skill-status@1'\n name: string\n bundled: { path: string; packageVersion: string; skillVersion: string; hash: string }\n canonical: {\n path: string\n exists: boolean\n managed: boolean\n installedHash: string\n modified: boolean\n current: boolean\n }\n claude: { path: string; state: 'ok' | 'missing' | 'conflict'; target: string }\n clients: Array<{\n name: 'claude-code' | 'codex' | 'opencode'\n label: string\n discovery: 'symlink' | 'shared-agent-skills'\n path: string\n state: 'ok' | 'missing' | 'conflict'\n }>\n legacyCodex: { path: string; conflict: boolean }\n}\n\nexport function skillStatus(packageRoot: string, options: SkillManagerOptions = {}): GlobalSkillStatus {\n const paths = globalPaths(packageRoot, options.home)\n const bundled = bundledInfo(packageRoot)\n const marker = readMarker(paths.canonical)\n const canonicalExists = pathExists(paths.canonical)\n const canonicalDirectory = canonicalExists && lstatSync(paths.canonical).isDirectory()\n const installedHash = canonicalDirectory ? hashDirectory(paths.canonical) : ''\n const managed = marker?.manager === MANAGER\n const modified = Boolean(managed && installedHash !== marker?.sourceHash)\n const claude = inspectExposure(paths.claude, paths.canonical)\n const sharedState = canonicalExists ? 'ok' : 'missing'\n return {\n $schema: 'dingtalk-agent/skill-status@1',\n name: GLOBAL_SKILL_NAME,\n bundled,\n canonical: {\n path: paths.canonical,\n exists: canonicalExists,\n managed,\n installedHash,\n modified,\n current: Boolean(managed && !modified && installedHash === bundled.hash),\n },\n claude: { path: paths.claude, ...claude },\n clients: [\n {\n name: 'claude-code', label: 'Claude Code', discovery: 'symlink',\n path: paths.claude, state: claude.state,\n },\n {\n name: 'codex', label: 'Codex', discovery: 'shared-agent-skills',\n path: paths.canonical, state: sharedState,\n },\n {\n name: 'opencode', label: 'OpenCode', discovery: 'shared-agent-skills',\n path: paths.canonical, state: sharedState,\n },\n ],\n legacyCodex: { path: paths.legacyCodex, conflict: pathExists(paths.legacyCodex) },\n }\n}\n\nexport function installGlobalSkill(\n packageRoot: string,\n options: SkillManagerOptions = {},\n): GlobalSkillStatus {\n const before = skillStatus(packageRoot, options)\n if (before.canonical.exists) {\n if (!before.canonical.managed) {\n throw new Error(`全局 Skill 同名目录不归 dingtalk-agent 管理,拒绝覆盖: ${before.canonical.path}`)\n }\n if (before.canonical.modified) {\n throw new Error(`全局 Skill 有本地修改,拒绝覆盖: ${before.canonical.path}`)\n }\n if (!before.canonical.current) {\n throw new Error('已安装版本不是当前内置版本;请运行 `dingtalk-agent skill upgrade`')\n }\n ensureClaudeExposure(before.canonical.path, before.claude.path, options.dryRun)\n return options.dryRun ? before : skillStatus(packageRoot, options)\n }\n\n if (before.claude.state === 'conflict') {\n throw new Error(`Claude Skill 路径已有陌生内容,拒绝覆盖: ${before.claude.path}`)\n }\n if (!options.dryRun) {\n installCanonical(packageRoot, before.canonical.path)\n ensureClaudeExposure(before.canonical.path, before.claude.path, false)\n }\n return options.dryRun ? before : skillStatus(packageRoot, options)\n}\n\nexport function upgradeGlobalSkill(\n packageRoot: string,\n options: SkillManagerOptions = {},\n): GlobalSkillStatus {\n const before = skillStatus(packageRoot, options)\n if (!before.canonical.exists) return installGlobalSkill(packageRoot, options)\n if (!before.canonical.managed) {\n throw new Error(`全局 Skill 不归 dingtalk-agent 管理,拒绝接管: ${before.canonical.path}`)\n }\n if (before.canonical.modified && !options.discardLocalChanges) {\n throw new Error(\n '全局 Skill 有本地修改;先保存改动,或显式使用 `--discard-local-changes` 放弃修改',\n )\n }\n if (before.claude.state === 'conflict') {\n throw new Error(`Claude Skill 路径已有陌生内容,拒绝覆盖: ${before.claude.path}`)\n }\n if (!options.dryRun && !before.canonical.current) {\n replaceCanonical(packageRoot, before.canonical.path)\n }\n ensureClaudeExposure(before.canonical.path, before.claude.path, options.dryRun)\n return options.dryRun ? before : skillStatus(packageRoot, options)\n}\n\nexport function uninstallGlobalSkill(\n packageRoot: string,\n options: SkillManagerOptions = {},\n): GlobalSkillStatus {\n const before = skillStatus(packageRoot, options)\n if (!before.canonical.exists) return before\n if (!before.canonical.managed) {\n throw new Error(`全局 Skill 不归 dingtalk-agent 管理,拒绝删除: ${before.canonical.path}`)\n }\n if (before.canonical.modified && !options.discardLocalChanges) {\n throw new Error(\n '全局 Skill 有本地修改;先保存改动,或显式使用 `--discard-local-changes` 放弃修改',\n )\n }\n if (!options.dryRun) {\n if (before.claude.state === 'ok') rmSync(before.claude.path)\n rmSync(before.canonical.path, { recursive: true, force: true })\n }\n return options.dryRun ? before : skillStatus(packageRoot, options)\n}\n\nfunction globalPaths(packageRoot: string, home = homedir()) {\n return {\n source: join(packageRoot, 'skills', GLOBAL_SKILL_NAME),\n canonical: join(home, '.agents', 'skills', GLOBAL_SKILL_NAME),\n claude: join(home, '.claude', 'skills', GLOBAL_SKILL_NAME),\n legacyCodex: join(home, '.codex', 'skills', GLOBAL_SKILL_NAME),\n }\n}\n\nfunction bundledInfo(packageRoot: string) {\n const paths = globalPaths(packageRoot)\n validateSkill(paths.source)\n const pkg = JSON.parse(readFileSync(join(packageRoot, 'package.json'), 'utf8'))\n const frontmatter = parseSkillFrontmatter(readFileSync(join(paths.source, 'SKILL.md'), 'utf8'))\n return {\n path: paths.source,\n packageVersion: String(pkg.version || ''),\n skillVersion: frontmatter.version,\n hash: hashDirectory(paths.source),\n }\n}\n\nfunction installCanonical(packageRoot: string, destination: string): void {\n const source = globalPaths(packageRoot).source\n const bundled = bundledInfo(packageRoot)\n const parent = dirname(destination)\n mkdirSync(parent, { recursive: true })\n const stage = join(parent, `.${GLOBAL_SKILL_NAME}.stage.${process.pid}.${randomUUID()}`)\n try {\n cpSync(source, stage, { recursive: true, errorOnExist: true, force: false })\n writeFileSync(join(stage, MARKER), JSON.stringify(markerFor(bundled), null, 2) + '\\n', { flag: 'wx' })\n validateSkill(stage)\n if (hashDirectory(stage) !== bundled.hash) throw new Error('Skill staging hash 与内置版本不一致')\n renameSync(stage, destination)\n } finally {\n rmSync(stage, { recursive: true, force: true })\n }\n}\n\nfunction replaceCanonical(packageRoot: string, destination: string): void {\n const parent = dirname(destination)\n const backup = join(parent, `.${GLOBAL_SKILL_NAME}.backup.${process.pid}.${randomUUID()}`)\n const stageDestination = join(parent, `.${GLOBAL_SKILL_NAME}.next.${process.pid}.${randomUUID()}`)\n installCanonical(packageRoot, stageDestination)\n renameSync(destination, backup)\n try {\n renameSync(stageDestination, destination)\n rmSync(backup, { recursive: true, force: true })\n } catch (error) {\n if (!existsSync(destination) && existsSync(backup)) renameSync(backup, destination)\n throw error\n } finally {\n rmSync(stageDestination, { recursive: true, force: true })\n }\n}\n\nfunction ensureClaudeExposure(canonical: string, exposure: string, dryRun = false): void {\n const state = inspectExposure(exposure, canonical)\n if (state.state === 'ok') return\n if (state.state === 'conflict') throw new Error(`Claude Skill 路径已有陌生内容: ${exposure}`)\n if (dryRun) return\n mkdirSync(dirname(exposure), { recursive: true })\n const target = relative(dirname(exposure), canonical) || '.'\n try {\n symlinkSync(target, exposure, 'dir')\n } catch (error) {\n throw new Error(\n `无法为 Claude Code 创建 Skill symlink: ${String(error.message || error)};` +\n '请检查 ~/.claude/skills 的写权限',\n )\n }\n}\n\nfunction inspectExposure(exposure: string, canonical: string): {\n state: 'ok' | 'missing' | 'conflict'\n target: string\n} {\n if (!pathExists(exposure)) return { state: 'missing', target: '' }\n const stat = lstatSync(exposure)\n if (!stat.isSymbolicLink()) return { state: 'conflict', target: '' }\n const raw = readlinkSync(exposure)\n const target = resolve(dirname(exposure), raw)\n return target === resolve(canonical)\n ? { state: 'ok', target: raw }\n : { state: 'conflict', target: raw }\n}\n\nfunction markerFor(bundled: ReturnType<typeof bundledInfo>): InstallMarker {\n return {\n $schema: 'dingtalk-agent/managed-skill@1',\n manager: MANAGER,\n packageVersion: bundled.packageVersion,\n skillVersion: bundled.skillVersion,\n sourceHash: bundled.hash,\n installedAt: new Date().toISOString(),\n exposure: { claude: 'symlink' },\n }\n}\n\nfunction readMarker(skillRoot: string): InstallMarker | null {\n const path = join(skillRoot, MARKER)\n if (!existsSync(path)) return null\n try {\n const value = JSON.parse(readFileSync(path, 'utf8'))\n return value?.$schema === 'dingtalk-agent/managed-skill@1' ? value : null\n } catch { return null }\n}\n\nfunction pathExists(path: string): boolean {\n try { lstatSync(path); return true } catch { return false }\n}\n\nfunction validateSkill(root: string): void {\n if (!existsSync(root) || !lstatSync(root).isDirectory()) {\n throw new Error(`内置 Skill 不存在: ${root}`)\n }\n const file = join(root, 'SKILL.md')\n if (!existsSync(file)) throw new Error(`Skill 缺少 SKILL.md: ${root}`)\n const metadata = parseSkillFrontmatter(readFileSync(file, 'utf8'))\n if (metadata.name !== GLOBAL_SKILL_NAME) {\n throw new Error(`Skill name=${metadata.name} 与目录名 ${GLOBAL_SKILL_NAME} 不一致`)\n }\n if (!metadata.description) throw new Error('Skill frontmatter 缺少 description')\n}\n\nfunction parseSkillFrontmatter(text: string): { name: string; description: string; version: string } {\n const match = text.match(/^---\\r?\\n([\\s\\S]*?)\\r?\\n---(?:\\r?\\n|$)/)\n if (!match) throw new Error('SKILL.md 缺少 YAML frontmatter')\n const block = match[1]\n const readScalar = (key: string) => {\n const found = block.match(new RegExp(`^${key}:\\\\s*(.+)$`, 'm'))\n return found ? found[1].trim().replace(/^(['\"])(.*)\\1$/, '$2') : ''\n }\n const nestedVersion = block.match(/^metadata:\\s*\\r?\\n(?:[ \\t]+.*\\r?\\n)*?[ \\t]+version:\\s*['\"]?([^'\"\\r\\n]+)['\"]?\\s*$/m)\n return {\n name: readScalar('name'),\n description: readScalar('description'),\n version: nestedVersion?.[1]?.trim() || readScalar('version'),\n }\n}\n\nfunction hashDirectory(root: string): string {\n const hash = createHash('sha256')\n for (const path of walk(root)) {\n const rel = relative(root, path).split('\\\\').join('/')\n if (rel === MARKER) continue\n hash.update(rel).update('\\0').update(readFileSync(path)).update('\\0')\n }\n return hash.digest('hex')\n}\n\nfunction walk(root: string): string[] {\n const out: string[] = []\n for (const name of readdirSync(root).sort()) {\n const path = join(root, name)\n const stat = lstatSync(path)\n if (stat.isSymbolicLink()) throw new Error(`Skill 内不允许符号链接: ${path}`)\n if (stat.isDirectory()) out.push(...walk(path))\n else if (stat.isFile()) out.push(path)\n }\n return out\n}\n"]}
|
|
1
|
+
{"version":3,"file":"skill-manager.js","sourceRoot":"","sources":["../../src/skill-manager.ts"],"names":[],"mappings":"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","sourcesContent":["// Skill 安装生命周期由开放生态的 `npx skills` 负责。\n// dingtalk-agent 只做两件事:把内置 Skill 目录交给上游 CLI;只读验证客户端能否发现。\n\nimport { existsSync, lstatSync, readFileSync, readlinkSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { dirname, join, resolve } from 'node:path'\nimport { spawnSync } from 'node:child_process'\n\nexport const GLOBAL_SKILL_NAME = 'dingtalk-basic-behavior'\nconst SKILLS_PACKAGE = 'skills@latest'\nconst REGISTRY = 'https://registry.npmjs.org'\nconst AGENTS = ['claude-code', 'codex', 'opencode']\n\nexport interface SkillManagerOptions {\n home?: string\n dryRun?: boolean\n env?: NodeJS.ProcessEnv\n}\n\nexport interface GlobalSkillStatus {\n $schema: 'dingtalk-agent/skill-status@2'\n name: string\n manager: 'skills-cli'\n bundled: { path: string; packageVersion: string; skillVersion: string }\n canonical: {\n path: string\n exists: boolean\n installedVersion: string\n current: boolean\n }\n claude: { path: string; state: 'ok' | 'missing' | 'conflict'; target: string }\n clients: Array<{\n name: 'claude-code' | 'codex' | 'opencode'\n label: string\n discovery: 'symlink' | 'shared-agent-skills'\n path: string\n state: 'ok' | 'missing' | 'conflict'\n }>\n operation?: {\n action: 'install' | 'upgrade' | 'uninstall'\n command: string\n executed: boolean\n exitCode: number | null\n output: string\n }\n}\n\nexport function skillStatus(packageRoot: string, options: SkillManagerOptions = {}): GlobalSkillStatus {\n const paths = globalPaths(packageRoot, options.home)\n const bundled = bundledInfo(packageRoot)\n const canonicalExists = isDirectory(paths.canonical)\n const installedVersion = canonicalExists\n ? parseSkillFrontmatter(readFileSync(join(paths.canonical, 'SKILL.md'), 'utf8')).version\n : ''\n const claude = inspectExposure(paths.claude, paths.canonical)\n const sharedState = canonicalExists ? 'ok' : 'missing'\n return {\n $schema: 'dingtalk-agent/skill-status@2',\n name: GLOBAL_SKILL_NAME,\n manager: 'skills-cli',\n bundled,\n canonical: {\n path: paths.canonical,\n exists: canonicalExists,\n installedVersion,\n current: Boolean(canonicalExists && installedVersion === bundled.skillVersion),\n },\n claude: { path: paths.claude, ...claude },\n clients: [\n {\n name: 'claude-code', label: 'Claude Code', discovery: 'symlink',\n path: paths.claude, state: claude.state,\n },\n {\n name: 'codex', label: 'Codex', discovery: 'shared-agent-skills',\n path: paths.canonical, state: sharedState,\n },\n {\n name: 'opencode', label: 'OpenCode', discovery: 'shared-agent-skills',\n path: paths.canonical, state: sharedState,\n },\n ],\n }\n}\n\nexport function installGlobalSkill(\n packageRoot: string,\n options: SkillManagerOptions = {},\n): GlobalSkillStatus {\n return runSkills(packageRoot, 'install', [\n 'add', globalPaths(packageRoot).source,\n '--global', '--yes', '--agent', ...AGENTS,\n ], options)\n}\n\nexport function upgradeGlobalSkill(\n packageRoot: string,\n options: SkillManagerOptions = {},\n): GlobalSkillStatus {\n // Skill 随 npm 包发布;重新 add 当前包内目录,让 skills CLI 执行自己的覆盖/链接语义。\n return runSkills(packageRoot, 'upgrade', [\n 'add', globalPaths(packageRoot).source,\n '--global', '--yes', '--agent', ...AGENTS,\n ], options)\n}\n\nexport function uninstallGlobalSkill(\n packageRoot: string,\n options: SkillManagerOptions = {},\n): GlobalSkillStatus {\n return runSkills(packageRoot, 'uninstall', [\n 'remove', GLOBAL_SKILL_NAME,\n '--global', '--yes', '--agent', ...AGENTS,\n ], options)\n}\n\nfunction runSkills(\n packageRoot: string,\n action: 'install' | 'upgrade' | 'uninstall',\n args: string[],\n options: SkillManagerOptions,\n): GlobalSkillStatus {\n const commandArgs = ['--yes', `--registry=${REGISTRY}`, SKILLS_PACKAGE, ...args]\n const command = ['npx', ...commandArgs].map(shellQuote).join(' ')\n const before = skillStatus(packageRoot, options)\n if (options.dryRun) {\n return {\n ...before,\n operation: { action, command, executed: false, exitCode: null, output: '' },\n }\n }\n\n const env = {\n ...process.env,\n ...(options.env || {}),\n HOME: options.home || options.env?.HOME || process.env.HOME || homedir(),\n }\n const run = spawnSync('npx', commandArgs, {\n encoding: 'utf8', env, timeout: 120_000,\n })\n const output = [run.stdout, run.stderr].filter(Boolean).join('\\n').trim()\n if (run.error || run.status !== 0) {\n const reason = (run.error as NodeJS.ErrnoException | undefined)?.code === 'ENOENT'\n ? 'PATH 找不到 npx;请安装带 npm/npx 的 Node.js 18.3+'\n : run.error?.message || output || `退出码 ${run.status}`\n throw new Error(\n `skills CLI ${action} 失败: ${reason}\\n` +\n `可手动执行: ${command}`,\n )\n }\n return {\n ...skillStatus(packageRoot, options),\n operation: { action, command, executed: true, exitCode: run.status, output },\n }\n}\n\nfunction globalPaths(packageRoot: string, home = homedir()) {\n return {\n source: join(packageRoot, 'skills', GLOBAL_SKILL_NAME),\n canonical: join(home, '.agents', 'skills', GLOBAL_SKILL_NAME),\n claude: join(home, '.claude', 'skills', GLOBAL_SKILL_NAME),\n }\n}\n\nfunction bundledInfo(packageRoot: string) {\n const source = globalPaths(packageRoot).source\n validateSkill(source)\n const pkg = JSON.parse(readFileSync(join(packageRoot, 'package.json'), 'utf8'))\n const frontmatter = parseSkillFrontmatter(readFileSync(join(source, 'SKILL.md'), 'utf8'))\n return {\n path: source,\n packageVersion: String(pkg.version || ''),\n skillVersion: frontmatter.version,\n }\n}\n\nfunction inspectExposure(exposure: string, canonical: string): {\n state: 'ok' | 'missing' | 'conflict'\n target: string\n} {\n if (!pathExists(exposure)) return { state: 'missing', target: '' }\n const stat = lstatSync(exposure)\n if (!stat.isSymbolicLink()) return { state: 'conflict', target: '' }\n const raw = readlinkSync(exposure)\n return resolve(dirname(exposure), raw) === resolve(canonical)\n ? { state: 'ok', target: raw }\n : { state: 'conflict', target: raw }\n}\n\nfunction validateSkill(root: string): void {\n if (!isDirectory(root)) throw new Error(`内置 Skill 不存在: ${root}`)\n const file = join(root, 'SKILL.md')\n if (!existsSync(file)) throw new Error(`Skill 缺少 SKILL.md: ${root}`)\n const metadata = parseSkillFrontmatter(readFileSync(file, 'utf8'))\n if (metadata.name !== GLOBAL_SKILL_NAME) {\n throw new Error(`Skill name=${metadata.name} 与目录名 ${GLOBAL_SKILL_NAME} 不一致`)\n }\n if (!metadata.description) throw new Error('Skill frontmatter 缺少 description')\n}\n\nfunction parseSkillFrontmatter(text: string): { name: string; description: string; version: string } {\n const match = text.match(/^---\\r?\\n([\\s\\S]*?)\\r?\\n---(?:\\r?\\n|$)/)\n if (!match) throw new Error('SKILL.md 缺少 YAML frontmatter')\n const block = match[1]\n const readScalar = (key: string) => {\n const found = block.match(new RegExp(`^${key}:\\\\s*(.+)$`, 'm'))\n return found ? found[1].trim().replace(/^(['\"])(.*)\\1$/, '$2') : ''\n }\n const nestedVersion = block.match(/^metadata:\\s*\\r?\\n(?:[ \\t]+.*\\r?\\n)*?[ \\t]+version:\\s*['\"]?([^'\"\\r\\n]+)['\"]?\\s*$/m)\n return {\n name: readScalar('name'),\n description: readScalar('description'),\n version: nestedVersion?.[1]?.trim() || readScalar('version'),\n }\n}\n\nfunction isDirectory(path: string): boolean {\n try { return lstatSync(path).isDirectory() } catch { return false }\n}\n\nfunction pathExists(path: string): boolean {\n try { lstatSync(path); return true } catch { return false }\n}\n\nfunction shellQuote(value: string): string {\n return /^[A-Za-z0-9_./:=@-]+$/.test(value) ? value : `'${value.replace(/'/g, `'\"'\"'`)}'`\n}\n"]}
|
package/docs/ARCHITECTURE.md
CHANGED
|
@@ -214,4 +214,4 @@ npm run typecheck
|
|
|
214
214
|
npm run eval:contract
|
|
215
215
|
```
|
|
216
216
|
|
|
217
|
-
|
|
217
|
+
29 个确定性场景覆盖三条主链:setup/PATH/DWS/多客户端发现与错误提示、基于 `npx skills` 的 Skill-first 安装/水合,以及 Prepared Run 的 Session、Wait、幂等、目标与回执。
|
package/docs/INSTALLATION.md
CHANGED
|
@@ -8,6 +8,14 @@
|
|
|
8
8
|
npx --yes --registry=https://registry.npmjs.org @xdxer/dingtalk-agent@beta setup
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
+
安装完成后优先使用短命令;长短名称完全等价:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
dta --version
|
|
15
|
+
dta doctor
|
|
16
|
+
# 等价于 dingtalk-agent doctor
|
|
17
|
+
```
|
|
18
|
+
|
|
11
19
|
Why:npm 全局命令会被链接到 `{prefix}/bin`,但不同 Node 版本管理器可能使用不同 prefix;包已经安装不代表该目录已进入当前 shell 的 PATH。`npx`/`npm exec` 会直接运行指定 npm 包,因此可以先启动安装器,再由安装器修复稳定入口。
|
|
12
20
|
|
|
13
21
|
## setup 做什么
|
|
@@ -65,7 +73,15 @@ dws auth login
|
|
|
65
73
|
|
|
66
74
|
## Skill 安装策略
|
|
67
75
|
|
|
68
|
-
`
|
|
76
|
+
`dta` 不维护第二套 Skill 安装器。`dta skill install` 等价于把 npm 包内的 Skill 目录交给开放生态的 `npx skills add`:
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
npx --yes --registry=https://registry.npmjs.org skills@latest add \
|
|
80
|
+
<package>/skills/dingtalk-basic-behavior \
|
|
81
|
+
--global --yes --agent claude-code codex opencode
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
上游 `skills` CLI 负责 canonical copy、客户端链接、覆盖和卸载语义:
|
|
69
85
|
|
|
70
86
|
| 客户端 | 发现方式 | 路径 |
|
|
71
87
|
|---|---|---|
|
|
@@ -73,13 +89,16 @@ dws auth login
|
|
|
73
89
|
| Codex | shared Agent Skills | `~/.agents/skills/dingtalk-basic-behavior` |
|
|
74
90
|
| OpenCode | shared Agent Skills | `~/.agents/skills/dingtalk-basic-behavior` |
|
|
75
91
|
|
|
76
|
-
|
|
92
|
+
检查、重装当前 npm 包内版本和卸载:
|
|
77
93
|
|
|
78
94
|
```bash
|
|
79
|
-
|
|
80
|
-
|
|
95
|
+
dta skill status
|
|
96
|
+
dta skill upgrade
|
|
97
|
+
dta skill uninstall
|
|
81
98
|
```
|
|
82
99
|
|
|
100
|
+
`skill status` 只做只读发现检查;`install/upgrade/uninstall` 分别委托 `skills add/add/remove`。旧版 dta 写入的管理 marker 会在第一次 `skills add` 时被上游 canonical copy 替换,此后不再存在两套管理状态。
|
|
101
|
+
|
|
83
102
|
OpenCode 官方同时支持 `.opencode/skills`、`.claude/skills` 和 `.agents/skills`,所以不需要再复制第三份内容。
|
|
84
103
|
|
|
85
104
|
## 使用 npx skills
|
|
@@ -97,7 +116,7 @@ npx skills add ./skills/dingtalk-basic-behavior \
|
|
|
97
116
|
--global --yes --agent claude-code --agent codex --agent opencode
|
|
98
117
|
```
|
|
99
118
|
|
|
100
|
-
|
|
119
|
+
也可以完全绕过 `dta skill ...`,直接使用 `npx skills` 管理;两种入口最终调用的是同一个上游安装器。
|
|
101
120
|
|
|
102
121
|
## 初始化的三个层级
|
|
103
122
|
|
|
@@ -110,14 +129,14 @@ init Workspace 级,可选:只为长期 Workspace / Prepared Run 创建
|
|
|
110
129
|
普通 Claude Code、Codex 或 OpenCode 会话:
|
|
111
130
|
|
|
112
131
|
```bash
|
|
113
|
-
|
|
132
|
+
dta bootstrap --json
|
|
114
133
|
```
|
|
115
134
|
|
|
116
135
|
需要可信钉钉事件、Session/Run/Wait/Receipt 时才执行:
|
|
117
136
|
|
|
118
137
|
```bash
|
|
119
|
-
|
|
120
|
-
|
|
138
|
+
dta init
|
|
139
|
+
dta prepare --event-file event.json --json
|
|
121
140
|
```
|
|
122
141
|
|
|
123
142
|
## Doctor 退出码
|
|
@@ -126,6 +145,17 @@ dingtalk-agent prepare --event-file event.json --json
|
|
|
126
145
|
- `2`:至少一个必要条件不满足,同时输出确定的修复命令;
|
|
127
146
|
- `--json`:输出 `dingtalk-agent/doctor@1`,供安装器、CI 或宿主解析。
|
|
128
147
|
|
|
148
|
+
## 错误提示约定
|
|
149
|
+
|
|
150
|
+
CLI 错误统一包含两层信息:
|
|
151
|
+
|
|
152
|
+
```text
|
|
153
|
+
错误: 发生了什么,以及为什么拒绝继续
|
|
154
|
+
提示: 下一条可复制执行的恢复命令
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
命令拼写错误会建议最接近的命令;DWS 错误指向 `dta doctor`/`dws auth login`;没有可信 Run 时会明确要求先 `prepare`,不会暗中初始化或猜测目标。
|
|
158
|
+
|
|
129
159
|
## 设计依据
|
|
130
160
|
|
|
131
161
|
- [npm Folders](https://docs.npmjs.com/files/folders.html/):Unix 全局 executable 被链接到 `{prefix}/bin`;
|
package/evals/evals.json
CHANGED
|
@@ -214,13 +214,13 @@
|
|
|
214
214
|
{
|
|
215
215
|
"id": 20,
|
|
216
216
|
"prompt": "在一个没有 Workspace 的空目录安装全局 Basic Behavior,重复安装,再制造一个同名陌生 Skill。",
|
|
217
|
-
"expected_output": "安装不依赖 init;canonical copy 可被 Codex 发现,Claude
|
|
217
|
+
"expected_output": "安装不依赖 init;dta 将本地 Skill source 委托给 npx skills;canonical copy 可被 Codex/OpenCode 发现,Claude 使用 symlink;重复安装由上游处理。",
|
|
218
218
|
"files": [],
|
|
219
219
|
"expectations": [
|
|
220
220
|
"空目录可直接安装 canonical Skill",
|
|
221
|
-
"
|
|
222
|
-
"Claude exposure
|
|
223
|
-
"
|
|
221
|
+
"重复安装由 skills CLI 执行并保持 current",
|
|
222
|
+
"Claude exposure 指向 canonical copy",
|
|
223
|
+
"安装结果不再包含 dta 自定义管理 marker"
|
|
224
224
|
]
|
|
225
225
|
},
|
|
226
226
|
{
|
|
@@ -259,14 +259,14 @@
|
|
|
259
259
|
},
|
|
260
260
|
{
|
|
261
261
|
"id": 24,
|
|
262
|
-
"prompt": "
|
|
263
|
-
"expected_output": "status
|
|
262
|
+
"prompt": "通过 dta 安装 Skill 后手工修改内容,再执行 upgrade 和 uninstall。",
|
|
263
|
+
"expected_output": "status 只读报告 skills-cli 管理状态;upgrade 通过 npx skills add 重装;uninstall 通过 npx skills remove 清理所有目标客户端。",
|
|
264
264
|
"files": [],
|
|
265
265
|
"expectations": [
|
|
266
|
-
"
|
|
267
|
-
"upgrade
|
|
268
|
-
"uninstall
|
|
269
|
-
"
|
|
266
|
+
"status 明确报告 manager=skills-cli",
|
|
267
|
+
"upgrade 委托 skills add 并采用上游覆盖语义",
|
|
268
|
+
"uninstall 委托 skills remove",
|
|
269
|
+
"升级后版本 current,卸载后 canonical 与 exposure 消失"
|
|
270
270
|
]
|
|
271
271
|
},
|
|
272
272
|
{
|
|
@@ -311,6 +311,17 @@
|
|
|
311
311
|
"canonical Skill 与 Claude exposure 安装成功,三个 Agent 客户端均可发现",
|
|
312
312
|
"DWS 版本和认证检查通过,setup 最终 ready"
|
|
313
313
|
]
|
|
314
|
+
},
|
|
315
|
+
{
|
|
316
|
+
"id": 29,
|
|
317
|
+
"prompt": "分别输入拼错的顶层命令、拼错的 skill 子命令和不支持的参数。",
|
|
318
|
+
"expected_output": "CLI 使用统一的错误与提示格式,给出最接近的 dta 命令或明确的参数恢复入口。",
|
|
319
|
+
"files": [],
|
|
320
|
+
"expectations": [
|
|
321
|
+
"顶层命令拼错时同时输出原因和 dta doctor 建议",
|
|
322
|
+
"skill 子命令拼错时建议 dta skill install",
|
|
323
|
+
"参数错误时提示检查拼写并运行 dta --help"
|
|
324
|
+
]
|
|
314
325
|
}
|
|
315
326
|
]
|
|
316
327
|
}
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
readdirSync, cpSync, existsSync, lstatSync, readlinkSync,
|
|
7
7
|
} from 'node:fs'
|
|
8
8
|
import { tmpdir } from 'node:os'
|
|
9
|
-
import { join, dirname } from 'node:path'
|
|
9
|
+
import { join, dirname, resolve } from 'node:path'
|
|
10
10
|
import { fileURLToPath } from 'node:url'
|
|
11
11
|
import { spawnSync } from 'node:child_process'
|
|
12
12
|
import { init } from '../dist/src/init.js'
|
|
@@ -42,7 +42,7 @@ const cases = [
|
|
|
42
42
|
evalWorkspaceAuthority, evalSessionSkillBinding,
|
|
43
43
|
evalGlobalSkillInstall, evalBootstrapLocal, evalBootstrapRemote, evalOptionalInit,
|
|
44
44
|
evalManagedSkillLifecycle, evalRemoteStorageTypeGate, evalDirectActGate,
|
|
45
|
-
evalDoctorMissingDependencies, evalFirstRunSetup,
|
|
45
|
+
evalDoctorMissingDependencies, evalFirstRunSetup, evalCliErrorHints,
|
|
46
46
|
]
|
|
47
47
|
const benchmarkRuns = []
|
|
48
48
|
for (let i = 0; i < cases.length; i++) {
|
|
@@ -748,8 +748,7 @@ function evalSessionSkillBinding() {
|
|
|
748
748
|
function evalGlobalSkillInstall() {
|
|
749
749
|
const home = mkdtempSync(join(tmpdir(), 'dta-skill-home-'))
|
|
750
750
|
const cwd = mkdtempSync(join(tmpdir(), 'dta-skill-cwd-'))
|
|
751
|
-
|
|
752
|
-
WORKSPACES.push(home, cwd, foreignHome)
|
|
751
|
+
WORKSPACES.push(home, cwd)
|
|
753
752
|
const env = { ...process.env, HOME: home }
|
|
754
753
|
const first = spawnSync(process.execPath, [CLI, 'skill', 'install', '--json'], {
|
|
755
754
|
cwd, env, encoding: 'utf8',
|
|
@@ -761,29 +760,23 @@ function evalGlobalSkillInstall() {
|
|
|
761
760
|
const canonical = join(home, '.agents', 'skills', 'dingtalk-basic-behavior')
|
|
762
761
|
const claude = join(home, '.claude', 'skills', 'dingtalk-basic-behavior')
|
|
763
762
|
|
|
764
|
-
const
|
|
765
|
-
mkdirSync(foreign, { recursive: true })
|
|
766
|
-
writeFileSync(join(foreign, 'SKILL.md'), '---\nname: dingtalk-basic-behavior\ndescription: foreign\n---\n')
|
|
767
|
-
const conflict = spawnSync(process.execPath, [CLI, 'skill', 'install'], {
|
|
768
|
-
cwd, env: { ...process.env, HOME: foreignHome }, encoding: 'utf8',
|
|
769
|
-
})
|
|
763
|
+
const marker = join(canonical, '.dingtalk-agent-install.json')
|
|
770
764
|
return {
|
|
771
765
|
output: {
|
|
772
766
|
firstStatus: first.status, secondStatus: second.status, status,
|
|
773
|
-
claudeTarget: readlinkSync(claude),
|
|
774
|
-
conflictError: conflict.stderr.trim(),
|
|
767
|
+
claudeTarget: readlinkSync(claude), markerExists: existsSync(marker),
|
|
775
768
|
},
|
|
776
769
|
toolCalls: 3, steps: 6,
|
|
777
770
|
checks: [
|
|
778
771
|
check(first.status === 0 && existsSync(join(canonical, 'SKILL.md')),
|
|
779
772
|
`status=${first.status}; canonical=${canonical}`),
|
|
780
|
-
check(second.status === 0 && status.
|
|
781
|
-
status.canonical.
|
|
782
|
-
`status=${second.status};
|
|
773
|
+
check(second.status === 0 && status.manager === 'skills-cli' &&
|
|
774
|
+
status.canonical.current === true && status.operation?.command.includes('skills@latest add'),
|
|
775
|
+
`status=${second.status}; manager=${status.manager}; current=${status.canonical.current}`),
|
|
783
776
|
check(lstatSync(claude).isSymbolicLink() &&
|
|
784
|
-
readlinkSync(claude) ===
|
|
777
|
+
resolve(dirname(claude), readlinkSync(claude)) === resolve(canonical),
|
|
785
778
|
`target=${readlinkSync(claude)}`),
|
|
786
|
-
check(
|
|
779
|
+
check(!existsSync(marker), '上游 skills CLI 接管后不存在 dta 自定义 marker'),
|
|
787
780
|
],
|
|
788
781
|
}
|
|
789
782
|
}
|
|
@@ -879,33 +872,29 @@ function evalManagedSkillLifecycle() {
|
|
|
879
872
|
cwd, env, encoding: 'utf8',
|
|
880
873
|
})
|
|
881
874
|
const modified = JSON.parse(statusRun.stdout)
|
|
882
|
-
const
|
|
883
|
-
cwd, env, encoding: 'utf8',
|
|
884
|
-
})
|
|
885
|
-
const guardedUninstall = spawnSync(process.execPath, [CLI, 'skill', 'uninstall'], {
|
|
875
|
+
const repaired = spawnSync(process.execPath, [CLI, 'skill', 'upgrade', '--json'], {
|
|
886
876
|
cwd, env, encoding: 'utf8',
|
|
887
877
|
})
|
|
888
|
-
const repaired = spawnSync(process.execPath, [
|
|
889
|
-
CLI, 'skill', 'upgrade', '--discard-local-changes', '--json',
|
|
890
|
-
], { cwd, env, encoding: 'utf8' })
|
|
891
878
|
const repairedStatus = JSON.parse(repaired.stdout)
|
|
879
|
+
const repairedBody = readFileSync(file, 'utf8')
|
|
892
880
|
const removed = spawnSync(process.execPath, [CLI, 'skill', 'uninstall', '--json'], {
|
|
893
881
|
cwd, env, encoding: 'utf8',
|
|
894
882
|
})
|
|
895
883
|
const removedStatus = JSON.parse(removed.stdout)
|
|
896
884
|
return {
|
|
897
885
|
output: {
|
|
898
|
-
modified,
|
|
899
|
-
guardedUninstall: guardedUninstall.stderr.trim(), repairedStatus, removedStatus,
|
|
886
|
+
modified, repairedStatus, removedStatus,
|
|
900
887
|
},
|
|
901
|
-
toolCalls:
|
|
888
|
+
toolCalls: 4, steps: 6,
|
|
902
889
|
checks: [
|
|
903
|
-
check(modified.
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
check(
|
|
890
|
+
check(modified.manager === 'skills-cli' && modified.canonical.exists === true,
|
|
891
|
+
JSON.stringify(modified.canonical)),
|
|
892
|
+
check(repaired.status === 0 && !repairedBody.includes('local edit') &&
|
|
893
|
+
repairedStatus.operation?.command.includes('skills@latest add'),
|
|
894
|
+
`status=${repaired.status}; command=${repairedStatus.operation?.command}`),
|
|
895
|
+
check(removed.status === 0 && removedStatus.operation?.command.includes('skills@latest remove'),
|
|
896
|
+
`status=${removed.status}; command=${removedStatus.operation?.command}`),
|
|
897
|
+
check(repairedStatus.canonical.current === true &&
|
|
909
898
|
removed.status === 0 && removedStatus.canonical.exists === false &&
|
|
910
899
|
removedStatus.claude.state === 'missing',
|
|
911
900
|
`repaired=${repairedStatus.canonical.current}; removed=${removedStatus.canonical.exists}; ` +
|
|
@@ -996,21 +985,28 @@ function evalFirstRunSetup() {
|
|
|
996
985
|
})
|
|
997
986
|
const out = run.stdout ? JSON.parse(run.stdout) : null
|
|
998
987
|
const executable = join(home, '.local', 'bin', 'dingtalk-agent')
|
|
988
|
+
const alias = join(home, '.local', 'bin', 'dta')
|
|
999
989
|
const version = existsSync(executable)
|
|
1000
990
|
? spawnSync(executable, ['--version'], { env, encoding: 'utf8' })
|
|
1001
991
|
: { status: -1, stdout: '' }
|
|
992
|
+
const aliasVersion = existsSync(alias)
|
|
993
|
+
? spawnSync(alias, ['--version'], { env, encoding: 'utf8' })
|
|
994
|
+
: { status: -1, stdout: '' }
|
|
1002
995
|
const rc = existsSync(join(home, '.zshrc')) ? readFileSync(join(home, '.zshrc'), 'utf8') : ''
|
|
1003
996
|
const canonical = join(home, '.agents', 'skills', 'dingtalk-basic-behavior')
|
|
1004
997
|
const claude = join(home, '.claude', 'skills', 'dingtalk-basic-behavior')
|
|
1005
998
|
return {
|
|
1006
999
|
output: {
|
|
1007
1000
|
status: run.status, stderr: run.stderr.trim(), report: out,
|
|
1008
|
-
executable, version: String(version.stdout || '').trim(),
|
|
1001
|
+
executable, alias, version: String(version.stdout || '').trim(),
|
|
1002
|
+
aliasVersion: String(aliasVersion.stdout || '').trim(), rc,
|
|
1009
1003
|
},
|
|
1010
1004
|
toolCalls: 1, steps: 6,
|
|
1011
1005
|
checks: [
|
|
1012
|
-
check(run.status === 0 && existsSync(executable) && version.status === 0
|
|
1013
|
-
|
|
1006
|
+
check(run.status === 0 && existsSync(executable) && version.status === 0 &&
|
|
1007
|
+
existsSync(alias) && aliasVersion.status === 0 && aliasVersion.stdout === version.stdout,
|
|
1008
|
+
`status=${run.status}; executable=${existsSync(executable)}; alias=${existsSync(alias)}; ` +
|
|
1009
|
+
`version=${version.status}/${aliasVersion.status}`),
|
|
1014
1010
|
check(out?.shell.updated === true && rc.includes('dingtalk-agent PATH') &&
|
|
1015
1011
|
rc.includes('$HOME/.local/bin'),
|
|
1016
1012
|
`updated=${out?.shell.updated}; rc=${JSON.stringify(rc)}`),
|
|
@@ -1025,6 +1021,28 @@ function evalFirstRunSetup() {
|
|
|
1025
1021
|
}
|
|
1026
1022
|
}
|
|
1027
1023
|
|
|
1024
|
+
function evalCliErrorHints() {
|
|
1025
|
+
const typo = spawnSync(process.execPath, [CLI, 'doctro'], { encoding: 'utf8' })
|
|
1026
|
+
const subcommand = spawnSync(process.execPath, [CLI, 'skill', 'instal'], { encoding: 'utf8' })
|
|
1027
|
+
const option = spawnSync(process.execPath, [CLI, 'doctor', '--bogus'], { encoding: 'utf8' })
|
|
1028
|
+
return {
|
|
1029
|
+
output: {
|
|
1030
|
+
typo: { status: typo.status, stderr: typo.stderr.trim() },
|
|
1031
|
+
subcommand: { status: subcommand.status, stderr: subcommand.stderr.trim() },
|
|
1032
|
+
option: { status: option.status, stderr: option.stderr.trim() },
|
|
1033
|
+
},
|
|
1034
|
+
toolCalls: 3, steps: 3,
|
|
1035
|
+
checks: [
|
|
1036
|
+
check(typo.status === 1 && typo.stderr.includes('错误:') &&
|
|
1037
|
+
typo.stderr.includes('提示:') && typo.stderr.includes('dta doctor'), typo.stderr.trim()),
|
|
1038
|
+
check(subcommand.status === 1 && subcommand.stderr.includes('dta skill install'),
|
|
1039
|
+
subcommand.stderr.trim()),
|
|
1040
|
+
check(option.status === 2 && option.stderr.includes('检查参数拼写') &&
|
|
1041
|
+
option.stderr.includes('dta --help'), option.stderr.trim()),
|
|
1042
|
+
],
|
|
1043
|
+
}
|
|
1044
|
+
}
|
|
1045
|
+
|
|
1028
1046
|
function dmEvent(eventId, messageId, actor, text, extra = {}) {
|
|
1029
1047
|
return {
|
|
1030
1048
|
event_corp_id: extra.tenantId || 'tenant-wait-eval',
|