aiwf 0.3.21 → 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.
Files changed (140) hide show
  1. package/package.json +3 -2
  2. package/src/cli/index.js +39 -336
  3. package/src/lib/installer.js +310 -90
  4. package/src/utils/messages.js +24 -0
  5. package/src/DEPENDENCY_MAP.md +0 -90
  6. package/src/cli/cache-cli.js +0 -459
  7. package/src/cli/checkpoint-cli.js +0 -417
  8. package/src/cli/language-cli.js +0 -286
  9. package/src/cli/sprint-cli.js +0 -287
  10. package/src/commands/ai-tool.js +0 -383
  11. package/src/commands/compress.js +0 -60
  12. package/src/commands/create-project.js +0 -160
  13. package/src/commands/evaluate.js +0 -459
  14. package/src/commands/persona.js +0 -309
  15. package/src/commands/sprint-task.js +0 -262
  16. package/src/commands/token.js +0 -312
  17. package/src/lib/ai-persona-manager.js +0 -711
  18. package/src/lib/cache-system.js +0 -332
  19. package/src/lib/context-engine.js +0 -568
  20. package/src/lib/github-integration.js +0 -402
  21. package/src/lib/memory-profiler.js +0 -471
  22. package/src/lib/metrics-collector.js +0 -885
  23. package/src/lib/offline-detector.js +0 -386
  24. package/src/lib/resource-loader-enhanced.js +0 -399
  25. package/src/lib/resource-loader.js +0 -250
  26. package/src/lib/resources/commands/ai-persona.js +0 -602
  27. package/src/lib/resources/commands/compress-context.js +0 -389
  28. package/src/lib/resources/commands/evaluate.js +0 -246
  29. package/src/lib/resources/commands/persona-context-apply.js +0 -562
  30. package/src/lib/resources/commands/token-tracking.js +0 -443
  31. package/src/lib/resources/config/commit-patterns.js +0 -103
  32. package/src/lib/resources/config/language.json +0 -6
  33. package/src/lib/resources/personas/PERSONA_INDEX.md +0 -57
  34. package/src/lib/resources/personas/analyst.json +0 -44
  35. package/src/lib/resources/personas/architect/best_practices.md +0 -136
  36. package/src/lib/resources/personas/architect/knowledge_base.md +0 -377
  37. package/src/lib/resources/personas/architect.json +0 -44
  38. package/src/lib/resources/personas/backend/best_practices.md +0 -766
  39. package/src/lib/resources/personas/backend/knowledge_base.md +0 -1070
  40. package/src/lib/resources/personas/data_analyst/best_practices.md +0 -594
  41. package/src/lib/resources/personas/data_analyst/knowledge_base.md +0 -1057
  42. package/src/lib/resources/personas/developer.json +0 -44
  43. package/src/lib/resources/personas/developer.md +0 -37
  44. package/src/lib/resources/personas/evaluation_criteria.json +0 -137
  45. package/src/lib/resources/personas/frontend/best_practices.md +0 -445
  46. package/src/lib/resources/personas/frontend/knowledge_base.md +0 -729
  47. package/src/lib/resources/personas/persona-index.json +0 -31
  48. package/src/lib/resources/personas/reviewer.json +0 -44
  49. package/src/lib/resources/personas/security/best_practices.md +0 -307
  50. package/src/lib/resources/personas/security/knowledge_base.md +0 -498
  51. package/src/lib/resources/personas/tester.json +0 -44
  52. package/src/lib/resources/templates/README.md +0 -78
  53. package/src/lib/resources/templates/api-server/config.json +0 -64
  54. package/src/lib/resources/templates/api-server/template/.aiwf/config.json +0 -56
  55. package/src/lib/resources/templates/api-server/template/.aiwf/feature-ledger.json +0 -42
  56. package/src/lib/resources/templates/api-server/template/.aiwf/personas/backend-engineer.json +0 -40
  57. package/src/lib/resources/templates/api-server/template/.aiwf/scripts/cli.js +0 -111
  58. package/src/lib/resources/templates/api-server/template/.env.example +0 -29
  59. package/src/lib/resources/templates/api-server/template/.eslintrc.json +0 -23
  60. package/src/lib/resources/templates/api-server/template/README.md +0 -171
  61. package/src/lib/resources/templates/api-server/template/jest.config.js +0 -26
  62. package/src/lib/resources/templates/api-server/template/nodemon.json +0 -9
  63. package/src/lib/resources/templates/api-server/template/package.json +0 -61
  64. package/src/lib/resources/templates/api-server/template/src/app.ts +0 -60
  65. package/src/lib/resources/templates/api-server/template/src/config/swagger.ts +0 -38
  66. package/src/lib/resources/templates/api-server/template/src/controllers/aiwfController.ts +0 -54
  67. package/src/lib/resources/templates/api-server/template/src/controllers/authController.ts +0 -128
  68. package/src/lib/resources/templates/api-server/template/src/controllers/statusController.ts +0 -28
  69. package/src/lib/resources/templates/api-server/template/src/index.ts +0 -28
  70. package/src/lib/resources/templates/api-server/template/src/middleware/aiwfMiddleware.ts +0 -50
  71. package/src/lib/resources/templates/api-server/template/src/middleware/authMiddleware.ts +0 -41
  72. package/src/lib/resources/templates/api-server/template/src/middleware/errorHandler.ts +0 -42
  73. package/src/lib/resources/templates/api-server/template/src/middleware/notFoundHandler.ts +0 -14
  74. package/src/lib/resources/templates/api-server/template/src/middleware/requestLogger.ts +0 -20
  75. package/src/lib/resources/templates/api-server/template/src/routes/aiwf.ts +0 -31
  76. package/src/lib/resources/templates/api-server/template/src/routes/index.ts +0 -13
  77. package/src/lib/resources/templates/api-server/template/src/routes/v1/index.ts +0 -67
  78. package/src/lib/resources/templates/api-server/template/src/utils/logger.ts +0 -37
  79. package/src/lib/resources/templates/api-server/template/tests/app.test.ts +0 -40
  80. package/src/lib/resources/templates/api-server/template/tsconfig.json +0 -43
  81. package/src/lib/resources/templates/npm-library/config.json +0 -61
  82. package/src/lib/resources/templates/npm-library/template/LICENSE +0 -21
  83. package/src/lib/resources/templates/npm-library/template/README.md +0 -201
  84. package/src/lib/resources/templates/npm-library/template/package.json +0 -78
  85. package/src/lib/resources/templates/web-app/config.json +0 -53
  86. package/src/lib/resources/templates/web-app/template/.aiwf/config.json +0 -54
  87. package/src/lib/resources/templates/web-app/template/.aiwf/feature-ledger.json +0 -37
  88. package/src/lib/resources/templates/web-app/template/.aiwf/personas/fullstack-developer.json +0 -40
  89. package/src/lib/resources/templates/web-app/template/.aiwf/scripts/cli.js +0 -110
  90. package/src/lib/resources/templates/web-app/template/.eslintrc.cjs +0 -20
  91. package/src/lib/resources/templates/web-app/template/README.md +0 -151
  92. package/src/lib/resources/templates/web-app/template/index.html +0 -14
  93. package/src/lib/resources/templates/web-app/template/package.json +0 -44
  94. package/src/lib/resources/templates/web-app/template/postcss.config.js +0 -6
  95. package/src/lib/resources/templates/web-app/template/public/vite.svg +0 -1
  96. package/src/lib/resources/templates/web-app/template/src/App.tsx +0 -21
  97. package/src/lib/resources/templates/web-app/template/src/components/Layout.tsx +0 -57
  98. package/src/lib/resources/templates/web-app/template/src/components/aiwf/ContextStatus.tsx +0 -107
  99. package/src/lib/resources/templates/web-app/template/src/components/aiwf/TokenUsage.tsx +0 -71
  100. package/src/lib/resources/templates/web-app/template/src/index.css +0 -60
  101. package/src/lib/resources/templates/web-app/template/src/main.tsx +0 -10
  102. package/src/lib/resources/templates/web-app/template/src/pages/AiwfDashboard.tsx +0 -57
  103. package/src/lib/resources/templates/web-app/template/src/pages/HomePage.tsx +0 -89
  104. package/src/lib/resources/templates/web-app/template/src/pages/NotFound.tsx +0 -25
  105. package/src/lib/resources/templates/web-app/template/src/stores/aiwfStore.ts +0 -126
  106. package/src/lib/resources/templates/web-app/template/src/types/global.d.ts +0 -9
  107. package/src/lib/resources/templates/web-app/template/src/vite-env.d.ts +0 -1
  108. package/src/lib/resources/templates/web-app/template/tailwind.config.js +0 -30
  109. package/src/lib/resources/templates/web-app/template/tsconfig.json +0 -37
  110. package/src/lib/resources/templates/web-app/template/tsconfig.node.json +0 -10
  111. package/src/lib/resources/templates/web-app/template/vite.config.ts +0 -23
  112. package/src/lib/resources/utils/background-monitor.js +0 -223
  113. package/src/lib/resources/utils/compression-metrics.js +0 -1031
  114. package/src/lib/resources/utils/compression-strategies.js +0 -557
  115. package/src/lib/resources/utils/content-normalizer.js +0 -455
  116. package/src/lib/resources/utils/context-compressor.js +0 -583
  117. package/src/lib/resources/utils/context-rule-parser.js +0 -180
  118. package/src/lib/resources/utils/context-token-monitor.js +0 -463
  119. package/src/lib/resources/utils/context-update-manager.js +0 -502
  120. package/src/lib/resources/utils/git-utils.js +0 -220
  121. package/src/lib/resources/utils/importance-classifier.js +0 -645
  122. package/src/lib/resources/utils/information-filter.js +0 -710
  123. package/src/lib/resources/utils/persona-aware-compressor.js +0 -598
  124. package/src/lib/resources/utils/prompt-injector.js +0 -242
  125. package/src/lib/resources/utils/simplified-evaluator.js +0 -119
  126. package/src/lib/resources/utils/text-summarizer.js +0 -492
  127. package/src/lib/resources/utils/token-counter.js +0 -177
  128. package/src/lib/resources/utils/token-monitor.js +0 -484
  129. package/src/lib/resources/utils/token-reporter.js +0 -452
  130. package/src/lib/resources/utils/token-storage.js +0 -433
  131. package/src/lib/resources/utils/token-tracker.js +0 -283
  132. package/src/lib/state/priority-calculator.js +0 -217
  133. package/src/lib/state/state-index.js +0 -155
  134. package/src/lib/state/task-scanner.js +0 -328
  135. package/src/lib/task-analyzer.js +0 -599
  136. package/src/lib/template-cache-system.js +0 -559
  137. package/src/lib/template-downloader.js +0 -467
  138. package/src/lib/template-version-manager.js +0 -491
  139. package/src/lib/token-optimizer.js +0 -517
  140. 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 };