From 8ca6341609c3e3b44279072369550fb9cee666a5 Mon Sep 17 00:00:00 2001 From: suyao Date: Sat, 21 Jun 2025 12:48:53 +0800 Subject: [PATCH] feat: add openai-compatible provider and enhance provider configuration - Introduced the @ai-sdk/openai-compatible package to support compatibility with OpenAI. - Added a new ProviderConfigFactory and ProviderConfigBuilder for streamlined provider configuration. - Updated the provider registry to include the new Google Vertex AI import path. - Enhanced the index.ts to export new provider configuration utilities for better type safety and usability. - Refactored ApiService and middleware to integrate the new provider configurations effectively. --- packages/aiCore/package.json | 1 + packages/aiCore/pnpm-lock.yaml | 1022 +++++++++++++++++ packages/aiCore/src/index.ts | 9 + packages/aiCore/src/providers/factory.ts | 330 ++++++ packages/aiCore/src/providers/registry.ts | 5 +- src/renderer/src/aiCore/index_new.ts | 58 +- .../aisdk/AiSdkMiddlewareBuilder.ts | 7 +- .../aisdk/ThinkingTimeMiddleware.ts | 5 +- src/renderer/src/aiCore/provider/factory.ts | 24 + .../src/aiCore/transformParameters.ts | 2 +- src/renderer/src/services/ApiService.ts | 1 + 11 files changed, 1413 insertions(+), 51 deletions(-) create mode 100644 packages/aiCore/pnpm-lock.yaml create mode 100644 packages/aiCore/src/providers/factory.ts create mode 100644 src/renderer/src/aiCore/provider/factory.ts diff --git a/packages/aiCore/package.json b/packages/aiCore/package.json index aec2760321..853753a176 100644 --- a/packages/aiCore/package.json +++ b/packages/aiCore/package.json @@ -35,6 +35,7 @@ "@ai-sdk/groq": "^1.2.9", "@ai-sdk/mistral": "^1.2.8", "@ai-sdk/openai": "^1.3.22", + "@ai-sdk/openai-compatible": "^0.2.14", "@ai-sdk/perplexity": "^1.1.9", "@ai-sdk/replicate": "^0.2.8", "@ai-sdk/togetherai": "^0.2.14", diff --git a/packages/aiCore/pnpm-lock.yaml b/packages/aiCore/pnpm-lock.yaml new file mode 100644 index 0000000000..6d16b5d833 --- /dev/null +++ b/packages/aiCore/pnpm-lock.yaml @@ -0,0 +1,1022 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + dependencies: + '@ai-sdk/amazon-bedrock': + specifier: ^2.2.10 + version: 2.2.10(zod@3.25.67) + '@ai-sdk/anthropic': + specifier: ^1.2.12 + version: 1.2.12(zod@3.25.67) + '@ai-sdk/azure': + specifier: ^1.3.23 + version: 1.3.23(zod@3.25.67) + '@ai-sdk/cerebras': + specifier: ^0.2.14 + version: 0.2.14(zod@3.25.67) + '@ai-sdk/cohere': + specifier: ^1.2.10 + version: 1.2.10(zod@3.25.67) + '@ai-sdk/deepinfra': + specifier: ^0.2.15 + version: 0.2.15(zod@3.25.67) + '@ai-sdk/deepseek': + specifier: ^0.2.14 + version: 0.2.14(zod@3.25.67) + '@ai-sdk/fal': + specifier: ^0.1.12 + version: 0.1.12(zod@3.25.67) + '@ai-sdk/fireworks': + specifier: ^0.2.14 + version: 0.2.14(zod@3.25.67) + '@ai-sdk/google': + specifier: ^1.2.19 + version: 1.2.19(zod@3.25.67) + '@ai-sdk/google-vertex': + specifier: ^2.2.24 + version: 2.2.24(zod@3.25.67) + '@ai-sdk/groq': + specifier: ^1.2.9 + version: 1.2.9(zod@3.25.67) + '@ai-sdk/mistral': + specifier: ^1.2.8 + version: 1.2.8(zod@3.25.67) + '@ai-sdk/openai': + specifier: ^1.3.22 + version: 1.3.22(zod@3.25.67) + '@ai-sdk/openai-compatible': + specifier: ^0.2.14 + version: 0.2.14(zod@3.25.67) + '@ai-sdk/perplexity': + specifier: ^1.1.9 + version: 1.1.9(zod@3.25.67) + '@ai-sdk/replicate': + specifier: ^0.2.8 + version: 0.2.8(zod@3.25.67) + '@ai-sdk/togetherai': + specifier: ^0.2.14 + version: 0.2.14(zod@3.25.67) + '@ai-sdk/vercel': + specifier: ^0.0.1 + version: 0.0.1(zod@3.25.67) + '@ai-sdk/xai': + specifier: ^1.2.16 + version: 1.2.16(zod@3.25.67) + '@openrouter/ai-sdk-provider': + specifier: ^0.1.0 + version: 0.1.0(zod@3.25.67) + ai: + specifier: ^4.3.16 + version: 4.3.16(react@19.1.0)(zod@3.25.67) + anthropic-vertex-ai: + specifier: ^1.0.2 + version: 1.0.2(zod@3.25.67) + ollama-ai-provider: + specifier: ^1.2.0 + version: 1.2.0(zod@3.25.67) + qwen-ai-provider: + specifier: ^0.1.0 + version: 0.1.0(zod@3.25.67) + zhipu-ai-provider: + specifier: ^0.1.1 + version: 0.1.1(zod@3.25.67) + devDependencies: + typescript: + specifier: ^5.0.0 + version: 5.8.3 + +packages: + + '@ai-sdk/amazon-bedrock@2.2.10': + resolution: {integrity: sha512-icLGO7Q0NinnHIPgT+y1QjHVwH4HwV+brWbvM+FfCG2Afpa89PyKa3Ret91kGjZpBgM/xnj1B7K5eM+rRlsXQA==} + engines: {node: '>=18'} + peerDependencies: + zod: ^3.0.0 + + '@ai-sdk/anthropic@1.2.12': + resolution: {integrity: sha512-YSzjlko7JvuiyQFmI9RN1tNZdEiZxc+6xld/0tq/VkJaHpEzGAb1yiNxxvmYVcjvfu/PcvCxAAYXmTYQQ63IHQ==} + engines: {node: '>=18'} + peerDependencies: + zod: ^3.0.0 + + '@ai-sdk/azure@1.3.23': + resolution: {integrity: sha512-vpsaPtU24RBVk/IMM5UylR/N4RtAuL2NZLWc7LJ3tvMTHu6pI46a7w+1qIwR3F6yO9ehWR8qvfLaBefJNFxaVw==} + engines: {node: '>=18'} + peerDependencies: + zod: ^3.0.0 + + '@ai-sdk/cerebras@0.2.14': + resolution: {integrity: sha512-BIDf9hfgAEEu3xhNUyBWvAzeSgt7A7cSMj7UcKS4jhBDybRoKjoEGWHC7916j8LS/5Hkdmo6jwaxWxn/gZJYbQ==} + engines: {node: '>=18'} + peerDependencies: + zod: ^3.0.0 + + '@ai-sdk/cohere@1.2.10': + resolution: {integrity: sha512-OaUwd5xj4bxSO8hdCbX1a5uUlTouU8FcodSuRON6xDSsmjZIvQL4O2G1XzcidxiQVL8JQuA+M0tHZOwGxSL96A==} + engines: {node: '>=18'} + peerDependencies: + zod: ^3.0.0 + + '@ai-sdk/deepinfra@0.2.15': + resolution: {integrity: sha512-oRWZydmKg0G6KZTh4mOi0Kb3rW4v6hMBv/dGUH5xfo/nNyV6gAwgtoXtZ96KRbkjqCgVQgebfN1OCba1lflP0A==} + engines: {node: '>=18'} + peerDependencies: + zod: ^3.0.0 + + '@ai-sdk/deepseek@0.2.14': + resolution: {integrity: sha512-TISD1FzBWuQkHEHoVustoJILV33ZNgfYxeTkq1xU2vHEZuWTGZV7/IlXixyFsfqDCdVgrbLeIABk5FuCw7niLg==} + engines: {node: '>=18'} + peerDependencies: + zod: ^3.0.0 + + '@ai-sdk/fal@0.1.12': + resolution: {integrity: sha512-Z0pUUR3qwLTj4HXgGJSes5fwjUbSowsMiKbpYKGl6V51sQeUk2EjZctdN4+a+GBuDNCP6Y32Wi8ejM54OMee+w==} + engines: {node: '>=18'} + peerDependencies: + zod: ^3.0.0 + + '@ai-sdk/fireworks@0.2.14': + resolution: {integrity: sha512-0xlh95Y+L9ccc7hwrjdFKi4u8dirx24FLc70ySXA53u1zZP6R1W35TBYGaLzFpTVhhBhDTOca0mE+/EjJihcxw==} + engines: {node: '>=18'} + peerDependencies: + zod: ^3.0.0 + + '@ai-sdk/google-vertex@2.2.24': + resolution: {integrity: sha512-zi1ZN6jQEBRke/WMbZv0YkeqQ3nOs8ihxjVh/8z1tUn+S1xgRaYXf4+r6+Izh2YqVHIMNwjhUYryQRBGq20cgQ==} + engines: {node: '>=18'} + peerDependencies: + zod: ^3.0.0 + + '@ai-sdk/google@1.2.19': + resolution: {integrity: sha512-Xgl6eftIRQ4srUdCzxM112JuewVMij5q4JLcNmHcB68Bxn9dpr3MVUSPlJwmameuiQuISIA8lMB+iRiRbFsaqA==} + engines: {node: '>=18'} + peerDependencies: + zod: ^3.0.0 + + '@ai-sdk/groq@1.2.9': + resolution: {integrity: sha512-7MoDaxm8yWtiRbD1LipYZG0kBl+Xe0sv/EeyxnHnGPZappXdlgtdOgTZVjjXkT3nWP30jjZi9A45zoVrBMb3Xg==} + engines: {node: '>=18'} + peerDependencies: + zod: ^3.0.0 + + '@ai-sdk/mistral@1.2.8': + resolution: {integrity: sha512-lv857D9UJqCVxiq2Fcu7mSPTypEHBUqLl1K+lCaP6X/7QAkcaxI36QDONG+tOhGHJOXTsS114u8lrUTaEiGXbg==} + engines: {node: '>=18'} + peerDependencies: + zod: ^3.0.0 + + '@ai-sdk/openai-compatible@0.2.14': + resolution: {integrity: sha512-icjObfMCHKSIbywijaoLdZ1nSnuRnWgMEMLgwoxPJgxsUHMx0aVORnsLUid4SPtdhHI3X2masrt6iaEQLvOSFw==} + engines: {node: '>=18'} + peerDependencies: + zod: ^3.0.0 + + '@ai-sdk/openai@1.3.22': + resolution: {integrity: sha512-QwA+2EkG0QyjVR+7h6FE7iOu2ivNqAVMm9UJZkVxxTk5OIq5fFJDTEI/zICEMuHImTTXR2JjsL6EirJ28Jc4cw==} + engines: {node: '>=18'} + peerDependencies: + zod: ^3.0.0 + + '@ai-sdk/perplexity@1.1.9': + resolution: {integrity: sha512-Ytolh/v2XupXbTvjE18EFBrHLoNMH0Ueji3lfSPhCoRUfkwrgZ2D9jlNxvCNCCRiGJG5kfinSHvzrH5vGDklYA==} + engines: {node: '>=18'} + peerDependencies: + zod: ^3.0.0 + + '@ai-sdk/provider-utils@1.0.20': + resolution: {integrity: sha512-ngg/RGpnA00eNOWEtXHenpX1MsM2QshQh4QJFjUfwcqHpM5kTfG7je7Rc3HcEDP+OkRVv2GF+X4fC1Vfcnl8Ow==} + engines: {node: '>=18'} + peerDependencies: + zod: ^3.0.0 + peerDependenciesMeta: + zod: + optional: true + + '@ai-sdk/provider-utils@2.1.10': + resolution: {integrity: sha512-4GZ8GHjOFxePFzkl3q42AU0DQOtTQ5w09vmaWUf/pKFXJPizlnzKSUkF0f+VkapIUfDugyMqPMT1ge8XQzVI7Q==} + engines: {node: '>=18'} + peerDependencies: + zod: ^3.0.0 + peerDependenciesMeta: + zod: + optional: true + + '@ai-sdk/provider-utils@2.1.5': + resolution: {integrity: sha512-PcNR7E4ovZGV/J47gUqaFlvzorgca6uUfN5WzfXJSFWeOeLunN+oxRVwgUOwj0zbmO0yGQTHQD+FHVw8s3Rz8w==} + engines: {node: '>=18'} + peerDependencies: + zod: ^3.0.0 + peerDependenciesMeta: + zod: + optional: true + + '@ai-sdk/provider-utils@2.2.8': + resolution: {integrity: sha512-fqhG+4sCVv8x7nFzYnFo19ryhAa3w096Kmc3hWxMQfW/TubPOmt3A6tYZhl4mUfQWWQMsuSkLrtjlWuXBVSGQA==} + engines: {node: '>=18'} + peerDependencies: + zod: ^3.23.8 + + '@ai-sdk/provider@0.0.24': + resolution: {integrity: sha512-XMsNGJdGO+L0cxhhegtqZ8+T6nn4EoShS819OvCgI2kLbYTIvk0GWFGD0AXJmxkxs3DrpsJxKAFukFR7bvTkgQ==} + engines: {node: '>=18'} + + '@ai-sdk/provider@1.0.6': + resolution: {integrity: sha512-hwj/gFNxpDgEfTaYzCYoslmw01IY9kWLKl/wf8xuPvHtQIzlfXWmmUwc8PnCwxyt8cKzIuV0dfUghCf68HQ0SA==} + engines: {node: '>=18'} + + '@ai-sdk/provider@1.0.9': + resolution: {integrity: sha512-jie6ZJT2ZR0uVOVCDc9R2xCX5I/Dum/wEK28lx21PJx6ZnFAN9EzD2WsPhcDWfCgGx3OAZZ0GyM3CEobXpa9LA==} + engines: {node: '>=18'} + + '@ai-sdk/provider@1.1.3': + resolution: {integrity: sha512-qZMxYJ0qqX/RfnuIaab+zp8UAeJn/ygXXAffR5I4N0n1IrvA6qBsjc8hXLmBiMV2zoXlifkacF7sEFnYnjBcqg==} + engines: {node: '>=18'} + + '@ai-sdk/react@1.2.12': + resolution: {integrity: sha512-jK1IZZ22evPZoQW3vlkZ7wvjYGYF+tRBKXtrcolduIkQ/m/sOAVcVeVDUDvh1T91xCnWCdUGCPZg2avZ90mv3g==} + engines: {node: '>=18'} + peerDependencies: + react: ^18 || ^19 || ^19.0.0-rc + zod: ^3.23.8 + peerDependenciesMeta: + zod: + optional: true + + '@ai-sdk/replicate@0.2.8': + resolution: {integrity: sha512-l9t4+RzbAn8osstkbWs6l++Nava+4LO4dsaddnE0GQM5E0BEIgMTJ14hoyfE02Ep0rJZ0M2HlXGqv5heW47P8A==} + engines: {node: '>=18'} + peerDependencies: + zod: ^3.0.0 + + '@ai-sdk/togetherai@0.2.14': + resolution: {integrity: sha512-tdCe5kawsQrnMZB8aF1iL1P3+NfrPwILH9UudAZ5cNVY5dTFl+mXk3R37YJS+mkWeAoedr8Cb7mAuGxR47bsFw==} + engines: {node: '>=18'} + peerDependencies: + zod: ^3.0.0 + + '@ai-sdk/ui-utils@1.2.11': + resolution: {integrity: sha512-3zcwCc8ezzFlwp3ZD15wAPjf2Au4s3vAbKsXQVyhxODHcmu0iyPO2Eua6D/vicq/AUm/BAo60r97O6HU+EI0+w==} + engines: {node: '>=18'} + peerDependencies: + zod: ^3.23.8 + + '@ai-sdk/vercel@0.0.1': + resolution: {integrity: sha512-hHDZotTYVpmNyiSiWySSv/XbSjkL9exmKkBR7FwR1zp41ml+LV6WBlfwatBWZ5m22hSSDrztx4abvvd/MFF0yg==} + engines: {node: '>=18'} + peerDependencies: + zod: ^3.0.0 + + '@ai-sdk/xai@1.2.16': + resolution: {integrity: sha512-UOZT8td9PWwMi2dF9a0U44t/Oltmf6QmIJdSvrOcLG4mvpRc1UJn6YJaR0HtXs3YnW6SvY1zRdIDrW4GFpv4NA==} + engines: {node: '>=18'} + peerDependencies: + zod: ^3.0.0 + + '@aws-crypto/crc32@5.2.0': + resolution: {integrity: sha512-nLbCWqQNgUiwwtFsen1AdzAtvuLRsQS8rYgMuxCrdKf9kOssamGLuPwyTY9wyYblNr9+1XM8v6zoDTPPSIeANg==} + engines: {node: '>=16.0.0'} + + '@aws-crypto/util@5.2.0': + resolution: {integrity: sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ==} + + '@aws-sdk/types@3.821.0': + resolution: {integrity: sha512-Znroqdai1a90TlxGaJ+FK1lwC0fHpo97Xjsp5UKGR5JODYm7f9+/fF17ebO1KdoBr/Rm0UIFiF5VmI8ts9F1eA==} + engines: {node: '>=18.0.0'} + + '@openrouter/ai-sdk-provider@0.1.0': + resolution: {integrity: sha512-kETuMSFu31Z9ND1lEl8cmXy+csCZBopKEpe33Pxz/B6J/AYOlGxvmdPKWlMqwkvE1dISuPMh9IL97Q6dof2Liw==} + engines: {node: '>=18'} + peerDependencies: + zod: ^3.0.0 + + '@opentelemetry/api@1.9.0': + resolution: {integrity: sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==} + engines: {node: '>=8.0.0'} + + '@smithy/eventstream-codec@4.0.4': + resolution: {integrity: sha512-7XoWfZqWb/QoR/rAU4VSi0mWnO2vu9/ltS6JZ5ZSZv0eovLVfDfu0/AX4ub33RsJTOth3TiFWSHS5YdztvFnig==} + engines: {node: '>=18.0.0'} + + '@smithy/is-array-buffer@2.2.0': + resolution: {integrity: sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==} + engines: {node: '>=14.0.0'} + + '@smithy/is-array-buffer@4.0.0': + resolution: {integrity: sha512-saYhF8ZZNoJDTvJBEWgeBccCg+yvp1CX+ed12yORU3NilJScfc6gfch2oVb4QgxZrGUx3/ZJlb+c/dJbyupxlw==} + engines: {node: '>=18.0.0'} + + '@smithy/types@4.3.1': + resolution: {integrity: sha512-UqKOQBL2x6+HWl3P+3QqFD4ncKq0I8Nuz9QItGv5WuKuMHuuwlhvqcZCoXGfc+P1QmfJE7VieykoYYmrOoFJxA==} + engines: {node: '>=18.0.0'} + + '@smithy/util-buffer-from@2.2.0': + resolution: {integrity: sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==} + engines: {node: '>=14.0.0'} + + '@smithy/util-buffer-from@4.0.0': + resolution: {integrity: sha512-9TOQ7781sZvddgO8nxueKi3+yGvkY35kotA0Y6BWRajAv8jjmigQ1sBwz0UX47pQMYXJPahSKEKYFgt+rXdcug==} + engines: {node: '>=18.0.0'} + + '@smithy/util-hex-encoding@4.0.0': + resolution: {integrity: sha512-Yk5mLhHtfIgW2W2WQZWSg5kuMZCVbvhFmC7rV4IO2QqnZdbEFPmQnCcGMAX2z/8Qj3B9hYYNjZOhWym+RwhePw==} + engines: {node: '>=18.0.0'} + + '@smithy/util-utf8@2.3.0': + resolution: {integrity: sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==} + engines: {node: '>=14.0.0'} + + '@smithy/util-utf8@4.0.0': + resolution: {integrity: sha512-b+zebfKCfRdgNJDknHCob3O7FpeYQN6ZG6YLExMcasDHsCXlsXCEuiPZeLnJLpwa5dvPetGlnGCiMHuLwGvFow==} + engines: {node: '>=18.0.0'} + + '@types/diff-match-patch@1.0.36': + resolution: {integrity: sha512-xFdR6tkm0MWvBfO8xXCSsinYxHcqkQUlcHeSpMC2ukzOb6lwQAfDmW+Qt0AvlGd8HpsS28qKsB+oPeJn9I39jg==} + + agent-base@7.1.3: + resolution: {integrity: sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==} + engines: {node: '>= 14'} + + ai@4.3.16: + resolution: {integrity: sha512-KUDwlThJ5tr2Vw0A1ZkbDKNME3wzWhuVfAOwIvFUzl1TPVDFAXDFTXio3p+jaKneB+dKNCvFFlolYmmgHttG1g==} + engines: {node: '>=18'} + peerDependencies: + react: ^18 || ^19 || ^19.0.0-rc + zod: ^3.23.8 + peerDependenciesMeta: + react: + optional: true + + anthropic-vertex-ai@1.0.2: + resolution: {integrity: sha512-4YuK04KMmBGkx6fi2UjnHkE4mhaIov7tnT5La9+DMn/gw/NSOLZoWNUx+13VY3mkcaseKBMEn1DBzdXXJFIP7A==} + engines: {node: '>=18'} + peerDependencies: + zod: ^3.0.0 + + aws4fetch@1.0.20: + resolution: {integrity: sha512-/djoAN709iY65ETD6LKCtyyEI04XIBP5xVvfmNxsEP0uJB5tyaGBztSryRr4HqMStr9R06PisQE7m9zDTXKu6g==} + + base64-js@1.5.1: + resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} + + bignumber.js@9.3.0: + resolution: {integrity: sha512-EM7aMFTXbptt/wZdMlBv2t8IViwQL+h6SLHosp8Yf0dqJMTnY6iL32opnAB6kAdL0SZPuvcAzFr31o0c/R3/RA==} + + buffer-equal-constant-time@1.0.1: + resolution: {integrity: sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==} + + chalk@5.4.1: + resolution: {integrity: sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==} + engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} + + debug@4.4.1: + resolution: {integrity: sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + dequal@2.0.3: + resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} + engines: {node: '>=6'} + + diff-match-patch@1.0.5: + resolution: {integrity: sha512-IayShXAgj/QMXgB0IWmKx+rOPuGMhqm5w6jvFxmVenXKIzRqTAAsbBPT3kWQeGANj3jGgvcvv4yK6SxqYmikgw==} + + ecdsa-sig-formatter@1.0.11: + resolution: {integrity: sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==} + + eventsource-parser@1.1.2: + resolution: {integrity: sha512-v0eOBUbiaFojBu2s2NPBfYUoRR9GjcDNvCXVaqEf5vVfpIAh9f8RCo4vXTP8c63QRKCFwoLpMpTdPwwhEKVgzA==} + engines: {node: '>=14.18'} + + eventsource-parser@3.0.2: + resolution: {integrity: sha512-6RxOBZ/cYgd8usLwsEl+EC09Au/9BcmCKYF2/xbml6DNczf7nv0MQb+7BA2F+li6//I+28VNlQR37XfQtcAJuA==} + engines: {node: '>=18.0.0'} + + extend@3.0.2: + resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} + + gaxios@6.7.1: + resolution: {integrity: sha512-LDODD4TMYx7XXdpwxAVRAIAuB0bzv0s+ywFonY46k126qzQHT9ygyoa9tncmOiQmmDrik65UYsEkv3lbfqQ3yQ==} + engines: {node: '>=14'} + + gcp-metadata@6.1.1: + resolution: {integrity: sha512-a4tiq7E0/5fTjxPAaH4jpjkSv/uCaU2p5KC6HVGrvl0cDjA8iBZv4vv1gyzlmK0ZUKqwpOyQMKzZQe3lTit77A==} + engines: {node: '>=14'} + + google-auth-library@9.15.1: + resolution: {integrity: sha512-Jb6Z0+nvECVz+2lzSMt9u98UsoakXxA2HGHMCxh+so3n90XgYWkq5dur19JAJV7ONiJY22yBTyJB1TSkvPq9Ng==} + engines: {node: '>=14'} + + google-logging-utils@0.0.2: + resolution: {integrity: sha512-NEgUnEcBiP5HrPzufUkBzJOD/Sxsco3rLNo1F1TNf7ieU8ryUzBhqba8r756CjLX7rn3fHl6iLEwPYuqpoKgQQ==} + engines: {node: '>=14'} + + gtoken@7.1.0: + resolution: {integrity: sha512-pCcEwRi+TKpMlxAQObHDQ56KawURgyAf6jtIY046fJ5tIv3zDe/LEIubckAO8fj6JnAxLdmWkUfNyulQ2iKdEw==} + engines: {node: '>=14.0.0'} + + https-proxy-agent@7.0.6: + resolution: {integrity: sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==} + engines: {node: '>= 14'} + + is-stream@2.0.1: + resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} + engines: {node: '>=8'} + + json-bigint@1.0.0: + resolution: {integrity: sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==} + + json-schema@0.4.0: + resolution: {integrity: sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==} + + jsondiffpatch@0.6.0: + resolution: {integrity: sha512-3QItJOXp2AP1uv7waBkao5nCvhEv+QmJAd38Ybq7wNI74Q+BBmnLn4EDKz6yI9xGAIQoUF87qHt+kc1IVxB4zQ==} + engines: {node: ^18.0.0 || >=20.0.0} + hasBin: true + + jwa@2.0.1: + resolution: {integrity: sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==} + + jws@4.0.0: + resolution: {integrity: sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg==} + + ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + + nanoid@3.3.11: + resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + + nanoid@3.3.6: + resolution: {integrity: sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + + node-fetch@2.7.0: + resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==} + engines: {node: 4.x || >=6.0.0} + peerDependencies: + encoding: ^0.1.0 + peerDependenciesMeta: + encoding: + optional: true + + ollama-ai-provider@1.2.0: + resolution: {integrity: sha512-jTNFruwe3O/ruJeppI/quoOUxG7NA6blG3ZyQj3lei4+NnJo7bi3eIRWqlVpRlu/mbzbFXeJSBuYQWF6pzGKww==} + engines: {node: '>=18'} + peerDependencies: + zod: ^3.0.0 + peerDependenciesMeta: + zod: + optional: true + + partial-json@0.1.7: + resolution: {integrity: sha512-Njv/59hHaokb/hRUjce3Hdv12wd60MtM9Z5Olmn+nehe0QDAsRtRbJPvJ0Z91TusF0SuZRIvnM+S4l6EIP8leA==} + + qwen-ai-provider@0.1.0: + resolution: {integrity: sha512-ylzb71U0WreJPyNOHJTwXvE9+jVSsFhnam5aDfB7hBSUuEajYFIGcvhhuQUgUE43OIpxINMgGHKSicpwJ8x/XQ==} + engines: {node: '>=18.0.0'} + peerDependencies: + zod: ^3.24.1 + + react@19.1.0: + resolution: {integrity: sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==} + engines: {node: '>=0.10.0'} + + safe-buffer@5.2.1: + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + + secure-json-parse@2.7.0: + resolution: {integrity: sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==} + + swr@2.3.3: + resolution: {integrity: sha512-dshNvs3ExOqtZ6kJBaAsabhPdHyeY4P2cKwRCniDVifBMoG/SVI7tfLWqPXriVspf2Rg4tPzXJTnwaihIeFw2A==} + peerDependencies: + react: ^16.11.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + + throttleit@2.1.0: + resolution: {integrity: sha512-nt6AMGKW1p/70DF/hGBdJB57B8Tspmbp5gfJ8ilhLnt7kkr2ye7hzD6NVG8GGErk2HWF34igrL2CXmNIkzKqKw==} + engines: {node: '>=18'} + + tr46@0.0.3: + resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} + + tslib@2.8.1: + resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + + typescript@5.8.3: + resolution: {integrity: sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==} + engines: {node: '>=14.17'} + hasBin: true + + use-sync-external-store@1.5.0: + resolution: {integrity: sha512-Rb46I4cGGVBmjamjphe8L/UnvJD+uPPtTkNvX5mZgqdbavhI4EbgIWJiIHXJ8bc/i9EQGPRh4DwEURJ552Do0A==} + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + + uuid@9.0.1: + resolution: {integrity: sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==} + hasBin: true + + webidl-conversions@3.0.1: + resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} + + whatwg-url@5.0.0: + resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} + + zhipu-ai-provider@0.1.1: + resolution: {integrity: sha512-cVwvvGtPiQqgsGdBzHCHC5oQ7z6slEQTbXJ5+42gQGX4N5uRUvYj+YYLp7Cr1HPQGF3zR2p8vNbT5etPHD4NbA==} + engines: {node: '>=18'} + peerDependencies: + zod: ^3.0.0 + + zod-to-json-schema@3.24.5: + resolution: {integrity: sha512-/AuWwMP+YqiPbsJx5D6TfgRTc4kTLjsh5SOcd4bLsfUg2RcEXrFMJl1DGgdHy2aCfsIA/cr/1JM0xcB2GZji8g==} + peerDependencies: + zod: ^3.24.1 + + zod@3.25.67: + resolution: {integrity: sha512-idA2YXwpCdqUSKRCACDE6ItZD9TZzy3OZMtpfLoh6oPR47lipysRrJfjzMqFxQ3uJuUPyUeWe1r9vLH33xO/Qw==} + +snapshots: + + '@ai-sdk/amazon-bedrock@2.2.10(zod@3.25.67)': + dependencies: + '@ai-sdk/provider': 1.1.3 + '@ai-sdk/provider-utils': 2.2.8(zod@3.25.67) + '@smithy/eventstream-codec': 4.0.4 + '@smithy/util-utf8': 4.0.0 + aws4fetch: 1.0.20 + zod: 3.25.67 + + '@ai-sdk/anthropic@1.2.12(zod@3.25.67)': + dependencies: + '@ai-sdk/provider': 1.1.3 + '@ai-sdk/provider-utils': 2.2.8(zod@3.25.67) + zod: 3.25.67 + + '@ai-sdk/azure@1.3.23(zod@3.25.67)': + dependencies: + '@ai-sdk/openai': 1.3.22(zod@3.25.67) + '@ai-sdk/provider': 1.1.3 + '@ai-sdk/provider-utils': 2.2.8(zod@3.25.67) + zod: 3.25.67 + + '@ai-sdk/cerebras@0.2.14(zod@3.25.67)': + dependencies: + '@ai-sdk/openai-compatible': 0.2.14(zod@3.25.67) + '@ai-sdk/provider': 1.1.3 + '@ai-sdk/provider-utils': 2.2.8(zod@3.25.67) + zod: 3.25.67 + + '@ai-sdk/cohere@1.2.10(zod@3.25.67)': + dependencies: + '@ai-sdk/provider': 1.1.3 + '@ai-sdk/provider-utils': 2.2.8(zod@3.25.67) + zod: 3.25.67 + + '@ai-sdk/deepinfra@0.2.15(zod@3.25.67)': + dependencies: + '@ai-sdk/openai-compatible': 0.2.14(zod@3.25.67) + '@ai-sdk/provider': 1.1.3 + '@ai-sdk/provider-utils': 2.2.8(zod@3.25.67) + zod: 3.25.67 + + '@ai-sdk/deepseek@0.2.14(zod@3.25.67)': + dependencies: + '@ai-sdk/openai-compatible': 0.2.14(zod@3.25.67) + '@ai-sdk/provider': 1.1.3 + '@ai-sdk/provider-utils': 2.2.8(zod@3.25.67) + zod: 3.25.67 + + '@ai-sdk/fal@0.1.12(zod@3.25.67)': + dependencies: + '@ai-sdk/provider': 1.1.3 + '@ai-sdk/provider-utils': 2.2.8(zod@3.25.67) + zod: 3.25.67 + + '@ai-sdk/fireworks@0.2.14(zod@3.25.67)': + dependencies: + '@ai-sdk/openai-compatible': 0.2.14(zod@3.25.67) + '@ai-sdk/provider': 1.1.3 + '@ai-sdk/provider-utils': 2.2.8(zod@3.25.67) + zod: 3.25.67 + + '@ai-sdk/google-vertex@2.2.24(zod@3.25.67)': + dependencies: + '@ai-sdk/anthropic': 1.2.12(zod@3.25.67) + '@ai-sdk/google': 1.2.19(zod@3.25.67) + '@ai-sdk/provider': 1.1.3 + '@ai-sdk/provider-utils': 2.2.8(zod@3.25.67) + google-auth-library: 9.15.1 + zod: 3.25.67 + transitivePeerDependencies: + - encoding + - supports-color + + '@ai-sdk/google@1.2.19(zod@3.25.67)': + dependencies: + '@ai-sdk/provider': 1.1.3 + '@ai-sdk/provider-utils': 2.2.8(zod@3.25.67) + zod: 3.25.67 + + '@ai-sdk/groq@1.2.9(zod@3.25.67)': + dependencies: + '@ai-sdk/provider': 1.1.3 + '@ai-sdk/provider-utils': 2.2.8(zod@3.25.67) + zod: 3.25.67 + + '@ai-sdk/mistral@1.2.8(zod@3.25.67)': + dependencies: + '@ai-sdk/provider': 1.1.3 + '@ai-sdk/provider-utils': 2.2.8(zod@3.25.67) + zod: 3.25.67 + + '@ai-sdk/openai-compatible@0.2.14(zod@3.25.67)': + dependencies: + '@ai-sdk/provider': 1.1.3 + '@ai-sdk/provider-utils': 2.2.8(zod@3.25.67) + zod: 3.25.67 + + '@ai-sdk/openai@1.3.22(zod@3.25.67)': + dependencies: + '@ai-sdk/provider': 1.1.3 + '@ai-sdk/provider-utils': 2.2.8(zod@3.25.67) + zod: 3.25.67 + + '@ai-sdk/perplexity@1.1.9(zod@3.25.67)': + dependencies: + '@ai-sdk/provider': 1.1.3 + '@ai-sdk/provider-utils': 2.2.8(zod@3.25.67) + zod: 3.25.67 + + '@ai-sdk/provider-utils@1.0.20(zod@3.25.67)': + dependencies: + '@ai-sdk/provider': 0.0.24 + eventsource-parser: 1.1.2 + nanoid: 3.3.6 + secure-json-parse: 2.7.0 + optionalDependencies: + zod: 3.25.67 + + '@ai-sdk/provider-utils@2.1.10(zod@3.25.67)': + dependencies: + '@ai-sdk/provider': 1.0.9 + eventsource-parser: 3.0.2 + nanoid: 3.3.11 + secure-json-parse: 2.7.0 + optionalDependencies: + zod: 3.25.67 + + '@ai-sdk/provider-utils@2.1.5(zod@3.25.67)': + dependencies: + '@ai-sdk/provider': 1.0.6 + eventsource-parser: 3.0.2 + nanoid: 3.3.11 + secure-json-parse: 2.7.0 + optionalDependencies: + zod: 3.25.67 + + '@ai-sdk/provider-utils@2.2.8(zod@3.25.67)': + dependencies: + '@ai-sdk/provider': 1.1.3 + nanoid: 3.3.11 + secure-json-parse: 2.7.0 + zod: 3.25.67 + + '@ai-sdk/provider@0.0.24': + dependencies: + json-schema: 0.4.0 + + '@ai-sdk/provider@1.0.6': + dependencies: + json-schema: 0.4.0 + + '@ai-sdk/provider@1.0.9': + dependencies: + json-schema: 0.4.0 + + '@ai-sdk/provider@1.1.3': + dependencies: + json-schema: 0.4.0 + + '@ai-sdk/react@1.2.12(react@19.1.0)(zod@3.25.67)': + dependencies: + '@ai-sdk/provider-utils': 2.2.8(zod@3.25.67) + '@ai-sdk/ui-utils': 1.2.11(zod@3.25.67) + react: 19.1.0 + swr: 2.3.3(react@19.1.0) + throttleit: 2.1.0 + optionalDependencies: + zod: 3.25.67 + + '@ai-sdk/replicate@0.2.8(zod@3.25.67)': + dependencies: + '@ai-sdk/provider': 1.1.3 + '@ai-sdk/provider-utils': 2.2.8(zod@3.25.67) + zod: 3.25.67 + + '@ai-sdk/togetherai@0.2.14(zod@3.25.67)': + dependencies: + '@ai-sdk/openai-compatible': 0.2.14(zod@3.25.67) + '@ai-sdk/provider': 1.1.3 + '@ai-sdk/provider-utils': 2.2.8(zod@3.25.67) + zod: 3.25.67 + + '@ai-sdk/ui-utils@1.2.11(zod@3.25.67)': + dependencies: + '@ai-sdk/provider': 1.1.3 + '@ai-sdk/provider-utils': 2.2.8(zod@3.25.67) + zod: 3.25.67 + zod-to-json-schema: 3.24.5(zod@3.25.67) + + '@ai-sdk/vercel@0.0.1(zod@3.25.67)': + dependencies: + '@ai-sdk/openai-compatible': 0.2.14(zod@3.25.67) + '@ai-sdk/provider': 1.1.3 + '@ai-sdk/provider-utils': 2.2.8(zod@3.25.67) + zod: 3.25.67 + + '@ai-sdk/xai@1.2.16(zod@3.25.67)': + dependencies: + '@ai-sdk/openai-compatible': 0.2.14(zod@3.25.67) + '@ai-sdk/provider': 1.1.3 + '@ai-sdk/provider-utils': 2.2.8(zod@3.25.67) + zod: 3.25.67 + + '@aws-crypto/crc32@5.2.0': + dependencies: + '@aws-crypto/util': 5.2.0 + '@aws-sdk/types': 3.821.0 + tslib: 2.8.1 + + '@aws-crypto/util@5.2.0': + dependencies: + '@aws-sdk/types': 3.821.0 + '@smithy/util-utf8': 2.3.0 + tslib: 2.8.1 + + '@aws-sdk/types@3.821.0': + dependencies: + '@smithy/types': 4.3.1 + tslib: 2.8.1 + + '@openrouter/ai-sdk-provider@0.1.0(zod@3.25.67)': + dependencies: + '@ai-sdk/provider': 1.0.6 + '@ai-sdk/provider-utils': 2.1.5(zod@3.25.67) + zod: 3.25.67 + + '@opentelemetry/api@1.9.0': {} + + '@smithy/eventstream-codec@4.0.4': + dependencies: + '@aws-crypto/crc32': 5.2.0 + '@smithy/types': 4.3.1 + '@smithy/util-hex-encoding': 4.0.0 + tslib: 2.8.1 + + '@smithy/is-array-buffer@2.2.0': + dependencies: + tslib: 2.8.1 + + '@smithy/is-array-buffer@4.0.0': + dependencies: + tslib: 2.8.1 + + '@smithy/types@4.3.1': + dependencies: + tslib: 2.8.1 + + '@smithy/util-buffer-from@2.2.0': + dependencies: + '@smithy/is-array-buffer': 2.2.0 + tslib: 2.8.1 + + '@smithy/util-buffer-from@4.0.0': + dependencies: + '@smithy/is-array-buffer': 4.0.0 + tslib: 2.8.1 + + '@smithy/util-hex-encoding@4.0.0': + dependencies: + tslib: 2.8.1 + + '@smithy/util-utf8@2.3.0': + dependencies: + '@smithy/util-buffer-from': 2.2.0 + tslib: 2.8.1 + + '@smithy/util-utf8@4.0.0': + dependencies: + '@smithy/util-buffer-from': 4.0.0 + tslib: 2.8.1 + + '@types/diff-match-patch@1.0.36': {} + + agent-base@7.1.3: {} + + ai@4.3.16(react@19.1.0)(zod@3.25.67): + dependencies: + '@ai-sdk/provider': 1.1.3 + '@ai-sdk/provider-utils': 2.2.8(zod@3.25.67) + '@ai-sdk/react': 1.2.12(react@19.1.0)(zod@3.25.67) + '@ai-sdk/ui-utils': 1.2.11(zod@3.25.67) + '@opentelemetry/api': 1.9.0 + jsondiffpatch: 0.6.0 + zod: 3.25.67 + optionalDependencies: + react: 19.1.0 + + anthropic-vertex-ai@1.0.2(zod@3.25.67): + dependencies: + '@ai-sdk/provider': 0.0.24 + '@ai-sdk/provider-utils': 1.0.20(zod@3.25.67) + google-auth-library: 9.15.1 + zod: 3.25.67 + transitivePeerDependencies: + - encoding + - supports-color + + aws4fetch@1.0.20: {} + + base64-js@1.5.1: {} + + bignumber.js@9.3.0: {} + + buffer-equal-constant-time@1.0.1: {} + + chalk@5.4.1: {} + + debug@4.4.1: + dependencies: + ms: 2.1.3 + + dequal@2.0.3: {} + + diff-match-patch@1.0.5: {} + + ecdsa-sig-formatter@1.0.11: + dependencies: + safe-buffer: 5.2.1 + + eventsource-parser@1.1.2: {} + + eventsource-parser@3.0.2: {} + + extend@3.0.2: {} + + gaxios@6.7.1: + dependencies: + extend: 3.0.2 + https-proxy-agent: 7.0.6 + is-stream: 2.0.1 + node-fetch: 2.7.0 + uuid: 9.0.1 + transitivePeerDependencies: + - encoding + - supports-color + + gcp-metadata@6.1.1: + dependencies: + gaxios: 6.7.1 + google-logging-utils: 0.0.2 + json-bigint: 1.0.0 + transitivePeerDependencies: + - encoding + - supports-color + + google-auth-library@9.15.1: + dependencies: + base64-js: 1.5.1 + ecdsa-sig-formatter: 1.0.11 + gaxios: 6.7.1 + gcp-metadata: 6.1.1 + gtoken: 7.1.0 + jws: 4.0.0 + transitivePeerDependencies: + - encoding + - supports-color + + google-logging-utils@0.0.2: {} + + gtoken@7.1.0: + dependencies: + gaxios: 6.7.1 + jws: 4.0.0 + transitivePeerDependencies: + - encoding + - supports-color + + https-proxy-agent@7.0.6: + dependencies: + agent-base: 7.1.3 + debug: 4.4.1 + transitivePeerDependencies: + - supports-color + + is-stream@2.0.1: {} + + json-bigint@1.0.0: + dependencies: + bignumber.js: 9.3.0 + + json-schema@0.4.0: {} + + jsondiffpatch@0.6.0: + dependencies: + '@types/diff-match-patch': 1.0.36 + chalk: 5.4.1 + diff-match-patch: 1.0.5 + + jwa@2.0.1: + dependencies: + buffer-equal-constant-time: 1.0.1 + ecdsa-sig-formatter: 1.0.11 + safe-buffer: 5.2.1 + + jws@4.0.0: + dependencies: + jwa: 2.0.1 + safe-buffer: 5.2.1 + + ms@2.1.3: {} + + nanoid@3.3.11: {} + + nanoid@3.3.6: {} + + node-fetch@2.7.0: + dependencies: + whatwg-url: 5.0.0 + + ollama-ai-provider@1.2.0(zod@3.25.67): + dependencies: + '@ai-sdk/provider': 1.1.3 + '@ai-sdk/provider-utils': 2.2.8(zod@3.25.67) + partial-json: 0.1.7 + optionalDependencies: + zod: 3.25.67 + + partial-json@0.1.7: {} + + qwen-ai-provider@0.1.0(zod@3.25.67): + dependencies: + '@ai-sdk/provider': 1.1.3 + '@ai-sdk/provider-utils': 2.2.8(zod@3.25.67) + zod: 3.25.67 + + react@19.1.0: {} + + safe-buffer@5.2.1: {} + + secure-json-parse@2.7.0: {} + + swr@2.3.3(react@19.1.0): + dependencies: + dequal: 2.0.3 + react: 19.1.0 + use-sync-external-store: 1.5.0(react@19.1.0) + + throttleit@2.1.0: {} + + tr46@0.0.3: {} + + tslib@2.8.1: {} + + typescript@5.8.3: {} + + use-sync-external-store@1.5.0(react@19.1.0): + dependencies: + react: 19.1.0 + + uuid@9.0.1: {} + + webidl-conversions@3.0.1: {} + + whatwg-url@5.0.0: + dependencies: + tr46: 0.0.3 + webidl-conversions: 3.0.1 + + zhipu-ai-provider@0.1.1(zod@3.25.67): + dependencies: + '@ai-sdk/provider': 1.0.9 + '@ai-sdk/provider-utils': 2.1.10(zod@3.25.67) + zod: 3.25.67 + + zod-to-json-schema@3.24.5(zod@3.25.67): + dependencies: + zod: 3.25.67 + + zod@3.25.67: {} diff --git a/packages/aiCore/src/index.ts b/packages/aiCore/src/index.ts index 107c07a5c2..c512e27bf3 100644 --- a/packages/aiCore/src/index.ts +++ b/packages/aiCore/src/index.ts @@ -116,6 +116,15 @@ export type { export { createClient as createApiClient, getClientInfo, getSupportedProviders } from './clients/ApiClientFactory' export { getAllProviders, getProvider, isProviderSupported, registerProvider } from './providers/registry' +// ==================== Provider 配置工厂 ==================== +export { + BaseProviderConfig, + createProviderConfig, + ProviderConfigBuilder, + providerConfigBuilder, + ProviderConfigFactory +} from './providers/factory' + // ==================== 包信息 ==================== export const AI_CORE_VERSION = '1.0.0' export const AI_CORE_NAME = '@cherrystudio/ai-core' diff --git a/packages/aiCore/src/providers/factory.ts b/packages/aiCore/src/providers/factory.ts new file mode 100644 index 0000000000..12c721bdd7 --- /dev/null +++ b/packages/aiCore/src/providers/factory.ts @@ -0,0 +1,330 @@ +/** + * AI Provider 配置工厂 + * 提供类型安全的 Provider 配置构建器 + */ + +import type { ProviderId, ProviderSettingsMap } from './registry' + +/** + * 通用配置基础类型,包含所有 Provider 共有的属性 + */ +export interface BaseProviderConfig { + apiKey?: string + baseURL?: string + timeout?: number + headers?: Record + fetch?: typeof globalThis.fetch +} + +/** + * 完整的配置类型,结合基础配置、AI SDK 配置和特定 Provider 配置 + */ +type CompleteProviderConfig = BaseProviderConfig & Partial + +type ConfigHandler = ( + builder: ProviderConfigBuilder, + provider: CompleteProviderConfig +) => void + +const configHandlers: { + [K in ProviderId]?: ConfigHandler +} = { + azure: (builder, provider) => { + const azureBuilder = builder as ProviderConfigBuilder<'azure'> + const azureProvider = provider as CompleteProviderConfig<'azure'> + azureBuilder.withAzureConfig({ + apiVersion: azureProvider.apiVersion, + resourceName: azureProvider.resourceName + }) + }, + 'google-vertex': (builder, provider) => { + const vertexBuilder = builder as ProviderConfigBuilder<'google-vertex'> + const vertexProvider = provider as CompleteProviderConfig<'google-vertex'> + vertexBuilder.withGoogleVertexConfig({ + project: vertexProvider.project, + location: vertexProvider.location + }) + } +} + +export class ProviderConfigBuilder { + private config: CompleteProviderConfig = {} as CompleteProviderConfig + + constructor(private providerId: T) {} + + /** + * 设置 API Key + */ + withApiKey(apiKey: string): this + withApiKey(apiKey: string, options: T extends 'openai' ? { organization?: string; project?: string } : never): this + withApiKey(apiKey: string, options?: any): this { + this.config.apiKey = apiKey + + // 类型安全的 OpenAI 特定配置 + if (this.providerId === 'openai' && options) { + const openaiConfig = this.config as CompleteProviderConfig<'openai'> + if (options.organization) { + openaiConfig.organization = options.organization + } + if (options.project) { + openaiConfig.project = options.project + } + } + + return this + } + + /** + * 设置基础 URL + */ + withBaseURL(baseURL: string) { + this.config.baseURL = baseURL + return this + } + + /** + * 设置请求配置 + */ + withRequestConfig(options: { headers?: Record; fetch?: typeof fetch }): this { + if (options.headers) { + this.config.headers = { ...this.config.headers, ...options.headers } + } + if (options.fetch) { + this.config.fetch = options.fetch + } + return this + } + + /** + * Azure OpenAI 特定配置 + */ + withAzureConfig(options: { apiVersion?: string; resourceName?: string }): T extends 'azure' ? this : never + withAzureConfig(options: any): any { + if (this.providerId === 'azure') { + const azureConfig = this.config as CompleteProviderConfig<'azure'> + if (options.apiVersion) { + azureConfig.apiVersion = options.apiVersion + } + if (options.resourceName) { + azureConfig.resourceName = options.resourceName + } + } + return this + } + + /** + * Google 特定配置 + */ + withGoogleVertexConfig(options: { project?: string; location?: string }): T extends 'google-vertex' ? this : never + withGoogleVertexConfig(options: any): any { + if (this.providerId === 'google-vertex') { + const googleConfig = this.config as CompleteProviderConfig<'google-vertex'> + if (options.project) { + googleConfig.project = options.project + } + if (options.location) { + googleConfig.location = options.location + } + } + return this + } + + withGoogleCredentials(credentials: { + clientEmail: string + privateKey: string + }): T extends 'google-vertex' ? this : never + withGoogleCredentials(credentials: any): any { + if (this.providerId === 'google-vertex') { + const vertexConfig = this.config as CompleteProviderConfig<'google-vertex'> + vertexConfig.googleCredentials = credentials + } + return this + } + + /** + * 设置自定义参数 + */ + withCustomParams(params: Record) { + Object.assign(this.config, params) + return this + } + + /** + * 构建最终配置 + */ + build(): ProviderSettingsMap[T] { + return this.config as ProviderSettingsMap[T] + } +} + +/** + * Provider 配置工厂 + * 提供便捷的配置创建方法 + */ +export class ProviderConfigFactory { + /** + * 创建配置构建器 + */ + static builder(providerId: T): ProviderConfigBuilder { + return new ProviderConfigBuilder(providerId) + } + + /** + * 从通用Provider对象创建配置 - 使用更优雅的处理器模式 + */ + static fromProvider( + providerId: T, + provider: CompleteProviderConfig, + options?: { + headers?: Record + [key: string]: any + } + ): ProviderSettingsMap[T] { + const builder = new ProviderConfigBuilder(providerId) + + // 设置基本配置 + if (provider.apiKey) { + builder.withApiKey(provider.apiKey) + } + + if (provider.baseURL) { + builder.withBaseURL(provider.baseURL) + } + + // 设置请求配置 + if (options?.headers) { + builder.withRequestConfig({ + headers: options.headers + }) + } + + // 使用配置处理器模式 - 更加优雅和可扩展 + const handler = configHandlers[providerId] + if (handler) { + handler(builder, provider) + } + + // 添加其他自定义参数 + if (options) { + const customOptions = { ...options } + delete customOptions.headers // 已经处理过了 + if (Object.keys(customOptions).length > 0) { + builder.withCustomParams(customOptions) + } + } + + return builder.build() + } + + /** + * 快速创建 OpenAI 配置 + */ + static createOpenAI( + apiKey: string, + options?: { + baseURL?: string + organization?: string + project?: string + } + ) { + const builder = this.builder('openai') + + // 使用类型安全的重载 + if (options?.organization || options?.project) { + builder.withApiKey(apiKey, { + organization: options.organization, + project: options.project + }) + } else { + builder.withApiKey(apiKey) + } + + return builder.withBaseURL(options?.baseURL || 'https://api.openai.com').build() + } + + /** + * 快速创建 Anthropic 配置 + */ + static createAnthropic( + apiKey: string, + options?: { + baseURL?: string + } + ) { + return this.builder('anthropic') + .withApiKey(apiKey) + .withBaseURL(options?.baseURL || 'https://api.anthropic.com') + .build() + } + + /** + * 快速创建 Azure OpenAI 配置 + */ + static createAzureOpenAI( + apiKey: string, + options: { + baseURL: string + apiVersion?: string + resourceName?: string + deploymentName?: string + } + ) { + return this.builder('azure') + .withApiKey(apiKey) + .withBaseURL(options.baseURL) + .withAzureConfig({ + apiVersion: options.apiVersion, + resourceName: options.resourceName + }) + .build() + } + + /** + * 快速创建 Google 配置 + */ + static createGoogle( + apiKey: string, + options?: { + baseURL?: string + projectId?: string + location?: string + } + ) { + return this.builder('google') + .withApiKey(apiKey) + .withBaseURL(options?.baseURL || 'https://generativelanguage.googleapis.com') + .build() + } + + /** + * 快速创建 Vertex AI 配置 + */ + static createVertexAI( + credentials: { + clientEmail: string + privateKey: string + }, + options?: { + project?: string + location?: string + } + ) { + return this.builder('google-vertex') + .withGoogleCredentials(credentials) + .withGoogleVertexConfig({ + project: options?.project, + location: options?.location + }) + .build() + } + + static createOpenAICompatible(baseURL: string, apiKey: string) { + return this.builder('openai-compatible').withBaseURL(baseURL).withApiKey(apiKey).build() + } +} + +/** + * 便捷的配置创建函数 + */ +export const createProviderConfig = ProviderConfigFactory.fromProvider +export const providerConfigBuilder = ProviderConfigFactory.builder diff --git a/packages/aiCore/src/providers/registry.ts b/packages/aiCore/src/providers/registry.ts index 53504b4b07..f0fc5e37ef 100644 --- a/packages/aiCore/src/providers/registry.ts +++ b/packages/aiCore/src/providers/registry.ts @@ -14,7 +14,7 @@ import { type DeepSeekProviderSettings } from '@ai-sdk/deepseek' import { type FalProviderSettings } from '@ai-sdk/fal' import { type FireworksProviderSettings } from '@ai-sdk/fireworks' import { type GoogleGenerativeAIProviderSettings } from '@ai-sdk/google' -import { type GoogleVertexProviderSettings } from '@ai-sdk/google-vertex' +import { type GoogleVertexProviderSettings } from '@ai-sdk/google-vertex/edge' import { type GroqProviderSettings } from '@ai-sdk/groq' import { type MistralProviderSettings } from '@ai-sdk/mistral' import { type OpenAIProviderSettings } from '@ai-sdk/openai' @@ -123,7 +123,7 @@ export class AiProviderRegistry { { id: 'google-vertex', name: 'Google Vertex AI', - import: () => import('@ai-sdk/google-vertex'), + import: () => import('@ai-sdk/google-vertex/edge'), creatorFunctionName: 'createVertex', supportsImageGeneration: true }, @@ -270,7 +270,6 @@ export class AiProviderRegistry { } ] - // 注册所有 providers (总计24个) providers.forEach((config) => { this.registry.set(config.id, config) }) diff --git a/src/renderer/src/aiCore/index_new.ts b/src/renderer/src/aiCore/index_new.ts index c448a3318b..530aca6e12 100644 --- a/src/renderer/src/aiCore/index_new.ts +++ b/src/renderer/src/aiCore/index_new.ts @@ -10,76 +10,50 @@ import { AiClient, - AiCore, createClient, - type OpenAICompatibleProviderSettings, + ProviderConfigFactory, type ProviderId, + type ProviderSettingsMap, smoothStream, StreamTextParams } from '@cherrystudio/ai-core' import { isDedicatedImageGenerationModel } from '@renderer/config/models' +import { getDefaultModel } from '@renderer/services/AssistantService' import type { GenerateImageParams, Model, Provider } from '@renderer/types' -// 引入适配器 import AiSdkToChunkAdapter from './AiSdkToChunkAdapter' -// 引入原有的AiProvider作为fallback import LegacyAiProvider from './index' import { AiSdkMiddlewareConfig, buildAiSdkMiddlewares } from './middleware/aisdk/AiSdkMiddlewareBuilder' import { CompletionsResult } from './middleware/schemas' -// 引入参数转换模块 - -/** - * 将现有 Provider 类型映射到 AI SDK 的 Provider ID - * 根据 registry.ts 中的支持列表进行映射 - */ -function mapProviderTypeToAiSdkId(providerType: string): string { - // Cherry Studio Provider Type -> AI SDK Provider ID 映射表 - const typeMapping: Record = { - // 需要转换的映射 - grok: 'xai', // grok -> xai - 'azure-openai': 'azure', // azure-openai -> azure - gemini: 'google', // gemini -> google - vertexai: 'google-vertex' // vertexai -> google-vertex - } - - return typeMapping[providerType] -} +import { getAiSdkProviderId } from './provider/factory' +import { getTimeout } from './transformParameters' /** * 将 Provider 配置转换为新 AI SDK 格式 */ function providerToAiSdkConfig(provider: Provider): { providerId: ProviderId | 'openai-compatible' - options: any + options: ProviderSettingsMap[keyof ProviderSettingsMap] } { - console.log('provider', provider) - // 1. 先映射 provider 类型到 AI SDK ID - const mappedProviderId = mapProviderTypeToAiSdkId(provider.id) + const aiSdkProviderId = getAiSdkProviderId(provider) - // 2. 检查映射后的 provider ID 是否在 AI SDK 注册表中 - const isSupported = AiCore.isSupported(mappedProviderId) + if (aiSdkProviderId !== 'openai-compatible') { + const defaultModel = getDefaultModel() + const options = ProviderConfigFactory.fromProvider(aiSdkProviderId, provider, { + timeout: getTimeout(defaultModel) + }) - console.log(`Provider mapping: ${provider.type} -> ${mappedProviderId}, supported: ${isSupported}`) - - // 3. 如果映射的 provider 不支持,则使用 openai-compatible - if (isSupported) { return { - providerId: mappedProviderId as ProviderId, - options: { - apiKey: provider.apiKey - } + providerId: aiSdkProviderId as ProviderId, + options } } else { console.log(`Using openai-compatible fallback for provider: ${provider.type}`) - const compatibleConfig: OpenAICompatibleProviderSettings = { - name: provider.name || provider.type, - apiKey: provider.apiKey, - baseURL: provider.apiHost - } + const options = ProviderConfigFactory.createOpenAICompatible(provider.apiHost, provider.apiKey) return { providerId: 'openai-compatible', - options: compatibleConfig + options } } } diff --git a/src/renderer/src/aiCore/middleware/aisdk/AiSdkMiddlewareBuilder.ts b/src/renderer/src/aiCore/middleware/aisdk/AiSdkMiddlewareBuilder.ts index f9303f3950..90a611d511 100644 --- a/src/renderer/src/aiCore/middleware/aisdk/AiSdkMiddlewareBuilder.ts +++ b/src/renderer/src/aiCore/middleware/aisdk/AiSdkMiddlewareBuilder.ts @@ -1,4 +1,4 @@ -import { AiPlugin, simulateStreamingMiddleware } from '@cherrystudio/ai-core' +import { AiPlugin, extractReasoningMiddleware, simulateStreamingMiddleware } from '@cherrystudio/ai-core' import { isReasoningModel } from '@renderer/config/models' import type { Model, Provider } from '@renderer/types' import type { Chunk } from '@renderer/types/chunk' @@ -140,7 +140,10 @@ function addProviderSpecificMiddlewares(builder: AiSdkMiddlewareBuilder, config: // Anthropic特定中间件 break case 'openai': - // OpenAI特定中间件 + builder.add({ + name: 'thinking-tag-extraction', + aiSdkMiddlewares: [extractReasoningMiddleware({ tagName: 'think', separator: '\n', startWithReasoning: true })] + }) break case 'gemini': // Gemini特定中间件 diff --git a/src/renderer/src/aiCore/middleware/aisdk/ThinkingTimeMiddleware.ts b/src/renderer/src/aiCore/middleware/aisdk/ThinkingTimeMiddleware.ts index 39fbef6d74..9025cb2e49 100644 --- a/src/renderer/src/aiCore/middleware/aisdk/ThinkingTimeMiddleware.ts +++ b/src/renderer/src/aiCore/middleware/aisdk/ThinkingTimeMiddleware.ts @@ -1,5 +1,4 @@ import { LanguageModelV1Middleware, LanguageModelV1StreamPart } from '@cherrystudio/ai-core' -import { ChunkType, ThinkingCompleteChunk } from '@renderer/types/chunk' /** * 一个用于统计 LLM "思考时间"(Time to First Token)的 AI SDK 中间件。 @@ -47,8 +46,8 @@ export default function thinkingTimeMiddleware(): LanguageModelV1Middleware { // 如果流的末尾都是 reasoning,也需要发送 complete 事件 if (hasThinkingContent && thinkingStartTime > 0) { const thinkingTime = Date.now() - thinkingStartTime - const thinkingCompleteChunk: ThinkingCompleteChunk = { - type: ChunkType.THINKING_COMPLETE, + const thinkingCompleteChunk = { + type: 'reasoning-signature', text: accumulatedThinkingContent, thinking_millsec: thinkingTime } diff --git a/src/renderer/src/aiCore/provider/factory.ts b/src/renderer/src/aiCore/provider/factory.ts new file mode 100644 index 0000000000..b6ee9bab92 --- /dev/null +++ b/src/renderer/src/aiCore/provider/factory.ts @@ -0,0 +1,24 @@ +import { AiCore, ProviderId } from '@cherrystudio/ai-core' +import { Provider } from '@renderer/types' + +const PROVIDER_MAPPING: Record = { + anthropic: 'anthropic', + gemini: 'google', + vertexai: 'google-vertex', + 'azure-openai': 'azure', + 'openai-response': 'openai' +} + +export function getAiSdkProviderId(provider: Provider): ProviderId | 'openai-compatible' { + const providerId = PROVIDER_MAPPING[provider.type] + + if (providerId) { + return providerId + } + + if (AiCore.isSupported(provider.id)) { + return provider.id as ProviderId + } + + return 'openai-compatible' +} diff --git a/src/renderer/src/aiCore/transformParameters.ts b/src/renderer/src/aiCore/transformParameters.ts index 128df9442d..dd9aed2111 100644 --- a/src/renderer/src/aiCore/transformParameters.ts +++ b/src/renderer/src/aiCore/transformParameters.ts @@ -3,7 +3,7 @@ * 统一管理从各个 apiClient 提取的参数处理和转换功能 */ -import type { CoreMessage, StreamTextParams } from '@cherrystudio/ai-core' +import { type CoreMessage, type StreamTextParams } from '@cherrystudio/ai-core' import { isGenerateImageModel, isNotSupportTemperatureAndTopP, diff --git a/src/renderer/src/services/ApiService.ts b/src/renderer/src/services/ApiService.ts index a3e706c25e..79ead1d949 100644 --- a/src/renderer/src/services/ApiService.ts +++ b/src/renderer/src/services/ApiService.ts @@ -14,6 +14,7 @@ import { } from '@renderer/config/models' import { getStoreSetting } from '@renderer/hooks/useSettings' import i18n from '@renderer/i18n' +import store from '@renderer/store' import { Assistant, MCPTool, Model, Provider } from '@renderer/types' import { type Chunk, ChunkType } from '@renderer/types/chunk' import { Message } from '@renderer/types/newMessage'