@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"];
|
|
@@ -22268,7 +22288,7 @@ function createVoiceboxClient(options = {}) {
|
|
|
22268
22288
|
}
|
|
22269
22289
|
} catch (err) {
|
|
22270
22290
|
const reason = err instanceof Error ? err.message : String(err);
|
|
22271
|
-
throw new Error(`Voicebox health check failed at ${url2}: ${reason}`);
|
|
22291
|
+
throw new Error(`Voicebox health check failed at ${url2}: ${reason} \u2014 is Voicebox.app running with its REST server enabled? (restart the app or fix VOICEBOX_URL)`);
|
|
22272
22292
|
}
|
|
22273
22293
|
},
|
|
22274
22294
|
async resolveProfile(nameOrId) {
|
|
@@ -22810,11 +22830,18 @@ async function processGeneratorIO(inputPath, outputPath, clientOverride, transco
|
|
|
22810
22830
|
const scripts = docs.map((doc2) => parseDocToVoiceScript(doc2, envDefaultProfile));
|
|
22811
22831
|
const combinedScript = mergeVoiceScripts(scripts, docs, envDefaultProfile);
|
|
22812
22832
|
validateVoiceScript(combinedScript);
|
|
22833
|
+
const renderStartedAt = Date.now();
|
|
22834
|
+
const maxRunMs = process.env.VOICE_GEN_MAX_RUN_MS ? parseInt(process.env.VOICE_GEN_MAX_RUN_MS, 10) : 0;
|
|
22835
|
+
echoError(`voice-gen: ${combinedScript.segments.length} segments queued for local render`);
|
|
22813
22836
|
const segmentWavs = [];
|
|
22814
22837
|
const segmentGaps = [];
|
|
22815
22838
|
const segmentMetadata = [];
|
|
22816
22839
|
let totalDuration = 0;
|
|
22817
|
-
for (const segment of combinedScript.segments) {
|
|
22840
|
+
for (const [segIndex, segment] of combinedScript.segments.entries()) {
|
|
22841
|
+
if (maxRunMs > 0 && Date.now() - renderStartedAt > maxRunMs) {
|
|
22842
|
+
throw new Error(`voice-gen: render budget ${maxRunMs}ms exceeded after ${segIndex}/${combinedScript.segments.length} segments \u2014 Voicebox may be wedged; raise VOICE_GEN_MAX_RUN_MS if the render is legitimately long`);
|
|
22843
|
+
}
|
|
22844
|
+
const segStartedAt = Date.now();
|
|
22818
22845
|
const speakerConfig = segment.speaker ? combinedScript.speakers?.[segment.speaker] : undefined;
|
|
22819
22846
|
const profileTarget = segment.profile_id ?? segment.profile ?? speakerConfig?.profile_id ?? speakerConfig?.profile ?? combinedScript.default_profile_id ?? combinedScript.default_profile ?? envDefaultProfile ?? (typeof docs[0]?.metadata?.voiceProfile === "string" ? docs[0].metadata.voiceProfile : undefined);
|
|
22820
22847
|
if (!profileTarget) {
|
|
@@ -22930,6 +22957,7 @@ async function processGeneratorIO(inputPath, outputPath, clientOverride, transco
|
|
|
22930
22957
|
transcription,
|
|
22931
22958
|
loudnessDip
|
|
22932
22959
|
});
|
|
22960
|
+
echoError(`voice-gen: segment ${segIndex + 1}/${combinedScript.segments.length} done in ${((Date.now() - segStartedAt) / 1000).toFixed(1)}s${verifyRetries ? ` (${verifyRetries} verify ${verifyRetries === 1 ? "retry" : "retries"})` : ""}`);
|
|
22933
22961
|
}
|
|
22934
22962
|
const concatenatedWav = concatWavs(segmentWavs, segmentGaps);
|
|
22935
22963
|
await fs.ensureDir(outDir);
|
|
@@ -83,6 +83,12 @@ export async function processGeneratorIO(
|
|
|
83
83
|
// 3. Validate VoiceScript
|
|
84
84
|
validateVoiceScript(combinedScript);
|
|
85
85
|
|
|
86
|
+
// Local render can take hours; per-segment progress + an optional total budget keep
|
|
87
|
+
// long renders observable and bounded (dogfood 2026-09-12: healthy 72-min render read as a hang).
|
|
88
|
+
const renderStartedAt = Date.now();
|
|
89
|
+
const maxRunMs = process.env.VOICE_GEN_MAX_RUN_MS ? parseInt(process.env.VOICE_GEN_MAX_RUN_MS, 10) : 0;
|
|
90
|
+
echoError(`voice-gen: ${combinedScript.segments.length} segments queued for local render`);
|
|
91
|
+
|
|
86
92
|
// 4. Generate each segment
|
|
87
93
|
const segmentWavs: Uint8Array[] = [];
|
|
88
94
|
const segmentGaps: number[] = [];
|
|
@@ -98,7 +104,13 @@ export async function processGeneratorIO(
|
|
|
98
104
|
}> = [];
|
|
99
105
|
let totalDuration = 0;
|
|
100
106
|
|
|
101
|
-
for (const segment of combinedScript.segments) {
|
|
107
|
+
for (const [segIndex, segment] of combinedScript.segments.entries()) {
|
|
108
|
+
if (maxRunMs > 0 && Date.now() - renderStartedAt > maxRunMs) {
|
|
109
|
+
throw new Error(
|
|
110
|
+
`voice-gen: render budget ${maxRunMs}ms exceeded after ${segIndex}/${combinedScript.segments.length} segments — Voicebox may be wedged; raise VOICE_GEN_MAX_RUN_MS if the render is legitimately long`,
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
const segStartedAt = Date.now();
|
|
102
114
|
const speakerConfig = segment.speaker ? combinedScript.speakers?.[segment.speaker] : undefined;
|
|
103
115
|
const profileTarget =
|
|
104
116
|
segment.profile_id ??
|
|
@@ -284,6 +296,9 @@ export async function processGeneratorIO(
|
|
|
284
296
|
transcription,
|
|
285
297
|
loudnessDip,
|
|
286
298
|
});
|
|
299
|
+
echoError(
|
|
300
|
+
`voice-gen: segment ${segIndex + 1}/${combinedScript.segments.length} done in ${((Date.now() - segStartedAt) / 1000).toFixed(1)}s${verifyRetries ? ` (${verifyRetries} verify ${verifyRetries === 1 ? 'retry' : 'retries'})` : ''}`,
|
|
301
|
+
);
|
|
287
302
|
}
|
|
288
303
|
|
|
289
304
|
// 5. Concatenate audio
|
|
@@ -73,7 +73,9 @@ export function createVoiceboxClient(options: VoiceboxClientOptions = {}): Voice
|
|
|
73
73
|
}
|
|
74
74
|
} catch (err: unknown) {
|
|
75
75
|
const reason = err instanceof Error ? err.message : String(err);
|
|
76
|
-
throw new Error(
|
|
76
|
+
throw new Error(
|
|
77
|
+
`Voicebox health check failed at ${url}: ${reason} — is Voicebox.app running with its REST server enabled? (restart the app or fix VOICEBOX_URL)`,
|
|
78
|
+
);
|
|
77
79
|
}
|
|
78
80
|
},
|
|
79
81
|
|
|
@@ -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"];
|
|
@@ -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"];
|
|
@@ -21850,6 +21850,26 @@ var ResultSchema = exports_external.object({
|
|
|
21850
21850
|
metadata: exports_external.record(exports_external.string(), exports_external.unknown()).optional()
|
|
21851
21851
|
});
|
|
21852
21852
|
var DocListSchema = exports_external.array(DocSchema);
|
|
21853
|
+
var omniVoiceGenContentSchema = ContentSchema.extend({
|
|
21854
|
+
format: exports_external.literal("audio"),
|
|
21855
|
+
metadata: exports_external.looseObject({
|
|
21856
|
+
generator: exports_external.literal("kk:omni-voice-gen"),
|
|
21857
|
+
audioPath: exports_external.string(),
|
|
21858
|
+
duration: exports_external.number(),
|
|
21859
|
+
segments: exports_external.array(exports_external.looseObject({
|
|
21860
|
+
generationId: exports_external.string(),
|
|
21861
|
+
profile: exports_external.string(),
|
|
21862
|
+
speaker: exports_external.string().optional(),
|
|
21863
|
+
emotion: exports_external.string().optional(),
|
|
21864
|
+
duration: exports_external.number(),
|
|
21865
|
+
verifyRetries: exports_external.number(),
|
|
21866
|
+
transcription: exports_external.string().optional(),
|
|
21867
|
+
loudnessDip: exports_external.boolean().optional()
|
|
21868
|
+
})),
|
|
21869
|
+
mp3Path: exports_external.string().optional(),
|
|
21870
|
+
qc: exports_external.record(exports_external.string(), exports_external.unknown()).optional()
|
|
21871
|
+
})
|
|
21872
|
+
});
|
|
21853
21873
|
|
|
21854
21874
|
// ../../packages/kk-core/src/kinds.ts
|
|
21855
21875
|
var PLUGIN_KINDS = ["ingestion", "generator", "publish"];
|
|
@@ -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"];
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: image-extract
|
|
3
|
+
description: Extract a reusable style preset (and optionally draft a format preset) from 1-5 reference images, saved to ~/.config/kk/image-presets/ after confirmation.
|
|
4
|
+
argument-hint: "--name <style-name> --ref <img> [--ref <img>…] [--emit-format <name> --job free|cover|illustration] (max 5 refs)"
|
|
5
|
+
allowed-tools: ["Skill"]
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# image-extract
|
|
9
|
+
|
|
10
|
+
Thin wrapper for the `image-authoring` skill's `extract-style` operation — all vision
|
|
11
|
+
analysis, schema-fill, merge, and validation logic lives in the skill. Forward
|
|
12
|
+
`$ARGUMENTS` with one substitution: this command's `--name <style-name>` is the skill's
|
|
13
|
+
`--extract-style <name>` (the flag doubles as the operation selector there — rewrite it,
|
|
14
|
+
do not pass `--name` through). `--ref`, `--emit-format`, and `--job` pass through unchanged.
|
|
15
|
+
|
|
16
|
+
```text
|
|
17
|
+
Skill(skill="kk:image-authoring", args="$ARGUMENTS with --name rewritten to --extract-style")
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## What it does
|
|
21
|
+
|
|
22
|
+
- Reads 1–5 reference images (`--ref`, repeatable; more than 5 is refused), analyses
|
|
23
|
+
the look, and shows you the composed `StylePreset` YAML for `--name <style-name>`.
|
|
24
|
+
- **Confirms with you before writing**, then saves to the user root
|
|
25
|
+
`~/.config/kk/image-presets/styles/<name>.yaml` — usable immediately via
|
|
26
|
+
`/kk:image-generate --style <name>`, shadowing any shipped preset of the same name.
|
|
27
|
+
- With `--emit-format <name> --job <job>`, additionally **drafts** a format preset from
|
|
28
|
+
the same images: measured dimensions + declared job + visual defaults authored from
|
|
29
|
+
the analysis, skeleton (variables, template grammar) reused from the shipped format
|
|
30
|
+
of the same job. Shown for confirmation and fine-tuning, then written to
|
|
31
|
+
`~/.config/kk/image-presets/formats/<name>.yaml` with `defaultStyle` set to the
|
|
32
|
+
style just extracted.
|
|
33
|
+
- Validates each new preset with a dry-run generation (`KK_IMAGE_DRY_RUN=1`).
|
|
34
|
+
|
|
35
|
+
Examples:
|
|
36
|
+
|
|
37
|
+
```text
|
|
38
|
+
/kk:image-extract --name flat-retro --ref a.png --ref b.png
|
|
39
|
+
/kk:image-extract --name flat-retro --ref a.png --emit-format retro-cover --job cover
|
|
40
|
+
```
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: image-generate
|
|
3
3
|
description: Generate images from a prompt or an article — covers, illustrations, or free-form — using named format and style presets.
|
|
4
|
-
argument-hint: "[prompt] [--format
|
|
4
|
+
argument-hint: "[prompt] [--format free|cover|illustration] [--style vibrant|minimalist|photorealistic|technical-diagram|editorial|fresh|warm|cute|sketch|clean-webapp-ui|<custom>] [--content <file>] [--ref <img>…] [--var K=V] [--dry-run] [--list-presets]"
|
|
5
5
|
allowed-tools: ["Skill"]
|
|
6
6
|
---
|
|
7
7
|
|
|
@@ -13,3 +13,20 @@ confirmation and delegation logic lives in the skill. Forward `$ARGUMENTS` uncha
|
|
|
13
13
|
```text
|
|
14
14
|
Skill(skill="kk:image-authoring", args="$ARGUMENTS")
|
|
15
15
|
```
|
|
16
|
+
|
|
17
|
+
## Built-in presets (user presets under `~/.config/kk/image-presets/` shadow these)
|
|
18
|
+
|
|
19
|
+
**Formats** (`--format`; default `free`):
|
|
20
|
+
|
|
21
|
+
| Format | Job | Aspect | Default style |
|
|
22
|
+
| ------ | --- | ------ | ------------- |
|
|
23
|
+
| `free` | free-form image from the positional prompt | 1:1 | vibrant |
|
|
24
|
+
| `cover` | article cover; requires `--content <file>` | 21:9 | vibrant |
|
|
25
|
+
| `illustration` | auto-insert illustrations into `--content <file>` | 4:3 | technical-diagram |
|
|
26
|
+
|
|
27
|
+
**Styles** (`--style`): `vibrant` · `minimalist` · `photorealistic` · `technical-diagram` ·
|
|
28
|
+
`editorial` · `fresh` · `warm` · `cute` · `sketch` · `clean-webapp-ui` — or any custom style
|
|
29
|
+
preset name. Omit to use the preference `image.style` or the format's default.
|
|
30
|
+
|
|
31
|
+
Run `--list-presets` for the live list with origins and shadows. Create new presets from
|
|
32
|
+
reference images with `/kk:image-extract`.
|
package/plugins/kk/plugin.json
CHANGED
|
@@ -86,8 +86,10 @@ owns the schema-fill rules, the multi-image merge rules, the cap-5 refusal wordi
|
|
|
86
86
|
where the preset is written (user root, shadowing by design), and the validation step:
|
|
87
87
|
read the images with your own vision, write `~/.config/kk/image-presets/styles/<name>.yaml`
|
|
88
88
|
filling exactly the `StylePreset` fields, then validate with a `KK_IMAGE_DRY_RUN=1` run
|
|
89
|
-
whose `style` is the new preset's name. Extraction
|
|
90
|
-
|
|
89
|
+
whose `style` is the new preset's name. Extraction writes `styles/*.yaml`; with
|
|
90
|
+
`--emit-format <name> --job <job>` it additionally **drafts** a `formats/*.yaml` from
|
|
91
|
+
the same references — a different act with its own authoritative procedure:
|
|
92
|
+
[references/format-drafting.md](references/format-drafting.md).
|
|
91
93
|
|
|
92
94
|
### list-presets
|
|
93
95
|
|
|
@@ -109,6 +111,7 @@ output is also the text an unknown `--format`/`--style` refusal quotes.
|
|
|
109
111
|
[prompt] [--format <name>] [--style <name>] [--var KEY=VALUE]... [--content <file>]
|
|
110
112
|
[--ref <path>]... [--count <n>] [--provider <name>] [--model <id>]
|
|
111
113
|
[--out <dir|file>] [--dry-run] [--list-presets] [--extract-style <name>]
|
|
114
|
+
[--emit-format <name> --job <job>]
|
|
112
115
|
```
|
|
113
116
|
|
|
114
117
|
| Token | Meaning | Default |
|
|
@@ -126,11 +129,15 @@ output is also the text an unknown `--format`/`--style` refusal quotes.
|
|
|
126
129
|
| `--dry-run` | compose and price, generate nothing | off |
|
|
127
130
|
| `--list-presets` | → the `list-presets` operation | — |
|
|
128
131
|
| `--extract-style <name>` | → the `extract-style` operation; **requires `--ref`** | — |
|
|
132
|
+
| `--emit-format <name>` | with `--extract-style`: also draft a format preset from the same refs; **requires `--job`** | — |
|
|
133
|
+
| `--job free\|cover\|illustration` | declared job for the drafted format — never inferred from pixels | — |
|
|
129
134
|
|
|
130
135
|
**Validation is this skill's, before any plugin spawn**, each refusal naming the
|
|
131
136
|
offending argument: unknown `--format` or `--style` (quote what `list-presets` would
|
|
132
137
|
show); `--count` on a non-`illustration` job; more than five `--ref` paths;
|
|
133
|
-
`--extract-style` without `--ref`;
|
|
138
|
+
`--extract-style` without `--ref`; `--emit-format` without `--extract-style` or
|
|
139
|
+
without `--job`, or a `--job` outside `free|cover|illustration`; a `--content` file
|
|
140
|
+
that does not exist. Flags the
|
|
134
141
|
wt plugin retired are **answered, not ignored** — state the replacement and stop; the
|
|
135
142
|
table lives in
|
|
136
143
|
[references/migrating-from-wt.md](references/migrating-from-wt.md)
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# Format drafting from reference images
|
|
2
|
+
|
|
3
|
+
Loaded by the image-authoring skill when `extract-style` runs with
|
|
4
|
+
`--emit-format <name> --job <job>`. Produces a **draft** `FormatPreset` from the same
|
|
5
|
+
reference images, for the operator to confirm and fine-tune. This is drafting, not
|
|
6
|
+
extraction: a picture supplies measurements and visual defaults, never job semantics
|
|
7
|
+
or variable contracts — those are **declared** or **reused**, and the report must say
|
|
8
|
+
which is which.
|
|
9
|
+
|
|
10
|
+
## Field provenance — three tiers, never blurred
|
|
11
|
+
|
|
12
|
+
| Tier | Fields | Source |
|
|
13
|
+
| ---- | ------ | ------ |
|
|
14
|
+
| **Measured** | `aspectRatio`, `width`, `height` | Observed pixel dimensions of the largest reference; `aspectRatio` is the nearest named ratio from `21:9`, `4:3`, `1:1`, `16:9`, `3:4`, `9:16`. No taste involved. |
|
|
15
|
+
| **Declared** | `name`, `job` | The operator's `--emit-format <name>` and `--job <job>`. `job` is never inferred from pixels — a picture does not know whether it is a cover. |
|
|
16
|
+
| **Drafted** | `description`, `keywords`, visual `variables` defaults, `template` | Agent vision over the same references the style came from. Fine-tuning expected. |
|
|
17
|
+
| **Reused** | `defaultStyle`, `outputFilename`, variable names, template grammar | See skeleton rule below. `defaultStyle` is the `--extract-style <name>` of this same run — the pairing is the point of doing both in one pass. |
|
|
18
|
+
|
|
19
|
+
## The skeleton rule
|
|
20
|
+
|
|
21
|
+
Start from the shipped format of the **same job** —
|
|
22
|
+
`plugins/generations/image-gen/presets/formats/<job>.yaml` — read it first, then:
|
|
23
|
+
|
|
24
|
+
- **Keep** its variable names, `outputFilename` grammar, and template placeholder
|
|
25
|
+
structure. The variable-to-article mapping (`{{title}}`, `{{topics}}`, …) is a
|
|
26
|
+
contract with the skill's `cover`/`illustration` branches; renaming variables
|
|
27
|
+
silently breaks `--content` derivation.
|
|
28
|
+
- **Re-author** the visual defaults from the image analysis: `description`,
|
|
29
|
+
`keywords`, and the default values of the visual variables (`visual_style`,
|
|
30
|
+
`composition`, `color_palette`, `atmosphere`, `mood`, or their skeleton
|
|
31
|
+
equivalents) so the drafted prompt would reproduce the reference look.
|
|
32
|
+
- A `free` job needs no `--content` variables; keep the skeleton minimal.
|
|
33
|
+
|
|
34
|
+
## Output rules
|
|
35
|
+
|
|
36
|
+
Emit **YAML only**, filling **exactly** the `FormatPreset` fields of
|
|
37
|
+
`plugins/generations/image-gen/src/presets.ts` (`name`, `description`, `job`,
|
|
38
|
+
`aspectRatio`, optional `width`/`height`, `defaultStyle`, `keywords`,
|
|
39
|
+
`outputFilename`, `variables`, `template`) — inventing a field is a defect, same rule
|
|
40
|
+
as style extraction. Multi-image merge follows the style-extraction rule: visual
|
|
41
|
+
defaults reflect traits present in **every** reference; discarded divergent traits are
|
|
42
|
+
named in the report.
|
|
43
|
+
|
|
44
|
+
## Where the preset goes
|
|
45
|
+
|
|
46
|
+
Write to the **user root**: `~/.config/kk/image-presets/formats/<name>.yaml`, after
|
|
47
|
+
showing the composed YAML and getting confirmation (interactive; the Confirmation
|
|
48
|
+
policy governs). Same-name shipped formats are shadowed whole-file — intended, as
|
|
49
|
+
with styles. No registration step; the 0102 loader scans the roots.
|
|
50
|
+
|
|
51
|
+
## Validation
|
|
52
|
+
|
|
53
|
+
Before reporting done, run one `KK_IMAGE_DRY_RUN=1` generation whose `format` is the
|
|
54
|
+
new preset's name (and whose `style` is the run's extracted style), then report the
|
|
55
|
+
composed prompt from that run's `Content.body`. The report must list each field's
|
|
56
|
+
tier — measured / declared / drafted / reused — so the operator knows exactly what to
|
|
57
|
+
fine-tune.
|
|
@@ -76,15 +76,20 @@ presets and not an average:
|
|
|
76
76
|
- `confidence` — capped at `medium` when the set disagrees on any fidelity axis.
|
|
77
77
|
- `source.refImages` — all N absolute paths, in the order given.
|
|
78
78
|
|
|
79
|
-
## What extraction
|
|
80
|
-
|
|
81
|
-
**Style
|
|
82
|
-
`
|
|
83
|
-
|
|
84
|
-
an image *does* yield is arithmetic
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
79
|
+
## What extraction writes
|
|
80
|
+
|
|
81
|
+
**Style by default; format drafting is opt-in.** A `FormatPreset` carries `template`,
|
|
82
|
+
`variables`, `keywords`, `defaultStyle`, `outputFilename` — none of which is
|
|
83
|
+
*recoverable* from a picture, so extraction alone never writes a `formats/*.yaml`.
|
|
84
|
+
What an image *does* yield is arithmetic: the extraction report **states the observed
|
|
85
|
+
pixel dimensions and the nearest named aspect ratio** of each reference, chosen from
|
|
86
|
+
`21:9`, `4:3`, `1:1`, `16:9`, `3:4`, `9:16`.
|
|
87
|
+
|
|
88
|
+
When the operator passes `--emit-format <name> --job <job>` alongside `--extract-style`,
|
|
89
|
+
that arithmetic plus the same visual analysis feeds a **draft** format preset — measured
|
|
90
|
+
fields taken, visual defaults authored, structural fields reused from the shipped
|
|
91
|
+
skeleton, operator fine-tuning expected. That procedure lives in
|
|
92
|
+
[format-drafting.md](format-drafting.md); this file stays style-only.
|
|
88
93
|
|
|
89
94
|
## Pass-through degradation (visible, never silent)
|
|
90
95
|
|