@geoly-ai/social-hub-cli 0.3.0 → 0.3.1

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.
Files changed (34) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/dist/cmd-manifest.json +2 -2
  3. package/dist/index.d.ts.map +1 -1
  4. package/dist/index.js +49 -72
  5. package/dist/index.js.map +1 -1
  6. package/dist/lib/json-arg.d.ts +46 -0
  7. package/dist/lib/json-arg.d.ts.map +1 -0
  8. package/dist/lib/json-arg.js +115 -0
  9. package/dist/lib/json-arg.js.map +1 -0
  10. package/dist/lib/json-arg.test.d.ts +2 -0
  11. package/dist/lib/json-arg.test.d.ts.map +1 -0
  12. package/dist/lib/json-arg.test.js +101 -0
  13. package/dist/lib/json-arg.test.js.map +1 -0
  14. package/dist/post-review-json-arg.test.d.ts +2 -0
  15. package/dist/post-review-json-arg.test.d.ts.map +1 -0
  16. package/dist/post-review-json-arg.test.js +86 -0
  17. package/dist/post-review-json-arg.test.js.map +1 -0
  18. package/dist/skills/install-planner.d.ts +9 -0
  19. package/dist/skills/install-planner.d.ts.map +1 -1
  20. package/dist/skills/install-planner.js +11 -1
  21. package/dist/skills/install-planner.js.map +1 -1
  22. package/dist/skills/install-planner.test.js +62 -1
  23. package/dist/skills/install-planner.test.js.map +1 -1
  24. package/dist/skills/installer.js +26 -0
  25. package/dist/skills/installer.js.map +1 -1
  26. package/dist/skills/managed-sync.integration.test.js +83 -0
  27. package/dist/skills/managed-sync.integration.test.js.map +1 -1
  28. package/dist/skills/types.d.ts +9 -0
  29. package/dist/skills/types.d.ts.map +1 -1
  30. package/package.json +1 -1
  31. package/skills/manifest.json +1 -1
  32. package/skills/reddit-matrix.lock.json +1 -1
  33. package/skills/reddit-voc-volume/SKILL.md +21 -4
  34. package/skills/reddit-voc-volume/references/hub-first.md +4 -2
package/CHANGELOG.md CHANGED
@@ -4,6 +4,17 @@ All notable changes to `@geoly-ai/social-hub-cli` are documented in this file.
4
4
 
5
5
  Release workflow: `pnpm release:cli` → `pnpm publish:cli`.
6
6
 
7
+ ## [0.3.1] - 2026-07-31
8
+
9
+ ### Added
10
+
11
+ - 首次 install 接管 unknown-source skill 目录(同步我方文件+保留用户文件)
12
+
13
+ ### Fixed
14
+
15
+ - -j/--json 在 Windows 报错 —— 加 --json-file/@file/stdin 输入绕开 shell 引号
16
+ - VOC 历史数据查询直接走 Arctic,不再默认 hub-first 先撞 Hub
17
+
7
18
  ## [0.3.0] - 2026-07-31
8
19
 
9
20
  ### Added
@@ -1,6 +1,6 @@
1
1
  {
2
- "generatedAt": "2026-07-31T03:56:37.911Z",
3
- "cliVersion": "0.3.0",
2
+ "generatedAt": "2026-07-31T04:40:00.481Z",
3
+ "cliVersion": "0.3.1",
4
4
  "commands": [
5
5
  "accounts",
6
6
  "accounts brand-bindings",
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAmCpC,QAAA,MAAM,OAAO,SAAgB,CAAC;AA27D9B,8DAA8D;AAC9D,wBAAgB,4BAA4B,CAC1C,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC5B,MAAM,GAAG,IAAI,CAOf;AA2/BD,MAAM,MAAM,gBAAgB,GAAG;IAC7B,QAAQ,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IAC1D,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACjE,CAAC;AAQF,wBAAsB,qBAAqB,CACzC,MAAM,EAAE,gBAAgB,EACxB,MAAM,EAAE;IACN,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACtC,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,OAAO,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACvC,GACA,OAAO,CAAC;IAAE,QAAQ,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,CAAC,CAkJnE;AA+1ED,OAAO,EAAE,OAAO,EAAE,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAoCpC,QAAA,MAAM,OAAO,SAAgB,CAAC;AA+8D9B,8DAA8D;AAC9D,wBAAgB,4BAA4B,CAC1C,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC5B,MAAM,GAAG,IAAI,CAOf;AA2/BD,MAAM,MAAM,gBAAgB,GAAG;IAC7B,QAAQ,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IAC1D,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACjE,CAAC;AAQF,wBAAsB,qBAAqB,CACzC,MAAM,EAAE,gBAAgB,EACxB,MAAM,EAAE;IACN,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACtC,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,OAAO,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACvC,GACA,OAAO,CAAC;IAAE,QAAQ,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,CAAC,CAkJnE;AA+1ED,OAAO,EAAE,OAAO,EAAE,CAAC"}
package/dist/index.js CHANGED
@@ -12,6 +12,7 @@ import { registerBatchAndExport } from "./register-batch.js";
12
12
  import { registerAgentContext, registerOpsRuntime } from "./register-ops.js";
13
13
  import { registerDoctorAndVersion } from "./register-shared.js";
14
14
  import { registerSkillsCommands } from "./register-skills.js";
15
+ import { readJsonArgOrExit } from "./lib/json-arg.js";
15
16
  import { maybeNotifyUpdate } from "./update-check.js";
16
17
  import { maybeNotifySkillUpdate } from "./skill-update-check.js";
17
18
  import { getCliVersion } from "./version-info.js";
@@ -117,16 +118,13 @@ events
117
118
  .command("batch")
118
119
  .description("POST /events/batch")
119
120
  .option("-t, --team <teamId>", "Team UUID(缺省用当前 context)")
120
- .requiredOption("-j, --json <json>", '{ "events": [ ... ] }')
121
+ .option("-j, --json <json>", '{ "events": [ ... ] }。也可 -j @<path> 读文件 / -j - 读 stdin')
122
+ .option("--json-file <path>", "从文件读 body JSON(路径,或 - 表示 stdin);与 -j 二选一。Windows 建议用此绕开 shell 引号问题")
121
123
  .action(async (opts) => {
122
- let body;
123
- try {
124
- body = JSON.parse(opts.json);
125
- }
126
- catch {
127
- console.error("Invalid -j / --json");
128
- process.exit(1);
129
- }
124
+ const body = readJsonArgOrExit({
125
+ inline: opts.json,
126
+ file: opts.jsonFile,
127
+ });
130
128
  const res = await requireClient().appendEventsBatch(resolveTeamId(opts.team), body);
131
129
  console.log(JSON.stringify(res, null, 2));
132
130
  });
@@ -217,16 +215,13 @@ styleMarks
217
215
  .description("PUT /events/external/:eventExternalRef/style-mark (idempotent upsert)")
218
216
  .option("-t, --team <teamId>", "Team UUID(缺省用当前 context)")
219
217
  .requiredOption("--event-ref <ref>", "event externalRef")
220
- .requiredOption("-j, --json <json>", "body JSON")
218
+ .option("-j, --json <json>", "body JSON。也可 -j @<path> 读文件 / -j - 读 stdin")
219
+ .option("--json-file <path>", "从文件读 body JSON(路径,或 - 表示 stdin);与 -j 二选一。Windows 建议用此绕开 shell 引号问题")
221
220
  .action(async (opts) => {
222
- let body;
223
- try {
224
- body = JSON.parse(opts.json);
225
- }
226
- catch {
227
- console.error("Invalid -j / --json");
228
- process.exit(1);
229
- }
221
+ const body = readJsonArgOrExit({
222
+ inline: opts.json,
223
+ file: opts.jsonFile,
224
+ });
230
225
  const res = await requireClient().upsertEventStyleMarkByExternalRef(resolveTeamId(opts.team), opts.eventRef, body);
231
226
  console.log(JSON.stringify(res, null, 2));
232
227
  });
@@ -234,16 +229,13 @@ styleMarks
234
229
  .command("create")
235
230
  .description("POST /style-marks(直接创建;事件可不存在,eventExternalRef 必填)")
236
231
  .option("-t, --team <teamId>", "Team UUID(缺省用当前 context)")
237
- .requiredOption("-j, --json <json>", "{ eventExternalRef, markExternalRef?, socialAccountId?, approved?, reasonTags?, styleTags?, note? }")
232
+ .option("-j, --json <json>", "{ eventExternalRef, markExternalRef?, socialAccountId?, approved?, reasonTags?, styleTags?, note? }。也可 -j @<path> 读文件 / -j - 读 stdin")
233
+ .option("--json-file <path>", "从文件读 body JSON(路径,或 - 表示 stdin);与 -j 二选一。Windows 建议用此绕开 shell 引号问题")
238
234
  .action(async (opts) => {
239
- let body;
240
- try {
241
- body = JSON.parse(opts.json);
242
- }
243
- catch {
244
- console.error("Invalid -j / --json");
245
- process.exit(1);
246
- }
235
+ const body = readJsonArgOrExit({
236
+ inline: opts.json,
237
+ file: opts.jsonFile,
238
+ });
247
239
  const res = await requireClient().createStyleMark(resolveTeamId(opts.team), body);
248
240
  console.log(JSON.stringify(res, null, 2));
249
241
  });
@@ -369,16 +361,13 @@ reddit
369
361
  .command("create-snapshot")
370
362
  .description("POST /reddit-post-snapshots(手工补录)")
371
363
  .option("-t, --team <teamId>", "Team UUID(缺省用当前 context)")
372
- .requiredOption("-j, --json <json>", '{"permalink":"...","subreddit":"...","score":0,"commentsCount":0,"brandNote":null,"negativeFeedback":null,"repostType":"none","firstRepostLink":null,"secondRepostLink":null}')
364
+ .option("-j, --json <json>", '{"permalink":"...","subreddit":"...","score":0,"commentsCount":0,"brandNote":null,"negativeFeedback":null,"repostType":"none","firstRepostLink":null,"secondRepostLink":null}。也可 -j @<path> 读文件 / -j - 读 stdin')
365
+ .option("--json-file <path>", "从文件读 body JSON(路径,或 - 表示 stdin);与 -j 二选一。Windows 建议用此绕开 shell 引号问题")
373
366
  .action(async (opts) => {
374
- let body;
375
- try {
376
- body = JSON.parse(opts.json);
377
- }
378
- catch {
379
- console.error("Invalid -j / --json");
380
- process.exit(1);
381
- }
367
+ const body = readJsonArgOrExit({
368
+ inline: opts.json,
369
+ file: opts.jsonFile,
370
+ });
382
371
  const res = await requireClient().createRedditPostSnapshot(resolveTeamId(opts.team), body);
383
372
  console.log(JSON.stringify(res, null, 2));
384
373
  });
@@ -410,16 +399,13 @@ jobs
410
399
  .command("create")
411
400
  .description("POST /scheduled-jobs(--json 为完整 body)")
412
401
  .option("-t, --team <teamId>", "Team UUID(缺省用当前 context)")
413
- .requiredOption("-j, --json <json>", "createScheduledJobBody JSON")
402
+ .option("-j, --json <json>", "createScheduledJobBody JSON。也可 -j @<path> 读文件 / -j - 读 stdin")
403
+ .option("--json-file <path>", "从文件读 body JSON(路径,或 - 表示 stdin);与 -j 二选一。Windows 建议用此绕开 shell 引号问题")
414
404
  .action(async (opts) => {
415
- let body;
416
- try {
417
- body = JSON.parse(opts.json);
418
- }
419
- catch {
420
- console.error("Invalid -j / --json");
421
- process.exit(1);
422
- }
405
+ const body = readJsonArgOrExit({
406
+ inline: opts.json,
407
+ file: opts.jsonFile,
408
+ });
423
409
  const res = await requireClient().createScheduledJob(resolveTeamId(opts.team), body);
424
410
  console.log(JSON.stringify(res, null, 2));
425
411
  });
@@ -427,16 +413,13 @@ jobs
427
413
  .command("batch")
428
414
  .description("POST /scheduled-jobs/batch")
429
415
  .option("-t, --team <teamId>", "Team UUID(缺省用当前 context)")
430
- .requiredOption("-j, --json <json>", '{ "jobs": [ ... ] }')
416
+ .option("-j, --json <json>", '{ "jobs": [ ... ] }。也可 -j @<path> 读文件 / -j - 读 stdin')
417
+ .option("--json-file <path>", "从文件读 body JSON(路径,或 - 表示 stdin);与 -j 二选一。Windows 建议用此绕开 shell 引号问题")
431
418
  .action(async (opts) => {
432
- let body;
433
- try {
434
- body = JSON.parse(opts.json);
435
- }
436
- catch {
437
- console.error("Invalid -j / --json");
438
- process.exit(1);
439
- }
419
+ const body = readJsonArgOrExit({
420
+ inline: opts.json,
421
+ file: opts.jsonFile,
422
+ });
440
423
  const res = await requireClient().createScheduledJobsBatch(resolveTeamId(opts.team), body);
441
424
  console.log(JSON.stringify(res, null, 2));
442
425
  });
@@ -466,17 +449,14 @@ content
466
449
  .command("review")
467
450
  .description("POST /content-review — 评论发布前独立 LLM 复审+优化(层③);degraded 时降级本地自审")
468
451
  .option("-t, --team <teamId>", "Team UUID(缺省用当前 context)")
469
- .requiredOption("-j, --json <json>", "{ accountId?, draft, commentType, thread:{subreddit,postTitle,...}, brandContext?:{brandKey|campaignId}, rewrite?, stage?, attempt? } (omit accountId for persona-less ContentOnly review)")
452
+ .option("-j, --json <json>", "{ accountId?, draft, commentType, thread:{subreddit,postTitle,...}, brandContext?:{brandKey|campaignId}, rewrite?, stage?, attempt? } (omit accountId for persona-less ContentOnly review)。也可 -j @<path> 读文件 / -j - 读 stdin")
453
+ .option("--json-file <path>", "从文件读 body JSON(路径,或 - 表示 stdin);与 -j 二选一。Windows 建议用此绕开 shell 引号问题")
470
454
  .option("--brand-context <json>", '品牌上下文 { "brandKey":"..." } 或 { "campaignId":"..." }(§0.3;便捷参数,覆盖 -j 里的 brandContext)')
471
455
  .action(async (opts) => {
472
- let body;
473
- try {
474
- body = JSON.parse(opts.json);
475
- }
476
- catch {
477
- console.error("Invalid -j / --json");
478
- process.exit(1);
479
- }
456
+ const body = readJsonArgOrExit({
457
+ inline: opts.json,
458
+ file: opts.jsonFile,
459
+ });
480
460
  if (opts.brandContext) {
481
461
  try {
482
462
  body.brandContext = JSON.parse(opts.brandContext);
@@ -493,17 +473,14 @@ content
493
473
  .command("post-review")
494
474
  .description("POST /post-review — 帖子(title+body)发布前独立 LLM 审核(七维,独立模型 key);仅审帖子正文,评论审核用 content review")
495
475
  .option("-t, --team <teamId>", "Team UUID(缺省用当前 context)")
496
- .requiredOption("-j, --json <json>", "{ accountId?, title, body, subreddit, subredditRules?, brandContext?:{brandKey|campaignId}, rewrite?, stage?, attempt? } (omit accountId for persona-less ContentOnly review)")
476
+ .option("-j, --json <json>", "{ accountId?, title, body, subreddit, subredditRules?, brandContext?:{brandKey|campaignId}, rewrite?, stage?, attempt? } (omit accountId for persona-less ContentOnly review)。也可 -j @<path> 读文件 / -j - 读 stdin")
477
+ .option("--json-file <path>", "从文件读 body JSON(路径,或 - 表示 stdin);与 -j 二选一。Windows 建议用此绕开 shell 引号问题")
497
478
  .option("--brand-context <json>", '品牌上下文 { "brandKey":"..." } 或 { "campaignId":"..." }(便捷参数,覆盖 -j 里的 brandContext)')
498
479
  .action(async (opts) => {
499
- let body;
500
- try {
501
- body = JSON.parse(opts.json);
502
- }
503
- catch {
504
- console.error("Invalid -j / --json");
505
- process.exit(1);
506
- }
480
+ const body = readJsonArgOrExit({
481
+ inline: opts.json,
482
+ file: opts.jsonFile,
483
+ });
507
484
  if (opts.brandContext) {
508
485
  try {
509
486
  body.brandContext = JSON.parse(opts.brandContext);