@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.
- package/dist/commands/doctor.d.ts +6 -0
- package/dist/commands/doctor.js +131 -0
- package/dist/commands/init.d.ts +0 -2
- package/dist/commands/init.js +164 -228
- package/dist/index.js +7 -0
- package/dist/templates/agents/aegis.md +1 -1
- package/dist/templates/agents/archon.md +116 -8
- package/dist/templates/agents/atlas.md +17 -17
- package/dist/templates/agents/canvas.md +1 -1
- package/dist/templates/agents/chronicle.md +1 -1
- package/dist/templates/agents/chronos.md +1 -1
- package/dist/templates/agents/cipher.md +1 -1
- package/dist/templates/agents/crucible.md +1 -1
- package/dist/templates/agents/echo.md +1 -1
- package/dist/templates/agents/forge.md +1 -1
- package/dist/templates/agents/ledger.md +34 -3
- package/dist/templates/agents/meridian.md +1 -1
- package/dist/templates/agents/nexus.md +1 -1
- package/dist/templates/agents/pythia.md +1 -1
- package/dist/templates/agents/scribe.md +1 -1
- package/dist/templates/agents/sentinel.md +1 -1
- package/dist/templates/agents/thoth.md +1 -1
- package/dist/templates/agents/unity.md +1 -1
- package/dist/templates/agents/vox.md +1 -1
- package/dist/templates/agents/weaver.md +1 -1
- package/dist/templates/commands/consult.md +1 -1
- package/dist/templates/commands/orchestrate.md +5 -129
- package/dist/templates/framework-agents/documentation-expert.md +3 -3
- package/dist/templates/framework-agents/tools-expert.md +3 -3
- package/dist/templates/templates/contextuate.md +1 -1
- package/dist/templates/tools/agent-creator.md +4 -4
- package/dist/templates/tools/standards-detector.md +1 -1
- package/dist/utils/tools.d.ts +60 -0
- package/dist/utils/tools.js +260 -0
- 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. **[
|
|
24
|
-
2. **[
|
|
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 [
|
|
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
|
|
|
@@ -78,7 +78,7 @@ Verify:
|
|
|
78
78
|
```markdown
|
|
79
79
|
# {Name} Expert Agent
|
|
80
80
|
|
|
81
|
-
> **Inherits:** [
|
|
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:** [
|
|
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. **[
|
|
197
|
-
2. **[
|
|
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
|
+
}
|