@gobing-ai/knowledge-kit 0.0.12 → 0.0.13

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 (66) hide show
  1. package/dist/index.js +100 -26
  2. package/package.json +1 -1
  3. package/plugins/generations/content-gen/dist/index.js +22167 -0
  4. package/plugins/generations/content-gen/plugin.json +1 -1
  5. package/plugins/generations/core-facts-gen/dist/index.js +22048 -0
  6. package/plugins/generations/core-facts-gen/plugin.json +1 -1
  7. package/plugins/generations/daily-article-gen/dist/index.js +22022 -0
  8. package/plugins/generations/daily-article-gen/plugin.json +1 -1
  9. package/plugins/generations/dailynews-gen/dist/index.js +22324 -0
  10. package/plugins/generations/dailynews-gen/plugin.json +1 -1
  11. package/plugins/generations/episode-plan-gen/dist/index.js +22479 -0
  12. package/plugins/generations/episode-plan-gen/plugin.json +1 -1
  13. package/plugins/generations/image-gen/config.example.yaml +75 -0
  14. package/plugins/generations/image-gen/dist/index.js +22619 -0
  15. package/plugins/generations/image-gen/package.json +17 -0
  16. package/plugins/generations/image-gen/plugin.json +7 -0
  17. package/plugins/generations/image-gen/presets/formats/cover.yaml +57 -0
  18. package/plugins/generations/image-gen/presets/formats/free.yaml +46 -0
  19. package/plugins/generations/image-gen/presets/formats/illustration.yaml +48 -0
  20. package/plugins/generations/image-gen/presets/styles/clean-webapp-ui.yaml +28 -0
  21. package/plugins/generations/image-gen/presets/styles/cute.yaml +3 -0
  22. package/plugins/generations/image-gen/presets/styles/editorial.yaml +3 -0
  23. package/plugins/generations/image-gen/presets/styles/fresh.yaml +3 -0
  24. package/plugins/generations/image-gen/presets/styles/minimalist.yaml +3 -0
  25. package/plugins/generations/image-gen/presets/styles/photorealistic.yaml +3 -0
  26. package/plugins/generations/image-gen/presets/styles/sketch.yaml +3 -0
  27. package/plugins/generations/image-gen/presets/styles/technical-diagram.yaml +3 -0
  28. package/plugins/generations/image-gen/presets/styles/vibrant.yaml +3 -0
  29. package/plugins/generations/image-gen/presets/styles/warm.yaml +3 -0
  30. package/plugins/generations/image-gen/src/bytes.ts +19 -0
  31. package/plugins/generations/image-gen/src/index.ts +319 -0
  32. package/plugins/generations/image-gen/src/job.ts +143 -0
  33. package/plugins/generations/image-gen/src/paths.ts +31 -0
  34. package/plugins/generations/image-gen/src/presets.ts +344 -0
  35. package/plugins/generations/image-gen/src/providers/seedream.ts +128 -0
  36. package/plugins/generations/image-gen/src/providers/types.ts +285 -0
  37. package/plugins/generations/image-gen/tsconfig.json +8 -0
  38. package/plugins/generations/voice-gen/dist/index.js +23027 -0
  39. package/plugins/generations/voice-gen/plugin.json +1 -1
  40. package/plugins/ingestions/aihot-ingest/dist/index.js +22358 -0
  41. package/plugins/ingestions/aihot-ingest/plugin.json +1 -1
  42. package/plugins/ingestions/horizon-ingest/dist/index.js +22105 -0
  43. package/plugins/ingestions/horizon-ingest/plugin.json +1 -1
  44. package/plugins/ingestions/karakeep-local/dist/index.js +24204 -0
  45. package/plugins/ingestions/karakeep-local/plugin.json +1 -1
  46. package/plugins/ingestions/last30days-ingest/dist/index.js +22050 -0
  47. package/plugins/ingestions/last30days-ingest/plugin.json +1 -1
  48. package/plugins/ingestions/web-search/dist/index.js +24379 -0
  49. package/plugins/ingestions/web-search/plugin.json +1 -1
  50. package/plugins/kk/commands/image-generate.md +15 -0
  51. package/plugins/kk/config.example.yaml +80 -0
  52. package/plugins/kk/skills/image-authoring/SKILL.md +250 -0
  53. package/plugins/kk/skills/image-authoring/references/illustration-positions.md +87 -0
  54. package/plugins/kk/skills/image-authoring/references/migrating-from-wt.md +31 -0
  55. package/plugins/kk/skills/image-authoring/references/providers.md +52 -0
  56. package/plugins/kk/skills/image-authoring/references/style-extraction.md +134 -0
  57. package/plugins/publishings/emdash-pub/dist/index.js +22243 -0
  58. package/plugins/publishings/emdash-pub/plugin.json +1 -1
  59. package/plugins/publishings/podcast-pub/dist/index.js +22596 -0
  60. package/plugins/publishings/podcast-pub/plugin.json +8 -2
  61. package/plugins/publishings/qiita-pub/dist/index.js +22081 -0
  62. package/plugins/publishings/qiita-pub/plugin.json +1 -1
  63. package/plugins/publishings/surfdash-pub/dist/index.js +22233 -0
  64. package/plugins/publishings/surfdash-pub/plugin.json +1 -1
  65. package/plugins/publishings/zenn-pub/dist/index.js +22122 -0
  66. package/plugins/publishings/zenn-pub/plugin.json +1 -1
package/dist/index.js CHANGED
@@ -26081,7 +26081,7 @@ function kindForCollection(name) {
26081
26081
  var CONTRACTS = {
26082
26082
  ingestion: { kind: "ingestion", input: null, output: DocListSchema },
26083
26083
  generator: { kind: "generator", input: DocListSchema, output: ContentSchema },
26084
- publish: { kind: "publish", input: exports_external.union([ContentSchema, DocListSchema]), output: ResultSchema }
26084
+ publish: { kind: "publish", input: ContentSchema, output: ResultSchema }
26085
26085
  };
26086
26086
  function kindContract(kind) {
26087
26087
  if (!isPluginKind(kind)) {
@@ -26094,12 +26094,14 @@ function isPluginKind(value) {
26094
26094
  }
26095
26095
  // ../../packages/kk-core/src/manifest.ts
26096
26096
  init_zod();
26097
+ var OperationIOSchema = exports_external.enum(["doc-list", "markdown"]);
26097
26098
  var PluginManifestSchema = exports_external.object({
26098
26099
  name: exports_external.string().min(1),
26099
26100
  kind: PluginKindSchema,
26100
26101
  entry: exports_external.string().min(1),
26101
26102
  version: exports_external.string().optional(),
26102
- description: exports_external.string().optional()
26103
+ description: exports_external.string().optional(),
26104
+ operations: exports_external.record(exports_external.string(), exports_external.object({ input: OperationIOSchema, output: OperationIOSchema })).optional()
26103
26105
  }).passthrough();
26104
26106
  // ../../packages/kk-core/src/registry.ts
26105
26107
  import { existsSync, readdirSync, readFileSync, realpathSync, statSync } from "fs";
@@ -26153,7 +26155,7 @@ function resolvePluginRoots(opts = {}) {
26153
26155
  if (builtinRoot !== undefined) {
26154
26156
  roots.push({ origin: "builtin", root: builtinRoot });
26155
26157
  }
26156
- const userRoot = join(opts.homeDir ?? homedir(), ".kk", "plugins");
26158
+ const userRoot = join(opts.homeDir ?? homedir(), ".config", "kk", "plugins");
26157
26159
  if (isDirectory(userRoot)) {
26158
26160
  roots.push({ origin: "user", root: userRoot });
26159
26161
  }
@@ -26331,7 +26333,8 @@ function consumeManifest(dirPath, expectedKind, origin, plugins, diagnostics, se
26331
26333
  manifestPath,
26332
26334
  origin,
26333
26335
  version: manifest.version,
26334
- description: manifest.description
26336
+ description: manifest.description,
26337
+ ...manifest.operations !== undefined ? { operations: manifest.operations } : {}
26335
26338
  });
26336
26339
  }
26337
26340
  function listSortedDir(absDir) {
@@ -26368,7 +26371,7 @@ if (false) {}
26368
26371
  init_dist();
26369
26372
 
26370
26373
  // src/invoke.ts
26371
- import { existsSync as existsSync3, readFileSync as readFileSync3, statSync as statSync3 } from "fs";
26374
+ import { existsSync as existsSync3, readFileSync as readFileSync3, statSync as statSync3, unlinkSync } from "fs";
26372
26375
  import { homedir as homedir2 } from "os";
26373
26376
  import { isAbsolute, join as join2, resolve as resolve2 } from "path";
26374
26377
  init_dist();
@@ -26448,21 +26451,44 @@ function spawnPluginEntry(opts) {
26448
26451
  stderr: proc.stderr.toString().trim()
26449
26452
  };
26450
26453
  }
26454
+ function killProcessTree(pid) {
26455
+ let stdout;
26456
+ try {
26457
+ stdout = Bun.spawnSync(["pgrep", "-P", String(pid)]).stdout.toString();
26458
+ } catch {
26459
+ stdout = "";
26460
+ }
26461
+ for (const line of stdout.trim().split(`
26462
+ `)) {
26463
+ const child = Number(line);
26464
+ if (Number.isInteger(child) && child > 0) {
26465
+ killProcessTree(child);
26466
+ }
26467
+ }
26468
+ try {
26469
+ process.kill(pid, "SIGKILL");
26470
+ } catch {}
26471
+ }
26451
26472
  async function spawnPluginEntryAsync(opts) {
26452
- const signal = opts.timeoutMs === undefined ? undefined : AbortSignal.timeout(opts.timeoutMs);
26453
26473
  let timedOut = false;
26454
- signal?.addEventListener("abort", () => {
26455
- timedOut = true;
26456
- });
26474
+ let timer;
26457
26475
  const proc = Bun.spawn(pluginEntryCmd(opts), {
26458
26476
  cwd: opts.cwd,
26459
26477
  env: pluginEntryEnv(opts),
26460
26478
  stdout: "pipe",
26461
- stderr: "pipe",
26462
- signal
26479
+ stderr: "pipe"
26463
26480
  });
26481
+ if (opts.timeoutMs !== undefined) {
26482
+ timer = setTimeout(() => {
26483
+ timedOut = true;
26484
+ killProcessTree(proc.pid);
26485
+ }, opts.timeoutMs);
26486
+ }
26464
26487
  const [stdout, stderr] = await Promise.all([new Response(proc.stdout).text(), new Response(proc.stderr).text()]);
26465
26488
  await proc.exited;
26489
+ if (timer !== undefined) {
26490
+ clearTimeout(timer);
26491
+ }
26466
26492
  return {
26467
26493
  exitCode: proc.exitCode === null ? 1 : proc.exitCode,
26468
26494
  stdout: stdout.trim(),
@@ -26485,7 +26511,11 @@ async function runInvoke(opts) {
26485
26511
  const contract = kindContract(record2.kind);
26486
26512
  const absInPath = resolve2(opts.inPath);
26487
26513
  const absOutPath = resolve2(opts.outPath);
26488
- let showNotesArrayInput = false;
26514
+ if (existsSync3(absInPath) && absInPath === absOutPath) {
26515
+ echoError(`--in and --out alias the same path (${absInPath}); refusing to overwrite the input`);
26516
+ return 1;
26517
+ }
26518
+ let artifactOutput = false;
26489
26519
  if (contract.input !== null) {
26490
26520
  if (!existsSync3(absInPath)) {
26491
26521
  echoError(`Input file does not exist: ${absInPath}`);
@@ -26505,13 +26535,27 @@ async function runInvoke(opts) {
26505
26535
  echoError(`Input file ${absInPath} is invalid JSON: ${err instanceof Error ? err.message : String(err)}`);
26506
26536
  return 1;
26507
26537
  }
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;
26538
+ if (record2.kind === "publish" && Array.isArray(json2)) {
26539
+ const op = Object.values(record2.operations ?? {}).find((o) => o.input === "doc-list");
26540
+ if (!op) {
26541
+ echoError(`Publish plugin '${record2.name}' received a Doc[] array but declares no doc-list operation; a Content object is required`);
26542
+ return 1;
26543
+ }
26544
+ const docs = DocListSchema.safeParse(json2);
26545
+ if (!docs.success) {
26546
+ const issues = docs.error.issues.map((i) => `${i.path.join(".") || "root"}: ${i.message}`).join("; ");
26547
+ echoError(`Input schema violation for the declared doc-list operation of '${record2.name}': ${issues}`);
26548
+ return 1;
26549
+ }
26550
+ artifactOutput = op.output === "markdown";
26551
+ } else {
26552
+ const parseResult = contract.input.safeParse(json2);
26553
+ if (!parseResult.success) {
26554
+ const issues = parseResult.error.issues.map((i) => `${i.path.join(".") || "root"}: ${i.message}`).join("; ");
26555
+ echoError(`Input schema violation for kind '${record2.kind}': ${issues}`);
26556
+ return 1;
26557
+ }
26513
26558
  }
26514
- showNotesArrayInput = record2.kind === "publish" && Array.isArray(json2);
26515
26559
  } else {
26516
26560
  if (!existsSync3(absInPath)) {
26517
26561
  echoError(`Source path does not exist: ${absInPath}`);
@@ -26523,6 +26567,14 @@ async function runInvoke(opts) {
26523
26567
  echoError(`Plugin entry script does not exist: ${entryPath}`);
26524
26568
  return 1;
26525
26569
  }
26570
+ if (existsSync3(absOutPath)) {
26571
+ try {
26572
+ unlinkSync(absOutPath);
26573
+ } catch (err) {
26574
+ echoError(`Failed to clear stale output ${absOutPath}: ${err instanceof Error ? err.message : String(err)}`);
26575
+ return 1;
26576
+ }
26577
+ }
26526
26578
  const proc = spawnPluginEntry({
26527
26579
  entryPath,
26528
26580
  cwd: record2.dir,
@@ -26541,7 +26593,7 @@ async function runInvoke(opts) {
26541
26593
  echoError(`Plugin entry succeeded but did not write output file: ${absOutPath}`);
26542
26594
  return 1;
26543
26595
  }
26544
- if (showNotesArrayInput) {
26596
+ if (artifactOutput) {
26545
26597
  if (statSync3(absOutPath).size === 0) {
26546
26598
  echoError(`Plugin entry succeeded but wrote an empty output file: ${absOutPath}`);
26547
26599
  return 1;
@@ -26568,6 +26620,12 @@ async function runInvoke(opts) {
26568
26620
  echoError(`Output schema violation for kind '${record2.kind}': ${issues}`);
26569
26621
  return 1;
26570
26622
  }
26623
+ const parsed = outResult.data;
26624
+ if (record2.kind === "publish" && parsed.ok === false) {
26625
+ const reason = parsed.error ?? parsed.message ?? "publish failed";
26626
+ echoError(`Plugin '${record2.name}' reported failure: ${reason}`);
26627
+ return 1;
26628
+ }
26571
26629
  return 0;
26572
26630
  }
26573
26631
 
@@ -26912,9 +26970,6 @@ async function fanout(content, targets, dispatch) {
26912
26970
  }
26913
26971
  return aggregate(entries);
26914
26972
  }
26915
- function selectRetryTargets(prior) {
26916
- return prior.targets.filter((t) => t.status === "failed").map((t) => t.target);
26917
- }
26918
26973
  async function readContent(fs2, path3) {
26919
26974
  if (!await fs2.exists(path3)) {
26920
26975
  echoError(`Content file does not exist: ${path3}`);
@@ -26989,6 +27044,14 @@ async function readAggregateResult(fs2, path3) {
26989
27044
  echoError(`Result file ${path3} violates the aggregate result schema (target ${String(t.target)})`);
26990
27045
  return null;
26991
27046
  }
27047
+ let metadata;
27048
+ if (t.metadata !== undefined) {
27049
+ if (typeof t.metadata !== "object" || t.metadata === null || Array.isArray(t.metadata)) {
27050
+ echoError(`Result file ${path3} violates the aggregate result schema: target '${String(t.target)}' metadata must be an object`);
27051
+ return null;
27052
+ }
27053
+ metadata = t.metadata;
27054
+ }
26992
27055
  targets.push({
26993
27056
  target: t.target,
26994
27057
  ok: t.ok,
@@ -26996,7 +27059,8 @@ async function readAggregateResult(fs2, path3) {
26996
27059
  ...typeof t.url === "string" ? { url: t.url } : {},
26997
27060
  ...typeof t.id === "string" ? { id: t.id } : {},
26998
27061
  ...typeof t.error === "string" ? { error: t.error } : {},
26999
- ...typeof t.durationMs === "number" ? { durationMs: t.durationMs } : {}
27062
+ ...typeof t.durationMs === "number" ? { durationMs: t.durationMs } : {},
27063
+ ...metadata !== undefined ? { metadata } : {}
27000
27064
  });
27001
27065
  }
27002
27066
  return {
@@ -27164,6 +27228,7 @@ async function runFanout(argv, deps = {}) {
27164
27228
  let prior;
27165
27229
  let skipped = [];
27166
27230
  let targets = opts.targets;
27231
+ let retainedFailed = [];
27167
27232
  if (opts.retryFromPath !== undefined) {
27168
27233
  const parsed = await readAggregateResult(fs2, opts.retryFromPath);
27169
27234
  if (parsed === null) {
@@ -27175,17 +27240,26 @@ async function runFanout(argv, deps = {}) {
27175
27240
  ok: true,
27176
27241
  status: "skipped",
27177
27242
  ...t.url !== undefined ? { url: t.url } : {},
27178
- ...t.id !== undefined ? { id: t.id } : {}
27243
+ ...t.id !== undefined ? { id: t.id } : {},
27244
+ ...t.metadata !== undefined ? { metadata: t.metadata } : {}
27179
27245
  }));
27180
27246
  const carried = new Set(skipped.map((t) => t.target));
27181
- targets = opts.targets.length > 0 ? opts.targets.filter((t) => !carried.has(t)) : selectRetryTargets(prior);
27247
+ const priorFailed = prior.targets.filter((t) => t.status === "failed");
27248
+ if (opts.targets.length > 0) {
27249
+ const attempt = [...new Set(opts.targets.filter((t) => !carried.has(t)))];
27250
+ const attemptSet = new Set(attempt);
27251
+ targets = attempt;
27252
+ retainedFailed = priorFailed.filter((t) => !attemptSet.has(t.target));
27253
+ } else {
27254
+ targets = priorFailed.map((t) => t.target);
27255
+ }
27182
27256
  }
27183
27257
  const dispatch = deps.dispatch ?? ((t) => pluginDispatch(t, opts.contentPath, discovery));
27184
27258
  if (deps.dispatch === undefined && !validateTargets(targets, discovery)) {
27185
27259
  return EXIT_INPUT2;
27186
27260
  }
27187
27261
  const fresh = await fanout(content, targets, dispatch);
27188
- const result = prior !== undefined ? aggregate([...skipped, ...fresh.targets]) : fresh;
27262
+ const result = prior !== undefined ? aggregate([...skipped, ...retainedFailed, ...fresh.targets]) : fresh;
27189
27263
  try {
27190
27264
  await fs2.writeFile(resolve4(opts.outPath), `${JSON.stringify(result, null, 2)}
27191
27265
  `);
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.13",
4
4
  "description": "An ingest → create → publish content pipeline CLI (Bun).",
5
5
  "repository": {
6
6
  "type": "git",