@lobehub/lobehub 2.0.0-next.78 → 2.0.0-next.79
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 +25 -0
- package/changelog/v1.json +9 -0
- package/package.json +1 -1
- package/packages/agent-runtime/src/types/instruction.ts +7 -2
- package/packages/database/src/utils/genWhere.test.ts +243 -0
- package/src/app/[variants]/(main)/discover/(list)/assistant/features/Category/index.tsx +1 -1
- package/src/app/[variants]/(main)/discover/(list)/mcp/features/Category/index.tsx +1 -1
- package/src/app/[variants]/(main)/discover/(list)/model/features/Category/index.tsx +1 -1
- package/src/store/chat/initialState.ts +4 -1
- package/src/store/chat/slices/operation/__tests__/actions.test.ts +353 -0
- package/src/store/chat/slices/operation/__tests__/selectors.test.ts +273 -0
- package/src/store/chat/slices/operation/actions.ts +451 -0
- package/src/store/chat/slices/operation/index.ts +4 -0
- package/src/store/chat/slices/operation/initialState.ts +44 -0
- package/src/store/chat/slices/operation/selectors.ts +246 -0
- package/src/store/chat/slices/operation/types.ts +134 -0
- package/src/store/chat/store.ts +4 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,31 @@
|
|
|
2
2
|
|
|
3
3
|
# Changelog
|
|
4
4
|
|
|
5
|
+
## [Version 2.0.0-next.79](https://github.com/lobehub/lobe-chat/compare/v2.0.0-next.78...v2.0.0-next.79)
|
|
6
|
+
|
|
7
|
+
<sup>Released on **2025-11-18**</sup>
|
|
8
|
+
|
|
9
|
+
#### 🐛 Bug Fixes
|
|
10
|
+
|
|
11
|
+
- **misc**: Fixed the discover page categray sider link error.
|
|
12
|
+
|
|
13
|
+
<br/>
|
|
14
|
+
|
|
15
|
+
<details>
|
|
16
|
+
<summary><kbd>Improvements and Fixes</kbd></summary>
|
|
17
|
+
|
|
18
|
+
#### What's fixed
|
|
19
|
+
|
|
20
|
+
- **misc**: Fixed the discover page categray sider link error, closes [#10282](https://github.com/lobehub/lobe-chat/issues/10282) ([39e8819](https://github.com/lobehub/lobe-chat/commit/39e8819))
|
|
21
|
+
|
|
22
|
+
</details>
|
|
23
|
+
|
|
24
|
+
<div align="right">
|
|
25
|
+
|
|
26
|
+
[](#readme-top)
|
|
27
|
+
|
|
28
|
+
</div>
|
|
29
|
+
|
|
5
30
|
## [Version 2.0.0-next.78](https://github.com/lobehub/lobe-chat/compare/v2.0.0-next.77...v2.0.0-next.78)
|
|
6
31
|
|
|
7
32
|
<sup>Released on **2025-11-18**</sup>
|
package/changelog/v1.json
CHANGED
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.79",
|
|
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",
|
|
@@ -9,6 +9,10 @@ import type { Cost, CostCalculationContext, Usage } from './usage';
|
|
|
9
9
|
*/
|
|
10
10
|
export interface AgentRuntimeContext {
|
|
11
11
|
metadata?: Record<string, unknown>;
|
|
12
|
+
|
|
13
|
+
/** Operation ID (links to Operation for business context) */
|
|
14
|
+
operationId?: string;
|
|
15
|
+
|
|
12
16
|
/** Phase-specific payload/context */
|
|
13
17
|
payload?: unknown;
|
|
14
18
|
/** Current execution phase */
|
|
@@ -21,8 +25,9 @@ export interface AgentRuntimeContext {
|
|
|
21
25
|
| 'human_response'
|
|
22
26
|
| 'human_approved_tool'
|
|
23
27
|
| 'error';
|
|
24
|
-
|
|
25
|
-
|
|
28
|
+
|
|
29
|
+
/** Session info (kept for backward compatibility, will be optional in the future) */
|
|
30
|
+
session?: {
|
|
26
31
|
messageCount: number;
|
|
27
32
|
sessionId: string;
|
|
28
33
|
status: AgentState['status'];
|
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
import dayjs from 'dayjs';
|
|
2
|
+
import { eq, sql } from 'drizzle-orm';
|
|
3
|
+
import { describe, expect, it } from 'vitest';
|
|
4
|
+
|
|
5
|
+
import { genEndDateWhere, genRangeWhere, genStartDateWhere, genWhere } from './genWhere';
|
|
6
|
+
|
|
7
|
+
describe('genWhere', () => {
|
|
8
|
+
describe('genWhere', () => {
|
|
9
|
+
it('should return undefined when array is empty', () => {
|
|
10
|
+
const result = genWhere([]);
|
|
11
|
+
expect(result).toBeUndefined();
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
it('should return undefined when all elements are undefined', () => {
|
|
15
|
+
const result = genWhere([undefined, undefined, undefined]);
|
|
16
|
+
expect(result).toBeUndefined();
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
it('should return the single SQL condition when only one valid condition exists', () => {
|
|
20
|
+
const condition = eq(sql`id`, 1);
|
|
21
|
+
const result = genWhere([condition]);
|
|
22
|
+
expect(result).toBe(condition);
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it('should return the single valid SQL condition when mixed with undefined', () => {
|
|
26
|
+
const condition = eq(sql`id`, 1);
|
|
27
|
+
const result = genWhere([undefined, condition, undefined]);
|
|
28
|
+
expect(result).toBe(condition);
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
it('should combine multiple SQL conditions with AND operator', () => {
|
|
32
|
+
const condition1 = eq(sql`id`, 1);
|
|
33
|
+
const condition2 = eq(sql`name`, 'test');
|
|
34
|
+
const result = genWhere([condition1, condition2]);
|
|
35
|
+
|
|
36
|
+
expect(result).toBeDefined();
|
|
37
|
+
// The result should be an AND combination
|
|
38
|
+
expect(result?.constructor.name).toBe('SQL');
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it('should filter out undefined conditions and combine valid ones', () => {
|
|
42
|
+
const condition1 = eq(sql`id`, 1);
|
|
43
|
+
const condition2 = eq(sql`name`, 'test');
|
|
44
|
+
const result = genWhere([undefined, condition1, undefined, condition2, undefined]);
|
|
45
|
+
|
|
46
|
+
expect(result).toBeDefined();
|
|
47
|
+
expect(result?.constructor.name).toBe('SQL');
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
describe('genStartDateWhere', () => {
|
|
52
|
+
const mockKey = sql`created_at`;
|
|
53
|
+
const mockFormat = (date: dayjs.Dayjs) => date.format('YYYY-MM-DD');
|
|
54
|
+
|
|
55
|
+
it('should return undefined when date is undefined', () => {
|
|
56
|
+
const result = genStartDateWhere(undefined, mockKey, mockFormat);
|
|
57
|
+
expect(result).toBeUndefined();
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it('should return undefined when date is empty string', () => {
|
|
61
|
+
const result = genStartDateWhere('', mockKey, mockFormat);
|
|
62
|
+
expect(result).toBeUndefined();
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it('should return undefined when date is invalid', () => {
|
|
66
|
+
const result = genStartDateWhere('invalid-date', mockKey, mockFormat);
|
|
67
|
+
expect(result).toBeUndefined();
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
it('should handle lenient date parsing for malformed dates', () => {
|
|
71
|
+
// dayjs is lenient and treats '2024-13-45' as valid, so it creates a condition
|
|
72
|
+
const result = genStartDateWhere('2024-13-45', mockKey, mockFormat);
|
|
73
|
+
expect(result).toBeDefined();
|
|
74
|
+
expect(result?.constructor.name).toBe('SQL');
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
it('should create gte condition for valid ISO date string', () => {
|
|
78
|
+
const result = genStartDateWhere('2024-01-15', mockKey, mockFormat);
|
|
79
|
+
|
|
80
|
+
expect(result).toBeDefined();
|
|
81
|
+
expect(result?.constructor.name).toBe('SQL');
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
it('should create gte condition for valid date with time', () => {
|
|
85
|
+
const result = genStartDateWhere('2024-01-15T10:30:00Z', mockKey, mockFormat);
|
|
86
|
+
|
|
87
|
+
expect(result).toBeDefined();
|
|
88
|
+
expect(result?.constructor.name).toBe('SQL');
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
it('should handle timestamp number as string', () => {
|
|
92
|
+
const timestamp = Date.now().toString();
|
|
93
|
+
const result = genStartDateWhere(timestamp, mockKey, mockFormat);
|
|
94
|
+
|
|
95
|
+
expect(result).toBeDefined();
|
|
96
|
+
expect(result?.constructor.name).toBe('SQL');
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
it('should work with custom format function', () => {
|
|
100
|
+
const customFormat = (date: dayjs.Dayjs) => date.unix();
|
|
101
|
+
const result = genStartDateWhere('2024-01-15', mockKey, customFormat);
|
|
102
|
+
|
|
103
|
+
expect(result).toBeDefined();
|
|
104
|
+
expect(result?.constructor.name).toBe('SQL');
|
|
105
|
+
});
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
describe('genEndDateWhere', () => {
|
|
109
|
+
const mockKey = sql`created_at`;
|
|
110
|
+
const mockFormat = (date: dayjs.Dayjs) => date.format('YYYY-MM-DD');
|
|
111
|
+
|
|
112
|
+
it('should return undefined when date is undefined', () => {
|
|
113
|
+
const result = genEndDateWhere(undefined, mockKey, mockFormat);
|
|
114
|
+
expect(result).toBeUndefined();
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
it('should return undefined when date is empty string', () => {
|
|
118
|
+
const result = genEndDateWhere('', mockKey, mockFormat);
|
|
119
|
+
expect(result).toBeUndefined();
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
it('should return undefined when date is invalid', () => {
|
|
123
|
+
const result = genEndDateWhere('invalid-date', mockKey, mockFormat);
|
|
124
|
+
expect(result).toBeUndefined();
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
it('should handle lenient date parsing for malformed dates', () => {
|
|
128
|
+
// dayjs is lenient and treats '2024-13-45' as valid, so it creates a condition
|
|
129
|
+
const result = genEndDateWhere('2024-13-45', mockKey, mockFormat);
|
|
130
|
+
expect(result).toBeDefined();
|
|
131
|
+
expect(result?.constructor.name).toBe('SQL');
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
it('should create lte condition with date plus one day', () => {
|
|
135
|
+
const result = genEndDateWhere('2024-01-15', mockKey, mockFormat);
|
|
136
|
+
|
|
137
|
+
expect(result).toBeDefined();
|
|
138
|
+
expect(result?.constructor.name).toBe('SQL');
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
it('should create lte condition for valid date with time', () => {
|
|
142
|
+
const result = genEndDateWhere('2024-01-15T10:30:00Z', mockKey, mockFormat);
|
|
143
|
+
|
|
144
|
+
expect(result).toBeDefined();
|
|
145
|
+
expect(result?.constructor.name).toBe('SQL');
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
it('should handle timestamp number as string', () => {
|
|
149
|
+
const timestamp = Date.now().toString();
|
|
150
|
+
const result = genEndDateWhere(timestamp, mockKey, mockFormat);
|
|
151
|
+
|
|
152
|
+
expect(result).toBeDefined();
|
|
153
|
+
expect(result?.constructor.name).toBe('SQL');
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
it('should work with custom format function', () => {
|
|
157
|
+
const customFormat = (date: dayjs.Dayjs) => date.unix();
|
|
158
|
+
const result = genEndDateWhere('2024-01-15', mockKey, customFormat);
|
|
159
|
+
|
|
160
|
+
expect(result).toBeDefined();
|
|
161
|
+
expect(result?.constructor.name).toBe('SQL');
|
|
162
|
+
});
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
describe('genRangeWhere', () => {
|
|
166
|
+
const mockKey = sql`created_at`;
|
|
167
|
+
const mockFormat = (date: dayjs.Dayjs) => date.format('YYYY-MM-DD');
|
|
168
|
+
|
|
169
|
+
it('should return undefined when range is undefined', () => {
|
|
170
|
+
const result = genRangeWhere(undefined, mockKey, mockFormat);
|
|
171
|
+
expect(result).toBeUndefined();
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
it('should return undefined when both dates in range are invalid', () => {
|
|
175
|
+
const result = genRangeWhere(['invalid-date', 'also-invalid'], mockKey, mockFormat);
|
|
176
|
+
expect(result).toBeUndefined();
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
it('should create end date condition when only end date is valid', () => {
|
|
180
|
+
const result = genRangeWhere(['invalid-date', '2024-01-15'], mockKey, mockFormat);
|
|
181
|
+
|
|
182
|
+
expect(result).toBeDefined();
|
|
183
|
+
expect(result?.constructor.name).toBe('SQL');
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
it('should create start date condition when only start date is valid', () => {
|
|
187
|
+
const result = genRangeWhere(['2024-01-15', 'invalid-date'], mockKey, mockFormat);
|
|
188
|
+
|
|
189
|
+
expect(result).toBeDefined();
|
|
190
|
+
expect(result?.constructor.name).toBe('SQL');
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
it('should combine both start and end date conditions when both are valid', () => {
|
|
194
|
+
const result = genRangeWhere(['2024-01-01', '2024-01-31'], mockKey, mockFormat);
|
|
195
|
+
|
|
196
|
+
expect(result).toBeDefined();
|
|
197
|
+
expect(result?.constructor.name).toBe('SQL');
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
it('should handle ISO date strings in range', () => {
|
|
201
|
+
const result = genRangeWhere(
|
|
202
|
+
['2024-01-01T00:00:00Z', '2024-01-31T23:59:59Z'],
|
|
203
|
+
mockKey,
|
|
204
|
+
mockFormat,
|
|
205
|
+
);
|
|
206
|
+
|
|
207
|
+
expect(result).toBeDefined();
|
|
208
|
+
expect(result?.constructor.name).toBe('SQL');
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
it('should handle timestamp numbers as strings in range', () => {
|
|
212
|
+
const startTimestamp = new Date('2024-01-01').getTime().toString();
|
|
213
|
+
const endTimestamp = new Date('2024-01-31').getTime().toString();
|
|
214
|
+
const result = genRangeWhere([startTimestamp, endTimestamp], mockKey, mockFormat);
|
|
215
|
+
|
|
216
|
+
expect(result).toBeDefined();
|
|
217
|
+
expect(result?.constructor.name).toBe('SQL');
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
it('should work with custom format function', () => {
|
|
221
|
+
const customFormat = (date: dayjs.Dayjs) => date.unix();
|
|
222
|
+
const result = genRangeWhere(['2024-01-01', '2024-01-31'], mockKey, customFormat);
|
|
223
|
+
|
|
224
|
+
expect(result).toBeDefined();
|
|
225
|
+
expect(result?.constructor.name).toBe('SQL');
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
it('should handle edge case where start date is after end date', () => {
|
|
229
|
+
// The function doesn't validate date order, it just creates the conditions
|
|
230
|
+
const result = genRangeWhere(['2024-01-31', '2024-01-01'], mockKey, mockFormat);
|
|
231
|
+
|
|
232
|
+
expect(result).toBeDefined();
|
|
233
|
+
expect(result?.constructor.name).toBe('SQL');
|
|
234
|
+
});
|
|
235
|
+
|
|
236
|
+
it('should handle same date for start and end', () => {
|
|
237
|
+
const result = genRangeWhere(['2024-01-15', '2024-01-15'], mockKey, mockFormat);
|
|
238
|
+
|
|
239
|
+
expect(result).toBeDefined();
|
|
240
|
+
expect(result?.constructor.name).toBe('SQL');
|
|
241
|
+
});
|
|
242
|
+
});
|
|
243
|
+
});
|
|
@@ -5,13 +5,15 @@ import { ChatMessageState, initialMessageState } from './slices/message/initialS
|
|
|
5
5
|
import { ChatTopicState, initialTopicState } from './slices/topic/initialState';
|
|
6
6
|
import { ChatAIChatState, initialAiChatState } from './slices/aiChat/initialState';
|
|
7
7
|
import { ChatThreadState, initialThreadState } from './slices/thread/initialState';
|
|
8
|
+
import { ChatOperationState, initialOperationState } from './slices/operation/initialState';
|
|
8
9
|
|
|
9
10
|
export type ChatStoreState = ChatTopicState &
|
|
10
11
|
ChatMessageState &
|
|
11
12
|
ChatAIChatState &
|
|
12
13
|
ChatToolState &
|
|
13
14
|
ChatThreadState &
|
|
14
|
-
ChatPortalState
|
|
15
|
+
ChatPortalState &
|
|
16
|
+
ChatOperationState;
|
|
15
17
|
|
|
16
18
|
export const initialState: ChatStoreState = {
|
|
17
19
|
...initialMessageState,
|
|
@@ -20,6 +22,7 @@ export const initialState: ChatStoreState = {
|
|
|
20
22
|
...initialToolState,
|
|
21
23
|
...initialThreadState,
|
|
22
24
|
...initialChatPortalState,
|
|
25
|
+
...initialOperationState,
|
|
23
26
|
|
|
24
27
|
// cloud
|
|
25
28
|
};
|