mirror of
https://bitbucket.org/siakitem/my-pi.git
synced 2026-10-26 10:45:22 +00:00
feat(pi-web-search): 搜索凭据迁移到 Pi auth.json
三个搜索 key 改为 auth.json 中的 tavily/exa/keenable api_key 凭据, pi-web-search/auth.ts 复刻上游 resolve-config-value 语义(!command、 $VAR 插值、credential env 优先、$$/$! 转义)并在每次调用时读取, 进程环境变量与 search.env 不再被直接读取。search_config.sh 重写为 scripts/search-auth.mjs 的薄封装:加锁原子写、权限 600、保留其他 凭据条目,支持 --migrate 从旧 search.env 一次性导入。 Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
co-authored by
Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
parent
ee1e6999d7
commit
0c9823ef5c
@@ -9,7 +9,7 @@
|
||||
|
||||
import type { AgentToolResult, ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
||||
|
||||
import { loadSearchConfigEnv } from "../extensions/search-config.ts";
|
||||
import { getSearchApiKey, type SearchKeyResolver } from "./auth.ts";
|
||||
import { exaFetchPages, exaSearch } from "./clients/exa.ts";
|
||||
import { keenableFetch, keenableSearch } from "./clients/keenable.ts";
|
||||
import { tavilyAvailable, tavilyExtract, tavilySearch } from "./clients/tavily.ts";
|
||||
@@ -108,9 +108,10 @@ export async function dispatchSearch(
|
||||
routeCache: Map<string, SearchProvider>,
|
||||
signal?: AbortSignal,
|
||||
runners: Record<SearchProvider, ProviderRunner> = createProviderRunners(),
|
||||
resolve: SearchKeyResolver = getSearchApiKey,
|
||||
): Promise<AgentToolResult> {
|
||||
const decision = await routeSearch(params, ctx, routeCache, signal);
|
||||
const order = [decision.provider, ...availableProviders().filter((p) => p !== decision.provider)];
|
||||
const decision = await routeSearch(params, ctx, routeCache, signal, resolve);
|
||||
const order = [decision.provider, ...availableProviders(resolve).filter((p) => p !== decision.provider)];
|
||||
let lastError: unknown;
|
||||
for (const provider of order) {
|
||||
try {
|
||||
@@ -161,6 +162,7 @@ export async function dispatchFetch(
|
||||
params: WebFetchParams,
|
||||
signal?: AbortSignal,
|
||||
fetchers: Record<SearchProvider, FetchRunner> = createFetchRunners(),
|
||||
resolve: SearchKeyResolver = getSearchApiKey,
|
||||
): Promise<AgentToolResult> {
|
||||
const urls = normalizeUrls(params.urls);
|
||||
if (!urls.length) {
|
||||
@@ -171,7 +173,7 @@ export async function dispatchFetch(
|
||||
}
|
||||
const maxCharacters = params.max_characters ?? DEFAULT_FETCH_MAX_CHARACTERS;
|
||||
const order: SearchProvider[] = ["exa", "keenable"];
|
||||
if (tavilyAvailable()) order.push("tavily");
|
||||
if (tavilyAvailable(resolve)) order.push("tavily");
|
||||
|
||||
let lastError: unknown;
|
||||
for (const provider of order) {
|
||||
@@ -186,9 +188,6 @@ export async function dispatchFetch(
|
||||
}
|
||||
|
||||
export default function webSearchExtension(pi: ExtensionAPI): void {
|
||||
// Keys may already be loaded by extensions/search-config.ts; this is a
|
||||
// harmless idempotent safety net for standalone loading.
|
||||
loadSearchConfigEnv();
|
||||
const routeCache = new Map<string, SearchProvider>();
|
||||
|
||||
pi.registerTool({
|
||||
|
||||
Reference in New Issue
Block a user