@gobing-ai/knowledge-kit 0.0.12 → 0.0.14

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 (152) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/dist/index.js +120 -26
  3. package/package.json +1 -1
  4. package/plugins/generations/content-gen/dist/index.js +22187 -0
  5. package/plugins/generations/content-gen/plugin.json +1 -1
  6. package/plugins/generations/core-facts-gen/dist/index.js +22068 -0
  7. package/plugins/generations/core-facts-gen/plugin.json +1 -1
  8. package/plugins/generations/daily-article-gen/dist/index.js +22050 -0
  9. package/plugins/generations/daily-article-gen/plugin.json +1 -1
  10. package/plugins/generations/daily-article-gen/src/index.ts +13 -1
  11. package/plugins/generations/dailynews-gen/dist/index.js +22344 -0
  12. package/plugins/generations/dailynews-gen/plugin.json +1 -1
  13. package/plugins/generations/episode-plan-gen/dist/index.js +22503 -0
  14. package/plugins/generations/episode-plan-gen/plugin.json +1 -1
  15. package/plugins/generations/episode-plan-gen/src/index.ts +11 -0
  16. package/plugins/generations/image-gen/config.example.yaml +75 -0
  17. package/plugins/generations/image-gen/dist/index.js +24862 -0
  18. package/plugins/generations/image-gen/package.json +17 -0
  19. package/plugins/generations/image-gen/plugin.json +7 -0
  20. package/plugins/generations/image-gen/presets/formats/cover.yaml +57 -0
  21. package/plugins/generations/image-gen/presets/formats/free.yaml +46 -0
  22. package/plugins/generations/image-gen/presets/formats/illustration.yaml +48 -0
  23. package/plugins/generations/image-gen/presets/styles/clean-webapp-ui.yaml +28 -0
  24. package/plugins/generations/image-gen/presets/styles/cute.yaml +3 -0
  25. package/plugins/generations/image-gen/presets/styles/editorial.yaml +3 -0
  26. package/plugins/generations/image-gen/presets/styles/fresh.yaml +3 -0
  27. package/plugins/generations/image-gen/presets/styles/minimalist.yaml +3 -0
  28. package/plugins/generations/image-gen/presets/styles/photorealistic.yaml +3 -0
  29. package/plugins/generations/image-gen/presets/styles/sketch.yaml +3 -0
  30. package/plugins/generations/image-gen/presets/styles/technical-diagram.yaml +3 -0
  31. package/plugins/generations/image-gen/presets/styles/vibrant.yaml +3 -0
  32. package/plugins/generations/image-gen/presets/styles/warm.yaml +3 -0
  33. package/plugins/generations/image-gen/src/bytes.ts +19 -0
  34. package/plugins/generations/image-gen/src/index.ts +319 -0
  35. package/plugins/generations/image-gen/src/job.ts +143 -0
  36. package/plugins/generations/image-gen/src/paths.ts +31 -0
  37. package/plugins/generations/image-gen/src/presets.ts +344 -0
  38. package/plugins/generations/image-gen/src/providers/agnes.ts +110 -0
  39. package/plugins/generations/image-gen/src/providers/azure.ts +153 -0
  40. package/plugins/generations/image-gen/src/providers/codex-cli.ts +170 -0
  41. package/plugins/generations/image-gen/src/providers/dashscope.ts +485 -0
  42. package/plugins/generations/image-gen/src/providers/google.ts +268 -0
  43. package/plugins/generations/image-gen/src/providers/huggingface.ts +59 -0
  44. package/plugins/generations/image-gen/src/providers/jimeng.ts +259 -0
  45. package/plugins/generations/image-gen/src/providers/minimax.ts +171 -0
  46. package/plugins/generations/image-gen/src/providers/openai.ts +319 -0
  47. package/plugins/generations/image-gen/src/providers/openrouter.ts +257 -0
  48. package/plugins/generations/image-gen/src/providers/refs.ts +24 -0
  49. package/plugins/generations/image-gen/src/providers/replicate.ts +279 -0
  50. package/plugins/generations/image-gen/src/providers/seedream.ts +128 -0
  51. package/plugins/generations/image-gen/src/providers/types.ts +286 -0
  52. package/plugins/generations/image-gen/src/providers/zai.ts +237 -0
  53. package/plugins/generations/image-gen/tsconfig.json +8 -0
  54. package/plugins/generations/news-report-gen/dist/index.js +22193 -0
  55. package/plugins/generations/news-report-gen/package.json +17 -0
  56. package/plugins/generations/news-report-gen/plugin.json +7 -0
  57. package/plugins/generations/news-report-gen/src/index.ts +308 -0
  58. package/plugins/generations/news-report-gen/tsconfig.json +4 -0
  59. package/plugins/generations/omni-voice-gen/Makefile +14 -0
  60. package/plugins/generations/omni-voice-gen/README.md +112 -0
  61. package/plugins/generations/omni-voice-gen/bin/omni-voice-gen +2 -0
  62. package/plugins/generations/omni-voice-gen/dist/omni-voice-gen-prr8skpb. +2 -0
  63. package/plugins/generations/omni-voice-gen/dist/omni-voice-gen.js +6 -0
  64. package/plugins/generations/omni-voice-gen/plugin.json +6 -0
  65. package/plugins/generations/omni-voice-gen/profiles.json +12 -0
  66. package/plugins/generations/omni-voice-gen/pyproject.toml +25 -0
  67. package/plugins/generations/omni-voice-gen/scripts/coverage_gate.py +74 -0
  68. package/plugins/generations/omni-voice-gen/src/omni_voice_gen/__init__.py +1 -0
  69. package/plugins/generations/omni-voice-gen/src/omni_voice_gen/__main__.py +39 -0
  70. package/plugins/generations/omni-voice-gen/src/omni_voice_gen/audio.py +190 -0
  71. package/plugins/generations/omni-voice-gen/src/omni_voice_gen/backend.py +150 -0
  72. package/plugins/generations/omni-voice-gen/src/omni_voice_gen/contract.py +76 -0
  73. package/plugins/generations/omni-voice-gen/src/omni_voice_gen/mp3.py +60 -0
  74. package/plugins/generations/omni-voice-gen/src/omni_voice_gen/pipeline.py +289 -0
  75. package/plugins/generations/omni-voice-gen/src/omni_voice_gen/profiles.py +100 -0
  76. package/plugins/generations/omni-voice-gen/src/omni_voice_gen/qc.py +234 -0
  77. package/plugins/generations/omni-voice-gen/src/omni_voice_gen/voicescript.py +352 -0
  78. package/plugins/generations/omni-voice-gen/uv.lock +3510 -0
  79. package/plugins/generations/voice-gen/dist/index.js +23055 -0
  80. package/plugins/generations/voice-gen/plugin.json +1 -1
  81. package/plugins/generations/voice-gen/src/index.ts +16 -1
  82. package/plugins/generations/voice-gen/src/voicebox-client.ts +3 -1
  83. package/plugins/ingestions/aihot-ingest/dist/index.js +22378 -0
  84. package/plugins/ingestions/aihot-ingest/plugin.json +1 -1
  85. package/plugins/ingestions/horizon-ingest/dist/index.js +22125 -0
  86. package/plugins/ingestions/horizon-ingest/plugin.json +1 -1
  87. package/plugins/ingestions/karakeep-local/dist/index.js +24204 -0
  88. package/plugins/ingestions/karakeep-local/plugin.json +1 -1
  89. package/plugins/ingestions/last30days-ingest/dist/index.js +22070 -0
  90. package/plugins/ingestions/last30days-ingest/plugin.json +1 -1
  91. package/plugins/ingestions/web-search/dist/index.js +24399 -0
  92. package/plugins/ingestions/web-search/plugin.json +1 -1
  93. package/plugins/kk/commands/image-extract.md +40 -0
  94. package/plugins/kk/commands/image-generate.md +32 -0
  95. package/plugins/kk/config.example.yaml +80 -0
  96. package/plugins/kk/plugin.json +1 -1
  97. package/plugins/kk/skills/image-authoring/SKILL.md +257 -0
  98. package/plugins/kk/skills/image-authoring/references/format-drafting.md +57 -0
  99. package/plugins/kk/skills/image-authoring/references/illustration-positions.md +87 -0
  100. package/plugins/kk/skills/image-authoring/references/migrating-from-wt.md +31 -0
  101. package/plugins/kk/skills/image-authoring/references/providers.md +52 -0
  102. package/plugins/kk/skills/image-authoring/references/style-extraction.md +139 -0
  103. package/plugins/kk/workflows/kk-daily-ai-voice.yaml +130 -30
  104. package/plugins/publishings/emdash-pub/dist/index.js +22263 -0
  105. package/plugins/publishings/emdash-pub/plugin.json +1 -1
  106. package/plugins/publishings/podcast-pub/dist/index.js +22650 -0
  107. package/plugins/publishings/podcast-pub/plugin.json +8 -2
  108. package/plugins/publishings/podcast-pub/src/index.ts +18 -2
  109. package/plugins/publishings/podcast-pub/src/show-notes.ts +56 -9
  110. package/plugins/publishings/qiita-pub/dist/index.js +22101 -0
  111. package/plugins/publishings/qiita-pub/plugin.json +1 -1
  112. package/plugins/publishings/surfdash-pub/dist/index.js +22323 -0
  113. package/plugins/publishings/surfdash-pub/plugin.json +1 -1
  114. package/plugins/publishings/surfdash-pub/src/index.ts +109 -9
  115. package/plugins/publishings/zenn-pub/dist/index.js +22142 -0
  116. package/plugins/publishings/zenn-pub/plugin.json +1 -1
  117. package/plugins/sp/scripts/batch-preflight.mjs +346 -0
  118. package/plugins/sp/scripts/batch-preflight.ts +459 -0
  119. package/plugins/sp/scripts/daily-summary/daily-summary.mjs +615 -0
  120. package/plugins/sp/scripts/daily-summary/daily-summary.ts +846 -0
  121. package/plugins/sp/scripts/daily-summary/logger.ts +28 -0
  122. package/plugins/sp/scripts/dogfood-testing/detect-pipeline-driving.mjs +223 -0
  123. package/plugins/sp/scripts/dogfood-testing/detect-pipeline-driving.ts +367 -0
  124. package/plugins/sp/scripts/dogfood-testing/validate-report.mjs +132 -0
  125. package/plugins/sp/scripts/dogfood-testing/validate-report.ts +169 -0
  126. package/plugins/sp/scripts/feature-dev-precheck.mjs +171 -0
  127. package/plugins/sp/scripts/feature-dev-precheck.ts +238 -0
  128. package/plugins/sp/scripts/feature-sync-bounded.mjs +285 -0
  129. package/plugins/sp/scripts/feature-sync-bounded.ts +478 -0
  130. package/plugins/sp/scripts/history-anatomy-cache.mjs +902 -0
  131. package/plugins/sp/scripts/history-anatomy-cache.ts +1028 -0
  132. package/plugins/sp/scripts/idea-handoff.mjs +22 -0
  133. package/plugins/sp/scripts/idea-handoff.ts +44 -0
  134. package/plugins/sp/scripts/inline-pipeline-parity-check.ts +185 -0
  135. package/plugins/sp/scripts/inline-run-setup.ts +198 -0
  136. package/plugins/sp/scripts/pr-reviewing.mjs +769 -0
  137. package/plugins/sp/scripts/pr-reviewing.ts +925 -0
  138. package/plugins/sp/scripts/quality-gate.mjs +179 -0
  139. package/plugins/sp/scripts/quality-gate.ts +217 -0
  140. package/plugins/sp/scripts/script-contract-check.ts +319 -0
  141. package/plugins/sp/scripts/stage-registry-adapter.ts +1533 -0
  142. package/plugins/sp/scripts/surface-drift-inventory.ts +929 -0
  143. package/plugins/sp/scripts/task-evidence-precheck.ts +181 -0
  144. package/plugins/sp/scripts/task-size-precheck.ts +175 -0
  145. package/plugins/sp/scripts/transition-shim-check.ts +238 -0
  146. package/plugins/sp/scripts/validate-commands.ts +689 -0
  147. package/plugins/sp/scripts/validate-flag-contracts.ts +878 -0
  148. package/plugins/sp/scripts/verify-answer-lint.ts +530 -0
  149. package/plugins/sp/scripts/workflow-step-profile.mjs +316 -0
  150. package/plugins/sp/scripts/workflow-step-profile.ts +456 -0
  151. package/plugins/sp/scripts/wrapup-steps.mjs +373 -0
  152. package/plugins/sp/scripts/wrapup-steps.ts +466 -0
@@ -6,7 +6,7 @@
6
6
  },
7
7
  "plugins": [
8
8
  {
9
- "version": "0.0.1",
9
+ "version": "0.0.14",
10
10
  "name": "kk",
11
11
  "source": "./plugins/kk",
12
12
  "description": "knowledge-kit — a set of toolkit for knowledge management"
package/dist/index.js CHANGED
@@ -26054,6 +26054,26 @@ var ResultSchema = exports_external.object({
26054
26054
  metadata: exports_external.record(exports_external.string(), exports_external.unknown()).optional()
26055
26055
  });
26056
26056
  var DocListSchema = exports_external.array(DocSchema);
26057
+ var omniVoiceGenContentSchema = ContentSchema.extend({
26058
+ format: exports_external.literal("audio"),
26059
+ metadata: exports_external.looseObject({
26060
+ generator: exports_external.literal("kk:omni-voice-gen"),
26061
+ audioPath: exports_external.string(),
26062
+ duration: exports_external.number(),
26063
+ segments: exports_external.array(exports_external.looseObject({
26064
+ generationId: exports_external.string(),
26065
+ profile: exports_external.string(),
26066
+ speaker: exports_external.string().optional(),
26067
+ emotion: exports_external.string().optional(),
26068
+ duration: exports_external.number(),
26069
+ verifyRetries: exports_external.number(),
26070
+ transcription: exports_external.string().optional(),
26071
+ loudnessDip: exports_external.boolean().optional()
26072
+ })),
26073
+ mp3Path: exports_external.string().optional(),
26074
+ qc: exports_external.record(exports_external.string(), exports_external.unknown()).optional()
26075
+ })
26076
+ });
26057
26077
 
26058
26078
  // ../../packages/kk-core/src/kinds.ts
26059
26079
  var PLUGIN_KINDS = ["ingestion", "generator", "publish"];
@@ -26081,7 +26101,7 @@ function kindForCollection(name) {
26081
26101
  var CONTRACTS = {
26082
26102
  ingestion: { kind: "ingestion", input: null, output: DocListSchema },
26083
26103
  generator: { kind: "generator", input: DocListSchema, output: ContentSchema },
26084
- publish: { kind: "publish", input: exports_external.union([ContentSchema, DocListSchema]), output: ResultSchema }
26104
+ publish: { kind: "publish", input: ContentSchema, output: ResultSchema }
26085
26105
  };
26086
26106
  function kindContract(kind) {
26087
26107
  if (!isPluginKind(kind)) {
@@ -26094,12 +26114,14 @@ function isPluginKind(value) {
26094
26114
  }
26095
26115
  // ../../packages/kk-core/src/manifest.ts
26096
26116
  init_zod();
26117
+ var OperationIOSchema = exports_external.enum(["doc-list", "markdown"]);
26097
26118
  var PluginManifestSchema = exports_external.object({
26098
26119
  name: exports_external.string().min(1),
26099
26120
  kind: PluginKindSchema,
26100
26121
  entry: exports_external.string().min(1),
26101
26122
  version: exports_external.string().optional(),
26102
- description: exports_external.string().optional()
26123
+ description: exports_external.string().optional(),
26124
+ operations: exports_external.record(exports_external.string(), exports_external.object({ input: OperationIOSchema, output: OperationIOSchema })).optional()
26103
26125
  }).passthrough();
26104
26126
  // ../../packages/kk-core/src/registry.ts
26105
26127
  import { existsSync, readdirSync, readFileSync, realpathSync, statSync } from "fs";
@@ -26153,7 +26175,7 @@ function resolvePluginRoots(opts = {}) {
26153
26175
  if (builtinRoot !== undefined) {
26154
26176
  roots.push({ origin: "builtin", root: builtinRoot });
26155
26177
  }
26156
- const userRoot = join(opts.homeDir ?? homedir(), ".kk", "plugins");
26178
+ const userRoot = join(opts.homeDir ?? homedir(), ".config", "kk", "plugins");
26157
26179
  if (isDirectory(userRoot)) {
26158
26180
  roots.push({ origin: "user", root: userRoot });
26159
26181
  }
@@ -26331,7 +26353,8 @@ function consumeManifest(dirPath, expectedKind, origin, plugins, diagnostics, se
26331
26353
  manifestPath,
26332
26354
  origin,
26333
26355
  version: manifest.version,
26334
- description: manifest.description
26356
+ description: manifest.description,
26357
+ ...manifest.operations !== undefined ? { operations: manifest.operations } : {}
26335
26358
  });
26336
26359
  }
26337
26360
  function listSortedDir(absDir) {
@@ -26368,7 +26391,7 @@ if (false) {}
26368
26391
  init_dist();
26369
26392
 
26370
26393
  // src/invoke.ts
26371
- import { existsSync as existsSync3, readFileSync as readFileSync3, statSync as statSync3 } from "fs";
26394
+ import { existsSync as existsSync3, readFileSync as readFileSync3, statSync as statSync3, unlinkSync } from "fs";
26372
26395
  import { homedir as homedir2 } from "os";
26373
26396
  import { isAbsolute, join as join2, resolve as resolve2 } from "path";
26374
26397
  init_dist();
@@ -26448,21 +26471,44 @@ function spawnPluginEntry(opts) {
26448
26471
  stderr: proc.stderr.toString().trim()
26449
26472
  };
26450
26473
  }
26474
+ function killProcessTree(pid) {
26475
+ let stdout;
26476
+ try {
26477
+ stdout = Bun.spawnSync(["pgrep", "-P", String(pid)]).stdout.toString();
26478
+ } catch {
26479
+ stdout = "";
26480
+ }
26481
+ for (const line of stdout.trim().split(`
26482
+ `)) {
26483
+ const child = Number(line);
26484
+ if (Number.isInteger(child) && child > 0) {
26485
+ killProcessTree(child);
26486
+ }
26487
+ }
26488
+ try {
26489
+ process.kill(pid, "SIGKILL");
26490
+ } catch {}
26491
+ }
26451
26492
  async function spawnPluginEntryAsync(opts) {
26452
- const signal = opts.timeoutMs === undefined ? undefined : AbortSignal.timeout(opts.timeoutMs);
26453
26493
  let timedOut = false;
26454
- signal?.addEventListener("abort", () => {
26455
- timedOut = true;
26456
- });
26494
+ let timer;
26457
26495
  const proc = Bun.spawn(pluginEntryCmd(opts), {
26458
26496
  cwd: opts.cwd,
26459
26497
  env: pluginEntryEnv(opts),
26460
26498
  stdout: "pipe",
26461
- stderr: "pipe",
26462
- signal
26499
+ stderr: "pipe"
26463
26500
  });
26501
+ if (opts.timeoutMs !== undefined) {
26502
+ timer = setTimeout(() => {
26503
+ timedOut = true;
26504
+ killProcessTree(proc.pid);
26505
+ }, opts.timeoutMs);
26506
+ }
26464
26507
  const [stdout, stderr] = await Promise.all([new Response(proc.stdout).text(), new Response(proc.stderr).text()]);
26465
26508
  await proc.exited;
26509
+ if (timer !== undefined) {
26510
+ clearTimeout(timer);
26511
+ }
26466
26512
  return {
26467
26513
  exitCode: proc.exitCode === null ? 1 : proc.exitCode,
26468
26514
  stdout: stdout.trim(),
@@ -26485,7 +26531,11 @@ async function runInvoke(opts) {
26485
26531
  const contract = kindContract(record2.kind);
26486
26532
  const absInPath = resolve2(opts.inPath);
26487
26533
  const absOutPath = resolve2(opts.outPath);
26488
- let showNotesArrayInput = false;
26534
+ if (existsSync3(absInPath) && absInPath === absOutPath) {
26535
+ echoError(`--in and --out alias the same path (${absInPath}); refusing to overwrite the input`);
26536
+ return 1;
26537
+ }
26538
+ let artifactOutput = false;
26489
26539
  if (contract.input !== null) {
26490
26540
  if (!existsSync3(absInPath)) {
26491
26541
  echoError(`Input file does not exist: ${absInPath}`);
@@ -26505,13 +26555,27 @@ async function runInvoke(opts) {
26505
26555
  echoError(`Input file ${absInPath} is invalid JSON: ${err instanceof Error ? err.message : String(err)}`);
26506
26556
  return 1;
26507
26557
  }
26508
- const parseResult = contract.input.safeParse(json2);
26509
- if (!parseResult.success) {
26510
- const issues = parseResult.error.issues.map((i) => `${i.path.join(".") || "root"}: ${i.message}`).join("; ");
26511
- echoError(`Input schema violation for kind '${record2.kind}': ${issues}`);
26512
- return 1;
26558
+ if (record2.kind === "publish" && Array.isArray(json2)) {
26559
+ const op = Object.values(record2.operations ?? {}).find((o) => o.input === "doc-list");
26560
+ if (!op) {
26561
+ echoError(`Publish plugin '${record2.name}' received a Doc[] array but declares no doc-list operation; a Content object is required`);
26562
+ return 1;
26563
+ }
26564
+ const docs = DocListSchema.safeParse(json2);
26565
+ if (!docs.success) {
26566
+ const issues = docs.error.issues.map((i) => `${i.path.join(".") || "root"}: ${i.message}`).join("; ");
26567
+ echoError(`Input schema violation for the declared doc-list operation of '${record2.name}': ${issues}`);
26568
+ return 1;
26569
+ }
26570
+ artifactOutput = op.output === "markdown";
26571
+ } else {
26572
+ const parseResult = contract.input.safeParse(json2);
26573
+ if (!parseResult.success) {
26574
+ const issues = parseResult.error.issues.map((i) => `${i.path.join(".") || "root"}: ${i.message}`).join("; ");
26575
+ echoError(`Input schema violation for kind '${record2.kind}': ${issues}`);
26576
+ return 1;
26577
+ }
26513
26578
  }
26514
- showNotesArrayInput = record2.kind === "publish" && Array.isArray(json2);
26515
26579
  } else {
26516
26580
  if (!existsSync3(absInPath)) {
26517
26581
  echoError(`Source path does not exist: ${absInPath}`);
@@ -26523,6 +26587,14 @@ async function runInvoke(opts) {
26523
26587
  echoError(`Plugin entry script does not exist: ${entryPath}`);
26524
26588
  return 1;
26525
26589
  }
26590
+ if (existsSync3(absOutPath)) {
26591
+ try {
26592
+ unlinkSync(absOutPath);
26593
+ } catch (err) {
26594
+ echoError(`Failed to clear stale output ${absOutPath}: ${err instanceof Error ? err.message : String(err)}`);
26595
+ return 1;
26596
+ }
26597
+ }
26526
26598
  const proc = spawnPluginEntry({
26527
26599
  entryPath,
26528
26600
  cwd: record2.dir,
@@ -26541,7 +26613,7 @@ async function runInvoke(opts) {
26541
26613
  echoError(`Plugin entry succeeded but did not write output file: ${absOutPath}`);
26542
26614
  return 1;
26543
26615
  }
26544
- if (showNotesArrayInput) {
26616
+ if (artifactOutput) {
26545
26617
  if (statSync3(absOutPath).size === 0) {
26546
26618
  echoError(`Plugin entry succeeded but wrote an empty output file: ${absOutPath}`);
26547
26619
  return 1;
@@ -26568,6 +26640,12 @@ async function runInvoke(opts) {
26568
26640
  echoError(`Output schema violation for kind '${record2.kind}': ${issues}`);
26569
26641
  return 1;
26570
26642
  }
26643
+ const parsed = outResult.data;
26644
+ if (record2.kind === "publish" && parsed.ok === false) {
26645
+ const reason = parsed.error ?? parsed.message ?? "publish failed";
26646
+ echoError(`Plugin '${record2.name}' reported failure: ${reason}`);
26647
+ return 1;
26648
+ }
26571
26649
  return 0;
26572
26650
  }
26573
26651
 
@@ -26912,9 +26990,6 @@ async function fanout(content, targets, dispatch) {
26912
26990
  }
26913
26991
  return aggregate(entries);
26914
26992
  }
26915
- function selectRetryTargets(prior) {
26916
- return prior.targets.filter((t) => t.status === "failed").map((t) => t.target);
26917
- }
26918
26993
  async function readContent(fs2, path3) {
26919
26994
  if (!await fs2.exists(path3)) {
26920
26995
  echoError(`Content file does not exist: ${path3}`);
@@ -26989,6 +27064,14 @@ async function readAggregateResult(fs2, path3) {
26989
27064
  echoError(`Result file ${path3} violates the aggregate result schema (target ${String(t.target)})`);
26990
27065
  return null;
26991
27066
  }
27067
+ let metadata;
27068
+ if (t.metadata !== undefined) {
27069
+ if (typeof t.metadata !== "object" || t.metadata === null || Array.isArray(t.metadata)) {
27070
+ echoError(`Result file ${path3} violates the aggregate result schema: target '${String(t.target)}' metadata must be an object`);
27071
+ return null;
27072
+ }
27073
+ metadata = t.metadata;
27074
+ }
26992
27075
  targets.push({
26993
27076
  target: t.target,
26994
27077
  ok: t.ok,
@@ -26996,7 +27079,8 @@ async function readAggregateResult(fs2, path3) {
26996
27079
  ...typeof t.url === "string" ? { url: t.url } : {},
26997
27080
  ...typeof t.id === "string" ? { id: t.id } : {},
26998
27081
  ...typeof t.error === "string" ? { error: t.error } : {},
26999
- ...typeof t.durationMs === "number" ? { durationMs: t.durationMs } : {}
27082
+ ...typeof t.durationMs === "number" ? { durationMs: t.durationMs } : {},
27083
+ ...metadata !== undefined ? { metadata } : {}
27000
27084
  });
27001
27085
  }
27002
27086
  return {
@@ -27164,6 +27248,7 @@ async function runFanout(argv, deps = {}) {
27164
27248
  let prior;
27165
27249
  let skipped = [];
27166
27250
  let targets = opts.targets;
27251
+ let retainedFailed = [];
27167
27252
  if (opts.retryFromPath !== undefined) {
27168
27253
  const parsed = await readAggregateResult(fs2, opts.retryFromPath);
27169
27254
  if (parsed === null) {
@@ -27175,17 +27260,26 @@ async function runFanout(argv, deps = {}) {
27175
27260
  ok: true,
27176
27261
  status: "skipped",
27177
27262
  ...t.url !== undefined ? { url: t.url } : {},
27178
- ...t.id !== undefined ? { id: t.id } : {}
27263
+ ...t.id !== undefined ? { id: t.id } : {},
27264
+ ...t.metadata !== undefined ? { metadata: t.metadata } : {}
27179
27265
  }));
27180
27266
  const carried = new Set(skipped.map((t) => t.target));
27181
- targets = opts.targets.length > 0 ? opts.targets.filter((t) => !carried.has(t)) : selectRetryTargets(prior);
27267
+ const priorFailed = prior.targets.filter((t) => t.status === "failed");
27268
+ if (opts.targets.length > 0) {
27269
+ const attempt = [...new Set(opts.targets.filter((t) => !carried.has(t)))];
27270
+ const attemptSet = new Set(attempt);
27271
+ targets = attempt;
27272
+ retainedFailed = priorFailed.filter((t) => !attemptSet.has(t.target));
27273
+ } else {
27274
+ targets = priorFailed.map((t) => t.target);
27275
+ }
27182
27276
  }
27183
27277
  const dispatch = deps.dispatch ?? ((t) => pluginDispatch(t, opts.contentPath, discovery));
27184
27278
  if (deps.dispatch === undefined && !validateTargets(targets, discovery)) {
27185
27279
  return EXIT_INPUT2;
27186
27280
  }
27187
27281
  const fresh = await fanout(content, targets, dispatch);
27188
- const result = prior !== undefined ? aggregate([...skipped, ...fresh.targets]) : fresh;
27282
+ const result = prior !== undefined ? aggregate([...skipped, ...retainedFailed, ...fresh.targets]) : fresh;
27189
27283
  try {
27190
27284
  await fs2.writeFile(resolve4(opts.outPath), `${JSON.stringify(result, null, 2)}
27191
27285
  `);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gobing-ai/knowledge-kit",
3
- "version": "0.0.12",
3
+ "version": "0.0.14",
4
4
  "description": "An ingest → create → publish content pipeline CLI (Bun).",
5
5
  "repository": {
6
6
  "type": "git",