aigent-team 0.2.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +150 -13
- package/dist/{chunk-U3NGK2UZ.js → chunk-OMO7OMKB.js} +264 -22
- package/dist/cli.js +1750 -217
- package/dist/index.d.ts +54 -0
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/templates/teams/ba/assets/story-template.md +49 -0
- package/templates/teams/ba/examples/acceptance-criteria.md +39 -0
- package/templates/teams/ba/output-contracts/user-story-rubric.md +33 -0
- package/templates/teams/ba/references/acceptance-criteria.md +7 -0
- package/templates/teams/ba/references/api-contract-design.md +7 -0
- package/templates/teams/ba/references/requirements-analysis.md +7 -0
- package/templates/teams/ba/references/user-story-mapping.md +7 -0
- package/templates/teams/ba/skills/requirement-validation.md +11 -0
- package/templates/teams/ba/skills/story-decomposition.md +16 -0
- package/templates/teams/be/references/api-design.md +7 -0
- package/templates/teams/be/references/async-processing.md +7 -0
- package/templates/teams/be/references/auth-security.md +7 -0
- package/templates/teams/be/references/caching.md +7 -0
- package/templates/teams/be/references/database.md +7 -0
- package/templates/teams/be/references/error-handling.md +7 -0
- package/templates/teams/be/references/observability.md +7 -0
- package/templates/teams/be/references/review-checklist.md +7 -0
- package/templates/teams/be/references/testing.md +7 -0
- package/templates/teams/be/skills/api-load-test.md +11 -0
- package/templates/teams/be/skills/database-migration.md +11 -0
- package/templates/teams/devops/references/ci-cd.md +7 -0
- package/templates/teams/devops/references/cost-optimization.md +7 -0
- package/templates/teams/devops/references/disaster-recovery.md +7 -0
- package/templates/teams/devops/references/docker.md +7 -0
- package/templates/teams/devops/references/infrastructure-as-code.md +7 -0
- package/templates/teams/devops/references/kubernetes.md +7 -0
- package/templates/teams/devops/references/monitoring.md +7 -0
- package/templates/teams/devops/references/review-checklist.md +7 -0
- package/templates/teams/devops/references/security.md +7 -0
- package/templates/teams/devops/scripts/health-check.sh +35 -0
- package/templates/teams/devops/skills/health-check.md +11 -0
- package/templates/teams/devops/skills/rollback-procedure.md +15 -0
- package/templates/teams/fe/examples/component-audit.md +35 -0
- package/templates/teams/fe/references/accessibility.md +7 -0
- package/templates/teams/fe/references/component-architecture.md +7 -0
- package/templates/teams/fe/references/css-styling.md +7 -0
- package/templates/teams/fe/references/forms.md +7 -0
- package/templates/teams/fe/references/performance.md +7 -0
- package/templates/teams/fe/references/review-checklist.md +7 -0
- package/templates/teams/fe/references/security.md +7 -0
- package/templates/teams/fe/references/state-management.md +7 -0
- package/templates/teams/fe/references/testing.md +7 -0
- package/templates/teams/fe/skills/analyze-bundle.md +16 -0
- package/templates/teams/fe/skills/component-audit.md +11 -0
- package/templates/teams/lead/references/cross-team-coordination.md +7 -0
- package/templates/teams/lead/references/quality-gates.md +7 -0
- package/templates/teams/lead/references/task-decomposition.md +7 -0
- package/templates/teams/lead/skills/parallel-orchestration.md +11 -0
- package/templates/teams/lead/skills/sprint-review.md +11 -0
- package/templates/teams/qa/assets/test-report-template.md +63 -0
- package/templates/teams/qa/output-contracts/test-plan-rubric.md +36 -0
- package/templates/teams/qa/references/ci-integration.md +7 -0
- package/templates/teams/qa/references/e2e-testing.md +7 -0
- package/templates/teams/qa/references/mocking.md +7 -0
- package/templates/teams/qa/references/performance-testing.md +7 -0
- package/templates/teams/qa/references/review-checklist.md +7 -0
- package/templates/teams/qa/references/security-testing.md +7 -0
- package/templates/teams/qa/references/test-data.md +7 -0
- package/templates/teams/qa/references/test-strategy.md +7 -0
- package/templates/teams/qa/skills/flaky-test-diagnosis.md +11 -0
- package/templates/teams/qa/skills/generate-test-data.md +15 -0
package/dist/cli.js
CHANGED
|
@@ -1,23 +1,32 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire } from 'module'; const require = createRequire(import.meta.url);
|
|
3
3
|
import {
|
|
4
|
+
GENERATE_SCOPES,
|
|
4
5
|
PLATFORMS,
|
|
6
|
+
PLUGIN_BUNDLE_DIRS,
|
|
7
|
+
TEAM_ROLES,
|
|
8
|
+
assembleAsset,
|
|
9
|
+
assembleExample,
|
|
10
|
+
assembleOutputContract,
|
|
5
11
|
assembleReference,
|
|
12
|
+
assembleScript,
|
|
6
13
|
assembleSkill,
|
|
7
14
|
assembleSkillIndex,
|
|
8
15
|
configExists,
|
|
9
16
|
loadAgents,
|
|
10
|
-
loadConfig
|
|
11
|
-
|
|
17
|
+
loadConfig,
|
|
18
|
+
parseFrontmatter
|
|
19
|
+
} from "./chunk-OMO7OMKB.js";
|
|
12
20
|
|
|
13
21
|
// bin/cli.ts
|
|
14
22
|
import { Command } from "commander";
|
|
23
|
+
import chalk7 from "chalk";
|
|
15
24
|
|
|
16
25
|
// src/cli/init.ts
|
|
17
|
-
import { writeFileSync
|
|
18
|
-
import { resolve as
|
|
26
|
+
import { writeFileSync } from "fs";
|
|
27
|
+
import { resolve as resolve2 } from "path";
|
|
19
28
|
import inquirer from "inquirer";
|
|
20
|
-
import
|
|
29
|
+
import chalk from "chalk";
|
|
21
30
|
|
|
22
31
|
// src/detectors/platform-detector.ts
|
|
23
32
|
import { execSync } from "child_process";
|
|
@@ -65,13 +74,172 @@ function detectPlatforms(cwd = process.cwd()) {
|
|
|
65
74
|
return results;
|
|
66
75
|
}
|
|
67
76
|
|
|
77
|
+
// src/cli/init.ts
|
|
78
|
+
async function runInit(cwd = process.cwd()) {
|
|
79
|
+
console.log(chalk.bold("\n\u{1F916} aigent-team init\n"));
|
|
80
|
+
if (configExists(cwd)) {
|
|
81
|
+
const { overwrite } = await inquirer.prompt([
|
|
82
|
+
{
|
|
83
|
+
type: "confirm",
|
|
84
|
+
name: "overwrite",
|
|
85
|
+
message: "aigent-team.config.json already exists. Overwrite?",
|
|
86
|
+
default: false
|
|
87
|
+
}
|
|
88
|
+
]);
|
|
89
|
+
if (!overwrite) {
|
|
90
|
+
console.log(chalk.yellow("Aborted."));
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
console.log(chalk.dim("Detecting installed AI tools..."));
|
|
95
|
+
const detections = detectPlatforms(cwd);
|
|
96
|
+
const detectedPlatforms = detections.filter((d) => d.detected);
|
|
97
|
+
if (detectedPlatforms.length > 0) {
|
|
98
|
+
console.log(chalk.green(`Found: ${detectedPlatforms.map((d) => d.platform).join(", ")}`));
|
|
99
|
+
} else {
|
|
100
|
+
console.log(chalk.dim("No AI tools detected. You can still select platforms manually."));
|
|
101
|
+
}
|
|
102
|
+
const answers = await inquirer.prompt([
|
|
103
|
+
{
|
|
104
|
+
type: "input",
|
|
105
|
+
name: "projectName",
|
|
106
|
+
message: "Project name:",
|
|
107
|
+
default: cwd.split("/").pop()
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
type: "checkbox",
|
|
111
|
+
name: "platforms",
|
|
112
|
+
message: "Target platforms:",
|
|
113
|
+
choices: PLATFORMS.map((p) => ({
|
|
114
|
+
name: p,
|
|
115
|
+
checked: detections.find((d) => d.platform === p)?.detected ?? false
|
|
116
|
+
})),
|
|
117
|
+
validate: (input) => input.length > 0 || "Select at least one platform"
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
type: "checkbox",
|
|
121
|
+
name: "teams",
|
|
122
|
+
message: "Team agents to enable:",
|
|
123
|
+
choices: [
|
|
124
|
+
{ name: "Lead (Tech Lead / Orchestrator)", value: "lead", checked: true },
|
|
125
|
+
{ name: "BA (Business Analyst)", value: "ba", checked: true },
|
|
126
|
+
{ name: "FE (Frontend)", value: "fe", checked: true },
|
|
127
|
+
{ name: "BE (Backend)", value: "be", checked: true },
|
|
128
|
+
{ name: "QA (Testing)", value: "qa", checked: true },
|
|
129
|
+
{ name: "DevOps (Infrastructure)", value: "devops", checked: true }
|
|
130
|
+
],
|
|
131
|
+
validate: (input) => input.length > 0 || "Select at least one team"
|
|
132
|
+
}
|
|
133
|
+
]);
|
|
134
|
+
const config = {
|
|
135
|
+
projectName: answers.projectName,
|
|
136
|
+
platforms: answers.platforms,
|
|
137
|
+
teams: answers.teams
|
|
138
|
+
};
|
|
139
|
+
const configPath = resolve2(cwd, "aigent-team.config.json");
|
|
140
|
+
writeFileSync(configPath, JSON.stringify(config, null, 2) + "\n");
|
|
141
|
+
console.log(chalk.green(`
|
|
142
|
+
\u2713 Created ${configPath}`));
|
|
143
|
+
console.log(chalk.bold.green("\n\u2705 aigent-team initialized successfully!\n"));
|
|
144
|
+
console.log(chalk.dim("Next steps:"));
|
|
145
|
+
console.log(chalk.dim(" - Review aigent-team.config.json and adjust if needed"));
|
|
146
|
+
console.log(chalk.dim(" - Run `aigent-team generate` to generate platform configs"));
|
|
147
|
+
console.log(chalk.dim(" - Use `aigent-team generate --scope agents,skills` to control what gets generated\n"));
|
|
148
|
+
}
|
|
149
|
+
|
|
68
150
|
// src/cli/generate.ts
|
|
69
|
-
import { writeFileSync, mkdirSync, existsSync as existsSync2, readFileSync } from "fs";
|
|
70
|
-
import { resolve as
|
|
71
|
-
import
|
|
151
|
+
import { writeFileSync as writeFileSync2, mkdirSync as mkdirSync2, existsSync as existsSync2, readFileSync } from "fs";
|
|
152
|
+
import { resolve as resolve3, dirname } from "path";
|
|
153
|
+
import inquirer2 from "inquirer";
|
|
154
|
+
import chalk2 from "chalk";
|
|
72
155
|
|
|
73
156
|
// src/compilers/base.compiler.ts
|
|
74
157
|
var BaseCompiler = class {
|
|
158
|
+
/**
|
|
159
|
+
* Compile with scope filtering. Delegates to decomposed methods.
|
|
160
|
+
* 'all' = hub + agents + skills + references.
|
|
161
|
+
* 'plugin' is handled externally in generate.ts.
|
|
162
|
+
*/
|
|
163
|
+
compileWithScope(agents, config, scopes) {
|
|
164
|
+
const normalized = /* @__PURE__ */ new Set();
|
|
165
|
+
for (const s of scopes) {
|
|
166
|
+
if (s === "all") {
|
|
167
|
+
normalized.add("hub");
|
|
168
|
+
normalized.add("agents");
|
|
169
|
+
normalized.add("skills");
|
|
170
|
+
normalized.add("references");
|
|
171
|
+
normalized.add("examples");
|
|
172
|
+
normalized.add("output-contracts");
|
|
173
|
+
normalized.add("scripts");
|
|
174
|
+
normalized.add("assets");
|
|
175
|
+
} else {
|
|
176
|
+
normalized.add(s);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
const outputs = [];
|
|
180
|
+
if (normalized.has("agents")) {
|
|
181
|
+
outputs.push(...this.compileHubFile(agents, config));
|
|
182
|
+
outputs.push(...this.compileAgentIndexes(agents, config));
|
|
183
|
+
}
|
|
184
|
+
if (normalized.has("skills")) {
|
|
185
|
+
outputs.push(...this.compileAllSkills(agents));
|
|
186
|
+
}
|
|
187
|
+
if (normalized.has("references")) {
|
|
188
|
+
outputs.push(...this.compileAllReferences(agents));
|
|
189
|
+
}
|
|
190
|
+
if (normalized.has("examples")) {
|
|
191
|
+
outputs.push(...this.compileAllExamples(agents));
|
|
192
|
+
}
|
|
193
|
+
if (normalized.has("output-contracts")) {
|
|
194
|
+
outputs.push(...this.compileAllOutputContracts(agents));
|
|
195
|
+
}
|
|
196
|
+
if (normalized.has("scripts")) {
|
|
197
|
+
outputs.push(...this.compileAllScripts(agents));
|
|
198
|
+
}
|
|
199
|
+
if (normalized.has("assets")) {
|
|
200
|
+
outputs.push(...this.compileAllAssets(agents));
|
|
201
|
+
}
|
|
202
|
+
return outputs;
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Count files per artifact category from compiled outputs.
|
|
206
|
+
* Subclasses can override to customize category detection.
|
|
207
|
+
*/
|
|
208
|
+
countArtifacts(outputs, rootDir) {
|
|
209
|
+
const counts = {};
|
|
210
|
+
const categories = ["rules", "skills", "agents", "kb", "examples", "contracts", "ai"];
|
|
211
|
+
for (const cat of categories) {
|
|
212
|
+
const prefix = `${rootDir}/${cat}/`;
|
|
213
|
+
const count = outputs.filter((o) => o.filePath.startsWith(prefix)).length;
|
|
214
|
+
if (count > 0) counts[cat] = count;
|
|
215
|
+
}
|
|
216
|
+
return counts;
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Compile all example files. Default no-op — override in subclasses.
|
|
220
|
+
*/
|
|
221
|
+
compileAllExamples(_agents) {
|
|
222
|
+
return [];
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* Compile all output contract files. Default no-op — override in subclasses.
|
|
226
|
+
*/
|
|
227
|
+
compileAllOutputContracts(_agents) {
|
|
228
|
+
return [];
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* Compile all script files. Default no-op — override in subclasses.
|
|
232
|
+
*/
|
|
233
|
+
compileAllScripts(_agents) {
|
|
234
|
+
return [];
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* Compile all asset files. Default no-op — override in subclasses.
|
|
238
|
+
*/
|
|
239
|
+
compileAllAssets(_agents) {
|
|
240
|
+
return [];
|
|
241
|
+
}
|
|
242
|
+
// ---- Shared helpers ----
|
|
75
243
|
/**
|
|
76
244
|
* Compile reference files for an agent into a given directory.
|
|
77
245
|
* Returns CompiledOutput[] for each reference file.
|
|
@@ -96,6 +264,50 @@ var BaseCompiler = class {
|
|
|
96
264
|
overwriteStrategy: "replace"
|
|
97
265
|
}));
|
|
98
266
|
}
|
|
267
|
+
/**
|
|
268
|
+
* Compile example files for an agent into a given directory.
|
|
269
|
+
*/
|
|
270
|
+
compileExamples(agent, baseDir, extension = ".md") {
|
|
271
|
+
if (!agent.examples?.length) return [];
|
|
272
|
+
return agent.examples.map((example) => ({
|
|
273
|
+
filePath: `${baseDir}/${example.id}${extension}`,
|
|
274
|
+
content: assembleExample(example) + "\n",
|
|
275
|
+
overwriteStrategy: "replace"
|
|
276
|
+
}));
|
|
277
|
+
}
|
|
278
|
+
/**
|
|
279
|
+
* Compile output contract files for an agent into a given directory.
|
|
280
|
+
*/
|
|
281
|
+
compileOutputContracts(agent, baseDir, extension = ".md") {
|
|
282
|
+
if (!agent.outputContracts?.length) return [];
|
|
283
|
+
return agent.outputContracts.map((contract) => ({
|
|
284
|
+
filePath: `${baseDir}/${contract.id}${extension}`,
|
|
285
|
+
content: assembleOutputContract(contract) + "\n",
|
|
286
|
+
overwriteStrategy: "replace"
|
|
287
|
+
}));
|
|
288
|
+
}
|
|
289
|
+
/**
|
|
290
|
+
* Compile script files for an agent into a given directory.
|
|
291
|
+
*/
|
|
292
|
+
compileScriptFiles(agent, baseDir, extension = ".md") {
|
|
293
|
+
if (!agent.scripts?.length) return [];
|
|
294
|
+
return agent.scripts.map((script) => ({
|
|
295
|
+
filePath: `${baseDir}/${script.id}${extension}`,
|
|
296
|
+
content: assembleScript(script) + "\n",
|
|
297
|
+
overwriteStrategy: "replace"
|
|
298
|
+
}));
|
|
299
|
+
}
|
|
300
|
+
/**
|
|
301
|
+
* Compile asset files for an agent into a given directory.
|
|
302
|
+
*/
|
|
303
|
+
compileAssetFiles(agent, baseDir, extension = ".md") {
|
|
304
|
+
if (!agent.assets?.length) return [];
|
|
305
|
+
return agent.assets.map((asset) => ({
|
|
306
|
+
filePath: `${baseDir}/${asset.id}${extension}`,
|
|
307
|
+
content: assembleAsset(asset) + "\n",
|
|
308
|
+
overwriteStrategy: "replace"
|
|
309
|
+
}));
|
|
310
|
+
}
|
|
99
311
|
formatFrontmatter(data) {
|
|
100
312
|
const lines = ["---"];
|
|
101
313
|
for (const [key, value] of Object.entries(data)) {
|
|
@@ -118,6 +330,31 @@ var BaseCompiler = class {
|
|
|
118
330
|
var ClaudeCodeCompiler = class extends BaseCompiler {
|
|
119
331
|
platform = "claude-code";
|
|
120
332
|
compile(agents, config) {
|
|
333
|
+
return this.compileWithScope(agents, config, ["all"]);
|
|
334
|
+
}
|
|
335
|
+
compileHubFile(agents, _config) {
|
|
336
|
+
const agentList = agents.map((a) => `- **${a.name}** (\`${a.id}\`): ${a.description.trim().split("\n")[0]}`).join("\n");
|
|
337
|
+
const claudeMd = [
|
|
338
|
+
`# CLAUDE.md`,
|
|
339
|
+
``,
|
|
340
|
+
`This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.`,
|
|
341
|
+
``,
|
|
342
|
+
`## Agent Team`,
|
|
343
|
+
``,
|
|
344
|
+
`This project uses aigent-team. The following specialized agents are available:`,
|
|
345
|
+
``,
|
|
346
|
+
agentList,
|
|
347
|
+
``,
|
|
348
|
+
`Use the appropriate agent for your task by invoking it from the .claude/agents/ directory.`,
|
|
349
|
+
``
|
|
350
|
+
].join("\n");
|
|
351
|
+
return [{
|
|
352
|
+
filePath: "CLAUDE.md",
|
|
353
|
+
content: claudeMd,
|
|
354
|
+
overwriteStrategy: "skip-if-exists"
|
|
355
|
+
}];
|
|
356
|
+
}
|
|
357
|
+
compileAgentIndexes(agents, _config) {
|
|
121
358
|
const outputs = [];
|
|
122
359
|
for (const agent of agents) {
|
|
123
360
|
const frontmatter = this.formatFrontmatter({
|
|
@@ -135,37 +372,174 @@ ${body}
|
|
|
135
372
|
content,
|
|
136
373
|
overwriteStrategy: "replace"
|
|
137
374
|
});
|
|
138
|
-
|
|
375
|
+
}
|
|
376
|
+
return outputs;
|
|
377
|
+
}
|
|
378
|
+
compileAllSkills(agents) {
|
|
379
|
+
const outputs = [];
|
|
380
|
+
for (const agent of agents) {
|
|
381
|
+
outputs.push(...this.compileSkills(
|
|
382
|
+
agent,
|
|
383
|
+
`.claude/agents/${agent.id}-agent/skills`
|
|
384
|
+
));
|
|
385
|
+
}
|
|
386
|
+
return outputs;
|
|
387
|
+
}
|
|
388
|
+
compileAllReferences(agents) {
|
|
389
|
+
const outputs = [];
|
|
390
|
+
for (const agent of agents) {
|
|
391
|
+
outputs.push(...this.compileReferences(
|
|
139
392
|
agent,
|
|
140
393
|
`.claude/agents/${agent.id}-agent/references`
|
|
141
|
-
);
|
|
142
|
-
|
|
143
|
-
|
|
394
|
+
));
|
|
395
|
+
}
|
|
396
|
+
return outputs;
|
|
397
|
+
}
|
|
398
|
+
compileAllExamples(agents) {
|
|
399
|
+
const outputs = [];
|
|
400
|
+
for (const agent of agents) {
|
|
401
|
+
outputs.push(...this.compileExamples(
|
|
144
402
|
agent,
|
|
145
|
-
`.claude/agents/${agent.id}-agent/
|
|
146
|
-
);
|
|
147
|
-
|
|
403
|
+
`.claude/agents/${agent.id}-agent/examples`
|
|
404
|
+
));
|
|
405
|
+
}
|
|
406
|
+
return outputs;
|
|
407
|
+
}
|
|
408
|
+
compileAllOutputContracts(agents) {
|
|
409
|
+
const outputs = [];
|
|
410
|
+
for (const agent of agents) {
|
|
411
|
+
outputs.push(...this.compileOutputContracts(
|
|
412
|
+
agent,
|
|
413
|
+
`.claude/agents/${agent.id}-agent/contracts`
|
|
414
|
+
));
|
|
415
|
+
}
|
|
416
|
+
return outputs;
|
|
417
|
+
}
|
|
418
|
+
compileAllScripts(agents) {
|
|
419
|
+
const outputs = [];
|
|
420
|
+
for (const agent of agents) {
|
|
421
|
+
outputs.push(...this.compileScriptFiles(
|
|
422
|
+
agent,
|
|
423
|
+
`.claude/agents/${agent.id}-agent/scripts`
|
|
424
|
+
));
|
|
425
|
+
}
|
|
426
|
+
return outputs;
|
|
427
|
+
}
|
|
428
|
+
compileAllAssets(agents) {
|
|
429
|
+
const outputs = [];
|
|
430
|
+
for (const agent of agents) {
|
|
431
|
+
outputs.push(...this.compileAssetFiles(
|
|
432
|
+
agent,
|
|
433
|
+
`.claude/agents/${agent.id}-agent/assets`
|
|
434
|
+
));
|
|
148
435
|
}
|
|
436
|
+
return outputs;
|
|
437
|
+
}
|
|
438
|
+
compilePluginBundle(agents, config, rootDir) {
|
|
439
|
+
const outputs = [];
|
|
149
440
|
const agentList = agents.map((a) => `- **${a.name}** (\`${a.id}\`): ${a.description.trim().split("\n")[0]}`).join("\n");
|
|
150
|
-
const claudeMd = [
|
|
151
|
-
`# CLAUDE.md`,
|
|
152
|
-
``,
|
|
153
|
-
`This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.`,
|
|
154
|
-
``,
|
|
155
|
-
`## Agent Team`,
|
|
156
|
-
``,
|
|
157
|
-
`This project uses aigent-team. The following specialized agents are available:`,
|
|
158
|
-
``,
|
|
159
|
-
agentList,
|
|
160
|
-
``,
|
|
161
|
-
`Use the appropriate agent for your task by invoking it from the .claude/agents/ directory.`,
|
|
162
|
-
``
|
|
163
|
-
].join("\n");
|
|
164
441
|
outputs.push({
|
|
165
|
-
filePath:
|
|
166
|
-
content:
|
|
167
|
-
|
|
442
|
+
filePath: `${rootDir}/rules/CLAUDE.md`,
|
|
443
|
+
content: [
|
|
444
|
+
`# CLAUDE.md`,
|
|
445
|
+
``,
|
|
446
|
+
`This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.`,
|
|
447
|
+
``,
|
|
448
|
+
`## Agent Team`,
|
|
449
|
+
``,
|
|
450
|
+
`This project uses aigent-team. The following specialized agents are available:`,
|
|
451
|
+
``,
|
|
452
|
+
agentList,
|
|
453
|
+
``,
|
|
454
|
+
`Use the appropriate agent for your task by invoking it from the agents/ directory.`,
|
|
455
|
+
``
|
|
456
|
+
].join("\n"),
|
|
457
|
+
overwriteStrategy: "replace"
|
|
168
458
|
});
|
|
459
|
+
for (const agent of agents) {
|
|
460
|
+
const frontmatter = this.formatFrontmatter({
|
|
461
|
+
name: agent.name,
|
|
462
|
+
description: agent.description,
|
|
463
|
+
tools: agent.tools.allowed
|
|
464
|
+
});
|
|
465
|
+
const body = assembleSkillIndex(agent);
|
|
466
|
+
outputs.push({
|
|
467
|
+
filePath: `${rootDir}/agents/${agent.id}-agent.md`,
|
|
468
|
+
content: `${frontmatter}
|
|
469
|
+
|
|
470
|
+
${body}
|
|
471
|
+
`,
|
|
472
|
+
overwriteStrategy: "replace"
|
|
473
|
+
});
|
|
474
|
+
}
|
|
475
|
+
for (const agent of agents) {
|
|
476
|
+
if (!agent.skills?.length) continue;
|
|
477
|
+
for (const skill of agent.skills) {
|
|
478
|
+
outputs.push({
|
|
479
|
+
filePath: `${rootDir}/skills/${agent.id}/${skill.id}.md`,
|
|
480
|
+
content: assembleSkill(skill) + "\n",
|
|
481
|
+
overwriteStrategy: "replace"
|
|
482
|
+
});
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
for (const agent of agents) {
|
|
486
|
+
if (!agent.references?.length) continue;
|
|
487
|
+
for (const ref of agent.references) {
|
|
488
|
+
outputs.push({
|
|
489
|
+
filePath: `${rootDir}/kb/${agent.id}/${ref.id}.md`,
|
|
490
|
+
content: assembleReference(ref) + "\n",
|
|
491
|
+
overwriteStrategy: "replace"
|
|
492
|
+
});
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
for (const agent of agents) {
|
|
496
|
+
if (!agent.examples?.length) continue;
|
|
497
|
+
for (const example of agent.examples) {
|
|
498
|
+
outputs.push({
|
|
499
|
+
filePath: `${rootDir}/examples/${agent.id}/${example.id}.md`,
|
|
500
|
+
content: assembleExample(example) + "\n",
|
|
501
|
+
overwriteStrategy: "replace"
|
|
502
|
+
});
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
for (const agent of agents) {
|
|
506
|
+
if (!agent.outputContracts?.length) continue;
|
|
507
|
+
for (const contract of agent.outputContracts) {
|
|
508
|
+
outputs.push({
|
|
509
|
+
filePath: `${rootDir}/contracts/${agent.id}/${contract.id}.md`,
|
|
510
|
+
content: assembleOutputContract(contract) + "\n",
|
|
511
|
+
overwriteStrategy: "replace"
|
|
512
|
+
});
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
for (const agent of agents) {
|
|
516
|
+
if (!agent.scripts?.length) continue;
|
|
517
|
+
for (const script of agent.scripts) {
|
|
518
|
+
outputs.push({
|
|
519
|
+
filePath: `${rootDir}/scripts/${agent.id}/${script.id}.md`,
|
|
520
|
+
content: assembleScript(script) + "\n",
|
|
521
|
+
overwriteStrategy: "replace"
|
|
522
|
+
});
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
for (const agent of agents) {
|
|
526
|
+
if (!agent.assets?.length) continue;
|
|
527
|
+
for (const asset of agent.assets) {
|
|
528
|
+
outputs.push({
|
|
529
|
+
filePath: `${rootDir}/assets/${agent.id}/${asset.id}.md`,
|
|
530
|
+
content: assembleAsset(asset) + "\n",
|
|
531
|
+
overwriteStrategy: "replace"
|
|
532
|
+
});
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
const sharedKnowledge = agents.flatMap((a) => a.sharedKnowledge).filter((v, i, arr) => arr.indexOf(v) === i && v);
|
|
536
|
+
for (let i = 0; i < sharedKnowledge.length; i++) {
|
|
537
|
+
outputs.push({
|
|
538
|
+
filePath: `${rootDir}/kb/shared/knowledge-${i + 1}.md`,
|
|
539
|
+
content: sharedKnowledge[i] + "\n",
|
|
540
|
+
overwriteStrategy: "replace"
|
|
541
|
+
});
|
|
542
|
+
}
|
|
169
543
|
return outputs;
|
|
170
544
|
}
|
|
171
545
|
validate(outputs) {
|
|
@@ -184,10 +558,38 @@ ${body}
|
|
|
184
558
|
}
|
|
185
559
|
};
|
|
186
560
|
|
|
561
|
+
// src/compilers/cursor-ide-plugin.compiler.ts
|
|
562
|
+
function toKebabCursorPluginId(projectName) {
|
|
563
|
+
const s = projectName.toLowerCase().replace(/[^a-z0-9.-]+/g, "-").replace(/^-+|-+$/g, "").replace(/\.{2,}/g, ".");
|
|
564
|
+
if (!s || !/^[a-z0-9]/.test(s)) {
|
|
565
|
+
return `aigent-team-${s || "pack"}`.replace(/^-+/, "");
|
|
566
|
+
}
|
|
567
|
+
return s;
|
|
568
|
+
}
|
|
569
|
+
|
|
187
570
|
// src/compilers/cursor.compiler.ts
|
|
188
571
|
var CursorCompiler = class extends BaseCompiler {
|
|
189
572
|
platform = "cursor";
|
|
190
573
|
compile(agents, config) {
|
|
574
|
+
return this.compileWithScope(agents, config, ["all"]);
|
|
575
|
+
}
|
|
576
|
+
compileHubFile(agents, _config) {
|
|
577
|
+
const sharedKnowledge = agents.flatMap((a) => a.sharedKnowledge).filter((v, i, arr) => arr.indexOf(v) === i && v).join("\n\n---\n\n");
|
|
578
|
+
if (!sharedKnowledge) return [];
|
|
579
|
+
const frontmatter = this.formatFrontmatter({
|
|
580
|
+
description: "Shared project conventions and knowledge for all team agents",
|
|
581
|
+
alwaysApply: true
|
|
582
|
+
});
|
|
583
|
+
return [{
|
|
584
|
+
filePath: ".cursor/rules/shared-conventions.mdc",
|
|
585
|
+
content: `${frontmatter}
|
|
586
|
+
|
|
587
|
+
${sharedKnowledge}
|
|
588
|
+
`,
|
|
589
|
+
overwriteStrategy: "replace"
|
|
590
|
+
}];
|
|
591
|
+
}
|
|
592
|
+
compileAgentIndexes(agents, _config) {
|
|
191
593
|
const outputs = [];
|
|
192
594
|
for (const agent of agents) {
|
|
193
595
|
const globs = agent.globs?.length ? agent.globs.join(", ") : void 0;
|
|
@@ -209,41 +611,118 @@ ${body}
|
|
|
209
611
|
content,
|
|
210
612
|
overwriteStrategy: "replace"
|
|
211
613
|
});
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
if (agent.skills?.length) {
|
|
230
|
-
for (const skill of agent.skills) {
|
|
231
|
-
const skillFrontmatter = this.formatFrontmatter({
|
|
232
|
-
description: `${agent.name} skill: ${skill.name}`,
|
|
233
|
-
alwaysApply: false,
|
|
234
|
-
globs: globs || void 0
|
|
235
|
-
});
|
|
236
|
-
outputs.push({
|
|
237
|
-
filePath: `.cursor/rules/${agent.id}-skills/${skill.id}.mdc`,
|
|
238
|
-
content: `${skillFrontmatter}
|
|
614
|
+
}
|
|
615
|
+
return outputs;
|
|
616
|
+
}
|
|
617
|
+
compileAllSkills(agents) {
|
|
618
|
+
const outputs = [];
|
|
619
|
+
for (const agent of agents) {
|
|
620
|
+
if (!agent.skills?.length) continue;
|
|
621
|
+
const globs = agent.globs?.length ? agent.globs.join(", ") : void 0;
|
|
622
|
+
for (const skill of agent.skills) {
|
|
623
|
+
const skillFrontmatter = this.formatFrontmatter({
|
|
624
|
+
description: `${agent.name} skill: ${skill.name}`,
|
|
625
|
+
alwaysApply: false,
|
|
626
|
+
globs: globs || void 0
|
|
627
|
+
});
|
|
628
|
+
outputs.push({
|
|
629
|
+
filePath: `.cursor/rules/${agent.id}-skills/${skill.id}.mdc`,
|
|
630
|
+
content: `${skillFrontmatter}
|
|
239
631
|
|
|
240
632
|
${skill.content}
|
|
241
633
|
`,
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
634
|
+
overwriteStrategy: "replace"
|
|
635
|
+
});
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
return outputs;
|
|
639
|
+
}
|
|
640
|
+
compileAllReferences(agents) {
|
|
641
|
+
const outputs = [];
|
|
642
|
+
for (const agent of agents) {
|
|
643
|
+
if (!agent.references?.length) continue;
|
|
644
|
+
const globs = agent.globs?.length ? agent.globs.join(", ") : void 0;
|
|
645
|
+
for (const ref of agent.references) {
|
|
646
|
+
const refFrontmatter = this.formatFrontmatter({
|
|
647
|
+
description: `${agent.name} reference: ${ref.title}`,
|
|
648
|
+
alwaysApply: false,
|
|
649
|
+
globs: globs || void 0
|
|
650
|
+
});
|
|
651
|
+
outputs.push({
|
|
652
|
+
filePath: `.cursor/rules/${agent.id}-refs/${ref.id}.mdc`,
|
|
653
|
+
content: `${refFrontmatter}
|
|
654
|
+
|
|
655
|
+
${ref.content}
|
|
656
|
+
`,
|
|
657
|
+
overwriteStrategy: "replace"
|
|
658
|
+
});
|
|
245
659
|
}
|
|
246
660
|
}
|
|
661
|
+
return outputs;
|
|
662
|
+
}
|
|
663
|
+
compileAllExamples(agents) {
|
|
664
|
+
const outputs = [];
|
|
665
|
+
for (const agent of agents) {
|
|
666
|
+
outputs.push(...this.compileExamples(
|
|
667
|
+
agent,
|
|
668
|
+
`.cursor/rules/${agent.id}-examples`,
|
|
669
|
+
".mdc"
|
|
670
|
+
));
|
|
671
|
+
}
|
|
672
|
+
return outputs;
|
|
673
|
+
}
|
|
674
|
+
compileAllOutputContracts(agents) {
|
|
675
|
+
const outputs = [];
|
|
676
|
+
for (const agent of agents) {
|
|
677
|
+
outputs.push(...this.compileOutputContracts(
|
|
678
|
+
agent,
|
|
679
|
+
`.cursor/rules/${agent.id}-contracts`,
|
|
680
|
+
".mdc"
|
|
681
|
+
));
|
|
682
|
+
}
|
|
683
|
+
return outputs;
|
|
684
|
+
}
|
|
685
|
+
compileAllScripts(agents) {
|
|
686
|
+
const outputs = [];
|
|
687
|
+
for (const agent of agents) {
|
|
688
|
+
outputs.push(...this.compileScriptFiles(
|
|
689
|
+
agent,
|
|
690
|
+
`.cursor/rules/${agent.id}-scripts`,
|
|
691
|
+
".mdc"
|
|
692
|
+
));
|
|
693
|
+
}
|
|
694
|
+
return outputs;
|
|
695
|
+
}
|
|
696
|
+
compileAllAssets(agents) {
|
|
697
|
+
const outputs = [];
|
|
698
|
+
for (const agent of agents) {
|
|
699
|
+
outputs.push(...this.compileAssetFiles(
|
|
700
|
+
agent,
|
|
701
|
+
`.cursor/rules/${agent.id}-assets`,
|
|
702
|
+
".mdc"
|
|
703
|
+
));
|
|
704
|
+
}
|
|
705
|
+
return outputs;
|
|
706
|
+
}
|
|
707
|
+
compilePluginBundle(agents, config, rootDir) {
|
|
708
|
+
const outputs = [];
|
|
709
|
+
const pluginId = toKebabCursorPluginId(config.projectName);
|
|
710
|
+
const firstLine = (text) => text.trim().split("\n")[0] ?? "";
|
|
711
|
+
outputs.push({
|
|
712
|
+
filePath: `${rootDir}/.cursor-plugin/plugin.json`,
|
|
713
|
+
content: JSON.stringify(
|
|
714
|
+
{
|
|
715
|
+
name: pluginId,
|
|
716
|
+
version: "0.1.0",
|
|
717
|
+
description: `Agent team pack for ${config.projectName} (generated by aigent-team)`,
|
|
718
|
+
keywords: ["aigent-team", "agents"],
|
|
719
|
+
author: { name: "aigent-team" }
|
|
720
|
+
},
|
|
721
|
+
null,
|
|
722
|
+
2
|
|
723
|
+
) + "\n",
|
|
724
|
+
overwriteStrategy: "replace"
|
|
725
|
+
});
|
|
247
726
|
const sharedKnowledge = agents.flatMap((a) => a.sharedKnowledge).filter((v, i, arr) => arr.indexOf(v) === i && v).join("\n\n---\n\n");
|
|
248
727
|
if (sharedKnowledge) {
|
|
249
728
|
const frontmatter = this.formatFrontmatter({
|
|
@@ -251,7 +730,7 @@ ${skill.content}
|
|
|
251
730
|
alwaysApply: true
|
|
252
731
|
});
|
|
253
732
|
outputs.push({
|
|
254
|
-
filePath:
|
|
733
|
+
filePath: `${rootDir}/rules/shared-conventions.mdc`,
|
|
255
734
|
content: `${frontmatter}
|
|
256
735
|
|
|
257
736
|
${sharedKnowledge}
|
|
@@ -259,6 +738,138 @@ ${sharedKnowledge}
|
|
|
259
738
|
overwriteStrategy: "replace"
|
|
260
739
|
});
|
|
261
740
|
}
|
|
741
|
+
for (const agent of agents) {
|
|
742
|
+
const globs = agent.globs?.length ? agent.globs.join(", ") : void 0;
|
|
743
|
+
const frontmatterData = {
|
|
744
|
+
description: firstLine(agent.description),
|
|
745
|
+
alwaysApply: !globs
|
|
746
|
+
};
|
|
747
|
+
if (globs) frontmatterData.globs = globs;
|
|
748
|
+
const frontmatter = this.formatFrontmatter(frontmatterData);
|
|
749
|
+
const body = assembleSkillIndex(agent);
|
|
750
|
+
outputs.push({
|
|
751
|
+
filePath: `${rootDir}/agents/${agent.id}-agent.mdc`,
|
|
752
|
+
content: `${frontmatter}
|
|
753
|
+
|
|
754
|
+
${body}
|
|
755
|
+
`,
|
|
756
|
+
overwriteStrategy: "replace"
|
|
757
|
+
});
|
|
758
|
+
}
|
|
759
|
+
for (const agent of agents) {
|
|
760
|
+
if (!agent.skills?.length) continue;
|
|
761
|
+
for (const skill of agent.skills) {
|
|
762
|
+
const skillId = `${agent.id}-${skill.id}`;
|
|
763
|
+
const descSource = skill.description?.trim() || skill.name?.trim() || skill.trigger?.trim() || `Procedure for ${agent.name}`;
|
|
764
|
+
const skillFrontmatter = this.formatFrontmatter({
|
|
765
|
+
name: skillId,
|
|
766
|
+
description: firstLine(descSource)
|
|
767
|
+
});
|
|
768
|
+
outputs.push({
|
|
769
|
+
filePath: `${rootDir}/skills/${skillId}/SKILL.md`,
|
|
770
|
+
content: `${skillFrontmatter}
|
|
771
|
+
|
|
772
|
+
${assembleSkill(skill)}
|
|
773
|
+
`,
|
|
774
|
+
overwriteStrategy: "replace"
|
|
775
|
+
});
|
|
776
|
+
}
|
|
777
|
+
}
|
|
778
|
+
for (const agent of agents) {
|
|
779
|
+
if (!agent.references?.length) continue;
|
|
780
|
+
const globs = agent.globs?.length ? agent.globs.join(", ") : void 0;
|
|
781
|
+
for (const ref of agent.references) {
|
|
782
|
+
const refFrontmatter = this.formatFrontmatter({
|
|
783
|
+
description: `${agent.name} reference: ${ref.title}`,
|
|
784
|
+
alwaysApply: false,
|
|
785
|
+
globs: globs || void 0
|
|
786
|
+
});
|
|
787
|
+
outputs.push({
|
|
788
|
+
filePath: `${rootDir}/kb/${agent.id}-refs/${ref.id}.mdc`,
|
|
789
|
+
content: `${refFrontmatter}
|
|
790
|
+
|
|
791
|
+
${assembleReference(ref)}
|
|
792
|
+
`,
|
|
793
|
+
overwriteStrategy: "replace"
|
|
794
|
+
});
|
|
795
|
+
}
|
|
796
|
+
}
|
|
797
|
+
for (const agent of agents) {
|
|
798
|
+
if (!agent.examples?.length) continue;
|
|
799
|
+
const globs = agent.globs?.length ? agent.globs.join(", ") : void 0;
|
|
800
|
+
for (const example of agent.examples) {
|
|
801
|
+
const exFrontmatter = this.formatFrontmatter({
|
|
802
|
+
description: `${agent.name} example: ${example.name}`,
|
|
803
|
+
alwaysApply: false,
|
|
804
|
+
globs: globs || void 0
|
|
805
|
+
});
|
|
806
|
+
outputs.push({
|
|
807
|
+
filePath: `${rootDir}/examples/${agent.id}/${example.id}.mdc`,
|
|
808
|
+
content: `${exFrontmatter}
|
|
809
|
+
|
|
810
|
+
${assembleExample(example)}
|
|
811
|
+
`,
|
|
812
|
+
overwriteStrategy: "replace"
|
|
813
|
+
});
|
|
814
|
+
}
|
|
815
|
+
}
|
|
816
|
+
for (const agent of agents) {
|
|
817
|
+
if (!agent.outputContracts?.length) continue;
|
|
818
|
+
const globs = agent.globs?.length ? agent.globs.join(", ") : void 0;
|
|
819
|
+
for (const contract of agent.outputContracts) {
|
|
820
|
+
const cFrontmatter = this.formatFrontmatter({
|
|
821
|
+
description: `${agent.name} contract: ${contract.name}`,
|
|
822
|
+
alwaysApply: false,
|
|
823
|
+
globs: globs || void 0
|
|
824
|
+
});
|
|
825
|
+
outputs.push({
|
|
826
|
+
filePath: `${rootDir}/contracts/${agent.id}/${contract.id}.mdc`,
|
|
827
|
+
content: `${cFrontmatter}
|
|
828
|
+
|
|
829
|
+
${assembleOutputContract(contract)}
|
|
830
|
+
`,
|
|
831
|
+
overwriteStrategy: "replace"
|
|
832
|
+
});
|
|
833
|
+
}
|
|
834
|
+
}
|
|
835
|
+
for (const agent of agents) {
|
|
836
|
+
if (!agent.scripts?.length) continue;
|
|
837
|
+
const globs = agent.globs?.length ? agent.globs.join(", ") : void 0;
|
|
838
|
+
for (const script of agent.scripts) {
|
|
839
|
+
const sFrontmatter = this.formatFrontmatter({
|
|
840
|
+
description: `${agent.name} script: ${script.name}`,
|
|
841
|
+
alwaysApply: false,
|
|
842
|
+
globs: globs || void 0
|
|
843
|
+
});
|
|
844
|
+
outputs.push({
|
|
845
|
+
filePath: `${rootDir}/scripts/${agent.id}/${script.id}.mdc`,
|
|
846
|
+
content: `${sFrontmatter}
|
|
847
|
+
|
|
848
|
+
${assembleScript(script)}
|
|
849
|
+
`,
|
|
850
|
+
overwriteStrategy: "replace"
|
|
851
|
+
});
|
|
852
|
+
}
|
|
853
|
+
}
|
|
854
|
+
for (const agent of agents) {
|
|
855
|
+
if (!agent.assets?.length) continue;
|
|
856
|
+
const globs = agent.globs?.length ? agent.globs.join(", ") : void 0;
|
|
857
|
+
for (const asset of agent.assets) {
|
|
858
|
+
const aFrontmatter = this.formatFrontmatter({
|
|
859
|
+
description: `${agent.name} asset: ${asset.name}`,
|
|
860
|
+
alwaysApply: false,
|
|
861
|
+
globs: globs || void 0
|
|
862
|
+
});
|
|
863
|
+
outputs.push({
|
|
864
|
+
filePath: `${rootDir}/assets/${agent.id}/${asset.id}.mdc`,
|
|
865
|
+
content: `${aFrontmatter}
|
|
866
|
+
|
|
867
|
+
${assembleAsset(asset)}
|
|
868
|
+
`,
|
|
869
|
+
overwriteStrategy: "replace"
|
|
870
|
+
});
|
|
871
|
+
}
|
|
872
|
+
}
|
|
262
873
|
return outputs;
|
|
263
874
|
}
|
|
264
875
|
validate(outputs) {
|
|
@@ -280,7 +891,9 @@ ${sharedKnowledge}
|
|
|
280
891
|
var CodexCompiler = class extends BaseCompiler {
|
|
281
892
|
platform = "codex";
|
|
282
893
|
compile(agents, config) {
|
|
283
|
-
|
|
894
|
+
return this.compileWithScope(agents, config, ["all"]);
|
|
895
|
+
}
|
|
896
|
+
compileHubFile(agents, _config) {
|
|
284
897
|
const sections = agents.map((agent) => {
|
|
285
898
|
const body = assembleSkillIndex(agent);
|
|
286
899
|
return `## ${agent.name} (${agent.id})
|
|
@@ -299,11 +912,14 @@ ${body}`;
|
|
|
299
912
|
|
|
300
913
|
${sharedKnowledge}` : ""
|
|
301
914
|
].filter(Boolean).join("\n\n");
|
|
302
|
-
|
|
915
|
+
return [{
|
|
303
916
|
filePath: "AGENTS.md",
|
|
304
917
|
content: agentsMd + "\n",
|
|
305
918
|
overwriteStrategy: "replace"
|
|
306
|
-
}
|
|
919
|
+
}];
|
|
920
|
+
}
|
|
921
|
+
compileAgentIndexes(agents, _config) {
|
|
922
|
+
const outputs = [];
|
|
307
923
|
for (const agent of agents) {
|
|
308
924
|
const frontmatter = this.formatFrontmatter({
|
|
309
925
|
nickname_candidates: [agent.id, agent.role],
|
|
@@ -319,16 +935,168 @@ ${body}
|
|
|
319
935
|
content,
|
|
320
936
|
overwriteStrategy: "replace"
|
|
321
937
|
});
|
|
322
|
-
|
|
938
|
+
}
|
|
939
|
+
return outputs;
|
|
940
|
+
}
|
|
941
|
+
compileAllSkills(agents) {
|
|
942
|
+
const outputs = [];
|
|
943
|
+
for (const agent of agents) {
|
|
944
|
+
outputs.push(...this.compileSkills(
|
|
945
|
+
agent,
|
|
946
|
+
`.codex/agents/${agent.id}-agent/skills`
|
|
947
|
+
));
|
|
948
|
+
}
|
|
949
|
+
return outputs;
|
|
950
|
+
}
|
|
951
|
+
compileAllReferences(agents) {
|
|
952
|
+
const outputs = [];
|
|
953
|
+
for (const agent of agents) {
|
|
954
|
+
outputs.push(...this.compileReferences(
|
|
323
955
|
agent,
|
|
324
956
|
`.codex/agents/${agent.id}-agent/references`
|
|
325
|
-
);
|
|
326
|
-
|
|
327
|
-
|
|
957
|
+
));
|
|
958
|
+
}
|
|
959
|
+
return outputs;
|
|
960
|
+
}
|
|
961
|
+
compileAllExamples(agents) {
|
|
962
|
+
const outputs = [];
|
|
963
|
+
for (const agent of agents) {
|
|
964
|
+
outputs.push(...this.compileExamples(
|
|
328
965
|
agent,
|
|
329
|
-
`.codex/agents/${agent.id}-agent/
|
|
330
|
-
);
|
|
331
|
-
|
|
966
|
+
`.codex/agents/${agent.id}-agent/examples`
|
|
967
|
+
));
|
|
968
|
+
}
|
|
969
|
+
return outputs;
|
|
970
|
+
}
|
|
971
|
+
compileAllOutputContracts(agents) {
|
|
972
|
+
const outputs = [];
|
|
973
|
+
for (const agent of agents) {
|
|
974
|
+
outputs.push(...this.compileOutputContracts(
|
|
975
|
+
agent,
|
|
976
|
+
`.codex/agents/${agent.id}-agent/contracts`
|
|
977
|
+
));
|
|
978
|
+
}
|
|
979
|
+
return outputs;
|
|
980
|
+
}
|
|
981
|
+
compileAllScripts(agents) {
|
|
982
|
+
const outputs = [];
|
|
983
|
+
for (const agent of agents) {
|
|
984
|
+
outputs.push(...this.compileScriptFiles(
|
|
985
|
+
agent,
|
|
986
|
+
`.codex/agents/${agent.id}-agent/scripts`
|
|
987
|
+
));
|
|
988
|
+
}
|
|
989
|
+
return outputs;
|
|
990
|
+
}
|
|
991
|
+
compileAllAssets(agents) {
|
|
992
|
+
const outputs = [];
|
|
993
|
+
for (const agent of agents) {
|
|
994
|
+
outputs.push(...this.compileAssetFiles(
|
|
995
|
+
agent,
|
|
996
|
+
`.codex/agents/${agent.id}-agent/assets`
|
|
997
|
+
));
|
|
998
|
+
}
|
|
999
|
+
return outputs;
|
|
1000
|
+
}
|
|
1001
|
+
compilePluginBundle(agents, _config, rootDir) {
|
|
1002
|
+
const outputs = [];
|
|
1003
|
+
const sections = agents.map((agent) => {
|
|
1004
|
+
const body = assembleSkillIndex(agent);
|
|
1005
|
+
return `## ${agent.name} (${agent.id})
|
|
1006
|
+
|
|
1007
|
+
${body}`;
|
|
1008
|
+
});
|
|
1009
|
+
const sharedKnowledge = agents.flatMap((a) => a.sharedKnowledge).filter((v, i, arr) => arr.indexOf(v) === i && v).join("\n\n");
|
|
1010
|
+
const agentsMd = [
|
|
1011
|
+
`# Project Agents`,
|
|
1012
|
+
``,
|
|
1013
|
+
`This project uses specialized AI agents for different team roles.`,
|
|
1014
|
+
``,
|
|
1015
|
+
...sections,
|
|
1016
|
+
``,
|
|
1017
|
+
sharedKnowledge ? `## Shared Knowledge
|
|
1018
|
+
|
|
1019
|
+
${sharedKnowledge}` : ""
|
|
1020
|
+
].filter(Boolean).join("\n\n");
|
|
1021
|
+
outputs.push({
|
|
1022
|
+
filePath: `${rootDir}/rules/AGENTS.md`,
|
|
1023
|
+
content: agentsMd + "\n",
|
|
1024
|
+
overwriteStrategy: "replace"
|
|
1025
|
+
});
|
|
1026
|
+
for (const agent of agents) {
|
|
1027
|
+
const frontmatter = this.formatFrontmatter({
|
|
1028
|
+
nickname_candidates: [agent.id, agent.role],
|
|
1029
|
+
model: "inherit"
|
|
1030
|
+
});
|
|
1031
|
+
const body = assembleSkillIndex(agent);
|
|
1032
|
+
outputs.push({
|
|
1033
|
+
filePath: `${rootDir}/agents/${agent.id}-agent.md`,
|
|
1034
|
+
content: `${frontmatter}
|
|
1035
|
+
|
|
1036
|
+
${body}
|
|
1037
|
+
`,
|
|
1038
|
+
overwriteStrategy: "replace"
|
|
1039
|
+
});
|
|
1040
|
+
}
|
|
1041
|
+
for (const agent of agents) {
|
|
1042
|
+
if (!agent.skills?.length) continue;
|
|
1043
|
+
for (const skill of agent.skills) {
|
|
1044
|
+
outputs.push({
|
|
1045
|
+
filePath: `${rootDir}/skills/${agent.id}/${skill.id}.md`,
|
|
1046
|
+
content: assembleSkill(skill) + "\n",
|
|
1047
|
+
overwriteStrategy: "replace"
|
|
1048
|
+
});
|
|
1049
|
+
}
|
|
1050
|
+
}
|
|
1051
|
+
for (const agent of agents) {
|
|
1052
|
+
if (!agent.references?.length) continue;
|
|
1053
|
+
for (const ref of agent.references) {
|
|
1054
|
+
outputs.push({
|
|
1055
|
+
filePath: `${rootDir}/kb/${agent.id}/${ref.id}.md`,
|
|
1056
|
+
content: assembleReference(ref) + "\n",
|
|
1057
|
+
overwriteStrategy: "replace"
|
|
1058
|
+
});
|
|
1059
|
+
}
|
|
1060
|
+
}
|
|
1061
|
+
for (const agent of agents) {
|
|
1062
|
+
if (!agent.examples?.length) continue;
|
|
1063
|
+
for (const example of agent.examples) {
|
|
1064
|
+
outputs.push({
|
|
1065
|
+
filePath: `${rootDir}/examples/${agent.id}/${example.id}.md`,
|
|
1066
|
+
content: assembleExample(example) + "\n",
|
|
1067
|
+
overwriteStrategy: "replace"
|
|
1068
|
+
});
|
|
1069
|
+
}
|
|
1070
|
+
}
|
|
1071
|
+
for (const agent of agents) {
|
|
1072
|
+
if (!agent.outputContracts?.length) continue;
|
|
1073
|
+
for (const contract of agent.outputContracts) {
|
|
1074
|
+
outputs.push({
|
|
1075
|
+
filePath: `${rootDir}/contracts/${agent.id}/${contract.id}.md`,
|
|
1076
|
+
content: assembleOutputContract(contract) + "\n",
|
|
1077
|
+
overwriteStrategy: "replace"
|
|
1078
|
+
});
|
|
1079
|
+
}
|
|
1080
|
+
}
|
|
1081
|
+
for (const agent of agents) {
|
|
1082
|
+
if (!agent.scripts?.length) continue;
|
|
1083
|
+
for (const script of agent.scripts) {
|
|
1084
|
+
outputs.push({
|
|
1085
|
+
filePath: `${rootDir}/scripts/${agent.id}/${script.id}.md`,
|
|
1086
|
+
content: assembleScript(script) + "\n",
|
|
1087
|
+
overwriteStrategy: "replace"
|
|
1088
|
+
});
|
|
1089
|
+
}
|
|
1090
|
+
}
|
|
1091
|
+
for (const agent of agents) {
|
|
1092
|
+
if (!agent.assets?.length) continue;
|
|
1093
|
+
for (const asset of agent.assets) {
|
|
1094
|
+
outputs.push({
|
|
1095
|
+
filePath: `${rootDir}/assets/${agent.id}/${asset.id}.md`,
|
|
1096
|
+
content: assembleAsset(asset) + "\n",
|
|
1097
|
+
overwriteStrategy: "replace"
|
|
1098
|
+
});
|
|
1099
|
+
}
|
|
332
1100
|
}
|
|
333
1101
|
return outputs;
|
|
334
1102
|
}
|
|
@@ -355,7 +1123,9 @@ var TOOL_MAP = {
|
|
|
355
1123
|
var AntigravityCompiler = class extends BaseCompiler {
|
|
356
1124
|
platform = "antigravity";
|
|
357
1125
|
compile(agents, config) {
|
|
358
|
-
|
|
1126
|
+
return this.compileWithScope(agents, config, ["all"]);
|
|
1127
|
+
}
|
|
1128
|
+
compileHubFile(agents, _config) {
|
|
359
1129
|
const agentList = agents.map((a) => `- **${a.name}** (\`${a.id}\`): ${a.description.trim().split("\n")[0]}`).join("\n");
|
|
360
1130
|
const geminiMd = [
|
|
361
1131
|
`# Antigravity Configuration`,
|
|
@@ -368,11 +1138,14 @@ var AntigravityCompiler = class extends BaseCompiler {
|
|
|
368
1138
|
`Use the appropriate agent skill for team-specific tasks.`,
|
|
369
1139
|
``
|
|
370
1140
|
].join("\n");
|
|
371
|
-
|
|
1141
|
+
return [{
|
|
372
1142
|
filePath: "GEMINI.md",
|
|
373
1143
|
content: geminiMd,
|
|
374
1144
|
overwriteStrategy: "replace"
|
|
375
|
-
}
|
|
1145
|
+
}];
|
|
1146
|
+
}
|
|
1147
|
+
compileAgentIndexes(agents, _config) {
|
|
1148
|
+
const outputs = [];
|
|
376
1149
|
for (const agent of agents) {
|
|
377
1150
|
const allowedTools = agent.tools.allowed.map((t) => TOOL_MAP[t] || t.toLowerCase()).filter((v, i, arr) => arr.indexOf(v) === i);
|
|
378
1151
|
const frontmatter = this.formatFrontmatter({
|
|
@@ -390,137 +1163,346 @@ ${body}
|
|
|
390
1163
|
content,
|
|
391
1164
|
overwriteStrategy: "replace"
|
|
392
1165
|
});
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
1166
|
+
}
|
|
1167
|
+
return outputs;
|
|
1168
|
+
}
|
|
1169
|
+
compileAllSkills(agents) {
|
|
1170
|
+
const outputs = [];
|
|
1171
|
+
for (const agent of agents) {
|
|
1172
|
+
outputs.push(...this.compileSkills(
|
|
399
1173
|
agent,
|
|
400
1174
|
`.agents/skills/${agent.id}-agent/skills`
|
|
401
|
-
);
|
|
402
|
-
outputs.push(...skills);
|
|
1175
|
+
));
|
|
403
1176
|
}
|
|
404
1177
|
return outputs;
|
|
405
1178
|
}
|
|
406
|
-
|
|
407
|
-
const
|
|
408
|
-
const
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
if (nameMatch && nameMatch[1] !== dirName) {
|
|
414
|
-
errors.push(
|
|
415
|
-
`${output.filePath}: SKILL.md name "${nameMatch[1]}" does not match directory "${dirName}"`
|
|
416
|
-
);
|
|
417
|
-
}
|
|
418
|
-
}
|
|
1179
|
+
compileAllReferences(agents) {
|
|
1180
|
+
const outputs = [];
|
|
1181
|
+
for (const agent of agents) {
|
|
1182
|
+
outputs.push(...this.compileReferences(
|
|
1183
|
+
agent,
|
|
1184
|
+
`.agents/skills/${agent.id}-agent/references`
|
|
1185
|
+
));
|
|
419
1186
|
}
|
|
420
|
-
return
|
|
421
|
-
}
|
|
422
|
-
};
|
|
423
|
-
|
|
424
|
-
// src/compilers/index.ts
|
|
425
|
-
var compilers = {
|
|
426
|
-
"claude-code": () => new ClaudeCodeCompiler(),
|
|
427
|
-
cursor: () => new CursorCompiler(),
|
|
428
|
-
codex: () => new CodexCompiler(),
|
|
429
|
-
antigravity: () => new AntigravityCompiler()
|
|
430
|
-
};
|
|
431
|
-
function getAllCompilers(platforms) {
|
|
432
|
-
return platforms.map((p) => compilers[p]());
|
|
433
|
-
}
|
|
434
|
-
|
|
435
|
-
// src/cli/generate.ts
|
|
436
|
-
function writeOutput(output, cwd) {
|
|
437
|
-
const fullPath = resolve2(cwd, output.filePath);
|
|
438
|
-
const dir = dirname(fullPath);
|
|
439
|
-
if (output.overwriteStrategy === "skip-if-exists" && existsSync2(fullPath)) {
|
|
440
|
-
return false;
|
|
1187
|
+
return outputs;
|
|
441
1188
|
}
|
|
442
|
-
|
|
443
|
-
const
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
1189
|
+
compileAllExamples(agents) {
|
|
1190
|
+
const outputs = [];
|
|
1191
|
+
for (const agent of agents) {
|
|
1192
|
+
outputs.push(...this.compileExamples(
|
|
1193
|
+
agent,
|
|
1194
|
+
`.agents/skills/${agent.id}-agent/examples`
|
|
1195
|
+
));
|
|
447
1196
|
}
|
|
448
|
-
return
|
|
1197
|
+
return outputs;
|
|
449
1198
|
}
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
const
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
1199
|
+
compileAllOutputContracts(agents) {
|
|
1200
|
+
const outputs = [];
|
|
1201
|
+
for (const agent of agents) {
|
|
1202
|
+
outputs.push(...this.compileOutputContracts(
|
|
1203
|
+
agent,
|
|
1204
|
+
`.agents/skills/${agent.id}-agent/contracts`
|
|
1205
|
+
));
|
|
1206
|
+
}
|
|
1207
|
+
return outputs;
|
|
1208
|
+
}
|
|
1209
|
+
compileAllScripts(agents) {
|
|
1210
|
+
const outputs = [];
|
|
1211
|
+
for (const agent of agents) {
|
|
1212
|
+
outputs.push(...this.compileScriptFiles(
|
|
1213
|
+
agent,
|
|
1214
|
+
`.agents/skills/${agent.id}-agent/scripts`
|
|
1215
|
+
));
|
|
1216
|
+
}
|
|
1217
|
+
return outputs;
|
|
1218
|
+
}
|
|
1219
|
+
compileAllAssets(agents) {
|
|
1220
|
+
const outputs = [];
|
|
1221
|
+
for (const agent of agents) {
|
|
1222
|
+
outputs.push(...this.compileAssetFiles(
|
|
1223
|
+
agent,
|
|
1224
|
+
`.agents/skills/${agent.id}-agent/assets`
|
|
1225
|
+
));
|
|
1226
|
+
}
|
|
1227
|
+
return outputs;
|
|
1228
|
+
}
|
|
1229
|
+
compilePluginBundle(agents, _config, rootDir) {
|
|
1230
|
+
const outputs = [];
|
|
1231
|
+
const agentList = agents.map((a) => `- **${a.name}** (\`${a.id}\`): ${a.description.trim().split("\n")[0]}`).join("\n");
|
|
1232
|
+
outputs.push({
|
|
1233
|
+
filePath: `${rootDir}/rules/GEMINI.md`,
|
|
1234
|
+
content: [
|
|
1235
|
+
`# Antigravity Configuration`,
|
|
1236
|
+
``,
|
|
1237
|
+
`## Available Agents`,
|
|
1238
|
+
``,
|
|
1239
|
+
agentList,
|
|
1240
|
+
``,
|
|
1241
|
+
`Agents are defined in the agents/ directory.`,
|
|
1242
|
+
`Use the appropriate agent for team-specific tasks.`,
|
|
1243
|
+
``
|
|
1244
|
+
].join("\n"),
|
|
1245
|
+
overwriteStrategy: "replace"
|
|
1246
|
+
});
|
|
1247
|
+
for (const agent of agents) {
|
|
1248
|
+
const allowedTools = agent.tools.allowed.map((t) => TOOL_MAP[t] || t.toLowerCase()).filter((v, i, arr) => arr.indexOf(v) === i);
|
|
1249
|
+
const frontmatter = this.formatFrontmatter({
|
|
1250
|
+
name: `${agent.id}-agent`,
|
|
1251
|
+
description: agent.description.trim().split("\n")[0],
|
|
1252
|
+
"allowed-tools": allowedTools
|
|
1253
|
+
});
|
|
1254
|
+
const body = assembleSkillIndex(agent);
|
|
1255
|
+
outputs.push({
|
|
1256
|
+
filePath: `${rootDir}/agents/${agent.id}-agent/SKILL.md`,
|
|
1257
|
+
content: `${frontmatter}
|
|
1258
|
+
|
|
1259
|
+
${body}
|
|
1260
|
+
`,
|
|
1261
|
+
overwriteStrategy: "replace"
|
|
1262
|
+
});
|
|
1263
|
+
}
|
|
1264
|
+
for (const agent of agents) {
|
|
1265
|
+
if (!agent.skills?.length) continue;
|
|
1266
|
+
for (const skill of agent.skills) {
|
|
1267
|
+
outputs.push({
|
|
1268
|
+
filePath: `${rootDir}/skills/${agent.id}/${skill.id}.md`,
|
|
1269
|
+
content: assembleSkill(skill) + "\n",
|
|
1270
|
+
overwriteStrategy: "replace"
|
|
1271
|
+
});
|
|
469
1272
|
}
|
|
470
|
-
continue;
|
|
471
1273
|
}
|
|
472
|
-
for (const
|
|
473
|
-
|
|
474
|
-
|
|
1274
|
+
for (const agent of agents) {
|
|
1275
|
+
if (!agent.references?.length) continue;
|
|
1276
|
+
for (const ref of agent.references) {
|
|
1277
|
+
outputs.push({
|
|
1278
|
+
filePath: `${rootDir}/kb/${agent.id}/${ref.id}.md`,
|
|
1279
|
+
content: assembleReference(ref) + "\n",
|
|
1280
|
+
overwriteStrategy: "replace"
|
|
1281
|
+
});
|
|
1282
|
+
}
|
|
475
1283
|
}
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
1284
|
+
for (const agent of agents) {
|
|
1285
|
+
if (!agent.examples?.length) continue;
|
|
1286
|
+
for (const example of agent.examples) {
|
|
1287
|
+
outputs.push({
|
|
1288
|
+
filePath: `${rootDir}/examples/${agent.id}/${example.id}.md`,
|
|
1289
|
+
content: assembleExample(example) + "\n",
|
|
1290
|
+
overwriteStrategy: "replace"
|
|
1291
|
+
});
|
|
481
1292
|
}
|
|
482
1293
|
}
|
|
483
|
-
|
|
484
|
-
|
|
1294
|
+
for (const agent of agents) {
|
|
1295
|
+
if (!agent.outputContracts?.length) continue;
|
|
1296
|
+
for (const contract of agent.outputContracts) {
|
|
1297
|
+
outputs.push({
|
|
1298
|
+
filePath: `${rootDir}/contracts/${agent.id}/${contract.id}.md`,
|
|
1299
|
+
content: assembleOutputContract(contract) + "\n",
|
|
1300
|
+
overwriteStrategy: "replace"
|
|
1301
|
+
});
|
|
1302
|
+
}
|
|
1303
|
+
}
|
|
1304
|
+
for (const agent of agents) {
|
|
1305
|
+
if (!agent.scripts?.length) continue;
|
|
1306
|
+
for (const script of agent.scripts) {
|
|
1307
|
+
outputs.push({
|
|
1308
|
+
filePath: `${rootDir}/scripts/${agent.id}/${script.id}.md`,
|
|
1309
|
+
content: assembleScript(script) + "\n",
|
|
1310
|
+
overwriteStrategy: "replace"
|
|
1311
|
+
});
|
|
1312
|
+
}
|
|
1313
|
+
}
|
|
1314
|
+
for (const agent of agents) {
|
|
1315
|
+
if (!agent.assets?.length) continue;
|
|
1316
|
+
for (const asset of agent.assets) {
|
|
1317
|
+
outputs.push({
|
|
1318
|
+
filePath: `${rootDir}/assets/${agent.id}/${asset.id}.md`,
|
|
1319
|
+
content: assembleAsset(asset) + "\n",
|
|
1320
|
+
overwriteStrategy: "replace"
|
|
1321
|
+
});
|
|
1322
|
+
}
|
|
1323
|
+
}
|
|
1324
|
+
const sharedKnowledge = agents.flatMap((a) => a.sharedKnowledge).filter((v, i, arr) => arr.indexOf(v) === i && v);
|
|
1325
|
+
for (let i = 0; i < sharedKnowledge.length; i++) {
|
|
1326
|
+
outputs.push({
|
|
1327
|
+
filePath: `${rootDir}/kb/shared/knowledge-${i + 1}.md`,
|
|
1328
|
+
content: sharedKnowledge[i] + "\n",
|
|
1329
|
+
overwriteStrategy: "replace"
|
|
1330
|
+
});
|
|
1331
|
+
}
|
|
1332
|
+
return outputs;
|
|
485
1333
|
}
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
1334
|
+
validate(outputs) {
|
|
1335
|
+
const errors = [];
|
|
1336
|
+
const warnings = [];
|
|
1337
|
+
for (const output of outputs) {
|
|
1338
|
+
if (output.filePath.includes("SKILL.md")) {
|
|
1339
|
+
const dirName = output.filePath.split("/").slice(-2, -1)[0];
|
|
1340
|
+
const nameMatch = output.content.match(/^name:\s*"?(.+?)"?\s*$/m);
|
|
1341
|
+
if (nameMatch && nameMatch[1] !== dirName) {
|
|
1342
|
+
errors.push(
|
|
1343
|
+
`${output.filePath}: SKILL.md name "${nameMatch[1]}" does not match directory "${dirName}"`
|
|
1344
|
+
);
|
|
1345
|
+
}
|
|
1346
|
+
}
|
|
1347
|
+
}
|
|
1348
|
+
return { valid: errors.length === 0, errors, warnings };
|
|
490
1349
|
}
|
|
1350
|
+
};
|
|
1351
|
+
|
|
1352
|
+
// src/compilers/index.ts
|
|
1353
|
+
var compilers = {
|
|
1354
|
+
"claude-code": () => new ClaudeCodeCompiler(),
|
|
1355
|
+
cursor: () => new CursorCompiler(),
|
|
1356
|
+
codex: () => new CodexCompiler(),
|
|
1357
|
+
antigravity: () => new AntigravityCompiler()
|
|
1358
|
+
};
|
|
1359
|
+
function getCompiler(platform) {
|
|
1360
|
+
return compilers[platform]();
|
|
1361
|
+
}
|
|
1362
|
+
function getAllCompilers(platforms) {
|
|
1363
|
+
return platforms.map((p) => compilers[p]());
|
|
491
1364
|
}
|
|
492
1365
|
|
|
493
|
-
// src/
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
const
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
1366
|
+
// src/compilers/plugin.compiler.ts
|
|
1367
|
+
var PluginCompiler = class {
|
|
1368
|
+
compilePlugin(agents, config, pluginDir = ".aigent-team-plugin") {
|
|
1369
|
+
const outputs = [];
|
|
1370
|
+
const bundles = [];
|
|
1371
|
+
for (const platform of config.platforms) {
|
|
1372
|
+
const bundleDir = PLUGIN_BUNDLE_DIRS[platform];
|
|
1373
|
+
const rootDir = `${pluginDir}/${bundleDir}`;
|
|
1374
|
+
const compiler = getCompiler(platform);
|
|
1375
|
+
const bundleOutputs = compiler.compilePluginBundle(agents, config, rootDir);
|
|
1376
|
+
outputs.push(...bundleOutputs);
|
|
1377
|
+
bundles.push({
|
|
1378
|
+
platform,
|
|
1379
|
+
directory: bundleDir,
|
|
1380
|
+
artifacts: compiler.countArtifacts(bundleOutputs, rootDir)
|
|
1381
|
+
});
|
|
1382
|
+
}
|
|
1383
|
+
const agentsMeta = agents.map((a) => ({
|
|
1384
|
+
id: a.id,
|
|
1385
|
+
name: a.name,
|
|
1386
|
+
description: a.description,
|
|
1387
|
+
role: a.role,
|
|
1388
|
+
tools: { allowed: [...a.tools.allowed], ...a.tools.denied ? { denied: [...a.tools.denied] } : {} },
|
|
1389
|
+
...a.globs?.length ? { globs: [...a.globs] } : {}
|
|
1390
|
+
}));
|
|
1391
|
+
const manifest = {
|
|
1392
|
+
name: config.projectName,
|
|
1393
|
+
version: "0.1.0",
|
|
1394
|
+
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1395
|
+
generator: "aigent-team",
|
|
1396
|
+
projectName: config.projectName,
|
|
1397
|
+
roles: [...config.teams],
|
|
1398
|
+
platforms: [...config.platforms],
|
|
1399
|
+
agents: agentsMeta,
|
|
1400
|
+
files: {
|
|
1401
|
+
agents: agents.length,
|
|
1402
|
+
skills: agents.reduce((sum, a) => sum + a.skills.length, 0),
|
|
1403
|
+
references: agents.reduce((sum, a) => sum + a.references.length, 0),
|
|
1404
|
+
examples: agents.reduce((sum, a) => sum + (a.examples?.length ?? 0), 0),
|
|
1405
|
+
outputContracts: agents.reduce((sum, a) => sum + (a.outputContracts?.length ?? 0), 0),
|
|
1406
|
+
scripts: agents.reduce((sum, a) => sum + (a.scripts?.length ?? 0), 0),
|
|
1407
|
+
assets: agents.reduce((sum, a) => sum + (a.assets?.length ?? 0), 0)
|
|
1408
|
+
},
|
|
1409
|
+
bundles
|
|
1410
|
+
};
|
|
1411
|
+
const governanceEntries = [];
|
|
1412
|
+
for (const agent of agents) {
|
|
1413
|
+
for (const skill of agent.skills) {
|
|
1414
|
+
if (skill.governance) {
|
|
1415
|
+
governanceEntries.push({
|
|
1416
|
+
skillId: skill.id,
|
|
1417
|
+
agentId: agent.id,
|
|
1418
|
+
name: skill.name,
|
|
1419
|
+
governance: skill.governance
|
|
1420
|
+
});
|
|
1421
|
+
}
|
|
503
1422
|
}
|
|
504
|
-
]);
|
|
505
|
-
if (!overwrite) {
|
|
506
|
-
console.log(chalk2.yellow("Aborted."));
|
|
507
|
-
return;
|
|
508
1423
|
}
|
|
1424
|
+
if (governanceEntries.length) {
|
|
1425
|
+
manifest.governance = governanceEntries;
|
|
1426
|
+
}
|
|
1427
|
+
outputs.push({
|
|
1428
|
+
filePath: `${pluginDir}/manifest.json`,
|
|
1429
|
+
content: JSON.stringify(manifest, null, 2) + "\n",
|
|
1430
|
+
overwriteStrategy: "replace"
|
|
1431
|
+
});
|
|
1432
|
+
return outputs;
|
|
509
1433
|
}
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
1434
|
+
};
|
|
1435
|
+
|
|
1436
|
+
// src/cli/generate.ts
|
|
1437
|
+
function writeOutput(output, cwd) {
|
|
1438
|
+
const fullPath = resolve3(cwd, output.filePath);
|
|
1439
|
+
const dir = dirname(fullPath);
|
|
1440
|
+
if (output.overwriteStrategy === "skip-if-exists" && existsSync2(fullPath)) {
|
|
1441
|
+
return false;
|
|
517
1442
|
}
|
|
518
|
-
|
|
1443
|
+
if (output.overwriteStrategy === "merge" && existsSync2(fullPath)) {
|
|
1444
|
+
const existing = readFileSync(fullPath, "utf-8");
|
|
1445
|
+
if (!existing.includes("## Agent Team")) {
|
|
1446
|
+
writeFileSync2(fullPath, existing + "\n" + output.content);
|
|
1447
|
+
return true;
|
|
1448
|
+
}
|
|
1449
|
+
return false;
|
|
1450
|
+
}
|
|
1451
|
+
mkdirSync2(dir, { recursive: true });
|
|
1452
|
+
writeFileSync2(fullPath, output.content);
|
|
1453
|
+
return true;
|
|
1454
|
+
}
|
|
1455
|
+
function writeOutputs(outputs, cwd, label) {
|
|
1456
|
+
let written = 0;
|
|
1457
|
+
for (const output of outputs) {
|
|
1458
|
+
if (writeOutput(output, cwd)) {
|
|
1459
|
+
written++;
|
|
1460
|
+
console.log(chalk2.dim(` ${output.filePath}`));
|
|
1461
|
+
}
|
|
1462
|
+
}
|
|
1463
|
+
console.log(chalk2.green(`\u2713 ${label}: ${written} file(s) generated`));
|
|
1464
|
+
return written;
|
|
1465
|
+
}
|
|
1466
|
+
async function promptGenerateOptions(configTeams, configPlatforms) {
|
|
1467
|
+
const { mode } = await inquirer2.prompt([
|
|
519
1468
|
{
|
|
520
|
-
type: "
|
|
521
|
-
name: "
|
|
522
|
-
message: "
|
|
523
|
-
|
|
1469
|
+
type: "list",
|
|
1470
|
+
name: "mode",
|
|
1471
|
+
message: "Generate mode:",
|
|
1472
|
+
choices: [
|
|
1473
|
+
{ name: "Platform configs (agents, skills, references)", value: "platform" },
|
|
1474
|
+
{ name: "Plugin bundle", value: "plugin" }
|
|
1475
|
+
]
|
|
1476
|
+
}
|
|
1477
|
+
]);
|
|
1478
|
+
if (mode === "plugin") {
|
|
1479
|
+
return { scopes: ["plugin"] };
|
|
1480
|
+
}
|
|
1481
|
+
const answers = await inquirer2.prompt([
|
|
1482
|
+
{
|
|
1483
|
+
type: "checkbox",
|
|
1484
|
+
name: "scopes",
|
|
1485
|
+
message: "What to generate:",
|
|
1486
|
+
choices: [
|
|
1487
|
+
{ name: "Agents", value: "agents", checked: true },
|
|
1488
|
+
{ name: "Skills", value: "skills", checked: true },
|
|
1489
|
+
{ name: "References", value: "references", checked: true },
|
|
1490
|
+
{ name: "Examples", value: "examples", checked: true },
|
|
1491
|
+
{ name: "Output Contracts", value: "output-contracts", checked: true },
|
|
1492
|
+
{ name: "Scripts", value: "scripts", checked: true },
|
|
1493
|
+
{ name: "Assets", value: "assets", checked: true }
|
|
1494
|
+
]
|
|
1495
|
+
},
|
|
1496
|
+
{
|
|
1497
|
+
type: "checkbox",
|
|
1498
|
+
name: "teams",
|
|
1499
|
+
message: "Team agents:",
|
|
1500
|
+
choices: TEAM_ROLES.map((role) => ({
|
|
1501
|
+
name: role,
|
|
1502
|
+
value: role,
|
|
1503
|
+
checked: configTeams.includes(role)
|
|
1504
|
+
})),
|
|
1505
|
+
validate: (input) => input.length > 0 || "Select at least one team"
|
|
524
1506
|
},
|
|
525
1507
|
{
|
|
526
1508
|
type: "checkbox",
|
|
@@ -528,41 +1510,64 @@ async function runInit(cwd = process.cwd()) {
|
|
|
528
1510
|
message: "Target platforms:",
|
|
529
1511
|
choices: PLATFORMS.map((p) => ({
|
|
530
1512
|
name: p,
|
|
531
|
-
|
|
1513
|
+
value: p,
|
|
1514
|
+
checked: configPlatforms.includes(p)
|
|
532
1515
|
})),
|
|
533
1516
|
validate: (input) => input.length > 0 || "Select at least one platform"
|
|
534
|
-
},
|
|
535
|
-
{
|
|
536
|
-
type: "checkbox",
|
|
537
|
-
name: "teams",
|
|
538
|
-
message: "Team agents to enable:",
|
|
539
|
-
choices: [
|
|
540
|
-
{ name: "Lead (Tech Lead / Orchestrator)", value: "lead", checked: true },
|
|
541
|
-
{ name: "BA (Business Analyst)", value: "ba", checked: true },
|
|
542
|
-
{ name: "FE (Frontend)", value: "fe", checked: true },
|
|
543
|
-
{ name: "BE (Backend)", value: "be", checked: true },
|
|
544
|
-
{ name: "QA (Testing)", value: "qa", checked: true },
|
|
545
|
-
{ name: "DevOps (Infrastructure)", value: "devops", checked: true }
|
|
546
|
-
],
|
|
547
|
-
validate: (input) => input.length > 0 || "Select at least one team"
|
|
548
1517
|
}
|
|
549
1518
|
]);
|
|
550
|
-
const
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
teams: answers.teams
|
|
1519
|
+
const scopes = answers.scopes.length > 0 ? answers.scopes : ["all"];
|
|
1520
|
+
return {
|
|
1521
|
+
scopes,
|
|
1522
|
+
teams: answers.teams,
|
|
1523
|
+
platforms: answers.platforms
|
|
554
1524
|
};
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
1525
|
+
}
|
|
1526
|
+
async function runGenerate(cwd = process.cwd(), options = {}) {
|
|
1527
|
+
const config = await loadConfig(cwd);
|
|
1528
|
+
const hasFlags = options.platform || options.platforms || options.teams || options.scopes && !(options.scopes.length === 1 && options.scopes[0] === "all");
|
|
1529
|
+
if (!hasFlags && process.stdin.isTTY) {
|
|
1530
|
+
const prompted = await promptGenerateOptions(config.teams, config.platforms);
|
|
1531
|
+
options = { ...options, ...prompted };
|
|
1532
|
+
}
|
|
1533
|
+
const effectiveConfig = options.teams ? { ...config, teams: options.teams } : config;
|
|
1534
|
+
const agents = loadAgents(effectiveConfig, cwd);
|
|
1535
|
+
const scopes = options.scopes ?? ["all"];
|
|
1536
|
+
if (scopes.includes("plugin")) {
|
|
1537
|
+
const pluginDir = effectiveConfig.output?.pluginDir ?? ".aigent-team-plugin";
|
|
1538
|
+
const pluginCompiler = new PluginCompiler();
|
|
1539
|
+
const outputs = pluginCompiler.compilePlugin(agents, effectiveConfig, pluginDir);
|
|
1540
|
+
const written = writeOutputs(outputs, cwd, "plugin");
|
|
1541
|
+
console.log(chalk2.bold(`
|
|
1542
|
+
Total: ${written} file(s) generated`));
|
|
1543
|
+
return;
|
|
1544
|
+
}
|
|
1545
|
+
const platforms = options.platform ? [options.platform] : options.platforms ?? effectiveConfig.platforms;
|
|
1546
|
+
const compilers2 = getAllCompilers(platforms);
|
|
1547
|
+
let totalFiles = 0;
|
|
1548
|
+
let totalWarnings = 0;
|
|
1549
|
+
for (const compiler of compilers2) {
|
|
1550
|
+
const outputs = compiler.compileWithScope(agents, effectiveConfig, scopes);
|
|
1551
|
+
const validation = compiler.validate(outputs);
|
|
1552
|
+
if (!validation.valid) {
|
|
1553
|
+
console.log(chalk2.red(`
|
|
1554
|
+
\u2717 ${compiler.platform} validation errors:`));
|
|
1555
|
+
for (const error of validation.errors) {
|
|
1556
|
+
console.log(chalk2.red(` - ${error}`));
|
|
1557
|
+
}
|
|
1558
|
+
continue;
|
|
1559
|
+
}
|
|
1560
|
+
for (const warning of validation.warnings) {
|
|
1561
|
+
console.log(chalk2.yellow(` \u26A0 ${warning}`));
|
|
1562
|
+
totalWarnings++;
|
|
1563
|
+
}
|
|
1564
|
+
totalFiles += writeOutputs(outputs, cwd, compiler.platform);
|
|
1565
|
+
}
|
|
1566
|
+
console.log(chalk2.bold(`
|
|
1567
|
+
Total: ${totalFiles} file(s) generated`));
|
|
1568
|
+
if (totalWarnings > 0) {
|
|
1569
|
+
console.log(chalk2.yellow(`${totalWarnings} warning(s)`));
|
|
1570
|
+
}
|
|
566
1571
|
}
|
|
567
1572
|
|
|
568
1573
|
// src/cli/validate.ts
|
|
@@ -604,18 +1609,546 @@ async function runValidate(cwd = process.cwd()) {
|
|
|
604
1609
|
}
|
|
605
1610
|
}
|
|
606
1611
|
|
|
1612
|
+
// src/cli/install.ts
|
|
1613
|
+
import { writeFileSync as writeFileSync3, mkdirSync as mkdirSync3, existsSync as existsSync5, readFileSync as readFileSync4, cpSync, rmSync } from "fs";
|
|
1614
|
+
import { homedir } from "os";
|
|
1615
|
+
import { resolve as resolve6, dirname as dirname2, join } from "path";
|
|
1616
|
+
import chalk4 from "chalk";
|
|
1617
|
+
|
|
1618
|
+
// src/core/plugin-loader.ts
|
|
1619
|
+
import { readFileSync as readFileSync3, existsSync as existsSync4, readdirSync } from "fs";
|
|
1620
|
+
import { resolve as resolve5, basename } from "path";
|
|
1621
|
+
function loadPlugin(pluginPath) {
|
|
1622
|
+
const absPath = resolve5(pluginPath);
|
|
1623
|
+
const manifestPath = resolve5(absPath, "manifest.json");
|
|
1624
|
+
if (!existsSync4(manifestPath)) {
|
|
1625
|
+
throw new Error(`Plugin manifest not found: ${manifestPath}`);
|
|
1626
|
+
}
|
|
1627
|
+
const manifest = JSON.parse(readFileSync3(manifestPath, "utf-8"));
|
|
1628
|
+
if (!manifest.agents?.length) {
|
|
1629
|
+
throw new Error("Plugin manifest has no agents metadata. Was it generated with aigent-team >= 0.3.0?");
|
|
1630
|
+
}
|
|
1631
|
+
const bundleDir = findBundleDir(absPath, manifest);
|
|
1632
|
+
const agents = [];
|
|
1633
|
+
for (const meta of manifest.agents) {
|
|
1634
|
+
const agentFilePath = resolve5(bundleDir, "agents", `${meta.id}-agent.md`);
|
|
1635
|
+
if (!existsSync4(agentFilePath)) {
|
|
1636
|
+
throw new Error(`Agent file not found: ${agentFilePath}`);
|
|
1637
|
+
}
|
|
1638
|
+
const skillContent = readFileSync3(agentFilePath, "utf-8").trim();
|
|
1639
|
+
const skills = loadSkillFiles(resolve5(bundleDir, "skills", meta.id));
|
|
1640
|
+
const references = loadReferenceFiles(resolve5(bundleDir, "kb", meta.id));
|
|
1641
|
+
const examples = loadExampleFiles(resolve5(bundleDir, "examples", meta.id));
|
|
1642
|
+
const outputContracts = loadOutputContractFiles(resolve5(bundleDir, "contracts", meta.id));
|
|
1643
|
+
const scripts = loadScriptFilesFromPlugin(resolve5(bundleDir, "scripts", meta.id));
|
|
1644
|
+
const assets = loadAssetFilesFromPlugin(resolve5(bundleDir, "assets", meta.id));
|
|
1645
|
+
const sharedKnowledge = loadSharedKnowledge(resolve5(bundleDir, "kb", "shared"));
|
|
1646
|
+
agents.push({
|
|
1647
|
+
id: meta.id,
|
|
1648
|
+
name: meta.name,
|
|
1649
|
+
description: meta.description,
|
|
1650
|
+
role: meta.role,
|
|
1651
|
+
tools: meta.tools,
|
|
1652
|
+
globs: meta.globs,
|
|
1653
|
+
// The skillContent already contains the assembled index (rules + skill content + catalog).
|
|
1654
|
+
// Set it as skillContent and leave rulesContent/skills empty so assembleSkillIndex()
|
|
1655
|
+
// returns it as-is without double-including rules or catalog.
|
|
1656
|
+
skillContent,
|
|
1657
|
+
rulesContent: "",
|
|
1658
|
+
skills,
|
|
1659
|
+
references,
|
|
1660
|
+
examples,
|
|
1661
|
+
outputContracts,
|
|
1662
|
+
scripts,
|
|
1663
|
+
assets,
|
|
1664
|
+
sharedKnowledge,
|
|
1665
|
+
// Unused during install — compilers only need the fields above
|
|
1666
|
+
systemPrompt: "",
|
|
1667
|
+
techStack: { languages: [], frameworks: [], libraries: [], buildTools: [] },
|
|
1668
|
+
conventions: "",
|
|
1669
|
+
reviewChecklist: "",
|
|
1670
|
+
workflows: []
|
|
1671
|
+
});
|
|
1672
|
+
}
|
|
1673
|
+
return { manifest, agents };
|
|
1674
|
+
}
|
|
1675
|
+
function findBundleDir(absPath, manifest) {
|
|
1676
|
+
const preferred = ["claude-code-plugin", "cursor-ide-plugin", "codex-plugin", "antigravity-plugin"];
|
|
1677
|
+
for (const dir of preferred) {
|
|
1678
|
+
const candidate = resolve5(absPath, dir);
|
|
1679
|
+
if (existsSync4(candidate)) return candidate;
|
|
1680
|
+
}
|
|
1681
|
+
for (const bundle of manifest.bundles ?? []) {
|
|
1682
|
+
const candidate = resolve5(absPath, bundle.directory);
|
|
1683
|
+
if (existsSync4(candidate)) return candidate;
|
|
1684
|
+
}
|
|
1685
|
+
throw new Error(`No platform bundle found in plugin: ${absPath}`);
|
|
1686
|
+
}
|
|
1687
|
+
function loadSkillFiles(dir) {
|
|
1688
|
+
if (!existsSync4(dir)) return [];
|
|
1689
|
+
return readdirSync(dir).filter((f) => f.endsWith(".md")).map((f) => {
|
|
1690
|
+
const id = basename(f, ".md");
|
|
1691
|
+
const raw = readFileSync3(resolve5(dir, f), "utf-8").trim();
|
|
1692
|
+
const { data, content } = parseFrontmatter(raw);
|
|
1693
|
+
return {
|
|
1694
|
+
id,
|
|
1695
|
+
name: data.name || id.replace(/-/g, " "),
|
|
1696
|
+
description: data.description || "",
|
|
1697
|
+
trigger: data.trigger || "",
|
|
1698
|
+
content,
|
|
1699
|
+
useCases: data.useCases || void 0,
|
|
1700
|
+
tags: data.tags || void 0
|
|
1701
|
+
};
|
|
1702
|
+
});
|
|
1703
|
+
}
|
|
1704
|
+
function loadReferenceFiles(dir) {
|
|
1705
|
+
if (!existsSync4(dir)) return [];
|
|
1706
|
+
return readdirSync(dir).filter((f) => f.endsWith(".md")).map((f) => {
|
|
1707
|
+
const id = basename(f, ".md");
|
|
1708
|
+
const raw = readFileSync3(resolve5(dir, f), "utf-8").trim();
|
|
1709
|
+
const { data, content } = parseFrontmatter(raw);
|
|
1710
|
+
return {
|
|
1711
|
+
id,
|
|
1712
|
+
title: data.title || id.replace(/-/g, " "),
|
|
1713
|
+
description: data.description || "",
|
|
1714
|
+
whenToRead: data.whenToRead || "",
|
|
1715
|
+
content,
|
|
1716
|
+
tags: data.tags || void 0
|
|
1717
|
+
};
|
|
1718
|
+
});
|
|
1719
|
+
}
|
|
1720
|
+
function loadExampleFiles(dir) {
|
|
1721
|
+
if (!existsSync4(dir)) return [];
|
|
1722
|
+
return readdirSync(dir).filter((f) => f.endsWith(".md")).map((f) => {
|
|
1723
|
+
const id = basename(f, ".md");
|
|
1724
|
+
const raw = readFileSync3(resolve5(dir, f), "utf-8").trim();
|
|
1725
|
+
const { data, content } = parseFrontmatter(raw);
|
|
1726
|
+
return {
|
|
1727
|
+
id,
|
|
1728
|
+
name: data.name || id.replace(/-/g, " "),
|
|
1729
|
+
description: data.description || "",
|
|
1730
|
+
skillRef: data.skillRef || void 0,
|
|
1731
|
+
content,
|
|
1732
|
+
tags: data.tags || void 0
|
|
1733
|
+
};
|
|
1734
|
+
});
|
|
1735
|
+
}
|
|
1736
|
+
function loadOutputContractFiles(dir) {
|
|
1737
|
+
if (!existsSync4(dir)) return [];
|
|
1738
|
+
return readdirSync(dir).filter((f) => f.endsWith(".md")).map((f) => {
|
|
1739
|
+
const id = basename(f, ".md");
|
|
1740
|
+
const raw = readFileSync3(resolve5(dir, f), "utf-8").trim();
|
|
1741
|
+
const { data, content } = parseFrontmatter(raw);
|
|
1742
|
+
return {
|
|
1743
|
+
id,
|
|
1744
|
+
name: data.name || id.replace(/-/g, " "),
|
|
1745
|
+
description: data.description || "",
|
|
1746
|
+
skillRef: data.skillRef || void 0,
|
|
1747
|
+
format: data.format || void 0,
|
|
1748
|
+
content,
|
|
1749
|
+
tags: data.tags || void 0
|
|
1750
|
+
};
|
|
1751
|
+
});
|
|
1752
|
+
}
|
|
1753
|
+
function loadScriptFilesFromPlugin(dir) {
|
|
1754
|
+
if (!existsSync4(dir)) return [];
|
|
1755
|
+
return readdirSync(dir).filter((f) => f.endsWith(".md")).map((f) => {
|
|
1756
|
+
const id = basename(f, ".md");
|
|
1757
|
+
const raw = readFileSync3(resolve5(dir, f), "utf-8").trim();
|
|
1758
|
+
const { data, content } = parseFrontmatter(raw);
|
|
1759
|
+
return {
|
|
1760
|
+
id,
|
|
1761
|
+
name: data.name || id.replace(/-/g, " "),
|
|
1762
|
+
description: data.description || "",
|
|
1763
|
+
language: data.language || "unknown",
|
|
1764
|
+
content,
|
|
1765
|
+
tags: data.tags || void 0
|
|
1766
|
+
};
|
|
1767
|
+
});
|
|
1768
|
+
}
|
|
1769
|
+
function loadAssetFilesFromPlugin(dir) {
|
|
1770
|
+
if (!existsSync4(dir)) return [];
|
|
1771
|
+
return readdirSync(dir).filter((f) => f.endsWith(".md")).map((f) => {
|
|
1772
|
+
const id = basename(f, ".md");
|
|
1773
|
+
const raw = readFileSync3(resolve5(dir, f), "utf-8").trim();
|
|
1774
|
+
const { data, content } = parseFrontmatter(raw);
|
|
1775
|
+
return {
|
|
1776
|
+
id,
|
|
1777
|
+
name: data.name || id.replace(/-/g, " "),
|
|
1778
|
+
description: data.description || "",
|
|
1779
|
+
format: data.format || "unknown",
|
|
1780
|
+
content,
|
|
1781
|
+
tags: data.tags || void 0
|
|
1782
|
+
};
|
|
1783
|
+
});
|
|
1784
|
+
}
|
|
1785
|
+
function loadSharedKnowledge(dir) {
|
|
1786
|
+
if (!existsSync4(dir)) return [];
|
|
1787
|
+
return readdirSync(dir).filter((f) => f.endsWith(".md")).sort().map((f) => readFileSync3(resolve5(dir, f), "utf-8").trim()).filter(Boolean);
|
|
1788
|
+
}
|
|
1789
|
+
|
|
1790
|
+
// src/cli/install.ts
|
|
1791
|
+
function readCursorPluginId(cursorIdePluginRoot) {
|
|
1792
|
+
const manifestPath = resolve6(cursorIdePluginRoot, ".cursor-plugin", "plugin.json");
|
|
1793
|
+
if (!existsSync5(manifestPath)) {
|
|
1794
|
+
throw new Error(`Missing ${manifestPath}`);
|
|
1795
|
+
}
|
|
1796
|
+
const raw = JSON.parse(readFileSync4(manifestPath, "utf-8"));
|
|
1797
|
+
if (!raw.name || typeof raw.name !== "string") {
|
|
1798
|
+
throw new Error(`Invalid Cursor plugin manifest: missing "name" in ${manifestPath}`);
|
|
1799
|
+
}
|
|
1800
|
+
return raw.name;
|
|
1801
|
+
}
|
|
1802
|
+
function installCursorUserPlugin(cursorIdePluginSource, force) {
|
|
1803
|
+
const pluginId = readCursorPluginId(cursorIdePluginSource);
|
|
1804
|
+
const localRoot = join(homedir(), ".cursor", "plugins", "local");
|
|
1805
|
+
const dest = join(localRoot, pluginId);
|
|
1806
|
+
if (existsSync5(dest) && !force) {
|
|
1807
|
+
throw new Error(
|
|
1808
|
+
`Cursor user plugin already exists: ${dest}
|
|
1809
|
+
Use --force to replace, or remove that folder first.`
|
|
1810
|
+
);
|
|
1811
|
+
}
|
|
1812
|
+
mkdirSync3(localRoot, { recursive: true });
|
|
1813
|
+
if (existsSync5(dest)) {
|
|
1814
|
+
rmSync(dest, { recursive: true, force: true });
|
|
1815
|
+
}
|
|
1816
|
+
cpSync(cursorIdePluginSource, dest, { recursive: true });
|
|
1817
|
+
return dest;
|
|
1818
|
+
}
|
|
1819
|
+
function writeInstallOutput(output, cwd, force) {
|
|
1820
|
+
const fullPath = resolve6(cwd, output.filePath);
|
|
1821
|
+
const dir = dirname2(fullPath);
|
|
1822
|
+
if (!force && existsSync5(fullPath)) {
|
|
1823
|
+
return false;
|
|
1824
|
+
}
|
|
1825
|
+
mkdirSync3(dir, { recursive: true });
|
|
1826
|
+
writeFileSync3(fullPath, output.content);
|
|
1827
|
+
return true;
|
|
1828
|
+
}
|
|
1829
|
+
async function runInstall(pluginPath, cwd = process.cwd(), options = {}) {
|
|
1830
|
+
const absPluginPath = resolve6(cwd, pluginPath);
|
|
1831
|
+
console.log(chalk4.dim(`Loading plugin from ${absPluginPath}...`));
|
|
1832
|
+
const { manifest, agents } = loadPlugin(absPluginPath);
|
|
1833
|
+
console.log(chalk4.bold(`Plugin: ${manifest.name} v${manifest.version}`));
|
|
1834
|
+
console.log(chalk4.dim(` ${manifest.agents.length} agent(s), ${manifest.files.skills} skill(s), ${manifest.files.references} reference(s)`));
|
|
1835
|
+
let platforms;
|
|
1836
|
+
if (options.platform) {
|
|
1837
|
+
platforms = [options.platform];
|
|
1838
|
+
} else if (configExists(cwd)) {
|
|
1839
|
+
const config2 = await loadConfig(cwd);
|
|
1840
|
+
platforms = config2.platforms;
|
|
1841
|
+
} else {
|
|
1842
|
+
platforms = manifest.platforms;
|
|
1843
|
+
}
|
|
1844
|
+
const config = configExists(cwd) ? await loadConfig(cwd) : {
|
|
1845
|
+
projectName: manifest.projectName,
|
|
1846
|
+
platforms,
|
|
1847
|
+
teams: manifest.roles
|
|
1848
|
+
};
|
|
1849
|
+
const compilers2 = getAllCompilers(platforms);
|
|
1850
|
+
const allWrittenFiles = [];
|
|
1851
|
+
let totalFiles = 0;
|
|
1852
|
+
let skipped = 0;
|
|
1853
|
+
for (const compiler of compilers2) {
|
|
1854
|
+
if (options.cursorUserPlugin && compiler.platform === "cursor") {
|
|
1855
|
+
continue;
|
|
1856
|
+
}
|
|
1857
|
+
const outputs = compiler.compileWithScope(agents, config, ["all"]);
|
|
1858
|
+
const validation = compiler.validate(outputs);
|
|
1859
|
+
if (!validation.valid) {
|
|
1860
|
+
console.log(chalk4.red(`
|
|
1861
|
+
\u2717 ${compiler.platform} validation errors:`));
|
|
1862
|
+
for (const error of validation.errors) {
|
|
1863
|
+
console.log(chalk4.red(` - ${error}`));
|
|
1864
|
+
}
|
|
1865
|
+
continue;
|
|
1866
|
+
}
|
|
1867
|
+
for (const warning of validation.warnings) {
|
|
1868
|
+
console.log(chalk4.yellow(` \u26A0 ${warning}`));
|
|
1869
|
+
}
|
|
1870
|
+
let written = 0;
|
|
1871
|
+
for (const output of outputs) {
|
|
1872
|
+
if (writeInstallOutput(output, cwd, !!options.force)) {
|
|
1873
|
+
written++;
|
|
1874
|
+
allWrittenFiles.push(output.filePath);
|
|
1875
|
+
console.log(chalk4.dim(` ${output.filePath}`));
|
|
1876
|
+
} else {
|
|
1877
|
+
skipped++;
|
|
1878
|
+
}
|
|
1879
|
+
}
|
|
1880
|
+
console.log(chalk4.green(`\u2713 ${compiler.platform}: ${written} file(s) installed`));
|
|
1881
|
+
totalFiles += written;
|
|
1882
|
+
}
|
|
1883
|
+
let cursorUserPluginPath;
|
|
1884
|
+
const cursorIdeBundle = resolve6(absPluginPath, "cursor-ide-plugin");
|
|
1885
|
+
const shouldInstallCursorUser = !!options.cursorUserPlugin && (!options.platform || options.platform === "cursor") && platforms.includes("cursor");
|
|
1886
|
+
if (shouldInstallCursorUser) {
|
|
1887
|
+
if (!existsSync5(cursorIdeBundle)) {
|
|
1888
|
+
console.log(
|
|
1889
|
+
chalk4.red(
|
|
1890
|
+
`
|
|
1891
|
+
\u2717 cursor-ide-plugin/ not found under ${absPluginPath}.
|
|
1892
|
+
Run: npx aigent-team generate --scope plugin`
|
|
1893
|
+
)
|
|
1894
|
+
);
|
|
1895
|
+
} else {
|
|
1896
|
+
try {
|
|
1897
|
+
cursorUserPluginPath = installCursorUserPlugin(cursorIdeBundle, !!options.force);
|
|
1898
|
+
console.log(chalk4.green(`\u2713 cursor (user plugin): ${cursorUserPluginPath}`));
|
|
1899
|
+
} catch (e) {
|
|
1900
|
+
console.log(chalk4.red(`
|
|
1901
|
+
\u2717 Cursor user plugin install failed: ${e.message}`));
|
|
1902
|
+
}
|
|
1903
|
+
}
|
|
1904
|
+
}
|
|
1905
|
+
const recordDir = resolve6(cwd, ".aigent-team", "installed");
|
|
1906
|
+
mkdirSync3(recordDir, { recursive: true });
|
|
1907
|
+
const record = {
|
|
1908
|
+
name: manifest.name,
|
|
1909
|
+
version: manifest.version,
|
|
1910
|
+
installedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1911
|
+
pluginPath: absPluginPath,
|
|
1912
|
+
files: allWrittenFiles,
|
|
1913
|
+
...cursorUserPluginPath ? { cursorUserPluginPath } : {}
|
|
1914
|
+
};
|
|
1915
|
+
writeFileSync3(
|
|
1916
|
+
resolve6(recordDir, `${manifest.name}.json`),
|
|
1917
|
+
JSON.stringify(record, null, 2) + "\n"
|
|
1918
|
+
);
|
|
1919
|
+
console.log(chalk4.bold(`
|
|
1920
|
+
Total: ${totalFiles} file(s) installed`));
|
|
1921
|
+
if (skipped > 0) {
|
|
1922
|
+
console.log(chalk4.yellow(`${skipped} file(s) skipped (already exist, use --force to overwrite)`));
|
|
1923
|
+
}
|
|
1924
|
+
}
|
|
1925
|
+
|
|
1926
|
+
// src/cli/uninstall.ts
|
|
1927
|
+
import { unlinkSync, existsSync as existsSync6, readFileSync as readFileSync5, readdirSync as readdirSync2, rmdirSync, rmSync as rmSync2 } from "fs";
|
|
1928
|
+
import { resolve as resolve7, dirname as dirname3 } from "path";
|
|
1929
|
+
import chalk5 from "chalk";
|
|
1930
|
+
async function runUninstall(pluginName, cwd = process.cwd()) {
|
|
1931
|
+
const recordPath = resolve7(cwd, ".aigent-team", "installed", `${pluginName}.json`);
|
|
1932
|
+
if (!existsSync6(recordPath)) {
|
|
1933
|
+
const installedDir = resolve7(cwd, ".aigent-team", "installed");
|
|
1934
|
+
if (existsSync6(installedDir)) {
|
|
1935
|
+
const installed = readdirSync2(installedDir).filter((f) => f.endsWith(".json")).map((f) => f.replace(".json", ""));
|
|
1936
|
+
if (installed.length > 0) {
|
|
1937
|
+
console.log(chalk5.red(`Plugin "${pluginName}" is not installed.`));
|
|
1938
|
+
console.log(chalk5.dim(`Installed plugins: ${installed.join(", ")}`));
|
|
1939
|
+
return;
|
|
1940
|
+
}
|
|
1941
|
+
}
|
|
1942
|
+
console.log(chalk5.red(`No installed plugins found.`));
|
|
1943
|
+
return;
|
|
1944
|
+
}
|
|
1945
|
+
const record = JSON.parse(readFileSync5(recordPath, "utf-8"));
|
|
1946
|
+
console.log(chalk5.bold(`Uninstalling: ${record.name} v${record.version}`));
|
|
1947
|
+
if (record.cursorUserPluginPath && existsSync6(record.cursorUserPluginPath)) {
|
|
1948
|
+
rmSync2(record.cursorUserPluginPath, { recursive: true, force: true });
|
|
1949
|
+
console.log(chalk5.dim(` \u2717 ${record.cursorUserPluginPath} (Cursor user plugin)`));
|
|
1950
|
+
}
|
|
1951
|
+
let removed = 0;
|
|
1952
|
+
let missing = 0;
|
|
1953
|
+
for (const filePath of record.files) {
|
|
1954
|
+
const fullPath = resolve7(cwd, filePath);
|
|
1955
|
+
if (existsSync6(fullPath)) {
|
|
1956
|
+
unlinkSync(fullPath);
|
|
1957
|
+
removed++;
|
|
1958
|
+
console.log(chalk5.dim(` \u2717 ${filePath}`));
|
|
1959
|
+
tryRemoveEmptyDir(dirname3(fullPath));
|
|
1960
|
+
} else {
|
|
1961
|
+
missing++;
|
|
1962
|
+
}
|
|
1963
|
+
}
|
|
1964
|
+
unlinkSync(recordPath);
|
|
1965
|
+
console.log(chalk5.bold(`
|
|
1966
|
+
Removed: ${removed} file(s)`));
|
|
1967
|
+
if (missing > 0) {
|
|
1968
|
+
console.log(chalk5.yellow(`${missing} file(s) already missing`));
|
|
1969
|
+
}
|
|
1970
|
+
}
|
|
1971
|
+
function tryRemoveEmptyDir(dir) {
|
|
1972
|
+
try {
|
|
1973
|
+
const entries = readdirSync2(dir);
|
|
1974
|
+
if (entries.length === 0) {
|
|
1975
|
+
rmdirSync(dir);
|
|
1976
|
+
tryRemoveEmptyDir(dirname3(dir));
|
|
1977
|
+
}
|
|
1978
|
+
} catch {
|
|
1979
|
+
}
|
|
1980
|
+
}
|
|
1981
|
+
|
|
1982
|
+
// src/cli/audit.ts
|
|
1983
|
+
import chalk6 from "chalk";
|
|
1984
|
+
function auditSkill(agent, skill) {
|
|
1985
|
+
const entries = [];
|
|
1986
|
+
const base = { agentId: agent.id, agentName: agent.name, skillId: skill.id, skillName: skill.name };
|
|
1987
|
+
if (!skill.governance) {
|
|
1988
|
+
entries.push({ ...base, issue: "No governance metadata", severity: "warning" });
|
|
1989
|
+
return entries;
|
|
1990
|
+
}
|
|
1991
|
+
const gov = skill.governance;
|
|
1992
|
+
if (gov.status === "deprecated") {
|
|
1993
|
+
entries.push({
|
|
1994
|
+
...base,
|
|
1995
|
+
issue: `Deprecated${gov.deprecatedReason ? `: ${gov.deprecatedReason}` : ""}`,
|
|
1996
|
+
severity: "error"
|
|
1997
|
+
});
|
|
1998
|
+
}
|
|
1999
|
+
if (gov.status === "review-needed") {
|
|
2000
|
+
entries.push({ ...base, issue: "Marked for review", severity: "warning" });
|
|
2001
|
+
}
|
|
2002
|
+
if (gov.status === "draft") {
|
|
2003
|
+
entries.push({ ...base, issue: "Still in draft", severity: "info" });
|
|
2004
|
+
}
|
|
2005
|
+
if (!gov.version) {
|
|
2006
|
+
entries.push({ ...base, issue: "Missing version", severity: "info" });
|
|
2007
|
+
}
|
|
2008
|
+
if (!gov.owner) {
|
|
2009
|
+
entries.push({ ...base, issue: "Missing owner", severity: "info" });
|
|
2010
|
+
}
|
|
2011
|
+
if (!skill.description) {
|
|
2012
|
+
entries.push({ ...base, issue: "Missing skill description", severity: "warning" });
|
|
2013
|
+
}
|
|
2014
|
+
if (!skill.trigger) {
|
|
2015
|
+
entries.push({ ...base, issue: "Missing skill trigger", severity: "info" });
|
|
2016
|
+
}
|
|
2017
|
+
return entries;
|
|
2018
|
+
}
|
|
2019
|
+
async function runAudit(cwd = process.cwd()) {
|
|
2020
|
+
const config = await loadConfig(cwd);
|
|
2021
|
+
const agents = loadAgents(config, cwd);
|
|
2022
|
+
const allEntries = [];
|
|
2023
|
+
let totalSkills = 0;
|
|
2024
|
+
let withGovernance = 0;
|
|
2025
|
+
for (const agent of agents) {
|
|
2026
|
+
for (const skill of agent.skills) {
|
|
2027
|
+
totalSkills++;
|
|
2028
|
+
if (skill.governance) withGovernance++;
|
|
2029
|
+
allEntries.push(...auditSkill(agent, skill));
|
|
2030
|
+
}
|
|
2031
|
+
}
|
|
2032
|
+
console.log(chalk6.bold("\nSkill Governance Audit"));
|
|
2033
|
+
console.log(chalk6.dim("\u2500".repeat(50)));
|
|
2034
|
+
console.log(`Total skills: ${totalSkills}`);
|
|
2035
|
+
console.log(`With governance metadata: ${withGovernance}/${totalSkills}`);
|
|
2036
|
+
const statusCounts = {
|
|
2037
|
+
"active": 0,
|
|
2038
|
+
"draft": 0,
|
|
2039
|
+
"review-needed": 0,
|
|
2040
|
+
"deprecated": 0,
|
|
2041
|
+
"none": 0
|
|
2042
|
+
};
|
|
2043
|
+
for (const agent of agents) {
|
|
2044
|
+
for (const skill of agent.skills) {
|
|
2045
|
+
const status = skill.governance?.status ?? "none";
|
|
2046
|
+
statusCounts[status]++;
|
|
2047
|
+
}
|
|
2048
|
+
}
|
|
2049
|
+
console.log(`
|
|
2050
|
+
Status breakdown:`);
|
|
2051
|
+
if (statusCounts.active) console.log(chalk6.green(` active: ${statusCounts.active}`));
|
|
2052
|
+
if (statusCounts.draft) console.log(chalk6.blue(` draft: ${statusCounts.draft}`));
|
|
2053
|
+
if (statusCounts["review-needed"]) console.log(chalk6.yellow(` review-needed: ${statusCounts["review-needed"]}`));
|
|
2054
|
+
if (statusCounts.deprecated) console.log(chalk6.red(` deprecated: ${statusCounts.deprecated}`));
|
|
2055
|
+
if (statusCounts.none) console.log(chalk6.dim(` no status: ${statusCounts.none}`));
|
|
2056
|
+
const errors = allEntries.filter((e) => e.severity === "error");
|
|
2057
|
+
const warnings = allEntries.filter((e) => e.severity === "warning");
|
|
2058
|
+
const infos = allEntries.filter((e) => e.severity === "info");
|
|
2059
|
+
if (errors.length) {
|
|
2060
|
+
console.log(chalk6.red(`
|
|
2061
|
+
\u2717 Errors (${errors.length}):`));
|
|
2062
|
+
for (const e of errors) {
|
|
2063
|
+
console.log(chalk6.red(` ${e.agentId}/${e.skillId}: ${e.issue}`));
|
|
2064
|
+
}
|
|
2065
|
+
}
|
|
2066
|
+
if (warnings.length) {
|
|
2067
|
+
console.log(chalk6.yellow(`
|
|
2068
|
+
\u26A0 Warnings (${warnings.length}):`));
|
|
2069
|
+
for (const e of warnings) {
|
|
2070
|
+
console.log(chalk6.yellow(` ${e.agentId}/${e.skillId}: ${e.issue}`));
|
|
2071
|
+
}
|
|
2072
|
+
}
|
|
2073
|
+
if (infos.length) {
|
|
2074
|
+
console.log(chalk6.blue(`
|
|
2075
|
+
\u2139 Info (${infos.length}):`));
|
|
2076
|
+
for (const e of infos) {
|
|
2077
|
+
console.log(chalk6.blue(` ${e.agentId}/${e.skillId}: ${e.issue}`));
|
|
2078
|
+
}
|
|
2079
|
+
}
|
|
2080
|
+
if (!allEntries.length) {
|
|
2081
|
+
console.log(chalk6.green("\n\u2713 All skills pass governance checks"));
|
|
2082
|
+
}
|
|
2083
|
+
console.log();
|
|
2084
|
+
if (errors.length) {
|
|
2085
|
+
process.exit(1);
|
|
2086
|
+
}
|
|
2087
|
+
}
|
|
2088
|
+
|
|
607
2089
|
// bin/cli.ts
|
|
608
2090
|
var program = new Command();
|
|
609
|
-
program.name("aigent-team").description("Cross-platform AI agent team plugin for Claude Code, Cursor, Codex, and Antigravity").version("0.
|
|
2091
|
+
program.name("aigent-team").description("Cross-platform AI agent team plugin for Claude Code, Cursor, Codex, and Antigravity").version("0.4.0");
|
|
610
2092
|
program.command("init").description("Initialize aigent-team in your project (interactive)").action(async () => {
|
|
611
2093
|
await runInit(process.cwd());
|
|
612
2094
|
});
|
|
613
|
-
program.command("generate").description("Generate platform-specific config files from aigent-team config").option("-p, --platform <platform>", "Generate for a specific platform only").action(async (options) => {
|
|
2095
|
+
program.command("generate").description("Generate platform-specific config files from aigent-team config").option("-p, --platform <platform>", "Generate for a specific platform only").option("-s, --scope <scopes>", "Output scope(s), comma-separated: all | agents | skills | references | plugin", "all").option("-t, --team <teams>", "Team roles to generate, comma-separated (overrides config)").action(async (options) => {
|
|
2096
|
+
if (options.platform && !PLATFORMS.includes(options.platform)) {
|
|
2097
|
+
console.log(chalk7.red(`Unknown platform: ${options.platform}. Valid: ${PLATFORMS.join(", ")}`));
|
|
2098
|
+
process.exit(1);
|
|
2099
|
+
}
|
|
2100
|
+
const scopes = options.scope.split(",");
|
|
2101
|
+
for (const s of scopes) {
|
|
2102
|
+
if (!GENERATE_SCOPES.includes(s)) {
|
|
2103
|
+
console.log(chalk7.red(`Unknown scope: ${s}. Valid: ${GENERATE_SCOPES.join(", ")}`));
|
|
2104
|
+
process.exit(1);
|
|
2105
|
+
}
|
|
2106
|
+
}
|
|
2107
|
+
if (scopes.includes("plugin") && scopes.length > 1) {
|
|
2108
|
+
console.log(chalk7.red(`Scope 'plugin' is exclusive and cannot be combined with other scopes.`));
|
|
2109
|
+
process.exit(1);
|
|
2110
|
+
}
|
|
2111
|
+
if (scopes.includes("all") && scopes.length > 1) {
|
|
2112
|
+
console.log(chalk7.red(`Scope 'all' is exclusive and cannot be combined with other scopes.`));
|
|
2113
|
+
process.exit(1);
|
|
2114
|
+
}
|
|
2115
|
+
let teams;
|
|
2116
|
+
if (options.team) {
|
|
2117
|
+
teams = options.team.split(",");
|
|
2118
|
+
for (const t of teams) {
|
|
2119
|
+
if (!TEAM_ROLES.includes(t)) {
|
|
2120
|
+
console.log(chalk7.red(`Unknown team role: ${t}. Valid: ${TEAM_ROLES.join(", ")}`));
|
|
2121
|
+
process.exit(1);
|
|
2122
|
+
}
|
|
2123
|
+
}
|
|
2124
|
+
}
|
|
614
2125
|
await runGenerate(process.cwd(), {
|
|
615
|
-
platform: options.platform
|
|
2126
|
+
platform: options.platform,
|
|
2127
|
+
scopes,
|
|
2128
|
+
teams
|
|
616
2129
|
});
|
|
617
2130
|
});
|
|
618
2131
|
program.command("validate").description("Validate generated config files against platform constraints").action(async () => {
|
|
619
2132
|
await runValidate(process.cwd());
|
|
620
2133
|
});
|
|
2134
|
+
program.command("install").description("Install a plugin bundle into the current project").argument("<plugin-path>", "Path to plugin directory (containing manifest.json)").option("-p, --platform <platform>", "Install for a specific platform only").option("-f, --force", "Overwrite existing files").option(
|
|
2135
|
+
"--cursor-user-plugin",
|
|
2136
|
+
"Install Cursor IDE bundle from plugin cursor-ide-plugin/ to ~/.cursor/plugins/local/ (see cursor.com/docs/plugins)"
|
|
2137
|
+
).action(async (pluginPath, options) => {
|
|
2138
|
+
if (options.platform && !PLATFORMS.includes(options.platform)) {
|
|
2139
|
+
console.log(chalk7.red(`Unknown platform: ${options.platform}. Valid: ${PLATFORMS.join(", ")}`));
|
|
2140
|
+
process.exit(1);
|
|
2141
|
+
}
|
|
2142
|
+
await runInstall(pluginPath, process.cwd(), {
|
|
2143
|
+
platform: options.platform,
|
|
2144
|
+
force: options.force,
|
|
2145
|
+
cursorUserPlugin: options.cursorUserPlugin
|
|
2146
|
+
});
|
|
2147
|
+
});
|
|
2148
|
+
program.command("uninstall").description("Uninstall a previously installed plugin").argument("<plugin-name>", "Name of the plugin to uninstall").action(async (pluginName) => {
|
|
2149
|
+
await runUninstall(pluginName, process.cwd());
|
|
2150
|
+
});
|
|
2151
|
+
program.command("audit").description("Audit skill governance metadata \u2014 report deprecated, review-needed, and missing metadata").action(async () => {
|
|
2152
|
+
await runAudit(process.cwd());
|
|
2153
|
+
});
|
|
621
2154
|
program.parse();
|