codehere 0.1.0
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/ARCHITECTURE.md +240 -0
- package/CHANGELOG.md +44 -0
- package/CONTRIBUTING.md +171 -0
- package/LICENSE +22 -0
- package/README.md +203 -0
- package/dist/ast-parser.d.ts +55 -0
- package/dist/ast-parser.d.ts.map +1 -0
- package/dist/ast-parser.js +331 -0
- package/dist/ast-parser.js.map +1 -0
- package/dist/benchmark.d.ts +39 -0
- package/dist/benchmark.d.ts.map +1 -0
- package/dist/benchmark.js +195 -0
- package/dist/benchmark.js.map +1 -0
- package/dist/cache.d.ts +45 -0
- package/dist/cache.d.ts.map +1 -0
- package/dist/cache.js +182 -0
- package/dist/cache.js.map +1 -0
- package/dist/chat.d.ts +4 -0
- package/dist/chat.d.ts.map +1 -0
- package/dist/chat.js +132 -0
- package/dist/chat.js.map +1 -0
- package/dist/code-analysis.d.ts +50 -0
- package/dist/code-analysis.d.ts.map +1 -0
- package/dist/code-analysis.js +327 -0
- package/dist/code-analysis.js.map +1 -0
- package/dist/context.d.ts +44 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +187 -0
- package/dist/context.js.map +1 -0
- package/dist/docs.d.ts +21 -0
- package/dist/docs.d.ts.map +1 -0
- package/dist/docs.js +147 -0
- package/dist/docs.js.map +1 -0
- package/dist/edit.d.ts +38 -0
- package/dist/edit.d.ts.map +1 -0
- package/dist/edit.js +594 -0
- package/dist/edit.js.map +1 -0
- package/dist/embed.d.ts +18 -0
- package/dist/embed.d.ts.map +1 -0
- package/dist/embed.js +479 -0
- package/dist/embed.js.map +1 -0
- package/dist/error-handler.d.ts +76 -0
- package/dist/error-handler.d.ts.map +1 -0
- package/dist/error-handler.js +213 -0
- package/dist/error-handler.js.map +1 -0
- package/dist/formatter.d.ts +25 -0
- package/dist/formatter.d.ts.map +1 -0
- package/dist/formatter.js +148 -0
- package/dist/formatter.js.map +1 -0
- package/dist/git.d.ts +55 -0
- package/dist/git.d.ts.map +1 -0
- package/dist/git.js +198 -0
- package/dist/git.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +964 -0
- package/dist/index.js.map +1 -0
- package/dist/intelligent-retrieval.d.ts +41 -0
- package/dist/intelligent-retrieval.d.ts.map +1 -0
- package/dist/intelligent-retrieval.js +265 -0
- package/dist/intelligent-retrieval.js.map +1 -0
- package/dist/iterative-refinement.d.ts +31 -0
- package/dist/iterative-refinement.d.ts.map +1 -0
- package/dist/iterative-refinement.js +172 -0
- package/dist/iterative-refinement.js.map +1 -0
- package/dist/learning.d.ts +69 -0
- package/dist/learning.d.ts.map +1 -0
- package/dist/learning.js +233 -0
- package/dist/learning.js.map +1 -0
- package/dist/log.d.ts +4 -0
- package/dist/log.d.ts.map +1 -0
- package/dist/log.js +31 -0
- package/dist/log.js.map +1 -0
- package/dist/migrate.d.ts +33 -0
- package/dist/migrate.d.ts.map +1 -0
- package/dist/migrate.js +133 -0
- package/dist/migrate.js.map +1 -0
- package/dist/monitoring.d.ts +75 -0
- package/dist/monitoring.d.ts.map +1 -0
- package/dist/monitoring.js +248 -0
- package/dist/monitoring.js.map +1 -0
- package/dist/parallel-processor.d.ts +43 -0
- package/dist/parallel-processor.d.ts.map +1 -0
- package/dist/parallel-processor.js +308 -0
- package/dist/parallel-processor.js.map +1 -0
- package/dist/planner.d.ts +47 -0
- package/dist/planner.d.ts.map +1 -0
- package/dist/planner.js +198 -0
- package/dist/planner.js.map +1 -0
- package/dist/policy.d.ts +3 -0
- package/dist/policy.d.ts.map +1 -0
- package/dist/policy.js +26 -0
- package/dist/policy.js.map +1 -0
- package/dist/query-optimizer.d.ts +32 -0
- package/dist/query-optimizer.d.ts.map +1 -0
- package/dist/query-optimizer.js +205 -0
- package/dist/query-optimizer.js.map +1 -0
- package/dist/refactor.d.ts +27 -0
- package/dist/refactor.d.ts.map +1 -0
- package/dist/refactor.js +118 -0
- package/dist/refactor.js.map +1 -0
- package/dist/review.d.ts +31 -0
- package/dist/review.d.ts.map +1 -0
- package/dist/review.js +206 -0
- package/dist/review.js.map +1 -0
- package/dist/scaffold.d.ts +14 -0
- package/dist/scaffold.d.ts.map +1 -0
- package/dist/scaffold.js +85 -0
- package/dist/scaffold.js.map +1 -0
- package/dist/search.d.ts +19 -0
- package/dist/search.d.ts.map +1 -0
- package/dist/search.js +198 -0
- package/dist/search.js.map +1 -0
- package/dist/session.d.ts +17 -0
- package/dist/session.d.ts.map +1 -0
- package/dist/session.js +301 -0
- package/dist/session.js.map +1 -0
- package/dist/task-verification.d.ts +39 -0
- package/dist/task-verification.d.ts.map +1 -0
- package/dist/task-verification.js +336 -0
- package/dist/task-verification.js.map +1 -0
- package/dist/test_cohere.d.ts +2 -0
- package/dist/test_cohere.d.ts.map +1 -0
- package/dist/test_cohere.js +68 -0
- package/dist/test_cohere.js.map +1 -0
- package/dist/test_env.d.ts +2 -0
- package/dist/test_env.d.ts.map +1 -0
- package/dist/test_env.js +24 -0
- package/dist/test_env.js.map +1 -0
- package/dist/test_retrieval.d.ts +2 -0
- package/dist/test_retrieval.d.ts.map +1 -0
- package/dist/test_retrieval.js +84 -0
- package/dist/test_retrieval.js.map +1 -0
- package/dist/testgen.d.ts +24 -0
- package/dist/testgen.d.ts.map +1 -0
- package/dist/testgen.js +167 -0
- package/dist/testgen.js.map +1 -0
- package/dist/token-optimizer.d.ts +20 -0
- package/dist/token-optimizer.d.ts.map +1 -0
- package/dist/token-optimizer.js +277 -0
- package/dist/token-optimizer.js.map +1 -0
- package/dist/types.d.ts +36 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/ui.d.ts +54 -0
- package/dist/ui.d.ts.map +1 -0
- package/dist/ui.js +295 -0
- package/dist/ui.js.map +1 -0
- package/dist/verify_db.d.ts +2 -0
- package/dist/verify_db.d.ts.map +1 -0
- package/dist/verify_db.js +52 -0
- package/dist/verify_db.js.map +1 -0
- package/package.json +71 -0
- package/templates/next-page/app/layout.tsx +19 -0
- package/templates/next-page/app/page.tsx +10 -0
- package/templates/next-page/package.json +22 -0
- package/templates/node-api/index.js +57 -0
- package/templates/node-api/package.json +13 -0
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Enterprise-Grade Error Handling & Recovery System
|
|
3
|
+
* Ensures 24/7 operation with automatic recovery
|
|
4
|
+
*/
|
|
5
|
+
export var ErrorType;
|
|
6
|
+
(function (ErrorType) {
|
|
7
|
+
ErrorType["RETRYABLE"] = "RETRYABLE";
|
|
8
|
+
ErrorType["FATAL"] = "FATAL";
|
|
9
|
+
ErrorType["RATE_LIMIT"] = "RATE_LIMIT";
|
|
10
|
+
ErrorType["NETWORK"] = "NETWORK";
|
|
11
|
+
ErrorType["API_ERROR"] = "API_ERROR";
|
|
12
|
+
ErrorType["VALIDATION"] = "VALIDATION";
|
|
13
|
+
ErrorType["POLICY"] = "POLICY";
|
|
14
|
+
})(ErrorType || (ErrorType = {}));
|
|
15
|
+
export class EnterpriseError extends Error {
|
|
16
|
+
errorType;
|
|
17
|
+
context;
|
|
18
|
+
retryable;
|
|
19
|
+
constructor(message, errorType, context, retryable = false) {
|
|
20
|
+
super(message);
|
|
21
|
+
this.errorType = errorType;
|
|
22
|
+
this.context = context;
|
|
23
|
+
this.retryable = retryable;
|
|
24
|
+
this.name = 'EnterpriseError';
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Classify error type for appropriate handling
|
|
29
|
+
*/
|
|
30
|
+
export function classifyError(error) {
|
|
31
|
+
if (error instanceof EnterpriseError) {
|
|
32
|
+
return error.errorType;
|
|
33
|
+
}
|
|
34
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
35
|
+
const lowerMessage = errorMessage.toLowerCase();
|
|
36
|
+
// Rate limiting
|
|
37
|
+
if (lowerMessage.includes('rate limit') || lowerMessage.includes('429') || lowerMessage.includes('too many requests')) {
|
|
38
|
+
return ErrorType.RATE_LIMIT;
|
|
39
|
+
}
|
|
40
|
+
// Network errors
|
|
41
|
+
if (lowerMessage.includes('network') || lowerMessage.includes('timeout') || lowerMessage.includes('econnrefused')) {
|
|
42
|
+
return ErrorType.NETWORK;
|
|
43
|
+
}
|
|
44
|
+
// API errors
|
|
45
|
+
if (lowerMessage.includes('api') || lowerMessage.includes('cohere')) {
|
|
46
|
+
return ErrorType.API_ERROR;
|
|
47
|
+
}
|
|
48
|
+
// Validation errors
|
|
49
|
+
if (lowerMessage.includes('validation') || lowerMessage.includes('invalid')) {
|
|
50
|
+
return ErrorType.VALIDATION;
|
|
51
|
+
}
|
|
52
|
+
// Default to retryable
|
|
53
|
+
return ErrorType.RETRYABLE;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Check if error is retryable
|
|
57
|
+
*/
|
|
58
|
+
export function isRetryable(error) {
|
|
59
|
+
const errorType = classifyError(error);
|
|
60
|
+
return [
|
|
61
|
+
ErrorType.RETRYABLE,
|
|
62
|
+
ErrorType.RATE_LIMIT,
|
|
63
|
+
ErrorType.NETWORK,
|
|
64
|
+
ErrorType.API_ERROR,
|
|
65
|
+
].includes(errorType);
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Calculate exponential backoff delay
|
|
69
|
+
*/
|
|
70
|
+
export function calculateBackoff(attempt, baseDelay = 1000, maxDelay = 60000) {
|
|
71
|
+
const delay = Math.min(baseDelay * Math.pow(2, attempt), maxDelay);
|
|
72
|
+
// Add jitter to prevent thundering herd
|
|
73
|
+
const jitter = Math.random() * 0.3 * delay;
|
|
74
|
+
return Math.floor(delay + jitter);
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Retry with exponential backoff
|
|
78
|
+
*/
|
|
79
|
+
export async function retryWithBackoff(operation, options = {}) {
|
|
80
|
+
const { maxRetries = 5, baseDelay = 1000, maxDelay = 60000, operationName = 'operation', onRetry, } = options;
|
|
81
|
+
let lastError;
|
|
82
|
+
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
83
|
+
try {
|
|
84
|
+
return await operation();
|
|
85
|
+
}
|
|
86
|
+
catch (error) {
|
|
87
|
+
lastError = error;
|
|
88
|
+
// Don't retry on fatal errors
|
|
89
|
+
if (!isRetryable(error)) {
|
|
90
|
+
throw new EnterpriseError(`Fatal error in ${operationName}: ${error instanceof Error ? error.message : String(error)}`, classifyError(error), {
|
|
91
|
+
operation: operationName,
|
|
92
|
+
attempt,
|
|
93
|
+
maxRetries,
|
|
94
|
+
timestamp: new Date().toISOString(),
|
|
95
|
+
errorType: classifyError(error),
|
|
96
|
+
originalError: error instanceof Error ? error : new Error(String(error)),
|
|
97
|
+
}, false);
|
|
98
|
+
}
|
|
99
|
+
// Last attempt, throw error
|
|
100
|
+
if (attempt === maxRetries) {
|
|
101
|
+
break;
|
|
102
|
+
}
|
|
103
|
+
// Calculate delay and wait
|
|
104
|
+
const delay = calculateBackoff(attempt, baseDelay, maxDelay);
|
|
105
|
+
if (onRetry) {
|
|
106
|
+
onRetry(attempt + 1, error);
|
|
107
|
+
}
|
|
108
|
+
await new Promise(resolve => setTimeout(resolve, delay));
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
// All retries exhausted
|
|
112
|
+
throw new EnterpriseError(`Operation ${operationName} failed after ${maxRetries} retries: ${lastError instanceof Error ? lastError.message : String(lastError)}`, classifyError(lastError), {
|
|
113
|
+
operation: operationName,
|
|
114
|
+
attempt: maxRetries,
|
|
115
|
+
maxRetries,
|
|
116
|
+
timestamp: new Date().toISOString(),
|
|
117
|
+
errorType: classifyError(lastError),
|
|
118
|
+
originalError: lastError instanceof Error ? lastError : new Error(String(lastError)),
|
|
119
|
+
}, false);
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Circuit breaker pattern for API calls
|
|
123
|
+
*/
|
|
124
|
+
export class CircuitBreaker {
|
|
125
|
+
threshold;
|
|
126
|
+
timeout;
|
|
127
|
+
resetTimeout;
|
|
128
|
+
failures = 0;
|
|
129
|
+
lastFailureTime = 0;
|
|
130
|
+
state = 'CLOSED';
|
|
131
|
+
constructor(threshold = 5, timeout = 60000, // 1 minute
|
|
132
|
+
resetTimeout = 30000 // 30 seconds
|
|
133
|
+
) {
|
|
134
|
+
this.threshold = threshold;
|
|
135
|
+
this.timeout = timeout;
|
|
136
|
+
this.resetTimeout = resetTimeout;
|
|
137
|
+
}
|
|
138
|
+
async execute(operation) {
|
|
139
|
+
// Check if circuit should be reset
|
|
140
|
+
if (this.state === 'OPEN') {
|
|
141
|
+
const timeSinceLastFailure = Date.now() - this.lastFailureTime;
|
|
142
|
+
if (timeSinceLastFailure > this.resetTimeout) {
|
|
143
|
+
this.state = 'HALF_OPEN';
|
|
144
|
+
}
|
|
145
|
+
else {
|
|
146
|
+
throw new EnterpriseError('Circuit breaker is OPEN. Service unavailable.', ErrorType.API_ERROR, {
|
|
147
|
+
operation: 'circuit_breaker',
|
|
148
|
+
timestamp: new Date().toISOString(),
|
|
149
|
+
errorType: ErrorType.API_ERROR,
|
|
150
|
+
originalError: new Error('Circuit breaker open'),
|
|
151
|
+
}, false);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
try {
|
|
155
|
+
const result = await operation();
|
|
156
|
+
// Success - reset failures if in HALF_OPEN
|
|
157
|
+
if (this.state === 'HALF_OPEN') {
|
|
158
|
+
this.state = 'CLOSED';
|
|
159
|
+
this.failures = 0;
|
|
160
|
+
}
|
|
161
|
+
else if (this.failures > 0) {
|
|
162
|
+
this.failures = 0;
|
|
163
|
+
}
|
|
164
|
+
return result;
|
|
165
|
+
}
|
|
166
|
+
catch (error) {
|
|
167
|
+
this.failures++;
|
|
168
|
+
this.lastFailureTime = Date.now();
|
|
169
|
+
// Open circuit if threshold exceeded
|
|
170
|
+
if (this.failures >= this.threshold) {
|
|
171
|
+
this.state = 'OPEN';
|
|
172
|
+
}
|
|
173
|
+
throw error;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
getState() {
|
|
177
|
+
return this.state;
|
|
178
|
+
}
|
|
179
|
+
reset() {
|
|
180
|
+
this.failures = 0;
|
|
181
|
+
this.state = 'CLOSED';
|
|
182
|
+
this.lastFailureTime = 0;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Global circuit breaker for Cohere API
|
|
187
|
+
*/
|
|
188
|
+
export const cohereCircuitBreaker = new CircuitBreaker(5, 60000, 30000);
|
|
189
|
+
/**
|
|
190
|
+
* Graceful error handler with recovery strategies
|
|
191
|
+
*/
|
|
192
|
+
export function handleError(error, context) {
|
|
193
|
+
const errorType = classifyError(error);
|
|
194
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
195
|
+
const fullContext = {
|
|
196
|
+
operation: context.operation || 'unknown',
|
|
197
|
+
filepath: context.filepath,
|
|
198
|
+
attempt: context.attempt,
|
|
199
|
+
maxRetries: context.maxRetries,
|
|
200
|
+
timestamp: new Date().toISOString(),
|
|
201
|
+
errorType,
|
|
202
|
+
originalError: error instanceof Error ? error : new Error(errorMessage),
|
|
203
|
+
metadata: context.metadata,
|
|
204
|
+
};
|
|
205
|
+
// Log error with full context
|
|
206
|
+
console.error('Enterprise Error:', {
|
|
207
|
+
message: errorMessage,
|
|
208
|
+
type: errorType,
|
|
209
|
+
context: fullContext,
|
|
210
|
+
});
|
|
211
|
+
throw new EnterpriseError(errorMessage, errorType, fullContext, isRetryable(error));
|
|
212
|
+
}
|
|
213
|
+
//# sourceMappingURL=error-handler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error-handler.js","sourceRoot":"","sources":["../src/error-handler.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Terminal Markdown Formatter
|
|
3
|
+
* Converts markdown to beautifully formatted terminal output
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Format markdown text for terminal display
|
|
7
|
+
*/
|
|
8
|
+
export declare function formatMarkdown(text: string): string;
|
|
9
|
+
/**
|
|
10
|
+
* Format code block for terminal
|
|
11
|
+
*/
|
|
12
|
+
export declare function formatCodeBlock(code: string, language?: string): string;
|
|
13
|
+
/**
|
|
14
|
+
* Format list items nicely
|
|
15
|
+
*/
|
|
16
|
+
export declare function formatList(items: string[]): string;
|
|
17
|
+
/**
|
|
18
|
+
* Format response text with proper wrapping and formatting
|
|
19
|
+
*/
|
|
20
|
+
export declare function formatResponse(text: string, maxWidth?: number): string;
|
|
21
|
+
/**
|
|
22
|
+
* Clean and format AI response for display
|
|
23
|
+
*/
|
|
24
|
+
export declare function cleanResponse(response: string): string;
|
|
25
|
+
//# sourceMappingURL=formatter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"formatter.d.ts","sourceRoot":"","sources":["../src/formatter.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH;;GAEG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAwEnD;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAkBvE;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,MAAM,CAElD;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,GAAE,MAAW,GAAG,MAAM,CAmC1E;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAetD"}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Terminal Markdown Formatter
|
|
3
|
+
* Converts markdown to beautifully formatted terminal output
|
|
4
|
+
*/
|
|
5
|
+
import { colors } from './ui.js';
|
|
6
|
+
/**
|
|
7
|
+
* Format markdown text for terminal display
|
|
8
|
+
*/
|
|
9
|
+
export function formatMarkdown(text) {
|
|
10
|
+
if (!text)
|
|
11
|
+
return '';
|
|
12
|
+
let formatted = text;
|
|
13
|
+
// Remove markdown code blocks but preserve content
|
|
14
|
+
formatted = formatted.replace(/```[\w]*\n?([\s\S]*?)```/g, (match, code) => {
|
|
15
|
+
return colors.cyan(code.trim());
|
|
16
|
+
});
|
|
17
|
+
// Remove inline code but style it
|
|
18
|
+
formatted = formatted.replace(/`([^`]+)`/g, (match, code) => {
|
|
19
|
+
return colors.cyan(code);
|
|
20
|
+
});
|
|
21
|
+
// Convert headers to bold
|
|
22
|
+
formatted = formatted.replace(/^### (.*$)/gim, (match, text) => {
|
|
23
|
+
return '\n' + colors.bold(text) + '\n';
|
|
24
|
+
});
|
|
25
|
+
formatted = formatted.replace(/^## (.*$)/gim, (match, text) => {
|
|
26
|
+
return '\n' + colors.bold(text) + '\n';
|
|
27
|
+
});
|
|
28
|
+
formatted = formatted.replace(/^# (.*$)/gim, (match, text) => {
|
|
29
|
+
return '\n' + colors.bold(text) + '\n';
|
|
30
|
+
});
|
|
31
|
+
// Convert bold (**text** or __text__) to colored bold
|
|
32
|
+
formatted = formatted.replace(/\*\*(.+?)\*\*/g, (match, text) => {
|
|
33
|
+
return colors.bold(text);
|
|
34
|
+
});
|
|
35
|
+
formatted = formatted.replace(/__(.+?)__/g, (match, text) => {
|
|
36
|
+
return colors.bold(text);
|
|
37
|
+
});
|
|
38
|
+
// Convert italic (*text* or _text_) to dim
|
|
39
|
+
formatted = formatted.replace(/\*(.+?)\*/g, (match, text) => {
|
|
40
|
+
// Don't convert if it's part of **bold**
|
|
41
|
+
if (text.includes('*'))
|
|
42
|
+
return match;
|
|
43
|
+
return colors.dim(text);
|
|
44
|
+
});
|
|
45
|
+
formatted = formatted.replace(/_(.+?)_/g, (match, text) => {
|
|
46
|
+
// Don't convert if it's part of __bold__
|
|
47
|
+
if (text.includes('_'))
|
|
48
|
+
return match;
|
|
49
|
+
return colors.dim(text);
|
|
50
|
+
});
|
|
51
|
+
// Convert bullet points to clean bullets
|
|
52
|
+
formatted = formatted.replace(/^[\*\-\+] (.+)$/gim, (match, text) => {
|
|
53
|
+
return ' • ' + text.trim();
|
|
54
|
+
});
|
|
55
|
+
// Convert numbered lists
|
|
56
|
+
formatted = formatted.replace(/^\d+\. (.+)$/gim, (match, text) => {
|
|
57
|
+
return ' ' + text.trim();
|
|
58
|
+
});
|
|
59
|
+
// Clean up multiple newlines (max 2)
|
|
60
|
+
formatted = formatted.replace(/\n{3,}/g, '\n\n');
|
|
61
|
+
// Remove markdown links but keep text
|
|
62
|
+
formatted = formatted.replace(/\[([^\]]+)\]\([^\)]+\)/g, (match, text) => {
|
|
63
|
+
return text;
|
|
64
|
+
});
|
|
65
|
+
// Remove horizontal rules
|
|
66
|
+
formatted = formatted.replace(/^---+\s*$/gim, '');
|
|
67
|
+
// Clean up any remaining markdown artifacts
|
|
68
|
+
formatted = formatted.replace(/\[([^\]]+)\]\[[^\]]+\]/g, '$1'); // Reference links
|
|
69
|
+
formatted = formatted.replace(/!\[([^\]]*)\]\([^\)]+\)/g, '$1'); // Images
|
|
70
|
+
return formatted.trim();
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Format code block for terminal
|
|
74
|
+
*/
|
|
75
|
+
export function formatCodeBlock(code, language) {
|
|
76
|
+
const lines = code.split('\n');
|
|
77
|
+
const maxWidth = process.stdout.columns || 80;
|
|
78
|
+
const indent = ' ';
|
|
79
|
+
let output = colors.dim('┌─ Code ──────────────────────────────────────┐\n');
|
|
80
|
+
for (const line of lines) {
|
|
81
|
+
// Truncate very long lines
|
|
82
|
+
const displayLine = line.length > maxWidth - 10
|
|
83
|
+
? line.substring(0, maxWidth - 13) + '...'
|
|
84
|
+
: line;
|
|
85
|
+
output += indent + colors.cyan(displayLine) + '\n';
|
|
86
|
+
}
|
|
87
|
+
output += colors.dim('└──────────────────────────────────────────────┘');
|
|
88
|
+
return output;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Format list items nicely
|
|
92
|
+
*/
|
|
93
|
+
export function formatList(items) {
|
|
94
|
+
return items.map(item => ' • ' + item.trim()).join('\n');
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Format response text with proper wrapping and formatting
|
|
98
|
+
*/
|
|
99
|
+
export function formatResponse(text, maxWidth = 80) {
|
|
100
|
+
if (!text)
|
|
101
|
+
return '';
|
|
102
|
+
// First format markdown
|
|
103
|
+
let formatted = formatMarkdown(text);
|
|
104
|
+
// Word wrap to terminal width
|
|
105
|
+
const lines = formatted.split('\n');
|
|
106
|
+
const wrapped = [];
|
|
107
|
+
for (const line of lines) {
|
|
108
|
+
if (line.length <= maxWidth) {
|
|
109
|
+
wrapped.push(line);
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
// Wrap long lines
|
|
113
|
+
const words = line.split(' ');
|
|
114
|
+
let currentLine = '';
|
|
115
|
+
for (const word of words) {
|
|
116
|
+
if ((currentLine + word).length <= maxWidth) {
|
|
117
|
+
currentLine += (currentLine ? ' ' : '') + word;
|
|
118
|
+
}
|
|
119
|
+
else {
|
|
120
|
+
if (currentLine) {
|
|
121
|
+
wrapped.push(currentLine);
|
|
122
|
+
}
|
|
123
|
+
currentLine = word;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
if (currentLine) {
|
|
127
|
+
wrapped.push(currentLine);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
return wrapped.join('\n');
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Clean and format AI response for display
|
|
135
|
+
*/
|
|
136
|
+
export function cleanResponse(response) {
|
|
137
|
+
if (!response)
|
|
138
|
+
return '';
|
|
139
|
+
let cleaned = response;
|
|
140
|
+
// Remove any leading/trailing markdown artifacts
|
|
141
|
+
cleaned = cleaned.trim();
|
|
142
|
+
// Remove markdown frontmatter if present
|
|
143
|
+
cleaned = cleaned.replace(/^---[\s\S]*?---\n/, '');
|
|
144
|
+
// Format the response
|
|
145
|
+
cleaned = formatResponse(cleaned);
|
|
146
|
+
return cleaned;
|
|
147
|
+
}
|
|
148
|
+
//# sourceMappingURL=formatter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"formatter.js","sourceRoot":"","sources":["../src/formatter.ts"],"names":[],"mappings":"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"}
|
package/dist/git.d.ts
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Git Integration System
|
|
3
|
+
* Understand code history and suggest improvements
|
|
4
|
+
*/
|
|
5
|
+
export interface GitDiff {
|
|
6
|
+
file: string;
|
|
7
|
+
added: number;
|
|
8
|
+
removed: number;
|
|
9
|
+
changes: string[];
|
|
10
|
+
}
|
|
11
|
+
export interface GitStatus {
|
|
12
|
+
isRepo: boolean;
|
|
13
|
+
branch?: string;
|
|
14
|
+
hasChanges: boolean;
|
|
15
|
+
modifiedFiles: string[];
|
|
16
|
+
untrackedFiles: string[];
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Check if current directory is a git repository
|
|
20
|
+
*/
|
|
21
|
+
export declare function isGitRepo(path?: string): boolean;
|
|
22
|
+
/**
|
|
23
|
+
* Get git status
|
|
24
|
+
*/
|
|
25
|
+
export declare function getGitStatus(path?: string): GitStatus;
|
|
26
|
+
/**
|
|
27
|
+
* Get git diff for a file
|
|
28
|
+
*/
|
|
29
|
+
export declare function getGitDiff(file: string, path?: string): GitDiff | null;
|
|
30
|
+
/**
|
|
31
|
+
* Get git diff for all modified files
|
|
32
|
+
*/
|
|
33
|
+
export declare function getAllGitDiffs(path?: string): Map<string, GitDiff>;
|
|
34
|
+
/**
|
|
35
|
+
* Analyze git diff and suggest improvements
|
|
36
|
+
*/
|
|
37
|
+
export declare function analyzeDiff(diff: GitDiff): {
|
|
38
|
+
summary: string;
|
|
39
|
+
suggestions: string[];
|
|
40
|
+
riskLevel: 'low' | 'medium' | 'high';
|
|
41
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
* Get commit history for a file
|
|
44
|
+
*/
|
|
45
|
+
export declare function getFileHistory(file: string, limit?: number, path?: string): Array<{
|
|
46
|
+
commit: string;
|
|
47
|
+
author: string;
|
|
48
|
+
date: string;
|
|
49
|
+
message: string;
|
|
50
|
+
}>;
|
|
51
|
+
/**
|
|
52
|
+
* Format git status for display
|
|
53
|
+
*/
|
|
54
|
+
export declare function formatGitStatus(status: GitStatus): string;
|
|
55
|
+
//# sourceMappingURL=git.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git.d.ts","sourceRoot":"","sources":["../src/git.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,MAAM,WAAW,SAAS;IACxB,MAAM,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,OAAO,CAAC;IACpB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,cAAc,EAAE,MAAM,EAAE,CAAC;CAC1B;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,IAAI,GAAE,MAAsB,GAAG,OAAO,CAE/D;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,IAAI,GAAE,MAAsB,GAAG,SAAS,CAmDpE;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,GAAE,MAAsB,GAAG,OAAO,GAAG,IAAI,CAuCrF;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,IAAI,GAAE,MAAsB,GAAG,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,CAYjF;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,OAAO,GAAG;IAC1C,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,SAAS,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;CACtC,CAgCA;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,GAAE,MAAW,EAAE,IAAI,GAAE,MAAsB,GAAG,KAAK,CAAC;IACpG,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC,CA8BD;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,SAAS,GAAG,MAAM,CAiBzD"}
|
package/dist/git.js
ADDED
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Git Integration System
|
|
3
|
+
* Understand code history and suggest improvements
|
|
4
|
+
*/
|
|
5
|
+
import { execSync } from 'child_process';
|
|
6
|
+
import { existsSync } from 'fs';
|
|
7
|
+
import { join } from 'path';
|
|
8
|
+
/**
|
|
9
|
+
* Check if current directory is a git repository
|
|
10
|
+
*/
|
|
11
|
+
export function isGitRepo(path = process.cwd()) {
|
|
12
|
+
return existsSync(join(path, '.git'));
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Get git status
|
|
16
|
+
*/
|
|
17
|
+
export function getGitStatus(path = process.cwd()) {
|
|
18
|
+
if (!isGitRepo(path)) {
|
|
19
|
+
return {
|
|
20
|
+
isRepo: false,
|
|
21
|
+
hasChanges: false,
|
|
22
|
+
modifiedFiles: [],
|
|
23
|
+
untrackedFiles: [],
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
try {
|
|
27
|
+
const statusOutput = execSync('git status --porcelain', {
|
|
28
|
+
cwd: path,
|
|
29
|
+
encoding: 'utf-8',
|
|
30
|
+
});
|
|
31
|
+
const branchOutput = execSync('git branch --show-current', {
|
|
32
|
+
cwd: path,
|
|
33
|
+
encoding: 'utf-8',
|
|
34
|
+
}).trim();
|
|
35
|
+
const lines = statusOutput.trim().split('\n').filter(l => l);
|
|
36
|
+
const modifiedFiles = [];
|
|
37
|
+
const untrackedFiles = [];
|
|
38
|
+
for (const line of lines) {
|
|
39
|
+
const status = line.substring(0, 2);
|
|
40
|
+
const file = line.substring(3);
|
|
41
|
+
if (status === '??') {
|
|
42
|
+
untrackedFiles.push(file);
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
modifiedFiles.push(file);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return {
|
|
49
|
+
isRepo: true,
|
|
50
|
+
branch: branchOutput || undefined,
|
|
51
|
+
hasChanges: lines.length > 0,
|
|
52
|
+
modifiedFiles,
|
|
53
|
+
untrackedFiles,
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
catch (error) {
|
|
57
|
+
return {
|
|
58
|
+
isRepo: true,
|
|
59
|
+
hasChanges: false,
|
|
60
|
+
modifiedFiles: [],
|
|
61
|
+
untrackedFiles: [],
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Get git diff for a file
|
|
67
|
+
*/
|
|
68
|
+
export function getGitDiff(file, path = process.cwd()) {
|
|
69
|
+
if (!isGitRepo(path)) {
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
try {
|
|
73
|
+
const diffOutput = execSync(`git diff ${file}`, {
|
|
74
|
+
cwd: path,
|
|
75
|
+
encoding: 'utf-8',
|
|
76
|
+
});
|
|
77
|
+
if (!diffOutput.trim()) {
|
|
78
|
+
return null;
|
|
79
|
+
}
|
|
80
|
+
const lines = diffOutput.split('\n');
|
|
81
|
+
let added = 0;
|
|
82
|
+
let removed = 0;
|
|
83
|
+
const changes = [];
|
|
84
|
+
for (const line of lines) {
|
|
85
|
+
if (line.startsWith('+') && !line.startsWith('+++')) {
|
|
86
|
+
added++;
|
|
87
|
+
changes.push(line);
|
|
88
|
+
}
|
|
89
|
+
else if (line.startsWith('-') && !line.startsWith('---')) {
|
|
90
|
+
removed++;
|
|
91
|
+
changes.push(line);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
return {
|
|
95
|
+
file,
|
|
96
|
+
added,
|
|
97
|
+
removed,
|
|
98
|
+
changes,
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
catch (error) {
|
|
102
|
+
return null;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Get git diff for all modified files
|
|
107
|
+
*/
|
|
108
|
+
export function getAllGitDiffs(path = process.cwd()) {
|
|
109
|
+
const diffs = new Map();
|
|
110
|
+
const status = getGitStatus(path);
|
|
111
|
+
for (const file of status.modifiedFiles) {
|
|
112
|
+
const diff = getGitDiff(file, path);
|
|
113
|
+
if (diff) {
|
|
114
|
+
diffs.set(file, diff);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
return diffs;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Analyze git diff and suggest improvements
|
|
121
|
+
*/
|
|
122
|
+
export function analyzeDiff(diff) {
|
|
123
|
+
const suggestions = [];
|
|
124
|
+
let riskLevel = 'low';
|
|
125
|
+
// Large changes
|
|
126
|
+
if (diff.added + diff.removed > 100) {
|
|
127
|
+
suggestions.push('Large change detected - consider breaking into smaller commits');
|
|
128
|
+
riskLevel = 'high';
|
|
129
|
+
}
|
|
130
|
+
else if (diff.added + diff.removed > 50) {
|
|
131
|
+
suggestions.push('Moderate change size - review carefully');
|
|
132
|
+
riskLevel = 'medium';
|
|
133
|
+
}
|
|
134
|
+
// Many additions
|
|
135
|
+
if (diff.added > 200) {
|
|
136
|
+
suggestions.push('Many new lines added - ensure proper testing');
|
|
137
|
+
riskLevel = riskLevel === 'low' ? 'medium' : riskLevel;
|
|
138
|
+
}
|
|
139
|
+
// Many removals
|
|
140
|
+
if (diff.removed > 100) {
|
|
141
|
+
suggestions.push('Significant code removal - verify no functionality lost');
|
|
142
|
+
riskLevel = riskLevel === 'low' ? 'medium' : riskLevel;
|
|
143
|
+
}
|
|
144
|
+
const summary = `File ${diff.file}: ${diff.added} additions, ${diff.removed} deletions`;
|
|
145
|
+
return {
|
|
146
|
+
summary,
|
|
147
|
+
suggestions,
|
|
148
|
+
riskLevel,
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Get commit history for a file
|
|
153
|
+
*/
|
|
154
|
+
export function getFileHistory(file, limit = 10, path = process.cwd()) {
|
|
155
|
+
if (!isGitRepo(path)) {
|
|
156
|
+
return [];
|
|
157
|
+
}
|
|
158
|
+
try {
|
|
159
|
+
const logOutput = execSync(`git log --pretty=format:"%H|%an|%ad|%s" --date=iso -n ${limit} -- ${file}`, {
|
|
160
|
+
cwd: path,
|
|
161
|
+
encoding: 'utf-8',
|
|
162
|
+
});
|
|
163
|
+
return logOutput
|
|
164
|
+
.trim()
|
|
165
|
+
.split('\n')
|
|
166
|
+
.filter(l => l)
|
|
167
|
+
.map(line => {
|
|
168
|
+
const [commit, author, date, ...messageParts] = line.split('|');
|
|
169
|
+
return {
|
|
170
|
+
commit: commit || '',
|
|
171
|
+
author: author || '',
|
|
172
|
+
date: date || '',
|
|
173
|
+
message: messageParts.join('|') || '',
|
|
174
|
+
};
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
catch (error) {
|
|
178
|
+
return [];
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Format git status for display
|
|
183
|
+
*/
|
|
184
|
+
export function formatGitStatus(status) {
|
|
185
|
+
if (!status.isRepo) {
|
|
186
|
+
return 'Not a git repository';
|
|
187
|
+
}
|
|
188
|
+
let output = `Branch: ${status.branch || 'unknown'}\n`;
|
|
189
|
+
output += `Changes: ${status.hasChanges ? 'Yes' : 'No'}\n`;
|
|
190
|
+
if (status.modifiedFiles.length > 0) {
|
|
191
|
+
output += `Modified: ${status.modifiedFiles.length} file(s)\n`;
|
|
192
|
+
}
|
|
193
|
+
if (status.untrackedFiles.length > 0) {
|
|
194
|
+
output += `Untracked: ${status.untrackedFiles.length} file(s)\n`;
|
|
195
|
+
}
|
|
196
|
+
return output;
|
|
197
|
+
}
|
|
198
|
+
//# sourceMappingURL=git.js.map
|