@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.
Files changed (479) hide show
  1. package/README.md +56 -12
  2. package/lib/client.js +2707 -268
  3. package/lib/client.js.map +4 -4
  4. package/lib/drama/manifest.json +136 -101
  5. package/lib/drama/skills/short-drama/SKILL.md +61 -1
  6. package/lib/drama/skills/short-drama/references/contract-and-ownership.md +7 -4
  7. package/lib/drama/skills/short-drama/references/creator-documents.md +133 -8
  8. package/lib/drama/skills/short-drama/references/creator-workflow.md +38 -2
  9. package/lib/drama/skills/short-drama/references/knowhow-index.md +3 -0
  10. package/lib/drama/skills/short-drama/references/reference-roles.md +10 -7
  11. package/lib/drama/skills/short-drama/references/runtime-preflight.md +3 -0
  12. package/lib/drama/skills/short-drama/scripts/creator_markdown_check.py +1002 -0
  13. package/lib/drama/skills/short-drama/scripts/project_tool.py +485 -5
  14. package/lib/drama/skills/short-drama-assets/SKILL.md +13 -3
  15. package/lib/drama/skills/short-drama-assets/references/continuity-lock.md +116 -0
  16. package/lib/drama/skills/short-drama-assets/references/identity-vs-variant.md +2 -1
  17. package/lib/drama/skills/short-drama-assets/references/prop-and-state.md +19 -0
  18. package/lib/drama/skills/short-drama-assets/references/stage-contract.md +2 -0
  19. package/lib/drama/skills/short-drama-assets/scripts/asset_check.py +1 -1
  20. package/lib/drama/skills/short-drama-image-prompts/SKILL.md +6 -2
  21. package/lib/drama/skills/short-drama-image-prompts/references/common-recipe.md +4 -3
  22. package/lib/drama/skills/short-drama-image-prompts/references/lookdev-frame.md +1 -1
  23. package/lib/drama/skills/short-drama-image-prompts/references/review-and-fixtures.md +1 -1
  24. package/lib/drama/skills/short-drama-image-prompts/references/stage-contract.md +3 -1
  25. package/lib/drama/skills/short-drama-image-prompts/scripts/image_prompt_check.py +8 -8
  26. package/lib/drama/skills/short-drama-image-prompts/scripts/selftest.py +4 -2
  27. package/lib/drama/skills/short-drama-produce/SKILL.md +46 -10
  28. package/lib/drama/skills/short-drama-produce/references/adapter-contract.md +65 -8
  29. package/lib/drama/skills/short-drama-produce/references/providers/minimax-h3-video.md +85 -0
  30. package/lib/drama/skills/short-drama-produce/references/providers/seedance.md +27 -10
  31. package/lib/drama/skills/short-drama-produce/scripts/production_tool.py +362 -3
  32. package/lib/drama/skills/short-drama-produce/scripts/provider_adapters.py +627 -40
  33. package/lib/drama/skills/short-drama-produce/scripts/selftest.py +5 -4
  34. package/lib/drama/skills/short-drama-review/references/rubric-visual-motion.md +12 -0
  35. package/lib/drama/skills/short-drama-review/scripts/review_check.py +1 -1
  36. package/lib/drama/skills/short-drama-storyboard/SKILL.md +76 -7
  37. package/lib/drama/skills/short-drama-storyboard/assets/shot-template.jsonl +1 -1
  38. package/lib/drama/skills/short-drama-storyboard/references/keyframe-craft.md +6 -2
  39. package/lib/drama/skills/short-drama-storyboard/references/production-shot-grammar.md +19 -4
  40. package/lib/drama/skills/short-drama-storyboard/references/review-and-fixtures.md +5 -2
  41. package/lib/drama/skills/short-drama-storyboard/references/screenplay-to-keyframe-example.md +16 -0
  42. package/lib/drama/skills/short-drama-storyboard/references/stage-contract.md +8 -3
  43. package/lib/drama/skills/short-drama-storyboard/scripts/storyboard_check.py +1 -1
  44. package/lib/drama/skills/short-drama-video-prompts/SKILL.md +81 -13
  45. package/lib/drama/skills/short-drama-video-prompts/assets/motion-spec.jsonl.md +6 -1
  46. package/lib/drama/skills/short-drama-video-prompts/assets/video-prompts.md +17 -1
  47. package/lib/drama/skills/short-drama-video-prompts/references/delivery-profile.md +21 -1
  48. package/lib/drama/skills/short-drama-video-prompts/references/minimax-h3.md +154 -0
  49. package/lib/drama/skills/short-drama-video-prompts/references/motion-recipe.md +24 -6
  50. package/lib/drama/skills/short-drama-video-prompts/references/production-prompt-grammar.md +11 -7
  51. package/lib/drama/skills/short-drama-video-prompts/references/seedance-2.0.md +41 -0
  52. package/lib/drama/skills/short-drama-video-prompts/references/seedance-2.5.md +66 -0
  53. package/lib/drama/skills/short-drama-video-prompts/references/stage-contract.md +5 -2
  54. package/lib/drama/skills/short-drama-video-prompts/references/target-model-profile.md +115 -0
  55. package/lib/drama/skills/short-drama-video-prompts/scripts/container_check.py +1 -1
  56. package/lib/drama/skills/short-drama-video-prompts/scripts/music_spec_check.py +1 -1
  57. package/lib/drama/skills/short-drama-write/SKILL.md +3 -2
  58. package/lib/drama/skills/short-drama-write/scripts/duration_estimate.py +1 -1
  59. package/lib/drama/skills/short-drama-write/scripts/screenplay_index.py +2 -2
  60. package/lib/drama/skills/short-drama-write/scripts/voice_sheet_check.py +1 -1
  61. package/lib/index.js +865 -33
  62. package/lib/index.js.map +4 -4
  63. package/lib/novel-to-game/LICENSE +21 -0
  64. package/lib/novel-to-game/README.md +180 -0
  65. package/lib/novel-to-game/README_ZH.md +178 -0
  66. package/lib/novel-to-game/VERSION +1 -0
  67. package/lib/novel-to-game/examples/jin-ping-mei/build/BUILD_BRIEF.md +217 -0
  68. package/lib/novel-to-game/examples/jin-ping-mei/build/app/.vercelignore +3 -0
  69. package/lib/novel-to-game/examples/jin-ping-mei/build/app/RUN.md +130 -0
  70. package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/bg/compound_new_guofeng.webp +0 -0
  71. package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/cg/finale/fate_coda.webp +0 -0
  72. package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/cg/finale/meng.webp +0 -0
  73. package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/cg/finale/pan.webp +0 -0
  74. package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/cg/finale/pinger.webp +0 -0
  75. package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/cg/finale/xuee.webp +0 -0
  76. package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/cg/finale/yue.webp +0 -0
  77. package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/cg/group/inner_court_accord_five.webp +0 -0
  78. package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/cg/group/inner_court_afterglow_five.webp +0 -0
  79. package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/cg/group/inner_court_alliance.webp +0 -0
  80. package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/cg/group/public_day10.webp +0 -0
  81. package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/cg/group/public_day15.webp +0 -0
  82. package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/cg/group/public_day5.webp +0 -0
  83. package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/cg/group/title_new_guofeng.webp +0 -0
  84. package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/cg/joint/pan_pinger.webp +0 -0
  85. package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/cg/joint/pan_xuee.webp +0 -0
  86. package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/cg/joint/yue_meng.webp +0 -0
  87. package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/cg/joint/yue_pan.webp +0 -0
  88. package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/cg/joint/yue_pinger.webp +0 -0
  89. package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/cg/meng/explicit.webp +0 -0
  90. package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/cg/meng/prelude.webp +0 -0
  91. package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/cg/milestone/meng.webp +0 -0
  92. package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/cg/milestone/pan.webp +0 -0
  93. package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/cg/milestone/pinger.webp +0 -0
  94. package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/cg/milestone/xuee.webp +0 -0
  95. package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/cg/milestone/yue.webp +0 -0
  96. package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/cg/pan/explicit.webp +0 -0
  97. package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/cg/pan/prelude.webp +0 -0
  98. package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/cg/pinger/explicit.webp +0 -0
  99. package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/cg/pinger/prelude.webp +0 -0
  100. package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/cg/xuee/explicit.webp +0 -0
  101. package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/cg/xuee/prelude.webp +0 -0
  102. package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/cg/yue/explicit.webp +0 -0
  103. package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/cg/yue/prelude.webp +0 -0
  104. package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/heroine/meng/night.webp +0 -0
  105. package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/heroine/pan/night.webp +0 -0
  106. package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/heroine/pinger/night.webp +0 -0
  107. package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/heroine/xuee/night.webp +0 -0
  108. package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/heroine/yue/night.webp +0 -0
  109. package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/household/li_jiaoer.webp +0 -0
  110. package/lib/novel-to-game/examples/jin-ping-mei/build/app/assets/scene/gate_collector.webp +0 -0
  111. package/lib/novel-to-game/examples/jin-ping-mei/build/app/css/new-guofeng.css +1105 -0
  112. package/lib/novel-to-game/examples/jin-ping-mei/build/app/css/style.css +2539 -0
  113. package/lib/novel-to-game/examples/jin-ping-mei/build/app/index.html +18 -0
  114. package/lib/novel-to-game/examples/jin-ping-mei/build/app/js/assets.js +147 -0
  115. package/lib/novel-to-game/examples/jin-ping-mei/build/app/js/audio.js +332 -0
  116. package/lib/novel-to-game/examples/jin-ping-mei/build/app/js/data.js +7472 -0
  117. package/lib/novel-to-game/examples/jin-ping-mei/build/app/js/engine.js +13077 -0
  118. package/lib/novel-to-game/examples/jin-ping-mei/build/app/js/main.js +3028 -0
  119. package/lib/novel-to-game/examples/jin-ping-mei/build/app/js/text.js +32 -0
  120. package/lib/novel-to-game/examples/jin-ping-mei/build/app/package.json +10 -0
  121. package/lib/novel-to-game/examples/jin-ping-mei/build/app/vercel.json +23 -0
  122. package/lib/novel-to-game/examples/jin-ping-mei/build/art/generated-art.json +161 -0
  123. package/lib/novel-to-game/examples/jin-ping-mei/example.json +12 -0
  124. package/lib/novel-to-game/examples/jin-ping-mei/qa/README.md +31 -0
  125. package/lib/novel-to-game/examples/jin-ping-mei/qa/playable-model.json +99 -0
  126. package/lib/novel-to-game/examples/jin-ping-mei/qa/verification.json +41 -0
  127. package/lib/novel-to-game/examples/jin-ping-mei/qa/verify_playable_model.mjs +129 -0
  128. package/lib/novel-to-game/manifest.json +508 -0
  129. package/lib/novel-to-game/skills/game-art-direction/SKILL.md +73 -0
  130. package/lib/novel-to-game/skills/game-art-direction/agents/openai.yaml +4 -0
  131. package/lib/novel-to-game/skills/game-art-direction/references/art-direction-method.md +119 -0
  132. package/lib/novel-to-game/skills/game-build/SKILL.md +84 -0
  133. package/lib/novel-to-game/skills/game-build/agents/openai.yaml +4 -0
  134. package/lib/novel-to-game/skills/game-build/references/build-brief-contract.md +109 -0
  135. package/lib/novel-to-game/skills/game-build/references/generative-media-pipeline.md +56 -0
  136. package/lib/novel-to-game/skills/game-build/references/playable-model-contract.md +81 -0
  137. package/lib/novel-to-game/skills/game-build/references/tts-production-contract.md +37 -0
  138. package/lib/novel-to-game/skills/game-concept/SKILL.md +72 -0
  139. package/lib/novel-to-game/skills/game-concept/agents/openai.yaml +4 -0
  140. package/lib/novel-to-game/skills/game-concept/references/concept-method.md +94 -0
  141. package/lib/novel-to-game/skills/game-qa/SKILL.md +50 -0
  142. package/lib/novel-to-game/skills/game-qa/agents/openai.yaml +4 -0
  143. package/lib/novel-to-game/skills/game-qa/references/qa-contract.md +66 -0
  144. package/lib/novel-to-game/skills/game-qa/references/test-design-method.md +45 -0
  145. package/lib/novel-to-game/skills/game-world-design/SKILL.md +63 -0
  146. package/lib/novel-to-game/skills/game-world-design/agents/openai.yaml +4 -0
  147. package/lib/novel-to-game/skills/game-world-design/references/dialogue-design-method.md +59 -0
  148. package/lib/novel-to-game/skills/game-world-design/references/game-writing-craft.md +53 -0
  149. package/lib/novel-to-game/skills/game-world-design/references/narrative-design-method.md +84 -0
  150. package/lib/novel-to-game/skills/game-world-design/references/numeric-design-method.md +56 -0
  151. package/lib/novel-to-game/skills/game-world-design/references/world-design-method.md +124 -0
  152. package/lib/novel-to-game/skills/novel-game-analyze/SKILL.md +77 -0
  153. package/lib/novel-to-game/skills/novel-game-analyze/agents/openai.yaml +4 -0
  154. package/lib/novel-to-game/skills/novel-game-analyze/references/gameability-protocol.md +65 -0
  155. package/lib/novel-to-game/skills/novel-to-game/SKILL.md +71 -0
  156. package/lib/novel-to-game/skills/novel-to-game/agents/openai.yaml +4 -0
  157. package/lib/novel-to-game/skills/novel-to-game/references/intake-benchmark-reference.md +42 -0
  158. package/lib/novel-to-game/skills/novel-to-game/references/intake-method.md +51 -0
  159. package/lib/novel-to-game/skills/novel-to-game/references/pipeline-contract.md +65 -0
  160. package/lib/oh-story/manifest.json +415 -305
  161. package/lib/oh-story/roles/consistency-checker.md +1 -1
  162. package/lib/oh-story/roles/narrative-writer.md +32 -33
  163. package/lib/oh-story/roles/story-architect.md +16 -26
  164. package/lib/oh-story/skills/browser-cdp/SKILL.md +1 -1
  165. package/lib/oh-story/skills/story/SKILL.md +16 -9
  166. package/lib/oh-story/skills/story/VERSION +1 -1
  167. package/lib/oh-story/skills/story/references/author-memory.md +163 -0
  168. package/lib/oh-story/skills/story/scripts/author_memory_commit.py +871 -0
  169. package/lib/oh-story/skills/story-cover/SKILL.md +1 -1
  170. package/lib/oh-story/skills/story-deslop/SKILL.md +10 -5
  171. package/lib/oh-story/skills/story-deslop/references/anti-ai-writing.md +2 -1
  172. package/lib/oh-story/skills/story-deslop/references/author-memory.md +163 -0
  173. package/lib/oh-story/skills/story-deslop/references/banned-words.md +6 -4
  174. package/lib/oh-story/skills/story-deslop/scripts/author_memory_commit.py +871 -0
  175. package/lib/oh-story/skills/story-deslop/scripts/check-ai-patterns.js +64 -1
  176. package/lib/oh-story/skills/story-import/SKILL.md +19 -10
  177. package/lib/oh-story/skills/story-import/references/format-and-structure.md +9 -10
  178. package/lib/oh-story/skills/story-import/references/structure-mapping-long.md +2 -2
  179. package/lib/oh-story/skills/story-import/references/structure-mapping-short.md +1 -1
  180. package/lib/oh-story/skills/story-import/references/tracking-transaction.md +14 -6
  181. package/lib/oh-story/skills/story-import/scripts/check-outline-contract.js +251 -0
  182. package/lib/oh-story/skills/story-import/scripts/tracking_commit.py +98 -9
  183. package/lib/oh-story/skills/story-import/scripts/wordcount_core.py +246 -0
  184. package/lib/oh-story/skills/story-long-analyze/SKILL.md +4 -4
  185. package/lib/oh-story/skills/story-long-scan/SKILL.md +1 -1
  186. package/lib/oh-story/skills/story-long-write/SKILL.md +35 -21
  187. package/lib/oh-story/skills/story-long-write/references/anti-ai-writing.md +2 -1
  188. package/lib/oh-story/skills/story-long-write/references/artifact-protocols.md +7 -3
  189. package/lib/oh-story/skills/story-long-write/references/author-memory.md +163 -0
  190. package/lib/oh-story/skills/story-long-write/references/banned-words.md +6 -4
  191. package/lib/oh-story/skills/story-long-write/references/cross-book-recall.md +6 -6
  192. package/lib/oh-story/skills/story-long-write/references/genre-prose-cards.md +1 -1
  193. package/lib/oh-story/skills/story-long-write/references/genre-readers.md +1 -1
  194. package/lib/oh-story/skills/{story-setup/references/agent-references/hooks-chapter.md → story-long-write/references/long-chapter-hooks.md} +5 -5
  195. package/lib/oh-story/skills/story-long-write/references/{quality-checklist.md → long-chapter-quality.md} +2 -1
  196. package/lib/oh-story/skills/story-long-write/references/long-format.md +42 -0
  197. package/lib/oh-story/skills/{story-setup/references/agent-references/genre-catalog.md → story-long-write/references/long-genre-catalog.md} +11 -97
  198. package/lib/oh-story/skills/{story-setup/references/agent-references/genre-core-mechanics.md → story-long-write/references/long-genre-mechanics.md} +1 -1
  199. package/lib/oh-story/skills/{story-short-write/references/reversal-toolkit.md → story-long-write/references/long-reversal.md} +18 -32
  200. package/lib/oh-story/skills/story-long-write/references/{hooks-suspense.md → long-suspense.md} +6 -6
  201. package/lib/oh-story/skills/story-long-write/references/opening-design.md +1 -1
  202. package/lib/oh-story/skills/story-long-write/references/outline-structure-theory.md +1 -1
  203. package/lib/oh-story/skills/story-long-write/references/style-genre-modules.md +1 -1
  204. package/lib/oh-story/skills/story-long-write/references/tracking-transaction.md +14 -6
  205. package/lib/oh-story/skills/story-long-write/references/workflow-chapter.md +32 -27
  206. package/lib/oh-story/skills/story-long-write/references/workflow-daily.md +4 -4
  207. package/lib/oh-story/skills/story-long-write/references/workflow-revision.md +2 -2
  208. package/lib/oh-story/skills/story-long-write/references/workflow-setup.md +14 -14
  209. package/lib/oh-story/skills/story-long-write/references/writing-craft.md +54 -54
  210. package/lib/oh-story/skills/story-long-write/scripts/author_memory_commit.py +871 -0
  211. package/lib/oh-story/skills/story-long-write/scripts/check-ai-patterns.js +64 -1
  212. package/lib/oh-story/skills/story-long-write/scripts/check-outline-contract.js +251 -0
  213. package/lib/oh-story/skills/story-long-write/scripts/storyctl.py +303 -0
  214. package/lib/oh-story/skills/story-long-write/scripts/tracking_commit.py +98 -9
  215. package/lib/oh-story/skills/story-long-write/scripts/wordcount_core.py +246 -0
  216. package/lib/oh-story/skills/story-review/SKILL.md +26 -17
  217. package/lib/oh-story/skills/story-review/references/anti-ai-writing.md +2 -1
  218. package/lib/oh-story/skills/story-review/references/author-memory.md +163 -0
  219. package/lib/oh-story/skills/story-review/references/banned-words.md +6 -4
  220. package/lib/oh-story/skills/story-review/references/{quality-checklist.md → review-quality.md} +22 -21
  221. package/lib/oh-story/skills/story-review/references/tracking-transaction.md +14 -6
  222. package/lib/oh-story/skills/story-review/scripts/author_memory_commit.py +871 -0
  223. package/lib/oh-story/skills/story-review/scripts/check-ai-patterns.js +64 -1
  224. package/lib/oh-story/skills/story-review/scripts/tracking_commit.py +98 -9
  225. package/lib/oh-story/skills/story-review/scripts/wordcount_core.py +246 -0
  226. package/lib/oh-story/skills/story-setup/SKILL.md +74 -33
  227. package/lib/oh-story/skills/story-setup/references/agent-references/agent-quality.md +72 -0
  228. package/lib/oh-story/skills/story-setup/references/agent-references/agent-reference-profiles.md +55 -0
  229. package/lib/oh-story/skills/story-setup/references/agent-references/anti-ai-writing.md +2 -1
  230. package/lib/oh-story/skills/story-setup/references/agent-references/banned-words.md +6 -4
  231. package/lib/oh-story/skills/story-setup/references/agent-references/format-and-structure.md +9 -10
  232. package/lib/oh-story/skills/story-setup/references/agent-references/genre-prose-cards.md +1 -1
  233. package/lib/oh-story/skills/story-setup/references/agent-references/genre-readers.md +1 -1
  234. package/lib/oh-story/skills/{story-short-analyze/references/hooks-chapter.md → story-setup/references/agent-references/long-chapter-hooks.md} +5 -5
  235. package/lib/oh-story/skills/story-setup/references/agent-references/long-emotional-methods.md +209 -0
  236. package/lib/oh-story/skills/{story-long-write/references/genre-catalog.md → story-setup/references/agent-references/long-genre-catalog.md} +11 -97
  237. package/lib/oh-story/skills/{story-long-write/references/genre-core-mechanics.md → story-setup/references/agent-references/long-genre-mechanics.md} +1 -1
  238. package/lib/oh-story/skills/story-setup/references/agent-references/long-quality.md +40 -0
  239. package/lib/oh-story/skills/story-setup/references/agent-references/{reversal-toolkit.md → long-reversal.md} +18 -32
  240. package/lib/oh-story/skills/{story-short-write/references/hooks-suspense.md → story-setup/references/agent-references/long-suspense.md} +6 -6
  241. package/lib/oh-story/skills/story-setup/references/agent-references/opening-design.md +1 -1
  242. package/lib/oh-story/skills/story-setup/references/agent-references/{emotional-methods.md → short-emotional-methods.md} +4 -4
  243. package/lib/oh-story/skills/{story-long-write/references/genre-writing-formulas.md → story-setup/references/agent-references/short-genre-formulas.md} +32 -44
  244. package/lib/oh-story/skills/story-setup/references/agent-references/short-quality.md +39 -0
  245. package/lib/oh-story/skills/{story-long-write/references/reversal-toolkit.md → story-setup/references/agent-references/short-reversal.md} +29 -23
  246. package/lib/oh-story/skills/story-setup/references/agent-references/{hooks-suspense.md → short-suspense.md} +31 -31
  247. package/lib/oh-story/skills/story-setup/references/agent-references/style-genre-modules.md +1 -1
  248. package/lib/oh-story/skills/story-setup/references/agent-references/writing-craft.md +55 -55
  249. package/lib/oh-story/skills/story-short-analyze/SKILL.md +28 -28
  250. package/lib/oh-story/skills/story-short-analyze/references/{character-basics.md → analysis-character-basics.md} +1 -1
  251. package/lib/oh-story/skills/story-short-analyze/references/{character-design-methods.md → analysis-character-design.md} +1 -1
  252. package/lib/oh-story/skills/story-short-analyze/references/{character-relations.md → analysis-character-relations.md} +1 -1
  253. package/lib/oh-story/skills/story-short-analyze/references/{hooks-paragraph.md → analysis-paragraph-hooks.md} +1 -1
  254. package/lib/oh-story/skills/story-short-analyze/references/{genre-readers.md → analysis-reader-profile.md} +2 -2
  255. package/lib/oh-story/skills/story-short-analyze/references/analysis-report-style.md +45 -0
  256. package/lib/oh-story/skills/story-short-analyze/references/analysis-short-genres.md +65 -0
  257. package/lib/oh-story/skills/story-short-analyze/references/analysis-short-hooks.md +77 -0
  258. package/lib/oh-story/skills/story-short-analyze/references/analysis-short-mechanics.md +82 -0
  259. package/lib/oh-story/skills/story-short-analyze/references/analysis-short-patterns.md +50 -0
  260. package/lib/oh-story/skills/story-short-analyze/references/analysis-short-suspense.md +98 -0
  261. package/lib/oh-story/skills/story-short-analyze/references/{genre-writing-techniques.md → analysis-writing-techniques.md} +21 -19
  262. package/lib/oh-story/skills/story-short-analyze/references/deconstruction-examples.md +1 -1
  263. package/lib/oh-story/skills/story-short-analyze/references/material-decomposition.md +21 -28
  264. package/lib/oh-story/skills/story-short-analyze/references/output-contract.md +1 -1
  265. package/lib/oh-story/skills/story-short-analyze/references/output-templates.md +17 -17
  266. package/lib/oh-story/skills/story-short-analyze/references/{quality-checklist.md → source-story-quality.md} +28 -49
  267. package/lib/oh-story/skills/story-short-analyze/references/zhihu-style.md +2 -2
  268. package/lib/oh-story/skills/story-short-scan/SKILL.md +1 -1
  269. package/lib/oh-story/skills/story-short-write/SKILL.md +78 -55
  270. package/lib/oh-story/skills/story-short-write/references/author-memory.md +163 -0
  271. package/lib/oh-story/skills/story-short-write/references/banned-words.md +6 -4
  272. package/lib/oh-story/skills/story-short-write/references/cross-book-recall.md +3 -3
  273. package/lib/oh-story/skills/story-short-write/references/emotional-methods.md +4 -4
  274. 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
  275. package/lib/oh-story/skills/story-short-write/references/genre-styles//345/217/214/347/224/267/344/270/273.md +2 -2
  276. 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
  277. 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
  278. 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
  279. package/lib/oh-story/skills/story-short-write/references/genre-styles//346/202/254/347/226/221.md +4 -4
  280. 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
  281. 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
  282. package/lib/oh-story/skills/story-short-write/references/genre-styles//347/224/234/345/256/240.md +4 -4
  283. 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
  284. package/lib/oh-story/skills/story-short-write/references/genre-writing-formulas.md +32 -44
  285. package/lib/oh-story/skills/story-short-write/references/genre-writing-techniques.md +20 -18
  286. package/lib/oh-story/skills/story-short-write/references/output-contract.md +1 -1
  287. package/lib/oh-story/skills/story-short-write/references/short-craft.md +18 -18
  288. package/lib/oh-story/skills/story-short-write/references/short-deslop.md +1 -1
  289. package/lib/oh-story/skills/story-short-write/references/short-format.md +38 -8
  290. package/lib/oh-story/skills/story-short-write/references/{quality-checklist.md → short-prose-quality.md} +22 -21
  291. package/lib/oh-story/skills/story-short-write/references/short-reversal.md +355 -0
  292. package/lib/oh-story/skills/{story-short-analyze/references/hooks-suspense.md → story-short-write/references/short-suspense.md} +31 -31
  293. package/lib/oh-story/skills/story-short-write/references/submission-craft.md +2 -2
  294. package/lib/oh-story/skills/story-short-write/references/writing-workflow.md +31 -22
  295. package/lib/oh-story/skills/story-short-write/scripts/author_memory_commit.py +871 -0
  296. package/lib/oh-story/skills/story-short-write/scripts/check-ai-patterns.js +64 -1
  297. package/lib/oh-story/skills/story-short-write/scripts/check-delivery-contract.js +212 -0
  298. package/lib/oh-story/skills/story-short-write/scripts/check-phase2-contract.js +363 -0
  299. package/lib/types/client/drama-production-view.d.ts +34 -0
  300. package/lib/types/client/drama-production-view.d.ts.map +1 -0
  301. package/lib/types/client/drama-production.d.ts +92 -0
  302. package/lib/types/client/drama-production.d.ts.map +1 -0
  303. package/lib/types/client/file-activity.d.ts +4 -2
  304. package/lib/types/client/file-activity.d.ts.map +1 -1
  305. package/lib/types/client/index.d.ts +1 -1
  306. package/lib/types/client/index.d.ts.map +1 -1
  307. package/lib/types/client/production-intents.d.ts +9 -0
  308. package/lib/types/client/production-intents.d.ts.map +1 -0
  309. package/lib/types/client/production-prompts.d.ts +9 -0
  310. package/lib/types/client/production-prompts.d.ts.map +1 -0
  311. package/lib/types/client/production-runtime.d.ts +58 -0
  312. package/lib/types/client/production-runtime.d.ts.map +1 -0
  313. package/lib/types/client/video-studio.d.ts +41 -0
  314. package/lib/types/client/video-studio.d.ts.map +1 -0
  315. package/lib/types/client/workbench-ui.d.ts +5 -0
  316. package/lib/types/client/workbench-ui.d.ts.map +1 -0
  317. package/lib/types/game-verification.d.ts +16 -0
  318. package/lib/types/game-verification.d.ts.map +1 -0
  319. package/lib/types/index.d.ts +3 -1
  320. package/lib/types/index.d.ts.map +1 -1
  321. package/lib/types/production-intent.d.ts +21 -0
  322. package/lib/types/production-intent.d.ts.map +1 -0
  323. package/lib/types/production-tool.d.ts +5 -0
  324. package/lib/types/production-tool.d.ts.map +1 -0
  325. package/lib/types/role-tool.d.ts.map +1 -1
  326. package/lib/types/skill-provider.d.ts +7 -0
  327. package/lib/types/skill-provider.d.ts.map +1 -1
  328. package/lib/types/video-project.d.ts +42 -0
  329. package/lib/types/video-project.d.ts.map +1 -0
  330. package/lib/types/workspace-request-trust.d.ts +6 -0
  331. package/lib/types/workspace-request-trust.d.ts.map +1 -1
  332. package/lib/types/workspace-route.d.ts +20 -0
  333. package/lib/types/workspace-route.d.ts.map +1 -1
  334. package/lib/video-recap/CHANGELOG.md +282 -0
  335. package/lib/video-recap/LICENSE +21 -0
  336. package/lib/video-recap/README.en.md +257 -0
  337. package/lib/video-recap/README.md +255 -0
  338. package/lib/video-recap/manifest.json +684 -0
  339. package/lib/video-recap/skills/video-assemble/SKILL.md +97 -0
  340. package/lib/video-recap/skills/video-assemble/references/jianying/LICENSE.duo-video +21 -0
  341. package/lib/video-recap/skills/video-assemble/references/jianying/SOURCE.md +15 -0
  342. package/lib/video-recap/skills/video-assemble/references/jianying/empty_draft_meta_info.json +69 -0
  343. package/lib/video-recap/skills/video-assemble/references/jianying/empty_jy_combination_segment.json +84 -0
  344. package/lib/video-recap/skills/video-assemble/references/jianying/empty_jy_combination_video_material.json +98 -0
  345. package/lib/video-recap/skills/video-assemble/references/jianying/empty_jy_draft.json +204 -0
  346. package/lib/video-recap/skills/video-assemble/references/jianying/empty_jy_material_video.json +83 -0
  347. package/lib/video-recap/skills/video-assemble/references/jianying/empty_jy_meta_material_value.json +23 -0
  348. package/lib/video-recap/skills/video-assemble/references/jianying/empty_jy_project_info.json +133 -0
  349. package/lib/video-recap/skills/video-assemble/references/jianying/empty_jy_segment.json +70 -0
  350. package/lib/video-recap/skills/video-assemble/references/jianying/empty_jy_text_styles.json +30 -0
  351. package/lib/video-recap/skills/video-assemble/references/jianying/empty_yj_material_audio.json +41 -0
  352. package/lib/video-recap/skills/video-assemble/references/jianying/empty_yj_material_text.json +109 -0
  353. package/lib/video-recap/skills/video-assemble/scripts/artifacts.py +88 -0
  354. package/lib/video-recap/skills/video-assemble/scripts/assemble.py +345 -0
  355. package/lib/video-recap/skills/video-assemble/scripts/assemble_constants.py +34 -0
  356. package/lib/video-recap/skills/video-assemble/scripts/assembly_contract.py +305 -0
  357. package/lib/video-recap/skills/video-assemble/scripts/assembly_settings.py +94 -0
  358. package/lib/video-recap/skills/video-assemble/scripts/audio_automation.py +205 -0
  359. package/lib/video-recap/skills/video-assemble/scripts/audio_mix.py +555 -0
  360. package/lib/video-recap/skills/video-assemble/scripts/export_jianying.py +261 -0
  361. package/lib/video-recap/skills/video-assemble/scripts/jianying_builders.py +767 -0
  362. package/lib/video-recap/skills/video-assemble/scripts/jianying_model.py +111 -0
  363. package/lib/video-recap/skills/video-assemble/scripts/jianying_optional.py +24 -0
  364. package/lib/video-recap/skills/video-assemble/scripts/jianying_schema.py +109 -0
  365. package/lib/video-recap/skills/video-assemble/scripts/jianying_templates.py +37 -0
  366. package/lib/video-recap/skills/video-assemble/scripts/jianying_timeline_contract.py +191 -0
  367. package/lib/video-recap/skills/video-assemble/scripts/jianying_tracks.py +75 -0
  368. package/lib/video-recap/skills/video-assemble/scripts/jianying_writer.py +394 -0
  369. package/lib/video-recap/skills/video-assemble/scripts/lib.py +239 -0
  370. package/lib/video-recap/skills/video-assemble/scripts/media.py +243 -0
  371. package/lib/video-recap/skills/video-assemble/scripts/narration_audio.py +477 -0
  372. package/lib/video-recap/skills/video-assemble/scripts/render_preflight.py +46 -0
  373. package/lib/video-recap/skills/video-assemble/scripts/source_subtitles.py +486 -0
  374. package/lib/video-recap/skills/video-assemble/scripts/subtitle_core.py +376 -0
  375. package/lib/video-recap/skills/video-assemble/scripts/subtitle_render.py +88 -0
  376. package/lib/video-recap/skills/video-assemble/scripts/timeline.py +248 -0
  377. package/lib/video-recap/skills/video-assemble/scripts/timeline_emit.py +89 -0
  378. package/lib/video-recap/skills/video-assemble/scripts/visual_render.py +512 -0
  379. package/lib/video-recap/skills/video-cut/SKILL.md +90 -0
  380. package/lib/video-recap/skills/video-cut/scripts/cut.py +67 -0
  381. package/lib/video-recap/skills/video-cut/scripts/cut_cli.py +320 -0
  382. package/lib/video-recap/skills/video-cut/scripts/cut_contract.py +545 -0
  383. package/lib/video-recap/skills/video-cut/scripts/cut_render.py +348 -0
  384. package/lib/video-recap/skills/video-cut/scripts/lib.py +77 -0
  385. package/lib/video-recap/skills/video-cut/scripts/media_geometry.py +341 -0
  386. package/lib/video-recap/skills/video-cut/scripts/narration_mapping.py +249 -0
  387. package/lib/video-recap/skills/video-cut/scripts/sentence_boundaries.py +745 -0
  388. package/lib/video-recap/skills/video-recap/SKILL.md +216 -0
  389. package/lib/video-recap/skills/video-recap/references/config-playbook.md +61 -0
  390. package/lib/video-recap/skills/video-recap/references/creative-editing-playbook.md +225 -0
  391. package/lib/video-recap/skills/video-recap/references/data-schema.md +534 -0
  392. package/lib/video-recap/skills/video-recap/references/research-guide.md +74 -0
  393. package/lib/video-recap/skills/video-recap/references/shift-left-qc-schema.md +23 -0
  394. package/lib/video-recap/skills/video-recap/references/timeline-and-jianying.md +251 -0
  395. package/lib/video-recap/skills/video-recap/scripts/doctor.py +483 -0
  396. package/lib/video-recap/skills/video-recap/scripts/final_qc.py +737 -0
  397. package/lib/video-recap/skills/video-recap/scripts/lib.py +242 -0
  398. package/lib/video-recap/skills/video-recap/scripts/materials.py +457 -0
  399. package/lib/video-recap/skills/video-recap/scripts/mimo_qc.py +95 -0
  400. package/lib/video-recap/skills/video-recap/scripts/mimo_qc_client.py +18 -0
  401. package/lib/video-recap/skills/video-recap/scripts/mimo_qc_contract.py +9 -0
  402. package/lib/video-recap/skills/video-recap/scripts/mimo_qc_evidence.py +371 -0
  403. package/lib/video-recap/skills/video-recap/scripts/mimo_qc_observations.py +201 -0
  404. package/lib/video-recap/skills/video-recap/scripts/mimo_qc_payload.py +227 -0
  405. package/lib/video-recap/skills/video-recap/scripts/mimo_qc_report.py +362 -0
  406. package/lib/video-recap/skills/video-recap/scripts/mimo_qc_runner.py +129 -0
  407. package/lib/video-recap/skills/video-recap/scripts/qc_contract.py +338 -0
  408. package/lib/video-recap/skills/video-recap/scripts/recap.py +9 -0
  409. package/lib/video-recap/skills/video-recap/scripts/recap_cli.py +140 -0
  410. package/lib/video-recap/skills/video-recap/scripts/recap_inspect.py +550 -0
  411. package/lib/video-recap/skills/video-recap/scripts/recap_review.py +77 -0
  412. package/lib/video-recap/skills/video-recap/scripts/recap_runner.py +654 -0
  413. package/lib/video-recap/skills/video-recap/scripts/recap_runtime.py +335 -0
  414. package/lib/video-recap/skills/video-recap/scripts/recap_stage_qc.py +217 -0
  415. package/lib/video-recap/skills/video-recap/scripts/recap_timeline.py +795 -0
  416. package/lib/video-recap/skills/video-script/SKILL.md +248 -0
  417. package/lib/video-recap/skills/video-script/references/creative-editing-playbook.md +225 -0
  418. package/lib/video-recap/skills/video-script/references/research-guide.md +75 -0
  419. package/lib/video-recap/skills/video-script/scripts/agent_brief.py +399 -0
  420. package/lib/video-recap/skills/video-script/scripts/agent_text.py +410 -0
  421. package/lib/video-recap/skills/video-script/scripts/brief_context.py +403 -0
  422. package/lib/video-recap/skills/video-script/scripts/brief_inputs.py +332 -0
  423. package/lib/video-recap/skills/video-script/scripts/brief_timeline.py +442 -0
  424. package/lib/video-recap/skills/video-script/scripts/deslop_qc.py +237 -0
  425. package/lib/video-recap/skills/video-script/scripts/evidence_bundle.py +492 -0
  426. package/lib/video-recap/skills/video-script/scripts/lib.py +327 -0
  427. package/lib/video-recap/skills/video-script/scripts/narration.py +12 -0
  428. package/lib/video-recap/skills/video-script/scripts/narration_lint.py +678 -0
  429. package/lib/video-recap/skills/video-script/scripts/review.py +42 -0
  430. package/lib/video-recap/skills/video-script/scripts/review_grounding.py +262 -0
  431. package/lib/video-recap/skills/video-script/scripts/review_response.py +761 -0
  432. package/lib/video-recap/skills/video-script/scripts/review_runner.py +200 -0
  433. package/lib/video-recap/skills/video-script/scripts/speech_ownership.py +204 -0
  434. package/lib/video-recap/skills/video-script/scripts/timeline_fusion.py +199 -0
  435. package/lib/video-recap/skills/video-script/scripts/validate.py +164 -0
  436. package/lib/video-recap/skills/video-understanding/SKILL.md +75 -0
  437. package/lib/video-recap/skills/video-understanding/references/data-schema.md +299 -0
  438. package/lib/video-recap/skills/video-understanding/references/prompt-templates.md +37 -0
  439. package/lib/video-recap/skills/video-understanding/references/research-guide.md +74 -0
  440. package/lib/video-recap/skills/video-understanding/scripts/agent_brief.py +399 -0
  441. package/lib/video-recap/skills/video-understanding/scripts/agent_text.py +410 -0
  442. package/lib/video-recap/skills/video-understanding/scripts/asr.py +260 -0
  443. package/lib/video-recap/skills/video-understanding/scripts/brief.py +12 -0
  444. package/lib/video-recap/skills/video-understanding/scripts/brief_context.py +403 -0
  445. package/lib/video-recap/skills/video-understanding/scripts/brief_inputs.py +332 -0
  446. package/lib/video-recap/skills/video-understanding/scripts/brief_timeline.py +442 -0
  447. package/lib/video-recap/skills/video-understanding/scripts/consolidate.py +647 -0
  448. package/lib/video-recap/skills/video-understanding/scripts/deslop_qc.py +237 -0
  449. package/lib/video-recap/skills/video-understanding/scripts/detect.py +513 -0
  450. package/lib/video-recap/skills/video-understanding/scripts/extract.py +62 -0
  451. package/lib/video-recap/skills/video-understanding/scripts/lib.py +470 -0
  452. package/lib/video-recap/skills/video-understanding/scripts/narration_lint.py +678 -0
  453. package/lib/video-recap/skills/video-understanding/scripts/speech_ownership.py +204 -0
  454. package/lib/video-recap/skills/video-understanding/scripts/storyboard.py +507 -0
  455. package/lib/video-recap/skills/video-understanding/scripts/timeline_fusion.py +199 -0
  456. package/lib/video-recap/skills/video-understanding/scripts/understand.py +9 -0
  457. package/lib/video-recap/skills/video-understanding/scripts/understanding_brief.py +216 -0
  458. package/lib/video-recap/skills/video-understanding/scripts/understanding_cache.py +327 -0
  459. package/lib/video-recap/skills/video-understanding/scripts/understanding_runner.py +367 -0
  460. package/lib/video-recap/skills/video-understanding/scripts/understanding_storyboard.py +162 -0
  461. package/lib/video-recap/skills/video-understanding/scripts/vlm.py +705 -0
  462. package/lib/video-recap/skills/video-voiceover/SKILL.md +81 -0
  463. package/lib/video-recap/skills/video-voiceover/scripts/dub.py +637 -0
  464. package/lib/video-recap/skills/video-voiceover/scripts/fish_audio.py +109 -0
  465. package/lib/video-recap/skills/video-voiceover/scripts/lib.py +421 -0
  466. package/lib/video-recap/skills/video-voiceover/scripts/tts_audio.py +113 -0
  467. package/lib/video-recap/skills/video-voiceover/scripts/voiceover.py +782 -0
  468. package/package.json +55 -40
  469. package/lib/oh-story/skills/story-deslop/scripts/check-outline-copy.js +0 -241
  470. package/lib/oh-story/skills/story-long-write/references/format-and-structure.md +0 -169
  471. package/lib/oh-story/skills/story-setup/references/agent-references/genre-writing-formulas.md +0 -444
  472. package/lib/oh-story/skills/story-setup/references/agent-references/quality-checklist.md +0 -247
  473. package/lib/oh-story/skills/story-short-analyze/references/anti-ai-writing.md +0 -582
  474. package/lib/oh-story/skills/story-short-analyze/references/banned-words.md +0 -147
  475. package/lib/oh-story/skills/story-short-analyze/references/genre-catalog.md +0 -490
  476. package/lib/oh-story/skills/story-short-analyze/references/genre-core-mechanics.md +0 -425
  477. package/lib/oh-story/skills/story-short-analyze/references/genre-writing-formulas.md +0 -453
  478. /package/lib/oh-story/skills/{story-long-write/references/hooks-chapter.md → story-setup/references/agent-references/short-chapter-hooks.md} +0 -0
  479. /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. The broad parser envelope is
28
- 1–15 seconds and `adaptive`, `1:1`, `3:4`, `4:3`, `9:16`, `16:9`, or `21:9`,
29
- but it is never treated as proof that a particular model supports the whole
30
- set. Values are compiled into the documented prompt switches `--dur` and
31
- `--ratio`, not sent as unverified top-level fields.
32
- The bundled runtime adapter currently supports text-to-video only. Local references fail closed because the public video
33
- contract does not prove that a local data URL is accepted. A deployment that needs image-to-video must add an external,
34
- authorized upload step and call `compile_seedance_payload` with the resulting HTTPS or `asset://` URI; do not put a
35
- temporary provider URL into the creator project.
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
- references = [
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) or set(document) != STORED_JOB_KEYS:
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
- execution = {key: document[key] for key in STORED_EXECUTION_KEYS}
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"],