@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,452 @@
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.initCommand = initCommand;
7
+ const inquirer_1 = __importDefault(require("inquirer"));
8
+ const chalk_1 = __importDefault(require("chalk"));
9
+ const fs_extra_1 = __importDefault(require("fs-extra"));
10
+ const path_1 = __importDefault(require("path"));
11
+ // Platform definitions with metadata
12
+ const PLATFORMS = [
13
+ { id: 'agents', name: 'Agents.ai', src: 'templates/platforms/AGENTS.md', dest: 'AGENTS.md' },
14
+ { id: 'antigravity', name: 'Antigravity', src: 'templates/platforms/GEMINI.md', dest: '.gemini/rules.md', ensureDir: '.gemini' },
15
+ { id: 'claude', name: 'Claude Code', src: 'templates/platforms/CLAUDE.md', dest: 'CLAUDE.md', symlinks: true },
16
+ { id: 'cline', name: 'Cline', src: 'templates/platforms/clinerules.md', dest: '.clinerules/cline-memory-bank.md', ensureDir: '.clinerules' },
17
+ { id: 'cursor', name: 'Cursor IDE', src: 'templates/platforms/cursor.mdc', dest: '.cursor/rules/project.mdc', ensureDir: '.cursor/rules' },
18
+ { id: 'gemini', name: 'Google Gemini', src: 'templates/platforms/GEMINI.md', dest: 'GEMINI.md' },
19
+ { id: 'copilot', name: 'GitHub Copilot', src: 'templates/platforms/copilot.md', dest: '.github/copilot-instructions.md', ensureDir: '.github' },
20
+ { id: 'windsurf', name: 'Windsurf IDE', src: 'templates/platforms/windsurf.md', dest: '.windsurf/rules/project.md', ensureDir: '.windsurf/rules' },
21
+ ];
22
+ // Fuzzy match platform names
23
+ function fuzzyMatchPlatform(input) {
24
+ const normalized = input.toLowerCase().trim();
25
+ // Direct ID match
26
+ const directMatch = PLATFORMS.find(p => p.id === normalized);
27
+ if (directMatch) {
28
+ return directMatch.id;
29
+ }
30
+ // Partial match - starts with or includes
31
+ const partialMatch = PLATFORMS.find(p => p.id.startsWith(normalized) ||
32
+ p.name.toLowerCase().includes(normalized));
33
+ if (partialMatch) {
34
+ return partialMatch.id;
35
+ }
36
+ // Special case for common variations
37
+ if (normalized === 'github' || normalized === 'copilot') {
38
+ return 'copilot';
39
+ }
40
+ return null;
41
+ }
42
+ async function initCommand(platformArgs, options) {
43
+ // Handle both old signature (no args) and new signature (with variadic args)
44
+ // When called with no args: first param is options object
45
+ // When called with args: first param is array, second param is options
46
+ let platforms = [];
47
+ let opts = {};
48
+ if (Array.isArray(platformArgs)) {
49
+ platforms = platformArgs;
50
+ opts = options || {};
51
+ }
52
+ else {
53
+ // Old signature - first param is actually options
54
+ opts = platformArgs || {};
55
+ platforms = [];
56
+ }
57
+ console.log(chalk_1.default.blue('╔════════════════════════════════════════╗'));
58
+ console.log(chalk_1.default.blue('║ Contextuate Installer ║'));
59
+ console.log(chalk_1.default.blue('║ AI Context Framework ║'));
60
+ console.log(chalk_1.default.blue('║ Powered by Esotech ║'));
61
+ console.log(chalk_1.default.blue('╚════════════════════════════════════════╝'));
62
+ console.log('');
63
+ try {
64
+ // Determine if running in non-interactive mode
65
+ const nonInteractive = platforms.length > 0;
66
+ // Check for project markers
67
+ const projectMarkers = ['.git', 'package.json', 'composer.json', 'Cargo.toml', 'go.mod'];
68
+ const hasMarker = projectMarkers.some(marker => fs_extra_1.default.existsSync(marker));
69
+ if (!hasMarker && !nonInteractive) {
70
+ console.log(chalk_1.default.yellow('[WARN] No project markers found (.git, package.json, etc.)'));
71
+ const { continueAnyway } = await inquirer_1.default.prompt([
72
+ {
73
+ type: 'confirm',
74
+ name: 'continueAnyway',
75
+ message: 'Continue anyway?',
76
+ default: true,
77
+ },
78
+ ]);
79
+ if (!continueAnyway) {
80
+ console.log(chalk_1.default.blue('[INFO] Installation cancelled.'));
81
+ return;
82
+ }
83
+ }
84
+ else if (!hasMarker && nonInteractive) {
85
+ console.log(chalk_1.default.yellow('[WARN] No project markers found (.git, package.json, etc.) - continuing anyway in non-interactive mode'));
86
+ }
87
+ let selectedPlatforms = [];
88
+ // Non-interactive mode - process CLI arguments
89
+ if (nonInteractive) {
90
+ // Check for "all" argument
91
+ if (platforms.some(arg => arg.toLowerCase() === 'all')) {
92
+ selectedPlatforms = PLATFORMS;
93
+ console.log(chalk_1.default.blue('[INFO] Installing all platforms'));
94
+ }
95
+ else {
96
+ // Fuzzy match each platform argument
97
+ for (const arg of platforms) {
98
+ const matchedId = fuzzyMatchPlatform(arg);
99
+ if (matchedId) {
100
+ const platform = PLATFORMS.find(p => p.id === matchedId);
101
+ if (platform && !selectedPlatforms.includes(platform)) {
102
+ selectedPlatforms.push(platform);
103
+ console.log(chalk_1.default.green(`[OK] Matched "${arg}" to ${platform.name}`));
104
+ }
105
+ }
106
+ else {
107
+ console.log(chalk_1.default.yellow(`[WARN] Could not match platform "${arg}" - skipping`));
108
+ }
109
+ }
110
+ if (selectedPlatforms.length === 0) {
111
+ console.log(chalk_1.default.red('[ERROR] No valid platforms matched. Available platforms:'));
112
+ PLATFORMS.forEach(p => console.log(` - ${p.id} (${p.name})`));
113
+ return;
114
+ }
115
+ }
116
+ }
117
+ else {
118
+ // Interactive mode - ask about platform selection
119
+ const { platforms } = await inquirer_1.default.prompt([
120
+ {
121
+ type: 'checkbox',
122
+ name: 'platforms',
123
+ message: 'Select the platforms to install:',
124
+ choices: [
125
+ { name: 'Select All', value: 'all' },
126
+ new inquirer_1.default.Separator(),
127
+ ...PLATFORMS.map(p => ({
128
+ name: p.name,
129
+ value: p.id,
130
+ checked: false,
131
+ }))
132
+ ],
133
+ validate: (answer) => {
134
+ if (answer.length < 1) {
135
+ return 'You must select at least one platform.';
136
+ }
137
+ return true;
138
+ },
139
+ },
140
+ ]);
141
+ if (platforms.includes('all')) {
142
+ selectedPlatforms = PLATFORMS;
143
+ }
144
+ else {
145
+ selectedPlatforms = PLATFORMS.filter(p => platforms.includes(p.id));
146
+ }
147
+ }
148
+ // Handle agent installation
149
+ let selectedAgents = [];
150
+ // Dynamically discover available agents from template source
151
+ let agentTemplateDir = path_1.default.join(__dirname, '../templates/agents');
152
+ // Handle ts-node vs compiled paths
153
+ if (path_1.default.basename(path_1.default.join(__dirname, '..')) === 'src') {
154
+ agentTemplateDir = path_1.default.join(__dirname, '../../src/templates/agents');
155
+ }
156
+ else if (path_1.default.basename(__dirname) === 'commands') {
157
+ agentTemplateDir = path_1.default.join(__dirname, '../templates/agents');
158
+ }
159
+ if (!fs_extra_1.default.existsSync(agentTemplateDir)) {
160
+ agentTemplateDir = path_1.default.join(__dirname, '../../templates/agents');
161
+ }
162
+ let availableAgents = [];
163
+ if (fs_extra_1.default.existsSync(agentTemplateDir)) {
164
+ const agentFiles = await fs_extra_1.default.readdir(agentTemplateDir);
165
+ availableAgents = agentFiles
166
+ .filter(f => f.endsWith('.md'))
167
+ .map(f => f.replace('.md', ''));
168
+ }
169
+ if (opts.agents && opts.agents.length > 0) {
170
+ // Non-interactive agent selection via --agents flag
171
+ if (opts.agents.includes('all')) {
172
+ selectedAgents = availableAgents;
173
+ console.log(chalk_1.default.blue('[INFO] Installing all agents'));
174
+ }
175
+ else {
176
+ // Match specific agents
177
+ for (const agentArg of opts.agents) {
178
+ const normalized = agentArg.toLowerCase().trim();
179
+ const matched = availableAgents.find(a => a.toLowerCase() === normalized);
180
+ if (matched) {
181
+ selectedAgents.push(matched);
182
+ console.log(chalk_1.default.green(`[OK] Matched agent "${agentArg}" to ${matched}`));
183
+ }
184
+ else {
185
+ console.log(chalk_1.default.yellow(`[WARN] Could not match agent "${agentArg}" - skipping`));
186
+ }
187
+ }
188
+ if (selectedAgents.length === 0 && opts.agents.length > 0 && !opts.agents.includes('all')) {
189
+ console.log(chalk_1.default.yellow('[WARN] No valid agents matched. Available agents:'));
190
+ availableAgents.forEach(a => console.log(` - ${a}`));
191
+ }
192
+ }
193
+ }
194
+ else if (!nonInteractive) {
195
+ // Interactive mode - ask about agent installation
196
+ const { installAgents } = await inquirer_1.default.prompt([
197
+ {
198
+ type: 'confirm',
199
+ name: 'installAgents',
200
+ message: 'Would you like to install pre-built AI agents?',
201
+ default: true,
202
+ },
203
+ ]);
204
+ if (installAgents && availableAgents.length > 0) {
205
+ const { agents } = await inquirer_1.default.prompt([
206
+ {
207
+ type: 'checkbox',
208
+ name: 'agents',
209
+ message: 'Select agents to install:',
210
+ choices: [
211
+ { name: 'Select All', value: 'all' },
212
+ new inquirer_1.default.Separator(),
213
+ ...availableAgents.map(agent => ({
214
+ name: agent.split('-').map(w => w.charAt(0).toUpperCase() + w.slice(1)).join(' '),
215
+ value: agent,
216
+ checked: false,
217
+ }))
218
+ ],
219
+ },
220
+ ]);
221
+ if (agents.includes('all')) {
222
+ selectedAgents = availableAgents;
223
+ }
224
+ else {
225
+ selectedAgents = agents;
226
+ }
227
+ }
228
+ }
229
+ console.log('');
230
+ console.log(chalk_1.default.blue('[INFO] Installing Contextuate framework...'));
231
+ console.log('');
232
+ // 1. Create directory structure
233
+ console.log(chalk_1.default.blue('[INFO] Creating directory structure...'));
234
+ const dirs = [
235
+ 'docs/ai/.contextuate/standards',
236
+ 'docs/ai/.contextuate/tools',
237
+ 'docs/ai/.contextuate/agents',
238
+ 'docs/ai/agents',
239
+ 'docs/ai/standards',
240
+ 'docs/ai/quickrefs',
241
+ 'docs/ai/tasks',
242
+ 'docs/ai/commands',
243
+ 'docs/ai/hooks',
244
+ 'docs/ai/skills',
245
+ ];
246
+ for (const dir of dirs) {
247
+ await fs_extra_1.default.ensureDir(dir);
248
+ console.log(chalk_1.default.green(`[OK] Created directory: ${dir}`));
249
+ }
250
+ // Cleanup legacy template directories if they exist
251
+ const legacyDirs = [
252
+ 'docs/ai/.contextuate/templates',
253
+ ];
254
+ for (const dir of legacyDirs) {
255
+ if (fs_extra_1.default.existsSync(dir)) {
256
+ await fs_extra_1.default.remove(dir);
257
+ console.log(chalk_1.default.yellow(`[CLEANUP] Removed legacy directory: ${dir}`));
258
+ }
259
+ }
260
+ console.log('');
261
+ // 2. Copy templates
262
+ console.log(chalk_1.default.blue('[INFO] Installing framework files...'));
263
+ // In development (ts-node), this is ../../src/templates relative to src/commands/init.ts
264
+ // In production (dist), this is ../templates relative to dist/commands/init.js
265
+ let templateSource = path_1.default.join(__dirname, '../templates');
266
+ // If running from src/commands (ts-node), we need to go up one more level if structure is src/commands/init.ts
267
+ if (path_1.default.basename(path_1.default.join(__dirname, '..')) === 'src') {
268
+ templateSource = path_1.default.join(__dirname, '../../src/templates');
269
+ }
270
+ else if (path_1.default.basename(__dirname) === 'commands') {
271
+ // dist/commands/init.js -> dist/templates
272
+ templateSource = path_1.default.join(__dirname, '../templates');
273
+ }
274
+ // Fallback/Verify
275
+ if (!fs_extra_1.default.existsSync(templateSource)) {
276
+ // Try one level up just in case
277
+ templateSource = path_1.default.join(__dirname, '../../templates');
278
+ }
279
+ if (!fs_extra_1.default.existsSync(templateSource)) {
280
+ console.error(chalk_1.default.red(`[ERROR] Could not find template source at ${templateSource}`));
281
+ return;
282
+ }
283
+ const installDir = 'docs/ai/.contextuate';
284
+ // Helper to copy files
285
+ const copyFile = async (src, dest) => {
286
+ // Resolve absolute paths to check for equality
287
+ const absSrc = path_1.default.resolve(src);
288
+ const absDest = path_1.default.resolve(dest);
289
+ if (absSrc === absDest) {
290
+ return;
291
+ }
292
+ if (!fs_extra_1.default.existsSync(src)) {
293
+ console.log(chalk_1.default.red(`[ERROR] Source file missing: ${src}`));
294
+ return;
295
+ }
296
+ if (fs_extra_1.default.existsSync(dest) && !opts.force) {
297
+ console.log(chalk_1.default.yellow(`[WARN] Skipped (exists): ${dest}`));
298
+ return;
299
+ }
300
+ await fs_extra_1.default.copy(src, dest);
301
+ console.log(chalk_1.default.green(`[OK] Created: ${dest}`));
302
+ };
303
+ // Copy core engine files only to .contextuate
304
+ await copyFile(path_1.default.join(templateSource, 'version.json'), path_1.default.join(installDir, 'version.json'));
305
+ await copyFile(path_1.default.join(templateSource, 'README.md'), path_1.default.join(installDir, 'README.md'));
306
+ // Copy directories - only core framework files
307
+ const copyDirContents = async (srcSubDir, destDir) => {
308
+ const srcDir = path_1.default.join(templateSource, srcSubDir);
309
+ if (fs_extra_1.default.existsSync(srcDir)) {
310
+ await fs_extra_1.default.ensureDir(destDir);
311
+ const files = await fs_extra_1.default.readdir(srcDir);
312
+ for (const file of files) {
313
+ await copyFile(path_1.default.join(srcDir, file), path_1.default.join(destDir, file));
314
+ }
315
+ }
316
+ };
317
+ // Copy core standards, tools, and framework agents to .contextuate (engine files)
318
+ await copyDirContents('standards', path_1.default.join(installDir, 'standards'));
319
+ await copyDirContents('tools', path_1.default.join(installDir, 'tools'));
320
+ await copyDirContents('framework-agents', path_1.default.join(installDir, 'agents'));
321
+ console.log(chalk_1.default.green('[OK] Copied framework files'));
322
+ console.log('');
323
+ // 3. Install selected agents to docs/ai/agents/
324
+ if (selectedAgents.length > 0) {
325
+ console.log(chalk_1.default.blue('[INFO] Installing selected agents...'));
326
+ for (const agent of selectedAgents) {
327
+ const agentFile = `${agent}.md`;
328
+ const srcPath = path_1.default.join(templateSource, 'agents', agentFile);
329
+ const destPath = path_1.default.join('docs/ai/agents', agentFile);
330
+ await copyFile(srcPath, destPath);
331
+ }
332
+ console.log(chalk_1.default.green(`[OK] Installed ${selectedAgents.length} agent(s) to docs/ai/agents/`));
333
+ console.log('');
334
+ }
335
+ // 4. Setup project context files
336
+ console.log(chalk_1.default.blue('[INFO] Setting up project context...'));
337
+ // Copy contextuate.md (main entry point) directly from templates to docs/ai/.contextuate/ (protected)
338
+ await copyFile(path_1.default.join(templateSource, 'templates/contextuate.md'), 'docs/ai/.contextuate/contextuate.md');
339
+ // Copy context.md (user customizable) directly from templates to docs/ai/
340
+ await copyFile(path_1.default.join(templateSource, 'templates/context.md'), 'docs/ai/context.md');
341
+ console.log('');
342
+ // 5. Generate jump files for selected platforms
343
+ console.log(chalk_1.default.blue('[INFO] Generating platform jump files...'));
344
+ for (const platform of selectedPlatforms) {
345
+ if (platform.ensureDir) {
346
+ await fs_extra_1.default.ensureDir(platform.ensureDir);
347
+ }
348
+ // Copy directly from template source, not from .contextuate
349
+ await copyFile(path_1.default.join(templateSource, platform.src), platform.dest);
350
+ }
351
+ console.log('');
352
+ // 6. Create platform-specific symlinks (only for platforms that need them)
353
+ const platformsWithSymlinks = selectedPlatforms.filter(p => p.symlinks);
354
+ if (platformsWithSymlinks.length > 0) {
355
+ console.log(chalk_1.default.blue('[INFO] Creating platform symlinks...'));
356
+ // Helper to create symlinks
357
+ const createSymlink = async (target, linkPath) => {
358
+ const linkDir = path_1.default.dirname(linkPath);
359
+ await fs_extra_1.default.ensureDir(linkDir);
360
+ // Calculate relative path from link location to target
361
+ const relativeTarget = path_1.default.relative(linkDir, target);
362
+ // Check if symlink already exists
363
+ try {
364
+ const existingLink = await fs_extra_1.default.readlink(linkPath);
365
+ if (existingLink === relativeTarget) {
366
+ console.log(chalk_1.default.yellow(`[WARN] Symlink exists: ${linkPath} -> ${relativeTarget}`));
367
+ return;
368
+ }
369
+ // Remove existing symlink if it points elsewhere
370
+ await fs_extra_1.default.remove(linkPath);
371
+ }
372
+ catch {
373
+ // Not a symlink or doesn't exist
374
+ if (fs_extra_1.default.existsSync(linkPath)) {
375
+ if (opts.force) {
376
+ await fs_extra_1.default.remove(linkPath);
377
+ }
378
+ else {
379
+ console.log(chalk_1.default.yellow(`[WARN] Skipped (path exists): ${linkPath}`));
380
+ return;
381
+ }
382
+ }
383
+ }
384
+ await fs_extra_1.default.ensureSymlink(relativeTarget, linkPath);
385
+ console.log(chalk_1.default.green(`[OK] Symlink: ${linkPath} -> ${relativeTarget}`));
386
+ };
387
+ // Create symlinks for Claude Code
388
+ if (selectedPlatforms.some(p => p.id === 'claude')) {
389
+ const symlinks = [
390
+ { target: 'docs/ai/commands', link: '.claude/commands' },
391
+ { target: 'docs/ai/agents', link: '.claude/agents' },
392
+ { target: 'docs/ai/hooks', link: '.claude/hooks' },
393
+ { target: 'docs/ai/skills', link: '.claude/skills' },
394
+ ];
395
+ for (const symlink of symlinks) {
396
+ await createSymlink(symlink.target, symlink.link);
397
+ }
398
+ }
399
+ console.log('');
400
+ }
401
+ console.log(chalk_1.default.green('╔════════════════════════════════════════╗'));
402
+ console.log(chalk_1.default.green('║ Installation Complete! ║'));
403
+ console.log(chalk_1.default.green('╚════════════════════════════════════════╝'));
404
+ console.log('');
405
+ console.log('Installed platforms:');
406
+ for (const platform of selectedPlatforms) {
407
+ console.log(` - ${chalk_1.default.cyan(platform.name)} (${platform.dest})`);
408
+ }
409
+ console.log('');
410
+ if (selectedAgents.length > 0) {
411
+ console.log('Installed agents:');
412
+ for (const agent of selectedAgents) {
413
+ console.log(` - ${chalk_1.default.cyan(agent)} (docs/ai/agents/${agent}.md)`);
414
+ }
415
+ console.log('');
416
+ }
417
+ console.log('Next steps:');
418
+ console.log('');
419
+ console.log(` 1. Edit ${chalk_1.default.blue('docs/ai/context.md')} with your project details`);
420
+ if (selectedAgents.length > 0) {
421
+ console.log(` 2. Review installed agents in ${chalk_1.default.blue('docs/ai/agents/')}`);
422
+ console.log(` 3. Add custom agents or quickrefs as needed`);
423
+ }
424
+ else {
425
+ console.log(` 2. Create custom agents in ${chalk_1.default.blue('docs/ai/agents/')}`);
426
+ console.log(` 3. Add quickrefs in ${chalk_1.default.blue('docs/ai/quickrefs/')}`);
427
+ }
428
+ console.log('');
429
+ console.log('');
430
+ console.log('Documentation: https://contextuate.md');
431
+ console.log('');
432
+ console.log(chalk_1.default.gray('Powered by Esotech.'));
433
+ console.log(chalk_1.default.gray('Created by Alexander Conroy (@geilt)'));
434
+ console.log('');
435
+ }
436
+ catch (error) {
437
+ if (error.isTtyError) {
438
+ // Prompt couldn't be rendered in the current environment
439
+ console.error(chalk_1.default.red('[ERROR] Prompt could not be rendered in the current environment'));
440
+ }
441
+ else if (error.name === 'ExitPromptError' || error.message.includes('User force closed the prompt')) {
442
+ console.log('');
443
+ console.log(chalk_1.default.yellow('👋 Installation cancelled by user.'));
444
+ process.exit(0);
445
+ }
446
+ else {
447
+ // Something else went wrong
448
+ console.error(chalk_1.default.red('[ERROR] An unexpected error occurred:'), error);
449
+ process.exit(1);
450
+ }
451
+ }
452
+ }