codehere 0.2.2 → 0.3.0-rc.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +88 -68
- package/dist/domain/entities/task.js +4 -4
- package/dist/error-handler.js +4 -9
- package/dist/index.js +253 -1219
- package/dist/infrastructure/config/product-context.js +7 -6
- package/dist/infrastructure/hooks/claude-sdk-hook.js +335 -63
- package/dist/infrastructure/observability/execution-tracer.js +11 -6
- package/dist/infrastructure/orchestration/agent-adapter.js +13 -0
- package/dist/infrastructure/orchestration/agent-installer.js +101 -0
- package/dist/infrastructure/orchestration/agents-config-seed.js +56 -0
- package/dist/infrastructure/orchestration/aider-adapter.js +319 -0
- package/dist/infrastructure/orchestration/artifacts-extractor.js +175 -0
- package/dist/infrastructure/orchestration/claude-code-adapter.js +352 -0
- package/dist/infrastructure/orchestration/codex-adapter.js +310 -0
- package/dist/infrastructure/orchestration/generic-cli-adapter.js +553 -0
- package/dist/infrastructure/orchestration/opencode-adapter.js +275 -0
- package/dist/infrastructure/orchestration/progress-aggregator.js +189 -0
- package/dist/infrastructure/orchestration/readiness.js +106 -0
- package/dist/infrastructure/orchestration/session-manager.js +272 -0
- package/dist/infrastructure/orchestration/session-persistence.js +109 -0
- package/dist/infrastructure/protocols/mcp-helpers.js +10 -30
- package/dist/infrastructure/protocols/mcp-server-impl.js +359 -21
- package/dist/infrastructure/protocols/ui-page.js +1827 -0
- package/dist/infrastructure/security/file-collection.js +115 -0
- package/dist/infrastructure/security/trust-scorer.js +301 -56
- package/dist/infrastructure/storage/task-repository.js +8 -7
- package/dist/monitoring.js +9 -38
- package/dist/presentation/cli/commands/help-command.js +96 -139
- package/dist/presentation/cli/commands/hook-command.js +17 -24
- package/dist/presentation/cli/commands/report-command.js +59 -72
- package/dist/presentation/cli/commands/setup-command.js +4 -4
- package/dist/presentation/cli/commands/status-command.js +321 -30
- package/dist/presentation/cli/commands/trust-command.js +84 -72
- package/dist/presentation/cli/error-display.js +17 -21
- package/dist/ui.js +11 -11
- package/package.json +24 -62
- package/dist/agents/base.js +0 -101
- package/dist/agents/orchestrator-model-driven.js +0 -141
- package/dist/agents/react-orchestrator-agent.js +0 -54
- package/dist/application/agents/execution-agent.js +0 -508
- package/dist/application/agents/multi-agent-orchestrator.js +0 -295
- package/dist/application/agents/planning-agent.js +0 -433
- package/dist/application/agents/validation-agent.js +0 -317
- package/dist/application/architectures/plan-and-act.js +0 -242
- package/dist/application/index.js +0 -12
- package/dist/application/services/agent-factory.js +0 -28
- package/dist/application/services/dependency-container.js +0 -596
- package/dist/application/services/git-context-service.js +0 -83
- package/dist/application/services/intelligent-router.js +0 -934
- package/dist/application/services/tool-executor-service.js +0 -94
- package/dist/application/use-cases/ask-question-use-case.js +0 -338
- package/dist/application/use-cases/edit-file-use-case.js +0 -830
- package/dist/application/use-cases/explain-file-use-case.js +0 -50
- package/dist/application/use-cases/index-codebase-use-case.js +0 -113
- package/dist/application/use-cases/planning-use-case.js +0 -276
- package/dist/application/use-cases/react-orchestration-use-case.js +0 -329
- package/dist/application/use-cases/reflexion-use-case.js +0 -30
- package/dist/application/workflows/deterministic-workflows.js +0 -189
- package/dist/ast-parser.js +0 -331
- package/dist/cache.js +0 -180
- package/dist/chat.js +0 -251
- package/dist/code-analysis.js +0 -327
- package/dist/context.js +0 -187
- package/dist/docs.js +0 -146
- package/dist/domain/entities/code-chunk.js +0 -6
- package/dist/domain/entities/decision.js +0 -9
- package/dist/domain/entities/edit.js +0 -6
- package/dist/domain/entities/knowledge-node.js +0 -9
- package/dist/domain/entities/knowledge-preservation.js +0 -10
- package/dist/domain/entities/memory.js +0 -6
- package/dist/domain/entities/pattern.js +0 -7
- package/dist/domain/entities/plan.js +0 -6
- package/dist/domain/entities/query.js +0 -6
- package/dist/domain/errors/embeddings-not-found-error.js +0 -13
- package/dist/domain/index.js +0 -19
- package/dist/domain/interfaces/ai-service.interface.js +0 -6
- package/dist/domain/interfaces/code-analyzer.interface.js +0 -6
- package/dist/domain/interfaces/decision-repository.interface.js +0 -9
- package/dist/domain/interfaces/embedding-repository.interface.js +0 -6
- package/dist/domain/interfaces/knowledge-graph-repository.interface.js +0 -9
- package/dist/domain/interfaces/knowledge-preservation-repository.interface.js +0 -8
- package/dist/domain/interfaces/memory-repository.interface.js +0 -6
- package/dist/domain/interfaces/pattern-repository.interface.js +0 -6
- package/dist/domain/interfaces/verification-service.interface.js +0 -6
- package/dist/domain/services/cross-team-pattern-sharing.js +0 -125
- package/dist/domain/services/decision-recorder.js +0 -223
- package/dist/domain/services/decision-retriever.js +0 -133
- package/dist/domain/services/environment-mode-manager.js +0 -22
- package/dist/domain/services/graded-memory-activation.js +0 -69
- package/dist/domain/services/knowledge-access.js +0 -132
- package/dist/domain/services/knowledge-extractor.js +0 -247
- package/dist/domain/services/knowledge-graph-builder.js +0 -268
- package/dist/domain/services/knowledge-graph-query.js +0 -187
- package/dist/domain/services/memory-retriever.js +0 -82
- package/dist/domain/services/memory-synthesizer.js +0 -91
- package/dist/domain/services/pattern-extractor.js +0 -442
- package/dist/domain/services/query-intent-classifier.js +0 -140
- package/dist/domain/services/react-loop.js +0 -186
- package/dist/domain/services/risk-tier-detector.js +0 -78
- package/dist/edit.js +0 -319
- package/dist/embed.js +0 -459
- package/dist/formatter.js +0 -168
- package/dist/git.js +0 -198
- package/dist/infrastructure/ai/cohere-ai-service.js +0 -607
- package/dist/infrastructure/ai/command-r-evaluation.js +0 -206
- package/dist/infrastructure/ai/model-config.js +0 -84
- package/dist/infrastructure/ai/provider-ai-service.js +0 -477
- package/dist/infrastructure/cache/embedding-cache.js +0 -175
- package/dist/infrastructure/cache/query-result-cache.js +0 -66
- package/dist/infrastructure/cache/response-cache.js +0 -48
- package/dist/infrastructure/cache/security-scan-cache.js +0 -47
- package/dist/infrastructure/chunking/ast-code-chunker.js +0 -19
- package/dist/infrastructure/chunking/code-aware-chunker.js +0 -397
- package/dist/infrastructure/context/context-compressor.js +0 -329
- package/dist/infrastructure/context/conversation-context.js +0 -128
- package/dist/infrastructure/context/session-manager.js +0 -94
- package/dist/infrastructure/cost/cost-tracker.js +0 -360
- package/dist/infrastructure/file-scanner/file-scanner.js +0 -106
- package/dist/infrastructure/governance/nist-ai-rmf.js +0 -292
- package/dist/infrastructure/governance/policy-as-code.js +0 -258
- package/dist/infrastructure/governance/prompt-to-code-lineage.js +0 -239
- package/dist/infrastructure/index.js +0 -7
- package/dist/infrastructure/observability/prompt-versioner.js +0 -145
- package/dist/infrastructure/protocols/a2a-metadata.js +0 -137
- package/dist/infrastructure/protocols/a2a-protocol.js +0 -314
- package/dist/infrastructure/protocols/mcp-oauth.js +0 -184
- package/dist/infrastructure/protocols/mcp-server.js +0 -333
- package/dist/infrastructure/protocols/streaming-handler.js +0 -103
- package/dist/infrastructure/providers/cohere-provider.js +0 -444
- package/dist/infrastructure/providers/fake-provider.js +0 -130
- package/dist/infrastructure/providers/local-llm-provider.js +0 -330
- package/dist/infrastructure/providers/model-config.types.js +0 -9
- package/dist/infrastructure/providers/model-provider.interface.js +0 -8
- package/dist/infrastructure/providers/openai-provider.js +0 -413
- package/dist/infrastructure/providers/openrouter-provider.js +0 -399
- package/dist/infrastructure/providers/operation-provider-resolver.js +0 -105
- package/dist/infrastructure/providers/provider-config-loader.js +0 -120
- package/dist/infrastructure/providers/provider-registry.js +0 -88
- package/dist/infrastructure/safety/pattern-detector.js +0 -133
- package/dist/infrastructure/security/ai-sast-scanner.js +0 -290
- package/dist/infrastructure/security/docker-sandbox.js +0 -178
- package/dist/infrastructure/security/enhanced-security-gate.js +0 -151
- package/dist/infrastructure/security/license-scanner.js +0 -167
- package/dist/infrastructure/security/provider-bias-detector.js +0 -164
- package/dist/infrastructure/security/sandbox-executor.js +0 -64
- package/dist/infrastructure/serialization/toon-serializer.js +0 -119
- package/dist/infrastructure/storage/memory-stream-service.js +0 -204
- package/dist/infrastructure/storage/plan-repository.js +0 -96
- package/dist/infrastructure/storage/sqlite-decision-repository.js +0 -232
- package/dist/infrastructure/storage/sqlite-embedding-repository.js +0 -311
- package/dist/infrastructure/storage/sqlite-knowledge-graph-repository.js +0 -417
- package/dist/infrastructure/storage/sqlite-knowledge-preservation-repository.js +0 -230
- package/dist/infrastructure/storage/sqlite-memory-repository.js +0 -229
- package/dist/infrastructure/storage/sqlite-pattern-repository.js +0 -249
- package/dist/infrastructure/storage/task-helpers.js +0 -197
- package/dist/infrastructure/telemetry/telemetry-service.js +0 -167
- package/dist/infrastructure/ux/appropriate-friction.js +0 -213
- package/dist/infrastructure/ux/bi-directional-learning.js +0 -337
- package/dist/infrastructure/ux/capability-boundaries.js +0 -42
- package/dist/infrastructure/ux/comprehensive-formatter.js +0 -117
- package/dist/infrastructure/ux/contextual-feature-discovery.js +0 -10
- package/dist/infrastructure/ux/expectation-management.js +0 -327
- package/dist/infrastructure/ux/feature-discovery.js +0 -14
- package/dist/infrastructure/ux/feedback-prompt.js +0 -45
- package/dist/infrastructure/ux/hitl-validation.js +0 -297
- package/dist/infrastructure/ux/progress-indicator.js +0 -116
- package/dist/infrastructure/ux/progressive-disclosure.js +0 -236
- package/dist/infrastructure/ux/review-checkpoint.js +0 -72
- package/dist/infrastructure/ux/staged-feature-intro.js +0 -24
- package/dist/infrastructure/ux/stream-markdown.js +0 -151
- package/dist/infrastructure/ux/syntax-highlighter.js +0 -91
- package/dist/infrastructure/ux/team-standards.js +0 -196
- package/dist/infrastructure/ux/transparency.js +0 -71
- package/dist/infrastructure/validation/agent-feedback.js +0 -55
- package/dist/infrastructure/validation/agent-validation-helper.js +0 -137
- package/dist/infrastructure/validation/review-handler.js +0 -40
- package/dist/infrastructure/validation/summary-aggregator.js +0 -70
- package/dist/infrastructure/validation/summary-extractor.js +0 -45
- package/dist/infrastructure/validation/trace-summary.js +0 -52
- package/dist/infrastructure/verification/verification-service.js +0 -47
- package/dist/infrastructure/xai/attention-visualizer.js +0 -172
- package/dist/infrastructure/xai/cot-visualizer.js +0 -283
- package/dist/infrastructure/xai/decision-tree-log.js +0 -212
- package/dist/infrastructure/xai/interactive-xai.js +0 -260
- package/dist/infrastructure/xai/uncertainty-quantifier.js +0 -198
- package/dist/intelligent-retrieval.js +0 -272
- package/dist/intent/classifier.js +0 -2
- package/dist/intent/context.js +0 -2
- package/dist/iterative-refinement.js +0 -189
- package/dist/learning.js +0 -232
- package/dist/log.js +0 -31
- package/dist/migrate.js +0 -133
- package/dist/parallel-processor.js +0 -534
- package/dist/planner.js +0 -198
- package/dist/policy.js +0 -26
- package/dist/presentation/cli/commands/ask-command.js +0 -314
- package/dist/presentation/cli/commands/cost-command.js +0 -191
- package/dist/presentation/cli/commands/decision-command.js +0 -207
- package/dist/presentation/cli/commands/docs-command.js +0 -25
- package/dist/presentation/cli/commands/fix-command.js +0 -53
- package/dist/presentation/cli/commands/knowledge-command.js +0 -129
- package/dist/presentation/cli/commands/learning-dashboard-command.js +0 -183
- package/dist/presentation/cli/commands/models-command.js +0 -194
- package/dist/presentation/cli/commands/orchestrate-command.js +0 -207
- package/dist/presentation/cli/commands/plan-command.js +0 -246
- package/dist/presentation/cli/commands/product-command.js +0 -199
- package/dist/presentation/cli/commands/react-command.js +0 -181
- package/dist/presentation/cli/commands/review-command.js +0 -154
- package/dist/presentation/cli/commands/run-command.js +0 -188
- package/dist/presentation/cli/commands/smart-command.js +0 -395
- package/dist/presentation/cli/commands/suggest-command.js +0 -138
- package/dist/presentation/cli/commands/trace-command.js +0 -129
- package/dist/presentation/cli/commands/undo-command.js +0 -150
- package/dist/query-optimizer.js +0 -205
- package/dist/refactor.js +0 -116
- package/dist/review.js +0 -206
- package/dist/search.js +0 -163
- package/dist/session.js +0 -704
- package/dist/task-verification.js +0 -336
- package/dist/testgen.js +0 -166
- package/dist/token-optimizer.js +0 -277
- package/dist/tools/bash.js +0 -213
- package/dist/tools/edit.js +0 -235
- package/dist/tools/executor.js +0 -153
- package/dist/tools/git-tool.js +0 -292
- package/dist/tools/parser.js +0 -158
- package/dist/tools/registry.js +0 -302
- package/dist/tools/search.js +0 -100
- package/dist/types.js +0 -2
- package/dist/utils/check-api-status.js +0 -100
- package/dist/utils/diff-parser.js +0 -162
- package/dist/verification/backup.js +0 -259
- package/dist/verification/compiler.js +0 -264
- package/dist/verification/index.js +0 -273
- package/dist/verification/test-runner.js +0 -379
package/dist/chat.js
DELETED
|
@@ -1,251 +0,0 @@
|
|
|
1
|
-
import { config } from 'dotenv';
|
|
2
|
-
import { join, dirname } from 'path';
|
|
3
|
-
import { fileURLToPath } from 'url';
|
|
4
|
-
import { retryWithBackoff, handleError } from './error-handler.js';
|
|
5
|
-
import { optimizeContext } from './token-optimizer.js';
|
|
6
|
-
import { optimizeQuery } from './query-optimizer.js';
|
|
7
|
-
// Load .env from agent directory
|
|
8
|
-
try {
|
|
9
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
10
|
-
const __dirname = dirname(__filename);
|
|
11
|
-
const agentDir = join(__dirname, '..');
|
|
12
|
-
config({ path: join(agentDir, '.env') });
|
|
13
|
-
}
|
|
14
|
-
catch {
|
|
15
|
-
// Fallback
|
|
16
|
-
}
|
|
17
|
-
config(); // Also try current directory
|
|
18
|
-
async function chatCompletion(prompt) {
|
|
19
|
-
// Route to available provider
|
|
20
|
-
if (process.env.ANTHROPIC_API_KEY) {
|
|
21
|
-
const response = await fetch('https://api.anthropic.com/v1/messages', {
|
|
22
|
-
method: 'POST',
|
|
23
|
-
headers: {
|
|
24
|
-
'x-api-key': process.env.ANTHROPIC_API_KEY,
|
|
25
|
-
'anthropic-version': '2023-06-01',
|
|
26
|
-
'content-type': 'application/json',
|
|
27
|
-
},
|
|
28
|
-
body: JSON.stringify({
|
|
29
|
-
model: 'claude-sonnet-4-20250514',
|
|
30
|
-
max_tokens: 4096,
|
|
31
|
-
messages: [{ role: 'user', content: prompt }],
|
|
32
|
-
}),
|
|
33
|
-
});
|
|
34
|
-
if (!response.ok)
|
|
35
|
-
throw new Error(`Anthropic API error: ${response.status}`);
|
|
36
|
-
const data = await response.json();
|
|
37
|
-
return data.content?.[0]?.text || 'No response generated';
|
|
38
|
-
}
|
|
39
|
-
if (process.env.OPENAI_API_KEY) {
|
|
40
|
-
const response = await fetch('https://api.openai.com/v1/chat/completions', {
|
|
41
|
-
method: 'POST',
|
|
42
|
-
headers: {
|
|
43
|
-
'Authorization': `Bearer ${process.env.OPENAI_API_KEY}`,
|
|
44
|
-
'Content-Type': 'application/json',
|
|
45
|
-
},
|
|
46
|
-
body: JSON.stringify({
|
|
47
|
-
model: 'gpt-4o-mini',
|
|
48
|
-
messages: [{ role: 'user', content: prompt }],
|
|
49
|
-
max_tokens: 4096,
|
|
50
|
-
}),
|
|
51
|
-
});
|
|
52
|
-
if (!response.ok)
|
|
53
|
-
throw new Error(`OpenAI API error: ${response.status}`);
|
|
54
|
-
const data = await response.json();
|
|
55
|
-
return data.choices?.[0]?.message?.content || 'No response generated';
|
|
56
|
-
}
|
|
57
|
-
if (process.env.COHERE_API_KEY) {
|
|
58
|
-
const { CohereClient } = require('cohere-ai');
|
|
59
|
-
const cohere = new CohereClient({ token: process.env.COHERE_API_KEY });
|
|
60
|
-
const response = await cohere.chat({ message: prompt });
|
|
61
|
-
return response.text || 'No response generated';
|
|
62
|
-
}
|
|
63
|
-
throw new Error('No API key found. Set ANTHROPIC_API_KEY, OPENAI_API_KEY, or COHERE_API_KEY.');
|
|
64
|
-
}
|
|
65
|
-
/**
|
|
66
|
-
* Streaming chat completion — yields tokens as they arrive
|
|
67
|
-
*/
|
|
68
|
-
async function chatCompletionStream(prompt, onToken) {
|
|
69
|
-
if (process.env.ANTHROPIC_API_KEY) {
|
|
70
|
-
const response = await fetch('https://api.anthropic.com/v1/messages', {
|
|
71
|
-
method: 'POST',
|
|
72
|
-
headers: {
|
|
73
|
-
'x-api-key': process.env.ANTHROPIC_API_KEY,
|
|
74
|
-
'anthropic-version': '2023-06-01',
|
|
75
|
-
'content-type': 'application/json',
|
|
76
|
-
},
|
|
77
|
-
body: JSON.stringify({
|
|
78
|
-
model: 'claude-sonnet-4-20250514',
|
|
79
|
-
max_tokens: 4096,
|
|
80
|
-
stream: true,
|
|
81
|
-
messages: [{ role: 'user', content: prompt }],
|
|
82
|
-
}),
|
|
83
|
-
});
|
|
84
|
-
if (!response.ok)
|
|
85
|
-
throw new Error(`Anthropic API error: ${response.status}`);
|
|
86
|
-
let fullText = '';
|
|
87
|
-
const reader = response.body?.getReader();
|
|
88
|
-
if (!reader)
|
|
89
|
-
throw new Error('No response body');
|
|
90
|
-
const decoder = new TextDecoder();
|
|
91
|
-
let buffer = '';
|
|
92
|
-
while (true) {
|
|
93
|
-
const { done, value } = await reader.read();
|
|
94
|
-
if (done)
|
|
95
|
-
break;
|
|
96
|
-
buffer += decoder.decode(value, { stream: true });
|
|
97
|
-
const lines = buffer.split('\n');
|
|
98
|
-
buffer = lines.pop() || '';
|
|
99
|
-
for (const line of lines) {
|
|
100
|
-
if (!line.startsWith('data: '))
|
|
101
|
-
continue;
|
|
102
|
-
const data = line.slice(6);
|
|
103
|
-
if (data === '[DONE]')
|
|
104
|
-
continue;
|
|
105
|
-
try {
|
|
106
|
-
const event = JSON.parse(data);
|
|
107
|
-
if (event.type === 'content_block_delta' && event.delta?.text) {
|
|
108
|
-
const token = event.delta.text;
|
|
109
|
-
fullText += token;
|
|
110
|
-
onToken(token);
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
catch {
|
|
114
|
-
// Skip malformed JSON
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
return fullText || 'No response generated';
|
|
119
|
-
}
|
|
120
|
-
// Fallback: non-streaming for other providers
|
|
121
|
-
const result = await chatCompletion(prompt);
|
|
122
|
-
onToken(result);
|
|
123
|
-
return result;
|
|
124
|
-
}
|
|
125
|
-
export async function chatWithContext(query, context) {
|
|
126
|
-
// Optimize query to understand intent and select strategy
|
|
127
|
-
const { optimizedQuery, strategy } = optimizeQuery(query);
|
|
128
|
-
// Optimize context to reduce tokens
|
|
129
|
-
const optimized = optimizeContext(context, optimizedQuery, strategy.maxTokens, strategy.contextStrategy);
|
|
130
|
-
// Use optimized chunks
|
|
131
|
-
const optimizedChunks = optimized.chunks;
|
|
132
|
-
const contextText = optimizedChunks
|
|
133
|
-
.map((chunk, idx) => `[Chunk ${idx + 1} from ${chunk.filepath}]\n${chunk.content}`)
|
|
134
|
-
.join('\n\n---\n\n');
|
|
135
|
-
const prompt = `You are a strict coding assistant for enterprise environments.
|
|
136
|
-
Use ONLY the provided code context.
|
|
137
|
-
|
|
138
|
-
CONTEXT:
|
|
139
|
-
|
|
140
|
-
${contextText}
|
|
141
|
-
|
|
142
|
-
USER QUERY:
|
|
143
|
-
|
|
144
|
-
${optimizedQuery}`;
|
|
145
|
-
return await retryWithBackoff(async () => {
|
|
146
|
-
return await chatCompletion(prompt);
|
|
147
|
-
}, {
|
|
148
|
-
maxRetries: 5,
|
|
149
|
-
baseDelay: 2000,
|
|
150
|
-
maxDelay: 60000,
|
|
151
|
-
operationName: 'chatWithContext',
|
|
152
|
-
onRetry: (attempt, error) => {
|
|
153
|
-
console.warn(`Retry attempt ${attempt} for chatWithContext: ${error instanceof Error ? error.message : String(error)}`);
|
|
154
|
-
},
|
|
155
|
-
}).catch(error => {
|
|
156
|
-
handleError(error, {
|
|
157
|
-
operation: 'chatWithContext',
|
|
158
|
-
metadata: {
|
|
159
|
-
query: optimizedQuery,
|
|
160
|
-
contextCount: optimizedChunks.length,
|
|
161
|
-
originalContextCount: context.length,
|
|
162
|
-
tokenReduction: `${optimized.reductionPercent.toFixed(1)}%`,
|
|
163
|
-
},
|
|
164
|
-
});
|
|
165
|
-
});
|
|
166
|
-
}
|
|
167
|
-
/**
|
|
168
|
-
* Chat with context — streaming version
|
|
169
|
-
* Calls onToken for each token as it arrives from the LLM
|
|
170
|
-
*/
|
|
171
|
-
export async function chatWithContextStream(query, context, onToken) {
|
|
172
|
-
const { optimizedQuery, strategy } = optimizeQuery(query);
|
|
173
|
-
const optimized = optimizeContext(context, optimizedQuery, strategy.maxTokens, strategy.contextStrategy);
|
|
174
|
-
const optimizedChunks = optimized.chunks;
|
|
175
|
-
const contextText = optimizedChunks
|
|
176
|
-
.map((chunk, idx) => `[Chunk ${idx + 1} from ${chunk.filepath}]\n${chunk.content}`)
|
|
177
|
-
.join('\n\n---\n\n');
|
|
178
|
-
const prompt = `You are a strict coding assistant for enterprise environments.
|
|
179
|
-
Use ONLY the provided code context.
|
|
180
|
-
|
|
181
|
-
CONTEXT:
|
|
182
|
-
|
|
183
|
-
${contextText}
|
|
184
|
-
|
|
185
|
-
USER QUERY:
|
|
186
|
-
|
|
187
|
-
${optimizedQuery}`;
|
|
188
|
-
return chatCompletionStream(prompt, onToken);
|
|
189
|
-
}
|
|
190
|
-
export async function generateDiff(fileContent, instruction, filepath) {
|
|
191
|
-
const prompt = `You are a code editor. Generate ONLY a unified diff patch that applies cleanly to the file.
|
|
192
|
-
Do not include any explanation, comments, or markdown formatting.
|
|
193
|
-
Return ONLY the raw unified diff starting with "---" and "+++".
|
|
194
|
-
|
|
195
|
-
CRITICAL RULES:
|
|
196
|
-
1. If renaming a function/class/variable, you MUST update ALL references including:
|
|
197
|
-
- module.exports statements
|
|
198
|
-
- export statements
|
|
199
|
-
- Import statements in other files (if this is an exported item)
|
|
200
|
-
- All usages within the file
|
|
201
|
-
2. NEVER create duplicate module.exports or export statements
|
|
202
|
-
3. If a function is exported, update the export when renaming
|
|
203
|
-
4. Ensure the diff is complete and correct
|
|
204
|
-
|
|
205
|
-
File path: ${filepath}
|
|
206
|
-
|
|
207
|
-
Current file content:
|
|
208
|
-
\`\`\`
|
|
209
|
-
${fileContent}
|
|
210
|
-
\`\`\`
|
|
211
|
-
|
|
212
|
-
Instruction: ${instruction}
|
|
213
|
-
|
|
214
|
-
Return the unified diff patch:`;
|
|
215
|
-
return await retryWithBackoff(async () => {
|
|
216
|
-
const responseText = await chatCompletion(prompt);
|
|
217
|
-
return (() => {
|
|
218
|
-
let diffText = responseText;
|
|
219
|
-
// Extract diff if wrapped in markdown code blocks
|
|
220
|
-
const diffMatch = diffText.match(/```(?:diff)?\n([\s\S]*?)```/);
|
|
221
|
-
if (diffMatch) {
|
|
222
|
-
diffText = diffMatch[1];
|
|
223
|
-
}
|
|
224
|
-
// Ensure it starts with --- or +++
|
|
225
|
-
if (!diffText.trim().startsWith('---') && !diffText.trim().startsWith('+++')) {
|
|
226
|
-
// Try to find the diff in the response
|
|
227
|
-
const lines = diffText.split('\n');
|
|
228
|
-
const diffStart = lines.findIndex((line) => line.startsWith('---') || line.startsWith('+++'));
|
|
229
|
-
if (diffStart >= 0) {
|
|
230
|
-
diffText = lines.slice(diffStart).join('\n');
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
return diffText.trim();
|
|
234
|
-
})();
|
|
235
|
-
}, {
|
|
236
|
-
maxRetries: 5,
|
|
237
|
-
baseDelay: 2000,
|
|
238
|
-
maxDelay: 60000,
|
|
239
|
-
operationName: 'generateDiff',
|
|
240
|
-
onRetry: (attempt, error) => {
|
|
241
|
-
console.warn(`Retry attempt ${attempt} for generateDiff: ${error instanceof Error ? error.message : String(error)}`);
|
|
242
|
-
},
|
|
243
|
-
}).catch(error => {
|
|
244
|
-
handleError(error, {
|
|
245
|
-
operation: 'generateDiff',
|
|
246
|
-
filepath,
|
|
247
|
-
metadata: { instruction, fileLength: fileContent.length },
|
|
248
|
-
});
|
|
249
|
-
});
|
|
250
|
-
}
|
|
251
|
-
//# sourceMappingURL=chat.js.map
|
package/dist/code-analysis.js
DELETED
|
@@ -1,327 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Code Analysis Engine
|
|
3
|
-
* Call graph, dependency graph, symbol resolution, import resolution
|
|
4
|
-
*/
|
|
5
|
-
import { parseFile, buildCallGraph, findCallers, findCallees } from './ast-parser.js';
|
|
6
|
-
import { readFileSync, existsSync, readdirSync } from 'fs';
|
|
7
|
-
import { join, dirname, extname, resolve } from 'path';
|
|
8
|
-
/**
|
|
9
|
-
* Analyze entire codebase
|
|
10
|
-
*/
|
|
11
|
-
export async function analyzeCodebase(baseDir, entryFiles) {
|
|
12
|
-
const files = new Map();
|
|
13
|
-
const dependencyGraph = new Map();
|
|
14
|
-
const callGraph = new Map();
|
|
15
|
-
const symbols = new Map();
|
|
16
|
-
// Find all TypeScript/JavaScript files
|
|
17
|
-
const codeFiles = findCodeFiles(baseDir);
|
|
18
|
-
// Parse all files
|
|
19
|
-
for (const filepath of codeFiles) {
|
|
20
|
-
const analysis = parseFile(filepath);
|
|
21
|
-
if (analysis) {
|
|
22
|
-
files.set(filepath, analysis);
|
|
23
|
-
// Index symbols
|
|
24
|
-
for (const symbol of analysis.symbols) {
|
|
25
|
-
symbols.set(symbol.name, {
|
|
26
|
-
filepath,
|
|
27
|
-
line: symbol.line,
|
|
28
|
-
kind: symbol.kind,
|
|
29
|
-
});
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
// Build dependency graph
|
|
34
|
-
for (const [filepath, analysis] of files.entries()) {
|
|
35
|
-
const resolvedDeps = analysis.imports
|
|
36
|
-
.map(imp => resolveImport(imp, filepath, baseDir, files))
|
|
37
|
-
.filter((dep) => dep !== null);
|
|
38
|
-
const dependents = Array.from(files.entries())
|
|
39
|
-
.filter(([_, a]) => a.imports.some(imp => resolveImport(imp, filepath, baseDir, files) === filepath))
|
|
40
|
-
.map(([fp]) => fp);
|
|
41
|
-
dependencyGraph.set(filepath, {
|
|
42
|
-
filepath,
|
|
43
|
-
dependencies: resolvedDeps,
|
|
44
|
-
dependents,
|
|
45
|
-
depth: 0, // Will be calculated
|
|
46
|
-
});
|
|
47
|
-
}
|
|
48
|
-
// Calculate dependency depths
|
|
49
|
-
const entryPoints = entryFiles || findEntryPoints(files, dependencyGraph);
|
|
50
|
-
calculateDepths(dependencyGraph, entryPoints);
|
|
51
|
-
// Build call graph
|
|
52
|
-
const astCallGraph = buildCallGraph(Array.from(files.values()));
|
|
53
|
-
for (const [symbolName, calls] of astCallGraph.entries()) {
|
|
54
|
-
const symbol = symbols.get(symbolName);
|
|
55
|
-
if (!symbol)
|
|
56
|
-
continue;
|
|
57
|
-
const calledBy = findCallers(symbolName, astCallGraph);
|
|
58
|
-
const callees = findCallees(symbolName, astCallGraph);
|
|
59
|
-
callGraph.set(symbolName, {
|
|
60
|
-
symbol: symbolName,
|
|
61
|
-
filepath: symbol.filepath,
|
|
62
|
-
calls: callees,
|
|
63
|
-
calledBy,
|
|
64
|
-
depth: 0, // Will be calculated
|
|
65
|
-
});
|
|
66
|
-
}
|
|
67
|
-
// Calculate call depths
|
|
68
|
-
calculateCallDepths(callGraph, entryPoints, symbols);
|
|
69
|
-
return {
|
|
70
|
-
files,
|
|
71
|
-
dependencyGraph,
|
|
72
|
-
callGraph,
|
|
73
|
-
entryPoints,
|
|
74
|
-
symbols,
|
|
75
|
-
};
|
|
76
|
-
}
|
|
77
|
-
/**
|
|
78
|
-
* Find all code files in directory
|
|
79
|
-
*/
|
|
80
|
-
function findCodeFiles(dir) {
|
|
81
|
-
const files = [];
|
|
82
|
-
try {
|
|
83
|
-
const entries = readdirSync(dir, { withFileTypes: true });
|
|
84
|
-
for (const entry of entries) {
|
|
85
|
-
const fullPath = join(dir, entry.name);
|
|
86
|
-
// Skip node_modules, .git, etc.
|
|
87
|
-
if (entry.name.startsWith('.') || entry.name === 'node_modules') {
|
|
88
|
-
continue;
|
|
89
|
-
}
|
|
90
|
-
if (entry.isDirectory()) {
|
|
91
|
-
files.push(...findCodeFiles(fullPath));
|
|
92
|
-
}
|
|
93
|
-
else if (entry.isFile()) {
|
|
94
|
-
const ext = extname(entry.name).toLowerCase();
|
|
95
|
-
if (['.ts', '.tsx', '.js', '.jsx'].includes(ext)) {
|
|
96
|
-
files.push(fullPath);
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
catch {
|
|
102
|
-
// Skip directories we can't read
|
|
103
|
-
}
|
|
104
|
-
return files;
|
|
105
|
-
}
|
|
106
|
-
/**
|
|
107
|
-
* Resolve import to actual file path
|
|
108
|
-
* FIXED: Better resolution for node_modules, aliases, and relative paths
|
|
109
|
-
*/
|
|
110
|
-
function resolveImport(importPath, fromFile, baseDir, files) {
|
|
111
|
-
// Handle node_modules imports (check package.json for resolution)
|
|
112
|
-
if (!importPath.startsWith('.') && !importPath.startsWith('/')) {
|
|
113
|
-
// Try to resolve from node_modules
|
|
114
|
-
const nodeModulesPath = join(baseDir, 'node_modules', importPath);
|
|
115
|
-
const extensions = ['.ts', '.tsx', '.js', '.jsx', ''];
|
|
116
|
-
for (const ext of extensions) {
|
|
117
|
-
const withExt = nodeModulesPath + ext;
|
|
118
|
-
if (existsSync(withExt)) {
|
|
119
|
-
return withExt;
|
|
120
|
-
}
|
|
121
|
-
// Try package.json main field
|
|
122
|
-
const packageJsonPath = join(nodeModulesPath, 'package.json');
|
|
123
|
-
if (existsSync(packageJsonPath)) {
|
|
124
|
-
try {
|
|
125
|
-
const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));
|
|
126
|
-
const mainFile = packageJson.main || packageJson.module || 'index.js';
|
|
127
|
-
const mainPath = join(nodeModulesPath, mainFile);
|
|
128
|
-
if (existsSync(mainPath)) {
|
|
129
|
-
return mainPath;
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
catch {
|
|
133
|
-
// Skip invalid package.json
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
// Try index files
|
|
137
|
-
const indexFile = join(nodeModulesPath, `index${ext}`);
|
|
138
|
-
if (existsSync(indexFile)) {
|
|
139
|
-
return indexFile;
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
return null; // External dependency, not in our codebase
|
|
143
|
-
}
|
|
144
|
-
const fromDir = dirname(fromFile);
|
|
145
|
-
let resolved;
|
|
146
|
-
try {
|
|
147
|
-
resolved = resolve(fromDir, importPath);
|
|
148
|
-
}
|
|
149
|
-
catch {
|
|
150
|
-
return null;
|
|
151
|
-
}
|
|
152
|
-
// Try with extensions
|
|
153
|
-
const extensions = ['.ts', '.tsx', '.js', '.jsx', ''];
|
|
154
|
-
for (const ext of extensions) {
|
|
155
|
-
const withExt = resolved + ext;
|
|
156
|
-
if (files.has(withExt) || existsSync(withExt)) {
|
|
157
|
-
return withExt;
|
|
158
|
-
}
|
|
159
|
-
// Try index files
|
|
160
|
-
const indexFile = join(resolved, `index${ext}`);
|
|
161
|
-
if (files.has(indexFile) || existsSync(indexFile)) {
|
|
162
|
-
return indexFile;
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
// Try resolving from baseDir (for absolute imports from project root)
|
|
166
|
-
try {
|
|
167
|
-
const fromBase = resolve(baseDir, importPath);
|
|
168
|
-
for (const ext of extensions) {
|
|
169
|
-
const withExt = fromBase + ext;
|
|
170
|
-
if (files.has(withExt) || existsSync(withExt)) {
|
|
171
|
-
return withExt;
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
catch {
|
|
176
|
-
// Ignore
|
|
177
|
-
}
|
|
178
|
-
return null;
|
|
179
|
-
}
|
|
180
|
-
/**
|
|
181
|
-
* Find entry points (main files, index files)
|
|
182
|
-
*/
|
|
183
|
-
function findEntryPoints(files, dependencyGraph) {
|
|
184
|
-
const entryPoints = [];
|
|
185
|
-
// Files with no dependencies (or only external dependencies)
|
|
186
|
-
for (const [filepath, graph] of dependencyGraph.entries()) {
|
|
187
|
-
if (graph.dependencies.length === 0) {
|
|
188
|
-
entryPoints.push(filepath);
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
// Index files
|
|
192
|
-
for (const filepath of files.keys()) {
|
|
193
|
-
if (filepath.endsWith('index.ts') || filepath.endsWith('index.js') ||
|
|
194
|
-
filepath.endsWith('main.ts') || filepath.endsWith('main.js') ||
|
|
195
|
-
filepath.endsWith('app.ts') || filepath.endsWith('app.js')) {
|
|
196
|
-
if (!entryPoints.includes(filepath)) {
|
|
197
|
-
entryPoints.push(filepath);
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
return entryPoints.length > 0 ? entryPoints : Array.from(files.keys()).slice(0, 1);
|
|
202
|
-
}
|
|
203
|
-
/**
|
|
204
|
-
* Calculate dependency depths from entry points
|
|
205
|
-
*/
|
|
206
|
-
function calculateDepths(dependencyGraph, entryPoints) {
|
|
207
|
-
const visited = new Set();
|
|
208
|
-
const queue = entryPoints.map(ep => ({ filepath: ep, depth: 0 }));
|
|
209
|
-
while (queue.length > 0) {
|
|
210
|
-
const { filepath, depth } = queue.shift();
|
|
211
|
-
if (visited.has(filepath))
|
|
212
|
-
continue;
|
|
213
|
-
visited.add(filepath);
|
|
214
|
-
const graph = dependencyGraph.get(filepath);
|
|
215
|
-
if (!graph)
|
|
216
|
-
continue;
|
|
217
|
-
graph.depth = depth;
|
|
218
|
-
// Add dependents to queue
|
|
219
|
-
for (const dependent of graph.dependents) {
|
|
220
|
-
if (!visited.has(dependent)) {
|
|
221
|
-
queue.push({ filepath: dependent, depth: depth + 1 });
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
/**
|
|
227
|
-
* Calculate call depths from entry points
|
|
228
|
-
*/
|
|
229
|
-
function calculateCallDepths(callGraph, entryPoints, symbols) {
|
|
230
|
-
// Find entry symbols (exported from entry files)
|
|
231
|
-
const entrySymbols = [];
|
|
232
|
-
for (const entryFile of entryPoints) {
|
|
233
|
-
for (const [symbolName, symbol] of symbols.entries()) {
|
|
234
|
-
if (symbol.filepath === entryFile) {
|
|
235
|
-
entrySymbols.push(symbolName);
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
|
-
const visited = new Set();
|
|
240
|
-
const queue = entrySymbols.map(s => ({ symbol: s, depth: 0 }));
|
|
241
|
-
while (queue.length > 0) {
|
|
242
|
-
const { symbol, depth } = queue.shift();
|
|
243
|
-
if (visited.has(symbol))
|
|
244
|
-
continue;
|
|
245
|
-
visited.add(symbol);
|
|
246
|
-
const node = callGraph.get(symbol);
|
|
247
|
-
if (!node)
|
|
248
|
-
continue;
|
|
249
|
-
node.depth = depth;
|
|
250
|
-
// Add callees to queue
|
|
251
|
-
for (const callee of node.calls) {
|
|
252
|
-
if (!visited.has(callee)) {
|
|
253
|
-
queue.push({ symbol: callee, depth: depth + 1 });
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
}
|
|
258
|
-
/**
|
|
259
|
-
* Find all files that depend on a given file
|
|
260
|
-
*/
|
|
261
|
-
export function findDependents(filepath, dependencyGraph) {
|
|
262
|
-
const graph = dependencyGraph.get(filepath);
|
|
263
|
-
if (!graph)
|
|
264
|
-
return [];
|
|
265
|
-
const allDependents = new Set(graph.dependents);
|
|
266
|
-
// Recursively find dependents of dependents
|
|
267
|
-
for (const dependent of graph.dependents) {
|
|
268
|
-
const depDependents = findDependents(dependent, dependencyGraph);
|
|
269
|
-
depDependents.forEach(d => allDependents.add(d));
|
|
270
|
-
}
|
|
271
|
-
return Array.from(allDependents);
|
|
272
|
-
}
|
|
273
|
-
/**
|
|
274
|
-
* Find all files that a given file depends on
|
|
275
|
-
*/
|
|
276
|
-
export function findDependencies(filepath, dependencyGraph) {
|
|
277
|
-
const graph = dependencyGraph.get(filepath);
|
|
278
|
-
if (!graph)
|
|
279
|
-
return [];
|
|
280
|
-
const allDependencies = new Set(graph.dependencies);
|
|
281
|
-
// Recursively find dependencies of dependencies
|
|
282
|
-
for (const dep of graph.dependencies) {
|
|
283
|
-
const depDeps = findDependencies(dep, dependencyGraph);
|
|
284
|
-
depDeps.forEach(d => allDependencies.add(d));
|
|
285
|
-
}
|
|
286
|
-
return Array.from(allDependencies);
|
|
287
|
-
}
|
|
288
|
-
/**
|
|
289
|
-
* Get impact of changing a file (what breaks)
|
|
290
|
-
*/
|
|
291
|
-
export function getChangeImpact(filepath, codebaseAnalysis) {
|
|
292
|
-
const dependents = findDependents(filepath, codebaseAnalysis.dependencyGraph);
|
|
293
|
-
const fileAnalysis = codebaseAnalysis.files.get(filepath);
|
|
294
|
-
if (!fileAnalysis) {
|
|
295
|
-
return {
|
|
296
|
-
affectedFiles: [],
|
|
297
|
-
affectedSymbols: [],
|
|
298
|
-
riskLevel: 'low',
|
|
299
|
-
};
|
|
300
|
-
}
|
|
301
|
-
const affectedSymbols = [];
|
|
302
|
-
// Find all symbols that use symbols from this file
|
|
303
|
-
for (const symbol of fileAnalysis.symbols) {
|
|
304
|
-
if (symbol.isExported) {
|
|
305
|
-
// Find all usages of this symbol
|
|
306
|
-
for (const [otherFilepath, otherAnalysis] of codebaseAnalysis.files.entries()) {
|
|
307
|
-
if (otherFilepath === filepath)
|
|
308
|
-
continue;
|
|
309
|
-
const usesSymbol = otherAnalysis.relationships.some(rel => rel.to === symbol.name || rel.from === symbol.name);
|
|
310
|
-
if (usesSymbol) {
|
|
311
|
-
affectedSymbols.push(symbol.name);
|
|
312
|
-
}
|
|
313
|
-
}
|
|
314
|
-
}
|
|
315
|
-
}
|
|
316
|
-
const riskLevel = dependents.length > 10 || affectedSymbols.length > 5
|
|
317
|
-
? 'high'
|
|
318
|
-
: dependents.length > 3 || affectedSymbols.length > 2
|
|
319
|
-
? 'medium'
|
|
320
|
-
: 'low';
|
|
321
|
-
return {
|
|
322
|
-
affectedFiles: dependents,
|
|
323
|
-
affectedSymbols: [...new Set(affectedSymbols)],
|
|
324
|
-
riskLevel,
|
|
325
|
-
};
|
|
326
|
-
}
|
|
327
|
-
//# sourceMappingURL=code-analysis.js.map
|