X2 C1-3(自排工具面与提示词): - request_think(thinktool.go,照 transcode/tool.go 范式)+ reason 必填/urgency 闭集 + 双守门 (安全闸 + owner 判定:群聊/陌生人一律拒) - **成对**进两张唤醒态允许集(quiet + awake;CAPACITY_TOOL_SETS 是整体替换) - 提示词抽共用段落 + 自排前缀优先(不枚举工具清单);面板加 self_wake 标签与筛选轴 - 4 个变异自检(拿掉 owner 判定/只加一张表/放宽 urgency/前端标签恒等) X3 收口(与 X2 共用 wire_services.go ⇒ 一并落): - 删掉第三份 SSRF 实现(guard.go),改由 io.ValidateRequestURL 唯一判定 + 薄门面(保两个错误身份) - 浏览器会话挂进 a.close(真机:真 Chrome 被关、无残留、生产未扰动) - a.wireBrowser() 归位到 wire_runtime.go,删掉 ioToolOptions 的临时挂点 - 5 个变异自检 顺带补提交 C1-2 漏掉的 internal/config/runtimeconfig/backthink_test.go(ed50053 漏 add)。
111 lines
4.5 KiB
Go
111 lines
4.5 KiB
Go
package runtimeconfig
|
||
|
||
import (
|
||
"errors"
|
||
"os"
|
||
"path/filepath"
|
||
"testing"
|
||
)
|
||
|
||
// 本文件守 design/12 §N C.5 的**只读加载件**:落点是
|
||
// `$DATA_DIR/config/backthink.json`(零新 env 键),文件缺失 = 还没配过(零值 + nil,
|
||
// 不是错误),存在但解不开 = 返回错(调用方记 WARN 并回落默认,绝不静默变成「无上限」)。
|
||
|
||
// TestDefaultBackthinkPath 钉住落点:`<dataDir>/config/backthink.json`。
|
||
// 它同时守住「新家族从一开始就只写 config/」(design/13 §2.1 第 5 条)——
|
||
// 路径里少一段 config 就是静默换家。
|
||
func TestDefaultBackthinkPath(t *testing.T) {
|
||
t.Parallel()
|
||
got := DefaultBackthinkPath(filepath.Join("root", "data"))
|
||
want := filepath.Join("root", "data", "config", "backthink.json")
|
||
if got != want {
|
||
t.Fatalf("DefaultBackthinkPath = %q, want %q", got, want)
|
||
}
|
||
}
|
||
|
||
// TestLoadBackgroundTuning_MissingFileIsNotAnError 钉住「没配过」不是错误:
|
||
// 返回零值 + nil,由服务侧 normalize 回落代码默认(4 轮/小时)。
|
||
func TestLoadBackgroundTuning_MissingFileIsNotAnError(t *testing.T) {
|
||
t.Parallel()
|
||
path := filepath.Join(t.TempDir(), "config", "backthink.json")
|
||
got, err := LoadBackgroundTuning(path)
|
||
if err != nil {
|
||
t.Fatalf("缺失文件应返回 nil error,得到 %v", err)
|
||
}
|
||
if got.SelfWakePerWindow != 0 || got.SelfWakeWindowSec != 0 {
|
||
t.Fatalf("缺失文件应返回零值,得到 %+v", got)
|
||
}
|
||
// 它**不建目录**:读路径不许留下副作用(新家族没有老位置,也没什么要建的)。
|
||
if _, statErr := os.Stat(filepath.Dir(path)); !os.IsNotExist(statErr) {
|
||
t.Fatalf("读路径建了目录或留下了别的痕迹:stat err = %v", statErr)
|
||
}
|
||
}
|
||
|
||
// TestLoadBackgroundTuning_EmptyFileIsNotConfigured 钉住「全空白 = 还没配过」,
|
||
// 与 plugins.json / web-search.json 的既有口径逐字一致。
|
||
func TestLoadBackgroundTuning_EmptyFileIsNotConfigured(t *testing.T) {
|
||
t.Parallel()
|
||
path := filepath.Join(t.TempDir(), "backthink.json")
|
||
if err := os.WriteFile(path, []byte(" \n\t\n"), 0o600); err != nil {
|
||
t.Fatalf("写测试文件: %v", err)
|
||
}
|
||
got, err := LoadBackgroundTuning(path)
|
||
if err != nil {
|
||
t.Fatalf("空白文件应返回 nil error,得到 %v", err)
|
||
}
|
||
if got != (BackgroundTuning{}) {
|
||
t.Fatalf("空白文件应返回零值,得到 %+v", got)
|
||
}
|
||
}
|
||
|
||
// TestLoadBackgroundTuning_ReadsSpecShape 钉住规格里给的形状逐字可读
|
||
// (design/12 §N C.5 的 JSON 例子),且原样交出**未**回落默认的原始数字
|
||
// —— 回落是服务侧 normalize 的事,这里不做第二套默认值。
|
||
func TestLoadBackgroundTuning_ReadsSpecShape(t *testing.T) {
|
||
t.Parallel()
|
||
path := filepath.Join(t.TempDir(), "backthink.json")
|
||
body := `{ "selfWakePerWindow": 2, "selfWakeWindowSec": 1800 }`
|
||
if err := os.WriteFile(path, []byte(body), 0o600); err != nil {
|
||
t.Fatalf("写测试文件: %v", err)
|
||
}
|
||
got, err := LoadBackgroundTuning(path)
|
||
if err != nil {
|
||
t.Fatalf("LoadBackgroundTuning: %v", err)
|
||
}
|
||
if got.SelfWakePerWindow != 2 || got.SelfWakeWindowSec != 1800 {
|
||
t.Fatalf("tuning = %+v, want {2 1800}", got)
|
||
}
|
||
}
|
||
|
||
// TestLoadBackgroundTuning_ZeroStaysZero 钉住「配成 0」原样交出去(不在这里改写成默认):
|
||
// 服务侧的 normalize 才是「≤0 回落默认」的唯一执行点,本层若也回落,就等于有了
|
||
// 两套默认值真源。
|
||
func TestLoadBackgroundTuning_ZeroStaysZero(t *testing.T) {
|
||
t.Parallel()
|
||
path := filepath.Join(t.TempDir(), "backthink.json")
|
||
if err := os.WriteFile(path, []byte(`{ "selfWakePerWindow": 0, "selfWakeWindowSec": -1 }`), 0o600); err != nil {
|
||
t.Fatalf("写测试文件: %v", err)
|
||
}
|
||
got, err := LoadBackgroundTuning(path)
|
||
if err != nil {
|
||
t.Fatalf("LoadBackgroundTuning: %v", err)
|
||
}
|
||
if got.SelfWakePerWindow != 0 || got.SelfWakeWindowSec != -1 {
|
||
t.Fatalf("tuning = %+v, want 原样(0 与 -1 都不在本地改写)", got)
|
||
}
|
||
}
|
||
|
||
// TestLoadBackgroundTuning_BrokenFileReturnsError 钉住坏文件**必须**报错:
|
||
// 调用方据此记 WARN 并回落默认。若这里静默返回零值,一个写坏的文件就会安静地
|
||
// 变成「用默认值」,与「如实告知」的红线相反。
|
||
func TestLoadBackgroundTuning_BrokenFileReturnsError(t *testing.T) {
|
||
t.Parallel()
|
||
path := filepath.Join(t.TempDir(), "backthink.json")
|
||
if err := os.WriteFile(path, []byte(`{ "selfWakePerWindow": `), 0o600); err != nil {
|
||
t.Fatalf("写测试文件: %v", err)
|
||
}
|
||
if _, err := LoadBackgroundTuning(path); !errors.Is(err, ErrInvalidBackthink) {
|
||
t.Fatalf("err = %v, want ErrInvalidBackthink", err)
|
||
}
|
||
}
|