@gobing-ai/knowledge-kit 0.0.33 → 0.0.35

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 (69) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/dist/index.js +25191 -24167
  3. package/package.json +4 -4
  4. package/plugins/generations/content-gen/dist/index.js +9 -9
  5. package/plugins/generations/core-facts-gen/dist/index.js +12 -12
  6. package/plugins/generations/daily-article-gen/dist/index.js +31 -23
  7. package/plugins/generations/daily-article-gen/src/index.ts +39 -14
  8. package/plugins/generations/dailynews-gen/dist/index.js +23 -21
  9. package/plugins/generations/dailynews-gen/src/script-builder.ts +30 -26
  10. package/plugins/generations/episode-plan-gen/dist/index.js +12 -12
  11. package/plugins/generations/gemini-tts/dist/index.js +13 -12
  12. package/plugins/generations/image-gen/dist/index.js +26 -11
  13. package/plugins/generations/image-gen/presets/formats/xhs-card.yaml +16 -14
  14. package/plugins/generations/image-gen/presets/styles/xhs-knowledge.yaml +2 -2
  15. package/plugins/generations/image-gen/src/compose/card.ts +17 -2
  16. package/plugins/generations/news-report-gen/dist/index.js +12 -12
  17. package/plugins/generations/omni-voice-gen/plugin.json +1 -1
  18. package/plugins/generations/voice-gen/dist/index.js +13 -12
  19. package/plugins/generations/voice-gen/src/index.ts +9 -3
  20. package/plugins/ingestions/aihot-ingest/dist/index.js +12 -12
  21. package/plugins/ingestions/horizon-ingest/dist/index.js +12 -12
  22. package/plugins/ingestions/karakeep-local/dist/index.js +13 -13
  23. package/plugins/ingestions/last30days-ingest/dist/index.js +12 -12
  24. package/plugins/ingestions/web-search/dist/index.js +10 -10
  25. package/plugins/kk/decisions/extract/ai-news.yaml +6 -0
  26. package/plugins/kk/decisions/kk-items.yaml +69 -3
  27. package/plugins/kk/plugin.json +1 -1
  28. package/plugins/kk/scripts/daily-stages.ts +834 -87
  29. package/plugins/kk/scripts/daily-voice-style.zh.md +15 -10
  30. package/plugins/kk/scripts/kk-workflow-stages.ts +46 -3
  31. package/plugins/kk/skills/content-safety/SKILL.md +1 -1
  32. package/plugins/kk/skills/content-safety/references/platforms/apple-podcasts.md +2 -2
  33. package/plugins/kk/skills/content-safety/references/platforms/wechatmp.md +2 -2
  34. package/plugins/kk/skills/content-safety/references/platforms/xiaoyuzhou.md +4 -2
  35. package/plugins/kk/workflows/kk-collect.yaml +7 -9
  36. package/plugins/kk/workflows/kk-daily-ai-voice.yaml +32 -7
  37. package/plugins/kk/workflows/kk-daily-ai-voice2.yaml +169 -47
  38. package/plugins/kk/workflows/kk-daily-safety.yaml +9 -12
  39. package/plugins/publishings/emdash-pub/dist/index.js +9 -9
  40. package/plugins/publishings/infoq-pub/dist/index.js +22 -22
  41. package/plugins/publishings/infoq-pub/dist/profile-check.js +30336 -0
  42. package/plugins/publishings/infoq-pub/plugin.json +1 -1
  43. package/plugins/publishings/juejin-pub/dist/index.js +22 -22
  44. package/plugins/publishings/juejin-pub/dist/profile-check.js +30322 -0
  45. package/plugins/publishings/juejin-pub/plugin.json +1 -1
  46. package/plugins/publishings/medium-pub/dist/index.js +9 -9
  47. package/plugins/publishings/podcast-pub/dist/index.js +9 -9
  48. package/plugins/publishings/qiita-pub/dist/index.js +9 -9
  49. package/plugins/publishings/substack-pub/dist/index.js +22 -22
  50. package/plugins/publishings/substack-pub/dist/profile-check.js +30392 -0
  51. package/plugins/publishings/substack-pub/plugin.json +1 -1
  52. package/plugins/publishings/surfdash-pub/dist/index.js +9 -9
  53. package/plugins/publishings/wechatmp-pub/dist/index.js +329 -154
  54. package/plugins/publishings/wechatmp-pub/dist/profile-check.js +30271 -0
  55. package/plugins/publishings/wechatmp-pub/plugin.json +1 -1
  56. package/plugins/publishings/wechatmp-pub/src/enrich.ts +106 -145
  57. package/plugins/publishings/wechatmp-pub/src/flow.ts +283 -42
  58. package/plugins/publishings/wechatmp-pub/src/page.ts +20 -0
  59. package/plugins/publishings/x-pub/dist/index.js +22 -22
  60. package/plugins/publishings/x-pub/dist/profile-check.js +30328 -0
  61. package/plugins/publishings/x-pub/plugin.json +1 -1
  62. package/plugins/publishings/xhs-pub/dist/index.js +76 -27
  63. package/plugins/publishings/xhs-pub/dist/profile-check.js +30538 -0
  64. package/plugins/publishings/xhs-pub/plugin.json +1 -1
  65. package/plugins/publishings/xhs-pub/src/flow.ts +9 -3
  66. package/plugins/publishings/xhs-pub/src/index.ts +111 -5
  67. package/plugins/publishings/zenn-pub/dist/index.js +9 -9
  68. package/plugins/generations/omni-voice-gen/dist/omni-voice-gen-prr8skpb. +0 -2
  69. package/plugins/generations/omni-voice-gen/dist/omni-voice-gen.js +0 -6
@@ -2,7 +2,7 @@
2
2
  "name": "xhs-pub",
3
3
  "kind": "publish",
4
4
  "entry": "./dist/index.js",
5
- "check": "./src/profile-check.ts",
5
+ "check": "./dist/profile-check.js",
6
6
  "version": "1.0.0",
7
7
  "description": "Publish plugin for Xiaohongshu (xhs): one creator console, four validated operations (上传图文 ≤18 images | 上传视频 | 写长文 | 发播客 audio+cover) saved as a draft via 暂存离开 or published live via 发布, over the Playwright script transport"
8
8
  }
@@ -403,8 +403,14 @@ async function isPodcastModalOpen(page: XhsPage): Promise<boolean> {
403
403
 
404
404
  /**
405
405
  * Leave the 发播客 modal. The recorded advance control is `去发布`, which is publish-adjacent, so a
406
- * draft run never clicks it: it waits for the platform to move on by itself and fails loud naming
407
- * the control it refused to click. Only an explicit `publishStatus: 'public'` may click it.
406
+ draft run never clicks it: it waits for the platform to move on by itself and fails loud naming the
407
+ control it refused to click. Only an explicit `publishStatus: 'public'` may click it.
408
+ *
409
+ * 0236 R3 (deferred, operator decision 2026-10-09): whether the modal offers a save path OTHER than
410
+ * `去发布` once both files are attached was never measured (`.spur/run/discovery/` holds only the
411
+ * modal open), and an attended walk under ADR-025 is what would measure it. So no draft-save selector
412
+ * is invented here: the run stops before the publish-adjacent control and says so, which is the
413
+ * failure the 0236 result carries (a `ok:false` entry that never fails the visit).
408
414
  */
409
415
  async function leavePodcastModal(deps: ModeRunDeps): Promise<void> {
410
416
  const closed = () => isPodcastModalOpen(deps.page).then((open) => !open);
@@ -420,7 +426,7 @@ async function leavePodcastModal(deps: ModeRunDeps): Promise<void> {
420
426
  if (await waitUntil(closed, deps.stepTimeoutMs)) return;
421
427
  }
422
428
  throw new Error(
423
- `podcast modal: the 发播客 modal was still open ${deps.stepTimeoutMs}ms after the audio and cover were attached; the only recorded advance control is '${PODCAST_MODAL_ADVANCE[0]}' and a draft run does not click it (it is publish-adjacent)`,
429
+ `podcast modal: the 发播客 modal was still open ${deps.stepTimeoutMs}ms after the audio and cover were attached; its post-attach save path has never been measured (task 0236 R3 — the attended walk is still pending) and the only recorded advance control is '${PODCAST_MODAL_ADVANCE[0]}', which a draft run does not click (it is publish-adjacent)`,
424
430
  );
425
431
  }
426
432
 
@@ -73,6 +73,71 @@ function fail(error: string): Result {
73
73
  return ResultSchema.parse({ ok: false, target: TARGET, error });
74
74
  }
75
75
 
76
+ /** One operation of a visit: its own Content and the mode input validated before any browser work. */
77
+ interface VisitOperation {
78
+ content: Content;
79
+ input: ModeInput;
80
+ }
81
+
82
+ /**
83
+ * A follow-up operation of a visit: planned, or refused with the reason it never reached the console.
84
+ * A refused follow-up is reported as its own failed Result entry — it can never fail the note the
85
+ * visit was opened for (ADR-025 amendment 2026-10-09).
86
+ */
87
+ type VisitFollowUp = { content: Content; operation: string; input: ModeInput } | { operation: string; error: string };
88
+
89
+ interface VisitPlan {
90
+ /** The requested operation, resolved and validated exactly as before task 0236. */
91
+ primary: VisitOperation;
92
+ /** The primary Content's `metadata.followUps`, in declared order. */
93
+ followUps: VisitFollowUp[];
94
+ }
95
+
96
+ /**
97
+ * Plan a visit (ADR-025 amendment 2026-10-09, task 0236 option A): the requested operation plus the
98
+ * follow-ups the caller attached to the primary Content's `metadata.followUps`. One headed visit may
99
+ * compose several notes under ONE cap entry — the cap still counts visits, not notes.
100
+ *
101
+ * The primary is planned as it always was: an unplannable primary is a `fail` and no browser opens.
102
+ * A follow-up that cannot be planned (not a Content, an undeclared operation, a missing or unreadable
103
+ * artifact) is refused here, before any console work, and reported as its own entry instead. A
104
+ * `metadata.followUps` that is not an array is a caller error, so it fails loud before any browser.
105
+ */
106
+ async function planVisit(
107
+ primary: VisitOperation,
108
+ content: Content,
109
+ ): Promise<{ plan: VisitPlan; error?: undefined } | { plan?: undefined; error: string }> {
110
+ const raw = content.metadata?.followUps;
111
+ if (raw === undefined) return { plan: { primary, followUps: [] } };
112
+ if (!Array.isArray(raw)) {
113
+ return {
114
+ error: `followUps validation: Content.metadata.followUps must be an array of Content objects, got ${typeof raw}`,
115
+ };
116
+ }
117
+ const followUps: VisitFollowUp[] = [];
118
+ for (const [index, entry] of raw.entries()) {
119
+ const label = `followUps[${index}]`;
120
+ const parsed = ContentSchema.safeParse(entry);
121
+ if (!parsed.success) {
122
+ followUps.push({ operation: label, error: `${label} is not a Content object` });
123
+ continue;
124
+ }
125
+ const operation = typeof parsed.data.metadata?.operation === 'string' ? parsed.data.metadata.operation : label;
126
+ const requested = resolveXhsOperation(undefined, parsed.data);
127
+ if (requested.error !== undefined) {
128
+ followUps.push({ operation, error: requested.error });
129
+ continue;
130
+ }
131
+ const validation = await validateModeInput(requested.operation, parsed.data);
132
+ if (validation.error !== undefined) {
133
+ followUps.push({ operation, error: validation.error });
134
+ continue;
135
+ }
136
+ followUps.push({ content: parsed.data, operation: requested.operation, input: validation.input });
137
+ }
138
+ return { plan: { primary, followUps } };
139
+ }
140
+
76
141
  /** CDP is Chromium-only; when unavailable the submit step fails loud instead of guessing. */
77
142
  export async function createShadowProbe(
78
143
  context: { newCDPSession?(page: unknown): Promise<ShadowCdpSession> },
@@ -239,13 +304,20 @@ export class XhsBrowserTransport implements PublishTransport {
239
304
  if (validation.error !== undefined) return fail(validation.error);
240
305
  const input: ModeInput = validation.input;
241
306
 
307
+ // ADR-025 amendment (2026-10-09, task 0236 option A): one visit may compose more than one
308
+ // note. The follow-ups ride the primary Content's `metadata.followUps` and are planned here,
309
+ // with the primary, before any browser work.
310
+ const visited = await planVisit({ content: payload.content, input }, payload.content);
311
+ if (visited.error !== undefined) return fail(visited.error);
312
+ const visit = visited.plan;
313
+
242
314
  const override = typeof payload.options?.profileDir === 'string' ? payload.options.profileDir : undefined;
243
315
  const profileDir = resolveChannelProfileDir(CHANNEL, override);
244
- const publishStatus = payload.content.metadata?.publishStatus === 'public' ? 'public' : 'draft';
245
316
 
246
317
  // ADR-025 automation guard — both gates run before any browser opens.
247
318
  // 1. Frequency cap: the operator's platform warning makes a repeated console visit an
248
- // account-level risk, not merely a failed run.
319
+ // account-level risk, not merely a failed run. The cap counts VISITS: one allow/record
320
+ // per visit covers every note the visit composes.
249
321
  const cap = this.automation.allow('publish');
250
322
  if (!cap.allowed) return fail(`automation cap: ${cap.reason}`);
251
323
  // 2. Headless session preflight: an unauthenticated profile must never produce a headed
@@ -266,6 +338,41 @@ export class XhsBrowserTransport implements PublishTransport {
266
338
  return fail(error instanceof Error ? error.message : String(error));
267
339
  }
268
340
  const { page, close } = opened;
341
+ try {
342
+ // The visit's own Result is the primary operation's: a failed primary ends the visit, as
343
+ // it always did, and only a primary that stood reports its follow-ups.
344
+ const primary = await this.runStep(visit.primary.input, visit.primary.content, page, profileDir);
345
+ if (!primary.ok || visit.followUps.length === 0) return primary;
346
+ // One Result entry per operation, in declared order; a refused and a failed follow-up
347
+ // are the same kind of entry, and neither can fail the note the visit was opened for.
348
+ const followUps: Result[] = [];
349
+ for (const followUp of visit.followUps) {
350
+ const step =
351
+ 'error' in followUp
352
+ ? fail(`follow-up (${followUp.operation}): ${followUp.error}`)
353
+ : await this.runStep(followUp.input, followUp.content, page, profileDir);
354
+ // Every entry names the operation it was planned under — a failed or refused one too,
355
+ // so the caller can tell which note fell; the step's own metadata wins.
356
+ followUps.push(
357
+ ResultSchema.parse({ ...step, metadata: { operation: followUp.operation, ...step.metadata } }),
358
+ );
359
+ }
360
+ return ResultSchema.parse({ ...primary, metadata: { ...primary.metadata, followUps } });
361
+ } finally {
362
+ await close();
363
+ }
364
+ }
365
+
366
+ /**
367
+ * Run one operation of the visit in the page the visit already opened. Every step enters the
368
+ * console from its landing view: the primary needs the login gate and the pre-entry draft
369
+ * baseline, and a follow-up needs both again — the previous note's editor replaces the header,
370
+ * and the baseline must be read before THIS note's mode is entered.
371
+ *
372
+ * A step never throws: its failure is that operation's own `ok:false` Result, which is what keeps
373
+ * a failed follow-up from failing the visit (ADR-025 amendment 2026-10-09).
374
+ */
375
+ private async runStep(input: ModeInput, content: Content, page: XhsPage, profileDir: string): Promise<Result> {
269
376
  const act = async <T>(what: string, fn: () => Promise<T>): Promise<T> => {
270
377
  try {
271
378
  return await fn();
@@ -283,6 +390,7 @@ export class XhsBrowserTransport implements PublishTransport {
283
390
  );
284
391
  }
285
392
 
393
+ const publishStatus = content.metadata?.publishStatus === 'public' ? 'public' : 'draft';
286
394
  // The draft counter and any save timestamps exist only on the landing view, so the
287
395
  // baseline is captured before the mode is entered (the editor replaces the header).
288
396
  const draftBaseline =
@@ -290,7 +398,7 @@ export class XhsBrowserTransport implements PublishTransport {
290
398
 
291
399
  return await runMode(input, {
292
400
  page,
293
- content: payload.content,
401
+ content,
294
402
  publishStatus,
295
403
  profileDir,
296
404
  driver: this.driver,
@@ -301,8 +409,6 @@ export class XhsBrowserTransport implements PublishTransport {
301
409
  });
302
410
  } catch (error) {
303
411
  return fail(error instanceof Error ? error.message : String(error));
304
- } finally {
305
- await close();
306
412
  }
307
413
  }
308
414
  }
@@ -14642,7 +14642,7 @@ var init_zod = __esm(() => {
14642
14642
  init_external();
14643
14643
  });
14644
14644
 
14645
- // ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.18/node_modules/@gobing-ai/ts-utils/dist/errors.js
14645
+ // ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.21/node_modules/@gobing-ai/ts-utils/dist/errors.js
14646
14646
  var ErrorCode;
14647
14647
  var init_errors3 = __esm(() => {
14648
14648
  ErrorCode = {
@@ -14653,7 +14653,7 @@ var init_errors3 = __esm(() => {
14653
14653
  };
14654
14654
  });
14655
14655
 
14656
- // ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.18/node_modules/@gobing-ai/ts-utils/dist/api-response.js
14656
+ // ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.21/node_modules/@gobing-ai/ts-utils/dist/api-response.js
14657
14657
  var API_ERROR_CODES, ERROR_CODE_TO_HTTP, CLIENT_SAFE_CODES;
14658
14658
  var init_api_response = __esm(() => {
14659
14659
  init_errors3();
@@ -14676,13 +14676,13 @@ var init_api_response = __esm(() => {
14676
14676
  CLIENT_SAFE_CODES = new Set([ErrorCode.NotFound, ErrorCode.Validation, ErrorCode.Conflict]);
14677
14677
  });
14678
14678
 
14679
- // ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.18/node_modules/@gobing-ai/ts-utils/dist/cursor.js
14679
+ // ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.21/node_modules/@gobing-ai/ts-utils/dist/cursor.js
14680
14680
  var init_cursor = () => {};
14681
14681
 
14682
- // ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.18/node_modules/@gobing-ai/ts-utils/dist/event-severity.js
14682
+ // ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.21/node_modules/@gobing-ai/ts-utils/dist/event-severity.js
14683
14683
  var init_event_severity = () => {};
14684
14684
 
14685
- // ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.18/node_modules/@gobing-ai/ts-utils/dist/output.js
14685
+ // ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.21/node_modules/@gobing-ai/ts-utils/dist/output.js
14686
14686
  function processStream(name) {
14687
14687
  const proc = globalThis.process;
14688
14688
  const stream = proc?.[name];
@@ -14700,7 +14700,7 @@ function echoError(message, target = defaultStderrTarget ?? processStream("stder
14700
14700
  }
14701
14701
  var defaultStderrTarget;
14702
14702
 
14703
- // ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.18/node_modules/@gobing-ai/ts-utils/dist/index.js
14703
+ // ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.21/node_modules/@gobing-ai/ts-utils/dist/index.js
14704
14704
  var init_dist = __esm(() => {
14705
14705
  init_api_response();
14706
14706
  init_cursor();
@@ -21698,7 +21698,7 @@ var init_dist2 = __esm(() => {
21698
21698
  $visitAsync = visit.visitAsync;
21699
21699
  });
21700
21700
 
21701
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.18+ea28d47622d670ff/node_modules/@gobing-ai/ts-runtime/dist/config.js
21701
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.21+44edd5c4d6372504/node_modules/@gobing-ai/ts-runtime/dist/config.js
21702
21702
  var configSchema;
21703
21703
  var init_config = __esm(() => {
21704
21704
  init_dist2();
@@ -21722,7 +21722,7 @@ var init_config = __esm(() => {
21722
21722
  });
21723
21723
  });
21724
21724
 
21725
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.18+ea28d47622d670ff/node_modules/@gobing-ai/ts-runtime/dist/file-system-node.js
21725
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.21+44edd5c4d6372504/node_modules/@gobing-ai/ts-runtime/dist/file-system-node.js
21726
21726
  import { appendFileSync, cpSync, createReadStream, createWriteStream, existsSync, mkdirSync, readdirSync, readFileSync, realpathSync, renameSync, rmSync, statSync, writeFileSync } from "fs";
21727
21727
  import { dirname, resolve as resolvePath } from "path";
21728
21728
  function createNodeFileSystem(root, paths) {
@@ -21902,7 +21902,7 @@ var PluginManifestSchema = exports_external.looseObject({
21902
21902
  description: exports_external.string().optional(),
21903
21903
  operations: exports_external.record(exports_external.string(), PluginOperationSchema).optional()
21904
21904
  });
21905
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.18+ea28d47622d670ff/node_modules/@gobing-ai/ts-runtime/dist/index.js
21905
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.21+44edd5c4d6372504/node_modules/@gobing-ai/ts-runtime/dist/index.js
21906
21906
  init_file_system_node();
21907
21907
  init_config();
21908
21908
 
@@ -1,2 +0,0 @@
1
- #!/usr/bin/env bash
2
- exec uv run --project "$(cd "$(dirname "$0")/.." && pwd)" python -m omni_voice_gen "$@"
@@ -1,6 +0,0 @@
1
- // @bun
2
- // ../../plugins/generations/omni-voice-gen/bin/omni-voice-gen
3
- var omni_voice_gen_default = "./omni-voice-gen-prr8skpb.";
4
- export {
5
- omni_voice_gen_default as default
6
- };