@gobing-ai/knowledge-kit 0.1.13 → 0.1.15
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 +796 -176
- package/package.json +1 -1
- package/plugins/generations/content-gen/dist/index.js +2 -2
- package/plugins/generations/core-facts-gen/dist/index.js +2 -2
- package/plugins/generations/daily-article-gen/dist/index.js +2 -2
- package/plugins/generations/dailynews-gen/dist/index.js +72 -9
- package/plugins/generations/dailynews-gen/src/index.ts +23 -1
- package/plugins/generations/dailynews-gen/src/script-plan.ts +103 -5
- package/plugins/generations/episode-plan-gen/dist/index.js +2 -2
- package/plugins/generations/gemini-tts/dist/index.js +2 -2
- package/plugins/generations/image-gen/dist/index.js +2 -2
- package/plugins/generations/news-report-gen/dist/index.js +2 -2
- package/plugins/generations/voice-gen/dist/index.js +2 -2
- package/plugins/generations/voxcpm-tts/dist/index.js +2 -2
- package/plugins/ingestions/aihot-ingest/dist/index.js +2 -2
- package/plugins/ingestions/horizon-ingest/dist/index.js +2 -2
- package/plugins/ingestions/last30days-ingest/dist/index.js +2 -2
- package/plugins/ingestions/web-search/dist/index.js +2 -2
- package/plugins/kk/plugin.json +1 -1
- package/plugins/kk/scripts/daily-scheduled-run.ts +53 -5
- package/plugins/kk/scripts/daily-stages.ts +476 -12
- package/plugins/kk/scripts/kk-workflow-stages.ts +20 -4
- package/plugins/kk/skills/content-judge/SKILL.md +5 -4
- package/plugins/kk/skills/content-judge/references/rubrics.md +14 -0
- package/plugins/kk/skills/news-editorial/SKILL.md +122 -0
- package/plugins/kk/skills/news-editorial/references/selection.md +47 -0
- package/plugins/kk/skills/news-editorial/references/style-contract.zh.md +99 -0
- package/plugins/kk/skills/publish/SKILL.md +3 -3
- package/plugins/kk/skills/web-automation/SKILL.md +229 -77
- package/plugins/kk/skills/web-automation/references/browser-launch.md +127 -36
- package/plugins/kk/workflows/kk-daily-ai-voice2.yaml +4 -6
- package/plugins/kk/workflows/kk-daily-ai-voice3.yaml +183 -222
- package/plugins/kk/workflows/kk-daily-publish3.yaml +16 -8
- package/plugins/publishings/bilibili-pub/dist/index.js +5 -3
- package/plugins/publishings/bilibili-pub/dist/profile-check.js +3 -1
- package/plugins/publishings/cnblogs-pub/dist/index.js +5 -3
- package/plugins/publishings/cnblogs-pub/dist/profile-check.js +3 -1
- package/plugins/publishings/csdn-pub/dist/index.js +5 -3
- package/plugins/publishings/csdn-pub/dist/profile-check.js +5 -3
- package/plugins/publishings/emdash-pub/dist/index.js +2 -2
- package/plugins/publishings/infoq-pub/dist/index.js +5 -3
- package/plugins/publishings/infoq-pub/dist/profile-check.js +5 -3
- package/plugins/publishings/jike-pub/dist/index.js +5 -3
- package/plugins/publishings/jike-pub/dist/profile-check.js +5 -3
- package/plugins/publishings/juejin-pub/dist/index.js +5 -3
- package/plugins/publishings/juejin-pub/dist/profile-check.js +5 -3
- package/plugins/publishings/linkedin-pub/dist/index.js +5 -3
- package/plugins/publishings/linkedin-pub/dist/profile-check.js +5 -3
- package/plugins/publishings/medium-pub/dist/index.js +2 -2
- package/plugins/publishings/podcast-pub/dist/index.js +147 -4
- package/plugins/publishings/podcast-pub/src/index.ts +71 -2
- package/plugins/publishings/podcast-pub/src/map.ts +3 -0
- package/plugins/publishings/podcast-pub/src/transcript.ts +195 -0
- package/plugins/publishings/qiita-pub/dist/index.js +2 -2
- package/plugins/publishings/shipinhao-pub/dist/index.js +5 -3
- package/plugins/publishings/shipinhao-pub/dist/profile-check.js +3 -1
- package/plugins/publishings/sspai-pub/dist/index.js +5 -3
- package/plugins/publishings/sspai-pub/dist/profile-check.js +3 -1
- package/plugins/publishings/substack-pub/dist/index.js +5 -3
- package/plugins/publishings/substack-pub/dist/profile-check.js +5 -3
- package/plugins/publishings/surfdash-pub/dist/index.js +2 -2
- package/plugins/publishings/threads-pub/dist/index.js +2 -2
- package/plugins/publishings/wechatmp-pub/dist/index.js +52 -33
- package/plugins/publishings/wechatmp-pub/dist/profile-check.js +5 -3
- package/plugins/publishings/wechatmp-pub/src/flow.ts +70 -33
- package/plugins/publishings/weibo-pub/dist/index.js +21 -6
- package/plugins/publishings/weibo-pub/dist/profile-check.js +5 -3
- package/plugins/publishings/weibo-pub/src/index.ts +31 -7
- package/plugins/publishings/x-pub/dist/index.js +5 -3
- package/plugins/publishings/x-pub/dist/profile-check.js +5 -3
- package/plugins/publishings/xhs-pub/dist/index.js +5 -3
- package/plugins/publishings/xhs-pub/dist/profile-check.js +5 -3
- package/plugins/publishings/xiaoyuzhou-pub/dist/index.js +5 -3
- package/plugins/publishings/xiaoyuzhou-pub/dist/profile-check.js +3 -1
- package/plugins/publishings/zenn-pub/dist/index.js +2 -2
- package/plugins/kk/scripts/daily-voice-style.zh.md +0 -70
package/package.json
CHANGED
|
@@ -12224,11 +12224,11 @@ var PluginManifestSchemaBase = looseObject({
|
|
|
12224
12224
|
});
|
|
12225
12225
|
var PluginManifestSchema = PluginManifestSchemaBase.superRefine((manifest, ctx) => {
|
|
12226
12226
|
if (manifest.browserSession !== undefined) {
|
|
12227
|
-
if (manifest.kind !== "publish") {
|
|
12227
|
+
if (manifest.kind !== "publish" && manifest.kind !== "ingestion") {
|
|
12228
12228
|
ctx.addIssue({
|
|
12229
12229
|
code: "custom",
|
|
12230
12230
|
path: ["browserSession"],
|
|
12231
|
-
message: `browserSession requires kind "publish", not "${manifest.kind}"`
|
|
12231
|
+
message: `browserSession requires kind "publish" or "ingestion", not "${manifest.kind}"`
|
|
12232
12232
|
});
|
|
12233
12233
|
}
|
|
12234
12234
|
if (manifest.check === undefined) {
|
|
@@ -12225,11 +12225,11 @@ var PluginManifestSchemaBase = looseObject({
|
|
|
12225
12225
|
});
|
|
12226
12226
|
var PluginManifestSchema = PluginManifestSchemaBase.superRefine((manifest, ctx) => {
|
|
12227
12227
|
if (manifest.browserSession !== undefined) {
|
|
12228
|
-
if (manifest.kind !== "publish") {
|
|
12228
|
+
if (manifest.kind !== "publish" && manifest.kind !== "ingestion") {
|
|
12229
12229
|
ctx.addIssue({
|
|
12230
12230
|
code: "custom",
|
|
12231
12231
|
path: ["browserSession"],
|
|
12232
|
-
message: `browserSession requires kind "publish", not "${manifest.kind}"`
|
|
12232
|
+
message: `browserSession requires kind "publish" or "ingestion", not "${manifest.kind}"`
|
|
12233
12233
|
});
|
|
12234
12234
|
}
|
|
12235
12235
|
if (manifest.check === undefined) {
|
|
@@ -12225,11 +12225,11 @@ var PluginManifestSchemaBase = looseObject({
|
|
|
12225
12225
|
});
|
|
12226
12226
|
var PluginManifestSchema = PluginManifestSchemaBase.superRefine((manifest, ctx) => {
|
|
12227
12227
|
if (manifest.browserSession !== undefined) {
|
|
12228
|
-
if (manifest.kind !== "publish") {
|
|
12228
|
+
if (manifest.kind !== "publish" && manifest.kind !== "ingestion") {
|
|
12229
12229
|
ctx.addIssue({
|
|
12230
12230
|
code: "custom",
|
|
12231
12231
|
path: ["browserSession"],
|
|
12232
|
-
message: `browserSession requires kind "publish", not "${manifest.kind}"`
|
|
12232
|
+
message: `browserSession requires kind "publish" or "ingestion", not "${manifest.kind}"`
|
|
12233
12233
|
});
|
|
12234
12234
|
}
|
|
12235
12235
|
if (manifest.check === undefined) {
|
|
@@ -12225,11 +12225,11 @@ var PluginManifestSchemaBase = looseObject({
|
|
|
12225
12225
|
});
|
|
12226
12226
|
var PluginManifestSchema = PluginManifestSchemaBase.superRefine((manifest, ctx) => {
|
|
12227
12227
|
if (manifest.browserSession !== undefined) {
|
|
12228
|
-
if (manifest.kind !== "publish") {
|
|
12228
|
+
if (manifest.kind !== "publish" && manifest.kind !== "ingestion") {
|
|
12229
12229
|
ctx.addIssue({
|
|
12230
12230
|
code: "custom",
|
|
12231
12231
|
path: ["browserSession"],
|
|
12232
|
-
message: `browserSession requires kind "publish", not "${manifest.kind}"`
|
|
12232
|
+
message: `browserSession requires kind "publish" or "ingestion", not "${manifest.kind}"`
|
|
12233
12233
|
});
|
|
12234
12234
|
}
|
|
12235
12235
|
if (manifest.check === undefined) {
|
|
@@ -12693,28 +12693,50 @@ function formatVoiceScriptToYaml(script) {
|
|
|
12693
12693
|
|
|
12694
12694
|
// ../../plugins/generations/dailynews-gen/src/script-plan.ts
|
|
12695
12695
|
init_zod();
|
|
12696
|
+
var ScriptPlanItemCardSchema = object({
|
|
12697
|
+
copy: string2().min(1),
|
|
12698
|
+
points: array(string2().min(1)).min(2).max(4),
|
|
12699
|
+
subject: string2().min(1)
|
|
12700
|
+
});
|
|
12696
12701
|
var ScriptPlanItemSchema = object({
|
|
12697
12702
|
id: string2().min(1),
|
|
12698
12703
|
lead: string2().min(1),
|
|
12699
|
-
insight: string2().min(1)
|
|
12704
|
+
insight: string2().min(1),
|
|
12705
|
+
card: ScriptPlanItemCardSchema.optional()
|
|
12700
12706
|
});
|
|
12701
12707
|
var ScriptPlanExclusionSchema = object({
|
|
12702
12708
|
id: string2().min(1),
|
|
12703
12709
|
reason: string2().min(1)
|
|
12704
12710
|
});
|
|
12711
|
+
var ScriptPlanCardsSchema = object({
|
|
12712
|
+
title: string2().min(1),
|
|
12713
|
+
body: string2().min(1)
|
|
12714
|
+
});
|
|
12715
|
+
var ScriptPlanSocialSchema = object({
|
|
12716
|
+
short: string2().min(1),
|
|
12717
|
+
long: string2().min(1)
|
|
12718
|
+
});
|
|
12705
12719
|
var ScriptPlanSchema = object({
|
|
12706
12720
|
version: literal(1),
|
|
12707
12721
|
intro: string2().min(1),
|
|
12708
12722
|
outro: string2().min(1),
|
|
12709
12723
|
items: array(ScriptPlanItemSchema),
|
|
12710
|
-
excluded: array(ScriptPlanExclusionSchema).optional()
|
|
12724
|
+
excluded: array(ScriptPlanExclusionSchema).optional(),
|
|
12725
|
+
cover: string2().min(1).optional(),
|
|
12726
|
+
cards: ScriptPlanCardsSchema.optional(),
|
|
12727
|
+
social: ScriptPlanSocialSchema.optional()
|
|
12711
12728
|
});
|
|
12712
12729
|
var StyleContractSchema = object({
|
|
12713
12730
|
caps: object({
|
|
12714
12731
|
intro: number2().int().positive(),
|
|
12715
12732
|
outro: number2().int().positive(),
|
|
12716
12733
|
lead: number2().int().positive(),
|
|
12717
|
-
insight: number2().int().positive()
|
|
12734
|
+
insight: number2().int().positive(),
|
|
12735
|
+
cover: number2().int().positive().optional(),
|
|
12736
|
+
cardCopy: number2().int().positive().optional(),
|
|
12737
|
+
cardTitle: number2().int().positive().optional(),
|
|
12738
|
+
socialShort: number2().int().positive().optional(),
|
|
12739
|
+
socialLong: number2().int().positive().optional()
|
|
12718
12740
|
}),
|
|
12719
12741
|
banned: array(string2().min(1))
|
|
12720
12742
|
});
|
|
@@ -12750,7 +12772,7 @@ function redundantInsightClauses(insight, reference) {
|
|
|
12750
12772
|
}
|
|
12751
12773
|
return count;
|
|
12752
12774
|
}
|
|
12753
|
-
function validateScriptPlan(plan, docs, style) {
|
|
12775
|
+
function validateScriptPlan(plan, docs, style, preExcludedIds) {
|
|
12754
12776
|
const parsed = ScriptPlanSchema.safeParse(plan);
|
|
12755
12777
|
if (!parsed.success) {
|
|
12756
12778
|
return { ok: false, errors: [{ itemId: "episode", rule: "schema" }] };
|
|
@@ -12765,8 +12787,9 @@ function validateScriptPlan(plan, docs, style) {
|
|
|
12765
12787
|
const plannedIds = new Set(valid.items.map((item) => item.id));
|
|
12766
12788
|
const excludedIds = new Set((valid.excluded ?? []).map((ex) => ex.id));
|
|
12767
12789
|
for (const ex of valid.excluded ?? []) {
|
|
12768
|
-
if (!docIds.has(ex.id))
|
|
12790
|
+
if (!docIds.has(ex.id) && !preExcludedIds?.has(ex.id)) {
|
|
12769
12791
|
errors.push({ itemId: ex.id, rule: "unknown-id" });
|
|
12792
|
+
}
|
|
12770
12793
|
if (plannedIds.has(ex.id))
|
|
12771
12794
|
errors.push({ itemId: ex.id, rule: "conflict-id" });
|
|
12772
12795
|
}
|
|
@@ -12778,11 +12801,28 @@ function validateScriptPlan(plan, docs, style) {
|
|
|
12778
12801
|
errors.push({ itemId: "episode", rule: "cap:intro" });
|
|
12779
12802
|
if (valid.outro.length > style.caps.outro)
|
|
12780
12803
|
errors.push({ itemId: "episode", rule: "cap:outro" });
|
|
12804
|
+
if (valid.cover !== undefined && valid.cover.length > (style.caps.cover ?? 240)) {
|
|
12805
|
+
errors.push({ itemId: "episode", rule: "cap:cover" });
|
|
12806
|
+
}
|
|
12807
|
+
if (valid.cards !== undefined && valid.cards.title.length > (style.caps.cardTitle ?? 20)) {
|
|
12808
|
+
errors.push({ itemId: "episode", rule: "cap:cardTitle" });
|
|
12809
|
+
}
|
|
12810
|
+
if (valid.social !== undefined) {
|
|
12811
|
+
if (valid.social.short.length > (style.caps.socialShort ?? 140)) {
|
|
12812
|
+
errors.push({ itemId: "episode", rule: "cap:socialShort" });
|
|
12813
|
+
}
|
|
12814
|
+
if (valid.social.long.length > (style.caps.socialLong ?? 500)) {
|
|
12815
|
+
errors.push({ itemId: "episode", rule: "cap:socialLong" });
|
|
12816
|
+
}
|
|
12817
|
+
}
|
|
12781
12818
|
for (const item of valid.items) {
|
|
12782
12819
|
if (item.lead.length > style.caps.lead)
|
|
12783
12820
|
errors.push({ itemId: item.id, rule: "cap:lead" });
|
|
12784
12821
|
if (item.insight.length > style.caps.insight)
|
|
12785
12822
|
errors.push({ itemId: item.id, rule: "cap:insight" });
|
|
12823
|
+
if (item.card !== undefined && item.card.copy.length > (style.caps.cardCopy ?? 12)) {
|
|
12824
|
+
errors.push({ itemId: item.id, rule: "cap:cardCopy" });
|
|
12825
|
+
}
|
|
12786
12826
|
const doc = docs.find((entry) => entry.id === item.id);
|
|
12787
12827
|
if (doc !== undefined && redundantInsightClauses(item.insight, `${item.lead}${doc.body}`) >= REDUNDANT_INSIGHT_CLAUSE_LIMIT) {
|
|
12788
12828
|
errors.push({ itemId: item.id, rule: "redundant-insight" });
|
|
@@ -12791,9 +12831,22 @@ function validateScriptPlan(plan, docs, style) {
|
|
|
12791
12831
|
const fields = [
|
|
12792
12832
|
{ itemId: "episode", text: valid.intro },
|
|
12793
12833
|
{ itemId: "episode", text: valid.outro },
|
|
12834
|
+
...valid.cover !== undefined ? [{ itemId: "episode", text: valid.cover }] : [],
|
|
12835
|
+
...valid.cards !== undefined ? [
|
|
12836
|
+
{ itemId: "episode", text: valid.cards.title },
|
|
12837
|
+
{ itemId: "episode", text: valid.cards.body }
|
|
12838
|
+
] : [],
|
|
12839
|
+
...valid.social !== undefined ? [
|
|
12840
|
+
{ itemId: "episode", text: valid.social.short },
|
|
12841
|
+
{ itemId: "episode", text: valid.social.long }
|
|
12842
|
+
] : [],
|
|
12794
12843
|
...valid.items.flatMap((item) => [
|
|
12795
12844
|
{ itemId: item.id, text: item.lead },
|
|
12796
|
-
{ itemId: item.id, text: item.insight }
|
|
12845
|
+
{ itemId: item.id, text: item.insight },
|
|
12846
|
+
...item.card !== undefined ? [
|
|
12847
|
+
{ itemId: item.id, text: item.card.copy },
|
|
12848
|
+
...item.card.points.map((point) => ({ itemId: item.id, text: point }))
|
|
12849
|
+
] : []
|
|
12797
12850
|
])
|
|
12798
12851
|
];
|
|
12799
12852
|
for (const field of fields) {
|
|
@@ -12838,7 +12891,17 @@ async function resolveScriptPlan(fs, docs) {
|
|
|
12838
12891
|
} catch {
|
|
12839
12892
|
return fallback([{ itemId: "episode", rule: "schema" }]);
|
|
12840
12893
|
}
|
|
12841
|
-
|
|
12894
|
+
let preExcludedIds;
|
|
12895
|
+
const curateExcludedPath = process.env.DAILYNEWS_CURATE_EXCLUDED;
|
|
12896
|
+
if (curateExcludedPath && await fs.exists(curateExcludedPath)) {
|
|
12897
|
+
try {
|
|
12898
|
+
const rawExcluded = JSON.parse(await fs.readFile(curateExcludedPath));
|
|
12899
|
+
if (Array.isArray(rawExcluded)) {
|
|
12900
|
+
preExcludedIds = new Set(rawExcluded.map((entry) => entry !== null && typeof entry === "object" && typeof entry.id === "string" ? entry.id : "").filter(Boolean));
|
|
12901
|
+
}
|
|
12902
|
+
} catch {}
|
|
12903
|
+
}
|
|
12904
|
+
const validated = validateScriptPlan(planJson, docs, style, preExcludedIds);
|
|
12842
12905
|
if (!validated.ok) {
|
|
12843
12906
|
return fallback(validated.errors);
|
|
12844
12907
|
}
|
|
@@ -59,7 +59,29 @@ async function resolveScriptPlan(fs: FileSystem, docs: Doc[]): Promise<ScriptPla
|
|
|
59
59
|
} catch {
|
|
60
60
|
return fallback([{ itemId: 'episode', rule: 'schema' }]);
|
|
61
61
|
}
|
|
62
|
-
|
|
62
|
+
let preExcludedIds: Set<string> | undefined;
|
|
63
|
+
const curateExcludedPath = process.env.DAILYNEWS_CURATE_EXCLUDED;
|
|
64
|
+
if (curateExcludedPath && (await fs.exists(curateExcludedPath))) {
|
|
65
|
+
try {
|
|
66
|
+
const rawExcluded = JSON.parse(await fs.readFile(curateExcludedPath));
|
|
67
|
+
if (Array.isArray(rawExcluded)) {
|
|
68
|
+
preExcludedIds = new Set(
|
|
69
|
+
rawExcluded
|
|
70
|
+
.map((entry: unknown) =>
|
|
71
|
+
entry !== null &&
|
|
72
|
+
typeof entry === 'object' &&
|
|
73
|
+
typeof (entry as { id?: unknown }).id === 'string'
|
|
74
|
+
? (entry as { id: string }).id
|
|
75
|
+
: '',
|
|
76
|
+
)
|
|
77
|
+
.filter(Boolean),
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
} catch {
|
|
81
|
+
// Ignore malformed sidecar; validateScriptPlan will validate against docs.
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
const validated = validateScriptPlan(planJson, docs, style, preExcludedIds);
|
|
63
85
|
if (!validated.ok) {
|
|
64
86
|
return fallback(validated.errors);
|
|
65
87
|
}
|
|
@@ -7,25 +7,55 @@ import { z } from 'zod';
|
|
|
7
7
|
* (`docs/design/daily-voice-script-plan.md` §3). `version` is pinned so a future shape change
|
|
8
8
|
* fails loud as `schema` instead of mis-substituting.
|
|
9
9
|
*/
|
|
10
|
+
export interface ScriptPlanItemCard {
|
|
11
|
+
copy: string;
|
|
12
|
+
points: string[];
|
|
13
|
+
subject: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface ScriptPlanCards {
|
|
17
|
+
title: string;
|
|
18
|
+
body: string;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface ScriptPlanSocial {
|
|
22
|
+
short: string;
|
|
23
|
+
long: string;
|
|
24
|
+
}
|
|
25
|
+
|
|
10
26
|
export interface ScriptPlan {
|
|
11
27
|
version: 1;
|
|
12
28
|
intro: string;
|
|
13
29
|
outro: string;
|
|
14
|
-
items: { id: string; lead: string; insight: string }[];
|
|
30
|
+
items: { id: string; lead: string; insight: string; card?: ScriptPlanItemCard }[];
|
|
15
31
|
/**
|
|
16
32
|
* Docs deliberately not spoken (topic-boundary exclusions, task 0189). An id here is
|
|
17
33
|
* exempt from `missing-item`; listing an id in both `items` and `excluded` is a
|
|
18
34
|
* `conflict-id` error, and an unknown id is `unknown-id` like any plan item.
|
|
19
35
|
*/
|
|
20
36
|
excluded?: { id: string; reason: string }[];
|
|
37
|
+
/** Optional master-artifact fields rendered deterministically by `daily-editorial-render` (0345 R10). */
|
|
38
|
+
cover?: string;
|
|
39
|
+
cards?: ScriptPlanCards;
|
|
40
|
+
social?: ScriptPlanSocial;
|
|
21
41
|
}
|
|
22
42
|
|
|
23
43
|
/**
|
|
24
|
-
* Machine-readable part of the style
|
|
44
|
+
* Machine-readable part of the style contract `plugins/kk/skills/news-editorial/references/style-contract.zh.md` (ADR-045) — the
|
|
25
45
|
* same fenced `json` block the script-write prompt reads, so prompt and validator share one source.
|
|
26
46
|
*/
|
|
27
47
|
export interface StyleContract {
|
|
28
|
-
caps: {
|
|
48
|
+
caps: {
|
|
49
|
+
intro: number;
|
|
50
|
+
outro: number;
|
|
51
|
+
lead: number;
|
|
52
|
+
insight: number;
|
|
53
|
+
cover?: number;
|
|
54
|
+
cardCopy?: number;
|
|
55
|
+
cardTitle?: number;
|
|
56
|
+
socialShort?: number;
|
|
57
|
+
socialLong?: number;
|
|
58
|
+
};
|
|
29
59
|
banned: string[];
|
|
30
60
|
}
|
|
31
61
|
|
|
@@ -37,6 +67,12 @@ export interface ScriptPlanError {
|
|
|
37
67
|
|
|
38
68
|
export type ScriptPlanValidation = { ok: true; plan: ScriptPlan } | { ok: false; errors: ScriptPlanError[] };
|
|
39
69
|
|
|
70
|
+
const ScriptPlanItemCardSchema = z.object({
|
|
71
|
+
copy: z.string().min(1),
|
|
72
|
+
points: z.array(z.string().min(1)).min(2).max(4),
|
|
73
|
+
subject: z.string().min(1),
|
|
74
|
+
});
|
|
75
|
+
|
|
40
76
|
/**
|
|
41
77
|
* Empty spoken text is a shape error (`schema`), not a cap/banned case: an empty intro or insight
|
|
42
78
|
* would normalize to a bare 「。」 segment, which no valid episode contains.
|
|
@@ -45,6 +81,7 @@ const ScriptPlanItemSchema = z.object({
|
|
|
45
81
|
id: z.string().min(1),
|
|
46
82
|
lead: z.string().min(1),
|
|
47
83
|
insight: z.string().min(1),
|
|
84
|
+
card: ScriptPlanItemCardSchema.optional(),
|
|
48
85
|
});
|
|
49
86
|
|
|
50
87
|
const ScriptPlanExclusionSchema = z.object({
|
|
@@ -52,12 +89,25 @@ const ScriptPlanExclusionSchema = z.object({
|
|
|
52
89
|
reason: z.string().min(1),
|
|
53
90
|
});
|
|
54
91
|
|
|
92
|
+
const ScriptPlanCardsSchema = z.object({
|
|
93
|
+
title: z.string().min(1),
|
|
94
|
+
body: z.string().min(1),
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
const ScriptPlanSocialSchema = z.object({
|
|
98
|
+
short: z.string().min(1),
|
|
99
|
+
long: z.string().min(1),
|
|
100
|
+
});
|
|
101
|
+
|
|
55
102
|
const ScriptPlanSchema = z.object({
|
|
56
103
|
version: z.literal(1),
|
|
57
104
|
intro: z.string().min(1),
|
|
58
105
|
outro: z.string().min(1),
|
|
59
106
|
items: z.array(ScriptPlanItemSchema),
|
|
60
107
|
excluded: z.array(ScriptPlanExclusionSchema).optional(),
|
|
108
|
+
cover: z.string().min(1).optional(),
|
|
109
|
+
cards: ScriptPlanCardsSchema.optional(),
|
|
110
|
+
social: ScriptPlanSocialSchema.optional(),
|
|
61
111
|
});
|
|
62
112
|
|
|
63
113
|
const StyleContractSchema = z.object({
|
|
@@ -66,6 +116,11 @@ const StyleContractSchema = z.object({
|
|
|
66
116
|
outro: z.number().int().positive(),
|
|
67
117
|
lead: z.number().int().positive(),
|
|
68
118
|
insight: z.number().int().positive(),
|
|
119
|
+
cover: z.number().int().positive().optional(),
|
|
120
|
+
cardCopy: z.number().int().positive().optional(),
|
|
121
|
+
cardTitle: z.number().int().positive().optional(),
|
|
122
|
+
socialShort: z.number().int().positive().optional(),
|
|
123
|
+
socialLong: z.number().int().positive().optional(),
|
|
69
124
|
}),
|
|
70
125
|
banned: z.array(z.string().min(1)),
|
|
71
126
|
});
|
|
@@ -131,7 +186,12 @@ function redundantInsightClauses(insight: string, reference: string): number {
|
|
|
131
186
|
}
|
|
132
187
|
return count;
|
|
133
188
|
}
|
|
134
|
-
export function validateScriptPlan(
|
|
189
|
+
export function validateScriptPlan(
|
|
190
|
+
plan: unknown,
|
|
191
|
+
docs: Doc[],
|
|
192
|
+
style: StyleContract,
|
|
193
|
+
preExcludedIds?: ReadonlySet<string>,
|
|
194
|
+
): ScriptPlanValidation {
|
|
135
195
|
const parsed = ScriptPlanSchema.safeParse(plan);
|
|
136
196
|
if (!parsed.success) {
|
|
137
197
|
return { ok: false, errors: [{ itemId: 'episode', rule: 'schema' }] };
|
|
@@ -146,7 +206,9 @@ export function validateScriptPlan(plan: unknown, docs: Doc[], style: StyleContr
|
|
|
146
206
|
const plannedIds = new Set(valid.items.map((item) => item.id));
|
|
147
207
|
const excludedIds = new Set((valid.excluded ?? []).map((ex) => ex.id));
|
|
148
208
|
for (const ex of valid.excluded ?? []) {
|
|
149
|
-
if (!docIds.has(ex.id)
|
|
209
|
+
if (!docIds.has(ex.id) && !preExcludedIds?.has(ex.id)) {
|
|
210
|
+
errors.push({ itemId: ex.id, rule: 'unknown-id' });
|
|
211
|
+
}
|
|
150
212
|
if (plannedIds.has(ex.id)) errors.push({ itemId: ex.id, rule: 'conflict-id' });
|
|
151
213
|
}
|
|
152
214
|
for (const doc of docs) {
|
|
@@ -155,9 +217,26 @@ export function validateScriptPlan(plan: unknown, docs: Doc[], style: StyleContr
|
|
|
155
217
|
|
|
156
218
|
if (valid.intro.length > style.caps.intro) errors.push({ itemId: 'episode', rule: 'cap:intro' });
|
|
157
219
|
if (valid.outro.length > style.caps.outro) errors.push({ itemId: 'episode', rule: 'cap:outro' });
|
|
220
|
+
if (valid.cover !== undefined && valid.cover.length > (style.caps.cover ?? 240)) {
|
|
221
|
+
errors.push({ itemId: 'episode', rule: 'cap:cover' });
|
|
222
|
+
}
|
|
223
|
+
if (valid.cards !== undefined && valid.cards.title.length > (style.caps.cardTitle ?? 20)) {
|
|
224
|
+
errors.push({ itemId: 'episode', rule: 'cap:cardTitle' });
|
|
225
|
+
}
|
|
226
|
+
if (valid.social !== undefined) {
|
|
227
|
+
if (valid.social.short.length > (style.caps.socialShort ?? 140)) {
|
|
228
|
+
errors.push({ itemId: 'episode', rule: 'cap:socialShort' });
|
|
229
|
+
}
|
|
230
|
+
if (valid.social.long.length > (style.caps.socialLong ?? 500)) {
|
|
231
|
+
errors.push({ itemId: 'episode', rule: 'cap:socialLong' });
|
|
232
|
+
}
|
|
233
|
+
}
|
|
158
234
|
for (const item of valid.items) {
|
|
159
235
|
if (item.lead.length > style.caps.lead) errors.push({ itemId: item.id, rule: 'cap:lead' });
|
|
160
236
|
if (item.insight.length > style.caps.insight) errors.push({ itemId: item.id, rule: 'cap:insight' });
|
|
237
|
+
if (item.card !== undefined && item.card.copy.length > (style.caps.cardCopy ?? 12)) {
|
|
238
|
+
errors.push({ itemId: item.id, rule: 'cap:cardCopy' });
|
|
239
|
+
}
|
|
161
240
|
const doc = docs.find((entry) => entry.id === item.id);
|
|
162
241
|
// unknown-id is already reported above; skip the redundancy check rather than double-report.
|
|
163
242
|
if (
|
|
@@ -171,9 +250,28 @@ export function validateScriptPlan(plan: unknown, docs: Doc[], style: StyleContr
|
|
|
171
250
|
const fields: { itemId: string; text: string }[] = [
|
|
172
251
|
{ itemId: 'episode', text: valid.intro },
|
|
173
252
|
{ itemId: 'episode', text: valid.outro },
|
|
253
|
+
...(valid.cover !== undefined ? [{ itemId: 'episode', text: valid.cover }] : []),
|
|
254
|
+
...(valid.cards !== undefined
|
|
255
|
+
? [
|
|
256
|
+
{ itemId: 'episode', text: valid.cards.title },
|
|
257
|
+
{ itemId: 'episode', text: valid.cards.body },
|
|
258
|
+
]
|
|
259
|
+
: []),
|
|
260
|
+
...(valid.social !== undefined
|
|
261
|
+
? [
|
|
262
|
+
{ itemId: 'episode', text: valid.social.short },
|
|
263
|
+
{ itemId: 'episode', text: valid.social.long },
|
|
264
|
+
]
|
|
265
|
+
: []),
|
|
174
266
|
...valid.items.flatMap((item) => [
|
|
175
267
|
{ itemId: item.id, text: item.lead },
|
|
176
268
|
{ itemId: item.id, text: item.insight },
|
|
269
|
+
...(item.card !== undefined
|
|
270
|
+
? [
|
|
271
|
+
{ itemId: item.id, text: item.card.copy },
|
|
272
|
+
...item.card.points.map((point) => ({ itemId: item.id, text: point })),
|
|
273
|
+
]
|
|
274
|
+
: []),
|
|
177
275
|
]),
|
|
178
276
|
];
|
|
179
277
|
for (const field of fields) {
|
|
@@ -12225,11 +12225,11 @@ var PluginManifestSchemaBase = looseObject({
|
|
|
12225
12225
|
});
|
|
12226
12226
|
var PluginManifestSchema = PluginManifestSchemaBase.superRefine((manifest, ctx) => {
|
|
12227
12227
|
if (manifest.browserSession !== undefined) {
|
|
12228
|
-
if (manifest.kind !== "publish") {
|
|
12228
|
+
if (manifest.kind !== "publish" && manifest.kind !== "ingestion") {
|
|
12229
12229
|
ctx.addIssue({
|
|
12230
12230
|
code: "custom",
|
|
12231
12231
|
path: ["browserSession"],
|
|
12232
|
-
message: `browserSession requires kind "publish", not "${manifest.kind}"`
|
|
12232
|
+
message: `browserSession requires kind "publish" or "ingestion", not "${manifest.kind}"`
|
|
12233
12233
|
});
|
|
12234
12234
|
}
|
|
12235
12235
|
if (manifest.check === undefined) {
|
|
@@ -12228,11 +12228,11 @@ var PluginManifestSchemaBase = looseObject({
|
|
|
12228
12228
|
});
|
|
12229
12229
|
var PluginManifestSchema = PluginManifestSchemaBase.superRefine((manifest, ctx) => {
|
|
12230
12230
|
if (manifest.browserSession !== undefined) {
|
|
12231
|
-
if (manifest.kind !== "publish") {
|
|
12231
|
+
if (manifest.kind !== "publish" && manifest.kind !== "ingestion") {
|
|
12232
12232
|
ctx.addIssue({
|
|
12233
12233
|
code: "custom",
|
|
12234
12234
|
path: ["browserSession"],
|
|
12235
|
-
message: `browserSession requires kind "publish", not "${manifest.kind}"`
|
|
12235
|
+
message: `browserSession requires kind "publish" or "ingestion", not "${manifest.kind}"`
|
|
12236
12236
|
});
|
|
12237
12237
|
}
|
|
12238
12238
|
if (manifest.check === undefined) {
|
|
@@ -12566,11 +12566,11 @@ var PluginManifestSchemaBase = looseObject({
|
|
|
12566
12566
|
});
|
|
12567
12567
|
var PluginManifestSchema = PluginManifestSchemaBase.superRefine((manifest, ctx) => {
|
|
12568
12568
|
if (manifest.browserSession !== undefined) {
|
|
12569
|
-
if (manifest.kind !== "publish") {
|
|
12569
|
+
if (manifest.kind !== "publish" && manifest.kind !== "ingestion") {
|
|
12570
12570
|
ctx.addIssue({
|
|
12571
12571
|
code: "custom",
|
|
12572
12572
|
path: ["browserSession"],
|
|
12573
|
-
message: `browserSession requires kind "publish", not "${manifest.kind}"`
|
|
12573
|
+
message: `browserSession requires kind "publish" or "ingestion", not "${manifest.kind}"`
|
|
12574
12574
|
});
|
|
12575
12575
|
}
|
|
12576
12576
|
if (manifest.check === undefined) {
|
|
@@ -12225,11 +12225,11 @@ var PluginManifestSchemaBase = looseObject({
|
|
|
12225
12225
|
});
|
|
12226
12226
|
var PluginManifestSchema = PluginManifestSchemaBase.superRefine((manifest, ctx) => {
|
|
12227
12227
|
if (manifest.browserSession !== undefined) {
|
|
12228
|
-
if (manifest.kind !== "publish") {
|
|
12228
|
+
if (manifest.kind !== "publish" && manifest.kind !== "ingestion") {
|
|
12229
12229
|
ctx.addIssue({
|
|
12230
12230
|
code: "custom",
|
|
12231
12231
|
path: ["browserSession"],
|
|
12232
|
-
message: `browserSession requires kind "publish", not "${manifest.kind}"`
|
|
12232
|
+
message: `browserSession requires kind "publish" or "ingestion", not "${manifest.kind}"`
|
|
12233
12233
|
});
|
|
12234
12234
|
}
|
|
12235
12235
|
if (manifest.check === undefined) {
|
|
@@ -12225,11 +12225,11 @@ var PluginManifestSchemaBase = looseObject({
|
|
|
12225
12225
|
});
|
|
12226
12226
|
var PluginManifestSchema = PluginManifestSchemaBase.superRefine((manifest, ctx) => {
|
|
12227
12227
|
if (manifest.browserSession !== undefined) {
|
|
12228
|
-
if (manifest.kind !== "publish") {
|
|
12228
|
+
if (manifest.kind !== "publish" && manifest.kind !== "ingestion") {
|
|
12229
12229
|
ctx.addIssue({
|
|
12230
12230
|
code: "custom",
|
|
12231
12231
|
path: ["browserSession"],
|
|
12232
|
-
message: `browserSession requires kind "publish", not "${manifest.kind}"`
|
|
12232
|
+
message: `browserSession requires kind "publish" or "ingestion", not "${manifest.kind}"`
|
|
12233
12233
|
});
|
|
12234
12234
|
}
|
|
12235
12235
|
if (manifest.check === undefined) {
|
|
@@ -12228,11 +12228,11 @@ var PluginManifestSchemaBase = looseObject({
|
|
|
12228
12228
|
});
|
|
12229
12229
|
var PluginManifestSchema = PluginManifestSchemaBase.superRefine((manifest, ctx) => {
|
|
12230
12230
|
if (manifest.browserSession !== undefined) {
|
|
12231
|
-
if (manifest.kind !== "publish") {
|
|
12231
|
+
if (manifest.kind !== "publish" && manifest.kind !== "ingestion") {
|
|
12232
12232
|
ctx.addIssue({
|
|
12233
12233
|
code: "custom",
|
|
12234
12234
|
path: ["browserSession"],
|
|
12235
|
-
message: `browserSession requires kind "publish", not "${manifest.kind}"`
|
|
12235
|
+
message: `browserSession requires kind "publish" or "ingestion", not "${manifest.kind}"`
|
|
12236
12236
|
});
|
|
12237
12237
|
}
|
|
12238
12238
|
if (manifest.check === undefined) {
|
|
@@ -12477,11 +12477,11 @@ var PluginManifestSchemaBase = looseObject({
|
|
|
12477
12477
|
});
|
|
12478
12478
|
var PluginManifestSchema = PluginManifestSchemaBase.superRefine((manifest, ctx) => {
|
|
12479
12479
|
if (manifest.browserSession !== undefined) {
|
|
12480
|
-
if (manifest.kind !== "publish") {
|
|
12480
|
+
if (manifest.kind !== "publish" && manifest.kind !== "ingestion") {
|
|
12481
12481
|
ctx.addIssue({
|
|
12482
12482
|
code: "custom",
|
|
12483
12483
|
path: ["browserSession"],
|
|
12484
|
-
message: `browserSession requires kind "publish", not "${manifest.kind}"`
|
|
12484
|
+
message: `browserSession requires kind "publish" or "ingestion", not "${manifest.kind}"`
|
|
12485
12485
|
});
|
|
12486
12486
|
}
|
|
12487
12487
|
if (manifest.check === undefined) {
|
|
@@ -12226,11 +12226,11 @@ var PluginManifestSchemaBase = looseObject({
|
|
|
12226
12226
|
});
|
|
12227
12227
|
var PluginManifestSchema = PluginManifestSchemaBase.superRefine((manifest, ctx) => {
|
|
12228
12228
|
if (manifest.browserSession !== undefined) {
|
|
12229
|
-
if (manifest.kind !== "publish") {
|
|
12229
|
+
if (manifest.kind !== "publish" && manifest.kind !== "ingestion") {
|
|
12230
12230
|
ctx.addIssue({
|
|
12231
12231
|
code: "custom",
|
|
12232
12232
|
path: ["browserSession"],
|
|
12233
|
-
message: `browserSession requires kind "publish", not "${manifest.kind}"`
|
|
12233
|
+
message: `browserSession requires kind "publish" or "ingestion", not "${manifest.kind}"`
|
|
12234
12234
|
});
|
|
12235
12235
|
}
|
|
12236
12236
|
if (manifest.check === undefined) {
|
|
@@ -12227,11 +12227,11 @@ var PluginManifestSchemaBase = looseObject({
|
|
|
12227
12227
|
});
|
|
12228
12228
|
var PluginManifestSchema = PluginManifestSchemaBase.superRefine((manifest, ctx) => {
|
|
12229
12229
|
if (manifest.browserSession !== undefined) {
|
|
12230
|
-
if (manifest.kind !== "publish") {
|
|
12230
|
+
if (manifest.kind !== "publish" && manifest.kind !== "ingestion") {
|
|
12231
12231
|
ctx.addIssue({
|
|
12232
12232
|
code: "custom",
|
|
12233
12233
|
path: ["browserSession"],
|
|
12234
|
-
message: `browserSession requires kind "publish", not "${manifest.kind}"`
|
|
12234
|
+
message: `browserSession requires kind "publish" or "ingestion", not "${manifest.kind}"`
|
|
12235
12235
|
});
|
|
12236
12236
|
}
|
|
12237
12237
|
if (manifest.check === undefined) {
|
|
@@ -12246,11 +12246,11 @@ var PluginManifestSchemaBase = looseObject({
|
|
|
12246
12246
|
});
|
|
12247
12247
|
var PluginManifestSchema = PluginManifestSchemaBase.superRefine((manifest, ctx) => {
|
|
12248
12248
|
if (manifest.browserSession !== undefined) {
|
|
12249
|
-
if (manifest.kind !== "publish") {
|
|
12249
|
+
if (manifest.kind !== "publish" && manifest.kind !== "ingestion") {
|
|
12250
12250
|
ctx.addIssue({
|
|
12251
12251
|
code: "custom",
|
|
12252
12252
|
path: ["browserSession"],
|
|
12253
|
-
message: `browserSession requires kind "publish", not "${manifest.kind}"`
|
|
12253
|
+
message: `browserSession requires kind "publish" or "ingestion", not "${manifest.kind}"`
|
|
12254
12254
|
});
|
|
12255
12255
|
}
|
|
12256
12256
|
if (manifest.check === undefined) {
|
package/plugins/kk/plugin.json
CHANGED