@geoly-ai/social-hub-cli 0.2.18 → 0.2.20
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 +16 -0
- package/dist/cmd-manifest.json +3 -2
- package/dist/index.d.ts +22 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +224 -0
- package/dist/index.js.map +1 -1
- package/dist/voc-acquire.test.d.ts +2 -0
- package/dist/voc-acquire.test.d.ts.map +1 -0
- package/dist/voc-acquire.test.js +253 -0
- package/dist/voc-acquire.test.js.map +1 -0
- package/package.json +3 -3
- package/skills/manifest.json +1 -1
- package/skills/social-hub-intelligence/SKILL.md +20 -2
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"voc-acquire.test.d.ts","sourceRoot":"","sources":["../src/voc-acquire.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
import { describe, expect, it, vi } from "vitest";
|
|
2
|
+
import { orchestrateVocAcquire } from "./index.js";
|
|
3
|
+
// 受控时钟:每次 now() 前进一固定步长;sleep 也推进时钟(便于 deadline 断言)。
|
|
4
|
+
function fakeClock(stepMs = 1000) {
|
|
5
|
+
let t = 0;
|
|
6
|
+
return {
|
|
7
|
+
now: () => t,
|
|
8
|
+
sleep: async (ms) => {
|
|
9
|
+
t += ms || stepMs;
|
|
10
|
+
},
|
|
11
|
+
advance: (ms) => {
|
|
12
|
+
t += ms;
|
|
13
|
+
},
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
const coverage = (satisfied) => ({ overall: { satisfied } });
|
|
17
|
+
function baseParams(clock, over = {}) {
|
|
18
|
+
return {
|
|
19
|
+
query: {},
|
|
20
|
+
requirements: {},
|
|
21
|
+
maxRounds: 3,
|
|
22
|
+
timeoutMs: 60_000,
|
|
23
|
+
pollMs: 1_000,
|
|
24
|
+
async: false,
|
|
25
|
+
now: clock.now,
|
|
26
|
+
sleep: clock.sleep,
|
|
27
|
+
...over,
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
describe("orchestrateVocAcquire", () => {
|
|
31
|
+
it("第一轮已满足 → exitCode 0", async () => {
|
|
32
|
+
const clock = fakeClock();
|
|
33
|
+
const client = {
|
|
34
|
+
getAuthContext: vi.fn(async () => ({ role: "manager" })),
|
|
35
|
+
vocQuery: vi.fn(async () => ({
|
|
36
|
+
coverage: coverage(true),
|
|
37
|
+
dispatched: [],
|
|
38
|
+
})),
|
|
39
|
+
getIntelRunProgress: vi.fn(),
|
|
40
|
+
};
|
|
41
|
+
const { exitCode, output } = await orchestrateVocAcquire(client, baseParams(clock));
|
|
42
|
+
expect(exitCode).toBe(0);
|
|
43
|
+
expect(output.status).toBe("satisfied");
|
|
44
|
+
expect(client.getIntelRunProgress).not.toHaveBeenCalled();
|
|
45
|
+
});
|
|
46
|
+
it("client 角色在派发前被拒 → exitCode 1(不调 vocQuery)", async () => {
|
|
47
|
+
const clock = fakeClock();
|
|
48
|
+
const client = {
|
|
49
|
+
getAuthContext: vi.fn(async () => ({ role: "client" })),
|
|
50
|
+
vocQuery: vi.fn(),
|
|
51
|
+
getIntelRunProgress: vi.fn(),
|
|
52
|
+
};
|
|
53
|
+
const { exitCode, output } = await orchestrateVocAcquire(client, baseParams(clock));
|
|
54
|
+
expect(exitCode).toBe(1);
|
|
55
|
+
expect(output.status).toBe("forbidden");
|
|
56
|
+
expect(client.vocQuery).not.toHaveBeenCalled();
|
|
57
|
+
});
|
|
58
|
+
it("派发→轮询到终态→重算满足 → exitCode 0", async () => {
|
|
59
|
+
const clock = fakeClock();
|
|
60
|
+
let progressCalls = 0;
|
|
61
|
+
const client = {
|
|
62
|
+
getAuthContext: vi.fn(async () => ({ role: "manager" })),
|
|
63
|
+
vocQuery: vi
|
|
64
|
+
.fn()
|
|
65
|
+
.mockResolvedValueOnce({
|
|
66
|
+
coverage: coverage(false),
|
|
67
|
+
dispatched: [{ runId: "r1" }, { runId: "r1" }],
|
|
68
|
+
})
|
|
69
|
+
.mockResolvedValueOnce({ coverage: coverage(true), dispatched: [] }),
|
|
70
|
+
getIntelRunProgress: vi.fn(async () => {
|
|
71
|
+
progressCalls += 1;
|
|
72
|
+
return { status: progressCalls >= 2 ? "succeeded" : "running" };
|
|
73
|
+
}),
|
|
74
|
+
};
|
|
75
|
+
const { exitCode } = await orchestrateVocAcquire(client, baseParams(clock));
|
|
76
|
+
expect(exitCode).toBe(0);
|
|
77
|
+
// dispatched 去重:只轮询 r1 一次(直到终态)。
|
|
78
|
+
expect(client.vocQuery).toHaveBeenCalledTimes(2); // dispatch 轮 + 最终验收
|
|
79
|
+
});
|
|
80
|
+
it("--async 只派一轮 → exitCode 2(不轮询)", async () => {
|
|
81
|
+
const clock = fakeClock();
|
|
82
|
+
const client = {
|
|
83
|
+
getAuthContext: vi.fn(async () => ({ role: "manager" })),
|
|
84
|
+
vocQuery: vi.fn(async () => ({
|
|
85
|
+
coverage: coverage(false),
|
|
86
|
+
dispatched: [{ runId: "r1" }],
|
|
87
|
+
})),
|
|
88
|
+
getIntelRunProgress: vi.fn(),
|
|
89
|
+
};
|
|
90
|
+
const { exitCode, output } = await orchestrateVocAcquire(client, baseParams(clock, { async: true }));
|
|
91
|
+
expect(exitCode).toBe(2);
|
|
92
|
+
expect(output.status).toBe("dispatched");
|
|
93
|
+
expect(client.getIntelRunProgress).not.toHaveBeenCalled();
|
|
94
|
+
});
|
|
95
|
+
it("run 进度 403 → exitCode 1(能派不能读,不误当完成)", async () => {
|
|
96
|
+
const clock = fakeClock();
|
|
97
|
+
const client = {
|
|
98
|
+
getAuthContext: vi.fn(async () => ({ role: "senior" })),
|
|
99
|
+
vocQuery: vi.fn(async () => ({
|
|
100
|
+
coverage: coverage(false),
|
|
101
|
+
dispatched: [{ runId: "r1" }],
|
|
102
|
+
})),
|
|
103
|
+
getIntelRunProgress: vi.fn(async () => {
|
|
104
|
+
throw new Error("HTTP 403: forbidden");
|
|
105
|
+
}),
|
|
106
|
+
};
|
|
107
|
+
const { exitCode, output } = await orchestrateVocAcquire(client, baseParams(clock));
|
|
108
|
+
expect(exitCode).toBe(1);
|
|
109
|
+
expect(output.status).toBe("forbidden");
|
|
110
|
+
});
|
|
111
|
+
it("网络错误重试、不误删 pending;终态后完成", async () => {
|
|
112
|
+
const clock = fakeClock();
|
|
113
|
+
let calls = 0;
|
|
114
|
+
const client = {
|
|
115
|
+
getAuthContext: vi.fn(async () => ({ role: "manager" })),
|
|
116
|
+
vocQuery: vi
|
|
117
|
+
.fn()
|
|
118
|
+
.mockResolvedValueOnce({
|
|
119
|
+
coverage: coverage(false),
|
|
120
|
+
dispatched: [{ runId: "r1" }],
|
|
121
|
+
})
|
|
122
|
+
.mockResolvedValueOnce({ coverage: coverage(true), dispatched: [] }),
|
|
123
|
+
getIntelRunProgress: vi.fn(async () => {
|
|
124
|
+
calls += 1;
|
|
125
|
+
if (calls === 1)
|
|
126
|
+
throw new Error("network ECONNRESET"); // 无 HTTP status
|
|
127
|
+
return { status: "succeeded" };
|
|
128
|
+
}),
|
|
129
|
+
};
|
|
130
|
+
const { exitCode } = await orchestrateVocAcquire(client, baseParams(clock));
|
|
131
|
+
expect(exitCode).toBe(0);
|
|
132
|
+
expect(calls).toBe(2); // 第一次网络错保留 pending,第二次成功。
|
|
133
|
+
});
|
|
134
|
+
it("轮询超时 → exitCode 2 + pendingRunIds", async () => {
|
|
135
|
+
const clock = fakeClock();
|
|
136
|
+
const client = {
|
|
137
|
+
getAuthContext: vi.fn(async () => ({ role: "manager" })),
|
|
138
|
+
vocQuery: vi.fn(async () => ({
|
|
139
|
+
coverage: coverage(false),
|
|
140
|
+
dispatched: [{ runId: "r1" }],
|
|
141
|
+
})),
|
|
142
|
+
getIntelRunProgress: vi.fn(async () => ({ status: "running" })), // 永不终态
|
|
143
|
+
};
|
|
144
|
+
// 短超时:sleep 每次推进 1000ms,几轮后越界。
|
|
145
|
+
const { exitCode, output } = await orchestrateVocAcquire(client, baseParams(clock, { timeoutMs: 3_000 }));
|
|
146
|
+
expect(exitCode).toBe(2);
|
|
147
|
+
expect(output.status).toBe("timeout");
|
|
148
|
+
expect(output.pendingRunIds).toEqual(["r1"]);
|
|
149
|
+
});
|
|
150
|
+
it("多轮后仍不满足 → exitCode 2 + externalImportMayBeRequired", async () => {
|
|
151
|
+
const clock = fakeClock();
|
|
152
|
+
const client = {
|
|
153
|
+
getAuthContext: vi.fn(async () => ({ role: "manager" })),
|
|
154
|
+
// 每轮都派发但从不满足;终态立即达成推进轮次。
|
|
155
|
+
vocQuery: vi.fn(async () => ({
|
|
156
|
+
coverage: coverage(false),
|
|
157
|
+
dispatched: [{ runId: "r1" }],
|
|
158
|
+
})),
|
|
159
|
+
getIntelRunProgress: vi.fn(async () => ({ status: "succeeded" })),
|
|
160
|
+
};
|
|
161
|
+
const { exitCode, output } = await orchestrateVocAcquire(client, baseParams(clock, { maxRounds: 2 }));
|
|
162
|
+
expect(exitCode).toBe(2);
|
|
163
|
+
expect(output.status).toBe("unsatisfied");
|
|
164
|
+
expect(output.externalImportMayBeRequired).toBe(true);
|
|
165
|
+
expect(output.recommendedCommand).toContain("evidence-import");
|
|
166
|
+
});
|
|
167
|
+
it("run 进度 404 → exitCode 1(run_not_found)", async () => {
|
|
168
|
+
const clock = fakeClock();
|
|
169
|
+
const client = {
|
|
170
|
+
getAuthContext: vi.fn(async () => ({ role: "manager" })),
|
|
171
|
+
vocQuery: vi.fn(async () => ({
|
|
172
|
+
coverage: coverage(false),
|
|
173
|
+
dispatched: [{ runId: "r1" }],
|
|
174
|
+
})),
|
|
175
|
+
getIntelRunProgress: vi.fn(async () => {
|
|
176
|
+
throw new Error("HTTP 404: not found");
|
|
177
|
+
}),
|
|
178
|
+
};
|
|
179
|
+
const { exitCode, output } = await orchestrateVocAcquire(client, baseParams(clock));
|
|
180
|
+
expect(exitCode).toBe(1);
|
|
181
|
+
expect(output.status).toBe("run_not_found");
|
|
182
|
+
});
|
|
183
|
+
it("请求永不 resolve → 真实定时器触发 → timeout 2(严格有界,race)", async () => {
|
|
184
|
+
// 用真实时钟(不注入 now/sleep):withDeadline 的真实 setTimeout(rem) 会先于永不 resolve 的请求触发。
|
|
185
|
+
const client = {
|
|
186
|
+
getAuthContext: vi.fn(async () => ({ role: "manager" })),
|
|
187
|
+
vocQuery: vi.fn(async () => ({
|
|
188
|
+
coverage: coverage(false),
|
|
189
|
+
dispatched: [{ runId: "r1" }],
|
|
190
|
+
})),
|
|
191
|
+
getIntelRunProgress: vi.fn(() => new Promise(() => { })), // 永不 resolve
|
|
192
|
+
};
|
|
193
|
+
const { exitCode, output } = await orchestrateVocAcquire(client, {
|
|
194
|
+
query: {},
|
|
195
|
+
requirements: {},
|
|
196
|
+
maxRounds: 3,
|
|
197
|
+
timeoutMs: 80, // 真实 80ms 后定时器触发
|
|
198
|
+
pollMs: 10,
|
|
199
|
+
async: false,
|
|
200
|
+
});
|
|
201
|
+
expect(exitCode).toBe(2);
|
|
202
|
+
expect(output.status).toBe("timeout");
|
|
203
|
+
});
|
|
204
|
+
it("deadline 耗尽后 withDeadline 短路、不再发起 vocQuery 请求(先查 remaining 再调 thunk)", async () => {
|
|
205
|
+
// now() 每次调用推进 500ms;timeout 1200ms → 最终验收 vocQuery 前 remaining<=0,thunk 不被调用
|
|
206
|
+
//(旧 eager-Promise 实现会多调一次;此断言防其回归)。
|
|
207
|
+
let t = 0;
|
|
208
|
+
const now = () => {
|
|
209
|
+
t += 500;
|
|
210
|
+
return t;
|
|
211
|
+
};
|
|
212
|
+
const client = {
|
|
213
|
+
getAuthContext: vi.fn(async () => ({ role: "manager" })),
|
|
214
|
+
vocQuery: vi.fn(async () => ({
|
|
215
|
+
coverage: coverage(false),
|
|
216
|
+
dispatched: [], // 无 runId → 不轮询,直接进下一步/最终验收
|
|
217
|
+
})),
|
|
218
|
+
getIntelRunProgress: vi.fn(),
|
|
219
|
+
};
|
|
220
|
+
const { exitCode, output } = await orchestrateVocAcquire(client, {
|
|
221
|
+
query: {},
|
|
222
|
+
requirements: {},
|
|
223
|
+
maxRounds: 5,
|
|
224
|
+
timeoutMs: 1200,
|
|
225
|
+
pollMs: 10,
|
|
226
|
+
async: false,
|
|
227
|
+
now,
|
|
228
|
+
sleep: async () => { },
|
|
229
|
+
});
|
|
230
|
+
// getAuthContext(1 次 now)+ round1 vocQuery(now)→ dispatched 空 break → 最终验收 vocQuery
|
|
231
|
+
// 在 remaining<=0 时抛 VocDeadlineError → timeout,不再真正发起。
|
|
232
|
+
expect(exitCode).toBe(2);
|
|
233
|
+
expect(output.status).toBe("timeout");
|
|
234
|
+
// 关键:只调过 1 次(round1 dispatch);最终验收在 remaining<=0 时短路,没发第 2 次请求。
|
|
235
|
+
expect(client.vocQuery).toHaveBeenCalledTimes(1);
|
|
236
|
+
});
|
|
237
|
+
it("缺口但无可派发(runId 空)→ 直接进最终验收、不满足 → exitCode 2", async () => {
|
|
238
|
+
const clock = fakeClock();
|
|
239
|
+
const client = {
|
|
240
|
+
getAuthContext: vi.fn(async () => ({ role: "manager" })),
|
|
241
|
+
vocQuery: vi.fn(async () => ({
|
|
242
|
+
coverage: coverage(false),
|
|
243
|
+
dispatched: [],
|
|
244
|
+
})),
|
|
245
|
+
getIntelRunProgress: vi.fn(),
|
|
246
|
+
};
|
|
247
|
+
const { exitCode, output } = await orchestrateVocAcquire(client, baseParams(clock));
|
|
248
|
+
expect(exitCode).toBe(2);
|
|
249
|
+
expect(output.status).toBe("unsatisfied");
|
|
250
|
+
expect(client.getIntelRunProgress).not.toHaveBeenCalled();
|
|
251
|
+
});
|
|
252
|
+
});
|
|
253
|
+
//# sourceMappingURL=voc-acquire.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"voc-acquire.test.js","sourceRoot":"","sources":["../src/voc-acquire.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.2.
|
|
3
|
+
"version": "0.2.20",
|
|
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.7",
|
|
26
|
+
"@geoly-ai/social-hub-sdk": "0.0.37"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
29
|
"@types/node": "^22.10.2",
|
package/skills/manifest.json
CHANGED
|
@@ -65,6 +65,9 @@ social-hub intelligence evidence-import --file evidence.json
|
|
|
65
65
|
# 热帖批量回灌(批≤200;每条 watchlistId 做品牌归因→进 subreddit_hot_post_snapshots;逐条拒收报告)
|
|
66
66
|
social-hub intelligence posts-import --file posts.json
|
|
67
67
|
# posts.json: {"items":[{"watchlistId":"<uuid>","subreddit":"espresso","title":"...","permalink":"https://www.reddit.com/r/espresso/comments/x/y/","score":12,"commentsCount":3}]}
|
|
68
|
+
# 返回 {createdCount(净新增),updatedCount(已有帖内容变),unchangedCount(内容未变),rejectedCount,
|
|
69
|
+
# importedCount=前三者和(兼容),results[{index,id,outcome}]}——created 才是净新增,无需抓前后比 permalink。
|
|
70
|
+
# 分类=material(标题/正文/flair/作者)变化;指标(score/comments)变不算 updated;陈旧回放不覆盖较新数据。
|
|
68
71
|
```
|
|
69
72
|
|
|
70
73
|
**热帖归因**:`watchlistId` 是品牌归因主键(watchlist 挂 brandId);受限主体回灌时该条
|
|
@@ -91,6 +94,18 @@ social-hub intelligence voc-query --brand-keywords aporro --subreddits espresso
|
|
|
91
94
|
满足直接消费系统数据;不满足带 --dispatch-on-gap 重发,拿 runIds 经 runs-list
|
|
92
95
|
轮询终态后再消费——"先查 Social Hub,缺口才抓 Reddit"落地为一次调用。
|
|
93
96
|
|
|
97
|
+
**一键有界编排 `voc-acquire`**(把上面循环封装成一条命令,免手工轮询 runs-list):
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
social-hub intelligence voc-acquire --brand-keywords aporro --subreddits espresso \
|
|
101
|
+
--need-comments --need-rules-evidence --max-rounds 3 --timeout 300 --poll-interval 5
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
循环 voc-query --dispatch-on-gap → 轮询本轮 run 到终态 → 重算 coverage 验收 → 缺口再派一轮(≤max-rounds)。
|
|
105
|
+
**退出码**:`0`=coverage 满足;`2`=尚未满足(超时 / 多轮后仍缺口——非命令失败,自动化据此判定);
|
|
106
|
+
`1`=错误(鉴权/格式/网络)。`--async` 只派第一轮不等待(退 2)。**第一版仅 unrestricted 角色**(client 恒拒)。
|
|
107
|
+
退 2 且 `externalImportMayBeRequired:true` 时按 `recommendedCommand` 走本地采集 + evidence-import 回灌。
|
|
108
|
+
|
|
94
109
|
## Coverage 覆盖率评估(cache-first 决策依据,纯读)
|
|
95
110
|
|
|
96
111
|
```bash
|
|
@@ -128,8 +143,11 @@ social-hub intelligence evidence-status --subreddit espresso
|
|
|
128
143
|
**8 类证据**:about / rules / wiki / submit_text / pinned / flair / page_signals /
|
|
129
144
|
installed_apps。**状态语义**:`available`=抓到内容(含"规则为空"这类可确证的空);
|
|
130
145
|
`not_visible`=页面明确无该项;`failed`=采集失败——**failed 不等于"没有规则"**,
|
|
131
|
-
|
|
132
|
-
|
|
146
|
+
合规判断必须区分。**采集完成度**:`needsAcquisition=true` 表示无新鲜的**已完成采集**证据
|
|
147
|
+
(从未采/过期/仅 failed);**fresh not_visible 与 fresh available 一样算已完成 → needsAcquisition=false**
|
|
148
|
+
(不再反复派发白吃额度),TTL 到期后 not_visible 才重新 needsAcquisition。**内容消费**另有
|
|
149
|
+
`evidence-list --fresh-only` 只返 available(not_visible 无内容可消费)。看 lastAttemptAt/
|
|
150
|
+
lastFailureReason 区分从未采/失败。TTL:
|
|
133
151
|
rules/wiki/about/submit_text 30 天、pinned 24 小时、flair/page_signals/
|
|
134
152
|
installed_apps 7 天。
|
|
135
153
|
|