codehere 0.2.2 → 0.3.0-rc.10

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 (238) 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 +261 -1224
  5. package/dist/infrastructure/config/product-context.js +7 -6
  6. package/dist/infrastructure/hooks/claude-sdk-hook.js +348 -72
  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/conductor-adapter.js +340 -0
  16. package/dist/infrastructure/orchestration/generic-cli-adapter.js +553 -0
  17. package/dist/infrastructure/orchestration/opencode-adapter.js +275 -0
  18. package/dist/infrastructure/orchestration/progress-aggregator.js +189 -0
  19. package/dist/infrastructure/orchestration/readiness.js +106 -0
  20. package/dist/infrastructure/orchestration/session-manager.js +278 -0
  21. package/dist/infrastructure/orchestration/session-persistence.js +109 -0
  22. package/dist/infrastructure/protocols/mcp-helpers.js +10 -30
  23. package/dist/infrastructure/protocols/mcp-server-impl.js +359 -21
  24. package/dist/infrastructure/protocols/probe-port.js +36 -0
  25. package/dist/infrastructure/protocols/ui-page.js +1827 -0
  26. package/dist/infrastructure/security/file-collection.js +115 -0
  27. package/dist/infrastructure/security/trust-scorer.js +301 -56
  28. package/dist/infrastructure/storage/task-repository.js +8 -7
  29. package/dist/monitoring.js +9 -38
  30. package/dist/presentation/cli/commands/help-command.js +96 -139
  31. package/dist/presentation/cli/commands/hook-command.js +17 -24
  32. package/dist/presentation/cli/commands/report-command.js +59 -72
  33. package/dist/presentation/cli/commands/setup-command.js +4 -4
  34. package/dist/presentation/cli/commands/status-command.js +321 -30
  35. package/dist/presentation/cli/commands/trust-command.js +84 -72
  36. package/dist/presentation/cli/error-display.js +17 -21
  37. package/dist/presentation/cli/repl.js +474 -0
  38. package/dist/ui.js +11 -11
  39. package/package.json +24 -62
  40. package/dist/agents/base.js +0 -101
  41. package/dist/agents/orchestrator-model-driven.js +0 -141
  42. package/dist/agents/react-orchestrator-agent.js +0 -54
  43. package/dist/application/agents/execution-agent.js +0 -508
  44. package/dist/application/agents/multi-agent-orchestrator.js +0 -295
  45. package/dist/application/agents/planning-agent.js +0 -433
  46. package/dist/application/agents/validation-agent.js +0 -317
  47. package/dist/application/architectures/plan-and-act.js +0 -242
  48. package/dist/application/index.js +0 -12
  49. package/dist/application/services/agent-factory.js +0 -28
  50. package/dist/application/services/dependency-container.js +0 -596
  51. package/dist/application/services/git-context-service.js +0 -83
  52. package/dist/application/services/intelligent-router.js +0 -934
  53. package/dist/application/services/tool-executor-service.js +0 -94
  54. package/dist/application/use-cases/ask-question-use-case.js +0 -338
  55. package/dist/application/use-cases/edit-file-use-case.js +0 -830
  56. package/dist/application/use-cases/explain-file-use-case.js +0 -50
  57. package/dist/application/use-cases/index-codebase-use-case.js +0 -113
  58. package/dist/application/use-cases/planning-use-case.js +0 -276
  59. package/dist/application/use-cases/react-orchestration-use-case.js +0 -329
  60. package/dist/application/use-cases/reflexion-use-case.js +0 -30
  61. package/dist/application/workflows/deterministic-workflows.js +0 -189
  62. package/dist/ast-parser.js +0 -331
  63. package/dist/cache.js +0 -180
  64. package/dist/chat.js +0 -251
  65. package/dist/code-analysis.js +0 -327
  66. package/dist/context.js +0 -187
  67. package/dist/docs.js +0 -146
  68. package/dist/domain/entities/code-chunk.js +0 -6
  69. package/dist/domain/entities/decision.js +0 -9
  70. package/dist/domain/entities/edit.js +0 -6
  71. package/dist/domain/entities/knowledge-node.js +0 -9
  72. package/dist/domain/entities/knowledge-preservation.js +0 -10
  73. package/dist/domain/entities/memory.js +0 -6
  74. package/dist/domain/entities/pattern.js +0 -7
  75. package/dist/domain/entities/plan.js +0 -6
  76. package/dist/domain/entities/query.js +0 -6
  77. package/dist/domain/errors/embeddings-not-found-error.js +0 -13
  78. package/dist/domain/index.js +0 -19
  79. package/dist/domain/interfaces/ai-service.interface.js +0 -6
  80. package/dist/domain/interfaces/code-analyzer.interface.js +0 -6
  81. package/dist/domain/interfaces/decision-repository.interface.js +0 -9
  82. package/dist/domain/interfaces/embedding-repository.interface.js +0 -6
  83. package/dist/domain/interfaces/knowledge-graph-repository.interface.js +0 -9
  84. package/dist/domain/interfaces/knowledge-preservation-repository.interface.js +0 -8
  85. package/dist/domain/interfaces/memory-repository.interface.js +0 -6
  86. package/dist/domain/interfaces/pattern-repository.interface.js +0 -6
  87. package/dist/domain/interfaces/verification-service.interface.js +0 -6
  88. package/dist/domain/services/cross-team-pattern-sharing.js +0 -125
  89. package/dist/domain/services/decision-recorder.js +0 -223
  90. package/dist/domain/services/decision-retriever.js +0 -133
  91. package/dist/domain/services/environment-mode-manager.js +0 -22
  92. package/dist/domain/services/graded-memory-activation.js +0 -69
  93. package/dist/domain/services/knowledge-access.js +0 -132
  94. package/dist/domain/services/knowledge-extractor.js +0 -247
  95. package/dist/domain/services/knowledge-graph-builder.js +0 -268
  96. package/dist/domain/services/knowledge-graph-query.js +0 -187
  97. package/dist/domain/services/memory-retriever.js +0 -82
  98. package/dist/domain/services/memory-synthesizer.js +0 -91
  99. package/dist/domain/services/pattern-extractor.js +0 -442
  100. package/dist/domain/services/query-intent-classifier.js +0 -140
  101. package/dist/domain/services/react-loop.js +0 -186
  102. package/dist/domain/services/risk-tier-detector.js +0 -78
  103. package/dist/edit.js +0 -319
  104. package/dist/embed.js +0 -459
  105. package/dist/formatter.js +0 -168
  106. package/dist/git.js +0 -198
  107. package/dist/infrastructure/ai/cohere-ai-service.js +0 -607
  108. package/dist/infrastructure/ai/command-r-evaluation.js +0 -206
  109. package/dist/infrastructure/ai/model-config.js +0 -84
  110. package/dist/infrastructure/ai/provider-ai-service.js +0 -477
  111. package/dist/infrastructure/cache/embedding-cache.js +0 -175
  112. package/dist/infrastructure/cache/query-result-cache.js +0 -66
  113. package/dist/infrastructure/cache/response-cache.js +0 -48
  114. package/dist/infrastructure/cache/security-scan-cache.js +0 -47
  115. package/dist/infrastructure/chunking/ast-code-chunker.js +0 -19
  116. package/dist/infrastructure/chunking/code-aware-chunker.js +0 -397
  117. package/dist/infrastructure/context/context-compressor.js +0 -329
  118. package/dist/infrastructure/context/conversation-context.js +0 -128
  119. package/dist/infrastructure/context/session-manager.js +0 -94
  120. package/dist/infrastructure/cost/cost-tracker.js +0 -360
  121. package/dist/infrastructure/file-scanner/file-scanner.js +0 -106
  122. package/dist/infrastructure/governance/nist-ai-rmf.js +0 -292
  123. package/dist/infrastructure/governance/policy-as-code.js +0 -258
  124. package/dist/infrastructure/governance/prompt-to-code-lineage.js +0 -239
  125. package/dist/infrastructure/index.js +0 -7
  126. package/dist/infrastructure/observability/prompt-versioner.js +0 -145
  127. package/dist/infrastructure/protocols/a2a-metadata.js +0 -137
  128. package/dist/infrastructure/protocols/a2a-protocol.js +0 -314
  129. package/dist/infrastructure/protocols/mcp-oauth.js +0 -184
  130. package/dist/infrastructure/protocols/mcp-server.js +0 -333
  131. package/dist/infrastructure/protocols/streaming-handler.js +0 -103
  132. package/dist/infrastructure/providers/cohere-provider.js +0 -444
  133. package/dist/infrastructure/providers/fake-provider.js +0 -130
  134. package/dist/infrastructure/providers/local-llm-provider.js +0 -330
  135. package/dist/infrastructure/providers/model-config.types.js +0 -9
  136. package/dist/infrastructure/providers/model-provider.interface.js +0 -8
  137. package/dist/infrastructure/providers/openai-provider.js +0 -413
  138. package/dist/infrastructure/providers/openrouter-provider.js +0 -399
  139. package/dist/infrastructure/providers/operation-provider-resolver.js +0 -105
  140. package/dist/infrastructure/providers/provider-config-loader.js +0 -120
  141. package/dist/infrastructure/providers/provider-registry.js +0 -88
  142. package/dist/infrastructure/safety/pattern-detector.js +0 -133
  143. package/dist/infrastructure/security/ai-sast-scanner.js +0 -290
  144. package/dist/infrastructure/security/docker-sandbox.js +0 -178
  145. package/dist/infrastructure/security/enhanced-security-gate.js +0 -151
  146. package/dist/infrastructure/security/license-scanner.js +0 -167
  147. package/dist/infrastructure/security/provider-bias-detector.js +0 -164
  148. package/dist/infrastructure/security/sandbox-executor.js +0 -64
  149. package/dist/infrastructure/serialization/toon-serializer.js +0 -119
  150. package/dist/infrastructure/storage/memory-stream-service.js +0 -204
  151. package/dist/infrastructure/storage/plan-repository.js +0 -96
  152. package/dist/infrastructure/storage/sqlite-decision-repository.js +0 -232
  153. package/dist/infrastructure/storage/sqlite-embedding-repository.js +0 -311
  154. package/dist/infrastructure/storage/sqlite-knowledge-graph-repository.js +0 -417
  155. package/dist/infrastructure/storage/sqlite-knowledge-preservation-repository.js +0 -230
  156. package/dist/infrastructure/storage/sqlite-memory-repository.js +0 -229
  157. package/dist/infrastructure/storage/sqlite-pattern-repository.js +0 -249
  158. package/dist/infrastructure/storage/task-helpers.js +0 -197
  159. package/dist/infrastructure/telemetry/telemetry-service.js +0 -167
  160. package/dist/infrastructure/ux/appropriate-friction.js +0 -213
  161. package/dist/infrastructure/ux/bi-directional-learning.js +0 -337
  162. package/dist/infrastructure/ux/capability-boundaries.js +0 -42
  163. package/dist/infrastructure/ux/comprehensive-formatter.js +0 -117
  164. package/dist/infrastructure/ux/contextual-feature-discovery.js +0 -10
  165. package/dist/infrastructure/ux/expectation-management.js +0 -327
  166. package/dist/infrastructure/ux/feature-discovery.js +0 -14
  167. package/dist/infrastructure/ux/feedback-prompt.js +0 -45
  168. package/dist/infrastructure/ux/hitl-validation.js +0 -297
  169. package/dist/infrastructure/ux/progress-indicator.js +0 -116
  170. package/dist/infrastructure/ux/progressive-disclosure.js +0 -236
  171. package/dist/infrastructure/ux/review-checkpoint.js +0 -72
  172. package/dist/infrastructure/ux/staged-feature-intro.js +0 -24
  173. package/dist/infrastructure/ux/stream-markdown.js +0 -151
  174. package/dist/infrastructure/ux/syntax-highlighter.js +0 -91
  175. package/dist/infrastructure/ux/team-standards.js +0 -196
  176. package/dist/infrastructure/ux/transparency.js +0 -71
  177. package/dist/infrastructure/validation/agent-feedback.js +0 -55
  178. package/dist/infrastructure/validation/agent-validation-helper.js +0 -137
  179. package/dist/infrastructure/validation/review-handler.js +0 -40
  180. package/dist/infrastructure/validation/summary-aggregator.js +0 -70
  181. package/dist/infrastructure/validation/summary-extractor.js +0 -45
  182. package/dist/infrastructure/validation/trace-summary.js +0 -52
  183. package/dist/infrastructure/verification/verification-service.js +0 -47
  184. package/dist/infrastructure/xai/attention-visualizer.js +0 -172
  185. package/dist/infrastructure/xai/cot-visualizer.js +0 -283
  186. package/dist/infrastructure/xai/decision-tree-log.js +0 -212
  187. package/dist/infrastructure/xai/interactive-xai.js +0 -260
  188. package/dist/infrastructure/xai/uncertainty-quantifier.js +0 -198
  189. package/dist/intelligent-retrieval.js +0 -272
  190. package/dist/intent/classifier.js +0 -2
  191. package/dist/intent/context.js +0 -2
  192. package/dist/iterative-refinement.js +0 -189
  193. package/dist/learning.js +0 -232
  194. package/dist/log.js +0 -31
  195. package/dist/migrate.js +0 -133
  196. package/dist/parallel-processor.js +0 -534
  197. package/dist/planner.js +0 -198
  198. package/dist/policy.js +0 -26
  199. package/dist/presentation/cli/commands/ask-command.js +0 -314
  200. package/dist/presentation/cli/commands/cost-command.js +0 -191
  201. package/dist/presentation/cli/commands/decision-command.js +0 -207
  202. package/dist/presentation/cli/commands/docs-command.js +0 -25
  203. package/dist/presentation/cli/commands/fix-command.js +0 -53
  204. package/dist/presentation/cli/commands/knowledge-command.js +0 -129
  205. package/dist/presentation/cli/commands/learning-dashboard-command.js +0 -183
  206. package/dist/presentation/cli/commands/models-command.js +0 -194
  207. package/dist/presentation/cli/commands/orchestrate-command.js +0 -207
  208. package/dist/presentation/cli/commands/plan-command.js +0 -246
  209. package/dist/presentation/cli/commands/product-command.js +0 -199
  210. package/dist/presentation/cli/commands/react-command.js +0 -181
  211. package/dist/presentation/cli/commands/review-command.js +0 -154
  212. package/dist/presentation/cli/commands/run-command.js +0 -188
  213. package/dist/presentation/cli/commands/smart-command.js +0 -395
  214. package/dist/presentation/cli/commands/suggest-command.js +0 -138
  215. package/dist/presentation/cli/commands/trace-command.js +0 -129
  216. package/dist/presentation/cli/commands/undo-command.js +0 -150
  217. package/dist/query-optimizer.js +0 -205
  218. package/dist/refactor.js +0 -116
  219. package/dist/review.js +0 -206
  220. package/dist/search.js +0 -163
  221. package/dist/session.js +0 -704
  222. package/dist/task-verification.js +0 -336
  223. package/dist/testgen.js +0 -166
  224. package/dist/token-optimizer.js +0 -277
  225. package/dist/tools/bash.js +0 -213
  226. package/dist/tools/edit.js +0 -235
  227. package/dist/tools/executor.js +0 -153
  228. package/dist/tools/git-tool.js +0 -292
  229. package/dist/tools/parser.js +0 -158
  230. package/dist/tools/registry.js +0 -302
  231. package/dist/tools/search.js +0 -100
  232. package/dist/types.js +0 -2
  233. package/dist/utils/check-api-status.js +0 -100
  234. package/dist/utils/diff-parser.js +0 -162
  235. package/dist/verification/backup.js +0 -259
  236. package/dist/verification/compiler.js +0 -264
  237. package/dist/verification/index.js +0 -273
  238. 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