@dcrays/web-search 0.1.1 → 0.1.3
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/README.md +2 -2
- package/package.json +2 -2
- package/plugin/index.d.ts +1 -4
- package/plugin/index.js +56 -50
- package/src/api-client.d.ts +2 -5
- package/src/api-client.js +54 -23
- package/src/config/env-config.d.ts +1 -10
- package/src/config/env-config.js +1 -16
package/README.md
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
# @dcrays/web-search
|
|
2
2
|
|
|
3
|
-
书灵墨宝的 DSH 联网搜索插件。加载后注册 `web_search`
|
|
3
|
+
书灵墨宝的 DSH 联网搜索插件。加载后注册 `web_search` 工具,把模型搜索请求映射到搜索网关。
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
单一发布包同时适用于生产与测试桌面:运行时从 `mobook.json` 根级 `servers.apiGatewayBaseUrl` 和 `account` 读取搜索网关与签名身份。
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dcrays/web-search",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"description": "DeepSeek Harness web search plugin for Mobook
|
|
3
|
+
"version": "0.1.3",
|
|
4
|
+
"description": "DeepSeek Harness web search plugin for Mobook",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "plugin/index.js",
|
|
7
7
|
"types": "plugin/index.d.ts",
|
package/plugin/index.d.ts
CHANGED
|
@@ -2,13 +2,10 @@ import type { Context } from '@deepseek-ai/cordis';
|
|
|
2
2
|
import { Service } from '@deepseek-ai/cordis';
|
|
3
3
|
import z from '@deepseek-ai/schemastery';
|
|
4
4
|
import { type WebSearchRequest, type WebSearchResult } from '../src/index.js';
|
|
5
|
-
export { DEFAULT_BUILD_ENV } from '../src/config/env-config.js';
|
|
6
5
|
export declare const name = "mbh-web-search";
|
|
7
6
|
export declare const inject: string[];
|
|
8
7
|
export interface Config {
|
|
9
8
|
enabled: boolean;
|
|
10
|
-
endpointUrl: string;
|
|
11
|
-
metadataPath: string;
|
|
12
9
|
timeoutMs: number;
|
|
13
10
|
maxResponseBytes: number;
|
|
14
11
|
defaultCount: number;
|
|
@@ -27,5 +24,5 @@ export declare class MbhWebSearchService extends Service {
|
|
|
27
24
|
isEnabled(): boolean;
|
|
28
25
|
search(request: WebSearchRequest, signal?: AbortSignal): Promise<WebSearchResult>;
|
|
29
26
|
}
|
|
30
|
-
export declare function resolveMetadataPath(
|
|
27
|
+
export declare function resolveMetadataPath(): string;
|
|
31
28
|
export declare function apply(ctx: Context, config: Config): void;
|
package/plugin/index.js
CHANGED
|
@@ -24,23 +24,45 @@ function searchServiceLabel(service) {
|
|
|
24
24
|
function record(value) {
|
|
25
25
|
return value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
|
|
26
26
|
}
|
|
27
|
+
var LEGACY_ACCOUNT_PLUGIN_KEYS = [
|
|
28
|
+
"mbh-chat",
|
|
29
|
+
"mbh-chat-test",
|
|
30
|
+
"mbhchat",
|
|
31
|
+
"mbhchat-test",
|
|
32
|
+
"mbh-chat-uat",
|
|
33
|
+
"mbhchat-uat"
|
|
34
|
+
];
|
|
27
35
|
function nonEmptyString(value) {
|
|
28
36
|
return typeof value === "string" && value.trim() ? value.trim() : void 0;
|
|
29
37
|
}
|
|
30
|
-
function
|
|
38
|
+
function credentialUserId(value) {
|
|
39
|
+
return typeof value === "number" && Number.isSafeInteger(value) ? String(value) : nonEmptyString(value);
|
|
40
|
+
}
|
|
41
|
+
function credentialsFrom(source, deviceId) {
|
|
42
|
+
const userId = credentialUserId(source?.userId);
|
|
43
|
+
const botToken = nonEmptyString(source?.botToken);
|
|
44
|
+
if (userId && botToken && deviceId)
|
|
45
|
+
return { userId, botToken, deviceId };
|
|
46
|
+
return void 0;
|
|
47
|
+
}
|
|
48
|
+
function resolveSearchCredentials(metadata) {
|
|
31
49
|
const root = record(metadata);
|
|
32
|
-
const plugins = record(root?.plugins);
|
|
33
50
|
const hardware = record(root?.hardware);
|
|
51
|
+
const plugins = record(root?.plugins);
|
|
34
52
|
const deviceId = nonEmptyString(hardware?.fingerprint);
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
const botToken = nonEmptyString(plugin?.botToken);
|
|
39
|
-
if (userId && botToken && deviceId)
|
|
40
|
-
return { userId, botToken, deviceId };
|
|
41
|
-
}
|
|
53
|
+
const credentials = credentialsFrom(record(root?.account), deviceId) ?? LEGACY_ACCOUNT_PLUGIN_KEYS.map((key) => credentialsFrom(record(plugins?.[key]), deviceId)).find(Boolean);
|
|
54
|
+
if (credentials)
|
|
55
|
+
return credentials;
|
|
42
56
|
throw new WebSearchApiError("MISSING_CREDENTIALS", "\u641C\u7D22\u670D\u52A1\u5C1A\u672A\u51C6\u5907\u597D\uFF0C\u8BF7\u786E\u8BA4\u5DF2\u767B\u5F55\u58A8\u5B9D\u5E76\u5B8C\u6210\u5BA2\u6237\u7AEF\u521D\u59CB\u5316\u540E\u91CD\u8BD5\u3002");
|
|
43
57
|
}
|
|
58
|
+
function resolveSearchEndpoint(metadata) {
|
|
59
|
+
const baseUrl = nonEmptyString(record(record(metadata)?.servers)?.apiGatewayBaseUrl);
|
|
60
|
+
if (!baseUrl) {
|
|
61
|
+
throw new WebSearchApiError("INVALID_CONFIG", "\u641C\u7D22\u670D\u52A1\u5730\u5740\u5C1A\u672A\u914D\u7F6E\uFF0C\u8BF7\u8054\u7CFB\u7BA1\u7406\u5458\u68C0\u67E5\u5BA2\u6237\u7AEF\u914D\u7F6E\u3002");
|
|
62
|
+
}
|
|
63
|
+
const base = toEndpoint(baseUrl);
|
|
64
|
+
return new URL("/apikey-manage/api/search", base);
|
|
65
|
+
}
|
|
44
66
|
function requestSignal(signal, timeoutMs) {
|
|
45
67
|
const timeout = AbortSignal.timeout(timeoutMs);
|
|
46
68
|
return signal ? AbortSignal.any([signal, timeout]) : timeout;
|
|
@@ -125,23 +147,26 @@ function parseResponse(text, fallbackQuery, service) {
|
|
|
125
147
|
}
|
|
126
148
|
return result;
|
|
127
149
|
}
|
|
150
|
+
function toEndpoint(endpointUrl) {
|
|
151
|
+
let endpoint;
|
|
152
|
+
try {
|
|
153
|
+
endpoint = new URL(endpointUrl);
|
|
154
|
+
} catch (error) {
|
|
155
|
+
throw new WebSearchApiError("INVALID_CONFIG", "\u641C\u7D22\u670D\u52A1\u5730\u5740\u914D\u7F6E\u4E0D\u6B63\u786E\uFF0C\u8BF7\u8054\u7CFB\u7BA1\u7406\u5458\u68C0\u67E5\u63D2\u4EF6\u914D\u7F6E\u3002", { cause: error });
|
|
156
|
+
}
|
|
157
|
+
if (!["http:", "https:"].includes(endpoint.protocol)) {
|
|
158
|
+
throw new WebSearchApiError("INVALID_CONFIG", "\u641C\u7D22\u670D\u52A1\u5730\u5740\u4EC5\u652F\u6301 HTTP \u6216 HTTPS\uFF0C\u8BF7\u8054\u7CFB\u7BA1\u7406\u5458\u68C0\u67E5\u63D2\u4EF6\u914D\u7F6E\u3002");
|
|
159
|
+
}
|
|
160
|
+
return endpoint;
|
|
161
|
+
}
|
|
128
162
|
var WebSearchApiClient = class {
|
|
129
163
|
config;
|
|
130
|
-
endpoint;
|
|
131
164
|
fetchImpl;
|
|
132
165
|
readFileImpl;
|
|
133
166
|
nowSeconds;
|
|
134
167
|
nonce;
|
|
135
168
|
constructor(config, dependencies = {}) {
|
|
136
169
|
this.config = config;
|
|
137
|
-
try {
|
|
138
|
-
this.endpoint = new URL(config.endpointUrl);
|
|
139
|
-
} catch (error) {
|
|
140
|
-
throw new WebSearchApiError("INVALID_CONFIG", "\u641C\u7D22\u670D\u52A1\u5730\u5740\u914D\u7F6E\u4E0D\u6B63\u786E\uFF0C\u8BF7\u8054\u7CFB\u7BA1\u7406\u5458\u68C0\u67E5\u63D2\u4EF6\u914D\u7F6E\u3002", { cause: error });
|
|
141
|
-
}
|
|
142
|
-
if (!["http:", "https:"].includes(this.endpoint.protocol)) {
|
|
143
|
-
throw new WebSearchApiError("INVALID_CONFIG", "\u641C\u7D22\u670D\u52A1\u5730\u5740\u4EC5\u652F\u6301 HTTP \u6216 HTTPS\uFF0C\u8BF7\u8054\u7CFB\u7BA1\u7406\u5458\u68C0\u67E5\u63D2\u4EF6\u914D\u7F6E\u3002");
|
|
144
|
-
}
|
|
145
170
|
for (const [name2, value] of [
|
|
146
171
|
["timeoutMs", config.timeoutMs],
|
|
147
172
|
["maxResponseBytes", config.maxResponseBytes],
|
|
@@ -176,9 +201,12 @@ var WebSearchApiClient = class {
|
|
|
176
201
|
try {
|
|
177
202
|
metadata = JSON.parse(await this.readFileImpl(this.config.metadataPath, "utf8"));
|
|
178
203
|
} catch (error) {
|
|
179
|
-
throw new WebSearchApiError("MISSING_CREDENTIALS", "\u6682\u65F6\u65E0\u6CD5\u8BFB\u53D6\u58A8\u5B9D\u8FD0\u884C\u914D\u7F6E\uFF0C\u8BF7\u786E\u8BA4\u5BA2\u6237\u7AEF\u5DF2\u6B63\u5E38\u521D\u59CB\u5316\u540E\u91CD\u8BD5\u3002", {
|
|
204
|
+
throw new WebSearchApiError("MISSING_CREDENTIALS", "\u6682\u65F6\u65E0\u6CD5\u8BFB\u53D6\u58A8\u5B9D\u8FD0\u884C\u914D\u7F6E\uFF0C\u8BF7\u786E\u8BA4\u5BA2\u6237\u7AEF\u5DF2\u6B63\u5E38\u521D\u59CB\u5316\u540E\u91CD\u8BD5\u3002", {
|
|
205
|
+
cause: error
|
|
206
|
+
});
|
|
180
207
|
}
|
|
181
|
-
const
|
|
208
|
+
const endpoint = resolveSearchEndpoint(metadata);
|
|
209
|
+
const credentials = resolveSearchCredentials(metadata);
|
|
182
210
|
const call = async (service) => {
|
|
183
211
|
const timestamp = String(this.nowSeconds());
|
|
184
212
|
const nonce = this.nonce();
|
|
@@ -207,7 +235,7 @@ ${nonce}`;
|
|
|
207
235
|
const effectiveSignal = requestSignal(signal, this.config.timeoutMs);
|
|
208
236
|
let response;
|
|
209
237
|
try {
|
|
210
|
-
response = await this.fetchImpl(
|
|
238
|
+
response = await this.fetchImpl(endpoint, {
|
|
211
239
|
method: "POST",
|
|
212
240
|
headers: { accept: "application/json", "content-type": "application/json" },
|
|
213
241
|
body: JSON.stringify(body),
|
|
@@ -221,7 +249,9 @@ ${nonce}`;
|
|
|
221
249
|
cause: error
|
|
222
250
|
});
|
|
223
251
|
}
|
|
224
|
-
throw new WebSearchApiError("NETWORK_ERROR", `\u6682\u65F6\u65E0\u6CD5\u8FDE\u63A5${searchServiceLabel(service)}\uFF0C\u8BF7\u68C0\u67E5\u7F51\u7EDC\u540E\u91CD\u8BD5\u3002`, {
|
|
252
|
+
throw new WebSearchApiError("NETWORK_ERROR", `\u6682\u65F6\u65E0\u6CD5\u8FDE\u63A5${searchServiceLabel(service)}\uFF0C\u8BF7\u68C0\u67E5\u7F51\u7EDC\u540E\u91CD\u8BD5\u3002`, {
|
|
253
|
+
cause: error
|
|
254
|
+
});
|
|
225
255
|
}
|
|
226
256
|
const text = await responseText(response, this.config.maxResponseBytes);
|
|
227
257
|
if (!response.ok) {
|
|
@@ -277,31 +307,11 @@ function createWebSearchTool(search) {
|
|
|
277
307
|
// dist-npm/src/index.js
|
|
278
308
|
var MBH_WEB_SEARCH_SERVICE_KEY = "mbhWebSearch";
|
|
279
309
|
|
|
280
|
-
// dist-npm/src/config/env-config.js
|
|
281
|
-
var ENV_CONFIG = {
|
|
282
|
-
production: {
|
|
283
|
-
packageName: "@dcrays/web-search",
|
|
284
|
-
channelId: "mbh-chat",
|
|
285
|
-
legacyChannelId: "mbhchat",
|
|
286
|
-
endpointUrl: "https://api-gateway.shuwenda.com/apikey-manage/api/search"
|
|
287
|
-
},
|
|
288
|
-
test: {
|
|
289
|
-
packageName: "@dcrays/web-search-test",
|
|
290
|
-
channelId: "mbh-chat-test",
|
|
291
|
-
legacyChannelId: "mbhchat-test",
|
|
292
|
-
endpointUrl: "https://api-gateway.shuwenda.icu/apikey-manage/api/search"
|
|
293
|
-
}
|
|
294
|
-
};
|
|
295
|
-
var DEFAULT_BUILD_ENV = "production";
|
|
296
|
-
var ACTIVE_ENV_CONFIG = ENV_CONFIG[DEFAULT_BUILD_ENV];
|
|
297
|
-
|
|
298
310
|
// dist-npm/plugin/index.js
|
|
299
311
|
var name = "@dcrays/web-search";
|
|
300
312
|
var inject = ["tools"];
|
|
301
313
|
var Config = z.object({
|
|
302
314
|
enabled: z.boolean().default(true),
|
|
303
|
-
endpointUrl: z.string().default(""),
|
|
304
|
-
metadataPath: z.string().default(""),
|
|
305
315
|
timeoutMs: z.natural().min(1).default(3e4),
|
|
306
316
|
maxResponseBytes: z.natural().min(1).default(1024 * 1024),
|
|
307
317
|
defaultCount: z.natural().min(1).default(5),
|
|
@@ -316,10 +326,7 @@ var MbhWebSearchService = class extends Service {
|
|
|
316
326
|
if (!config.enabled)
|
|
317
327
|
return;
|
|
318
328
|
this.operations = new WebSearchApiClient({
|
|
319
|
-
|
|
320
|
-
metadataPath: resolveMetadataPath(config.metadataPath),
|
|
321
|
-
channelId: ACTIVE_ENV_CONFIG.channelId,
|
|
322
|
-
legacyChannelId: ACTIVE_ENV_CONFIG.legacyChannelId,
|
|
329
|
+
metadataPath: resolveMetadataPath(),
|
|
323
330
|
timeoutMs: config.timeoutMs,
|
|
324
331
|
maxResponseBytes: config.maxResponseBytes,
|
|
325
332
|
defaultCount: config.defaultCount,
|
|
@@ -336,8 +343,8 @@ var MbhWebSearchService = class extends Service {
|
|
|
336
343
|
return this.operations.search(request, signal);
|
|
337
344
|
}
|
|
338
345
|
};
|
|
339
|
-
function resolveMetadataPath(
|
|
340
|
-
return
|
|
346
|
+
function resolveMetadataPath() {
|
|
347
|
+
return resolve(resolveDshHome(), "mobook.json");
|
|
341
348
|
}
|
|
342
349
|
function apply(ctx, config) {
|
|
343
350
|
const service = new MbhWebSearchService(ctx, config);
|
|
@@ -345,13 +352,12 @@ function apply(ctx, config) {
|
|
|
345
352
|
if (!service.isEnabled())
|
|
346
353
|
return () => void 0;
|
|
347
354
|
const unregister = ctx.tools.register(createWebSearchTool(service));
|
|
348
|
-
ctx.logger(name).info("%s plugin loaded with web_search tool
|
|
355
|
+
ctx.logger(name).info("%s plugin loaded with web_search tool", name);
|
|
349
356
|
return unregister;
|
|
350
357
|
}, `${name} lifecycle`);
|
|
351
358
|
}
|
|
352
359
|
export {
|
|
353
360
|
Config,
|
|
354
|
-
DEFAULT_BUILD_ENV,
|
|
355
361
|
MbhWebSearchService,
|
|
356
362
|
apply,
|
|
357
363
|
inject,
|
package/src/api-client.d.ts
CHANGED
|
@@ -24,10 +24,7 @@ export interface WebSearchOperations {
|
|
|
24
24
|
search(request: WebSearchRequest, signal?: AbortSignal): Promise<WebSearchResult>;
|
|
25
25
|
}
|
|
26
26
|
export interface WebSearchApiClientConfig {
|
|
27
|
-
endpointUrl: string;
|
|
28
27
|
metadataPath: string;
|
|
29
|
-
channelId: string;
|
|
30
|
-
legacyChannelId: string;
|
|
31
28
|
timeoutMs: number;
|
|
32
29
|
maxResponseBytes: number;
|
|
33
30
|
defaultCount: number;
|
|
@@ -50,10 +47,10 @@ interface SearchCredentials {
|
|
|
50
47
|
botToken: string;
|
|
51
48
|
deviceId: string;
|
|
52
49
|
}
|
|
53
|
-
export declare function resolveSearchCredentials(metadata: unknown
|
|
50
|
+
export declare function resolveSearchCredentials(metadata: unknown): SearchCredentials;
|
|
51
|
+
export declare function resolveSearchEndpoint(metadata: unknown): URL;
|
|
54
52
|
export declare class WebSearchApiClient implements WebSearchOperations {
|
|
55
53
|
private readonly config;
|
|
56
|
-
private readonly endpoint;
|
|
57
54
|
private readonly fetchImpl;
|
|
58
55
|
private readonly readFileImpl;
|
|
59
56
|
private readonly nowSeconds;
|
package/src/api-client.js
CHANGED
|
@@ -15,23 +15,46 @@ function searchServiceLabel(service) {
|
|
|
15
15
|
function record(value) {
|
|
16
16
|
return value && typeof value === 'object' && !Array.isArray(value) ? value : undefined;
|
|
17
17
|
}
|
|
18
|
+
const LEGACY_ACCOUNT_PLUGIN_KEYS = [
|
|
19
|
+
'mbh-chat',
|
|
20
|
+
'mbh-chat-test',
|
|
21
|
+
'mbhchat',
|
|
22
|
+
'mbhchat-test',
|
|
23
|
+
'mbh-chat-uat',
|
|
24
|
+
'mbhchat-uat'
|
|
25
|
+
];
|
|
18
26
|
function nonEmptyString(value) {
|
|
19
27
|
return typeof value === 'string' && value.trim() ? value.trim() : undefined;
|
|
20
28
|
}
|
|
21
|
-
|
|
29
|
+
function credentialUserId(value) {
|
|
30
|
+
return typeof value === 'number' && Number.isSafeInteger(value) ? String(value) : nonEmptyString(value);
|
|
31
|
+
}
|
|
32
|
+
function credentialsFrom(source, deviceId) {
|
|
33
|
+
const userId = credentialUserId(source?.userId);
|
|
34
|
+
const botToken = nonEmptyString(source?.botToken);
|
|
35
|
+
if (userId && botToken && deviceId)
|
|
36
|
+
return { userId, botToken, deviceId };
|
|
37
|
+
return undefined;
|
|
38
|
+
}
|
|
39
|
+
export function resolveSearchCredentials(metadata) {
|
|
22
40
|
const root = record(metadata);
|
|
23
|
-
const plugins = record(root?.plugins);
|
|
24
41
|
const hardware = record(root?.hardware);
|
|
42
|
+
const plugins = record(root?.plugins);
|
|
25
43
|
const deviceId = nonEmptyString(hardware?.fingerprint);
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
if (userId && botToken && deviceId)
|
|
31
|
-
return { userId, botToken, deviceId };
|
|
32
|
-
}
|
|
44
|
+
const credentials = credentialsFrom(record(root?.account), deviceId) ??
|
|
45
|
+
LEGACY_ACCOUNT_PLUGIN_KEYS.map((key) => credentialsFrom(record(plugins?.[key]), deviceId)).find(Boolean);
|
|
46
|
+
if (credentials)
|
|
47
|
+
return credentials;
|
|
33
48
|
throw new WebSearchApiError('MISSING_CREDENTIALS', '搜索服务尚未准备好,请确认已登录墨宝并完成客户端初始化后重试。');
|
|
34
49
|
}
|
|
50
|
+
export function resolveSearchEndpoint(metadata) {
|
|
51
|
+
const baseUrl = nonEmptyString(record(record(metadata)?.servers)?.apiGatewayBaseUrl);
|
|
52
|
+
if (!baseUrl) {
|
|
53
|
+
throw new WebSearchApiError('INVALID_CONFIG', '搜索服务地址尚未配置,请联系管理员检查客户端配置。');
|
|
54
|
+
}
|
|
55
|
+
const base = toEndpoint(baseUrl);
|
|
56
|
+
return new URL('/apikey-manage/api/search', base);
|
|
57
|
+
}
|
|
35
58
|
function requestSignal(signal, timeoutMs) {
|
|
36
59
|
const timeout = AbortSignal.timeout(timeoutMs);
|
|
37
60
|
return signal ? AbortSignal.any([signal, timeout]) : timeout;
|
|
@@ -118,24 +141,27 @@ function parseResponse(text, fallbackQuery, service) {
|
|
|
118
141
|
}
|
|
119
142
|
return result;
|
|
120
143
|
}
|
|
144
|
+
function toEndpoint(endpointUrl) {
|
|
145
|
+
let endpoint;
|
|
146
|
+
try {
|
|
147
|
+
endpoint = new URL(endpointUrl);
|
|
148
|
+
}
|
|
149
|
+
catch (error) {
|
|
150
|
+
throw new WebSearchApiError('INVALID_CONFIG', '搜索服务地址配置不正确,请联系管理员检查插件配置。', { cause: error });
|
|
151
|
+
}
|
|
152
|
+
if (!['http:', 'https:'].includes(endpoint.protocol)) {
|
|
153
|
+
throw new WebSearchApiError('INVALID_CONFIG', '搜索服务地址仅支持 HTTP 或 HTTPS,请联系管理员检查插件配置。');
|
|
154
|
+
}
|
|
155
|
+
return endpoint;
|
|
156
|
+
}
|
|
121
157
|
export class WebSearchApiClient {
|
|
122
158
|
config;
|
|
123
|
-
endpoint;
|
|
124
159
|
fetchImpl;
|
|
125
160
|
readFileImpl;
|
|
126
161
|
nowSeconds;
|
|
127
162
|
nonce;
|
|
128
163
|
constructor(config, dependencies = {}) {
|
|
129
164
|
this.config = config;
|
|
130
|
-
try {
|
|
131
|
-
this.endpoint = new URL(config.endpointUrl);
|
|
132
|
-
}
|
|
133
|
-
catch (error) {
|
|
134
|
-
throw new WebSearchApiError('INVALID_CONFIG', '搜索服务地址配置不正确,请联系管理员检查插件配置。', { cause: error });
|
|
135
|
-
}
|
|
136
|
-
if (!['http:', 'https:'].includes(this.endpoint.protocol)) {
|
|
137
|
-
throw new WebSearchApiError('INVALID_CONFIG', '搜索服务地址仅支持 HTTP 或 HTTPS,请联系管理员检查插件配置。');
|
|
138
|
-
}
|
|
139
165
|
for (const [name, value] of [
|
|
140
166
|
['timeoutMs', config.timeoutMs],
|
|
141
167
|
['maxResponseBytes', config.maxResponseBytes],
|
|
@@ -171,9 +197,12 @@ export class WebSearchApiClient {
|
|
|
171
197
|
metadata = JSON.parse(await this.readFileImpl(this.config.metadataPath, 'utf8'));
|
|
172
198
|
}
|
|
173
199
|
catch (error) {
|
|
174
|
-
throw new WebSearchApiError('MISSING_CREDENTIALS', '暂时无法读取墨宝运行配置,请确认客户端已正常初始化后重试。', {
|
|
200
|
+
throw new WebSearchApiError('MISSING_CREDENTIALS', '暂时无法读取墨宝运行配置,请确认客户端已正常初始化后重试。', {
|
|
201
|
+
cause: error
|
|
202
|
+
});
|
|
175
203
|
}
|
|
176
|
-
const
|
|
204
|
+
const endpoint = resolveSearchEndpoint(metadata);
|
|
205
|
+
const credentials = resolveSearchCredentials(metadata);
|
|
177
206
|
const call = async (service) => {
|
|
178
207
|
const timestamp = String(this.nowSeconds());
|
|
179
208
|
const nonce = this.nonce();
|
|
@@ -199,7 +228,7 @@ export class WebSearchApiClient {
|
|
|
199
228
|
const effectiveSignal = requestSignal(signal, this.config.timeoutMs);
|
|
200
229
|
let response;
|
|
201
230
|
try {
|
|
202
|
-
response = await this.fetchImpl(
|
|
231
|
+
response = await this.fetchImpl(endpoint, {
|
|
203
232
|
method: 'POST',
|
|
204
233
|
headers: { accept: 'application/json', 'content-type': 'application/json' },
|
|
205
234
|
body: JSON.stringify(body),
|
|
@@ -214,7 +243,9 @@ export class WebSearchApiClient {
|
|
|
214
243
|
cause: error
|
|
215
244
|
});
|
|
216
245
|
}
|
|
217
|
-
throw new WebSearchApiError('NETWORK_ERROR', `暂时无法连接${searchServiceLabel(service)},请检查网络后重试。`, {
|
|
246
|
+
throw new WebSearchApiError('NETWORK_ERROR', `暂时无法连接${searchServiceLabel(service)},请检查网络后重试。`, {
|
|
247
|
+
cause: error
|
|
248
|
+
});
|
|
218
249
|
}
|
|
219
250
|
const text = await responseText(response, this.config.maxResponseBytes);
|
|
220
251
|
if (!response.ok) {
|
|
@@ -1,10 +1 @@
|
|
|
1
|
-
export
|
|
2
|
-
export interface EnvConfig {
|
|
3
|
-
packageName: string;
|
|
4
|
-
channelId: string;
|
|
5
|
-
legacyChannelId: string;
|
|
6
|
-
endpointUrl: string;
|
|
7
|
-
}
|
|
8
|
-
export declare const ENV_CONFIG: Record<BuildEnv, EnvConfig>;
|
|
9
|
-
export declare const DEFAULT_BUILD_ENV: BuildEnv;
|
|
10
|
-
export declare const ACTIVE_ENV_CONFIG: EnvConfig;
|
|
1
|
+
export declare const PACKAGE_NAME = "@dcrays/web-search";
|
package/src/config/env-config.js
CHANGED
|
@@ -1,16 +1 @@
|
|
|
1
|
-
export const
|
|
2
|
-
production: {
|
|
3
|
-
packageName: '@dcrays/web-search',
|
|
4
|
-
channelId: 'mbh-chat',
|
|
5
|
-
legacyChannelId: 'mbhchat',
|
|
6
|
-
endpointUrl: 'https://api-gateway.shuwenda.com/apikey-manage/api/search'
|
|
7
|
-
},
|
|
8
|
-
test: {
|
|
9
|
-
packageName: '@dcrays/web-search-test',
|
|
10
|
-
channelId: 'mbh-chat-test',
|
|
11
|
-
legacyChannelId: 'mbhchat-test',
|
|
12
|
-
endpointUrl: 'https://api-gateway.shuwenda.icu/apikey-manage/api/search'
|
|
13
|
-
}
|
|
14
|
-
};
|
|
15
|
-
export const DEFAULT_BUILD_ENV = 'production';
|
|
16
|
-
export const ACTIVE_ENV_CONFIG = ENV_CONFIG[DEFAULT_BUILD_ENV];
|
|
1
|
+
export const PACKAGE_NAME = '@dcrays/web-search';
|