pi-web-providers 2.2.0 → 2.3.0
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 +77 -11
- package/dist/index.js +792 -207
- package/package.json +5 -3
package/dist/index.js
CHANGED
|
@@ -23,7 +23,7 @@ import {
|
|
|
23
23
|
visibleWidth,
|
|
24
24
|
wrapTextWithAnsi
|
|
25
25
|
} from "@mariozechner/pi-tui";
|
|
26
|
-
import { Type as
|
|
26
|
+
import { Type as Type15 } from "@sinclair/typebox";
|
|
27
27
|
|
|
28
28
|
// src/config.ts
|
|
29
29
|
import { execSync } from "node:child_process";
|
|
@@ -41,8 +41,9 @@ var PROVIDER_TOOLS_BY_ID = {
|
|
|
41
41
|
firecrawl: ["search", "contents"],
|
|
42
42
|
gemini: ["search", "answer", "research"],
|
|
43
43
|
linkup: ["search", "contents"],
|
|
44
|
-
|
|
44
|
+
openai: ["search", "answer", "research"],
|
|
45
45
|
parallel: ["search", "contents"],
|
|
46
|
+
perplexity: ["search", "answer", "research"],
|
|
46
47
|
tavily: ["search", "contents"],
|
|
47
48
|
valyu: ["search", "contents", "answer", "research"]
|
|
48
49
|
};
|
|
@@ -86,8 +87,9 @@ var PROVIDER_IDS = [
|
|
|
86
87
|
"firecrawl",
|
|
87
88
|
"gemini",
|
|
88
89
|
"linkup",
|
|
89
|
-
"
|
|
90
|
+
"openai",
|
|
90
91
|
"parallel",
|
|
92
|
+
"perplexity",
|
|
91
93
|
"tavily",
|
|
92
94
|
"valyu"
|
|
93
95
|
];
|
|
@@ -271,6 +273,18 @@ function normalizeProvider(providerId, raw, source) {
|
|
|
271
273
|
options: readOptionalObject,
|
|
272
274
|
settings: parseOptionalExecutionSettings
|
|
273
275
|
});
|
|
276
|
+
case "openai":
|
|
277
|
+
return parseProviderWithShape(raw, source, providerId, {
|
|
278
|
+
apiKey: readOptionalString,
|
|
279
|
+
baseUrl: readOptionalString,
|
|
280
|
+
options: (value, innerSource, field) => parseOptionalCapabilityOptions(
|
|
281
|
+
value,
|
|
282
|
+
innerSource,
|
|
283
|
+
field,
|
|
284
|
+
["search", "answer", "research"]
|
|
285
|
+
),
|
|
286
|
+
settings: parseOptionalExecutionSettings
|
|
287
|
+
});
|
|
274
288
|
case "firecrawl":
|
|
275
289
|
case "linkup":
|
|
276
290
|
case "parallel":
|
|
@@ -4082,12 +4096,528 @@ function toDate(value, name) {
|
|
|
4082
4096
|
return date;
|
|
4083
4097
|
}
|
|
4084
4098
|
|
|
4085
|
-
// src/providers/
|
|
4099
|
+
// src/providers/openai.ts
|
|
4086
4100
|
import { Type as Type10 } from "@sinclair/typebox";
|
|
4101
|
+
import OpenAI from "openai";
|
|
4102
|
+
var DEFAULT_SEARCH_MODEL2 = "gpt-4.1";
|
|
4103
|
+
var DEFAULT_ANSWER_MODEL2 = "gpt-4.1";
|
|
4104
|
+
var DEFAULT_RESEARCH_MODEL = "o4-mini-deep-research";
|
|
4105
|
+
var openaiSearchOptionsSchema = Type10.Object(
|
|
4106
|
+
{
|
|
4107
|
+
model: Type10.Optional(
|
|
4108
|
+
Type10.String({
|
|
4109
|
+
description: "OpenAI model to use for web search (for example 'gpt-4.1')."
|
|
4110
|
+
})
|
|
4111
|
+
),
|
|
4112
|
+
instructions: Type10.Optional(
|
|
4113
|
+
Type10.String({
|
|
4114
|
+
description: "Optional instructions that shape source selection and result style."
|
|
4115
|
+
})
|
|
4116
|
+
)
|
|
4117
|
+
},
|
|
4118
|
+
{ description: "OpenAI search options." }
|
|
4119
|
+
);
|
|
4120
|
+
var openaiAnswerOptionsSchema = Type10.Object(
|
|
4121
|
+
{
|
|
4122
|
+
model: Type10.Optional(
|
|
4123
|
+
Type10.String({
|
|
4124
|
+
description: "OpenAI model to use for grounded answers (for example 'gpt-4.1')."
|
|
4125
|
+
})
|
|
4126
|
+
),
|
|
4127
|
+
instructions: Type10.Optional(
|
|
4128
|
+
Type10.String({
|
|
4129
|
+
description: "Optional instructions that shape the answer structure, tone, and source selection."
|
|
4130
|
+
})
|
|
4131
|
+
)
|
|
4132
|
+
},
|
|
4133
|
+
{ description: "OpenAI answer options." }
|
|
4134
|
+
);
|
|
4135
|
+
var openaiResearchOptionsSchema = Type10.Object(
|
|
4136
|
+
{
|
|
4137
|
+
model: Type10.Optional(
|
|
4138
|
+
Type10.String({
|
|
4139
|
+
description: "OpenAI deep research model to use (for example 'o4-mini-deep-research')."
|
|
4140
|
+
})
|
|
4141
|
+
),
|
|
4142
|
+
instructions: Type10.Optional(
|
|
4143
|
+
Type10.String({
|
|
4144
|
+
description: "Optional instructions that shape the report structure, tone, and source selection."
|
|
4145
|
+
})
|
|
4146
|
+
),
|
|
4147
|
+
max_tool_calls: Type10.Optional(
|
|
4148
|
+
Type10.Integer({
|
|
4149
|
+
minimum: 1,
|
|
4150
|
+
description: "Maximum number of built-in tool calls the model may make during the research run."
|
|
4151
|
+
})
|
|
4152
|
+
)
|
|
4153
|
+
},
|
|
4154
|
+
{ description: "OpenAI deep research options." }
|
|
4155
|
+
);
|
|
4156
|
+
var searchResultSchema = {
|
|
4157
|
+
type: "object",
|
|
4158
|
+
additionalProperties: false,
|
|
4159
|
+
required: ["sources"],
|
|
4160
|
+
properties: {
|
|
4161
|
+
sources: {
|
|
4162
|
+
type: "array",
|
|
4163
|
+
items: {
|
|
4164
|
+
type: "object",
|
|
4165
|
+
additionalProperties: false,
|
|
4166
|
+
required: ["title", "url", "snippet"],
|
|
4167
|
+
properties: {
|
|
4168
|
+
title: { type: "string" },
|
|
4169
|
+
url: { type: "string" },
|
|
4170
|
+
snippet: { type: "string" }
|
|
4171
|
+
}
|
|
4172
|
+
}
|
|
4173
|
+
}
|
|
4174
|
+
}
|
|
4175
|
+
};
|
|
4176
|
+
var openaiAdapter = {
|
|
4177
|
+
id: "openai",
|
|
4178
|
+
label: "OpenAI",
|
|
4179
|
+
docsUrl: "https://platform.openai.com/docs/guides/deep-research",
|
|
4180
|
+
tools: ["search", "answer", "research"],
|
|
4181
|
+
getToolOptionsSchema(capability) {
|
|
4182
|
+
switch (capability) {
|
|
4183
|
+
case "search":
|
|
4184
|
+
return openaiSearchOptionsSchema;
|
|
4185
|
+
case "answer":
|
|
4186
|
+
return openaiAnswerOptionsSchema;
|
|
4187
|
+
case "research":
|
|
4188
|
+
return openaiResearchOptionsSchema;
|
|
4189
|
+
default:
|
|
4190
|
+
return void 0;
|
|
4191
|
+
}
|
|
4192
|
+
},
|
|
4193
|
+
createTemplate() {
|
|
4194
|
+
return {
|
|
4195
|
+
apiKey: "OPENAI_API_KEY",
|
|
4196
|
+
options: {
|
|
4197
|
+
search: {
|
|
4198
|
+
model: DEFAULT_SEARCH_MODEL2
|
|
4199
|
+
},
|
|
4200
|
+
answer: {
|
|
4201
|
+
model: DEFAULT_ANSWER_MODEL2
|
|
4202
|
+
},
|
|
4203
|
+
research: {
|
|
4204
|
+
model: DEFAULT_RESEARCH_MODEL
|
|
4205
|
+
}
|
|
4206
|
+
}
|
|
4207
|
+
};
|
|
4208
|
+
},
|
|
4209
|
+
getConfigForCapability(capability, config) {
|
|
4210
|
+
switch (capability) {
|
|
4211
|
+
case "search":
|
|
4212
|
+
return {
|
|
4213
|
+
apiKey: config.apiKey,
|
|
4214
|
+
baseUrl: config.baseUrl,
|
|
4215
|
+
options: config.options?.search,
|
|
4216
|
+
settings: config.settings
|
|
4217
|
+
};
|
|
4218
|
+
case "answer":
|
|
4219
|
+
return {
|
|
4220
|
+
apiKey: config.apiKey,
|
|
4221
|
+
baseUrl: config.baseUrl,
|
|
4222
|
+
options: config.options?.answer,
|
|
4223
|
+
settings: config.settings
|
|
4224
|
+
};
|
|
4225
|
+
case "research":
|
|
4226
|
+
return {
|
|
4227
|
+
apiKey: config.apiKey,
|
|
4228
|
+
baseUrl: config.baseUrl,
|
|
4229
|
+
options: config.options?.research,
|
|
4230
|
+
settings: config.settings
|
|
4231
|
+
};
|
|
4232
|
+
default:
|
|
4233
|
+
return config;
|
|
4234
|
+
}
|
|
4235
|
+
},
|
|
4236
|
+
getCapabilityStatus(config) {
|
|
4237
|
+
return getApiKeyStatus(config?.apiKey);
|
|
4238
|
+
},
|
|
4239
|
+
buildPlan(request, config) {
|
|
4240
|
+
return buildProviderPlan({
|
|
4241
|
+
request,
|
|
4242
|
+
config,
|
|
4243
|
+
providerId: openaiAdapter.id,
|
|
4244
|
+
providerLabel: openaiAdapter.label,
|
|
4245
|
+
handlers: {
|
|
4246
|
+
search: {
|
|
4247
|
+
execute: (searchRequest, providerConfig, context) => openaiAdapter.search(
|
|
4248
|
+
searchRequest.query,
|
|
4249
|
+
searchRequest.maxResults,
|
|
4250
|
+
providerConfig,
|
|
4251
|
+
context,
|
|
4252
|
+
searchRequest.options
|
|
4253
|
+
)
|
|
4254
|
+
},
|
|
4255
|
+
answer: {
|
|
4256
|
+
execute: (answerRequest, providerConfig, context) => openaiAdapter.answer(
|
|
4257
|
+
answerRequest.query,
|
|
4258
|
+
providerConfig,
|
|
4259
|
+
context,
|
|
4260
|
+
answerRequest.options
|
|
4261
|
+
)
|
|
4262
|
+
},
|
|
4263
|
+
research: {
|
|
4264
|
+
execute: (researchRequest, providerConfig, context) => openaiAdapter.research(
|
|
4265
|
+
researchRequest.input,
|
|
4266
|
+
providerConfig,
|
|
4267
|
+
context,
|
|
4268
|
+
researchRequest.options
|
|
4269
|
+
)
|
|
4270
|
+
}
|
|
4271
|
+
}
|
|
4272
|
+
});
|
|
4273
|
+
},
|
|
4274
|
+
async search(query2, maxResults, config, context, options) {
|
|
4275
|
+
const client = createClient5(config);
|
|
4276
|
+
const response = await client.responses.create(
|
|
4277
|
+
buildOpenAISearchRequest(query2, maxResults, config, options),
|
|
4278
|
+
buildRequestOptions2(context.signal, context.idempotencyKey)
|
|
4279
|
+
);
|
|
4280
|
+
return parseSearchResponse2(response, maxResults);
|
|
4281
|
+
},
|
|
4282
|
+
async answer(query2, config, context, options) {
|
|
4283
|
+
const client = createClient5(config);
|
|
4284
|
+
const response = await client.responses.create(
|
|
4285
|
+
buildOpenAIAnswerRequest(query2, config, options),
|
|
4286
|
+
buildRequestOptions2(context.signal, context.idempotencyKey)
|
|
4287
|
+
);
|
|
4288
|
+
return ensureCompletedResponse(response, "answer");
|
|
4289
|
+
},
|
|
4290
|
+
async research(input, config, context, options) {
|
|
4291
|
+
return await executeAsyncResearch({
|
|
4292
|
+
providerLabel: openaiAdapter.label,
|
|
4293
|
+
providerId: openaiAdapter.id,
|
|
4294
|
+
context,
|
|
4295
|
+
start: (researchContext) => openaiAdapter.startResearch(input, config, researchContext, options),
|
|
4296
|
+
poll: (id, researchContext) => openaiAdapter.pollResearch(id, config, researchContext, options)
|
|
4297
|
+
});
|
|
4298
|
+
},
|
|
4299
|
+
async startResearch(input, config, context, options) {
|
|
4300
|
+
const client = createClient5(config);
|
|
4301
|
+
const response = await client.responses.create(
|
|
4302
|
+
buildOpenAIResearchRequest(input, config, options),
|
|
4303
|
+
buildRequestOptions2(context.signal, context.idempotencyKey)
|
|
4304
|
+
);
|
|
4305
|
+
return { id: response.id };
|
|
4306
|
+
},
|
|
4307
|
+
async pollResearch(id, config, context, _options) {
|
|
4308
|
+
const client = createClient5(config);
|
|
4309
|
+
const response = await client.responses.retrieve(
|
|
4310
|
+
id,
|
|
4311
|
+
void 0,
|
|
4312
|
+
buildRequestOptions2(context.signal)
|
|
4313
|
+
);
|
|
4314
|
+
const status = response.status ?? "completed";
|
|
4315
|
+
if (status === "completed") {
|
|
4316
|
+
return {
|
|
4317
|
+
status: "completed",
|
|
4318
|
+
output: formatResponseOutput(response, "research")
|
|
4319
|
+
};
|
|
4320
|
+
}
|
|
4321
|
+
if (status === "failed") {
|
|
4322
|
+
return {
|
|
4323
|
+
status: "failed",
|
|
4324
|
+
error: response.error?.message ?? "research failed"
|
|
4325
|
+
};
|
|
4326
|
+
}
|
|
4327
|
+
if (status === "cancelled") {
|
|
4328
|
+
return {
|
|
4329
|
+
status: "cancelled",
|
|
4330
|
+
error: "research was canceled"
|
|
4331
|
+
};
|
|
4332
|
+
}
|
|
4333
|
+
if (status === "incomplete") {
|
|
4334
|
+
return {
|
|
4335
|
+
status: "failed",
|
|
4336
|
+
error: formatIncompleteError(response, "research")
|
|
4337
|
+
};
|
|
4338
|
+
}
|
|
4339
|
+
return {
|
|
4340
|
+
status: "in_progress",
|
|
4341
|
+
statusText: status
|
|
4342
|
+
};
|
|
4343
|
+
}
|
|
4344
|
+
};
|
|
4345
|
+
function createClient5(config) {
|
|
4346
|
+
const apiKey = resolveConfigValue(config.apiKey);
|
|
4347
|
+
if (!apiKey) {
|
|
4348
|
+
throw new Error("is missing an API key");
|
|
4349
|
+
}
|
|
4350
|
+
const baseUrl = resolveConfigValue(config.baseUrl);
|
|
4351
|
+
return new OpenAI({
|
|
4352
|
+
apiKey,
|
|
4353
|
+
...baseUrl ? { baseURL: baseUrl } : {}
|
|
4354
|
+
});
|
|
4355
|
+
}
|
|
4356
|
+
function buildOpenAISearchRequest(query2, maxResults, config, options) {
|
|
4357
|
+
const mergedOptions = resolveOpenAISearchOptions(config, options);
|
|
4358
|
+
const model = mergedOptions.model ?? DEFAULT_SEARCH_MODEL2;
|
|
4359
|
+
const instructions = mergedOptions.instructions;
|
|
4360
|
+
return {
|
|
4361
|
+
model,
|
|
4362
|
+
input: [
|
|
4363
|
+
"Search the public web and return only the most relevant sources for the user's query.",
|
|
4364
|
+
`Return at most ${maxResults} sources.`,
|
|
4365
|
+
"Prefer official, primary, or highly reputable sources when available.",
|
|
4366
|
+
"Each snippet should be short, specific, and grounded in the retrieved source.",
|
|
4367
|
+
"Return only data matching the provided JSON schema.",
|
|
4368
|
+
"",
|
|
4369
|
+
`User query: ${query2}`
|
|
4370
|
+
].join("\n"),
|
|
4371
|
+
tools: [{ type: "web_search_preview" }],
|
|
4372
|
+
text: {
|
|
4373
|
+
format: {
|
|
4374
|
+
type: "json_schema",
|
|
4375
|
+
name: "openai_web_search_results",
|
|
4376
|
+
schema: searchResultSchema,
|
|
4377
|
+
strict: true
|
|
4378
|
+
}
|
|
4379
|
+
},
|
|
4380
|
+
...instructions ? { instructions } : {}
|
|
4381
|
+
};
|
|
4382
|
+
}
|
|
4383
|
+
function buildOpenAIAnswerRequest(query2, config, options) {
|
|
4384
|
+
const mergedOptions = resolveOpenAIAnswerOptions(config, options);
|
|
4385
|
+
const model = mergedOptions.model ?? DEFAULT_ANSWER_MODEL2;
|
|
4386
|
+
const instructions = mergedOptions.instructions;
|
|
4387
|
+
return {
|
|
4388
|
+
model,
|
|
4389
|
+
input: query2,
|
|
4390
|
+
tools: [{ type: "web_search_preview" }],
|
|
4391
|
+
...instructions ? { instructions } : {}
|
|
4392
|
+
};
|
|
4393
|
+
}
|
|
4394
|
+
function buildOpenAIResearchRequest(input, config, options) {
|
|
4395
|
+
const mergedOptions = resolveOpenAIResearchOptions(config, options);
|
|
4396
|
+
const model = mergedOptions.model ?? DEFAULT_RESEARCH_MODEL;
|
|
4397
|
+
const instructions = mergedOptions.instructions;
|
|
4398
|
+
const maxToolCalls = mergedOptions.max_tool_calls;
|
|
4399
|
+
return {
|
|
4400
|
+
model,
|
|
4401
|
+
input,
|
|
4402
|
+
background: true,
|
|
4403
|
+
tools: [{ type: "web_search_preview" }],
|
|
4404
|
+
...instructions ? { instructions } : {},
|
|
4405
|
+
...maxToolCalls ? { max_tool_calls: maxToolCalls } : {}
|
|
4406
|
+
};
|
|
4407
|
+
}
|
|
4408
|
+
function resolveOpenAISearchOptions(config, options) {
|
|
4409
|
+
const mergedOptions = {
|
|
4410
|
+
...config.options?.search ?? {},
|
|
4411
|
+
...options ?? {}
|
|
4412
|
+
};
|
|
4413
|
+
const model = readNonEmptyString4(mergedOptions.model);
|
|
4414
|
+
const instructions = readNonEmptyString4(mergedOptions.instructions);
|
|
4415
|
+
return {
|
|
4416
|
+
...model ? { model } : {},
|
|
4417
|
+
...instructions ? { instructions } : {}
|
|
4418
|
+
};
|
|
4419
|
+
}
|
|
4420
|
+
function resolveOpenAIAnswerOptions(config, options) {
|
|
4421
|
+
const mergedOptions = {
|
|
4422
|
+
...config.options?.answer ?? {},
|
|
4423
|
+
...options ?? {}
|
|
4424
|
+
};
|
|
4425
|
+
const model = readNonEmptyString4(mergedOptions.model);
|
|
4426
|
+
const instructions = readNonEmptyString4(mergedOptions.instructions);
|
|
4427
|
+
return {
|
|
4428
|
+
...model ? { model } : {},
|
|
4429
|
+
...instructions ? { instructions } : {}
|
|
4430
|
+
};
|
|
4431
|
+
}
|
|
4432
|
+
function resolveOpenAIResearchOptions(config, options) {
|
|
4433
|
+
const mergedOptions = {
|
|
4434
|
+
...config.options?.research ?? {},
|
|
4435
|
+
...options ?? {}
|
|
4436
|
+
};
|
|
4437
|
+
const model = readNonEmptyString4(mergedOptions.model);
|
|
4438
|
+
const instructions = readNonEmptyString4(mergedOptions.instructions);
|
|
4439
|
+
const maxToolCalls = readPositiveInteger2(mergedOptions.max_tool_calls);
|
|
4440
|
+
return {
|
|
4441
|
+
...model ? { model } : {},
|
|
4442
|
+
...instructions ? { instructions } : {},
|
|
4443
|
+
...maxToolCalls ? { max_tool_calls: maxToolCalls } : {}
|
|
4444
|
+
};
|
|
4445
|
+
}
|
|
4446
|
+
function buildRequestOptions2(signal, idempotencyKey) {
|
|
4447
|
+
if (!signal && !idempotencyKey) {
|
|
4448
|
+
return void 0;
|
|
4449
|
+
}
|
|
4450
|
+
return {
|
|
4451
|
+
...signal ? { signal } : {},
|
|
4452
|
+
...idempotencyKey ? { idempotencyKey } : {}
|
|
4453
|
+
};
|
|
4454
|
+
}
|
|
4455
|
+
function parseSearchResponse2(response, maxResults) {
|
|
4456
|
+
const status = response.status ?? "completed";
|
|
4457
|
+
if (status === "failed") {
|
|
4458
|
+
throw new Error(response.error?.message ?? "search failed");
|
|
4459
|
+
}
|
|
4460
|
+
if (status === "cancelled") {
|
|
4461
|
+
throw new Error("search was canceled");
|
|
4462
|
+
}
|
|
4463
|
+
if (status === "incomplete") {
|
|
4464
|
+
throw new Error(formatIncompleteError(response, "search"));
|
|
4465
|
+
}
|
|
4466
|
+
if (status !== "completed") {
|
|
4467
|
+
throw new Error(`search did not complete (status: ${status})`);
|
|
4468
|
+
}
|
|
4469
|
+
const payload = parseSearchPayload(response.output_text);
|
|
4470
|
+
return {
|
|
4471
|
+
provider: openaiAdapter.id,
|
|
4472
|
+
results: payload.sources.slice(0, maxResults).map((source) => ({
|
|
4473
|
+
title: source.title.trim(),
|
|
4474
|
+
url: source.url.trim(),
|
|
4475
|
+
snippet: trimSnippet(source.snippet)
|
|
4476
|
+
}))
|
|
4477
|
+
};
|
|
4478
|
+
}
|
|
4479
|
+
function ensureCompletedResponse(response, operation) {
|
|
4480
|
+
const status = response.status ?? "completed";
|
|
4481
|
+
if (status === "completed") {
|
|
4482
|
+
return formatResponseOutput(response, operation);
|
|
4483
|
+
}
|
|
4484
|
+
if (status === "failed") {
|
|
4485
|
+
throw new Error(response.error?.message ?? `${operation} failed`);
|
|
4486
|
+
}
|
|
4487
|
+
if (status === "cancelled") {
|
|
4488
|
+
throw new Error(`${operation} was canceled`);
|
|
4489
|
+
}
|
|
4490
|
+
if (status === "incomplete") {
|
|
4491
|
+
throw new Error(formatIncompleteError(response, operation));
|
|
4492
|
+
}
|
|
4493
|
+
throw new Error(`${operation} did not complete (status: ${status})`);
|
|
4494
|
+
}
|
|
4495
|
+
function formatResponseOutput(response, operation) {
|
|
4496
|
+
const lines = [];
|
|
4497
|
+
lines.push(
|
|
4498
|
+
response.output_text?.trim() || `OpenAI ${operation} completed without textual output.`
|
|
4499
|
+
);
|
|
4500
|
+
const citations = extractUrlCitations(response);
|
|
4501
|
+
if (citations.length > 0) {
|
|
4502
|
+
lines.push("");
|
|
4503
|
+
lines.push("Sources:");
|
|
4504
|
+
for (const [index, citation] of citations.entries()) {
|
|
4505
|
+
lines.push(`${index + 1}. ${citation.title}`);
|
|
4506
|
+
lines.push(` ${citation.url}`);
|
|
4507
|
+
}
|
|
4508
|
+
}
|
|
4509
|
+
return {
|
|
4510
|
+
provider: openaiAdapter.id,
|
|
4511
|
+
text: lines.join("\n").trimEnd(),
|
|
4512
|
+
itemCount: citations.length,
|
|
4513
|
+
metadata: {
|
|
4514
|
+
responseId: response.id,
|
|
4515
|
+
model: response.model,
|
|
4516
|
+
citations
|
|
4517
|
+
}
|
|
4518
|
+
};
|
|
4519
|
+
}
|
|
4520
|
+
function extractUrlCitations(response) {
|
|
4521
|
+
const citations = [];
|
|
4522
|
+
const seen = /* @__PURE__ */ new Set();
|
|
4523
|
+
for (const item of response.output) {
|
|
4524
|
+
if (item.type !== "message" || !item.content) {
|
|
4525
|
+
continue;
|
|
4526
|
+
}
|
|
4527
|
+
for (const content of item.content) {
|
|
4528
|
+
if (content.type !== "output_text" || !content.annotations) {
|
|
4529
|
+
continue;
|
|
4530
|
+
}
|
|
4531
|
+
for (const annotation of content.annotations) {
|
|
4532
|
+
if (annotation.type !== "url_citation") {
|
|
4533
|
+
continue;
|
|
4534
|
+
}
|
|
4535
|
+
const title = readNonEmptyString4(annotation.title);
|
|
4536
|
+
const url = readNonEmptyString4(annotation.url);
|
|
4537
|
+
const startIndex = readInteger(annotation.start_index);
|
|
4538
|
+
const endIndex = readInteger(annotation.end_index);
|
|
4539
|
+
if (!title || !url || startIndex === void 0 || endIndex === void 0) {
|
|
4540
|
+
continue;
|
|
4541
|
+
}
|
|
4542
|
+
const citation = {
|
|
4543
|
+
title,
|
|
4544
|
+
url,
|
|
4545
|
+
startIndex,
|
|
4546
|
+
endIndex
|
|
4547
|
+
};
|
|
4548
|
+
const key = [
|
|
4549
|
+
citation.title,
|
|
4550
|
+
citation.url,
|
|
4551
|
+
String(citation.startIndex),
|
|
4552
|
+
String(citation.endIndex)
|
|
4553
|
+
].join("::");
|
|
4554
|
+
if (seen.has(key)) {
|
|
4555
|
+
continue;
|
|
4556
|
+
}
|
|
4557
|
+
seen.add(key);
|
|
4558
|
+
citations.push(citation);
|
|
4559
|
+
}
|
|
4560
|
+
}
|
|
4561
|
+
}
|
|
4562
|
+
return citations;
|
|
4563
|
+
}
|
|
4564
|
+
function parseSearchPayload(text) {
|
|
4565
|
+
let parsed;
|
|
4566
|
+
try {
|
|
4567
|
+
parsed = JSON.parse(text ?? "");
|
|
4568
|
+
} catch (error) {
|
|
4569
|
+
throw new Error(
|
|
4570
|
+
`search returned invalid JSON: ${error.message}`
|
|
4571
|
+
);
|
|
4572
|
+
}
|
|
4573
|
+
if (typeof parsed !== "object" || parsed === null || !("sources" in parsed) || !Array.isArray(parsed.sources)) {
|
|
4574
|
+
throw new Error("search output must include a 'sources' array");
|
|
4575
|
+
}
|
|
4576
|
+
return {
|
|
4577
|
+
sources: parsed.sources.map((source, index) => {
|
|
4578
|
+
if (typeof source !== "object" || source === null) {
|
|
4579
|
+
throw new Error(`search source at index ${index} must be an object`);
|
|
4580
|
+
}
|
|
4581
|
+
const entry = source;
|
|
4582
|
+
const title = readNonEmptyString4(entry.title);
|
|
4583
|
+
const url = readNonEmptyString4(entry.url);
|
|
4584
|
+
const snippet = readNonEmptyString4(entry.snippet);
|
|
4585
|
+
if (!title) {
|
|
4586
|
+
throw new Error(`search source at index ${index} is missing title`);
|
|
4587
|
+
}
|
|
4588
|
+
if (!url) {
|
|
4589
|
+
throw new Error(`search source at index ${index} is missing url`);
|
|
4590
|
+
}
|
|
4591
|
+
if (!snippet) {
|
|
4592
|
+
throw new Error(`search source at index ${index} is missing snippet`);
|
|
4593
|
+
}
|
|
4594
|
+
return { title, url, snippet };
|
|
4595
|
+
})
|
|
4596
|
+
};
|
|
4597
|
+
}
|
|
4598
|
+
function formatIncompleteError(response, operation) {
|
|
4599
|
+
const reason = response.incomplete_details?.reason;
|
|
4600
|
+
if (reason) {
|
|
4601
|
+
return `${operation} ended incomplete (${reason})`;
|
|
4602
|
+
}
|
|
4603
|
+
return `${operation} ended incomplete`;
|
|
4604
|
+
}
|
|
4605
|
+
function readNonEmptyString4(value) {
|
|
4606
|
+
return typeof value === "string" && value.trim().length > 0 ? value : void 0;
|
|
4607
|
+
}
|
|
4608
|
+
function readPositiveInteger2(value) {
|
|
4609
|
+
return typeof value === "number" && Number.isInteger(value) && value > 0 ? value : void 0;
|
|
4610
|
+
}
|
|
4611
|
+
function readInteger(value) {
|
|
4612
|
+
return typeof value === "number" && Number.isInteger(value) ? value : void 0;
|
|
4613
|
+
}
|
|
4614
|
+
|
|
4615
|
+
// src/providers/parallel.ts
|
|
4616
|
+
import { Type as Type11 } from "@sinclair/typebox";
|
|
4087
4617
|
import ParallelClient from "parallel-web";
|
|
4088
|
-
var parallelSearchOptionsSchema =
|
|
4618
|
+
var parallelSearchOptionsSchema = Type11.Object(
|
|
4089
4619
|
{
|
|
4090
|
-
mode:
|
|
4620
|
+
mode: Type11.Optional(
|
|
4091
4621
|
literalUnion(["agentic", "one-shot"], {
|
|
4092
4622
|
description: "Parallel search mode."
|
|
4093
4623
|
})
|
|
@@ -4095,13 +4625,13 @@ var parallelSearchOptionsSchema = Type10.Object(
|
|
|
4095
4625
|
},
|
|
4096
4626
|
{ description: "Parallel search options." }
|
|
4097
4627
|
);
|
|
4098
|
-
var parallelExtractOptionsSchema =
|
|
4628
|
+
var parallelExtractOptionsSchema = Type11.Object(
|
|
4099
4629
|
{
|
|
4100
|
-
excerpts:
|
|
4101
|
-
|
|
4630
|
+
excerpts: Type11.Optional(
|
|
4631
|
+
Type11.Boolean({ description: "Include excerpts in extraction results." })
|
|
4102
4632
|
),
|
|
4103
|
-
full_content:
|
|
4104
|
-
|
|
4633
|
+
full_content: Type11.Optional(
|
|
4634
|
+
Type11.Boolean({
|
|
4105
4635
|
description: "Include full page content in extraction results."
|
|
4106
4636
|
})
|
|
4107
4637
|
)
|
|
@@ -4188,7 +4718,7 @@ var parallelAdapter = {
|
|
|
4188
4718
|
});
|
|
4189
4719
|
},
|
|
4190
4720
|
async search(query2, maxResults, config, context, options) {
|
|
4191
|
-
const client =
|
|
4721
|
+
const client = createClient6(config);
|
|
4192
4722
|
const defaults = stripLocalExecutionOptions(asJsonObject(config.options?.search)) ?? {};
|
|
4193
4723
|
const response = await client.beta.search(
|
|
4194
4724
|
{
|
|
@@ -4197,7 +4727,7 @@ var parallelAdapter = {
|
|
|
4197
4727
|
objective: query2,
|
|
4198
4728
|
max_results: maxResults
|
|
4199
4729
|
},
|
|
4200
|
-
|
|
4730
|
+
buildRequestOptions3(context)
|
|
4201
4731
|
);
|
|
4202
4732
|
return {
|
|
4203
4733
|
provider: parallelAdapter.id,
|
|
@@ -4209,7 +4739,7 @@ var parallelAdapter = {
|
|
|
4209
4739
|
};
|
|
4210
4740
|
},
|
|
4211
4741
|
async contents(urls, config, context, options) {
|
|
4212
|
-
const client =
|
|
4742
|
+
const client = createClient6(config);
|
|
4213
4743
|
const defaults = stripLocalExecutionOptions(asJsonObject(config.options?.extract)) ?? {};
|
|
4214
4744
|
const response = await client.beta.extract(
|
|
4215
4745
|
{
|
|
@@ -4217,7 +4747,7 @@ var parallelAdapter = {
|
|
|
4217
4747
|
...options ?? {},
|
|
4218
4748
|
urls
|
|
4219
4749
|
},
|
|
4220
|
-
|
|
4750
|
+
buildRequestOptions3(context)
|
|
4221
4751
|
);
|
|
4222
4752
|
const resultsByUrl = new Map(
|
|
4223
4753
|
response.results.map((result) => [result.url, result])
|
|
@@ -4248,7 +4778,7 @@ var parallelAdapter = {
|
|
|
4248
4778
|
};
|
|
4249
4779
|
}
|
|
4250
4780
|
};
|
|
4251
|
-
function
|
|
4781
|
+
function createClient6(config) {
|
|
4252
4782
|
const apiKey = resolveConfigValue(config.apiKey);
|
|
4253
4783
|
if (!apiKey) {
|
|
4254
4784
|
throw new Error("is missing an API key");
|
|
@@ -4258,48 +4788,48 @@ function createClient5(config) {
|
|
|
4258
4788
|
baseURL: resolveConfigValue(config.baseUrl)
|
|
4259
4789
|
});
|
|
4260
4790
|
}
|
|
4261
|
-
function
|
|
4791
|
+
function buildRequestOptions3(context) {
|
|
4262
4792
|
return context.signal ? { signal: context.signal } : void 0;
|
|
4263
4793
|
}
|
|
4264
4794
|
|
|
4265
4795
|
// src/providers/perplexity.ts
|
|
4266
4796
|
import PerplexityClient from "@perplexity-ai/perplexity_ai";
|
|
4267
|
-
import { Type as
|
|
4268
|
-
var
|
|
4269
|
-
var
|
|
4270
|
-
var perplexitySearchOptionsSchema =
|
|
4797
|
+
import { Type as Type12 } from "@sinclair/typebox";
|
|
4798
|
+
var DEFAULT_ANSWER_MODEL3 = "sonar";
|
|
4799
|
+
var DEFAULT_RESEARCH_MODEL2 = "sonar-deep-research";
|
|
4800
|
+
var perplexitySearchOptionsSchema = Type12.Object(
|
|
4271
4801
|
{
|
|
4272
|
-
country:
|
|
4273
|
-
|
|
4802
|
+
country: Type12.Optional(
|
|
4803
|
+
Type12.String({ description: "Country hint for search results." })
|
|
4274
4804
|
),
|
|
4275
|
-
search_mode:
|
|
4276
|
-
|
|
4805
|
+
search_mode: Type12.Optional(
|
|
4806
|
+
Type12.String({ description: "Perplexity search mode." })
|
|
4277
4807
|
),
|
|
4278
|
-
search_domain_filter:
|
|
4279
|
-
|
|
4808
|
+
search_domain_filter: Type12.Optional(
|
|
4809
|
+
Type12.Array(Type12.String(), {
|
|
4280
4810
|
description: "Restrict search results to these domains."
|
|
4281
4811
|
})
|
|
4282
4812
|
),
|
|
4283
|
-
search_recency_filter:
|
|
4284
|
-
|
|
4813
|
+
search_recency_filter: Type12.Optional(
|
|
4814
|
+
Type12.String({ description: "Recency filter for search results." })
|
|
4285
4815
|
)
|
|
4286
4816
|
},
|
|
4287
4817
|
{ description: "Perplexity search options." }
|
|
4288
4818
|
);
|
|
4289
|
-
var perplexityAnswerOptionsSchema =
|
|
4819
|
+
var perplexityAnswerOptionsSchema = Type12.Object(
|
|
4290
4820
|
{
|
|
4291
|
-
model:
|
|
4292
|
-
|
|
4821
|
+
model: Type12.Optional(
|
|
4822
|
+
Type12.String({
|
|
4293
4823
|
description: "Perplexity model to use (for example 'sonar' or 'sonar-pro')."
|
|
4294
4824
|
})
|
|
4295
4825
|
)
|
|
4296
4826
|
},
|
|
4297
4827
|
{ description: "Perplexity answer options." }
|
|
4298
4828
|
);
|
|
4299
|
-
var perplexityResearchOptionsSchema =
|
|
4829
|
+
var perplexityResearchOptionsSchema = Type12.Object(
|
|
4300
4830
|
{
|
|
4301
|
-
model:
|
|
4302
|
-
|
|
4831
|
+
model: Type12.Optional(
|
|
4832
|
+
Type12.String({
|
|
4303
4833
|
description: "Perplexity model to use (for example 'sonar-deep-research')."
|
|
4304
4834
|
})
|
|
4305
4835
|
)
|
|
@@ -4328,10 +4858,10 @@ var perplexityAdapter = {
|
|
|
4328
4858
|
apiKey: "PERPLEXITY_API_KEY",
|
|
4329
4859
|
options: {
|
|
4330
4860
|
answer: {
|
|
4331
|
-
model:
|
|
4861
|
+
model: DEFAULT_ANSWER_MODEL3
|
|
4332
4862
|
},
|
|
4333
4863
|
research: {
|
|
4334
|
-
model:
|
|
4864
|
+
model: DEFAULT_RESEARCH_MODEL2
|
|
4335
4865
|
}
|
|
4336
4866
|
}
|
|
4337
4867
|
};
|
|
@@ -4375,7 +4905,7 @@ var perplexityAdapter = {
|
|
|
4375
4905
|
});
|
|
4376
4906
|
},
|
|
4377
4907
|
async search(query2, maxResults, config, context, options) {
|
|
4378
|
-
const client =
|
|
4908
|
+
const client = createClient7(config);
|
|
4379
4909
|
const request = {
|
|
4380
4910
|
...stripLocalExecutionOptions(asJsonObject(config.options?.search)) ?? {},
|
|
4381
4911
|
...options ?? {},
|
|
@@ -4384,7 +4914,7 @@ var perplexityAdapter = {
|
|
|
4384
4914
|
};
|
|
4385
4915
|
const response = await client.search.create(
|
|
4386
4916
|
request,
|
|
4387
|
-
|
|
4917
|
+
buildRequestOptions4(context)
|
|
4388
4918
|
);
|
|
4389
4919
|
return {
|
|
4390
4920
|
provider: perplexityAdapter.id,
|
|
@@ -4404,7 +4934,7 @@ var perplexityAdapter = {
|
|
|
4404
4934
|
query2,
|
|
4405
4935
|
config,
|
|
4406
4936
|
context,
|
|
4407
|
-
|
|
4937
|
+
DEFAULT_ANSWER_MODEL3,
|
|
4408
4938
|
"Answer",
|
|
4409
4939
|
options
|
|
4410
4940
|
);
|
|
@@ -4414,14 +4944,14 @@ var perplexityAdapter = {
|
|
|
4414
4944
|
input,
|
|
4415
4945
|
config,
|
|
4416
4946
|
context,
|
|
4417
|
-
|
|
4947
|
+
DEFAULT_RESEARCH_MODEL2,
|
|
4418
4948
|
"Research",
|
|
4419
4949
|
options
|
|
4420
4950
|
);
|
|
4421
4951
|
}
|
|
4422
4952
|
};
|
|
4423
4953
|
async function runSilentForegroundChatTool(input, config, context, fallbackModel, label, options, isResearch = false) {
|
|
4424
|
-
const client =
|
|
4954
|
+
const client = createClient7(config);
|
|
4425
4955
|
const defaults = stripLocalExecutionOptions(
|
|
4426
4956
|
isResearch ? asJsonObject(config.options?.research) : asJsonObject(config.options?.answer)
|
|
4427
4957
|
) ?? {};
|
|
@@ -4434,7 +4964,7 @@ async function runSilentForegroundChatTool(input, config, context, fallbackModel
|
|
|
4434
4964
|
};
|
|
4435
4965
|
const response = await client.chat.completions.create(
|
|
4436
4966
|
request,
|
|
4437
|
-
|
|
4967
|
+
buildRequestOptions4(context)
|
|
4438
4968
|
);
|
|
4439
4969
|
const content = extractMessageText(response.choices[0]?.message?.content);
|
|
4440
4970
|
const sources = dedupeSources(extractSources(response));
|
|
@@ -4455,7 +4985,7 @@ async function runSilentForegroundChatTool(input, config, context, fallbackModel
|
|
|
4455
4985
|
};
|
|
4456
4986
|
}
|
|
4457
4987
|
async function runStreamingForegroundChatTool(input, config, context, fallbackModel, label, options) {
|
|
4458
|
-
const client =
|
|
4988
|
+
const client = createClient7(config);
|
|
4459
4989
|
const defaults = stripLocalExecutionOptions(asJsonObject(config.options?.research)) ?? {};
|
|
4460
4990
|
const request = {
|
|
4461
4991
|
...defaults,
|
|
@@ -4466,7 +4996,7 @@ async function runStreamingForegroundChatTool(input, config, context, fallbackMo
|
|
|
4466
4996
|
};
|
|
4467
4997
|
const stream = await client.chat.completions.create(
|
|
4468
4998
|
request,
|
|
4469
|
-
|
|
4999
|
+
buildRequestOptions4(context)
|
|
4470
5000
|
);
|
|
4471
5001
|
let partialText = "";
|
|
4472
5002
|
let lastChunk;
|
|
@@ -4496,7 +5026,7 @@ async function runStreamingForegroundChatTool(input, config, context, fallbackMo
|
|
|
4496
5026
|
itemCount: dedupedSources.length
|
|
4497
5027
|
};
|
|
4498
5028
|
}
|
|
4499
|
-
function
|
|
5029
|
+
function createClient7(config) {
|
|
4500
5030
|
const apiKey = resolveConfigValue(config.apiKey);
|
|
4501
5031
|
if (!apiKey) {
|
|
4502
5032
|
throw new Error("is missing an API key");
|
|
@@ -4573,60 +5103,60 @@ function extractSources(response) {
|
|
|
4573
5103
|
return url ? [{ title: url, url }] : [];
|
|
4574
5104
|
}) ?? [];
|
|
4575
5105
|
}
|
|
4576
|
-
function
|
|
5106
|
+
function buildRequestOptions4(context) {
|
|
4577
5107
|
return context.signal ? { signal: context.signal } : void 0;
|
|
4578
5108
|
}
|
|
4579
5109
|
|
|
4580
5110
|
// src/providers/tavily.ts
|
|
4581
|
-
import { Type as
|
|
5111
|
+
import { Type as Type13 } from "@sinclair/typebox";
|
|
4582
5112
|
import {
|
|
4583
5113
|
tavily
|
|
4584
5114
|
} from "@tavily/core";
|
|
4585
|
-
var tavilySearchOptionsSchema =
|
|
5115
|
+
var tavilySearchOptionsSchema = Type13.Object(
|
|
4586
5116
|
{
|
|
4587
|
-
topic:
|
|
5117
|
+
topic: Type13.Optional(
|
|
4588
5118
|
literalUnion(["general", "news", "finance"], {
|
|
4589
5119
|
description: "Category of the search query."
|
|
4590
5120
|
})
|
|
4591
5121
|
),
|
|
4592
|
-
searchDepth:
|
|
5122
|
+
searchDepth: Type13.Optional(
|
|
4593
5123
|
literalUnion(["basic", "advanced"], {
|
|
4594
5124
|
description: "Depth of the search. 'advanced' is slower but more thorough."
|
|
4595
5125
|
})
|
|
4596
5126
|
),
|
|
4597
|
-
timeRange:
|
|
4598
|
-
|
|
5127
|
+
timeRange: Type13.Optional(
|
|
5128
|
+
Type13.String({ description: "Named time range filter." })
|
|
4599
5129
|
),
|
|
4600
|
-
country:
|
|
4601
|
-
|
|
5130
|
+
country: Type13.Optional(
|
|
5131
|
+
Type13.String({ description: "Country hint for search results." })
|
|
4602
5132
|
),
|
|
4603
|
-
exactMatch:
|
|
4604
|
-
|
|
5133
|
+
exactMatch: Type13.Optional(
|
|
5134
|
+
Type13.Boolean({ description: "Prefer exact matches." })
|
|
4605
5135
|
),
|
|
4606
|
-
includeAnswer:
|
|
4607
|
-
|
|
5136
|
+
includeAnswer: Type13.Optional(
|
|
5137
|
+
Type13.Boolean({ description: "Include a short AI-generated answer." })
|
|
4608
5138
|
),
|
|
4609
|
-
includeRawContent:
|
|
4610
|
-
|
|
5139
|
+
includeRawContent: Type13.Optional(
|
|
5140
|
+
Type13.Boolean({ description: "Include raw page content in results." })
|
|
4611
5141
|
),
|
|
4612
|
-
includeImages:
|
|
4613
|
-
|
|
5142
|
+
includeImages: Type13.Optional(
|
|
5143
|
+
Type13.Boolean({ description: "Include related images." })
|
|
4614
5144
|
),
|
|
4615
|
-
includeFavicon:
|
|
4616
|
-
|
|
5145
|
+
includeFavicon: Type13.Optional(
|
|
5146
|
+
Type13.Boolean({ description: "Include favicon URLs." })
|
|
4617
5147
|
),
|
|
4618
|
-
includeDomains:
|
|
4619
|
-
|
|
5148
|
+
includeDomains: Type13.Optional(
|
|
5149
|
+
Type13.Array(Type13.String(), {
|
|
4620
5150
|
description: "Restrict results to these domains."
|
|
4621
5151
|
})
|
|
4622
5152
|
),
|
|
4623
|
-
excludeDomains:
|
|
4624
|
-
|
|
5153
|
+
excludeDomains: Type13.Optional(
|
|
5154
|
+
Type13.Array(Type13.String(), {
|
|
4625
5155
|
description: "Exclude these domains from results."
|
|
4626
5156
|
})
|
|
4627
5157
|
),
|
|
4628
|
-
days:
|
|
4629
|
-
|
|
5158
|
+
days: Type13.Optional(
|
|
5159
|
+
Type13.Integer({
|
|
4630
5160
|
minimum: 1,
|
|
4631
5161
|
description: "Limit results to the last N days."
|
|
4632
5162
|
})
|
|
@@ -4634,27 +5164,27 @@ var tavilySearchOptionsSchema = Type12.Object(
|
|
|
4634
5164
|
},
|
|
4635
5165
|
{ description: "Tavily search options." }
|
|
4636
5166
|
);
|
|
4637
|
-
var tavilyExtractOptionsSchema =
|
|
5167
|
+
var tavilyExtractOptionsSchema = Type13.Object(
|
|
4638
5168
|
{
|
|
4639
|
-
extractDepth:
|
|
4640
|
-
|
|
5169
|
+
extractDepth: Type13.Optional(
|
|
5170
|
+
Type13.String({ description: "Depth setting for extraction." })
|
|
4641
5171
|
),
|
|
4642
|
-
format:
|
|
5172
|
+
format: Type13.Optional(
|
|
4643
5173
|
literalUnion(["markdown", "text"], {
|
|
4644
5174
|
description: "Output format for extracted content."
|
|
4645
5175
|
})
|
|
4646
5176
|
),
|
|
4647
|
-
includeImages:
|
|
4648
|
-
|
|
5177
|
+
includeImages: Type13.Optional(
|
|
5178
|
+
Type13.Boolean({ description: "Include extracted images." })
|
|
4649
5179
|
),
|
|
4650
|
-
query:
|
|
4651
|
-
|
|
5180
|
+
query: Type13.Optional(
|
|
5181
|
+
Type13.String({ description: "Optional query to focus extraction." })
|
|
4652
5182
|
),
|
|
4653
|
-
chunksPerSource:
|
|
4654
|
-
|
|
5183
|
+
chunksPerSource: Type13.Optional(
|
|
5184
|
+
Type13.Integer({ minimum: 1, description: "Maximum chunks per source." })
|
|
4655
5185
|
),
|
|
4656
|
-
includeFavicon:
|
|
4657
|
-
|
|
5186
|
+
includeFavicon: Type13.Optional(
|
|
5187
|
+
Type13.Boolean({ description: "Include favicon URLs." })
|
|
4658
5188
|
)
|
|
4659
5189
|
},
|
|
4660
5190
|
{ description: "Tavily extract options." }
|
|
@@ -4739,7 +5269,7 @@ var tavilyAdapter = {
|
|
|
4739
5269
|
});
|
|
4740
5270
|
},
|
|
4741
5271
|
async search(query2, maxResults, config, _context, options) {
|
|
4742
|
-
const client =
|
|
5272
|
+
const client = createClient8(config);
|
|
4743
5273
|
const defaults = stripLocalExecutionOptions(asJsonObject(config.options?.search)) ?? {};
|
|
4744
5274
|
const response = await client.search(query2, {
|
|
4745
5275
|
...defaults,
|
|
@@ -4758,7 +5288,7 @@ var tavilyAdapter = {
|
|
|
4758
5288
|
};
|
|
4759
5289
|
},
|
|
4760
5290
|
async contents(urls, config, _context, options) {
|
|
4761
|
-
const client =
|
|
5291
|
+
const client = createClient8(config);
|
|
4762
5292
|
const defaults = stripLocalExecutionOptions(asJsonObject(config.options?.extract)) ?? {};
|
|
4763
5293
|
const response = await client.extract(urls, {
|
|
4764
5294
|
...defaults,
|
|
@@ -4796,7 +5326,7 @@ var tavilyAdapter = {
|
|
|
4796
5326
|
};
|
|
4797
5327
|
}
|
|
4798
5328
|
};
|
|
4799
|
-
function
|
|
5329
|
+
function createClient8(config) {
|
|
4800
5330
|
const apiKey = resolveConfigValue(config.apiKey);
|
|
4801
5331
|
if (!apiKey) {
|
|
4802
5332
|
throw new Error("is missing an API key");
|
|
@@ -4828,48 +5358,48 @@ function buildExtractMetadata(response, result) {
|
|
|
4828
5358
|
}
|
|
4829
5359
|
|
|
4830
5360
|
// src/providers/valyu.ts
|
|
4831
|
-
import { Type as
|
|
5361
|
+
import { Type as Type14 } from "@sinclair/typebox";
|
|
4832
5362
|
import { Valyu as ValyuClient } from "valyu-js";
|
|
4833
|
-
var valyuSearchOptionsSchema =
|
|
5363
|
+
var valyuSearchOptionsSchema = Type14.Object(
|
|
4834
5364
|
{
|
|
4835
|
-
searchType:
|
|
5365
|
+
searchType: Type14.Optional(
|
|
4836
5366
|
literalUnion(["all", "web", "proprietary", "news"], {
|
|
4837
5367
|
description: "Valyu search type."
|
|
4838
5368
|
})
|
|
4839
5369
|
),
|
|
4840
|
-
responseLength:
|
|
5370
|
+
responseLength: Type14.Optional(
|
|
4841
5371
|
literalUnion(["short", "medium", "large", "max"], {
|
|
4842
5372
|
description: "Response length."
|
|
4843
5373
|
})
|
|
4844
5374
|
),
|
|
4845
|
-
countryCode:
|
|
4846
|
-
|
|
5375
|
+
countryCode: Type14.Optional(
|
|
5376
|
+
Type14.String({ description: "Country code to scope search results." })
|
|
4847
5377
|
)
|
|
4848
5378
|
},
|
|
4849
5379
|
{ description: "Valyu search options." }
|
|
4850
5380
|
);
|
|
4851
|
-
var valyuAnswerOptionsSchema =
|
|
5381
|
+
var valyuAnswerOptionsSchema = Type14.Object(
|
|
4852
5382
|
{
|
|
4853
|
-
responseLength:
|
|
5383
|
+
responseLength: Type14.Optional(
|
|
4854
5384
|
literalUnion(["short", "medium", "large", "max"], {
|
|
4855
5385
|
description: "Response length for answers."
|
|
4856
5386
|
})
|
|
4857
5387
|
),
|
|
4858
|
-
countryCode:
|
|
4859
|
-
|
|
5388
|
+
countryCode: Type14.Optional(
|
|
5389
|
+
Type14.String({ description: "Country code to scope answer results." })
|
|
4860
5390
|
)
|
|
4861
5391
|
},
|
|
4862
5392
|
{ description: "Valyu answer options." }
|
|
4863
5393
|
);
|
|
4864
|
-
var valyuResearchOptionsSchema =
|
|
5394
|
+
var valyuResearchOptionsSchema = Type14.Object(
|
|
4865
5395
|
{
|
|
4866
|
-
responseLength:
|
|
5396
|
+
responseLength: Type14.Optional(
|
|
4867
5397
|
literalUnion(["short", "medium", "large", "max"], {
|
|
4868
5398
|
description: "Response length for research."
|
|
4869
5399
|
})
|
|
4870
5400
|
),
|
|
4871
|
-
countryCode:
|
|
4872
|
-
|
|
5401
|
+
countryCode: Type14.Optional(
|
|
5402
|
+
Type14.String({ description: "Country code to scope research results." })
|
|
4873
5403
|
)
|
|
4874
5404
|
},
|
|
4875
5405
|
{ description: "Valyu research options." }
|
|
@@ -4982,7 +5512,7 @@ var valyuAdapter = {
|
|
|
4982
5512
|
});
|
|
4983
5513
|
},
|
|
4984
5514
|
async search(query2, maxResults, config, _context, searchOptions) {
|
|
4985
|
-
const client =
|
|
5515
|
+
const client = createClient9(config);
|
|
4986
5516
|
const options = {
|
|
4987
5517
|
...stripLocalExecutionOptions(asJsonObject(config.options?.search)) ?? {},
|
|
4988
5518
|
...searchOptions ?? {},
|
|
@@ -5005,7 +5535,7 @@ var valyuAdapter = {
|
|
|
5005
5535
|
};
|
|
5006
5536
|
},
|
|
5007
5537
|
async contents(urls, config, _context, options) {
|
|
5008
|
-
const client =
|
|
5538
|
+
const client = createClient9(config);
|
|
5009
5539
|
const response = await client.contents(urls, options);
|
|
5010
5540
|
const finalResponse = "jobId" in response ? await client.waitForJob(response.jobId, {}) : response;
|
|
5011
5541
|
if (!finalResponse.success) {
|
|
@@ -5039,7 +5569,7 @@ var valyuAdapter = {
|
|
|
5039
5569
|
};
|
|
5040
5570
|
},
|
|
5041
5571
|
async answer(query2, config, _context, options) {
|
|
5042
|
-
const client =
|
|
5572
|
+
const client = createClient9(config);
|
|
5043
5573
|
const response = await client.answer(query2, {
|
|
5044
5574
|
...stripLocalExecutionOptions(asJsonObject(config.options?.answer)) ?? {},
|
|
5045
5575
|
...options ?? {},
|
|
@@ -5078,7 +5608,7 @@ var valyuAdapter = {
|
|
|
5078
5608
|
});
|
|
5079
5609
|
},
|
|
5080
5610
|
async startResearch(input, config, _context, options) {
|
|
5081
|
-
const client =
|
|
5611
|
+
const client = createClient9(config);
|
|
5082
5612
|
const task = await client.deepresearch.create({
|
|
5083
5613
|
input,
|
|
5084
5614
|
...stripLocalExecutionOptions(asJsonObject(config.options?.research)) ?? {},
|
|
@@ -5090,7 +5620,7 @@ var valyuAdapter = {
|
|
|
5090
5620
|
return { id: task.deepresearch_id };
|
|
5091
5621
|
},
|
|
5092
5622
|
async pollResearch(id, config, _context, _options) {
|
|
5093
|
-
const client =
|
|
5623
|
+
const client = createClient9(config);
|
|
5094
5624
|
const result = await client.deepresearch.status(id);
|
|
5095
5625
|
if (!result.success) {
|
|
5096
5626
|
throw new Error(result.error || "deep research failed");
|
|
@@ -5133,7 +5663,7 @@ var valyuAdapter = {
|
|
|
5133
5663
|
return { status: "in_progress" };
|
|
5134
5664
|
}
|
|
5135
5665
|
};
|
|
5136
|
-
function
|
|
5666
|
+
function createClient9(config) {
|
|
5137
5667
|
const apiKey = resolveConfigValue(config.apiKey);
|
|
5138
5668
|
if (!apiKey) {
|
|
5139
5669
|
throw new Error("is missing an API key");
|
|
@@ -5144,15 +5674,16 @@ function createClient8(config) {
|
|
|
5144
5674
|
// src/providers/index.ts
|
|
5145
5675
|
var ADAPTERS_BY_ID = {
|
|
5146
5676
|
claude: claudeAdapter,
|
|
5147
|
-
cloudflare: cloudflareAdapter,
|
|
5148
5677
|
codex: codexAdapter,
|
|
5678
|
+
cloudflare: cloudflareAdapter,
|
|
5149
5679
|
custom: customAdapter,
|
|
5150
5680
|
exa: exaAdapter,
|
|
5151
5681
|
firecrawl: firecrawlAdapter,
|
|
5152
5682
|
gemini: geminiAdapter,
|
|
5153
5683
|
linkup: linkupAdapter,
|
|
5154
|
-
|
|
5684
|
+
openai: openaiAdapter,
|
|
5155
5685
|
parallel: parallelAdapter,
|
|
5686
|
+
perplexity: perplexityAdapter,
|
|
5156
5687
|
tavily: tavilyAdapter,
|
|
5157
5688
|
valyu: valyuAdapter
|
|
5158
5689
|
};
|
|
@@ -6226,8 +6757,7 @@ var PROVIDER_CONFIG_MANIFESTS = {
|
|
|
6226
6757
|
setValue: (config, value) => {
|
|
6227
6758
|
setCustomEnv(config, "research", value);
|
|
6228
6759
|
}
|
|
6229
|
-
})
|
|
6230
|
-
...requestSettings("custom")
|
|
6760
|
+
})
|
|
6231
6761
|
]
|
|
6232
6762
|
},
|
|
6233
6763
|
exa: {
|
|
@@ -6355,10 +6885,111 @@ var PROVIDER_CONFIG_MANIFESTS = {
|
|
|
6355
6885
|
]
|
|
6356
6886
|
},
|
|
6357
6887
|
linkup: {
|
|
6888
|
+
settings: [apiKeySetting(), baseUrlSetting()]
|
|
6889
|
+
},
|
|
6890
|
+
openai: {
|
|
6358
6891
|
settings: [
|
|
6359
6892
|
apiKeySetting(),
|
|
6360
6893
|
baseUrlSetting(),
|
|
6361
|
-
|
|
6894
|
+
stringSetting({
|
|
6895
|
+
id: "openaiSearchModel",
|
|
6896
|
+
label: "Search model",
|
|
6897
|
+
help: "Model used for OpenAI web search runs.",
|
|
6898
|
+
getValue: (config) => getOpenAISearchOptions(config)?.model,
|
|
6899
|
+
setValue: (config, value) => {
|
|
6900
|
+
assignOptionalString(
|
|
6901
|
+
ensureOpenAISearchOptions(config),
|
|
6902
|
+
"model",
|
|
6903
|
+
value
|
|
6904
|
+
);
|
|
6905
|
+
cleanupCapabilityOptions(config, ["search", "answer", "research"]);
|
|
6906
|
+
}
|
|
6907
|
+
}),
|
|
6908
|
+
stringSetting({
|
|
6909
|
+
id: "openaiSearchInstructions",
|
|
6910
|
+
label: "Search instructions",
|
|
6911
|
+
help: "Optional default instructions for OpenAI web search runs.",
|
|
6912
|
+
getValue: (config) => getOpenAISearchOptions(config)?.instructions,
|
|
6913
|
+
setValue: (config, value) => {
|
|
6914
|
+
assignOptionalString(
|
|
6915
|
+
ensureOpenAISearchOptions(config),
|
|
6916
|
+
"instructions",
|
|
6917
|
+
value
|
|
6918
|
+
);
|
|
6919
|
+
cleanupCapabilityOptions(config, ["search", "answer", "research"]);
|
|
6920
|
+
}
|
|
6921
|
+
}),
|
|
6922
|
+
stringSetting({
|
|
6923
|
+
id: "openaiAnswerModel",
|
|
6924
|
+
label: "Answer model",
|
|
6925
|
+
help: "Model used for OpenAI grounded answers.",
|
|
6926
|
+
getValue: (config) => getOpenAIAnswerOptions(config)?.model,
|
|
6927
|
+
setValue: (config, value) => {
|
|
6928
|
+
assignOptionalString(
|
|
6929
|
+
ensureOpenAIAnswerOptions(config),
|
|
6930
|
+
"model",
|
|
6931
|
+
value
|
|
6932
|
+
);
|
|
6933
|
+
cleanupCapabilityOptions(config, ["search", "answer", "research"]);
|
|
6934
|
+
}
|
|
6935
|
+
}),
|
|
6936
|
+
stringSetting({
|
|
6937
|
+
id: "openaiAnswerInstructions",
|
|
6938
|
+
label: "Answer instructions",
|
|
6939
|
+
help: "Optional default instructions for OpenAI grounded answers.",
|
|
6940
|
+
getValue: (config) => getOpenAIAnswerOptions(config)?.instructions,
|
|
6941
|
+
setValue: (config, value) => {
|
|
6942
|
+
assignOptionalString(
|
|
6943
|
+
ensureOpenAIAnswerOptions(config),
|
|
6944
|
+
"instructions",
|
|
6945
|
+
value
|
|
6946
|
+
);
|
|
6947
|
+
cleanupCapabilityOptions(config, ["search", "answer", "research"]);
|
|
6948
|
+
}
|
|
6949
|
+
}),
|
|
6950
|
+
stringSetting({
|
|
6951
|
+
id: "openaiResearchModel",
|
|
6952
|
+
label: "Research model",
|
|
6953
|
+
help: "Model used for OpenAI deep research runs.",
|
|
6954
|
+
getValue: (config) => getOpenAIResearchOptions(config)?.model,
|
|
6955
|
+
setValue: (config, value) => {
|
|
6956
|
+
assignOptionalString(
|
|
6957
|
+
ensureOpenAIResearchOptions(config),
|
|
6958
|
+
"model",
|
|
6959
|
+
value
|
|
6960
|
+
);
|
|
6961
|
+
cleanupCapabilityOptions(config, ["search", "answer", "research"]);
|
|
6962
|
+
}
|
|
6963
|
+
}),
|
|
6964
|
+
stringSetting({
|
|
6965
|
+
id: "openaiResearchInstructions",
|
|
6966
|
+
label: "Research instructions",
|
|
6967
|
+
help: "Optional default instructions for OpenAI deep research runs.",
|
|
6968
|
+
getValue: (config) => getOpenAIResearchOptions(config)?.instructions,
|
|
6969
|
+
setValue: (config, value) => {
|
|
6970
|
+
assignOptionalString(
|
|
6971
|
+
ensureOpenAIResearchOptions(config),
|
|
6972
|
+
"instructions",
|
|
6973
|
+
value
|
|
6974
|
+
);
|
|
6975
|
+
cleanupCapabilityOptions(config, ["search", "answer", "research"]);
|
|
6976
|
+
}
|
|
6977
|
+
}),
|
|
6978
|
+
stringSetting({
|
|
6979
|
+
id: "openaiResearchMaxToolCalls",
|
|
6980
|
+
label: "Research max tool calls",
|
|
6981
|
+
help: "Optional default maximum number of built-in tool calls for OpenAI deep research runs.",
|
|
6982
|
+
getValue: (config) => getIntegerString(getOpenAIResearchOptions(config)?.max_tool_calls),
|
|
6983
|
+
setValue: (config, value) => {
|
|
6984
|
+
assignOptionalInteger(
|
|
6985
|
+
ensureOpenAIResearchOptions(config),
|
|
6986
|
+
"max_tool_calls",
|
|
6987
|
+
value,
|
|
6988
|
+
"OpenAI research max tool calls must be a positive integer."
|
|
6989
|
+
);
|
|
6990
|
+
cleanupCapabilityOptions(config, ["search", "answer", "research"]);
|
|
6991
|
+
}
|
|
6992
|
+
})
|
|
6362
6993
|
]
|
|
6363
6994
|
},
|
|
6364
6995
|
perplexity: {
|
|
@@ -6428,11 +7059,7 @@ var PROVIDER_CONFIG_MANIFESTS = {
|
|
|
6428
7059
|
]
|
|
6429
7060
|
},
|
|
6430
7061
|
tavily: {
|
|
6431
|
-
settings: [
|
|
6432
|
-
apiKeySetting(),
|
|
6433
|
-
baseUrlSetting(),
|
|
6434
|
-
...requestSettings("tavily")
|
|
6435
|
-
]
|
|
7062
|
+
settings: [apiKeySetting(), baseUrlSetting()]
|
|
6436
7063
|
},
|
|
6437
7064
|
valyu: {
|
|
6438
7065
|
settings: [
|
|
@@ -6539,88 +7166,20 @@ function baseUrlSetting() {
|
|
|
6539
7166
|
}
|
|
6540
7167
|
});
|
|
6541
7168
|
}
|
|
6542
|
-
function requestSettings(providerId) {
|
|
6543
|
-
const settings = [
|
|
6544
|
-
stringSetting({
|
|
6545
|
-
id: "requestTimeoutMs",
|
|
6546
|
-
label: "Request timeout (ms)",
|
|
6547
|
-
help: "Maximum time to wait for each command before failing that attempt for this provider. Leave empty to inherit the shared setting.",
|
|
6548
|
-
getValue: (config) => getIntegerString(config?.settings?.requestTimeoutMs),
|
|
6549
|
-
setValue: (config, value) => {
|
|
6550
|
-
assignOptionalInteger(
|
|
6551
|
-
ensureSettings(config),
|
|
6552
|
-
"requestTimeoutMs",
|
|
6553
|
-
value,
|
|
6554
|
-
"Request timeout must be a positive integer."
|
|
6555
|
-
);
|
|
6556
|
-
cleanupEmpty(config, "settings");
|
|
6557
|
-
}
|
|
6558
|
-
}),
|
|
6559
|
-
stringSetting({
|
|
6560
|
-
id: "retryCount",
|
|
6561
|
-
label: "Retry count",
|
|
6562
|
-
help: "How many times to retry transient command failures for this provider. Leave empty to inherit the shared setting.",
|
|
6563
|
-
getValue: (config) => getIntegerString(config?.settings?.retryCount),
|
|
6564
|
-
setValue: (config, value) => {
|
|
6565
|
-
assignOptionalInteger(
|
|
6566
|
-
ensureSettings(config),
|
|
6567
|
-
"retryCount",
|
|
6568
|
-
value,
|
|
6569
|
-
"Retry count must be a non-negative integer.",
|
|
6570
|
-
{ allowZero: true }
|
|
6571
|
-
);
|
|
6572
|
-
cleanupEmpty(config, "settings");
|
|
6573
|
-
}
|
|
6574
|
-
}),
|
|
6575
|
-
stringSetting({
|
|
6576
|
-
id: "retryDelayMs",
|
|
6577
|
-
label: "Retry delay (ms)",
|
|
6578
|
-
help: "Initial delay before retrying command failures for this provider. Leave empty to inherit the shared setting.",
|
|
6579
|
-
getValue: (config) => getIntegerString(config?.settings?.retryDelayMs),
|
|
6580
|
-
setValue: (config, value) => {
|
|
6581
|
-
assignOptionalInteger(
|
|
6582
|
-
ensureSettings(config),
|
|
6583
|
-
"retryDelayMs",
|
|
6584
|
-
value,
|
|
6585
|
-
"Retry delay must be a positive integer."
|
|
6586
|
-
);
|
|
6587
|
-
cleanupEmpty(config, "settings");
|
|
6588
|
-
}
|
|
6589
|
-
})
|
|
6590
|
-
];
|
|
6591
|
-
if (supportsTool(providerId, "research")) {
|
|
6592
|
-
settings.push(
|
|
6593
|
-
stringSetting({
|
|
6594
|
-
id: "researchTimeoutMs",
|
|
6595
|
-
label: "Research timeout (ms)",
|
|
6596
|
-
help: "Maximum total time to allow long-running web research for this provider before aborting it. Leave empty to inherit the shared setting.",
|
|
6597
|
-
getValue: (config) => getIntegerString(config?.settings?.researchTimeoutMs),
|
|
6598
|
-
setValue: (config, value) => {
|
|
6599
|
-
assignOptionalInteger(
|
|
6600
|
-
ensureSettings(config),
|
|
6601
|
-
"researchTimeoutMs",
|
|
6602
|
-
value,
|
|
6603
|
-
"Research timeout must be a positive integer."
|
|
6604
|
-
);
|
|
6605
|
-
cleanupEmpty(config, "settings");
|
|
6606
|
-
}
|
|
6607
|
-
})
|
|
6608
|
-
);
|
|
6609
|
-
}
|
|
6610
|
-
return settings;
|
|
6611
|
-
}
|
|
6612
7169
|
function assignOptionalString(target, key, value) {
|
|
7170
|
+
const record = target;
|
|
6613
7171
|
const trimmed = value.trim();
|
|
6614
7172
|
if (!trimmed) {
|
|
6615
|
-
delete
|
|
7173
|
+
delete record[key];
|
|
6616
7174
|
} else {
|
|
6617
|
-
|
|
7175
|
+
record[key] = trimmed;
|
|
6618
7176
|
}
|
|
6619
7177
|
}
|
|
6620
7178
|
function assignOptionalInteger(target, key, value, errorMessage, options) {
|
|
7179
|
+
const record = target;
|
|
6621
7180
|
const trimmed = value.trim();
|
|
6622
7181
|
if (!trimmed) {
|
|
6623
|
-
delete
|
|
7182
|
+
delete record[key];
|
|
6624
7183
|
return;
|
|
6625
7184
|
}
|
|
6626
7185
|
const parsed = Number(trimmed);
|
|
@@ -6628,7 +7187,7 @@ function assignOptionalInteger(target, key, value, errorMessage, options) {
|
|
|
6628
7187
|
if (!Number.isInteger(parsed) || parsed < minimum) {
|
|
6629
7188
|
throw new Error(errorMessage);
|
|
6630
7189
|
}
|
|
6631
|
-
|
|
7190
|
+
record[key] = parsed;
|
|
6632
7191
|
}
|
|
6633
7192
|
function assignOptionalBoolean(target, key, value) {
|
|
6634
7193
|
if (value === "default") {
|
|
@@ -6649,10 +7208,6 @@ function readString4(value) {
|
|
|
6649
7208
|
function asJsonObject2(value) {
|
|
6650
7209
|
return typeof value === "object" && value !== null && !Array.isArray(value) ? value : void 0;
|
|
6651
7210
|
}
|
|
6652
|
-
function ensureSettings(config) {
|
|
6653
|
-
config.settings = { ...config.settings ?? {} };
|
|
6654
|
-
return config.settings;
|
|
6655
|
-
}
|
|
6656
7211
|
function cleanupEmpty(config, key) {
|
|
6657
7212
|
const value = asJsonObject2(config[key]);
|
|
6658
7213
|
if (value && Object.keys(value).length === 0) {
|
|
@@ -6817,6 +7372,36 @@ function ensureExaSearchOptions(config) {
|
|
|
6817
7372
|
};
|
|
6818
7373
|
return config.options.search;
|
|
6819
7374
|
}
|
|
7375
|
+
function getOpenAISearchOptions(config) {
|
|
7376
|
+
return config?.options?.search;
|
|
7377
|
+
}
|
|
7378
|
+
function ensureOpenAISearchOptions(config) {
|
|
7379
|
+
config.options = {
|
|
7380
|
+
...config.options ?? {},
|
|
7381
|
+
search: { ...config.options?.search ?? {} }
|
|
7382
|
+
};
|
|
7383
|
+
return config.options.search ?? (config.options.search = {});
|
|
7384
|
+
}
|
|
7385
|
+
function getOpenAIAnswerOptions(config) {
|
|
7386
|
+
return config?.options?.answer;
|
|
7387
|
+
}
|
|
7388
|
+
function ensureOpenAIAnswerOptions(config) {
|
|
7389
|
+
config.options = {
|
|
7390
|
+
...config.options ?? {},
|
|
7391
|
+
answer: { ...config.options?.answer ?? {} }
|
|
7392
|
+
};
|
|
7393
|
+
return config.options.answer ?? (config.options.answer = {});
|
|
7394
|
+
}
|
|
7395
|
+
function getOpenAIResearchOptions(config) {
|
|
7396
|
+
return config?.options?.research;
|
|
7397
|
+
}
|
|
7398
|
+
function ensureOpenAIResearchOptions(config) {
|
|
7399
|
+
config.options = {
|
|
7400
|
+
...config.options ?? {},
|
|
7401
|
+
research: { ...config.options?.research ?? {} }
|
|
7402
|
+
};
|
|
7403
|
+
return config.options.research ?? (config.options.research = {});
|
|
7404
|
+
}
|
|
6820
7405
|
function getValyuCapabilityOptions(config, capability) {
|
|
6821
7406
|
return config?.options?.[capability];
|
|
6822
7407
|
}
|
|
@@ -6992,14 +7577,14 @@ function registerWebSearchTool(pi, providerIds) {
|
|
|
6992
7577
|
promptGuidelines: [
|
|
6993
7578
|
"Batch related searches when grouped comparison matters; use separate sibling web_search calls when independent results should surface as soon as they are ready."
|
|
6994
7579
|
],
|
|
6995
|
-
parameters:
|
|
6996
|
-
queries:
|
|
7580
|
+
parameters: Type15.Object({
|
|
7581
|
+
queries: Type15.Array(Type15.String({ minLength: 1 }), {
|
|
6997
7582
|
minItems: 1,
|
|
6998
7583
|
maxItems: MAX_SEARCH_QUERIES,
|
|
6999
7584
|
description: `One or more search queries to run in one call (max ${MAX_SEARCH_QUERIES})`
|
|
7000
7585
|
}),
|
|
7001
|
-
maxResults:
|
|
7002
|
-
|
|
7586
|
+
maxResults: Type15.Optional(
|
|
7587
|
+
Type15.Integer({
|
|
7003
7588
|
minimum: 1,
|
|
7004
7589
|
maximum: MAX_ALLOWED_RESULTS,
|
|
7005
7590
|
description: `Maximum number of results to return (default: ${DEFAULT_MAX_RESULTS})`
|
|
@@ -7048,8 +7633,8 @@ function registerWebContentsTool(pi, providerIds) {
|
|
|
7048
7633
|
name: "web_contents",
|
|
7049
7634
|
label: "Web Contents",
|
|
7050
7635
|
description: "Read and extract the main contents of one or more web pages. Batch related pages together, or use separate sibling calls when each page can be acted on independently.",
|
|
7051
|
-
parameters:
|
|
7052
|
-
urls:
|
|
7636
|
+
parameters: Type15.Object({
|
|
7637
|
+
urls: Type15.Array(Type15.String({ minLength: 1 }), {
|
|
7053
7638
|
minItems: 1,
|
|
7054
7639
|
description: "One or more URLs to extract"
|
|
7055
7640
|
}),
|
|
@@ -7099,8 +7684,8 @@ function registerWebAnswerTool(pi, providerIds) {
|
|
|
7099
7684
|
name: "web_answer",
|
|
7100
7685
|
label: "Web Answer",
|
|
7101
7686
|
description: `Answer one or more questions using web-grounded evidence (up to ${MAX_SEARCH_QUERIES} per call).`,
|
|
7102
|
-
parameters:
|
|
7103
|
-
queries:
|
|
7687
|
+
parameters: Type15.Object({
|
|
7688
|
+
queries: Type15.Array(Type15.String({ minLength: 1 }), {
|
|
7104
7689
|
minItems: 1,
|
|
7105
7690
|
maxItems: MAX_SEARCH_QUERIES,
|
|
7106
7691
|
description: `One or more questions to answer in one call (max ${MAX_SEARCH_QUERIES})`
|
|
@@ -7154,8 +7739,8 @@ function registerWebResearchTool(pi, webResearchLifecycle, providerIds) {
|
|
|
7154
7739
|
name: "web_research",
|
|
7155
7740
|
label: "Web Research",
|
|
7156
7741
|
description: "Start a long-running web research job. Returns immediately with a dispatch notice; the final report is saved to a file and posted later as a custom message.",
|
|
7157
|
-
parameters:
|
|
7158
|
-
input:
|
|
7742
|
+
parameters: Type15.Object({
|
|
7743
|
+
input: Type15.String({ description: "Research brief or question" }),
|
|
7159
7744
|
...optionalField(
|
|
7160
7745
|
"options",
|
|
7161
7746
|
buildStructuredOptionsSchema("research", selectedProviderId)
|
|
@@ -7298,7 +7883,7 @@ function optionalField(name, schema) {
|
|
|
7298
7883
|
function buildStructuredOptionsSchema(capability, providerId) {
|
|
7299
7884
|
const providerSchema = resolveProviderOptionsSchema(capability, providerId);
|
|
7300
7885
|
const schema = buildToolOptionsSchema(capability, providerSchema);
|
|
7301
|
-
return schema ?
|
|
7886
|
+
return schema ? Type15.Optional(schema) : void 0;
|
|
7302
7887
|
}
|
|
7303
7888
|
function resolveProviderOptionsSchema(capability, providerId) {
|
|
7304
7889
|
if (!providerId) {
|
|
@@ -8606,7 +9191,7 @@ function getSharedSettingRawValue(config, id) {
|
|
|
8606
9191
|
const value = config.settings?.[id];
|
|
8607
9192
|
return typeof value === "number" ? String(value) : "";
|
|
8608
9193
|
}
|
|
8609
|
-
function
|
|
9194
|
+
function ensureSettings(config) {
|
|
8610
9195
|
config.settings = { ...config.settings ?? {} };
|
|
8611
9196
|
return config.settings;
|
|
8612
9197
|
}
|
|
@@ -8951,7 +9536,7 @@ var WebProvidersSettingsView = class {
|
|
|
8951
9536
|
async handleSharedSettingChange(id, value) {
|
|
8952
9537
|
await this.persist((config) => {
|
|
8953
9538
|
const parsed = SETTING_META[id].parse(value);
|
|
8954
|
-
const settings =
|
|
9539
|
+
const settings = ensureSettings(config);
|
|
8955
9540
|
if (parsed === void 0) {
|
|
8956
9541
|
delete settings[id];
|
|
8957
9542
|
} else {
|