prjct-cli 0.8.6 → 0.9.1
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/CHANGELOG.md +216 -0
- package/CLAUDE.md +34 -0
- package/core/agentic/agent-router.js +482 -0
- package/core/agentic/command-executor.js +70 -15
- package/core/agentic/context-builder.js +4 -3
- package/core/agentic/context-filter.js +545 -0
- package/core/agentic/prompt-builder.js +48 -38
- package/core/agentic/tool-registry.js +35 -0
- package/core/command-registry.js +104 -164
- package/core/commands.js +84 -0
- package/core/domain/agent-generator.js +55 -44
- package/core/domain/architecture-generator.js +561 -0
- package/core/domain/task-stack.js +496 -0
- package/core/infrastructure/legacy-installer-detector.js +546 -0
- package/core/infrastructure/session-manager.js +14 -2
- package/core/infrastructure/setup.js +29 -11
- package/core/utils/jsonl-helper.js +137 -0
- package/package.json +1 -1
- package/scripts/install.sh +45 -8
- package/scripts/postinstall.js +5 -5
- package/templates/agents/AGENTS.md +3 -3
- package/templates/commands/analyze.md +10 -53
- package/templates/commands/ask.md +25 -338
- package/templates/commands/bug.md +11 -70
- package/templates/commands/build.md +8 -35
- package/templates/commands/cleanup.md +9 -32
- package/templates/commands/dash.md +241 -0
- package/templates/commands/design.md +5 -28
- package/templates/commands/done.md +6 -20
- package/templates/commands/feature.md +12 -225
- package/templates/commands/help.md +26 -313
- package/templates/commands/idea.md +7 -25
- package/templates/commands/init.md +15 -191
- package/templates/commands/migrate-all.md +25 -84
- package/templates/commands/next.md +6 -26
- package/templates/commands/now.md +6 -25
- package/templates/commands/pause.md +18 -0
- package/templates/commands/progress.md +5 -50
- package/templates/commands/recap.md +5 -54
- package/templates/commands/resume.md +97 -0
- package/templates/commands/ship.md +14 -135
- package/templates/commands/status.md +7 -32
- package/templates/commands/suggest.md +36 -495
- package/templates/commands/sync.md +7 -24
- package/templates/commands/work.md +44 -0
- package/templates/commands/workflow.md +3 -25
- package/templates/planning-methodology.md +195 -0
|
@@ -0,0 +1,545 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Intelligent Context Filtering System
|
|
3
|
+
*
|
|
4
|
+
* Reduces context window usage by 70-90% by loading only
|
|
5
|
+
* relevant files for each specialized agent
|
|
6
|
+
*
|
|
7
|
+
* @version 1.0.0
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
const fs = require('fs').promises;
|
|
11
|
+
const path = require('path');
|
|
12
|
+
const glob = require('glob');
|
|
13
|
+
const { promisify } = require('util');
|
|
14
|
+
const globAsync = promisify(glob);
|
|
15
|
+
|
|
16
|
+
class ContextFilter {
|
|
17
|
+
constructor() {
|
|
18
|
+
// Technology-specific file patterns
|
|
19
|
+
this.techPatterns = this.initializeTechPatterns();
|
|
20
|
+
|
|
21
|
+
// Task-based filtering rules
|
|
22
|
+
this.taskPatterns = this.initializeTaskPatterns();
|
|
23
|
+
|
|
24
|
+
// Cache for file analysis
|
|
25
|
+
this.fileCache = new Map();
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Main entry point - filters context based on agent and task
|
|
30
|
+
*/
|
|
31
|
+
async filterForAgent(agent, task, projectPath, fullContext = {}) {
|
|
32
|
+
const startTime = Date.now();
|
|
33
|
+
|
|
34
|
+
// Determine what files this agent needs
|
|
35
|
+
const relevantPatterns = await this.determineRelevantPatterns(
|
|
36
|
+
agent,
|
|
37
|
+
task,
|
|
38
|
+
projectPath
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
// Load only relevant files
|
|
42
|
+
const filteredFiles = await this.loadRelevantFiles(
|
|
43
|
+
projectPath,
|
|
44
|
+
relevantPatterns
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
// Calculate reduction metrics
|
|
48
|
+
const metrics = this.calculateMetrics(
|
|
49
|
+
fullContext.fileCount || 1000, // estimate if not provided
|
|
50
|
+
filteredFiles.length,
|
|
51
|
+
startTime
|
|
52
|
+
);
|
|
53
|
+
|
|
54
|
+
return {
|
|
55
|
+
files: filteredFiles,
|
|
56
|
+
patterns: relevantPatterns,
|
|
57
|
+
metrics,
|
|
58
|
+
agent: agent.name,
|
|
59
|
+
filtered: true
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Initialize technology-specific patterns
|
|
65
|
+
*/
|
|
66
|
+
initializeTechPatterns() {
|
|
67
|
+
return {
|
|
68
|
+
// Languages
|
|
69
|
+
javascript: {
|
|
70
|
+
extensions: ['.js', '.mjs', '.cjs'],
|
|
71
|
+
directories: ['src', 'lib', 'utils'],
|
|
72
|
+
exclude: ['node_modules', 'dist', 'build']
|
|
73
|
+
},
|
|
74
|
+
typescript: {
|
|
75
|
+
extensions: ['.ts', '.tsx', '.d.ts'],
|
|
76
|
+
directories: ['src', 'lib', 'types'],
|
|
77
|
+
exclude: ['node_modules', 'dist', 'build']
|
|
78
|
+
},
|
|
79
|
+
python: {
|
|
80
|
+
extensions: ['.py', '.pyx'],
|
|
81
|
+
directories: ['src', 'lib', 'app'],
|
|
82
|
+
exclude: ['__pycache__', 'venv', '.env']
|
|
83
|
+
},
|
|
84
|
+
ruby: {
|
|
85
|
+
extensions: ['.rb', '.rake'],
|
|
86
|
+
directories: ['app', 'lib', 'config'],
|
|
87
|
+
exclude: ['vendor', 'tmp', 'log']
|
|
88
|
+
},
|
|
89
|
+
go: {
|
|
90
|
+
extensions: ['.go'],
|
|
91
|
+
directories: ['pkg', 'cmd', 'internal'],
|
|
92
|
+
exclude: ['vendor', 'bin']
|
|
93
|
+
},
|
|
94
|
+
rust: {
|
|
95
|
+
extensions: ['.rs'],
|
|
96
|
+
directories: ['src', 'lib'],
|
|
97
|
+
exclude: ['target', 'dist']
|
|
98
|
+
},
|
|
99
|
+
java: {
|
|
100
|
+
extensions: ['.java'],
|
|
101
|
+
directories: ['src/main/java', 'src/test/java'],
|
|
102
|
+
exclude: ['target', 'build', '.gradle']
|
|
103
|
+
},
|
|
104
|
+
php: {
|
|
105
|
+
extensions: ['.php'],
|
|
106
|
+
directories: ['src', 'app', 'lib'],
|
|
107
|
+
exclude: ['vendor', 'cache']
|
|
108
|
+
},
|
|
109
|
+
elixir: {
|
|
110
|
+
extensions: ['.ex', '.exs'],
|
|
111
|
+
directories: ['lib', 'web', 'apps'],
|
|
112
|
+
exclude: ['_build', 'deps', 'cover']
|
|
113
|
+
},
|
|
114
|
+
|
|
115
|
+
// Frameworks
|
|
116
|
+
react: {
|
|
117
|
+
extensions: ['.jsx', '.tsx', '.js', '.ts'],
|
|
118
|
+
directories: ['components', 'pages', 'hooks', 'contexts'],
|
|
119
|
+
patterns: ['**/components/**', '**/pages/**', '**/hooks/**'],
|
|
120
|
+
exclude: ['node_modules', 'build', 'dist']
|
|
121
|
+
},
|
|
122
|
+
vue: {
|
|
123
|
+
extensions: ['.vue', '.js', '.ts'],
|
|
124
|
+
directories: ['components', 'views', 'stores'],
|
|
125
|
+
patterns: ['**/*.vue', '**/components/**'],
|
|
126
|
+
exclude: ['node_modules', 'dist']
|
|
127
|
+
},
|
|
128
|
+
angular: {
|
|
129
|
+
extensions: ['.ts', '.html', '.scss'],
|
|
130
|
+
directories: ['src/app'],
|
|
131
|
+
patterns: ['**/*.component.ts', '**/*.service.ts'],
|
|
132
|
+
exclude: ['node_modules', 'dist']
|
|
133
|
+
},
|
|
134
|
+
rails: {
|
|
135
|
+
extensions: ['.rb', '.erb', '.haml'],
|
|
136
|
+
directories: ['app', 'config', 'db'],
|
|
137
|
+
patterns: ['app/**/*.rb', 'config/**/*.rb'],
|
|
138
|
+
exclude: ['tmp', 'log', 'vendor']
|
|
139
|
+
},
|
|
140
|
+
django: {
|
|
141
|
+
extensions: ['.py', '.html'],
|
|
142
|
+
directories: ['apps', 'templates', 'static'],
|
|
143
|
+
patterns: ['**/*.py', 'templates/**'],
|
|
144
|
+
exclude: ['venv', '__pycache__', 'media']
|
|
145
|
+
},
|
|
146
|
+
express: {
|
|
147
|
+
extensions: ['.js', '.ts'],
|
|
148
|
+
directories: ['routes', 'controllers', 'middleware'],
|
|
149
|
+
patterns: ['routes/**', 'controllers/**'],
|
|
150
|
+
exclude: ['node_modules', 'public']
|
|
151
|
+
},
|
|
152
|
+
fastapi: {
|
|
153
|
+
extensions: ['.py'],
|
|
154
|
+
directories: ['app', 'api', 'routers'],
|
|
155
|
+
patterns: ['app/**/*.py', 'api/**/*.py'],
|
|
156
|
+
exclude: ['venv', '__pycache__']
|
|
157
|
+
},
|
|
158
|
+
|
|
159
|
+
// Databases
|
|
160
|
+
postgres: {
|
|
161
|
+
extensions: ['.sql', '.plpgsql'],
|
|
162
|
+
directories: ['migrations', 'schemas', 'functions'],
|
|
163
|
+
patterns: ['**/*.sql', 'migrations/**'],
|
|
164
|
+
exclude: []
|
|
165
|
+
},
|
|
166
|
+
mongodb: {
|
|
167
|
+
extensions: ['.js', '.ts', '.json'],
|
|
168
|
+
directories: ['models', 'schemas'],
|
|
169
|
+
patterns: ['models/**', 'schemas/**'],
|
|
170
|
+
exclude: []
|
|
171
|
+
},
|
|
172
|
+
mysql: {
|
|
173
|
+
extensions: ['.sql'],
|
|
174
|
+
directories: ['migrations', 'schemas'],
|
|
175
|
+
patterns: ['**/*.sql'],
|
|
176
|
+
exclude: []
|
|
177
|
+
}
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Initialize task-based patterns
|
|
183
|
+
*/
|
|
184
|
+
initializeTaskPatterns() {
|
|
185
|
+
return {
|
|
186
|
+
api: {
|
|
187
|
+
include: ['routes', 'controllers', 'middleware', 'api'],
|
|
188
|
+
patterns: ['**/api/**', '**/routes/**', '**/controllers/**'],
|
|
189
|
+
focus: 'backend logic and endpoints'
|
|
190
|
+
},
|
|
191
|
+
ui: {
|
|
192
|
+
include: ['components', 'pages', 'views', 'styles'],
|
|
193
|
+
patterns: ['**/components/**', '**/pages/**', '**/*.css', '**/*.scss'],
|
|
194
|
+
focus: 'user interface and styling'
|
|
195
|
+
},
|
|
196
|
+
database: {
|
|
197
|
+
include: ['models', 'migrations', 'schemas', 'db'],
|
|
198
|
+
patterns: ['**/models/**', '**/migrations/**', '**/*.sql'],
|
|
199
|
+
focus: 'data layer and persistence'
|
|
200
|
+
},
|
|
201
|
+
testing: {
|
|
202
|
+
include: ['test', 'tests', 'spec', '__tests__'],
|
|
203
|
+
patterns: ['**/*.test.*', '**/*.spec.*', '**/test/**'],
|
|
204
|
+
focus: 'test files and test utilities'
|
|
205
|
+
},
|
|
206
|
+
configuration: {
|
|
207
|
+
include: ['config', 'env', 'settings'],
|
|
208
|
+
patterns: ['**/config/**', '**/.env*', '**/*config.*'],
|
|
209
|
+
focus: 'configuration and environment'
|
|
210
|
+
},
|
|
211
|
+
deployment: {
|
|
212
|
+
include: ['.github', '.gitlab', 'docker', 'k8s'],
|
|
213
|
+
patterns: ['Dockerfile*', '**/*.yml', '**/*.yaml', '.github/**'],
|
|
214
|
+
focus: 'CI/CD and deployment'
|
|
215
|
+
},
|
|
216
|
+
documentation: {
|
|
217
|
+
include: ['docs', 'README'],
|
|
218
|
+
patterns: ['**/*.md', 'docs/**', 'README*'],
|
|
219
|
+
focus: 'documentation files'
|
|
220
|
+
}
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* Determine which patterns to use based on agent and task
|
|
226
|
+
*/
|
|
227
|
+
async determineRelevantPatterns(agent, task, projectPath) {
|
|
228
|
+
const patterns = {
|
|
229
|
+
include: [],
|
|
230
|
+
exclude: [],
|
|
231
|
+
extensions: [],
|
|
232
|
+
specific: []
|
|
233
|
+
};
|
|
234
|
+
|
|
235
|
+
// Detect technologies in the project
|
|
236
|
+
const detectedTech = await this.detectProjectTechnologies(projectPath);
|
|
237
|
+
|
|
238
|
+
// Add patterns based on detected technologies
|
|
239
|
+
detectedTech.forEach(tech => {
|
|
240
|
+
if (this.techPatterns[tech]) {
|
|
241
|
+
const techPattern = this.techPatterns[tech];
|
|
242
|
+
patterns.extensions.push(...(techPattern.extensions || []));
|
|
243
|
+
patterns.include.push(...(techPattern.directories || []));
|
|
244
|
+
patterns.exclude.push(...(techPattern.exclude || []));
|
|
245
|
+
patterns.specific.push(...(techPattern.patterns || []));
|
|
246
|
+
}
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
// Add patterns based on task type
|
|
250
|
+
const taskType = this.detectTaskType(task);
|
|
251
|
+
if (this.taskPatterns[taskType]) {
|
|
252
|
+
const taskPattern = this.taskPatterns[taskType];
|
|
253
|
+
patterns.include.push(...(taskPattern.include || []));
|
|
254
|
+
patterns.specific.push(...(taskPattern.patterns || []));
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
// Add agent-specific patterns
|
|
258
|
+
const agentPatterns = this.getAgentSpecificPatterns(agent);
|
|
259
|
+
patterns.include.push(...agentPatterns.include);
|
|
260
|
+
patterns.exclude.push(...agentPatterns.exclude);
|
|
261
|
+
|
|
262
|
+
// Remove duplicates
|
|
263
|
+
patterns.include = [...new Set(patterns.include)];
|
|
264
|
+
patterns.exclude = [...new Set(patterns.exclude)];
|
|
265
|
+
patterns.extensions = [...new Set(patterns.extensions)];
|
|
266
|
+
patterns.specific = [...new Set(patterns.specific)];
|
|
267
|
+
|
|
268
|
+
return patterns;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* Detect technologies used in the project
|
|
273
|
+
*/
|
|
274
|
+
async detectProjectTechnologies(projectPath) {
|
|
275
|
+
const detected = new Set();
|
|
276
|
+
|
|
277
|
+
try {
|
|
278
|
+
// Check package.json for JS/TS projects
|
|
279
|
+
const packageJsonPath = path.join(projectPath, 'package.json');
|
|
280
|
+
if (await this.fileExists(packageJsonPath)) {
|
|
281
|
+
const packageJson = JSON.parse(await fs.readFile(packageJsonPath, 'utf8'));
|
|
282
|
+
|
|
283
|
+
// Check dependencies
|
|
284
|
+
const deps = {
|
|
285
|
+
...packageJson.dependencies,
|
|
286
|
+
...packageJson.devDependencies
|
|
287
|
+
};
|
|
288
|
+
|
|
289
|
+
// Detect frameworks
|
|
290
|
+
if (deps.react) detected.add('react');
|
|
291
|
+
if (deps.vue) detected.add('vue');
|
|
292
|
+
if (deps['@angular/core']) detected.add('angular');
|
|
293
|
+
if (deps.express) detected.add('express');
|
|
294
|
+
if (deps.next) detected.add('nextjs');
|
|
295
|
+
if (deps.fastify) detected.add('fastify');
|
|
296
|
+
|
|
297
|
+
// Language
|
|
298
|
+
if (deps.typescript) detected.add('typescript');
|
|
299
|
+
else detected.add('javascript');
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
// Check Gemfile for Ruby projects
|
|
303
|
+
const gemfilePath = path.join(projectPath, 'Gemfile');
|
|
304
|
+
if (await this.fileExists(gemfilePath)) {
|
|
305
|
+
detected.add('ruby');
|
|
306
|
+
const gemfile = await fs.readFile(gemfilePath, 'utf8');
|
|
307
|
+
if (gemfile.includes('rails')) detected.add('rails');
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
// Check requirements.txt or setup.py for Python
|
|
311
|
+
const requirementsPath = path.join(projectPath, 'requirements.txt');
|
|
312
|
+
const setupPyPath = path.join(projectPath, 'setup.py');
|
|
313
|
+
if (await this.fileExists(requirementsPath) || await this.fileExists(setupPyPath)) {
|
|
314
|
+
detected.add('python');
|
|
315
|
+
|
|
316
|
+
if (await this.fileExists(requirementsPath)) {
|
|
317
|
+
const requirements = await fs.readFile(requirementsPath, 'utf8');
|
|
318
|
+
if (requirements.includes('django')) detected.add('django');
|
|
319
|
+
if (requirements.includes('fastapi')) detected.add('fastapi');
|
|
320
|
+
if (requirements.includes('flask')) detected.add('flask');
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
// Check go.mod for Go projects
|
|
325
|
+
const goModPath = path.join(projectPath, 'go.mod');
|
|
326
|
+
if (await this.fileExists(goModPath)) {
|
|
327
|
+
detected.add('go');
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
// Check Cargo.toml for Rust
|
|
331
|
+
const cargoPath = path.join(projectPath, 'Cargo.toml');
|
|
332
|
+
if (await this.fileExists(cargoPath)) {
|
|
333
|
+
detected.add('rust');
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
// Check mix.exs for Elixir
|
|
337
|
+
const mixPath = path.join(projectPath, 'mix.exs');
|
|
338
|
+
if (await this.fileExists(mixPath)) {
|
|
339
|
+
detected.add('elixir');
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
// Check for Java/Maven/Gradle
|
|
343
|
+
const pomPath = path.join(projectPath, 'pom.xml');
|
|
344
|
+
const gradlePath = path.join(projectPath, 'build.gradle');
|
|
345
|
+
if (await this.fileExists(pomPath) || await this.fileExists(gradlePath)) {
|
|
346
|
+
detected.add('java');
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
// Check composer.json for PHP
|
|
350
|
+
const composerPath = path.join(projectPath, 'composer.json');
|
|
351
|
+
if (await this.fileExists(composerPath)) {
|
|
352
|
+
detected.add('php');
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
} catch (error) {
|
|
356
|
+
console.error('Error detecting technologies:', error.message);
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
return Array.from(detected);
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
/**
|
|
363
|
+
* Detect task type from description
|
|
364
|
+
*/
|
|
365
|
+
detectTaskType(task) {
|
|
366
|
+
const description = (task.description || '').toLowerCase();
|
|
367
|
+
|
|
368
|
+
if (description.includes('api') || description.includes('endpoint')) {
|
|
369
|
+
return 'api';
|
|
370
|
+
}
|
|
371
|
+
if (description.includes('ui') || description.includes('component') || description.includes('style')) {
|
|
372
|
+
return 'ui';
|
|
373
|
+
}
|
|
374
|
+
if (description.includes('database') || description.includes('migration') || description.includes('schema')) {
|
|
375
|
+
return 'database';
|
|
376
|
+
}
|
|
377
|
+
if (description.includes('test') || description.includes('spec')) {
|
|
378
|
+
return 'testing';
|
|
379
|
+
}
|
|
380
|
+
if (description.includes('deploy') || description.includes('docker') || description.includes('ci')) {
|
|
381
|
+
return 'deployment';
|
|
382
|
+
}
|
|
383
|
+
if (description.includes('config') || description.includes('env')) {
|
|
384
|
+
return 'configuration';
|
|
385
|
+
}
|
|
386
|
+
if (description.includes('docs') || description.includes('readme')) {
|
|
387
|
+
return 'documentation';
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
return 'general';
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
/**
|
|
394
|
+
* Get agent-specific patterns
|
|
395
|
+
*/
|
|
396
|
+
getAgentSpecificPatterns(agent) {
|
|
397
|
+
const agentType = (agent.type || agent.name || '').toLowerCase();
|
|
398
|
+
|
|
399
|
+
const patterns = {
|
|
400
|
+
'frontend': {
|
|
401
|
+
include: ['components', 'pages', 'views', 'styles', 'public'],
|
|
402
|
+
exclude: ['backend', 'api', 'server', 'database']
|
|
403
|
+
},
|
|
404
|
+
'backend': {
|
|
405
|
+
include: ['api', 'routes', 'controllers', 'services', 'middleware'],
|
|
406
|
+
exclude: ['components', 'styles', 'public']
|
|
407
|
+
},
|
|
408
|
+
'database': {
|
|
409
|
+
include: ['models', 'schemas', 'migrations', 'db'],
|
|
410
|
+
exclude: ['components', 'styles', 'public', 'static']
|
|
411
|
+
},
|
|
412
|
+
'devops': {
|
|
413
|
+
include: ['.github', '.gitlab', 'docker', 'k8s', 'terraform'],
|
|
414
|
+
exclude: ['src', 'app', 'components']
|
|
415
|
+
},
|
|
416
|
+
'qa': {
|
|
417
|
+
include: ['test', 'tests', 'spec', '__tests__', 'cypress'],
|
|
418
|
+
exclude: ['src', 'app', 'public']
|
|
419
|
+
}
|
|
420
|
+
};
|
|
421
|
+
|
|
422
|
+
// Find matching pattern
|
|
423
|
+
for (const [key, pattern] of Object.entries(patterns)) {
|
|
424
|
+
if (agentType.includes(key)) {
|
|
425
|
+
return pattern;
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
// Default pattern
|
|
430
|
+
return {
|
|
431
|
+
include: [],
|
|
432
|
+
exclude: ['node_modules', 'vendor', 'dist', 'build', '.git']
|
|
433
|
+
};
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
/**
|
|
437
|
+
* Load only relevant files based on patterns
|
|
438
|
+
*/
|
|
439
|
+
async loadRelevantFiles(projectPath, patterns) {
|
|
440
|
+
const files = [];
|
|
441
|
+
|
|
442
|
+
try {
|
|
443
|
+
// Build glob patterns
|
|
444
|
+
const globPatterns = this.buildGlobPatterns(patterns);
|
|
445
|
+
|
|
446
|
+
// Execute glob searches
|
|
447
|
+
for (const pattern of globPatterns) {
|
|
448
|
+
const matches = await globAsync(pattern, {
|
|
449
|
+
cwd: projectPath,
|
|
450
|
+
ignore: patterns.exclude,
|
|
451
|
+
nodir: true,
|
|
452
|
+
follow: false
|
|
453
|
+
});
|
|
454
|
+
|
|
455
|
+
files.push(...matches);
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
// Remove duplicates and sort
|
|
459
|
+
const uniqueFiles = [...new Set(files)].sort();
|
|
460
|
+
|
|
461
|
+
// Limit to reasonable number
|
|
462
|
+
const maxFiles = 100;
|
|
463
|
+
if (uniqueFiles.length > maxFiles) {
|
|
464
|
+
console.log(`Limiting context to ${maxFiles} most relevant files`);
|
|
465
|
+
return uniqueFiles.slice(0, maxFiles);
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
return uniqueFiles;
|
|
469
|
+
|
|
470
|
+
} catch (error) {
|
|
471
|
+
console.error('Error loading files:', error.message);
|
|
472
|
+
return [];
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
/**
|
|
477
|
+
* Build glob patterns from pattern configuration
|
|
478
|
+
*/
|
|
479
|
+
buildGlobPatterns(patterns) {
|
|
480
|
+
const globs = [];
|
|
481
|
+
|
|
482
|
+
// Add specific patterns
|
|
483
|
+
globs.push(...patterns.specific);
|
|
484
|
+
|
|
485
|
+
// Add extension-based patterns
|
|
486
|
+
if (patterns.extensions.length > 0) {
|
|
487
|
+
const extPattern = `**/*{${patterns.extensions.join(',')}}`;
|
|
488
|
+
globs.push(extPattern);
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
// Add directory patterns
|
|
492
|
+
patterns.include.forEach(dir => {
|
|
493
|
+
globs.push(`${dir}/**/*`);
|
|
494
|
+
});
|
|
495
|
+
|
|
496
|
+
// Default pattern if none specified
|
|
497
|
+
if (globs.length === 0) {
|
|
498
|
+
globs.push('**/*.{js,ts,jsx,tsx,py,rb,go,java,php}');
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
return globs;
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
/**
|
|
505
|
+
* Calculate metrics for context reduction
|
|
506
|
+
*/
|
|
507
|
+
calculateMetrics(originalCount, filteredCount, startTime) {
|
|
508
|
+
const reduction = originalCount > 0
|
|
509
|
+
? Math.round(((originalCount - filteredCount) / originalCount) * 100)
|
|
510
|
+
: 0;
|
|
511
|
+
|
|
512
|
+
return {
|
|
513
|
+
originalFiles: originalCount,
|
|
514
|
+
filteredFiles: filteredCount,
|
|
515
|
+
reductionPercent: reduction,
|
|
516
|
+
processingTime: Date.now() - startTime,
|
|
517
|
+
effectiveness: reduction > 70 ? 'high' : reduction > 40 ? 'medium' : 'low'
|
|
518
|
+
};
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
/**
|
|
522
|
+
* Check if file exists
|
|
523
|
+
*/
|
|
524
|
+
async fileExists(filePath) {
|
|
525
|
+
try {
|
|
526
|
+
await fs.access(filePath);
|
|
527
|
+
return true;
|
|
528
|
+
} catch {
|
|
529
|
+
return false;
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
/**
|
|
534
|
+
* Get filter statistics
|
|
535
|
+
*/
|
|
536
|
+
getStatistics() {
|
|
537
|
+
return {
|
|
538
|
+
cachedFiles: this.fileCache.size,
|
|
539
|
+
supportedTechnologies: Object.keys(this.techPatterns).length,
|
|
540
|
+
taskTypes: Object.keys(this.taskPatterns).length
|
|
541
|
+
};
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
module.exports = ContextFilter;
|
|
@@ -6,61 +6,71 @@
|
|
|
6
6
|
|
|
7
7
|
class PromptBuilder {
|
|
8
8
|
/**
|
|
9
|
-
* Build
|
|
10
|
-
* @param {Object} template - Template from template-loader
|
|
11
|
-
* @param {Object} context - Context from context-builder
|
|
12
|
-
* @param {Object} state - Current state from context-builder
|
|
13
|
-
* @returns {string} Prompt for Claude
|
|
9
|
+
* Build concise prompt - only essentials
|
|
14
10
|
*/
|
|
15
|
-
build(template, context, state) {
|
|
11
|
+
build(template, context, state, agent = null) {
|
|
16
12
|
const parts = []
|
|
17
13
|
|
|
18
|
-
//
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
14
|
+
// Agent assignment (if applicable)
|
|
15
|
+
if (agent) {
|
|
16
|
+
parts.push(`AGENT: ${agent.name}\n`)
|
|
17
|
+
parts.push(`CONTEXT: ${context.filteredSize || 'all'} files (${context.reduction || 0}% reduced)\n\n`)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// Core instruction (concise)
|
|
21
|
+
parts.push(`TASK: ${template.frontmatter.description}\n`)
|
|
22
22
|
|
|
23
|
-
//
|
|
23
|
+
// Tools (inline)
|
|
24
24
|
if (template.frontmatter['allowed-tools']) {
|
|
25
|
-
parts.push('
|
|
26
|
-
parts.push(`You can use: ${template.frontmatter['allowed-tools'].join(', ')}\n\n`)
|
|
25
|
+
parts.push(`TOOLS: ${template.frontmatter['allowed-tools'].join(', ')}\n`)
|
|
27
26
|
}
|
|
28
27
|
|
|
29
|
-
//
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
parts.push('\n')
|
|
28
|
+
// Critical parameters only
|
|
29
|
+
if (context.params?.task || context.params?.description) {
|
|
30
|
+
parts.push(`INPUT: ${context.params.task || context.params.description}\n`)
|
|
31
|
+
}
|
|
34
32
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
33
|
+
parts.push('\n---\n')
|
|
34
|
+
|
|
35
|
+
// Template (only the flow section, skip verbose explanations)
|
|
36
|
+
const flowMatch = template.content.match(/## Flow([\s\S]*?)(?=##|$)/)
|
|
37
|
+
if (flowMatch) {
|
|
38
|
+
parts.push(flowMatch[0])
|
|
39
|
+
} else {
|
|
40
|
+
// Fallback to full template if no flow section
|
|
41
|
+
parts.push(template.content)
|
|
44
42
|
}
|
|
45
43
|
|
|
46
|
-
//
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
}
|
|
44
|
+
// Current state (only if exists and relevant)
|
|
45
|
+
const relevantState = this.filterRelevantState(state)
|
|
46
|
+
if (relevantState) {
|
|
47
|
+
parts.push('\nSTATE:\n')
|
|
48
|
+
parts.push(relevantState)
|
|
52
49
|
parts.push('\n')
|
|
53
50
|
}
|
|
54
51
|
|
|
55
|
-
//
|
|
56
|
-
parts.push('
|
|
57
|
-
parts.push('Based on the instructions above, execute the command.\n')
|
|
58
|
-
parts.push('Use ONLY the allowed tools.\n')
|
|
59
|
-
parts.push('Make decisions based on context - do not follow rigid if/else rules.\n')
|
|
52
|
+
// Simple execution directive
|
|
53
|
+
parts.push('\nEXECUTE: Follow flow. Use tools. Decide.\n')
|
|
60
54
|
|
|
61
55
|
return parts.join('')
|
|
62
56
|
}
|
|
63
57
|
|
|
58
|
+
/**
|
|
59
|
+
* Filter only relevant state data
|
|
60
|
+
*/
|
|
61
|
+
filterRelevantState(state) {
|
|
62
|
+
if (!state || Object.keys(state).length === 0) return null
|
|
63
|
+
|
|
64
|
+
const relevant = []
|
|
65
|
+
for (const [key, content] of Object.entries(state)) {
|
|
66
|
+
if (content && content.trim() && content.length < 500) {
|
|
67
|
+
relevant.push(`${key}: ${content.substring(0, 200)}`)
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return relevant.length > 0 ? relevant.join('\n') : null
|
|
72
|
+
}
|
|
73
|
+
|
|
64
74
|
/**
|
|
65
75
|
* Build analysis prompt
|
|
66
76
|
* Used for tasks that need Claude to analyze before acting
|