codehere 0.2.2 → 0.3.0-rc.2

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 +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/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,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