@lobehub/lobehub 2.0.0-next.308 → 2.0.0-next.309
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/locales/en-US/plugin.json +1 -0
- package/locales/zh-CN/plugin.json +1 -0
- package/package.json +1 -1
- package/packages/agent-runtime/src/types/state.ts +2 -0
- package/packages/builtin-tool-group-agent-builder/src/client/Inspector/GetAgentInfo/index.tsx +68 -0
- package/packages/builtin-tool-group-agent-builder/src/client/Inspector/index.ts +3 -0
- package/packages/builtin-tool-memory/src/manifest.ts +581 -19
- package/packages/types/src/topic/thread.ts +2 -2
- package/packages/types/src/userMemory/layers.ts +19 -8
- package/packages/types/src/userMemory/shared.ts +7 -1
- package/src/locales/default/plugin.ts +1 -0
- package/src/server/modules/AgentRuntime/RuntimeExecutors.ts +11 -3
- package/src/server/modules/Mecha/AgentToolsEngine/index.ts +14 -6
- package/src/server/modules/Mecha/AgentToolsEngine/types.ts +4 -3
- package/src/server/routers/lambda/aiAgent.ts +10 -0
- package/src/server/services/agent/index.test.ts +155 -0
- package/src/server/services/agent/index.ts +25 -0
- package/src/server/services/agentRuntime/AgentRuntimeService.ts +2 -0
- package/src/server/services/agentRuntime/types.ts +1 -0
- package/src/server/services/aiAgent/__tests__/execAgent.threadId.test.ts +29 -9
- package/src/server/services/aiAgent/index.ts +175 -6
- package/src/server/services/lobehubSkill/index.ts +109 -0
- package/src/server/services/toolExecution/builtin.ts +28 -2
- package/src/server/services/toolExecution/types.ts +3 -0
- package/src/store/chat/agents/createAgentExecutors.ts +4 -2
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { AgentRuntimeContext, AgentState } from '@lobechat/agent-runtime';
|
|
2
|
+
import type { LobeToolManifest } from '@lobechat/context-engine';
|
|
2
3
|
import { type LobeChatDatabase } from '@lobechat/database';
|
|
3
4
|
import type {
|
|
4
5
|
ExecAgentParams,
|
|
@@ -10,6 +11,7 @@ import type {
|
|
|
10
11
|
} from '@lobechat/types';
|
|
11
12
|
import { ThreadStatus, ThreadType } from '@lobechat/types';
|
|
12
13
|
import { nanoid } from '@lobechat/utils';
|
|
14
|
+
import { MarketSDK } from '@lobehub/market-sdk';
|
|
13
15
|
import debug from 'debug';
|
|
14
16
|
|
|
15
17
|
import { LOADING_FLAT } from '@/const/message';
|
|
@@ -18,16 +20,43 @@ import { MessageModel } from '@/database/models/message';
|
|
|
18
20
|
import { PluginModel } from '@/database/models/plugin';
|
|
19
21
|
import { ThreadModel } from '@/database/models/thread';
|
|
20
22
|
import { TopicModel } from '@/database/models/topic';
|
|
23
|
+
import { UserModel } from '@/database/models/user';
|
|
24
|
+
import { generateTrustedClientToken } from '@/libs/trusted-client';
|
|
21
25
|
import {
|
|
22
26
|
type ServerAgentToolsContext,
|
|
23
27
|
createServerAgentToolsEngine,
|
|
24
28
|
serverMessagesEngine,
|
|
25
29
|
} from '@/server/modules/Mecha';
|
|
30
|
+
import { AgentService } from '@/server/services/agent';
|
|
26
31
|
import { AgentRuntimeService } from '@/server/services/agentRuntime';
|
|
27
32
|
import type { StepLifecycleCallbacks } from '@/server/services/agentRuntime/types';
|
|
28
33
|
|
|
29
34
|
const log = debug('lobe-server:ai-agent-service');
|
|
30
35
|
|
|
36
|
+
/**
|
|
37
|
+
* Format error for storage in thread metadata
|
|
38
|
+
* Handles Error objects which don't serialize properly with JSON.stringify
|
|
39
|
+
*/
|
|
40
|
+
function formatErrorForMetadata(error: unknown): Record<string, any> | undefined {
|
|
41
|
+
if (!error) return undefined;
|
|
42
|
+
|
|
43
|
+
// Handle Error objects
|
|
44
|
+
if (error instanceof Error) {
|
|
45
|
+
return {
|
|
46
|
+
message: error.message,
|
|
47
|
+
name: error.name,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Handle objects with message property (like ChatMessageError)
|
|
52
|
+
if (typeof error === 'object' && 'message' in error) {
|
|
53
|
+
return error as Record<string, any>;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Fallback: wrap in object
|
|
57
|
+
return { message: String(error) };
|
|
58
|
+
}
|
|
59
|
+
|
|
31
60
|
/**
|
|
32
61
|
* Internal params for execAgent with step lifecycle callbacks
|
|
33
62
|
* This extends the public ExecAgentParams with server-side only options
|
|
@@ -53,6 +82,7 @@ export class AiAgentService {
|
|
|
53
82
|
private readonly userId: string;
|
|
54
83
|
private readonly db: LobeChatDatabase;
|
|
55
84
|
private readonly agentModel: AgentModel;
|
|
85
|
+
private readonly agentService: AgentService;
|
|
56
86
|
private readonly messageModel: MessageModel;
|
|
57
87
|
private readonly pluginModel: PluginModel;
|
|
58
88
|
private readonly threadModel: ThreadModel;
|
|
@@ -63,6 +93,7 @@ export class AiAgentService {
|
|
|
63
93
|
this.userId = userId;
|
|
64
94
|
this.db = db;
|
|
65
95
|
this.agentModel = new AgentModel(db, userId);
|
|
96
|
+
this.agentService = new AgentService(db, userId);
|
|
66
97
|
this.messageModel = new MessageModel(db, userId);
|
|
67
98
|
this.pluginModel = new PluginModel(db, userId);
|
|
68
99
|
this.threadModel = new ThreadModel(db, userId);
|
|
@@ -106,8 +137,8 @@ export class AiAgentService {
|
|
|
106
137
|
|
|
107
138
|
log('execAgent: identifier=%s, prompt=%s', identifier, prompt.slice(0, 50));
|
|
108
139
|
|
|
109
|
-
// 1. Get agent configuration
|
|
110
|
-
const agentConfig = await this.
|
|
140
|
+
// 1. Get agent configuration with default config merged (supports both id and slug)
|
|
141
|
+
const agentConfig = await this.agentService.getAgentConfig(identifier);
|
|
111
142
|
if (!agentConfig) {
|
|
112
143
|
throw new Error(`Agent not found: ${identifier}`);
|
|
113
144
|
}
|
|
@@ -158,7 +189,11 @@ export class AiAgentService {
|
|
|
158
189
|
return info?.abilities?.functionCall ?? true;
|
|
159
190
|
};
|
|
160
191
|
|
|
161
|
-
// 5.
|
|
192
|
+
// 5. Fetch LobeHub Skills manifests (temporary solution until LOBE-3517 is implemented)
|
|
193
|
+
const lobehubSkillManifests = await this.fetchLobehubSkillManifests();
|
|
194
|
+
log('execAgent: got %d lobehub skill manifests', lobehubSkillManifests.length);
|
|
195
|
+
|
|
196
|
+
// 6. Create tools using Server AgentToolsEngine
|
|
162
197
|
const hasEnabledKnowledgeBases =
|
|
163
198
|
agentConfig.knowledgeBases?.some((kb: { enabled?: boolean | null }) => kb.enabled === true) ??
|
|
164
199
|
false;
|
|
@@ -169,6 +204,7 @@ export class AiAgentService {
|
|
|
169
204
|
};
|
|
170
205
|
|
|
171
206
|
const toolsEngine = createServerAgentToolsEngine(toolsContext, {
|
|
207
|
+
additionalManifests: lobehubSkillManifests,
|
|
172
208
|
agentConfig: {
|
|
173
209
|
chatConfig: agentConfig.chatConfig ?? undefined,
|
|
174
210
|
plugins: agentConfig.plugins ?? undefined,
|
|
@@ -180,6 +216,8 @@ export class AiAgentService {
|
|
|
180
216
|
|
|
181
217
|
// Generate tools and manifest map
|
|
182
218
|
const pluginIds = agentConfig.plugins || [];
|
|
219
|
+
log('execAgent: agent configured plugins: %O', pluginIds);
|
|
220
|
+
|
|
183
221
|
const toolsResult = toolsEngine.generateToolsDetailed({
|
|
184
222
|
model,
|
|
185
223
|
provider,
|
|
@@ -188,6 +226,12 @@ export class AiAgentService {
|
|
|
188
226
|
|
|
189
227
|
const tools = toolsResult.tools;
|
|
190
228
|
|
|
229
|
+
// Log detailed tools generation result
|
|
230
|
+
if (toolsResult.filteredTools && toolsResult.filteredTools.length > 0) {
|
|
231
|
+
log('execAgent: filtered tools: %O', toolsResult.filteredTools);
|
|
232
|
+
}
|
|
233
|
+
log('execAgent: enabled tool ids: %O', toolsResult.enabledToolIds);
|
|
234
|
+
|
|
191
235
|
// Get manifest map and convert from Map to Record
|
|
192
236
|
const manifestMap = toolsEngine.getEnabledPluginManifests(pluginIds);
|
|
193
237
|
const toolManifestMap: Record<string, any> = {};
|
|
@@ -195,7 +239,20 @@ export class AiAgentService {
|
|
|
195
239
|
toolManifestMap[id] = manifest;
|
|
196
240
|
});
|
|
197
241
|
|
|
198
|
-
|
|
242
|
+
// Build toolSourceMap for routing tool execution
|
|
243
|
+
const toolSourceMap: Record<string, 'builtin' | 'plugin' | 'mcp' | 'klavis' | 'lobehubSkill'> =
|
|
244
|
+
{};
|
|
245
|
+
// Mark lobehub skills
|
|
246
|
+
for (const manifest of lobehubSkillManifests) {
|
|
247
|
+
toolSourceMap[manifest.identifier] = 'lobehubSkill';
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
log(
|
|
251
|
+
'execAgent: generated %d tools from %d configured plugins, %d lobehub skills',
|
|
252
|
+
tools?.length ?? 0,
|
|
253
|
+
pluginIds.length,
|
|
254
|
+
lobehubSkillManifests.length,
|
|
255
|
+
);
|
|
199
256
|
|
|
200
257
|
// 6. Get existing messages if provided
|
|
201
258
|
let historyMessages: any[] = [];
|
|
@@ -301,7 +358,18 @@ export class AiAgentService {
|
|
|
301
358
|
},
|
|
302
359
|
};
|
|
303
360
|
|
|
304
|
-
// 12.
|
|
361
|
+
// 12. Log final operation parameters summary
|
|
362
|
+
log(
|
|
363
|
+
'execAgent: creating operation %s with params: model=%s, provider=%s, tools=%d, messages=%d, manifests=%d',
|
|
364
|
+
operationId,
|
|
365
|
+
model,
|
|
366
|
+
provider,
|
|
367
|
+
tools?.length ?? 0,
|
|
368
|
+
processedMessages.length,
|
|
369
|
+
Object.keys(toolManifestMap).length,
|
|
370
|
+
);
|
|
371
|
+
|
|
372
|
+
// 13. Create operation using AgentRuntimeService
|
|
305
373
|
// Wrap in try-catch to handle operation startup failures (e.g., QStash unavailable)
|
|
306
374
|
// If createOperation fails, we still have valid messages that need error info
|
|
307
375
|
try {
|
|
@@ -320,6 +388,7 @@ export class AiAgentService {
|
|
|
320
388
|
operationId,
|
|
321
389
|
stepCallbacks,
|
|
322
390
|
toolManifestMap,
|
|
391
|
+
toolSourceMap,
|
|
323
392
|
tools,
|
|
324
393
|
userId: this.userId,
|
|
325
394
|
});
|
|
@@ -616,6 +685,11 @@ export class AiAgentService {
|
|
|
616
685
|
}
|
|
617
686
|
}
|
|
618
687
|
|
|
688
|
+
// Log error when task fails
|
|
689
|
+
if (reason === 'error' && finalState.error) {
|
|
690
|
+
console.error('execSubAgentTask: task failed for thread %s:', threadId, finalState.error);
|
|
691
|
+
}
|
|
692
|
+
|
|
619
693
|
try {
|
|
620
694
|
// Extract summary from last assistant message and update task message content
|
|
621
695
|
const lastAssistantMessage = finalState.messages
|
|
@@ -630,12 +704,15 @@ export class AiAgentService {
|
|
|
630
704
|
log('execSubAgentTask: updated task message %s with summary', sourceMessageId);
|
|
631
705
|
}
|
|
632
706
|
|
|
707
|
+
// Format error for proper serialization (Error objects don't serialize with JSON.stringify)
|
|
708
|
+
const formattedError = formatErrorForMetadata(finalState.error);
|
|
709
|
+
|
|
633
710
|
// Update Thread metadata
|
|
634
711
|
await this.threadModel.update(threadId, {
|
|
635
712
|
metadata: {
|
|
636
713
|
completedAt,
|
|
637
714
|
duration,
|
|
638
|
-
error:
|
|
715
|
+
error: formattedError,
|
|
639
716
|
operationId: finalState.operationId,
|
|
640
717
|
startedAt,
|
|
641
718
|
totalCost: finalState.cost?.total,
|
|
@@ -659,6 +736,98 @@ export class AiAgentService {
|
|
|
659
736
|
};
|
|
660
737
|
}
|
|
661
738
|
|
|
739
|
+
/**
|
|
740
|
+
* Fetch LobeHub Skills manifests from Market API
|
|
741
|
+
* This is a temporary solution until LOBE-3517 is implemented (store skills in DB)
|
|
742
|
+
*/
|
|
743
|
+
private async fetchLobehubSkillManifests(): Promise<LobeToolManifest[]> {
|
|
744
|
+
try {
|
|
745
|
+
// 1. Get user info for trusted client token
|
|
746
|
+
const user = await UserModel.findById(this.db, this.userId);
|
|
747
|
+
if (!user?.email) {
|
|
748
|
+
log('fetchLobehubSkillManifests: user email not found, skipping');
|
|
749
|
+
return [];
|
|
750
|
+
}
|
|
751
|
+
|
|
752
|
+
// 2. Generate trusted client token
|
|
753
|
+
const trustedClientToken = generateTrustedClientToken({
|
|
754
|
+
email: user.email,
|
|
755
|
+
name: user.fullName || user.firstName || undefined,
|
|
756
|
+
userId: this.userId,
|
|
757
|
+
});
|
|
758
|
+
|
|
759
|
+
if (!trustedClientToken) {
|
|
760
|
+
log('fetchLobehubSkillManifests: trusted client not configured, skipping');
|
|
761
|
+
return [];
|
|
762
|
+
}
|
|
763
|
+
|
|
764
|
+
// 3. Create MarketSDK instance
|
|
765
|
+
const marketSDK = new MarketSDK({
|
|
766
|
+
baseURL: process.env.NEXT_PUBLIC_MARKET_BASE_URL,
|
|
767
|
+
trustedClientToken,
|
|
768
|
+
});
|
|
769
|
+
|
|
770
|
+
// 4. Get user's connected skills
|
|
771
|
+
const { connections } = await marketSDK.connect.listConnections();
|
|
772
|
+
if (!connections || connections.length === 0) {
|
|
773
|
+
log('fetchLobehubSkillManifests: no connected skills found');
|
|
774
|
+
return [];
|
|
775
|
+
}
|
|
776
|
+
|
|
777
|
+
log('fetchLobehubSkillManifests: found %d connected skills', connections.length);
|
|
778
|
+
|
|
779
|
+
// 5. Fetch tools for each connection and build manifests
|
|
780
|
+
const manifests: LobeToolManifest[] = [];
|
|
781
|
+
|
|
782
|
+
for (const connection of connections) {
|
|
783
|
+
try {
|
|
784
|
+
// Connection returns providerId (e.g., 'twitter', 'linear'), not numeric id
|
|
785
|
+
const providerId = (connection as any).providerId;
|
|
786
|
+
if (!providerId) {
|
|
787
|
+
log('fetchLobehubSkillManifests: connection missing providerId: %O', connection);
|
|
788
|
+
continue;
|
|
789
|
+
}
|
|
790
|
+
const providerName =
|
|
791
|
+
(connection as any).providerName || (connection as any).name || providerId;
|
|
792
|
+
const icon = (connection as any).icon;
|
|
793
|
+
|
|
794
|
+
const { tools } = await marketSDK.skills.listTools(providerId);
|
|
795
|
+
if (!tools || tools.length === 0) continue;
|
|
796
|
+
|
|
797
|
+
const manifest: LobeToolManifest = {
|
|
798
|
+
api: tools.map((tool: any) => ({
|
|
799
|
+
description: tool.description || '',
|
|
800
|
+
name: tool.name,
|
|
801
|
+
parameters: tool.inputSchema || { properties: {}, type: 'object' },
|
|
802
|
+
})),
|
|
803
|
+
identifier: providerId,
|
|
804
|
+
meta: {
|
|
805
|
+
avatar: icon || '🔗',
|
|
806
|
+
description: `LobeHub Skill: ${providerName}`,
|
|
807
|
+
tags: ['lobehub-skill', providerId],
|
|
808
|
+
title: providerName,
|
|
809
|
+
},
|
|
810
|
+
type: 'builtin',
|
|
811
|
+
};
|
|
812
|
+
|
|
813
|
+
manifests.push(manifest);
|
|
814
|
+
log(
|
|
815
|
+
'fetchLobehubSkillManifests: built manifest for %s with %d tools',
|
|
816
|
+
providerId,
|
|
817
|
+
tools.length,
|
|
818
|
+
);
|
|
819
|
+
} catch (error) {
|
|
820
|
+
log('fetchLobehubSkillManifests: failed to fetch tools for connection: %O', error);
|
|
821
|
+
}
|
|
822
|
+
}
|
|
823
|
+
|
|
824
|
+
return manifests;
|
|
825
|
+
} catch (error) {
|
|
826
|
+
log('fetchLobehubSkillManifests: error fetching skills: %O', error);
|
|
827
|
+
return [];
|
|
828
|
+
}
|
|
829
|
+
}
|
|
830
|
+
|
|
662
831
|
/**
|
|
663
832
|
* Calculate total tokens from AgentState usage object
|
|
664
833
|
* AgentState.usage is of type Usage from @lobechat/agent-runtime
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { type LobeChatDatabase } from '@lobechat/database';
|
|
2
|
+
import { MarketSDK } from '@lobehub/market-sdk';
|
|
3
|
+
import debug from 'debug';
|
|
4
|
+
|
|
5
|
+
import { UserModel } from '@/database/models/user';
|
|
6
|
+
import { generateTrustedClientToken } from '@/libs/trusted-client';
|
|
7
|
+
|
|
8
|
+
const log = debug('lobe-server:lobehub-skill-service');
|
|
9
|
+
|
|
10
|
+
export interface LobehubSkillExecuteParams {
|
|
11
|
+
args: Record<string, any>;
|
|
12
|
+
provider: string;
|
|
13
|
+
toolName: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface LobehubSkillExecuteResult {
|
|
17
|
+
content: string;
|
|
18
|
+
error?: { code: string; message?: string };
|
|
19
|
+
success: boolean;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export class LobehubSkillService {
|
|
23
|
+
private db: LobeChatDatabase;
|
|
24
|
+
private userId: string;
|
|
25
|
+
private marketSDK?: MarketSDK;
|
|
26
|
+
|
|
27
|
+
constructor(db: LobeChatDatabase, userId: string) {
|
|
28
|
+
this.db = db;
|
|
29
|
+
this.userId = userId;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Initialize MarketSDK with trusted client token
|
|
34
|
+
*/
|
|
35
|
+
private async getMarketSDK(): Promise<MarketSDK | null> {
|
|
36
|
+
if (this.marketSDK) return this.marketSDK;
|
|
37
|
+
|
|
38
|
+
try {
|
|
39
|
+
const user = await UserModel.findById(this.db, this.userId);
|
|
40
|
+
if (!user?.email) {
|
|
41
|
+
log('getMarketSDK: user email not found');
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const trustedClientToken = generateTrustedClientToken({
|
|
46
|
+
email: user.email,
|
|
47
|
+
name: user.fullName || user.firstName || undefined,
|
|
48
|
+
userId: this.userId,
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
if (!trustedClientToken) {
|
|
52
|
+
log('getMarketSDK: trusted client not configured');
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
this.marketSDK = new MarketSDK({
|
|
57
|
+
baseURL: process.env.NEXT_PUBLIC_MARKET_BASE_URL,
|
|
58
|
+
trustedClientToken,
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
return this.marketSDK;
|
|
62
|
+
} catch (error) {
|
|
63
|
+
log('getMarketSDK: error creating SDK: %O', error);
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Execute a LobeHub Skill tool
|
|
70
|
+
*/
|
|
71
|
+
async execute(params: LobehubSkillExecuteParams): Promise<LobehubSkillExecuteResult> {
|
|
72
|
+
const { provider, toolName, args } = params;
|
|
73
|
+
|
|
74
|
+
log('execute: %s/%s with args: %O', provider, toolName, args);
|
|
75
|
+
|
|
76
|
+
const sdk = await this.getMarketSDK();
|
|
77
|
+
if (!sdk) {
|
|
78
|
+
return {
|
|
79
|
+
content:
|
|
80
|
+
'MarketSDK not available. Please ensure you are authenticated with LobeHub Market.',
|
|
81
|
+
error: { code: 'MARKET_SDK_NOT_AVAILABLE' },
|
|
82
|
+
success: false,
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
try {
|
|
87
|
+
const response = await sdk.skills.callTool(provider, {
|
|
88
|
+
args,
|
|
89
|
+
tool: toolName,
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
log('execute: response: %O', response);
|
|
93
|
+
|
|
94
|
+
return {
|
|
95
|
+
content: typeof response.data === 'string' ? response.data : JSON.stringify(response.data),
|
|
96
|
+
success: response.success,
|
|
97
|
+
};
|
|
98
|
+
} catch (error) {
|
|
99
|
+
const err = error as Error;
|
|
100
|
+
console.error('LobehubSkillService.execute error %s/%s: %O', provider, toolName, err);
|
|
101
|
+
|
|
102
|
+
return {
|
|
103
|
+
content: err.message,
|
|
104
|
+
error: { code: 'LOBEHUB_SKILL_ERROR', message: err.message },
|
|
105
|
+
success: false,
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
@@ -4,6 +4,7 @@ import { type ChatToolPayload } from '@lobechat/types';
|
|
|
4
4
|
import { safeParseJSON } from '@lobechat/utils';
|
|
5
5
|
import debug from 'debug';
|
|
6
6
|
|
|
7
|
+
import { LobehubSkillService } from '@/server/services/lobehubSkill';
|
|
7
8
|
import { SearchService } from '@/server/services/search';
|
|
8
9
|
|
|
9
10
|
import { type IToolExecutor, type ToolExecutionContext, type ToolExecutionResult } from './types';
|
|
@@ -19,11 +20,36 @@ export class BuiltinToolsExecutor implements IToolExecutor {
|
|
|
19
20
|
payload: ChatToolPayload,
|
|
20
21
|
context: ToolExecutionContext,
|
|
21
22
|
): Promise<ToolExecutionResult> {
|
|
22
|
-
const { identifier, apiName, arguments: argsStr } = payload;
|
|
23
|
+
const { identifier, apiName, arguments: argsStr, source } = payload;
|
|
23
24
|
const args = safeParseJSON(argsStr) || {};
|
|
24
25
|
|
|
25
|
-
log(
|
|
26
|
+
log(
|
|
27
|
+
'Executing builtin tool: %s:%s (source: %s) with args: %O',
|
|
28
|
+
identifier,
|
|
29
|
+
apiName,
|
|
30
|
+
source,
|
|
31
|
+
args,
|
|
32
|
+
);
|
|
26
33
|
|
|
34
|
+
// Route LobeHub Skills to dedicated service
|
|
35
|
+
if (source === 'lobehubSkill') {
|
|
36
|
+
if (!context.serverDB || !context.userId) {
|
|
37
|
+
return {
|
|
38
|
+
content: 'Server context not available for LobeHub Skills execution.',
|
|
39
|
+
error: { code: 'CONTEXT_NOT_AVAILABLE' },
|
|
40
|
+
success: false,
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const skillService = new LobehubSkillService(context.serverDB, context.userId);
|
|
45
|
+
return skillService.execute({
|
|
46
|
+
args,
|
|
47
|
+
provider: identifier,
|
|
48
|
+
toolName: apiName,
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Default: original builtin runtime logic
|
|
27
53
|
const ServerRuntime = BuiltinToolServerRuntimes[identifier];
|
|
28
54
|
|
|
29
55
|
if (!ServerRuntime) {
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import { type LobeToolManifest } from '@lobechat/context-engine';
|
|
2
|
+
import { type LobeChatDatabase } from '@lobechat/database';
|
|
2
3
|
import { type ChatToolPayload } from '@lobechat/types';
|
|
3
4
|
|
|
4
5
|
export interface ToolExecutionContext {
|
|
6
|
+
/** Server database for LobeHub Skills execution */
|
|
7
|
+
serverDB?: LobeChatDatabase;
|
|
5
8
|
toolManifestMap: Record<string, LobeToolManifest>;
|
|
6
9
|
userId?: string;
|
|
7
10
|
}
|
|
@@ -1087,12 +1087,14 @@ export const createAgentExecutors = (context: {
|
|
|
1087
1087
|
}
|
|
1088
1088
|
|
|
1089
1089
|
if (status.status === 'failed') {
|
|
1090
|
-
|
|
1090
|
+
// Extract error message (error is always a string in TaskStatusResult)
|
|
1091
|
+
const errorMessage = status.error || 'Unknown error';
|
|
1092
|
+
log('[%s] Task failed: %s', taskLogId, errorMessage);
|
|
1091
1093
|
await context
|
|
1092
1094
|
.get()
|
|
1093
1095
|
.optimisticUpdateMessageContent(
|
|
1094
1096
|
taskMessageId,
|
|
1095
|
-
`Task failed: ${
|
|
1097
|
+
`Task failed: ${errorMessage}`,
|
|
1096
1098
|
undefined,
|
|
1097
1099
|
{ operationId: state.operationId },
|
|
1098
1100
|
);
|