@lobehub/lobehub 2.0.0-next.293 → 2.0.0-next.295
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/release-desktop-beta.yml +6 -6
- package/.github/workflows/release-desktop-stable.yml +11 -11
- package/CHANGELOG.md +52 -0
- package/apps/desktop/electron.vite.config.ts +0 -1
- package/apps/desktop/src/main/__mocks__/node-mac-permissions.ts +0 -1
- package/apps/desktop/src/main/__mocks__/setup.ts +0 -1
- package/apps/desktop/src/main/controllers/McpCtr.ts +50 -18
- package/apps/desktop/src/main/controllers/__tests__/SystemCtr.test.ts +1 -4
- package/apps/desktop/src/main/libs/mcp/client.ts +54 -2
- package/apps/desktop/tsconfig.json +4 -10
- package/changelog/v1.json +14 -0
- package/e2e/scripts/setup.ts +45 -32
- package/package.json +1 -1
- package/packages/database/src/models/__tests__/knowledgeBase.test.ts +1 -1
- package/packages/database/src/repositories/knowledge/index.ts +1 -4
- package/packages/types/src/discover/assistants.ts +2 -2
- package/scripts/migrate-spa-navigation.ts +129 -0
- package/src/app/(backend)/api/workflows/memory-user-memory/pipelines/chat-topic/process-topics/route.ts +112 -109
- package/src/app/(backend)/api/workflows/memory-user-memory/pipelines/chat-topic/process-user-topics/route.ts +125 -113
- package/src/app/(backend)/api/workflows/memory-user-memory/pipelines/chat-topic/process-users/route.ts +74 -65
- package/src/app/[variants]/(auth)/auth-error/page.tsx +1 -1
- package/src/app/[variants]/(auth)/login/[[...login]]/page.tsx +1 -1
- package/src/app/[variants]/(auth)/next-auth/error/AuthErrorPage.tsx +1 -1
- package/src/app/[variants]/(auth)/next-auth/signin/AuthSignInBox.tsx +1 -1
- package/src/app/[variants]/(auth)/oauth/callback/error/page.tsx +1 -1
- package/src/app/[variants]/(auth)/oauth/callback/success/page.tsx +1 -1
- package/src/app/[variants]/(auth)/oauth/consent/[uid]/page.tsx +1 -1
- package/src/app/[variants]/(auth)/reset-password/layout.tsx +1 -1
- package/src/app/[variants]/(auth)/reset-password/page.tsx +2 -2
- package/src/app/[variants]/(auth)/signin/layout.tsx +1 -1
- package/src/app/[variants]/(auth)/signin/useSignIn.ts +1 -1
- package/src/app/[variants]/(auth)/signup/[[...signup]]/BetterAuthSignUpForm.tsx +2 -2
- package/src/app/[variants]/(auth)/signup/[[...signup]]/page.tsx +1 -1
- package/src/app/[variants]/(auth)/signup/[[...signup]]/useSignUp.tsx +1 -1
- package/src/app/[variants]/(auth)/verify-email/layout.tsx +1 -1
- package/src/app/[variants]/(auth)/verify-email/page.tsx +2 -2
- package/src/app/[variants]/(main)/_layout/index.tsx +1 -1
- package/src/app/[variants]/(main)/agent/_layout/AgentIdSync.tsx +12 -1
- package/src/app/[variants]/(main)/agent/_layout/Sidebar/Cron/CronTopicGroup.tsx +1 -1
- package/src/app/[variants]/(main)/agent/_layout/Sidebar/Header/AddTopicButon.tsx +1 -1
- package/src/app/[variants]/(main)/agent/_layout/Sidebar/Header/Nav.tsx +1 -1
- package/src/app/[variants]/(main)/agent/_layout/Sidebar/Topic/AllTopicsDrawer/index.tsx +1 -1
- package/src/app/[variants]/(main)/agent/_layout/Sidebar/Topic/hooks/useThreadNavigation.ts +1 -1
- package/src/app/[variants]/(main)/agent/_layout/Sidebar/Topic/hooks/useTopicNavigation.ts +1 -1
- package/src/app/[variants]/(main)/agent/features/TelemetryNotification.tsx +2 -3
- package/src/app/[variants]/(main)/community/(detail)/assistant/features/Details/Nav.tsx +9 -9
- package/src/app/[variants]/(main)/community/(detail)/assistant/features/Details/Versions/index.tsx +2 -3
- package/src/app/[variants]/(main)/community/(detail)/features/MakedownRender.tsx +1 -2
- package/src/app/[variants]/(main)/community/(detail)/features/ShareButton.tsx +2 -3
- package/src/app/[variants]/(main)/community/(detail)/features/Toc/Heading.tsx +2 -3
- package/src/app/[variants]/(main)/community/(detail)/mcp/features/Details/Versions/index.tsx +2 -2
- package/src/app/[variants]/(main)/community/(detail)/model/features/Details/Nav.tsx +12 -11
- package/src/app/[variants]/(main)/community/(detail)/model/features/Details/Parameter/ParameterItem.tsx +2 -3
- package/src/app/[variants]/(main)/community/(detail)/provider/features/Details/Nav.tsx +11 -10
- package/src/app/[variants]/(main)/community/(detail)/provider/features/Header.tsx +10 -9
- package/src/app/[variants]/(main)/community/(list)/(home)/index.tsx +1 -1
- package/src/app/[variants]/(main)/community/(list)/assistant/features/Category/useCategory.tsx +1 -1
- package/src/app/[variants]/(main)/community/(list)/features/SortButton/index.tsx +2 -3
- package/src/app/[variants]/(main)/community/_layout/Sidebar/Header/Nav.tsx +1 -1
- package/src/app/[variants]/(main)/community/features/CreateButton/Inner.tsx +1 -1
- package/src/app/[variants]/(main)/community/features/CreateButton/index.tsx +1 -1
- package/src/app/[variants]/(main)/community/features/Search.tsx +1 -2
- package/src/app/[variants]/(main)/community/features/Title.tsx +5 -5
- package/src/app/[variants]/(main)/group/_layout/GroupIdSync.tsx +12 -1
- package/src/app/[variants]/(main)/group/_layout/Sidebar/Header/Nav.tsx +1 -1
- package/src/app/[variants]/(main)/group/_layout/Sidebar/Topic/AllTopicsDrawer/index.tsx +1 -1
- package/src/app/[variants]/(main)/group/_layout/Sidebar/Topic/hooks/useThreadNavigation.ts +1 -1
- package/src/app/[variants]/(main)/group/features/Conversation/Header/ShareButton/index.tsx +1 -1
- package/src/app/[variants]/(main)/group/features/TelemetryNotification.tsx +2 -3
- package/src/app/[variants]/(main)/home/_layout/Body/Agent/AllAgentsDrawer/index.tsx +1 -1
- package/src/app/[variants]/(main)/hooks/useActiveTabKey.ts +6 -11
- package/src/app/[variants]/(main)/image/NotSupportClient.tsx +4 -3
- package/src/app/[variants]/(main)/image/_layout/ConfigPanel/components/ImageUpload.tsx +1 -1
- package/src/app/[variants]/(main)/image/_layout/ConfigPanel/components/MultiImagesUpload/ImageManageModal.tsx +1 -1
- package/src/app/[variants]/(main)/image/_layout/ConfigPanel/components/MultiImagesUpload/index.tsx +1 -1
- package/src/app/[variants]/(main)/memory/(home)/features/RoleTagCloud/index.tsx +1 -1
- package/src/app/[variants]/(main)/memory/_layout/Sidebar/Header/Nav.tsx +1 -1
- package/src/app/[variants]/(main)/memory/features/SourceLink.tsx +1 -1
- package/src/app/[variants]/(main)/page/_layout/Body/AllPagesDrawer/index.tsx +1 -1
- package/src/app/[variants]/(main)/settings/about/features/ItemCard.tsx +2 -3
- package/src/app/[variants]/(main)/settings/about/features/ItemLink.tsx +2 -3
- package/src/app/[variants]/(main)/settings/about/features/Version.tsx +6 -7
- package/src/app/[variants]/(main)/settings/features/SettingsContent.tsx +1 -1
- package/src/app/[variants]/(main)/settings/features/UpgradeAlert.tsx +4 -4
- package/src/app/[variants]/(main)/settings/provider/(list)/Footer.tsx +2 -2
- package/src/app/[variants]/(main)/settings/provider/detail/index.tsx +1 -1
- package/src/app/[variants]/(main)/settings/provider/detail/ollama/CheckError.tsx +1 -1
- package/src/app/[variants]/(main)/settings/provider/features/ProviderConfig/index.tsx +12 -6
- package/src/app/[variants]/(main)/settings/security/index.tsx +1 -1
- package/src/app/[variants]/(main)/settings/stats/features/overview/ShareButton/ShareModal.tsx +1 -1
- package/src/app/[variants]/(main)/settings/stats/features/rankings/AssistantsRank.tsx +1 -1
- package/src/app/[variants]/(main)/settings/stats/features/rankings/TopicsRank.tsx +1 -1
- package/src/app/[variants]/(mobile)/_layout/index.tsx +1 -1
- package/src/app/[variants]/(mobile)/chat/settings/features/AgentInfoDescription/index.tsx +1 -1
- package/src/app/[variants]/(mobile)/chat/settings/features/SettingButton.tsx +1 -1
- package/src/app/[variants]/(mobile)/router/index.tsx +1 -1
- package/src/app/[variants]/page.tsx +1 -1
- package/src/app/[variants]/router/index.tsx +1 -1
- package/src/components/404/index.tsx +4 -4
- package/src/components/Analytics/index.tsx +1 -1
- package/src/components/BrandWatermark/index.tsx +4 -4
- package/src/components/Branding/ProductLogo/Custom.tsx +1 -1
- package/src/components/Error/index.tsx +3 -4
- package/src/components/GoBack/index.tsx +2 -2
- package/src/components/LabsModal/LabCard.tsx +1 -1
- package/src/components/Link.tsx +25 -5
- package/src/components/OllamaSetupGuide/index.tsx +5 -4
- package/src/components/WebFavicon/index.tsx +1 -1
- package/src/components/client/ClientResponsiveContent/index.tsx +1 -1
- package/src/components/client/ClientResponsiveLayout.tsx +1 -1
- package/src/components/mdx/Image.tsx +1 -1
- package/src/components/mdx/Link.tsx +26 -9
- package/src/features/AlertBanner/CloudBanner.tsx +2 -3
- package/src/features/ChatInput/ActionBar/Model/ControlsForm.tsx +8 -7
- package/src/features/ChatInput/ActionBar/Params/Controls.tsx +1 -3
- package/src/features/ChatInput/ActionBar/Token/index.tsx +1 -1
- package/src/features/ChatInput/Mobile/index.tsx +1 -1
- package/src/features/Conversation/ChatItem/components/MessageContent/index.tsx +1 -1
- package/src/features/Conversation/Error/OllamaBizError/index.tsx +1 -1
- package/src/features/Conversation/Error/OllamaSetupGuide/Desktop.tsx +1 -2
- package/src/features/Conversation/Error/index.tsx +1 -1
- package/src/features/Conversation/Messages/AssistantGroup/Tool/Actions/Settings.tsx +1 -1
- package/src/features/Conversation/Messages/AssistantGroup/Tool/index.tsx +1 -1
- package/src/features/Conversation/Messages/AssistantGroup/index.tsx +1 -1
- package/src/features/Conversation/Messages/Tool/Tool/index.tsx +1 -1
- package/src/features/Conversation/Messages/components/SearchGrounding.tsx +1 -1
- package/src/features/DataImporter/Error.tsx +3 -3
- package/src/features/DevPanel/CacheViewer/cacheProvider.tsx +2 -1
- package/src/features/DevPanel/MetadataViewer/Og.tsx +1 -1
- package/src/features/DevPanel/features/FloatPanel.tsx +1 -1
- package/src/features/DevPanel/features/Table/TooltipContent.tsx +3 -4
- package/src/features/DevPanel/index.tsx +1 -1
- package/src/features/EditorCanvas/InlineToolbar.tsx +1 -6
- package/src/features/FileViewer/NotSupport/index.tsx +2 -3
- package/src/features/Follow/index.tsx +8 -9
- package/src/features/LibraryModal/AddFilesToKnowledgeBase/SelectForm.tsx +2 -2
- package/src/features/MCP/MCPInstallProgress/InstallError/ErrorDetails.tsx +61 -83
- package/src/features/MCP/Scores.tsx +1 -1
- package/src/features/MCPPluginDetail/Nav.tsx +8 -8
- package/src/features/MCPPluginDetail/Overview/TagList.tsx +1 -1
- package/src/features/MobileTabBar/index.tsx +2 -1
- package/src/features/OllamaSetupGuide/Desktop.tsx +1 -2
- package/src/features/PWAInstall/Install.tsx +1 -1
- package/src/features/PWAInstall/index.tsx +1 -1
- package/src/features/PluginDevModal/MCPManifestForm/index.tsx +30 -3
- package/src/features/PluginStore/McpList/index.tsx +1 -1
- package/src/features/PluginStore/PluginList/Detail/Header.tsx +6 -6
- package/src/features/PluginsUI/Render/DefaultType/index.tsx +1 -1
- package/src/features/Portal/Artifacts/Body/Renderer/index.tsx +1 -1
- package/src/features/ResourceManager/components/ChunkDrawer/index.tsx +1 -1
- package/src/features/ResourceManager/components/Explorer/ListView/Skeleton.tsx +26 -26
- package/src/features/ResourceManager/components/Explorer/ToolBar/BatchActionsDropdown.tsx +147 -149
- package/src/features/ResourceManager/index.tsx +1 -1
- package/src/features/Setting/Footer.tsx +4 -5
- package/src/features/User/UserPanel/PanelContent.tsx +1 -1
- package/src/hooks/useActiveTabKey.ts +6 -3
- package/src/hooks/useIsSingleMode.test.ts +10 -24
- package/src/hooks/useIsSingleMode.ts +4 -2
- package/src/hooks/useIsSubSlug.ts +2 -1
- package/src/hooks/useQuery.ts +5 -5
- package/src/layout/GlobalProvider/AppTheme.tsx +2 -2
- package/src/layout/GlobalProvider/StyleRegistry.tsx +1 -1
- package/src/layout/GlobalProvider/useUserStateRedirect.ts +13 -25
- package/src/libs/mcp/types.ts +31 -0
- package/src/libs/next/Image.tsx +13 -0
- package/src/libs/next/Link.tsx +13 -0
- package/src/libs/next/dynamic.tsx +13 -0
- package/src/libs/next/index.ts +22 -0
- package/src/libs/next/navigation.ts +22 -0
- package/src/libs/router/Link.tsx +30 -0
- package/src/libs/router/index.ts +18 -0
- package/src/libs/router/navigation.ts +72 -0
- package/src/server/modules/AgentRuntime/AgentStateManager.ts +5 -1
- package/src/store/chat/slices/portal/selectors.test.ts +5 -15
- package/src/store/page/index.ts +1 -1
- package/src/store/page/slices/crud/index.ts +1 -1
- package/src/store/tool/slices/mcpStore/action.ts +26 -11
- package/src/app/[variants]/(main)/hooks/usePathname.ts +0 -10
- package/src/app/[variants]/(main)/hooks/useQuery.ts +0 -12
- package/src/app/[variants]/(main)/hooks/useRouter.ts +0 -22
- package/src/app/[variants]/(main)/hooks/useSearchParams.ts +0 -11
|
@@ -18,7 +18,7 @@ export enum AssistantCategory {
|
|
|
18
18
|
Marketing = 'marketing',
|
|
19
19
|
Office = 'office',
|
|
20
20
|
Programming = 'programming',
|
|
21
|
-
Translation = 'translation'
|
|
21
|
+
Translation = 'translation',
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
export enum AssistantSorts {
|
|
@@ -29,7 +29,7 @@ export enum AssistantSorts {
|
|
|
29
29
|
PluginCount = 'pluginCount',
|
|
30
30
|
Recommended = 'recommended',
|
|
31
31
|
Title = 'title',
|
|
32
|
-
TokenUsage = 'tokenUsage'
|
|
32
|
+
TokenUsage = 'tokenUsage',
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
export enum AssistantNavKey {
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
/**
|
|
3
|
+
* Script to migrate SPA internal components from @/libs/next/navigation
|
|
4
|
+
* to React Router version hooks.
|
|
5
|
+
*
|
|
6
|
+
* For files in (main) directory:
|
|
7
|
+
* - usePathname -> @/app/[variants]/(main)/hooks/usePathname
|
|
8
|
+
* - useSearchParams -> @/app/[variants]/(main)/hooks/useSearchParams
|
|
9
|
+
* - useRouter -> @/app/[variants]/(main)/hooks/useRouter
|
|
10
|
+
*
|
|
11
|
+
* @see RFC 147: LOBE-2850 - Phase 3
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import { readFile, writeFile } from 'node:fs/promises';
|
|
15
|
+
import { dirname, join, relative } from 'node:path';
|
|
16
|
+
import { fileURLToPath } from 'node:url';
|
|
17
|
+
|
|
18
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
19
|
+
|
|
20
|
+
// Files that should be migrated to React Router version
|
|
21
|
+
const SPA_FILES = [
|
|
22
|
+
// (main) directory files using @/libs/next/navigation
|
|
23
|
+
'src/app/[variants]/(main)/community/_layout/Sidebar/Header/Nav.tsx',
|
|
24
|
+
'src/app/[variants]/(main)/group/_layout/Sidebar/Header/Nav.tsx',
|
|
25
|
+
'src/app/[variants]/(main)/group/_layout/Sidebar/Topic/hooks/useTopicNavigation.ts',
|
|
26
|
+
'src/app/[variants]/(main)/group/_layout/Sidebar/Topic/hooks/useThreadNavigation.ts',
|
|
27
|
+
'src/app/[variants]/(main)/chat/_layout/Sidebar/Header/AddTopicButon.tsx',
|
|
28
|
+
'src/app/[variants]/(main)/chat/_layout/Sidebar/Header/Nav.tsx',
|
|
29
|
+
'src/app/[variants]/(main)/chat/_layout/Sidebar/Topic/hooks/useTopicNavigation.ts',
|
|
30
|
+
'src/app/[variants]/(main)/chat/_layout/Sidebar/Topic/hooks/useThreadNavigation.ts',
|
|
31
|
+
'src/app/[variants]/(main)/memory/_layout/Sidebar/Header/Nav.tsx',
|
|
32
|
+
];
|
|
33
|
+
|
|
34
|
+
interface MigrationResult {
|
|
35
|
+
changes: string[];
|
|
36
|
+
filePath: string;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
async function migrateFile(relativePath: string): Promise<MigrationResult | null> {
|
|
40
|
+
const fullPath = join(__dirname, '..', relativePath);
|
|
41
|
+
const content = await readFile(fullPath, 'utf8');
|
|
42
|
+
let newContent = content;
|
|
43
|
+
const changes: string[] = [];
|
|
44
|
+
|
|
45
|
+
// Check what hooks are being imported from @/libs/next/navigation
|
|
46
|
+
const importMatch = content.match(
|
|
47
|
+
/import\s*\{([^}]+)\}\s*from\s*['"]@\/libs\/next\/navigation['"]/
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
if (!importMatch) {
|
|
51
|
+
console.log(`⏭️ ${relativePath} - No @/libs/next/navigation import found`);
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const importedHooks = importMatch[1]
|
|
56
|
+
.split(',')
|
|
57
|
+
.map((s) => s.trim())
|
|
58
|
+
.filter(Boolean);
|
|
59
|
+
|
|
60
|
+
console.log(`📝 ${relativePath}`);
|
|
61
|
+
console.log(` Imported hooks: ${importedHooks.join(', ')}`);
|
|
62
|
+
|
|
63
|
+
// Build new imports
|
|
64
|
+
const newImports: string[] = [];
|
|
65
|
+
|
|
66
|
+
for (const hook of importedHooks) {
|
|
67
|
+
if (hook === 'usePathname') {
|
|
68
|
+
newImports.push(`import { usePathname } from '@/app/[variants]/(main)/hooks/usePathname';`);
|
|
69
|
+
changes.push('usePathname -> React Router version');
|
|
70
|
+
} else if (hook === 'useSearchParams') {
|
|
71
|
+
newImports.push(
|
|
72
|
+
`import { useSearchParams } from '@/app/[variants]/(main)/hooks/useSearchParams';`
|
|
73
|
+
);
|
|
74
|
+
changes.push('useSearchParams -> React Router version');
|
|
75
|
+
} else if (hook === 'useRouter') {
|
|
76
|
+
newImports.push(`import { useRouter } from '@/app/[variants]/(main)/hooks/useRouter';`);
|
|
77
|
+
changes.push('useRouter -> React Router version');
|
|
78
|
+
} else {
|
|
79
|
+
// Keep other imports (like notFound, redirect) from next/navigation
|
|
80
|
+
console.log(` ⚠️ Unknown hook "${hook}" - keeping original import`);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if (newImports.length === 0) {
|
|
85
|
+
console.log(` ⏭️ No hooks to migrate`);
|
|
86
|
+
return null;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Replace the old import with new imports
|
|
90
|
+
newContent = newContent.replace(
|
|
91
|
+
/import\s*\{[^}]+\}\s*from\s*['"]@\/libs\/next\/navigation['"];?\n?/,
|
|
92
|
+
newImports.join('\n') + '\n'
|
|
93
|
+
);
|
|
94
|
+
|
|
95
|
+
if (newContent !== content) {
|
|
96
|
+
await writeFile(fullPath, newContent, 'utf8');
|
|
97
|
+
for (const change of changes) {
|
|
98
|
+
console.log(` ✅ ${change}`);
|
|
99
|
+
}
|
|
100
|
+
return { changes, filePath: relativePath };
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return null;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
async function main() {
|
|
107
|
+
console.log('🚀 Starting SPA navigation migration...\n');
|
|
108
|
+
|
|
109
|
+
const results: MigrationResult[] = [];
|
|
110
|
+
|
|
111
|
+
for (const file of SPA_FILES) {
|
|
112
|
+
try {
|
|
113
|
+
const result = await migrateFile(file);
|
|
114
|
+
if (result) {
|
|
115
|
+
results.push(result);
|
|
116
|
+
}
|
|
117
|
+
} catch (error) {
|
|
118
|
+
console.error(`❌ Error processing ${file}:`, error);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
console.log('\n' + '='.repeat(60));
|
|
123
|
+
console.log(`📊 Migration Summary:`);
|
|
124
|
+
console.log(` - Files processed: ${SPA_FILES.length}`);
|
|
125
|
+
console.log(` - Files modified: ${results.length}`);
|
|
126
|
+
console.log('\n✨ SPA navigation migration complete!');
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
await main();
|
|
@@ -4,143 +4,145 @@ import {
|
|
|
4
4
|
tracer as upstashWorkflowTracer,
|
|
5
5
|
} from '@lobechat/observability-otel/modules/upstash-workflow';
|
|
6
6
|
import { LayersEnum, MemorySourceType } from '@lobechat/types';
|
|
7
|
-
import {
|
|
7
|
+
import { Client } from '@upstash/qstash';
|
|
8
8
|
import { WorkflowAbort } from '@upstash/workflow';
|
|
9
|
+
import { serve } from '@upstash/workflow/nextjs';
|
|
9
10
|
|
|
11
|
+
import { parseMemoryExtractionConfig } from '@/server/globalConfig/parseMemoryExtractionConfig';
|
|
10
12
|
import {
|
|
11
13
|
MemoryExtractionExecutor,
|
|
12
14
|
type MemoryExtractionPayloadInput,
|
|
13
15
|
normalizeMemoryExtractionPayload,
|
|
14
16
|
} from '@/server/services/memory/userMemory/extract';
|
|
15
|
-
import { Client } from '@upstash/qstash'
|
|
16
|
-
import { parseMemoryExtractionConfig } from '@/server/globalConfig/parseMemoryExtractionConfig';
|
|
17
17
|
|
|
18
18
|
const { upstashWorkflowExtraHeaders } = parseMemoryExtractionConfig();
|
|
19
19
|
|
|
20
20
|
const CEP_LAYERS: LayersEnum[] = [LayersEnum.Context, LayersEnum.Experience, LayersEnum.Preference];
|
|
21
21
|
const IDENTITY_LAYERS: LayersEnum[] = [LayersEnum.Identity];
|
|
22
22
|
|
|
23
|
-
export const { POST } = serve<MemoryExtractionPayloadInput>(
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
try {
|
|
41
|
-
console.log('[chat-topic][batch] Starting batch topic processing workflow', {
|
|
42
|
-
topicIds: payload.topicIds,
|
|
43
|
-
userIds: payload.userIds,
|
|
23
|
+
export const { POST } = serve<MemoryExtractionPayloadInput>(
|
|
24
|
+
(context) =>
|
|
25
|
+
upstashWorkflowTracer.startActiveSpan(
|
|
26
|
+
'workflow:memory-user-memory:process-topics',
|
|
27
|
+
async (span) => {
|
|
28
|
+
const payload = normalizeMemoryExtractionPayload(context.requestPayload || {});
|
|
29
|
+
|
|
30
|
+
span.setAttributes({
|
|
31
|
+
...buildUpstashWorkflowAttributes(context),
|
|
32
|
+
'workflow.memory_user_memory.force_all': payload.forceAll,
|
|
33
|
+
'workflow.memory_user_memory.force_topics': payload.forceTopics,
|
|
34
|
+
'workflow.memory_user_memory.layers': payload.layers.join(','),
|
|
35
|
+
'workflow.memory_user_memory.source': payload.sources.join(','),
|
|
36
|
+
'workflow.memory_user_memory.topic_count': payload.topicIds.length,
|
|
37
|
+
'workflow.memory_user_memory.user_count': payload.userIds.length,
|
|
38
|
+
'workflow.name': 'memory-user-memory:process-topics',
|
|
44
39
|
});
|
|
45
40
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
41
|
+
try {
|
|
42
|
+
console.log('[chat-topic][batch] Starting batch topic processing workflow', {
|
|
43
|
+
topicIds: payload.topicIds,
|
|
44
|
+
userIds: payload.userIds,
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
if (!payload.userIds.length) {
|
|
48
|
+
span.setStatus({ code: SpanStatusCode.OK });
|
|
49
|
+
|
|
50
|
+
return {
|
|
51
|
+
message: 'No user id provided for topic batch.',
|
|
52
|
+
processedTopics: 0,
|
|
53
|
+
processedUsers: 0,
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
if (!payload.topicIds.length) {
|
|
57
|
+
span.setStatus({ code: SpanStatusCode.OK });
|
|
58
|
+
|
|
59
|
+
return {
|
|
60
|
+
message: 'No topic ids provided for extraction.',
|
|
61
|
+
processedTopics: 0,
|
|
62
|
+
processedUsers: 0,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
if (!payload.sources.includes(MemorySourceType.ChatTopic)) {
|
|
66
|
+
span.setStatus({ code: SpanStatusCode.OK });
|
|
67
|
+
|
|
68
|
+
return {
|
|
69
|
+
message: 'Source not supported in topic batch.',
|
|
70
|
+
processedTopics: 0,
|
|
71
|
+
processedUsers: 0,
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const userId = payload.userIds[0];
|
|
76
|
+
const executor = await MemoryExtractionExecutor.create();
|
|
77
|
+
|
|
78
|
+
// CEP: run in parallel across the batch
|
|
79
|
+
await Promise.all(
|
|
80
|
+
payload.topicIds.map((topicId, index) =>
|
|
81
|
+
context.run(
|
|
82
|
+
`memory:user-memory:extract:users:${userId}:topics:${topicId}:cep:${index}`,
|
|
83
|
+
() =>
|
|
84
|
+
executor.extractTopic({
|
|
85
|
+
forceAll: payload.forceAll,
|
|
86
|
+
forceTopics: payload.forceTopics,
|
|
87
|
+
from: payload.from,
|
|
88
|
+
layers: CEP_LAYERS,
|
|
89
|
+
source: MemorySourceType.ChatTopic,
|
|
90
|
+
to: payload.to,
|
|
91
|
+
topicId,
|
|
92
|
+
userId,
|
|
93
|
+
}),
|
|
94
|
+
),
|
|
95
|
+
),
|
|
96
|
+
);
|
|
76
97
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
`memory:user-memory:extract:users:${userId}:topics:${topicId}:cep:${index}`,
|
|
98
|
+
// Identity: run sequentially for the batch
|
|
99
|
+
for (const [index, topicId] of payload.topicIds.entries()) {
|
|
100
|
+
await context.run(
|
|
101
|
+
`memory:user-memory:extract:users:${userId}:topics:${topicId}:identity:${index}`,
|
|
82
102
|
() =>
|
|
83
103
|
executor.extractTopic({
|
|
84
104
|
forceAll: payload.forceAll,
|
|
85
105
|
forceTopics: payload.forceTopics,
|
|
86
106
|
from: payload.from,
|
|
87
|
-
layers:
|
|
107
|
+
layers: IDENTITY_LAYERS,
|
|
88
108
|
source: MemorySourceType.ChatTopic,
|
|
89
109
|
to: payload.to,
|
|
90
110
|
topicId,
|
|
91
111
|
userId,
|
|
92
112
|
}),
|
|
93
|
-
)
|
|
94
|
-
|
|
95
|
-
);
|
|
96
|
-
|
|
97
|
-
// Identity: run sequentially for the batch
|
|
98
|
-
for (const [index, topicId] of payload.topicIds.entries()) {
|
|
99
|
-
await context.run(
|
|
100
|
-
`memory:user-memory:extract:users:${userId}:topics:${topicId}:identity:${index}`,
|
|
101
|
-
() =>
|
|
102
|
-
executor.extractTopic({
|
|
103
|
-
forceAll: payload.forceAll,
|
|
104
|
-
forceTopics: payload.forceTopics,
|
|
105
|
-
from: payload.from,
|
|
106
|
-
layers: IDENTITY_LAYERS,
|
|
107
|
-
source: MemorySourceType.ChatTopic,
|
|
108
|
-
to: payload.to,
|
|
109
|
-
topicId,
|
|
110
|
-
userId,
|
|
111
|
-
}),
|
|
112
|
-
);
|
|
113
|
-
}
|
|
113
|
+
);
|
|
114
|
+
}
|
|
114
115
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
116
|
+
console.log('[chat-topic][batch] Batch topic processing workflow completed', {
|
|
117
|
+
processedTopics: payload.topicIds.length,
|
|
118
|
+
});
|
|
118
119
|
|
|
119
|
-
|
|
120
|
+
span.setStatus({ code: SpanStatusCode.OK });
|
|
121
|
+
|
|
122
|
+
return {
|
|
123
|
+
processedTopics: payload.topicIds.length,
|
|
124
|
+
processedUsers: payload.userIds.length,
|
|
125
|
+
};
|
|
126
|
+
} catch (error) {
|
|
127
|
+
// NOTICE: Let WorkflowAbort bubble up (used internally by Upstash); record others
|
|
128
|
+
if (error instanceof WorkflowAbort) {
|
|
129
|
+
console.warn('workflow aborted:', error.message);
|
|
130
|
+
throw error;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
span.recordException(error as Error);
|
|
134
|
+
span.setStatus({
|
|
135
|
+
code: SpanStatusCode.ERROR,
|
|
136
|
+
message: error instanceof Error ? error.message : 'process-topics workflow failed',
|
|
137
|
+
});
|
|
120
138
|
|
|
121
|
-
return {
|
|
122
|
-
processedTopics: payload.topicIds.length,
|
|
123
|
-
processedUsers: payload.userIds.length,
|
|
124
|
-
};
|
|
125
|
-
} catch (error) {
|
|
126
|
-
// NOTICE: Let WorkflowAbort bubble up (used internally by Upstash); record others
|
|
127
|
-
if (error instanceof WorkflowAbort) {
|
|
128
|
-
console.warn('workflow aborted:', error.message);
|
|
129
139
|
throw error;
|
|
140
|
+
} finally {
|
|
141
|
+
span.end();
|
|
130
142
|
}
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
code: SpanStatusCode.ERROR,
|
|
135
|
-
message: error instanceof Error ? error.message : 'process-topics workflow failed',
|
|
136
|
-
});
|
|
137
|
-
|
|
138
|
-
throw error;
|
|
139
|
-
} finally {
|
|
140
|
-
span.end();
|
|
141
|
-
}
|
|
142
|
-
},
|
|
143
|
-
), {
|
|
143
|
+
},
|
|
144
|
+
),
|
|
145
|
+
{
|
|
144
146
|
// NOTICE(@nekomeowww): Here as scenarios like Vercel Deployment Protection,
|
|
145
147
|
// intermediate context.run(...) won't offer customizable headers like context.trigger(...) / client.trigger(...)
|
|
146
148
|
// for passing additional headers, we have to provide a custom QStash client with the required headers here.
|
|
@@ -151,6 +153,7 @@ export const { POST } = serve<MemoryExtractionPayloadInput>((context) =>
|
|
|
151
153
|
headers: {
|
|
152
154
|
...upstashWorkflowExtraHeaders,
|
|
153
155
|
},
|
|
154
|
-
token: process.env.QSTASH_TOKEN
|
|
155
|
-
})
|
|
156
|
-
}
|
|
156
|
+
token: process.env.QSTASH_TOKEN!,
|
|
157
|
+
}),
|
|
158
|
+
},
|
|
159
|
+
);
|