@gobing-ai/knowledge-kit 0.1.11 → 0.1.12
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 +2359 -1721
- package/package.json +1 -1
- package/plugins/generations/image-gen/README.md +108 -0
- package/plugins/generations/image-gen/assets/sample/cover__clean-webapp-ui.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/cover__cute.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/cover__daily-news.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/cover__editorial.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/cover__fresh.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/cover__minimalist.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/cover__photorealistic.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/cover__sketch.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/cover__technical-diagram.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/cover__vibrant.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/cover__warm.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/cover__xhs-knowledge.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/daily-news-cover__clean-webapp-ui.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/daily-news-cover__cute.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/daily-news-cover__daily-news.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/daily-news-cover__editorial.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/daily-news-cover__fresh.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/daily-news-cover__minimalist.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/daily-news-cover__photorealistic.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/daily-news-cover__sketch.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/daily-news-cover__technical-diagram.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/daily-news-cover__vibrant.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/daily-news-cover__warm.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/daily-news-cover__xhs-knowledge.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/free__clean-webapp-ui.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/free__cute.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/free__daily-news.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/free__editorial.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/free__fresh.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/free__minimalist.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/free__photorealistic.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/free__sketch.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/free__technical-diagram.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/free__vibrant.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/free__warm.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/free__xhs-knowledge.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/illustration__clean-webapp-ui.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/illustration__cute.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/illustration__daily-news.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/illustration__editorial.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/illustration__fresh.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/illustration__minimalist.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/illustration__photorealistic.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/illustration__sketch.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/illustration__technical-diagram.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/illustration__vibrant.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/illustration__warm.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/illustration__xhs-knowledge.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/xhs-card__clean-webapp-ui.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/xhs-card__cute.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/xhs-card__daily-news.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/xhs-card__editorial.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/xhs-card__fresh.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/xhs-card__minimalist.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/xhs-card__photorealistic.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/xhs-card__sketch.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/xhs-card__technical-diagram.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/xhs-card__vibrant.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/xhs-card__warm.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/xhs-card__xhs-knowledge.jpg +0 -0
- package/plugins/generations/image-gen/dist/index.js +102 -58
- package/plugins/generations/image-gen/scripts/compose-e2e-artifact.ts +5 -21
- package/plugins/generations/image-gen/scripts/gen-samples.ts +208 -0
- package/plugins/generations/image-gen/src/compose/chromium.ts +2 -3
- package/plugins/generations/image-gen/src/presets.ts +6 -3
- package/plugins/generations/image-gen/src/providers/errors.ts +16 -1
- package/plugins/generations/image-gen/src/providers/minimax.ts +46 -17
- package/plugins/ingestions/web-search/src/index.ts +1 -1
- package/plugins/kk/README.md +18 -0
- package/plugins/kk/commands/image-extract.md +1 -0
- package/plugins/kk/commands/image-generate.md +1 -0
- package/plugins/kk/commands/tell-me.md +1 -0
- package/plugins/kk/commands/workflow-run.md +7 -1
- package/plugins/kk/decisions/extract/it-topics.yaml +24 -0
- package/plugins/kk/decisions/kk-itc.yaml +6 -4
- package/plugins/kk/plugin.json +1 -1
- package/plugins/kk/publish-presets/daily-ai-voice-migration.json +146 -0
- package/plugins/kk/publish-presets/daily-ai-voice.json +11 -3
- package/plugins/kk/schedules/kk-collect.grok-bot.md.tmpl +69 -0
- package/plugins/kk/schedules/kk-daily-ai-voice3.cron.tmpl +18 -0
- package/plugins/kk/schedules/kk-daily-publish3-cn-peak.cron.tmpl +15 -5
- package/plugins/kk/schedules/kk-daily-publish3-overseas.cron.tmpl +9 -4
- package/plugins/kk/scripts/daily-stages.ts +346 -48
- package/plugins/kk/scripts/kk-workflow-stages.ts +190 -0
- package/plugins/kk/scripts/safety-artifact-check.ts +70 -28
- package/plugins/kk/scripts/voice3-publish-window.ts +202 -0
- package/plugins/kk/skills/article-adapt/SKILL.md +1 -0
- package/plugins/kk/skills/audio-authoring/SKILL.md +1 -0
- package/plugins/kk/skills/content-judge/SKILL.md +1 -0
- package/plugins/kk/skills/content-safety/SKILL.md +1 -0
- package/plugins/kk/skills/explain-things/SKILL.md +1 -0
- package/plugins/kk/skills/image-authoring/SKILL.md +1 -0
- package/plugins/kk/skills/itc-generating/SKILL.md +1 -0
- package/plugins/kk/skills/publish/SKILL.md +1 -0
- package/plugins/kk/skills/smart-seo/SKILL.md +1 -0
- package/plugins/kk/skills/storm-research/SKILL.md +1 -0
- package/plugins/kk/skills/taste-unslop/SKILL.md +1 -0
- package/plugins/kk/skills/topic/SKILL.md +1 -0
- package/plugins/kk/skills/web-automation/SKILL.md +1 -0
- package/plugins/kk/skills/xhs-images/SKILL.md +1 -0
- package/plugins/kk/workflows/kk-daily-ai-voice2.yaml +9 -7
- package/plugins/kk/workflows/kk-daily-ai-voice3.yaml +161 -61
- package/plugins/kk/workflows/kk-daily-publish3.yaml +82 -26
- package/plugins/kk/workflows/kk-daily-safety.yaml +39 -31
- package/plugins/kk/workflows/kk-itc-author.yaml +75 -0
- package/plugins/kk/workflows/kk-itc-publish-tail.yaml +25 -3
- package/plugins/kk/workflows/kk-itc.yaml +36 -4
- package/plugins/publishings/linkedin-pub/dist/index.js +21333 -0
- package/plugins/publishings/linkedin-pub/dist/profile-check.js +21005 -0
- package/plugins/publishings/linkedin-pub/package.json +19 -0
- package/plugins/publishings/linkedin-pub/plugin.json +12 -0
- package/plugins/publishings/linkedin-pub/src/index.ts +705 -0
- package/plugins/publishings/linkedin-pub/src/profile-check.ts +17 -0
- package/plugins/publishings/linkedin-pub/tsconfig.json +4 -0
- package/plugins/publishings/surfdash-pub/dist/index.js +1 -1
- package/plugins/publishings/surfdash-pub/src/index.ts +3 -1
- package/plugins/publishings/threads-pub/dist/index.js +7 -0
- package/plugins/publishings/threads-pub/src/index.ts +12 -0
- package/plugins/publishings/wechatmp-pub/dist/index.js +5 -2
- package/plugins/publishings/wechatmp-pub/src/flow.ts +11 -3
- package/plugins/publishings/x-pub/dist/index.js +7 -0
- package/plugins/publishings/x-pub/src/index.ts +11 -0
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LinkedIn profile-session capability (0328 R2).
|
|
3
|
+
*
|
|
4
|
+
* `login` opens the feed in a headed browser and resolves only once LinkedIn's readiness predicate
|
|
5
|
+
* passes; `check` reopens the profile headlessly and reports `verified` or `refused` without
|
|
6
|
+
* posting. Arg parsing, profile precedence (`--profile` > `LINKEDIN_PROFILE_DIR` >
|
|
7
|
+
* `KK_BROWSER_PROFILE_DIR` > `~/.config/kk/browser-profiles/linkedin`, ADR-042) and the exit codes
|
|
8
|
+
* (0 verified, 1 refused, 2 usage error) all live in the shared `runProfileCli`, so the publish
|
|
9
|
+
* preflight (`kk plugin check linkedin-pub` and the publish-matrix probe) and this CLI apply one
|
|
10
|
+
* gate.
|
|
11
|
+
*/
|
|
12
|
+
import { runProfileCli } from '@gobing-ai/publish-harness/browser';
|
|
13
|
+
import { LINKEDIN_CONFIG } from './index';
|
|
14
|
+
|
|
15
|
+
if (import.meta.main) {
|
|
16
|
+
process.exit(await runProfileCli(LINKEDIN_CONFIG, Bun.argv.slice(2)));
|
|
17
|
+
}
|
|
@@ -13079,7 +13079,7 @@ function normalizeLocaleFrontmatter(markdown) {
|
|
|
13079
13079
|
const close = lines.findIndex((l, i) => i > 0 && l.trim() === "---");
|
|
13080
13080
|
if (close < 0)
|
|
13081
13081
|
return markdown;
|
|
13082
|
-
const head = lines.slice(1, close).filter((l) => !/^canonical\s
|
|
13082
|
+
const head = lines.slice(1, close).filter((l) => !/^canonical\s*:.*\/zh\//.test(l)).map((l) => /^draft\s*:/.test(l) ? "draft: false" : l);
|
|
13083
13083
|
return [lines[0], ...head, ...lines.slice(close)].join(`
|
|
13084
13084
|
`);
|
|
13085
13085
|
}
|
|
@@ -735,7 +735,9 @@ export function normalizeLocaleFrontmatter(markdown: string): string {
|
|
|
735
735
|
if (close < 0) return markdown;
|
|
736
736
|
const head = lines
|
|
737
737
|
.slice(1, close)
|
|
738
|
-
|
|
738
|
+
// Only the zh scaffold's canonical is stale; a sibling's own (refined) canonical must survive,
|
|
739
|
+
// or the orchestrator re-dumps the frontmatter and the byte-exact drift gate fails.
|
|
740
|
+
.filter((l) => !/^canonical\s*:.*\/zh\//.test(l))
|
|
739
741
|
.map((l) => (/^draft\s*:/.test(l) ? 'draft: false' : l));
|
|
740
742
|
return [lines[0], ...head, ...lines.slice(close)].join('\n');
|
|
741
743
|
}
|
|
@@ -12391,6 +12391,13 @@ class ThreadsPostApiTransport {
|
|
|
12391
12391
|
const unsupported = refuseUnsupportedOptions(payload.options, payload.content);
|
|
12392
12392
|
if (unsupported !== undefined)
|
|
12393
12393
|
return fail(unsupported);
|
|
12394
|
+
const requestedStatus = payload.content.metadata?.publishStatus;
|
|
12395
|
+
if (requestedStatus === "draft") {
|
|
12396
|
+
return fail("threads post has no draft: the Threads API publishes immediately \u2014 plan this target dummy/off or launch it live");
|
|
12397
|
+
}
|
|
12398
|
+
if (requestedStatus !== undefined && requestedStatus !== "public") {
|
|
12399
|
+
return fail(`unknown publishStatus '${String(requestedStatus)}' (expected absent, 'draft' or 'public')`);
|
|
12400
|
+
}
|
|
12394
12401
|
const missing = TOKEN_ENVS.filter((key) => {
|
|
12395
12402
|
const value = process.env[key];
|
|
12396
12403
|
return !value || value.trim().length === 0;
|
|
@@ -146,6 +146,18 @@ export class ThreadsPostApiTransport implements PublishTransport {
|
|
|
146
146
|
const unsupported = refuseUnsupportedOptions(payload.options, payload.content);
|
|
147
147
|
if (unsupported !== undefined) return fail(unsupported);
|
|
148
148
|
|
|
149
|
+
// 0330 R2: the post API publishes immediately — there is no draft. Intercept before the
|
|
150
|
+
// credential lookup so a planned draft never reaches Threads, and fail closed on unknown modes.
|
|
151
|
+
const requestedStatus = payload.content.metadata?.publishStatus;
|
|
152
|
+
if (requestedStatus === 'draft') {
|
|
153
|
+
return fail(
|
|
154
|
+
'threads post has no draft: the Threads API publishes immediately — plan this target dummy/off or launch it live',
|
|
155
|
+
);
|
|
156
|
+
}
|
|
157
|
+
if (requestedStatus !== undefined && requestedStatus !== 'public') {
|
|
158
|
+
return fail(`unknown publishStatus '${String(requestedStatus)}' (expected absent, 'draft' or 'public')`);
|
|
159
|
+
}
|
|
160
|
+
|
|
149
161
|
const missing = TOKEN_ENVS.filter((key) => {
|
|
150
162
|
const value = process.env[key];
|
|
151
163
|
return !value || value.trim().length === 0;
|
|
@@ -23504,6 +23504,8 @@ function publicSnapshotIsIncomplete(expected, actual) {
|
|
|
23504
23504
|
return true;
|
|
23505
23505
|
if (!snapshotValueIsEmpty(expected.body) && snapshotValueIsEmpty(actual.body))
|
|
23506
23506
|
return true;
|
|
23507
|
+
if (actual.body.length < expected.body.length && expected.body.startsWith(actual.body))
|
|
23508
|
+
return true;
|
|
23507
23509
|
if (expected.media.length > actual.media.length)
|
|
23508
23510
|
return true;
|
|
23509
23511
|
if (!snapshotValueIsEmpty(expected.cover) && snapshotValueIsEmpty(actual.cover))
|
|
@@ -23659,8 +23661,9 @@ async function recoverStaleVersion(deps, entry, saved) {
|
|
|
23659
23661
|
}, deps.draftTimeoutMs, deps.pollMs);
|
|
23660
23662
|
if (!snapshotSettled || latestSnapshot === null)
|
|
23661
23663
|
return fail("public stale-version recovery: latest editor snapshot was unreadable; no second \u53D1\u8868 click attempted");
|
|
23664
|
+
const latestBody = latestSnapshot.body;
|
|
23662
23665
|
if (differences.length > 0)
|
|
23663
|
-
return fail(`public stale-version recovery: latest editor content mismatch (${differences.join(", ")}); no second \u53D1\u8868 click attempted`);
|
|
23666
|
+
return fail(`public stale-version recovery: latest editor content mismatch (${differences.join(", ")}; body ${latestBody.length}/${saved.snapshot.body.length} chars); no second \u53D1\u8868 click attempted`);
|
|
23664
23667
|
if (!await waitForPublicEditorReadiness(latestEditor, deps))
|
|
23665
23668
|
return fail("public stale-version recovery: latest editor did not provide two consecutive recognized readiness probes; no second \u53D1\u8868 click attempted");
|
|
23666
23669
|
return {
|
|
@@ -23716,7 +23719,7 @@ function shouldNotifySubscribers(content) {
|
|
|
23716
23719
|
return wechatmp.notifySubscribers !== false;
|
|
23717
23720
|
}
|
|
23718
23721
|
async function confirmPublicPublish(page, notifySubscribers, stepTimeoutMs, pollMs) {
|
|
23719
|
-
const confirmationTimeoutMs =
|
|
23722
|
+
const confirmationTimeoutMs = stepTimeoutMs;
|
|
23720
23723
|
const dialog = await findUniqueVisibleSelector(page, PUBLISH_DIALOG, confirmationTimeoutMs, pollMs);
|
|
23721
23724
|
if (dialog.selector === undefined) {
|
|
23722
23725
|
if (dialog.reason === "missing") {
|
|
@@ -1590,6 +1590,9 @@ function snapshotValueIsEmpty(value: string): boolean {
|
|
|
1590
1590
|
function publicSnapshotIsIncomplete(expected: PublicDraftSnapshot, actual: PublicDraftSnapshot): boolean {
|
|
1591
1591
|
if (!snapshotValueIsEmpty(expected.title) && snapshotValueIsEmpty(actual.title)) return true;
|
|
1592
1592
|
if (!snapshotValueIsEmpty(expected.body) && snapshotValueIsEmpty(actual.body)) return true;
|
|
1593
|
+
// The editor renders a long body progressively; a strict prefix is still hydrating, not a
|
|
1594
|
+
// different version (20261104: 查看新草稿 failed on its first non-empty read).
|
|
1595
|
+
if (actual.body.length < expected.body.length && expected.body.startsWith(actual.body)) return true;
|
|
1593
1596
|
if (expected.media.length > actual.media.length) return true;
|
|
1594
1597
|
if (!snapshotValueIsEmpty(expected.cover) && snapshotValueIsEmpty(actual.cover)) return true;
|
|
1595
1598
|
if (expected.originalUrl !== '' && actual.originalUrl === '') return true;
|
|
@@ -1837,9 +1840,11 @@ async function recoverStaleVersion(
|
|
|
1837
1840
|
return fail(
|
|
1838
1841
|
'public stale-version recovery: latest editor snapshot was unreadable; no second 发表 click attempted',
|
|
1839
1842
|
);
|
|
1843
|
+
// TS narrows the closure-assigned `let` to never after the null guard; re-read it through a cast.
|
|
1844
|
+
const latestBody = (latestSnapshot as PublicDraftSnapshot).body;
|
|
1840
1845
|
if (differences.length > 0)
|
|
1841
1846
|
return fail(
|
|
1842
|
-
`public stale-version recovery: latest editor content mismatch (${differences.join(', ')}); no second 发表 click attempted`,
|
|
1847
|
+
`public stale-version recovery: latest editor content mismatch (${differences.join(', ')}; body ${latestBody.length}/${saved.snapshot.body.length} chars); no second 发表 click attempted`,
|
|
1843
1848
|
);
|
|
1844
1849
|
|
|
1845
1850
|
if (!(await waitForPublicEditorReadiness(latestEditor, deps)))
|
|
@@ -1948,7 +1953,10 @@ async function confirmPublicPublish(
|
|
|
1948
1953
|
stepTimeoutMs: number,
|
|
1949
1954
|
pollMs: number,
|
|
1950
1955
|
): Promise<Result | PublicConfirmation | PreconfirmationStaleVersion> {
|
|
1951
|
-
|
|
1956
|
+
// Not CONFIRM_TIMEOUT_MS: this dialog runs a server-side check before it mounts (3.6s on an idle
|
|
1957
|
+
// editor, 2026-11-04), so a 5s cap reported it missing on 2026-11-03/04. Waiting costs nothing
|
|
1958
|
+
// irreversible — no click happens until the dialog is uniquely observed.
|
|
1959
|
+
const confirmationTimeoutMs = stepTimeoutMs;
|
|
1952
1960
|
const dialog = await findUniqueVisibleSelector(page, PUBLISH_DIALOG, confirmationTimeoutMs, pollMs);
|
|
1953
1961
|
if (dialog.selector === undefined) {
|
|
1954
1962
|
if (dialog.reason === 'missing') {
|
|
@@ -2234,7 +2242,7 @@ export async function runMode(input: ModeInput, deps: ModeRunDeps): Promise<Resu
|
|
|
2234
2242
|
* TypeScript only — no Python, no theme CLI.
|
|
2235
2243
|
*
|
|
2236
2244
|
* Kept instead of the shared `markdownToHtml` because the two differ on safety, measured on Bun
|
|
2237
|
-
* 1.3.14: `Bun.markdown.html` passes raw HTML straight through (`<script>` included) and renders
|
|
2245
|
+
* 1.3.14 and again on 1.4.3: `Bun.markdown.html` passes raw HTML straight through (`<script>` included) and renders
|
|
2238
2246
|
* `javascript:` link destinations, while this renderer escapes text and refuses non-http(s) link
|
|
2239
2247
|
* schemes (R9). The *insertion* is the shared `pasteHtml` either way, so the ADR-029 rail holds.
|
|
2240
2248
|
*/
|
|
@@ -21008,6 +21008,13 @@ function resolveOperation(options, content) {
|
|
|
21008
21008
|
class XPostApiTransport {
|
|
21009
21009
|
kind = "file-cli";
|
|
21010
21010
|
async publish(payload) {
|
|
21011
|
+
const requestedStatus = payload.content.metadata?.publishStatus;
|
|
21012
|
+
if (requestedStatus === "draft") {
|
|
21013
|
+
return fail("x post has no draft: the post API publishes immediately \u2014 plan this target dummy/off or launch it live");
|
|
21014
|
+
}
|
|
21015
|
+
if (requestedStatus !== undefined && requestedStatus !== "public") {
|
|
21016
|
+
return fail(`unknown publishStatus '${String(requestedStatus)}' (expected absent, 'draft' or 'public')`);
|
|
21017
|
+
}
|
|
21011
21018
|
const missing = TOKEN_ENVS.filter((key) => {
|
|
21012
21019
|
const value = process.env[key];
|
|
21013
21020
|
return !value || value.trim().length === 0;
|
|
@@ -105,6 +105,17 @@ export class XPostApiTransport implements PublishTransport {
|
|
|
105
105
|
public readonly kind = 'file-cli';
|
|
106
106
|
|
|
107
107
|
public async publish(payload: PublishTransportPayload): Promise<Result> {
|
|
108
|
+
// 0330 R2: the post API publishes immediately — there is no draft. Intercept before the
|
|
109
|
+
// credential lookup so a planned draft never touches X, and fail closed on unknown modes.
|
|
110
|
+
const requestedStatus = payload.content.metadata?.publishStatus;
|
|
111
|
+
if (requestedStatus === 'draft') {
|
|
112
|
+
return fail(
|
|
113
|
+
'x post has no draft: the post API publishes immediately — plan this target dummy/off or launch it live',
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
if (requestedStatus !== undefined && requestedStatus !== 'public') {
|
|
117
|
+
return fail(`unknown publishStatus '${String(requestedStatus)}' (expected absent, 'draft' or 'public')`);
|
|
118
|
+
}
|
|
108
119
|
const missing = TOKEN_ENVS.filter((key) => {
|
|
109
120
|
const value = process.env[key];
|
|
110
121
|
return !value || value.trim().length === 0;
|