@oh-story/dsh 0.1.9 → 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 (197) hide show
  1. package/README.md +12 -12
  2. package/lib/client.js +204 -72
  3. package/lib/client.js.map +3 -3
  4. package/lib/drama/manifest.json +84 -74
  5. package/lib/drama/skills/short-drama/SKILL.md +2 -2
  6. package/lib/drama/skills/short-drama/scripts/creator_markdown_check.py +14 -0
  7. package/lib/drama/skills/short-drama-assets/references/character-and-look.md +10 -0
  8. package/lib/drama/skills/short-drama-assets/references/continuity-lock.md +6 -9
  9. package/lib/drama/skills/short-drama-assets/references/voice-direction.md +28 -0
  10. package/lib/drama/skills/short-drama-edit/SKILL.md +27 -29
  11. package/lib/drama/skills/short-drama-edit/assets//345/211/252/350/276/221/345/215/225.md +2 -2
  12. package/lib/drama/skills/short-drama-edit/references/cut-craft.md +24 -67
  13. package/lib/drama/skills/short-drama-edit/references/delivery-verify.md +27 -56
  14. package/lib/drama/skills/short-drama-edit/references/generated-footage.md +37 -79
  15. package/lib/drama/skills/short-drama-edit/references/sound-and-subtitles.md +39 -92
  16. package/lib/drama/skills/short-drama-edit/references/stage-contract.md +12 -16
  17. package/lib/drama/skills/short-drama-edit/scripts/edit_tool.py +126 -11
  18. package/lib/drama/skills/short-drama-edit/scripts/selftest.py +64 -0
  19. package/lib/drama/skills/short-drama-image-prompts/SKILL.md +2 -0
  20. package/lib/drama/skills/short-drama-image-prompts/references/common-recipe.md +11 -0
  21. package/lib/drama/skills/short-drama-produce/SKILL.md +5 -1
  22. package/lib/drama/skills/short-drama-produce/references/adapter-contract.md +14 -20
  23. package/lib/drama/skills/short-drama-produce/references/providers/minimax-h3-video.md +8 -26
  24. package/lib/drama/skills/short-drama-produce/references/providers/minimax-speech.md +41 -0
  25. package/lib/drama/skills/short-drama-produce/scripts/provider_adapters.py +142 -1
  26. package/lib/drama/skills/short-drama-review/SKILL.md +2 -3
  27. package/lib/drama/skills/short-drama-review/references/production-quality-gates.md +6 -19
  28. package/lib/drama/skills/short-drama-review/references/rubric-visual-motion.md +9 -35
  29. package/lib/drama/skills/short-drama-storyboard/SKILL.md +10 -6
  30. package/lib/drama/skills/short-drama-storyboard/references/lighting-craft.md +39 -0
  31. package/lib/drama/skills/short-drama-storyboard/references/shot-craft.md +58 -21
  32. package/lib/drama/skills/short-drama-storyboard/references/stage-contract.md +1 -1
  33. package/lib/drama/skills/short-drama-video-prompts/SKILL.md +10 -9
  34. package/lib/drama/skills/short-drama-video-prompts/references/camera-audio-continuity.md +17 -0
  35. package/lib/drama/skills/short-drama-video-prompts/references/minimax-h3.md +12 -38
  36. package/lib/drama/skills/short-drama-video-prompts/references/motion-recipe.md +4 -7
  37. package/lib/drama/skills/short-drama-video-prompts/references/performance-action-timing.md +8 -22
  38. package/lib/drama/skills/short-drama-video-prompts/references/production-prompt-grammar.md +6 -19
  39. package/lib/drama/skills/short-drama-video-prompts/references/seedance-2.0.md +2 -3
  40. package/lib/drama/skills/short-drama-video-prompts/references/seedance-2.5.md +34 -9
  41. package/lib/drama/skills/short-drama-video-prompts/references/stage-contract.md +2 -2
  42. package/lib/drama/skills/short-drama-write/SKILL.md +2 -4
  43. package/lib/index.js +289 -91
  44. package/lib/index.js.map +4 -4
  45. package/lib/novel-to-game/README.md +299 -59
  46. package/lib/novel-to-game/README_ZH.md +299 -56
  47. package/lib/novel-to-game/VERSION +1 -1
  48. package/lib/novel-to-game/examples/jin-ping-mei/build/BUILD_BRIEF.md +3 -1
  49. package/lib/novel-to-game/examples/jin-ping-mei/build/app/RUN.md +11 -3
  50. package/lib/novel-to-game/examples/jin-ping-mei/build/app/css/new-guofeng.css +397 -8
  51. package/lib/novel-to-game/examples/jin-ping-mei/build/app/css/style.css +0 -31
  52. package/lib/novel-to-game/examples/jin-ping-mei/build/app/js/data.js +71 -73
  53. package/lib/novel-to-game/examples/jin-ping-mei/build/app/js/engine.js +78 -89
  54. package/lib/novel-to-game/examples/jin-ping-mei/build/app/js/main.js +37 -14
  55. package/lib/novel-to-game/examples/jin-ping-mei/build/app/js/text.js +5 -5
  56. package/lib/novel-to-game/examples/jin-ping-mei/build/app/package.json +2 -1
  57. package/lib/novel-to-game/examples/jin-ping-mei/qa/README.md +11 -16
  58. package/lib/novel-to-game/examples/jin-ping-mei/qa/verification.json +11 -11
  59. package/lib/novel-to-game/examples/jin-ping-mei/qa/verify_playable_model.mjs +23 -0
  60. package/lib/novel-to-game/manifest.json +77 -87
  61. package/lib/novel-to-game/skills/game-art-direction/SKILL.md +7 -12
  62. package/lib/novel-to-game/skills/game-art-direction/references/art-direction-method.md +27 -106
  63. package/lib/novel-to-game/skills/game-build/SKILL.md +13 -14
  64. package/lib/novel-to-game/skills/game-build/references/blender-asset-workflow.md +24 -0
  65. package/lib/novel-to-game/skills/game-build/references/build-brief-contract.md +45 -82
  66. package/lib/novel-to-game/skills/game-build/references/generative-media-pipeline.md +14 -45
  67. package/lib/novel-to-game/skills/game-build/references/playable-model-contract.md +30 -65
  68. package/lib/novel-to-game/skills/game-build/references/tts-production-contract.md +13 -27
  69. package/lib/novel-to-game/skills/game-concept/SKILL.md +13 -15
  70. package/lib/novel-to-game/skills/game-concept/references/concept-method.md +28 -75
  71. package/lib/novel-to-game/skills/game-qa/SKILL.md +6 -7
  72. package/lib/novel-to-game/skills/game-qa/references/test-design-method.md +9 -5
  73. package/lib/novel-to-game/skills/game-world-design/SKILL.md +12 -16
  74. package/lib/novel-to-game/skills/game-world-design/references/narrative-design-method.md +23 -72
  75. package/lib/novel-to-game/skills/game-world-design/references/numeric-design-method.md +14 -48
  76. package/lib/novel-to-game/skills/game-world-design/references/world-design-method.md +36 -103
  77. package/lib/novel-to-game/skills/novel-game-analyze/SKILL.md +4 -10
  78. package/lib/novel-to-game/skills/novel-game-analyze/references/gameability-protocol.md +4 -4
  79. package/lib/novel-to-game/skills/novel-to-game/SKILL.md +9 -21
  80. package/lib/novel-to-game/skills/novel-to-game/references/intake-method.md +5 -4
  81. package/lib/novel-to-game/skills/novel-to-game/references/pipeline-contract.md +5 -8
  82. package/lib/oh-story/manifest.json +230 -185
  83. package/lib/oh-story/roles/chapter-extractor.md +177 -237
  84. package/lib/oh-story/roles/consistency-checker.md +4 -4
  85. package/lib/oh-story/roles/narrative-writer.md +24 -25
  86. package/lib/oh-story/roles/story-architect.md +5 -5
  87. package/lib/oh-story/roles/story-explorer.md +11 -11
  88. package/lib/oh-story/skills/story/SKILL.md +13 -7
  89. package/lib/oh-story/skills/story/VERSION +1 -1
  90. package/lib/oh-story/skills/story/references/author-memory.md +54 -24
  91. package/lib/oh-story/skills/story/scripts/author_memory_commit.py +934 -170
  92. package/lib/oh-story/skills/story-cover/SKILL.md +10 -1
  93. package/lib/oh-story/skills/story-deslop/SKILL.md +40 -53
  94. package/lib/oh-story/skills/story-deslop/references/anti-ai-writing.md +11 -10
  95. package/lib/oh-story/skills/story-deslop/references/author-memory.md +54 -24
  96. package/lib/oh-story/skills/story-deslop/references/deslop-gates.md +1 -1
  97. package/lib/oh-story/skills/story-deslop/scripts/author_memory_commit.py +934 -170
  98. package/lib/oh-story/skills/story-import/SKILL.md +77 -81
  99. package/lib/oh-story/skills/story-import/references/character-state-reverse.md +1 -1
  100. package/lib/oh-story/skills/story-import/references/state-tracking.md +4 -69
  101. package/lib/oh-story/skills/story-import/references/structure-mapping-long.md +10 -8
  102. package/lib/oh-story/skills/story-import/references/tracking-transaction.md +8 -6
  103. package/lib/oh-story/skills/story-import/scripts/check-outline-contract.js +34 -16
  104. package/lib/oh-story/skills/story-import/scripts/tracking_commit.py +210 -2
  105. package/lib/oh-story/skills/story-import/scripts/wordcount_core.py +3 -0
  106. package/lib/oh-story/skills/story-long-analyze/SKILL.md +91 -258
  107. package/lib/oh-story/skills/story-long-analyze/references/author-facing.md +245 -0
  108. package/lib/oh-story/skills/story-long-analyze/references/deconstruction-notes.md +2 -2
  109. package/lib/oh-story/skills/story-long-analyze/references/inspiration-library.md +105 -0
  110. package/lib/oh-story/skills/story-long-analyze/references/material-decomposition.md +113 -105
  111. package/lib/oh-story/skills/story-long-analyze/references/output-templates.md +169 -125
  112. package/lib/oh-story/skills/story-long-analyze/references/pipeline-ops.md +172 -64
  113. package/lib/oh-story/skills/story-long-analyze/references/semantic-acceptance-fixtures.md +84 -0
  114. package/lib/oh-story/skills/story-long-analyze/references/style-profile-generator.md +42 -132
  115. package/lib/oh-story/skills/story-long-analyze/references/style-profile-protocol.md +5 -5
  116. package/lib/oh-story/skills/story-long-analyze/scripts/build_chapter_index.py +466 -0
  117. package/lib/oh-story/skills/story-long-analyze/scripts/inspect_existing_assets.py +702 -0
  118. package/lib/oh-story/skills/story-long-analyze/scripts/inspiration_index.py +864 -0
  119. package/lib/oh-story/skills/story-long-analyze/scripts/manage_analysis_run.py +1106 -0
  120. package/lib/oh-story/skills/story-long-analyze/scripts/render_relation_chart.py +425 -0
  121. package/lib/oh-story/skills/story-long-scan/SKILL.md +4 -1
  122. package/lib/oh-story/skills/story-long-write/SKILL.md +38 -29
  123. package/lib/oh-story/skills/story-long-write/references/anti-ai-writing.md +11 -10
  124. package/lib/oh-story/skills/story-long-write/references/artifact-protocols.md +25 -20
  125. package/lib/oh-story/skills/story-long-write/references/author-memory.md +54 -24
  126. package/lib/oh-story/skills/story-long-write/references/benchmark-recall.md +3 -3
  127. package/lib/oh-story/skills/story-long-write/references/cross-book-recall.md +26 -0
  128. package/lib/oh-story/skills/story-long-write/references/dialogue-mastery.md +4 -0
  129. package/lib/oh-story/skills/story-long-write/references/emotional-methods.md +2 -2
  130. package/lib/oh-story/skills/story-long-write/references/long-chapter-quality.md +4 -13
  131. package/lib/oh-story/skills/story-long-write/references/outline-structure-theory.md +1 -1
  132. package/lib/oh-story/skills/story-long-write/references/project-files.md +9 -7
  133. package/lib/oh-story/skills/story-long-write/references/reader-contract-and-progression.md +12 -4
  134. package/lib/oh-story/skills/story-long-write/references/reference-index.md +1 -2
  135. package/lib/oh-story/skills/story-long-write/references/tracking-transaction.md +8 -6
  136. package/lib/oh-story/skills/story-long-write/references/workflow-chapter.md +86 -115
  137. package/lib/oh-story/skills/story-long-write/references/workflow-daily.md +55 -120
  138. package/lib/oh-story/skills/story-long-write/references/workflow-revision.md +15 -11
  139. package/lib/oh-story/skills/story-long-write/references/workflow-setup.md +66 -68
  140. package/lib/oh-story/skills/story-long-write/references/writer-prompt-fallback.md +3 -3
  141. package/lib/oh-story/skills/story-long-write/references/writing-craft.md +4 -12
  142. package/lib/oh-story/skills/story-long-write/scripts/author_memory_commit.py +934 -170
  143. package/lib/oh-story/skills/story-long-write/scripts/build_writer_prompt.py +139 -18
  144. package/lib/oh-story/skills/story-long-write/scripts/check-outline-contract.js +34 -16
  145. package/lib/oh-story/skills/story-long-write/scripts/outline_view.py +5 -3
  146. package/lib/oh-story/skills/story-long-write/scripts/storyctl.py +58 -0
  147. package/lib/oh-story/skills/story-long-write/scripts/tracking_commit.py +210 -2
  148. package/lib/oh-story/skills/story-long-write/scripts/wordcount_core.py +3 -0
  149. package/lib/oh-story/skills/story-review/SKILL.md +68 -85
  150. package/lib/oh-story/skills/story-review/references/anti-ai-writing.md +11 -10
  151. package/lib/oh-story/skills/story-review/references/author-memory.md +54 -24
  152. package/lib/oh-story/skills/story-review/references/dialogue-mastery.md +4 -0
  153. package/lib/oh-story/skills/story-review/references/review-quality.md +4 -10
  154. package/lib/oh-story/skills/story-review/references/tracking-transaction.md +8 -6
  155. package/lib/oh-story/skills/story-review/scripts/author_memory_commit.py +934 -170
  156. package/lib/oh-story/skills/story-review/scripts/tracking_commit.py +210 -2
  157. package/lib/oh-story/skills/story-review/scripts/wordcount_core.py +3 -0
  158. package/lib/oh-story/skills/story-setup/SKILL.md +50 -42
  159. package/lib/oh-story/skills/story-setup/references/agent-references/anti-ai-writing.md +11 -10
  160. package/lib/oh-story/skills/story-setup/references/agent-references/deslop-gates.md +1 -1
  161. package/lib/oh-story/skills/story-setup/references/agent-references/dialogue-mastery.md +4 -0
  162. package/lib/oh-story/skills/story-setup/references/agent-references/long-emotional-methods.md +2 -2
  163. package/lib/oh-story/skills/story-setup/references/agent-references/long-quality.md +1 -1
  164. package/lib/oh-story/skills/story-setup/references/agent-references/writing-craft.md +4 -12
  165. package/lib/oh-story/skills/story-setup/references/diagnostics.md +1 -1
  166. package/lib/oh-story/skills/story-short-analyze/SKILL.md +22 -3
  167. package/lib/oh-story/skills/story-short-analyze/references/material-decomposition.md +5 -1
  168. package/lib/oh-story/skills/story-short-scan/SKILL.md +5 -1
  169. package/lib/oh-story/skills/story-short-write/SKILL.md +6 -147
  170. package/lib/oh-story/skills/story-short-write/references/author-memory.md +54 -24
  171. package/lib/oh-story/skills/story-short-write/references/dialogue-mastery.md +4 -0
  172. package/lib/oh-story/skills/story-short-write/references/reference-index.md +2 -0
  173. package/lib/oh-story/skills/story-short-write/references/workflow-design.md +3 -2
  174. package/lib/oh-story/skills/story-short-write/references/workflow-draft.md +126 -0
  175. package/lib/oh-story/skills/story-short-write/references/workflow-revision.md +32 -0
  176. package/lib/oh-story/skills/story-short-write/scripts/author_memory_commit.py +934 -170
  177. package/lib/types/client/drama-production-view.d.ts.map +1 -1
  178. package/lib/types/client/file-activity.d.ts +19 -1
  179. package/lib/types/client/file-activity.d.ts.map +1 -1
  180. package/lib/types/client/index.d.ts.map +1 -1
  181. package/lib/types/client/production-prompts.d.ts +7 -0
  182. package/lib/types/client/production-prompts.d.ts.map +1 -1
  183. package/lib/types/client/production-runtime.d.ts +16 -0
  184. package/lib/types/client/production-runtime.d.ts.map +1 -1
  185. package/lib/types/drama-adapters.d.ts +5 -3
  186. package/lib/types/drama-adapters.d.ts.map +1 -1
  187. package/lib/types/native-hooks.d.ts +52 -0
  188. package/lib/types/native-hooks.d.ts.map +1 -1
  189. package/lib/types/role-identity.d.ts +17 -0
  190. package/lib/types/role-identity.d.ts.map +1 -0
  191. package/lib/types/role-tool.d.ts.map +1 -1
  192. package/lib/types/skill-provider.d.ts.map +1 -1
  193. package/package.json +45 -45
  194. package/lib/novel-to-game/skills/game-world-design/references/dialogue-design-method.md +0 -58
  195. package/lib/novel-to-game/skills/game-world-design/references/game-writing-craft.md +0 -53
  196. package/lib/novel-to-game/skills/novel-to-game/references/intake-benchmark-reference.md +0 -38
  197. 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,6 +857,8 @@ ${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) {
@@ -826,10 +873,34 @@ ${orderedPaths.map((path, index) => `${String(index + 1)}. ${path}`).join(`
826
873
  - \u526A\u8F91\u5355\uFF1A${production.episodeDirectory}/\u526A\u8F91\u5355.md
827
874
  - \u8F93\u51FA\uFF1A${production.episodeDirectory}/\u5236\u4F5C\u6210\u679C/\u6210\u7247/
828
875
 
829
- \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\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\u7F3A\u5931\u6216\u4E0D\u53EF\u7528\u7684\u7D20\u6750\u5199\u8FDB\u300C\u672A\u91C7\u7528\u955C\u5934\u300D\u5E76\u8BF4\u660E\u5C5E\u4E8E\u54EA\u4E00\u7C7B\uFF0C\u4E0D\u8981\u9000\u56DE\u53BB\u751F\u6210\u65B0\u7D20\u6750\uFF0C\u4E5F\u4E0D\u8981\u6539\u52A8\u5267\u672C\u3001\u5206\u955C\u6216\u89C6\u9891\u63D0\u793A\u8BCD\u7684\u8BED\u4E49\u3002\u5B57\u5E55\u9ED8\u8BA4\u8D70\u96F6\u4F9D\u8D56\u7684 ffmpeg \u8DEF\u7EBF\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\u3002ffmpeg \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`;
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
879
+
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`;
830
885
  }
831
886
 
832
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
+ }
833
904
  function createPendingJob(input) {
834
905
  return {
835
906
  id: input.id,
@@ -848,7 +919,9 @@ function selectedVersionForTarget(targetId, versions, selections, kind) {
848
919
  let candidates = versions.filter((version) => version.targetId === targetId && (kind === void 0 || version.kind === kind));
849
920
  return candidates.find((version) => version.id === selections[targetId]) ?? candidates.at(-1);
850
921
  }
922
+ var EDIT_OUTPUT_DIRECTORY = /(?:^|\/)制作成果\/成片\//u;
851
923
  function mediaTargetFromPath(path, knownTargets) {
924
+ if (EDIT_OUTPUT_DIRECTORY.test(path)) return;
852
925
  let segments = path.toLocaleUpperCase().split("/"), filename = segments.at(-1) ?? "";
853
926
  return [...knownTargets].sort((left, right) => right.length - left.length).find((target) => {
854
927
  let canonical = target.toLocaleUpperCase();
@@ -868,6 +941,9 @@ function outputsForJob(job, versions) {
868
941
  function compositionInFlight(jobs) {
869
942
  return jobs.some((job) => job.kind === "composition" && (job.status === "awaiting_confirmation" || job.status === "pending" || job.status === "running"));
870
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
+ }
871
947
  function referencesForTarget(targetId, production, versions, selections, libraryVersions = versions, manualReferences = {}) {
872
948
  let shot = production.shots.find((item) => item.id === targetId);
873
949
  if (shot === void 0) return [];
@@ -890,8 +966,7 @@ function activeProductionJobId(jobs, queue, sessionRunning) {
890
966
  return [...jobs].reverse().find((job) => (job.status === "awaiting_confirmation" || job.status === "pending" || job.status === "running") && queuedItemForJob(job.id, queue) === void 0)?.id;
891
967
  }
892
968
  function reconcileProductionJobs(jobs, queue, sessionRunning, versions) {
893
- let latestPending = [...jobs].reverse().find((job) => job.status === "pending" && queuedItemForJob(job.id, queue) === void 0);
894
- return jobs.map((job) => {
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) => {
895
970
  let queued = queuedItemForJob(job.id, queue) !== void 0;
896
971
  if (job.status === "canceled" || job.status === "succeeded" || job.status === "failed" && job.outputPath !== void 0) return job;
897
972
  let outputs = outputsForJob(job, versions);
@@ -907,7 +982,9 @@ function reconcileProductionJobs(jobs, queue, sessionRunning, versions) {
907
982
  status: "dispatched_unknown",
908
983
  progress: Math.round(outputs.length / job.expectedOutputs * 100),
909
984
  completedOutputs: outputs.length,
910
- 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"
911
988
  } : outputs.length > 0 ? {
912
989
  ...job,
913
990
  status: job.status === "failed" ? "failed" : "running",
@@ -916,6 +993,7 @@ function reconcileProductionJobs(jobs, queue, sessionRunning, versions) {
916
993
  error: job.status === "failed" ? job.error : void 0
917
994
  } : job;
918
995
  });
996
+ return settleCompositions(reconciled);
919
997
  }
920
998
  function reconcileSequence(shotIds, current, versions, selections) {
921
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 }));
@@ -940,7 +1018,7 @@ function reorderSequence(sequence, source, target) {
940
1018
  }
941
1019
 
942
1020
  // src/client/drama-production-view.tsx
943
- 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", 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" };
944
1022
  function ProductionEnvironment({ sessionId }) {
945
1023
  let [preflight, setPreflight] = (0, import_react.useState)(), [attempt, setAttempt] = (0, import_react.useState)(0);
946
1024
  (0, import_react.useEffect)(() => {
@@ -974,7 +1052,7 @@ function ProductionEnvironment({ sessionId }) {
974
1052
  adapter.configured ? "" : ` \xB7 \u7F3A ${adapter.missing.join("\u3001")}`
975
1053
  ] }, adapter.name)),
976
1054
  /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("em", { children: [
977
- "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",
978
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",
979
1057
  " ",
980
1058
  "Adapter \u914D\u7F6E",
@@ -1238,7 +1316,10 @@ function AssetBoard(props) {
1238
1316
  ] })
1239
1317
  ] })
1240
1318
  ] }),
1241
- 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
+ ] }),
1242
1323
  /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "oh-story-media-library-grid", children: library.map((version) => {
1243
1324
  let selected = referenceTarget !== void 0 && (props.manualReferences[referenceTarget] ?? []).includes(version.id);
1244
1325
  return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("article", { children: [
@@ -1249,9 +1330,9 @@ function AssetBoard(props) {
1249
1330
  version.path !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", onClick: () => {
1250
1331
  props.onOpenMedia(version.path);
1251
1332
  }, children: "\u6253\u5F00\u6587\u4EF6" }),
1252
- 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: () => {
1253
1334
  toggleReference(version.id);
1254
- }, children: selected ? "\u5DF2\u5F15\u7528" : "\u4F5C\u4E3A\u53C2\u8003" })
1335
+ }, children: selected ? "\u5DF2\u8BBE\u8865\u5145\u53C2\u8003" : "\u8BBE\u4E3A\u8865\u5145\u53C2\u8003" })
1255
1336
  ] })
1256
1337
  ] }, version.id);
1257
1338
  }) })
@@ -1261,7 +1342,7 @@ function AssetBoard(props) {
1261
1342
  function TaskBoard({ jobs, queue, sessionRunning, onCancel, onRemoveQueued }) {
1262
1343
  let activeJobId = activeProductionJobId(jobs, queue, sessionRunning);
1263
1344
  return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("section", { className: "oh-story-task-board", children: [
1264
- /* @__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" }),
1265
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) => {
1266
1347
  let queued = queuedItemForJob(job.id, queue), displayStatus = queued === void 0 ? STATUS_LABELS[job.status] : "DSH Queue";
1267
1348
  return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("article", { "data-job-id": job.id, "data-status": job.status, children: [
@@ -1905,8 +1986,9 @@ var plugin_default = `.oh-story-bridge-marker { display: none; }
1905
1986
  border-left: 1px solid var(--os-border);
1906
1987
  }
1907
1988
 
1989
+ /* DSH 0.1.7 nests a data-chat-flow inside every step-process group; only the top-level flow needs room. */
1908
1990
  [data-conversation-scroll]:has(> [data-slot="conversation.session"] > .oh-story-split-surface[data-open="true"])
1909
- [data-chat-flow] {
1991
+ [data-chat-flow]:not([data-step-process-content]) {
1910
1992
  padding-bottom: calc(max(var(--dsh-composer-height, 152px), var(--oh-story-composer-height, 0px)) + 16px);
1911
1993
  }
1912
1994
 
@@ -2987,6 +3069,7 @@ var import_jsx_runtime5 = require("react/jsx-runtime"), name = "oh-story", injec
2987
3069
  function applyUpdate(current, update) {
2988
3070
  return typeof update == "function" ? update(current) : update;
2989
3071
  }
3072
+ var workbenchMemoryBySession = /* @__PURE__ */ new Map(), NO_UNDISPATCHED_CALLS = [];
2990
3073
  function createWorkbenchStore() {
2991
3074
  return (0, import_dsh_client_store.defineStore)({
2992
3075
  init: () => ({
@@ -3010,9 +3093,17 @@ function createWorkbenchStore() {
3010
3093
  productionSequence: {},
3011
3094
  productionCanvas: {},
3012
3095
  productionZoom: {},
3013
- productionIntentCalls: {}
3096
+ productionIntentCalls: {},
3097
+ settledMutation: void 0,
3098
+ hydrated: !1
3014
3099
  }),
3015
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
+ },
3016
3107
  setBuffers: (draft, update) => {
3017
3108
  draft.buffers = applyUpdate(draft.buffers, update);
3018
3109
  },
@@ -3400,7 +3491,10 @@ function CreativeWorkbench({
3400
3491
  sessionId,
3401
3492
  runningCalls,
3402
3493
  partial,
3494
+ undispatched,
3403
3495
  settledMutation,
3496
+ settledMutationTurn,
3497
+ liveTurn,
3404
3498
  sessionRunning,
3405
3499
  productionQueue,
3406
3500
  productionIntents,
@@ -3413,18 +3507,21 @@ function CreativeWorkbench({
3413
3507
  reload,
3414
3508
  open,
3415
3509
  creativeProject,
3510
+ welcome,
3416
3511
  useStore,
3417
3512
  actions
3418
3513
  }) {
3419
3514
  let activities = (0, import_react3.useMemo)(
3420
- () => fileMutations(runningCalls, partial),
3421
- [partial, runningCalls]
3515
+ () => fileMutations(runningCalls, partial, undispatched),
3516
+ [partial, runningCalls, undispatched]
3422
3517
  ), normalizedActivities = (0, import_react3.useMemo)(() => activities.flatMap((activity2) => {
3423
3518
  let path = creativeRelativePath(activity2.path, workspace?.cwd);
3424
3519
  return path === void 0 ? [] : [{ activity: activity2, path }];
3425
- }), [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) => {
3426
3521
  setWorkbenchPreference(preference), writeWorkbenchPreference(workbenchPreferenceStorage(), workspace?.cwd, preference);
3427
- }, [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)(
3428
3525
  () => episodeDirectory === void 0 ? [] : creatorDocumentPaths(workspace?.files.filter((file) => file.kind === "text") ?? [], episodeDirectory),
3429
3526
  [episodeDirectory, workspace?.files]
3430
3527
  ), episodeDocuments = (0, import_react3.useMemo)(() => Object.fromEntries(episodeDocumentPaths.flatMap((path) => {
@@ -3592,10 +3689,10 @@ function CreativeWorkbench({
3592
3689
  setBuffers((current) => {
3593
3690
  let changed = !1, next = { ...current };
3594
3691
  for (let [path, value] of Object.entries(current))
3595
- 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));
3596
3693
  return changed ? next : current;
3597
3694
  });
3598
- }, [activityPaths, workspace, workspaceLoading]), (0, import_react3.useEffect)(() => {
3695
+ }, [activityPaths, sessionRunning, settledPath, workspace, workspaceLoading]), (0, import_react3.useEffect)(() => {
3599
3696
  if (selected === void 0 || selectedMedia || activityPaths.has(selected) || !(workspace?.files.some((file) => file.path === selected) ?? !1)) return;
3600
3697
  let controller = new AbortController();
3601
3698
  return setBuffers((current) => {
@@ -3699,11 +3796,16 @@ function CreativeWorkbench({
3699
3796
  signals.has(callId.split(":", 1)[0] ?? callId) || activityBases.current.delete(callId);
3700
3797
  previousSignals.current = signals, settled && reload();
3701
3798
  }, [normalizedActivities, reload, runningCalls]), (0, import_react3.useEffect)(() => {
3702
- if (settledMutation === void 0 || settledMutation === previousSettledMutation.current || workspace?.cwd === void 0) return;
3703
- 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);
3704
3806
  let path = creativeRelativePath(settledMutation.slice(settledMutation.indexOf("\0") + 1), workspace.cwd);
3705
3807
  path !== void 0 && followAgentPath(path), reload();
3706
- }, [followAgentPath, reload, settledMutation, workspace?.cwd]), (0, import_react3.useEffect)(() => {
3808
+ }, [actions, consumedSettledMutation, followAgentPath, reload, settledMutation, settledMutationTurn, workspace?.cwd]), (0, import_react3.useEffect)(() => {
3707
3809
  if (selected !== void 0) {
3708
3810
  for (let button of navRef.current?.querySelectorAll("button[data-file-path]") ?? [])
3709
3811
  if (button.dataset.filePath === selected) {
@@ -4114,7 +4216,7 @@ function CreativeWorkbench({
4114
4216
  )
4115
4217
  ] })
4116
4218
  ] })
4117
- ] }) : !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: [
4118
4220
  /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("style", { children: plugin_default }),
4119
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: () => {
4120
4222
  applyWorkbenchPreference("open");
@@ -4124,8 +4226,29 @@ function CreativeWorkbench({
4124
4226
  ] })
4125
4227
  ] });
4126
4228
  }
4127
- function CreativeSplitBridge({ sessionId, useSession, useChat, useStore, actions, sendProductionPrompt, cancelProduction, removeQueuedProduction }) {
4128
- 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)(
4129
4252
  () => readWorkbenchPreference(workbenchPreferenceStorage(), workspace?.cwd),
4130
4253
  [workspace?.cwd]
4131
4254
  ), open = resolveWorkbenchOpen(chosenPreference ?? storedPreference, creativeProject);
@@ -4133,7 +4256,9 @@ function CreativeSplitBridge({ sessionId, useSession, useChat, useStore, actions
4133
4256
  let document = marker.current?.ownerDocument;
4134
4257
  if (document === void 0) return;
4135
4258
  let locate = () => {
4136
- 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
+ );
4137
4262
  setTarget((current) => current === anchor ? current : anchor ?? void 0);
4138
4263
  };
4139
4264
  locate();
@@ -4168,7 +4293,7 @@ function CreativeSplitBridge({ sessionId, useSession, useChat, useStore, actions
4168
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";
4169
4294
  scroller.dataset.ohStoryLayout !== layout && (scroller.dataset.ohStoryLayout = layout), parked && (scroller.scrollTop = scroller.scrollHeight - scroller.clientHeight);
4170
4295
  }, observer = new ResizeObserver(publishLayout), observed = /* @__PURE__ */ new WeakSet(), flowObserved = !1, observePanes = () => {
4171
- let flow = scroller.querySelector("[data-chat-flow]");
4296
+ let flow = scroller.querySelector("[data-chat-flow]:not([data-step-process-content])");
4172
4297
  flowObserved = flow !== null;
4173
4298
  for (let pane of [composerSeat(), flow])
4174
4299
  pane === null || observed.has(pane) || (observed.add(pane), observer.observe(pane));
@@ -4198,7 +4323,10 @@ function CreativeSplitBridge({ sessionId, useSession, useChat, useStore, actions
4198
4323
  sessionId,
4199
4324
  runningCalls,
4200
4325
  partial,
4326
+ undispatched: sessionRunning ? undispatched : NO_UNDISPATCHED_CALLS,
4201
4327
  settledMutation,
4328
+ settledMutationTurn,
4329
+ liveTurn,
4202
4330
  sessionRunning,
4203
4331
  productionQueue,
4204
4332
  productionIntents,
@@ -4208,6 +4336,7 @@ function CreativeSplitBridge({ sessionId, useSession, useChat, useStore, actions
4208
4336
  reload,
4209
4337
  open,
4210
4338
  creativeProject,
4339
+ welcome,
4211
4340
  sendProductionPrompt,
4212
4341
  cancelProduction,
4213
4342
  removeQueuedProduction,
@@ -4217,13 +4346,36 @@ function CreativeSplitBridge({ sessionId, useSession, useChat, useStore, actions
4217
4346
  ), target)
4218
4347
  ] });
4219
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
+ }
4220
4372
  function WorkbenchWelcome() {
4221
4373
  let marker = (0, import_react3.useRef)(null), [target, setTarget] = (0, import_react3.useState)();
4222
4374
  return (0, import_react3.useLayoutEffect)(() => {
4223
4375
  let document = marker.current?.ownerDocument;
4224
4376
  if (document === void 0) return;
4225
4377
  let locate = () => {
4226
- let anchor = document.querySelector("[data-conversation-scroll]");
4378
+ let anchor = document.querySelector("[data-conversation-content]:not([data-sidebar-chat] *) > [data-conversation-scroll]");
4227
4379
  setTarget((current) => current === anchor ? current : anchor ?? void 0);
4228
4380
  };
4229
4381
  locate();
@@ -4232,35 +4384,15 @@ function WorkbenchWelcome() {
4232
4384
  observer.disconnect();
4233
4385
  };
4234
4386
  }, []), /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
4235
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("style", { children: plugin_default }),
4236
4387
  /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { ref: marker, className: "oh-story-bridge-marker", "aria-hidden": !0 }),
4237
- 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: [
4238
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("h2", { children: "Oh Story \u5DF2\u52A0\u8F7D" }),
4239
- /* @__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" }),
4240
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("ol", { children: [
4241
- /* @__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" }),
4242
- /* @__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" }),
4243
- /* @__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" })
4244
- ] }),
4245
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("p", { children: [
4246
- "\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 ",
4247
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("code", { children: "/story" }),
4248
- "\u3001",
4249
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("code", { children: "/short-drama" }),
4250
- "\u3001",
4251
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("code", { children: "/novel-to-game quick" }),
4252
- " \u6216 ",
4253
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("code", { children: "/video-recap" }),
4254
- "\u3002"
4255
- ] })
4256
- ] }), target)
4388
+ target === void 0 ? null : (0, import_react_dom.createPortal)(/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(WelcomeGuide, {}), target)
4257
4389
  ] });
4258
4390
  }
4259
4391
  function WorkbenchSeat({ SessionProvider, renderSlot }) {
4260
4392
  return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(SessionProvider, { empty: () => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(WorkbenchWelcome, {}), children: renderSlot("oh-story.workspace", {}) });
4261
4393
  }
4262
4394
  function argsOf(block) {
4263
- 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) ?? "{}";
4264
4396
  try {
4265
4397
  let value = JSON.parse(raw);
4266
4398
  return typeof value == "object" && value !== null && !Array.isArray(value) ? value : {};