@lobehub/lobehub 2.0.2 → 2.0.3
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 +26 -0
- package/changelog/v2.json +9 -0
- package/locales/en-US/setting.json +2 -0
- package/locales/zh-CN/setting.json +2 -0
- package/package.json +2 -2
- package/packages/agent-runtime/src/agents/GeneralChatAgent.ts +18 -14
- package/packages/agent-runtime/src/types/generalAgent.ts +5 -4
- package/src/features/ChatInput/ActionBar/Params/Controls.tsx +17 -1
- package/src/features/ModelSelect/index.tsx +1 -1
- package/src/locales/default/setting.ts +3 -0
- package/src/server/services/agentRuntime/AgentRuntimeService.ts +4 -2
- package/src/store/chat/slices/aiChat/actions/streamingExecutor.ts +3 -0
- package/src/store/chat/slices/message/selectors/displayMessage.test.ts +21 -0
- package/src/store/chat/slices/message/selectors/displayMessage.ts +7 -2
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,32 @@
|
|
|
2
2
|
|
|
3
3
|
# Changelog
|
|
4
4
|
|
|
5
|
+
### [Version 2.0.3](https://github.com/lobehub/lobe-chat/compare/v2.0.2...v2.0.3)
|
|
6
|
+
|
|
7
|
+
<sup>Released on **2026-01-27**</sup>
|
|
8
|
+
|
|
9
|
+
#### 🐛 Bug Fixes
|
|
10
|
+
|
|
11
|
+
- **misc**: Fixed compressed group message & open the switch config to control compression config enabled, fixed the onboarding crash problem.
|
|
12
|
+
|
|
13
|
+
<br/>
|
|
14
|
+
|
|
15
|
+
<details>
|
|
16
|
+
<summary><kbd>Improvements and Fixes</kbd></summary>
|
|
17
|
+
|
|
18
|
+
#### What's fixed
|
|
19
|
+
|
|
20
|
+
- **misc**: Fixed compressed group message & open the switch config to control compression config enabled, closes [#11901](https://github.com/lobehub/lobe-chat/issues/11901) ([dc51838](https://github.com/lobehub/lobe-chat/commit/dc51838))
|
|
21
|
+
- **misc**: Fixed the onboarding crash problem, closes [#11905](https://github.com/lobehub/lobe-chat/issues/11905) ([439e4ee](https://github.com/lobehub/lobe-chat/commit/439e4ee))
|
|
22
|
+
|
|
23
|
+
</details>
|
|
24
|
+
|
|
25
|
+
<div align="right">
|
|
26
|
+
|
|
27
|
+
[](#readme-top)
|
|
28
|
+
|
|
29
|
+
</div>
|
|
30
|
+
|
|
5
31
|
### [Version 2.0.2](https://github.com/lobehub/lobe-chat/compare/v2.0.1...v2.0.2)
|
|
6
32
|
|
|
7
33
|
<sup>Released on **2026-01-27**</sup>
|
package/changelog/v2.json
CHANGED
|
@@ -1,4 +1,13 @@
|
|
|
1
1
|
[
|
|
2
|
+
{
|
|
3
|
+
"children": {
|
|
4
|
+
"fixes": [
|
|
5
|
+
"Fixed compressed group message & open the switch config to control compression config enabled, fixed the onboarding crash problem."
|
|
6
|
+
]
|
|
7
|
+
},
|
|
8
|
+
"date": "2026-01-27",
|
|
9
|
+
"version": "2.0.3"
|
|
10
|
+
},
|
|
2
11
|
{
|
|
3
12
|
"children": {
|
|
4
13
|
"fixes": [
|
|
@@ -446,6 +446,8 @@
|
|
|
446
446
|
"settingImage.defaultCount.desc": "Set the default number of images generated when creating a new task in the image generation panel.",
|
|
447
447
|
"settingImage.defaultCount.label": "Default Image Count",
|
|
448
448
|
"settingImage.defaultCount.title": "AI Art",
|
|
449
|
+
"settingModel.enableContextCompression.desc": "Automatically compress historical messages into summaries when conversation exceeds 64,000 tokens, saving 60-80% token usage",
|
|
450
|
+
"settingModel.enableContextCompression.title": "Enable Auto Context Compression",
|
|
449
451
|
"settingModel.enableMaxTokens.title": "Enable Max Tokens Limit",
|
|
450
452
|
"settingModel.enableReasoningEffort.title": "Enable Reasoning Effort Adjustment",
|
|
451
453
|
"settingModel.frequencyPenalty.desc": "The higher the value, the more diverse and rich the vocabulary; the lower the value, the simpler and more straightforward the language.",
|
|
@@ -446,6 +446,8 @@
|
|
|
446
446
|
"settingImage.defaultCount.desc": "设置图像生成面板在创建新任务时的默认图片数量。",
|
|
447
447
|
"settingImage.defaultCount.label": "默认图片数量",
|
|
448
448
|
"settingImage.defaultCount.title": "AI 绘画设置",
|
|
449
|
+
"settingModel.enableContextCompression.desc": "当对话消息超过 64,000 tokens 时,自动将历史消息压缩为摘要,节省 60-80% 的 token 用量",
|
|
450
|
+
"settingModel.enableContextCompression.title": "开启自动上下文压缩",
|
|
449
451
|
"settingModel.enableMaxTokens.title": "开启单次回复限制",
|
|
450
452
|
"settingModel.enableReasoningEffort.title": "开启推理强度调整",
|
|
451
453
|
"settingModel.frequencyPenalty.desc": "值越大,用词越丰富多样;值越低,用词更朴实简单",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lobehub/lobehub",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.3",
|
|
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",
|
|
@@ -328,7 +328,7 @@
|
|
|
328
328
|
"remark-gfm": "^4.0.1",
|
|
329
329
|
"remark-html": "^16.0.1",
|
|
330
330
|
"remove-markdown": "^0.6.3",
|
|
331
|
-
"resend": "
|
|
331
|
+
"resend": "6.8.0",
|
|
332
332
|
"resolve-accept-language": "^3.1.15",
|
|
333
333
|
"rtl-detect": "^1.1.2",
|
|
334
334
|
"semver": "^7.7.3",
|
|
@@ -283,21 +283,25 @@ export class GeneralChatAgent implements Agent {
|
|
|
283
283
|
switch (context.phase) {
|
|
284
284
|
case 'init':
|
|
285
285
|
case 'user_input': {
|
|
286
|
-
// Check if context compression is needed before calling LLM
|
|
287
|
-
const
|
|
288
|
-
maxWindowToken: this.config.compressionConfig?.maxWindowToken,
|
|
289
|
-
});
|
|
286
|
+
// Check if context compression is enabled and needed before calling LLM
|
|
287
|
+
const compressionEnabled = this.config.compressionConfig?.enabled ?? true; // Default to enabled
|
|
290
288
|
|
|
291
|
-
if (
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
289
|
+
if (compressionEnabled) {
|
|
290
|
+
const compressionCheck = shouldCompress(state.messages, {
|
|
291
|
+
maxWindowToken: this.config.compressionConfig?.maxWindowToken,
|
|
292
|
+
});
|
|
293
|
+
|
|
294
|
+
if (compressionCheck.needsCompression) {
|
|
295
|
+
// Context exceeds threshold, compress ALL messages into a single summary
|
|
296
|
+
return {
|
|
297
|
+
payload: {
|
|
298
|
+
currentTokenCount: compressionCheck.currentTokenCount,
|
|
299
|
+
existingSummary: this.findExistingSummary(state.messages),
|
|
300
|
+
messages: state.messages,
|
|
301
|
+
},
|
|
302
|
+
type: 'compress_context',
|
|
303
|
+
} as AgentInstructionCompressContext;
|
|
304
|
+
}
|
|
301
305
|
}
|
|
302
306
|
|
|
303
307
|
// User input received, call LLM to generate response
|
|
@@ -69,16 +69,15 @@ export interface GeneralAgentConfig {
|
|
|
69
69
|
};
|
|
70
70
|
/**
|
|
71
71
|
* Context compression configuration
|
|
72
|
-
*
|
|
73
|
-
* When triggered, ALL messages are compressed into a single MessageGroup summary.
|
|
72
|
+
* When enabled and triggered, ALL messages are compressed into a single MessageGroup summary.
|
|
74
73
|
*/
|
|
75
74
|
compressionConfig?: {
|
|
75
|
+
/** Whether context compression is enabled (default: true) */
|
|
76
|
+
enabled?: boolean;
|
|
76
77
|
/** Model's max context window token count (default: 128k) */
|
|
77
78
|
maxWindowToken?: number;
|
|
78
79
|
};
|
|
79
80
|
modelRuntimeConfig?: {
|
|
80
|
-
model: string;
|
|
81
|
-
provider: string;
|
|
82
81
|
/**
|
|
83
82
|
* Compression model configuration
|
|
84
83
|
* Used for context compression tasks
|
|
@@ -87,6 +86,8 @@ export interface GeneralAgentConfig {
|
|
|
87
86
|
model: string;
|
|
88
87
|
provider: string;
|
|
89
88
|
};
|
|
89
|
+
model: string;
|
|
90
|
+
provider: string;
|
|
90
91
|
};
|
|
91
92
|
operationId: string;
|
|
92
93
|
userId?: string;
|
|
@@ -320,7 +320,23 @@ const Controls = memo<ControlsProps>(({ setUpdating }) => {
|
|
|
320
320
|
: []),
|
|
321
321
|
];
|
|
322
322
|
|
|
323
|
-
|
|
323
|
+
// Context Compression items
|
|
324
|
+
const contextCompressionItems: FormItemProps[] = [
|
|
325
|
+
{
|
|
326
|
+
children: <Switch />,
|
|
327
|
+
label: (
|
|
328
|
+
<Flexbox align={'center'} className={styles.label} gap={8} horizontal>
|
|
329
|
+
{t('settingModel.enableContextCompression.title')}
|
|
330
|
+
<InfoTooltip title={t('settingModel.enableContextCompression.desc')} />
|
|
331
|
+
</Flexbox>
|
|
332
|
+
),
|
|
333
|
+
name: ['chatConfig', 'enableContextCompression'],
|
|
334
|
+
tag: 'compression',
|
|
335
|
+
valuePropName: 'checked',
|
|
336
|
+
},
|
|
337
|
+
];
|
|
338
|
+
|
|
339
|
+
const allItems = [...baseItems, ...maxTokensItems, ...contextCompressionItems];
|
|
324
340
|
|
|
325
341
|
return (
|
|
326
342
|
<Form
|
|
@@ -501,6 +501,9 @@ export default {
|
|
|
501
501
|
'Set the default number of images generated when creating a new task in the image generation panel.',
|
|
502
502
|
'settingImage.defaultCount.label': 'Default Image Count',
|
|
503
503
|
'settingImage.defaultCount.title': 'AI Art',
|
|
504
|
+
'settingModel.enableContextCompression.desc':
|
|
505
|
+
'Automatically compress historical messages into summaries when conversation exceeds 64,000 tokens, saving 60-80% token usage',
|
|
506
|
+
'settingModel.enableContextCompression.title': 'Enable Auto Context Compression',
|
|
504
507
|
'settingModel.enableMaxTokens.title': 'Enable Max Tokens Limit',
|
|
505
508
|
'settingModel.enableReasoningEffort.title': 'Enable Reasoning Effort Adjustment',
|
|
506
509
|
'settingModel.frequencyPenalty.desc':
|
|
@@ -126,8 +126,7 @@ export class AgentRuntimeService {
|
|
|
126
126
|
*/
|
|
127
127
|
private stepCallbacks: Map<string, StepLifecycleCallbacks> = new Map();
|
|
128
128
|
private get baseURL() {
|
|
129
|
-
const baseUrl =
|
|
130
|
-
process.env.AGENT_RUNTIME_BASE_URL || appEnv.APP_URL || 'http://localhost:3010';
|
|
129
|
+
const baseUrl = process.env.AGENT_RUNTIME_BASE_URL || appEnv.APP_URL || 'http://localhost:3010';
|
|
131
130
|
|
|
132
131
|
return urlJoin(baseUrl, '/api/agent');
|
|
133
132
|
}
|
|
@@ -840,6 +839,9 @@ export class AgentRuntimeService {
|
|
|
840
839
|
// Create Durable Agent instance
|
|
841
840
|
const agent = new GeneralChatAgent({
|
|
842
841
|
agentConfig: metadata?.agentConfig,
|
|
842
|
+
compressionConfig: {
|
|
843
|
+
enabled: metadata?.agentConfig?.chatConfig?.enableContextCompression ?? true,
|
|
844
|
+
},
|
|
843
845
|
modelRuntimeConfig: metadata?.modelRuntimeConfig,
|
|
844
846
|
operationId,
|
|
845
847
|
userId: metadata?.userId,
|
|
@@ -702,6 +702,9 @@ export const streamingExecutor: StateCreator<
|
|
|
702
702
|
|
|
703
703
|
const agent = new GeneralChatAgent({
|
|
704
704
|
agentConfig: { maxSteps: 1000 },
|
|
705
|
+
compressionConfig: {
|
|
706
|
+
enabled: agentConfigData.chatConfig?.enableContextCompression ?? true, // Default to enabled
|
|
707
|
+
},
|
|
705
708
|
operationId: `${messageKey}/${params.parentMessageId}`,
|
|
706
709
|
modelRuntimeConfig,
|
|
707
710
|
});
|
|
@@ -833,5 +833,26 @@ describe('displayMessageSelectors', () => {
|
|
|
833
833
|
const result = displayMessageSelectors.findLastMessageId('msg-1')(state as ChatStore);
|
|
834
834
|
expect(result).toBe('tool-result-id');
|
|
835
835
|
});
|
|
836
|
+
|
|
837
|
+
it('should return lastMessageId for compressedGroup instead of group id', () => {
|
|
838
|
+
const compressedGroupMessage = {
|
|
839
|
+
id: 'mg_123456',
|
|
840
|
+
role: 'compressedGroup',
|
|
841
|
+
content: 'Compressed summary',
|
|
842
|
+
lastMessageId: 'msg-999',
|
|
843
|
+
compressedMessages: [],
|
|
844
|
+
pinnedMessages: [],
|
|
845
|
+
} as unknown as UIChatMessage;
|
|
846
|
+
|
|
847
|
+
const state: Partial<ChatStore> = {
|
|
848
|
+
activeAgentId: 'test-id',
|
|
849
|
+
messagesMap: {
|
|
850
|
+
[messageMapKey({ agentId: 'test-id' })]: [compressedGroupMessage],
|
|
851
|
+
},
|
|
852
|
+
};
|
|
853
|
+
|
|
854
|
+
const result = displayMessageSelectors.findLastMessageId('mg_123456')(state as ChatStore);
|
|
855
|
+
expect(result).toBe('msg-999');
|
|
856
|
+
});
|
|
836
857
|
});
|
|
837
858
|
});
|
|
@@ -247,7 +247,7 @@ const findLastBlockId = (block: AssistantContentBlock | undefined): string | und
|
|
|
247
247
|
|
|
248
248
|
/**
|
|
249
249
|
* Recursively finds the last message ID in a message tree
|
|
250
|
-
* Priority: children > tools > self
|
|
250
|
+
* Priority: children > tools > compressedGroup.lastMessageId > self
|
|
251
251
|
*/
|
|
252
252
|
const findLastMessageIdRecursive = (node: UIChatMessage | undefined): string | undefined => {
|
|
253
253
|
if (!node) return undefined;
|
|
@@ -264,7 +264,12 @@ const findLastMessageIdRecursive = (node: UIChatMessage | undefined): string | u
|
|
|
264
264
|
return lastTool?.result_msg_id;
|
|
265
265
|
}
|
|
266
266
|
|
|
267
|
-
// Priority 3:
|
|
267
|
+
// Priority 3: For compressedGroup, return lastMessageId instead of group ID
|
|
268
|
+
if (node.role === 'compressedGroup' && 'lastMessageId' in node) {
|
|
269
|
+
return (node as any).lastMessageId;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
// Priority 4: Return self ID
|
|
268
273
|
return node.id;
|
|
269
274
|
};
|
|
270
275
|
|