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.
Files changed (44) hide show
  1. package/README.md +567 -17
  2. package/dist/index.d.mts +1750 -3
  3. package/dist/index.d.ts +1750 -3
  4. package/dist/index.js +2317 -161
  5. package/dist/index.js.map +1 -1
  6. package/dist/index.mjs +2292 -160
  7. package/dist/index.mjs.map +1 -1
  8. package/package.json +1 -1
  9. package/src/__tests__/auto-detect.test.ts +140 -0
  10. package/src/__tests__/code-validation.test.ts +267 -0
  11. package/src/__tests__/ensemble.test.ts +242 -0
  12. package/src/__tests__/file-cache.test.ts +310 -0
  13. package/src/__tests__/model-config.test.ts +120 -0
  14. package/src/__tests__/multi-agent.test.ts +201 -0
  15. package/src/__tests__/project-tools.test.ts +181 -0
  16. package/src/__tests__/reasoning-utils.test.ts +164 -0
  17. package/src/__tests__/tools.test.ts +76 -8
  18. package/src/chat/kimi-chat-language-model.ts +21 -2
  19. package/src/chat/kimi-chat-settings.ts +15 -1
  20. package/src/code-validation/detector.ts +319 -0
  21. package/src/code-validation/index.ts +31 -0
  22. package/src/code-validation/types.ts +291 -0
  23. package/src/code-validation/validator.ts +547 -0
  24. package/src/core/errors.ts +91 -0
  25. package/src/core/index.ts +15 -3
  26. package/src/core/types.ts +57 -2
  27. package/src/core/utils.ts +138 -0
  28. package/src/ensemble/index.ts +17 -0
  29. package/src/ensemble/multi-sampler.ts +433 -0
  30. package/src/ensemble/types.ts +279 -0
  31. package/src/files/attachment-processor.ts +51 -4
  32. package/src/files/file-cache.ts +260 -0
  33. package/src/files/index.ts +16 -1
  34. package/src/index.ts +102 -3
  35. package/src/kimi-provider.ts +354 -1
  36. package/src/multi-agent/index.ts +21 -0
  37. package/src/multi-agent/types.ts +312 -0
  38. package/src/multi-agent/workflows.ts +539 -0
  39. package/src/project-tools/index.ts +16 -0
  40. package/src/project-tools/scaffolder.ts +494 -0
  41. package/src/project-tools/types.ts +244 -0
  42. package/src/tools/auto-detect.ts +276 -0
  43. package/src/tools/index.ts +6 -2
  44. package/src/tools/prepare-tools.ts +179 -4
package/dist/index.js CHANGED
@@ -20,6 +20,8 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // src/index.ts
21
21
  var index_exports = {};
22
22
  __export(index_exports, {
23
+ CodeValidator: () => CodeValidator,
24
+ DEFAULT_SYSTEM_PROMPTS: () => DEFAULT_SYSTEM_PROMPTS,
23
25
  KIMI_CODE_BASE_URL: () => KIMI_CODE_BASE_URL,
24
26
  KIMI_CODE_DEFAULT_MODEL: () => KIMI_CODE_DEFAULT_MODEL,
25
27
  KIMI_CODE_INTERPRETER_TOOL_NAME: () => KIMI_CODE_INTERPRETER_TOOL_NAME,
@@ -28,22 +30,43 @@ __export(index_exports, {
28
30
  KimiAuthenticationError: () => KimiAuthenticationError,
29
31
  KimiChatLanguageModel: () => KimiChatLanguageModel,
30
32
  KimiCodeLanguageModel: () => KimiCodeLanguageModel,
33
+ KimiCodeValidationError: () => KimiCodeValidationError,
31
34
  KimiContentFilterError: () => KimiContentFilterError,
32
35
  KimiContextLengthError: () => KimiContextLengthError,
36
+ KimiEnsembleTimeoutError: () => KimiEnsembleTimeoutError,
37
+ KimiEnsembleValidationError: () => KimiEnsembleValidationError,
33
38
  KimiError: () => KimiError,
34
39
  KimiFileClient: () => KimiFileClient,
35
40
  KimiModelNotFoundError: () => KimiModelNotFoundError,
41
+ KimiMultiAgentError: () => KimiMultiAgentError,
36
42
  KimiRateLimitError: () => KimiRateLimitError,
43
+ KimiScaffoldError: () => KimiScaffoldError,
37
44
  KimiValidationError: () => KimiValidationError,
45
+ MultiSampler: () => MultiSampler,
46
+ ProjectScaffolder: () => ProjectScaffolder,
38
47
  SUPPORTED_FILE_EXTENSIONS: () => SUPPORTED_FILE_EXTENSIONS,
39
48
  SUPPORTED_MIME_TYPES: () => SUPPORTED_MIME_TYPES,
49
+ WorkflowRunner: () => WorkflowRunner,
50
+ containsCode: () => containsCode,
40
51
  createCodeInterpreterTool: () => createCodeInterpreterTool,
52
+ createEmptyMultiAgentResult: () => createEmptyMultiAgentResult,
53
+ createEmptyScaffoldResult: () => createEmptyScaffoldResult,
54
+ createFailedValidationResult: () => createFailedValidationResult,
41
55
  createKimi: () => createKimi,
42
56
  createKimiCode: () => createKimiCode,
43
57
  createKimiWebSearchTool: () => createKimiWebSearchTool,
58
+ createPassedValidationResult: () => createPassedValidationResult,
59
+ createSingletonEnsembleResult: () => createSingletonEnsembleResult,
44
60
  createWebSearchTool: () => createWebSearchTool,
61
+ detectLanguage: () => detectLanguage,
62
+ detectToolsFromPrompt: () => detectToolsFromPrompt,
63
+ extractCodeBlocks: () => extractCodeBlocks,
64
+ extractPrimaryCode: () => extractPrimaryCode,
65
+ generateToolGuidanceMessage: () => generateToolGuidanceMessage,
66
+ getFileExtension: () => getFileExtension,
45
67
  getMediaTypeFromExtension: () => getMediaTypeFromExtension,
46
68
  getPurposeFromMediaType: () => getPurposeFromMediaType,
69
+ hasToolOptOut: () => hasToolOptOut,
47
70
  inferKimiCodeCapabilities: () => inferKimiCodeCapabilities,
48
71
  inferModelCapabilities: () => inferModelCapabilities,
49
72
  isDocumentMediaType: () => isDocumentMediaType,
@@ -56,7 +79,8 @@ __export(index_exports, {
56
79
  kimiCodeProviderOptionsSchema: () => kimiCodeProviderOptionsSchema,
57
80
  kimiProviderOptionsSchema: () => kimiProviderOptionsSchema,
58
81
  kimiTools: () => kimiTools,
59
- processAttachments: () => processAttachments
82
+ processAttachments: () => processAttachments,
83
+ shouldAutoEnableTools: () => shouldAutoEnableTools
60
84
  });
61
85
  module.exports = __toCommonJS(index_exports);
62
86
 
@@ -142,8 +166,51 @@ var KimiContextLengthError = class extends KimiError {
142
166
  this.name = "KimiContextLengthError";
143
167
  }
144
168
  };
169
+ var KimiEnsembleValidationError = class extends KimiError {
170
+ constructor(message, config, modelId) {
171
+ super(message, "ensemble_validation_error", 400);
172
+ this.name = "KimiEnsembleValidationError";
173
+ this.config = config;
174
+ this.modelId = modelId;
175
+ }
176
+ };
177
+ var KimiEnsembleTimeoutError = class extends KimiError {
178
+ constructor(message, completedSamples, requestedSamples) {
179
+ super(message, "ensemble_timeout", 408);
180
+ this.name = "KimiEnsembleTimeoutError";
181
+ this.completedSamples = completedSamples;
182
+ this.requestedSamples = requestedSamples;
183
+ }
184
+ };
185
+ var KimiMultiAgentError = class extends KimiError {
186
+ constructor(message, workflow, step, stepError) {
187
+ super(message, "multi_agent_error", 500);
188
+ this.name = "KimiMultiAgentError";
189
+ this.workflow = workflow;
190
+ this.step = step;
191
+ this.stepError = stepError;
192
+ }
193
+ };
194
+ var KimiCodeValidationError = class extends KimiError {
195
+ constructor(message, validationErrors, attempts) {
196
+ super(message, "code_validation_error", 400);
197
+ this.name = "KimiCodeValidationError";
198
+ this.validationErrors = validationErrors;
199
+ this.attempts = attempts;
200
+ }
201
+ };
202
+ var KimiScaffoldError = class extends KimiError {
203
+ constructor(message, projectType) {
204
+ super(message, "scaffold_error", 500);
205
+ this.name = "KimiScaffoldError";
206
+ this.projectType = projectType;
207
+ }
208
+ };
145
209
 
146
210
  // src/core/types.ts
211
+ var THINKING_MODEL_TEMPERATURE = 1;
212
+ var THINKING_MODEL_DEFAULT_MAX_TOKENS = 32768;
213
+ var STANDARD_MODEL_DEFAULT_MAX_TOKENS = 4096;
147
214
  function inferModelCapabilities(modelId) {
148
215
  const isThinkingModel = modelId.includes("-thinking");
149
216
  const isK25Model = modelId.includes("k2.5") || modelId.includes("k2-5");
@@ -158,7 +225,12 @@ function inferModelCapabilities(modelId) {
158
225
  // 256k context window
159
226
  toolCalling: true,
160
227
  jsonMode: true,
161
- structuredOutputs: true
228
+ structuredOutputs: true,
229
+ // Thinking models require temperature=1.0 for optimal reasoning
230
+ defaultTemperature: isThinkingModel ? THINKING_MODEL_TEMPERATURE : void 0,
231
+ temperatureLocked: isThinkingModel,
232
+ // Thinking models need higher token limits to avoid truncated reasoning
233
+ defaultMaxOutputTokens: isThinkingModel ? THINKING_MODEL_DEFAULT_MAX_TOKENS : STANDARD_MODEL_DEFAULT_MAX_TOKENS
162
234
  };
163
235
  }
164
236
 
@@ -277,6 +349,131 @@ function extractMessageContent(message) {
277
349
  return { text, reasoning };
278
350
  }
279
351
 
352
+ // src/tools/auto-detect.ts
353
+ var WEB_SEARCH_PATTERNS = [
354
+ // Direct search requests
355
+ { pattern: /search\s+(for|the\s+web|online|internet)/i, weight: 1, name: "direct_search" },
356
+ { pattern: /look\s+up\b/i, weight: 0.9, name: "look_up" },
357
+ { pattern: /find\s+(information|info|data|details)\s+(about|on|regarding)/i, weight: 0.9, name: "find_info" },
358
+ // Real-time/current information
359
+ {
360
+ pattern: /\b(latest|current|recent|today'?s?|now)\b.*\b(news|price|weather|update|version|status)/i,
361
+ weight: 1,
362
+ name: "current_info"
363
+ },
364
+ { pattern: /what\s+(is|are)\s+the\s+(latest|current|newest)/i, weight: 0.95, name: "what_latest" },
365
+ { pattern: /\b(right\s+now|at\s+the\s+moment|currently)\b/i, weight: 0.7, name: "temporal" },
366
+ // News and events
367
+ { pattern: /\bnews\b.*\b(about|on|regarding)\b/i, weight: 0.85, name: "news_about" },
368
+ { pattern: /what('?s|\s+is)\s+happening\b/i, weight: 0.8, name: "happening" },
369
+ { pattern: /\b(headline|breaking|trending)\b/i, weight: 0.85, name: "headlines" },
370
+ // Prices and markets
371
+ { pattern: /\b(price|cost|rate)\s+of\b/i, weight: 0.7, name: "price" },
372
+ { pattern: /\b(stock|crypto|bitcoin|ethereum|btc|eth)\s+(price|value|market)/i, weight: 0.95, name: "crypto_stock" },
373
+ { pattern: /how\s+much\s+(does|is|are).*\b(cost|worth)\b/i, weight: 0.7, name: "how_much" },
374
+ // Weather
375
+ { pattern: /\bweather\b.*\b(in|at|for|today|tomorrow|forecast)\b/i, weight: 0.95, name: "weather" },
376
+ // Documentation and APIs
377
+ { pattern: /\bdocumentation\b.*\b(for|of|about)\b/i, weight: 0.6, name: "documentation" },
378
+ { pattern: /official\s+(website|docs|documentation|guide)/i, weight: 0.7, name: "official_docs" },
379
+ // Verification needs
380
+ { pattern: /\b(verify|confirm|check|fact-check)\b.*\b(true|accurate|correct|real)\b/i, weight: 0.75, name: "verify" },
381
+ // Comparisons with external data
382
+ { pattern: /\bcompare\b.*\b(prices|reviews|ratings|options)\b/i, weight: 0.65, name: "compare" }
383
+ ];
384
+ var CODE_INTERPRETER_PATTERNS = [
385
+ // Direct code requests
386
+ { pattern: /write\s+(a\s+)?(function|code|script|program|algorithm)/i, weight: 0.95, name: "write_code" },
387
+ { pattern: /\b(code|implement|program)\s+(this|that|the|a)/i, weight: 0.85, name: "code_this" },
388
+ { pattern: /create\s+(a\s+)?(script|function|class|module)/i, weight: 0.9, name: "create_script" },
389
+ // Mathematical calculations
390
+ { pattern: /\bcalculate\b.*\d+/i, weight: 0.9, name: "calculate" },
391
+ { pattern: /\b(compute|evaluate|solve)\b.*\b(equation|expression|formula|problem)\b/i, weight: 0.9, name: "compute" },
392
+ { pattern: /what\s+(is|are)\s+\d+[\s+\-*/^]+\d+/i, weight: 0.95, name: "arithmetic" },
393
+ { pattern: /\b(factorial|fibonacci|prime|sqrt|power|exponent)\b/i, weight: 0.85, name: "math_functions" },
394
+ // Data processing
395
+ {
396
+ pattern: /\b(parse|process|transform|convert)\s+(this\s+)?(data|json|csv|xml)/i,
397
+ weight: 0.85,
398
+ name: "data_processing"
399
+ },
400
+ { pattern: /\b(analyze|process)\s+(this\s+)?(file|dataset|table)/i, weight: 0.8, name: "analyze_data" },
401
+ // Debugging
402
+ { pattern: /\bdebug\b.*\b(this|my|the)\s+(code|function|script|program)/i, weight: 0.9, name: "debug" },
403
+ { pattern: /\b(fix|correct|repair)\s+(this|my|the)\s+(error|bug|issue|problem)\b/i, weight: 0.85, name: "fix_error" },
404
+ {
405
+ pattern: /why\s+(is|does)\s+(this|my)\s+(code|function)\s+(not\s+work|fail|error)/i,
406
+ weight: 0.9,
407
+ name: "why_not_work"
408
+ },
409
+ // Testing
410
+ {
411
+ pattern: /\b(test|verify|validate)\s+(this|my|the)\s+(code|function|implementation)/i,
412
+ weight: 0.85,
413
+ name: "test_code"
414
+ },
415
+ { pattern: /\brun\s+(this|my|the)\s+(code|script|program)/i, weight: 0.95, name: "run_code" },
416
+ { pattern: /\bexecute\b.*\b(code|script|command)/i, weight: 0.95, name: "execute" },
417
+ // Code blocks in input (handles various markdown formats)
418
+ { pattern: /```[\w]*[\s\S]*?```/, weight: 0.7, name: "code_block" },
419
+ // Algorithm requests
420
+ { pattern: /\b(sort|search|traverse|optimize)\s+(algorithm|function|method)/i, weight: 0.85, name: "algorithm" },
421
+ // Regex
422
+ { pattern: /\b(regex|regular\s+expression)\b/i, weight: 0.75, name: "regex" },
423
+ // File operations
424
+ { pattern: /\b(read|write|create|delete)\s+(a\s+)?(file|directory|folder)/i, weight: 0.7, name: "file_ops" }
425
+ ];
426
+ function detectToolsFromPrompt(prompt, config = {}) {
427
+ const { confidenceThreshold = 0.3, includePartialMatches = true } = config;
428
+ const webSearchResult = detectPatterns(prompt, WEB_SEARCH_PATTERNS, includePartialMatches);
429
+ const codeInterpreterResult = detectPatterns(prompt, CODE_INTERPRETER_PATTERNS, includePartialMatches);
430
+ return {
431
+ webSearch: webSearchResult.confidence >= confidenceThreshold,
432
+ codeInterpreter: codeInterpreterResult.confidence >= confidenceThreshold,
433
+ webSearchConfidence: webSearchResult.confidence,
434
+ codeInterpreterConfidence: codeInterpreterResult.confidence,
435
+ webSearchMatches: webSearchResult.matches,
436
+ codeInterpreterMatches: codeInterpreterResult.matches
437
+ };
438
+ }
439
+ function shouldAutoEnableTools(prompt) {
440
+ const result = detectToolsFromPrompt(prompt);
441
+ return {
442
+ webSearch: result.webSearch,
443
+ codeInterpreter: result.codeInterpreter
444
+ };
445
+ }
446
+ function detectPatterns(text, patterns, includePartial) {
447
+ const matches = [];
448
+ let maxWeight = 0;
449
+ let matchCount = 0;
450
+ for (const { pattern, weight, name } of patterns) {
451
+ if (pattern.test(text)) {
452
+ matches.push(name);
453
+ maxWeight = Math.max(maxWeight, weight);
454
+ matchCount++;
455
+ }
456
+ }
457
+ let confidence = 0;
458
+ if (matchCount > 0) {
459
+ if (includePartial) {
460
+ const boost = Math.min(0.15, (matchCount - 1) * 0.05);
461
+ confidence = Math.min(1, maxWeight + boost);
462
+ } else {
463
+ confidence = maxWeight;
464
+ }
465
+ }
466
+ return { confidence, matches };
467
+ }
468
+ function hasToolOptOut(prompt) {
469
+ const webSearchOptOut = /(don'?t|do\s+not|without|no)\s+(search(ing)?|web|internet|online)/i.test(prompt);
470
+ const codeOptOut = /(don'?t|do\s+not|without|no)\s+(run(ning)?|execut(e|ing)|cod(e|ing))/i.test(prompt) || /without\s+[\w\s]*running\s+code/i.test(prompt) || /(or|and)\s+running\s+code/i.test(prompt);
471
+ return {
472
+ webSearch: webSearchOptOut,
473
+ codeInterpreter: codeOptOut
474
+ };
475
+ }
476
+
280
477
  // src/tools/builtin-tools.ts
281
478
  var KIMI_WEB_SEARCH_TOOL_NAME = "$web_search";
282
479
  var KIMI_CODE_INTERPRETER_TOOL_NAME = "$code";
@@ -395,13 +592,15 @@ function prepareKimiTools({
395
592
  });
396
593
  continue;
397
594
  }
595
+ const sanitizedSchema = sanitizeToolSchema(tool.inputSchema);
398
596
  kimiTools2.push({
399
597
  type: "function",
400
598
  function: {
401
599
  name: tool.name,
402
600
  description: tool.description,
403
- parameters: tool.inputSchema,
404
- ...tool.strict != null ? { strict: tool.strict } : {}
601
+ parameters: sanitizedSchema
602
+ // Don't pass strict mode to Kimi - it may cause issues
603
+ // ...(tool.strict != null ? { strict: tool.strict } : {})
405
604
  }
406
605
  });
407
606
  }
@@ -469,11 +668,104 @@ function prepareKimiTools({
469
668
  }
470
669
  }
471
670
  }
671
+ var TOOL_DESCRIPTIONS = {
672
+ $web_search: "Search the web for up-to-date information, current events, facts, news, prices, weather, or any data not available in your training",
673
+ $code: "Execute code to perform calculations, data processing, algorithmic tasks, or verify code correctness"
674
+ };
675
+ function generateToolGuidanceMessage(options) {
676
+ const { toolNames, choiceType, targetTool, promptContext, includeDescriptions = true } = options;
677
+ const lines = ["=== TOOL USAGE GUIDANCE ===", ""];
678
+ if (includeDescriptions && toolNames.length > 0) {
679
+ lines.push("Available tools:");
680
+ for (const toolName of toolNames) {
681
+ const description = TOOL_DESCRIPTIONS[toolName] || "Execute this tool";
682
+ lines.push(`- ${toolName}: ${description}`);
683
+ }
684
+ lines.push("");
685
+ }
686
+ if (choiceType === "required") {
687
+ lines.push("\u26A0\uFE0F IMPORTANT: You MUST use at least one of the available tools to respond.");
688
+ lines.push("Do NOT provide a direct text response without first calling a tool.");
689
+ } else if (choiceType === "tool" && targetTool) {
690
+ lines.push(`\u26A0\uFE0F IMPORTANT: You MUST use the "${targetTool}" tool to respond.`);
691
+ lines.push("Do NOT use any other tool or provide a direct text response.");
692
+ }
693
+ if (promptContext) {
694
+ lines.push("");
695
+ lines.push(`Task context: ${promptContext.slice(0, 200)}${promptContext.length > 200 ? "..." : ""}`);
696
+ }
697
+ return lines.join("\n");
698
+ }
472
699
  function generateRequiredToolMessage(toolNames) {
473
- return `IMPORTANT INSTRUCTION: You MUST use one of the available tools (${toolNames}) to respond to the user's request. Do NOT provide a direct text response without first calling a tool. Always invoke a tool to complete this task.`;
700
+ const tools = toolNames.split(", ");
701
+ return generateToolGuidanceMessage({
702
+ toolNames: tools,
703
+ choiceType: "required",
704
+ includeDescriptions: true
705
+ });
474
706
  }
475
707
  function generateSpecificToolMessage(toolName) {
476
- return `IMPORTANT INSTRUCTION: You MUST use the "${toolName}" tool to respond to this request. Do NOT use any other tool or provide a direct text response. Call the "${toolName}" tool with appropriate parameters.`;
708
+ return generateToolGuidanceMessage({
709
+ toolNames: [toolName],
710
+ choiceType: "tool",
711
+ targetTool: toolName,
712
+ includeDescriptions: true
713
+ });
714
+ }
715
+ var UNSUPPORTED_SCHEMA_KEYWORDS = [
716
+ "$schema",
717
+ "$id",
718
+ "$ref",
719
+ "$defs",
720
+ "definitions",
721
+ "if",
722
+ "then",
723
+ "else",
724
+ "allOf",
725
+ "anyOf",
726
+ "oneOf",
727
+ "not",
728
+ "patternProperties",
729
+ "additionalItems",
730
+ "contains",
731
+ "propertyNames",
732
+ "const",
733
+ "contentMediaType",
734
+ "contentEncoding",
735
+ "examples",
736
+ "$comment"
737
+ ];
738
+ function sanitizeToolSchema(schema) {
739
+ if (schema === null || schema === void 0) {
740
+ return schema;
741
+ }
742
+ if (Array.isArray(schema)) {
743
+ return schema.map(sanitizeToolSchema);
744
+ }
745
+ if (typeof schema !== "object") {
746
+ return schema;
747
+ }
748
+ const sanitized = {};
749
+ const schemaObj = schema;
750
+ for (const [key, value] of Object.entries(schemaObj)) {
751
+ if (UNSUPPORTED_SCHEMA_KEYWORDS.includes(key)) {
752
+ continue;
753
+ }
754
+ if (key === "properties" && typeof value === "object" && value !== null) {
755
+ const props = {};
756
+ for (const [propKey, propValue] of Object.entries(value)) {
757
+ props[propKey] = sanitizeToolSchema(propValue);
758
+ }
759
+ sanitized[key] = props;
760
+ } else if (key === "items" && typeof value === "object") {
761
+ sanitized[key] = sanitizeToolSchema(value);
762
+ } else if (key === "additionalProperties" && typeof value === "object") {
763
+ sanitized[key] = sanitizeToolSchema(value);
764
+ } else {
765
+ sanitized[key] = value;
766
+ }
767
+ }
768
+ return sanitized;
477
769
  }
478
770
  function tryConvertToKimiBuiltinTool(tool) {
479
771
  if (!tool.id.startsWith("kimi.")) {
@@ -762,7 +1054,11 @@ var kimiProviderOptionsSchema = import_v42.z.object({
762
1054
  /**
763
1055
  * Enable tool choice polyfill for this request.
764
1056
  */
765
- toolChoicePolyfill: import_v42.z.boolean().optional()
1057
+ toolChoicePolyfill: import_v42.z.boolean().optional(),
1058
+ /**
1059
+ * Auto-enable tools based on prompt content analysis.
1060
+ */
1061
+ autoEnableTools: import_v42.z.boolean().optional()
766
1062
  });
767
1063
 
768
1064
  // src/chat/kimi-chat-language-model.ts
@@ -876,11 +1172,24 @@ var KimiChatLanguageModel = class {
876
1172
  if (toolChoiceSystemMessage) {
877
1173
  messages.unshift({ role: "system", content: toolChoiceSystemMessage });
878
1174
  }
1175
+ const caps = this.capabilities;
1176
+ let resolvedTemperature = temperature;
1177
+ if (caps.temperatureLocked && caps.defaultTemperature !== void 0) {
1178
+ if (temperature !== void 0 && temperature !== caps.defaultTemperature) {
1179
+ warnings.push({
1180
+ type: "compatibility",
1181
+ feature: "temperature",
1182
+ details: `Thinking models require temperature=${caps.defaultTemperature}. Your value (${temperature}) will be overridden.`
1183
+ });
1184
+ }
1185
+ resolvedTemperature = caps.defaultTemperature;
1186
+ }
1187
+ const resolvedMaxTokens = maxOutputTokens ?? caps.defaultMaxOutputTokens;
879
1188
  const body = (0, import_provider_utils3.removeUndefinedEntries)({
880
1189
  model: this.modelId,
881
1190
  messages,
882
- max_tokens: maxOutputTokens,
883
- temperature,
1191
+ max_tokens: resolvedMaxTokens,
1192
+ temperature: resolvedTemperature,
884
1193
  top_p: topP,
885
1194
  frequency_penalty: frequencyPenalty,
886
1195
  presence_penalty: presencePenalty,
@@ -1365,163 +1674,1145 @@ var kimiChatChunkBaseSchema = import_v43.z.looseObject({
1365
1674
  });
1366
1675
  var kimiChatChunkSchema = import_v43.z.union([kimiChatChunkBaseSchema, kimiErrorSchema]);
1367
1676
 
1368
- // src/files/file-utils.ts
1369
- var SUPPORTED_FILE_EXTENSIONS = [
1370
- // Documents
1371
- ".pdf",
1372
- ".txt",
1373
- ".csv",
1374
- ".doc",
1375
- ".docx",
1376
- ".xls",
1377
- ".xlsx",
1378
- ".ppt",
1379
- ".pptx",
1380
- ".md",
1381
- ".epub",
1382
- ".mobi",
1383
- ".html",
1384
- ".json",
1385
- ".log",
1386
- ".dot",
1387
- ".ini",
1388
- ".conf",
1389
- ".yaml",
1390
- ".yml",
1391
- // Images
1392
- ".jpeg",
1393
- ".jpg",
1394
- ".png",
1395
- ".bmp",
1396
- ".gif",
1397
- ".svg",
1398
- ".svgz",
1399
- ".webp",
1400
- ".ico",
1401
- ".xbm",
1402
- ".dib",
1403
- ".pjp",
1404
- ".tif",
1405
- ".tiff",
1406
- ".pjpeg",
1407
- ".avif",
1408
- ".apng",
1409
- ".jfif",
1410
- // Code files
1411
- ".go",
1412
- ".h",
1413
- ".c",
1414
- ".cpp",
1415
- ".cxx",
1416
- ".cc",
1417
- ".cs",
1418
- ".java",
1419
- ".js",
1420
- ".css",
1421
- ".jsp",
1422
- ".php",
1423
- ".py",
1424
- ".py3",
1425
- ".asp",
1426
- ".ts",
1427
- ".tsx"
1677
+ // src/code-validation/detector.ts
1678
+ var LANGUAGE_PATTERNS = [
1679
+ {
1680
+ language: "typescript",
1681
+ patterns: [
1682
+ { pattern: /:\s*(string|number|boolean|void|any|unknown|never)\b/, weight: 0.9, name: "type_annotation" },
1683
+ { pattern: /interface\s+\w+\s*{/, weight: 0.95, name: "interface" },
1684
+ { pattern: /type\s+\w+\s*=/, weight: 0.9, name: "type_alias" },
1685
+ { pattern: /<\w+>/, weight: 0.5, name: "generics" },
1686
+ { pattern: /import\s+.*\s+from\s+['"]/, weight: 0.7, name: "import_from" },
1687
+ { pattern: /export\s+(interface|type|enum)\b/, weight: 0.95, name: "export_type" },
1688
+ { pattern: /as\s+(string|number|boolean|any)\b/, weight: 0.85, name: "type_assertion" }
1689
+ ]
1690
+ },
1691
+ {
1692
+ language: "javascript",
1693
+ patterns: [
1694
+ { pattern: /\bfunction\s+\w+\s*\(/, weight: 0.6, name: "function_decl" },
1695
+ { pattern: /\bconst\s+\w+\s*=/, weight: 0.5, name: "const" },
1696
+ { pattern: /\blet\s+\w+\s*=/, weight: 0.5, name: "let" },
1697
+ { pattern: /=>\s*{/, weight: 0.6, name: "arrow_function" },
1698
+ { pattern: /require\s*\(['"]/, weight: 0.7, name: "require" },
1699
+ { pattern: /module\.exports\s*=/, weight: 0.85, name: "module_exports" },
1700
+ { pattern: /console\.(log|error|warn)\(/, weight: 0.5, name: "console" }
1701
+ ]
1702
+ },
1703
+ {
1704
+ language: "python",
1705
+ patterns: [
1706
+ { pattern: /\bdef\s+\w+\s*\([^)]*\)\s*:/, weight: 0.9, name: "def" },
1707
+ { pattern: /\bclass\s+\w+.*:/, weight: 0.85, name: "class" },
1708
+ { pattern: /\bimport\s+\w+/, weight: 0.6, name: "import" },
1709
+ { pattern: /\bfrom\s+\w+\s+import\b/, weight: 0.85, name: "from_import" },
1710
+ { pattern: /\bif\s+__name__\s*==\s*['"]__main__['"]\s*:/, weight: 0.95, name: "main_guard" },
1711
+ { pattern: /\bprint\s*\(/, weight: 0.5, name: "print" },
1712
+ { pattern: /\bself\.\w+/, weight: 0.85, name: "self" },
1713
+ { pattern: /#.*$/, weight: 0.3, name: "comment" }
1714
+ ]
1715
+ },
1716
+ {
1717
+ language: "java",
1718
+ patterns: [
1719
+ { pattern: /public\s+class\s+\w+/, weight: 0.95, name: "public_class" },
1720
+ { pattern: /public\s+static\s+void\s+main/, weight: 0.98, name: "main_method" },
1721
+ { pattern: /System\.out\.println/, weight: 0.9, name: "sysout" },
1722
+ { pattern: /\bpackage\s+[\w.]+;/, weight: 0.95, name: "package" },
1723
+ { pattern: /\bimport\s+[\w.]+;/, weight: 0.8, name: "import" },
1724
+ { pattern: /@Override\b/, weight: 0.9, name: "override" },
1725
+ { pattern: /\bprivate\s+\w+\s+\w+;/, weight: 0.7, name: "private_field" }
1726
+ ]
1727
+ },
1728
+ {
1729
+ language: "go",
1730
+ patterns: [
1731
+ { pattern: /\bpackage\s+main\b/, weight: 0.95, name: "package_main" },
1732
+ { pattern: /\bfunc\s+\w+\s*\(/, weight: 0.85, name: "func" },
1733
+ { pattern: /\bfmt\.Print/, weight: 0.9, name: "fmt_print" },
1734
+ { pattern: /\bimport\s+\(/, weight: 0.85, name: "import_block" },
1735
+ { pattern: /:=/, weight: 0.7, name: "short_var_decl" },
1736
+ { pattern: /\bgo\s+\w+\(/, weight: 0.9, name: "goroutine" },
1737
+ { pattern: /\bchan\s+\w+/, weight: 0.9, name: "channel" }
1738
+ ]
1739
+ },
1740
+ {
1741
+ language: "rust",
1742
+ patterns: [
1743
+ { pattern: /\bfn\s+\w+\s*\(/, weight: 0.9, name: "fn" },
1744
+ { pattern: /\blet\s+mut\s+\w+/, weight: 0.95, name: "let_mut" },
1745
+ { pattern: /\bimpl\s+\w+\s+for\s+\w+/, weight: 0.95, name: "impl_for" },
1746
+ { pattern: /\buse\s+[\w:]+;/, weight: 0.85, name: "use" },
1747
+ { pattern: /\bpub\s+(fn|struct|enum|mod)\b/, weight: 0.9, name: "pub" },
1748
+ { pattern: /->.*{/, weight: 0.7, name: "return_type" },
1749
+ { pattern: /\bprintln!\(/, weight: 0.95, name: "println_macro" }
1750
+ ]
1751
+ },
1752
+ {
1753
+ language: "ruby",
1754
+ patterns: [
1755
+ { pattern: /\bdef\s+\w+/, weight: 0.8, name: "def" },
1756
+ { pattern: /\bclass\s+\w+/, weight: 0.7, name: "class" },
1757
+ { pattern: /\bend\s*$/, weight: 0.4, name: "end" },
1758
+ { pattern: /\brequire\s+['"]/, weight: 0.85, name: "require" },
1759
+ { pattern: /\bputs\s+/, weight: 0.8, name: "puts" },
1760
+ { pattern: /@\w+/, weight: 0.5, name: "instance_var" },
1761
+ { pattern: /\.each\s+do\s*\|/, weight: 0.85, name: "each_block" }
1762
+ ]
1763
+ },
1764
+ {
1765
+ language: "php",
1766
+ patterns: [
1767
+ { pattern: /<\?php/, weight: 0.98, name: "php_tag" },
1768
+ { pattern: /\$\w+\s*=/, weight: 0.75, name: "php_var" },
1769
+ { pattern: /\bfunction\s+\w+\s*\(/, weight: 0.5, name: "function" },
1770
+ { pattern: /\becho\s+/, weight: 0.7, name: "echo" },
1771
+ { pattern: /->(\w+)\(/, weight: 0.6, name: "method_call" },
1772
+ { pattern: /\buse\s+[\w\\]+;/, weight: 0.8, name: "use" }
1773
+ ]
1774
+ },
1775
+ {
1776
+ language: "cpp",
1777
+ patterns: [
1778
+ { pattern: /#include\s*<[\w.]+>/, weight: 0.9, name: "include_angle" },
1779
+ { pattern: /#include\s*"[\w.]+"/, weight: 0.85, name: "include_quote" },
1780
+ { pattern: /\bstd::\w+/, weight: 0.9, name: "std_namespace" },
1781
+ { pattern: /\bint\s+main\s*\(/, weight: 0.95, name: "main" },
1782
+ { pattern: /\bcout\s*<</, weight: 0.95, name: "cout" },
1783
+ { pattern: /\bnamespace\s+\w+/, weight: 0.85, name: "namespace" },
1784
+ { pattern: /\btemplate\s*</, weight: 0.9, name: "template" }
1785
+ ]
1786
+ }
1428
1787
  ];
1429
- var SUPPORTED_MIME_TYPES = {
1430
- // Documents
1431
- "application/pdf": "file-extract",
1432
- "text/plain": "file-extract",
1433
- "text/csv": "file-extract",
1434
- "application/msword": "file-extract",
1435
- "application/vnd.openxmlformats-officedocument.wordprocessingml.document": "file-extract",
1436
- "application/vnd.ms-excel": "file-extract",
1437
- "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": "file-extract",
1438
- "application/vnd.ms-powerpoint": "file-extract",
1439
- "application/vnd.openxmlformats-officedocument.presentationml.presentation": "file-extract",
1440
- "text/markdown": "file-extract",
1441
- "text/html": "file-extract",
1442
- "application/json": "file-extract",
1443
- "application/epub+zip": "file-extract",
1444
- "text/yaml": "file-extract",
1445
- "application/x-yaml": "file-extract",
1446
- // Code files (treated as text)
1447
- "text/javascript": "file-extract",
1448
- "text/typescript": "file-extract",
1449
- "text/x-python": "file-extract",
1450
- "text/x-java": "file-extract",
1451
- "text/x-c": "file-extract",
1452
- "text/x-c++": "file-extract",
1453
- "text/css": "file-extract",
1454
- // Images
1455
- "image/jpeg": "image",
1456
- "image/png": "image",
1457
- "image/gif": "image",
1458
- "image/webp": "image",
1459
- "image/svg+xml": "image",
1460
- "image/bmp": "image",
1461
- "image/tiff": "image",
1462
- "image/avif": "image",
1463
- "image/apng": "image",
1464
- "image/x-icon": "image",
1465
- // Videos
1466
- "video/mp4": "video",
1467
- "video/webm": "video",
1468
- "video/ogg": "video",
1469
- "video/quicktime": "video"
1470
- };
1471
- function isImageMediaType2(mediaType) {
1472
- return mediaType.startsWith("image/");
1788
+ function detectLanguage(code) {
1789
+ const scores = /* @__PURE__ */ new Map();
1790
+ for (const { language } of LANGUAGE_PATTERNS) {
1791
+ scores.set(language, { score: 0, indicators: [] });
1792
+ }
1793
+ for (const { language, patterns } of LANGUAGE_PATTERNS) {
1794
+ const langScore = scores.get(language);
1795
+ for (const { pattern, weight, name } of patterns) {
1796
+ if (pattern.test(code)) {
1797
+ langScore.score += weight;
1798
+ langScore.indicators.push(name);
1799
+ }
1800
+ }
1801
+ }
1802
+ let bestLanguage = "javascript";
1803
+ let bestScore = 0;
1804
+ let bestIndicators = [];
1805
+ for (const [language, { score, indicators }] of scores) {
1806
+ if (score > bestScore) {
1807
+ bestScore = score;
1808
+ bestLanguage = language;
1809
+ bestIndicators = indicators;
1810
+ }
1811
+ }
1812
+ const tsScore = scores.get("typescript").score;
1813
+ const jsScore = scores.get("javascript").score;
1814
+ if (tsScore > 0 && jsScore > 0 && Math.abs(tsScore - jsScore) < 0.5 && scores.get("typescript").indicators.some((i) => ["type_annotation", "interface", "type_alias", "export_type"].includes(i))) {
1815
+ bestLanguage = "typescript";
1816
+ bestScore = tsScore;
1817
+ bestIndicators = scores.get("typescript").indicators;
1818
+ }
1819
+ const maxPossibleScore = LANGUAGE_PATTERNS.find((l) => l.language === bestLanguage)?.patterns.reduce((sum, p) => sum + p.weight, 0) ?? 1;
1820
+ const confidence = Math.min(1, bestScore / Math.max(1, maxPossibleScore * 0.5));
1821
+ return {
1822
+ language: bestLanguage,
1823
+ confidence,
1824
+ indicators: bestIndicators
1825
+ };
1473
1826
  }
1474
- function isVideoMediaType2(mediaType) {
1475
- return mediaType.startsWith("video/");
1827
+ function extractCodeBlocks(text) {
1828
+ const blocks = [];
1829
+ const fenceRegex = /```(\w*)\n([\s\S]*?)```/g;
1830
+ let match = fenceRegex.exec(text);
1831
+ while (match !== null) {
1832
+ blocks.push({
1833
+ code: match[2].trim(),
1834
+ language: match[1] || void 0,
1835
+ startIndex: match.index,
1836
+ endIndex: match.index + match[0].length
1837
+ });
1838
+ match = fenceRegex.exec(text);
1839
+ }
1840
+ if (blocks.length === 0) {
1841
+ const { confidence } = detectLanguage(text);
1842
+ if (confidence > 0.3) {
1843
+ blocks.push({
1844
+ code: text.trim(),
1845
+ startIndex: 0,
1846
+ endIndex: text.length
1847
+ });
1848
+ }
1849
+ }
1850
+ return {
1851
+ blocks,
1852
+ hasCode: blocks.length > 0
1853
+ };
1476
1854
  }
1477
- function isFileExtractMediaType(mediaType) {
1478
- if (mediaType in SUPPORTED_MIME_TYPES) {
1479
- return SUPPORTED_MIME_TYPES[mediaType] === "file-extract";
1855
+ function extractPrimaryCode(text) {
1856
+ const { blocks, hasCode } = extractCodeBlocks(text);
1857
+ if (!hasCode) {
1858
+ return void 0;
1480
1859
  }
1481
- if (mediaType.startsWith("text/") || mediaType === "application/pdf") {
1860
+ return blocks.reduce((largest, block) => block.code.length > largest.code.length ? block : largest).code;
1861
+ }
1862
+ function containsCode(text) {
1863
+ if (/```[\s\S]*```/.test(text)) {
1482
1864
  return true;
1483
1865
  }
1484
- return false;
1485
- }
1486
- function isDocumentMediaType(mediaType) {
1487
- const documentTypes = [
1488
- "application/pdf",
1489
- "application/msword",
1490
- "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
1491
- "application/vnd.ms-excel",
1492
- "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
1493
- "application/vnd.ms-powerpoint",
1494
- "application/vnd.openxmlformats-officedocument.presentationml.presentation",
1495
- "application/epub+zip"
1866
+ const quickCodePatterns = [
1867
+ /\bfunction\s+\w+\s*\([^)]*\)\s*\{/,
1868
+ // function declarations
1869
+ /\bconst\s+\w+\s*=\s*\([^)]*\)\s*=>/,
1870
+ // arrow functions
1871
+ /\bclass\s+\w+\s*(\s+extends\s+\w+)?\s*\{/,
1872
+ // class declarations
1873
+ /\bdef\s+\w+\s*\([^)]*\)\s*:/,
1874
+ // Python functions
1875
+ /\bimport\s+.*\s+from\s+['"]/,
1876
+ // ES imports
1877
+ /\b(if|for|while)\s*\([^)]*\)\s*\{/,
1878
+ // Control structures with braces
1879
+ /=>\s*\{[\s\S]*\}/,
1880
+ // Arrow function bodies
1881
+ /\breturn\s+[\w"'`{[<]/
1882
+ // Return statements
1496
1883
  ];
1497
- return documentTypes.includes(mediaType);
1884
+ for (const pattern of quickCodePatterns) {
1885
+ if (pattern.test(text)) {
1886
+ return true;
1887
+ }
1888
+ }
1889
+ const { confidence } = detectLanguage(text);
1890
+ return confidence > 0.4;
1498
1891
  }
1499
- function getPurposeFromMediaType(mediaType) {
1500
- if (isImageMediaType2(mediaType)) {
1501
- return "image";
1892
+ function getFileExtension(language) {
1893
+ const extensions = {
1894
+ javascript: "js",
1895
+ typescript: "ts",
1896
+ python: "py",
1897
+ java: "java",
1898
+ cpp: "cpp",
1899
+ go: "go",
1900
+ rust: "rs",
1901
+ ruby: "rb",
1902
+ php: "php",
1903
+ auto: "txt"
1904
+ };
1905
+ return extensions[language] || "txt";
1906
+ }
1907
+
1908
+ // src/code-validation/validator.ts
1909
+ var CodeValidator = class {
1910
+ constructor(options) {
1911
+ this.generateText = options.generateText;
1912
+ this.executeCode = options.executeCode;
1502
1913
  }
1503
- if (isVideoMediaType2(mediaType)) {
1504
- return "video";
1914
+ /**
1915
+ * Validate code and optionally fix errors.
1916
+ *
1917
+ * @param code - The code to validate
1918
+ * @param config - Validation configuration
1919
+ * @param originalPrompt - The original user prompt (for context in fixes)
1920
+ * @returns Validation result
1921
+ */
1922
+ async validate(code, config, originalPrompt = "") {
1923
+ const {
1924
+ maxAttempts = 3,
1925
+ language: configLanguage = "auto",
1926
+ executionTimeoutMs = 3e4,
1927
+ strictness = "strict",
1928
+ returnPartialFix = true
1929
+ } = config;
1930
+ const language = configLanguage === "auto" ? detectLanguage(code).language : configLanguage;
1931
+ let currentCode = code;
1932
+ const allErrors = [];
1933
+ const allWarnings = [];
1934
+ const fixHistory = [];
1935
+ let attempts = 0;
1936
+ for (let i = 0; i < maxAttempts; i++) {
1937
+ attempts++;
1938
+ const validationResult = await this.validateCode(currentCode, language, strictness, executionTimeoutMs);
1939
+ const newErrors = validationResult.errors.filter(
1940
+ (e) => !allErrors.some((existing) => existing.message === e.message)
1941
+ );
1942
+ allErrors.push(...newErrors);
1943
+ allWarnings.push(...validationResult.warnings);
1944
+ if (validationResult.valid) {
1945
+ return {
1946
+ valid: true,
1947
+ errors: [],
1948
+ warnings: allWarnings,
1949
+ output: validationResult.output,
1950
+ executionTimeMs: validationResult.executionTimeMs,
1951
+ attempts,
1952
+ finalCode: currentCode,
1953
+ originalCode: code,
1954
+ language,
1955
+ fixHistory
1956
+ };
1957
+ }
1958
+ if (i === maxAttempts - 1) {
1959
+ break;
1960
+ }
1961
+ const fixResult = await this.attemptFix(currentCode, validationResult.errors, language, originalPrompt);
1962
+ fixHistory.push({
1963
+ attempt: attempts,
1964
+ codeBefore: currentCode,
1965
+ codeAfter: fixResult.code,
1966
+ errorsAddressed: validationResult.errors,
1967
+ success: false
1968
+ // Will be updated if next validation passes
1969
+ });
1970
+ if (fixResult.fixed) {
1971
+ currentCode = fixResult.code;
1972
+ } else {
1973
+ break;
1974
+ }
1975
+ }
1976
+ return {
1977
+ valid: false,
1978
+ errors: allErrors,
1979
+ warnings: allWarnings,
1980
+ attempts,
1981
+ finalCode: returnPartialFix ? currentCode : code,
1982
+ originalCode: code,
1983
+ language,
1984
+ fixHistory
1985
+ };
1505
1986
  }
1506
- return "file-extract";
1507
- }
1508
- function getMediaTypeFromExtension(extension) {
1509
- const ext = extension.toLowerCase().startsWith(".") ? extension.toLowerCase() : `.${extension.toLowerCase()}`;
1510
- const extensionToMime = {
1511
- // Documents
1512
- ".pdf": "application/pdf",
1513
- ".txt": "text/plain",
1514
- ".csv": "text/csv",
1515
- ".doc": "application/msword",
1516
- ".docx": "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
1517
- ".xls": "application/vnd.ms-excel",
1518
- ".xlsx": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
1519
- ".ppt": "application/vnd.ms-powerpoint",
1520
- ".pptx": "application/vnd.openxmlformats-officedocument.presentationml.presentation",
1521
- ".md": "text/markdown",
1522
- ".html": "text/html",
1523
- ".json": "application/json",
1524
- ".epub": "application/epub+zip",
1987
+ /**
1988
+ * Validate code without attempting fixes.
1989
+ */
1990
+ async validateCode(code, language, strictness, _timeoutMs) {
1991
+ const errors = [];
1992
+ const warnings = [];
1993
+ const staticErrors = this.performStaticAnalysis(code, language);
1994
+ errors.push(...staticErrors);
1995
+ if (staticErrors.some((e) => e.type === "syntax" && e.severity === "error")) {
1996
+ return { valid: false, errors, warnings };
1997
+ }
1998
+ if (this.executeCode) {
1999
+ try {
2000
+ const startTime = Date.now();
2001
+ const output = await this.executeCode(code, language);
2002
+ const executionTimeMs = Date.now() - startTime;
2003
+ const runtimeErrors = this.detectRuntimeErrors(output);
2004
+ errors.push(...runtimeErrors);
2005
+ if (runtimeErrors.length === 0) {
2006
+ return {
2007
+ valid: true,
2008
+ errors: [],
2009
+ warnings,
2010
+ output,
2011
+ executionTimeMs
2012
+ };
2013
+ }
2014
+ } catch (error) {
2015
+ const message = error instanceof Error ? error.message : "Execution failed";
2016
+ errors.push({
2017
+ type: "runtime",
2018
+ message,
2019
+ severity: "error"
2020
+ });
2021
+ }
2022
+ }
2023
+ if (!this.executeCode && strictness !== "lenient") {
2024
+ const llmValidation = await this.validateWithLLM(code, language);
2025
+ errors.push(...llmValidation.errors);
2026
+ warnings.push(...llmValidation.warnings);
2027
+ }
2028
+ return {
2029
+ valid: errors.length === 0,
2030
+ errors,
2031
+ warnings
2032
+ };
2033
+ }
2034
+ /**
2035
+ * Perform static analysis on code.
2036
+ */
2037
+ performStaticAnalysis(code, language) {
2038
+ const errors = [];
2039
+ switch (language) {
2040
+ case "javascript":
2041
+ case "typescript":
2042
+ errors.push(...this.analyzeJavaScript(code));
2043
+ break;
2044
+ case "python":
2045
+ errors.push(...this.analyzePython(code));
2046
+ break;
2047
+ default:
2048
+ errors.push(...this.analyzeGeneric(code));
2049
+ }
2050
+ return errors;
2051
+ }
2052
+ /**
2053
+ * Analyze JavaScript/TypeScript code.
2054
+ */
2055
+ analyzeJavaScript(code) {
2056
+ const errors = [];
2057
+ const patterns = [
2058
+ { pattern: /\bif\s*\([^)]*\)\s*[^{](?!.*[;{])/, message: "Missing braces after if statement" },
2059
+ { pattern: /\bfor\s*\([^)]*\)\s*[^{](?!.*[;{])/, message: "Missing braces after for loop" },
2060
+ { pattern: /==(?!=)/, message: "Use === instead of == for strict equality", isWarning: true },
2061
+ { pattern: /!=(?!=)/, message: "Use !== instead of != for strict inequality", isWarning: true },
2062
+ { pattern: /\bconsole\.log\(/, message: "Console.log found - remove for production", isWarning: true }
2063
+ ];
2064
+ const bracketBalance = this.checkBracketBalance(code);
2065
+ if (!bracketBalance.valid) {
2066
+ errors.push({
2067
+ type: "syntax",
2068
+ message: bracketBalance.message,
2069
+ severity: "error"
2070
+ });
2071
+ }
2072
+ for (const { pattern, message, isWarning } of patterns) {
2073
+ if (pattern.test(code)) {
2074
+ errors.push({
2075
+ type: isWarning ? "style" : "syntax",
2076
+ message,
2077
+ severity: isWarning ? "warning" : "error"
2078
+ });
2079
+ }
2080
+ }
2081
+ return errors;
2082
+ }
2083
+ /**
2084
+ * Analyze Python code.
2085
+ */
2086
+ analyzePython(code) {
2087
+ const errors = [];
2088
+ const lines = code.split("\n");
2089
+ let indentUnit = null;
2090
+ for (let i = 0; i < lines.length; i++) {
2091
+ const line = lines[i];
2092
+ if (line.trim() === "" || line.trim().startsWith("#")) {
2093
+ continue;
2094
+ }
2095
+ const leadingSpaces = line.match(/^(\s*)/)?.[1].length ?? 0;
2096
+ if (indentUnit === null && leadingSpaces > 0) {
2097
+ indentUnit = leadingSpaces;
2098
+ }
2099
+ if (/^\s*\t/.test(line) && /^\s* /.test(line)) {
2100
+ errors.push({
2101
+ type: "style",
2102
+ message: "Mixed tabs and spaces in indentation",
2103
+ line: i + 1,
2104
+ severity: "warning"
2105
+ });
2106
+ }
2107
+ }
2108
+ if (/\bprint\s+[^(]/.test(code)) {
2109
+ errors.push({
2110
+ type: "syntax",
2111
+ message: "Python 2 print statement syntax - use print() function",
2112
+ severity: "error"
2113
+ });
2114
+ }
2115
+ return errors;
2116
+ }
2117
+ /**
2118
+ * Generic code analysis.
2119
+ */
2120
+ analyzeGeneric(code) {
2121
+ const errors = [];
2122
+ const bracketBalance = this.checkBracketBalance(code);
2123
+ if (!bracketBalance.valid) {
2124
+ errors.push({
2125
+ type: "syntax",
2126
+ message: bracketBalance.message,
2127
+ severity: "error"
2128
+ });
2129
+ }
2130
+ return errors;
2131
+ }
2132
+ /**
2133
+ * Check bracket balance in code.
2134
+ */
2135
+ checkBracketBalance(code) {
2136
+ const stack = [];
2137
+ const pairs = {
2138
+ "(": ")",
2139
+ "[": "]",
2140
+ "{": "}"
2141
+ };
2142
+ const cleanCode = code.replace(/"[^"\\]*(\\.[^"\\]*)*"/g, '""').replace(/'[^'\\]*(\\.[^'\\]*)*'/g, "''").replace(/`[^`\\]*(\\.[^`\\]*)*`/g, "``").replace(/\/\/.*$/gm, "").replace(/\/\*[\s\S]*?\*\//g, "").replace(/#.*$/gm, "");
2143
+ for (const char of cleanCode) {
2144
+ if (char in pairs) {
2145
+ stack.push(pairs[char]);
2146
+ } else if (Object.values(pairs).includes(char)) {
2147
+ if (stack.length === 0 || stack.pop() !== char) {
2148
+ return { valid: false, message: `Unmatched bracket: ${char}` };
2149
+ }
2150
+ }
2151
+ }
2152
+ if (stack.length > 0) {
2153
+ return { valid: false, message: `Missing closing bracket: ${stack[stack.length - 1]}` };
2154
+ }
2155
+ return { valid: true, message: "" };
2156
+ }
2157
+ /**
2158
+ * Detect runtime errors from execution output.
2159
+ */
2160
+ detectRuntimeErrors(output) {
2161
+ const errors = [];
2162
+ const errorPatterns = [
2163
+ { pattern: /SyntaxError:\s*(.+)/i, type: "syntax" },
2164
+ { pattern: /ReferenceError:\s*(.+)/i, type: "runtime" },
2165
+ { pattern: /TypeError:\s*(.+)/i, type: "runtime" },
2166
+ { pattern: /RangeError:\s*(.+)/i, type: "runtime" },
2167
+ { pattern: /Error:\s*(.+)/i, type: "runtime" },
2168
+ { pattern: /Exception:\s*(.+)/i, type: "runtime" },
2169
+ { pattern: /Traceback \(most recent call last\)/i, type: "runtime" }
2170
+ ];
2171
+ for (const { pattern, type } of errorPatterns) {
2172
+ const match = output.match(pattern);
2173
+ if (match) {
2174
+ errors.push({
2175
+ type,
2176
+ message: match[1] || match[0],
2177
+ severity: "error"
2178
+ });
2179
+ }
2180
+ }
2181
+ return errors;
2182
+ }
2183
+ /**
2184
+ * Use LLM to validate code.
2185
+ */
2186
+ async validateWithLLM(code, language) {
2187
+ const prompt = `Analyze this ${language} code for errors. Only report actual bugs, not style preferences.
2188
+ Return JSON format: {"errors": [{"message": "...", "line": N, "type": "syntax|runtime|logic"}], "warnings": [{"message": "..."}]}
2189
+ If no errors, return: {"errors": [], "warnings": []}
2190
+
2191
+ Code:
2192
+ \`\`\`${language}
2193
+ ${code}
2194
+ \`\`\`
2195
+
2196
+ Respond ONLY with the JSON object, no other text.`;
2197
+ try {
2198
+ const result = await this.generateText(prompt);
2199
+ const parsed = JSON.parse(result.text);
2200
+ return {
2201
+ errors: (parsed.errors || []).map((e) => {
2202
+ return {
2203
+ type: e.type || "logic",
2204
+ message: e.message,
2205
+ line: e.line,
2206
+ severity: "error"
2207
+ };
2208
+ }),
2209
+ warnings: (parsed.warnings || []).map((w) => {
2210
+ return {
2211
+ type: "style",
2212
+ message: w.message,
2213
+ severity: "warning"
2214
+ };
2215
+ })
2216
+ };
2217
+ } catch {
2218
+ return { errors: [], warnings: [] };
2219
+ }
2220
+ }
2221
+ /**
2222
+ * Attempt to fix errors in code.
2223
+ */
2224
+ async attemptFix(code, errors, language, originalPrompt) {
2225
+ const errorList = errors.map((e) => `- ${e.type}: ${e.message}${e.line ? ` (line ${e.line})` : ""}`).join("\n");
2226
+ const prompt = `Fix the following errors in this ${language} code.
2227
+
2228
+ ${originalPrompt ? `Original request: ${originalPrompt}
2229
+ ` : ""}
2230
+ Errors to fix:
2231
+ ${errorList}
2232
+
2233
+ Current code:
2234
+ \`\`\`${language}
2235
+ ${code}
2236
+ \`\`\`
2237
+
2238
+ Provide ONLY the fixed code wrapped in a code block. No explanations.`;
2239
+ try {
2240
+ const result = await this.generateText(prompt);
2241
+ const extractedCode = extractPrimaryCode(result.text);
2242
+ if (extractedCode && extractedCode !== code) {
2243
+ return { fixed: true, code: extractedCode };
2244
+ }
2245
+ } catch {
2246
+ }
2247
+ return { fixed: false, code };
2248
+ }
2249
+ };
2250
+ function createPassedValidationResult(code, language, output) {
2251
+ return {
2252
+ valid: true,
2253
+ errors: [],
2254
+ warnings: [],
2255
+ output,
2256
+ attempts: 1,
2257
+ finalCode: code,
2258
+ originalCode: code,
2259
+ language
2260
+ };
2261
+ }
2262
+ function createFailedValidationResult(code, language, errors) {
2263
+ return {
2264
+ valid: false,
2265
+ errors,
2266
+ warnings: [],
2267
+ attempts: 1,
2268
+ finalCode: code,
2269
+ originalCode: code,
2270
+ language
2271
+ };
2272
+ }
2273
+
2274
+ // src/ensemble/multi-sampler.ts
2275
+ var MultiSampler = class {
2276
+ constructor(options) {
2277
+ this.modelId = options.modelId;
2278
+ this.baseTemperature = options.baseTemperature ?? 0.7;
2279
+ }
2280
+ /**
2281
+ * Generate multiple samples and select the best one.
2282
+ *
2283
+ * @param generateFn - Function to generate a single response
2284
+ * @param config - Ensemble configuration
2285
+ * @returns The ensemble result
2286
+ */
2287
+ async generate(generateFn, config) {
2288
+ const startTime = Date.now();
2289
+ const {
2290
+ n,
2291
+ selectionStrategy = "best",
2292
+ temperatureVariance = 0.1,
2293
+ scoringHeuristic = "confidence",
2294
+ customScorer,
2295
+ timeoutMs = 6e4,
2296
+ allowPartialFailure = true,
2297
+ minSuccessfulSamples = 1
2298
+ } = config;
2299
+ if (n < 1 || n > 10) {
2300
+ throw new Error("Ensemble n must be between 1 and 10");
2301
+ }
2302
+ const promises = Array.from({ length: n }, async (_, i) => {
2303
+ const temperature = Math.min(this.baseTemperature + i * temperatureVariance, 2);
2304
+ const sampleStart = Date.now();
2305
+ try {
2306
+ const result2 = await generateFn({ temperature, sampleIndex: i });
2307
+ return {
2308
+ text: result2.text,
2309
+ reasoning: result2.reasoning,
2310
+ toolCalls: result2.toolCalls,
2311
+ toolResults: result2.toolResults,
2312
+ usage: result2.usage,
2313
+ sampleIndex: i,
2314
+ temperature,
2315
+ finishReason: result2.finishReason,
2316
+ success: true,
2317
+ durationMs: Date.now() - sampleStart
2318
+ };
2319
+ } catch (error) {
2320
+ return {
2321
+ text: "",
2322
+ sampleIndex: i,
2323
+ temperature,
2324
+ finishReason: "error",
2325
+ success: false,
2326
+ error: error instanceof Error ? error.message : "Unknown error",
2327
+ durationMs: Date.now() - sampleStart
2328
+ };
2329
+ }
2330
+ });
2331
+ let responses;
2332
+ try {
2333
+ responses = await Promise.race([
2334
+ Promise.all(promises),
2335
+ new Promise(
2336
+ (_, reject) => setTimeout(() => reject(new Error("Ensemble generation timed out")), timeoutMs)
2337
+ )
2338
+ ]);
2339
+ } catch (_error) {
2340
+ const partialResponses = await Promise.all(
2341
+ promises.map(
2342
+ (p) => p.catch(
2343
+ () => ({
2344
+ text: "",
2345
+ sampleIndex: -1,
2346
+ temperature: 0,
2347
+ finishReason: "timeout",
2348
+ success: false,
2349
+ error: "Timed out"
2350
+ })
2351
+ )
2352
+ )
2353
+ );
2354
+ responses = partialResponses.filter((r) => r.sampleIndex >= 0);
2355
+ }
2356
+ const successfulResponses = responses.filter((r) => r.success);
2357
+ if (successfulResponses.length < minSuccessfulSamples && !allowPartialFailure) {
2358
+ throw new Error(
2359
+ `Only ${successfulResponses.length} samples succeeded, minimum required is ${minSuccessfulSamples}`
2360
+ );
2361
+ }
2362
+ if (successfulResponses.length === 0) {
2363
+ throw new Error("All ensemble samples failed");
2364
+ }
2365
+ const result = this.selectBest(successfulResponses, responses, {
2366
+ selectionStrategy,
2367
+ scoringHeuristic,
2368
+ customScorer,
2369
+ modelId: this.modelId,
2370
+ startTime
2371
+ });
2372
+ return result;
2373
+ }
2374
+ /**
2375
+ * Select the best response based on the strategy.
2376
+ */
2377
+ selectBest(successfulResponses, allResponses, options) {
2378
+ const { selectionStrategy, scoringHeuristic, customScorer, modelId, startTime } = options;
2379
+ const scored = successfulResponses.map((r) => {
2380
+ return {
2381
+ ...r,
2382
+ score: this.calculateScore(r, scoringHeuristic, customScorer)
2383
+ };
2384
+ });
2385
+ let winner;
2386
+ let alternatives;
2387
+ switch (selectionStrategy) {
2388
+ case "first":
2389
+ winner = scored[0];
2390
+ break;
2391
+ case "vote":
2392
+ winner = this.majorityVote(scored);
2393
+ break;
2394
+ case "best":
2395
+ scored.sort((a, b) => (b.score ?? 0) - (a.score ?? 0));
2396
+ winner = scored[0];
2397
+ break;
2398
+ case "all":
2399
+ winner = scored[0];
2400
+ alternatives = scored;
2401
+ break;
2402
+ default:
2403
+ throw new Error(`Unknown selection strategy: ${selectionStrategy}`);
2404
+ }
2405
+ const metadata = {
2406
+ nRequested: allResponses.length,
2407
+ nCompleted: successfulResponses.length,
2408
+ nFailed: allResponses.filter((r) => !r.success).length,
2409
+ selectionStrategy,
2410
+ winningIndex: winner.sampleIndex,
2411
+ scores: scored.map((r) => r.score ?? 0),
2412
+ durationMs: Date.now() - startTime,
2413
+ modelId,
2414
+ totalUsage: this.aggregateUsage(successfulResponses)
2415
+ };
2416
+ return {
2417
+ text: winner.text,
2418
+ reasoning: winner.reasoning,
2419
+ toolCalls: winner.toolCalls,
2420
+ toolResults: winner.toolResults,
2421
+ usage: winner.usage ?? { promptTokens: 0, completionTokens: 0, totalTokens: 0 },
2422
+ alternatives,
2423
+ metadata
2424
+ };
2425
+ }
2426
+ /**
2427
+ * Calculate score for a response based on the heuristic.
2428
+ */
2429
+ calculateScore(response, heuristic, customScorer) {
2430
+ switch (heuristic) {
2431
+ case "length":
2432
+ return 1e3 / (response.text.length + 1);
2433
+ case "confidence":
2434
+ return response.usage?.completionTokens ?? 0;
2435
+ case "code":
2436
+ return this.scoreCodeQuality(response.text);
2437
+ case "custom":
2438
+ if (!customScorer) {
2439
+ throw new Error("Custom scorer function required for custom heuristic");
2440
+ }
2441
+ return customScorer(response);
2442
+ default:
2443
+ return 0;
2444
+ }
2445
+ }
2446
+ /**
2447
+ * Score code quality based on heuristics.
2448
+ */
2449
+ scoreCodeQuality(text) {
2450
+ let score = 100;
2451
+ const errorPatterns = [
2452
+ { pattern: /SyntaxError/gi, penalty: 25 },
2453
+ { pattern: /ReferenceError/gi, penalty: 20 },
2454
+ { pattern: /TypeError/gi, penalty: 20 },
2455
+ { pattern: /undefined is not/gi, penalty: 15 },
2456
+ { pattern: /cannot read property/gi, penalty: 15 },
2457
+ { pattern: /is not defined/gi, penalty: 15 },
2458
+ { pattern: /unexpected token/gi, penalty: 20 },
2459
+ { pattern: /null is not/gi, penalty: 15 }
2460
+ ];
2461
+ for (const { pattern, penalty } of errorPatterns) {
2462
+ const matches = text.match(pattern);
2463
+ if (matches) {
2464
+ score -= penalty * matches.length;
2465
+ }
2466
+ }
2467
+ if (text.includes("```")) {
2468
+ score += 10;
2469
+ }
2470
+ if (/\/\/.*|\/\*[\s\S]*?\*\/|#.*/.test(text)) {
2471
+ score += 5;
2472
+ }
2473
+ if (/\b(test|spec|assert|expect|describe|it)\b/i.test(text)) {
2474
+ score += 5;
2475
+ }
2476
+ if (/:\s*(string|number|boolean|void|any|unknown|never)\b/.test(text)) {
2477
+ score += 5;
2478
+ }
2479
+ if (/\b(TODO|FIXME|XXX|HACK)\b/i.test(text)) {
2480
+ score -= 5;
2481
+ }
2482
+ return Math.max(0, score);
2483
+ }
2484
+ /**
2485
+ * Select the most common response (majority voting).
2486
+ */
2487
+ majorityVote(responses) {
2488
+ const normalized = responses.map((r) => {
2489
+ return {
2490
+ response: r,
2491
+ key: r.text.toLowerCase().replace(/\s+/g, " ").trim().slice(0, 500)
2492
+ };
2493
+ });
2494
+ const votes = /* @__PURE__ */ new Map();
2495
+ for (const { response, key } of normalized) {
2496
+ const existing = votes.get(key);
2497
+ if (existing) {
2498
+ existing.count++;
2499
+ } else {
2500
+ votes.set(key, { count: 1, response });
2501
+ }
2502
+ }
2503
+ let maxVotes = 0;
2504
+ let winner = responses[0];
2505
+ for (const { count, response } of votes.values()) {
2506
+ if (count > maxVotes) {
2507
+ maxVotes = count;
2508
+ winner = response;
2509
+ }
2510
+ }
2511
+ return winner;
2512
+ }
2513
+ /**
2514
+ * Aggregate usage across all responses.
2515
+ */
2516
+ aggregateUsage(responses) {
2517
+ return responses.reduce(
2518
+ (acc, r) => {
2519
+ return {
2520
+ promptTokens: acc.promptTokens + (r.usage?.promptTokens ?? 0),
2521
+ completionTokens: acc.completionTokens + (r.usage?.completionTokens ?? 0),
2522
+ totalTokens: acc.totalTokens + (r.usage?.totalTokens ?? 0)
2523
+ };
2524
+ },
2525
+ { promptTokens: 0, completionTokens: 0, totalTokens: 0 }
2526
+ );
2527
+ }
2528
+ };
2529
+ function createSingletonEnsembleResult(response, modelId, durationMs) {
2530
+ return {
2531
+ text: response.text,
2532
+ reasoning: response.reasoning,
2533
+ toolCalls: response.toolCalls,
2534
+ toolResults: response.toolResults,
2535
+ usage: response.usage ?? { promptTokens: 0, completionTokens: 0, totalTokens: 0 },
2536
+ metadata: {
2537
+ nRequested: 1,
2538
+ nCompleted: 1,
2539
+ nFailed: 0,
2540
+ selectionStrategy: "first",
2541
+ winningIndex: 0,
2542
+ scores: [100],
2543
+ durationMs,
2544
+ modelId,
2545
+ totalUsage: response.usage ?? { promptTokens: 0, completionTokens: 0, totalTokens: 0 }
2546
+ }
2547
+ };
2548
+ }
2549
+
2550
+ // src/files/file-cache.ts
2551
+ var FileCache = class {
2552
+ constructor(options = {}) {
2553
+ this.maxSize = options.maxSize ?? 100;
2554
+ this.ttlMs = options.ttlMs ?? 36e5;
2555
+ this.cache = /* @__PURE__ */ new Map();
2556
+ }
2557
+ /**
2558
+ * Get a cached entry by content hash.
2559
+ * Returns undefined if not found or expired.
2560
+ * Moves the entry to the end (most recently used).
2561
+ */
2562
+ get(contentHash) {
2563
+ const entry = this.cache.get(contentHash);
2564
+ if (!entry) {
2565
+ return void 0;
2566
+ }
2567
+ if (this.isExpired(entry)) {
2568
+ this.cache.delete(contentHash);
2569
+ return void 0;
2570
+ }
2571
+ this.cache.delete(contentHash);
2572
+ this.cache.set(contentHash, entry);
2573
+ return entry;
2574
+ }
2575
+ /**
2576
+ * Set a cache entry.
2577
+ * Evicts the least recently used entry if cache is full.
2578
+ */
2579
+ set(contentHash, entry) {
2580
+ this.cache.delete(contentHash);
2581
+ while (this.cache.size >= this.maxSize) {
2582
+ const oldestKey = this.cache.keys().next().value;
2583
+ if (oldestKey !== void 0) {
2584
+ this.cache.delete(oldestKey);
2585
+ } else {
2586
+ break;
2587
+ }
2588
+ }
2589
+ this.cache.set(contentHash, entry);
2590
+ }
2591
+ /**
2592
+ * Check if an entry exists and is not expired.
2593
+ */
2594
+ has(contentHash) {
2595
+ return this.get(contentHash) !== void 0;
2596
+ }
2597
+ /**
2598
+ * Delete a specific entry.
2599
+ */
2600
+ delete(contentHash) {
2601
+ return this.cache.delete(contentHash);
2602
+ }
2603
+ /**
2604
+ * Clear all entries.
2605
+ */
2606
+ clear() {
2607
+ this.cache.clear();
2608
+ }
2609
+ /**
2610
+ * Get the current cache size.
2611
+ */
2612
+ get size() {
2613
+ return this.cache.size;
2614
+ }
2615
+ /**
2616
+ * Remove all expired entries.
2617
+ */
2618
+ prune() {
2619
+ let pruned = 0;
2620
+ for (const [key, entry] of this.cache) {
2621
+ if (this.isExpired(entry)) {
2622
+ this.cache.delete(key);
2623
+ pruned++;
2624
+ }
2625
+ }
2626
+ return pruned;
2627
+ }
2628
+ /**
2629
+ * Check if an entry is expired.
2630
+ */
2631
+ isExpired(entry) {
2632
+ return Date.now() - entry.createdAt > this.ttlMs;
2633
+ }
2634
+ };
2635
+ function generateContentHash(data) {
2636
+ const bytes = typeof data === "string" ? new TextEncoder().encode(data) : data;
2637
+ let hash = 2166136261;
2638
+ for (let i = 0; i < bytes.length; i++) {
2639
+ hash ^= bytes[i];
2640
+ hash = Math.imul(hash, 16777619);
2641
+ }
2642
+ hash ^= bytes.length;
2643
+ return (hash >>> 0).toString(16).padStart(8, "0");
2644
+ }
2645
+ function generateCacheKey(data, filename) {
2646
+ const bytes = typeof data === "string" ? new TextEncoder().encode(data) : data;
2647
+ const contentHash = generateContentHash(data);
2648
+ const normalizedFilename = filename.toLowerCase().replace(/[^a-z0-9.]/g, "_");
2649
+ return `${contentHash}_${bytes.length}_${normalizedFilename}`;
2650
+ }
2651
+ var defaultCache = null;
2652
+ function getDefaultFileCache() {
2653
+ if (!defaultCache) {
2654
+ defaultCache = new FileCache();
2655
+ }
2656
+ return defaultCache;
2657
+ }
2658
+
2659
+ // src/files/file-utils.ts
2660
+ var SUPPORTED_FILE_EXTENSIONS = [
2661
+ // Documents
2662
+ ".pdf",
2663
+ ".txt",
2664
+ ".csv",
2665
+ ".doc",
2666
+ ".docx",
2667
+ ".xls",
2668
+ ".xlsx",
2669
+ ".ppt",
2670
+ ".pptx",
2671
+ ".md",
2672
+ ".epub",
2673
+ ".mobi",
2674
+ ".html",
2675
+ ".json",
2676
+ ".log",
2677
+ ".dot",
2678
+ ".ini",
2679
+ ".conf",
2680
+ ".yaml",
2681
+ ".yml",
2682
+ // Images
2683
+ ".jpeg",
2684
+ ".jpg",
2685
+ ".png",
2686
+ ".bmp",
2687
+ ".gif",
2688
+ ".svg",
2689
+ ".svgz",
2690
+ ".webp",
2691
+ ".ico",
2692
+ ".xbm",
2693
+ ".dib",
2694
+ ".pjp",
2695
+ ".tif",
2696
+ ".tiff",
2697
+ ".pjpeg",
2698
+ ".avif",
2699
+ ".apng",
2700
+ ".jfif",
2701
+ // Code files
2702
+ ".go",
2703
+ ".h",
2704
+ ".c",
2705
+ ".cpp",
2706
+ ".cxx",
2707
+ ".cc",
2708
+ ".cs",
2709
+ ".java",
2710
+ ".js",
2711
+ ".css",
2712
+ ".jsp",
2713
+ ".php",
2714
+ ".py",
2715
+ ".py3",
2716
+ ".asp",
2717
+ ".ts",
2718
+ ".tsx"
2719
+ ];
2720
+ var SUPPORTED_MIME_TYPES = {
2721
+ // Documents
2722
+ "application/pdf": "file-extract",
2723
+ "text/plain": "file-extract",
2724
+ "text/csv": "file-extract",
2725
+ "application/msword": "file-extract",
2726
+ "application/vnd.openxmlformats-officedocument.wordprocessingml.document": "file-extract",
2727
+ "application/vnd.ms-excel": "file-extract",
2728
+ "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": "file-extract",
2729
+ "application/vnd.ms-powerpoint": "file-extract",
2730
+ "application/vnd.openxmlformats-officedocument.presentationml.presentation": "file-extract",
2731
+ "text/markdown": "file-extract",
2732
+ "text/html": "file-extract",
2733
+ "application/json": "file-extract",
2734
+ "application/epub+zip": "file-extract",
2735
+ "text/yaml": "file-extract",
2736
+ "application/x-yaml": "file-extract",
2737
+ // Code files (treated as text)
2738
+ "text/javascript": "file-extract",
2739
+ "text/typescript": "file-extract",
2740
+ "text/x-python": "file-extract",
2741
+ "text/x-java": "file-extract",
2742
+ "text/x-c": "file-extract",
2743
+ "text/x-c++": "file-extract",
2744
+ "text/css": "file-extract",
2745
+ // Images
2746
+ "image/jpeg": "image",
2747
+ "image/png": "image",
2748
+ "image/gif": "image",
2749
+ "image/webp": "image",
2750
+ "image/svg+xml": "image",
2751
+ "image/bmp": "image",
2752
+ "image/tiff": "image",
2753
+ "image/avif": "image",
2754
+ "image/apng": "image",
2755
+ "image/x-icon": "image",
2756
+ // Videos
2757
+ "video/mp4": "video",
2758
+ "video/webm": "video",
2759
+ "video/ogg": "video",
2760
+ "video/quicktime": "video"
2761
+ };
2762
+ function isImageMediaType2(mediaType) {
2763
+ return mediaType.startsWith("image/");
2764
+ }
2765
+ function isVideoMediaType2(mediaType) {
2766
+ return mediaType.startsWith("video/");
2767
+ }
2768
+ function isFileExtractMediaType(mediaType) {
2769
+ if (mediaType in SUPPORTED_MIME_TYPES) {
2770
+ return SUPPORTED_MIME_TYPES[mediaType] === "file-extract";
2771
+ }
2772
+ if (mediaType.startsWith("text/") || mediaType === "application/pdf") {
2773
+ return true;
2774
+ }
2775
+ return false;
2776
+ }
2777
+ function isDocumentMediaType(mediaType) {
2778
+ const documentTypes = [
2779
+ "application/pdf",
2780
+ "application/msword",
2781
+ "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
2782
+ "application/vnd.ms-excel",
2783
+ "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
2784
+ "application/vnd.ms-powerpoint",
2785
+ "application/vnd.openxmlformats-officedocument.presentationml.presentation",
2786
+ "application/epub+zip"
2787
+ ];
2788
+ return documentTypes.includes(mediaType);
2789
+ }
2790
+ function getPurposeFromMediaType(mediaType) {
2791
+ if (isImageMediaType2(mediaType)) {
2792
+ return "image";
2793
+ }
2794
+ if (isVideoMediaType2(mediaType)) {
2795
+ return "video";
2796
+ }
2797
+ return "file-extract";
2798
+ }
2799
+ function getMediaTypeFromExtension(extension) {
2800
+ const ext = extension.toLowerCase().startsWith(".") ? extension.toLowerCase() : `.${extension.toLowerCase()}`;
2801
+ const extensionToMime = {
2802
+ // Documents
2803
+ ".pdf": "application/pdf",
2804
+ ".txt": "text/plain",
2805
+ ".csv": "text/csv",
2806
+ ".doc": "application/msword",
2807
+ ".docx": "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
2808
+ ".xls": "application/vnd.ms-excel",
2809
+ ".xlsx": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
2810
+ ".ppt": "application/vnd.ms-powerpoint",
2811
+ ".pptx": "application/vnd.openxmlformats-officedocument.presentationml.presentation",
2812
+ ".md": "text/markdown",
2813
+ ".html": "text/html",
2814
+ ".json": "application/json",
2815
+ ".epub": "application/epub+zip",
1525
2816
  ".yaml": "text/yaml",
1526
2817
  ".yml": "text/yaml",
1527
2818
  ".log": "text/plain",
@@ -1720,8 +3011,10 @@ async function processAttachments(options) {
1720
3011
  clientConfig,
1721
3012
  autoUploadDocuments = true,
1722
3013
  uploadImages = false,
1723
- cleanupAfterExtract = false
3014
+ cleanupAfterExtract = false,
3015
+ cache = false
1724
3016
  } = options;
3017
+ const cacheInstance = cache === true ? getDefaultFileCache() : cache === false ? null : cache;
1725
3018
  const results = [];
1726
3019
  const client = new KimiFileClient(clientConfig);
1727
3020
  for (const attachment of attachments) {
@@ -1729,7 +3022,8 @@ async function processAttachments(options) {
1729
3022
  const processed = await processAttachment(attachment, client, {
1730
3023
  autoUploadDocuments,
1731
3024
  uploadImages,
1732
- cleanupAfterExtract
3025
+ cleanupAfterExtract,
3026
+ cache: cacheInstance
1733
3027
  });
1734
3028
  results.push(processed);
1735
3029
  } catch (error) {
@@ -1789,12 +3083,35 @@ async function processAttachment(attachment, client, options) {
1789
3083
  error: "No content or URL provided for document attachment"
1790
3084
  };
1791
3085
  }
3086
+ const filename = attachment.name ?? guessFilename(attachment, contentType);
3087
+ if (options.cache) {
3088
+ const cacheKey = generateCacheKey(data, filename);
3089
+ const cached = options.cache.get(cacheKey);
3090
+ if (cached) {
3091
+ return {
3092
+ original: attachment,
3093
+ type: "text-inject",
3094
+ textContent: cached.content,
3095
+ fileId: cached.fileId
3096
+ };
3097
+ }
3098
+ }
1792
3099
  const result = await client.uploadAndExtract({
1793
3100
  data,
1794
- filename: attachment.name ?? guessFilename(attachment, contentType),
3101
+ filename,
1795
3102
  mediaType: contentType,
1796
3103
  purpose: "file-extract"
1797
3104
  });
3105
+ if (options.cache && result.content) {
3106
+ const cacheKey = generateCacheKey(data, filename);
3107
+ const cacheEntry = {
3108
+ fileId: result.file.id,
3109
+ content: result.content,
3110
+ createdAt: Date.now(),
3111
+ purpose: "file-extract"
3112
+ };
3113
+ options.cache.set(cacheKey, cacheEntry);
3114
+ }
1798
3115
  if (options.cleanupAfterExtract && result.file.id) {
1799
3116
  try {
1800
3117
  await client.deleteFile(result.file.id);
@@ -1850,8 +3167,747 @@ function guessFilename(attachment, contentType) {
1850
3167
  return extensionMap[contentType] ?? "file.bin";
1851
3168
  }
1852
3169
 
3170
+ // src/multi-agent/types.ts
3171
+ var DEFAULT_SYSTEM_PROMPTS = {
3172
+ planner: `You are a system architect and planner. Your role is to:
3173
+ 1. Analyze the problem thoroughly
3174
+ 2. Break it down into clear, actionable steps
3175
+ 3. Consider edge cases and potential issues
3176
+ 4. Provide a detailed implementation plan
3177
+
3178
+ Format your response as a numbered list of steps that can be followed to implement the solution.`,
3179
+ executor: `You are an expert implementer. Your role is to:
3180
+ 1. Follow the provided plan precisely
3181
+ 2. Write clean, well-documented code
3182
+ 3. Handle edge cases mentioned in the plan
3183
+ 4. Ensure the implementation is complete and functional
3184
+
3185
+ Provide only the implementation code with necessary comments.`,
3186
+ proposer: `You are a solution architect. Your role is to:
3187
+ 1. Analyze the problem carefully
3188
+ 2. Propose a complete solution
3189
+ 3. Consider best practices and patterns
3190
+ 4. Write clean, maintainable code
3191
+
3192
+ Provide your solution with explanations for key design decisions.`,
3193
+ critic: `You are a code reviewer and critic. Your role is to:
3194
+ 1. Review the proposed solution critically
3195
+ 2. Identify any bugs, errors, or issues
3196
+ 3. Suggest improvements for performance and readability
3197
+ 4. Verify edge cases are handled
3198
+
3199
+ Provide specific, actionable feedback. Be thorough but constructive.`
3200
+ };
3201
+
3202
+ // src/multi-agent/workflows.ts
3203
+ var WorkflowRunner = class {
3204
+ constructor(generateText, validateCode) {
3205
+ this.generateText = generateText;
3206
+ this.validateCode = validateCode;
3207
+ }
3208
+ /**
3209
+ * Run a multi-agent workflow.
3210
+ */
3211
+ async run(prompt, config) {
3212
+ const startTime = Date.now();
3213
+ switch (config.workflow) {
3214
+ case "planner-executor":
3215
+ return this.runPlannerExecutor(prompt, config, startTime);
3216
+ case "proposer-critic":
3217
+ return this.runProposerCritic(prompt, config, startTime);
3218
+ case "debate":
3219
+ return this.runDebate(prompt, config, startTime);
3220
+ case "custom":
3221
+ if (!config.customWorkflow) {
3222
+ throw new Error("Custom workflow requires customWorkflow function");
3223
+ }
3224
+ return this.runCustom(prompt, config, startTime);
3225
+ default:
3226
+ throw new Error(`Unknown workflow type: ${config.workflow}`);
3227
+ }
3228
+ }
3229
+ /**
3230
+ * Planner-Executor workflow.
3231
+ */
3232
+ async runPlannerExecutor(prompt, config, startTime) {
3233
+ const steps = [];
3234
+ let totalUsage = { promptTokens: 0, completionTokens: 0, totalTokens: 0 };
3235
+ const modelA = config.modelA || "kimi-k2.5-thinking";
3236
+ const modelB = config.modelB || "kimi-k2.5";
3237
+ const planStart = Date.now();
3238
+ const plannerPrompt = `${config.systemPrompts?.planner || DEFAULT_SYSTEM_PROMPTS.planner}
3239
+
3240
+ Problem to solve:
3241
+ ${prompt}
3242
+
3243
+ Provide a detailed step-by-step plan.`;
3244
+ const planResult = await this.generateText(modelA, plannerPrompt);
3245
+ steps.push({
3246
+ agent: "A (Planner)",
3247
+ role: "planner",
3248
+ action: "Create implementation plan",
3249
+ input: prompt,
3250
+ output: planResult.text,
3251
+ timestamp: Date.now(),
3252
+ durationMs: Date.now() - planStart,
3253
+ usage: planResult.usage,
3254
+ model: modelA
3255
+ });
3256
+ totalUsage = this.addUsage(totalUsage, planResult.usage);
3257
+ const execStart = Date.now();
3258
+ const executorPrompt = `${config.systemPrompts?.executor || DEFAULT_SYSTEM_PROMPTS.executor}
3259
+
3260
+ Plan to implement:
3261
+ ${planResult.text}
3262
+
3263
+ Original problem: ${prompt}
3264
+
3265
+ Implement the solution following the plan.`;
3266
+ const execResult = await this.generateText(modelB, executorPrompt);
3267
+ steps.push({
3268
+ agent: "B (Executor)",
3269
+ role: "executor",
3270
+ action: "Implement solution",
3271
+ input: planResult.text,
3272
+ output: execResult.text,
3273
+ timestamp: Date.now(),
3274
+ durationMs: Date.now() - execStart,
3275
+ usage: execResult.usage,
3276
+ model: modelB
3277
+ });
3278
+ totalUsage = this.addUsage(totalUsage, execResult.usage);
3279
+ let validation;
3280
+ if (config.validateCode && this.validateCode) {
3281
+ const code = extractPrimaryCode(execResult.text);
3282
+ if (code) {
3283
+ const validStart = Date.now();
3284
+ const validResult = await this.validateCode(code);
3285
+ steps.push({
3286
+ agent: "Validator",
3287
+ role: "validator",
3288
+ action: "Validate code",
3289
+ input: code,
3290
+ output: validResult.valid ? "Code is valid" : `Errors: ${validResult.errors.join(", ")}`,
3291
+ timestamp: Date.now(),
3292
+ durationMs: Date.now() - validStart
3293
+ });
3294
+ validation = {
3295
+ valid: validResult.valid,
3296
+ errors: validResult.errors,
3297
+ finalCode: validResult.fixedCode || code
3298
+ };
3299
+ }
3300
+ }
3301
+ return {
3302
+ text: execResult.text,
3303
+ reasoning: planResult.text,
3304
+ intermediateSteps: steps,
3305
+ usage: totalUsage,
3306
+ metadata: this.buildMetadata(config, steps, startTime, [modelA, modelB]),
3307
+ validation
3308
+ };
3309
+ }
3310
+ /**
3311
+ * Proposer-Critic workflow.
3312
+ */
3313
+ async runProposerCritic(prompt, config, startTime) {
3314
+ const steps = [];
3315
+ let totalUsage = { promptTokens: 0, completionTokens: 0, totalTokens: 0 };
3316
+ const modelA = config.modelA || "kimi-k2.5";
3317
+ const modelB = config.modelB || "kimi-k2.5-thinking";
3318
+ const iterations = config.iterations || 2;
3319
+ let currentSolution = "";
3320
+ let critique = "";
3321
+ for (let i = 0; i < iterations; i++) {
3322
+ const proposeStart = Date.now();
3323
+ const proposerPrompt = i === 0 ? `${config.systemPrompts?.proposer || DEFAULT_SYSTEM_PROMPTS.proposer}
3324
+
3325
+ Problem: ${prompt}
3326
+
3327
+ Provide your solution.` : `${config.systemPrompts?.proposer || DEFAULT_SYSTEM_PROMPTS.proposer}
3328
+
3329
+ Problem: ${prompt}
3330
+
3331
+ Previous solution:
3332
+ ${currentSolution}
3333
+
3334
+ Critique/feedback to address:
3335
+ ${critique}
3336
+
3337
+ Provide an improved solution addressing the feedback.`;
3338
+ const proposeResult = await this.generateText(modelA, proposerPrompt);
3339
+ currentSolution = proposeResult.text;
3340
+ steps.push({
3341
+ agent: "A (Proposer)",
3342
+ role: "proposer",
3343
+ action: `Generate solution (iteration ${i + 1})`,
3344
+ input: i === 0 ? prompt : critique,
3345
+ output: currentSolution,
3346
+ timestamp: Date.now(),
3347
+ durationMs: Date.now() - proposeStart,
3348
+ usage: proposeResult.usage,
3349
+ model: modelA
3350
+ });
3351
+ totalUsage = this.addUsage(totalUsage, proposeResult.usage);
3352
+ if (i < iterations - 1) {
3353
+ const critiqueStart = Date.now();
3354
+ const criticPrompt = `${config.systemPrompts?.critic || DEFAULT_SYSTEM_PROMPTS.critic}
3355
+
3356
+ Original problem: ${prompt}
3357
+
3358
+ Solution to review:
3359
+ ${currentSolution}
3360
+
3361
+ Provide detailed feedback and suggestions for improvement.`;
3362
+ const critiqueResult = await this.generateText(modelB, criticPrompt);
3363
+ critique = critiqueResult.text;
3364
+ steps.push({
3365
+ agent: "B (Critic)",
3366
+ role: "critic",
3367
+ action: `Critique solution (iteration ${i + 1})`,
3368
+ input: currentSolution,
3369
+ output: critique,
3370
+ timestamp: Date.now(),
3371
+ durationMs: Date.now() - critiqueStart,
3372
+ usage: critiqueResult.usage,
3373
+ model: modelB
3374
+ });
3375
+ totalUsage = this.addUsage(totalUsage, critiqueResult.usage);
3376
+ }
3377
+ }
3378
+ let validation;
3379
+ if (config.validateCode && this.validateCode) {
3380
+ const code = extractPrimaryCode(currentSolution);
3381
+ if (code) {
3382
+ const validResult = await this.validateCode(code);
3383
+ validation = {
3384
+ valid: validResult.valid,
3385
+ errors: validResult.errors,
3386
+ finalCode: validResult.fixedCode || code
3387
+ };
3388
+ }
3389
+ }
3390
+ return {
3391
+ text: currentSolution,
3392
+ reasoning: critique,
3393
+ intermediateSteps: steps,
3394
+ usage: totalUsage,
3395
+ metadata: this.buildMetadata(config, steps, startTime, [modelA, modelB]),
3396
+ validation
3397
+ };
3398
+ }
3399
+ /**
3400
+ * Debate workflow.
3401
+ */
3402
+ async runDebate(prompt, config, startTime) {
3403
+ const steps = [];
3404
+ let totalUsage = { promptTokens: 0, completionTokens: 0, totalTokens: 0 };
3405
+ const modelA = config.modelA || "kimi-k2.5";
3406
+ const modelB = config.modelB || "kimi-k2.5";
3407
+ const iterations = config.iterations || 2;
3408
+ let positionA = "";
3409
+ let positionB = "";
3410
+ const initialPrompt = `Problem: ${prompt}
3411
+
3412
+ Provide your solution and reasoning.`;
3413
+ const aStart = Date.now();
3414
+ const aResult = await this.generateText(modelA, initialPrompt);
3415
+ positionA = aResult.text;
3416
+ steps.push({
3417
+ agent: "A",
3418
+ role: "proposer",
3419
+ action: "Initial position",
3420
+ input: prompt,
3421
+ output: positionA,
3422
+ timestamp: Date.now(),
3423
+ durationMs: Date.now() - aStart,
3424
+ usage: aResult.usage,
3425
+ model: modelA
3426
+ });
3427
+ totalUsage = this.addUsage(totalUsage, aResult.usage);
3428
+ const bStart = Date.now();
3429
+ const bResult = await this.generateText(modelB, initialPrompt);
3430
+ positionB = bResult.text;
3431
+ steps.push({
3432
+ agent: "B",
3433
+ role: "proposer",
3434
+ action: "Initial position",
3435
+ input: prompt,
3436
+ output: positionB,
3437
+ timestamp: Date.now(),
3438
+ durationMs: Date.now() - bStart,
3439
+ usage: bResult.usage,
3440
+ model: modelB
3441
+ });
3442
+ totalUsage = this.addUsage(totalUsage, bResult.usage);
3443
+ for (let i = 0; i < iterations - 1; i++) {
3444
+ const aDebateStart = Date.now();
3445
+ const aDebatePrompt = `Problem: ${prompt}
3446
+
3447
+ Your previous position:
3448
+ ${positionA}
3449
+
3450
+ Other perspective:
3451
+ ${positionB}
3452
+
3453
+ Consider the other perspective. Either defend your position with additional reasoning, or revise it based on valid points. Provide your updated solution.`;
3454
+ const aDebateResult = await this.generateText(modelA, aDebatePrompt);
3455
+ positionA = aDebateResult.text;
3456
+ steps.push({
3457
+ agent: "A",
3458
+ role: "proposer",
3459
+ action: `Debate round ${i + 1}`,
3460
+ input: positionB,
3461
+ output: positionA,
3462
+ timestamp: Date.now(),
3463
+ durationMs: Date.now() - aDebateStart,
3464
+ usage: aDebateResult.usage,
3465
+ model: modelA
3466
+ });
3467
+ totalUsage = this.addUsage(totalUsage, aDebateResult.usage);
3468
+ const bDebateStart = Date.now();
3469
+ const bDebatePrompt = `Problem: ${prompt}
3470
+
3471
+ Your previous position:
3472
+ ${positionB}
3473
+
3474
+ Other perspective:
3475
+ ${positionA}
3476
+
3477
+ Consider the other perspective. Either defend your position with additional reasoning, or revise it based on valid points. Provide your updated solution.`;
3478
+ const bDebateResult = await this.generateText(modelB, bDebatePrompt);
3479
+ positionB = bDebateResult.text;
3480
+ steps.push({
3481
+ agent: "B",
3482
+ role: "proposer",
3483
+ action: `Debate round ${i + 1}`,
3484
+ input: positionA,
3485
+ output: positionB,
3486
+ timestamp: Date.now(),
3487
+ durationMs: Date.now() - bDebateStart,
3488
+ usage: bDebateResult.usage,
3489
+ model: modelB
3490
+ });
3491
+ totalUsage = this.addUsage(totalUsage, bDebateResult.usage);
3492
+ }
3493
+ const finalText = positionA.length > positionB.length ? positionA : positionB;
3494
+ return {
3495
+ text: finalText,
3496
+ reasoning: `Debate synthesis from ${iterations} rounds`,
3497
+ intermediateSteps: steps,
3498
+ usage: totalUsage,
3499
+ metadata: this.buildMetadata(config, steps, startTime, [modelA, modelB])
3500
+ };
3501
+ }
3502
+ /**
3503
+ * Custom workflow.
3504
+ */
3505
+ async runCustom(prompt, config, startTime) {
3506
+ const steps = [];
3507
+ const modelA = config.modelA || "kimi-k2.5";
3508
+ const modelB = config.modelB || "kimi-k2.5";
3509
+ const context = {
3510
+ generateWithModelA: (p) => this.generateText(modelA, p),
3511
+ generateWithModelB: (p) => this.generateText(modelB, p),
3512
+ validateCode: this.validateCode,
3513
+ config,
3514
+ addStep: (step) => {
3515
+ steps.push({
3516
+ ...step,
3517
+ timestamp: Date.now(),
3518
+ durationMs: 0
3519
+ });
3520
+ }
3521
+ };
3522
+ const result = await config.customWorkflow(prompt, context);
3523
+ if (result.intermediateSteps.length === 0 && steps.length > 0) {
3524
+ result.intermediateSteps = steps;
3525
+ }
3526
+ result.metadata.durationMs = Date.now() - startTime;
3527
+ return result;
3528
+ }
3529
+ /**
3530
+ * Build metadata for result.
3531
+ */
3532
+ buildMetadata(config, steps, startTime, models) {
3533
+ return {
3534
+ workflow: config.workflow,
3535
+ iterations: steps.length,
3536
+ durationMs: Date.now() - startTime,
3537
+ models: [...new Set(models)],
3538
+ validationEnabled: config.validateCode ?? false,
3539
+ success: true
3540
+ };
3541
+ }
3542
+ /**
3543
+ * Add usage stats.
3544
+ */
3545
+ addUsage(a, b) {
3546
+ if (!b) {
3547
+ return a;
3548
+ }
3549
+ return {
3550
+ promptTokens: a.promptTokens + b.promptTokens,
3551
+ completionTokens: a.completionTokens + b.completionTokens,
3552
+ totalTokens: a.totalTokens + b.totalTokens
3553
+ };
3554
+ }
3555
+ };
3556
+ function createEmptyMultiAgentResult(workflow, error) {
3557
+ return {
3558
+ text: "",
3559
+ intermediateSteps: [],
3560
+ usage: { promptTokens: 0, completionTokens: 0, totalTokens: 0 },
3561
+ metadata: {
3562
+ workflow,
3563
+ iterations: 0,
3564
+ durationMs: 0,
3565
+ models: [],
3566
+ validationEnabled: false,
3567
+ success: false,
3568
+ error
3569
+ }
3570
+ };
3571
+ }
3572
+
3573
+ // src/project-tools/scaffolder.ts
3574
+ var ProjectScaffolder = class {
3575
+ constructor(options) {
3576
+ this.generateText = options.generateText;
3577
+ }
3578
+ /**
3579
+ * Scaffold a new project based on a description.
3580
+ *
3581
+ * @param description - Description of the project to create
3582
+ * @param config - Scaffold configuration
3583
+ * @returns Scaffold result with files and instructions
3584
+ */
3585
+ async scaffold(description, config = {}) {
3586
+ const {
3587
+ type = "auto",
3588
+ includeTests = true,
3589
+ includeCI = false,
3590
+ includeDocs = true,
3591
+ includeDocker = false,
3592
+ includeLinting = true,
3593
+ outputFormat = "files",
3594
+ useTypeScript = true,
3595
+ features = [],
3596
+ customTemplate
3597
+ } = config;
3598
+ const prompt = this.buildScaffoldPrompt(description, {
3599
+ type,
3600
+ includeTests,
3601
+ includeCI,
3602
+ includeDocs,
3603
+ includeDocker,
3604
+ includeLinting,
3605
+ useTypeScript,
3606
+ features,
3607
+ customTemplate
3608
+ });
3609
+ const result = await this.generateText(prompt);
3610
+ const parsed = this.parseResponse(result.text, type);
3611
+ return this.formatResult(parsed, outputFormat, result.text);
3612
+ }
3613
+ /**
3614
+ * Build the scaffold prompt.
3615
+ */
3616
+ buildScaffoldPrompt(description, config) {
3617
+ const parts = [];
3618
+ parts.push("Generate a complete project structure for the following description:");
3619
+ parts.push(`"${description}"`);
3620
+ parts.push("");
3621
+ if (config.type !== "auto") {
3622
+ parts.push(`Framework/Type: ${config.type}`);
3623
+ }
3624
+ parts.push(`Language: ${config.useTypeScript ? "TypeScript" : "JavaScript/Python/Go (as appropriate)"}`);
3625
+ const includes = [];
3626
+ if (config.includeTests) {
3627
+ includes.push("comprehensive test files");
3628
+ }
3629
+ if (config.includeCI) {
3630
+ includes.push("GitHub Actions CI/CD workflow");
3631
+ }
3632
+ if (config.includeDocs) {
3633
+ includes.push("README with setup instructions");
3634
+ }
3635
+ if (config.includeDocker) {
3636
+ includes.push("Dockerfile and docker-compose.yml");
3637
+ }
3638
+ if (config.includeLinting) {
3639
+ includes.push("ESLint/linting configuration");
3640
+ }
3641
+ if (includes.length > 0) {
3642
+ parts.push(`Include: ${includes.join(", ")}`);
3643
+ }
3644
+ if (config.features.length > 0) {
3645
+ parts.push(`Additional features: ${config.features.join(", ")}`);
3646
+ }
3647
+ if (config.customTemplate) {
3648
+ parts.push("");
3649
+ parts.push("Custom requirements:");
3650
+ parts.push(config.customTemplate);
3651
+ }
3652
+ parts.push("");
3653
+ parts.push("Respond with a JSON object in this exact format:");
3654
+ parts.push("```json");
3655
+ parts.push("{");
3656
+ parts.push(' "projectName": "project-name",');
3657
+ parts.push(' "projectType": "detected-type",');
3658
+ parts.push(' "technologies": ["tech1", "tech2"],');
3659
+ parts.push(' "files": [');
3660
+ parts.push(" {");
3661
+ parts.push(' "path": "relative/path/to/file.ts",');
3662
+ parts.push(' "content": "full file content here",');
3663
+ parts.push(' "description": "what this file does"');
3664
+ parts.push(" }");
3665
+ parts.push(" ],");
3666
+ parts.push(' "setupCommands": ["npm install", "npm run dev"],');
3667
+ parts.push(' "estimatedSetupTime": "5 minutes"');
3668
+ parts.push("}");
3669
+ parts.push("```");
3670
+ parts.push("");
3671
+ parts.push(
3672
+ "Include ALL necessary files for a working project: package.json/requirements.txt, source files, config files, etc."
3673
+ );
3674
+ parts.push("Make sure file contents are complete and functional, not placeholders.");
3675
+ return parts.join("\n");
3676
+ }
3677
+ /**
3678
+ * Parse the model response into structured data.
3679
+ */
3680
+ parseResponse(text, defaultType) {
3681
+ const jsonMatch = text.match(/```json\n?([\s\S]*?)```/) || text.match(/\{[\s\S]*"files"[\s\S]*\}/);
3682
+ if (jsonMatch) {
3683
+ try {
3684
+ const json = JSON.parse(jsonMatch[1] || jsonMatch[0]);
3685
+ const files = (json.files || []).map((f) => {
3686
+ return {
3687
+ path: f.path,
3688
+ content: f.content,
3689
+ description: f.description
3690
+ };
3691
+ });
3692
+ let projectType;
3693
+ if (json.projectType) {
3694
+ projectType = json.projectType;
3695
+ } else if (defaultType === "auto") {
3696
+ projectType = this.detectProjectType(files);
3697
+ } else {
3698
+ projectType = defaultType;
3699
+ }
3700
+ return {
3701
+ files,
3702
+ metadata: {
3703
+ projectType,
3704
+ projectName: json.projectName || "my-project",
3705
+ fileCount: files.length,
3706
+ totalSize: files.reduce((sum, f) => sum + (f.content?.length || 0), 0),
3707
+ estimatedSetupTime: json.estimatedSetupTime || "unknown",
3708
+ technologies: json.technologies || [],
3709
+ features: []
3710
+ },
3711
+ setupCommands: json.setupCommands || []
3712
+ };
3713
+ } catch {
3714
+ }
3715
+ }
3716
+ return this.parseFromCodeBlocks(text, defaultType);
3717
+ }
3718
+ /**
3719
+ * Parse files from markdown code blocks.
3720
+ */
3721
+ parseFromCodeBlocks(text, defaultType) {
3722
+ const files = [];
3723
+ const fileBlockRegex = /```(?:(\w+):)?([\w./-]+)\n([\s\S]*?)```/g;
3724
+ let match = fileBlockRegex.exec(text);
3725
+ while (match !== null) {
3726
+ const path = match[2];
3727
+ const content = match[3].trim();
3728
+ if (path.includes(".")) {
3729
+ files.push({
3730
+ path,
3731
+ content,
3732
+ description: void 0
3733
+ });
3734
+ }
3735
+ match = fileBlockRegex.exec(text);
3736
+ }
3737
+ if (files.length === 0) {
3738
+ const genericBlockRegex = /```(\w*)\n([\s\S]*?)```/g;
3739
+ let blockMatch = genericBlockRegex.exec(text);
3740
+ let index = 0;
3741
+ while (blockMatch !== null) {
3742
+ const lang = blockMatch[1] || "txt";
3743
+ const content = blockMatch[2].trim();
3744
+ if (content.length > 10) {
3745
+ const ext = this.getExtensionForLanguage(lang);
3746
+ files.push({
3747
+ path: `file${index}.${ext}`,
3748
+ content
3749
+ });
3750
+ index++;
3751
+ }
3752
+ blockMatch = genericBlockRegex.exec(text);
3753
+ }
3754
+ }
3755
+ return {
3756
+ files,
3757
+ metadata: {
3758
+ projectType: defaultType === "auto" ? this.detectProjectType(files) : defaultType,
3759
+ projectName: "my-project",
3760
+ fileCount: files.length,
3761
+ totalSize: files.reduce((sum, f) => sum + f.content.length, 0),
3762
+ estimatedSetupTime: "unknown",
3763
+ technologies: [],
3764
+ features: []
3765
+ },
3766
+ setupCommands: []
3767
+ };
3768
+ }
3769
+ /**
3770
+ * Detect project type from files.
3771
+ */
3772
+ detectProjectType(files) {
3773
+ const paths = files.map((f) => f.path.toLowerCase());
3774
+ const contents = files.map((f) => f.content);
3775
+ if (paths.some((p) => p.includes("next.config"))) {
3776
+ return "nextjs";
3777
+ }
3778
+ if (contents.some((c) => c.includes("from fastapi"))) {
3779
+ return "fastapi";
3780
+ }
3781
+ if (contents.some((c) => c.includes("from flask"))) {
3782
+ return "flask";
3783
+ }
3784
+ if (paths.some((p) => p.includes("package.json"))) {
3785
+ const pkgFile = files.find((f) => f.path.includes("package.json"));
3786
+ if (pkgFile) {
3787
+ if (pkgFile.content.includes('"react"')) {
3788
+ return "react";
3789
+ }
3790
+ if (pkgFile.content.includes('"vue"')) {
3791
+ return "vue";
3792
+ }
3793
+ if (pkgFile.content.includes('"express"')) {
3794
+ return "express";
3795
+ }
3796
+ if (pkgFile.content.includes('"fastify"')) {
3797
+ return "fastify";
3798
+ }
3799
+ }
3800
+ return "node";
3801
+ }
3802
+ if (paths.some((p) => p.includes("requirements.txt") || p.endsWith(".py"))) {
3803
+ return "python";
3804
+ }
3805
+ if (paths.some((p) => p.includes("go.mod") || p.endsWith(".go"))) {
3806
+ return "go";
3807
+ }
3808
+ if (paths.some((p) => p.includes("cargo.toml") || p.endsWith(".rs"))) {
3809
+ return "rust";
3810
+ }
3811
+ return "node";
3812
+ }
3813
+ /**
3814
+ * Get file extension for a language.
3815
+ */
3816
+ getExtensionForLanguage(lang) {
3817
+ const map = {
3818
+ typescript: "ts",
3819
+ javascript: "js",
3820
+ python: "py",
3821
+ go: "go",
3822
+ rust: "rs",
3823
+ json: "json",
3824
+ yaml: "yml",
3825
+ markdown: "md",
3826
+ html: "html",
3827
+ css: "css",
3828
+ shell: "sh",
3829
+ bash: "sh",
3830
+ dockerfile: "dockerfile",
3831
+ sql: "sql"
3832
+ };
3833
+ return map[lang.toLowerCase()] || "txt";
3834
+ }
3835
+ /**
3836
+ * Format the result based on output format.
3837
+ */
3838
+ formatResult(parsed, format, rawResponse) {
3839
+ const instructions = this.generateInstructions(parsed);
3840
+ return {
3841
+ files: format === "instructions" ? [] : parsed.files,
3842
+ instructions,
3843
+ setupCommands: parsed.setupCommands,
3844
+ metadata: parsed.metadata,
3845
+ rawResponse: format === "json" ? rawResponse : void 0
3846
+ };
3847
+ }
3848
+ /**
3849
+ * Generate setup instructions.
3850
+ */
3851
+ generateInstructions(parsed) {
3852
+ const lines = [];
3853
+ lines.push(`# ${parsed.metadata.projectName} Setup`);
3854
+ lines.push("");
3855
+ lines.push(`Project type: ${parsed.metadata.projectType}`);
3856
+ lines.push(`Files: ${parsed.metadata.fileCount}`);
3857
+ lines.push("");
3858
+ if (parsed.metadata.technologies.length > 0) {
3859
+ lines.push("## Technologies");
3860
+ lines.push(parsed.metadata.technologies.map((t) => `- ${t}`).join("\n"));
3861
+ lines.push("");
3862
+ }
3863
+ lines.push("## Quick Start");
3864
+ lines.push("");
3865
+ lines.push("1. Create project directory:");
3866
+ lines.push("```bash");
3867
+ lines.push(`mkdir ${parsed.metadata.projectName}`);
3868
+ lines.push(`cd ${parsed.metadata.projectName}`);
3869
+ lines.push("```");
3870
+ lines.push("");
3871
+ lines.push("2. Create the following files:");
3872
+ for (const file of parsed.files.slice(0, 10)) {
3873
+ lines.push(` - \`${file.path}\`${file.description ? `: ${file.description}` : ""}`);
3874
+ }
3875
+ if (parsed.files.length > 10) {
3876
+ lines.push(` - ... and ${parsed.files.length - 10} more files`);
3877
+ }
3878
+ lines.push("");
3879
+ if (parsed.setupCommands.length > 0) {
3880
+ lines.push("3. Run setup commands:");
3881
+ lines.push("```bash");
3882
+ lines.push(parsed.setupCommands.join("\n"));
3883
+ lines.push("```");
3884
+ lines.push("");
3885
+ }
3886
+ if (parsed.metadata.estimatedSetupTime !== "unknown") {
3887
+ lines.push(`Estimated setup time: ${parsed.metadata.estimatedSetupTime}`);
3888
+ }
3889
+ return lines.join("\n");
3890
+ }
3891
+ };
3892
+ function createEmptyScaffoldResult(error) {
3893
+ return {
3894
+ files: [],
3895
+ instructions: `Error: ${error}`,
3896
+ setupCommands: [],
3897
+ metadata: {
3898
+ projectType: "auto",
3899
+ projectName: "unknown",
3900
+ fileCount: 0,
3901
+ totalSize: 0,
3902
+ estimatedSetupTime: "unknown",
3903
+ technologies: [],
3904
+ features: []
3905
+ }
3906
+ };
3907
+ }
3908
+
1853
3909
  // src/version.ts
1854
- var VERSION = "0.3.0".length > 0 ? "0.3.0" : "0.0.0";
3910
+ var VERSION = "0.5.0".length > 0 ? "0.5.0" : "0.0.0";
1855
3911
 
1856
3912
  // src/kimi-provider.ts
1857
3913
  var GLOBAL_BASE_URL = "https://api.moonshot.ai/v1";
@@ -1907,6 +3963,82 @@ function createKimi(options = {}) {
1907
3963
  provider.rerankingModel = (modelId) => {
1908
3964
  throw new import_provider4.NoSuchModelError({ modelId, modelType: "rerankingModel" });
1909
3965
  };
3966
+ provider.ensemble = async (prompt, generateFn, ensembleOptions = {}) => {
3967
+ const { model = "kimi-k2.5", baseTemperature = 0.7, ...config } = ensembleOptions;
3968
+ const sampler = new MultiSampler({
3969
+ modelId: model,
3970
+ baseTemperature
3971
+ });
3972
+ const wrappedGenerateFn = async (options2) => {
3973
+ const languageModel = createChatModel(model, {});
3974
+ const result = await generateFn(languageModel, prompt, { temperature: options2.temperature });
3975
+ return {
3976
+ text: result.text,
3977
+ reasoning: result.reasoning,
3978
+ toolCalls: result.toolCalls,
3979
+ toolResults: result.toolResults,
3980
+ usage: result.usage,
3981
+ finishReason: result.finishReason ?? "stop"
3982
+ };
3983
+ };
3984
+ return sampler.generate(wrappedGenerateFn, {
3985
+ n: config.n ?? 3,
3986
+ selectionStrategy: config.selectionStrategy ?? "best",
3987
+ temperatureVariance: config.temperatureVariance ?? 0.1,
3988
+ scoringHeuristic: config.scoringHeuristic ?? "confidence",
3989
+ customScorer: config.customScorer,
3990
+ timeoutMs: config.timeoutMs ?? 6e4,
3991
+ allowPartialFailure: config.allowPartialFailure ?? true,
3992
+ minSuccessfulSamples: config.minSuccessfulSamples ?? 1
3993
+ });
3994
+ };
3995
+ provider.multiAgent = async (prompt, generateFn, agentOptions = {}) => {
3996
+ const { modelSettings, ...config } = agentOptions;
3997
+ const runner = new WorkflowRunner(generateFn);
3998
+ return runner.run(prompt, {
3999
+ workflow: config.workflow ?? "planner-executor",
4000
+ modelA: config.modelA ?? "kimi-k2.5-thinking",
4001
+ modelB: config.modelB ?? "kimi-k2.5",
4002
+ iterations: config.iterations ?? 2,
4003
+ validateCode: config.validateCode ?? false,
4004
+ timeoutMs: config.timeoutMs ?? 12e4,
4005
+ customWorkflow: config.customWorkflow,
4006
+ verbose: config.verbose ?? false,
4007
+ systemPrompts: config.systemPrompts
4008
+ });
4009
+ };
4010
+ provider.validateCode = async (code, generateFn, validateOptions = {}) => {
4011
+ const { model = "kimi-k2.5", modelSettings, ...config } = validateOptions;
4012
+ const languageModel = createChatModel(model, modelSettings);
4013
+ const llmGenerateFn = generateFn ? async (prompt) => generateFn(languageModel, prompt) : async (_prompt) => {
4014
+ return { text: "" };
4015
+ };
4016
+ const validator = new CodeValidator({
4017
+ generateText: llmGenerateFn
4018
+ });
4019
+ return validator.validate(code, {
4020
+ enabled: true,
4021
+ maxAttempts: config.maxAttempts ?? 3,
4022
+ language: config.language ?? "auto",
4023
+ strictness: config.strictness ?? "strict",
4024
+ executionTimeoutMs: config.executionTimeoutMs ?? 3e4,
4025
+ includeTests: config.includeTests ?? true,
4026
+ returnPartialFix: config.returnPartialFix ?? true
4027
+ });
4028
+ };
4029
+ provider.scaffoldProject = async (description, generateFn, scaffoldOptions = {}) => {
4030
+ const scaffolder = new ProjectScaffolder({
4031
+ generateText: generateFn
4032
+ });
4033
+ return scaffolder.scaffold(description, scaffoldOptions);
4034
+ };
4035
+ provider.detectTools = (prompt) => {
4036
+ const result = detectToolsFromPrompt(prompt);
4037
+ return {
4038
+ webSearch: result.webSearch,
4039
+ codeInterpreter: result.codeInterpreter
4040
+ };
4041
+ };
1910
4042
  return provider;
1911
4043
  }
1912
4044
  var kimi = createKimi();
@@ -2740,6 +4872,8 @@ function createKimiCode(options = {}) {
2740
4872
  var kimiCode = createKimiCode();
2741
4873
  // Annotate the CommonJS export names for ESM import in node:
2742
4874
  0 && (module.exports = {
4875
+ CodeValidator,
4876
+ DEFAULT_SYSTEM_PROMPTS,
2743
4877
  KIMI_CODE_BASE_URL,
2744
4878
  KIMI_CODE_DEFAULT_MODEL,
2745
4879
  KIMI_CODE_INTERPRETER_TOOL_NAME,
@@ -2748,22 +4882,43 @@ var kimiCode = createKimiCode();
2748
4882
  KimiAuthenticationError,
2749
4883
  KimiChatLanguageModel,
2750
4884
  KimiCodeLanguageModel,
4885
+ KimiCodeValidationError,
2751
4886
  KimiContentFilterError,
2752
4887
  KimiContextLengthError,
4888
+ KimiEnsembleTimeoutError,
4889
+ KimiEnsembleValidationError,
2753
4890
  KimiError,
2754
4891
  KimiFileClient,
2755
4892
  KimiModelNotFoundError,
4893
+ KimiMultiAgentError,
2756
4894
  KimiRateLimitError,
4895
+ KimiScaffoldError,
2757
4896
  KimiValidationError,
4897
+ MultiSampler,
4898
+ ProjectScaffolder,
2758
4899
  SUPPORTED_FILE_EXTENSIONS,
2759
4900
  SUPPORTED_MIME_TYPES,
4901
+ WorkflowRunner,
4902
+ containsCode,
2760
4903
  createCodeInterpreterTool,
4904
+ createEmptyMultiAgentResult,
4905
+ createEmptyScaffoldResult,
4906
+ createFailedValidationResult,
2761
4907
  createKimi,
2762
4908
  createKimiCode,
2763
4909
  createKimiWebSearchTool,
4910
+ createPassedValidationResult,
4911
+ createSingletonEnsembleResult,
2764
4912
  createWebSearchTool,
4913
+ detectLanguage,
4914
+ detectToolsFromPrompt,
4915
+ extractCodeBlocks,
4916
+ extractPrimaryCode,
4917
+ generateToolGuidanceMessage,
4918
+ getFileExtension,
2765
4919
  getMediaTypeFromExtension,
2766
4920
  getPurposeFromMediaType,
4921
+ hasToolOptOut,
2767
4922
  inferKimiCodeCapabilities,
2768
4923
  inferModelCapabilities,
2769
4924
  isDocumentMediaType,
@@ -2776,6 +4931,7 @@ var kimiCode = createKimiCode();
2776
4931
  kimiCodeProviderOptionsSchema,
2777
4932
  kimiProviderOptionsSchema,
2778
4933
  kimiTools,
2779
- processAttachments
4934
+ processAttachments,
4935
+ shouldAutoEnableTools
2780
4936
  });
2781
4937
  //# sourceMappingURL=index.js.map