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
@@ -0,0 +1,539 @@
1
+ /**
2
+ * Multi-agent workflow implementations.
3
+ * @module
4
+ */
5
+
6
+ import type {
7
+ AgentStep,
8
+ GenerateResult,
9
+ LanguageModelUsage,
10
+ MultiAgentConfig,
11
+ MultiAgentMetadata,
12
+ MultiAgentResult,
13
+ WorkflowContext
14
+ } from './types';
15
+ import { extractPrimaryCode } from '../code-validation/detector';
16
+ import { DEFAULT_SYSTEM_PROMPTS } from './types';
17
+
18
+ // ============================================================================
19
+ // Types
20
+ // ============================================================================
21
+
22
+ /**
23
+ * Function type for generating text.
24
+ */
25
+ export type GenerateTextFunction = (modelId: string, prompt: string, systemPrompt?: string) => Promise<GenerateResult>;
26
+
27
+ /**
28
+ * Function type for validating code.
29
+ */
30
+ export type ValidateCodeFunction = (code: string) => Promise<{
31
+ valid: boolean;
32
+ errors: string[];
33
+ fixedCode?: string;
34
+ }>;
35
+
36
+ /**
37
+ * Options for running a workflow.
38
+ */
39
+ export interface WorkflowRunnerOptions {
40
+ /**
41
+ * The user's prompt.
42
+ */
43
+ prompt: string;
44
+
45
+ /**
46
+ * Workflow configuration.
47
+ */
48
+ config: MultiAgentConfig;
49
+
50
+ /**
51
+ * Function to generate text.
52
+ */
53
+ generateText: GenerateTextFunction;
54
+
55
+ /**
56
+ * Optional function to validate code.
57
+ */
58
+ validateCode?: ValidateCodeFunction;
59
+ }
60
+
61
+ // ============================================================================
62
+ // WorkflowRunner Class
63
+ // ============================================================================
64
+
65
+ /**
66
+ * Runner for multi-agent workflows.
67
+ */
68
+ export class WorkflowRunner {
69
+ private generateText: GenerateTextFunction;
70
+ private validateCode?: ValidateCodeFunction;
71
+
72
+ constructor(generateText: GenerateTextFunction, validateCode?: ValidateCodeFunction) {
73
+ this.generateText = generateText;
74
+ this.validateCode = validateCode;
75
+ }
76
+
77
+ /**
78
+ * Run a multi-agent workflow.
79
+ */
80
+ async run(prompt: string, config: MultiAgentConfig): Promise<MultiAgentResult> {
81
+ const startTime = Date.now();
82
+
83
+ switch (config.workflow) {
84
+ case 'planner-executor':
85
+ return this.runPlannerExecutor(prompt, config, startTime);
86
+
87
+ case 'proposer-critic':
88
+ return this.runProposerCritic(prompt, config, startTime);
89
+
90
+ case 'debate':
91
+ return this.runDebate(prompt, config, startTime);
92
+
93
+ case 'custom':
94
+ if (!config.customWorkflow) {
95
+ throw new Error('Custom workflow requires customWorkflow function');
96
+ }
97
+ return this.runCustom(prompt, config, startTime);
98
+
99
+ default:
100
+ throw new Error(`Unknown workflow type: ${config.workflow}`);
101
+ }
102
+ }
103
+
104
+ /**
105
+ * Planner-Executor workflow.
106
+ */
107
+ private async runPlannerExecutor(
108
+ prompt: string,
109
+ config: MultiAgentConfig,
110
+ startTime: number
111
+ ): Promise<MultiAgentResult> {
112
+ const steps: AgentStep[] = [];
113
+ let totalUsage: LanguageModelUsage = { promptTokens: 0, completionTokens: 0, totalTokens: 0 };
114
+
115
+ const modelA = config.modelA || 'kimi-k2.5-thinking';
116
+ const modelB = config.modelB || 'kimi-k2.5';
117
+
118
+ // Step 1: Planner creates plan
119
+ const planStart = Date.now();
120
+ const plannerPrompt = `${config.systemPrompts?.planner || DEFAULT_SYSTEM_PROMPTS.planner}
121
+
122
+ Problem to solve:
123
+ ${prompt}
124
+
125
+ Provide a detailed step-by-step plan.`;
126
+
127
+ const planResult = await this.generateText(modelA, plannerPrompt);
128
+
129
+ steps.push({
130
+ agent: 'A (Planner)',
131
+ role: 'planner',
132
+ action: 'Create implementation plan',
133
+ input: prompt,
134
+ output: planResult.text,
135
+ timestamp: Date.now(),
136
+ durationMs: Date.now() - planStart,
137
+ usage: planResult.usage,
138
+ model: modelA
139
+ });
140
+
141
+ totalUsage = this.addUsage(totalUsage, planResult.usage);
142
+
143
+ // Step 2: Executor implements
144
+ const execStart = Date.now();
145
+ const executorPrompt = `${config.systemPrompts?.executor || DEFAULT_SYSTEM_PROMPTS.executor}
146
+
147
+ Plan to implement:
148
+ ${planResult.text}
149
+
150
+ Original problem: ${prompt}
151
+
152
+ Implement the solution following the plan.`;
153
+
154
+ const execResult = await this.generateText(modelB, executorPrompt);
155
+
156
+ steps.push({
157
+ agent: 'B (Executor)',
158
+ role: 'executor',
159
+ action: 'Implement solution',
160
+ input: planResult.text,
161
+ output: execResult.text,
162
+ timestamp: Date.now(),
163
+ durationMs: Date.now() - execStart,
164
+ usage: execResult.usage,
165
+ model: modelB
166
+ });
167
+
168
+ totalUsage = this.addUsage(totalUsage, execResult.usage);
169
+
170
+ // Step 3: Optional validation
171
+ let validation: MultiAgentResult['validation'];
172
+ if (config.validateCode && this.validateCode) {
173
+ const code = extractPrimaryCode(execResult.text);
174
+ if (code) {
175
+ const validStart = Date.now();
176
+ const validResult = await this.validateCode(code);
177
+
178
+ steps.push({
179
+ agent: 'Validator',
180
+ role: 'validator',
181
+ action: 'Validate code',
182
+ input: code,
183
+ output: validResult.valid ? 'Code is valid' : `Errors: ${validResult.errors.join(', ')}`,
184
+ timestamp: Date.now(),
185
+ durationMs: Date.now() - validStart
186
+ });
187
+
188
+ validation = {
189
+ valid: validResult.valid,
190
+ errors: validResult.errors,
191
+ finalCode: validResult.fixedCode || code
192
+ };
193
+ }
194
+ }
195
+
196
+ return {
197
+ text: execResult.text,
198
+ reasoning: planResult.text,
199
+ intermediateSteps: steps,
200
+ usage: totalUsage,
201
+ metadata: this.buildMetadata(config, steps, startTime, [modelA, modelB]),
202
+ validation
203
+ };
204
+ }
205
+
206
+ /**
207
+ * Proposer-Critic workflow.
208
+ */
209
+ private async runProposerCritic(
210
+ prompt: string,
211
+ config: MultiAgentConfig,
212
+ startTime: number
213
+ ): Promise<MultiAgentResult> {
214
+ const steps: AgentStep[] = [];
215
+ let totalUsage: LanguageModelUsage = { promptTokens: 0, completionTokens: 0, totalTokens: 0 };
216
+
217
+ const modelA = config.modelA || 'kimi-k2.5';
218
+ const modelB = config.modelB || 'kimi-k2.5-thinking';
219
+ const iterations = config.iterations || 2;
220
+
221
+ let currentSolution = '';
222
+ let critique = '';
223
+
224
+ for (let i = 0; i < iterations; i++) {
225
+ // Proposer generates/improves solution
226
+ const proposeStart = Date.now();
227
+ const proposerPrompt =
228
+ i === 0
229
+ ? `${config.systemPrompts?.proposer || DEFAULT_SYSTEM_PROMPTS.proposer}
230
+
231
+ Problem: ${prompt}
232
+
233
+ Provide your solution.`
234
+ : `${config.systemPrompts?.proposer || DEFAULT_SYSTEM_PROMPTS.proposer}
235
+
236
+ Problem: ${prompt}
237
+
238
+ Previous solution:
239
+ ${currentSolution}
240
+
241
+ Critique/feedback to address:
242
+ ${critique}
243
+
244
+ Provide an improved solution addressing the feedback.`;
245
+
246
+ const proposeResult = await this.generateText(modelA, proposerPrompt);
247
+ currentSolution = proposeResult.text;
248
+
249
+ steps.push({
250
+ agent: 'A (Proposer)',
251
+ role: 'proposer',
252
+ action: `Generate solution (iteration ${i + 1})`,
253
+ input: i === 0 ? prompt : critique,
254
+ output: currentSolution,
255
+ timestamp: Date.now(),
256
+ durationMs: Date.now() - proposeStart,
257
+ usage: proposeResult.usage,
258
+ model: modelA
259
+ });
260
+
261
+ totalUsage = this.addUsage(totalUsage, proposeResult.usage);
262
+
263
+ // Critic reviews (except on last iteration)
264
+ if (i < iterations - 1) {
265
+ const critiqueStart = Date.now();
266
+ const criticPrompt = `${config.systemPrompts?.critic || DEFAULT_SYSTEM_PROMPTS.critic}
267
+
268
+ Original problem: ${prompt}
269
+
270
+ Solution to review:
271
+ ${currentSolution}
272
+
273
+ Provide detailed feedback and suggestions for improvement.`;
274
+
275
+ const critiqueResult = await this.generateText(modelB, criticPrompt);
276
+ critique = critiqueResult.text;
277
+
278
+ steps.push({
279
+ agent: 'B (Critic)',
280
+ role: 'critic',
281
+ action: `Critique solution (iteration ${i + 1})`,
282
+ input: currentSolution,
283
+ output: critique,
284
+ timestamp: Date.now(),
285
+ durationMs: Date.now() - critiqueStart,
286
+ usage: critiqueResult.usage,
287
+ model: modelB
288
+ });
289
+
290
+ totalUsage = this.addUsage(totalUsage, critiqueResult.usage);
291
+ }
292
+ }
293
+
294
+ // Optional validation
295
+ let validation: MultiAgentResult['validation'];
296
+ if (config.validateCode && this.validateCode) {
297
+ const code = extractPrimaryCode(currentSolution);
298
+ if (code) {
299
+ const validResult = await this.validateCode(code);
300
+ validation = {
301
+ valid: validResult.valid,
302
+ errors: validResult.errors,
303
+ finalCode: validResult.fixedCode || code
304
+ };
305
+ }
306
+ }
307
+
308
+ return {
309
+ text: currentSolution,
310
+ reasoning: critique,
311
+ intermediateSteps: steps,
312
+ usage: totalUsage,
313
+ metadata: this.buildMetadata(config, steps, startTime, [modelA, modelB]),
314
+ validation
315
+ };
316
+ }
317
+
318
+ /**
319
+ * Debate workflow.
320
+ */
321
+ private async runDebate(prompt: string, config: MultiAgentConfig, startTime: number): Promise<MultiAgentResult> {
322
+ const steps: AgentStep[] = [];
323
+ let totalUsage: LanguageModelUsage = { promptTokens: 0, completionTokens: 0, totalTokens: 0 };
324
+
325
+ const modelA = config.modelA || 'kimi-k2.5';
326
+ const modelB = config.modelB || 'kimi-k2.5';
327
+ const iterations = config.iterations || 2;
328
+
329
+ let positionA = '';
330
+ let positionB = '';
331
+
332
+ // Initial positions
333
+ const initialPrompt = `Problem: ${prompt}
334
+
335
+ Provide your solution and reasoning.`;
336
+
337
+ // Agent A's initial position
338
+ const aStart = Date.now();
339
+ const aResult = await this.generateText(modelA, initialPrompt);
340
+ positionA = aResult.text;
341
+
342
+ steps.push({
343
+ agent: 'A',
344
+ role: 'proposer',
345
+ action: 'Initial position',
346
+ input: prompt,
347
+ output: positionA,
348
+ timestamp: Date.now(),
349
+ durationMs: Date.now() - aStart,
350
+ usage: aResult.usage,
351
+ model: modelA
352
+ });
353
+
354
+ totalUsage = this.addUsage(totalUsage, aResult.usage);
355
+
356
+ // Agent B's initial position
357
+ const bStart = Date.now();
358
+ const bResult = await this.generateText(modelB, initialPrompt);
359
+ positionB = bResult.text;
360
+
361
+ steps.push({
362
+ agent: 'B',
363
+ role: 'proposer',
364
+ action: 'Initial position',
365
+ input: prompt,
366
+ output: positionB,
367
+ timestamp: Date.now(),
368
+ durationMs: Date.now() - bStart,
369
+ usage: bResult.usage,
370
+ model: modelB
371
+ });
372
+
373
+ totalUsage = this.addUsage(totalUsage, bResult.usage);
374
+
375
+ // Debate rounds
376
+ for (let i = 0; i < iterations - 1; i++) {
377
+ // A responds to B
378
+ const aDebateStart = Date.now();
379
+ const aDebatePrompt = `Problem: ${prompt}
380
+
381
+ Your previous position:
382
+ ${positionA}
383
+
384
+ Other perspective:
385
+ ${positionB}
386
+
387
+ Consider the other perspective. Either defend your position with additional reasoning, or revise it based on valid points. Provide your updated solution.`;
388
+
389
+ const aDebateResult = await this.generateText(modelA, aDebatePrompt);
390
+ positionA = aDebateResult.text;
391
+
392
+ steps.push({
393
+ agent: 'A',
394
+ role: 'proposer',
395
+ action: `Debate round ${i + 1}`,
396
+ input: positionB,
397
+ output: positionA,
398
+ timestamp: Date.now(),
399
+ durationMs: Date.now() - aDebateStart,
400
+ usage: aDebateResult.usage,
401
+ model: modelA
402
+ });
403
+
404
+ totalUsage = this.addUsage(totalUsage, aDebateResult.usage);
405
+
406
+ // B responds to A
407
+ const bDebateStart = Date.now();
408
+ const bDebatePrompt = `Problem: ${prompt}
409
+
410
+ Your previous position:
411
+ ${positionB}
412
+
413
+ Other perspective:
414
+ ${positionA}
415
+
416
+ Consider the other perspective. Either defend your position with additional reasoning, or revise it based on valid points. Provide your updated solution.`;
417
+
418
+ const bDebateResult = await this.generateText(modelB, bDebatePrompt);
419
+ positionB = bDebateResult.text;
420
+
421
+ steps.push({
422
+ agent: 'B',
423
+ role: 'proposer',
424
+ action: `Debate round ${i + 1}`,
425
+ input: positionA,
426
+ output: positionB,
427
+ timestamp: Date.now(),
428
+ durationMs: Date.now() - bDebateStart,
429
+ usage: bDebateResult.usage,
430
+ model: modelB
431
+ });
432
+
433
+ totalUsage = this.addUsage(totalUsage, bDebateResult.usage);
434
+ }
435
+
436
+ // Synthesize final answer (use last response as primary)
437
+ const finalText = positionA.length > positionB.length ? positionA : positionB;
438
+
439
+ return {
440
+ text: finalText,
441
+ reasoning: `Debate synthesis from ${iterations} rounds`,
442
+ intermediateSteps: steps,
443
+ usage: totalUsage,
444
+ metadata: this.buildMetadata(config, steps, startTime, [modelA, modelB])
445
+ };
446
+ }
447
+
448
+ /**
449
+ * Custom workflow.
450
+ */
451
+ private async runCustom(prompt: string, config: MultiAgentConfig, startTime: number): Promise<MultiAgentResult> {
452
+ const steps: AgentStep[] = [];
453
+ const modelA = config.modelA || 'kimi-k2.5';
454
+ const modelB = config.modelB || 'kimi-k2.5';
455
+
456
+ const context: WorkflowContext = {
457
+ generateWithModelA: (p: string) => this.generateText(modelA, p),
458
+ generateWithModelB: (p: string) => this.generateText(modelB, p),
459
+ validateCode: this.validateCode,
460
+ config,
461
+ addStep: (step) => {
462
+ steps.push({
463
+ ...step,
464
+ timestamp: Date.now(),
465
+ durationMs: 0
466
+ });
467
+ }
468
+ };
469
+
470
+ const result = await config.customWorkflow!(prompt, context);
471
+
472
+ // Merge steps if result doesn't include them
473
+ if (result.intermediateSteps.length === 0 && steps.length > 0) {
474
+ result.intermediateSteps = steps;
475
+ }
476
+
477
+ // Update metadata with timing
478
+ result.metadata.durationMs = Date.now() - startTime;
479
+
480
+ return result;
481
+ }
482
+
483
+ /**
484
+ * Build metadata for result.
485
+ */
486
+ private buildMetadata(
487
+ config: MultiAgentConfig,
488
+ steps: AgentStep[],
489
+ startTime: number,
490
+ models: string[]
491
+ ): MultiAgentMetadata {
492
+ return {
493
+ workflow: config.workflow,
494
+ iterations: steps.length,
495
+ durationMs: Date.now() - startTime,
496
+ models: [...new Set(models)],
497
+ validationEnabled: config.validateCode ?? false,
498
+ success: true
499
+ };
500
+ }
501
+
502
+ /**
503
+ * Add usage stats.
504
+ */
505
+ private addUsage(a: LanguageModelUsage, b?: LanguageModelUsage): LanguageModelUsage {
506
+ if (!b) {
507
+ return a;
508
+ }
509
+ return {
510
+ promptTokens: a.promptTokens + b.promptTokens,
511
+ completionTokens: a.completionTokens + b.completionTokens,
512
+ totalTokens: a.totalTokens + b.totalTokens
513
+ };
514
+ }
515
+ }
516
+
517
+ // ============================================================================
518
+ // Utility Functions
519
+ // ============================================================================
520
+
521
+ /**
522
+ * Create an empty multi-agent result.
523
+ */
524
+ export function createEmptyMultiAgentResult(workflow: MultiAgentConfig['workflow'], error: string): MultiAgentResult {
525
+ return {
526
+ text: '',
527
+ intermediateSteps: [],
528
+ usage: { promptTokens: 0, completionTokens: 0, totalTokens: 0 },
529
+ metadata: {
530
+ workflow,
531
+ iterations: 0,
532
+ durationMs: 0,
533
+ models: [],
534
+ validationEnabled: false,
535
+ success: false,
536
+ error
537
+ }
538
+ };
539
+ }
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Project tools module exports.
3
+ * @module
4
+ */
5
+
6
+ export type { GenerateTextFunction, ScaffolderOptions } from './scaffolder';
7
+ export type {
8
+ OutputFormat,
9
+ ProjectFile,
10
+ ProjectMetadata,
11
+ ProjectTemplate,
12
+ ProjectType,
13
+ ScaffoldConfig,
14
+ ScaffoldResult
15
+ } from './types';
16
+ export { ProjectScaffolder, createEmptyScaffoldResult } from './scaffolder';