- 新增 $DATA_DIR/config/plugins/web-search.json(0600 + temp+rename,文件名 = 插件 id)
- 组合根改「先读可变源、缺失回落 .env 播种」;**不新增任何 env 键**(.env 已冻结)
- 多实例:每家 provider 独立 key/baseURL/启用态 + 「测试连通」探针
- 用 PLG-1 的声明库给出该面板的 adminPanels 声明;动作名交给 PLG-2 的通用动作端点分发
(本片自己不开路由)
⚠️ 本片自认越界:改了 cmd/cyrene/wire_web_search_test.go(既有测试,为适配 DataDir);
另有 design/28 的相关注册留给主会话。
88 lines
3.6 KiB
Go
88 lines
3.6 KiB
Go
package search
|
|
|
|
import "strings"
|
|
|
|
// 本文件是「搜索提供商」页的**数据面**:表格行与下拉选项的来源。
|
|
//
|
|
// 它只做**翻译**(事实 → 面板要的形状),不读文件、不开路由、不鉴权 —— 那些是插件管理器
|
|
// 与宿主端点的事(design/09 §5.2.1 B)。放这里的理由只有一个:`state` 与选项值的语义
|
|
// 属于 provider 领域(要问 `Configured` / `KnownNames`),散到宿主里就会与面板声明各写一套。
|
|
|
|
// 表格 `state` 列的取值(design/09 §5.2 示例:「ok | 未配置 | 凭据失效 | 未知」)。
|
|
//
|
|
// 「凭据失效」不在这里:它只能由一次真实调用得知(那是 plugin.testProvider 的结论,
|
|
// 见 probe.go),列表接口不该为了它去逐家发请求。
|
|
const (
|
|
// StateOK 表示这家可以用了(名字已登记且已配齐且启用)。
|
|
StateOK = "ok"
|
|
// StateNotConfigured 表示这个名字已登记,但没配齐(云家缺 key、searxng 缺地址)。
|
|
StateNotConfigured = "not_configured"
|
|
// StateDisabled 表示这条已被显式停用(enabled=false)。
|
|
StateDisabled = "disabled"
|
|
// StateUnknown 表示这个名字本期没登记(写错了 / 还没做,如 tavily)。
|
|
StateUnknown = "unknown"
|
|
)
|
|
|
|
// ProviderInput 是构造一行所需的最小事实(一条 provider 配置)。
|
|
//
|
|
// 刻意用平铺字段而不是引用 runtimeconfig 的类型:search 包是插件实现,不该认识宿主的
|
|
// 配置文件形状(那份形状属于宿主,见 internal/config/runtimeconfig/websearch.go)。
|
|
type ProviderInput struct {
|
|
// Provider 是 provider 名。
|
|
Provider string
|
|
// APIKey 是上游凭据(判定是否配齐用,**绝不进行数据**)。
|
|
APIKey string
|
|
// BaseURL 是上游基地址(同上,判定用)。
|
|
BaseURL string
|
|
// Enabled 是启用态。
|
|
Enabled bool
|
|
}
|
|
|
|
// ProviderRow 是「已配置的提供商」表格的一行。字段名即表格列的 key(panel.go 的 columns)。
|
|
//
|
|
// 凭据与基地址**都不进行数据**:列表只需要状态,凭据读侧无明文(design/09 §5.4.2),
|
|
// 而基地址可能带用户名口令。要看地址就点「重配凭据」,由表单一对一带回。
|
|
type ProviderRow struct {
|
|
Provider string `json:"provider"`
|
|
State string `json:"state"`
|
|
Enabled bool `json:"enabled"`
|
|
}
|
|
|
|
// BuildRows 把各条配置翻译成表格行。
|
|
//
|
|
// 判定顺序是把「根因」排在前面:名字没登记(写错了)> 显式停用 > 没配齐 > 可用。
|
|
// 一个停用的陌生名字报 `unknown` —— 名字错了才是要修的那处。
|
|
func BuildRows(inputs []ProviderInput) []ProviderRow {
|
|
out := make([]ProviderRow, 0, len(inputs))
|
|
for _, in := range inputs {
|
|
out = append(out, ProviderRow{
|
|
Provider: strings.ToLower(strings.TrimSpace(in.Provider)),
|
|
State: providerState(in),
|
|
Enabled: in.Enabled,
|
|
})
|
|
}
|
|
return out
|
|
}
|
|
|
|
// providerState 判定一条配置的表格状态。
|
|
func providerState(in ProviderInput) string {
|
|
name := strings.ToLower(strings.TrimSpace(in.Provider))
|
|
if !Known(name) {
|
|
return StateUnknown
|
|
}
|
|
if !in.Enabled {
|
|
return StateDisabled
|
|
}
|
|
if !Configured(name, in.APIKey, in.BaseURL) {
|
|
return StateNotConfigured
|
|
}
|
|
return StateOK
|
|
}
|
|
|
|
// ProviderOptions 返回 `optionsFrom: plugin:providers` 的选项值 —— 本期**全部已登记**的
|
|
// provider 名(含尚未配置的家),稳定排序。
|
|
//
|
|
// 为什么给全部而不是「已配置的家」:表单的用途就是**新增**一家,只列已配置的会让
|
|
// 「第一次配置」无从选起。可用性不靠下拉限制,靠列表的 `state` 列如实呈现。
|
|
func ProviderOptions() []string { return KnownNames() }
|