codehere 0.2.2 → 0.3.0-rc.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.
Files changed (235) hide show
  1. package/README.md +88 -68
  2. package/dist/domain/entities/task.js +4 -4
  3. package/dist/error-handler.js +4 -9
  4. package/dist/index.js +253 -1219
  5. package/dist/infrastructure/config/product-context.js +7 -6
  6. package/dist/infrastructure/hooks/claude-sdk-hook.js +335 -63
  7. package/dist/infrastructure/observability/execution-tracer.js +11 -6
  8. package/dist/infrastructure/orchestration/agent-adapter.js +13 -0
  9. package/dist/infrastructure/orchestration/agent-installer.js +101 -0
  10. package/dist/infrastructure/orchestration/agents-config-seed.js +56 -0
  11. package/dist/infrastructure/orchestration/aider-adapter.js +319 -0
  12. package/dist/infrastructure/orchestration/artifacts-extractor.js +175 -0
  13. package/dist/infrastructure/orchestration/claude-code-adapter.js +352 -0
  14. package/dist/infrastructure/orchestration/codex-adapter.js +310 -0
  15. package/dist/infrastructure/orchestration/generic-cli-adapter.js +553 -0
  16. package/dist/infrastructure/orchestration/opencode-adapter.js +275 -0
  17. package/dist/infrastructure/orchestration/progress-aggregator.js +189 -0
  18. package/dist/infrastructure/orchestration/readiness.js +106 -0
  19. package/dist/infrastructure/orchestration/session-manager.js +272 -0
  20. package/dist/infrastructure/orchestration/session-persistence.js +109 -0
  21. package/dist/infrastructure/protocols/mcp-helpers.js +10 -30
  22. package/dist/infrastructure/protocols/mcp-server-impl.js +359 -21
  23. package/dist/infrastructure/protocols/ui-page.js +1827 -0
  24. package/dist/infrastructure/security/file-collection.js +115 -0
  25. package/dist/infrastructure/security/trust-scorer.js +301 -56
  26. package/dist/infrastructure/storage/task-repository.js +8 -7
  27. package/dist/monitoring.js +9 -38
  28. package/dist/presentation/cli/commands/help-command.js +96 -139
  29. package/dist/presentation/cli/commands/hook-command.js +17 -24
  30. package/dist/presentation/cli/commands/report-command.js +59 -72
  31. package/dist/presentation/cli/commands/setup-command.js +4 -4
  32. package/dist/presentation/cli/commands/status-command.js +321 -30
  33. package/dist/presentation/cli/commands/trust-command.js +84 -72
  34. package/dist/presentation/cli/error-display.js +17 -21
  35. package/dist/ui.js +11 -11
  36. package/package.json +24 -62
  37. package/dist/agents/base.js +0 -101
  38. package/dist/agents/orchestrator-model-driven.js +0 -141
  39. package/dist/agents/react-orchestrator-agent.js +0 -54
  40. package/dist/application/agents/execution-agent.js +0 -508
  41. package/dist/application/agents/multi-agent-orchestrator.js +0 -295
  42. package/dist/application/agents/planning-agent.js +0 -433
  43. package/dist/application/agents/validation-agent.js +0 -317
  44. package/dist/application/architectures/plan-and-act.js +0 -242
  45. package/dist/application/index.js +0 -12
  46. package/dist/application/services/agent-factory.js +0 -28
  47. package/dist/application/services/dependency-container.js +0 -596
  48. package/dist/application/services/git-context-service.js +0 -83
  49. package/dist/application/services/intelligent-router.js +0 -934
  50. package/dist/application/services/tool-executor-service.js +0 -94
  51. package/dist/application/use-cases/ask-question-use-case.js +0 -338
  52. package/dist/application/use-cases/edit-file-use-case.js +0 -830
  53. package/dist/application/use-cases/explain-file-use-case.js +0 -50
  54. package/dist/application/use-cases/index-codebase-use-case.js +0 -113
  55. package/dist/application/use-cases/planning-use-case.js +0 -276
  56. package/dist/application/use-cases/react-orchestration-use-case.js +0 -329
  57. package/dist/application/use-cases/reflexion-use-case.js +0 -30
  58. package/dist/application/workflows/deterministic-workflows.js +0 -189
  59. package/dist/ast-parser.js +0 -331
  60. package/dist/cache.js +0 -180
  61. package/dist/chat.js +0 -251
  62. package/dist/code-analysis.js +0 -327
  63. package/dist/context.js +0 -187
  64. package/dist/docs.js +0 -146
  65. package/dist/domain/entities/code-chunk.js +0 -6
  66. package/dist/domain/entities/decision.js +0 -9
  67. package/dist/domain/entities/edit.js +0 -6
  68. package/dist/domain/entities/knowledge-node.js +0 -9
  69. package/dist/domain/entities/knowledge-preservation.js +0 -10
  70. package/dist/domain/entities/memory.js +0 -6
  71. package/dist/domain/entities/pattern.js +0 -7
  72. package/dist/domain/entities/plan.js +0 -6
  73. package/dist/domain/entities/query.js +0 -6
  74. package/dist/domain/errors/embeddings-not-found-error.js +0 -13
  75. package/dist/domain/index.js +0 -19
  76. package/dist/domain/interfaces/ai-service.interface.js +0 -6
  77. package/dist/domain/interfaces/code-analyzer.interface.js +0 -6
  78. package/dist/domain/interfaces/decision-repository.interface.js +0 -9
  79. package/dist/domain/interfaces/embedding-repository.interface.js +0 -6
  80. package/dist/domain/interfaces/knowledge-graph-repository.interface.js +0 -9
  81. package/dist/domain/interfaces/knowledge-preservation-repository.interface.js +0 -8
  82. package/dist/domain/interfaces/memory-repository.interface.js +0 -6
  83. package/dist/domain/interfaces/pattern-repository.interface.js +0 -6
  84. package/dist/domain/interfaces/verification-service.interface.js +0 -6
  85. package/dist/domain/services/cross-team-pattern-sharing.js +0 -125
  86. package/dist/domain/services/decision-recorder.js +0 -223
  87. package/dist/domain/services/decision-retriever.js +0 -133
  88. package/dist/domain/services/environment-mode-manager.js +0 -22
  89. package/dist/domain/services/graded-memory-activation.js +0 -69
  90. package/dist/domain/services/knowledge-access.js +0 -132
  91. package/dist/domain/services/knowledge-extractor.js +0 -247
  92. package/dist/domain/services/knowledge-graph-builder.js +0 -268
  93. package/dist/domain/services/knowledge-graph-query.js +0 -187
  94. package/dist/domain/services/memory-retriever.js +0 -82
  95. package/dist/domain/services/memory-synthesizer.js +0 -91
  96. package/dist/domain/services/pattern-extractor.js +0 -442
  97. package/dist/domain/services/query-intent-classifier.js +0 -140
  98. package/dist/domain/services/react-loop.js +0 -186
  99. package/dist/domain/services/risk-tier-detector.js +0 -78
  100. package/dist/edit.js +0 -319
  101. package/dist/embed.js +0 -459
  102. package/dist/formatter.js +0 -168
  103. package/dist/git.js +0 -198
  104. package/dist/infrastructure/ai/cohere-ai-service.js +0 -607
  105. package/dist/infrastructure/ai/command-r-evaluation.js +0 -206
  106. package/dist/infrastructure/ai/model-config.js +0 -84
  107. package/dist/infrastructure/ai/provider-ai-service.js +0 -477
  108. package/dist/infrastructure/cache/embedding-cache.js +0 -175
  109. package/dist/infrastructure/cache/query-result-cache.js +0 -66
  110. package/dist/infrastructure/cache/response-cache.js +0 -48
  111. package/dist/infrastructure/cache/security-scan-cache.js +0 -47
  112. package/dist/infrastructure/chunking/ast-code-chunker.js +0 -19
  113. package/dist/infrastructure/chunking/code-aware-chunker.js +0 -397
  114. package/dist/infrastructure/context/context-compressor.js +0 -329
  115. package/dist/infrastructure/context/conversation-context.js +0 -128
  116. package/dist/infrastructure/context/session-manager.js +0 -94
  117. package/dist/infrastructure/cost/cost-tracker.js +0 -360
  118. package/dist/infrastructure/file-scanner/file-scanner.js +0 -106
  119. package/dist/infrastructure/governance/nist-ai-rmf.js +0 -292
  120. package/dist/infrastructure/governance/policy-as-code.js +0 -258
  121. package/dist/infrastructure/governance/prompt-to-code-lineage.js +0 -239
  122. package/dist/infrastructure/index.js +0 -7
  123. package/dist/infrastructure/observability/prompt-versioner.js +0 -145
  124. package/dist/infrastructure/protocols/a2a-metadata.js +0 -137
  125. package/dist/infrastructure/protocols/a2a-protocol.js +0 -314
  126. package/dist/infrastructure/protocols/mcp-oauth.js +0 -184
  127. package/dist/infrastructure/protocols/mcp-server.js +0 -333
  128. package/dist/infrastructure/protocols/streaming-handler.js +0 -103
  129. package/dist/infrastructure/providers/cohere-provider.js +0 -444
  130. package/dist/infrastructure/providers/fake-provider.js +0 -130
  131. package/dist/infrastructure/providers/local-llm-provider.js +0 -330
  132. package/dist/infrastructure/providers/model-config.types.js +0 -9
  133. package/dist/infrastructure/providers/model-provider.interface.js +0 -8
  134. package/dist/infrastructure/providers/openai-provider.js +0 -413
  135. package/dist/infrastructure/providers/openrouter-provider.js +0 -399
  136. package/dist/infrastructure/providers/operation-provider-resolver.js +0 -105
  137. package/dist/infrastructure/providers/provider-config-loader.js +0 -120
  138. package/dist/infrastructure/providers/provider-registry.js +0 -88
  139. package/dist/infrastructure/safety/pattern-detector.js +0 -133
  140. package/dist/infrastructure/security/ai-sast-scanner.js +0 -290
  141. package/dist/infrastructure/security/docker-sandbox.js +0 -178
  142. package/dist/infrastructure/security/enhanced-security-gate.js +0 -151
  143. package/dist/infrastructure/security/license-scanner.js +0 -167
  144. package/dist/infrastructure/security/provider-bias-detector.js +0 -164
  145. package/dist/infrastructure/security/sandbox-executor.js +0 -64
  146. package/dist/infrastructure/serialization/toon-serializer.js +0 -119
  147. package/dist/infrastructure/storage/memory-stream-service.js +0 -204
  148. package/dist/infrastructure/storage/plan-repository.js +0 -96
  149. package/dist/infrastructure/storage/sqlite-decision-repository.js +0 -232
  150. package/dist/infrastructure/storage/sqlite-embedding-repository.js +0 -311
  151. package/dist/infrastructure/storage/sqlite-knowledge-graph-repository.js +0 -417
  152. package/dist/infrastructure/storage/sqlite-knowledge-preservation-repository.js +0 -230
  153. package/dist/infrastructure/storage/sqlite-memory-repository.js +0 -229
  154. package/dist/infrastructure/storage/sqlite-pattern-repository.js +0 -249
  155. package/dist/infrastructure/storage/task-helpers.js +0 -197
  156. package/dist/infrastructure/telemetry/telemetry-service.js +0 -167
  157. package/dist/infrastructure/ux/appropriate-friction.js +0 -213
  158. package/dist/infrastructure/ux/bi-directional-learning.js +0 -337
  159. package/dist/infrastructure/ux/capability-boundaries.js +0 -42
  160. package/dist/infrastructure/ux/comprehensive-formatter.js +0 -117
  161. package/dist/infrastructure/ux/contextual-feature-discovery.js +0 -10
  162. package/dist/infrastructure/ux/expectation-management.js +0 -327
  163. package/dist/infrastructure/ux/feature-discovery.js +0 -14
  164. package/dist/infrastructure/ux/feedback-prompt.js +0 -45
  165. package/dist/infrastructure/ux/hitl-validation.js +0 -297
  166. package/dist/infrastructure/ux/progress-indicator.js +0 -116
  167. package/dist/infrastructure/ux/progressive-disclosure.js +0 -236
  168. package/dist/infrastructure/ux/review-checkpoint.js +0 -72
  169. package/dist/infrastructure/ux/staged-feature-intro.js +0 -24
  170. package/dist/infrastructure/ux/stream-markdown.js +0 -151
  171. package/dist/infrastructure/ux/syntax-highlighter.js +0 -91
  172. package/dist/infrastructure/ux/team-standards.js +0 -196
  173. package/dist/infrastructure/ux/transparency.js +0 -71
  174. package/dist/infrastructure/validation/agent-feedback.js +0 -55
  175. package/dist/infrastructure/validation/agent-validation-helper.js +0 -137
  176. package/dist/infrastructure/validation/review-handler.js +0 -40
  177. package/dist/infrastructure/validation/summary-aggregator.js +0 -70
  178. package/dist/infrastructure/validation/summary-extractor.js +0 -45
  179. package/dist/infrastructure/validation/trace-summary.js +0 -52
  180. package/dist/infrastructure/verification/verification-service.js +0 -47
  181. package/dist/infrastructure/xai/attention-visualizer.js +0 -172
  182. package/dist/infrastructure/xai/cot-visualizer.js +0 -283
  183. package/dist/infrastructure/xai/decision-tree-log.js +0 -212
  184. package/dist/infrastructure/xai/interactive-xai.js +0 -260
  185. package/dist/infrastructure/xai/uncertainty-quantifier.js +0 -198
  186. package/dist/intelligent-retrieval.js +0 -272
  187. package/dist/intent/classifier.js +0 -2
  188. package/dist/intent/context.js +0 -2
  189. package/dist/iterative-refinement.js +0 -189
  190. package/dist/learning.js +0 -232
  191. package/dist/log.js +0 -31
  192. package/dist/migrate.js +0 -133
  193. package/dist/parallel-processor.js +0 -534
  194. package/dist/planner.js +0 -198
  195. package/dist/policy.js +0 -26
  196. package/dist/presentation/cli/commands/ask-command.js +0 -314
  197. package/dist/presentation/cli/commands/cost-command.js +0 -191
  198. package/dist/presentation/cli/commands/decision-command.js +0 -207
  199. package/dist/presentation/cli/commands/docs-command.js +0 -25
  200. package/dist/presentation/cli/commands/fix-command.js +0 -53
  201. package/dist/presentation/cli/commands/knowledge-command.js +0 -129
  202. package/dist/presentation/cli/commands/learning-dashboard-command.js +0 -183
  203. package/dist/presentation/cli/commands/models-command.js +0 -194
  204. package/dist/presentation/cli/commands/orchestrate-command.js +0 -207
  205. package/dist/presentation/cli/commands/plan-command.js +0 -246
  206. package/dist/presentation/cli/commands/product-command.js +0 -199
  207. package/dist/presentation/cli/commands/react-command.js +0 -181
  208. package/dist/presentation/cli/commands/review-command.js +0 -154
  209. package/dist/presentation/cli/commands/run-command.js +0 -188
  210. package/dist/presentation/cli/commands/smart-command.js +0 -395
  211. package/dist/presentation/cli/commands/suggest-command.js +0 -138
  212. package/dist/presentation/cli/commands/trace-command.js +0 -129
  213. package/dist/presentation/cli/commands/undo-command.js +0 -150
  214. package/dist/query-optimizer.js +0 -205
  215. package/dist/refactor.js +0 -116
  216. package/dist/review.js +0 -206
  217. package/dist/search.js +0 -163
  218. package/dist/session.js +0 -704
  219. package/dist/task-verification.js +0 -336
  220. package/dist/testgen.js +0 -166
  221. package/dist/token-optimizer.js +0 -277
  222. package/dist/tools/bash.js +0 -213
  223. package/dist/tools/edit.js +0 -235
  224. package/dist/tools/executor.js +0 -153
  225. package/dist/tools/git-tool.js +0 -292
  226. package/dist/tools/parser.js +0 -158
  227. package/dist/tools/registry.js +0 -302
  228. package/dist/tools/search.js +0 -100
  229. package/dist/types.js +0 -2
  230. package/dist/utils/check-api-status.js +0 -100
  231. package/dist/utils/diff-parser.js +0 -162
  232. package/dist/verification/backup.js +0 -259
  233. package/dist/verification/compiler.js +0 -264
  234. package/dist/verification/index.js +0 -273
  235. package/dist/verification/test-runner.js +0 -379
@@ -1,934 +0,0 @@
1
- /**
2
- * Intelligent Query Router
3
- * Understands user intent and routes to appropriate use cases
4
- * Provides seamless experience - user just types what they want
5
- * MEMORY-AWARE: Uses Memory Stream to inform routing decisions
6
- */
7
- const DEBUG = process.env.CODEHERE_DEBUG === '1';
8
- import { QueryIntentClassifier } from '../../domain/services/query-intent-classifier.js';
9
- import { validateQuery } from '../../infrastructure/security/input-validator.js';
10
- import { executionTracer } from '../../infrastructure/observability/execution-tracer.js';
11
- import { agentFeedbackManager } from '../../infrastructure/validation/agent-feedback.js';
12
- import { findCodebaseRoot } from '../../domain/services/codebase-detector.js';
13
- export class IntelligentRouter {
14
- intentClassifier;
15
- aiService;
16
- memoryStream;
17
- constructor(intentClassifier, aiService, memoryStream) {
18
- this.intentClassifier = intentClassifier || new QueryIntentClassifier();
19
- this.aiService = aiService;
20
- this.memoryStream = memoryStream;
21
- }
22
- async route(request) {
23
- // Start routing trace
24
- const codebaseInfo = findCodebaseRoot(process.cwd());
25
- const routingRunId = executionTracer.startRun('intelligent-router', {
26
- query: request.query,
27
- codebaseId: codebaseInfo?.codebaseId || codebaseInfo?.rootPath,
28
- });
29
- // Track routing decision data
30
- let routingDecision;
31
- try {
32
- // Validate input
33
- const validation = validateQuery(request.query);
34
- if (!validation.valid) {
35
- executionTracer.endRun();
36
- return {
37
- intent: 'error',
38
- action: 'general',
39
- result: null,
40
- success: false,
41
- error: `Invalid query: ${validation.errors.join(', ')}`,
42
- routingRunId,
43
- };
44
- }
45
- // Use sanitized query if validation found issues
46
- let query = (validation.sanitized || request.query).trim();
47
- // 2. Classify intent FIRST (needed for conversation tracking)
48
- const classifiedIntent = this.intentClassifier.classify(query);
49
- // Record intent classification
50
- executionTracer.trace({
51
- operationType: 'code_analysis',
52
- operationName: 'intent_classification',
53
- input: { query },
54
- output: { intent: classifiedIntent },
55
- metadata: {
56
- classifier: 'QueryIntentClassifier',
57
- },
58
- });
59
- // Resolve conversation references if we have history
60
- let resolvedQuery = query;
61
- let sessionId;
62
- if (request.context?.conversationHistory && request.context.conversationHistory.length > 0) {
63
- const { conversationContextManager } = await import('../../infrastructure/context/conversation-context.js');
64
- sessionId = request.context.sessionId || 'default-session';
65
- // Resolve references in query (e.g., "it", "that", "the previous")
66
- resolvedQuery = conversationContextManager.resolveReferences(sessionId, query);
67
- // Extract entities for context tracking
68
- const entities = conversationContextManager.extractEntities(resolvedQuery);
69
- // Store original query turn (will be updated with response after routing)
70
- conversationContextManager.addTurn(sessionId, query, '', entities, classifiedIntent);
71
- }
72
- // Use resolved query for processing
73
- query = resolvedQuery;
74
- // 1. MEMORY-AWARE: Retrieve relevant memories to inform routing decision
75
- let memories = [];
76
- let memoryInformedIntent = null;
77
- if (this.memoryStream) {
78
- try {
79
- // Retrieve memories relevant to this query
80
- memories = await this.memoryStream.retrieve(query, 10);
81
- // If we have memories, use them to inform intent classification
82
- if (memories.length > 0 && this.aiService) {
83
- memoryInformedIntent = await this.classifyIntentWithMemory(query, memories);
84
- }
85
- }
86
- catch (error) {
87
- // Fallback to basic classification if memory retrieval fails
88
- console.warn('Memory retrieval failed, using basic classification:', error);
89
- }
90
- }
91
- // CRITICAL: Compound instructions (numbered steps) MUST route to Planning Module
92
- // Check this BEFORE memory-informed intent to prevent override
93
- const isCompoundInstruction = query.includes('\n') && /\d+\.\s+[^\n]+\n\s*\d+\.\s+/.test(query);
94
- // Use memory-informed intent ONLY if not a compound instruction
95
- const intent = isCompoundInstruction && classifiedIntent === 'multi-file-modify'
96
- ? 'multi-file-modify' // Force compound instructions to Planning Module
97
- : (memoryInformedIntent || classifiedIntent);
98
- const symbols = this.intentClassifier.extractSymbols(query);
99
- // Determine which action/agent will be selected based on intent
100
- const actionMap = {
101
- 'explain': 'explain',
102
- 'multi-file-modify': 'orchestrate',
103
- 'modify': 'edit',
104
- 'debug': 'edit',
105
- 'implement': 'edit',
106
- 'index': 'index',
107
- 'plan': 'plan',
108
- 'find': 'ask',
109
- 'understand': 'ask',
110
- 'general': 'ask',
111
- };
112
- const selectedAction = actionMap[intent] || 'ask';
113
- const selectedAgent = selectedAction === 'orchestrate' ? 'multi-agent-orchestrator' :
114
- selectedAction === 'plan' ? 'planning-agent' :
115
- selectedAction === 'react' ? 'react-orchestration' :
116
- selectedAction === 'edit' ? 'edit-file-use-case' :
117
- selectedAction === 'explain' ? 'explain-file-use-case' :
118
- selectedAction === 'index' ? 'index-codebase-use-case' :
119
- 'ask-question-use-case';
120
- // Calculate confidence score (heuristic)
121
- let confidence = 0.8; // Default confidence
122
- if (memoryInformedIntent && memoryInformedIntent === classifiedIntent) {
123
- confidence = 0.95; // High confidence when memory and classifier agree
124
- }
125
- else if (memoryInformedIntent) {
126
- confidence = 0.85; // Good confidence with memory override
127
- }
128
- else if (isCompoundInstruction) {
129
- confidence = 0.9; // High confidence for compound instructions
130
- }
131
- // Build selection reason
132
- const selectionReason = isCompoundInstruction
133
- ? 'Compound instruction detected - routing to orchestration'
134
- : memoryInformedIntent && memoryInformedIntent !== classifiedIntent
135
- ? `Memory-informed routing: ${classifiedIntent} → ${memoryInformedIntent}`
136
- : `Intent classification: ${intent}`;
137
- // Track alternatives considered
138
- const alternatives = Object.keys(actionMap)
139
- .filter(k => actionMap[k] !== selectedAction)
140
- .map(k => actionMap[k])
141
- .filter((v, i, arr) => arr.indexOf(v) === i) // Deduplicate
142
- .slice(0, 3); // Top 3 alternatives
143
- // Record routing decision
144
- routingDecision = {
145
- confidence,
146
- selectedAgent,
147
- selectionReason,
148
- alternatives,
149
- };
150
- // Trace routing decision
151
- executionTracer.trace({
152
- operationType: 'code_analysis',
153
- operationName: 'routing_decision',
154
- input: { query, intent, classifiedIntent, memoryInformedIntent },
155
- output: { selectedAction, selectedAgent, confidence },
156
- metadata: {
157
- intent,
158
- selectedAction,
159
- selectedAgent,
160
- confidence,
161
- memoryInformed: !!memoryInformedIntent,
162
- memoriesUsed: memories.length,
163
- compoundInstruction: isCompoundInstruction,
164
- },
165
- });
166
- // Debug logging for compound instructions
167
- if (isCompoundInstruction) {
168
- if (DEBUG)
169
- console.log(`[IntelligentRouter] Compound instruction detected. Classified: ${classifiedIntent}, Memory: ${memoryInformedIntent}, Using: ${intent}`);
170
- }
171
- // 3. Check if indexing is needed
172
- const needsIndex = await this.checkIfIndexingNeeded(request.context);
173
- // Handle indexing first if needed
174
- if (needsIndex && (intent === 'find' || intent === 'understand' || intent === 'explain')) {
175
- executionTracer.endRun();
176
- // Record routing decision feedback
177
- try {
178
- agentFeedbackManager.recordFeedback({
179
- runId: routingRunId,
180
- agentName: 'intelligent-router',
181
- operation: 'route',
182
- query: request.query,
183
- outcome: 'failure',
184
- userAction: 'not_required', // Error case - no review flow
185
- errors: ['Indexing required'],
186
- });
187
- }
188
- catch {
189
- // Non-blocking
190
- }
191
- return {
192
- intent: 'index',
193
- action: 'index',
194
- result: { message: 'Indexing required. Please run: codehere index' },
195
- success: false,
196
- message: 'Codebase not indexed. Run "codehere index" first, then try again.',
197
- memoriesUsed: memories.length,
198
- routingDecision,
199
- routingRunId,
200
- };
201
- }
202
- // Route based on intent (pass memories for context)
203
- // Design: default to ask (LLM answers anything). Only use specialized
204
- // handlers when the user explicitly targets a file or action.
205
- let routingResult;
206
- try {
207
- switch (intent) {
208
- case 'explain': {
209
- // Only use file-explain if the query contains a real file path
210
- const filepath = this.extractFilepath(query);
211
- if (filepath) {
212
- routingResult = await this.handleExplainWithWorkflow(query, symbols, memories);
213
- }
214
- else {
215
- // No file path → treat as a question about the codebase
216
- routingResult = await this.handleAsk(query, memories);
217
- }
218
- break;
219
- }
220
- case 'modify':
221
- case 'debug':
222
- case 'implement': {
223
- // Only route to edit if query references a specific file
224
- const editPath = this.extractFilepath(query);
225
- if (editPath) {
226
- routingResult = await this.handleEdit(query, symbols, memories);
227
- }
228
- else {
229
- // "fix the auth" without a file → ask (LLM explains what to do)
230
- routingResult = await this.handleAsk(query, memories);
231
- }
232
- break;
233
- }
234
- case 'multi-file-modify':
235
- routingResult = await this.handleOrchestrate(query, memories);
236
- break;
237
- case 'index':
238
- routingResult = await this.handleIndex(query);
239
- break;
240
- case 'plan':
241
- routingResult = await this.handlePlan(query, memories);
242
- break;
243
- default:
244
- // Everything else → ask. The LLM is smart enough.
245
- routingResult = await this.handleAsk(query, memories);
246
- break;
247
- }
248
- // Attach routing decision to result
249
- routingResult.routingDecision = routingDecision;
250
- routingResult.routingRunId = routingRunId;
251
- // End routing trace
252
- executionTracer.endRun();
253
- // Record routing feedback
254
- try {
255
- agentFeedbackManager.recordFeedback({
256
- runId: routingRunId,
257
- agentName: 'intelligent-router',
258
- operation: 'route',
259
- query: request.query,
260
- outcome: routingResult.success ? 'success' : 'failure',
261
- userAction: 'not_required', // Internal routing - no review flow
262
- errors: routingResult.error ? [routingResult.error] : undefined,
263
- });
264
- }
265
- catch {
266
- // Non-blocking
267
- }
268
- return routingResult;
269
- }
270
- catch (error) {
271
- // End run on error
272
- executionTracer.endRun();
273
- // Record failure
274
- try {
275
- agentFeedbackManager.recordFeedback({
276
- runId: routingRunId,
277
- agentName: 'intelligent-router',
278
- operation: 'route',
279
- query: request.query,
280
- outcome: 'failure',
281
- userAction: 'not_required', // Error case - no review flow
282
- errors: [error instanceof Error ? error.message : String(error)],
283
- });
284
- }
285
- catch {
286
- // Non-blocking
287
- }
288
- return {
289
- intent,
290
- action: selectedAction === 'orchestrate' ? 'general' : selectedAction,
291
- result: null,
292
- success: false,
293
- error: error instanceof Error ? error.message : String(error),
294
- routingDecision,
295
- routingRunId,
296
- };
297
- }
298
- }
299
- catch (outerError) {
300
- // Catch any errors from the outer try block (validation, classification, etc.)
301
- executionTracer.endRun();
302
- try {
303
- agentFeedbackManager.recordFeedback({
304
- runId: routingRunId,
305
- agentName: 'intelligent-router',
306
- operation: 'route',
307
- query: request.query,
308
- outcome: 'failure',
309
- userAction: 'not_required', // Error case - no review flow
310
- errors: [outerError instanceof Error ? outerError.message : String(outerError)],
311
- });
312
- }
313
- catch {
314
- // Non-blocking
315
- }
316
- return {
317
- intent: 'error',
318
- action: 'general',
319
- result: null,
320
- success: false,
321
- error: outerError instanceof Error ? outerError.message : String(outerError),
322
- routingRunId,
323
- };
324
- }
325
- }
326
- /**
327
- * Classify intent using AI and memory context
328
- * More accurate than keyword-based classification
329
- */
330
- async classifyIntentWithMemory(query, memories) {
331
- if (!this.aiService) {
332
- return this.intentClassifier.classify(query);
333
- }
334
- // Build memory context
335
- const memoryContext = memories
336
- .slice(0, 5) // Use top 5 most relevant
337
- .map((m, i) => `${i + 1}. ${m.description} (${m.type})`)
338
- .join('\n');
339
- const prompt = `Classify the intent of this user query. Consider past experiences that might inform the classification.
340
-
341
- Query: "${query}"
342
-
343
- Relevant Past Experiences:
344
- ${memoryContext}
345
-
346
- Classify the intent as ONE of: explain, refactor, debug, implement, understand, find, modify, multi-file-modify, index, review, test, plan, general
347
-
348
- Consider:
349
- - If similar queries were handled successfully before, use that intent
350
- - If past experiences suggest a specific approach, use that
351
- - If the query is complex and requires planning, use "plan"
352
- - If it's a simple question, use "understand" or "find"
353
-
354
- Respond with ONLY the intent word (e.g., "explain", "plan", "understand"):`;
355
- try {
356
- const response = await this.aiService.chat(prompt, []);
357
- const intent = response.trim().toLowerCase().split(/\s+/)[0];
358
- // Validate intent
359
- const validIntents = ['explain', 'refactor', 'debug', 'implement', 'understand', 'find', 'modify', 'multi-file-modify', 'index', 'review', 'test', 'plan', 'general'];
360
- if (validIntents.includes(intent)) {
361
- return intent;
362
- }
363
- }
364
- catch (error) {
365
- // Fallback to keyword-based
366
- }
367
- return this.intentClassifier.classify(query);
368
- }
369
- /**
370
- * Check if query is a simple question (explain, find, understand)
371
- * Simple questions should NEVER use ReAct - they go directly to AskQuestionUseCase
372
- */
373
- isSimpleQuestion(query) {
374
- const lower = query.toLowerCase();
375
- // Simple question patterns
376
- const simplePatterns = [
377
- /^(what|where|how|why|when|who|which|is|are|does|do|can|could|will|would)\s+/i,
378
- /^(explain|describe|tell me about|show me|find|locate|search for)/i,
379
- /^(what is|what are|where is|where are|how does|how do|how is|how are)/i,
380
- /\?$/, // Ends with question mark
381
- ];
382
- // Check if query matches simple question patterns
383
- const isQuestion = simplePatterns.some(pattern => pattern.test(query));
384
- // Simple if it's a question AND doesn't require multiple steps
385
- const isSingleStep = !this.isComplexQuery(query);
386
- return isQuestion && isSingleStep;
387
- }
388
- /**
389
- * Determine if ReAct should be used based on query complexity and past experiences
390
- * CRITICAL: Only use ReAct for truly complex multi-step queries
391
- */
392
- shouldUseReAct(query, memories) {
393
- // NEVER use ReAct for simple questions
394
- if (this.isSimpleQuestion(query)) {
395
- return false;
396
- }
397
- // Check query complexity - must be truly complex
398
- if (!this.isComplexQuery(query)) {
399
- return false;
400
- }
401
- // Additional check: Query must require multiple tools/steps
402
- const requiresMultipleSteps = this.requiresMultipleSteps(query);
403
- if (!requiresMultipleSteps) {
404
- return false;
405
- }
406
- // Check memories for similar queries that used ReAct successfully
407
- // But only if query is already complex
408
- if (memories.length > 0) {
409
- const similarQueries = memories.filter(m => {
410
- const desc = m.description.toLowerCase();
411
- const queryLower = query.toLowerCase();
412
- // Check if memory mentions ReAct or similar complex handling
413
- return desc.includes('react') ||
414
- desc.includes('complex') ||
415
- desc.includes('multi-step') ||
416
- (desc.includes(queryLower.split(' ')[0]) && m.metadata?.action === 'react');
417
- });
418
- // If we have memories of similar queries using ReAct, use it
419
- if (similarQueries.length > 0) {
420
- return true;
421
- }
422
- }
423
- return false;
424
- }
425
- /**
426
- * Check if query requires multiple steps/tools
427
- */
428
- requiresMultipleSteps(query) {
429
- const lower = query.toLowerCase();
430
- // Multi-step indicators
431
- const multiStepIndicators = [
432
- 'and then',
433
- 'after that',
434
- 'also',
435
- 'first',
436
- 'second',
437
- 'third',
438
- 'finally',
439
- 'then',
440
- 'next',
441
- 'step',
442
- 'steps',
443
- 'multiple',
444
- 'several',
445
- 'check',
446
- 'verify',
447
- 'debug',
448
- 'fix',
449
- 'and',
450
- 'while',
451
- 'during',
452
- ];
453
- // Count multi-step indicators
454
- const indicatorCount = multiStepIndicators.filter(indicator => lower.includes(indicator)).length;
455
- // Requires multiple steps if 2+ indicators or very long query
456
- return indicatorCount >= 2 || query.split(' ').length > 20;
457
- }
458
- async checkIfIndexingNeeded(context) {
459
- if (context?.hasIndex === false)
460
- return true;
461
- try {
462
- const { container } = await import('./dependency-container.js');
463
- // Use per-repo embedding repository for codebase isolation
464
- const repo = container.getEmbeddingRepository(process.cwd());
465
- // Check if any embeddings exist
466
- const testSearch = await repo.searchWithEmbedding([0.1], 1);
467
- return testSearch.length === 0;
468
- }
469
- catch {
470
- return true; // Assume needs indexing if check fails
471
- }
472
- }
473
- async handleAsk(query, memories) {
474
- try {
475
- const { container } = await import('./dependency-container.js');
476
- // Use per-repo use case for codebase isolation
477
- const useCase = container.getAskQuestionUseCase(process.cwd());
478
- const result = await useCase.execute({ query, maxResults: 15 });
479
- // Record successful routing in memory
480
- if (this.memoryStream && memories && memories.length > 0) {
481
- await this.memoryStream.recordObservation(`Successfully routed query to AskQuestionUseCase: ${query}`, {
482
- query,
483
- action: 'ask',
484
- memoriesUsed: memories.length,
485
- });
486
- }
487
- return {
488
- intent: 'understand',
489
- action: 'ask',
490
- result,
491
- success: result.chunks.length > 0,
492
- message: result.answer,
493
- memoriesUsed: memories?.length || 0,
494
- };
495
- }
496
- catch (error) {
497
- return {
498
- intent: 'understand',
499
- action: 'ask',
500
- result: null,
501
- success: false,
502
- error: error instanceof Error ? error.message : String(error),
503
- memoriesUsed: memories?.length || 0,
504
- };
505
- }
506
- }
507
- async handleExplainWithWorkflow(query, symbols, memories) {
508
- // Try deterministic workflow first (faster, no ReAct overhead)
509
- try {
510
- const { container } = await import('./dependency-container.js');
511
- const { ExplainWorkflow } = await import('../workflows/deterministic-workflows.js');
512
- // Use per-repo embedding repository for codebase isolation
513
- const explainWorkflow = new ExplainWorkflow(container.getEmbeddingRepository(process.cwd()), container.aiService);
514
- const workflowResult = await explainWorkflow.execute(query);
515
- if (workflowResult.success) {
516
- return {
517
- intent: 'explain',
518
- action: 'explain',
519
- result: workflowResult.result,
520
- success: true,
521
- message: workflowResult.result?.explanation || 'Explanation generated',
522
- memoriesUsed: memories?.length || 0,
523
- };
524
- }
525
- }
526
- catch (error) {
527
- // Fallback to original implementation if workflow fails
528
- console.warn('Workflow failed, falling back to standard explain:', error);
529
- }
530
- // Fallback to standard explain
531
- return await this.handleExplain(query, symbols, memories);
532
- }
533
- async handleExplain(query, symbols, memories) {
534
- // Extract filepath from query
535
- const filepath = this.extractFilepath(query);
536
- if (!filepath) {
537
- // No filepath found, treat as ask query
538
- return await this.handleAsk(query, memories);
539
- }
540
- try {
541
- const { container } = await import('./dependency-container.js');
542
- const useCase = container.explainFileUseCase;
543
- const result = await useCase.execute({ filepath });
544
- // Record successful routing
545
- if (this.memoryStream && memories && memories.length > 0) {
546
- await this.memoryStream.recordObservation(`Successfully routed to ExplainFileUseCase: ${query}`, {
547
- query,
548
- action: 'explain',
549
- filepath,
550
- memoriesUsed: memories.length,
551
- });
552
- }
553
- return {
554
- intent: 'explain',
555
- action: 'explain',
556
- result,
557
- success: true,
558
- message: result.explanation,
559
- memoriesUsed: memories?.length || 0,
560
- };
561
- }
562
- catch (error) {
563
- return {
564
- intent: 'explain',
565
- action: 'explain',
566
- result: null,
567
- success: false,
568
- error: error instanceof Error ? error.message : String(error),
569
- memoriesUsed: memories?.length || 0,
570
- };
571
- }
572
- }
573
- async handleEdit(query, symbols, memories) {
574
- // Extract filepath and instruction
575
- let { filepath, instruction } = this.extractEditParams(query);
576
- // CRITICAL: Fast security check BEFORE any expensive operations (file search, reading, etc.)
577
- // This prevents wasting time and tokens on dangerous code
578
- if (instruction) {
579
- const securityCheck = await this.fastSecurityCheck(instruction);
580
- if (!securityCheck.allowed) {
581
- return {
582
- intent: 'edit',
583
- action: 'edit',
584
- result: null,
585
- success: false,
586
- error: securityCheck.reason,
587
- memoriesUsed: memories?.length || 0,
588
- };
589
- }
590
- }
591
- if (DEBUG)
592
- console.log(`[IntelligentRouter] Edit query: ${query}`);
593
- if (DEBUG)
594
- console.log(`[IntelligentRouter] Extracted filepath: ${filepath || 'none'}`);
595
- if (DEBUG)
596
- console.log(`[IntelligentRouter] Extracted instruction: ${instruction || 'none'}`);
597
- if (DEBUG)
598
- console.log(`[IntelligentRouter] Symbols found: ${symbols.join(', ')}`);
599
- // If no filepath found but we have symbols (class/function names), search for the file
600
- if (!filepath && symbols.length > 0) {
601
- // Filter out common words and prioritize capitalized names (likely class/function names)
602
- const meaningfulSymbols = symbols.filter(s => {
603
- const lower = s.toLowerCase();
604
- // Exclude common words
605
- return !['in', 'to', 'the', 'a', 'an', 'and', 'or', 'of', 'for', 'with', 'from'].includes(lower) &&
606
- s.length > 2; // At least 3 characters
607
- });
608
- // Prioritize capitalized names (classes) and camelCase (functions)
609
- const prioritizedSymbols = meaningfulSymbols.sort((a, b) => {
610
- const aIsClass = /^[A-Z]/.test(a);
611
- const bIsClass = /^[A-Z]/.test(b);
612
- if (aIsClass && !bIsClass)
613
- return -1;
614
- if (!aIsClass && bIsClass)
615
- return 1;
616
- return b.length - a.length; // Longer names are more specific
617
- });
618
- if (DEBUG)
619
- console.log(`[IntelligentRouter] Filtered symbols: ${prioritizedSymbols.join(', ')}`);
620
- if (prioritizedSymbols.length > 0) {
621
- if (DEBUG)
622
- console.log(`[IntelligentRouter] Searching for file containing symbol: ${prioritizedSymbols[0]}`);
623
- filepath = await this.findFileBySymbol(prioritizedSymbols[0], query);
624
- if (DEBUG)
625
- console.log(`[IntelligentRouter] Found filepath: ${filepath || 'none'}`);
626
- }
627
- }
628
- if (!filepath || !instruction) {
629
- console.error(`[IntelligentRouter] Missing filepath or instruction. filepath: ${filepath}, instruction: ${instruction}`);
630
- return {
631
- intent: 'edit',
632
- action: 'edit',
633
- result: null,
634
- success: false,
635
- error: 'Could not extract filepath and instruction from query. Format: "edit <file> <instruction>" or "fix <file> <what to fix>" or mention the class/function name',
636
- memoriesUsed: memories?.length || 0,
637
- };
638
- }
639
- if (DEBUG)
640
- console.log(`[IntelligentRouter] Proceeding with edit: ${filepath} - ${instruction}`);
641
- try {
642
- const { container } = await import('./dependency-container.js');
643
- const useCase = container.editFileUseCase;
644
- const result = await useCase.execute({ filepath, instruction });
645
- // Record successful routing
646
- if (this.memoryStream && memories && memories.length > 0) {
647
- await this.memoryStream.recordObservation(`Successfully routed to EditFileUseCase: ${query}`, {
648
- query,
649
- action: 'edit',
650
- filepath,
651
- memoriesUsed: memories.length,
652
- success: result.success,
653
- });
654
- }
655
- return {
656
- intent: 'edit',
657
- action: 'edit',
658
- result,
659
- success: result.success,
660
- message: result.success ? 'Edit applied successfully' : result.error,
661
- error: result.error,
662
- memoriesUsed: memories?.length || 0,
663
- };
664
- }
665
- catch (error) {
666
- return {
667
- intent: 'edit',
668
- action: 'edit',
669
- result: null,
670
- success: false,
671
- error: error instanceof Error ? error.message : String(error),
672
- memoriesUsed: memories?.length || 0,
673
- };
674
- }
675
- }
676
- async handleReAct(query, memories) {
677
- try {
678
- const { container } = await import('./dependency-container.js');
679
- const useCase = container.reactOrchestrationUseCase;
680
- // Pass memories to ReAct for context
681
- const result = await useCase.execute({
682
- query,
683
- maxTurns: 15,
684
- context: {
685
- memories: memories || [],
686
- },
687
- });
688
- // Record successful routing
689
- if (this.memoryStream && memories && memories.length > 0) {
690
- await this.memoryStream.recordObservation(`Successfully routed complex query to ReAct: ${query}`, {
691
- query,
692
- action: 'react',
693
- memoriesUsed: memories.length,
694
- steps: result.trajectory.steps.length,
695
- });
696
- }
697
- return {
698
- intent: 'general',
699
- action: 'react',
700
- result,
701
- success: result.trajectory.success,
702
- message: result.answer,
703
- memoriesUsed: memories?.length || 0,
704
- };
705
- }
706
- catch (error) {
707
- return {
708
- intent: 'general',
709
- action: 'react',
710
- result: null,
711
- success: false,
712
- error: error instanceof Error ? error.message : String(error),
713
- memoriesUsed: memories?.length || 0,
714
- };
715
- }
716
- }
717
- async handleIndex(query) {
718
- return {
719
- intent: 'index',
720
- action: 'index',
721
- result: { message: 'Use "codehere index" command to index the codebase' },
722
- success: false,
723
- message: 'To index the codebase, run: codehere index',
724
- };
725
- }
726
- async handlePlan(query, memories) {
727
- try {
728
- const { container } = await import('./dependency-container.js');
729
- const useCase = container.planningUseCase;
730
- const result = await useCase.execute({
731
- goal: query,
732
- planningMode: 'hybrid',
733
- context: {
734
- // Pass memories for planning context
735
- },
736
- });
737
- // Record successful planning
738
- if (this.memoryStream && memories && memories.length > 0) {
739
- await this.memoryStream.recordObservation(`Successfully routed to Planning Module: ${query}`, {
740
- query,
741
- action: 'plan',
742
- memoriesUsed: memories.length,
743
- subPlans: result.plan.subPlans.length,
744
- });
745
- }
746
- return {
747
- intent: 'plan',
748
- action: 'plan',
749
- result,
750
- success: true,
751
- message: `Plan created with ${result.plan.subPlans.length} sub-plans`,
752
- memoriesUsed: memories?.length || 0,
753
- };
754
- }
755
- catch (error) {
756
- return {
757
- intent: 'plan',
758
- action: 'plan',
759
- result: null,
760
- success: false,
761
- error: error instanceof Error ? error.message : String(error),
762
- memoriesUsed: memories?.length || 0,
763
- };
764
- }
765
- }
766
- async handleOrchestrate(query, memories) {
767
- try {
768
- const { container } = await import('./dependency-container.js');
769
- const orchestrator = container.multiAgentOrchestrator;
770
- const result = await orchestrator.orchestrate({
771
- goal: query,
772
- mode: 'full', // Plan + Execute + Validate
773
- context: {
774
- // Pass memories context if needed
775
- },
776
- });
777
- // Record successful orchestration
778
- if (this.memoryStream && memories && memories.length > 0) {
779
- await this.memoryStream.recordObservation(`Successfully routed compound instruction to Orchestrator: ${query}`, {
780
- query,
781
- action: 'orchestrate',
782
- memoriesUsed: memories.length,
783
- planSubPlans: result.plan?.subPlans.length || 0,
784
- executionCompleted: result.execution?.completedSubPlans || 0,
785
- });
786
- }
787
- return {
788
- intent: 'plan',
789
- action: 'plan',
790
- result,
791
- success: result.success,
792
- message: result.message,
793
- error: result.success ? undefined : result.message,
794
- memoriesUsed: memories?.length || 0,
795
- };
796
- }
797
- catch (error) {
798
- return {
799
- intent: 'plan',
800
- action: 'plan',
801
- result: null,
802
- success: false,
803
- error: error instanceof Error ? error.message : String(error),
804
- memoriesUsed: memories?.length || 0,
805
- };
806
- }
807
- }
808
- extractFilepath(query) {
809
- // Look for file paths in query
810
- const patterns = [
811
- /(?:file|in|from|at)\s+([^\s]+\.(ts|js|tsx|jsx|py|java|cpp|go|rs|rb|php|vue|svelte|html|css|json|yaml|yml|md|txt|sh|bash))/i,
812
- /([a-zA-Z0-9_\-/]+\.(ts|js|tsx|jsx|py|java|cpp|go|rs|rb|php|vue|svelte|html|css|json|yaml|yml|md|txt|sh|bash))/,
813
- /src\/[^\s]+/,
814
- /\.\/[^\s]+/,
815
- ];
816
- for (const pattern of patterns) {
817
- const match = query.match(pattern);
818
- if (match) {
819
- return match[1] || match[0];
820
- }
821
- }
822
- return null;
823
- }
824
- extractEditParams(query) {
825
- const filepath = this.extractFilepath(query);
826
- if (!filepath) {
827
- return { filepath: null, instruction: query };
828
- }
829
- // Remove filepath from query to get instruction
830
- const instruction = query
831
- .replace(new RegExp(filepath.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), 'gi'), '')
832
- .replace(/(?:edit|fix|modify|change|update|add to|remove from)\s+/i, '')
833
- .trim();
834
- return { filepath, instruction: instruction || 'Make the requested changes' };
835
- }
836
- isComplexQuery(query) {
837
- const lower = query.toLowerCase();
838
- // Complex if it requires multiple steps
839
- const complexIndicators = [
840
- 'and then',
841
- 'after that',
842
- 'also',
843
- 'multiple',
844
- 'several',
845
- 'steps',
846
- 'first',
847
- 'second',
848
- 'finally',
849
- 'create',
850
- 'build',
851
- 'implement',
852
- 'refactor',
853
- ];
854
- return complexIndicators.some(indicator => lower.includes(indicator)) ||
855
- query.split(' ').length > 15; // Long queries are likely complex
856
- }
857
- /**
858
- * Fast security check using pattern matching (before expensive operations)
859
- * Synchronous pattern matching - instant rejection for dangerous patterns
860
- */
861
- fastSecurityCheck(query) {
862
- // Fast pattern-based check for obvious security issues (synchronous, no API calls)
863
- const lower = query.toLowerCase();
864
- // Dangerous patterns that should be blocked immediately
865
- const dangerousPatterns = [
866
- { pattern: /execute.*user.*input|eval.*user|exec.*user/i, reason: 'Security vulnerabilities detected: 1 critical, 0 high severity findings. Review and fix before applying.' },
867
- { pattern: /shell.*command|system.*call|process\.exec/i, reason: 'Security vulnerabilities detected: 1 critical, 0 high severity findings. Review and fix before applying.' },
868
- { pattern: /bypass.*security|disable.*security|remove.*validation/i, reason: 'Security vulnerabilities detected: 1 critical, 0 high severity findings. Review and fix before applying.' },
869
- { pattern: /hardcode.*password|store.*password.*plaintext|plaintext.*password/i, reason: 'Security vulnerabilities detected: 0 critical, 1 high severity findings. Review and fix before applying.' },
870
- ];
871
- for (const { pattern, reason } of dangerousPatterns) {
872
- if (pattern.test(query)) {
873
- return { allowed: false, reason };
874
- }
875
- }
876
- return { allowed: true };
877
- }
878
- /**
879
- * Find file containing a symbol (class/function name)
880
- * Uses search to locate the file
881
- */
882
- async findFileBySymbol(symbol, query) {
883
- try {
884
- if (DEBUG)
885
- console.log(`[IntelligentRouter] Searching for symbol: ${symbol}`);
886
- const { container } = await import('./dependency-container.js');
887
- const useCase = container.askQuestionUseCase;
888
- // Search for the symbol - try multiple query variations
889
- const searchQueries = [
890
- `Find ${symbol}`,
891
- `file containing ${symbol}`,
892
- `Where is ${symbol} defined`,
893
- `${symbol} class or function`,
894
- ];
895
- for (const searchQuery of searchQueries) {
896
- if (DEBUG)
897
- console.log(`[IntelligentRouter] Trying search query: ${searchQuery}`);
898
- const result = await useCase.execute({ query: searchQuery, maxResults: 5 });
899
- // Look for filepath in results
900
- if (result.chunks && result.chunks.length > 0) {
901
- // Get the most relevant chunk
902
- const topChunk = result.chunks[0];
903
- if (topChunk && topChunk.filepath) {
904
- // Convert absolute path to relative if needed
905
- let filepath = topChunk.filepath;
906
- const cwd = process.cwd();
907
- if (filepath.startsWith(cwd)) {
908
- filepath = filepath.substring(cwd.length + 1); // Remove leading slash
909
- }
910
- if (DEBUG)
911
- console.log(`[IntelligentRouter] Found filepath from search: ${filepath}`);
912
- return filepath;
913
- }
914
- }
915
- // Also check answer for filepath mentions
916
- if (result.answer) {
917
- const filepathMatch = result.answer.match(/([^\s]+\.(ts|js|tsx|jsx|py|java|cpp|go|rs|rb|php|vue|svelte|html|css|json|yaml|yml|md|txt|sh|bash))/);
918
- if (filepathMatch) {
919
- if (DEBUG)
920
- console.log(`[IntelligentRouter] Found filepath from answer: ${filepathMatch[1]}`);
921
- return filepathMatch[1];
922
- }
923
- }
924
- }
925
- console.warn(`[IntelligentRouter] Could not find file for symbol: ${symbol}`);
926
- return null;
927
- }
928
- catch (error) {
929
- console.error(`[IntelligentRouter] Failed to find file by symbol:`, error);
930
- return null;
931
- }
932
- }
933
- }
934
- //# sourceMappingURL=intelligent-router.js.map