@sisu-ai/tool-web-search-openai 8.0.1 → 8.0.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/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { Tool } from '@sisu-ai/core';
1
+ import type { Tool } from "@sisu-ai/core";
2
2
  export interface OpenAIWebSearchArgs {
3
3
  query: string;
4
4
  }
package/dist/index.js CHANGED
@@ -1,46 +1,68 @@
1
- import { z } from 'zod';
1
+ import { z } from "zod";
2
2
  // Uses OpenAI Responses API web_search tool
3
3
  export const openAIWebSearch = {
4
- name: 'webSearch',
5
- description: 'Search the web using OpenAI\'s built-in web search tool.',
4
+ name: "webSearch",
5
+ description: "Search the web using OpenAI's built-in web search tool.",
6
6
  schema: z.object({ query: z.string() }),
7
7
  handler: async ({ query }, ctx) => {
8
8
  const deps = (ctx?.deps ?? {});
9
9
  const depsOpenAI = (deps.openai ?? {});
10
10
  const cliApiKey = depsOpenAI.apiKey ?? deps.apiKey;
11
- const apiKey = cliApiKey || (process.env.OPENAI_API_KEY || process.env.API_KEY);
11
+ const apiKey = cliApiKey || process.env.OPENAI_API_KEY || process.env.API_KEY;
12
12
  if (!apiKey)
13
- throw new Error('Missing OPENAI_API_KEY or API_KEY');
14
- const cliRespBase = depsOpenAI.responsesBaseUrl ?? deps.responsesBaseUrl;
15
- const cliBase = depsOpenAI.baseUrl ?? deps.baseUrl;
16
- const envBase = process.env.OPENAI_RESPONSES_BASE_URL || process.env.OPENAI_BASE_URL || process.env.BASE_URL;
17
- const baseUrl = ((cliRespBase || cliBase || envBase) ?? 'https://api.openai.com').replace(/\/$/, '');
18
- const fromMeta = ctx?.model?.meta?.responseModel || ctx?.model?.responseModel;
19
- const fromAdapterName = typeof ctx?.model?.name === 'string' && ctx.model.name.startsWith('openai:')
20
- ? ctx.model.name.slice('openai:'.length)
13
+ throw new Error("Missing OPENAI_API_KEY or API_KEY");
14
+ const cliRespBase = (depsOpenAI.responsesBaseUrl ??
15
+ deps.responsesBaseUrl);
16
+ const cliBase = (depsOpenAI.baseUrl ?? deps.baseUrl);
17
+ const envBase = process.env.OPENAI_RESPONSES_BASE_URL ||
18
+ process.env.OPENAI_BASE_URL ||
19
+ process.env.BASE_URL;
20
+ const baseUrl = ((cliRespBase || cliBase || envBase) ??
21
+ "https://api.openai.com").replace(/\/$/, "");
22
+ const fromMeta = ctx?.model?.meta
23
+ ?.responseModel ||
24
+ (ctx?.model).responseModel;
25
+ const fromAdapterName = typeof ctx?.model?.name === "string" &&
26
+ ctx.model.name.startsWith("openai:")
27
+ ? ctx.model.name.slice("openai:".length)
21
28
  : undefined;
22
- const cliRespModel = depsOpenAI.responsesModel ?? deps.responsesModel;
23
- const cliModel = depsOpenAI.model ?? deps.model;
24
- let model = cliRespModel || cliModel || process.env.OPENAI_RESPONSES_MODEL || process.env.OPENAI_MODEL || fromMeta || fromAdapterName || 'gpt-4.1-mini';
29
+ const cliRespModel = (depsOpenAI.responsesModel ?? deps.responsesModel);
30
+ const cliModel = (depsOpenAI.model ?? deps.model);
31
+ let model = cliRespModel ||
32
+ cliModel ||
33
+ process.env.OPENAI_RESPONSES_MODEL ||
34
+ process.env.OPENAI_MODEL ||
35
+ fromMeta ||
36
+ fromAdapterName ||
37
+ "gpt-4.1-mini";
25
38
  const url = `${baseUrl}/v1/responses`;
26
39
  const body = {
27
40
  model,
28
41
  input: query,
29
- tools: [{ type: 'web_search' }],
30
- tool_choice: { type: 'web_search' }
42
+ tools: [{ type: "web_search" }],
43
+ tool_choice: { type: "web_search" },
31
44
  };
32
- const DEBUG = String(process.env.DEBUG_LLM || '').toLowerCase() === 'true' || process.env.DEBUG_LLM === '1';
45
+ const DEBUG = String(process.env.DEBUG_LLM || "").toLowerCase() === "true" ||
46
+ process.env.DEBUG_LLM === "1";
33
47
  if (DEBUG) {
34
- console.error('[DEBUG_LLM] request', { url, headers: { Authorization: 'Bearer ***', 'Content-Type': 'application/json', Accept: 'application/json' }, body });
48
+ console.error("[DEBUG_LLM] request", {
49
+ url,
50
+ headers: {
51
+ Authorization: "Bearer ***",
52
+ "Content-Type": "application/json",
53
+ Accept: "application/json",
54
+ },
55
+ body,
56
+ });
35
57
  }
36
58
  const doRequest = async (modelToUse) => fetch(url, {
37
- method: 'POST',
59
+ method: "POST",
38
60
  headers: {
39
- 'Content-Type': 'application/json',
40
- 'Authorization': `Bearer ${apiKey}`,
41
- 'Accept': 'application/json'
61
+ "Content-Type": "application/json",
62
+ Authorization: `Bearer ${apiKey}`,
63
+ Accept: "application/json",
42
64
  },
43
- body: JSON.stringify({ ...body, model: modelToUse })
65
+ body: JSON.stringify({ ...body, model: modelToUse }),
44
66
  });
45
67
  let res = await doRequest(model);
46
68
  let raw = await res.text();
@@ -50,20 +72,33 @@ export const openAIWebSearch = {
50
72
  const j = JSON.parse(raw);
51
73
  details = j.error?.message ?? raw;
52
74
  }
53
- catch { /* ignore JSON parse error */ }
75
+ catch {
76
+ /* ignore JSON parse error */
77
+ }
54
78
  if (DEBUG) {
55
- console.error('[DEBUG_LLM] response_error', { status: res.status, statusText: res.statusText, body: typeof raw === 'string' ? raw.slice(0, 500) : raw });
79
+ console.error("[DEBUG_LLM] response_error", {
80
+ status: res.status,
81
+ statusText: res.statusText,
82
+ body: typeof raw === "string" ? raw.slice(0, 500) : raw,
83
+ });
56
84
  }
57
85
  // Retry once with a safe default model if we suspect model/tool mismatch
58
86
  const msg = String(details).toLowerCase();
59
- const shouldRetry = res.status === 400 || msg.includes('tool') || msg.includes('web_search');
60
- if (shouldRetry && model !== 'gpt-4.1-mini') {
61
- const fallback = 'gpt-4.1-mini';
87
+ const shouldRetry = res.status === 400 ||
88
+ msg.includes("tool") ||
89
+ msg.includes("web_search");
90
+ if (shouldRetry && model !== "gpt-4.1-mini") {
91
+ const fallback = "gpt-4.1-mini";
62
92
  if (DEBUG) {
63
93
  try {
64
- console.error('[DEBUG_LLM] retrying with fallback model', { from: model, to: fallback });
94
+ console.error("[DEBUG_LLM] retrying with fallback model", {
95
+ from: model,
96
+ to: fallback,
97
+ });
98
+ }
99
+ catch {
100
+ /* ignore JSON parse error */
65
101
  }
66
- catch { /* ignore JSON parse error */ }
67
102
  }
68
103
  model = fallback;
69
104
  res = await doRequest(model);
@@ -74,7 +109,9 @@ export const openAIWebSearch = {
74
109
  const j2 = JSON.parse(raw);
75
110
  d2 = j2.error?.message ?? raw;
76
111
  }
77
- catch { /* ignore JSON parse error */ }
112
+ catch {
113
+ /* ignore JSON parse error */
114
+ }
78
115
  throw new Error(`OpenAI web search failed: ${res.status} ${res.statusText} — ${String(d2).slice(0, 500)}`);
79
116
  }
80
117
  }
@@ -82,20 +119,28 @@ export const openAIWebSearch = {
82
119
  throw new Error(`OpenAI web search failed: ${res.status} ${res.statusText} — ${String(details).slice(0, 500)}`);
83
120
  }
84
121
  }
85
- const ct = res.headers.get('content-type') || '';
86
- if (!ct.toLowerCase().includes('application/json')) {
122
+ const ct = res.headers.get("content-type") || "";
123
+ if (!ct.toLowerCase().includes("application/json")) {
87
124
  if (DEBUG) {
88
- console.error('[DEBUG_LLM] non_json_response', { contentType: ct, snippet: typeof raw === 'string' ? raw.slice(0, 200) : raw });
125
+ console.error("[DEBUG_LLM] non_json_response", {
126
+ contentType: ct,
127
+ snippet: typeof raw === "string" ? raw.slice(0, 200) : raw,
128
+ });
89
129
  }
90
130
  throw new Error(`OpenAI web search returned non-JSON content (content-type: ${ct}). Check OPENAI_BASE_URL/BASE_URL and API key. Snippet: ${String(raw).slice(0, 200)}`);
91
131
  }
92
132
  const json = raw ? JSON.parse(raw) : {};
93
133
  if (DEBUG) {
94
- console.log('[DEBUG_LLM] response_ok', { keys: Object.keys(json ?? {}), outputType: Array.isArray(json?.output) ? 'array' : typeof json?.output });
134
+ console.log("[DEBUG_LLM] response_ok", {
135
+ keys: Object.keys(json ?? {}),
136
+ outputType: Array.isArray(json?.output) ? "array" : typeof json?.output,
137
+ });
95
138
  }
96
- const results = json.output?.find?.((p) => p.type === 'web_search_results')?.web_search_results
97
- ?? json.output?.[0]?.content?.find?.((c) => c.type === 'web_search_results')?.web_search_results;
139
+ const results = json.output?.find?.((p) => p.type === "web_search_results")
140
+ ?.web_search_results ??
141
+ json.output?.[0]?.content?.find?.((c) => c.type === "web_search_results")
142
+ ?.web_search_results;
98
143
  return results ?? json;
99
- }
144
+ },
100
145
  };
101
146
  export default openAIWebSearch;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sisu-ai/tool-web-search-openai",
3
- "version": "8.0.1",
3
+ "version": "8.0.2",
4
4
  "license": "Apache-2.0",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",