@lobehub/lobehub 2.0.0-next.250 → 2.0.0-next.252
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/CHANGELOG.md +50 -0
- package/changelog/v1.json +14 -0
- package/package.json +1 -1
- package/packages/builtin-tool-notebook/src/client/Render/CreateDocument/DocumentCard.tsx +0 -2
- package/packages/database/migrations/meta/_journal.json +1 -1
- package/packages/database/src/models/__tests__/topics/topic.create.test.ts +37 -8
- package/packages/database/src/models/topic.ts +71 -4
- package/packages/database/src/schemas/agentCronJob.ts +1 -2
- package/packages/memory-user-memory/src/extractors/context.ts +1 -4
- package/packages/memory-user-memory/src/extractors/experience.ts +2 -8
- package/packages/memory-user-memory/src/extractors/preference.ts +2 -8
- package/packages/memory-user-memory/src/prompts/gatekeeper.ts +123 -123
- package/packages/memory-user-memory/src/prompts/layers/context.ts +152 -152
- package/packages/memory-user-memory/src/prompts/layers/experience.ts +159 -159
- package/packages/memory-user-memory/src/prompts/layers/identity.ts +213 -213
- package/packages/memory-user-memory/src/prompts/layers/preference.ts +160 -160
- package/packages/memory-user-memory/src/services/extractExecutor.ts +33 -30
- package/packages/memory-user-memory/src/types.ts +10 -8
- package/packages/types/src/discover/mcp.ts +1 -1
- package/packages/types/src/topic/topic.ts +9 -0
- package/src/app/[variants]/(main)/chat/_layout/Sidebar/Body.tsx +4 -1
- package/src/app/[variants]/(main)/chat/_layout/Sidebar/Topic/CronTopicList/CronTopicGroup.tsx +74 -0
- package/src/app/[variants]/(main)/chat/_layout/Sidebar/Topic/CronTopicList/CronTopicItem.tsx +40 -0
- package/src/app/[variants]/(main)/chat/_layout/Sidebar/Topic/CronTopicList/index.tsx +140 -0
- package/src/app/[variants]/(main)/chat/_layout/Sidebar/Topic/List/index.tsx +1 -1
- package/src/app/[variants]/(main)/chat/_layout/Sidebar/Topic/TopicListContent/index.tsx +1 -1
- package/src/app/[variants]/(main)/chat/_layout/Sidebar/Topic/index.tsx +1 -1
- package/src/app/[variants]/(main)/chat/cron/[cronId]/index.tsx +664 -0
- package/src/app/[variants]/(main)/chat/profile/features/AgentCronJobs/CronJobCards.tsx +160 -0
- package/src/app/[variants]/(main)/chat/profile/features/AgentCronJobs/CronJobForm.tsx +202 -0
- package/src/app/[variants]/(main)/chat/profile/features/AgentCronJobs/CronJobList.tsx +137 -0
- package/src/app/[variants]/(main)/chat/profile/features/AgentCronJobs/hooks/useAgentCronJobs.ts +138 -0
- package/src/app/[variants]/(main)/chat/profile/features/AgentCronJobs/index.tsx +130 -0
- package/src/app/[variants]/(main)/chat/profile/features/ProfileEditor/index.tsx +33 -3
- package/src/app/[variants]/(main)/community/(detail)/assistant/features/Sidebar/ActionButton/AddAgent.tsx +6 -0
- package/src/app/[variants]/(main)/community/(list)/assistant/features/List/Item.tsx +12 -3
- package/src/app/[variants]/(main)/community/(list)/mcp/features/List/Item.tsx +14 -4
- package/src/app/[variants]/router/desktopRouter.config.tsx +7 -0
- package/src/features/ResourceManager/components/Explorer/useCheckTaskStatus.ts +1 -1
- package/src/hooks/useFetchCronTopics.ts +29 -0
- package/src/hooks/useFetchCronTopicsWithJobInfo.ts +56 -0
- package/src/hooks/useFetchTopics.ts +4 -1
- package/src/locales/default/setting.ts +44 -1
- package/src/server/routers/lambda/agentCronJob.ts +367 -0
- package/src/server/routers/lambda/image/index.test.ts +2 -2
- package/src/server/routers/lambda/index.ts +2 -0
- package/src/server/routers/lambda/market/index.ts +45 -4
- package/src/server/routers/lambda/topic.ts +15 -3
- package/src/server/services/aiAgent/index.ts +18 -1
- package/src/server/services/discover/index.ts +29 -3
- package/src/server/services/memory/userMemory/extract.ts +14 -6
- package/src/services/agentCronJob.ts +95 -0
- package/src/services/discover.ts +38 -1
- package/src/services/topic/index.ts +1 -0
- package/src/store/chat/slices/topic/action.ts +53 -2
- package/src/store/chat/slices/topic/initialState.ts +1 -0
- package/src/store/chat/slices/topic/selectors.ts +14 -6
- package/src/store/tool/slices/mcpStore/action.test.ts +38 -0
- package/src/store/tool/slices/mcpStore/action.ts +18 -0
- package/src/tools/placeholders.ts +1 -4
|
@@ -4,21 +4,20 @@ import {
|
|
|
4
4
|
} from '@lobechat/const';
|
|
5
5
|
import { messages, topics } from '@lobechat/database/schemas';
|
|
6
6
|
import {
|
|
7
|
+
BenchmarkLocomoContextProvider,
|
|
7
8
|
LobeChatTopicContextProvider,
|
|
8
9
|
LobeChatTopicResultRecorder,
|
|
9
10
|
MemoryExtractionService,
|
|
10
11
|
RetrievalUserMemoryContextProvider,
|
|
11
12
|
RetrievalUserMemoryIdentitiesProvider,
|
|
12
|
-
BenchmarkLocomoContextProvider,
|
|
13
13
|
} from '@lobechat/memory-user-memory';
|
|
14
14
|
import type {
|
|
15
|
+
BenchmarkLocomoPart,
|
|
15
16
|
MemoryExtractionAgent,
|
|
16
17
|
MemoryExtractionJob,
|
|
17
18
|
MemoryExtractionResult,
|
|
18
|
-
BenchmarkLocomoPart,
|
|
19
19
|
PersistedMemoryResult,
|
|
20
20
|
} from '@lobechat/memory-user-memory';
|
|
21
|
-
import { UserMemorySourceBenchmarkLoCoMoModel } from '@/database/models/userMemory/sources/benchmarkLoCoMo';
|
|
22
21
|
import { ModelRuntime } from '@lobechat/model-runtime';
|
|
23
22
|
import type {
|
|
24
23
|
Embeddings,
|
|
@@ -45,6 +44,7 @@ import type {
|
|
|
45
44
|
MemoryExtractionTracePayload,
|
|
46
45
|
} from '@lobechat/types';
|
|
47
46
|
import { Client } from '@upstash/workflow';
|
|
47
|
+
import debug from 'debug';
|
|
48
48
|
import { and, asc, eq, inArray } from 'drizzle-orm';
|
|
49
49
|
import { join } from 'pathe';
|
|
50
50
|
import { z } from 'zod';
|
|
@@ -54,6 +54,7 @@ import { TopicModel } from '@/database/models/topic';
|
|
|
54
54
|
import type { ListUsersForMemoryExtractorCursor } from '@/database/models/user';
|
|
55
55
|
import { UserModel } from '@/database/models/user';
|
|
56
56
|
import { UserMemoryModel } from '@/database/models/userMemory';
|
|
57
|
+
import { UserMemorySourceBenchmarkLoCoMoModel } from '@/database/models/userMemory/sources/benchmarkLoCoMo';
|
|
57
58
|
import { getServerDB } from '@/database/server';
|
|
58
59
|
import { getServerGlobalConfig } from '@/server/globalConfig';
|
|
59
60
|
import {
|
|
@@ -64,9 +65,13 @@ import { KeyVaultsGateKeeper } from '@/server/modules/KeyVaultsEncrypt';
|
|
|
64
65
|
import { S3 } from '@/server/modules/S3';
|
|
65
66
|
import type { GlobalMemoryLayer } from '@/types/serverConfig';
|
|
66
67
|
import type { UserKeyVaults } from '@/types/user/settings';
|
|
67
|
-
import {
|
|
68
|
+
import {
|
|
69
|
+
LayersEnum,
|
|
70
|
+
MemorySourceType,
|
|
71
|
+
type MergeStrategyEnum,
|
|
72
|
+
TypesEnum,
|
|
73
|
+
} from '@/types/userMemory';
|
|
68
74
|
import { encodeAsync } from '@/utils/tokenizer';
|
|
69
|
-
import debug from 'debug';
|
|
70
75
|
|
|
71
76
|
const SOURCE_ALIAS_MAP: Record<string, MemorySourceType> = {
|
|
72
77
|
benchmark_locomo: MemorySourceType.BenchmarkLocomo,
|
|
@@ -913,7 +918,10 @@ export class MemoryExtractionExecutor {
|
|
|
913
918
|
};
|
|
914
919
|
}
|
|
915
920
|
|
|
916
|
-
async listUserMemoryIdentities(
|
|
921
|
+
async listUserMemoryIdentities(
|
|
922
|
+
job: MemoryExtractionJob,
|
|
923
|
+
userId: string,
|
|
924
|
+
): Promise<IdentityMemoryDetail[]> {
|
|
917
925
|
const db = await this.db;
|
|
918
926
|
const userMemoryModel = new UserMemoryModel(db, userId);
|
|
919
927
|
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
CreateAgentCronJobData,
|
|
3
|
+
UpdateAgentCronJobData,
|
|
4
|
+
} from '@/database/schemas/agentCronJob';
|
|
5
|
+
import { lambdaClient } from '@/libs/trpc/client/lambda';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Client-side service for Agent Cron Job operations
|
|
9
|
+
*
|
|
10
|
+
* This service provides a clean interface for frontend components
|
|
11
|
+
* to interact with agent cron job data using tRPC client.
|
|
12
|
+
*/
|
|
13
|
+
class AgentCronJobService {
|
|
14
|
+
/**
|
|
15
|
+
* Create a new cron job
|
|
16
|
+
*/
|
|
17
|
+
async create(data: Omit<CreateAgentCronJobData, 'userId'>) {
|
|
18
|
+
return await lambdaClient.agentCronJob.create.mutate(data);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Get cron jobs for a specific agent
|
|
23
|
+
*/
|
|
24
|
+
async getByAgentId(agentId: string) {
|
|
25
|
+
return await lambdaClient.agentCronJob.findByAgent.query({ agentId });
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Get a single cron job by ID
|
|
30
|
+
*/
|
|
31
|
+
async getById(id: string) {
|
|
32
|
+
return await lambdaClient.agentCronJob.findById.query({ id });
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* List cron jobs with pagination and filtering
|
|
37
|
+
*/
|
|
38
|
+
async list(
|
|
39
|
+
options: {
|
|
40
|
+
agentId?: string;
|
|
41
|
+
enabled?: boolean;
|
|
42
|
+
limit?: number;
|
|
43
|
+
offset?: number;
|
|
44
|
+
} = {},
|
|
45
|
+
) {
|
|
46
|
+
return await lambdaClient.agentCronJob.list.query(options);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Update a cron job
|
|
51
|
+
*/
|
|
52
|
+
async update(id: string, data: UpdateAgentCronJobData) {
|
|
53
|
+
return await lambdaClient.agentCronJob.update.mutate({ data, id });
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Delete a cron job
|
|
58
|
+
*/
|
|
59
|
+
async delete(id: string) {
|
|
60
|
+
return await lambdaClient.agentCronJob.delete.mutate({ id });
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Reset execution counts
|
|
65
|
+
*/
|
|
66
|
+
async resetExecutions(id: string, newMaxExecutions?: number) {
|
|
67
|
+
return await lambdaClient.agentCronJob.resetExecutions.mutate({
|
|
68
|
+
id,
|
|
69
|
+
newMaxExecutions,
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Get execution statistics
|
|
75
|
+
*/
|
|
76
|
+
async getStats() {
|
|
77
|
+
return await lambdaClient.agentCronJob.getStats.query();
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Get jobs near depletion
|
|
82
|
+
*/
|
|
83
|
+
async getNearDepletion(threshold: number = 5) {
|
|
84
|
+
return await lambdaClient.agentCronJob.getNearDepletion.query({ threshold });
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Batch update status (enable/disable) for multiple jobs
|
|
89
|
+
*/
|
|
90
|
+
async batchUpdateStatus(ids: string[], enabled: boolean) {
|
|
91
|
+
return await lambdaClient.agentCronJob.batchUpdateStatus.mutate({ enabled, ids });
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export const agentCronJobService = new AgentCronJobService();
|
package/src/services/discover.ts
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import { type CategoryItem, type CategoryListQuery, type PluginManifest } from '@lobehub/market-sdk';
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
AgentEventRequest,
|
|
4
|
+
type CallReportRequest,
|
|
5
|
+
type InstallReportRequest,
|
|
6
|
+
type PluginEventRequest,
|
|
7
|
+
} from '@lobehub/market-types';
|
|
3
8
|
|
|
4
9
|
import { lambdaClient } from '@/libs/trpc/client';
|
|
5
10
|
import { globalHelpers } from '@/store/global/helpers';
|
|
@@ -195,6 +200,22 @@ class DiscoverService {
|
|
|
195
200
|
});
|
|
196
201
|
};
|
|
197
202
|
|
|
203
|
+
reportMcpEvent = async (eventData: PluginEventRequest) => {
|
|
204
|
+
const allow = userGeneralSettingsSelectors.telemetry(useUserStore.getState());
|
|
205
|
+
if (!allow) return;
|
|
206
|
+
|
|
207
|
+
await this.injectMPToken();
|
|
208
|
+
|
|
209
|
+
const payload = cleanObject({
|
|
210
|
+
...eventData,
|
|
211
|
+
source: eventData.source ?? 'community/mcp',
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
lambdaClient.market.reportMcpEvent.mutate(payload).catch((error) => {
|
|
215
|
+
console.warn('Failed to report MCP event:', error);
|
|
216
|
+
});
|
|
217
|
+
};
|
|
218
|
+
|
|
198
219
|
/**
|
|
199
220
|
* Report agent installation to increase install count
|
|
200
221
|
*/
|
|
@@ -211,6 +232,22 @@ class DiscoverService {
|
|
|
211
232
|
});
|
|
212
233
|
};
|
|
213
234
|
|
|
235
|
+
reportAgentEvent = async (eventData: AgentEventRequest) => {
|
|
236
|
+
const allow = userGeneralSettingsSelectors.telemetry(useUserStore.getState());
|
|
237
|
+
if (!allow) return;
|
|
238
|
+
|
|
239
|
+
await this.injectMPToken();
|
|
240
|
+
|
|
241
|
+
const payload = cleanObject({
|
|
242
|
+
...eventData,
|
|
243
|
+
source: eventData.source ?? 'community/agent',
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
lambdaClient.market.reportAgentEvent.mutate(payload).catch((error) => {
|
|
247
|
+
console.warn('Failed to report Agent event:', error);
|
|
248
|
+
});
|
|
249
|
+
};
|
|
250
|
+
|
|
214
251
|
// ============================== Models ==============================
|
|
215
252
|
|
|
216
253
|
getModelCategories = async (params: CategoryListQuery = {}): Promise<CategoryItem[]> => {
|
|
@@ -38,6 +38,11 @@ const n = setNamespace('t');
|
|
|
38
38
|
|
|
39
39
|
const SWR_USE_FETCH_TOPIC = 'SWR_USE_FETCH_TOPIC';
|
|
40
40
|
const SWR_USE_SEARCH_TOPIC = 'SWR_USE_SEARCH_TOPIC';
|
|
41
|
+
type CronTopicsGroupWithJobInfo = {
|
|
42
|
+
cronJob: unknown;
|
|
43
|
+
cronJobId: string;
|
|
44
|
+
topics: ChatTopic[];
|
|
45
|
+
};
|
|
41
46
|
|
|
42
47
|
/**
|
|
43
48
|
* Options for switchTopic action
|
|
@@ -91,6 +96,7 @@ export interface ChatTopicAction {
|
|
|
91
96
|
enable: boolean,
|
|
92
97
|
params: {
|
|
93
98
|
agentId?: string;
|
|
99
|
+
excludeTriggers?: string[];
|
|
94
100
|
groupId?: string;
|
|
95
101
|
isInbox?: boolean;
|
|
96
102
|
pageSize?: number;
|
|
@@ -282,7 +288,34 @@ export const chatTopic: StateCreator<
|
|
|
282
288
|
});
|
|
283
289
|
},
|
|
284
290
|
favoriteTopic: async (id, favorite) => {
|
|
291
|
+
const { activeAgentId } = get();
|
|
285
292
|
await get().internal_updateTopic(id, { favorite });
|
|
293
|
+
|
|
294
|
+
if (!activeAgentId) return;
|
|
295
|
+
|
|
296
|
+
await mutate(
|
|
297
|
+
['cronTopicsWithJobInfo', activeAgentId],
|
|
298
|
+
(groups?: CronTopicsGroupWithJobInfo[]) => {
|
|
299
|
+
if (!groups) return groups;
|
|
300
|
+
|
|
301
|
+
let updated = false;
|
|
302
|
+
const next = groups.map((group) => {
|
|
303
|
+
let groupUpdated = false;
|
|
304
|
+
const topics = group.topics.map((topic) => {
|
|
305
|
+
if (topic.id !== id) return topic;
|
|
306
|
+
if (topic.favorite === favorite) return topic;
|
|
307
|
+
groupUpdated = true;
|
|
308
|
+
updated = true;
|
|
309
|
+
return { ...topic, favorite };
|
|
310
|
+
});
|
|
311
|
+
|
|
312
|
+
return groupUpdated ? { ...group, topics } : group;
|
|
313
|
+
});
|
|
314
|
+
|
|
315
|
+
return updated ? next : groups;
|
|
316
|
+
},
|
|
317
|
+
{ revalidate: false },
|
|
318
|
+
);
|
|
286
319
|
},
|
|
287
320
|
|
|
288
321
|
updateTopicMetadata: async (id, metadata) => {
|
|
@@ -314,15 +347,28 @@ export const chatTopic: StateCreator<
|
|
|
314
347
|
},
|
|
315
348
|
|
|
316
349
|
// query
|
|
317
|
-
useFetchTopics: (
|
|
350
|
+
useFetchTopics: (
|
|
351
|
+
enable,
|
|
352
|
+
{ agentId, excludeTriggers, groupId, pageSize: customPageSize, isInbox },
|
|
353
|
+
) => {
|
|
318
354
|
const pageSize = customPageSize || 20;
|
|
355
|
+
const effectiveExcludeTriggers =
|
|
356
|
+
excludeTriggers && excludeTriggers.length > 0 ? excludeTriggers : undefined;
|
|
319
357
|
// Use topicMapKey to generate the container key for topic data map
|
|
320
358
|
const containerKey = topicMapKey({ agentId, groupId });
|
|
321
359
|
const hasValidContainer = !!(groupId || agentId);
|
|
322
360
|
|
|
323
361
|
return useClientDataSWRWithSync<{ items: ChatTopic[]; total: number }>(
|
|
324
362
|
enable && hasValidContainer
|
|
325
|
-
? [
|
|
363
|
+
? [
|
|
364
|
+
SWR_USE_FETCH_TOPIC,
|
|
365
|
+
containerKey,
|
|
366
|
+
{
|
|
367
|
+
isInbox,
|
|
368
|
+
pageSize,
|
|
369
|
+
...(effectiveExcludeTriggers ? { excludeTriggers: effectiveExcludeTriggers } : {}),
|
|
370
|
+
},
|
|
371
|
+
]
|
|
326
372
|
: null,
|
|
327
373
|
async () => {
|
|
328
374
|
// agentId, groupId, isInbox, pageSize come from the outer scope closure
|
|
@@ -343,6 +389,7 @@ export const chatTopic: StateCreator<
|
|
|
343
389
|
const result = await topicService.getTopics({
|
|
344
390
|
agentId,
|
|
345
391
|
current: 0,
|
|
392
|
+
excludeTriggers: effectiveExcludeTriggers,
|
|
346
393
|
groupId,
|
|
347
394
|
isInbox,
|
|
348
395
|
pageSize,
|
|
@@ -374,6 +421,7 @@ export const chatTopic: StateCreator<
|
|
|
374
421
|
...get().topicDataMap,
|
|
375
422
|
[containerKey]: {
|
|
376
423
|
currentPage: 0,
|
|
424
|
+
excludeTriggers: effectiveExcludeTriggers,
|
|
377
425
|
hasMore,
|
|
378
426
|
isExpandingPageSize: false,
|
|
379
427
|
items: topics,
|
|
@@ -413,9 +461,11 @@ export const chatTopic: StateCreator<
|
|
|
413
461
|
|
|
414
462
|
try {
|
|
415
463
|
const pageSize = useGlobalStore.getState().status.topicPageSize || 20;
|
|
464
|
+
const excludeTriggers = currentData?.excludeTriggers;
|
|
416
465
|
const result = await topicService.getTopics({
|
|
417
466
|
agentId: activeAgentId,
|
|
418
467
|
current: nextPage,
|
|
468
|
+
excludeTriggers,
|
|
419
469
|
groupId: activeGroupId,
|
|
420
470
|
pageSize,
|
|
421
471
|
});
|
|
@@ -429,6 +479,7 @@ export const chatTopic: StateCreator<
|
|
|
429
479
|
...get().topicDataMap,
|
|
430
480
|
[key]: {
|
|
431
481
|
currentPage: nextPage,
|
|
482
|
+
excludeTriggers,
|
|
432
483
|
hasMore,
|
|
433
484
|
isLoadingMore: false,
|
|
434
485
|
items: [...currentTopics, ...result.items],
|
|
@@ -18,27 +18,34 @@ const currentTopicData = (s: ChatStoreState): TopicData | undefined => {
|
|
|
18
18
|
|
|
19
19
|
const currentTopics = (s: ChatStoreState): ChatTopic[] | undefined => currentTopicData(s)?.items;
|
|
20
20
|
|
|
21
|
+
// Get topics without cron-triggered ones
|
|
22
|
+
const currentTopicsWithoutCron = (s: ChatStoreState): ChatTopic[] | undefined => {
|
|
23
|
+
const topics = currentTopics(s);
|
|
24
|
+
if (!topics) return undefined;
|
|
25
|
+
return topics.filter((topic) => topic.trigger !== 'cron');
|
|
26
|
+
};
|
|
27
|
+
|
|
21
28
|
const currentActiveTopic = (s: ChatStoreState): ChatTopic | undefined => {
|
|
22
29
|
return currentTopics(s)?.find((topic) => topic.id === s.activeTopicId);
|
|
23
30
|
};
|
|
24
31
|
const searchTopics = (s: ChatStoreState): ChatTopic[] => s.searchTopics;
|
|
25
32
|
|
|
26
|
-
const displayTopics = (s: ChatStoreState): ChatTopic[] | undefined =>
|
|
33
|
+
const displayTopics = (s: ChatStoreState): ChatTopic[] | undefined => currentTopicsWithoutCron(s);
|
|
27
34
|
|
|
28
35
|
const currentFavTopics = (s: ChatStoreState): ChatTopic[] =>
|
|
29
|
-
|
|
36
|
+
currentTopicsWithoutCron(s)?.filter((s) => s.favorite) || [];
|
|
30
37
|
|
|
31
38
|
const currentUnFavTopics = (s: ChatStoreState): ChatTopic[] =>
|
|
32
|
-
|
|
39
|
+
currentTopicsWithoutCron(s)?.filter((s) => !s.favorite) || [];
|
|
33
40
|
|
|
34
|
-
const currentTopicLength = (s: ChatStoreState): number =>
|
|
41
|
+
const currentTopicLength = (s: ChatStoreState): number => currentTopicsWithoutCron(s)?.length || 0;
|
|
35
42
|
|
|
36
43
|
const currentTopicCount = (s: ChatStoreState): number => currentTopicData(s)?.total || 0;
|
|
37
44
|
|
|
38
45
|
const getTopicById =
|
|
39
46
|
(id: string) =>
|
|
40
47
|
(s: ChatStoreState): ChatTopic | undefined =>
|
|
41
|
-
currentTopics(s)?.find((topic) => topic.id === id);
|
|
48
|
+
currentTopics(s)?.find((topic) => topic.id === id); // Don't filter here, need to access all topics by ID
|
|
42
49
|
|
|
43
50
|
/**
|
|
44
51
|
* Get topics by specific agentId (for AgentBuilder scenarios where agentId differs from activeAgentId)
|
|
@@ -79,7 +86,7 @@ const isSearchingTopic = (s: ChatStoreState) => s.isSearchingTopic;
|
|
|
79
86
|
const displayTopicsForSidebar =
|
|
80
87
|
(pageSize: number) =>
|
|
81
88
|
(s: ChatStoreState): ChatTopic[] | undefined => {
|
|
82
|
-
const topics =
|
|
89
|
+
const topics = currentTopicsWithoutCron(s);
|
|
83
90
|
if (!topics) return undefined;
|
|
84
91
|
|
|
85
92
|
// Return only the first page worth of topics for sidebar
|
|
@@ -143,6 +150,7 @@ export const topicSelectors = {
|
|
|
143
150
|
currentTopicLength,
|
|
144
151
|
currentTopicWorkingDirectory,
|
|
145
152
|
currentTopics,
|
|
153
|
+
currentTopicsWithoutCron,
|
|
146
154
|
currentUnFavTopics,
|
|
147
155
|
displayTopics,
|
|
148
156
|
displayTopicsForSidebar,
|
|
@@ -12,6 +12,37 @@ import { CheckMcpInstallResult, MCPInstallStep } from '@/types/plugins';
|
|
|
12
12
|
|
|
13
13
|
import { useToolStore } from '../../store';
|
|
14
14
|
|
|
15
|
+
vi.mock('@/libs/trpc/client', () => ({
|
|
16
|
+
asyncClient: {},
|
|
17
|
+
lambdaClient: {
|
|
18
|
+
market: {
|
|
19
|
+
getMcpCategories: { query: vi.fn() },
|
|
20
|
+
getMcpDetail: { query: vi.fn() },
|
|
21
|
+
getMcpList: { query: vi.fn() },
|
|
22
|
+
getMcpManifest: { query: vi.fn() },
|
|
23
|
+
registerClientInMarketplace: {
|
|
24
|
+
mutate: vi.fn().mockResolvedValue({
|
|
25
|
+
clientId: 'test-client-id',
|
|
26
|
+
clientSecret: 'test-client-secret',
|
|
27
|
+
}),
|
|
28
|
+
},
|
|
29
|
+
registerM2MToken: { query: vi.fn().mockResolvedValue({ success: true }) },
|
|
30
|
+
reportCall: { mutate: vi.fn().mockResolvedValue(undefined) },
|
|
31
|
+
reportMcpEvent: { mutate: vi.fn().mockResolvedValue(undefined) },
|
|
32
|
+
reportMcpInstallResult: { mutate: vi.fn().mockResolvedValue(undefined) },
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
toolsClient: {
|
|
36
|
+
market: {
|
|
37
|
+
callCloudMcpEndpoint: { mutate: vi.fn() },
|
|
38
|
+
},
|
|
39
|
+
mcp: {
|
|
40
|
+
callTool: { mutate: vi.fn() },
|
|
41
|
+
getStreamableMcpServerManifest: { query: vi.fn() },
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
}));
|
|
45
|
+
|
|
15
46
|
// Keep zustand mock as it's needed globally
|
|
16
47
|
vi.mock('zustand/traditional');
|
|
17
48
|
|
|
@@ -61,6 +92,13 @@ const bootstrapToolStoreWithDesktop = async (isDesktopEnv: boolean) => {
|
|
|
61
92
|
beforeEach(() => {
|
|
62
93
|
vi.clearAllMocks();
|
|
63
94
|
|
|
95
|
+
vi.spyOn(discoverService, 'injectMPToken').mockResolvedValue(undefined);
|
|
96
|
+
vi.spyOn(discoverService, 'registerClient').mockResolvedValue({
|
|
97
|
+
clientId: 'test-client-id',
|
|
98
|
+
clientSecret: 'test-client-secret',
|
|
99
|
+
});
|
|
100
|
+
vi.spyOn(discoverService, 'reportMcpEvent').mockResolvedValue(undefined as any);
|
|
101
|
+
|
|
64
102
|
// Reset store state
|
|
65
103
|
act(() => {
|
|
66
104
|
useToolStore.setState(
|
|
@@ -588,6 +588,12 @@ export const createMCPPluginStoreSlice: StateCreator<
|
|
|
588
588
|
// Calculate installation duration
|
|
589
589
|
const installDurationMs = Date.now() - installStartTime;
|
|
590
590
|
|
|
591
|
+
discoverService.reportMcpEvent({
|
|
592
|
+
event: 'install',
|
|
593
|
+
identifier: plugin.identifier,
|
|
594
|
+
source: 'self',
|
|
595
|
+
})
|
|
596
|
+
|
|
591
597
|
discoverService.reportMcpInstallResult({
|
|
592
598
|
identifier: plugin.identifier,
|
|
593
599
|
installDurationMs,
|
|
@@ -790,6 +796,12 @@ export const createMCPPluginStoreSlice: StateCreator<
|
|
|
790
796
|
n('testMcpConnection/success'),
|
|
791
797
|
);
|
|
792
798
|
|
|
799
|
+
discoverService.reportMcpEvent({
|
|
800
|
+
event: 'activate',
|
|
801
|
+
identifier: identifier,
|
|
802
|
+
source: 'self',
|
|
803
|
+
})
|
|
804
|
+
|
|
793
805
|
return { manifest, success: true };
|
|
794
806
|
} catch (error) {
|
|
795
807
|
// Silently handle errors caused by cancellation
|
|
@@ -817,6 +829,12 @@ export const createMCPPluginStoreSlice: StateCreator<
|
|
|
817
829
|
uninstallMCPPlugin: async (identifier) => {
|
|
818
830
|
await pluginService.uninstallPlugin(identifier);
|
|
819
831
|
await get().refreshPlugins();
|
|
832
|
+
|
|
833
|
+
discoverService.reportMcpEvent({
|
|
834
|
+
event: 'uninstall',
|
|
835
|
+
identifier: identifier,
|
|
836
|
+
source: 'self',
|
|
837
|
+
})
|
|
820
838
|
},
|
|
821
839
|
|
|
822
840
|
updateMCPInstallProgress: (identifier, progress) => {
|
|
@@ -4,10 +4,7 @@ import {
|
|
|
4
4
|
LocalSystemListFilesPlaceholder,
|
|
5
5
|
LocalSystemSearchFilesPlaceholder,
|
|
6
6
|
} from '@lobechat/builtin-tool-local-system/client';
|
|
7
|
-
import {
|
|
8
|
-
NotebookIdentifier,
|
|
9
|
-
NotebookPlaceholders,
|
|
10
|
-
} from '@lobechat/builtin-tool-notebook/client';
|
|
7
|
+
import { NotebookIdentifier, NotebookPlaceholders } from '@lobechat/builtin-tool-notebook/client';
|
|
11
8
|
import {
|
|
12
9
|
WebBrowsingManifest,
|
|
13
10
|
WebBrowsingPlaceholders,
|