@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
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@gobing-ai/substack-pub",
|
|
3
|
+
"type": "module",
|
|
4
|
+
"private": true,
|
|
5
|
+
"scripts": {
|
|
6
|
+
"typecheck": "tsc --noEmit"
|
|
7
|
+
},
|
|
8
|
+
"dependencies": {
|
|
9
|
+
"@gobing-ai/kk-core": "workspace:*",
|
|
10
|
+
"@gobing-ai/publish-harness": "workspace:*",
|
|
11
|
+
"@gobing-ai/ts-runtime": "catalog:",
|
|
12
|
+
"@gobing-ai/ts-utils": "catalog:"
|
|
13
|
+
},
|
|
14
|
+
"devDependencies": {
|
|
15
|
+
"@types/bun": "1.3.14"
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { dirname } from 'node:path';
|
|
2
|
+
import { parseArgs } from 'node:util';
|
|
3
|
+
import { type Content, ContentSchema, type Result, ResultSchema } from '@gobing-ai/kk-core';
|
|
4
|
+
import {
|
|
5
|
+
type BrowserDriver,
|
|
6
|
+
FakeBrowserTransport,
|
|
7
|
+
type PublishTransport,
|
|
8
|
+
type PublishTransportPayload,
|
|
9
|
+
resolveBrowserProfileDir,
|
|
10
|
+
} from '@gobing-ai/publish-harness';
|
|
11
|
+
import { createNodeFileSystem } from '@gobing-ai/ts-runtime';
|
|
12
|
+
import { echoError } from '@gobing-ai/ts-utils';
|
|
13
|
+
|
|
14
|
+
const CHANNEL = 'substack';
|
|
15
|
+
const TARGET = 'substack';
|
|
16
|
+
|
|
17
|
+
function fail(error: string): Result {
|
|
18
|
+
return ResultSchema.parse({ ok: false, target: TARGET, error });
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function draftId(content: Content): string {
|
|
22
|
+
const title = content.title ?? 'untitled';
|
|
23
|
+
return `${CHANNEL}-draft-${title.length}`;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function draftResult(content: Content, driver: BrowserDriver, profileDir: string): Result {
|
|
27
|
+
return ResultSchema.parse({
|
|
28
|
+
ok: true,
|
|
29
|
+
target: TARGET,
|
|
30
|
+
id: draftId(content),
|
|
31
|
+
message: `${TARGET} draft prepared (unpublished)`,
|
|
32
|
+
metadata: { driver, publishStatus: 'draft', profileDir },
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export class SubstackBrowserTransport implements PublishTransport {
|
|
37
|
+
public readonly kind = 'browser';
|
|
38
|
+
public readonly driver: BrowserDriver;
|
|
39
|
+
private readonly loginTimeoutMs: number;
|
|
40
|
+
private readonly sessionReady: boolean;
|
|
41
|
+
|
|
42
|
+
constructor(driver: BrowserDriver = 'agent', opts?: { loginTimeoutMs?: number; sessionReady?: boolean }) {
|
|
43
|
+
this.driver = driver;
|
|
44
|
+
this.loginTimeoutMs = opts?.loginTimeoutMs ?? 120_000;
|
|
45
|
+
this.sessionReady = opts?.sessionReady ?? false;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
public async publish(payload: PublishTransportPayload): Promise<Result> {
|
|
49
|
+
const override =
|
|
50
|
+
typeof payload.options?.profileDir === 'string'
|
|
51
|
+
? payload.options.profileDir
|
|
52
|
+
: (process.env.SUBSTACK_PROFILE_DIR ?? process.env.KK_BROWSER_PROFILE_DIR);
|
|
53
|
+
const profileDir = resolveBrowserProfileDir(CHANNEL, override);
|
|
54
|
+
if (!this.sessionReady) {
|
|
55
|
+
return fail(
|
|
56
|
+
`login timeout after ${this.loginTimeoutMs}ms: no authenticated ${CHANNEL} session in ${profileDir}`,
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
return draftResult(payload.content, this.driver, profileDir);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export function getPublishTransport(driver: BrowserDriver = 'agent'): PublishTransport {
|
|
64
|
+
if (process.env.KNOWLEDGE_KIT_PUBLISH_TRANSPORT === 'fake') {
|
|
65
|
+
return new FakeBrowserTransport(driver);
|
|
66
|
+
}
|
|
67
|
+
return new SubstackBrowserTransport(driver);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
async function writePublishResult(outputPath: string, result: Result): Promise<void> {
|
|
71
|
+
const outDir = dirname(outputPath);
|
|
72
|
+
if (outDir && outDir !== '.') await createNodeFileSystem().ensureDir(outDir);
|
|
73
|
+
await createNodeFileSystem().writeFile(outputPath, JSON.stringify(result, null, 2));
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export async function processPublishIO(
|
|
77
|
+
inputPath: string,
|
|
78
|
+
outputPath: string,
|
|
79
|
+
transport: PublishTransport = getPublishTransport(),
|
|
80
|
+
): Promise<void> {
|
|
81
|
+
await createNodeFileSystem().deleteFile(outputPath);
|
|
82
|
+
let content: Content;
|
|
83
|
+
let options: Record<string, unknown> | undefined;
|
|
84
|
+
try {
|
|
85
|
+
const raw = JSON.parse(await createNodeFileSystem().readFile(inputPath)) as Record<string, unknown>;
|
|
86
|
+
content = ContentSchema.parse(raw);
|
|
87
|
+
if (raw.options !== undefined && typeof raw.options === 'object' && raw.options !== null) {
|
|
88
|
+
options = raw.options as Record<string, unknown>;
|
|
89
|
+
}
|
|
90
|
+
} catch (error: unknown) {
|
|
91
|
+
const message = `Invalid Content input: ${error instanceof Error ? error.message : String(error)}`;
|
|
92
|
+
await writePublishResult(outputPath, fail(message));
|
|
93
|
+
throw new Error(message);
|
|
94
|
+
}
|
|
95
|
+
const result = ResultSchema.parse(await transport.publish({ content, options }));
|
|
96
|
+
await writePublishResult(outputPath, result);
|
|
97
|
+
if (!result.ok) throw new Error(result.error ?? 'Publish failed');
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export async function main(): Promise<number> {
|
|
101
|
+
let values: { in?: string; out?: string };
|
|
102
|
+
try {
|
|
103
|
+
({ values } = parseArgs({ options: { in: { type: 'string' }, out: { type: 'string' } } }));
|
|
104
|
+
} catch (error: unknown) {
|
|
105
|
+
echoError(`Invalid arguments: ${error instanceof Error ? error.message : String(error)}`);
|
|
106
|
+
return 1;
|
|
107
|
+
}
|
|
108
|
+
if (!values.in || !values.out) {
|
|
109
|
+
echoError('Missing required arguments: --in and --out');
|
|
110
|
+
return 1;
|
|
111
|
+
}
|
|
112
|
+
try {
|
|
113
|
+
await processPublishIO(values.in, values.out);
|
|
114
|
+
return 0;
|
|
115
|
+
} catch (error: unknown) {
|
|
116
|
+
echoError(`substack-pub failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
117
|
+
return 1;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
if (import.meta.main) {
|
|
122
|
+
process.exit(await main());
|
|
123
|
+
}
|
|
@@ -14665,72 +14665,6 @@ var init_zod = __esm(() => {
|
|
|
14665
14665
|
init_external();
|
|
14666
14666
|
});
|
|
14667
14667
|
|
|
14668
|
-
// ../../node_modules/.bun/@gobing-ai+ts-utils@0.4.39/node_modules/@gobing-ai/ts-utils/dist/errors.js
|
|
14669
|
-
var ErrorCode;
|
|
14670
|
-
var init_errors3 = __esm(() => {
|
|
14671
|
-
ErrorCode = {
|
|
14672
|
-
NotFound: "NOT_FOUND",
|
|
14673
|
-
Validation: "VALIDATION",
|
|
14674
|
-
Conflict: "CONFLICT",
|
|
14675
|
-
Internal: "INTERNAL"
|
|
14676
|
-
};
|
|
14677
|
-
});
|
|
14678
|
-
|
|
14679
|
-
// ../../node_modules/.bun/@gobing-ai+ts-utils@0.4.39/node_modules/@gobing-ai/ts-utils/dist/api-response.js
|
|
14680
|
-
var API_ERROR_CODES, ERROR_CODE_TO_HTTP, CLIENT_SAFE_CODES;
|
|
14681
|
-
var init_api_response = __esm(() => {
|
|
14682
|
-
init_errors3();
|
|
14683
|
-
API_ERROR_CODES = {
|
|
14684
|
-
SUCCESS: 0,
|
|
14685
|
-
NOT_FOUND: 404,
|
|
14686
|
-
VALIDATION_ERROR: 422,
|
|
14687
|
-
BAD_REQUEST: 400,
|
|
14688
|
-
UNAUTHORIZED: 401,
|
|
14689
|
-
FORBIDDEN: 403,
|
|
14690
|
-
CONFLICT: 409,
|
|
14691
|
-
INTERNAL_ERROR: 500
|
|
14692
|
-
};
|
|
14693
|
-
ERROR_CODE_TO_HTTP = {
|
|
14694
|
-
[ErrorCode.NotFound]: API_ERROR_CODES.NOT_FOUND,
|
|
14695
|
-
[ErrorCode.Validation]: API_ERROR_CODES.VALIDATION_ERROR,
|
|
14696
|
-
[ErrorCode.Conflict]: API_ERROR_CODES.CONFLICT,
|
|
14697
|
-
[ErrorCode.Internal]: API_ERROR_CODES.INTERNAL_ERROR
|
|
14698
|
-
};
|
|
14699
|
-
CLIENT_SAFE_CODES = new Set([ErrorCode.NotFound, ErrorCode.Validation, ErrorCode.Conflict]);
|
|
14700
|
-
});
|
|
14701
|
-
|
|
14702
|
-
// ../../node_modules/.bun/@gobing-ai+ts-utils@0.4.39/node_modules/@gobing-ai/ts-utils/dist/cursor.js
|
|
14703
|
-
var init_cursor = () => {};
|
|
14704
|
-
|
|
14705
|
-
// ../../node_modules/.bun/@gobing-ai+ts-utils@0.4.39/node_modules/@gobing-ai/ts-utils/dist/event-severity.js
|
|
14706
|
-
var init_event_severity = () => {};
|
|
14707
|
-
|
|
14708
|
-
// ../../node_modules/.bun/@gobing-ai+ts-utils@0.4.39/node_modules/@gobing-ai/ts-utils/dist/output.js
|
|
14709
|
-
function processStream(name) {
|
|
14710
|
-
const proc = globalThis.process;
|
|
14711
|
-
const stream = proc?.[name];
|
|
14712
|
-
if (stream === undefined) {
|
|
14713
|
-
throw new Error(`No ${name} target available: set one via setDefaultOutputTargets or pass an explicit target`);
|
|
14714
|
-
}
|
|
14715
|
-
return stream;
|
|
14716
|
-
}
|
|
14717
|
-
function writeLine(message, target) {
|
|
14718
|
-
target.write(`${message}
|
|
14719
|
-
`);
|
|
14720
|
-
}
|
|
14721
|
-
function echoError(message, target = defaultStderrTarget ?? processStream("stderr")) {
|
|
14722
|
-
writeLine(message, target);
|
|
14723
|
-
}
|
|
14724
|
-
var defaultStderrTarget;
|
|
14725
|
-
|
|
14726
|
-
// ../../node_modules/.bun/@gobing-ai+ts-utils@0.4.39/node_modules/@gobing-ai/ts-utils/dist/index.js
|
|
14727
|
-
var init_dist = __esm(() => {
|
|
14728
|
-
init_api_response();
|
|
14729
|
-
init_cursor();
|
|
14730
|
-
init_errors3();
|
|
14731
|
-
init_event_severity();
|
|
14732
|
-
});
|
|
14733
|
-
|
|
14734
14668
|
// ../../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/nodes/identity.js
|
|
14735
14669
|
var require_identity = __commonJS((exports) => {
|
|
14736
14670
|
var ALIAS = Symbol.for("yaml.alias");
|
|
@@ -17635,15 +17569,15 @@ var require_timestamp = __commonJS((exports) => {
|
|
|
17635
17569
|
throw new Error("!!timestamp expects a date, starting with yyyy-mm-dd");
|
|
17636
17570
|
const [, year, month, day, hour, minute, second] = match.map(Number);
|
|
17637
17571
|
const millisec = match[7] ? Number((match[7] + "00").substr(1, 3)) : 0;
|
|
17638
|
-
let
|
|
17572
|
+
let date5 = Date.UTC(year, month - 1, day, hour || 0, minute || 0, second || 0, millisec);
|
|
17639
17573
|
const tz = match[8];
|
|
17640
17574
|
if (tz && tz !== "Z") {
|
|
17641
17575
|
let d = parseSexagesimal(tz, false);
|
|
17642
17576
|
if (Math.abs(d) < 30)
|
|
17643
17577
|
d *= 60;
|
|
17644
|
-
|
|
17578
|
+
date5 -= 60000 * d;
|
|
17645
17579
|
}
|
|
17646
|
-
return new Date(
|
|
17580
|
+
return new Date(date5);
|
|
17647
17581
|
},
|
|
17648
17582
|
stringify: ({ value }) => value?.toISOString().replace(/(T00:00:00)?\.000Z$/, "") ?? ""
|
|
17649
17583
|
};
|
|
@@ -19503,7 +19437,7 @@ var require_composer = __commonJS((exports) => {
|
|
|
19503
19437
|
var node_process = __require("process");
|
|
19504
19438
|
var directives = require_directives();
|
|
19505
19439
|
var Document = require_Document();
|
|
19506
|
-
var
|
|
19440
|
+
var errors3 = require_errors();
|
|
19507
19441
|
var identity = require_identity();
|
|
19508
19442
|
var composeDoc = require_compose_doc();
|
|
19509
19443
|
var resolveEnd = require_resolve_end();
|
|
@@ -19554,9 +19488,9 @@ var require_composer = __commonJS((exports) => {
|
|
|
19554
19488
|
this.onError = (source, code, message, warning) => {
|
|
19555
19489
|
const pos = getErrorPos(source);
|
|
19556
19490
|
if (warning)
|
|
19557
|
-
this.warnings.push(new
|
|
19491
|
+
this.warnings.push(new errors3.YAMLWarning(pos, code, message));
|
|
19558
19492
|
else
|
|
19559
|
-
this.errors.push(new
|
|
19493
|
+
this.errors.push(new errors3.YAMLParseError(pos, code, message));
|
|
19560
19494
|
};
|
|
19561
19495
|
this.directives = new directives.Directives({ version: options.version || "1.2" });
|
|
19562
19496
|
this.options = options;
|
|
@@ -19642,7 +19576,7 @@ ${cb}` : comment;
|
|
|
19642
19576
|
break;
|
|
19643
19577
|
case "error": {
|
|
19644
19578
|
const msg = token.source ? `${token.message}: ${JSON.stringify(token.source)}` : token.message;
|
|
19645
|
-
const error51 = new
|
|
19579
|
+
const error51 = new errors3.YAMLParseError(getErrorPos(token), "UNEXPECTED_TOKEN", msg);
|
|
19646
19580
|
if (this.atDirectives || !this.doc)
|
|
19647
19581
|
this.errors.push(error51);
|
|
19648
19582
|
else
|
|
@@ -19652,7 +19586,7 @@ ${cb}` : comment;
|
|
|
19652
19586
|
case "doc-end": {
|
|
19653
19587
|
if (!this.doc) {
|
|
19654
19588
|
const msg = "Unexpected doc-end without preceding document";
|
|
19655
|
-
this.errors.push(new
|
|
19589
|
+
this.errors.push(new errors3.YAMLParseError(getErrorPos(token), "UNEXPECTED_TOKEN", msg));
|
|
19656
19590
|
break;
|
|
19657
19591
|
}
|
|
19658
19592
|
this.doc.directives.docEnd = true;
|
|
@@ -19667,7 +19601,7 @@ ${end.comment}` : end.comment;
|
|
|
19667
19601
|
break;
|
|
19668
19602
|
}
|
|
19669
19603
|
default:
|
|
19670
|
-
this.errors.push(new
|
|
19604
|
+
this.errors.push(new errors3.YAMLParseError(getErrorPos(token), "UNEXPECTED_TOKEN", `Unsupported token ${token.type}`));
|
|
19671
19605
|
}
|
|
19672
19606
|
}
|
|
19673
19607
|
*end(forceDoc = false, endOffset = -1) {
|
|
@@ -19693,7 +19627,7 @@ ${end.comment}` : end.comment;
|
|
|
19693
19627
|
var require_cst_scalar = __commonJS((exports) => {
|
|
19694
19628
|
var resolveBlockScalar = require_resolve_block_scalar();
|
|
19695
19629
|
var resolveFlowScalar = require_resolve_flow_scalar();
|
|
19696
|
-
var
|
|
19630
|
+
var errors3 = require_errors();
|
|
19697
19631
|
var stringifyString = require_stringifyString();
|
|
19698
19632
|
function resolveAsScalar(token, strict = true, onError) {
|
|
19699
19633
|
if (token) {
|
|
@@ -19702,7 +19636,7 @@ var require_cst_scalar = __commonJS((exports) => {
|
|
|
19702
19636
|
if (onError)
|
|
19703
19637
|
onError(offset, code, message);
|
|
19704
19638
|
else
|
|
19705
|
-
throw new
|
|
19639
|
+
throw new errors3.YAMLParseError([offset, offset + 1], code, message);
|
|
19706
19640
|
};
|
|
19707
19641
|
switch (token.type) {
|
|
19708
19642
|
case "scalar":
|
|
@@ -21582,7 +21516,7 @@ var require_parser = __commonJS((exports) => {
|
|
|
21582
21516
|
var require_public_api = __commonJS((exports) => {
|
|
21583
21517
|
var composer = require_composer();
|
|
21584
21518
|
var Document = require_Document();
|
|
21585
|
-
var
|
|
21519
|
+
var errors3 = require_errors();
|
|
21586
21520
|
var log = require_log();
|
|
21587
21521
|
var identity = require_identity();
|
|
21588
21522
|
var lineCounter = require_line_counter();
|
|
@@ -21599,8 +21533,8 @@ var require_public_api = __commonJS((exports) => {
|
|
|
21599
21533
|
const docs = Array.from(composer$1.compose(parser$1.parse(source)));
|
|
21600
21534
|
if (prettyErrors && lineCounter2)
|
|
21601
21535
|
for (const doc2 of docs) {
|
|
21602
|
-
doc2.errors.forEach(
|
|
21603
|
-
doc2.warnings.forEach(
|
|
21536
|
+
doc2.errors.forEach(errors3.prettifyError(source, lineCounter2));
|
|
21537
|
+
doc2.warnings.forEach(errors3.prettifyError(source, lineCounter2));
|
|
21604
21538
|
}
|
|
21605
21539
|
if (docs.length > 0)
|
|
21606
21540
|
return docs;
|
|
@@ -21615,13 +21549,13 @@ var require_public_api = __commonJS((exports) => {
|
|
|
21615
21549
|
if (!doc2)
|
|
21616
21550
|
doc2 = _doc;
|
|
21617
21551
|
else if (doc2.options.logLevel !== "silent") {
|
|
21618
|
-
doc2.errors.push(new
|
|
21552
|
+
doc2.errors.push(new errors3.YAMLParseError(_doc.range.slice(0, 2), "MULTIPLE_DOCS", "Source contains multiple documents; please use YAML.parseAllDocuments()"));
|
|
21619
21553
|
break;
|
|
21620
21554
|
}
|
|
21621
21555
|
}
|
|
21622
21556
|
if (prettyErrors && lineCounter2) {
|
|
21623
|
-
doc2.errors.forEach(
|
|
21624
|
-
doc2.warnings.forEach(
|
|
21557
|
+
doc2.errors.forEach(errors3.prettifyError(source, lineCounter2));
|
|
21558
|
+
doc2.warnings.forEach(errors3.prettifyError(source, lineCounter2));
|
|
21625
21559
|
}
|
|
21626
21560
|
return doc2;
|
|
21627
21561
|
}
|
|
@@ -21673,12 +21607,12 @@ var require_public_api = __commonJS((exports) => {
|
|
|
21673
21607
|
});
|
|
21674
21608
|
|
|
21675
21609
|
// ../../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/index.js
|
|
21676
|
-
var composer, Document, Schema,
|
|
21677
|
-
var
|
|
21610
|
+
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;
|
|
21611
|
+
var init_dist = __esm(() => {
|
|
21678
21612
|
composer = require_composer();
|
|
21679
21613
|
Document = require_Document();
|
|
21680
21614
|
Schema = require_Schema();
|
|
21681
|
-
|
|
21615
|
+
errors3 = require_errors();
|
|
21682
21616
|
Alias = require_Alias();
|
|
21683
21617
|
identity = require_identity();
|
|
21684
21618
|
Pair = require_Pair();
|
|
@@ -21694,9 +21628,9 @@ var init_dist2 = __esm(() => {
|
|
|
21694
21628
|
$Composer = composer.Composer;
|
|
21695
21629
|
$Document = Document.Document;
|
|
21696
21630
|
$Schema = Schema.Schema;
|
|
21697
|
-
$YAMLError =
|
|
21698
|
-
$YAMLParseError =
|
|
21699
|
-
$YAMLWarning =
|
|
21631
|
+
$YAMLError = errors3.YAMLError;
|
|
21632
|
+
$YAMLParseError = errors3.YAMLParseError;
|
|
21633
|
+
$YAMLWarning = errors3.YAMLWarning;
|
|
21700
21634
|
$Alias = Alias.Alias;
|
|
21701
21635
|
$isAlias = identity.isAlias;
|
|
21702
21636
|
$isCollection = identity.isCollection;
|
|
@@ -21724,7 +21658,7 @@ var init_dist2 = __esm(() => {
|
|
|
21724
21658
|
// ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.39/node_modules/@gobing-ai/ts-runtime/dist/config.js
|
|
21725
21659
|
var configSchema;
|
|
21726
21660
|
var init_config = __esm(() => {
|
|
21727
|
-
|
|
21661
|
+
init_dist();
|
|
21728
21662
|
init_zod();
|
|
21729
21663
|
configSchema = exports_external.object({
|
|
21730
21664
|
app: exports_external.object({
|
|
@@ -21835,8 +21769,14 @@ var init_file_system_node = () => {};
|
|
|
21835
21769
|
// ../../packages/publish-harness/src/index.ts
|
|
21836
21770
|
var exports_src = {};
|
|
21837
21771
|
__export(exports_src, {
|
|
21838
|
-
|
|
21772
|
+
trySelectors: () => trySelectors,
|
|
21773
|
+
resolveBrowserProfileDir: () => resolveBrowserProfileDir,
|
|
21774
|
+
launchPersistentBrowser: () => launchPersistentBrowser,
|
|
21775
|
+
FakeFileCliTransport: () => FakeFileCliTransport,
|
|
21776
|
+
FakeBrowserTransport: () => FakeBrowserTransport
|
|
21839
21777
|
});
|
|
21778
|
+
import { homedir } from "os";
|
|
21779
|
+
import { join } from "path";
|
|
21840
21780
|
|
|
21841
21781
|
class FakeFileCliTransport {
|
|
21842
21782
|
kind = "file-cli";
|
|
@@ -21873,10 +21813,96 @@ class FakeFileCliTransport {
|
|
|
21873
21813
|
}
|
|
21874
21814
|
}
|
|
21875
21815
|
|
|
21816
|
+
class FakeBrowserTransport {
|
|
21817
|
+
kind = "browser";
|
|
21818
|
+
driver;
|
|
21819
|
+
callLogs;
|
|
21820
|
+
nextResult;
|
|
21821
|
+
constructor(driver = "agent") {
|
|
21822
|
+
this.driver = driver;
|
|
21823
|
+
this.callLogs = [];
|
|
21824
|
+
}
|
|
21825
|
+
setNextResult(result) {
|
|
21826
|
+
this.nextResult = result;
|
|
21827
|
+
}
|
|
21828
|
+
async publish(payload) {
|
|
21829
|
+
this.callLogs.push({
|
|
21830
|
+
timestamp: new Date().toISOString(),
|
|
21831
|
+
payload
|
|
21832
|
+
});
|
|
21833
|
+
if (this.nextResult) {
|
|
21834
|
+
return this.nextResult;
|
|
21835
|
+
}
|
|
21836
|
+
return {
|
|
21837
|
+
ok: true,
|
|
21838
|
+
target: "fake-browser",
|
|
21839
|
+
url: "https://example.com/browser-draft",
|
|
21840
|
+
id: "fake-browser-id-123",
|
|
21841
|
+
message: "Published offline via FakeBrowserTransport",
|
|
21842
|
+
metadata: { driver: this.driver }
|
|
21843
|
+
};
|
|
21844
|
+
}
|
|
21845
|
+
getCallLogs() {
|
|
21846
|
+
return this.callLogs;
|
|
21847
|
+
}
|
|
21848
|
+
reset() {
|
|
21849
|
+
this.callLogs = [];
|
|
21850
|
+
this.nextResult = undefined;
|
|
21851
|
+
}
|
|
21852
|
+
}
|
|
21853
|
+
function resolveBrowserProfileDir(channel, override) {
|
|
21854
|
+
if (override && override.trim().length > 0) {
|
|
21855
|
+
const trimmed = override.trim();
|
|
21856
|
+
if (trimmed.startsWith("~/")) {
|
|
21857
|
+
return join(homedir(), trimmed.slice(2));
|
|
21858
|
+
}
|
|
21859
|
+
return trimmed;
|
|
21860
|
+
}
|
|
21861
|
+
return join(homedir(), ".config", "kk", "browser-profiles", channel);
|
|
21862
|
+
}
|
|
21863
|
+
async function trySelectors(page, selectors, options = {}) {
|
|
21864
|
+
const timeout = options.timeout ?? 5000;
|
|
21865
|
+
const visible = options.visible ?? true;
|
|
21866
|
+
for (const selector of selectors) {
|
|
21867
|
+
try {
|
|
21868
|
+
const locator = page.locator(selector).first();
|
|
21869
|
+
const attached = await locator.count() > 0;
|
|
21870
|
+
if (!attached) {
|
|
21871
|
+
continue;
|
|
21872
|
+
}
|
|
21873
|
+
if (visible) {
|
|
21874
|
+
const isVisible = await locator.isVisible({ timeout: Math.min(timeout, 2000) }).catch(() => false);
|
|
21875
|
+
if (!isVisible) {
|
|
21876
|
+
continue;
|
|
21877
|
+
}
|
|
21878
|
+
}
|
|
21879
|
+
return { found: true, selector };
|
|
21880
|
+
} catch {}
|
|
21881
|
+
}
|
|
21882
|
+
return { found: false, selector: null };
|
|
21883
|
+
}
|
|
21884
|
+
async function launchPersistentBrowser(opts) {
|
|
21885
|
+
let chromium;
|
|
21886
|
+
try {
|
|
21887
|
+
const playwright = await import("playwright");
|
|
21888
|
+
chromium = playwright.chromium;
|
|
21889
|
+
} catch (error51) {
|
|
21890
|
+
const reason = error51 instanceof Error ? error51.message : String(error51);
|
|
21891
|
+
throw new Error(`launchPersistentBrowser requires the playwright package on the caller's dependency tree: ${reason}`);
|
|
21892
|
+
}
|
|
21893
|
+
if (typeof chromium?.launchPersistentContext !== "function") {
|
|
21894
|
+
throw new Error("launchPersistentBrowser requires the playwright package on the caller's dependency tree: chromium.launchPersistentContext is missing");
|
|
21895
|
+
}
|
|
21896
|
+
return chromium.launchPersistentContext(opts.profileDir, {
|
|
21897
|
+
headless: opts.headless ?? false
|
|
21898
|
+
});
|
|
21899
|
+
}
|
|
21900
|
+
var init_src = () => {};
|
|
21901
|
+
|
|
21876
21902
|
// ../../plugins/publishings/surfdash-pub/src/index.ts
|
|
21877
|
-
import { existsSync as existsSync2 } from "fs";
|
|
21878
|
-
import { copyFile, cp } from "fs/promises";
|
|
21879
|
-
import { dirname as dirname2, isAbsolute, join, resolve, sep } from "path";
|
|
21903
|
+
import { existsSync as existsSync2, readFileSync as readFileSync2 } from "fs";
|
|
21904
|
+
import { copyFile, cp, writeFile } from "fs/promises";
|
|
21905
|
+
import { dirname as dirname2, isAbsolute, join as join2, resolve, sep } from "path";
|
|
21880
21906
|
import { parseArgs } from "util";
|
|
21881
21907
|
|
|
21882
21908
|
// ../../packages/kk-core/src/kinds.ts
|
|
@@ -21953,10 +21979,27 @@ var PluginManifestSchema = exports_external.object({
|
|
|
21953
21979
|
init_file_system_node();
|
|
21954
21980
|
init_config();
|
|
21955
21981
|
|
|
21982
|
+
// ../../node_modules/.bun/@gobing-ai+ts-utils@0.4.67/node_modules/@gobing-ai/ts-utils/dist/output.js
|
|
21983
|
+
var defaultStderrTarget;
|
|
21984
|
+
function processStream(name) {
|
|
21985
|
+
const proc = globalThis.process;
|
|
21986
|
+
const stream = proc?.[name];
|
|
21987
|
+
if (stream === undefined) {
|
|
21988
|
+
throw new Error(`No ${name} target available: set one via setDefaultOutputTargets or pass an explicit target`);
|
|
21989
|
+
}
|
|
21990
|
+
return stream;
|
|
21991
|
+
}
|
|
21992
|
+
function writeLine(message, target) {
|
|
21993
|
+
target.write(`${message}
|
|
21994
|
+
`);
|
|
21995
|
+
}
|
|
21996
|
+
function echoError(message, target = defaultStderrTarget ?? processStream("stderr")) {
|
|
21997
|
+
writeLine(message, target);
|
|
21998
|
+
}
|
|
21999
|
+
|
|
21956
22000
|
// ../../packages/kk-core/src/render-md.ts
|
|
21957
22001
|
if (false) {}
|
|
21958
22002
|
// ../../plugins/publishings/surfdash-pub/src/index.ts
|
|
21959
|
-
init_dist();
|
|
21960
22003
|
var TARGET = "surfdash";
|
|
21961
22004
|
var OPERATIONS = ["publish", "scaffold-locale", "sync"];
|
|
21962
22005
|
var SCAFFOLD_LOCALES = ["en", "ja"];
|
|
@@ -22146,9 +22189,9 @@ async function scaffoldLocale(options) {
|
|
|
22146
22189
|
if (!existsSync2(draftPath)) {
|
|
22147
22190
|
return fail(`sd translate reported success but the draft is missing: ${draftPath}`);
|
|
22148
22191
|
}
|
|
22149
|
-
const assetsDir =
|
|
22192
|
+
const assetsDir = join2(dirname2(postPath.postPath), "assets");
|
|
22150
22193
|
if (existsSync2(assetsDir)) {
|
|
22151
|
-
await cp(assetsDir,
|
|
22194
|
+
await cp(assetsDir, join2(dirname2(draftPath), "assets"), { recursive: true });
|
|
22152
22195
|
}
|
|
22153
22196
|
return ResultSchema.parse({
|
|
22154
22197
|
ok: true,
|
|
@@ -22160,6 +22203,21 @@ async function scaffoldLocale(options) {
|
|
|
22160
22203
|
return fail(`scaffold-locale transport error: ${error51 instanceof Error ? error51.message : String(error51)}`);
|
|
22161
22204
|
}
|
|
22162
22205
|
}
|
|
22206
|
+
function normalizeLocaleFrontmatter(markdown) {
|
|
22207
|
+
const lines = markdown.split(`
|
|
22208
|
+
`);
|
|
22209
|
+
const inFrontmatter = lines[0]?.trim() === "---";
|
|
22210
|
+
for (let i = 1;inFrontmatter && i < lines.length; i++) {
|
|
22211
|
+
if (lines[i]?.trim() === "---")
|
|
22212
|
+
break;
|
|
22213
|
+
if (/^canonical\s*:/.test(lines[i] ?? ""))
|
|
22214
|
+
lines[i] = "";
|
|
22215
|
+
else if (/^draft\s*:/.test(lines[i] ?? ""))
|
|
22216
|
+
lines[i] = "draft: false";
|
|
22217
|
+
}
|
|
22218
|
+
return lines.filter((line) => line !== "").join(`
|
|
22219
|
+
`);
|
|
22220
|
+
}
|
|
22163
22221
|
async function syncPost(options) {
|
|
22164
22222
|
const postPath = resolvePostPath(options);
|
|
22165
22223
|
if ("error" in postPath)
|
|
@@ -22171,6 +22229,16 @@ async function syncPost(options) {
|
|
|
22171
22229
|
const outsideRoot = postPathOutsideRoot(postPath.postPath, surfdashRoot);
|
|
22172
22230
|
if (outsideRoot)
|
|
22173
22231
|
return fail(outsideRoot);
|
|
22232
|
+
for (const locale of ["en", "ja"]) {
|
|
22233
|
+
const sibling = deriveLocaleDraftPath(postPath.postPath, locale);
|
|
22234
|
+
if (!sibling || !existsSync2(sibling))
|
|
22235
|
+
continue;
|
|
22236
|
+
const normalized = normalizeLocaleFrontmatter(readFileSync2(sibling, "utf-8"));
|
|
22237
|
+
if (normalized !== readFileSync2(sibling, "utf-8")) {
|
|
22238
|
+
await writeFile(sibling, normalized);
|
|
22239
|
+
echoError(`sync: normalized frontmatter for ${locale} sibling: ${sibling}`);
|
|
22240
|
+
}
|
|
22241
|
+
}
|
|
22174
22242
|
try {
|
|
22175
22243
|
const spawned = await spawnCli(["bun", "scripts/publish-orchestrator.ts", "sync", postPath.postPath], surfdashRoot);
|
|
22176
22244
|
if (spawned.exitCode !== 0) {
|
|
@@ -22198,22 +22266,22 @@ async function publishPost(payload) {
|
|
|
22198
22266
|
const dateStamp = runDate || today;
|
|
22199
22267
|
const titleSlug = slugify2(payload.content.title ?? "");
|
|
22200
22268
|
const slug = titleSlug ? `${dateStamp}-${titleSlug}` : `${dateStamp}-post`;
|
|
22201
|
-
const postDir =
|
|
22269
|
+
const postDir = join2(surfdashRoot, "content", "posts", "articles", locale, slug);
|
|
22202
22270
|
await createNodeFileSystem().ensureDir(postDir);
|
|
22203
22271
|
let imageFrontmatter;
|
|
22204
22272
|
const coverPath = payload.content.metadata?.coverImage;
|
|
22205
22273
|
if (typeof coverPath === "string" && existsSync2(coverPath)) {
|
|
22206
|
-
const assetsDir =
|
|
22274
|
+
const assetsDir = join2(postDir, "assets");
|
|
22207
22275
|
await createNodeFileSystem().ensureDir(assetsDir);
|
|
22208
22276
|
const coverName = `cover${coverPath.slice(coverPath.lastIndexOf("."))}`;
|
|
22209
|
-
await copyFile(coverPath,
|
|
22277
|
+
await copyFile(coverPath, join2(assetsDir, coverName));
|
|
22210
22278
|
imageFrontmatter = `./assets/${coverName}`;
|
|
22211
22279
|
}
|
|
22212
22280
|
const markdown = mapContentToSurfingMarkdown(payload.content, {
|
|
22213
22281
|
image: imageFrontmatter,
|
|
22214
22282
|
publishDate: runDate ? `${runDate.slice(0, 4)}-${runDate.slice(4, 6)}-${runDate.slice(6, 8)}` : undefined
|
|
22215
22283
|
});
|
|
22216
|
-
const filePath =
|
|
22284
|
+
const filePath = join2(postDir, "index.md");
|
|
22217
22285
|
try {
|
|
22218
22286
|
await createNodeFileSystem().writeFile(filePath, markdown);
|
|
22219
22287
|
const spawned = await spawnCli([postsurfingBin, "publish", filePath], surfdashRoot);
|
|
@@ -22230,7 +22298,7 @@ async function publishPost(payload) {
|
|
|
22230
22298
|
metadata: { postPath: filePath }
|
|
22231
22299
|
});
|
|
22232
22300
|
}
|
|
22233
|
-
const relPostDir =
|
|
22301
|
+
const relPostDir = join2("content", "posts", "articles", locale, slug);
|
|
22234
22302
|
const pushed = await pushPostGit(surfdashRoot, relPostDir, `content: daily AI news ${dateStamp} (zh)`);
|
|
22235
22303
|
if (!pushed.ok)
|
|
22236
22304
|
return fail(pushed.error);
|
|
@@ -22266,7 +22334,7 @@ class PostsurfingFileCliTransport {
|
|
|
22266
22334
|
}
|
|
22267
22335
|
function getPublishTransport() {
|
|
22268
22336
|
if (process.env.KNOWLEDGE_KIT_PUBLISH_TRANSPORT === "fake") {
|
|
22269
|
-
const { FakeFileCliTransport: FakeFileCliTransport2 } = __toCommonJS(exports_src);
|
|
22337
|
+
const { FakeFileCliTransport: FakeFileCliTransport2 } = (init_src(), __toCommonJS(exports_src));
|
|
22270
22338
|
return new FakeFileCliTransport2;
|
|
22271
22339
|
}
|
|
22272
22340
|
return new PostsurfingFileCliTransport;
|
|
@@ -22315,6 +22383,7 @@ export {
|
|
|
22315
22383
|
slugify2 as slugify,
|
|
22316
22384
|
pushPostGit,
|
|
22317
22385
|
processPublishIO,
|
|
22386
|
+
normalizeLocaleFrontmatter,
|
|
22318
22387
|
mapContentToSurfingMarkdown,
|
|
22319
22388
|
main2 as main,
|
|
22320
22389
|
getPublishTransport,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { existsSync } from 'node:fs';
|
|
2
|
-
import { copyFile, cp } from 'node:fs/promises';
|
|
1
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
2
|
+
import { copyFile, cp, writeFile } from 'node:fs/promises';
|
|
3
3
|
import { dirname, isAbsolute, join, resolve, sep } from 'node:path';
|
|
4
4
|
import { parseArgs } from 'node:util';
|
|
5
5
|
import { type Content, ContentSchema, type Result, ResultSchema } from '@gobing-ai/kk-core';
|
|
@@ -350,6 +350,25 @@ async function scaffoldLocale(options: SurfdashPubOptions): Promise<Result> {
|
|
|
350
350
|
* `bun scripts/publish-orchestrator.ts sync <postPath>` inside the surfdash checkout
|
|
351
351
|
* and returns ok/fail with stderr on failure.
|
|
352
352
|
*/
|
|
353
|
+
/**
|
|
354
|
+
* Deterministic frontmatter normalization for locale siblings before CMS sync
|
|
355
|
+
* (2026-09-16 hreflang feedback): the site's alternates builder reads published
|
|
356
|
+
* disk siblings, so each non-primary locale must end `draft: false` and must not
|
|
357
|
+
* carry a stale cross-locale `canonical` (the translation agent sometimes copies
|
|
358
|
+
* zh frontmatter verbatim). Line-based — no YAML lib in this plugin. Backstop
|
|
359
|
+
* for the agent prompt; safe because sync always runs after the agent's edit.
|
|
360
|
+
*/
|
|
361
|
+
export function normalizeLocaleFrontmatter(markdown: string): string {
|
|
362
|
+
const lines = markdown.split('\n');
|
|
363
|
+
const inFrontmatter = lines[0]?.trim() === '---';
|
|
364
|
+
for (let i = 1; inFrontmatter && i < lines.length; i++) {
|
|
365
|
+
if (lines[i]?.trim() === '---') break;
|
|
366
|
+
if (/^canonical\s*:/.test(lines[i] ?? '')) lines[i] = '';
|
|
367
|
+
else if (/^draft\s*:/.test(lines[i] ?? '')) lines[i] = 'draft: false';
|
|
368
|
+
}
|
|
369
|
+
return lines.filter((line) => line !== '').join('\n');
|
|
370
|
+
}
|
|
371
|
+
|
|
353
372
|
async function syncPost(options: SurfdashPubOptions): Promise<Result> {
|
|
354
373
|
const postPath = resolvePostPath(options);
|
|
355
374
|
if ('error' in postPath) return fail(postPath.error);
|
|
@@ -361,6 +380,17 @@ async function syncPost(options: SurfdashPubOptions): Promise<Result> {
|
|
|
361
380
|
const outsideRoot = postPathOutsideRoot(postPath.postPath, surfdashRoot);
|
|
362
381
|
if (outsideRoot) return fail(outsideRoot);
|
|
363
382
|
|
|
383
|
+
// Normalize en/ja siblings (draft flag + stale canonical) before the orchestrator syncs them.
|
|
384
|
+
for (const locale of ['en', 'ja'] as const) {
|
|
385
|
+
const sibling = deriveLocaleDraftPath(postPath.postPath, locale);
|
|
386
|
+
if (!sibling || !existsSync(sibling)) continue;
|
|
387
|
+
const normalized = normalizeLocaleFrontmatter(readFileSync(sibling, 'utf-8'));
|
|
388
|
+
if (normalized !== readFileSync(sibling, 'utf-8')) {
|
|
389
|
+
await writeFile(sibling, normalized);
|
|
390
|
+
echoError(`sync: normalized frontmatter for ${locale} sibling: ${sibling}`);
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
|
|
364
394
|
try {
|
|
365
395
|
const spawned = await spawnCli(
|
|
366
396
|
['bun', 'scripts/publish-orchestrator.ts', 'sync', postPath.postPath],
|