@lobehub/chat 1.141.8 → 1.141.10
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/apps/desktop/package.json +1 -0
- package/apps/desktop/src/main/controllers/LocalFileCtr.ts +279 -52
- package/apps/desktop/src/main/controllers/__tests__/LocalFileCtr.test.ts +392 -0
- package/changelog/v1.json +18 -0
- package/package.json +1 -1
- package/packages/agent-runtime/src/core/InterventionChecker.ts +173 -0
- package/packages/agent-runtime/src/core/UsageCounter.ts +248 -0
- package/packages/agent-runtime/src/core/__tests__/InterventionChecker.test.ts +334 -0
- package/packages/agent-runtime/src/core/__tests__/UsageCounter.test.ts +873 -0
- package/packages/agent-runtime/src/core/__tests__/runtime.test.ts +32 -26
- package/packages/agent-runtime/src/core/index.ts +2 -0
- package/packages/agent-runtime/src/core/runtime.ts +31 -18
- package/packages/agent-runtime/src/types/instruction.ts +1 -1
- package/packages/agent-runtime/src/types/state.ts +3 -3
- package/packages/agent-runtime/src/types/usage.ts +34 -25
- package/packages/context-engine/src/index.ts +1 -0
- package/packages/context-engine/src/tools/ToolNameResolver.ts +2 -2
- package/packages/context-engine/src/tools/ToolsEngine.ts +37 -8
- package/packages/context-engine/src/tools/__tests__/ToolsEngine.test.ts +149 -5
- package/packages/context-engine/src/tools/__tests__/utils.test.ts +2 -2
- package/packages/context-engine/src/tools/index.ts +1 -0
- package/packages/context-engine/src/tools/types.ts +18 -3
- package/packages/context-engine/src/tools/utils.ts +4 -4
- package/packages/types/src/tool/builtin.ts +54 -1
- package/packages/types/src/tool/index.ts +1 -0
- package/packages/types/src/tool/intervention.ts +114 -0
- package/packages/types/src/user/settings/tool.ts +37 -0
- package/src/app/[variants]/(main)/discover/(list)/(home)/Client.tsx +2 -2
- package/src/app/[variants]/(main)/discover/(list)/(home)/HomePage.tsx +2 -2
- package/src/app/[variants]/(main)/discover/DiscoverRouter.tsx +2 -1
- package/src/features/Conversation/Messages/Assistant/Tool/Render/index.tsx +4 -2
- package/src/store/chat/slices/builtinTool/actions/{dalle.test.ts → __tests__/dalle.test.ts} +2 -5
- package/src/store/chat/slices/builtinTool/actions/__tests__/{localFile.test.ts → localSystem.test.ts} +4 -4
- package/src/store/chat/slices/builtinTool/actions/index.ts +2 -2
- package/src/store/chat/slices/builtinTool/actions/{localFile.ts → localSystem.ts} +183 -69
- package/src/store/electron/selectors/__tests__/desktopState.test.ts +3 -3
- package/src/store/electron/selectors/desktopState.ts +11 -2
- package/src/tools/local-system/Placeholder/ListFiles.tsx +10 -8
- package/src/tools/local-system/Placeholder/SearchFiles.tsx +12 -10
- package/src/tools/local-system/Placeholder/index.tsx +1 -1
- package/src/tools/local-system/Render/ReadLocalFile/ReadFileSkeleton.tsx +8 -18
- package/src/tools/local-system/Render/ReadLocalFile/ReadFileView.tsx +21 -6
- package/src/tools/local-system/Render/SearchFiles/Result.tsx +5 -4
- package/src/tools/local-system/Render/SearchFiles/SearchQuery/SearchView.tsx +4 -15
- package/src/tools/local-system/Render/SearchFiles/index.tsx +3 -2
- package/src/tools/local-system/type.ts +39 -0
- package/src/tools/local-system/Placeholder/ReadLocalFile.tsx +0 -9
- package/src/tools/local-system/Render/ReadLocalFile/style.ts +0 -37
- /package/src/store/chat/slices/builtinTool/actions/{search.test.ts → __tests__/search.test.ts} +0 -0
|
@@ -369,7 +369,7 @@ describe('AgentRuntime', () => {
|
|
|
369
369
|
type: 'tool_pending',
|
|
370
370
|
});
|
|
371
371
|
|
|
372
|
-
expect(result.newState.status).toBe('
|
|
372
|
+
expect(result.newState.status).toBe('waiting_for_human');
|
|
373
373
|
expect(result.newState.pendingToolsCalling).toBeDefined();
|
|
374
374
|
});
|
|
375
375
|
|
|
@@ -396,7 +396,7 @@ describe('AgentRuntime', () => {
|
|
|
396
396
|
sessionId: 'test-session',
|
|
397
397
|
});
|
|
398
398
|
|
|
399
|
-
expect(result.newState.status).toBe('
|
|
399
|
+
expect(result.newState.status).toBe('waiting_for_human');
|
|
400
400
|
expect(result.newState.pendingHumanPrompt).toEqual({
|
|
401
401
|
prompt: 'Please provide input',
|
|
402
402
|
metadata: { key: 'value' },
|
|
@@ -434,7 +434,7 @@ describe('AgentRuntime', () => {
|
|
|
434
434
|
sessionId: 'test-session',
|
|
435
435
|
});
|
|
436
436
|
|
|
437
|
-
expect(result.newState.status).toBe('
|
|
437
|
+
expect(result.newState.status).toBe('waiting_for_human');
|
|
438
438
|
});
|
|
439
439
|
});
|
|
440
440
|
|
|
@@ -733,7 +733,7 @@ describe('AgentRuntime', () => {
|
|
|
733
733
|
},
|
|
734
734
|
tools: {
|
|
735
735
|
totalCalls: 0,
|
|
736
|
-
byTool:
|
|
736
|
+
byTool: [],
|
|
737
737
|
totalTimeMs: 0,
|
|
738
738
|
},
|
|
739
739
|
humanInteraction: {
|
|
@@ -746,12 +746,12 @@ describe('AgentRuntime', () => {
|
|
|
746
746
|
|
|
747
747
|
expect(state.cost).toMatchObject({
|
|
748
748
|
llm: {
|
|
749
|
-
byModel:
|
|
749
|
+
byModel: [],
|
|
750
750
|
total: 0,
|
|
751
751
|
currency: 'USD',
|
|
752
752
|
},
|
|
753
753
|
tools: {
|
|
754
|
-
byTool:
|
|
754
|
+
byTool: [],
|
|
755
755
|
total: 0,
|
|
756
756
|
currency: 'USD',
|
|
757
757
|
},
|
|
@@ -890,8 +890,8 @@ describe('AgentRuntime', () => {
|
|
|
890
890
|
|
|
891
891
|
calculateCost(context: CostCalculationContext): Cost {
|
|
892
892
|
return {
|
|
893
|
-
llm: { byModel:
|
|
894
|
-
tools: { byTool:
|
|
893
|
+
llm: { byModel: [], total: 15.0, currency: 'USD' },
|
|
894
|
+
tools: { byTool: [], total: 0, currency: 'USD' },
|
|
895
895
|
total: 15.0,
|
|
896
896
|
currency: 'USD',
|
|
897
897
|
calculatedAt: new Date().toISOString(),
|
|
@@ -1018,7 +1018,7 @@ describe('AgentRuntime', () => {
|
|
|
1018
1018
|
result = await runtime.step(result.newState, result.nextContext);
|
|
1019
1019
|
|
|
1020
1020
|
// Now should request human approval
|
|
1021
|
-
expect(result.newState.status).toBe('
|
|
1021
|
+
expect(result.newState.status).toBe('waiting_for_human');
|
|
1022
1022
|
expect(result.newState.pendingToolsCalling).toHaveLength(1);
|
|
1023
1023
|
|
|
1024
1024
|
// Step 2: Approve and execute tool call
|
|
@@ -1210,7 +1210,7 @@ describe('AgentRuntime', () => {
|
|
|
1210
1210
|
expect(agent.tools.safe_tool).toHaveBeenCalled();
|
|
1211
1211
|
|
|
1212
1212
|
// Should be in waiting state (blocked by approval request)
|
|
1213
|
-
expect(result.newState.status).toBe('
|
|
1213
|
+
expect(result.newState.status).toBe('waiting_for_human');
|
|
1214
1214
|
|
|
1215
1215
|
// Should have pending tool calls
|
|
1216
1216
|
expect(result.newState.pendingToolsCalling).toHaveLength(1);
|
|
@@ -1333,8 +1333,8 @@ describe('AgentRuntime', () => {
|
|
|
1333
1333
|
return {
|
|
1334
1334
|
calculatedAt: new Date().toISOString(),
|
|
1335
1335
|
currency: 'USD',
|
|
1336
|
-
llm: { byModel:
|
|
1337
|
-
tools: { byTool:
|
|
1336
|
+
llm: { byModel: [], currency: 'USD', total: 15.0 },
|
|
1337
|
+
tools: { byTool: [], currency: 'USD', total: 0 },
|
|
1338
1338
|
total: 15.0,
|
|
1339
1339
|
};
|
|
1340
1340
|
}
|
|
@@ -1396,8 +1396,8 @@ describe('AgentRuntime', () => {
|
|
|
1396
1396
|
return {
|
|
1397
1397
|
calculatedAt: new Date().toISOString(),
|
|
1398
1398
|
currency: 'USD',
|
|
1399
|
-
llm: { byModel:
|
|
1400
|
-
tools: { byTool:
|
|
1399
|
+
llm: { byModel: [], currency: 'USD', total: 0 },
|
|
1400
|
+
tools: { byTool: [], currency: 'USD', total: 20.0 },
|
|
1401
1401
|
total: 20.0,
|
|
1402
1402
|
};
|
|
1403
1403
|
}
|
|
@@ -1438,8 +1438,8 @@ describe('AgentRuntime', () => {
|
|
|
1438
1438
|
const baseCost = context.previousCost || {
|
|
1439
1439
|
calculatedAt: new Date().toISOString(),
|
|
1440
1440
|
currency: 'USD',
|
|
1441
|
-
llm: { byModel:
|
|
1442
|
-
tools: { byTool:
|
|
1441
|
+
llm: { byModel: [], currency: 'USD', total: 0 },
|
|
1442
|
+
tools: { byTool: [], currency: 'USD', total: 0 },
|
|
1443
1443
|
total: 0,
|
|
1444
1444
|
};
|
|
1445
1445
|
|
|
@@ -1447,7 +1447,7 @@ describe('AgentRuntime', () => {
|
|
|
1447
1447
|
...baseCost,
|
|
1448
1448
|
calculatedAt: new Date().toISOString(),
|
|
1449
1449
|
tools: {
|
|
1450
|
-
byTool:
|
|
1450
|
+
byTool: [],
|
|
1451
1451
|
currency: 'USD',
|
|
1452
1452
|
total: baseCost.tools.total + 5.0,
|
|
1453
1453
|
},
|
|
@@ -1514,15 +1514,17 @@ describe('AgentRuntime', () => {
|
|
|
1514
1514
|
newUsage.tools.totalCalls += 1;
|
|
1515
1515
|
newUsage.tools.totalTimeMs += 100;
|
|
1516
1516
|
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1517
|
+
const existingTool = newUsage.tools.byTool.find((t) => t.name === toolName);
|
|
1518
|
+
if (existingTool) {
|
|
1519
|
+
existingTool.calls += 1;
|
|
1520
|
+
existingTool.totalTimeMs += 100;
|
|
1520
1521
|
} else {
|
|
1521
|
-
newUsage.tools.byTool
|
|
1522
|
+
newUsage.tools.byTool.push({
|
|
1522
1523
|
calls: 1,
|
|
1523
1524
|
errors: 0,
|
|
1525
|
+
name: toolName,
|
|
1524
1526
|
totalTimeMs: 100,
|
|
1525
|
-
};
|
|
1527
|
+
});
|
|
1526
1528
|
}
|
|
1527
1529
|
|
|
1528
1530
|
return newUsage;
|
|
@@ -1567,10 +1569,14 @@ describe('AgentRuntime', () => {
|
|
|
1567
1569
|
|
|
1568
1570
|
// Should have per-tool statistics
|
|
1569
1571
|
expect(result.newState.usage.tools.totalCalls).toBe(2);
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1572
|
+
const analyticsTool = result.newState.usage.tools.byTool.find(
|
|
1573
|
+
(t) => t.name === 'analytics_tool',
|
|
1574
|
+
);
|
|
1575
|
+
const loggingTool = result.newState.usage.tools.byTool.find((t) => t.name === 'logging_tool');
|
|
1576
|
+
expect(analyticsTool).toBeDefined();
|
|
1577
|
+
expect(analyticsTool!.calls).toBe(1);
|
|
1578
|
+
expect(loggingTool).toBeDefined();
|
|
1579
|
+
expect(loggingTool!.calls).toBe(1);
|
|
1574
1580
|
});
|
|
1575
1581
|
});
|
|
1576
1582
|
});
|
|
@@ -120,10 +120,7 @@ export class AgentRuntime {
|
|
|
120
120
|
}
|
|
121
121
|
|
|
122
122
|
// Stop execution if blocked
|
|
123
|
-
if (
|
|
124
|
-
currentState.status === 'waiting_for_human_input' ||
|
|
125
|
-
currentState.status === 'interrupted'
|
|
126
|
-
) {
|
|
123
|
+
if (currentState.status === 'waiting_for_human' || currentState.status === 'interrupted') {
|
|
127
124
|
break;
|
|
128
125
|
}
|
|
129
126
|
}
|
|
@@ -273,7 +270,7 @@ export class AgentRuntime {
|
|
|
273
270
|
tokens: { input: 0, output: 0, total: 0 },
|
|
274
271
|
},
|
|
275
272
|
tools: {
|
|
276
|
-
byTool:
|
|
273
|
+
byTool: [],
|
|
277
274
|
totalCalls: 0,
|
|
278
275
|
totalTimeMs: 0,
|
|
279
276
|
},
|
|
@@ -290,12 +287,12 @@ export class AgentRuntime {
|
|
|
290
287
|
calculatedAt: now,
|
|
291
288
|
currency: 'USD',
|
|
292
289
|
llm: {
|
|
293
|
-
byModel:
|
|
290
|
+
byModel: [],
|
|
294
291
|
currency: 'USD',
|
|
295
292
|
total: 0,
|
|
296
293
|
},
|
|
297
294
|
tools: {
|
|
298
|
-
byTool:
|
|
295
|
+
byTool: [],
|
|
299
296
|
currency: 'USD',
|
|
300
297
|
total: 0,
|
|
301
298
|
},
|
|
@@ -308,7 +305,9 @@ export class AgentRuntime {
|
|
|
308
305
|
* @param partialState - Partial state to override defaults
|
|
309
306
|
* @returns Complete AgentState with defaults filled in
|
|
310
307
|
*/
|
|
311
|
-
static createInitialState(
|
|
308
|
+
static createInitialState(
|
|
309
|
+
partialState?: Partial<AgentState> & { sessionId: string },
|
|
310
|
+
): AgentState {
|
|
312
311
|
const now = new Date().toISOString();
|
|
313
312
|
|
|
314
313
|
return {
|
|
@@ -319,9 +318,10 @@ export class AgentRuntime {
|
|
|
319
318
|
messages: [],
|
|
320
319
|
status: 'idle',
|
|
321
320
|
stepCount: 0,
|
|
321
|
+
toolManifestMap: {},
|
|
322
322
|
usage: AgentRuntime.createDefaultUsage(),
|
|
323
323
|
// User provided values override defaults
|
|
324
|
-
...partialState,
|
|
324
|
+
...(partialState || { sessionId: '' }),
|
|
325
325
|
};
|
|
326
326
|
}
|
|
327
327
|
|
|
@@ -489,7 +489,7 @@ export class AgentRuntime {
|
|
|
489
489
|
const newState = structuredClone(state);
|
|
490
490
|
|
|
491
491
|
newState.lastModified = new Date().toISOString();
|
|
492
|
-
newState.status = '
|
|
492
|
+
newState.status = 'waiting_for_human';
|
|
493
493
|
newState.pendingToolsCalling = pendingToolsCalling;
|
|
494
494
|
|
|
495
495
|
const events: AgentEvent[] = [
|
|
@@ -515,7 +515,7 @@ export class AgentRuntime {
|
|
|
515
515
|
const newState = structuredClone(state);
|
|
516
516
|
|
|
517
517
|
newState.lastModified = new Date().toISOString();
|
|
518
|
-
newState.status = '
|
|
518
|
+
newState.status = 'waiting_for_human';
|
|
519
519
|
newState.pendingHumanPrompt = { metadata, prompt };
|
|
520
520
|
|
|
521
521
|
const events: AgentEvent[] = [
|
|
@@ -541,7 +541,7 @@ export class AgentRuntime {
|
|
|
541
541
|
const newState = structuredClone(state);
|
|
542
542
|
|
|
543
543
|
newState.lastModified = new Date().toISOString();
|
|
544
|
-
newState.status = '
|
|
544
|
+
newState.status = 'waiting_for_human';
|
|
545
545
|
newState.pendingHumanSelect = { metadata, multi, options, prompt };
|
|
546
546
|
|
|
547
547
|
const events: AgentEvent[] = [
|
|
@@ -641,13 +641,15 @@ export class AgentRuntime {
|
|
|
641
641
|
newState.usage.tools.totalCalls += result.newState.usage.tools.totalCalls;
|
|
642
642
|
newState.usage.tools.totalTimeMs += result.newState.usage.tools.totalTimeMs;
|
|
643
643
|
|
|
644
|
-
// Merge per-tool statistics
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
644
|
+
// Merge per-tool statistics (now using array)
|
|
645
|
+
result.newState.usage.tools.byTool.forEach((toolStats) => {
|
|
646
|
+
const existingTool = newState.usage.tools.byTool.find((t) => t.name === toolStats.name);
|
|
647
|
+
if (existingTool) {
|
|
648
|
+
existingTool.calls += toolStats.calls;
|
|
649
|
+
existingTool.totalTimeMs += toolStats.totalTimeMs;
|
|
650
|
+
existingTool.errors += toolStats.errors || 0;
|
|
649
651
|
} else {
|
|
650
|
-
newState.usage.tools.byTool
|
|
652
|
+
newState.usage.tools.byTool.push({ ...toolStats });
|
|
651
653
|
}
|
|
652
654
|
});
|
|
653
655
|
}
|
|
@@ -656,6 +658,17 @@ export class AgentRuntime {
|
|
|
656
658
|
if (result.newState.cost && newState.cost) {
|
|
657
659
|
newState.cost.tools.total += result.newState.cost.tools.total;
|
|
658
660
|
newState.cost.total += result.newState.cost.tools.total;
|
|
661
|
+
|
|
662
|
+
// Merge per-tool cost statistics (now using array)
|
|
663
|
+
result.newState.cost.tools.byTool.forEach((toolCost) => {
|
|
664
|
+
const existingToolCost = newState.cost.tools.byTool.find((t) => t.name === toolCost.name);
|
|
665
|
+
if (existingToolCost) {
|
|
666
|
+
existingToolCost.calls += toolCost.calls;
|
|
667
|
+
existingToolCost.totalCost += toolCost.totalCost;
|
|
668
|
+
} else {
|
|
669
|
+
newState.cost.tools.byTool.push({ ...toolCost });
|
|
670
|
+
}
|
|
671
|
+
});
|
|
659
672
|
}
|
|
660
673
|
}
|
|
661
674
|
|
|
@@ -8,13 +8,13 @@ import type { Cost, CostLimit, Usage } from './usage';
|
|
|
8
8
|
export interface AgentState {
|
|
9
9
|
sessionId: string;
|
|
10
10
|
// --- State Machine ---
|
|
11
|
-
status: 'idle' | 'running' | '
|
|
11
|
+
status: 'idle' | 'running' | 'waiting_for_human' | 'done' | 'error' | 'interrupted';
|
|
12
12
|
|
|
13
13
|
// --- Core Context ---
|
|
14
14
|
messages: any[];
|
|
15
15
|
tools?: any[];
|
|
16
16
|
systemRole?: string;
|
|
17
|
-
|
|
17
|
+
toolManifestMap: Record<string, any>;
|
|
18
18
|
// --- Execution Tracking ---
|
|
19
19
|
/**
|
|
20
20
|
* Number of execution steps in this session.
|
|
@@ -46,7 +46,7 @@ export interface AgentState {
|
|
|
46
46
|
|
|
47
47
|
// --- HIL ---
|
|
48
48
|
/**
|
|
49
|
-
* When status is '
|
|
49
|
+
* When status is 'waiting_for_human', this stores pending requests
|
|
50
50
|
* for human-in-the-loop operations.
|
|
51
51
|
*/
|
|
52
52
|
pendingToolsCalling?: ToolsCalling[];
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { ModelUsage } from '@lobechat/types';
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* Token usage tracking for different types of operations
|
|
3
5
|
*/
|
|
@@ -39,14 +41,16 @@ export interface Usage {
|
|
|
39
41
|
/** Tool usage statistics */
|
|
40
42
|
tools: {
|
|
41
43
|
/** Usage breakdown by tool name */
|
|
42
|
-
byTool:
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
44
|
+
byTool: Array<{
|
|
45
|
+
/** Number of calls */
|
|
46
|
+
calls: number;
|
|
47
|
+
/** Number of errors */
|
|
48
|
+
errors: number;
|
|
49
|
+
/** Tool name/identifier */
|
|
50
|
+
name: string;
|
|
51
|
+
/** Total execution time in milliseconds */
|
|
52
|
+
totalTimeMs: number;
|
|
53
|
+
}>;
|
|
50
54
|
/** Number of tool calls executed */
|
|
51
55
|
totalCalls: number;
|
|
52
56
|
/** Total tool execution time */
|
|
@@ -66,15 +70,18 @@ export interface Cost {
|
|
|
66
70
|
/** LLM API costs */
|
|
67
71
|
llm: {
|
|
68
72
|
/** Cost per model used */
|
|
69
|
-
byModel:
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
73
|
+
byModel: Array<{
|
|
74
|
+
/** Model identifier in format "provider/model" */
|
|
75
|
+
id: string;
|
|
76
|
+
/** Model name */
|
|
77
|
+
model: string;
|
|
78
|
+
/** Provider name */
|
|
79
|
+
provider: string;
|
|
80
|
+
/** Total cost for this model */
|
|
81
|
+
totalCost: number;
|
|
82
|
+
/** Detailed usage breakdown */
|
|
83
|
+
usage: ModelUsage;
|
|
84
|
+
}>;
|
|
78
85
|
currency: string;
|
|
79
86
|
/** Total LLM cost */
|
|
80
87
|
total: number;
|
|
@@ -82,14 +89,16 @@ export interface Cost {
|
|
|
82
89
|
/** Tool execution costs */
|
|
83
90
|
tools: {
|
|
84
91
|
/** Cost per tool (if tool has associated costs) */
|
|
85
|
-
byTool:
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
92
|
+
byTool: Array<{
|
|
93
|
+
/** Number of calls */
|
|
94
|
+
calls: number;
|
|
95
|
+
/** Currency */
|
|
96
|
+
currency: string;
|
|
97
|
+
/** Tool name/identifier */
|
|
98
|
+
name: string;
|
|
99
|
+
/** Total cost for this tool */
|
|
100
|
+
totalCost: number;
|
|
101
|
+
}>;
|
|
93
102
|
currency: string;
|
|
94
103
|
/** Total tool cost */
|
|
95
104
|
total: number;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ChatToolPayload, MessageToolCall } from '@lobechat/types';
|
|
2
2
|
import { Md5 } from 'ts-md5';
|
|
3
3
|
|
|
4
|
-
import { LobeChatPluginApi,
|
|
4
|
+
import { LobeChatPluginApi, LobeToolManifest } from './types';
|
|
5
5
|
|
|
6
6
|
// Tool naming constants
|
|
7
7
|
const PLUGIN_SCHEMA_SEPARATOR = '____';
|
|
@@ -57,7 +57,7 @@ export class ToolNameResolver {
|
|
|
57
57
|
*/
|
|
58
58
|
resolve(
|
|
59
59
|
toolCalls: MessageToolCall[],
|
|
60
|
-
manifests: Record<string,
|
|
60
|
+
manifests: Record<string, LobeToolManifest>,
|
|
61
61
|
): ChatToolPayload[] {
|
|
62
62
|
return toolCalls
|
|
63
63
|
.map((toolCall): ChatToolPayload | null => {
|
|
@@ -3,7 +3,7 @@ import debug from 'debug';
|
|
|
3
3
|
import {
|
|
4
4
|
FunctionCallChecker,
|
|
5
5
|
GenerateToolsParams,
|
|
6
|
-
|
|
6
|
+
LobeToolManifest,
|
|
7
7
|
PluginEnableChecker,
|
|
8
8
|
ToolsEngineOptions,
|
|
9
9
|
ToolsGenerationContext,
|
|
@@ -18,7 +18,7 @@ const log = debug('context-engine:tools-engine');
|
|
|
18
18
|
* Tools Engine - Unified processing of tools array construction and transformation
|
|
19
19
|
*/
|
|
20
20
|
export class ToolsEngine {
|
|
21
|
-
private manifestSchemas: Map<string,
|
|
21
|
+
private manifestSchemas: Map<string, LobeToolManifest>;
|
|
22
22
|
private enableChecker?: PluginEnableChecker;
|
|
23
23
|
private functionCallChecker?: FunctionCallChecker;
|
|
24
24
|
private defaultToolIds: string[];
|
|
@@ -162,13 +162,13 @@ export class ToolsEngine {
|
|
|
162
162
|
context?: ToolsGenerationContext,
|
|
163
163
|
supportsFunctionCall?: boolean,
|
|
164
164
|
): {
|
|
165
|
-
enabledManifests:
|
|
165
|
+
enabledManifests: LobeToolManifest[];
|
|
166
166
|
filteredPlugins: Array<{
|
|
167
167
|
id: string;
|
|
168
168
|
reason: 'not_found' | 'disabled' | 'incompatible';
|
|
169
169
|
}>;
|
|
170
170
|
} {
|
|
171
|
-
const enabledManifests:
|
|
171
|
+
const enabledManifests: LobeToolManifest[] = [];
|
|
172
172
|
const filteredPlugins: Array<{
|
|
173
173
|
id: string;
|
|
174
174
|
reason: 'not_found' | 'disabled' | 'incompatible';
|
|
@@ -240,7 +240,7 @@ export class ToolsEngine {
|
|
|
240
240
|
/**
|
|
241
241
|
* Convert manifests to UniformTool array
|
|
242
242
|
*/
|
|
243
|
-
private convertManifestsToTools(manifests:
|
|
243
|
+
private convertManifestsToTools(manifests: LobeToolManifest[]): UniformTool[] {
|
|
244
244
|
log('Converting %d manifests to tools', manifests.length);
|
|
245
245
|
|
|
246
246
|
// Use simplified conversion logic to avoid external package dependencies
|
|
@@ -290,14 +290,14 @@ export class ToolsEngine {
|
|
|
290
290
|
/**
|
|
291
291
|
* 获取插件的 manifest
|
|
292
292
|
*/
|
|
293
|
-
getPluginManifest(pluginId: string):
|
|
293
|
+
getPluginManifest(pluginId: string): LobeToolManifest | undefined {
|
|
294
294
|
return this.manifestSchemas.get(pluginId);
|
|
295
295
|
}
|
|
296
296
|
|
|
297
297
|
/**
|
|
298
298
|
* 更新插件 manifest schemas(用于动态添加插件)
|
|
299
299
|
*/
|
|
300
|
-
updateManifestSchemas(manifestSchemas:
|
|
300
|
+
updateManifestSchemas(manifestSchemas: LobeToolManifest[]): void {
|
|
301
301
|
this.manifestSchemas.clear();
|
|
302
302
|
for (const schema of manifestSchemas) {
|
|
303
303
|
this.manifestSchemas.set(schema.identifier, schema);
|
|
@@ -307,7 +307,7 @@ export class ToolsEngine {
|
|
|
307
307
|
/**
|
|
308
308
|
* 添加单个插件 manifest
|
|
309
309
|
*/
|
|
310
|
-
addPluginManifest(manifest:
|
|
310
|
+
addPluginManifest(manifest: LobeToolManifest): void {
|
|
311
311
|
this.manifestSchemas.set(manifest.identifier, manifest);
|
|
312
312
|
}
|
|
313
313
|
|
|
@@ -317,4 +317,33 @@ export class ToolsEngine {
|
|
|
317
317
|
removePluginManifest(pluginId: string): boolean {
|
|
318
318
|
return this.manifestSchemas.delete(pluginId);
|
|
319
319
|
}
|
|
320
|
+
|
|
321
|
+
/**
|
|
322
|
+
* 获取所有 enabled plugin 的 Manifest Map
|
|
323
|
+
*/
|
|
324
|
+
getEnabledPluginManifests(toolIds: string[] = []): Map<string, LobeToolManifest> {
|
|
325
|
+
// Merge user-provided tool IDs with default tool IDs
|
|
326
|
+
const allToolIds = [...toolIds, ...this.defaultToolIds];
|
|
327
|
+
|
|
328
|
+
log('Getting enabled plugin manifests for pluginIds=%o', allToolIds);
|
|
329
|
+
|
|
330
|
+
const manifestMap = new Map<string, LobeToolManifest>();
|
|
331
|
+
|
|
332
|
+
for (const pluginId of allToolIds) {
|
|
333
|
+
const manifest = this.manifestSchemas.get(pluginId);
|
|
334
|
+
if (manifest) {
|
|
335
|
+
manifestMap.set(pluginId, manifest);
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
log('Returning %d enabled plugin manifests', manifestMap.size);
|
|
340
|
+
return manifestMap;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
/**
|
|
344
|
+
* 获取所有插件的 Manifest Map
|
|
345
|
+
*/
|
|
346
|
+
getAllPluginManifests(): Map<string, LobeToolManifest> {
|
|
347
|
+
return new Map(this.manifestSchemas);
|
|
348
|
+
}
|
|
320
349
|
}
|