@lobehub/chat 1.119.1 → 1.120.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.vscode/settings.json +2 -3
- package/CHANGELOG.md +58 -0
- package/changelog/v1.json +17 -0
- package/package.json +5 -6
- package/packages/const/src/auth.ts +0 -36
- package/packages/const/src/index.ts +3 -1
- package/packages/database/src/models/__tests__/aiModel.test.ts +1 -2
- package/packages/database/src/models/__tests__/generationBatch.test.ts +47 -1
- package/packages/database/src/models/aiModel.ts +2 -3
- package/packages/database/src/models/generationBatch.ts +8 -1
- package/packages/database/src/repositories/aiInfra/index.test.ts +1 -1
- package/packages/database/src/repositories/aiInfra/index.ts +4 -4
- package/packages/model-bank/src/aiModels/ai21.ts +1 -1
- package/packages/model-bank/src/aiModels/ai302.ts +1 -1
- package/packages/model-bank/src/aiModels/ai360.ts +1 -1
- package/packages/model-bank/src/aiModels/aihubmix.ts +3 -3
- package/packages/model-bank/src/aiModels/akashchat.ts +1 -1
- package/packages/model-bank/src/aiModels/anthropic.ts +1 -1
- package/packages/model-bank/src/aiModels/azure.ts +1 -1
- package/packages/model-bank/src/aiModels/azureai.ts +1 -1
- package/packages/model-bank/src/aiModels/baichuan.ts +1 -1
- package/packages/model-bank/src/aiModels/bedrock.ts +1 -1
- package/packages/model-bank/src/aiModels/bfl.ts +2 -3
- package/packages/model-bank/src/aiModels/cloudflare.ts +1 -1
- package/packages/model-bank/src/aiModels/cohere.ts +1 -1
- package/packages/model-bank/src/aiModels/deepseek.ts +1 -1
- package/packages/model-bank/src/aiModels/fal.ts +1 -1
- package/packages/model-bank/src/aiModels/fireworksai.ts +1 -1
- package/packages/model-bank/src/aiModels/giteeai.ts +1 -1
- package/packages/model-bank/src/aiModels/github.ts +1 -1
- package/packages/model-bank/src/aiModels/google.ts +6 -7
- package/packages/model-bank/src/aiModels/groq.ts +1 -1
- package/packages/model-bank/src/aiModels/higress.ts +1 -1
- package/packages/model-bank/src/aiModels/huggingface.ts +1 -1
- package/packages/model-bank/src/aiModels/hunyuan.ts +1 -1
- package/packages/model-bank/src/aiModels/index.ts +1 -1
- package/packages/model-bank/src/aiModels/infiniai.ts +1 -1
- package/packages/model-bank/src/aiModels/internlm.ts +1 -1
- package/packages/model-bank/src/aiModels/jina.ts +1 -1
- package/packages/model-bank/src/aiModels/lmstudio.ts +1 -1
- package/packages/model-bank/src/aiModels/lobehub.ts +1 -1
- package/packages/model-bank/src/aiModels/minimax.ts +1 -1
- package/packages/model-bank/src/aiModels/mistral.ts +1 -1
- package/packages/model-bank/src/aiModels/modelscope.ts +1 -1
- package/packages/model-bank/src/aiModels/moonshot.ts +1 -1
- package/packages/model-bank/src/aiModels/novita.ts +1 -1
- package/packages/model-bank/src/aiModels/nvidia.ts +1 -1
- package/packages/model-bank/src/aiModels/ollama.ts +1 -1
- package/packages/model-bank/src/aiModels/openai.ts +1 -1
- package/packages/model-bank/src/aiModels/openrouter.ts +3 -3
- package/packages/model-bank/src/aiModels/perplexity.ts +1 -1
- package/packages/model-bank/src/aiModels/ppio.ts +1 -1
- package/packages/model-bank/src/aiModels/qiniu.ts +1 -1
- package/packages/model-bank/src/aiModels/qwen.ts +4 -2
- package/packages/model-bank/src/aiModels/sambanova.ts +1 -1
- package/packages/model-bank/src/aiModels/search1api.ts +1 -1
- package/packages/model-bank/src/aiModels/sensenova.ts +1 -1
- package/packages/model-bank/src/aiModels/siliconcloud.ts +7 -1
- package/packages/model-bank/src/aiModels/spark.ts +1 -1
- package/packages/model-bank/src/aiModels/stepfun.ts +1 -1
- package/packages/model-bank/src/aiModels/taichu.ts +1 -1
- package/packages/model-bank/src/aiModels/tencentcloud.ts +1 -1
- package/packages/model-bank/src/aiModels/togetherai.ts +1 -1
- package/packages/model-bank/src/aiModels/upstage.ts +1 -1
- package/packages/model-bank/src/aiModels/v0.ts +1 -1
- package/packages/model-bank/src/aiModels/vertexai.ts +3 -3
- package/packages/model-bank/src/aiModels/vllm.ts +1 -1
- package/packages/model-bank/src/aiModels/volcengine.ts +1 -1
- package/packages/model-bank/src/aiModels/wenxin.ts +1 -1
- package/packages/model-bank/src/aiModels/xai.ts +1 -1
- package/packages/model-bank/src/aiModels/xinference.ts +1 -1
- package/packages/model-bank/src/aiModels/zeroone.ts +1 -1
- package/packages/model-bank/src/aiModels/zhipu.ts +1 -1
- package/packages/model-bank/src/index.ts +1 -0
- package/packages/model-bank/src/standard-parameters/index.ts +48 -0
- package/packages/{types/src → model-bank/src/types}/aiModel.ts +12 -1
- package/packages/model-bank/src/types/index.ts +1 -0
- package/packages/model-runtime/package.json +4 -1
- package/packages/model-runtime/src/BaseAI.ts +2 -2
- package/packages/model-runtime/src/ModelRuntime.test.ts +4 -4
- package/packages/model-runtime/src/RouterRuntime/createRuntime.ts +3 -7
- package/packages/model-runtime/src/ai302/index.ts +1 -1
- package/packages/model-runtime/src/aihubmix/index.ts +1 -2
- package/packages/model-runtime/src/anthropic/index.ts +1 -1
- package/packages/model-runtime/src/azureOpenai/index.ts +2 -3
- package/packages/model-runtime/src/azureai/index.ts +2 -3
- package/packages/model-runtime/src/bedrock/index.ts +1 -1
- package/packages/model-runtime/src/bfl/createImage.test.ts +4 -4
- package/packages/model-runtime/src/bfl/createImage.ts +2 -2
- package/packages/model-runtime/src/bfl/index.ts +1 -1
- package/packages/model-runtime/src/cloudflare/index.ts +1 -1
- package/packages/model-runtime/src/const/models.ts +64 -0
- package/packages/model-runtime/src/fal/index.test.ts +2 -3
- package/packages/model-runtime/src/fal/index.ts +1 -1
- package/packages/model-runtime/src/github/index.ts +1 -1
- package/packages/model-runtime/src/google/createImage.test.ts +1 -1
- package/packages/model-runtime/src/google/createImage.ts +53 -25
- package/packages/model-runtime/src/google/index.test.ts +1 -1
- package/packages/model-runtime/src/google/index.ts +4 -3
- package/packages/model-runtime/src/groq/index.ts +1 -1
- package/packages/model-runtime/src/helpers/parseToolCalls.ts +1 -2
- package/packages/model-runtime/src/huggingface/index.ts +1 -1
- package/packages/model-runtime/src/index.ts +3 -1
- package/packages/model-runtime/src/infiniai/index.ts +1 -1
- package/packages/model-runtime/src/ollama/index.test.ts +1 -1
- package/packages/model-runtime/src/ollama/index.ts +2 -3
- package/packages/model-runtime/src/openai/index.ts +16 -8
- package/packages/model-runtime/src/providerTestUtils.ts +1 -2
- package/packages/model-runtime/src/qiniu/index.test.ts +2 -3
- package/packages/model-runtime/src/qwen/index.ts +1 -1
- package/packages/model-runtime/src/siliconcloud/index.ts +2 -2
- package/packages/model-runtime/src/types/chat.ts +2 -22
- package/packages/model-runtime/src/{error.ts → types/error.ts} +29 -0
- package/packages/model-runtime/src/types/index.ts +4 -0
- package/packages/model-runtime/src/types/toolsCalling.ts +48 -0
- package/packages/model-runtime/src/types/type.ts +1 -1
- package/packages/model-runtime/src/types/usage.ts +27 -0
- package/packages/model-runtime/src/utils/anthropicHelpers.test.ts +2 -2
- package/packages/model-runtime/src/utils/anthropicHelpers.ts +1 -1
- package/packages/model-runtime/src/utils/createError.ts +1 -1
- package/packages/model-runtime/src/utils/errorResponse.test.ts +110 -0
- package/packages/model-runtime/src/utils/errorResponse.ts +64 -0
- package/packages/{utils/src → model-runtime/src/utils}/getFallbackModelProperty.ts +1 -1
- package/packages/model-runtime/src/utils/googleErrorParser.test.ts +1 -1
- package/packages/model-runtime/src/utils/googleErrorParser.ts +1 -1
- package/packages/model-runtime/src/utils/handleOpenAIError.ts +1 -1
- package/packages/model-runtime/src/utils/imageToBase64.test.ts +91 -0
- package/packages/model-runtime/src/utils/imageToBase64.ts +62 -0
- package/packages/model-runtime/src/utils/modelParse.test.ts +2 -2
- package/packages/model-runtime/src/utils/modelParse.ts +16 -10
- package/packages/model-runtime/src/utils/openaiCompatibleFactory/createImage.ts +1 -1
- package/packages/model-runtime/src/utils/openaiCompatibleFactory/index.ts +3 -3
- package/packages/model-runtime/src/utils/openaiHelpers.test.ts +2 -2
- package/packages/model-runtime/src/utils/openaiHelpers.ts +3 -4
- package/packages/model-runtime/src/utils/postProcessModelList.ts +2 -2
- package/packages/model-runtime/src/utils/safeParseJSON.test.ts +71 -0
- package/packages/model-runtime/src/utils/safeParseJSON.ts +12 -0
- package/packages/model-runtime/src/utils/streams/bedrock/claude.ts +1 -1
- package/packages/model-runtime/src/utils/streams/bedrock/llama.test.ts +1 -2
- package/packages/model-runtime/src/utils/streams/bedrock/llama.ts +1 -1
- package/packages/model-runtime/src/utils/streams/google-ai.test.ts +1 -1
- package/packages/model-runtime/src/utils/streams/google-ai.ts +1 -1
- package/packages/model-runtime/src/utils/streams/ollama.test.ts +1 -1
- package/packages/model-runtime/src/utils/streams/ollama.ts +2 -3
- package/packages/model-runtime/src/utils/streams/openai/openai.test.ts +1 -2
- package/packages/model-runtime/src/utils/streams/openai/openai.ts +1 -1
- package/packages/model-runtime/src/utils/streams/openai/responsesStream.ts +1 -1
- package/packages/model-runtime/src/utils/streams/protocol.ts +3 -3
- package/packages/model-runtime/src/utils/streams/vertex-ai.test.ts +1 -1
- package/packages/model-runtime/src/utils/streams/vertex-ai.ts +2 -2
- package/packages/model-runtime/src/utils/uuid.ts +7 -0
- package/packages/model-runtime/src/vertexai/index.ts +1 -1
- package/packages/types/src/agent/index.ts +2 -1
- package/packages/types/src/aiProvider.ts +10 -2
- package/packages/types/src/auth.ts +35 -0
- package/packages/types/src/discover/models.ts +1 -1
- package/packages/types/src/discover/providers.ts +1 -1
- package/packages/types/src/index.ts +4 -0
- package/packages/types/src/llm.ts +2 -47
- package/packages/types/src/session/agentSession.ts +3 -3
- package/packages/types/src/session/index.ts +2 -2
- package/packages/types/src/session/sessionGroup.ts +0 -2
- package/packages/types/src/user/settings/general.ts +1 -1
- package/packages/types/src/user/settings/modelProvider.ts +1 -1
- package/packages/utils/src/fetch/fetchSSE.ts +1 -1
- package/packages/utils/src/format.ts +2 -3
- package/packages/utils/src/index.ts +3 -1
- package/packages/utils/src/number.test.ts +1 -2
- package/packages/utils/src/number.ts +1 -2
- package/packages/utils/src/parseModels.test.ts +1 -2
- package/packages/utils/src/parseModels.ts +2 -3
- package/packages/utils/src/pricing.test.ts +1 -2
- package/packages/utils/src/pricing.ts +1 -1
- package/packages/utils/src/server/xor.ts +3 -1
- package/src/app/(backend)/middleware/auth/index.ts +1 -2
- package/src/app/(backend)/webapi/chat/vertexai/route.ts +1 -1
- package/src/app/(backend)/webapi/text-to-image/[provider]/route.ts +1 -2
- package/src/app/[variants]/(main)/(mobile)/me/settings/features/useCategory.tsx +2 -16
- package/src/app/[variants]/(main)/chat/@session/_layout/Desktop/SessionHeader.tsx +1 -3
- package/src/app/[variants]/(main)/chat/@session/_layout/Mobile/SessionHeader.tsx +1 -3
- package/src/app/[variants]/(main)/discover/(list)/model/features/List/ModelTypeIcon.tsx +1 -2
- package/src/app/[variants]/(main)/image/@menu/components/SeedNumberInput/index.tsx +1 -1
- package/src/app/[variants]/(main)/image/@menu/features/ConfigPanel/hooks/useAutoDimensions.ts +4 -3
- package/src/app/[variants]/(main)/settings/hooks/useCategory.tsx +3 -21
- package/src/app/[variants]/(main)/settings/provider/features/ModelList/CreateNewModelModal/Form.tsx +1 -1
- package/src/app/[variants]/(main)/settings/provider/features/ModelList/ModelItem.tsx +1 -1
- package/src/app/[variants]/(main)/settings/provider/features/ModelList/SortModelModal/ListItem.tsx +1 -1
- package/src/app/[variants]/(main)/settings/provider/features/ModelList/SortModelModal/index.tsx +1 -1
- package/src/components/ModelSelect/index.tsx +1 -1
- package/src/config/featureFlags/schema.test.ts +1 -2
- package/src/config/featureFlags/schema.ts +0 -6
- package/src/config/featureFlags/utils/parser.test.ts +7 -7
- package/src/database/_deprecated/core/index.ts +0 -1
- package/src/database/_deprecated/core/migrations/migrateSettingsToUser/type.ts +2 -5
- package/src/database/_deprecated/core/model.ts +4 -38
- package/src/database/_deprecated/models/message.ts +1 -1
- package/src/features/Conversation/Extras/Usage/UsageDetail/ModelCard.tsx +1 -1
- package/src/features/Conversation/Extras/Usage/UsageDetail/pricing.ts +3 -4
- package/src/features/Conversation/Extras/Usage/UsageDetail/tokens.test.ts +1 -1
- package/src/features/Conversation/Extras/Usage/UsageDetail/tokens.ts +3 -2
- package/src/layout/GlobalProvider/StoreInitialization.tsx +0 -3
- package/src/libs/trpc/async/context.ts +2 -1
- package/src/libs/trpc/edge/context.ts +2 -6
- package/src/libs/trpc/lambda/context.ts +1 -1
- package/src/migrations/FromV5ToV6/types/v5.ts +2 -2
- package/src/migrations/FromV5ToV6/types/v6.ts +2 -1
- package/src/server/globalConfig/genServerAiProviderConfig.ts +3 -3
- package/src/server/modules/ModelRuntime/index.test.ts +1 -1
- package/src/server/modules/ModelRuntime/index.ts +1 -1
- package/src/server/routers/async/caller.ts +2 -1
- package/src/server/routers/async/image.ts +2 -2
- package/src/server/routers/lambda/aiModel.ts +1 -1
- package/src/server/services/chunk/index.ts +2 -1
- package/src/server/services/generation/index.ts +2 -2
- package/src/services/_auth.ts +2 -1
- package/src/services/aiModel/server.test.ts +1 -1
- package/src/services/aiModel/type.ts +1 -1
- package/src/services/chat.ts +1 -1
- package/src/services/upload.ts +3 -3
- package/src/store/agent/slices/chat/action.ts +1 -1
- package/src/store/aiInfra/slices/aiModel/action.ts +6 -6
- package/src/store/aiInfra/slices/aiModel/initialState.ts +1 -1
- package/src/store/aiInfra/slices/aiModel/selectors.test.ts +1 -1
- package/src/store/aiInfra/slices/aiModel/selectors.ts +2 -1
- package/src/store/aiInfra/slices/aiProvider/__tests__/action.test.ts +7 -7
- package/src/store/aiInfra/slices/aiProvider/action.ts +8 -8
- package/src/store/aiInfra/slices/aiProvider/initialState.ts +2 -1
- package/src/store/electron/actions/app.ts +1 -1
- package/src/store/image/slices/generationConfig/action.test.ts +1 -1
- package/src/store/image/slices/generationConfig/action.ts +1 -1
- package/src/store/image/slices/generationConfig/hooks.test.ts +1 -1
- package/src/store/image/slices/generationConfig/hooks.ts +6 -3
- package/src/store/image/slices/generationConfig/selectors.test.ts +1 -1
- package/src/store/serverConfig/selectors.test.ts +0 -1
- package/src/store/user/initialState.ts +1 -4
- package/src/store/user/selectors.ts +0 -1
- package/src/store/user/slices/auth/action.ts +1 -1
- package/src/store/user/slices/auth/selectors.ts +3 -4
- package/src/store/user/slices/modelList/action.ts +8 -7
- package/src/store/user/slices/modelList/selectors/modelProvider.ts +8 -5
- package/src/store/user/slices/preference/selectors.ts +3 -2
- package/src/store/user/slices/settings/selectors/settings.ts +1 -2
- package/src/store/user/store.ts +1 -4
- package/docs/self-hosting/advanced/webrtc.mdx +0 -86
- package/docs/self-hosting/advanced/webrtc.zh-CN.mdx +0 -80
- package/packages/const/src/image.ts +0 -51
- package/src/app/[variants]/(main)/settings/sync/features/Alert.tsx +0 -53
- package/src/app/[variants]/(main)/settings/sync/features/DeviceInfo/Card.tsx +0 -42
- package/src/app/[variants]/(main)/settings/sync/features/DeviceInfo/DeviceName.tsx +0 -62
- package/src/app/[variants]/(main)/settings/sync/features/DeviceInfo/SystemIcon.tsx +0 -31
- package/src/app/[variants]/(main)/settings/sync/features/DeviceInfo/index.tsx +0 -103
- package/src/app/[variants]/(main)/settings/sync/features/WebRTC/ChannelNameInput.tsx +0 -45
- package/src/app/[variants]/(main)/settings/sync/features/WebRTC/SyncSwitch/index.css +0 -238
- package/src/app/[variants]/(main)/settings/sync/features/WebRTC/SyncSwitch/index.tsx +0 -79
- package/src/app/[variants]/(main)/settings/sync/features/WebRTC/generateRandomRoomName.ts +0 -4
- package/src/app/[variants]/(main)/settings/sync/features/WebRTC/index.tsx +0 -103
- package/src/app/[variants]/(main)/settings/sync/index.tsx +0 -17
- package/src/app/[variants]/(main)/settings/sync/page.tsx +0 -29
- package/src/database/_deprecated/core/sync.ts +0 -321
- package/src/features/SyncStatusInspector/DisableSync.tsx +0 -79
- package/src/features/SyncStatusInspector/EnableSync.tsx +0 -132
- package/src/features/SyncStatusInspector/EnableTag.tsx +0 -66
- package/src/features/SyncStatusInspector/index.tsx +0 -27
- package/src/hooks/useSyncData.ts +0 -50
- package/src/services/__tests__/sync.test.ts +0 -56
- package/src/services/sync.ts +0 -19
- package/src/store/user/slices/sync/action.test.ts +0 -164
- package/src/store/user/slices/sync/action.ts +0 -101
- package/src/store/user/slices/sync/initialState.ts +0 -13
- package/src/store/user/slices/sync/selectors.ts +0 -20
- /package/packages/{utils/src → model-runtime/src/utils}/getFallbackModelProperty.test.ts +0 -0
@@ -0,0 +1,110 @@
|
|
1
|
+
import { AgentRuntimeErrorType } from '@lobechat/model-runtime';
|
2
|
+
import { ChatErrorType } from '@lobechat/types';
|
3
|
+
import { describe, expect, it, vi } from 'vitest';
|
4
|
+
|
5
|
+
import { createErrorResponse } from './errorResponse';
|
6
|
+
|
7
|
+
describe('createErrorResponse', () => {
|
8
|
+
// 测试包含Invalid的错误类型
|
9
|
+
it('returns a 401 status for Invalid error type', () => {
|
10
|
+
const errorType = 'InvalidTestError';
|
11
|
+
const response = createErrorResponse(errorType as any);
|
12
|
+
expect(response.status).toBe(401);
|
13
|
+
});
|
14
|
+
|
15
|
+
it('returns a 403 status for LocationNotSupportError error type', () => {
|
16
|
+
const errorType = AgentRuntimeErrorType.LocationNotSupportError;
|
17
|
+
const response = createErrorResponse(errorType);
|
18
|
+
expect(response.status).toBe(403);
|
19
|
+
});
|
20
|
+
|
21
|
+
it('returns a 404 status for ModelNotFound error type', () => {
|
22
|
+
const errorType = AgentRuntimeErrorType.ModelNotFound;
|
23
|
+
const response = createErrorResponse(errorType);
|
24
|
+
expect(response.status).toBe(404);
|
25
|
+
});
|
26
|
+
|
27
|
+
it('returns a 429 status for InsufficientQuota error type', () => {
|
28
|
+
const errorType = AgentRuntimeErrorType.InsufficientQuota;
|
29
|
+
const response = createErrorResponse(errorType);
|
30
|
+
expect(response.status).toBe(429);
|
31
|
+
});
|
32
|
+
|
33
|
+
it('returns a 429 status for QuotaLimitReached error type', () => {
|
34
|
+
const errorType = AgentRuntimeErrorType.QuotaLimitReached;
|
35
|
+
const response = createErrorResponse(errorType);
|
36
|
+
expect(response.status).toBe(429);
|
37
|
+
});
|
38
|
+
|
39
|
+
it('returns a 400 status for ExceededContextWindow error type', () => {
|
40
|
+
const errorType = AgentRuntimeErrorType.ExceededContextWindow;
|
41
|
+
const response = createErrorResponse(errorType);
|
42
|
+
expect(response.status).toBe(400);
|
43
|
+
});
|
44
|
+
|
45
|
+
describe('Provider Biz Error', () => {
|
46
|
+
it('returns a 471 status for ProviderBizError error type', () => {
|
47
|
+
const errorType = AgentRuntimeErrorType.ProviderBizError;
|
48
|
+
const response = createErrorResponse(errorType);
|
49
|
+
expect(response.status).toBe(471);
|
50
|
+
});
|
51
|
+
|
52
|
+
it('returns a 470 status for AgentRuntimeError error type', () => {
|
53
|
+
const errorType = AgentRuntimeErrorType.AgentRuntimeError;
|
54
|
+
const response = createErrorResponse(errorType);
|
55
|
+
expect(response.status).toBe(470);
|
56
|
+
});
|
57
|
+
|
58
|
+
it('returns a 472 status for OllamaBizError error type', () => {
|
59
|
+
const errorType = AgentRuntimeErrorType.OllamaBizError;
|
60
|
+
const response = createErrorResponse(errorType);
|
61
|
+
expect(response.status).toBe(472);
|
62
|
+
});
|
63
|
+
|
64
|
+
it('returns a 472 status for OllamaServiceUnavailable error type', () => {
|
65
|
+
const errorType = ChatErrorType.OllamaServiceUnavailable;
|
66
|
+
const response = createErrorResponse(errorType);
|
67
|
+
expect(response.status).toBe(472);
|
68
|
+
});
|
69
|
+
});
|
70
|
+
|
71
|
+
// 测试状态码不在200-599范围内的情况
|
72
|
+
it('logs an error when the status code is not a number or not in the range of 200-599', () => {
|
73
|
+
const errorType = 'Unknown Error';
|
74
|
+
const consoleSpy = vi.spyOn(console, 'error');
|
75
|
+
try {
|
76
|
+
createErrorResponse(errorType as any);
|
77
|
+
} catch (e) {}
|
78
|
+
expect(consoleSpy).toHaveBeenCalled();
|
79
|
+
consoleSpy.mockRestore();
|
80
|
+
});
|
81
|
+
|
82
|
+
// 测试默认情况
|
83
|
+
it('returns the same error type as status for unknown error types', () => {
|
84
|
+
const errorType = 500; // 假设500是一个未知的错误类型
|
85
|
+
const response = createErrorResponse(errorType as any);
|
86
|
+
expect(response.status).toBe(errorType);
|
87
|
+
});
|
88
|
+
|
89
|
+
// 测试返回的Response对象是否包含正确的body和errorType
|
90
|
+
it('returns a Response object with the correct body and errorType', () => {
|
91
|
+
const errorType = ChatErrorType.NoOpenAIAPIKey;
|
92
|
+
const body = { message: 'No API key provided' };
|
93
|
+
const response = createErrorResponse(errorType, body);
|
94
|
+
return response.json().then((data) => {
|
95
|
+
expect(data).toEqual({
|
96
|
+
body,
|
97
|
+
errorType,
|
98
|
+
});
|
99
|
+
});
|
100
|
+
});
|
101
|
+
|
102
|
+
// 测试没有提供body时,返回的Response对象的body是否为undefined
|
103
|
+
it('returns a Response object with an undefined body when no body is provided', () => {
|
104
|
+
const errorType = ChatErrorType.NoOpenAIAPIKey;
|
105
|
+
const response = createErrorResponse(errorType);
|
106
|
+
return response.json().then((data) => {
|
107
|
+
expect(data.body).toBeUndefined();
|
108
|
+
});
|
109
|
+
});
|
110
|
+
});
|
@@ -0,0 +1,64 @@
|
|
1
|
+
import { ChatErrorType, ErrorResponse, ErrorType } from '@lobechat/types';
|
2
|
+
|
3
|
+
import { AgentRuntimeErrorType, ILobeAgentRuntimeErrorType } from '../types';
|
4
|
+
|
5
|
+
const getStatus = (errorType: ILobeAgentRuntimeErrorType | ErrorType) => {
|
6
|
+
// InvalidAccessCode / InvalidAzureAPIKey / InvalidOpenAIAPIKey / InvalidZhipuAPIKey ....
|
7
|
+
if (errorType.toString().includes('Invalid')) return 401;
|
8
|
+
|
9
|
+
switch (errorType) {
|
10
|
+
case AgentRuntimeErrorType.InvalidProviderAPIKey: {
|
11
|
+
return 401;
|
12
|
+
}
|
13
|
+
|
14
|
+
case AgentRuntimeErrorType.ExceededContextWindow: {
|
15
|
+
return 400;
|
16
|
+
}
|
17
|
+
|
18
|
+
case AgentRuntimeErrorType.LocationNotSupportError: {
|
19
|
+
return 403;
|
20
|
+
}
|
21
|
+
|
22
|
+
case AgentRuntimeErrorType.ModelNotFound: {
|
23
|
+
return 404;
|
24
|
+
}
|
25
|
+
|
26
|
+
case AgentRuntimeErrorType.InsufficientQuota:
|
27
|
+
case AgentRuntimeErrorType.QuotaLimitReached: {
|
28
|
+
return 429;
|
29
|
+
}
|
30
|
+
|
31
|
+
// define the 471~480 as provider error
|
32
|
+
case AgentRuntimeErrorType.AgentRuntimeError: {
|
33
|
+
return 470;
|
34
|
+
}
|
35
|
+
|
36
|
+
case AgentRuntimeErrorType.ProviderBizError: {
|
37
|
+
return 471;
|
38
|
+
}
|
39
|
+
|
40
|
+
// all local provider connection error
|
41
|
+
case AgentRuntimeErrorType.OllamaServiceUnavailable:
|
42
|
+
case ChatErrorType.OllamaServiceUnavailable:
|
43
|
+
case AgentRuntimeErrorType.OllamaBizError: {
|
44
|
+
return 472;
|
45
|
+
}
|
46
|
+
}
|
47
|
+
|
48
|
+
return errorType as number;
|
49
|
+
};
|
50
|
+
|
51
|
+
export const createErrorResponse = (errorType: ILobeAgentRuntimeErrorType, body?: any) => {
|
52
|
+
const statusCode = getStatus(errorType);
|
53
|
+
|
54
|
+
const data: ErrorResponse = { body, errorType };
|
55
|
+
|
56
|
+
if (typeof statusCode !== 'number' || statusCode < 200 || statusCode > 599) {
|
57
|
+
console.error(
|
58
|
+
`current StatusCode: \`${statusCode}\` .`,
|
59
|
+
'Please go to `./utils/errorResponse.ts` to defined the statusCode.',
|
60
|
+
);
|
61
|
+
}
|
62
|
+
|
63
|
+
return new Response(JSON.stringify(data), { status: statusCode });
|
64
|
+
};
|
@@ -0,0 +1,91 @@
|
|
1
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
2
|
+
|
3
|
+
import { imageToBase64, imageUrlToBase64 } from './imageToBase64';
|
4
|
+
|
5
|
+
describe('imageToBase64', () => {
|
6
|
+
let mockImage: HTMLImageElement;
|
7
|
+
let mockCanvas: HTMLCanvasElement;
|
8
|
+
let mockContext: CanvasRenderingContext2D;
|
9
|
+
|
10
|
+
beforeEach(() => {
|
11
|
+
mockImage = {
|
12
|
+
width: 200,
|
13
|
+
height: 100,
|
14
|
+
} as HTMLImageElement;
|
15
|
+
|
16
|
+
mockContext = {
|
17
|
+
drawImage: vi.fn(),
|
18
|
+
} as unknown as CanvasRenderingContext2D;
|
19
|
+
|
20
|
+
mockCanvas = {
|
21
|
+
width: 0,
|
22
|
+
height: 0,
|
23
|
+
getContext: vi.fn().mockReturnValue(mockContext),
|
24
|
+
toDataURL: vi.fn().mockReturnValue('data:image/webp;base64,mockBase64Data'),
|
25
|
+
} as unknown as HTMLCanvasElement;
|
26
|
+
|
27
|
+
vi.spyOn(document, 'createElement').mockReturnValue(mockCanvas);
|
28
|
+
});
|
29
|
+
|
30
|
+
afterEach(() => {
|
31
|
+
vi.restoreAllMocks();
|
32
|
+
});
|
33
|
+
|
34
|
+
it('should convert image to base64 with correct size and type', () => {
|
35
|
+
const result = imageToBase64({ img: mockImage, size: 100, type: 'image/jpeg' });
|
36
|
+
|
37
|
+
expect(document.createElement).toHaveBeenCalledWith('canvas');
|
38
|
+
expect(mockCanvas.width).toBe(100);
|
39
|
+
expect(mockCanvas.height).toBe(100);
|
40
|
+
expect(mockCanvas.getContext).toHaveBeenCalledWith('2d');
|
41
|
+
expect(mockContext.drawImage).toHaveBeenCalledWith(mockImage, 50, 0, 100, 100, 0, 0, 100, 100);
|
42
|
+
expect(mockCanvas.toDataURL).toHaveBeenCalledWith('image/jpeg');
|
43
|
+
expect(result).toBe('data:image/webp;base64,mockBase64Data');
|
44
|
+
});
|
45
|
+
|
46
|
+
it('should use default type when not specified', () => {
|
47
|
+
imageToBase64({ img: mockImage, size: 100 });
|
48
|
+
expect(mockCanvas.toDataURL).toHaveBeenCalledWith('image/webp');
|
49
|
+
});
|
50
|
+
|
51
|
+
it('should handle taller images correctly', () => {
|
52
|
+
mockImage.width = 100;
|
53
|
+
mockImage.height = 200;
|
54
|
+
imageToBase64({ img: mockImage, size: 100 });
|
55
|
+
expect(mockContext.drawImage).toHaveBeenCalledWith(mockImage, 0, 50, 100, 100, 0, 0, 100, 100);
|
56
|
+
});
|
57
|
+
});
|
58
|
+
|
59
|
+
describe('imageUrlToBase64', () => {
|
60
|
+
const mockFetch = vi.fn();
|
61
|
+
const mockArrayBuffer = new ArrayBuffer(8);
|
62
|
+
|
63
|
+
beforeEach(() => {
|
64
|
+
global.fetch = mockFetch;
|
65
|
+
global.btoa = vi.fn().mockReturnValue('mockBase64String');
|
66
|
+
});
|
67
|
+
|
68
|
+
afterEach(() => {
|
69
|
+
vi.restoreAllMocks();
|
70
|
+
});
|
71
|
+
|
72
|
+
it('should convert image URL to base64 string', async () => {
|
73
|
+
mockFetch.mockResolvedValue({
|
74
|
+
arrayBuffer: () => Promise.resolve(mockArrayBuffer),
|
75
|
+
blob: () => Promise.resolve(new Blob([mockArrayBuffer], { type: 'image/jpg' })),
|
76
|
+
});
|
77
|
+
|
78
|
+
const result = await imageUrlToBase64('https://example.com/image.jpg');
|
79
|
+
|
80
|
+
expect(mockFetch).toHaveBeenCalledWith('https://example.com/image.jpg');
|
81
|
+
expect(global.btoa).toHaveBeenCalled();
|
82
|
+
expect(result).toEqual({ base64: 'mockBase64String', mimeType: 'image/jpg' });
|
83
|
+
});
|
84
|
+
|
85
|
+
it('should throw an error when fetch fails', async () => {
|
86
|
+
const mockError = new Error('Fetch failed');
|
87
|
+
mockFetch.mockRejectedValue(mockError);
|
88
|
+
|
89
|
+
await expect(imageUrlToBase64('https://example.com/image.jpg')).rejects.toThrow('Fetch failed');
|
90
|
+
});
|
91
|
+
});
|
@@ -0,0 +1,62 @@
|
|
1
|
+
export const imageToBase64 = ({
|
2
|
+
size,
|
3
|
+
img,
|
4
|
+
type = 'image/webp',
|
5
|
+
}: {
|
6
|
+
img: HTMLImageElement;
|
7
|
+
size: number;
|
8
|
+
type?: string;
|
9
|
+
}) => {
|
10
|
+
const canvas = document.createElement('canvas');
|
11
|
+
const ctx = canvas.getContext('2d') as CanvasRenderingContext2D;
|
12
|
+
let startX = 0;
|
13
|
+
let startY = 0;
|
14
|
+
|
15
|
+
if (img.width > img.height) {
|
16
|
+
startX = (img.width - img.height) / 2;
|
17
|
+
} else {
|
18
|
+
startY = (img.height - img.width) / 2;
|
19
|
+
}
|
20
|
+
|
21
|
+
canvas.width = size;
|
22
|
+
canvas.height = size;
|
23
|
+
|
24
|
+
ctx.drawImage(
|
25
|
+
img,
|
26
|
+
startX,
|
27
|
+
startY,
|
28
|
+
Math.min(img.width, img.height),
|
29
|
+
Math.min(img.width, img.height),
|
30
|
+
0,
|
31
|
+
0,
|
32
|
+
size,
|
33
|
+
size,
|
34
|
+
);
|
35
|
+
|
36
|
+
return canvas.toDataURL(type);
|
37
|
+
};
|
38
|
+
|
39
|
+
export const imageUrlToBase64 = async (
|
40
|
+
imageUrl: string,
|
41
|
+
): Promise<{ base64: string; mimeType: string }> => {
|
42
|
+
try {
|
43
|
+
const res = await fetch(imageUrl);
|
44
|
+
const blob = await res.blob();
|
45
|
+
const arrayBuffer = await blob.arrayBuffer();
|
46
|
+
|
47
|
+
const base64 =
|
48
|
+
typeof btoa === 'function'
|
49
|
+
? btoa(
|
50
|
+
new Uint8Array(arrayBuffer).reduce(
|
51
|
+
(data, byte) => data + String.fromCharCode(byte),
|
52
|
+
'',
|
53
|
+
),
|
54
|
+
)
|
55
|
+
: Buffer.from(arrayBuffer).toString('base64');
|
56
|
+
|
57
|
+
return { base64, mimeType: blob.type };
|
58
|
+
} catch (error) {
|
59
|
+
console.error('Error converting image to base64:', error);
|
60
|
+
throw error;
|
61
|
+
}
|
62
|
+
};
|
@@ -4,7 +4,7 @@ import type { ChatModelCard } from '@/types/llm';
|
|
4
4
|
|
5
5
|
import {
|
6
6
|
MODEL_LIST_CONFIGS,
|
7
|
-
|
7
|
+
MODEL_OWNER_DETECTION_CONFIG,
|
8
8
|
detectModelProvider,
|
9
9
|
processModelList,
|
10
10
|
processMultiProviderModelList,
|
@@ -754,7 +754,7 @@ describe('modelParse', () => {
|
|
754
754
|
describe('MODEL_LIST_CONFIGS and PROVIDER_DETECTION_CONFIG', () => {
|
755
755
|
it('should have matching keys in both configuration objects', () => {
|
756
756
|
const modelConfigKeys = Object.keys(MODEL_LIST_CONFIGS);
|
757
|
-
const providerDetectionKeys = Object.keys(
|
757
|
+
const providerDetectionKeys = Object.keys(MODEL_OWNER_DETECTION_CONFIG);
|
758
758
|
expect(modelConfigKeys.sort()).toEqual(providerDetectionKeys.sort());
|
759
759
|
});
|
760
760
|
});
|
@@ -1,4 +1,5 @@
|
|
1
1
|
import type { ChatModelCard } from '@lobechat/types';
|
2
|
+
import { AIBaseModelCard } from 'model-bank';
|
2
3
|
|
3
4
|
import type { ModelProviderKey } from '../types';
|
4
5
|
|
@@ -25,16 +26,16 @@ export const MODEL_LIST_CONFIGS = {
|
|
25
26
|
reasoningKeywords: ['thinking', '-2.5-'],
|
26
27
|
visionKeywords: ['gemini', 'learnlm'],
|
27
28
|
},
|
29
|
+
llama: {
|
30
|
+
functionCallKeywords: ['llama-3.2', 'llama-3.3', 'llama-4'],
|
31
|
+
reasoningKeywords: [],
|
32
|
+
visionKeywords: ['llava'],
|
33
|
+
},
|
28
34
|
moonshot: {
|
29
35
|
functionCallKeywords: ['moonshot', 'kimi'],
|
30
36
|
reasoningKeywords: ['thinking'],
|
31
37
|
visionKeywords: ['vision', 'kimi-latest', 'kimi-thinking-preview'],
|
32
38
|
},
|
33
|
-
ollama: {
|
34
|
-
functionCallKeywords: ['llama-3.2', 'llama-3.3', 'llama-4'],
|
35
|
-
reasoningKeywords: [],
|
36
|
-
visionKeywords: ['llava'],
|
37
|
-
},
|
38
39
|
openai: {
|
39
40
|
excludeKeywords: ['audio'],
|
40
41
|
functionCallKeywords: ['4o', '4.1', 'o3', 'o4', 'oss'],
|
@@ -81,13 +82,13 @@ export const MODEL_LIST_CONFIGS = {
|
|
81
82
|
},
|
82
83
|
} as const;
|
83
84
|
|
84
|
-
//
|
85
|
-
export const
|
85
|
+
// 模型所有者 (提供商) 关键词配置
|
86
|
+
export const MODEL_OWNER_DETECTION_CONFIG = {
|
86
87
|
anthropic: ['claude'],
|
87
88
|
deepseek: ['deepseek'],
|
88
89
|
google: ['gemini', 'imagen'],
|
90
|
+
llama: ['llama', 'llava'],
|
89
91
|
moonshot: ['moonshot', 'kimi'],
|
90
|
-
ollama: ['llama', 'llava'],
|
91
92
|
openai: ['o1', 'o3', 'o4', 'gpt-'],
|
92
93
|
qwen: ['qwen', 'qwq', 'qvq'],
|
93
94
|
v0: ['v0'],
|
@@ -175,7 +176,12 @@ const findKnownModelByProvider = async (
|
|
175
176
|
// 尝试动态导入对应的配置文件
|
176
177
|
const modules = await import('model-bank');
|
177
178
|
|
178
|
-
|
179
|
+
// 如果提供商配置文件不存在,跳过
|
180
|
+
if (!(provider in modules)) {
|
181
|
+
return null;
|
182
|
+
}
|
183
|
+
|
184
|
+
const providerModels = modules[provider as keyof typeof modules] as AIBaseModelCard[];
|
179
185
|
|
180
186
|
// 如果导入成功且有数据,进行查找
|
181
187
|
if (Array.isArray(providerModels)) {
|
@@ -197,7 +203,7 @@ const findKnownModelByProvider = async (
|
|
197
203
|
export const detectModelProvider = (modelId: string): keyof typeof MODEL_LIST_CONFIGS => {
|
198
204
|
const lowerModelId = modelId.toLowerCase();
|
199
205
|
|
200
|
-
for (const [provider, keywords] of Object.entries(
|
206
|
+
for (const [provider, keywords] of Object.entries(MODEL_OWNER_DETECTION_CONFIG)) {
|
201
207
|
const hasKeyword = isKeywordListMatch(lowerModelId, keywords);
|
202
208
|
|
203
209
|
if (hasKeyword && provider in MODEL_LIST_CONFIGS) {
|
@@ -1,9 +1,9 @@
|
|
1
|
-
import { imageUrlToBase64 } from '@lobechat/utils';
|
2
1
|
import createDebug from 'debug';
|
3
2
|
import { RuntimeImageGenParamsValue } from 'model-bank';
|
4
3
|
import OpenAI from 'openai';
|
5
4
|
|
6
5
|
import { CreateImagePayload, CreateImageResponse } from '../../types/image';
|
6
|
+
import { imageUrlToBase64 } from '../imageToBase64';
|
7
7
|
import { convertImageUrlToFile } from '../openaiHelpers';
|
8
8
|
import { parseDataUri } from '../uriParser';
|
9
9
|
|
@@ -1,15 +1,13 @@
|
|
1
|
-
import { getModelPropertyWithFallback } from '@lobechat/utils';
|
2
1
|
import dayjs from 'dayjs';
|
3
2
|
import utc from 'dayjs/plugin/utc';
|
4
3
|
import { LOBE_DEFAULT_MODEL_LIST } from 'model-bank';
|
4
|
+
import type { AiModelType } from 'model-bank';
|
5
5
|
import OpenAI, { ClientOptions } from 'openai';
|
6
6
|
import { Stream } from 'openai/streaming';
|
7
7
|
|
8
|
-
import type { AiModelType } from '@/types/aiModel';
|
9
8
|
import type { ChatModelCard } from '@/types/llm';
|
10
9
|
|
11
10
|
import { LobeRuntimeAI } from '../../BaseAI';
|
12
|
-
import { AgentRuntimeErrorType, ILobeAgentRuntimeErrorType } from '../../error';
|
13
11
|
import {
|
14
12
|
ChatCompletionErrorPayload,
|
15
13
|
ChatCompletionTool,
|
@@ -24,10 +22,12 @@ import {
|
|
24
22
|
TextToSpeechOptions,
|
25
23
|
TextToSpeechPayload,
|
26
24
|
} from '../../types';
|
25
|
+
import { AgentRuntimeErrorType, ILobeAgentRuntimeErrorType } from '../../types/error';
|
27
26
|
import { CreateImagePayload, CreateImageResponse } from '../../types/image';
|
28
27
|
import { AgentRuntimeError } from '../createError';
|
29
28
|
import { debugResponse, debugStream } from '../debugStream';
|
30
29
|
import { desensitizeUrl } from '../desensitizeUrl';
|
30
|
+
import { getModelPropertyWithFallback } from '../getFallbackModelProperty';
|
31
31
|
import { handleOpenAIError } from '../handleOpenAIError';
|
32
32
|
import { convertOpenAIMessages, convertOpenAIResponseInputs } from '../openaiHelpers';
|
33
33
|
import { postProcessModelList } from '../postProcessModelList';
|
@@ -1,7 +1,7 @@
|
|
1
|
-
import { imageUrlToBase64 } from '@lobechat/utils';
|
2
1
|
import OpenAI from 'openai';
|
3
2
|
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
4
3
|
|
4
|
+
import { imageUrlToBase64 } from './imageToBase64';
|
5
5
|
import {
|
6
6
|
convertImageUrlToFile,
|
7
7
|
convertMessageContent,
|
@@ -11,7 +11,7 @@ import {
|
|
11
11
|
import { parseDataUri } from './uriParser';
|
12
12
|
|
13
13
|
// 模拟依赖
|
14
|
-
vi.mock('
|
14
|
+
vi.mock('./imageToBase64');
|
15
15
|
vi.mock('./uriParser');
|
16
16
|
|
17
17
|
describe('convertMessageContent', () => {
|
@@ -1,9 +1,8 @@
|
|
1
|
-
import { imageUrlToBase64 } from '@lobechat/utils';
|
2
1
|
import OpenAI, { toFile } from 'openai';
|
3
2
|
|
4
|
-
import { disableStreamModels, systemToUserModels } from '
|
5
|
-
import { ChatStreamPayload, OpenAIChatMessage } from '
|
6
|
-
|
3
|
+
import { disableStreamModels, systemToUserModels } from '../const/models';
|
4
|
+
import { ChatStreamPayload, OpenAIChatMessage } from '../types';
|
5
|
+
import { imageUrlToBase64 } from './imageToBase64';
|
7
6
|
import { parseDataUri } from './uriParser';
|
8
7
|
|
9
8
|
export const convertMessageContent = async (
|
@@ -1,5 +1,5 @@
|
|
1
|
-
import { CHAT_MODEL_IMAGE_GENERATION_PARAMS } from '
|
2
|
-
|
1
|
+
import { AiModelType, CHAT_MODEL_IMAGE_GENERATION_PARAMS } from 'model-bank';
|
2
|
+
|
3
3
|
import type { ChatModelCard } from '@/types/llm';
|
4
4
|
|
5
5
|
// Whitelist for automatic image model generation
|
@@ -0,0 +1,71 @@
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
2
|
+
|
3
|
+
import { safeParseJSON } from './safeParseJSON';
|
4
|
+
|
5
|
+
describe('safeParseJSON', () => {
|
6
|
+
it('should parse a valid JSON string', () => {
|
7
|
+
const validJSON = '{"name": "John", "age": 30}';
|
8
|
+
const result = safeParseJSON(validJSON);
|
9
|
+
expect(result).toEqual({ name: 'John', age: 30 });
|
10
|
+
});
|
11
|
+
|
12
|
+
it('should return undefined for invalid JSON', () => {
|
13
|
+
const invalidJSON = '{name: John}';
|
14
|
+
const result = safeParseJSON(invalidJSON);
|
15
|
+
expect(result).toBeUndefined();
|
16
|
+
});
|
17
|
+
|
18
|
+
it('should parse an empty object', () => {
|
19
|
+
const emptyObject = '{}';
|
20
|
+
const result = safeParseJSON(emptyObject);
|
21
|
+
expect(result).toEqual({});
|
22
|
+
});
|
23
|
+
|
24
|
+
it('should parse an array', () => {
|
25
|
+
const arrayJSON = '[1, 2, 3]';
|
26
|
+
const result = safeParseJSON(arrayJSON);
|
27
|
+
expect(result).toEqual([1, 2, 3]);
|
28
|
+
});
|
29
|
+
|
30
|
+
it('should parse nested objects', () => {
|
31
|
+
const nestedJSON = '{"user": {"name": "John", "age": 30}}';
|
32
|
+
const result = safeParseJSON(nestedJSON);
|
33
|
+
expect(result).toEqual({ user: { name: 'John', age: 30 } });
|
34
|
+
});
|
35
|
+
|
36
|
+
it('should return undefined for an empty string', () => {
|
37
|
+
const result = safeParseJSON('');
|
38
|
+
expect(result).toBeUndefined();
|
39
|
+
});
|
40
|
+
|
41
|
+
it('should return undefined for non-string input', () => {
|
42
|
+
// @ts-expect-error: Testing with invalid input type
|
43
|
+
const result = safeParseJSON(123);
|
44
|
+
expect(result).toBeUndefined();
|
45
|
+
});
|
46
|
+
|
47
|
+
it('should parse JSON with special characters', () => {
|
48
|
+
const specialJSON = '{"message": "Hello, \\"world\\"!"}';
|
49
|
+
const result = safeParseJSON(specialJSON);
|
50
|
+
expect(result).toEqual({ message: 'Hello, "world"!' });
|
51
|
+
});
|
52
|
+
|
53
|
+
it('should parse large JSON without throwing an error', () => {
|
54
|
+
const largeJSON = JSON.stringify({ data: Array(1000).fill('test') });
|
55
|
+
const result = safeParseJSON(largeJSON);
|
56
|
+
expect(result).toHaveProperty('data');
|
57
|
+
expect(Array.isArray(result!.data)).toBe(true);
|
58
|
+
expect(result!.data).toHaveLength(1000);
|
59
|
+
});
|
60
|
+
|
61
|
+
it('should handle JSON with different data types', () => {
|
62
|
+
const mixedJSON = '{"string": "text", "number": 42, "boolean": true, "null": null}';
|
63
|
+
const result = safeParseJSON(mixedJSON);
|
64
|
+
expect(result).toEqual({
|
65
|
+
string: 'text',
|
66
|
+
number: 42,
|
67
|
+
boolean: true,
|
68
|
+
null: null,
|
69
|
+
});
|
70
|
+
});
|
71
|
+
});
|
@@ -1,7 +1,7 @@
|
|
1
1
|
import { InvokeModelWithResponseStreamResponse } from '@aws-sdk/client-bedrock-runtime';
|
2
|
-
import { nanoid } from '@lobechat/utils';
|
3
2
|
|
4
3
|
import { ChatStreamCallbacks } from '../../../types';
|
4
|
+
import { nanoid } from '../../uuid';
|
5
5
|
import { transformAnthropicStream } from '../anthropic';
|
6
6
|
import {
|
7
7
|
StreamContext,
|
@@ -1,8 +1,7 @@
|
|
1
1
|
import { InvokeModelWithResponseStreamResponse } from '@aws-sdk/client-bedrock-runtime';
|
2
|
-
import * as uuidModule from '@lobechat/utils';
|
3
|
-
import { Readable } from 'stream';
|
4
2
|
import { describe, expect, it, vi } from 'vitest';
|
5
3
|
|
4
|
+
import * as uuidModule from '../../uuid';
|
6
5
|
import { AWSBedrockLlamaStream } from './llama';
|
7
6
|
|
8
7
|
describe('AWSBedrockLlamaStream', () => {
|
@@ -1,7 +1,7 @@
|
|
1
1
|
import { InvokeModelWithResponseStreamResponse } from '@aws-sdk/client-bedrock-runtime';
|
2
|
-
import { nanoid } from '@lobechat/utils';
|
3
2
|
|
4
3
|
import { ChatStreamCallbacks } from '../../../types';
|
4
|
+
import { nanoid } from '../../uuid';
|
5
5
|
import {
|
6
6
|
StreamContext,
|
7
7
|
StreamProtocolChunk,
|
@@ -1,7 +1,7 @@
|
|
1
1
|
import { GenerateContentResponse } from '@google/genai';
|
2
|
-
import * as uuidModule from '@lobechat/utils';
|
3
2
|
import { describe, expect, it, vi } from 'vitest';
|
4
3
|
|
4
|
+
import * as uuidModule from '../uuid';
|
5
5
|
import { GoogleGenerativeAIStream } from './google-ai';
|
6
6
|
|
7
7
|
describe('GoogleGenerativeAIStream', () => {
|
@@ -1,11 +1,11 @@
|
|
1
1
|
import { GenerateContentResponse } from '@google/genai';
|
2
|
-
import { nanoid } from '@lobechat/utils';
|
3
2
|
|
4
3
|
import errorLocale from '@/locales/default/error';
|
5
4
|
import { ModelTokensUsage } from '@/types/message';
|
6
5
|
import { GroundingSearch } from '@/types/search';
|
7
6
|
|
8
7
|
import { ChatStreamCallbacks } from '../../types';
|
8
|
+
import { nanoid } from '../uuid';
|
9
9
|
import {
|
10
10
|
StreamContext,
|
11
11
|
StreamProtocolChunk,
|