@lobehub/lobehub 2.0.0-next.194 → 2.0.0-next.195

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.
Files changed (29) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/changelog/v1.json +9 -0
  3. package/package.json +1 -1
  4. package/packages/database/src/models/user.ts +8 -0
  5. package/packages/database/src/repositories/aiInfra/index.test.ts +11 -8
  6. package/packages/database/src/repositories/dataExporter/index.test.ts +11 -9
  7. package/packages/database/src/repositories/tableViewer/index.test.ts +13 -14
  8. package/packages/model-runtime/src/providers/zhipu/index.ts +6 -6
  9. package/src/envs/app.ts +2 -0
  10. package/src/libs/trpc/lambda/middleware/index.ts +1 -0
  11. package/src/libs/trpc/lambda/middleware/telemetry.test.ts +237 -0
  12. package/src/libs/trpc/lambda/middleware/telemetry.ts +74 -0
  13. package/src/server/routers/lambda/market/index.ts +1 -93
  14. package/src/server/routers/tools/_helpers/index.ts +1 -0
  15. package/src/server/routers/tools/_helpers/scheduleToolCallReport.ts +113 -0
  16. package/src/server/routers/tools/index.ts +2 -2
  17. package/src/server/routers/tools/market.ts +375 -0
  18. package/src/server/routers/tools/mcp.ts +77 -20
  19. package/src/services/chat/index.ts +0 -2
  20. package/src/services/codeInterpreter.ts +6 -6
  21. package/src/services/mcp.test.ts +60 -46
  22. package/src/services/mcp.ts +67 -48
  23. package/src/store/chat/slices/plugin/action.test.ts +191 -0
  24. package/src/store/chat/slices/plugin/actions/internals.ts +2 -18
  25. package/src/store/chat/slices/plugin/actions/pluginTypes.ts +31 -44
  26. package/packages/database/src/client/db.test.ts +0 -52
  27. package/packages/database/src/client/db.ts +0 -195
  28. package/packages/database/src/client/type.ts +0 -6
  29. package/src/server/routers/tools/codeInterpreter.ts +0 -255
@@ -36,6 +36,11 @@ vi.mock('@lobechat/utils', () => ({
36
36
 
37
37
  vi.mock('@/libs/trpc/client', () => ({
38
38
  toolsClient: {
39
+ market: {
40
+ callCloudMcpEndpoint: {
41
+ mutate: vi.fn(),
42
+ },
43
+ },
39
44
  mcp: {
40
45
  callTool: {
41
46
  mutate: vi.fn(),
@@ -53,6 +58,7 @@ vi.mock('@/utils/electron/ipc', () => ({
53
58
 
54
59
  vi.mock('./discover', () => ({
55
60
  discoverService: {
61
+ injectMPToken: vi.fn().mockResolvedValue(undefined),
56
62
  reportPluginCall: vi.fn().mockResolvedValue(undefined),
57
63
  },
58
64
  }));
@@ -129,22 +135,20 @@ describe('MCPService', () => {
129
135
  name: 'test-plugin',
130
136
  env: { API_KEY: 'test-key' },
131
137
  },
138
+ meta: {
139
+ customPluginInfo: undefined,
140
+ isCustomPlugin: false,
141
+ sessionId: 'topic-1',
142
+ version: '1.0.0',
143
+ },
132
144
  toolName: 'testMethod',
133
145
  },
134
146
  { signal: undefined },
135
147
  );
136
148
 
137
- // Wait for async reporting to complete
149
+ // For SSE type, reporting is handled by server-side, frontend should NOT call reportPluginCall
138
150
  await new Promise((resolve) => setTimeout(resolve, 10));
139
-
140
- expect(discoverService.reportPluginCall).toHaveBeenCalled();
141
- const reportCall = vi.mocked(discoverService.reportPluginCall).mock.calls[0][0];
142
- expect(reportCall).toMatchObject({
143
- identifier: 'test-plugin',
144
- methodName: 'testMethod',
145
- success: true,
146
- isCustomPlugin: false,
147
- });
151
+ expect(discoverService.reportPluginCall).not.toHaveBeenCalled();
148
152
  });
149
153
 
150
154
  it('should invoke tool call with custom plugin', async () => {
@@ -274,28 +278,22 @@ describe('MCPService', () => {
274
278
 
275
279
  await expect(mcpService.invokeMcpToolCall(payload, {})).rejects.toThrow('Tool call failed');
276
280
 
277
- // Wait for async reporting to complete
281
+ // For SSE type, reporting is handled by server-side, frontend should NOT call reportPluginCall
278
282
  await new Promise((resolve) => setTimeout(resolve, 10));
279
-
280
- expect(discoverService.reportPluginCall).toHaveBeenCalled();
281
- const reportCall = vi.mocked(discoverService.reportPluginCall).mock.calls[0][0];
282
- expect(reportCall).toMatchObject({
283
- success: false,
284
- errorCode: 'CALL_FAILED',
285
- errorMessage: 'Tool call failed',
286
- });
283
+ expect(discoverService.reportPluginCall).not.toHaveBeenCalled();
287
284
  });
288
285
 
289
- it('should calculate request and response sizes correctly', async () => {
290
- const { toolsClient } = await import('@/libs/trpc/client');
286
+ it('should call toolsClient.market.callCloudMcpEndpoint for cloud type and not report from frontend', async () => {
291
287
  const { discoverService } = await import('./discover');
288
+ const { toolsClient } = await import('@/libs/trpc/client');
292
289
 
290
+ // Use cloud type which now reports from server-side
293
291
  const mockPlugin = {
294
292
  customParams: {
295
- mcp: { type: 'sse' },
293
+ mcp: { type: 'cloud' },
296
294
  },
297
295
  manifest: {
298
- meta: { title: 'Size Test Plugin' },
296
+ meta: { title: 'Cloud Plugin' },
299
297
  version: '1.0.0',
300
298
  },
301
299
  };
@@ -303,32 +301,44 @@ describe('MCPService', () => {
303
301
  mockPluginSelectors.getInstalledPluginById.mockReturnValue(() => mockPlugin);
304
302
  mockPluginSelectors.getCustomPluginById.mockReturnValue(() => null);
305
303
 
304
+ // Mock the toolsClient for cloud type
306
305
  const mockResult = {
307
306
  content: 'response data',
308
307
  state: {
309
- content: [{ text: 'response data', type: 'text' }],
308
+ content: [{ text: 'response data', type: 'text' as const }],
310
309
  },
311
310
  success: true,
312
311
  };
313
- vi.mocked(toolsClient.mcp.callTool.mutate).mockResolvedValue(mockResult);
312
+ vi.mocked(toolsClient.market.callCloudMcpEndpoint.mutate).mockResolvedValue(mockResult);
314
313
 
315
314
  const payload: ChatToolPayload = {
316
315
  id: 'tool-call-6',
317
- identifier: 'size-plugin',
318
- apiName: 'sizeMethod',
316
+ identifier: 'cloud-plugin',
317
+ apiName: 'cloudMethod',
319
318
  arguments: '{"key": "value"}',
320
319
  type: 'standalone',
321
320
  };
322
321
 
323
- await mcpService.invokeMcpToolCall(payload, {});
322
+ const result = await mcpService.invokeMcpToolCall(payload, { topicId: 'topic-123' });
323
+
324
+ expect(result).toEqual(mockResult);
325
+ expect(toolsClient.market.callCloudMcpEndpoint.mutate).toHaveBeenCalledWith({
326
+ apiParams: { key: 'value' },
327
+ identifier: 'cloud-plugin',
328
+ meta: {
329
+ customPluginInfo: undefined,
330
+ isCustomPlugin: false,
331
+ sessionId: 'topic-123',
332
+ version: '1.0.0',
333
+ },
334
+ toolName: 'cloudMethod',
335
+ });
324
336
 
325
337
  // Wait for async reporting
326
338
  await new Promise((resolve) => setTimeout(resolve, 10));
327
339
 
328
- expect(discoverService.reportPluginCall).toHaveBeenCalled();
329
- const reportCall = vi.mocked(discoverService.reportPluginCall).mock.calls[0][0];
330
- expect(reportCall.requestSizeBytes).toBeGreaterThan(0);
331
- expect(reportCall.responseSizeBytes).toBeGreaterThan(0);
340
+ // Cloud type should NOT report from frontend (handled server-side)
341
+ expect(discoverService.reportPluginCall).not.toHaveBeenCalled();
332
342
  });
333
343
 
334
344
  it('should handle abort signal', async () => {
@@ -372,9 +382,8 @@ describe('MCPService', () => {
372
382
  expect(result).toEqual(mockResult);
373
383
  });
374
384
 
375
- it('should report custom plugin info correctly', async () => {
385
+ it('should pass meta to server for custom plugin', async () => {
376
386
  const { toolsClient } = await import('@/libs/trpc/client');
377
- const { discoverService } = await import('./discover');
378
387
 
379
388
  const mockCustomPlugin = {
380
389
  customParams: {
@@ -406,19 +415,24 @@ describe('MCPService', () => {
406
415
  type: 'standalone',
407
416
  };
408
417
 
409
- await mcpService.invokeMcpToolCall(payload, {});
410
-
411
- // Wait for async reporting
412
- await new Promise((resolve) => setTimeout(resolve, 10));
418
+ await mcpService.invokeMcpToolCall(payload, { topicId: 'topic-123' });
413
419
 
414
- expect(discoverService.reportPluginCall).toHaveBeenCalled();
415
- const reportCall = vi.mocked(discoverService.reportPluginCall).mock.calls[0][0];
416
- expect(reportCall.isCustomPlugin).toBe(true);
417
- expect(reportCall.customPluginInfo).toEqual({
418
- avatar: '🔧',
419
- description: 'Custom tool description',
420
- name: 'Custom Tool',
421
- });
420
+ // Verify meta is passed to server
421
+ expect(toolsClient.mcp.callTool.mutate).toHaveBeenCalledWith(
422
+ expect.objectContaining({
423
+ meta: {
424
+ customPluginInfo: {
425
+ avatar: '🔧',
426
+ description: 'Custom tool description',
427
+ name: 'Custom Tool',
428
+ },
429
+ isCustomPlugin: true,
430
+ sessionId: 'topic-123',
431
+ version: '3.0.0',
432
+ },
433
+ }),
434
+ expect.anything(),
435
+ );
422
436
  });
423
437
  });
424
438
 
@@ -1,12 +1,16 @@
1
1
  import { CURRENT_VERSION, isDesktop } from '@lobechat/const';
2
- import { type ChatToolPayload, type CheckMcpInstallResult, type CustomPluginMetadata } from '@lobechat/types';
2
+ import {
3
+ type ChatToolPayload,
4
+ type CheckMcpInstallResult,
5
+ type CustomPluginMetadata,
6
+ } from '@lobechat/types';
3
7
  import { isLocalOrPrivateUrl, safeParseJSON } from '@lobechat/utils';
4
8
  import { type PluginManifest } from '@lobehub/market-sdk';
5
9
  import { type CallReportRequest } from '@lobehub/market-types';
6
10
  import superjson from 'superjson';
7
11
 
8
12
  import { type MCPToolCallResult } from '@/libs/mcp';
9
- import { lambdaClient, toolsClient } from '@/libs/trpc/client';
13
+ import { toolsClient } from '@/libs/trpc/client';
10
14
  import { ensureElectronIpc } from '@/utils/electron/ipc';
11
15
 
12
16
  import { discoverService } from './discover';
@@ -31,6 +35,8 @@ class MCPService {
31
35
  payload: ChatToolPayload,
32
36
  { signal, topicId }: { signal?: AbortSignal; topicId?: string },
33
37
  ) {
38
+ await discoverService.injectMPToken();
39
+
34
40
  const { pluginSelectors } = await import('@/store/tool/selectors');
35
41
  const { getToolStoreState } = await import('@/store/tool/store');
36
42
 
@@ -80,12 +86,28 @@ class MCPService {
80
86
 
81
87
  const isStdio = plugin?.customParams?.mcp?.type === 'stdio';
82
88
  const isCloud = plugin?.customParams?.mcp?.type === 'cloud';
89
+ const isCustomPlugin = !!customPlugin;
90
+
91
+ // Build meta for server-side reporting
92
+ const meta = {
93
+ customPluginInfo: isCustomPlugin
94
+ ? {
95
+ avatar: plugin.manifest?.meta.avatar,
96
+ description: plugin.manifest?.meta.description,
97
+ name: plugin.manifest?.meta.title,
98
+ }
99
+ : undefined,
100
+ isCustomPlugin,
101
+ sessionId: topicId,
102
+ version: plugin.manifest?.version || 'unknown',
103
+ };
83
104
 
84
105
  const data = {
85
106
  // For desktop IPC, always pass a record/object for tool "arguments"
86
107
  // (IPC layer will superjson serialize the whole payload).
87
108
  args: isDesktop && isStdio ? (safeParseJSON(args) ?? {}) : args,
88
109
  env: connection?.type === 'stdio' ? params.env : (pluginSettings ?? connection?.env),
110
+ meta,
89
111
  params,
90
112
  toolName: apiName,
91
113
  };
@@ -103,13 +125,14 @@ class MCPService {
103
125
  // Parse args
104
126
  const apiParams = safeParseJSON(args) || {};
105
127
 
106
- // Call cloud gateway via lambda market endpoint
128
+ // Call cloud gateway via tools market endpoint
107
129
  // Server will automatically get user access token from database
108
130
  // and format the result to MCPToolCallResult
109
- // @ts-ignore tsgo 误报错误
110
- result = await lambdaClient.market.callCloudMcpEndpoint.mutate({
131
+ // Server-side also handles telemetry reporting
132
+ result = await toolsClient.market.callCloudMcpEndpoint.mutate({
111
133
  apiParams,
112
134
  identifier,
135
+ meta,
113
136
  toolName: apiName,
114
137
  });
115
138
  } else if (isDesktop && isStdio) {
@@ -134,50 +157,46 @@ class MCPService {
134
157
  // Rethrow error, maintain original error handling logic
135
158
  throw error;
136
159
  } finally {
137
- // Asynchronously report call result without affecting main flow
138
- const callEndTime = Date.now();
139
- const callDurationMs = callEndTime - callStartTime;
140
-
141
- // Calculate request size
142
- const inputParams = safeParseJSON(args) || args;
143
-
144
- const requestSizeBytes = calculateObjectSizeBytes(inputParams);
145
- // Calculate response size
146
- const responseSizeBytes = success && result ? calculateObjectSizeBytes(result.state) : 0;
147
-
148
- const isCustomPlugin = !!customPlugin;
149
- // Construct report data
150
- const reportData: CallReportRequest = {
151
- callDurationMs,
152
- customPluginInfo: isCustomPlugin
153
- ? {
154
- avatar: plugin.manifest?.meta.avatar,
155
- description: plugin.manifest?.meta.description,
156
- name: plugin.manifest?.meta.title,
157
- }
158
- : undefined,
159
- errorCode,
160
- errorMessage,
161
- identifier,
162
- isCustomPlugin,
163
- metadata: {
164
- appVersion: CURRENT_VERSION,
165
- command: plugin.customParams?.mcp?.command,
166
- mcpType: plugin.customParams?.mcp?.type,
167
- },
168
- methodName: apiName,
169
- methodType: 'tool' as const,
170
- requestSizeBytes,
171
- responseSizeBytes,
172
- sessionId: topicId,
173
- success,
174
- version: plugin.manifest!.version || 'unknown',
175
- };
160
+ // HTTP/SSE/streamable types: reporting is handled by server-side via mcp.callTool
161
+ // Cloud type: reporting is handled by server-side via market.callCloudMcpEndpoint
162
+ // Only report from frontend for stdio types (desktop only)
163
+ if (isStdio) {
164
+ const callEndTime = Date.now();
165
+ const callDurationMs = callEndTime - callStartTime;
166
+
167
+ // Calculate request size
168
+ const inputParams = safeParseJSON(args) || args;
169
+ const requestSizeBytes = calculateObjectSizeBytes(inputParams);
170
+ // Calculate response size
171
+ const responseSizeBytes = success && result ? calculateObjectSizeBytes(result.state) : 0;
176
172
 
177
- // Asynchronously report without affecting main flow
178
- discoverService.reportPluginCall(reportData).catch((reportError) => {
179
- console.warn('Failed to report MCP tool call:', reportError);
180
- });
173
+ // Construct report data
174
+ const reportData: CallReportRequest = {
175
+ callDurationMs,
176
+ customPluginInfo: meta.customPluginInfo,
177
+ errorCode,
178
+ errorMessage,
179
+ identifier,
180
+ isCustomPlugin,
181
+ metadata: {
182
+ appVersion: CURRENT_VERSION,
183
+ command: plugin.customParams?.mcp?.command,
184
+ mcpType: plugin.customParams?.mcp?.type,
185
+ },
186
+ methodName: apiName,
187
+ methodType: 'tool' as const,
188
+ requestSizeBytes,
189
+ responseSizeBytes,
190
+ sessionId: topicId,
191
+ success,
192
+ version: meta.version,
193
+ };
194
+
195
+ // Asynchronously report without affecting main flow
196
+ discoverService.reportPluginCall(reportData).catch((reportError) => {
197
+ console.warn('Failed to report MCP tool call:', reportError);
198
+ });
199
+ }
181
200
  }
182
201
  }
183
202
 
@@ -1429,4 +1429,195 @@ describe('ChatPluginAction', () => {
1429
1429
  });
1430
1430
  });
1431
1431
  });
1432
+
1433
+ describe('Plugin invoke functions use optimisticUpdateToolMessage', () => {
1434
+ const messageId = 'message-id';
1435
+ const payload: ChatToolPayload = {
1436
+ apiName: 'test-api',
1437
+ arguments: '{}',
1438
+ id: 'tool-call-id',
1439
+ identifier: 'test-plugin',
1440
+ type: 'default',
1441
+ };
1442
+
1443
+ describe('invokeMCPTypePlugin', () => {
1444
+ it('should use optimisticUpdateToolMessage for successful result', async () => {
1445
+ const mockResult = {
1446
+ content: 'mcp result content',
1447
+ state: { content: [], isError: false },
1448
+ success: true,
1449
+ };
1450
+
1451
+ // Mock the mcpService
1452
+ const mcpService = await import('@/services/mcp');
1453
+ vi.spyOn(mcpService.mcpService, 'invokeMcpToolCall').mockResolvedValue(mockResult);
1454
+
1455
+ const optimisticUpdateToolMessageMock = vi.fn().mockResolvedValue(undefined);
1456
+
1457
+ act(() => {
1458
+ useChatStore.setState({
1459
+ activeAgentId: 'session-id',
1460
+ messagesMap: { [messageMapKey({ agentId: 'session-id' })]: [] },
1461
+ optimisticUpdateToolMessage: optimisticUpdateToolMessageMock,
1462
+ replaceMessages: vi.fn(),
1463
+ messageOperationMap: {},
1464
+ operations: {},
1465
+ });
1466
+ });
1467
+
1468
+ const { result } = renderHook(() => useChatStore());
1469
+
1470
+ await act(async () => {
1471
+ await result.current.invokeMCPTypePlugin(messageId, payload);
1472
+ });
1473
+
1474
+ expect(optimisticUpdateToolMessageMock).toHaveBeenCalledWith(
1475
+ messageId,
1476
+ {
1477
+ content: mockResult.content,
1478
+ pluginError: undefined,
1479
+ pluginState: mockResult.state,
1480
+ },
1481
+ undefined,
1482
+ );
1483
+ });
1484
+
1485
+ it('should use optimisticUpdateToolMessage for error result', async () => {
1486
+ const mockResult = {
1487
+ content: 'error content',
1488
+ error: { message: 'test error' },
1489
+ state: { content: [], isError: true },
1490
+ success: false,
1491
+ };
1492
+
1493
+ const mcpService = await import('@/services/mcp');
1494
+ vi.spyOn(mcpService.mcpService, 'invokeMcpToolCall').mockResolvedValue(mockResult);
1495
+
1496
+ const optimisticUpdateToolMessageMock = vi.fn().mockResolvedValue(undefined);
1497
+
1498
+ act(() => {
1499
+ useChatStore.setState({
1500
+ activeAgentId: 'session-id',
1501
+ messagesMap: { [messageMapKey({ agentId: 'session-id' })]: [] },
1502
+ optimisticUpdateToolMessage: optimisticUpdateToolMessageMock,
1503
+ replaceMessages: vi.fn(),
1504
+ messageOperationMap: {},
1505
+ operations: {},
1506
+ });
1507
+ });
1508
+
1509
+ const { result } = renderHook(() => useChatStore());
1510
+
1511
+ await act(async () => {
1512
+ await result.current.invokeMCPTypePlugin(messageId, payload);
1513
+ });
1514
+
1515
+ expect(optimisticUpdateToolMessageMock).toHaveBeenCalledWith(
1516
+ messageId,
1517
+ {
1518
+ content: mockResult.content,
1519
+ pluginError: mockResult.error,
1520
+ pluginState: undefined,
1521
+ },
1522
+ undefined,
1523
+ );
1524
+ });
1525
+ });
1526
+
1527
+ describe('invokeKlavisTypePlugin', () => {
1528
+ it('should use optimisticUpdateToolMessage for successful result', async () => {
1529
+ const mockResult = {
1530
+ content: 'klavis result content',
1531
+ state: { data: 'test-data' },
1532
+ success: true,
1533
+ };
1534
+
1535
+ // Mock useToolStore to return a server
1536
+ vi.spyOn(useToolStore, 'getState').mockReturnValue({
1537
+ servers: [{ identifier: 'test-plugin', serverUrl: 'http://test.com' }],
1538
+ callKlavisTool: vi.fn().mockResolvedValue({
1539
+ success: true,
1540
+ data: mockResult,
1541
+ }),
1542
+ } as any);
1543
+
1544
+ const optimisticUpdateToolMessageMock = vi.fn().mockResolvedValue(undefined);
1545
+
1546
+ act(() => {
1547
+ useChatStore.setState({
1548
+ activeAgentId: 'session-id',
1549
+ messagesMap: { [messageMapKey({ agentId: 'session-id' })]: [] },
1550
+ optimisticUpdateToolMessage: optimisticUpdateToolMessageMock,
1551
+ replaceMessages: vi.fn(),
1552
+ messageOperationMap: {},
1553
+ operations: {},
1554
+ });
1555
+ });
1556
+
1557
+ const { result } = renderHook(() => useChatStore());
1558
+
1559
+ await act(async () => {
1560
+ await result.current.invokeKlavisTypePlugin(messageId, payload);
1561
+ });
1562
+
1563
+ expect(optimisticUpdateToolMessageMock).toHaveBeenCalledWith(
1564
+ messageId,
1565
+ {
1566
+ content: mockResult.content,
1567
+ pluginError: undefined,
1568
+ pluginState: mockResult.state,
1569
+ },
1570
+ undefined,
1571
+ );
1572
+ });
1573
+ });
1574
+
1575
+ describe('invokeCloudCodeInterpreterTool', () => {
1576
+ it('should use optimisticUpdateToolMessage for successful result', async () => {
1577
+ const mockResult = {
1578
+ content: 'code interpreter result',
1579
+ state: { output: 'test output' },
1580
+ success: true,
1581
+ };
1582
+
1583
+ // Mock CloudSandboxExecutionRuntime using doMock for dynamic mocking
1584
+ vi.doMock('@lobechat/builtin-tool-cloud-sandbox/executionRuntime', () => ({
1585
+ CloudSandboxExecutionRuntime: class {
1586
+ 'test-api' = vi.fn().mockResolvedValue(mockResult);
1587
+ },
1588
+ }));
1589
+
1590
+ const optimisticUpdateToolMessageMock = vi.fn().mockResolvedValue(undefined);
1591
+
1592
+ act(() => {
1593
+ useChatStore.setState({
1594
+ activeAgentId: 'session-id',
1595
+ messagesMap: { [messageMapKey({ agentId: 'session-id' })]: [] },
1596
+ optimisticUpdateToolMessage: optimisticUpdateToolMessageMock,
1597
+ replaceMessages: vi.fn(),
1598
+ messageOperationMap: {},
1599
+ operations: {},
1600
+ });
1601
+ });
1602
+
1603
+ const { result } = renderHook(() => useChatStore());
1604
+
1605
+ await act(async () => {
1606
+ await result.current.invokeCloudCodeInterpreterTool(messageId, payload);
1607
+ });
1608
+
1609
+ expect(optimisticUpdateToolMessageMock).toHaveBeenCalledWith(
1610
+ messageId,
1611
+ {
1612
+ content: mockResult.content,
1613
+ pluginError: undefined,
1614
+ pluginState: mockResult.state,
1615
+ },
1616
+ undefined,
1617
+ );
1618
+
1619
+ vi.doUnmock('@lobechat/builtin-tool-cloud-sandbox/executionRuntime');
1620
+ });
1621
+ });
1622
+ });
1432
1623
  });
@@ -1,6 +1,6 @@
1
1
  /* eslint-disable sort-keys-fix/sort-keys-fix, typescript-sort-keys/interface */
2
2
  import { ToolNameResolver } from '@lobechat/context-engine';
3
- import { type ChatToolPayload, type MessageToolCall, type ToolsCallingContext } from '@lobechat/types';
3
+ import { type ChatToolPayload, type MessageToolCall } from '@lobechat/types';
4
4
  import { type LobeChatPluginManifest } from '@lobehub/chat-plugin-sdk';
5
5
  import { type StateCreator } from 'zustand/vanilla';
6
6
 
@@ -9,8 +9,6 @@ import { useToolStore } from '@/store/tool';
9
9
  import { klavisStoreSelectors, pluginSelectors } from '@/store/tool/selectors';
10
10
  import { builtinTools } from '@/tools';
11
11
 
12
- import { displayMessageSelectors } from '../../message/selectors';
13
-
14
12
  /**
15
13
  * Internal utility methods and runtime state management
16
14
  * These are building blocks used by other actions
@@ -20,11 +18,6 @@ export interface PluginInternalsAction {
20
18
  * Transform tool calls from runtime format to storage format
21
19
  */
22
20
  internal_transformToolCalls: (toolCalls: MessageToolCall[]) => ChatToolPayload[];
23
-
24
- /**
25
- * Construct tools calling context for plugin invocation
26
- */
27
- internal_constructToolsCallingContext: (id: string) => ToolsCallingContext | undefined;
28
21
  }
29
22
 
30
23
  export const pluginInternals: StateCreator<
@@ -32,7 +25,7 @@ export const pluginInternals: StateCreator<
32
25
  [['zustand/devtools', never]],
33
26
  [],
34
27
  PluginInternalsAction
35
- > = (set, get) => ({
28
+ > = () => ({
36
29
  internal_transformToolCalls: (toolCalls) => {
37
30
  const toolNameResolver = new ToolNameResolver();
38
31
 
@@ -77,13 +70,4 @@ export const pluginInternals: StateCreator<
77
70
  source: sourceMap[payload.identifier],
78
71
  }));
79
72
  },
80
-
81
- internal_constructToolsCallingContext: (id: string) => {
82
- const message = displayMessageSelectors.getDisplayMessageById(id)(get());
83
- if (!message) return;
84
-
85
- return {
86
- topicId: message.topicId,
87
- };
88
- },
89
73
  });