@oh-story/dsh 0.1.4 → 0.1.6
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/README.md +56 -12
- package/lib/client.js +2707 -268
- package/lib/client.js.map +4 -4
- package/lib/drama/manifest.json +136 -101
- package/lib/drama/skills/short-drama/SKILL.md +61 -1
- package/lib/drama/skills/short-drama/references/contract-and-ownership.md +7 -4
- package/lib/drama/skills/short-drama/references/creator-documents.md +133 -8
- package/lib/drama/skills/short-drama/references/creator-workflow.md +38 -2
- package/lib/drama/skills/short-drama/references/knowhow-index.md +3 -0
- package/lib/drama/skills/short-drama/references/reference-roles.md +10 -7
- package/lib/drama/skills/short-drama/references/runtime-preflight.md +3 -0
- package/lib/drama/skills/short-drama/scripts/creator_markdown_check.py +1002 -0
- package/lib/drama/skills/short-drama/scripts/project_tool.py +485 -5
- package/lib/drama/skills/short-drama-assets/SKILL.md +13 -3
- package/lib/drama/skills/short-drama-assets/references/continuity-lock.md +116 -0
- package/lib/drama/skills/short-drama-assets/references/identity-vs-variant.md +2 -1
- package/lib/drama/skills/short-drama-assets/references/prop-and-state.md +19 -0
- package/lib/drama/skills/short-drama-assets/references/stage-contract.md +2 -0
- package/lib/drama/skills/short-drama-assets/scripts/asset_check.py +1 -1
- package/lib/drama/skills/short-drama-image-prompts/SKILL.md +6 -2
- package/lib/drama/skills/short-drama-image-prompts/references/common-recipe.md +4 -3
- package/lib/drama/skills/short-drama-image-prompts/references/lookdev-frame.md +1 -1
- package/lib/drama/skills/short-drama-image-prompts/references/review-and-fixtures.md +1 -1
- package/lib/drama/skills/short-drama-image-prompts/references/stage-contract.md +3 -1
- package/lib/drama/skills/short-drama-image-prompts/scripts/image_prompt_check.py +8 -8
- package/lib/drama/skills/short-drama-image-prompts/scripts/selftest.py +4 -2
- package/lib/drama/skills/short-drama-produce/SKILL.md +46 -10
- package/lib/drama/skills/short-drama-produce/references/adapter-contract.md +65 -8
- package/lib/drama/skills/short-drama-produce/references/providers/minimax-h3-video.md +85 -0
- package/lib/drama/skills/short-drama-produce/references/providers/seedance.md +27 -10
- package/lib/drama/skills/short-drama-produce/scripts/production_tool.py +362 -3
- package/lib/drama/skills/short-drama-produce/scripts/provider_adapters.py +627 -40
- package/lib/drama/skills/short-drama-produce/scripts/selftest.py +5 -4
- package/lib/drama/skills/short-drama-review/references/rubric-visual-motion.md +12 -0
- package/lib/drama/skills/short-drama-review/scripts/review_check.py +1 -1
- package/lib/drama/skills/short-drama-storyboard/SKILL.md +76 -7
- package/lib/drama/skills/short-drama-storyboard/assets/shot-template.jsonl +1 -1
- package/lib/drama/skills/short-drama-storyboard/references/keyframe-craft.md +6 -2
- package/lib/drama/skills/short-drama-storyboard/references/production-shot-grammar.md +19 -4
- package/lib/drama/skills/short-drama-storyboard/references/review-and-fixtures.md +5 -2
- package/lib/drama/skills/short-drama-storyboard/references/screenplay-to-keyframe-example.md +16 -0
- package/lib/drama/skills/short-drama-storyboard/references/stage-contract.md +8 -3
- package/lib/drama/skills/short-drama-storyboard/scripts/storyboard_check.py +1 -1
- package/lib/drama/skills/short-drama-video-prompts/SKILL.md +81 -13
- package/lib/drama/skills/short-drama-video-prompts/assets/motion-spec.jsonl.md +6 -1
- package/lib/drama/skills/short-drama-video-prompts/assets/video-prompts.md +17 -1
- package/lib/drama/skills/short-drama-video-prompts/references/delivery-profile.md +21 -1
- package/lib/drama/skills/short-drama-video-prompts/references/minimax-h3.md +154 -0
- package/lib/drama/skills/short-drama-video-prompts/references/motion-recipe.md +24 -6
- package/lib/drama/skills/short-drama-video-prompts/references/production-prompt-grammar.md +11 -7
- package/lib/drama/skills/short-drama-video-prompts/references/seedance-2.0.md +41 -0
- package/lib/drama/skills/short-drama-video-prompts/references/seedance-2.5.md +66 -0
- package/lib/drama/skills/short-drama-video-prompts/references/stage-contract.md +5 -2
- package/lib/drama/skills/short-drama-video-prompts/references/target-model-profile.md +115 -0
- package/lib/drama/skills/short-drama-video-prompts/scripts/container_check.py +1 -1
- package/lib/drama/skills/short-drama-video-prompts/scripts/music_spec_check.py +1 -1
- package/lib/drama/skills/short-drama-write/SKILL.md +3 -2
- package/lib/drama/skills/short-drama-write/scripts/duration_estimate.py +1 -1
- package/lib/drama/skills/short-drama-write/scripts/screenplay_index.py +2 -2
- package/lib/drama/skills/short-drama-write/scripts/voice_sheet_check.py +1 -1
- package/lib/index.js +865 -33
- package/lib/index.js.map +4 -4
- package/lib/novel-to-game/LICENSE +21 -0
- package/lib/novel-to-game/README.md +180 -0
- package/lib/novel-to-game/README_ZH.md +178 -0
- package/lib/novel-to-game/VERSION +1 -0
- package/lib/novel-to-game/examples/jin-ping-mei/build/BUILD_BRIEF.md +217 -0
- package/lib/novel-to-game/examples/jin-ping-mei/build/app/.vercelignore +3 -0
- package/lib/novel-to-game/examples/jin-ping-mei/build/app/RUN.md +130 -0
- package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/bg/compound_new_guofeng.webp +0 -0
- package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/cg/finale/fate_coda.webp +0 -0
- package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/cg/finale/meng.webp +0 -0
- package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/cg/finale/pan.webp +0 -0
- package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/cg/finale/pinger.webp +0 -0
- package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/cg/finale/xuee.webp +0 -0
- package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/cg/finale/yue.webp +0 -0
- package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/cg/group/inner_court_accord_five.webp +0 -0
- package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/cg/group/inner_court_afterglow_five.webp +0 -0
- package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/cg/group/inner_court_alliance.webp +0 -0
- package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/cg/group/public_day10.webp +0 -0
- package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/cg/group/public_day15.webp +0 -0
- package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/cg/group/public_day5.webp +0 -0
- package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/cg/group/title_new_guofeng.webp +0 -0
- package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/cg/joint/pan_pinger.webp +0 -0
- package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/cg/joint/pan_xuee.webp +0 -0
- package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/cg/joint/yue_meng.webp +0 -0
- package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/cg/joint/yue_pan.webp +0 -0
- package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/cg/joint/yue_pinger.webp +0 -0
- package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/cg/meng/explicit.webp +0 -0
- package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/cg/meng/prelude.webp +0 -0
- package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/cg/milestone/meng.webp +0 -0
- package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/cg/milestone/pan.webp +0 -0
- package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/cg/milestone/pinger.webp +0 -0
- package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/cg/milestone/xuee.webp +0 -0
- package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/cg/milestone/yue.webp +0 -0
- package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/cg/pan/explicit.webp +0 -0
- package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/cg/pan/prelude.webp +0 -0
- package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/cg/pinger/explicit.webp +0 -0
- package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/cg/pinger/prelude.webp +0 -0
- package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/cg/xuee/explicit.webp +0 -0
- package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/cg/xuee/prelude.webp +0 -0
- package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/cg/yue/explicit.webp +0 -0
- package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/cg/yue/prelude.webp +0 -0
- package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/heroine/meng/night.webp +0 -0
- package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/heroine/pan/night.webp +0 -0
- package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/heroine/pinger/night.webp +0 -0
- package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/heroine/xuee/night.webp +0 -0
- package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/heroine/yue/night.webp +0 -0
- package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/household/li_jiaoer.webp +0 -0
- package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/scene/gate_collector.webp +0 -0
- package/lib/novel-to-game/examples/jin-ping-mei/build/app/css/new-guofeng.css +1105 -0
- package/lib/novel-to-game/examples/jin-ping-mei/build/app/css/style.css +2539 -0
- package/lib/novel-to-game/examples/jin-ping-mei/build/app/index.html +18 -0
- package/lib/novel-to-game/examples/jin-ping-mei/build/app/js/assets.js +147 -0
- package/lib/novel-to-game/examples/jin-ping-mei/build/app/js/audio.js +332 -0
- package/lib/novel-to-game/examples/jin-ping-mei/build/app/js/data.js +7472 -0
- package/lib/novel-to-game/examples/jin-ping-mei/build/app/js/engine.js +13077 -0
- package/lib/novel-to-game/examples/jin-ping-mei/build/app/js/main.js +3028 -0
- package/lib/novel-to-game/examples/jin-ping-mei/build/app/js/text.js +32 -0
- package/lib/novel-to-game/examples/jin-ping-mei/build/app/package.json +10 -0
- package/lib/novel-to-game/examples/jin-ping-mei/build/app/vercel.json +23 -0
- package/lib/novel-to-game/examples/jin-ping-mei/build/art/generated-art.json +161 -0
- package/lib/novel-to-game/examples/jin-ping-mei/example.json +12 -0
- package/lib/novel-to-game/examples/jin-ping-mei/qa/README.md +31 -0
- package/lib/novel-to-game/examples/jin-ping-mei/qa/playable-model.json +99 -0
- package/lib/novel-to-game/examples/jin-ping-mei/qa/verification.json +41 -0
- package/lib/novel-to-game/examples/jin-ping-mei/qa/verify_playable_model.mjs +129 -0
- package/lib/novel-to-game/manifest.json +508 -0
- package/lib/novel-to-game/skills/game-art-direction/SKILL.md +73 -0
- package/lib/novel-to-game/skills/game-art-direction/agents/openai.yaml +4 -0
- package/lib/novel-to-game/skills/game-art-direction/references/art-direction-method.md +119 -0
- package/lib/novel-to-game/skills/game-build/SKILL.md +84 -0
- package/lib/novel-to-game/skills/game-build/agents/openai.yaml +4 -0
- package/lib/novel-to-game/skills/game-build/references/build-brief-contract.md +109 -0
- package/lib/novel-to-game/skills/game-build/references/generative-media-pipeline.md +56 -0
- package/lib/novel-to-game/skills/game-build/references/playable-model-contract.md +81 -0
- package/lib/novel-to-game/skills/game-build/references/tts-production-contract.md +37 -0
- package/lib/novel-to-game/skills/game-concept/SKILL.md +72 -0
- package/lib/novel-to-game/skills/game-concept/agents/openai.yaml +4 -0
- package/lib/novel-to-game/skills/game-concept/references/concept-method.md +94 -0
- package/lib/novel-to-game/skills/game-qa/SKILL.md +50 -0
- package/lib/novel-to-game/skills/game-qa/agents/openai.yaml +4 -0
- package/lib/novel-to-game/skills/game-qa/references/qa-contract.md +66 -0
- package/lib/novel-to-game/skills/game-qa/references/test-design-method.md +45 -0
- package/lib/novel-to-game/skills/game-world-design/SKILL.md +63 -0
- package/lib/novel-to-game/skills/game-world-design/agents/openai.yaml +4 -0
- package/lib/novel-to-game/skills/game-world-design/references/dialogue-design-method.md +59 -0
- package/lib/novel-to-game/skills/game-world-design/references/game-writing-craft.md +53 -0
- package/lib/novel-to-game/skills/game-world-design/references/narrative-design-method.md +84 -0
- package/lib/novel-to-game/skills/game-world-design/references/numeric-design-method.md +56 -0
- package/lib/novel-to-game/skills/game-world-design/references/world-design-method.md +124 -0
- package/lib/novel-to-game/skills/novel-game-analyze/SKILL.md +77 -0
- package/lib/novel-to-game/skills/novel-game-analyze/agents/openai.yaml +4 -0
- package/lib/novel-to-game/skills/novel-game-analyze/references/gameability-protocol.md +65 -0
- package/lib/novel-to-game/skills/novel-to-game/SKILL.md +71 -0
- package/lib/novel-to-game/skills/novel-to-game/agents/openai.yaml +4 -0
- package/lib/novel-to-game/skills/novel-to-game/references/intake-benchmark-reference.md +42 -0
- package/lib/novel-to-game/skills/novel-to-game/references/intake-method.md +51 -0
- package/lib/novel-to-game/skills/novel-to-game/references/pipeline-contract.md +65 -0
- package/lib/oh-story/manifest.json +415 -305
- package/lib/oh-story/roles/consistency-checker.md +1 -1
- package/lib/oh-story/roles/narrative-writer.md +32 -33
- package/lib/oh-story/roles/story-architect.md +16 -26
- package/lib/oh-story/skills/browser-cdp/SKILL.md +1 -1
- package/lib/oh-story/skills/story/SKILL.md +16 -9
- package/lib/oh-story/skills/story/VERSION +1 -1
- package/lib/oh-story/skills/story/references/author-memory.md +163 -0
- package/lib/oh-story/skills/story/scripts/author_memory_commit.py +871 -0
- package/lib/oh-story/skills/story-cover/SKILL.md +1 -1
- package/lib/oh-story/skills/story-deslop/SKILL.md +10 -5
- package/lib/oh-story/skills/story-deslop/references/anti-ai-writing.md +2 -1
- package/lib/oh-story/skills/story-deslop/references/author-memory.md +163 -0
- package/lib/oh-story/skills/story-deslop/references/banned-words.md +6 -4
- package/lib/oh-story/skills/story-deslop/scripts/author_memory_commit.py +871 -0
- package/lib/oh-story/skills/story-deslop/scripts/check-ai-patterns.js +64 -1
- package/lib/oh-story/skills/story-import/SKILL.md +19 -10
- package/lib/oh-story/skills/story-import/references/format-and-structure.md +9 -10
- package/lib/oh-story/skills/story-import/references/structure-mapping-long.md +2 -2
- package/lib/oh-story/skills/story-import/references/structure-mapping-short.md +1 -1
- package/lib/oh-story/skills/story-import/references/tracking-transaction.md +14 -6
- package/lib/oh-story/skills/story-import/scripts/check-outline-contract.js +251 -0
- package/lib/oh-story/skills/story-import/scripts/tracking_commit.py +98 -9
- package/lib/oh-story/skills/story-import/scripts/wordcount_core.py +246 -0
- package/lib/oh-story/skills/story-long-analyze/SKILL.md +4 -4
- package/lib/oh-story/skills/story-long-scan/SKILL.md +1 -1
- package/lib/oh-story/skills/story-long-write/SKILL.md +35 -21
- package/lib/oh-story/skills/story-long-write/references/anti-ai-writing.md +2 -1
- package/lib/oh-story/skills/story-long-write/references/artifact-protocols.md +7 -3
- package/lib/oh-story/skills/story-long-write/references/author-memory.md +163 -0
- package/lib/oh-story/skills/story-long-write/references/banned-words.md +6 -4
- package/lib/oh-story/skills/story-long-write/references/cross-book-recall.md +6 -6
- package/lib/oh-story/skills/story-long-write/references/genre-prose-cards.md +1 -1
- package/lib/oh-story/skills/story-long-write/references/genre-readers.md +1 -1
- package/lib/oh-story/skills/{story-setup/references/agent-references/hooks-chapter.md → story-long-write/references/long-chapter-hooks.md} +5 -5
- package/lib/oh-story/skills/story-long-write/references/{quality-checklist.md → long-chapter-quality.md} +2 -1
- package/lib/oh-story/skills/story-long-write/references/long-format.md +42 -0
- package/lib/oh-story/skills/{story-setup/references/agent-references/genre-catalog.md → story-long-write/references/long-genre-catalog.md} +11 -97
- package/lib/oh-story/skills/{story-setup/references/agent-references/genre-core-mechanics.md → story-long-write/references/long-genre-mechanics.md} +1 -1
- package/lib/oh-story/skills/{story-short-write/references/reversal-toolkit.md → story-long-write/references/long-reversal.md} +18 -32
- package/lib/oh-story/skills/story-long-write/references/{hooks-suspense.md → long-suspense.md} +6 -6
- package/lib/oh-story/skills/story-long-write/references/opening-design.md +1 -1
- package/lib/oh-story/skills/story-long-write/references/outline-structure-theory.md +1 -1
- package/lib/oh-story/skills/story-long-write/references/style-genre-modules.md +1 -1
- package/lib/oh-story/skills/story-long-write/references/tracking-transaction.md +14 -6
- package/lib/oh-story/skills/story-long-write/references/workflow-chapter.md +32 -27
- package/lib/oh-story/skills/story-long-write/references/workflow-daily.md +4 -4
- package/lib/oh-story/skills/story-long-write/references/workflow-revision.md +2 -2
- package/lib/oh-story/skills/story-long-write/references/workflow-setup.md +14 -14
- package/lib/oh-story/skills/story-long-write/references/writing-craft.md +54 -54
- package/lib/oh-story/skills/story-long-write/scripts/author_memory_commit.py +871 -0
- package/lib/oh-story/skills/story-long-write/scripts/check-ai-patterns.js +64 -1
- package/lib/oh-story/skills/story-long-write/scripts/check-outline-contract.js +251 -0
- package/lib/oh-story/skills/story-long-write/scripts/storyctl.py +303 -0
- package/lib/oh-story/skills/story-long-write/scripts/tracking_commit.py +98 -9
- package/lib/oh-story/skills/story-long-write/scripts/wordcount_core.py +246 -0
- package/lib/oh-story/skills/story-review/SKILL.md +26 -17
- package/lib/oh-story/skills/story-review/references/anti-ai-writing.md +2 -1
- package/lib/oh-story/skills/story-review/references/author-memory.md +163 -0
- package/lib/oh-story/skills/story-review/references/banned-words.md +6 -4
- package/lib/oh-story/skills/story-review/references/{quality-checklist.md → review-quality.md} +22 -21
- package/lib/oh-story/skills/story-review/references/tracking-transaction.md +14 -6
- package/lib/oh-story/skills/story-review/scripts/author_memory_commit.py +871 -0
- package/lib/oh-story/skills/story-review/scripts/check-ai-patterns.js +64 -1
- package/lib/oh-story/skills/story-review/scripts/tracking_commit.py +98 -9
- package/lib/oh-story/skills/story-review/scripts/wordcount_core.py +246 -0
- package/lib/oh-story/skills/story-setup/SKILL.md +74 -33
- package/lib/oh-story/skills/story-setup/references/agent-references/agent-quality.md +72 -0
- package/lib/oh-story/skills/story-setup/references/agent-references/agent-reference-profiles.md +55 -0
- package/lib/oh-story/skills/story-setup/references/agent-references/anti-ai-writing.md +2 -1
- package/lib/oh-story/skills/story-setup/references/agent-references/banned-words.md +6 -4
- package/lib/oh-story/skills/story-setup/references/agent-references/format-and-structure.md +9 -10
- package/lib/oh-story/skills/story-setup/references/agent-references/genre-prose-cards.md +1 -1
- package/lib/oh-story/skills/story-setup/references/agent-references/genre-readers.md +1 -1
- package/lib/oh-story/skills/{story-short-analyze/references/hooks-chapter.md → story-setup/references/agent-references/long-chapter-hooks.md} +5 -5
- package/lib/oh-story/skills/story-setup/references/agent-references/long-emotional-methods.md +209 -0
- package/lib/oh-story/skills/{story-long-write/references/genre-catalog.md → story-setup/references/agent-references/long-genre-catalog.md} +11 -97
- package/lib/oh-story/skills/{story-long-write/references/genre-core-mechanics.md → story-setup/references/agent-references/long-genre-mechanics.md} +1 -1
- package/lib/oh-story/skills/story-setup/references/agent-references/long-quality.md +40 -0
- package/lib/oh-story/skills/story-setup/references/agent-references/{reversal-toolkit.md → long-reversal.md} +18 -32
- package/lib/oh-story/skills/{story-short-write/references/hooks-suspense.md → story-setup/references/agent-references/long-suspense.md} +6 -6
- package/lib/oh-story/skills/story-setup/references/agent-references/opening-design.md +1 -1
- package/lib/oh-story/skills/story-setup/references/agent-references/{emotional-methods.md → short-emotional-methods.md} +4 -4
- package/lib/oh-story/skills/{story-long-write/references/genre-writing-formulas.md → story-setup/references/agent-references/short-genre-formulas.md} +32 -44
- package/lib/oh-story/skills/story-setup/references/agent-references/short-quality.md +39 -0
- package/lib/oh-story/skills/{story-long-write/references/reversal-toolkit.md → story-setup/references/agent-references/short-reversal.md} +29 -23
- package/lib/oh-story/skills/story-setup/references/agent-references/{hooks-suspense.md → short-suspense.md} +31 -31
- package/lib/oh-story/skills/story-setup/references/agent-references/style-genre-modules.md +1 -1
- package/lib/oh-story/skills/story-setup/references/agent-references/writing-craft.md +55 -55
- package/lib/oh-story/skills/story-short-analyze/SKILL.md +28 -28
- package/lib/oh-story/skills/story-short-analyze/references/{character-basics.md → analysis-character-basics.md} +1 -1
- package/lib/oh-story/skills/story-short-analyze/references/{character-design-methods.md → analysis-character-design.md} +1 -1
- package/lib/oh-story/skills/story-short-analyze/references/{character-relations.md → analysis-character-relations.md} +1 -1
- package/lib/oh-story/skills/story-short-analyze/references/{hooks-paragraph.md → analysis-paragraph-hooks.md} +1 -1
- package/lib/oh-story/skills/story-short-analyze/references/{genre-readers.md → analysis-reader-profile.md} +2 -2
- package/lib/oh-story/skills/story-short-analyze/references/analysis-report-style.md +45 -0
- package/lib/oh-story/skills/story-short-analyze/references/analysis-short-genres.md +65 -0
- package/lib/oh-story/skills/story-short-analyze/references/analysis-short-hooks.md +77 -0
- package/lib/oh-story/skills/story-short-analyze/references/analysis-short-mechanics.md +82 -0
- package/lib/oh-story/skills/story-short-analyze/references/analysis-short-patterns.md +50 -0
- package/lib/oh-story/skills/story-short-analyze/references/analysis-short-suspense.md +98 -0
- package/lib/oh-story/skills/story-short-analyze/references/{genre-writing-techniques.md → analysis-writing-techniques.md} +21 -19
- package/lib/oh-story/skills/story-short-analyze/references/deconstruction-examples.md +1 -1
- package/lib/oh-story/skills/story-short-analyze/references/material-decomposition.md +21 -28
- package/lib/oh-story/skills/story-short-analyze/references/output-contract.md +1 -1
- package/lib/oh-story/skills/story-short-analyze/references/output-templates.md +17 -17
- package/lib/oh-story/skills/story-short-analyze/references/{quality-checklist.md → source-story-quality.md} +28 -49
- package/lib/oh-story/skills/story-short-analyze/references/zhihu-style.md +2 -2
- package/lib/oh-story/skills/story-short-scan/SKILL.md +1 -1
- package/lib/oh-story/skills/story-short-write/SKILL.md +78 -55
- package/lib/oh-story/skills/story-short-write/references/author-memory.md +163 -0
- package/lib/oh-story/skills/story-short-write/references/banned-words.md +6 -4
- package/lib/oh-story/skills/story-short-write/references/cross-book-recall.md +3 -3
- package/lib/oh-story/skills/story-short-write/references/emotional-methods.md +4 -4
- package/lib/oh-story/skills/story-short-write/references/genre-styles//344/270/226/346/203/205/346/211/223/350/204/270.md +3 -3
- package/lib/oh-story/skills/story-short-write/references/genre-styles//345/217/214/347/224/267/344/270/273.md +2 -2
- package/lib/oh-story/skills/story-short-write/references/genre-styles//345/244/215/344/273/207/346/211/223/350/204/270.md +3 -3
- package/lib/oh-story/skills/story-short-write/references/genre-styles//345/256/205/346/226/227/345/256/253/346/226/227.md +6 -6
- package/lib/oh-story/skills/story-short-write/references/genre-styles//346/200/273/350/243/201/350/261/252/351/227/250.md +3 -3
- package/lib/oh-story/skills/story-short-write/references/genre-styles//346/202/254/347/226/221.md +4 -4
- package/lib/oh-story/skills/story-short-write/references/genre-styles//346/260/221/344/277/227/346/200/252/350/260/210.md +7 -7
- package/lib/oh-story/skills/story-short-write/references/genre-styles//346/262/231/351/233/225/350/204/221/346/264/236.md +5 -5
- package/lib/oh-story/skills/story-short-write/references/genre-styles//347/224/234/345/256/240.md +4 -4
- package/lib/oh-story/skills/story-short-write/references/genre-styles//350/277/275/345/246/273/347/201/253/350/221/254/345/234/272.md +3 -3
- package/lib/oh-story/skills/story-short-write/references/genre-writing-formulas.md +32 -44
- package/lib/oh-story/skills/story-short-write/references/genre-writing-techniques.md +20 -18
- package/lib/oh-story/skills/story-short-write/references/output-contract.md +1 -1
- package/lib/oh-story/skills/story-short-write/references/short-craft.md +18 -18
- package/lib/oh-story/skills/story-short-write/references/short-deslop.md +1 -1
- package/lib/oh-story/skills/story-short-write/references/short-format.md +38 -8
- package/lib/oh-story/skills/story-short-write/references/{quality-checklist.md → short-prose-quality.md} +22 -21
- package/lib/oh-story/skills/story-short-write/references/short-reversal.md +355 -0
- package/lib/oh-story/skills/{story-short-analyze/references/hooks-suspense.md → story-short-write/references/short-suspense.md} +31 -31
- package/lib/oh-story/skills/story-short-write/references/submission-craft.md +2 -2
- package/lib/oh-story/skills/story-short-write/references/writing-workflow.md +31 -22
- package/lib/oh-story/skills/story-short-write/scripts/author_memory_commit.py +871 -0
- package/lib/oh-story/skills/story-short-write/scripts/check-ai-patterns.js +64 -1
- package/lib/oh-story/skills/story-short-write/scripts/check-delivery-contract.js +212 -0
- package/lib/oh-story/skills/story-short-write/scripts/check-phase2-contract.js +363 -0
- package/lib/types/client/drama-production-view.d.ts +34 -0
- package/lib/types/client/drama-production-view.d.ts.map +1 -0
- package/lib/types/client/drama-production.d.ts +92 -0
- package/lib/types/client/drama-production.d.ts.map +1 -0
- package/lib/types/client/file-activity.d.ts +4 -2
- package/lib/types/client/file-activity.d.ts.map +1 -1
- package/lib/types/client/index.d.ts +1 -1
- package/lib/types/client/index.d.ts.map +1 -1
- package/lib/types/client/production-intents.d.ts +9 -0
- package/lib/types/client/production-intents.d.ts.map +1 -0
- package/lib/types/client/production-prompts.d.ts +9 -0
- package/lib/types/client/production-prompts.d.ts.map +1 -0
- package/lib/types/client/production-runtime.d.ts +58 -0
- package/lib/types/client/production-runtime.d.ts.map +1 -0
- package/lib/types/client/video-studio.d.ts +41 -0
- package/lib/types/client/video-studio.d.ts.map +1 -0
- package/lib/types/client/workbench-ui.d.ts +5 -0
- package/lib/types/client/workbench-ui.d.ts.map +1 -0
- package/lib/types/game-verification.d.ts +16 -0
- package/lib/types/game-verification.d.ts.map +1 -0
- package/lib/types/index.d.ts +3 -1
- package/lib/types/index.d.ts.map +1 -1
- package/lib/types/production-intent.d.ts +21 -0
- package/lib/types/production-intent.d.ts.map +1 -0
- package/lib/types/production-tool.d.ts +5 -0
- package/lib/types/production-tool.d.ts.map +1 -0
- package/lib/types/role-tool.d.ts.map +1 -1
- package/lib/types/skill-provider.d.ts +7 -0
- package/lib/types/skill-provider.d.ts.map +1 -1
- package/lib/types/video-project.d.ts +42 -0
- package/lib/types/video-project.d.ts.map +1 -0
- package/lib/types/workspace-request-trust.d.ts +6 -0
- package/lib/types/workspace-request-trust.d.ts.map +1 -1
- package/lib/types/workspace-route.d.ts +20 -0
- package/lib/types/workspace-route.d.ts.map +1 -1
- package/lib/video-recap/CHANGELOG.md +282 -0
- package/lib/video-recap/LICENSE +21 -0
- package/lib/video-recap/README.en.md +257 -0
- package/lib/video-recap/README.md +255 -0
- package/lib/video-recap/manifest.json +684 -0
- package/lib/video-recap/skills/video-assemble/SKILL.md +97 -0
- package/lib/video-recap/skills/video-assemble/references/jianying/LICENSE.duo-video +21 -0
- package/lib/video-recap/skills/video-assemble/references/jianying/SOURCE.md +15 -0
- package/lib/video-recap/skills/video-assemble/references/jianying/empty_draft_meta_info.json +69 -0
- package/lib/video-recap/skills/video-assemble/references/jianying/empty_jy_combination_segment.json +84 -0
- package/lib/video-recap/skills/video-assemble/references/jianying/empty_jy_combination_video_material.json +98 -0
- package/lib/video-recap/skills/video-assemble/references/jianying/empty_jy_draft.json +204 -0
- package/lib/video-recap/skills/video-assemble/references/jianying/empty_jy_material_video.json +83 -0
- package/lib/video-recap/skills/video-assemble/references/jianying/empty_jy_meta_material_value.json +23 -0
- package/lib/video-recap/skills/video-assemble/references/jianying/empty_jy_project_info.json +133 -0
- package/lib/video-recap/skills/video-assemble/references/jianying/empty_jy_segment.json +70 -0
- package/lib/video-recap/skills/video-assemble/references/jianying/empty_jy_text_styles.json +30 -0
- package/lib/video-recap/skills/video-assemble/references/jianying/empty_yj_material_audio.json +41 -0
- package/lib/video-recap/skills/video-assemble/references/jianying/empty_yj_material_text.json +109 -0
- package/lib/video-recap/skills/video-assemble/scripts/artifacts.py +88 -0
- package/lib/video-recap/skills/video-assemble/scripts/assemble.py +345 -0
- package/lib/video-recap/skills/video-assemble/scripts/assemble_constants.py +34 -0
- package/lib/video-recap/skills/video-assemble/scripts/assembly_contract.py +305 -0
- package/lib/video-recap/skills/video-assemble/scripts/assembly_settings.py +94 -0
- package/lib/video-recap/skills/video-assemble/scripts/audio_automation.py +205 -0
- package/lib/video-recap/skills/video-assemble/scripts/audio_mix.py +555 -0
- package/lib/video-recap/skills/video-assemble/scripts/export_jianying.py +261 -0
- package/lib/video-recap/skills/video-assemble/scripts/jianying_builders.py +767 -0
- package/lib/video-recap/skills/video-assemble/scripts/jianying_model.py +111 -0
- package/lib/video-recap/skills/video-assemble/scripts/jianying_optional.py +24 -0
- package/lib/video-recap/skills/video-assemble/scripts/jianying_schema.py +109 -0
- package/lib/video-recap/skills/video-assemble/scripts/jianying_templates.py +37 -0
- package/lib/video-recap/skills/video-assemble/scripts/jianying_timeline_contract.py +191 -0
- package/lib/video-recap/skills/video-assemble/scripts/jianying_tracks.py +75 -0
- package/lib/video-recap/skills/video-assemble/scripts/jianying_writer.py +394 -0
- package/lib/video-recap/skills/video-assemble/scripts/lib.py +239 -0
- package/lib/video-recap/skills/video-assemble/scripts/media.py +243 -0
- package/lib/video-recap/skills/video-assemble/scripts/narration_audio.py +477 -0
- package/lib/video-recap/skills/video-assemble/scripts/render_preflight.py +46 -0
- package/lib/video-recap/skills/video-assemble/scripts/source_subtitles.py +486 -0
- package/lib/video-recap/skills/video-assemble/scripts/subtitle_core.py +376 -0
- package/lib/video-recap/skills/video-assemble/scripts/subtitle_render.py +88 -0
- package/lib/video-recap/skills/video-assemble/scripts/timeline.py +248 -0
- package/lib/video-recap/skills/video-assemble/scripts/timeline_emit.py +89 -0
- package/lib/video-recap/skills/video-assemble/scripts/visual_render.py +512 -0
- package/lib/video-recap/skills/video-cut/SKILL.md +90 -0
- package/lib/video-recap/skills/video-cut/scripts/cut.py +67 -0
- package/lib/video-recap/skills/video-cut/scripts/cut_cli.py +320 -0
- package/lib/video-recap/skills/video-cut/scripts/cut_contract.py +545 -0
- package/lib/video-recap/skills/video-cut/scripts/cut_render.py +348 -0
- package/lib/video-recap/skills/video-cut/scripts/lib.py +77 -0
- package/lib/video-recap/skills/video-cut/scripts/media_geometry.py +341 -0
- package/lib/video-recap/skills/video-cut/scripts/narration_mapping.py +249 -0
- package/lib/video-recap/skills/video-cut/scripts/sentence_boundaries.py +745 -0
- package/lib/video-recap/skills/video-recap/SKILL.md +216 -0
- package/lib/video-recap/skills/video-recap/references/config-playbook.md +61 -0
- package/lib/video-recap/skills/video-recap/references/creative-editing-playbook.md +225 -0
- package/lib/video-recap/skills/video-recap/references/data-schema.md +534 -0
- package/lib/video-recap/skills/video-recap/references/research-guide.md +74 -0
- package/lib/video-recap/skills/video-recap/references/shift-left-qc-schema.md +23 -0
- package/lib/video-recap/skills/video-recap/references/timeline-and-jianying.md +251 -0
- package/lib/video-recap/skills/video-recap/scripts/doctor.py +483 -0
- package/lib/video-recap/skills/video-recap/scripts/final_qc.py +737 -0
- package/lib/video-recap/skills/video-recap/scripts/lib.py +242 -0
- package/lib/video-recap/skills/video-recap/scripts/materials.py +457 -0
- package/lib/video-recap/skills/video-recap/scripts/mimo_qc.py +95 -0
- package/lib/video-recap/skills/video-recap/scripts/mimo_qc_client.py +18 -0
- package/lib/video-recap/skills/video-recap/scripts/mimo_qc_contract.py +9 -0
- package/lib/video-recap/skills/video-recap/scripts/mimo_qc_evidence.py +371 -0
- package/lib/video-recap/skills/video-recap/scripts/mimo_qc_observations.py +201 -0
- package/lib/video-recap/skills/video-recap/scripts/mimo_qc_payload.py +227 -0
- package/lib/video-recap/skills/video-recap/scripts/mimo_qc_report.py +362 -0
- package/lib/video-recap/skills/video-recap/scripts/mimo_qc_runner.py +129 -0
- package/lib/video-recap/skills/video-recap/scripts/qc_contract.py +338 -0
- package/lib/video-recap/skills/video-recap/scripts/recap.py +9 -0
- package/lib/video-recap/skills/video-recap/scripts/recap_cli.py +140 -0
- package/lib/video-recap/skills/video-recap/scripts/recap_inspect.py +550 -0
- package/lib/video-recap/skills/video-recap/scripts/recap_review.py +77 -0
- package/lib/video-recap/skills/video-recap/scripts/recap_runner.py +654 -0
- package/lib/video-recap/skills/video-recap/scripts/recap_runtime.py +335 -0
- package/lib/video-recap/skills/video-recap/scripts/recap_stage_qc.py +217 -0
- package/lib/video-recap/skills/video-recap/scripts/recap_timeline.py +795 -0
- package/lib/video-recap/skills/video-script/SKILL.md +248 -0
- package/lib/video-recap/skills/video-script/references/creative-editing-playbook.md +225 -0
- package/lib/video-recap/skills/video-script/references/research-guide.md +75 -0
- package/lib/video-recap/skills/video-script/scripts/agent_brief.py +399 -0
- package/lib/video-recap/skills/video-script/scripts/agent_text.py +410 -0
- package/lib/video-recap/skills/video-script/scripts/brief_context.py +403 -0
- package/lib/video-recap/skills/video-script/scripts/brief_inputs.py +332 -0
- package/lib/video-recap/skills/video-script/scripts/brief_timeline.py +442 -0
- package/lib/video-recap/skills/video-script/scripts/deslop_qc.py +237 -0
- package/lib/video-recap/skills/video-script/scripts/evidence_bundle.py +492 -0
- package/lib/video-recap/skills/video-script/scripts/lib.py +327 -0
- package/lib/video-recap/skills/video-script/scripts/narration.py +12 -0
- package/lib/video-recap/skills/video-script/scripts/narration_lint.py +678 -0
- package/lib/video-recap/skills/video-script/scripts/review.py +42 -0
- package/lib/video-recap/skills/video-script/scripts/review_grounding.py +262 -0
- package/lib/video-recap/skills/video-script/scripts/review_response.py +761 -0
- package/lib/video-recap/skills/video-script/scripts/review_runner.py +200 -0
- package/lib/video-recap/skills/video-script/scripts/speech_ownership.py +204 -0
- package/lib/video-recap/skills/video-script/scripts/timeline_fusion.py +199 -0
- package/lib/video-recap/skills/video-script/scripts/validate.py +164 -0
- package/lib/video-recap/skills/video-understanding/SKILL.md +75 -0
- package/lib/video-recap/skills/video-understanding/references/data-schema.md +299 -0
- package/lib/video-recap/skills/video-understanding/references/prompt-templates.md +37 -0
- package/lib/video-recap/skills/video-understanding/references/research-guide.md +74 -0
- package/lib/video-recap/skills/video-understanding/scripts/agent_brief.py +399 -0
- package/lib/video-recap/skills/video-understanding/scripts/agent_text.py +410 -0
- package/lib/video-recap/skills/video-understanding/scripts/asr.py +260 -0
- package/lib/video-recap/skills/video-understanding/scripts/brief.py +12 -0
- package/lib/video-recap/skills/video-understanding/scripts/brief_context.py +403 -0
- package/lib/video-recap/skills/video-understanding/scripts/brief_inputs.py +332 -0
- package/lib/video-recap/skills/video-understanding/scripts/brief_timeline.py +442 -0
- package/lib/video-recap/skills/video-understanding/scripts/consolidate.py +647 -0
- package/lib/video-recap/skills/video-understanding/scripts/deslop_qc.py +237 -0
- package/lib/video-recap/skills/video-understanding/scripts/detect.py +513 -0
- package/lib/video-recap/skills/video-understanding/scripts/extract.py +62 -0
- package/lib/video-recap/skills/video-understanding/scripts/lib.py +470 -0
- package/lib/video-recap/skills/video-understanding/scripts/narration_lint.py +678 -0
- package/lib/video-recap/skills/video-understanding/scripts/speech_ownership.py +204 -0
- package/lib/video-recap/skills/video-understanding/scripts/storyboard.py +507 -0
- package/lib/video-recap/skills/video-understanding/scripts/timeline_fusion.py +199 -0
- package/lib/video-recap/skills/video-understanding/scripts/understand.py +9 -0
- package/lib/video-recap/skills/video-understanding/scripts/understanding_brief.py +216 -0
- package/lib/video-recap/skills/video-understanding/scripts/understanding_cache.py +327 -0
- package/lib/video-recap/skills/video-understanding/scripts/understanding_runner.py +367 -0
- package/lib/video-recap/skills/video-understanding/scripts/understanding_storyboard.py +162 -0
- package/lib/video-recap/skills/video-understanding/scripts/vlm.py +705 -0
- package/lib/video-recap/skills/video-voiceover/SKILL.md +81 -0
- package/lib/video-recap/skills/video-voiceover/scripts/dub.py +637 -0
- package/lib/video-recap/skills/video-voiceover/scripts/fish_audio.py +109 -0
- package/lib/video-recap/skills/video-voiceover/scripts/lib.py +421 -0
- package/lib/video-recap/skills/video-voiceover/scripts/tts_audio.py +113 -0
- package/lib/video-recap/skills/video-voiceover/scripts/voiceover.py +782 -0
- package/package.json +55 -40
- package/lib/oh-story/skills/story-deslop/scripts/check-outline-copy.js +0 -241
- package/lib/oh-story/skills/story-long-write/references/format-and-structure.md +0 -169
- package/lib/oh-story/skills/story-setup/references/agent-references/genre-writing-formulas.md +0 -444
- package/lib/oh-story/skills/story-setup/references/agent-references/quality-checklist.md +0 -247
- package/lib/oh-story/skills/story-short-analyze/references/anti-ai-writing.md +0 -582
- package/lib/oh-story/skills/story-short-analyze/references/banned-words.md +0 -147
- package/lib/oh-story/skills/story-short-analyze/references/genre-catalog.md +0 -490
- package/lib/oh-story/skills/story-short-analyze/references/genre-core-mechanics.md +0 -425
- package/lib/oh-story/skills/story-short-analyze/references/genre-writing-formulas.md +0 -453
- /package/lib/oh-story/skills/{story-long-write/references/hooks-chapter.md → story-setup/references/agent-references/short-chapter-hooks.md} +0 -0
- /package/lib/oh-story/skills/{story-long-write/references/hooks-paragraph.md → story-setup/references/agent-references/short-paragraph-hooks.md} +0 -0
|
@@ -20,19 +20,36 @@ Optional environment:
|
|
|
20
20
|
- `SEEDANCE_ALLOWED_RATIOS`: comma-separated subset explicitly supported by
|
|
21
21
|
the configured model, such as `9:16,16:9`.
|
|
22
22
|
- `SEEDANCE_MIN_DURATION` and `SEEDANCE_MAX_DURATION`: the configured model's
|
|
23
|
-
explicit inclusive duration range. Set both or neither.
|
|
23
|
+
explicit inclusive duration range. Set both or neither. Official integer profiles are `4–15`
|
|
24
|
+
for Seedance 2.0 and `4–30` for Seedance 2.5.
|
|
24
25
|
|
|
25
26
|
The job must have modality `video` and exactly one `.mp4` output. Optional
|
|
26
27
|
`duration` and `ratio` parameters are accepted only when the external runtime
|
|
27
|
-
profile above explicitly permits their values
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
28
|
+
profile above explicitly permits their values, then sent as the API's top-level fields. Optional
|
|
29
|
+
`generate_audio` is a boolean. The broad compiler envelope remains configurable rather than proving
|
|
30
|
+
that every Seedance release supports every value.
|
|
31
|
+
|
|
32
|
+
`compile_seedance_payload` accepts explicit `reference_image`, `reference_video`, and
|
|
33
|
+
`reference_audio` roles with matching HTTPS, `asset://` or base64 data URI values. It emits the matching multimodal
|
|
34
|
+
content type and uses `@图片N`、`@视频N`、`@音频N` in its appended reference contract. The bundled
|
|
35
|
+
runtime sends a project-relative reference inline as a `data:<mime>;base64,<...>` URI, which the
|
|
36
|
+
official contract lists alongside a public URL and `asset://`, so binding an image in the creator
|
|
37
|
+
documents is enough to run the job. Each file's bytes must match the media type its extension claims.
|
|
38
|
+
Volcengine publishes no per-file size numbers, so this adapter applies the same conservative guard as
|
|
39
|
+
the MiniMax path — 30MB per image, 50MB per video, 15MB per audio clip, 64MB per request after base64
|
|
40
|
+
expansion — and fails closed above them rather than sending a body the provider may reject. Each
|
|
41
|
+
reference takes its provider role from the confirmed job's `reference_bindings[].role`; a job with
|
|
42
|
+
references but no bindings fails closed rather than guessing.
|
|
43
|
+
|
|
44
|
+
Prompt wording for Seedance 2.0 is version-specific: normal reference uses “参考 @视频1”, while
|
|
45
|
+
continuation says “向后延长 @视频1” and binds the actual tail as `@图片1`. See the video-prompt
|
|
46
|
+
skill's `references/seedance-2.0.md`.
|
|
47
|
+
|
|
48
|
+
Seedance 2.5 has a separate `references/seedance-2.5.md` dialect and may carry
|
|
49
|
+
`omni_reference_task_type: reference|edit|extend|auto`. The compiler enforces the documented hard
|
|
50
|
+
parameter combinations for `edit` (`adaptive`, `-1`, reference video) and `extend` (`adaptive`,
|
|
51
|
+
reference video). It does not infer the task type from prompt keywords, because the API checks that
|
|
52
|
+
the explicit type and semantic intent agree.
|
|
36
53
|
|
|
37
54
|
The adapter creates an asynchronous task, polls `GET /contents/generations/tasks/{id}` until a terminal state, and
|
|
38
55
|
downloads `content.video_url` into a private temporary directory. Any unknown status fails closed.
|
|
@@ -63,13 +63,23 @@ ALLOWED_JOB_KEYS = {
|
|
|
63
63
|
"adapter",
|
|
64
64
|
"prompt",
|
|
65
65
|
"source",
|
|
66
|
+
"source_entry",
|
|
66
67
|
"references",
|
|
68
|
+
"reference_bindings",
|
|
67
69
|
"outputs",
|
|
68
70
|
"parameters",
|
|
69
71
|
"overwrite",
|
|
70
72
|
}
|
|
71
73
|
STORED_EXECUTION_KEYS = ALLOWED_JOB_KEYS | {"inputs"}
|
|
72
74
|
STORED_JOB_KEYS = STORED_EXECUTION_KEYS | {"fingerprint", "prepared_at"}
|
|
75
|
+
LEGACY_STORED_EXECUTION_KEYS = STORED_EXECUTION_KEYS - {
|
|
76
|
+
"source_entry",
|
|
77
|
+
"reference_bindings",
|
|
78
|
+
}
|
|
79
|
+
LEGACY_STORED_JOB_KEYS = LEGACY_STORED_EXECUTION_KEYS | {
|
|
80
|
+
"fingerprint",
|
|
81
|
+
"prepared_at",
|
|
82
|
+
}
|
|
73
83
|
SECRET_KEYS = {
|
|
74
84
|
"authorization",
|
|
75
85
|
"credential",
|
|
@@ -102,6 +112,35 @@ MEDIA_TYPES = {
|
|
|
102
112
|
".flac": "audio/flac",
|
|
103
113
|
".opus": "audio/ogg",
|
|
104
114
|
}
|
|
115
|
+
CREATOR_SOURCE_NAMES = {
|
|
116
|
+
"图片提示词.md": "image",
|
|
117
|
+
"视频提示词.md": "video",
|
|
118
|
+
# A shot's frozen keyframe is a producible image and lives nowhere else, so
|
|
119
|
+
# without this the start frame a video job wants to bind has no stage that
|
|
120
|
+
# can render it.
|
|
121
|
+
"分镜.md": "image",
|
|
122
|
+
}
|
|
123
|
+
# Which H2 IDs a creator source may select, and where that entry keeps its
|
|
124
|
+
# copyable body.
|
|
125
|
+
CREATOR_SOURCE_ENTRIES = {
|
|
126
|
+
"图片提示词.md": ("IMG-", r"可复制(?:通用)?提示词", "参考"),
|
|
127
|
+
"视频提示词.md": ("MOTION-", r"可复制(?:通用)?提示词", "输入参考图"),
|
|
128
|
+
"分镜.md": ("SHOT-", r"冻结关键帧提示词", "输入参考图"),
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
REF_SLOT_RE = re.compile(r"REF-[A-Z0-9][A-Z0-9-]{0,79}")
|
|
132
|
+
SOURCE_ENTRY_RE = re.compile(r"[A-Z][A-Z0-9-]{1,99}")
|
|
133
|
+
REFERENCE_SUFFIX_RE = r"(?:png|jpe?g|webp)"
|
|
134
|
+
# 用途 is the creator-facing question "what does this picture decide here"; the
|
|
135
|
+
# job's own `role` is its production translation. The segment is optional so a
|
|
136
|
+
# declaration written before that field existed still prepares, and so the
|
|
137
|
+
# creator-side diagnostic stays with creator_markdown_check.py.
|
|
138
|
+
REFERENCE_LINE_RE = re.compile(
|
|
139
|
+
rf"(REF-[A-Z0-9][A-Z0-9-]{{0,79}})(顺序:([1-9]\d*))· "
|
|
140
|
+
rf"([^;\n]+?\.{REFERENCE_SUFFIX_RE})《([^》\n]+)》"
|
|
141
|
+
r"((?:用途:[^;)\n]+;)?控制:([^;)\n]+);不得控制:([^)\n]+))",
|
|
142
|
+
re.IGNORECASE,
|
|
143
|
+
)
|
|
105
144
|
|
|
106
145
|
|
|
107
146
|
class ConfirmationRequiredError(RuntimeError):
|
|
@@ -627,6 +666,225 @@ def _string_list(value: object, *, label: str, limit: int = 32) -> list[str]:
|
|
|
627
666
|
return list(value)
|
|
628
667
|
|
|
629
668
|
|
|
669
|
+
def _scope_list(value: object, *, label: str) -> list[str]:
|
|
670
|
+
items = _string_list(value, label=label, limit=32)
|
|
671
|
+
if not items or any(not item.strip() or len(item) > 200 for item in items):
|
|
672
|
+
raise ValueError(f"{label} must contain non-empty bounded text")
|
|
673
|
+
normalized = [item.strip() for item in items]
|
|
674
|
+
folded = [item.casefold() for item in normalized]
|
|
675
|
+
if len(folded) != len(set(folded)):
|
|
676
|
+
raise ValueError(f"{label} must not contain duplicates")
|
|
677
|
+
return normalized
|
|
678
|
+
|
|
679
|
+
|
|
680
|
+
def _canonical_creator_source_modality(source: str | None) -> str | None:
|
|
681
|
+
if source is None:
|
|
682
|
+
return None
|
|
683
|
+
path = PurePosixPath(source)
|
|
684
|
+
if (
|
|
685
|
+
len(path.parts) != 3
|
|
686
|
+
or path.parts[0] not in {"剧集", "episodes"}
|
|
687
|
+
or not path.parts[1]
|
|
688
|
+
):
|
|
689
|
+
return None
|
|
690
|
+
return CREATOR_SOURCE_NAMES.get(path.name)
|
|
691
|
+
|
|
692
|
+
|
|
693
|
+
def _normalize_reference_bindings(value: object) -> list[dict[str, Any]]:
|
|
694
|
+
if value is None:
|
|
695
|
+
return []
|
|
696
|
+
if not isinstance(value, list) or len(value) > 16:
|
|
697
|
+
raise ValueError("reference_bindings must be a list of at most sixteen entries")
|
|
698
|
+
normalized: list[dict[str, Any]] = []
|
|
699
|
+
for index, binding in enumerate(value, 1):
|
|
700
|
+
label = f"reference_bindings[{index}]"
|
|
701
|
+
if not isinstance(binding, Mapping) or set(binding) != {
|
|
702
|
+
"slot_id",
|
|
703
|
+
"order",
|
|
704
|
+
"path",
|
|
705
|
+
"label",
|
|
706
|
+
"role",
|
|
707
|
+
"may_control",
|
|
708
|
+
"must_not_control",
|
|
709
|
+
}:
|
|
710
|
+
raise ValueError(f"{label} fields are invalid")
|
|
711
|
+
slot_id = binding.get("slot_id")
|
|
712
|
+
order = binding.get("order")
|
|
713
|
+
raw_label = binding.get("label")
|
|
714
|
+
role = binding.get("role")
|
|
715
|
+
if not isinstance(slot_id, str) or REF_SLOT_RE.fullmatch(slot_id) is None:
|
|
716
|
+
raise ValueError(f"{label} slot_id is invalid")
|
|
717
|
+
if not isinstance(order, int) or isinstance(order, bool) or order < 1:
|
|
718
|
+
raise ValueError(f"{label} order is invalid")
|
|
719
|
+
if (
|
|
720
|
+
not isinstance(raw_label, str)
|
|
721
|
+
or not raw_label.strip()
|
|
722
|
+
or len(raw_label) > 200
|
|
723
|
+
or re.search(r"[\u3400-\u9fff]", raw_label) is None
|
|
724
|
+
):
|
|
725
|
+
raise ValueError(f"{label} label must contain Chinese text")
|
|
726
|
+
if not isinstance(role, str) or not role.strip() or len(role) > 80:
|
|
727
|
+
raise ValueError(f"{label} role is invalid")
|
|
728
|
+
may_control = _scope_list(
|
|
729
|
+
binding.get("may_control"), label=f"{label}.may_control"
|
|
730
|
+
)
|
|
731
|
+
must_not_control = _scope_list(
|
|
732
|
+
binding.get("must_not_control"), label=f"{label}.must_not_control"
|
|
733
|
+
)
|
|
734
|
+
if {item.casefold() for item in may_control} & {
|
|
735
|
+
item.casefold() for item in must_not_control
|
|
736
|
+
}:
|
|
737
|
+
raise ValueError(f"{label} control scopes must not overlap")
|
|
738
|
+
normalized.append(
|
|
739
|
+
{
|
|
740
|
+
"slot_id": slot_id,
|
|
741
|
+
"order": order,
|
|
742
|
+
"path": _relative_path(binding.get("path")),
|
|
743
|
+
"label": raw_label.strip(),
|
|
744
|
+
"role": role.strip(),
|
|
745
|
+
"may_control": may_control,
|
|
746
|
+
"must_not_control": must_not_control,
|
|
747
|
+
}
|
|
748
|
+
)
|
|
749
|
+
normalized.sort(key=lambda item: int(item["order"]))
|
|
750
|
+
slots = [str(item["slot_id"]) for item in normalized]
|
|
751
|
+
orders = [int(item["order"]) for item in normalized]
|
|
752
|
+
paths = [str(item["path"]) for item in normalized]
|
|
753
|
+
if len(slots) != len(set(slots)):
|
|
754
|
+
raise ValueError("reference binding slot_ids must be unique")
|
|
755
|
+
if orders != list(range(1, len(orders) + 1)):
|
|
756
|
+
raise ValueError("reference binding order must be unique and contiguous from 1")
|
|
757
|
+
if len(paths) != len(set(paths)):
|
|
758
|
+
raise ValueError("reference binding paths must be unique")
|
|
759
|
+
return normalized
|
|
760
|
+
|
|
761
|
+
|
|
762
|
+
def _markdown_section(document: str, source_entry: str) -> str:
|
|
763
|
+
heading = re.compile(
|
|
764
|
+
rf"^##\s+`?{re.escape(source_entry)}`?(?:\s+·.*)?\s*$", re.MULTILINE
|
|
765
|
+
)
|
|
766
|
+
matches = list(heading.finditer(document))
|
|
767
|
+
if not matches:
|
|
768
|
+
raise ValueError(f"source entry is missing from Markdown: {source_entry}")
|
|
769
|
+
if len(matches) != 1:
|
|
770
|
+
raise ValueError(f"source entry is duplicated in Markdown: {source_entry}")
|
|
771
|
+
match = matches[0]
|
|
772
|
+
next_heading = re.search(r"^##\s+", document[match.end() :], re.MULTILINE)
|
|
773
|
+
end = match.end() + next_heading.start() if next_heading is not None else len(document)
|
|
774
|
+
return document[match.start() : end]
|
|
775
|
+
|
|
776
|
+
|
|
777
|
+
def _copyable_prompt(
|
|
778
|
+
section: str, heading: str = r"可复制(?:通用)?提示词"
|
|
779
|
+
) -> str:
|
|
780
|
+
markers = list(
|
|
781
|
+
re.finditer(rf"^###\s+{heading}\s*$", section, re.MULTILINE)
|
|
782
|
+
)
|
|
783
|
+
if not markers:
|
|
784
|
+
raise ValueError("source entry has no copyable prompt")
|
|
785
|
+
if len(markers) != 1:
|
|
786
|
+
raise ValueError("source entry has duplicate copyable prompts")
|
|
787
|
+
marker = markers[0]
|
|
788
|
+
body = section[marker.end() :]
|
|
789
|
+
following = re.search(r"^###\s+|^##\s+", body, re.MULTILINE)
|
|
790
|
+
if following is not None:
|
|
791
|
+
body = body[: following.start()]
|
|
792
|
+
body_lines = [line for line in body.splitlines() if line.strip()]
|
|
793
|
+
if any(not line.startswith(">") for line in body_lines):
|
|
794
|
+
raise ValueError("source entry copyable prompt contains unquoted content")
|
|
795
|
+
lines = [line[1:].lstrip() for line in body_lines]
|
|
796
|
+
if not lines or not "\n".join(lines).strip():
|
|
797
|
+
raise ValueError("source entry copyable prompt is empty")
|
|
798
|
+
return "\n".join(lines).strip()
|
|
799
|
+
|
|
800
|
+
|
|
801
|
+
def _scope_items(value: str) -> list[str]:
|
|
802
|
+
return [item.strip() for item in re.split(r"[、,,]", value) if item.strip()]
|
|
803
|
+
|
|
804
|
+
|
|
805
|
+
def _contains_ref_token(value: str) -> bool:
|
|
806
|
+
return "ref-" in value.casefold()
|
|
807
|
+
|
|
808
|
+
|
|
809
|
+
def _markdown_reference_bindings(
|
|
810
|
+
section: str, *, field_name: str
|
|
811
|
+
) -> list[dict[str, Any]]:
|
|
812
|
+
lines = re.findall(
|
|
813
|
+
rf"^- {re.escape(field_name)}:(.+)$", section, re.MULTILINE
|
|
814
|
+
)
|
|
815
|
+
if not lines:
|
|
816
|
+
raise ValueError(f"source entry has no {field_name} declaration")
|
|
817
|
+
if len(lines) != 1:
|
|
818
|
+
raise ValueError(f"source entry has duplicate {field_name} declarations")
|
|
819
|
+
value = lines[0].strip()
|
|
820
|
+
if (
|
|
821
|
+
field_name == "输入参考图"
|
|
822
|
+
and not _contains_ref_token(value)
|
|
823
|
+
and re.fullmatch(r"无(?:([^)\n]+))?。?", value)
|
|
824
|
+
):
|
|
825
|
+
return []
|
|
826
|
+
if (
|
|
827
|
+
field_name == "参考"
|
|
828
|
+
and not _contains_ref_token(value)
|
|
829
|
+
and re.fullmatch(r"无(?:外部参考)?(?:;[^\n]*)?。?", value)
|
|
830
|
+
):
|
|
831
|
+
return []
|
|
832
|
+
matches = list(REFERENCE_LINE_RE.finditer(value))
|
|
833
|
+
if not matches:
|
|
834
|
+
raise ValueError("source entry input-reference declaration is invalid")
|
|
835
|
+
cursor = 0
|
|
836
|
+
for index, match in enumerate(matches):
|
|
837
|
+
separator = value[cursor : match.start()]
|
|
838
|
+
if separator != ("" if index == 0 else ";"):
|
|
839
|
+
raise ValueError("source entry input-reference declaration is invalid")
|
|
840
|
+
cursor = match.end()
|
|
841
|
+
if value[cursor:] not in {"", "。"}:
|
|
842
|
+
raise ValueError("source entry input-reference declaration is invalid")
|
|
843
|
+
return [
|
|
844
|
+
{
|
|
845
|
+
"slot_id": match.group(1),
|
|
846
|
+
"order": int(match.group(2)),
|
|
847
|
+
"path": _relative_path(match.group(3)),
|
|
848
|
+
"label": match.group(4).strip(),
|
|
849
|
+
"may_control": _scope_items(match.group(5)),
|
|
850
|
+
"must_not_control": _scope_items(match.group(6)),
|
|
851
|
+
}
|
|
852
|
+
for match in matches
|
|
853
|
+
]
|
|
854
|
+
|
|
855
|
+
|
|
856
|
+
def _verify_markdown_source(
|
|
857
|
+
root: Path,
|
|
858
|
+
*,
|
|
859
|
+
source: str,
|
|
860
|
+
source_entry: str,
|
|
861
|
+
prompt: str,
|
|
862
|
+
bindings: list[dict[str, Any]],
|
|
863
|
+
) -> None:
|
|
864
|
+
source_path = _project_file(root, source)
|
|
865
|
+
if source_path.suffix.casefold() != ".md":
|
|
866
|
+
raise ValueError("source_entry requires a Markdown source")
|
|
867
|
+
document = source_path.read_text(encoding="utf-8")
|
|
868
|
+
section = _markdown_section(document, source_entry)
|
|
869
|
+
_, heading, field_name = CREATOR_SOURCE_ENTRIES[source_path.name]
|
|
870
|
+
if _copyable_prompt(section, heading) != prompt.strip():
|
|
871
|
+
raise ValueError("job prompt does not match the selected source entry")
|
|
872
|
+
declared = _markdown_reference_bindings(section, field_name=field_name)
|
|
873
|
+
comparable = [
|
|
874
|
+
{key: binding[key] for key in (
|
|
875
|
+
"slot_id",
|
|
876
|
+
"order",
|
|
877
|
+
"path",
|
|
878
|
+
"label",
|
|
879
|
+
"may_control",
|
|
880
|
+
"must_not_control",
|
|
881
|
+
)}
|
|
882
|
+
for binding in bindings
|
|
883
|
+
]
|
|
884
|
+
if declared != comparable:
|
|
885
|
+
raise ValueError("job reference bindings do not match the selected source entry")
|
|
886
|
+
|
|
887
|
+
|
|
630
888
|
def _normalize_job(root: Path, raw: object) -> dict[str, Any]:
|
|
631
889
|
if not isinstance(raw, Mapping) or set(raw) - ALLOWED_JOB_KEYS:
|
|
632
890
|
raise ValueError("job contains unsupported fields")
|
|
@@ -646,10 +904,59 @@ def _normalize_job(root: Path, raw: object) -> dict[str, Any]:
|
|
|
646
904
|
raise ValueError("prompt must be non-empty and at most 100000 characters")
|
|
647
905
|
source_raw = raw.get("source")
|
|
648
906
|
source = _relative_path(source_raw) if source_raw is not None else None
|
|
649
|
-
|
|
907
|
+
source_entry = raw.get("source_entry")
|
|
908
|
+
if source_entry is not None and (
|
|
909
|
+
not isinstance(source_entry, str)
|
|
910
|
+
or SOURCE_ENTRY_RE.fullmatch(source_entry) is None
|
|
911
|
+
):
|
|
912
|
+
raise ValueError("source_entry must be a visible uppercase Markdown entry ID")
|
|
913
|
+
if source_entry is not None and source is None:
|
|
914
|
+
raise ValueError("source_entry requires source")
|
|
915
|
+
creator_source_modality = _canonical_creator_source_modality(source)
|
|
916
|
+
if creator_source_modality == modality and source_entry is None:
|
|
917
|
+
raise ValueError("creator Markdown source requires source_entry")
|
|
918
|
+
if creator_source_modality is not None and modality != creator_source_modality and not (
|
|
919
|
+
creator_source_modality == "video"
|
|
920
|
+
and modality == "music"
|
|
921
|
+
and source_entry is None
|
|
922
|
+
):
|
|
923
|
+
raise ValueError("creator Markdown source does not match the job modality")
|
|
924
|
+
expected_entry_prefix = (
|
|
925
|
+
CREATOR_SOURCE_ENTRIES[PurePosixPath(source).name][0]
|
|
926
|
+
if source is not None
|
|
927
|
+
and PurePosixPath(source).name in CREATOR_SOURCE_ENTRIES
|
|
928
|
+
and creator_source_modality == modality
|
|
929
|
+
else None
|
|
930
|
+
)
|
|
931
|
+
if source_entry is not None and creator_source_modality != modality:
|
|
932
|
+
raise ValueError("source_entry requires the canonical creator Markdown path")
|
|
933
|
+
if source_entry is not None and (
|
|
934
|
+
expected_entry_prefix is None
|
|
935
|
+
or not source_entry.startswith(expected_entry_prefix)
|
|
936
|
+
):
|
|
937
|
+
raise ValueError("source_entry does not match the job modality")
|
|
938
|
+
references_supplied = "references" in raw
|
|
939
|
+
supplied_references = [
|
|
650
940
|
_relative_path(path)
|
|
651
941
|
for path in _string_list(raw.get("references", []), label="references", limit=16)
|
|
652
942
|
]
|
|
943
|
+
reference_bindings = _normalize_reference_bindings(raw.get("reference_bindings"))
|
|
944
|
+
binding_references = [str(binding["path"]) for binding in reference_bindings]
|
|
945
|
+
if (
|
|
946
|
+
references_supplied
|
|
947
|
+
and (reference_bindings or source_entry is not None)
|
|
948
|
+
and supplied_references != binding_references
|
|
949
|
+
):
|
|
950
|
+
raise ValueError("references must match reference_bindings order")
|
|
951
|
+
references = binding_references if reference_bindings else supplied_references
|
|
952
|
+
if source_entry is not None:
|
|
953
|
+
_verify_markdown_source(
|
|
954
|
+
root,
|
|
955
|
+
source=str(source),
|
|
956
|
+
source_entry=source_entry,
|
|
957
|
+
prompt=prompt,
|
|
958
|
+
bindings=reference_bindings,
|
|
959
|
+
)
|
|
653
960
|
outputs = [
|
|
654
961
|
_relative_path(path, output=True)
|
|
655
962
|
for path in _string_list(raw.get("outputs"), label="outputs", limit=16)
|
|
@@ -678,7 +985,9 @@ def _normalize_job(root: Path, raw: object) -> dict[str, Any]:
|
|
|
678
985
|
"adapter": adapter,
|
|
679
986
|
"prompt": prompt,
|
|
680
987
|
"source": source,
|
|
988
|
+
"source_entry": source_entry,
|
|
681
989
|
"references": references,
|
|
990
|
+
"reference_bindings": reference_bindings,
|
|
682
991
|
"outputs": outputs,
|
|
683
992
|
"parameters": dict(parameters),
|
|
684
993
|
"overwrite": raw.get("overwrite", False),
|
|
@@ -713,8 +1022,17 @@ def _validate_stored_job(
|
|
|
713
1022
|
root: Path, document: object, *, expected_job_id: str | None = None
|
|
714
1023
|
) -> dict[str, Any]:
|
|
715
1024
|
root = root.resolve()
|
|
716
|
-
if not isinstance(document, dict)
|
|
1025
|
+
if not isinstance(document, dict):
|
|
1026
|
+
raise ValueError("stored job fields are invalid")
|
|
1027
|
+
stored_keys = set(document)
|
|
1028
|
+
legacy = stored_keys == LEGACY_STORED_JOB_KEYS
|
|
1029
|
+
if not legacy and stored_keys != STORED_JOB_KEYS:
|
|
717
1030
|
raise ValueError("stored job fields are invalid")
|
|
1031
|
+
original = document
|
|
1032
|
+
document = dict(document)
|
|
1033
|
+
if legacy:
|
|
1034
|
+
document["source_entry"] = None
|
|
1035
|
+
document["reference_bindings"] = []
|
|
718
1036
|
job_id = document.get("job_id")
|
|
719
1037
|
if (
|
|
720
1038
|
not isinstance(job_id, str)
|
|
@@ -736,11 +1054,47 @@ def _validate_stored_job(
|
|
|
736
1054
|
source = document.get("source")
|
|
737
1055
|
if source is not None and _relative_path(source) != source:
|
|
738
1056
|
raise ValueError("stored job source is invalid")
|
|
1057
|
+
source_entry = document.get("source_entry")
|
|
1058
|
+
if source_entry is not None and (
|
|
1059
|
+
not isinstance(source_entry, str)
|
|
1060
|
+
or SOURCE_ENTRY_RE.fullmatch(source_entry) is None
|
|
1061
|
+
or source is None
|
|
1062
|
+
):
|
|
1063
|
+
raise ValueError("stored job source entry is invalid")
|
|
1064
|
+
expected_entry_prefix = {"image": "IMG-", "video": "MOTION-"}.get(
|
|
1065
|
+
str(modality)
|
|
1066
|
+
)
|
|
1067
|
+
if source_entry is not None and (
|
|
1068
|
+
expected_entry_prefix is None
|
|
1069
|
+
or not source_entry.startswith(expected_entry_prefix)
|
|
1070
|
+
):
|
|
1071
|
+
raise ValueError("stored job source entry has the wrong modality")
|
|
1072
|
+
creator_source_modality = _canonical_creator_source_modality(
|
|
1073
|
+
str(source) if source is not None else None
|
|
1074
|
+
)
|
|
1075
|
+
if not legacy and creator_source_modality == modality and source_entry is None:
|
|
1076
|
+
raise ValueError("stored creator Markdown job has no source entry")
|
|
1077
|
+
if creator_source_modality is not None and modality != creator_source_modality and not (
|
|
1078
|
+
creator_source_modality == "video"
|
|
1079
|
+
and modality == "music"
|
|
1080
|
+
and source_entry is None
|
|
1081
|
+
):
|
|
1082
|
+
raise ValueError("stored creator Markdown source has the wrong modality")
|
|
1083
|
+
if source_entry is not None and creator_source_modality != modality:
|
|
1084
|
+
raise ValueError("stored job creator source path is invalid")
|
|
739
1085
|
references = _string_list(
|
|
740
1086
|
document.get("references"), label="stored references", limit=16
|
|
741
1087
|
)
|
|
742
1088
|
if any(_relative_path(reference) != reference for reference in references):
|
|
743
1089
|
raise ValueError("stored job references are invalid")
|
|
1090
|
+
reference_bindings = _normalize_reference_bindings(
|
|
1091
|
+
document.get("reference_bindings")
|
|
1092
|
+
)
|
|
1093
|
+
binding_references = [binding["path"] for binding in reference_bindings]
|
|
1094
|
+
if (
|
|
1095
|
+
source_entry is not None or reference_bindings
|
|
1096
|
+
) and binding_references != references:
|
|
1097
|
+
raise ValueError("stored job references do not match reference bindings")
|
|
744
1098
|
outputs = _string_list(document.get("outputs"), label="stored outputs", limit=16)
|
|
745
1099
|
if not outputs or len(outputs) != len(set(outputs)):
|
|
746
1100
|
raise ValueError("stored job outputs are invalid")
|
|
@@ -771,7 +1125,10 @@ def _validate_stored_job(
|
|
|
771
1125
|
):
|
|
772
1126
|
raise ValueError("stored job input hash is invalid")
|
|
773
1127
|
fingerprint = document.get("fingerprint")
|
|
774
|
-
|
|
1128
|
+
execution_keys = (
|
|
1129
|
+
LEGACY_STORED_EXECUTION_KEYS if legacy else STORED_EXECUTION_KEYS
|
|
1130
|
+
)
|
|
1131
|
+
execution = {key: original[key] for key in execution_keys}
|
|
775
1132
|
if (
|
|
776
1133
|
not isinstance(fingerprint, str)
|
|
777
1134
|
or re.fullmatch(r"[0-9a-f]{64}", fingerprint) is None
|
|
@@ -803,7 +1160,9 @@ def _preview(job: Mapping[str, Any]) -> dict[str, Any]:
|
|
|
803
1160
|
"count": len(job["outputs"]),
|
|
804
1161
|
"prompt": job["prompt"],
|
|
805
1162
|
"source": job["source"],
|
|
1163
|
+
"source_entry": job["source_entry"],
|
|
806
1164
|
"references": job["references"],
|
|
1165
|
+
"reference_bindings": job["reference_bindings"],
|
|
807
1166
|
"outputs": job["outputs"],
|
|
808
1167
|
"parameters": job["parameters"],
|
|
809
1168
|
"overwrite": job["overwrite"],
|