@gobing-ai/knowledge-kit 0.0.13 → 0.0.14
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 +20 -0
- package/package.json +1 -1
- package/plugins/generations/content-gen/dist/index.js +20 -0
- package/plugins/generations/core-facts-gen/dist/index.js +20 -0
- package/plugins/generations/daily-article-gen/dist/index.js +29 -1
- package/plugins/generations/daily-article-gen/src/index.ts +13 -1
- package/plugins/generations/dailynews-gen/dist/index.js +20 -0
- package/plugins/generations/episode-plan-gen/dist/index.js +24 -0
- package/plugins/generations/episode-plan-gen/src/index.ts +11 -0
- package/plugins/generations/image-gen/dist/index.js +2296 -53
- package/plugins/generations/image-gen/src/providers/agnes.ts +110 -0
- package/plugins/generations/image-gen/src/providers/azure.ts +153 -0
- package/plugins/generations/image-gen/src/providers/codex-cli.ts +170 -0
- package/plugins/generations/image-gen/src/providers/dashscope.ts +485 -0
- package/plugins/generations/image-gen/src/providers/google.ts +268 -0
- package/plugins/generations/image-gen/src/providers/huggingface.ts +59 -0
- package/plugins/generations/image-gen/src/providers/jimeng.ts +259 -0
- package/plugins/generations/image-gen/src/providers/minimax.ts +171 -0
- package/plugins/generations/image-gen/src/providers/openai.ts +319 -0
- package/plugins/generations/image-gen/src/providers/openrouter.ts +257 -0
- package/plugins/generations/image-gen/src/providers/refs.ts +24 -0
- package/plugins/generations/image-gen/src/providers/replicate.ts +279 -0
- package/plugins/generations/image-gen/src/providers/seedream.ts +1 -1
- package/plugins/generations/image-gen/src/providers/types.ts +52 -51
- package/plugins/generations/image-gen/src/providers/zai.ts +237 -0
- package/plugins/generations/news-report-gen/dist/index.js +22193 -0
- package/plugins/generations/news-report-gen/package.json +17 -0
- package/plugins/generations/news-report-gen/plugin.json +7 -0
- package/plugins/generations/news-report-gen/src/index.ts +308 -0
- package/plugins/generations/news-report-gen/tsconfig.json +4 -0
- package/plugins/generations/omni-voice-gen/Makefile +14 -0
- package/plugins/generations/omni-voice-gen/README.md +112 -0
- package/plugins/generations/omni-voice-gen/bin/omni-voice-gen +2 -0
- package/plugins/generations/omni-voice-gen/dist/omni-voice-gen-prr8skpb. +2 -0
- package/plugins/generations/omni-voice-gen/dist/omni-voice-gen.js +6 -0
- package/plugins/generations/omni-voice-gen/plugin.json +6 -0
- package/plugins/generations/omni-voice-gen/profiles.json +12 -0
- package/plugins/generations/omni-voice-gen/pyproject.toml +25 -0
- package/plugins/generations/omni-voice-gen/scripts/coverage_gate.py +74 -0
- package/plugins/generations/omni-voice-gen/src/omni_voice_gen/__init__.py +1 -0
- package/plugins/generations/omni-voice-gen/src/omni_voice_gen/__main__.py +39 -0
- package/plugins/generations/omni-voice-gen/src/omni_voice_gen/audio.py +190 -0
- package/plugins/generations/omni-voice-gen/src/omni_voice_gen/backend.py +150 -0
- package/plugins/generations/omni-voice-gen/src/omni_voice_gen/contract.py +76 -0
- package/plugins/generations/omni-voice-gen/src/omni_voice_gen/mp3.py +60 -0
- package/plugins/generations/omni-voice-gen/src/omni_voice_gen/pipeline.py +289 -0
- package/plugins/generations/omni-voice-gen/src/omni_voice_gen/profiles.py +100 -0
- package/plugins/generations/omni-voice-gen/src/omni_voice_gen/qc.py +234 -0
- package/plugins/generations/omni-voice-gen/src/omni_voice_gen/voicescript.py +352 -0
- package/plugins/generations/omni-voice-gen/uv.lock +3510 -0
- package/plugins/generations/voice-gen/dist/index.js +30 -2
- package/plugins/generations/voice-gen/src/index.ts +16 -1
- package/plugins/generations/voice-gen/src/voicebox-client.ts +3 -1
- package/plugins/ingestions/aihot-ingest/dist/index.js +20 -0
- package/plugins/ingestions/horizon-ingest/dist/index.js +20 -0
- package/plugins/ingestions/last30days-ingest/dist/index.js +20 -0
- package/plugins/ingestions/web-search/dist/index.js +20 -0
- package/plugins/kk/commands/image-extract.md +40 -0
- package/plugins/kk/commands/image-generate.md +18 -1
- package/plugins/kk/plugin.json +1 -1
- package/plugins/kk/skills/image-authoring/SKILL.md +10 -3
- package/plugins/kk/skills/image-authoring/references/format-drafting.md +57 -0
- package/plugins/kk/skills/image-authoring/references/style-extraction.md +14 -9
- package/plugins/kk/workflows/kk-daily-ai-voice.yaml +130 -30
- package/plugins/publishings/emdash-pub/dist/index.js +20 -0
- package/plugins/publishings/podcast-pub/dist/index.js +57 -3
- package/plugins/publishings/podcast-pub/src/index.ts +18 -2
- package/plugins/publishings/podcast-pub/src/show-notes.ts +56 -9
- package/plugins/publishings/qiita-pub/dist/index.js +20 -0
- package/plugins/publishings/surfdash-pub/dist/index.js +96 -6
- package/plugins/publishings/surfdash-pub/src/index.ts +109 -9
- package/plugins/publishings/zenn-pub/dist/index.js +20 -0
- package/plugins/sp/scripts/batch-preflight.mjs +346 -0
- package/plugins/sp/scripts/batch-preflight.ts +459 -0
- package/plugins/sp/scripts/daily-summary/daily-summary.mjs +615 -0
- package/plugins/sp/scripts/daily-summary/daily-summary.ts +846 -0
- package/plugins/sp/scripts/daily-summary/logger.ts +28 -0
- package/plugins/sp/scripts/dogfood-testing/detect-pipeline-driving.mjs +223 -0
- package/plugins/sp/scripts/dogfood-testing/detect-pipeline-driving.ts +367 -0
- package/plugins/sp/scripts/dogfood-testing/validate-report.mjs +132 -0
- package/plugins/sp/scripts/dogfood-testing/validate-report.ts +169 -0
- package/plugins/sp/scripts/feature-dev-precheck.mjs +171 -0
- package/plugins/sp/scripts/feature-dev-precheck.ts +238 -0
- package/plugins/sp/scripts/feature-sync-bounded.mjs +285 -0
- package/plugins/sp/scripts/feature-sync-bounded.ts +478 -0
- package/plugins/sp/scripts/history-anatomy-cache.mjs +902 -0
- package/plugins/sp/scripts/history-anatomy-cache.ts +1028 -0
- package/plugins/sp/scripts/idea-handoff.mjs +22 -0
- package/plugins/sp/scripts/idea-handoff.ts +44 -0
- package/plugins/sp/scripts/inline-pipeline-parity-check.ts +185 -0
- package/plugins/sp/scripts/inline-run-setup.ts +198 -0
- package/plugins/sp/scripts/pr-reviewing.mjs +769 -0
- package/plugins/sp/scripts/pr-reviewing.ts +925 -0
- package/plugins/sp/scripts/quality-gate.mjs +179 -0
- package/plugins/sp/scripts/quality-gate.ts +217 -0
- package/plugins/sp/scripts/script-contract-check.ts +319 -0
- package/plugins/sp/scripts/stage-registry-adapter.ts +1533 -0
- package/plugins/sp/scripts/surface-drift-inventory.ts +929 -0
- package/plugins/sp/scripts/task-evidence-precheck.ts +181 -0
- package/plugins/sp/scripts/task-size-precheck.ts +175 -0
- package/plugins/sp/scripts/transition-shim-check.ts +238 -0
- package/plugins/sp/scripts/validate-commands.ts +689 -0
- package/plugins/sp/scripts/validate-flag-contracts.ts +878 -0
- package/plugins/sp/scripts/verify-answer-lint.ts +530 -0
- package/plugins/sp/scripts/workflow-step-profile.mjs +316 -0
- package/plugins/sp/scripts/workflow-step-profile.ts +456 -0
- package/plugins/sp/scripts/wrapup-steps.mjs +373 -0
- package/plugins/sp/scripts/wrapup-steps.ts +466 -0
|
@@ -21848,6 +21848,26 @@ var ResultSchema = exports_external.object({
|
|
|
21848
21848
|
metadata: exports_external.record(exports_external.string(), exports_external.unknown()).optional()
|
|
21849
21849
|
});
|
|
21850
21850
|
var DocListSchema = exports_external.array(DocSchema);
|
|
21851
|
+
var omniVoiceGenContentSchema = ContentSchema.extend({
|
|
21852
|
+
format: exports_external.literal("audio"),
|
|
21853
|
+
metadata: exports_external.looseObject({
|
|
21854
|
+
generator: exports_external.literal("kk:omni-voice-gen"),
|
|
21855
|
+
audioPath: exports_external.string(),
|
|
21856
|
+
duration: exports_external.number(),
|
|
21857
|
+
segments: exports_external.array(exports_external.looseObject({
|
|
21858
|
+
generationId: exports_external.string(),
|
|
21859
|
+
profile: exports_external.string(),
|
|
21860
|
+
speaker: exports_external.string().optional(),
|
|
21861
|
+
emotion: exports_external.string().optional(),
|
|
21862
|
+
duration: exports_external.number(),
|
|
21863
|
+
verifyRetries: exports_external.number(),
|
|
21864
|
+
transcription: exports_external.string().optional(),
|
|
21865
|
+
loudnessDip: exports_external.boolean().optional()
|
|
21866
|
+
})),
|
|
21867
|
+
mp3Path: exports_external.string().optional(),
|
|
21868
|
+
qc: exports_external.record(exports_external.string(), exports_external.unknown()).optional()
|
|
21869
|
+
})
|
|
21870
|
+
});
|
|
21851
21871
|
|
|
21852
21872
|
// ../../packages/kk-core/src/kinds.ts
|
|
21853
21873
|
var PLUGIN_KINDS = ["ingestion", "generator", "publish"];
|
|
@@ -21914,6 +21914,26 @@ var ResultSchema = exports_external.object({
|
|
|
21914
21914
|
metadata: exports_external.record(exports_external.string(), exports_external.unknown()).optional()
|
|
21915
21915
|
});
|
|
21916
21916
|
var DocListSchema = exports_external.array(DocSchema);
|
|
21917
|
+
var omniVoiceGenContentSchema = ContentSchema.extend({
|
|
21918
|
+
format: exports_external.literal("audio"),
|
|
21919
|
+
metadata: exports_external.looseObject({
|
|
21920
|
+
generator: exports_external.literal("kk:omni-voice-gen"),
|
|
21921
|
+
audioPath: exports_external.string(),
|
|
21922
|
+
duration: exports_external.number(),
|
|
21923
|
+
segments: exports_external.array(exports_external.looseObject({
|
|
21924
|
+
generationId: exports_external.string(),
|
|
21925
|
+
profile: exports_external.string(),
|
|
21926
|
+
speaker: exports_external.string().optional(),
|
|
21927
|
+
emotion: exports_external.string().optional(),
|
|
21928
|
+
duration: exports_external.number(),
|
|
21929
|
+
verifyRetries: exports_external.number(),
|
|
21930
|
+
transcription: exports_external.string().optional(),
|
|
21931
|
+
loudnessDip: exports_external.boolean().optional()
|
|
21932
|
+
})),
|
|
21933
|
+
mp3Path: exports_external.string().optional(),
|
|
21934
|
+
qc: exports_external.record(exports_external.string(), exports_external.unknown()).optional()
|
|
21935
|
+
})
|
|
21936
|
+
});
|
|
21917
21937
|
|
|
21918
21938
|
// ../../packages/kk-core/src/kinds.ts
|
|
21919
21939
|
var PLUGIN_KINDS = ["ingestion", "generator", "publish"];
|
|
@@ -22043,7 +22063,59 @@ async function spawnCli(cmd, cwd) {
|
|
|
22043
22063
|
return { exitCode, stdout, stderr };
|
|
22044
22064
|
}
|
|
22045
22065
|
function cliErrorText(spawned) {
|
|
22046
|
-
return spawned.stderr.trim()
|
|
22066
|
+
return [spawned.stderr.trim(), spawned.stdout.trim()].filter((part) => part !== "").join(`
|
|
22067
|
+
`) || "Unknown error";
|
|
22068
|
+
}
|
|
22069
|
+
function withEmdashTokenHint(errText) {
|
|
22070
|
+
return /INVALID_TOKEN|API error 401/.test(errText) ? `${errText} \u2014 hint: regenerate the EmDash token (surfing.salty.vip admin console) and update EMDASH_API_TOKEN in ~/.config/kk/config.yaml` : errText;
|
|
22071
|
+
}
|
|
22072
|
+
async function pushPostGit(surfdashRoot, relPostDir, message) {
|
|
22073
|
+
const branch = await spawnCli(["git", "rev-parse", "--abbrev-ref", "HEAD"], surfdashRoot);
|
|
22074
|
+
if (branch.exitCode !== 0)
|
|
22075
|
+
return { ok: false, error: `surfdash git branch check failed: ${cliErrorText(branch)}` };
|
|
22076
|
+
const branchName = branch.stdout.trim();
|
|
22077
|
+
if (branchName !== "main") {
|
|
22078
|
+
return {
|
|
22079
|
+
ok: false,
|
|
22080
|
+
error: `surfdash checkout is on '${branchName}', not 'main' \u2014 deploy.yml only builds main; refusing to push from a feature branch`
|
|
22081
|
+
};
|
|
22082
|
+
}
|
|
22083
|
+
const add = await spawnCli(["git", "add", "--", relPostDir], surfdashRoot);
|
|
22084
|
+
if (add.exitCode !== 0)
|
|
22085
|
+
return { ok: false, error: `surfdash git add failed: ${cliErrorText(add)}` };
|
|
22086
|
+
const staged = await spawnCli(["git", "diff", "--cached", "--quiet", "--", relPostDir], surfdashRoot);
|
|
22087
|
+
if (staged.exitCode === 0) {
|
|
22088
|
+
const unpushed = await spawnCli(["git", "diff", "--quiet", "origin/main..HEAD", "--", relPostDir], surfdashRoot);
|
|
22089
|
+
if (unpushed.exitCode === 0) {
|
|
22090
|
+
const hash3 = await spawnCli(["git", "rev-parse", "--short", "HEAD"], surfdashRoot);
|
|
22091
|
+
return { ok: true, hash: hash3.stdout.trim() || "unknown" };
|
|
22092
|
+
}
|
|
22093
|
+
} else {
|
|
22094
|
+
const commit = await spawnCli(["git", "commit", "-m", message, "--", relPostDir], surfdashRoot);
|
|
22095
|
+
if (commit.exitCode !== 0)
|
|
22096
|
+
return { ok: false, error: `surfdash git commit failed: ${cliErrorText(commit)}` };
|
|
22097
|
+
}
|
|
22098
|
+
const push = await spawnCli(["git", "push", "origin", "main"], surfdashRoot);
|
|
22099
|
+
if (push.exitCode !== 0) {
|
|
22100
|
+
return {
|
|
22101
|
+
ok: false,
|
|
22102
|
+
error: `surfdash git push failed (deploy.yml deploys on push to main): ${cliErrorText(push)}`
|
|
22103
|
+
};
|
|
22104
|
+
}
|
|
22105
|
+
const hash2 = await spawnCli(["git", "rev-parse", "--short", "HEAD"], surfdashRoot);
|
|
22106
|
+
return { ok: true, hash: hash2.stdout.trim() || "unknown" };
|
|
22107
|
+
}
|
|
22108
|
+
async function awaitArticleLive(url2, timeoutMs = 180000, intervalMs = 1e4) {
|
|
22109
|
+
const deadline = Date.now() + timeoutMs;
|
|
22110
|
+
while (Date.now() < deadline) {
|
|
22111
|
+
try {
|
|
22112
|
+
const resp = await fetch(url2, { redirect: "follow", signal: AbortSignal.timeout(5000) });
|
|
22113
|
+
if (resp.ok)
|
|
22114
|
+
return true;
|
|
22115
|
+
} catch {}
|
|
22116
|
+
await Bun.sleep(intervalMs);
|
|
22117
|
+
}
|
|
22118
|
+
return false;
|
|
22047
22119
|
}
|
|
22048
22120
|
async function scaffoldLocale(options) {
|
|
22049
22121
|
const postPath = resolvePostPath(options);
|
|
@@ -22102,7 +22174,7 @@ async function syncPost(options) {
|
|
|
22102
22174
|
try {
|
|
22103
22175
|
const spawned = await spawnCli(["bun", "scripts/publish-orchestrator.ts", "sync", postPath.postPath], surfdashRoot);
|
|
22104
22176
|
if (spawned.exitCode !== 0) {
|
|
22105
|
-
return fail(`publish-orchestrator sync failed (exit ${spawned.exitCode}): ${cliErrorText(spawned)}`);
|
|
22177
|
+
return fail(`publish-orchestrator sync failed (exit ${spawned.exitCode}): ${withEmdashTokenHint(cliErrorText(spawned))}`);
|
|
22106
22178
|
}
|
|
22107
22179
|
return ResultSchema.parse({
|
|
22108
22180
|
ok: true,
|
|
@@ -22146,14 +22218,29 @@ async function publishPost(payload) {
|
|
|
22146
22218
|
await createNodeFileSystem().writeFile(filePath, markdown);
|
|
22147
22219
|
const spawned = await spawnCli([postsurfingBin, "publish", filePath], surfdashRoot);
|
|
22148
22220
|
if (spawned.exitCode !== 0) {
|
|
22149
|
-
return fail(`postsurfing CLI failed (exit ${spawned.exitCode}): ${cliErrorText(spawned)}`);
|
|
22221
|
+
return fail(`postsurfing CLI failed (exit ${spawned.exitCode}): ${withEmdashTokenHint(cliErrorText(spawned))}`);
|
|
22222
|
+
}
|
|
22223
|
+
const articleUrl = `${(process.env.SURFDASH_URL ?? "https://surfing.salty.vip").replace(/\/$/, "")}/${locale}/posts/${slug}`;
|
|
22224
|
+
if (process.env.SURFDASH_AUTO_PUSH === "0") {
|
|
22225
|
+
return ResultSchema.parse({
|
|
22226
|
+
ok: true,
|
|
22227
|
+
target: TARGET,
|
|
22228
|
+
url: articleUrl,
|
|
22229
|
+
message: "Published via postsurfing CLI (auto-push disabled)",
|
|
22230
|
+
metadata: { postPath: filePath }
|
|
22231
|
+
});
|
|
22150
22232
|
}
|
|
22233
|
+
const relPostDir = join("content", "posts", "articles", locale, slug);
|
|
22234
|
+
const pushed = await pushPostGit(surfdashRoot, relPostDir, `content: daily AI news ${dateStamp} (zh)`);
|
|
22235
|
+
if (!pushed.ok)
|
|
22236
|
+
return fail(pushed.error);
|
|
22237
|
+
const live = await awaitArticleLive(articleUrl);
|
|
22151
22238
|
return ResultSchema.parse({
|
|
22152
22239
|
ok: true,
|
|
22153
22240
|
target: TARGET,
|
|
22154
|
-
url:
|
|
22155
|
-
message: "Published
|
|
22156
|
-
metadata: { postPath: filePath }
|
|
22241
|
+
url: articleUrl,
|
|
22242
|
+
message: live ? "Published, committed, pushed, and live on the site" : "Published and pushed; URL not live within the verify window \u2014 check the surfdash deploy workflow",
|
|
22243
|
+
metadata: { postPath: filePath, gitCommit: pushed.hash, live }
|
|
22157
22244
|
});
|
|
22158
22245
|
} catch (err) {
|
|
22159
22246
|
return fail(`Postsurfing transport error: ${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -22224,10 +22311,13 @@ if (import.meta.main) {
|
|
|
22224
22311
|
process.exit(await main2());
|
|
22225
22312
|
}
|
|
22226
22313
|
export {
|
|
22314
|
+
withEmdashTokenHint,
|
|
22227
22315
|
slugify2 as slugify,
|
|
22316
|
+
pushPostGit,
|
|
22228
22317
|
processPublishIO,
|
|
22229
22318
|
mapContentToSurfingMarkdown,
|
|
22230
22319
|
main2 as main,
|
|
22231
22320
|
getPublishTransport,
|
|
22321
|
+
awaitArticleLive,
|
|
22232
22322
|
PostsurfingFileCliTransport
|
|
22233
22323
|
};
|
|
@@ -210,9 +210,85 @@ async function spawnCli(cmd: string[], cwd: string): Promise<CliSpawnResult> {
|
|
|
210
210
|
return { exitCode, stdout, stderr };
|
|
211
211
|
}
|
|
212
212
|
|
|
213
|
-
/**
|
|
213
|
+
/** Error text for a failed CLI spawn — both streams concatenated: postsurfing streams the
|
|
214
|
+
* failing stage's API error (e.g. 401 INVALID_TOKEN) on stdout while bun stacks land on stderr. */
|
|
214
215
|
function cliErrorText(spawned: CliSpawnResult): string {
|
|
215
|
-
return spawned.stderr.trim()
|
|
216
|
+
return [spawned.stderr.trim(), spawned.stdout.trim()].filter((part) => part !== '').join('\n') || 'Unknown error';
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/** The EmDash CMS token in kk config expires periodically; map the API's 401 to the fix. */
|
|
220
|
+
export function withEmdashTokenHint(errText: string): string {
|
|
221
|
+
return /INVALID_TOKEN|API error 401/.test(errText)
|
|
222
|
+
? `${errText} — hint: regenerate the EmDash token (surfing.salty.vip admin console) and update EMDASH_API_TOKEN in ~/.config/kk/config.yaml`
|
|
223
|
+
: errText;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/** Outcome of {@link pushPostGit} — the union keeps fail-loud errors typed at the call site. */
|
|
227
|
+
export type GitPushOutcome = { ok: true; hash: string } | { ok: false; error: string };
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* Commits the published post path and pushes to the remote. Production deploys run
|
|
231
|
+
* from surfdash's `deploy.yml` on every push to `main` — the publishing FSM itself
|
|
232
|
+
* never touches git, so without this step the article 404s until a manual commit.
|
|
233
|
+
* Committing with a pathspec (`git commit -- <path>`) keeps unrelated staged files
|
|
234
|
+
* out of the publish commit. Fails loud on branch/commit/push errors.
|
|
235
|
+
*/
|
|
236
|
+
export async function pushPostGit(surfdashRoot: string, relPostDir: string, message: string): Promise<GitPushOutcome> {
|
|
237
|
+
const branch = await spawnCli(['git', 'rev-parse', '--abbrev-ref', 'HEAD'], surfdashRoot);
|
|
238
|
+
if (branch.exitCode !== 0) return { ok: false, error: `surfdash git branch check failed: ${cliErrorText(branch)}` };
|
|
239
|
+
const branchName = branch.stdout.trim();
|
|
240
|
+
if (branchName !== 'main') {
|
|
241
|
+
return {
|
|
242
|
+
ok: false,
|
|
243
|
+
error: `surfdash checkout is on '${branchName}', not 'main' — deploy.yml only builds main; refusing to push from a feature branch`,
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
const add = await spawnCli(['git', 'add', '--', relPostDir], surfdashRoot);
|
|
247
|
+
if (add.exitCode !== 0) return { ok: false, error: `surfdash git add failed: ${cliErrorText(add)}` };
|
|
248
|
+
// Idempotent retry: post content identical to HEAD stages nothing. Only push when
|
|
249
|
+
// origin lacks commits touching this post; a clean post means it's already live.
|
|
250
|
+
const staged = await spawnCli(['git', 'diff', '--cached', '--quiet', '--', relPostDir], surfdashRoot);
|
|
251
|
+
if (staged.exitCode === 0) {
|
|
252
|
+
const unpushed = await spawnCli(
|
|
253
|
+
['git', 'diff', '--quiet', 'origin/main..HEAD', '--', relPostDir],
|
|
254
|
+
surfdashRoot,
|
|
255
|
+
);
|
|
256
|
+
if (unpushed.exitCode === 0) {
|
|
257
|
+
const hash = await spawnCli(['git', 'rev-parse', '--short', 'HEAD'], surfdashRoot);
|
|
258
|
+
return { ok: true, hash: hash.stdout.trim() || 'unknown' };
|
|
259
|
+
}
|
|
260
|
+
} else {
|
|
261
|
+
const commit = await spawnCli(['git', 'commit', '-m', message, '--', relPostDir], surfdashRoot);
|
|
262
|
+
if (commit.exitCode !== 0) return { ok: false, error: `surfdash git commit failed: ${cliErrorText(commit)}` };
|
|
263
|
+
}
|
|
264
|
+
const push = await spawnCli(['git', 'push', 'origin', 'main'], surfdashRoot);
|
|
265
|
+
if (push.exitCode !== 0) {
|
|
266
|
+
return {
|
|
267
|
+
ok: false,
|
|
268
|
+
error: `surfdash git push failed (deploy.yml deploys on push to main): ${cliErrorText(push)}`,
|
|
269
|
+
};
|
|
270
|
+
}
|
|
271
|
+
const hash = await spawnCli(['git', 'rev-parse', '--short', 'HEAD'], surfdashRoot);
|
|
272
|
+
return { ok: true, hash: hash.stdout.trim() || 'unknown' };
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
/**
|
|
276
|
+
* Polls the article URL until the CDN serves it (deploy.yml build latency). Push
|
|
277
|
+
* acceptance is the authoritative publish signal, so an unverified URL is reported
|
|
278
|
+
* in the result message rather than failing the publish.
|
|
279
|
+
*/
|
|
280
|
+
export async function awaitArticleLive(url: string, timeoutMs = 180_000, intervalMs = 10_000): Promise<boolean> {
|
|
281
|
+
const deadline = Date.now() + timeoutMs;
|
|
282
|
+
while (Date.now() < deadline) {
|
|
283
|
+
try {
|
|
284
|
+
const resp = await fetch(url, { redirect: 'follow', signal: AbortSignal.timeout(5_000) });
|
|
285
|
+
if (resp.ok) return true;
|
|
286
|
+
} catch {
|
|
287
|
+
// network blips during CI deploy — keep polling until the deadline
|
|
288
|
+
}
|
|
289
|
+
await Bun.sleep(intervalMs);
|
|
290
|
+
}
|
|
291
|
+
return false;
|
|
216
292
|
}
|
|
217
293
|
|
|
218
294
|
/**
|
|
@@ -291,7 +367,9 @@ async function syncPost(options: SurfdashPubOptions): Promise<Result> {
|
|
|
291
367
|
surfdashRoot,
|
|
292
368
|
);
|
|
293
369
|
if (spawned.exitCode !== 0) {
|
|
294
|
-
return fail(
|
|
370
|
+
return fail(
|
|
371
|
+
`publish-orchestrator sync failed (exit ${spawned.exitCode}): ${withEmdashTokenHint(cliErrorText(spawned))}`,
|
|
372
|
+
);
|
|
295
373
|
}
|
|
296
374
|
return ResultSchema.parse({
|
|
297
375
|
ok: true,
|
|
@@ -352,17 +430,39 @@ async function publishPost(payload: PublishTransportPayload): Promise<Result> {
|
|
|
352
430
|
const spawned = await spawnCli([postsurfingBin, 'publish', filePath], surfdashRoot);
|
|
353
431
|
|
|
354
432
|
if (spawned.exitCode !== 0) {
|
|
355
|
-
return fail(
|
|
433
|
+
return fail(
|
|
434
|
+
`postsurfing CLI failed (exit ${spawned.exitCode}): ${withEmdashTokenHint(cliErrorText(spawned))}`,
|
|
435
|
+
);
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
// Deploy seam: commit + push the post so deploy.yml builds it, then wait for
|
|
439
|
+
// the live URL — downstream show-notes advertise a real page, not a 404.
|
|
440
|
+
// Tests (and offline runs) opt out via SURFDASH_AUTO_PUSH=0.
|
|
441
|
+
const articleUrl = `${(process.env.SURFDASH_URL ?? 'https://surfing.salty.vip').replace(/\/$/, '')}/${locale}/posts/${slug}`;
|
|
442
|
+
if (process.env.SURFDASH_AUTO_PUSH === '0') {
|
|
443
|
+
return ResultSchema.parse({
|
|
444
|
+
ok: true,
|
|
445
|
+
target: TARGET,
|
|
446
|
+
url: articleUrl,
|
|
447
|
+
message: 'Published via postsurfing CLI (auto-push disabled)',
|
|
448
|
+
// Absolute post path lets downstream steps (locale translation + CMS sync)
|
|
449
|
+
// derive the surfdash checkout root without extra configuration.
|
|
450
|
+
metadata: { postPath: filePath },
|
|
451
|
+
});
|
|
356
452
|
}
|
|
453
|
+
const relPostDir = join('content', 'posts', 'articles', locale, slug);
|
|
454
|
+
const pushed = await pushPostGit(surfdashRoot, relPostDir, `content: daily AI news ${dateStamp} (zh)`);
|
|
455
|
+
if (!pushed.ok) return fail(pushed.error);
|
|
456
|
+
const live = await awaitArticleLive(articleUrl);
|
|
357
457
|
|
|
358
458
|
return ResultSchema.parse({
|
|
359
459
|
ok: true,
|
|
360
460
|
target: TARGET,
|
|
361
|
-
url:
|
|
362
|
-
message:
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
metadata: { postPath: filePath },
|
|
461
|
+
url: articleUrl,
|
|
462
|
+
message: live
|
|
463
|
+
? 'Published, committed, pushed, and live on the site'
|
|
464
|
+
: 'Published and pushed; URL not live within the verify window — check the surfdash deploy workflow',
|
|
465
|
+
metadata: { postPath: filePath, gitCommit: pushed.hash, live },
|
|
366
466
|
});
|
|
367
467
|
} catch (err: unknown) {
|
|
368
468
|
return fail(`Postsurfing transport error: ${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -21849,6 +21849,26 @@ var ResultSchema = exports_external.object({
|
|
|
21849
21849
|
metadata: exports_external.record(exports_external.string(), exports_external.unknown()).optional()
|
|
21850
21850
|
});
|
|
21851
21851
|
var DocListSchema = exports_external.array(DocSchema);
|
|
21852
|
+
var omniVoiceGenContentSchema = ContentSchema.extend({
|
|
21853
|
+
format: exports_external.literal("audio"),
|
|
21854
|
+
metadata: exports_external.looseObject({
|
|
21855
|
+
generator: exports_external.literal("kk:omni-voice-gen"),
|
|
21856
|
+
audioPath: exports_external.string(),
|
|
21857
|
+
duration: exports_external.number(),
|
|
21858
|
+
segments: exports_external.array(exports_external.looseObject({
|
|
21859
|
+
generationId: exports_external.string(),
|
|
21860
|
+
profile: exports_external.string(),
|
|
21861
|
+
speaker: exports_external.string().optional(),
|
|
21862
|
+
emotion: exports_external.string().optional(),
|
|
21863
|
+
duration: exports_external.number(),
|
|
21864
|
+
verifyRetries: exports_external.number(),
|
|
21865
|
+
transcription: exports_external.string().optional(),
|
|
21866
|
+
loudnessDip: exports_external.boolean().optional()
|
|
21867
|
+
})),
|
|
21868
|
+
mp3Path: exports_external.string().optional(),
|
|
21869
|
+
qc: exports_external.record(exports_external.string(), exports_external.unknown()).optional()
|
|
21870
|
+
})
|
|
21871
|
+
});
|
|
21852
21872
|
|
|
21853
21873
|
// ../../packages/kk-core/src/kinds.ts
|
|
21854
21874
|
var PLUGIN_KINDS = ["ingestion", "generator", "publish"];
|