@xdxer/dingtalk-agent 0.1.4-beta.10 → 0.1.4-beta.11
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 +20 -0
- package/README.en.md +2 -2
- package/README.md +5 -3
- package/dist/bin/dingtalk-agent.js +106 -16
- package/dist/bin/dingtalk-agent.js.map +1 -1
- package/dist/src/agent-platform.js +158 -0
- package/dist/src/agent-platform.js.map +1 -0
- package/dist/src/development-workspace.js +8 -1
- package/dist/src/development-workspace.js.map +1 -1
- package/dist/src/doctor.js +31 -15
- package/dist/src/doctor.js.map +1 -1
- package/dist/src/map.js +157 -0
- package/dist/src/map.js.map +1 -0
- package/dist/src/setup.js +6 -5
- package/dist/src/setup.js.map +1 -1
- package/dist/src/skill-manager.js +28 -2
- package/dist/src/skill-manager.js.map +1 -1
- package/docs/INSTALLATION.md +1 -1
- package/docs/schemas/agent-platform.schema.json +13 -0
- package/docs/schemas/project.schema.json +1 -0
- package/docs/schemas/release-readiness.schema.json +2 -1
- package/package.json +1 -1
- package/skills/dingtalk-agent-compose/SKILL.md +3 -3
- package/skills/dingtalk-agent-compose/evals/evals.json +1 -1
package/dist/src/map.js
ADDED
|
@@ -0,0 +1,157 @@
|
|
|
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
|
|
@@ -0,0 +1 @@
|
|
|
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"]}
|
package/dist/src/setup.js
CHANGED
|
@@ -3,7 +3,7 @@ import { delimiter, join } from 'node:path';
|
|
|
3
3
|
import { homedir } from 'node:os';
|
|
4
4
|
import { spawnSync } from 'node:child_process';
|
|
5
5
|
import { doctor, findExecutable } from './doctor.js';
|
|
6
|
-
import {
|
|
6
|
+
import { GLOBAL_SKILL_NAME, installBundledSkills, skillSuiteStatus, } from './skill-manager.js';
|
|
7
7
|
const PATH_MARKER_START = '# >>> dingtalk-agent PATH >>>';
|
|
8
8
|
const PATH_MARKER_END = '# <<< dingtalk-agent PATH <<<';
|
|
9
9
|
export function setup(packageRoot, options = {}) {
|
|
@@ -41,10 +41,10 @@ export function setup(packageRoot, options = {}) {
|
|
|
41
41
|
...env,
|
|
42
42
|
PATH: [binDir, env.PATH || ''].filter(Boolean).join(delimiter),
|
|
43
43
|
};
|
|
44
|
-
const
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
44
|
+
const suite = options.dryRun
|
|
45
|
+
? skillSuiteStatus(packageRoot, { home })
|
|
46
|
+
: installBundledSkills(packageRoot, { home, env: effectiveEnv });
|
|
47
|
+
const skill = suite.skills.find((item) => item.name === GLOBAL_SKILL_NAME) || suite.skills[0];
|
|
48
48
|
const report = doctor(packageRoot, { home, env: effectiveEnv });
|
|
49
49
|
return {
|
|
50
50
|
$schema: 'dingtalk-agent/setup@1',
|
|
@@ -60,6 +60,7 @@ export function setup(packageRoot, options = {}) {
|
|
|
60
60
|
},
|
|
61
61
|
shell,
|
|
62
62
|
skill,
|
|
63
|
+
skills: suite.skills,
|
|
63
64
|
doctor: report,
|
|
64
65
|
nextCommand: report.ready ? 'dta bootstrap --json' : 'dta doctor',
|
|
65
66
|
};
|
package/dist/src/setup.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"setup.js","sourceRoot":"","sources":["../../src/setup.ts"],"names":[],"mappings":"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","sourcesContent":["import { appendFileSync, existsSync, mkdirSync, readFileSync } from 'node:fs'\nimport { delimiter, join } from 'node:path'\nimport { homedir } from 'node:os'\nimport { spawnSync } from 'node:child_process'\n\nimport { doctor, findExecutable, type DoctorReport } from './doctor.js'\nimport {\n installGlobalSkill, skillStatus, type GlobalSkillStatus,\n} from './skill-manager.js'\n\nconst PATH_MARKER_START = '# >>> dingtalk-agent PATH >>>'\nconst PATH_MARKER_END = '# <<< dingtalk-agent PATH <<<'\n\nexport interface SetupOptions {\n home?: string\n env?: NodeJS.ProcessEnv\n prefix?: string\n dryRun?: boolean\n writeShell?: boolean\n skipCliInstall?: boolean\n}\n\nexport interface SetupResult {\n $schema: 'dingtalk-agent/setup@1'\n dryRun: boolean\n cli: {\n installed: boolean\n skipped: boolean\n prefix: string\n binDir: string\n executable: string\n alias: string\n packageSpec: string\n }\n shell: {\n pathReady: boolean\n rcFile: string\n updated: boolean\n activateCommand: string\n }\n skill: GlobalSkillStatus\n doctor: DoctorReport\n nextCommand: string\n}\n\nexport function setup(packageRoot: string, options: SetupOptions = {}): SetupResult {\n const home = options.home || homedir()\n const env = { ...(options.env || process.env) }\n const prefix = options.prefix || join(home, '.local')\n const binDir = process.platform === 'win32' ? prefix : join(prefix, 'bin')\n const executable = join(binDir, process.platform === 'win32' ? 'dingtalk-agent.cmd' : 'dingtalk-agent')\n const alias = join(binDir, process.platform === 'win32' ? 'dta.cmd' : 'dta')\n const pkg = JSON.parse(readFileSync(join(packageRoot, 'package.json'), 'utf8'))\n const packageSpec = env.DTA_SETUP_PACKAGE_SOURCE || `${pkg.name}@${pkg.version}`\n const npm = findExecutable(process.platform === 'win32' ? 'npm.cmd' : 'npm', env) || 'npm'\n const installedVersion = existsSync(executable)\n ? readInstalledVersion(executable, env)\n : ''\n const aliasVersion = existsSync(alias) ? readInstalledVersion(alias, env) : ''\n const alreadyCurrent = installedVersion === String(pkg.version || '') && aliasVersion === installedVersion\n\n if (!options.dryRun && !options.skipCliInstall && !alreadyCurrent) {\n mkdirSync(prefix, { recursive: true })\n const run = spawnSync(npm, [\n 'install', '--global', '--prefix', prefix, '--registry', 'https://registry.npmjs.org', packageSpec,\n ], { encoding: 'utf8', env, timeout: 120_000 })\n if (run.status !== 0 || run.error) {\n throw new Error(\n `CLI 用户级安装失败: ${run.error?.message || String(run.stderr || run.stdout).trim() || `退出码 ${run.status}`}`,\n )\n }\n if (!existsSync(executable) || !existsSync(alias)) {\n throw new Error(`npm 安装完成但 CLI 入口不完整: ${executable} / ${alias}`)\n }\n }\n\n const shell = ensureShellPath(home, binDir, env, {\n dryRun: Boolean(options.dryRun),\n writeShell: options.writeShell !== false,\n })\n const effectiveEnv = {\n ...env,\n PATH: [binDir, env.PATH || ''].filter(Boolean).join(delimiter),\n }\n const beforeSkill = skillStatus(packageRoot, { home })\n const skill = options.dryRun\n ? beforeSkill\n : installGlobalSkill(packageRoot, { home, env: effectiveEnv })\n const report = doctor(packageRoot, { home, env: effectiveEnv })\n return {\n $schema: 'dingtalk-agent/setup@1',\n dryRun: Boolean(options.dryRun),\n cli: {\n installed: !options.dryRun && !options.skipCliInstall && existsSync(executable),\n skipped: Boolean(options.skipCliInstall || alreadyCurrent),\n prefix,\n binDir,\n executable,\n alias,\n packageSpec,\n },\n shell,\n skill,\n doctor: report,\n nextCommand: report.ready ? 'dta bootstrap --json' : 'dta doctor',\n }\n}\n\nfunction ensureShellPath(\n home: string,\n binDir: string,\n env: NodeJS.ProcessEnv,\n options: { dryRun: boolean; writeShell: boolean },\n) {\n const current = (env.PATH || '').split(delimiter).filter(Boolean)\n const pathReady = current.includes(binDir)\n const shell = env.SHELL || ''\n const rcFile = shell.endsWith('/zsh')\n ? join(home, '.zshrc')\n : shell.endsWith('/bash')\n ? join(home, '.bashrc')\n : ''\n const isDefaultBin = binDir === join(home, '.local', 'bin')\n const activateCommand = isDefaultBin\n ? 'export PATH=\"$HOME/.local/bin:$PATH\"'\n : `export PATH=${shellQuote(binDir)}:\"$PATH\"`\n let updated = false\n if (!pathReady && options.writeShell && rcFile) {\n const before = existsSync(rcFile) ? readFileSync(rcFile, 'utf8') : ''\n if (!before.includes(PATH_MARKER_START) && !options.dryRun) {\n const pathLine = isDefaultBin\n ? 'export PATH=\"$HOME/.local/bin:$PATH\"'\n : `export PATH=${shellQuote(binDir)}:\"$PATH\"`\n const block = `${before && !before.endsWith('\\n') ? '\\n' : ''}${PATH_MARKER_START}\\n` +\n `${pathLine}\\n${PATH_MARKER_END}\\n`\n appendFileSync(rcFile, block)\n updated = true\n }\n }\n return { pathReady, rcFile, updated, activateCommand }\n}\n\nfunction shellQuote(value: string): string {\n return `'${value.replace(/'/g, `'\"'\"'`)}'`\n}\n\nfunction readInstalledVersion(executable: string, env: NodeJS.ProcessEnv): string {\n const run = spawnSync(executable, ['--version'], { encoding: 'utf8', env, timeout: 8_000 })\n return run.status === 0 ? String(run.stdout || '').trim() : ''\n}\n"]}
|
|
1
|
+
{"version":3,"file":"setup.js","sourceRoot":"","sources":["../../src/setup.ts"],"names":[],"mappings":"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","sourcesContent":["import { appendFileSync, existsSync, mkdirSync, readFileSync } from 'node:fs'\nimport { delimiter, join } from 'node:path'\nimport { homedir } from 'node:os'\nimport { spawnSync } from 'node:child_process'\n\nimport { doctor, findExecutable, type DoctorReport } from './doctor.js'\nimport {\n GLOBAL_SKILL_NAME, installBundledSkills, skillSuiteStatus, type GlobalSkillStatus,\n} from './skill-manager.js'\n\nconst PATH_MARKER_START = '# >>> dingtalk-agent PATH >>>'\nconst PATH_MARKER_END = '# <<< dingtalk-agent PATH <<<'\n\nexport interface SetupOptions {\n home?: string\n env?: NodeJS.ProcessEnv\n prefix?: string\n dryRun?: boolean\n writeShell?: boolean\n skipCliInstall?: boolean\n}\n\nexport interface SetupResult {\n $schema: 'dingtalk-agent/setup@1'\n dryRun: boolean\n cli: {\n installed: boolean\n skipped: boolean\n prefix: string\n binDir: string\n executable: string\n alias: string\n packageSpec: string\n }\n shell: {\n pathReady: boolean\n rcFile: string\n updated: boolean\n activateCommand: string\n }\n skill: GlobalSkillStatus\n skills: GlobalSkillStatus[]\n doctor: DoctorReport\n nextCommand: string\n}\n\nexport function setup(packageRoot: string, options: SetupOptions = {}): SetupResult {\n const home = options.home || homedir()\n const env = { ...(options.env || process.env) }\n const prefix = options.prefix || join(home, '.local')\n const binDir = process.platform === 'win32' ? prefix : join(prefix, 'bin')\n const executable = join(binDir, process.platform === 'win32' ? 'dingtalk-agent.cmd' : 'dingtalk-agent')\n const alias = join(binDir, process.platform === 'win32' ? 'dta.cmd' : 'dta')\n const pkg = JSON.parse(readFileSync(join(packageRoot, 'package.json'), 'utf8'))\n const packageSpec = env.DTA_SETUP_PACKAGE_SOURCE || `${pkg.name}@${pkg.version}`\n const npm = findExecutable(process.platform === 'win32' ? 'npm.cmd' : 'npm', env) || 'npm'\n const installedVersion = existsSync(executable)\n ? readInstalledVersion(executable, env)\n : ''\n const aliasVersion = existsSync(alias) ? readInstalledVersion(alias, env) : ''\n const alreadyCurrent = installedVersion === String(pkg.version || '') && aliasVersion === installedVersion\n\n if (!options.dryRun && !options.skipCliInstall && !alreadyCurrent) {\n mkdirSync(prefix, { recursive: true })\n const run = spawnSync(npm, [\n 'install', '--global', '--prefix', prefix, '--registry', 'https://registry.npmjs.org', packageSpec,\n ], { encoding: 'utf8', env, timeout: 120_000 })\n if (run.status !== 0 || run.error) {\n throw new Error(\n `CLI 用户级安装失败: ${run.error?.message || String(run.stderr || run.stdout).trim() || `退出码 ${run.status}`}`,\n )\n }\n if (!existsSync(executable) || !existsSync(alias)) {\n throw new Error(`npm 安装完成但 CLI 入口不完整: ${executable} / ${alias}`)\n }\n }\n\n const shell = ensureShellPath(home, binDir, env, {\n dryRun: Boolean(options.dryRun),\n writeShell: options.writeShell !== false,\n })\n const effectiveEnv = {\n ...env,\n PATH: [binDir, env.PATH || ''].filter(Boolean).join(delimiter),\n }\n const suite = options.dryRun\n ? skillSuiteStatus(packageRoot, { home })\n : installBundledSkills(packageRoot, { home, env: effectiveEnv })\n const skill = suite.skills.find((item) => item.name === GLOBAL_SKILL_NAME) || suite.skills[0]\n const report = doctor(packageRoot, { home, env: effectiveEnv })\n return {\n $schema: 'dingtalk-agent/setup@1',\n dryRun: Boolean(options.dryRun),\n cli: {\n installed: !options.dryRun && !options.skipCliInstall && existsSync(executable),\n skipped: Boolean(options.skipCliInstall || alreadyCurrent),\n prefix,\n binDir,\n executable,\n alias,\n packageSpec,\n },\n shell,\n skill,\n skills: suite.skills,\n doctor: report,\n nextCommand: report.ready ? 'dta bootstrap --json' : 'dta doctor',\n }\n}\n\nfunction ensureShellPath(\n home: string,\n binDir: string,\n env: NodeJS.ProcessEnv,\n options: { dryRun: boolean; writeShell: boolean },\n) {\n const current = (env.PATH || '').split(delimiter).filter(Boolean)\n const pathReady = current.includes(binDir)\n const shell = env.SHELL || ''\n const rcFile = shell.endsWith('/zsh')\n ? join(home, '.zshrc')\n : shell.endsWith('/bash')\n ? join(home, '.bashrc')\n : ''\n const isDefaultBin = binDir === join(home, '.local', 'bin')\n const activateCommand = isDefaultBin\n ? 'export PATH=\"$HOME/.local/bin:$PATH\"'\n : `export PATH=${shellQuote(binDir)}:\"$PATH\"`\n let updated = false\n if (!pathReady && options.writeShell && rcFile) {\n const before = existsSync(rcFile) ? readFileSync(rcFile, 'utf8') : ''\n if (!before.includes(PATH_MARKER_START) && !options.dryRun) {\n const pathLine = isDefaultBin\n ? 'export PATH=\"$HOME/.local/bin:$PATH\"'\n : `export PATH=${shellQuote(binDir)}:\"$PATH\"`\n const block = `${before && !before.endsWith('\\n') ? '\\n' : ''}${PATH_MARKER_START}\\n` +\n `${pathLine}\\n${PATH_MARKER_END}\\n`\n appendFileSync(rcFile, block)\n updated = true\n }\n }\n return { pathReady, rcFile, updated, activateCommand }\n}\n\nfunction shellQuote(value: string): string {\n return `'${value.replace(/'/g, `'\"'\"'`)}'`\n}\n\nfunction readInstalledVersion(executable: string, env: NodeJS.ProcessEnv): string {\n const run = spawnSync(executable, ['--version'], { encoding: 'utf8', env, timeout: 8_000 })\n return run.status === 0 ? String(run.stdout || '').trim() : ''\n}\n"]}
|
|
@@ -1,14 +1,40 @@
|
|
|
1
1
|
// Skill 安装生命周期由开放生态的 `npx skills` 负责。
|
|
2
2
|
// dingtalk-agent 只做两件事:把内置 Skill 目录交给上游 CLI;只读验证客户端能否发现。
|
|
3
|
+
// 默认(不指定 name)对全部内置 Skill 生效:基础行为 + Agent 装配;指定 name 时只操作该 Skill。
|
|
3
4
|
import { existsSync, lstatSync, readFileSync, readlinkSync } from 'node:fs';
|
|
4
5
|
import { homedir } from 'node:os';
|
|
5
6
|
import { dirname, join, resolve } from 'node:path';
|
|
6
7
|
import { spawnSync } from 'node:child_process';
|
|
7
8
|
export const GLOBAL_SKILL_NAME = 'dingtalk-basic-behavior';
|
|
9
|
+
// 默认套装:所有机器都装的通用 Skill。平台 Skill(deploy/boot-multica 等)不在默认套装内,
|
|
10
|
+
// 只有工作区通过 `dta map use` 选择对应 managed agents platform 时才按名安装。
|
|
8
11
|
export const BUNDLED_SKILL_NAMES = [GLOBAL_SKILL_NAME, 'dingtalk-agent-compose'];
|
|
12
|
+
export const INSTALLABLE_SKILL_NAMES = [
|
|
13
|
+
...BUNDLED_SKILL_NAMES, 'dingtalk-agent-deploy', 'dingtalk-agent-boot-multica',
|
|
14
|
+
];
|
|
9
15
|
const SKILLS_PACKAGE = 'skills@latest';
|
|
10
16
|
const REGISTRY = 'https://registry.npmjs.org';
|
|
11
17
|
const AGENTS = ['claude-code', 'codex', 'opencode'];
|
|
18
|
+
export function skillSuiteStatus(packageRoot, options = {}) {
|
|
19
|
+
return suiteOf(BUNDLED_SKILL_NAMES.map((name) => skillStatus(packageRoot, { ...options, name })));
|
|
20
|
+
}
|
|
21
|
+
export function installBundledSkills(packageRoot, options = {}) {
|
|
22
|
+
return suiteOf(BUNDLED_SKILL_NAMES.map((name) => installGlobalSkill(packageRoot, { ...options, name })));
|
|
23
|
+
}
|
|
24
|
+
export function upgradeBundledSkills(packageRoot, options = {}) {
|
|
25
|
+
return suiteOf(BUNDLED_SKILL_NAMES.map((name) => upgradeGlobalSkill(packageRoot, { ...options, name })));
|
|
26
|
+
}
|
|
27
|
+
export function uninstallBundledSkills(packageRoot, options = {}) {
|
|
28
|
+
return suiteOf(BUNDLED_SKILL_NAMES.map((name) => uninstallGlobalSkill(packageRoot, { ...options, name })));
|
|
29
|
+
}
|
|
30
|
+
function suiteOf(skills) {
|
|
31
|
+
return {
|
|
32
|
+
$schema: 'dingtalk-agent/skill-status-suite@1',
|
|
33
|
+
manager: 'skills-cli',
|
|
34
|
+
names: skills.map((skill) => skill.name),
|
|
35
|
+
skills,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
12
38
|
export function skillStatus(packageRoot, options = {}) {
|
|
13
39
|
const name = bundledSkillName(options.name);
|
|
14
40
|
const paths = globalPaths(packageRoot, options.home, name);
|
|
@@ -143,8 +169,8 @@ function validateSkill(root, name) {
|
|
|
143
169
|
}
|
|
144
170
|
function bundledSkillName(value = '') {
|
|
145
171
|
const name = value.trim() || GLOBAL_SKILL_NAME;
|
|
146
|
-
if (!
|
|
147
|
-
throw new Error(`不支持的内置 Skill: ${name};可用: ${
|
|
172
|
+
if (!INSTALLABLE_SKILL_NAMES.includes(name)) {
|
|
173
|
+
throw new Error(`不支持的内置 Skill: ${name};可用: ${INSTALLABLE_SKILL_NAMES.join(', ')}`);
|
|
148
174
|
}
|
|
149
175
|
return name;
|
|
150
176
|
}
|
|
@@ -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\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'\nexport const BUNDLED_SKILL_NAMES = [GLOBAL_SKILL_NAME, 'dingtalk-agent-compose'] as const\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}\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 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\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,\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, 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 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(), name = GLOBAL_SKILL_NAME) {\n return {\n source: join(packageRoot, 'skills', 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 }\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}\n\nfunction bundledSkillName(value = ''): string {\n const name = value.trim() || GLOBAL_SKILL_NAME\n if (!(BUNDLED_SKILL_NAMES as readonly string[]).includes(name)) {\n throw new Error(`不支持的内置 Skill: ${name};可用: ${BUNDLED_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 { 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'\n// 默认套装:所有机器都装的通用 Skill。平台 Skill(deploy/boot-multica 等)不在默认套装内,\n// 只有工作区通过 `dta map use` 选择对应 managed agents platform 时才按名安装。\nexport const BUNDLED_SKILL_NAMES = [GLOBAL_SKILL_NAME, 'dingtalk-agent-compose'] as const\nexport const INSTALLABLE_SKILL_NAMES = [\n ...BUNDLED_SKILL_NAMES, 'dingtalk-agent-deploy', 'dingtalk-agent-boot-multica',\n] as const\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}\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 interface GlobalSkillSuiteStatus {\n $schema: 'dingtalk-agent/skill-status-suite@1'\n manager: 'skills-cli'\n names: string[]\n skills: GlobalSkillStatus[]\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.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.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 return {\n $schema: 'dingtalk-agent/skill-status-suite@1',\n manager: 'skills-cli',\n names: skills.map((skill) => skill.name),\n skills,\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\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,\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, 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 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(), name = GLOBAL_SKILL_NAME) {\n return {\n source: join(packageRoot, 'skills', 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 }\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}\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/docs/INSTALLATION.md
CHANGED
|
@@ -69,7 +69,7 @@ npm 全局命令会被链接到 `{prefix}/bin`,但不同 Node 版本管理器
|
|
|
69
69
|
npm install → dta setup
|
|
70
70
|
→ 安装当前版本到 ~/.local/bin
|
|
71
71
|
→ 检查并幂等补充 ~/.zshrc / ~/.bashrc PATH
|
|
72
|
-
→ 安装 canonical Basic Behavior
|
|
72
|
+
→ 安装 canonical 内置 Skill(Basic Behavior + Compose)
|
|
73
73
|
→ 暴露给 Claude Code,验证 Codex/OpenCode 共享发现
|
|
74
74
|
→ 检查 DWS 版本和认证
|
|
75
75
|
→ 给出唯一下一条命令
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://github.com/D1-2004/dingtalk-agent/docs/schemas/agent-platform.schema.json",
|
|
4
|
+
"title": "dingtalk-agent Managed Agent Platform declaration",
|
|
5
|
+
"description": "工作区归属的 managed agent platform。解析顺序:DTA_AGENT_PLATFORM 环境变量 > dingtalk-agent.json#agentPlatform > .dingtalk-agent/agent-platform.json > 按 Provider 声明推断。",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"additionalProperties": false,
|
|
8
|
+
"required": ["$schema", "agentPlatform"],
|
|
9
|
+
"properties": {
|
|
10
|
+
"$schema": { "const": "dingtalk-agent/agent-platform@1" },
|
|
11
|
+
"agentPlatform": { "enum": ["multica-dingtalk", "deap"] }
|
|
12
|
+
}
|
|
13
|
+
}
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
"$schema": { "const": "dingtalk-agent/project@1" },
|
|
10
10
|
"name": { "$ref": "#/$defs/name" },
|
|
11
11
|
"dtaVersion": { "type": "string", "minLength": 1 },
|
|
12
|
+
"agentPlatform": { "enum": ["multica-dingtalk", "deap"] },
|
|
12
13
|
"agent": {
|
|
13
14
|
"type": "object",
|
|
14
15
|
"additionalProperties": false,
|
|
@@ -24,12 +24,13 @@
|
|
|
24
24
|
},
|
|
25
25
|
"install": {
|
|
26
26
|
"type": "object", "additionalProperties": false,
|
|
27
|
-
"required": ["offlineTarball", "cliEntries", "versionMatched", "canonicalSkillCopies", "clientsReady"],
|
|
27
|
+
"required": ["offlineTarball", "cliEntries", "versionMatched", "canonicalSkillCopies", "composeSkillCopies", "clientsReady"],
|
|
28
28
|
"properties": {
|
|
29
29
|
"offlineTarball": { "const": true },
|
|
30
30
|
"cliEntries": { "const": 2 },
|
|
31
31
|
"versionMatched": { "const": true },
|
|
32
32
|
"canonicalSkillCopies": { "const": 1 },
|
|
33
|
+
"composeSkillCopies": { "const": 1 },
|
|
33
34
|
"clientsReady": { "const": 3 }
|
|
34
35
|
}
|
|
35
36
|
},
|
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: dingtalk-agent-compose
|
|
3
|
-
description:
|
|
3
|
+
description: 当用户要创建、新建、装配一个 Agent 或钉钉数字员工——包括把 GitHub 仓库、本地文件夹或钉钉文档定义成 Agent,或要审计、补齐、优化 Agent 的 AGENTS.md、本体职责、岗位 Skills、记忆/知识/产物存储与 DWS 权限绑定时使用。即使尚未 init Workspace,也按 dingtalk-agent 的 AgentDefinition 范式给出可运行的最小装配方案;不负责事件触发器。
|
|
4
4
|
compatibility: Requires dingtalk-agent on PATH; remote DingTalk documents require authenticated dws.
|
|
5
5
|
metadata:
|
|
6
|
-
version: "0.5.
|
|
6
|
+
version: "0.5.1"
|
|
7
7
|
---
|
|
8
8
|
|
|
9
|
-
#
|
|
9
|
+
# 装配一个可工作的钉钉数字员工 Agent
|
|
10
10
|
|
|
11
11
|
把用户已有的仓库、目录或钉钉文档整理成两部分:**本体(body + role skills)**和**存储路由(memory + knowledge + artifacts + private state)**。复用 dta 的 Basic Behavior、Invocation、Session/Run/Wait 与 Action Gate,不复制一套新运行时。
|
|
12
12
|
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
},
|
|
15
15
|
{
|
|
16
16
|
"id": 2,
|
|
17
|
-
"prompt": "这个本地目录已经有 AGENTS.md 和 skills
|
|
17
|
+
"prompt": "这个本地目录已经有 AGENTS.md 和 skills/,帮我判断能不能作为钉钉数字员工 Agent,并给出验证命令。",
|
|
18
18
|
"expected_output": "运行 bootstrap 和 agent audit;依据稳定 check/missing/repairs 判断;说明 Basic 与 Role Skills 可叠加及 Session 冻结边界。",
|
|
19
19
|
"files": [],
|
|
20
20
|
"expectations": [
|