@esotech/contextuate 2.1.1 → 2.1.2

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 (35) hide show
  1. package/dist/commands/doctor.d.ts +6 -0
  2. package/dist/commands/doctor.js +131 -0
  3. package/dist/commands/init.d.ts +0 -2
  4. package/dist/commands/init.js +164 -228
  5. package/dist/index.js +7 -0
  6. package/dist/templates/agents/aegis.md +1 -1
  7. package/dist/templates/agents/archon.md +116 -8
  8. package/dist/templates/agents/atlas.md +17 -17
  9. package/dist/templates/agents/canvas.md +1 -1
  10. package/dist/templates/agents/chronicle.md +1 -1
  11. package/dist/templates/agents/chronos.md +1 -1
  12. package/dist/templates/agents/cipher.md +1 -1
  13. package/dist/templates/agents/crucible.md +1 -1
  14. package/dist/templates/agents/echo.md +1 -1
  15. package/dist/templates/agents/forge.md +1 -1
  16. package/dist/templates/agents/ledger.md +34 -3
  17. package/dist/templates/agents/meridian.md +1 -1
  18. package/dist/templates/agents/nexus.md +1 -1
  19. package/dist/templates/agents/pythia.md +1 -1
  20. package/dist/templates/agents/scribe.md +1 -1
  21. package/dist/templates/agents/sentinel.md +1 -1
  22. package/dist/templates/agents/thoth.md +1 -1
  23. package/dist/templates/agents/unity.md +1 -1
  24. package/dist/templates/agents/vox.md +1 -1
  25. package/dist/templates/agents/weaver.md +1 -1
  26. package/dist/templates/commands/consult.md +1 -1
  27. package/dist/templates/commands/orchestrate.md +5 -129
  28. package/dist/templates/framework-agents/documentation-expert.md +3 -3
  29. package/dist/templates/framework-agents/tools-expert.md +3 -3
  30. package/dist/templates/templates/contextuate.md +1 -1
  31. package/dist/templates/tools/agent-creator.md +4 -4
  32. package/dist/templates/tools/standards-detector.md +1 -1
  33. package/dist/utils/tools.d.ts +60 -0
  34. package/dist/utils/tools.js +260 -0
  35. package/package.json +1 -1
@@ -20,8 +20,8 @@ You are responsible for creating and maintaining documentation for both humans a
20
20
 
21
21
  In addition to base agent context, you MUST read:
22
22
 
23
- 1. **[Task Workflow](../standards/task-workflow.md)** - For task documentation structure
24
- 2. **[Quickref Tool](../tools/quickref.md)** - For generating AI-friendly references
23
+ 1. **[../standards/task-workflow.md](../standards/task-workflow.md)** - For task documentation structure
24
+ 2. **[../tools/quickref.md](../tools/quickref.md)** - For generating AI-friendly references
25
25
 
26
26
  ---
27
27
 
@@ -192,7 +192,7 @@ For AI assistants. Condensed, scannable method/API signatures.
192
192
 
193
193
  ## Quickref Generation
194
194
 
195
- Use the [Quickref Tool](../tools/quickref.md) to generate AI-friendly references:
195
+ Use the [../tools/quickref.md](../tools/quickref.md) to generate AI-friendly references:
196
196
 
197
197
  1. Read the tool guide
198
198
  2. Read the source documentation
@@ -24,9 +24,9 @@ Guides that AI assistants follow to perform tasks.
24
24
 
25
25
  | Tool | Purpose | Guide |
26
26
  |------|---------|-------|
27
- | Quickref Generator | Generate condensed references from docs | [quickref.md](../tools/quickref.md) |
28
- | Standards Detector | Analyze code to detect coding standards | [standards-detector.md](../tools/standards-detector.md) |
29
- | Agent Creator | Create new AI agent definitions | [agent-creator.md](../tools/agent-creator.md) |
27
+ | Quickref Generator | Generate condensed references from docs | [../tools/quickref.md](../tools/quickref.md) |
28
+ | Standards Detector | Analyze code to detect coding standards | [../tools/standards-detector.md](../tools/standards-detector.md) |
29
+ | Agent Creator | Create new AI agent definitions | [../tools/agent-creator.md](../tools/agent-creator.md) |
30
30
 
31
31
  ### Framework Scripts (`docs/ai/.contextuate/bin/`)
32
32
 
@@ -15,7 +15,7 @@
15
15
 
16
16
  **Read the project-specific context file for details about this project:**
17
17
 
18
- [Project Context](../context.md)
18
+ [../context.md](../context.md)
19
19
 
20
20
  > If `context.md` exists, it contains project identity, tech stack, and custom configurations.
21
21
 
@@ -78,7 +78,7 @@ Verify:
78
78
  ```markdown
79
79
  # {Name} Expert Agent
80
80
 
81
- > **Inherits:** [Base Agent Configuration](../.contextuate/agents/base.md)
81
+ > **Inherits:** [../.contextuate/agents/base.md](../.contextuate/agents/base.md)
82
82
  > **Role:** {One-line description of expertise}
83
83
  > **Domain:** `{file patterns covered}`
84
84
 
@@ -179,7 +179,7 @@ File: `docs/ai/agents/database-expert.md`
179
179
  ```markdown
180
180
  # Database Expert Agent
181
181
 
182
- > **Inherits:** [Base Agent Configuration](../.contextuate/agents/base.md)
182
+ > **Inherits:** [../.contextuate/agents/base.md](../.contextuate/agents/base.md)
183
183
  > **Role:** Expert in database operations, queries, and schema design
184
184
  > **Domain:** `*.sql`, `migrations/`, `**/db/**`
185
185
 
@@ -193,8 +193,8 @@ You are an expert in database operations. Your role is to:
193
193
 
194
194
  ## Required Context
195
195
 
196
- 1. **[Database Documentation](../../database.md)** - Schema and conventions
197
- 2. **[Database Quickref](../quickrefs/database.quickref.md)** - API reference
196
+ 1. **[../../database.md](../../database.md)** - Schema and conventions
197
+ 2. **[../quickrefs/database.quickref.md](../quickrefs/database.quickref.md)** - API reference
198
198
  ```
199
199
 
200
200
  ---
@@ -126,7 +126,7 @@ docs/ai/standards/
126
126
  ```
127
127
 
128
128
  These user standards take priority over framework defaults in `docs/ai/.context/templates/standards/`.
129
- See [coding-standards.md](../standards/coding-standards.md) for resolution order.
129
+ See [../standards/coding-standards.md](../standards/coding-standards.md) for resolution order.
130
130
 
131
131
  ---
132
132
 
@@ -0,0 +1,60 @@
1
+ export interface ToolInfo {
2
+ installed: boolean;
3
+ version: string | null;
4
+ path: string | null;
5
+ }
6
+ export interface ToolsConfig {
7
+ ripgrep: ToolInfo;
8
+ }
9
+ export interface ContextuateConfig {
10
+ name: string;
11
+ version: string;
12
+ description: string;
13
+ repository: string;
14
+ initialized: string;
15
+ updated: string;
16
+ tools: ToolsConfig;
17
+ }
18
+ /**
19
+ * Detect ripgrep installation
20
+ */
21
+ export declare function detectRipgrep(): ToolInfo;
22
+ /**
23
+ * Detect all tools
24
+ */
25
+ export declare function detectTools(): ToolsConfig;
26
+ /**
27
+ * Detect the current operating system and package manager
28
+ */
29
+ export declare function detectPlatform(): {
30
+ os: 'macos' | 'linux' | 'windows';
31
+ packageManager: string | null;
32
+ };
33
+ /**
34
+ * Install ripgrep using the appropriate package manager
35
+ */
36
+ export declare function installRipgrep(): Promise<boolean>;
37
+ /**
38
+ * Prompt user to install missing tools
39
+ */
40
+ export declare function promptInstallTools(tools: ToolsConfig, nonInteractive?: boolean): Promise<ToolsConfig>;
41
+ /**
42
+ * Process template variables in a file
43
+ */
44
+ export declare function processTemplateVariables(content: string, tools: ToolsConfig): string;
45
+ /**
46
+ * Process template variables in all files in a directory
47
+ */
48
+ export declare function processTemplateDirectory(dir: string, tools: ToolsConfig): Promise<number>;
49
+ /**
50
+ * Read contextuate.json config
51
+ */
52
+ export declare function readContextuateConfig(installDir: string): Promise<ContextuateConfig | null>;
53
+ /**
54
+ * Write contextuate.json config
55
+ */
56
+ export declare function writeContextuateConfig(installDir: string, config: ContextuateConfig): Promise<void>;
57
+ /**
58
+ * Print tool status
59
+ */
60
+ export declare function printToolStatus(tools: ToolsConfig): void;
@@ -0,0 +1,260 @@
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.detectRipgrep = detectRipgrep;
7
+ exports.detectTools = detectTools;
8
+ exports.detectPlatform = detectPlatform;
9
+ exports.installRipgrep = installRipgrep;
10
+ exports.promptInstallTools = promptInstallTools;
11
+ exports.processTemplateVariables = processTemplateVariables;
12
+ exports.processTemplateDirectory = processTemplateDirectory;
13
+ exports.readContextuateConfig = readContextuateConfig;
14
+ exports.writeContextuateConfig = writeContextuateConfig;
15
+ exports.printToolStatus = printToolStatus;
16
+ const child_process_1 = require("child_process");
17
+ const chalk_1 = __importDefault(require("chalk"));
18
+ const inquirer_1 = __importDefault(require("inquirer"));
19
+ const fs_extra_1 = __importDefault(require("fs-extra"));
20
+ const path_1 = __importDefault(require("path"));
21
+ const os_1 = __importDefault(require("os"));
22
+ /**
23
+ * Detect if a command exists and get its path
24
+ */
25
+ function detectCommand(command) {
26
+ try {
27
+ const result = (0, child_process_1.execSync)(`which ${command}`, { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] });
28
+ return { exists: true, path: result.trim() };
29
+ }
30
+ catch {
31
+ return { exists: false, path: null };
32
+ }
33
+ }
34
+ /**
35
+ * Get ripgrep version
36
+ */
37
+ function getRipgrepVersion(rgPath) {
38
+ try {
39
+ const result = (0, child_process_1.execSync)(`"${rgPath}" --version`, { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] });
40
+ const match = result.match(/ripgrep\s+(\d+\.\d+\.\d+)/);
41
+ return match ? match[1] : null;
42
+ }
43
+ catch {
44
+ return null;
45
+ }
46
+ }
47
+ /**
48
+ * Detect ripgrep installation
49
+ */
50
+ function detectRipgrep() {
51
+ const detection = detectCommand('rg');
52
+ if (!detection.exists) {
53
+ return { installed: false, version: null, path: null };
54
+ }
55
+ const version = getRipgrepVersion(detection.path);
56
+ return {
57
+ installed: true,
58
+ version,
59
+ path: detection.path
60
+ };
61
+ }
62
+ /**
63
+ * Detect all tools
64
+ */
65
+ function detectTools() {
66
+ return {
67
+ ripgrep: detectRipgrep()
68
+ };
69
+ }
70
+ /**
71
+ * Detect the current operating system and package manager
72
+ */
73
+ function detectPlatform() {
74
+ const platform = os_1.default.platform();
75
+ if (platform === 'darwin') {
76
+ // Check for Homebrew
77
+ const brew = detectCommand('brew');
78
+ return { os: 'macos', packageManager: brew.exists ? 'brew' : null };
79
+ }
80
+ if (platform === 'linux') {
81
+ // Check for common package managers
82
+ if (detectCommand('apt-get').exists) {
83
+ return { os: 'linux', packageManager: 'apt' };
84
+ }
85
+ if (detectCommand('dnf').exists) {
86
+ return { os: 'linux', packageManager: 'dnf' };
87
+ }
88
+ if (detectCommand('yum').exists) {
89
+ return { os: 'linux', packageManager: 'yum' };
90
+ }
91
+ if (detectCommand('pacman').exists) {
92
+ return { os: 'linux', packageManager: 'pacman' };
93
+ }
94
+ return { os: 'linux', packageManager: null };
95
+ }
96
+ if (platform === 'win32') {
97
+ // Check for common Windows package managers
98
+ if (detectCommand('choco').exists) {
99
+ return { os: 'windows', packageManager: 'choco' };
100
+ }
101
+ if (detectCommand('winget').exists) {
102
+ return { os: 'windows', packageManager: 'winget' };
103
+ }
104
+ return { os: 'windows', packageManager: null };
105
+ }
106
+ return { os: 'linux', packageManager: null };
107
+ }
108
+ /**
109
+ * Install ripgrep using the appropriate package manager
110
+ */
111
+ async function installRipgrep() {
112
+ const platform = detectPlatform();
113
+ let installCommand;
114
+ switch (platform.packageManager) {
115
+ case 'brew':
116
+ installCommand = 'brew install ripgrep';
117
+ break;
118
+ case 'apt':
119
+ installCommand = 'sudo apt-get install -y ripgrep';
120
+ break;
121
+ case 'dnf':
122
+ installCommand = 'sudo dnf install -y ripgrep';
123
+ break;
124
+ case 'yum':
125
+ installCommand = 'sudo yum install -y ripgrep';
126
+ break;
127
+ case 'pacman':
128
+ installCommand = 'sudo pacman -S --noconfirm ripgrep';
129
+ break;
130
+ case 'choco':
131
+ installCommand = 'choco install ripgrep -y';
132
+ break;
133
+ case 'winget':
134
+ installCommand = 'winget install BurntSushi.ripgrep.MSVC';
135
+ break;
136
+ default:
137
+ console.log(chalk_1.default.yellow('[WARN] No supported package manager found.'));
138
+ console.log(chalk_1.default.blue('[INFO] Please install ripgrep manually:'));
139
+ console.log(chalk_1.default.gray(' - macOS: brew install ripgrep'));
140
+ console.log(chalk_1.default.gray(' - Ubuntu/Debian: sudo apt install ripgrep'));
141
+ console.log(chalk_1.default.gray(' - Fedora: sudo dnf install ripgrep'));
142
+ console.log(chalk_1.default.gray(' - Arch: sudo pacman -S ripgrep'));
143
+ console.log(chalk_1.default.gray(' - Windows: choco install ripgrep'));
144
+ console.log(chalk_1.default.gray(' - Or download from: https://github.com/BurntSushi/ripgrep/releases'));
145
+ return false;
146
+ }
147
+ console.log(chalk_1.default.blue(`[INFO] Installing ripgrep via ${platform.packageManager}...`));
148
+ console.log(chalk_1.default.gray(` Running: ${installCommand}`));
149
+ return new Promise((resolve) => {
150
+ (0, child_process_1.exec)(installCommand, (error, stdout, stderr) => {
151
+ if (error) {
152
+ console.log(chalk_1.default.red(`[ERROR] Installation failed: ${error.message}`));
153
+ if (stderr) {
154
+ console.log(chalk_1.default.gray(stderr));
155
+ }
156
+ resolve(false);
157
+ }
158
+ else {
159
+ console.log(chalk_1.default.green('[OK] ripgrep installed successfully'));
160
+ resolve(true);
161
+ }
162
+ });
163
+ });
164
+ }
165
+ /**
166
+ * Prompt user to install missing tools
167
+ */
168
+ async function promptInstallTools(tools, nonInteractive = false) {
169
+ // Check ripgrep
170
+ if (!tools.ripgrep.installed && !nonInteractive) {
171
+ const { installRg } = await inquirer_1.default.prompt([
172
+ {
173
+ type: 'confirm',
174
+ name: 'installRg',
175
+ message: 'ripgrep (rg) is not installed. Would you like to install it? (Recommended for faster code search)',
176
+ default: true,
177
+ },
178
+ ]);
179
+ if (installRg) {
180
+ const success = await installRipgrep();
181
+ if (success) {
182
+ // Re-detect after installation
183
+ tools.ripgrep = detectRipgrep();
184
+ }
185
+ }
186
+ }
187
+ return tools;
188
+ }
189
+ /**
190
+ * Process template variables in a file
191
+ */
192
+ function processTemplateVariables(content, tools) {
193
+ // Replace {grep} with rg if ripgrep is installed, otherwise grep
194
+ const grepCommand = tools.ripgrep.installed ? 'rg' : 'grep';
195
+ return content.replace(/\{grep\}/g, grepCommand);
196
+ }
197
+ /**
198
+ * Process template variables in all files in a directory
199
+ */
200
+ async function processTemplateDirectory(dir, tools) {
201
+ let processedCount = 0;
202
+ if (!fs_extra_1.default.existsSync(dir)) {
203
+ return processedCount;
204
+ }
205
+ const processDir = async (currentDir) => {
206
+ const entries = await fs_extra_1.default.readdir(currentDir, { withFileTypes: true });
207
+ for (const entry of entries) {
208
+ const fullPath = path_1.default.join(currentDir, entry.name);
209
+ if (entry.isDirectory()) {
210
+ await processDir(fullPath);
211
+ }
212
+ else if (entry.isFile() && entry.name.endsWith('.md')) {
213
+ const content = await fs_extra_1.default.readFile(fullPath, 'utf-8');
214
+ const processed = processTemplateVariables(content, tools);
215
+ if (content !== processed) {
216
+ await fs_extra_1.default.writeFile(fullPath, processed);
217
+ processedCount++;
218
+ }
219
+ }
220
+ }
221
+ };
222
+ await processDir(dir);
223
+ return processedCount;
224
+ }
225
+ /**
226
+ * Read contextuate.json config
227
+ */
228
+ async function readContextuateConfig(installDir) {
229
+ const configPath = path_1.default.join(installDir, 'contextuate.json');
230
+ try {
231
+ if (fs_extra_1.default.existsSync(configPath)) {
232
+ const content = await fs_extra_1.default.readFile(configPath, 'utf-8');
233
+ return JSON.parse(content);
234
+ }
235
+ }
236
+ catch {
237
+ // Config doesn't exist or is invalid
238
+ }
239
+ return null;
240
+ }
241
+ /**
242
+ * Write contextuate.json config
243
+ */
244
+ async function writeContextuateConfig(installDir, config) {
245
+ const configPath = path_1.default.join(installDir, 'contextuate.json');
246
+ await fs_extra_1.default.writeFile(configPath, JSON.stringify(config, null, 2));
247
+ }
248
+ /**
249
+ * Print tool status
250
+ */
251
+ function printToolStatus(tools) {
252
+ console.log('');
253
+ console.log(chalk_1.default.blue('[INFO] Tool Status:'));
254
+ if (tools.ripgrep.installed) {
255
+ console.log(chalk_1.default.green(` [OK] ripgrep: ${tools.ripgrep.path} (v${tools.ripgrep.version})`));
256
+ }
257
+ else {
258
+ console.log(chalk_1.default.yellow(' [--] ripgrep: not installed (using grep fallback)'));
259
+ }
260
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@esotech/contextuate",
3
- "version": "2.1.1",
3
+ "version": "2.1.2",
4
4
  "description": "**Standardized AI Context for Software Projects**",
5
5
  "main": "dist/index.js",
6
6
  "bin": {