kimi-vercel-ai-sdk-provider 0.3.0 → 0.5.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/README.md +567 -17
- package/dist/index.d.mts +1750 -3
- package/dist/index.d.ts +1750 -3
- package/dist/index.js +2317 -161
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2292 -160
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/__tests__/auto-detect.test.ts +140 -0
- package/src/__tests__/code-validation.test.ts +267 -0
- package/src/__tests__/ensemble.test.ts +242 -0
- package/src/__tests__/file-cache.test.ts +310 -0
- package/src/__tests__/model-config.test.ts +120 -0
- package/src/__tests__/multi-agent.test.ts +201 -0
- package/src/__tests__/project-tools.test.ts +181 -0
- package/src/__tests__/reasoning-utils.test.ts +164 -0
- package/src/__tests__/tools.test.ts +76 -8
- package/src/chat/kimi-chat-language-model.ts +21 -2
- package/src/chat/kimi-chat-settings.ts +15 -1
- package/src/code-validation/detector.ts +319 -0
- package/src/code-validation/index.ts +31 -0
- package/src/code-validation/types.ts +291 -0
- package/src/code-validation/validator.ts +547 -0
- package/src/core/errors.ts +91 -0
- package/src/core/index.ts +15 -3
- package/src/core/types.ts +57 -2
- package/src/core/utils.ts +138 -0
- package/src/ensemble/index.ts +17 -0
- package/src/ensemble/multi-sampler.ts +433 -0
- package/src/ensemble/types.ts +279 -0
- package/src/files/attachment-processor.ts +51 -4
- package/src/files/file-cache.ts +260 -0
- package/src/files/index.ts +16 -1
- package/src/index.ts +102 -3
- package/src/kimi-provider.ts +354 -1
- package/src/multi-agent/index.ts +21 -0
- package/src/multi-agent/types.ts +312 -0
- package/src/multi-agent/workflows.ts +539 -0
- package/src/project-tools/index.ts +16 -0
- package/src/project-tools/scaffolder.ts +494 -0
- package/src/project-tools/types.ts +244 -0
- package/src/tools/auto-detect.ts +276 -0
- package/src/tools/index.ts +6 -2
- package/src/tools/prepare-tools.ts +179 -4
|
@@ -0,0 +1,547 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Code validator implementation.
|
|
3
|
+
* @module
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type { CodeValidationConfig, FixAttempt, SupportedLanguage, ValidationError, ValidationResult } from './types';
|
|
7
|
+
import { detectLanguage, extractPrimaryCode } from './detector';
|
|
8
|
+
|
|
9
|
+
// ============================================================================
|
|
10
|
+
// Types
|
|
11
|
+
// ============================================================================
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Function to generate text from a model.
|
|
15
|
+
*/
|
|
16
|
+
export type GenerateTextFunction = (prompt: string) => Promise<{
|
|
17
|
+
text: string;
|
|
18
|
+
toolCalls?: unknown[];
|
|
19
|
+
toolResults?: unknown[];
|
|
20
|
+
}>;
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Options for creating a code validator.
|
|
24
|
+
*/
|
|
25
|
+
export interface CodeValidatorOptions {
|
|
26
|
+
/**
|
|
27
|
+
* Function to generate text (for fix attempts).
|
|
28
|
+
*/
|
|
29
|
+
generateText: GenerateTextFunction;
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Function to execute code using the code interpreter.
|
|
33
|
+
* Should return output or throw on error.
|
|
34
|
+
*/
|
|
35
|
+
executeCode?: (code: string, language: string) => Promise<string>;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// ============================================================================
|
|
39
|
+
// CodeValidator Class
|
|
40
|
+
// ============================================================================
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Validates code and attempts to fix errors automatically.
|
|
44
|
+
*
|
|
45
|
+
* @example
|
|
46
|
+
* ```ts
|
|
47
|
+
* const validator = new CodeValidator({
|
|
48
|
+
* generateText: async (prompt) => {
|
|
49
|
+
* const result = await generateText({ model, prompt });
|
|
50
|
+
* return { text: result.text };
|
|
51
|
+
* },
|
|
52
|
+
* });
|
|
53
|
+
*
|
|
54
|
+
* const result = await validator.validate(code, {
|
|
55
|
+
* enabled: true,
|
|
56
|
+
* maxAttempts: 3,
|
|
57
|
+
* language: 'javascript',
|
|
58
|
+
* });
|
|
59
|
+
* ```
|
|
60
|
+
*/
|
|
61
|
+
export class CodeValidator {
|
|
62
|
+
private generateText: GenerateTextFunction;
|
|
63
|
+
private executeCode?: (code: string, language: string) => Promise<string>;
|
|
64
|
+
|
|
65
|
+
constructor(options: CodeValidatorOptions) {
|
|
66
|
+
this.generateText = options.generateText;
|
|
67
|
+
this.executeCode = options.executeCode;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Validate code and optionally fix errors.
|
|
72
|
+
*
|
|
73
|
+
* @param code - The code to validate
|
|
74
|
+
* @param config - Validation configuration
|
|
75
|
+
* @param originalPrompt - The original user prompt (for context in fixes)
|
|
76
|
+
* @returns Validation result
|
|
77
|
+
*/
|
|
78
|
+
async validate(code: string, config: CodeValidationConfig, originalPrompt: string = ''): Promise<ValidationResult> {
|
|
79
|
+
const {
|
|
80
|
+
maxAttempts = 3,
|
|
81
|
+
language: configLanguage = 'auto',
|
|
82
|
+
executionTimeoutMs = 30000,
|
|
83
|
+
strictness = 'strict',
|
|
84
|
+
returnPartialFix = true
|
|
85
|
+
} = config;
|
|
86
|
+
|
|
87
|
+
// Detect language if auto
|
|
88
|
+
const language = configLanguage === 'auto' ? detectLanguage(code).language : configLanguage;
|
|
89
|
+
|
|
90
|
+
let currentCode = code;
|
|
91
|
+
const allErrors: ValidationError[] = [];
|
|
92
|
+
const allWarnings: ValidationError[] = [];
|
|
93
|
+
const fixHistory: FixAttempt[] = [];
|
|
94
|
+
let attempts = 0;
|
|
95
|
+
|
|
96
|
+
for (let i = 0; i < maxAttempts; i++) {
|
|
97
|
+
attempts++;
|
|
98
|
+
|
|
99
|
+
// Validate the current code
|
|
100
|
+
const validationResult = await this.validateCode(currentCode, language, strictness, executionTimeoutMs);
|
|
101
|
+
|
|
102
|
+
// Collect errors and warnings
|
|
103
|
+
const newErrors = validationResult.errors.filter(
|
|
104
|
+
(e) => !allErrors.some((existing) => existing.message === e.message)
|
|
105
|
+
);
|
|
106
|
+
allErrors.push(...newErrors);
|
|
107
|
+
allWarnings.push(...validationResult.warnings);
|
|
108
|
+
|
|
109
|
+
// If valid, we're done
|
|
110
|
+
if (validationResult.valid) {
|
|
111
|
+
return {
|
|
112
|
+
valid: true,
|
|
113
|
+
errors: [],
|
|
114
|
+
warnings: allWarnings,
|
|
115
|
+
output: validationResult.output,
|
|
116
|
+
executionTimeMs: validationResult.executionTimeMs,
|
|
117
|
+
attempts,
|
|
118
|
+
finalCode: currentCode,
|
|
119
|
+
originalCode: code,
|
|
120
|
+
language,
|
|
121
|
+
fixHistory
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// If this is the last attempt, don't try to fix
|
|
126
|
+
if (i === maxAttempts - 1) {
|
|
127
|
+
break;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// Try to fix the errors
|
|
131
|
+
const fixResult = await this.attemptFix(currentCode, validationResult.errors, language, originalPrompt);
|
|
132
|
+
|
|
133
|
+
fixHistory.push({
|
|
134
|
+
attempt: attempts,
|
|
135
|
+
codeBefore: currentCode,
|
|
136
|
+
codeAfter: fixResult.code,
|
|
137
|
+
errorsAddressed: validationResult.errors,
|
|
138
|
+
success: false // Will be updated if next validation passes
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
if (fixResult.fixed) {
|
|
142
|
+
currentCode = fixResult.code;
|
|
143
|
+
} else {
|
|
144
|
+
// Can't fix, stop trying
|
|
145
|
+
break;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// Return failed result
|
|
150
|
+
return {
|
|
151
|
+
valid: false,
|
|
152
|
+
errors: allErrors,
|
|
153
|
+
warnings: allWarnings,
|
|
154
|
+
attempts,
|
|
155
|
+
finalCode: returnPartialFix ? currentCode : code,
|
|
156
|
+
originalCode: code,
|
|
157
|
+
language,
|
|
158
|
+
fixHistory
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Validate code without attempting fixes.
|
|
164
|
+
*/
|
|
165
|
+
private async validateCode(
|
|
166
|
+
code: string,
|
|
167
|
+
language: SupportedLanguage,
|
|
168
|
+
strictness: string,
|
|
169
|
+
_timeoutMs: number
|
|
170
|
+
): Promise<{
|
|
171
|
+
valid: boolean;
|
|
172
|
+
errors: ValidationError[];
|
|
173
|
+
warnings: ValidationError[];
|
|
174
|
+
output?: string;
|
|
175
|
+
executionTimeMs?: number;
|
|
176
|
+
}> {
|
|
177
|
+
const errors: ValidationError[] = [];
|
|
178
|
+
const warnings: ValidationError[] = [];
|
|
179
|
+
|
|
180
|
+
// Static analysis first
|
|
181
|
+
const staticErrors = this.performStaticAnalysis(code, language);
|
|
182
|
+
errors.push(...staticErrors);
|
|
183
|
+
|
|
184
|
+
// If we have critical syntax errors, don't try to execute
|
|
185
|
+
if (staticErrors.some((e) => e.type === 'syntax' && e.severity === 'error')) {
|
|
186
|
+
return { valid: false, errors, warnings };
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// Try to execute if we have an executor
|
|
190
|
+
if (this.executeCode) {
|
|
191
|
+
try {
|
|
192
|
+
const startTime = Date.now();
|
|
193
|
+
const output = await this.executeCode(code, language);
|
|
194
|
+
const executionTimeMs = Date.now() - startTime;
|
|
195
|
+
|
|
196
|
+
// Check output for error patterns
|
|
197
|
+
const runtimeErrors = this.detectRuntimeErrors(output);
|
|
198
|
+
errors.push(...runtimeErrors);
|
|
199
|
+
|
|
200
|
+
if (runtimeErrors.length === 0) {
|
|
201
|
+
return {
|
|
202
|
+
valid: true,
|
|
203
|
+
errors: [],
|
|
204
|
+
warnings,
|
|
205
|
+
output,
|
|
206
|
+
executionTimeMs
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
} catch (error) {
|
|
210
|
+
const message = error instanceof Error ? error.message : 'Execution failed';
|
|
211
|
+
errors.push({
|
|
212
|
+
type: 'runtime',
|
|
213
|
+
message,
|
|
214
|
+
severity: 'error'
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
// If no executor, use LLM to validate
|
|
220
|
+
if (!this.executeCode && strictness !== 'lenient') {
|
|
221
|
+
const llmValidation = await this.validateWithLLM(code, language);
|
|
222
|
+
errors.push(...llmValidation.errors);
|
|
223
|
+
warnings.push(...llmValidation.warnings);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
return {
|
|
227
|
+
valid: errors.length === 0,
|
|
228
|
+
errors,
|
|
229
|
+
warnings
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* Perform static analysis on code.
|
|
235
|
+
*/
|
|
236
|
+
private performStaticAnalysis(code: string, language: SupportedLanguage): ValidationError[] {
|
|
237
|
+
const errors: ValidationError[] = [];
|
|
238
|
+
|
|
239
|
+
// Language-specific checks
|
|
240
|
+
switch (language) {
|
|
241
|
+
case 'javascript':
|
|
242
|
+
case 'typescript':
|
|
243
|
+
errors.push(...this.analyzeJavaScript(code));
|
|
244
|
+
break;
|
|
245
|
+
case 'python':
|
|
246
|
+
errors.push(...this.analyzePython(code));
|
|
247
|
+
break;
|
|
248
|
+
default:
|
|
249
|
+
errors.push(...this.analyzeGeneric(code));
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
return errors;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
/**
|
|
256
|
+
* Analyze JavaScript/TypeScript code.
|
|
257
|
+
*/
|
|
258
|
+
private analyzeJavaScript(code: string): ValidationError[] {
|
|
259
|
+
const errors: ValidationError[] = [];
|
|
260
|
+
|
|
261
|
+
// Check for common syntax issues
|
|
262
|
+
const patterns = [
|
|
263
|
+
{ pattern: /\bif\s*\([^)]*\)\s*[^{](?!.*[;{])/, message: 'Missing braces after if statement' },
|
|
264
|
+
{ pattern: /\bfor\s*\([^)]*\)\s*[^{](?!.*[;{])/, message: 'Missing braces after for loop' },
|
|
265
|
+
{ pattern: /==(?!=)/, message: 'Use === instead of == for strict equality', isWarning: true },
|
|
266
|
+
{ pattern: /!=(?!=)/, message: 'Use !== instead of != for strict inequality', isWarning: true },
|
|
267
|
+
{ pattern: /\bconsole\.log\(/, message: 'Console.log found - remove for production', isWarning: true }
|
|
268
|
+
];
|
|
269
|
+
|
|
270
|
+
// Check bracket balance
|
|
271
|
+
const bracketBalance = this.checkBracketBalance(code);
|
|
272
|
+
if (!bracketBalance.valid) {
|
|
273
|
+
errors.push({
|
|
274
|
+
type: 'syntax',
|
|
275
|
+
message: bracketBalance.message,
|
|
276
|
+
severity: 'error'
|
|
277
|
+
});
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
// Check patterns
|
|
281
|
+
for (const { pattern, message, isWarning } of patterns) {
|
|
282
|
+
if (pattern.test(code)) {
|
|
283
|
+
errors.push({
|
|
284
|
+
type: isWarning ? 'style' : 'syntax',
|
|
285
|
+
message,
|
|
286
|
+
severity: isWarning ? 'warning' : 'error'
|
|
287
|
+
});
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
return errors;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
/**
|
|
295
|
+
* Analyze Python code.
|
|
296
|
+
*/
|
|
297
|
+
private analyzePython(code: string): ValidationError[] {
|
|
298
|
+
const errors: ValidationError[] = [];
|
|
299
|
+
|
|
300
|
+
// Check indentation consistency
|
|
301
|
+
const lines = code.split('\n');
|
|
302
|
+
let indentUnit: number | null = null;
|
|
303
|
+
|
|
304
|
+
for (let i = 0; i < lines.length; i++) {
|
|
305
|
+
const line = lines[i];
|
|
306
|
+
if (line.trim() === '' || line.trim().startsWith('#')) {
|
|
307
|
+
continue;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
const leadingSpaces = line.match(/^(\s*)/)?.[1].length ?? 0;
|
|
311
|
+
|
|
312
|
+
// Detect indent unit
|
|
313
|
+
if (indentUnit === null && leadingSpaces > 0) {
|
|
314
|
+
indentUnit = leadingSpaces;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
// Check for mixed tabs and spaces
|
|
318
|
+
if (/^\s*\t/.test(line) && /^\s* /.test(line)) {
|
|
319
|
+
errors.push({
|
|
320
|
+
type: 'style',
|
|
321
|
+
message: 'Mixed tabs and spaces in indentation',
|
|
322
|
+
line: i + 1,
|
|
323
|
+
severity: 'warning'
|
|
324
|
+
});
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
// Check for common issues
|
|
329
|
+
if (/\bprint\s+[^(]/.test(code)) {
|
|
330
|
+
errors.push({
|
|
331
|
+
type: 'syntax',
|
|
332
|
+
message: 'Python 2 print statement syntax - use print() function',
|
|
333
|
+
severity: 'error'
|
|
334
|
+
});
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
return errors;
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
/**
|
|
341
|
+
* Generic code analysis.
|
|
342
|
+
*/
|
|
343
|
+
private analyzeGeneric(code: string): ValidationError[] {
|
|
344
|
+
const errors: ValidationError[] = [];
|
|
345
|
+
|
|
346
|
+
// Check bracket balance
|
|
347
|
+
const bracketBalance = this.checkBracketBalance(code);
|
|
348
|
+
if (!bracketBalance.valid) {
|
|
349
|
+
errors.push({
|
|
350
|
+
type: 'syntax',
|
|
351
|
+
message: bracketBalance.message,
|
|
352
|
+
severity: 'error'
|
|
353
|
+
});
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
return errors;
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
/**
|
|
360
|
+
* Check bracket balance in code.
|
|
361
|
+
*/
|
|
362
|
+
private checkBracketBalance(code: string): { valid: boolean; message: string } {
|
|
363
|
+
const stack: string[] = [];
|
|
364
|
+
const pairs: Record<string, string> = {
|
|
365
|
+
'(': ')',
|
|
366
|
+
'[': ']',
|
|
367
|
+
'{': '}'
|
|
368
|
+
};
|
|
369
|
+
|
|
370
|
+
// Remove strings and comments to avoid false positives
|
|
371
|
+
const cleanCode = code
|
|
372
|
+
.replace(/"[^"\\]*(\\.[^"\\]*)*"/g, '""')
|
|
373
|
+
.replace(/'[^'\\]*(\\.[^'\\]*)*'/g, "''")
|
|
374
|
+
.replace(/`[^`\\]*(\\.[^`\\]*)*`/g, '``')
|
|
375
|
+
.replace(/\/\/.*$/gm, '')
|
|
376
|
+
.replace(/\/\*[\s\S]*?\*\//g, '')
|
|
377
|
+
.replace(/#.*$/gm, '');
|
|
378
|
+
|
|
379
|
+
for (const char of cleanCode) {
|
|
380
|
+
if (char in pairs) {
|
|
381
|
+
stack.push(pairs[char]);
|
|
382
|
+
} else if (Object.values(pairs).includes(char)) {
|
|
383
|
+
if (stack.length === 0 || stack.pop() !== char) {
|
|
384
|
+
return { valid: false, message: `Unmatched bracket: ${char}` };
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
if (stack.length > 0) {
|
|
390
|
+
return { valid: false, message: `Missing closing bracket: ${stack[stack.length - 1]}` };
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
return { valid: true, message: '' };
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
/**
|
|
397
|
+
* Detect runtime errors from execution output.
|
|
398
|
+
*/
|
|
399
|
+
private detectRuntimeErrors(output: string): ValidationError[] {
|
|
400
|
+
const errors: ValidationError[] = [];
|
|
401
|
+
|
|
402
|
+
const errorPatterns = [
|
|
403
|
+
{ pattern: /SyntaxError:\s*(.+)/i, type: 'syntax' as const },
|
|
404
|
+
{ pattern: /ReferenceError:\s*(.+)/i, type: 'runtime' as const },
|
|
405
|
+
{ pattern: /TypeError:\s*(.+)/i, type: 'runtime' as const },
|
|
406
|
+
{ pattern: /RangeError:\s*(.+)/i, type: 'runtime' as const },
|
|
407
|
+
{ pattern: /Error:\s*(.+)/i, type: 'runtime' as const },
|
|
408
|
+
{ pattern: /Exception:\s*(.+)/i, type: 'runtime' as const },
|
|
409
|
+
{ pattern: /Traceback \(most recent call last\)/i, type: 'runtime' as const }
|
|
410
|
+
];
|
|
411
|
+
|
|
412
|
+
for (const { pattern, type } of errorPatterns) {
|
|
413
|
+
const match = output.match(pattern);
|
|
414
|
+
if (match) {
|
|
415
|
+
errors.push({
|
|
416
|
+
type,
|
|
417
|
+
message: match[1] || match[0],
|
|
418
|
+
severity: 'error'
|
|
419
|
+
});
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
return errors;
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
/**
|
|
427
|
+
* Use LLM to validate code.
|
|
428
|
+
*/
|
|
429
|
+
private async validateWithLLM(
|
|
430
|
+
code: string,
|
|
431
|
+
language: SupportedLanguage
|
|
432
|
+
): Promise<{ errors: ValidationError[]; warnings: ValidationError[] }> {
|
|
433
|
+
const prompt = `Analyze this ${language} code for errors. Only report actual bugs, not style preferences.
|
|
434
|
+
Return JSON format: {"errors": [{"message": "...", "line": N, "type": "syntax|runtime|logic"}], "warnings": [{"message": "..."}]}
|
|
435
|
+
If no errors, return: {"errors": [], "warnings": []}
|
|
436
|
+
|
|
437
|
+
Code:
|
|
438
|
+
\`\`\`${language}
|
|
439
|
+
${code}
|
|
440
|
+
\`\`\`
|
|
441
|
+
|
|
442
|
+
Respond ONLY with the JSON object, no other text.`;
|
|
443
|
+
|
|
444
|
+
try {
|
|
445
|
+
const result = await this.generateText(prompt);
|
|
446
|
+
const parsed = JSON.parse(result.text);
|
|
447
|
+
|
|
448
|
+
return {
|
|
449
|
+
errors: (parsed.errors || []).map((e: { message: string; line?: number; type?: string }) => {
|
|
450
|
+
return {
|
|
451
|
+
type: e.type || 'logic',
|
|
452
|
+
message: e.message,
|
|
453
|
+
line: e.line,
|
|
454
|
+
severity: 'error' as const
|
|
455
|
+
};
|
|
456
|
+
}),
|
|
457
|
+
warnings: (parsed.warnings || []).map((w: { message: string }) => {
|
|
458
|
+
return {
|
|
459
|
+
type: 'style' as const,
|
|
460
|
+
message: w.message,
|
|
461
|
+
severity: 'warning' as const
|
|
462
|
+
};
|
|
463
|
+
})
|
|
464
|
+
};
|
|
465
|
+
} catch {
|
|
466
|
+
// LLM validation failed, return empty
|
|
467
|
+
return { errors: [], warnings: [] };
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
/**
|
|
472
|
+
* Attempt to fix errors in code.
|
|
473
|
+
*/
|
|
474
|
+
private async attemptFix(
|
|
475
|
+
code: string,
|
|
476
|
+
errors: ValidationError[],
|
|
477
|
+
language: SupportedLanguage,
|
|
478
|
+
originalPrompt: string
|
|
479
|
+
): Promise<{ fixed: boolean; code: string }> {
|
|
480
|
+
const errorList = errors.map((e) => `- ${e.type}: ${e.message}${e.line ? ` (line ${e.line})` : ''}`).join('\n');
|
|
481
|
+
|
|
482
|
+
const prompt = `Fix the following errors in this ${language} code.
|
|
483
|
+
|
|
484
|
+
${originalPrompt ? `Original request: ${originalPrompt}\n` : ''}
|
|
485
|
+
Errors to fix:
|
|
486
|
+
${errorList}
|
|
487
|
+
|
|
488
|
+
Current code:
|
|
489
|
+
\`\`\`${language}
|
|
490
|
+
${code}
|
|
491
|
+
\`\`\`
|
|
492
|
+
|
|
493
|
+
Provide ONLY the fixed code wrapped in a code block. No explanations.`;
|
|
494
|
+
|
|
495
|
+
try {
|
|
496
|
+
const result = await this.generateText(prompt);
|
|
497
|
+
const extractedCode = extractPrimaryCode(result.text);
|
|
498
|
+
|
|
499
|
+
if (extractedCode && extractedCode !== code) {
|
|
500
|
+
return { fixed: true, code: extractedCode };
|
|
501
|
+
}
|
|
502
|
+
} catch {
|
|
503
|
+
// Fix attempt failed
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
return { fixed: false, code };
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
// ============================================================================
|
|
511
|
+
// Utility Functions
|
|
512
|
+
// ============================================================================
|
|
513
|
+
|
|
514
|
+
/**
|
|
515
|
+
* Create a simple validation result for code that passed without issues.
|
|
516
|
+
*/
|
|
517
|
+
export function createPassedValidationResult(code: string, language: string, output?: string): ValidationResult {
|
|
518
|
+
return {
|
|
519
|
+
valid: true,
|
|
520
|
+
errors: [],
|
|
521
|
+
warnings: [],
|
|
522
|
+
output,
|
|
523
|
+
attempts: 1,
|
|
524
|
+
finalCode: code,
|
|
525
|
+
originalCode: code,
|
|
526
|
+
language
|
|
527
|
+
};
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
/**
|
|
531
|
+
* Create a validation result for code that failed.
|
|
532
|
+
*/
|
|
533
|
+
export function createFailedValidationResult(
|
|
534
|
+
code: string,
|
|
535
|
+
language: string,
|
|
536
|
+
errors: ValidationError[]
|
|
537
|
+
): ValidationResult {
|
|
538
|
+
return {
|
|
539
|
+
valid: false,
|
|
540
|
+
errors,
|
|
541
|
+
warnings: [],
|
|
542
|
+
attempts: 1,
|
|
543
|
+
finalCode: code,
|
|
544
|
+
originalCode: code,
|
|
545
|
+
language
|
|
546
|
+
};
|
|
547
|
+
}
|
package/src/core/errors.ts
CHANGED
|
@@ -138,3 +138,94 @@ export class KimiContextLengthError extends KimiError {
|
|
|
138
138
|
this.name = 'KimiContextLengthError';
|
|
139
139
|
}
|
|
140
140
|
}
|
|
141
|
+
|
|
142
|
+
// ============================================================================
|
|
143
|
+
// Ensemble Errors
|
|
144
|
+
// ============================================================================
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Error thrown when ensemble configuration is invalid.
|
|
148
|
+
*/
|
|
149
|
+
export class KimiEnsembleValidationError extends KimiError {
|
|
150
|
+
readonly config: unknown;
|
|
151
|
+
readonly modelId: string;
|
|
152
|
+
|
|
153
|
+
constructor(message: string, config: unknown, modelId: string) {
|
|
154
|
+
super(message, 'ensemble_validation_error', 400);
|
|
155
|
+
this.name = 'KimiEnsembleValidationError';
|
|
156
|
+
this.config = config;
|
|
157
|
+
this.modelId = modelId;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Error thrown when ensemble generation times out.
|
|
163
|
+
*/
|
|
164
|
+
export class KimiEnsembleTimeoutError extends KimiError {
|
|
165
|
+
readonly completedSamples: number;
|
|
166
|
+
readonly requestedSamples: number;
|
|
167
|
+
|
|
168
|
+
constructor(message: string, completedSamples: number, requestedSamples: number) {
|
|
169
|
+
super(message, 'ensemble_timeout', 408);
|
|
170
|
+
this.name = 'KimiEnsembleTimeoutError';
|
|
171
|
+
this.completedSamples = completedSamples;
|
|
172
|
+
this.requestedSamples = requestedSamples;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// ============================================================================
|
|
177
|
+
// Multi-Agent Errors
|
|
178
|
+
// ============================================================================
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Error thrown when a multi-agent workflow fails.
|
|
182
|
+
*/
|
|
183
|
+
export class KimiMultiAgentError extends KimiError {
|
|
184
|
+
readonly workflow: string;
|
|
185
|
+
readonly step: number;
|
|
186
|
+
readonly stepError?: Error;
|
|
187
|
+
|
|
188
|
+
constructor(message: string, workflow: string, step: number, stepError?: Error) {
|
|
189
|
+
super(message, 'multi_agent_error', 500);
|
|
190
|
+
this.name = 'KimiMultiAgentError';
|
|
191
|
+
this.workflow = workflow;
|
|
192
|
+
this.step = step;
|
|
193
|
+
this.stepError = stepError;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// ============================================================================
|
|
198
|
+
// Code Validation Errors
|
|
199
|
+
// ============================================================================
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Error thrown when code validation fails.
|
|
203
|
+
*/
|
|
204
|
+
export class KimiCodeValidationError extends KimiError {
|
|
205
|
+
readonly validationErrors: string[];
|
|
206
|
+
readonly attempts: number;
|
|
207
|
+
|
|
208
|
+
constructor(message: string, validationErrors: string[], attempts: number) {
|
|
209
|
+
super(message, 'code_validation_error', 400);
|
|
210
|
+
this.name = 'KimiCodeValidationError';
|
|
211
|
+
this.validationErrors = validationErrors;
|
|
212
|
+
this.attempts = attempts;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// ============================================================================
|
|
217
|
+
// Project Scaffolding Errors
|
|
218
|
+
// ============================================================================
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* Error thrown when project scaffolding fails.
|
|
222
|
+
*/
|
|
223
|
+
export class KimiScaffoldError extends KimiError {
|
|
224
|
+
readonly projectType?: string;
|
|
225
|
+
|
|
226
|
+
constructor(message: string, projectType?: string) {
|
|
227
|
+
super(message, 'scaffold_error', 500);
|
|
228
|
+
this.name = 'KimiScaffoldError';
|
|
229
|
+
this.projectType = projectType;
|
|
230
|
+
}
|
|
231
|
+
}
|
package/src/core/index.ts
CHANGED
|
@@ -13,24 +13,36 @@ export type {
|
|
|
13
13
|
KimiTokenUsage
|
|
14
14
|
} from './types';
|
|
15
15
|
// Utilities
|
|
16
|
-
export type { KimiExtendedUsage } from './utils';
|
|
16
|
+
export type { KimiExtendedUsage, ReasoningAnalysis } from './utils';
|
|
17
17
|
// Errors
|
|
18
18
|
export {
|
|
19
19
|
KimiAuthenticationError,
|
|
20
|
+
KimiCodeValidationError,
|
|
20
21
|
KimiContentFilterError,
|
|
21
22
|
KimiContextLengthError,
|
|
23
|
+
KimiEnsembleTimeoutError,
|
|
24
|
+
KimiEnsembleValidationError,
|
|
22
25
|
KimiError,
|
|
23
26
|
KimiModelNotFoundError,
|
|
27
|
+
KimiMultiAgentError,
|
|
24
28
|
KimiRateLimitError,
|
|
29
|
+
KimiScaffoldError,
|
|
25
30
|
KimiValidationError,
|
|
26
31
|
kimiErrorSchema,
|
|
27
32
|
kimiFailedResponseHandler
|
|
28
33
|
} from './errors';
|
|
29
|
-
export { inferModelCapabilities } from './types';
|
|
30
34
|
export {
|
|
35
|
+
STANDARD_MODEL_DEFAULT_MAX_TOKENS,
|
|
36
|
+
THINKING_MODEL_DEFAULT_MAX_TOKENS,
|
|
37
|
+
THINKING_MODEL_TEMPERATURE,
|
|
38
|
+
inferModelCapabilities
|
|
39
|
+
} from './types';
|
|
40
|
+
export {
|
|
41
|
+
analyzeReasoningPreservation,
|
|
31
42
|
convertKimiUsage,
|
|
32
43
|
extractMessageContent,
|
|
33
44
|
getKimiRequestId,
|
|
34
45
|
getResponseMetadata,
|
|
35
|
-
mapKimiFinishReason
|
|
46
|
+
mapKimiFinishReason,
|
|
47
|
+
recommendThinkingModel
|
|
36
48
|
} from './utils';
|