@geoly-ai/social-hub-cli 0.2.19 → 0.2.21
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 +13 -0
- package/dist/cmd-manifest.json +3 -2
- package/dist/index.d.ts +19 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +215 -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 +243 -0
- package/dist/voc-acquire.test.js.map +1 -0
- package/package.json +2 -2
- package/skills/manifest.json +1 -1
- package/skills/social-hub-intelligence/SKILL.md +21 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"voc-acquire.test.d.ts","sourceRoot":"","sources":["../src/voc-acquire.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,243 @@
|
|
|
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
|
+
vocQuery: vi.fn(async () => ({
|
|
35
|
+
coverage: coverage(true),
|
|
36
|
+
dispatched: [],
|
|
37
|
+
})),
|
|
38
|
+
getIntelRunProgress: vi.fn(),
|
|
39
|
+
};
|
|
40
|
+
const { exitCode, output } = await orchestrateVocAcquire(client, baseParams(clock));
|
|
41
|
+
expect(exitCode).toBe(0);
|
|
42
|
+
expect(output.status).toBe("satisfied");
|
|
43
|
+
expect(client.getIntelRunProgress).not.toHaveBeenCalled();
|
|
44
|
+
});
|
|
45
|
+
it("受限主体无预检:无 evidence create 时 vocQuery 首次 403 → 抛出(命令层退 1),派发前无副作用", async () => {
|
|
46
|
+
const clock = fakeClock();
|
|
47
|
+
const client = {
|
|
48
|
+
vocQuery: vi.fn(async () => {
|
|
49
|
+
throw new Error("HTTP 403: forbidden");
|
|
50
|
+
}),
|
|
51
|
+
getIntelRunProgress: vi.fn(),
|
|
52
|
+
};
|
|
53
|
+
// 无角色预检:错误由服务端 403 抛出,orchestrate 不吞(非 deadline)→ 命令层退 1。
|
|
54
|
+
await expect(orchestrateVocAcquire(client, baseParams(clock))).rejects.toThrow(/403/);
|
|
55
|
+
expect(client.getIntelRunProgress).not.toHaveBeenCalled();
|
|
56
|
+
});
|
|
57
|
+
it("派发→轮询到终态→重算满足 → exitCode 0", async () => {
|
|
58
|
+
const clock = fakeClock();
|
|
59
|
+
let progressCalls = 0;
|
|
60
|
+
const client = {
|
|
61
|
+
vocQuery: vi
|
|
62
|
+
.fn()
|
|
63
|
+
.mockResolvedValueOnce({
|
|
64
|
+
coverage: coverage(false),
|
|
65
|
+
dispatched: [{ runId: "r1" }, { runId: "r1" }],
|
|
66
|
+
})
|
|
67
|
+
.mockResolvedValueOnce({ coverage: coverage(true), dispatched: [] }),
|
|
68
|
+
getIntelRunProgress: vi.fn(async () => {
|
|
69
|
+
progressCalls += 1;
|
|
70
|
+
return { status: progressCalls >= 2 ? "succeeded" : "running" };
|
|
71
|
+
}),
|
|
72
|
+
};
|
|
73
|
+
const { exitCode } = await orchestrateVocAcquire(client, baseParams(clock));
|
|
74
|
+
expect(exitCode).toBe(0);
|
|
75
|
+
// dispatched 去重:只轮询 r1 一次(直到终态)。
|
|
76
|
+
expect(client.vocQuery).toHaveBeenCalledTimes(2); // dispatch 轮 + 最终验收
|
|
77
|
+
});
|
|
78
|
+
it("--async 只派一轮 → exitCode 2(不轮询)", async () => {
|
|
79
|
+
const clock = fakeClock();
|
|
80
|
+
const client = {
|
|
81
|
+
vocQuery: vi.fn(async () => ({
|
|
82
|
+
coverage: coverage(false),
|
|
83
|
+
dispatched: [{ runId: "r1" }],
|
|
84
|
+
})),
|
|
85
|
+
getIntelRunProgress: vi.fn(),
|
|
86
|
+
};
|
|
87
|
+
const { exitCode, output } = await orchestrateVocAcquire(client, baseParams(clock, { async: true }));
|
|
88
|
+
expect(exitCode).toBe(2);
|
|
89
|
+
expect(output.status).toBe("dispatched");
|
|
90
|
+
expect(client.getIntelRunProgress).not.toHaveBeenCalled();
|
|
91
|
+
});
|
|
92
|
+
it("run 进度 403 → exitCode 1(能派不能读,不误当完成)", async () => {
|
|
93
|
+
const clock = fakeClock();
|
|
94
|
+
const client = {
|
|
95
|
+
vocQuery: vi.fn(async () => ({
|
|
96
|
+
coverage: coverage(false),
|
|
97
|
+
dispatched: [{ runId: "r1" }],
|
|
98
|
+
})),
|
|
99
|
+
getIntelRunProgress: vi.fn(async () => {
|
|
100
|
+
throw new Error("HTTP 403: forbidden");
|
|
101
|
+
}),
|
|
102
|
+
};
|
|
103
|
+
const { exitCode, output } = await orchestrateVocAcquire(client, baseParams(clock));
|
|
104
|
+
expect(exitCode).toBe(1);
|
|
105
|
+
expect(output.status).toBe("forbidden");
|
|
106
|
+
});
|
|
107
|
+
it("网络错误重试、不误删 pending;终态后完成", async () => {
|
|
108
|
+
const clock = fakeClock();
|
|
109
|
+
let calls = 0;
|
|
110
|
+
const client = {
|
|
111
|
+
vocQuery: vi
|
|
112
|
+
.fn()
|
|
113
|
+
.mockResolvedValueOnce({
|
|
114
|
+
coverage: coverage(false),
|
|
115
|
+
dispatched: [{ runId: "r1" }],
|
|
116
|
+
})
|
|
117
|
+
.mockResolvedValueOnce({ coverage: coverage(true), dispatched: [] }),
|
|
118
|
+
getIntelRunProgress: vi.fn(async () => {
|
|
119
|
+
calls += 1;
|
|
120
|
+
if (calls === 1)
|
|
121
|
+
throw new Error("network ECONNRESET"); // 无 HTTP status
|
|
122
|
+
return { status: "succeeded" };
|
|
123
|
+
}),
|
|
124
|
+
};
|
|
125
|
+
const { exitCode } = await orchestrateVocAcquire(client, baseParams(clock));
|
|
126
|
+
expect(exitCode).toBe(0);
|
|
127
|
+
expect(calls).toBe(2); // 第一次网络错保留 pending,第二次成功。
|
|
128
|
+
});
|
|
129
|
+
it("轮询超时 → exitCode 2 + pendingRunIds", async () => {
|
|
130
|
+
const clock = fakeClock();
|
|
131
|
+
const client = {
|
|
132
|
+
vocQuery: vi.fn(async () => ({
|
|
133
|
+
coverage: coverage(false),
|
|
134
|
+
dispatched: [{ runId: "r1" }],
|
|
135
|
+
})),
|
|
136
|
+
getIntelRunProgress: vi.fn(async () => ({ status: "running" })), // 永不终态
|
|
137
|
+
};
|
|
138
|
+
// 短超时:sleep 每次推进 1000ms,几轮后越界。
|
|
139
|
+
const { exitCode, output } = await orchestrateVocAcquire(client, baseParams(clock, { timeoutMs: 3_000 }));
|
|
140
|
+
expect(exitCode).toBe(2);
|
|
141
|
+
expect(output.status).toBe("timeout");
|
|
142
|
+
expect(output.pendingRunIds).toEqual(["r1"]);
|
|
143
|
+
});
|
|
144
|
+
it("多轮后仍不满足 → exitCode 2 + externalImportMayBeRequired", async () => {
|
|
145
|
+
const clock = fakeClock();
|
|
146
|
+
const client = {
|
|
147
|
+
// 每轮都派发但从不满足;终态立即达成推进轮次。
|
|
148
|
+
vocQuery: vi.fn(async () => ({
|
|
149
|
+
coverage: coverage(false),
|
|
150
|
+
dispatched: [{ runId: "r1" }],
|
|
151
|
+
})),
|
|
152
|
+
getIntelRunProgress: vi.fn(async () => ({ status: "succeeded" })),
|
|
153
|
+
};
|
|
154
|
+
const { exitCode, output } = await orchestrateVocAcquire(client, baseParams(clock, { maxRounds: 2 }));
|
|
155
|
+
expect(exitCode).toBe(2);
|
|
156
|
+
expect(output.status).toBe("unsatisfied");
|
|
157
|
+
expect(output.externalImportMayBeRequired).toBe(true);
|
|
158
|
+
expect(output.recommendedCommand).toContain("evidence-import");
|
|
159
|
+
});
|
|
160
|
+
it("run 进度 404 → exitCode 1(run_not_found)", async () => {
|
|
161
|
+
const clock = fakeClock();
|
|
162
|
+
const client = {
|
|
163
|
+
vocQuery: vi.fn(async () => ({
|
|
164
|
+
coverage: coverage(false),
|
|
165
|
+
dispatched: [{ runId: "r1" }],
|
|
166
|
+
})),
|
|
167
|
+
getIntelRunProgress: vi.fn(async () => {
|
|
168
|
+
throw new Error("HTTP 404: not found");
|
|
169
|
+
}),
|
|
170
|
+
};
|
|
171
|
+
const { exitCode, output } = await orchestrateVocAcquire(client, baseParams(clock));
|
|
172
|
+
expect(exitCode).toBe(1);
|
|
173
|
+
expect(output.status).toBe("run_not_found");
|
|
174
|
+
});
|
|
175
|
+
it("请求永不 resolve → 真实定时器触发 → timeout 2(严格有界,race)", async () => {
|
|
176
|
+
// 用真实时钟(不注入 now/sleep):withDeadline 的真实 setTimeout(rem) 会先于永不 resolve 的请求触发。
|
|
177
|
+
const client = {
|
|
178
|
+
vocQuery: vi.fn(async () => ({
|
|
179
|
+
coverage: coverage(false),
|
|
180
|
+
dispatched: [{ runId: "r1" }],
|
|
181
|
+
})),
|
|
182
|
+
getIntelRunProgress: vi.fn(() => new Promise(() => { })), // 永不 resolve
|
|
183
|
+
};
|
|
184
|
+
const { exitCode, output } = await orchestrateVocAcquire(client, {
|
|
185
|
+
query: {},
|
|
186
|
+
requirements: {},
|
|
187
|
+
maxRounds: 3,
|
|
188
|
+
timeoutMs: 80, // 真实 80ms 后定时器触发
|
|
189
|
+
pollMs: 10,
|
|
190
|
+
async: false,
|
|
191
|
+
});
|
|
192
|
+
expect(exitCode).toBe(2);
|
|
193
|
+
expect(output.status).toBe("timeout");
|
|
194
|
+
});
|
|
195
|
+
it("deadline 耗尽后 withDeadline 短路、不再发起 vocQuery 请求(先查 remaining 再调 thunk)", async () => {
|
|
196
|
+
// now() 每次调用推进 500ms;timeout 1000ms → 最终验收 vocQuery 前 remaining<=0,thunk 不被调用
|
|
197
|
+
//(旧 eager-Promise 实现会多调一次;此断言防其回归)。
|
|
198
|
+
let t = 0;
|
|
199
|
+
const now = () => {
|
|
200
|
+
t += 500;
|
|
201
|
+
return t;
|
|
202
|
+
};
|
|
203
|
+
const client = {
|
|
204
|
+
vocQuery: vi.fn(async () => ({
|
|
205
|
+
coverage: coverage(false),
|
|
206
|
+
dispatched: [], // 无 runId → 不轮询,直接进下一步/最终验收
|
|
207
|
+
})),
|
|
208
|
+
getIntelRunProgress: vi.fn(),
|
|
209
|
+
};
|
|
210
|
+
const { exitCode, output } = await orchestrateVocAcquire(client, {
|
|
211
|
+
query: {},
|
|
212
|
+
requirements: {},
|
|
213
|
+
maxRounds: 5,
|
|
214
|
+
timeoutMs: 1000,
|
|
215
|
+
pollMs: 10,
|
|
216
|
+
async: false,
|
|
217
|
+
now,
|
|
218
|
+
sleep: async () => { },
|
|
219
|
+
});
|
|
220
|
+
// deadline 计算(now→t=500)→ round1 vocQuery withDeadline(now→t=1000)→ dispatched 空 break →
|
|
221
|
+
// 最终验收 vocQuery withDeadline(now→t=1500,remaining=1500-1500=0<=0)→ VocDeadlineError → timeout。
|
|
222
|
+
// deadline=500+1000=1500,故最终验收短路不发起。
|
|
223
|
+
expect(exitCode).toBe(2);
|
|
224
|
+
expect(output.status).toBe("timeout");
|
|
225
|
+
// 关键:只调过 1 次(round1 dispatch);最终验收在 remaining<=0 时短路,没发第 2 次请求。
|
|
226
|
+
expect(client.vocQuery).toHaveBeenCalledTimes(1);
|
|
227
|
+
});
|
|
228
|
+
it("缺口但无可派发(runId 空)→ 直接进最终验收、不满足 → exitCode 2", async () => {
|
|
229
|
+
const clock = fakeClock();
|
|
230
|
+
const client = {
|
|
231
|
+
vocQuery: vi.fn(async () => ({
|
|
232
|
+
coverage: coverage(false),
|
|
233
|
+
dispatched: [],
|
|
234
|
+
})),
|
|
235
|
+
getIntelRunProgress: vi.fn(),
|
|
236
|
+
};
|
|
237
|
+
const { exitCode, output } = await orchestrateVocAcquire(client, baseParams(clock));
|
|
238
|
+
expect(exitCode).toBe(2);
|
|
239
|
+
expect(output.status).toBe("unsatisfied");
|
|
240
|
+
expect(client.getIntelRunProgress).not.toHaveBeenCalled();
|
|
241
|
+
});
|
|
242
|
+
});
|
|
243
|
+
//# 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.21",
|
|
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.
|
|
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
|
@@ -53,8 +53,12 @@ social-hub intelligence comments [--post-id t3_xxx] [--subreddit espresso] [--ke
|
|
|
53
53
|
```bash
|
|
54
54
|
# 评论回灌(批≤200;redditCommentId=t1_*/postId=t3_*;逐条拒收报告不整批拒)
|
|
55
55
|
social-hub intelligence comments-import --file batch.json
|
|
56
|
-
# batch.json: {"items":[{"redditCommentId":"t1_x","postId":"t3_y","subreddit":"espresso","body":"..."
|
|
56
|
+
# batch.json: {"items":[{"redditCommentId":"t1_x","postId":"t3_y","subreddit":"espresso","body":"...",
|
|
57
|
+
# "label":{"intent":"complaint","sentiment":"negative","confidence":0.9},"matchedTerms":["aporro"]}],
|
|
57
58
|
# "provenance":{"provider":"matrix_voc","collectorVersion":"2.12.19","sourceUrl":"https://..."}}
|
|
59
|
+
# 可选 label(intent/sentiment/confidence 须齐全):矩阵 skill 已自行 LLM 标注就直接带→写入即标记 labeled
|
|
60
|
+
# (labelModel=external_import),异步标注 cron 自动跳过、无需再等标注任务;缺 label 则留待 cron 标注。
|
|
61
|
+
# 仅新增 label(内容未变)也算 update 不丢弃。intent 枚举见 comments 查询的 --intent。matchedTerms=关键词命中。
|
|
58
62
|
# 证据回灌(单条观测;Hub 派生状态)
|
|
59
63
|
social-hub intelligence evidence-import -j '{"subreddit":"espresso","evidenceType":"flair","observation":{"contentMd":"- Help\n- Gear"},"provenance":{"sourceUrl":"https://www.reddit.com/r/espresso/","provider":"matrix_voc","collectorVersion":"2.12.19"}}'
|
|
60
64
|
# 证据批量回灌(批≤200;多缺口一次导入;逐条独立成败,返回 {total,imported,deduped,rejected,results[]})
|
|
@@ -94,6 +98,22 @@ social-hub intelligence voc-query --brand-keywords aporro --subreddits espresso
|
|
|
94
98
|
满足直接消费系统数据;不满足带 --dispatch-on-gap 重发,拿 runIds 经 runs-list
|
|
95
99
|
轮询终态后再消费——"先查 Social Hub,缺口才抓 Reddit"落地为一次调用。
|
|
96
100
|
|
|
101
|
+
**一键有界编排 `voc-acquire`**(把上面循环封装成一条命令,免手工轮询 runs-list):
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
social-hub intelligence voc-acquire --brand-keywords aporro --subreddits espresso \
|
|
105
|
+
--need-comments --need-rules-evidence --max-rounds 3 --timeout 300 --poll-interval 5
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
循环 voc-query --dispatch-on-gap → 轮询本轮 run 到终态 → 重算 coverage 验收 → 缺口再派一轮(≤max-rounds)。
|
|
109
|
+
**退出码**:`0`=coverage 满足;`2`=尚未满足(超时 / 多轮后仍缺口——非命令失败,自动化据此判定);
|
|
110
|
+
`1`=错误(鉴权/格式/网络)。`--async` 只派第一轮不等待(退 2)。**受限主体亦可**(权限由服务端强制:
|
|
111
|
+
需 evidence create 派发 + 该 dimension read 轮询进度;无权则对应请求 403/404→退 1)。
|
|
112
|
+
退 2 且 `externalImportMayBeRequired:true` 时按 `recommendedCommand` 走本地采集 + evidence-import 回灌
|
|
113
|
+
——注:CLI 无本地 Reddit collector,**外部采集(Firecrawl/本地)+ 回灌仍是独立步骤**(voc-acquire 只做
|
|
114
|
+
Hub-native 派发+验收,配额耗尽/无命中时诚实交回 recommendedCommand,由采集任务自行 evidence-import/
|
|
115
|
+
comments-import/posts-import 回灌;这是架构边界,非一条命令能完成所有外部采集)。
|
|
116
|
+
|
|
97
117
|
## Coverage 覆盖率评估(cache-first 决策依据,纯读)
|
|
98
118
|
|
|
99
119
|
```bash
|