@xdxer/dingtalk-agent 0.1.5-beta.7 → 0.1.5-beta.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +14 -0
- package/dist/bin/dingtalk-agent.js +3 -1
- package/dist/bin/dingtalk-agent.js.map +1 -1
- package/dist/src/skill-manager.js +76 -9
- package/dist/src/skill-manager.js.map +1 -1
- package/package.json +1 -1
- package/dist/src/map.js +0 -157
- package/dist/src/map.js.map +0 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// Skill 安装生命周期由开放生态的 `npx skills` 负责。
|
|
2
2
|
// dingtalk-agent 只做两件事:把内置 Skill 目录交给上游 CLI;只读验证客户端能否发现。
|
|
3
3
|
// 默认(不指定 name)对全部内置 Skill 生效:基础行为 + Agent 装配 + 交付后评测;指定 name 时只操作该 Skill。
|
|
4
|
-
import { existsSync, lstatSync, readdirSync, readFileSync, readlinkSync, rmSync } from 'node:fs';
|
|
4
|
+
import { existsSync, lstatSync, readdirSync, readFileSync, readlinkSync, rmSync, unlinkSync, } from 'node:fs';
|
|
5
5
|
import { homedir } from 'node:os';
|
|
6
6
|
import { dirname, join, resolve } from 'node:path';
|
|
7
7
|
import { spawnSync } from 'node:child_process';
|
|
@@ -60,6 +60,10 @@ const LEGACY_BASIC_SKILL_NAMES = Object.entries(LEGACY_SKILL_RENAMES)
|
|
|
60
60
|
export function isBasicSkillName(name) {
|
|
61
61
|
return name === GLOBAL_SKILL_NAME || LEGACY_BASIC_SKILL_NAMES.includes(name);
|
|
62
62
|
}
|
|
63
|
+
// 已经从包里删除、且没有替代品的 Skill。它们不会被任何 install 装回来,也就永远
|
|
64
|
+
// 不会自己消失:`dingtalk-agent-boot-multica` 在 0.1.5-beta.2 就已移除,却仍留在
|
|
65
|
+
// 机器上并通过 ~/.claude/skills 的符号链继续作为可用 Skill 暴露给 Host。
|
|
66
|
+
export const REMOVED_SKILL_NAMES = ['dingtalk-agent-boot-multica'];
|
|
63
67
|
/**
|
|
64
68
|
* 删除改名前留在本机的旧名副本。install/upgrade 每次都调用,幂等。
|
|
65
69
|
*
|
|
@@ -76,15 +80,67 @@ export function pruneLegacySkills(home = homedir()) {
|
|
|
76
80
|
for (const [name, replacedBy] of Object.entries(LEGACY_SKILL_RENAMES)) {
|
|
77
81
|
if (!isDirectory(join(home, '.agents', 'skills', replacedBy)))
|
|
78
82
|
continue;
|
|
79
|
-
const removed =
|
|
80
|
-
|
|
81
|
-
|
|
83
|
+
const removed = removeSkillCopies(home, name);
|
|
84
|
+
if (removed.length)
|
|
85
|
+
pruned.push({ name, replacedBy, removed });
|
|
86
|
+
}
|
|
87
|
+
// 停用的 Skill 没有「现名已落地」这道闸门可用——它本来就不该再存在于任何机器上。
|
|
88
|
+
for (const name of REMOVED_SKILL_NAMES) {
|
|
89
|
+
const removed = removeSkillCopies(home, name);
|
|
90
|
+
if (removed.length)
|
|
91
|
+
pruned.push({ name, replacedBy: '', removed });
|
|
92
|
+
}
|
|
93
|
+
return pruned;
|
|
94
|
+
}
|
|
95
|
+
function removeSkillCopies(home, name) {
|
|
96
|
+
const removed = [];
|
|
97
|
+
for (const path of [join(home, '.agents', 'skills', name), join(home, '.claude', 'skills', name)]) {
|
|
98
|
+
let stat;
|
|
99
|
+
try {
|
|
100
|
+
stat = lstatSync(path);
|
|
101
|
+
}
|
|
102
|
+
catch {
|
|
82
103
|
continue;
|
|
83
|
-
|
|
104
|
+
}
|
|
105
|
+
// 符号链接必须 unlink。canonical 先删、exposure 后删,到这一步 Claude 那条链接
|
|
106
|
+
// 已经悬空,而 rmSync 是按**目标**去 stat 的:ENOENT 被 force 当成「本来就没有」
|
|
107
|
+
// 吞掉,链接原地不动。于是 Host 继续看得见这个 Skill,每轮清理还会重复上报一次。
|
|
108
|
+
if (stat.isSymbolicLink())
|
|
109
|
+
unlinkSync(path);
|
|
110
|
+
else
|
|
84
111
|
rmSync(path, { recursive: true, force: true });
|
|
85
|
-
|
|
112
|
+
removed.push(path);
|
|
86
113
|
}
|
|
87
|
-
return
|
|
114
|
+
return removed;
|
|
115
|
+
}
|
|
116
|
+
/** 旧名还装着、现名却没装上的 Skill。它们卡在半路,不会自己往前走。 */
|
|
117
|
+
export function strandedLegacySkills(home = homedir()) {
|
|
118
|
+
return Object.entries(LEGACY_SKILL_RENAMES)
|
|
119
|
+
.filter(([name, replacedBy]) => pathExists(join(home, '.agents', 'skills', name)) &&
|
|
120
|
+
!isDirectory(join(home, '.agents', 'skills', replacedBy)))
|
|
121
|
+
.map(([name, replacedBy]) => ({ name, replacedBy }));
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* 把卡在旧名上的 Skill 真正迁移过去:先装现名,再删旧名。
|
|
125
|
+
*
|
|
126
|
+
* 只对**本机已经装了旧名**的 Skill 动作,所以它保留用户既有的能力,而不是凭空多装
|
|
127
|
+
* 东西。平台 Skill(deploy/ops)不在默认套装里,光靠 `skill install` 永远等不到自己
|
|
128
|
+
* 的替代品——没有这一步,升级完它们就永久停在改名前的陈旧副本上,且无人告知。
|
|
129
|
+
*/
|
|
130
|
+
export function migrateStrandedLegacySkills(packageRoot, options = {}) {
|
|
131
|
+
const home = options.home || options.env?.HOME || process.env.HOME || homedir();
|
|
132
|
+
if (options.dryRun)
|
|
133
|
+
return [];
|
|
134
|
+
const migrated = [];
|
|
135
|
+
for (const { replacedBy } of strandedLegacySkills(home)) {
|
|
136
|
+
if (!INSTALLABLE_SKILL_NAMES.includes(replacedBy))
|
|
137
|
+
continue;
|
|
138
|
+
// 装现名的那一步内部就会清掉对应旧名,报告在它的 status 上——必须收下来,
|
|
139
|
+
// 否则迁移做了却没人说,正是「静默删目录」要避免的那种沉默。
|
|
140
|
+
migrated.push(...(installGlobalSkill(packageRoot, { ...options, name: replacedBy })
|
|
141
|
+
.prunedLegacy || []));
|
|
142
|
+
}
|
|
143
|
+
return [...migrated, ...pruneLegacySkills(home)];
|
|
88
144
|
}
|
|
89
145
|
const SKILLS_PACKAGE = 'skills@latest';
|
|
90
146
|
const REGISTRY = 'https://registry.npmjs.org';
|
|
@@ -93,12 +149,23 @@ export function skillSuiteStatus(packageRoot, options = {}) {
|
|
|
93
149
|
return suiteOf(BUNDLED_SKILL_NAMES.map((name) => skillStatus(packageRoot, { ...options, name })));
|
|
94
150
|
}
|
|
95
151
|
export function installBundledSkills(packageRoot, options = {}) {
|
|
96
|
-
|
|
152
|
+
const suite = suiteOf(BUNDLED_SKILL_NAMES
|
|
97
153
|
.map((name) => installGlobalSkill(packageRoot, { ...options, name })));
|
|
154
|
+
return withStrandedMigration(suite, packageRoot, options);
|
|
98
155
|
}
|
|
99
156
|
export function upgradeBundledSkills(packageRoot, options = {}) {
|
|
100
|
-
|
|
157
|
+
const suite = suiteOf(BUNDLED_SKILL_NAMES
|
|
101
158
|
.map((name) => upgradeGlobalSkill(packageRoot, { ...options, name })));
|
|
159
|
+
return withStrandedMigration(suite, packageRoot, options);
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* 套装装完之后再补一轮:默认套装只覆盖 core,卡在旧名上的平台 Skill 只能在这里
|
|
163
|
+
* 被带过去,否则升级完就永久停在改名前的副本上。
|
|
164
|
+
*/
|
|
165
|
+
function withStrandedMigration(suite, packageRoot, options) {
|
|
166
|
+
const migrated = migrateStrandedLegacySkills(packageRoot, options);
|
|
167
|
+
const prunedLegacy = [...(suite.prunedLegacy || []), ...migrated];
|
|
168
|
+
return { ...suite, ...(prunedLegacy.length ? { prunedLegacy } : {}) };
|
|
102
169
|
}
|
|
103
170
|
export function uninstallBundledSkills(packageRoot, options = {}) {
|
|
104
171
|
return suiteOf(BUNDLED_SKILL_NAMES.map((name) => uninstallGlobalSkill(packageRoot, { ...options, name })));
|
|
@@ -1 +1 @@
|
|
|
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// 默认(不指定 name)对全部内置 Skill 生效:基础行为 + Agent 装配 + 交付后评测;指定 name 时只操作该 Skill。\n\nimport { existsSync, lstatSync, readdirSync, readFileSync, readlinkSync, rmSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { dirname, join, resolve } from 'node:path'\nimport { spawnSync } from 'node:child_process'\nimport { createHash } from 'node:crypto'\nimport { cleanVersion, compareVersions, isValidVersion } from './version.js'\n\nexport const GLOBAL_SKILL_NAME = 'dta-basic-behavior'\n// 默认套装:所有机器都装的通用 Skill。平台 Skill(deploy/ops 等)不在默认套装内,\n// 只有工作区通过 `dta agent-platform use` 选择对应 managed agent platform 时才按名安装。\n// 默认套装:所有机器都装的通用 Skill。\n// people-group-memory 属于默认套装而非可选包:它是标准能力,且**未绑定存储前完全惰性**\n// (零写入、零探测、零副作用),所以人人都装不会产生后果;用户主动要求时才绑定并激活。\nexport const BUNDLED_SKILL_NAMES = [\n GLOBAL_SKILL_NAME, 'dta-agent-compose', 'dta-agent-eval',\n 'dta-people-group-memory',\n] as const\nexport const INSTALLABLE_SKILL_NAMES = [\n ...BUNDLED_SKILL_NAMES,\n 'dta-deploy-multica', 'dta-ops-multica',\n] as const\n\n// 仓库/包内的 Skill 源码路径注册表:core 为通用套装,platforms/<platform> 按平台装填。\n// 安装后的 canonical 布局仍是扁平的 ~/.agents/skills/<name>;分层只存在于包内。\nconst BUNDLED_SKILL_DIRS: Record<string, string> = {\n 'dta-basic-behavior': 'skills/core/dta-basic-behavior',\n 'dta-agent-compose': 'skills/core/dta-agent-compose',\n 'dta-agent-eval': 'skills/core/dta-agent-eval',\n 'dta-people-group-memory': 'skills/core/dta-people-group-memory',\n 'dta-deploy-multica': 'skills/platforms/multica-dingtalk/dta-deploy-multica',\n 'dta-ops-multica': 'skills/platforms/multica-dingtalk/dta-ops-multica',\n}\n\n/** 解析包内 Skill 源码目录;未注册的名字回退到历史扁平布局。 */\nexport function bundledSkillPath(packageRoot: string, name: string): string {\n return join(packageRoot, BUNDLED_SKILL_DIRS[name] || join('skills', name))\n}\n\n// 改名前的旧名 → 现名。一方 Skill 在 0.1.5-beta.7 统一到 `dta-` 前缀。\n//\n// ~/.agents/skills/ 是**扁平共享目录**:改名后 install 会装出新名目录,旧名目录却原地\n// 不动,于是三个 Host 会同时发现两份 description 几乎一样的 Skill,触发哪一份不确定。\n// 旧副本没有任何保留价值——它是本包发布的、已被取代的同一份东西——所以直接在\n// install/upgrade 时删掉,不做「先警告再等用户确认」的两段式。\nexport const LEGACY_SKILL_RENAMES: Record<string, string> = {\n 'dingtalk-basic-behavior': 'dta-basic-behavior',\n 'dingtalk-agent-compose': 'dta-agent-compose',\n 'dingtalk-agent-eval': 'dta-agent-eval',\n 'dingtalk-people-group-memory': 'dta-people-group-memory',\n 'dingtalk-agent-deploy-multica': 'dta-deploy-multica',\n 'multica-external': 'dta-ops-multica',\n}\n\nconst LEGACY_BASIC_SKILL_NAMES = Object.entries(LEGACY_SKILL_RENAMES)\n .filter(([, current]) => current === GLOBAL_SKILL_NAME).map(([legacy]) => legacy)\n\n/**\n * 声明的名字是否指向 Basic Skill(含改名前的旧名)。\n *\n * 只放宽「是不是 Basic」的判定,**不做名字归一化**:调用方必须继续用声明的原名解析\n * 路径,否则用户仓库里已 check-in 的 `agent/skills/dingtalk-basic-behavior/` 会解析不到。\n */\nexport function isBasicSkillName(name: string): boolean {\n return name === GLOBAL_SKILL_NAME || LEGACY_BASIC_SKILL_NAMES.includes(name)\n}\n\nexport interface PrunedLegacySkill {\n name: string\n replacedBy: string\n removed: string[]\n}\n\n/**\n * 删除改名前留在本机的旧名副本。install/upgrade 每次都调用,幂等。\n *\n * 只碰 LEGACY_SKILL_RENAMES 里登记过的名字,且只在本包自己的两个安装位置下操作——\n * 不接受外部传名,避免这个函数退化成任意目录删除器。\n *\n * **前置条件是现名副本已经落地**,不是「调用顺序排在 install 后面」。两者不等价:\n * 平台 Skill(deploy/ops)不在默认套装里,`skill install` 根本不会装它们,若按调用\n * 顺序推断就会把只装过 multica-external 的机器删成两手空空。以现名 canonical 是否\n * 存在为闸门,这类顺序推理错误就不可能发生——没装上就一定不删。\n */\nexport function pruneLegacySkills(home = homedir()): PrunedLegacySkill[] {\n const pruned: PrunedLegacySkill[] = []\n for (const [name, replacedBy] of Object.entries(LEGACY_SKILL_RENAMES)) {\n if (!isDirectory(join(home, '.agents', 'skills', replacedBy))) continue\n const removed = [join(home, '.agents', 'skills', name), join(home, '.claude', 'skills', name)]\n .filter(pathExists)\n if (!removed.length) continue\n for (const path of removed) rmSync(path, { recursive: true, force: true })\n pruned.push({ name, replacedBy, removed })\n }\n return pruned\n}\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 name?: string\n allowDowngrade?: boolean\n}\n\n/**\n * 本机副本相对包内 Skill 的漂移状态。`current` 是它的派生布尔,保留给既有读者。\n * 版本相等但内容不同(用户手改过)必须与真正一致区分开,否则升级提示会漏掉这类漂移。\n */\nexport type SkillDriftState =\n | 'missing' // canonical 不存在\n | 'current' // 版本相等且内容 hash 相等\n | 'modified' // 版本相等但内容 hash 不等\n | 'outdated' // 已装版本低于包内版本\n | 'ahead' // 已装版本高于包内版本\n | 'unknown' // 已装版本缺失或非法\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; contentHash: string }\n canonical: {\n path: string\n exists: boolean\n installedVersion: string\n installedHash: string\n state: SkillDriftState\n comparison: number | null\n current: boolean\n }\n claude: { path: string; state: 'ok' | 'missing' | 'conflict'; target: string }\n /** 本次 install/upgrade 顺带清掉的改名前旧副本(现名落地后才会有)。 */\n prunedLegacy?: PrunedLegacySkill[]\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 before: { installedVersion: string; state: SkillDriftState }\n after: { installedVersion: string; state: SkillDriftState } | null\n }\n}\n\nexport interface GlobalSkillSuiteStatus {\n $schema: 'dingtalk-agent/skill-status-suite@1'\n manager: 'skills-cli'\n names: string[]\n skills: GlobalSkillStatus[]\n /** 本次 install/upgrade 顺带清掉的改名前旧副本;status/uninstall 不返回此字段。 */\n prunedLegacy?: PrunedLegacySkill[]\n}\n\nexport function skillSuiteStatus(\n packageRoot: string,\n options: Omit<SkillManagerOptions, 'name'> = {},\n): GlobalSkillSuiteStatus {\n return suiteOf(BUNDLED_SKILL_NAMES.map((name) => skillStatus(packageRoot, { ...options, name })))\n}\n\nexport function installBundledSkills(\n packageRoot: string,\n options: Omit<SkillManagerOptions, 'name'> = {},\n): GlobalSkillSuiteStatus {\n return suiteOf(BUNDLED_SKILL_NAMES\n .map((name) => installGlobalSkill(packageRoot, { ...options, name })))\n}\n\nexport function upgradeBundledSkills(\n packageRoot: string,\n options: Omit<SkillManagerOptions, 'name'> = {},\n): GlobalSkillSuiteStatus {\n return suiteOf(BUNDLED_SKILL_NAMES\n .map((name) => upgradeGlobalSkill(packageRoot, { ...options, name })))\n}\n\nexport function uninstallBundledSkills(\n packageRoot: string,\n options: Omit<SkillManagerOptions, 'name'> = {},\n): GlobalSkillSuiteStatus {\n return suiteOf(BUNDLED_SKILL_NAMES.map((name) => uninstallGlobalSkill(packageRoot, { ...options, name })))\n}\n\nfunction suiteOf(skills: GlobalSkillStatus[]): GlobalSkillSuiteStatus {\n // 每个 Skill 装完各自清理各自的旧名,套装层只做汇总,不再重复扫一遍。\n const prunedLegacy = skills.flatMap((skill) => skill.prunedLegacy || [])\n return {\n $schema: 'dingtalk-agent/skill-status-suite@1',\n manager: 'skills-cli',\n names: skills.map((skill) => skill.name),\n skills,\n ...(prunedLegacy.length ? { prunedLegacy } : {}),\n }\n}\n\nexport function skillStatus(packageRoot: string, options: SkillManagerOptions = {}): GlobalSkillStatus {\n const name = bundledSkillName(options.name)\n const paths = globalPaths(packageRoot, options.home, name)\n const bundled = bundledInfo(packageRoot, name)\n const canonicalExists = isDirectory(paths.canonical)\n const installedVersion = canonicalExists ? readInstalledVersion(paths.canonical) : ''\n const installedHash = canonicalExists ? skillContentHash(paths.canonical) : ''\n const drift = driftOf({\n exists: canonicalExists,\n installedVersion,\n installedHash,\n bundledVersion: bundled.skillVersion,\n bundledHash: bundled.contentHash,\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,\n manager: 'skills-cli',\n bundled,\n canonical: {\n path: paths.canonical,\n exists: canonicalExists,\n installedVersion,\n installedHash,\n state: drift.state,\n comparison: drift.comparison,\n current: drift.state === 'current',\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, undefined, bundledSkillName(options.name)).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, undefined, bundledSkillName(options.name)).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', bundledSkillName(options.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 = [\n '--yes', `--registry=${REGISTRY}`, `--package=${SKILLS_PACKAGE}`, '--', 'skills', ...args,\n ]\n const command = ['npx', ...commandArgs].map(shellQuote).join(' ')\n const before = skillStatus(packageRoot, options)\n const beforeState = { installedVersion: before.canonical.installedVersion, state: before.canonical.state }\n if (options.dryRun) {\n return {\n ...before,\n operation: {\n action, command, executed: false, exitCode: null, output: '',\n before: beforeState, after: null,\n },\n }\n }\n // 本机比包内新时覆盖就是降级;与 npm 包升级策略一致,默认拒绝。\n if (action !== 'uninstall' && before.canonical.state === 'ahead' && !options.allowDowngrade) {\n throw new Error(\n `拒绝降级 ${before.name}: 本机 ${before.canonical.installedVersion} 高于包内 ` +\n `${before.bundled.skillVersion};确认要覆盖时加 --allow-downgrade`,\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 // 退出码 0 不等于本机副本已经是目标版本;升级/安装后必须回读确认。\n const after = skillStatus(packageRoot, options)\n if (action !== 'uninstall' && after.canonical.state !== 'current') {\n throw new Error(\n `skills CLI ${action} 退出码为 0,但回读 ${after.name} 仍为 ${after.canonical.state}` +\n `(本机 ${after.canonical.installedVersion || '未声明'} / 包内 ${after.bundled.skillVersion})\\n` +\n `可手动执行: ${command}`,\n )\n }\n // 回读确认现名到位之后才清旧名。放在这一层而不是套装层,是为了让平台 Skill\n // (只经 `agent-platform use` 按名安装)走同一条清理路径,不必各自记得调一次。\n const prunedLegacy = action === 'uninstall'\n ? [] : pruneLegacySkills(env.HOME)\n return {\n ...after,\n ...(prunedLegacy.length ? { prunedLegacy } : {}),\n operation: {\n action, command, executed: true, exitCode: run.status, output,\n before: beforeState,\n after: { installedVersion: after.canonical.installedVersion, state: after.canonical.state },\n },\n }\n}\n\nfunction globalPaths(packageRoot: string, home = homedir(), name = GLOBAL_SKILL_NAME) {\n return {\n source: bundledSkillPath(packageRoot, name),\n canonical: join(home, '.agents', 'skills', name),\n claude: join(home, '.claude', 'skills', name),\n }\n}\n\nfunction bundledInfo(packageRoot: string, name: string) {\n const source = globalPaths(packageRoot, undefined, name).source\n validateSkill(source, name)\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 contentHash: skillContentHash(source),\n }\n}\n\n/** 本机副本的版本号;用户手改坏格式时返回空串并由调用方降级为 unknown,不抛错。 */\nfunction readInstalledVersion(canonical: string): string {\n try {\n return parseSkillFrontmatter(readFileSync(join(canonical, 'SKILL.md'), 'utf8')).version\n } catch {\n return ''\n }\n}\n\n/**\n * 全树内容 hash:按相对路径排序,逐个 update(相对路径 + \\0 + 内容)。\n * 它证明 references/assets 完整一致,补上\"改了正文但没 bump 版本\"这类版本号测不出的漂移。\n */\nexport function skillContentHash(root: string): string {\n const hash = createHash('sha256')\n for (const relative of listSkillFiles(root)) {\n hash.update(relative)\n hash.update('\\0')\n hash.update(readFileSync(join(root, relative)))\n }\n return `sha256:${hash.digest('hex').slice(0, 16)}`\n}\n\nfunction listSkillFiles(root: string, prefix = ''): string[] {\n const files: string[] = []\n for (const entry of readdirSync(join(root, prefix), { withFileTypes: true })) {\n if (entry.name === '.DS_Store' || entry.isSymbolicLink()) continue\n const relative = prefix ? `${prefix}/${entry.name}` : entry.name\n if (entry.isDirectory()) files.push(...listSkillFiles(root, relative))\n else if (entry.isFile()) files.push(relative)\n }\n return files.sort()\n}\n\nfunction driftOf(input: {\n exists: boolean\n installedVersion: string\n installedHash: string\n bundledVersion: string\n bundledHash: string\n}): { state: SkillDriftState; comparison: number | null } {\n if (!input.exists) return { state: 'missing', comparison: null }\n if (!isValidVersion(input.installedVersion)) return { state: 'unknown', comparison: null }\n const comparison = compareVersions(input.installedVersion, input.bundledVersion)\n if (comparison > 0) return { state: 'ahead', comparison }\n if (comparison < 0) return { state: 'outdated', comparison }\n return {\n state: input.installedHash === input.bundledHash ? 'current' : 'modified',\n comparison,\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, name: 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 !== name) {\n throw new Error(`Skill name=${metadata.name} 与目录名 ${name} 不一致`)\n }\n if (!metadata.description) throw new Error('Skill frontmatter 缺少 description')\n // 包内 Skill 缺版本号是仓库缺陷:没有版本就无法判断本机副本是否过期,直接 fail closed。\n if (!metadata.version) throw new Error(`Skill 缺少 metadata.version: ${root}`)\n cleanVersion(metadata.version)\n}\n\nfunction bundledSkillName(value = ''): string {\n const name = value.trim() || GLOBAL_SKILL_NAME\n if (!(INSTALLABLE_SKILL_NAMES as readonly string[]).includes(name)) {\n throw new Error(`不支持的内置 Skill: ${name};可用: ${INSTALLABLE_SKILL_NAMES.join(', ')}`)\n }\n return name\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"]}
|
|
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// 默认(不指定 name)对全部内置 Skill 生效:基础行为 + Agent 装配 + 交付后评测;指定 name 时只操作该 Skill。\n\nimport {\n existsSync, lstatSync, readdirSync, readFileSync, readlinkSync, rmSync, unlinkSync,\n} from 'node:fs'\nimport { homedir } from 'node:os'\nimport { dirname, join, resolve } from 'node:path'\nimport { spawnSync } from 'node:child_process'\nimport { createHash } from 'node:crypto'\nimport { cleanVersion, compareVersions, isValidVersion } from './version.js'\n\nexport const GLOBAL_SKILL_NAME = 'dta-basic-behavior'\n// 默认套装:所有机器都装的通用 Skill。平台 Skill(deploy/ops 等)不在默认套装内,\n// 只有工作区通过 `dta agent-platform use` 选择对应 managed agent platform 时才按名安装。\n// 默认套装:所有机器都装的通用 Skill。\n// people-group-memory 属于默认套装而非可选包:它是标准能力,且**未绑定存储前完全惰性**\n// (零写入、零探测、零副作用),所以人人都装不会产生后果;用户主动要求时才绑定并激活。\nexport const BUNDLED_SKILL_NAMES = [\n GLOBAL_SKILL_NAME, 'dta-agent-compose', 'dta-agent-eval',\n 'dta-people-group-memory',\n] as const\nexport const INSTALLABLE_SKILL_NAMES = [\n ...BUNDLED_SKILL_NAMES,\n 'dta-deploy-multica', 'dta-ops-multica',\n] as const\n\n// 仓库/包内的 Skill 源码路径注册表:core 为通用套装,platforms/<platform> 按平台装填。\n// 安装后的 canonical 布局仍是扁平的 ~/.agents/skills/<name>;分层只存在于包内。\nconst BUNDLED_SKILL_DIRS: Record<string, string> = {\n 'dta-basic-behavior': 'skills/core/dta-basic-behavior',\n 'dta-agent-compose': 'skills/core/dta-agent-compose',\n 'dta-agent-eval': 'skills/core/dta-agent-eval',\n 'dta-people-group-memory': 'skills/core/dta-people-group-memory',\n 'dta-deploy-multica': 'skills/platforms/multica-dingtalk/dta-deploy-multica',\n 'dta-ops-multica': 'skills/platforms/multica-dingtalk/dta-ops-multica',\n}\n\n/** 解析包内 Skill 源码目录;未注册的名字回退到历史扁平布局。 */\nexport function bundledSkillPath(packageRoot: string, name: string): string {\n return join(packageRoot, BUNDLED_SKILL_DIRS[name] || join('skills', name))\n}\n\n// 改名前的旧名 → 现名。一方 Skill 在 0.1.5-beta.7 统一到 `dta-` 前缀。\n//\n// ~/.agents/skills/ 是**扁平共享目录**:改名后 install 会装出新名目录,旧名目录却原地\n// 不动,于是三个 Host 会同时发现两份 description 几乎一样的 Skill,触发哪一份不确定。\n// 旧副本没有任何保留价值——它是本包发布的、已被取代的同一份东西——所以直接在\n// install/upgrade 时删掉,不做「先警告再等用户确认」的两段式。\nexport const LEGACY_SKILL_RENAMES: Record<string, string> = {\n 'dingtalk-basic-behavior': 'dta-basic-behavior',\n 'dingtalk-agent-compose': 'dta-agent-compose',\n 'dingtalk-agent-eval': 'dta-agent-eval',\n 'dingtalk-people-group-memory': 'dta-people-group-memory',\n 'dingtalk-agent-deploy-multica': 'dta-deploy-multica',\n 'multica-external': 'dta-ops-multica',\n}\n\nconst LEGACY_BASIC_SKILL_NAMES = Object.entries(LEGACY_SKILL_RENAMES)\n .filter(([, current]) => current === GLOBAL_SKILL_NAME).map(([legacy]) => legacy)\n\n/**\n * 声明的名字是否指向 Basic Skill(含改名前的旧名)。\n *\n * 只放宽「是不是 Basic」的判定,**不做名字归一化**:调用方必须继续用声明的原名解析\n * 路径,否则用户仓库里已 check-in 的 `agent/skills/dingtalk-basic-behavior/` 会解析不到。\n */\nexport function isBasicSkillName(name: string): boolean {\n return name === GLOBAL_SKILL_NAME || LEGACY_BASIC_SKILL_NAMES.includes(name)\n}\n\n// 已经从包里删除、且没有替代品的 Skill。它们不会被任何 install 装回来,也就永远\n// 不会自己消失:`dingtalk-agent-boot-multica` 在 0.1.5-beta.2 就已移除,却仍留在\n// 机器上并通过 ~/.claude/skills 的符号链继续作为可用 Skill 暴露给 Host。\nexport const REMOVED_SKILL_NAMES = ['dingtalk-agent-boot-multica']\n\nexport interface PrunedLegacySkill {\n name: string\n /** 已停用且无替代品时为空字符串。 */\n replacedBy: string\n removed: string[]\n}\n\n/**\n * 删除改名前留在本机的旧名副本。install/upgrade 每次都调用,幂等。\n *\n * 只碰 LEGACY_SKILL_RENAMES 里登记过的名字,且只在本包自己的两个安装位置下操作——\n * 不接受外部传名,避免这个函数退化成任意目录删除器。\n *\n * **前置条件是现名副本已经落地**,不是「调用顺序排在 install 后面」。两者不等价:\n * 平台 Skill(deploy/ops)不在默认套装里,`skill install` 根本不会装它们,若按调用\n * 顺序推断就会把只装过 multica-external 的机器删成两手空空。以现名 canonical 是否\n * 存在为闸门,这类顺序推理错误就不可能发生——没装上就一定不删。\n */\nexport function pruneLegacySkills(home = homedir()): PrunedLegacySkill[] {\n const pruned: PrunedLegacySkill[] = []\n for (const [name, replacedBy] of Object.entries(LEGACY_SKILL_RENAMES)) {\n if (!isDirectory(join(home, '.agents', 'skills', replacedBy))) continue\n const removed = removeSkillCopies(home, name)\n if (removed.length) pruned.push({ name, replacedBy, removed })\n }\n // 停用的 Skill 没有「现名已落地」这道闸门可用——它本来就不该再存在于任何机器上。\n for (const name of REMOVED_SKILL_NAMES) {\n const removed = removeSkillCopies(home, name)\n if (removed.length) pruned.push({ name, replacedBy: '', removed })\n }\n return pruned\n}\n\nfunction removeSkillCopies(home: string, name: string): string[] {\n const removed: string[] = []\n for (const path of [join(home, '.agents', 'skills', name), join(home, '.claude', 'skills', name)]) {\n let stat\n try { stat = lstatSync(path) } catch { continue }\n // 符号链接必须 unlink。canonical 先删、exposure 后删,到这一步 Claude 那条链接\n // 已经悬空,而 rmSync 是按**目标**去 stat 的:ENOENT 被 force 当成「本来就没有」\n // 吞掉,链接原地不动。于是 Host 继续看得见这个 Skill,每轮清理还会重复上报一次。\n if (stat.isSymbolicLink()) unlinkSync(path)\n else rmSync(path, { recursive: true, force: true })\n removed.push(path)\n }\n return removed\n}\n\n/** 旧名还装着、现名却没装上的 Skill。它们卡在半路,不会自己往前走。 */\nexport function strandedLegacySkills(home = homedir()): Array<{ name: string; replacedBy: string }> {\n return Object.entries(LEGACY_SKILL_RENAMES)\n .filter(([name, replacedBy]) =>\n pathExists(join(home, '.agents', 'skills', name)) &&\n !isDirectory(join(home, '.agents', 'skills', replacedBy)))\n .map(([name, replacedBy]) => ({ name, replacedBy }))\n}\n\n/**\n * 把卡在旧名上的 Skill 真正迁移过去:先装现名,再删旧名。\n *\n * 只对**本机已经装了旧名**的 Skill 动作,所以它保留用户既有的能力,而不是凭空多装\n * 东西。平台 Skill(deploy/ops)不在默认套装里,光靠 `skill install` 永远等不到自己\n * 的替代品——没有这一步,升级完它们就永久停在改名前的陈旧副本上,且无人告知。\n */\nexport function migrateStrandedLegacySkills(\n packageRoot: string,\n options: Omit<SkillManagerOptions, 'name'> = {},\n): PrunedLegacySkill[] {\n const home = options.home || options.env?.HOME || process.env.HOME || homedir()\n if (options.dryRun) return []\n const migrated: PrunedLegacySkill[] = []\n for (const { replacedBy } of strandedLegacySkills(home)) {\n if (!(INSTALLABLE_SKILL_NAMES as readonly string[]).includes(replacedBy)) continue\n // 装现名的那一步内部就会清掉对应旧名,报告在它的 status 上——必须收下来,\n // 否则迁移做了却没人说,正是「静默删目录」要避免的那种沉默。\n migrated.push(...(installGlobalSkill(packageRoot, { ...options, name: replacedBy })\n .prunedLegacy || []))\n }\n return [...migrated, ...pruneLegacySkills(home)]\n}\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 name?: string\n allowDowngrade?: boolean\n}\n\n/**\n * 本机副本相对包内 Skill 的漂移状态。`current` 是它的派生布尔,保留给既有读者。\n * 版本相等但内容不同(用户手改过)必须与真正一致区分开,否则升级提示会漏掉这类漂移。\n */\nexport type SkillDriftState =\n | 'missing' // canonical 不存在\n | 'current' // 版本相等且内容 hash 相等\n | 'modified' // 版本相等但内容 hash 不等\n | 'outdated' // 已装版本低于包内版本\n | 'ahead' // 已装版本高于包内版本\n | 'unknown' // 已装版本缺失或非法\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; contentHash: string }\n canonical: {\n path: string\n exists: boolean\n installedVersion: string\n installedHash: string\n state: SkillDriftState\n comparison: number | null\n current: boolean\n }\n claude: { path: string; state: 'ok' | 'missing' | 'conflict'; target: string }\n /** 本次 install/upgrade 顺带清掉的改名前旧副本(现名落地后才会有)。 */\n prunedLegacy?: PrunedLegacySkill[]\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 before: { installedVersion: string; state: SkillDriftState }\n after: { installedVersion: string; state: SkillDriftState } | null\n }\n}\n\nexport interface GlobalSkillSuiteStatus {\n $schema: 'dingtalk-agent/skill-status-suite@1'\n manager: 'skills-cli'\n names: string[]\n skills: GlobalSkillStatus[]\n /** 本次 install/upgrade 顺带清掉的改名前旧副本;status/uninstall 不返回此字段。 */\n prunedLegacy?: PrunedLegacySkill[]\n}\n\nexport function skillSuiteStatus(\n packageRoot: string,\n options: Omit<SkillManagerOptions, 'name'> = {},\n): GlobalSkillSuiteStatus {\n return suiteOf(BUNDLED_SKILL_NAMES.map((name) => skillStatus(packageRoot, { ...options, name })))\n}\n\nexport function installBundledSkills(\n packageRoot: string,\n options: Omit<SkillManagerOptions, 'name'> = {},\n): GlobalSkillSuiteStatus {\n const suite = suiteOf(BUNDLED_SKILL_NAMES\n .map((name) => installGlobalSkill(packageRoot, { ...options, name })))\n return withStrandedMigration(suite, packageRoot, options)\n}\n\nexport function upgradeBundledSkills(\n packageRoot: string,\n options: Omit<SkillManagerOptions, 'name'> = {},\n): GlobalSkillSuiteStatus {\n const suite = suiteOf(BUNDLED_SKILL_NAMES\n .map((name) => upgradeGlobalSkill(packageRoot, { ...options, name })))\n return withStrandedMigration(suite, packageRoot, options)\n}\n\n/**\n * 套装装完之后再补一轮:默认套装只覆盖 core,卡在旧名上的平台 Skill 只能在这里\n * 被带过去,否则升级完就永久停在改名前的副本上。\n */\nfunction withStrandedMigration(\n suite: GlobalSkillSuiteStatus,\n packageRoot: string,\n options: Omit<SkillManagerOptions, 'name'>,\n): GlobalSkillSuiteStatus {\n const migrated = migrateStrandedLegacySkills(packageRoot, options)\n const prunedLegacy = [...(suite.prunedLegacy || []), ...migrated]\n return { ...suite, ...(prunedLegacy.length ? { prunedLegacy } : {}) }\n}\n\nexport function uninstallBundledSkills(\n packageRoot: string,\n options: Omit<SkillManagerOptions, 'name'> = {},\n): GlobalSkillSuiteStatus {\n return suiteOf(BUNDLED_SKILL_NAMES.map((name) => uninstallGlobalSkill(packageRoot, { ...options, name })))\n}\n\nfunction suiteOf(skills: GlobalSkillStatus[]): GlobalSkillSuiteStatus {\n // 每个 Skill 装完各自清理各自的旧名,套装层只做汇总,不再重复扫一遍。\n const prunedLegacy = skills.flatMap((skill) => skill.prunedLegacy || [])\n return {\n $schema: 'dingtalk-agent/skill-status-suite@1',\n manager: 'skills-cli',\n names: skills.map((skill) => skill.name),\n skills,\n ...(prunedLegacy.length ? { prunedLegacy } : {}),\n }\n}\n\nexport function skillStatus(packageRoot: string, options: SkillManagerOptions = {}): GlobalSkillStatus {\n const name = bundledSkillName(options.name)\n const paths = globalPaths(packageRoot, options.home, name)\n const bundled = bundledInfo(packageRoot, name)\n const canonicalExists = isDirectory(paths.canonical)\n const installedVersion = canonicalExists ? readInstalledVersion(paths.canonical) : ''\n const installedHash = canonicalExists ? skillContentHash(paths.canonical) : ''\n const drift = driftOf({\n exists: canonicalExists,\n installedVersion,\n installedHash,\n bundledVersion: bundled.skillVersion,\n bundledHash: bundled.contentHash,\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,\n manager: 'skills-cli',\n bundled,\n canonical: {\n path: paths.canonical,\n exists: canonicalExists,\n installedVersion,\n installedHash,\n state: drift.state,\n comparison: drift.comparison,\n current: drift.state === 'current',\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, undefined, bundledSkillName(options.name)).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, undefined, bundledSkillName(options.name)).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', bundledSkillName(options.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 = [\n '--yes', `--registry=${REGISTRY}`, `--package=${SKILLS_PACKAGE}`, '--', 'skills', ...args,\n ]\n const command = ['npx', ...commandArgs].map(shellQuote).join(' ')\n const before = skillStatus(packageRoot, options)\n const beforeState = { installedVersion: before.canonical.installedVersion, state: before.canonical.state }\n if (options.dryRun) {\n return {\n ...before,\n operation: {\n action, command, executed: false, exitCode: null, output: '',\n before: beforeState, after: null,\n },\n }\n }\n // 本机比包内新时覆盖就是降级;与 npm 包升级策略一致,默认拒绝。\n if (action !== 'uninstall' && before.canonical.state === 'ahead' && !options.allowDowngrade) {\n throw new Error(\n `拒绝降级 ${before.name}: 本机 ${before.canonical.installedVersion} 高于包内 ` +\n `${before.bundled.skillVersion};确认要覆盖时加 --allow-downgrade`,\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 // 退出码 0 不等于本机副本已经是目标版本;升级/安装后必须回读确认。\n const after = skillStatus(packageRoot, options)\n if (action !== 'uninstall' && after.canonical.state !== 'current') {\n throw new Error(\n `skills CLI ${action} 退出码为 0,但回读 ${after.name} 仍为 ${after.canonical.state}` +\n `(本机 ${after.canonical.installedVersion || '未声明'} / 包内 ${after.bundled.skillVersion})\\n` +\n `可手动执行: ${command}`,\n )\n }\n // 回读确认现名到位之后才清旧名。放在这一层而不是套装层,是为了让平台 Skill\n // (只经 `agent-platform use` 按名安装)走同一条清理路径,不必各自记得调一次。\n const prunedLegacy = action === 'uninstall'\n ? [] : pruneLegacySkills(env.HOME)\n return {\n ...after,\n ...(prunedLegacy.length ? { prunedLegacy } : {}),\n operation: {\n action, command, executed: true, exitCode: run.status, output,\n before: beforeState,\n after: { installedVersion: after.canonical.installedVersion, state: after.canonical.state },\n },\n }\n}\n\nfunction globalPaths(packageRoot: string, home = homedir(), name = GLOBAL_SKILL_NAME) {\n return {\n source: bundledSkillPath(packageRoot, name),\n canonical: join(home, '.agents', 'skills', name),\n claude: join(home, '.claude', 'skills', name),\n }\n}\n\nfunction bundledInfo(packageRoot: string, name: string) {\n const source = globalPaths(packageRoot, undefined, name).source\n validateSkill(source, name)\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 contentHash: skillContentHash(source),\n }\n}\n\n/** 本机副本的版本号;用户手改坏格式时返回空串并由调用方降级为 unknown,不抛错。 */\nfunction readInstalledVersion(canonical: string): string {\n try {\n return parseSkillFrontmatter(readFileSync(join(canonical, 'SKILL.md'), 'utf8')).version\n } catch {\n return ''\n }\n}\n\n/**\n * 全树内容 hash:按相对路径排序,逐个 update(相对路径 + \\0 + 内容)。\n * 它证明 references/assets 完整一致,补上\"改了正文但没 bump 版本\"这类版本号测不出的漂移。\n */\nexport function skillContentHash(root: string): string {\n const hash = createHash('sha256')\n for (const relative of listSkillFiles(root)) {\n hash.update(relative)\n hash.update('\\0')\n hash.update(readFileSync(join(root, relative)))\n }\n return `sha256:${hash.digest('hex').slice(0, 16)}`\n}\n\nfunction listSkillFiles(root: string, prefix = ''): string[] {\n const files: string[] = []\n for (const entry of readdirSync(join(root, prefix), { withFileTypes: true })) {\n if (entry.name === '.DS_Store' || entry.isSymbolicLink()) continue\n const relative = prefix ? `${prefix}/${entry.name}` : entry.name\n if (entry.isDirectory()) files.push(...listSkillFiles(root, relative))\n else if (entry.isFile()) files.push(relative)\n }\n return files.sort()\n}\n\nfunction driftOf(input: {\n exists: boolean\n installedVersion: string\n installedHash: string\n bundledVersion: string\n bundledHash: string\n}): { state: SkillDriftState; comparison: number | null } {\n if (!input.exists) return { state: 'missing', comparison: null }\n if (!isValidVersion(input.installedVersion)) return { state: 'unknown', comparison: null }\n const comparison = compareVersions(input.installedVersion, input.bundledVersion)\n if (comparison > 0) return { state: 'ahead', comparison }\n if (comparison < 0) return { state: 'outdated', comparison }\n return {\n state: input.installedHash === input.bundledHash ? 'current' : 'modified',\n comparison,\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, name: 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 !== name) {\n throw new Error(`Skill name=${metadata.name} 与目录名 ${name} 不一致`)\n }\n if (!metadata.description) throw new Error('Skill frontmatter 缺少 description')\n // 包内 Skill 缺版本号是仓库缺陷:没有版本就无法判断本机副本是否过期,直接 fail closed。\n if (!metadata.version) throw new Error(`Skill 缺少 metadata.version: ${root}`)\n cleanVersion(metadata.version)\n}\n\nfunction bundledSkillName(value = ''): string {\n const name = value.trim() || GLOBAL_SKILL_NAME\n if (!(INSTALLABLE_SKILL_NAMES as readonly string[]).includes(name)) {\n throw new Error(`不支持的内置 Skill: ${name};可用: ${INSTALLABLE_SKILL_NAMES.join(', ')}`)\n }\n return name\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/package.json
CHANGED
package/dist/src/map.js
DELETED
|
@@ -1,157 +0,0 @@
|
|
|
1
|
-
// Managed Agents Platform(MAP)注册表与工作区归属解析。
|
|
2
|
-
//
|
|
3
|
-
// 一个 Agent 工作区归属于至多一个托管平台;归属解析顺序固定:
|
|
4
|
-
// DTA_MAP 环境变量 > dingtalk-agent.json#map > .dingtalk-agent/map.json > 按 Provider 声明推断。
|
|
5
|
-
// 平台相关的方法学不写进 CLI——它们随对应平台的 Skill 包分发,只在用户选择该平台时安装。
|
|
6
|
-
// 平台命令(如 deploy/promote/observe)必须先通过归属门禁;coming-soon 平台一律 fail-closed。
|
|
7
|
-
import { existsSync, lstatSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
8
|
-
import { dirname, join, parse, resolve } from 'node:path';
|
|
9
|
-
import { findAgentProjectRoot } from './development-workspace.js';
|
|
10
|
-
import { installGlobalSkill } from './skill-manager.js';
|
|
11
|
-
export const MANAGED_AGENT_PLATFORMS = [
|
|
12
|
-
{
|
|
13
|
-
name: 'multica-dingtalk',
|
|
14
|
-
label: 'Multica (DingTalk)',
|
|
15
|
-
status: 'supported',
|
|
16
|
-
description: '钉钉 Multica 托管平台:受控部署、晋级与观测回流。',
|
|
17
|
-
skills: ['dingtalk-agent-deploy', 'dingtalk-agent-boot-multica'],
|
|
18
|
-
commands: ['deploy', 'promote', 'observe'],
|
|
19
|
-
},
|
|
20
|
-
{
|
|
21
|
-
name: 'deap',
|
|
22
|
-
label: 'DEAP',
|
|
23
|
-
status: 'coming-soon',
|
|
24
|
-
description: '敬请期待。',
|
|
25
|
-
skills: [],
|
|
26
|
-
commands: [],
|
|
27
|
-
},
|
|
28
|
-
];
|
|
29
|
-
export const MAP_FILE = '.dingtalk-agent/map.json';
|
|
30
|
-
const PROJECT_FILE = 'dingtalk-agent.json';
|
|
31
|
-
export function mapDefinition(name) {
|
|
32
|
-
return MANAGED_AGENT_PLATFORMS.find((item) => item.name === name) || null;
|
|
33
|
-
}
|
|
34
|
-
export function resolveMap(start = process.cwd(), env = process.env) {
|
|
35
|
-
const fromEnv = String(env.DTA_MAP || '').trim();
|
|
36
|
-
if (fromEnv)
|
|
37
|
-
return resolution(fromEnv, 'env', '');
|
|
38
|
-
const projectRoot = findAgentProjectRoot(start);
|
|
39
|
-
if (projectRoot) {
|
|
40
|
-
const manifestPath = join(projectRoot, PROJECT_FILE);
|
|
41
|
-
if (existsSync(manifestPath) && !lstatSync(manifestPath).isSymbolicLink()) {
|
|
42
|
-
const manifest = readJsonOrNull(manifestPath);
|
|
43
|
-
const declared = typeof manifest?.map === 'string' ? manifest.map.trim() : '';
|
|
44
|
-
if (declared)
|
|
45
|
-
return resolution(declared, 'project-manifest', manifestPath);
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
const mapPath = findUp(start, MAP_FILE);
|
|
49
|
-
if (mapPath) {
|
|
50
|
-
const stored = readJsonOrNull(mapPath);
|
|
51
|
-
const declared = typeof stored?.map === 'string' ? stored.map.trim() : '';
|
|
52
|
-
if (declared)
|
|
53
|
-
return resolution(declared, 'map-file', mapPath);
|
|
54
|
-
}
|
|
55
|
-
if (projectRoot) {
|
|
56
|
-
const manifest = readJsonOrNull(join(projectRoot, PROJECT_FILE));
|
|
57
|
-
const providers = Object.values(manifest?.workspaces || {})
|
|
58
|
-
.map((workspace) => workspace?.provider?.kind);
|
|
59
|
-
if (providers.includes('multica')) {
|
|
60
|
-
return resolution('multica-dingtalk', 'inferred', join(projectRoot, PROJECT_FILE));
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
return resolution(null, 'none', '');
|
|
64
|
-
}
|
|
65
|
-
export function useMap(start, name, options) {
|
|
66
|
-
const definition = mapDefinition(name);
|
|
67
|
-
if (!definition) {
|
|
68
|
-
throw new Error(`未知 managed agents platform: ${name}\n` +
|
|
69
|
-
`可用: ${MANAGED_AGENT_PLATFORMS.map((item) => `${item.name}(${statusLabel(item.status)})`).join('、')}`);
|
|
70
|
-
}
|
|
71
|
-
if (definition.status !== 'supported') {
|
|
72
|
-
throw new Error(`${definition.label} 敬请期待——当前版本尚未开放该平台。`);
|
|
73
|
-
}
|
|
74
|
-
const projectRoot = findAgentProjectRoot(start);
|
|
75
|
-
let written;
|
|
76
|
-
if (projectRoot && existsSync(join(projectRoot, PROJECT_FILE))) {
|
|
77
|
-
const manifestPath = join(projectRoot, PROJECT_FILE);
|
|
78
|
-
if (lstatSync(manifestPath).isSymbolicLink()) {
|
|
79
|
-
throw new Error(`${PROJECT_FILE} 不能是符号链接`);
|
|
80
|
-
}
|
|
81
|
-
const manifest = readJsonOrNull(manifestPath);
|
|
82
|
-
if (!manifest || typeof manifest !== 'object') {
|
|
83
|
-
throw new Error(`${PROJECT_FILE} 不是合法 JSON,无法写入 map 归属`);
|
|
84
|
-
}
|
|
85
|
-
manifest.map = definition.name;
|
|
86
|
-
writeFileSync(manifestPath, JSON.stringify(manifest, null, 2) + '\n');
|
|
87
|
-
written = manifestPath;
|
|
88
|
-
}
|
|
89
|
-
else {
|
|
90
|
-
const target = join(resolve(start), MAP_FILE);
|
|
91
|
-
mkdirSync(dirname(target), { recursive: true });
|
|
92
|
-
writeFileSync(target, JSON.stringify({ $schema: 'dingtalk-agent/map@1', map: definition.name }, null, 2) + '\n');
|
|
93
|
-
written = target;
|
|
94
|
-
}
|
|
95
|
-
const skillInstalls = [];
|
|
96
|
-
if (options.installSkills !== false) {
|
|
97
|
-
for (const skill of definition.skills) {
|
|
98
|
-
skillInstalls.push(installGlobalSkill(options.packageRoot, {
|
|
99
|
-
name: skill, home: options.home, env: options.env,
|
|
100
|
-
}));
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
return { ...resolveMap(start, options.env || process.env), written, skillInstalls };
|
|
104
|
-
}
|
|
105
|
-
/** deploy/promote/observe 等平台命令的归属门禁:未归属、未知或 coming-soon 一律 fail-closed。 */
|
|
106
|
-
export function requireSupportedMap(command, start = process.cwd(), env = process.env) {
|
|
107
|
-
const resolved = resolveMap(start, env);
|
|
108
|
-
if (!resolved.map) {
|
|
109
|
-
throw new Error(`当前工作区未声明 managed agents platform,无法执行 \`${command}\`。\n` +
|
|
110
|
-
'先运行 `dta map use multica-dingtalk`,或设置 DTA_MAP 环境变量。');
|
|
111
|
-
}
|
|
112
|
-
if (!resolved.definition) {
|
|
113
|
-
throw new Error(`工作区声明了未知 platform: ${resolved.map}(来源 ${resolved.source})。\n` +
|
|
114
|
-
`可用: ${MANAGED_AGENT_PLATFORMS.map((item) => item.name).join('、')}`);
|
|
115
|
-
}
|
|
116
|
-
if (resolved.definition.status !== 'supported') {
|
|
117
|
-
throw new Error(`${resolved.definition.label} 敬请期待——\`${command}\` 尚未在该平台开放。`);
|
|
118
|
-
}
|
|
119
|
-
if (!resolved.definition.commands.includes(command)) {
|
|
120
|
-
throw new Error(`${resolved.definition.label} 不承接命令 \`${command}\`。`);
|
|
121
|
-
}
|
|
122
|
-
return resolved;
|
|
123
|
-
}
|
|
124
|
-
export function statusLabel(status) {
|
|
125
|
-
return status === 'supported' ? '已支持' : '敬请期待';
|
|
126
|
-
}
|
|
127
|
-
function resolution(name, source, file) {
|
|
128
|
-
return {
|
|
129
|
-
$schema: 'dingtalk-agent/map-resolution@1',
|
|
130
|
-
map: name,
|
|
131
|
-
source,
|
|
132
|
-
file,
|
|
133
|
-
definition: name ? mapDefinition(name) : null,
|
|
134
|
-
platforms: MANAGED_AGENT_PLATFORMS,
|
|
135
|
-
};
|
|
136
|
-
}
|
|
137
|
-
function readJsonOrNull(path) {
|
|
138
|
-
try {
|
|
139
|
-
return JSON.parse(readFileSync(path, 'utf8'));
|
|
140
|
-
}
|
|
141
|
-
catch {
|
|
142
|
-
return null;
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
function findUp(start, relativePath) {
|
|
146
|
-
let dir = resolve(start);
|
|
147
|
-
while (true) {
|
|
148
|
-
const candidate = join(dir, relativePath);
|
|
149
|
-
if (existsSync(candidate) && !lstatSync(candidate).isSymbolicLink())
|
|
150
|
-
return candidate;
|
|
151
|
-
const parent = dirname(dir);
|
|
152
|
-
if (parent === dir || dir === parse(dir).root)
|
|
153
|
-
return null;
|
|
154
|
-
dir = parent;
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
//# sourceMappingURL=map.js.map
|
package/dist/src/map.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"map.js","sourceRoot":"","sources":["../../src/map.ts"],"names":[],"mappings":"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","sourcesContent":["// Managed Agents Platform(MAP)注册表与工作区归属解析。\n//\n// 一个 Agent 工作区归属于至多一个托管平台;归属解析顺序固定:\n// DTA_MAP 环境变量 > dingtalk-agent.json#map > .dingtalk-agent/map.json > 按 Provider 声明推断。\n// 平台相关的方法学不写进 CLI——它们随对应平台的 Skill 包分发,只在用户选择该平台时安装。\n// 平台命令(如 deploy/promote/observe)必须先通过归属门禁;coming-soon 平台一律 fail-closed。\n\nimport { existsSync, lstatSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs'\nimport { dirname, join, parse, resolve } from 'node:path'\n\nimport { findAgentProjectRoot } from './development-workspace.js'\nimport { installGlobalSkill, type GlobalSkillStatus } from './skill-manager.js'\n\nexport type MapStatus = 'supported' | 'coming-soon'\n\nexport interface MapDefinition {\n name: string\n label: string\n status: MapStatus\n description: string\n skills: string[]\n commands: string[]\n}\n\nexport const MANAGED_AGENT_PLATFORMS: MapDefinition[] = [\n {\n name: 'multica-dingtalk',\n label: 'Multica (DingTalk)',\n status: 'supported',\n description: '钉钉 Multica 托管平台:受控部署、晋级与观测回流。',\n skills: ['dingtalk-agent-deploy', 'dingtalk-agent-boot-multica'],\n commands: ['deploy', 'promote', 'observe'],\n },\n {\n name: 'deap',\n label: 'DEAP',\n status: 'coming-soon',\n description: '敬请期待。',\n skills: [],\n commands: [],\n },\n]\n\nexport const MAP_FILE = '.dingtalk-agent/map.json'\nconst PROJECT_FILE = 'dingtalk-agent.json'\n\nexport type MapSource = 'env' | 'project-manifest' | 'map-file' | 'inferred' | 'none'\n\nexport interface MapResolution {\n $schema: 'dingtalk-agent/map-resolution@1'\n map: string | null\n source: MapSource\n file: string\n definition: MapDefinition | null\n platforms: MapDefinition[]\n}\n\nexport interface MapUseResult extends MapResolution {\n written: string\n skillInstalls: GlobalSkillStatus[]\n}\n\nexport function mapDefinition(name: string): MapDefinition | null {\n return MANAGED_AGENT_PLATFORMS.find((item) => item.name === name) || null\n}\n\nexport function resolveMap(start = process.cwd(), env: NodeJS.ProcessEnv = process.env): MapResolution {\n const fromEnv = String(env.DTA_MAP || '').trim()\n if (fromEnv) return resolution(fromEnv, 'env', '')\n\n const projectRoot = findAgentProjectRoot(start)\n if (projectRoot) {\n const manifestPath = join(projectRoot, PROJECT_FILE)\n if (existsSync(manifestPath) && !lstatSync(manifestPath).isSymbolicLink()) {\n const manifest = readJsonOrNull(manifestPath)\n const declared = typeof manifest?.map === 'string' ? manifest.map.trim() : ''\n if (declared) return resolution(declared, 'project-manifest', manifestPath)\n }\n }\n\n const mapPath = findUp(start, MAP_FILE)\n if (mapPath) {\n const stored = readJsonOrNull(mapPath)\n const declared = typeof stored?.map === 'string' ? stored.map.trim() : ''\n if (declared) return resolution(declared, 'map-file', mapPath)\n }\n\n if (projectRoot) {\n const manifest = readJsonOrNull(join(projectRoot, PROJECT_FILE))\n const providers = Object.values(manifest?.workspaces || {})\n .map((workspace: any) => workspace?.provider?.kind)\n if (providers.includes('multica')) {\n return resolution('multica-dingtalk', 'inferred', join(projectRoot, PROJECT_FILE))\n }\n }\n\n return resolution(null, 'none', '')\n}\n\nexport interface MapUseOptions {\n packageRoot: string\n home?: string\n env?: NodeJS.ProcessEnv\n installSkills?: boolean\n}\n\nexport function useMap(start: string, name: string, options: MapUseOptions): MapUseResult {\n const definition = mapDefinition(name)\n if (!definition) {\n throw new Error(\n `未知 managed agents platform: ${name}\\n` +\n `可用: ${MANAGED_AGENT_PLATFORMS.map((item) => `${item.name}(${statusLabel(item.status)})`).join('、')}`,\n )\n }\n if (definition.status !== 'supported') {\n throw new Error(`${definition.label} 敬请期待——当前版本尚未开放该平台。`)\n }\n\n const projectRoot = findAgentProjectRoot(start)\n let written: string\n if (projectRoot && existsSync(join(projectRoot, PROJECT_FILE))) {\n const manifestPath = join(projectRoot, PROJECT_FILE)\n if (lstatSync(manifestPath).isSymbolicLink()) {\n throw new Error(`${PROJECT_FILE} 不能是符号链接`)\n }\n const manifest = readJsonOrNull(manifestPath)\n if (!manifest || typeof manifest !== 'object') {\n throw new Error(`${PROJECT_FILE} 不是合法 JSON,无法写入 map 归属`)\n }\n manifest.map = definition.name\n writeFileSync(manifestPath, JSON.stringify(manifest, null, 2) + '\\n')\n written = manifestPath\n } else {\n const target = join(resolve(start), MAP_FILE)\n mkdirSync(dirname(target), { recursive: true })\n writeFileSync(target, JSON.stringify(\n { $schema: 'dingtalk-agent/map@1', map: definition.name }, null, 2,\n ) + '\\n')\n written = target\n }\n\n const skillInstalls: GlobalSkillStatus[] = []\n if (options.installSkills !== false) {\n for (const skill of definition.skills) {\n skillInstalls.push(installGlobalSkill(options.packageRoot, {\n name: skill, home: options.home, env: options.env,\n }))\n }\n }\n\n return { ...resolveMap(start, options.env || process.env), written, skillInstalls }\n}\n\n/** deploy/promote/observe 等平台命令的归属门禁:未归属、未知或 coming-soon 一律 fail-closed。 */\nexport function requireSupportedMap(\n command: string, start = process.cwd(), env: NodeJS.ProcessEnv = process.env,\n): MapResolution {\n const resolved = resolveMap(start, env)\n if (!resolved.map) {\n throw new Error(\n `当前工作区未声明 managed agents platform,无法执行 \\`${command}\\`。\\n` +\n '先运行 `dta map use multica-dingtalk`,或设置 DTA_MAP 环境变量。',\n )\n }\n if (!resolved.definition) {\n throw new Error(\n `工作区声明了未知 platform: ${resolved.map}(来源 ${resolved.source})。\\n` +\n `可用: ${MANAGED_AGENT_PLATFORMS.map((item) => item.name).join('、')}`,\n )\n }\n if (resolved.definition.status !== 'supported') {\n throw new Error(`${resolved.definition.label} 敬请期待——\\`${command}\\` 尚未在该平台开放。`)\n }\n if (!resolved.definition.commands.includes(command)) {\n throw new Error(`${resolved.definition.label} 不承接命令 \\`${command}\\`。`)\n }\n return resolved\n}\n\nexport function statusLabel(status: MapStatus): string {\n return status === 'supported' ? '已支持' : '敬请期待'\n}\n\nfunction resolution(name: string | null, source: MapSource, file: string): MapResolution {\n return {\n $schema: 'dingtalk-agent/map-resolution@1',\n map: name,\n source,\n file,\n definition: name ? mapDefinition(name) : null,\n platforms: MANAGED_AGENT_PLATFORMS,\n }\n}\n\nfunction readJsonOrNull(path: string): any {\n try { return JSON.parse(readFileSync(path, 'utf8')) } catch { return null }\n}\n\nfunction findUp(start: string, relativePath: string): string | null {\n let dir = resolve(start)\n while (true) {\n const candidate = join(dir, relativePath)\n if (existsSync(candidate) && !lstatSync(candidate).isSymbolicLink()) return candidate\n const parent = dirname(dir)\n if (parent === dir || dir === parse(dir).root) return null\n dir = parent\n }\n}\n"]}
|