@lobehub/lobehub 2.0.0-next.1 → 2.0.0-next.11
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/.github/workflows/desktop-pr-build.yml +12 -10
- package/.github/workflows/docker.yml +25 -20
- package/.github/workflows/e2e.yml +3 -3
- package/.github/workflows/release-desktop-beta.yml +8 -8
- package/.github/workflows/release.yml +1 -1
- package/.github/workflows/test.yml +4 -4
- package/CHANGELOG.md +261 -0
- package/apps/desktop/src/main/utils/next-electron-rsc.ts +7 -5
- package/changelog/v1.json +82 -0
- package/docs/development/database-schema.dbml +11 -1
- package/docs/self-hosting/advanced/auth/next-auth/auth0.mdx +2 -2
- package/docs/self-hosting/advanced/auth/next-auth/auth0.zh-CN.mdx +2 -2
- package/docs/self-hosting/advanced/auth/next-auth/authelia.mdx +2 -2
- package/docs/self-hosting/advanced/auth/next-auth/authelia.zh-CN.mdx +2 -2
- package/docs/self-hosting/advanced/auth/next-auth/authentik.mdx +2 -2
- package/docs/self-hosting/advanced/auth/next-auth/authentik.zh-CN.mdx +2 -2
- package/docs/self-hosting/advanced/auth/next-auth/casdoor.mdx +2 -2
- package/docs/self-hosting/advanced/auth/next-auth/casdoor.zh-CN.mdx +2 -2
- package/docs/self-hosting/advanced/auth/next-auth/cloudflare-zero-trust.mdx +2 -2
- package/docs/self-hosting/advanced/auth/next-auth/cloudflare-zero-trust.zh-CN.mdx +2 -2
- package/docs/self-hosting/advanced/auth/next-auth/github.mdx +2 -2
- package/docs/self-hosting/advanced/auth/next-auth/github.zh-CN.mdx +2 -2
- package/docs/self-hosting/advanced/auth/next-auth/google.mdx +32 -29
- package/docs/self-hosting/advanced/auth/next-auth/keycloak.mdx +2 -2
- package/docs/self-hosting/advanced/auth/next-auth/keycloak.zh-CN.mdx +2 -2
- package/docs/self-hosting/advanced/auth/next-auth/logto.mdx +5 -3
- package/docs/self-hosting/advanced/auth/next-auth/logto.zh-CN.mdx +5 -3
- package/docs/self-hosting/advanced/auth/next-auth/microsoft-entra-id.mdx +2 -2
- package/docs/self-hosting/advanced/auth/next-auth/microsoft-entra-id.zh-CN.mdx +2 -2
- package/docs/self-hosting/advanced/auth/next-auth/okta.mdx +2 -2
- package/docs/self-hosting/advanced/auth/next-auth/okta.zh-CN.mdx +2 -2
- package/docs/self-hosting/advanced/auth/next-auth/wechat.mdx +2 -2
- package/docs/self-hosting/advanced/auth/next-auth/wechat.zh-CN.mdx +2 -2
- package/docs/self-hosting/advanced/auth/next-auth/zitadel.mdx +2 -2
- package/docs/self-hosting/advanced/auth/next-auth/zitadel.zh-CN.mdx +2 -2
- package/docs/self-hosting/advanced/auth.mdx +32 -21
- package/docs/self-hosting/advanced/auth.zh-CN.mdx +30 -19
- package/docs/self-hosting/advanced/online-search.mdx +30 -25
- package/docs/self-hosting/advanced/online-search.zh-CN.mdx +25 -23
- package/locales/ar/models.json +15 -6
- package/locales/bg-BG/models.json +15 -6
- package/locales/de-DE/models.json +15 -6
- package/locales/en-US/models.json +15 -6
- package/locales/es-ES/models.json +15 -6
- package/locales/fa-IR/models.json +15 -6
- package/locales/fr-FR/models.json +15 -6
- package/locales/it-IT/models.json +15 -6
- package/locales/ja-JP/models.json +15 -6
- package/locales/ko-KR/models.json +21 -12
- package/locales/nl-NL/models.json +15 -6
- package/locales/pl-PL/models.json +15 -6
- package/locales/pt-BR/models.json +15 -6
- package/locales/ru-RU/models.json +15 -6
- package/locales/tr-TR/models.json +15 -6
- package/locales/vi-VN/models.json +15 -6
- package/locales/zh-CN/models.json +15 -6
- package/locales/zh-TW/models.json +15 -6
- package/next.config.ts +2 -3
- package/package.json +17 -23
- package/packages/const/src/index.ts +0 -1
- package/packages/const/src/models.ts +13 -0
- package/packages/const/src/url.ts +1 -4
- package/packages/context-engine/src/index.ts +1 -6
- package/packages/context-engine/src/processors/GroupMessageFlatten.ts +12 -2
- package/packages/context-engine/src/processors/__tests__/GroupMessageFlatten.test.ts +73 -9
- package/packages/context-engine/src/providers/index.ts +0 -2
- package/packages/database/migrations/0041_improve_index.sql +10 -0
- package/packages/database/migrations/meta/0041_snapshot.json +7784 -0
- package/packages/database/migrations/meta/_journal.json +7 -0
- package/packages/database/package.json +1 -1
- package/packages/database/src/core/migrations.json +17 -0
- package/packages/database/src/models/__tests__/message.grouping.test.ts +812 -0
- package/packages/database/src/models/__tests__/message.test.ts +322 -170
- package/packages/database/src/models/message.ts +62 -24
- package/packages/database/src/models/session.ts +60 -19
- package/packages/database/src/schemas/agent.ts +10 -11
- package/packages/database/src/schemas/message.ts +5 -1
- package/packages/database/src/schemas/relations.ts +6 -4
- package/packages/database/src/schemas/session.ts +2 -0
- package/packages/database/src/schemas/topic.ts +6 -1
- package/packages/database/src/utils/__tests__/groupMessages.test.ts +145 -2
- package/packages/database/src/utils/groupMessages.ts +7 -5
- package/packages/electron-client-ipc/package.json +4 -1
- package/packages/file-loaders/package.json +1 -0
- package/packages/model-bank/src/aiModels/anthropic.ts +0 -63
- package/packages/model-bank/src/aiModels/azure.ts +155 -0
- package/packages/model-bank/src/aiModels/bedrock.ts +44 -0
- package/packages/model-bank/src/aiModels/higress.ts +0 -55
- package/packages/model-bank/src/aiModels/infiniai.ts +21 -0
- package/packages/model-bank/src/aiModels/ollamacloud.ts +13 -0
- package/packages/model-bank/src/aiModels/siliconcloud.ts +19 -0
- package/packages/model-runtime/src/core/openaiCompatibleFactory/createImage.ts +1 -1
- package/packages/model-runtime/src/core/openaiCompatibleFactory/index.test.ts +33 -3
- package/packages/model-runtime/src/core/parameterResolver.ts +3 -0
- package/packages/model-runtime/src/core/streams/openai/__snapshots__/responsesStream.test.ts.snap +0 -38
- package/packages/model-runtime/src/providers/azureOpenai/index.ts +2 -1
- package/packages/model-runtime/src/providers/minimax/index.ts +5 -5
- package/packages/model-runtime/src/providers/search1api/index.test.ts +2 -2
- package/packages/types/src/message/common/base.ts +13 -0
- package/packages/types/src/message/common/image.ts +8 -0
- package/packages/types/src/message/common/metadata.ts +39 -0
- package/packages/types/src/message/common/tools.ts +10 -0
- package/packages/types/src/message/db/params.ts +47 -1
- package/packages/types/src/message/ui/chat.ts +4 -1
- package/packages/types/src/search.ts +16 -0
- package/packages/web-crawler/src/crawImpl/firecrawl.ts +39 -12
- package/scripts/migrateServerDB/index.ts +2 -1
- package/src/app/(backend)/oidc/consent/route.ts +0 -1
- package/src/app/(backend)/webapi/revalidate/route.ts +1 -1
- package/src/app/[variants]/(main)/chat/(workspace)/@conversation/features/ChatInput/V1Mobile/index.tsx +2 -2
- package/src/app/[variants]/(main)/chat/(workspace)/@conversation/features/ChatInput/V1Mobile/useSend.ts +6 -4
- package/src/app/[variants]/(main)/chat/(workspace)/@conversation/features/ChatInput/useSend.ts +15 -10
- package/src/app/[variants]/(main)/chat/@session/features/SessionListContent/List/Item/index.tsx +4 -2
- package/src/app/[variants]/(main)/settings/_layout/SettingsContent.tsx +0 -3
- package/src/app/[variants]/layout.tsx +1 -0
- package/src/app/sitemap.tsx +7 -1
- package/src/components/Thinking/index.tsx +4 -3
- package/src/config/modelProviders/anthropic.ts +0 -23
- package/src/config/modelProviders/higress.ts +0 -23
- package/src/config/modelProviders/minimax.ts +1 -1
- package/src/config/modelProviders/qiniu.ts +1 -1
- package/src/envs/auth.ts +0 -179
- package/src/features/AgentSetting/AgentPlugin/index.tsx +21 -13
- package/src/features/ChatInput/ActionBar/STT/browser.tsx +2 -2
- package/src/features/ChatInput/ActionBar/STT/openai.tsx +2 -2
- package/src/features/ChatInput/ActionBar/Tools/useControls.tsx +1 -3
- package/src/features/Conversation/Error/ErrorJsonViewer.tsx +4 -3
- package/src/features/Conversation/Error/OllamaBizError/index.tsx +7 -2
- package/src/features/Conversation/Error/index.tsx +15 -5
- package/src/features/Conversation/MarkdownElements/LobeArtifact/Render/index.tsx +2 -2
- package/src/features/Conversation/Messages/Assistant/Extra/index.tsx +2 -2
- package/src/features/Conversation/Messages/Assistant/MessageContent.tsx +5 -3
- package/src/features/Conversation/Messages/Assistant/Tool/Inspector/BuiltinPluginTitle.tsx +2 -2
- package/src/features/Conversation/Messages/Assistant/Tool/Inspector/ToolTitle.tsx +4 -2
- package/src/features/Conversation/Messages/Assistant/Tool/Render/CustomRender.tsx +2 -2
- package/src/features/Conversation/Messages/Assistant/Tool/Render/index.tsx +2 -2
- package/src/features/Conversation/Messages/Assistant/Tool/index.tsx +2 -2
- package/src/features/Conversation/Messages/Assistant/index.tsx +4 -4
- package/src/features/Conversation/Messages/Default.tsx +2 -2
- package/src/features/Conversation/Messages/User/Extra.tsx +2 -2
- package/src/features/Conversation/Messages/User/index.tsx +4 -4
- package/src/features/Conversation/Messages/index.tsx +3 -3
- package/src/features/Conversation/components/AutoScroll.tsx +2 -2
- package/src/features/Conversation/components/Extras/Usage/UsageDetail/index.tsx +9 -6
- package/src/features/PluginTag/index.tsx +1 -3
- package/src/features/PluginsUI/Render/BuiltinType/index.test.tsx +37 -28
- package/src/features/Portal/Artifacts/Body/index.tsx +2 -2
- package/src/libs/next-auth/auth.config.ts +1 -1
- package/src/libs/next-auth/sso-providers/auth0.ts +0 -7
- package/src/libs/next-auth/sso-providers/authelia.ts +3 -5
- package/src/libs/next-auth/sso-providers/authentik.ts +0 -7
- package/src/libs/next-auth/sso-providers/cloudflare-zero-trust.ts +3 -6
- package/src/libs/next-auth/sso-providers/cognito.ts +1 -5
- package/src/libs/next-auth/sso-providers/generic-oidc.ts +3 -5
- package/src/libs/next-auth/sso-providers/github.ts +0 -6
- package/src/libs/next-auth/sso-providers/google.ts +0 -2
- package/src/libs/next-auth/sso-providers/index.ts +0 -2
- package/src/libs/next-auth/sso-providers/keycloak.ts +0 -3
- package/src/libs/next-auth/sso-providers/logto.ts +3 -5
- package/src/libs/next-auth/sso-providers/okta.ts +0 -4
- package/src/libs/next-auth/sso-providers/zitadel.ts +0 -7
- package/src/libs/oidc-provider/provider.ts +1 -1
- package/src/server/modules/AssistantStore/index.ts +1 -1
- package/src/server/modules/ModelRuntime/trace.ts +11 -4
- package/src/server/routers/lambda/message.ts +14 -3
- package/src/server/routers/lambda/session.ts +8 -5
- package/src/server/services/search/impls/firecrawl/index.ts +51 -11
- package/src/server/services/search/impls/firecrawl/type.ts +60 -9
- package/src/services/chat/chat.test.ts +1 -40
- package/src/services/chat/contextEngineering.test.ts +0 -30
- package/src/services/chat/contextEngineering.ts +1 -12
- package/src/services/chat/index.ts +2 -7
- package/src/services/chat/types.ts +1 -1
- package/src/services/message/_deprecated.ts +1 -1
- package/src/services/message/client.ts +8 -2
- package/src/services/message/server.ts +7 -2
- package/src/services/message/type.ts +6 -1
- package/src/services/user/client.test.ts +4 -1
- package/src/store/chat/helpers.test.ts +99 -0
- package/src/store/chat/helpers.ts +21 -2
- package/src/store/chat/selectors.ts +1 -1
- package/src/store/chat/slices/aiChat/actions/generateAIChat.ts +3 -3
- package/src/store/chat/slices/builtinTool/actions/index.ts +1 -4
- package/src/store/chat/slices/message/action.test.ts +5 -1
- package/src/store/chat/slices/message/action.ts +102 -14
- package/src/store/chat/slices/message/reducer.test.ts +363 -5
- package/src/store/chat/slices/message/reducer.ts +87 -3
- package/src/store/chat/slices/message/{selectors.test.ts → selectors/chat.test.ts} +266 -30
- package/src/store/chat/slices/message/{selectors.ts → selectors/chat.ts} +29 -79
- package/src/store/chat/slices/message/selectors/index.ts +2 -0
- package/src/store/chat/slices/message/selectors/messageState.test.ts +36 -0
- package/src/store/chat/slices/message/selectors/messageState.ts +80 -0
- package/src/store/chat/slices/plugin/action.test.ts +34 -132
- package/src/store/chat/slices/plugin/action.ts +1 -44
- package/src/store/tool/selectors/tool.test.ts +1 -1
- package/src/store/tool/selectors/tool.ts +6 -8
- package/src/store/tool/slices/builtin/action.test.ts +83 -35
- package/src/store/tool/slices/builtin/action.ts +0 -9
- package/src/store/tool/slices/builtin/selectors.test.ts +4 -30
- package/src/store/tool/slices/builtin/selectors.ts +15 -21
- package/src/tools/index.ts +0 -6
- package/src/tools/renders.ts +0 -3
- package/src/tools/web-browsing/Portal/Search/Footer.tsx +2 -2
- package/tsconfig.json +9 -2
- package/packages/const/src/guide.ts +0 -89
- package/packages/context-engine/src/providers/InboxGuide.ts +0 -102
- package/packages/context-engine/src/providers/__tests__/InboxGuideProvider.test.ts +0 -121
- package/src/app/[variants]/(main)/settings/llm/ProviderList/Azure/index.tsx +0 -93
- package/src/app/[variants]/(main)/settings/llm/ProviderList/Bedrock/index.tsx +0 -70
- package/src/app/[variants]/(main)/settings/llm/ProviderList/Cloudflare/index.tsx +0 -39
- package/src/app/[variants]/(main)/settings/llm/ProviderList/Github/index.tsx +0 -52
- package/src/app/[variants]/(main)/settings/llm/ProviderList/HuggingFace/index.tsx +0 -52
- package/src/app/[variants]/(main)/settings/llm/ProviderList/Ollama/index.tsx +0 -20
- package/src/app/[variants]/(main)/settings/llm/ProviderList/OpenAI/index.tsx +0 -17
- package/src/app/[variants]/(main)/settings/llm/ProviderList/providers.tsx +0 -132
- package/src/app/[variants]/(main)/settings/llm/components/Checker.tsx +0 -118
- package/src/app/[variants]/(main)/settings/llm/components/ProviderConfig/index.tsx +0 -303
- package/src/app/[variants]/(main)/settings/llm/components/ProviderModelList/CustomModelOption.tsx +0 -98
- package/src/app/[variants]/(main)/settings/llm/components/ProviderModelList/ModelConfigModal/Form.tsx +0 -104
- package/src/app/[variants]/(main)/settings/llm/components/ProviderModelList/ModelConfigModal/index.tsx +0 -77
- package/src/app/[variants]/(main)/settings/llm/components/ProviderModelList/ModelFetcher.tsx +0 -105
- package/src/app/[variants]/(main)/settings/llm/components/ProviderModelList/Option.tsx +0 -68
- package/src/app/[variants]/(main)/settings/llm/components/ProviderModelList/index.tsx +0 -146
- package/src/app/[variants]/(main)/settings/llm/const.ts +0 -20
- package/src/app/[variants]/(main)/settings/llm/features/Footer.tsx +0 -35
- package/src/app/[variants]/(main)/settings/llm/index.tsx +0 -30
- package/src/app/[variants]/(main)/settings/llm/type.ts +0 -5
- package/src/envs/__tests__/auth.test.ts +0 -200
- package/src/libs/next-auth/sso-providers/azure-ad.ts +0 -33
- package/src/services/chat/__snapshots__/chat.test.ts.snap +0 -110
- package/src/store/chat/slices/builtinTool/actions/__tests__/dalle.test.ts +0 -121
- package/src/store/chat/slices/builtinTool/actions/dalle.ts +0 -124
- package/src/tools/dalle/Render/GalleyGrid.tsx +0 -60
- package/src/tools/dalle/Render/Item/EditMode.tsx +0 -66
- package/src/tools/dalle/Render/Item/Error.tsx +0 -49
- package/src/tools/dalle/Render/Item/Image.tsx +0 -44
- package/src/tools/dalle/Render/Item/ImageFileItem.tsx +0 -57
- package/src/tools/dalle/Render/Item/index.tsx +0 -88
- package/src/tools/dalle/Render/ToolBar.tsx +0 -56
- package/src/tools/dalle/Render/index.tsx +0 -52
- package/src/tools/dalle/index.ts +0 -92
- /package/src/{middleware.ts → proxy.ts} +0 -0
|
@@ -26,7 +26,7 @@ export class FirecrawlImpl implements SearchServiceImpl {
|
|
|
26
26
|
|
|
27
27
|
private get baseUrl(): string {
|
|
28
28
|
// Assuming the base URL is consistent with the crawl endpoint
|
|
29
|
-
return process.env.FIRECRAWL_URL || 'https://api.firecrawl.dev/
|
|
29
|
+
return process.env.FIRECRAWL_URL || 'https://api.firecrawl.dev/v2';
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
async query(query: string, params: SearchParams = {}): Promise<UniformSearchResponse> {
|
|
@@ -34,13 +34,14 @@ export class FirecrawlImpl implements SearchServiceImpl {
|
|
|
34
34
|
const endpoint = urlJoin(this.baseUrl, '/search');
|
|
35
35
|
|
|
36
36
|
const defaultQueryParams: FirecrawlSearchParameters = {
|
|
37
|
-
limit:
|
|
37
|
+
limit: 20,
|
|
38
38
|
query,
|
|
39
39
|
/*
|
|
40
40
|
scrapeOptions: {
|
|
41
41
|
formats: ["markdown"]
|
|
42
42
|
},
|
|
43
43
|
*/
|
|
44
|
+
sources: [{ type: 'web' }, { type: 'news' }],
|
|
44
45
|
};
|
|
45
46
|
|
|
46
47
|
let body: FirecrawlSearchParameters = {
|
|
@@ -95,25 +96,64 @@ export class FirecrawlImpl implements SearchServiceImpl {
|
|
|
95
96
|
|
|
96
97
|
log('Parsed Firecrawl response: %o', firecrawlResponse);
|
|
97
98
|
|
|
98
|
-
|
|
99
|
+
// V2 API returns data as object with web/images/news arrays
|
|
100
|
+
const webResults = firecrawlResponse.data.web || [];
|
|
101
|
+
const imageResults = firecrawlResponse.data.images || [];
|
|
102
|
+
const newsResults = firecrawlResponse.data.news || [];
|
|
103
|
+
|
|
104
|
+
// Map web results
|
|
105
|
+
const mappedWebResults = webResults.map(
|
|
106
|
+
(result): UniformSearchResult => ({
|
|
107
|
+
category: 'general',
|
|
108
|
+
content: result.description || result.markdown || '',
|
|
109
|
+
engines: ['firecrawl'],
|
|
110
|
+
parsedUrl: result.url ? new URL(result.url).hostname : '',
|
|
111
|
+
score: 1,
|
|
112
|
+
title: result.title || '',
|
|
113
|
+
url: result.url,
|
|
114
|
+
}),
|
|
115
|
+
);
|
|
116
|
+
|
|
117
|
+
// Map news results
|
|
118
|
+
const mappedNewsResults = newsResults.map(
|
|
99
119
|
(result): UniformSearchResult => ({
|
|
100
|
-
category: '
|
|
101
|
-
content: result.
|
|
102
|
-
engines: ['firecrawl'],
|
|
103
|
-
parsedUrl: result.url ? new URL(result.url).hostname : '',
|
|
104
|
-
score: 1,
|
|
120
|
+
category: 'news',
|
|
121
|
+
content: result.snippet || result.markdown || '',
|
|
122
|
+
engines: ['firecrawl'],
|
|
123
|
+
parsedUrl: result.url ? new URL(result.url).hostname : '',
|
|
124
|
+
score: 1,
|
|
105
125
|
title: result.title || '',
|
|
106
126
|
url: result.url,
|
|
107
127
|
}),
|
|
108
128
|
);
|
|
109
129
|
|
|
110
|
-
|
|
130
|
+
// Map image results
|
|
131
|
+
const mappedImageResults = imageResults.map(
|
|
132
|
+
(result): UniformSearchResult => ({
|
|
133
|
+
category: 'images',
|
|
134
|
+
content: result.title || '',
|
|
135
|
+
engines: ['firecrawl'],
|
|
136
|
+
parsedUrl: result.url ? new URL(result.url).hostname : '',
|
|
137
|
+
score: 1,
|
|
138
|
+
title: result.title || '',
|
|
139
|
+
url: result.imageUrl, // Use imageUrl for images
|
|
140
|
+
}),
|
|
141
|
+
);
|
|
142
|
+
|
|
143
|
+
// Combine all results
|
|
144
|
+
const allResults = [...mappedWebResults, ...mappedNewsResults, ...mappedImageResults];
|
|
145
|
+
|
|
146
|
+
log('Mapped %d results to SearchResult format', allResults.length);
|
|
147
|
+
|
|
148
|
+
if (firecrawlResponse.warning) {
|
|
149
|
+
log.extend('warn')('Firecrawl warning: %s', firecrawlResponse.warning);
|
|
150
|
+
}
|
|
111
151
|
|
|
112
152
|
return {
|
|
113
153
|
costTime,
|
|
114
154
|
query: query,
|
|
115
|
-
resultNumbers:
|
|
116
|
-
results:
|
|
155
|
+
resultNumbers: allResults.length,
|
|
156
|
+
results: allResults,
|
|
117
157
|
};
|
|
118
158
|
} catch (error) {
|
|
119
159
|
log.extend('error')('Error parsing Firecrawl response: %o', error);
|
|
@@ -1,35 +1,86 @@
|
|
|
1
|
+
// V2 API Types
|
|
1
2
|
interface FirecrawlScrapeOptions {
|
|
2
|
-
|
|
3
|
+
blockAds?: boolean;
|
|
4
|
+
formats?: string[];
|
|
5
|
+
maxAge?: number;
|
|
6
|
+
onlyMainContent?: boolean;
|
|
7
|
+
removeBase64Images?: boolean;
|
|
3
8
|
}
|
|
4
9
|
|
|
10
|
+
type FirecrawlSource =
|
|
11
|
+
| { location?: string; tbs?: string; type: 'web' }
|
|
12
|
+
| { type: 'images' }
|
|
13
|
+
| { type: 'news' };
|
|
14
|
+
|
|
15
|
+
type FirecrawlCategory = { type: 'github' } | { type: 'research' } | { type: 'pdf' };
|
|
16
|
+
|
|
5
17
|
export interface FirecrawlSearchParameters {
|
|
18
|
+
categories?: FirecrawlCategory[];
|
|
6
19
|
country?: string;
|
|
7
|
-
|
|
20
|
+
ignoreInvalidURLs?: boolean;
|
|
8
21
|
limit?: number;
|
|
22
|
+
location?: string;
|
|
9
23
|
query: string;
|
|
10
24
|
scrapeOptions?: FirecrawlScrapeOptions;
|
|
25
|
+
sources?: FirecrawlSource[];
|
|
11
26
|
tbs?: string;
|
|
12
27
|
timeout?: number;
|
|
13
28
|
}
|
|
14
29
|
|
|
15
30
|
interface FirecrawlMetadata {
|
|
16
31
|
description?: string;
|
|
32
|
+
error?: string | null;
|
|
17
33
|
sourceURL?: string;
|
|
18
34
|
statusCode?: number;
|
|
35
|
+
title?: string;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Web search result
|
|
39
|
+
interface FirecrawlWebResult {
|
|
40
|
+
description: string;
|
|
41
|
+
html?: string | null;
|
|
42
|
+
links?: string[];
|
|
43
|
+
markdown?: string | null;
|
|
44
|
+
metadata?: FirecrawlMetadata;
|
|
45
|
+
rawHtml?: string | null;
|
|
46
|
+
screenshot?: string | null;
|
|
19
47
|
title: string;
|
|
48
|
+
url: string;
|
|
20
49
|
}
|
|
21
50
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
51
|
+
// Image search result
|
|
52
|
+
interface FirecrawlImageResult {
|
|
53
|
+
imageHeight: number;
|
|
54
|
+
imageUrl: string;
|
|
55
|
+
imageWidth: number;
|
|
56
|
+
position: number;
|
|
57
|
+
title: string;
|
|
58
|
+
url: string;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// News search result
|
|
62
|
+
interface FirecrawlNewsResult {
|
|
63
|
+
date: string;
|
|
64
|
+
html?: string | null;
|
|
65
|
+
imageUrl?: string;
|
|
25
66
|
links?: string[];
|
|
26
|
-
markdown?: string;
|
|
67
|
+
markdown?: string | null;
|
|
27
68
|
metadata?: FirecrawlMetadata;
|
|
28
|
-
|
|
69
|
+
position: number;
|
|
70
|
+
rawHtml?: string | null;
|
|
71
|
+
screenshot?: string | null;
|
|
72
|
+
snippet: string;
|
|
73
|
+
title: string;
|
|
29
74
|
url: string;
|
|
30
75
|
}
|
|
31
76
|
|
|
77
|
+
// V2 Response structure
|
|
32
78
|
export interface FirecrawlResponse {
|
|
33
|
-
data:
|
|
34
|
-
|
|
79
|
+
data: {
|
|
80
|
+
images?: FirecrawlImageResult[];
|
|
81
|
+
news?: FirecrawlNewsResult[];
|
|
82
|
+
web?: FirecrawlWebResult[];
|
|
83
|
+
};
|
|
84
|
+
success: boolean;
|
|
85
|
+
warning?: string | null;
|
|
35
86
|
}
|
|
@@ -8,18 +8,12 @@ import { type Mock, afterEach, beforeEach, describe, expect, it, vi } from 'vite
|
|
|
8
8
|
|
|
9
9
|
import { DEFAULT_USER_AVATAR } from '@/const/meta';
|
|
10
10
|
import { DEFAULT_AGENT_CONFIG } from '@/const/settings';
|
|
11
|
-
import * as isCanUseFCModule from '@/helpers/isCanUseFC';
|
|
12
11
|
import * as toolEngineeringModule from '@/helpers/toolEngineering';
|
|
13
|
-
import { agentChatConfigSelectors
|
|
12
|
+
import { agentChatConfigSelectors } from '@/store/agent/selectors';
|
|
14
13
|
import { aiModelSelectors } from '@/store/aiInfra';
|
|
15
14
|
import { useToolStore } from '@/store/tool';
|
|
16
|
-
import { toolSelectors } from '@/store/tool/selectors';
|
|
17
|
-
import { modelProviderSelectors } from '@/store/user/selectors';
|
|
18
|
-
import { DalleManifest } from '@/tools/dalle';
|
|
19
15
|
import { WebBrowsingManifest } from '@/tools/web-browsing';
|
|
20
16
|
|
|
21
|
-
import { API_ENDPOINTS } from '../_url';
|
|
22
|
-
import * as helpers from './helper';
|
|
23
17
|
import { chatService } from './index';
|
|
24
18
|
|
|
25
19
|
// Mocking external dependencies
|
|
@@ -831,39 +825,6 @@ describe('ChatService', () => {
|
|
|
831
825
|
undefined,
|
|
832
826
|
);
|
|
833
827
|
});
|
|
834
|
-
|
|
835
|
-
it('work with dalle3', async () => {
|
|
836
|
-
const getChatCompletionSpy = vi.spyOn(chatService, 'getChatCompletion');
|
|
837
|
-
const messages = [
|
|
838
|
-
{
|
|
839
|
-
role: 'user',
|
|
840
|
-
content: 'https://vercel.com/ 请分析 chatGPT 关键词\n\n',
|
|
841
|
-
sessionId: 'inbox',
|
|
842
|
-
createdAt: 1702723964330,
|
|
843
|
-
id: 'vyQvEw6V',
|
|
844
|
-
updatedAt: 1702723964330,
|
|
845
|
-
extra: {},
|
|
846
|
-
meta: {
|
|
847
|
-
avatar: DEFAULT_USER_AVATAR,
|
|
848
|
-
},
|
|
849
|
-
},
|
|
850
|
-
] as UIChatMessage[];
|
|
851
|
-
|
|
852
|
-
await chatService.createAssistantMessage({
|
|
853
|
-
messages,
|
|
854
|
-
model: 'gpt-3.5-turbo-1106',
|
|
855
|
-
top_p: 1,
|
|
856
|
-
plugins: [DalleManifest.identifier],
|
|
857
|
-
});
|
|
858
|
-
|
|
859
|
-
// Assert that getChatCompletionSpy was called with the expected arguments
|
|
860
|
-
expect(getChatCompletionSpy).toHaveBeenCalled();
|
|
861
|
-
|
|
862
|
-
const calls = getChatCompletionSpy.mock.lastCall;
|
|
863
|
-
// Take a snapshot of the first call's first argument
|
|
864
|
-
expect(calls![0]).toMatchSnapshot();
|
|
865
|
-
expect(calls![1]).toBeUndefined();
|
|
866
|
-
});
|
|
867
828
|
});
|
|
868
829
|
|
|
869
830
|
describe('search functionality', () => {
|
|
@@ -248,36 +248,6 @@ describe('contextEngineering', () => {
|
|
|
248
248
|
]);
|
|
249
249
|
});
|
|
250
250
|
|
|
251
|
-
it('should inject INBOX_GUIDE_SYSTEM_ROLE for welcome questions in inbox session', async () => {
|
|
252
|
-
// Don't mock INBOX_GUIDE_SYSTEMROLE, use the real one
|
|
253
|
-
const messages: UIChatMessage[] = [
|
|
254
|
-
{
|
|
255
|
-
role: 'user',
|
|
256
|
-
content: 'Hello, this is my first question',
|
|
257
|
-
createdAt: Date.now(),
|
|
258
|
-
id: 'test-welcome',
|
|
259
|
-
meta: {},
|
|
260
|
-
updatedAt: Date.now(),
|
|
261
|
-
},
|
|
262
|
-
];
|
|
263
|
-
|
|
264
|
-
const result = await contextEngineering({
|
|
265
|
-
messages,
|
|
266
|
-
model: 'gpt-4',
|
|
267
|
-
provider: 'openai',
|
|
268
|
-
isWelcomeQuestion: true,
|
|
269
|
-
sessionId: 'inbox',
|
|
270
|
-
});
|
|
271
|
-
|
|
272
|
-
// Should have system message with inbox guide content
|
|
273
|
-
const systemMessage = result.find((msg) => msg.role === 'system');
|
|
274
|
-
expect(systemMessage).toBeDefined();
|
|
275
|
-
// Check for characteristic content of the actual INBOX_GUIDE_SYSTEMROLE
|
|
276
|
-
expect(systemMessage!.content).toContain('LobeChat Support Assistant');
|
|
277
|
-
expect(systemMessage!.content).toContain('LobeHub');
|
|
278
|
-
expect(Object.keys(systemMessage!).length).toEqual(2);
|
|
279
|
-
});
|
|
280
|
-
|
|
281
251
|
it('should inject historySummary into system message when provided', async () => {
|
|
282
252
|
const historySummary = 'Previous conversation summary: User discussed AI topics.';
|
|
283
253
|
|
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { isDesktop, isServerMode } from '@lobechat/const';
|
|
2
2
|
import {
|
|
3
3
|
ContextEngine,
|
|
4
4
|
HistorySummaryProvider,
|
|
5
5
|
HistoryTruncateProcessor,
|
|
6
|
-
InboxGuideProvider,
|
|
7
6
|
InputTemplateProcessor,
|
|
8
7
|
MessageCleanupProcessor,
|
|
9
8
|
MessageContentProcessor,
|
|
@@ -48,8 +47,6 @@ export const contextEngineering = async ({
|
|
|
48
47
|
enableHistoryCount,
|
|
49
48
|
historyCount,
|
|
50
49
|
historySummary,
|
|
51
|
-
sessionId,
|
|
52
|
-
isWelcomeQuestion,
|
|
53
50
|
}: ContextEngineeringContext): Promise<OpenAIChatMessage[]> => {
|
|
54
51
|
const toolNameResolver = new ToolNameResolver();
|
|
55
52
|
|
|
@@ -63,14 +60,6 @@ export const contextEngineering = async ({
|
|
|
63
60
|
// 2. System role injection (agent's system role)
|
|
64
61
|
new SystemRoleInjector({ systemRole }),
|
|
65
62
|
|
|
66
|
-
// 3. Inbox guide system role injection
|
|
67
|
-
new InboxGuideProvider({
|
|
68
|
-
inboxGuideSystemRole: INBOX_GUIDE_SYSTEMROLE,
|
|
69
|
-
inboxSessionId: INBOX_SESSION_ID,
|
|
70
|
-
isWelcomeQuestion: isWelcomeQuestion,
|
|
71
|
-
sessionId: sessionId,
|
|
72
|
-
}),
|
|
73
|
-
|
|
74
63
|
// 4. Tool system role injection
|
|
75
64
|
new ToolSystemRoleProvider({
|
|
76
65
|
getToolSystemRoles: (tools) => toolSelectors.enabledSystemRoles(tools)(getToolStoreState()),
|
|
@@ -66,7 +66,6 @@ interface FetchAITaskResultParams extends FetchSSEOptions {
|
|
|
66
66
|
interface CreateAssistantMessageStream extends FetchSSEOptions {
|
|
67
67
|
abortController?: AbortController;
|
|
68
68
|
historySummary?: string;
|
|
69
|
-
isWelcomeQuestion?: boolean;
|
|
70
69
|
params: GetChatCompletionPayload;
|
|
71
70
|
trace?: TracePayload;
|
|
72
71
|
}
|
|
@@ -113,9 +112,7 @@ class ChatService {
|
|
|
113
112
|
enableHistoryCount: agentChatConfigSelectors.enableHistoryCount(agentStoreState),
|
|
114
113
|
// include user messages
|
|
115
114
|
historyCount: agentChatConfigSelectors.historyCount(agentStoreState) + 2,
|
|
116
|
-
historySummary: options?.historySummary,
|
|
117
115
|
inputTemplate: chatConfig.inputTemplate,
|
|
118
|
-
isWelcomeQuestion: options?.isWelcomeQuestion,
|
|
119
116
|
messages,
|
|
120
117
|
model: payload.model,
|
|
121
118
|
provider: payload.provider!,
|
|
@@ -217,12 +214,10 @@ class ChatService {
|
|
|
217
214
|
onErrorHandle,
|
|
218
215
|
onFinish,
|
|
219
216
|
trace,
|
|
220
|
-
isWelcomeQuestion,
|
|
221
217
|
historySummary,
|
|
222
218
|
}: CreateAssistantMessageStream) => {
|
|
223
219
|
await this.createAssistantMessage(params, {
|
|
224
220
|
historySummary,
|
|
225
|
-
isWelcomeQuestion,
|
|
226
221
|
onAbort,
|
|
227
222
|
onErrorHandle,
|
|
228
223
|
onFinish,
|
|
@@ -404,7 +399,7 @@ class ChatService {
|
|
|
404
399
|
onLoadingChange?.(true);
|
|
405
400
|
|
|
406
401
|
try {
|
|
407
|
-
const
|
|
402
|
+
const llmMessages = await contextEngineering({
|
|
408
403
|
messages: params.messages as any,
|
|
409
404
|
model: params.model!,
|
|
410
405
|
provider: params.provider!,
|
|
@@ -421,7 +416,7 @@ class ChatService {
|
|
|
421
416
|
// remove plugins
|
|
422
417
|
delete params.plugins;
|
|
423
418
|
await this.getChatCompletion(
|
|
424
|
-
{ ...params, messages:
|
|
419
|
+
{ ...params, messages: llmMessages, tools },
|
|
425
420
|
{
|
|
426
421
|
onErrorHandle: (error) => {
|
|
427
422
|
errorHandle(new Error(error.message), error);
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { TracePayload } from '@lobechat/types';
|
|
2
|
+
|
|
2
3
|
import { FetchSSEOptions } from '@/utils/fetch';
|
|
3
4
|
|
|
4
5
|
export interface FetchOptions extends FetchSSEOptions {
|
|
5
6
|
historySummary?: string;
|
|
6
|
-
isWelcomeQuestion?: boolean;
|
|
7
7
|
signal?: AbortSignal | undefined;
|
|
8
8
|
trace?: TracePayload;
|
|
9
9
|
}
|
|
@@ -102,7 +102,7 @@ export class ClientService implements IMessageService {
|
|
|
102
102
|
}
|
|
103
103
|
|
|
104
104
|
// @ts-ignore
|
|
105
|
-
async updateMessage(id: string, message: Partial<DB_Message>) {
|
|
105
|
+
async updateMessage(id: string, message: Partial<DB_Message>): Promise<any> {
|
|
106
106
|
return MessageModel.update(id, message);
|
|
107
107
|
}
|
|
108
108
|
|
|
@@ -45,6 +45,7 @@ export class ClientService extends BaseClientService implements IMessageService
|
|
|
45
45
|
topicId,
|
|
46
46
|
},
|
|
47
47
|
{
|
|
48
|
+
groupAssistantMessages: false,
|
|
48
49
|
postProcessUrl: this.postProcessUrl,
|
|
49
50
|
},
|
|
50
51
|
);
|
|
@@ -60,6 +61,7 @@ export class ClientService extends BaseClientService implements IMessageService
|
|
|
60
61
|
topicId,
|
|
61
62
|
},
|
|
62
63
|
{
|
|
64
|
+
groupAssistantMessages: false,
|
|
63
65
|
postProcessUrl: this.postProcessUrl,
|
|
64
66
|
},
|
|
65
67
|
);
|
|
@@ -99,8 +101,12 @@ export class ClientService extends BaseClientService implements IMessageService
|
|
|
99
101
|
return this.messageModel.update(id, { error });
|
|
100
102
|
};
|
|
101
103
|
|
|
102
|
-
updateMessage: IMessageService['updateMessage'] = async (id, message) => {
|
|
103
|
-
return this.messageModel.update(id, message
|
|
104
|
+
updateMessage: IMessageService['updateMessage'] = async (id, message, options) => {
|
|
105
|
+
return this.messageModel.update(id, message, {
|
|
106
|
+
postProcessUrl: this.postProcessUrl,
|
|
107
|
+
sessionId: options?.sessionId,
|
|
108
|
+
topicId: options?.topicId,
|
|
109
|
+
});
|
|
104
110
|
};
|
|
105
111
|
|
|
106
112
|
updateMessageTTS: IMessageService['updateMessageTTS'] = async (id, tts) => {
|
|
@@ -81,8 +81,13 @@ export class ServerService implements IMessageService {
|
|
|
81
81
|
return lambdaClient.message.updateMessagePlugin.mutate({ id, value: { arguments: args } });
|
|
82
82
|
};
|
|
83
83
|
|
|
84
|
-
updateMessage: IMessageService['updateMessage'] = async (id, value) => {
|
|
85
|
-
return lambdaClient.message.update.mutate({
|
|
84
|
+
updateMessage: IMessageService['updateMessage'] = async (id, value, options) => {
|
|
85
|
+
return lambdaClient.message.update.mutate({
|
|
86
|
+
id,
|
|
87
|
+
sessionId: options?.sessionId,
|
|
88
|
+
topicId: options?.topicId,
|
|
89
|
+
value,
|
|
90
|
+
});
|
|
86
91
|
};
|
|
87
92
|
|
|
88
93
|
updateMessageTranslate: IMessageService['updateMessageTranslate'] = async (id, translate) => {
|
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
UIChatMessage,
|
|
11
11
|
UpdateMessageParams,
|
|
12
12
|
UpdateMessageRAGParams,
|
|
13
|
+
UpdateMessageResult,
|
|
13
14
|
} from '@lobechat/types';
|
|
14
15
|
import type { HeatmapsProps } from '@lobehub/charts';
|
|
15
16
|
|
|
@@ -37,7 +38,11 @@ export interface IMessageService {
|
|
|
37
38
|
rankModels(): Promise<ModelRankItem[]>;
|
|
38
39
|
getHeatmaps(): Promise<HeatmapsProps['data']>;
|
|
39
40
|
updateMessageError(id: string, error: ChatMessageError): Promise<any>;
|
|
40
|
-
updateMessage(
|
|
41
|
+
updateMessage(
|
|
42
|
+
id: string,
|
|
43
|
+
message: Partial<UpdateMessageParams>,
|
|
44
|
+
options?: { sessionId?: string | null; topicId?: string | null },
|
|
45
|
+
): Promise<UpdateMessageResult>;
|
|
41
46
|
updateMessageTTS(id: string, tts: Partial<ChatTTS> | false): Promise<any>;
|
|
42
47
|
updateMessageTranslate(id: string, translate: Partial<ChatTranslate> | false): Promise<any>;
|
|
43
48
|
updateMessagePluginState(id: string, value: Record<string, any>): Promise<any>;
|
|
@@ -26,7 +26,10 @@ beforeEach(async () => {
|
|
|
26
26
|
await initializeDB();
|
|
27
27
|
await clientDB.delete(users);
|
|
28
28
|
|
|
29
|
-
await clientDB
|
|
29
|
+
await clientDB
|
|
30
|
+
.insert(users)
|
|
31
|
+
.values({ id: mockUser.uuid, avatar: 'avatar.png' })
|
|
32
|
+
.onConflictDoNothing();
|
|
30
33
|
await clientDB
|
|
31
34
|
.insert(userSettings)
|
|
32
35
|
.values({ id: mockUser.uuid, general: { themeMode: 'light' } });
|
|
@@ -64,6 +64,105 @@ describe('chatHelpers', () => {
|
|
|
64
64
|
const message = chatHelpers.getMessageById([], '1');
|
|
65
65
|
expect(message).toBeUndefined();
|
|
66
66
|
});
|
|
67
|
+
|
|
68
|
+
it('finds a block within a group message', () => {
|
|
69
|
+
const messagesWithGroup = [
|
|
70
|
+
{ id: '1', content: 'Hello' },
|
|
71
|
+
{
|
|
72
|
+
id: 'group1',
|
|
73
|
+
role: 'group',
|
|
74
|
+
content: '',
|
|
75
|
+
children: [
|
|
76
|
+
{ id: 'block1', content: 'First block' },
|
|
77
|
+
{ id: 'block2', content: 'Second block' },
|
|
78
|
+
],
|
|
79
|
+
},
|
|
80
|
+
] as UIChatMessage[];
|
|
81
|
+
|
|
82
|
+
const block = chatHelpers.getMessageById(messagesWithGroup, 'block1');
|
|
83
|
+
expect(block).toBeDefined();
|
|
84
|
+
expect(block?.id).toBe('block1');
|
|
85
|
+
expect(block?.content).toBe('First block');
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
it('returns block with parentId set to group message id', () => {
|
|
89
|
+
const messagesWithGroup = [
|
|
90
|
+
{
|
|
91
|
+
id: 'group1',
|
|
92
|
+
role: 'group',
|
|
93
|
+
content: '',
|
|
94
|
+
children: [{ id: 'block1', content: 'Block content' }],
|
|
95
|
+
},
|
|
96
|
+
] as UIChatMessage[];
|
|
97
|
+
|
|
98
|
+
const block = chatHelpers.getMessageById(messagesWithGroup, 'block1');
|
|
99
|
+
expect(block).toBeDefined();
|
|
100
|
+
expect(block?.parentId).toBe('group1');
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
it('searches across multiple group messages', () => {
|
|
104
|
+
const messagesWithGroups = [
|
|
105
|
+
{
|
|
106
|
+
id: 'group1',
|
|
107
|
+
role: 'group',
|
|
108
|
+
content: '',
|
|
109
|
+
children: [{ id: 'block1', content: 'First group block' }],
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
id: 'group2',
|
|
113
|
+
role: 'group',
|
|
114
|
+
content: '',
|
|
115
|
+
children: [{ id: 'block2', content: 'Second group block' }],
|
|
116
|
+
},
|
|
117
|
+
] as UIChatMessage[];
|
|
118
|
+
|
|
119
|
+
const block = chatHelpers.getMessageById(messagesWithGroups, 'block2');
|
|
120
|
+
expect(block).toBeDefined();
|
|
121
|
+
expect(block?.id).toBe('block2');
|
|
122
|
+
expect(block?.parentId).toBe('group2');
|
|
123
|
+
expect(block?.content).toBe('Second group block');
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
it('prioritizes top-level message over block with same id', () => {
|
|
127
|
+
const messagesWithConflict = [
|
|
128
|
+
{ id: 'duplicate', content: 'Top-level message', role: 'user' },
|
|
129
|
+
{
|
|
130
|
+
id: 'group1',
|
|
131
|
+
role: 'group',
|
|
132
|
+
content: '',
|
|
133
|
+
children: [{ id: 'duplicate', content: 'Block message' }],
|
|
134
|
+
},
|
|
135
|
+
] as UIChatMessage[];
|
|
136
|
+
|
|
137
|
+
const message = chatHelpers.getMessageById(messagesWithConflict, 'duplicate');
|
|
138
|
+
expect(message).toBeDefined();
|
|
139
|
+
expect(message?.content).toBe('Top-level message');
|
|
140
|
+
expect(message?.role).toBe('user');
|
|
141
|
+
expect(message?.parentId).toBeUndefined();
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
it('returns undefined when block is not found in any group', () => {
|
|
145
|
+
const messagesWithGroup = [
|
|
146
|
+
{
|
|
147
|
+
id: 'group1',
|
|
148
|
+
role: 'group',
|
|
149
|
+
content: '',
|
|
150
|
+
children: [{ id: 'block1', content: 'Block content' }],
|
|
151
|
+
},
|
|
152
|
+
] as UIChatMessage[];
|
|
153
|
+
|
|
154
|
+
const block = chatHelpers.getMessageById(messagesWithGroup, 'nonexistent');
|
|
155
|
+
expect(block).toBeUndefined();
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
it('handles group message without children', () => {
|
|
159
|
+
const messagesWithEmptyGroup = [
|
|
160
|
+
{ id: 'group1', role: 'group', content: '' },
|
|
161
|
+
] as UIChatMessage[];
|
|
162
|
+
|
|
163
|
+
const block = chatHelpers.getMessageById(messagesWithEmptyGroup, 'block1');
|
|
164
|
+
expect(block).toBeUndefined();
|
|
165
|
+
});
|
|
67
166
|
});
|
|
68
167
|
|
|
69
168
|
describe('getSlicedMessages', () => {
|
|
@@ -5,8 +5,27 @@ import { encodeAsync } from '@/utils/tokenizer';
|
|
|
5
5
|
export const getMessagesTokenCount = async (messages: OpenAIChatMessage[]) =>
|
|
6
6
|
encodeAsync(messages.map((m) => m.content).join(''));
|
|
7
7
|
|
|
8
|
-
export const getMessageById = (
|
|
9
|
-
messages
|
|
8
|
+
export const getMessageById = (
|
|
9
|
+
messages: UIChatMessage[],
|
|
10
|
+
id: string,
|
|
11
|
+
): UIChatMessage | undefined => {
|
|
12
|
+
// First try to find in top-level messages
|
|
13
|
+
const directMatch = messages.find((m) => m.id === id);
|
|
14
|
+
if (directMatch) return directMatch;
|
|
15
|
+
|
|
16
|
+
// If not found, search in group message children (blocks)
|
|
17
|
+
for (const message of messages) {
|
|
18
|
+
if (message.role === 'group' && message.children) {
|
|
19
|
+
const blockMatch = message.children.find((block) => block.id === id);
|
|
20
|
+
if (blockMatch) {
|
|
21
|
+
// Return the block with parentId set to group message ID
|
|
22
|
+
return { ...blockMatch, parentId: message.id } as UIChatMessage;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return undefined;
|
|
28
|
+
};
|
|
10
29
|
|
|
11
30
|
const getSlicedMessages = (
|
|
12
31
|
messages: UIChatMessage[],
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { aiChatSelectors } from './slices/aiChat/selectors';
|
|
2
2
|
export { chatToolSelectors } from './slices/builtinTool/selectors';
|
|
3
|
-
export
|
|
3
|
+
export * from './slices/message/selectors';
|
|
4
4
|
export * from './slices/portal/selectors';
|
|
5
5
|
export { threadSelectors } from './slices/thread/selectors';
|
|
6
6
|
export { topicSelectors } from './slices/topic/selectors';
|
|
@@ -29,7 +29,7 @@ import { useSessionStore } from '@/store/session';
|
|
|
29
29
|
import { WebBrowsingManifest } from '@/tools/web-browsing';
|
|
30
30
|
import { Action, setNamespace } from '@/utils/storeDebug';
|
|
31
31
|
|
|
32
|
-
import { chatSelectors, topicSelectors } from '../../../selectors';
|
|
32
|
+
import { chatSelectors, messageStateSelectors, topicSelectors } from '../../../selectors';
|
|
33
33
|
|
|
34
34
|
const n = setNamespace('ai');
|
|
35
35
|
|
|
@@ -598,7 +598,6 @@ export const generateAIChat: StateCreator<
|
|
|
598
598
|
topicId: get().activeTopicId,
|
|
599
599
|
traceName: TraceNameMap.Conversation,
|
|
600
600
|
},
|
|
601
|
-
isWelcomeQuestion: params?.isWelcomeQuestion,
|
|
602
601
|
onErrorHandle: async (error) => {
|
|
603
602
|
await messageService.updateMessageError(messageId, error);
|
|
604
603
|
await refreshMessages();
|
|
@@ -707,7 +706,8 @@ export const generateAIChat: StateCreator<
|
|
|
707
706
|
if (!duration) {
|
|
708
707
|
duration = Date.now() - thinkingStartAt;
|
|
709
708
|
|
|
710
|
-
const isInChatReasoning =
|
|
709
|
+
const isInChatReasoning =
|
|
710
|
+
messageStateSelectors.isMessageInChatReasoning(messageId)(get());
|
|
711
711
|
if (isInChatReasoning) {
|
|
712
712
|
internal_toggleChatReasoning(
|
|
713
713
|
false,
|
|
@@ -2,14 +2,12 @@ import { StateCreator } from 'zustand/vanilla';
|
|
|
2
2
|
|
|
3
3
|
import { ChatStore } from '@/store/chat/store';
|
|
4
4
|
|
|
5
|
-
import { ChatDallEAction, dalleSlice } from './dalle';
|
|
6
5
|
import { ChatCodeInterpreterAction, codeInterpreterSlice } from './interpreter';
|
|
7
6
|
import { LocalFileAction, localSystemSlice } from './localSystem';
|
|
8
7
|
import { SearchAction, searchSlice } from './search';
|
|
9
8
|
|
|
10
9
|
export interface ChatBuiltinToolAction
|
|
11
|
-
extends
|
|
12
|
-
SearchAction,
|
|
10
|
+
extends SearchAction,
|
|
13
11
|
LocalFileAction,
|
|
14
12
|
ChatCodeInterpreterAction {}
|
|
15
13
|
|
|
@@ -19,7 +17,6 @@ export const chatToolSlice: StateCreator<
|
|
|
19
17
|
[],
|
|
20
18
|
ChatBuiltinToolAction
|
|
21
19
|
> = (...params) => ({
|
|
22
|
-
...dalleSlice(...params),
|
|
23
20
|
...searchSlice(...params),
|
|
24
21
|
...localSystemSlice(...params),
|
|
25
22
|
...codeInterpreterSlice(...params),
|