@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.
- package/LICENSE +21 -0
- package/README.md +287 -0
- package/dist/commands/context.js +80 -0
- package/dist/commands/create.js +93 -0
- package/dist/commands/index.js +46 -0
- package/dist/commands/init.js +452 -0
- package/dist/commands/install.js +359 -0
- package/dist/commands/remove.js +77 -0
- package/dist/commands/run.js +205 -0
- package/dist/index.js +96 -0
- package/dist/runtime/driver.js +64 -0
- package/dist/runtime/tools.js +48 -0
- package/dist/templates/README.md +152 -0
- package/dist/templates/agents/aegis.md +366 -0
- package/dist/templates/agents/archon.md +247 -0
- package/dist/templates/agents/atlas.md +326 -0
- package/dist/templates/agents/canvas.md +19 -0
- package/dist/templates/agents/chronicle.md +424 -0
- package/dist/templates/agents/chronos.md +20 -0
- package/dist/templates/agents/cipher.md +360 -0
- package/dist/templates/agents/crucible.md +375 -0
- package/dist/templates/agents/echo.md +297 -0
- package/dist/templates/agents/forge.md +613 -0
- package/dist/templates/agents/ledger.md +317 -0
- package/dist/templates/agents/meridian.md +281 -0
- package/dist/templates/agents/nexus.md +600 -0
- package/dist/templates/agents/oracle.md +281 -0
- package/dist/templates/agents/scribe.md +612 -0
- package/dist/templates/agents/sentinel.md +312 -0
- package/dist/templates/agents/unity.md +17 -0
- package/dist/templates/agents/vox.md +19 -0
- package/dist/templates/agents/weaver.md +334 -0
- package/dist/templates/framework-agents/base.md +166 -0
- package/dist/templates/framework-agents/documentation-expert.md +292 -0
- package/dist/templates/framework-agents/tools-expert.md +245 -0
- package/dist/templates/standards/agent-roles.md +34 -0
- package/dist/templates/standards/agent-workflow.md +170 -0
- package/dist/templates/standards/behavioral-guidelines.md +145 -0
- package/dist/templates/standards/coding-standards.md +171 -0
- package/dist/templates/standards/task-workflow.md +246 -0
- package/dist/templates/templates/context.md +33 -0
- package/dist/templates/templates/contextuate.md +109 -0
- package/dist/templates/templates/platforms/AGENTS.md +5 -0
- package/dist/templates/templates/platforms/CLAUDE.md +5 -0
- package/dist/templates/templates/platforms/GEMINI.md +5 -0
- package/dist/templates/templates/platforms/clinerules.md +5 -0
- package/dist/templates/templates/platforms/copilot.md +5 -0
- package/dist/templates/templates/platforms/cursor.mdc +9 -0
- package/dist/templates/templates/platforms/windsurf.md +5 -0
- package/dist/templates/templates/standards/go.standards.md +167 -0
- package/dist/templates/templates/standards/java.standards.md +167 -0
- package/dist/templates/templates/standards/javascript.standards.md +292 -0
- package/dist/templates/templates/standards/php.standards.md +181 -0
- package/dist/templates/templates/standards/python.standards.md +175 -0
- package/dist/templates/tools/agent-creator.tool.md +252 -0
- package/dist/templates/tools/quickref.tool.md +216 -0
- package/dist/templates/tools/spawn.tool.md +31 -0
- package/dist/templates/tools/standards-detector.tool.md +301 -0
- package/dist/templates/version.json +8 -0
- package/dist/utils/git.js +62 -0
- package/dist/utils/tokens.js +74 -0
- 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
|
+
}
|