@gobing-ai/knowledge-kit 0.0.23 → 0.0.24
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 +137 -59
- package/package.json +4 -4
- package/plugins/generations/content-gen/dist/index.js +97 -45
- package/plugins/generations/core-facts-gen/dist/index.js +106 -57
- package/plugins/generations/daily-article-gen/dist/index.js +105 -56
- package/plugins/generations/dailynews-gen/dist/index.js +235 -57
- package/plugins/generations/dailynews-gen/src/index.ts +67 -2
- package/plugins/generations/dailynews-gen/src/script-builder.ts +36 -15
- package/plugins/generations/dailynews-gen/src/script-plan.ts +142 -0
- package/plugins/generations/episode-plan-gen/dist/index.js +115 -66
- package/plugins/generations/gemini-tts/README.md +24 -0
- package/plugins/generations/gemini-tts/dist/index.js +326 -260
- package/plugins/generations/gemini-tts/src/gemini-client.ts +41 -11
- package/plugins/generations/image-gen/dist/index.js +338 -117
- package/plugins/generations/image-gen/presets/formats/daily-news-cover.yaml +19 -0
- package/plugins/generations/image-gen/presets/formats/xhs-card.yaml +55 -0
- package/plugins/generations/image-gen/presets/styles/daily-news.yaml +9 -0
- package/plugins/generations/image-gen/presets/styles/xhs-knowledge.yaml +7 -0
- package/plugins/generations/image-gen/src/index.ts +148 -14
- package/plugins/generations/image-gen/src/job.ts +30 -0
- package/plugins/generations/image-gen/src/providers/errors.ts +91 -0
- package/plugins/generations/image-gen/src/providers/types.ts +79 -0
- package/plugins/generations/news-report-gen/dist/index.js +136 -55
- package/plugins/generations/news-report-gen/src/index.ts +57 -1
- package/plugins/generations/voice-gen/dist/index.js +119 -67
- package/plugins/ingestions/aihot-ingest/dist/index.js +103 -53
- package/plugins/ingestions/horizon-ingest/dist/index.js +102 -53
- package/plugins/ingestions/karakeep-local/dist/index.js +273 -224
- package/plugins/ingestions/last30days-ingest/dist/index.js +97 -48
- package/plugins/ingestions/web-search/dist/index.js +121 -72
- package/plugins/kk/config.example.yaml +13 -0
- package/plugins/kk/plugin.json +1 -1
- package/plugins/kk/scripts/daily-voice-style.zh.md +52 -0
- package/plugins/kk/scripts/kk-workflow-stages.ts +433 -16
- package/plugins/kk/skills/publish/SKILL.md +24 -1
- package/plugins/kk/skills/xhs-images/SKILL.md +89 -0
- package/plugins/kk/skills/xhs-images/references/card-layouts.md +35 -0
- package/plugins/kk/workflows/kk-daily-ai-voice.yaml +162 -11
- package/plugins/publishings/emdash-pub/dist/index.js +94 -45
- package/plugins/publishings/infoq-pub/dist/index.js +94 -45
- package/plugins/publishings/juejin-pub/dist/index.js +94 -45
- package/plugins/publishings/medium-pub/dist/index.js +94 -45
- package/plugins/publishings/podcast-pub/dist/index.js +115 -55
- package/plugins/publishings/podcast-pub/src/map.ts +30 -10
- package/plugins/publishings/podcast-pub/src/show-notes.ts +6 -1
- package/plugins/publishings/qiita-pub/dist/index.js +94 -45
- package/plugins/publishings/substack-pub/dist/index.js +94 -45
- package/plugins/publishings/surfdash-pub/dist/index.js +99 -63
- package/plugins/publishings/surfdash-pub/src/index.ts +10 -1
- package/plugins/publishings/wechatmp-pub/dist/index.js +94 -45
- package/plugins/publishings/x-pub/dist/index.js +94 -45
- package/plugins/publishings/xhs-pub/dist/index.js +8908 -229
- package/plugins/publishings/xhs-pub/package.json +1 -0
- package/plugins/publishings/xhs-pub/plugin.json +1 -1
- package/plugins/publishings/xhs-pub/src/automation-guard.ts +128 -0
- package/plugins/publishings/xhs-pub/src/index.ts +753 -24
- package/plugins/publishings/xhs-pub/src/profile-check.ts +133 -0
- package/plugins/publishings/zenn-pub/dist/index.js +94 -45
- package/plugins/sp/lib/env.ts +46 -0
- package/plugins/sp/lib/inline-run.generated.mjs +1489 -0
- package/plugins/sp/scripts/feature-verification-steps.ts +275 -0
- package/plugins/sp/scripts/inline-run-setup.ts +571 -47
- package/plugins/sp/scripts/wrapup-drift-probe.mjs +190 -0
- package/plugins/sp/scripts/wrapup-drift-probe.ts +258 -0
- package/plugins/sp/scripts/wrapup-steps.mjs +77 -6
- package/plugins/sp/scripts/wrapup-steps.ts +91 -5
|
@@ -14642,6 +14642,72 @@ var init_zod = __esm(() => {
|
|
|
14642
14642
|
init_external();
|
|
14643
14643
|
});
|
|
14644
14644
|
|
|
14645
|
+
// ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.11/node_modules/@gobing-ai/ts-utils/dist/errors.js
|
|
14646
|
+
var ErrorCode;
|
|
14647
|
+
var init_errors3 = __esm(() => {
|
|
14648
|
+
ErrorCode = {
|
|
14649
|
+
NotFound: "NOT_FOUND",
|
|
14650
|
+
Validation: "VALIDATION",
|
|
14651
|
+
Conflict: "CONFLICT",
|
|
14652
|
+
Internal: "INTERNAL"
|
|
14653
|
+
};
|
|
14654
|
+
});
|
|
14655
|
+
|
|
14656
|
+
// ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.11/node_modules/@gobing-ai/ts-utils/dist/api-response.js
|
|
14657
|
+
var API_ERROR_CODES, ERROR_CODE_TO_HTTP, CLIENT_SAFE_CODES;
|
|
14658
|
+
var init_api_response = __esm(() => {
|
|
14659
|
+
init_errors3();
|
|
14660
|
+
API_ERROR_CODES = {
|
|
14661
|
+
SUCCESS: 0,
|
|
14662
|
+
NOT_FOUND: 404,
|
|
14663
|
+
VALIDATION_ERROR: 422,
|
|
14664
|
+
BAD_REQUEST: 400,
|
|
14665
|
+
UNAUTHORIZED: 401,
|
|
14666
|
+
FORBIDDEN: 403,
|
|
14667
|
+
CONFLICT: 409,
|
|
14668
|
+
INTERNAL_ERROR: 500
|
|
14669
|
+
};
|
|
14670
|
+
ERROR_CODE_TO_HTTP = {
|
|
14671
|
+
[ErrorCode.NotFound]: API_ERROR_CODES.NOT_FOUND,
|
|
14672
|
+
[ErrorCode.Validation]: API_ERROR_CODES.VALIDATION_ERROR,
|
|
14673
|
+
[ErrorCode.Conflict]: API_ERROR_CODES.CONFLICT,
|
|
14674
|
+
[ErrorCode.Internal]: API_ERROR_CODES.INTERNAL_ERROR
|
|
14675
|
+
};
|
|
14676
|
+
CLIENT_SAFE_CODES = new Set([ErrorCode.NotFound, ErrorCode.Validation, ErrorCode.Conflict]);
|
|
14677
|
+
});
|
|
14678
|
+
|
|
14679
|
+
// ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.11/node_modules/@gobing-ai/ts-utils/dist/cursor.js
|
|
14680
|
+
var init_cursor = () => {};
|
|
14681
|
+
|
|
14682
|
+
// ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.11/node_modules/@gobing-ai/ts-utils/dist/event-severity.js
|
|
14683
|
+
var init_event_severity = () => {};
|
|
14684
|
+
|
|
14685
|
+
// ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.11/node_modules/@gobing-ai/ts-utils/dist/output.js
|
|
14686
|
+
function processStream(name) {
|
|
14687
|
+
const proc = globalThis.process;
|
|
14688
|
+
const stream = proc?.[name];
|
|
14689
|
+
if (stream === undefined) {
|
|
14690
|
+
throw new Error(`No ${name} target available: set one via setDefaultOutputTargets or pass an explicit target`);
|
|
14691
|
+
}
|
|
14692
|
+
return stream;
|
|
14693
|
+
}
|
|
14694
|
+
function writeLine(message, target) {
|
|
14695
|
+
target.write(`${message}
|
|
14696
|
+
`);
|
|
14697
|
+
}
|
|
14698
|
+
function echoError(message, target = defaultStderrTarget ?? processStream("stderr")) {
|
|
14699
|
+
writeLine(message, target);
|
|
14700
|
+
}
|
|
14701
|
+
var defaultStderrTarget;
|
|
14702
|
+
|
|
14703
|
+
// ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.11/node_modules/@gobing-ai/ts-utils/dist/index.js
|
|
14704
|
+
var init_dist = __esm(() => {
|
|
14705
|
+
init_api_response();
|
|
14706
|
+
init_cursor();
|
|
14707
|
+
init_errors3();
|
|
14708
|
+
init_event_severity();
|
|
14709
|
+
});
|
|
14710
|
+
|
|
14645
14711
|
// ../../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/nodes/identity.js
|
|
14646
14712
|
var require_identity = __commonJS((exports) => {
|
|
14647
14713
|
var ALIAS = Symbol.for("yaml.alias");
|
|
@@ -17546,15 +17612,15 @@ var require_timestamp = __commonJS((exports) => {
|
|
|
17546
17612
|
throw new Error("!!timestamp expects a date, starting with yyyy-mm-dd");
|
|
17547
17613
|
const [, year, month, day, hour, minute, second] = match.map(Number);
|
|
17548
17614
|
const millisec = match[7] ? Number((match[7] + "00").substr(1, 3)) : 0;
|
|
17549
|
-
let
|
|
17615
|
+
let date6 = Date.UTC(year, month - 1, day, hour || 0, minute || 0, second || 0, millisec);
|
|
17550
17616
|
const tz = match[8];
|
|
17551
17617
|
if (tz && tz !== "Z") {
|
|
17552
17618
|
let d = parseSexagesimal(tz, false);
|
|
17553
17619
|
if (Math.abs(d) < 30)
|
|
17554
17620
|
d *= 60;
|
|
17555
|
-
|
|
17621
|
+
date6 -= 60000 * d;
|
|
17556
17622
|
}
|
|
17557
|
-
return new Date(
|
|
17623
|
+
return new Date(date6);
|
|
17558
17624
|
},
|
|
17559
17625
|
stringify: ({ value }) => value?.toISOString().replace(/(T00:00:00)?\.000Z$/, "") ?? ""
|
|
17560
17626
|
};
|
|
@@ -19414,7 +19480,7 @@ var require_composer = __commonJS((exports) => {
|
|
|
19414
19480
|
var node_process = __require("process");
|
|
19415
19481
|
var directives = require_directives();
|
|
19416
19482
|
var Document = require_Document();
|
|
19417
|
-
var
|
|
19483
|
+
var errors4 = require_errors();
|
|
19418
19484
|
var identity = require_identity();
|
|
19419
19485
|
var composeDoc = require_compose_doc();
|
|
19420
19486
|
var resolveEnd = require_resolve_end();
|
|
@@ -19465,9 +19531,9 @@ var require_composer = __commonJS((exports) => {
|
|
|
19465
19531
|
this.onError = (source, code, message, warning) => {
|
|
19466
19532
|
const pos = getErrorPos(source);
|
|
19467
19533
|
if (warning)
|
|
19468
|
-
this.warnings.push(new
|
|
19534
|
+
this.warnings.push(new errors4.YAMLWarning(pos, code, message));
|
|
19469
19535
|
else
|
|
19470
|
-
this.errors.push(new
|
|
19536
|
+
this.errors.push(new errors4.YAMLParseError(pos, code, message));
|
|
19471
19537
|
};
|
|
19472
19538
|
this.directives = new directives.Directives({ version: options.version || "1.2" });
|
|
19473
19539
|
this.options = options;
|
|
@@ -19553,7 +19619,7 @@ ${cb}` : comment;
|
|
|
19553
19619
|
break;
|
|
19554
19620
|
case "error": {
|
|
19555
19621
|
const msg = token.source ? `${token.message}: ${JSON.stringify(token.source)}` : token.message;
|
|
19556
|
-
const error51 = new
|
|
19622
|
+
const error51 = new errors4.YAMLParseError(getErrorPos(token), "UNEXPECTED_TOKEN", msg);
|
|
19557
19623
|
if (this.atDirectives || !this.doc)
|
|
19558
19624
|
this.errors.push(error51);
|
|
19559
19625
|
else
|
|
@@ -19563,7 +19629,7 @@ ${cb}` : comment;
|
|
|
19563
19629
|
case "doc-end": {
|
|
19564
19630
|
if (!this.doc) {
|
|
19565
19631
|
const msg = "Unexpected doc-end without preceding document";
|
|
19566
|
-
this.errors.push(new
|
|
19632
|
+
this.errors.push(new errors4.YAMLParseError(getErrorPos(token), "UNEXPECTED_TOKEN", msg));
|
|
19567
19633
|
break;
|
|
19568
19634
|
}
|
|
19569
19635
|
this.doc.directives.docEnd = true;
|
|
@@ -19578,7 +19644,7 @@ ${end.comment}` : end.comment;
|
|
|
19578
19644
|
break;
|
|
19579
19645
|
}
|
|
19580
19646
|
default:
|
|
19581
|
-
this.errors.push(new
|
|
19647
|
+
this.errors.push(new errors4.YAMLParseError(getErrorPos(token), "UNEXPECTED_TOKEN", `Unsupported token ${token.type}`));
|
|
19582
19648
|
}
|
|
19583
19649
|
}
|
|
19584
19650
|
*end(forceDoc = false, endOffset = -1) {
|
|
@@ -19604,7 +19670,7 @@ ${end.comment}` : end.comment;
|
|
|
19604
19670
|
var require_cst_scalar = __commonJS((exports) => {
|
|
19605
19671
|
var resolveBlockScalar = require_resolve_block_scalar();
|
|
19606
19672
|
var resolveFlowScalar = require_resolve_flow_scalar();
|
|
19607
|
-
var
|
|
19673
|
+
var errors4 = require_errors();
|
|
19608
19674
|
var stringifyString = require_stringifyString();
|
|
19609
19675
|
function resolveAsScalar(token, strict = true, onError) {
|
|
19610
19676
|
if (token) {
|
|
@@ -19613,7 +19679,7 @@ var require_cst_scalar = __commonJS((exports) => {
|
|
|
19613
19679
|
if (onError)
|
|
19614
19680
|
onError(offset, code, message);
|
|
19615
19681
|
else
|
|
19616
|
-
throw new
|
|
19682
|
+
throw new errors4.YAMLParseError([offset, offset + 1], code, message);
|
|
19617
19683
|
};
|
|
19618
19684
|
switch (token.type) {
|
|
19619
19685
|
case "scalar":
|
|
@@ -21493,7 +21559,7 @@ var require_parser = __commonJS((exports) => {
|
|
|
21493
21559
|
var require_public_api = __commonJS((exports) => {
|
|
21494
21560
|
var composer = require_composer();
|
|
21495
21561
|
var Document = require_Document();
|
|
21496
|
-
var
|
|
21562
|
+
var errors4 = require_errors();
|
|
21497
21563
|
var log = require_log();
|
|
21498
21564
|
var identity = require_identity();
|
|
21499
21565
|
var lineCounter = require_line_counter();
|
|
@@ -21510,8 +21576,8 @@ var require_public_api = __commonJS((exports) => {
|
|
|
21510
21576
|
const docs = Array.from(composer$1.compose(parser$1.parse(source)));
|
|
21511
21577
|
if (prettyErrors && lineCounter2)
|
|
21512
21578
|
for (const doc2 of docs) {
|
|
21513
|
-
doc2.errors.forEach(
|
|
21514
|
-
doc2.warnings.forEach(
|
|
21579
|
+
doc2.errors.forEach(errors4.prettifyError(source, lineCounter2));
|
|
21580
|
+
doc2.warnings.forEach(errors4.prettifyError(source, lineCounter2));
|
|
21515
21581
|
}
|
|
21516
21582
|
if (docs.length > 0)
|
|
21517
21583
|
return docs;
|
|
@@ -21526,13 +21592,13 @@ var require_public_api = __commonJS((exports) => {
|
|
|
21526
21592
|
if (!doc2)
|
|
21527
21593
|
doc2 = _doc;
|
|
21528
21594
|
else if (doc2.options.logLevel !== "silent") {
|
|
21529
|
-
doc2.errors.push(new
|
|
21595
|
+
doc2.errors.push(new errors4.YAMLParseError(_doc.range.slice(0, 2), "MULTIPLE_DOCS", "Source contains multiple documents; please use YAML.parseAllDocuments()"));
|
|
21530
21596
|
break;
|
|
21531
21597
|
}
|
|
21532
21598
|
}
|
|
21533
21599
|
if (prettyErrors && lineCounter2) {
|
|
21534
|
-
doc2.errors.forEach(
|
|
21535
|
-
doc2.warnings.forEach(
|
|
21600
|
+
doc2.errors.forEach(errors4.prettifyError(source, lineCounter2));
|
|
21601
|
+
doc2.warnings.forEach(errors4.prettifyError(source, lineCounter2));
|
|
21536
21602
|
}
|
|
21537
21603
|
return doc2;
|
|
21538
21604
|
}
|
|
@@ -21584,12 +21650,12 @@ var require_public_api = __commonJS((exports) => {
|
|
|
21584
21650
|
});
|
|
21585
21651
|
|
|
21586
21652
|
// ../../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/index.js
|
|
21587
|
-
var composer, Document, Schema,
|
|
21588
|
-
var
|
|
21653
|
+
var composer, Document, Schema, errors4, Alias, identity, Pair, Scalar, YAMLMap, YAMLSeq, cst, lexer, lineCounter, parser, publicApi, visit, $Composer, $Document, $Schema, $YAMLError, $YAMLParseError, $YAMLWarning, $Alias, $isAlias, $isCollection, $isDocument, $isMap, $isNode, $isPair, $isScalar, $isSeq, $Pair, $Scalar, $YAMLMap, $YAMLSeq, $Lexer, $LineCounter, $Parser, $parse, $parseAllDocuments, $parseDocument, $stringify, $visit, $visitAsync;
|
|
21654
|
+
var init_dist2 = __esm(() => {
|
|
21589
21655
|
composer = require_composer();
|
|
21590
21656
|
Document = require_Document();
|
|
21591
21657
|
Schema = require_Schema();
|
|
21592
|
-
|
|
21658
|
+
errors4 = require_errors();
|
|
21593
21659
|
Alias = require_Alias();
|
|
21594
21660
|
identity = require_identity();
|
|
21595
21661
|
Pair = require_Pair();
|
|
@@ -21605,9 +21671,9 @@ var init_dist = __esm(() => {
|
|
|
21605
21671
|
$Composer = composer.Composer;
|
|
21606
21672
|
$Document = Document.Document;
|
|
21607
21673
|
$Schema = Schema.Schema;
|
|
21608
|
-
$YAMLError =
|
|
21609
|
-
$YAMLParseError =
|
|
21610
|
-
$YAMLWarning =
|
|
21674
|
+
$YAMLError = errors4.YAMLError;
|
|
21675
|
+
$YAMLParseError = errors4.YAMLParseError;
|
|
21676
|
+
$YAMLWarning = errors4.YAMLWarning;
|
|
21611
21677
|
$Alias = Alias.Alias;
|
|
21612
21678
|
$isAlias = identity.isAlias;
|
|
21613
21679
|
$isCollection = identity.isCollection;
|
|
@@ -21632,10 +21698,10 @@ var init_dist = __esm(() => {
|
|
|
21632
21698
|
$visitAsync = visit.visitAsync;
|
|
21633
21699
|
});
|
|
21634
21700
|
|
|
21635
|
-
// ../../node_modules/.bun/@gobing-ai+ts-runtime@0.
|
|
21701
|
+
// ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.11/node_modules/@gobing-ai/ts-runtime/dist/config.js
|
|
21636
21702
|
var configSchema;
|
|
21637
21703
|
var init_config = __esm(() => {
|
|
21638
|
-
|
|
21704
|
+
init_dist2();
|
|
21639
21705
|
init_zod();
|
|
21640
21706
|
configSchema = exports_external.object({
|
|
21641
21707
|
app: exports_external.object({
|
|
@@ -21656,7 +21722,7 @@ var init_config = __esm(() => {
|
|
|
21656
21722
|
});
|
|
21657
21723
|
});
|
|
21658
21724
|
|
|
21659
|
-
// ../../node_modules/.bun/@gobing-ai+ts-runtime@0.
|
|
21725
|
+
// ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.11/node_modules/@gobing-ai/ts-runtime/dist/file-system-node.js
|
|
21660
21726
|
import { appendFileSync, cpSync, createReadStream, createWriteStream, existsSync, mkdirSync, readdirSync, readFileSync, realpathSync, renameSync, rmSync, statSync, writeFileSync } from "fs";
|
|
21661
21727
|
import { dirname, resolve as resolvePath } from "path";
|
|
21662
21728
|
function createNodeFileSystem(root, paths) {
|
|
@@ -21834,30 +21900,15 @@ var PluginManifestSchema = exports_external.looseObject({
|
|
|
21834
21900
|
description: exports_external.string().optional(),
|
|
21835
21901
|
operations: exports_external.record(exports_external.string(), PluginOperationSchema).optional()
|
|
21836
21902
|
});
|
|
21837
|
-
// ../../node_modules/.bun/@gobing-ai+ts-runtime@0.
|
|
21903
|
+
// ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.11/node_modules/@gobing-ai/ts-runtime/dist/index.js
|
|
21838
21904
|
init_file_system_node();
|
|
21839
21905
|
init_config();
|
|
21840
21906
|
|
|
21841
|
-
// ../../node_modules/.bun/@gobing-ai+ts-utils@0.4.67/node_modules/@gobing-ai/ts-utils/dist/output.js
|
|
21842
|
-
var defaultStderrTarget;
|
|
21843
|
-
function processStream(name) {
|
|
21844
|
-
const proc = globalThis.process;
|
|
21845
|
-
const stream = proc?.[name];
|
|
21846
|
-
if (stream === undefined) {
|
|
21847
|
-
throw new Error(`No ${name} target available: set one via setDefaultOutputTargets or pass an explicit target`);
|
|
21848
|
-
}
|
|
21849
|
-
return stream;
|
|
21850
|
-
}
|
|
21851
|
-
function writeLine(message, target) {
|
|
21852
|
-
target.write(`${message}
|
|
21853
|
-
`);
|
|
21854
|
-
}
|
|
21855
|
-
function echoError(message, target = defaultStderrTarget ?? processStream("stderr")) {
|
|
21856
|
-
writeLine(message, target);
|
|
21857
|
-
}
|
|
21858
|
-
|
|
21859
21907
|
// ../../packages/kk-core/src/render-md.ts
|
|
21860
21908
|
if (false) {}
|
|
21909
|
+
// ../../plugins/generations/dailynews-gen/src/index.ts
|
|
21910
|
+
init_dist();
|
|
21911
|
+
|
|
21861
21912
|
// ../../plugins/generations/dailynews-gen/src/script-builder.ts
|
|
21862
21913
|
init_zod();
|
|
21863
21914
|
var EffectConfigSchema = exports_external.object({
|
|
@@ -21918,13 +21969,13 @@ function formatChineseCount(n) {
|
|
|
21918
21969
|
return ZH_DIGITS[n] ?? String(n);
|
|
21919
21970
|
return String(n);
|
|
21920
21971
|
}
|
|
21921
|
-
function formatBroadcastDate(
|
|
21972
|
+
function formatBroadcastDate(date6, language) {
|
|
21922
21973
|
if (language === "zh") {
|
|
21923
|
-
const year =
|
|
21924
|
-
const month =
|
|
21925
|
-
const day =
|
|
21974
|
+
const year = date6.getFullYear();
|
|
21975
|
+
const month = date6.getMonth() + 1;
|
|
21976
|
+
const day = date6.getDate();
|
|
21926
21977
|
const weekdays = ["\u65E5", "\u4E00", "\u4E8C", "\u4E09", "\u56DB", "\u4E94", "\u516D"];
|
|
21927
|
-
const weekday = weekdays[
|
|
21978
|
+
const weekday = weekdays[date6.getDay()] ?? "\u65E5";
|
|
21928
21979
|
return `${year}\u5E74${month}\u6708${day}\u65E5\uFF0C\u661F\u671F${weekday}`;
|
|
21929
21980
|
}
|
|
21930
21981
|
return new Intl.DateTimeFormat("en-US", {
|
|
@@ -21932,7 +21983,7 @@ function formatBroadcastDate(date5, language) {
|
|
|
21932
21983
|
month: "long",
|
|
21933
21984
|
day: "numeric",
|
|
21934
21985
|
year: "numeric"
|
|
21935
|
-
}).format(
|
|
21986
|
+
}).format(date6);
|
|
21936
21987
|
}
|
|
21937
21988
|
function normalizeBroadcastText(raw, isZh) {
|
|
21938
21989
|
let text = raw.trim();
|
|
@@ -22103,9 +22154,11 @@ function buildNewsVoiceScript(docs, options) {
|
|
|
22103
22154
|
if (hostName.length > 0) {
|
|
22104
22155
|
hostName = hostName.charAt(0).toUpperCase() + hostName.slice(1);
|
|
22105
22156
|
}
|
|
22157
|
+
const scriptPlan = isZh ? options?.scriptPlan : undefined;
|
|
22158
|
+
const planItems = new Map((scriptPlan?.items ?? []).map((item) => [item.id, item]));
|
|
22106
22159
|
const countText = isZh ? `${formatChineseCount(docs.length)}\u6761` : `${docs.length}`;
|
|
22107
22160
|
const titlesSummary = docs.slice(0, 3).map((d) => (d.title ?? "").trim()).filter(Boolean).join("\u3001");
|
|
22108
|
-
const introText = isZh ? `\u5927\u5BB6\u597D\uFF0C\u4ECA\u5929\u662F${dateStr}\uFF0C\u6B22\u8FCE\u6536\u542C\u7531${hostName}\u4E3A\u60A8\u5E26\u6765\u7684\u4ECA\u65E5AI\u79D1\u6280\u6F2B\u8C08\u3002\u4ECA\u5929\u79D1\u6280\u5708\u6709\u51E0\u6761\u975E\u5E38\u6709\u770B\u70B9\u7684\u5927\u6D88\u606F\uFF0C\u6211\u7CBE\u9009\u4E86${countText}\u6700\u503C\u5F97\u5173\u6CE8\u7684\u91CD\u70B9\u52A8\u6001\u6765\u548C\u5927\u5BB6\u804A\u4E00\u804A${titlesSummary ? `\uFF0C\u5305\u62EC${titlesSummary}` : ""}\u3002\u8BDD\u4E0D\u591A\u8BF4\uFF0C\u6211\u4EEC\u9A6C\u4E0A\u8FDB\u5165\u4ECA\u5929\u7684\u6B63\u9898\u3002` : `Hello and welcome. Today is ${dateStr}. This is ${hostName} with your AI Daily Briefing. In today's episode, we have ${countText} fascinating stories from the AI world. Let's dive straight in.`;
|
|
22161
|
+
const introText = isZh ? scriptPlan ? `\u5927\u5BB6\u597D\uFF0C\u4ECA\u5929\u662F${dateStr}\uFF0C\u6B22\u8FCE\u6536\u542C\u7531${hostName}\u4E3A\u60A8\u5E26\u6765\u7684\u4ECA\u65E5AI\u79D1\u6280\u6F2B\u8C08\u3002${scriptPlan.intro}` : `\u5927\u5BB6\u597D\uFF0C\u4ECA\u5929\u662F${dateStr}\uFF0C\u6B22\u8FCE\u6536\u542C\u7531${hostName}\u4E3A\u60A8\u5E26\u6765\u7684\u4ECA\u65E5AI\u79D1\u6280\u6F2B\u8C08\u3002\u4ECA\u5929\u79D1\u6280\u5708\u6709\u51E0\u6761\u975E\u5E38\u6709\u770B\u70B9\u7684\u5927\u6D88\u606F\uFF0C\u6211\u7CBE\u9009\u4E86${countText}\u6700\u503C\u5F97\u5173\u6CE8\u7684\u91CD\u70B9\u52A8\u6001\u6765\u548C\u5927\u5BB6\u804A\u4E00\u804A${titlesSummary ? `\uFF0C\u5305\u62EC${titlesSummary}` : ""}\u3002\u8BDD\u4E0D\u591A\u8BF4\uFF0C\u6211\u4EEC\u9A6C\u4E0A\u8FDB\u5165\u4ECA\u5929\u7684\u6B63\u9898\u3002` : `Hello and welcome. Today is ${dateStr}. This is ${hostName} with your AI Daily Briefing. In today's episode, we have ${countText} fascinating stories from the AI world. Let's dive straight in.`;
|
|
22109
22162
|
segments.push({
|
|
22110
22163
|
text: normalizeBroadcastText(introText, isZh),
|
|
22111
22164
|
gap_ms: 700,
|
|
@@ -22116,10 +22169,11 @@ function buildNewsVoiceScript(docs, options) {
|
|
|
22116
22169
|
const isLast = idx === docs.length - 1 && docs.length > 1;
|
|
22117
22170
|
const cleanTitle = (doc2.title ?? "").trim();
|
|
22118
22171
|
const cleanBody = stripLeadingTitleEcho(stripTagMetadataLines((doc2.body ?? "").trim()), cleanTitle);
|
|
22119
|
-
const
|
|
22172
|
+
const planItem = planItems.get(doc2.id);
|
|
22173
|
+
const lead = planItem ? `${planItem.lead}\u3010${cleanTitle}\u3011\u3002` : isZh ? idx === 0 ? `\u9996\u5148\u6765\u804A\u804A\u5927\u5BB6\u975E\u5E38\u5173\u6CE8\u7684\u3010${cleanTitle}\u3011\u3002` : isLast ? `\u6700\u540E\uFF0C\u6765\u770B\u770B\u4ECA\u5929\u7684\u6700\u540E\u4E00\u6761\u8D44\u8BAF\uFF0C\u3010${cleanTitle}\u3011\u3002` : `\u63A5\u7740\u6211\u4EEC\u628A\u76EE\u5149\u8F6C\u5411\u53E6\u4E00\u6761\u91CD\u8981\u8FDB\u5C55\uFF0C\u3010${cleanTitle}\u3011\u3002` : idx === 0 ? `First up today, let's look at ${cleanTitle}.` : isLast ? `And finally today, let's wrap up with ${cleanTitle}.` : `Next, turning our attention to ${cleanTitle}.`;
|
|
22120
22174
|
const normalizedLead = normalizeBroadcastText(lead, isZh);
|
|
22121
22175
|
const normalizedBody = cleanBody === "" ? "" : normalizeBroadcastText(cleanBody, isZh);
|
|
22122
|
-
const insight = synthesizePersonalUnderstanding(cleanTitle, cleanBody, isZh, usedInsights);
|
|
22176
|
+
const insight = planItem?.insight ?? synthesizePersonalUnderstanding(cleanTitle, cleanBody, isZh, usedInsights);
|
|
22123
22177
|
const normalizedInsight = insight === null ? null : normalizeBroadcastText(insight, isZh);
|
|
22124
22178
|
const factText = isZh ? `${normalizedLead}${normalizedBody}` : `${normalizedLead} ${normalizedBody}`;
|
|
22125
22179
|
for (const chunk of splitFactText(factText)) {
|
|
@@ -22139,7 +22193,7 @@ function buildNewsVoiceScript(docs, options) {
|
|
|
22139
22193
|
});
|
|
22140
22194
|
}
|
|
22141
22195
|
});
|
|
22142
|
-
const outroText = isZh ? `\u597D\u4E86\uFF0C\u4EE5\u4E0A\u5C31\u662F\u4ECA\u5929AI\u79D1\u6280\u6F2B\u8C08\u7684\u5168\u90E8\u5185\u5BB9\u3002\u4E0D\u77E5\u9053\u4ECA\u5929\u8FD9\u51E0\u6761\u6D88\u606F\u6709\u6CA1\u6709\u7ED9\u60A8\u5E26\u6765\u4E00\u4E9B\u65B0\u7684\u542F\u53D1\uFF1F\u611F\u8C22\u60A8\u7684\u6536\u542C\uFF0C\u6211\u662F${hostName}\uFF0C\u795D\u60A8\u62E5\u6709\u5145\u5B9E\u9AD8\u6548\u7684\u4E00\u5929\uFF0C\u6211\u4EEC\u4E0B\u671F\u8282\u76EE\u4E0D\u89C1\u4E0D\u6563\uFF01` : `That wraps up today's AI Daily Briefing. I hope today's highlights gave you some useful takeaways. Thank you for listening. This is ${hostName}, wishing you a productive and wonderful day. Until next time!`;
|
|
22196
|
+
const outroText = isZh ? scriptPlan ? `${scriptPlan.outro}\u611F\u8C22\u60A8\u7684\u6536\u542C\uFF0C\u6211\u662F${hostName}\uFF0C\u795D\u60A8\u62E5\u6709\u5145\u5B9E\u9AD8\u6548\u7684\u4E00\u5929\uFF0C\u6211\u4EEC\u4E0B\u671F\u8282\u76EE\u4E0D\u89C1\u4E0D\u6563\uFF01` : `\u597D\u4E86\uFF0C\u4EE5\u4E0A\u5C31\u662F\u4ECA\u5929AI\u79D1\u6280\u6F2B\u8C08\u7684\u5168\u90E8\u5185\u5BB9\u3002\u4E0D\u77E5\u9053\u4ECA\u5929\u8FD9\u51E0\u6761\u6D88\u606F\u6709\u6CA1\u6709\u7ED9\u60A8\u5E26\u6765\u4E00\u4E9B\u65B0\u7684\u542F\u53D1\uFF1F\u611F\u8C22\u60A8\u7684\u6536\u542C\uFF0C\u6211\u662F${hostName}\uFF0C\u795D\u60A8\u62E5\u6709\u5145\u5B9E\u9AD8\u6548\u7684\u4E00\u5929\uFF0C\u6211\u4EEC\u4E0B\u671F\u8282\u76EE\u4E0D\u89C1\u4E0D\u6563\uFF01` : `That wraps up today's AI Daily Briefing. I hope today's highlights gave you some useful takeaways. Thank you for listening. This is ${hostName}, wishing you a productive and wonderful day. Until next time!`;
|
|
22143
22197
|
segments.push({
|
|
22144
22198
|
text: normalizeBroadcastText(outroText, isZh),
|
|
22145
22199
|
gap_ms: 300,
|
|
@@ -22280,7 +22334,125 @@ function formatVoiceScriptToYaml(script) {
|
|
|
22280
22334
|
`;
|
|
22281
22335
|
}
|
|
22282
22336
|
|
|
22337
|
+
// ../../plugins/generations/dailynews-gen/src/script-plan.ts
|
|
22338
|
+
init_zod();
|
|
22339
|
+
var ScriptPlanItemSchema = exports_external.object({
|
|
22340
|
+
id: exports_external.string().min(1),
|
|
22341
|
+
lead: exports_external.string().min(1),
|
|
22342
|
+
insight: exports_external.string().min(1)
|
|
22343
|
+
});
|
|
22344
|
+
var ScriptPlanSchema = exports_external.object({
|
|
22345
|
+
version: exports_external.literal(1),
|
|
22346
|
+
intro: exports_external.string().min(1),
|
|
22347
|
+
outro: exports_external.string().min(1),
|
|
22348
|
+
items: exports_external.array(ScriptPlanItemSchema)
|
|
22349
|
+
});
|
|
22350
|
+
var StyleContractSchema = exports_external.object({
|
|
22351
|
+
caps: exports_external.object({
|
|
22352
|
+
intro: exports_external.number().int().positive(),
|
|
22353
|
+
outro: exports_external.number().int().positive(),
|
|
22354
|
+
lead: exports_external.number().int().positive(),
|
|
22355
|
+
insight: exports_external.number().int().positive()
|
|
22356
|
+
}),
|
|
22357
|
+
banned: exports_external.array(exports_external.string().min(1))
|
|
22358
|
+
});
|
|
22359
|
+
var STYLE_JSON_FENCE_RE = /```json\s*([\s\S]*?)```/;
|
|
22360
|
+
function parseStyleContract(markdown) {
|
|
22361
|
+
const match = markdown.match(STYLE_JSON_FENCE_RE);
|
|
22362
|
+
if (!match?.[1]) {
|
|
22363
|
+
throw new Error("style contract has no ```json fenced block");
|
|
22364
|
+
}
|
|
22365
|
+
let parsed;
|
|
22366
|
+
try {
|
|
22367
|
+
parsed = JSON.parse(match[1].trim());
|
|
22368
|
+
} catch (err) {
|
|
22369
|
+
throw new Error(`style contract json block is not valid JSON: ${err instanceof Error ? err.message : String(err)}`);
|
|
22370
|
+
}
|
|
22371
|
+
return StyleContractSchema.parse(parsed);
|
|
22372
|
+
}
|
|
22373
|
+
function validateScriptPlan(plan, docs, style) {
|
|
22374
|
+
const parsed = ScriptPlanSchema.safeParse(plan);
|
|
22375
|
+
if (!parsed.success) {
|
|
22376
|
+
return { ok: false, errors: [{ itemId: "episode", rule: "schema" }] };
|
|
22377
|
+
}
|
|
22378
|
+
const valid = parsed.data;
|
|
22379
|
+
const errors5 = [];
|
|
22380
|
+
const docIds = new Set(docs.map((doc2) => doc2.id));
|
|
22381
|
+
for (const item of valid.items) {
|
|
22382
|
+
if (!docIds.has(item.id))
|
|
22383
|
+
errors5.push({ itemId: item.id, rule: "unknown-id" });
|
|
22384
|
+
}
|
|
22385
|
+
const plannedIds = new Set(valid.items.map((item) => item.id));
|
|
22386
|
+
for (const doc2 of docs) {
|
|
22387
|
+
if (!plannedIds.has(doc2.id))
|
|
22388
|
+
errors5.push({ itemId: doc2.id, rule: "missing-item" });
|
|
22389
|
+
}
|
|
22390
|
+
if (valid.intro.length > style.caps.intro)
|
|
22391
|
+
errors5.push({ itemId: "episode", rule: "cap:intro" });
|
|
22392
|
+
if (valid.outro.length > style.caps.outro)
|
|
22393
|
+
errors5.push({ itemId: "episode", rule: "cap:outro" });
|
|
22394
|
+
for (const item of valid.items) {
|
|
22395
|
+
if (item.lead.length > style.caps.lead)
|
|
22396
|
+
errors5.push({ itemId: item.id, rule: "cap:lead" });
|
|
22397
|
+
if (item.insight.length > style.caps.insight)
|
|
22398
|
+
errors5.push({ itemId: item.id, rule: "cap:insight" });
|
|
22399
|
+
}
|
|
22400
|
+
const fields = [
|
|
22401
|
+
{ itemId: "episode", text: valid.intro },
|
|
22402
|
+
{ itemId: "episode", text: valid.outro },
|
|
22403
|
+
...valid.items.flatMap((item) => [
|
|
22404
|
+
{ itemId: item.id, text: item.lead },
|
|
22405
|
+
{ itemId: item.id, text: item.insight }
|
|
22406
|
+
])
|
|
22407
|
+
];
|
|
22408
|
+
for (const field of fields) {
|
|
22409
|
+
for (const phrase of style.banned) {
|
|
22410
|
+
if (field.text.includes(phrase))
|
|
22411
|
+
errors5.push({ itemId: field.itemId, rule: `banned:${phrase}` });
|
|
22412
|
+
}
|
|
22413
|
+
}
|
|
22414
|
+
const seenInsights = new Set;
|
|
22415
|
+
for (const item of valid.items) {
|
|
22416
|
+
if (seenInsights.has(item.insight))
|
|
22417
|
+
errors5.push({ itemId: item.id, rule: "duplicate-insight" });
|
|
22418
|
+
else
|
|
22419
|
+
seenInsights.add(item.insight);
|
|
22420
|
+
}
|
|
22421
|
+
return errors5.length > 0 ? { ok: false, errors: errors5 } : { ok: true, plan: valid };
|
|
22422
|
+
}
|
|
22423
|
+
|
|
22283
22424
|
// ../../plugins/generations/dailynews-gen/src/index.ts
|
|
22425
|
+
async function resolveScriptPlan(fs, docs) {
|
|
22426
|
+
const planPath = process.env.DAILYNEWS_SCRIPT_PLAN;
|
|
22427
|
+
if (!planPath) {
|
|
22428
|
+
return { scriptSource: "template", scriptPlanErrors: [] };
|
|
22429
|
+
}
|
|
22430
|
+
const fallback = (errors5) => {
|
|
22431
|
+
const reason = errors5.map((error51) => `${error51.itemId}:${error51.rule}`).join(", ");
|
|
22432
|
+
echoError(`dailynews-gen: script plan rejected, falling back to templates (${reason})`);
|
|
22433
|
+
return { scriptSource: "template", scriptPlanErrors: errors5 };
|
|
22434
|
+
};
|
|
22435
|
+
if (!await fs.exists(planPath)) {
|
|
22436
|
+
return fallback([{ itemId: "episode", rule: "missing-plan" }]);
|
|
22437
|
+
}
|
|
22438
|
+
let style;
|
|
22439
|
+
try {
|
|
22440
|
+
style = parseStyleContract(await fs.readFile(process.env.DAILYNEWS_STYLE_FILE ?? ""));
|
|
22441
|
+
} catch {
|
|
22442
|
+
return fallback([{ itemId: "episode", rule: "no-style" }]);
|
|
22443
|
+
}
|
|
22444
|
+
let planJson;
|
|
22445
|
+
try {
|
|
22446
|
+
planJson = JSON.parse(await fs.readFile(planPath));
|
|
22447
|
+
} catch {
|
|
22448
|
+
return fallback([{ itemId: "episode", rule: "schema" }]);
|
|
22449
|
+
}
|
|
22450
|
+
const validated = validateScriptPlan(planJson, docs, style);
|
|
22451
|
+
if (!validated.ok) {
|
|
22452
|
+
return fallback(validated.errors);
|
|
22453
|
+
}
|
|
22454
|
+
return { scriptPlan: validated.plan, scriptSource: "plan", scriptPlanErrors: [] };
|
|
22455
|
+
}
|
|
22284
22456
|
async function processGeneratorIO(inputPath, outputPath, options) {
|
|
22285
22457
|
const fs = createNodeFileSystem();
|
|
22286
22458
|
let docs;
|
|
@@ -22298,7 +22470,9 @@ async function processGeneratorIO(inputPath, outputPath, options) {
|
|
|
22298
22470
|
docs = docs.slice(0, maxItems);
|
|
22299
22471
|
}
|
|
22300
22472
|
}
|
|
22301
|
-
const
|
|
22473
|
+
const isZh = (options?.language || "zh").toLowerCase() === "zh";
|
|
22474
|
+
const planOutcome = isZh ? await resolveScriptPlan(fs, docs) : { scriptSource: "template", scriptPlanErrors: [] };
|
|
22475
|
+
const script = buildNewsVoiceScript(docs, { ...options, scriptPlan: planOutcome.scriptPlan });
|
|
22302
22476
|
const yamlBody = formatVoiceScriptToYaml(script);
|
|
22303
22477
|
const content = {
|
|
22304
22478
|
title: script.title,
|
|
@@ -22317,7 +22491,9 @@ async function processGeneratorIO(inputPath, outputPath, options) {
|
|
|
22317
22491
|
id: d.id,
|
|
22318
22492
|
title: d.title,
|
|
22319
22493
|
sourceUri: d.sourceUri
|
|
22320
|
-
}))
|
|
22494
|
+
})),
|
|
22495
|
+
scriptSource: planOutcome.scriptSource,
|
|
22496
|
+
scriptPlanErrors: planOutcome.scriptPlanErrors
|
|
22321
22497
|
}
|
|
22322
22498
|
};
|
|
22323
22499
|
const validatedContent = ContentSchema.parse(content);
|
|
@@ -22364,11 +22540,13 @@ if (import.meta.main) {
|
|
|
22364
22540
|
process.exit(await main2());
|
|
22365
22541
|
}
|
|
22366
22542
|
export {
|
|
22543
|
+
validateScriptPlan,
|
|
22367
22544
|
synthesizePersonalUnderstanding,
|
|
22368
22545
|
stripTagMetadataLines,
|
|
22369
22546
|
stripLeadingTitleEcho,
|
|
22370
22547
|
splitFactText,
|
|
22371
22548
|
processGeneratorIO,
|
|
22549
|
+
parseStyleContract,
|
|
22372
22550
|
normalizeBroadcastText,
|
|
22373
22551
|
main2 as main,
|
|
22374
22552
|
formatVoiceScriptToYaml,
|
|
@@ -1,17 +1,71 @@
|
|
|
1
1
|
import { dirname } from 'node:path';
|
|
2
2
|
import { parseArgs } from 'node:util';
|
|
3
3
|
import { type Content, ContentSchema, type Doc, DocListSchema } from '@gobing-ai/kk-core';
|
|
4
|
-
import { createNodeFileSystem } from '@gobing-ai/ts-runtime';
|
|
4
|
+
import { createNodeFileSystem, type FileSystem } from '@gobing-ai/ts-runtime';
|
|
5
5
|
import { echoError } from '@gobing-ai/ts-utils';
|
|
6
6
|
import { buildNewsVoiceScript, formatVoiceScriptToYaml, type ScriptBuilderOptions } from './script-builder';
|
|
7
|
+
import {
|
|
8
|
+
parseStyleContract,
|
|
9
|
+
type ScriptPlan,
|
|
10
|
+
type ScriptPlanError,
|
|
11
|
+
type StyleContract,
|
|
12
|
+
validateScriptPlan,
|
|
13
|
+
} from './script-plan';
|
|
7
14
|
|
|
8
15
|
export * from './script-builder';
|
|
16
|
+
export * from './script-plan';
|
|
9
17
|
|
|
10
18
|
export interface GeneratorOptions extends ScriptBuilderOptions {
|
|
11
19
|
in: string;
|
|
12
20
|
out: string;
|
|
13
21
|
}
|
|
14
22
|
|
|
23
|
+
/** `Content.metadata` stamp describing which script path ran (F613 R4). */
|
|
24
|
+
interface ScriptPlanOutcome {
|
|
25
|
+
scriptPlan?: ScriptPlan;
|
|
26
|
+
scriptSource: 'plan' | 'template';
|
|
27
|
+
scriptPlanErrors: ScriptPlanError[];
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Resolve the optional VoiceScript plan (F613). `DAILYNEWS_SCRIPT_PLAN` / `DAILYNEWS_STYLE_FILE`
|
|
32
|
+
* are absolute paths owned by the caller (the workflow wires them; plugin cwd is the package dir,
|
|
33
|
+
* so a relative path is the caller's bug). All-or-nothing: any failure — absent plan, unreadable
|
|
34
|
+
* style, unparseable plan, rejected content — falls back to templates with one warn line naming
|
|
35
|
+
* every `itemId`/`rule`. Fallback is never silent; the exit code stays 0.
|
|
36
|
+
*/
|
|
37
|
+
async function resolveScriptPlan(fs: FileSystem, docs: Doc[]): Promise<ScriptPlanOutcome> {
|
|
38
|
+
const planPath = process.env.DAILYNEWS_SCRIPT_PLAN;
|
|
39
|
+
if (!planPath) {
|
|
40
|
+
return { scriptSource: 'template', scriptPlanErrors: [] };
|
|
41
|
+
}
|
|
42
|
+
const fallback = (errors: ScriptPlanError[]): ScriptPlanOutcome => {
|
|
43
|
+
const reason = errors.map((error) => `${error.itemId}:${error.rule}`).join(', ');
|
|
44
|
+
echoError(`dailynews-gen: script plan rejected, falling back to templates (${reason})`);
|
|
45
|
+
return { scriptSource: 'template', scriptPlanErrors: errors };
|
|
46
|
+
};
|
|
47
|
+
if (!(await fs.exists(planPath))) {
|
|
48
|
+
return fallback([{ itemId: 'episode', rule: 'missing-plan' }]);
|
|
49
|
+
}
|
|
50
|
+
let style: StyleContract;
|
|
51
|
+
try {
|
|
52
|
+
style = parseStyleContract(await fs.readFile(process.env.DAILYNEWS_STYLE_FILE ?? ''));
|
|
53
|
+
} catch {
|
|
54
|
+
return fallback([{ itemId: 'episode', rule: 'no-style' }]);
|
|
55
|
+
}
|
|
56
|
+
let planJson: unknown;
|
|
57
|
+
try {
|
|
58
|
+
planJson = JSON.parse(await fs.readFile(planPath));
|
|
59
|
+
} catch {
|
|
60
|
+
return fallback([{ itemId: 'episode', rule: 'schema' }]);
|
|
61
|
+
}
|
|
62
|
+
const validated = validateScriptPlan(planJson, docs, style);
|
|
63
|
+
if (!validated.ok) {
|
|
64
|
+
return fallback(validated.errors);
|
|
65
|
+
}
|
|
66
|
+
return { scriptPlan: validated.plan, scriptSource: 'plan', scriptPlanErrors: [] };
|
|
67
|
+
}
|
|
68
|
+
|
|
15
69
|
export async function processGeneratorIO(
|
|
16
70
|
inputPath: string,
|
|
17
71
|
outputPath: string,
|
|
@@ -38,7 +92,16 @@ export async function processGeneratorIO(
|
|
|
38
92
|
}
|
|
39
93
|
}
|
|
40
94
|
|
|
41
|
-
|
|
95
|
+
// F613: env-handled plan (validated against the capped docs — the same items that are spoken)
|
|
96
|
+
// with explicit template fallback; the outcome is always stamped into Content.metadata.
|
|
97
|
+
// 0161-review P2: the builder template-builds en regardless of any plan (script-builder.ts's
|
|
98
|
+
// isZh guard), so en must never stamp scriptSource 'plan' — skip resolution entirely so the
|
|
99
|
+
// stamp and the fallback warn channel stay zh-only.
|
|
100
|
+
const isZh = (options?.language || 'zh').toLowerCase() === 'zh';
|
|
101
|
+
const planOutcome = isZh
|
|
102
|
+
? await resolveScriptPlan(fs, docs)
|
|
103
|
+
: { scriptSource: 'template' as const, scriptPlanErrors: [] as ScriptPlanError[] };
|
|
104
|
+
const script = buildNewsVoiceScript(docs, { ...options, scriptPlan: planOutcome.scriptPlan });
|
|
42
105
|
const yamlBody = formatVoiceScriptToYaml(script);
|
|
43
106
|
|
|
44
107
|
const content: Content = {
|
|
@@ -61,6 +124,8 @@ export async function processGeneratorIO(
|
|
|
61
124
|
title: d.title,
|
|
62
125
|
sourceUri: d.sourceUri,
|
|
63
126
|
})),
|
|
127
|
+
scriptSource: planOutcome.scriptSource,
|
|
128
|
+
scriptPlanErrors: planOutcome.scriptPlanErrors,
|
|
64
129
|
},
|
|
65
130
|
};
|
|
66
131
|
|