@gobing-ai/knowledge-kit 0.1.9 → 0.1.10
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.
- package/.claude-plugin/marketplace.json +1 -1
- package/dist/index.js +4 -0
- package/package.json +1 -1
- package/plugins/generations/content-gen/dist/index.js +4 -0
- package/plugins/generations/core-facts-gen/dist/index.js +4 -0
- package/plugins/generations/daily-article-gen/dist/index.js +4 -0
- package/plugins/generations/dailynews-gen/dist/index.js +4 -0
- package/plugins/generations/episode-plan-gen/dist/index.js +102 -1
- package/plugins/generations/episode-plan-gen/src/index.ts +2 -4
- package/plugins/generations/gemini-tts/dist/index.js +4 -0
- package/plugins/generations/image-gen/dist/index.js +4 -0
- package/plugins/generations/news-report-gen/dist/index.js +4 -0
- package/plugins/generations/voice-gen/dist/index.js +4 -0
- package/plugins/generations/voxcpm-tts/dist/index.js +4 -0
- package/plugins/ingestions/aihot-ingest/dist/index.js +4 -0
- package/plugins/ingestions/horizon-ingest/dist/index.js +4 -0
- package/plugins/ingestions/last30days-ingest/dist/index.js +11 -3
- package/plugins/ingestions/last30days-ingest/src/index.ts +14 -3
- package/plugins/ingestions/web-search/dist/index.js +4 -0
- package/plugins/kk/plugin.json +1 -1
- package/plugins/kk/scripts/daily-stages.ts +86 -1
- package/plugins/kk/scripts/sentences.ts +134 -0
- package/plugins/kk/scripts/series-names.ts +124 -0
- package/plugins/kk/workflows/kk-daily-ai-voice2.yaml +37 -3
- package/plugins/kk/workflows/kk-daily-safety.yaml +50 -5
- package/plugins/publishings/bilibili-pub/dist/index.js +4 -0
- package/plugins/publishings/cnblogs-pub/dist/index.js +4 -0
- package/plugins/publishings/csdn-pub/dist/index.js +4 -0
- package/plugins/publishings/csdn-pub/dist/profile-check.js +4 -0
- package/plugins/publishings/emdash-pub/dist/index.js +4 -0
- package/plugins/publishings/infoq-pub/dist/index.js +4 -0
- package/plugins/publishings/infoq-pub/dist/profile-check.js +4 -0
- package/plugins/publishings/jike-pub/dist/index.js +4 -0
- package/plugins/publishings/jike-pub/dist/profile-check.js +4 -0
- package/plugins/publishings/juejin-pub/dist/index.js +4 -0
- package/plugins/publishings/juejin-pub/dist/profile-check.js +4 -0
- package/plugins/publishings/medium-pub/dist/index.js +4 -0
- package/plugins/publishings/podcast-pub/dist/index.js +105 -8
- package/plugins/publishings/podcast-pub/src/seo.ts +2 -4
- package/plugins/publishings/podcast-pub/src/show-notes.ts +3 -8
- package/plugins/publishings/qiita-pub/dist/index.js +4 -0
- package/plugins/publishings/shipinhao-pub/dist/index.js +4 -0
- package/plugins/publishings/sspai-pub/dist/index.js +4 -0
- package/plugins/publishings/substack-pub/dist/index.js +4 -0
- package/plugins/publishings/substack-pub/dist/profile-check.js +4 -0
- package/plugins/publishings/surfdash-pub/dist/index.js +247 -27
- package/plugins/publishings/surfdash-pub/src/digest-check.ts +218 -0
- package/plugins/publishings/surfdash-pub/src/index.ts +76 -29
- package/plugins/publishings/surfdash-pub/src/patch.ts +44 -7
- package/plugins/publishings/threads-pub/dist/index.js +4 -0
- package/plugins/publishings/wechatmp-pub/dist/index.js +4 -0
- package/plugins/publishings/wechatmp-pub/dist/profile-check.js +4 -0
- package/plugins/publishings/weibo-pub/dist/index.js +4 -0
- package/plugins/publishings/weibo-pub/dist/profile-check.js +4 -0
- package/plugins/publishings/x-pub/dist/index.js +4 -0
- package/plugins/publishings/x-pub/dist/profile-check.js +4 -0
- package/plugins/publishings/xhs-pub/dist/index.js +4 -0
- package/plugins/publishings/xhs-pub/dist/profile-check.js +4 -0
- package/plugins/publishings/xiaoyuzhou-pub/dist/index.js +4 -0
- package/plugins/publishings/zenn-pub/dist/index.js +4 -0
package/dist/index.js
CHANGED
|
@@ -42385,6 +42385,10 @@ function getByName(result, name) {
|
|
|
42385
42385
|
}
|
|
42386
42386
|
// ../../packages/kk-core/src/render-md.ts
|
|
42387
42387
|
if (false) {}
|
|
42388
|
+
// ../../packages/kk-core/src/sentences.ts
|
|
42389
|
+
var CJK_TERMINATORS = new Set(["\u3002", "\uFF01", "\uFF1F"]);
|
|
42390
|
+
var LATIN_TERMINATORS = new Set([".", "!", "?"]);
|
|
42391
|
+
var ATTACHED_CLOSERS = new Set(["\u201D", "\u2019", "\u300D", "\u300F", "\uFF09", ")", '"', "'"]);
|
|
42388
42392
|
// src/invoke.ts
|
|
42389
42393
|
init_dist();
|
|
42390
42394
|
|
package/package.json
CHANGED
|
@@ -12253,6 +12253,10 @@ init_config();
|
|
|
12253
12253
|
|
|
12254
12254
|
// ../../packages/kk-core/src/render-md.ts
|
|
12255
12255
|
if (false) {}
|
|
12256
|
+
// ../../packages/kk-core/src/sentences.ts
|
|
12257
|
+
var CJK_TERMINATORS = new Set(["\u3002", "\uFF01", "\uFF1F"]);
|
|
12258
|
+
var LATIN_TERMINATORS = new Set([".", "!", "?"]);
|
|
12259
|
+
var ATTACHED_CLOSERS = new Set(["\u201D", "\u2019", "\u300D", "\u300F", "\uFF09", ")", '"', "'"]);
|
|
12256
12260
|
// ../../plugins/generations/content-gen/src/index.ts
|
|
12257
12261
|
init_dist();
|
|
12258
12262
|
|
|
@@ -12319,6 +12319,10 @@ function uniqueToken() {
|
|
|
12319
12319
|
}
|
|
12320
12320
|
// ../../packages/kk-core/src/render-md.ts
|
|
12321
12321
|
if (false) {}
|
|
12322
|
+
// ../../packages/kk-core/src/sentences.ts
|
|
12323
|
+
var CJK_TERMINATORS = new Set(["\u3002", "\uFF01", "\uFF1F"]);
|
|
12324
|
+
var LATIN_TERMINATORS = new Set([".", "!", "?"]);
|
|
12325
|
+
var ATTACHED_CLOSERS = new Set(["\u201D", "\u2019", "\u300D", "\u300F", "\uFF09", ")", '"', "'"]);
|
|
12322
12326
|
// ../../plugins/generations/core-facts-gen/src/index.ts
|
|
12323
12327
|
init_dist();
|
|
12324
12328
|
function sourceFileOf(entry) {
|
|
@@ -12319,6 +12319,10 @@ function uniqueToken() {
|
|
|
12319
12319
|
}
|
|
12320
12320
|
// ../../packages/kk-core/src/render-md.ts
|
|
12321
12321
|
if (false) {}
|
|
12322
|
+
// ../../packages/kk-core/src/sentences.ts
|
|
12323
|
+
var CJK_TERMINATORS = new Set(["\u3002", "\uFF01", "\uFF1F"]);
|
|
12324
|
+
var LATIN_TERMINATORS = new Set([".", "!", "?"]);
|
|
12325
|
+
var ATTACHED_CLOSERS = new Set(["\u201D", "\u2019", "\u300D", "\u300F", "\uFF09", ")", '"', "'"]);
|
|
12322
12326
|
// ../../plugins/generations/daily-article-gen/src/index.ts
|
|
12323
12327
|
init_dist();
|
|
12324
12328
|
function sourceLabelOf(doc) {
|
|
@@ -12254,6 +12254,10 @@ init_config();
|
|
|
12254
12254
|
|
|
12255
12255
|
// ../../packages/kk-core/src/render-md.ts
|
|
12256
12256
|
if (false) {}
|
|
12257
|
+
// ../../packages/kk-core/src/sentences.ts
|
|
12258
|
+
var CJK_TERMINATORS = new Set(["\u3002", "\uFF01", "\uFF1F"]);
|
|
12259
|
+
var LATIN_TERMINATORS = new Set([".", "!", "?"]);
|
|
12260
|
+
var ATTACHED_CLOSERS = new Set(["\u201D", "\u2019", "\u300D", "\u300F", "\uFF09", ")", '"', "'"]);
|
|
12257
12261
|
// ../../plugins/generations/dailynews-gen/src/index.ts
|
|
12258
12262
|
init_dist();
|
|
12259
12263
|
|
|
@@ -12319,6 +12319,107 @@ function uniqueToken() {
|
|
|
12319
12319
|
}
|
|
12320
12320
|
// ../../packages/kk-core/src/render-md.ts
|
|
12321
12321
|
if (false) {}
|
|
12322
|
+
// ../../packages/kk-core/src/sentences.ts
|
|
12323
|
+
var CJK_TERMINATORS = new Set(["\u3002", "\uFF01", "\uFF1F"]);
|
|
12324
|
+
var LATIN_TERMINATORS = new Set([".", "!", "?"]);
|
|
12325
|
+
var ATTACHED_CLOSERS = new Set(["\u201D", "\u2019", "\u300D", "\u300F", "\uFF09", ")", '"', "'"]);
|
|
12326
|
+
var OPEN_PAIRS = {
|
|
12327
|
+
"\u300C": "\u300D",
|
|
12328
|
+
"\u300E": "\u300F",
|
|
12329
|
+
"\u201C": "\u201D",
|
|
12330
|
+
"\uFF08": "\uFF09",
|
|
12331
|
+
"(": ")"
|
|
12332
|
+
};
|
|
12333
|
+
var CLOSE_PAIRS = {
|
|
12334
|
+
"\u300D": "\u300C",
|
|
12335
|
+
"\u300F": "\u300E",
|
|
12336
|
+
"\u201D": "\u201C",
|
|
12337
|
+
"\uFF09": "\uFF08",
|
|
12338
|
+
")": "("
|
|
12339
|
+
};
|
|
12340
|
+
function splitSentences(text, options = {}) {
|
|
12341
|
+
if (!text || typeof text !== "string")
|
|
12342
|
+
return [];
|
|
12343
|
+
const results = [];
|
|
12344
|
+
let sentenceStart = 0;
|
|
12345
|
+
let stack = [];
|
|
12346
|
+
let i = 0;
|
|
12347
|
+
const isTerminator = (c) => CJK_TERMINATORS.has(c) || options.cjkOnly !== true && LATIN_TERMINATORS.has(c);
|
|
12348
|
+
while (i < text.length) {
|
|
12349
|
+
const ch = text[i];
|
|
12350
|
+
if (isTerminator(ch)) {
|
|
12351
|
+
let termEnd = i;
|
|
12352
|
+
let hasCjkTerm = false;
|
|
12353
|
+
let hasLatinTerm = false;
|
|
12354
|
+
while (termEnd < text.length) {
|
|
12355
|
+
const termChar = text[termEnd];
|
|
12356
|
+
if (!termChar || !isTerminator(termChar)) {
|
|
12357
|
+
break;
|
|
12358
|
+
}
|
|
12359
|
+
if (CJK_TERMINATORS.has(termChar))
|
|
12360
|
+
hasCjkTerm = true;
|
|
12361
|
+
if (LATIN_TERMINATORS.has(termChar))
|
|
12362
|
+
hasLatinTerm = true;
|
|
12363
|
+
termEnd++;
|
|
12364
|
+
}
|
|
12365
|
+
let closerEnd = termEnd;
|
|
12366
|
+
const tempStack = [...stack];
|
|
12367
|
+
while (closerEnd < text.length) {
|
|
12368
|
+
const closer = text[closerEnd];
|
|
12369
|
+
if (!closer || !ATTACHED_CLOSERS.has(closer)) {
|
|
12370
|
+
break;
|
|
12371
|
+
}
|
|
12372
|
+
const top = tempStack[tempStack.length - 1];
|
|
12373
|
+
if (top !== undefined && top === closer) {
|
|
12374
|
+
tempStack.pop();
|
|
12375
|
+
} else if (CLOSE_PAIRS[closer]) {
|
|
12376
|
+
const idx = tempStack.lastIndexOf(closer);
|
|
12377
|
+
if (idx >= 0)
|
|
12378
|
+
tempStack.splice(idx, 1);
|
|
12379
|
+
}
|
|
12380
|
+
closerEnd++;
|
|
12381
|
+
}
|
|
12382
|
+
let isBoundary = false;
|
|
12383
|
+
if (tempStack.length === 0) {
|
|
12384
|
+
if (hasCjkTerm) {
|
|
12385
|
+
isBoundary = true;
|
|
12386
|
+
} else if (hasLatinTerm) {
|
|
12387
|
+
const nextChar = text[closerEnd];
|
|
12388
|
+
if (closerEnd === text.length || nextChar !== undefined && /\s/.test(nextChar)) {
|
|
12389
|
+
isBoundary = true;
|
|
12390
|
+
}
|
|
12391
|
+
}
|
|
12392
|
+
}
|
|
12393
|
+
if (isBoundary) {
|
|
12394
|
+
const sentence = text.slice(sentenceStart, closerEnd).trim();
|
|
12395
|
+
if (sentence.length > 0) {
|
|
12396
|
+
results.push(sentence);
|
|
12397
|
+
}
|
|
12398
|
+
sentenceStart = closerEnd;
|
|
12399
|
+
stack = tempStack;
|
|
12400
|
+
i = closerEnd;
|
|
12401
|
+
continue;
|
|
12402
|
+
}
|
|
12403
|
+
}
|
|
12404
|
+
const openMatch = OPEN_PAIRS[ch];
|
|
12405
|
+
const closeMatch = CLOSE_PAIRS[ch];
|
|
12406
|
+
if (openMatch) {
|
|
12407
|
+
stack.push(openMatch);
|
|
12408
|
+
} else if (closeMatch) {
|
|
12409
|
+
const idx = stack.lastIndexOf(ch);
|
|
12410
|
+
if (idx >= 0)
|
|
12411
|
+
stack.splice(idx, 1);
|
|
12412
|
+
}
|
|
12413
|
+
i++;
|
|
12414
|
+
}
|
|
12415
|
+
if (sentenceStart < text.length) {
|
|
12416
|
+
const tail = text.slice(sentenceStart).trim();
|
|
12417
|
+
if (tail.length > 0) {
|
|
12418
|
+
results.push(tail);
|
|
12419
|
+
}
|
|
12420
|
+
}
|
|
12421
|
+
return results;
|
|
12422
|
+
}
|
|
12322
12423
|
// ../../plugins/generations/episode-plan-gen/src/index.ts
|
|
12323
12424
|
init_dist();
|
|
12324
12425
|
var SOURCE_BASE = {
|
|
@@ -12731,7 +12832,7 @@ function planEpisode(docs, options) {
|
|
|
12731
12832
|
return selected.map((r) => {
|
|
12732
12833
|
const meta = asRecord(r.doc.metadata);
|
|
12733
12834
|
const ascii = asciiRatio(r.doc.title ?? "");
|
|
12734
|
-
const brief = (r.doc.body ?? "").trim()
|
|
12835
|
+
const brief = splitSentences((r.doc.body ?? "").trim(), { cjkOnly: true }).slice(0, 2).join("");
|
|
12735
12836
|
const published = docTimestamp(r.doc);
|
|
12736
12837
|
return {
|
|
12737
12838
|
...r.doc,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { dirname } from 'node:path';
|
|
2
2
|
import { parseArgs } from 'node:util';
|
|
3
|
-
import { type Content, ContentSchema, type Doc, DocListSchema } from '@gobing-ai/kk-core';
|
|
3
|
+
import { type Content, ContentSchema, type Doc, DocListSchema, splitSentences } from '@gobing-ai/kk-core';
|
|
4
4
|
import { atomicWriteJson, createNodeFileSystem, readJsonFile } from '@gobing-ai/ts-runtime';
|
|
5
5
|
import { echoError } from '@gobing-ai/ts-utils';
|
|
6
6
|
|
|
@@ -597,9 +597,7 @@ export function planEpisode(docs: Doc[], options: PlanOptions): Doc[] {
|
|
|
597
597
|
// Task 0118: 1–2-sentence briefing (first two 。!?-terminated sentences of the
|
|
598
598
|
// cleaned body) + best-effort publish timestamp ride the plan metadata so the
|
|
599
599
|
// podcast show-notes brief/timeline render stays deterministic, no LLM.
|
|
600
|
-
const brief = (r.doc.body ?? '')
|
|
601
|
-
.trim()
|
|
602
|
-
.split(/(?<=[。!?])\s*/)
|
|
600
|
+
const brief = splitSentences((r.doc.body ?? '').trim(), { cjkOnly: true })
|
|
603
601
|
.slice(0, 2)
|
|
604
602
|
.join('');
|
|
605
603
|
const published = docTimestamp(r.doc);
|
|
@@ -12257,6 +12257,10 @@ init_config();
|
|
|
12257
12257
|
|
|
12258
12258
|
// ../../packages/kk-core/src/render-md.ts
|
|
12259
12259
|
if (false) {}
|
|
12260
|
+
// ../../packages/kk-core/src/sentences.ts
|
|
12261
|
+
var CJK_TERMINATORS = new Set(["\u3002", "\uFF01", "\uFF1F"]);
|
|
12262
|
+
var LATIN_TERMINATORS = new Set([".", "!", "?"]);
|
|
12263
|
+
var ATTACHED_CLOSERS = new Set(["\u201D", "\u2019", "\u300D", "\u300F", "\uFF09", ")", '"', "'"]);
|
|
12260
12264
|
// ../../plugins/generations/voice-gen/src/index.ts
|
|
12261
12265
|
init_dist();
|
|
12262
12266
|
|
|
@@ -12595,6 +12595,10 @@ init_config();
|
|
|
12595
12595
|
|
|
12596
12596
|
// ../../packages/kk-core/src/render-md.ts
|
|
12597
12597
|
if (false) {}
|
|
12598
|
+
// ../../packages/kk-core/src/sentences.ts
|
|
12599
|
+
var CJK_TERMINATORS = new Set(["\u3002", "\uFF01", "\uFF1F"]);
|
|
12600
|
+
var LATIN_TERMINATORS = new Set([".", "!", "?"]);
|
|
12601
|
+
var ATTACHED_CLOSERS = new Set(["\u201D", "\u2019", "\u300D", "\u300F", "\uFF09", ")", '"', "'"]);
|
|
12598
12602
|
// ../../plugins/generations/image-gen/src/index.ts
|
|
12599
12603
|
init_dist();
|
|
12600
12604
|
|
|
@@ -12319,6 +12319,10 @@ function uniqueToken() {
|
|
|
12319
12319
|
}
|
|
12320
12320
|
// ../../packages/kk-core/src/render-md.ts
|
|
12321
12321
|
if (false) {}
|
|
12322
|
+
// ../../packages/kk-core/src/sentences.ts
|
|
12323
|
+
var CJK_TERMINATORS = new Set(["\u3002", "\uFF01", "\uFF1F"]);
|
|
12324
|
+
var LATIN_TERMINATORS = new Set([".", "!", "?"]);
|
|
12325
|
+
var ATTACHED_CLOSERS = new Set(["\u201D", "\u2019", "\u300D", "\u300F", "\uFF09", ")", '"', "'"]);
|
|
12322
12326
|
// ../../plugins/generations/news-report-gen/src/index.ts
|
|
12323
12327
|
init_dist();
|
|
12324
12328
|
var QC_DIMENSIONS = ["quality", "importance", "urgency", "impact"];
|
|
@@ -12254,6 +12254,10 @@ init_config();
|
|
|
12254
12254
|
|
|
12255
12255
|
// ../../packages/kk-core/src/render-md.ts
|
|
12256
12256
|
if (false) {}
|
|
12257
|
+
// ../../packages/kk-core/src/sentences.ts
|
|
12258
|
+
var CJK_TERMINATORS = new Set(["\u3002", "\uFF01", "\uFF1F"]);
|
|
12259
|
+
var LATIN_TERMINATORS = new Set([".", "!", "?"]);
|
|
12260
|
+
var ATTACHED_CLOSERS = new Set(["\u201D", "\u2019", "\u300D", "\u300F", "\uFF09", ")", '"', "'"]);
|
|
12257
12261
|
// ../../plugins/generations/voice-gen/src/index.ts
|
|
12258
12262
|
init_dist();
|
|
12259
12263
|
|
|
@@ -12257,6 +12257,10 @@ init_config();
|
|
|
12257
12257
|
|
|
12258
12258
|
// ../../packages/kk-core/src/render-md.ts
|
|
12259
12259
|
if (false) {}
|
|
12260
|
+
// ../../packages/kk-core/src/sentences.ts
|
|
12261
|
+
var CJK_TERMINATORS = new Set(["\u3002", "\uFF01", "\uFF1F"]);
|
|
12262
|
+
var LATIN_TERMINATORS = new Set([".", "!", "?"]);
|
|
12263
|
+
var ATTACHED_CLOSERS = new Set(["\u201D", "\u2019", "\u300D", "\u300F", "\uFF09", ")", '"', "'"]);
|
|
12260
12264
|
// ../../plugins/generations/voice-gen/src/index.ts
|
|
12261
12265
|
init_dist();
|
|
12262
12266
|
|
|
@@ -12571,6 +12571,10 @@ function uniqueToken() {
|
|
|
12571
12571
|
}
|
|
12572
12572
|
// ../../packages/kk-core/src/render-md.ts
|
|
12573
12573
|
if (false) {}
|
|
12574
|
+
// ../../packages/kk-core/src/sentences.ts
|
|
12575
|
+
var CJK_TERMINATORS = new Set(["\u3002", "\uFF01", "\uFF1F"]);
|
|
12576
|
+
var LATIN_TERMINATORS = new Set([".", "!", "?"]);
|
|
12577
|
+
var ATTACHED_CLOSERS = new Set(["\u201D", "\u2019", "\u300D", "\u300F", "\uFF09", ")", '"', "'"]);
|
|
12574
12578
|
// ../../plugins/ingestions/aihot-ingest/src/index.ts
|
|
12575
12579
|
init_dist();
|
|
12576
12580
|
init_zod();
|
|
@@ -12320,6 +12320,10 @@ function uniqueToken() {
|
|
|
12320
12320
|
}
|
|
12321
12321
|
// ../../packages/kk-core/src/render-md.ts
|
|
12322
12322
|
if (false) {}
|
|
12323
|
+
// ../../packages/kk-core/src/sentences.ts
|
|
12324
|
+
var CJK_TERMINATORS = new Set(["\u3002", "\uFF01", "\uFF1F"]);
|
|
12325
|
+
var LATIN_TERMINATORS = new Set([".", "!", "?"]);
|
|
12326
|
+
var ATTACHED_CLOSERS = new Set(["\u201D", "\u2019", "\u300D", "\u300F", "\uFF09", ")", '"', "'"]);
|
|
12323
12327
|
// ../../plugins/ingestions/horizon-ingest/src/index.ts
|
|
12324
12328
|
init_dist();
|
|
12325
12329
|
init_zod();
|
|
@@ -11983,7 +11983,7 @@ var init_file_system_node = () => {};
|
|
|
11983
11983
|
// ../../plugins/ingestions/last30days-ingest/src/index.ts
|
|
11984
11984
|
import { createHash } from "crypto";
|
|
11985
11985
|
import { homedir } from "os";
|
|
11986
|
-
import { dirname as dirname2, join } from "path";
|
|
11986
|
+
import { dirname as dirname2, join, resolve } from "path";
|
|
11987
11987
|
import { parseArgs } from "util";
|
|
11988
11988
|
|
|
11989
11989
|
// ../../packages/kk-core/src/content-limits.ts
|
|
@@ -12321,6 +12321,10 @@ function uniqueToken() {
|
|
|
12321
12321
|
}
|
|
12322
12322
|
// ../../packages/kk-core/src/render-md.ts
|
|
12323
12323
|
if (false) {}
|
|
12324
|
+
// ../../packages/kk-core/src/sentences.ts
|
|
12325
|
+
var CJK_TERMINATORS = new Set(["\u3002", "\uFF01", "\uFF1F"]);
|
|
12326
|
+
var LATIN_TERMINATORS = new Set([".", "!", "?"]);
|
|
12327
|
+
var ATTACHED_CLOSERS = new Set(["\u201D", "\u2019", "\u300D", "\u300F", "\uFF09", ")", '"', "'"]);
|
|
12324
12328
|
// ../../plugins/ingestions/last30days-ingest/src/index.ts
|
|
12325
12329
|
init_dist();
|
|
12326
12330
|
init_zod();
|
|
@@ -12332,6 +12336,9 @@ var InputConfigSchema = object({
|
|
|
12332
12336
|
});
|
|
12333
12337
|
var defaultRunner = async (config, outputPath) => {
|
|
12334
12338
|
const skillDir = process.env.LAST30DAYS_SKILL_DIR ?? join(homedir(), ".agents", "skills", "last30days");
|
|
12339
|
+
if (!createNodeFileSystem().exists(skillDir)) {
|
|
12340
|
+
throw new Error(`skill dir missing at ${skillDir} \u2014 restore the last30days skill checkout/symlink or set LAST30DAYS_SKILL_DIR`);
|
|
12341
|
+
}
|
|
12335
12342
|
const argv = [
|
|
12336
12343
|
process.env.LAST30DAYS_PYTHON ?? "python3",
|
|
12337
12344
|
join(skillDir, "scripts", "last30days.py"),
|
|
@@ -12391,7 +12398,8 @@ function mapResultsToDocs(agentJson, topic) {
|
|
|
12391
12398
|
}
|
|
12392
12399
|
async function processIngestionIO(options, config, runner = defaultRunner) {
|
|
12393
12400
|
const fs = createNodeFileSystem();
|
|
12394
|
-
const
|
|
12401
|
+
const out = resolve(options.out);
|
|
12402
|
+
const outDir = dirname2(out);
|
|
12395
12403
|
if (outDir && outDir !== ".")
|
|
12396
12404
|
await fs.ensureDir(outDir);
|
|
12397
12405
|
const capturePath = join(outDir || ".", ".last30days-agent.json");
|
|
@@ -12400,7 +12408,7 @@ async function processIngestionIO(options, config, runner = defaultRunner) {
|
|
|
12400
12408
|
throw new Error(`last30days exited ${run.exitCode}: ${run.stderr.trim() || "no stderr"}`);
|
|
12401
12409
|
}
|
|
12402
12410
|
const docs = mapResultsToDocs(await readJsonFile(capturePath), config.topic);
|
|
12403
|
-
await atomicWriteJson(
|
|
12411
|
+
await atomicWriteJson(out, docs, fs);
|
|
12404
12412
|
return { docs };
|
|
12405
12413
|
}
|
|
12406
12414
|
async function main2(runner) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { createHash } from 'node:crypto';
|
|
2
2
|
import { homedir } from 'node:os';
|
|
3
|
-
import { dirname, join } from 'node:path';
|
|
3
|
+
import { dirname, join, resolve } from 'node:path';
|
|
4
4
|
import { parseArgs } from 'node:util';
|
|
5
5
|
import { type Doc, DocListSchema } from '@gobing-ai/kk-core';
|
|
6
6
|
import { atomicWriteJson, createNodeFileSystem, readJsonFile } from '@gobing-ai/ts-runtime';
|
|
@@ -36,6 +36,14 @@ export type RunLast30Days = (
|
|
|
36
36
|
|
|
37
37
|
export const defaultRunner: RunLast30Days = async (config, outputPath) => {
|
|
38
38
|
const skillDir = process.env.LAST30DAYS_SKILL_DIR ?? join(homedir(), '.agents', 'skills', 'last30days');
|
|
39
|
+
// The skill dir is the spawn cwd: when the ~/.agents/skills/last30days symlink dangles,
|
|
40
|
+
// Bun reports it as `ENOENT ... posix_spawn 'python3'` — pointing at the interpreter, not
|
|
41
|
+
// the dir (2026-10-20 incident lost 9h of diagnosis to that). Fail with the real problem.
|
|
42
|
+
if (!createNodeFileSystem().exists(skillDir)) {
|
|
43
|
+
throw new Error(
|
|
44
|
+
`skill dir missing at ${skillDir} — restore the last30days skill checkout/symlink or set LAST30DAYS_SKILL_DIR`,
|
|
45
|
+
);
|
|
46
|
+
}
|
|
39
47
|
const argv = [
|
|
40
48
|
process.env.LAST30DAYS_PYTHON ?? 'python3',
|
|
41
49
|
join(skillDir, 'scripts', 'last30days.py'),
|
|
@@ -109,7 +117,10 @@ export async function processIngestionIO(
|
|
|
109
117
|
runner: RunLast30Days = defaultRunner,
|
|
110
118
|
): Promise<{ docs: Doc[] }> {
|
|
111
119
|
const fs = createNodeFileSystem();
|
|
112
|
-
|
|
120
|
+
// Relative --out would split cwd semantics: the engine writes its capture relative to the
|
|
121
|
+
// skill dir (its cwd) while we read it relative to ours. Pin everything to an absolute path.
|
|
122
|
+
const out = resolve(options.out);
|
|
123
|
+
const outDir = dirname(out);
|
|
113
124
|
if (outDir && outDir !== '.') await fs.ensureDir(outDir);
|
|
114
125
|
const capturePath = join(outDir || '.', '.last30days-agent.json');
|
|
115
126
|
const run = await runner(config, capturePath);
|
|
@@ -117,7 +128,7 @@ export async function processIngestionIO(
|
|
|
117
128
|
throw new Error(`last30days exited ${run.exitCode}: ${run.stderr.trim() || 'no stderr'}`);
|
|
118
129
|
}
|
|
119
130
|
const docs = mapResultsToDocs(await readJsonFile(capturePath), config.topic);
|
|
120
|
-
await atomicWriteJson(
|
|
131
|
+
await atomicWriteJson(out, docs, fs);
|
|
121
132
|
return { docs };
|
|
122
133
|
}
|
|
123
134
|
|
|
@@ -12275,6 +12275,10 @@ init_config();
|
|
|
12275
12275
|
|
|
12276
12276
|
// ../../packages/kk-core/src/render-md.ts
|
|
12277
12277
|
if (false) {}
|
|
12278
|
+
// ../../packages/kk-core/src/sentences.ts
|
|
12279
|
+
var CJK_TERMINATORS = new Set(["\u3002", "\uFF01", "\uFF1F"]);
|
|
12280
|
+
var LATIN_TERMINATORS = new Set([".", "!", "?"]);
|
|
12281
|
+
var ATTACHED_CLOSERS = new Set(["\u201D", "\u2019", "\u300D", "\u300F", "\uFF09", ")", '"', "'"]);
|
|
12278
12282
|
// ../../node_modules/.bun/@logtape+logtape@2.3.1/node_modules/@logtape/logtape/dist/context.js
|
|
12279
12283
|
var categoryPrefixSymbol = Symbol.for("logtape.categoryPrefix");
|
|
12280
12284
|
function getCategoryPrefix() {
|
package/plugins/kk/plugin.json
CHANGED
|
@@ -114,6 +114,8 @@ import {
|
|
|
114
114
|
type XhsCard,
|
|
115
115
|
xhsPlan,
|
|
116
116
|
} from './kk-workflow-stages.ts';
|
|
117
|
+
import { splitSentences } from './sentences.ts';
|
|
118
|
+
import { normalizeSeriesNames } from './series-names.ts';
|
|
117
119
|
|
|
118
120
|
export function dailyQcContent(args: string[]): void {
|
|
119
121
|
const [
|
|
@@ -1902,6 +1904,37 @@ function readFrontmatterScalar(filePath: string, key: string): string | undefine
|
|
|
1902
1904
|
return value.length > 0 ? value : undefined;
|
|
1903
1905
|
}
|
|
1904
1906
|
|
|
1907
|
+
/** The `key_points` item texts of a Surfing post's frontmatter; undefined when absent/unreadable. */
|
|
1908
|
+
export function readKeyPointItems(filePath: string): string[] | undefined {
|
|
1909
|
+
if (!isFile(filePath)) return undefined;
|
|
1910
|
+
let raw: string;
|
|
1911
|
+
try {
|
|
1912
|
+
raw = readFileSync(filePath, 'utf-8');
|
|
1913
|
+
} catch {
|
|
1914
|
+
return undefined;
|
|
1915
|
+
}
|
|
1916
|
+
const block = /^---\r?\n([\s\S]*?)\r?\n---/.exec(raw)?.[1];
|
|
1917
|
+
if (!block) return undefined;
|
|
1918
|
+
// Slice from `key_points` to the first top-level key (or block end), then take the item lines
|
|
1919
|
+
// (`- `), so folded (`>-`) and quoted single-line items both read once.
|
|
1920
|
+
const head = /^key_points:\n/m.exec(block);
|
|
1921
|
+
if (!head) return undefined;
|
|
1922
|
+
const body = block.slice(head.index + head[0].length);
|
|
1923
|
+
const endMatch = /^\S/m.exec(body);
|
|
1924
|
+
const list = endMatch ? body.slice(0, endMatch.index) : body;
|
|
1925
|
+
// A quoted scalar's quotes are YAML syntax, not text — strip them so label lengths are real.
|
|
1926
|
+
return list
|
|
1927
|
+
.split('\n')
|
|
1928
|
+
.filter((line) => /^[ \t]+- /.test(line))
|
|
1929
|
+
.map((line) => line.replace(/^[ \t]+- /, '').trim())
|
|
1930
|
+
.map((item) => item.replace(/^(["'])(.*)\1$/, '$2'));
|
|
1931
|
+
}
|
|
1932
|
+
|
|
1933
|
+
/** Count `key_points` list items in a Surfing post's frontmatter; undefined when absent/unreadable. */
|
|
1934
|
+
export function countKeyPoints(filePath: string): number | undefined {
|
|
1935
|
+
return readKeyPointItems(filePath)?.length;
|
|
1936
|
+
}
|
|
1937
|
+
|
|
1905
1938
|
function firstRefinedTitle(parsed: Record<string, unknown> | null): string {
|
|
1906
1939
|
const targets = parsed?.targets;
|
|
1907
1940
|
if (!Array.isArray(targets)) return '';
|
|
@@ -1940,7 +1973,7 @@ function planItemsForPodcast(workDir: string, runDate: string): Array<{ title: s
|
|
|
1940
1973
|
? String((meta as Record<string, unknown>).brief).trim()
|
|
1941
1974
|
: '';
|
|
1942
1975
|
const body = typeof record.body === 'string' ? record.body.trim() : '';
|
|
1943
|
-
const brief = metaBrief || (body
|
|
1976
|
+
const brief = metaBrief || (splitSentences(body, { cjkOnly: true })[0] ?? '').trim();
|
|
1944
1977
|
items.push(brief.length > 0 ? { title, brief } : { title });
|
|
1945
1978
|
}
|
|
1946
1979
|
return items;
|
|
@@ -3113,6 +3146,58 @@ export function dailyTranslateSync(args: string[]): void {
|
|
|
3113
3146
|
`translate-sync: 4th argument must be the zh marker file (${runDate}_20_translate-localize_zh-post-path.txt), not the post itself — '${zhPathFile}' holds ${zhPostPath.includes('\n') ? 'a multi-line document' : `'${zhPostPath}'`}`,
|
|
3114
3147
|
);
|
|
3115
3148
|
}
|
|
3149
|
+
// The 2026-10-23 translate run published spliced en/ja description/key_points; the locale
|
|
3150
|
+
// channel has no judge, so gate the structural minimum here before the CMS sync:
|
|
3151
|
+
// a summary must exist and the key_points count must match the zh post (splices merge items).
|
|
3152
|
+
// The same run also invented retired series names (毎日AIブレンド, "Daily AI Medley",
|
|
3153
|
+
// zh-name listen links inside en/ja): normalizeSeriesNames rewrites the known bad set per
|
|
3154
|
+
// locale deterministically (URLs untouched) and any leftover it cannot make safe fails the
|
|
3155
|
+
// sync. The zh post rides the same sync, so it gets the same series-name pass.
|
|
3156
|
+
const zhPoints = countKeyPoints(zhPostPath);
|
|
3157
|
+
for (const locale of ['zh', 'en', 'ja'] as const) {
|
|
3158
|
+
const sibling = locale === 'zh' ? zhPostPath : zhPostPath.replace('/zh/', `/${locale}/`);
|
|
3159
|
+
if (!isFile(sibling)) continue;
|
|
3160
|
+
const problems: string[] = [];
|
|
3161
|
+
const raw = readFileSync(sibling, 'utf-8');
|
|
3162
|
+
const { markdown, remaining } = normalizeSeriesNames(raw, locale);
|
|
3163
|
+
if (markdown !== raw) sted('write', sibling, () => writeRaw(sibling, markdown));
|
|
3164
|
+
if (remaining.length > 0) {
|
|
3165
|
+
problems.push(`retired series names left after rewrite: ${remaining.join(' / ')}`);
|
|
3166
|
+
}
|
|
3167
|
+
if (locale !== 'zh') {
|
|
3168
|
+
if (readFrontmatterScalar(sibling, 'description') === undefined) {
|
|
3169
|
+
problems.push('description missing/empty');
|
|
3170
|
+
}
|
|
3171
|
+
const points = countKeyPoints(sibling);
|
|
3172
|
+
if (zhPoints !== undefined && points !== undefined && points !== zhPoints) {
|
|
3173
|
+
problems.push(`key_points count ${points} != zh ${zhPoints} (spliced or merged items)`);
|
|
3174
|
+
}
|
|
3175
|
+
// Label discipline (same 2026-10-23 audit): a key_points item is `Label — sentence`
|
|
3176
|
+
// and the label is a short phrase — ≤14 chars for ja, ≤28 for en — never a
|
|
3177
|
+
// sentence and never an ellipsis-truncated fragment.
|
|
3178
|
+
const items = readKeyPointItems(sibling);
|
|
3179
|
+
if (items !== undefined) {
|
|
3180
|
+
const cap = locale === 'en' ? 28 : 14;
|
|
3181
|
+
const overLimit = items.filter((item) => {
|
|
3182
|
+
const sep = item.indexOf(' — ');
|
|
3183
|
+
if (sep < 0) return false;
|
|
3184
|
+
const label = item.slice(0, sep);
|
|
3185
|
+
return label.includes('…') || Array.from(label).length > cap;
|
|
3186
|
+
});
|
|
3187
|
+
if (overLimit.length > 0) {
|
|
3188
|
+
problems.push(
|
|
3189
|
+
`key_points label over ${cap} chars or …-truncated: ${overLimit.length} of ${items.length} items`,
|
|
3190
|
+
);
|
|
3191
|
+
}
|
|
3192
|
+
}
|
|
3193
|
+
}
|
|
3194
|
+
if (problems.length > 0) {
|
|
3195
|
+
failWith(
|
|
3196
|
+
1,
|
|
3197
|
+
`translate-sync: ${locale} draft failed the pre-sync structural check (${problems.join('; ')}) — repair ${sibling} per the translate stage contract before syncing`,
|
|
3198
|
+
);
|
|
3199
|
+
}
|
|
3200
|
+
}
|
|
3116
3201
|
sted('write', sync, () =>
|
|
3117
3202
|
writeJqText(sync, { body: '', options: { operation: 'sync', postPath: zhPostPath } }),
|
|
3118
3203
|
);
|