chore: 根目录清理(第二轮)—— 移除过程文档、本机脚本、临时产物 (#3)

★ 上一轮清理被合并覆盖:GUI 分支含 DESKTOP-PET-NOTES.md /
SERVER-HANDOFF.md / GUI-PLAN.md,合并时取了我方版本,
但我方 main 已是 squash 产物 ⇒ 三个文件复活。
而我当时只核对了 benchmark.md 一个就宣布成功 —— 判断依据不足。

本轮逐个文件验证(不再抽样)。

删除(零代码引用)
  DESKTOP-PET-NOTES.md    外部产品(Coopanion)拆解笔记
  SERVER-HANDOFF.md       给服务端的待办清单,已过时
  napcat-design-dna.json  设计 DNA 数据
  tmp_jinabench.py        临时脚本
  tmp_benchmark/          临时跑分程序

归位(不是删)
  plan.md        → docs/zh/legacy-issues.md  (遗留问题清单,有价值)
  GUI-PLAN.md    → cmd/gui/GUI-PLAN.md      (含坐标换算/koffi 踩坑)
                   根目录那份与 cmd/gui/ 已有副本字节相同(285b84dd…),删前者
  deploy-plan.sh     → deploy/scripts/
  deploy-waiter.sh   → deploy/scripts/
  deploy-sdk-site.sh → deploy/scripts/

脱敏(deploy-plan.sh 与 deploy-sdk-site.sh 含本机路径)
  /home/newqqagent      → ${HA_DATA}
  /home/program/TrueAgent → ${REPO}
  /home/program         → ${HOME_DIR}

引用同步:27 处(docs/zh/deploy-runbook.md、toolcall-parallel-execution-plan.md、
scripts/capability-bench/PLAN.md、三个脚本自身的用法注释、ci.yml 注释)

根目录现状:仅 README.md / README_EN.md / LICENSE / Makefile /
go.mod / go.sum / .gitignore / .golangci.yml / .mailmap / .pi-lens.json

验证:go build ✅  三个 sh 的 bash -n ✅
     go test -short ./internal/... ./pkg/... ./cmd/... 全绿
     根目录文件清单逐个核对(10 项,全为门面/配置)

Co-authored-by: pi <pi@local>
This commit is contained in:
JianFeeeee
2026-10-05 11:44:04 +08:00
committed by GitHub
parent 2946391ba3
commit 7901651946
14 changed files with 164 additions and 1695 deletions

View File

@ -0,0 +1,132 @@
package remotedevice
import (
"os"
"path/filepath"
"strings"
"testing"
)
// clipboardsue 的 content 参数:从**服务端可见的路径**读入剪切板。
//
// ## 为什么要它(2026-10-05)
//
// 长文本/代码块塞不进 `clipboardsue <文字>` 的命令行;让模型先生成一大段
// 文本再原样传给设备,既烧 token 又容易在转述中失真。
// 与 GUI 侧 screensue / speakeruse 的 `@<路径>` 是同一类问题的同一类解法。
//
// ## 这些判据钉住的行为
//
// ① text 与 content 都空 ⇒ 明确报错(不能静默写空剪切板)
// ② content 指向不存在的文件 ⇒ 报错且**带上路径**(否则模型无从修正)
// ③ content 超上限 ⇒ 报错(防止把会话撑爆)
// ④ 设备不可用时优先报设备错,而不是先读文件
// ——顺序很重要:不然一个离线设备会伪装成「文件不存在」
//
// 注:本文件只验**参数校验与错误路径**。真正读文件并下发需要一台在线设备,
// 那由 binary_test.go 的 WS 级联调覆盖。
// newOfflineDevice 造一个 device,其 clipboardsue 必然在 clipboardCheck 阶段失败。
func newOfflineDevice(t *testing.T) *devicectlDevice {
t.Helper()
return &devicectlDevice{reg: NewRegistry()}
}
func TestClipboardsue_EmptyTextAndContentRejected(t *testing.T) {
d := newOfflineDevice(t)
_, err := d.clipboardsue(map[string]interface{}{"device_id": "x"})
if err == nil {
t.Fatal("text 与 content 都为空时应当报错(不能静默写空剪切板)")
}
if !strings.Contains(err.Error(), "text") && !strings.Contains(err.Error(), "content") {
t.Errorf("错误信息应指明缺哪个参数,实际: %v", err)
}
// 只有空白也视为空
if _, err2 := d.clipboardsue(map[string]interface{}{
"device_id": "x", "text": " ", "content": " ",
}); err2 == nil {
t.Error("空白 text/content 也应报错")
}
}
func TestClipboardsue_DeviceCheckedBeforeReadingFile(t *testing.T) {
// 设备不存在 ⇒ 必须先报「设备不存在」,
// 而不是先读文件报「文件不存在」——否则离线设备会伪装成文件问题。
d := newOfflineDevice(t)
_, err := d.clipboardsue(map[string]interface{}{
"device_id": "no-such-device",
"content": filepath.Join(t.TempDir(), "nope.txt"),
})
if err == nil {
t.Fatal("设备不存在时应当报错")
}
if !strings.Contains(err.Error(), "no-such-device") {
t.Errorf("应先报设备问题(设备 %s 不存在),实际: %v", "no-such-device", err)
}
}
func TestClipboardsueMaxBytesIsTwoMB(t *testing.T) {
// 上限与 GUI 侧 CAPABILITY_SOURCE_MAX_BYTES 对齐(2MB)。
// 改这个常量时这条判据会红——提醒同步改 GUI。
if clipboardsueMaxBytes != 2*1024*1024 {
t.Errorf("clipboardsue 上限应为 2MB(与 GUI 侧一致),实际 %d", clipboardsueMaxBytes)
}
}
func TestClipboardsue_ContentFileReadable(t *testing.T) {
// 造一个真文件,确认 os.ReadFile 能读到(判据本身的自检:
// 若将来换成别的读法或路径处理变了,这里会先炸)。
dir := t.TempDir()
p := filepath.Join(dir, "note.txt")
want := "行1\n行2\n"
if err := os.WriteFile(p, []byte(want), 0o644); err != nil {
t.Fatal(err)
}
b, err := os.ReadFile(p)
if err != nil {
t.Fatalf("读取失败: %v", err)
}
if string(b) != want {
t.Errorf("读回内容不符: %q", string(b))
}
}
// TestClipboardsue_ContentOversizeRejected 钉住**上限真的被用上**。
//
// ★ 这条判据是补来的:我先前只写了「常量等于 2MB」那条,
//
// 把 `if len(b) > clipboardsueMaxBytes` 改成 `if false` 它照样绿——
// **测的是常量、不是闸**。凡是要验「闸真的关着」,
// 必须造一个越过阈值的数据去撞它,而不是断言阈值的数值。
func TestClipboardsue_ContentOversizeRejected(t *testing.T) {
// 造一个在线且已授权的设备,让 clipboardCheck 过;
// 随后超限文件必须在**读文件后的校验**处被拦下。
dir := t.TempDir()
p := filepath.Join(dir, "big.txt")
big := make([]byte, clipboardsueMaxBytes+1)
for i := range big {
big[i] = 'x'
}
if err := os.WriteFile(p, big, 0o644); err != nil {
t.Fatal(err)
}
reg := NewRegistry()
// 注册一个在线设备并授 capability:clipboardsue。
reg.devices["d1"] = &DeviceMeta{
DeviceID: "d1", Name: "d", Kind: "computer", Online: true,
Caps: []string{"clipboardsue"},
}
d := &devicectlDevice{reg: reg}
_, err := d.clipboardsue(map[string]interface{}{
"device_id": "d1",
"content": p,
})
if err == nil {
t.Fatal("超 2MB 的 content 应当被拒绝(把上限改成 if false 时这条会红)")
}
if !strings.Contains(err.Error(), "过大") && !strings.Contains(err.Error(), "上限") {
t.Errorf("错误信息应说明超限,实际: %v", err)
}
}