@gobing-ai/knowledge-kit 0.0.33 → 0.0.34
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 +25191 -24167
- package/package.json +4 -4
- package/plugins/generations/content-gen/dist/index.js +9 -9
- package/plugins/generations/core-facts-gen/dist/index.js +12 -12
- package/plugins/generations/daily-article-gen/dist/index.js +14 -20
- package/plugins/generations/daily-article-gen/src/index.ts +7 -11
- package/plugins/generations/dailynews-gen/dist/index.js +22 -21
- package/plugins/generations/dailynews-gen/src/script-builder.ts +25 -26
- package/plugins/generations/episode-plan-gen/dist/index.js +12 -12
- package/plugins/generations/gemini-tts/dist/index.js +9 -9
- package/plugins/generations/image-gen/dist/index.js +26 -11
- package/plugins/generations/image-gen/presets/formats/xhs-card.yaml +16 -14
- package/plugins/generations/image-gen/presets/styles/xhs-knowledge.yaml +2 -2
- package/plugins/generations/image-gen/src/compose/card.ts +17 -2
- package/plugins/generations/news-report-gen/dist/index.js +12 -12
- package/plugins/generations/voice-gen/dist/index.js +9 -9
- package/plugins/ingestions/aihot-ingest/dist/index.js +12 -12
- package/plugins/ingestions/horizon-ingest/dist/index.js +12 -12
- package/plugins/ingestions/karakeep-local/dist/index.js +13 -13
- package/plugins/ingestions/last30days-ingest/dist/index.js +12 -12
- package/plugins/ingestions/web-search/dist/index.js +10 -10
- package/plugins/kk/decisions/extract/ai-news.yaml +6 -0
- package/plugins/kk/decisions/kk-items.yaml +69 -3
- package/plugins/kk/plugin.json +1 -1
- package/plugins/kk/scripts/daily-stages.ts +539 -49
- package/plugins/kk/scripts/daily-voice-style.zh.md +15 -10
- package/plugins/kk/scripts/kk-workflow-stages.ts +6 -3
- package/plugins/kk/skills/content-safety/SKILL.md +1 -1
- package/plugins/kk/skills/content-safety/references/platforms/apple-podcasts.md +2 -2
- package/plugins/kk/workflows/kk-collect.yaml +7 -9
- package/plugins/kk/workflows/kk-daily-ai-voice2.yaml +163 -44
- package/plugins/kk/workflows/kk-daily-safety.yaml +8 -11
- package/plugins/publishings/emdash-pub/dist/index.js +9 -9
- package/plugins/publishings/infoq-pub/dist/index.js +22 -22
- package/plugins/publishings/juejin-pub/dist/index.js +22 -22
- package/plugins/publishings/medium-pub/dist/index.js +9 -9
- package/plugins/publishings/podcast-pub/dist/index.js +9 -9
- package/plugins/publishings/qiita-pub/dist/index.js +9 -9
- package/plugins/publishings/substack-pub/dist/index.js +22 -22
- package/plugins/publishings/surfdash-pub/dist/index.js +9 -9
- package/plugins/publishings/wechatmp-pub/dist/index.js +22 -22
- package/plugins/publishings/x-pub/dist/index.js +22 -22
- package/plugins/publishings/xhs-pub/dist/index.js +76 -27
- package/plugins/publishings/xhs-pub/src/flow.ts +9 -3
- package/plugins/publishings/xhs-pub/src/index.ts +111 -5
- package/plugins/publishings/zenn-pub/dist/index.js +9 -9
|
@@ -14671,7 +14671,7 @@ var init_zod = __esm(() => {
|
|
|
14671
14671
|
init_external();
|
|
14672
14672
|
});
|
|
14673
14673
|
|
|
14674
|
-
// ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.
|
|
14674
|
+
// ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.21/node_modules/@gobing-ai/ts-utils/dist/errors.js
|
|
14675
14675
|
var ErrorCode;
|
|
14676
14676
|
var init_errors3 = __esm(() => {
|
|
14677
14677
|
ErrorCode = {
|
|
@@ -14682,7 +14682,7 @@ var init_errors3 = __esm(() => {
|
|
|
14682
14682
|
};
|
|
14683
14683
|
});
|
|
14684
14684
|
|
|
14685
|
-
// ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.
|
|
14685
|
+
// ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.21/node_modules/@gobing-ai/ts-utils/dist/api-response.js
|
|
14686
14686
|
var API_ERROR_CODES, ERROR_CODE_TO_HTTP, CLIENT_SAFE_CODES;
|
|
14687
14687
|
var init_api_response = __esm(() => {
|
|
14688
14688
|
init_errors3();
|
|
@@ -14705,10 +14705,10 @@ var init_api_response = __esm(() => {
|
|
|
14705
14705
|
CLIENT_SAFE_CODES = new Set([ErrorCode.NotFound, ErrorCode.Validation, ErrorCode.Conflict]);
|
|
14706
14706
|
});
|
|
14707
14707
|
|
|
14708
|
-
// ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.
|
|
14708
|
+
// ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.21/node_modules/@gobing-ai/ts-utils/dist/cursor.js
|
|
14709
14709
|
var init_cursor = () => {};
|
|
14710
14710
|
|
|
14711
|
-
// ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.
|
|
14711
|
+
// ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.21/node_modules/@gobing-ai/ts-utils/dist/env.js
|
|
14712
14712
|
function getEnvVar(name, fallback) {
|
|
14713
14713
|
const raw = process.env[name];
|
|
14714
14714
|
return raw === undefined ? fallback : raw;
|
|
@@ -14717,10 +14717,10 @@ function getEnvVars() {
|
|
|
14717
14717
|
return process.env;
|
|
14718
14718
|
}
|
|
14719
14719
|
|
|
14720
|
-
// ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.
|
|
14720
|
+
// ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.21/node_modules/@gobing-ai/ts-utils/dist/event-severity.js
|
|
14721
14721
|
var init_event_severity = () => {};
|
|
14722
14722
|
|
|
14723
|
-
// ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.
|
|
14723
|
+
// ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.21/node_modules/@gobing-ai/ts-utils/dist/object.js
|
|
14724
14724
|
function isPlainObject2(value) {
|
|
14725
14725
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
14726
14726
|
}
|
|
@@ -14738,7 +14738,7 @@ function deepMerge(target, source) {
|
|
|
14738
14738
|
return result;
|
|
14739
14739
|
}
|
|
14740
14740
|
|
|
14741
|
-
// ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.
|
|
14741
|
+
// ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.21/node_modules/@gobing-ai/ts-utils/dist/output.js
|
|
14742
14742
|
function processStream(name) {
|
|
14743
14743
|
const proc = globalThis.process;
|
|
14744
14744
|
const stream = proc?.[name];
|
|
@@ -14756,7 +14756,7 @@ function echoError(message, target = defaultStderrTarget ?? processStream("stder
|
|
|
14756
14756
|
}
|
|
14757
14757
|
var defaultStderrTarget;
|
|
14758
14758
|
|
|
14759
|
-
// ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.
|
|
14759
|
+
// ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.21/node_modules/@gobing-ai/ts-utils/dist/index.js
|
|
14760
14760
|
var init_dist = __esm(() => {
|
|
14761
14761
|
init_api_response();
|
|
14762
14762
|
init_cursor();
|
|
@@ -21754,7 +21754,7 @@ var init_dist2 = __esm(() => {
|
|
|
21754
21754
|
$visitAsync = visit.visitAsync;
|
|
21755
21755
|
});
|
|
21756
21756
|
|
|
21757
|
-
// ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.
|
|
21757
|
+
// ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.21+44edd5c4d6372504/node_modules/@gobing-ai/ts-runtime/dist/config.js
|
|
21758
21758
|
function getProcessEnv() {
|
|
21759
21759
|
return getEnvVars();
|
|
21760
21760
|
}
|
|
@@ -21832,7 +21832,7 @@ var init_config = __esm(() => {
|
|
|
21832
21832
|
};
|
|
21833
21833
|
});
|
|
21834
21834
|
|
|
21835
|
-
// ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.
|
|
21835
|
+
// ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.21+44edd5c4d6372504/node_modules/@gobing-ai/ts-runtime/dist/file-system-node.js
|
|
21836
21836
|
import { appendFileSync, cpSync, createReadStream, createWriteStream, existsSync, mkdirSync, readdirSync, readFileSync, realpathSync, renameSync, rmSync, statSync, writeFileSync } from "fs";
|
|
21837
21837
|
import { dirname, resolve as resolvePath } from "path";
|
|
21838
21838
|
function createNodeFileSystem(root, paths) {
|
|
@@ -21919,7 +21919,7 @@ function findProjectRoot(startDir) {
|
|
|
21919
21919
|
}
|
|
21920
21920
|
var init_file_system_node = () => {};
|
|
21921
21921
|
|
|
21922
|
-
// ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.
|
|
21922
|
+
// ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.21+44edd5c4d6372504/node_modules/@gobing-ai/ts-runtime/dist/db-errors.js
|
|
21923
21923
|
var DbModuleNotInstalledError;
|
|
21924
21924
|
var init_db_errors = __esm(() => {
|
|
21925
21925
|
DbModuleNotInstalledError = class DbModuleNotInstalledError extends Error {
|
|
@@ -29130,7 +29130,7 @@ var init_execa = __esm(() => {
|
|
|
29130
29130
|
} = getIpcExport());
|
|
29131
29131
|
});
|
|
29132
29132
|
|
|
29133
|
-
// ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.
|
|
29133
|
+
// ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.21+44edd5c4d6372504/node_modules/@gobing-ai/ts-runtime/dist/process-group.js
|
|
29134
29134
|
function resolveDeadline(optionTimeout, defaultTimeout) {
|
|
29135
29135
|
if (optionTimeout === null)
|
|
29136
29136
|
return null;
|
|
@@ -29222,7 +29222,7 @@ function ownProcessGroupLifecycle(ownership) {
|
|
|
29222
29222
|
}
|
|
29223
29223
|
var MAX_TIMEOUT_MS = 2147483647, DEFAULT_KILL_GRACE_MS = 5000, GROUP_POLL_INTERVAL_MS = 25, GROUP_KILL_PATIENCE_MS = 2000;
|
|
29224
29224
|
|
|
29225
|
-
// ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.
|
|
29225
|
+
// ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.21+44edd5c4d6372504/node_modules/@gobing-ai/ts-runtime/dist/process-executor.js
|
|
29226
29226
|
import { isatty } from "tty";
|
|
29227
29227
|
function processEventSeverity(reason, exitCode) {
|
|
29228
29228
|
if (reason === "error")
|
|
@@ -29594,7 +29594,7 @@ var init_process_executor = __esm(() => {
|
|
|
29594
29594
|
init_config();
|
|
29595
29595
|
});
|
|
29596
29596
|
|
|
29597
|
-
// ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.
|
|
29597
|
+
// ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.21+44edd5c4d6372504/node_modules/@gobing-ai/ts-runtime/dist/runtime-node-bun.js
|
|
29598
29598
|
function getNodeFileSystem() {
|
|
29599
29599
|
if (!_nodeFileSystem)
|
|
29600
29600
|
_nodeFileSystem = createNodeFileSystem();
|
|
@@ -29746,11 +29746,11 @@ var PluginManifestSchema = exports_external.looseObject({
|
|
|
29746
29746
|
description: exports_external.string().optional(),
|
|
29747
29747
|
operations: exports_external.record(exports_external.string(), PluginOperationSchema).optional()
|
|
29748
29748
|
});
|
|
29749
|
-
// ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.
|
|
29749
|
+
// ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.21+44edd5c4d6372504/node_modules/@gobing-ai/ts-runtime/dist/index.js
|
|
29750
29750
|
init_file_system_node();
|
|
29751
29751
|
init_config();
|
|
29752
29752
|
|
|
29753
|
-
// ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.
|
|
29753
|
+
// ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.21+44edd5c4d6372504/node_modules/@gobing-ai/ts-runtime/dist/path.js
|
|
29754
29754
|
function normalizeSeparators(path6) {
|
|
29755
29755
|
return path6.replaceAll("\\", "/");
|
|
29756
29756
|
}
|
|
@@ -29808,7 +29808,7 @@ function getProcessCwd() {
|
|
|
29808
29808
|
return globalThis.process?.cwd?.() ?? "/";
|
|
29809
29809
|
}
|
|
29810
29810
|
|
|
29811
|
-
// ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.
|
|
29811
|
+
// ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.21+44edd5c4d6372504/node_modules/@gobing-ai/ts-runtime/dist/index.js
|
|
29812
29812
|
init_runtime_node_bun();
|
|
29813
29813
|
|
|
29814
29814
|
// ../../packages/kk-core/src/render-md.ts
|
|
@@ -29924,7 +29924,7 @@ async function trySelectors(page, selectors, options = {}) {
|
|
|
29924
29924
|
// ../../packages/publish-harness/src/browser.ts
|
|
29925
29925
|
import { resolve as resolve2 } from "path";
|
|
29926
29926
|
|
|
29927
|
-
// ../../node_modules/.bun/@gobing-ai+ts-browser-automation@0.5.
|
|
29927
|
+
// ../../node_modules/.bun/@gobing-ai+ts-browser-automation@0.5.21+b6949ba92ac553f0/node_modules/@gobing-ai/ts-browser-automation/dist/errors.js
|
|
29928
29928
|
class BrowserAutomationError extends Error {
|
|
29929
29929
|
constructor(message, options) {
|
|
29930
29930
|
super(message, options);
|
|
@@ -29973,10 +29973,10 @@ class OperationAbortedError extends BrowserAutomationError {
|
|
|
29973
29973
|
this.name = "OperationAbortedError";
|
|
29974
29974
|
}
|
|
29975
29975
|
}
|
|
29976
|
-
// ../../node_modules/.bun/@gobing-ai+ts-browser-automation@0.5.
|
|
29976
|
+
// ../../node_modules/.bun/@gobing-ai+ts-browser-automation@0.5.21+b6949ba92ac553f0/node_modules/@gobing-ai/ts-browser-automation/dist/launcher.js
|
|
29977
29977
|
import { mkdir } from "fs/promises";
|
|
29978
29978
|
|
|
29979
|
-
// ../../node_modules/.bun/@gobing-ai+ts-browser-automation@0.5.
|
|
29979
|
+
// ../../node_modules/.bun/@gobing-ai+ts-browser-automation@0.5.21+b6949ba92ac553f0/node_modules/@gobing-ai/ts-browser-automation/dist/profile-dir.js
|
|
29980
29980
|
function resolveProfileDir(profileDir) {
|
|
29981
29981
|
if (profileDir.trim() === "") {
|
|
29982
29982
|
throw new InvalidProfileDirError;
|
|
@@ -29988,7 +29988,7 @@ function resolveProfileDir(profileDir) {
|
|
|
29988
29988
|
return resolved;
|
|
29989
29989
|
}
|
|
29990
29990
|
|
|
29991
|
-
// ../../node_modules/.bun/@gobing-ai+ts-browser-automation@0.5.
|
|
29991
|
+
// ../../node_modules/.bun/@gobing-ai+ts-browser-automation@0.5.21+b6949ba92ac553f0/node_modules/@gobing-ai/ts-browser-automation/dist/launcher.js
|
|
29992
29992
|
var PROFILE_DIR_MODE = 448;
|
|
29993
29993
|
var BUSY_PROFILE_PATTERN = /singleton|already in use|in use by another/i;
|
|
29994
29994
|
var CHROMIUM_MISSING_PATTERN = /playwright install|executable doesn't exist/i;
|
|
@@ -30039,7 +30039,7 @@ function createPersistentLauncher(options = {}) {
|
|
|
30039
30039
|
};
|
|
30040
30040
|
}
|
|
30041
30041
|
|
|
30042
|
-
// ../../node_modules/.bun/@gobing-ai+ts-browser-automation@0.5.
|
|
30042
|
+
// ../../node_modules/.bun/@gobing-ai+ts-browser-automation@0.5.21+b6949ba92ac553f0/node_modules/@gobing-ai/ts-browser-automation/dist/operations.js
|
|
30043
30043
|
var DEFAULT_TIMEOUT_MS = 30000;
|
|
30044
30044
|
var POLL_INTERVAL_MS = 250;
|
|
30045
30045
|
var defaultLauncher;
|
|
@@ -30950,7 +30950,7 @@ async function leavePodcastModal(deps) {
|
|
|
30950
30950
|
if (await waitUntil(closed, deps.stepTimeoutMs))
|
|
30951
30951
|
return;
|
|
30952
30952
|
}
|
|
30953
|
-
throw new Error(`podcast modal: the \u53D1\u64AD\u5BA2 modal was still open ${deps.stepTimeoutMs}ms after the audio and cover were attached; the only recorded advance control is '${PODCAST_MODAL_ADVANCE[0]}'
|
|
30953
|
+
throw new Error(`podcast modal: the \u53D1\u64AD\u5BA2 modal was still open ${deps.stepTimeoutMs}ms after the audio and cover were attached; its post-attach save path has never been measured (task 0236 R3 \u2014 the attended walk is still pending) and the only recorded advance control is '${PODCAST_MODAL_ADVANCE[0]}', which a draft run does not click (it is publish-adjacent)`);
|
|
30954
30954
|
}
|
|
30955
30955
|
async function composePodcast(input, deps) {
|
|
30956
30956
|
await enterMode(deps, input.operation);
|
|
@@ -31072,6 +31072,38 @@ var AUTH_GATE = ["div.creator-tab", "text=\u4E0A\u4F20\u56FE\u6587"];
|
|
|
31072
31072
|
function fail2(error51) {
|
|
31073
31073
|
return ResultSchema.parse({ ok: false, target: TARGET, error: error51 });
|
|
31074
31074
|
}
|
|
31075
|
+
async function planVisit(primary, content) {
|
|
31076
|
+
const raw = content.metadata?.followUps;
|
|
31077
|
+
if (raw === undefined)
|
|
31078
|
+
return { plan: { primary, followUps: [] } };
|
|
31079
|
+
if (!Array.isArray(raw)) {
|
|
31080
|
+
return {
|
|
31081
|
+
error: `followUps validation: Content.metadata.followUps must be an array of Content objects, got ${typeof raw}`
|
|
31082
|
+
};
|
|
31083
|
+
}
|
|
31084
|
+
const followUps = [];
|
|
31085
|
+
for (const [index, entry] of raw.entries()) {
|
|
31086
|
+
const label = `followUps[${index}]`;
|
|
31087
|
+
const parsed = ContentSchema.safeParse(entry);
|
|
31088
|
+
if (!parsed.success) {
|
|
31089
|
+
followUps.push({ operation: label, error: `${label} is not a Content object` });
|
|
31090
|
+
continue;
|
|
31091
|
+
}
|
|
31092
|
+
const operation = typeof parsed.data.metadata?.operation === "string" ? parsed.data.metadata.operation : label;
|
|
31093
|
+
const requested = resolveXhsOperation(undefined, parsed.data);
|
|
31094
|
+
if (requested.error !== undefined) {
|
|
31095
|
+
followUps.push({ operation, error: requested.error });
|
|
31096
|
+
continue;
|
|
31097
|
+
}
|
|
31098
|
+
const validation = await validateModeInput(requested.operation, parsed.data);
|
|
31099
|
+
if (validation.error !== undefined) {
|
|
31100
|
+
followUps.push({ operation, error: validation.error });
|
|
31101
|
+
continue;
|
|
31102
|
+
}
|
|
31103
|
+
followUps.push({ content: parsed.data, operation: requested.operation, input: validation.input });
|
|
31104
|
+
}
|
|
31105
|
+
return { plan: { primary, followUps } };
|
|
31106
|
+
}
|
|
31075
31107
|
async function createShadowProbe(context2, page) {
|
|
31076
31108
|
const find = await createShadowFinder(context2, page);
|
|
31077
31109
|
return find === undefined ? undefined : { findControl: (labels) => find(labels) };
|
|
@@ -31145,9 +31177,12 @@ class XhsBrowserTransport {
|
|
|
31145
31177
|
if (validation.error !== undefined)
|
|
31146
31178
|
return fail2(validation.error);
|
|
31147
31179
|
const input = validation.input;
|
|
31180
|
+
const visited = await planVisit({ content: payload.content, input }, payload.content);
|
|
31181
|
+
if (visited.error !== undefined)
|
|
31182
|
+
return fail2(visited.error);
|
|
31183
|
+
const visit2 = visited.plan;
|
|
31148
31184
|
const override = typeof payload.options?.profileDir === "string" ? payload.options.profileDir : undefined;
|
|
31149
31185
|
const profileDir = resolveChannelProfileDir(CHANNEL, override);
|
|
31150
|
-
const publishStatus = payload.content.metadata?.publishStatus === "public" ? "public" : "draft";
|
|
31151
31186
|
const cap = this.automation.allow("publish");
|
|
31152
31187
|
if (!cap.allowed)
|
|
31153
31188
|
return fail2(`automation cap: ${cap.reason}`);
|
|
@@ -31163,6 +31198,21 @@ class XhsBrowserTransport {
|
|
|
31163
31198
|
return fail2(error51 instanceof Error ? error51.message : String(error51));
|
|
31164
31199
|
}
|
|
31165
31200
|
const { page, close } = opened;
|
|
31201
|
+
try {
|
|
31202
|
+
const primary = await this.runStep(visit2.primary.input, visit2.primary.content, page, profileDir);
|
|
31203
|
+
if (!primary.ok || visit2.followUps.length === 0)
|
|
31204
|
+
return primary;
|
|
31205
|
+
const followUps = [];
|
|
31206
|
+
for (const followUp of visit2.followUps) {
|
|
31207
|
+
const step = "error" in followUp ? fail2(`follow-up (${followUp.operation}): ${followUp.error}`) : await this.runStep(followUp.input, followUp.content, page, profileDir);
|
|
31208
|
+
followUps.push(ResultSchema.parse({ ...step, metadata: { operation: followUp.operation, ...step.metadata } }));
|
|
31209
|
+
}
|
|
31210
|
+
return ResultSchema.parse({ ...primary, metadata: { ...primary.metadata, followUps } });
|
|
31211
|
+
} finally {
|
|
31212
|
+
await close();
|
|
31213
|
+
}
|
|
31214
|
+
}
|
|
31215
|
+
async runStep(input, content, page, profileDir) {
|
|
31166
31216
|
const act = async (what, fn) => {
|
|
31167
31217
|
try {
|
|
31168
31218
|
return await fn();
|
|
@@ -31176,10 +31226,11 @@ class XhsBrowserTransport {
|
|
|
31176
31226
|
if (!gated) {
|
|
31177
31227
|
return fail2(`login timeout after ${this.loginTimeoutMs}ms: no authenticated ${CHANNEL} creator console in ${profileDir}`);
|
|
31178
31228
|
}
|
|
31229
|
+
const publishStatus = content.metadata?.publishStatus === "public" ? "public" : "draft";
|
|
31179
31230
|
const draftBaseline = publishStatus === "draft" ? await readDraftBaseline(page) : { count: null, stamps: [] };
|
|
31180
31231
|
return await runMode(input, {
|
|
31181
31232
|
page,
|
|
31182
|
-
content
|
|
31233
|
+
content,
|
|
31183
31234
|
publishStatus,
|
|
31184
31235
|
profileDir,
|
|
31185
31236
|
driver: this.driver,
|
|
@@ -31190,8 +31241,6 @@ class XhsBrowserTransport {
|
|
|
31190
31241
|
});
|
|
31191
31242
|
} catch (error51) {
|
|
31192
31243
|
return fail2(error51 instanceof Error ? error51.message : String(error51));
|
|
31193
|
-
} finally {
|
|
31194
|
-
await close();
|
|
31195
31244
|
}
|
|
31196
31245
|
}
|
|
31197
31246
|
}
|
|
@@ -403,8 +403,14 @@ async function isPodcastModalOpen(page: XhsPage): Promise<boolean> {
|
|
|
403
403
|
|
|
404
404
|
/**
|
|
405
405
|
* Leave the 发播客 modal. The recorded advance control is `去发布`, which is publish-adjacent, so a
|
|
406
|
-
|
|
407
|
-
|
|
406
|
+
draft run never clicks it: it waits for the platform to move on by itself and fails loud naming the
|
|
407
|
+
control it refused to click. Only an explicit `publishStatus: 'public'` may click it.
|
|
408
|
+
*
|
|
409
|
+
* 0236 R3 (deferred, operator decision 2026-10-09): whether the modal offers a save path OTHER than
|
|
410
|
+
* `去发布` once both files are attached was never measured (`.spur/run/discovery/` holds only the
|
|
411
|
+
* modal open), and an attended walk under ADR-025 is what would measure it. So no draft-save selector
|
|
412
|
+
* is invented here: the run stops before the publish-adjacent control and says so, which is the
|
|
413
|
+
* failure the 0236 result carries (a `ok:false` entry that never fails the visit).
|
|
408
414
|
*/
|
|
409
415
|
async function leavePodcastModal(deps: ModeRunDeps): Promise<void> {
|
|
410
416
|
const closed = () => isPodcastModalOpen(deps.page).then((open) => !open);
|
|
@@ -420,7 +426,7 @@ async function leavePodcastModal(deps: ModeRunDeps): Promise<void> {
|
|
|
420
426
|
if (await waitUntil(closed, deps.stepTimeoutMs)) return;
|
|
421
427
|
}
|
|
422
428
|
throw new Error(
|
|
423
|
-
`podcast modal: the 发播客 modal was still open ${deps.stepTimeoutMs}ms after the audio and cover were attached; the only recorded advance control is '${PODCAST_MODAL_ADVANCE[0]}'
|
|
429
|
+
`podcast modal: the 发播客 modal was still open ${deps.stepTimeoutMs}ms after the audio and cover were attached; its post-attach save path has never been measured (task 0236 R3 — the attended walk is still pending) and the only recorded advance control is '${PODCAST_MODAL_ADVANCE[0]}', which a draft run does not click (it is publish-adjacent)`,
|
|
424
430
|
);
|
|
425
431
|
}
|
|
426
432
|
|
|
@@ -73,6 +73,71 @@ function fail(error: string): Result {
|
|
|
73
73
|
return ResultSchema.parse({ ok: false, target: TARGET, error });
|
|
74
74
|
}
|
|
75
75
|
|
|
76
|
+
/** One operation of a visit: its own Content and the mode input validated before any browser work. */
|
|
77
|
+
interface VisitOperation {
|
|
78
|
+
content: Content;
|
|
79
|
+
input: ModeInput;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* A follow-up operation of a visit: planned, or refused with the reason it never reached the console.
|
|
84
|
+
* A refused follow-up is reported as its own failed Result entry — it can never fail the note the
|
|
85
|
+
* visit was opened for (ADR-025 amendment 2026-10-09).
|
|
86
|
+
*/
|
|
87
|
+
type VisitFollowUp = { content: Content; operation: string; input: ModeInput } | { operation: string; error: string };
|
|
88
|
+
|
|
89
|
+
interface VisitPlan {
|
|
90
|
+
/** The requested operation, resolved and validated exactly as before task 0236. */
|
|
91
|
+
primary: VisitOperation;
|
|
92
|
+
/** The primary Content's `metadata.followUps`, in declared order. */
|
|
93
|
+
followUps: VisitFollowUp[];
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Plan a visit (ADR-025 amendment 2026-10-09, task 0236 option A): the requested operation plus the
|
|
98
|
+
* follow-ups the caller attached to the primary Content's `metadata.followUps`. One headed visit may
|
|
99
|
+
* compose several notes under ONE cap entry — the cap still counts visits, not notes.
|
|
100
|
+
*
|
|
101
|
+
* The primary is planned as it always was: an unplannable primary is a `fail` and no browser opens.
|
|
102
|
+
* A follow-up that cannot be planned (not a Content, an undeclared operation, a missing or unreadable
|
|
103
|
+
* artifact) is refused here, before any console work, and reported as its own entry instead. A
|
|
104
|
+
* `metadata.followUps` that is not an array is a caller error, so it fails loud before any browser.
|
|
105
|
+
*/
|
|
106
|
+
async function planVisit(
|
|
107
|
+
primary: VisitOperation,
|
|
108
|
+
content: Content,
|
|
109
|
+
): Promise<{ plan: VisitPlan; error?: undefined } | { plan?: undefined; error: string }> {
|
|
110
|
+
const raw = content.metadata?.followUps;
|
|
111
|
+
if (raw === undefined) return { plan: { primary, followUps: [] } };
|
|
112
|
+
if (!Array.isArray(raw)) {
|
|
113
|
+
return {
|
|
114
|
+
error: `followUps validation: Content.metadata.followUps must be an array of Content objects, got ${typeof raw}`,
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
const followUps: VisitFollowUp[] = [];
|
|
118
|
+
for (const [index, entry] of raw.entries()) {
|
|
119
|
+
const label = `followUps[${index}]`;
|
|
120
|
+
const parsed = ContentSchema.safeParse(entry);
|
|
121
|
+
if (!parsed.success) {
|
|
122
|
+
followUps.push({ operation: label, error: `${label} is not a Content object` });
|
|
123
|
+
continue;
|
|
124
|
+
}
|
|
125
|
+
const operation = typeof parsed.data.metadata?.operation === 'string' ? parsed.data.metadata.operation : label;
|
|
126
|
+
const requested = resolveXhsOperation(undefined, parsed.data);
|
|
127
|
+
if (requested.error !== undefined) {
|
|
128
|
+
followUps.push({ operation, error: requested.error });
|
|
129
|
+
continue;
|
|
130
|
+
}
|
|
131
|
+
const validation = await validateModeInput(requested.operation, parsed.data);
|
|
132
|
+
if (validation.error !== undefined) {
|
|
133
|
+
followUps.push({ operation, error: validation.error });
|
|
134
|
+
continue;
|
|
135
|
+
}
|
|
136
|
+
followUps.push({ content: parsed.data, operation: requested.operation, input: validation.input });
|
|
137
|
+
}
|
|
138
|
+
return { plan: { primary, followUps } };
|
|
139
|
+
}
|
|
140
|
+
|
|
76
141
|
/** CDP is Chromium-only; when unavailable the submit step fails loud instead of guessing. */
|
|
77
142
|
export async function createShadowProbe(
|
|
78
143
|
context: { newCDPSession?(page: unknown): Promise<ShadowCdpSession> },
|
|
@@ -239,13 +304,20 @@ export class XhsBrowserTransport implements PublishTransport {
|
|
|
239
304
|
if (validation.error !== undefined) return fail(validation.error);
|
|
240
305
|
const input: ModeInput = validation.input;
|
|
241
306
|
|
|
307
|
+
// ADR-025 amendment (2026-10-09, task 0236 option A): one visit may compose more than one
|
|
308
|
+
// note. The follow-ups ride the primary Content's `metadata.followUps` and are planned here,
|
|
309
|
+
// with the primary, before any browser work.
|
|
310
|
+
const visited = await planVisit({ content: payload.content, input }, payload.content);
|
|
311
|
+
if (visited.error !== undefined) return fail(visited.error);
|
|
312
|
+
const visit = visited.plan;
|
|
313
|
+
|
|
242
314
|
const override = typeof payload.options?.profileDir === 'string' ? payload.options.profileDir : undefined;
|
|
243
315
|
const profileDir = resolveChannelProfileDir(CHANNEL, override);
|
|
244
|
-
const publishStatus = payload.content.metadata?.publishStatus === 'public' ? 'public' : 'draft';
|
|
245
316
|
|
|
246
317
|
// ADR-025 automation guard — both gates run before any browser opens.
|
|
247
318
|
// 1. Frequency cap: the operator's platform warning makes a repeated console visit an
|
|
248
|
-
// account-level risk, not merely a failed run.
|
|
319
|
+
// account-level risk, not merely a failed run. The cap counts VISITS: one allow/record
|
|
320
|
+
// per visit covers every note the visit composes.
|
|
249
321
|
const cap = this.automation.allow('publish');
|
|
250
322
|
if (!cap.allowed) return fail(`automation cap: ${cap.reason}`);
|
|
251
323
|
// 2. Headless session preflight: an unauthenticated profile must never produce a headed
|
|
@@ -266,6 +338,41 @@ export class XhsBrowserTransport implements PublishTransport {
|
|
|
266
338
|
return fail(error instanceof Error ? error.message : String(error));
|
|
267
339
|
}
|
|
268
340
|
const { page, close } = opened;
|
|
341
|
+
try {
|
|
342
|
+
// The visit's own Result is the primary operation's: a failed primary ends the visit, as
|
|
343
|
+
// it always did, and only a primary that stood reports its follow-ups.
|
|
344
|
+
const primary = await this.runStep(visit.primary.input, visit.primary.content, page, profileDir);
|
|
345
|
+
if (!primary.ok || visit.followUps.length === 0) return primary;
|
|
346
|
+
// One Result entry per operation, in declared order; a refused and a failed follow-up
|
|
347
|
+
// are the same kind of entry, and neither can fail the note the visit was opened for.
|
|
348
|
+
const followUps: Result[] = [];
|
|
349
|
+
for (const followUp of visit.followUps) {
|
|
350
|
+
const step =
|
|
351
|
+
'error' in followUp
|
|
352
|
+
? fail(`follow-up (${followUp.operation}): ${followUp.error}`)
|
|
353
|
+
: await this.runStep(followUp.input, followUp.content, page, profileDir);
|
|
354
|
+
// Every entry names the operation it was planned under — a failed or refused one too,
|
|
355
|
+
// so the caller can tell which note fell; the step's own metadata wins.
|
|
356
|
+
followUps.push(
|
|
357
|
+
ResultSchema.parse({ ...step, metadata: { operation: followUp.operation, ...step.metadata } }),
|
|
358
|
+
);
|
|
359
|
+
}
|
|
360
|
+
return ResultSchema.parse({ ...primary, metadata: { ...primary.metadata, followUps } });
|
|
361
|
+
} finally {
|
|
362
|
+
await close();
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
/**
|
|
367
|
+
* Run one operation of the visit in the page the visit already opened. Every step enters the
|
|
368
|
+
* console from its landing view: the primary needs the login gate and the pre-entry draft
|
|
369
|
+
* baseline, and a follow-up needs both again — the previous note's editor replaces the header,
|
|
370
|
+
* and the baseline must be read before THIS note's mode is entered.
|
|
371
|
+
*
|
|
372
|
+
* A step never throws: its failure is that operation's own `ok:false` Result, which is what keeps
|
|
373
|
+
* a failed follow-up from failing the visit (ADR-025 amendment 2026-10-09).
|
|
374
|
+
*/
|
|
375
|
+
private async runStep(input: ModeInput, content: Content, page: XhsPage, profileDir: string): Promise<Result> {
|
|
269
376
|
const act = async <T>(what: string, fn: () => Promise<T>): Promise<T> => {
|
|
270
377
|
try {
|
|
271
378
|
return await fn();
|
|
@@ -283,6 +390,7 @@ export class XhsBrowserTransport implements PublishTransport {
|
|
|
283
390
|
);
|
|
284
391
|
}
|
|
285
392
|
|
|
393
|
+
const publishStatus = content.metadata?.publishStatus === 'public' ? 'public' : 'draft';
|
|
286
394
|
// The draft counter and any save timestamps exist only on the landing view, so the
|
|
287
395
|
// baseline is captured before the mode is entered (the editor replaces the header).
|
|
288
396
|
const draftBaseline =
|
|
@@ -290,7 +398,7 @@ export class XhsBrowserTransport implements PublishTransport {
|
|
|
290
398
|
|
|
291
399
|
return await runMode(input, {
|
|
292
400
|
page,
|
|
293
|
-
content
|
|
401
|
+
content,
|
|
294
402
|
publishStatus,
|
|
295
403
|
profileDir,
|
|
296
404
|
driver: this.driver,
|
|
@@ -301,8 +409,6 @@ export class XhsBrowserTransport implements PublishTransport {
|
|
|
301
409
|
});
|
|
302
410
|
} catch (error) {
|
|
303
411
|
return fail(error instanceof Error ? error.message : String(error));
|
|
304
|
-
} finally {
|
|
305
|
-
await close();
|
|
306
412
|
}
|
|
307
413
|
}
|
|
308
414
|
}
|
|
@@ -14642,7 +14642,7 @@ var init_zod = __esm(() => {
|
|
|
14642
14642
|
init_external();
|
|
14643
14643
|
});
|
|
14644
14644
|
|
|
14645
|
-
// ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.
|
|
14645
|
+
// ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.21/node_modules/@gobing-ai/ts-utils/dist/errors.js
|
|
14646
14646
|
var ErrorCode;
|
|
14647
14647
|
var init_errors3 = __esm(() => {
|
|
14648
14648
|
ErrorCode = {
|
|
@@ -14653,7 +14653,7 @@ var init_errors3 = __esm(() => {
|
|
|
14653
14653
|
};
|
|
14654
14654
|
});
|
|
14655
14655
|
|
|
14656
|
-
// ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.
|
|
14656
|
+
// ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.21/node_modules/@gobing-ai/ts-utils/dist/api-response.js
|
|
14657
14657
|
var API_ERROR_CODES, ERROR_CODE_TO_HTTP, CLIENT_SAFE_CODES;
|
|
14658
14658
|
var init_api_response = __esm(() => {
|
|
14659
14659
|
init_errors3();
|
|
@@ -14676,13 +14676,13 @@ var init_api_response = __esm(() => {
|
|
|
14676
14676
|
CLIENT_SAFE_CODES = new Set([ErrorCode.NotFound, ErrorCode.Validation, ErrorCode.Conflict]);
|
|
14677
14677
|
});
|
|
14678
14678
|
|
|
14679
|
-
// ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.
|
|
14679
|
+
// ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.21/node_modules/@gobing-ai/ts-utils/dist/cursor.js
|
|
14680
14680
|
var init_cursor = () => {};
|
|
14681
14681
|
|
|
14682
|
-
// ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.
|
|
14682
|
+
// ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.21/node_modules/@gobing-ai/ts-utils/dist/event-severity.js
|
|
14683
14683
|
var init_event_severity = () => {};
|
|
14684
14684
|
|
|
14685
|
-
// ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.
|
|
14685
|
+
// ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.21/node_modules/@gobing-ai/ts-utils/dist/output.js
|
|
14686
14686
|
function processStream(name) {
|
|
14687
14687
|
const proc = globalThis.process;
|
|
14688
14688
|
const stream = proc?.[name];
|
|
@@ -14700,7 +14700,7 @@ function echoError(message, target = defaultStderrTarget ?? processStream("stder
|
|
|
14700
14700
|
}
|
|
14701
14701
|
var defaultStderrTarget;
|
|
14702
14702
|
|
|
14703
|
-
// ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.
|
|
14703
|
+
// ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.21/node_modules/@gobing-ai/ts-utils/dist/index.js
|
|
14704
14704
|
var init_dist = __esm(() => {
|
|
14705
14705
|
init_api_response();
|
|
14706
14706
|
init_cursor();
|
|
@@ -21698,7 +21698,7 @@ var init_dist2 = __esm(() => {
|
|
|
21698
21698
|
$visitAsync = visit.visitAsync;
|
|
21699
21699
|
});
|
|
21700
21700
|
|
|
21701
|
-
// ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.
|
|
21701
|
+
// ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.21+44edd5c4d6372504/node_modules/@gobing-ai/ts-runtime/dist/config.js
|
|
21702
21702
|
var configSchema;
|
|
21703
21703
|
var init_config = __esm(() => {
|
|
21704
21704
|
init_dist2();
|
|
@@ -21722,7 +21722,7 @@ var init_config = __esm(() => {
|
|
|
21722
21722
|
});
|
|
21723
21723
|
});
|
|
21724
21724
|
|
|
21725
|
-
// ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.
|
|
21725
|
+
// ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.21+44edd5c4d6372504/node_modules/@gobing-ai/ts-runtime/dist/file-system-node.js
|
|
21726
21726
|
import { appendFileSync, cpSync, createReadStream, createWriteStream, existsSync, mkdirSync, readdirSync, readFileSync, realpathSync, renameSync, rmSync, statSync, writeFileSync } from "fs";
|
|
21727
21727
|
import { dirname, resolve as resolvePath } from "path";
|
|
21728
21728
|
function createNodeFileSystem(root, paths) {
|
|
@@ -21902,7 +21902,7 @@ var PluginManifestSchema = exports_external.looseObject({
|
|
|
21902
21902
|
description: exports_external.string().optional(),
|
|
21903
21903
|
operations: exports_external.record(exports_external.string(), PluginOperationSchema).optional()
|
|
21904
21904
|
});
|
|
21905
|
-
// ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.
|
|
21905
|
+
// ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.21+44edd5c4d6372504/node_modules/@gobing-ai/ts-runtime/dist/index.js
|
|
21906
21906
|
init_file_system_node();
|
|
21907
21907
|
init_config();
|
|
21908
21908
|
|