@lobehub/lobehub 2.0.0-next.310 → 2.0.0-next.311
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/.github/PULL_REQUEST_TEMPLATE.md +1 -1
- package/CHANGELOG.md +25 -0
- package/changelog/v1.json +9 -0
- package/docs/development/basic/chat-api.mdx +0 -1
- package/docs/development/basic/chat-api.zh-CN.mdx +0 -1
- package/package.json +1 -1
- package/packages/model-runtime/src/core/BaseAI.ts +0 -2
- package/packages/model-runtime/src/core/ModelRuntime.test.ts +0 -37
- package/packages/model-runtime/src/core/ModelRuntime.ts +0 -5
- package/packages/model-runtime/src/core/RouterRuntime/baseRuntimeMap.ts +4 -0
- package/packages/model-runtime/src/core/RouterRuntime/createRuntime.test.ts +325 -200
- package/packages/model-runtime/src/core/RouterRuntime/createRuntime.ts +205 -64
- package/packages/model-runtime/src/core/openaiCompatibleFactory/index.ts +0 -14
- package/packages/model-runtime/src/providers/aihubmix/index.test.ts +14 -20
- package/packages/model-runtime/src/types/index.ts +0 -1
- package/packages/model-runtime/src/utils/createError.test.ts +0 -20
- package/packages/model-runtime/src/utils/createError.ts +0 -1
- package/src/app/(backend)/market/agent/[[...segments]]/route.ts +3 -33
- package/src/app/(backend)/market/oidc/[[...segments]]/route.ts +5 -6
- package/src/app/(backend)/market/social/[[...segments]]/route.ts +5 -52
- package/src/app/(backend)/market/user/[username]/route.ts +3 -9
- package/src/app/(backend)/market/user/me/route.ts +3 -34
- package/src/features/ChatMiniMap/useMinimapData.ts +1 -1
- package/src/features/Conversation/ChatList/components/VirtualizedList.tsx +20 -2
- package/src/features/Conversation/store/slices/virtuaList/action.ts +9 -0
- package/src/libs/trpc/lambda/middleware/marketSDK.ts +14 -23
- package/src/libs/trusted-client/index.ts +1 -1
- package/src/server/routers/lambda/market/index.ts +5 -0
- package/src/server/routers/lambda/market/oidc.ts +41 -61
- package/src/server/routers/tools/market.ts +12 -44
- package/src/server/services/agentRuntime/AgentRuntimeService.test.ts +7 -0
- package/src/server/services/agentRuntime/AgentRuntimeService.ts +1 -1
- package/src/server/services/aiAgent/__tests__/execAgent.threadId.test.ts +7 -0
- package/src/server/services/aiAgent/__tests__/execGroupSubAgentTask.test.ts +7 -0
- package/src/server/services/aiAgent/index.ts +9 -96
- package/src/server/services/discover/index.ts +11 -16
- package/src/server/services/market/index.ts +485 -0
- package/src/server/services/toolExecution/builtin.ts +11 -17
- package/src/server/services/toolExecution/index.ts +6 -2
- package/src/services/codeInterpreter.ts +0 -13
- package/packages/model-runtime/src/types/textToImage.ts +0 -36
- package/src/server/services/lobehubSkill/index.ts +0 -109
|
@@ -0,0 +1,485 @@
|
|
|
1
|
+
import type { LobeToolManifest } from '@lobechat/context-engine';
|
|
2
|
+
import { MarketSDK } from '@lobehub/market-sdk';
|
|
3
|
+
import debug from 'debug';
|
|
4
|
+
import { type NextRequest } from 'next/server';
|
|
5
|
+
|
|
6
|
+
import {
|
|
7
|
+
type TrustedClientUserInfo,
|
|
8
|
+
generateTrustedClientToken,
|
|
9
|
+
getTrustedClientTokenForSession,
|
|
10
|
+
} from '@/libs/trusted-client';
|
|
11
|
+
|
|
12
|
+
const log = debug('lobe-server:market-service');
|
|
13
|
+
|
|
14
|
+
const MARKET_BASE_URL = process.env.NEXT_PUBLIC_MARKET_BASE_URL || 'https://market.lobehub.com';
|
|
15
|
+
|
|
16
|
+
// ============================== Helper Functions ==============================
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Extract access token from Authorization header
|
|
20
|
+
*/
|
|
21
|
+
export function extractAccessToken(req: NextRequest): string | undefined {
|
|
22
|
+
const authHeader = req.headers.get('authorization');
|
|
23
|
+
if (authHeader?.startsWith('Bearer ')) {
|
|
24
|
+
return authHeader.slice(7);
|
|
25
|
+
}
|
|
26
|
+
return undefined;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export interface LobehubSkillExecuteParams {
|
|
30
|
+
args: Record<string, any>;
|
|
31
|
+
provider: string;
|
|
32
|
+
toolName: string;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export interface LobehubSkillExecuteResult {
|
|
36
|
+
content: string;
|
|
37
|
+
error?: { code: string; message?: string };
|
|
38
|
+
success: boolean;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export interface MarketServiceOptions {
|
|
42
|
+
/** Access token from OIDC flow (user token) */
|
|
43
|
+
accessToken?: string;
|
|
44
|
+
/** Client credentials for M2M authentication */
|
|
45
|
+
clientCredentials?: {
|
|
46
|
+
clientId: string;
|
|
47
|
+
clientSecret: string;
|
|
48
|
+
};
|
|
49
|
+
/** Pre-generated trusted client token (alternative to userInfo) */
|
|
50
|
+
trustedClientToken?: string;
|
|
51
|
+
/** User info for generating trusted client token */
|
|
52
|
+
userInfo?: TrustedClientUserInfo;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Market Service
|
|
57
|
+
*
|
|
58
|
+
* Provides a unified interface to MarketSDK with business logic encapsulation.
|
|
59
|
+
* This service wraps MarketSDK methods to avoid repetition across the codebase.
|
|
60
|
+
*
|
|
61
|
+
* Usage:
|
|
62
|
+
* ```typescript
|
|
63
|
+
* // From Next.js request (API Routes) - recommended
|
|
64
|
+
* const marketService = await MarketService.createFromRequest(req);
|
|
65
|
+
* await marketService.submitFeedback({ ... });
|
|
66
|
+
*
|
|
67
|
+
* // With user authentication
|
|
68
|
+
* const service = new MarketService({ accessToken, userInfo });
|
|
69
|
+
*
|
|
70
|
+
* // With trusted client only
|
|
71
|
+
* const service = new MarketService({ userInfo });
|
|
72
|
+
*
|
|
73
|
+
* // M2M authentication
|
|
74
|
+
* const service = new MarketService({ clientCredentials: { clientId, clientSecret } });
|
|
75
|
+
*
|
|
76
|
+
* // Public endpoints (no auth)
|
|
77
|
+
* const service = new MarketService();
|
|
78
|
+
* ```
|
|
79
|
+
*/
|
|
80
|
+
export class MarketService {
|
|
81
|
+
market: MarketSDK;
|
|
82
|
+
|
|
83
|
+
constructor(options: MarketServiceOptions = {}) {
|
|
84
|
+
const { accessToken, userInfo, clientCredentials, trustedClientToken } = options;
|
|
85
|
+
|
|
86
|
+
// Use provided trustedClientToken or generate from userInfo
|
|
87
|
+
const resolvedTrustedClientToken =
|
|
88
|
+
trustedClientToken || (userInfo ? generateTrustedClientToken(userInfo) : undefined);
|
|
89
|
+
|
|
90
|
+
this.market = new MarketSDK({
|
|
91
|
+
accessToken,
|
|
92
|
+
baseURL: MARKET_BASE_URL,
|
|
93
|
+
clientId: clientCredentials?.clientId,
|
|
94
|
+
clientSecret: clientCredentials?.clientSecret,
|
|
95
|
+
trustedClientToken: resolvedTrustedClientToken,
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
log(
|
|
99
|
+
'MarketService initialized: baseURL=%s, hasAccessToken=%s, hasTrustedToken=%s, hasClientCredentials=%s',
|
|
100
|
+
MARKET_BASE_URL,
|
|
101
|
+
!!accessToken,
|
|
102
|
+
!!resolvedTrustedClientToken,
|
|
103
|
+
!!clientCredentials,
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// ============================== Factory Methods ==============================
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Create MarketService from Next.js request (server-side only)
|
|
111
|
+
* Extracts accessToken from Authorization header and trustedClientToken from session
|
|
112
|
+
*/
|
|
113
|
+
static async createFromRequest(req: NextRequest): Promise<MarketService> {
|
|
114
|
+
const accessToken = extractAccessToken(req);
|
|
115
|
+
const trustedClientToken = await getTrustedClientTokenForSession();
|
|
116
|
+
|
|
117
|
+
return new MarketService({
|
|
118
|
+
accessToken,
|
|
119
|
+
trustedClientToken,
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// ============================== Feedback Methods ==============================
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Submit feedback to LobeHub
|
|
127
|
+
*/
|
|
128
|
+
async submitFeedback(params: {
|
|
129
|
+
clientInfo?: {
|
|
130
|
+
language?: string;
|
|
131
|
+
timezone?: string;
|
|
132
|
+
url?: string;
|
|
133
|
+
userAgent?: string;
|
|
134
|
+
};
|
|
135
|
+
email?: string;
|
|
136
|
+
message: string;
|
|
137
|
+
screenshotUrl?: string;
|
|
138
|
+
title: string;
|
|
139
|
+
}) {
|
|
140
|
+
const { title, message, email, screenshotUrl, clientInfo } = params;
|
|
141
|
+
|
|
142
|
+
// Build message with screenshot if available
|
|
143
|
+
let feedbackMessage = message;
|
|
144
|
+
if (screenshotUrl) {
|
|
145
|
+
feedbackMessage += `\n\n**Screenshot**: ${screenshotUrl}`;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
return this.market.feedback.submitFeedback({
|
|
149
|
+
clientInfo,
|
|
150
|
+
email: email || '',
|
|
151
|
+
message: feedbackMessage,
|
|
152
|
+
title,
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// ============================== Auth Methods ==============================
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Exchange OAuth authorization code for tokens
|
|
160
|
+
*/
|
|
161
|
+
async exchangeAuthorizationCode(params: {
|
|
162
|
+
clientId: string;
|
|
163
|
+
code: string;
|
|
164
|
+
codeVerifier: string;
|
|
165
|
+
redirectUri: string;
|
|
166
|
+
}) {
|
|
167
|
+
return this.market.auth.exchangeOAuthToken({
|
|
168
|
+
clientId: params.clientId,
|
|
169
|
+
code: params.code,
|
|
170
|
+
codeVerifier: params.codeVerifier,
|
|
171
|
+
grantType: 'authorization_code',
|
|
172
|
+
redirectUri: params.redirectUri,
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Get OAuth handoff information
|
|
178
|
+
*/
|
|
179
|
+
async getOAuthHandoff(id: string) {
|
|
180
|
+
return this.market.auth.getOAuthHandoff(id);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Get user info from token
|
|
185
|
+
*/
|
|
186
|
+
async getUserInfo(token: string) {
|
|
187
|
+
return this.market.auth.getUserInfo(token);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Get user info with trusted client token (server-side)
|
|
192
|
+
*/
|
|
193
|
+
async getUserInfoWithTrustedClient() {
|
|
194
|
+
const userInfoUrl = `${MARKET_BASE_URL}/lobehub-oidc/userinfo`;
|
|
195
|
+
const response = await fetch(userInfoUrl, {
|
|
196
|
+
// @ts-ignore
|
|
197
|
+
headers: this.market.headers,
|
|
198
|
+
method: 'GET',
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
if (!response.ok) {
|
|
202
|
+
throw new Error('Failed to get user info');
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
return response.json();
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Refresh OAuth token
|
|
210
|
+
*/
|
|
211
|
+
async refreshToken(params: { clientId: string; refreshToken: string }) {
|
|
212
|
+
return this.market.auth.exchangeOAuthToken({
|
|
213
|
+
clientId: params.clientId,
|
|
214
|
+
grantType: 'refresh_token',
|
|
215
|
+
refreshToken: params.refreshToken,
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
// ============================== Client Methods ==============================
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* Register client for M2M authentication
|
|
223
|
+
*/
|
|
224
|
+
async registerClient(params: {
|
|
225
|
+
clientName: string;
|
|
226
|
+
clientType: string;
|
|
227
|
+
deviceId: string;
|
|
228
|
+
platform?: string;
|
|
229
|
+
version?: string;
|
|
230
|
+
}) {
|
|
231
|
+
// @ts-ignore
|
|
232
|
+
return this.market.registerClient(params);
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* Fetch M2M token with client credentials
|
|
237
|
+
*/
|
|
238
|
+
async fetchM2MToken() {
|
|
239
|
+
return this.market.fetchM2MToken();
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
// ============================== Skills Methods ==============================
|
|
243
|
+
|
|
244
|
+
/**
|
|
245
|
+
* List available tools for a provider
|
|
246
|
+
*/
|
|
247
|
+
async listSkillTools(providerId: string) {
|
|
248
|
+
return this.market.skills.listTools(providerId);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
/**
|
|
252
|
+
* Call a skill tool
|
|
253
|
+
*/
|
|
254
|
+
async callSkillTool(provider: string, params: { args: Record<string, any>; tool: string }) {
|
|
255
|
+
return this.market.skills.callTool(provider, params);
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/**
|
|
259
|
+
* List user's connected skills
|
|
260
|
+
*/
|
|
261
|
+
async listSkillConnections() {
|
|
262
|
+
return this.market.connect.listConnections();
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
// ============================== Plugin Methods ==============================
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* Call cloud MCP endpoint
|
|
269
|
+
*/
|
|
270
|
+
async callCloudMcpEndpoint(
|
|
271
|
+
params: {
|
|
272
|
+
apiParams: Record<string, any>;
|
|
273
|
+
identifier: string;
|
|
274
|
+
toolName: string;
|
|
275
|
+
},
|
|
276
|
+
options?: {
|
|
277
|
+
headers?: Record<string, string>;
|
|
278
|
+
},
|
|
279
|
+
) {
|
|
280
|
+
return this.market.plugins.callCloudGateway(params, options);
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
/**
|
|
284
|
+
* Get plugin manifest
|
|
285
|
+
*/
|
|
286
|
+
async getPluginManifest(params: {
|
|
287
|
+
identifier: string;
|
|
288
|
+
install?: boolean;
|
|
289
|
+
locale?: string;
|
|
290
|
+
version?: string;
|
|
291
|
+
}) {
|
|
292
|
+
return this.market.plugins.getPluginManifest(params);
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
/**
|
|
296
|
+
* Report plugin installation
|
|
297
|
+
*/
|
|
298
|
+
async reportPluginInstallation(params: any) {
|
|
299
|
+
return this.market.plugins.reportInstallation(params);
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
/**
|
|
303
|
+
* Report plugin call
|
|
304
|
+
*/
|
|
305
|
+
async reportPluginCall(params: any) {
|
|
306
|
+
return this.market.plugins.reportCall(params);
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
/**
|
|
310
|
+
* Create plugin event
|
|
311
|
+
*/
|
|
312
|
+
async createPluginEvent(params: any) {
|
|
313
|
+
return this.market.plugins.createEvent(params);
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
// ============================== Agent Methods ==============================
|
|
317
|
+
|
|
318
|
+
/**
|
|
319
|
+
* Get agent detail
|
|
320
|
+
*/
|
|
321
|
+
async getAgentDetail(identifier: string, options?: { locale?: string; version?: string }) {
|
|
322
|
+
return this.market.agents.getAgentDetail(identifier, options);
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
/**
|
|
326
|
+
* Get agent list
|
|
327
|
+
*/
|
|
328
|
+
async getAgentList(params?: any) {
|
|
329
|
+
return this.market.agents.getAgentList(params);
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
/**
|
|
333
|
+
* Increase agent install count
|
|
334
|
+
*/
|
|
335
|
+
async increaseAgentInstallCount(identifier: string) {
|
|
336
|
+
return this.market.agents.increaseInstallCount(identifier);
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
/**
|
|
340
|
+
* Create agent event
|
|
341
|
+
*/
|
|
342
|
+
async createAgentEvent(params: any) {
|
|
343
|
+
return this.market.agents.createEvent(params);
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
// ============================== Agent Group Methods ==============================
|
|
347
|
+
|
|
348
|
+
/**
|
|
349
|
+
* Get agent group detail
|
|
350
|
+
*/
|
|
351
|
+
async getAgentGroupDetail(identifier: string, options?: { locale?: string; version?: number }) {
|
|
352
|
+
return this.market.agentGroups.getAgentGroupDetail(identifier, options);
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
/**
|
|
356
|
+
* Get agent group list
|
|
357
|
+
*/
|
|
358
|
+
async getAgentGroupList(params?: any) {
|
|
359
|
+
return this.market.agentGroups.getAgentGroupList(params);
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
// ============================== User Methods ==============================
|
|
363
|
+
|
|
364
|
+
/**
|
|
365
|
+
* Get user profile by username
|
|
366
|
+
*/
|
|
367
|
+
async getUserProfile(username: string, options?: { locale?: string }) {
|
|
368
|
+
return this.market.user.getUserInfo(username, options);
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
// ============================== Skills Methods ==============================
|
|
372
|
+
|
|
373
|
+
/**
|
|
374
|
+
* Execute a LobeHub Skill tool
|
|
375
|
+
* @param params - The skill execution parameters (provider, toolName, args)
|
|
376
|
+
* @returns Execution result with content and success status
|
|
377
|
+
*/
|
|
378
|
+
async executeLobehubSkill(params: LobehubSkillExecuteParams): Promise<LobehubSkillExecuteResult> {
|
|
379
|
+
const { provider, toolName, args } = params;
|
|
380
|
+
|
|
381
|
+
log('executeLobehubSkill: %s/%s with args: %O', provider, toolName, args);
|
|
382
|
+
|
|
383
|
+
try {
|
|
384
|
+
const response = await this.market.skills.callTool(provider, {
|
|
385
|
+
args,
|
|
386
|
+
tool: toolName,
|
|
387
|
+
});
|
|
388
|
+
|
|
389
|
+
log('executeLobehubSkill: response: %O', response);
|
|
390
|
+
|
|
391
|
+
return {
|
|
392
|
+
content: typeof response.data === 'string' ? response.data : JSON.stringify(response.data),
|
|
393
|
+
success: response.success,
|
|
394
|
+
};
|
|
395
|
+
} catch (error) {
|
|
396
|
+
const err = error as Error;
|
|
397
|
+
console.error('MarketService.executeLobehubSkill error %s/%s: %O', provider, toolName, err);
|
|
398
|
+
|
|
399
|
+
return {
|
|
400
|
+
content: err.message,
|
|
401
|
+
error: { code: 'LOBEHUB_SKILL_ERROR', message: err.message },
|
|
402
|
+
success: false,
|
|
403
|
+
};
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
/**
|
|
408
|
+
* Fetch LobeHub Skills manifests from Market API
|
|
409
|
+
* Gets user's connected skills and builds tool manifests for agent execution
|
|
410
|
+
*
|
|
411
|
+
* @returns Array of tool manifests for connected skills
|
|
412
|
+
*/
|
|
413
|
+
async getLobehubSkillManifests(): Promise<LobeToolManifest[]> {
|
|
414
|
+
try {
|
|
415
|
+
// 1. Get user's connected skills
|
|
416
|
+
const { connections } = await this.market.connect.listConnections();
|
|
417
|
+
if (!connections || connections.length === 0) {
|
|
418
|
+
log('getLobehubSkillManifests: no connected skills found');
|
|
419
|
+
return [];
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
log('getLobehubSkillManifests: found %d connected skills', connections.length);
|
|
423
|
+
|
|
424
|
+
// 2. Fetch tools for each connection and build manifests
|
|
425
|
+
const manifests: LobeToolManifest[] = [];
|
|
426
|
+
|
|
427
|
+
for (const connection of connections) {
|
|
428
|
+
try {
|
|
429
|
+
// Connection returns providerId (e.g., 'twitter', 'linear'), not numeric id
|
|
430
|
+
const providerId = (connection as any).providerId;
|
|
431
|
+
if (!providerId) {
|
|
432
|
+
log('getLobehubSkillManifests: connection missing providerId: %O', connection);
|
|
433
|
+
continue;
|
|
434
|
+
}
|
|
435
|
+
const providerName =
|
|
436
|
+
(connection as any).providerName || (connection as any).name || providerId;
|
|
437
|
+
const icon = (connection as any).icon;
|
|
438
|
+
|
|
439
|
+
const { tools } = await this.market.skills.listTools(providerId);
|
|
440
|
+
if (!tools || tools.length === 0) continue;
|
|
441
|
+
|
|
442
|
+
const manifest: LobeToolManifest = {
|
|
443
|
+
api: tools.map((tool: any) => ({
|
|
444
|
+
description: tool.description || '',
|
|
445
|
+
name: tool.name,
|
|
446
|
+
parameters: tool.inputSchema || { properties: {}, type: 'object' },
|
|
447
|
+
})),
|
|
448
|
+
identifier: providerId,
|
|
449
|
+
meta: {
|
|
450
|
+
avatar: icon || '🔗',
|
|
451
|
+
description: `LobeHub Skill: ${providerName}`,
|
|
452
|
+
tags: ['lobehub-skill', providerId],
|
|
453
|
+
title: providerName,
|
|
454
|
+
},
|
|
455
|
+
type: 'builtin',
|
|
456
|
+
};
|
|
457
|
+
|
|
458
|
+
manifests.push(manifest);
|
|
459
|
+
log(
|
|
460
|
+
'getLobehubSkillManifests: built manifest for %s with %d tools',
|
|
461
|
+
providerId,
|
|
462
|
+
tools.length,
|
|
463
|
+
);
|
|
464
|
+
} catch (error) {
|
|
465
|
+
log('getLobehubSkillManifests: failed to fetch tools for connection: %O', error);
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
return manifests;
|
|
470
|
+
} catch (error) {
|
|
471
|
+
log('getLobehubSkillManifests: error fetching skills: %O', error);
|
|
472
|
+
return [];
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
// ============================== Direct SDK Access ==============================
|
|
477
|
+
|
|
478
|
+
/**
|
|
479
|
+
* Get MarketSDK instance for advanced usage
|
|
480
|
+
* Use this when you need direct access to SDK methods not wrapped by this service
|
|
481
|
+
*/
|
|
482
|
+
getSDK(): MarketSDK {
|
|
483
|
+
return this.market;
|
|
484
|
+
}
|
|
485
|
+
}
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import { WebBrowsingManifest } from '@lobechat/builtin-tool-web-browsing';
|
|
2
2
|
import { WebBrowsingExecutionRuntime } from '@lobechat/builtin-tool-web-browsing/executionRuntime';
|
|
3
|
+
import { type LobeChatDatabase } from '@lobechat/database';
|
|
3
4
|
import { type ChatToolPayload } from '@lobechat/types';
|
|
4
5
|
import { safeParseJSON } from '@lobechat/utils';
|
|
5
6
|
import debug from 'debug';
|
|
6
7
|
|
|
7
|
-
import {
|
|
8
|
+
import { MarketService } from '@/server/services/market';
|
|
8
9
|
import { SearchService } from '@/server/services/search';
|
|
9
10
|
|
|
10
|
-
import { type IToolExecutor, type
|
|
11
|
+
import { type IToolExecutor, type ToolExecutionResult } from './types';
|
|
11
12
|
|
|
12
13
|
const log = debug('lobe-server:builtin-tools-executor');
|
|
13
14
|
|
|
@@ -16,10 +17,12 @@ const BuiltinToolServerRuntimes: Record<string, any> = {
|
|
|
16
17
|
};
|
|
17
18
|
|
|
18
19
|
export class BuiltinToolsExecutor implements IToolExecutor {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
20
|
+
private marketService: MarketService;
|
|
21
|
+
|
|
22
|
+
constructor(db: LobeChatDatabase, userId: string) {
|
|
23
|
+
this.marketService = new MarketService({ userInfo: { userId } });
|
|
24
|
+
}
|
|
25
|
+
async execute(payload: ChatToolPayload): Promise<ToolExecutionResult> {
|
|
23
26
|
const { identifier, apiName, arguments: argsStr, source } = payload;
|
|
24
27
|
const args = safeParseJSON(argsStr) || {};
|
|
25
28
|
|
|
@@ -31,18 +34,9 @@ export class BuiltinToolsExecutor implements IToolExecutor {
|
|
|
31
34
|
args,
|
|
32
35
|
);
|
|
33
36
|
|
|
34
|
-
// Route LobeHub Skills to
|
|
37
|
+
// Route LobeHub Skills to MarketService
|
|
35
38
|
if (source === 'lobehubSkill') {
|
|
36
|
-
|
|
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({
|
|
39
|
+
return this.marketService.executeLobehubSkill({
|
|
46
40
|
args,
|
|
47
41
|
provider: identifier,
|
|
48
42
|
toolName: apiName,
|
|
@@ -4,7 +4,11 @@ import debug from 'debug';
|
|
|
4
4
|
import { type MCPService } from '../mcp';
|
|
5
5
|
import { type PluginGatewayService } from '../pluginGateway';
|
|
6
6
|
import { type BuiltinToolsExecutor } from './builtin';
|
|
7
|
-
import {
|
|
7
|
+
import {
|
|
8
|
+
type ToolExecutionContext,
|
|
9
|
+
type ToolExecutionResult,
|
|
10
|
+
type ToolExecutionResultResponse,
|
|
11
|
+
} from './types';
|
|
8
12
|
|
|
9
13
|
const log = debug('lobe-server:tool-execution-service');
|
|
10
14
|
|
|
@@ -43,7 +47,7 @@ export class ToolExecutionService {
|
|
|
43
47
|
let data: ToolExecutionResult;
|
|
44
48
|
switch (typeStr) {
|
|
45
49
|
case 'builtin': {
|
|
46
|
-
data = await this.builtinToolsExecutor.execute(payload
|
|
50
|
+
data = await this.builtinToolsExecutor.execute(payload);
|
|
47
51
|
break;
|
|
48
52
|
}
|
|
49
53
|
|
|
@@ -5,16 +5,6 @@ import type {
|
|
|
5
5
|
ExportAndUploadFileInput,
|
|
6
6
|
ExportAndUploadFileResult,
|
|
7
7
|
} from '@/server/routers/tools/market';
|
|
8
|
-
import { useUserStore } from '@/store/user';
|
|
9
|
-
import { settingsSelectors } from '@/store/user/slices/settings/selectors/settings';
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Get Market access token from user settings (stored by MarketAuthProvider)
|
|
13
|
-
*/
|
|
14
|
-
const getMarketAccessToken = (): string | undefined => {
|
|
15
|
-
const settings = settingsSelectors.currentSettings(useUserStore.getState());
|
|
16
|
-
return settings.market?.accessToken;
|
|
17
|
-
};
|
|
18
8
|
|
|
19
9
|
class CodeInterpreterService {
|
|
20
10
|
/**
|
|
@@ -28,10 +18,7 @@ class CodeInterpreterService {
|
|
|
28
18
|
params: Record<string, any>,
|
|
29
19
|
context: { topicId: string; userId: string },
|
|
30
20
|
): Promise<CallToolResult> {
|
|
31
|
-
const marketAccessToken = getMarketAccessToken();
|
|
32
|
-
|
|
33
21
|
const input: CallCodeInterpreterToolInput = {
|
|
34
|
-
marketAccessToken,
|
|
35
22
|
params,
|
|
36
23
|
toolName,
|
|
37
24
|
topicId: context.topicId,
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
export type DallEImageQuality = 'standard' | 'hd';
|
|
2
|
-
export type DallEImageStyle = 'vivid' | 'natural';
|
|
3
|
-
export type DallEImageSize = '1792x1024' | '1024x1024' | '1024x1792';
|
|
4
|
-
|
|
5
|
-
export interface TextToImagePayload {
|
|
6
|
-
model: string;
|
|
7
|
-
/**
|
|
8
|
-
* The number of images to generate. Must be between 1 and 10.
|
|
9
|
-
*/
|
|
10
|
-
n?: number;
|
|
11
|
-
/**
|
|
12
|
-
* A text description of the desired image(s).
|
|
13
|
-
* The maximum length is 1000 characters.
|
|
14
|
-
*/
|
|
15
|
-
prompt: string;
|
|
16
|
-
/**
|
|
17
|
-
* The quality of the image that will be generated.
|
|
18
|
-
* hd creates images with finer details and greater consistency across the image.
|
|
19
|
-
* This param is only supported for dall-e-3.
|
|
20
|
-
*/
|
|
21
|
-
quality?: DallEImageQuality;
|
|
22
|
-
/**
|
|
23
|
-
* The size of the generated images.
|
|
24
|
-
* Must be one of '1792x1024' , '1024x1024' , '1024x1792'
|
|
25
|
-
*/
|
|
26
|
-
size?: DallEImageSize;
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* The style of the generated images. Must be one of vivid or natural.
|
|
30
|
-
* Vivid causes the model to lean towards generating hyper-real and dramatic images.
|
|
31
|
-
* Natural causes the model to produce more natural, less hyper-real looking images.
|
|
32
|
-
* This param is only supported for dall-e-3.
|
|
33
|
-
* @default vivid
|
|
34
|
-
*/
|
|
35
|
-
style?: DallEImageStyle;
|
|
36
|
-
}
|