aiwf 0.3.22 → 0.3.23
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/package.json +3 -2
- package/src/cli/index.js +39 -336
- package/src/lib/installer.js +294 -90
- package/src/utils/messages.js +24 -0
- package/src/DEPENDENCY_MAP.md +0 -90
- package/src/cli/cache-cli.js +0 -459
- package/src/cli/checkpoint-cli.js +0 -417
- package/src/cli/language-cli.js +0 -286
- package/src/cli/sprint-cli.js +0 -287
- package/src/commands/ai-tool.js +0 -383
- package/src/commands/compress.js +0 -60
- package/src/commands/create-project.js +0 -160
- package/src/commands/evaluate.js +0 -459
- package/src/commands/persona.js +0 -309
- package/src/commands/sprint-task.js +0 -262
- package/src/commands/token.js +0 -312
- package/src/lib/ai-persona-manager.js +0 -711
- package/src/lib/cache-system.js +0 -332
- package/src/lib/context-engine.js +0 -568
- package/src/lib/github-integration.js +0 -402
- package/src/lib/memory-profiler.js +0 -471
- package/src/lib/metrics-collector.js +0 -885
- package/src/lib/offline-detector.js +0 -386
- package/src/lib/resource-loader-enhanced.js +0 -399
- package/src/lib/resource-loader.js +0 -250
- package/src/lib/resources/commands/ai-persona.js +0 -602
- package/src/lib/resources/commands/compress-context.js +0 -389
- package/src/lib/resources/commands/evaluate.js +0 -246
- package/src/lib/resources/commands/persona-context-apply.js +0 -562
- package/src/lib/resources/commands/token-tracking.js +0 -443
- package/src/lib/resources/config/commit-patterns.js +0 -103
- package/src/lib/resources/config/language.json +0 -6
- package/src/lib/resources/personas/PERSONA_INDEX.md +0 -57
- package/src/lib/resources/personas/analyst.json +0 -44
- package/src/lib/resources/personas/architect/best_practices.md +0 -136
- package/src/lib/resources/personas/architect/knowledge_base.md +0 -377
- package/src/lib/resources/personas/architect.json +0 -44
- package/src/lib/resources/personas/backend/best_practices.md +0 -766
- package/src/lib/resources/personas/backend/knowledge_base.md +0 -1070
- package/src/lib/resources/personas/data_analyst/best_practices.md +0 -594
- package/src/lib/resources/personas/data_analyst/knowledge_base.md +0 -1057
- package/src/lib/resources/personas/developer.json +0 -44
- package/src/lib/resources/personas/developer.md +0 -37
- package/src/lib/resources/personas/evaluation_criteria.json +0 -137
- package/src/lib/resources/personas/frontend/best_practices.md +0 -445
- package/src/lib/resources/personas/frontend/knowledge_base.md +0 -729
- package/src/lib/resources/personas/persona-index.json +0 -31
- package/src/lib/resources/personas/reviewer.json +0 -44
- package/src/lib/resources/personas/security/best_practices.md +0 -307
- package/src/lib/resources/personas/security/knowledge_base.md +0 -498
- package/src/lib/resources/personas/tester.json +0 -44
- package/src/lib/resources/templates/README.md +0 -78
- package/src/lib/resources/templates/api-server/config.json +0 -64
- package/src/lib/resources/templates/api-server/template/.aiwf/config.json +0 -56
- package/src/lib/resources/templates/api-server/template/.aiwf/feature-ledger.json +0 -42
- package/src/lib/resources/templates/api-server/template/.aiwf/personas/backend-engineer.json +0 -40
- package/src/lib/resources/templates/api-server/template/.aiwf/scripts/cli.js +0 -111
- package/src/lib/resources/templates/api-server/template/.env.example +0 -29
- package/src/lib/resources/templates/api-server/template/.eslintrc.json +0 -23
- package/src/lib/resources/templates/api-server/template/README.md +0 -171
- package/src/lib/resources/templates/api-server/template/jest.config.js +0 -26
- package/src/lib/resources/templates/api-server/template/nodemon.json +0 -9
- package/src/lib/resources/templates/api-server/template/package.json +0 -61
- package/src/lib/resources/templates/api-server/template/src/app.ts +0 -60
- package/src/lib/resources/templates/api-server/template/src/config/swagger.ts +0 -38
- package/src/lib/resources/templates/api-server/template/src/controllers/aiwfController.ts +0 -54
- package/src/lib/resources/templates/api-server/template/src/controllers/authController.ts +0 -128
- package/src/lib/resources/templates/api-server/template/src/controllers/statusController.ts +0 -28
- package/src/lib/resources/templates/api-server/template/src/index.ts +0 -28
- package/src/lib/resources/templates/api-server/template/src/middleware/aiwfMiddleware.ts +0 -50
- package/src/lib/resources/templates/api-server/template/src/middleware/authMiddleware.ts +0 -41
- package/src/lib/resources/templates/api-server/template/src/middleware/errorHandler.ts +0 -42
- package/src/lib/resources/templates/api-server/template/src/middleware/notFoundHandler.ts +0 -14
- package/src/lib/resources/templates/api-server/template/src/middleware/requestLogger.ts +0 -20
- package/src/lib/resources/templates/api-server/template/src/routes/aiwf.ts +0 -31
- package/src/lib/resources/templates/api-server/template/src/routes/index.ts +0 -13
- package/src/lib/resources/templates/api-server/template/src/routes/v1/index.ts +0 -67
- package/src/lib/resources/templates/api-server/template/src/utils/logger.ts +0 -37
- package/src/lib/resources/templates/api-server/template/tests/app.test.ts +0 -40
- package/src/lib/resources/templates/api-server/template/tsconfig.json +0 -43
- package/src/lib/resources/templates/npm-library/config.json +0 -61
- package/src/lib/resources/templates/npm-library/template/LICENSE +0 -21
- package/src/lib/resources/templates/npm-library/template/README.md +0 -201
- package/src/lib/resources/templates/npm-library/template/package.json +0 -78
- package/src/lib/resources/templates/web-app/config.json +0 -53
- package/src/lib/resources/templates/web-app/template/.aiwf/config.json +0 -54
- package/src/lib/resources/templates/web-app/template/.aiwf/feature-ledger.json +0 -37
- package/src/lib/resources/templates/web-app/template/.aiwf/personas/fullstack-developer.json +0 -40
- package/src/lib/resources/templates/web-app/template/.aiwf/scripts/cli.js +0 -110
- package/src/lib/resources/templates/web-app/template/.eslintrc.cjs +0 -20
- package/src/lib/resources/templates/web-app/template/README.md +0 -151
- package/src/lib/resources/templates/web-app/template/index.html +0 -14
- package/src/lib/resources/templates/web-app/template/package.json +0 -44
- package/src/lib/resources/templates/web-app/template/postcss.config.js +0 -6
- package/src/lib/resources/templates/web-app/template/public/vite.svg +0 -1
- package/src/lib/resources/templates/web-app/template/src/App.tsx +0 -21
- package/src/lib/resources/templates/web-app/template/src/components/Layout.tsx +0 -57
- package/src/lib/resources/templates/web-app/template/src/components/aiwf/ContextStatus.tsx +0 -107
- package/src/lib/resources/templates/web-app/template/src/components/aiwf/TokenUsage.tsx +0 -71
- package/src/lib/resources/templates/web-app/template/src/index.css +0 -60
- package/src/lib/resources/templates/web-app/template/src/main.tsx +0 -10
- package/src/lib/resources/templates/web-app/template/src/pages/AiwfDashboard.tsx +0 -57
- package/src/lib/resources/templates/web-app/template/src/pages/HomePage.tsx +0 -89
- package/src/lib/resources/templates/web-app/template/src/pages/NotFound.tsx +0 -25
- package/src/lib/resources/templates/web-app/template/src/stores/aiwfStore.ts +0 -126
- package/src/lib/resources/templates/web-app/template/src/types/global.d.ts +0 -9
- package/src/lib/resources/templates/web-app/template/src/vite-env.d.ts +0 -1
- package/src/lib/resources/templates/web-app/template/tailwind.config.js +0 -30
- package/src/lib/resources/templates/web-app/template/tsconfig.json +0 -37
- package/src/lib/resources/templates/web-app/template/tsconfig.node.json +0 -10
- package/src/lib/resources/templates/web-app/template/vite.config.ts +0 -23
- package/src/lib/resources/utils/background-monitor.js +0 -223
- package/src/lib/resources/utils/compression-metrics.js +0 -1031
- package/src/lib/resources/utils/compression-strategies.js +0 -557
- package/src/lib/resources/utils/content-normalizer.js +0 -455
- package/src/lib/resources/utils/context-compressor.js +0 -583
- package/src/lib/resources/utils/context-rule-parser.js +0 -180
- package/src/lib/resources/utils/context-token-monitor.js +0 -463
- package/src/lib/resources/utils/context-update-manager.js +0 -502
- package/src/lib/resources/utils/git-utils.js +0 -220
- package/src/lib/resources/utils/importance-classifier.js +0 -645
- package/src/lib/resources/utils/information-filter.js +0 -710
- package/src/lib/resources/utils/persona-aware-compressor.js +0 -598
- package/src/lib/resources/utils/prompt-injector.js +0 -242
- package/src/lib/resources/utils/simplified-evaluator.js +0 -119
- package/src/lib/resources/utils/text-summarizer.js +0 -492
- package/src/lib/resources/utils/token-counter.js +0 -177
- package/src/lib/resources/utils/token-monitor.js +0 -484
- package/src/lib/resources/utils/token-reporter.js +0 -452
- package/src/lib/resources/utils/token-storage.js +0 -433
- package/src/lib/resources/utils/token-tracker.js +0 -283
- package/src/lib/state/priority-calculator.js +0 -217
- package/src/lib/state/state-index.js +0 -155
- package/src/lib/state/task-scanner.js +0 -328
- package/src/lib/task-analyzer.js +0 -599
- package/src/lib/template-cache-system.js +0 -559
- package/src/lib/template-downloader.js +0 -467
- package/src/lib/template-version-manager.js +0 -491
- package/src/lib/token-optimizer.js +0 -517
- package/src/utils/engineering-guard.js +0 -399
|
@@ -1,568 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Context Engine
|
|
3
|
-
* Manages context rules and content filtering for AI personas
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import fs from 'fs/promises';
|
|
7
|
-
import path from 'path';
|
|
8
|
-
import { EventEmitter } from 'events';
|
|
9
|
-
|
|
10
|
-
// Import token optimizer
|
|
11
|
-
import { TokenOptimizer } from './token-optimizer.js';
|
|
12
|
-
|
|
13
|
-
class ContextEngine extends EventEmitter {
|
|
14
|
-
constructor(options = {}) {
|
|
15
|
-
super();
|
|
16
|
-
|
|
17
|
-
this.options = {
|
|
18
|
-
maxContextSize: options.maxContextSize || 100000, // Max tokens
|
|
19
|
-
preserveBase: options.preserveBase !== false,
|
|
20
|
-
enableOptimization: options.enableOptimization !== false,
|
|
21
|
-
contextCachePath: options.contextCachePath ||
|
|
22
|
-
path.join(process.cwd(), '.aiwf', 'cache', 'context'),
|
|
23
|
-
...options
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
this.baseContext = null;
|
|
27
|
-
this.personaOverlay = null;
|
|
28
|
-
this.currentContext = null;
|
|
29
|
-
|
|
30
|
-
// Initialize token optimizer
|
|
31
|
-
this.tokenOptimizer = new TokenOptimizer(this.options);
|
|
32
|
-
|
|
33
|
-
// Context cache
|
|
34
|
-
this.contextCache = new Map();
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Initialize the context engine
|
|
39
|
-
*/
|
|
40
|
-
async init() {
|
|
41
|
-
try {
|
|
42
|
-
// Ensure cache directory exists
|
|
43
|
-
await fs.mkdir(this.options.contextCachePath, { recursive: true });
|
|
44
|
-
|
|
45
|
-
// Capture initial context
|
|
46
|
-
this.baseContext = await this.captureCurrentContext();
|
|
47
|
-
|
|
48
|
-
this.emit('initialized', {
|
|
49
|
-
baseContextSize: this.baseContext?.size || 0
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
return true;
|
|
53
|
-
} catch (error) {
|
|
54
|
-
this.emit('error', { error, phase: 'initialization' });
|
|
55
|
-
throw error;
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
* Apply persona-specific context rules
|
|
61
|
-
*/
|
|
62
|
-
async applyPersonaRules(persona) {
|
|
63
|
-
try {
|
|
64
|
-
// Preserve base context if enabled
|
|
65
|
-
if (this.options.preserveBase && !this.baseContext) {
|
|
66
|
-
this.baseContext = await this.captureCurrentContext();
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
// Build persona-specific overlay
|
|
70
|
-
this.personaOverlay = {
|
|
71
|
-
systemPrompt: this.buildSystemPrompt(persona),
|
|
72
|
-
priorityPatterns: persona.contextRules.priority || [],
|
|
73
|
-
exclusionPatterns: persona.contextRules.exclude || [],
|
|
74
|
-
focusAreas: persona.contextRules.focus || [],
|
|
75
|
-
keywords: persona.contextRules.keywords || [],
|
|
76
|
-
tokenAllocation: persona.tokenAllocation || { context: 0.4, response: 0.6 }
|
|
77
|
-
};
|
|
78
|
-
|
|
79
|
-
// Optimize context if enabled
|
|
80
|
-
let optimizedContext;
|
|
81
|
-
if (this.options.enableOptimization) {
|
|
82
|
-
optimizedContext = await this.tokenOptimizer.optimize(
|
|
83
|
-
this.baseContext,
|
|
84
|
-
this.personaOverlay,
|
|
85
|
-
persona.tokenAllocation
|
|
86
|
-
);
|
|
87
|
-
} else {
|
|
88
|
-
optimizedContext = this.mergeContexts(this.baseContext, this.personaOverlay);
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
// Apply the context
|
|
92
|
-
this.currentContext = optimizedContext;
|
|
93
|
-
await this.injectContext(optimizedContext);
|
|
94
|
-
|
|
95
|
-
// Cache the context
|
|
96
|
-
this.cacheContext(persona.name, optimizedContext);
|
|
97
|
-
|
|
98
|
-
this.emit('contextApplied', {
|
|
99
|
-
persona: persona.name,
|
|
100
|
-
contextSize: optimizedContext.size,
|
|
101
|
-
optimization: this.options.enableOptimization
|
|
102
|
-
});
|
|
103
|
-
|
|
104
|
-
return optimizedContext;
|
|
105
|
-
} catch (error) {
|
|
106
|
-
this.emit('error', { error, phase: 'apply_rules' });
|
|
107
|
-
throw error;
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
/**
|
|
112
|
-
* Build system prompt for persona
|
|
113
|
-
*/
|
|
114
|
-
buildSystemPrompt(persona) {
|
|
115
|
-
const sections = [];
|
|
116
|
-
|
|
117
|
-
// Operating mode
|
|
118
|
-
sections.push(`You are currently operating in ${persona.name} mode.`);
|
|
119
|
-
sections.push('');
|
|
120
|
-
|
|
121
|
-
// Key behaviors
|
|
122
|
-
if (persona.behaviors?.length) {
|
|
123
|
-
sections.push('Key behaviors:');
|
|
124
|
-
persona.behaviors.forEach(behavior => {
|
|
125
|
-
sections.push(`- ${behavior}`);
|
|
126
|
-
});
|
|
127
|
-
sections.push('');
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
// Focus areas
|
|
131
|
-
if (persona.focusAreas?.length) {
|
|
132
|
-
sections.push('Focus areas:');
|
|
133
|
-
persona.focusAreas.forEach(area => {
|
|
134
|
-
sections.push(`- ${area}`);
|
|
135
|
-
});
|
|
136
|
-
sections.push('');
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
// Communication style
|
|
140
|
-
if (persona.communicationStyle) {
|
|
141
|
-
sections.push(`Communication style: ${persona.communicationStyle}`);
|
|
142
|
-
sections.push('');
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
// Recommended tools
|
|
146
|
-
if (persona.recommendedTools?.length) {
|
|
147
|
-
sections.push(`Recommended tools: ${persona.recommendedTools.join(', ')}`);
|
|
148
|
-
sections.push('');
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
// Context rules
|
|
152
|
-
if (persona.contextRules) {
|
|
153
|
-
sections.push('Context priorities:');
|
|
154
|
-
|
|
155
|
-
if (persona.contextRules.priority?.length) {
|
|
156
|
-
sections.push(`- Prioritize: ${persona.contextRules.priority.join(', ')}`);
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
if (persona.contextRules.exclude?.length) {
|
|
160
|
-
sections.push(`- Exclude: ${persona.contextRules.exclude.join(', ')}`);
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
if (persona.contextRules.focus?.length) {
|
|
164
|
-
sections.push(`- Focus on: ${persona.contextRules.focus.join(', ')}`);
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
return sections.join('\n');
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
/**
|
|
172
|
-
* Capture current context from environment
|
|
173
|
-
*/
|
|
174
|
-
async captureCurrentContext() {
|
|
175
|
-
const context = {
|
|
176
|
-
timestamp: new Date(),
|
|
177
|
-
environment: await this.captureEnvironment(),
|
|
178
|
-
projectFiles: await this.captureProjectFiles(),
|
|
179
|
-
recentChanges: await this.captureRecentChanges(),
|
|
180
|
-
size: 0 // Will be calculated
|
|
181
|
-
};
|
|
182
|
-
|
|
183
|
-
// Calculate size
|
|
184
|
-
context.size = this.calculateContextSize(context);
|
|
185
|
-
|
|
186
|
-
return context;
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
/**
|
|
190
|
-
* Capture environment information
|
|
191
|
-
*/
|
|
192
|
-
async captureEnvironment() {
|
|
193
|
-
return {
|
|
194
|
-
workingDirectory: process.cwd(),
|
|
195
|
-
nodeVersion: process.version,
|
|
196
|
-
platform: process.platform,
|
|
197
|
-
timestamp: new Date().toISOString()
|
|
198
|
-
};
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
/**
|
|
202
|
-
* Capture relevant project files
|
|
203
|
-
*/
|
|
204
|
-
async captureProjectFiles() {
|
|
205
|
-
const projectFiles = {
|
|
206
|
-
structure: [],
|
|
207
|
-
recentFiles: [],
|
|
208
|
-
importantFiles: []
|
|
209
|
-
};
|
|
210
|
-
|
|
211
|
-
try {
|
|
212
|
-
// Get project structure
|
|
213
|
-
projectFiles.structure = await this.getProjectStructure();
|
|
214
|
-
|
|
215
|
-
// Get recently modified files
|
|
216
|
-
projectFiles.recentFiles = await this.getRecentFiles();
|
|
217
|
-
|
|
218
|
-
// Get important files (package.json, README, etc.)
|
|
219
|
-
projectFiles.importantFiles = await this.getImportantFiles();
|
|
220
|
-
} catch (error) {
|
|
221
|
-
// Non-critical, continue without files
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
return projectFiles;
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
/**
|
|
228
|
-
* Capture recent changes (git history, etc.)
|
|
229
|
-
*/
|
|
230
|
-
async captureRecentChanges() {
|
|
231
|
-
const changes = {
|
|
232
|
-
gitStatus: null,
|
|
233
|
-
recentCommits: [],
|
|
234
|
-
uncommittedChanges: []
|
|
235
|
-
};
|
|
236
|
-
|
|
237
|
-
try {
|
|
238
|
-
// This would integrate with git
|
|
239
|
-
// For now, return empty structure
|
|
240
|
-
} catch (error) {
|
|
241
|
-
// Non-critical, continue without git info
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
return changes;
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
/**
|
|
248
|
-
* Get project structure
|
|
249
|
-
*/
|
|
250
|
-
async getProjectStructure(dir = process.cwd(), level = 0, maxLevel = 3) {
|
|
251
|
-
if (level > maxLevel) return [];
|
|
252
|
-
|
|
253
|
-
const structure = [];
|
|
254
|
-
|
|
255
|
-
try {
|
|
256
|
-
const entries = await fs.readdir(dir, { withFileTypes: true });
|
|
257
|
-
|
|
258
|
-
for (const entry of entries) {
|
|
259
|
-
// Skip node_modules and hidden directories
|
|
260
|
-
if (entry.name.startsWith('.') || entry.name === 'node_modules') {
|
|
261
|
-
continue;
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
const fullPath = path.join(dir, entry.name);
|
|
265
|
-
const relativePath = path.relative(process.cwd(), fullPath);
|
|
266
|
-
|
|
267
|
-
if (entry.isDirectory()) {
|
|
268
|
-
structure.push({
|
|
269
|
-
type: 'directory',
|
|
270
|
-
path: relativePath,
|
|
271
|
-
children: await this.getProjectStructure(fullPath, level + 1, maxLevel)
|
|
272
|
-
});
|
|
273
|
-
} else {
|
|
274
|
-
structure.push({
|
|
275
|
-
type: 'file',
|
|
276
|
-
path: relativePath,
|
|
277
|
-
extension: path.extname(entry.name)
|
|
278
|
-
});
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
|
-
} catch (error) {
|
|
282
|
-
// Ignore errors
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
return structure;
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
/**
|
|
289
|
-
* Get recently modified files
|
|
290
|
-
*/
|
|
291
|
-
async getRecentFiles(limit = 10) {
|
|
292
|
-
// This would use file system stats to find recent files
|
|
293
|
-
// For now, return empty array
|
|
294
|
-
return [];
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
/**
|
|
298
|
-
* Get important project files
|
|
299
|
-
*/
|
|
300
|
-
async getImportantFiles() {
|
|
301
|
-
const importantFiles = [];
|
|
302
|
-
const filesToCheck = [
|
|
303
|
-
'package.json',
|
|
304
|
-
'README.md',
|
|
305
|
-
'tsconfig.json',
|
|
306
|
-
'.aiwf/00_PROJECT_MANIFEST.md',
|
|
307
|
-
'CLAUDE.md'
|
|
308
|
-
];
|
|
309
|
-
|
|
310
|
-
for (const file of filesToCheck) {
|
|
311
|
-
try {
|
|
312
|
-
const filePath = path.join(process.cwd(), file);
|
|
313
|
-
const stats = await fs.stat(filePath);
|
|
314
|
-
if (stats.isFile()) {
|
|
315
|
-
importantFiles.push({
|
|
316
|
-
path: file,
|
|
317
|
-
size: stats.size,
|
|
318
|
-
modified: stats.mtime
|
|
319
|
-
});
|
|
320
|
-
}
|
|
321
|
-
} catch (error) {
|
|
322
|
-
// File doesn't exist, skip
|
|
323
|
-
}
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
return importantFiles;
|
|
327
|
-
}
|
|
328
|
-
|
|
329
|
-
/**
|
|
330
|
-
* Calculate context size (approximate token count)
|
|
331
|
-
*/
|
|
332
|
-
calculateContextSize(context) {
|
|
333
|
-
// Rough approximation: 1 token ≈ 4 characters
|
|
334
|
-
const jsonString = JSON.stringify(context);
|
|
335
|
-
return Math.ceil(jsonString.length / 4);
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
/**
|
|
339
|
-
* Merge base context with persona overlay
|
|
340
|
-
*/
|
|
341
|
-
mergeContexts(base, overlay) {
|
|
342
|
-
return {
|
|
343
|
-
...base,
|
|
344
|
-
personaOverlay: overlay,
|
|
345
|
-
size: this.calculateContextSize({ ...base, personaOverlay: overlay })
|
|
346
|
-
};
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
/**
|
|
350
|
-
* Inject context into Claude Code
|
|
351
|
-
*/
|
|
352
|
-
async injectContext(context) {
|
|
353
|
-
// This would integrate with Claude Code's context system
|
|
354
|
-
// For now, we'll prepare the context for injection
|
|
355
|
-
|
|
356
|
-
const injection = {
|
|
357
|
-
systemPrompt: context.personaOverlay?.systemPrompt || '',
|
|
358
|
-
contextRules: context.personaOverlay || {},
|
|
359
|
-
metadata: {
|
|
360
|
-
persona: context.persona,
|
|
361
|
-
timestamp: new Date(),
|
|
362
|
-
size: context.size
|
|
363
|
-
}
|
|
364
|
-
};
|
|
365
|
-
|
|
366
|
-
// In a real implementation, this would communicate with Claude Code
|
|
367
|
-
// For now, we'll emit an event
|
|
368
|
-
this.emit('contextInjected', injection);
|
|
369
|
-
|
|
370
|
-
return true;
|
|
371
|
-
}
|
|
372
|
-
|
|
373
|
-
/**
|
|
374
|
-
* Filter content based on persona rules
|
|
375
|
-
*/
|
|
376
|
-
async filterContent(content, persona) {
|
|
377
|
-
if (!persona.contextRules) {
|
|
378
|
-
return content;
|
|
379
|
-
}
|
|
380
|
-
|
|
381
|
-
let filtered = content;
|
|
382
|
-
|
|
383
|
-
// Apply exclusion patterns
|
|
384
|
-
if (persona.contextRules.exclude?.length) {
|
|
385
|
-
filtered = await this.applyExclusions(filtered, persona.contextRules.exclude);
|
|
386
|
-
}
|
|
387
|
-
|
|
388
|
-
// Apply priority patterns
|
|
389
|
-
if (persona.contextRules.priority?.length) {
|
|
390
|
-
filtered = await this.applyPriorities(filtered, persona.contextRules.priority);
|
|
391
|
-
}
|
|
392
|
-
|
|
393
|
-
// Focus on specific areas
|
|
394
|
-
if (persona.contextRules.focus?.length) {
|
|
395
|
-
filtered = await this.applyFocus(filtered, persona.contextRules.focus);
|
|
396
|
-
}
|
|
397
|
-
|
|
398
|
-
return filtered;
|
|
399
|
-
}
|
|
400
|
-
|
|
401
|
-
/**
|
|
402
|
-
* Apply exclusion patterns to content
|
|
403
|
-
*/
|
|
404
|
-
async applyExclusions(content, patterns) {
|
|
405
|
-
if (typeof content === 'string') {
|
|
406
|
-
// For string content, remove lines matching patterns
|
|
407
|
-
const lines = content.split('\n');
|
|
408
|
-
const filtered = lines.filter(line => {
|
|
409
|
-
return !patterns.some(pattern => this.matchesPattern(line, pattern));
|
|
410
|
-
});
|
|
411
|
-
return filtered.join('\n');
|
|
412
|
-
} else if (Array.isArray(content)) {
|
|
413
|
-
// For array content, filter items
|
|
414
|
-
return content.filter(item => {
|
|
415
|
-
const itemStr = typeof item === 'string' ? item : item.path || '';
|
|
416
|
-
return !patterns.some(pattern => this.matchesPattern(itemStr, pattern));
|
|
417
|
-
});
|
|
418
|
-
} else if (typeof content === 'object') {
|
|
419
|
-
// For object content, recursively filter
|
|
420
|
-
const filtered = {};
|
|
421
|
-
for (const [key, value] of Object.entries(content)) {
|
|
422
|
-
if (!patterns.some(pattern => this.matchesPattern(key, pattern))) {
|
|
423
|
-
filtered[key] = await this.applyExclusions(value, patterns);
|
|
424
|
-
}
|
|
425
|
-
}
|
|
426
|
-
return filtered;
|
|
427
|
-
}
|
|
428
|
-
|
|
429
|
-
return content;
|
|
430
|
-
}
|
|
431
|
-
|
|
432
|
-
/**
|
|
433
|
-
* Apply priority patterns to content
|
|
434
|
-
*/
|
|
435
|
-
async applyPriorities(content, patterns) {
|
|
436
|
-
if (Array.isArray(content)) {
|
|
437
|
-
// Sort array content by priority
|
|
438
|
-
return content.sort((a, b) => {
|
|
439
|
-
const aStr = typeof a === 'string' ? a : a.path || '';
|
|
440
|
-
const bStr = typeof b === 'string' ? b : b.path || '';
|
|
441
|
-
|
|
442
|
-
const aPriority = this.calculatePriority(aStr, patterns);
|
|
443
|
-
const bPriority = this.calculatePriority(bStr, patterns);
|
|
444
|
-
|
|
445
|
-
return bPriority - aPriority;
|
|
446
|
-
});
|
|
447
|
-
}
|
|
448
|
-
|
|
449
|
-
// For other content types, return as-is
|
|
450
|
-
return content;
|
|
451
|
-
}
|
|
452
|
-
|
|
453
|
-
/**
|
|
454
|
-
* Apply focus areas to content
|
|
455
|
-
*/
|
|
456
|
-
async applyFocus(content, focusAreas) {
|
|
457
|
-
// This would implement intelligent focusing based on the focus areas
|
|
458
|
-
// For now, return content as-is
|
|
459
|
-
return content;
|
|
460
|
-
}
|
|
461
|
-
|
|
462
|
-
/**
|
|
463
|
-
* Calculate priority score for an item
|
|
464
|
-
*/
|
|
465
|
-
calculatePriority(item, patterns) {
|
|
466
|
-
let score = 0;
|
|
467
|
-
|
|
468
|
-
patterns.forEach((pattern, index) => {
|
|
469
|
-
if (this.matchesPattern(item, pattern)) {
|
|
470
|
-
// Higher priority for patterns listed first
|
|
471
|
-
score += (patterns.length - index) * 10;
|
|
472
|
-
}
|
|
473
|
-
});
|
|
474
|
-
|
|
475
|
-
return score;
|
|
476
|
-
}
|
|
477
|
-
|
|
478
|
-
/**
|
|
479
|
-
* Check if item matches pattern
|
|
480
|
-
*/
|
|
481
|
-
matchesPattern(item, pattern) {
|
|
482
|
-
// Convert glob pattern to regex
|
|
483
|
-
const regex = pattern
|
|
484
|
-
.replace(/\*\*/g, '.*')
|
|
485
|
-
.replace(/\*/g, '[^/]*')
|
|
486
|
-
.replace(/\?/g, '.')
|
|
487
|
-
.replace(/\./g, '\\.');
|
|
488
|
-
|
|
489
|
-
return new RegExp(regex).test(item);
|
|
490
|
-
}
|
|
491
|
-
|
|
492
|
-
/**
|
|
493
|
-
* Cache context for reuse
|
|
494
|
-
*/
|
|
495
|
-
cacheContext(personaName, context) {
|
|
496
|
-
const cacheKey = `${personaName}_${Date.now()}`;
|
|
497
|
-
this.contextCache.set(cacheKey, {
|
|
498
|
-
context,
|
|
499
|
-
timestamp: Date.now()
|
|
500
|
-
});
|
|
501
|
-
|
|
502
|
-
// Limit cache size
|
|
503
|
-
if (this.contextCache.size > 10) {
|
|
504
|
-
const oldestKey = Array.from(this.contextCache.keys())[0];
|
|
505
|
-
this.contextCache.delete(oldestKey);
|
|
506
|
-
}
|
|
507
|
-
}
|
|
508
|
-
|
|
509
|
-
/**
|
|
510
|
-
* Get cached context
|
|
511
|
-
*/
|
|
512
|
-
getCachedContext(personaName) {
|
|
513
|
-
for (const [key, value] of this.contextCache.entries()) {
|
|
514
|
-
if (key.startsWith(personaName)) {
|
|
515
|
-
// Check if cache is still valid (5 minutes)
|
|
516
|
-
if (Date.now() - value.timestamp < 300000) {
|
|
517
|
-
return value.context;
|
|
518
|
-
}
|
|
519
|
-
}
|
|
520
|
-
}
|
|
521
|
-
return null;
|
|
522
|
-
}
|
|
523
|
-
|
|
524
|
-
/**
|
|
525
|
-
* Get current context
|
|
526
|
-
*/
|
|
527
|
-
getCurrentContext() {
|
|
528
|
-
return this.currentContext;
|
|
529
|
-
}
|
|
530
|
-
|
|
531
|
-
/**
|
|
532
|
-
* Get context statistics
|
|
533
|
-
*/
|
|
534
|
-
getContextStats() {
|
|
535
|
-
return {
|
|
536
|
-
baseContextSize: this.baseContext?.size || 0,
|
|
537
|
-
currentContextSize: this.currentContext?.size || 0,
|
|
538
|
-
cacheSize: this.contextCache.size,
|
|
539
|
-
hasPersonaOverlay: !!this.personaOverlay
|
|
540
|
-
};
|
|
541
|
-
}
|
|
542
|
-
|
|
543
|
-
/**
|
|
544
|
-
* Reset context engine
|
|
545
|
-
*/
|
|
546
|
-
async reset() {
|
|
547
|
-
this.baseContext = null;
|
|
548
|
-
this.personaOverlay = null;
|
|
549
|
-
this.currentContext = null;
|
|
550
|
-
this.contextCache.clear();
|
|
551
|
-
|
|
552
|
-
// Recapture base context
|
|
553
|
-
this.baseContext = await this.captureCurrentContext();
|
|
554
|
-
|
|
555
|
-
this.emit('reset');
|
|
556
|
-
}
|
|
557
|
-
|
|
558
|
-
/**
|
|
559
|
-
* Cleanup resources
|
|
560
|
-
*/
|
|
561
|
-
async cleanup() {
|
|
562
|
-
this.contextCache.clear();
|
|
563
|
-
this.removeAllListeners();
|
|
564
|
-
}
|
|
565
|
-
}
|
|
566
|
-
|
|
567
|
-
export default ContextEngine;
|
|
568
|
-
export { ContextEngine };
|