webfox 4.2.0 → 4.2.1
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/{adapter-AB7LKV7N.js → adapter-6EZAIE65.js} +86 -48
- package/dist/{chunk-KC6K6LCQ.js → chunk-SGHBA2PZ.js} +1 -1
- package/dist/{chunk-CIZXLW6C.js → chunk-TJWQTB6W.js} +4 -5
- package/dist/cli.js +2 -2
- package/dist/config.schema.json +1 -1
- package/dist/index.js +2 -2
- package/dist/pi.js +2 -2
- package/dist/providers/gemini/adapter.d.ts +0 -2
- package/package.json +1 -2
|
@@ -3,30 +3,35 @@ import {
|
|
|
3
3
|
} from "./chunk-EF4VMDZL.js";
|
|
4
4
|
import "./chunk-I2UIACY3.js";
|
|
5
5
|
import "./chunk-WCTOYZVB.js";
|
|
6
|
-
import
|
|
6
|
+
import {
|
|
7
|
+
httpError
|
|
8
|
+
} from "./chunk-U4BLULLV.js";
|
|
7
9
|
|
|
8
10
|
// src/providers/gemini/adapter.ts
|
|
9
|
-
import { GoogleGenAI } from "@google/genai";
|
|
10
11
|
var DEFAULT_ANSWER_MODEL = "gemini-3.8-flash";
|
|
11
12
|
var DEFAULT_RESEARCH_AGENT = "deep-research-preview-04-2026";
|
|
12
13
|
var geminiImplementation = {
|
|
13
14
|
async answer(query, config, context, options) {
|
|
14
|
-
const ai = this.createClient(config);
|
|
15
15
|
const request = buildGeminiGenerateContentRequest({
|
|
16
16
|
defaultModel: DEFAULT_ANSWER_MODEL,
|
|
17
17
|
prompt: query,
|
|
18
18
|
options,
|
|
19
19
|
toolConfig: { googleSearch: {} }
|
|
20
20
|
});
|
|
21
|
-
const response = await
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
21
|
+
const response = await requestGemini(
|
|
22
|
+
`models/${encodeURIComponent(request.model.replace(/^models\//, ""))}:generateContent`,
|
|
23
|
+
config,
|
|
24
|
+
context,
|
|
25
|
+
request.body
|
|
26
|
+
);
|
|
27
|
+
const candidate = Array.isArray(response.candidates) ? asRecord(response.candidates[0]) : {};
|
|
28
|
+
const parts = asRecord(candidate.content).parts;
|
|
29
|
+
const text = Array.isArray(parts) ? parts.filter(
|
|
30
|
+
(part) => isPlainObject(part) && !part.thought && typeof part.text === "string"
|
|
31
|
+
).map((part) => part.text).join("").trim() : "";
|
|
32
|
+
const lines = [text || "No answer returned."];
|
|
28
33
|
const sources = extractGroundingSources(
|
|
29
|
-
|
|
34
|
+
asRecord(candidate.groundingMetadata).groundingChunks
|
|
30
35
|
);
|
|
31
36
|
if (sources.length > 0) {
|
|
32
37
|
lines.push("");
|
|
@@ -54,25 +59,30 @@ var geminiImplementation = {
|
|
|
54
59
|
});
|
|
55
60
|
},
|
|
56
61
|
async startResearch(input, config, context, options) {
|
|
57
|
-
const ai = this.createClient(config);
|
|
58
62
|
const requestOptions = getGeminiResearchRequestOptions(options);
|
|
59
|
-
const interaction = await
|
|
63
|
+
const interaction = await requestGemini(
|
|
64
|
+
"interactions",
|
|
65
|
+
config,
|
|
66
|
+
context,
|
|
60
67
|
{
|
|
61
68
|
...requestOptions,
|
|
62
69
|
input,
|
|
63
70
|
agent: DEFAULT_RESEARCH_AGENT,
|
|
64
71
|
background: true
|
|
65
72
|
},
|
|
66
|
-
|
|
73
|
+
context.idempotencyKey
|
|
67
74
|
);
|
|
68
|
-
|
|
75
|
+
const id = readNonEmptyString(interaction.id);
|
|
76
|
+
if (!id) {
|
|
77
|
+
throw new Error("Gemini research response is missing an interaction ID.");
|
|
78
|
+
}
|
|
79
|
+
return { id };
|
|
69
80
|
},
|
|
70
81
|
async pollResearch(id, config, context, _options) {
|
|
71
|
-
const
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
buildGeminiRequestOptions(context.signal)
|
|
82
|
+
const interaction = await requestGemini(
|
|
83
|
+
`interactions/${encodeURIComponent(id)}`,
|
|
84
|
+
config,
|
|
85
|
+
context
|
|
76
86
|
);
|
|
77
87
|
const status = readNonEmptyString(interaction.status) ?? "unknown";
|
|
78
88
|
if (status === "completed") {
|
|
@@ -110,33 +120,46 @@ var geminiImplementation = {
|
|
|
110
120
|
};
|
|
111
121
|
}
|
|
112
122
|
return status === "in_progress" ? { status: "in_progress" } : { status: "in_progress", statusText: status };
|
|
113
|
-
},
|
|
114
|
-
createClient(config) {
|
|
115
|
-
const apiKey = config.credentials?.api;
|
|
116
|
-
if (!apiKey) {
|
|
117
|
-
throw new Error("is missing an API key");
|
|
118
|
-
}
|
|
119
|
-
return new GoogleGenAI({
|
|
120
|
-
httpOptions: { retryOptions: { attempts: 1 } },
|
|
121
|
-
apiKey
|
|
122
|
-
});
|
|
123
123
|
}
|
|
124
124
|
};
|
|
125
|
-
function
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
125
|
+
async function requestGemini(path, config, context, body, idempotencyKey) {
|
|
126
|
+
const apiKey = config.credentials?.api;
|
|
127
|
+
if (!apiKey) throw new Error("is missing an API key");
|
|
128
|
+
const response = await fetch(
|
|
129
|
+
`https://generativelanguage.googleapis.com/v1beta/${path}`,
|
|
130
|
+
{
|
|
131
|
+
method: body === void 0 ? "GET" : "POST",
|
|
132
|
+
headers: {
|
|
133
|
+
"content-type": "application/json",
|
|
134
|
+
"x-goog-api-key": apiKey,
|
|
135
|
+
...idempotencyKey ? { "Idempotency-Key": idempotencyKey } : {}
|
|
136
|
+
},
|
|
137
|
+
...body === void 0 ? {} : { body: JSON.stringify(body) },
|
|
138
|
+
signal: context.signal
|
|
139
|
+
}
|
|
140
|
+
);
|
|
141
|
+
if (!response.ok) {
|
|
142
|
+
const text = (await response.text()).trim();
|
|
143
|
+
let detail = text;
|
|
144
|
+
try {
|
|
145
|
+
const error = asRecord(asRecord(JSON.parse(text)).error);
|
|
146
|
+
detail = readNonEmptyString(error.message) ?? text;
|
|
147
|
+
} catch {
|
|
148
|
+
}
|
|
149
|
+
detail = detail.replaceAll(apiKey, "[redacted]").slice(0, 1e3);
|
|
150
|
+
throw httpError(
|
|
151
|
+
response,
|
|
152
|
+
`Gemini API request failed (${response.status})${detail ? `: ${detail}` : "."}`
|
|
153
|
+
);
|
|
135
154
|
}
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
}
|
|
155
|
+
const payload = await response.json();
|
|
156
|
+
if (!isPlainObject(payload)) {
|
|
157
|
+
throw new Error("Gemini API returned an invalid response.");
|
|
158
|
+
}
|
|
159
|
+
return payload;
|
|
160
|
+
}
|
|
161
|
+
function asRecord(value) {
|
|
162
|
+
return isPlainObject(value) ? value : {};
|
|
140
163
|
}
|
|
141
164
|
function readInteractionSteps(interaction) {
|
|
142
165
|
return typeof interaction === "object" && interaction !== null ? interaction.steps : void 0;
|
|
@@ -229,12 +252,27 @@ function buildGeminiGenerateContentRequest({
|
|
|
229
252
|
}) {
|
|
230
253
|
const requestOptions = isPlainObject(options) ? options : {};
|
|
231
254
|
const explicitConfig = isPlainObject(requestOptions.config) ? requestOptions.config : {};
|
|
255
|
+
if (explicitConfig.labels !== void 0) {
|
|
256
|
+
throw new Error(
|
|
257
|
+
"Gemini answer config.labels is not supported by the Gemini Developer API."
|
|
258
|
+
);
|
|
259
|
+
}
|
|
260
|
+
const generationConfig = Object.fromEntries(
|
|
261
|
+
[
|
|
262
|
+
"thinkingConfig",
|
|
263
|
+
"temperature",
|
|
264
|
+
"topP",
|
|
265
|
+
"topK",
|
|
266
|
+
"candidateCount",
|
|
267
|
+
"maxOutputTokens"
|
|
268
|
+
].filter((key) => explicitConfig[key] !== void 0).map((key) => [key, explicitConfig[key]])
|
|
269
|
+
);
|
|
232
270
|
return {
|
|
233
271
|
model: readNonEmptyString(requestOptions.model) ?? defaultModel,
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
272
|
+
body: {
|
|
273
|
+
contents: [{ role: "user", parts: [{ text: prompt }] }],
|
|
274
|
+
tools: [toolConfig],
|
|
275
|
+
...Object.keys(generationConfig).length ? { generationConfig } : {}
|
|
238
276
|
}
|
|
239
277
|
};
|
|
240
278
|
}
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
// package.json
|
|
9
9
|
var package_default = {
|
|
10
10
|
name: "webfox",
|
|
11
|
-
version: "4.2.
|
|
11
|
+
version: "4.2.1",
|
|
12
12
|
description: "Search the web, extract pages, get grounded answers, and run deep research with the web CLI, a TypeScript library, and a pi extension. Bring your own providers and API keys.",
|
|
13
13
|
type: "module",
|
|
14
14
|
files: [
|
|
@@ -96,7 +96,6 @@ var package_default = {
|
|
|
96
96
|
"test:watch": "vitest"
|
|
97
97
|
},
|
|
98
98
|
dependencies: {
|
|
99
|
-
"@google/genai": "^2.21.0",
|
|
100
99
|
"@mendable/firecrawl-js": "^4.38.0",
|
|
101
100
|
"@perplexity-ai/perplexity_ai": "^0.38.5",
|
|
102
101
|
"@tavily/core": "^0.7.9",
|
|
@@ -1249,7 +1248,7 @@ var firecrawlProvider = defineProvider({
|
|
|
1249
1248
|
var geminiProvider = defineProvider({
|
|
1250
1249
|
id: "gemini",
|
|
1251
1250
|
label: "Gemini",
|
|
1252
|
-
docsUrl: "https://
|
|
1251
|
+
docsUrl: "https://ai.google.dev/api",
|
|
1253
1252
|
local: false,
|
|
1254
1253
|
credentials: [
|
|
1255
1254
|
{
|
|
@@ -1303,7 +1302,7 @@ var geminiProvider = defineProvider({
|
|
|
1303
1302
|
type: "string"
|
|
1304
1303
|
}
|
|
1305
1304
|
},
|
|
1306
|
-
description: "
|
|
1305
|
+
description: "Unsupported by the Gemini Developer API; requests with labels are rejected."
|
|
1307
1306
|
},
|
|
1308
1307
|
temperature: {
|
|
1309
1308
|
type: "number",
|
|
@@ -1367,7 +1366,7 @@ var geminiProvider = defineProvider({
|
|
|
1367
1366
|
retrySafe: false
|
|
1368
1367
|
}
|
|
1369
1368
|
},
|
|
1370
|
-
load: async () => (await import("./adapter-
|
|
1369
|
+
load: async () => (await import("./adapter-6EZAIE65.js")).adapter
|
|
1371
1370
|
});
|
|
1372
1371
|
|
|
1373
1372
|
// src/providers/linkup/definition.ts
|
package/dist/cli.js
CHANGED
|
@@ -11,12 +11,12 @@ import {
|
|
|
11
11
|
redactConfig,
|
|
12
12
|
resolveConfigPath,
|
|
13
13
|
setCapabilityDefault
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-SGHBA2PZ.js";
|
|
15
15
|
import "./chunk-WCTOYZVB.js";
|
|
16
16
|
import {
|
|
17
17
|
PACKAGE_VERSION,
|
|
18
18
|
validateConfiguredOptions
|
|
19
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-TJWQTB6W.js";
|
|
20
20
|
import "./chunk-ZVTVERW5.js";
|
|
21
21
|
import {
|
|
22
22
|
CAPABILITIES,
|
package/dist/config.schema.json
CHANGED
|
@@ -2115,7 +2115,7 @@
|
|
|
2115
2115
|
"type": "string"
|
|
2116
2116
|
}
|
|
2117
2117
|
},
|
|
2118
|
-
"description": "
|
|
2118
|
+
"description": "Unsupported by the Gemini Developer API; requests with labels are rejected."
|
|
2119
2119
|
},
|
|
2120
2120
|
"temperature": {
|
|
2121
2121
|
"type": "number",
|
package/dist/index.js
CHANGED
|
@@ -6,12 +6,12 @@ import {
|
|
|
6
6
|
resolveConfigPath,
|
|
7
7
|
setCapabilityDefault,
|
|
8
8
|
validateConfig
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-SGHBA2PZ.js";
|
|
10
10
|
import "./chunk-WCTOYZVB.js";
|
|
11
11
|
import {
|
|
12
12
|
CONFIG_SCHEMA_URL,
|
|
13
13
|
validateConfiguredOptions
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-TJWQTB6W.js";
|
|
15
15
|
import "./chunk-ZVTVERW5.js";
|
|
16
16
|
import {
|
|
17
17
|
CAPABILITIES,
|
package/dist/pi.js
CHANGED
|
@@ -4,9 +4,9 @@ import {
|
|
|
4
4
|
import {
|
|
5
5
|
createWebfox,
|
|
6
6
|
resolveConfigPath
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-SGHBA2PZ.js";
|
|
8
8
|
import "./chunk-WCTOYZVB.js";
|
|
9
|
-
import "./chunk-
|
|
9
|
+
import "./chunk-TJWQTB6W.js";
|
|
10
10
|
import "./chunk-ZVTVERW5.js";
|
|
11
11
|
import {
|
|
12
12
|
CAPABILITIES
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { GoogleGenAI } from "@google/genai";
|
|
2
1
|
import type { ProviderContext, ResearchJob, ResearchPollResult, ToolOutput } from "../contract.js";
|
|
3
2
|
import type { Gemini } from "./types.js";
|
|
4
3
|
export declare const geminiImplementation: {
|
|
@@ -6,7 +5,6 @@ export declare const geminiImplementation: {
|
|
|
6
5
|
research(input: string, config: Gemini, context: ProviderContext, options?: Record<string, unknown>): Promise<ToolOutput>;
|
|
7
6
|
startResearch(input: string, config: Gemini, context: ProviderContext, options?: Record<string, unknown>): Promise<ResearchJob>;
|
|
8
7
|
pollResearch(id: string, config: Gemini, context: ProviderContext, _options?: Record<string, unknown>): Promise<ResearchPollResult>;
|
|
9
|
-
createClient(config: Gemini): GoogleGenAI;
|
|
10
8
|
};
|
|
11
9
|
export declare const adapter: {
|
|
12
10
|
answer(input: import("../contract.js").ProviderRequest<"answer">, config: Gemini, context: ProviderContext): Promise<ToolOutput>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "webfox",
|
|
3
|
-
"version": "4.2.
|
|
3
|
+
"version": "4.2.1",
|
|
4
4
|
"description": "Search the web, extract pages, get grounded answers, and run deep research with the web CLI, a TypeScript library, and a pi extension. Bring your own providers and API keys.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"files": [
|
|
@@ -88,7 +88,6 @@
|
|
|
88
88
|
"test:watch": "vitest"
|
|
89
89
|
},
|
|
90
90
|
"dependencies": {
|
|
91
|
-
"@google/genai": "^2.21.0",
|
|
92
91
|
"@mendable/firecrawl-js": "^4.38.0",
|
|
93
92
|
"@perplexity-ai/perplexity_ai": "^0.38.5",
|
|
94
93
|
"@tavily/core": "^0.7.9",
|