Files
AskaEth 29181245ce feat(browser): 浏览器配置与探测库(internal/capability/browsercfg,纯库零接线)
按 design/28 §2/§3 的「配置不进 .env」口径:读 $DATA_DIR/config/plugins/browser.json
(0600 + temp+rename 范式,**不读 env、不加新键**);有头/无头、CDP 端点、profile 目录、
视口/超时/并发(1)/截图上限全部类型化 + 常量默认值;**探测优先级**(本机 Chrome/Chromium
可执行文件 → 已在跑的容器)并返回可分类的「为什么不可用」(供上层如实降级,不假装可用);
profile 目录含凭据 ⇒ 0600 + 不进 git/不进上下文的注释与校验。

本片零既有文件改动(不注册工具、不碰 cmd/),接线留 B2。
2026-10-06 09:03:34 +08:00

55 lines
2.4 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package browsercfg
import "errors"
// 哨兵错误。AGENTS §10 只放行 `var ErrXxx` 作为包级变量,故原因码与文案用常量。
var (
// ErrInvalidConfig 表示 browser.json 解码失败、是空文件,或字段越界:
// 视口/截图字节超过硬上限、cdpEndpoint 不是 http(s) 绝对地址。
ErrInvalidConfig = errors.New("browsercfg: 配置非法")
// ErrProfileInGitTree 表示 profile 目录会落在 git 工作树内 —— profile 含凭据
// (cookie / 登录态),被 `git add` 收走就是把主人的登录态提交出去(design/28 §4)。
ErrProfileInGitTree = errors.New("browsercfg: profile 目录不得位于 git 工作树内")
)
// Reason 是可用性判定「为什么不可用」的**分类原因码**。上层据它如实降级与记日志,
// 不许把它含糊成「探测失败」四个字(design/28 §6 坑 5:失败要如实报)。
type Reason string
// 分类原因码。取值稳定、可断言;人类可读文案见 Message()。
const (
// ReasonUsable 表示探测到可用来源(Usable=true 时使用)。
ReasonUsable Reason = "usable"
// ReasonExecutableMissing 表示配置显式给出的浏览器可执行文件不存在或不可执行。
ReasonExecutableMissing Reason = "executable_missing"
// ReasonCDPUnreachable 表示 CDP 端点不可达 —— 配置里显式给定的那个,或兜底候选。
ReasonCDPUnreachable Reason = "cdp_unreachable"
// ReasonNoSource 表示本机既无 Chrome/Chromium 可执行文件、也没有在跑的 CDP 端点。
ReasonNoSource Reason = "no_source"
)
// 分类原因的中文文案:上层直接写进日志/面板,避免两处各写一份措辞
// (照 config.WebSearchReason* 的既有口径)。
const (
messageUsable = "可用"
messageExecutableMissing = "指定的浏览器可执行文件不存在或不可执行"
messageCDPUnreachable = "CDP 端点不可达"
messageNoSource = "本机未发现 Chrome/Chromium,也没有在跑的 CDP 端点"
)
// Message 返回原因码对应的中文文案;未知码返回空串(调用方回落到 Detail)。
func (r Reason) Message() string {
switch r {
case ReasonUsable:
return messageUsable
case ReasonExecutableMissing:
return messageExecutableMissing
case ReasonCDPUnreachable:
return messageCDPUnreachable
case ReasonNoSource:
return messageNoSource
default:
return ""
}
}