prizmkit 1.1.119 → 1.1.120
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/bin/create-prizmkit.js +1 -5
- package/bundled/VERSION.json +3 -3
- package/bundled/dev-pipeline/README.md +41 -38
- package/bundled/dev-pipeline/assets/skill-subagent-integration.md +76 -0
- package/bundled/dev-pipeline/prizmkit_runtime/config.py +2 -8
- package/bundled/dev-pipeline/prizmkit_runtime/interoperability.py +1 -1
- package/bundled/dev-pipeline/prizmkit_runtime/platform_detection.py +3 -3
- package/bundled/dev-pipeline/prizmkit_runtime/runners.py +45 -3
- package/bundled/dev-pipeline/prizmkit_runtime/sessions.py +28 -6
- package/bundled/dev-pipeline/scripts/generate-bootstrap-prompt.py +60 -102
- package/bundled/dev-pipeline/scripts/generate-bugfix-prompt.py +1 -19
- package/bundled/dev-pipeline/scripts/generate-refactor-prompt.py +1 -19
- package/bundled/dev-pipeline/scripts/{init-dev-team.py → init-change-artifact.py} +6 -16
- package/bundled/dev-pipeline/scripts/parse-stream-progress.py +364 -76
- package/bundled/dev-pipeline/scripts/utils.py +1 -1
- package/bundled/dev-pipeline/templates/bootstrap-prompt.md +2 -2
- package/bundled/dev-pipeline/templates/bootstrap-tier3.md +7 -9
- package/bundled/dev-pipeline/templates/sections/bugfix-phase-review.md +2 -2
- package/bundled/dev-pipeline/templates/sections/context-budget-rules.md +1 -1
- package/bundled/dev-pipeline/templates/sections/critical-paths-agent.md +0 -1
- package/bundled/dev-pipeline/templates/sections/critical-paths-full.md +0 -2
- package/bundled/dev-pipeline/templates/sections/phase-commit-full.md +8 -1
- package/bundled/dev-pipeline/templates/sections/phase-implement-agent.md +6 -7
- package/bundled/dev-pipeline/templates/sections/phase-implement-full.md +6 -7
- package/bundled/dev-pipeline/templates/sections/phase-implement-lite.md +4 -2
- package/bundled/dev-pipeline/templates/sections/phase-review-agent.md +2 -2
- package/bundled/dev-pipeline/templates/sections/phase-review-full.md +4 -2
- package/bundled/dev-pipeline/templates/sections/phase-specify-plan-full.md +20 -0
- package/bundled/dev-pipeline/templates/sections/refactor-phase-review.md +2 -2
- package/bundled/dev-pipeline/tests/test_generate_bootstrap_prompt.py +204 -141
- package/bundled/dev-pipeline/tests/test_generate_bugfix_prompt.py +16 -10
- package/bundled/dev-pipeline/tests/test_generate_refactor_prompt.py +2 -13
- package/bundled/dev-pipeline/tests/test_python_runner_parity.py +13 -14
- package/bundled/dev-pipeline/tests/test_unified_cli.py +205 -6
- package/bundled/skills/_metadata.json +1 -1
- package/bundled/skills/app-planner/SKILL.md +2 -2
- package/bundled/skills/app-planner/references/architecture-decisions.md +1 -3
- package/bundled/skills/prizmkit-code-review/SKILL.md +16 -14
- package/bundled/skills/prizmkit-code-review/references/reviewer-agent-prompt.md +9 -9
- package/bundled/skills/prizmkit-implement/SKILL.md +21 -1
- package/bundled/skills/prizmkit-implement/references/implementation-subagent-procedure.md +67 -0
- package/package.json +1 -1
- package/src/clean.js +12 -8
- package/src/config.js +24 -42
- package/src/index.js +1 -10
- package/src/manifest.js +3 -9
- package/src/metadata.js +0 -26
- package/src/prompts.js +0 -13
- package/src/scaffold.js +76 -201
- package/src/upgrade.js +16 -33
- package/bundled/adapters/claude/agent-adapter.js +0 -96
- package/bundled/adapters/claude/team-adapter.js +0 -183
- package/bundled/adapters/codebuddy/agent-adapter.js +0 -42
- package/bundled/adapters/codebuddy/team-adapter.js +0 -46
- package/bundled/adapters/codex/agent-adapter.js +0 -38
- package/bundled/adapters/codex/team-adapter.js +0 -37
- package/bundled/agents/prizm-dev-team-dev.md +0 -123
- package/bundled/agents/prizm-dev-team-reviewer.md +0 -113
- package/bundled/dev-pipeline/assets/prizm-dev-team-integration.md +0 -65
- package/bundled/dev-pipeline/templates/bootstrap-tier1.md +0 -436
- package/bundled/dev-pipeline/templates/bootstrap-tier2.md +0 -510
- package/bundled/team/prizm-dev-team.json +0 -27
package/src/scaffold.js
CHANGED
|
@@ -16,8 +16,6 @@ import { dirname, join } from 'path';
|
|
|
16
16
|
import { execSync } from 'child_process';
|
|
17
17
|
import {
|
|
18
18
|
loadMetadata,
|
|
19
|
-
getAgentsDir,
|
|
20
|
-
getTeamDir,
|
|
21
19
|
getTemplatesDir,
|
|
22
20
|
getPipelineDir,
|
|
23
21
|
getAdaptersDir,
|
|
@@ -82,6 +80,74 @@ const RETIRED_POWERSHELL_RUNTIME_FILES = new Set([
|
|
|
82
80
|
'lib/branch.ps1',
|
|
83
81
|
'lib/heartbeat.ps1',
|
|
84
82
|
]);
|
|
83
|
+
const LEGACY_TEAM_NAME = ['prizm', 'dev', 'team'].join('-');
|
|
84
|
+
const LEGACY_AGENT_BASENAMES = [
|
|
85
|
+
`${LEGACY_TEAM_NAME}-dev`,
|
|
86
|
+
`${LEGACY_TEAM_NAME}-reviewer`,
|
|
87
|
+
];
|
|
88
|
+
|
|
89
|
+
async function removeEmptyDirectory(dirPath) {
|
|
90
|
+
if (!await fs.pathExists(dirPath)) return;
|
|
91
|
+
const entries = await fs.readdir(dirPath);
|
|
92
|
+
if (entries.length === 0) {
|
|
93
|
+
await fs.remove(dirPath);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export async function removeRetiredAgentTeamArtifacts(platform, projectRoot, dryRun) {
|
|
98
|
+
const agentDir = platform === 'claude'
|
|
99
|
+
? path.join(projectRoot, '.claude', 'agents')
|
|
100
|
+
: platform === 'codex'
|
|
101
|
+
? path.join(projectRoot, '.codex', 'agents')
|
|
102
|
+
: path.join(projectRoot, '.codebuddy', 'agents');
|
|
103
|
+
const agentExtensions = platform === 'codex' ? ['.toml', '.md'] : ['.md'];
|
|
104
|
+
|
|
105
|
+
for (const basename of LEGACY_AGENT_BASENAMES) {
|
|
106
|
+
for (const extension of agentExtensions) {
|
|
107
|
+
const filePath = path.join(agentDir, `${basename}${extension}`);
|
|
108
|
+
if (!await fs.pathExists(filePath)) continue;
|
|
109
|
+
if (dryRun) {
|
|
110
|
+
console.log(chalk.gray(` [dry-run] remove retired ${path.relative(projectRoot, filePath)}`));
|
|
111
|
+
} else {
|
|
112
|
+
await fs.remove(filePath);
|
|
113
|
+
console.log(chalk.red(` ✗ removed retired ${path.relative(projectRoot, filePath)}`));
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
if (!dryRun) {
|
|
119
|
+
await removeEmptyDirectory(agentDir);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
const teamInfoPath = platform === 'claude'
|
|
123
|
+
? path.join(projectRoot, '.claude', 'team-info.json')
|
|
124
|
+
: platform === 'codex'
|
|
125
|
+
? path.join(projectRoot, '.codex', 'team-info.json')
|
|
126
|
+
: path.join(projectRoot, '.codebuddy', 'team-info.json');
|
|
127
|
+
if (await fs.pathExists(teamInfoPath)) {
|
|
128
|
+
if (dryRun) {
|
|
129
|
+
console.log(chalk.gray(` [dry-run] remove retired ${path.relative(projectRoot, teamInfoPath)}`));
|
|
130
|
+
} else {
|
|
131
|
+
await fs.remove(teamInfoPath);
|
|
132
|
+
console.log(chalk.red(` ✗ removed retired ${path.relative(projectRoot, teamInfoPath)}`));
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
if (platform === 'codebuddy') {
|
|
137
|
+
const homeDir = process.env.HOME || process.env.USERPROFILE;
|
|
138
|
+
if (homeDir) {
|
|
139
|
+
const globalTeamDir = path.join(homeDir, '.codebuddy', 'teams', LEGACY_TEAM_NAME);
|
|
140
|
+
if (await fs.pathExists(globalTeamDir)) {
|
|
141
|
+
if (dryRun) {
|
|
142
|
+
console.log(chalk.gray(' [dry-run] remove retired global CodeBuddy team config'));
|
|
143
|
+
} else {
|
|
144
|
+
await fs.remove(globalTeamDir);
|
|
145
|
+
console.log(chalk.red(' ✗ removed retired global CodeBuddy team config'));
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
85
151
|
|
|
86
152
|
// ============================================================
|
|
87
153
|
// Adapter 动态加载
|
|
@@ -282,186 +348,9 @@ export async function installSkills(platform, skills, projectRoot, dryRun, runti
|
|
|
282
348
|
}
|
|
283
349
|
|
|
284
350
|
/**
|
|
285
|
-
*
|
|
286
|
-
|
|
287
|
-
export async function installAgents(platform, projectRoot, dryRun) {
|
|
288
|
-
const agentsDir = getAgentsDir();
|
|
289
|
-
const agentFiles = (await fs.readdir(agentsDir)).filter(f => f.endsWith('.md'));
|
|
290
|
-
|
|
291
|
-
// Load Claude agent adapter
|
|
292
|
-
let convertAgentFn;
|
|
293
|
-
if (platform === 'claude') {
|
|
294
|
-
const agentAdapter = await loadAdapter('claude', 'agent-adapter.js');
|
|
295
|
-
convertAgentFn = agentAdapter.convertAgent;
|
|
296
|
-
} else if (platform === 'codex') {
|
|
297
|
-
const agentAdapter = await loadAdapter('codex', 'agent-adapter.js');
|
|
298
|
-
convertAgentFn = agentAdapter.convertAgent;
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
for (const file of agentFiles) {
|
|
302
|
-
const content = await fs.readFile(path.join(agentsDir, file), 'utf8');
|
|
303
|
-
|
|
304
|
-
if (platform === 'codebuddy') {
|
|
305
|
-
const targetDir = path.join(projectRoot, '.codebuddy', 'agents');
|
|
306
|
-
if (dryRun) {
|
|
307
|
-
console.log(chalk.gray(` [dry-run] .codebuddy/agents/${file}`));
|
|
308
|
-
continue;
|
|
309
|
-
}
|
|
310
|
-
await fs.ensureDir(targetDir);
|
|
311
|
-
await fs.writeFile(path.join(targetDir, file), content);
|
|
312
|
-
console.log(chalk.green(` ✓ .codebuddy/agents/${file}`));
|
|
313
|
-
|
|
314
|
-
} else if (platform === 'claude') {
|
|
315
|
-
const converted = convertAgentFn(content, { model: 'inherit' });
|
|
316
|
-
|
|
317
|
-
const targetDir = path.join(projectRoot, '.claude', 'agents');
|
|
318
|
-
if (dryRun) {
|
|
319
|
-
console.log(chalk.gray(` [dry-run] .claude/agents/${file}`));
|
|
320
|
-
continue;
|
|
321
|
-
}
|
|
322
|
-
await fs.ensureDir(targetDir);
|
|
323
|
-
await fs.writeFile(path.join(targetDir, file), converted);
|
|
324
|
-
console.log(chalk.green(` ✓ .claude/agents/${file}`));
|
|
325
|
-
} else if (platform === 'codex') {
|
|
326
|
-
const baseName = path.basename(file, '.md');
|
|
327
|
-
const targetFile = `${baseName}.toml`;
|
|
328
|
-
const converted = convertAgentFn(content, { name: baseName });
|
|
329
|
-
const targetDir = path.join(projectRoot, '.codex', 'agents');
|
|
330
|
-
if (dryRun) {
|
|
331
|
-
console.log(chalk.gray(` [dry-run] .codex/agents/${targetFile}`));
|
|
332
|
-
continue;
|
|
333
|
-
}
|
|
334
|
-
await fs.ensureDir(targetDir);
|
|
335
|
-
await fs.writeFile(path.join(targetDir, targetFile), converted);
|
|
336
|
-
await fs.remove(path.join(targetDir, file));
|
|
337
|
-
console.log(chalk.green(` ✓ .codex/agents/${targetFile}`));
|
|
338
|
-
}
|
|
339
|
-
}
|
|
340
|
-
}
|
|
341
|
-
|
|
342
|
-
/**
|
|
343
|
-
* 安装 Team 配置
|
|
351
|
+
* Legacy platform named-agent and team installation has been retired.
|
|
352
|
+
* Skill-owned references now provide inline reviewer/implementation subagent contracts.
|
|
344
353
|
*/
|
|
345
|
-
export async function installTeamConfig(platform, projectRoot, dryRun) {
|
|
346
|
-
const teamDir = getTeamDir();
|
|
347
|
-
const teamDefPath = path.join(teamDir, 'prizm-dev-team.json');
|
|
348
|
-
|
|
349
|
-
if (!await fs.pathExists(teamDefPath)) {
|
|
350
|
-
console.log(chalk.yellow(' ⚠ 未找到团队配置文件,跳过'));
|
|
351
|
-
return;
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
const teamDef = await fs.readJSON(teamDefPath);
|
|
355
|
-
|
|
356
|
-
if (platform === 'codebuddy') {
|
|
357
|
-
const homeDir = process.env.HOME || process.env.USERPROFILE;
|
|
358
|
-
const targetDir = path.join(homeDir, '.codebuddy', 'teams', 'prizm-dev-team');
|
|
359
|
-
|
|
360
|
-
if (dryRun) {
|
|
361
|
-
console.log(chalk.gray(` [dry-run] ~/.codebuddy/teams/prizm-dev-team/`));
|
|
362
|
-
return;
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
await fs.ensureDir(path.join(targetDir, 'inboxes'));
|
|
366
|
-
|
|
367
|
-
const config = {
|
|
368
|
-
name: teamDef.name,
|
|
369
|
-
description: teamDef.description,
|
|
370
|
-
createdAt: Date.now(),
|
|
371
|
-
leadAgentId: `${teamDef.lead}@${teamDef.name}`,
|
|
372
|
-
leadSessionId: '',
|
|
373
|
-
members: teamDef.members.map((m, i) => ({
|
|
374
|
-
agentId: `${m.name}@${teamDef.name}`,
|
|
375
|
-
name: m.name,
|
|
376
|
-
agentType: m.agentDefinition || m.name,
|
|
377
|
-
...(m.prompt ? { prompt: m.prompt } : {}),
|
|
378
|
-
joinedAt: Date.now() + i,
|
|
379
|
-
tmuxPaneId: '',
|
|
380
|
-
cwd: '',
|
|
381
|
-
subscriptions: m.subscriptions || [],
|
|
382
|
-
})),
|
|
383
|
-
};
|
|
384
|
-
|
|
385
|
-
await fs.writeFile(path.join(targetDir, 'config.json'), JSON.stringify(config, null, 2));
|
|
386
|
-
|
|
387
|
-
for (const member of teamDef.members) {
|
|
388
|
-
const inboxPath = path.join(targetDir, 'inboxes', `${member.name}.json`);
|
|
389
|
-
if (!await fs.pathExists(inboxPath)) {
|
|
390
|
-
await fs.writeFile(inboxPath, JSON.stringify([], null, 2));
|
|
391
|
-
}
|
|
392
|
-
}
|
|
393
|
-
|
|
394
|
-
console.log(chalk.green(` ✓ ~/.codebuddy/teams/prizm-dev-team/`));
|
|
395
|
-
|
|
396
|
-
} else if (platform === 'claude') {
|
|
397
|
-
const claudeDir = path.join(projectRoot, '.claude');
|
|
398
|
-
|
|
399
|
-
if (dryRun) {
|
|
400
|
-
console.log(chalk.gray(` [dry-run] .claude/team-info.json`));
|
|
401
|
-
return;
|
|
402
|
-
}
|
|
403
|
-
|
|
404
|
-
await fs.ensureDir(claudeDir);
|
|
405
|
-
|
|
406
|
-
const teamConfig = {
|
|
407
|
-
name: teamDef.name,
|
|
408
|
-
description: teamDef.description,
|
|
409
|
-
platform: 'claude',
|
|
410
|
-
orchestrationMode: 'subagent',
|
|
411
|
-
agents: teamDef.members
|
|
412
|
-
.filter(m => m.role !== 'lead')
|
|
413
|
-
.map(m => ({
|
|
414
|
-
name: m.name,
|
|
415
|
-
role: m.role,
|
|
416
|
-
agentFile: `.claude/agents/${m.agentDefinition}.md`,
|
|
417
|
-
prompt: m.prompt,
|
|
418
|
-
})),
|
|
419
|
-
upgrade: {
|
|
420
|
-
envVar: 'CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS',
|
|
421
|
-
command: '设置 CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1 可启用原生 Agent Teams 模式',
|
|
422
|
-
},
|
|
423
|
-
};
|
|
424
|
-
|
|
425
|
-
await fs.writeFile(
|
|
426
|
-
path.join(claudeDir, 'team-info.json'),
|
|
427
|
-
JSON.stringify(teamConfig, null, 2)
|
|
428
|
-
);
|
|
429
|
-
|
|
430
|
-
console.log(chalk.green(` ✓ .claude/team-info.json`));
|
|
431
|
-
} else if (platform === 'codex') {
|
|
432
|
-
const codexDir = path.join(projectRoot, '.codex');
|
|
433
|
-
|
|
434
|
-
if (dryRun) {
|
|
435
|
-
console.log(chalk.gray(` [dry-run] .codex/team-info.json`));
|
|
436
|
-
return;
|
|
437
|
-
}
|
|
438
|
-
|
|
439
|
-
await fs.ensureDir(codexDir);
|
|
440
|
-
|
|
441
|
-
const teamConfig = {
|
|
442
|
-
name: teamDef.name,
|
|
443
|
-
description: teamDef.description,
|
|
444
|
-
platform: 'codex',
|
|
445
|
-
orchestrationMode: 'codex-subagents',
|
|
446
|
-
agents: teamDef.members
|
|
447
|
-
.filter(m => m.role !== 'lead')
|
|
448
|
-
.map(m => ({
|
|
449
|
-
name: m.name,
|
|
450
|
-
role: m.role,
|
|
451
|
-
agentFile: `.codex/agents/${m.agentDefinition}.toml`,
|
|
452
|
-
prompt: m.prompt,
|
|
453
|
-
subscriptions: m.subscriptions || [],
|
|
454
|
-
})),
|
|
455
|
-
};
|
|
456
|
-
|
|
457
|
-
await fs.writeFile(
|
|
458
|
-
path.join(codexDir, 'team-info.json'),
|
|
459
|
-
JSON.stringify(teamConfig, null, 2)
|
|
460
|
-
);
|
|
461
|
-
|
|
462
|
-
console.log(chalk.green(` ✓ .codex/team-info.json`));
|
|
463
|
-
}
|
|
464
|
-
}
|
|
465
354
|
|
|
466
355
|
/**
|
|
467
356
|
* 安装平台配置文件(settings/hooks/rules)
|
|
@@ -591,7 +480,7 @@ export async function installSettings(platform, projectRoot, options, dryRun, ru
|
|
|
591
480
|
await fs.ensureDir(path.dirname(configPath));
|
|
592
481
|
const configToml = `# Generated by PrizmKit for Codex CLI project configuration.
|
|
593
482
|
# Keep project guidance in AGENTS.md; repository skills in .agents/skills/;
|
|
594
|
-
# PrizmKit behavioral rules live in .agents/rules
|
|
483
|
+
# PrizmKit behavioral rules live in .agents/rules/.
|
|
595
484
|
|
|
596
485
|
project_doc_fallback_filenames = ["CLAUDE.md", "CODEBUDDY.md"]
|
|
597
486
|
|
|
@@ -1058,7 +947,7 @@ Codex discovers repository skills from \`.agents/skills/\`. When a user or promp
|
|
|
1058
947
|
- Start with \`.agents/skills/prizmkit/SKILL.md\` to see all available PrizmKit skills.
|
|
1059
948
|
- Skill assets and references live inside each \`.agents/skills/<skill>/\` directory.
|
|
1060
949
|
- PrizmKit behavioral rules live in \`.agents/rules/\`; read the relevant Markdown guidance before commit, documentation, or context-loading work.
|
|
1061
|
-
|
|
950
|
+
`
|
|
1062
951
|
);
|
|
1063
952
|
}
|
|
1064
953
|
|
|
@@ -1585,7 +1474,6 @@ export const EXTRAS_REGISTRY = {
|
|
|
1585
1474
|
* @param {string} config.platform - 'codebuddy' | 'claude' | 'codex' | 'all'
|
|
1586
1475
|
* @param {string} [config.runtime] - 'python' (legacy aliases accepted: 'unix' | 'windows')
|
|
1587
1476
|
* @param {string} config.skills - 'core' | 'minimal' | 'recommended:<type>'
|
|
1588
|
-
* @param {boolean} config.team - 是否启用团队模式
|
|
1589
1477
|
* @param {boolean} config.pipeline - 是否安装 dev-pipeline
|
|
1590
1478
|
* @param {string} [config.rules] - Rules preset: 'recommended' | 'minimal' | 'none'
|
|
1591
1479
|
* @param {string} [config.aiCli] - AI CLI 可执行命令(写入 .prizmkit/config.json)
|
|
@@ -1597,7 +1485,7 @@ export const EXTRAS_REGISTRY = {
|
|
|
1597
1485
|
* @param {boolean} config.dryRun - 是否为预览模式
|
|
1598
1486
|
*/
|
|
1599
1487
|
export async function scaffold(config) {
|
|
1600
|
-
const { platform, skills,
|
|
1488
|
+
const { platform, skills, pipeline, rules, aiCli, aiCliLaunch, externalSkills, playwrightCli, openCli, openCliAutoDownload, projectRoot, dryRun } = config;
|
|
1601
1489
|
const runtime = normalizeRuntime(config.runtime);
|
|
1602
1490
|
const launchSelection = resolveAiCliLaunchSelection(aiCli || '', {
|
|
1603
1491
|
aiCliLaunch,
|
|
@@ -1622,21 +1510,13 @@ export async function scaffold(config) {
|
|
|
1622
1510
|
for (const p of payloadPlatforms) {
|
|
1623
1511
|
console.log(chalk.bold(` 正在安装 ${platformLabel(p)} 环境...${platforms.includes(p) ? '' : chalk.gray(' (AI CLI payload)')}\n`));
|
|
1624
1512
|
|
|
1513
|
+
await removeRetiredAgentTeamArtifacts(p, projectRoot, dryRun);
|
|
1514
|
+
|
|
1625
1515
|
// 1. Skills
|
|
1626
1516
|
console.log(chalk.blue(' 技能文件:'));
|
|
1627
1517
|
await installSkills(p, skillList, projectRoot, dryRun, runtime);
|
|
1628
1518
|
|
|
1629
|
-
// 2.
|
|
1630
|
-
console.log(chalk.blue('\n Agent 定义:'));
|
|
1631
|
-
await installAgents(p, projectRoot, dryRun);
|
|
1632
|
-
|
|
1633
|
-
// 3. Team
|
|
1634
|
-
if (team) {
|
|
1635
|
-
console.log(chalk.blue('\n 团队配置:'));
|
|
1636
|
-
await installTeamConfig(p, projectRoot, dryRun);
|
|
1637
|
-
}
|
|
1638
|
-
|
|
1639
|
-
// 4. Settings/Hooks/Rules
|
|
1519
|
+
// 2. Settings/Hooks/Rules
|
|
1640
1520
|
console.log(chalk.blue('\n 平台配置:'));
|
|
1641
1521
|
await installSettings(p, projectRoot, { pipeline, rules }, dryRun, runtime);
|
|
1642
1522
|
|
|
@@ -1747,8 +1627,6 @@ export async function scaffold(config) {
|
|
|
1747
1627
|
|
|
1748
1628
|
// 14. Write installation manifest
|
|
1749
1629
|
if (!dryRun) {
|
|
1750
|
-
const agentsDir = getAgentsDir();
|
|
1751
|
-
const agentFileNames = (await fs.readdir(agentsDir)).filter(f => f.endsWith('.md'));
|
|
1752
1630
|
const rulesMeta = await loadRulesMetadata();
|
|
1753
1631
|
const rulesPresetName = rules || 'recommended';
|
|
1754
1632
|
const ruleFileNames = resolveRuleNamesForRuntime(rulesMeta, rulesPresetName, runtime).map(name => `${name}.md`);
|
|
@@ -1759,10 +1637,8 @@ export async function scaffold(config) {
|
|
|
1759
1637
|
runtime,
|
|
1760
1638
|
suite: skills,
|
|
1761
1639
|
skills: skillList,
|
|
1762
|
-
agents: agentFileNames,
|
|
1763
1640
|
rules: ruleFileNames,
|
|
1764
1641
|
pipeline: installedPipelineFiles,
|
|
1765
|
-
team,
|
|
1766
1642
|
aiCli: resolvedAiCli,
|
|
1767
1643
|
rulesPreset: rulesPresetName,
|
|
1768
1644
|
extras: activeExtras,
|
|
@@ -1819,7 +1695,6 @@ export async function scaffold(config) {
|
|
|
1819
1695
|
console.log(chalk.gray(` AI CLI 载荷平台: ${payloadPlatforms.map(platformLabel).join(' + ')}`));
|
|
1820
1696
|
}
|
|
1821
1697
|
console.log(chalk.gray(` 运行时: ${runtimeLabel(runtime)}`));
|
|
1822
|
-
console.log(chalk.gray(` 团队: ${team ? '已启用' : '未启用'}`));
|
|
1823
1698
|
console.log(chalk.gray(` 流水线: ${pipeline ? '已安装' : '未安装'}`));
|
|
1824
1699
|
const browserTools = [playwrightCli && 'playwright-cli', openCli && 'opencli'].filter(Boolean);
|
|
1825
1700
|
console.log(chalk.gray(` 浏览器工具: ${browserTools.length ? '已安装 (' + browserTools.join(' + ') + ')' : '未安装'}`));
|
package/src/upgrade.js
CHANGED
|
@@ -16,23 +16,21 @@ import { confirm } from '@inquirer/prompts';
|
|
|
16
16
|
import { readManifest, writeManifest, buildManifest, diffManifest } from './manifest.js';
|
|
17
17
|
import {
|
|
18
18
|
loadRulesMetadata,
|
|
19
|
-
getAgentsDir,
|
|
20
19
|
} from './metadata.js';
|
|
21
20
|
import {
|
|
22
21
|
installSkills,
|
|
23
|
-
installAgents,
|
|
24
22
|
installSettings,
|
|
25
23
|
installPipeline,
|
|
26
24
|
installPrizmkitScripts,
|
|
27
25
|
installGitHook,
|
|
28
26
|
installGitignore,
|
|
29
27
|
installProjectMemory,
|
|
30
|
-
installTeamConfig,
|
|
31
28
|
resolvePipelineFileList,
|
|
32
29
|
findStaleManagedPipelineFiles,
|
|
33
30
|
removeStaleManagedPipelineFiles,
|
|
34
31
|
resolveRuleNamesForRuntime,
|
|
35
32
|
resolveSkillList,
|
|
33
|
+
removeRetiredAgentTeamArtifacts,
|
|
36
34
|
EXTRAS_REGISTRY,
|
|
37
35
|
} from './scaffold.js';
|
|
38
36
|
import { platformLabel, privateProjectMemoryFiles, resolvePayloadPlatforms } from './platforms.js';
|
|
@@ -222,7 +220,6 @@ export async function runUpgrade(directory, options = {}) {
|
|
|
222
220
|
// 3. Resolve new skill list using old manifest's suite + platform (or defaults)
|
|
223
221
|
const suite = oldManifest?.suite || 'core';
|
|
224
222
|
const runtime = normalizeRuntime(oldManifest?.runtime);
|
|
225
|
-
const team = oldManifest?.options?.team ?? true;
|
|
226
223
|
const pipeline = oldManifest?.options?.pipeline ?? true;
|
|
227
224
|
const rulesPreset = oldManifest?.options?.rules || 'recommended';
|
|
228
225
|
const aiCli = userConfig.ai_cli || oldManifest?.options?.aiCli || '';
|
|
@@ -243,12 +240,9 @@ export async function runUpgrade(directory, options = {}) {
|
|
|
243
240
|
return false;
|
|
244
241
|
}
|
|
245
242
|
};
|
|
246
|
-
const hasClaude = await hasPlatformFiles(path.join(projectRoot, '.claude', 'commands'))
|
|
247
|
-
|
|
248
|
-
const
|
|
249
|
-
|| await hasPlatformFiles(path.join(projectRoot, '.codebuddy', 'agents'));
|
|
250
|
-
const hasCodex = await hasPlatformFiles(path.join(projectRoot, '.agents', 'skills'))
|
|
251
|
-
|| await hasPlatformFiles(path.join(projectRoot, '.codex', 'agents'));
|
|
243
|
+
const hasClaude = await hasPlatformFiles(path.join(projectRoot, '.claude', 'commands'));
|
|
244
|
+
const hasCodeBuddy = await hasPlatformFiles(path.join(projectRoot, '.codebuddy', 'skills'));
|
|
245
|
+
const hasCodex = await hasPlatformFiles(path.join(projectRoot, '.agents', 'skills'));
|
|
252
246
|
|
|
253
247
|
const detectedPlatforms = [
|
|
254
248
|
hasCodeBuddy && 'codebuddy',
|
|
@@ -262,8 +256,6 @@ export async function runUpgrade(directory, options = {}) {
|
|
|
262
256
|
}
|
|
263
257
|
|
|
264
258
|
const newSkillList = await resolveSkillList(suite);
|
|
265
|
-
const agentsDir = getAgentsDir();
|
|
266
|
-
const newAgentFiles = (await fs.readdir(agentsDir)).filter(f => f.endsWith('.md'));
|
|
267
259
|
const rulesMeta = await loadRulesMetadata();
|
|
268
260
|
const newRuleFiles = resolveRuleNamesForRuntime(rulesMeta, rulesPreset, runtime).map(name => `${name}.md`);
|
|
269
261
|
|
|
@@ -286,10 +278,8 @@ export async function runUpgrade(directory, options = {}) {
|
|
|
286
278
|
runtime,
|
|
287
279
|
suite,
|
|
288
280
|
skills: newSkillList,
|
|
289
|
-
agents: newAgentFiles,
|
|
290
281
|
rules: newRuleFiles,
|
|
291
282
|
pipeline: newPipelineFiles,
|
|
292
|
-
team,
|
|
293
283
|
aiCli,
|
|
294
284
|
rulesPreset,
|
|
295
285
|
extras: extrasToInstall,
|
|
@@ -301,7 +291,7 @@ export async function runUpgrade(directory, options = {}) {
|
|
|
301
291
|
newManifest.installedAt = oldManifest.installedAt;
|
|
302
292
|
}
|
|
303
293
|
|
|
304
|
-
const diff = oldManifest ? diffManifest(oldManifest, newManifest) : { skills: { added: [], removed: [] },
|
|
294
|
+
const diff = oldManifest ? diffManifest(oldManifest, newManifest) : { skills: { added: [], removed: [] }, rules: { added: [], removed: [] }, pipeline: { added: [], removed: [] }, extras: { added: [], removed: [] }, legacyAgents: { added: [], removed: [] } };
|
|
305
295
|
const removedPipelineSet = new Set(diff.pipeline.removed);
|
|
306
296
|
const staleManagedPipelineFiles = pipeline
|
|
307
297
|
? (await findStaleManagedPipelineFiles(projectRoot, runtime))
|
|
@@ -317,14 +307,13 @@ export async function runUpgrade(directory, options = {}) {
|
|
|
317
307
|
console.log(` Suite: ${suite}`);
|
|
318
308
|
console.log('');
|
|
319
309
|
|
|
320
|
-
const totalAdded = diff.skills.added.length + diff.
|
|
321
|
-
const totalRemoved = diff.skills.removed.length + diff.
|
|
322
|
-
const totalUpdated = newSkillList.length +
|
|
310
|
+
const totalAdded = diff.skills.added.length + diff.rules.added.length + diff.pipeline.added.length + diff.extras.added.length;
|
|
311
|
+
const totalRemoved = diff.skills.removed.length + diff.rules.removed.length + diff.pipeline.removed.length + diff.extras.removed.length + diff.legacyAgents.removed.length + staleManagedPipelineFiles.length;
|
|
312
|
+
const totalUpdated = newSkillList.length + newRuleFiles.length;
|
|
323
313
|
|
|
324
314
|
if (diff.skills.added.length) console.log(chalk.green(` + Skills added: ${diff.skills.added.join(', ')}`));
|
|
325
315
|
if (diff.skills.removed.length) console.log(chalk.red(` - Skills removed: ${diff.skills.removed.join(', ')}`));
|
|
326
|
-
if (diff.
|
|
327
|
-
if (diff.agents.removed.length) console.log(chalk.red(` - Agents removed: ${diff.agents.removed.join(', ')}`));
|
|
316
|
+
if (diff.legacyAgents.removed.length) console.log(chalk.red(` - Legacy agents removed: ${diff.legacyAgents.removed.join(', ')}`));
|
|
328
317
|
if (diff.rules.added.length) console.log(chalk.green(` + Rules added: ${diff.rules.added.join(', ')}`));
|
|
329
318
|
if (diff.rules.removed.length) console.log(chalk.red(` - Rules removed: ${diff.rules.removed.join(', ')}`));
|
|
330
319
|
if (diff.pipeline.added.length) console.log(chalk.green(` + Pipeline files added: ${diff.pipeline.added.length} file(s)`));
|
|
@@ -356,17 +345,19 @@ export async function runUpgrade(directory, options = {}) {
|
|
|
356
345
|
const platforms = payloadPlatforms;
|
|
357
346
|
|
|
358
347
|
// 7a. Remove orphaned files
|
|
359
|
-
if (diff.skills.removed.length || diff.
|
|
348
|
+
if (diff.skills.removed.length || diff.legacyAgents.removed.length || diff.rules.removed.length || diff.pipeline.removed.length || staleManagedPipelineFiles.length) {
|
|
360
349
|
console.log(chalk.bold('\n Removing orphaned files...'));
|
|
361
350
|
for (const p of platforms) {
|
|
362
351
|
if (diff.skills.removed.length) {
|
|
363
352
|
console.log(chalk.blue(`\n Removed skills (${p}):`));
|
|
364
353
|
await removeSkillFiles(p, projectRoot, diff.skills.removed, dryRun);
|
|
365
354
|
}
|
|
366
|
-
if (diff.
|
|
367
|
-
console.log(chalk.blue(`\n Removed agents (${p}):`));
|
|
368
|
-
await removeAgentFiles(p, projectRoot, diff.
|
|
355
|
+
if (diff.legacyAgents.removed.length) {
|
|
356
|
+
console.log(chalk.blue(`\n Removed legacy agents (${p}):`));
|
|
357
|
+
await removeAgentFiles(p, projectRoot, diff.legacyAgents.removed, dryRun);
|
|
369
358
|
}
|
|
359
|
+
console.log(chalk.blue(`\n Removed retired agent/team artifacts (${p}):`));
|
|
360
|
+
await removeRetiredAgentTeamArtifacts(p, projectRoot, dryRun);
|
|
370
361
|
if (diff.rules.removed.length) {
|
|
371
362
|
console.log(chalk.blue(`\n Removed rules (${p}):`));
|
|
372
363
|
await removeRuleFiles(p, projectRoot, diff.rules.removed, dryRun);
|
|
@@ -387,24 +378,16 @@ export async function runUpgrade(directory, options = {}) {
|
|
|
387
378
|
|
|
388
379
|
for (const p of platforms) {
|
|
389
380
|
console.log(chalk.bold(` Installing ${platformLabel(p)} environment...\n`));
|
|
381
|
+
await removeRetiredAgentTeamArtifacts(p, projectRoot, dryRun);
|
|
390
382
|
|
|
391
383
|
// Skills
|
|
392
384
|
console.log(chalk.blue(' Skills:'));
|
|
393
385
|
await installSkills(p, newSkillList, projectRoot, dryRun, runtime);
|
|
394
386
|
|
|
395
|
-
// Agents
|
|
396
|
-
console.log(chalk.blue('\n Agents:'));
|
|
397
|
-
await installAgents(p, projectRoot, dryRun);
|
|
398
|
-
|
|
399
387
|
// Settings/Rules
|
|
400
388
|
console.log(chalk.blue('\n Settings & Rules:'));
|
|
401
389
|
await installSettings(p, projectRoot, { pipeline, rules: rulesPreset }, dryRun, runtime);
|
|
402
390
|
|
|
403
|
-
if (team) {
|
|
404
|
-
console.log(chalk.blue('\n Team Config:'));
|
|
405
|
-
await installTeamConfig(p, projectRoot, dryRun);
|
|
406
|
-
}
|
|
407
|
-
|
|
408
391
|
console.log('');
|
|
409
392
|
}
|
|
410
393
|
|
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Claude Code Agent Adapter
|
|
3
|
-
* Converts core/ agent definitions to .claude/agents/ format.
|
|
4
|
-
*
|
|
5
|
-
* Key differences from CodeBuddy agents:
|
|
6
|
-
* - tools: comma-separated string -> YAML array
|
|
7
|
-
* - model: "inherit" -> explicit model name (or kept as "inherit")
|
|
8
|
-
* - skills: kept as comma-separated string (Claude Code supports it natively)
|
|
9
|
-
* - TaskCreate/Get/Update/List -> Task (single tool)
|
|
10
|
-
* - SendMessage -> SendMessage (native Agent Teams communication)
|
|
11
|
-
*/
|
|
12
|
-
|
|
13
|
-
import { parseFrontmatter, buildMarkdown } from '../shared/frontmatter.js';
|
|
14
|
-
import { TOOL_MAPPING } from '../shared/constants.js';
|
|
15
|
-
import { mkdirSync } from 'node:fs';
|
|
16
|
-
import { readFile, writeFile } from 'node:fs/promises';
|
|
17
|
-
import path from 'path';
|
|
18
|
-
|
|
19
|
-
// Default model for Claude Code agents
|
|
20
|
-
const DEFAULT_MODEL = 'claude-sonnet-4-20250514';
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Convert a core agent definition to Claude Code format.
|
|
24
|
-
* @param {string} agentContent - Content of the core agent .md
|
|
25
|
-
* @param {Object} options - { model?: string }
|
|
26
|
-
* @returns {string} - Claude Code formatted agent .md content
|
|
27
|
-
*/
|
|
28
|
-
export function convertAgent(agentContent, options = {}) {
|
|
29
|
-
const { frontmatter, body } = parseFrontmatter(agentContent);
|
|
30
|
-
|
|
31
|
-
// Convert tools: comma-separated string -> deduplicated array
|
|
32
|
-
let tools = [];
|
|
33
|
-
if (frontmatter.tools) {
|
|
34
|
-
const rawTools = frontmatter.tools.split(',').map(t => t.trim());
|
|
35
|
-
const mapped = rawTools.map(t => {
|
|
36
|
-
if (TOOL_MAPPING.hasOwnProperty(t)) {
|
|
37
|
-
return TOOL_MAPPING[t];
|
|
38
|
-
}
|
|
39
|
-
return t;
|
|
40
|
-
}).filter(Boolean);
|
|
41
|
-
tools = [...new Set(mapped)];
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
// Body content is used as-is — no injection or transformation needed.
|
|
45
|
-
// Claude Code natively supports skills in frontmatter and slash commands in body.
|
|
46
|
-
let convertedBody = body;
|
|
47
|
-
|
|
48
|
-
// Convert disallowedTools: comma-separated string -> deduplicated array
|
|
49
|
-
let disallowedTools = [];
|
|
50
|
-
if (frontmatter.disallowedTools) {
|
|
51
|
-
const rawDisallowed = frontmatter.disallowedTools.split(',').map(t => t.trim());
|
|
52
|
-
const mappedDisallowed = rawDisallowed.map(t => {
|
|
53
|
-
if (TOOL_MAPPING.hasOwnProperty(t)) {
|
|
54
|
-
return TOOL_MAPPING[t];
|
|
55
|
-
}
|
|
56
|
-
return t;
|
|
57
|
-
}).filter(Boolean);
|
|
58
|
-
disallowedTools = [...new Set(mappedDisallowed)];
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
// Build Claude Code frontmatter
|
|
62
|
-
const claudeFrontmatter = {
|
|
63
|
-
name: frontmatter.name,
|
|
64
|
-
description: frontmatter.description,
|
|
65
|
-
tools: tools,
|
|
66
|
-
model: options.model || DEFAULT_MODEL,
|
|
67
|
-
};
|
|
68
|
-
|
|
69
|
-
// Add disallowedTools if present
|
|
70
|
-
if (disallowedTools.length > 0) {
|
|
71
|
-
claudeFrontmatter.disallowedTools = disallowedTools;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
// Preserve skills field if present (Claude Code supports it natively)
|
|
75
|
-
if (frontmatter.skills) {
|
|
76
|
-
claudeFrontmatter.skills = frontmatter.skills;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
return buildMarkdown(claudeFrontmatter, convertedBody);
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
/**
|
|
83
|
-
* Install an agent definition to the target project's .claude/agents/.
|
|
84
|
-
* @param {string} corePath - Path to core/agents/<name>.md
|
|
85
|
-
* @param {string} targetRoot - Target project root
|
|
86
|
-
* @param {Object} options - { model?: string }
|
|
87
|
-
*/
|
|
88
|
-
export async function installAgent(corePath, targetRoot, options = {}) {
|
|
89
|
-
const filename = path.basename(corePath);
|
|
90
|
-
const targetDir = path.join(targetRoot, '.claude', 'agents');
|
|
91
|
-
mkdirSync(targetDir, { recursive: true });
|
|
92
|
-
|
|
93
|
-
const content = await readFile(corePath, 'utf8');
|
|
94
|
-
const converted = convertAgent(content, options);
|
|
95
|
-
await writeFile(path.join(targetDir, filename), converted);
|
|
96
|
-
}
|