@geoly-ai/social-hub-cli 0.3.26 → 0.3.27
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +7 -0
- package/dist/client.d.ts +12 -0
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +26 -3
- package/dist/client.js.map +1 -1
- package/dist/client.test.js +6 -1
- package/dist/client.test.js.map +1 -1
- package/dist/cmd-manifest.json +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +16 -5
- package/dist/index.js.map +1 -1
- package/dist/output.d.ts +15 -0
- package/dist/output.d.ts.map +1 -1
- package/dist/output.js +6 -1
- package/dist/output.js.map +1 -1
- package/dist/partial-list-guard.test.d.ts +2 -0
- package/dist/partial-list-guard.test.d.ts.map +1 -0
- package/dist/partial-list-guard.test.js +327 -0
- package/dist/partial-list-guard.test.js.map +1 -0
- package/package.json +3 -3
- package/skills/manifest.json +1 -1
- package/skills/social-hub-graph-compliance/SKILL.md +5 -0
package/dist/output.d.ts
CHANGED
|
@@ -5,6 +5,16 @@ export declare function resolveOutputFormat(opts: {
|
|
|
5
5
|
export declare function printResult(data: unknown, format?: OutputFormat): void;
|
|
6
6
|
export declare function parseJsonOption(raw: string | undefined): Record<string, unknown>;
|
|
7
7
|
export declare function formatCliError(e: unknown): string;
|
|
8
|
+
/**
|
|
9
|
+
* 把一行文本**同步**写进 stderr,写完再返回(D-06)。
|
|
10
|
+
*
|
|
11
|
+
* 不能用 `console.error` + `process.exit()`:Node 对管道的写在 **macOS 上是异步的**
|
|
12
|
+
* (Windows/Linux 同步),`process.exit()` 会把还没刷出去的尾巴截掉。错误消息一长
|
|
13
|
+
* (服务端返回超长 message 时)就会丢尾,于是「报错了但看不全」——这正是 D-06
|
|
14
|
+
* 那种「输出通道不可信」的同一类毛病。`fs.writeSync` 循环写到写完为止,既不截断,
|
|
15
|
+
* 也不需要为了等 flush 而放弃 `process.exit`(留句柄的 handler 会让进程挂死)。
|
|
16
|
+
*/
|
|
17
|
+
export declare function writeStderrSync(text: string): void;
|
|
8
18
|
/**
|
|
9
19
|
* per-command 错误边界(历史产物,392 处 `.action(` 里只有 72 处包了它)。
|
|
10
20
|
*
|
|
@@ -36,6 +46,11 @@ export declare function withCliErrorBoundary(run: () => Promise<void>): Promise<
|
|
|
36
46
|
* ⚠️ 这里不做任何「降级/截断/兜底成空结果」:比如 `accounts list -n 300` 超出
|
|
37
47
|
* 服务端上限 200 时必须报错退出,绝不能悄悄按 200 返回 —— 那只会把一种静默失败
|
|
38
48
|
* 换成另一种假数据。
|
|
49
|
+
*
|
|
50
|
+
* ⚠️ **同一套纪律也适用于「成功但不完整」的返回**:响应体里 `items.length < total`
|
|
51
|
+
* 时,警告走 **stderr**、stdout 保持干净可解析、**退出码不变**(不完整不是错误,
|
|
52
|
+
* 是需要被看见的事实)。落点在 `client.ts` 的 `partialListSink`,复用本文件的
|
|
53
|
+
* `writeStderrSync` —— 不要另起一套 stderr 写法。
|
|
39
54
|
*/
|
|
40
55
|
export declare function runCliProgram(parseArgv: () => Promise<unknown>): Promise<void>;
|
|
41
56
|
//# sourceMappingURL=output.d.ts.map
|
package/dist/output.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"output.d.ts","sourceRoot":"","sources":["../src/output.ts"],"names":[],"mappings":"AAMA,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,OAAO,GAAG,KAAK,GAAG,QAAQ,CAAC;AAM/D,wBAAgB,mBAAmB,CAAC,IAAI,EAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,YAAY,CAI3E;AAED,wBAAgB,WAAW,CACzB,IAAI,EAAE,OAAO,EACb,MAAM,GAAE,YAAqB,GAC5B,IAAI,CA0BN;AAED,wBAAgB,eAAe,CAC7B,GAAG,EAAE,MAAM,GAAG,SAAS,GACtB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAQzB;AAED,wBAAgB,cAAc,CAAC,CAAC,EAAE,OAAO,GAAG,MAAM,CA0CjD;
|
|
1
|
+
{"version":3,"file":"output.d.ts","sourceRoot":"","sources":["../src/output.ts"],"names":[],"mappings":"AAMA,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,OAAO,GAAG,KAAK,GAAG,QAAQ,CAAC;AAM/D,wBAAgB,mBAAmB,CAAC,IAAI,EAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,YAAY,CAI3E;AAED,wBAAgB,WAAW,CACzB,IAAI,EAAE,OAAO,EACb,MAAM,GAAE,YAAqB,GAC5B,IAAI,CA0BN;AAED,wBAAgB,eAAe,CAC7B,GAAG,EAAE,MAAM,GAAG,SAAS,GACtB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAQzB;AAED,wBAAgB,cAAc,CAAC,CAAC,EAAE,OAAO,GAAG,MAAM,CA0CjD;AAED;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAsBlD;AAOD;;;;;;;GAOG;AACH,wBAAsB,oBAAoB,CACxC,GAAG,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GACvB,OAAO,CAAC,IAAI,CAAC,CAOf;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAsB,aAAa,CACjC,SAAS,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,GAChC,OAAO,CAAC,IAAI,CAAC,CAqBf"}
|
package/dist/output.js
CHANGED
|
@@ -92,7 +92,7 @@ export function formatCliError(e) {
|
|
|
92
92
|
* 那种「输出通道不可信」的同一类毛病。`fs.writeSync` 循环写到写完为止,既不截断,
|
|
93
93
|
* 也不需要为了等 flush 而放弃 `process.exit`(留句柄的 handler 会让进程挂死)。
|
|
94
94
|
*/
|
|
95
|
-
function writeStderrSync(text) {
|
|
95
|
+
export function writeStderrSync(text) {
|
|
96
96
|
const bytes = Buffer.from(`${text}\n`, "utf8");
|
|
97
97
|
let offset = 0;
|
|
98
98
|
while (offset < bytes.length) {
|
|
@@ -160,6 +160,11 @@ export async function withCliErrorBoundary(run) {
|
|
|
160
160
|
* ⚠️ 这里不做任何「降级/截断/兜底成空结果」:比如 `accounts list -n 300` 超出
|
|
161
161
|
* 服务端上限 200 时必须报错退出,绝不能悄悄按 200 返回 —— 那只会把一种静默失败
|
|
162
162
|
* 换成另一种假数据。
|
|
163
|
+
*
|
|
164
|
+
* ⚠️ **同一套纪律也适用于「成功但不完整」的返回**:响应体里 `items.length < total`
|
|
165
|
+
* 时,警告走 **stderr**、stdout 保持干净可解析、**退出码不变**(不完整不是错误,
|
|
166
|
+
* 是需要被看见的事实)。落点在 `client.ts` 的 `partialListSink`,复用本文件的
|
|
167
|
+
* `writeStderrSync` —— 不要另起一套 stderr 写法。
|
|
163
168
|
*/
|
|
164
169
|
export async function runCliProgram(parseArgv) {
|
|
165
170
|
try {
|
package/dist/output.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"output.js","sourceRoot":"","sources":["../src/output.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"output.js","sourceRoot":"","sources":["../src/output.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"partial-list-guard.test.d.ts","sourceRoot":"","sources":["../src/partial-list-guard.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,327 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 「返回了不完整结果、但看起来像完整的」这一族缺陷的回归。
|
|
3
|
+
*
|
|
4
|
+
* 触发用例(运营侧生产实测):
|
|
5
|
+
* social-hub compliance blocklists-list --kind bot_bouncer
|
|
6
|
+
* → items: 100 条,但同一个返回体里 total: 112。CLI 当时**没有任何分页参数**,
|
|
7
|
+
* 所以通过 CLI 拿不到那 12 条,一条都拿不到。
|
|
8
|
+
*
|
|
9
|
+
* 为什么严重:运营侧 skill 明文要求 agent 跑这条命令做板块准入判断(命中即禁入),
|
|
10
|
+
* 所以 agent 每天在用一份不全的黑名单做安全判断,而且它不知道自己漏了。
|
|
11
|
+
* 漏的还不是随机 12 条 —— 默认按 `createdAt DESC`,漏掉的是**最早加入**的那批,
|
|
12
|
+
* 往往是最确定该封的。这个失效方式在 packages/db/src/subreddit-blocklists.ts
|
|
13
|
+
* 的注释里被预言过。
|
|
14
|
+
*
|
|
15
|
+
* 这一族此前已经复发四次(accounts list -n 300 静默空、pools catalog-list 默认单页 50、
|
|
16
|
+
* blocklists-list 截断 100、以及测试断言自己空过),所以这里验两件事:
|
|
17
|
+
* ① blocklists-list 默认自动翻页,最终必须给出**全部** 112 条,且必须**真的**
|
|
18
|
+
* 发出了第二次带 offset 的请求(只断言条数会被「stub 一次给 112 条」蒙混过去)。
|
|
19
|
+
* ② 通用收口:任何返回体同时有 items 与 total 且 items.length < total 时,
|
|
20
|
+
* CLI 在 **stderr** 打警告 —— stdout 保持干净可解析、退出码不变。
|
|
21
|
+
*
|
|
22
|
+
* ⚠️ 三个通道**分开断言,绝不用 `2>&1` 合并** —— 合并后就分不清警告到底打到了
|
|
23
|
+
* 哪个通道,而「警告漏进 stdout」正是会把下游 `jq` 打挂的那种回归
|
|
24
|
+
* (与 cli-error-channels.test.ts 同一条纪律,D-06)。
|
|
25
|
+
*/
|
|
26
|
+
import { execFile, execFileSync } from "node:child_process";
|
|
27
|
+
import { createServer } from "node:http";
|
|
28
|
+
import { existsSync, mkdtempSync } from "node:fs";
|
|
29
|
+
import { tmpdir } from "node:os";
|
|
30
|
+
import { dirname, join } from "node:path";
|
|
31
|
+
import { fileURLToPath } from "node:url";
|
|
32
|
+
import { afterAll, beforeAll, describe, expect, it } from "vitest";
|
|
33
|
+
const pkgRoot = join(dirname(fileURLToPath(import.meta.url)), "..");
|
|
34
|
+
const cliEntry = join(pkgRoot, "dist", "index.js");
|
|
35
|
+
/** 生产实测的那组数字:total 112,服务端单页上限 200、默认 100。 */
|
|
36
|
+
const BLOCKLIST_TOTAL = 112;
|
|
37
|
+
/** 服务端默认页大小 —— 缺陷现场就是「只拿到这么多」。 */
|
|
38
|
+
const SERVER_DEFAULT_LIMIT = 100;
|
|
39
|
+
/** accounts stub 的总条数(通用截断警告用)。 */
|
|
40
|
+
const ACCOUNTS_TOTAL = 7;
|
|
41
|
+
let server;
|
|
42
|
+
let baseUrl;
|
|
43
|
+
let configDir;
|
|
44
|
+
/** 服务端实际收到的每一次请求 —— 用来证明确实发生了第二次带 offset 的翻页。 */
|
|
45
|
+
const seenRequests = [];
|
|
46
|
+
/**
|
|
47
|
+
* 置真后,blocklist 端点每被请求一次就把 total 报大 1 ——
|
|
48
|
+
* 模拟「翻页期间一直有人在增删」,让任何一趟都无法自证一致。
|
|
49
|
+
*/
|
|
50
|
+
let blocklistTotalDrifts = false;
|
|
51
|
+
/** drift 模式下已发生的请求次数。 */
|
|
52
|
+
let blocklistDriftTicks = 0;
|
|
53
|
+
function blocklistRow(index) {
|
|
54
|
+
return {
|
|
55
|
+
id: `00000000-0000-4000-8000-${String(index).padStart(12, "0")}`,
|
|
56
|
+
kind: "bot_bouncer",
|
|
57
|
+
subreddit: `sub_${index}`,
|
|
58
|
+
reason: null,
|
|
59
|
+
source: null,
|
|
60
|
+
expiresAt: null,
|
|
61
|
+
// createdAt DESC:index 越大越新。第一页给的是最新的那批,
|
|
62
|
+
// 漏掉的是 index 最小、也就是最早加入的那批。
|
|
63
|
+
createdAt: new Date(1_700_000_000_000 + index * 1000).toISOString(),
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
/** 全量 112 行,按 createdAt DESC(与生产排序一致)。 */
|
|
67
|
+
const ALL_ROWS = Array.from({ length: BLOCKLIST_TOTAL }, (_, i) => blocklistRow(BLOCKLIST_TOTAL - i));
|
|
68
|
+
function runCli(args) {
|
|
69
|
+
return new Promise((resolve) => {
|
|
70
|
+
// ⚠️ 不合并通道:execFile 天然把 stdout / stderr 分开给回来。
|
|
71
|
+
execFile(process.execPath, [cliEntry, ...args], {
|
|
72
|
+
env: {
|
|
73
|
+
...process.env,
|
|
74
|
+
VITEST: "",
|
|
75
|
+
SOCIAL_HUB_CONFIG_DIR: configDir,
|
|
76
|
+
SOCIAL_HUB_API_URL: baseUrl,
|
|
77
|
+
SOCIAL_HUB_API_KEY: "test-key",
|
|
78
|
+
SOCIAL_HUB_TEAM_ID: "11111111-1111-1111-1111-111111111111",
|
|
79
|
+
// 关掉自更新/skill 同步,否则它们的提示会污染 stderr 断言。
|
|
80
|
+
SOCIAL_HUB_NO_UPDATE_CHECK: "1",
|
|
81
|
+
SOCIAL_HUB_NO_SKILL_CHECK: "1",
|
|
82
|
+
SOCIAL_HUB_NO_AUTO_UPDATE: "1",
|
|
83
|
+
SOCIAL_HUB_NO_SKILLS_AUTO_UPDATE: "1",
|
|
84
|
+
},
|
|
85
|
+
// 自动翻页若回归成死循环,给硬超时让它以失败告终而不是把测试挂死。
|
|
86
|
+
timeout: 30_000,
|
|
87
|
+
maxBuffer: 16 * 1024 * 1024,
|
|
88
|
+
}, (err, stdout, stderr) => {
|
|
89
|
+
const code = err && typeof err.code === "number"
|
|
90
|
+
? err.code
|
|
91
|
+
: err
|
|
92
|
+
? 1
|
|
93
|
+
: 0;
|
|
94
|
+
resolve({ code, stdout, stderr });
|
|
95
|
+
});
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
beforeAll(async () => {
|
|
99
|
+
// 必须跑真实的 bin(dist/index.js):要验的是**进程**的三个输出通道,
|
|
100
|
+
// 在 vitest 进程内 import program 是验不了 stdout/stderr 分离的。
|
|
101
|
+
// 与 cli-error-channels.test.ts 同理,这里显式编译一次。
|
|
102
|
+
try {
|
|
103
|
+
execFileSync(process.execPath, [join(pkgRoot, "node_modules", "typescript", "bin", "tsc")], { cwd: pkgRoot, stdio: "pipe" });
|
|
104
|
+
}
|
|
105
|
+
catch (e) {
|
|
106
|
+
const { stdout, stderr } = e;
|
|
107
|
+
throw new Error(`CLI tsc build failed:\n${stdout?.toString() ?? ""}\n${stderr?.toString() ?? ""}`);
|
|
108
|
+
}
|
|
109
|
+
expect(existsSync(cliEntry)).toBe(true);
|
|
110
|
+
configDir = mkdtempSync(join(tmpdir(), "social-hub-cli-partial-"));
|
|
111
|
+
server = createServer((req, res) => {
|
|
112
|
+
const url = new URL(req.url ?? "/", "http://stub.local");
|
|
113
|
+
const rawLimit = url.searchParams.get("limit");
|
|
114
|
+
const rawOffset = url.searchParams.get("offset");
|
|
115
|
+
seenRequests.push({
|
|
116
|
+
path: url.pathname,
|
|
117
|
+
limit: rawLimit,
|
|
118
|
+
offset: rawOffset,
|
|
119
|
+
});
|
|
120
|
+
if (url.pathname === "/v1/system/subreddit-blocklists") {
|
|
121
|
+
// 单页**硬顶 100**,即使调用方传了更大的 limit —— 这样才复现生产现场
|
|
122
|
+
// (total=112 / 单页 100),也顺带钉住一条正确性:翻页必须按服务端**实际返回**
|
|
123
|
+
// 的条数推进 offset,不能按自己请求的 limit 推进。后者在服务端给的比要的少时
|
|
124
|
+
// 会跳过整段数据 —— 又是一次「看起来完整的不完整结果」。
|
|
125
|
+
const limit = Math.min(rawLimit === null ? SERVER_DEFAULT_LIMIT : Number(rawLimit), SERVER_DEFAULT_LIMIT);
|
|
126
|
+
const offset = rawOffset === null ? 0 : Number(rawOffset);
|
|
127
|
+
let total = BLOCKLIST_TOTAL;
|
|
128
|
+
if (blocklistTotalDrifts) {
|
|
129
|
+
blocklistDriftTicks += 1;
|
|
130
|
+
total = BLOCKLIST_TOTAL + blocklistDriftTicks;
|
|
131
|
+
}
|
|
132
|
+
res.writeHead(200, { "content-type": "application/json" });
|
|
133
|
+
res.end(JSON.stringify({
|
|
134
|
+
items: ALL_ROWS.slice(offset, offset + limit),
|
|
135
|
+
total,
|
|
136
|
+
limit,
|
|
137
|
+
offset,
|
|
138
|
+
}));
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
// 通用截断警告用。两种形态由 limit 选:
|
|
142
|
+
// · 不传 limit → 只给 2 条但 total=7 → **截断**,必须警告;
|
|
143
|
+
// · limit>=7 → 给满 7 条且 total=7 → **完整**,必须**静默**。
|
|
144
|
+
// 后者是阈值的边界用例:少了它,把判据从 `<` 写成 `<=` 的回归抓不住
|
|
145
|
+
// (per-page 的中间态永远是严格小于,碰不到相等这一点)。
|
|
146
|
+
if (url.pathname.endsWith("/accounts")) {
|
|
147
|
+
const wanted = rawLimit === null ? 2 : Number(rawLimit);
|
|
148
|
+
const shown = Math.min(wanted, ACCOUNTS_TOTAL);
|
|
149
|
+
res.writeHead(200, { "content-type": "application/json" });
|
|
150
|
+
res.end(JSON.stringify({
|
|
151
|
+
items: Array.from({ length: shown }, (_, i) => ({
|
|
152
|
+
id: `a-${i + 1}`,
|
|
153
|
+
})),
|
|
154
|
+
total: ACCOUNTS_TOTAL,
|
|
155
|
+
limit: wanted,
|
|
156
|
+
offset: 0,
|
|
157
|
+
}));
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
// 计数被封顶 / 没有总数的端点(0140 起的评论样本形状):
|
|
161
|
+
// total 不是精确条数,分页信号只有 hasMore。
|
|
162
|
+
if (url.pathname === "/v1/system/subreddit-intelligence/comments") {
|
|
163
|
+
res.writeHead(200, { "content-type": "application/json" });
|
|
164
|
+
res.end(JSON.stringify({
|
|
165
|
+
items: [{ id: "c-1" }],
|
|
166
|
+
total: 1,
|
|
167
|
+
// total 与 items.length 相等 —— 只按数字判会认为「已经全了」,
|
|
168
|
+
// 但服务端明说还有。这条只有 hasMore 判据能抓住。
|
|
169
|
+
totalRelation: "gte",
|
|
170
|
+
hasMore: true,
|
|
171
|
+
}));
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
res.writeHead(404, { "content-type": "application/json" });
|
|
175
|
+
res.end(JSON.stringify({ error: { message: "not stubbed" } }));
|
|
176
|
+
});
|
|
177
|
+
await new Promise((resolve) => {
|
|
178
|
+
server.listen(0, "127.0.0.1", resolve);
|
|
179
|
+
});
|
|
180
|
+
const addr = server.address();
|
|
181
|
+
if (typeof addr === "string" || addr === null)
|
|
182
|
+
throw new Error("no port");
|
|
183
|
+
baseUrl = `http://127.0.0.1:${addr.port}`;
|
|
184
|
+
}, 120_000);
|
|
185
|
+
afterAll(async () => {
|
|
186
|
+
await new Promise((resolve) => server.close(() => resolve()));
|
|
187
|
+
});
|
|
188
|
+
describe("blocklists-list 默认自动翻页拉全量", () => {
|
|
189
|
+
it("total=112 但单页上限时,仍输出 112 条,且真的发出了带 offset 的第二次请求", async () => {
|
|
190
|
+
seenRequests.length = 0;
|
|
191
|
+
blocklistTotalDrifts = false;
|
|
192
|
+
const { code, stdout, stderr } = await runCli([
|
|
193
|
+
"compliance",
|
|
194
|
+
"blocklists-list",
|
|
195
|
+
"--kind",
|
|
196
|
+
"bot_bouncer",
|
|
197
|
+
]);
|
|
198
|
+
// ① stdout 通道:必须是干净可解析的 JSON,且**条数就是 total**。
|
|
199
|
+
// 这是这条命令存在的全部意义 —— 少一条就是一次错误的准入放行。
|
|
200
|
+
const parsed = JSON.parse(stdout);
|
|
201
|
+
expect(parsed.total).toBe(BLOCKLIST_TOTAL);
|
|
202
|
+
expect(parsed.items).toHaveLength(BLOCKLIST_TOTAL);
|
|
203
|
+
// 漏的不是随机 12 条,是**最早加入**的那批(createdAt DESC 的尾巴)。
|
|
204
|
+
// 所以专门钉住尾巴那几条在不在 —— 只断言长度挡不住「补了 12 条重复的」。
|
|
205
|
+
const subs = new Set(parsed.items.map((r) => r.subreddit));
|
|
206
|
+
expect(subs.size).toBe(BLOCKLIST_TOTAL);
|
|
207
|
+
for (const oldest of ["sub_1", "sub_2", "sub_12"]) {
|
|
208
|
+
expect(subs.has(oldest)).toBe(true);
|
|
209
|
+
}
|
|
210
|
+
// ② 必须**真的**翻了页 —— stub 分片给出,只有第二次带 offset 的请求
|
|
211
|
+
// 才可能凑齐 112 条。只断言条数会被「一次就给全」的实现蒙混过去。
|
|
212
|
+
const pages = seenRequests.filter((r) => r.path === "/v1/system/subreddit-blocklists");
|
|
213
|
+
expect(pages.length).toBeGreaterThanOrEqual(2);
|
|
214
|
+
expect(pages[0]?.offset).toBe("0");
|
|
215
|
+
expect(Number(pages[1]?.offset)).toBeGreaterThan(0);
|
|
216
|
+
// ③ 退出码 0,且 stderr 里**没有**截断警告 —— 拿到的就是全量,
|
|
217
|
+
// 翻页中间态的 per-page 警告必须被抑制,否则拉全量反而刷一屏假警告。
|
|
218
|
+
expect(code).toBe(0);
|
|
219
|
+
expect(stderr).not.toContain("mode=truncated");
|
|
220
|
+
}, 60_000);
|
|
221
|
+
it("不提供 --limit/--offset 逃生口(安全闸不留部分结果的路)", async () => {
|
|
222
|
+
const { code, stdout, stderr } = await runCli([
|
|
223
|
+
"compliance",
|
|
224
|
+
"blocklists-list",
|
|
225
|
+
"--limit",
|
|
226
|
+
"10",
|
|
227
|
+
]);
|
|
228
|
+
// commander 对未知 option 报错退出:证明这个口子确实没开。
|
|
229
|
+
expect(code).not.toBe(0);
|
|
230
|
+
expect(stdout).toBe("");
|
|
231
|
+
expect(stderr).toContain("unknown option");
|
|
232
|
+
}, 60_000);
|
|
233
|
+
it("翻页期间 total 一直在变 → 报错,绝不静默拼一个可能不一致的结果", async () => {
|
|
234
|
+
seenRequests.length = 0;
|
|
235
|
+
blocklistTotalDrifts = true;
|
|
236
|
+
blocklistDriftTicks = 0;
|
|
237
|
+
const { code, stdout, stderr } = await runCli([
|
|
238
|
+
"compliance",
|
|
239
|
+
"blocklists-list",
|
|
240
|
+
]);
|
|
241
|
+
blocklistTotalDrifts = false;
|
|
242
|
+
// stdout 零字节:宁可什么都不给,也不给一个「可能不全但看起来完整」的结果。
|
|
243
|
+
// 这是本次修复的核心取舍 —— 对安全闸来说「没有答案」是安全的(重跑一次即可),
|
|
244
|
+
// 而「一个可能不全、但看起来完整的答案」正是本次要消灭的缺陷本身。
|
|
245
|
+
expect(stdout).toBe("");
|
|
246
|
+
expect(code).toBe(1);
|
|
247
|
+
expect(stderr).toContain("possibly-incomplete blocklist");
|
|
248
|
+
// 必须**真的**重试满 3 趟才放弃,不是一遇到不一致就报错。
|
|
249
|
+
expect(stderr).toContain("attempt 3");
|
|
250
|
+
}, 60_000);
|
|
251
|
+
});
|
|
252
|
+
describe("通用收口:items.length < total 一律 stderr 警告", () => {
|
|
253
|
+
it("stdout 仍是干净可解析 JSON / 警告只在 stderr / 退出码不变", async () => {
|
|
254
|
+
seenRequests.length = 0;
|
|
255
|
+
// 显式给 -n 2:让服务端只给 2 条而 total 是 7 —— 这正是「拿到一页、
|
|
256
|
+
// 却看起来像全量」的形状。(不传 -n 的话 CLI 有自己的默认 limit,
|
|
257
|
+
// stub 会给满 7 条,反而验不到截断。)
|
|
258
|
+
const { code, stdout, stderr } = await runCli([
|
|
259
|
+
"accounts",
|
|
260
|
+
"list",
|
|
261
|
+
"-n",
|
|
262
|
+
"2",
|
|
263
|
+
]);
|
|
264
|
+
// ① stdout:干净、可 JSON.parse —— 警告一个字节都不许漏进来。
|
|
265
|
+
const parsed = JSON.parse(stdout);
|
|
266
|
+
expect(parsed.items).toHaveLength(2);
|
|
267
|
+
expect(parsed.total).toBe(7);
|
|
268
|
+
expect(stdout).not.toContain("mode=truncated");
|
|
269
|
+
expect(stdout).not.toContain("[warn]");
|
|
270
|
+
// ② stderr:必须有警告,且把三个关键数字都说清楚
|
|
271
|
+
// (拿到几条 / 一共几条 / 缺几条),否则 agent 看到也不知道该干嘛。
|
|
272
|
+
expect(stderr).toContain("mode=truncated");
|
|
273
|
+
expect(stderr).toContain("items=2");
|
|
274
|
+
expect(stderr).toContain("total=7");
|
|
275
|
+
expect(stderr).toContain("缺 5 条");
|
|
276
|
+
// ③ 退出码不变 —— 不完整是需要被看见的**事实**,不是错误。
|
|
277
|
+
// 当成错误退出会打断一批把 items 当分页用的既有脚本。
|
|
278
|
+
expect(code).toBe(0);
|
|
279
|
+
}, 60_000);
|
|
280
|
+
it("total 被封顶(totalRelation=gte)时靠 hasMore 判,且不编造「缺 N 条」", async () => {
|
|
281
|
+
seenRequests.length = 0;
|
|
282
|
+
// 服务端给的是 items=1 / total=1 / totalRelation=gte / hasMore=true。
|
|
283
|
+
// 只按 `items.length < total` 判会认为「已经全了」而**静默放过** ——
|
|
284
|
+
// 0140 起评论样本正是这个形状,漏的是一整类端点。
|
|
285
|
+
const { code, stdout, stderr } = await runCli([
|
|
286
|
+
"intelligence",
|
|
287
|
+
"comments",
|
|
288
|
+
"--subreddit",
|
|
289
|
+
"test",
|
|
290
|
+
]);
|
|
291
|
+
expect(code).toBe(0);
|
|
292
|
+
expect(JSON.parse(stdout).items).toHaveLength(1);
|
|
293
|
+
// 必须报,且必须点明 total 只是下界。
|
|
294
|
+
expect(stderr).toContain("mode=truncated");
|
|
295
|
+
expect(stderr).toContain("gte");
|
|
296
|
+
// 🔴 绝不能算出「缺 0 条」这种既错又误导的数字 —— total 是下界,缺口算不出来。
|
|
297
|
+
expect(stderr).not.toContain("缺 0 条");
|
|
298
|
+
}, 60_000);
|
|
299
|
+
it("警告文案不写死 --limit/--offset(blocklists 刻意没有这两个参数)", async () => {
|
|
300
|
+
seenRequests.length = 0;
|
|
301
|
+
const { stderr } = await runCli(["accounts", "list", "-n", "2"]);
|
|
302
|
+
expect(stderr).toContain("mode=truncated");
|
|
303
|
+
// 通用文案若写死「用 --limit/--offset 翻页」,照着做的 agent 在
|
|
304
|
+
// blocklists-list 上会撞 "unknown option" —— 提示必须是条件式的。
|
|
305
|
+
expect(stderr).not.toContain("用 --limit/--offset 翻页");
|
|
306
|
+
}, 60_000);
|
|
307
|
+
it("items.length === total 时不打警告(否则每条列表命令都刷噪音)", async () => {
|
|
308
|
+
seenRequests.length = 0;
|
|
309
|
+
// ⚠️ 这一条必须打到**恰好相等**这个点上。翻页的 per-page 中间态永远是
|
|
310
|
+
// 严格小于,碰不到相等 —— 用它来验「相等不警告」是验不出来的
|
|
311
|
+
// (实测:把判据从 `>=` 改成 `>` 的变异能存活)。所以这里显式让服务端
|
|
312
|
+
// 一次给满 7 条、total 也是 7。
|
|
313
|
+
const { code, stdout, stderr } = await runCli([
|
|
314
|
+
"accounts",
|
|
315
|
+
"list",
|
|
316
|
+
"-n",
|
|
317
|
+
String(ACCOUNTS_TOTAL),
|
|
318
|
+
]);
|
|
319
|
+
const parsed = JSON.parse(stdout);
|
|
320
|
+
expect(parsed.items).toHaveLength(ACCOUNTS_TOTAL);
|
|
321
|
+
expect(parsed.total).toBe(ACCOUNTS_TOTAL);
|
|
322
|
+
expect(code).toBe(0);
|
|
323
|
+
expect(stderr).not.toContain("mode=truncated");
|
|
324
|
+
expect(stderr).not.toContain("[warn]");
|
|
325
|
+
}, 60_000);
|
|
326
|
+
});
|
|
327
|
+
//# sourceMappingURL=partial-list-guard.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"partial-list-guard.test.js","sourceRoot":"","sources":["../src/partial-list-guard.test.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@geoly-ai/social-hub-cli",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.27",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "social-hub CLI for Social Ops Hub",
|
|
6
6
|
"repository": {
|
|
@@ -22,8 +22,8 @@
|
|
|
22
22
|
},
|
|
23
23
|
"dependencies": {
|
|
24
24
|
"commander": "^12.1.0",
|
|
25
|
-
"@geoly-ai/social-hub-
|
|
26
|
-
"@geoly-ai/social-hub-
|
|
25
|
+
"@geoly-ai/social-hub-authz": "0.0.19",
|
|
26
|
+
"@geoly-ai/social-hub-sdk": "0.1.3"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
29
|
"@types/node": "^22.10.2",
|
package/skills/manifest.json
CHANGED
|
@@ -47,8 +47,13 @@ social-hub graph project --all [--dry-run] # 全部可见团队
|
|
|
47
47
|
```bash
|
|
48
48
|
social-hub compliance sanctions-list -t <team-id> [--account <uuid>] [--sub <name>]
|
|
49
49
|
social-hub compliance sanctions-create -t <team-id> -j '{"socialAccountId":"<uuid>","subreddit":"example","status":"blocked","reason":"..."}'
|
|
50
|
+
# 返回 {"id":"...","created":true|false}。created=false = 已有一条**同账号×同板块×同 status**
|
|
51
|
+
# 的生效制裁,这次什么都没建(服务端按归一后的板块名去重,大小写/`r/` 前缀/空白都算同一个板)。
|
|
52
|
+
# ⚠️ created=false 时**不会**用你传的 reason/expiresAt 去覆盖已有行 —— 要改已有制裁请用
|
|
53
|
+
# sanctions-update,别靠重复 create。板块名落库时统一归一成小写、去 `r/`。
|
|
50
54
|
# 解除制裁只认 status:"lifted"(枚举 warned/banned/restricted/blocked/cooldown/shadowbanned_suspected/lifted);
|
|
51
55
|
# HTTP API 对 resolved/cleared 等旧值直接 400(仅内部导入路径会归一),必须写 lifted
|
|
56
|
+
# ⚠️ 解封要 sanctions-update **旧那条行**;新建一条 lifted 不会解除已有的 banned 行。
|
|
52
57
|
social-hub compliance sanctions-update -t <team-id> --id <sanction-uuid> -j '{"status":"lifted"}'
|
|
53
58
|
social-hub compliance sanctions-delete -t <team-id> --id <sanction-uuid>
|
|
54
59
|
|