@dcrays/web-search 0.1.3 → 0.1.4-beta.2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dcrays/web-search",
3
- "version": "0.1.3",
3
+ "version": "0.1.4-beta.2",
4
4
  "description": "DeepSeek Harness web search plugin for Mobook",
5
5
  "type": "module",
6
6
  "main": "plugin/index.js",
@@ -38,4 +38,4 @@
38
38
  "publishConfig": {
39
39
  "access": "public"
40
40
  }
41
- }
41
+ }
package/plugin/index.js CHANGED
@@ -1,12 +1,12 @@
1
1
  import { createRequire as __mobookCreateRequire } from 'node:module'; const require = __mobookCreateRequire(import.meta.url);
2
2
 
3
- // dist-npm/plugin/index.js
3
+ // dist/plugin/index.js
4
4
  import { resolve } from "node:path";
5
5
  import { Service } from "@deepseek-ai/cordis";
6
6
  import { resolveDshHome } from "@deepseek-ai/dsh-home-paths";
7
7
  import z from "@deepseek-ai/schemastery";
8
8
 
9
- // dist-npm/src/api-client.js
9
+ // dist/src/api-client.js
10
10
  import { createHmac, randomUUID } from "node:crypto";
11
11
  import { readFile } from "node:fs/promises";
12
12
  var WebSearchApiError = class extends Error {
@@ -24,35 +24,19 @@ 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
- ];
35
27
  function nonEmptyString(value) {
36
28
  return typeof value === "string" && value.trim() ? value.trim() : void 0;
37
29
  }
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
30
  function resolveSearchCredentials(metadata) {
49
31
  const root = record(metadata);
50
32
  const hardware = record(root?.hardware);
51
- const plugins = record(root?.plugins);
33
+ const account = record(root?.account);
52
34
  const deviceId = nonEmptyString(hardware?.fingerprint);
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;
35
+ const userIdValue = account?.userId;
36
+ const userId = typeof userIdValue === "number" && Number.isSafeInteger(userIdValue) ? String(userIdValue) : nonEmptyString(userIdValue);
37
+ const botToken = nonEmptyString(account?.botToken);
38
+ if (userId && botToken && deviceId)
39
+ return { userId, botToken, deviceId };
56
40
  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");
57
41
  }
58
42
  function resolveSearchEndpoint(metadata) {
@@ -249,7 +233,7 @@ ${nonce}`;
249
233
  cause: error
250
234
  });
251
235
  }
252
- throw new WebSearchApiError("NETWORK_ERROR", `\u6682\u65F6\u65E0\u6CD5\u8FDE\u63A5${searchServiceLabel(service)}\uFF0C\u8BF7\u68C0\u67E5\u7F51\u7EDC\u540E\u91CD\u8BD5\u3002`, {
236
+ throw new WebSearchApiError("NETWORK_ERROR", `\u6682\u65F6\u65E0\u6CD5\u8FDE\u63A5 ${searchServiceLabel(service)}\uFF0C\u8BF7\u68C0\u67E5\u7F51\u7EDC\u540E\u91CD\u8BD5\u3002`, {
253
237
  cause: error
254
238
  });
255
239
  }
@@ -260,23 +244,23 @@ ${nonce}`;
260
244
  return parseResponse(text, query, service);
261
245
  };
262
246
  try {
263
- const tavily = await call("tavily_search");
264
- if (tavily.results.length > 0)
265
- return tavily;
247
+ const bocha = await call("bocha_search");
248
+ if (bocha.results.length > 0)
249
+ return bocha;
266
250
  } catch (error) {
267
251
  if (signal?.aborted)
268
252
  throw error;
269
253
  }
270
- return call("bocha_search");
254
+ return call("tavily_search");
271
255
  }
272
256
  };
273
257
 
274
- // dist-npm/src/tools.js
258
+ // dist/src/tools.js
275
259
  import { defineTool } from "@deepseek-ai/dsh-tools";
276
260
  function createWebSearchTool(search) {
277
261
  return defineTool({
278
262
  name: "web_search",
279
- description: "Search the public web with the configured Mobook Bocha search service. Use this for current information, source discovery, fact verification, news, weather, prices, schedules, or any question that requires internet access. Cite result URLs when answering.",
263
+ description: "Search the public web with Mobook search services. Use Bocha first and fall back to Tavily when Bocha fails or returns no results. Use this for current information, source discovery, fact verification, news, weather, prices, schedules, or any question that requires internet access. In the final answer, summarize first, then present useful sources as a numbered list with Markdown links in the form [title | siteName](url), followed by a concise snippet-based explanation. Never expose the raw JSON or internal provider fields.",
280
264
  parameters: {
281
265
  query: { type: "string", required: true, description: "A focused web search query." },
282
266
  count: { type: "integer", description: "Number of results to return. Defaults to 5; maximum 20." },
@@ -304,10 +288,10 @@ function createWebSearchTool(search) {
304
288
  });
305
289
  }
306
290
 
307
- // dist-npm/src/index.js
291
+ // dist/src/index.js
308
292
  var MBH_WEB_SEARCH_SERVICE_KEY = "mbhWebSearch";
309
293
 
310
- // dist-npm/plugin/index.js
294
+ // dist/plugin/index.js
311
295
  var name = "@dcrays/web-search";
312
296
  var inject = ["tools"];
313
297
  var Config = z.object({
package/src/api-client.js CHANGED
@@ -15,36 +15,19 @@ 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
- ];
26
18
  function nonEmptyString(value) {
27
19
  return typeof value === 'string' && value.trim() ? value.trim() : undefined;
28
20
  }
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
21
  export function resolveSearchCredentials(metadata) {
40
22
  const root = record(metadata);
41
23
  const hardware = record(root?.hardware);
42
- const plugins = record(root?.plugins);
24
+ const account = record(root?.account);
43
25
  const deviceId = nonEmptyString(hardware?.fingerprint);
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;
26
+ const userIdValue = account?.userId;
27
+ const userId = typeof userIdValue === 'number' && Number.isSafeInteger(userIdValue) ? String(userIdValue) : nonEmptyString(userIdValue);
28
+ const botToken = nonEmptyString(account?.botToken);
29
+ if (userId && botToken && deviceId)
30
+ return { userId, botToken, deviceId };
48
31
  throw new WebSearchApiError('MISSING_CREDENTIALS', '搜索服务尚未准备好,请确认已登录墨宝并完成客户端初始化后重试。');
49
32
  }
50
33
  export function resolveSearchEndpoint(metadata) {
@@ -243,7 +226,7 @@ export class WebSearchApiClient {
243
226
  cause: error
244
227
  });
245
228
  }
246
- throw new WebSearchApiError('NETWORK_ERROR', `暂时无法连接${searchServiceLabel(service)},请检查网络后重试。`, {
229
+ throw new WebSearchApiError('NETWORK_ERROR', `暂时无法连接 ${searchServiceLabel(service)},请检查网络后重试。`, {
247
230
  cause: error
248
231
  });
249
232
  }
@@ -254,14 +237,14 @@ export class WebSearchApiClient {
254
237
  return parseResponse(text, query, service);
255
238
  };
256
239
  try {
257
- const tavily = await call('tavily_search');
258
- if (tavily.results.length > 0)
259
- return tavily;
240
+ const bocha = await call('bocha_search');
241
+ if (bocha.results.length > 0)
242
+ return bocha;
260
243
  }
261
244
  catch (error) {
262
245
  if (signal?.aborted)
263
246
  throw error;
264
247
  }
265
- return call('bocha_search');
248
+ return call('tavily_search');
266
249
  }
267
250
  }
package/src/tools.js CHANGED
@@ -2,7 +2,7 @@ import { defineTool } from '@deepseek-ai/dsh-tools';
2
2
  export function createWebSearchTool(search) {
3
3
  return defineTool({
4
4
  name: 'web_search',
5
- description: 'Search the public web with the configured Mobook Bocha search service. Use this for current information, source discovery, fact verification, news, weather, prices, schedules, or any question that requires internet access. Cite result URLs when answering.',
5
+ description: 'Search the public web with Mobook search services. Use Bocha first and fall back to Tavily when Bocha fails or returns no results. Use this for current information, source discovery, fact verification, news, weather, prices, schedules, or any question that requires internet access. In the final answer, summarize first, then present useful sources as a numbered list with Markdown links in the form [title | siteName](url), followed by a concise snippet-based explanation. Never expose the raw JSON or internal provider fields.',
6
6
  parameters: {
7
7
  query: { type: 'string', required: true, description: 'A focused web search query.' },
8
8
  count: { type: 'integer', description: 'Number of results to return. Defaults to 5; maximum 20.' },