@gobing-ai/knowledge-kit 0.0.17 → 0.0.18
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/README.md +74 -0
- package/dist/index.js +46 -100
- package/package.json +19 -1
- package/plugins/generations/content-gen/dist/index.js +42 -94
- package/plugins/generations/core-facts-gen/dist/index.js +51 -100
- package/plugins/generations/daily-article-gen/dist/index.js +57 -99
- package/plugins/generations/daily-article-gen/src/index.ts +12 -4
- package/plugins/generations/dailynews-gen/dist/index.js +57 -102
- package/plugins/generations/dailynews-gen/src/script-builder.ts +9 -1
- package/plugins/generations/episode-plan-gen/dist/index.js +120 -113
- package/plugins/generations/episode-plan-gen/src/index.ts +102 -22
- package/plugins/generations/image-gen/dist/index.js +63 -115
- package/plugins/generations/news-report-gen/dist/index.js +117 -99
- package/plugins/generations/news-report-gen/src/index.ts +117 -1
- package/plugins/generations/omni-voice-gen/src/omni_voice_gen/pipeline.py +1 -1
- package/plugins/generations/omni-voice-gen/src/omni_voice_gen/voicescript.py +8 -0
- package/plugins/generations/voice-gen/dist/index.js +101 -117
- package/plugins/generations/voice-gen/src/concat.ts +34 -0
- package/plugins/generations/voice-gen/src/index.ts +6 -4
- package/plugins/generations/voice-gen/src/voicescript.ts +8 -0
- package/plugins/ingestions/aihot-ingest/dist/index.js +47 -97
- package/plugins/ingestions/horizon-ingest/dist/index.js +47 -96
- package/plugins/ingestions/karakeep-local/dist/index.js +217 -266
- package/plugins/ingestions/last30days-ingest/dist/index.js +42 -91
- package/plugins/ingestions/web-search/dist/index.js +68 -117
- package/plugins/kk/plugin.json +1 -1
- package/plugins/kk/scripts/kk-workflow-stages.ts +320 -62
- package/plugins/kk/skills/publish/SKILL.md +80 -0
- package/plugins/kk/workflows/kk-daily-ai-voice.yaml +107 -107
- package/plugins/kk/workflows/leftover-publish-fanout-example.yaml +53 -0
- package/plugins/publishings/emdash-pub/dist/index.js +42 -91
- package/plugins/publishings/infoq-pub/dist/index.js +21994 -0
- package/plugins/publishings/infoq-pub/package.json +17 -0
- package/plugins/publishings/infoq-pub/plugin.json +7 -0
- package/plugins/publishings/infoq-pub/src/index.ts +123 -0
- package/plugins/publishings/infoq-pub/tsconfig.json +4 -0
- package/plugins/publishings/juejin-pub/dist/index.js +21994 -0
- package/plugins/publishings/juejin-pub/package.json +17 -0
- package/plugins/publishings/juejin-pub/plugin.json +7 -0
- package/plugins/publishings/juejin-pub/src/index.ts +123 -0
- package/plugins/publishings/juejin-pub/tsconfig.json +4 -0
- package/plugins/publishings/medium-pub/dist/index.js +22041 -0
- package/plugins/publishings/medium-pub/package.json +17 -0
- package/plugins/publishings/medium-pub/plugin.json +7 -0
- package/plugins/publishings/medium-pub/src/index.ts +215 -0
- package/plugins/publishings/medium-pub/tsconfig.json +4 -0
- package/plugins/publishings/podcast-pub/dist/index.js +183 -123
- package/plugins/publishings/podcast-pub/src/index.ts +47 -3
- package/plugins/publishings/podcast-pub/src/show-notes.ts +153 -34
- package/plugins/publishings/qiita-pub/dist/index.js +42 -91
- package/plugins/publishings/substack-pub/dist/index.js +21994 -0
- package/plugins/publishings/substack-pub/package.json +17 -0
- package/plugins/publishings/substack-pub/plugin.json +7 -0
- package/plugins/publishings/substack-pub/src/index.ts +123 -0
- package/plugins/publishings/substack-pub/tsconfig.json +4 -0
- package/plugins/publishings/surfdash-pub/dist/index.js +172 -103
- package/plugins/publishings/surfdash-pub/src/index.ts +32 -2
- package/plugins/publishings/wechatmp-pub/dist/index.js +22119 -0
- package/plugins/publishings/wechatmp-pub/package.json +17 -0
- package/plugins/publishings/wechatmp-pub/plugin.json +7 -0
- package/plugins/publishings/wechatmp-pub/src/index.ts +304 -0
- package/plugins/publishings/wechatmp-pub/tsconfig.json +4 -0
- package/plugins/publishings/x-pub/dist/index.js +22110 -0
- package/plugins/publishings/x-pub/package.json +17 -0
- package/plugins/publishings/x-pub/plugin.json +7 -0
- package/plugins/publishings/x-pub/src/index.ts +222 -0
- package/plugins/publishings/x-pub/tsconfig.json +4 -0
- package/plugins/publishings/xhs-pub/dist/index.js +21994 -0
- package/plugins/publishings/xhs-pub/package.json +17 -0
- package/plugins/publishings/xhs-pub/plugin.json +7 -0
- package/plugins/publishings/xhs-pub/src/index.ts +123 -0
- package/plugins/publishings/xhs-pub/tsconfig.json +4 -0
- package/plugins/publishings/zenn-pub/dist/index.js +42 -91
|
@@ -14642,72 +14642,6 @@ var init_zod = __esm(() => {
|
|
|
14642
14642
|
init_external();
|
|
14643
14643
|
});
|
|
14644
14644
|
|
|
14645
|
-
// ../../node_modules/.bun/@gobing-ai+ts-utils@0.4.39/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.4.39/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.4.39/node_modules/@gobing-ai/ts-utils/dist/cursor.js
|
|
14680
|
-
var init_cursor = () => {};
|
|
14681
|
-
|
|
14682
|
-
// ../../node_modules/.bun/@gobing-ai+ts-utils@0.4.39/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.4.39/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.4.39/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
|
-
|
|
14711
14645
|
// ../../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/nodes/identity.js
|
|
14712
14646
|
var require_identity = __commonJS((exports) => {
|
|
14713
14647
|
var ALIAS = Symbol.for("yaml.alias");
|
|
@@ -17612,15 +17546,15 @@ var require_timestamp = __commonJS((exports) => {
|
|
|
17612
17546
|
throw new Error("!!timestamp expects a date, starting with yyyy-mm-dd");
|
|
17613
17547
|
const [, year, month, day, hour, minute, second] = match.map(Number);
|
|
17614
17548
|
const millisec = match[7] ? Number((match[7] + "00").substr(1, 3)) : 0;
|
|
17615
|
-
let
|
|
17549
|
+
let date5 = Date.UTC(year, month - 1, day, hour || 0, minute || 0, second || 0, millisec);
|
|
17616
17550
|
const tz = match[8];
|
|
17617
17551
|
if (tz && tz !== "Z") {
|
|
17618
17552
|
let d = parseSexagesimal(tz, false);
|
|
17619
17553
|
if (Math.abs(d) < 30)
|
|
17620
17554
|
d *= 60;
|
|
17621
|
-
|
|
17555
|
+
date5 -= 60000 * d;
|
|
17622
17556
|
}
|
|
17623
|
-
return new Date(
|
|
17557
|
+
return new Date(date5);
|
|
17624
17558
|
},
|
|
17625
17559
|
stringify: ({ value }) => value?.toISOString().replace(/(T00:00:00)?\.000Z$/, "") ?? ""
|
|
17626
17560
|
};
|
|
@@ -19480,7 +19414,7 @@ var require_composer = __commonJS((exports) => {
|
|
|
19480
19414
|
var node_process = __require("process");
|
|
19481
19415
|
var directives = require_directives();
|
|
19482
19416
|
var Document = require_Document();
|
|
19483
|
-
var
|
|
19417
|
+
var errors3 = require_errors();
|
|
19484
19418
|
var identity = require_identity();
|
|
19485
19419
|
var composeDoc = require_compose_doc();
|
|
19486
19420
|
var resolveEnd = require_resolve_end();
|
|
@@ -19531,9 +19465,9 @@ var require_composer = __commonJS((exports) => {
|
|
|
19531
19465
|
this.onError = (source, code, message, warning) => {
|
|
19532
19466
|
const pos = getErrorPos(source);
|
|
19533
19467
|
if (warning)
|
|
19534
|
-
this.warnings.push(new
|
|
19468
|
+
this.warnings.push(new errors3.YAMLWarning(pos, code, message));
|
|
19535
19469
|
else
|
|
19536
|
-
this.errors.push(new
|
|
19470
|
+
this.errors.push(new errors3.YAMLParseError(pos, code, message));
|
|
19537
19471
|
};
|
|
19538
19472
|
this.directives = new directives.Directives({ version: options.version || "1.2" });
|
|
19539
19473
|
this.options = options;
|
|
@@ -19619,7 +19553,7 @@ ${cb}` : comment;
|
|
|
19619
19553
|
break;
|
|
19620
19554
|
case "error": {
|
|
19621
19555
|
const msg = token.source ? `${token.message}: ${JSON.stringify(token.source)}` : token.message;
|
|
19622
|
-
const error51 = new
|
|
19556
|
+
const error51 = new errors3.YAMLParseError(getErrorPos(token), "UNEXPECTED_TOKEN", msg);
|
|
19623
19557
|
if (this.atDirectives || !this.doc)
|
|
19624
19558
|
this.errors.push(error51);
|
|
19625
19559
|
else
|
|
@@ -19629,7 +19563,7 @@ ${cb}` : comment;
|
|
|
19629
19563
|
case "doc-end": {
|
|
19630
19564
|
if (!this.doc) {
|
|
19631
19565
|
const msg = "Unexpected doc-end without preceding document";
|
|
19632
|
-
this.errors.push(new
|
|
19566
|
+
this.errors.push(new errors3.YAMLParseError(getErrorPos(token), "UNEXPECTED_TOKEN", msg));
|
|
19633
19567
|
break;
|
|
19634
19568
|
}
|
|
19635
19569
|
this.doc.directives.docEnd = true;
|
|
@@ -19644,7 +19578,7 @@ ${end.comment}` : end.comment;
|
|
|
19644
19578
|
break;
|
|
19645
19579
|
}
|
|
19646
19580
|
default:
|
|
19647
|
-
this.errors.push(new
|
|
19581
|
+
this.errors.push(new errors3.YAMLParseError(getErrorPos(token), "UNEXPECTED_TOKEN", `Unsupported token ${token.type}`));
|
|
19648
19582
|
}
|
|
19649
19583
|
}
|
|
19650
19584
|
*end(forceDoc = false, endOffset = -1) {
|
|
@@ -19670,7 +19604,7 @@ ${end.comment}` : end.comment;
|
|
|
19670
19604
|
var require_cst_scalar = __commonJS((exports) => {
|
|
19671
19605
|
var resolveBlockScalar = require_resolve_block_scalar();
|
|
19672
19606
|
var resolveFlowScalar = require_resolve_flow_scalar();
|
|
19673
|
-
var
|
|
19607
|
+
var errors3 = require_errors();
|
|
19674
19608
|
var stringifyString = require_stringifyString();
|
|
19675
19609
|
function resolveAsScalar(token, strict = true, onError) {
|
|
19676
19610
|
if (token) {
|
|
@@ -19679,7 +19613,7 @@ var require_cst_scalar = __commonJS((exports) => {
|
|
|
19679
19613
|
if (onError)
|
|
19680
19614
|
onError(offset, code, message);
|
|
19681
19615
|
else
|
|
19682
|
-
throw new
|
|
19616
|
+
throw new errors3.YAMLParseError([offset, offset + 1], code, message);
|
|
19683
19617
|
};
|
|
19684
19618
|
switch (token.type) {
|
|
19685
19619
|
case "scalar":
|
|
@@ -21559,7 +21493,7 @@ var require_parser = __commonJS((exports) => {
|
|
|
21559
21493
|
var require_public_api = __commonJS((exports) => {
|
|
21560
21494
|
var composer = require_composer();
|
|
21561
21495
|
var Document = require_Document();
|
|
21562
|
-
var
|
|
21496
|
+
var errors3 = require_errors();
|
|
21563
21497
|
var log = require_log();
|
|
21564
21498
|
var identity = require_identity();
|
|
21565
21499
|
var lineCounter = require_line_counter();
|
|
@@ -21576,8 +21510,8 @@ var require_public_api = __commonJS((exports) => {
|
|
|
21576
21510
|
const docs = Array.from(composer$1.compose(parser$1.parse(source)));
|
|
21577
21511
|
if (prettyErrors && lineCounter2)
|
|
21578
21512
|
for (const doc2 of docs) {
|
|
21579
|
-
doc2.errors.forEach(
|
|
21580
|
-
doc2.warnings.forEach(
|
|
21513
|
+
doc2.errors.forEach(errors3.prettifyError(source, lineCounter2));
|
|
21514
|
+
doc2.warnings.forEach(errors3.prettifyError(source, lineCounter2));
|
|
21581
21515
|
}
|
|
21582
21516
|
if (docs.length > 0)
|
|
21583
21517
|
return docs;
|
|
@@ -21592,13 +21526,13 @@ var require_public_api = __commonJS((exports) => {
|
|
|
21592
21526
|
if (!doc2)
|
|
21593
21527
|
doc2 = _doc;
|
|
21594
21528
|
else if (doc2.options.logLevel !== "silent") {
|
|
21595
|
-
doc2.errors.push(new
|
|
21529
|
+
doc2.errors.push(new errors3.YAMLParseError(_doc.range.slice(0, 2), "MULTIPLE_DOCS", "Source contains multiple documents; please use YAML.parseAllDocuments()"));
|
|
21596
21530
|
break;
|
|
21597
21531
|
}
|
|
21598
21532
|
}
|
|
21599
21533
|
if (prettyErrors && lineCounter2) {
|
|
21600
|
-
doc2.errors.forEach(
|
|
21601
|
-
doc2.warnings.forEach(
|
|
21534
|
+
doc2.errors.forEach(errors3.prettifyError(source, lineCounter2));
|
|
21535
|
+
doc2.warnings.forEach(errors3.prettifyError(source, lineCounter2));
|
|
21602
21536
|
}
|
|
21603
21537
|
return doc2;
|
|
21604
21538
|
}
|
|
@@ -21650,12 +21584,12 @@ var require_public_api = __commonJS((exports) => {
|
|
|
21650
21584
|
});
|
|
21651
21585
|
|
|
21652
21586
|
// ../../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/index.js
|
|
21653
|
-
var composer, Document, Schema,
|
|
21654
|
-
var
|
|
21587
|
+
var composer, Document, Schema, errors3, 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;
|
|
21588
|
+
var init_dist = __esm(() => {
|
|
21655
21589
|
composer = require_composer();
|
|
21656
21590
|
Document = require_Document();
|
|
21657
21591
|
Schema = require_Schema();
|
|
21658
|
-
|
|
21592
|
+
errors3 = require_errors();
|
|
21659
21593
|
Alias = require_Alias();
|
|
21660
21594
|
identity = require_identity();
|
|
21661
21595
|
Pair = require_Pair();
|
|
@@ -21671,9 +21605,9 @@ var init_dist2 = __esm(() => {
|
|
|
21671
21605
|
$Composer = composer.Composer;
|
|
21672
21606
|
$Document = Document.Document;
|
|
21673
21607
|
$Schema = Schema.Schema;
|
|
21674
|
-
$YAMLError =
|
|
21675
|
-
$YAMLParseError =
|
|
21676
|
-
$YAMLWarning =
|
|
21608
|
+
$YAMLError = errors3.YAMLError;
|
|
21609
|
+
$YAMLParseError = errors3.YAMLParseError;
|
|
21610
|
+
$YAMLWarning = errors3.YAMLWarning;
|
|
21677
21611
|
$Alias = Alias.Alias;
|
|
21678
21612
|
$isAlias = identity.isAlias;
|
|
21679
21613
|
$isCollection = identity.isCollection;
|
|
@@ -21701,7 +21635,7 @@ var init_dist2 = __esm(() => {
|
|
|
21701
21635
|
// ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.39/node_modules/@gobing-ai/ts-runtime/dist/config.js
|
|
21702
21636
|
var configSchema;
|
|
21703
21637
|
var init_config = __esm(() => {
|
|
21704
|
-
|
|
21638
|
+
init_dist();
|
|
21705
21639
|
init_zod();
|
|
21706
21640
|
configSchema = exports_external.object({
|
|
21707
21641
|
app: exports_external.object({
|
|
@@ -21810,6 +21744,7 @@ function findProjectRoot(startDir) {
|
|
|
21810
21744
|
var init_file_system_node = () => {};
|
|
21811
21745
|
|
|
21812
21746
|
// ../../plugins/publishings/podcast-pub/src/index.ts
|
|
21747
|
+
import { readFileSync as readFileSync2 } from "fs";
|
|
21813
21748
|
import { readFile } from "fs/promises";
|
|
21814
21749
|
import { dirname as dirname2 } from "path";
|
|
21815
21750
|
import { parseArgs } from "util";
|
|
@@ -21888,6 +21823,24 @@ var PluginManifestSchema = exports_external.object({
|
|
|
21888
21823
|
init_file_system_node();
|
|
21889
21824
|
init_config();
|
|
21890
21825
|
|
|
21826
|
+
// ../../node_modules/.bun/@gobing-ai+ts-utils@0.4.67/node_modules/@gobing-ai/ts-utils/dist/output.js
|
|
21827
|
+
var defaultStderrTarget;
|
|
21828
|
+
function processStream(name) {
|
|
21829
|
+
const proc = globalThis.process;
|
|
21830
|
+
const stream = proc?.[name];
|
|
21831
|
+
if (stream === undefined) {
|
|
21832
|
+
throw new Error(`No ${name} target available: set one via setDefaultOutputTargets or pass an explicit target`);
|
|
21833
|
+
}
|
|
21834
|
+
return stream;
|
|
21835
|
+
}
|
|
21836
|
+
function writeLine(message, target) {
|
|
21837
|
+
target.write(`${message}
|
|
21838
|
+
`);
|
|
21839
|
+
}
|
|
21840
|
+
function echoError(message, target = defaultStderrTarget ?? processStream("stderr")) {
|
|
21841
|
+
writeLine(message, target);
|
|
21842
|
+
}
|
|
21843
|
+
|
|
21891
21844
|
// ../../packages/kk-core/src/render-md.ts
|
|
21892
21845
|
if (false) {}
|
|
21893
21846
|
// ../../packages/publish-harness/src/index.ts
|
|
@@ -21926,9 +21879,6 @@ class FakeFileCliTransport {
|
|
|
21926
21879
|
}
|
|
21927
21880
|
}
|
|
21928
21881
|
|
|
21929
|
-
// ../../plugins/publishings/podcast-pub/src/index.ts
|
|
21930
|
-
init_dist();
|
|
21931
|
-
|
|
21932
21882
|
// ../../plugins/publishings/podcast-pub/src/show-notes.ts
|
|
21933
21883
|
function escapeHtml(value) {
|
|
21934
21884
|
return value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """);
|
|
@@ -21945,8 +21895,80 @@ function renderInline(escaped) {
|
|
|
21945
21895
|
}
|
|
21946
21896
|
return (out + rest).replace(/\*\*([^*]+)\*\*/g, "<strong>$1</strong>");
|
|
21947
21897
|
}
|
|
21898
|
+
function normalizeForMatch(text) {
|
|
21899
|
+
return text.toLowerCase().replace(/[^\p{Script=Han}\p{L}\p{N}]+/gu, "");
|
|
21900
|
+
}
|
|
21901
|
+
function formatOffset(seconds) {
|
|
21902
|
+
if (!Number.isFinite(seconds) || seconds < 0)
|
|
21903
|
+
return "--:--";
|
|
21904
|
+
const m = Math.floor(seconds / 60);
|
|
21905
|
+
const s = Math.round(seconds % 60);
|
|
21906
|
+
return s === 60 ? `${m + 1}:00` : `${m}:${String(s).padStart(2, "0")}`;
|
|
21907
|
+
}
|
|
21908
|
+
function computeAudioOffsets(docs, segments) {
|
|
21909
|
+
const fallback = () => {
|
|
21910
|
+
const chars = docs.map((d) => Math.max((d.body ?? "").trim().length, 1));
|
|
21911
|
+
const total = chars.reduce((a, b) => a + b, 0);
|
|
21912
|
+
const sumDuration = (segments ?? []).reduce((a, s) => a + (s.duration ?? 0), 0);
|
|
21913
|
+
let acc = 0;
|
|
21914
|
+
return chars.map((c) => {
|
|
21915
|
+
const at = acc;
|
|
21916
|
+
acc += c / total * sumDuration;
|
|
21917
|
+
return at;
|
|
21918
|
+
});
|
|
21919
|
+
};
|
|
21920
|
+
if (!segments || segments.length < 2)
|
|
21921
|
+
return fallback();
|
|
21922
|
+
const starts = [];
|
|
21923
|
+
let elapsed = 0;
|
|
21924
|
+
const marks = segments.map((s) => {
|
|
21925
|
+
const at = elapsed;
|
|
21926
|
+
elapsed += s.duration ?? 0;
|
|
21927
|
+
return { at, text: normalizeForMatch(s.transcription ?? "") };
|
|
21928
|
+
});
|
|
21929
|
+
let cursor = 1;
|
|
21930
|
+
for (const d of docs) {
|
|
21931
|
+
const title = normalizeForMatch(d.title ?? "");
|
|
21932
|
+
const needle = title.slice(0, 12);
|
|
21933
|
+
const hit = needle.length >= 4 ? marks.findIndex((m, i) => i >= cursor && m.text.includes(needle)) : -1;
|
|
21934
|
+
if (hit >= 0) {
|
|
21935
|
+
starts.push(marks[hit]?.at ?? 0);
|
|
21936
|
+
cursor = hit + 1;
|
|
21937
|
+
} else {
|
|
21938
|
+
starts.push(Number.NaN);
|
|
21939
|
+
}
|
|
21940
|
+
}
|
|
21941
|
+
if (starts.some((v) => !Number.isFinite(v)))
|
|
21942
|
+
return fallback();
|
|
21943
|
+
return starts;
|
|
21944
|
+
}
|
|
21945
|
+
function renderTimelineHtml(docs, offsets, articleUrl) {
|
|
21946
|
+
const rows = docs.map((d, i) => {
|
|
21947
|
+
const title = escapeHtml(d.title ?? `\u6761\u76EE ${i + 1}`);
|
|
21948
|
+
const brief = escapeHtml(itemBrief(d));
|
|
21949
|
+
const at = formatOffset(offsets[i] ?? Number.NaN);
|
|
21950
|
+
const link = d.sourceUri ? ` <a href="${escapeHtml(d.sourceUri)}" target="_blank" rel="noopener">\u6765\u6E90</a>` : "";
|
|
21951
|
+
return `
|
|
21952
|
+
<div class="kk-tl-row"><div class="kk-tl-t">${at}</div><div class="kk-tl-body"><div class="kk-tl-title">${i + 1}. ${title}${link}</div><p class="kk-tl-brief">${brief}</p></div></div>`;
|
|
21953
|
+
}).join("");
|
|
21954
|
+
return `<!--kk:timeline-->
|
|
21955
|
+
<style>
|
|
21956
|
+
.kk-tl{margin:1em 0}
|
|
21957
|
+
.kk-tl-row{display:flex;gap:12px;padding:10px 0;border-bottom:1px solid rgba(128,128,128,.25)}
|
|
21958
|
+
.kk-tl-t{flex:0 0 56px;font-variant-numeric:tabular-nums;font-weight:700;color:#0969da}
|
|
21959
|
+
.kk-tl-body{flex:1;min-width:0}
|
|
21960
|
+
.kk-tl-title{font-weight:600}
|
|
21961
|
+
.kk-tl-brief{margin:4px 0 0;color:#666;font-size:.95em}
|
|
21962
|
+
</style>
|
|
21963
|
+
<div class="kk-tl">${rows}
|
|
21964
|
+
</div>
|
|
21965
|
+
<p>\u5B8C\u6574\u56FE\u6587\u7248\uFF1A<a href="${escapeHtml(articleUrl)}" target="_blank" rel="noopener">${escapeHtml("\u672C\u671F\u5B8C\u6574\u6587\u7AE0")}</a></p>
|
|
21966
|
+
<!--/kk:timeline-->`;
|
|
21967
|
+
}
|
|
21948
21968
|
function renderShowNotesHtml(markdown) {
|
|
21949
21969
|
const blocks = [];
|
|
21970
|
+
const timeline = [];
|
|
21971
|
+
let inTimeline = false;
|
|
21950
21972
|
let paragraph = [];
|
|
21951
21973
|
const flush = () => {
|
|
21952
21974
|
if (paragraph.length > 0) {
|
|
@@ -21957,6 +21979,19 @@ function renderShowNotesHtml(markdown) {
|
|
|
21957
21979
|
for (const rawLine of markdown.split(`
|
|
21958
21980
|
`)) {
|
|
21959
21981
|
const line = rawLine.trim();
|
|
21982
|
+
if (line === "<!--kk:timeline-->") {
|
|
21983
|
+
flush();
|
|
21984
|
+
inTimeline = true;
|
|
21985
|
+
continue;
|
|
21986
|
+
}
|
|
21987
|
+
if (inTimeline) {
|
|
21988
|
+
if (line === "<!--/kk:timeline-->") {
|
|
21989
|
+
inTimeline = false;
|
|
21990
|
+
continue;
|
|
21991
|
+
}
|
|
21992
|
+
timeline.push(rawLine);
|
|
21993
|
+
continue;
|
|
21994
|
+
}
|
|
21960
21995
|
if (line.length === 0) {
|
|
21961
21996
|
flush();
|
|
21962
21997
|
continue;
|
|
@@ -21974,9 +22009,18 @@ function renderShowNotesHtml(markdown) {
|
|
|
21974
22009
|
paragraph.push(line);
|
|
21975
22010
|
}
|
|
21976
22011
|
flush();
|
|
22012
|
+
if (timeline.length > 0)
|
|
22013
|
+
blocks.push(timeline.join(`
|
|
22014
|
+
`));
|
|
21977
22015
|
return blocks.join(`
|
|
21978
22016
|
`);
|
|
21979
22017
|
}
|
|
22018
|
+
function itemBrief(d) {
|
|
22019
|
+
const meta3 = d.metadata ?? {};
|
|
22020
|
+
if (typeof meta3.brief === "string" && meta3.brief.trim().length > 0)
|
|
22021
|
+
return meta3.brief.trim();
|
|
22022
|
+
return (d.body ?? "").trim().split(/(?<=[\u3002\uFF01\uFF1F])\s*/).slice(0, 2).join("");
|
|
22023
|
+
}
|
|
21980
22024
|
function renderShowNotesMarkdown(docs, opts) {
|
|
21981
22025
|
const slugify2 = (t) => {
|
|
21982
22026
|
const s = t.toLowerCase().replace(/[^\w\s-]/g, "").trim().replace(/[\s_]+/g, "-");
|
|
@@ -21998,33 +22042,18 @@ function renderShowNotesMarkdown(docs, opts) {
|
|
|
21998
22042
|
return "\u6765\u6E90";
|
|
21999
22043
|
}
|
|
22000
22044
|
};
|
|
22001
|
-
const
|
|
22002
|
-
const meta3 = d.metadata ?? {};
|
|
22003
|
-
if (typeof meta3.brief === "string" && meta3.brief.trim().length > 0)
|
|
22004
|
-
return meta3.brief.trim();
|
|
22005
|
-
return (d.body ?? "").trim().split(/(?<=[\u3002\uFF01\uFF1F])\s*/).slice(0, 2).join("");
|
|
22006
|
-
};
|
|
22007
|
-
const itemTimestamp = (d) => {
|
|
22008
|
-
const meta3 = d.metadata ?? {};
|
|
22009
|
-
const raw = meta3.publishAt;
|
|
22010
|
-
const t = typeof raw === "string" ? Date.parse(raw) : typeof raw === "number" ? raw : Number.NaN;
|
|
22011
|
-
if (!Number.isFinite(t))
|
|
22012
|
-
return "--:--";
|
|
22013
|
-
const at = new Date(t);
|
|
22014
|
-
return `${String(at.getHours()).padStart(2, "0")}:${String(at.getMinutes()).padStart(2, "0")}`;
|
|
22015
|
-
};
|
|
22045
|
+
const offsets = computeAudioOffsets(docs, opts.audioSegments);
|
|
22016
22046
|
const lines = [`# ${opts.title}`, ""];
|
|
22017
|
-
|
|
22018
|
-
|
|
22019
|
-
|
|
22020
|
-
|
|
22021
|
-
|
|
22022
|
-
|
|
22023
|
-
|
|
22024
|
-
|
|
22025
|
-
}
|
|
22026
|
-
}
|
|
22027
|
-
lines.push(`\u8BE6\u60C5\u89C1\u672C\u671F\u5B8C\u6574\u6587\u7AE0\uFF1A[ ${opts.title} ](${articleUrl})`, "");
|
|
22047
|
+
if (briefMode) {
|
|
22048
|
+
lines.push(renderTimelineHtml(docs, offsets, articleUrl), "");
|
|
22049
|
+
} else {
|
|
22050
|
+
docs.forEach((d, i) => {
|
|
22051
|
+
const body = (d.body ?? "").trim();
|
|
22052
|
+
const sentences = body.split(/(?<=[\u3002\uFF01\uFF1F])\s*/).slice(0, 2).join("");
|
|
22053
|
+
lines.push(`## ${i + 1}. ${d.title ?? `\u6761\u76EE ${i + 1}`}`, "", sentences, "", `[\u6765\u6E90\uFF1A${sourceLabel(d)}](${d.sourceUri ?? ""})`, "");
|
|
22054
|
+
});
|
|
22055
|
+
lines.push(`\u8BE6\u60C5\u89C1\u672C\u671F\u5B8C\u6574\u6587\u7AE0\uFF1A[ ${opts.title} ](${articleUrl})`, "");
|
|
22056
|
+
}
|
|
22028
22057
|
return lines.join(`
|
|
22029
22058
|
`);
|
|
22030
22059
|
}
|
|
@@ -22255,6 +22284,14 @@ class MicrofeedClient {
|
|
|
22255
22284
|
}
|
|
22256
22285
|
|
|
22257
22286
|
// ../../plugins/publishings/podcast-pub/src/index.ts
|
|
22287
|
+
function publicItemUrl(item, itemId, client) {
|
|
22288
|
+
const microfeed = item?._microfeed;
|
|
22289
|
+
const webUrl = typeof microfeed?.web_url === "string" ? microfeed.web_url : "";
|
|
22290
|
+
if (webUrl !== "")
|
|
22291
|
+
return webUrl;
|
|
22292
|
+
const feedUrl = typeof item?.url === "string" ? item.url : "";
|
|
22293
|
+
return feedUrl !== "" ? feedUrl : client.itemUrl(itemId);
|
|
22294
|
+
}
|
|
22258
22295
|
var TARGET = "podcast-pub";
|
|
22259
22296
|
var OPERATIONS = ["publish", "show-notes", "list", "get", "update", "delete", "validate"];
|
|
22260
22297
|
function resolveClient() {
|
|
@@ -22310,13 +22347,28 @@ function resolveShowNotesRenderOptions(options) {
|
|
|
22310
22347
|
const briefModeRaw = options.briefMode ?? process.env.PODCAST_PUB_BRIEF_MODE;
|
|
22311
22348
|
const briefMode = briefModeRaw === true || briefModeRaw === "true" || briefModeRaw === "1";
|
|
22312
22349
|
const articlePostPath = resolveOptionString(options.articlePostPath, "PODCAST_PUB_ARTICLE_POST_PATH");
|
|
22350
|
+
let audioSegments;
|
|
22351
|
+
const audioContentPath = resolveOptionString(undefined, "PODCAST_PUB_AUDIO_CONTENT");
|
|
22352
|
+
if (audioContentPath !== undefined) {
|
|
22353
|
+
try {
|
|
22354
|
+
const parsed = JSON.parse(readFileSync2(audioContentPath, "utf-8"));
|
|
22355
|
+
const meta3 = parsed?.metadata;
|
|
22356
|
+
if (Array.isArray(meta3?.segments)) {
|
|
22357
|
+
audioSegments = meta3.segments.map((s) => ({
|
|
22358
|
+
duration: typeof s.duration === "number" ? s.duration : undefined,
|
|
22359
|
+
transcription: typeof s.transcription === "string" ? s.transcription : undefined
|
|
22360
|
+
}));
|
|
22361
|
+
}
|
|
22362
|
+
} catch {}
|
|
22363
|
+
}
|
|
22313
22364
|
return {
|
|
22314
22365
|
renderOptions: {
|
|
22315
22366
|
title,
|
|
22316
22367
|
runDate,
|
|
22317
22368
|
...articleBaseUrl !== undefined ? { articleBaseUrl } : {},
|
|
22318
22369
|
...briefMode ? { briefMode: true } : {},
|
|
22319
|
-
...articlePostPath !== undefined ? { articlePostPath } : {}
|
|
22370
|
+
...articlePostPath !== undefined ? { articlePostPath } : {},
|
|
22371
|
+
...audioSegments !== undefined ? { audioSegments } : {}
|
|
22320
22372
|
}
|
|
22321
22373
|
};
|
|
22322
22374
|
}
|
|
@@ -22410,10 +22462,16 @@ async function publishEpisode(client, payload, options) {
|
|
|
22410
22462
|
attachments: [audioAttachment(episode.audio, episode.audio.url, undefined, episode.durationSeconds)],
|
|
22411
22463
|
...episodeExtras(episode)
|
|
22412
22464
|
}, idempotencyKey);
|
|
22465
|
+
let hostedItem;
|
|
22466
|
+
try {
|
|
22467
|
+
hostedItem = (await client.getItem(itemId2)).items?.[0];
|
|
22468
|
+
} catch {
|
|
22469
|
+
hostedItem = undefined;
|
|
22470
|
+
}
|
|
22413
22471
|
return ResultSchema.parse({
|
|
22414
22472
|
ok: true,
|
|
22415
22473
|
target: TARGET,
|
|
22416
|
-
url:
|
|
22474
|
+
url: publicItemUrl(hostedItem, itemId2, client),
|
|
22417
22475
|
id: itemId2,
|
|
22418
22476
|
message: "Published successfully to microfeed (hosted audio, single-call create)"
|
|
22419
22477
|
});
|
|
@@ -22455,9 +22513,10 @@ async function publishEpisode(client, payload, options) {
|
|
|
22455
22513
|
return ResultSchema.parse({
|
|
22456
22514
|
ok: true,
|
|
22457
22515
|
target: TARGET,
|
|
22458
|
-
url:
|
|
22516
|
+
url: publicItemUrl(item, itemId, client),
|
|
22459
22517
|
id: itemId,
|
|
22460
|
-
message: "Published successfully to microfeed (two-phase upload + publish)"
|
|
22518
|
+
message: "Published successfully to microfeed (two-phase upload + publish)",
|
|
22519
|
+
metadata: { itemId, imageUrl: imageUrl ?? null }
|
|
22461
22520
|
});
|
|
22462
22521
|
}
|
|
22463
22522
|
|
|
@@ -22643,6 +22702,7 @@ if (import.meta.main) {
|
|
|
22643
22702
|
process.exit(await main2());
|
|
22644
22703
|
}
|
|
22645
22704
|
export {
|
|
22705
|
+
publicItemUrl,
|
|
22646
22706
|
processPublishIO,
|
|
22647
22707
|
main2 as main,
|
|
22648
22708
|
getPublishTransport,
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs';
|
|
1
2
|
import { readFile } from 'node:fs/promises';
|
|
2
3
|
import { dirname } from 'node:path';
|
|
3
4
|
import { parseArgs } from 'node:util';
|
|
@@ -6,10 +7,23 @@ import { FakeFileCliTransport, type PublishTransport, type PublishTransportPaylo
|
|
|
6
7
|
import { createNodeFileSystem } from '@gobing-ai/ts-runtime';
|
|
7
8
|
import { echoError } from '@gobing-ai/ts-utils';
|
|
8
9
|
import { type EpisodeMapping, mapContentToEpisode } from './map';
|
|
9
|
-
import { MicrofeedClient, type MicrofeedItemInput, resolveTimeoutMs } from './microfeed-client';
|
|
10
|
+
import { MicrofeedClient, type MicrofeedItem, type MicrofeedItemInput, resolveTimeoutMs } from './microfeed-client';
|
|
10
11
|
import { renderShowNotesMarkdown, type ShowNotesRenderOptions } from './show-notes';
|
|
11
12
|
|
|
12
13
|
/** Result target name for this plugin. */
|
|
14
|
+
/**
|
|
15
|
+
* Canonical public page URL from a microfeed item: `_microfeed.web_url` (`/i/{slug}-{id}/` — the
|
|
16
|
+
* deployment's real page shape) wins, then the JSON Feed `url`, then the client's `/items/{id}`
|
|
17
|
+
* fallback (which 404s on some deployments but is the only shape derivable from the id alone).
|
|
18
|
+
*/
|
|
19
|
+
export function publicItemUrl(item: MicrofeedItem | undefined, itemId: string, client: MicrofeedClient): string {
|
|
20
|
+
const microfeed = item?._microfeed as Record<string, unknown> | undefined;
|
|
21
|
+
const webUrl = typeof microfeed?.web_url === 'string' ? microfeed.web_url : '';
|
|
22
|
+
if (webUrl !== '') return webUrl;
|
|
23
|
+
const feedUrl = typeof item?.url === 'string' ? item.url : '';
|
|
24
|
+
return feedUrl !== '' ? feedUrl : client.itemUrl(itemId);
|
|
25
|
+
}
|
|
26
|
+
|
|
13
27
|
const TARGET = 'podcast-pub';
|
|
14
28
|
|
|
15
29
|
/** Management operations routed via `options.operation` (design D5). */
|
|
@@ -113,6 +127,24 @@ function resolveShowNotesRenderOptions(
|
|
|
113
127
|
const briefModeRaw = options.briefMode ?? process.env.PODCAST_PUB_BRIEF_MODE;
|
|
114
128
|
const briefMode = briefModeRaw === true || briefModeRaw === 'true' || briefModeRaw === '1';
|
|
115
129
|
const articlePostPath = resolveOptionString(options.articlePostPath, 'PODCAST_PUB_ARTICLE_POST_PATH');
|
|
130
|
+
// Audio segment metadata for real timeline offsets: the generated episode content's
|
|
131
|
+
// `metadata.segments[]` (duration + ASR transcription). Absent ⇒ `--:--` offsets.
|
|
132
|
+
let audioSegments: ShowNotesRenderOptions['audioSegments'];
|
|
133
|
+
const audioContentPath = resolveOptionString(undefined, 'PODCAST_PUB_AUDIO_CONTENT');
|
|
134
|
+
if (audioContentPath !== undefined) {
|
|
135
|
+
try {
|
|
136
|
+
const parsed: unknown = JSON.parse(readFileSync(audioContentPath, 'utf-8'));
|
|
137
|
+
const meta = (parsed as { metadata?: unknown })?.metadata as Record<string, unknown> | undefined;
|
|
138
|
+
if (Array.isArray(meta?.segments)) {
|
|
139
|
+
audioSegments = (meta.segments as Array<Record<string, unknown>>).map((s) => ({
|
|
140
|
+
duration: typeof s.duration === 'number' ? s.duration : undefined,
|
|
141
|
+
transcription: typeof s.transcription === 'string' ? s.transcription : undefined,
|
|
142
|
+
}));
|
|
143
|
+
}
|
|
144
|
+
} catch {
|
|
145
|
+
// Timeline offsets degrade to proportional — never block show-notes on audio metadata.
|
|
146
|
+
}
|
|
147
|
+
}
|
|
116
148
|
return {
|
|
117
149
|
renderOptions: {
|
|
118
150
|
title,
|
|
@@ -120,6 +152,7 @@ function resolveShowNotesRenderOptions(
|
|
|
120
152
|
...(articleBaseUrl !== undefined ? { articleBaseUrl } : {}),
|
|
121
153
|
...(briefMode ? { briefMode: true } : {}),
|
|
122
154
|
...(articlePostPath !== undefined ? { articlePostPath } : {}),
|
|
155
|
+
...(audioSegments !== undefined ? { audioSegments } : {}),
|
|
123
156
|
},
|
|
124
157
|
};
|
|
125
158
|
}
|
|
@@ -262,10 +295,18 @@ async function publishEpisode(
|
|
|
262
295
|
},
|
|
263
296
|
idempotencyKey,
|
|
264
297
|
);
|
|
298
|
+
// Best-effort canonical-URL enrichment: the episode is already published, so a failed
|
|
299
|
+
// follow-up GET (or an unparsable response) falls back to publicItemUrl's own chain.
|
|
300
|
+
let hostedItem: MicrofeedItem | undefined;
|
|
301
|
+
try {
|
|
302
|
+
hostedItem = (await client.getItem(itemId)).items?.[0];
|
|
303
|
+
} catch {
|
|
304
|
+
hostedItem = undefined;
|
|
305
|
+
}
|
|
265
306
|
return ResultSchema.parse({
|
|
266
307
|
ok: true,
|
|
267
308
|
target: TARGET,
|
|
268
|
-
url:
|
|
309
|
+
url: publicItemUrl(hostedItem, itemId, client),
|
|
269
310
|
id: itemId,
|
|
270
311
|
message: 'Published successfully to microfeed (hosted audio, single-call create)',
|
|
271
312
|
});
|
|
@@ -319,9 +360,12 @@ async function publishEpisode(
|
|
|
319
360
|
return ResultSchema.parse({
|
|
320
361
|
ok: true,
|
|
321
362
|
target: TARGET,
|
|
322
|
-
url:
|
|
363
|
+
url: publicItemUrl(item, itemId, client),
|
|
323
364
|
id: itemId,
|
|
324
365
|
message: 'Published successfully to microfeed (two-phase upload + publish)',
|
|
366
|
+
// 20260917 review #6: downstream surfdash patch reuses the podcast-hosted cover URL
|
|
367
|
+
// (no re-upload); null when the episode carried no local cover.
|
|
368
|
+
metadata: { itemId, imageUrl: imageUrl ?? null },
|
|
325
369
|
});
|
|
326
370
|
}
|
|
327
371
|
|