@lobehub/lobehub 2.0.0-next.347 → 2.0.0-next.349
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 +53 -0
- package/changelog/v1.json +18 -0
- package/package.json +1 -1
- package/packages/builtin-tool-group-agent-builder/src/client/Inspector/BatchCreateAgents/index.tsx +1 -1
- package/packages/database/src/models/__tests__/topics/topic.create.test.ts +124 -1
- package/packages/database/src/models/topic.ts +82 -20
- package/src/app/[variants]/(main)/community/(detail)/group_agent/features/Sidebar/ActionButton/ForkGroupAndChat.tsx +1 -1
- package/src/features/Conversation/Messages/AgentCouncil/components/CouncilList.tsx +2 -2
- package/src/features/PageEditor/Copilot/Toolbar.tsx +21 -5
- package/src/features/ProfileEditor/AgentTool.tsx +3 -2
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,59 @@
|
|
|
2
2
|
|
|
3
3
|
# Changelog
|
|
4
4
|
|
|
5
|
+
## [Version 2.0.0-next.349](https://github.com/lobehub/lobe-chat/compare/v2.0.0-next.348...v2.0.0-next.349)
|
|
6
|
+
|
|
7
|
+
<sup>Released on **2026-01-23**</sup>
|
|
8
|
+
|
|
9
|
+
#### 🐛 Bug Fixes
|
|
10
|
+
|
|
11
|
+
- **misc**: When use market group, the group sys role was not used.
|
|
12
|
+
|
|
13
|
+
<br/>
|
|
14
|
+
|
|
15
|
+
<details>
|
|
16
|
+
<summary><kbd>Improvements and Fixes</kbd></summary>
|
|
17
|
+
|
|
18
|
+
#### What's fixed
|
|
19
|
+
|
|
20
|
+
- **misc**: When use market group, the group sys role was not used, closes [#11739](https://github.com/lobehub/lobe-chat/issues/11739) ([afc76f9](https://github.com/lobehub/lobe-chat/commit/afc76f9))
|
|
21
|
+
|
|
22
|
+
</details>
|
|
23
|
+
|
|
24
|
+
<div align="right">
|
|
25
|
+
|
|
26
|
+
[](#readme-top)
|
|
27
|
+
|
|
28
|
+
</div>
|
|
29
|
+
|
|
30
|
+
## [Version 2.0.0-next.348](https://github.com/lobehub/lobe-chat/compare/v2.0.0-next.347...v2.0.0-next.348)
|
|
31
|
+
|
|
32
|
+
<sup>Released on **2026-01-23**</sup>
|
|
33
|
+
|
|
34
|
+
#### 🐛 Bug Fixes
|
|
35
|
+
|
|
36
|
+
- **copilot**: History popover not refreshing when agentId changes.
|
|
37
|
+
- **misc**: Fixed the agent group builder tools excaution edge case crash, fixed the group topic copy not right.
|
|
38
|
+
|
|
39
|
+
<br/>
|
|
40
|
+
|
|
41
|
+
<details>
|
|
42
|
+
<summary><kbd>Improvements and Fixes</kbd></summary>
|
|
43
|
+
|
|
44
|
+
#### What's fixed
|
|
45
|
+
|
|
46
|
+
- **copilot**: History popover not refreshing when agentId changes, closes [#11731](https://github.com/lobehub/lobe-chat/issues/11731) ([64f39e7](https://github.com/lobehub/lobe-chat/commit/64f39e7))
|
|
47
|
+
- **misc**: Fixed the agent group builder tools excaution edge case crash, closes [#11735](https://github.com/lobehub/lobe-chat/issues/11735) ([5de4742](https://github.com/lobehub/lobe-chat/commit/5de4742))
|
|
48
|
+
- **misc**: Fixed the group topic copy not right, closes [#11730](https://github.com/lobehub/lobe-chat/issues/11730) ([282c1fb](https://github.com/lobehub/lobe-chat/commit/282c1fb))
|
|
49
|
+
|
|
50
|
+
</details>
|
|
51
|
+
|
|
52
|
+
<div align="right">
|
|
53
|
+
|
|
54
|
+
[](#readme-top)
|
|
55
|
+
|
|
56
|
+
</div>
|
|
57
|
+
|
|
5
58
|
## [Version 2.0.0-next.347](https://github.com/lobehub/lobe-chat/compare/v2.0.0-next.346...v2.0.0-next.347)
|
|
6
59
|
|
|
7
60
|
<sup>Released on **2026-01-23**</sup>
|
package/changelog/v1.json
CHANGED
|
@@ -1,4 +1,22 @@
|
|
|
1
1
|
[
|
|
2
|
+
{
|
|
3
|
+
"children": {
|
|
4
|
+
"fixes": [
|
|
5
|
+
"When use market group, the group sys role was not used."
|
|
6
|
+
]
|
|
7
|
+
},
|
|
8
|
+
"date": "2026-01-23",
|
|
9
|
+
"version": "2.0.0-next.349"
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
"children": {
|
|
13
|
+
"fixes": [
|
|
14
|
+
"Fixed the agent group builder tools excaution edge case crash, fixed the group topic copy not right."
|
|
15
|
+
]
|
|
16
|
+
},
|
|
17
|
+
"date": "2026-01-23",
|
|
18
|
+
"version": "2.0.0-next.348"
|
|
19
|
+
},
|
|
2
20
|
{
|
|
3
21
|
"children": {
|
|
4
22
|
"fixes": [
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lobehub/lobehub",
|
|
3
|
-
"version": "2.0.0-next.
|
|
3
|
+
"version": "2.0.0-next.349",
|
|
4
4
|
"description": "LobeHub - an open-source,comprehensive AI Agent framework that supports speech synthesis, multimodal, and extensible Function Call plugin system. Supports one-click free deployment of your private ChatGPT/LLM web application.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"framework",
|
package/packages/builtin-tool-group-agent-builder/src/client/Inspector/BatchCreateAgents/index.tsx
CHANGED
|
@@ -81,7 +81,7 @@ export const BatchCreateAgentsInspector = memo<
|
|
|
81
81
|
{displayInfo && (
|
|
82
82
|
<>
|
|
83
83
|
<div className={styles.avatarGroup}>
|
|
84
|
-
{displayInfo.displayAgents
|
|
84
|
+
{displayInfo.displayAgents?.map((agent, index) => (
|
|
85
85
|
<Avatar
|
|
86
86
|
avatar={agent.avatar}
|
|
87
87
|
key={index}
|
|
@@ -2,7 +2,7 @@ import { eq, inArray } from 'drizzle-orm';
|
|
|
2
2
|
import { afterEach, beforeEach, describe, expect, it } from 'vitest';
|
|
3
3
|
|
|
4
4
|
import { getTestDB } from '../../../core/getTestDB';
|
|
5
|
-
import { agents, messages, sessions, topics, users } from '../../../schemas';
|
|
5
|
+
import { agents, messagePlugins, messages, sessions, topics, users } from '../../../schemas';
|
|
6
6
|
import { LobeChatDatabase } from '../../../type';
|
|
7
7
|
import { CreateTopicParams, TopicModel } from '../../topic';
|
|
8
8
|
|
|
@@ -279,6 +279,129 @@ describe('TopicModel - Create', () => {
|
|
|
279
279
|
expect(duplicatedMessages[1].content).toBe('Assistant message');
|
|
280
280
|
});
|
|
281
281
|
|
|
282
|
+
it('should correctly map parentId references when duplicating messages', async () => {
|
|
283
|
+
const topicId = 'topic-with-parent-refs';
|
|
284
|
+
|
|
285
|
+
await serverDB.transaction(async (tx) => {
|
|
286
|
+
await tx.insert(topics).values({ id: topicId, sessionId, userId, title: 'Original Topic' });
|
|
287
|
+
await tx.insert(messages).values([
|
|
288
|
+
{ id: 'msg1', role: 'user', topicId, userId, content: 'First message', parentId: null },
|
|
289
|
+
{
|
|
290
|
+
id: 'msg2',
|
|
291
|
+
role: 'assistant',
|
|
292
|
+
topicId,
|
|
293
|
+
userId,
|
|
294
|
+
content: 'Reply to first',
|
|
295
|
+
parentId: 'msg1',
|
|
296
|
+
},
|
|
297
|
+
{
|
|
298
|
+
id: 'msg3',
|
|
299
|
+
role: 'tool',
|
|
300
|
+
topicId,
|
|
301
|
+
userId,
|
|
302
|
+
content: 'Tool response',
|
|
303
|
+
parentId: 'msg2',
|
|
304
|
+
},
|
|
305
|
+
{
|
|
306
|
+
id: 'msg4',
|
|
307
|
+
role: 'assistant',
|
|
308
|
+
topicId,
|
|
309
|
+
userId,
|
|
310
|
+
content: 'Final message',
|
|
311
|
+
parentId: 'msg3',
|
|
312
|
+
},
|
|
313
|
+
]);
|
|
314
|
+
});
|
|
315
|
+
|
|
316
|
+
const { topic: duplicatedTopic, messages: duplicatedMessages } = await topicModel.duplicate(
|
|
317
|
+
topicId,
|
|
318
|
+
'Duplicated Topic',
|
|
319
|
+
);
|
|
320
|
+
|
|
321
|
+
expect(duplicatedMessages).toHaveLength(4);
|
|
322
|
+
|
|
323
|
+
const msgMap = new Map(duplicatedMessages.map((m) => [m.content, m]));
|
|
324
|
+
const newMsg1 = msgMap.get('First message')!;
|
|
325
|
+
const newMsg2 = msgMap.get('Reply to first')!;
|
|
326
|
+
const newMsg3 = msgMap.get('Tool response')!;
|
|
327
|
+
const newMsg4 = msgMap.get('Final message')!;
|
|
328
|
+
|
|
329
|
+
expect(newMsg1.parentId).toBeNull();
|
|
330
|
+
expect(newMsg2.parentId).toBe(newMsg1.id);
|
|
331
|
+
expect(newMsg3.parentId).toBe(newMsg2.id);
|
|
332
|
+
expect(newMsg4.parentId).toBe(newMsg3.id);
|
|
333
|
+
|
|
334
|
+
expect(newMsg1.id).not.toBe('msg1');
|
|
335
|
+
expect(newMsg2.id).not.toBe('msg2');
|
|
336
|
+
expect(newMsg3.id).not.toBe('msg3');
|
|
337
|
+
expect(newMsg4.id).not.toBe('msg4');
|
|
338
|
+
});
|
|
339
|
+
|
|
340
|
+
it('should correctly map tool_call_id when duplicating messages with tools', async () => {
|
|
341
|
+
const topicId = 'topic-with-tools';
|
|
342
|
+
const originalToolId = 'toolu_original_123';
|
|
343
|
+
|
|
344
|
+
await serverDB.transaction(async (tx) => {
|
|
345
|
+
await tx.insert(topics).values({ id: topicId, sessionId, userId, title: 'Original Topic' });
|
|
346
|
+
|
|
347
|
+
// Insert assistant message with tools
|
|
348
|
+
await tx.insert(messages).values({
|
|
349
|
+
id: 'msg1',
|
|
350
|
+
role: 'assistant',
|
|
351
|
+
topicId,
|
|
352
|
+
userId,
|
|
353
|
+
content: 'Using tool',
|
|
354
|
+
parentId: null,
|
|
355
|
+
tools: [{ id: originalToolId, type: 'builtin', apiName: 'broadcast' }],
|
|
356
|
+
});
|
|
357
|
+
|
|
358
|
+
// Insert tool message
|
|
359
|
+
await tx.insert(messages).values({
|
|
360
|
+
id: 'msg2',
|
|
361
|
+
role: 'tool',
|
|
362
|
+
topicId,
|
|
363
|
+
userId,
|
|
364
|
+
content: 'Tool response',
|
|
365
|
+
parentId: 'msg1',
|
|
366
|
+
});
|
|
367
|
+
|
|
368
|
+
// Insert messagePlugins entry
|
|
369
|
+
await tx.insert(messagePlugins).values({
|
|
370
|
+
id: 'msg2',
|
|
371
|
+
userId,
|
|
372
|
+
toolCallId: originalToolId,
|
|
373
|
+
apiName: 'broadcast',
|
|
374
|
+
});
|
|
375
|
+
});
|
|
376
|
+
|
|
377
|
+
const { topic: duplicatedTopic, messages: duplicatedMessages } = await topicModel.duplicate(
|
|
378
|
+
topicId,
|
|
379
|
+
'Duplicated Topic',
|
|
380
|
+
);
|
|
381
|
+
|
|
382
|
+
expect(duplicatedMessages).toHaveLength(2);
|
|
383
|
+
|
|
384
|
+
const msgMap = new Map(duplicatedMessages.map((m) => [m.role, m]));
|
|
385
|
+
const newAssistant = msgMap.get('assistant')!;
|
|
386
|
+
const newTool = msgMap.get('tool')!;
|
|
387
|
+
|
|
388
|
+
// Check that tools array has new IDs
|
|
389
|
+
expect(newAssistant.tools).toBeDefined();
|
|
390
|
+
const newTools = newAssistant.tools as any[];
|
|
391
|
+
expect(newTools).toHaveLength(1);
|
|
392
|
+
expect(newTools[0].id).not.toBe(originalToolId);
|
|
393
|
+
expect(newTools[0].id).toMatch(/^toolu_/);
|
|
394
|
+
|
|
395
|
+
// Check that messagePlugins was copied with new toolCallId
|
|
396
|
+
const newPlugin = await serverDB.query.messagePlugins.findFirst({
|
|
397
|
+
where: eq(messagePlugins.id, newTool.id),
|
|
398
|
+
});
|
|
399
|
+
|
|
400
|
+
expect(newPlugin).toBeDefined();
|
|
401
|
+
expect(newPlugin!.toolCallId).toBe(newTools[0].id);
|
|
402
|
+
expect(newPlugin!.toolCallId).not.toBe(originalToolId);
|
|
403
|
+
});
|
|
404
|
+
|
|
282
405
|
it('should throw an error if the topic to duplicate does not exist', async () => {
|
|
283
406
|
const topicId = 'nonexistent-topic';
|
|
284
407
|
|
|
@@ -17,7 +17,14 @@ import {
|
|
|
17
17
|
sql,
|
|
18
18
|
} from 'drizzle-orm';
|
|
19
19
|
|
|
20
|
-
import {
|
|
20
|
+
import {
|
|
21
|
+
TopicItem,
|
|
22
|
+
agents,
|
|
23
|
+
agentsToSessions,
|
|
24
|
+
messagePlugins,
|
|
25
|
+
messages,
|
|
26
|
+
topics,
|
|
27
|
+
} from '../schemas';
|
|
21
28
|
import { LobeChatDatabase } from '../type';
|
|
22
29
|
import { genEndDateWhere, genRangeWhere, genStartDateWhere, genWhere } from '../utils/genWhere';
|
|
23
30
|
import { idGenerator } from '../utils/idGenerator';
|
|
@@ -498,28 +505,83 @@ export class TopicModel {
|
|
|
498
505
|
})
|
|
499
506
|
.returning();
|
|
500
507
|
|
|
501
|
-
// Find messages associated with the original topic
|
|
508
|
+
// Find messages associated with the original topic, ordered by createdAt
|
|
502
509
|
const originalMessages = await tx
|
|
503
510
|
.select()
|
|
504
511
|
.from(messages)
|
|
505
|
-
.where(and(eq(messages.topicId, topicId), eq(messages.userId, this.userId)))
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
id
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
);
|
|
512
|
+
.where(and(eq(messages.topicId, topicId), eq(messages.userId, this.userId)))
|
|
513
|
+
.orderBy(messages.createdAt);
|
|
514
|
+
|
|
515
|
+
// Find all messagePlugins for this topic
|
|
516
|
+
const messageIds = originalMessages.map((m) => m.id);
|
|
517
|
+
const originalPlugins =
|
|
518
|
+
messageIds.length > 0
|
|
519
|
+
? await tx
|
|
520
|
+
.select()
|
|
521
|
+
.from(messagePlugins)
|
|
522
|
+
.where(inArray(messagePlugins.id, messageIds))
|
|
523
|
+
: [];
|
|
524
|
+
|
|
525
|
+
// Build oldId -> newId mapping for messages
|
|
526
|
+
const idMap = new Map<string, string>();
|
|
527
|
+
originalMessages.forEach((message) => {
|
|
528
|
+
idMap.set(message.id, idGenerator('messages'));
|
|
529
|
+
});
|
|
530
|
+
|
|
531
|
+
// Build oldToolId -> newToolId mapping for tools
|
|
532
|
+
const toolIdMap = new Map<string, string>();
|
|
533
|
+
originalMessages.forEach((message) => {
|
|
534
|
+
if (message.tools && Array.isArray(message.tools)) {
|
|
535
|
+
(message.tools as any[]).forEach((tool: any) => {
|
|
536
|
+
if (tool.id) {
|
|
537
|
+
toolIdMap.set(tool.id, `toolu_${idGenerator('messages')}`);
|
|
538
|
+
}
|
|
539
|
+
});
|
|
540
|
+
}
|
|
541
|
+
});
|
|
542
|
+
|
|
543
|
+
// copy messages sequentially to respect foreign key constraints
|
|
544
|
+
const duplicatedMessages: DBMessageItem[] = [];
|
|
545
|
+
for (const message of originalMessages) {
|
|
546
|
+
const newId = idMap.get(message.id)!;
|
|
547
|
+
const newParentId = message.parentId ? idMap.get(message.parentId) || null : null;
|
|
548
|
+
|
|
549
|
+
// Update tool IDs in tools array
|
|
550
|
+
let newTools = message.tools;
|
|
551
|
+
if (newTools && Array.isArray(newTools)) {
|
|
552
|
+
newTools = (newTools as any[]).map((tool: any) => ({
|
|
553
|
+
...tool,
|
|
554
|
+
id: tool.id ? toolIdMap.get(tool.id) || tool.id : tool.id,
|
|
555
|
+
}));
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
const result = (await tx
|
|
559
|
+
.insert(messages)
|
|
560
|
+
.values({
|
|
561
|
+
...message,
|
|
562
|
+
clientId: null,
|
|
563
|
+
id: newId,
|
|
564
|
+
parentId: newParentId,
|
|
565
|
+
topicId: duplicatedTopic.id,
|
|
566
|
+
tools: newTools,
|
|
567
|
+
})
|
|
568
|
+
.returning()) as DBMessageItem[];
|
|
569
|
+
|
|
570
|
+
duplicatedMessages.push(result[0]);
|
|
571
|
+
|
|
572
|
+
// Copy messagePlugins if exists for this message
|
|
573
|
+
const plugin = originalPlugins.find((p) => p.id === message.id);
|
|
574
|
+
if (plugin) {
|
|
575
|
+
const newToolCallId = plugin.toolCallId ? toolIdMap.get(plugin.toolCallId) || null : null;
|
|
576
|
+
|
|
577
|
+
await tx.insert(messagePlugins).values({
|
|
578
|
+
...plugin,
|
|
579
|
+
id: newId,
|
|
580
|
+
clientId: null,
|
|
581
|
+
toolCallId: newToolCallId,
|
|
582
|
+
});
|
|
583
|
+
}
|
|
584
|
+
}
|
|
523
585
|
|
|
524
586
|
return {
|
|
525
587
|
messages: duplicatedMessages,
|
|
@@ -130,7 +130,7 @@ const ForkGroupAndChat = memo<{ mobile?: boolean }>(() => {
|
|
|
130
130
|
forkedFromIdentifier: identifier, // Store the source group identifier
|
|
131
131
|
},
|
|
132
132
|
// Group content is the supervisor's systemRole (for backward compatibility)
|
|
133
|
-
content:
|
|
133
|
+
content: config.systemRole || supervisorConfig?.systemRole,
|
|
134
134
|
...meta,
|
|
135
135
|
};
|
|
136
136
|
|
|
@@ -62,7 +62,7 @@ const CouncilList = memo<CouncilListProps>(({ members, displayMode, activeTab })
|
|
|
62
62
|
minWidth: MIN_WIDTH * members.length + 32 + 32 * (members.length - 1),
|
|
63
63
|
}}
|
|
64
64
|
>
|
|
65
|
-
{members
|
|
65
|
+
{members?.map((member, idx) => {
|
|
66
66
|
if (!member) return null;
|
|
67
67
|
return (
|
|
68
68
|
<Fragment key={member.id}>
|
|
@@ -77,7 +77,7 @@ const CouncilList = memo<CouncilListProps>(({ members, displayMode, activeTab })
|
|
|
77
77
|
>
|
|
78
78
|
<CouncilMember index={idx} item={member} />
|
|
79
79
|
</Flexbox>
|
|
80
|
-
{idx < members
|
|
80
|
+
{idx < members?.length - 1 && (
|
|
81
81
|
<Divider
|
|
82
82
|
dashed
|
|
83
83
|
orientation={'vertical'}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ActionIcon, Block, Flexbox, Popover } from '@lobehub/ui';
|
|
2
2
|
import { createStaticStyles, cx } from 'antd-style';
|
|
3
3
|
import { ChevronsUpDownIcon, Clock3Icon, PanelRightCloseIcon, PlusIcon } from 'lucide-react';
|
|
4
|
-
import { Suspense, memo, useMemo, useState } from 'react';
|
|
4
|
+
import { Suspense, memo, useCallback, useMemo, useState } from 'react';
|
|
5
5
|
import { useTranslation } from 'react-i18next';
|
|
6
6
|
|
|
7
7
|
import AgentAvatar from '@/app/[variants]/(main)/home/_layout/Body/Agent/List/AgentItem/Avatar';
|
|
@@ -164,6 +164,15 @@ const CopilotToolbar = memo<CopilotToolbarProps>(({ agentId, isHovered }) => {
|
|
|
164
164
|
const setActiveAgentId = useAgentStore((s) => s.setActiveAgentId);
|
|
165
165
|
const [topicPopoverOpen, setTopicPopoverOpen] = useState(false);
|
|
166
166
|
|
|
167
|
+
const handleAgentChange = useCallback(
|
|
168
|
+
(id: string) => {
|
|
169
|
+
setActiveAgentId(id);
|
|
170
|
+
// Sync chatStore's activeAgentId to ensure topic selectors work correctly
|
|
171
|
+
useChatStore.setState({ activeAgentId: id });
|
|
172
|
+
},
|
|
173
|
+
[setActiveAgentId],
|
|
174
|
+
);
|
|
175
|
+
|
|
167
176
|
// Fetch topics for the agent builder
|
|
168
177
|
useChatStore((s) => s.useFetchTopics)(true, { agentId });
|
|
169
178
|
|
|
@@ -175,13 +184,15 @@ const CopilotToolbar = memo<CopilotToolbarProps>(({ agentId, isHovered }) => {
|
|
|
175
184
|
|
|
176
185
|
const [toggleRightPanel] = useGlobalStore((s) => [s.toggleRightPanel]);
|
|
177
186
|
|
|
178
|
-
|
|
187
|
+
// topics === undefined means still loading, topics.length === 0 means confirmed empty
|
|
188
|
+
const isLoadingTopics = topics === undefined;
|
|
189
|
+
const hideHistory = !isLoadingTopics && topics.length === 0;
|
|
179
190
|
|
|
180
191
|
return (
|
|
181
192
|
<NavHeader
|
|
182
193
|
left={
|
|
183
194
|
<Flexbox align="center" gap={8} horizontal>
|
|
184
|
-
<AgentSelector agentId={agentId} onAgentChange={
|
|
195
|
+
<AgentSelector agentId={agentId} onAgentChange={handleAgentChange} />
|
|
185
196
|
</Flexbox>
|
|
186
197
|
}
|
|
187
198
|
right={
|
|
@@ -218,7 +229,7 @@ const CopilotToolbar = memo<CopilotToolbarProps>(({ agentId, isHovered }) => {
|
|
|
218
229
|
</Flexbox>
|
|
219
230
|
}
|
|
220
231
|
onOpenChange={setTopicPopoverOpen}
|
|
221
|
-
open={topicPopoverOpen}
|
|
232
|
+
open={isLoadingTopics ? false : topicPopoverOpen}
|
|
222
233
|
placement="bottomRight"
|
|
223
234
|
styles={{
|
|
224
235
|
content: {
|
|
@@ -228,7 +239,12 @@ const CopilotToolbar = memo<CopilotToolbarProps>(({ agentId, isHovered }) => {
|
|
|
228
239
|
}}
|
|
229
240
|
trigger="click"
|
|
230
241
|
>
|
|
231
|
-
<ActionIcon
|
|
242
|
+
<ActionIcon
|
|
243
|
+
disabled={isLoadingTopics}
|
|
244
|
+
icon={Clock3Icon}
|
|
245
|
+
loading={isLoadingTopics}
|
|
246
|
+
size={DESKTOP_HEADER_ICON_SIZE}
|
|
247
|
+
/>
|
|
232
248
|
</Popover>
|
|
233
249
|
)}
|
|
234
250
|
</div>
|
|
@@ -35,7 +35,6 @@ import { type LobeToolMetaWithAvailability } from '@/store/tool/slices/builtin/s
|
|
|
35
35
|
|
|
36
36
|
import PluginTag from './PluginTag';
|
|
37
37
|
|
|
38
|
-
|
|
39
38
|
const WEB_BROWSING_IDENTIFIER = 'lobe-web-browsing';
|
|
40
39
|
|
|
41
40
|
type TabType = 'all' | 'installed';
|
|
@@ -334,7 +333,9 @@ const AgentTool = memo<AgentToolProps>(
|
|
|
334
333
|
() => [
|
|
335
334
|
// 原有的 builtin 工具
|
|
336
335
|
...filteredBuiltinList.map((item) => ({
|
|
337
|
-
icon:
|
|
336
|
+
icon: (
|
|
337
|
+
<Avatar avatar={item.meta.avatar} size={20} style={{ flex: 'none', marginRight: 0 }} />
|
|
338
|
+
),
|
|
338
339
|
key: item.identifier,
|
|
339
340
|
label: (
|
|
340
341
|
<ToolItem
|