import type { GlobalSettings } from "@umt/contracts";
import { LoaderCircle } from "lucide-react";
import { toast } from "sonner";
import { useTestWebSearch } from "~/api/settings.ts";
import { Button } from "~/components/ui/button.tsx";
import { errorMessage } from "~/lib/api.ts";
import { secretPatch } from "~/lib/secret.ts";
import { num, str } from "./resource-section.tsx";
import { type CardSpec, n } from "./settings-card.tsx";
// Agent 分区「网页搜索」:provider / Key(只写,存 secret)/ 地区 / 语言 / 安全搜索 / 每次条数 / 每分钟上限 + 测试
export const WEBSEARCH_CARD: CardSpec = {
anchor: "websearch",
title: "网页搜索",
description:
"开启后智能体可以用 web.search 搜索站外公开信息,用 web.fetch 读取搜索结果里的网页。结果和正文按不可信数据交给模型,web.fetch 不能读内网地址和结果以外的链接。",
fields: [
{
name: "agent.webSearch.provider",
label: "搜索服务",
kind: "select",
options: [
{ value: "none", label: "关闭" },
{ value: "brave", label: "Brave Search" },
],
},
{
name: "agent.webSearch.apiKey",
label: "API Key",
kind: "secret",
secret: { set: (v) => v["agent.webSearch.apiKey:set"] === true, clearable: true },
hint: "Brave Search API 的 Subscription Token",
visible: (v) => v["agent.webSearch.provider"] !== "none",
},
{
name: "agent.webSearch.country",
label: "搜索地区",
kind: "text",
placeholder: "ALL",
hint: "两位国家码,如 CN、US;ALL 表示不限",
visible: (v) => v["agent.webSearch.provider"] !== "none",
},
{
name: "agent.webSearch.searchLang",
label: "结果语言",
kind: "text",
placeholder: "不限",
hint: "如 zh-hans、en;留空不限",
visible: (v) => v["agent.webSearch.provider"] !== "none",
},
{
name: "agent.webSearch.safesearch",
label: "安全搜索",
kind: "select",
options: [
{ value: "off", label: "关闭" },
{ value: "moderate", label: "适中" },
{ value: "strict", label: "严格" },
],
visible: (v) => v["agent.webSearch.provider"] !== "none",
},
{
name: "agent.webSearch.maxResults",
label: "每次条数",
kind: "number",
hint: "1–10,智能体可以要更少",
visible: (v) => v["agent.webSearch.provider"] !== "none",
},
{
name: "agent.webSearch.requestsPerMinute",
label: "每分钟上限",
kind: "number",
hint: "三个进程共用;10 分钟内的相同搜索走缓存,不计次数",
visible: (v) => v["agent.webSearch.provider"] !== "none",
},
],
fromSettings: (s) => {
const w = s.agent.webSearch;
return {
"agent.webSearch.provider": w.provider,
"agent.webSearch.apiKey": "",
"agent.webSearch.apiKey:set": !!w.apiKeySecretRef,
"agent.webSearch.country": w.country,
"agent.webSearch.searchLang": w.searchLang ?? "",
"agent.webSearch.safesearch": w.safesearch,
"agent.webSearch.maxResults": n(w.maxResults),
"agent.webSearch.requestsPerMinute": n(w.requestsPerMinute),
};
},
toPatch: (v) => {
const key = secretPatch(v["agent.webSearch.apiKey"]);
const safe = str(v["agent.webSearch.safesearch"]);
return {
agent: {
webSearch: {
provider: v["agent.webSearch.provider"] === "brave" ? "brave" : "none",
country: str(v["agent.webSearch.country"]).toUpperCase() || "ALL",
searchLang: str(v["agent.webSearch.searchLang"]).toLowerCase() || null,
safesearch: safe === "off" || safe === "strict" ? safe : "moderate",
maxResults: num(v["agent.webSearch.maxResults"]),
requestsPerMinute: num(v["agent.webSearch.requestsPerMinute"]),
...(key !== undefined ? { apiKey: key } : {}),
},
},
};
},
extra: (s) =>