@lobehub/lobehub 2.0.0-next.208 → 2.0.0-next.209
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 +27 -0
- package/changelog/v1.json +9 -0
- package/package.json +1 -1
- package/packages/model-runtime/src/core/contextBuilders/anthropic.test.ts +27 -0
- package/packages/model-runtime/src/core/contextBuilders/anthropic.ts +8 -1
- package/src/helpers/parserPlaceholder/index.test.ts +361 -2
- package/src/server/routers/lambda/userMemories.ts +7 -5
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,33 @@
|
|
|
2
2
|
|
|
3
3
|
# Changelog
|
|
4
4
|
|
|
5
|
+
## [Version 2.0.0-next.209](https://github.com/lobehub/lobe-chat/compare/v2.0.0-next.208...v2.0.0-next.209)
|
|
6
|
+
|
|
7
|
+
<sup>Released on **2026-01-04**</sup>
|
|
8
|
+
|
|
9
|
+
#### 🐛 Bug Fixes
|
|
10
|
+
|
|
11
|
+
- **model-runtime**: Handle array content in anthropic assistant messages.
|
|
12
|
+
- **misc**: Use configured embedding provider instead of hardcoded OpenAI.
|
|
13
|
+
|
|
14
|
+
<br/>
|
|
15
|
+
|
|
16
|
+
<details>
|
|
17
|
+
<summary><kbd>Improvements and Fixes</kbd></summary>
|
|
18
|
+
|
|
19
|
+
#### What's fixed
|
|
20
|
+
|
|
21
|
+
- **model-runtime**: Handle array content in anthropic assistant messages, closes [#11206](https://github.com/lobehub/lobe-chat/issues/11206) ([b03845d](https://github.com/lobehub/lobe-chat/commit/b03845d))
|
|
22
|
+
- **misc**: Use configured embedding provider instead of hardcoded OpenAI, closes [#11133](https://github.com/lobehub/lobe-chat/issues/11133) ([503c3eb](https://github.com/lobehub/lobe-chat/commit/503c3eb))
|
|
23
|
+
|
|
24
|
+
</details>
|
|
25
|
+
|
|
26
|
+
<div align="right">
|
|
27
|
+
|
|
28
|
+
[](#readme-top)
|
|
29
|
+
|
|
30
|
+
</div>
|
|
31
|
+
|
|
5
32
|
## [Version 2.0.0-next.208](https://github.com/lobehub/lobe-chat/compare/v2.0.0-next.207...v2.0.0-next.208)
|
|
6
33
|
|
|
7
34
|
<sup>Released on **2026-01-04**</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.209",
|
|
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",
|
|
@@ -216,6 +216,33 @@ describe('anthropicHelpers', () => {
|
|
|
216
216
|
role: 'assistant',
|
|
217
217
|
});
|
|
218
218
|
});
|
|
219
|
+
|
|
220
|
+
it('should correctly convert assistant message with array content but no tool_calls', async () => {
|
|
221
|
+
const message: OpenAIChatMessage = {
|
|
222
|
+
content: [
|
|
223
|
+
{ thinking: 'Let me think about this...', type: 'thinking', signature: 'sig123' },
|
|
224
|
+
{ type: 'text', text: 'Here is my response.' },
|
|
225
|
+
],
|
|
226
|
+
role: 'assistant',
|
|
227
|
+
};
|
|
228
|
+
const result = await buildAnthropicMessage(message);
|
|
229
|
+
expect(result).toEqual({
|
|
230
|
+
content: [
|
|
231
|
+
{ thinking: 'Let me think about this...', type: 'thinking', signature: 'sig123' },
|
|
232
|
+
{ type: 'text', text: 'Here is my response.' },
|
|
233
|
+
],
|
|
234
|
+
role: 'assistant',
|
|
235
|
+
});
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
it('should return undefined for assistant message with empty array content', async () => {
|
|
239
|
+
const message: OpenAIChatMessage = {
|
|
240
|
+
content: [],
|
|
241
|
+
role: 'assistant',
|
|
242
|
+
};
|
|
243
|
+
const result = await buildAnthropicMessage(message);
|
|
244
|
+
expect(result).toBeUndefined();
|
|
245
|
+
});
|
|
219
246
|
});
|
|
220
247
|
|
|
221
248
|
describe('buildAnthropicMessages', () => {
|
|
@@ -118,8 +118,15 @@ export const buildAnthropicMessage = async (
|
|
|
118
118
|
}
|
|
119
119
|
|
|
120
120
|
// or it's a plain assistant message
|
|
121
|
+
// Handle array content (e.g., content with thinking blocks)
|
|
122
|
+
if (Array.isArray(content)) {
|
|
123
|
+
const messageContent = await buildArrayContent(content);
|
|
124
|
+
if (messageContent.length === 0) return undefined;
|
|
125
|
+
return { content: messageContent, role: 'assistant' };
|
|
126
|
+
}
|
|
127
|
+
|
|
121
128
|
// Anthropic API requires non-empty content, filter out empty/whitespace-only content
|
|
122
|
-
const textContent =
|
|
129
|
+
const textContent = content?.trim();
|
|
123
130
|
if (!textContent) return undefined;
|
|
124
131
|
return { content: textContent, role: 'assistant' };
|
|
125
132
|
}
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
VARIABLE_GENERATORS,
|
|
5
|
+
parsePlaceholderVariables,
|
|
6
|
+
parsePlaceholderVariablesMessages,
|
|
7
|
+
} from './index';
|
|
4
8
|
|
|
5
9
|
// Mock dependencies
|
|
6
10
|
vi.mock('@lobechat/utils', () => ({
|
|
@@ -48,7 +52,7 @@ vi.mock('@/store/chat/selectors', () => ({
|
|
|
48
52
|
},
|
|
49
53
|
}));
|
|
50
54
|
|
|
51
|
-
vi.mock('
|
|
55
|
+
vi.mock('../GlobalAgentContextManager', () => ({
|
|
52
56
|
globalAgentContextManager: {
|
|
53
57
|
getContext: () => ({
|
|
54
58
|
homePath: '/Users/test',
|
|
@@ -330,3 +334,358 @@ describe('parsePlaceholderVariablesMessages', () => {
|
|
|
330
334
|
});
|
|
331
335
|
});
|
|
332
336
|
});
|
|
337
|
+
|
|
338
|
+
describe('parsePlaceholderVariables', () => {
|
|
339
|
+
beforeEach(() => {
|
|
340
|
+
vi.useFakeTimers();
|
|
341
|
+
vi.setSystemTime(new Date('2025-06-06T06:06:06.666Z'));
|
|
342
|
+
vi.spyOn(Math, 'random').mockReturnValue(0.5);
|
|
343
|
+
});
|
|
344
|
+
|
|
345
|
+
afterEach(() => {
|
|
346
|
+
vi.useRealTimers();
|
|
347
|
+
vi.restoreAllMocks();
|
|
348
|
+
});
|
|
349
|
+
|
|
350
|
+
describe('basic variable replacement', () => {
|
|
351
|
+
it('should replace a single variable', () => {
|
|
352
|
+
const text = 'Hello {{username}}!';
|
|
353
|
+
const result = parsePlaceholderVariables(text);
|
|
354
|
+
expect(result).toBe('Hello testuser!');
|
|
355
|
+
});
|
|
356
|
+
|
|
357
|
+
it('should replace multiple variables', () => {
|
|
358
|
+
const text = 'User: {{username}}, Email: {{email}}';
|
|
359
|
+
const result = parsePlaceholderVariables(text);
|
|
360
|
+
expect(result).toBe('User: testuser, Email: test@example.com');
|
|
361
|
+
});
|
|
362
|
+
|
|
363
|
+
it('should return original text if no variables present', () => {
|
|
364
|
+
const text = 'Hello world!';
|
|
365
|
+
const result = parsePlaceholderVariables(text);
|
|
366
|
+
expect(result).toBe('Hello world!');
|
|
367
|
+
});
|
|
368
|
+
|
|
369
|
+
it('should handle empty string', () => {
|
|
370
|
+
const result = parsePlaceholderVariables('');
|
|
371
|
+
expect(result).toBe('');
|
|
372
|
+
});
|
|
373
|
+
|
|
374
|
+
it('should preserve unknown variables', () => {
|
|
375
|
+
const text = 'Hello {{unknown_var}}!';
|
|
376
|
+
const result = parsePlaceholderVariables(text);
|
|
377
|
+
expect(result).toBe('Hello {{unknown_var}}!');
|
|
378
|
+
});
|
|
379
|
+
});
|
|
380
|
+
|
|
381
|
+
describe('recursive depth handling', () => {
|
|
382
|
+
it('should handle default depth of 2', () => {
|
|
383
|
+
const text = 'Test {{username}}';
|
|
384
|
+
const result = parsePlaceholderVariables(text);
|
|
385
|
+
expect(result).toBe('Test testuser');
|
|
386
|
+
});
|
|
387
|
+
|
|
388
|
+
it('should handle custom depth', () => {
|
|
389
|
+
const text = 'Test {{username}}';
|
|
390
|
+
const result = parsePlaceholderVariables(text, 1);
|
|
391
|
+
expect(result).toBe('Test testuser');
|
|
392
|
+
});
|
|
393
|
+
|
|
394
|
+
it('should handle depth of 0', () => {
|
|
395
|
+
const text = 'Test {{username}}';
|
|
396
|
+
const result = parsePlaceholderVariables(text, 0);
|
|
397
|
+
// With depth 0, no replacements should occur
|
|
398
|
+
expect(result).toBe('Test {{username}}');
|
|
399
|
+
});
|
|
400
|
+
|
|
401
|
+
it('should stop early if no more replacements needed', () => {
|
|
402
|
+
const text = 'Static text';
|
|
403
|
+
const result = parsePlaceholderVariables(text, 10);
|
|
404
|
+
expect(result).toBe('Static text');
|
|
405
|
+
});
|
|
406
|
+
});
|
|
407
|
+
|
|
408
|
+
describe('special characters and edge cases', () => {
|
|
409
|
+
it('should handle variables with spaces', () => {
|
|
410
|
+
const text = 'Hello {{ username }}!';
|
|
411
|
+
const result = parsePlaceholderVariables(text);
|
|
412
|
+
// The regex trims spaces, so this should work
|
|
413
|
+
expect(result).toBe('Hello testuser!');
|
|
414
|
+
});
|
|
415
|
+
|
|
416
|
+
it('should handle consecutive variables', () => {
|
|
417
|
+
const text = '{{username}}{{email}}';
|
|
418
|
+
const result = parsePlaceholderVariables(text);
|
|
419
|
+
expect(result).toBe('testusertest@example.com');
|
|
420
|
+
});
|
|
421
|
+
|
|
422
|
+
it('should handle variables at start and end', () => {
|
|
423
|
+
const text = '{{username}} middle {{email}}';
|
|
424
|
+
const result = parsePlaceholderVariables(text);
|
|
425
|
+
expect(result).toBe('testuser middle test@example.com');
|
|
426
|
+
});
|
|
427
|
+
|
|
428
|
+
it('should handle malformed brackets', () => {
|
|
429
|
+
const text = '{username} or {{{username}}}';
|
|
430
|
+
const result = parsePlaceholderVariables(text);
|
|
431
|
+
// Only {{username}} should be replaced
|
|
432
|
+
expect(result).toContain('{username}');
|
|
433
|
+
});
|
|
434
|
+
});
|
|
435
|
+
});
|
|
436
|
+
|
|
437
|
+
describe('VARIABLE_GENERATORS', () => {
|
|
438
|
+
describe('time-related variables', () => {
|
|
439
|
+
beforeEach(() => {
|
|
440
|
+
vi.useFakeTimers();
|
|
441
|
+
vi.setSystemTime(new Date('2025-06-06T06:06:06.666Z'));
|
|
442
|
+
});
|
|
443
|
+
|
|
444
|
+
afterEach(() => {
|
|
445
|
+
vi.useRealTimers();
|
|
446
|
+
});
|
|
447
|
+
|
|
448
|
+
it('should generate year', () => {
|
|
449
|
+
expect(VARIABLE_GENERATORS.year()).toBe('2025');
|
|
450
|
+
});
|
|
451
|
+
|
|
452
|
+
it('should generate month with padding', () => {
|
|
453
|
+
expect(VARIABLE_GENERATORS.month()).toBe('06');
|
|
454
|
+
});
|
|
455
|
+
|
|
456
|
+
it('should generate day with padding', () => {
|
|
457
|
+
expect(VARIABLE_GENERATORS.day()).toBe('06');
|
|
458
|
+
});
|
|
459
|
+
|
|
460
|
+
it('should generate hour with padding', () => {
|
|
461
|
+
expect(VARIABLE_GENERATORS.hour()).toBe('06');
|
|
462
|
+
});
|
|
463
|
+
|
|
464
|
+
it('should generate minute with padding', () => {
|
|
465
|
+
expect(VARIABLE_GENERATORS.minute()).toBe('06');
|
|
466
|
+
});
|
|
467
|
+
|
|
468
|
+
it('should generate second with padding', () => {
|
|
469
|
+
expect(VARIABLE_GENERATORS.second()).toBe('06');
|
|
470
|
+
});
|
|
471
|
+
|
|
472
|
+
it('should generate ISO timestamp', () => {
|
|
473
|
+
expect(VARIABLE_GENERATORS.iso()).toBe('2025-06-06T06:06:06.666Z');
|
|
474
|
+
});
|
|
475
|
+
|
|
476
|
+
it('should generate timestamp', () => {
|
|
477
|
+
const result = VARIABLE_GENERATORS.timestamp();
|
|
478
|
+
expect(result).toBe(Date.now().toString());
|
|
479
|
+
});
|
|
480
|
+
|
|
481
|
+
it('should generate date string', () => {
|
|
482
|
+
const result = VARIABLE_GENERATORS.date();
|
|
483
|
+
expect(result).toBeTruthy();
|
|
484
|
+
expect(typeof result).toBe('string');
|
|
485
|
+
});
|
|
486
|
+
|
|
487
|
+
it('should generate time string', () => {
|
|
488
|
+
const result = VARIABLE_GENERATORS.time();
|
|
489
|
+
expect(result).toBeTruthy();
|
|
490
|
+
expect(typeof result).toBe('string');
|
|
491
|
+
});
|
|
492
|
+
|
|
493
|
+
it('should generate datetime string', () => {
|
|
494
|
+
const result = VARIABLE_GENERATORS.datetime();
|
|
495
|
+
expect(result).toBeTruthy();
|
|
496
|
+
expect(typeof result).toBe('string');
|
|
497
|
+
});
|
|
498
|
+
|
|
499
|
+
it('should generate weekday', () => {
|
|
500
|
+
const result = VARIABLE_GENERATORS.weekday();
|
|
501
|
+
expect(result).toBe('Friday');
|
|
502
|
+
});
|
|
503
|
+
|
|
504
|
+
it('should generate locale', () => {
|
|
505
|
+
const result = VARIABLE_GENERATORS.locale();
|
|
506
|
+
expect(result).toBeTruthy();
|
|
507
|
+
expect(typeof result).toBe('string');
|
|
508
|
+
});
|
|
509
|
+
|
|
510
|
+
it('should generate timezone', () => {
|
|
511
|
+
const result = VARIABLE_GENERATORS.timezone();
|
|
512
|
+
expect(result).toBeTruthy();
|
|
513
|
+
expect(typeof result).toBe('string');
|
|
514
|
+
});
|
|
515
|
+
});
|
|
516
|
+
|
|
517
|
+
describe('random value variables', () => {
|
|
518
|
+
beforeEach(() => {
|
|
519
|
+
vi.spyOn(Math, 'random').mockReturnValue(0.5);
|
|
520
|
+
});
|
|
521
|
+
|
|
522
|
+
afterEach(() => {
|
|
523
|
+
vi.restoreAllMocks();
|
|
524
|
+
});
|
|
525
|
+
|
|
526
|
+
it('should generate random number', () => {
|
|
527
|
+
expect(VARIABLE_GENERATORS.random()).toBe('500001');
|
|
528
|
+
});
|
|
529
|
+
|
|
530
|
+
it('should generate random boolean', () => {
|
|
531
|
+
expect(VARIABLE_GENERATORS.random_bool()).toBe('false');
|
|
532
|
+
});
|
|
533
|
+
|
|
534
|
+
it('should generate random float', () => {
|
|
535
|
+
expect(VARIABLE_GENERATORS.random_float()).toBe('50.00');
|
|
536
|
+
});
|
|
537
|
+
|
|
538
|
+
it('should generate random integer', () => {
|
|
539
|
+
expect(VARIABLE_GENERATORS.random_int()).toBe('51');
|
|
540
|
+
});
|
|
541
|
+
|
|
542
|
+
it('should generate random hex color', () => {
|
|
543
|
+
const result = VARIABLE_GENERATORS.random_hex();
|
|
544
|
+
// Math.floor(0.5 * 16777215) = 8388607 = 0x7fffff
|
|
545
|
+
expect(result).toBe('7fffff');
|
|
546
|
+
expect(result.length).toBe(6);
|
|
547
|
+
});
|
|
548
|
+
|
|
549
|
+
it('should generate random string', () => {
|
|
550
|
+
const result = VARIABLE_GENERATORS.random_string();
|
|
551
|
+
expect(result).toBeTruthy();
|
|
552
|
+
expect(typeof result).toBe('string');
|
|
553
|
+
});
|
|
554
|
+
|
|
555
|
+
it('should generate random digit', () => {
|
|
556
|
+
expect(VARIABLE_GENERATORS.random_digit()).toBe('5');
|
|
557
|
+
});
|
|
558
|
+
|
|
559
|
+
it('should generate different random booleans', () => {
|
|
560
|
+
vi.spyOn(Math, 'random').mockReturnValue(0.6);
|
|
561
|
+
expect(VARIABLE_GENERATORS.random_bool()).toBe('true');
|
|
562
|
+
|
|
563
|
+
vi.spyOn(Math, 'random').mockReturnValue(0.4);
|
|
564
|
+
expect(VARIABLE_GENERATORS.random_bool()).toBe('false');
|
|
565
|
+
});
|
|
566
|
+
});
|
|
567
|
+
|
|
568
|
+
describe('UUID variables', () => {
|
|
569
|
+
it('should generate full UUID', () => {
|
|
570
|
+
expect(VARIABLE_GENERATORS.uuid()).toBe('mocked-uuid-12345');
|
|
571
|
+
});
|
|
572
|
+
|
|
573
|
+
it('should generate short UUID', () => {
|
|
574
|
+
expect(VARIABLE_GENERATORS.uuid_short()).toBe('mocked');
|
|
575
|
+
});
|
|
576
|
+
});
|
|
577
|
+
|
|
578
|
+
describe('user information variables', () => {
|
|
579
|
+
it('should get username', () => {
|
|
580
|
+
expect(VARIABLE_GENERATORS.username()).toBe('testuser');
|
|
581
|
+
});
|
|
582
|
+
|
|
583
|
+
it('should get nickname', () => {
|
|
584
|
+
expect(VARIABLE_GENERATORS.nickname()).toBe('Test User');
|
|
585
|
+
});
|
|
586
|
+
|
|
587
|
+
it('should get email', () => {
|
|
588
|
+
expect(VARIABLE_GENERATORS.email()).toBe('test@example.com');
|
|
589
|
+
});
|
|
590
|
+
});
|
|
591
|
+
|
|
592
|
+
describe('model information variables', () => {
|
|
593
|
+
it('should get current model', () => {
|
|
594
|
+
expect(VARIABLE_GENERATORS.model()).toBe('gpt-4');
|
|
595
|
+
});
|
|
596
|
+
|
|
597
|
+
it('should get current provider', () => {
|
|
598
|
+
expect(VARIABLE_GENERATORS.provider()).toBe('openai');
|
|
599
|
+
});
|
|
600
|
+
});
|
|
601
|
+
|
|
602
|
+
describe('desktop path variables', () => {
|
|
603
|
+
it('should get home path', () => {
|
|
604
|
+
expect(VARIABLE_GENERATORS.homePath()).toBe('/Users/test');
|
|
605
|
+
});
|
|
606
|
+
|
|
607
|
+
it('should get desktop path', () => {
|
|
608
|
+
expect(VARIABLE_GENERATORS.desktopPath()).toBe('/Users/test/Desktop');
|
|
609
|
+
});
|
|
610
|
+
|
|
611
|
+
it('should get documents path', () => {
|
|
612
|
+
expect(VARIABLE_GENERATORS.documentsPath()).toBe('/Users/test/Documents');
|
|
613
|
+
});
|
|
614
|
+
|
|
615
|
+
it('should get downloads path', () => {
|
|
616
|
+
expect(VARIABLE_GENERATORS.downloadsPath()).toBe('/Users/test/Downloads');
|
|
617
|
+
});
|
|
618
|
+
|
|
619
|
+
it('should return empty string for missing music path', () => {
|
|
620
|
+
expect(VARIABLE_GENERATORS.musicPath()).toBe('');
|
|
621
|
+
});
|
|
622
|
+
|
|
623
|
+
it('should return empty string for missing pictures path', () => {
|
|
624
|
+
expect(VARIABLE_GENERATORS.picturesPath()).toBe('');
|
|
625
|
+
});
|
|
626
|
+
|
|
627
|
+
it('should return empty string for missing videos path', () => {
|
|
628
|
+
expect(VARIABLE_GENERATORS.videosPath()).toBe('');
|
|
629
|
+
});
|
|
630
|
+
|
|
631
|
+
it('should return empty string for missing userData path', () => {
|
|
632
|
+
expect(VARIABLE_GENERATORS.userDataPath()).toBe('');
|
|
633
|
+
});
|
|
634
|
+
|
|
635
|
+
it('should return default message for working directory when not specified', () => {
|
|
636
|
+
const result = VARIABLE_GENERATORS.workingDirectory();
|
|
637
|
+
expect(result).toBe('(not specified, use user Desktop directory as default)');
|
|
638
|
+
});
|
|
639
|
+
});
|
|
640
|
+
|
|
641
|
+
describe('platform variables', () => {
|
|
642
|
+
const originalNavigator = global.navigator;
|
|
643
|
+
|
|
644
|
+
beforeEach(() => {
|
|
645
|
+
Object.defineProperty(global, 'navigator', {
|
|
646
|
+
writable: true,
|
|
647
|
+
configurable: true,
|
|
648
|
+
value: {
|
|
649
|
+
language: 'en-US',
|
|
650
|
+
platform: 'MacIntel',
|
|
651
|
+
userAgent:
|
|
652
|
+
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Safari/537.36',
|
|
653
|
+
},
|
|
654
|
+
});
|
|
655
|
+
});
|
|
656
|
+
|
|
657
|
+
afterEach(() => {
|
|
658
|
+
Object.defineProperty(global, 'navigator', {
|
|
659
|
+
writable: true,
|
|
660
|
+
configurable: true,
|
|
661
|
+
value: originalNavigator,
|
|
662
|
+
});
|
|
663
|
+
});
|
|
664
|
+
|
|
665
|
+
it('should get language', () => {
|
|
666
|
+
expect(VARIABLE_GENERATORS.language()).toBe('en-US');
|
|
667
|
+
});
|
|
668
|
+
|
|
669
|
+
it('should get platform', () => {
|
|
670
|
+
expect(VARIABLE_GENERATORS.platform()).toBe('MacIntel');
|
|
671
|
+
});
|
|
672
|
+
|
|
673
|
+
it('should get user agent', () => {
|
|
674
|
+
const result = VARIABLE_GENERATORS.user_agent();
|
|
675
|
+
expect(result).toContain('Mozilla/5.0');
|
|
676
|
+
expect(result).toContain('Chrome/132.0.0.0');
|
|
677
|
+
});
|
|
678
|
+
|
|
679
|
+
it('should return empty string when navigator is undefined', () => {
|
|
680
|
+
Object.defineProperty(global, 'navigator', {
|
|
681
|
+
writable: true,
|
|
682
|
+
configurable: true,
|
|
683
|
+
value: undefined,
|
|
684
|
+
});
|
|
685
|
+
|
|
686
|
+
expect(VARIABLE_GENERATORS.language()).toBe('');
|
|
687
|
+
expect(VARIABLE_GENERATORS.platform()).toBe('');
|
|
688
|
+
expect(VARIABLE_GENERATORS.user_agent()).toBe('');
|
|
689
|
+
});
|
|
690
|
+
});
|
|
691
|
+
});
|
|
@@ -15,7 +15,6 @@ import {
|
|
|
15
15
|
} from '@lobechat/memory-user-memory';
|
|
16
16
|
import { LayersEnum, type SearchMemoryResult, searchMemorySchema } from '@lobechat/types';
|
|
17
17
|
import { type SQL, and, asc, eq, gte, lte } from 'drizzle-orm';
|
|
18
|
-
import { ModelProvider } from 'model-bank';
|
|
19
18
|
import pMap from 'p-map';
|
|
20
19
|
import { z } from 'zod';
|
|
21
20
|
|
|
@@ -135,11 +134,14 @@ const searchUserMemories = async (
|
|
|
135
134
|
};
|
|
136
135
|
|
|
137
136
|
const getEmbeddingRuntime = async (serverDB: LobeChatDatabase, userId: string) => {
|
|
138
|
-
const provider
|
|
139
|
-
// Read user's provider config from database
|
|
140
|
-
const agentRuntime = await initModelRuntimeFromDB(serverDB, userId, provider);
|
|
141
|
-
const { model: embeddingModel } =
|
|
137
|
+
const { provider, model: embeddingModel } =
|
|
142
138
|
getServerDefaultFilesConfig().embeddingModel || DEFAULT_USER_MEMORY_EMBEDDING_MODEL_ITEM;
|
|
139
|
+
// Read user's provider config from database
|
|
140
|
+
const agentRuntime = await initModelRuntimeFromDB(
|
|
141
|
+
serverDB,
|
|
142
|
+
userId,
|
|
143
|
+
ENABLE_BUSINESS_FEATURES ? BRANDING_PROVIDER : provider,
|
|
144
|
+
);
|
|
143
145
|
|
|
144
146
|
return { agentRuntime, embeddingModel };
|
|
145
147
|
};
|