@geoly-ai/social-hub-cli 0.2.19 → 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.
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=voc-acquire.test.d.ts.map
@@ -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.19",
3
+ "version": "0.2.20",
4
4
  "type": "module",
5
5
  "description": "social-hub CLI for Social Ops Hub",
6
6
  "repository": {
@@ -23,7 +23,7 @@
23
23
  "dependencies": {
24
24
  "commander": "^12.1.0",
25
25
  "@geoly-ai/social-hub-authz": "0.0.7",
26
- "@geoly-ai/social-hub-sdk": "0.0.36"
26
+ "@geoly-ai/social-hub-sdk": "0.0.37"
27
27
  },
28
28
  "devDependencies": {
29
29
  "@types/node": "^22.10.2",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 1,
3
3
  "package": "social-ops-hub",
4
- "cliVersion": "0.2.19",
4
+ "cliVersion": "0.2.20",
5
5
  "repository": "social-ops-hub",
6
6
  "publish": {
7
7
  "registry": "https://skill.sh",
@@ -94,6 +94,18 @@ social-hub intelligence voc-query --brand-keywords aporro --subreddits espresso
94
94
  满足直接消费系统数据;不满足带 --dispatch-on-gap 重发,拿 runIds 经 runs-list
95
95
  轮询终态后再消费——"先查 Social Hub,缺口才抓 Reddit"落地为一次调用。
96
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
+
97
109
  ## Coverage 覆盖率评估(cache-first 决策依据,纯读)
98
110
 
99
111
  ```bash