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,607 +0,0 @@
1
- /**
2
- * Infrastructure: CohereAIService
3
- * Implements IAIService using Cohere API
4
- */
5
- import { CohereClient } from 'cohere-ai';
6
- import { config } from 'dotenv';
7
- import { join, dirname } from 'path';
8
- import { fileURLToPath } from 'url';
9
- import { encoding_for_model } from 'tiktoken';
10
- import { retryWithBackoff, cohereCircuitBreaker } from '../../error-handler.js';
11
- import { executionTracer } from '../observability/execution-tracer.js';
12
- import { promptVersioner } from '../observability/prompt-versioner.js';
13
- import { getModelConfigManager } from './model-config.js';
14
- // Initialize tiktoken encoder for accurate token counting
15
- // Using cl100k_base which is compatible with most models
16
- let tokenEncoder = null;
17
- function getTokenEncoder() {
18
- if (!tokenEncoder) {
19
- try {
20
- tokenEncoder = encoding_for_model('gpt-3.5-turbo'); // cl100k_base encoding
21
- }
22
- catch {
23
- // Fallback if model not found
24
- tokenEncoder = encoding_for_model('gpt-4');
25
- }
26
- }
27
- return tokenEncoder;
28
- }
29
- function countTokens(text) {
30
- try {
31
- const encoder = getTokenEncoder();
32
- return encoder.encode(text).length;
33
- }
34
- catch (error) {
35
- // Fallback: Use character-based estimate only if tiktoken completely fails
36
- // This should rarely happen, but provides a safety net
37
- console.warn('Warning: tiktoken failed, using character-based estimate (less accurate)');
38
- return Math.ceil(text.length / 4);
39
- }
40
- }
41
- // Load .env
42
- try {
43
- const __filename = fileURLToPath(import.meta.url);
44
- const __dirname = dirname(__filename);
45
- const agentDir = join(__dirname, '../../..');
46
- config({ path: join(agentDir, '.env') });
47
- }
48
- catch { }
49
- config();
50
- export class CohereAIService {
51
- client;
52
- _contextCompressor;
53
- constructor(contextCompressor) {
54
- this._contextCompressor = contextCompressor;
55
- const apiKey = process.env.COHERE_API_KEY;
56
- if (!apiKey) {
57
- throw new Error('COHERE_API_KEY not found in environment');
58
- }
59
- this.client = new CohereClient({ token: apiKey });
60
- }
61
- async chat(query, context, memories) {
62
- // Context Compression: Compress if context is too large (P0 - prevents cost escalation)
63
- let finalContext = context;
64
- let finalMemories = memories;
65
- let compressionMetrics;
66
- // Lazy getter for context compressor to avoid circular dependency
67
- const contextCompressor = this._contextCompressor || this.contextCompressor;
68
- if (contextCompressor) {
69
- // Estimate tokens (rough: 1 token ≈ 4 chars)
70
- const estimatedTokens = context.reduce((sum, chunk) => sum + Math.ceil(chunk.content.length / 4), 0);
71
- // OPTIMIZATION: Lower compression threshold to trigger earlier (3000 vs 8000)
72
- // This reduces AI Chat latency by compressing context more aggressively
73
- // Further reduced from 4000 to 3000 for even more aggressive compression
74
- const maxTokens = 3000; // Reduced from 8000 to trigger compression earlier
75
- if (estimatedTokens > maxTokens) {
76
- const strategy = {
77
- maxTokens,
78
- preserveCode: true, // Keep code, compress comments/context
79
- preserveErrors: true,
80
- compressMemories: true,
81
- compressObservations: false, // Not applicable here
82
- };
83
- const compressed = await contextCompressor.compressWithSummarization(context, query, strategy);
84
- finalContext = compressed.chunks;
85
- compressionMetrics = {
86
- originalTokens: compressed.originalTokenCount,
87
- compressedTokens: compressed.compressedTokenCount,
88
- reductionPercent: compressed.reductionPercent,
89
- };
90
- // Compress memories if enabled
91
- if (strategy.compressMemories && memories && memories.length > 10) {
92
- finalMemories = await contextCompressor.compressMemories(memories, query, 10);
93
- }
94
- // Log compression metrics
95
- const runId = executionTracer.getCurrentRunId();
96
- if (runId) {
97
- executionTracer.trace({
98
- operationType: 'context_compression',
99
- operationName: 'compress_context',
100
- input: { contextCount: context.length, estimatedTokens },
101
- output: {
102
- compressedCount: finalContext.length,
103
- ...compressionMetrics
104
- },
105
- metadata: { strategy: 'llm_summarization' },
106
- });
107
- }
108
- }
109
- }
110
- // Use TOON serialization if enabled, otherwise use traditional format
111
- const { serializeCodeChunks } = await import('../serialization/toon-serializer.js');
112
- const contextText = await serializeCodeChunks(finalContext);
113
- const memoryText = finalMemories && finalMemories.length > 0
114
- ? `\n\nPREVIOUS EXPERIENCES:\n${finalMemories.map(m => `- ${m.description}`).join('\n')}`
115
- : '';
116
- // Get conversation history if available in context
117
- let conversationHistoryText = '';
118
- if (context.length > 0 && context[0].conversationHistory) {
119
- const history = context[0].conversationHistory;
120
- if (history && history.length > 0) {
121
- const recentHistory = history.slice(-3); // Last 3 turns
122
- conversationHistoryText = `\n\nCONVERSATION HISTORY:\n${recentHistory.map((turn, idx) => `[Previous ${idx + 1}]: User asked "${turn.query}". Response: ${turn.response.substring(0, 150)}...`).join('\n')}\n`;
123
- }
124
- }
125
- const prompt = `You are a strict coding assistant for enterprise environments.
126
- Use ONLY the provided code context.
127
- ${conversationHistoryText ? 'Consider the conversation history when answering the current query, especially if the user uses references like "it", "that", or "the previous".' : ''}
128
-
129
- CONTEXT:
130
- ${contextText}${memoryText}${conversationHistoryText}
131
-
132
- USER QUERY:
133
- ${query}`;
134
- // Determine model based on context size and use case
135
- // For now, use default. Command A evaluation will determine if we should migrate.
136
- const model = this.selectModel(context.length, memories?.length || 0, 'chat');
137
- // Register prompt version for reproducibility
138
- const promptVersionId = promptVersioner.registerVersion(prompt, {
139
- model: model || 'default',
140
- temperature: 0.7,
141
- operation: 'chat',
142
- });
143
- // Link to current run if available
144
- const runId = executionTracer.getCurrentRunId();
145
- if (runId) {
146
- promptVersioner.linkRunToVersion(prompt, runId);
147
- }
148
- const startTime = Date.now();
149
- return await retryWithBackoff(async () => {
150
- return await cohereCircuitBreaker.execute(async () => {
151
- // Trace LLM call
152
- const traceId = executionTracer.trace({
153
- operationType: 'llm_call',
154
- operationName: 'chat',
155
- input: { query, contextCount: context.length, memoryCount: memories?.length || 0 },
156
- metadata: {
157
- model: model || 'default',
158
- temperature: 0.7,
159
- promptVersionId,
160
- },
161
- });
162
- try {
163
- const response = await this.client.chat({
164
- message: prompt,
165
- ...(model ? { model } : {}), // Only add model if specified
166
- temperature: 0.7, // Balanced for general chat/explanation
167
- });
168
- const result = response.text || 'No response generated';
169
- const duration = Date.now() - startTime;
170
- // Count tokens for trace metadata
171
- const inputTokens = countTokens(prompt);
172
- const outputTokens = countTokens(result);
173
- // Update trace with output
174
- executionTracer.trace({
175
- operationType: 'llm_call',
176
- operationName: 'chat',
177
- output: { responseLength: result.length, inputTokens, outputTokens },
178
- duration,
179
- metadata: {
180
- model: model || 'default',
181
- temperature: 0.7,
182
- promptVersionId,
183
- },
184
- });
185
- return result;
186
- }
187
- catch (error) {
188
- // Trace error
189
- executionTracer.trace({
190
- operationType: 'llm_call',
191
- operationName: 'chat',
192
- error: error instanceof Error ? error : new Error(String(error)),
193
- duration: Date.now() - startTime,
194
- metadata: {
195
- model: model || 'default',
196
- temperature: 0.7,
197
- promptVersionId,
198
- },
199
- });
200
- throw error;
201
- }
202
- });
203
- }, {
204
- maxRetries: 5,
205
- baseDelay: 2000,
206
- maxDelay: 60000,
207
- operationName: 'chat',
208
- });
209
- }
210
- /**
211
- * Generate chat response with streaming support
212
- * Real-time feedback for better UX (target: < 200ms latency)
213
- *
214
- * NOTE: Cohere SDK streaming implementation - using async iteration pattern
215
- * Falls back to regular chat if streaming is not available
216
- */
217
- async chatStream(query, context, memories, streamHandler) {
218
- const contextText = context
219
- .map((chunk, idx) => `[Chunk ${idx + 1} from ${chunk.filepath}]\n${chunk.content}`)
220
- .join('\n\n---\n\n');
221
- const memoryText = memories && memories.length > 0
222
- ? `\n\nPREVIOUS EXPERIENCES:\n${memories.map(m => `- ${m.description}`).join('\n')}`
223
- : '';
224
- const prompt = `You are a strict coding assistant for enterprise environments.
225
- Use ONLY the provided code context.
226
-
227
- CONTEXT:
228
- ${contextText}${memoryText}
229
-
230
- USER QUERY:
231
- ${query}`;
232
- const model = this.selectModel(context.length, memories?.length || 0, 'chat');
233
- // Register prompt version
234
- const promptVersionId = promptVersioner.registerVersion(prompt, {
235
- model: model || 'default',
236
- temperature: 0.7,
237
- operation: 'chat-stream',
238
- });
239
- const runId = executionTracer.getCurrentRunId();
240
- if (runId) {
241
- promptVersioner.linkRunToVersion(prompt, runId);
242
- }
243
- const startTime = Date.now();
244
- let fullText = '';
245
- try {
246
- // Trace streaming start
247
- executionTracer.trace({
248
- operationType: 'llm_call',
249
- operationName: 'chat-stream',
250
- input: { query, contextCount: context.length, memoryCount: memories?.length || 0 },
251
- metadata: {
252
- model: model || 'default',
253
- temperature: 0.7,
254
- promptVersionId,
255
- streaming: true,
256
- },
257
- });
258
- // Check if Cohere SDK supports streaming
259
- // Cohere SDK v7+ should support streaming via chatStream method or stream option
260
- // Fallback: Use regular chat if streaming not available
261
- if (typeof this.client.chatStream === 'function') {
262
- // Use Cohere's native streaming
263
- const stream = await this.client.chatStream({
264
- message: prompt,
265
- ...(model ? { model } : {}),
266
- temperature: 0.7,
267
- });
268
- // Process stream events (Cohere SDK typically uses async iterator)
269
- for await (const event of stream) {
270
- if (event.eventType === 'text-generation' || event.type === 'text') {
271
- const token = event.text || event.delta || '';
272
- if (token) {
273
- fullText += token;
274
- if (streamHandler.onToken) {
275
- streamHandler.onToken(token);
276
- }
277
- }
278
- }
279
- }
280
- }
281
- else {
282
- // Fallback: Use regular chat and simulate streaming
283
- // Split response into chunks for better UX
284
- const response = await this.client.chat({
285
- message: prompt,
286
- ...(model ? { model } : {}),
287
- temperature: 0.7,
288
- });
289
- fullText = response.text || '';
290
- // Simulate streaming by sending chunks
291
- // Target: < 200ms latency (send chunks every 50-100ms)
292
- const chunkSize = 10; // Characters per chunk
293
- for (let i = 0; i < fullText.length; i += chunkSize) {
294
- const chunk = fullText.substring(i, i + chunkSize);
295
- if (streamHandler.onToken) {
296
- streamHandler.onToken(chunk);
297
- }
298
- // Small delay to simulate streaming (only if text is long enough)
299
- if (fullText.length > chunkSize * 2) {
300
- await new Promise(resolve => setTimeout(resolve, 50));
301
- }
302
- }
303
- }
304
- const duration = Date.now() - startTime;
305
- // Count tokens for trace metadata
306
- const inputTokens = countTokens(prompt);
307
- const outputTokens = countTokens(fullText);
308
- // Update trace
309
- executionTracer.trace({
310
- operationType: 'llm_call',
311
- operationName: 'chat-stream',
312
- output: { responseLength: fullText.length, inputTokens, outputTokens },
313
- duration,
314
- metadata: {
315
- model: model || 'default',
316
- temperature: 0.7,
317
- promptVersionId,
318
- streaming: true,
319
- },
320
- });
321
- // Call completion handler
322
- if (streamHandler.onComplete) {
323
- streamHandler.onComplete(fullText);
324
- }
325
- return fullText;
326
- }
327
- catch (error) {
328
- const duration = Date.now() - startTime;
329
- // Trace error
330
- executionTracer.trace({
331
- operationType: 'llm_call',
332
- operationName: 'chat-stream',
333
- error: error instanceof Error ? error : new Error(String(error)),
334
- duration,
335
- metadata: {
336
- model: model || 'default',
337
- temperature: 0.7,
338
- promptVersionId,
339
- streaming: true,
340
- },
341
- });
342
- // Call error handler
343
- if (streamHandler.onError) {
344
- streamHandler.onError(error instanceof Error ? error : new Error(String(error)));
345
- }
346
- throw error;
347
- }
348
- }
349
- /**
350
- * Select appropriate model based on context size and use case
351
- * Returns model name if we should use a specific model, undefined for default
352
- * Uses model configuration from Command A evaluation results
353
- */
354
- selectModel(contextChunks, memoryCount, useCase = 'default') {
355
- const modelConfig = getModelConfigManager();
356
- // Check if Command models are available from evaluation
357
- if (modelConfig.isCommandModelAvailable()) {
358
- const preferredModel = modelConfig.getPreferredModel(useCase);
359
- if (preferredModel) {
360
- return preferredModel;
361
- }
362
- }
363
- // Use default model for now (will be updated after Command A evaluation)
364
- // Large context or many memories → might need Command A (after evaluation)
365
- if (contextChunks > 20 || memoryCount > 10) {
366
- // After evaluation, this will return the preferred Command model
367
- return undefined; // Use default for now
368
- }
369
- return undefined; // Use default
370
- }
371
- /**
372
- * Embed text as documents (for code chunks, memory storage)
373
- * Uses 'search_document' input type for optimal document embedding
374
- */
375
- async embed(text) {
376
- const texts = Array.isArray(text) ? text : [text];
377
- return await retryWithBackoff(async () => {
378
- return await cohereCircuitBreaker.execute(async () => {
379
- const response = await this.client.embed({
380
- texts,
381
- model: 'embed-english-v3.0',
382
- inputType: 'search_document', // For code chunks/documents
383
- });
384
- const embeddings = response.embeddings;
385
- if (texts.length === 1) {
386
- return embeddings[0];
387
- }
388
- return embeddings;
389
- });
390
- }, {
391
- maxRetries: 5,
392
- baseDelay: 2000,
393
- maxDelay: 60000,
394
- operationName: 'embed',
395
- });
396
- }
397
- /**
398
- * Embed text as a search query (for user queries)
399
- * Uses 'search_query' input type for optimal query-document matching
400
- * This is critical for better search quality!
401
- */
402
- async embedQuery(query) {
403
- return await retryWithBackoff(async () => {
404
- return await cohereCircuitBreaker.execute(async () => {
405
- const response = await this.client.embed({
406
- texts: [query],
407
- model: 'embed-english-v3.0',
408
- inputType: 'search_query', // For user queries - better matching!
409
- });
410
- const embeddings = response.embeddings;
411
- // Handle both array and object response types
412
- if (Array.isArray(embeddings)) {
413
- if (embeddings.length === 0) {
414
- throw new Error('No embedding returned for query');
415
- }
416
- return embeddings[0] || [];
417
- }
418
- else {
419
- // Handle EmbedByTypeResponseEmbeddings type
420
- const embeddingsArray = embeddings.float || [];
421
- if (embeddingsArray.length === 0) {
422
- throw new Error('No embedding returned for query');
423
- }
424
- return embeddingsArray[0] || [];
425
- }
426
- });
427
- }, {
428
- maxRetries: 5,
429
- baseDelay: 2000,
430
- maxDelay: 60000,
431
- operationName: 'embedQuery',
432
- });
433
- }
434
- async generateEdit(fileContent, instruction, filepath) {
435
- // For simplicity and reliability, always request the complete modified file
436
- // This avoids diff parsing issues and is more reliable
437
- const prompt = `You are a code editor. Return the COMPLETE modified file content.
438
-
439
- CRITICAL RULES:
440
- 1. Return ONLY the complete modified file content - no explanations, no markdown, no code blocks
441
- 2. If renaming a function/class/variable, you MUST update ALL references
442
- 3. Maintain exact indentation and formatting from the original
443
- 4. Only modify what's necessary for the instruction
444
- 5. Return the ENTIRE file, not just the changes
445
-
446
- FILE: ${filepath}
447
-
448
- CURRENT CODE:
449
- \`\`\`
450
- ${fileContent}
451
- \`\`\`
452
-
453
- INSTRUCTION: ${instruction}
454
-
455
- Return the COMPLETE modified file content (entire file, not a diff):`;
456
- return await retryWithBackoff(async () => {
457
- return await cohereCircuitBreaker.execute(async () => {
458
- const response = await this.client.chat({
459
- message: prompt,
460
- temperature: 0.3, // Lower for deterministic code generation and editing
461
- });
462
- const result = response.text || '';
463
- return result;
464
- });
465
- }, {
466
- maxRetries: 3,
467
- baseDelay: 2000,
468
- maxDelay: 30000,
469
- operationName: 'generateEdit',
470
- });
471
- }
472
- async generateFileContent(filepath, instruction, requirements = []) {
473
- const requirementsText = requirements.length > 0
474
- ? `\n\nREQUIREMENTS:\n${requirements.map((r, i) => `${i + 1}. ${r}`).join('\n')}`
475
- : '';
476
- // Detect file type from extension
477
- const ext = filepath.split('.').pop()?.toLowerCase() || '';
478
- const languageMap = {
479
- 'ts': 'TypeScript',
480
- 'js': 'JavaScript',
481
- 'tsx': 'TypeScript React',
482
- 'jsx': 'JavaScript React',
483
- 'py': 'Python',
484
- 'java': 'Java',
485
- 'go': 'Go',
486
- 'rs': 'Rust',
487
- 'rb': 'Ruby',
488
- 'php': 'PHP',
489
- 'vue': 'Vue',
490
- 'svelte': 'Svelte',
491
- 'html': 'HTML',
492
- 'css': 'CSS',
493
- 'json': 'JSON',
494
- 'yaml': 'YAML',
495
- 'yml': 'YAML',
496
- 'md': 'Markdown',
497
- 'sh': 'Bash',
498
- 'bash': 'Bash',
499
- };
500
- const language = languageMap[ext] || 'code';
501
- const prompt = `You are a code generator. Create a NEW ${language} file from scratch.
502
-
503
- CRITICAL RULES:
504
- 1. Return ONLY the complete file content - no explanations, no markdown, no code blocks
505
- 2. Follow ${language} best practices and conventions
506
- 3. Include proper imports, exports, and structure
507
- 4. Add appropriate comments for clarity
508
- 5. Ensure the code is production-ready and well-structured
509
-
510
- FILE PATH: ${filepath}
511
- FILE TYPE: ${language}${requirementsText}
512
-
513
- INSTRUCTION: ${instruction}
514
-
515
- Return the COMPLETE file content (entire file, ready to save):`;
516
- return await retryWithBackoff(async () => {
517
- return await cohereCircuitBreaker.execute(async () => {
518
- const response = await this.client.chat({
519
- message: prompt,
520
- temperature: 0.35, // Slightly higher for new file generation (allows some creativity while staying deterministic)
521
- });
522
- let content = response.text || '';
523
- // Clean up common markdown formatting
524
- // Remove code blocks if present
525
- content = content.replace(/^```[\w]*\n?/gm, '');
526
- content = content.replace(/^```$/gm, '');
527
- content = content.trim();
528
- return content;
529
- });
530
- }, {
531
- maxRetries: 3,
532
- baseDelay: 2000,
533
- maxDelay: 30000,
534
- operationName: 'generateFileContent',
535
- });
536
- }
537
- async generateReflection(trajectory, reward, errors) {
538
- const prompt = `You are a self-reflection model. Analyze the following failed trajectory:
539
-
540
- Trajectory:
541
- ${JSON.stringify(trajectory, null, 2)}
542
-
543
- Reward: ${reward}
544
- Errors: ${errors.join('; ')}
545
-
546
- Generate a reflective text that:
547
- 1. Identifies the root cause of failure
548
- 2. Explains what went wrong
549
- 3. Suggests specific improvements for the next attempt
550
- 4. Extracts lessons learned
551
-
552
- Reflection:`;
553
- return await retryWithBackoff(async () => {
554
- return await cohereCircuitBreaker.execute(async () => {
555
- const response = await this.client.chat({
556
- message: prompt,
557
- temperature: 0.5, // Balanced for reflection (analytical but open to insights)
558
- });
559
- const result = response.text || '';
560
- return result;
561
- });
562
- }, {
563
- maxRetries: 3,
564
- baseDelay: 2000,
565
- maxDelay: 30000,
566
- operationName: 'generateReflection',
567
- });
568
- }
569
- /**
570
- * Rerank search results using Cohere Rerank API
571
- * Implements two-stage retrieval: initial recall → rerank precision
572
- *
573
- * Strategy:
574
- * 1. Initial retrieval (vector search) finds candidate documents
575
- * 2. Rerank API scores and reorders for precision
576
- * 3. Returns top N most relevant results
577
- */
578
- async rerank(query, documents, topN = 10) {
579
- if (documents.length === 0) {
580
- return [];
581
- }
582
- // Cohere Rerank API has limits, so we cap at 100 documents
583
- const documentsToRerank = documents.slice(0, 100);
584
- const topNAdjusted = Math.min(topN, documentsToRerank.length);
585
- return await retryWithBackoff(async () => {
586
- return await cohereCircuitBreaker.execute(async () => {
587
- const response = await this.client.rerank({
588
- model: 'rerank-english-v3.0', // Use latest English rerank model
589
- query,
590
- documents: documentsToRerank,
591
- topN: topNAdjusted,
592
- });
593
- // Map Cohere rerank results to our format
594
- return (response.results || []).map((result) => ({
595
- index: result.index,
596
- relevanceScore: result.relevanceScore || 0,
597
- }));
598
- });
599
- }, {
600
- maxRetries: 3,
601
- baseDelay: 2000,
602
- maxDelay: 30000,
603
- operationName: 'rerank',
604
- });
605
- }
606
- }
607
- //# sourceMappingURL=cohere-ai-service.js.map