agents.dev 1.0.5 → 1.0.7
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 +44 -132
- package/definitions/dev.coder.yaml +60 -60
- package/package.json +39 -44
- package/src/index.js +139 -0
- package/src/lib/docs.js +97 -0
- package/src/lib/schema.js +13 -0
- package/src/lib/transformers.js +89 -0
- package/dist/generators/agents.js +0 -196
- package/dist/generators/docs.js +0 -89
- package/dist/index.js +0 -160
- package/dist/parsers/markdown.js +0 -86
- package/dist/transformers/gemini.js +0 -36
- package/dist/transformers/kilo.js +0 -18
- package/dist/transformers/opencode.js +0 -18
- package/dist/transformers/roo.js +0 -20
- package/dist/types.js +0 -13
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Converte definição do agente para TOML do Gemini CLI
|
|
3
|
+
*/
|
|
4
|
+
function toGeminiTOML(agent) {
|
|
5
|
+
// Escapa aspas duplas na descrição
|
|
6
|
+
const description = (agent.description || agent.role).replace(/"/g, '\\"');
|
|
7
|
+
|
|
8
|
+
// Constrói o prompt completo
|
|
9
|
+
const parts = [
|
|
10
|
+
`# Identity`,
|
|
11
|
+
`You are **${agent.name}** ${agent.emoji}`,
|
|
12
|
+
`Role: ${agent.role}\n`,
|
|
13
|
+
`# Core Instructions`,
|
|
14
|
+
agent.systemPrompt.trim(),
|
|
15
|
+
'\n'
|
|
16
|
+
];
|
|
17
|
+
|
|
18
|
+
if (agent.rules && agent.rules.length > 0) {
|
|
19
|
+
parts.push(`# Rules & Guidelines`);
|
|
20
|
+
agent.rules.forEach(rule => parts.push(`- ${rule}`));
|
|
21
|
+
parts.push('\n');
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const fullPrompt = parts.join('\n');
|
|
25
|
+
|
|
26
|
+
// Escapa aspas triplas para o bloco multilinha TOML
|
|
27
|
+
const escapedPrompt = fullPrompt.replace(/"""/g, '\\"\\\"\\"');
|
|
28
|
+
|
|
29
|
+
// Monta o TOML final
|
|
30
|
+
let toml = `description = "${description}"\n`;
|
|
31
|
+
toml += `prompt = """\n${escapedPrompt}\n"""\n`;
|
|
32
|
+
|
|
33
|
+
// Mantém rules como array separado se a ferramenta suportar (Gemini CLI suporta)
|
|
34
|
+
if (agent.rules && agent.rules.length > 0) {
|
|
35
|
+
toml += 'rules = [\n';
|
|
36
|
+
agent.rules.forEach(rule => {
|
|
37
|
+
const escaped = rule.replace(/\\/g, '\\\\').replace(/"/g, '\\"');
|
|
38
|
+
toml += ` "${escaped}",\n`;
|
|
39
|
+
});
|
|
40
|
+
toml += ']\n';
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return toml;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Converte para configuração de Custom Mode do Roo Code / Cline (JSON)
|
|
48
|
+
*/
|
|
49
|
+
function toRooConfig(agent, slug) {
|
|
50
|
+
const promptParts = [
|
|
51
|
+
`# ${agent.name} (${agent.role})`,
|
|
52
|
+
`\n${agent.systemPrompt.trim()}\n`
|
|
53
|
+
];
|
|
54
|
+
|
|
55
|
+
if (agent.rules && agent.rules.length > 0) {
|
|
56
|
+
promptParts.push(`## Rules & Guidelines`);
|
|
57
|
+
agent.rules.forEach(rule => promptParts.push(`- ${rule}`));
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return {
|
|
61
|
+
slug: slug,
|
|
62
|
+
name: `${agent.emoji} ${agent.name}`,
|
|
63
|
+
roleDefinition: promptParts.join('\n'),
|
|
64
|
+
groups: ["read", "edit", "browser", "command", "mcp"]
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Converte para Markdown do Kilo Code
|
|
70
|
+
*/
|
|
71
|
+
function toKiloMarkdown(agent) {
|
|
72
|
+
const parts = [
|
|
73
|
+
`<!--- Kilo Code Agent Config --->`,
|
|
74
|
+
`# ${agent.name} ${agent.emoji}`,
|
|
75
|
+
`**Role**: ${agent.role}\n`,
|
|
76
|
+
`## Instructions`,
|
|
77
|
+
agent.systemPrompt.trim(),
|
|
78
|
+
'\n'
|
|
79
|
+
];
|
|
80
|
+
|
|
81
|
+
if (agent.rules && agent.rules.length > 0) {
|
|
82
|
+
parts.push(`## Constraints`);
|
|
83
|
+
agent.rules.forEach(rule => parts.push(`- ${rule}`));
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
return parts.join('\n');
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
module.exports = { toGeminiTOML, toRooConfig, toKiloMarkdown };
|
|
@@ -1,196 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.getAvailableAgents = getAvailableAgents;
|
|
7
|
-
exports.generateAgents = generateAgents;
|
|
8
|
-
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
9
|
-
const path_1 = __importDefault(require("path"));
|
|
10
|
-
const yaml_1 = __importDefault(require("yaml"));
|
|
11
|
-
const chalk_1 = __importDefault(require("chalk"));
|
|
12
|
-
const types_1 = require("../types");
|
|
13
|
-
const gemini_1 = require("../transformers/gemini");
|
|
14
|
-
const roo_1 = require("../transformers/roo");
|
|
15
|
-
const kilo_1 = require("../transformers/kilo");
|
|
16
|
-
const opencode_1 = require("../transformers/opencode");
|
|
17
|
-
const markdown_1 = require("../parsers/markdown");
|
|
18
|
-
async function getAvailableAgents(definitionsDir) {
|
|
19
|
-
if (!(await fs_extra_1.default.pathExists(definitionsDir))) {
|
|
20
|
-
return [];
|
|
21
|
-
}
|
|
22
|
-
const agents = [];
|
|
23
|
-
let files = [];
|
|
24
|
-
let baseDir = definitionsDir;
|
|
25
|
-
const stats = await fs_extra_1.default.stat(definitionsDir);
|
|
26
|
-
if (stats.isFile()) {
|
|
27
|
-
baseDir = path_1.default.dirname(definitionsDir);
|
|
28
|
-
files = [path_1.default.basename(definitionsDir)];
|
|
29
|
-
}
|
|
30
|
-
else {
|
|
31
|
-
files = await fs_extra_1.default.readdir(definitionsDir);
|
|
32
|
-
}
|
|
33
|
-
for (const file of files) {
|
|
34
|
-
const filePath = path_1.default.join(baseDir, file);
|
|
35
|
-
if (file.endsWith('.yaml') || file.endsWith('.yml')) {
|
|
36
|
-
try {
|
|
37
|
-
const content = await fs_extra_1.default.readFile(filePath, 'utf-8');
|
|
38
|
-
const rawAgent = yaml_1.default.parse(content);
|
|
39
|
-
const parseResult = types_1.AgentSchema.safeParse(rawAgent);
|
|
40
|
-
if (parseResult.success) {
|
|
41
|
-
const slug = file.replace(/\.(yaml|yml)$/, '');
|
|
42
|
-
agents.push({
|
|
43
|
-
name: parseResult.data.name,
|
|
44
|
-
slug: slug,
|
|
45
|
-
description: parseResult.data.description
|
|
46
|
-
});
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
catch (e) { }
|
|
50
|
-
}
|
|
51
|
-
else if (file.endsWith('.md')) {
|
|
52
|
-
try {
|
|
53
|
-
const content = await fs_extra_1.default.readFile(filePath, 'utf-8');
|
|
54
|
-
const parsedAgents = (0, markdown_1.parseMarkdownAgents)(content);
|
|
55
|
-
for (const agent of parsedAgents) {
|
|
56
|
-
const parseResult = types_1.AgentSchema.safeParse(agent);
|
|
57
|
-
if (parseResult.success) {
|
|
58
|
-
agents.push({
|
|
59
|
-
name: parseResult.data.name,
|
|
60
|
-
slug: toSlug(parseResult.data.name),
|
|
61
|
-
description: parseResult.data.description
|
|
62
|
-
});
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
catch (e) { }
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
return agents.sort((a, b) => a.name.localeCompare(b.name));
|
|
70
|
-
}
|
|
71
|
-
async function generateAgents(definitionsDir, outDir, selectedTargets, agentWhitelist) {
|
|
72
|
-
console.log(chalk_1.default.blue(`\n📦 Building agents from ${definitionsDir}...`));
|
|
73
|
-
try {
|
|
74
|
-
if (outDir !== process.cwd()) {
|
|
75
|
-
await fs_extra_1.default.ensureDir(outDir);
|
|
76
|
-
}
|
|
77
|
-
// Check if input exists
|
|
78
|
-
if (!(await fs_extra_1.default.pathExists(definitionsDir))) {
|
|
79
|
-
console.error(chalk_1.default.red(`Input not found: ${definitionsDir}`));
|
|
80
|
-
return;
|
|
81
|
-
}
|
|
82
|
-
let files = [];
|
|
83
|
-
let baseDir = definitionsDir;
|
|
84
|
-
const stats = await fs_extra_1.default.stat(definitionsDir);
|
|
85
|
-
if (stats.isFile()) {
|
|
86
|
-
baseDir = path_1.default.dirname(definitionsDir);
|
|
87
|
-
files = [path_1.default.basename(definitionsDir)];
|
|
88
|
-
}
|
|
89
|
-
else {
|
|
90
|
-
files = await fs_extra_1.default.readdir(definitionsDir);
|
|
91
|
-
}
|
|
92
|
-
for (const file of files) {
|
|
93
|
-
const filePath = path_1.default.join(baseDir, file);
|
|
94
|
-
// 1. Handle YAML
|
|
95
|
-
if (file.endsWith('.yaml') || file.endsWith('.yml')) {
|
|
96
|
-
const content = await fs_extra_1.default.readFile(filePath, 'utf-8');
|
|
97
|
-
try {
|
|
98
|
-
const rawAgent = yaml_1.default.parse(content);
|
|
99
|
-
const parseResult = types_1.AgentSchema.safeParse(rawAgent);
|
|
100
|
-
if (!parseResult.success) {
|
|
101
|
-
logValidationErrors(file, parseResult.error);
|
|
102
|
-
continue;
|
|
103
|
-
}
|
|
104
|
-
// Use filename as slug for YAML (backward compatibility)
|
|
105
|
-
const slug = file.replace(/\.(yaml|yml)$/, '');
|
|
106
|
-
if (agentWhitelist && !agentWhitelist.includes(slug)) {
|
|
107
|
-
continue;
|
|
108
|
-
}
|
|
109
|
-
await buildAgentArtifacts(parseResult.data, slug, outDir, selectedTargets);
|
|
110
|
-
}
|
|
111
|
-
catch (e) {
|
|
112
|
-
console.error(chalk_1.default.red(`Error parsing YAML ${file}: ${e.message}`));
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
// 2. Handle Markdown
|
|
116
|
-
else if (file.endsWith('.md')) {
|
|
117
|
-
const content = await fs_extra_1.default.readFile(filePath, 'utf-8');
|
|
118
|
-
const agents = (0, markdown_1.parseMarkdownAgents)(content);
|
|
119
|
-
if (agents.length === 0) {
|
|
120
|
-
console.warn(chalk_1.default.yellow(`⚠️ No agents found in ${file}`));
|
|
121
|
-
continue;
|
|
122
|
-
}
|
|
123
|
-
for (const agent of agents) {
|
|
124
|
-
const parseResult = types_1.AgentSchema.safeParse(agent);
|
|
125
|
-
if (!parseResult.success) {
|
|
126
|
-
logValidationErrors(`${file} -> ${agent.name}`, parseResult.error);
|
|
127
|
-
continue;
|
|
128
|
-
}
|
|
129
|
-
// Use agent name as slug for Markdown
|
|
130
|
-
const slug = toSlug(agent.name);
|
|
131
|
-
if (agentWhitelist && !agentWhitelist.includes(slug)) {
|
|
132
|
-
continue;
|
|
133
|
-
}
|
|
134
|
-
await buildAgentArtifacts(agent, slug, outDir, selectedTargets);
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
console.log(chalk_1.default.bold.green('\n🎉 Build complete! Agents are ready to use.'));
|
|
139
|
-
}
|
|
140
|
-
catch (err) {
|
|
141
|
-
console.error(chalk_1.default.red('Build failed:'), err);
|
|
142
|
-
process.exit(1);
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
async function buildAgentArtifacts(agent, slug, outDir, selectedTargets) {
|
|
146
|
-
const allTargets = [
|
|
147
|
-
{
|
|
148
|
-
id: 'gemini',
|
|
149
|
-
subDir: '.gemini/commands',
|
|
150
|
-
ext: 'toml',
|
|
151
|
-
content: (0, gemini_1.toGeminiSystemPrompt)(agent),
|
|
152
|
-
name: `${slug}.toml`
|
|
153
|
-
},
|
|
154
|
-
{
|
|
155
|
-
id: 'roo',
|
|
156
|
-
subDir: '.roo/commands',
|
|
157
|
-
ext: 'md',
|
|
158
|
-
content: (0, roo_1.toRooRules)(agent),
|
|
159
|
-
name: `${slug}.md`
|
|
160
|
-
},
|
|
161
|
-
{
|
|
162
|
-
id: 'kilo',
|
|
163
|
-
subDir: '.kilocode/workflows',
|
|
164
|
-
ext: 'md',
|
|
165
|
-
content: (0, kilo_1.toKiloConfig)(agent),
|
|
166
|
-
name: `${slug}.md`
|
|
167
|
-
},
|
|
168
|
-
{
|
|
169
|
-
id: 'opencode',
|
|
170
|
-
subDir: '.opencode/command',
|
|
171
|
-
ext: 'md',
|
|
172
|
-
content: (0, opencode_1.toOpenCodeCommand)(agent),
|
|
173
|
-
name: `${slug}.md`
|
|
174
|
-
}
|
|
175
|
-
];
|
|
176
|
-
const targetsToBuild = allTargets.filter((t) => selectedTargets.includes(t.id));
|
|
177
|
-
for (const target of targetsToBuild) {
|
|
178
|
-
const targetDir = path_1.default.join(outDir, target.subDir);
|
|
179
|
-
await fs_extra_1.default.ensureDir(targetDir);
|
|
180
|
-
await fs_extra_1.default.writeFile(path_1.default.join(targetDir, target.name), target.content);
|
|
181
|
-
console.log(chalk_1.default.gray(` -> ${target.subDir}/${target.name}`));
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
function logValidationErrors(source, error) {
|
|
185
|
-
console.error(chalk_1.default.red(`❌ Validation failed for ${source}:`));
|
|
186
|
-
error.issues.forEach((err) => {
|
|
187
|
-
console.error(chalk_1.default.red(` - ${err.path.join('.')}: ${err.message}`));
|
|
188
|
-
});
|
|
189
|
-
}
|
|
190
|
-
function toSlug(name) {
|
|
191
|
-
return name
|
|
192
|
-
.toLowerCase()
|
|
193
|
-
.replace(/[^\w\s-]/g, '') // remove non-word chars
|
|
194
|
-
.replace(/[\s_-]+/g, '-') // collapse whitespace/underscores to hyphens
|
|
195
|
-
.replace(/^-+|-+$/g, ''); // trim hyphens
|
|
196
|
-
}
|
package/dist/generators/docs.js
DELETED
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.generateWorkflowGuide = generateWorkflowGuide;
|
|
7
|
-
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
8
|
-
const path_1 = __importDefault(require("path"));
|
|
9
|
-
const chalk_1 = __importDefault(require("chalk"));
|
|
10
|
-
async function generateWorkflowGuide(docsDir, shell) {
|
|
11
|
-
const readmeContent = `# 🤖 Agent Workflow Guide
|
|
12
|
-
|
|
13
|
-
This document outlines the standard development flow using the installed Agents.
|
|
14
|
-
The system follows a **Waterfall-like** process relative to planning (to ensure precision) and an **Iterative** process for execution.
|
|
15
|
-
|
|
16
|
-
---
|
|
17
|
-
|
|
18
|
-
## 1. 🏗️ Project Spec (@Project Architect)
|
|
19
|
-
**Role:** The Visionary.
|
|
20
|
-
**Goal:** Translate your vague idea into a concrete Specification with defined "Project Principles" (Constitution).
|
|
21
|
-
- **Why?** To ensure the machine understands the "Soul" of the project (e.g., "Mobile First", "Minimalist").
|
|
22
|
-
- **Command:** \`/dev:project "I want a Todo App that..."\`
|
|
23
|
-
- **Output:** \`docs/project.md\`
|
|
24
|
-
|
|
25
|
-
## 2. 🧱 Requirements Engineering (@Requirements Engineer)
|
|
26
|
-
**Role:** The Tech Lead.
|
|
27
|
-
**Goal:** Lock down technical decisions (Stack, Database, Libraries) based on the Spec.
|
|
28
|
-
- **Why?** To prevent the Coder from "inventing" architecture on the fly. It creates a "Contract" of what to build.
|
|
29
|
-
- **Command:** \`/dev:requirements\`
|
|
30
|
-
- **Output:** \`docs/requirements.md\` (The Technical Contract)
|
|
31
|
-
|
|
32
|
-
## 3. 🗺️ Roadmap Strategy (@Milestone Manager)
|
|
33
|
-
**Role:** The Strategist.
|
|
34
|
-
**Goal:** Slice the project into logical delivery phases (MVPs).
|
|
35
|
-
- **Why?** To avoid "Big Bang" development. It organizes work into sequential milestones (e.g., "M1: Auth", "M2: Dashboard").
|
|
36
|
-
- **Command:** \`/dev:milestone\`
|
|
37
|
-
- **Output:** \`docs/milestones.md\`
|
|
38
|
-
|
|
39
|
-
## 4. 📋 Task Planning (@Task Planner)
|
|
40
|
-
**Role:** The Manager.
|
|
41
|
-
**Goal:** Break down a specific Milestone into atomic, developer-ready tasks.
|
|
42
|
-
- **Why?** AI coders fail with large contexts. Small, clear tasks = Perfect code.
|
|
43
|
-
- **Command:** \`/dev:tasks <Milestone_ID>\`
|
|
44
|
-
- **Output:** \`docs/task.md\`
|
|
45
|
-
|
|
46
|
-
## 5. 🕵️ Blueprint Audit (@Auditor)
|
|
47
|
-
**Role:** The Gatekeeper.
|
|
48
|
-
**Goal:** Validate consistency between **Requirements** (The Contract) and **Tasks** (The Plan).
|
|
49
|
-
- **Why?** To catch missing requirements or dangerous hallucinations *before* a single line of code is written.
|
|
50
|
-
- **Command:** \`/dev:auditor\`
|
|
51
|
-
- **Output:** \`audit_report.md\`
|
|
52
|
-
|
|
53
|
-
## 6. 💻 Implementation (@Coder)
|
|
54
|
-
**Role:** The Builder.
|
|
55
|
-
**Goal:** Execute *one task at a time* from the \`task.md\` file.
|
|
56
|
-
- **Why?** Focus. It reads the docs, writes the code (and tests), and logs progress.
|
|
57
|
-
- **Safeguards:** Checks for \`.gitignore\` and strictly follows \`requirements.md\`.
|
|
58
|
-
- **Command:** \`/dev:coder <Task_ID>\`
|
|
59
|
-
- **Buffer:** \`work_log.md\`
|
|
60
|
-
|
|
61
|
-
## 7. ⚖️ Quality Assurance (@QA Engineer)
|
|
62
|
-
**Role:** The Inspector.
|
|
63
|
-
**Goal:** Verify if the implementation matches the Requirement Artifacts.
|
|
64
|
-
- **Why?** Trust but verify. It reads the \`work_log.md\` and checks against expectations.
|
|
65
|
-
- **Command:** \`/dev:review <Task_ID>\`
|
|
66
|
-
- **Output:** \`docs/logs/review_log.md\`
|
|
67
|
-
|
|
68
|
-
## 8. 📦 Release Management (@Release Manager)
|
|
69
|
-
**Role:** The Historian.
|
|
70
|
-
**Goal:** Consolidate the temporary \`work_log.md\` into a permanent \`changelog.md\`.
|
|
71
|
-
- **Why?** To clean up the workspace and keep a professional history of the project.
|
|
72
|
-
- **Command:** \`/dev:log\`
|
|
73
|
-
- **Output:** \`changelog.md\`
|
|
74
|
-
|
|
75
|
-
---
|
|
76
|
-
|
|
77
|
-
## 🛠️ On-Demand Utilities
|
|
78
|
-
|
|
79
|
-
### Infrastructure (@DevOps Engineer)
|
|
80
|
-
**Role:** The Mechanic.
|
|
81
|
-
**Goal:** Handle "Config Hell" (Docker, CI/CD, Linters).
|
|
82
|
-
- **Why?** Keeps the Coder focused on business logic.
|
|
83
|
-
- **Command:** \`/dev:ops\`
|
|
84
|
-
`;
|
|
85
|
-
await fs_extra_1.default.ensureDir(docsDir);
|
|
86
|
-
await fs_extra_1.default.writeFile(path_1.default.join(docsDir, 'README.md'), readmeContent);
|
|
87
|
-
console.log(chalk_1.default.green(`✅ Created "docs/" directory (Optimized for ${shell}).\n`));
|
|
88
|
-
console.log(chalk_1.default.green(` -> Generated "docs/README.md" with workflow instructions.\n`));
|
|
89
|
-
}
|
package/dist/index.js
DELETED
|
@@ -1,160 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
"use strict";
|
|
3
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
4
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
5
|
-
};
|
|
6
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
-
const commander_1 = require("commander");
|
|
8
|
-
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
9
|
-
const path_1 = __importDefault(require("path"));
|
|
10
|
-
const chalk_1 = __importDefault(require("chalk"));
|
|
11
|
-
const inquirer_1 = __importDefault(require("inquirer"));
|
|
12
|
-
const docs_1 = require("./generators/docs");
|
|
13
|
-
const agents_1 = require("./generators/agents");
|
|
14
|
-
const program = new commander_1.Command();
|
|
15
|
-
program
|
|
16
|
-
.name('agents')
|
|
17
|
-
.description('Agent Installer CLI')
|
|
18
|
-
.version('1.0.4');
|
|
19
|
-
program.command('init')
|
|
20
|
-
.description('Initialize agents configuration interactively')
|
|
21
|
-
.option('-o, --out <dir>', 'Output directory', '.')
|
|
22
|
-
.option('-i, --input <path>', 'Input file or directory (default: definitions/ or agents.md)')
|
|
23
|
-
.option('-t, --target <targets>', 'Comma-separated target formats (gemini, roo, kilo, opencode)')
|
|
24
|
-
.action(async (options) => {
|
|
25
|
-
// Safety check for non-interactive environments (CI/CD)
|
|
26
|
-
if (!process.stdout.isTTY || process.env.CI === 'true' || process.env.CI === '1') {
|
|
27
|
-
console.log(chalk_1.default.yellow('Skipping interactive installer (non-interactive environment detected).'));
|
|
28
|
-
console.log(chalk_1.default.gray('Run "npx agents.dev" manually to configure your agents.'));
|
|
29
|
-
return;
|
|
30
|
-
}
|
|
31
|
-
try {
|
|
32
|
-
console.log(chalk_1.default.bold.blue('\n🚀 Agents.dev Installer Wizard\n'));
|
|
33
|
-
// --- STEP 1: INITIALIZATION (Docs & Shell) ---
|
|
34
|
-
const docsDir = path_1.default.join(process.cwd(), 'docs');
|
|
35
|
-
// Check if docs directory exists
|
|
36
|
-
if (!(await fs_extra_1.default.pathExists(docsDir))) {
|
|
37
|
-
console.log(chalk_1.default.yellow('ℹ️ Project documentation structure not found.'));
|
|
38
|
-
const initAnswers = await inquirer_1.default.prompt([
|
|
39
|
-
{
|
|
40
|
-
type: 'list',
|
|
41
|
-
name: 'shell',
|
|
42
|
-
message: 'Initialize validation: Which shell do you use?',
|
|
43
|
-
choices: [
|
|
44
|
-
{ name: 'Windows (CMD/PowerShell)', value: 'win32' },
|
|
45
|
-
{ name: 'Unix-like (Bash/Zsh/Ubuntu)', value: 'unix' }
|
|
46
|
-
]
|
|
47
|
-
}
|
|
48
|
-
]);
|
|
49
|
-
await (0, docs_1.generateWorkflowGuide)(docsDir, initAnswers.shell);
|
|
50
|
-
}
|
|
51
|
-
else {
|
|
52
|
-
console.log(chalk_1.default.gray('✅ "docs/" directory already exists.\n'));
|
|
53
|
-
}
|
|
54
|
-
// --- STEP 2: BUILD AGENTS ---
|
|
55
|
-
let inputPath = options.input ? path_1.default.resolve(options.input) : path_1.default.join(process.cwd(), 'definitions');
|
|
56
|
-
// If default definitions dir doesn't exist and no input specified, try agents.md
|
|
57
|
-
if (!options.input && !(await fs_extra_1.default.pathExists(inputPath))) {
|
|
58
|
-
const localAgentsMd = path_1.default.join(process.cwd(), 'agents.md');
|
|
59
|
-
if (await fs_extra_1.default.pathExists(localAgentsMd)) {
|
|
60
|
-
inputPath = localAgentsMd;
|
|
61
|
-
console.log(chalk_1.default.gray(`ℹ️ Using 'agents.md' found in root.`));
|
|
62
|
-
}
|
|
63
|
-
else {
|
|
64
|
-
// Fallback: Check if we are running from the installed package and definitions exist there
|
|
65
|
-
const packageDefinitions = path_1.default.join(__dirname, '../definitions');
|
|
66
|
-
if (await fs_extra_1.default.pathExists(packageDefinitions)) {
|
|
67
|
-
inputPath = packageDefinitions;
|
|
68
|
-
// console.log(chalk.gray(`ℹ️ Using default definitions from package.`));
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
const outDir = path_1.default.resolve(options.out);
|
|
73
|
-
// Determine targets
|
|
74
|
-
let selectedTargets = [];
|
|
75
|
-
if (options.target) {
|
|
76
|
-
selectedTargets = options.target.split(',').map((t) => t.trim().toLowerCase());
|
|
77
|
-
}
|
|
78
|
-
else {
|
|
79
|
-
const buildAnswers = await inquirer_1.default.prompt([
|
|
80
|
-
{
|
|
81
|
-
type: 'checkbox',
|
|
82
|
-
name: 'targets',
|
|
83
|
-
message: 'Select target formats to build:',
|
|
84
|
-
choices: [
|
|
85
|
-
{ name: 'Gemini CLI', value: 'gemini', checked: true },
|
|
86
|
-
{ name: 'Roo Code', value: 'roo', checked: false },
|
|
87
|
-
{ name: 'Kilo Code', value: 'kilo', checked: false },
|
|
88
|
-
{ name: 'OpenCode', value: 'opencode', checked: false }
|
|
89
|
-
],
|
|
90
|
-
validate: (answer) => {
|
|
91
|
-
if (answer.length < 1) {
|
|
92
|
-
return 'You must choose at least one target.';
|
|
93
|
-
}
|
|
94
|
-
return true;
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
]);
|
|
98
|
-
selectedTargets = buildAnswers.targets;
|
|
99
|
-
}
|
|
100
|
-
if (selectedTargets.length === 0) {
|
|
101
|
-
console.log(chalk_1.default.yellow('No targets selected. Exiting.'));
|
|
102
|
-
return;
|
|
103
|
-
}
|
|
104
|
-
// --- STEP 3: SELECT AGENTS ---
|
|
105
|
-
let selectedAgents = undefined;
|
|
106
|
-
const availableAgents = await (0, agents_1.getAvailableAgents)(inputPath);
|
|
107
|
-
if (availableAgents.length > 0) {
|
|
108
|
-
const agentSelection = await inquirer_1.default.prompt([
|
|
109
|
-
{
|
|
110
|
-
type: 'list',
|
|
111
|
-
name: 'mode',
|
|
112
|
-
message: 'How do you want to install agents?',
|
|
113
|
-
choices: [
|
|
114
|
-
{ name: 'Install All Standard Agents (Recommended)', value: 'all' },
|
|
115
|
-
{ name: 'Custom Selection', value: 'custom' }
|
|
116
|
-
]
|
|
117
|
-
},
|
|
118
|
-
{
|
|
119
|
-
type: 'checkbox',
|
|
120
|
-
name: 'agents',
|
|
121
|
-
message: 'Select agents to install:',
|
|
122
|
-
choices: availableAgents.map((a) => ({
|
|
123
|
-
name: a.description ? `${a.name} - ${chalk_1.default.gray(a.description)}` : a.name,
|
|
124
|
-
value: a.slug,
|
|
125
|
-
checked: true
|
|
126
|
-
})),
|
|
127
|
-
when: (answers) => answers.mode === 'custom',
|
|
128
|
-
validate: (answer) => {
|
|
129
|
-
if (answer.length < 1) {
|
|
130
|
-
return 'You must choose at least one agent.';
|
|
131
|
-
}
|
|
132
|
-
return true;
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
]);
|
|
136
|
-
if (agentSelection.mode === 'custom') {
|
|
137
|
-
selectedAgents = agentSelection.agents;
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
await (0, agents_1.generateAgents)(inputPath, outDir, selectedTargets, selectedAgents);
|
|
141
|
-
}
|
|
142
|
-
catch (error) {
|
|
143
|
-
if (error.isTtyError) {
|
|
144
|
-
console.log(chalk_1.default.yellow('Interactive prompt not supported in this environment.'));
|
|
145
|
-
}
|
|
146
|
-
else if (error.message.includes('User force closed')) {
|
|
147
|
-
console.log(chalk_1.default.yellow('\nInstallation cancelled by user.'));
|
|
148
|
-
}
|
|
149
|
-
else {
|
|
150
|
-
console.error(chalk_1.default.red('\nAn error occurred during installation:'), error.message);
|
|
151
|
-
}
|
|
152
|
-
// Always exit with 0 to prevent npm install from failing loudly
|
|
153
|
-
process.exit(0);
|
|
154
|
-
}
|
|
155
|
-
});
|
|
156
|
-
// Default command (show help if no command)
|
|
157
|
-
program.action(() => {
|
|
158
|
-
program.help();
|
|
159
|
-
});
|
|
160
|
-
program.parse(process.argv);
|
package/dist/parsers/markdown.js
DELETED
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.parseMarkdownAgents = parseMarkdownAgents;
|
|
4
|
-
function parseMarkdownAgents(content) {
|
|
5
|
-
const agents = [];
|
|
6
|
-
// Normalize line endings
|
|
7
|
-
const normalized = content.replace(/\r\n/g, '\n');
|
|
8
|
-
// Split by H1 headers (# Name)
|
|
9
|
-
// We use a lookahead to keep the delimiter or just split and ignore the first empty part if it starts with #
|
|
10
|
-
const parts = normalized.split(/^# /gm);
|
|
11
|
-
for (const part of parts) {
|
|
12
|
-
if (!part.trim())
|
|
13
|
-
continue;
|
|
14
|
-
const lines = part.split('\n');
|
|
15
|
-
const headerLine = lines[0].trim();
|
|
16
|
-
// Extract emoji if present at the end
|
|
17
|
-
// E.g. "Project Manager 👩💼" -> name: "Project Manager", emoji: "👩💼"
|
|
18
|
-
// Simple emoji regex or just take the last char if it looks like an emoji?
|
|
19
|
-
// Let's generic split by space and check if last part is emoji-like or just treat whole as name
|
|
20
|
-
// A simplified approach: regex for emoji is complex, let's just grab the whole string as name for now,
|
|
21
|
-
// or try to extract the last non-word character if it looks like a symbol.
|
|
22
|
-
// Spec said: "# Agent Name [Emoji]"
|
|
23
|
-
const emojiMatch = headerLine.match(/^(.*?)\s+([^\w\s\d]+)$/);
|
|
24
|
-
let name = headerLine;
|
|
25
|
-
let emoji = '';
|
|
26
|
-
if (emojiMatch) {
|
|
27
|
-
name = emojiMatch[1].trim();
|
|
28
|
-
emoji = emojiMatch[2].trim();
|
|
29
|
-
}
|
|
30
|
-
const remainingLines = lines.slice(1);
|
|
31
|
-
const sectionContent = remainingLines.join('\n');
|
|
32
|
-
// Parse sections
|
|
33
|
-
// > Role
|
|
34
|
-
// ## System Prompt
|
|
35
|
-
// ## Rules
|
|
36
|
-
// ## Tools
|
|
37
|
-
let role = '';
|
|
38
|
-
let systemPrompt = '';
|
|
39
|
-
const rules = [];
|
|
40
|
-
const tools = [];
|
|
41
|
-
// Extract Role (Blockquote)
|
|
42
|
-
const roleMatch = sectionContent.match(/^\s*>\s*(.+)$/m);
|
|
43
|
-
if (roleMatch) {
|
|
44
|
-
role = roleMatch[1].trim();
|
|
45
|
-
}
|
|
46
|
-
// specific sections
|
|
47
|
-
const sections = sectionContent.split(/^## /gm);
|
|
48
|
-
for (const section of sections) {
|
|
49
|
-
const trimmed = section.trim();
|
|
50
|
-
if (!trimmed)
|
|
51
|
-
continue;
|
|
52
|
-
const sectionLines = trimmed.split('\n');
|
|
53
|
-
const sectionTitle = sectionLines[0].trim().toLowerCase();
|
|
54
|
-
const sectionBody = sectionLines.slice(1).join('\n').trim();
|
|
55
|
-
if (sectionTitle.includes('system prompt') || sectionTitle.includes('instructions')) {
|
|
56
|
-
systemPrompt = sectionBody;
|
|
57
|
-
}
|
|
58
|
-
else if (sectionTitle.includes('rules')) {
|
|
59
|
-
// Extract bullets
|
|
60
|
-
const bullets = sectionBody.split('\n')
|
|
61
|
-
.map(l => l.trim())
|
|
62
|
-
.filter(l => l.startsWith('- ') || l.startsWith('* '))
|
|
63
|
-
.map(l => l.substring(2).trim());
|
|
64
|
-
rules.push(...bullets);
|
|
65
|
-
}
|
|
66
|
-
else if (sectionTitle.includes('tools')) {
|
|
67
|
-
const bullets = sectionBody.split('\n')
|
|
68
|
-
.map(l => l.trim())
|
|
69
|
-
.filter(l => l.startsWith('- ') || l.startsWith('* '))
|
|
70
|
-
.map(l => l.substring(2).trim());
|
|
71
|
-
tools.push(...bullets);
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
if (name) {
|
|
75
|
-
agents.push({
|
|
76
|
-
name,
|
|
77
|
-
role,
|
|
78
|
-
emoji,
|
|
79
|
-
systemPrompt,
|
|
80
|
-
rules,
|
|
81
|
-
tools
|
|
82
|
-
});
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
return agents;
|
|
86
|
-
}
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.toGeminiSystemPrompt = toGeminiSystemPrompt;
|
|
4
|
-
function toGeminiSystemPrompt(agent) {
|
|
5
|
-
// Construct the prompt content (System Prompt + Rules + Tools)
|
|
6
|
-
const promptParts = [];
|
|
7
|
-
// Identity logic is usually part of the prompt in this TOML structure
|
|
8
|
-
promptParts.push(`# Identity`);
|
|
9
|
-
promptParts.push(`You are **${agent.name}** ${agent.emoji || ''}`);
|
|
10
|
-
promptParts.push(`Role: ${agent.role}\n`);
|
|
11
|
-
promptParts.push(`# Core Instructions`);
|
|
12
|
-
promptParts.push(agent.systemPrompt.trim());
|
|
13
|
-
promptParts.push('\n');
|
|
14
|
-
if (agent.rules && agent.rules.length > 0) {
|
|
15
|
-
promptParts.push(`# Rules & Guidelines`);
|
|
16
|
-
agent.rules.forEach(rule => promptParts.push(`- ${rule}`));
|
|
17
|
-
promptParts.push('\n');
|
|
18
|
-
}
|
|
19
|
-
if (agent.tools && agent.tools.length > 0) {
|
|
20
|
-
promptParts.push(`# Preferred Tools`);
|
|
21
|
-
agent.tools.forEach(tool => promptParts.push(`- ${tool}`));
|
|
22
|
-
promptParts.push('\n');
|
|
23
|
-
}
|
|
24
|
-
const fullPrompt = promptParts.join('\n');
|
|
25
|
-
// Manual TOML construction
|
|
26
|
-
// 1. description = "..."
|
|
27
|
-
// Basic escaping for double quotes
|
|
28
|
-
const escapedDescription = agent.role.replace(/"/g, '\\"');
|
|
29
|
-
// 2. prompt = """..."""
|
|
30
|
-
// Escape triple quotes if they exist in the content (rare but possible)
|
|
31
|
-
const escapedPrompt = fullPrompt.replace(/"""/g, '\\"\\"\\"');
|
|
32
|
-
return `description = "${escapedDescription}"
|
|
33
|
-
prompt = """
|
|
34
|
-
${escapedPrompt}
|
|
35
|
-
"""`;
|
|
36
|
-
}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.toKiloConfig = toKiloConfig;
|
|
4
|
-
function toKiloConfig(agent) {
|
|
5
|
-
// Kilo Code generic config/prompt
|
|
6
|
-
const parts = [];
|
|
7
|
-
parts.push(`<!--- Kilo Code Agent Config --->`);
|
|
8
|
-
parts.push(`# ${agent.name} ${agent.emoji || ''}`);
|
|
9
|
-
parts.push(`**Role**: ${agent.role}\n`);
|
|
10
|
-
parts.push(`## Instructions`);
|
|
11
|
-
parts.push(agent.systemPrompt.trim());
|
|
12
|
-
parts.push('\n');
|
|
13
|
-
if (agent.rules && agent.rules.length > 0) {
|
|
14
|
-
parts.push(`## Constraints`);
|
|
15
|
-
agent.rules.forEach(rule => parts.push(`- ${rule}`));
|
|
16
|
-
}
|
|
17
|
-
return parts.join('\n');
|
|
18
|
-
}
|