@gobing-ai/knowledge-kit 0.0.37 → 0.1.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 (157) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/dist/board/collect/index.css +654 -16
  3. package/dist/board/collect/index.js +191 -64
  4. package/dist/board/daily-voice/index.css +679 -12
  5. package/dist/board/daily-voice/index.js +185 -66
  6. package/dist/board/itc/index.css +679 -13
  7. package/dist/board/itc/index.js +188 -66
  8. package/dist/index.js +2864 -139
  9. package/package.json +3 -2
  10. package/plugins/generations/content-gen/dist/index.js +158 -12
  11. package/plugins/generations/core-facts-gen/dist/index.js +158 -12
  12. package/plugins/generations/daily-article-gen/dist/index.js +158 -12
  13. package/plugins/generations/dailynews-gen/dist/index.js +158 -12
  14. package/plugins/generations/episode-plan-gen/dist/index.js +158 -12
  15. package/plugins/generations/gemini-tts/README.md +4 -3
  16. package/plugins/generations/gemini-tts/dist/index.js +158 -12
  17. package/plugins/generations/image-gen/dist/index.js +158 -12
  18. package/plugins/generations/news-report-gen/dist/index.js +158 -12
  19. package/plugins/generations/omni-voice-gen/README.md +15 -4
  20. package/plugins/generations/omni-voice-gen/profiles.json +1 -2
  21. package/plugins/generations/voice-gen/dist/index.js +158 -12
  22. package/plugins/generations/voxcpm-tts/README.md +21 -1
  23. package/plugins/generations/voxcpm-tts/dist/index.js +173 -13
  24. package/plugins/generations/voxcpm-tts/scripts/audit-speaker-consistency.py +109 -0
  25. package/plugins/generations/voxcpm-tts/src/voxcpm-client.ts +28 -1
  26. package/plugins/ingestions/aihot-ingest/dist/index.js +158 -12
  27. package/plugins/ingestions/horizon-ingest/dist/index.js +158 -12
  28. package/plugins/ingestions/last30days-ingest/dist/index.js +158 -12
  29. package/plugins/ingestions/web-search/dist/index.js +158 -12
  30. package/plugins/kk/commands/workflow-run.md +56 -18
  31. package/plugins/kk/decisions/kk-itc.yaml +46 -0
  32. package/plugins/kk/decisions/kk-seo-keyword.yaml +57 -0
  33. package/plugins/kk/decisions/kk-seo-page.yaml +230 -0
  34. package/plugins/kk/decisions/kk-seo-pair.yaml +21 -0
  35. package/plugins/kk/decisions/kk-seo-site.yaml +90 -0
  36. package/plugins/kk/plugin.json +1 -1
  37. package/plugins/kk/publish-presets/chinese-article.json +14 -0
  38. package/plugins/kk/publish-presets/technical-article.json +14 -0
  39. package/plugins/kk/references/smart-seo-attribution.md +85 -0
  40. package/plugins/kk/scripts/daily-stages.ts +42 -2
  41. package/plugins/kk/scripts/itc-stages.ts +25 -118
  42. package/plugins/kk/scripts/kk-workflow-stages.ts +38 -1
  43. package/plugins/kk/scripts/seo-decisions.ts +491 -0
  44. package/plugins/kk/scripts/seo-enrich.ts +728 -0
  45. package/plugins/kk/scripts/seo-facts.ts +610 -0
  46. package/plugins/kk/scripts/seo-fetch.ts +766 -0
  47. package/plugins/kk/scripts/seo-report.ts +460 -0
  48. package/plugins/kk/scripts/seo-rules.ts +1882 -0
  49. package/plugins/kk/scripts/seo-stages.ts +1044 -0
  50. package/plugins/kk/skills/article-adapt/SKILL.md +2 -2
  51. package/plugins/kk/skills/smart-seo/SKILL.md +183 -0
  52. package/plugins/kk/skills/smart-seo/references/method.md +126 -0
  53. package/plugins/kk/skills/smart-seo/references/narrative.md +125 -0
  54. package/plugins/kk/skills/smart-seo/references/operations.md +209 -0
  55. package/plugins/kk/skills/smart-seo/references/seo-geo-sources.md +90 -0
  56. package/plugins/kk/workflows/feature-verification.yaml +28 -24
  57. package/plugins/kk/workflows/kk-daily-ai-voice2.yaml +85 -17
  58. package/plugins/kk/workflows/kk-itc-author.yaml +406 -0
  59. package/plugins/kk/workflows/kk-itc.yaml +208 -682
  60. package/plugins/kk/workflows/kk-smart-seo.yaml +251 -0
  61. package/plugins/publishings/bilibili-pub/dist/index.js +21782 -0
  62. package/plugins/publishings/bilibili-pub/dist/profile-check.js +20410 -0
  63. package/plugins/publishings/bilibili-pub/package.json +20 -0
  64. package/plugins/publishings/bilibili-pub/plugin.json +12 -0
  65. package/plugins/publishings/bilibili-pub/src/flow.ts +1296 -0
  66. package/plugins/publishings/bilibili-pub/src/index.ts +139 -0
  67. package/plugins/publishings/bilibili-pub/src/profile-check.ts +19 -0
  68. package/plugins/publishings/bilibili-pub/src/selectors.ts +222 -0
  69. package/plugins/publishings/bilibili-pub/tsconfig.json +4 -0
  70. package/plugins/publishings/cnblogs-pub/dist/index.js +21383 -0
  71. package/plugins/publishings/cnblogs-pub/dist/profile-check.js +20412 -0
  72. package/plugins/publishings/cnblogs-pub/package.json +19 -0
  73. package/plugins/publishings/cnblogs-pub/plugin.json +12 -0
  74. package/plugins/publishings/cnblogs-pub/src/flow.ts +708 -0
  75. package/plugins/publishings/cnblogs-pub/src/index.ts +172 -0
  76. package/plugins/publishings/cnblogs-pub/src/profile-check.ts +24 -0
  77. package/plugins/publishings/cnblogs-pub/src/selectors.ts +104 -0
  78. package/plugins/publishings/cnblogs-pub/tsconfig.json +4 -0
  79. package/plugins/publishings/csdn-pub/dist/index.js +21552 -0
  80. package/plugins/publishings/csdn-pub/dist/profile-check.js +20963 -0
  81. package/plugins/publishings/csdn-pub/package.json +19 -0
  82. package/plugins/publishings/csdn-pub/plugin.json +12 -0
  83. package/plugins/publishings/csdn-pub/src/index.ts +1178 -0
  84. package/plugins/publishings/csdn-pub/src/profile-check.ts +23 -0
  85. package/plugins/publishings/csdn-pub/tsconfig.json +4 -0
  86. package/plugins/publishings/emdash-pub/dist/index.js +158 -12
  87. package/plugins/publishings/emdash-pub/plugin.json +22 -1
  88. package/plugins/publishings/infoq-pub/dist/index.js +160 -12
  89. package/plugins/publishings/infoq-pub/dist/profile-check.js +160 -12
  90. package/plugins/publishings/infoq-pub/plugin.json +21 -0
  91. package/plugins/publishings/jike-pub/dist/index.js +21379 -0
  92. package/plugins/publishings/jike-pub/dist/profile-check.js +20951 -0
  93. package/plugins/publishings/jike-pub/package.json +19 -0
  94. package/plugins/publishings/jike-pub/plugin.json +12 -0
  95. package/plugins/publishings/jike-pub/src/index.ts +800 -0
  96. package/plugins/publishings/jike-pub/src/profile-check.ts +21 -0
  97. package/plugins/publishings/jike-pub/tsconfig.json +4 -0
  98. package/plugins/publishings/juejin-pub/dist/index.js +160 -12
  99. package/plugins/publishings/juejin-pub/dist/profile-check.js +160 -12
  100. package/plugins/publishings/juejin-pub/plugin.json +21 -0
  101. package/plugins/publishings/medium-pub/dist/index.js +158 -12
  102. package/plugins/publishings/medium-pub/plugin.json +22 -1
  103. package/plugins/publishings/podcast-pub/dist/index.js +158 -12
  104. package/plugins/publishings/qiita-pub/dist/index.js +158 -12
  105. package/plugins/publishings/qiita-pub/plugin.json +24 -1
  106. package/plugins/publishings/shipinhao-pub/dist/index.js +21715 -0
  107. package/plugins/publishings/shipinhao-pub/dist/profile-check.js +20431 -0
  108. package/plugins/publishings/shipinhao-pub/package.json +19 -0
  109. package/plugins/publishings/shipinhao-pub/plugin.json +12 -0
  110. package/plugins/publishings/shipinhao-pub/src/flow.ts +1323 -0
  111. package/plugins/publishings/shipinhao-pub/src/index.ts +173 -0
  112. package/plugins/publishings/shipinhao-pub/src/profile-check.ts +25 -0
  113. package/plugins/publishings/shipinhao-pub/src/selectors.ts +241 -0
  114. package/plugins/publishings/shipinhao-pub/tsconfig.json +4 -0
  115. package/plugins/publishings/sspai-pub/dist/index.js +21371 -0
  116. package/plugins/publishings/sspai-pub/dist/profile-check.js +20414 -0
  117. package/plugins/publishings/sspai-pub/package.json +19 -0
  118. package/plugins/publishings/sspai-pub/plugin.json +12 -0
  119. package/plugins/publishings/sspai-pub/src/flow.ts +624 -0
  120. package/plugins/publishings/sspai-pub/src/index.ts +167 -0
  121. package/plugins/publishings/sspai-pub/src/profile-check.ts +25 -0
  122. package/plugins/publishings/sspai-pub/src/selectors.ts +122 -0
  123. package/plugins/publishings/sspai-pub/tsconfig.json +4 -0
  124. package/plugins/publishings/substack-pub/dist/index.js +160 -12
  125. package/plugins/publishings/substack-pub/dist/profile-check.js +160 -12
  126. package/plugins/publishings/substack-pub/plugin.json +21 -0
  127. package/plugins/publishings/surfdash-pub/dist/index.js +158 -12
  128. package/plugins/publishings/surfdash-pub/plugin.json +22 -1
  129. package/plugins/publishings/threads-pub/dist/index.js +158 -12
  130. package/plugins/publishings/wechatmp-pub/dist/index.js +1669 -502
  131. package/plugins/publishings/wechatmp-pub/dist/profile-check.js +204 -21
  132. package/plugins/publishings/wechatmp-pub/plugin.json +32 -0
  133. package/plugins/publishings/wechatmp-pub/src/cgi-draft.ts +540 -0
  134. package/plugins/publishings/wechatmp-pub/src/cgi-media.ts +380 -0
  135. package/plugins/publishings/wechatmp-pub/src/cgi.ts +485 -0
  136. package/plugins/publishings/wechatmp-pub/src/flow.ts +104 -0
  137. package/plugins/publishings/weibo-pub/dist/index.js +160 -12
  138. package/plugins/publishings/weibo-pub/dist/profile-check.js +160 -12
  139. package/plugins/publishings/weibo-pub/plugin.json +35 -0
  140. package/plugins/publishings/x-pub/dist/index.js +160 -12
  141. package/plugins/publishings/x-pub/dist/profile-check.js +160 -12
  142. package/plugins/publishings/x-pub/plugin.json +40 -0
  143. package/plugins/publishings/xhs-pub/dist/index.js +160 -12
  144. package/plugins/publishings/xhs-pub/dist/profile-check.js +160 -12
  145. package/plugins/publishings/xhs-pub/plugin.json +37 -0
  146. package/plugins/publishings/xiaoyuzhou-pub/dist/index.js +21491 -0
  147. package/plugins/publishings/xiaoyuzhou-pub/dist/profile-check.js +20417 -0
  148. package/plugins/publishings/xiaoyuzhou-pub/package.json +19 -0
  149. package/plugins/publishings/xiaoyuzhou-pub/plugin.json +12 -0
  150. package/plugins/publishings/xiaoyuzhou-pub/src/flow.ts +826 -0
  151. package/plugins/publishings/xiaoyuzhou-pub/src/index.ts +174 -0
  152. package/plugins/publishings/xiaoyuzhou-pub/src/profile-check.ts +26 -0
  153. package/plugins/publishings/xiaoyuzhou-pub/src/selectors.ts +125 -0
  154. package/plugins/publishings/xiaoyuzhou-pub/tsconfig.json +4 -0
  155. package/plugins/publishings/zenn-pub/dist/index.js +158 -12
  156. package/plugins/publishings/zenn-pub/plugin.json +22 -1
  157. package/plugins/generations/omni-voice-gen/voices/robin-news.wav +0 -0
@@ -12309,6 +12309,83 @@ var init_chromium = __esm(() => {
12309
12309
  import { dirname as dirname3, join as join4 } from "path";
12310
12310
  import { parseArgs } from "util";
12311
12311
 
12312
+ // ../../packages/kk-core/src/content-limits.ts
12313
+ var PLATFORM_CONTENT_LIMITS = Object.freeze({
12314
+ schemaVersion: 5,
12315
+ tagLimits: Object.freeze({
12316
+ default: 7,
12317
+ imageText: Object.freeze({
12318
+ instagram: 5,
12319
+ douyin: 5,
12320
+ kuaishou: 4,
12321
+ weixin: 1,
12322
+ xiaohongshu: 10
12323
+ }),
12324
+ shortVideo: Object.freeze({
12325
+ douyin: 5,
12326
+ kuaishou: 4,
12327
+ xiaohongshu: 10,
12328
+ bilibili: 10,
12329
+ zhihu: 5,
12330
+ tiktok: 20,
12331
+ youtube: 60
12332
+ })
12333
+ }),
12334
+ titleCapabilities: Object.freeze({
12335
+ dynamic: Object.freeze({
12336
+ bilibili: Object.freeze({ max: 20, unit: "utf16_code_units" }),
12337
+ zhihu: Object.freeze({ max: 50, unit: "utf16_code_units" }),
12338
+ douban: Object.freeze({ max: 70, unit: "utf16_code_units" }),
12339
+ x: null,
12340
+ threads: null,
12341
+ weibo: null,
12342
+ jike: null,
12343
+ zsxq: null,
12344
+ toutiao: null,
12345
+ juejin: null
12346
+ }),
12347
+ imageText: Object.freeze({
12348
+ xiaohongshu: Object.freeze({ max: 20, unit: "xiaohongshu_title_weighted" }),
12349
+ weixin: Object.freeze({ max: 20, unit: "utf16_code_units" }),
12350
+ douyin: Object.freeze({ max: 20, unit: "utf16_code_units" }),
12351
+ shipinhao: Object.freeze({ max: 22, unit: "utf16_code_units" }),
12352
+ reddit: Object.freeze({ max: 300, unit: "utf16_code_units" })
12353
+ }),
12354
+ article: Object.freeze({
12355
+ juejin: Object.freeze({ max: 100, unit: "utf16_code_units" }),
12356
+ csdn: Object.freeze({ max: 100, unit: "utf16_code_units" }),
12357
+ cnblogs: Object.freeze({ max: 128, unit: "utf16_code_units" }),
12358
+ weibo: Object.freeze({ max: 30, unit: "utf16_code_units" }),
12359
+ sspai: Object.freeze({ max: 80, unit: "utf16_code_units" })
12360
+ }),
12361
+ shortVideo: Object.freeze({
12362
+ shipinhao: Object.freeze({ max: 16, unit: "utf16_code_units" }),
12363
+ douyin: Object.freeze({ max: 30, unit: "utf16_code_units" }),
12364
+ bilibili: Object.freeze({ max: 80, unit: "utf16_code_units" })
12365
+ })
12366
+ }),
12367
+ bodyCapabilities: Object.freeze({
12368
+ dynamic: Object.freeze({
12369
+ threads: Object.freeze({ max: 500, unit: "unicode_code_points", behavior: "split_thread" }),
12370
+ x: Object.freeze({ max: 280, unit: "weighted", behavior: "split_thread" }),
12371
+ weibo: Object.freeze({ max: 2000, unit: "unicode_code_points" }),
12372
+ jike: Object.freeze({ max: 1000, unit: "unicode_code_points" })
12373
+ }),
12374
+ imageText: Object.freeze({
12375
+ xiaohongshu: Object.freeze({ max: 1000, unit: "unicode_code_points" }),
12376
+ douyin: Object.freeze({ max: 1000, unit: "unicode_code_points" })
12377
+ }),
12378
+ article: Object.freeze({
12379
+ wechatmp: Object.freeze({ max: 50000, unit: "unicode_code_points" }),
12380
+ juejin: Object.freeze({ max: 50000, unit: "unicode_code_points" })
12381
+ }),
12382
+ shortVideo: Object.freeze({
12383
+ douyin: Object.freeze({ max: 1000, unit: "unicode_code_points" }),
12384
+ kuaishou: Object.freeze({ max: 1000, unit: "unicode_code_points" }),
12385
+ shipinhao: Object.freeze({ max: 1000, unit: "unicode_code_points" })
12386
+ })
12387
+ })
12388
+ });
12312
12389
  // ../../packages/kk-core/src/kinds.ts
12313
12390
  init_zod();
12314
12391
 
@@ -12399,6 +12476,67 @@ var BrowserSessionDescriptorSchema = object({
12399
12476
  }
12400
12477
  }).optional()
12401
12478
  }).strict();
12479
+ var ContentCountUnitSchema = _enum([
12480
+ "utf16_code_units",
12481
+ "unicode_code_points",
12482
+ "weighted",
12483
+ "xiaohongshu_title_weighted"
12484
+ ]);
12485
+ var LimitEntrySchema = object({
12486
+ max: number2().int().positive(),
12487
+ unit: ContentCountUnitSchema
12488
+ }).strict();
12489
+ var PublishingProfileLimitsSchema = object({
12490
+ title: LimitEntrySchema.optional(),
12491
+ body: LimitEntrySchema.optional()
12492
+ }).strict();
12493
+ var PublishingProfileRequiresSchema = object({
12494
+ cover: boolean2().optional(),
12495
+ orderedImages: boolean2().optional()
12496
+ }).strict();
12497
+ var PublishingProfileModeBindingSchema = object({
12498
+ metadata: record(string2(), unknown())
12499
+ }).strict();
12500
+ var PublishingProfileModesSchema = object({
12501
+ draft: PublishingProfileModeBindingSchema.optional(),
12502
+ live: PublishingProfileModeBindingSchema.optional()
12503
+ }).strict().superRefine((modes, ctx) => {
12504
+ if (modes.draft === undefined && modes.live === undefined) {
12505
+ ctx.addIssue({
12506
+ code: "custom",
12507
+ message: 'modes must define at least one of "draft" or "live"'
12508
+ });
12509
+ }
12510
+ });
12511
+ var PublishingProfileSchema = object({
12512
+ format: string2().min(1),
12513
+ locale: string2().regex(/^(source|[a-z]{2,3}(-[A-Za-z0-9]+)*)$/, {
12514
+ message: 'locale must be "source" or a valid language tag'
12515
+ }),
12516
+ limits: PublishingProfileLimitsSchema.optional(),
12517
+ requires: PublishingProfileRequiresSchema.optional(),
12518
+ modes: PublishingProfileModesSchema
12519
+ }).strict();
12520
+ var PublishingCapabilitiesSchema = object({
12521
+ defaultProfile: string2().min(1),
12522
+ profiles: record(string2().regex(/^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/), PublishingProfileSchema)
12523
+ }).strict().superRefine((data, ctx) => {
12524
+ const keys = Object.keys(data.profiles);
12525
+ if (keys.length === 0) {
12526
+ ctx.addIssue({
12527
+ code: "custom",
12528
+ path: ["profiles"],
12529
+ message: "profiles record must be nonempty"
12530
+ });
12531
+ }
12532
+ if (!(data.defaultProfile in data.profiles)) {
12533
+ ctx.addIssue({
12534
+ code: "custom",
12535
+ path: ["defaultProfile"],
12536
+ message: `defaultProfile "${data.defaultProfile}" must reference a declared profile`
12537
+ });
12538
+ }
12539
+ });
12402
12540
  var PluginManifestSchemaBase = looseObject({
12403
12541
  name: string2().min(1),
12404
12542
  kind: PluginKindSchema,
@@ -12407,23 +12545,31 @@ var PluginManifestSchemaBase = looseObject({
12407
12545
  version: string2().optional(),
12408
12546
  description: string2().optional(),
12409
12547
  operations: record(string2(), PluginOperationSchema).optional(),
12410
- browserSession: BrowserSessionDescriptorSchema.optional()
12548
+ browserSession: BrowserSessionDescriptorSchema.optional(),
12549
+ publishing: PublishingCapabilitiesSchema.optional()
12411
12550
  });
12412
12551
  var PluginManifestSchema = PluginManifestSchemaBase.superRefine((manifest, ctx) => {
12413
- if (manifest.browserSession === undefined)
12414
- return;
12415
- if (manifest.kind !== "publish") {
12416
- ctx.addIssue({
12417
- code: "custom",
12418
- path: ["browserSession"],
12419
- message: `browserSession requires kind "publish", not "${manifest.kind}"`
12420
- });
12552
+ if (manifest.browserSession !== undefined) {
12553
+ if (manifest.kind !== "publish") {
12554
+ ctx.addIssue({
12555
+ code: "custom",
12556
+ path: ["browserSession"],
12557
+ message: `browserSession requires kind "publish", not "${manifest.kind}"`
12558
+ });
12559
+ }
12560
+ if (manifest.check === undefined) {
12561
+ ctx.addIssue({
12562
+ code: "custom",
12563
+ path: ["browserSession"],
12564
+ message: "browserSession requires a check probe entry that owns the session routines"
12565
+ });
12566
+ }
12421
12567
  }
12422
- if (manifest.check === undefined) {
12568
+ if (manifest.publishing !== undefined && manifest.kind !== "publish") {
12423
12569
  ctx.addIssue({
12424
12570
  code: "custom",
12425
- path: ["browserSession"],
12426
- message: "browserSession requires a check probe entry that owns the session routines"
12571
+ path: ["publishing"],
12572
+ message: `publishing requires kind "publish", not "${manifest.kind}"`
12427
12573
  });
12428
12574
  }
12429
12575
  });
@@ -11984,6 +11984,83 @@ var init_file_system_node = () => {};
11984
11984
  import { dirname as dirname2 } from "path";
11985
11985
  import { parseArgs } from "util";
11986
11986
 
11987
+ // ../../packages/kk-core/src/content-limits.ts
11988
+ var PLATFORM_CONTENT_LIMITS = Object.freeze({
11989
+ schemaVersion: 5,
11990
+ tagLimits: Object.freeze({
11991
+ default: 7,
11992
+ imageText: Object.freeze({
11993
+ instagram: 5,
11994
+ douyin: 5,
11995
+ kuaishou: 4,
11996
+ weixin: 1,
11997
+ xiaohongshu: 10
11998
+ }),
11999
+ shortVideo: Object.freeze({
12000
+ douyin: 5,
12001
+ kuaishou: 4,
12002
+ xiaohongshu: 10,
12003
+ bilibili: 10,
12004
+ zhihu: 5,
12005
+ tiktok: 20,
12006
+ youtube: 60
12007
+ })
12008
+ }),
12009
+ titleCapabilities: Object.freeze({
12010
+ dynamic: Object.freeze({
12011
+ bilibili: Object.freeze({ max: 20, unit: "utf16_code_units" }),
12012
+ zhihu: Object.freeze({ max: 50, unit: "utf16_code_units" }),
12013
+ douban: Object.freeze({ max: 70, unit: "utf16_code_units" }),
12014
+ x: null,
12015
+ threads: null,
12016
+ weibo: null,
12017
+ jike: null,
12018
+ zsxq: null,
12019
+ toutiao: null,
12020
+ juejin: null
12021
+ }),
12022
+ imageText: Object.freeze({
12023
+ xiaohongshu: Object.freeze({ max: 20, unit: "xiaohongshu_title_weighted" }),
12024
+ weixin: Object.freeze({ max: 20, unit: "utf16_code_units" }),
12025
+ douyin: Object.freeze({ max: 20, unit: "utf16_code_units" }),
12026
+ shipinhao: Object.freeze({ max: 22, unit: "utf16_code_units" }),
12027
+ reddit: Object.freeze({ max: 300, unit: "utf16_code_units" })
12028
+ }),
12029
+ article: Object.freeze({
12030
+ juejin: Object.freeze({ max: 100, unit: "utf16_code_units" }),
12031
+ csdn: Object.freeze({ max: 100, unit: "utf16_code_units" }),
12032
+ cnblogs: Object.freeze({ max: 128, unit: "utf16_code_units" }),
12033
+ weibo: Object.freeze({ max: 30, unit: "utf16_code_units" }),
12034
+ sspai: Object.freeze({ max: 80, unit: "utf16_code_units" })
12035
+ }),
12036
+ shortVideo: Object.freeze({
12037
+ shipinhao: Object.freeze({ max: 16, unit: "utf16_code_units" }),
12038
+ douyin: Object.freeze({ max: 30, unit: "utf16_code_units" }),
12039
+ bilibili: Object.freeze({ max: 80, unit: "utf16_code_units" })
12040
+ })
12041
+ }),
12042
+ bodyCapabilities: Object.freeze({
12043
+ dynamic: Object.freeze({
12044
+ threads: Object.freeze({ max: 500, unit: "unicode_code_points", behavior: "split_thread" }),
12045
+ x: Object.freeze({ max: 280, unit: "weighted", behavior: "split_thread" }),
12046
+ weibo: Object.freeze({ max: 2000, unit: "unicode_code_points" }),
12047
+ jike: Object.freeze({ max: 1000, unit: "unicode_code_points" })
12048
+ }),
12049
+ imageText: Object.freeze({
12050
+ xiaohongshu: Object.freeze({ max: 1000, unit: "unicode_code_points" }),
12051
+ douyin: Object.freeze({ max: 1000, unit: "unicode_code_points" })
12052
+ }),
12053
+ article: Object.freeze({
12054
+ wechatmp: Object.freeze({ max: 50000, unit: "unicode_code_points" }),
12055
+ juejin: Object.freeze({ max: 50000, unit: "unicode_code_points" })
12056
+ }),
12057
+ shortVideo: Object.freeze({
12058
+ douyin: Object.freeze({ max: 1000, unit: "unicode_code_points" }),
12059
+ kuaishou: Object.freeze({ max: 1000, unit: "unicode_code_points" }),
12060
+ shipinhao: Object.freeze({ max: 1000, unit: "unicode_code_points" })
12061
+ })
12062
+ })
12063
+ });
11987
12064
  // ../../packages/kk-core/src/kinds.ts
11988
12065
  init_zod();
11989
12066
 
@@ -12074,6 +12151,67 @@ var BrowserSessionDescriptorSchema = object({
12074
12151
  }
12075
12152
  }).optional()
12076
12153
  }).strict();
12154
+ var ContentCountUnitSchema = _enum([
12155
+ "utf16_code_units",
12156
+ "unicode_code_points",
12157
+ "weighted",
12158
+ "xiaohongshu_title_weighted"
12159
+ ]);
12160
+ var LimitEntrySchema = object({
12161
+ max: number2().int().positive(),
12162
+ unit: ContentCountUnitSchema
12163
+ }).strict();
12164
+ var PublishingProfileLimitsSchema = object({
12165
+ title: LimitEntrySchema.optional(),
12166
+ body: LimitEntrySchema.optional()
12167
+ }).strict();
12168
+ var PublishingProfileRequiresSchema = object({
12169
+ cover: boolean2().optional(),
12170
+ orderedImages: boolean2().optional()
12171
+ }).strict();
12172
+ var PublishingProfileModeBindingSchema = object({
12173
+ metadata: record(string2(), unknown())
12174
+ }).strict();
12175
+ var PublishingProfileModesSchema = object({
12176
+ draft: PublishingProfileModeBindingSchema.optional(),
12177
+ live: PublishingProfileModeBindingSchema.optional()
12178
+ }).strict().superRefine((modes, ctx) => {
12179
+ if (modes.draft === undefined && modes.live === undefined) {
12180
+ ctx.addIssue({
12181
+ code: "custom",
12182
+ message: 'modes must define at least one of "draft" or "live"'
12183
+ });
12184
+ }
12185
+ });
12186
+ var PublishingProfileSchema = object({
12187
+ format: string2().min(1),
12188
+ locale: string2().regex(/^(source|[a-z]{2,3}(-[A-Za-z0-9]+)*)$/, {
12189
+ message: 'locale must be "source" or a valid language tag'
12190
+ }),
12191
+ limits: PublishingProfileLimitsSchema.optional(),
12192
+ requires: PublishingProfileRequiresSchema.optional(),
12193
+ modes: PublishingProfileModesSchema
12194
+ }).strict();
12195
+ var PublishingCapabilitiesSchema = object({
12196
+ defaultProfile: string2().min(1),
12197
+ profiles: record(string2().regex(/^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/), PublishingProfileSchema)
12198
+ }).strict().superRefine((data, ctx) => {
12199
+ const keys = Object.keys(data.profiles);
12200
+ if (keys.length === 0) {
12201
+ ctx.addIssue({
12202
+ code: "custom",
12203
+ path: ["profiles"],
12204
+ message: "profiles record must be nonempty"
12205
+ });
12206
+ }
12207
+ if (!(data.defaultProfile in data.profiles)) {
12208
+ ctx.addIssue({
12209
+ code: "custom",
12210
+ path: ["defaultProfile"],
12211
+ message: `defaultProfile "${data.defaultProfile}" must reference a declared profile`
12212
+ });
12213
+ }
12214
+ });
12077
12215
  var PluginManifestSchemaBase = looseObject({
12078
12216
  name: string2().min(1),
12079
12217
  kind: PluginKindSchema,
@@ -12082,23 +12220,31 @@ var PluginManifestSchemaBase = looseObject({
12082
12220
  version: string2().optional(),
12083
12221
  description: string2().optional(),
12084
12222
  operations: record(string2(), PluginOperationSchema).optional(),
12085
- browserSession: BrowserSessionDescriptorSchema.optional()
12223
+ browserSession: BrowserSessionDescriptorSchema.optional(),
12224
+ publishing: PublishingCapabilitiesSchema.optional()
12086
12225
  });
12087
12226
  var PluginManifestSchema = PluginManifestSchemaBase.superRefine((manifest, ctx) => {
12088
- if (manifest.browserSession === undefined)
12089
- return;
12090
- if (manifest.kind !== "publish") {
12091
- ctx.addIssue({
12092
- code: "custom",
12093
- path: ["browserSession"],
12094
- message: `browserSession requires kind "publish", not "${manifest.kind}"`
12095
- });
12227
+ if (manifest.browserSession !== undefined) {
12228
+ if (manifest.kind !== "publish") {
12229
+ ctx.addIssue({
12230
+ code: "custom",
12231
+ path: ["browserSession"],
12232
+ message: `browserSession requires kind "publish", not "${manifest.kind}"`
12233
+ });
12234
+ }
12235
+ if (manifest.check === undefined) {
12236
+ ctx.addIssue({
12237
+ code: "custom",
12238
+ path: ["browserSession"],
12239
+ message: "browserSession requires a check probe entry that owns the session routines"
12240
+ });
12241
+ }
12096
12242
  }
12097
- if (manifest.check === undefined) {
12243
+ if (manifest.publishing !== undefined && manifest.kind !== "publish") {
12098
12244
  ctx.addIssue({
12099
12245
  code: "custom",
12100
- path: ["browserSession"],
12101
- message: "browserSession requires a check probe entry that owns the session routines"
12246
+ path: ["publishing"],
12247
+ message: `publishing requires kind "publish", not "${manifest.kind}"`
12102
12248
  });
12103
12249
  }
12104
12250
  });
@@ -10,9 +10,12 @@ spur workflow run plugins/kk/workflows/kk-daily-ai-voice.yaml \
10
10
  --vars '{"voice_generator":"voice-gen"}' # other vars per your kk config
11
11
  ```
12
12
 
13
- > **Voice identity:** the shipped `robin-news` profile is an instruct placeholder. For a real
14
- > operator voice, record a 3–10 s clip into a private registry (`OMNIVOICE_PROFILE_REGISTRY`)
15
- > and it supersedes the committed entry.
13
+ > **Voice identity:** the shipped `robin-news` profile is an instruct placeholder — it pins no
14
+ > speaker, so a multi-segment render can change voice between segments. For a real operator voice,
15
+ > keep a 3–10 s clip outside the repo (e.g. `~/.config/kk/voices/robin-news.wav`), record it in a
16
+ > private registry (`OMNIVOICE_PROFILE_REGISTRY`, e.g. `~/.config/kk/omni-voice-profiles.json`,
17
+ > wired through `plugins.generations.omni-voice-gen.env`), and it supersedes the committed entry.
18
+ > Voice assets are never committed (task 0159).
16
19
 
17
20
  ## Setup
18
21
 
@@ -51,7 +54,15 @@ Profiles map a name to one of three voice-specification kinds. The registry live
51
54
  |------|-----------|-------------|
52
55
  | **Clone** | `{ "ref_audio": "<path>", "ref_text": "<transcript>" }` | 3–10 s reference clip + its transcript |
53
56
  | **Saved prompt** | `{ "prompt": "<path>.pt" }` | Pre-computed clone prompt via `create_voice_clone_prompt` |
54
- | **Instruct** | `{ "instruct": "<description>" }` | Text description of the desired voice style |
57
+ | **Instruct** | `{ "instruct": "<tokens>" }` | Voice style from OmniVoice's allowlisted tokens |
58
+
59
+ **Instruct vocabulary** (OmniVoice rejects anything else with *Unsupported instruct items*, so
60
+ only these are usable): gender `male`/`female`; age `child`, `teenager`, `young adult`,
61
+ `middle-aged`, `elderly`; pitch `very low pitch` … `very high pitch`; style `whisper`; accent
62
+ `american accent`, `british accent`, … — English tokens comma+space separated; the Chinese
63
+ equivalents use a full-width comma. Free-form prose like *"clear, natural, calm news
64
+ broadcast"* fails validation, and an instruct pins no speaker identity anyway: every request
65
+ draws a new voice, so use a clone profile for multi-segment work.
55
66
 
56
67
  ### Creating a profile (clone example)
57
68
 
@@ -1,7 +1,6 @@
1
1
  {
2
2
  "robin-news": {
3
- "ref_audio": "voices/robin-news.wav",
4
- "ref_text": "本届赛事由北京市人民政府、中央广播电视总台、世界机器人合作组织、亚太机器人世界杯国际理事会联合主办。来自六大洲 16 个国家的 666 支队伍、2056 台机器人参赛,队伍数量较首届增长 138%,机器人"
3
+ "instruct": "male, middle-aged, moderate pitch"
5
4
  },
6
5
  "sample-clone": {
7
6
  "ref_audio": "voices/sample-ref.wav",
@@ -11984,6 +11984,83 @@ var init_file_system_node = () => {};
11984
11984
  import { basename, dirname as dirname2, extname, join as join2, resolve } from "path";
11985
11985
  import { parseArgs } from "util";
11986
11986
 
11987
+ // ../../packages/kk-core/src/content-limits.ts
11988
+ var PLATFORM_CONTENT_LIMITS = Object.freeze({
11989
+ schemaVersion: 5,
11990
+ tagLimits: Object.freeze({
11991
+ default: 7,
11992
+ imageText: Object.freeze({
11993
+ instagram: 5,
11994
+ douyin: 5,
11995
+ kuaishou: 4,
11996
+ weixin: 1,
11997
+ xiaohongshu: 10
11998
+ }),
11999
+ shortVideo: Object.freeze({
12000
+ douyin: 5,
12001
+ kuaishou: 4,
12002
+ xiaohongshu: 10,
12003
+ bilibili: 10,
12004
+ zhihu: 5,
12005
+ tiktok: 20,
12006
+ youtube: 60
12007
+ })
12008
+ }),
12009
+ titleCapabilities: Object.freeze({
12010
+ dynamic: Object.freeze({
12011
+ bilibili: Object.freeze({ max: 20, unit: "utf16_code_units" }),
12012
+ zhihu: Object.freeze({ max: 50, unit: "utf16_code_units" }),
12013
+ douban: Object.freeze({ max: 70, unit: "utf16_code_units" }),
12014
+ x: null,
12015
+ threads: null,
12016
+ weibo: null,
12017
+ jike: null,
12018
+ zsxq: null,
12019
+ toutiao: null,
12020
+ juejin: null
12021
+ }),
12022
+ imageText: Object.freeze({
12023
+ xiaohongshu: Object.freeze({ max: 20, unit: "xiaohongshu_title_weighted" }),
12024
+ weixin: Object.freeze({ max: 20, unit: "utf16_code_units" }),
12025
+ douyin: Object.freeze({ max: 20, unit: "utf16_code_units" }),
12026
+ shipinhao: Object.freeze({ max: 22, unit: "utf16_code_units" }),
12027
+ reddit: Object.freeze({ max: 300, unit: "utf16_code_units" })
12028
+ }),
12029
+ article: Object.freeze({
12030
+ juejin: Object.freeze({ max: 100, unit: "utf16_code_units" }),
12031
+ csdn: Object.freeze({ max: 100, unit: "utf16_code_units" }),
12032
+ cnblogs: Object.freeze({ max: 128, unit: "utf16_code_units" }),
12033
+ weibo: Object.freeze({ max: 30, unit: "utf16_code_units" }),
12034
+ sspai: Object.freeze({ max: 80, unit: "utf16_code_units" })
12035
+ }),
12036
+ shortVideo: Object.freeze({
12037
+ shipinhao: Object.freeze({ max: 16, unit: "utf16_code_units" }),
12038
+ douyin: Object.freeze({ max: 30, unit: "utf16_code_units" }),
12039
+ bilibili: Object.freeze({ max: 80, unit: "utf16_code_units" })
12040
+ })
12041
+ }),
12042
+ bodyCapabilities: Object.freeze({
12043
+ dynamic: Object.freeze({
12044
+ threads: Object.freeze({ max: 500, unit: "unicode_code_points", behavior: "split_thread" }),
12045
+ x: Object.freeze({ max: 280, unit: "weighted", behavior: "split_thread" }),
12046
+ weibo: Object.freeze({ max: 2000, unit: "unicode_code_points" }),
12047
+ jike: Object.freeze({ max: 1000, unit: "unicode_code_points" })
12048
+ }),
12049
+ imageText: Object.freeze({
12050
+ xiaohongshu: Object.freeze({ max: 1000, unit: "unicode_code_points" }),
12051
+ douyin: Object.freeze({ max: 1000, unit: "unicode_code_points" })
12052
+ }),
12053
+ article: Object.freeze({
12054
+ wechatmp: Object.freeze({ max: 50000, unit: "unicode_code_points" }),
12055
+ juejin: Object.freeze({ max: 50000, unit: "unicode_code_points" })
12056
+ }),
12057
+ shortVideo: Object.freeze({
12058
+ douyin: Object.freeze({ max: 1000, unit: "unicode_code_points" }),
12059
+ kuaishou: Object.freeze({ max: 1000, unit: "unicode_code_points" }),
12060
+ shipinhao: Object.freeze({ max: 1000, unit: "unicode_code_points" })
12061
+ })
12062
+ })
12063
+ });
11987
12064
  // ../../packages/kk-core/src/kinds.ts
11988
12065
  init_zod();
11989
12066
 
@@ -12074,6 +12151,67 @@ var BrowserSessionDescriptorSchema = object({
12074
12151
  }
12075
12152
  }).optional()
12076
12153
  }).strict();
12154
+ var ContentCountUnitSchema = _enum([
12155
+ "utf16_code_units",
12156
+ "unicode_code_points",
12157
+ "weighted",
12158
+ "xiaohongshu_title_weighted"
12159
+ ]);
12160
+ var LimitEntrySchema = object({
12161
+ max: number2().int().positive(),
12162
+ unit: ContentCountUnitSchema
12163
+ }).strict();
12164
+ var PublishingProfileLimitsSchema = object({
12165
+ title: LimitEntrySchema.optional(),
12166
+ body: LimitEntrySchema.optional()
12167
+ }).strict();
12168
+ var PublishingProfileRequiresSchema = object({
12169
+ cover: boolean2().optional(),
12170
+ orderedImages: boolean2().optional()
12171
+ }).strict();
12172
+ var PublishingProfileModeBindingSchema = object({
12173
+ metadata: record(string2(), unknown())
12174
+ }).strict();
12175
+ var PublishingProfileModesSchema = object({
12176
+ draft: PublishingProfileModeBindingSchema.optional(),
12177
+ live: PublishingProfileModeBindingSchema.optional()
12178
+ }).strict().superRefine((modes, ctx) => {
12179
+ if (modes.draft === undefined && modes.live === undefined) {
12180
+ ctx.addIssue({
12181
+ code: "custom",
12182
+ message: 'modes must define at least one of "draft" or "live"'
12183
+ });
12184
+ }
12185
+ });
12186
+ var PublishingProfileSchema = object({
12187
+ format: string2().min(1),
12188
+ locale: string2().regex(/^(source|[a-z]{2,3}(-[A-Za-z0-9]+)*)$/, {
12189
+ message: 'locale must be "source" or a valid language tag'
12190
+ }),
12191
+ limits: PublishingProfileLimitsSchema.optional(),
12192
+ requires: PublishingProfileRequiresSchema.optional(),
12193
+ modes: PublishingProfileModesSchema
12194
+ }).strict();
12195
+ var PublishingCapabilitiesSchema = object({
12196
+ defaultProfile: string2().min(1),
12197
+ profiles: record(string2().regex(/^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/), PublishingProfileSchema)
12198
+ }).strict().superRefine((data, ctx) => {
12199
+ const keys = Object.keys(data.profiles);
12200
+ if (keys.length === 0) {
12201
+ ctx.addIssue({
12202
+ code: "custom",
12203
+ path: ["profiles"],
12204
+ message: "profiles record must be nonempty"
12205
+ });
12206
+ }
12207
+ if (!(data.defaultProfile in data.profiles)) {
12208
+ ctx.addIssue({
12209
+ code: "custom",
12210
+ path: ["defaultProfile"],
12211
+ message: `defaultProfile "${data.defaultProfile}" must reference a declared profile`
12212
+ });
12213
+ }
12214
+ });
12077
12215
  var PluginManifestSchemaBase = looseObject({
12078
12216
  name: string2().min(1),
12079
12217
  kind: PluginKindSchema,
@@ -12082,23 +12220,31 @@ var PluginManifestSchemaBase = looseObject({
12082
12220
  version: string2().optional(),
12083
12221
  description: string2().optional(),
12084
12222
  operations: record(string2(), PluginOperationSchema).optional(),
12085
- browserSession: BrowserSessionDescriptorSchema.optional()
12223
+ browserSession: BrowserSessionDescriptorSchema.optional(),
12224
+ publishing: PublishingCapabilitiesSchema.optional()
12086
12225
  });
12087
12226
  var PluginManifestSchema = PluginManifestSchemaBase.superRefine((manifest, ctx) => {
12088
- if (manifest.browserSession === undefined)
12089
- return;
12090
- if (manifest.kind !== "publish") {
12091
- ctx.addIssue({
12092
- code: "custom",
12093
- path: ["browserSession"],
12094
- message: `browserSession requires kind "publish", not "${manifest.kind}"`
12095
- });
12227
+ if (manifest.browserSession !== undefined) {
12228
+ if (manifest.kind !== "publish") {
12229
+ ctx.addIssue({
12230
+ code: "custom",
12231
+ path: ["browserSession"],
12232
+ message: `browserSession requires kind "publish", not "${manifest.kind}"`
12233
+ });
12234
+ }
12235
+ if (manifest.check === undefined) {
12236
+ ctx.addIssue({
12237
+ code: "custom",
12238
+ path: ["browserSession"],
12239
+ message: "browserSession requires a check probe entry that owns the session routines"
12240
+ });
12241
+ }
12096
12242
  }
12097
- if (manifest.check === undefined) {
12243
+ if (manifest.publishing !== undefined && manifest.kind !== "publish") {
12098
12244
  ctx.addIssue({
12099
12245
  code: "custom",
12100
- path: ["browserSession"],
12101
- message: "browserSession requires a check probe entry that owns the session routines"
12246
+ path: ["publishing"],
12247
+ message: `publishing requires kind "publish", not "${manifest.kind}"`
12102
12248
  });
12103
12249
  }
12104
12250
  });
@@ -62,11 +62,31 @@ that evidence belongs to task 0258.
62
62
  - Relative assets resolve against the registry directory; serialized OmniVoice prompts, duplicate
63
63
  ids/names, mixed mode fields and vendor paths are refused.
64
64
 
65
+ > **Voice identity — `instruct` pins no speaker, and multi-segment work is refused on it.** VoxCPM conditions on a reference clip when one is
66
+ > given; with `instruct` alone there is no prompt cache, so the model samples `torch.randn` per
67
+ > request and **every segment can change voice**. The shipped registry is an instruct placeholder
68
+ > (`mode: instruct`): a single segment still renders, but a second one fails the invocation, so a
69
+ > multi-segment episode can never ship a voice that changes mid-item. `kk-daily-ai-voice2` defaults
70
+ > to this driver with the operator's anchored `robin-news` clone (adopted 2026-10-15 after an A/B
71
+ > listen); the shipped placeholder exists only so the mode machinery is exercised. For a stable voice
72
+ > point `VOXCPM_PROFILES_PATH` at an operator-private registry holding a `reference` (or
73
+ > `continuation`) profile — e.g. `~/.config/kk/voxcpm-profiles/profiles.json` with
74
+ > `reference_wav_path` aimed at a clip in `~/.config/kk/voices/`, wired through
75
+ > `plugins.generations.voxcpm-tts.env` in `~/.config/kk/config.yaml`.
76
+ >
77
+ > Measured 2026-10-15 on the same three texts: `instruct` swung 141 Hz of median pitch (sd 58 Hz);
78
+ > a reference-anchored profile swung 22–26 Hz (sd 9–12 Hz) and correlated 0.95+ with its clip.
79
+ > Grade any render with `scripts/audit-speaker-consistency.py` (needs this plugin's venv):
80
+ > a per-item F0 spread over 45 Hz means the profile is not anchoring a speaker.
81
+
65
82
  ## Control policy
66
83
 
67
84
  `normalize` maps directly; an explicit `seed` calls `torch.manual_seed` before synthesis (the
68
85
  2.0.3 API has no `seed`/`instruct` keyword); `language` is automatic multilingual inference with
69
86
  an advisory diagnostic; `max_chunk_chars`/`crossfade_ms` are advisory (one warning per invocation)
70
- — the shared VoiceScript segmentation remains the request boundary. A per-request `engine`,
87
+ — the shared VoiceScript segmentation remains the request boundary. A per-request `instruct` is
88
+ **ignored** on a `reference`/`continuation` profile (advisory diagnostic): the daily pipeline sends
89
+ one for every segment, derived from its `emotion`, and the anchored clip already defines the voice.
90
+ A per-request `engine`,
71
91
  `personality=true` or an active `effects_chain` is rejected. Speed stays in shared postprocessing.
72
92
  Transcription is omitted, so ASR-dependent QC is reported unavailable (not passing evidence).