From ecc08bd3f725aace84d161f2775fe6fd14b6fbac Mon Sep 17 00:00:00 2001 From: suyao Date: Fri, 1 Aug 2025 10:45:31 +0800 Subject: [PATCH] feat: integrate image generation capabilities and enhance testing framework - Added support for image generation in the `RuntimeExecutor` with a new `generateImage` method. - Updated `aiCore` package to include `vitest` for testing, with new test scripts added. - Enhanced type definitions to accommodate image model handling in plugins. - Introduced new methods for resolving and executing image generation with plugins. - Updated package dependencies in `package.json` to include `vitest` and ensure compatibility with new features. --- packages/aiCore/examples/image-generation.ts | 167 ++++ packages/aiCore/package.json | 7 +- packages/aiCore/src/core/plugins/types.ts | 6 +- .../runtime/__tests__/generateImage.test.ts | 533 ++++++++++++ packages/aiCore/src/core/runtime/errors.ts | 38 + packages/aiCore/src/core/runtime/executor.ts | 88 +- packages/aiCore/src/core/runtime/index.ts | 15 + .../aiCore/src/core/runtime/pluginEngine.ts | 57 ++ packages/aiCore/src/index.ts | 1 + packages/aiCore/vitest.config.ts | 13 + src/renderer/src/aiCore/index_new.ts | 159 +++- yarn.lock | 806 +++++++++++++++++- 12 files changed, 1873 insertions(+), 17 deletions(-) create mode 100644 packages/aiCore/examples/image-generation.ts create mode 100644 packages/aiCore/src/core/runtime/__tests__/generateImage.test.ts create mode 100644 packages/aiCore/src/core/runtime/errors.ts create mode 100644 packages/aiCore/vitest.config.ts diff --git a/packages/aiCore/examples/image-generation.ts b/packages/aiCore/examples/image-generation.ts new file mode 100644 index 000000000..811aa048c --- /dev/null +++ b/packages/aiCore/examples/image-generation.ts @@ -0,0 +1,167 @@ +/** + * Image Generation Example + * 演示如何使用 aiCore 的文生图功能 + */ + +import { createExecutor, generateImage } from '../src/index' + +async function main() { + // 方式1: 使用执行器实例 + console.log('📸 创建 OpenAI 图像生成执行器...') + const executor = createExecutor('openai', { + apiKey: process.env.OPENAI_API_KEY! + }) + + try { + console.log('🎨 使用执行器生成图像...') + const result1 = await executor.generateImage('dall-e-3', { + prompt: 'A futuristic cityscape at sunset with flying cars', + size: '1024x1024', + n: 1 + }) + + console.log('✅ 图像生成成功!') + console.log('📊 结果:', { + imagesCount: result1.images.length, + mediaType: result1.image.mediaType, + hasBase64: !!result1.image.base64, + providerMetadata: result1.providerMetadata + }) + } catch (error) { + console.error('❌ 执行器生成失败:', error) + } + + // 方式2: 使用直接调用 API + try { + console.log('🎨 使用直接 API 生成图像...') + const result2 = await generateImage('openai', { apiKey: process.env.OPENAI_API_KEY! }, 'dall-e-3', { + prompt: 'A magical forest with glowing mushrooms and fairy lights', + aspectRatio: '16:9', + providerOptions: { + openai: { + quality: 'hd', + style: 'vivid' + } + } + }) + + console.log('✅ 直接 API 生成成功!') + console.log('📊 结果:', { + imagesCount: result2.images.length, + mediaType: result2.image.mediaType, + hasBase64: !!result2.image.base64 + }) + } catch (error) { + console.error('❌ 直接 API 生成失败:', error) + } + + // 方式3: 支持其他提供商 (Google Imagen) + if (process.env.GOOGLE_API_KEY) { + try { + console.log('🎨 使用 Google Imagen 生成图像...') + const googleExecutor = createExecutor('google', { + apiKey: process.env.GOOGLE_API_KEY! + }) + + const result3 = await googleExecutor.generateImage('imagen-3.0-generate-002', { + prompt: 'A serene mountain lake at dawn with mist rising from the water', + aspectRatio: '1:1' + }) + + console.log('✅ Google Imagen 生成成功!') + console.log('📊 结果:', { + imagesCount: result3.images.length, + mediaType: result3.image.mediaType, + hasBase64: !!result3.image.base64 + }) + } catch (error) { + console.error('❌ Google Imagen 生成失败:', error) + } + } + + // 方式4: 支持插件系统 + const pluginExample = async () => { + console.log('🔌 演示插件系统...') + + // 创建一个示例插件,用于修改提示词 + const promptEnhancerPlugin = { + name: 'prompt-enhancer', + transformParams: async (params: any) => { + console.log('🔧 插件: 增强提示词...') + return { + ...params, + prompt: `${params.prompt}, highly detailed, cinematic lighting, 4K resolution` + } + }, + transformResult: async (result: any) => { + console.log('🔧 插件: 处理结果...') + return { + ...result, + enhanced: true + } + } + } + + const executorWithPlugin = createExecutor( + 'openai', + { + apiKey: process.env.OPENAI_API_KEY! + }, + [promptEnhancerPlugin] + ) + + try { + const result4 = await executorWithPlugin.generateImage('dall-e-3', { + prompt: 'A cute robot playing in a garden' + }) + + console.log('✅ 插件系统生成成功!') + console.log('📊 结果:', { + imagesCount: result4.images.length, + enhanced: (result4 as any).enhanced, + mediaType: result4.image.mediaType + }) + } catch (error) { + console.error('❌ 插件系统生成失败:', error) + } + } + + await pluginExample() +} + +// 错误处理演示 +async function errorHandlingExample() { + console.log('⚠️ 演示错误处理...') + + try { + const executor = createExecutor('openai', { + apiKey: 'invalid-key' + }) + + await executor.generateImage('dall-e-3', { + prompt: 'Test image' + }) + } catch (error: any) { + console.log('✅ 成功捕获错误:', error.constructor.name) + console.log('📋 错误信息:', error.message) + console.log('🏷️ 提供商ID:', error.providerId) + console.log('🏷️ 模型ID:', error.modelId) + } +} + +// 运行示例 +if (require.main === module) { + main() + .then(() => { + console.log('🎉 所有示例完成!') + return errorHandlingExample() + }) + .then(() => { + console.log('🎯 示例程序结束') + process.exit(0) + }) + .catch((error) => { + console.error('💥 程序执行出错:', error) + process.exit(1) + }) +} diff --git a/packages/aiCore/package.json b/packages/aiCore/package.json index 1b855d388..48dfaf906 100644 --- a/packages/aiCore/package.json +++ b/packages/aiCore/package.json @@ -9,7 +9,9 @@ "scripts": { "build": "tsdown", "dev": "tsc -w", - "clean": "rm -rf dist" + "clean": "rm -rf dist", + "test": "vitest run", + "test:watch": "vitest" }, "keywords": [ "ai", @@ -45,7 +47,8 @@ }, "devDependencies": { "tsdown": "^0.12.9", - "typescript": "^5.0.0" + "typescript": "^5.0.0", + "vitest": "^1.0.0" }, "sideEffects": false, "engines": { diff --git a/packages/aiCore/src/core/plugins/types.ts b/packages/aiCore/src/core/plugins/types.ts index 388ca977b..47060e107 100644 --- a/packages/aiCore/src/core/plugins/types.ts +++ b/packages/aiCore/src/core/plugins/types.ts @@ -1,3 +1,4 @@ +import type { ImageModelV2 } from '@ai-sdk/provider' import type { LanguageModel, TextStreamPart, ToolSet } from 'ai' import { type ProviderId } from '../providers/types' @@ -32,7 +33,10 @@ export interface AiPlugin { enforce?: 'pre' | 'post' // 【First】首个钩子 - 只执行第一个返回值的插件 - resolveModel?: (modelId: string, context: AiRequestContext) => Promise | LanguageModel | null + resolveModel?: ( + modelId: string, + context: AiRequestContext + ) => Promise | LanguageModel | ImageModelV2 | null loadTemplate?: (templateName: string, context: AiRequestContext) => any | null | Promise // 【Sequential】串行钩子 - 链式执行,支持数据转换 diff --git a/packages/aiCore/src/core/runtime/__tests__/generateImage.test.ts b/packages/aiCore/src/core/runtime/__tests__/generateImage.test.ts new file mode 100644 index 000000000..67273fdd5 --- /dev/null +++ b/packages/aiCore/src/core/runtime/__tests__/generateImage.test.ts @@ -0,0 +1,533 @@ +import { ImageModelV2 } from '@ai-sdk/provider' +import { experimental_generateImage as aiGenerateImage, NoImageGeneratedError } from 'ai' +import { beforeEach, describe, expect, it, vi } from 'vitest' + +import { createImageModel } from '../../models/ModelCreator' +import { type AiPlugin } from '../../plugins' +import { ImageGenerationError } from '../errors' +import { RuntimeExecutor } from '../executor' + +// Mock dependencies +vi.mock('ai', () => ({ + experimental_generateImage: vi.fn(), + NoImageGeneratedError: class NoImageGeneratedError extends Error { + static isInstance = vi.fn() + constructor() { + super('No image generated') + this.name = 'NoImageGeneratedError' + } + } +})) + +vi.mock('../../models/ModelCreator', () => ({ + createImageModel: vi.fn() +})) + +describe('RuntimeExecutor.generateImage', () => { + let executor: RuntimeExecutor<'openai'> + let mockImageModel: ImageModelV2 + let mockGenerateImageResult: any + + beforeEach(() => { + // Reset all mocks + vi.clearAllMocks() + + // Create executor instance + executor = RuntimeExecutor.create('openai', { + apiKey: 'test-key' + }) + + // Mock image model + mockImageModel = { + modelId: 'dall-e-3', + provider: 'openai' + } as ImageModelV2 + + // Mock generateImage result + mockGenerateImageResult = { + image: { + base64: 'base64-encoded-image-data', + uint8Array: new Uint8Array([1, 2, 3]), + mediaType: 'image/png' + }, + images: [ + { + base64: 'base64-encoded-image-data', + uint8Array: new Uint8Array([1, 2, 3]), + mediaType: 'image/png' + } + ], + warnings: [], + providerMetadata: { + openai: { + images: [{ revisedPrompt: 'A detailed prompt' }] + } + }, + responses: [] + } + + // Setup mocks + vi.mocked(createImageModel).mockResolvedValue(mockImageModel) + vi.mocked(aiGenerateImage).mockResolvedValue(mockGenerateImageResult) + }) + + describe('Basic functionality', () => { + it('should generate a single image with minimal parameters', async () => { + const result = await executor.generateImage('dall-e-3', { + prompt: 'A futuristic cityscape at sunset' + }) + + expect(createImageModel).toHaveBeenCalledWith('openai', 'dall-e-3', { apiKey: 'test-key' }) + + expect(aiGenerateImage).toHaveBeenCalledWith({ + model: mockImageModel, + prompt: 'A futuristic cityscape at sunset' + }) + + expect(result).toEqual(mockGenerateImageResult) + }) + + it('should generate image with pre-created model', async () => { + const result = await executor.generateImage(mockImageModel, { + prompt: 'A beautiful landscape' + }) + + // Note: createImageModel may still be called due to resolveImageModel logic + expect(aiGenerateImage).toHaveBeenCalledWith({ + model: mockImageModel, + prompt: 'A beautiful landscape' + }) + + expect(result).toEqual(mockGenerateImageResult) + }) + + it('should support multiple images generation', async () => { + await executor.generateImage('dall-e-3', { + prompt: 'A futuristic cityscape', + n: 3 + }) + + expect(aiGenerateImage).toHaveBeenCalledWith({ + model: mockImageModel, + prompt: 'A futuristic cityscape', + n: 3 + }) + }) + + it('should support size specification', async () => { + await executor.generateImage('dall-e-3', { + prompt: 'A beautiful sunset', + size: '1024x1024' + }) + + expect(aiGenerateImage).toHaveBeenCalledWith({ + model: mockImageModel, + prompt: 'A beautiful sunset', + size: '1024x1024' + }) + }) + + it('should support aspect ratio specification', async () => { + await executor.generateImage('dall-e-3', { + prompt: 'A mountain landscape', + aspectRatio: '16:9' + }) + + expect(aiGenerateImage).toHaveBeenCalledWith({ + model: mockImageModel, + prompt: 'A mountain landscape', + aspectRatio: '16:9' + }) + }) + + it('should support seed for consistent output', async () => { + await executor.generateImage('dall-e-3', { + prompt: 'A cat in space', + seed: 1234567890 + }) + + expect(aiGenerateImage).toHaveBeenCalledWith({ + model: mockImageModel, + prompt: 'A cat in space', + seed: 1234567890 + }) + }) + + it('should support abort signal', async () => { + const abortController = new AbortController() + + await executor.generateImage('dall-e-3', { + prompt: 'A cityscape', + abortSignal: abortController.signal + }) + + expect(aiGenerateImage).toHaveBeenCalledWith({ + model: mockImageModel, + prompt: 'A cityscape', + abortSignal: abortController.signal + }) + }) + + it('should support provider-specific options', async () => { + await executor.generateImage('dall-e-3', { + prompt: 'A space station', + providerOptions: { + openai: { + quality: 'hd', + style: 'vivid' + } + } + }) + + expect(aiGenerateImage).toHaveBeenCalledWith({ + model: mockImageModel, + prompt: 'A space station', + providerOptions: { + openai: { + quality: 'hd', + style: 'vivid' + } + } + }) + }) + + it('should support custom headers', async () => { + await executor.generateImage('dall-e-3', { + prompt: 'A robot', + headers: { + 'X-Custom-Header': 'test-value' + } + }) + + expect(aiGenerateImage).toHaveBeenCalledWith({ + model: mockImageModel, + prompt: 'A robot', + headers: { + 'X-Custom-Header': 'test-value' + } + }) + }) + }) + + describe('Plugin integration', () => { + it('should execute plugins in correct order', async () => { + const pluginCallOrder: string[] = [] + + const testPlugin: AiPlugin = { + name: 'test-plugin', + onRequestStart: vi.fn(async () => { + pluginCallOrder.push('onRequestStart') + }), + transformParams: vi.fn(async (params) => { + pluginCallOrder.push('transformParams') + return { ...params, size: '512x512' } + }), + transformResult: vi.fn(async (result) => { + pluginCallOrder.push('transformResult') + return { ...result, processed: true } + }), + onRequestEnd: vi.fn(async () => { + pluginCallOrder.push('onRequestEnd') + }) + } + + const executorWithPlugin = RuntimeExecutor.create( + 'openai', + { + apiKey: 'test-key' + }, + [testPlugin] + ) + + const result = await executorWithPlugin.generateImage('dall-e-3', { + prompt: 'A test image' + }) + + expect(pluginCallOrder).toEqual(['onRequestStart', 'transformParams', 'transformResult', 'onRequestEnd']) + + expect(testPlugin.transformParams).toHaveBeenCalledWith( + { prompt: 'A test image' }, + expect.objectContaining({ + providerId: 'openai', + modelId: 'dall-e-3' + }) + ) + + expect(aiGenerateImage).toHaveBeenCalledWith({ + model: mockImageModel, + prompt: 'A test image', + size: '512x512' // Should be transformed by plugin + }) + + expect(result).toEqual({ + ...mockGenerateImageResult, + processed: true // Should be transformed by plugin + }) + }) + + it('should handle model resolution through plugins', async () => { + const customImageModel = { + modelId: 'custom-model', + provider: 'openai' + } as ImageModelV2 + + const modelResolutionPlugin: AiPlugin = { + name: 'model-resolver', + resolveModel: vi.fn(async () => customImageModel) + } + + const executorWithPlugin = RuntimeExecutor.create( + 'openai', + { + apiKey: 'test-key' + }, + [modelResolutionPlugin] + ) + + await executorWithPlugin.generateImage('dall-e-3', { + prompt: 'A test image' + }) + + expect(modelResolutionPlugin.resolveModel).toHaveBeenCalledWith( + 'dall-e-3', + expect.objectContaining({ + providerId: 'openai', + modelId: 'dall-e-3' + }) + ) + + expect(aiGenerateImage).toHaveBeenCalledWith({ + model: customImageModel, + prompt: 'A test image' + }) + }) + + it('should support recursive calls from plugins', async () => { + const recursivePlugin: AiPlugin = { + name: 'recursive-plugin', + transformParams: vi.fn(async (params, context) => { + if (!context.isRecursiveCall && params.prompt === 'original') { + // Make a recursive call with modified prompt + await context.recursiveCall({ + prompt: 'modified' + }) + } + return params + }) + } + + const executorWithPlugin = RuntimeExecutor.create( + 'openai', + { + apiKey: 'test-key' + }, + [recursivePlugin] + ) + + await executorWithPlugin.generateImage('dall-e-3', { + prompt: 'original' + }) + + expect(recursivePlugin.transformParams).toHaveBeenCalledTimes(2) + expect(aiGenerateImage).toHaveBeenCalledTimes(2) + }) + }) + + describe('Error handling', () => { + it('should handle model creation errors', async () => { + const modelError = new Error('Failed to create image model') + vi.mocked(createImageModel).mockRejectedValue(modelError) + + await expect( + executor.generateImage('invalid-model', { + prompt: 'A test image' + }) + ).rejects.toThrow(ImageGenerationError) + }) + + it('should handle image generation API errors', async () => { + const apiError = new Error('API request failed') + vi.mocked(aiGenerateImage).mockRejectedValue(apiError) + + await expect( + executor.generateImage('dall-e-3', { + prompt: 'A test image' + }) + ).rejects.toThrow('Failed to generate image: API request failed') + }) + + it('should handle NoImageGeneratedError', async () => { + const noImageError = new NoImageGeneratedError({ + cause: new Error('No image generated'), + responses: [] + }) + + vi.mocked(aiGenerateImage).mockRejectedValue(noImageError) + vi.mocked(NoImageGeneratedError.isInstance).mockReturnValue(true) + + await expect( + executor.generateImage('dall-e-3', { + prompt: 'A test image' + }) + ).rejects.toThrow('Failed to generate image: No image generated') + }) + + it('should execute onError plugin hook on failure', async () => { + const error = new Error('Generation failed') + vi.mocked(aiGenerateImage).mockRejectedValue(error) + + const errorPlugin: AiPlugin = { + name: 'error-handler', + onError: vi.fn() + } + + const executorWithPlugin = RuntimeExecutor.create( + 'openai', + { + apiKey: 'test-key' + }, + [errorPlugin] + ) + + await expect( + executorWithPlugin.generateImage('dall-e-3', { + prompt: 'A test image' + }) + ).rejects.toThrow('Failed to generate image: Generation failed') + + expect(errorPlugin.onError).toHaveBeenCalledWith( + error, + expect.objectContaining({ + providerId: 'openai', + modelId: 'dall-e-3' + }) + ) + }) + + it('should handle abort signal timeout', async () => { + const abortError = new Error('Operation was aborted') + abortError.name = 'AbortError' + vi.mocked(aiGenerateImage).mockRejectedValue(abortError) + + const abortController = new AbortController() + setTimeout(() => abortController.abort(), 10) + + await expect( + executor.generateImage('dall-e-3', { + prompt: 'A test image', + abortSignal: abortController.signal + }) + ).rejects.toThrow('Operation was aborted') + }) + }) + + describe('Multiple providers support', () => { + it('should work with different providers', async () => { + const googleExecutor = RuntimeExecutor.create('google', { + apiKey: 'google-key' + }) + + await googleExecutor.generateImage('imagen-3.0-generate-002', { + prompt: 'A landscape' + }) + + expect(createImageModel).toHaveBeenCalledWith('google', 'imagen-3.0-generate-002', { apiKey: 'google-key' }) + }) + + it('should support xAI Grok image models', async () => { + const xaiExecutor = RuntimeExecutor.create('xai', { + apiKey: 'xai-key' + }) + + await xaiExecutor.generateImage('grok-2-image', { + prompt: 'A futuristic robot' + }) + + expect(createImageModel).toHaveBeenCalledWith('xai', 'grok-2-image', { apiKey: 'xai-key' }) + }) + }) + + describe('Advanced features', () => { + it('should support batch image generation with maxImagesPerCall', async () => { + await executor.generateImage('dall-e-3', { + prompt: 'A test image', + n: 10, + maxImagesPerCall: 5 + }) + + expect(aiGenerateImage).toHaveBeenCalledWith({ + model: mockImageModel, + prompt: 'A test image', + n: 10, + maxImagesPerCall: 5 + }) + }) + + it('should support retries with maxRetries', async () => { + await executor.generateImage('dall-e-3', { + prompt: 'A test image', + maxRetries: 3 + }) + + expect(aiGenerateImage).toHaveBeenCalledWith({ + model: mockImageModel, + prompt: 'A test image', + maxRetries: 3 + }) + }) + + it('should handle warnings from the model', async () => { + const resultWithWarnings = { + ...mockGenerateImageResult, + warnings: [ + { + type: 'unsupported-setting', + message: 'Size parameter not supported for this model' + } + ] + } + + vi.mocked(aiGenerateImage).mockResolvedValue(resultWithWarnings) + + const result = await executor.generateImage('dall-e-3', { + prompt: 'A test image', + size: '2048x2048' // Unsupported size + }) + + expect(result.warnings).toHaveLength(1) + expect(result.warnings[0].type).toBe('unsupported-setting') + }) + + it('should provide access to provider metadata', async () => { + const result = await executor.generateImage('dall-e-3', { + prompt: 'A test image' + }) + + expect(result.providerMetadata).toBeDefined() + expect(result.providerMetadata.openai).toBeDefined() + }) + + it('should provide response metadata', async () => { + const resultWithMetadata = { + ...mockGenerateImageResult, + responses: [ + { + timestamp: new Date(), + modelId: 'dall-e-3', + headers: { 'x-request-id': 'test-123' } + } + ] + } + + vi.mocked(aiGenerateImage).mockResolvedValue(resultWithMetadata) + + const result = await executor.generateImage('dall-e-3', { + prompt: 'A test image' + }) + + expect(result.responses).toHaveLength(1) + expect(result.responses[0].modelId).toBe('dall-e-3') + expect(result.responses[0].headers).toEqual({ 'x-request-id': 'test-123' }) + }) + }) +}) diff --git a/packages/aiCore/src/core/runtime/errors.ts b/packages/aiCore/src/core/runtime/errors.ts new file mode 100644 index 000000000..f3d7cbd1f --- /dev/null +++ b/packages/aiCore/src/core/runtime/errors.ts @@ -0,0 +1,38 @@ +/** + * Error classes for runtime operations + */ + +/** + * Error thrown when image generation fails + */ +export class ImageGenerationError extends Error { + constructor( + message: string, + public providerId?: string, + public modelId?: string, + public cause?: Error + ) { + super(message) + this.name = 'ImageGenerationError' + + // Maintain proper stack trace (for V8 engines) + if (Error.captureStackTrace) { + Error.captureStackTrace(this, ImageGenerationError) + } + } +} + +/** + * Error thrown when model resolution fails during image generation + */ +export class ImageModelResolutionError extends ImageGenerationError { + constructor(modelId: string, providerId?: string, cause?: Error) { + super( + `Failed to resolve image model: ${modelId}${providerId ? ` for provider: ${providerId}` : ''}`, + providerId, + modelId, + cause + ) + this.name = 'ImageModelResolutionError' + } +} diff --git a/packages/aiCore/src/core/runtime/executor.ts b/packages/aiCore/src/core/runtime/executor.ts index 1f29baa74..0cc1b331f 100644 --- a/packages/aiCore/src/core/runtime/executor.ts +++ b/packages/aiCore/src/core/runtime/executor.ts @@ -2,13 +2,21 @@ * 运行时执行器 * 专注于插件化的AI调用处理 */ -import { LanguageModelV2, LanguageModelV2Middleware } from '@ai-sdk/provider' -import { generateObject, generateText, LanguageModel, streamObject, streamText } from 'ai' +import { ImageModelV2, LanguageModelV2, LanguageModelV2Middleware } from '@ai-sdk/provider' +import { + experimental_generateImage as generateImage, + generateObject, + generateText, + LanguageModel, + streamObject, + streamText +} from 'ai' import { type ProviderId } from '../../types' -import { createModel, getProviderInfo } from '../models' +import { createImageModel, createModel, getProviderInfo } from '../models' import { type ModelConfig } from '../models/types' import { type AiPlugin, type AiRequestContext, definePlugin } from '../plugins' +import { ImageGenerationError, ImageModelResolutionError } from './errors' import { PluginEngine } from './pluginEngine' import { type RuntimeConfig } from './types' @@ -42,6 +50,17 @@ export class RuntimeExecutor { }) } + createResolveImageModelPlugin() { + return definePlugin({ + name: '_internal_resolveImageModel', + enforce: 'post', + + resolveModel: async (modelId: string) => { + return await this.resolveImageModel(modelId) + } + }) + } + createConfigureContextPlugin() { return definePlugin({ name: '_internal_configureContext', @@ -203,6 +222,48 @@ export class RuntimeExecutor { ) } + /** + * 生成图像 - 使用已创建的图像模型 + */ + async generateImage( + model: ImageModelV2, + params: Omit[0], 'model'> + ): Promise> + async generateImage( + modelId: string, + params: Omit[0], 'model'>, + options?: { + middlewares?: LanguageModelV2Middleware[] + } + ): Promise> + async generateImage( + modelOrId: ImageModelV2 | string, + params: Omit[0], 'model'> + ): Promise> { + try { + this.pluginEngine.usePlugins([this.createResolveImageModelPlugin(), this.createConfigureContextPlugin()]) + + return await this.pluginEngine.executeImageWithPlugins( + 'generateImage', + typeof modelOrId === 'string' ? modelOrId : modelOrId.modelId, + params, + async (model, transformedParams) => { + return await generateImage({ model, ...transformedParams }) + } + ) + } catch (error) { + if (error instanceof Error) { + throw new ImageGenerationError( + `Failed to generate image: ${error.message}`, + this.config.providerId, + typeof modelOrId === 'string' ? modelOrId : modelOrId.modelId, + error + ) + } + throw error + } + } + // === 辅助方法 === /** @@ -228,6 +289,27 @@ export class RuntimeExecutor { } } + /** + * 解析图像模型:如果是字符串则创建图像模型,如果是模型则直接返回 + */ + private async resolveImageModel(modelOrId: ImageModelV2 | string): Promise { + try { + if (typeof modelOrId === 'string') { + // 字符串modelId,需要创建图像模型 + return await createImageModel(this.config.providerId, modelOrId, this.config.providerSettings) + } else { + // 已经是模型,直接返回 + return modelOrId + } + } catch (error) { + throw new ImageModelResolutionError( + typeof modelOrId === 'string' ? modelOrId : modelOrId.modelId, + this.config.providerId, + error instanceof Error ? error : undefined + ) + } + } + /** * 获取客户端信息 */ diff --git a/packages/aiCore/src/core/runtime/index.ts b/packages/aiCore/src/core/runtime/index.ts index 0fd1e4ad0..279c6126b 100644 --- a/packages/aiCore/src/core/runtime/index.ts +++ b/packages/aiCore/src/core/runtime/index.ts @@ -100,6 +100,21 @@ export async function streamObject( return executor.streamObject(modelId, params, { middlewares }) } +/** + * 直接生成图像 - 支持middlewares + */ +export async function generateImage( + providerId: T, + options: ProviderSettingsMap[T] & { mode?: 'chat' | 'responses' }, + modelId: string, + params: Parameters['generateImage']>[1], + plugins?: AiPlugin[], + middlewares?: LanguageModelV2Middleware[] +): Promise['generateImage']>> { + const executor = createExecutor(providerId, options, plugins) + return executor.generateImage(modelId, params, { middlewares }) +} + // === Agent 功能预留 === // 未来将在 ../agents/ 文件夹中添加: // - AgentExecutor.ts diff --git a/packages/aiCore/src/core/runtime/pluginEngine.ts b/packages/aiCore/src/core/runtime/pluginEngine.ts index e64650114..b3f737020 100644 --- a/packages/aiCore/src/core/runtime/pluginEngine.ts +++ b/packages/aiCore/src/core/runtime/pluginEngine.ts @@ -1,3 +1,4 @@ +import { ImageModelV2 } from '@ai-sdk/provider' import { LanguageModel } from 'ai' import { type AiPlugin, createContext, PluginManager } from '../plugins' @@ -113,6 +114,62 @@ export class PluginEngine { } } + /** + * 执行带插件的图像生成操作 + * 提供给AiExecutor使用 + */ + async executeImageWithPlugins( + methodName: string, + modelId: string, + params: TParams, + executor: (model: ImageModelV2, transformedParams: TParams) => Promise, + _context?: ReturnType + ): Promise { + // 使用正确的createContext创建请求上下文 + const context = _context ? _context : createContext(this.providerId, modelId, params) + + // 🔥 为上下文添加递归调用能力 + context.recursiveCall = async (newParams: any): Promise => { + // 递归调用自身,重新走完整的插件流程 + context.isRecursiveCall = true + const result = await this.executeImageWithPlugins(methodName, modelId, newParams, executor, context) + context.isRecursiveCall = false + return result + } + + try { + // 0. 配置上下文 + await this.pluginManager.executeConfigureContext(context) + + // 1. 触发请求开始事件 + await this.pluginManager.executeParallel('onRequestStart', context) + + // 2. 解析模型 + const model = await this.pluginManager.executeFirst('resolveModel', modelId, context) + if (!model) { + throw new Error(`Failed to resolve image model: ${modelId}`) + } + + // 3. 转换请求参数 + const transformedParams = await this.pluginManager.executeSequential('transformParams', params, context) + + // 4. 执行具体的 API 调用 + const result = await executor(model, transformedParams) + + // 5. 转换结果 + const transformedResult = await this.pluginManager.executeSequential('transformResult', result, context) + + // 6. 触发完成事件 + await this.pluginManager.executeParallel('onRequestEnd', context, transformedResult) + + return transformedResult + } catch (error) { + // 7. 触发错误事件 + await this.pluginManager.executeParallel('onError', context, undefined, error as Error) + throw error + } + } + /** * 执行流式调用的通用逻辑(支持流转换器) * 提供给AiExecutor使用 diff --git a/packages/aiCore/src/index.ts b/packages/aiCore/src/index.ts index 61f058d61..15e27e79a 100644 --- a/packages/aiCore/src/index.ts +++ b/packages/aiCore/src/index.ts @@ -17,6 +17,7 @@ import { createExecutor } from './core/runtime' export { createExecutor, createOpenAICompatibleExecutor, + generateImage, generateObject, generateText, streamText diff --git a/packages/aiCore/vitest.config.ts b/packages/aiCore/vitest.config.ts new file mode 100644 index 000000000..3786228ac --- /dev/null +++ b/packages/aiCore/vitest.config.ts @@ -0,0 +1,13 @@ +import { defineConfig } from 'vitest/config' + +export default defineConfig({ + test: { + environment: 'node', + globals: true + }, + resolve: { + alias: { + '@': './src' + } + } +}) diff --git a/src/renderer/src/aiCore/index_new.ts b/src/renderer/src/aiCore/index_new.ts index b5cffe8b7..b59163874 100644 --- a/src/renderer/src/aiCore/index_new.ts +++ b/src/renderer/src/aiCore/index_new.ts @@ -12,6 +12,7 @@ import { AiCore, AiPlugin, createExecutor, + generateImage, ProviderConfigFactory, type ProviderId, type ProviderSettingsMap, @@ -22,6 +23,7 @@ import { isDedicatedImageGenerationModel } from '@renderer/config/models' import { createVertexProvider, isVertexAIConfigured, isVertexProvider } from '@renderer/hooks/useVertexAI' import { getProviderByModel } from '@renderer/services/AssistantService' import type { GenerateImageParams, Model, Provider } from '@renderer/types' +import { ChunkType } from '@renderer/types/chunk' import { formatApiHost } from '@renderer/utils/api' import { cloneDeep } from 'lodash' @@ -127,9 +129,11 @@ function isModernSdkSupported(provider: Provider, model?: Model): boolean { return false } - // 检查是否为图像生成模型(暂时不支持) + // 图像生成模型现在支持新的 AI SDK + // (但需要确保 provider 是支持的 + if (model && isDedicatedImageGenerationModel(model)) { - return false + return true } return true @@ -211,6 +215,12 @@ export default class ModernAiProvider { middlewareConfig: AiSdkMiddlewareConfig ): Promise { console.log('completions', modelId, params, middlewareConfig) + + // 检查是否为图像生成模型 + if (middlewareConfig.model && isDedicatedImageGenerationModel(middlewareConfig.model)) { + return await this.modernImageGeneration(modelId, params, middlewareConfig) + } + return await this.modernCompletions(modelId, params, middlewareConfig) } @@ -271,6 +281,109 @@ export default class ModernAiProvider { // } } + /** + * 使用现代化 AI SDK 的图像生成实现,支持流式输出 + */ + private async modernImageGeneration( + modelId: string, + params: StreamTextParams, + middlewareConfig: AiSdkMiddlewareConfig + ): Promise { + const { onChunk } = middlewareConfig + + try { + // 检查 messages 是否存在 + if (!params.messages || params.messages.length === 0) { + throw new Error('No messages provided for image generation.') + } + + // 从最后一条用户消息中提取 prompt + const lastUserMessage = params.messages.findLast((m) => m.role === 'user') + if (!lastUserMessage) { + throw new Error('No user message found for image generation.') + } + + // 直接使用消息内容,避免类型转换问题 + const prompt = + typeof lastUserMessage.content === 'string' + ? lastUserMessage.content + : lastUserMessage.content?.map((part) => ('text' in part ? part.text : '')).join('') || '' + + if (!prompt) { + throw new Error('No prompt found in user message.') + } + + // 发送图像生成开始事件 + if (onChunk) { + onChunk({ type: ChunkType.IMAGE_CREATED }) + } + + const startTime = Date.now() + + // 构建图像生成参数 + const imageParams = { + prompt, + size: '1024x1024' as `${number}x${number}`, // 默认尺寸,使用正确的类型 + n: 1, + ...(params.abortSignal && { abortSignal: params.abortSignal }) + } + + // 调用新 AI SDK 的图像生成功能 + const result = await generateImage(this.config.providerId, this.config.options, modelId, imageParams) + + // 转换结果格式 + const images: string[] = [] + const imageType: 'url' | 'base64' = 'base64' + + if (result.images) { + for (const image of result.images) { + if ('base64' in image && image.base64) { + images.push(`data:image/png;base64,${image.base64}`) + } + } + } + + // 发送图像生成完成事件 + if (onChunk && images.length > 0) { + onChunk({ + type: ChunkType.IMAGE_COMPLETE, + image: { type: imageType, images } + }) + } + + // 发送响应完成事件 + if (onChunk) { + const usage = { + prompt_tokens: 0, + completion_tokens: 0, + total_tokens: 0 + } + + onChunk({ + type: ChunkType.LLM_RESPONSE_COMPLETE, + response: { + usage, + metrics: { + completion_tokens: usage.completion_tokens, + time_first_token_millsec: 0, + time_completion_millsec: Date.now() - startTime + } + } + }) + } + + return { + getText: () => '' // 图像生成不返回文本 + } + } catch (error) { + // 发送错误事件 + if (onChunk) { + onChunk({ type: ChunkType.ERROR, error: error as any }) + } + throw error + } + } + // 代理其他方法到原有实现 public async models() { return this.legacyProvider.models() @@ -281,9 +394,51 @@ export default class ModernAiProvider { } public async generateImage(params: GenerateImageParams): Promise { + // 如果支持新的 AI SDK,使用现代化实现 + if (isModernSdkSupported(this.actualProvider)) { + try { + const result = await this.modernGenerateImage(params) + return result + } catch (error) { + console.warn('Modern AI SDK generateImage failed, falling back to legacy:', error) + // fallback 到传统实现 + return this.legacyProvider.generateImage(params) + } + } + + // 直接使用传统实现 return this.legacyProvider.generateImage(params) } + /** + * 使用现代化 AI SDK 的图像生成实现 + */ + private async modernGenerateImage(params: GenerateImageParams): Promise { + const { model, prompt, imageSize, batchSize, signal } = params + + // 转换参数格式 + const aiSdkParams = { + prompt, + size: (imageSize || '1024x1024') as `${number}x${number}`, + n: batchSize || 1, + ...(signal && { abortSignal: signal }) + } + + const result = await generateImage(this.config.providerId, this.config.options, model, aiSdkParams) + + // 转换结果格式 + const images: string[] = [] + if (result.images) { + for (const image of result.images) { + if ('base64' in image && image.base64) { + images.push(`data:image/png;base64,${image.base64}`) + } + } + } + + return images + } + public getBaseURL(): string { return this.legacyProvider.getBaseURL() } diff --git a/yarn.lock b/yarn.lock index 726196501..c427cd90a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1284,6 +1284,7 @@ __metadata: ai: "npm:5.0.0-beta.9" tsdown: "npm:^0.12.9" typescript: "npm:^5.0.0" + vitest: "npm:^1.0.0" zod: "npm:^3.25.0" languageName: unknown linkType: soft @@ -2291,6 +2292,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/aix-ppc64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/aix-ppc64@npm:0.21.5" + conditions: os=aix & cpu=ppc64 + languageName: node + linkType: hard + "@esbuild/aix-ppc64@npm:0.25.6": version: 0.25.6 resolution: "@esbuild/aix-ppc64@npm:0.25.6" @@ -2298,6 +2306,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/android-arm64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/android-arm64@npm:0.21.5" + conditions: os=android & cpu=arm64 + languageName: node + linkType: hard + "@esbuild/android-arm64@npm:0.25.6": version: 0.25.6 resolution: "@esbuild/android-arm64@npm:0.25.6" @@ -2305,6 +2320,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/android-arm@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/android-arm@npm:0.21.5" + conditions: os=android & cpu=arm + languageName: node + linkType: hard + "@esbuild/android-arm@npm:0.25.6": version: 0.25.6 resolution: "@esbuild/android-arm@npm:0.25.6" @@ -2312,6 +2334,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/android-x64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/android-x64@npm:0.21.5" + conditions: os=android & cpu=x64 + languageName: node + linkType: hard + "@esbuild/android-x64@npm:0.25.6": version: 0.25.6 resolution: "@esbuild/android-x64@npm:0.25.6" @@ -2319,6 +2348,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/darwin-arm64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/darwin-arm64@npm:0.21.5" + conditions: os=darwin & cpu=arm64 + languageName: node + linkType: hard + "@esbuild/darwin-arm64@npm:0.25.6": version: 0.25.6 resolution: "@esbuild/darwin-arm64@npm:0.25.6" @@ -2326,6 +2362,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/darwin-x64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/darwin-x64@npm:0.21.5" + conditions: os=darwin & cpu=x64 + languageName: node + linkType: hard + "@esbuild/darwin-x64@npm:0.25.6": version: 0.25.6 resolution: "@esbuild/darwin-x64@npm:0.25.6" @@ -2333,6 +2376,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/freebsd-arm64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/freebsd-arm64@npm:0.21.5" + conditions: os=freebsd & cpu=arm64 + languageName: node + linkType: hard + "@esbuild/freebsd-arm64@npm:0.25.6": version: 0.25.6 resolution: "@esbuild/freebsd-arm64@npm:0.25.6" @@ -2340,6 +2390,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/freebsd-x64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/freebsd-x64@npm:0.21.5" + conditions: os=freebsd & cpu=x64 + languageName: node + linkType: hard + "@esbuild/freebsd-x64@npm:0.25.6": version: 0.25.6 resolution: "@esbuild/freebsd-x64@npm:0.25.6" @@ -2347,6 +2404,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-arm64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/linux-arm64@npm:0.21.5" + conditions: os=linux & cpu=arm64 + languageName: node + linkType: hard + "@esbuild/linux-arm64@npm:0.25.6": version: 0.25.6 resolution: "@esbuild/linux-arm64@npm:0.25.6" @@ -2354,6 +2418,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-arm@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/linux-arm@npm:0.21.5" + conditions: os=linux & cpu=arm + languageName: node + linkType: hard + "@esbuild/linux-arm@npm:0.25.6": version: 0.25.6 resolution: "@esbuild/linux-arm@npm:0.25.6" @@ -2361,6 +2432,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-ia32@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/linux-ia32@npm:0.21.5" + conditions: os=linux & cpu=ia32 + languageName: node + linkType: hard + "@esbuild/linux-ia32@npm:0.25.6": version: 0.25.6 resolution: "@esbuild/linux-ia32@npm:0.25.6" @@ -2368,6 +2446,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-loong64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/linux-loong64@npm:0.21.5" + conditions: os=linux & cpu=loong64 + languageName: node + linkType: hard + "@esbuild/linux-loong64@npm:0.25.6": version: 0.25.6 resolution: "@esbuild/linux-loong64@npm:0.25.6" @@ -2375,6 +2460,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-mips64el@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/linux-mips64el@npm:0.21.5" + conditions: os=linux & cpu=mips64el + languageName: node + linkType: hard + "@esbuild/linux-mips64el@npm:0.25.6": version: 0.25.6 resolution: "@esbuild/linux-mips64el@npm:0.25.6" @@ -2382,6 +2474,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-ppc64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/linux-ppc64@npm:0.21.5" + conditions: os=linux & cpu=ppc64 + languageName: node + linkType: hard + "@esbuild/linux-ppc64@npm:0.25.6": version: 0.25.6 resolution: "@esbuild/linux-ppc64@npm:0.25.6" @@ -2389,6 +2488,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-riscv64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/linux-riscv64@npm:0.21.5" + conditions: os=linux & cpu=riscv64 + languageName: node + linkType: hard + "@esbuild/linux-riscv64@npm:0.25.6": version: 0.25.6 resolution: "@esbuild/linux-riscv64@npm:0.25.6" @@ -2396,6 +2502,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-s390x@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/linux-s390x@npm:0.21.5" + conditions: os=linux & cpu=s390x + languageName: node + linkType: hard + "@esbuild/linux-s390x@npm:0.25.6": version: 0.25.6 resolution: "@esbuild/linux-s390x@npm:0.25.6" @@ -2403,6 +2516,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-x64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/linux-x64@npm:0.21.5" + conditions: os=linux & cpu=x64 + languageName: node + linkType: hard + "@esbuild/linux-x64@npm:0.25.6": version: 0.25.6 resolution: "@esbuild/linux-x64@npm:0.25.6" @@ -2417,6 +2537,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/netbsd-x64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/netbsd-x64@npm:0.21.5" + conditions: os=netbsd & cpu=x64 + languageName: node + linkType: hard + "@esbuild/netbsd-x64@npm:0.25.6": version: 0.25.6 resolution: "@esbuild/netbsd-x64@npm:0.25.6" @@ -2431,6 +2558,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/openbsd-x64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/openbsd-x64@npm:0.21.5" + conditions: os=openbsd & cpu=x64 + languageName: node + linkType: hard + "@esbuild/openbsd-x64@npm:0.25.6": version: 0.25.6 resolution: "@esbuild/openbsd-x64@npm:0.25.6" @@ -2445,6 +2579,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/sunos-x64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/sunos-x64@npm:0.21.5" + conditions: os=sunos & cpu=x64 + languageName: node + linkType: hard + "@esbuild/sunos-x64@npm:0.25.6": version: 0.25.6 resolution: "@esbuild/sunos-x64@npm:0.25.6" @@ -2452,6 +2593,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/win32-arm64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/win32-arm64@npm:0.21.5" + conditions: os=win32 & cpu=arm64 + languageName: node + linkType: hard + "@esbuild/win32-arm64@npm:0.25.6": version: 0.25.6 resolution: "@esbuild/win32-arm64@npm:0.25.6" @@ -2459,6 +2607,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/win32-ia32@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/win32-ia32@npm:0.21.5" + conditions: os=win32 & cpu=ia32 + languageName: node + linkType: hard + "@esbuild/win32-ia32@npm:0.25.6": version: 0.25.6 resolution: "@esbuild/win32-ia32@npm:0.25.6" @@ -2466,6 +2621,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/win32-x64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/win32-x64@npm:0.21.5" + conditions: os=win32 & cpu=x64 + languageName: node + linkType: hard + "@esbuild/win32-x64@npm:0.25.6": version: 0.25.6 resolution: "@esbuild/win32-x64@npm:0.25.6" @@ -2861,6 +3023,15 @@ __metadata: languageName: node linkType: hard +"@jest/schemas@npm:^29.6.3": + version: 29.6.3 + resolution: "@jest/schemas@npm:29.6.3" + dependencies: + "@sinclair/typebox": "npm:^0.27.8" + checksum: 10c0/b329e89cd5f20b9278ae1233df74016ebf7b385e0d14b9f4c1ad18d096c4c19d1e687aa113a9c976b16ec07f021ae53dea811fb8c1248a50ac34fbe009fdf6be + languageName: node + linkType: hard + "@jridgewell/gen-mapping@npm:^0.3.12, @jridgewell/gen-mapping@npm:^0.3.5": version: 0.3.12 resolution: "@jridgewell/gen-mapping@npm:0.3.12" @@ -4637,6 +4808,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-android-arm-eabi@npm:4.46.2": + version: 4.46.2 + resolution: "@rollup/rollup-android-arm-eabi@npm:4.46.2" + conditions: os=android & cpu=arm + languageName: node + linkType: hard + "@rollup/rollup-android-arm64@npm:4.45.1": version: 4.45.1 resolution: "@rollup/rollup-android-arm64@npm:4.45.1" @@ -4644,6 +4822,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-android-arm64@npm:4.46.2": + version: 4.46.2 + resolution: "@rollup/rollup-android-arm64@npm:4.46.2" + conditions: os=android & cpu=arm64 + languageName: node + linkType: hard + "@rollup/rollup-darwin-arm64@npm:4.45.1": version: 4.45.1 resolution: "@rollup/rollup-darwin-arm64@npm:4.45.1" @@ -4651,6 +4836,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-darwin-arm64@npm:4.46.2": + version: 4.46.2 + resolution: "@rollup/rollup-darwin-arm64@npm:4.46.2" + conditions: os=darwin & cpu=arm64 + languageName: node + linkType: hard + "@rollup/rollup-darwin-x64@npm:4.45.1": version: 4.45.1 resolution: "@rollup/rollup-darwin-x64@npm:4.45.1" @@ -4658,6 +4850,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-darwin-x64@npm:4.46.2": + version: 4.46.2 + resolution: "@rollup/rollup-darwin-x64@npm:4.46.2" + conditions: os=darwin & cpu=x64 + languageName: node + linkType: hard + "@rollup/rollup-freebsd-arm64@npm:4.45.1": version: 4.45.1 resolution: "@rollup/rollup-freebsd-arm64@npm:4.45.1" @@ -4665,6 +4864,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-freebsd-arm64@npm:4.46.2": + version: 4.46.2 + resolution: "@rollup/rollup-freebsd-arm64@npm:4.46.2" + conditions: os=freebsd & cpu=arm64 + languageName: node + linkType: hard + "@rollup/rollup-freebsd-x64@npm:4.45.1": version: 4.45.1 resolution: "@rollup/rollup-freebsd-x64@npm:4.45.1" @@ -4672,6 +4878,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-freebsd-x64@npm:4.46.2": + version: 4.46.2 + resolution: "@rollup/rollup-freebsd-x64@npm:4.46.2" + conditions: os=freebsd & cpu=x64 + languageName: node + linkType: hard + "@rollup/rollup-linux-arm-gnueabihf@npm:4.45.1": version: 4.45.1 resolution: "@rollup/rollup-linux-arm-gnueabihf@npm:4.45.1" @@ -4679,6 +4892,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-linux-arm-gnueabihf@npm:4.46.2": + version: 4.46.2 + resolution: "@rollup/rollup-linux-arm-gnueabihf@npm:4.46.2" + conditions: os=linux & cpu=arm & libc=glibc + languageName: node + linkType: hard + "@rollup/rollup-linux-arm-musleabihf@npm:4.45.1": version: 4.45.1 resolution: "@rollup/rollup-linux-arm-musleabihf@npm:4.45.1" @@ -4686,6 +4906,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-linux-arm-musleabihf@npm:4.46.2": + version: 4.46.2 + resolution: "@rollup/rollup-linux-arm-musleabihf@npm:4.46.2" + conditions: os=linux & cpu=arm & libc=musl + languageName: node + linkType: hard + "@rollup/rollup-linux-arm64-gnu@npm:4.45.1": version: 4.45.1 resolution: "@rollup/rollup-linux-arm64-gnu@npm:4.45.1" @@ -4693,6 +4920,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-linux-arm64-gnu@npm:4.46.2": + version: 4.46.2 + resolution: "@rollup/rollup-linux-arm64-gnu@npm:4.46.2" + conditions: os=linux & cpu=arm64 & libc=glibc + languageName: node + linkType: hard + "@rollup/rollup-linux-arm64-musl@npm:4.45.1": version: 4.45.1 resolution: "@rollup/rollup-linux-arm64-musl@npm:4.45.1" @@ -4700,6 +4934,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-linux-arm64-musl@npm:4.46.2": + version: 4.46.2 + resolution: "@rollup/rollup-linux-arm64-musl@npm:4.46.2" + conditions: os=linux & cpu=arm64 & libc=musl + languageName: node + linkType: hard + "@rollup/rollup-linux-loongarch64-gnu@npm:4.45.1": version: 4.45.1 resolution: "@rollup/rollup-linux-loongarch64-gnu@npm:4.45.1" @@ -4707,6 +4948,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-linux-loongarch64-gnu@npm:4.46.2": + version: 4.46.2 + resolution: "@rollup/rollup-linux-loongarch64-gnu@npm:4.46.2" + conditions: os=linux & cpu=loong64 & libc=glibc + languageName: node + linkType: hard + "@rollup/rollup-linux-powerpc64le-gnu@npm:4.45.1": version: 4.45.1 resolution: "@rollup/rollup-linux-powerpc64le-gnu@npm:4.45.1" @@ -4714,6 +4962,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-linux-ppc64-gnu@npm:4.46.2": + version: 4.46.2 + resolution: "@rollup/rollup-linux-ppc64-gnu@npm:4.46.2" + conditions: os=linux & cpu=ppc64 & libc=glibc + languageName: node + linkType: hard + "@rollup/rollup-linux-riscv64-gnu@npm:4.45.1": version: 4.45.1 resolution: "@rollup/rollup-linux-riscv64-gnu@npm:4.45.1" @@ -4721,6 +4976,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-linux-riscv64-gnu@npm:4.46.2": + version: 4.46.2 + resolution: "@rollup/rollup-linux-riscv64-gnu@npm:4.46.2" + conditions: os=linux & cpu=riscv64 & libc=glibc + languageName: node + linkType: hard + "@rollup/rollup-linux-riscv64-musl@npm:4.45.1": version: 4.45.1 resolution: "@rollup/rollup-linux-riscv64-musl@npm:4.45.1" @@ -4728,6 +4990,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-linux-riscv64-musl@npm:4.46.2": + version: 4.46.2 + resolution: "@rollup/rollup-linux-riscv64-musl@npm:4.46.2" + conditions: os=linux & cpu=riscv64 & libc=musl + languageName: node + linkType: hard + "@rollup/rollup-linux-s390x-gnu@npm:4.45.1": version: 4.45.1 resolution: "@rollup/rollup-linux-s390x-gnu@npm:4.45.1" @@ -4735,6 +5004,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-linux-s390x-gnu@npm:4.46.2": + version: 4.46.2 + resolution: "@rollup/rollup-linux-s390x-gnu@npm:4.46.2" + conditions: os=linux & cpu=s390x & libc=glibc + languageName: node + linkType: hard + "@rollup/rollup-linux-x64-gnu@npm:4.45.1": version: 4.45.1 resolution: "@rollup/rollup-linux-x64-gnu@npm:4.45.1" @@ -4742,6 +5018,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-linux-x64-gnu@npm:4.46.2": + version: 4.46.2 + resolution: "@rollup/rollup-linux-x64-gnu@npm:4.46.2" + conditions: os=linux & cpu=x64 & libc=glibc + languageName: node + linkType: hard + "@rollup/rollup-linux-x64-musl@npm:4.45.1": version: 4.45.1 resolution: "@rollup/rollup-linux-x64-musl@npm:4.45.1" @@ -4749,6 +5032,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-linux-x64-musl@npm:4.46.2": + version: 4.46.2 + resolution: "@rollup/rollup-linux-x64-musl@npm:4.46.2" + conditions: os=linux & cpu=x64 & libc=musl + languageName: node + linkType: hard + "@rollup/rollup-win32-arm64-msvc@npm:4.45.1": version: 4.45.1 resolution: "@rollup/rollup-win32-arm64-msvc@npm:4.45.1" @@ -4756,6 +5046,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-win32-arm64-msvc@npm:4.46.2": + version: 4.46.2 + resolution: "@rollup/rollup-win32-arm64-msvc@npm:4.46.2" + conditions: os=win32 & cpu=arm64 + languageName: node + linkType: hard + "@rollup/rollup-win32-ia32-msvc@npm:4.45.1": version: 4.45.1 resolution: "@rollup/rollup-win32-ia32-msvc@npm:4.45.1" @@ -4763,6 +5060,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-win32-ia32-msvc@npm:4.46.2": + version: 4.46.2 + resolution: "@rollup/rollup-win32-ia32-msvc@npm:4.46.2" + conditions: os=win32 & cpu=ia32 + languageName: node + linkType: hard + "@rollup/rollup-win32-x64-msvc@npm:4.45.1": version: 4.45.1 resolution: "@rollup/rollup-win32-x64-msvc@npm:4.45.1" @@ -4770,6 +5074,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-win32-x64-msvc@npm:4.46.2": + version: 4.46.2 + resolution: "@rollup/rollup-win32-x64-msvc@npm:4.46.2" + conditions: os=win32 & cpu=x64 + languageName: node + linkType: hard + "@selderee/plugin-htmlparser2@npm:^0.11.0": version: 0.11.0 resolution: "@selderee/plugin-htmlparser2@npm:0.11.0" @@ -4863,6 +5174,13 @@ __metadata: languageName: node linkType: hard +"@sinclair/typebox@npm:^0.27.8": + version: 0.27.8 + resolution: "@sinclair/typebox@npm:0.27.8" + checksum: 10c0/ef6351ae073c45c2ac89494dbb3e1f87cc60a93ce4cde797b782812b6f97da0d620ae81973f104b43c9b7eaa789ad20ba4f6a1359f1cc62f63729a55a7d22d4e + languageName: node + linkType: hard + "@sindresorhus/is@npm:^4.0.0": version: 4.6.0 resolution: "@sindresorhus/is@npm:4.6.0" @@ -7159,6 +7477,17 @@ __metadata: languageName: node linkType: hard +"@vitest/expect@npm:1.6.1": + version: 1.6.1 + resolution: "@vitest/expect@npm:1.6.1" + dependencies: + "@vitest/spy": "npm:1.6.1" + "@vitest/utils": "npm:1.6.1" + chai: "npm:^4.3.10" + checksum: 10c0/278164b2a32a7019b443444f21111c5e32e4cadee026cae047ae2a3b347d99dca1d1fb7b79509c88b67dc3db19fa9a16265b7d7a8377485f7e37f7851e44495a + languageName: node + linkType: hard + "@vitest/expect@npm:3.2.4": version: 3.2.4 resolution: "@vitest/expect@npm:3.2.4" @@ -7200,6 +7529,17 @@ __metadata: languageName: node linkType: hard +"@vitest/runner@npm:1.6.1": + version: 1.6.1 + resolution: "@vitest/runner@npm:1.6.1" + dependencies: + "@vitest/utils": "npm:1.6.1" + p-limit: "npm:^5.0.0" + pathe: "npm:^1.1.1" + checksum: 10c0/36333f1a596c4ad85d42c6126cc32959c984d584ef28d366d366fa3672678c1a0f5e5c2e8717a36675b6620b57e8830f765d6712d1687f163ed0a8ebf23c87db + languageName: node + linkType: hard + "@vitest/runner@npm:3.2.4": version: 3.2.4 resolution: "@vitest/runner@npm:3.2.4" @@ -7211,6 +7551,17 @@ __metadata: languageName: node linkType: hard +"@vitest/snapshot@npm:1.6.1": + version: 1.6.1 + resolution: "@vitest/snapshot@npm:1.6.1" + dependencies: + magic-string: "npm:^0.30.5" + pathe: "npm:^1.1.1" + pretty-format: "npm:^29.7.0" + checksum: 10c0/68bbc3132c195ec37376469e4b183fc408e0aeedd827dffcc899aac378e9ea324825f0873062786e18f00e3da9dd8a93c9bb871c07471ee483e8df963cb272eb + languageName: node + linkType: hard + "@vitest/snapshot@npm:3.2.4": version: 3.2.4 resolution: "@vitest/snapshot@npm:3.2.4" @@ -7222,6 +7573,15 @@ __metadata: languageName: node linkType: hard +"@vitest/spy@npm:1.6.1": + version: 1.6.1 + resolution: "@vitest/spy@npm:1.6.1" + dependencies: + tinyspy: "npm:^2.2.0" + checksum: 10c0/5207ec0e7882819f0e0811293ae6d14163e26927e781bb4de7d40b3bd99c1fae656934c437bb7a30443a3e7e736c5bccb037bbf4436dbbc83d29e65247888885 + languageName: node + linkType: hard + "@vitest/spy@npm:3.2.4": version: 3.2.4 resolution: "@vitest/spy@npm:3.2.4" @@ -7248,6 +7608,18 @@ __metadata: languageName: node linkType: hard +"@vitest/utils@npm:1.6.1": + version: 1.6.1 + resolution: "@vitest/utils@npm:1.6.1" + dependencies: + diff-sequences: "npm:^29.6.3" + estree-walker: "npm:^3.0.3" + loupe: "npm:^2.3.7" + pretty-format: "npm:^29.7.0" + checksum: 10c0/0d4c619e5688cbc22a60c412719c6baa40376b7671bdbdc3072552f5c5a5ee5d24a96ea328b054018debd49e0626a5e3db672921b2c6b5b17b9a52edd296806a + languageName: node + linkType: hard + "@vitest/utils@npm:3.2.4": version: 3.2.4 resolution: "@vitest/utils@npm:3.2.4" @@ -7604,7 +7976,16 @@ __metadata: languageName: node linkType: hard -"acorn@npm:^8.14.0, acorn@npm:^8.15.0": +"acorn-walk@npm:^8.3.2": + version: 8.3.4 + resolution: "acorn-walk@npm:8.3.4" + dependencies: + acorn: "npm:^8.11.0" + checksum: 10c0/76537ac5fb2c37a64560feaf3342023dadc086c46da57da363e64c6148dc21b57d49ace26f949e225063acb6fb441eabffd89f7a3066de5ad37ab3e328927c62 + languageName: node + linkType: hard + +"acorn@npm:^8.11.0, acorn@npm:^8.14.0, acorn@npm:^8.15.0": version: 8.15.0 resolution: "acorn@npm:8.15.0" bin: @@ -8077,6 +8458,13 @@ __metadata: languageName: node linkType: hard +"assertion-error@npm:^1.1.0": + version: 1.1.0 + resolution: "assertion-error@npm:1.1.0" + checksum: 10c0/25456b2aa333250f01143968e02e4884a34588a8538fbbf65c91a637f1dbfb8069249133cd2f4e530f10f624d206a664e7df30207830b659e9f5298b00a4099b + languageName: node + linkType: hard + "assertion-error@npm:^2.0.1": version: 2.0.1 resolution: "assertion-error@npm:2.0.1" @@ -8680,6 +9068,21 @@ __metadata: languageName: node linkType: hard +"chai@npm:^4.3.10": + version: 4.5.0 + resolution: "chai@npm:4.5.0" + dependencies: + assertion-error: "npm:^1.1.0" + check-error: "npm:^1.0.3" + deep-eql: "npm:^4.1.3" + get-func-name: "npm:^2.0.2" + loupe: "npm:^2.3.6" + pathval: "npm:^1.1.1" + type-detect: "npm:^4.1.0" + checksum: 10c0/b8cb596bd1aece1aec659e41a6e479290c7d9bee5b3ad63d2898ad230064e5b47889a3bc367b20100a0853b62e026e2dc514acf25a3c9385f936aa3614d4ab4d + languageName: node + linkType: hard + "chai@npm:^5.2.0": version: 5.2.1 resolution: "chai@npm:5.2.1" @@ -8786,6 +9189,15 @@ __metadata: languageName: node linkType: hard +"check-error@npm:^1.0.3": + version: 1.0.3 + resolution: "check-error@npm:1.0.3" + dependencies: + get-func-name: "npm:^2.0.2" + checksum: 10c0/94aa37a7315c0e8a83d0112b5bfb5a8624f7f0f81057c73e4707729cdd8077166c6aefb3d8e2b92c63ee130d4a2ff94bad46d547e12f3238cc1d78342a973841 + languageName: node + linkType: hard + "check-error@npm:^2.1.1": version: 2.1.1 resolution: "check-error@npm:2.1.1" @@ -10014,6 +10426,15 @@ __metadata: languageName: node linkType: hard +"deep-eql@npm:^4.1.3": + version: 4.1.4 + resolution: "deep-eql@npm:4.1.4" + dependencies: + type-detect: "npm:^4.0.0" + checksum: 10c0/264e0613493b43552fc908f4ff87b8b445c0e6e075656649600e1b8a17a57ee03e960156fce7177646e4d2ddaf8e5ee616d76bd79929ff593e5c79e4e5e6c517 + languageName: node + linkType: hard + "deep-eql@npm:^5.0.1": version: 5.0.2 resolution: "deep-eql@npm:5.0.2" @@ -10206,6 +10627,13 @@ __metadata: languageName: node linkType: hard +"diff-sequences@npm:^29.6.3": + version: 29.6.3 + resolution: "diff-sequences@npm:29.6.3" + checksum: 10c0/32e27ac7dbffdf2fb0eb5a84efd98a9ad084fbabd5ac9abb8757c6770d5320d2acd172830b28c4add29bb873d59420601dfc805ac4064330ce59b1adfd0593b2 + languageName: node + linkType: hard + "diff@npm:^7.0.0": version: 7.0.0 resolution: "diff@npm:7.0.0" @@ -10785,6 +11213,86 @@ __metadata: languageName: node linkType: hard +"esbuild@npm:^0.21.3": + version: 0.21.5 + resolution: "esbuild@npm:0.21.5" + dependencies: + "@esbuild/aix-ppc64": "npm:0.21.5" + "@esbuild/android-arm": "npm:0.21.5" + "@esbuild/android-arm64": "npm:0.21.5" + "@esbuild/android-x64": "npm:0.21.5" + "@esbuild/darwin-arm64": "npm:0.21.5" + "@esbuild/darwin-x64": "npm:0.21.5" + "@esbuild/freebsd-arm64": "npm:0.21.5" + "@esbuild/freebsd-x64": "npm:0.21.5" + "@esbuild/linux-arm": "npm:0.21.5" + "@esbuild/linux-arm64": "npm:0.21.5" + "@esbuild/linux-ia32": "npm:0.21.5" + "@esbuild/linux-loong64": "npm:0.21.5" + "@esbuild/linux-mips64el": "npm:0.21.5" + "@esbuild/linux-ppc64": "npm:0.21.5" + "@esbuild/linux-riscv64": "npm:0.21.5" + "@esbuild/linux-s390x": "npm:0.21.5" + "@esbuild/linux-x64": "npm:0.21.5" + "@esbuild/netbsd-x64": "npm:0.21.5" + "@esbuild/openbsd-x64": "npm:0.21.5" + "@esbuild/sunos-x64": "npm:0.21.5" + "@esbuild/win32-arm64": "npm:0.21.5" + "@esbuild/win32-ia32": "npm:0.21.5" + "@esbuild/win32-x64": "npm:0.21.5" + dependenciesMeta: + "@esbuild/aix-ppc64": + optional: true + "@esbuild/android-arm": + optional: true + "@esbuild/android-arm64": + optional: true + "@esbuild/android-x64": + optional: true + "@esbuild/darwin-arm64": + optional: true + "@esbuild/darwin-x64": + optional: true + "@esbuild/freebsd-arm64": + optional: true + "@esbuild/freebsd-x64": + optional: true + "@esbuild/linux-arm": + optional: true + "@esbuild/linux-arm64": + optional: true + "@esbuild/linux-ia32": + optional: true + "@esbuild/linux-loong64": + optional: true + "@esbuild/linux-mips64el": + optional: true + "@esbuild/linux-ppc64": + optional: true + "@esbuild/linux-riscv64": + optional: true + "@esbuild/linux-s390x": + optional: true + "@esbuild/linux-x64": + optional: true + "@esbuild/netbsd-x64": + optional: true + "@esbuild/openbsd-x64": + optional: true + "@esbuild/sunos-x64": + optional: true + "@esbuild/win32-arm64": + optional: true + "@esbuild/win32-ia32": + optional: true + "@esbuild/win32-x64": + optional: true + bin: + esbuild: bin/esbuild + checksum: 10c0/fa08508adf683c3f399e8a014a6382a6b65542213431e26206c0720e536b31c09b50798747c2a105a4bbba1d9767b8d3615a74c2f7bf1ddf6d836cd11eb672de + languageName: node + linkType: hard + "esbuild@npm:^0.25.0, esbuild@npm:^0.25.1": version: 0.25.6 resolution: "esbuild@npm:0.25.6" @@ -12106,6 +12614,13 @@ __metadata: languageName: node linkType: hard +"get-func-name@npm:^2.0.1, get-func-name@npm:^2.0.2": + version: 2.0.2 + resolution: "get-func-name@npm:2.0.2" + checksum: 10c0/89830fd07623fa73429a711b9daecdb304386d237c71268007f788f113505ef1d4cc2d0b9680e072c5082490aec9df5d7758bf5ac6f1c37062855e8e3dc0b9df + languageName: node + linkType: hard + "get-intrinsic@npm:^1.2.4, get-intrinsic@npm:^1.2.5, get-intrinsic@npm:^1.2.6, get-intrinsic@npm:^1.3.0": version: 1.3.0 resolution: "get-intrinsic@npm:1.3.0" @@ -14066,6 +14581,16 @@ __metadata: languageName: node linkType: hard +"local-pkg@npm:^0.5.0": + version: 0.5.1 + resolution: "local-pkg@npm:0.5.1" + dependencies: + mlly: "npm:^1.7.3" + pkg-types: "npm:^1.2.1" + checksum: 10c0/ade8346f1dc04875921461adee3c40774b00d4b74095261222ebd4d5fd0a444676e36e325f76760f21af6a60bc82480e154909b54d2d9f7173671e36dacf1808 + languageName: node + linkType: hard + "local-pkg@npm:^1.0.0": version: 1.1.1 resolution: "local-pkg@npm:1.1.1" @@ -14193,6 +14718,15 @@ __metadata: languageName: node linkType: hard +"loupe@npm:^2.3.6, loupe@npm:^2.3.7": + version: 2.3.7 + resolution: "loupe@npm:2.3.7" + dependencies: + get-func-name: "npm:^2.0.1" + checksum: 10c0/71a781c8fc21527b99ed1062043f1f2bb30bdaf54fa4cf92463427e1718bc6567af2988300bc243c1f276e4f0876f29e3cbf7b58106fdc186915687456ce5bf4 + languageName: node + linkType: hard + "loupe@npm:^3.1.0, loupe@npm:^3.1.4": version: 3.1.4 resolution: "loupe@npm:3.1.4" @@ -14285,7 +14819,7 @@ __metadata: languageName: node linkType: hard -"magic-string@npm:^0.30.17": +"magic-string@npm:^0.30.17, magic-string@npm:^0.30.5": version: 0.30.17 resolution: "magic-string@npm:0.30.17" dependencies: @@ -15739,7 +16273,7 @@ __metadata: languageName: node linkType: hard -"mlly@npm:^1.7.4": +"mlly@npm:^1.7.3, mlly@npm:^1.7.4": version: 1.7.4 resolution: "mlly@npm:1.7.4" dependencies: @@ -16561,6 +17095,15 @@ __metadata: languageName: node linkType: hard +"p-limit@npm:^5.0.0": + version: 5.0.0 + resolution: "p-limit@npm:5.0.0" + dependencies: + yocto-queue: "npm:^1.0.0" + checksum: 10c0/574e93b8895a26e8485eb1df7c4b58a1a6e8d8ae41b1750cc2cc440922b3d306044fc6e9a7f74578a883d46802d9db72b30f2e612690fcef838c173261b1ed83 + languageName: node + linkType: hard + "p-locate@npm:^3.0.0": version: 3.0.0 resolution: "p-locate@npm:3.0.0" @@ -16832,6 +17375,13 @@ __metadata: languageName: node linkType: hard +"pathe@npm:^1.1.1": + version: 1.1.2 + resolution: "pathe@npm:1.1.2" + checksum: 10c0/64ee0a4e587fb0f208d9777a6c56e4f9050039268faaaaecd50e959ef01bf847b7872785c36483fa5cdcdbdfdb31fef2ff222684d4fc21c330ab60395c681897 + languageName: node + linkType: hard + "pathe@npm:^2.0.1, pathe@npm:^2.0.3": version: 2.0.3 resolution: "pathe@npm:2.0.3" @@ -16839,6 +17389,13 @@ __metadata: languageName: node linkType: hard +"pathval@npm:^1.1.1": + version: 1.1.1 + resolution: "pathval@npm:1.1.1" + checksum: 10c0/f63e1bc1b33593cdf094ed6ff5c49c1c0dc5dc20a646ca9725cc7fe7cd9995002d51d5685b9b2ec6814342935748b711bafa840f84c0bb04e38ff40a335c94dc + languageName: node + linkType: hard + "pathval@npm:^2.0.0": version: 2.0.1 resolution: "pathval@npm:2.0.1" @@ -16913,7 +17470,7 @@ __metadata: languageName: node linkType: hard -"picocolors@npm:^1.1.1": +"picocolors@npm:^1.0.0, picocolors@npm:^1.1.1": version: 1.1.1 resolution: "picocolors@npm:1.1.1" checksum: 10c0/e2e3e8170ab9d7c7421969adaa7e1b31434f789afb9b3f115f6b96d91945041ac3ceb02e9ec6fe6510ff036bcc0bf91e69a1772edc0b707e12b19c0f2d6bcf58 @@ -16980,7 +17537,7 @@ __metadata: languageName: node linkType: hard -"pkg-types@npm:^1.3.0": +"pkg-types@npm:^1.2.1, pkg-types@npm:^1.3.0": version: 1.3.1 resolution: "pkg-types@npm:1.3.1" dependencies: @@ -17098,7 +17655,7 @@ __metadata: languageName: node linkType: hard -"postcss@npm:^8.5.3, postcss@npm:^8.5.6": +"postcss@npm:^8.4.43, postcss@npm:^8.5.3, postcss@npm:^8.5.6": version: 8.5.6 resolution: "postcss@npm:8.5.6" dependencies: @@ -17170,6 +17727,17 @@ __metadata: languageName: node linkType: hard +"pretty-format@npm:^29.7.0": + version: 29.7.0 + resolution: "pretty-format@npm:29.7.0" + dependencies: + "@jest/schemas": "npm:^29.6.3" + ansi-styles: "npm:^5.0.0" + react-is: "npm:^18.0.0" + checksum: 10c0/edc5ff89f51916f036c62ed433506b55446ff739358de77207e63e88a28ca2894caac6e73dcb68166a606e51c8087d32d400473e6a9fdd2dbe743f46c9c0276f + languageName: node + linkType: hard + "proc-log@npm:^2.0.1": version: 2.0.1 resolution: "proc-log@npm:2.0.1" @@ -18732,6 +19300,81 @@ __metadata: languageName: node linkType: hard +"rollup@npm:^4.20.0": + version: 4.46.2 + resolution: "rollup@npm:4.46.2" + dependencies: + "@rollup/rollup-android-arm-eabi": "npm:4.46.2" + "@rollup/rollup-android-arm64": "npm:4.46.2" + "@rollup/rollup-darwin-arm64": "npm:4.46.2" + "@rollup/rollup-darwin-x64": "npm:4.46.2" + "@rollup/rollup-freebsd-arm64": "npm:4.46.2" + "@rollup/rollup-freebsd-x64": "npm:4.46.2" + "@rollup/rollup-linux-arm-gnueabihf": "npm:4.46.2" + "@rollup/rollup-linux-arm-musleabihf": "npm:4.46.2" + "@rollup/rollup-linux-arm64-gnu": "npm:4.46.2" + "@rollup/rollup-linux-arm64-musl": "npm:4.46.2" + "@rollup/rollup-linux-loongarch64-gnu": "npm:4.46.2" + "@rollup/rollup-linux-ppc64-gnu": "npm:4.46.2" + "@rollup/rollup-linux-riscv64-gnu": "npm:4.46.2" + "@rollup/rollup-linux-riscv64-musl": "npm:4.46.2" + "@rollup/rollup-linux-s390x-gnu": "npm:4.46.2" + "@rollup/rollup-linux-x64-gnu": "npm:4.46.2" + "@rollup/rollup-linux-x64-musl": "npm:4.46.2" + "@rollup/rollup-win32-arm64-msvc": "npm:4.46.2" + "@rollup/rollup-win32-ia32-msvc": "npm:4.46.2" + "@rollup/rollup-win32-x64-msvc": "npm:4.46.2" + "@types/estree": "npm:1.0.8" + fsevents: "npm:~2.3.2" + dependenciesMeta: + "@rollup/rollup-android-arm-eabi": + optional: true + "@rollup/rollup-android-arm64": + optional: true + "@rollup/rollup-darwin-arm64": + optional: true + "@rollup/rollup-darwin-x64": + optional: true + "@rollup/rollup-freebsd-arm64": + optional: true + "@rollup/rollup-freebsd-x64": + optional: true + "@rollup/rollup-linux-arm-gnueabihf": + optional: true + "@rollup/rollup-linux-arm-musleabihf": + optional: true + "@rollup/rollup-linux-arm64-gnu": + optional: true + "@rollup/rollup-linux-arm64-musl": + optional: true + "@rollup/rollup-linux-loongarch64-gnu": + optional: true + "@rollup/rollup-linux-ppc64-gnu": + optional: true + "@rollup/rollup-linux-riscv64-gnu": + optional: true + "@rollup/rollup-linux-riscv64-musl": + optional: true + "@rollup/rollup-linux-s390x-gnu": + optional: true + "@rollup/rollup-linux-x64-gnu": + optional: true + "@rollup/rollup-linux-x64-musl": + optional: true + "@rollup/rollup-win32-arm64-msvc": + optional: true + "@rollup/rollup-win32-ia32-msvc": + optional: true + "@rollup/rollup-win32-x64-msvc": + optional: true + fsevents: + optional: true + bin: + rollup: dist/bin/rollup + checksum: 10c0/f428497fe119fe7c4e34f1020d45ba13e99b94c9aa36958d88823d932b155c9df3d84f53166f3ee913ff68ea6c7599a9ab34861d88562ad9d8420f64ca5dad4c + languageName: node + linkType: hard + "rollup@npm:^4.30.1, rollup@npm:^4.40.0": version: 4.45.1 resolution: "rollup@npm:4.45.1" @@ -19430,7 +20073,7 @@ __metadata: languageName: node linkType: hard -"std-env@npm:^3.9.0": +"std-env@npm:^3.5.0, std-env@npm:^3.9.0": version: 3.9.0 resolution: "std-env@npm:3.9.0" checksum: 10c0/4a6f9218aef3f41046c3c7ecf1f98df00b30a07f4f35c6d47b28329bc2531eef820828951c7d7b39a1c5eb19ad8a46e3ddfc7deb28f0a2f3ceebee11bab7ba50 @@ -19630,6 +20273,15 @@ __metadata: languageName: node linkType: hard +"strip-literal@npm:^2.0.0": + version: 2.1.1 + resolution: "strip-literal@npm:2.1.1" + dependencies: + js-tokens: "npm:^9.0.1" + checksum: 10c0/66a7353f5ba1ae6a4fb2805b4aba228171847200640083117c41512692e6b2c020e18580402984f55c0ae69c30f857f9a55abd672863e4ca8fdb463fdf93ba19 + languageName: node + linkType: hard + "strip-literal@npm:^3.0.0": version: 3.0.0 resolution: "strip-literal@npm:3.0.0" @@ -19957,7 +20609,7 @@ __metadata: languageName: node linkType: hard -"tinybench@npm:^2.9.0": +"tinybench@npm:^2.5.1, tinybench@npm:^2.9.0": version: 2.9.0 resolution: "tinybench@npm:2.9.0" checksum: 10c0/c3500b0f60d2eb8db65250afe750b66d51623057ee88720b7f064894a6cb7eb93360ca824a60a31ab16dab30c7b1f06efe0795b352e37914a9d4bad86386a20c @@ -19988,6 +20640,13 @@ __metadata: languageName: node linkType: hard +"tinypool@npm:^0.8.3": + version: 0.8.4 + resolution: "tinypool@npm:0.8.4" + checksum: 10c0/779c790adcb0316a45359652f4b025958c1dff5a82460fe49f553c864309b12ad732c8288be52f852973bc76317f5e7b3598878aee0beb8a33322c0e72c4a66c + languageName: node + linkType: hard + "tinypool@npm:^1.1.1": version: 1.1.1 resolution: "tinypool@npm:1.1.1" @@ -20002,6 +20661,13 @@ __metadata: languageName: node linkType: hard +"tinyspy@npm:^2.2.0": + version: 2.2.1 + resolution: "tinyspy@npm:2.2.1" + checksum: 10c0/0b4cfd07c09871e12c592dfa7b91528124dc49a4766a0b23350638c62e6a483d5a2a667de7e6282246c0d4f09996482ddaacbd01f0c05b7ed7e0f79d32409bdc + languageName: node + linkType: hard + "tinyspy@npm:^4.0.3": version: 4.0.3 resolution: "tinyspy@npm:4.0.3" @@ -20298,6 +20964,13 @@ __metadata: languageName: node linkType: hard +"type-detect@npm:^4.0.0, type-detect@npm:^4.1.0": + version: 4.1.0 + resolution: "type-detect@npm:4.1.0" + checksum: 10c0/df8157ca3f5d311edc22885abc134e18ff8ffbc93d6a9848af5b682730ca6a5a44499259750197250479c5331a8a75b5537529df5ec410622041650a7f293e2a + languageName: node + linkType: hard + "type-fest@npm:^0.13.1": version: 0.13.1 resolution: "type-fest@npm:0.13.1" @@ -20832,6 +21505,21 @@ __metadata: languageName: node linkType: hard +"vite-node@npm:1.6.1": + version: 1.6.1 + resolution: "vite-node@npm:1.6.1" + dependencies: + cac: "npm:^6.7.14" + debug: "npm:^4.3.4" + pathe: "npm:^1.1.1" + picocolors: "npm:^1.0.0" + vite: "npm:^5.0.0" + bin: + vite-node: vite-node.mjs + checksum: 10c0/4d96da9f11bd0df8b60c46e65a740edaad7dd2d1aff3cdb3da5714ea8c10b5f2683111b60bfe45545c7e8c1f33e7e8a5095573d5e9ba55f50a845233292c2e02 + languageName: node + linkType: hard + "vite-node@npm:3.2.4": version: 3.2.4 resolution: "vite-node@npm:3.2.4" @@ -20899,6 +21587,49 @@ __metadata: languageName: node linkType: hard +"vite@npm:^5.0.0": + version: 5.4.19 + resolution: "vite@npm:5.4.19" + dependencies: + esbuild: "npm:^0.21.3" + fsevents: "npm:~2.3.3" + postcss: "npm:^8.4.43" + rollup: "npm:^4.20.0" + peerDependencies: + "@types/node": ^18.0.0 || >=20.0.0 + less: "*" + lightningcss: ^1.21.0 + sass: "*" + sass-embedded: "*" + stylus: "*" + sugarss: "*" + terser: ^5.4.0 + dependenciesMeta: + fsevents: + optional: true + peerDependenciesMeta: + "@types/node": + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + bin: + vite: bin/vite.js + checksum: 10c0/c97601234dba482cea5290f2a2ea0fcd65e1fab3df06718ea48adc8ceb14bc3129508216c4989329c618f6a0470b42f439677a207aef62b0c76f445091c2d89e + languageName: node + linkType: hard + "vite@npm:^5.0.0 || ^6.0.0 || ^7.0.0-0": version: 7.0.5 resolution: "vite@npm:7.0.5" @@ -20954,6 +21685,56 @@ __metadata: languageName: node linkType: hard +"vitest@npm:^1.0.0": + version: 1.6.1 + resolution: "vitest@npm:1.6.1" + dependencies: + "@vitest/expect": "npm:1.6.1" + "@vitest/runner": "npm:1.6.1" + "@vitest/snapshot": "npm:1.6.1" + "@vitest/spy": "npm:1.6.1" + "@vitest/utils": "npm:1.6.1" + acorn-walk: "npm:^8.3.2" + chai: "npm:^4.3.10" + debug: "npm:^4.3.4" + execa: "npm:^8.0.1" + local-pkg: "npm:^0.5.0" + magic-string: "npm:^0.30.5" + pathe: "npm:^1.1.1" + picocolors: "npm:^1.0.0" + std-env: "npm:^3.5.0" + strip-literal: "npm:^2.0.0" + tinybench: "npm:^2.5.1" + tinypool: "npm:^0.8.3" + vite: "npm:^5.0.0" + vite-node: "npm:1.6.1" + why-is-node-running: "npm:^2.2.2" + peerDependencies: + "@edge-runtime/vm": "*" + "@types/node": ^18.0.0 || >=20.0.0 + "@vitest/browser": 1.6.1 + "@vitest/ui": 1.6.1 + happy-dom: "*" + jsdom: "*" + peerDependenciesMeta: + "@edge-runtime/vm": + optional: true + "@types/node": + optional: true + "@vitest/browser": + optional: true + "@vitest/ui": + optional: true + happy-dom: + optional: true + jsdom: + optional: true + bin: + vitest: vitest.mjs + checksum: 10c0/511d27d7f697683964826db2fad7ac303f9bc7eeb59d9422111dc488371ccf1f9eed47ac3a80eb47ca86b7242228ba5ca9cc3613290830d0e916973768cac215 + languageName: node + linkType: hard + "vitest@npm:^3.1.4": version: 3.2.4 resolution: "vitest@npm:3.2.4" @@ -21260,7 +22041,7 @@ __metadata: languageName: node linkType: hard -"why-is-node-running@npm:^2.3.0": +"why-is-node-running@npm:^2.2.2, why-is-node-running@npm:^2.3.0": version: 2.3.0 resolution: "why-is-node-running@npm:2.3.0" dependencies: @@ -21541,6 +22322,13 @@ __metadata: languageName: node linkType: hard +"yocto-queue@npm:^1.0.0": + version: 1.2.1 + resolution: "yocto-queue@npm:1.2.1" + checksum: 10c0/5762caa3d0b421f4bdb7a1926b2ae2189fc6e4a14469258f183600028eb16db3e9e0306f46e8ebf5a52ff4b81a881f22637afefbef5399d6ad440824e9b27f9f + languageName: node + linkType: hard + "zip-stream@npm:^6.0.1": version: 6.0.1 resolution: "zip-stream@npm:6.0.1"