pi-web-providers 2.2.0 → 2.4.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 +109 -10
- package/dist/index.js +1263 -418
- package/package.json +6 -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 Type16 } from "@sinclair/typebox";
|
|
27
27
|
|
|
28
28
|
// src/config.ts
|
|
29
29
|
import { execSync } from "node:child_process";
|
|
@@ -41,8 +41,10 @@ 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"],
|
|
47
|
+
serper: ["search"],
|
|
46
48
|
tavily: ["search", "contents"],
|
|
47
49
|
valyu: ["search", "contents", "answer", "research"]
|
|
48
50
|
};
|
|
@@ -86,8 +88,10 @@ var PROVIDER_IDS = [
|
|
|
86
88
|
"firecrawl",
|
|
87
89
|
"gemini",
|
|
88
90
|
"linkup",
|
|
89
|
-
"
|
|
91
|
+
"openai",
|
|
90
92
|
"parallel",
|
|
93
|
+
"perplexity",
|
|
94
|
+
"serper",
|
|
91
95
|
"tavily",
|
|
92
96
|
"valyu"
|
|
93
97
|
];
|
|
@@ -271,10 +275,45 @@ function normalizeProvider(providerId, raw, source) {
|
|
|
271
275
|
options: readOptionalObject,
|
|
272
276
|
settings: parseOptionalExecutionSettings
|
|
273
277
|
});
|
|
278
|
+
case "openai":
|
|
279
|
+
return parseProviderWithShape(raw, source, providerId, {
|
|
280
|
+
apiKey: readOptionalString,
|
|
281
|
+
baseUrl: readOptionalString,
|
|
282
|
+
options: (value, innerSource, field) => parseOptionalCapabilityOptions(
|
|
283
|
+
value,
|
|
284
|
+
innerSource,
|
|
285
|
+
field,
|
|
286
|
+
["search", "answer", "research"]
|
|
287
|
+
),
|
|
288
|
+
settings: parseOptionalExecutionSettings
|
|
289
|
+
});
|
|
274
290
|
case "firecrawl":
|
|
275
291
|
case "linkup":
|
|
276
292
|
case "parallel":
|
|
277
293
|
case "perplexity":
|
|
294
|
+
return parseProviderWithShape(
|
|
295
|
+
raw,
|
|
296
|
+
source,
|
|
297
|
+
providerId,
|
|
298
|
+
{
|
|
299
|
+
apiKey: readOptionalString,
|
|
300
|
+
baseUrl: readOptionalString,
|
|
301
|
+
options: readOptionalObject,
|
|
302
|
+
settings: parseOptionalExecutionSettings
|
|
303
|
+
}
|
|
304
|
+
);
|
|
305
|
+
case "serper":
|
|
306
|
+
return parseProviderWithShape(raw, source, providerId, {
|
|
307
|
+
apiKey: readOptionalString,
|
|
308
|
+
baseUrl: readOptionalString,
|
|
309
|
+
options: (value, innerSource, field) => parseOptionalCapabilityOptions(
|
|
310
|
+
value,
|
|
311
|
+
innerSource,
|
|
312
|
+
field,
|
|
313
|
+
["search"]
|
|
314
|
+
),
|
|
315
|
+
settings: parseOptionalExecutionSettings
|
|
316
|
+
});
|
|
278
317
|
case "tavily":
|
|
279
318
|
return parseProviderWithShape(raw, source, providerId, {
|
|
280
319
|
apiKey: readOptionalString,
|
|
@@ -4082,57 +4121,112 @@ function toDate(value, name) {
|
|
|
4082
4121
|
return date;
|
|
4083
4122
|
}
|
|
4084
4123
|
|
|
4085
|
-
// src/providers/
|
|
4124
|
+
// src/providers/openai.ts
|
|
4086
4125
|
import { Type as Type10 } from "@sinclair/typebox";
|
|
4087
|
-
import
|
|
4088
|
-
var
|
|
4126
|
+
import OpenAI from "openai";
|
|
4127
|
+
var DEFAULT_SEARCH_MODEL2 = "gpt-4.1";
|
|
4128
|
+
var DEFAULT_ANSWER_MODEL2 = "gpt-4.1";
|
|
4129
|
+
var DEFAULT_RESEARCH_MODEL = "o4-mini-deep-research";
|
|
4130
|
+
var openaiSearchOptionsSchema = Type10.Object(
|
|
4089
4131
|
{
|
|
4090
|
-
|
|
4091
|
-
|
|
4092
|
-
description: "
|
|
4132
|
+
model: Type10.Optional(
|
|
4133
|
+
Type10.String({
|
|
4134
|
+
description: "OpenAI model to use for web search (for example 'gpt-4.1')."
|
|
4135
|
+
})
|
|
4136
|
+
),
|
|
4137
|
+
instructions: Type10.Optional(
|
|
4138
|
+
Type10.String({
|
|
4139
|
+
description: "Optional instructions that shape source selection and result style."
|
|
4093
4140
|
})
|
|
4094
4141
|
)
|
|
4095
4142
|
},
|
|
4096
|
-
{ description: "
|
|
4143
|
+
{ description: "OpenAI search options." }
|
|
4097
4144
|
);
|
|
4098
|
-
var
|
|
4145
|
+
var openaiAnswerOptionsSchema = Type10.Object(
|
|
4099
4146
|
{
|
|
4100
|
-
|
|
4101
|
-
Type10.
|
|
4147
|
+
model: Type10.Optional(
|
|
4148
|
+
Type10.String({
|
|
4149
|
+
description: "OpenAI model to use for grounded answers (for example 'gpt-4.1')."
|
|
4150
|
+
})
|
|
4102
4151
|
),
|
|
4103
|
-
|
|
4104
|
-
Type10.
|
|
4105
|
-
description: "
|
|
4152
|
+
instructions: Type10.Optional(
|
|
4153
|
+
Type10.String({
|
|
4154
|
+
description: "Optional instructions that shape the answer structure, tone, and source selection."
|
|
4106
4155
|
})
|
|
4107
4156
|
)
|
|
4108
4157
|
},
|
|
4109
|
-
{ description: "
|
|
4158
|
+
{ description: "OpenAI answer options." }
|
|
4110
4159
|
);
|
|
4111
|
-
var
|
|
4112
|
-
|
|
4113
|
-
|
|
4114
|
-
|
|
4115
|
-
|
|
4160
|
+
var openaiResearchOptionsSchema = Type10.Object(
|
|
4161
|
+
{
|
|
4162
|
+
model: Type10.Optional(
|
|
4163
|
+
Type10.String({
|
|
4164
|
+
description: "OpenAI deep research model to use (for example 'o4-mini-deep-research')."
|
|
4165
|
+
})
|
|
4166
|
+
),
|
|
4167
|
+
instructions: Type10.Optional(
|
|
4168
|
+
Type10.String({
|
|
4169
|
+
description: "Optional instructions that shape the report structure, tone, and source selection."
|
|
4170
|
+
})
|
|
4171
|
+
),
|
|
4172
|
+
max_tool_calls: Type10.Optional(
|
|
4173
|
+
Type10.Integer({
|
|
4174
|
+
minimum: 1,
|
|
4175
|
+
description: "Maximum number of built-in tool calls the model may make during the research run."
|
|
4176
|
+
})
|
|
4177
|
+
)
|
|
4178
|
+
},
|
|
4179
|
+
{ description: "OpenAI deep research options." }
|
|
4180
|
+
);
|
|
4181
|
+
var searchResultSchema = {
|
|
4182
|
+
type: "object",
|
|
4183
|
+
additionalProperties: false,
|
|
4184
|
+
required: ["sources"],
|
|
4185
|
+
properties: {
|
|
4186
|
+
sources: {
|
|
4187
|
+
type: "array",
|
|
4188
|
+
items: {
|
|
4189
|
+
type: "object",
|
|
4190
|
+
additionalProperties: false,
|
|
4191
|
+
required: ["title", "url", "snippet"],
|
|
4192
|
+
properties: {
|
|
4193
|
+
title: { type: "string" },
|
|
4194
|
+
url: { type: "string" },
|
|
4195
|
+
snippet: { type: "string" }
|
|
4196
|
+
}
|
|
4197
|
+
}
|
|
4198
|
+
}
|
|
4199
|
+
}
|
|
4200
|
+
};
|
|
4201
|
+
var openaiAdapter = {
|
|
4202
|
+
id: "openai",
|
|
4203
|
+
label: "OpenAI",
|
|
4204
|
+
docsUrl: "https://platform.openai.com/docs/guides/deep-research",
|
|
4205
|
+
tools: ["search", "answer", "research"],
|
|
4116
4206
|
getToolOptionsSchema(capability) {
|
|
4117
4207
|
switch (capability) {
|
|
4118
4208
|
case "search":
|
|
4119
|
-
return
|
|
4120
|
-
case "
|
|
4121
|
-
return
|
|
4209
|
+
return openaiSearchOptionsSchema;
|
|
4210
|
+
case "answer":
|
|
4211
|
+
return openaiAnswerOptionsSchema;
|
|
4212
|
+
case "research":
|
|
4213
|
+
return openaiResearchOptionsSchema;
|
|
4122
4214
|
default:
|
|
4123
4215
|
return void 0;
|
|
4124
4216
|
}
|
|
4125
4217
|
},
|
|
4126
4218
|
createTemplate() {
|
|
4127
4219
|
return {
|
|
4128
|
-
apiKey: "
|
|
4220
|
+
apiKey: "OPENAI_API_KEY",
|
|
4129
4221
|
options: {
|
|
4130
4222
|
search: {
|
|
4131
|
-
|
|
4223
|
+
model: DEFAULT_SEARCH_MODEL2
|
|
4132
4224
|
},
|
|
4133
|
-
|
|
4134
|
-
|
|
4135
|
-
|
|
4225
|
+
answer: {
|
|
4226
|
+
model: DEFAULT_ANSWER_MODEL2
|
|
4227
|
+
},
|
|
4228
|
+
research: {
|
|
4229
|
+
model: DEFAULT_RESEARCH_MODEL
|
|
4136
4230
|
}
|
|
4137
4231
|
}
|
|
4138
4232
|
};
|
|
@@ -4146,11 +4240,18 @@ var parallelAdapter = {
|
|
|
4146
4240
|
options: config.options?.search,
|
|
4147
4241
|
settings: config.settings
|
|
4148
4242
|
};
|
|
4149
|
-
case "
|
|
4243
|
+
case "answer":
|
|
4150
4244
|
return {
|
|
4151
4245
|
apiKey: config.apiKey,
|
|
4152
4246
|
baseUrl: config.baseUrl,
|
|
4153
|
-
options: config.options?.
|
|
4247
|
+
options: config.options?.answer,
|
|
4248
|
+
settings: config.settings
|
|
4249
|
+
};
|
|
4250
|
+
case "research":
|
|
4251
|
+
return {
|
|
4252
|
+
apiKey: config.apiKey,
|
|
4253
|
+
baseUrl: config.baseUrl,
|
|
4254
|
+
options: config.options?.research,
|
|
4154
4255
|
settings: config.settings
|
|
4155
4256
|
};
|
|
4156
4257
|
default:
|
|
@@ -4164,11 +4265,11 @@ var parallelAdapter = {
|
|
|
4164
4265
|
return buildProviderPlan({
|
|
4165
4266
|
request,
|
|
4166
4267
|
config,
|
|
4167
|
-
providerId:
|
|
4168
|
-
providerLabel:
|
|
4268
|
+
providerId: openaiAdapter.id,
|
|
4269
|
+
providerLabel: openaiAdapter.label,
|
|
4169
4270
|
handlers: {
|
|
4170
4271
|
search: {
|
|
4171
|
-
execute: (searchRequest, providerConfig, context) =>
|
|
4272
|
+
execute: (searchRequest, providerConfig, context) => openaiAdapter.search(
|
|
4172
4273
|
searchRequest.query,
|
|
4173
4274
|
searchRequest.maxResults,
|
|
4174
4275
|
providerConfig,
|
|
@@ -4176,12 +4277,20 @@ var parallelAdapter = {
|
|
|
4176
4277
|
searchRequest.options
|
|
4177
4278
|
)
|
|
4178
4279
|
},
|
|
4179
|
-
|
|
4180
|
-
execute: (
|
|
4181
|
-
|
|
4280
|
+
answer: {
|
|
4281
|
+
execute: (answerRequest, providerConfig, context) => openaiAdapter.answer(
|
|
4282
|
+
answerRequest.query,
|
|
4182
4283
|
providerConfig,
|
|
4183
4284
|
context,
|
|
4184
|
-
|
|
4285
|
+
answerRequest.options
|
|
4286
|
+
)
|
|
4287
|
+
},
|
|
4288
|
+
research: {
|
|
4289
|
+
execute: (researchRequest, providerConfig, context) => openaiAdapter.research(
|
|
4290
|
+
researchRequest.input,
|
|
4291
|
+
providerConfig,
|
|
4292
|
+
context,
|
|
4293
|
+
researchRequest.options
|
|
4185
4294
|
)
|
|
4186
4295
|
}
|
|
4187
4296
|
}
|
|
@@ -4189,62 +4298,72 @@ var parallelAdapter = {
|
|
|
4189
4298
|
},
|
|
4190
4299
|
async search(query2, maxResults, config, context, options) {
|
|
4191
4300
|
const client = createClient5(config);
|
|
4192
|
-
const
|
|
4193
|
-
|
|
4194
|
-
|
|
4195
|
-
...defaults,
|
|
4196
|
-
...options ?? {},
|
|
4197
|
-
objective: query2,
|
|
4198
|
-
max_results: maxResults
|
|
4199
|
-
},
|
|
4200
|
-
buildRequestOptions2(context)
|
|
4301
|
+
const response = await client.responses.create(
|
|
4302
|
+
buildOpenAISearchRequest(query2, maxResults, config, options),
|
|
4303
|
+
buildRequestOptions2(context.signal, context.idempotencyKey)
|
|
4201
4304
|
);
|
|
4202
|
-
return
|
|
4203
|
-
provider: parallelAdapter.id,
|
|
4204
|
-
results: response.results.slice(0, maxResults).map((result) => ({
|
|
4205
|
-
title: result.title ?? result.url,
|
|
4206
|
-
url: result.url,
|
|
4207
|
-
snippet: trimSnippet(result.excerpts?.join(" ") ?? "")
|
|
4208
|
-
}))
|
|
4209
|
-
};
|
|
4305
|
+
return parseSearchResponse2(response, maxResults);
|
|
4210
4306
|
},
|
|
4211
|
-
async
|
|
4307
|
+
async answer(query2, config, context, options) {
|
|
4212
4308
|
const client = createClient5(config);
|
|
4213
|
-
const
|
|
4214
|
-
|
|
4215
|
-
|
|
4216
|
-
...defaults,
|
|
4217
|
-
...options ?? {},
|
|
4218
|
-
urls
|
|
4219
|
-
},
|
|
4220
|
-
buildRequestOptions2(context)
|
|
4309
|
+
const response = await client.responses.create(
|
|
4310
|
+
buildOpenAIAnswerRequest(query2, config, options),
|
|
4311
|
+
buildRequestOptions2(context.signal, context.idempotencyKey)
|
|
4221
4312
|
);
|
|
4222
|
-
|
|
4223
|
-
|
|
4313
|
+
return ensureCompletedResponse(response, "answer");
|
|
4314
|
+
},
|
|
4315
|
+
async research(input, config, context, options) {
|
|
4316
|
+
return await executeAsyncResearch({
|
|
4317
|
+
providerLabel: openaiAdapter.label,
|
|
4318
|
+
providerId: openaiAdapter.id,
|
|
4319
|
+
context,
|
|
4320
|
+
start: (researchContext) => openaiAdapter.startResearch(input, config, researchContext, options),
|
|
4321
|
+
poll: (id, researchContext) => openaiAdapter.pollResearch(id, config, researchContext, options)
|
|
4322
|
+
});
|
|
4323
|
+
},
|
|
4324
|
+
async startResearch(input, config, context, options) {
|
|
4325
|
+
const client = createClient5(config);
|
|
4326
|
+
const response = await client.responses.create(
|
|
4327
|
+
buildOpenAIResearchRequest(input, config, options),
|
|
4328
|
+
buildRequestOptions2(context.signal, context.idempotencyKey)
|
|
4224
4329
|
);
|
|
4225
|
-
|
|
4226
|
-
|
|
4330
|
+
return { id: response.id };
|
|
4331
|
+
},
|
|
4332
|
+
async pollResearch(id, config, context, _options) {
|
|
4333
|
+
const client = createClient5(config);
|
|
4334
|
+
const response = await client.responses.retrieve(
|
|
4335
|
+
id,
|
|
4336
|
+
void 0,
|
|
4337
|
+
buildRequestOptions2(context.signal)
|
|
4227
4338
|
);
|
|
4339
|
+
const status = response.status ?? "completed";
|
|
4340
|
+
if (status === "completed") {
|
|
4341
|
+
return {
|
|
4342
|
+
status: "completed",
|
|
4343
|
+
output: formatResponseOutput(response, "research")
|
|
4344
|
+
};
|
|
4345
|
+
}
|
|
4346
|
+
if (status === "failed") {
|
|
4347
|
+
return {
|
|
4348
|
+
status: "failed",
|
|
4349
|
+
error: response.error?.message ?? "research failed"
|
|
4350
|
+
};
|
|
4351
|
+
}
|
|
4352
|
+
if (status === "cancelled") {
|
|
4353
|
+
return {
|
|
4354
|
+
status: "cancelled",
|
|
4355
|
+
error: "research was canceled"
|
|
4356
|
+
};
|
|
4357
|
+
}
|
|
4358
|
+
if (status === "incomplete") {
|
|
4359
|
+
return {
|
|
4360
|
+
status: "failed",
|
|
4361
|
+
error: formatIncompleteError(response, "research")
|
|
4362
|
+
};
|
|
4363
|
+
}
|
|
4228
4364
|
return {
|
|
4229
|
-
|
|
4230
|
-
|
|
4231
|
-
const result = resultsByUrl.get(url);
|
|
4232
|
-
if (result) {
|
|
4233
|
-
return {
|
|
4234
|
-
url,
|
|
4235
|
-
content: result.full_content ?? result.excerpts?.join("\n\n") ?? void 0,
|
|
4236
|
-
metadata: result
|
|
4237
|
-
};
|
|
4238
|
-
}
|
|
4239
|
-
const error = errorsByUrl.get(url);
|
|
4240
|
-
return error ? {
|
|
4241
|
-
url,
|
|
4242
|
-
error: formatJson(error)
|
|
4243
|
-
} : {
|
|
4244
|
-
url,
|
|
4245
|
-
error: "No content returned for this URL."
|
|
4246
|
-
};
|
|
4247
|
-
})
|
|
4365
|
+
status: "in_progress",
|
|
4366
|
+
statusText: status
|
|
4248
4367
|
};
|
|
4249
4368
|
}
|
|
4250
4369
|
};
|
|
@@ -4253,85 +4372,521 @@ function createClient5(config) {
|
|
|
4253
4372
|
if (!apiKey) {
|
|
4254
4373
|
throw new Error("is missing an API key");
|
|
4255
4374
|
}
|
|
4256
|
-
|
|
4375
|
+
const baseUrl = resolveConfigValue(config.baseUrl);
|
|
4376
|
+
return new OpenAI({
|
|
4257
4377
|
apiKey,
|
|
4258
|
-
baseURL:
|
|
4378
|
+
...baseUrl ? { baseURL: baseUrl } : {}
|
|
4259
4379
|
});
|
|
4260
4380
|
}
|
|
4261
|
-
function
|
|
4262
|
-
|
|
4381
|
+
function buildOpenAISearchRequest(query2, maxResults, config, options) {
|
|
4382
|
+
const mergedOptions = resolveOpenAISearchOptions(config, options);
|
|
4383
|
+
const model = mergedOptions.model ?? DEFAULT_SEARCH_MODEL2;
|
|
4384
|
+
const instructions = mergedOptions.instructions;
|
|
4385
|
+
return {
|
|
4386
|
+
model,
|
|
4387
|
+
input: [
|
|
4388
|
+
"Search the public web and return only the most relevant sources for the user's query.",
|
|
4389
|
+
`Return at most ${maxResults} sources.`,
|
|
4390
|
+
"Prefer official, primary, or highly reputable sources when available.",
|
|
4391
|
+
"Each snippet should be short, specific, and grounded in the retrieved source.",
|
|
4392
|
+
"Return only data matching the provided JSON schema.",
|
|
4393
|
+
"",
|
|
4394
|
+
`User query: ${query2}`
|
|
4395
|
+
].join("\n"),
|
|
4396
|
+
tools: [{ type: "web_search_preview" }],
|
|
4397
|
+
text: {
|
|
4398
|
+
format: {
|
|
4399
|
+
type: "json_schema",
|
|
4400
|
+
name: "openai_web_search_results",
|
|
4401
|
+
schema: searchResultSchema,
|
|
4402
|
+
strict: true
|
|
4403
|
+
}
|
|
4404
|
+
},
|
|
4405
|
+
...instructions ? { instructions } : {}
|
|
4406
|
+
};
|
|
4263
4407
|
}
|
|
4264
|
-
|
|
4265
|
-
|
|
4266
|
-
|
|
4267
|
-
|
|
4268
|
-
|
|
4269
|
-
|
|
4270
|
-
|
|
4271
|
-
|
|
4272
|
-
|
|
4273
|
-
|
|
4274
|
-
|
|
4275
|
-
|
|
4276
|
-
|
|
4277
|
-
|
|
4278
|
-
|
|
4279
|
-
|
|
4280
|
-
|
|
4281
|
-
|
|
4282
|
-
|
|
4283
|
-
|
|
4284
|
-
|
|
4285
|
-
|
|
4286
|
-
|
|
4287
|
-
|
|
4288
|
-
|
|
4289
|
-
|
|
4290
|
-
{
|
|
4291
|
-
|
|
4292
|
-
|
|
4293
|
-
|
|
4294
|
-
|
|
4295
|
-
|
|
4296
|
-
|
|
4297
|
-
|
|
4298
|
-
|
|
4299
|
-
|
|
4300
|
-
|
|
4301
|
-
|
|
4302
|
-
|
|
4303
|
-
|
|
4304
|
-
|
|
4305
|
-
|
|
4306
|
-
|
|
4307
|
-
|
|
4308
|
-
|
|
4309
|
-
|
|
4310
|
-
|
|
4311
|
-
|
|
4312
|
-
|
|
4313
|
-
|
|
4314
|
-
|
|
4315
|
-
|
|
4316
|
-
|
|
4317
|
-
|
|
4318
|
-
|
|
4319
|
-
|
|
4320
|
-
|
|
4321
|
-
|
|
4322
|
-
|
|
4323
|
-
|
|
4324
|
-
}
|
|
4325
|
-
}
|
|
4326
|
-
|
|
4327
|
-
|
|
4408
|
+
function buildOpenAIAnswerRequest(query2, config, options) {
|
|
4409
|
+
const mergedOptions = resolveOpenAIAnswerOptions(config, options);
|
|
4410
|
+
const model = mergedOptions.model ?? DEFAULT_ANSWER_MODEL2;
|
|
4411
|
+
const instructions = mergedOptions.instructions;
|
|
4412
|
+
return {
|
|
4413
|
+
model,
|
|
4414
|
+
input: query2,
|
|
4415
|
+
tools: [{ type: "web_search_preview" }],
|
|
4416
|
+
...instructions ? { instructions } : {}
|
|
4417
|
+
};
|
|
4418
|
+
}
|
|
4419
|
+
function buildOpenAIResearchRequest(input, config, options) {
|
|
4420
|
+
const mergedOptions = resolveOpenAIResearchOptions(config, options);
|
|
4421
|
+
const model = mergedOptions.model ?? DEFAULT_RESEARCH_MODEL;
|
|
4422
|
+
const instructions = mergedOptions.instructions;
|
|
4423
|
+
const maxToolCalls = mergedOptions.max_tool_calls;
|
|
4424
|
+
return {
|
|
4425
|
+
model,
|
|
4426
|
+
input,
|
|
4427
|
+
background: true,
|
|
4428
|
+
tools: [{ type: "web_search_preview" }],
|
|
4429
|
+
...instructions ? { instructions } : {},
|
|
4430
|
+
...maxToolCalls ? { max_tool_calls: maxToolCalls } : {}
|
|
4431
|
+
};
|
|
4432
|
+
}
|
|
4433
|
+
function resolveOpenAISearchOptions(config, options) {
|
|
4434
|
+
const mergedOptions = {
|
|
4435
|
+
...config.options?.search ?? {},
|
|
4436
|
+
...options ?? {}
|
|
4437
|
+
};
|
|
4438
|
+
const model = readNonEmptyString4(mergedOptions.model);
|
|
4439
|
+
const instructions = readNonEmptyString4(mergedOptions.instructions);
|
|
4440
|
+
return {
|
|
4441
|
+
...model ? { model } : {},
|
|
4442
|
+
...instructions ? { instructions } : {}
|
|
4443
|
+
};
|
|
4444
|
+
}
|
|
4445
|
+
function resolveOpenAIAnswerOptions(config, options) {
|
|
4446
|
+
const mergedOptions = {
|
|
4447
|
+
...config.options?.answer ?? {},
|
|
4448
|
+
...options ?? {}
|
|
4449
|
+
};
|
|
4450
|
+
const model = readNonEmptyString4(mergedOptions.model);
|
|
4451
|
+
const instructions = readNonEmptyString4(mergedOptions.instructions);
|
|
4452
|
+
return {
|
|
4453
|
+
...model ? { model } : {},
|
|
4454
|
+
...instructions ? { instructions } : {}
|
|
4455
|
+
};
|
|
4456
|
+
}
|
|
4457
|
+
function resolveOpenAIResearchOptions(config, options) {
|
|
4458
|
+
const mergedOptions = {
|
|
4459
|
+
...config.options?.research ?? {},
|
|
4460
|
+
...options ?? {}
|
|
4461
|
+
};
|
|
4462
|
+
const model = readNonEmptyString4(mergedOptions.model);
|
|
4463
|
+
const instructions = readNonEmptyString4(mergedOptions.instructions);
|
|
4464
|
+
const maxToolCalls = readPositiveInteger2(mergedOptions.max_tool_calls);
|
|
4465
|
+
return {
|
|
4466
|
+
...model ? { model } : {},
|
|
4467
|
+
...instructions ? { instructions } : {},
|
|
4468
|
+
...maxToolCalls ? { max_tool_calls: maxToolCalls } : {}
|
|
4469
|
+
};
|
|
4470
|
+
}
|
|
4471
|
+
function buildRequestOptions2(signal, idempotencyKey) {
|
|
4472
|
+
if (!signal && !idempotencyKey) {
|
|
4473
|
+
return void 0;
|
|
4474
|
+
}
|
|
4475
|
+
return {
|
|
4476
|
+
...signal ? { signal } : {},
|
|
4477
|
+
...idempotencyKey ? { idempotencyKey } : {}
|
|
4478
|
+
};
|
|
4479
|
+
}
|
|
4480
|
+
function parseSearchResponse2(response, maxResults) {
|
|
4481
|
+
const status = response.status ?? "completed";
|
|
4482
|
+
if (status === "failed") {
|
|
4483
|
+
throw new Error(response.error?.message ?? "search failed");
|
|
4484
|
+
}
|
|
4485
|
+
if (status === "cancelled") {
|
|
4486
|
+
throw new Error("search was canceled");
|
|
4487
|
+
}
|
|
4488
|
+
if (status === "incomplete") {
|
|
4489
|
+
throw new Error(formatIncompleteError(response, "search"));
|
|
4490
|
+
}
|
|
4491
|
+
if (status !== "completed") {
|
|
4492
|
+
throw new Error(`search did not complete (status: ${status})`);
|
|
4493
|
+
}
|
|
4494
|
+
const payload = parseSearchPayload(response.output_text);
|
|
4495
|
+
return {
|
|
4496
|
+
provider: openaiAdapter.id,
|
|
4497
|
+
results: payload.sources.slice(0, maxResults).map((source) => ({
|
|
4498
|
+
title: source.title.trim(),
|
|
4499
|
+
url: source.url.trim(),
|
|
4500
|
+
snippet: trimSnippet(source.snippet)
|
|
4501
|
+
}))
|
|
4502
|
+
};
|
|
4503
|
+
}
|
|
4504
|
+
function ensureCompletedResponse(response, operation) {
|
|
4505
|
+
const status = response.status ?? "completed";
|
|
4506
|
+
if (status === "completed") {
|
|
4507
|
+
return formatResponseOutput(response, operation);
|
|
4508
|
+
}
|
|
4509
|
+
if (status === "failed") {
|
|
4510
|
+
throw new Error(response.error?.message ?? `${operation} failed`);
|
|
4511
|
+
}
|
|
4512
|
+
if (status === "cancelled") {
|
|
4513
|
+
throw new Error(`${operation} was canceled`);
|
|
4514
|
+
}
|
|
4515
|
+
if (status === "incomplete") {
|
|
4516
|
+
throw new Error(formatIncompleteError(response, operation));
|
|
4517
|
+
}
|
|
4518
|
+
throw new Error(`${operation} did not complete (status: ${status})`);
|
|
4519
|
+
}
|
|
4520
|
+
function formatResponseOutput(response, operation) {
|
|
4521
|
+
const lines = [];
|
|
4522
|
+
lines.push(
|
|
4523
|
+
response.output_text?.trim() || `OpenAI ${operation} completed without textual output.`
|
|
4524
|
+
);
|
|
4525
|
+
const citations = extractUrlCitations(response);
|
|
4526
|
+
if (citations.length > 0) {
|
|
4527
|
+
lines.push("");
|
|
4528
|
+
lines.push("Sources:");
|
|
4529
|
+
for (const [index, citation] of citations.entries()) {
|
|
4530
|
+
lines.push(`${index + 1}. ${citation.title}`);
|
|
4531
|
+
lines.push(` ${citation.url}`);
|
|
4532
|
+
}
|
|
4533
|
+
}
|
|
4534
|
+
return {
|
|
4535
|
+
provider: openaiAdapter.id,
|
|
4536
|
+
text: lines.join("\n").trimEnd(),
|
|
4537
|
+
itemCount: citations.length,
|
|
4538
|
+
metadata: {
|
|
4539
|
+
responseId: response.id,
|
|
4540
|
+
model: response.model,
|
|
4541
|
+
citations
|
|
4542
|
+
}
|
|
4543
|
+
};
|
|
4544
|
+
}
|
|
4545
|
+
function extractUrlCitations(response) {
|
|
4546
|
+
const citations = [];
|
|
4547
|
+
const seen = /* @__PURE__ */ new Set();
|
|
4548
|
+
for (const item of response.output) {
|
|
4549
|
+
if (item.type !== "message" || !item.content) {
|
|
4550
|
+
continue;
|
|
4551
|
+
}
|
|
4552
|
+
for (const content of item.content) {
|
|
4553
|
+
if (content.type !== "output_text" || !content.annotations) {
|
|
4554
|
+
continue;
|
|
4555
|
+
}
|
|
4556
|
+
for (const annotation of content.annotations) {
|
|
4557
|
+
if (annotation.type !== "url_citation") {
|
|
4558
|
+
continue;
|
|
4559
|
+
}
|
|
4560
|
+
const title = readNonEmptyString4(annotation.title);
|
|
4561
|
+
const url = readNonEmptyString4(annotation.url);
|
|
4562
|
+
const startIndex = readInteger(annotation.start_index);
|
|
4563
|
+
const endIndex = readInteger(annotation.end_index);
|
|
4564
|
+
if (!title || !url || startIndex === void 0 || endIndex === void 0) {
|
|
4565
|
+
continue;
|
|
4566
|
+
}
|
|
4567
|
+
const citation = {
|
|
4568
|
+
title,
|
|
4569
|
+
url,
|
|
4570
|
+
startIndex,
|
|
4571
|
+
endIndex
|
|
4572
|
+
};
|
|
4573
|
+
const key = [
|
|
4574
|
+
citation.title,
|
|
4575
|
+
citation.url,
|
|
4576
|
+
String(citation.startIndex),
|
|
4577
|
+
String(citation.endIndex)
|
|
4578
|
+
].join("::");
|
|
4579
|
+
if (seen.has(key)) {
|
|
4580
|
+
continue;
|
|
4581
|
+
}
|
|
4582
|
+
seen.add(key);
|
|
4583
|
+
citations.push(citation);
|
|
4584
|
+
}
|
|
4585
|
+
}
|
|
4586
|
+
}
|
|
4587
|
+
return citations;
|
|
4588
|
+
}
|
|
4589
|
+
function parseSearchPayload(text) {
|
|
4590
|
+
let parsed;
|
|
4591
|
+
try {
|
|
4592
|
+
parsed = JSON.parse(text ?? "");
|
|
4593
|
+
} catch (error) {
|
|
4594
|
+
throw new Error(
|
|
4595
|
+
`search returned invalid JSON: ${error.message}`
|
|
4596
|
+
);
|
|
4597
|
+
}
|
|
4598
|
+
if (typeof parsed !== "object" || parsed === null || !("sources" in parsed) || !Array.isArray(parsed.sources)) {
|
|
4599
|
+
throw new Error("search output must include a 'sources' array");
|
|
4600
|
+
}
|
|
4601
|
+
return {
|
|
4602
|
+
sources: parsed.sources.map((source, index) => {
|
|
4603
|
+
if (typeof source !== "object" || source === null) {
|
|
4604
|
+
throw new Error(`search source at index ${index} must be an object`);
|
|
4605
|
+
}
|
|
4606
|
+
const entry = source;
|
|
4607
|
+
const title = readNonEmptyString4(entry.title);
|
|
4608
|
+
const url = readNonEmptyString4(entry.url);
|
|
4609
|
+
const snippet = readNonEmptyString4(entry.snippet);
|
|
4610
|
+
if (!title) {
|
|
4611
|
+
throw new Error(`search source at index ${index} is missing title`);
|
|
4612
|
+
}
|
|
4613
|
+
if (!url) {
|
|
4614
|
+
throw new Error(`search source at index ${index} is missing url`);
|
|
4615
|
+
}
|
|
4616
|
+
if (!snippet) {
|
|
4617
|
+
throw new Error(`search source at index ${index} is missing snippet`);
|
|
4618
|
+
}
|
|
4619
|
+
return { title, url, snippet };
|
|
4620
|
+
})
|
|
4621
|
+
};
|
|
4622
|
+
}
|
|
4623
|
+
function formatIncompleteError(response, operation) {
|
|
4624
|
+
const reason = response.incomplete_details?.reason;
|
|
4625
|
+
if (reason) {
|
|
4626
|
+
return `${operation} ended incomplete (${reason})`;
|
|
4627
|
+
}
|
|
4628
|
+
return `${operation} ended incomplete`;
|
|
4629
|
+
}
|
|
4630
|
+
function readNonEmptyString4(value) {
|
|
4631
|
+
return typeof value === "string" && value.trim().length > 0 ? value : void 0;
|
|
4632
|
+
}
|
|
4633
|
+
function readPositiveInteger2(value) {
|
|
4634
|
+
return typeof value === "number" && Number.isInteger(value) && value > 0 ? value : void 0;
|
|
4635
|
+
}
|
|
4636
|
+
function readInteger(value) {
|
|
4637
|
+
return typeof value === "number" && Number.isInteger(value) ? value : void 0;
|
|
4638
|
+
}
|
|
4639
|
+
|
|
4640
|
+
// src/providers/parallel.ts
|
|
4641
|
+
import { Type as Type11 } from "@sinclair/typebox";
|
|
4642
|
+
import ParallelClient from "parallel-web";
|
|
4643
|
+
var parallelSearchOptionsSchema = Type11.Object(
|
|
4644
|
+
{
|
|
4645
|
+
mode: Type11.Optional(
|
|
4646
|
+
literalUnion(["agentic", "one-shot"], {
|
|
4647
|
+
description: "Parallel search mode."
|
|
4648
|
+
})
|
|
4649
|
+
)
|
|
4650
|
+
},
|
|
4651
|
+
{ description: "Parallel search options." }
|
|
4652
|
+
);
|
|
4653
|
+
var parallelExtractOptionsSchema = Type11.Object(
|
|
4654
|
+
{
|
|
4655
|
+
excerpts: Type11.Optional(
|
|
4656
|
+
Type11.Boolean({ description: "Include excerpts in extraction results." })
|
|
4657
|
+
),
|
|
4658
|
+
full_content: Type11.Optional(
|
|
4659
|
+
Type11.Boolean({
|
|
4660
|
+
description: "Include full page content in extraction results."
|
|
4661
|
+
})
|
|
4662
|
+
)
|
|
4663
|
+
},
|
|
4664
|
+
{ description: "Parallel extract options." }
|
|
4665
|
+
);
|
|
4666
|
+
var parallelAdapter = {
|
|
4667
|
+
id: "parallel",
|
|
4668
|
+
label: "Parallel",
|
|
4669
|
+
docsUrl: "https://github.com/parallel-web/parallel-sdk-typescript",
|
|
4670
|
+
tools: ["search", "contents"],
|
|
4671
|
+
getToolOptionsSchema(capability) {
|
|
4672
|
+
switch (capability) {
|
|
4673
|
+
case "search":
|
|
4674
|
+
return parallelSearchOptionsSchema;
|
|
4675
|
+
case "contents":
|
|
4676
|
+
return parallelExtractOptionsSchema;
|
|
4677
|
+
default:
|
|
4678
|
+
return void 0;
|
|
4679
|
+
}
|
|
4680
|
+
},
|
|
4681
|
+
createTemplate() {
|
|
4682
|
+
return {
|
|
4683
|
+
apiKey: "PARALLEL_API_KEY",
|
|
4684
|
+
options: {
|
|
4685
|
+
search: {
|
|
4686
|
+
mode: "agentic"
|
|
4687
|
+
},
|
|
4688
|
+
extract: {
|
|
4689
|
+
excerpts: false,
|
|
4690
|
+
full_content: true
|
|
4691
|
+
}
|
|
4692
|
+
}
|
|
4693
|
+
};
|
|
4694
|
+
},
|
|
4695
|
+
getConfigForCapability(capability, config) {
|
|
4696
|
+
switch (capability) {
|
|
4697
|
+
case "search":
|
|
4698
|
+
return {
|
|
4699
|
+
apiKey: config.apiKey,
|
|
4700
|
+
baseUrl: config.baseUrl,
|
|
4701
|
+
options: config.options?.search,
|
|
4702
|
+
settings: config.settings
|
|
4703
|
+
};
|
|
4704
|
+
case "contents":
|
|
4705
|
+
return {
|
|
4706
|
+
apiKey: config.apiKey,
|
|
4707
|
+
baseUrl: config.baseUrl,
|
|
4708
|
+
options: config.options?.extract,
|
|
4709
|
+
settings: config.settings
|
|
4710
|
+
};
|
|
4711
|
+
default:
|
|
4712
|
+
return config;
|
|
4713
|
+
}
|
|
4714
|
+
},
|
|
4715
|
+
getCapabilityStatus(config) {
|
|
4716
|
+
return getApiKeyStatus(config?.apiKey);
|
|
4717
|
+
},
|
|
4718
|
+
buildPlan(request, config) {
|
|
4719
|
+
return buildProviderPlan({
|
|
4720
|
+
request,
|
|
4721
|
+
config,
|
|
4722
|
+
providerId: parallelAdapter.id,
|
|
4723
|
+
providerLabel: parallelAdapter.label,
|
|
4724
|
+
handlers: {
|
|
4725
|
+
search: {
|
|
4726
|
+
execute: (searchRequest, providerConfig, context) => parallelAdapter.search(
|
|
4727
|
+
searchRequest.query,
|
|
4728
|
+
searchRequest.maxResults,
|
|
4729
|
+
providerConfig,
|
|
4730
|
+
context,
|
|
4731
|
+
searchRequest.options
|
|
4732
|
+
)
|
|
4733
|
+
},
|
|
4734
|
+
contents: {
|
|
4735
|
+
execute: (contentsRequest, providerConfig, context) => parallelAdapter.contents(
|
|
4736
|
+
contentsRequest.urls,
|
|
4737
|
+
providerConfig,
|
|
4738
|
+
context,
|
|
4739
|
+
contentsRequest.options
|
|
4740
|
+
)
|
|
4741
|
+
}
|
|
4742
|
+
}
|
|
4743
|
+
});
|
|
4744
|
+
},
|
|
4745
|
+
async search(query2, maxResults, config, context, options) {
|
|
4746
|
+
const client = createClient6(config);
|
|
4747
|
+
const defaults = stripLocalExecutionOptions(asJsonObject(config.options?.search)) ?? {};
|
|
4748
|
+
const response = await client.beta.search(
|
|
4749
|
+
{
|
|
4750
|
+
...defaults,
|
|
4751
|
+
...options ?? {},
|
|
4752
|
+
objective: query2,
|
|
4753
|
+
max_results: maxResults
|
|
4754
|
+
},
|
|
4755
|
+
buildRequestOptions3(context)
|
|
4756
|
+
);
|
|
4757
|
+
return {
|
|
4758
|
+
provider: parallelAdapter.id,
|
|
4759
|
+
results: response.results.slice(0, maxResults).map((result) => ({
|
|
4760
|
+
title: result.title ?? result.url,
|
|
4761
|
+
url: result.url,
|
|
4762
|
+
snippet: trimSnippet(result.excerpts?.join(" ") ?? "")
|
|
4763
|
+
}))
|
|
4764
|
+
};
|
|
4765
|
+
},
|
|
4766
|
+
async contents(urls, config, context, options) {
|
|
4767
|
+
const client = createClient6(config);
|
|
4768
|
+
const defaults = stripLocalExecutionOptions(asJsonObject(config.options?.extract)) ?? {};
|
|
4769
|
+
const response = await client.beta.extract(
|
|
4770
|
+
{
|
|
4771
|
+
...defaults,
|
|
4772
|
+
...options ?? {},
|
|
4773
|
+
urls
|
|
4774
|
+
},
|
|
4775
|
+
buildRequestOptions3(context)
|
|
4776
|
+
);
|
|
4777
|
+
const resultsByUrl = new Map(
|
|
4778
|
+
response.results.map((result) => [result.url, result])
|
|
4779
|
+
);
|
|
4780
|
+
const errorsByUrl = new Map(
|
|
4781
|
+
response.errors.map((error) => [error.url, error])
|
|
4782
|
+
);
|
|
4783
|
+
return {
|
|
4784
|
+
provider: parallelAdapter.id,
|
|
4785
|
+
answers: urls.map((url) => {
|
|
4786
|
+
const result = resultsByUrl.get(url);
|
|
4787
|
+
if (result) {
|
|
4788
|
+
return {
|
|
4789
|
+
url,
|
|
4790
|
+
content: result.full_content ?? result.excerpts?.join("\n\n") ?? void 0,
|
|
4791
|
+
metadata: result
|
|
4792
|
+
};
|
|
4793
|
+
}
|
|
4794
|
+
const error = errorsByUrl.get(url);
|
|
4795
|
+
return error ? {
|
|
4796
|
+
url,
|
|
4797
|
+
error: formatJson(error)
|
|
4798
|
+
} : {
|
|
4799
|
+
url,
|
|
4800
|
+
error: "No content returned for this URL."
|
|
4801
|
+
};
|
|
4802
|
+
})
|
|
4803
|
+
};
|
|
4804
|
+
}
|
|
4805
|
+
};
|
|
4806
|
+
function createClient6(config) {
|
|
4807
|
+
const apiKey = resolveConfigValue(config.apiKey);
|
|
4808
|
+
if (!apiKey) {
|
|
4809
|
+
throw new Error("is missing an API key");
|
|
4810
|
+
}
|
|
4811
|
+
return new ParallelClient({
|
|
4812
|
+
apiKey,
|
|
4813
|
+
baseURL: resolveConfigValue(config.baseUrl)
|
|
4814
|
+
});
|
|
4815
|
+
}
|
|
4816
|
+
function buildRequestOptions3(context) {
|
|
4817
|
+
return context.signal ? { signal: context.signal } : void 0;
|
|
4818
|
+
}
|
|
4819
|
+
|
|
4820
|
+
// src/providers/perplexity.ts
|
|
4821
|
+
import PerplexityClient from "@perplexity-ai/perplexity_ai";
|
|
4822
|
+
import { Type as Type12 } from "@sinclair/typebox";
|
|
4823
|
+
var DEFAULT_ANSWER_MODEL3 = "sonar";
|
|
4824
|
+
var DEFAULT_RESEARCH_MODEL2 = "sonar-deep-research";
|
|
4825
|
+
var perplexitySearchOptionsSchema = Type12.Object(
|
|
4826
|
+
{
|
|
4827
|
+
country: Type12.Optional(
|
|
4828
|
+
Type12.String({ description: "Country hint for search results." })
|
|
4829
|
+
),
|
|
4830
|
+
search_mode: Type12.Optional(
|
|
4831
|
+
Type12.String({ description: "Perplexity search mode." })
|
|
4832
|
+
),
|
|
4833
|
+
search_domain_filter: Type12.Optional(
|
|
4834
|
+
Type12.Array(Type12.String(), {
|
|
4835
|
+
description: "Restrict search results to these domains."
|
|
4836
|
+
})
|
|
4837
|
+
),
|
|
4838
|
+
search_recency_filter: Type12.Optional(
|
|
4839
|
+
Type12.String({ description: "Recency filter for search results." })
|
|
4840
|
+
)
|
|
4841
|
+
},
|
|
4842
|
+
{ description: "Perplexity search options." }
|
|
4843
|
+
);
|
|
4844
|
+
var perplexityAnswerOptionsSchema = Type12.Object(
|
|
4845
|
+
{
|
|
4846
|
+
model: Type12.Optional(
|
|
4847
|
+
Type12.String({
|
|
4848
|
+
description: "Perplexity model to use (for example 'sonar' or 'sonar-pro')."
|
|
4849
|
+
})
|
|
4850
|
+
)
|
|
4851
|
+
},
|
|
4852
|
+
{ description: "Perplexity answer options." }
|
|
4853
|
+
);
|
|
4854
|
+
var perplexityResearchOptionsSchema = Type12.Object(
|
|
4855
|
+
{
|
|
4856
|
+
model: Type12.Optional(
|
|
4857
|
+
Type12.String({
|
|
4858
|
+
description: "Perplexity model to use (for example 'sonar-deep-research')."
|
|
4859
|
+
})
|
|
4860
|
+
)
|
|
4861
|
+
},
|
|
4862
|
+
{ description: "Perplexity research options." }
|
|
4863
|
+
);
|
|
4864
|
+
var perplexityAdapter = {
|
|
4865
|
+
id: "perplexity",
|
|
4866
|
+
label: "Perplexity",
|
|
4867
|
+
docsUrl: "https://docs.perplexity.ai/docs/sdk/overview.md",
|
|
4868
|
+
tools: ["search", "answer", "research"],
|
|
4869
|
+
getToolOptionsSchema(capability) {
|
|
4870
|
+
switch (capability) {
|
|
4871
|
+
case "search":
|
|
4872
|
+
return perplexitySearchOptionsSchema;
|
|
4873
|
+
case "answer":
|
|
4874
|
+
return perplexityAnswerOptionsSchema;
|
|
4875
|
+
case "research":
|
|
4876
|
+
return perplexityResearchOptionsSchema;
|
|
4877
|
+
default:
|
|
4878
|
+
return void 0;
|
|
4879
|
+
}
|
|
4880
|
+
},
|
|
4881
|
+
createTemplate() {
|
|
4882
|
+
return {
|
|
4328
4883
|
apiKey: "PERPLEXITY_API_KEY",
|
|
4329
4884
|
options: {
|
|
4330
4885
|
answer: {
|
|
4331
|
-
model:
|
|
4886
|
+
model: DEFAULT_ANSWER_MODEL3
|
|
4332
4887
|
},
|
|
4333
4888
|
research: {
|
|
4334
|
-
model:
|
|
4889
|
+
model: DEFAULT_RESEARCH_MODEL2
|
|
4335
4890
|
}
|
|
4336
4891
|
}
|
|
4337
4892
|
};
|
|
@@ -4375,7 +4930,7 @@ var perplexityAdapter = {
|
|
|
4375
4930
|
});
|
|
4376
4931
|
},
|
|
4377
4932
|
async search(query2, maxResults, config, context, options) {
|
|
4378
|
-
const client =
|
|
4933
|
+
const client = createClient7(config);
|
|
4379
4934
|
const request = {
|
|
4380
4935
|
...stripLocalExecutionOptions(asJsonObject(config.options?.search)) ?? {},
|
|
4381
4936
|
...options ?? {},
|
|
@@ -4384,7 +4939,7 @@ var perplexityAdapter = {
|
|
|
4384
4939
|
};
|
|
4385
4940
|
const response = await client.search.create(
|
|
4386
4941
|
request,
|
|
4387
|
-
|
|
4942
|
+
buildRequestOptions4(context)
|
|
4388
4943
|
);
|
|
4389
4944
|
return {
|
|
4390
4945
|
provider: perplexityAdapter.id,
|
|
@@ -4404,7 +4959,7 @@ var perplexityAdapter = {
|
|
|
4404
4959
|
query2,
|
|
4405
4960
|
config,
|
|
4406
4961
|
context,
|
|
4407
|
-
|
|
4962
|
+
DEFAULT_ANSWER_MODEL3,
|
|
4408
4963
|
"Answer",
|
|
4409
4964
|
options
|
|
4410
4965
|
);
|
|
@@ -4414,14 +4969,14 @@ var perplexityAdapter = {
|
|
|
4414
4969
|
input,
|
|
4415
4970
|
config,
|
|
4416
4971
|
context,
|
|
4417
|
-
|
|
4972
|
+
DEFAULT_RESEARCH_MODEL2,
|
|
4418
4973
|
"Research",
|
|
4419
4974
|
options
|
|
4420
4975
|
);
|
|
4421
4976
|
}
|
|
4422
4977
|
};
|
|
4423
4978
|
async function runSilentForegroundChatTool(input, config, context, fallbackModel, label, options, isResearch = false) {
|
|
4424
|
-
const client =
|
|
4979
|
+
const client = createClient7(config);
|
|
4425
4980
|
const defaults = stripLocalExecutionOptions(
|
|
4426
4981
|
isResearch ? asJsonObject(config.options?.research) : asJsonObject(config.options?.answer)
|
|
4427
4982
|
) ?? {};
|
|
@@ -4434,7 +4989,7 @@ async function runSilentForegroundChatTool(input, config, context, fallbackModel
|
|
|
4434
4989
|
};
|
|
4435
4990
|
const response = await client.chat.completions.create(
|
|
4436
4991
|
request,
|
|
4437
|
-
|
|
4992
|
+
buildRequestOptions4(context)
|
|
4438
4993
|
);
|
|
4439
4994
|
const content = extractMessageText(response.choices[0]?.message?.content);
|
|
4440
4995
|
const sources = dedupeSources(extractSources(response));
|
|
@@ -4455,7 +5010,7 @@ async function runSilentForegroundChatTool(input, config, context, fallbackModel
|
|
|
4455
5010
|
};
|
|
4456
5011
|
}
|
|
4457
5012
|
async function runStreamingForegroundChatTool(input, config, context, fallbackModel, label, options) {
|
|
4458
|
-
const client =
|
|
5013
|
+
const client = createClient7(config);
|
|
4459
5014
|
const defaults = stripLocalExecutionOptions(asJsonObject(config.options?.research)) ?? {};
|
|
4460
5015
|
const request = {
|
|
4461
5016
|
...defaults,
|
|
@@ -4466,7 +5021,7 @@ async function runStreamingForegroundChatTool(input, config, context, fallbackMo
|
|
|
4466
5021
|
};
|
|
4467
5022
|
const stream = await client.chat.completions.create(
|
|
4468
5023
|
request,
|
|
4469
|
-
|
|
5024
|
+
buildRequestOptions4(context)
|
|
4470
5025
|
);
|
|
4471
5026
|
let partialText = "";
|
|
4472
5027
|
let lastChunk;
|
|
@@ -4477,156 +5032,387 @@ async function runStreamingForegroundChatTool(input, config, context, fallbackMo
|
|
|
4477
5032
|
if (deltaText) {
|
|
4478
5033
|
partialText = `${partialText}${deltaText}`;
|
|
4479
5034
|
}
|
|
4480
|
-
sources.push(...extractSources(chunk));
|
|
5035
|
+
sources.push(...extractSources(chunk));
|
|
5036
|
+
}
|
|
5037
|
+
const finalText = partialText.trim() || extractMessageText(lastChunk?.choices?.[0]?.message?.content) || `No ${label.toLowerCase()} returned.`;
|
|
5038
|
+
const dedupedSources = dedupeSources(sources);
|
|
5039
|
+
const lines = [finalText];
|
|
5040
|
+
if (dedupedSources.length > 0) {
|
|
5041
|
+
lines.push("");
|
|
5042
|
+
lines.push("Sources:");
|
|
5043
|
+
for (const [index, source] of dedupedSources.entries()) {
|
|
5044
|
+
lines.push(`${index + 1}. ${source.title}`);
|
|
5045
|
+
lines.push(` ${source.url}`);
|
|
5046
|
+
}
|
|
5047
|
+
}
|
|
5048
|
+
return {
|
|
5049
|
+
provider: perplexityAdapter.id,
|
|
5050
|
+
text: lines.join("\n").trimEnd(),
|
|
5051
|
+
itemCount: dedupedSources.length
|
|
5052
|
+
};
|
|
5053
|
+
}
|
|
5054
|
+
function createClient7(config) {
|
|
5055
|
+
const apiKey = resolveConfigValue(config.apiKey);
|
|
5056
|
+
if (!apiKey) {
|
|
5057
|
+
throw new Error("is missing an API key");
|
|
5058
|
+
}
|
|
5059
|
+
return new PerplexityClient({
|
|
5060
|
+
apiKey,
|
|
5061
|
+
baseURL: resolveConfigValue(config.baseUrl)
|
|
5062
|
+
});
|
|
5063
|
+
}
|
|
5064
|
+
function resolveModel(optionModel, defaultModel, fallbackModel) {
|
|
5065
|
+
if (typeof optionModel === "string" && optionModel.trim().length > 0) {
|
|
5066
|
+
return optionModel;
|
|
5067
|
+
}
|
|
5068
|
+
if (typeof defaultModel === "string" && defaultModel.trim().length > 0) {
|
|
5069
|
+
return defaultModel;
|
|
5070
|
+
}
|
|
5071
|
+
return fallbackModel;
|
|
5072
|
+
}
|
|
5073
|
+
function extractMessageText(content) {
|
|
5074
|
+
if (typeof content === "string") {
|
|
5075
|
+
return content.trim();
|
|
5076
|
+
}
|
|
5077
|
+
if (!Array.isArray(content)) {
|
|
5078
|
+
return "";
|
|
5079
|
+
}
|
|
5080
|
+
return content.flatMap((chunk) => {
|
|
5081
|
+
if (typeof chunk === "object" && chunk !== null && "type" in chunk && chunk.type === "text" && "text" in chunk && typeof chunk.text === "string") {
|
|
5082
|
+
return [chunk.text.trim()];
|
|
5083
|
+
}
|
|
5084
|
+
return [];
|
|
5085
|
+
}).filter((text) => text.length > 0).join("\n\n").trim();
|
|
5086
|
+
}
|
|
5087
|
+
function extractDeltaText(content) {
|
|
5088
|
+
if (typeof content === "string") {
|
|
5089
|
+
return content;
|
|
5090
|
+
}
|
|
5091
|
+
if (!Array.isArray(content)) {
|
|
5092
|
+
return "";
|
|
5093
|
+
}
|
|
5094
|
+
return content.flatMap((chunk) => {
|
|
5095
|
+
if (typeof chunk === "object" && chunk !== null && "type" in chunk && chunk.type === "text" && "text" in chunk && typeof chunk.text === "string") {
|
|
5096
|
+
return [chunk.text];
|
|
5097
|
+
}
|
|
5098
|
+
return [];
|
|
5099
|
+
}).join("");
|
|
5100
|
+
}
|
|
5101
|
+
function dedupeSources(sources) {
|
|
5102
|
+
const seen = /* @__PURE__ */ new Set();
|
|
5103
|
+
const unique = [];
|
|
5104
|
+
for (const source of sources) {
|
|
5105
|
+
const title = source.title.trim() || source.url.trim() || "Untitled";
|
|
5106
|
+
const url = source.url.trim();
|
|
5107
|
+
if (!url) continue;
|
|
5108
|
+
const key = `${title.toLowerCase()}::${url.toLowerCase()}`;
|
|
5109
|
+
if (seen.has(key)) continue;
|
|
5110
|
+
seen.add(key);
|
|
5111
|
+
unique.push({ title, url });
|
|
5112
|
+
}
|
|
5113
|
+
return unique;
|
|
5114
|
+
}
|
|
5115
|
+
function extractSources(response) {
|
|
5116
|
+
const searchResults = response.search_results?.flatMap((result) => {
|
|
5117
|
+
const url = result.url?.trim() ?? "";
|
|
5118
|
+
if (!url) {
|
|
5119
|
+
return [];
|
|
5120
|
+
}
|
|
5121
|
+
return [{ title: result.title?.trim() ?? url, url }];
|
|
5122
|
+
}) ?? [];
|
|
5123
|
+
if (searchResults.length > 0) {
|
|
5124
|
+
return searchResults;
|
|
5125
|
+
}
|
|
5126
|
+
return response.citations?.flatMap((citation) => {
|
|
5127
|
+
const url = citation?.trim() ?? "";
|
|
5128
|
+
return url ? [{ title: url, url }] : [];
|
|
5129
|
+
}) ?? [];
|
|
5130
|
+
}
|
|
5131
|
+
function buildRequestOptions4(context) {
|
|
5132
|
+
return context.signal ? { signal: context.signal } : void 0;
|
|
5133
|
+
}
|
|
5134
|
+
|
|
5135
|
+
// src/providers/serper.ts
|
|
5136
|
+
import { Type as Type13 } from "@sinclair/typebox";
|
|
5137
|
+
var DEFAULT_BASE_URL = "https://google.serper.dev";
|
|
5138
|
+
var serperSearchOptionsSchema = Type13.Object(
|
|
5139
|
+
{
|
|
5140
|
+
gl: Type13.Optional(
|
|
5141
|
+
Type13.String({
|
|
5142
|
+
description: "Country code hint for Google results (for example 'us')."
|
|
5143
|
+
})
|
|
5144
|
+
),
|
|
5145
|
+
hl: Type13.Optional(
|
|
5146
|
+
Type13.String({
|
|
5147
|
+
description: "Language code hint for Google results (for example 'en')."
|
|
5148
|
+
})
|
|
5149
|
+
),
|
|
5150
|
+
location: Type13.Optional(
|
|
5151
|
+
Type13.String({
|
|
5152
|
+
description: "Geographic location hint for Google results."
|
|
5153
|
+
})
|
|
5154
|
+
),
|
|
5155
|
+
page: Type13.Optional(
|
|
5156
|
+
Type13.Integer({
|
|
5157
|
+
minimum: 1,
|
|
5158
|
+
description: "1-based results page to request from Serper."
|
|
5159
|
+
})
|
|
5160
|
+
),
|
|
5161
|
+
autocorrect: Type13.Optional(
|
|
5162
|
+
Type13.Boolean({
|
|
5163
|
+
description: "Enable or disable Serper query autocorrection."
|
|
5164
|
+
})
|
|
5165
|
+
)
|
|
5166
|
+
},
|
|
5167
|
+
{ description: "Serper search options." }
|
|
5168
|
+
);
|
|
5169
|
+
var serperAdapter = {
|
|
5170
|
+
id: "serper",
|
|
5171
|
+
label: "Serper",
|
|
5172
|
+
docsUrl: "https://serper.dev/",
|
|
5173
|
+
tools: ["search"],
|
|
5174
|
+
getToolOptionsSchema(capability) {
|
|
5175
|
+
switch (capability) {
|
|
5176
|
+
case "search":
|
|
5177
|
+
return serperSearchOptionsSchema;
|
|
5178
|
+
default:
|
|
5179
|
+
return void 0;
|
|
5180
|
+
}
|
|
5181
|
+
},
|
|
5182
|
+
createTemplate() {
|
|
5183
|
+
return {
|
|
5184
|
+
apiKey: "SERPER_API_KEY",
|
|
5185
|
+
options: {}
|
|
5186
|
+
};
|
|
5187
|
+
},
|
|
5188
|
+
getConfigForCapability(capability, config) {
|
|
5189
|
+
switch (capability) {
|
|
5190
|
+
case "search":
|
|
5191
|
+
return {
|
|
5192
|
+
apiKey: config.apiKey,
|
|
5193
|
+
baseUrl: config.baseUrl,
|
|
5194
|
+
options: config.options?.search,
|
|
5195
|
+
settings: config.settings
|
|
5196
|
+
};
|
|
5197
|
+
default:
|
|
5198
|
+
return config;
|
|
5199
|
+
}
|
|
5200
|
+
},
|
|
5201
|
+
getCapabilityStatus(config) {
|
|
5202
|
+
return getApiKeyStatus(config?.apiKey);
|
|
5203
|
+
},
|
|
5204
|
+
buildPlan(request, config) {
|
|
5205
|
+
return buildProviderPlan({
|
|
5206
|
+
request,
|
|
5207
|
+
config,
|
|
5208
|
+
providerId: serperAdapter.id,
|
|
5209
|
+
providerLabel: serperAdapter.label,
|
|
5210
|
+
handlers: {
|
|
5211
|
+
search: {
|
|
5212
|
+
execute: (searchRequest, providerConfig, context) => serperAdapter.search(
|
|
5213
|
+
searchRequest.query,
|
|
5214
|
+
searchRequest.maxResults,
|
|
5215
|
+
providerConfig,
|
|
5216
|
+
context,
|
|
5217
|
+
searchRequest.options
|
|
5218
|
+
)
|
|
5219
|
+
}
|
|
5220
|
+
}
|
|
5221
|
+
});
|
|
5222
|
+
},
|
|
5223
|
+
async search(query2, maxResults, config, context, options) {
|
|
5224
|
+
const apiKey = resolveConfigValue(config.apiKey);
|
|
5225
|
+
if (!apiKey) {
|
|
5226
|
+
throw new Error("is missing an API key");
|
|
5227
|
+
}
|
|
5228
|
+
const defaults = stripLocalExecutionOptions(asJsonObject(config.options?.search)) ?? {};
|
|
5229
|
+
const runtimeOptions = stripLocalExecutionOptions(asJsonObject(options));
|
|
5230
|
+
const {
|
|
5231
|
+
q: _ignoredQuery,
|
|
5232
|
+
num: _ignoredNum,
|
|
5233
|
+
...providerOptions
|
|
5234
|
+
} = {
|
|
5235
|
+
...defaults,
|
|
5236
|
+
...runtimeOptions ?? {}
|
|
5237
|
+
};
|
|
5238
|
+
const response = await fetch(joinUrl(resolveConfigValue(config.baseUrl)), {
|
|
5239
|
+
method: "POST",
|
|
5240
|
+
headers: {
|
|
5241
|
+
"content-type": "application/json",
|
|
5242
|
+
"x-api-key": apiKey
|
|
5243
|
+
},
|
|
5244
|
+
body: JSON.stringify({
|
|
5245
|
+
q: query2,
|
|
5246
|
+
num: clampMaxResults(maxResults),
|
|
5247
|
+
...providerOptions
|
|
5248
|
+
}),
|
|
5249
|
+
signal: context.signal
|
|
5250
|
+
});
|
|
5251
|
+
if (!response.ok) {
|
|
5252
|
+
throw new Error(await buildHttpError(response));
|
|
5253
|
+
}
|
|
5254
|
+
const payload = await response.json();
|
|
5255
|
+
const responseRecord = asRecord3(payload) ?? {};
|
|
5256
|
+
const organic = asArray(responseRecord.organic) ?? [];
|
|
5257
|
+
const searchContext = buildSearchContext(responseRecord);
|
|
5258
|
+
return {
|
|
5259
|
+
provider: serperAdapter.id,
|
|
5260
|
+
results: organic.map((entry) => toSearchResult3(entry, searchContext)).filter(
|
|
5261
|
+
(result) => result !== null
|
|
5262
|
+
).slice(0, clampMaxResults(maxResults))
|
|
5263
|
+
};
|
|
4481
5264
|
}
|
|
4482
|
-
|
|
4483
|
-
|
|
4484
|
-
const
|
|
4485
|
-
|
|
4486
|
-
|
|
4487
|
-
|
|
4488
|
-
|
|
4489
|
-
|
|
4490
|
-
|
|
5265
|
+
};
|
|
5266
|
+
function joinUrl(baseUrl) {
|
|
5267
|
+
const base = (baseUrl ?? DEFAULT_BASE_URL).replace(/\/+$/, "");
|
|
5268
|
+
return `${base}/search`;
|
|
5269
|
+
}
|
|
5270
|
+
function clampMaxResults(value) {
|
|
5271
|
+
return Math.max(1, Math.min(20, Math.trunc(value || 0)));
|
|
5272
|
+
}
|
|
5273
|
+
async function buildHttpError(response) {
|
|
5274
|
+
const detail = await readErrorDetail(response);
|
|
5275
|
+
const status = `${response.status}${response.statusText ? ` ${response.statusText}` : ""}`;
|
|
5276
|
+
return detail ? `Serper API request failed (${status}): ${detail}` : `Serper API request failed (${status}).`;
|
|
5277
|
+
}
|
|
5278
|
+
async function readErrorDetail(response) {
|
|
5279
|
+
const text = (await response.text()).trim();
|
|
5280
|
+
if (!text) {
|
|
5281
|
+
return void 0;
|
|
5282
|
+
}
|
|
5283
|
+
try {
|
|
5284
|
+
const parsed = JSON.parse(text);
|
|
5285
|
+
const record = asRecord3(parsed);
|
|
5286
|
+
const detail = readString4(record?.message) ?? readString4(record?.error) ?? readString4(record?.detail);
|
|
5287
|
+
if (detail) {
|
|
5288
|
+
return detail;
|
|
4491
5289
|
}
|
|
5290
|
+
return JSON.stringify(parsed);
|
|
5291
|
+
} catch {
|
|
5292
|
+
return text;
|
|
5293
|
+
}
|
|
5294
|
+
}
|
|
5295
|
+
function toSearchResult3(entry, searchContext) {
|
|
5296
|
+
const record = asRecord3(entry);
|
|
5297
|
+
if (!record) {
|
|
5298
|
+
return null;
|
|
4492
5299
|
}
|
|
5300
|
+
const url = readString4(record.link) ?? "";
|
|
5301
|
+
const title = readString4(record.title) || url || "Untitled";
|
|
5302
|
+
const snippet = trimSnippet(
|
|
5303
|
+
readString4(record.snippet) ?? readString4(record.richSnippet) ?? readString4(record.date) ?? ""
|
|
5304
|
+
);
|
|
5305
|
+
const metadata = omitUndefined({
|
|
5306
|
+
source: "organic",
|
|
5307
|
+
position: readNumber(record.position),
|
|
5308
|
+
date: readString4(record.date),
|
|
5309
|
+
attributes: asRecord3(record.attributes),
|
|
5310
|
+
sitelinks: asArray(record.sitelinks),
|
|
5311
|
+
rating: readNumber(record.rating),
|
|
5312
|
+
ratingCount: readNumber(record.ratingCount),
|
|
5313
|
+
cid: readString4(record.cid),
|
|
5314
|
+
...extractExtraMetadata(record, ["title", "link", "snippet"]),
|
|
5315
|
+
...searchContext ? { searchContext } : {}
|
|
5316
|
+
});
|
|
4493
5317
|
return {
|
|
4494
|
-
|
|
4495
|
-
|
|
4496
|
-
|
|
5318
|
+
title,
|
|
5319
|
+
url,
|
|
5320
|
+
snippet,
|
|
5321
|
+
...Object.keys(metadata).length > 0 ? { metadata } : {}
|
|
4497
5322
|
};
|
|
4498
5323
|
}
|
|
4499
|
-
function
|
|
4500
|
-
const
|
|
4501
|
-
|
|
4502
|
-
|
|
4503
|
-
|
|
4504
|
-
|
|
4505
|
-
|
|
4506
|
-
|
|
5324
|
+
function buildSearchContext(response) {
|
|
5325
|
+
const context = omitUndefined({
|
|
5326
|
+
searchParameters: asRecord3(response.searchParameters),
|
|
5327
|
+
searchInformation: asRecord3(response.searchInformation),
|
|
5328
|
+
credits: readNumber(response.credits),
|
|
5329
|
+
answerBox: asRecord3(response.answerBox),
|
|
5330
|
+
knowledgeGraph: asRecord3(response.knowledgeGraph),
|
|
5331
|
+
peopleAlsoAsk: asArray(response.peopleAlsoAsk),
|
|
5332
|
+
relatedSearches: asArray(response.relatedSearches),
|
|
5333
|
+
topStories: asArray(response.topStories),
|
|
5334
|
+
news: asArray(response.news),
|
|
5335
|
+
images: asArray(response.images),
|
|
5336
|
+
videos: asArray(response.videos),
|
|
5337
|
+
places: asArray(response.places)
|
|
4507
5338
|
});
|
|
5339
|
+
return Object.keys(context).length > 0 ? context : void 0;
|
|
4508
5340
|
}
|
|
4509
|
-
function
|
|
4510
|
-
|
|
4511
|
-
|
|
4512
|
-
|
|
4513
|
-
|
|
4514
|
-
|
|
4515
|
-
}
|
|
4516
|
-
return fallbackModel;
|
|
5341
|
+
function extractExtraMetadata(record, ignoredKeys) {
|
|
5342
|
+
return Object.fromEntries(
|
|
5343
|
+
Object.entries(record).filter(
|
|
5344
|
+
([key, value]) => !ignoredKeys.includes(key) && value !== void 0
|
|
5345
|
+
)
|
|
5346
|
+
);
|
|
4517
5347
|
}
|
|
4518
|
-
function
|
|
4519
|
-
|
|
4520
|
-
|
|
4521
|
-
|
|
4522
|
-
if (!Array.isArray(content)) {
|
|
4523
|
-
return "";
|
|
4524
|
-
}
|
|
4525
|
-
return content.flatMap((chunk) => {
|
|
4526
|
-
if (typeof chunk === "object" && chunk !== null && "type" in chunk && chunk.type === "text" && "text" in chunk && typeof chunk.text === "string") {
|
|
4527
|
-
return [chunk.text.trim()];
|
|
4528
|
-
}
|
|
4529
|
-
return [];
|
|
4530
|
-
}).filter((text) => text.length > 0).join("\n\n").trim();
|
|
5348
|
+
function omitUndefined(value) {
|
|
5349
|
+
return Object.fromEntries(
|
|
5350
|
+
Object.entries(value).filter(([, entry]) => entry !== void 0)
|
|
5351
|
+
);
|
|
4531
5352
|
}
|
|
4532
|
-
function
|
|
4533
|
-
|
|
4534
|
-
return content;
|
|
4535
|
-
}
|
|
4536
|
-
if (!Array.isArray(content)) {
|
|
4537
|
-
return "";
|
|
4538
|
-
}
|
|
4539
|
-
return content.flatMap((chunk) => {
|
|
4540
|
-
if (typeof chunk === "object" && chunk !== null && "type" in chunk && chunk.type === "text" && "text" in chunk && typeof chunk.text === "string") {
|
|
4541
|
-
return [chunk.text];
|
|
4542
|
-
}
|
|
4543
|
-
return [];
|
|
4544
|
-
}).join("");
|
|
5353
|
+
function asRecord3(value) {
|
|
5354
|
+
return typeof value === "object" && value !== null && !Array.isArray(value) ? value : void 0;
|
|
4545
5355
|
}
|
|
4546
|
-
function
|
|
4547
|
-
|
|
4548
|
-
const unique = [];
|
|
4549
|
-
for (const source of sources) {
|
|
4550
|
-
const title = source.title.trim() || source.url.trim() || "Untitled";
|
|
4551
|
-
const url = source.url.trim();
|
|
4552
|
-
if (!url) continue;
|
|
4553
|
-
const key = `${title.toLowerCase()}::${url.toLowerCase()}`;
|
|
4554
|
-
if (seen.has(key)) continue;
|
|
4555
|
-
seen.add(key);
|
|
4556
|
-
unique.push({ title, url });
|
|
4557
|
-
}
|
|
4558
|
-
return unique;
|
|
5356
|
+
function asArray(value) {
|
|
5357
|
+
return Array.isArray(value) ? value : void 0;
|
|
4559
5358
|
}
|
|
4560
|
-
function
|
|
4561
|
-
|
|
4562
|
-
const url = result.url?.trim() ?? "";
|
|
4563
|
-
if (!url) {
|
|
4564
|
-
return [];
|
|
4565
|
-
}
|
|
4566
|
-
return [{ title: result.title?.trim() ?? url, url }];
|
|
4567
|
-
}) ?? [];
|
|
4568
|
-
if (searchResults.length > 0) {
|
|
4569
|
-
return searchResults;
|
|
4570
|
-
}
|
|
4571
|
-
return response.citations?.flatMap((citation) => {
|
|
4572
|
-
const url = citation?.trim() ?? "";
|
|
4573
|
-
return url ? [{ title: url, url }] : [];
|
|
4574
|
-
}) ?? [];
|
|
5359
|
+
function readString4(value) {
|
|
5360
|
+
return typeof value === "string" ? value : void 0;
|
|
4575
5361
|
}
|
|
4576
|
-
function
|
|
4577
|
-
return
|
|
5362
|
+
function readNumber(value) {
|
|
5363
|
+
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
4578
5364
|
}
|
|
4579
5365
|
|
|
4580
5366
|
// src/providers/tavily.ts
|
|
4581
|
-
import { Type as
|
|
5367
|
+
import { Type as Type14 } from "@sinclair/typebox";
|
|
4582
5368
|
import {
|
|
4583
5369
|
tavily
|
|
4584
5370
|
} from "@tavily/core";
|
|
4585
|
-
var tavilySearchOptionsSchema =
|
|
5371
|
+
var tavilySearchOptionsSchema = Type14.Object(
|
|
4586
5372
|
{
|
|
4587
|
-
topic:
|
|
5373
|
+
topic: Type14.Optional(
|
|
4588
5374
|
literalUnion(["general", "news", "finance"], {
|
|
4589
5375
|
description: "Category of the search query."
|
|
4590
5376
|
})
|
|
4591
5377
|
),
|
|
4592
|
-
searchDepth:
|
|
5378
|
+
searchDepth: Type14.Optional(
|
|
4593
5379
|
literalUnion(["basic", "advanced"], {
|
|
4594
5380
|
description: "Depth of the search. 'advanced' is slower but more thorough."
|
|
4595
5381
|
})
|
|
4596
5382
|
),
|
|
4597
|
-
timeRange:
|
|
4598
|
-
|
|
5383
|
+
timeRange: Type14.Optional(
|
|
5384
|
+
Type14.String({ description: "Named time range filter." })
|
|
4599
5385
|
),
|
|
4600
|
-
country:
|
|
4601
|
-
|
|
5386
|
+
country: Type14.Optional(
|
|
5387
|
+
Type14.String({ description: "Country hint for search results." })
|
|
4602
5388
|
),
|
|
4603
|
-
exactMatch:
|
|
4604
|
-
|
|
5389
|
+
exactMatch: Type14.Optional(
|
|
5390
|
+
Type14.Boolean({ description: "Prefer exact matches." })
|
|
4605
5391
|
),
|
|
4606
|
-
includeAnswer:
|
|
4607
|
-
|
|
5392
|
+
includeAnswer: Type14.Optional(
|
|
5393
|
+
Type14.Boolean({ description: "Include a short AI-generated answer." })
|
|
4608
5394
|
),
|
|
4609
|
-
includeRawContent:
|
|
4610
|
-
|
|
5395
|
+
includeRawContent: Type14.Optional(
|
|
5396
|
+
Type14.Boolean({ description: "Include raw page content in results." })
|
|
4611
5397
|
),
|
|
4612
|
-
includeImages:
|
|
4613
|
-
|
|
5398
|
+
includeImages: Type14.Optional(
|
|
5399
|
+
Type14.Boolean({ description: "Include related images." })
|
|
4614
5400
|
),
|
|
4615
|
-
includeFavicon:
|
|
4616
|
-
|
|
5401
|
+
includeFavicon: Type14.Optional(
|
|
5402
|
+
Type14.Boolean({ description: "Include favicon URLs." })
|
|
4617
5403
|
),
|
|
4618
|
-
includeDomains:
|
|
4619
|
-
|
|
5404
|
+
includeDomains: Type14.Optional(
|
|
5405
|
+
Type14.Array(Type14.String(), {
|
|
4620
5406
|
description: "Restrict results to these domains."
|
|
4621
5407
|
})
|
|
4622
5408
|
),
|
|
4623
|
-
excludeDomains:
|
|
4624
|
-
|
|
5409
|
+
excludeDomains: Type14.Optional(
|
|
5410
|
+
Type14.Array(Type14.String(), {
|
|
4625
5411
|
description: "Exclude these domains from results."
|
|
4626
5412
|
})
|
|
4627
5413
|
),
|
|
4628
|
-
days:
|
|
4629
|
-
|
|
5414
|
+
days: Type14.Optional(
|
|
5415
|
+
Type14.Integer({
|
|
4630
5416
|
minimum: 1,
|
|
4631
5417
|
description: "Limit results to the last N days."
|
|
4632
5418
|
})
|
|
@@ -4634,27 +5420,27 @@ var tavilySearchOptionsSchema = Type12.Object(
|
|
|
4634
5420
|
},
|
|
4635
5421
|
{ description: "Tavily search options." }
|
|
4636
5422
|
);
|
|
4637
|
-
var tavilyExtractOptionsSchema =
|
|
5423
|
+
var tavilyExtractOptionsSchema = Type14.Object(
|
|
4638
5424
|
{
|
|
4639
|
-
extractDepth:
|
|
4640
|
-
|
|
5425
|
+
extractDepth: Type14.Optional(
|
|
5426
|
+
Type14.String({ description: "Depth setting for extraction." })
|
|
4641
5427
|
),
|
|
4642
|
-
format:
|
|
5428
|
+
format: Type14.Optional(
|
|
4643
5429
|
literalUnion(["markdown", "text"], {
|
|
4644
5430
|
description: "Output format for extracted content."
|
|
4645
5431
|
})
|
|
4646
5432
|
),
|
|
4647
|
-
includeImages:
|
|
4648
|
-
|
|
5433
|
+
includeImages: Type14.Optional(
|
|
5434
|
+
Type14.Boolean({ description: "Include extracted images." })
|
|
4649
5435
|
),
|
|
4650
|
-
query:
|
|
4651
|
-
|
|
5436
|
+
query: Type14.Optional(
|
|
5437
|
+
Type14.String({ description: "Optional query to focus extraction." })
|
|
4652
5438
|
),
|
|
4653
|
-
chunksPerSource:
|
|
4654
|
-
|
|
5439
|
+
chunksPerSource: Type14.Optional(
|
|
5440
|
+
Type14.Integer({ minimum: 1, description: "Maximum chunks per source." })
|
|
4655
5441
|
),
|
|
4656
|
-
includeFavicon:
|
|
4657
|
-
|
|
5442
|
+
includeFavicon: Type14.Optional(
|
|
5443
|
+
Type14.Boolean({ description: "Include favicon URLs." })
|
|
4658
5444
|
)
|
|
4659
5445
|
},
|
|
4660
5446
|
{ description: "Tavily extract options." }
|
|
@@ -4739,7 +5525,7 @@ var tavilyAdapter = {
|
|
|
4739
5525
|
});
|
|
4740
5526
|
},
|
|
4741
5527
|
async search(query2, maxResults, config, _context, options) {
|
|
4742
|
-
const client =
|
|
5528
|
+
const client = createClient8(config);
|
|
4743
5529
|
const defaults = stripLocalExecutionOptions(asJsonObject(config.options?.search)) ?? {};
|
|
4744
5530
|
const response = await client.search(query2, {
|
|
4745
5531
|
...defaults,
|
|
@@ -4758,7 +5544,7 @@ var tavilyAdapter = {
|
|
|
4758
5544
|
};
|
|
4759
5545
|
},
|
|
4760
5546
|
async contents(urls, config, _context, options) {
|
|
4761
|
-
const client =
|
|
5547
|
+
const client = createClient8(config);
|
|
4762
5548
|
const defaults = stripLocalExecutionOptions(asJsonObject(config.options?.extract)) ?? {};
|
|
4763
5549
|
const response = await client.extract(urls, {
|
|
4764
5550
|
...defaults,
|
|
@@ -4796,7 +5582,7 @@ var tavilyAdapter = {
|
|
|
4796
5582
|
};
|
|
4797
5583
|
}
|
|
4798
5584
|
};
|
|
4799
|
-
function
|
|
5585
|
+
function createClient8(config) {
|
|
4800
5586
|
const apiKey = resolveConfigValue(config.apiKey);
|
|
4801
5587
|
if (!apiKey) {
|
|
4802
5588
|
throw new Error("is missing an API key");
|
|
@@ -4828,48 +5614,48 @@ function buildExtractMetadata(response, result) {
|
|
|
4828
5614
|
}
|
|
4829
5615
|
|
|
4830
5616
|
// src/providers/valyu.ts
|
|
4831
|
-
import { Type as
|
|
5617
|
+
import { Type as Type15 } from "@sinclair/typebox";
|
|
4832
5618
|
import { Valyu as ValyuClient } from "valyu-js";
|
|
4833
|
-
var valyuSearchOptionsSchema =
|
|
5619
|
+
var valyuSearchOptionsSchema = Type15.Object(
|
|
4834
5620
|
{
|
|
4835
|
-
searchType:
|
|
5621
|
+
searchType: Type15.Optional(
|
|
4836
5622
|
literalUnion(["all", "web", "proprietary", "news"], {
|
|
4837
5623
|
description: "Valyu search type."
|
|
4838
5624
|
})
|
|
4839
5625
|
),
|
|
4840
|
-
responseLength:
|
|
5626
|
+
responseLength: Type15.Optional(
|
|
4841
5627
|
literalUnion(["short", "medium", "large", "max"], {
|
|
4842
5628
|
description: "Response length."
|
|
4843
5629
|
})
|
|
4844
5630
|
),
|
|
4845
|
-
countryCode:
|
|
4846
|
-
|
|
5631
|
+
countryCode: Type15.Optional(
|
|
5632
|
+
Type15.String({ description: "Country code to scope search results." })
|
|
4847
5633
|
)
|
|
4848
5634
|
},
|
|
4849
5635
|
{ description: "Valyu search options." }
|
|
4850
5636
|
);
|
|
4851
|
-
var valyuAnswerOptionsSchema =
|
|
5637
|
+
var valyuAnswerOptionsSchema = Type15.Object(
|
|
4852
5638
|
{
|
|
4853
|
-
responseLength:
|
|
5639
|
+
responseLength: Type15.Optional(
|
|
4854
5640
|
literalUnion(["short", "medium", "large", "max"], {
|
|
4855
5641
|
description: "Response length for answers."
|
|
4856
5642
|
})
|
|
4857
5643
|
),
|
|
4858
|
-
countryCode:
|
|
4859
|
-
|
|
5644
|
+
countryCode: Type15.Optional(
|
|
5645
|
+
Type15.String({ description: "Country code to scope answer results." })
|
|
4860
5646
|
)
|
|
4861
5647
|
},
|
|
4862
5648
|
{ description: "Valyu answer options." }
|
|
4863
5649
|
);
|
|
4864
|
-
var valyuResearchOptionsSchema =
|
|
5650
|
+
var valyuResearchOptionsSchema = Type15.Object(
|
|
4865
5651
|
{
|
|
4866
|
-
responseLength:
|
|
5652
|
+
responseLength: Type15.Optional(
|
|
4867
5653
|
literalUnion(["short", "medium", "large", "max"], {
|
|
4868
5654
|
description: "Response length for research."
|
|
4869
5655
|
})
|
|
4870
5656
|
),
|
|
4871
|
-
countryCode:
|
|
4872
|
-
|
|
5657
|
+
countryCode: Type15.Optional(
|
|
5658
|
+
Type15.String({ description: "Country code to scope research results." })
|
|
4873
5659
|
)
|
|
4874
5660
|
},
|
|
4875
5661
|
{ description: "Valyu research options." }
|
|
@@ -4982,7 +5768,7 @@ var valyuAdapter = {
|
|
|
4982
5768
|
});
|
|
4983
5769
|
},
|
|
4984
5770
|
async search(query2, maxResults, config, _context, searchOptions) {
|
|
4985
|
-
const client =
|
|
5771
|
+
const client = createClient9(config);
|
|
4986
5772
|
const options = {
|
|
4987
5773
|
...stripLocalExecutionOptions(asJsonObject(config.options?.search)) ?? {},
|
|
4988
5774
|
...searchOptions ?? {},
|
|
@@ -5005,7 +5791,7 @@ var valyuAdapter = {
|
|
|
5005
5791
|
};
|
|
5006
5792
|
},
|
|
5007
5793
|
async contents(urls, config, _context, options) {
|
|
5008
|
-
const client =
|
|
5794
|
+
const client = createClient9(config);
|
|
5009
5795
|
const response = await client.contents(urls, options);
|
|
5010
5796
|
const finalResponse = "jobId" in response ? await client.waitForJob(response.jobId, {}) : response;
|
|
5011
5797
|
if (!finalResponse.success) {
|
|
@@ -5039,7 +5825,7 @@ var valyuAdapter = {
|
|
|
5039
5825
|
};
|
|
5040
5826
|
},
|
|
5041
5827
|
async answer(query2, config, _context, options) {
|
|
5042
|
-
const client =
|
|
5828
|
+
const client = createClient9(config);
|
|
5043
5829
|
const response = await client.answer(query2, {
|
|
5044
5830
|
...stripLocalExecutionOptions(asJsonObject(config.options?.answer)) ?? {},
|
|
5045
5831
|
...options ?? {},
|
|
@@ -5078,7 +5864,7 @@ var valyuAdapter = {
|
|
|
5078
5864
|
});
|
|
5079
5865
|
},
|
|
5080
5866
|
async startResearch(input, config, _context, options) {
|
|
5081
|
-
const client =
|
|
5867
|
+
const client = createClient9(config);
|
|
5082
5868
|
const task = await client.deepresearch.create({
|
|
5083
5869
|
input,
|
|
5084
5870
|
...stripLocalExecutionOptions(asJsonObject(config.options?.research)) ?? {},
|
|
@@ -5090,7 +5876,7 @@ var valyuAdapter = {
|
|
|
5090
5876
|
return { id: task.deepresearch_id };
|
|
5091
5877
|
},
|
|
5092
5878
|
async pollResearch(id, config, _context, _options) {
|
|
5093
|
-
const client =
|
|
5879
|
+
const client = createClient9(config);
|
|
5094
5880
|
const result = await client.deepresearch.status(id);
|
|
5095
5881
|
if (!result.success) {
|
|
5096
5882
|
throw new Error(result.error || "deep research failed");
|
|
@@ -5133,7 +5919,7 @@ var valyuAdapter = {
|
|
|
5133
5919
|
return { status: "in_progress" };
|
|
5134
5920
|
}
|
|
5135
5921
|
};
|
|
5136
|
-
function
|
|
5922
|
+
function createClient9(config) {
|
|
5137
5923
|
const apiKey = resolveConfigValue(config.apiKey);
|
|
5138
5924
|
if (!apiKey) {
|
|
5139
5925
|
throw new Error("is missing an API key");
|
|
@@ -5144,15 +5930,17 @@ function createClient8(config) {
|
|
|
5144
5930
|
// src/providers/index.ts
|
|
5145
5931
|
var ADAPTERS_BY_ID = {
|
|
5146
5932
|
claude: claudeAdapter,
|
|
5147
|
-
cloudflare: cloudflareAdapter,
|
|
5148
5933
|
codex: codexAdapter,
|
|
5934
|
+
cloudflare: cloudflareAdapter,
|
|
5149
5935
|
custom: customAdapter,
|
|
5150
5936
|
exa: exaAdapter,
|
|
5151
5937
|
firecrawl: firecrawlAdapter,
|
|
5152
5938
|
gemini: geminiAdapter,
|
|
5153
5939
|
linkup: linkupAdapter,
|
|
5154
|
-
|
|
5940
|
+
openai: openaiAdapter,
|
|
5155
5941
|
parallel: parallelAdapter,
|
|
5942
|
+
perplexity: perplexityAdapter,
|
|
5943
|
+
serper: serperAdapter,
|
|
5156
5944
|
tavily: tavilyAdapter,
|
|
5157
5945
|
valyu: valyuAdapter
|
|
5158
5946
|
};
|
|
@@ -6226,8 +7014,7 @@ var PROVIDER_CONFIG_MANIFESTS = {
|
|
|
6226
7014
|
setValue: (config, value) => {
|
|
6227
7015
|
setCustomEnv(config, "research", value);
|
|
6228
7016
|
}
|
|
6229
|
-
})
|
|
6230
|
-
...requestSettings("custom")
|
|
7017
|
+
})
|
|
6231
7018
|
]
|
|
6232
7019
|
},
|
|
6233
7020
|
exa: {
|
|
@@ -6250,7 +7037,7 @@ var PROVIDER_CONFIG_MANIFESTS = {
|
|
|
6250
7037
|
"deep-reasoning",
|
|
6251
7038
|
"deep-max"
|
|
6252
7039
|
],
|
|
6253
|
-
getValue: (config) =>
|
|
7040
|
+
getValue: (config) => readString5(getExaSearchOptions(config)?.type) ?? "default",
|
|
6254
7041
|
setValue: (config, value) => {
|
|
6255
7042
|
const options = ensureExaSearchOptions(config);
|
|
6256
7043
|
if (value === "default") {
|
|
@@ -6355,10 +7142,111 @@ var PROVIDER_CONFIG_MANIFESTS = {
|
|
|
6355
7142
|
]
|
|
6356
7143
|
},
|
|
6357
7144
|
linkup: {
|
|
7145
|
+
settings: [apiKeySetting(), baseUrlSetting()]
|
|
7146
|
+
},
|
|
7147
|
+
openai: {
|
|
6358
7148
|
settings: [
|
|
6359
7149
|
apiKeySetting(),
|
|
6360
7150
|
baseUrlSetting(),
|
|
6361
|
-
|
|
7151
|
+
stringSetting({
|
|
7152
|
+
id: "openaiSearchModel",
|
|
7153
|
+
label: "Search model",
|
|
7154
|
+
help: "Model used for OpenAI web search runs.",
|
|
7155
|
+
getValue: (config) => getOpenAISearchOptions(config)?.model,
|
|
7156
|
+
setValue: (config, value) => {
|
|
7157
|
+
assignOptionalString(
|
|
7158
|
+
ensureOpenAISearchOptions(config),
|
|
7159
|
+
"model",
|
|
7160
|
+
value
|
|
7161
|
+
);
|
|
7162
|
+
cleanupCapabilityOptions(config, ["search", "answer", "research"]);
|
|
7163
|
+
}
|
|
7164
|
+
}),
|
|
7165
|
+
stringSetting({
|
|
7166
|
+
id: "openaiSearchInstructions",
|
|
7167
|
+
label: "Search instructions",
|
|
7168
|
+
help: "Optional default instructions for OpenAI web search runs.",
|
|
7169
|
+
getValue: (config) => getOpenAISearchOptions(config)?.instructions,
|
|
7170
|
+
setValue: (config, value) => {
|
|
7171
|
+
assignOptionalString(
|
|
7172
|
+
ensureOpenAISearchOptions(config),
|
|
7173
|
+
"instructions",
|
|
7174
|
+
value
|
|
7175
|
+
);
|
|
7176
|
+
cleanupCapabilityOptions(config, ["search", "answer", "research"]);
|
|
7177
|
+
}
|
|
7178
|
+
}),
|
|
7179
|
+
stringSetting({
|
|
7180
|
+
id: "openaiAnswerModel",
|
|
7181
|
+
label: "Answer model",
|
|
7182
|
+
help: "Model used for OpenAI grounded answers.",
|
|
7183
|
+
getValue: (config) => getOpenAIAnswerOptions(config)?.model,
|
|
7184
|
+
setValue: (config, value) => {
|
|
7185
|
+
assignOptionalString(
|
|
7186
|
+
ensureOpenAIAnswerOptions(config),
|
|
7187
|
+
"model",
|
|
7188
|
+
value
|
|
7189
|
+
);
|
|
7190
|
+
cleanupCapabilityOptions(config, ["search", "answer", "research"]);
|
|
7191
|
+
}
|
|
7192
|
+
}),
|
|
7193
|
+
stringSetting({
|
|
7194
|
+
id: "openaiAnswerInstructions",
|
|
7195
|
+
label: "Answer instructions",
|
|
7196
|
+
help: "Optional default instructions for OpenAI grounded answers.",
|
|
7197
|
+
getValue: (config) => getOpenAIAnswerOptions(config)?.instructions,
|
|
7198
|
+
setValue: (config, value) => {
|
|
7199
|
+
assignOptionalString(
|
|
7200
|
+
ensureOpenAIAnswerOptions(config),
|
|
7201
|
+
"instructions",
|
|
7202
|
+
value
|
|
7203
|
+
);
|
|
7204
|
+
cleanupCapabilityOptions(config, ["search", "answer", "research"]);
|
|
7205
|
+
}
|
|
7206
|
+
}),
|
|
7207
|
+
stringSetting({
|
|
7208
|
+
id: "openaiResearchModel",
|
|
7209
|
+
label: "Research model",
|
|
7210
|
+
help: "Model used for OpenAI deep research runs.",
|
|
7211
|
+
getValue: (config) => getOpenAIResearchOptions(config)?.model,
|
|
7212
|
+
setValue: (config, value) => {
|
|
7213
|
+
assignOptionalString(
|
|
7214
|
+
ensureOpenAIResearchOptions(config),
|
|
7215
|
+
"model",
|
|
7216
|
+
value
|
|
7217
|
+
);
|
|
7218
|
+
cleanupCapabilityOptions(config, ["search", "answer", "research"]);
|
|
7219
|
+
}
|
|
7220
|
+
}),
|
|
7221
|
+
stringSetting({
|
|
7222
|
+
id: "openaiResearchInstructions",
|
|
7223
|
+
label: "Research instructions",
|
|
7224
|
+
help: "Optional default instructions for OpenAI deep research runs.",
|
|
7225
|
+
getValue: (config) => getOpenAIResearchOptions(config)?.instructions,
|
|
7226
|
+
setValue: (config, value) => {
|
|
7227
|
+
assignOptionalString(
|
|
7228
|
+
ensureOpenAIResearchOptions(config),
|
|
7229
|
+
"instructions",
|
|
7230
|
+
value
|
|
7231
|
+
);
|
|
7232
|
+
cleanupCapabilityOptions(config, ["search", "answer", "research"]);
|
|
7233
|
+
}
|
|
7234
|
+
}),
|
|
7235
|
+
stringSetting({
|
|
7236
|
+
id: "openaiResearchMaxToolCalls",
|
|
7237
|
+
label: "Research max tool calls",
|
|
7238
|
+
help: "Optional default maximum number of built-in tool calls for OpenAI deep research runs.",
|
|
7239
|
+
getValue: (config) => getIntegerString(getOpenAIResearchOptions(config)?.max_tool_calls),
|
|
7240
|
+
setValue: (config, value) => {
|
|
7241
|
+
assignOptionalInteger(
|
|
7242
|
+
ensureOpenAIResearchOptions(config),
|
|
7243
|
+
"max_tool_calls",
|
|
7244
|
+
value,
|
|
7245
|
+
"OpenAI research max tool calls must be a positive integer."
|
|
7246
|
+
);
|
|
7247
|
+
cleanupCapabilityOptions(config, ["search", "answer", "research"]);
|
|
7248
|
+
}
|
|
7249
|
+
})
|
|
6362
7250
|
]
|
|
6363
7251
|
},
|
|
6364
7252
|
perplexity: {
|
|
@@ -6373,7 +7261,7 @@ var PROVIDER_CONFIG_MANIFESTS = {
|
|
|
6373
7261
|
label: "Search mode",
|
|
6374
7262
|
help: "Parallel search mode. 'default' uses the SDK default.",
|
|
6375
7263
|
values: ["default", "agentic", "one-shot"],
|
|
6376
|
-
getValue: (config) =>
|
|
7264
|
+
getValue: (config) => readString5(getParallelOptions(config)?.search?.mode) ?? "default",
|
|
6377
7265
|
setValue: (config, value) => {
|
|
6378
7266
|
const options = ensureParallelOptions(config);
|
|
6379
7267
|
options.search = asJsonObject2(options.search) ?? {};
|
|
@@ -6427,12 +7315,11 @@ var PROVIDER_CONFIG_MANIFESTS = {
|
|
|
6427
7315
|
})
|
|
6428
7316
|
]
|
|
6429
7317
|
},
|
|
7318
|
+
serper: {
|
|
7319
|
+
settings: [apiKeySetting(), baseUrlSetting()]
|
|
7320
|
+
},
|
|
6430
7321
|
tavily: {
|
|
6431
|
-
settings: [
|
|
6432
|
-
apiKeySetting(),
|
|
6433
|
-
baseUrlSetting(),
|
|
6434
|
-
...requestSettings("tavily")
|
|
6435
|
-
]
|
|
7322
|
+
settings: [apiKeySetting(), baseUrlSetting()]
|
|
6436
7323
|
},
|
|
6437
7324
|
valyu: {
|
|
6438
7325
|
settings: [
|
|
@@ -6443,7 +7330,7 @@ var PROVIDER_CONFIG_MANIFESTS = {
|
|
|
6443
7330
|
label: "Search type",
|
|
6444
7331
|
help: "Valyu search type. 'default' uses the SDK default.",
|
|
6445
7332
|
values: ["default", "all", "web", "proprietary", "news"],
|
|
6446
|
-
getValue: (config) =>
|
|
7333
|
+
getValue: (config) => readString5(getValyuCapabilityOptions(config, "search")?.searchType) ?? "default",
|
|
6447
7334
|
setValue: (config, value) => {
|
|
6448
7335
|
const options = ensureValyuCapabilityOptions(config, "search");
|
|
6449
7336
|
if (value === "default") {
|
|
@@ -6459,7 +7346,7 @@ var PROVIDER_CONFIG_MANIFESTS = {
|
|
|
6459
7346
|
label: "Search response length",
|
|
6460
7347
|
help: "Valyu search response length. 'default' uses the SDK default.",
|
|
6461
7348
|
values: ["default", "short", "medium", "large", "max"],
|
|
6462
|
-
getValue: (config) =>
|
|
7349
|
+
getValue: (config) => readString5(
|
|
6463
7350
|
getValyuCapabilityOptions(config, "search")?.responseLength
|
|
6464
7351
|
) ?? "default",
|
|
6465
7352
|
setValue: (config, value) => {
|
|
@@ -6471,7 +7358,7 @@ var PROVIDER_CONFIG_MANIFESTS = {
|
|
|
6471
7358
|
label: "Answer response length",
|
|
6472
7359
|
help: "Valyu answer response length. 'default' uses the SDK default.",
|
|
6473
7360
|
values: ["default", "short", "medium", "large", "max"],
|
|
6474
|
-
getValue: (config) =>
|
|
7361
|
+
getValue: (config) => readString5(
|
|
6475
7362
|
getValyuCapabilityOptions(config, "answer")?.responseLength
|
|
6476
7363
|
) ?? "default",
|
|
6477
7364
|
setValue: (config, value) => {
|
|
@@ -6483,7 +7370,7 @@ var PROVIDER_CONFIG_MANIFESTS = {
|
|
|
6483
7370
|
label: "Research response length",
|
|
6484
7371
|
help: "Valyu research response length. 'default' uses the SDK default.",
|
|
6485
7372
|
values: ["default", "short", "medium", "large", "max"],
|
|
6486
|
-
getValue: (config) =>
|
|
7373
|
+
getValue: (config) => readString5(
|
|
6487
7374
|
getValyuCapabilityOptions(config, "research")?.responseLength
|
|
6488
7375
|
) ?? "default",
|
|
6489
7376
|
setValue: (config, value) => {
|
|
@@ -6539,88 +7426,20 @@ function baseUrlSetting() {
|
|
|
6539
7426
|
}
|
|
6540
7427
|
});
|
|
6541
7428
|
}
|
|
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
7429
|
function assignOptionalString(target, key, value) {
|
|
7430
|
+
const record = target;
|
|
6613
7431
|
const trimmed = value.trim();
|
|
6614
7432
|
if (!trimmed) {
|
|
6615
|
-
delete
|
|
7433
|
+
delete record[key];
|
|
6616
7434
|
} else {
|
|
6617
|
-
|
|
7435
|
+
record[key] = trimmed;
|
|
6618
7436
|
}
|
|
6619
7437
|
}
|
|
6620
7438
|
function assignOptionalInteger(target, key, value, errorMessage, options) {
|
|
7439
|
+
const record = target;
|
|
6621
7440
|
const trimmed = value.trim();
|
|
6622
7441
|
if (!trimmed) {
|
|
6623
|
-
delete
|
|
7442
|
+
delete record[key];
|
|
6624
7443
|
return;
|
|
6625
7444
|
}
|
|
6626
7445
|
const parsed = Number(trimmed);
|
|
@@ -6628,7 +7447,7 @@ function assignOptionalInteger(target, key, value, errorMessage, options) {
|
|
|
6628
7447
|
if (!Number.isInteger(parsed) || parsed < minimum) {
|
|
6629
7448
|
throw new Error(errorMessage);
|
|
6630
7449
|
}
|
|
6631
|
-
|
|
7450
|
+
record[key] = parsed;
|
|
6632
7451
|
}
|
|
6633
7452
|
function assignOptionalBoolean(target, key, value) {
|
|
6634
7453
|
if (value === "default") {
|
|
@@ -6643,16 +7462,12 @@ function getIntegerString(value) {
|
|
|
6643
7462
|
function getBooleanValue(value) {
|
|
6644
7463
|
return typeof value === "boolean" ? String(value) : "default";
|
|
6645
7464
|
}
|
|
6646
|
-
function
|
|
7465
|
+
function readString5(value) {
|
|
6647
7466
|
return typeof value === "string" ? value : void 0;
|
|
6648
7467
|
}
|
|
6649
7468
|
function asJsonObject2(value) {
|
|
6650
7469
|
return typeof value === "object" && value !== null && !Array.isArray(value) ? value : void 0;
|
|
6651
7470
|
}
|
|
6652
|
-
function ensureSettings(config) {
|
|
6653
|
-
config.settings = { ...config.settings ?? {} };
|
|
6654
|
-
return config.settings;
|
|
6655
|
-
}
|
|
6656
7471
|
function cleanupEmpty(config, key) {
|
|
6657
7472
|
const value = asJsonObject2(config[key]);
|
|
6658
7473
|
if (value && Object.keys(value).length === 0) {
|
|
@@ -6817,6 +7632,36 @@ function ensureExaSearchOptions(config) {
|
|
|
6817
7632
|
};
|
|
6818
7633
|
return config.options.search;
|
|
6819
7634
|
}
|
|
7635
|
+
function getOpenAISearchOptions(config) {
|
|
7636
|
+
return config?.options?.search;
|
|
7637
|
+
}
|
|
7638
|
+
function ensureOpenAISearchOptions(config) {
|
|
7639
|
+
config.options = {
|
|
7640
|
+
...config.options ?? {},
|
|
7641
|
+
search: { ...config.options?.search ?? {} }
|
|
7642
|
+
};
|
|
7643
|
+
return config.options.search ?? (config.options.search = {});
|
|
7644
|
+
}
|
|
7645
|
+
function getOpenAIAnswerOptions(config) {
|
|
7646
|
+
return config?.options?.answer;
|
|
7647
|
+
}
|
|
7648
|
+
function ensureOpenAIAnswerOptions(config) {
|
|
7649
|
+
config.options = {
|
|
7650
|
+
...config.options ?? {},
|
|
7651
|
+
answer: { ...config.options?.answer ?? {} }
|
|
7652
|
+
};
|
|
7653
|
+
return config.options.answer ?? (config.options.answer = {});
|
|
7654
|
+
}
|
|
7655
|
+
function getOpenAIResearchOptions(config) {
|
|
7656
|
+
return config?.options?.research;
|
|
7657
|
+
}
|
|
7658
|
+
function ensureOpenAIResearchOptions(config) {
|
|
7659
|
+
config.options = {
|
|
7660
|
+
...config.options ?? {},
|
|
7661
|
+
research: { ...config.options?.research ?? {} }
|
|
7662
|
+
};
|
|
7663
|
+
return config.options.research ?? (config.options.research = {});
|
|
7664
|
+
}
|
|
6820
7665
|
function getValyuCapabilityOptions(config, capability) {
|
|
6821
7666
|
return config?.options?.[capability];
|
|
6822
7667
|
}
|
|
@@ -6992,14 +7837,14 @@ function registerWebSearchTool(pi, providerIds) {
|
|
|
6992
7837
|
promptGuidelines: [
|
|
6993
7838
|
"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
7839
|
],
|
|
6995
|
-
parameters:
|
|
6996
|
-
queries:
|
|
7840
|
+
parameters: Type16.Object({
|
|
7841
|
+
queries: Type16.Array(Type16.String({ minLength: 1 }), {
|
|
6997
7842
|
minItems: 1,
|
|
6998
7843
|
maxItems: MAX_SEARCH_QUERIES,
|
|
6999
7844
|
description: `One or more search queries to run in one call (max ${MAX_SEARCH_QUERIES})`
|
|
7000
7845
|
}),
|
|
7001
|
-
maxResults:
|
|
7002
|
-
|
|
7846
|
+
maxResults: Type16.Optional(
|
|
7847
|
+
Type16.Integer({
|
|
7003
7848
|
minimum: 1,
|
|
7004
7849
|
maximum: MAX_ALLOWED_RESULTS,
|
|
7005
7850
|
description: `Maximum number of results to return (default: ${DEFAULT_MAX_RESULTS})`
|
|
@@ -7048,8 +7893,8 @@ function registerWebContentsTool(pi, providerIds) {
|
|
|
7048
7893
|
name: "web_contents",
|
|
7049
7894
|
label: "Web Contents",
|
|
7050
7895
|
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:
|
|
7896
|
+
parameters: Type16.Object({
|
|
7897
|
+
urls: Type16.Array(Type16.String({ minLength: 1 }), {
|
|
7053
7898
|
minItems: 1,
|
|
7054
7899
|
description: "One or more URLs to extract"
|
|
7055
7900
|
}),
|
|
@@ -7099,8 +7944,8 @@ function registerWebAnswerTool(pi, providerIds) {
|
|
|
7099
7944
|
name: "web_answer",
|
|
7100
7945
|
label: "Web Answer",
|
|
7101
7946
|
description: `Answer one or more questions using web-grounded evidence (up to ${MAX_SEARCH_QUERIES} per call).`,
|
|
7102
|
-
parameters:
|
|
7103
|
-
queries:
|
|
7947
|
+
parameters: Type16.Object({
|
|
7948
|
+
queries: Type16.Array(Type16.String({ minLength: 1 }), {
|
|
7104
7949
|
minItems: 1,
|
|
7105
7950
|
maxItems: MAX_SEARCH_QUERIES,
|
|
7106
7951
|
description: `One or more questions to answer in one call (max ${MAX_SEARCH_QUERIES})`
|
|
@@ -7154,8 +7999,8 @@ function registerWebResearchTool(pi, webResearchLifecycle, providerIds) {
|
|
|
7154
7999
|
name: "web_research",
|
|
7155
8000
|
label: "Web Research",
|
|
7156
8001
|
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:
|
|
8002
|
+
parameters: Type16.Object({
|
|
8003
|
+
input: Type16.String({ description: "Research brief or question" }),
|
|
7159
8004
|
...optionalField(
|
|
7160
8005
|
"options",
|
|
7161
8006
|
buildStructuredOptionsSchema("research", selectedProviderId)
|
|
@@ -7298,7 +8143,7 @@ function optionalField(name, schema) {
|
|
|
7298
8143
|
function buildStructuredOptionsSchema(capability, providerId) {
|
|
7299
8144
|
const providerSchema = resolveProviderOptionsSchema(capability, providerId);
|
|
7300
8145
|
const schema = buildToolOptionsSchema(capability, providerSchema);
|
|
7301
|
-
return schema ?
|
|
8146
|
+
return schema ? Type16.Optional(schema) : void 0;
|
|
7302
8147
|
}
|
|
7303
8148
|
function resolveProviderOptionsSchema(capability, providerId) {
|
|
7304
8149
|
if (!providerId) {
|
|
@@ -8606,7 +9451,7 @@ function getSharedSettingRawValue(config, id) {
|
|
|
8606
9451
|
const value = config.settings?.[id];
|
|
8607
9452
|
return typeof value === "number" ? String(value) : "";
|
|
8608
9453
|
}
|
|
8609
|
-
function
|
|
9454
|
+
function ensureSettings(config) {
|
|
8610
9455
|
config.settings = { ...config.settings ?? {} };
|
|
8611
9456
|
return config.settings;
|
|
8612
9457
|
}
|
|
@@ -8951,7 +9796,7 @@ var WebProvidersSettingsView = class {
|
|
|
8951
9796
|
async handleSharedSettingChange(id, value) {
|
|
8952
9797
|
await this.persist((config) => {
|
|
8953
9798
|
const parsed = SETTING_META[id].parse(value);
|
|
8954
|
-
const settings =
|
|
9799
|
+
const settings = ensureSettings(config);
|
|
8955
9800
|
if (parsed === void 0) {
|
|
8956
9801
|
delete settings[id];
|
|
8957
9802
|
} else {
|