@geoly-ai/social-hub-cli 0.3.33 → 0.3.34

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,30 @@
1
+ import type { Command } from "commander";
2
+ /**
3
+ * Reddit 账号平台判定状态交付面(Block C)—— `social-hub reddit-verification ...`。
4
+ *
5
+ * team 维度端点(`/v1/teams/:teamId/...`):读 = 非 client 内部角色 + internal 只读;
6
+ * 写(record observation / patch evidence)= senior 及以上(client 恒拒,见 authz
7
+ * `redditAccountVerification` 资源梯度)。⛔ 一期不暴露 dispatch policy——本 CLI 只吐
8
+ * 原始 verification state,不做「能不能派活」的建议。
9
+ */
10
+ declare const evidenceKinds: readonly ["dom_snapshot", "screenshot", "agent_narrative"];
11
+ declare const observedStates: readonly ["verification_required", "app_labeled", "verified"];
12
+ /** `observations record` 请求体的本地形状校验(非法输入 dry-run 前即拒)。 */
13
+ export declare function buildRecordObservationBody(raw: Record<string, unknown>): {
14
+ observedState: (typeof observedStates)[number];
15
+ observedAt: string;
16
+ requestId: string;
17
+ sourceEventType: string;
18
+ deadlineRaw?: string | null;
19
+ deadlineAt?: string | null;
20
+ evidence: Array<{
21
+ kind: (typeof evidenceKinds)[number];
22
+ ref?: string | null;
23
+ host?: string | null;
24
+ capturedAt?: string | null;
25
+ expiresAt?: string | null;
26
+ }>;
27
+ };
28
+ export declare function registerRedditAccountVerificationCommands(program: Command): void;
29
+ export {};
30
+ //# sourceMappingURL=register-reddit-account-verification.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"register-reddit-account-verification.d.ts","sourceRoot":"","sources":["../src/register-reddit-account-verification.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAUzC;;;;;;;GAOG;AAEH,QAAA,MAAM,aAAa,4DAIT,CAAC;AACX,QAAA,MAAM,cAAc,+DAIV,CAAC;AAQX,0DAA0D;AAC1D,wBAAgB,0BAA0B,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG;IACxE,aAAa,EAAE,CAAC,OAAO,cAAc,CAAC,CAAC,MAAM,CAAC,CAAC;IAC/C,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,QAAQ,EAAE,KAAK,CAAC;QACd,IAAI,EAAE,CAAC,OAAO,aAAa,CAAC,CAAC,MAAM,CAAC,CAAC;QACrC,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QACpB,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QACrB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QAC3B,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;KAC3B,CAAC,CAAC;CACJ,CA0DA;AAED,wBAAgB,yCAAyC,CACvD,OAAO,EAAE,OAAO,GACf,IAAI,CA2LN"}
@@ -0,0 +1,207 @@
1
+ import { requireClient, resolveTeamId } from "./client.js";
2
+ import { assertApplyOrDryRun } from "./dry-run.js";
3
+ import { parseJsonOption, printResult, withCliErrorBoundary, } from "./output.js";
4
+ import { withPermissionGates } from "./permission-runner.js";
5
+ /**
6
+ * Reddit 账号平台判定状态交付面(Block C)—— `social-hub reddit-verification ...`。
7
+ *
8
+ * team 维度端点(`/v1/teams/:teamId/...`):读 = 非 client 内部角色 + internal 只读;
9
+ * 写(record observation / patch evidence)= senior 及以上(client 恒拒,见 authz
10
+ * `redditAccountVerification` 资源梯度)。⛔ 一期不暴露 dispatch policy——本 CLI 只吐
11
+ * 原始 verification state,不做「能不能派活」的建议。
12
+ */
13
+ const evidenceKinds = [
14
+ "dom_snapshot",
15
+ "screenshot",
16
+ "agent_narrative",
17
+ ];
18
+ const observedStates = [
19
+ "verification_required",
20
+ "app_labeled",
21
+ "verified",
22
+ ];
23
+ const evidenceAvailabilities = [
24
+ "available",
25
+ "expired",
26
+ "missing",
27
+ "revoked",
28
+ ];
29
+ /** `observations record` 请求体的本地形状校验(非法输入 dry-run 前即拒)。 */
30
+ export function buildRecordObservationBody(raw) {
31
+ const fail = (msg) => {
32
+ console.error(msg);
33
+ process.exit(1);
34
+ };
35
+ const str = (k, required) => {
36
+ const v = raw[k];
37
+ if (v === undefined || v === null) {
38
+ if (required)
39
+ return fail(`--json 缺少必填字段 ${k}(string)`);
40
+ return undefined;
41
+ }
42
+ if (typeof v !== "string" || v.trim() === "") {
43
+ return fail(`--json 字段 ${k} 须为非空 string`);
44
+ }
45
+ return v;
46
+ };
47
+ const observedState = str("observedState", true);
48
+ if (!observedStates.includes(observedState)) {
49
+ return fail(`--json 字段 observedState 须为 ${observedStates.join("|")}`);
50
+ }
51
+ const observedAt = str("observedAt", true);
52
+ const requestId = str("requestId", true);
53
+ const sourceEventType = str("sourceEventType", true);
54
+ const deadlineRaw = str("deadlineRaw", false);
55
+ const deadlineAt = str("deadlineAt", false);
56
+ const evidenceRaw = raw.evidence;
57
+ if (!Array.isArray(evidenceRaw) || evidenceRaw.length === 0) {
58
+ return fail("--json 字段 evidence 须为非空数组");
59
+ }
60
+ const evidence = evidenceRaw.map((entry, i) => {
61
+ if (typeof entry !== "object" || entry === null || Array.isArray(entry)) {
62
+ return fail(`--json evidence[${i}] 须为对象`);
63
+ }
64
+ const e = entry;
65
+ const kind = e.kind;
66
+ if (typeof kind !== "string" ||
67
+ !evidenceKinds.includes(kind)) {
68
+ return fail(`--json evidence[${i}].kind 须为 ${evidenceKinds.join("|")}`);
69
+ }
70
+ return {
71
+ kind: kind,
72
+ ref: typeof e.ref === "string" ? e.ref : undefined,
73
+ host: typeof e.host === "string" ? e.host : undefined,
74
+ capturedAt: typeof e.capturedAt === "string" ? e.capturedAt : undefined,
75
+ expiresAt: typeof e.expiresAt === "string" ? e.expiresAt : undefined,
76
+ };
77
+ });
78
+ return {
79
+ observedState: observedState,
80
+ observedAt,
81
+ requestId,
82
+ sourceEventType,
83
+ ...(deadlineRaw ? { deadlineRaw } : {}),
84
+ ...(deadlineAt ? { deadlineAt } : {}),
85
+ evidence,
86
+ };
87
+ }
88
+ export function registerRedditAccountVerificationCommands(program) {
89
+ const rav = program
90
+ .command("reddit-verification")
91
+ .description("Reddit 账号平台判定状态(team 级;client 恒拒;⛔ 不含 dispatch policy)");
92
+ // ── 读:单账号详情(current + 最近 N 条 observation)─────────────────────
93
+ rav
94
+ .command("get")
95
+ .description("GET .../accounts/:accountId/reddit-verification — current + 最近 N 条 observation(含 evidence 摘要)")
96
+ .option("-t, --team <teamId>", "Team UUID(缺省用当前 context)")
97
+ .requiredOption("--account-id <uuid>", "social_accounts.id")
98
+ .option("--limit <n>", "最近观测条数上限(1-100,默认 20)")
99
+ .action(async (opts) => {
100
+ await withCliErrorBoundary(async () => {
101
+ await withPermissionGates({
102
+ command: "reddit-verification get",
103
+ gates: [{ resource: "redditAccountVerification", action: "read" }],
104
+ teamId: opts.team,
105
+ }, async () => {
106
+ const teamId = resolveTeamId(opts.team);
107
+ printResult(await requireClient().getRedditAccountVerification(teamId, opts.accountId, { limit: opts.limit ? Number(opts.limit) : undefined }));
108
+ });
109
+ });
110
+ });
111
+ // ── 读:列表 + coverage ──────────────────────────────────────────────────
112
+ rav
113
+ .command("list")
114
+ .description("GET .../reddit-verification/accounts — 列表 + coverage 计数(默认只看需处理:verification_required+app_labeled)")
115
+ .option("-t, --team <teamId>", "Team UUID(缺省用当前 context)")
116
+ .option("--all", "看全量(含 unknown/verified),默认只看需处理队列", false)
117
+ .option("--limit <n>", "最多返回条数(1-200,默认 50)")
118
+ .option("--offset <n>", "偏移")
119
+ .action(async (opts) => {
120
+ await withCliErrorBoundary(async () => {
121
+ await withPermissionGates({
122
+ command: "reddit-verification list",
123
+ gates: [{ resource: "redditAccountVerification", action: "list" }],
124
+ teamId: opts.team,
125
+ }, async () => {
126
+ const teamId = resolveTeamId(opts.team);
127
+ printResult(await requireClient().listRedditAccountVerificationAccounts(teamId, {
128
+ needsAttention: opts.all ? false : true,
129
+ limit: opts.limit ? Number(opts.limit) : undefined,
130
+ offset: opts.offset ? Number(opts.offset) : undefined,
131
+ }));
132
+ });
133
+ });
134
+ });
135
+ // ── 写:记一条观测(幂等键 requestId;响应固定三态)───────────────────────
136
+ rav
137
+ .command("record-observation")
138
+ .description("POST .../accounts/:accountId/reddit-verification/observations — 幂等键 requestId;201=recorded/200=duplicate_delivery/409=两种专用冲突码")
139
+ .option("-t, --team <teamId>", "Team UUID(缺省用当前 context)")
140
+ .requiredOption("--account-id <uuid>", "social_accounts.id")
141
+ .requiredOption("-j, --json <json>", '{ "observedState","observedAt","requestId","sourceEventType", 可选 "deadlineRaw"/"deadlineAt", "evidence":[{"kind",...}] }')
142
+ .option("--dry-run", "预览", false)
143
+ .option("--apply", "执行写入", false)
144
+ .action(async (opts) => {
145
+ await withCliErrorBoundary(async () => {
146
+ await withPermissionGates({
147
+ command: "reddit-verification record-observation",
148
+ gates: [
149
+ { resource: "redditAccountVerification", action: "create" },
150
+ ],
151
+ teamId: opts.team,
152
+ }, async () => {
153
+ const body = buildRecordObservationBody(parseJsonOption(opts.json));
154
+ if (!assertApplyOrDryRun(opts, {
155
+ command: "reddit-verification record-observation",
156
+ danger: "write",
157
+ summary: { accountId: opts.accountId, ...body },
158
+ })) {
159
+ return;
160
+ }
161
+ const teamId = resolveTeamId(opts.team);
162
+ printResult(await requireClient().recordRedditAccountVerificationObservation(teamId, opts.accountId, body));
163
+ });
164
+ });
165
+ });
166
+ // ── 写:标注证据可用性(只改 availability;拒绝较旧检查覆盖较新结果)────
167
+ rav
168
+ .command("mark-evidence")
169
+ .description("PATCH .../reddit-verification/evidence/:evidenceId — 只改 availability;checkedAt 必填,较旧检查覆盖较新结果会被拒(409)")
170
+ .option("-t, --team <teamId>", "Team UUID(缺省用当前 context)")
171
+ .requiredOption("--evidence-id <uuid>", "evidence 行 id")
172
+ .requiredOption("--availability <a>", `证据可用性(${evidenceAvailabilities.join("|")})`)
173
+ .requiredOption("--checked-at <iso>", "调用方实际检查该证据的时间(ISO 8601)")
174
+ .option("--dry-run", "预览", false)
175
+ .option("--apply", "执行写入", false)
176
+ .action(async (opts) => {
177
+ await withCliErrorBoundary(async () => {
178
+ await withPermissionGates({
179
+ command: "reddit-verification mark-evidence",
180
+ gates: [
181
+ { resource: "redditAccountVerification", action: "update" },
182
+ ],
183
+ teamId: opts.team,
184
+ }, async () => {
185
+ const availability = opts.availability;
186
+ if (!evidenceAvailabilities.includes(availability)) {
187
+ console.error(`--availability 须为 ${evidenceAvailabilities.join("|")}`);
188
+ process.exit(1);
189
+ }
190
+ const body = {
191
+ availability: availability,
192
+ checkedAt: opts.checkedAt,
193
+ };
194
+ if (!assertApplyOrDryRun(opts, {
195
+ command: "reddit-verification mark-evidence",
196
+ danger: "write",
197
+ summary: { evidenceId: opts.evidenceId, ...body },
198
+ })) {
199
+ return;
200
+ }
201
+ const teamId = resolveTeamId(opts.team);
202
+ printResult(await requireClient().patchRedditAccountVerificationEvidence(teamId, opts.evidenceId, body));
203
+ });
204
+ });
205
+ });
206
+ }
207
+ //# sourceMappingURL=register-reddit-account-verification.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"register-reddit-account-verification.js","sourceRoot":"","sources":["../src/register-reddit-account-verification.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.33",
3
+ "version": "0.3.34",
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-authz": "0.0.19",
26
- "@geoly-ai/social-hub-sdk": "0.1.6"
25
+ "@geoly-ai/social-hub-authz": "0.0.20",
26
+ "@geoly-ai/social-hub-sdk": "0.1.8"
27
27
  },
28
28
  "devDependencies": {
29
29
  "@types/node": "^22.10.2",
@@ -4,7 +4,7 @@
4
4
  "fileCount": 1656,
5
5
  "files": {
6
6
  "README.md": "5246d4ae2712e3e656b101041929183d7ae7f8ea487dacf5854187826ab7c335",
7
- "manifest.json": "31478ce9f69ae1e789065feba800e702fdf6f7bf8e6a2f18a5c45cb84fabfe63",
7
+ "manifest.json": "958d12d518a307be8485b1b99402e2642cbbe2c52d73c0ec384ebeafa929cf8e",
8
8
  "reddit-answers-research/SKILL.md": "ab6fd12eeb2fef4dc31a6f3c21a84810d6b5bdb309f130bcdc9eb902f075294a",
9
9
  "reddit-answers-research/references/browser-playbook.md": "a8f61d3d43ca93d46dadc8a092a515ddcd32df12fb1d08d334cce2e02709d915",
10
10
  "reddit-answers-research/references/report-template.md": "9aa9acf555ba8b2ca503bdbdf5750a5f53c66e19989bf6807fa6200c7317e306",
@@ -1643,7 +1643,7 @@
1643
1643
  "social-hub-content-review/SKILL.md": "6d10a84ab56552fd953863b97978bddc0e925e3a2667d64a7a4c51e33a3ddb58",
1644
1644
  "social-hub-events-observability/SKILL.md": "f4c17487c64bb1f48381d8d60e97cfa160a94a0f120153b1c0e798a0c7ee7ebe",
1645
1645
  "social-hub-graph-compliance/SKILL.md": "2270aeb321733f0318f75da4838ca1ca03996c6cac59e5a12f7152bd1ecdfa26",
1646
- "social-hub-intelligence/SKILL.md": "a3f615eb19c96161cbbcf7d014b51f9980149ffa4a5ef11f19352db813fa047d",
1646
+ "social-hub-intelligence/SKILL.md": "beb25541425dda8639e799b6d8c027dee7e9d4ecd02433b8236ea06280bd82af",
1647
1647
  "social-hub-migration/SKILL.md": "1c13f231bb81ae8d242c834eec93a499830481804c66f6dba95922972f56f9ce",
1648
1648
  "social-hub-notifications/SKILL.md": "f80f4cf2f9ef0dbf60bd6e8bb4ad7e27dc0ff1fe59f4c7e79e49cc691ed4be6a",
1649
1649
  "social-hub-openclaw-context/SKILL.md": "97c48f38f1f1a206c3af2af49fcd445a1cd5b78d4a9c805c2456de4ce98fec09",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 1,
3
3
  "package": "social-ops-hub",
4
- "cliVersion": "0.3.33",
4
+ "cliVersion": "0.3.34",
5
5
  "repository": "social-ops-hub",
6
6
  "publish": {
7
7
  "registry": "https://skill.sh",
@@ -79,6 +79,36 @@ social-hub intelligence posts-import --file posts.json
79
79
  # 分类=material(标题/正文/flair/作者)变化;指标(score/comments)变不算 updated;陈旧回放不覆盖较新数据。
80
80
  ```
81
81
 
82
+ **🔴 强烈建议带上 `rawPayload`(可选字段,但不带就永久丢失 format)**:
83
+
84
+ ```jsonc
85
+ // posts.json 的每一项,除上面那 6 个必填字段外,再带:
86
+ "rawPayload": {
87
+ "is_self": true, // 有正文帖 / link 帖
88
+ "is_video": false,
89
+ "is_gallery": false,
90
+ "url": "https://...", // ⛔ 键名必须是 url,不是 link_url(见下)
91
+ "selftext": "..." // 有就带,没有就省略
92
+ }
93
+ ```
94
+
95
+ **为什么重要**:服务端从 `rawPayload` 派生帖子的 `format`(poll/gallery/native_video/
96
+ image/external_link/self_text),**这个派生不问 LLM、只认原始字段**。不带 rawPayload 时
97
+ format 恒为 `unknown` —— 2026-08-31 实测生产 200 条连续 run **100% 是 unknown**,
98
+ 根因就是回灌方没带这些字段(而本文档此前也没说要带)。
99
+
100
+ ⚠️ **键名必须用 Reddit 原始名。** `reddit-voc-volume` 脚本输出的是 **`link_url`**,
101
+ 而服务端读的是 **`url`** —— 直接把脚本输出整个塞进 rawPayload,external_link 那一档
102
+ **匹配不上、静默落 unknown**,比不带更难查(因为"明明传了")。映射一下再传。
103
+
104
+ ⚠️ ⛔ **不要传脚本的加工字段**(`selftext_chars` / `selftext_excerpt` / `body_status` /
105
+ `sample_role` 等):对 format 派生无用,只会让 rawPayload 变大、且看起来像服务端应该认识它们。
106
+
107
+ ⚠️ `image` 与 `poll` 两类**仍会是 unknown**(需要 `post_hint` / `poll_data`,
108
+ Arctic Shift 经脚本层后拿不到)。这是"确实没有证据",可接受;
109
+ ⛔ **不要为了凑满六值去猜**(比如拿 thumbnail 猜 image)——format 进 revision hash,
110
+ 猜错会静默产生一个错误的 revision 并据此重标。
111
+
82
112
  **热帖归因**:`watchlistId` 是品牌归因主键(watchlist 挂 brandId);受限主体回灌时该条
83
113
  必须能归因到授权板块、watchlist 属本牌、permalink 板块与声明一致,否则该条 rejected
84
114
  (不整批拒)。permalink 全局去重(同帖多次回灌折叠为一行)。