@esotech/contextuate 2.0.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.
Files changed (62) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +287 -0
  3. package/dist/commands/context.js +80 -0
  4. package/dist/commands/create.js +93 -0
  5. package/dist/commands/index.js +46 -0
  6. package/dist/commands/init.js +452 -0
  7. package/dist/commands/install.js +359 -0
  8. package/dist/commands/remove.js +77 -0
  9. package/dist/commands/run.js +205 -0
  10. package/dist/index.js +96 -0
  11. package/dist/runtime/driver.js +64 -0
  12. package/dist/runtime/tools.js +48 -0
  13. package/dist/templates/README.md +152 -0
  14. package/dist/templates/agents/aegis.md +366 -0
  15. package/dist/templates/agents/archon.md +247 -0
  16. package/dist/templates/agents/atlas.md +326 -0
  17. package/dist/templates/agents/canvas.md +19 -0
  18. package/dist/templates/agents/chronicle.md +424 -0
  19. package/dist/templates/agents/chronos.md +20 -0
  20. package/dist/templates/agents/cipher.md +360 -0
  21. package/dist/templates/agents/crucible.md +375 -0
  22. package/dist/templates/agents/echo.md +297 -0
  23. package/dist/templates/agents/forge.md +613 -0
  24. package/dist/templates/agents/ledger.md +317 -0
  25. package/dist/templates/agents/meridian.md +281 -0
  26. package/dist/templates/agents/nexus.md +600 -0
  27. package/dist/templates/agents/oracle.md +281 -0
  28. package/dist/templates/agents/scribe.md +612 -0
  29. package/dist/templates/agents/sentinel.md +312 -0
  30. package/dist/templates/agents/unity.md +17 -0
  31. package/dist/templates/agents/vox.md +19 -0
  32. package/dist/templates/agents/weaver.md +334 -0
  33. package/dist/templates/framework-agents/base.md +166 -0
  34. package/dist/templates/framework-agents/documentation-expert.md +292 -0
  35. package/dist/templates/framework-agents/tools-expert.md +245 -0
  36. package/dist/templates/standards/agent-roles.md +34 -0
  37. package/dist/templates/standards/agent-workflow.md +170 -0
  38. package/dist/templates/standards/behavioral-guidelines.md +145 -0
  39. package/dist/templates/standards/coding-standards.md +171 -0
  40. package/dist/templates/standards/task-workflow.md +246 -0
  41. package/dist/templates/templates/context.md +33 -0
  42. package/dist/templates/templates/contextuate.md +109 -0
  43. package/dist/templates/templates/platforms/AGENTS.md +5 -0
  44. package/dist/templates/templates/platforms/CLAUDE.md +5 -0
  45. package/dist/templates/templates/platforms/GEMINI.md +5 -0
  46. package/dist/templates/templates/platforms/clinerules.md +5 -0
  47. package/dist/templates/templates/platforms/copilot.md +5 -0
  48. package/dist/templates/templates/platforms/cursor.mdc +9 -0
  49. package/dist/templates/templates/platforms/windsurf.md +5 -0
  50. package/dist/templates/templates/standards/go.standards.md +167 -0
  51. package/dist/templates/templates/standards/java.standards.md +167 -0
  52. package/dist/templates/templates/standards/javascript.standards.md +292 -0
  53. package/dist/templates/templates/standards/php.standards.md +181 -0
  54. package/dist/templates/templates/standards/python.standards.md +175 -0
  55. package/dist/templates/tools/agent-creator.tool.md +252 -0
  56. package/dist/templates/tools/quickref.tool.md +216 -0
  57. package/dist/templates/tools/spawn.tool.md +31 -0
  58. package/dist/templates/tools/standards-detector.tool.md +301 -0
  59. package/dist/templates/version.json +8 -0
  60. package/dist/utils/git.js +62 -0
  61. package/dist/utils/tokens.js +74 -0
  62. package/package.json +59 -0
@@ -0,0 +1,359 @@
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.installAgentsCommand = installAgentsCommand;
7
+ exports.installStandardsCommand = installStandardsCommand;
8
+ exports.installToolsCommand = installToolsCommand;
9
+ exports.installCommand = installCommand;
10
+ const inquirer_1 = __importDefault(require("inquirer"));
11
+ const chalk_1 = __importDefault(require("chalk"));
12
+ const fs_extra_1 = __importDefault(require("fs-extra"));
13
+ const path_1 = __importDefault(require("path"));
14
+ // Get template source directory
15
+ function getTemplateSource() {
16
+ let templateSource = path_1.default.join(__dirname, '../templates');
17
+ // Handle ts-node vs compiled paths
18
+ if (path_1.default.basename(path_1.default.join(__dirname, '..')) === 'src') {
19
+ templateSource = path_1.default.join(__dirname, '../../src/templates');
20
+ }
21
+ else if (path_1.default.basename(__dirname) === 'commands') {
22
+ templateSource = path_1.default.join(__dirname, '../templates');
23
+ }
24
+ if (!fs_extra_1.default.existsSync(templateSource)) {
25
+ templateSource = path_1.default.join(__dirname, '../../templates');
26
+ }
27
+ return templateSource;
28
+ }
29
+ // Discover available templates
30
+ async function discoverTemplates() {
31
+ const templateSource = getTemplateSource();
32
+ const result = {
33
+ agents: [],
34
+ standards: [],
35
+ tools: [],
36
+ };
37
+ // Discover agents
38
+ const agentDir = path_1.default.join(templateSource, 'agents');
39
+ if (fs_extra_1.default.existsSync(agentDir)) {
40
+ const files = await fs_extra_1.default.readdir(agentDir);
41
+ result.agents = files
42
+ .filter(f => f.endsWith('.md'))
43
+ .map(f => f.replace('.md', ''));
44
+ }
45
+ // Discover language standards
46
+ const standardsDir = path_1.default.join(templateSource, 'templates/standards');
47
+ if (fs_extra_1.default.existsSync(standardsDir)) {
48
+ const files = await fs_extra_1.default.readdir(standardsDir);
49
+ result.standards = files
50
+ .filter(f => f.endsWith('.standards.md'))
51
+ .map(f => f.replace('.standards.md', ''));
52
+ }
53
+ // Discover tools
54
+ const toolsDir = path_1.default.join(templateSource, 'tools');
55
+ if (fs_extra_1.default.existsSync(toolsDir)) {
56
+ const files = await fs_extra_1.default.readdir(toolsDir);
57
+ result.tools = files
58
+ .filter(f => f.endsWith('.tool.md'))
59
+ .map(f => f.replace('.tool.md', ''));
60
+ }
61
+ return result;
62
+ }
63
+ // List available templates
64
+ async function listTemplates() {
65
+ const templates = await discoverTemplates();
66
+ console.log(chalk_1.default.blue('\nAvailable Templates:\n'));
67
+ console.log(chalk_1.default.cyan('Agents:'));
68
+ if (templates.agents.length > 0) {
69
+ templates.agents.forEach(a => console.log(` - ${a}`));
70
+ }
71
+ else {
72
+ console.log(' (none found)');
73
+ }
74
+ console.log(chalk_1.default.cyan('\nLanguage Standards:'));
75
+ if (templates.standards.length > 0) {
76
+ templates.standards.forEach(s => console.log(` - ${s}`));
77
+ }
78
+ else {
79
+ console.log(' (none found)');
80
+ }
81
+ console.log(chalk_1.default.cyan('\nTools:'));
82
+ if (templates.tools.length > 0) {
83
+ templates.tools.forEach(t => console.log(` - ${t}`));
84
+ }
85
+ else {
86
+ console.log(' (none found)');
87
+ }
88
+ console.log('');
89
+ }
90
+ // Copy helper
91
+ async function copyFile(src, dest, force) {
92
+ const absSrc = path_1.default.resolve(src);
93
+ const absDest = path_1.default.resolve(dest);
94
+ if (absSrc === absDest) {
95
+ return false;
96
+ }
97
+ if (!fs_extra_1.default.existsSync(src)) {
98
+ console.log(chalk_1.default.red(`[ERROR] Source file missing: ${src}`));
99
+ return false;
100
+ }
101
+ if (fs_extra_1.default.existsSync(dest) && !force) {
102
+ console.log(chalk_1.default.yellow(`[SKIP] Already exists: ${dest}`));
103
+ return false;
104
+ }
105
+ await fs_extra_1.default.ensureDir(path_1.default.dirname(dest));
106
+ await fs_extra_1.default.copy(src, dest);
107
+ console.log(chalk_1.default.green(`[OK] Installed: ${dest}`));
108
+ return true;
109
+ }
110
+ // Install agents
111
+ async function installAgents(names, force) {
112
+ const templateSource = getTemplateSource();
113
+ const templates = await discoverTemplates();
114
+ let installed = 0;
115
+ for (const name of names) {
116
+ const normalized = name.toLowerCase().trim();
117
+ const matched = templates.agents.find(a => a.toLowerCase() === normalized);
118
+ if (matched) {
119
+ const src = path_1.default.join(templateSource, 'agents', `${matched}.md`);
120
+ const dest = path_1.default.join('docs/ai/agents', `${matched}.md`);
121
+ if (await copyFile(src, dest, force)) {
122
+ installed++;
123
+ }
124
+ }
125
+ else {
126
+ console.log(chalk_1.default.yellow(`[WARN] Agent "${name}" not found. Use --list to see available agents.`));
127
+ }
128
+ }
129
+ return installed;
130
+ }
131
+ // Install language standards
132
+ async function installStandards(names, force) {
133
+ const templateSource = getTemplateSource();
134
+ const templates = await discoverTemplates();
135
+ let installed = 0;
136
+ for (const name of names) {
137
+ const normalized = name.toLowerCase().trim();
138
+ const matched = templates.standards.find(s => s.toLowerCase() === normalized);
139
+ if (matched) {
140
+ const src = path_1.default.join(templateSource, 'templates/standards', `${matched}.standards.md`);
141
+ const dest = path_1.default.join('docs/ai/standards', `${matched}.standards.md`);
142
+ if (await copyFile(src, dest, force)) {
143
+ installed++;
144
+ }
145
+ }
146
+ else {
147
+ console.log(chalk_1.default.yellow(`[WARN] Standard "${name}" not found. Use --list to see available standards.`));
148
+ }
149
+ }
150
+ return installed;
151
+ }
152
+ // Install tools
153
+ async function installTools(names, force) {
154
+ const templateSource = getTemplateSource();
155
+ const templates = await discoverTemplates();
156
+ let installed = 0;
157
+ for (const name of names) {
158
+ const normalized = name.toLowerCase().trim();
159
+ const matched = templates.tools.find(t => t.toLowerCase() === normalized);
160
+ if (matched) {
161
+ const src = path_1.default.join(templateSource, 'tools', `${matched}.tool.md`);
162
+ const dest = path_1.default.join('docs/ai/.contextuate/tools', `${matched}.tool.md`);
163
+ if (await copyFile(src, dest, force)) {
164
+ installed++;
165
+ }
166
+ }
167
+ else {
168
+ console.log(chalk_1.default.yellow(`[WARN] Tool "${name}" not found. Use --list to see available tools.`));
169
+ }
170
+ }
171
+ return installed;
172
+ }
173
+ // Subcommand handlers
174
+ async function installAgentsCommand(names, options) {
175
+ const templates = await discoverTemplates();
176
+ const useAll = options.all || names.includes('all');
177
+ const agentsToInstall = useAll ? templates.agents : names;
178
+ if (agentsToInstall.length === 0) {
179
+ console.log(chalk_1.default.yellow('No agents specified. Use "all" or provide agent names.'));
180
+ console.log(chalk_1.default.gray('Available agents:'));
181
+ templates.agents.forEach(a => console.log(` - ${a}`));
182
+ return;
183
+ }
184
+ console.log(chalk_1.default.blue('\n[INFO] Installing agents...\n'));
185
+ const count = await installAgents(agentsToInstall, options.force || false);
186
+ console.log(chalk_1.default.green(`\n[OK] Installed ${count} agent(s)\n`));
187
+ }
188
+ async function installStandardsCommand(names, options) {
189
+ const templates = await discoverTemplates();
190
+ const useAll = options.all || names.includes('all');
191
+ const standardsToInstall = useAll ? templates.standards : names;
192
+ if (standardsToInstall.length === 0) {
193
+ console.log(chalk_1.default.yellow('No standards specified. Use "all" or provide language names.'));
194
+ console.log(chalk_1.default.gray('Available standards:'));
195
+ templates.standards.forEach(s => console.log(` - ${s}`));
196
+ return;
197
+ }
198
+ console.log(chalk_1.default.blue('\n[INFO] Installing language standards...\n'));
199
+ const count = await installStandards(standardsToInstall, options.force || false);
200
+ console.log(chalk_1.default.green(`\n[OK] Installed ${count} standard(s)\n`));
201
+ }
202
+ async function installToolsCommand(names, options) {
203
+ const templates = await discoverTemplates();
204
+ const useAll = options.all || names.includes('all');
205
+ const toolsToInstall = useAll ? templates.tools : names;
206
+ if (toolsToInstall.length === 0) {
207
+ console.log(chalk_1.default.yellow('No tools specified. Use "all" or provide tool names.'));
208
+ console.log(chalk_1.default.gray('Available tools:'));
209
+ templates.tools.forEach(t => console.log(` - ${t}`));
210
+ return;
211
+ }
212
+ console.log(chalk_1.default.blue('\n[INFO] Installing tools...\n'));
213
+ const count = await installTools(toolsToInstall, options.force || false);
214
+ console.log(chalk_1.default.green(`\n[OK] Installed ${count} tool(s)\n`));
215
+ }
216
+ // Main install command (flag style or interactive)
217
+ async function installCommand(options) {
218
+ // Handle --list flag
219
+ if (options.list) {
220
+ await listTemplates();
221
+ return;
222
+ }
223
+ const templates = await discoverTemplates();
224
+ const force = options.force || false;
225
+ // Check if any flags were provided
226
+ const hasFlags = options.agents || options.standards || options.tools || options.all;
227
+ if (!hasFlags) {
228
+ // Interactive mode
229
+ try {
230
+ const { categories } = await inquirer_1.default.prompt([
231
+ {
232
+ type: 'checkbox',
233
+ name: 'categories',
234
+ message: 'What would you like to install?',
235
+ choices: [
236
+ { name: 'Agents (AI persona definitions)', value: 'agents' },
237
+ { name: 'Language Standards (coding guidelines)', value: 'standards' },
238
+ { name: 'Tools (AI tool guides)', value: 'tools' },
239
+ ],
240
+ validate: (answer) => {
241
+ if (answer.length < 1) {
242
+ return 'Select at least one category.';
243
+ }
244
+ return true;
245
+ },
246
+ },
247
+ ]);
248
+ let selectedAgents = [];
249
+ let selectedStandards = [];
250
+ let selectedTools = [];
251
+ if (categories.includes('agents') && templates.agents.length > 0) {
252
+ const { agents } = await inquirer_1.default.prompt([
253
+ {
254
+ type: 'checkbox',
255
+ name: 'agents',
256
+ message: 'Select agents to install:',
257
+ choices: [
258
+ { name: 'Select All', value: '__all__' },
259
+ new inquirer_1.default.Separator(),
260
+ ...templates.agents.map(a => ({
261
+ name: a.split('-').map(w => w.charAt(0).toUpperCase() + w.slice(1)).join(' '),
262
+ value: a,
263
+ })),
264
+ ],
265
+ },
266
+ ]);
267
+ selectedAgents = agents.includes('__all__') ? templates.agents : agents;
268
+ }
269
+ if (categories.includes('standards') && templates.standards.length > 0) {
270
+ const { standards } = await inquirer_1.default.prompt([
271
+ {
272
+ type: 'checkbox',
273
+ name: 'standards',
274
+ message: 'Select language standards to install:',
275
+ choices: [
276
+ { name: 'Select All', value: '__all__' },
277
+ new inquirer_1.default.Separator(),
278
+ ...templates.standards.map(s => ({
279
+ name: s.charAt(0).toUpperCase() + s.slice(1),
280
+ value: s,
281
+ })),
282
+ ],
283
+ },
284
+ ]);
285
+ selectedStandards = standards.includes('__all__') ? templates.standards : standards;
286
+ }
287
+ if (categories.includes('tools') && templates.tools.length > 0) {
288
+ const { tools } = await inquirer_1.default.prompt([
289
+ {
290
+ type: 'checkbox',
291
+ name: 'tools',
292
+ message: 'Select tools to install:',
293
+ choices: [
294
+ { name: 'Select All', value: '__all__' },
295
+ new inquirer_1.default.Separator(),
296
+ ...templates.tools.map(t => ({
297
+ name: t.split('-').map(w => w.charAt(0).toUpperCase() + w.slice(1)).join(' '),
298
+ value: t,
299
+ })),
300
+ ],
301
+ },
302
+ ]);
303
+ selectedTools = tools.includes('__all__') ? templates.tools : tools;
304
+ }
305
+ // Install selected items
306
+ let totalInstalled = 0;
307
+ if (selectedAgents.length > 0) {
308
+ console.log(chalk_1.default.blue('\n[INFO] Installing agents...'));
309
+ totalInstalled += await installAgents(selectedAgents, force);
310
+ }
311
+ if (selectedStandards.length > 0) {
312
+ console.log(chalk_1.default.blue('\n[INFO] Installing language standards...'));
313
+ totalInstalled += await installStandards(selectedStandards, force);
314
+ }
315
+ if (selectedTools.length > 0) {
316
+ console.log(chalk_1.default.blue('\n[INFO] Installing tools...'));
317
+ totalInstalled += await installTools(selectedTools, force);
318
+ }
319
+ console.log(chalk_1.default.green(`\n[OK] Installation complete. ${totalInstalled} file(s) installed.\n`));
320
+ }
321
+ catch (error) {
322
+ if (error.name === 'ExitPromptError' || error.message?.includes('User force closed')) {
323
+ console.log(chalk_1.default.yellow('\nInstallation cancelled.'));
324
+ process.exit(0);
325
+ }
326
+ throw error;
327
+ }
328
+ }
329
+ else {
330
+ // Flag-based mode
331
+ let totalInstalled = 0;
332
+ // Handle --all flag
333
+ if (options.all) {
334
+ console.log(chalk_1.default.blue('\n[INFO] Installing all templates...\n'));
335
+ totalInstalled += await installAgents(templates.agents, force);
336
+ totalInstalled += await installStandards(templates.standards, force);
337
+ totalInstalled += await installTools(templates.tools, force);
338
+ }
339
+ else {
340
+ // Handle individual flags
341
+ if (options.agents && options.agents.length > 0) {
342
+ const agentsToInstall = options.agents.includes('all') ? templates.agents : options.agents;
343
+ console.log(chalk_1.default.blue('\n[INFO] Installing agents...'));
344
+ totalInstalled += await installAgents(agentsToInstall, force);
345
+ }
346
+ if (options.standards && options.standards.length > 0) {
347
+ const standardsToInstall = options.standards.includes('all') ? templates.standards : options.standards;
348
+ console.log(chalk_1.default.blue('\n[INFO] Installing language standards...'));
349
+ totalInstalled += await installStandards(standardsToInstall, force);
350
+ }
351
+ if (options.tools && options.tools.length > 0) {
352
+ const toolsToInstall = options.tools.includes('all') ? templates.tools : options.tools;
353
+ console.log(chalk_1.default.blue('\n[INFO] Installing tools...'));
354
+ totalInstalled += await installTools(toolsToInstall, force);
355
+ }
356
+ }
357
+ console.log(chalk_1.default.green(`\n[OK] Installation complete. ${totalInstalled} file(s) installed.\n`));
358
+ }
359
+ }
@@ -0,0 +1,77 @@
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.removeCommand = removeCommand;
7
+ const chalk_1 = __importDefault(require("chalk"));
8
+ const fs_extra_1 = __importDefault(require("fs-extra"));
9
+ const path_1 = __importDefault(require("path"));
10
+ const crypto_1 = __importDefault(require("crypto"));
11
+ async function removeCommand(options) {
12
+ console.log(chalk_1.default.blue('╔════════════════════════════════════════╗'));
13
+ console.log(chalk_1.default.blue('║ Contextuate Cleanup ║'));
14
+ console.log(chalk_1.default.blue('╚════════════════════════════════════════╝'));
15
+ console.log('');
16
+ // Define source directory for templates
17
+ let templateSource = path_1.default.join(__dirname, '../../docs/ai/.contextuate');
18
+ if (!fs_extra_1.default.existsSync(templateSource)) {
19
+ templateSource = path_1.default.join(__dirname, '../../../docs/ai/.contextuate');
20
+ }
21
+ if (!fs_extra_1.default.existsSync(templateSource)) {
22
+ console.error(chalk_1.default.red(`[ERROR] Could not find template source at ${templateSource}`));
23
+ return;
24
+ }
25
+ // Define jump files to check
26
+ const jumpFiles = [
27
+ { src: 'templates/platforms/CLAUDE.md', dest: 'CLAUDE.md' },
28
+ { src: 'templates/platforms/AGENTS.md', dest: 'AGENTS.md' },
29
+ { src: 'templates/platforms/GEMINI.md', dest: 'GEMINI.md' },
30
+ { src: 'templates/platforms/clinerules.md', dest: '.clinerules/cline-memory-bank.md' },
31
+ { src: 'templates/platforms/copilot.md', dest: '.github/copilot-instructions.md' },
32
+ { src: 'templates/platforms/cursor.mdc', dest: '.cursor/rules/project.mdc' },
33
+ { src: 'templates/platforms/windsurf.md', dest: '.windsurf/rules/project.md' },
34
+ { src: 'templates/platforms/antigravity.md', dest: '.antigravity/rules.md' },
35
+ ];
36
+ const calculateHash = async (filePath) => {
37
+ const content = await fs_extra_1.default.readFile(filePath);
38
+ return crypto_1.default.createHash('sha256').update(content).digest('hex');
39
+ };
40
+ console.log(chalk_1.default.blue('[INFO] Checking for unmodified jump files...'));
41
+ for (const file of jumpFiles) {
42
+ const templatePath = path_1.default.join(templateSource, file.src);
43
+ const destPath = path_1.default.resolve(file.dest);
44
+ if (fs_extra_1.default.existsSync(destPath)) {
45
+ if (fs_extra_1.default.existsSync(templatePath)) {
46
+ try {
47
+ const templateHash = await calculateHash(templatePath);
48
+ const destHash = await calculateHash(destPath);
49
+ if (templateHash === destHash) {
50
+ await fs_extra_1.default.remove(destPath);
51
+ console.log(chalk_1.default.green(`[OK] Removed (unmodified): ${file.dest}`));
52
+ // Clean up empty parent directories if applicable
53
+ const dir = path_1.default.dirname(destPath);
54
+ if (dir !== process.cwd()) {
55
+ const files = await fs_extra_1.default.readdir(dir);
56
+ if (files.length === 0) {
57
+ await fs_extra_1.default.remove(dir);
58
+ console.log(chalk_1.default.gray(`[CLEAN] Removed empty directory: ${path_1.default.relative(process.cwd(), dir)}`));
59
+ }
60
+ }
61
+ }
62
+ else {
63
+ console.log(chalk_1.default.yellow(`[SKIP] Kept (modified): ${file.dest}`));
64
+ }
65
+ }
66
+ catch (error) {
67
+ console.error(chalk_1.default.red(`[ERROR] Failed to process ${file.dest}: ${error}`));
68
+ }
69
+ }
70
+ else {
71
+ console.warn(chalk_1.default.yellow(`[WARN] Template not found for comparison: ${file.src}`));
72
+ }
73
+ }
74
+ }
75
+ console.log('');
76
+ console.log(chalk_1.default.green('Cleanup complete!'));
77
+ }
@@ -0,0 +1,205 @@
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.runCommand = runCommand;
7
+ const chalk_1 = __importDefault(require("chalk"));
8
+ const fs_extra_1 = __importDefault(require("fs-extra"));
9
+ const path_1 = __importDefault(require("path"));
10
+ const gray_matter_1 = __importDefault(require("gray-matter"));
11
+ const git_1 = require("../utils/git");
12
+ const tokens_1 = require("../utils/tokens");
13
+ // ... imports
14
+ const driver_1 = require("../runtime/driver");
15
+ async function runCommand(agentName, options) {
16
+ console.log(chalk_1.default.blue(`[INFO] Launching Agent: ${agentName}`));
17
+ if (options.goal) {
18
+ console.log(chalk_1.default.bold('Goal: ') + options.goal);
19
+ }
20
+ // 1. Locate the agent file
21
+ const agentPath = path_1.default.join(process.cwd(), 'docs/ai/agents', `${agentName}.md`);
22
+ if (!fs_extra_1.default.existsSync(agentPath)) {
23
+ console.error(chalk_1.default.red(`[ERROR] Agent definition not found at: ${agentPath}`));
24
+ console.log(chalk_1.default.yellow(`Available agents:`));
25
+ try {
26
+ const files = await fs_extra_1.default.readdir(path_1.default.join(process.cwd(), 'docs/ai/agents'));
27
+ files.forEach(f => {
28
+ if (f.endsWith('.md')) {
29
+ console.log(`- ${f.replace('.md', '')}`);
30
+ }
31
+ });
32
+ }
33
+ catch (e) {
34
+ console.log(chalk_1.default.red('Could not list agents directory.'));
35
+ }
36
+ process.exit(1);
37
+ }
38
+ // 2. Parse the definition
39
+ let config;
40
+ try {
41
+ const fileContent = await fs_extra_1.default.readFile(agentPath, 'utf-8');
42
+ const parsed = (0, gray_matter_1.default)(fileContent);
43
+ config = parsed.data;
44
+ // Add default provider config if missing
45
+ if (!config.provider) {
46
+ config.provider = { type: 'mock', model: 'test' };
47
+ }
48
+ console.log(chalk_1.default.green(`[OK] Loaded agent definition`));
49
+ }
50
+ catch (error) {
51
+ console.error(chalk_1.default.red('[ERROR] Failed to parse agent definition:'), error);
52
+ process.exit(1);
53
+ }
54
+ // 3. Prepare Runtime
55
+ const git = new git_1.GitManager(process.cwd());
56
+ const isGit = await git.isGitRepo();
57
+ let runtimeCwd = process.cwd();
58
+ let sessionId = Date.now().toString();
59
+ if (options.isolation === 'worktree') {
60
+ if (!isGit) {
61
+ console.error(chalk_1.default.red('[ERROR] --isolation=worktree require a git repository.'));
62
+ process.exit(1);
63
+ }
64
+ console.log(chalk_1.default.blue('[INFO] Setting up Git Worktree...'));
65
+ try {
66
+ runtimeCwd = await git.createWorktree(config.name || agentName, sessionId);
67
+ console.log(chalk_1.default.green(`[OK] Worktree created at: ${runtimeCwd}`));
68
+ }
69
+ catch (e) {
70
+ console.error(chalk_1.default.red(`[ERROR] Failed to create worktree: ${e.message}`));
71
+ process.exit(1);
72
+ }
73
+ }
74
+ // 4. Simulate Execution (or Dry Run)
75
+ console.log(chalk_1.default.bold('\nAgent Runtime Environment:'));
76
+ console.log(`Working Directory: ${chalk_1.default.yellow(runtimeCwd)}`);
77
+ console.log(`Agent: ${config.name || agentName}`);
78
+ // Validate Configuration involves checking if requires fields exist
79
+ if (config.name && config.name !== agentName) {
80
+ console.warn(chalk_1.default.yellow(`[WARN] filename '${agentName}' does not match agent name '${config.name}'`));
81
+ }
82
+ console.log(chalk_1.default.bold('\nAgent Configuration:'));
83
+ console.log(`Name: ${config.name || agentName}`);
84
+ console.log(`Description: ${config.description || 'No description provided'}`);
85
+ if (config.capabilities && config.capabilities.length > 0) {
86
+ console.log(chalk_1.default.bold('\nCapabilities:'));
87
+ config.capabilities.forEach(cap => console.log(`- ${cap}`));
88
+ }
89
+ if (config.env && config.env.length > 0) {
90
+ console.log(chalk_1.default.bold('\nRequired Environment:'));
91
+ const missingEnv = [];
92
+ config.env.forEach(envVar => {
93
+ const exists = process.env[envVar] !== undefined;
94
+ const status = exists ? chalk_1.default.green('OK') : chalk_1.default.red('MISSING');
95
+ console.log(`- ${envVar}: ${status}`);
96
+ if (!exists)
97
+ missingEnv.push(envVar);
98
+ });
99
+ if (missingEnv.length > 0) {
100
+ console.warn(chalk_1.default.yellow(`[WARN] Missing ${missingEnv.length} environment variables.`));
101
+ }
102
+ }
103
+ const extraContext = [];
104
+ if (options.task) {
105
+ console.log(chalk_1.default.bold('\nTask Context:'));
106
+ const taskPath = path_1.default.join(process.cwd(), 'docs/ai/tasks', options.task);
107
+ if (!fs_extra_1.default.existsSync(taskPath)) {
108
+ console.error(chalk_1.default.red(`[ERROR] Task not found at: ${taskPath}`));
109
+ process.exit(1);
110
+ }
111
+ const scopeFile = path_1.default.join(taskPath, '00-project-scope.md');
112
+ if (fs_extra_1.default.existsSync(scopeFile)) {
113
+ console.log(`- Scope: ${chalk_1.default.green('FOUND')} (${scopeFile})`);
114
+ config.context = config.context || {};
115
+ config.context.files = config.context.files || [];
116
+ config.context.files.push(scopeFile);
117
+ extraContext.push(scopeFile);
118
+ }
119
+ else {
120
+ console.warn(chalk_1.default.yellow(`[WARN] Task scope not found: ${scopeFile}`));
121
+ }
122
+ // Find latest log
123
+ const logsDir = path_1.default.join(taskPath, 'logs');
124
+ if (fs_extra_1.default.existsSync(logsDir)) {
125
+ const logFiles = await fs_extra_1.default.readdir(logsDir);
126
+ const latestLog = logFiles.sort().reverse()[0];
127
+ if (latestLog) {
128
+ const logPath = path_1.default.join(logsDir, latestLog);
129
+ console.log(`- Latest Log: ${chalk_1.default.green('FOUND')} (${logPath})`);
130
+ config.context = config.context || {};
131
+ config.context.files = config.context.files || [];
132
+ config.context.files.push(logPath);
133
+ extraContext.push(logPath);
134
+ }
135
+ }
136
+ }
137
+ // Inject Project Structure Index if available
138
+ const indexFile = path_1.default.join(process.cwd(), 'docs/ai/project-structure.md');
139
+ if (await fs_extra_1.default.pathExists(indexFile)) {
140
+ console.log(`- Project Index: ${chalk_1.default.green('FOUND')} (${indexFile})`);
141
+ config.context = config.context || {};
142
+ config.context.files = config.context.files || [];
143
+ // Avoid duplicates
144
+ if (!config.context.files.includes(indexFile)) {
145
+ config.context.files.unshift(indexFile); // Add to beginning
146
+ }
147
+ }
148
+ if (config.context) {
149
+ console.log('\nLoading Context:');
150
+ // In a real implementation we would copy these files or process them
151
+ // For now we just verify they exist from the perspective of the runtimeCwd
152
+ const files = config.context.files || [];
153
+ let totalTokens = 0;
154
+ for (const file of files) {
155
+ // Check if absolute path (from task loading) or relative
156
+ const checkPath = path_1.default.isAbsolute(file) ? file : path_1.default.join(runtimeCwd, file);
157
+ const exists = await fs_extra_1.default.pathExists(checkPath);
158
+ const status = exists ? chalk_1.default.green('FOUND') : chalk_1.default.red('MISSING');
159
+ let fileTokens = 0;
160
+ if (exists) {
161
+ const content = await fs_extra_1.default.readFile(checkPath, 'utf-8');
162
+ fileTokens = (0, tokens_1.estimateTokens)(content);
163
+ totalTokens += fileTokens;
164
+ }
165
+ console.log(`- ${file}: ${status} (${fileTokens} tokens)`);
166
+ }
167
+ console.log(chalk_1.default.cyan(`\nTotal Context Size: ~${totalTokens} tokens`));
168
+ if (totalTokens > 32000) {
169
+ console.log(chalk_1.default.yellow(`[WARN] Context size is quite large (>32k). Consider removing files.`));
170
+ }
171
+ if (config.context.directories) {
172
+ config.context.directories.forEach(d => console.log(`- [DIR] ${d}`));
173
+ }
174
+ }
175
+ if (!options.dryRun) {
176
+ // Here we would spawn the actual agent process or loop
177
+ console.log(chalk_1.default.magenta('\n*** AGENT EXECUTION STARTED ***'));
178
+ try {
179
+ const driver = new driver_1.LLMDriver({
180
+ provider: config.provider?.type || 'mock',
181
+ model: config.provider?.model || 'test',
182
+ capabilities: config.capabilities || []
183
+ }, options.goal || 'No explicit goal provided.', runtimeCwd, (config.context?.files || []).map(f => path_1.default.isAbsolute(f) ? f : path_1.default.join(runtimeCwd, f)));
184
+ await driver.run();
185
+ }
186
+ catch (e) {
187
+ console.error(chalk_1.default.red(`[ERROR] Execution failed: ${e.message}`));
188
+ }
189
+ console.log(chalk_1.default.magenta('*** AGENT EXECUTION FINISHED ***'));
190
+ // If worktree, ask to commit or verify
191
+ if (options.isolation === 'worktree') {
192
+ // For prototype, we just mention it
193
+ console.log(chalk_1.default.yellow(`\n[INFO] Worktree is preserved at: ${runtimeCwd}`));
194
+ console.log(`Inspect changes there, then delete with: git worktree remove "${runtimeCwd}"`);
195
+ }
196
+ }
197
+ else {
198
+ // Cleanup worktree immediately in dry-run to avoid litter
199
+ if (options.isolation === 'worktree') {
200
+ console.log(chalk_1.default.blue('\n[INFO] Cleaning up dry-run worktree...'));
201
+ await git.removeWorktree(runtimeCwd);
202
+ console.log(chalk_1.default.green('[OK] Worktree removed.'));
203
+ }
204
+ }
205
+ }