@gobing-ai/knowledge-kit 0.0.11 → 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 (99) hide show
  1. package/dist/index.js +451 -152
  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/content-gen/src/storm.ts +99 -50
  6. package/plugins/generations/core-facts-gen/dist/index.js +22048 -0
  7. package/plugins/generations/core-facts-gen/package.json +17 -0
  8. package/plugins/generations/core-facts-gen/plugin.json +7 -0
  9. package/plugins/generations/core-facts-gen/src/index.ts +116 -0
  10. package/plugins/generations/core-facts-gen/tsconfig.json +4 -0
  11. package/plugins/generations/daily-article-gen/dist/index.js +22022 -0
  12. package/plugins/generations/daily-article-gen/package.json +17 -0
  13. package/plugins/generations/daily-article-gen/plugin.json +7 -0
  14. package/plugins/generations/daily-article-gen/src/index.ts +91 -0
  15. package/plugins/generations/daily-article-gen/tsconfig.json +4 -0
  16. package/plugins/generations/dailynews-gen/dist/index.js +22324 -0
  17. package/plugins/generations/dailynews-gen/plugin.json +1 -1
  18. package/plugins/generations/dailynews-gen/src/index.ts +11 -0
  19. package/plugins/generations/dailynews-gen/src/script-builder.ts +1 -1
  20. package/plugins/generations/episode-plan-gen/dist/index.js +22479 -0
  21. package/plugins/generations/episode-plan-gen/package.json +17 -0
  22. package/plugins/generations/episode-plan-gen/plugin.json +7 -0
  23. package/plugins/generations/episode-plan-gen/src/index.ts +726 -0
  24. package/plugins/generations/episode-plan-gen/tsconfig.json +4 -0
  25. package/plugins/generations/image-gen/config.example.yaml +75 -0
  26. package/plugins/generations/image-gen/dist/index.js +22619 -0
  27. package/plugins/generations/image-gen/package.json +17 -0
  28. package/plugins/generations/image-gen/plugin.json +7 -0
  29. package/plugins/generations/image-gen/presets/formats/cover.yaml +57 -0
  30. package/plugins/generations/image-gen/presets/formats/free.yaml +46 -0
  31. package/plugins/generations/image-gen/presets/formats/illustration.yaml +48 -0
  32. package/plugins/generations/image-gen/presets/styles/clean-webapp-ui.yaml +28 -0
  33. package/plugins/generations/image-gen/presets/styles/cute.yaml +3 -0
  34. package/plugins/generations/image-gen/presets/styles/editorial.yaml +3 -0
  35. package/plugins/generations/image-gen/presets/styles/fresh.yaml +3 -0
  36. package/plugins/generations/image-gen/presets/styles/minimalist.yaml +3 -0
  37. package/plugins/generations/image-gen/presets/styles/photorealistic.yaml +3 -0
  38. package/plugins/generations/image-gen/presets/styles/sketch.yaml +3 -0
  39. package/plugins/generations/image-gen/presets/styles/technical-diagram.yaml +3 -0
  40. package/plugins/generations/image-gen/presets/styles/vibrant.yaml +3 -0
  41. package/plugins/generations/image-gen/presets/styles/warm.yaml +3 -0
  42. package/plugins/generations/image-gen/src/bytes.ts +19 -0
  43. package/plugins/generations/image-gen/src/index.ts +319 -0
  44. package/plugins/generations/image-gen/src/job.ts +143 -0
  45. package/plugins/generations/image-gen/src/paths.ts +31 -0
  46. package/plugins/generations/image-gen/src/presets.ts +344 -0
  47. package/plugins/generations/image-gen/src/providers/seedream.ts +128 -0
  48. package/plugins/generations/image-gen/src/providers/types.ts +285 -0
  49. package/plugins/generations/image-gen/tsconfig.json +8 -0
  50. package/plugins/generations/voice-gen/dist/index.js +23027 -0
  51. package/plugins/generations/voice-gen/plugin.json +1 -1
  52. package/plugins/generations/voice-gen/src/index.ts +102 -11
  53. package/plugins/generations/voice-gen/src/qc.ts +154 -9
  54. package/plugins/ingestions/aihot-ingest/dist/index.js +22358 -0
  55. package/plugins/ingestions/aihot-ingest/plugin.json +2 -2
  56. package/plugins/ingestions/aihot-ingest/src/index.ts +72 -13
  57. package/plugins/ingestions/aihot-ingest/src/mapper.ts +1 -0
  58. package/plugins/ingestions/aihot-ingest/src/rss.ts +151 -0
  59. package/plugins/ingestions/horizon-ingest/dist/index.js +22105 -0
  60. package/plugins/ingestions/horizon-ingest/package.json +17 -0
  61. package/plugins/ingestions/horizon-ingest/plugin.json +7 -0
  62. package/plugins/ingestions/horizon-ingest/src/index.ts +205 -0
  63. package/plugins/ingestions/horizon-ingest/tsconfig.json +4 -0
  64. package/plugins/ingestions/karakeep-local/dist/index.js +24204 -0
  65. package/plugins/ingestions/karakeep-local/plugin.json +1 -1
  66. package/plugins/ingestions/last30days-ingest/dist/index.js +22050 -0
  67. package/plugins/ingestions/last30days-ingest/package.json +17 -0
  68. package/plugins/ingestions/last30days-ingest/plugin.json +7 -0
  69. package/plugins/ingestions/last30days-ingest/src/index.ts +148 -0
  70. package/plugins/ingestions/last30days-ingest/tsconfig.json +4 -0
  71. package/plugins/ingestions/web-search/dist/index.js +24379 -0
  72. package/plugins/ingestions/web-search/plugin.json +1 -1
  73. package/plugins/kk/commands/image-generate.md +15 -0
  74. package/plugins/kk/config.example.yaml +80 -0
  75. package/plugins/kk/skills/image-authoring/SKILL.md +250 -0
  76. package/plugins/kk/skills/image-authoring/references/illustration-positions.md +87 -0
  77. package/plugins/kk/skills/image-authoring/references/migrating-from-wt.md +31 -0
  78. package/plugins/kk/skills/image-authoring/references/providers.md +52 -0
  79. package/plugins/kk/skills/image-authoring/references/style-extraction.md +134 -0
  80. package/plugins/kk/skills/taste-unslop/SKILL.md +12 -6
  81. package/plugins/kk/skills/taste-unslop/references/pattern-guide.md +128 -48
  82. package/plugins/kk/workflows/kk-daily-ai-voice.yaml +432 -19
  83. package/plugins/publishings/emdash-pub/dist/index.js +22243 -0
  84. package/plugins/publishings/emdash-pub/plugin.json +1 -1
  85. package/plugins/publishings/podcast-pub/dist/index.js +22596 -0
  86. package/plugins/publishings/podcast-pub/package.json +17 -0
  87. package/plugins/publishings/podcast-pub/plugin.json +13 -0
  88. package/plugins/publishings/podcast-pub/src/index.ts +538 -0
  89. package/plugins/publishings/podcast-pub/src/map.ts +165 -0
  90. package/plugins/publishings/podcast-pub/src/microfeed-client.ts +196 -0
  91. package/plugins/publishings/podcast-pub/src/show-notes.ts +132 -0
  92. package/plugins/publishings/podcast-pub/tsconfig.json +4 -0
  93. package/plugins/publishings/qiita-pub/dist/index.js +22081 -0
  94. package/plugins/publishings/qiita-pub/plugin.json +1 -1
  95. package/plugins/publishings/surfdash-pub/dist/index.js +22233 -0
  96. package/plugins/publishings/surfdash-pub/plugin.json +1 -1
  97. package/plugins/publishings/surfdash-pub/src/index.ts +328 -62
  98. package/plugins/publishings/zenn-pub/dist/index.js +22122 -0
  99. package/plugins/publishings/zenn-pub/plugin.json +1 -1
@@ -0,0 +1,17 @@
1
+ {
2
+ "name": "@gobing-ai/horizon-ingest",
3
+ "type": "module",
4
+ "private": true,
5
+ "scripts": {
6
+ "typecheck": "tsc --noEmit"
7
+ },
8
+ "dependencies": {
9
+ "@gobing-ai/kk-core": "workspace:*",
10
+ "@gobing-ai/ts-runtime": "catalog:",
11
+ "@gobing-ai/ts-utils": "catalog:",
12
+ "zod": "4.4.3"
13
+ },
14
+ "devDependencies": {
15
+ "@types/bun": "1.3.14"
16
+ }
17
+ }
@@ -0,0 +1,7 @@
1
+ {
2
+ "name": "horizon-ingest",
3
+ "kind": "ingestion",
4
+ "entry": "./dist/index.js",
5
+ "version": "1.0.0",
6
+ "description": "Wraps the Horizon CLI (uv run horizon) into Doc[] — one Doc per digest item block"
7
+ }
@@ -0,0 +1,205 @@
1
+ import { homedir } from 'node:os';
2
+ import { dirname, join } from 'node:path';
3
+ import { parseArgs } from 'node:util';
4
+ import { type Doc, DocListSchema } from '@gobing-ai/kk-core';
5
+ import { atomicWriteJson, createNodeFileSystem, readJsonFile } from '@gobing-ai/ts-runtime';
6
+ import { echoError } from '@gobing-ai/ts-utils';
7
+ import { z } from 'zod';
8
+
9
+ /**
10
+ * Ingestion adapter over the Horizon CLI (task 0089 contract).
11
+ * Runs `uv run horizon` (cwd = the Horizon repo), then parses the digest
12
+ * `<data-dir>/summaries/horizon-<date>-<lang>.md` written during this run —
13
+ * one Doc per `### [title](url)` item block.
14
+ */
15
+
16
+ const InputConfigSchema = z.object({
17
+ data_dir: z.string().trim().min(1).optional(),
18
+ config: z.string().trim().min(1).optional(),
19
+ hours: z.number().int().min(1).optional(),
20
+ languages: z.array(z.string().trim().min(1)).optional(),
21
+ horizon_dir: z.string().trim().min(1).optional(),
22
+ });
23
+
24
+ export interface HorizonRunResult {
25
+ exitCode: number;
26
+ stderr: string;
27
+ }
28
+
29
+ /** Subprocess seam — tests inject a fake that pre-seeds a summaries file. */
30
+ export type RunHorizon = (config: z.infer<typeof InputConfigSchema>, horizonDir: string) => Promise<HorizonRunResult>;
31
+
32
+ export const defaultRunner: RunHorizon = async (config, horizonDir) => {
33
+ const argv = [process.env.HORIZON_UV ?? 'uv', 'run', 'horizon'];
34
+ if (config.hours !== undefined) argv.push('--hours', String(config.hours));
35
+ if (config.data_dir !== undefined) argv.push('-d', config.data_dir);
36
+ if (config.config !== undefined) argv.push('-c', config.config);
37
+ const proc = Bun.spawnSync(argv, { cwd: horizonDir, stdout: 'pipe', stderr: 'pipe' });
38
+ return { exitCode: proc.exitCode ?? 1, stderr: proc.stderr.toString() };
39
+ };
40
+
41
+ const HEADING_RE = /^### \[(.+)\]\((.+)\) ⭐️ ([\d.]+)\/10\s*$/m;
42
+ const ANCHOR_RE = /<a id="item-([a-z0-9-]+)-(\d+)"><\/a>/;
43
+
44
+ interface ParsedItem {
45
+ anchorProfile: string;
46
+ anchorN: string;
47
+ title: string;
48
+ url: string;
49
+ score: number;
50
+ block: string;
51
+ }
52
+
53
+ /** Split a digest markdown file into per-item blocks keyed off the item anchors. */
54
+ export function splitItemBlocks(markdown: string): ParsedItem[] {
55
+ const items: ParsedItem[] = [];
56
+ const segments = markdown.split(/(?=<a id="item-)/);
57
+ for (const segment of segments) {
58
+ const anchor = segment.match(ANCHOR_RE);
59
+ const heading = segment.match(HEADING_RE);
60
+ if (!anchor || !heading) continue;
61
+ items.push({
62
+ anchorProfile: anchor[1] ?? '',
63
+ anchorN: anchor[2] ?? '',
64
+ title: heading[1] ?? '',
65
+ url: heading[2] ?? '',
66
+ score: Number(heading[3]),
67
+ block: segment,
68
+ });
69
+ }
70
+ return items;
71
+ }
72
+
73
+ /** Map one parsed item block to a Doc. */
74
+ export function itemToDoc(item: ParsedItem, date: string, lang: string): Doc {
75
+ const lines = item.block.split('\n');
76
+ const bodyParts: string[] = [];
77
+ const references: string[] = [];
78
+ let sourceLine = '';
79
+ let tags: string[] = [];
80
+ let inDetails = false;
81
+ for (const line of lines.slice(1)) {
82
+ if (line.startsWith('<details')) inDetails = true;
83
+ if (line.startsWith('</details>')) {
84
+ inDetails = false;
85
+ continue;
86
+ }
87
+ if (inDetails) {
88
+ const href = line.match(/<a href="([^"]+)"/);
89
+ if (href?.[1]) references.push(href[1]);
90
+ continue;
91
+ }
92
+ const tagMatch = line.match(/^\*\*Tags\*\*:\s*(.+)$/);
93
+ if (tagMatch?.[1]) {
94
+ tags = [...tagMatch[1].matchAll(/#([^`,\s]+)/g)].map((m) => m[1] ?? '');
95
+ continue;
96
+ }
97
+ if (/^---\s*$/.test(line)) continue;
98
+ if (/^[a-z0-9_-]+ · /i.test(line) && !sourceLine) {
99
+ sourceLine = line.trim();
100
+ continue;
101
+ }
102
+ if (line.trim()) bodyParts.push(line);
103
+ }
104
+ const doc: Doc = {
105
+ id: `horizon:${date}-${item.anchorProfile}-${item.anchorN}`,
106
+ title: item.title,
107
+ body: bodyParts.join('\n').trim(),
108
+ sourceUri: item.url,
109
+ mediaType: 'text/markdown',
110
+ metadata: {
111
+ lang,
112
+ date,
113
+ profile: item.anchorProfile,
114
+ score: item.score,
115
+ source: sourceLine.split(' · ')[0] ?? '',
116
+ source_line: sourceLine,
117
+ tags,
118
+ references,
119
+ },
120
+ };
121
+ return doc;
122
+ }
123
+
124
+ /** Parse a full digest file into Doc[]. */
125
+ export function digestToDocs(markdown: string, date: string, lang: string): Doc[] {
126
+ return DocListSchema.parse(splitItemBlocks(markdown).map((item) => itemToDoc(item, date, lang)));
127
+ }
128
+
129
+ export interface IngestionOptions {
130
+ out: string;
131
+ }
132
+
133
+ export async function processIngestionIO(
134
+ options: IngestionOptions,
135
+ config: z.infer<typeof InputConfigSchema>,
136
+ runner: RunHorizon = defaultRunner,
137
+ now: Date = new Date(),
138
+ ): Promise<{ docs: Doc[] }> {
139
+ const fs = createNodeFileSystem();
140
+ const horizonDir = config.horizon_dir ?? process.env.HORIZON_DIR ?? join(homedir(), 'tools', 'Horizon');
141
+ const dataDir = config.data_dir ?? join(horizonDir, 'data');
142
+
143
+ const runStartedAt = now.getTime();
144
+ const run = await runner(config, horizonDir);
145
+ if (run.exitCode !== 0) {
146
+ throw new Error(`horizon exited ${run.exitCode}: ${run.stderr.trim() || 'no stderr'}`);
147
+ }
148
+
149
+ // Collect digests written (or refreshed) during this run. The date comes from the
150
+ // FILENAME, not the run clock — Horizon names the digest for the date it finishes,
151
+ // which crosses UTC midnight when a long crawl runs late in the day (dogfood
152
+ // daily-ai-news-20260903: run started 23:35 UTC, digest written 00:03 UTC next day).
153
+ const langs = new Set(config.languages ?? ['zh', 'en']);
154
+ const summariesDir = join(dataDir, 'summaries');
155
+ const docs: Doc[] = [];
156
+ if (!(await fs.exists(summariesDir))) {
157
+ echoError(`horizon-ingest: no summaries dir at ${summariesDir} — emitting []`);
158
+ }
159
+ const digestRe = /^horizon-(\d{4}-\d{2}-\d{2})-([a-z-]+)\.md$/;
160
+ const entries = (await fs.exists(summariesDir)) ? await fs.readDir(summariesDir) : [];
161
+ for (const entry of entries) {
162
+ const match = entry.match(digestRe);
163
+ if (!match?.[1] || !match?.[2] || !langs.has(match[2])) continue;
164
+ const file = join(summariesDir, entry);
165
+ const stat = await fs.stat(file);
166
+ if (!stat || stat.mtimeMs < runStartedAt - 1000) continue; // stale file from an earlier run
167
+ docs.push(...digestToDocs(await fs.readFile(file), match[1], match[2]));
168
+ }
169
+ if (docs.length === 0) {
170
+ echoError(
171
+ `horizon-ingest: no fresh digest in ${summariesDir} (languages: ${[...langs].join(', ')}) — emitting []`,
172
+ );
173
+ }
174
+
175
+ const outDir = dirname(options.out);
176
+ if (outDir && outDir !== '.') await fs.ensureDir(outDir);
177
+ await atomicWriteJson(options.out, DocListSchema.parse(docs), fs);
178
+ return { docs };
179
+ }
180
+
181
+ export async function main(runner?: RunHorizon): Promise<number> {
182
+ let values: { in?: string; out?: string };
183
+ try {
184
+ ({ values } = parseArgs({ options: { in: { type: 'string' }, out: { type: 'string' } } }));
185
+ } catch (err: unknown) {
186
+ echoError(`horizon-ingest failed: ${err instanceof Error ? err.message : String(err)}`);
187
+ return 1;
188
+ }
189
+ if (!values.in || !values.out) {
190
+ echoError('horizon-ingest failed: Missing required arguments: --in <config.json> --out <docs.json>');
191
+ return 1;
192
+ }
193
+ try {
194
+ const config = InputConfigSchema.parse(await readJsonFile(values.in));
195
+ await processIngestionIO({ out: values.out }, config, runner);
196
+ return 0;
197
+ } catch (err: unknown) {
198
+ echoError(`horizon-ingest failed: ${err instanceof Error ? err.message : String(err)}`);
199
+ return 1;
200
+ }
201
+ }
202
+
203
+ if (import.meta.main) {
204
+ process.exit(await main());
205
+ }
@@ -0,0 +1,4 @@
1
+ {
2
+ "extends": "../../../tooling/typescript/base.json",
3
+ "include": ["src", "tests"]
4
+ }