chore: 规范标点

This commit is contained in:
pluv committed 2026-10-03 14:56:56 +08:00
1 parent 15e79887fa
commit 3dd2231c70
81 files changed
+1751 -1751

No files matched your search

+30 -30
View File
@@ -69,7 +69,7 @@ int main(void)
CHECK(has_image, "schema 里应有 read_image");
}
{
/* line 是集合型参数:schema 里必须是 array (元素 integer),
/* line 是集合型参数: schema 里必须是 array (元素 integer),
* 否则模型根本不会想到可以给数组 —— 参数表的 "integer[]" 写法
* 只有 schema 展开对了才作数 */
JsonValue *props = NULL, *reqd = NULL;
@@ -158,7 +158,7 @@ int main(void)
CHECK(err == 1, "读不存在的文件应报错: %s", r);
free(r);
/* ---- edit_file:替换由行号钉住 ---- */
/* ---- edit_file: 替换由行号钉住 ---- */
puts("edit_file");
r = call("edit_file",
"{\"path\":\"sub/dir/a.txt\",\"line\":2,\"old_string\":\"line2\","
@@ -170,9 +170,9 @@ int main(void)
CHECK(strstr(r, "LINE-TWO") != NULL, "替换结果应落盘: %s", r);
free(r);
/* 省略 line 不再是错误:那是"全文件替换"这条逃生门 (见下面那组用例) */
/* 省略 line 不再是错误: 那是"全文件替换"这条逃生门 (见下面那组用例) */
/* 行号对不上:必须报出它**真正在哪一行**, 否则模型只能反复猜 */
/* 行号对不上: 必须报出它**真正在哪一行**, 否则模型只能反复猜 */
r = call("edit_file",
"{\"path\":\"sub/dir/a.txt\",\"line\":3,\"old_string\":\"LINE-TWO\","
"\"new_string\":\"x\"}", &err);
@@ -180,7 +180,7 @@ int main(void)
CHECK(strstr(r, "第 2 行") != NULL, "应指出它真正的行号: %s", r);
free(r);
/* 越界行号:要连文件总行数一起说清楚 */
/* 越界行号: 要连文件总行数一起说清楚 */
r = call("edit_file",
"{\"path\":\"sub/dir/a.txt\",\"line\":99,\"old_string\":\"x\","
"\"new_string\":\"y\"}", &err);
@@ -188,7 +188,7 @@ int main(void)
"越界行号应报错并给出总行数: %s", r);
free(r);
/* 唯一性只要求**在这一行里**唯一:同一个词出现在别的行不该拦住替换
/* 唯一性只要求**在这一行里**唯一: 同一个词出现在别的行不该拦住替换
* (这正是"全文唯一"最烦人的地方——文件一长, 随便一个短串都不唯一) */
r = call("edit_file",
"{\"path\":\"sub/dir/a.txt\",\"line\":1,\"old_string\":\"line\","
@@ -223,16 +223,16 @@ int main(void)
CHECK(err == 1, "replace_all 也必须锚定在真实的一行上: %s", r);
free(r);
/* ---- edit_file:line 是集合型 ----
/* ---- edit_file: line 是集合型 ----
* 集合是**搜索范围** (old_string 的起点落在其中任一行即可), 不是
* "每行都改一次":真改动的仍是唯一那一处. */
puts("edit_file:line 集合");
* "每行都改一次": 真改动的仍是唯一那一处. */
puts("edit_file: line 集合");
r = call("write_file",
"{\"path\":\"set.txt\",\"content\":\"aaa\\nbbb\\nccc\\nddd\\n\"}", &err);
CHECK(err == 0, "写入 set.txt: %s", r);
free(r);
/* 数组写法:起点落在集合里的哪一行都算命中; 回执要带上整个集合 */
/* 数组写法: 起点落在集合里的哪一行都算命中; 回执要带上整个集合 */
r = call("edit_file",
"{\"path\":\"set.txt\",\"line\":[1,2],\"old_string\":\"aaa\","
"\"new_string\":\"AAA\"}", &err);
@@ -264,7 +264,7 @@ int main(void)
"集合里多处匹配应拒绝: %s", r);
free(r);
/* 重复的行号要去重:不然同一处匹配会被数成两处 */
/* 重复的行号要去重: 不然同一处匹配会被数成两处 */
r = call("write_file", "{\"path\":\"dup3.txt\",\"content\":\"foo\\n\"}", &err);
CHECK(err == 0, "写入 dup3.txt: %s", r);
free(r);
@@ -282,7 +282,7 @@ int main(void)
"集合里的越界行号应报错并给出总行数: %s", r);
free(r);
/* 写法本身不对的三种:空数组、非整数元素、一次给太多 */
/* 写法本身不对的三种: 空数组、非整数元素、一次给太多 */
r = call("edit_file",
"{\"path\":\"set.txt\",\"line\":[],\"old_string\":\"x\","
"\"new_string\":\"y\"}", &err);
@@ -298,7 +298,7 @@ int main(void)
free(r);
/* ---- 省略 line = 全文件替换所有匹配 ----
* 这是 range 那样的集合参数该有的默认值:不给范围就是不设范围. */
* 这是 range 那样的集合参数该有的默认值: 不给范围就是不设范围. */
r = call("write_file", "{\"path\":\"all.txt\",\"content\":\"k\\nx\\nk\\n\"}", &err);
CHECK(err == 0, "写入 all.txt: %s", r);
free(r);
@@ -312,13 +312,13 @@ int main(void)
CHECK(strstr(r, "K") != NULL && !strstr(r, "k"), "两处都该被换掉: %s", r);
free(r);
/* 省略 line 时文件里没有 old_string:只说整个文件里没有 (没有"哪几行"可说) */
/* 省略 line 时文件里没有 old_string: 只说整个文件里没有 (没有"哪几行"可说) */
r = call("edit_file",
"{\"path\":\"all.txt\",\"old_string\":\"zzz\",\"new_string\":\"y\"}", &err);
CHECK(err == 1 && strstr(r, "整个文件里没有") != NULL, "该报整个文件里没有: %s", r);
free(r);
/* line 给错了类型 (不是"想全局"):仍然当场报错, 并告诉它可以省略 */
/* line 给错了类型 (不是"想全局"): 仍然当场报错, 并告诉它可以省略 */
r = call("edit_file",
"{\"path\":\"all.txt\",\"line\":\"1\",\"old_string\":\"K\","
"\"new_string\":\"z\"}", &err);
@@ -327,7 +327,7 @@ int main(void)
free(r);
{
/* 65 个行号:超过一次能圈住的范围, 要明说 */
/* 65 个行号: 超过一次能圈住的范围, 要明说 */
char big[600];
size_t o = (size_t)snprintf(big, sizeof big, "{\"path\":\"set.txt\",\"line\":[");
for (int i = 1; i <= 65; i++)
@@ -348,7 +348,7 @@ int main(void)
CHECK(err == 1, "不存在的目录应报错: %s", r);
free(r);
/* 这两个工具都已经删掉:搜索交给模型自己用 run_command 里的真 grep,
/* 这两个工具都已经删掉: 搜索交给模型自己用 run_command 里的真 grep,
* 子代理 (spawn_subagent)整个功能也去掉了. 留着断言是为了钉住
* "不要再冒出一个半吊子的替代品". */
r = call("grep", "{\"pattern\":\"x\",\"path\":\".\"}", &err);
@@ -362,7 +362,7 @@ int main(void)
puts("超大文件防护");
{
/* 稀疏文件, 创建几乎不耗时; 关键是客户端要在读之前就发现它太大.
* 开头 16 KB 写成 'x':这样它是"文本" (探测的前 8 KB 里没有 NUL),
* 开头 16 KB 写成 'x': 这样它是"文本" (探测的前 8 KB 里没有 NUL),
* 否则连 read_file 都会先被二进制检测拦掉 —— 这个用例就测不到
* "分段读大文件"了. */
FILE *big = fopen("huge.txt", "wb");
@@ -389,7 +389,7 @@ int main(void)
unlink("huge.txt");
}
/* ---- 二进制文件:所有处理文本的工具都必须拒绝 (而且要说明该用什么) ---- */
/* ---- 二进制文件: 所有处理文本的工具都必须拒绝 (而且要说明该用什么) ---- */
puts("二进制拒绝");
{
FILE *bf = fopen("bin.dat", "wb");
@@ -447,18 +447,18 @@ int main(void)
CHECK(tool_mutating("没有这个工具") == 0, "未知工具按只读处理");
CHECK(tool_mutating(NULL) == 0, "空名字不应崩");
/* ---- read_image:只收真的能内联进去的图 ----
/* ---- read_image: 只收真的能内联进去的图 ----
*
* 两条拒绝路径是新的:格式不认识、体积超限. 它们都必须**不备份** ——
* 两条拒绝路径是新的: 格式不认识、体积超限. 它们都必须**不备份** ——
* 一张交不出去的图, 留备份只会让 ligent.archive 变成垃圾场. */
puts("read_image:本地就把不合格的图拦掉");
puts("read_image: 本地就把不合格的图拦掉");
{
char btmp[] = "/tmp/ligent_tools_img_XXXXXX";
char *bdir = mkdtemp(btmp);
CHECK(bdir != NULL, "建备份临时目录失败");
if (bdir) {
image_set_bindir(bdir);
image_pending_take(); /* 清干净, 免得上一段残留 */
image_pending_take(); /* 清干净, 以免上一段残留 */
/* 1) 内容是文本、扩展名骗人 */
FILE *f = fopen("notanimage.png", "wb");
@@ -469,7 +469,7 @@ int main(void)
CHECK(strstr(r, "按文件内容判断") != NULL, "应说明是看内容判断的");
free(r);
/* 2) 体积超限:base64 后超过 IMAGE_MAX_B64.
/* 2) 体积超限: base64 后超过 IMAGE_MAX_B64.
* 4/3 * 原始大小 = 编码后大小, 所以原始要 > 3/4 * 上限. */
size_t raw_needed = (size_t)(IMAGE_MAX_B64 / 4 * 3) + 4096;
f = fopen("huge.png", "wb");
@@ -491,7 +491,7 @@ int main(void)
CHECK(strstr(r, "内联上限") != NULL, "应说清上限是多少");
free(r);
/* 3) 合法的小图:成功, 并且挂上待发附件 */
/* 3) 合法的小图: 成功, 并且挂上待发附件 */
f = fopen("ok.png", "wb");
if (f) { fwrite("\x89PNG\r\n\x1a\n", 1, 8, f); fwrite("payload", 1, 7, f); fclose(f); }
r = call("read_image", "{\"path\":\"ok.png\"}", &err);
@@ -519,7 +519,7 @@ int main(void)
}
}
/* ---- 超长单行:read_file 报出的行号必须与 edit_file 的口径一致 ----
/* ---- 超长单行: read_file 报出的行号必须与 edit_file 的口径一致 ----
*
* read_file 以前用 fgets + 固定 64 KB 缓冲, 一行比缓冲长时会被切成"多行"、
* 每块各带一个行号. 于是模型按 read_file 看到的行号去 edit_file 改, 要么改错
@@ -537,7 +537,7 @@ int main(void)
CHECK(err == 0, "读超长行文件失败: %s", r);
CHECK(strstr(r, " 1\ta") != NULL, "第 1 行应以 a 开头:\n%.120s", r);
CHECK(strstr(r, " 2\tsecond line") != NULL,
"超长行之后的第 2 行应是 second line (它不能被算成好几行):\n%.200s", r);
"超长行之后的第 2 行应是 second line (它不能被算成好几行): \n%.200s", r);
CHECK(strstr(r, " 3\tthird line") != NULL, "第 3 行应是 third line");
CHECK(strstr(r, " 4\t") == NULL, "不应该出现第 4 行");
free(r);
@@ -553,7 +553,7 @@ int main(void)
CHECK(after && strstr(after, "THIRD LINE") != NULL, "改动应落到文件里");
free(after);
/* 单行本身就超过输出上限:必须说清"这一行只给了开头", 不能说成
/* 单行本身就超过输出上限: 必须说清"这一行只给了开头", 不能说成
* "已截断, 从下一行继续" —— 那会让调用方以为拿到的是完整的行. */
FILE *hf = fopen("hugeline.txt", "wb");
for (int i = 0; i < 200000; i++) fputc('b', hf);
@@ -562,14 +562,14 @@ int main(void)
fclose(hf);
r = call("read_file", "{\"path\":\"hugeline.txt\"}", &err);
CHECK(strstr(r, "第 1 行本身就超过") != NULL,
"应说清是这一行超过上限:%.160s", r);
"应说清是这一行超过上限: %.160s", r);
CHECK(strstr(r, " 2\t") == NULL, "不能把剩下的半个行伪装成第 2 行");
free(r);
remove("hugeline.txt");
remove("longline.txt");
}
/* ---- 空目录:qsort 的第一个参数会拿到 NULL ---- */
/* ---- 空目录: qsort 的第一个参数会拿到 NULL ---- */
puts("list_dir 空目录");
if (mkdir("emptydir", 0755) != 0) { /* 可能已存在 */ }
r = call("list_dir", "{\"path\":\"emptydir\"}", &err);