pi-web-providers 2.0.0 → 2.1.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 +16 -1
- package/dist/index.js +252 -27
- package/package.json +20 -18
package/README.md
CHANGED
|
@@ -13,7 +13,7 @@ off entirely.
|
|
|
13
13
|
## ✨ Features
|
|
14
14
|
|
|
15
15
|
- **Multiple providers**: Claude, Cloudflare, Codex, Exa, Firecrawl,
|
|
16
|
-
Gemini, Perplexity, Parallel, [Tavily](https://tavily.com), Valyu
|
|
16
|
+
Gemini, Linkup, Perplexity, Parallel, [Tavily](https://tavily.com), Valyu
|
|
17
17
|
- **Batched search and answers**: run several related queries in a single
|
|
18
18
|
`web_search` or `web_answer` call and get grouped results back in one response
|
|
19
19
|
- **Async contents prefetch**: optionally start background `web_contents`
|
|
@@ -46,6 +46,7 @@ Each tool can be routed to any compatible provider:
|
|
|
46
46
|
| **Exa** | ✔ | ✔ | ✔ | ✔ | `EXA_API_KEY` |
|
|
47
47
|
| **Firecrawl** | ✔ | ✔ | | | `FIRECRAWL_API_KEY` |
|
|
48
48
|
| **Gemini** | ✔ | | ✔ | ✔ | `GOOGLE_API_KEY` |
|
|
49
|
+
| **Linkup** | ✔ | ✔ | | | `LINKUP_API_KEY` |
|
|
49
50
|
| **Perplexity** | ✔ | | ✔ | ✔ | `PERPLEXITY_API_KEY` |
|
|
50
51
|
| **Parallel** | ✔ | ✔ | | | `PARALLEL_API_KEY` |
|
|
51
52
|
| **Tavily** | ✔ | ✔ | | | `TAVILY_API_KEY` |
|
|
@@ -264,6 +265,20 @@ scope, or account ID is usually wrong.
|
|
|
264
265
|
|
|
265
266
|
</details>
|
|
266
267
|
|
|
268
|
+
<details>
|
|
269
|
+
<summary><strong>Linkup</strong></summary>
|
|
270
|
+
|
|
271
|
+
- SDK: `linkup-sdk`
|
|
272
|
+
- Supports `web_search` via Linkup Search with fixed `searchResults` output
|
|
273
|
+
- Supports `web_contents` via Linkup Fetch and always returns markdown
|
|
274
|
+
- Supports provider-specific `options.search` such as `depth`, domain filters,
|
|
275
|
+
image inclusion, and date filters
|
|
276
|
+
- Supports provider-specific `options.fetch` such as `renderJs`,
|
|
277
|
+
`includeRawHtml`, and `extractImages`
|
|
278
|
+
- Good fit for a simple search-plus-markdown setup without extra provider wiring
|
|
279
|
+
|
|
280
|
+
</details>
|
|
281
|
+
|
|
267
282
|
<details>
|
|
268
283
|
<summary><strong>Perplexity</strong></summary>
|
|
269
284
|
|
package/dist/index.js
CHANGED
|
@@ -612,7 +612,7 @@ function $constructor(name, initializer3, params) {
|
|
|
612
612
|
Object.defineProperty(_, "name", { value: name });
|
|
613
613
|
return _;
|
|
614
614
|
}
|
|
615
|
-
var $brand = Symbol("zod_brand");
|
|
615
|
+
var $brand = /* @__PURE__ */ Symbol("zod_brand");
|
|
616
616
|
var $ZodAsyncError = class extends Error {
|
|
617
617
|
constructor() {
|
|
618
618
|
super(`Encountered Promise during synchronous parse. Use .parseAsync() instead.`);
|
|
@@ -759,7 +759,7 @@ function floatSafeRemainder(val, step) {
|
|
|
759
759
|
const stepInt = Number.parseInt(step.toFixed(decCount).replace(".", ""));
|
|
760
760
|
return valInt % stepInt / 10 ** decCount;
|
|
761
761
|
}
|
|
762
|
-
var EVALUATING = Symbol("evaluating");
|
|
762
|
+
var EVALUATING = /* @__PURE__ */ Symbol("evaluating");
|
|
763
763
|
function defineLazy(object2, key, getter) {
|
|
764
764
|
let value = void 0;
|
|
765
765
|
Object.defineProperty(object2, key, {
|
|
@@ -9832,8 +9832,8 @@ function yo_default() {
|
|
|
9832
9832
|
|
|
9833
9833
|
// node_modules/zod/v4/core/registries.js
|
|
9834
9834
|
var _a;
|
|
9835
|
-
var $output = Symbol("ZodOutput");
|
|
9836
|
-
var $input = Symbol("ZodInput");
|
|
9835
|
+
var $output = /* @__PURE__ */ Symbol("ZodOutput");
|
|
9836
|
+
var $input = /* @__PURE__ */ Symbol("ZodInput");
|
|
9837
9837
|
var $ZodRegistry = class {
|
|
9838
9838
|
constructor() {
|
|
9839
9839
|
this._map = /* @__PURE__ */ new WeakMap();
|
|
@@ -13814,6 +13814,7 @@ var PROVIDER_TOOLS_BY_ID = {
|
|
|
13814
13814
|
exa: ["search", "contents", "answer", "research"],
|
|
13815
13815
|
firecrawl: ["search", "contents"],
|
|
13816
13816
|
gemini: ["search", "answer", "research"],
|
|
13817
|
+
linkup: ["search", "contents"],
|
|
13817
13818
|
perplexity: ["search", "answer", "research"],
|
|
13818
13819
|
parallel: ["search", "contents"],
|
|
13819
13820
|
tavily: ["search", "contents"],
|
|
@@ -13858,6 +13859,7 @@ var PROVIDER_IDS = [
|
|
|
13858
13859
|
"exa",
|
|
13859
13860
|
"firecrawl",
|
|
13860
13861
|
"gemini",
|
|
13862
|
+
"linkup",
|
|
13861
13863
|
"perplexity",
|
|
13862
13864
|
"parallel",
|
|
13863
13865
|
"tavily",
|
|
@@ -13933,6 +13935,16 @@ var geminiProviderSchema = external_exports.object({
|
|
|
13933
13935
|
options: geminiOptionsSchema.optional(),
|
|
13934
13936
|
settings: executionSettingsSchema.optional()
|
|
13935
13937
|
}).strict();
|
|
13938
|
+
var linkupOptionsSchema = external_exports.object({
|
|
13939
|
+
search: jsonObjectSchema.optional(),
|
|
13940
|
+
fetch: jsonObjectSchema.optional()
|
|
13941
|
+
}).strict();
|
|
13942
|
+
var linkupProviderSchema = external_exports.object({
|
|
13943
|
+
apiKey: stringSchema.optional(),
|
|
13944
|
+
baseUrl: stringSchema.optional(),
|
|
13945
|
+
options: linkupOptionsSchema.optional(),
|
|
13946
|
+
settings: executionSettingsSchema.optional()
|
|
13947
|
+
}).strict();
|
|
13936
13948
|
var perplexityOptionsSchema = external_exports.object({
|
|
13937
13949
|
search: jsonObjectSchema.optional(),
|
|
13938
13950
|
answer: jsonObjectSchema.optional(),
|
|
@@ -14110,6 +14122,7 @@ function normalizeConfig(raw, source) {
|
|
|
14110
14122
|
exa: normalizeExaProvider,
|
|
14111
14123
|
firecrawl: normalizeFirecrawlProvider,
|
|
14112
14124
|
gemini: normalizeGeminiProvider,
|
|
14125
|
+
linkup: normalizeLinkupProvider,
|
|
14113
14126
|
perplexity: normalizePerplexityProvider,
|
|
14114
14127
|
parallel: normalizeParallelProvider,
|
|
14115
14128
|
tavily: normalizeTavilyProvider,
|
|
@@ -14160,6 +14173,9 @@ function normalizeValyuProvider(raw, source) {
|
|
|
14160
14173
|
function normalizeGeminiProvider(raw, source) {
|
|
14161
14174
|
return parseProviderWithSchema(raw, source, "gemini", geminiProviderSchema);
|
|
14162
14175
|
}
|
|
14176
|
+
function normalizeLinkupProvider(raw, source) {
|
|
14177
|
+
return parseProviderWithSchema(raw, source, "linkup", linkupProviderSchema);
|
|
14178
|
+
}
|
|
14163
14179
|
function normalizePerplexityProvider(raw, source) {
|
|
14164
14180
|
return parseProviderWithSchema(
|
|
14165
14181
|
raw,
|
|
@@ -16965,6 +16981,185 @@ function readNonEmptyString3(value) {
|
|
|
16965
16981
|
return typeof value === "string" && value.trim().length > 0 ? value : void 0;
|
|
16966
16982
|
}
|
|
16967
16983
|
|
|
16984
|
+
// src/providers/linkup.ts
|
|
16985
|
+
import {
|
|
16986
|
+
LinkupClient
|
|
16987
|
+
} from "linkup-sdk";
|
|
16988
|
+
var linkupAdapter = {
|
|
16989
|
+
id: "linkup",
|
|
16990
|
+
label: "Linkup",
|
|
16991
|
+
docsUrl: "https://docs.linkup.so/pages/sdk/js/js",
|
|
16992
|
+
tools: ["search", "contents"],
|
|
16993
|
+
createTemplate() {
|
|
16994
|
+
return {
|
|
16995
|
+
apiKey: "LINKUP_API_KEY"
|
|
16996
|
+
};
|
|
16997
|
+
},
|
|
16998
|
+
getCapabilityStatus(config2) {
|
|
16999
|
+
return getApiKeyStatus(config2?.apiKey);
|
|
17000
|
+
},
|
|
17001
|
+
buildPlan(request, config2) {
|
|
17002
|
+
return buildProviderPlan({
|
|
17003
|
+
request,
|
|
17004
|
+
config: config2,
|
|
17005
|
+
providerId: linkupAdapter.id,
|
|
17006
|
+
providerLabel: linkupAdapter.label,
|
|
17007
|
+
handlers: {
|
|
17008
|
+
search: {
|
|
17009
|
+
execute: (searchRequest, providerConfig, context) => linkupAdapter.search(
|
|
17010
|
+
searchRequest.query,
|
|
17011
|
+
searchRequest.maxResults,
|
|
17012
|
+
providerConfig,
|
|
17013
|
+
context,
|
|
17014
|
+
searchRequest.options
|
|
17015
|
+
)
|
|
17016
|
+
},
|
|
17017
|
+
contents: {
|
|
17018
|
+
execute: (contentsRequest, providerConfig, context) => linkupAdapter.contents(
|
|
17019
|
+
contentsRequest.urls,
|
|
17020
|
+
providerConfig,
|
|
17021
|
+
context,
|
|
17022
|
+
contentsRequest.options
|
|
17023
|
+
)
|
|
17024
|
+
}
|
|
17025
|
+
}
|
|
17026
|
+
});
|
|
17027
|
+
},
|
|
17028
|
+
async search(query2, maxResults, config2, _context, options) {
|
|
17029
|
+
const client = createClient4(config2);
|
|
17030
|
+
const defaults = stripLocalExecutionOptions(asJsonObject(config2.options?.search)) ?? {};
|
|
17031
|
+
const response = await client.search(
|
|
17032
|
+
buildSearchParams(query2, maxResults, {
|
|
17033
|
+
...defaults,
|
|
17034
|
+
...stripLocalExecutionOptions(options) ?? {}
|
|
17035
|
+
})
|
|
17036
|
+
);
|
|
17037
|
+
return {
|
|
17038
|
+
provider: linkupAdapter.id,
|
|
17039
|
+
results: (response.results ?? []).map(toSearchResult2).filter((result) => result !== null).slice(0, maxResults)
|
|
17040
|
+
};
|
|
17041
|
+
},
|
|
17042
|
+
async contents(urls, config2, _context, options) {
|
|
17043
|
+
const client = createClient4(config2);
|
|
17044
|
+
const defaults = stripLocalExecutionOptions(asJsonObject(config2.options?.fetch)) ?? {};
|
|
17045
|
+
return {
|
|
17046
|
+
provider: linkupAdapter.id,
|
|
17047
|
+
answers: await Promise.all(
|
|
17048
|
+
urls.map(async (url2) => {
|
|
17049
|
+
try {
|
|
17050
|
+
const response = await client.fetch(
|
|
17051
|
+
buildFetchParams(url2, {
|
|
17052
|
+
...defaults,
|
|
17053
|
+
...stripLocalExecutionOptions(options) ?? {}
|
|
17054
|
+
})
|
|
17055
|
+
);
|
|
17056
|
+
return response.markdown ? {
|
|
17057
|
+
url: url2,
|
|
17058
|
+
content: response.markdown
|
|
17059
|
+
} : {
|
|
17060
|
+
url: url2,
|
|
17061
|
+
error: "No content returned for this URL."
|
|
17062
|
+
};
|
|
17063
|
+
} catch (error48) {
|
|
17064
|
+
return {
|
|
17065
|
+
url: url2,
|
|
17066
|
+
error: error48 instanceof Error ? error48.message : String(error48)
|
|
17067
|
+
};
|
|
17068
|
+
}
|
|
17069
|
+
})
|
|
17070
|
+
)
|
|
17071
|
+
};
|
|
17072
|
+
}
|
|
17073
|
+
};
|
|
17074
|
+
function buildSearchParams(query2, maxResults, options) {
|
|
17075
|
+
const searchOptions = options;
|
|
17076
|
+
if (searchOptions.query !== void 0) {
|
|
17077
|
+
throw new Error("Linkup search options cannot override the managed query.");
|
|
17078
|
+
}
|
|
17079
|
+
if (searchOptions.maxResults !== void 0) {
|
|
17080
|
+
throw new Error(
|
|
17081
|
+
"Linkup search options cannot override the managed maxResults."
|
|
17082
|
+
);
|
|
17083
|
+
}
|
|
17084
|
+
if (searchOptions.outputType !== void 0 && searchOptions.outputType !== "searchResults") {
|
|
17085
|
+
throw new Error("Linkup search only supports outputType 'searchResults'.");
|
|
17086
|
+
}
|
|
17087
|
+
if (searchOptions.includeInlineCitations !== void 0 || searchOptions.includeSources !== void 0 || searchOptions.structuredOutputSchema !== void 0) {
|
|
17088
|
+
throw new Error(
|
|
17089
|
+
"Linkup search only supports search-results mode for managed web_search."
|
|
17090
|
+
);
|
|
17091
|
+
}
|
|
17092
|
+
return {
|
|
17093
|
+
query: query2,
|
|
17094
|
+
depth: searchOptions.depth ?? "standard",
|
|
17095
|
+
outputType: "searchResults",
|
|
17096
|
+
maxResults,
|
|
17097
|
+
...searchOptions.includeImages !== void 0 ? { includeImages: searchOptions.includeImages } : {},
|
|
17098
|
+
...searchOptions.includeDomains !== void 0 ? { includeDomains: searchOptions.includeDomains } : {},
|
|
17099
|
+
...searchOptions.excludeDomains !== void 0 ? { excludeDomains: searchOptions.excludeDomains } : {},
|
|
17100
|
+
...searchOptions.fromDate !== void 0 ? { fromDate: toDate(searchOptions.fromDate, "fromDate") } : {},
|
|
17101
|
+
...searchOptions.toDate !== void 0 ? { toDate: toDate(searchOptions.toDate, "toDate") } : {}
|
|
17102
|
+
};
|
|
17103
|
+
}
|
|
17104
|
+
function buildFetchParams(url2, options) {
|
|
17105
|
+
const fetchOptions = options;
|
|
17106
|
+
if (fetchOptions.url !== void 0) {
|
|
17107
|
+
throw new Error("Linkup fetch options cannot override the managed URL.");
|
|
17108
|
+
}
|
|
17109
|
+
return {
|
|
17110
|
+
url: url2,
|
|
17111
|
+
...fetchOptions.renderJs !== void 0 ? { renderJs: fetchOptions.renderJs } : {},
|
|
17112
|
+
...fetchOptions.includeRawHtml !== void 0 ? { includeRawHtml: fetchOptions.includeRawHtml } : {},
|
|
17113
|
+
...fetchOptions.extractImages !== void 0 ? { extractImages: fetchOptions.extractImages } : {}
|
|
17114
|
+
};
|
|
17115
|
+
}
|
|
17116
|
+
function createClient4(config2) {
|
|
17117
|
+
const apiKey = resolveConfigValue(config2.apiKey);
|
|
17118
|
+
if (!apiKey) {
|
|
17119
|
+
throw new Error("is missing an API key");
|
|
17120
|
+
}
|
|
17121
|
+
return new LinkupClient({
|
|
17122
|
+
apiKey,
|
|
17123
|
+
baseUrl: resolveConfigValue(config2.baseUrl)
|
|
17124
|
+
});
|
|
17125
|
+
}
|
|
17126
|
+
function toSearchResult2(value) {
|
|
17127
|
+
const entry = asRecord2(value);
|
|
17128
|
+
if (!entry) {
|
|
17129
|
+
return null;
|
|
17130
|
+
}
|
|
17131
|
+
const url2 = readString3(entry.url) ?? "";
|
|
17132
|
+
const title = readString3(entry.name) ?? (url2 || "Untitled");
|
|
17133
|
+
const type = readString3(entry.type);
|
|
17134
|
+
const favicon = readString3(entry.favicon);
|
|
17135
|
+
const snippet = type === "text" ? trimSnippet(readString3(entry.content) ?? "") : "";
|
|
17136
|
+
const metadata = {
|
|
17137
|
+
...type ? { type } : {},
|
|
17138
|
+
...favicon ? { favicon } : {}
|
|
17139
|
+
};
|
|
17140
|
+
return {
|
|
17141
|
+
title,
|
|
17142
|
+
url: url2,
|
|
17143
|
+
snippet,
|
|
17144
|
+
metadata: Object.keys(metadata).length > 0 ? metadata : void 0
|
|
17145
|
+
};
|
|
17146
|
+
}
|
|
17147
|
+
function asRecord2(value) {
|
|
17148
|
+
return typeof value === "object" && value !== null && !Array.isArray(value) ? value : void 0;
|
|
17149
|
+
}
|
|
17150
|
+
function readString3(value) {
|
|
17151
|
+
return typeof value === "string" ? value : void 0;
|
|
17152
|
+
}
|
|
17153
|
+
function toDate(value, name) {
|
|
17154
|
+
const date5 = value instanceof Date ? value : new Date(value);
|
|
17155
|
+
if (Number.isNaN(date5.getTime())) {
|
|
17156
|
+
throw new Error(
|
|
17157
|
+
`Linkup option '${name}' must be a valid date string, timestamp, or Date.`
|
|
17158
|
+
);
|
|
17159
|
+
}
|
|
17160
|
+
return date5;
|
|
17161
|
+
}
|
|
17162
|
+
|
|
16968
17163
|
// src/providers/parallel.ts
|
|
16969
17164
|
import ParallelClient from "parallel-web";
|
|
16970
17165
|
var parallelAdapter = {
|
|
@@ -17017,7 +17212,7 @@ var parallelAdapter = {
|
|
|
17017
17212
|
});
|
|
17018
17213
|
},
|
|
17019
17214
|
async search(query2, maxResults, config2, context, options) {
|
|
17020
|
-
const client =
|
|
17215
|
+
const client = createClient5(config2);
|
|
17021
17216
|
const defaults = stripLocalExecutionOptions(asJsonObject(config2.options?.search)) ?? {};
|
|
17022
17217
|
const response = await client.beta.search(
|
|
17023
17218
|
{
|
|
@@ -17038,7 +17233,7 @@ var parallelAdapter = {
|
|
|
17038
17233
|
};
|
|
17039
17234
|
},
|
|
17040
17235
|
async contents(urls, config2, context, options) {
|
|
17041
|
-
const client =
|
|
17236
|
+
const client = createClient5(config2);
|
|
17042
17237
|
const defaults = stripLocalExecutionOptions(asJsonObject(config2.options?.extract)) ?? {};
|
|
17043
17238
|
const response = await client.beta.extract(
|
|
17044
17239
|
{
|
|
@@ -17077,7 +17272,7 @@ var parallelAdapter = {
|
|
|
17077
17272
|
};
|
|
17078
17273
|
}
|
|
17079
17274
|
};
|
|
17080
|
-
function
|
|
17275
|
+
function createClient5(config2) {
|
|
17081
17276
|
const apiKey = resolveConfigValue(config2.apiKey);
|
|
17082
17277
|
if (!apiKey) {
|
|
17083
17278
|
throw new Error("is missing an API key");
|
|
@@ -17152,7 +17347,7 @@ var perplexityAdapter = {
|
|
|
17152
17347
|
});
|
|
17153
17348
|
},
|
|
17154
17349
|
async search(query2, maxResults, config2, context, options) {
|
|
17155
|
-
const client =
|
|
17350
|
+
const client = createClient6(config2);
|
|
17156
17351
|
const request = {
|
|
17157
17352
|
...stripLocalExecutionOptions(asJsonObject(config2.options?.search)) ?? {},
|
|
17158
17353
|
...options ?? {},
|
|
@@ -17198,7 +17393,7 @@ var perplexityAdapter = {
|
|
|
17198
17393
|
}
|
|
17199
17394
|
};
|
|
17200
17395
|
async function runSilentForegroundChatTool(input, config2, context, fallbackModel, label, options, isResearch = false) {
|
|
17201
|
-
const client =
|
|
17396
|
+
const client = createClient6(config2);
|
|
17202
17397
|
const defaults = stripLocalExecutionOptions(
|
|
17203
17398
|
isResearch ? asJsonObject(config2.options?.research) : asJsonObject(config2.options?.answer)
|
|
17204
17399
|
) ?? {};
|
|
@@ -17232,7 +17427,7 @@ async function runSilentForegroundChatTool(input, config2, context, fallbackMode
|
|
|
17232
17427
|
};
|
|
17233
17428
|
}
|
|
17234
17429
|
async function runStreamingForegroundChatTool(input, config2, context, fallbackModel, label, options) {
|
|
17235
|
-
const client =
|
|
17430
|
+
const client = createClient6(config2);
|
|
17236
17431
|
const defaults = stripLocalExecutionOptions(asJsonObject(config2.options?.research)) ?? {};
|
|
17237
17432
|
const request = {
|
|
17238
17433
|
...defaults,
|
|
@@ -17273,7 +17468,7 @@ async function runStreamingForegroundChatTool(input, config2, context, fallbackM
|
|
|
17273
17468
|
itemCount: dedupedSources.length
|
|
17274
17469
|
};
|
|
17275
17470
|
}
|
|
17276
|
-
function
|
|
17471
|
+
function createClient6(config2) {
|
|
17277
17472
|
const apiKey = resolveConfigValue(config2.apiKey);
|
|
17278
17473
|
if (!apiKey) {
|
|
17279
17474
|
throw new Error("is missing an API key");
|
|
@@ -17408,7 +17603,7 @@ var tavilyAdapter = {
|
|
|
17408
17603
|
});
|
|
17409
17604
|
},
|
|
17410
17605
|
async search(query2, maxResults, config2, _context, options) {
|
|
17411
|
-
const client =
|
|
17606
|
+
const client = createClient7(config2);
|
|
17412
17607
|
const defaults = stripLocalExecutionOptions(asJsonObject(config2.options?.search)) ?? {};
|
|
17413
17608
|
const response = await client.search(query2, {
|
|
17414
17609
|
...defaults,
|
|
@@ -17427,7 +17622,7 @@ var tavilyAdapter = {
|
|
|
17427
17622
|
};
|
|
17428
17623
|
},
|
|
17429
17624
|
async contents(urls, config2, _context, options) {
|
|
17430
|
-
const client =
|
|
17625
|
+
const client = createClient7(config2);
|
|
17431
17626
|
const defaults = stripLocalExecutionOptions(asJsonObject(config2.options?.extract)) ?? {};
|
|
17432
17627
|
const response = await client.extract(urls, {
|
|
17433
17628
|
...defaults,
|
|
@@ -17465,7 +17660,7 @@ var tavilyAdapter = {
|
|
|
17465
17660
|
};
|
|
17466
17661
|
}
|
|
17467
17662
|
};
|
|
17468
|
-
function
|
|
17663
|
+
function createClient7(config2) {
|
|
17469
17664
|
const apiKey = resolveConfigValue(config2.apiKey);
|
|
17470
17665
|
if (!apiKey) {
|
|
17471
17666
|
throw new Error("is missing an API key");
|
|
@@ -17559,7 +17754,7 @@ var valyuAdapter = {
|
|
|
17559
17754
|
});
|
|
17560
17755
|
},
|
|
17561
17756
|
async search(query2, maxResults, config2, _context, searchOptions) {
|
|
17562
|
-
const client =
|
|
17757
|
+
const client = createClient8(config2);
|
|
17563
17758
|
const options = {
|
|
17564
17759
|
...stripLocalExecutionOptions(asJsonObject(config2.options)) ?? {},
|
|
17565
17760
|
...searchOptions ?? {},
|
|
@@ -17582,7 +17777,7 @@ var valyuAdapter = {
|
|
|
17582
17777
|
};
|
|
17583
17778
|
},
|
|
17584
17779
|
async contents(urls, config2, _context, options) {
|
|
17585
|
-
const client =
|
|
17780
|
+
const client = createClient8(config2);
|
|
17586
17781
|
const response = await client.contents(urls, options);
|
|
17587
17782
|
const finalResponse = "jobId" in response ? await client.waitForJob(response.jobId, {}) : response;
|
|
17588
17783
|
if (!finalResponse.success) {
|
|
@@ -17616,7 +17811,7 @@ var valyuAdapter = {
|
|
|
17616
17811
|
};
|
|
17617
17812
|
},
|
|
17618
17813
|
async answer(query2, config2, _context, options) {
|
|
17619
|
-
const client =
|
|
17814
|
+
const client = createClient8(config2);
|
|
17620
17815
|
const response = await client.answer(query2, {
|
|
17621
17816
|
...options ?? {},
|
|
17622
17817
|
streaming: false
|
|
@@ -17654,7 +17849,7 @@ var valyuAdapter = {
|
|
|
17654
17849
|
});
|
|
17655
17850
|
},
|
|
17656
17851
|
async startResearch(input, config2, _context, options) {
|
|
17657
|
-
const client =
|
|
17852
|
+
const client = createClient8(config2);
|
|
17658
17853
|
const task = await client.deepresearch.create({
|
|
17659
17854
|
input,
|
|
17660
17855
|
...options ?? {}
|
|
@@ -17665,7 +17860,7 @@ var valyuAdapter = {
|
|
|
17665
17860
|
return { id: task.deepresearch_id };
|
|
17666
17861
|
},
|
|
17667
17862
|
async pollResearch(id, config2, _context, _options) {
|
|
17668
|
-
const client =
|
|
17863
|
+
const client = createClient8(config2);
|
|
17669
17864
|
const result = await client.deepresearch.status(id);
|
|
17670
17865
|
if (!result.success) {
|
|
17671
17866
|
throw new Error(result.error || "deep research failed");
|
|
@@ -17708,7 +17903,7 @@ var valyuAdapter = {
|
|
|
17708
17903
|
return { status: "in_progress" };
|
|
17709
17904
|
}
|
|
17710
17905
|
};
|
|
17711
|
-
function
|
|
17906
|
+
function createClient8(config2) {
|
|
17712
17907
|
const apiKey = resolveConfigValue(config2.apiKey);
|
|
17713
17908
|
if (!apiKey) {
|
|
17714
17909
|
throw new Error("is missing an API key");
|
|
@@ -17725,6 +17920,7 @@ var ADAPTERS_BY_ID = {
|
|
|
17725
17920
|
exa: exaAdapter,
|
|
17726
17921
|
firecrawl: firecrawlAdapter,
|
|
17727
17922
|
gemini: geminiAdapter,
|
|
17923
|
+
linkup: linkupAdapter,
|
|
17728
17924
|
perplexity: perplexityAdapter,
|
|
17729
17925
|
parallel: parallelAdapter,
|
|
17730
17926
|
tavily: tavilyAdapter,
|
|
@@ -18846,7 +19042,7 @@ var PROVIDER_CONFIG_MANIFESTS = {
|
|
|
18846
19042
|
"deep-reasoning",
|
|
18847
19043
|
"deep-max"
|
|
18848
19044
|
],
|
|
18849
|
-
getValue: (config2) =>
|
|
19045
|
+
getValue: (config2) => readString4(getExaOptions(config2)?.type) ?? "default",
|
|
18850
19046
|
setValue: (config2, value) => {
|
|
18851
19047
|
const options = ensureExaOptions(config2);
|
|
18852
19048
|
if (value === "default") {
|
|
@@ -18950,6 +19146,13 @@ var PROVIDER_CONFIG_MANIFESTS = {
|
|
|
18950
19146
|
})
|
|
18951
19147
|
]
|
|
18952
19148
|
},
|
|
19149
|
+
linkup: {
|
|
19150
|
+
settings: [
|
|
19151
|
+
apiKeySetting(),
|
|
19152
|
+
baseUrlSetting(),
|
|
19153
|
+
...requestSettings("linkup")
|
|
19154
|
+
]
|
|
19155
|
+
},
|
|
18953
19156
|
perplexity: {
|
|
18954
19157
|
settings: [apiKeySetting(), baseUrlSetting()]
|
|
18955
19158
|
},
|
|
@@ -18962,7 +19165,7 @@ var PROVIDER_CONFIG_MANIFESTS = {
|
|
|
18962
19165
|
label: "Search mode",
|
|
18963
19166
|
help: "Parallel search mode. 'default' uses the SDK default.",
|
|
18964
19167
|
values: ["default", "agentic", "one-shot"],
|
|
18965
|
-
getValue: (config2) =>
|
|
19168
|
+
getValue: (config2) => readString4(getParallelOptions(config2)?.search?.mode) ?? "default",
|
|
18966
19169
|
setValue: (config2, value) => {
|
|
18967
19170
|
const options = ensureParallelOptions(config2);
|
|
18968
19171
|
options.search = asJsonObject2(options.search) ?? {};
|
|
@@ -19032,7 +19235,7 @@ var PROVIDER_CONFIG_MANIFESTS = {
|
|
|
19032
19235
|
label: "Search type",
|
|
19033
19236
|
help: "Valyu search type. 'default' uses the SDK default.",
|
|
19034
19237
|
values: ["default", "all", "web", "proprietary", "news"],
|
|
19035
|
-
getValue: (config2) =>
|
|
19238
|
+
getValue: (config2) => readString4(getValyuOptions(config2)?.searchType) ?? "default",
|
|
19036
19239
|
setValue: (config2, value) => {
|
|
19037
19240
|
const options = ensureValyuOptions(config2);
|
|
19038
19241
|
if (value === "default") {
|
|
@@ -19048,7 +19251,7 @@ var PROVIDER_CONFIG_MANIFESTS = {
|
|
|
19048
19251
|
label: "Response length",
|
|
19049
19252
|
help: "Valyu response length. 'default' uses the SDK default.",
|
|
19050
19253
|
values: ["default", "short", "medium", "large", "max"],
|
|
19051
|
-
getValue: (config2) =>
|
|
19254
|
+
getValue: (config2) => readString4(getValyuOptions(config2)?.responseLength) ?? "default",
|
|
19052
19255
|
setValue: (config2, value) => {
|
|
19053
19256
|
const options = ensureValyuOptions(config2);
|
|
19054
19257
|
if (value === "default") {
|
|
@@ -19212,7 +19415,7 @@ function getIntegerString(value) {
|
|
|
19212
19415
|
function getBooleanValue(value) {
|
|
19213
19416
|
return typeof value === "boolean" ? String(value) : "default";
|
|
19214
19417
|
}
|
|
19215
|
-
function
|
|
19418
|
+
function readString4(value) {
|
|
19216
19419
|
return typeof value === "string" ? value : void 0;
|
|
19217
19420
|
}
|
|
19218
19421
|
function asJsonObject2(value) {
|
|
@@ -19477,7 +19680,7 @@ function webProvidersExtension(pi) {
|
|
|
19477
19680
|
latestWidgetContext = ctx;
|
|
19478
19681
|
resetContentStore();
|
|
19479
19682
|
updateWebResearchWidget(ctx);
|
|
19480
|
-
await
|
|
19683
|
+
await refreshManagedToolsOnStartup(
|
|
19481
19684
|
pi,
|
|
19482
19685
|
{ activeWebResearchRequests, updateWebResearchWidget },
|
|
19483
19686
|
ctx.cwd,
|
|
@@ -19492,7 +19695,7 @@ function webProvidersExtension(pi) {
|
|
|
19492
19695
|
latestWidgetContext = ctx;
|
|
19493
19696
|
await cleanupContentStore();
|
|
19494
19697
|
updateWebResearchWidget(ctx);
|
|
19495
|
-
await
|
|
19698
|
+
await refreshManagedToolsOnStartup(
|
|
19496
19699
|
pi,
|
|
19497
19700
|
{ activeWebResearchRequests, updateWebResearchWidget },
|
|
19498
19701
|
ctx.cwd,
|
|
@@ -19722,6 +19925,10 @@ async function runWebProvidersConfig(pi, webResearchLifecycle, ctx) {
|
|
|
19722
19925
|
addAvailable: true
|
|
19723
19926
|
});
|
|
19724
19927
|
}
|
|
19928
|
+
function formatStartupConfigError(error48) {
|
|
19929
|
+
const detail = error48 instanceof Error ? error48.message : String(error48);
|
|
19930
|
+
return `web-providers config error: ${detail.replace(getConfigPath(), "~/.pi/agent/web-providers.json")}`;
|
|
19931
|
+
}
|
|
19725
19932
|
function getAvailableProviderIdsForCapability(config2, cwd, capability) {
|
|
19726
19933
|
const providerId = getMappedProviderIdForTool(config2, capability);
|
|
19727
19934
|
if (!providerId) {
|
|
@@ -19772,6 +19979,24 @@ async function refreshManagedTools(pi, webResearchLifecycle, cwd, options) {
|
|
|
19772
19979
|
});
|
|
19773
19980
|
await syncManagedToolAvailability(pi, nextActiveTools);
|
|
19774
19981
|
}
|
|
19982
|
+
async function refreshManagedToolsOnStartup(pi, webResearchLifecycle, cwd, options) {
|
|
19983
|
+
try {
|
|
19984
|
+
await refreshManagedTools(pi, webResearchLifecycle, cwd, options);
|
|
19985
|
+
} catch (error48) {
|
|
19986
|
+
const message = formatStartupConfigError(error48);
|
|
19987
|
+
pi.sendMessage({
|
|
19988
|
+
customType: "web-providers-config-error",
|
|
19989
|
+
content: message,
|
|
19990
|
+
display: true
|
|
19991
|
+
});
|
|
19992
|
+
await syncManagedToolAvailability(
|
|
19993
|
+
pi,
|
|
19994
|
+
new Set(
|
|
19995
|
+
pi.getActiveTools().filter((toolName) => !MANAGED_TOOL_NAMES.includes(toolName))
|
|
19996
|
+
)
|
|
19997
|
+
);
|
|
19998
|
+
}
|
|
19999
|
+
}
|
|
19775
20000
|
async function syncManagedToolAvailability(pi, nextActiveTools) {
|
|
19776
20001
|
const activeTools = pi.getActiveTools();
|
|
19777
20002
|
const changed = activeTools.length !== nextActiveTools.size || activeTools.some((toolName) => !nextActiveTools.has(toolName));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-web-providers",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.1.0",
|
|
4
4
|
"description": "Configurable web access extension for pi with per-tool provider routing for search, contents, answers, and research.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"files": [
|
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
"exa",
|
|
23
23
|
"firecrawl",
|
|
24
24
|
"gemini",
|
|
25
|
+
"linkup",
|
|
25
26
|
"perplexity",
|
|
26
27
|
"parallel",
|
|
27
28
|
"tavily",
|
|
@@ -45,7 +46,7 @@
|
|
|
45
46
|
]
|
|
46
47
|
},
|
|
47
48
|
"scripts": {
|
|
48
|
-
"build": "rm -rf dist && esbuild src/index.ts --bundle --format=esm --platform=node --outfile=dist/index.js --external:@mariozechner/pi-coding-agent --external:@mariozechner/pi-ai --external:@mariozechner/pi-tui --external:@sinclair/typebox --external:@anthropic-ai/claude-agent-sdk --external:@google/genai --external:@mendable/firecrawl-js --external:@openai/codex-sdk --external:@perplexity-ai/perplexity_ai --external:@tavily/core --external:cloudflare --external:exa-js --external:parallel-web --external:valyu-js",
|
|
49
|
+
"build": "rm -rf dist && esbuild src/index.ts --bundle --format=esm --platform=node --outfile=dist/index.js --external:@mariozechner/pi-coding-agent --external:@mariozechner/pi-ai --external:@mariozechner/pi-tui --external:@sinclair/typebox --external:@anthropic-ai/claude-agent-sdk --external:@google/genai --external:@mendable/firecrawl-js --external:@openai/codex-sdk --external:@perplexity-ai/perplexity_ai --external:@tavily/core --external:cloudflare --external:exa-js --external:linkup-sdk --external:parallel-web --external:valyu-js",
|
|
49
50
|
"prepare": "npm run build",
|
|
50
51
|
"prepack": "npm run build",
|
|
51
52
|
"check": "tsc --noEmit",
|
|
@@ -56,26 +57,27 @@
|
|
|
56
57
|
"test:watch": "vitest"
|
|
57
58
|
},
|
|
58
59
|
"dependencies": {
|
|
59
|
-
"@anthropic-ai/claude-agent-sdk": "^0.2.
|
|
60
|
-
"@google/genai": "^1.
|
|
60
|
+
"@anthropic-ai/claude-agent-sdk": "^0.2.89",
|
|
61
|
+
"@google/genai": "^1.47.0",
|
|
61
62
|
"@mendable/firecrawl-js": "^4.18.1",
|
|
62
|
-
"@openai/codex-sdk": "^0.
|
|
63
|
-
"@perplexity-ai/perplexity_ai": "^0.26.
|
|
63
|
+
"@openai/codex-sdk": "^0.118.0",
|
|
64
|
+
"@perplexity-ai/perplexity_ai": "^0.26.5",
|
|
64
65
|
"@tavily/core": "^0.7.2",
|
|
65
66
|
"cloudflare": "^5.2.0",
|
|
66
|
-
"exa-js": "^2.
|
|
67
|
-
"
|
|
68
|
-
"
|
|
69
|
-
"
|
|
67
|
+
"exa-js": "^2.10.2",
|
|
68
|
+
"linkup-sdk": "^2.7.0",
|
|
69
|
+
"parallel-web": "^0.3.2",
|
|
70
|
+
"valyu-js": "^2.7.6",
|
|
71
|
+
"zod": "^4.3.6"
|
|
70
72
|
},
|
|
71
73
|
"devDependencies": {
|
|
72
|
-
"@biomejs/biome": "^2.4.
|
|
73
|
-
"@mariozechner/pi-ai": "
|
|
74
|
-
"@mariozechner/pi-coding-agent": "
|
|
75
|
-
"@sinclair/typebox": "
|
|
76
|
-
"@types/node": "^
|
|
77
|
-
"esbuild": "^0.
|
|
78
|
-
"typescript": "^
|
|
79
|
-
"vitest": "^4.
|
|
74
|
+
"@biomejs/biome": "^2.4.10",
|
|
75
|
+
"@mariozechner/pi-ai": "^0.64.0",
|
|
76
|
+
"@mariozechner/pi-coding-agent": "^0.64.0",
|
|
77
|
+
"@sinclair/typebox": "^0.34.49",
|
|
78
|
+
"@types/node": "^25.5.0",
|
|
79
|
+
"esbuild": "^0.27.4",
|
|
80
|
+
"typescript": "^6.0.2",
|
|
81
|
+
"vitest": "^4.1.2"
|
|
80
82
|
}
|
|
81
83
|
}
|