web-search-plus-plugin 1.3.0 → 1.3.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/index.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { definePluginEntry } from "openclaw/plugin-sdk/plugin-entry";
2
2
  import { Type } from "@sinclair/typebox";
3
- import { spawnSync } from "child_process";
3
+ import { spawn } from "child_process";
4
4
  import fs from "fs";
5
5
  import path from "path";
6
6
  import { fileURLToPath } from "url";
@@ -32,6 +32,46 @@ function loadEnvFile(envPath: string): Record<string, string> {
32
32
  return env;
33
33
  }
34
34
 
35
+ function runPython(
36
+ args: string[],
37
+ env: NodeJS.ProcessEnv,
38
+ timeoutMs: number,
39
+ ): Promise<{ stdout: string; stderr: string; code: number }> {
40
+ return new Promise((resolve) => {
41
+ const child = spawn("python3", args, { env, shell: false });
42
+ let stdout = "";
43
+ let stderr = "";
44
+ let settled = false;
45
+
46
+ const timer = setTimeout(() => {
47
+ if (!settled) {
48
+ settled = true;
49
+ child.kill();
50
+ resolve({ stdout: "", stderr: "Search timed out", code: 1 });
51
+ }
52
+ }, timeoutMs);
53
+
54
+ child.stdout.on("data", (d: Buffer) => { stdout += d.toString(); });
55
+ child.stderr.on("data", (d: Buffer) => { stderr += d.toString(); });
56
+
57
+ child.on("close", (code: number | null) => {
58
+ if (!settled) {
59
+ settled = true;
60
+ clearTimeout(timer);
61
+ resolve({ stdout, stderr, code: code ?? 1 });
62
+ }
63
+ });
64
+
65
+ child.on("error", (err: Error) => {
66
+ if (!settled) {
67
+ settled = true;
68
+ clearTimeout(timer);
69
+ resolve({ stdout: "", stderr: err.message, code: 1 });
70
+ }
71
+ });
72
+ });
73
+ }
74
+
35
75
  const PLUGIN_DIR = getPluginDir();
36
76
  const scriptPath = path.join(PLUGIN_DIR, "scripts", "search.py");
37
77
 
@@ -43,7 +83,7 @@ export default definePluginEntry({
43
83
  register(api) {
44
84
  // Bridge OpenClaw config fields to env vars expected by search.py
45
85
  const configEnv: Record<string, string> = {};
46
- const pluginConfig: Record<string, string> = (api as any)?.config ?? {};
86
+ const pluginConfig: Record<string, string> = (api.pluginConfig ?? {}) as Record<string, string>;
47
87
  const configKeyMap: Record<string, string> = {
48
88
  serperApiKey: "SERPER_API_KEY",
49
89
  tavilyApiKey: "TAVILY_API_KEY",
@@ -139,6 +179,12 @@ export default definePluginEntry({
139
179
  exclude_domains?: string[];
140
180
  },
141
181
  ) {
182
+ if (!fs.existsSync(scriptPath)) {
183
+ return {
184
+ content: [{ type: "text", text: `Search failed: script not found at ${scriptPath}` }],
185
+ };
186
+ }
187
+
142
188
  const args = [scriptPath, "--query", params.query, "--compact"];
143
189
 
144
190
  if (params.provider && params.provider !== "auto") {
@@ -146,10 +192,7 @@ export default definePluginEntry({
146
192
  }
147
193
 
148
194
  if (typeof params.count === "number" && Number.isFinite(params.count)) {
149
- args.push(
150
- "--max-results",
151
- String(Math.max(1, Math.floor(params.count))),
152
- );
195
+ args.push("--max-results", String(Math.max(1, Math.floor(params.count))));
153
196
  }
154
197
 
155
198
  if (params.depth && params.depth !== "normal") {
@@ -179,44 +222,18 @@ export default definePluginEntry({
179
222
  }
180
223
  const childEnv = { ...process.env, ...configEnv, ...fileEnv };
181
224
 
182
- try {
183
- const child = spawnSync("python3", args, {
184
- timeout: 75000,
185
- env: childEnv,
186
- shell: false,
187
- encoding: "utf8",
188
- });
189
-
190
- if (child.error) {
191
- return {
192
- content: [
193
- { type: "text", text: `Search failed: ${child.error.message}` },
194
- ],
195
- };
196
- }
197
-
198
- if (child.status !== 0) {
199
- const stderr = child.stderr?.trim() || "Unknown error";
200
- return {
201
- content: [
202
- {
203
- type: "text",
204
- text: `Search failed (exit ${child.status}): ${stderr}`,
205
- },
206
- ],
207
- };
208
- }
225
+ const result = await runPython(args, childEnv, 75000);
209
226
 
227
+ if (result.code !== 0) {
228
+ const stderr = result.stderr.trim() || "Unknown error";
210
229
  return {
211
- content: [{ type: "text", text: child.stdout?.trim() || "{}" }],
212
- };
213
- } catch (err: any) {
214
- return {
215
- content: [
216
- { type: "text", text: `Search failed: ${err?.message ?? err}` },
217
- ],
230
+ content: [{ type: "text", text: `Search failed (exit ${result.code}): ${stderr}` }],
218
231
  };
219
232
  }
233
+
234
+ return {
235
+ content: [{ type: "text", text: result.stdout.trim() || "{}" }],
236
+ };
220
237
  },
221
238
  },
222
239
  { optional: true },
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "id": "web-search-plus-plugin",
3
3
  "name": "Web Search Plus",
4
- "version": "1.3.0",
4
+ "version": "1.3.2",
5
5
  "description": "Multi-provider web search (Serper/Google, Tavily, Querit/Multilingual AI Search, Exa/Neural+Deep, Perplexity, You.com, SearXNG) with intelligent auto-routing",
6
6
  "configSchema": {
7
7
  "type": "object",
@@ -21,6 +21,7 @@
21
21
  "serperApiKey": { "label": "Serper API Key", "placeholder": "sk-...", "sensitive": true },
22
22
  "tavilyApiKey": { "label": "Tavily API Key", "placeholder": "tvly-...", "sensitive": true },
23
23
  "queritApiKey": { "label": "Querit API Key", "placeholder": "querit-sk-...", "sensitive": true },
24
+ "queritApiKey": { "label": "Querit API Key", "placeholder": "querit-sk-...", "sensitive": true },
24
25
  "exaApiKey": { "label": "Exa API Key", "placeholder": "exa-...", "sensitive": true },
25
26
  "perplexityApiKey": { "label": "Perplexity API Key", "placeholder": "pplx-...", "sensitive": true },
26
27
  "kilocodeApiKey": { "label": "Kilo Gateway API Key", "placeholder": "...", "sensitive": true },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "web-search-plus-plugin",
3
- "version": "1.3.0",
3
+ "version": "1.3.2",
4
4
  "description": "OpenClaw plugin: multi-provider web search (Serper/Google, Tavily, Querit/Multilingual AI Search, Exa/Neural+Deep, Perplexity, You.com, SearXNG) with intelligent auto-routing",
5
5
  "type": "module",
6
6
  "main": "index.ts",