@oh-story/dsh 0.1.8 → 0.1.10

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 (360) hide show
  1. package/README.md +14 -14
  2. package/lib/client.js +237 -84
  3. package/lib/client.js.map +3 -3
  4. package/lib/drama/manifest.json +183 -77
  5. package/lib/drama/skills/short-drama/SKILL.md +5 -1
  6. package/lib/drama/skills/short-drama/scripts/creator_markdown_check.py +140 -9
  7. package/lib/drama/skills/short-drama/scripts/project_tool.py +11 -0
  8. package/lib/drama/skills/short-drama-assets/references/character-and-look.md +28 -0
  9. package/lib/drama/skills/short-drama-assets/references/continuity-lock.md +8 -2
  10. package/lib/drama/skills/short-drama-assets/references/voice-direction.md +28 -0
  11. package/lib/drama/skills/short-drama-edit/SKILL.md +146 -0
  12. package/lib/drama/skills/short-drama-edit/agents/openai.yaml +4 -0
  13. package/lib/drama/skills/short-drama-edit/assets/remotion/README.md +60 -0
  14. package/lib/drama/skills/short-drama-edit/assets/remotion/package.json +15 -0
  15. package/lib/drama/skills/short-drama-edit/assets/remotion/remotion.config.ts +6 -0
  16. package/lib/drama/skills/short-drama-edit/assets/remotion/src/Root.tsx +26 -0
  17. package/lib/drama/skills/short-drama-edit/assets/remotion/src/Subtitles.tsx +88 -0
  18. package/lib/drama/skills/short-drama-edit/assets/remotion/src/font.ts +46 -0
  19. package/lib/drama/skills/short-drama-edit/assets/remotion/src/index.ts +4 -0
  20. package/lib/drama/skills/short-drama-edit/assets/remotion/src/schema.ts +32 -0
  21. package/lib/drama/skills/short-drama-edit/assets/remotion/tsconfig.json +13 -0
  22. package/lib/drama/skills/short-drama-edit/assets//345/211/252/350/276/221/345/215/225.md +43 -0
  23. package/lib/drama/skills/short-drama-edit/references/cut-craft.md +38 -0
  24. package/lib/drama/skills/short-drama-edit/references/delivery-verify.md +29 -0
  25. package/lib/drama/skills/short-drama-edit/references/generated-footage.md +54 -0
  26. package/lib/drama/skills/short-drama-edit/references/sound-and-subtitles.md +60 -0
  27. package/lib/drama/skills/short-drama-edit/references/stage-contract.md +51 -0
  28. package/lib/drama/skills/short-drama-edit/scripts/edit_tool.py +1156 -0
  29. package/lib/drama/skills/short-drama-edit/scripts/selftest.py +520 -0
  30. package/lib/drama/skills/short-drama-image-prompts/SKILL.md +2 -0
  31. package/lib/drama/skills/short-drama-image-prompts/assets/image-prompts.md +5 -0
  32. package/lib/drama/skills/short-drama-image-prompts/assets/lookdev-prompts.md +3 -0
  33. package/lib/drama/skills/short-drama-image-prompts/references/common-recipe.md +11 -0
  34. package/lib/drama/skills/short-drama-novel-analyze/references/aggregation-and-entities.md +2 -2
  35. package/lib/drama/skills/short-drama-novel-analyze/references/chapter-extraction.md +4 -1
  36. package/lib/drama/skills/short-drama-produce/SKILL.md +29 -4
  37. package/lib/drama/skills/short-drama-produce/references/adapter-contract.md +22 -0
  38. package/lib/drama/skills/short-drama-produce/references/providers/minimax-h3-video.md +13 -12
  39. package/lib/drama/skills/short-drama-produce/references/providers/minimax-speech.md +41 -0
  40. package/lib/drama/skills/short-drama-produce/references/providers/seedance.md +7 -0
  41. package/lib/drama/skills/short-drama-produce/scripts/fixture_adapter.py +18 -1
  42. package/lib/drama/skills/short-drama-produce/scripts/production_tool.py +181 -2
  43. package/lib/drama/skills/short-drama-produce/scripts/provider_adapters.py +199 -3
  44. package/lib/drama/skills/short-drama-review/SKILL.md +2 -0
  45. package/lib/drama/skills/short-drama-review/references/production-quality-gates.md +7 -0
  46. package/lib/drama/skills/short-drama-review/references/rubric-visual-motion.md +10 -0
  47. package/lib/drama/skills/short-drama-storyboard/SKILL.md +12 -1
  48. package/lib/drama/skills/short-drama-storyboard/assets/keyframe-prompts.md +4 -0
  49. package/lib/drama/skills/short-drama-storyboard/references/lighting-craft.md +39 -0
  50. package/lib/drama/skills/short-drama-storyboard/references/shot-craft.md +78 -2
  51. package/lib/drama/skills/short-drama-storyboard/references/stage-contract.md +2 -0
  52. package/lib/drama/skills/short-drama-video-prompts/SKILL.md +12 -5
  53. package/lib/drama/skills/short-drama-video-prompts/references/camera-audio-continuity.md +17 -0
  54. package/lib/drama/skills/short-drama-video-prompts/references/minimax-h3.md +76 -7
  55. package/lib/drama/skills/short-drama-video-prompts/references/motion-recipe.md +5 -2
  56. package/lib/drama/skills/short-drama-video-prompts/references/performance-action-timing.md +21 -0
  57. package/lib/drama/skills/short-drama-video-prompts/references/production-prompt-grammar.md +6 -17
  58. package/lib/drama/skills/short-drama-video-prompts/references/seedance-2.0.md +12 -3
  59. package/lib/drama/skills/short-drama-video-prompts/references/seedance-2.5.md +61 -5
  60. package/lib/drama/skills/short-drama-video-prompts/references/stage-contract.md +3 -3
  61. package/lib/drama/skills/short-drama-write/SKILL.md +11 -2
  62. package/lib/drama/skills/short-drama-write/references/screenplay-format.md +6 -0
  63. package/lib/drama/skills/short-drama-write/references/stage-contract.md +1 -0
  64. package/lib/index.js +290 -90
  65. package/lib/index.js.map +4 -4
  66. package/lib/novel-to-game/README.md +299 -59
  67. package/lib/novel-to-game/README_ZH.md +299 -56
  68. package/lib/novel-to-game/VERSION +1 -1
  69. package/lib/novel-to-game/examples/jin-ping-mei/build/BUILD_BRIEF.md +3 -1
  70. package/lib/novel-to-game/examples/jin-ping-mei/build/app/RUN.md +11 -3
  71. package/lib/novel-to-game/examples/jin-ping-mei/build/app/css/new-guofeng.css +397 -8
  72. package/lib/novel-to-game/examples/jin-ping-mei/build/app/css/style.css +0 -31
  73. package/lib/novel-to-game/examples/jin-ping-mei/build/app/js/data.js +71 -73
  74. package/lib/novel-to-game/examples/jin-ping-mei/build/app/js/engine.js +78 -89
  75. package/lib/novel-to-game/examples/jin-ping-mei/build/app/js/main.js +37 -14
  76. package/lib/novel-to-game/examples/jin-ping-mei/build/app/js/text.js +5 -5
  77. package/lib/novel-to-game/examples/jin-ping-mei/build/app/package.json +2 -1
  78. package/lib/novel-to-game/examples/jin-ping-mei/qa/README.md +11 -16
  79. package/lib/novel-to-game/examples/jin-ping-mei/qa/verification.json +11 -11
  80. package/lib/novel-to-game/examples/jin-ping-mei/qa/verify_playable_model.mjs +23 -0
  81. package/lib/novel-to-game/manifest.json +77 -87
  82. package/lib/novel-to-game/skills/game-art-direction/SKILL.md +9 -35
  83. package/lib/novel-to-game/skills/game-art-direction/references/art-direction-method.md +27 -106
  84. package/lib/novel-to-game/skills/game-build/SKILL.md +17 -35
  85. package/lib/novel-to-game/skills/game-build/references/blender-asset-workflow.md +24 -0
  86. package/lib/novel-to-game/skills/game-build/references/build-brief-contract.md +45 -82
  87. package/lib/novel-to-game/skills/game-build/references/generative-media-pipeline.md +14 -45
  88. package/lib/novel-to-game/skills/game-build/references/playable-model-contract.md +30 -65
  89. package/lib/novel-to-game/skills/game-build/references/tts-production-contract.md +13 -27
  90. package/lib/novel-to-game/skills/game-concept/SKILL.md +16 -34
  91. package/lib/novel-to-game/skills/game-concept/references/concept-method.md +28 -75
  92. package/lib/novel-to-game/skills/game-qa/SKILL.md +9 -20
  93. package/lib/novel-to-game/skills/game-qa/references/test-design-method.md +10 -6
  94. package/lib/novel-to-game/skills/game-world-design/SKILL.md +19 -32
  95. package/lib/novel-to-game/skills/game-world-design/references/narrative-design-method.md +23 -72
  96. package/lib/novel-to-game/skills/game-world-design/references/numeric-design-method.md +14 -48
  97. package/lib/novel-to-game/skills/game-world-design/references/world-design-method.md +36 -103
  98. package/lib/novel-to-game/skills/novel-game-analyze/SKILL.md +9 -18
  99. package/lib/novel-to-game/skills/novel-game-analyze/references/gameability-protocol.md +4 -4
  100. package/lib/novel-to-game/skills/novel-to-game/SKILL.md +10 -27
  101. package/lib/novel-to-game/skills/novel-to-game/references/intake-method.md +5 -6
  102. package/lib/novel-to-game/skills/novel-to-game/references/pipeline-contract.md +6 -11
  103. package/lib/oh-story/manifest.json +419 -254
  104. package/lib/oh-story/roles/chapter-extractor.md +177 -237
  105. package/lib/oh-story/roles/character-designer.md +1 -1
  106. package/lib/oh-story/roles/consistency-checker.md +4 -4
  107. package/lib/oh-story/roles/narrative-writer.md +56 -243
  108. package/lib/oh-story/roles/story-architect.md +6 -6
  109. package/lib/oh-story/roles/story-explorer.md +11 -11
  110. package/lib/oh-story/skills/story/SKILL.md +13 -7
  111. package/lib/oh-story/skills/story/VERSION +1 -1
  112. package/lib/oh-story/skills/story/references/author-memory.md +61 -29
  113. package/lib/oh-story/skills/story/scripts/author_memory_commit.py +934 -170
  114. package/lib/oh-story/skills/story-cover/SKILL.md +10 -1
  115. package/lib/oh-story/skills/story-deslop/SKILL.md +54 -229
  116. package/lib/oh-story/skills/story-deslop/references/anti-ai-writing.md +29 -56
  117. package/lib/oh-story/skills/story-deslop/references/author-memory.md +61 -29
  118. package/lib/oh-story/skills/story-deslop/references/banned-words.md +3 -1
  119. package/lib/oh-story/skills/story-deslop/references/deslop-gates.md +154 -0
  120. package/lib/oh-story/skills/story-deslop/references/style-resolution.md +27 -0
  121. package/lib/oh-story/skills/story-deslop/scripts/author_memory_commit.py +934 -170
  122. package/lib/oh-story/skills/story-deslop/scripts/check-ai-patterns.js +6 -1
  123. package/lib/oh-story/skills/story-deslop/scripts/check-degeneration.js +39 -20
  124. package/lib/oh-story/skills/story-deslop/scripts/normalize-punctuation.js +10 -5
  125. package/lib/oh-story/skills/story-deslop/scripts/style-whitelist.js +39 -0
  126. package/lib/oh-story/skills/story-import/SKILL.md +78 -82
  127. package/lib/oh-story/skills/story-import/references/character-state-reverse.md +1 -1
  128. package/lib/oh-story/skills/story-import/references/format-and-structure.md +2 -2
  129. package/lib/oh-story/skills/story-import/references/state-tracking.md +4 -69
  130. package/lib/oh-story/skills/story-import/references/structure-mapping-long.md +10 -8
  131. package/lib/oh-story/skills/story-import/references/tracking-initialization.md +31 -0
  132. package/lib/oh-story/skills/story-import/references/tracking-transaction.md +9 -34
  133. package/lib/oh-story/skills/story-import/scripts/check-outline-contract.js +197 -15
  134. package/lib/oh-story/skills/story-import/scripts/tracking_commit.py +210 -2
  135. package/lib/oh-story/skills/story-import/scripts/wordcount_core.py +3 -0
  136. package/lib/oh-story/skills/story-long-analyze/SKILL.md +91 -258
  137. package/lib/oh-story/skills/story-long-analyze/references/author-facing.md +245 -0
  138. package/lib/oh-story/skills/story-long-analyze/references/deconstruction-notes.md +2 -2
  139. package/lib/oh-story/skills/story-long-analyze/references/inspiration-library.md +105 -0
  140. package/lib/oh-story/skills/story-long-analyze/references/material-decomposition.md +113 -105
  141. package/lib/oh-story/skills/story-long-analyze/references/output-templates.md +169 -125
  142. package/lib/oh-story/skills/story-long-analyze/references/pipeline-ops.md +172 -64
  143. package/lib/oh-story/skills/story-long-analyze/references/semantic-acceptance-fixtures.md +84 -0
  144. package/lib/oh-story/skills/story-long-analyze/references/style-profile-generator.md +42 -132
  145. package/lib/oh-story/skills/story-long-analyze/references/style-profile-protocol.md +5 -5
  146. package/lib/oh-story/skills/story-long-analyze/scripts/build_chapter_index.py +466 -0
  147. package/lib/oh-story/skills/story-long-analyze/scripts/inspect_existing_assets.py +702 -0
  148. package/lib/oh-story/skills/story-long-analyze/scripts/inspiration_index.py +864 -0
  149. package/lib/oh-story/skills/story-long-analyze/scripts/manage_analysis_run.py +1106 -0
  150. package/lib/oh-story/skills/story-long-analyze/scripts/render_relation_chart.py +425 -0
  151. package/lib/oh-story/skills/story-long-scan/SKILL.md +4 -1
  152. package/lib/oh-story/skills/story-long-write/SKILL.md +52 -216
  153. package/lib/oh-story/skills/story-long-write/references/anti-ai-writing.md +29 -56
  154. package/lib/oh-story/skills/story-long-write/references/artifact-protocols.md +72 -12
  155. package/lib/oh-story/skills/story-long-write/references/author-memory.md +61 -29
  156. package/lib/oh-story/skills/story-long-write/references/banned-words.md +3 -1
  157. package/lib/oh-story/skills/story-long-write/references/benchmark-recall.md +20 -0
  158. package/lib/oh-story/skills/story-long-write/references/cross-book-recall.md +26 -0
  159. package/lib/oh-story/skills/story-long-write/references/dialogue-mastery.md +10 -4
  160. package/lib/oh-story/skills/story-long-write/references/emotional-methods.md +2 -2
  161. package/lib/oh-story/skills/story-long-write/references/long-chapter-quality.md +6 -15
  162. package/lib/oh-story/skills/story-long-write/references/long-format.md +2 -0
  163. package/lib/oh-story/skills/story-long-write/references/outline-structure-theory.md +2 -0
  164. package/lib/oh-story/skills/story-long-write/references/project-files.md +110 -0
  165. package/lib/oh-story/skills/story-long-write/references/reader-contract-and-progression.md +12 -4
  166. package/lib/oh-story/skills/story-long-write/references/reference-index.md +86 -0
  167. package/lib/oh-story/skills/story-long-write/references/style-combat-face.md +1 -1
  168. package/lib/oh-story/skills/story-long-write/references/style-craft.md +9 -29
  169. package/lib/oh-story/skills/story-long-write/references/style-genre-modules.md +1 -1
  170. package/lib/oh-story/skills/story-long-write/references/style-resolution.md +27 -0
  171. package/lib/oh-story/skills/story-long-write/references/tracking-initialization.md +31 -0
  172. package/lib/oh-story/skills/story-long-write/references/tracking-transaction.md +9 -34
  173. package/lib/oh-story/skills/story-long-write/references/workflow-chapter.md +88 -118
  174. package/lib/oh-story/skills/story-long-write/references/workflow-daily.md +55 -119
  175. package/lib/oh-story/skills/story-long-write/references/workflow-revision.md +15 -11
  176. package/lib/oh-story/skills/story-long-write/references/workflow-setup.md +73 -54
  177. package/lib/oh-story/skills/story-long-write/references/writer-prompt-fallback.md +22 -0
  178. package/lib/oh-story/skills/story-long-write/references/writing-craft.md +63 -4
  179. package/lib/oh-story/skills/story-long-write/scripts/author_memory_commit.py +934 -170
  180. package/lib/oh-story/skills/story-long-write/scripts/build_writer_prompt.py +531 -0
  181. package/lib/oh-story/skills/story-long-write/scripts/check-ai-patterns.js +6 -1
  182. package/lib/oh-story/skills/story-long-write/scripts/check-degeneration.js +39 -20
  183. package/lib/oh-story/skills/story-long-write/scripts/check-outline-contract.js +197 -15
  184. package/lib/oh-story/skills/story-long-write/scripts/check-outline-copy.js +90 -23
  185. package/lib/oh-story/skills/story-long-write/scripts/normalize-punctuation.js +10 -5
  186. package/lib/oh-story/skills/story-long-write/scripts/outline_view.py +285 -0
  187. package/lib/oh-story/skills/story-long-write/scripts/storyctl.py +58 -0
  188. package/lib/oh-story/skills/story-long-write/scripts/style-whitelist.js +39 -0
  189. package/lib/oh-story/skills/story-long-write/scripts/tracking_commit.py +210 -2
  190. package/lib/oh-story/skills/story-long-write/scripts/wordcount_core.py +3 -0
  191. package/lib/oh-story/skills/story-review/SKILL.md +80 -87
  192. package/lib/oh-story/skills/story-review/references/anti-ai-writing.md +29 -56
  193. package/lib/oh-story/skills/story-review/references/author-memory.md +61 -29
  194. package/lib/oh-story/skills/story-review/references/banned-words.md +3 -1
  195. package/lib/oh-story/skills/story-review/references/dialogue-mastery.md +10 -4
  196. package/lib/oh-story/skills/story-review/references/review-quality.md +6 -12
  197. package/lib/oh-story/skills/story-review/references/style-resolution.md +27 -0
  198. package/lib/oh-story/skills/story-review/references/tracking-initialization.md +31 -0
  199. package/lib/oh-story/skills/story-review/references/tracking-transaction.md +9 -34
  200. package/lib/oh-story/skills/story-review/scripts/author_memory_commit.py +934 -170
  201. package/lib/oh-story/skills/story-review/scripts/check-ai-patterns.js +6 -1
  202. package/lib/oh-story/skills/story-review/scripts/check-degeneration.js +39 -20
  203. package/lib/oh-story/skills/story-review/scripts/normalize-punctuation.js +10 -5
  204. package/lib/oh-story/skills/story-review/scripts/style-whitelist.js +39 -0
  205. package/lib/oh-story/skills/story-review/scripts/tracking_commit.py +210 -2
  206. package/lib/oh-story/skills/story-review/scripts/wordcount_core.py +3 -0
  207. package/lib/oh-story/skills/story-setup/SKILL.md +58 -43
  208. package/lib/oh-story/skills/story-setup/references/agent-references/anti-ai-writing.md +29 -56
  209. package/lib/oh-story/skills/story-setup/references/agent-references/banned-words.md +3 -1
  210. package/lib/oh-story/skills/story-setup/references/agent-references/deslop-gates.md +154 -0
  211. package/lib/oh-story/skills/story-setup/references/agent-references/dialogue-mastery.md +10 -4
  212. package/lib/oh-story/skills/story-setup/references/agent-references/format-and-structure.md +2 -2
  213. package/lib/oh-story/skills/story-setup/references/agent-references/long-emotional-methods.md +2 -2
  214. package/lib/oh-story/skills/story-setup/references/agent-references/long-quality.md +1 -1
  215. package/lib/oh-story/skills/story-setup/references/agent-references/short-genre-formulas.md +1 -1
  216. package/lib/oh-story/skills/story-setup/references/agent-references/style-combat-face.md +1 -1
  217. package/lib/oh-story/skills/story-setup/references/agent-references/style-genre-modules.md +1 -1
  218. package/lib/oh-story/skills/story-setup/references/agent-references/style-resolution.md +27 -0
  219. package/lib/oh-story/skills/story-setup/references/agent-references/writing-craft.md +63 -4
  220. package/lib/oh-story/skills/story-setup/references/diagnostics.md +38 -0
  221. package/lib/oh-story/skills/story-short-analyze/SKILL.md +22 -3
  222. package/lib/oh-story/skills/story-short-analyze/references/analysis-writing-techniques.md +1 -1
  223. package/lib/oh-story/skills/story-short-analyze/references/material-decomposition.md +5 -1
  224. package/lib/oh-story/skills/story-short-analyze/references/source-story-quality.md +2 -2
  225. package/lib/oh-story/skills/story-short-scan/SKILL.md +5 -1
  226. package/lib/oh-story/skills/story-short-write/SKILL.md +15 -324
  227. package/lib/oh-story/skills/story-short-write/references/author-memory.md +61 -29
  228. package/lib/oh-story/skills/story-short-write/references/banned-words.md +3 -1
  229. package/lib/oh-story/skills/story-short-write/references/benchmark-recall.md +60 -0
  230. package/lib/oh-story/skills/story-short-write/references/dialogue-mastery.md +10 -4
  231. package/lib/oh-story/skills/story-short-write/references/genre-styles//344/270/226/346/203/205/346/211/223/350/204/270.md +2 -2
  232. package/lib/oh-story/skills/story-short-write/references/genre-styles//345/217/214/347/224/267/344/270/273.md +1 -1
  233. 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
  234. package/lib/oh-story/skills/story-short-write/references/genre-styles//345/256/205/346/226/227/345/256/253/346/226/227.md +3 -3
  235. 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
  236. package/lib/oh-story/skills/story-short-write/references/genre-styles//346/202/254/347/226/221.md +5 -5
  237. package/lib/oh-story/skills/story-short-write/references/genre-styles//346/260/221/344/277/227/346/200/252/350/260/210.md +4 -4
  238. package/lib/oh-story/skills/story-short-write/references/genre-styles//347/224/234/345/256/240.md +5 -5
  239. 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
  240. package/lib/oh-story/skills/story-short-write/references/genre-writing-formulas.md +1 -1
  241. package/lib/oh-story/skills/story-short-write/references/genre-writing-techniques.md +1 -1
  242. package/lib/oh-story/skills/story-short-write/references/reference-index.md +55 -0
  243. package/lib/oh-story/skills/story-short-write/references/short-craft.md +12 -14
  244. package/lib/oh-story/skills/story-short-write/references/short-deslop.md +10 -10
  245. package/lib/oh-story/skills/story-short-write/references/short-format.md +3 -1
  246. package/lib/oh-story/skills/story-short-write/references/short-prose-quality.md +2 -2
  247. package/lib/oh-story/skills/story-short-write/references/style-resolution.md +27 -0
  248. package/lib/oh-story/skills/story-short-write/references/workflow-design.md +78 -0
  249. package/lib/oh-story/skills/story-short-write/references/workflow-draft.md +126 -0
  250. package/lib/oh-story/skills/story-short-write/references/workflow-revision.md +32 -0
  251. package/lib/oh-story/skills/story-short-write/references/writing-workflow.md +5 -5
  252. package/lib/oh-story/skills/story-short-write/scripts/author_memory_commit.py +934 -170
  253. package/lib/oh-story/skills/story-short-write/scripts/check-ai-patterns.js +6 -1
  254. package/lib/oh-story/skills/story-short-write/scripts/check-degeneration.js +39 -20
  255. package/lib/oh-story/skills/story-short-write/scripts/check-delivery-contract.js +34 -5
  256. package/lib/oh-story/skills/story-short-write/scripts/check-outline-copy.js +90 -23
  257. package/lib/oh-story/skills/story-short-write/scripts/normalize-punctuation.js +10 -5
  258. package/lib/oh-story/skills/story-short-write/scripts/style-whitelist.js +39 -0
  259. package/lib/types/client/drama-production-view.d.ts.map +1 -1
  260. package/lib/types/client/file-activity.d.ts +19 -1
  261. package/lib/types/client/file-activity.d.ts.map +1 -1
  262. package/lib/types/client/index.d.ts.map +1 -1
  263. package/lib/types/client/production-prompts.d.ts +7 -0
  264. package/lib/types/client/production-prompts.d.ts.map +1 -1
  265. package/lib/types/client/production-runtime.d.ts +33 -0
  266. package/lib/types/client/production-runtime.d.ts.map +1 -1
  267. package/lib/types/drama-adapters.d.ts +5 -3
  268. package/lib/types/drama-adapters.d.ts.map +1 -1
  269. package/lib/types/native-hooks.d.ts +52 -0
  270. package/lib/types/native-hooks.d.ts.map +1 -1
  271. package/lib/types/role-identity.d.ts +17 -0
  272. package/lib/types/role-identity.d.ts.map +1 -0
  273. package/lib/types/role-tool.d.ts.map +1 -1
  274. package/lib/types/skill-provider.d.ts.map +1 -1
  275. package/lib/video-recap/CHANGELOG.md +31 -1
  276. package/lib/video-recap/manifest.json +162 -162
  277. package/lib/video-recap/skills/video-assemble/scripts/artifacts.py +4 -9
  278. package/lib/video-recap/skills/video-assemble/scripts/assemble.py +47 -60
  279. package/lib/video-recap/skills/video-assemble/scripts/assembly_contract.py +77 -115
  280. package/lib/video-recap/skills/video-assemble/scripts/assembly_settings.py +41 -40
  281. package/lib/video-recap/skills/video-assemble/scripts/audio_automation.py +22 -32
  282. package/lib/video-recap/skills/video-assemble/scripts/audio_mix.py +102 -192
  283. package/lib/video-recap/skills/video-assemble/scripts/jianying_builders.py +14 -35
  284. package/lib/video-recap/skills/video-assemble/scripts/jianying_model.py +14 -12
  285. package/lib/video-recap/skills/video-assemble/scripts/jianying_optional.py +8 -9
  286. package/lib/video-recap/skills/video-assemble/scripts/jianying_schema.py +3 -14
  287. package/lib/video-recap/skills/video-assemble/scripts/jianying_timeline_contract.py +23 -12
  288. package/lib/video-recap/skills/video-assemble/scripts/jianying_tracks.py +1 -4
  289. package/lib/video-recap/skills/video-assemble/scripts/jianying_writer.py +24 -25
  290. package/lib/video-recap/skills/video-assemble/scripts/lib.py +31 -85
  291. package/lib/video-recap/skills/video-assemble/scripts/media.py +100 -144
  292. package/lib/video-recap/skills/video-assemble/scripts/narration_audio.py +101 -195
  293. package/lib/video-recap/skills/video-assemble/scripts/render_preflight.py +10 -21
  294. package/lib/video-recap/skills/video-assemble/scripts/source_subtitles.py +90 -169
  295. package/lib/video-recap/skills/video-assemble/scripts/subtitle_core.py +69 -122
  296. package/lib/video-recap/skills/video-assemble/scripts/subtitle_render.py +10 -17
  297. package/lib/video-recap/skills/video-assemble/scripts/timeline.py +33 -48
  298. package/lib/video-recap/skills/video-assemble/scripts/timeline_emit.py +14 -20
  299. package/lib/video-recap/skills/video-assemble/scripts/visual_render.py +135 -213
  300. package/lib/video-recap/skills/video-cut/scripts/cut_cli.py +49 -57
  301. package/lib/video-recap/skills/video-cut/scripts/cut_contract.py +38 -74
  302. package/lib/video-recap/skills/video-cut/scripts/cut_render.py +46 -95
  303. package/lib/video-recap/skills/video-cut/scripts/lib.py +23 -25
  304. package/lib/video-recap/skills/video-cut/scripts/media_geometry.py +70 -173
  305. package/lib/video-recap/skills/video-cut/scripts/narration_mapping.py +28 -53
  306. package/lib/video-recap/skills/video-cut/scripts/sentence_boundaries.py +162 -322
  307. package/lib/video-recap/skills/video-recap/references/timeline-and-jianying.md +6 -7
  308. package/lib/video-recap/skills/video-recap/scripts/doctor.py +104 -124
  309. package/lib/video-recap/skills/video-recap/scripts/final_qc.py +255 -412
  310. package/lib/video-recap/skills/video-recap/scripts/lib.py +30 -52
  311. package/lib/video-recap/skills/video-recap/scripts/materials.py +97 -120
  312. package/lib/video-recap/skills/video-recap/scripts/mimo_qc_client.py +7 -12
  313. package/lib/video-recap/skills/video-recap/scripts/mimo_qc_evidence.py +46 -97
  314. package/lib/video-recap/skills/video-recap/scripts/mimo_qc_observations.py +18 -36
  315. package/lib/video-recap/skills/video-recap/scripts/mimo_qc_payload.py +29 -47
  316. package/lib/video-recap/skills/video-recap/scripts/mimo_qc_report.py +43 -76
  317. package/lib/video-recap/skills/video-recap/scripts/mimo_qc_runner.py +2 -1
  318. package/lib/video-recap/skills/video-recap/scripts/qc_contract.py +2 -1
  319. package/lib/video-recap/skills/video-recap/scripts/recap_cli.py +2 -2
  320. package/lib/video-recap/skills/video-recap/scripts/recap_inspect.py +129 -145
  321. package/lib/video-recap/skills/video-recap/scripts/recap_review.py +27 -20
  322. package/lib/video-recap/skills/video-recap/scripts/recap_runner.py +20 -31
  323. package/lib/video-recap/skills/video-recap/scripts/recap_runtime.py +31 -106
  324. package/lib/video-recap/skills/video-recap/scripts/recap_stage_qc.py +43 -113
  325. package/lib/video-recap/skills/video-recap/scripts/recap_timeline.py +196 -377
  326. package/lib/video-recap/skills/video-script/scripts/agent_brief.py +1 -1
  327. package/lib/video-recap/skills/video-script/scripts/agent_text.py +63 -172
  328. package/lib/video-recap/skills/video-script/scripts/brief_context.py +80 -135
  329. package/lib/video-recap/skills/video-script/scripts/brief_inputs.py +125 -167
  330. package/lib/video-recap/skills/video-script/scripts/brief_timeline.py +93 -208
  331. package/lib/video-recap/skills/video-script/scripts/deslop_qc.py +20 -46
  332. package/lib/video-recap/skills/video-script/scripts/lib.py +30 -26
  333. package/lib/video-recap/skills/video-script/scripts/narration_lint.py +145 -140
  334. package/lib/video-recap/skills/video-script/scripts/review_response.py +12 -42
  335. package/lib/video-recap/skills/video-script/scripts/review_runner.py +0 -6
  336. package/lib/video-recap/skills/video-script/scripts/speech_ownership.py +39 -100
  337. package/lib/video-recap/skills/video-script/scripts/timeline_fusion.py +33 -124
  338. package/lib/video-recap/skills/video-understanding/scripts/agent_brief.py +1 -1
  339. package/lib/video-recap/skills/video-understanding/scripts/agent_text.py +63 -172
  340. package/lib/video-recap/skills/video-understanding/scripts/asr.py +1 -2
  341. package/lib/video-recap/skills/video-understanding/scripts/brief_context.py +80 -135
  342. package/lib/video-recap/skills/video-understanding/scripts/brief_inputs.py +125 -167
  343. package/lib/video-recap/skills/video-understanding/scripts/brief_timeline.py +93 -208
  344. package/lib/video-recap/skills/video-understanding/scripts/consolidate.py +1 -1
  345. package/lib/video-recap/skills/video-understanding/scripts/deslop_qc.py +20 -46
  346. package/lib/video-recap/skills/video-understanding/scripts/lib.py +31 -26
  347. package/lib/video-recap/skills/video-understanding/scripts/narration_lint.py +145 -140
  348. package/lib/video-recap/skills/video-understanding/scripts/speech_ownership.py +39 -100
  349. package/lib/video-recap/skills/video-understanding/scripts/timeline_fusion.py +33 -124
  350. package/lib/video-recap/skills/video-understanding/scripts/vlm.py +1 -4
  351. package/lib/video-recap/skills/video-voiceover/scripts/dub.py +7 -13
  352. package/lib/video-recap/skills/video-voiceover/scripts/fish_audio.py +12 -30
  353. package/lib/video-recap/skills/video-voiceover/scripts/lib.py +98 -131
  354. package/lib/video-recap/skills/video-voiceover/scripts/tts_audio.py +17 -28
  355. package/lib/video-recap/skills/video-voiceover/scripts/voiceover.py +151 -240
  356. package/package.json +45 -45
  357. package/lib/novel-to-game/skills/game-world-design/references/dialogue-design-method.md +0 -59
  358. package/lib/novel-to-game/skills/game-world-design/references/game-writing-craft.md +0 -53
  359. package/lib/novel-to-game/skills/novel-to-game/references/intake-benchmark-reference.md +0 -42
  360. package/lib/oh-story/skills/story-long-write/references/state-tracking.md +0 -108
package/lib/client.js CHANGED
@@ -174,12 +174,39 @@ function visitRunning(blocks, visit2) {
174
174
  for (let block of blocks)
175
175
  "kind" in block || visit2(block), visitRunning(block.subCalls, visit2);
176
176
  }
177
- function fileMutations(runningCalls, partial = null) {
177
+ function undispatchedCalls(chat) {
178
+ let turnNumber = chat.timeline.turnOrder.at(-1), turn = turnNumber === void 0 ? void 0 : chat.timeline.turns.get(turnNumber);
179
+ if (turn === void 0 || turn.status === "closed") return [];
180
+ let calls = [];
181
+ for (let step of turn.steps) {
182
+ let assistant = step.data.get("assistant-step");
183
+ if (assistant?.status === "settled")
184
+ for (let block of assistant.blocks)
185
+ block.kind === "tool-call" && calls.push({ callId: block.callId, name: block.name, argsRaw: block.argsRaw });
186
+ }
187
+ if (calls.length === 0) return calls;
188
+ let settled = /* @__PURE__ */ new Set();
189
+ for (let node of chat.legacy.nodes) {
190
+ let value = node;
191
+ value.kind === "tool-result" && typeof value.callId == "string" && settled.add(value.callId);
192
+ }
193
+ return calls.filter((call) => !settled.has(call.callId));
194
+ }
195
+ function sameUndispatchedCalls(left, right) {
196
+ return left.length === right.length && left.every((call, index) => call.callId === right[index]?.callId && call.argsRaw === right[index].argsRaw);
197
+ }
198
+ function fileMutations(runningCalls, partial = null, undispatched = []) {
178
199
  let values = [];
179
200
  visitRunning(runningCalls, (call) => {
201
+ if (call.phase !== "start") return;
180
202
  let mutation = mutationFromArgs(call.name, call.callId, call.argsRaw, "running");
181
203
  mutation !== void 0 && values.push(mutation);
182
204
  });
205
+ for (let call of undispatched) {
206
+ if (values.some((candidate) => candidate.callId === call.callId)) continue;
207
+ let mutation = mutationFromArgs(call.name, call.callId, call.argsRaw, "running");
208
+ mutation !== void 0 && values.push(mutation);
209
+ }
183
210
  for (let block of partial?.blocks ?? []) {
184
211
  if (block.kind !== "tool-call") continue;
185
212
  let value = mutationFromArgs(block.name, block.callId, block.argsRaw, "streaming");
@@ -199,14 +226,27 @@ function settledMutationSignals(block) {
199
226
  let mutation = mutationFromArgs(block.call.name, block.callId, block.call.argsRaw, "running");
200
227
  return mutation?.path === void 0 ? nested : [`${block.callId}\0${mutation.path}`, ...nested];
201
228
  }
202
- function latestSettledMutation(chat) {
229
+ function latestSettledWrite(chat) {
203
230
  for (let key of chat.order.toReversed()) {
204
231
  let node = chat.nodes.get(key);
205
232
  if (node?.kind !== "tool-call") continue;
206
233
  let root = node.data.root, signal = root === void 0 ? void 0 : settledMutationSignals(root).at(-1);
207
- if (signal !== void 0) return signal;
234
+ if (signal === void 0) continue;
235
+ let location = node.location;
236
+ return { signal, turn: location.kind === "turn" || location.kind === "step" ? location.turn.turn : void 0 };
208
237
  }
209
238
  }
239
+ function latestSettledMutation(chat) {
240
+ return latestSettledWrite(chat)?.signal;
241
+ }
242
+ function latestSettledMutationTurn(chat) {
243
+ return latestSettledWrite(chat)?.turn;
244
+ }
245
+ function openTurn(chat) {
246
+ let turnNumber = chat.timeline.turnOrder.at(-1);
247
+ if (turnNumber !== void 0)
248
+ return chat.timeline.turns.get(turnNumber)?.status === "open" ? turnNumber : void 0;
249
+ }
210
250
  function creativeRelativePath(path, cwd) {
211
251
  if (path === void 0 || path === "") return;
212
252
  let normalized = path.replaceAll("\\", "/"), root = cwd?.replaceAll("\\", "/").replace(/\/$/u, ""), insideRoot = root !== void 0 && normalized.startsWith(`${root}/`);
@@ -322,18 +362,18 @@ var import_jsx_runtime = require("react/jsx-runtime"), TITLE_KEYS = [
322
362
  function objectRecord(value) {
323
363
  return typeof value == "object" && value !== null && !Array.isArray(value) ? value : void 0;
324
364
  }
325
- function stringField(record, keys) {
365
+ function stringField(record2, keys) {
326
366
  for (let key of keys) {
327
- let value = record[key];
367
+ let value = record2[key];
328
368
  if (typeof value == "string" && value.trim() !== "") return value;
329
369
  }
330
370
  }
331
371
  function metadata(value, line) {
332
- let record = objectRecord(value);
333
- if (record === void 0) return { title: typeof value == "string" ? value : JSON.stringify(value) ?? `\u7B2C ${String(line)} \u884C` };
334
- let type = stringField(record, ["record_type", "type", "kind"]), acceptance = objectRecord(record.creator_acceptance), status = stringField(record, ["status"]) ?? (acceptance === void 0 ? void 0 : stringField(acceptance, ["status"]));
372
+ let record2 = objectRecord(value);
373
+ if (record2 === void 0) return { title: typeof value == "string" ? value : JSON.stringify(value) ?? `\u7B2C ${String(line)} \u884C` };
374
+ let type = stringField(record2, ["record_type", "type", "kind"]), acceptance = objectRecord(record2.creator_acceptance), status = stringField(record2, ["status"]) ?? (acceptance === void 0 ? void 0 : stringField(acceptance, ["status"]));
335
375
  return {
336
- title: stringField(record, TITLE_KEYS) ?? `\u8BB0\u5F55 ${String(line)}`,
376
+ title: stringField(record2, TITLE_KEYS) ?? `\u8BB0\u5F55 ${String(line)}`,
337
377
  ...type === void 0 ? {} : { type },
338
378
  ...status === void 0 ? {} : { status }
339
379
  };
@@ -362,7 +402,7 @@ var PREVIEW_LIMIT = 200;
362
402
  function JsonlPreview({ content, label }) {
363
403
  let records = parseJsonl(content);
364
404
  if (records.length === 0) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "oh-story-markdown-empty", children: "\u8FD9\u4E2A JSONL \u6587\u4EF6\u8FD8\u662F\u7A7A\u7684\u3002" });
365
- let valid = records.filter((record) => record.error === void 0).length, errors = records.length - valid, visible = records.slice(0, PREVIEW_LIMIT);
405
+ let valid = records.filter((record2) => record2.error === void 0).length, errors = records.length - valid, visible = records.slice(0, PREVIEW_LIMIT);
366
406
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { className: "oh-story-jsonl", "aria-label": `${label} \u7ED3\u6784\u5316\u9884\u89C8`, children: [
367
407
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("header", { className: "oh-story-jsonl-summary", children: [
368
408
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { children: errors === 0 ? `${String(valid)} \u6761\u8BB0\u5F55` : `${String(valid)} \u6761\u6709\u6548\u8BB0\u5F55` }),
@@ -376,23 +416,23 @@ function JsonlPreview({ content, label }) {
376
416
  " \u6761"
377
417
  ] })
378
418
  ] }),
379
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "oh-story-jsonl-records", children: visible.map((record) => record.error === void 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("details", { open: records.length <= 2, children: [
419
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "oh-story-jsonl-records", children: visible.map((record2) => record2.error === void 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("details", { open: records.length <= 2, children: [
380
420
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("summary", { children: [
381
421
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { children: [
382
422
  "\u7B2C ",
383
- String(record.line),
423
+ String(record2.line),
384
424
  " \u884C"
385
425
  ] }),
386
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { children: record.title }),
387
- record.type !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("code", { children: record.type }),
388
- record.status !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("em", { children: record.status })
426
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { children: record2.title }),
427
+ record2.type !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("code", { children: record2.type }),
428
+ record2.status !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("em", { children: record2.status })
389
429
  ] }),
390
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("pre", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("code", { children: JSON.stringify(record.value, null, 2) }) })
391
- ] }, record.line) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "oh-story-jsonl-error", role: "alert", children: [
392
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { children: record.title }),
393
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: record.error }),
394
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("pre", { children: record.raw })
395
- ] }, record.line)) })
430
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("pre", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("code", { children: JSON.stringify(record2.value, null, 2) }) })
431
+ ] }, record2.line) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "oh-story-jsonl-error", role: "alert", children: [
432
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { children: record2.title }),
433
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: record2.error }),
434
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("pre", { children: record2.raw })
435
+ ] }, record2.line)) })
396
436
  ] });
397
437
  }
398
438
 
@@ -774,7 +814,10 @@ function endpoint(path, sessionId, file) {
774
814
  }
775
815
 
776
816
  // src/client/production-prompts.ts
777
- var authorityBoundary = "\u53EA\u4F7F\u7528\u5F53\u524D DSH Preset \u53EF\u89C1\u7684\u5DE5\u5177\uFF1B\u6240\u6709\u6587\u4EF6\u3001\u7F51\u7EDC\u3001\u751F\u6210\u548C\u547D\u4EE4\u64CD\u4F5C\u7EE7\u7EED\u9075\u5B88 DSH \u6743\u9650\u4E0E\u5BA1\u6279\u3002";
817
+ var authorityBoundary = "\u53EA\u4F7F\u7528\u5F53\u524D DSH Preset \u53EF\u89C1\u7684\u5DE5\u5177\uFF1B\u6240\u6709\u6587\u4EF6\u3001\u7F51\u7EDC\u3001\u751F\u6210\u548C\u547D\u4EE4\u64CD\u4F5C\u7EE7\u7EED\u9075\u5B88 DSH \u6743\u9650\u4E0E\u5BA1\u6279\u3002", referenceRules = "\u53C2\u8003\u56FE\u4EE5\u6765\u6E90\u6761\u76EE\u81EA\u5DF1\u7684\u58F0\u660E\u4E3A\u51C6\uFF08IMG-* \u7684\u300C\u53C2\u8003\u300D\uFF0CSHOT-*\uFF0FMOTION-* \u7684\u300C\u8F93\u5165\u53C2\u8003\u56FE\u300D\uFF09\uFF1Areference_bindings \u5FC5\u987B\u4E0E\u8BE5\u6761\u76EE\u9010\u69FD\u4E00\u81F4\uFF0C\u5DE5\u4F5C\u53F0\u5217\u51FA\u7684\u8865\u5145\u53C2\u8003\u53EA\u4F5C\u6838\u5BF9\uFF0C\u6761\u76EE\u91CC\u6CA1\u6709\u58F0\u660E\u7684\u4E0D\u8981\u76F4\u63A5\u52A0\u8FDB job\uFF0C\u786E\u9700\u4F7F\u7528\u65F6\u5148\u8BF7\u62E5\u6709\u8BE5\u6761\u76EE\u7684\u9636\u6BB5\u4FEE\u8BA2\u6587\u6863\u3002\u8D77\u59CB\u5E27\u4E0E\u7ED3\u675F\u5E27\u7684\u89D2\u8272\u53EA\u53D6\u81EA\u6765\u6E90\u6761\u76EE\u81EA\u5DF1\u300C\u8F93\u5165\u53C2\u8003\u56FE\u300D\u5404\u69FD\u4F4D\u8BB0\u5F55\u7684\u7528\u9014\uFF08\u8D77\u59CB\u5E27\uFF0F\u7ED3\u675F\u5E27\uFF09\uFF1ASHOT-* \u770B\u300A\u5206\u955C.md\u300B\uFF0CMOTION-* \u770B\u300A\u89C6\u9891\u63D0\u793A\u8BCD.md\u300B\uFF1B\u518D\u7531\u76EE\u6807\u6A21\u578B\u65B9\u8A00\u7FFB\u6210 adapter \u7684 role\uFF0C\u4E0D\u6309\u6587\u4EF6\u540D\u6216\u5DE5\u4F5C\u53F0\u6E05\u5355\u63A8\u65AD\u3002\u76EE\u6807\u65B9\u8A00\u7528 first_frame\uFF0Flast_frame \u4F4D\u7F6E\u627F\u63A5\u8FD9\u7EC4\u8F93\u5165\u65F6\uFF0C\u7ED3\u675F\u5E27\u53EA\u8FDB last_frame\uFF0C\u7EDD\u4E0D\u964D\u7EA7\u6210\u666E\u901A\u53C2\u8003\u56FE\uFF1B\u65B9\u8A00\u8981\u6C42\u6574\u7EC4\u8D70\u591A\u69FD\u53C2\u8003\u65F6\uFF08\u5982 MiniMax H3 \u7684 full-reference\uFF1A\u9996\u5C3E\u5E27\u8F93\u5165\u4E0E\u53C2\u8003\u8F93\u5165\u4E92\u65A5\uFF0C\u8D77\u59CB\u5E27\u3001\u7ED3\u675F\u5E27\u90FD\u968F\u6574\u7EC4\u4EE5 reference_image \u9001\u5165\uFF09\uFF0C\u6309\u65B9\u8A00\u7FFB\u8BD1\uFF0C\u5E76\u5728\u9884\u89C8\u91CC\u5199\u660E\u7ED3\u675F\u5E27\u5C06\u4F5C\u4E3A\u53C2\u8003\u56FE\u9001\u5165\uFF0C\u6216\u5148\u8BF7\u5206\u955C owner \u53D6\u820D\u3002", shotStartFrameNote = "\u5206\u955C.md \u7684 SHOT-* \u53EA\u4EA7\u51FA\u8D77\u59CB\u5E27\uFF1B\u8981\u4EA7\u51FA\u7ED3\u675F\u5E27\uFF0C\u5148\u7531\u56FE\u7247\u63D0\u793A\u8BCD\u9636\u6BB5\u5EFA\u7ACB\u72EC\u7ACB\u7684 IMG-* \u6761\u76EE\u518D\u6295\u4EA7\u3002";
818
+ function referenceParagraph(kind) {
819
+ return kind === "image" ? `${referenceRules}${shotStartFrameNote}` : referenceRules;
820
+ }
778
821
  function nativeProductionPrompt(production, job, references) {
779
822
  let referenceText = references.length === 0 ? "\u65E0" : references.map((item) => `${item.targetId}: ${item.path ?? item.url}`).join(`
780
823
  `);
@@ -786,7 +829,7 @@ function nativeProductionPrompt(production, job, references) {
786
829
  - \u5EFA\u8BAE adapter \u5951\u7EA6\uFF1A${job.kind === "image" ? "gpt-image-2" : "seedance"}\uFF08\u5B9E\u9645\u914D\u7F6E\u4E0E\u6A21\u578B\u4EE5\u5F53\u524D DSH \u8FD0\u884C\u73AF\u5883\u4E3A\u51C6\uFF09
787
830
  - \u6295\u4EA7\u5BF9\u8C61\uFF1A${job.targetId}
788
831
  - \u521B\u4F5C\u6587\u6863\u76EE\u5F55\uFF1A${production.episodeDirectory}
789
- - \u53C2\u8003\u7D20\u6750\uFF1A
832
+ - \u5DE5\u4F5C\u53F0\u5217\u51FA\u7684\u8865\u5145\u53C2\u8003\uFF08\u4E0D\u662F\u751F\u4EA7\u8F93\u5165\u5FEB\u7167\uFF09\uFF1A
790
833
  ${referenceText}
791
834
  - \u8F93\u51FA\u76EE\u5F55\uFF1A${production.episodeDirectory}/\u5236\u4F5C\u6210\u679C/${job.targetId}
792
835
  - \u8F93\u51FA\u6587\u4EF6\u540D\u5FC5\u987B\u540C\u65F6\u5305\u542B\u6295\u4EA7\u5BF9\u8C61 ID \u4E0E\u4EFB\u52A1 ID ${job.id}\uFF0C\u4EE5\u4FBF DSH \u5DE5\u4F5C\u53F0\u5173\u8054\u7248\u672C\u3002
@@ -794,6 +837,8 @@ ${referenceText}
794
837
  \u5F85\u9884\u68C0\u63D0\u793A\u8BCD\uFF1A
795
838
  ${job.prompt}
796
839
 
840
+ ${referenceParagraph(job.kind)}
841
+
797
842
  \u6309 short-drama-produce \u7684\u786C\u95F8\u95E8\u5EFA\u7ACB\u4E34\u65F6 job \u5E76\u6267\u884C prepare\uFF0C\u5728 Chat \u4E2D\u5B8C\u6574\u5C55\u793A adapter\u3001\u6A21\u578B/profile\u3001\u6570\u91CF\u3001\u53C2\u6570\u3001references\u3001outputs \u4E0E overwrite\u3002\u6B64\u6309\u94AE\u53EA\u8868\u8FBE\u201C\u51C6\u5907\u9884\u89C8\u201D\uFF0C\u4E0D\u6784\u6210\u770B\u5230\u9884\u89C8\u540E\u7684\u751F\u4EA7\u786E\u8BA4\uFF1B\u4E0D\u5F97 confirm \u6216 run\u3002\u7528\u6237\u5728\u540E\u7EED\u6D88\u606F\u660E\u786E\u786E\u8BA4\u8FD9\u4EFD\u9884\u89C8\u540E\uFF0C\u624D\u53EF\u8C03\u7528 oh_story_production track_job \u767B\u8BB0\u540C\u4E00\u4E2A\u4EFB\u52A1 ID\uFF0C\u5E76\u8FD0\u884C Provider\u3002${authorityBoundary}`;
798
843
  }
799
844
  function nativeBatchPrompt(production, job, candidates) {
@@ -812,23 +857,50 @@ ${item.prompt}`).join(`
812
857
 
813
858
  `)}
814
859
 
860
+ ${referenceParagraph(job.kind)}
861
+
815
862
  \u628A\u6570\u91CF\u3001\u9010\u9879\u8F93\u51FA\u548C\u6210\u672C\u8FB9\u754C\u5B8C\u6574\u5C55\u793A\u7ED9\u521B\u4F5C\u8005\u3002\u6B64\u6309\u94AE\u53EA\u8868\u8FBE\u201C\u51C6\u5907\u9884\u89C8\u201D\uFF0C\u4E0D\u6784\u6210\u770B\u5230\u9884\u89C8\u540E\u7684\u751F\u4EA7\u786E\u8BA4\uFF1B\u4E0D\u5F97 confirm \u6216 run\u3002\u7528\u6237\u5728\u540E\u7EED\u6D88\u606F\u660E\u786E\u786E\u8BA4\u8FD9\u4EFD\u9884\u89C8\u540E\uFF0C\u624D\u53EF\u8C03\u7528 oh_story_production track_job \u767B\u8BB0\u540C\u4E00\u4E2A\u6279\u6B21\u4EFB\u52A1 ID\uFF0C\u5E76\u8FD0\u884C Provider\u3002${authorityBoundary}`;
816
863
  }
817
864
  function nativeCompositionPrompt(production, job, orderedPaths) {
818
- return `/short-drama-produce
865
+ return `/short-drama-edit
819
866
 
820
- \u6267\u884C\u521B\u4F5C\u8005\u5DF2\u660E\u786E\u786E\u8BA4\u7684\u6210\u7247\u5408\u6210\u4EFB\u52A1\u3002
867
+ \u6267\u884C\u521B\u4F5C\u8005\u5DF2\u660E\u786E\u786E\u8BA4\u7684\u6210\u7247\u88C5\u914D\u4EFB\u52A1\u3002
821
868
  - \u4EFB\u52A1 ID\uFF1A${job.id}
822
869
  - \u5267\u96C6\uFF1A${production.episodeDirectory}
823
- - \u6309\u4EE5\u4E0B\u987A\u5E8F\u5408\u6210\uFF0C\u4E0D\u5F97\u81EA\u884C\u6362\u5E8F\uFF1A
870
+ - \u521B\u4F5C\u8005\u5728\u6210\u7247\u89C6\u56FE\u6392\u5B9A\u7684\u955C\u5E8F\uFF0C\u4E0D\u5F97\u81EA\u884C\u6362\u5E8F\uFF1A
824
871
  ${orderedPaths.map((path, index) => `${String(index + 1)}. ${path}`).join(`
825
872
  `)}
826
- - \u8F93\u51FA\uFF1A${production.episodeDirectory}/\u5236\u4F5C\u6210\u679C/\u6210\u7247-${job.id}.mp4
873
+ - \u526A\u8F91\u5355\uFF1A${production.episodeDirectory}/\u526A\u8F91\u5355.md
874
+ - \u8F93\u51FA\uFF1A${production.episodeDirectory}/\u5236\u4F5C\u6210\u679C/\u6210\u7247/
875
+
876
+ \u5148\u5199\u526A\u8F91\u5355\u518D\u6E32\u67D3\u3002\u9010\u6BB5\u770B\u5B8C\u7D20\u6750\u540E\u5199\u4E0B\u771F\u5B9E\u7684\u5165\u51FA\u70B9\u3001\u53D6\u820D\u7406\u7531\u3001\u58F0\u97F3\u5904\u7406\u4E0E\u5B57\u5E55\uFF0C\u4E0D\u8981\u6309\u955C\u5E8F\u51ED\u7A7A\u586B\u65F6\u95F4\uFF1B\u5B57\u5E55\u9010\u5B57\u53D6\u81EA\u5267\u672C.md\u3002\u526A\u8F91\u5355\u8BB0\u5F55\u7D20\u6750\u53D6\u820D\u3001\u5165\u51FA\u70B9\u3001\u540E\u671F\u5904\u7406\u4E0E\u4EA4\u4ED8\u89C4\u683C\uFF0C\u4E0D\u6539\u5199\u5267\u672C\u3001\u5206\u955C\u6216\u89C6\u9891\u63D0\u793A\u8BCD\u7684\u8BED\u4E49\uFF1B\u4E0D\u8981\u9000\u56DE\u53BB\u751F\u6210\u65B0\u7D20\u6750\u3002
877
+
878
+ \u89C6\u9891\u63D0\u793A\u8BCD.md \u91CC\u7684\u6BCF\u4E2A\u300C## MOTION-*\u300D\u90FD\u5FC5\u987B\u4F5C\u4E3A\u67D0\u4E2A CUT \u7684\u300C\u6765\u6E90\u300D\uFF0C\u5426\u5219\u5199\u8FDB\u526A\u8F91\u5355\u5F00\u5934\uFF08\u4EA4\u4ED8\u89C4\u683C\u6240\u5728\u5904\u3001\u7B2C\u4E00\u4E2A\u300C## CUT-\u300D\u4E4B\u524D\uFF09\u7684\u4E00\u884C\uFF1A\u300C- \u672A\u91C7\u7528\u955C\u5934\uFF1AMOTION-\u2026\uFF08\u7406\u7531\uFF1A\u6587\u4EF6\u7F3A\u5931\u2014\u2014\u2026\uFF09\uFF1BMOTION-\u2026\uFF08\u7406\u7531\uFF1A\u8D28\u91CF\u4E0D\u53EF\u7528\u2014\u2014\u2026\uFF09\u300D\u3002\u591A\u9879\u7528\u5168\u89D2\u300C\uFF1B\u300D\u8FDE\u63A5\uFF0C\u7406\u7531\u4E0D\u80FD\u4E3A\u7A7A\u3001\u81EA\u8EAB\u4E0D\u542B\u300C\uFF1B\u300D\uFF0C\u5E76\u5199\u660E\u5C5E\u4E8E\u6587\u4EF6\u7F3A\u5931\u3001\u8D28\u91CF\u4E0D\u53EF\u7528\u8FD8\u662F\u53D9\u4E8B\u53D6\u820D\uFF1B\u6F0F\u6389\u4EFB\u4F55\u4E00\u4E2A\uFF0Ccheck \u90FD\u4F1A\u963B\u65AD\u3002
827
879
 
828
- \u5148\u9A8C\u8BC1\u8F93\u5165\u5747\u5B58\u5728\u4E14\u53EF\u8BFB\uFF0C\u518D\u4F7F\u7528\u5F53\u524D DSH Preset \u53EF\u89C1\u7684\u5A92\u4F53/\u547D\u4EE4\u5DE5\u5177\u6267\u884C\uFF1B\u97F3\u89C6\u9891\u53C2\u6570\u4E0D\u517C\u5BB9\u65F6\u505A\u660E\u786E\u3001\u53EF\u5BA1\u8BA1\u7684\u6807\u51C6\u5316\u3002\u6240\u6709\u547D\u4EE4\u548C\u5199\u5165\u7EE7\u7EED\u9075\u5B88 DSH \u6743\u9650\u4E0E\u5BA1\u6279\uFF0C\u4E0D\u5F97\u4F2A\u9020\u6210\u529F\u3002`;
880
+ \u526A\u8F91\u5355\u843D\u76D8\u540E\u4F9D\u6B21\u8FD0\u884C edit_tool.py \u7684 check \u4E0E render\uFF0Ccheck \u62A5\u51FA\u7684\u95EE\u9898\u5148\u6539\u6587\u6863\u518D\u91CD\u8DD1\u3002\u6240\u6709 CUT \u7684\u7D20\u6750\u5FC5\u987B\u540C\u5BBD\u3001\u540C\u9AD8\u3001\u540C\u5E27\u7387\uFF1Arender \u53EA\u786C\u62FC\u63A5\uFF0C\u4E0D\u7F29\u653E\u4E5F\u4E0D\u6539\u5E27\u7387\u3002check \u62A5\u51FA\u753B\u5E45\u6216\u5E27\u7387\u4E0D\u4E00\u81F4\u65F6\uFF0C\u5728\u5F53\u524D DSH \u6267\u884C\u73AF\u5883\u91CC\u7ECF\u5BA1\u6279\u7528 ffmpeg \u6309\u4EA4\u4ED8\u89C4\u683C\u7EDF\u4E00\u3001\u4FDD\u7559\u6784\u56FE\uFF0C\u65B0\u6587\u4EF6\u5199\u5230 ${production.episodeDirectory}/\u5236\u4F5C\u6210\u679C/\u6210\u7247/\u89C4\u683C\u7EDF\u4E00/\u2014\u2014\u8FD9\u662F\u526A\u8F91\u9636\u6BB5\u81EA\u5DF1\u7684\u4E2D\u95F4\u6587\u4EF6\uFF0C\u4E0D\u653E\u5728\u751F\u4EA7\u9636\u6BB5\u7684\u539F\u7D20\u6750\u65C1\u8FB9\u3001\u4E0D\u8986\u76D6\u5DF2\u751F\u4EA7\u7684\u7D20\u6750\uFF0C\u6587\u4EF6\u540D\u4E5F\u4E0D\u6CBF\u7528\u539F\u6587\u4EF6\u91CC\u7684\u4EFB\u52A1 ID\uFF08\u53EF\u76F4\u63A5\u7528 MOTION ID\uFF09\uFF1B\u5728\u8BE5 CUT \u4E0B\u8BB0\u5F55\u88C1\u5207\u6216\u7559\u8FB9\uFF08\u4E0D\u8981\u5199\u8FDB\u300C\u753B\u9762\u300D\u884C\uFF0C\u5B83\u53EA\u8BA4\u4EAE\u5EA6\u3001\u9971\u548C\u3001\u8272\u6E29\uFF09\uFF0C\u628A\u300C\u6765\u6E90\u300D\u6539\u6307\u65B0\u6587\u4EF6\uFF0C\u5165\u51FA\u70B9\u968F\u8F6C\u6362\u53D8\u5316\u65F6\u540C\u6B65\u4FEE\u6539\uFF0C\u518D\u91CD\u8DD1 check\u3002
881
+
882
+ \u9ED8\u8BA4\u7684\u786C\u5B57\u5E55\u8DEF\u7EBF\u9700\u8981\u5E26 libass \u7684 ffmpeg\uFF0C\u7F3A libass \u65F6\u5982\u5B9E\u62A5\u51FA\uFF0C\u4E0D\u8981\u6084\u6084\u53BB\u6389\u5B57\u5E55\uFF1B\u6539\u7528 Remotion \u9700\u8981\u5148\u5B89\u88C5 Node \u4F9D\u8D56\u5E76\u9010\u5E27\u8FC7\u65E0\u5934\u6D4F\u89C8\u5668\uFF0C\u53EA\u6709\u521B\u4F5C\u8005\u660E\u786E\u540C\u610F\u8FD9\u6B21\u5B89\u88C5\u65F6\u624D\u8D70\u3002\u526A\u8F91\u5355\u7684\u300C\u58F0\u97F3\u300D\u884C\u53EA\u662F\u8BB0\u5F55\uFF0Crender \u4E0D\u6267\u884C\u5B83\uFF1Arender \u53EA\u5207\u6BB5\u3001\u786C\u62FC\u63A5\u3001\u70E7\u5B57\u5E55\u3001\u505A\u300C\u753B\u9762\u300D\u6821\u6B63\u4E0E\u53EF\u9009\u9897\u7C92\u3001\u7EDF\u4E00\u54CD\u5EA6\u3002\u6DF7\u97F3\u3001\u4EA4\u53C9\u6DE1\u5165\u3001\u914D\u4E50\u3001\u8F6C\u573A\u6216\u683C\u5F0F\u8F6C\u6362\u90FD\u662F\u53E6\u4E00\u6B65\u7ECF\u5BA1\u6279\u7684\u5916\u90E8 ffmpeg \u5904\u7406\uFF0C\u5148\u5199\u5230\u4E34\u65F6\u6587\u4EF6\uFF1B\u8FD9\u4E00\u6B65\u6700\u540E\u8981\u50CF render \u4E00\u6837\u6309\u526A\u8F91\u5355\u7684\u300C\u4EA4\u4ED8\u54CD\u5EA6\u300D\u5BF9\u6574\u7247\u505A\u4E24\u904D loudnorm\uFF08I=\u4EA4\u4ED8\u54CD\u5EA6\u3001TP=-1.5\u3001LRA=11\uFF0C\u7B2C\u4E8C\u904D\u4EE3\u5165\u7B2C\u4E00\u904D\u7684\u5B9E\u6D4B\u503C\u5E76\u7528 linear=true\uFF09\uFF0C\u97F3\u9891\u7F16\u7801\u4E3A AAC 192k\u300148 kHz\uFF0C\u7136\u540E\u624D\u66FF\u6362 ${production.episodeDirectory}/\u5236\u4F5C\u6210\u679C/\u6210\u7247/\u6210\u7247.mp4\uFF0C\u5E76\u628A\u547D\u4EE4\u8BB0\u8FDB\u526A\u8F91\u5355\uFF1B\u91CD\u65B0 render \u4F1A\u8986\u76D6\u6210\u7247\uFF0C\u8FD9\u4E9B\u6B65\u9AA4\u8981\u91CD\u505A\u3002\u6700\u540E\u5BF9\u4EA4\u4ED8\u7684\u8FD9\u4EFD\u6210\u7247.mp4 \u8FD0\u884C edit_tool.py verify \u5E76\u62A5\u544A\u5B9E\u6D4B\u6570\u5B57\uFF0C\u300C\u672A\u6D4B\u300D\u9879\u7167\u5B9E\u5199\u672A\u6D4B\u3002
883
+
884
+ ffmpeg \u4E0E ffprobe \u901A\u8FC7\u5F53\u524D DSH \u6267\u884C\u73AF\u5883\u8C03\u7528\uFF0C\u4E0D\u53EF\u7528\u65F6\u5982\u5B9E\u62A5\u51FA\u6765\uFF0C\u4E0D\u8981\u628A\u300C\u6CA1\u6D4B\u300D\u5199\u6210\u300C\u901A\u8FC7\u300D\u3002\u6240\u6709\u547D\u4EE4\u548C\u5199\u5165\u7EE7\u7EED\u9075\u5B88 DSH \u6743\u9650\u4E0E\u5BA1\u6279\uFF0C\u4E0D\u5F97\u4F2A\u9020\u6210\u529F\u3002`;
829
885
  }
830
886
 
831
887
  // src/client/production-runtime.ts
888
+ function record(value) {
889
+ return typeof value == "object" && value !== null && !Array.isArray(value) ? value : void 0;
890
+ }
891
+ function productionQueueFromInbox(rows, claimedRequestIds = /* @__PURE__ */ new Set()) {
892
+ return Array.isArray(rows) ? rows.flatMap((row) => {
893
+ let item = record(row);
894
+ if (item === void 0 || typeof item.id != "string" || !Array.isArray(item.content)) return [];
895
+ let source = record(item.source);
896
+ if (source?.kind === "user" && typeof source.rpcId == "string" && claimedRequestIds.has(source.rpcId)) return [];
897
+ let preview = item.content.flatMap((block) => {
898
+ let value = record(block);
899
+ return value?.type === "text" && typeof value.text == "string" ? [value.text] : [];
900
+ }).join(" ");
901
+ return [{ id: item.id, preview }];
902
+ }) : [];
903
+ }
832
904
  function createPendingJob(input) {
833
905
  return {
834
906
  id: input.id,
@@ -838,14 +910,18 @@ function createPendingJob(input) {
838
910
  progress: 0,
839
911
  prompt: input.prompt,
840
912
  expectedOutputs: Math.max(1, Math.floor(input.expectedOutputs ?? 1)),
841
- completedOutputs: 0
913
+ completedOutputs: 0,
914
+ outputPath: input.outputPath,
915
+ supersededOutputIds: input.supersededOutputIds
842
916
  };
843
917
  }
844
918
  function selectedVersionForTarget(targetId, versions, selections, kind) {
845
919
  let candidates = versions.filter((version) => version.targetId === targetId && (kind === void 0 || version.kind === kind));
846
920
  return candidates.find((version) => version.id === selections[targetId]) ?? candidates.at(-1);
847
921
  }
922
+ var EDIT_OUTPUT_DIRECTORY = /(?:^|\/)制作成果\/成片\//u;
848
923
  function mediaTargetFromPath(path, knownTargets) {
924
+ if (EDIT_OUTPUT_DIRECTORY.test(path)) return;
849
925
  let segments = path.toLocaleUpperCase().split("/"), filename = segments.at(-1) ?? "";
850
926
  return [...knownTargets].sort((left, right) => right.length - left.length).find((target) => {
851
927
  let canonical = target.toLocaleUpperCase();
@@ -857,6 +933,17 @@ function mediaVersionMatchesJob(version, jobId) {
857
933
  let escaped = jobId.replace(/[.*+?^${}()|[\]\\]/gu, "\\$&"), basename = version.path.split("/").at(-1) ?? "";
858
934
  return new RegExp(`(?:^|[-_.])${escaped}(?:[-_.]|$)`, "u").test(basename);
859
935
  }
936
+ function outputsForJob(job, versions) {
937
+ if (job.outputPath === void 0) return versions.filter((version) => mediaVersionMatchesJob(version, job.id));
938
+ let superseded = new Set(job.supersededOutputIds ?? []);
939
+ return versions.filter((version) => version.path === job.outputPath && !superseded.has(version.id));
940
+ }
941
+ function compositionInFlight(jobs) {
942
+ return jobs.some((job) => job.kind === "composition" && (job.status === "awaiting_confirmation" || job.status === "pending" || job.status === "running"));
943
+ }
944
+ function settleSupersededCompositions(jobs, next) {
945
+ return next.kind !== "composition" ? [...jobs] : jobs.map((job) => job.id !== next.id && job.kind === "composition" && job.status === "dispatched_unknown" && (job.targetId === next.targetId || job.outputPath !== void 0 && job.outputPath === next.outputPath) ? { ...job, status: "failed" } : job);
946
+ }
860
947
  function referencesForTarget(targetId, production, versions, selections, libraryVersions = versions, manualReferences = {}) {
861
948
  let shot = production.shots.find((item) => item.id === targetId);
862
949
  if (shot === void 0) return [];
@@ -879,9 +966,10 @@ function activeProductionJobId(jobs, queue, sessionRunning) {
879
966
  return [...jobs].reverse().find((job) => (job.status === "awaiting_confirmation" || job.status === "pending" || job.status === "running") && queuedItemForJob(job.id, queue) === void 0)?.id;
880
967
  }
881
968
  function reconcileProductionJobs(jobs, queue, sessionRunning, versions) {
882
- let latestPending = [...jobs].reverse().find((job) => job.status === "pending" && queuedItemForJob(job.id, queue) === void 0);
883
- return jobs.map((job) => {
884
- let queued = queuedItemForJob(job.id, queue) !== void 0, outputs = versions.filter((version) => mediaVersionMatchesJob(version, job.id));
969
+ let latestPending = [...jobs].reverse().find((job) => job.status === "pending" && queuedItemForJob(job.id, queue) === void 0), settleCompositions = (list) => list.filter((job) => job.kind === "composition" && job.status === "running").reduce((current, running) => settleSupersededCompositions(current, running), [...list]), reconciled = settleCompositions(jobs).map((job) => {
970
+ let queued = queuedItemForJob(job.id, queue) !== void 0;
971
+ if (job.status === "canceled" || job.status === "succeeded" || job.status === "failed" && job.outputPath !== void 0) return job;
972
+ let outputs = outputsForJob(job, versions);
885
973
  return outputs.length >= job.expectedOutputs ? {
886
974
  ...job,
887
975
  status: "succeeded",
@@ -889,12 +977,14 @@ function reconcileProductionJobs(jobs, queue, sessionRunning, versions) {
889
977
  completedOutputs: outputs.length,
890
978
  output: outputs[0],
891
979
  error: void 0
892
- } : job.status === "canceled" || job.status === "succeeded" || job.status === "awaiting_confirmation" && outputs.length === 0 ? job : job.status === "running" && queued ? { ...job, status: "pending", progress: 0 } : job.status === "pending" && sessionRunning && !queued && job === latestPending ? { ...job, status: "running", progress: Math.max(10, job.progress), error: void 0 } : !sessionRunning && !queued && (job.status === "running" || job.status === "dispatched_unknown") ? {
980
+ } : job.status === "awaiting_confirmation" && outputs.length === 0 ? job : job.status === "running" && queued ? { ...job, status: "pending", progress: 0 } : job.status === "pending" && sessionRunning && !queued && job === latestPending ? { ...job, status: "running", progress: Math.max(10, job.progress), error: void 0 } : !sessionRunning && !queued && (job.status === "running" || job.status === "dispatched_unknown") ? {
893
981
  ...job,
894
982
  status: "dispatched_unknown",
895
983
  progress: Math.round(outputs.length / job.expectedOutputs * 100),
896
984
  completedOutputs: outputs.length,
897
- error: outputs.length === 0 ? "DSH Turn \u5DF2\u7ED3\u675F\uFF0C\u5C1A\u672A\u53D1\u73B0\u5173\u8054\u6210\u679C\u3002\u4EFB\u52A1\u53EF\u80FD\u5DF2\u6D3E\u53D1\uFF0C\u8BF7\u5148\u5237\u65B0\u6210\u679C\uFF0C\u907F\u514D\u91CD\u590D\u8BA1\u8D39\u3002" : `DSH Turn \u5DF2\u7ED3\u675F\uFF0C\u5DF2\u53D1\u73B0 ${String(outputs.length)}/${String(job.expectedOutputs)} \u9879\u6210\u679C\uFF1B\u8BF7\u5237\u65B0\u6838\u5BF9\u5269\u4F59\u8F93\u51FA\u3002`
985
+ // Assembly is local ffmpeg, so nothing was billed: a missing cut usually means edit_tool
986
+ // check blocked the render, and those findings — not a billing warning — are what to show.
987
+ error: outputs.length > 0 ? `DSH Turn \u5DF2\u7ED3\u675F\uFF0C\u5DF2\u53D1\u73B0 ${String(outputs.length)}/${String(job.expectedOutputs)} \u9879\u6210\u679C\uFF1B\u8BF7\u5237\u65B0\u6838\u5BF9\u5269\u4F59\u8F93\u51FA\u3002` : job.kind === "composition" ? "\u6210\u7247\u672A\u751F\u6210\uFF1A\u8BF7\u5728 Chat \u67E5\u770B edit_tool check \u7684\u963B\u65AD\u9879\uFF08\u672A\u91C7\u7528\u955C\u5934\u7406\u7531\u3001\u753B\u5E45/\u5E27\u7387\u4E0D\u4E00\u81F4\u7B49\uFF09\uFF0C\u4FEE\u6B63\u540E\u518D\u5408\u6210\u3002" : "DSH Turn \u5DF2\u7ED3\u675F\uFF0C\u5C1A\u672A\u53D1\u73B0\u5173\u8054\u6210\u679C\u3002\u4EFB\u52A1\u53EF\u80FD\u5DF2\u6D3E\u53D1\uFF0C\u8BF7\u5148\u5237\u65B0\u6210\u679C\uFF0C\u907F\u514D\u91CD\u590D\u8BA1\u8D39\u3002"
898
988
  } : outputs.length > 0 ? {
899
989
  ...job,
900
990
  status: job.status === "failed" ? "failed" : "running",
@@ -903,6 +993,7 @@ function reconcileProductionJobs(jobs, queue, sessionRunning, versions) {
903
993
  error: job.status === "failed" ? job.error : void 0
904
994
  } : job;
905
995
  });
996
+ return settleCompositions(reconciled);
906
997
  }
907
998
  function reconcileSequence(shotIds, current, versions, selections) {
908
999
  let shotSet = new Set(shotIds), preserved = current.filter((item) => shotSet.has(item.shotId)), present = new Set(preserved.map((item) => item.shotId)), appended = shotIds.filter((shotId) => !present.has(shotId)).map((shotId) => ({ shotId }));
@@ -927,7 +1018,7 @@ function reorderSequence(sequence, source, target) {
927
1018
  }
928
1019
 
929
1020
  // src/client/drama-production-view.tsx
930
- var import_jsx_runtime3 = require("react/jsx-runtime"), SECTION_LABELS = { shots: "\u955C\u5934", assets: "\u7D20\u6750", tasks: "\u4EFB\u52A1", sequence: "\u6210\u7247", canvas: "\u753B\u5E03" }, SECTION_ORDER = Object.keys(SECTION_LABELS), STATUS_LABELS = { awaiting_confirmation: "\u7B49\u5F85\u786E\u8BA4", pending: "\u5DF2\u63D0\u4EA4", running: "DSH \u6267\u884C\u4E2D", dispatched_unknown: "\u5F85\u6838\u5BF9", succeeded: "\u5DF2\u5B8C\u6210", failed: "\u5931\u8D25", canceled: "\u5DF2\u53D6\u6D88" }, ASSET_KIND_LABEL = { character: "\u4EBA\u7269", scene: "\u573A\u666F", prop: "\u9053\u5177", state: "\u72B6\u6001", unknown: "\u8BBE\u5B9A" }, JOB_KIND_LABEL = { image: "\u56FE\u7247", video: "\u89C6\u9891", composition: "\u6210\u7247" }, MODALITY_LABEL = { image: "\u56FE\u7247", video: "\u89C6\u9891", music: "\u97F3\u4E50" };
1021
+ var import_jsx_runtime3 = require("react/jsx-runtime"), SECTION_LABELS = { shots: "\u955C\u5934", assets: "\u7D20\u6750", tasks: "\u4EFB\u52A1", sequence: "\u6210\u7247", canvas: "\u753B\u5E03" }, SECTION_ORDER = Object.keys(SECTION_LABELS), STATUS_LABELS = { awaiting_confirmation: "\u7B49\u5F85\u786E\u8BA4", pending: "\u5DF2\u63D0\u4EA4", running: "DSH \u6267\u884C\u4E2D", dispatched_unknown: "\u5F85\u6838\u5BF9", succeeded: "\u5DF2\u5B8C\u6210", failed: "\u5931\u8D25", canceled: "\u5DF2\u53D6\u6D88" }, ASSET_KIND_LABEL = { character: "\u4EBA\u7269", scene: "\u573A\u666F", prop: "\u9053\u5177", state: "\u72B6\u6001", unknown: "\u8BBE\u5B9A" }, JOB_KIND_LABEL = { image: "\u56FE\u7247", video: "\u89C6\u9891", composition: "\u6210\u7247" }, ASSEMBLED_CUT_PATH = "\u5236\u4F5C\u6210\u679C/\u6210\u7247/\u6210\u7247.mp4", MODALITY_LABEL = { image: "\u56FE\u7247", video: "\u89C6\u9891", tts: "\u8BED\u97F3", music: "\u97F3\u4E50" };
931
1022
  function ProductionEnvironment({ sessionId }) {
932
1023
  let [preflight, setPreflight] = (0, import_react.useState)(), [attempt, setAttempt] = (0, import_react.useState)(0);
933
1024
  (0, import_react.useEffect)(() => {
@@ -961,7 +1052,7 @@ function ProductionEnvironment({ sessionId }) {
961
1052
  adapter.configured ? "" : ` \xB7 \u7F3A ${adapter.missing.join("\u3001")}`
962
1053
  ] }, adapter.name)),
963
1054
  /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("em", { children: [
964
- "DeepSeek \u53EA\u8D1F\u8D23\u5199\u63D0\u793A\u8BCD\uFF1B\u56FE\u7247\u3001\u89C6\u9891\u3001\u97F3\u4E50\u7531\u4E0A\u9762\u7684\u4F9B\u5E94\u5546 API \u751F\u6210\uFF0CKey \u5728\u542F\u52A8 DSH \u524D\u5199\u5165\u5BBF\u4E3B\u673A\u73AF\u5883\u53D8\u91CF\u3002",
1055
+ "DeepSeek \u53EA\u8D1F\u8D23\u5199\u63D0\u793A\u8BCD\uFF1B\u56FE\u7247\u3001\u89C6\u9891\u3001\u8BED\u97F3\u3001\u97F3\u4E50\u7531\u4E0A\u9762\u7684\u4F9B\u5E94\u5546 API \u751F\u6210\uFF0CKey \u5728\u542F\u52A8 DSH \u524D\u5199\u5165\u5BBF\u4E3B\u673A\u73AF\u5883\u53D8\u91CF\u3002",
965
1056
  unconfigured.length === preflight.adapters.length && " \u5F53\u524D\u4E00\u4E2A\u90FD\u6CA1\u914D\u7F6E\uFF0C\u751F\u4EA7\u4EFB\u52A1\u4F1A\u505C\u5728 adapter \u4E4B\u524D\u3002",
966
1057
  " ",
967
1058
  "Adapter \u914D\u7F6E",
@@ -1053,7 +1144,15 @@ ${item.prompt}`).join(`
1053
1144
  setNotice(issues[0]);
1054
1145
  return;
1055
1146
  }
1056
- dispatchComposition(createPendingJob({ id: crypto.randomUUID(), targetId: props.production.episodeDirectory, kind: "composition", prompt: "\u6309\u6210\u7247\u987A\u5E8F\u5408\u6210" }));
1147
+ let outputPath = `${props.production.episodeDirectory}/${ASSEMBLED_CUT_PATH}`;
1148
+ dispatchComposition(createPendingJob({
1149
+ id: crypto.randomUUID(),
1150
+ targetId: props.production.episodeDirectory,
1151
+ kind: "composition",
1152
+ prompt: "\u6309\u6210\u7247\u987A\u5E8F\u5408\u6210",
1153
+ outputPath,
1154
+ supersededOutputIds: props.libraryVersions.flatMap((version) => version.path === outputPath ? [version.id] : [])
1155
+ }));
1057
1156
  };
1058
1157
  return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "oh-story-production", children: [
1059
1158
  /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "oh-story-production-bar", children: [
@@ -1217,7 +1316,10 @@ function AssetBoard(props) {
1217
1316
  ] })
1218
1317
  ] })
1219
1318
  ] }),
1220
- referenceTarget === void 0 && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: "oh-story-projection-note", children: "\u5148\u5728\u955C\u5934\u9875\u9009\u4E2D\u4E00\u4E2A\u955C\u5934\uFF0C\u518D\u56DE\u5230\u8FD9\u91CC\u628A\u5DF2\u6709\u56FE\u7247\u8BBE\u4E3A\u8BE5\u955C\u5934\u7684\u989D\u5916\u53C2\u8003\u3002" }),
1319
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("p", { className: "oh-story-projection-note", children: [
1320
+ referenceTarget === void 0 ? "\u5148\u5728\u955C\u5934\u9875\u9009\u4E2D\u4E00\u4E2A\u955C\u5934\uFF0C\u518D\u56DE\u5230\u8FD9\u91CC\u628A\u5DF2\u6709\u56FE\u7247\u8BBE\u4E3A\u8BE5\u955C\u5934\u7684\u8865\u5145\u53C2\u8003\u3002" : `\u53EF\u628A\u4E0B\u9762\u7684\u56FE\u7247\u8BBE\u4E3A ${referenceTarget} \u7684\u8865\u5145\u53C2\u8003\u3002`,
1321
+ "\u8865\u5145\u53C2\u8003\u53EA\u63D0\u793A Agent \u6838\u5BF9\uFF1B\u5199\u8FDB\u6765\u6E90\u6761\u76EE\u7684\u300C\u8F93\u5165\u53C2\u8003\u56FE\u300D\u540E\u624D\u4F1A\u9001\u8FDB\u751F\u4EA7\u3002"
1322
+ ] }),
1221
1323
  /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "oh-story-media-library-grid", children: library.map((version) => {
1222
1324
  let selected = referenceTarget !== void 0 && (props.manualReferences[referenceTarget] ?? []).includes(version.id);
1223
1325
  return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("article", { children: [
@@ -1228,9 +1330,9 @@ function AssetBoard(props) {
1228
1330
  version.path !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", onClick: () => {
1229
1331
  props.onOpenMedia(version.path);
1230
1332
  }, children: "\u6253\u5F00\u6587\u4EF6" }),
1231
- referenceTarget !== void 0 && version.kind === "image" && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", "aria-pressed": selected, "aria-label": `${selected ? "\u53D6\u6D88" : "\u8BBE\u4E3A"} ${referenceTarget} \u53C2\u8003 ${version.targetId}`, onClick: () => {
1333
+ referenceTarget !== void 0 && version.kind === "image" && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", "aria-pressed": selected, "aria-label": `${selected ? "\u53D6\u6D88" : "\u8BBE\u4E3A"} ${referenceTarget} \u53C2\u8003 ${version.targetId}`, title: "\u63D0\u793A Agent \u6838\u5BF9\uFF1B\u5199\u8FDB\u300C\u8F93\u5165\u53C2\u8003\u56FE\u300D\u540E\u624D\u4F1A\u9001\u8FDB\u751F\u4EA7", onClick: () => {
1232
1334
  toggleReference(version.id);
1233
- }, children: selected ? "\u5DF2\u5F15\u7528" : "\u4F5C\u4E3A\u53C2\u8003" })
1335
+ }, children: selected ? "\u5DF2\u8BBE\u8865\u5145\u53C2\u8003" : "\u8BBE\u4E3A\u8865\u5145\u53C2\u8003" })
1234
1336
  ] })
1235
1337
  ] }, version.id);
1236
1338
  }) })
@@ -1240,7 +1342,7 @@ function AssetBoard(props) {
1240
1342
  function TaskBoard({ jobs, queue, sessionRunning, onCancel, onRemoveQueued }) {
1241
1343
  let activeJobId = activeProductionJobId(jobs, queue, sessionRunning);
1242
1344
  return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("section", { className: "oh-story-task-board", children: [
1243
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "oh-story-projection-note", children: "\u56FE\u7247\u4E0E\u89C6\u9891\u5148\u9884\u68C0\u3001\u540E\u786E\u8BA4\u3002\u5185\u7F6E\u5951\u7EA6\u652F\u6301 GPT Image 2 / Seedance\uFF1B\u5B9E\u9645\u8D26\u53F7\u3001\u6A21\u578B\u4E0E\u53EF\u7528\u6027\u7531\u5F53\u524D DSH \u8FD0\u884C\u73AF\u5883\u51B3\u5B9A\u3002" }),
1345
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "oh-story-projection-note", children: "\u56FE\u7247\u3001\u89C6\u9891\u3001\u8BED\u97F3\u3001\u97F3\u4E50\u90FD\u5148\u9884\u68C0\u3001\u540E\u786E\u8BA4\u3002\u8FD9\u91CC\u8DDF\u8E2A\u56FE\u7247\u3001\u89C6\u9891\u4E0E\u6210\u7247\u4EFB\u52A1\uFF1B\u8BED\u97F3\u548C\u97F3\u4E50\u5728 Chat \u91CC\u5B8C\u6210\uFF0C\u7ED3\u679C\u76F4\u63A5\u843D\u5728\u5236\u4F5C\u6210\u679C\u76EE\u5F55\u3002\u4F9B\u5E94\u5546\u89C1\u4E0A\u65B9\u300C\u751F\u6210\u73AF\u5883\u300D\uFF0C\u5B9E\u9645\u8D26\u53F7\u3001\u6A21\u578B\u4E0E\u53EF\u7528\u6027\u7531\u5F53\u524D DSH \u8FD0\u884C\u73AF\u5883\u51B3\u5B9A\u3002" }),
1244
1346
  jobs.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "oh-story-production-empty", children: "\u8FD8\u6CA1\u6709\u751F\u4EA7\u4EFB\u52A1\u3002\u53EF\u4ECE\u955C\u5934\u6216\u7D20\u6750\u9875\u63D0\u4EA4\u5355\u4E2A\u6216\u6279\u91CF\u4EFB\u52A1\u3002" }) : [...jobs].reverse().map((job) => {
1245
1347
  let queued = queuedItemForJob(job.id, queue), displayStatus = queued === void 0 ? STATUS_LABELS[job.status] : "DSH Queue";
1246
1348
  return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("article", { "data-job-id": job.id, "data-status": job.status, children: [
@@ -1275,7 +1377,7 @@ function TaskBoard({ jobs, queue, sessionRunning, onCancel, onRemoveQueued }) {
1275
1377
  ] });
1276
1378
  }
1277
1379
  function SequenceBoard(props) {
1278
- let issues = sequenceIssues(props.sequence, props.versions), versionById = new Map(props.versions.map((version) => [version.id, version])), move = (index, delta) => {
1380
+ let composing = compositionInFlight(props.jobs), issues = sequenceIssues(props.sequence, props.versions), versionById = new Map(props.versions.map((version) => [version.id, version])), move = (index, delta) => {
1279
1381
  let source = props.sequence[index], target = props.sequence[index + delta];
1280
1382
  source !== void 0 && target !== void 0 && props.onSequenceChange(reorderSequence(props.sequence, index, index + delta));
1281
1383
  };
@@ -1285,8 +1387,8 @@ function SequenceBoard(props) {
1285
1387
  props.sequence.length,
1286
1388
  " \u4E2A\u955C\u5934"
1287
1389
  ] }),
1288
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { children: props.sequence.length === 0 ? "\u8FD8\u6CA1\u6709\u955C\u5934" : issues.length === 0 ? "\u5DF2\u53EF\u5408\u6210" : `${String(issues.length)} \u4E2A\u963B\u585E\u9879` }),
1289
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", disabled: issues.length > 0 || props.sequence.length < 2, onClick: props.onCompose, children: "\u5408\u6210\u6210\u7247" })
1390
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { children: props.sequence.length === 0 ? "\u8FD8\u6CA1\u6709\u955C\u5934" : composing ? "\u6210\u7247\u4EFB\u52A1\u8FDB\u884C\u4E2D" : issues.length === 0 ? "\u5DF2\u53EF\u5408\u6210" : `${String(issues.length)} \u4E2A\u963B\u585E\u9879` }),
1391
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", disabled: composing || issues.length > 0 || props.sequence.length < 2, onClick: props.onCompose, children: "\u5408\u6210\u6210\u7247" })
1290
1392
  ] }),
1291
1393
  issues.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("ul", { className: "oh-story-sequence-issues", children: [
1292
1394
  issues.slice(0, 3).map((issue) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("li", { children: issue }, issue)),
@@ -1884,8 +1986,9 @@ var plugin_default = `.oh-story-bridge-marker { display: none; }
1884
1986
  border-left: 1px solid var(--os-border);
1885
1987
  }
1886
1988
 
1989
+ /* DSH 0.1.7 nests a data-chat-flow inside every step-process group; only the top-level flow needs room. */
1887
1990
  [data-conversation-scroll]:has(> [data-slot="conversation.session"] > .oh-story-split-surface[data-open="true"])
1888
- [data-chat-flow] {
1991
+ [data-chat-flow]:not([data-step-process-content]) {
1889
1992
  padding-bottom: calc(max(var(--dsh-composer-height, 152px), var(--oh-story-composer-height, 0px)) + 16px);
1890
1993
  }
1891
1994
 
@@ -2966,6 +3069,7 @@ var import_jsx_runtime5 = require("react/jsx-runtime"), name = "oh-story", injec
2966
3069
  function applyUpdate(current, update) {
2967
3070
  return typeof update == "function" ? update(current) : update;
2968
3071
  }
3072
+ var workbenchMemoryBySession = /* @__PURE__ */ new Map(), NO_UNDISPATCHED_CALLS = [];
2969
3073
  function createWorkbenchStore() {
2970
3074
  return (0, import_dsh_client_store.defineStore)({
2971
3075
  init: () => ({
@@ -2989,9 +3093,17 @@ function createWorkbenchStore() {
2989
3093
  productionSequence: {},
2990
3094
  productionCanvas: {},
2991
3095
  productionZoom: {},
2992
- productionIntentCalls: {}
3096
+ productionIntentCalls: {},
3097
+ settledMutation: void 0,
3098
+ hydrated: !1
2993
3099
  }),
2994
3100
  actions: {
3101
+ restore: (draft, memory) => {
3102
+ memory !== void 0 && (Object.assign(draft, memory), draft.buffers = Object.fromEntries(Object.entries(memory.buffers).map(([path, buffer]) => [path, { ...buffer, saving: void 0 }]))), draft.hydrated = !0;
3103
+ },
3104
+ setSettledMutation: (draft, value) => {
3105
+ draft.settledMutation = value;
3106
+ },
2995
3107
  setBuffers: (draft, update) => {
2996
3108
  draft.buffers = applyUpdate(draft.buffers, update);
2997
3109
  },
@@ -3379,7 +3491,10 @@ function CreativeWorkbench({
3379
3491
  sessionId,
3380
3492
  runningCalls,
3381
3493
  partial,
3494
+ undispatched,
3382
3495
  settledMutation,
3496
+ settledMutationTurn,
3497
+ liveTurn,
3383
3498
  sessionRunning,
3384
3499
  productionQueue,
3385
3500
  productionIntents,
@@ -3392,18 +3507,21 @@ function CreativeWorkbench({
3392
3507
  reload,
3393
3508
  open,
3394
3509
  creativeProject,
3510
+ welcome,
3395
3511
  useStore,
3396
3512
  actions
3397
3513
  }) {
3398
3514
  let activities = (0, import_react3.useMemo)(
3399
- () => fileMutations(runningCalls, partial),
3400
- [partial, runningCalls]
3515
+ () => fileMutations(runningCalls, partial, undispatched),
3516
+ [partial, runningCalls, undispatched]
3401
3517
  ), normalizedActivities = (0, import_react3.useMemo)(() => activities.flatMap((activity2) => {
3402
3518
  let path = creativeRelativePath(activity2.path, workspace?.cwd);
3403
3519
  return path === void 0 ? [] : [{ activity: activity2, path }];
3404
- }), [activities, workspace?.cwd]), primaryActivity = normalizedActivities.at(-1), activityPaths = (0, import_react3.useMemo)(() => new Set(normalizedActivities.map((value) => value.path)), [normalizedActivities]), activity = primaryActivity?.activity, activityPath = primaryActivity?.path, workbench = useStore((memory) => memory.workbench), setWorkbench = actions.setWorkbench, gameTab = useStore((memory) => memory.gameTab), setGameTab = actions.setGameTab, gameProjectId = useStore((memory) => memory.gameProjectId), setGameProjectId = actions.setGameProjectId, gamePane = useStore((memory) => memory.gamePane), setGamePane = actions.setGamePane, videoTab = useStore((memory) => memory.videoTab), setVideoTab = actions.setVideoTab, videoProjectId = useStore((memory) => memory.videoProjectId), setVideoProjectId = actions.setVideoProjectId, videoPane = useStore((memory) => memory.videoPane), setVideoPane = actions.setVideoPane, selected = useStore((memory) => memory.selected), setSelected = actions.setSelected, buffers = useStore((memory) => memory.buffers), setBuffers = actions.setBuffers, buffersRef = (0, import_react3.useRef)({}), expanded = useStore((memory) => memory.expanded), setExpanded = actions.setExpanded, productionSection = useStore((memory) => memory.productionSection), setProductionSection = actions.setProductionSection, productionSelectedIds = useStore((memory) => memory.productionSelectedIds), productionJobsByEpisode = useStore((memory) => memory.productionJobs), productionSelectionsByEpisode = useStore((memory) => memory.productionSelections), productionReferencesByEpisode = useStore((memory) => memory.productionReferences), productionSequenceByEpisode = useStore((memory) => memory.productionSequence), productionCanvasByEpisode = useStore((memory) => memory.productionCanvas), productionZoomByEpisode = useStore((memory) => memory.productionZoom), productionIntentCalls = useStore((memory) => memory.productionIntentCalls), surfaceRef = (0, import_react3.useRef)(null), setWorkbenchPreference = actions.setWorkbenchPreference, applyWorkbenchPreference = (0, import_react3.useCallback)((preference) => {
3520
+ }), [activities, workspace?.cwd]), primaryActivity = normalizedActivities.at(-1), activityPaths = (0, import_react3.useMemo)(() => new Set(normalizedActivities.map((value) => value.path)), [normalizedActivities]), settledPath = settledMutation === void 0 ? void 0 : creativeRelativePath(settledMutation.slice(settledMutation.indexOf("\0") + 1), workspace?.cwd), activity = primaryActivity?.activity, activityPath = primaryActivity?.path, workbench = useStore((memory) => memory.workbench), setWorkbench = actions.setWorkbench, gameTab = useStore((memory) => memory.gameTab), setGameTab = actions.setGameTab, gameProjectId = useStore((memory) => memory.gameProjectId), setGameProjectId = actions.setGameProjectId, gamePane = useStore((memory) => memory.gamePane), setGamePane = actions.setGamePane, videoTab = useStore((memory) => memory.videoTab), setVideoTab = actions.setVideoTab, videoProjectId = useStore((memory) => memory.videoProjectId), setVideoProjectId = actions.setVideoProjectId, videoPane = useStore((memory) => memory.videoPane), setVideoPane = actions.setVideoPane, selected = useStore((memory) => memory.selected), setSelected = actions.setSelected, buffers = useStore((memory) => memory.buffers), setBuffers = actions.setBuffers, buffersRef = (0, import_react3.useRef)({}), expanded = useStore((memory) => memory.expanded), setExpanded = actions.setExpanded, productionSection = useStore((memory) => memory.productionSection), setProductionSection = actions.setProductionSection, productionSelectedIds = useStore((memory) => memory.productionSelectedIds), productionJobsByEpisode = useStore((memory) => memory.productionJobs), productionSelectionsByEpisode = useStore((memory) => memory.productionSelections), productionReferencesByEpisode = useStore((memory) => memory.productionReferences), productionSequenceByEpisode = useStore((memory) => memory.productionSequence), productionCanvasByEpisode = useStore((memory) => memory.productionCanvas), productionZoomByEpisode = useStore((memory) => memory.productionZoom), productionIntentCalls = useStore((memory) => memory.productionIntentCalls), surfaceRef = (0, import_react3.useRef)(null), setWorkbenchPreference = actions.setWorkbenchPreference, applyWorkbenchPreference = (0, import_react3.useCallback)((preference) => {
3405
3521
  setWorkbenchPreference(preference), writeWorkbenchPreference(workbenchPreferenceStorage(), workspace?.cwd, preference);
3406
- }, [setWorkbenchPreference, workspace?.cwd]), compactTabsId = (0, import_react3.useId)(), compactStudioId = `${compactTabsId}-studio-panel`, compactVideoStudioId = `${compactTabsId}-video-studio-panel`, compactChatId = `${compactTabsId}-chat-panel`, navRef = (0, import_react3.useRef)(null), activityBases = (0, import_react3.useRef)(/* @__PURE__ */ new Map()), previousSignals = (0, import_react3.useRef)(/* @__PURE__ */ new Set()), previousSettledMutation = (0, import_react3.useRef)(settledMutation), saveLocks = (0, import_react3.useRef)(/* @__PURE__ */ new Set()), buffer = selected === void 0 ? void 0 : buffers[selected], selectedFile = workspace?.files.find((file) => file.path === selected), selectedMedia = selectedFile?.kind === "media", dirty = buffer?.source === "human" && buffer.content !== buffer.saved, saving = buffer?.saving === !0, fileError = buffer?.error, conflict = buffer?.conflict, selectedLower = selected?.toLocaleLowerCase(), markdown = selectedLower?.endsWith(".md") === !0, jsonl = selectedLower?.endsWith(".jsonl") === !0, structured = jsonl || selectedLower?.endsWith(".json") === !0, previewable = markdown || jsonl, episodeDirectory = episodeDirectoryForPath(selected), productionAvailable = selected !== void 0 && isCreatorDocumentPath(selected) && episodeDirectory !== void 0, editorModes = productionAvailable ? EDITOR_MODES : EDITOR_MODES.filter((mode) => mode !== "production"), episodeDocumentPaths = (0, import_react3.useMemo)(
3522
+ }, [setWorkbenchPreference, workspace?.cwd]), compactTabsId = (0, import_react3.useId)(), compactStudioId = `${compactTabsId}-studio-panel`, compactVideoStudioId = `${compactTabsId}-video-studio-panel`, compactChatId = `${compactTabsId}-chat-panel`, navRef = (0, import_react3.useRef)(null), activityBases = (0, import_react3.useRef)(/* @__PURE__ */ new Map()), previousSignals = (0, import_react3.useRef)(/* @__PURE__ */ new Set()), consumedSettledMutation = useStore((memory) => memory.settledMutation), liveTurns = (0, import_react3.useRef)(/* @__PURE__ */ new Set());
3523
+ liveTurn !== void 0 && liveTurns.current.add(liveTurn);
3524
+ let saveLocks = (0, import_react3.useRef)(/* @__PURE__ */ new Set()), buffer = selected === void 0 ? void 0 : buffers[selected], selectedFile = workspace?.files.find((file) => file.path === selected), selectedMedia = selectedFile?.kind === "media", dirty = buffer?.source === "human" && buffer.content !== buffer.saved, saving = buffer?.saving === !0, fileError = buffer?.error, conflict = buffer?.conflict, selectedLower = selected?.toLocaleLowerCase(), markdown = selectedLower?.endsWith(".md") === !0, jsonl = selectedLower?.endsWith(".jsonl") === !0, structured = jsonl || selectedLower?.endsWith(".json") === !0, previewable = markdown || jsonl, episodeDirectory = episodeDirectoryForPath(selected), productionAvailable = selected !== void 0 && isCreatorDocumentPath(selected) && episodeDirectory !== void 0, editorModes = productionAvailable ? EDITOR_MODES : EDITOR_MODES.filter((mode) => mode !== "production"), episodeDocumentPaths = (0, import_react3.useMemo)(
3407
3525
  () => episodeDirectory === void 0 ? [] : creatorDocumentPaths(workspace?.files.filter((file) => file.kind === "text") ?? [], episodeDirectory),
3408
3526
  [episodeDirectory, workspace?.files]
3409
3527
  ), episodeDocuments = (0, import_react3.useMemo)(() => Object.fromEntries(episodeDocumentPaths.flatMap((path) => {
@@ -3432,7 +3550,7 @@ function CreativeWorkbench({
3432
3550
  ...episodeProduction.motions.map((motion) => motion.id)
3433
3551
  ].sort((left, right) => right.length - left.length), motionTargets = new Map(episodeProduction.motions.flatMap((motion) => motion.shotId === void 0 ? [] : [[motion.id, motion.shotId]])), fromWorkspace = productionLibrary.flatMap((version) => {
3434
3552
  if (version.path === void 0 || !version.path.startsWith(`${episodeProduction.episodeDirectory}/`) && !version.path.startsWith(`\u4EA4\u4ED8/${episodeName}/`)) return [];
3435
- let matched = mediaTargetFromPath(version.path, knownTargets), composition = /(?:^|\/)成片-[^/]+\.mp4$/iu.test(version.path);
3553
+ let matched = mediaTargetFromPath(version.path, knownTargets), composition = /(?:^|\/)成片-[^/]+\.mp4$/iu.test(version.path) || /(?:^|\/)制作成果\/成片\//u.test(version.path);
3436
3554
  if (matched === void 0 && !composition) return [];
3437
3555
  let targetId = matched === void 0 ? episodeProduction.episodeDirectory : motionTargets.get(matched) ?? matched;
3438
3556
  return [{ ...version, targetId }];
@@ -3571,10 +3689,10 @@ function CreativeWorkbench({
3571
3689
  setBuffers((current) => {
3572
3690
  let changed = !1, next = { ...current };
3573
3691
  for (let [path, value] of Object.entries(current))
3574
- paths.has(path) || activityPaths.has(path) || (value.source === "human" && value.content !== value.saved ? value.missing !== !0 && (next[path] = { ...value, missing: !0, error: "\u6587\u4EF6\u5DF2\u4ECE workspace \u79FB\u9664\u3002\u672C\u5730\u8349\u7A3F\u4ECD\u4FDD\u7559\uFF0C\u53EF\u590D\u5236\u540E\u653E\u5F03\u8349\u7A3F\u3002" }, changed = !0) : (delete next[path], changed = !0));
3692
+ paths.has(path) || activityPaths.has(path) || value.source === "agent" && sessionRunning && path === settledPath || (value.source === "human" && value.content !== value.saved ? value.missing !== !0 && (next[path] = { ...value, missing: !0, error: "\u6587\u4EF6\u5DF2\u4ECE workspace \u79FB\u9664\u3002\u672C\u5730\u8349\u7A3F\u4ECD\u4FDD\u7559\uFF0C\u53EF\u590D\u5236\u540E\u653E\u5F03\u8349\u7A3F\u3002" }, changed = !0) : (delete next[path], changed = !0));
3575
3693
  return changed ? next : current;
3576
3694
  });
3577
- }, [activityPaths, workspace, workspaceLoading]), (0, import_react3.useEffect)(() => {
3695
+ }, [activityPaths, sessionRunning, settledPath, workspace, workspaceLoading]), (0, import_react3.useEffect)(() => {
3578
3696
  if (selected === void 0 || selectedMedia || activityPaths.has(selected) || !(workspace?.files.some((file) => file.path === selected) ?? !1)) return;
3579
3697
  let controller = new AbortController();
3580
3698
  return setBuffers((current) => {
@@ -3678,11 +3796,16 @@ function CreativeWorkbench({
3678
3796
  signals.has(callId.split(":", 1)[0] ?? callId) || activityBases.current.delete(callId);
3679
3797
  previousSignals.current = signals, settled && reload();
3680
3798
  }, [normalizedActivities, reload, runningCalls]), (0, import_react3.useEffect)(() => {
3681
- if (settledMutation === void 0 || settledMutation === previousSettledMutation.current || workspace?.cwd === void 0) return;
3682
- previousSettledMutation.current = settledMutation;
3799
+ if (settledMutation === void 0 || settledMutation === consumedSettledMutation) return;
3800
+ if (settledMutationTurn === void 0 || !liveTurns.current.has(settledMutationTurn)) {
3801
+ actions.setSettledMutation(settledMutation);
3802
+ return;
3803
+ }
3804
+ if (workspace?.cwd === void 0) return;
3805
+ actions.setSettledMutation(settledMutation);
3683
3806
  let path = creativeRelativePath(settledMutation.slice(settledMutation.indexOf("\0") + 1), workspace.cwd);
3684
3807
  path !== void 0 && followAgentPath(path), reload();
3685
- }, [followAgentPath, reload, settledMutation, workspace?.cwd]), (0, import_react3.useEffect)(() => {
3808
+ }, [actions, consumedSettledMutation, followAgentPath, reload, settledMutation, settledMutationTurn, workspace?.cwd]), (0, import_react3.useEffect)(() => {
3686
3809
  if (selected !== void 0) {
3687
3810
  for (let button of navRef.current?.querySelectorAll("button[data-file-path]") ?? [])
3688
3811
  if (button.dataset.filePath === selected) {
@@ -4093,7 +4216,7 @@ function CreativeWorkbench({
4093
4216
  )
4094
4217
  ] })
4095
4218
  ] })
4096
- ] }) : !creativeProject && error === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { ref: surfaceRef, className: "oh-story-split-surface", "data-open": "false", children: [
4219
+ ] }) : !creativeProject && error === void 0 ? welcome ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(WelcomeGuide, {}) : null : /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { ref: surfaceRef, className: "oh-story-split-surface", "data-open": "false", children: [
4097
4220
  /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("style", { children: plugin_default }),
4098
4221
  /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("button", { className: "oh-story-launcher", type: "button", title: error ?? "\u6253\u5F00\u521B\u4F5C\u5DE5\u4F5C\u53F0", "aria-label": "\u6253\u5F00\u521B\u4F5C\u5DE5\u4F5C\u53F0", onClick: () => {
4099
4222
  applyWorkbenchPreference("open");
@@ -4103,8 +4226,29 @@ function CreativeWorkbench({
4103
4226
  ] })
4104
4227
  ] });
4105
4228
  }
4106
- function CreativeSplitBridge({ sessionId, useSession, useChat, useStore, actions, sendProductionPrompt, cancelProduction, removeQueuedProduction }) {
4107
- let marker = (0, import_react3.useRef)(null), [target, setTarget] = (0, import_react3.useState)(), runningCalls = useChat((snapshot) => snapshot.legacy.runningCalls), partial = useChat((snapshot) => streamingAssistant(snapshot.timeline)), settledMutation = useChat((snapshot) => latestSettledMutation(snapshot)), workbench = useStore((memory) => memory.workbench), gamePane = useStore((memory) => memory.gamePane), videoPane = useStore((memory) => memory.videoPane), sessionRunning = useSession((snapshot) => snapshot.running), productionQueue = useSession((snapshot) => snapshot.queue.map((item) => ({ id: item.id, preview: item.preview }))), chat = useChat((snapshot) => snapshot), productionIntents = (0, import_react3.useMemo)(() => settledProductionIntents(chat), [chat]), { workspace, error, loading: workspaceLoading, reload } = useWorkspace(sessionId), chosenPreference = useStore((memory) => memory.workbenchPreference), creativeProject = hasCreativeProject(workspace), storedPreference = (0, import_react3.useMemo)(
4229
+ function CreativeSplitBridge(props) {
4230
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(SessionWorkbenchMemory, { ...props }, props.sessionId);
4231
+ }
4232
+ function SessionWorkbenchMemory(props) {
4233
+ let { sessionId, useStore, actions } = props, hydrated = useStore((state) => state.hydrated);
4234
+ return (0, import_react3.useLayoutEffect)(() => {
4235
+ hydrated || actions.restore(workbenchMemoryBySession.get(sessionId));
4236
+ }, [actions, hydrated, sessionId]), hydrated ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
4237
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(WorkbenchMemoryMirror, { sessionId, useStore }),
4238
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(SessionWorkbenchBridge, { ...props })
4239
+ ] }) : null;
4240
+ }
4241
+ function WorkbenchMemoryMirror({ sessionId, useStore }) {
4242
+ let memory = useStore((state) => state);
4243
+ return (0, import_react3.useEffect)(() => {
4244
+ workbenchMemoryBySession.set(sessionId, memory);
4245
+ }, [memory, sessionId]), null;
4246
+ }
4247
+ function SessionWorkbenchBridge({ sessionId, useSession, useSessions, useProjection, useChat, useStore, actions, sendProductionPrompt, cancelProduction, removeQueuedProduction }) {
4248
+ let marker = (0, import_react3.useRef)(null), [target, setTarget] = (0, import_react3.useState)(), runningCalls = useChat((snapshot) => snapshot.legacy.runningCalls), partial = useChat((snapshot) => streamingAssistant(snapshot.timeline)), undispatched = useChat((snapshot) => undispatchedCalls(snapshot), sameUndispatchedCalls), settledMutation = useChat((snapshot) => latestSettledMutation(snapshot)), settledMutationTurn = useChat((snapshot) => latestSettledMutationTurn(snapshot)), liveTurn = useChat((snapshot) => openTurn(snapshot)), workbench = useStore((memory) => memory.workbench), gamePane = useStore((memory) => memory.gamePane), videoPane = useStore((memory) => memory.videoPane), sessionRunning = useSession((snapshot) => snapshot.running), inboxRows = useProjection("inbox", (inbox) => inbox?.["next-turn"]), pendingSubmissions = useSession((snapshot) => snapshot.pendingSubmissions), productionQueue = (0, import_react3.useMemo)(() => productionQueueFromInbox(
4249
+ inboxRows,
4250
+ new Set(pendingSubmissions.filter((item) => item.placement === "transcript").map((item) => item.requestId))
4251
+ ), [inboxRows, pendingSubmissions]), chat = useChat((snapshot) => snapshot), productionIntents = (0, import_react3.useMemo)(() => settledProductionIntents(chat), [chat]), { workspace, error, loading: workspaceLoading, reload } = useWorkspace(sessionId), chosenPreference = useStore((memory) => memory.workbenchPreference), creativeProject = hasCreativeProject(workspace), welcome = useSessions((state) => state.byId[sessionId]?.blank === !0) && workspace !== void 0 && !workspaceLoading && !creativeProject, storedPreference = (0, import_react3.useMemo)(
4108
4252
  () => readWorkbenchPreference(workbenchPreferenceStorage(), workspace?.cwd),
4109
4253
  [workspace?.cwd]
4110
4254
  ), open = resolveWorkbenchOpen(chosenPreference ?? storedPreference, creativeProject);
@@ -4112,7 +4256,9 @@ function CreativeSplitBridge({ sessionId, useSession, useChat, useStore, actions
4112
4256
  let document = marker.current?.ownerDocument;
4113
4257
  if (document === void 0) return;
4114
4258
  let locate = () => {
4115
- let anchor = document.querySelector("[data-conversation-scroll] > [data-slot='conversation.session']");
4259
+ let anchor = document.querySelector(
4260
+ `[data-conversation-content][data-conversation-session="${CSS.escape(sessionId)}"]:not([data-sidebar-chat] *) > [data-conversation-scroll] > [data-slot='conversation.session']`
4261
+ );
4116
4262
  setTarget((current) => current === anchor ? current : anchor ?? void 0);
4117
4263
  };
4118
4264
  locate();
@@ -4147,7 +4293,7 @@ function CreativeSplitBridge({ sessionId, useSession, useChat, useStore, actions
4147
4293
  let compactAt = workbench === "game" || workbench === "video" ? 720 : 620, mediumAt = workbench === "game" || workbench === "video" ? 960 : 900, layout = scroller.clientWidth < compactAt ? "compact" : scroller.clientWidth < mediumAt ? "medium" : "wide";
4148
4294
  scroller.dataset.ohStoryLayout !== layout && (scroller.dataset.ohStoryLayout = layout), parked && (scroller.scrollTop = scroller.scrollHeight - scroller.clientHeight);
4149
4295
  }, observer = new ResizeObserver(publishLayout), observed = /* @__PURE__ */ new WeakSet(), flowObserved = !1, observePanes = () => {
4150
- let flow = scroller.querySelector("[data-chat-flow]");
4296
+ let flow = scroller.querySelector("[data-chat-flow]:not([data-step-process-content])");
4151
4297
  flowObserved = flow !== null;
4152
4298
  for (let pane of [composerSeat(), flow])
4153
4299
  pane === null || observed.has(pane) || (observed.add(pane), observer.observe(pane));
@@ -4177,7 +4323,10 @@ function CreativeSplitBridge({ sessionId, useSession, useChat, useStore, actions
4177
4323
  sessionId,
4178
4324
  runningCalls,
4179
4325
  partial,
4326
+ undispatched: sessionRunning ? undispatched : NO_UNDISPATCHED_CALLS,
4180
4327
  settledMutation,
4328
+ settledMutationTurn,
4329
+ liveTurn,
4181
4330
  sessionRunning,
4182
4331
  productionQueue,
4183
4332
  productionIntents,
@@ -4187,6 +4336,7 @@ function CreativeSplitBridge({ sessionId, useSession, useChat, useStore, actions
4187
4336
  reload,
4188
4337
  open,
4189
4338
  creativeProject,
4339
+ welcome,
4190
4340
  sendProductionPrompt,
4191
4341
  cancelProduction,
4192
4342
  removeQueuedProduction,
@@ -4196,13 +4346,36 @@ function CreativeSplitBridge({ sessionId, useSession, useChat, useStore, actions
4196
4346
  ), target)
4197
4347
  ] });
4198
4348
  }
4349
+ function WelcomeGuide() {
4350
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("section", { className: "oh-story-welcome", "aria-label": "Oh Story \u4F7F\u7528\u5F15\u5BFC", children: [
4351
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("style", { children: plugin_default }),
4352
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("h2", { children: "Oh Story \u5DF2\u52A0\u8F7D" }),
4353
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { children: "\u4F5C\u54C1\u76EE\u5F55\u4E2D\u6709\u521B\u4F5C\u6587\u4EF6\u65F6\uFF0C\u5C0F\u8BF4\u3001\u77ED\u5267\u3001\u6E38\u620F\u3001\u89C6\u9891\u5DE5\u4F5C\u53F0\u4F1A\u81EA\u52A8\u663E\u793A\u3002" }),
4354
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("ol", { children: [
4355
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("li", { children: "\u70B9\u51FB\u5DE6\u4FA7\u300C\u5DE5\u4F5C\u533A / Workspaces\u300D\u65C1\u7684\u300C\u6DFB\u52A0\u5DE5\u4F5C\u533A / Add workspace\u300D\uFF0C\u9009\u62E9\u5B58\u653E\u4F5C\u54C1\u7684\u6587\u4EF6\u5939\u3002" }),
4356
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("li", { children: "\u5728\u4E0B\u65B9\u300C\u9009\u62E9\u5DE5\u4F5C\u533A / Choose workspace\u300D\u4E2D\u9009\u4E2D\u8BE5\u76EE\u5F55\uFF0C\u6216\u6253\u5F00\u5DF2\u6709\u4F1A\u8BDD\u3002" }),
4357
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("li", { children: "\u7A7A\u76EE\u5F55\uFF08\u5305\u62EC DSH \u81EA\u52A8\u5EFA\u7ACB\u7684\u300C\u9ED8\u8BA4\u5DE5\u4F5C\u533A / Default workspace\u300D\uFF09\u5148\u5728 Chat \u4E2D\u5F00\u59CB\u521B\u4F5C\uFF0C\u751F\u6210\u7B2C\u4E00\u4E2A\u521B\u4F5C\u6587\u4EF6\u540E\uFF0C\u5DE5\u4F5C\u53F0\u4F1A\u81EA\u52A8\u51FA\u73B0\u3002" })
4358
+ ] }),
4359
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("p", { children: [
4360
+ "\u67E5\u770B\u5DF2\u6709\u4F5C\u54C1\u65E0\u9700 API Key\u3002\u5F00\u59CB AI \u521B\u4F5C\u524D\uFF0C\u5728\u300C\u8BBE\u7F6E \u2192 \u6A21\u578B\u300D\u914D\u7F6E\u6A21\u578B\uFF0C\u518D\u8F93\u5165 ",
4361
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("code", { children: "/story" }),
4362
+ "\u3001",
4363
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("code", { children: "/short-drama" }),
4364
+ "\u3001",
4365
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("code", { children: "/novel-to-game quick" }),
4366
+ " \u6216 ",
4367
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("code", { children: "/video-recap" }),
4368
+ "\u3002"
4369
+ ] })
4370
+ ] });
4371
+ }
4199
4372
  function WorkbenchWelcome() {
4200
4373
  let marker = (0, import_react3.useRef)(null), [target, setTarget] = (0, import_react3.useState)();
4201
4374
  return (0, import_react3.useLayoutEffect)(() => {
4202
4375
  let document = marker.current?.ownerDocument;
4203
4376
  if (document === void 0) return;
4204
4377
  let locate = () => {
4205
- let anchor = document.querySelector("[data-conversation-scroll]");
4378
+ let anchor = document.querySelector("[data-conversation-content]:not([data-sidebar-chat] *) > [data-conversation-scroll]");
4206
4379
  setTarget((current) => current === anchor ? current : anchor ?? void 0);
4207
4380
  };
4208
4381
  locate();
@@ -4211,35 +4384,15 @@ function WorkbenchWelcome() {
4211
4384
  observer.disconnect();
4212
4385
  };
4213
4386
  }, []), /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
4214
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("style", { children: plugin_default }),
4215
4387
  /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { ref: marker, className: "oh-story-bridge-marker", "aria-hidden": !0 }),
4216
- target === void 0 ? null : (0, import_react_dom.createPortal)(/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("section", { className: "oh-story-welcome", "aria-label": "Oh Story \u4F7F\u7528\u5F15\u5BFC", children: [
4217
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("h2", { children: "Oh Story \u5DF2\u52A0\u8F7D" }),
4218
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { children: "\u4F5C\u54C1\u76EE\u5F55\u4E2D\u6709\u521B\u4F5C\u6587\u4EF6\u65F6\uFF0C\u5C0F\u8BF4\u3001\u77ED\u5267\u3001\u6E38\u620F\u3001\u89C6\u9891\u5DE5\u4F5C\u53F0\u4F1A\u81EA\u52A8\u663E\u793A\u3002" }),
4219
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("ol", { children: [
4220
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("li", { children: "\u70B9\u51FB\u5DE6\u4FA7\u300C\u6DFB\u52A0\u5DE5\u4F5C\u533A / Add workspace\u300D\u7684 \uFF0B\uFF0C\u9009\u62E9\u5B58\u653E\u4F5C\u54C1\u7684\u6587\u4EF6\u5939\u3002" }),
4221
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("li", { children: "\u5728\u4E0B\u65B9\u300C\u9009\u62E9\u5DE5\u4F5C\u533A / Choose workspace\u300D\u4E2D\u9009\u4E2D\u8BE5\u76EE\u5F55\uFF0C\u6216\u6253\u5F00\u5DF2\u6709\u4F1A\u8BDD\u3002" }),
4222
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("li", { children: "\u7A7A\u76EE\u5F55\u5148\u5728 Chat \u4E2D\u5F00\u59CB\u521B\u4F5C\uFF0C\u751F\u6210\u7B2C\u4E00\u4E2A\u521B\u4F5C\u6587\u4EF6\u540E\uFF0C\u5DE5\u4F5C\u53F0\u4F1A\u81EA\u52A8\u51FA\u73B0\u3002" })
4223
- ] }),
4224
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("p", { children: [
4225
- "\u67E5\u770B\u5DF2\u6709\u4F5C\u54C1\u65E0\u9700 API Key\u3002\u5F00\u59CB AI \u521B\u4F5C\u524D\uFF0C\u5728\u300C\u8BBE\u7F6E \u2192 \u6A21\u578B\u300D\u914D\u7F6E\u6A21\u578B\uFF0C\u518D\u8F93\u5165 ",
4226
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("code", { children: "/story" }),
4227
- "\u3001",
4228
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("code", { children: "/short-drama" }),
4229
- "\u3001",
4230
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("code", { children: "/novel-to-game quick" }),
4231
- " \u6216 ",
4232
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("code", { children: "/video-recap" }),
4233
- "\u3002"
4234
- ] })
4235
- ] }), target)
4388
+ target === void 0 ? null : (0, import_react_dom.createPortal)(/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(WelcomeGuide, {}), target)
4236
4389
  ] });
4237
4390
  }
4238
4391
  function WorkbenchSeat({ SessionProvider, renderSlot }) {
4239
4392
  return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(SessionProvider, { empty: () => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(WorkbenchWelcome, {}), children: renderSlot("oh-story.workspace", {}) });
4240
4393
  }
4241
4394
  function argsOf(block) {
4242
- let raw = ("kind" in block ? block.call?.argsRaw : block.argsRaw) ?? "{}";
4395
+ let raw = ("kind" in block ? block.call?.argsRaw : block.phase === "start" ? block.argsRaw : void 0) ?? "{}";
4243
4396
  try {
4244
4397
  let value = JSON.parse(raw);
4245
4398
  return typeof value == "object" && value !== null && !Array.isArray(value) ? value : {};