@oh-story/dsh 0.1.13 → 0.1.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -6
- package/lib/client.js +932 -631
- package/lib/client.js.map +4 -4
- package/lib/index.js +1 -0
- package/lib/index.js.map +2 -2
- package/lib/types/client/canvas-viewport.d.ts +31 -0
- package/lib/types/client/canvas-viewport.d.ts.map +1 -0
- package/lib/types/client/drama-production-view.d.ts +3 -2
- package/lib/types/client/drama-production-view.d.ts.map +1 -1
- package/lib/types/client/index.d.ts.map +1 -1
- package/lib/types/client/production-canvas.d.ts +24 -0
- package/lib/types/client/production-canvas.d.ts.map +1 -0
- package/lib/types/skill-provider.d.ts.map +1 -1
- package/lib/video-recap/CHANGELOG.md +16 -1
- package/lib/video-recap/README.en.md +2 -2
- package/lib/video-recap/README.md +2 -2
- package/lib/video-recap/manifest.json +25 -25
- package/lib/video-recap/skills/video-recap/SKILL.md +4 -2
- package/lib/video-recap/skills/video-recap/references/config-playbook.md +2 -2
- package/lib/video-recap/skills/video-recap/scripts/recap_cli.py +6 -0
- package/lib/video-recap/skills/video-recap/scripts/recap_runner.py +10 -1
- package/lib/video-recap/skills/video-script/SKILL.md +45 -18
- package/lib/video-recap/skills/video-script/scripts/review_runner.py +11 -2
- package/lib/video-recap/skills/video-voiceover/SKILL.md +34 -8
- package/lib/video-recap/skills/video-voiceover/scripts/dub.py +21 -0
- package/package.json +1 -1
package/lib/index.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/index.ts", "../src/skill-provider.ts", "../src/drama-adapters.ts", "../src/host-python.ts", "../src/native-hooks.ts", "../src/role-provider.ts", "../src/role-identity.ts", "../src/role-tool.ts", "../src/reference-tool.ts", "../src/production-tool.ts", "../src/production-intent.ts", "../src/workspace-route.ts", "../src/game-verification.ts", "../src/video-project.ts", "../src/workspace-request-trust.ts"],
|
|
4
|
-
"sourcesContent": ["import type { Context } from \"@deepseek-ai/cordis\";\nimport type {} from \"@deepseek-ai/dsh-host-webserver\";\nimport type {} from \"@deepseek-ai/dsh-skill\";\nimport type {} from \"@deepseek-ai/dsh-subagent\";\nimport type {} from \"@deepseek-ai/dsh-tools\";\nimport z from \"@deepseek-ai/schemastery\";\nimport { createDramaSkillProvider, createNovelToGameSkillProvider, createOhStorySkillProvider, createVideoRecapSkillProvider, defaultDramaSkillRoot } from \"./skill-provider.js\";\nimport { ensureDramaAdapterConfig } from \"./drama-adapters.js\";\nimport { hostPython } from \"./host-python.js\";\nimport { registerOhStoryHooks } from \"./native-hooks.js\";\nimport { registerOhStoryRoleTool } from \"./role-tool.js\";\nimport { registerOhStoryProductionTool } from \"./production-tool.js\";\nimport { registerWorkspaceRoute } from \"./workspace-route.js\";\nimport { assertTrustedWorkspaceAuthority } from \"./workspace-request-trust.js\";\n\nexport { createDramaSkillProvider, createNovelToGameSkillProvider, createOhStorySkillProvider, createVideoRecapSkillProvider, parseBundledSkill } from \"./skill-provider.js\";\nexport { OH_STORY_ROLE_NAMES, loadBundledRole } from \"./role-provider.js\";\nexport { createOhStoryRoleTool, OH_STORY_ROLE_TOOL_NAME, registerOhStoryRoleTool, roleToolFilter, type OhStoryRoleSubagents } from \"./role-tool.js\";\nexport { createOhStoryProductionTool, registerOhStoryProductionTool } from \"./production-tool.js\";\nexport { OH_STORY_PRODUCTION_TOOL_NAME, validateProductionIntent, type ProductionIntentArgs } from \"./production-intent.js\";\nexport { bundledReferenceGuard, createOhStoryReferenceTool, OH_STORY_REFERENCE_TOOL_NAME } from \"./reference-tool.js\";\nexport { registerWorkspaceRoute } from \"./workspace-route.js\";\nexport { registerOhStoryHooks } from \"./native-hooks.js\";\nexport { DRAMA_ADAPTER_CONFIG_ENV, DRAMA_ADAPTERS, dramaAdapterConfigPath, dramaAdapterStatuses, ensureDramaAdapterConfig } from \"./drama-adapters.js\";\n\nexport const name = \"oh-story\";\nexport const inject = [\"skills\", \"subagents\", \"tools\", \"typert\", \"webServer\"];\n\n/** DSH owns models, providers, presets, permissions, roots, runs, and sessions. */\nexport interface Config {\n readonly editorMaxBytes?: number;\n readonly trustedHosts?: string[];\n}\n\nexport const Config = z.object({\n editorMaxBytes: z.natural().min(65_536).max(8_388_608).default(2_097_152),\n trustedHosts: z.array(String).default([])\n}) as z<Config>;\n\n/** Mount only domain contributions into the current DSH process. */\nexport async function apply(context: Context, config: Config = {}): Promise<void> {\n const trustedHosts = config.trustedHosts ?? [];\n for (const entry of trustedHosts) assertTrustedWorkspaceAuthority(entry);\n context.skills.registerProvider(() => createOhStorySkillProvider());\n context.skills.registerProvider(() => createDramaSkillProvider());\n context.skills.registerProvider(() => createNovelToGameSkillProvider());\n context.skills.registerProvider(() => createVideoRecapSkillProvider());\n registerOhStoryHooks(context);\n registerOhStoryProductionTool(context);\n await registerOhStoryRoleTool(context);\n registerWorkspaceRoute(context, { maxBytes: config.editorMaxBytes ?? 2_097_152, trustedHosts });\n // Register the bundled media adapters for this host up front so the first\n // short-drama-produce run has a config to pass; the preflight route repeats\n // this and reports the outcome, so a failure here only delays the message.\n await ensureDramaAdapterConfig(defaultDramaSkillRoot(), { python: (await hostPython()).command });\n}\n\nexport default { name, inject, Config, apply };\n", "import { readdir, readFile } from \"node:fs/promises\";\nimport { basename, dirname, isAbsolute, join, relative, resolve } from \"node:path\";\nimport { dramaAdapterConfigPath, dramaAdapterSummary, DRAMA_ADAPTER_CONFIG_ENV } from \"./drama-adapters.js\";\nimport { fileURLToPath, pathToFileURL } from \"node:url\";\nimport {\n BUNDLED_SKILL_RANK,\n type SkillCandidate,\n type SkillDefinition,\n type SkillProvider\n} from \"@deepseek-ai/dsh-skill\";\n\nconst STORY_PROVIDER_NAME = \"oh-story\";\nconst DRAMA_PROVIDER_NAME = \"short-drama\";\nconst GAME_PROVIDER_NAME = \"novel-to-game\";\nconst VIDEO_PROVIDER_NAME = \"video-recap\";\nconst DSH_SKILL_BRIDGE = [\n \"<oh-story-dsh-integration>\",\n \"This Skill is a native contribution to the current DeepSeek Harness session.\",\n \"DSH owns the workspace, model, preset, permissions, Session Log, tools, subagents, cancellation, resume, and Agent UI.\",\n \"Never start another Agent runtime, session transport, Dashboard, SSE stream, polling loop, or model configuration.\",\n \"All seven upstream Oh Story specialist Roles are bundled. Invoke one with oh_story_role and a self-contained prompt.\",\n \"Never inspect .claude/agents, .codex/agents, .opencode/agents, .agents/agents, .zcode, or .story-deployed to decide whether a Role is available.\",\n \"Oh Story Roles are reached only through oh_story_role. Never start one through a generic subagent or Task tool \u2014 not DSH's subagent or subagent_fork tools and not invoke_subagent \u2014 and never pass a Role name as subagent_type, agent_type, agent, or TypeName, even where the upstream text below describes that for another host.\",\n \"Use only DSH-visible tools. DSH sandbox and permission policy remain authoritative.\",\n // Upstream deploys these \u300C\u4E0E\u4F5C\u8005\u534F\u4F5C\u300D rules only in its CLAUDE.md/AGENTS.md\n // templates, which DSH does not install.\n \"Working with the author: reply and report in the author's writing terms (book, chapter, outline, settings), never in script, field, or state names; attach a raw error only when something failed. A template block marked <!-- author-report --> is only a format reference: output its text directly, without that marker and without a code fence.\",\n \"Record a writing habit or preference the author asks to remember, forget, or confirm only through the story Skill's author memory, whose scripts/author_memory_commit.py writes .story/\u4F5C\u8005\u8BB0\u5FC6/; never keep it in a host or DSH memory. Simply follow a one-off request without recording it.\",\n \"Never edit the bundled Skill files (SKILL.md, references/, scripts/). When a Skill script fails, stop and show the author the command you ran and its error instead of patching or working around it.\",\n \"</oh-story-dsh-integration>\"\n].join(\"\\n\");\n/** Oh Story 0.8.4 long-form analysis Stage 2 (pipeline-ops.md \u00A74), shared by story-long-analyze and story-import. */\nconst DSH_ANALYSIS_BATCHES = [\n \"Stage 2 batches in DSH: dispatch each planned batch with oh_story_role, role chapter-extractor, and a self-contained prompt that copies this batch's plan fields verbatim, prefixing paths with {\u62C6\u6587\u76EE\u5F55}/: batch_id, input_kind, source_files (per-chapter source_locator for a raw batch), chapter_chars, min_plot_points, the output file {\u62C6\u6587\u76EE\u5F55}/_analysis_cache/\u8F93\u5165-{\u6279\u6B21ID}.md, and the plan's handoff_cache when it is not empty.\",\n \"The extractor reads the source itself, writes or edits only that batch input file (DSH denies any other write or edit by a chapter-extractor child), and replies with one receipt line; do not read the file yourself.\",\n \"Commit it with manage_analysis_run.py commit, one commit at a time in this session. When a commit is rejected, dispatch the same batch to a chapter-extractor again with every field above plus the error code, and have it fix only the broken spots with edit (rewriting the whole file only when its structure is broken), then commit again.\",\n \"Run manage_analysis_run.py and the other bundled Python 3 scripts through the current DSH execution world, trying python3, python, then py -3. If none is available, stop and tell the author in plain words that this step needs Python 3 on the machine running DSH; never simulate a script's output or hand-write the files it owns.\",\n \"Keep concurrent oh_story_role calls modest. The default is upstream's \u6709\u9650\u5E76\u884C tier: three batches per round, issued together, the next round only after all three are committed; an unasked, full, multi-book, or import run uses it. DSH runs calls from one step in parallel only up to the host's own limit and may run them one after another, so never promise more. Use \u4E32\u884C or \u4E0D\u9650\u6279\u6B21\u987A\u5E8F only when the author chooses it, and under \u4E0D\u9650\u6279\u6B21\u987A\u5E8F halve the count on any rate limit, timeout, or child error.\"\n].join(\" \");\nconst DSH_SKILL_OVERRIDES: Readonly<Partial<Record<string, string>>> = {\n story: \"The \u5C0F\u8BF4 workspace is an official DSH conversation view. Never start or open a second web application.\",\n \"story-setup\": \"Initialize or validate novel project data only. DSH already supplies Skills, Roles, hooks, tools, permissions, sessions, and UI; never deploy Claude/OpenCode/Codex/Antigravity/ZCode/OpenClaw/Reasonix files or a .story-deployed marker.\",\n \"story-long-analyze\": `Use oh_story_role for chapter extraction or specialist analysis. Never inspect platform agent directories or require a deployed external Agent definition. ${DSH_ANALYSIS_BATCHES}`,\n \"story-long-write\": \"All named Roles are provided through oh_story_role. Do not check platform agent files. Keep the upstream writing, Tracking, lint, outline, revision, and quality workflows. Create and assemble \u6B63\u6587/ chapter files only with the write and edit tools, never through shell redirection, cp, mv, tee, or a script, so that DSH's outline guard, its Tracking reminder, and the \u5C0F\u8BF4 view observe the write; upstream's own in-place chapter fixes such as storyctl.py chapter check --fix-punctuation stay as upstream describes.\",\n \"story-review\": \"All named reviewer Roles are provided through oh_story_role. Do not check platform agent files; full/lean review may use the bundled Roles directly. When a review falls back to solo in DSH, the reason is that oh_story_role or DSH's spawn runtime is unavailable in this Session (Fallback agent tool unavailable -> solo) or a Role run failed (Fallback spawn failed -> solo); say that in one plain sentence. Never tell the author that the reviewers are not installed, missing, or outdated, and never tell them to run /story-setup.\",\n \"story-import\": `All named Roles are provided through oh_story_role. Do not require story-setup to deploy them, never inspect platform agent directories or .story-deployed, and never offer the author Step 4's choice to install a writing environment with /story-setup: in DSH record \u5199\u4F5C\u73AF\u5883 in .story/work/\u5BFC\u5165\u8BB0\u5F55.md as installed, with the analysis helper and story-architect both available. Phase 2 runs the story-long-analyze pipeline the DSH way below; an import counts as automatic continuation, so it uses the limited-parallel tier without asking. ${DSH_ANALYSIS_BATCHES} Run the scripts this Skill needs (build_outline_brief.py, tracking_commit.py init and check with Python 3; check-outline-contract.js with Node) the same way. Keep upstream's order: Phase 3-L Step 2 copies the manuscript into \u6B63\u6587/, Step 10 reverse-builds the \u7EC6\u7EB2 in batches, and Phase 4 initialises Tracking. DSH's prose guard mirrors the outline gate of upstream proseBlockReason for books with \u5927\u7EB2/ or \u8FFD\u8E2A/, so open an import window before Step 2 copies any chapter: create .story/work/\u5BFC\u5165\u4E2D.md in the book directory (the workspace root in DSH's usual single-book layout) with one line naming the book being imported, and delete it right after Phase 4's tracking_commit.py init and check both succeed. The window only holds while \u8FFD\u8E2A/_tracking-state.json is absent. \u5BFC\u5165\u4E2D.md is DSH's own marker; keep upstream's \u5BFC\u5165\u8BB0\u5F55.md exactly as the Skill describes.`,\n \"story-deslop\": \"Use the bundled narrative-writer Role through oh_story_role when specialist review is useful. Never inspect platform agent directories.\",\n \"story-short-analyze\": \"Use oh_story_role for specialist analysis. Never inspect platform agent directories or require external Agent deployment.\",\n \"story-short-write\": \"All named Roles are provided through oh_story_role. Do not inspect platform agent files; preserve the upstream short-fiction workflow and quality gates.\",\n \"browser-cdp\": \"Use only browser or web capabilities visible in the current DSH preset. Do not start a parallel browser host; if no compatible capability is visible, explain the limitation.\",\n \"story-cover\": \"Use only image-generation or HTTP capabilities visible in the current DSH preset. Never assume a separate Codex or Claude runtime.\"\n};\nconst DSH_DRAMA_BRIDGE = [\n \"<short-drama-dsh-integration>\",\n \"This Skill is a native contribution to the current DeepSeek Harness session.\",\n \"DSH owns the workspace, model, preset, permissions, Session Log, tools, approvals, cancellation, resume, and Agent UI.\",\n \"The \u77ED\u5267 tab is the creator workspace. Never start dashboard_server.py, another web server, Dashboard, Agent runtime, session transport, or model configuration.\",\n \"Drama Skills uses a creator-first contract: each episode keeps only the requested documents, up to five creator-facing sources at \u5267\u96C6/<EP>/\u5267\u672C.md, \u89C6\u89C9\u8BBE\u5B9A.md, \u5206\u955C.md, \u56FE\u7247\u63D0\u793A\u8BCD.md, and \u89C6\u9891\u63D0\u793A\u8BCD.md. Never precreate empty documents, backfill nominal stages, or start work the creator did not request. Persisted reviews use creator-readable Markdown under \u5BA1\u67E5/; an oral review writes nothing.\",\n \"\u5267\u96C6/<EP>/\u526A\u8F91\u5355.md is the v0.7 assembly record, not a sixth creative truth: the five creator documents stay the creative truth. It is written after readable media exists and records what reaches the cut \u2014 which footage or accepted static keyframes are kept or left unused and why, each cut's in/out timing, its subtitles, \u753B\u9762\u6587\u5B57 overlays, \u97F3\u6548 cues, \u914D\u97F3 and \u73AF\u5883\u58F0, post-processing such as shot-match correction or an external mix, and the delivery spec including optional \u9897\u7C92 grain and \u63A5\u955C\u5339\u914D. It never changes a line, a shot's job, or a declared duration; changing any of those means returning to the document that owns it.\",\n \"For a v0.6 project, never create a parallel JSON/JSONL lifecycle truth, indexes, fingerprints, coverage tables, or QA records merely because legacy maintenance scripts and templates remain bundled.\",\n \"Never upgrade a v0.5 structured project in place or mix both contracts in one project root. Keep legacy production/audit artifacts read-only and pinned to v0.5; migrate only into a new creator-first root with manual per-episode creator confirmation.\",\n \"Use only tools visible in the current DSH preset and preserve the upstream project ownership, freshness, review, and explicit production-confirmation contracts.\",\n \"Use oh_story_production only for semantic production-view intents (open/focus, explicit shot order, or tracking a job that this Agent is actually executing). Cosmetic canvas layout remains creator-controlled. The tool changes only the Session projection: it does not edit creator documents, generate media, or authorize production.\",\n \"Production credentials remain outside project files. Never treat a prior acceptance, preview, continuation request, or budget discussion as confirmation for a paid production run.\",\n \"</short-drama-dsh-integration>\"\n].join(\"\\n\");\nconst DSH_DRAMA_OVERRIDES: Readonly<Partial<Record<string, string | ((skillRoot: string) => string)>>> = {\n \"short-drama\": \"A dashboard request means focus or use the native \u77ED\u5267 tab in this DSH Session. Do not run the bundled standalone Dashboard script. New projects follow only the v0.6 creator-first contract and create only documents required by the current request.\",\n \"short-drama-produce\": (skillRoot) => `Use an upstream adapter only after the creator explicitly confirms the exact current job. Its source must be the current creator-first Markdown and its output belongs under \u5267\u96C6/<EP>/\u5236\u4F5C\u6210\u679C/. DSH permissions and approval UI remain authoritative. When oh_story_production is visible, register a previewed image or video job with track_job after the confirmation is valid and before run \u2014 never at prepare time \u2014 passing the same job ID, target, modality and count the creator just approved. track_job's jobKind is image, video or composition (the assembled cut), so from this Skill it registers image and video jobs only: speech (tts) and music jobs pass through the same prepare \u2192 explicit creator confirmation \u2192 run gate but are never registered with track_job or relabelled as another kind, and their audio results stay under \u5267\u96C6/<EP>/\u5236\u4F5C\u6210\u679C/. Optional voice references belong on the MOTION entry's separate \u53C2\u8003\u97F3\u9891 line, never in \u8F93\u5165\u53C2\u8003\u56FE or the workbench image picker. Compile them as reference_audio bindings, preserve character exactly from \u89D2\u8272, and match the project-local audio path to that character's single \u58F0\u97F3\u53C2\u8003 in \u89C6\u89C9\u8BBE\u5B9A.md. \u4E0D\u5F97\u63A7\u5236 lists \u53F0\u8BCD\u3001\u8BED\u6C14\u3001\u60C5\u7EEA individually. The selected adapter profile must explicitly declare reference_audio in reference_roles; otherwise reject before paid submission, never drop or substitute the binding. The generated generic adapter profiles intentionally omit reference_audio because their model IDs are environment-selected; use a creator-owned OH_STORY_DRAMA_ADAPTER_CONFIG profile that declares audio support only for a known reference-audio-capable model. DeepSeek generates no media: every image, video, speech, or music result comes from a provider adapter. The bundled adapters are ${dramaAdapterSummary()}; they are registered for this DSH host in ${dramaAdapterConfigPath(skillRoot).path} \u2014 pass that file as --adapter-config unless the creator names another config (${DRAMA_ADAPTER_CONFIG_ENV}). Credentials are read only from the DSH host process environment. Before preparing a paid job, name the adapter that will run it; if its variables are missing, tell the creator exactly which ones to export before starting DSH instead of failing inside run. Never read, print, or write credential values. A submitted video job is already billed, so an interrupted run is recovered, not resubmitted: when audit reports orphaned_provider_job, recover it with collect, passing --job-id \u2014 the drama job the finding names, not its provider_job_id, which collect reads from the run handle itself. collect spends nothing and does not need the confirmation gate \u2014 the gate exists to stop unintended spending \u2014 but re-running the same job does, and would charge the creator twice.`,\n \"short-drama-edit\": [\n \"Assembly runs inside this DSH Session. Write \u5267\u96C6/<EP>/\u526A\u8F91\u5355.md first, then run edit_tool.py check and render through the current DSH execution world; the rendered cut belongs under \u5267\u96C6/<EP>/\u5236\u4F5C\u6210\u679C/\u6210\u7247/ and the \u77ED\u5267 tab shows it there. ffmpeg and ffprobe come from the DSH host \u2014 when one is missing, say so instead of approximating or reporting an untested measurement as a pass.\",\n // edit_tool.py 0.7.1 `_unaccounted_shots`: `- \u672A\u91C7\u7528\u955C\u5934\uFF1A` is read only outside CUT blocks, split on `\uFF1B`, and each item must fullmatch `MOTION-\u2026\uFF08\u7406\u7531\uFF1A<non-empty>\uFF09`.\n \"Video cuts use existing MOTION IDs; static-frame cuts use SHOT IDs from \u5206\u955C.md or IMG IDs from \u56FE\u7247\u63D0\u793A\u8BCD.md and accepted png/jpg/jpeg/webp files. Every unused MOTION and, when static cuts exist, every storyboard SHOT must be accounted for before the first `## CUT-` on one line: `- \u672A\u91C7\u7528\u955C\u5934\uFF1AMOTION-\u2026\uFF08\u7406\u7531\uFF1A\u2026\uFF09\uFF1BSHOT-\u2026\uFF08\u7406\u7531\uFF1A\u2026\uFF09`. Join items with a full-width `\uFF1B`; reasons name \u6587\u4EF6\u7F3A\u5931, \u8D28\u91CF\u4E0D\u53EF\u7528 or \u53D9\u4E8B\u53D6\u820D. A static CUT starts at 0.00, lasts at least 0.50 seconds, requires the delivery width/height/frame rate, and may use \u8FD0\u955C. The native production sequence accepts video and accepted keyframe images, keeps storyboard order and source identity, and dispatches /short-drama-edit in Chat; never relabel images as video or generate paid video unnecessarily.\",\n \"Every video cut must share one width, height and frame rate: render hard-joins the encoded video segments and never scales or retimes them. Static cuts are rendered to the delivery specification with the declared crop/motion. When check reports a mismatch, normalise the odd clips to the delivery spec with ffmpeg in the DSH execution world, under approval, preserving the composition. Write them under \u5267\u96C6/<EP>/\u5236\u4F5C\u6210\u679C/\u6210\u7247/\u89C4\u683C\u7EDF\u4E00/, an edit-owned intermediate, never beside the produce-stage originals and never over produced footage, and name them without the original's job-id token (the MOTION ID will do). Record the crop or pad in that CUT's block (not in its \u753B\u9762 line, which accepts only \u4EAE\u5EA6/\u9971\u548C/\u8272\u6E29), point \u6765\u6E90 at the new file, update \u5165\u70B9/\u51FA\u70B9 if the conversion moved them, and rerun check.\",\n \"The default burned-subtitle route needs an ffmpeg built with libass; when the host's ffmpeg lacks it, say so instead of silently dropping subtitles. Remotion renders every frame through a headless browser from a Node workspace outside the project, ~/.cache/short-drama-edit/remotion, which edit_tool.py rewrites on each run: the optional subtitle route uses it, and any `\u753B\u9762\u6587\u5B57` line in \u526A\u8F91\u5355.md requires it whatever the subtitle route. Install it (npm install in that workspace; an install from before Drama Skills 0.8 must run npm install again) only after the creator approves, through DSH approval. Without that approval write no \u753B\u9762\u6587\u5B57 lines and tell the creator the blank on-screen panels stay empty. Never treat Remotion as a second Agent runtime, dashboard, or session transport.\",\n \"The \u58F0\u97F3 line in \u526A\u8F91\u5355.md is a record, not an instruction the built-in render executes. render trims, auto-matches adjacent cuts within one scene (a CUT's \u753B\u9762 correction replaces it, `- \u753B\u9762\uFF1A\u4E0D\u6821` skips it, and `- \u63A5\u955C\u5339\u914D\uFF1A\u65E0` in the delivery spec turns it off), hard-joins, mixes in the `\u97F3\u6548` lines, cross-cut `\u914D\u97F3` and looping `\u73AF\u5883\u58F0`, burns subtitles and \u753B\u9762\u6587\u5B57, applies optional \u9897\u7C92, and normalises loudness. A mix beyond the declared \u97F3\u6548/\u914D\u97F3/\u73AF\u5883\u58F0 lines, crossfade, transition or format conversion is an external ffmpeg step, run under approval, that writes a temporary file, ends as render does with whole-film two-pass loudnorm to the declared \u4EA4\u4ED8\u54CD\u5EA6 (I=<\u4EA4\u4ED8\u54CD\u5EA6>:TP=-1.5:LRA=11, the second pass fed the first pass's measurements with linear=true, audio re-encoded as AAC 192k at 48 kHz), and only then replaces \u5267\u96C6/<EP>/\u5236\u4F5C\u6210\u679C/\u6210\u7247/\u6210\u7247.mp4; record its command in \u526A\u8F91\u5355.md and repeat it after any re-render, which overwrites that file. Run edit_tool.py verify last, on that delivered file, and report every \u672A\u6D4B item as untested, never as passed.\",\n \"This stage never generates footage and never edits \u5267\u672C.md, \u5206\u955C.md, or \u89C6\u9891\u63D0\u793A\u8BCD.md \u2014 route those back to their owning Skill.\"\n ].join(\" \"),\n \"short-drama-assets\": \"Keep one stable `- ID\uFF1AVISUAL-*` line on every \u4EBA\u7269/\u9020\u578B/\u5730\u70B9/\u9053\u5177/\u72B6\u6001 entry in \u89C6\u89C9\u8BBE\u5B9A.md, and never change an existing ID when editing its heading or text. The \u751F\u4EA7 view identifies canvas nodes by that ID; entries without one still render, but the workbench reports their node identity as unstable.\"\n};\nconst DSH_GAME_BRIDGE = [\n \"<novel-to-game-dsh-integration>\",\n \"This Skill is a native contribution to the current DeepSeek Harness session.\",\n \"DSH owns the workspace, model, preset, permissions, Session Log, tools, approvals, cancellation, resume, Todo, and Chat UI.\",\n \"The \u6E38\u620F tab is the playable Game Studio. Never start a second Agent runtime, dashboard, session transport, or model configuration.\",\n \"Keep the complete upstream seven-Skill pipeline and write adaptation artifacts under game-adaptations/<project>/ exactly as the upstream contracts specify.\",\n \"For a web target, keep the authoritative playable entry at build/app/index.html so Game Studio can preview it. Do not silently replace a requested non-web runtime with a web build.\",\n \"Use only DSH-visible tools and approvals. qa/verification.json remains the sole machine QA truth and must cover launch, render, input, coreLoop, outcome, and restart with real execution evidence.\",\n \"The bundled Jin Ping Mei project is a read-only example, not a template to copy mechanically and not proof that another adaptation passed QA.\",\n \"</novel-to-game-dsh-integration>\"\n].join(\"\\n\");\nconst DSH_VIDEO_BRIDGE = [\n \"<video-recap-dsh-integration>\",\n \"This Skill is a native contribution to the current DeepSeek Harness session.\",\n \"DSH owns the workspace, model, preset, permissions, Session Log, tools, approvals, cancellation, resume, Todo, Chat, and the \u89C6\u9891 preview Studio.\",\n \"Never start a second Agent runtime, dashboard, session transport, web server, polling loop, or model configuration.\",\n \"A dashboard request means the native \u89C6\u9891 tab in this DSH Session: dashboard_server.py and its dashboard assets are not bundled, so never try to run them. To inspect a resource library, use the read-only scripts/library.py check, list, or show.\",\n \"Keep the complete upstream six-Skill production pipeline plus the on-demand video-reference Skill; video-reference extracts reusable production references only when requested and never enters the default production path. Put each project under video-recaps/<project>/, copy or import source media under sources/, and use work/ as the upstream work_dir so the Studio can discover authoritative manifests and outputs. A project binding passed with --project belongs at video-recaps/<project>/recap_project.json.\",\n \"full-mode validation is lint-only: never truncate, drop, merge or reorder approved narration to satisfy a budget; report over_budget and request a revised script. final_qc.json uses schema 2 findings (code/message/blocking/evidence/next_action); do not read removed golden_eval.json, mimo_qc.json or preflight_qc.json. Do not pass removed --mimo-qc, --preserve-approved-text or --clip-padding flags, MIMO_QC* variables, CLIP_PADDING or SOURCE_VIDEO. Except dub, delivery uses tagged H.264 8-bit 4:2:0 with true peak <= -1 dBTP; delivered_true_peak_over_target blocks delivery. If libass is unavailable, deliver external .srt rather than dropping subtitles or aborting preflight.\",\n \"The Video Studio is a preview and artifact surface, not a nonlinear editor. Do not invent a second project-state format, timeline truth, or render queue; recap_run_manifest.json, recap_phase.json, timeline.json, assembly_manifest.json, and the upstream artifacts remain authoritative.\",\n \"MIMO_API_KEY, FISH_API_KEY, and voice credentials stay in the host environment. Never write secrets into project files, tool arguments shown to the browser, or chat output.\",\n \"Use only DSH-visible tools and approvals. Run Python and ffmpeg through the current DSH execution world, preserve cancellation, and do not install or upgrade system dependencies without explicit user approval.\",\n \"When a new edited or final video is ready, tell the user that Video Studio can load it; never interrupt playback by replacing the currently loaded video silently.\",\n \"</video-recap-dsh-integration>\"\n].join(\"\\n\");\n\nconst DSH_NATIVE_SKILLS: Readonly<Partial<Record<string, string>>> = {\n story: `# story \u2014 DSH \u5C0F\u8BF4\u6D41\u7A0B\u5165\u53E3\n\n\u5728\u5F53\u524D DSH Session \u5185\u5224\u65AD\u7528\u6237\u610F\u56FE\uFF0C\u5E76\u52A0\u8F7D\u6700\u5339\u914D\u7684 Oh Story Skill\uFF1A\n\n- \u65B0\u5EFA\u6216\u4FEE\u590D\u5C0F\u8BF4\u5DE5\u7A0B\uFF1Astory-setup\n- \u957F\u7BC7\u89C4\u5212\u4E0E\u5199\u4F5C\uFF08\u8BA8\u8BBA\u957F\u7BC7\u7ED3\u6784\u3001\u89C4\u5212\u5267\u60C5\u3001\u5F00\u4E66\u3001\u5199\u5927\u7EB2\u3001\u8865\u7EC6\u7EB2\u3001\u5199\u6B63\u6587\u3001\u65E5\u66F4\uFF09\uFF1A\n story-long-write\u3002\u53EA\u8981\u7ED3\u6784\u3001\u5927\u7EB2\u3001\u5377\u7EB2\u6216\u7EC6\u7EB2\u65F6\u53EA\u4EA4\u4ED8\u6240\u8BF7\u6C42\u7684\u89C4\u5212\uFF0C\u4E0D\u5199\u6B63\u6587\uFF1B\n \u7528\u6237\u660E\u786E\u8981\u6C42\u5199\u6B63\u6587\u624D\u8FDB\u5165\u6B63\u6587\u6D41\u7A0B\n- \u957F\u7BC7\u9009\u9898/\u626B\u699C\uFF1Astory-long-scan\uFF1B\u957F\u7BC7\u62C6\u6587\uFF1Astory-long-analyze\n- \u7075\u611F\u5E93\u3001\u63D0\u70BC\u7075\u611F\u3001\u8DE8\u4E66\u7075\u611F\u805A\u5408\u3001\u66F4\u65B0\u7075\u611F\u5E93\uFF1Astory-long-analyze \u7684\u53EF\u9009\u7075\u611F\u5E93\u7BA1\u9053\n \uFF08\u5355\u4E66\u62C6\u6587\u4E0D\u81EA\u52A8\u5165\u5E93\uFF09\n- \u77ED\u7BC7\u9009\u9898/\u62C6\u6587/\u5199\u4F5C\uFF1Astory-short-scan\u3001story-short-analyze\u3001story-short-write\n- \u5BFC\u5165\u5DF2\u6709\u4F5C\u54C1\uFF1Astory-import\n- \u5BA1\u7A3F\u4E0E\u53BB AI \u5473\uFF1Astory-review\u3001story-deslop\n- \u5C01\u9762\uFF1Astory-cover\n- \u67E5\u672C\u4E66\u7684\u89D2\u8272\u3001\u4F0F\u7B14\u3001\u8FDB\u5EA6\u6216\u8BBE\u5B9A\uFF1A\u7528 oh_story_role \u8C03\u7528 story-explorer\uFF1B\u67E5\u5916\u90E8\u8D44\u6599\uFF1A\n story-researcher\u3002\u56DE\u7B54\u8BB2\u6545\u4E8B\u91CC\u7684\u4E8B\uFF0C\u7F16\u53F7\u53EA\u8DDF\u7740\u6545\u4E8B\u63CF\u8FF0\u51FA\u73B0\n- \u7BA1\u7406\u4F5C\u8005\u4E60\u60EF\uFF08\u8BB0\u4F4F/\u67E5\u770B/\u786E\u8BA4/\u66FF\u6362/\u5FD8\u6389\u5199\u4F5C\u504F\u597D\uFF09\uFF1A\u52A0\u8F7D\u672C skill \u7684\n references/author-memory.md\uFF0C\u53EA\u7528\u672C skill \u7684 scripts/author_memory_commit.py \u7BA1\u7406\n \u4E24\u7EA7\u4F5C\u8005\u8BB0\u5FC6\uFF1A\u5168\u5C40\u3001\u9898\u6750\u3001\u6D41\u7A0B\u6761\u76EE\u5728\u5DE5\u4F5C\u533A .story/\u4F5C\u8005\u8BB0\u5FC6/\uFF08AP \u7F16\u53F7\uFF09\uFF0C\u672C\u4E66\u6761\u76EE\u5728\n \u4E66\u7EA7 store\uFF08BP \u7F16\u53F7\uFF09\u3002--workspace \u5FC5\u987B\u663E\u5F0F\u4F20\u3002DSH \u7684\u5C0F\u8BF4\u5DE5\u4F5C\u533A\u901A\u5E38\u5C31\u662F\u4E66\u6839\n \uFF08\u6B63\u6587/\u3001\u8BBE\u5B9A/ \u76F4\u63A5\u5728\u5DE5\u4F5C\u533A\u6839\uFF09\uFF1A\u6B64\u65F6 --workspace \u4E0E --book-root \u90FD\u4F20\u5DE5\u4F5C\u533A\u672C\u8EAB\uFF0C\n \u4E66\u7EA7 store \u5728 .story/\u4F5C\u8005\u8BB0\u5FC6/\u4E66\u7EA7/\uFF1B\u4E66\u5728\u5B50\u76EE\u5F55\u65F6 --book-root \u4F20\u90A3\u672C\u4E66\u7684\u76EE\u5F55\u3002\n \u5904\u7406\u67D0\u672C\u4E66\u65F6\u6BCF\u6761\u547D\u4EE4\u90FD\u5E26 --book-root\uFF08\u4E66\u7EA7\u64CD\u4F5C\u7F3A\u5B83\u76F4\u63A5\u62A5\u9519\uFF09\uFF0Cquery \u5FC5\u987B\u5E26\n --kind\uFF08\u53EF\u91CD\u590D\uFF09\u3002\u53EA\u8BB0\u4F5C\u8005\u660E\u786E\u8BF4\u51FA\u7684\u504F\u597D\uFF0C\u4E0D\u4ECE\u53CD\u590D\u4FEE\u6539\u6216\u6210\u7A3F\u63A8\u65AD\u3002\u5DE5\u5177\u672A\u8FD4\u56DE\n Author Memory Receipt \u524D\u4E0D\u5F97\u58F0\u79F0\u5DF2\u8BB0\u4F4F\uFF1B\u544A\u8BC9\u4F5C\u8005\u65F6\u5148\u7528\u4E00\u53E5\u4EBA\u8BDD\u8BF4\u8BB0\u4F4F\u4E86\u4EC0\u4E48\uFF0C\n \u56DE\u6267\u653E\u6700\u540E\u4E00\u884C\u3002\u4F5C\u8005\u8BF4\u300C\u6574\u7406\u4F5C\u8005\u8BB0\u5FC6\u300D\u3001\u56DE\u6267\u63D0\u793A\u4E60\u60EF\u6512\u5F97\u592A\u591A\u3001\u5DE5\u5177\u62A5\u5355\u4E66\u5E03\u5C40\u9519\u8BEF\uFF0C\n \u6216\u5DE5\u4F5C\u533A\u753B\u50CF\u91CC\u8FD8\u6709\u300C\u672C\u4E66\uFF1A\u300D\u6761\u76EE\uFF08\u5347\u7EA7\u524D\u5199\u5165\u7684\u672C\u4E66\u504F\u597D\uFF0C\u5DF2\u4E0D\u53C2\u4E0E\u67E5\u8BE2\uFF09\u65F6\uFF0C\u518D\u52A0\u8F7D\n references/author-memory-maintenance.md\uFF1B\u8FC1\u79FB\u300C\u672C\u4E66\uFF1A\u300D\u6761\u76EE\u5C31\u6309\u5B83\u8FD0\u884C\u4E00\u6B21\n migrate --workspace {\u5DE5\u4F5C\u533A} --book-root {\u4E66\u76EE\u5F55} \u628A\u5B83\u4EEC\u642C\u8FDB\u4E66\u7EA7 store\u3002\n\n\u53EA\u8BF4 /story\u3001\u770B\u4E0D\u51FA\u610F\u56FE\u65F6\uFF0C\u4E0D\u8D34\u8DEF\u7531\u8868\uFF0C\u7ED9\u56DB\u4E2A\u767D\u8BDD\u9009\u9879\uFF1A\u300C\u5F00\u4E00\u672C\u957F\u7BC7\u6216\u63A5\u7740\u5199\u300D\u2192\nstory-long-write\uFF1B\u300C\u5199\u4E00\u7BC7\u77ED\u7BC7\u300D\u2192 story-short-write\uFF1B\u300C\u628A\u4E00\u7AE0\u6539\u5F97\u4E0D\u90A3\u4E48 AI\u300D\u2192\nstory-deslop\uFF1B\u300C\u66F4\u591A\uFF08\u62C6\u4E66\u3001\u626B\u699C\u3001\u5BFC\u5165\u65E7\u7A3F\u3001\u5BA1\u7A3F\u3001\u5C01\u9762\uFF09\u300D\u2192 \u518D\u5217\u8FDB\u9636\u9879\u3002\u610F\u56FE\u660E\u786E\u65F6\n\u76F4\u63A5\u8FDB\u5165\u5BF9\u5E94 Skill\uFF1B\u53EA\u5DEE\u4E00\u4E2A\u4F1A\u6539\u53D8\u6D41\u7A0B\u7684\u9009\u62E9\u65F6\u53EA\u95EE\u8FD9\u4E00\u4E2A\u95EE\u9898\u3002\u9879\u76EE\u6587\u4EF6\u3001Agent\u3001\n\u6A21\u578B\u3001\u6743\u9650\u3001Session Log \u548C UI \u5747\u7531\u5F53\u524D DSH \u4F1A\u8BDD\u7BA1\u7406\u3002\u5C0F\u8BF4\u6587\u4EF6\u901A\u8FC7\u201C\u5C0F\u8BF4\u201D\u89C6\u56FE\u67E5\u770B\uFF0C\nAgent \u8FC7\u7A0B\u901A\u8FC7\u53F3\u4FA7\u52A8\u6001\u680F\u6216\u5B98\u65B9 Chat \u67E5\u770B\u3002\u7981\u6B62\u542F\u52A8\u72EC\u7ACB Dashboard\u3002`,\n \"story-setup\": `# story-setup \u2014 DSH \u539F\u751F\u5C0F\u8BF4\u5DE5\u7A0B\u521D\u59CB\u5316\n\n\u53EA\u521D\u59CB\u5316\u6216\u6821\u9A8C\u5F53\u524D DSH workspace \u4E2D\u7684\u5C0F\u8BF4\u6570\u636E\uFF0C\u4E0D\u90E8\u7F72\u4EFB\u4F55 Agent \u5E73\u53F0\u6587\u4EF6\u3002\n\n1. \u68C0\u67E5\u73B0\u6709\u6B63\u6587\u3001\u8BBE\u5B9A\u3001\u5927\u7EB2\u548C\u8FFD\u8E2A\u6587\u4EF6\uFF0C\u5DF2\u6709\u5185\u5BB9\u7EDD\u4E0D\u8986\u76D6\u3002\n2. \u6839\u636E\u7528\u6237\u58F0\u660E\u4E0E\u73B0\u6709\u7ED3\u6784\u5224\u65AD\u957F\u7BC7/\u77ED\u7BC7\uFF1B\u65E0\u6CD5\u53EF\u9760\u5224\u65AD\u65F6\u8BF7\u6C42\u786E\u8BA4\u3002\n3. \u957F\u7BC7\u6309\u9700\u5EFA\u7ACB \u6B63\u6587/\u3001\u8BBE\u5B9A/\u3001\u5927\u7EB2/\u3002\u521D\u59CB\u5316\u3001\u5F00\u4E66\u3001\u5927\u7EB2\u548C\u7EC6\u7EB2\u9636\u6BB5\u90FD\u4E0D\u5EFA \u8FFD\u8E2A/\uFF0C\n \u4E5F\u4E0D\u5199 \u8FFD\u8E2A/_tracking-state.json\uFF1A\u8FFD\u8E2A\u5728\u7B2C\u4E00\u7AE0\u6B63\u6587\u52A8\u7B14\u524D\uFF0C\u7531 story-long-write\n \u5355\u7AE0\u6D41\u7A0B\u7528\u5B83\u7684 scripts/tracking_commit.py init \u521D\u59CB\u5316\uFF08\u4E8B\u52A1 JSON \u653E\u4E66\u76EE\u5F55\n .story/work/\uFF0Ccheck \u901A\u8FC7\u540E\u5220\u6389\uFF09\uFF0C\u4E4B\u540E\u6BCF\u7AE0\u7531\u811A\u672C\u63D0\u4EA4\u3002_tracking-state.json \u4E0E\n \u4E0A\u4E0B\u6587.md \u7B49\u6D3E\u751F Tracking \u89C6\u56FE\u53EA\u7531\u811A\u672C\u751F\u6210\uFF0C\u7EDD\u4E0D\u624B\u6539\u3002\n \u7B2C\u4E00\u7AE0\u6B63\u6587\u843D\u76D8\u524D\u5FC5\u987B\u6709\u5BF9\u5E94\u7EC6\u7EB2\u3002\u77ED\u7BC7\u4FDD\u6301\u8F7B\u91CF\u7ED3\u6784\uFF0C\u4E0D\u5F3A\u52A0\u957F\u7BC7 Tracking\u3002\n4. \u5DF2\u6709\u6B63\u6587\u5374\u6CA1\u6709 \u8FFD\u8E2A/_tracking-state.json \u65F6\uFF0C\u4E0D\u81EA\u884C\u8865\u5EFA\u8FFD\u8E2A\u6587\u4EF6\uFF1A\u5DF2\u6709\u65E7 \u8FFD\u8E2A/\n \u7684\u662F\u65E7\u8FFD\u8E2A\u7ED3\u6784\uFF0C\u5EFA\u8BAE\u8D70 story-import \u7684\u300C\u65E7\u8FFD\u8E2A\u9879\u76EE\u8FC1\u79FB\u300D\uFF1B\u6CA1\u6709 \u8FFD\u8E2A/ \u7684\u65E2\u6709\u4E66\u7A3F\n \u5EFA\u8BAE\u7528 story-import \u5BFC\u5165\u3002\n5. \u9700\u8981\u67B6\u6784\u3001\u89D2\u8272\u6216\u7814\u7A76\u5DE5\u4F5C\u65F6\uFF0C\u901A\u8FC7 oh_story_role \u8C03\u7528\u5DF2\u6253\u5305 Role\uFF1B\u4E0D\u8981\u68C0\u67E5\u6216\n \u751F\u6210 .claude\u3001.codex\u3001.opencode\u3001.agents\u3001.zcode\u3001AGENTS.md \u6216 .story-deployed\u3002\n6. \u7ED9\u4F5C\u8005\u7684\u62A5\u544A\u6309\u8FD9\u4E2A\u987A\u5E8F\u5199\uFF1A\u5148\u5199\u300C\u73B0\u5728\u53EF\u4EE5\u505A\u4EC0\u4E48\u300D\uFF0C\u7528\u5199\u4E66\u7684\u8BDD\u5217\u771F\u6B63\u53EF\u7528\u7684\u4E8B\n \uFF08\u5982\u300C\u53EF\u4EE5\u5F00\u65B0\u4E66\u3001\u7EED\u5199\uFF1A\u8BF4 /story-long-write\u300D\uFF09\uFF1B\u518D\u5199\u300C\u4F60\u8FD8\u9700\u8981\u505A\u7684\u4E8B\u300D\uFF0C\u9010\u6761\n \u53EF\u7167\u505A\uFF08\u542B\u9700\u8981\u4F5C\u8005\u786E\u8BA4\u7684\u957F\u7BC7/\u77ED\u7BC7\u5224\u65AD\uFF09\uFF0C\u6CA1\u6709\u5C31\u5199\u300C\u65E0\u9700\u5176\u4ED6\u64CD\u4F5C\u300D\u3002\u8FD9\u4E24\u6BB5\u4E0D\u51FA\u73B0\n \u811A\u672C\u540D\u3001\u5B57\u6BB5\u540D\u3001\u72B6\u6001\u540D\u6216\u6587\u4EF6\u8DEF\u5F84\uFF1B\u6700\u540E\u624D\u7B80\u77ED\u5217\u51FA\u521B\u5EFA\u548C\u4FDD\u7559\u4E86\u54EA\u4E9B\u6587\u4EF6\u3002\n \u4E0D\u8981\u914D\u7F6E\u6A21\u578B\u3001\u6743\u9650\u3001Hooks \u6216 Session\u3002\n\n\u9898\u6750\u3001\u89D2\u8272\u3001\u8282\u594F\u3001\u51B2\u7A81\u3001\u5F00\u7BC7\u548C\u5199\u4F5C\u65B9\u6CD5\u8D44\u6599\u4F4D\u4E8E references/agent-references/\uFF1B\n\u53EA\u52A0\u8F7D\u5F53\u524D\u4EFB\u52A1\u9700\u8981\u7684\u6587\u4EF6\u3002`,\n \"browser-cdp\": `# browser-cdp \u2014 DSH \u6D4F\u89C8\u5668\u80FD\u529B\u9002\u914D\n\n\u672C Skill \u4E0D\u542F\u52A8 Chrome\u3001CDP \u7AEF\u53E3\u3001\u72EC\u7ACB\u6D4F\u89C8\u5668 Host \u6216 setup-cdp-chrome.js\u3002\n\u4EC5\u4F7F\u7528\u5F53\u524D DSH Preset \u5DF2\u66B4\u9732\u7684 web_search\u3001web_fetch \u6216\u6D4F\u89C8\u5668\u5DE5\u5177\u5B8C\u6210\u7F51\u9875\u8BFB\u53D6\u3001\n\u699C\u5355\u91C7\u96C6\u548C\u8D44\u6599\u6838\u9A8C\u3002\u4FDD\u6301\u4EE5\u4E0B\u539F\u5219\uFF1A\n\n1. \u4F18\u5148\u4F7F\u7528\u7ED3\u6784\u5316\u641C\u7D22/\u6293\u53D6\u5DE5\u5177\uFF1B\u9700\u8981\u767B\u5F55\u6001\u6216\u4EA4\u4E92\u9875\u9762\u65F6\u624D\u4F7F\u7528\u53EF\u89C1\u6D4F\u89C8\u5668\u80FD\u529B\u3002\n2. \u5C0A\u91CD\u7AD9\u70B9\u6761\u6B3E\u3001\u8BBF\u95EE\u9891\u7387\u4E0E\u7528\u6237\u6388\u6743\uFF1B\u4E0D\u7ED5\u8FC7\u9A8C\u8BC1\u7801\u3001\u4ED8\u8D39\u5899\u6216\u8BBF\u95EE\u63A7\u5236\u3002\n3. \u8BB0\u5F55\u6765\u6E90 URL\u3001\u91C7\u96C6\u65F6\u95F4\u3001\u5931\u8D25\u9879\u548C\u6570\u636E\u8D28\u91CF\uFF0C\u4E0D\u628A\u63A8\u65AD\u5199\u6210\u9875\u9762\u4E8B\u5B9E\u3002\n4. \u5F53\u524D Preset \u6CA1\u6709\u517C\u5BB9\u80FD\u529B\u65F6\uFF0C\u8BF4\u660E\u7F3A\u5931\u80FD\u529B\u548C\u53EF\u884C\u7684\u624B\u5DE5\u6B65\u9AA4\uFF0C\u4E0D\u53E6\u8D77\u8FD0\u884C\u65F6\u3002`,\n \"story-long-scan\": `# story-long-scan \u2014 DSH \u539F\u751F\u957F\u7BC7\u626B\u699C\n\n\u57FA\u4E8E\u53EF\u6838\u9A8C\u6837\u672C\u8BC6\u522B\u957F\u7BC7\u7F51\u6587\u8D8B\u52BF\uFF0C\u4E0D\u8FD0\u884C\u6253\u5305\u811A\u672C\u3001\u4E0D\u63D0\u53D6\u767B\u5F55\u51ED\u636E\uFF0C\u4E5F\u4E0D\u7ED5\u8FC7\u9A8C\u8BC1\u7801\u3001\n\u8BBF\u95EE\u63A7\u5236\u6216\u7AD9\u70B9\u9650\u5236\u3002\n\n1. \u660E\u786E\u5E73\u53F0\u3001\u9891\u9053\u548C\u9898\u6750\u65B9\u5411\uFF1B\u53EA\u6709\u7B54\u6848\u4F1A\u6539\u53D8\u91C7\u6837\u8303\u56F4\u65F6\u624D\u95EE\u4E00\u4E2A\u95EE\u9898\u3002\n2. \u6570\u636E\u6765\u6E90\u4F9D\u6B21\u4E3A\uFF1A\u7528\u6237\u63D0\u4F9B\u7684\u6570\u636E\u6216\u94FE\u63A5\u3001\u5F53\u524D DSH Preset \u53EF\u89C1\u7684\u7F51\u9875\u5DE5\u5177\u3001\n references/genre-trends.md \u4E2D\u7684\u5386\u53F2\u8D8B\u52BF\u3002\u65E0\u6CD5\u83B7\u53D6\u5B9E\u65F6\u6570\u636E\u65F6\u5FC5\u987B\u660E\u786E\u6807\u4E3A\u5386\u53F2\u5047\u8BBE\u3002\n3. \u6BCF\u4E2A\u6837\u672C\u8BB0\u5F55\u6765\u6E90 URL\u3001\u91C7\u96C6\u65E5\u671F\u3001\u699C\u5355\u53E3\u5F84\u3001\u6709\u6548\u6761\u76EE\u6570\u3001\u7F3A\u5931\u5B57\u6BB5\u548C\u5F02\u5E38\u9879\uFF1B\n \u4E0D\u628A\u641C\u7D22\u6458\u8981\u3001\u63A8\u65AD\u6216\u8FC7\u671F\u7F13\u5B58\u5199\u6210\u9875\u9762\u4E8B\u5B9E\u3002\n4. \u6309\u9898\u6750\u5206\u5E03\u3001\u65B0\u9898\u6750\u4FE1\u53F7\u3001\u7ECF\u5178\u9898\u6750\u53D8\u5316\u3001\u7BC7\u5E45\u4E0E\u66F4\u65B0\u3001\u4E66\u540D\u6A21\u5F0F\u3001\u5F00\u5934\u5356\u70B9\u548C\n \u5DEE\u5F02\u5316\u5143\u7D20\u5206\u6790\u3002\u9700\u8981\u51B3\u7B56\u95E8\u7981\u65F6\u4F7F\u7528 references/topic-decision.md\u3002\n5. \u8F93\u51FA\u5E02\u573A\u6982\u51B5\u3001\u9898\u6750\u70ED\u5EA6\u3001\u8BC1\u636E\u4E0E\u53EF\u4FE1\u5EA6\u3001\u98CE\u9669\u3001\u4E09\u9879\u53EF\u6267\u884C\u65B9\u5411\u548C\u4E0B\u6B21\u590D\u626B\u65F6\u95F4\u3002\n6. \u62A5\u544A\u5199\u7ED9\u4F5C\u8005\uFF1A\u8BB2\u5E02\u573A\u7ED3\u8BBA\u548C\u80FD\u5199\u7684\u65B9\u5411\uFF1B\u811A\u672C\u540D\u3001\u547D\u4EE4\u548C\u91C7\u96C6\u72B6\u6001\u7801\u4E0D\u8FDB\u62A5\u544A\u3002\n \u67D0\u4E2A\u699C\u6CA1\u91C7\u5230\uFF0C\u5C31\u7528\u4E00\u53E5\u8BDD\u8BF4\u660E\u300CXX \u699C\u8FD9\u6B21\u6CA1\u62FF\u5230\uFF08\u539F\u56E0\uFF09\uFF0C\u7ED3\u8BBA\u4E0D\u542B\u5B83\u300D\u3002\n7. \u6BCF\u6B21\u626B\u699C\u65B0\u5EFA \u626B\u699C/{YYYYMMDD}/\uFF08\u540C\u65E5\u518D\u626B\u52A0 -2\uFF09\uFF0C\u6837\u672C\u8BB0\u5F55\u5B58\u5728\u8FD9\u91CC\uFF1B\u62A5\u544A\u540C\u65F6\u6309\n references/topic-decision.md \u7684\u6A21\u677F\u5199\u8FDB\u8BE5\u76EE\u5F55\u7684 \u9009\u9898\u51B3\u7B56.md\uFF08\u5E26\u300C\u626B\u699C\u65E5\u671F\u300D\uFF09\uFF0C\n \u4F5C\u4E3A\u300C\u626B\u699C\u7ED3\u8BBA\u300D\u4E00\u8282\uFF0C\u4F5C\u8005\u8981\u9009\u9898\u65F6\u518D\u5199\u300C\u63A8\u8350\u9009\u9898\u300D\u4E00\u8282\u3002story-long-write \u5F00\u4E66\u65F6\n \u4ECE\u8FD9\u4EFD\u6587\u4EF6\u63A5\u4E0A\uFF0C\u6240\u4EE5\u7ED3\u8BBA\u8981\u843D\u76D8\uFF0C\u4E0D\u53EA\u7559\u5728\u5BF9\u8BDD\u91CC\u3002\n\n\u5F53\u524D Preset \u6CA1\u6709\u7F51\u9875\u80FD\u529B\u4E14\u7528\u6237\u4E5F\u672A\u63D0\u4F9B\u6837\u672C\u65F6\uFF0C\u4F7F\u7528\u5185\u7F6E\u53C2\u8003\u5B8C\u6210\u65B9\u6CD5\u8BBA\u5206\u6790\uFF0C\n\u5E76\u5217\u51FA\u4ECD\u9700\u6838\u9A8C\u7684\u699C\u5355\uFF1B\u4E0D\u8981\u542F\u52A8 CDP\u3001\u72EC\u7ACB\u6D4F\u89C8\u5668\u6216\u5E76\u884C\u8FD0\u884C\u65F6\u3002`,\n \"story-short-scan\": `# story-short-scan \u2014 DSH \u539F\u751F\u77ED\u7BC7\u626B\u699C\n\n\u57FA\u4E8E\u53EF\u6838\u9A8C\u6837\u672C\u8BC6\u522B\u77ED\u7BC7\u5E02\u573A\u7684\u60C5\u7EEA\u3001\u9898\u6750\u4E0E\u4F20\u64AD\u4FE1\u53F7\uFF0C\u4E0D\u8FD0\u884C\u6253\u5305\u811A\u672C\u3001\u4E0D\u8BFB\u53D6 Cookie\n\u6216 token\uFF0C\u4E5F\u4E0D\u7ED5\u8FC7\u9A8C\u8BC1\u7801\u3001\u767B\u5F55\u6216\u8BBF\u95EE\u63A7\u5236\u3002\n\n1. \u660E\u786E\u5E73\u53F0\u4E0E\u65B9\u5411\uFF1B\u53EA\u6709\u7B54\u6848\u4F1A\u6539\u53D8\u91C7\u6837\u8303\u56F4\u65F6\u624D\u95EE\u4E00\u4E2A\u95EE\u9898\u3002\n2. \u6570\u636E\u6765\u6E90\u4F9D\u6B21\u4E3A\uFF1A\u7528\u6237\u63D0\u4F9B\u7684\u6570\u636E\u6216\u94FE\u63A5\u3001\u5F53\u524D DSH Preset \u53EF\u89C1\u7684\u7F51\u9875\u5DE5\u5177\u3001\n references/real-market-data.md \u4E2D\u7684\u5386\u53F2\u8D44\u6599\u3002\u65E0\u6CD5\u8054\u7F51\u65F6\u5FC5\u987B\u628A\u7ED3\u8BBA\u6807\u4E3A\u5019\u9009\u5047\u8BBE\u3002\n3. \u8BB0\u5F55\u6765\u6E90 URL\u3001\u91C7\u96C6\u65E5\u671F\u3001\u699C\u5355\u53E3\u5F84\u3001\u6709\u6548\u6837\u672C\u6570\u3001\u7F3A\u5931\u5B57\u6BB5\u548C\u5F02\u5E38\u9879\u3002\n4. \u5206\u6790\u60C5\u7EEA\u7C7B\u578B\u3001\u9898\u6750\u70ED\u70B9\u3001\u7BC7\u5E45\u3001\u5F00\u5934\u3001\u7ED3\u5C3E\u3001\u6807\u9898\u3001\u4EBA\u8BBE\u4E0E\u4F20\u64AD\u89E6\u53D1\u70B9\uFF1B\n \u7ED9\u6BCF\u4E2A\u8D8B\u52BF\u6807\u6CE8\u8BC1\u636E\u5F3A\u5EA6\u3001\u9971\u548C\u98CE\u9669\u548C\u6709\u6548\u671F\u3002\n5. \u8F93\u51FA\u5E02\u573A\u6982\u51B5\uFF08\u626B\u699C\u65F6\u95F4\u3001\u6838\u5FC3\u53D1\u73B0\u548C\u53EF\u4FE1\u5EA6\uFF1A\u6837\u672C\u591A\u5C11\u7BC7\u3001\u6765\u81EA\u54EA\u51E0\u4E2A\u699C\uFF0C\u5E76\u5EFA\u8BAE\n \u54EA\u5929\u524D\u540E\u518D\u626B\u4E00\u6B21\uFF09\u3001\u60C5\u7EEA\u70ED\u5EA6\u3001\u9898\u6750\u70ED\u70B9\u3001\u5173\u952E\u6570\u636E\u3001\u98CE\u53E3\u9884\u8B66\u3001\u4E09\u9879\u53EF\u5199\u65B9\u5411\u3002\n6. \u62A5\u544A\u5199\u7ED9\u4F5C\u8005\uFF1A\u8BB2\u5E02\u573A\u7ED3\u8BBA\u548C\u80FD\u5199\u7684\u65B9\u5411\uFF1B\u811A\u672C\u540D\u3001\u547D\u4EE4\u548C SKIP \u8FD9\u7C7B\u91C7\u96C6\u72B6\u6001\u4E0D\u8FDB\u62A5\u544A\u3002\n \u67D0\u4E2A\u5E73\u53F0\u6CA1\u91C7\u5230\uFF0C\u5C31\u7528\u4E00\u53E5\u8BDD\u8BF4\u660E\u300CXX \u8FD9\u6B21\u6CA1\u62FF\u5230\uFF08\u539F\u56E0\uFF09\uFF0C\u7ED3\u8BBA\u4E0D\u542B\u5B83\u300D\u3002\n7. \u6BCF\u6B21\u626B\u699C\u65B0\u5EFA \u626B\u699C/{YYYYMMDD}/\uFF08\u540C\u65E5\u518D\u626B\u52A0 -2\uFF09\uFF0C\u6837\u672C\u8BB0\u5F55\u5B58\u5728\u8FD9\u91CC\uFF1B\u62A5\u544A\u540C\u65F6\u6309\n references/topic-match.md \u7684\u6A21\u677F\u5199\u8FDB\u8BE5\u76EE\u5F55\u7684 \u77ED\u7BC7\u626B\u699C\u7ED3\u8BBA.md\uFF0C\u4F5C\u4E3A\u300C\u626B\u699C\u7ED3\u8BBA\u300D\n \u4E00\u8282\uFF0C\u7ED3\u5408\u9879\u76EE\u6761\u4EF6\u518D\u5199\u300C\u9009\u9898\u5339\u914D\u300D\u4E00\u8282\u3002story-short-write \u4ECE\u8FD9\u4EFD\u6587\u4EF6\u63A5\u4E0A\u9009\u9898\u3002\n \u4F5C\u8005\u81EA\u5DF1\u7ED9\u699C\u5355\u65F6\uFF0C\u6309 references/manual-rank-input.md \u7684\u683C\u5F0F\u6574\u7406\u3002\n\n\u5F53\u524D Preset \u6CA1\u6709\u7F51\u9875\u80FD\u529B\u4E14\u7528\u6237\u4E5F\u672A\u63D0\u4F9B\u6837\u672C\u65F6\uFF0C\u53EA\u505A\u5386\u53F2\u8D44\u6599\u5206\u6790\u5E76\u5217\u51FA\u9A8C\u8BC1\u52A8\u4F5C\uFF1B\n\u4E0D\u8981\u542F\u52A8 CDP\u3001\u72EC\u7ACB\u6D4F\u89C8\u5668\u6216\u5E76\u884C\u8FD0\u884C\u65F6\u3002`\n};\n\ninterface ParsedSkill {\n readonly name: string;\n readonly description: string;\n readonly content: string;\n readonly userInvocable: boolean;\n}\n\nfunction frontmatterValue(frontmatter: string, key: string): string | undefined {\n const lines = frontmatter.split(/\\r?\\n/u);\n const index = lines.findIndex((line) => new RegExp(`^${key}:\\\\s*`, \"u\").test(line));\n if (index < 0) return undefined;\n const raw = lines[index]?.replace(new RegExp(`^${key}:\\\\s*`, \"u\"), \"\").trim();\n if (raw === undefined) return undefined;\n if (raw === \">\" || raw === \"|\" || raw === \">-\" || raw === \"|-\") {\n const values: string[] = [];\n for (const line of lines.slice(index + 1)) {\n if (/^\\S/u.test(line)) break;\n values.push(line.trim());\n }\n return (raw.startsWith(\">\") ? values.join(\" \") : values.join(\"\\n\")).trim();\n }\n if (raw.startsWith(\"\\\"\") && raw.endsWith(\"\\\"\")) {\n try { return JSON.parse(raw) as string; }\n catch { return raw.slice(1, -1); }\n }\n return raw.replace(/^['\"]|['\"]$/gu, \"\");\n}\n\nexport function parseBundledSkill(source: string): ParsedSkill {\n const match = /^---\\r?\\n([\\s\\S]*?)\\r?\\n---\\r?\\n?/u.exec(source);\n if (match?.[1] === undefined) throw new Error(\"Bundled skill is missing YAML frontmatter.\");\n const name = frontmatterValue(match[1], \"name\");\n const description = frontmatterValue(match[1], \"description\");\n if (!name || !/^[a-z0-9]+(?:-[a-z0-9]+)*$/u.test(name)) throw new Error(\"Bundled skill has an invalid name.\");\n if (!description) throw new Error(`Bundled skill \"${name}\" has no description.`);\n return {\n name,\n description,\n content: source.slice(match[0].length),\n userInvocable: frontmatterValue(match[1], \"user-invocable\") !== \"false\"\n };\n}\n\nexport function dshSkillContent(name: string, content: string): string {\n const override = DSH_SKILL_OVERRIDES[name];\n const native = DSH_NATIVE_SKILLS[name];\n return `${DSH_SKILL_BRIDGE}${override === undefined ? \"\" : `\\n<skill-specific-dsh-override>${override}</skill-specific-dsh-override>`}\\n\\n${native ?? content}`;\n}\n\nexport function defaultBundledSkillRoot(): string {\n const current = dirname(fileURLToPath(import.meta.url));\n return basename(current) === \"src\"\n ? resolve(current, \"../../knowledge/oh-story/skills\")\n : resolve(current, \"oh-story/skills\");\n}\n\nexport function defaultDramaSkillRoot(): string {\n const current = dirname(fileURLToPath(import.meta.url));\n return basename(current) === \"src\"\n ? resolve(current, \"../../knowledge/drama/skills\")\n : resolve(current, \"drama/skills\");\n}\n\nexport function defaultNovelToGameSkillRoot(): string {\n const current = dirname(fileURLToPath(import.meta.url));\n return basename(current) === \"src\"\n ? resolve(current, \"../../knowledge/novel-to-game/skills\")\n : resolve(current, \"novel-to-game/skills\");\n}\n\nfunction createBundledSkillProvider(\n providerName: string,\n skillRoot: string,\n content: (name: string, source: string) => string\n): SkillProvider {\n const root = resolve(skillRoot);\n return {\n name: providerName,\n async list(): Promise<readonly SkillCandidate[]> {\n const directories = (await readdir(root, { withFileTypes: true }))\n .filter((entry) => entry.isDirectory())\n .map((entry) => entry.name)\n .sort();\n return Promise.all(directories.map(async (directory): Promise<SkillCandidate> => {\n const path = join(root, directory, \"SKILL.md\");\n const parsed = parseBundledSkill(await readFile(path, \"utf8\"));\n if (parsed.name !== directory) throw new Error(`Bundled skill directory \"${directory}\" does not match name \"${parsed.name}\".`);\n return {\n name: parsed.name,\n description: parsed.description,\n invocation: { modelInvocable: true, userInvocable: parsed.userInvocable },\n provider: providerName,\n source: \"bundled\",\n resourceBase: { kind: \"directory\", path: join(root, directory) },\n rank: BUNDLED_SKILL_RANK,\n locator: pathToFileURL(path),\n path\n };\n }));\n },\n async get(candidate): Promise<SkillDefinition | undefined> {\n if (candidate.provider !== providerName || typeof candidate.path !== \"string\") return undefined;\n const path = resolve(candidate.path);\n const relativePath = relative(root, path);\n if (relativePath === \"\" || relativePath.startsWith(\"..\") || isAbsolute(relativePath)) {\n throw new Error(\"Bundled skill locator escaped the packaged skill root.\");\n }\n const parsed = parseBundledSkill(await readFile(path, \"utf8\"));\n if (parsed.name !== candidate.name) return undefined;\n return {\n name: parsed.name,\n description: parsed.description,\n invocation: { modelInvocable: true, userInvocable: parsed.userInvocable },\n provider: providerName,\n source: \"bundled\",\n resourceBase: { kind: \"directory\", path: join(root, parsed.name) },\n path,\n content: content(parsed.name, parsed.content)\n };\n }\n };\n}\n\nexport function createOhStorySkillProvider(skillRoot = defaultBundledSkillRoot()): SkillProvider {\n return createBundledSkillProvider(STORY_PROVIDER_NAME, skillRoot, dshSkillContent);\n}\n\nexport function dshDramaSkillContent(name: string, content: string, skillRoot = defaultDramaSkillRoot()): string {\n const entry = DSH_DRAMA_OVERRIDES[name];\n // Resolved per read, not at import: the config path follows the environment\n // the host actually runs with, and matches what /oh-story/drama-preflight reports.\n const override = typeof entry === \"function\" ? entry(skillRoot) : entry;\n return `${DSH_DRAMA_BRIDGE}${override === undefined ? \"\" : `\\n<skill-specific-dsh-override>${override}</skill-specific-dsh-override>`}\\n\\n${content}`;\n}\n\nexport function createDramaSkillProvider(skillRoot = defaultDramaSkillRoot()): SkillProvider {\n return createBundledSkillProvider(DRAMA_PROVIDER_NAME, skillRoot, (name, content) => dshDramaSkillContent(name, content, skillRoot));\n}\n\nexport function dshNovelToGameSkillContent(_name: string, content: string): string {\n return `${DSH_GAME_BRIDGE}\\n\\n${content}`;\n}\n\nexport function createNovelToGameSkillProvider(skillRoot = defaultNovelToGameSkillRoot()): SkillProvider {\n return createBundledSkillProvider(GAME_PROVIDER_NAME, skillRoot, dshNovelToGameSkillContent);\n}\n\nexport function defaultVideoRecapSkillRoot(): string {\n const current = dirname(fileURLToPath(import.meta.url));\n return basename(current) === \"src\"\n ? resolve(current, \"../../knowledge/video-recap/skills\")\n : resolve(current, \"video-recap/skills\");\n}\n\nexport function dshVideoRecapSkillContent(_name: string, content: string): string {\n return `${DSH_VIDEO_BRIDGE}\\n\\n${content}`;\n}\n\nexport function createVideoRecapSkillProvider(skillRoot = defaultVideoRecapSkillRoot()): SkillProvider {\n return createBundledSkillProvider(VIDEO_PROVIDER_NAME, skillRoot, dshVideoRecapSkillContent);\n}\n", "import { createHash } from \"node:crypto\";\nimport { access, lstat, mkdir, rename, writeFile } from \"node:fs/promises\";\nimport { tmpdir } from \"node:os\";\nimport { dirname, join, resolve } from \"node:path\";\n\n/**\n * Drama Skills generates no media by itself and neither does DeepSeek: every\n * image, video, speech, or music result comes from a provider adapter that\n * `short-drama-produce` runs through `production_tool.py run --adapter-config`.\n * Upstream deliberately leaves that config file and its credentials outside\n * every project. This module names the bundled adapters (five as of Drama\n * Skills 0.7.1, one per `provider_adapters.py` choice), registers them for the\n * current DSH host so the Agent has a file to pass, and reports which host\n * environment variables are present \u2014 never their values.\n */\n/** Upstream job modalities with a bundled adapter; `tts` is spoken dialogue (MiniMax Speech). */\nexport type DramaAdapterModality = \"image\" | \"video\" | \"tts\" | \"music\";\n\nexport interface DramaAdapterSpec {\n /** Adapter id used both in the config file and in a job's `adapter` field. */\n readonly name: string;\n readonly label: string;\n readonly modality: DramaAdapterModality;\n /** Host environment variables the bundled adapter refuses to run without. */\n readonly requiredEnv: readonly string[];\n readonly optionalEnv: readonly string[];\n readonly timeoutSeconds: number;\n /** Provider reference shipped with the Skill, relative to the drama skill root. */\n readonly reference: string;\n}\n\nexport interface DramaAdapterStatus {\n readonly name: string;\n readonly label: string;\n readonly modality: DramaAdapterModality;\n readonly configured: boolean;\n readonly missing: readonly string[];\n}\n\nexport interface DramaAdapterConfigLocation {\n readonly path: string;\n /** True when the plugin writes the file; false when the creator points at their own. */\n readonly generated: boolean;\n}\n\n/** Point at a creator-owned adapter config instead of the generated one. */\nexport const DRAMA_ADAPTER_CONFIG_ENV = \"OH_STORY_DRAMA_ADAPTER_CONFIG\";\n\nconst PROVIDER_SCRIPT = \"short-drama-produce/scripts/provider_adapters.py\";\n\nexport const DRAMA_ADAPTERS: readonly DramaAdapterSpec[] = [\n {\n name: \"gpt-image-2\",\n label: \"GPT Image 2\",\n modality: \"image\",\n requiredEnv: [\"OPENAI_API_KEY\"],\n optionalEnv: [\"OPENAI_BASE_URL\"],\n timeoutSeconds: 600,\n reference: \"short-drama-produce/references/providers/gpt-image-2.md\"\n },\n {\n name: \"seedance\",\n label: \"Seedance\",\n modality: \"video\",\n requiredEnv: [\"ARK_API_KEY\", \"SEEDANCE_MODEL\"],\n optionalEnv: [\"SEEDANCE_BASE_URL\", \"SEEDANCE_ALLOWED_RATIOS\", \"SEEDANCE_MIN_DURATION\", \"SEEDANCE_MAX_DURATION\"],\n timeoutSeconds: 3_600,\n reference: \"short-drama-produce/references/providers/seedance.md\"\n },\n {\n name: \"minimax-h3\",\n label: \"MiniMax H3\",\n modality: \"video\",\n // Every H3 job carries an integer duration, and the adapter refuses it without this range.\n requiredEnv: [\"MINIMAX_API_KEY\", \"MINIMAX_VIDEO_MODEL\", \"MINIMAX_VIDEO_RESOLUTIONS\", \"MINIMAX_VIDEO_MIN_DURATION\", \"MINIMAX_VIDEO_MAX_DURATION\"],\n optionalEnv: [\"MINIMAX_VIDEO_BASE_URL\", \"MINIMAX_VIDEO_RATIOS\"],\n timeoutSeconds: 3_600,\n reference: \"short-drama-produce/references/providers/minimax-h3-video.md\"\n },\n {\n name: \"minimax-music\",\n label: \"MiniMax Music\",\n modality: \"music\",\n requiredEnv: [\"MINIMAX_API_KEY\"],\n optionalEnv: [\"MINIMAX_BASE_URL\"],\n timeoutSeconds: 600,\n reference: \"short-drama-produce/references/providers/minimax-music.md\"\n },\n {\n name: \"minimax-speech\",\n label: \"MiniMax Speech\",\n modality: \"tts\",\n requiredEnv: [\"MINIMAX_API_KEY\"],\n optionalEnv: [\"MINIMAX_BASE_URL\"],\n timeoutSeconds: 600,\n reference: \"short-drama-produce/references/providers/minimax-speech.md\"\n }\n];\n\n/** Directory owned by this user: `/tmp` is world-writable on Linux, so the name carries the uid. */\nfunction generatedDirectory(temporaryRoot: string): string {\n const uid = process.getuid?.();\n return join(temporaryRoot, uid === undefined ? \"oh-story-dsh\" : `oh-story-dsh-${String(uid)}`);\n}\n\n/**\n * The generated file is keyed by the skill root so two DSH profiles running\n * different plugin installs never overwrite each other's registration.\n */\nexport function dramaAdapterConfigPath(skillRoot: string, env: NodeJS.ProcessEnv = process.env, temporaryRoot = tmpdir()): DramaAdapterConfigLocation {\n const custom = env[DRAMA_ADAPTER_CONFIG_ENV] ?? \"\";\n if (custom !== \"\") return { path: resolve(custom), generated: false };\n const key = createHash(\"sha256\").update(resolve(skillRoot)).digest(\"hex\").slice(0, 12);\n return { path: join(generatedDirectory(temporaryRoot), `drama-adapters-${key}.json`), generated: true };\n}\n\n/**\n * The file's content becomes an argv that `production_tool.py` executes, so it\n * is written only into a directory this process owns: a pre-existing directory\n * that belongs to someone else, or a symlink, is refused rather than reused.\n */\nasync function privateDirectory(path: string): Promise<boolean> {\n await mkdir(path, { recursive: true, mode: 0o700 });\n const info = await lstat(path);\n if (!info.isDirectory()) return false;\n const uid = process.getuid?.();\n return uid === undefined || info.uid === uid;\n}\n\n/** The upstream adapter-config document: argv commands and timeouts only, never credentials. */\nexport function dramaAdapterConfigDocument(skillRoot: string, python = \"python3\"): {\n readonly adapters: Record<string, { readonly command: readonly string[]; readonly timeout_seconds: number }>;\n} {\n const script = resolve(skillRoot, PROVIDER_SCRIPT);\n const adapters: Record<string, { readonly command: readonly string[]; readonly timeout_seconds: number }> = {};\n for (const adapter of DRAMA_ADAPTERS) {\n adapters[adapter.name] = { command: [python, script, adapter.name], timeout_seconds: adapter.timeoutSeconds };\n }\n return { adapters };\n}\n\n/**\n * Register the bundled adapters for this host. A creator-owned config is left\n * untouched and only checked for existence.\n */\nexport async function ensureDramaAdapterConfig(\n skillRoot: string,\n options: { readonly python?: string; readonly env?: NodeJS.ProcessEnv; readonly temporaryRoot?: string } = {}\n): Promise<DramaAdapterConfigLocation & { readonly ok: boolean }> {\n const location = dramaAdapterConfigPath(skillRoot, options.env ?? process.env, options.temporaryRoot ?? tmpdir());\n if (!location.generated) {\n return { ...location, ok: await access(location.path).then(() => true, () => false) };\n }\n try {\n if (!(await privateDirectory(dirname(location.path)))) return { ...location, ok: false };\n const existing = await lstat(location.path).catch(() => undefined);\n if (existing !== undefined && !existing.isFile()) return { ...location, ok: false };\n // Temp file + rename: a reader never sees a truncated document.\n const staging = `${location.path}.${String(process.pid)}.tmp`;\n await writeFile(staging, `${JSON.stringify(dramaAdapterConfigDocument(skillRoot, options.python ?? \"python3\"), null, 2)}\\n`, { encoding: \"utf8\", mode: 0o600 });\n await rename(staging, location.path);\n return { ...location, ok: true };\n } catch {\n return { ...location, ok: false };\n }\n}\n\n/** Presence only: a variable counts as configured when it is set and non-empty. */\nexport function dramaAdapterStatuses(env: NodeJS.ProcessEnv = process.env): DramaAdapterStatus[] {\n return DRAMA_ADAPTERS.map((adapter) => {\n const missing = adapter.requiredEnv.filter((name) => (env[name] ?? \"\") === \"\");\n return { name: adapter.name, label: adapter.label, modality: adapter.modality, configured: missing.length === 0, missing };\n });\n}\n\n/** One line per adapter for Skill text: `gpt-image-2 (image: OPENAI_API_KEY)`. */\nexport function dramaAdapterSummary(): string {\n return DRAMA_ADAPTERS.map((adapter) => `${adapter.name} (${adapter.modality}: ${adapter.requiredEnv.join(\" + \")})`).join(\", \");\n}\n", "import { execFile } from \"node:child_process\";\nimport { promisify } from \"node:util\";\n\nconst execFileAsync = promisify(execFile);\n\nexport interface PythonProbe { readonly ok: boolean; readonly version?: string | undefined }\n\nexport async function commandOutput(command: string, args: readonly string[]): Promise<string | undefined> {\n try {\n const { stdout, stderr } = await execFileAsync(command, [...args], { encoding: \"utf8\", timeout: 5_000, maxBuffer: 4 * 1_024 * 1_024 });\n return `${stdout}${stderr}`.trim();\n } catch { return undefined; }\n}\n\n/** Upstream Skills require Python 3.10+. */\nexport function pythonVersion(value: string | undefined): PythonProbe {\n const match = /Python\\s+(\\d+)\\.(\\d+)(?:\\.(\\d+))?/u.exec(value ?? \"\");\n if (match === null) return { ok: false };\n const major = Number(match[1]);\n const minor = Number(match[2]);\n return { ok: major > 3 || (major === 3 && minor >= 10), version: match[0].replace(/^Python\\s+/u, \"\") };\n}\n\n/**\n * The interpreter the host will run upstream scripts with. The first command\n * that meets the version floor wins; an interpreter that answers but is too old\n * is reported only when nothing better exists, so `python3` at 3.9 does not hide\n * `python` at 3.12. The command is written into the adapter config's argv, so\n * this is the same choice everywhere the plugin starts Python.\n */\nexport async function hostPython(probe: (command: string, args: readonly string[]) => Promise<string | undefined> = commandOutput): Promise<{ readonly command: string; readonly probe: PythonProbe }> {\n let fallback: { readonly command: string; readonly probe: PythonProbe } | undefined;\n for (const command of [\"python3\", \"python\"]) {\n const parsed = pythonVersion(await probe(command, [\"--version\"]));\n if (parsed.ok) return { command, probe: parsed };\n if (parsed.version !== undefined) fallback ??= { command, probe: parsed };\n }\n return fallback ?? { command: \"python3\", probe: { ok: false } };\n}\n", "import type { Context } from \"@deepseek-ai/cordis\";\nimport type { FileSystem, FsDirEntry, FsTarget } from \"@deepseek-ai/dsh-fs\";\nimport { boundContextSummary, createUserMessage, type ContextFormed } from \"@deepseek-ai/dsh-llm\";\nimport type {} from \"@deepseek-ai/dsh-session\";\nimport type { PostToolDecision, PreToolDecision, ToolExecution } from \"@deepseek-ai/dsh-tools\";\nimport { observeOhStoryRoleDescriptor, ohStoryRoleOfSession } from \"./role-identity.js\";\n\ndeclare module \"@deepseek-ai/dsh-llm\" {\n interface MessageSourceMap {\n /** DSH 0.1.7 dropped the shared `plugin` kind: each producer declares its own. */\n \"oh-story-post-write\": { kind: \"oh-story-post-write\" } & ContextFormed;\n }\n}\n\nconst MUTATION_TOOLS = new Set([\"write\", \"edit\", \"str_replace_editor\"]);\n\nexport interface StoryMutation {\n readonly root: string;\n /** Workspace-relative path of the mutated \u6B63\u6587 file. */\n readonly path: string;\n readonly chapter?: number;\n}\n\nfunction argumentRecord(args: unknown): Record<string, unknown> | undefined {\n return typeof args === \"object\" && args !== null && !Array.isArray(args) ? args as Record<string, unknown> : undefined;\n}\n\nfunction mutationPath(name: string, args: unknown): string | undefined {\n const record = argumentRecord(args);\n if (!MUTATION_TOOLS.has(name) || record === undefined) return undefined;\n if (name === \"str_replace_editor\") {\n if (!new Set([\"create\", \"str_replace\", \"insert\"]).has(String(record.command))) return undefined;\n return typeof record.path === \"string\" && record.path.trim() !== \"\" ? record.path : undefined;\n }\n return typeof record.file_path === \"string\" && record.file_path.trim() !== \"\" ? record.file_path : undefined;\n}\n\nfunction normalizedRelativePath(path: string): string | undefined {\n const segments: string[] = [];\n for (const part of path.split(\"/\")) {\n if (part === \"\" || part === \".\") continue;\n if (part === \"..\") {\n if (segments.length === 0) return undefined;\n segments.pop();\n } else segments.push(part);\n }\n return segments.join(\"/\");\n}\n\n/**\n * Split a workspace-relative path into the book that owns its \u6B63\u6587/ directory\n * and the file name. The book is \"\" when the workspace root is the book (the\n * DSH single-book layout); upstream imports and multi-book workspaces put it\n * in a subdirectory such as `{\u4E66\u540D}/\u6B63\u6587/`.\n */\nfunction proseLocation(path: string): { readonly book: string; readonly name: string } | undefined {\n const segments = path.split(\"/\");\n if (segments.length < 2) return undefined;\n const index = segments.lastIndexOf(\"\u6B63\u6587\", segments.length - 2);\n if (index < 0) return undefined;\n return { book: segments.slice(0, index).join(\"/\"), name: segments.at(-1) ?? \"\" };\n}\n\nfunction inBook(book: string, path: string): string {\n return book === \"\" ? path : `${book}/${path}`;\n}\n\nfunction lastSegment(path: string): string {\n return path.replaceAll(\"\\\\\", \"/\").split(\"/\").filter((part) => part !== \"\").at(-1) ?? \"\";\n}\n\nexport function detectStoryMutation(name: string, args: unknown, cwd: string | undefined): StoryMutation | undefined {\n const rawPath = mutationPath(name, args);\n if (cwd === undefined || rawPath === undefined) return undefined;\n const root = cwd.replaceAll(\"\\\\\", \"/\").replace(/\\/$/u, \"\");\n const candidate = rawPath.replaceAll(\"\\\\\", \"/\");\n const absolute = candidate.startsWith(\"/\") || /^[a-z]:\\//iu.test(candidate) || /^[a-z][a-z\\d+.-]*:\\/\\//iu.test(candidate);\n const insideRoot = /^[a-z]:\\//iu.test(root)\n ? candidate.toLowerCase().startsWith(`${root.toLowerCase()}/`)\n : candidate.startsWith(`${root}/`);\n if (absolute && !insideRoot) return undefined;\n const normalized = normalizedRelativePath(absolute ? candidate.slice(root.length + 1) : candidate);\n if (normalized === undefined) return undefined;\n const location = proseLocation(normalized);\n if (location === undefined) return undefined;\n const chapterText = /^\u7B2C0*(\\d+)\u7AE0/u.exec(location.name)?.[1];\n return { root, path: normalized, ...(chapterText === undefined ? {} : { chapter: Number(chapterText) }) };\n}\n\ntype StoryFileSystem = Pick<FileSystem, \"resolve\" | \"contains\" | \"stat\" | \"listDir\"> & Partial<Pick<FileSystem, \"readBytes\">>;\n\nasync function storyMutation(exec: ToolExecution, fs: StoryFileSystem): Promise<StoryMutation | undefined> {\n const cwd = exec.agent?.session.header.cwd;\n const path = mutationPath(exec.name, exec.arguments);\n if (cwd === undefined || path === undefined) return undefined;\n try {\n const [rootTarget, mutationTarget] = await Promise.all([\n fs.resolve(cwd, { signal: exec.signal }),\n fs.resolve(path, { cwd, signal: exec.signal })\n ]);\n if (!fs.contains(rootTarget, mutationTarget)) return undefined;\n } catch { return undefined; }\n return detectStoryMutation(exec.name, exec.arguments, cwd);\n}\n\nasync function target(fs: StoryFileSystem, root: string, path: string, signal?: AbortSignal): Promise<FsTarget> {\n return fs.resolve(path, { cwd: root, ...(signal === undefined ? {} : { signal }) });\n}\n\nasync function exists(fs: StoryFileSystem, root: string, path: string, signal?: AbortSignal): Promise<boolean> {\n return target(fs, root, path, signal)\n .then((value) => fs.stat(value, signal))\n .then((info) => info !== undefined, () => false);\n}\n\n/** A long-form book has \u5927\u7EB2/ or \u8FFD\u8E2A/; plain workspaces that merely contain \u6B63\u6587/ stay unguarded. */\nasync function isLongFormBook(fs: StoryFileSystem, root: string, book: string, signal?: AbortSignal): Promise<boolean> {\n return await exists(fs, root, inBook(book, \"\u5927\u7EB2\"), signal) || await exists(fs, root, inBook(book, \"\u8FFD\u8E2A\"), signal);\n}\n\n/** Upstream story_hook_core.js `OUTLINE_MIN_CHARS` (Oh Story 0.8.1). */\nconst OUTLINE_MIN_CHARS = 30;\nconst OUTLINE_READ_LIMIT = 64 * 1024;\n\n/**\n * Upstream `outlineIsEmpty`: after a BOM and each line's leading `#`s, fewer than\n * {@link OUTLINE_MIN_CHARS} characters other than whitespace (full-width space\n * included). A file that cannot be read or is not UTF-8 counts as written, as upstream.\n */\nasync function outlineIsEmpty(fs: StoryFileSystem, outline: FsTarget, signal?: AbortSignal): Promise<boolean> {\n if (fs.readBytes === undefined) return false;\n let text: string;\n try { text = new TextDecoder(\"utf-8\", { fatal: true, ignoreBOM: true }).decode(await fs.readBytes(outline, signal, OUTLINE_READ_LIMIT)); }\n catch { return false; }\n if (text.startsWith(\"\\uFEFF\")) text = text.slice(1);\n const body = text.split(\"\\n\").map((line) => line.replace(/^[ \\t]*#+/u, \"\")).join(\"\");\n return Array.from(body.replace(/[ \\t\\r\\n\\f\\v\\u3000]/gu, \"\")).length < OUTLINE_MIN_CHARS;\n}\n\n/** The chapter's \u7EC6\u7EB2 files; any one with content satisfies the gate, as upstream. */\nasync function chapterOutlines(fs: StoryFileSystem, root: string, book: string, chapter: number, signal?: AbortSignal): Promise<FsDirEntry[]> {\n const entries = await target(fs, root, inBook(book, \"\u5927\u7EB2\"), signal)\n .then((directory) => fs.listDir(directory, signal))\n .catch(() => []);\n return entries.filter((entry) => entry.type === \"file\"\n && Number(/^\u7EC6\u7EB2_\u7B2C0*(\\d+)\u7AE0.*\\.md$/u.exec(entry.name)?.[1]) === chapter)\n .sort((left, right) => (left.name < right.name ? -1 : left.name > right.name ? 1 : 0));\n}\n\nconst TRACKING_STATE = \"\u8FFD\u8E2A/_tracking-state.json\";\n\n/**\n * DSH's explicit import-window marker, relative to the book directory (the\n * workspace root in DSH's single-book layout). The story-import overlay has\n * the model create it before copying chapters and delete it once\n * `tracking_commit.py init` and `check` succeed.\n */\nexport const IMPORT_MARKER = \".story/work/\u5BFC\u5165\u4E2D.md\";\n\nasync function hasTrackingState(fs: StoryFileSystem, root: string, book: string, signal?: AbortSignal): Promise<boolean> {\n return exists(fs, root, inBook(book, TRACKING_STATE), signal);\n}\n\n/**\n * Upstream story-import Phase 3-L creates \u5927\u7EB2/ and \u8FFD\u8E2A/ (Step 1) and copies\n * the manuscript into \u6B63\u6587/ (Step 2) long before it writes \u7EC6\u7EB2 (Step 6) and\n * runs `tracking_commit.py init` (Step 7). Upstream recognises that window by\n * `\u62C6\u6587\u5E93/{basename(\u4E66\u76EE\u5F55)}`; in DSH's single-book layout the book is the\n * workspace root, so that key must equal the workspace folder name and rarely\n * does. DSH therefore also accepts its own marker, {@link IMPORT_MARKER}.\n * Any other `\u62C6\u6587\u5E93/*` entry \u2014 an analysed \u5BF9\u6807 book \u2014 is never a signal.\n */\nasync function hasImportSignal(fs: StoryFileSystem, root: string, book: string, signal?: AbortSignal): Promise<boolean> {\n if (await exists(fs, root, inBook(book, IMPORT_MARKER), signal)) return true;\n const bookName = book === \"\" ? lastSegment(root) : lastSegment(book);\n return bookName !== \"\" && await exists(fs, root, `\u62C6\u6587\u5E93/${bookName}`, signal);\n}\n\n/**\n * Mirrors the outline gate of upstream Oh Story's prose guard\n * (`proseBlockReason`) for books with \u5927\u7EB2/ or \u8FFD\u8E2A/: creating a new\n * `\u6B63\u6587/\u7B2CN\u7AE0*.md` requires a `\u5927\u7EB2/\u7EC6\u7EB2_\u7B2CN\u7AE0*.md` that is not empty, whether or not Tracking\n * exists yet. The one bypass is an import window \u2014 an import signal while the\n * book has no `\u8FFD\u8E2A/_tracking-state.json`. Rewriting an existing chapter is not\n * gated on its outline.\n *\n * It leaves out the rest of proseBlockReason: the Tracking checkpoint (state\n * present and at schema_version 4, \u4E0A\u4E0B\u6587.md at the same state revision, the\n * previous chapter committed), the previous chapter's toxic-phrase debt, the\n * short-story gate that wants \u5C0F\u8282\u5927\u7EB2.md before \u6B63\u6587.md, and shell-write\n * targets (redirection, cp, tee, scripts), which DSH hooks do not see as file\n * mutations \u2014 the story-long-write overlay asks for write/edit instead. It also\n * leaves a workspace with \u6B63\u6587/ but neither \u5927\u7EB2/ nor \u8FFD\u8E2A/ unguarded.\n */\nexport async function validateStoryMutation(\n fs: StoryFileSystem,\n mutation: StoryMutation,\n signal?: AbortSignal\n): Promise<string | undefined> {\n const location = proseLocation(mutation.path);\n if (mutation.chapter === undefined || location === undefined) return undefined;\n const { book } = location;\n if (!(await isLongFormBook(fs, mutation.root, book, signal))) return undefined;\n if (await exists(fs, mutation.root, mutation.path, signal)) return undefined;\n if (!(await hasTrackingState(fs, mutation.root, book, signal)) && await hasImportSignal(fs, mutation.root, book, signal)) {\n return undefined;\n }\n const outlines = await chapterOutlines(fs, mutation.root, book, mutation.chapter, signal);\n const [first] = outlines;\n if (first !== undefined) {\n for (const outline of outlines) if (!(await outlineIsEmpty(fs, outline.target, signal))) return undefined;\n return `Oh Story \u963B\u6B62\u5199\u5165\u7B2C ${String(mutation.chapter)} \u7AE0\uFF1A\u7EC6\u7EB2 ${inBook(book, \"\u5927\u7EB2\")}/${first.name} \u662F\u7A7A\u7684\uFF08\u4E0D\u8BA1 # \u53F7\u548C\u7A7A\u767D\u4E0D\u5230 ${String(OUTLINE_MIN_CHARS)} \u5B57\uFF09\u3002`\n + \"\u5148\u6309 story-long-write \u5355\u7AE0\u6D41\u7A0B\u628A\u7EC6\u7EB2\u5199\u5B8C\u6574\uFF08\u8FD9\u7AE0\u53D1\u751F\u4EC0\u4E48\u3001\u4E3B\u89D2\u505A\u4EC0\u4E48\u9009\u62E9\uFF09\uFF0C\u518D\u5199\u6B63\u6587\u3002\";\n }\n const padded = String(mutation.chapter).padStart(3, \"0\");\n return `Oh Story \u963B\u6B62\u5199\u5165\u7B2C ${String(mutation.chapter)} \u7AE0\uFF1A\u672A\u627E\u5230\u5BF9\u5E94\u7684 ${inBook(book, \"\u5927\u7EB2\")}/\u7EC6\u7EB2_\u7B2C${padded}\u7AE0*.md\u3002`\n + \"\u5148\u6309 story-long-write \u5355\u7AE0\u6D41\u7A0B\u8865\u5EFA\u7EC6\u7EB2\u518D\u5199\u6B63\u6587\u3002\";\n}\n\nexport async function decideStoryMutation(\n exec: ToolExecution,\n next: () => Promise<PreToolDecision>\n): Promise<PreToolDecision> {\n const fs = exec.agent?.ctx.get(\"fs\");\n if (fs === undefined) return next();\n const mutation = await storyMutation(exec, fs);\n if (mutation === undefined) return next();\n const reason = await validateStoryMutation(fs, mutation, exec.signal);\n if (reason !== undefined) return { kind: \"deny\", reason };\n return next();\n}\n\nconst ANALYSIS_INPUT = /^\u8F93\u5165-(RAW|REUSE)-(\\d+)-(\\d+)\\.md$/u;\nconst ANALYSIS_INPUT_RULE = \"\u53EA\u5141\u8BB8\u5199\u8C03\u7528\u65B9\u7ED9\u7684 {\u62C6\u6587\u76EE\u5F55}/_analysis_cache/\u8F93\u5165-{\u6279\u6B21ID}.md\uFF08\u6279\u6B21 ID \u5982 RAW-4-6\uFF09\uFF0C\u4E0D\u5199\u5176\u4ED6\u6587\u4EF6\u3002\";\n\nfunction isFileMutationCall(name: string, args: unknown): boolean {\n if (name === \"write\" || name === \"edit\") return true;\n return name === \"str_replace_editor\" && argumentRecord(args)?.command !== \"view\";\n}\n\nfunction displayParent(path: string): string {\n const index = Math.max(path.lastIndexOf(\"/\"), path.lastIndexOf(\"\\\\\"));\n return index <= 0 ? path.slice(0, index + 1) : path.slice(0, index);\n}\n\nfunction displayName(path: string): string {\n return path.slice(Math.max(path.lastIndexOf(\"/\"), path.lastIndexOf(\"\\\\\")) + 1);\n}\n\nasync function isAnalysisDirectory(fs: StoryFileSystem, directory: string, signal?: AbortSignal): Promise<boolean> {\n return await exists(fs, directory, \"chapter_index.csv\", signal) || await exists(fs, directory, \"_progress.md\", signal);\n}\n\n/**\n * Mirror of upstream's `analysis-input-guard` (story_hook_cli.js): the\n * chapter-extractor may write or edit only\n * `{\u62C6\u6587\u76EE\u5F55}/_analysis_cache/\u8F93\u5165-{RAW|REUSE}-{\u8D77\u7AE0}-{\u6B62\u7AE0}.md`, where the\n * \u62C6\u6587\u76EE\u5F55 holds `chapter_index.csv` or `_progress.md` and lies inside the\n * workspace. The commit script still validates the file's content.\n */\nexport async function validateAnalysisInputWrite(\n fs: StoryFileSystem,\n cwd: string,\n path: string | undefined,\n signal?: AbortSignal\n): Promise<string | undefined> {\n const deny = (shown: string, reasons: readonly string[]): string =>\n `Oh Story \u963B\u6B62 chapter-extractor \u5199\u5165 ${shown}\uFF1A${reasons.join(\"\uFF1B\")}\u3002${ANALYSIS_INPUT_RULE}`;\n if (path === undefined) return deny(\"\uFF08\u672A\u7ED9\u51FA\u8DEF\u5F84\uFF09\", [\"\u5199\u5165\u6CA1\u6709\u7ED9\u51FA\u6587\u4EF6\u8DEF\u5F84\"]);\n let rootTarget: FsTarget;\n let fileTarget: FsTarget;\n try {\n [rootTarget, fileTarget] = await Promise.all([\n fs.resolve(cwd, signal === undefined ? {} : { signal }),\n fs.resolve(path, { cwd, ...(signal === undefined ? {} : { signal }) })\n ]);\n } catch {\n return deny(path, [\"\u8DEF\u5F84\u65E0\u6CD5\u89E3\u6790\"]);\n }\n const reasons: string[] = [];\n const match = ANALYSIS_INPUT.exec(displayName(fileTarget.displayPath));\n if (match === null) reasons.push(\"\u6587\u4EF6\u540D\u5FC5\u987B\u662F \u8F93\u5165-{RAW|REUSE}-{\u8D77\u7AE0}-{\u6B62\u7AE0}.md\");\n else if (Number(match[2]) < 1 || Number(match[3]) < Number(match[2])) reasons.push(\"\u6279\u6B21\u7AE0\u53F7\u8303\u56F4\u65E0\u6548\");\n const cacheDirectory = displayParent(fileTarget.displayPath);\n if (displayName(cacheDirectory) !== \"_analysis_cache\") reasons.push(\"\u53EA\u80FD\u5199\u5728\u62C6\u6587\u76EE\u5F55\u7684 _analysis_cache/ \u4E0B\");\n else if (!(await isAnalysisDirectory(fs, displayParent(cacheDirectory), signal))) {\n reasons.push(\"\u4E0A\u7EA7\u76EE\u5F55\u4E0D\u662F\u62C6\u6587\u76EE\u5F55\uFF08\u7F3A chapter_index.csv \u4E0E _progress.md\uFF09\");\n }\n if (!fs.contains(rootTarget, fileTarget)) reasons.push(\"\u8DEF\u5F84\u5728\u9879\u76EE\u76EE\u5F55\u4E4B\u5916\");\n return reasons.length === 0 ? undefined : deny(path, reasons);\n}\n\n/**\n * Fence file mutations by a chapter-extractor child to its batch input file.\n * The child is identified by the Role DSH recorded in its Session descriptor,\n * so other Roles and the main Agent are unaffected.\n */\nexport async function decideChapterExtractorWrite(\n exec: ToolExecution,\n next: () => Promise<PreToolDecision>\n): Promise<PreToolDecision> {\n if (ohStoryRoleOfSession(exec.agent?.session) !== \"chapter-extractor\" || !isFileMutationCall(exec.name, exec.arguments)) {\n return next();\n }\n const fs = exec.agent?.ctx.get(\"fs\");\n const cwd = exec.agent?.session.header.cwd;\n const reason = fs === undefined || cwd === undefined\n ? `Oh Story \u963B\u6B62 chapter-extractor \u5199\u5165\uFF1A\u65E0\u6CD5\u786E\u8BA4\u9879\u76EE\u76EE\u5F55\u3002${ANALYSIS_INPUT_RULE}`\n : await validateAnalysisInputWrite(fs, cwd, mutationPath(exec.name, exec.arguments), exec.signal);\n return reason === undefined ? next() : { kind: \"deny\", reason };\n}\n\nexport interface PostWriteReminderOptions {\n /** The book has no \u8FFD\u8E2A/_tracking-state.json and no import signal. */\n readonly trackingUninitialized?: boolean;\n}\n\nexport function postWriteReminderText(path: string, options: PostWriteReminderOptions = {}): string {\n return [\n `<oh-story-post-write>\u6B63\u6587 ${path} \u5DF2\u53D8\u66F4\u3002`,\n \"\u6BCF\u6B21\u5199\u5165\u6B63\u6587\u90FD\u4F1A\u51FA\u73B0\u8FD9\u6761\u63D0\u9192\uFF0C\u4E00\u7AE0\u5199\u5230\u4E00\u534A\u65F6\u4E5F\u4F1A\uFF1B\u5B83\u4E0D\u8868\u793A\u672C\u7AE0\u5DF2\u7ECF\u5B8C\u6210\uFF0C\u4E5F\u4E0D\u662F\u4F5C\u8005\u7684\u65B0\u5199\u4F5C\u8981\u6C42\uFF0C\u7EE7\u7EED\u5F53\u524D\u6B65\u9AA4\u5373\u53EF\u3002\",\n ...options.trackingUninitialized === true\n ? [\n \"\u672C\u4E66\u8FD8\u6CA1\u6709 \u8FFD\u8E2A/_tracking-state.json\u3002\u65B0\u4E66\u5199\u7B2C\u4E00\u7AE0\u65F6\uFF0Cdraft \u4E4B\u524D\u5148\u6309 story-long-write workflow-chapter \u5F00\u5934\u7684\u521D\u59CB\u5316\u6B65\u9AA4\u5B8C\u6574\u8BFB\u53D6 references/tracking-initialization.md\uFF0C\u6784\u9020 last_chapter=0 \u7684\u521D\u59CB\u5316\u4E8B\u52A1\u5B58\u4E66\u76EE\u5F55 .story/work/init.json\uFF0C\u8FD0\u884C scripts/tracking_commit.py init\uFF0C\u518D\u8FD0\u884C tracking_commit.py check\uFF0C\u901A\u8FC7\u540E\u5220\u6389 init.json\uFF1B\",\n \"\u4E66\u91CC\u5728\u672C\u7AE0\u4E4B\u524D\u5DF2\u6709\u6B63\u6587\u65F6\u4E0D\u8981\u521D\u59CB\u5316\uFF0C\u505C\u4E0B\u6765\u6539\u8D70 story-import \u7684\u300C\u65E7\u8FFD\u8E2A\u9879\u76EE\u8FC1\u79FB\u300D\u3002\"\n ]\n : [],\n \"\u7B49\u672C\u7AE0\u5199\u5B8C\u6536\u5C3E\u65F6\u518D\u63D0\u4EA4\u8FFD\u8E2A\uFF1A\u65B0\u7AE0\u5148\u7528 story-long-write \u7684 scripts/tracking_commit.py draft \u751F\u6210\u672C\u7AE0\u8349\u7A3F\uFF0C\u586B\u597D\u540E\u6267\u884C scripts/storyctl.py chapter commit\uFF08\u4F5C\u8005\u63A5\u53D7\u5F53\u524D\u957F\u5EA6\u65F6\u7528 chapter accept-current-length\uFF09\uFF1B\",\n \"\u4FEE\u6539\u5DF2\u63D0\u4EA4\u7684\u7AE0\u8282\u6309 workflow-revision \u63D0\u4EA4\u4E00\u6B21 mode=revision \u4E8B\u52A1\uFF1B\u5BFC\u5165\u65E2\u6709\u6B63\u6587\u65F6\u7531 story-import \u5728\u8FC1\u79FB\u540E\u7528 tracking_commit.py init \u7EDF\u4E00\u521D\u59CB\u5316\u3002\",\n \"\u8FFD\u8E2A/_tracking-state.json \u4EE5\u53CA \u4E0A\u4E0B\u6587.md\u3001\u89D2\u8272\u72B6\u6001/\u3001\u4F0F\u7B14.md\u3001\u65F6\u95F4\u7EBF/\u3001\u9010\u7AE0\u8BB0\u5F55/ \u7B49\u6D3E\u751F Tracking \u89C6\u56FE\u53EA\u7531\u8FD9\u4E9B\u811A\u672C\u5199\u5165\uFF0C\u7EDD\u4E0D\u624B\u6539\u3002</oh-story-post-write>\"\n ].join(\"\");\n}\n\n/**\n * Native DSH equivalents of the upstream prose guards. They join DSH's typed\n * tool waterfall, so decisions remain visible in the official approval/tool UI.\n */\nexport function registerOhStoryHooks(context: Context): void {\n context.on(\"session/event\", (session, event) => { observeOhStoryRoleDescriptor(session, event); });\n context.on(\"tools/pre-execute\", decideChapterExtractorWrite);\n context.on(\"tools/pre-execute\", decideStoryMutation);\n\n context.on(\"tools/post-execute\", async (exec, result, next): Promise<PostToolDecision> => {\n const downstream = await next();\n if (result.isError || downstream.kind !== \"accept\") return downstream;\n // Tracking is committed by the main session. oh_story_role children never\n // get the reminder: narrative-writer's Role body forbids writing Tracking.\n if (ohStoryRoleOfSession(exec.agent?.session) !== undefined) return downstream;\n const fs = exec.agent?.ctx.get(\"fs\");\n const mutation = fs === undefined ? undefined : await storyMutation(exec, fs);\n const location = mutation === undefined ? undefined : proseLocation(mutation.path);\n if (fs === undefined || mutation === undefined || location === undefined) return downstream;\n const { root } = mutation;\n const { book } = location;\n if (!(await isLongFormBook(fs, root, book, exec.signal))) return downstream;\n const trackingUninitialized = !(await hasTrackingState(fs, root, book, exec.signal))\n && !(await hasImportSignal(fs, root, book, exec.signal));\n const reminder = createUserMessage({\n source: { kind: \"oh-story-post-write\", form: \"notice\", summary: boundContextSummary(`\u6B63\u6587 ${mutation.path} \u5DF2\u53D8\u66F4`) },\n content: [{ type: \"text\", text: postWriteReminderText(mutation.path, { trackingUninitialized }) }]\n });\n return {\n ...downstream,\n additionalContexts: [...downstream.additionalContexts ?? [], reminder]\n };\n });\n}\n", "import { readFile } from \"node:fs/promises\";\nimport { basename, dirname, join, resolve } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nexport const OH_STORY_ROLE_NAMES = [\n \"chapter-extractor\",\n \"character-designer\",\n \"consistency-checker\",\n \"narrative-writer\",\n \"story-architect\",\n \"story-explorer\",\n \"story-researcher\"\n] as const;\n\nexport type OhStoryRoleName = typeof OH_STORY_ROLE_NAMES[number];\nexport type OhStoryRoleExecution = \"tool-free\" | \"native-tools\";\n\nfunction roleBody(source: string): string {\n const frontmatter = /^---\\r?\\n[\\s\\S]*?\\r?\\n---\\r?\\n?/u.exec(source);\n return source.slice(frontmatter?.[0].length ?? 0).trim();\n}\n\nexport function defaultBundledRoleRoot(): string {\n const current = dirname(fileURLToPath(import.meta.url));\n return basename(current) === \"src\"\n ? resolve(current, \"../../knowledge/oh-story/roles\")\n : resolve(current, \"oh-story/roles\");\n}\n\nexport async function loadBundledRole(\n name: OhStoryRoleName,\n roleRoot = defaultBundledRoleRoot(),\n execution: OhStoryRoleExecution = \"tool-free\"\n): Promise<string> {\n const body = roleBody(await readFile(join(resolve(roleRoot), `${name}.md`), \"utf8\"));\n if (body.length === 0) throw new Error(`Bundled role \"${name}\" is empty.`);\n const integration = execution === \"tool-free\"\n ? [\n \"You are running inside an Oh Story review-required DSH collaboration. The caller supplies every permitted input in the prompt.\",\n \"Do not read or write project files, do not call tools, and do not follow legacy .claude/.codex path or deployment instructions in the upstream role text.\",\n \"Return only the output contract requested by the caller; never claim to have changed the project.\"\n ]\n : [\n \"You are running as a native oh-story-dsh specialist. The current DSH workspace and visible tool set are your complete authority boundary.\",\n \"Never inspect or require legacy .claude/.opencode/.codex agent deployment files; this exact pinned Role is already active.\",\n \"Bundled story-setup references are pinned plugin resources, not project files or project Skills. When the upstream Role marks one mandatory, call oh_story_bundled_reference with the exact story-setup/references/agent-references path, then use only the returned content.\",\n \"If oh_story_bundled_reference or a required bundled reference is unavailable, report the missing reference to the caller. Never call the generic skill tool, fall back to a legacy platform path, or claim that an unread reference was used.\",\n \"Use only the tools actually visible to you. Mutate files only when the caller explicitly requests it and your visible DSH tools permit it; otherwise return findings to the caller.\"\n ];\n return [\n `OH_STORY_DSH_ROLE:${name}`,\n ...integration,\n \"\",\n body\n ].join(\"\\n\");\n}\n", "import type { Session, SessionEvent } from \"@deepseek-ai/dsh-session\";\nimport type {} from \"@deepseek-ai/dsh-subagent\";\nimport { OH_STORY_ROLE_NAMES, type OhStoryRoleName } from \"./role-provider.js\";\n\nconst ROLE_LABEL_PREFIX = \"oh-story:\";\n\n/** The durable creation label oh_story_role gives every child it starts. */\nexport function ohStoryRoleLabel(role: OhStoryRoleName): string {\n return `${ROLE_LABEL_PREFIX}${role}`;\n}\n\nfunction roleFromLabel(label: unknown): OhStoryRoleName | undefined {\n if (typeof label !== \"string\" || !label.startsWith(ROLE_LABEL_PREFIX)) return undefined;\n const name = label.slice(ROLE_LABEL_PREFIX.length);\n return OH_STORY_ROLE_NAMES.find((role) => role === name);\n}\n\n// Keyed by the live Session object: a one-shot child keeps one Session for its\n// whole life, and a WeakMap releases the entry with the child.\nconst roleSessions = new WeakMap<Session, OhStoryRoleName>();\n\n/**\n * Record the Role of a child whose Session DSH has just stamped with its\n * `subagent/descriptor`. The in-process spawn driver appends that event inside\n * the child's first step, before its first model request, so the identity is\n * known before the child can call any tool. The first descriptor is\n * authoritative, as in DSH's own `foldSubagentDescriptor`.\n */\nexport function observeOhStoryRoleDescriptor(session: Session, event: SessionEvent): void {\n if (event.type !== \"subagent/descriptor\" || roleSessions.has(session)) return;\n const role = roleFromLabel((event.data as { readonly label?: unknown }).label);\n if (role !== undefined) roleSessions.set(session, role);\n}\n\n/** Record a Role for a child Session the Role tool started itself. */\nexport function markOhStoryRoleSession(session: Session, role: OhStoryRoleName): void {\n if (!roleSessions.has(session)) roleSessions.set(session, role);\n}\n\n/** The Oh Story Role running in this Session, if it is an oh_story_role child. */\nexport function ohStoryRoleOfSession(session: Session | undefined): OhStoryRoleName | undefined {\n return session === undefined ? undefined : roleSessions.get(session);\n}\n", "import type { Context } from \"@deepseek-ai/cordis\";\nimport type { ContentBlock } from \"@deepseek-ai/dsh-llm\";\nimport type { SubagentRuntime } from \"@deepseek-ai/dsh-subagent\";\nimport type { JsonValue } from \"@deepseek-ai/dsh-util-values\";\nimport { defineTool, type ToolDefinition } from \"@deepseek-ai/dsh-tools\";\nimport {\n bundledReferenceGuard,\n createOhStoryReferenceTool,\n OH_STORY_REFERENCE_TOOL_NAME\n} from \"./reference-tool.js\";\nimport { markOhStoryRoleSession, ohStoryRoleLabel } from \"./role-identity.js\";\nimport { OH_STORY_ROLE_NAMES, loadBundledRole, type OhStoryRoleName } from \"./role-provider.js\";\n\nexport const OH_STORY_ROLE_TOOL_NAME = \"oh_story_role\";\nexport type OhStoryRoleSubagents = Pick<SubagentRuntime, \"start\">;\n\nconst roleTools: Readonly<Record<OhStoryRoleName, readonly string[]>> = {\n // Oh Story 0.8.0 lets the extractor write its own batch input file (never\n // bash). native-hooks fences write/edit to {\u62C6\u6587\u76EE\u5F55}/_analysis_cache/\u8F93\u5165-*.md.\n \"chapter-extractor\": [\"read\", \"glob\", \"grep\", \"write\", \"edit\"],\n \"character-designer\": [OH_STORY_REFERENCE_TOOL_NAME, \"read\", \"glob\", \"grep\", \"write\", \"edit\"],\n \"consistency-checker\": [OH_STORY_REFERENCE_TOOL_NAME, \"read\", \"glob\", \"grep\"],\n \"narrative-writer\": [OH_STORY_REFERENCE_TOOL_NAME, \"read\", \"glob\", \"grep\", \"write\", \"edit\", \"bash\"],\n \"story-architect\": [OH_STORY_REFERENCE_TOOL_NAME, \"read\", \"glob\", \"grep\", \"write\", \"edit\"],\n // Oh Story 0.8.2 moved benchmark_style_load's procedure into agent-references/benchmark-style-load.md.\n \"story-explorer\": [OH_STORY_REFERENCE_TOOL_NAME, \"read\", \"glob\", \"grep\"],\n \"story-researcher\": [\"read\", \"glob\", \"grep\", \"bash\", \"write\", \"web_search\", \"web_fetch\"]\n};\n\nexport function roleToolFilter(role: OhStoryRoleName): { readonly allow: readonly string[] } {\n return { allow: roleTools[role] };\n}\n\nfunction resultText(output: readonly ContentBlock[]): string {\n return output.map((block) => block.type === \"text\" ? block.text : JSON.stringify(block)).join(\"\\n\");\n}\n\nexport async function createOhStoryRoleTool(subagents?: OhStoryRoleSubagents): Promise<ToolDefinition> {\n const personas = new Map<OhStoryRoleName, string>();\n await Promise.all(OH_STORY_ROLE_NAMES.map(async (role) => {\n personas.set(role, await loadBundledRole(role, undefined, \"native-tools\"));\n }));\n return defineTool({\n name: OH_STORY_ROLE_TOOL_NAME,\n description: \"Run one focused Oh Story specialist as a child of the current DSH Agent. The child inherits DSH model, workspace, permissions, lifecycle, and UI.\",\n parameters: {\n role: {\n type: \"string\",\n required: true,\n enum: OH_STORY_ROLE_NAMES,\n description: \"The exact Oh Story Role to run.\"\n },\n prompt: {\n type: \"string\",\n required: true,\n description: \"A self-contained task. The child inherits the current DSH workspace but not the current in-flight turn.\"\n }\n },\n output: {\n schema: {\n type: \"object\",\n additionalProperties: false,\n properties: {\n role: { type: \"string\", required: true, enum: OH_STORY_ROLE_NAMES },\n runId: { type: \"string\", required: true },\n content: { type: \"array\", required: true, items: { type: \"json\" } }\n }\n },\n render: (_args, value) => [{ type: \"text\", text: resultText(value.content as unknown as ContentBlock[]) }]\n },\n isConcurrencySafe: () => true,\n async execute(args, exec) {\n if (exec.agent === undefined) throw new Error(\"oh_story_role requires a calling DSH Agent.\");\n const persona = personas.get(args.role);\n if (persona === undefined) throw new Error(`Oh Story Role ${args.role} is not bundled.`);\n const allowed = roleToolFilter(args.role).allow.filter((name) =>\n exec.agent?.ctx.tools.get(name, exec.agent) !== undefined);\n const runtime = subagents ?? exec.agent.ctx.get(\"subagents\");\n if (runtime === undefined) throw new Error(\"oh_story_role requires the DSH subagent runtime.\");\n const run = await runtime.start(\"spawn\", {\n // DSH persists this label in the child's subagent/descriptor; the\n // native hooks read the Role back from it before the child's first tool call.\n label: ohStoryRoleLabel(args.role),\n prompt: [{ type: \"text\", text: args.prompt }],\n parent: exec.agent,\n persona,\n toolFilter: { allow: allowed },\n maxDepth: 1,\n signal: exec.signal\n });\n if (run.localAgent !== undefined) markOhStoryRoleSession(run.localAgent.session, args.role);\n try {\n const result = await run.result;\n if (result.stopReason !== \"completed\") {\n throw new Error(`Oh Story Role ${args.role} ended with ${result.stopReason}${result.diagnostic === undefined ? \"\" : `: ${result.diagnostic}`}`);\n }\n return {\n role: args.role,\n runId: run.id,\n content: result.output as unknown as JsonValue[]\n };\n } finally {\n await run.dispose();\n }\n }\n });\n}\n\nexport async function registerOhStoryRoleTool(context: Context): Promise<void> {\n const [definition, referenceDefinition] = await Promise.all([\n createOhStoryRoleTool(context.subagents),\n createOhStoryReferenceTool()\n ]);\n context.tools.register(referenceDefinition);\n context.tools.guard(bundledReferenceGuard(referenceDefinition, context.tools));\n let dispose: (() => void) | undefined;\n const mount = (): void => { dispose ??= context.tools.register(definition); };\n const unmount = (): void => { dispose?.(); dispose = undefined; };\n context.on(\"subagent/provider-added\", (provider) => { if (provider.name === \"spawn\") mount(); });\n context.on(\"subagent/provider-removed\", (name) => { if (name === \"spawn\") unmount(); });\n if (context.subagents.getProvider(\"spawn\") !== undefined) mount();\n}\n", "import { readdir, readFile, realpath } from \"node:fs/promises\";\nimport { isAbsolute, join, relative, resolve } from \"node:path\";\nimport { defineTool, type ToolDefinition, type ToolGuard, type ToolRuntime } from \"@deepseek-ai/dsh-tools\";\nimport { defaultBundledSkillRoot } from \"./skill-provider.js\";\n\nexport const OH_STORY_REFERENCE_TOOL_NAME = \"oh_story_bundled_reference\";\n\ninterface BundledReference {\n readonly canonicalPath: string;\n readonly name: string;\n}\n\nasync function collectMarkdown(root: string, directory = root): Promise<string[]> {\n const entries = await readdir(directory, { withFileTypes: true });\n const nested = await Promise.all(entries.map(async (entry): Promise<string[]> => {\n const path = join(directory, entry.name);\n if (entry.isDirectory()) return collectMarkdown(root, path);\n return entry.isFile() && entry.name.endsWith(\".md\") ? [path] : [];\n }));\n return nested.flat();\n}\n\nasync function bundledReferences(storySetupRoot: string): Promise<readonly BundledReference[]> {\n const root = await realpath(resolve(storySetupRoot));\n const referenceRoot = await realpath(join(root, \"references\", \"agent-references\"));\n const referenceDirectory = relative(root, referenceRoot);\n if (referenceDirectory === \"\" || referenceDirectory.startsWith(\"..\") || isAbsolute(referenceDirectory)) {\n throw new Error(\"Bundled Oh Story reference directory escaped its package root.\");\n }\n const values = await Promise.all((await collectMarkdown(referenceRoot)).map(async (path): Promise<BundledReference> => {\n const canonicalPath = await realpath(path);\n const inside = relative(referenceRoot, canonicalPath);\n if (inside === \"\" || inside.startsWith(\"..\") || isAbsolute(inside)) {\n throw new Error(`Bundled Oh Story reference escaped its package root: ${path}`);\n }\n return {\n canonicalPath,\n name: `story-setup/references/agent-references/${inside.replaceAll(\"\\\\\", \"/\")}`\n };\n }));\n return values.sort((left, right) => left.name.localeCompare(right.name));\n}\n\nexport async function createOhStoryReferenceTool(\n storySetupRoot = join(defaultBundledSkillRoot(), \"story-setup\")\n): Promise<ToolDefinition> {\n const references = await bundledReferences(storySetupRoot);\n if (references.length === 0) throw new Error(\"No bundled Oh Story references were found.\");\n const paths = references.map((reference) => reference.name);\n const byName = new Map(references.map((reference) => [reference.name, reference.canonicalPath]));\n return defineTool({\n name: OH_STORY_REFERENCE_TOOL_NAME,\n description: \"Read one exact, pinned Oh Story story-setup reference bundled with this plugin. This does not resolve project Skills or workspace files.\",\n parameters: {\n reference: {\n type: \"string\",\n required: true,\n enum: paths,\n description: \"The exact story-setup reference path named by the active bundled Role.\"\n }\n },\n output: {\n schema: {\n type: \"object\",\n additionalProperties: false,\n properties: {\n reference: { type: \"string\", required: true },\n content: { type: \"string\", required: true }\n }\n },\n render: (_args, value) => [{\n type: \"text\",\n text: `Bundled Oh Story reference: ${value.reference}\\n\\n${value.content}`\n }]\n },\n isConcurrencySafe: () => true,\n async execute(args) {\n const path = byName.get(args.reference);\n if (path === undefined) throw new Error(`Oh Story reference is not bundled: ${args.reference}`);\n return { reference: args.reference, content: await readFile(path, \"utf8\") };\n }\n });\n}\n\n/** Deny a scoped same-name replacement instead of executing untrusted reference code. */\nexport function bundledReferenceGuard(\n definition: ToolDefinition,\n tools: Pick<ToolRuntime, \"get\">\n): ToolGuard {\n return (execution) => execution.name === OH_STORY_REFERENCE_TOOL_NAME\n && tools.get(OH_STORY_REFERENCE_TOOL_NAME, execution.agent) !== definition\n ? \"The pinned Oh Story reference tool was shadowed in this Agent scope.\"\n : undefined;\n}\n", "import type { Context } from \"@deepseek-ai/cordis\";\nimport { defineTool, type ToolDefinition } from \"@deepseek-ai/dsh-tools\";\nimport {\n OH_STORY_PRODUCTION_TOOL_NAME,\n PRODUCTION_INTENT_ACTIONS,\n PRODUCTION_INTENT_JOB_KINDS,\n PRODUCTION_INTENT_SECTIONS,\n validateProductionIntent,\n type ProductionIntentArgs\n} from \"./production-intent.js\";\n\nfunction intentMessage(intent: ProductionIntentArgs): string {\n if (intent.action === \"track_job\") return `\u5DF2\u628A ${intent.targetId ?? \"\u751F\u4EA7\u5BF9\u8C61\"} \u7684 ${intent.jobKind ?? \"\u5A92\u4F53\"} \u4EFB\u52A1\u6295\u5F71\u5230 ${intent.episode} \u7684\u4EFB\u52A1\u677F\u3002`;\n if (intent.action === \"set_sequence\") return `\u5DF2\u628A ${String(intent.shotIds?.length ?? 0)} \u4E2A\u955C\u5934\u7684\u987A\u5E8F\u53D1\u9001\u5230 ${intent.episode} \u6210\u7247\u89C6\u56FE\u3002`;\n if (intent.action === \"focus_target\") return `\u5DF2\u8BF7\u6C42 ${intent.episode} \u751F\u4EA7\u89C6\u56FE\u805A\u7126 ${intent.targetId ?? \"\u76EE\u6807\"}\u3002`;\n return `\u5DF2\u628A ${intent.action} \u754C\u9762\u610F\u56FE\u53D1\u9001\u5230 ${intent.episode} \u751F\u4EA7\u5DE5\u4F5C\u53F0\u3002`;\n}\n\nexport function createOhStoryProductionTool(): ToolDefinition {\n return defineTool({\n name: OH_STORY_PRODUCTION_TOOL_NAME,\n description: \"Operate the native oh-story short-drama production projection in the current DSH Session. It can open or focus semantic production targets, set an explicit shot order, or track a job the Agent is actually executing. It never controls cosmetic canvas layout, generates media, changes creator documents, or counts as creator confirmation for paid production.\",\n parameters: {\n action: { type: \"string\", required: true, enum: PRODUCTION_INTENT_ACTIONS, description: \"The exact production UI/task projection operation.\" },\n episode: { type: \"string\", required: true, description: \"Creator-first episode directory, for example \u5267\u96C6/EP001.\" },\n section: { type: \"string\", enum: PRODUCTION_INTENT_SECTIONS },\n targetId: { type: \"string\" },\n shotIds: { type: \"array\", items: { type: \"string\" } },\n jobId: { type: \"string\", description: \"Stable ID that must also appear in produced output filenames.\" },\n jobKind: { type: \"string\", enum: PRODUCTION_INTENT_JOB_KINDS },\n expectedOutputs: { type: \"integer\", description: \"Number of media files this job will produce. Repeat the count the creator approved when re-registering a batch; omit it to keep the count the workbench already recorded.\" },\n prompt: { type: \"string\", description: \"Exact prompt/specification for a tracked job; not a production authorization.\" }\n },\n output: {\n schema: {\n type: \"object\",\n additionalProperties: false,\n properties: {\n action: { type: \"string\", required: true, enum: PRODUCTION_INTENT_ACTIONS },\n episode: { type: \"string\", required: true },\n message: { type: \"string\", required: true }\n }\n },\n render: (_args, value) => [{ type: \"text\", text: value.message }]\n },\n isConcurrencySafe: () => true,\n execute(args) {\n const intent = validateProductionIntent(args);\n return Promise.resolve({ action: intent.action, episode: intent.episode, message: intentMessage(intent) });\n }\n });\n}\n\nexport function registerOhStoryProductionTool(context: Context): void {\n context.tools.register(createOhStoryProductionTool());\n}\n", "export const OH_STORY_PRODUCTION_TOOL_NAME = \"oh_story_production\";\n\nexport const PRODUCTION_INTENT_ACTIONS = [\n \"open_section\",\n \"focus_target\",\n \"set_sequence\",\n \"track_job\"\n] as const;\n\nexport const PRODUCTION_INTENT_SECTIONS = [\"shots\", \"assets\", \"tasks\", \"sequence\", \"canvas\"] as const;\nexport const PRODUCTION_INTENT_JOB_KINDS = [\"image\", \"video\", \"composition\"] as const;\n\nexport type ProductionIntentAction = typeof PRODUCTION_INTENT_ACTIONS[number];\nexport type ProductionIntentSection = typeof PRODUCTION_INTENT_SECTIONS[number];\nexport type ProductionIntentJobKind = typeof PRODUCTION_INTENT_JOB_KINDS[number];\n\nexport interface ProductionIntentArgs {\n readonly action: ProductionIntentAction;\n readonly episode: string;\n readonly section?: ProductionIntentSection | undefined;\n readonly targetId?: string | undefined;\n readonly shotIds?: readonly string[] | undefined;\n readonly jobId?: string | undefined;\n readonly jobKind?: ProductionIntentJobKind | undefined;\n readonly expectedOutputs?: number | undefined;\n readonly prompt?: string | undefined;\n}\n\nfunction requiredText(value: string | undefined, field: string): string {\n const normalized = value?.trim();\n if (!normalized) throw new Error(`oh_story_production ${field} is required for this action.`);\n if (normalized.length > 512) throw new Error(`oh_story_production ${field} is too long.`);\n return normalized;\n}\n\n/** Validate the cross-runtime UI intent without reading or mutating workspace state. */\nexport function validateProductionIntent(args: ProductionIntentArgs): ProductionIntentArgs {\n const episode = args.episode.trim().replaceAll(\"\\\\\", \"/\").replace(/\\/$/u, \"\");\n if (!/^\u5267\u96C6\\/EP\\d{3,}$/u.test(episode)) {\n throw new Error(\"oh_story_production episode must use the creator path form \u5267\u96C6/EP001.\");\n }\n if (args.action === \"open_section\") {\n if (args.section === undefined) throw new Error(\"oh_story_production section is required for open_section.\");\n return { action: args.action, episode, section: args.section };\n }\n if (args.action === \"focus_target\") {\n return { action: args.action, episode, targetId: requiredText(args.targetId, \"targetId\"), section: args.section };\n }\n if (args.action === \"set_sequence\") {\n const shotIds = args.shotIds?.map((value) => value.trim()).filter((value) => value !== \"\") ?? [];\n if (shotIds.length === 0) throw new Error(\"oh_story_production shotIds must contain at least one shot for set_sequence.\");\n if (shotIds.length > 500 || new Set(shotIds).size !== shotIds.length || shotIds.some((value) => !/^SHOT-[A-Z0-9-]+$/u.test(value))) {\n throw new Error(\"oh_story_production shotIds must be unique canonical SHOT-* identifiers.\");\n }\n return { action: args.action, episode, shotIds };\n }\n // Leave expectedOutputs/prompt undefined when the caller omits them: track_job re-registers a job the\n // workbench already created, and defaulting here would silently reset a batch's count to 1.\n const expectedOutputs = args.expectedOutputs;\n if (expectedOutputs !== undefined && (!Number.isInteger(expectedOutputs) || expectedOutputs < 1 || expectedOutputs > 500)) {\n throw new Error(\"oh_story_production expectedOutputs must be an integer between 1 and 500.\");\n }\n if (args.jobKind === undefined) throw new Error(\"oh_story_production jobKind is required for track_job.\");\n const prompt = args.prompt?.trim();\n return {\n action: args.action,\n episode,\n jobId: requiredText(args.jobId, \"jobId\"),\n targetId: requiredText(args.targetId, \"targetId\"),\n jobKind: args.jobKind,\n expectedOutputs,\n prompt: prompt === \"\" ? undefined : prompt\n };\n}\n", "import { createHash } from \"node:crypto\";\nimport { createReadStream } from \"node:fs\";\nimport { readFile as readNodeFile, realpath as nodeRealpath, stat as nodeStat } from \"node:fs/promises\";\nimport type { IncomingMessage, ServerResponse } from \"node:http\";\nimport { extname, isAbsolute, relative, resolve } from \"node:path\";\nimport type { Context } from \"@deepseek-ai/cordis\";\nimport type { Agent } from \"@deepseek-ai/dsh-agent\";\nimport { FsError, type FileSystem, type FsInfo, type FsTarget, type FsVersion } from \"@deepseek-ai/dsh-fs\";\nimport type {} from \"@deepseek-ai/dsh-host-webserver\";\nimport type { SandboxPolicyService } from \"@deepseek-ai/dsh-sandbox-policy\";\nimport { SessionId } from \"@deepseek-ai/dsh-session\";\nimport type {} from \"@deepseek-ai/dsh-typert-registry\";\nimport { type GameVerificationBinding, WorkspaceVerificationTracker } from \"./game-verification.js\";\nimport { dramaAdapterStatuses, ensureDramaAdapterConfig, type DramaAdapterStatus } from \"./drama-adapters.js\";\nimport { commandOutput, hostPython } from \"./host-python.js\";\nimport { defaultDramaSkillRoot, defaultNovelToGameSkillRoot } from \"./skill-provider.js\";\nimport { skipVideoDirectory, summarizeVideoProject, VIDEO_DIRECTORY, videoProjectRoot, visibleVideoPath, type VideoProjectSummary } from \"./video-project.js\";\nimport { isTrustedPreviewNavigation, isTrustedWorkspaceRequest } from \"./workspace-request-trust.js\";\n\nconst STORY_DIRECTORIES = [\"\u6B63\u6587\", \"\u5927\u7EB2\", \"\u8BBE\u5B9A\", \"\u8FFD\u8E2A\", \"\u5BF9\u6807\", \"\u53C2\u8003\u8D44\u6599\"] as const;\nconst DRAMA_DIRECTORIES = [\"\u8F93\u5165\", \"\u9879\u76EE\u5F00\u53D1\", \"\u8BBE\u5B9A\u96C6\", \"\u5267\u96C6\", \"\u4EA4\u4ED8\", \"\u521B\u4F5C\u8005\u51B3\u7B56\", \"\u5BA1\u67E5\"] as const;\nconst GAME_DIRECTORY = \"game-adaptations\";\n// Preview studios need only a small manifest-driven subset, so discover them before a very large\n// prose workspace can consume the shared listing budget.\nconst CREATIVE_DIRECTORIES = [VIDEO_DIRECTORY, GAME_DIRECTORY, ...STORY_DIRECTORIES, ...DRAMA_DIRECTORIES] as const;\nconst ROOT_FILES = new Set([\"short-drama.json\"]);\nconst EDITABLE_EXTENSIONS = new Set([\".md\", \".txt\", \".json\", \".jsonl\"]);\nconst GAME_EDITABLE_EXTENSIONS = new Set([...EDITABLE_EXTENSIONS, \".html\", \".css\", \".js\", \".mjs\", \".cjs\", \".ts\", \".tsx\", \".jsx\"]);\nconst VIDEO_EDITABLE_EXTENSIONS = new Set([...EDITABLE_EXTENSIONS, \".srt\", \".ass\"]);\nconst MEDIA_TYPES: ReadonlyMap<string, string> = new Map([\n [\".png\", \"image/png\"], [\".jpg\", \"image/jpeg\"], [\".jpeg\", \"image/jpeg\"], [\".webp\", \"image/webp\"], [\".gif\", \"image/gif\"],\n [\".mp4\", \"video/mp4\"], [\".webm\", \"video/webm\"], [\".mov\", \"video/quicktime\"], [\".mkv\", \"video/x-matroska\"],\n [\".mp3\", \"audio/mpeg\"], [\".wav\", \"audio/wav\"], [\".m4a\", \"audio/mp4\"], [\".aac\", \"audio/aac\"], [\".flac\", \"audio/flac\"]\n]);\nconst MEDIA_MAX_BYTES = 256 * 1_024 * 1_024;\nconst FILE_LIMIT = 1_000;\nconst PREVIEW_FILE_LIMIT = 32 * 1024 * 1024;\nconst BUNDLED_GAME_EXAMPLE = \"jin-ping-mei\";\nconst workspaceVerificationTracker = new WorkspaceVerificationTracker();\nlet videoPreflightCache: { readonly expires: number; readonly value: VideoPreflightSummary } | undefined;\nlet dramaPreflightCache: { readonly expires: number; readonly value: DramaPreflightSummary } | undefined;\n\ninterface WorkspaceRouteOptions {\n readonly maxBytes: number;\n readonly trustedHosts?: readonly string[];\n}\n\n/** Host-process capability probe. The Agent's execution world may differ; `video-recap --doctor` is authoritative there. */\ninterface VideoPreflightSummary {\n readonly python: { readonly ok: boolean; readonly version?: string | undefined };\n readonly ffmpeg: { readonly ok: boolean; readonly subtitles: boolean };\n readonly ffprobe: { readonly ok: boolean };\n readonly credentials: { readonly mimo: boolean; readonly fish: boolean; readonly indexTts: boolean; readonly ttsProvider: string };\n}\n\ninterface WorkspaceFile {\n readonly path: string;\n readonly bytes: number;\n readonly version: string;\n readonly kind: \"text\" | \"media\";\n readonly mimeType?: string | undefined;\n}\n\ninterface GameVerificationSummary {\n readonly status: \"NOT_RUN\" | \"FAIL\" | \"PASS\";\n readonly checks: Readonly<Record<string, \"NOT_RUN\" | \"FAIL\" | \"PASS\">>;\n readonly runId?: string | undefined;\n readonly limitations: readonly { readonly scope: string; readonly reason: string }[];\n readonly binding: GameVerificationBinding;\n readonly verifiedPreviewVersion?: string | undefined;\n}\n\ninterface GameProjectSummary {\n readonly id: string;\n readonly root: string;\n readonly title: string;\n readonly source: \"workspace\" | \"example\";\n readonly previewReady: boolean;\n readonly previewUrl?: string | undefined;\n readonly previewVersion: string;\n readonly verification: GameVerificationSummary;\n}\n\ninterface WorkspaceRealm {\n readonly agent: Agent;\n readonly fs: FileSystem;\n readonly sandboxPolicy: SandboxPolicyService;\n readonly cwd: string;\n readonly root: FsTarget;\n}\n\ninterface ReadFileResult {\n readonly content: string;\n readonly bytes: number;\n readonly version: FsVersion;\n}\n\nclass WorkspaceHttpError extends Error {\n constructor(readonly status: number, message: string) { super(message); }\n}\n\nfunction configured(...names: readonly string[]): boolean {\n return names.some((name) => (process.env[name] ?? \"\") !== \"\");\n}\n\n/**\n * Host-process view of short-drama production: which bundled media adapters\n * have their environment set, and where the adapter config the Agent passes to\n * `production_tool.py run` lives. Values never leave the process.\n */\ninterface DramaPreflightSummary {\n readonly python: { readonly ok: boolean; readonly version?: string | undefined };\n readonly adapterConfig: { readonly path: string; readonly generated: boolean; readonly ok: boolean };\n readonly adapters: readonly DramaAdapterStatus[];\n}\n\nlet dramaPreflightInFlight: Promise<DramaPreflightSummary> | undefined;\n\nasync function dramaPreflight(): Promise<DramaPreflightSummary> {\n if (dramaPreflightCache !== undefined && dramaPreflightCache.expires > Date.now()) return dramaPreflightCache.value;\n // One probe per cache miss: concurrent requests share the write instead of\n // racing it, and the write itself is atomic (temp file + rename).\n dramaPreflightInFlight ??= (async () => {\n try {\n const python = await hostPython();\n const adapterConfig = await ensureDramaAdapterConfig(defaultDramaSkillRoot(), { python: python.command });\n const value = { python: python.probe, adapterConfig, adapters: dramaAdapterStatuses() };\n dramaPreflightCache = { expires: Date.now() + 30_000, value };\n return value;\n } finally { dramaPreflightInFlight = undefined; }\n })();\n return dramaPreflightInFlight;\n}\n\nasync function videoPreflight(): Promise<VideoPreflightSummary> {\n if (videoPreflightCache !== undefined && videoPreflightCache.expires > Date.now()) return videoPreflightCache.value;\n const python = (await hostPython()).probe;\n const [ffmpegOutput, ffmpegFilters, ffprobeOutput] = await Promise.all([\n commandOutput(\"ffmpeg\", [\"-version\"]),\n commandOutput(\"ffmpeg\", [\"-hide_banner\", \"-filters\"]),\n commandOutput(\"ffprobe\", [\"-version\"])\n ]);\n const value = {\n python,\n ffmpeg: { ok: ffmpegOutput !== undefined, subtitles: /\\bsubtitles\\b/u.test(ffmpegFilters ?? \"\") },\n ffprobe: { ok: ffprobeOutput !== undefined },\n credentials: {\n // Upstream falls back to the shared MIMO_API_KEY only when a per-service key is unset.\n mimo: configured(\"MIMO_API_KEY\", \"MIMO_VIDEO_API_KEY\", \"MIMO_TTS_API_KEY\", \"MIMO_ASR_API_KEY\"),\n fish: configured(\"FISH_API_KEY\"),\n // index-tts fails before any request unless both are set (video-voiceover/references/index-tts.md).\n indexTts: configured(\"INDEX_TTS_ENDPOINT\") && configured(\"INDEX_TTS_VOICE\"),\n // Upstream accepts auto | mimo-tts | fish-audio | index-tts and defaults to auto (voiceover.py).\n ttsProvider: (process.env.TTS_PROVIDER ?? \"\").trim().toLowerCase() || \"auto\"\n }\n };\n videoPreflightCache = { expires: Date.now() + 30_000, value };\n return value;\n}\n\nfunction send(response: ServerResponse, status: number, value: unknown): void {\n const body = `${JSON.stringify(value)}\\n`;\n response.writeHead(status, {\n \"content-type\": \"application/json; charset=utf-8\",\n \"content-length\": Buffer.byteLength(body),\n \"cache-control\": \"no-store\",\n \"x-content-type-options\": \"nosniff\"\n });\n response.end(body);\n}\n\nexport interface ByteRange { readonly start: number; readonly end: number }\n\n/**\n * RFC 9110 14.2: a Range this server cannot parse or does not support is ignored (`undefined`, full\n * 200 response); only a well-formed but unsatisfiable range earns a 416 (`null`).\n */\nexport function parseByteRange(value: string | undefined, size: number): ByteRange | undefined | null {\n const match = value === undefined ? null : /^bytes=(\\d*)-(\\d*)$/u.exec(value.trim());\n if (match === null) return undefined;\n const left = match[1] ?? \"\";\n const right = match[2] ?? \"\";\n if (left === \"\") {\n const suffix = Number(right);\n if (right === \"\" || !Number.isSafeInteger(suffix)) return undefined;\n return suffix === 0 || size <= 0 ? null : { start: Math.max(0, size - suffix), end: size - 1 };\n }\n const start = Number(left);\n const requestedEnd = right === \"\" ? Number.MAX_SAFE_INTEGER : Number(right);\n if (!Number.isSafeInteger(start) || !Number.isSafeInteger(requestedEnd) || requestedEnd < start) return undefined;\n return start >= size ? null : { start, end: Math.min(requestedEnd, size - 1) };\n}\n\nfunction mediaHeaders(mimeType: string, size: number, range: ByteRange | undefined): Record<string, string | number> {\n const start = range?.start ?? 0;\n const end = range?.end ?? size - 1;\n return {\n \"content-type\": mimeType,\n \"content-length\": Math.max(0, end - start + 1),\n \"cache-control\": \"private, max-age=60\",\n \"accept-ranges\": \"bytes\",\n ...(range === undefined ? {} : { \"content-range\": `bytes ${String(start)}-${String(end)}/${String(size)}` }),\n \"x-content-type-options\": \"nosniff\"\n };\n}\n\nfunction sendMediaBytes(request: IncomingMessage, response: ServerResponse, bytes: Uint8Array, mimeType: string): void {\n const range = parseByteRange(typeof request.headers.range === \"string\" ? request.headers.range : undefined, bytes.byteLength);\n if (range === null) {\n response.writeHead(416, { \"content-range\": `bytes */${String(bytes.byteLength)}`, \"cache-control\": \"no-store\" });\n response.end();\n return;\n }\n const start = range?.start ?? 0;\n const end = range?.end ?? bytes.byteLength - 1;\n const body = bytes.subarray(start, end + 1);\n response.writeHead(range === undefined ? 200 : 206, mediaHeaders(mimeType, bytes.byteLength, range));\n response.end(request.method === \"HEAD\" ? undefined : Buffer.from(body));\n}\n\n/**\n * Resolve the target to a path this web host may open directly, or `undefined` when it may not.\n * `processPath` is canonical in the backend's execution world, which is not necessarily this\n * process's, so containment is re-checked against the host-visible workspace root: a remote path\n * that happens to exist locally never becomes a stream.\n */\nasync function hostWorkspaceFile(realm: WorkspaceRealm, target: FsTarget, expectedSize: number): Promise<string | undefined> {\n const [root, path] = await Promise.all([\n nodeRealpath(realm.fs.processPath(realm.root)),\n nodeRealpath(realm.fs.processPath(target))\n ]);\n const inside = relative(root, path);\n if (inside === \"\" || inside.startsWith(\"..\") || isAbsolute(inside)) return undefined;\n const local = await nodeStat(path);\n return local.isFile() && local.size === expectedSize ? path : undefined;\n}\n\nasync function sendWorkspaceMedia(request: IncomingMessage, response: ServerResponse, realm: WorkspaceRealm, target: FsTarget, info: FsInfo, mimeType: string): Promise<void> {\n const expectedSize = info.size;\n if (expectedSize !== undefined) {\n // A remote filesystem may expose a process path this web host cannot read; fall back to its\n // bounded binary API for modest files.\n const processPath = await hostWorkspaceFile(realm, target, expectedSize).catch(() => undefined);\n if (processPath !== undefined) {\n const range = parseByteRange(typeof request.headers.range === \"string\" ? request.headers.range : undefined, expectedSize);\n if (range === null) {\n response.writeHead(416, { \"content-range\": `bytes */${String(expectedSize)}`, \"cache-control\": \"no-store\" });\n response.end();\n return;\n }\n response.writeHead(range === undefined ? 200 : 206, mediaHeaders(mimeType, expectedSize, range));\n if (request.method === \"HEAD\") { response.end(); return; }\n const stream = createReadStream(processPath, range === undefined ? undefined : { start: range.start, end: range.end });\n request.once(\"close\", () => { if (!response.writableEnded) stream.destroy(); });\n stream.on(\"error\", () => { if (!response.headersSent) response.destroy(); else response.end(); });\n stream.pipe(response);\n return;\n }\n if (expectedSize > MEDIA_MAX_BYTES) throw new WorkspaceHttpError(413, \"\u8FDC\u7A0B\u5A92\u4F53\u8D85\u8FC7\u5DE5\u4F5C\u53F0\u56DE\u9000\u9884\u89C8\u5927\u5C0F\u9650\u5236\u3002\");\n }\n sendMediaBytes(request, response, await realm.fs.readBytes(target, undefined, MEDIA_MAX_BYTES), mimeType);\n}\n\nasync function jsonBody(request: IncomingMessage, maxBytes: number): Promise<Record<string, unknown>> {\n const chunks: Buffer[] = [];\n let size = 0;\n for await (const chunk of request as AsyncIterable<Uint8Array>) {\n const value = Buffer.from(chunk);\n size += value.byteLength;\n if (size > maxBytes) throw new WorkspaceHttpError(413, \"\u8BF7\u6C42\u5185\u5BB9\u8FC7\u5927\u3002\");\n chunks.push(value);\n }\n try {\n const value = JSON.parse(Buffer.concat(chunks).toString(\"utf8\")) as unknown;\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) throw new Error();\n return value as Record<string, unknown>;\n } catch {\n throw new WorkspaceHttpError(400, \"\u8BF7\u6C42\u5FC5\u987B\u662F JSON \u5BF9\u8C61\u3002\");\n }\n}\n\nfunction safeRelativePath(path: string): boolean {\n return path !== \"\"\n && !path.startsWith(\"/\")\n && !path.includes(\"\\\\\")\n && !path.split(\"/\").some((segment) => segment === \"\" || segment === \".\" || segment === \"..\");\n}\n\nfunction editablePath(path: string): boolean {\n const extensions = path.startsWith(`${GAME_DIRECTORY}/`) ? GAME_EDITABLE_EXTENSIONS\n : path.startsWith(`${VIDEO_DIRECTORY}/`) ? VIDEO_EDITABLE_EXTENSIONS\n : EDITABLE_EXTENSIONS;\n return extensions.has(extname(path).toLocaleLowerCase());\n}\n\nexport function assertCreativePath(path: string, kind: \"text\" | \"media\"): void {\n if (kind === \"text\" ? !editablePath(path) : !MEDIA_TYPES.has(extname(path).toLocaleLowerCase())) {\n throw new WorkspaceHttpError(415, kind === \"text\" ? \"\u5DE5\u4F5C\u53F0\u4E0D\u652F\u6301\u7F16\u8F91\u8BE5\u6587\u4EF6\u7C7B\u578B\u3002\" : \"\u76EE\u6807\u4E0D\u662F\u53D7\u652F\u6301\u7684\u77ED\u5267\u5A92\u4F53\u6587\u4EF6\u3002\");\n }\n if (!safeRelativePath(path)) {\n throw new WorkspaceHttpError(403, \"\u6587\u4EF6\u8DEF\u5F84\u4E0D\u5728\u521B\u4F5C\u5DE5\u4F5C\u53F0\u4E2D\u3002\");\n }\n const root = path.split(\"/\", 1)[0];\n if (!CREATIVE_DIRECTORIES.some((directory) => directory === root) && !ROOT_FILES.has(path)) {\n throw new WorkspaceHttpError(403, \"\u6587\u4EF6\u8DEF\u5F84\u4E0D\u5728\u521B\u4F5C\u5DE5\u4F5C\u53F0\u4E2D\u3002\");\n }\n}\n\nexport function mediaMimeTypeForPath(path: string): string | undefined {\n return MEDIA_TYPES.get(extname(path).toLocaleLowerCase());\n}\n\nasync function workspaceRealmForSession(context: Context, rawId: string): Promise<WorkspaceRealm> {\n if (rawId === \"\") throw new WorkspaceHttpError(400, \"\u7F3A\u5C11 DSH sessionId\u3002\");\n const lookup = context.typert.lookups.get(\"agent\");\n if (lookup === undefined) throw new WorkspaceHttpError(503, \"DSH Agent lookup \u5F53\u524D\u4E0D\u53EF\u7528\u3002\");\n let agent: Agent | undefined;\n try {\n agent = await lookup.resolve(SessionId(rawId)) as Agent | undefined;\n } catch {\n throw new WorkspaceHttpError(404, \"DSH \u4F1A\u8BDD\u4E0D\u53EF\u7528\u3002\");\n }\n if (agent === undefined) throw new WorkspaceHttpError(404, \"DSH \u4F1A\u8BDD\u4E0D\u53EF\u7528\u3002\");\n if (agent.session.header.parentSession !== undefined || agent.session.header.origin === \"subagent\") {\n throw new WorkspaceHttpError(403, \"\u5B50 Agent \u4F1A\u8BDD\u4E0D\u5F00\u653E\u521B\u4F5C\u7F16\u8F91\u5668\u3002\");\n }\n const cwd = agent.session.header.cwd;\n if (cwd === undefined) throw new WorkspaceHttpError(409, \"\u5F53\u524D DSH \u4F1A\u8BDD\u6CA1\u6709\u5DE5\u4F5C\u76EE\u5F55\u3002\");\n const fs = agent.ctx.get(\"fs\");\n const sandboxPolicy = agent.ctx.get(\"sandboxPolicy\");\n if (fs === undefined || sandboxPolicy === undefined) throw new WorkspaceHttpError(503, \"DSH \u6587\u4EF6\u7CFB\u7EDF\u5F53\u524D\u4E0D\u53EF\u7528\u3002\");\n return { agent, fs, sandboxPolicy, cwd, root: await fs.resolve(cwd) };\n}\n\nasync function workspaceRealm(context: Context, url: URL): Promise<WorkspaceRealm> {\n const rawId = url.searchParams.get(\"sessionId\");\n if (rawId === null) throw new WorkspaceHttpError(400, \"\u7F3A\u5C11 DSH sessionId\u3002\");\n return workspaceRealmForSession(context, rawId);\n}\n\nasync function creativeTarget(realm: WorkspaceRealm, path: string, kind: \"text\" | \"media\" = \"text\"): Promise<FsTarget> {\n assertCreativePath(path, kind);\n const target = await realm.fs.resolve(path, { cwd: realm.cwd });\n if (!realm.fs.contains(realm.root, target)) throw new WorkspaceHttpError(403, \"\u6587\u4EF6\u8DEF\u5F84\u79BB\u5F00\u4E86 DSH \u5DE5\u4F5C\u76EE\u5F55\u3002\");\n return target;\n}\n\nfunction requireRegularFile(info: FsInfo | undefined): FsInfo {\n if (info === undefined) throw new WorkspaceHttpError(404, \"\u6587\u4EF6\u4E0D\u5B58\u5728\u3002\");\n if (info.type !== \"file\") throw new WorkspaceHttpError(415, \"\u76EE\u6807\u4E0D\u662F\u53EF\u7F16\u8F91\u7684\u666E\u901A\u6587\u4EF6\u3002\");\n return info;\n}\n\n/** Read bytes and a matching opaque version, retrying if a writer wins the read window. */\nasync function readVersionedFile(fs: FileSystem, target: FsTarget, maxBytes: number): Promise<ReadFileResult> {\n for (let attempt = 0; attempt < 3; attempt += 1) {\n const before = requireRegularFile(await fs.stat(target));\n if (before.size !== undefined && before.size > maxBytes) throw new WorkspaceHttpError(413, \"\u6587\u4EF6\u8D85\u8FC7\u5DE5\u4F5C\u53F0\u5927\u5C0F\u9650\u5236\u3002\");\n const bytes = await fs.readBytes(target, undefined, maxBytes);\n const after = requireRegularFile(await fs.stat(target));\n if (before.version !== after.version) continue;\n let content: string;\n try {\n content = new TextDecoder(\"utf-8\", { fatal: true }).decode(bytes);\n } catch {\n throw new WorkspaceHttpError(415, \"\u6587\u4EF6\u4E0D\u662F\u6709\u6548\u7684 UTF-8 \u6587\u672C\u3002\");\n }\n return { content, bytes: bytes.byteLength, version: after.version };\n }\n throw new WorkspaceHttpError(409, \"\u6587\u4EF6\u6B63\u5728\u88AB\u4FEE\u6539\uFF0C\u8BF7\u91CD\u8BD5\u3002\");\n}\n\nasync function listFiles(realm: WorkspaceRealm): Promise<WorkspaceFile[]> {\n const files: WorkspaceFile[] = [];\n const walk = async (path: string, directory: FsTarget): Promise<void> => {\n for (const entry of await realm.fs.listDir(directory)) {\n if (entry.name.startsWith(\".\") || !realm.fs.contains(realm.root, entry.target)) continue;\n const childPath = `${path}/${entry.name}`;\n if (entry.type === \"directory\") {\n if (!skipVideoDirectory(childPath)) await walk(childPath, entry.target);\n }\n else if (entry.type === \"file\" && (editablePath(childPath) || MEDIA_TYPES.has(extname(entry.name).toLocaleLowerCase()))) {\n const info = entry.version === undefined || entry.size === undefined ? await realm.fs.stat(entry.target) : undefined;\n const version = entry.version ?? info?.version;\n const mimeType = MEDIA_TYPES.get(extname(entry.name).toLocaleLowerCase());\n if (version !== undefined && (!childPath.startsWith(`${VIDEO_DIRECTORY}/`) || visibleVideoPath(childPath))) {\n files.push({ path: childPath, bytes: entry.size ?? info?.size ?? 0, version, kind: mimeType === undefined ? \"text\" : \"media\", mimeType });\n }\n }\n if (files.length >= FILE_LIMIT) return;\n }\n };\n for (const directory of CREATIVE_DIRECTORIES) {\n const target = await realm.fs.resolve(directory, { cwd: realm.cwd });\n if (!realm.fs.contains(realm.root, target)) continue;\n const info = await realm.fs.stat(target);\n if (info?.type === \"directory\") await walk(directory, target);\n if (files.length >= FILE_LIMIT) break;\n }\n for (const path of ROOT_FILES) {\n const target = await creativeTarget(realm, path);\n const info = await realm.fs.stat(target);\n if (info?.type === \"file\") files.push({ path, bytes: info.size ?? 0, version: info.version, kind: \"text\" });\n }\n return files.sort((left, right) => left.path.localeCompare(right.path, \"zh-Hans-CN\"));\n}\n\nasync function metadata(realm: WorkspaceRealm, files: readonly WorkspaceFile[], path: string, maxBytes: number): Promise<{ readonly value: unknown; readonly error?: string }> {\n if (!files.some((file) => file.path === path)) return { value: null };\n try {\n const target = await creativeTarget(realm, path);\n return { value: JSON.parse((await readVersionedFile(realm.fs, target, maxBytes)).content) as unknown };\n } catch (error) {\n return { value: null, error: error instanceof SyntaxError ? `${path} \u4E0D\u662F\u6709\u6548\u7684 JSON\u3002` : `${path} \u6682\u65F6\u65E0\u6CD5\u8BFB\u53D6\u3002` };\n }\n}\n\nfunction token(value: string): string {\n return Buffer.from(value, \"utf8\").toString(\"base64url\");\n}\n\nfunction untoken(value: string): string {\n try { return Buffer.from(value, \"base64url\").toString(\"utf8\"); }\n catch { throw new WorkspaceHttpError(400, \"\u6E38\u620F\u9884\u89C8\u6807\u8BC6\u65E0\u6548\u3002\"); }\n}\n\nexport function gameRoot(path: string): boolean {\n // Reject only what is actually unsafe; fs.resolve + fs.contains remain the real boundary.\n // A stricter slug allowlist silently hid legitimate project names (spaces, \u00B7, leading _, NFD).\n const parts = path.split(\"/\");\n const name = parts[1];\n return parts.length === 2 && parts[0] === GAME_DIRECTORY && name !== undefined\n && name !== \"\" && name !== \".\" && name !== \"..\" && name.length <= 128\n && !name.startsWith(\".\") && !name.includes(\"\\\\\");\n}\n\nfunction normalizedVerification(\n value: unknown,\n binding: GameVerificationBinding,\n verifiedPreviewVersion?: string\n): GameVerificationSummary {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n return { status: \"NOT_RUN\", checks: {}, limitations: [], binding };\n }\n const record = value as Record<string, unknown>;\n const status = record.status === \"PASS\" || record.status === \"FAIL\" ? record.status : \"NOT_RUN\";\n const rawChecks = typeof record.checks === \"object\" && record.checks !== null && !Array.isArray(record.checks)\n ? record.checks as Record<string, unknown>\n : {};\n const checks: Record<string, \"NOT_RUN\" | \"FAIL\" | \"PASS\"> = {};\n for (const name of [\"launch\", \"render\", \"input\", \"coreLoop\", \"outcome\", \"restart\"]) {\n const check = rawChecks[name];\n checks[name] = check === \"PASS\" || check === \"FAIL\" ? check : \"NOT_RUN\";\n }\n const completeRun = typeof record.completeRun === \"object\" && record.completeRun !== null && !Array.isArray(record.completeRun)\n ? record.completeRun as Record<string, unknown>\n : {};\n const limitations = Array.isArray(record.limitations) ? record.limitations.flatMap((entry) => {\n if (typeof entry !== \"object\" || entry === null || Array.isArray(entry)) return [];\n const item = entry as Record<string, unknown>;\n return typeof item.scope === \"string\" && typeof item.reason === \"string\"\n ? [{ scope: item.scope, reason: item.reason }]\n : [];\n }) : [];\n return {\n status,\n checks,\n runId: typeof completeRun.id === \"string\" ? completeRun.id : undefined,\n limitations,\n binding,\n verifiedPreviewVersion\n };\n}\n\nasync function workspaceText(realm: WorkspaceRealm, path: string, maxBytes: number): Promise<string | undefined> {\n const target = await realm.fs.resolve(path, { cwd: realm.cwd });\n if (!realm.fs.contains(realm.root, target) || (await realm.fs.stat(target))?.type !== \"file\") return undefined;\n return (await readVersionedFile(realm.fs, target, maxBytes)).content;\n}\n\nasync function previewDigest(realm: WorkspaceRealm, projectRoot: string): Promise<{ readonly ready: boolean; readonly version: string }> {\n const appPath = `${projectRoot}/build/app`;\n const app = await realm.fs.resolve(appPath, { cwd: realm.cwd });\n if (!realm.fs.contains(realm.root, app) || (await realm.fs.stat(app))?.type !== \"directory\") return { ready: false, version: \"missing\" };\n const entries: string[] = [];\n let ready = false;\n const visit = async (directory: FsTarget, path: string): Promise<void> => {\n for (const entry of await realm.fs.listDir(directory)) {\n if (entry.name.startsWith(\".\") || !realm.fs.contains(app, entry.target)) continue;\n const childPath = path === \"\" ? entry.name : `${path}/${entry.name}`;\n if (entry.type === \"directory\") await visit(entry.target, childPath);\n else if (entry.type === \"file\") {\n const info = entry.version === undefined ? await realm.fs.stat(entry.target) : undefined;\n const version = entry.version ?? info?.version;\n if (version !== undefined) entries.push(`${childPath}\\0${version}`);\n if (childPath === \"index.html\") ready = true;\n }\n if (entries.length >= 5_000) return;\n }\n };\n await visit(app, \"\");\n return { ready, version: createHash(\"sha256\").update(entries.sort().join(\"\\n\")).digest(\"hex\").slice(0, 16) };\n}\n\nfunction headingTitle(content: string | undefined, fallback: string): string {\n const heading = content?.split(/\\r?\\n/u).find((line) => /^#\\s+/u.test(line));\n return heading?.replace(/^#\\s+/u, \"\").replace(/^PRODUCT_BRIEF\\s*[\u00B7\u30FB:]?\\s*/iu, \"\").trim() || fallback;\n}\n\nasync function workspaceGameProjects(\n realm: WorkspaceRealm,\n files: readonly WorkspaceFile[],\n sessionId: string,\n maxBytes: number\n): Promise<GameProjectSummary[]> {\n const roots = [...new Set(files.flatMap((file) => {\n const parts = file.path.split(\"/\");\n return parts[0] === GAME_DIRECTORY && parts[1] !== undefined ? [`${GAME_DIRECTORY}/${parts[1]}`] : [];\n }))].filter(gameRoot).sort();\n return Promise.all(roots.map(async (root) => {\n const id = root.slice(`${GAME_DIRECTORY}/`.length);\n const qaPath = `${root}/qa/verification.json`;\n const qaFile = files.find((file) => file.path === qaPath);\n // Isolate per-project metadata failures: an unreadable brief, a non-UTF-8 or oversized\n // verification file, or a build/app subtree removed mid-rebuild must degrade this one card,\n // never abort the shared workspace listing (which also carries the story and drama trees).\n const [brief, qa, preview] = await Promise.all([\n workspaceText(realm, `${root}/PRODUCT_BRIEF.md`, maxBytes).catch(() => undefined),\n workspaceText(realm, qaPath, maxBytes).catch(() => undefined),\n previewDigest(realm, root).catch(() => ({ ready: false, version: \"unavailable\" }))\n ]);\n let verification: unknown;\n try { verification = qa === undefined ? undefined : JSON.parse(qa) as unknown; }\n catch { verification = undefined; }\n const freshness = workspaceVerificationTracker.observe(`${sessionId}\\0${root}`, qaFile?.version, preview.version);\n return {\n id: `workspace:${id}`,\n root,\n title: headingTitle(brief, id),\n source: \"workspace\" as const,\n previewReady: preview.ready,\n previewUrl: preview.ready\n ? `/oh-story/game-preview/workspace/${token(sessionId)}/${token(root)}/index.html`\n : undefined,\n previewVersion: preview.version,\n verification: normalizedVerification(verification, freshness.binding, freshness.verifiedPreviewVersion)\n };\n }));\n}\n\nasync function workspaceVideoProjects(realm: WorkspaceRealm, files: readonly WorkspaceFile[], maxBytes: number): Promise<VideoProjectSummary[]> {\n const roots = [...new Set(files.flatMap((file) => {\n const root = videoProjectRoot(file.path);\n return root === undefined ? [] : [root];\n }))].sort((left, right) => left.localeCompare(right, \"zh-Hans-CN\"));\n return Promise.all(roots.map(async (root) => {\n const findPath = (name: string): string | undefined => files.find((file) => file.path.startsWith(`${root}/`) && file.path.split(\"/\").at(-1) === name)?.path;\n const readJson = async (name: string): Promise<unknown> => {\n const path = findPath(name);\n if (path === undefined) return undefined;\n const content = await workspaceText(realm, path, maxBytes).catch(() => undefined);\n if (content === undefined) return undefined;\n try { return JSON.parse(content) as unknown; }\n catch { return undefined; }\n };\n const [project, runManifest, assembly] = await Promise.all([\n readJson(\"project.json\"),\n readJson(\"recap_run_manifest.json\"),\n readJson(\"assembly_manifest.json\")\n ]);\n return summarizeVideoProject(root, files, { project, runManifest, assembly });\n }));\n}\n\nfunction bundledExampleRoot(): string {\n return resolve(defaultNovelToGameSkillRoot(), `../examples/${BUNDLED_GAME_EXAMPLE}`);\n}\n\nasync function bundledGameExample(): Promise<GameProjectSummary> {\n const root = bundledExampleRoot();\n const [example, verification, manifest] = await Promise.all([\n readNodeFile(resolve(root, \"example.json\"), \"utf8\"),\n readNodeFile(resolve(root, \"qa/verification.json\"), \"utf8\"),\n readNodeFile(resolve(defaultNovelToGameSkillRoot(), \"../manifest.json\"), \"utf8\")\n ]);\n const exampleJson = JSON.parse(example) as { readonly title?: unknown };\n const manifestJson = JSON.parse(manifest) as { readonly upstream?: { readonly commit?: unknown } };\n const previewVersion = typeof manifestJson.upstream?.commit === \"string\" ? manifestJson.upstream.commit.slice(0, 16) : \"bundled\";\n return {\n id: `example:${BUNDLED_GAME_EXAMPLE}`,\n root: `examples/${BUNDLED_GAME_EXAMPLE}`,\n title: typeof exampleJson.title === \"string\" ? exampleJson.title : \"\u91D1\u74F6\u6885 \u00B7 \u98CE\u6708\u603B\u8D26\",\n source: \"example\",\n previewReady: true,\n previewUrl: `/oh-story/game-preview/example/${BUNDLED_GAME_EXAMPLE}/index.html`,\n previewVersion,\n verification: normalizedVerification(JSON.parse(verification) as unknown, \"PINNED\", previewVersion)\n };\n}\n\nfunction previewContentType(path: string): string {\n switch (extname(path).toLocaleLowerCase()) {\n case \".html\": return \"text/html; charset=utf-8\";\n case \".css\": return \"text/css; charset=utf-8\";\n case \".js\":\n case \".mjs\": return \"text/javascript; charset=utf-8\";\n case \".json\": return \"application/json; charset=utf-8\";\n case \".svg\": return \"image/svg+xml\";\n case \".png\": return \"image/png\";\n case \".jpg\":\n case \".jpeg\": return \"image/jpeg\";\n case \".webp\": return \"image/webp\";\n case \".gif\": return \"image/gif\";\n case \".woff\": return \"font/woff\";\n case \".woff2\": return \"font/woff2\";\n case \".wasm\": return \"application/wasm\";\n case \".mp3\": return \"audio/mpeg\";\n case \".ogg\": return \"audio/ogg\";\n default: return \"application/octet-stream\";\n }\n}\n\nfunction previewAssetSources(request: IncomingMessage): string {\n const authority = request.headers.host;\n if (authority === undefined) return \"'none'\";\n const prefix = `${authority}/oh-story/game-preview/`;\n return `http://${prefix} https://${prefix}`;\n}\n\n/**\n * Emitted for EVERY preview response, not just HTML. previewContentType serves .svg as\n * image/svg+xml \u2014 an active document type \u2014 so a game that self-navigates its frame to a scripted\n * SVG would otherwise land in a document with no policy at all, while the iframe sandbox flags\n * (which do persist across that navigation) still grant it script execution. The `sandbox`\n * directive makes each response self-confining regardless of the iframe attribute.\n */\nexport function previewContentSecurityPolicy(assets: string): string {\n return [\n \"sandbox allow-scripts allow-forms allow-modals allow-downloads allow-same-origin\",\n \"default-src 'none'\",\n `script-src 'unsafe-inline' 'wasm-unsafe-eval' blob: ${assets}`,\n `style-src 'unsafe-inline' ${assets}`,\n `img-src data: blob: ${assets}`,\n `media-src data: blob: ${assets}`,\n `font-src data: ${assets}`,\n `connect-src ${assets}`,\n `worker-src blob: ${assets}`,\n `manifest-src ${assets}`,\n \"object-src 'none'\",\n \"base-uri 'none'\",\n \"form-action 'none'\",\n \"frame-ancestors 'self' http://127.0.0.1:* http://localhost:*\"\n ].join(\"; \");\n}\n\nfunction sendPreview(request: IncomingMessage, response: ServerResponse, path: string, bytes: Uint8Array): void {\n const assets = previewAssetSources(request);\n response.writeHead(200, {\n \"content-type\": previewContentType(path),\n \"content-length\": bytes.byteLength,\n \"cache-control\": \"no-store\",\n \"x-content-type-options\": \"nosniff\",\n \"cross-origin-resource-policy\": \"cross-origin\",\n \"access-control-allow-origin\": \"*\",\n \"content-security-policy\": previewContentSecurityPolicy(assets),\n });\n response.end(bytes);\n}\n\nasync function previewBytes(context: Context, pathname: string): Promise<{ readonly path: string; readonly bytes: Uint8Array }> {\n let segments: string[];\n try {\n segments = pathname.split(\"/\").slice(3).map((segment) => decodeURIComponent(segment));\n } catch {\n throw new WorkspaceHttpError(400, \"\u6E38\u620F\u9884\u89C8\u5730\u5740\u65E0\u6548\u3002\");\n }\n const kind = segments.shift();\n if (kind === \"example\") {\n const id = segments.shift();\n const path = segments.join(\"/\") || \"index.html\";\n if (id !== BUNDLED_GAME_EXAMPLE || !safeRelativePath(path)) throw new WorkspaceHttpError(404, \"\u6E38\u620F\u793A\u4F8B\u4E0D\u5B58\u5728\u3002\");\n const appRoot = resolve(bundledExampleRoot(), \"build/app\");\n const target = resolve(appRoot, path);\n const escaped = relative(appRoot, target);\n if (escaped.startsWith(\"..\") || isAbsolute(escaped)) throw new WorkspaceHttpError(403, \"\u9884\u89C8\u8D44\u6E90\u79BB\u5F00\u4E86\u6E38\u620F\u76EE\u5F55\u3002\");\n const info = await nodeStat(target).catch(() => undefined);\n if (!info?.isFile()) throw new WorkspaceHttpError(404, \"\u9884\u89C8\u8D44\u6E90\u4E0D\u5B58\u5728\u3002\");\n if (info.size > PREVIEW_FILE_LIMIT) throw new WorkspaceHttpError(413, \"\u9884\u89C8\u8D44\u6E90\u8FC7\u5927\u3002\");\n return { path, bytes: await readNodeFile(target) };\n }\n if (kind === \"workspace\") {\n const session = segments.shift();\n const project = segments.shift();\n const path = segments.join(\"/\") || \"index.html\";\n if (session === undefined || project === undefined || !safeRelativePath(path)) throw new WorkspaceHttpError(400, \"\u6E38\u620F\u9884\u89C8\u5730\u5740\u65E0\u6548\u3002\");\n const realm = await workspaceRealmForSession(context, untoken(session));\n const root = untoken(project);\n if (!gameRoot(root)) throw new WorkspaceHttpError(403, \"\u6E38\u620F\u9879\u76EE\u8DEF\u5F84\u65E0\u6548\u3002\");\n const appRoot = await realm.fs.resolve(`${root}/build/app`, { cwd: realm.cwd });\n const target = await realm.fs.resolve(`${root}/build/app/${path}`, { cwd: realm.cwd });\n if (!realm.fs.contains(realm.root, appRoot) || !realm.fs.contains(appRoot, target)) {\n throw new WorkspaceHttpError(403, \"\u9884\u89C8\u8D44\u6E90\u79BB\u5F00\u4E86\u6E38\u620F\u76EE\u5F55\u3002\");\n }\n const info = requireRegularFile(await realm.fs.stat(target));\n if (info.size !== undefined && info.size > PREVIEW_FILE_LIMIT) throw new WorkspaceHttpError(413, \"\u9884\u89C8\u8D44\u6E90\u8FC7\u5927\u3002\");\n return { path, bytes: await realm.fs.readBytes(target, undefined, PREVIEW_FILE_LIMIT) };\n }\n throw new WorkspaceHttpError(404, \"\u6E38\u620F\u9884\u89C8\u4E0D\u5B58\u5728\u3002\");\n}\n\nfunction mapFsError(error: unknown): WorkspaceHttpError | undefined {\n if (!(error instanceof FsError)) return undefined;\n switch (error.code) {\n case \"FS_NOT_FOUND\": return new WorkspaceHttpError(404, \"\u6587\u4EF6\u4E0D\u5B58\u5728\u3002\");\n case \"FS_TOO_LARGE\": return new WorkspaceHttpError(413, \"\u6587\u4EF6\u8D85\u8FC7\u5DE5\u4F5C\u53F0\u5927\u5C0F\u9650\u5236\u3002\");\n case \"FS_NOT_TEXT\":\n case \"FS_NOT_REGULAR_FILE\": return new WorkspaceHttpError(415, \"\u76EE\u6807\u4E0D\u662F\u53EF\u7F16\u8F91\u7684\u6587\u672C\u6587\u4EF6\u3002\");\n case \"FS_PERMISSION_DENIED\":\n case \"FS_SANDBOX_DENIED\": return new WorkspaceHttpError(403, \"\u5F53\u524D DSH \u6743\u9650\u4E0D\u5141\u8BB8\u4FEE\u6539\u8BE5\u6587\u4EF6\u3002\");\n case \"FS_STALE_VERSION\":\n case \"FS_NOT_OBSERVED\": return new WorkspaceHttpError(412, \"\u6587\u4EF6\u5DF2\u5728\u78C1\u76D8\u4E0A\u66F4\u65B0\u3002\u8BF7\u5904\u7406\u51B2\u7A81\u540E\u518D\u4FDD\u5B58\u3002\");\n case \"FS_ABORTED\": return new WorkspaceHttpError(409, \"\u6587\u4EF6\u64CD\u4F5C\u5DF2\u53D6\u6D88\u3002\");\n default: return new WorkspaceHttpError(500, \"DSH \u6587\u4EF6\u7CFB\u7EDF\u64CD\u4F5C\u5931\u8D25\u3002\");\n }\n}\n\nasync function handle(context: Context, request: IncomingMessage, response: ServerResponse, options: WorkspaceRouteOptions): Promise<void> {\n try {\n const url = new URL(request.url ?? \"/\", \"http://127.0.0.1\");\n const gamePreview = url.pathname.startsWith(\"/oh-story/game-preview/\");\n const trusted = gamePreview\n ? isTrustedPreviewNavigation(request, options.trustedHosts ?? [])\n : isTrustedWorkspaceRequest(request, options.trustedHosts ?? []);\n if (!trusted) throw new WorkspaceHttpError(403, \"\u8BF7\u6C42\u6765\u6E90\u4E0D\u53D7\u4FE1\u4EFB\u3002\");\n if (gamePreview && request.method === \"GET\") {\n const preview = await previewBytes(context, url.pathname);\n sendPreview(request, response, preview.path, preview.bytes);\n return;\n }\n if (url.pathname === \"/oh-story/workspace\" && request.method === \"GET\") {\n const realm = await workspaceRealm(context, url);\n const files = await listFiles(realm);\n const tracking = await metadata(realm, files, \"\u8FFD\u8E2A/_tracking-state.json\", options.maxBytes);\n const shortDrama = await metadata(realm, files, \"short-drama.json\", options.maxBytes);\n const metadataErrors = [tracking.error, shortDrama.error].filter((value): value is string => value !== undefined);\n const sessionId = url.searchParams.get(\"sessionId\");\n if (sessionId === null) throw new WorkspaceHttpError(400, \"\u7F3A\u5C11 DSH sessionId\u3002\");\n const games = [\n ...await workspaceGameProjects(realm, files, sessionId, options.maxBytes),\n await bundledGameExample()\n ];\n const videos = await workspaceVideoProjects(realm, files, options.maxBytes);\n send(response, 200, { cwd: realm.cwd, files, games, videos, tracking: tracking.value, shortDrama: shortDrama.value, metadataErrors, mode: \"dsh-session\" });\n return;\n }\n if (url.pathname === \"/oh-story/video-preflight\" && request.method === \"GET\") {\n send(response, 200, await videoPreflight());\n return;\n }\n if (url.pathname === \"/oh-story/drama-preflight\" && request.method === \"GET\") {\n send(response, 200, await dramaPreflight());\n return;\n }\n if (url.pathname === \"/oh-story/file\" && request.method === \"GET\") {\n const realm = await workspaceRealm(context, url);\n const path = url.searchParams.get(\"path\");\n if (path === null) throw new WorkspaceHttpError(400, \"\u7F3A\u5C11\u6587\u4EF6\u8DEF\u5F84\u3002\");\n const file = await readVersionedFile(realm.fs, await creativeTarget(realm, path), options.maxBytes);\n send(response, 200, { path, ...file });\n return;\n }\n if (url.pathname === \"/oh-story/media\" && (request.method === \"GET\" || request.method === \"HEAD\")) {\n const realm = await workspaceRealm(context, url);\n const path = url.searchParams.get(\"path\");\n if (path === null) throw new WorkspaceHttpError(400, \"\u7F3A\u5C11\u5A92\u4F53\u6587\u4EF6\u8DEF\u5F84\u3002\");\n const mimeType = mediaMimeTypeForPath(path);\n if (mimeType === undefined) throw new WorkspaceHttpError(415, \"\u76EE\u6807\u4E0D\u662F\u53D7\u652F\u6301\u7684\u77ED\u5267\u5A92\u4F53\u6587\u4EF6\u3002\");\n const target = await creativeTarget(realm, path, \"media\");\n const info = requireRegularFile(await realm.fs.stat(target));\n await sendWorkspaceMedia(request, response, realm, target, info, mimeType);\n return;\n }\n if (url.pathname === \"/oh-story/file\" && request.method === \"PUT\") {\n const realm = await workspaceRealm(context, url);\n const path = url.searchParams.get(\"path\");\n if (path === null) throw new WorkspaceHttpError(400, \"\u7F3A\u5C11\u6587\u4EF6\u8DEF\u5F84\u3002\");\n const input = await jsonBody(request, options.maxBytes * 6 + 1_024);\n if (typeof input.content !== \"string\") throw new WorkspaceHttpError(400, \"content \u5FC5\u987B\u662F\u5B57\u7B26\u4E32\u3002\");\n if (typeof input.baseVersion !== \"string\" || input.baseVersion === \"\") throw new WorkspaceHttpError(400, \"baseVersion \u5FC5\u987B\u662F\u6709\u6548\u7248\u672C\u3002\");\n if (Buffer.byteLength(input.content) > options.maxBytes) throw new WorkspaceHttpError(413, \"\u6587\u4EF6\u8D85\u8FC7\u5DE5\u4F5C\u53F0\u5927\u5C0F\u9650\u5236\u3002\");\n const outcome = await realm.fs.writeText(\n await creativeTarget(realm, path),\n input.content,\n { kind: \"replaceIfVersion\", version: input.baseVersion as FsVersion },\n undefined,\n realm.sandboxPolicy.resolve({ session: realm.agent.session })\n );\n send(response, 200, { path, content: outcome.after, bytes: Buffer.byteLength(outcome.after), version: outcome.version });\n return;\n }\n send(response, 404, { error: \"Oh Story route not found.\" });\n } catch (error) {\n const mapped = error instanceof WorkspaceHttpError ? error : mapFsError(error);\n if (mapped === undefined) context.logger(\"oh-story\").error(\"workspace route failed\", error);\n send(response, mapped?.status ?? 500, { error: mapped?.message ?? \"Oh Story workspace operation failed.\" });\n }\n}\n\n/** Mount the narrow editor API on DSH's official web-server extension seam. */\nexport function registerWorkspaceRoute(context: Context, options: WorkspaceRouteOptions): void {\n context.effect(() => context.webServer.register({\n kind: \"prefix\",\n path: \"/oh-story\",\n handler: (request, response) => handle(context, request, response, options)\n }), \"oh-story: DSH-session workspace API\");\n}\n", "export type GameVerificationBinding = \"CURRENT\" | \"PINNED\" | \"STALE\" | \"UNBOUND\";\n\nexport interface GameVerificationFreshness {\n readonly binding: Exclude<GameVerificationBinding, \"PINNED\">;\n readonly verifiedPreviewVersion?: string | undefined;\n}\n\ninterface Observation {\n readonly verificationRevision: string | undefined;\n readonly previewVersion: string;\n readonly bound: boolean;\n}\n\n/**\n * The upstream QA schema intentionally contains no build digest. Track what\n * this DSH process actually observes instead of pretending an imported PASS\n * belongs to the current build. A QA rewrite binds that run to the preview\n * visible at the same observation; later preview changes make it stale.\n */\nexport class WorkspaceVerificationTracker {\n readonly #observations = new Map<string, Observation>();\n\n observe(key: string, verificationRevision: string | undefined, previewVersion: string): GameVerificationFreshness {\n const previous = this.#observations.get(key);\n if (previous === undefined) {\n this.#remember(key, { verificationRevision, previewVersion, bound: false });\n return { binding: \"UNBOUND\" };\n }\n if (verificationRevision !== previous.verificationRevision) {\n const bound = verificationRevision !== undefined;\n this.#remember(key, { verificationRevision, previewVersion, bound });\n return bound ? { binding: \"CURRENT\", verifiedPreviewVersion: previewVersion } : { binding: \"UNBOUND\" };\n }\n if (!previous.bound) return { binding: \"UNBOUND\" };\n return previewVersion === previous.previewVersion\n ? { binding: \"CURRENT\", verifiedPreviewVersion: previous.previewVersion }\n : { binding: \"STALE\", verifiedPreviewVersion: previous.previewVersion };\n }\n\n #remember(key: string, observation: Observation): void {\n this.#observations.set(key, observation);\n if (this.#observations.size <= 500) return;\n const oldest = this.#observations.keys().next();\n if (!oldest.done) this.#observations.delete(oldest.value);\n }\n}\n", "import { basename, extname } from \"node:path\";\n\nexport const VIDEO_DIRECTORY = \"video-recaps\";\n\nexport interface VideoWorkspaceFile {\n readonly path: string;\n readonly bytes: number;\n readonly version: string;\n readonly kind: \"text\" | \"media\";\n readonly mimeType?: string | undefined;\n}\n\nexport interface VideoPreviewAsset {\n readonly role: \"source\" | \"edited\" | \"final\";\n readonly label: string;\n readonly path: string;\n readonly bytes: number;\n readonly version: string;\n readonly mimeType: string;\n}\n\nexport interface VideoArtifactSummary {\n readonly label: string;\n readonly path: string;\n readonly version: string;\n readonly kind: \"plan\" | \"script\" | \"subtitle\" | \"quality\" | \"manifest\";\n}\n\nexport interface VideoProjectSummary {\n readonly id: string;\n readonly root: string;\n readonly title: string;\n readonly state: \"not-started\" | \"working\" | \"waiting\" | \"ready\";\n readonly stage: string;\n readonly stageLabel: string;\n readonly nextArtifact?: string | undefined;\n readonly previews: readonly VideoPreviewAsset[];\n readonly artifacts: readonly VideoArtifactSummary[];\n}\n\nconst VIDEO_EXTENSIONS = new Set([\".mp4\", \".mov\", \".mkv\", \".webm\"]);\nconst SKIPPED_DIRECTORIES = new Set([\"frames\", \"tts_segments\", \"asr_chunks\", \"chunks\", \"cache\", \"tmp\", \".subtitle_measure\"]);\nconst VISIBLE_TEXT_FILES = new Set([\n \"project.json\",\n \"recap_run_manifest.json\",\n \"recap_phase.json\",\n \"agent_narration_brief.md\",\n \"recap_story_plan.json\",\n \"production_reference.json\",\n \"reference_measurements.json\",\n \"reference_breakdown.json\",\n \"visual_audio_board.json\",\n \"clip_plan.json\",\n \"clip_plan_validated.json\",\n \"narration.json\",\n \"narration_review.md\",\n \"tts_meta.json\",\n \"timeline.json\",\n \"assembly_manifest.json\",\n \"assembly_qc.json\",\n \"final_qc.json\",\n \"final_qc.md\",\n \"delivery_qc.json\",\n \"cut_delivery_qc.json\",\n \"recap_project.json\",\n \"resource_lock.json\",\n \"subtitles.srt\",\n \"subtitles.ass\"\n]);\n\nconst ARTIFACT_META: Readonly<Record<string, { readonly label: string; readonly kind: VideoArtifactSummary[\"kind\"] }>> = {\n \"recap_run_manifest.json\": { label: \"\u8FD0\u884C\u6E05\u5355\", kind: \"manifest\" },\n \"recap_phase.json\": { label: \"\u9636\u6BB5\u8D26\u672C\", kind: \"manifest\" },\n \"agent_narration_brief.md\": { label: \"\u89E3\u8BF4 Brief\", kind: \"plan\" },\n \"recap_story_plan.json\": { label: \"\u6545\u4E8B\u65B9\u6848\", kind: \"plan\" },\n \"production_reference.json\": { label: \"\u5236\u4F5C\u53C2\u8003\", kind: \"plan\" },\n \"reference_measurements.json\": { label: \"\u53C2\u8003\u6D4B\u91CF\", kind: \"quality\" },\n \"reference_breakdown.json\": { label: \"\u53C2\u8003\u62C6\u89E3\", kind: \"plan\" },\n \"visual_audio_board.json\": { label: \"\u97F3\u753B\u65B9\u6848\", kind: \"plan\" },\n \"clip_plan.json\": { label: \"\u526A\u8F91\u8BA1\u5212\", kind: \"plan\" },\n \"clip_plan_validated.json\": { label: \"\u5DF2\u6821\u9A8C\u526A\u8F91\u8BA1\u5212\", kind: \"plan\" },\n \"narration.json\": { label: \"\u89E3\u8BF4\u8BCD\", kind: \"script\" },\n \"narration_review.md\": { label: \"\u89E3\u8BF4\u590D\u6838\", kind: \"quality\" },\n \"timeline.json\": { label: \"\u6210\u7247\u65F6\u95F4\u7EBF\", kind: \"plan\" },\n \"assembly_manifest.json\": { label: \"\u5408\u6210\u6E05\u5355\", kind: \"manifest\" },\n \"assembly_qc.json\": { label: \"\u5408\u6210\u8D28\u68C0\", kind: \"quality\" },\n \"final_qc.json\": { label: \"\u6700\u7EC8\u8D28\u68C0\", kind: \"quality\" },\n \"final_qc.md\": { label: \"\u6700\u7EC8\u8D28\u68C0\u62A5\u544A\", kind: \"quality\" },\n \"delivery_qc.json\": { label: \"\u4EA4\u4ED8\u8D28\u68C0\", kind: \"quality\" },\n \"cut_delivery_qc.json\": { label: \"\u526A\u540E\u7247\u8D28\u68C0\", kind: \"quality\" },\n \"recap_project.json\": { label: \"\u9879\u76EE\u7ED1\u5B9A\", kind: \"manifest\" },\n \"resource_lock.json\": { label: \"\u8D44\u6E90\u9501\u5B9A\", kind: \"manifest\" },\n \"subtitles.srt\": { label: \"SRT \u5B57\u5E55\", kind: \"subtitle\" },\n \"subtitles.ass\": { label: \"ASS \u5B57\u5E55\", kind: \"subtitle\" }\n};\n\nexport function videoProjectRoot(path: string): string | undefined {\n const parts = path.split(\"/\");\n const name = parts[1];\n if (parts[0] !== VIDEO_DIRECTORY || name === undefined || name === \"\" || name === \".\" || name === \"..\" || name.startsWith(\".\") || name.includes(\"\\\\\") || name.length > 128) return undefined;\n return `${VIDEO_DIRECTORY}/${name}`;\n}\n\nexport function skipVideoDirectory(path: string): boolean {\n const parts = path.split(\"/\");\n return parts[0] === VIDEO_DIRECTORY && parts.length >= 3 && SKIPPED_DIRECTORIES.has(parts.at(-1) ?? \"\");\n}\n\nexport function visibleVideoPath(path: string): boolean {\n const root = videoProjectRoot(path);\n if (root === undefined || path === root) return false;\n const name = basename(path);\n const extension = extname(name).toLocaleLowerCase();\n if (VISIBLE_TEXT_FILES.has(name)) return true;\n if (!VIDEO_EXTENSIONS.has(extension)) return false;\n return path.startsWith(`${root}/sources/`)\n || path.startsWith(`${root}/outputs/`)\n || name === \"edited_source.mp4\"\n || /^recap_.+\\.(?:mp4|mov|webm)$/iu.test(name);\n}\n\nfunction record(value: unknown): Record<string, unknown> | undefined {\n return typeof value === \"object\" && value !== null && !Array.isArray(value) ? value as Record<string, unknown> : undefined;\n}\n\nfunction text(value: unknown): string | undefined {\n return typeof value === \"string\" && value.trim() !== \"\" ? value.trim() : undefined;\n}\n\nfunction referencedMedia(files: readonly VideoWorkspaceFile[], value: unknown): VideoWorkspaceFile | undefined {\n const path = text(value)?.replaceAll(\"\\\\\", \"/\");\n if (path === undefined) return undefined;\n const direct = files.find((file) => file.path === path || path.endsWith(`/${file.path}`));\n if (direct !== undefined) return direct;\n const name = path.split(\"/\").at(-1);\n const matching = files.filter((file) => file.path.split(\"/\").at(-1) === name);\n return matching.length === 1 ? matching[0] : undefined;\n}\n\nfunction previewAsset(file: VideoWorkspaceFile, role: VideoPreviewAsset[\"role\"], label: string): VideoPreviewAsset | undefined {\n return file.kind === \"media\" && file.mimeType?.startsWith(\"video/\") === true\n ? { role, label, path: file.path, bytes: file.bytes, version: file.version, mimeType: file.mimeType }\n : undefined;\n}\n\nexport function summarizeVideoProject(\n root: string,\n files: readonly VideoWorkspaceFile[],\n metadata: {\n readonly project?: unknown;\n readonly runManifest?: unknown;\n readonly assembly?: unknown;\n } = {}\n): VideoProjectSummary {\n const id = root.slice(`${VIDEO_DIRECTORY}/`.length);\n const projectFiles = files.filter((file) => file.path.startsWith(`${root}/`));\n const project = record(metadata.project);\n const manifest = record(metadata.runManifest);\n const settings = record(manifest?.settings);\n const assembly = record(metadata.assembly);\n const source = referencedMedia(projectFiles, manifest?.source_video)\n ?? projectFiles.find((file) => file.kind === \"media\" && file.path.startsWith(`${root}/sources/`) && file.mimeType?.startsWith(\"video/\") === true);\n const edited = projectFiles.find((file) => file.path.split(\"/\").at(-1) === \"edited_source.mp4\");\n const final = referencedMedia(projectFiles, assembly?.final_output)\n ?? projectFiles.filter((file) => file.kind === \"media\" && (file.path.startsWith(`${root}/outputs/`) || /^recap_.+\\.(?:mp4|mov|webm)$/iu.test(file.path.split(\"/\").at(-1) ?? \"\"))).at(-1);\n const previews = [\n source === undefined ? undefined : previewAsset(source, \"source\", \"\u539F\u7247\"),\n edited === undefined ? undefined : previewAsset(edited, \"edited\", \"\u526A\u540E\u7247\"),\n final === undefined ? undefined : previewAsset(final, \"final\", \"\u6700\u7EC8\u6210\u7247\")\n ].filter((value): value is VideoPreviewAsset => value !== undefined);\n const names = new Set(projectFiles.map((file) => file.path.split(\"/\").at(-1)));\n const cutMode = settings?.edit_mode === \"cut\" || names.has(\"clip_plan.json\") || edited !== undefined;\n // 0.6.0 records --audio-mode in the run manifest; source-mix and adopted-packet-copy never write\n // narration, so a cut goes straight from edited_source.mp4 to assembly and full has no pause at all.\n const narrated = (text(record(manifest?.audio)?.mode) ?? \"narration\") === \"narration\";\n let state: VideoProjectSummary[\"state\"] = \"not-started\";\n let stage = \"source\";\n let stageLabel = source === undefined ? \"\u7B49\u5F85\u5BFC\u5165\u89C6\u9891\" : \"\u53EF\u4EE5\u5F00\u59CB\";\n let nextArtifact: string | undefined;\n if (final !== undefined) {\n state = \"ready\"; stage = \"complete\"; stageLabel = \"\u6210\u7247\u5DF2\u5C31\u7EEA\";\n } else if (names.has(\"tts_meta.json\")) {\n state = \"working\"; stage = \"assemble\"; stageLabel = \"\u6B63\u5728\u5408\u6210\";\n } else if (names.has(\"narration.json\")) {\n state = \"working\"; stage = \"voiceover\"; stageLabel = \"\u914D\u97F3\u4E0E\u5408\u6210\";\n } else if (cutMode && edited !== undefined) {\n if (narrated) { state = \"waiting\"; stage = \"narration\"; stageLabel = \"\u7B49\u5F85\u89E3\u8BF4\u8BCD\"; nextArtifact = \"narration.json\"; }\n else { state = \"working\"; stage = \"assemble\"; stageLabel = \"\u6B63\u5728\u5408\u6210\"; }\n } else if (cutMode && names.has(\"clip_plan.json\")) {\n state = \"working\"; stage = \"cut\"; stageLabel = \"\u6B63\u5728\u526A\u8F91\";\n } else if (manifest !== undefined && !cutMode && !narrated) {\n state = \"working\"; stage = \"assemble\"; stageLabel = \"\u6B63\u5728\u5408\u6210\";\n } else if (manifest !== undefined) {\n state = \"waiting\";\n stage = cutMode ? \"clip-plan\" : \"narration\";\n stageLabel = cutMode ? \"\u7B49\u5F85\u526A\u8F91\u8BA1\u5212\" : \"\u7B49\u5F85\u89E3\u8BF4\u8BCD\";\n nextArtifact = cutMode ? \"clip_plan.json\" : \"narration.json\";\n }\n const artifacts = projectFiles.flatMap((file): VideoArtifactSummary[] => {\n const name = file.path.split(\"/\").at(-1) ?? \"\";\n const meta = ARTIFACT_META[name];\n return meta === undefined ? [] : [{ ...meta, path: file.path, version: file.version }];\n }).sort((left, right) => left.path.localeCompare(right.path, \"zh-Hans-CN\"));\n return {\n id,\n root,\n title: text(project?.title) ?? id,\n state,\n stage,\n stageLabel,\n nextArtifact,\n previews,\n artifacts\n };\n}\n", "import type { IncomingHttpHeaders } from \"node:http\";\n\ninterface WorkspaceTrustRequest {\n readonly headers: IncomingHttpHeaders | Headers;\n}\n\nfunction header(headers: IncomingHttpHeaders | Headers, name: string): string | undefined {\n if (headers instanceof Headers) return headers.get(name) ?? undefined;\n const value = headers[name];\n return typeof value === \"string\" ? value : undefined;\n}\n\nfunction parseAuthority(authority: string): URL | undefined {\n try { return new URL(`http://${authority}`); }\n catch { return undefined; }\n}\n\nfunction canonicalAuthority(entry: string, url: URL): string {\n const port = url.port !== \"\" ? url.port : new URL(`https://${entry}`).port;\n return port === \"\" ? url.hostname : `${url.hostname}:${port}`;\n}\n\nfunction isLoopbackHostname(hostname: string): boolean {\n if (hostname === \"localhost\" || hostname === \"[::1]\") return true;\n const parts = hostname.split(\".\");\n return parts.length === 4\n && parts[0] === \"127\"\n && parts.every((part) => /^\\d{1,3}$/u.test(part) && Number(part) <= 255);\n}\n\nfunction isTrustedAuthority(host: URL, trustedHosts: readonly string[]): boolean {\n return trustedHosts.some((entry) => {\n const candidate = parseAuthority(entry);\n if (candidate === undefined) return false;\n return canonicalAuthority(entry, candidate) === candidate.hostname\n ? candidate.hostname === host.hostname\n : candidate.host === host.host;\n });\n}\n\n/** Reject malformed declarations at plugin load instead of silently widening access. */\nexport function assertTrustedWorkspaceAuthority(entry: string): void {\n const url = parseAuthority(entry);\n if (url !== undefined && canonicalAuthority(entry, url) === entry.toLocaleLowerCase()) return;\n throw new Error(`oh-story: trustedHosts entry ${JSON.stringify(entry)} is not a bare host[:port] authority`);\n}\n\n/**\n * Same browser trust boundary as DSH's native API: every request must address a\n * loopback or explicitly trusted Host, and browser markers must be same-origin.\n */\nexport function isTrustedWorkspaceRequest(\n request: WorkspaceTrustRequest,\n trustedHosts: readonly string[]\n): boolean {\n const authority = header(request.headers, \"host\");\n if (authority === undefined) return false;\n const host = parseAuthority(authority);\n if (host === undefined) return false;\n if (!isLoopbackHostname(host.hostname) && !isTrustedAuthority(host, trustedHosts)) return false;\n if (header(request.headers, \"sec-fetch-site\") === \"cross-site\") return false;\n const origin = header(request.headers, \"origin\");\n if (origin === undefined) return true;\n try { return new URL(origin).host === host.host; }\n catch { return false; }\n}\n\n/**\n * Permit a generated-game document to navigate from one loopback alias to\n * another (127.0.0.1 \u2194 localhost). Subresources then become same-origin with\n * the isolated preview document and use the stricter path above.\n */\nexport function isTrustedPreviewNavigation(\n request: WorkspaceTrustRequest,\n trustedHosts: readonly string[]\n): boolean {\n if (isTrustedWorkspaceRequest(request, trustedHosts)) return true;\n const authority = header(request.headers, \"host\");\n if (authority === undefined) return false;\n const host = parseAuthority(authority);\n if (host === undefined || (!isLoopbackHostname(host.hostname) && !isTrustedAuthority(host, trustedHosts))) return false;\n return header(request.headers, \"origin\") === undefined\n && header(request.headers, \"sec-fetch-site\") === \"cross-site\"\n && header(request.headers, \"sec-fetch-mode\") === \"navigate\"\n && [\"document\", \"iframe\"].includes(header(request.headers, \"sec-fetch-dest\") ?? \"\");\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["import type { Context } from \"@deepseek-ai/cordis\";\nimport type {} from \"@deepseek-ai/dsh-host-webserver\";\nimport type {} from \"@deepseek-ai/dsh-skill\";\nimport type {} from \"@deepseek-ai/dsh-subagent\";\nimport type {} from \"@deepseek-ai/dsh-tools\";\nimport z from \"@deepseek-ai/schemastery\";\nimport { createDramaSkillProvider, createNovelToGameSkillProvider, createOhStorySkillProvider, createVideoRecapSkillProvider, defaultDramaSkillRoot } from \"./skill-provider.js\";\nimport { ensureDramaAdapterConfig } from \"./drama-adapters.js\";\nimport { hostPython } from \"./host-python.js\";\nimport { registerOhStoryHooks } from \"./native-hooks.js\";\nimport { registerOhStoryRoleTool } from \"./role-tool.js\";\nimport { registerOhStoryProductionTool } from \"./production-tool.js\";\nimport { registerWorkspaceRoute } from \"./workspace-route.js\";\nimport { assertTrustedWorkspaceAuthority } from \"./workspace-request-trust.js\";\n\nexport { createDramaSkillProvider, createNovelToGameSkillProvider, createOhStorySkillProvider, createVideoRecapSkillProvider, parseBundledSkill } from \"./skill-provider.js\";\nexport { OH_STORY_ROLE_NAMES, loadBundledRole } from \"./role-provider.js\";\nexport { createOhStoryRoleTool, OH_STORY_ROLE_TOOL_NAME, registerOhStoryRoleTool, roleToolFilter, type OhStoryRoleSubagents } from \"./role-tool.js\";\nexport { createOhStoryProductionTool, registerOhStoryProductionTool } from \"./production-tool.js\";\nexport { OH_STORY_PRODUCTION_TOOL_NAME, validateProductionIntent, type ProductionIntentArgs } from \"./production-intent.js\";\nexport { bundledReferenceGuard, createOhStoryReferenceTool, OH_STORY_REFERENCE_TOOL_NAME } from \"./reference-tool.js\";\nexport { registerWorkspaceRoute } from \"./workspace-route.js\";\nexport { registerOhStoryHooks } from \"./native-hooks.js\";\nexport { DRAMA_ADAPTER_CONFIG_ENV, DRAMA_ADAPTERS, dramaAdapterConfigPath, dramaAdapterStatuses, ensureDramaAdapterConfig } from \"./drama-adapters.js\";\n\nexport const name = \"oh-story\";\nexport const inject = [\"skills\", \"subagents\", \"tools\", \"typert\", \"webServer\"];\n\n/** DSH owns models, providers, presets, permissions, roots, runs, and sessions. */\nexport interface Config {\n readonly editorMaxBytes?: number;\n readonly trustedHosts?: string[];\n}\n\nexport const Config = z.object({\n editorMaxBytes: z.natural().min(65_536).max(8_388_608).default(2_097_152),\n trustedHosts: z.array(String).default([])\n}) as z<Config>;\n\n/** Mount only domain contributions into the current DSH process. */\nexport async function apply(context: Context, config: Config = {}): Promise<void> {\n const trustedHosts = config.trustedHosts ?? [];\n for (const entry of trustedHosts) assertTrustedWorkspaceAuthority(entry);\n context.skills.registerProvider(() => createOhStorySkillProvider());\n context.skills.registerProvider(() => createDramaSkillProvider());\n context.skills.registerProvider(() => createNovelToGameSkillProvider());\n context.skills.registerProvider(() => createVideoRecapSkillProvider());\n registerOhStoryHooks(context);\n registerOhStoryProductionTool(context);\n await registerOhStoryRoleTool(context);\n registerWorkspaceRoute(context, { maxBytes: config.editorMaxBytes ?? 2_097_152, trustedHosts });\n // Register the bundled media adapters for this host up front so the first\n // short-drama-produce run has a config to pass; the preflight route repeats\n // this and reports the outcome, so a failure here only delays the message.\n await ensureDramaAdapterConfig(defaultDramaSkillRoot(), { python: (await hostPython()).command });\n}\n\nexport default { name, inject, Config, apply };\n", "import { readdir, readFile } from \"node:fs/promises\";\nimport { basename, dirname, isAbsolute, join, relative, resolve } from \"node:path\";\nimport { dramaAdapterConfigPath, dramaAdapterSummary, DRAMA_ADAPTER_CONFIG_ENV } from \"./drama-adapters.js\";\nimport { fileURLToPath, pathToFileURL } from \"node:url\";\nimport {\n BUNDLED_SKILL_RANK,\n type SkillCandidate,\n type SkillDefinition,\n type SkillProvider\n} from \"@deepseek-ai/dsh-skill\";\n\nconst STORY_PROVIDER_NAME = \"oh-story\";\nconst DRAMA_PROVIDER_NAME = \"short-drama\";\nconst GAME_PROVIDER_NAME = \"novel-to-game\";\nconst VIDEO_PROVIDER_NAME = \"video-recap\";\nconst DSH_SKILL_BRIDGE = [\n \"<oh-story-dsh-integration>\",\n \"This Skill is a native contribution to the current DeepSeek Harness session.\",\n \"DSH owns the workspace, model, preset, permissions, Session Log, tools, subagents, cancellation, resume, and Agent UI.\",\n \"Never start another Agent runtime, session transport, Dashboard, SSE stream, polling loop, or model configuration.\",\n \"All seven upstream Oh Story specialist Roles are bundled. Invoke one with oh_story_role and a self-contained prompt.\",\n \"Never inspect .claude/agents, .codex/agents, .opencode/agents, .agents/agents, .zcode, or .story-deployed to decide whether a Role is available.\",\n \"Oh Story Roles are reached only through oh_story_role. Never start one through a generic subagent or Task tool \u2014 not DSH's subagent or subagent_fork tools and not invoke_subagent \u2014 and never pass a Role name as subagent_type, agent_type, agent, or TypeName, even where the upstream text below describes that for another host.\",\n \"Use only DSH-visible tools. DSH sandbox and permission policy remain authoritative.\",\n // Upstream deploys these \u300C\u4E0E\u4F5C\u8005\u534F\u4F5C\u300D rules only in its CLAUDE.md/AGENTS.md\n // templates, which DSH does not install.\n \"Working with the author: reply and report in the author's writing terms (book, chapter, outline, settings), never in script, field, or state names; attach a raw error only when something failed. A template block marked <!-- author-report --> is only a format reference: output its text directly, without that marker and without a code fence.\",\n \"Record a writing habit or preference the author asks to remember, forget, or confirm only through the story Skill's author memory, whose scripts/author_memory_commit.py writes .story/\u4F5C\u8005\u8BB0\u5FC6/; never keep it in a host or DSH memory. Simply follow a one-off request without recording it.\",\n \"Never edit the bundled Skill files (SKILL.md, references/, scripts/). When a Skill script fails, stop and show the author the command you ran and its error instead of patching or working around it.\",\n \"</oh-story-dsh-integration>\"\n].join(\"\\n\");\n/** Oh Story 0.8.4 long-form analysis Stage 2 (pipeline-ops.md \u00A74), shared by story-long-analyze and story-import. */\nconst DSH_ANALYSIS_BATCHES = [\n \"Stage 2 batches in DSH: dispatch each planned batch with oh_story_role, role chapter-extractor, and a self-contained prompt that copies this batch's plan fields verbatim, prefixing paths with {\u62C6\u6587\u76EE\u5F55}/: batch_id, input_kind, source_files (per-chapter source_locator for a raw batch), chapter_chars, min_plot_points, the output file {\u62C6\u6587\u76EE\u5F55}/_analysis_cache/\u8F93\u5165-{\u6279\u6B21ID}.md, and the plan's handoff_cache when it is not empty.\",\n \"The extractor reads the source itself, writes or edits only that batch input file (DSH denies any other write or edit by a chapter-extractor child), and replies with one receipt line; do not read the file yourself.\",\n \"Commit it with manage_analysis_run.py commit, one commit at a time in this session. When a commit is rejected, dispatch the same batch to a chapter-extractor again with every field above plus the error code, and have it fix only the broken spots with edit (rewriting the whole file only when its structure is broken), then commit again.\",\n \"Run manage_analysis_run.py and the other bundled Python 3 scripts through the current DSH execution world, trying python3, python, then py -3. If none is available, stop and tell the author in plain words that this step needs Python 3 on the machine running DSH; never simulate a script's output or hand-write the files it owns.\",\n \"Keep concurrent oh_story_role calls modest. The default is upstream's \u6709\u9650\u5E76\u884C tier: three batches per round, issued together, the next round only after all three are committed; an unasked, full, multi-book, or import run uses it. DSH runs calls from one step in parallel only up to the host's own limit and may run them one after another, so never promise more. Use \u4E32\u884C or \u4E0D\u9650\u6279\u6B21\u987A\u5E8F only when the author chooses it, and under \u4E0D\u9650\u6279\u6B21\u987A\u5E8F halve the count on any rate limit, timeout, or child error.\"\n].join(\" \");\nconst DSH_SKILL_OVERRIDES: Readonly<Partial<Record<string, string>>> = {\n story: \"The \u5C0F\u8BF4 workspace is an official DSH conversation view. Never start or open a second web application.\",\n \"story-setup\": \"Initialize or validate novel project data only. DSH already supplies Skills, Roles, hooks, tools, permissions, sessions, and UI; never deploy Claude/OpenCode/Codex/Antigravity/ZCode/OpenClaw/Reasonix files or a .story-deployed marker.\",\n \"story-long-analyze\": `Use oh_story_role for chapter extraction or specialist analysis. Never inspect platform agent directories or require a deployed external Agent definition. ${DSH_ANALYSIS_BATCHES}`,\n \"story-long-write\": \"All named Roles are provided through oh_story_role. Do not check platform agent files. Keep the upstream writing, Tracking, lint, outline, revision, and quality workflows. Create and assemble \u6B63\u6587/ chapter files only with the write and edit tools, never through shell redirection, cp, mv, tee, or a script, so that DSH's outline guard, its Tracking reminder, and the \u5C0F\u8BF4 view observe the write; upstream's own in-place chapter fixes such as storyctl.py chapter check --fix-punctuation stay as upstream describes.\",\n \"story-review\": \"All named reviewer Roles are provided through oh_story_role. Do not check platform agent files; full/lean review may use the bundled Roles directly. When a review falls back to solo in DSH, the reason is that oh_story_role or DSH's spawn runtime is unavailable in this Session (Fallback agent tool unavailable -> solo) or a Role run failed (Fallback spawn failed -> solo); say that in one plain sentence. Never tell the author that the reviewers are not installed, missing, or outdated, and never tell them to run /story-setup.\",\n \"story-import\": `All named Roles are provided through oh_story_role. Do not require story-setup to deploy them, never inspect platform agent directories or .story-deployed, and never offer the author Step 4's choice to install a writing environment with /story-setup: in DSH record \u5199\u4F5C\u73AF\u5883 in .story/work/\u5BFC\u5165\u8BB0\u5F55.md as installed, with the analysis helper and story-architect both available. Phase 2 runs the story-long-analyze pipeline the DSH way below; an import counts as automatic continuation, so it uses the limited-parallel tier without asking. ${DSH_ANALYSIS_BATCHES} Run the scripts this Skill needs (build_outline_brief.py, tracking_commit.py init and check with Python 3; check-outline-contract.js with Node) the same way. Keep upstream's order: Phase 3-L Step 2 copies the manuscript into \u6B63\u6587/, Step 10 reverse-builds the \u7EC6\u7EB2 in batches, and Phase 4 initialises Tracking. DSH's prose guard mirrors the outline gate of upstream proseBlockReason for books with \u5927\u7EB2/ or \u8FFD\u8E2A/, so open an import window before Step 2 copies any chapter: create .story/work/\u5BFC\u5165\u4E2D.md in the book directory (the workspace root in DSH's usual single-book layout) with one line naming the book being imported, and delete it right after Phase 4's tracking_commit.py init and check both succeed. The window only holds while \u8FFD\u8E2A/_tracking-state.json is absent. \u5BFC\u5165\u4E2D.md is DSH's own marker; keep upstream's \u5BFC\u5165\u8BB0\u5F55.md exactly as the Skill describes.`,\n \"story-deslop\": \"Use the bundled narrative-writer Role through oh_story_role when specialist review is useful. Never inspect platform agent directories.\",\n \"story-short-analyze\": \"Use oh_story_role for specialist analysis. Never inspect platform agent directories or require external Agent deployment.\",\n \"story-short-write\": \"All named Roles are provided through oh_story_role. Do not inspect platform agent files; preserve the upstream short-fiction workflow and quality gates.\",\n \"browser-cdp\": \"Use only browser or web capabilities visible in the current DSH preset. Do not start a parallel browser host; if no compatible capability is visible, explain the limitation.\",\n \"story-cover\": \"Use only image-generation or HTTP capabilities visible in the current DSH preset. Never assume a separate Codex or Claude runtime.\"\n};\nconst DSH_DRAMA_BRIDGE = [\n \"<short-drama-dsh-integration>\",\n \"This Skill is a native contribution to the current DeepSeek Harness session.\",\n \"DSH owns the workspace, model, preset, permissions, Session Log, tools, approvals, cancellation, resume, and Agent UI.\",\n \"The \u77ED\u5267 tab is the creator workspace. Never start dashboard_server.py, another web server, Dashboard, Agent runtime, session transport, or model configuration.\",\n \"Drama Skills uses a creator-first contract: each episode keeps only the requested documents, up to five creator-facing sources at \u5267\u96C6/<EP>/\u5267\u672C.md, \u89C6\u89C9\u8BBE\u5B9A.md, \u5206\u955C.md, \u56FE\u7247\u63D0\u793A\u8BCD.md, and \u89C6\u9891\u63D0\u793A\u8BCD.md. Never precreate empty documents, backfill nominal stages, or start work the creator did not request. Persisted reviews use creator-readable Markdown under \u5BA1\u67E5/; an oral review writes nothing.\",\n \"\u5267\u96C6/<EP>/\u526A\u8F91\u5355.md is the v0.7 assembly record, not a sixth creative truth: the five creator documents stay the creative truth. It is written after readable media exists and records what reaches the cut \u2014 which footage or accepted static keyframes are kept or left unused and why, each cut's in/out timing, its subtitles, \u753B\u9762\u6587\u5B57 overlays, \u97F3\u6548 cues, \u914D\u97F3 and \u73AF\u5883\u58F0, post-processing such as shot-match correction or an external mix, and the delivery spec including optional \u9897\u7C92 grain and \u63A5\u955C\u5339\u914D. It never changes a line, a shot's job, or a declared duration; changing any of those means returning to the document that owns it.\",\n \"For a v0.6 project, never create a parallel JSON/JSONL lifecycle truth, indexes, fingerprints, coverage tables, or QA records merely because legacy maintenance scripts and templates remain bundled.\",\n \"Never upgrade a v0.5 structured project in place or mix both contracts in one project root. Keep legacy production/audit artifacts read-only and pinned to v0.5; migrate only into a new creator-first root with manual per-episode creator confirmation.\",\n \"Use only tools visible in the current DSH preset and preserve the upstream project ownership, freshness, review, and explicit production-confirmation contracts.\",\n \"Use oh_story_production only for semantic production-view intents (open/focus, explicit shot order, or tracking a job that this Agent is actually executing). Cosmetic canvas layout remains creator-controlled. The tool changes only the Session projection: it does not edit creator documents, generate media, or authorize production.\",\n \"Production credentials remain outside project files. Never treat a prior acceptance, preview, continuation request, or budget discussion as confirmation for a paid production run.\",\n \"</short-drama-dsh-integration>\"\n].join(\"\\n\");\nconst DSH_DRAMA_OVERRIDES: Readonly<Partial<Record<string, string | ((skillRoot: string) => string)>>> = {\n \"short-drama\": \"A dashboard request means focus or use the native \u77ED\u5267 tab in this DSH Session. Do not run the bundled standalone Dashboard script. New projects follow only the v0.6 creator-first contract and create only documents required by the current request.\",\n \"short-drama-produce\": (skillRoot) => `Use an upstream adapter only after the creator explicitly confirms the exact current job. Its source must be the current creator-first Markdown and its output belongs under \u5267\u96C6/<EP>/\u5236\u4F5C\u6210\u679C/. DSH permissions and approval UI remain authoritative. When oh_story_production is visible, register a previewed image or video job with track_job after the confirmation is valid and before run \u2014 never at prepare time \u2014 passing the same job ID, target, modality and count the creator just approved. track_job's jobKind is image, video or composition (the assembled cut), so from this Skill it registers image and video jobs only: speech (tts) and music jobs pass through the same prepare \u2192 explicit creator confirmation \u2192 run gate but are never registered with track_job or relabelled as another kind, and their audio results stay under \u5267\u96C6/<EP>/\u5236\u4F5C\u6210\u679C/. Optional voice references belong on the MOTION entry's separate \u53C2\u8003\u97F3\u9891 line, never in \u8F93\u5165\u53C2\u8003\u56FE or the workbench image picker. Compile them as reference_audio bindings, preserve character exactly from \u89D2\u8272, and match the project-local audio path to that character's single \u58F0\u97F3\u53C2\u8003 in \u89C6\u89C9\u8BBE\u5B9A.md. \u4E0D\u5F97\u63A7\u5236 lists \u53F0\u8BCD\u3001\u8BED\u6C14\u3001\u60C5\u7EEA individually. The selected adapter profile must explicitly declare reference_audio in reference_roles; otherwise reject before paid submission, never drop or substitute the binding. The generated generic adapter profiles intentionally omit reference_audio because their model IDs are environment-selected; use a creator-owned OH_STORY_DRAMA_ADAPTER_CONFIG profile that declares audio support only for a known reference-audio-capable model. DeepSeek generates no media: every image, video, speech, or music result comes from a provider adapter. The bundled adapters are ${dramaAdapterSummary()}; they are registered for this DSH host in ${dramaAdapterConfigPath(skillRoot).path} \u2014 pass that file as --adapter-config unless the creator names another config (${DRAMA_ADAPTER_CONFIG_ENV}). Credentials are read only from the DSH host process environment. Before preparing a paid job, name the adapter that will run it; if its variables are missing, tell the creator exactly which ones to export before starting DSH instead of failing inside run. Never read, print, or write credential values. A submitted video job is already billed, so an interrupted run is recovered, not resubmitted: when audit reports orphaned_provider_job, recover it with collect, passing --job-id \u2014 the drama job the finding names, not its provider_job_id, which collect reads from the run handle itself. collect spends nothing and does not need the confirmation gate \u2014 the gate exists to stop unintended spending \u2014 but re-running the same job does, and would charge the creator twice.`,\n \"short-drama-edit\": [\n \"Assembly runs inside this DSH Session. Write \u5267\u96C6/<EP>/\u526A\u8F91\u5355.md first, then run edit_tool.py check and render through the current DSH execution world; the rendered cut belongs under \u5267\u96C6/<EP>/\u5236\u4F5C\u6210\u679C/\u6210\u7247/ and the \u77ED\u5267 tab shows it there. ffmpeg and ffprobe come from the DSH host \u2014 when one is missing, say so instead of approximating or reporting an untested measurement as a pass.\",\n // edit_tool.py 0.7.1 `_unaccounted_shots`: `- \u672A\u91C7\u7528\u955C\u5934\uFF1A` is read only outside CUT blocks, split on `\uFF1B`, and each item must fullmatch `MOTION-\u2026\uFF08\u7406\u7531\uFF1A<non-empty>\uFF09`.\n \"Video cuts use existing MOTION IDs; static-frame cuts use SHOT IDs from \u5206\u955C.md or IMG IDs from \u56FE\u7247\u63D0\u793A\u8BCD.md and accepted png/jpg/jpeg/webp files. Every unused MOTION and, when static cuts exist, every storyboard SHOT must be accounted for before the first `## CUT-` on one line: `- \u672A\u91C7\u7528\u955C\u5934\uFF1AMOTION-\u2026\uFF08\u7406\u7531\uFF1A\u2026\uFF09\uFF1BSHOT-\u2026\uFF08\u7406\u7531\uFF1A\u2026\uFF09`. Join items with a full-width `\uFF1B`; reasons name \u6587\u4EF6\u7F3A\u5931, \u8D28\u91CF\u4E0D\u53EF\u7528 or \u53D9\u4E8B\u53D6\u820D. A static CUT starts at 0.00, lasts at least 0.50 seconds, requires the delivery width/height/frame rate, and may use \u8FD0\u955C. The native production sequence accepts video and accepted keyframe images, keeps storyboard order and source identity, and dispatches /short-drama-edit in Chat; never relabel images as video or generate paid video unnecessarily.\",\n \"Every video cut must share one width, height and frame rate: render hard-joins the encoded video segments and never scales or retimes them. Static cuts are rendered to the delivery specification with the declared crop/motion. When check reports a mismatch, normalise the odd clips to the delivery spec with ffmpeg in the DSH execution world, under approval, preserving the composition. Write them under \u5267\u96C6/<EP>/\u5236\u4F5C\u6210\u679C/\u6210\u7247/\u89C4\u683C\u7EDF\u4E00/, an edit-owned intermediate, never beside the produce-stage originals and never over produced footage, and name them without the original's job-id token (the MOTION ID will do). Record the crop or pad in that CUT's block (not in its \u753B\u9762 line, which accepts only \u4EAE\u5EA6/\u9971\u548C/\u8272\u6E29), point \u6765\u6E90 at the new file, update \u5165\u70B9/\u51FA\u70B9 if the conversion moved them, and rerun check.\",\n \"The default burned-subtitle route needs an ffmpeg built with libass; when the host's ffmpeg lacks it, say so instead of silently dropping subtitles. Remotion renders every frame through a headless browser from a Node workspace outside the project, ~/.cache/short-drama-edit/remotion, which edit_tool.py rewrites on each run: the optional subtitle route uses it, and any `\u753B\u9762\u6587\u5B57` line in \u526A\u8F91\u5355.md requires it whatever the subtitle route. Install it (npm install in that workspace; an install from before Drama Skills 0.8 must run npm install again) only after the creator approves, through DSH approval. Without that approval write no \u753B\u9762\u6587\u5B57 lines and tell the creator the blank on-screen panels stay empty. Never treat Remotion as a second Agent runtime, dashboard, or session transport.\",\n \"The \u58F0\u97F3 line in \u526A\u8F91\u5355.md is a record, not an instruction the built-in render executes. render trims, auto-matches adjacent cuts within one scene (a CUT's \u753B\u9762 correction replaces it, `- \u753B\u9762\uFF1A\u4E0D\u6821` skips it, and `- \u63A5\u955C\u5339\u914D\uFF1A\u65E0` in the delivery spec turns it off), hard-joins, mixes in the `\u97F3\u6548` lines, cross-cut `\u914D\u97F3` and looping `\u73AF\u5883\u58F0`, burns subtitles and \u753B\u9762\u6587\u5B57, applies optional \u9897\u7C92, and normalises loudness. A mix beyond the declared \u97F3\u6548/\u914D\u97F3/\u73AF\u5883\u58F0 lines, crossfade, transition or format conversion is an external ffmpeg step, run under approval, that writes a temporary file, ends as render does with whole-film two-pass loudnorm to the declared \u4EA4\u4ED8\u54CD\u5EA6 (I=<\u4EA4\u4ED8\u54CD\u5EA6>:TP=-1.5:LRA=11, the second pass fed the first pass's measurements with linear=true, audio re-encoded as AAC 192k at 48 kHz), and only then replaces \u5267\u96C6/<EP>/\u5236\u4F5C\u6210\u679C/\u6210\u7247/\u6210\u7247.mp4; record its command in \u526A\u8F91\u5355.md and repeat it after any re-render, which overwrites that file. Run edit_tool.py verify last, on that delivered file, and report every \u672A\u6D4B item as untested, never as passed.\",\n \"This stage never generates footage and never edits \u5267\u672C.md, \u5206\u955C.md, or \u89C6\u9891\u63D0\u793A\u8BCD.md \u2014 route those back to their owning Skill.\"\n ].join(\" \"),\n \"short-drama-assets\": \"Keep one stable `- ID\uFF1AVISUAL-*` line on every \u4EBA\u7269/\u9020\u578B/\u5730\u70B9/\u9053\u5177/\u72B6\u6001 entry in \u89C6\u89C9\u8BBE\u5B9A.md, and never change an existing ID when editing its heading or text. The \u751F\u4EA7 view identifies canvas nodes by that ID; entries without one still render, but the workbench reports their node identity as unstable.\"\n};\nconst DSH_GAME_BRIDGE = [\n \"<novel-to-game-dsh-integration>\",\n \"This Skill is a native contribution to the current DeepSeek Harness session.\",\n \"DSH owns the workspace, model, preset, permissions, Session Log, tools, approvals, cancellation, resume, Todo, and Chat UI.\",\n \"The \u6E38\u620F tab is the playable Game Studio. Never start a second Agent runtime, dashboard, session transport, or model configuration.\",\n \"Keep the complete upstream seven-Skill pipeline and write adaptation artifacts under game-adaptations/<project>/ exactly as the upstream contracts specify.\",\n \"For a web target, keep the authoritative playable entry at build/app/index.html so Game Studio can preview it. Do not silently replace a requested non-web runtime with a web build.\",\n \"Use only DSH-visible tools and approvals. qa/verification.json remains the sole machine QA truth and must cover launch, render, input, coreLoop, outcome, and restart with real execution evidence.\",\n \"The bundled Jin Ping Mei project is a read-only example, not a template to copy mechanically and not proof that another adaptation passed QA.\",\n \"</novel-to-game-dsh-integration>\"\n].join(\"\\n\");\nconst DSH_VIDEO_BRIDGE = [\n \"<video-recap-dsh-integration>\",\n \"This Skill is a native contribution to the current DeepSeek Harness session.\",\n \"DSH owns the workspace, model, preset, permissions, Session Log, tools, approvals, cancellation, resume, Todo, Chat, and the \u89C6\u9891 preview Studio.\",\n \"Never start a second Agent runtime, dashboard, session transport, web server, polling loop, or model configuration.\",\n \"A dashboard request means the native \u89C6\u9891 tab in this DSH Session: dashboard_server.py and its dashboard assets are not bundled, so never try to run them. To inspect a resource library, use the read-only scripts/library.py check, list, or show.\",\n \"Keep the complete upstream six-Skill production pipeline plus the on-demand video-reference Skill; video-reference extracts reusable production references only when requested and never enters the default production path. Put each project under video-recaps/<project>/, copy or import source media under sources/, and use work/ as the upstream work_dir so the Studio can discover authoritative manifests and outputs. A project binding passed with --project belongs at video-recaps/<project>/recap_project.json.\",\n \"full-mode validation is lint-only: never truncate, drop, merge or reorder approved narration to satisfy a budget; report over_budget and request a revised script. final_qc.json uses schema 2 findings (code/message/blocking/evidence/next_action); do not read removed golden_eval.json, mimo_qc.json or preflight_qc.json. Do not pass removed --mimo-qc, --preserve-approved-text or --clip-padding flags, MIMO_QC* variables, CLIP_PADDING or SOURCE_VIDEO. Except dub, delivery uses tagged H.264 8-bit 4:2:0 with true peak <= -1 dBTP; delivered_true_peak_over_target blocks delivery. If libass is unavailable, deliver external .srt rather than dropping subtitles or aborting preflight.\",\n \"The Video Studio is a preview and artifact surface, not a nonlinear editor. Do not invent a second project-state format, timeline truth, or render queue; recap_run_manifest.json, recap_phase.json, timeline.json, assembly_manifest.json, and the upstream artifacts remain authoritative.\",\n \"--edit-mode dub sends the source audio to MiMo ASR and clones the original speaker's voice, so it requires --confirm-voice-rights. Ask the user first and pass it only after they confirm they may use the video's audio and the speaker consents to voice cloning; never add it on your own, including to resume commands printed for an older work_dir.\",\n \"MIMO_API_KEY, FISH_API_KEY, and voice credentials stay in the host environment. Never write secrets into project files, tool arguments shown to the browser, or chat output.\",\n \"Use only DSH-visible tools and approvals. Run Python and ffmpeg through the current DSH execution world, preserve cancellation, and do not install or upgrade system dependencies without explicit user approval.\",\n \"When a new edited or final video is ready, tell the user that Video Studio can load it; never interrupt playback by replacing the currently loaded video silently.\",\n \"</video-recap-dsh-integration>\"\n].join(\"\\n\");\n\nconst DSH_NATIVE_SKILLS: Readonly<Partial<Record<string, string>>> = {\n story: `# story \u2014 DSH \u5C0F\u8BF4\u6D41\u7A0B\u5165\u53E3\n\n\u5728\u5F53\u524D DSH Session \u5185\u5224\u65AD\u7528\u6237\u610F\u56FE\uFF0C\u5E76\u52A0\u8F7D\u6700\u5339\u914D\u7684 Oh Story Skill\uFF1A\n\n- \u65B0\u5EFA\u6216\u4FEE\u590D\u5C0F\u8BF4\u5DE5\u7A0B\uFF1Astory-setup\n- \u957F\u7BC7\u89C4\u5212\u4E0E\u5199\u4F5C\uFF08\u8BA8\u8BBA\u957F\u7BC7\u7ED3\u6784\u3001\u89C4\u5212\u5267\u60C5\u3001\u5F00\u4E66\u3001\u5199\u5927\u7EB2\u3001\u8865\u7EC6\u7EB2\u3001\u5199\u6B63\u6587\u3001\u65E5\u66F4\uFF09\uFF1A\n story-long-write\u3002\u53EA\u8981\u7ED3\u6784\u3001\u5927\u7EB2\u3001\u5377\u7EB2\u6216\u7EC6\u7EB2\u65F6\u53EA\u4EA4\u4ED8\u6240\u8BF7\u6C42\u7684\u89C4\u5212\uFF0C\u4E0D\u5199\u6B63\u6587\uFF1B\n \u7528\u6237\u660E\u786E\u8981\u6C42\u5199\u6B63\u6587\u624D\u8FDB\u5165\u6B63\u6587\u6D41\u7A0B\n- \u957F\u7BC7\u9009\u9898/\u626B\u699C\uFF1Astory-long-scan\uFF1B\u957F\u7BC7\u62C6\u6587\uFF1Astory-long-analyze\n- \u7075\u611F\u5E93\u3001\u63D0\u70BC\u7075\u611F\u3001\u8DE8\u4E66\u7075\u611F\u805A\u5408\u3001\u66F4\u65B0\u7075\u611F\u5E93\uFF1Astory-long-analyze \u7684\u53EF\u9009\u7075\u611F\u5E93\u7BA1\u9053\n \uFF08\u5355\u4E66\u62C6\u6587\u4E0D\u81EA\u52A8\u5165\u5E93\uFF09\n- \u77ED\u7BC7\u9009\u9898/\u62C6\u6587/\u5199\u4F5C\uFF1Astory-short-scan\u3001story-short-analyze\u3001story-short-write\n- \u5BFC\u5165\u5DF2\u6709\u4F5C\u54C1\uFF1Astory-import\n- \u5BA1\u7A3F\u4E0E\u53BB AI \u5473\uFF1Astory-review\u3001story-deslop\n- \u5C01\u9762\uFF1Astory-cover\n- \u67E5\u672C\u4E66\u7684\u89D2\u8272\u3001\u4F0F\u7B14\u3001\u8FDB\u5EA6\u6216\u8BBE\u5B9A\uFF1A\u7528 oh_story_role \u8C03\u7528 story-explorer\uFF1B\u67E5\u5916\u90E8\u8D44\u6599\uFF1A\n story-researcher\u3002\u56DE\u7B54\u8BB2\u6545\u4E8B\u91CC\u7684\u4E8B\uFF0C\u7F16\u53F7\u53EA\u8DDF\u7740\u6545\u4E8B\u63CF\u8FF0\u51FA\u73B0\n- \u7BA1\u7406\u4F5C\u8005\u4E60\u60EF\uFF08\u8BB0\u4F4F/\u67E5\u770B/\u786E\u8BA4/\u66FF\u6362/\u5FD8\u6389\u5199\u4F5C\u504F\u597D\uFF09\uFF1A\u52A0\u8F7D\u672C skill \u7684\n references/author-memory.md\uFF0C\u53EA\u7528\u672C skill \u7684 scripts/author_memory_commit.py \u7BA1\u7406\n \u4E24\u7EA7\u4F5C\u8005\u8BB0\u5FC6\uFF1A\u5168\u5C40\u3001\u9898\u6750\u3001\u6D41\u7A0B\u6761\u76EE\u5728\u5DE5\u4F5C\u533A .story/\u4F5C\u8005\u8BB0\u5FC6/\uFF08AP \u7F16\u53F7\uFF09\uFF0C\u672C\u4E66\u6761\u76EE\u5728\n \u4E66\u7EA7 store\uFF08BP \u7F16\u53F7\uFF09\u3002--workspace \u5FC5\u987B\u663E\u5F0F\u4F20\u3002DSH \u7684\u5C0F\u8BF4\u5DE5\u4F5C\u533A\u901A\u5E38\u5C31\u662F\u4E66\u6839\n \uFF08\u6B63\u6587/\u3001\u8BBE\u5B9A/ \u76F4\u63A5\u5728\u5DE5\u4F5C\u533A\u6839\uFF09\uFF1A\u6B64\u65F6 --workspace \u4E0E --book-root \u90FD\u4F20\u5DE5\u4F5C\u533A\u672C\u8EAB\uFF0C\n \u4E66\u7EA7 store \u5728 .story/\u4F5C\u8005\u8BB0\u5FC6/\u4E66\u7EA7/\uFF1B\u4E66\u5728\u5B50\u76EE\u5F55\u65F6 --book-root \u4F20\u90A3\u672C\u4E66\u7684\u76EE\u5F55\u3002\n \u5904\u7406\u67D0\u672C\u4E66\u65F6\u6BCF\u6761\u547D\u4EE4\u90FD\u5E26 --book-root\uFF08\u4E66\u7EA7\u64CD\u4F5C\u7F3A\u5B83\u76F4\u63A5\u62A5\u9519\uFF09\uFF0Cquery \u5FC5\u987B\u5E26\n --kind\uFF08\u53EF\u91CD\u590D\uFF09\u3002\u53EA\u8BB0\u4F5C\u8005\u660E\u786E\u8BF4\u51FA\u7684\u504F\u597D\uFF0C\u4E0D\u4ECE\u53CD\u590D\u4FEE\u6539\u6216\u6210\u7A3F\u63A8\u65AD\u3002\u5DE5\u5177\u672A\u8FD4\u56DE\n Author Memory Receipt \u524D\u4E0D\u5F97\u58F0\u79F0\u5DF2\u8BB0\u4F4F\uFF1B\u544A\u8BC9\u4F5C\u8005\u65F6\u5148\u7528\u4E00\u53E5\u4EBA\u8BDD\u8BF4\u8BB0\u4F4F\u4E86\u4EC0\u4E48\uFF0C\n \u56DE\u6267\u653E\u6700\u540E\u4E00\u884C\u3002\u4F5C\u8005\u8BF4\u300C\u6574\u7406\u4F5C\u8005\u8BB0\u5FC6\u300D\u3001\u56DE\u6267\u63D0\u793A\u4E60\u60EF\u6512\u5F97\u592A\u591A\u3001\u5DE5\u5177\u62A5\u5355\u4E66\u5E03\u5C40\u9519\u8BEF\uFF0C\n \u6216\u5DE5\u4F5C\u533A\u753B\u50CF\u91CC\u8FD8\u6709\u300C\u672C\u4E66\uFF1A\u300D\u6761\u76EE\uFF08\u5347\u7EA7\u524D\u5199\u5165\u7684\u672C\u4E66\u504F\u597D\uFF0C\u5DF2\u4E0D\u53C2\u4E0E\u67E5\u8BE2\uFF09\u65F6\uFF0C\u518D\u52A0\u8F7D\n references/author-memory-maintenance.md\uFF1B\u8FC1\u79FB\u300C\u672C\u4E66\uFF1A\u300D\u6761\u76EE\u5C31\u6309\u5B83\u8FD0\u884C\u4E00\u6B21\n migrate --workspace {\u5DE5\u4F5C\u533A} --book-root {\u4E66\u76EE\u5F55} \u628A\u5B83\u4EEC\u642C\u8FDB\u4E66\u7EA7 store\u3002\n\n\u53EA\u8BF4 /story\u3001\u770B\u4E0D\u51FA\u610F\u56FE\u65F6\uFF0C\u4E0D\u8D34\u8DEF\u7531\u8868\uFF0C\u7ED9\u56DB\u4E2A\u767D\u8BDD\u9009\u9879\uFF1A\u300C\u5F00\u4E00\u672C\u957F\u7BC7\u6216\u63A5\u7740\u5199\u300D\u2192\nstory-long-write\uFF1B\u300C\u5199\u4E00\u7BC7\u77ED\u7BC7\u300D\u2192 story-short-write\uFF1B\u300C\u628A\u4E00\u7AE0\u6539\u5F97\u4E0D\u90A3\u4E48 AI\u300D\u2192\nstory-deslop\uFF1B\u300C\u66F4\u591A\uFF08\u62C6\u4E66\u3001\u626B\u699C\u3001\u5BFC\u5165\u65E7\u7A3F\u3001\u5BA1\u7A3F\u3001\u5C01\u9762\uFF09\u300D\u2192 \u518D\u5217\u8FDB\u9636\u9879\u3002\u610F\u56FE\u660E\u786E\u65F6\n\u76F4\u63A5\u8FDB\u5165\u5BF9\u5E94 Skill\uFF1B\u53EA\u5DEE\u4E00\u4E2A\u4F1A\u6539\u53D8\u6D41\u7A0B\u7684\u9009\u62E9\u65F6\u53EA\u95EE\u8FD9\u4E00\u4E2A\u95EE\u9898\u3002\u9879\u76EE\u6587\u4EF6\u3001Agent\u3001\n\u6A21\u578B\u3001\u6743\u9650\u3001Session Log \u548C UI \u5747\u7531\u5F53\u524D DSH \u4F1A\u8BDD\u7BA1\u7406\u3002\u5C0F\u8BF4\u6587\u4EF6\u901A\u8FC7\u201C\u5C0F\u8BF4\u201D\u89C6\u56FE\u67E5\u770B\uFF0C\nAgent \u8FC7\u7A0B\u901A\u8FC7\u53F3\u4FA7\u52A8\u6001\u680F\u6216\u5B98\u65B9 Chat \u67E5\u770B\u3002\u7981\u6B62\u542F\u52A8\u72EC\u7ACB Dashboard\u3002`,\n \"story-setup\": `# story-setup \u2014 DSH \u539F\u751F\u5C0F\u8BF4\u5DE5\u7A0B\u521D\u59CB\u5316\n\n\u53EA\u521D\u59CB\u5316\u6216\u6821\u9A8C\u5F53\u524D DSH workspace \u4E2D\u7684\u5C0F\u8BF4\u6570\u636E\uFF0C\u4E0D\u90E8\u7F72\u4EFB\u4F55 Agent \u5E73\u53F0\u6587\u4EF6\u3002\n\n1. \u68C0\u67E5\u73B0\u6709\u6B63\u6587\u3001\u8BBE\u5B9A\u3001\u5927\u7EB2\u548C\u8FFD\u8E2A\u6587\u4EF6\uFF0C\u5DF2\u6709\u5185\u5BB9\u7EDD\u4E0D\u8986\u76D6\u3002\n2. \u6839\u636E\u7528\u6237\u58F0\u660E\u4E0E\u73B0\u6709\u7ED3\u6784\u5224\u65AD\u957F\u7BC7/\u77ED\u7BC7\uFF1B\u65E0\u6CD5\u53EF\u9760\u5224\u65AD\u65F6\u8BF7\u6C42\u786E\u8BA4\u3002\n3. \u957F\u7BC7\u6309\u9700\u5EFA\u7ACB \u6B63\u6587/\u3001\u8BBE\u5B9A/\u3001\u5927\u7EB2/\u3002\u521D\u59CB\u5316\u3001\u5F00\u4E66\u3001\u5927\u7EB2\u548C\u7EC6\u7EB2\u9636\u6BB5\u90FD\u4E0D\u5EFA \u8FFD\u8E2A/\uFF0C\n \u4E5F\u4E0D\u5199 \u8FFD\u8E2A/_tracking-state.json\uFF1A\u8FFD\u8E2A\u5728\u7B2C\u4E00\u7AE0\u6B63\u6587\u52A8\u7B14\u524D\uFF0C\u7531 story-long-write\n \u5355\u7AE0\u6D41\u7A0B\u7528\u5B83\u7684 scripts/tracking_commit.py init \u521D\u59CB\u5316\uFF08\u4E8B\u52A1 JSON \u653E\u4E66\u76EE\u5F55\n .story/work/\uFF0Ccheck \u901A\u8FC7\u540E\u5220\u6389\uFF09\uFF0C\u4E4B\u540E\u6BCF\u7AE0\u7531\u811A\u672C\u63D0\u4EA4\u3002_tracking-state.json \u4E0E\n \u4E0A\u4E0B\u6587.md \u7B49\u6D3E\u751F Tracking \u89C6\u56FE\u53EA\u7531\u811A\u672C\u751F\u6210\uFF0C\u7EDD\u4E0D\u624B\u6539\u3002\n \u7B2C\u4E00\u7AE0\u6B63\u6587\u843D\u76D8\u524D\u5FC5\u987B\u6709\u5BF9\u5E94\u7EC6\u7EB2\u3002\u77ED\u7BC7\u4FDD\u6301\u8F7B\u91CF\u7ED3\u6784\uFF0C\u4E0D\u5F3A\u52A0\u957F\u7BC7 Tracking\u3002\n4. \u5DF2\u6709\u6B63\u6587\u5374\u6CA1\u6709 \u8FFD\u8E2A/_tracking-state.json \u65F6\uFF0C\u4E0D\u81EA\u884C\u8865\u5EFA\u8FFD\u8E2A\u6587\u4EF6\uFF1A\u5DF2\u6709\u65E7 \u8FFD\u8E2A/\n \u7684\u662F\u65E7\u8FFD\u8E2A\u7ED3\u6784\uFF0C\u5EFA\u8BAE\u8D70 story-import \u7684\u300C\u65E7\u8FFD\u8E2A\u9879\u76EE\u8FC1\u79FB\u300D\uFF1B\u6CA1\u6709 \u8FFD\u8E2A/ \u7684\u65E2\u6709\u4E66\u7A3F\n \u5EFA\u8BAE\u7528 story-import \u5BFC\u5165\u3002\n5. \u9700\u8981\u67B6\u6784\u3001\u89D2\u8272\u6216\u7814\u7A76\u5DE5\u4F5C\u65F6\uFF0C\u901A\u8FC7 oh_story_role \u8C03\u7528\u5DF2\u6253\u5305 Role\uFF1B\u4E0D\u8981\u68C0\u67E5\u6216\n \u751F\u6210 .claude\u3001.codex\u3001.opencode\u3001.agents\u3001.zcode\u3001AGENTS.md \u6216 .story-deployed\u3002\n6. \u7ED9\u4F5C\u8005\u7684\u62A5\u544A\u6309\u8FD9\u4E2A\u987A\u5E8F\u5199\uFF1A\u5148\u5199\u300C\u73B0\u5728\u53EF\u4EE5\u505A\u4EC0\u4E48\u300D\uFF0C\u7528\u5199\u4E66\u7684\u8BDD\u5217\u771F\u6B63\u53EF\u7528\u7684\u4E8B\n \uFF08\u5982\u300C\u53EF\u4EE5\u5F00\u65B0\u4E66\u3001\u7EED\u5199\uFF1A\u8BF4 /story-long-write\u300D\uFF09\uFF1B\u518D\u5199\u300C\u4F60\u8FD8\u9700\u8981\u505A\u7684\u4E8B\u300D\uFF0C\u9010\u6761\n \u53EF\u7167\u505A\uFF08\u542B\u9700\u8981\u4F5C\u8005\u786E\u8BA4\u7684\u957F\u7BC7/\u77ED\u7BC7\u5224\u65AD\uFF09\uFF0C\u6CA1\u6709\u5C31\u5199\u300C\u65E0\u9700\u5176\u4ED6\u64CD\u4F5C\u300D\u3002\u8FD9\u4E24\u6BB5\u4E0D\u51FA\u73B0\n \u811A\u672C\u540D\u3001\u5B57\u6BB5\u540D\u3001\u72B6\u6001\u540D\u6216\u6587\u4EF6\u8DEF\u5F84\uFF1B\u6700\u540E\u624D\u7B80\u77ED\u5217\u51FA\u521B\u5EFA\u548C\u4FDD\u7559\u4E86\u54EA\u4E9B\u6587\u4EF6\u3002\n \u4E0D\u8981\u914D\u7F6E\u6A21\u578B\u3001\u6743\u9650\u3001Hooks \u6216 Session\u3002\n\n\u9898\u6750\u3001\u89D2\u8272\u3001\u8282\u594F\u3001\u51B2\u7A81\u3001\u5F00\u7BC7\u548C\u5199\u4F5C\u65B9\u6CD5\u8D44\u6599\u4F4D\u4E8E references/agent-references/\uFF1B\n\u53EA\u52A0\u8F7D\u5F53\u524D\u4EFB\u52A1\u9700\u8981\u7684\u6587\u4EF6\u3002`,\n \"browser-cdp\": `# browser-cdp \u2014 DSH \u6D4F\u89C8\u5668\u80FD\u529B\u9002\u914D\n\n\u672C Skill \u4E0D\u542F\u52A8 Chrome\u3001CDP \u7AEF\u53E3\u3001\u72EC\u7ACB\u6D4F\u89C8\u5668 Host \u6216 setup-cdp-chrome.js\u3002\n\u4EC5\u4F7F\u7528\u5F53\u524D DSH Preset \u5DF2\u66B4\u9732\u7684 web_search\u3001web_fetch \u6216\u6D4F\u89C8\u5668\u5DE5\u5177\u5B8C\u6210\u7F51\u9875\u8BFB\u53D6\u3001\n\u699C\u5355\u91C7\u96C6\u548C\u8D44\u6599\u6838\u9A8C\u3002\u4FDD\u6301\u4EE5\u4E0B\u539F\u5219\uFF1A\n\n1. \u4F18\u5148\u4F7F\u7528\u7ED3\u6784\u5316\u641C\u7D22/\u6293\u53D6\u5DE5\u5177\uFF1B\u9700\u8981\u767B\u5F55\u6001\u6216\u4EA4\u4E92\u9875\u9762\u65F6\u624D\u4F7F\u7528\u53EF\u89C1\u6D4F\u89C8\u5668\u80FD\u529B\u3002\n2. \u5C0A\u91CD\u7AD9\u70B9\u6761\u6B3E\u3001\u8BBF\u95EE\u9891\u7387\u4E0E\u7528\u6237\u6388\u6743\uFF1B\u4E0D\u7ED5\u8FC7\u9A8C\u8BC1\u7801\u3001\u4ED8\u8D39\u5899\u6216\u8BBF\u95EE\u63A7\u5236\u3002\n3. \u8BB0\u5F55\u6765\u6E90 URL\u3001\u91C7\u96C6\u65F6\u95F4\u3001\u5931\u8D25\u9879\u548C\u6570\u636E\u8D28\u91CF\uFF0C\u4E0D\u628A\u63A8\u65AD\u5199\u6210\u9875\u9762\u4E8B\u5B9E\u3002\n4. \u5F53\u524D Preset \u6CA1\u6709\u517C\u5BB9\u80FD\u529B\u65F6\uFF0C\u8BF4\u660E\u7F3A\u5931\u80FD\u529B\u548C\u53EF\u884C\u7684\u624B\u5DE5\u6B65\u9AA4\uFF0C\u4E0D\u53E6\u8D77\u8FD0\u884C\u65F6\u3002`,\n \"story-long-scan\": `# story-long-scan \u2014 DSH \u539F\u751F\u957F\u7BC7\u626B\u699C\n\n\u57FA\u4E8E\u53EF\u6838\u9A8C\u6837\u672C\u8BC6\u522B\u957F\u7BC7\u7F51\u6587\u8D8B\u52BF\uFF0C\u4E0D\u8FD0\u884C\u6253\u5305\u811A\u672C\u3001\u4E0D\u63D0\u53D6\u767B\u5F55\u51ED\u636E\uFF0C\u4E5F\u4E0D\u7ED5\u8FC7\u9A8C\u8BC1\u7801\u3001\n\u8BBF\u95EE\u63A7\u5236\u6216\u7AD9\u70B9\u9650\u5236\u3002\n\n1. \u660E\u786E\u5E73\u53F0\u3001\u9891\u9053\u548C\u9898\u6750\u65B9\u5411\uFF1B\u53EA\u6709\u7B54\u6848\u4F1A\u6539\u53D8\u91C7\u6837\u8303\u56F4\u65F6\u624D\u95EE\u4E00\u4E2A\u95EE\u9898\u3002\n2. \u6570\u636E\u6765\u6E90\u4F9D\u6B21\u4E3A\uFF1A\u7528\u6237\u63D0\u4F9B\u7684\u6570\u636E\u6216\u94FE\u63A5\u3001\u5F53\u524D DSH Preset \u53EF\u89C1\u7684\u7F51\u9875\u5DE5\u5177\u3001\n references/genre-trends.md \u4E2D\u7684\u5386\u53F2\u8D8B\u52BF\u3002\u65E0\u6CD5\u83B7\u53D6\u5B9E\u65F6\u6570\u636E\u65F6\u5FC5\u987B\u660E\u786E\u6807\u4E3A\u5386\u53F2\u5047\u8BBE\u3002\n3. \u6BCF\u4E2A\u6837\u672C\u8BB0\u5F55\u6765\u6E90 URL\u3001\u91C7\u96C6\u65E5\u671F\u3001\u699C\u5355\u53E3\u5F84\u3001\u6709\u6548\u6761\u76EE\u6570\u3001\u7F3A\u5931\u5B57\u6BB5\u548C\u5F02\u5E38\u9879\uFF1B\n \u4E0D\u628A\u641C\u7D22\u6458\u8981\u3001\u63A8\u65AD\u6216\u8FC7\u671F\u7F13\u5B58\u5199\u6210\u9875\u9762\u4E8B\u5B9E\u3002\n4. \u6309\u9898\u6750\u5206\u5E03\u3001\u65B0\u9898\u6750\u4FE1\u53F7\u3001\u7ECF\u5178\u9898\u6750\u53D8\u5316\u3001\u7BC7\u5E45\u4E0E\u66F4\u65B0\u3001\u4E66\u540D\u6A21\u5F0F\u3001\u5F00\u5934\u5356\u70B9\u548C\n \u5DEE\u5F02\u5316\u5143\u7D20\u5206\u6790\u3002\u9700\u8981\u51B3\u7B56\u95E8\u7981\u65F6\u4F7F\u7528 references/topic-decision.md\u3002\n5. \u8F93\u51FA\u5E02\u573A\u6982\u51B5\u3001\u9898\u6750\u70ED\u5EA6\u3001\u8BC1\u636E\u4E0E\u53EF\u4FE1\u5EA6\u3001\u98CE\u9669\u3001\u4E09\u9879\u53EF\u6267\u884C\u65B9\u5411\u548C\u4E0B\u6B21\u590D\u626B\u65F6\u95F4\u3002\n6. \u62A5\u544A\u5199\u7ED9\u4F5C\u8005\uFF1A\u8BB2\u5E02\u573A\u7ED3\u8BBA\u548C\u80FD\u5199\u7684\u65B9\u5411\uFF1B\u811A\u672C\u540D\u3001\u547D\u4EE4\u548C\u91C7\u96C6\u72B6\u6001\u7801\u4E0D\u8FDB\u62A5\u544A\u3002\n \u67D0\u4E2A\u699C\u6CA1\u91C7\u5230\uFF0C\u5C31\u7528\u4E00\u53E5\u8BDD\u8BF4\u660E\u300CXX \u699C\u8FD9\u6B21\u6CA1\u62FF\u5230\uFF08\u539F\u56E0\uFF09\uFF0C\u7ED3\u8BBA\u4E0D\u542B\u5B83\u300D\u3002\n7. \u6BCF\u6B21\u626B\u699C\u65B0\u5EFA \u626B\u699C/{YYYYMMDD}/\uFF08\u540C\u65E5\u518D\u626B\u52A0 -2\uFF09\uFF0C\u6837\u672C\u8BB0\u5F55\u5B58\u5728\u8FD9\u91CC\uFF1B\u62A5\u544A\u540C\u65F6\u6309\n references/topic-decision.md \u7684\u6A21\u677F\u5199\u8FDB\u8BE5\u76EE\u5F55\u7684 \u9009\u9898\u51B3\u7B56.md\uFF08\u5E26\u300C\u626B\u699C\u65E5\u671F\u300D\uFF09\uFF0C\n \u4F5C\u4E3A\u300C\u626B\u699C\u7ED3\u8BBA\u300D\u4E00\u8282\uFF0C\u4F5C\u8005\u8981\u9009\u9898\u65F6\u518D\u5199\u300C\u63A8\u8350\u9009\u9898\u300D\u4E00\u8282\u3002story-long-write \u5F00\u4E66\u65F6\n \u4ECE\u8FD9\u4EFD\u6587\u4EF6\u63A5\u4E0A\uFF0C\u6240\u4EE5\u7ED3\u8BBA\u8981\u843D\u76D8\uFF0C\u4E0D\u53EA\u7559\u5728\u5BF9\u8BDD\u91CC\u3002\n\n\u5F53\u524D Preset \u6CA1\u6709\u7F51\u9875\u80FD\u529B\u4E14\u7528\u6237\u4E5F\u672A\u63D0\u4F9B\u6837\u672C\u65F6\uFF0C\u4F7F\u7528\u5185\u7F6E\u53C2\u8003\u5B8C\u6210\u65B9\u6CD5\u8BBA\u5206\u6790\uFF0C\n\u5E76\u5217\u51FA\u4ECD\u9700\u6838\u9A8C\u7684\u699C\u5355\uFF1B\u4E0D\u8981\u542F\u52A8 CDP\u3001\u72EC\u7ACB\u6D4F\u89C8\u5668\u6216\u5E76\u884C\u8FD0\u884C\u65F6\u3002`,\n \"story-short-scan\": `# story-short-scan \u2014 DSH \u539F\u751F\u77ED\u7BC7\u626B\u699C\n\n\u57FA\u4E8E\u53EF\u6838\u9A8C\u6837\u672C\u8BC6\u522B\u77ED\u7BC7\u5E02\u573A\u7684\u60C5\u7EEA\u3001\u9898\u6750\u4E0E\u4F20\u64AD\u4FE1\u53F7\uFF0C\u4E0D\u8FD0\u884C\u6253\u5305\u811A\u672C\u3001\u4E0D\u8BFB\u53D6 Cookie\n\u6216 token\uFF0C\u4E5F\u4E0D\u7ED5\u8FC7\u9A8C\u8BC1\u7801\u3001\u767B\u5F55\u6216\u8BBF\u95EE\u63A7\u5236\u3002\n\n1. \u660E\u786E\u5E73\u53F0\u4E0E\u65B9\u5411\uFF1B\u53EA\u6709\u7B54\u6848\u4F1A\u6539\u53D8\u91C7\u6837\u8303\u56F4\u65F6\u624D\u95EE\u4E00\u4E2A\u95EE\u9898\u3002\n2. \u6570\u636E\u6765\u6E90\u4F9D\u6B21\u4E3A\uFF1A\u7528\u6237\u63D0\u4F9B\u7684\u6570\u636E\u6216\u94FE\u63A5\u3001\u5F53\u524D DSH Preset \u53EF\u89C1\u7684\u7F51\u9875\u5DE5\u5177\u3001\n references/real-market-data.md \u4E2D\u7684\u5386\u53F2\u8D44\u6599\u3002\u65E0\u6CD5\u8054\u7F51\u65F6\u5FC5\u987B\u628A\u7ED3\u8BBA\u6807\u4E3A\u5019\u9009\u5047\u8BBE\u3002\n3. \u8BB0\u5F55\u6765\u6E90 URL\u3001\u91C7\u96C6\u65E5\u671F\u3001\u699C\u5355\u53E3\u5F84\u3001\u6709\u6548\u6837\u672C\u6570\u3001\u7F3A\u5931\u5B57\u6BB5\u548C\u5F02\u5E38\u9879\u3002\n4. \u5206\u6790\u60C5\u7EEA\u7C7B\u578B\u3001\u9898\u6750\u70ED\u70B9\u3001\u7BC7\u5E45\u3001\u5F00\u5934\u3001\u7ED3\u5C3E\u3001\u6807\u9898\u3001\u4EBA\u8BBE\u4E0E\u4F20\u64AD\u89E6\u53D1\u70B9\uFF1B\n \u7ED9\u6BCF\u4E2A\u8D8B\u52BF\u6807\u6CE8\u8BC1\u636E\u5F3A\u5EA6\u3001\u9971\u548C\u98CE\u9669\u548C\u6709\u6548\u671F\u3002\n5. \u8F93\u51FA\u5E02\u573A\u6982\u51B5\uFF08\u626B\u699C\u65F6\u95F4\u3001\u6838\u5FC3\u53D1\u73B0\u548C\u53EF\u4FE1\u5EA6\uFF1A\u6837\u672C\u591A\u5C11\u7BC7\u3001\u6765\u81EA\u54EA\u51E0\u4E2A\u699C\uFF0C\u5E76\u5EFA\u8BAE\n \u54EA\u5929\u524D\u540E\u518D\u626B\u4E00\u6B21\uFF09\u3001\u60C5\u7EEA\u70ED\u5EA6\u3001\u9898\u6750\u70ED\u70B9\u3001\u5173\u952E\u6570\u636E\u3001\u98CE\u53E3\u9884\u8B66\u3001\u4E09\u9879\u53EF\u5199\u65B9\u5411\u3002\n6. \u62A5\u544A\u5199\u7ED9\u4F5C\u8005\uFF1A\u8BB2\u5E02\u573A\u7ED3\u8BBA\u548C\u80FD\u5199\u7684\u65B9\u5411\uFF1B\u811A\u672C\u540D\u3001\u547D\u4EE4\u548C SKIP \u8FD9\u7C7B\u91C7\u96C6\u72B6\u6001\u4E0D\u8FDB\u62A5\u544A\u3002\n \u67D0\u4E2A\u5E73\u53F0\u6CA1\u91C7\u5230\uFF0C\u5C31\u7528\u4E00\u53E5\u8BDD\u8BF4\u660E\u300CXX \u8FD9\u6B21\u6CA1\u62FF\u5230\uFF08\u539F\u56E0\uFF09\uFF0C\u7ED3\u8BBA\u4E0D\u542B\u5B83\u300D\u3002\n7. \u6BCF\u6B21\u626B\u699C\u65B0\u5EFA \u626B\u699C/{YYYYMMDD}/\uFF08\u540C\u65E5\u518D\u626B\u52A0 -2\uFF09\uFF0C\u6837\u672C\u8BB0\u5F55\u5B58\u5728\u8FD9\u91CC\uFF1B\u62A5\u544A\u540C\u65F6\u6309\n references/topic-match.md \u7684\u6A21\u677F\u5199\u8FDB\u8BE5\u76EE\u5F55\u7684 \u77ED\u7BC7\u626B\u699C\u7ED3\u8BBA.md\uFF0C\u4F5C\u4E3A\u300C\u626B\u699C\u7ED3\u8BBA\u300D\n \u4E00\u8282\uFF0C\u7ED3\u5408\u9879\u76EE\u6761\u4EF6\u518D\u5199\u300C\u9009\u9898\u5339\u914D\u300D\u4E00\u8282\u3002story-short-write \u4ECE\u8FD9\u4EFD\u6587\u4EF6\u63A5\u4E0A\u9009\u9898\u3002\n \u4F5C\u8005\u81EA\u5DF1\u7ED9\u699C\u5355\u65F6\uFF0C\u6309 references/manual-rank-input.md \u7684\u683C\u5F0F\u6574\u7406\u3002\n\n\u5F53\u524D Preset \u6CA1\u6709\u7F51\u9875\u80FD\u529B\u4E14\u7528\u6237\u4E5F\u672A\u63D0\u4F9B\u6837\u672C\u65F6\uFF0C\u53EA\u505A\u5386\u53F2\u8D44\u6599\u5206\u6790\u5E76\u5217\u51FA\u9A8C\u8BC1\u52A8\u4F5C\uFF1B\n\u4E0D\u8981\u542F\u52A8 CDP\u3001\u72EC\u7ACB\u6D4F\u89C8\u5668\u6216\u5E76\u884C\u8FD0\u884C\u65F6\u3002`\n};\n\ninterface ParsedSkill {\n readonly name: string;\n readonly description: string;\n readonly content: string;\n readonly userInvocable: boolean;\n}\n\nfunction frontmatterValue(frontmatter: string, key: string): string | undefined {\n const lines = frontmatter.split(/\\r?\\n/u);\n const index = lines.findIndex((line) => new RegExp(`^${key}:\\\\s*`, \"u\").test(line));\n if (index < 0) return undefined;\n const raw = lines[index]?.replace(new RegExp(`^${key}:\\\\s*`, \"u\"), \"\").trim();\n if (raw === undefined) return undefined;\n if (raw === \">\" || raw === \"|\" || raw === \">-\" || raw === \"|-\") {\n const values: string[] = [];\n for (const line of lines.slice(index + 1)) {\n if (/^\\S/u.test(line)) break;\n values.push(line.trim());\n }\n return (raw.startsWith(\">\") ? values.join(\" \") : values.join(\"\\n\")).trim();\n }\n if (raw.startsWith(\"\\\"\") && raw.endsWith(\"\\\"\")) {\n try { return JSON.parse(raw) as string; }\n catch { return raw.slice(1, -1); }\n }\n return raw.replace(/^['\"]|['\"]$/gu, \"\");\n}\n\nexport function parseBundledSkill(source: string): ParsedSkill {\n const match = /^---\\r?\\n([\\s\\S]*?)\\r?\\n---\\r?\\n?/u.exec(source);\n if (match?.[1] === undefined) throw new Error(\"Bundled skill is missing YAML frontmatter.\");\n const name = frontmatterValue(match[1], \"name\");\n const description = frontmatterValue(match[1], \"description\");\n if (!name || !/^[a-z0-9]+(?:-[a-z0-9]+)*$/u.test(name)) throw new Error(\"Bundled skill has an invalid name.\");\n if (!description) throw new Error(`Bundled skill \"${name}\" has no description.`);\n return {\n name,\n description,\n content: source.slice(match[0].length),\n userInvocable: frontmatterValue(match[1], \"user-invocable\") !== \"false\"\n };\n}\n\nexport function dshSkillContent(name: string, content: string): string {\n const override = DSH_SKILL_OVERRIDES[name];\n const native = DSH_NATIVE_SKILLS[name];\n return `${DSH_SKILL_BRIDGE}${override === undefined ? \"\" : `\\n<skill-specific-dsh-override>${override}</skill-specific-dsh-override>`}\\n\\n${native ?? content}`;\n}\n\nexport function defaultBundledSkillRoot(): string {\n const current = dirname(fileURLToPath(import.meta.url));\n return basename(current) === \"src\"\n ? resolve(current, \"../../knowledge/oh-story/skills\")\n : resolve(current, \"oh-story/skills\");\n}\n\nexport function defaultDramaSkillRoot(): string {\n const current = dirname(fileURLToPath(import.meta.url));\n return basename(current) === \"src\"\n ? resolve(current, \"../../knowledge/drama/skills\")\n : resolve(current, \"drama/skills\");\n}\n\nexport function defaultNovelToGameSkillRoot(): string {\n const current = dirname(fileURLToPath(import.meta.url));\n return basename(current) === \"src\"\n ? resolve(current, \"../../knowledge/novel-to-game/skills\")\n : resolve(current, \"novel-to-game/skills\");\n}\n\nfunction createBundledSkillProvider(\n providerName: string,\n skillRoot: string,\n content: (name: string, source: string) => string\n): SkillProvider {\n const root = resolve(skillRoot);\n return {\n name: providerName,\n async list(): Promise<readonly SkillCandidate[]> {\n const directories = (await readdir(root, { withFileTypes: true }))\n .filter((entry) => entry.isDirectory())\n .map((entry) => entry.name)\n .sort();\n return Promise.all(directories.map(async (directory): Promise<SkillCandidate> => {\n const path = join(root, directory, \"SKILL.md\");\n const parsed = parseBundledSkill(await readFile(path, \"utf8\"));\n if (parsed.name !== directory) throw new Error(`Bundled skill directory \"${directory}\" does not match name \"${parsed.name}\".`);\n return {\n name: parsed.name,\n description: parsed.description,\n invocation: { modelInvocable: true, userInvocable: parsed.userInvocable },\n provider: providerName,\n source: \"bundled\",\n resourceBase: { kind: \"directory\", path: join(root, directory) },\n rank: BUNDLED_SKILL_RANK,\n locator: pathToFileURL(path),\n path\n };\n }));\n },\n async get(candidate): Promise<SkillDefinition | undefined> {\n if (candidate.provider !== providerName || typeof candidate.path !== \"string\") return undefined;\n const path = resolve(candidate.path);\n const relativePath = relative(root, path);\n if (relativePath === \"\" || relativePath.startsWith(\"..\") || isAbsolute(relativePath)) {\n throw new Error(\"Bundled skill locator escaped the packaged skill root.\");\n }\n const parsed = parseBundledSkill(await readFile(path, \"utf8\"));\n if (parsed.name !== candidate.name) return undefined;\n return {\n name: parsed.name,\n description: parsed.description,\n invocation: { modelInvocable: true, userInvocable: parsed.userInvocable },\n provider: providerName,\n source: \"bundled\",\n resourceBase: { kind: \"directory\", path: join(root, parsed.name) },\n path,\n content: content(parsed.name, parsed.content)\n };\n }\n };\n}\n\nexport function createOhStorySkillProvider(skillRoot = defaultBundledSkillRoot()): SkillProvider {\n return createBundledSkillProvider(STORY_PROVIDER_NAME, skillRoot, dshSkillContent);\n}\n\nexport function dshDramaSkillContent(name: string, content: string, skillRoot = defaultDramaSkillRoot()): string {\n const entry = DSH_DRAMA_OVERRIDES[name];\n // Resolved per read, not at import: the config path follows the environment\n // the host actually runs with, and matches what /oh-story/drama-preflight reports.\n const override = typeof entry === \"function\" ? entry(skillRoot) : entry;\n return `${DSH_DRAMA_BRIDGE}${override === undefined ? \"\" : `\\n<skill-specific-dsh-override>${override}</skill-specific-dsh-override>`}\\n\\n${content}`;\n}\n\nexport function createDramaSkillProvider(skillRoot = defaultDramaSkillRoot()): SkillProvider {\n return createBundledSkillProvider(DRAMA_PROVIDER_NAME, skillRoot, (name, content) => dshDramaSkillContent(name, content, skillRoot));\n}\n\nexport function dshNovelToGameSkillContent(_name: string, content: string): string {\n return `${DSH_GAME_BRIDGE}\\n\\n${content}`;\n}\n\nexport function createNovelToGameSkillProvider(skillRoot = defaultNovelToGameSkillRoot()): SkillProvider {\n return createBundledSkillProvider(GAME_PROVIDER_NAME, skillRoot, dshNovelToGameSkillContent);\n}\n\nexport function defaultVideoRecapSkillRoot(): string {\n const current = dirname(fileURLToPath(import.meta.url));\n return basename(current) === \"src\"\n ? resolve(current, \"../../knowledge/video-recap/skills\")\n : resolve(current, \"video-recap/skills\");\n}\n\nexport function dshVideoRecapSkillContent(_name: string, content: string): string {\n return `${DSH_VIDEO_BRIDGE}\\n\\n${content}`;\n}\n\nexport function createVideoRecapSkillProvider(skillRoot = defaultVideoRecapSkillRoot()): SkillProvider {\n return createBundledSkillProvider(VIDEO_PROVIDER_NAME, skillRoot, dshVideoRecapSkillContent);\n}\n", "import { createHash } from \"node:crypto\";\nimport { access, lstat, mkdir, rename, writeFile } from \"node:fs/promises\";\nimport { tmpdir } from \"node:os\";\nimport { dirname, join, resolve } from \"node:path\";\n\n/**\n * Drama Skills generates no media by itself and neither does DeepSeek: every\n * image, video, speech, or music result comes from a provider adapter that\n * `short-drama-produce` runs through `production_tool.py run --adapter-config`.\n * Upstream deliberately leaves that config file and its credentials outside\n * every project. This module names the bundled adapters (five as of Drama\n * Skills 0.7.1, one per `provider_adapters.py` choice), registers them for the\n * current DSH host so the Agent has a file to pass, and reports which host\n * environment variables are present \u2014 never their values.\n */\n/** Upstream job modalities with a bundled adapter; `tts` is spoken dialogue (MiniMax Speech). */\nexport type DramaAdapterModality = \"image\" | \"video\" | \"tts\" | \"music\";\n\nexport interface DramaAdapterSpec {\n /** Adapter id used both in the config file and in a job's `adapter` field. */\n readonly name: string;\n readonly label: string;\n readonly modality: DramaAdapterModality;\n /** Host environment variables the bundled adapter refuses to run without. */\n readonly requiredEnv: readonly string[];\n readonly optionalEnv: readonly string[];\n readonly timeoutSeconds: number;\n /** Provider reference shipped with the Skill, relative to the drama skill root. */\n readonly reference: string;\n}\n\nexport interface DramaAdapterStatus {\n readonly name: string;\n readonly label: string;\n readonly modality: DramaAdapterModality;\n readonly configured: boolean;\n readonly missing: readonly string[];\n}\n\nexport interface DramaAdapterConfigLocation {\n readonly path: string;\n /** True when the plugin writes the file; false when the creator points at their own. */\n readonly generated: boolean;\n}\n\n/** Point at a creator-owned adapter config instead of the generated one. */\nexport const DRAMA_ADAPTER_CONFIG_ENV = \"OH_STORY_DRAMA_ADAPTER_CONFIG\";\n\nconst PROVIDER_SCRIPT = \"short-drama-produce/scripts/provider_adapters.py\";\n\nexport const DRAMA_ADAPTERS: readonly DramaAdapterSpec[] = [\n {\n name: \"gpt-image-2\",\n label: \"GPT Image 2\",\n modality: \"image\",\n requiredEnv: [\"OPENAI_API_KEY\"],\n optionalEnv: [\"OPENAI_BASE_URL\"],\n timeoutSeconds: 600,\n reference: \"short-drama-produce/references/providers/gpt-image-2.md\"\n },\n {\n name: \"seedance\",\n label: \"Seedance\",\n modality: \"video\",\n requiredEnv: [\"ARK_API_KEY\", \"SEEDANCE_MODEL\"],\n optionalEnv: [\"SEEDANCE_BASE_URL\", \"SEEDANCE_ALLOWED_RATIOS\", \"SEEDANCE_MIN_DURATION\", \"SEEDANCE_MAX_DURATION\"],\n timeoutSeconds: 3_600,\n reference: \"short-drama-produce/references/providers/seedance.md\"\n },\n {\n name: \"minimax-h3\",\n label: \"MiniMax H3\",\n modality: \"video\",\n // Every H3 job carries an integer duration, and the adapter refuses it without this range.\n requiredEnv: [\"MINIMAX_API_KEY\", \"MINIMAX_VIDEO_MODEL\", \"MINIMAX_VIDEO_RESOLUTIONS\", \"MINIMAX_VIDEO_MIN_DURATION\", \"MINIMAX_VIDEO_MAX_DURATION\"],\n optionalEnv: [\"MINIMAX_VIDEO_BASE_URL\", \"MINIMAX_VIDEO_RATIOS\"],\n timeoutSeconds: 3_600,\n reference: \"short-drama-produce/references/providers/minimax-h3-video.md\"\n },\n {\n name: \"minimax-music\",\n label: \"MiniMax Music\",\n modality: \"music\",\n requiredEnv: [\"MINIMAX_API_KEY\"],\n optionalEnv: [\"MINIMAX_BASE_URL\"],\n timeoutSeconds: 600,\n reference: \"short-drama-produce/references/providers/minimax-music.md\"\n },\n {\n name: \"minimax-speech\",\n label: \"MiniMax Speech\",\n modality: \"tts\",\n requiredEnv: [\"MINIMAX_API_KEY\"],\n optionalEnv: [\"MINIMAX_BASE_URL\"],\n timeoutSeconds: 600,\n reference: \"short-drama-produce/references/providers/minimax-speech.md\"\n }\n];\n\n/** Directory owned by this user: `/tmp` is world-writable on Linux, so the name carries the uid. */\nfunction generatedDirectory(temporaryRoot: string): string {\n const uid = process.getuid?.();\n return join(temporaryRoot, uid === undefined ? \"oh-story-dsh\" : `oh-story-dsh-${String(uid)}`);\n}\n\n/**\n * The generated file is keyed by the skill root so two DSH profiles running\n * different plugin installs never overwrite each other's registration.\n */\nexport function dramaAdapterConfigPath(skillRoot: string, env: NodeJS.ProcessEnv = process.env, temporaryRoot = tmpdir()): DramaAdapterConfigLocation {\n const custom = env[DRAMA_ADAPTER_CONFIG_ENV] ?? \"\";\n if (custom !== \"\") return { path: resolve(custom), generated: false };\n const key = createHash(\"sha256\").update(resolve(skillRoot)).digest(\"hex\").slice(0, 12);\n return { path: join(generatedDirectory(temporaryRoot), `drama-adapters-${key}.json`), generated: true };\n}\n\n/**\n * The file's content becomes an argv that `production_tool.py` executes, so it\n * is written only into a directory this process owns: a pre-existing directory\n * that belongs to someone else, or a symlink, is refused rather than reused.\n */\nasync function privateDirectory(path: string): Promise<boolean> {\n await mkdir(path, { recursive: true, mode: 0o700 });\n const info = await lstat(path);\n if (!info.isDirectory()) return false;\n const uid = process.getuid?.();\n return uid === undefined || info.uid === uid;\n}\n\n/** The upstream adapter-config document: argv commands and timeouts only, never credentials. */\nexport function dramaAdapterConfigDocument(skillRoot: string, python = \"python3\"): {\n readonly adapters: Record<string, { readonly command: readonly string[]; readonly timeout_seconds: number }>;\n} {\n const script = resolve(skillRoot, PROVIDER_SCRIPT);\n const adapters: Record<string, { readonly command: readonly string[]; readonly timeout_seconds: number }> = {};\n for (const adapter of DRAMA_ADAPTERS) {\n adapters[adapter.name] = { command: [python, script, adapter.name], timeout_seconds: adapter.timeoutSeconds };\n }\n return { adapters };\n}\n\n/**\n * Register the bundled adapters for this host. A creator-owned config is left\n * untouched and only checked for existence.\n */\nexport async function ensureDramaAdapterConfig(\n skillRoot: string,\n options: { readonly python?: string; readonly env?: NodeJS.ProcessEnv; readonly temporaryRoot?: string } = {}\n): Promise<DramaAdapterConfigLocation & { readonly ok: boolean }> {\n const location = dramaAdapterConfigPath(skillRoot, options.env ?? process.env, options.temporaryRoot ?? tmpdir());\n if (!location.generated) {\n return { ...location, ok: await access(location.path).then(() => true, () => false) };\n }\n try {\n if (!(await privateDirectory(dirname(location.path)))) return { ...location, ok: false };\n const existing = await lstat(location.path).catch(() => undefined);\n if (existing !== undefined && !existing.isFile()) return { ...location, ok: false };\n // Temp file + rename: a reader never sees a truncated document.\n const staging = `${location.path}.${String(process.pid)}.tmp`;\n await writeFile(staging, `${JSON.stringify(dramaAdapterConfigDocument(skillRoot, options.python ?? \"python3\"), null, 2)}\\n`, { encoding: \"utf8\", mode: 0o600 });\n await rename(staging, location.path);\n return { ...location, ok: true };\n } catch {\n return { ...location, ok: false };\n }\n}\n\n/** Presence only: a variable counts as configured when it is set and non-empty. */\nexport function dramaAdapterStatuses(env: NodeJS.ProcessEnv = process.env): DramaAdapterStatus[] {\n return DRAMA_ADAPTERS.map((adapter) => {\n const missing = adapter.requiredEnv.filter((name) => (env[name] ?? \"\") === \"\");\n return { name: adapter.name, label: adapter.label, modality: adapter.modality, configured: missing.length === 0, missing };\n });\n}\n\n/** One line per adapter for Skill text: `gpt-image-2 (image: OPENAI_API_KEY)`. */\nexport function dramaAdapterSummary(): string {\n return DRAMA_ADAPTERS.map((adapter) => `${adapter.name} (${adapter.modality}: ${adapter.requiredEnv.join(\" + \")})`).join(\", \");\n}\n", "import { execFile } from \"node:child_process\";\nimport { promisify } from \"node:util\";\n\nconst execFileAsync = promisify(execFile);\n\nexport interface PythonProbe { readonly ok: boolean; readonly version?: string | undefined }\n\nexport async function commandOutput(command: string, args: readonly string[]): Promise<string | undefined> {\n try {\n const { stdout, stderr } = await execFileAsync(command, [...args], { encoding: \"utf8\", timeout: 5_000, maxBuffer: 4 * 1_024 * 1_024 });\n return `${stdout}${stderr}`.trim();\n } catch { return undefined; }\n}\n\n/** Upstream Skills require Python 3.10+. */\nexport function pythonVersion(value: string | undefined): PythonProbe {\n const match = /Python\\s+(\\d+)\\.(\\d+)(?:\\.(\\d+))?/u.exec(value ?? \"\");\n if (match === null) return { ok: false };\n const major = Number(match[1]);\n const minor = Number(match[2]);\n return { ok: major > 3 || (major === 3 && minor >= 10), version: match[0].replace(/^Python\\s+/u, \"\") };\n}\n\n/**\n * The interpreter the host will run upstream scripts with. The first command\n * that meets the version floor wins; an interpreter that answers but is too old\n * is reported only when nothing better exists, so `python3` at 3.9 does not hide\n * `python` at 3.12. The command is written into the adapter config's argv, so\n * this is the same choice everywhere the plugin starts Python.\n */\nexport async function hostPython(probe: (command: string, args: readonly string[]) => Promise<string | undefined> = commandOutput): Promise<{ readonly command: string; readonly probe: PythonProbe }> {\n let fallback: { readonly command: string; readonly probe: PythonProbe } | undefined;\n for (const command of [\"python3\", \"python\"]) {\n const parsed = pythonVersion(await probe(command, [\"--version\"]));\n if (parsed.ok) return { command, probe: parsed };\n if (parsed.version !== undefined) fallback ??= { command, probe: parsed };\n }\n return fallback ?? { command: \"python3\", probe: { ok: false } };\n}\n", "import type { Context } from \"@deepseek-ai/cordis\";\nimport type { FileSystem, FsDirEntry, FsTarget } from \"@deepseek-ai/dsh-fs\";\nimport { boundContextSummary, createUserMessage, type ContextFormed } from \"@deepseek-ai/dsh-llm\";\nimport type {} from \"@deepseek-ai/dsh-session\";\nimport type { PostToolDecision, PreToolDecision, ToolExecution } from \"@deepseek-ai/dsh-tools\";\nimport { observeOhStoryRoleDescriptor, ohStoryRoleOfSession } from \"./role-identity.js\";\n\ndeclare module \"@deepseek-ai/dsh-llm\" {\n interface MessageSourceMap {\n /** DSH 0.1.7 dropped the shared `plugin` kind: each producer declares its own. */\n \"oh-story-post-write\": { kind: \"oh-story-post-write\" } & ContextFormed;\n }\n}\n\nconst MUTATION_TOOLS = new Set([\"write\", \"edit\", \"str_replace_editor\"]);\n\nexport interface StoryMutation {\n readonly root: string;\n /** Workspace-relative path of the mutated \u6B63\u6587 file. */\n readonly path: string;\n readonly chapter?: number;\n}\n\nfunction argumentRecord(args: unknown): Record<string, unknown> | undefined {\n return typeof args === \"object\" && args !== null && !Array.isArray(args) ? args as Record<string, unknown> : undefined;\n}\n\nfunction mutationPath(name: string, args: unknown): string | undefined {\n const record = argumentRecord(args);\n if (!MUTATION_TOOLS.has(name) || record === undefined) return undefined;\n if (name === \"str_replace_editor\") {\n if (!new Set([\"create\", \"str_replace\", \"insert\"]).has(String(record.command))) return undefined;\n return typeof record.path === \"string\" && record.path.trim() !== \"\" ? record.path : undefined;\n }\n return typeof record.file_path === \"string\" && record.file_path.trim() !== \"\" ? record.file_path : undefined;\n}\n\nfunction normalizedRelativePath(path: string): string | undefined {\n const segments: string[] = [];\n for (const part of path.split(\"/\")) {\n if (part === \"\" || part === \".\") continue;\n if (part === \"..\") {\n if (segments.length === 0) return undefined;\n segments.pop();\n } else segments.push(part);\n }\n return segments.join(\"/\");\n}\n\n/**\n * Split a workspace-relative path into the book that owns its \u6B63\u6587/ directory\n * and the file name. The book is \"\" when the workspace root is the book (the\n * DSH single-book layout); upstream imports and multi-book workspaces put it\n * in a subdirectory such as `{\u4E66\u540D}/\u6B63\u6587/`.\n */\nfunction proseLocation(path: string): { readonly book: string; readonly name: string } | undefined {\n const segments = path.split(\"/\");\n if (segments.length < 2) return undefined;\n const index = segments.lastIndexOf(\"\u6B63\u6587\", segments.length - 2);\n if (index < 0) return undefined;\n return { book: segments.slice(0, index).join(\"/\"), name: segments.at(-1) ?? \"\" };\n}\n\nfunction inBook(book: string, path: string): string {\n return book === \"\" ? path : `${book}/${path}`;\n}\n\nfunction lastSegment(path: string): string {\n return path.replaceAll(\"\\\\\", \"/\").split(\"/\").filter((part) => part !== \"\").at(-1) ?? \"\";\n}\n\nexport function detectStoryMutation(name: string, args: unknown, cwd: string | undefined): StoryMutation | undefined {\n const rawPath = mutationPath(name, args);\n if (cwd === undefined || rawPath === undefined) return undefined;\n const root = cwd.replaceAll(\"\\\\\", \"/\").replace(/\\/$/u, \"\");\n const candidate = rawPath.replaceAll(\"\\\\\", \"/\");\n const absolute = candidate.startsWith(\"/\") || /^[a-z]:\\//iu.test(candidate) || /^[a-z][a-z\\d+.-]*:\\/\\//iu.test(candidate);\n const insideRoot = /^[a-z]:\\//iu.test(root)\n ? candidate.toLowerCase().startsWith(`${root.toLowerCase()}/`)\n : candidate.startsWith(`${root}/`);\n if (absolute && !insideRoot) return undefined;\n const normalized = normalizedRelativePath(absolute ? candidate.slice(root.length + 1) : candidate);\n if (normalized === undefined) return undefined;\n const location = proseLocation(normalized);\n if (location === undefined) return undefined;\n const chapterText = /^\u7B2C0*(\\d+)\u7AE0/u.exec(location.name)?.[1];\n return { root, path: normalized, ...(chapterText === undefined ? {} : { chapter: Number(chapterText) }) };\n}\n\ntype StoryFileSystem = Pick<FileSystem, \"resolve\" | \"contains\" | \"stat\" | \"listDir\"> & Partial<Pick<FileSystem, \"readBytes\">>;\n\nasync function storyMutation(exec: ToolExecution, fs: StoryFileSystem): Promise<StoryMutation | undefined> {\n const cwd = exec.agent?.session.header.cwd;\n const path = mutationPath(exec.name, exec.arguments);\n if (cwd === undefined || path === undefined) return undefined;\n try {\n const [rootTarget, mutationTarget] = await Promise.all([\n fs.resolve(cwd, { signal: exec.signal }),\n fs.resolve(path, { cwd, signal: exec.signal })\n ]);\n if (!fs.contains(rootTarget, mutationTarget)) return undefined;\n } catch { return undefined; }\n return detectStoryMutation(exec.name, exec.arguments, cwd);\n}\n\nasync function target(fs: StoryFileSystem, root: string, path: string, signal?: AbortSignal): Promise<FsTarget> {\n return fs.resolve(path, { cwd: root, ...(signal === undefined ? {} : { signal }) });\n}\n\nasync function exists(fs: StoryFileSystem, root: string, path: string, signal?: AbortSignal): Promise<boolean> {\n return target(fs, root, path, signal)\n .then((value) => fs.stat(value, signal))\n .then((info) => info !== undefined, () => false);\n}\n\n/** A long-form book has \u5927\u7EB2/ or \u8FFD\u8E2A/; plain workspaces that merely contain \u6B63\u6587/ stay unguarded. */\nasync function isLongFormBook(fs: StoryFileSystem, root: string, book: string, signal?: AbortSignal): Promise<boolean> {\n return await exists(fs, root, inBook(book, \"\u5927\u7EB2\"), signal) || await exists(fs, root, inBook(book, \"\u8FFD\u8E2A\"), signal);\n}\n\n/** Upstream story_hook_core.js `OUTLINE_MIN_CHARS` (Oh Story 0.8.1). */\nconst OUTLINE_MIN_CHARS = 30;\nconst OUTLINE_READ_LIMIT = 64 * 1024;\n\n/**\n * Upstream `outlineIsEmpty`: after a BOM and each line's leading `#`s, fewer than\n * {@link OUTLINE_MIN_CHARS} characters other than whitespace (full-width space\n * included). A file that cannot be read or is not UTF-8 counts as written, as upstream.\n */\nasync function outlineIsEmpty(fs: StoryFileSystem, outline: FsTarget, signal?: AbortSignal): Promise<boolean> {\n if (fs.readBytes === undefined) return false;\n let text: string;\n try { text = new TextDecoder(\"utf-8\", { fatal: true, ignoreBOM: true }).decode(await fs.readBytes(outline, signal, OUTLINE_READ_LIMIT)); }\n catch { return false; }\n if (text.startsWith(\"\\uFEFF\")) text = text.slice(1);\n const body = text.split(\"\\n\").map((line) => line.replace(/^[ \\t]*#+/u, \"\")).join(\"\");\n return Array.from(body.replace(/[ \\t\\r\\n\\f\\v\\u3000]/gu, \"\")).length < OUTLINE_MIN_CHARS;\n}\n\n/** The chapter's \u7EC6\u7EB2 files; any one with content satisfies the gate, as upstream. */\nasync function chapterOutlines(fs: StoryFileSystem, root: string, book: string, chapter: number, signal?: AbortSignal): Promise<FsDirEntry[]> {\n const entries = await target(fs, root, inBook(book, \"\u5927\u7EB2\"), signal)\n .then((directory) => fs.listDir(directory, signal))\n .catch(() => []);\n return entries.filter((entry) => entry.type === \"file\"\n && Number(/^\u7EC6\u7EB2_\u7B2C0*(\\d+)\u7AE0.*\\.md$/u.exec(entry.name)?.[1]) === chapter)\n .sort((left, right) => (left.name < right.name ? -1 : left.name > right.name ? 1 : 0));\n}\n\nconst TRACKING_STATE = \"\u8FFD\u8E2A/_tracking-state.json\";\n\n/**\n * DSH's explicit import-window marker, relative to the book directory (the\n * workspace root in DSH's single-book layout). The story-import overlay has\n * the model create it before copying chapters and delete it once\n * `tracking_commit.py init` and `check` succeed.\n */\nexport const IMPORT_MARKER = \".story/work/\u5BFC\u5165\u4E2D.md\";\n\nasync function hasTrackingState(fs: StoryFileSystem, root: string, book: string, signal?: AbortSignal): Promise<boolean> {\n return exists(fs, root, inBook(book, TRACKING_STATE), signal);\n}\n\n/**\n * Upstream story-import Phase 3-L creates \u5927\u7EB2/ and \u8FFD\u8E2A/ (Step 1) and copies\n * the manuscript into \u6B63\u6587/ (Step 2) long before it writes \u7EC6\u7EB2 (Step 6) and\n * runs `tracking_commit.py init` (Step 7). Upstream recognises that window by\n * `\u62C6\u6587\u5E93/{basename(\u4E66\u76EE\u5F55)}`; in DSH's single-book layout the book is the\n * workspace root, so that key must equal the workspace folder name and rarely\n * does. DSH therefore also accepts its own marker, {@link IMPORT_MARKER}.\n * Any other `\u62C6\u6587\u5E93/*` entry \u2014 an analysed \u5BF9\u6807 book \u2014 is never a signal.\n */\nasync function hasImportSignal(fs: StoryFileSystem, root: string, book: string, signal?: AbortSignal): Promise<boolean> {\n if (await exists(fs, root, inBook(book, IMPORT_MARKER), signal)) return true;\n const bookName = book === \"\" ? lastSegment(root) : lastSegment(book);\n return bookName !== \"\" && await exists(fs, root, `\u62C6\u6587\u5E93/${bookName}`, signal);\n}\n\n/**\n * Mirrors the outline gate of upstream Oh Story's prose guard\n * (`proseBlockReason`) for books with \u5927\u7EB2/ or \u8FFD\u8E2A/: creating a new\n * `\u6B63\u6587/\u7B2CN\u7AE0*.md` requires a `\u5927\u7EB2/\u7EC6\u7EB2_\u7B2CN\u7AE0*.md` that is not empty, whether or not Tracking\n * exists yet. The one bypass is an import window \u2014 an import signal while the\n * book has no `\u8FFD\u8E2A/_tracking-state.json`. Rewriting an existing chapter is not\n * gated on its outline.\n *\n * It leaves out the rest of proseBlockReason: the Tracking checkpoint (state\n * present and at schema_version 4, \u4E0A\u4E0B\u6587.md at the same state revision, the\n * previous chapter committed), the previous chapter's toxic-phrase debt, the\n * short-story gate that wants \u5C0F\u8282\u5927\u7EB2.md before \u6B63\u6587.md, and shell-write\n * targets (redirection, cp, tee, scripts), which DSH hooks do not see as file\n * mutations \u2014 the story-long-write overlay asks for write/edit instead. It also\n * leaves a workspace with \u6B63\u6587/ but neither \u5927\u7EB2/ nor \u8FFD\u8E2A/ unguarded.\n */\nexport async function validateStoryMutation(\n fs: StoryFileSystem,\n mutation: StoryMutation,\n signal?: AbortSignal\n): Promise<string | undefined> {\n const location = proseLocation(mutation.path);\n if (mutation.chapter === undefined || location === undefined) return undefined;\n const { book } = location;\n if (!(await isLongFormBook(fs, mutation.root, book, signal))) return undefined;\n if (await exists(fs, mutation.root, mutation.path, signal)) return undefined;\n if (!(await hasTrackingState(fs, mutation.root, book, signal)) && await hasImportSignal(fs, mutation.root, book, signal)) {\n return undefined;\n }\n const outlines = await chapterOutlines(fs, mutation.root, book, mutation.chapter, signal);\n const [first] = outlines;\n if (first !== undefined) {\n for (const outline of outlines) if (!(await outlineIsEmpty(fs, outline.target, signal))) return undefined;\n return `Oh Story \u963B\u6B62\u5199\u5165\u7B2C ${String(mutation.chapter)} \u7AE0\uFF1A\u7EC6\u7EB2 ${inBook(book, \"\u5927\u7EB2\")}/${first.name} \u662F\u7A7A\u7684\uFF08\u4E0D\u8BA1 # \u53F7\u548C\u7A7A\u767D\u4E0D\u5230 ${String(OUTLINE_MIN_CHARS)} \u5B57\uFF09\u3002`\n + \"\u5148\u6309 story-long-write \u5355\u7AE0\u6D41\u7A0B\u628A\u7EC6\u7EB2\u5199\u5B8C\u6574\uFF08\u8FD9\u7AE0\u53D1\u751F\u4EC0\u4E48\u3001\u4E3B\u89D2\u505A\u4EC0\u4E48\u9009\u62E9\uFF09\uFF0C\u518D\u5199\u6B63\u6587\u3002\";\n }\n const padded = String(mutation.chapter).padStart(3, \"0\");\n return `Oh Story \u963B\u6B62\u5199\u5165\u7B2C ${String(mutation.chapter)} \u7AE0\uFF1A\u672A\u627E\u5230\u5BF9\u5E94\u7684 ${inBook(book, \"\u5927\u7EB2\")}/\u7EC6\u7EB2_\u7B2C${padded}\u7AE0*.md\u3002`\n + \"\u5148\u6309 story-long-write \u5355\u7AE0\u6D41\u7A0B\u8865\u5EFA\u7EC6\u7EB2\u518D\u5199\u6B63\u6587\u3002\";\n}\n\nexport async function decideStoryMutation(\n exec: ToolExecution,\n next: () => Promise<PreToolDecision>\n): Promise<PreToolDecision> {\n const fs = exec.agent?.ctx.get(\"fs\");\n if (fs === undefined) return next();\n const mutation = await storyMutation(exec, fs);\n if (mutation === undefined) return next();\n const reason = await validateStoryMutation(fs, mutation, exec.signal);\n if (reason !== undefined) return { kind: \"deny\", reason };\n return next();\n}\n\nconst ANALYSIS_INPUT = /^\u8F93\u5165-(RAW|REUSE)-(\\d+)-(\\d+)\\.md$/u;\nconst ANALYSIS_INPUT_RULE = \"\u53EA\u5141\u8BB8\u5199\u8C03\u7528\u65B9\u7ED9\u7684 {\u62C6\u6587\u76EE\u5F55}/_analysis_cache/\u8F93\u5165-{\u6279\u6B21ID}.md\uFF08\u6279\u6B21 ID \u5982 RAW-4-6\uFF09\uFF0C\u4E0D\u5199\u5176\u4ED6\u6587\u4EF6\u3002\";\n\nfunction isFileMutationCall(name: string, args: unknown): boolean {\n if (name === \"write\" || name === \"edit\") return true;\n return name === \"str_replace_editor\" && argumentRecord(args)?.command !== \"view\";\n}\n\nfunction displayParent(path: string): string {\n const index = Math.max(path.lastIndexOf(\"/\"), path.lastIndexOf(\"\\\\\"));\n return index <= 0 ? path.slice(0, index + 1) : path.slice(0, index);\n}\n\nfunction displayName(path: string): string {\n return path.slice(Math.max(path.lastIndexOf(\"/\"), path.lastIndexOf(\"\\\\\")) + 1);\n}\n\nasync function isAnalysisDirectory(fs: StoryFileSystem, directory: string, signal?: AbortSignal): Promise<boolean> {\n return await exists(fs, directory, \"chapter_index.csv\", signal) || await exists(fs, directory, \"_progress.md\", signal);\n}\n\n/**\n * Mirror of upstream's `analysis-input-guard` (story_hook_cli.js): the\n * chapter-extractor may write or edit only\n * `{\u62C6\u6587\u76EE\u5F55}/_analysis_cache/\u8F93\u5165-{RAW|REUSE}-{\u8D77\u7AE0}-{\u6B62\u7AE0}.md`, where the\n * \u62C6\u6587\u76EE\u5F55 holds `chapter_index.csv` or `_progress.md` and lies inside the\n * workspace. The commit script still validates the file's content.\n */\nexport async function validateAnalysisInputWrite(\n fs: StoryFileSystem,\n cwd: string,\n path: string | undefined,\n signal?: AbortSignal\n): Promise<string | undefined> {\n const deny = (shown: string, reasons: readonly string[]): string =>\n `Oh Story \u963B\u6B62 chapter-extractor \u5199\u5165 ${shown}\uFF1A${reasons.join(\"\uFF1B\")}\u3002${ANALYSIS_INPUT_RULE}`;\n if (path === undefined) return deny(\"\uFF08\u672A\u7ED9\u51FA\u8DEF\u5F84\uFF09\", [\"\u5199\u5165\u6CA1\u6709\u7ED9\u51FA\u6587\u4EF6\u8DEF\u5F84\"]);\n let rootTarget: FsTarget;\n let fileTarget: FsTarget;\n try {\n [rootTarget, fileTarget] = await Promise.all([\n fs.resolve(cwd, signal === undefined ? {} : { signal }),\n fs.resolve(path, { cwd, ...(signal === undefined ? {} : { signal }) })\n ]);\n } catch {\n return deny(path, [\"\u8DEF\u5F84\u65E0\u6CD5\u89E3\u6790\"]);\n }\n const reasons: string[] = [];\n const match = ANALYSIS_INPUT.exec(displayName(fileTarget.displayPath));\n if (match === null) reasons.push(\"\u6587\u4EF6\u540D\u5FC5\u987B\u662F \u8F93\u5165-{RAW|REUSE}-{\u8D77\u7AE0}-{\u6B62\u7AE0}.md\");\n else if (Number(match[2]) < 1 || Number(match[3]) < Number(match[2])) reasons.push(\"\u6279\u6B21\u7AE0\u53F7\u8303\u56F4\u65E0\u6548\");\n const cacheDirectory = displayParent(fileTarget.displayPath);\n if (displayName(cacheDirectory) !== \"_analysis_cache\") reasons.push(\"\u53EA\u80FD\u5199\u5728\u62C6\u6587\u76EE\u5F55\u7684 _analysis_cache/ \u4E0B\");\n else if (!(await isAnalysisDirectory(fs, displayParent(cacheDirectory), signal))) {\n reasons.push(\"\u4E0A\u7EA7\u76EE\u5F55\u4E0D\u662F\u62C6\u6587\u76EE\u5F55\uFF08\u7F3A chapter_index.csv \u4E0E _progress.md\uFF09\");\n }\n if (!fs.contains(rootTarget, fileTarget)) reasons.push(\"\u8DEF\u5F84\u5728\u9879\u76EE\u76EE\u5F55\u4E4B\u5916\");\n return reasons.length === 0 ? undefined : deny(path, reasons);\n}\n\n/**\n * Fence file mutations by a chapter-extractor child to its batch input file.\n * The child is identified by the Role DSH recorded in its Session descriptor,\n * so other Roles and the main Agent are unaffected.\n */\nexport async function decideChapterExtractorWrite(\n exec: ToolExecution,\n next: () => Promise<PreToolDecision>\n): Promise<PreToolDecision> {\n if (ohStoryRoleOfSession(exec.agent?.session) !== \"chapter-extractor\" || !isFileMutationCall(exec.name, exec.arguments)) {\n return next();\n }\n const fs = exec.agent?.ctx.get(\"fs\");\n const cwd = exec.agent?.session.header.cwd;\n const reason = fs === undefined || cwd === undefined\n ? `Oh Story \u963B\u6B62 chapter-extractor \u5199\u5165\uFF1A\u65E0\u6CD5\u786E\u8BA4\u9879\u76EE\u76EE\u5F55\u3002${ANALYSIS_INPUT_RULE}`\n : await validateAnalysisInputWrite(fs, cwd, mutationPath(exec.name, exec.arguments), exec.signal);\n return reason === undefined ? next() : { kind: \"deny\", reason };\n}\n\nexport interface PostWriteReminderOptions {\n /** The book has no \u8FFD\u8E2A/_tracking-state.json and no import signal. */\n readonly trackingUninitialized?: boolean;\n}\n\nexport function postWriteReminderText(path: string, options: PostWriteReminderOptions = {}): string {\n return [\n `<oh-story-post-write>\u6B63\u6587 ${path} \u5DF2\u53D8\u66F4\u3002`,\n \"\u6BCF\u6B21\u5199\u5165\u6B63\u6587\u90FD\u4F1A\u51FA\u73B0\u8FD9\u6761\u63D0\u9192\uFF0C\u4E00\u7AE0\u5199\u5230\u4E00\u534A\u65F6\u4E5F\u4F1A\uFF1B\u5B83\u4E0D\u8868\u793A\u672C\u7AE0\u5DF2\u7ECF\u5B8C\u6210\uFF0C\u4E5F\u4E0D\u662F\u4F5C\u8005\u7684\u65B0\u5199\u4F5C\u8981\u6C42\uFF0C\u7EE7\u7EED\u5F53\u524D\u6B65\u9AA4\u5373\u53EF\u3002\",\n ...options.trackingUninitialized === true\n ? [\n \"\u672C\u4E66\u8FD8\u6CA1\u6709 \u8FFD\u8E2A/_tracking-state.json\u3002\u65B0\u4E66\u5199\u7B2C\u4E00\u7AE0\u65F6\uFF0Cdraft \u4E4B\u524D\u5148\u6309 story-long-write workflow-chapter \u5F00\u5934\u7684\u521D\u59CB\u5316\u6B65\u9AA4\u5B8C\u6574\u8BFB\u53D6 references/tracking-initialization.md\uFF0C\u6784\u9020 last_chapter=0 \u7684\u521D\u59CB\u5316\u4E8B\u52A1\u5B58\u4E66\u76EE\u5F55 .story/work/init.json\uFF0C\u8FD0\u884C scripts/tracking_commit.py init\uFF0C\u518D\u8FD0\u884C tracking_commit.py check\uFF0C\u901A\u8FC7\u540E\u5220\u6389 init.json\uFF1B\",\n \"\u4E66\u91CC\u5728\u672C\u7AE0\u4E4B\u524D\u5DF2\u6709\u6B63\u6587\u65F6\u4E0D\u8981\u521D\u59CB\u5316\uFF0C\u505C\u4E0B\u6765\u6539\u8D70 story-import \u7684\u300C\u65E7\u8FFD\u8E2A\u9879\u76EE\u8FC1\u79FB\u300D\u3002\"\n ]\n : [],\n \"\u7B49\u672C\u7AE0\u5199\u5B8C\u6536\u5C3E\u65F6\u518D\u63D0\u4EA4\u8FFD\u8E2A\uFF1A\u65B0\u7AE0\u5148\u7528 story-long-write \u7684 scripts/tracking_commit.py draft \u751F\u6210\u672C\u7AE0\u8349\u7A3F\uFF0C\u586B\u597D\u540E\u6267\u884C scripts/storyctl.py chapter commit\uFF08\u4F5C\u8005\u63A5\u53D7\u5F53\u524D\u957F\u5EA6\u65F6\u7528 chapter accept-current-length\uFF09\uFF1B\",\n \"\u4FEE\u6539\u5DF2\u63D0\u4EA4\u7684\u7AE0\u8282\u6309 workflow-revision \u63D0\u4EA4\u4E00\u6B21 mode=revision \u4E8B\u52A1\uFF1B\u5BFC\u5165\u65E2\u6709\u6B63\u6587\u65F6\u7531 story-import \u5728\u8FC1\u79FB\u540E\u7528 tracking_commit.py init \u7EDF\u4E00\u521D\u59CB\u5316\u3002\",\n \"\u8FFD\u8E2A/_tracking-state.json \u4EE5\u53CA \u4E0A\u4E0B\u6587.md\u3001\u89D2\u8272\u72B6\u6001/\u3001\u4F0F\u7B14.md\u3001\u65F6\u95F4\u7EBF/\u3001\u9010\u7AE0\u8BB0\u5F55/ \u7B49\u6D3E\u751F Tracking \u89C6\u56FE\u53EA\u7531\u8FD9\u4E9B\u811A\u672C\u5199\u5165\uFF0C\u7EDD\u4E0D\u624B\u6539\u3002</oh-story-post-write>\"\n ].join(\"\");\n}\n\n/**\n * Native DSH equivalents of the upstream prose guards. They join DSH's typed\n * tool waterfall, so decisions remain visible in the official approval/tool UI.\n */\nexport function registerOhStoryHooks(context: Context): void {\n context.on(\"session/event\", (session, event) => { observeOhStoryRoleDescriptor(session, event); });\n context.on(\"tools/pre-execute\", decideChapterExtractorWrite);\n context.on(\"tools/pre-execute\", decideStoryMutation);\n\n context.on(\"tools/post-execute\", async (exec, result, next): Promise<PostToolDecision> => {\n const downstream = await next();\n if (result.isError || downstream.kind !== \"accept\") return downstream;\n // Tracking is committed by the main session. oh_story_role children never\n // get the reminder: narrative-writer's Role body forbids writing Tracking.\n if (ohStoryRoleOfSession(exec.agent?.session) !== undefined) return downstream;\n const fs = exec.agent?.ctx.get(\"fs\");\n const mutation = fs === undefined ? undefined : await storyMutation(exec, fs);\n const location = mutation === undefined ? undefined : proseLocation(mutation.path);\n if (fs === undefined || mutation === undefined || location === undefined) return downstream;\n const { root } = mutation;\n const { book } = location;\n if (!(await isLongFormBook(fs, root, book, exec.signal))) return downstream;\n const trackingUninitialized = !(await hasTrackingState(fs, root, book, exec.signal))\n && !(await hasImportSignal(fs, root, book, exec.signal));\n const reminder = createUserMessage({\n source: { kind: \"oh-story-post-write\", form: \"notice\", summary: boundContextSummary(`\u6B63\u6587 ${mutation.path} \u5DF2\u53D8\u66F4`) },\n content: [{ type: \"text\", text: postWriteReminderText(mutation.path, { trackingUninitialized }) }]\n });\n return {\n ...downstream,\n additionalContexts: [...downstream.additionalContexts ?? [], reminder]\n };\n });\n}\n", "import { readFile } from \"node:fs/promises\";\nimport { basename, dirname, join, resolve } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nexport const OH_STORY_ROLE_NAMES = [\n \"chapter-extractor\",\n \"character-designer\",\n \"consistency-checker\",\n \"narrative-writer\",\n \"story-architect\",\n \"story-explorer\",\n \"story-researcher\"\n] as const;\n\nexport type OhStoryRoleName = typeof OH_STORY_ROLE_NAMES[number];\nexport type OhStoryRoleExecution = \"tool-free\" | \"native-tools\";\n\nfunction roleBody(source: string): string {\n const frontmatter = /^---\\r?\\n[\\s\\S]*?\\r?\\n---\\r?\\n?/u.exec(source);\n return source.slice(frontmatter?.[0].length ?? 0).trim();\n}\n\nexport function defaultBundledRoleRoot(): string {\n const current = dirname(fileURLToPath(import.meta.url));\n return basename(current) === \"src\"\n ? resolve(current, \"../../knowledge/oh-story/roles\")\n : resolve(current, \"oh-story/roles\");\n}\n\nexport async function loadBundledRole(\n name: OhStoryRoleName,\n roleRoot = defaultBundledRoleRoot(),\n execution: OhStoryRoleExecution = \"tool-free\"\n): Promise<string> {\n const body = roleBody(await readFile(join(resolve(roleRoot), `${name}.md`), \"utf8\"));\n if (body.length === 0) throw new Error(`Bundled role \"${name}\" is empty.`);\n const integration = execution === \"tool-free\"\n ? [\n \"You are running inside an Oh Story review-required DSH collaboration. The caller supplies every permitted input in the prompt.\",\n \"Do not read or write project files, do not call tools, and do not follow legacy .claude/.codex path or deployment instructions in the upstream role text.\",\n \"Return only the output contract requested by the caller; never claim to have changed the project.\"\n ]\n : [\n \"You are running as a native oh-story-dsh specialist. The current DSH workspace and visible tool set are your complete authority boundary.\",\n \"Never inspect or require legacy .claude/.opencode/.codex agent deployment files; this exact pinned Role is already active.\",\n \"Bundled story-setup references are pinned plugin resources, not project files or project Skills. When the upstream Role marks one mandatory, call oh_story_bundled_reference with the exact story-setup/references/agent-references path, then use only the returned content.\",\n \"If oh_story_bundled_reference or a required bundled reference is unavailable, report the missing reference to the caller. Never call the generic skill tool, fall back to a legacy platform path, or claim that an unread reference was used.\",\n \"Use only the tools actually visible to you. Mutate files only when the caller explicitly requests it and your visible DSH tools permit it; otherwise return findings to the caller.\"\n ];\n return [\n `OH_STORY_DSH_ROLE:${name}`,\n ...integration,\n \"\",\n body\n ].join(\"\\n\");\n}\n", "import type { Session, SessionEvent } from \"@deepseek-ai/dsh-session\";\nimport type {} from \"@deepseek-ai/dsh-subagent\";\nimport { OH_STORY_ROLE_NAMES, type OhStoryRoleName } from \"./role-provider.js\";\n\nconst ROLE_LABEL_PREFIX = \"oh-story:\";\n\n/** The durable creation label oh_story_role gives every child it starts. */\nexport function ohStoryRoleLabel(role: OhStoryRoleName): string {\n return `${ROLE_LABEL_PREFIX}${role}`;\n}\n\nfunction roleFromLabel(label: unknown): OhStoryRoleName | undefined {\n if (typeof label !== \"string\" || !label.startsWith(ROLE_LABEL_PREFIX)) return undefined;\n const name = label.slice(ROLE_LABEL_PREFIX.length);\n return OH_STORY_ROLE_NAMES.find((role) => role === name);\n}\n\n// Keyed by the live Session object: a one-shot child keeps one Session for its\n// whole life, and a WeakMap releases the entry with the child.\nconst roleSessions = new WeakMap<Session, OhStoryRoleName>();\n\n/**\n * Record the Role of a child whose Session DSH has just stamped with its\n * `subagent/descriptor`. The in-process spawn driver appends that event inside\n * the child's first step, before its first model request, so the identity is\n * known before the child can call any tool. The first descriptor is\n * authoritative, as in DSH's own `foldSubagentDescriptor`.\n */\nexport function observeOhStoryRoleDescriptor(session: Session, event: SessionEvent): void {\n if (event.type !== \"subagent/descriptor\" || roleSessions.has(session)) return;\n const role = roleFromLabel((event.data as { readonly label?: unknown }).label);\n if (role !== undefined) roleSessions.set(session, role);\n}\n\n/** Record a Role for a child Session the Role tool started itself. */\nexport function markOhStoryRoleSession(session: Session, role: OhStoryRoleName): void {\n if (!roleSessions.has(session)) roleSessions.set(session, role);\n}\n\n/** The Oh Story Role running in this Session, if it is an oh_story_role child. */\nexport function ohStoryRoleOfSession(session: Session | undefined): OhStoryRoleName | undefined {\n return session === undefined ? undefined : roleSessions.get(session);\n}\n", "import type { Context } from \"@deepseek-ai/cordis\";\nimport type { ContentBlock } from \"@deepseek-ai/dsh-llm\";\nimport type { SubagentRuntime } from \"@deepseek-ai/dsh-subagent\";\nimport type { JsonValue } from \"@deepseek-ai/dsh-util-values\";\nimport { defineTool, type ToolDefinition } from \"@deepseek-ai/dsh-tools\";\nimport {\n bundledReferenceGuard,\n createOhStoryReferenceTool,\n OH_STORY_REFERENCE_TOOL_NAME\n} from \"./reference-tool.js\";\nimport { markOhStoryRoleSession, ohStoryRoleLabel } from \"./role-identity.js\";\nimport { OH_STORY_ROLE_NAMES, loadBundledRole, type OhStoryRoleName } from \"./role-provider.js\";\n\nexport const OH_STORY_ROLE_TOOL_NAME = \"oh_story_role\";\nexport type OhStoryRoleSubagents = Pick<SubagentRuntime, \"start\">;\n\nconst roleTools: Readonly<Record<OhStoryRoleName, readonly string[]>> = {\n // Oh Story 0.8.0 lets the extractor write its own batch input file (never\n // bash). native-hooks fences write/edit to {\u62C6\u6587\u76EE\u5F55}/_analysis_cache/\u8F93\u5165-*.md.\n \"chapter-extractor\": [\"read\", \"glob\", \"grep\", \"write\", \"edit\"],\n \"character-designer\": [OH_STORY_REFERENCE_TOOL_NAME, \"read\", \"glob\", \"grep\", \"write\", \"edit\"],\n \"consistency-checker\": [OH_STORY_REFERENCE_TOOL_NAME, \"read\", \"glob\", \"grep\"],\n \"narrative-writer\": [OH_STORY_REFERENCE_TOOL_NAME, \"read\", \"glob\", \"grep\", \"write\", \"edit\", \"bash\"],\n \"story-architect\": [OH_STORY_REFERENCE_TOOL_NAME, \"read\", \"glob\", \"grep\", \"write\", \"edit\"],\n // Oh Story 0.8.2 moved benchmark_style_load's procedure into agent-references/benchmark-style-load.md.\n \"story-explorer\": [OH_STORY_REFERENCE_TOOL_NAME, \"read\", \"glob\", \"grep\"],\n \"story-researcher\": [\"read\", \"glob\", \"grep\", \"bash\", \"write\", \"web_search\", \"web_fetch\"]\n};\n\nexport function roleToolFilter(role: OhStoryRoleName): { readonly allow: readonly string[] } {\n return { allow: roleTools[role] };\n}\n\nfunction resultText(output: readonly ContentBlock[]): string {\n return output.map((block) => block.type === \"text\" ? block.text : JSON.stringify(block)).join(\"\\n\");\n}\n\nexport async function createOhStoryRoleTool(subagents?: OhStoryRoleSubagents): Promise<ToolDefinition> {\n const personas = new Map<OhStoryRoleName, string>();\n await Promise.all(OH_STORY_ROLE_NAMES.map(async (role) => {\n personas.set(role, await loadBundledRole(role, undefined, \"native-tools\"));\n }));\n return defineTool({\n name: OH_STORY_ROLE_TOOL_NAME,\n description: \"Run one focused Oh Story specialist as a child of the current DSH Agent. The child inherits DSH model, workspace, permissions, lifecycle, and UI.\",\n parameters: {\n role: {\n type: \"string\",\n required: true,\n enum: OH_STORY_ROLE_NAMES,\n description: \"The exact Oh Story Role to run.\"\n },\n prompt: {\n type: \"string\",\n required: true,\n description: \"A self-contained task. The child inherits the current DSH workspace but not the current in-flight turn.\"\n }\n },\n output: {\n schema: {\n type: \"object\",\n additionalProperties: false,\n properties: {\n role: { type: \"string\", required: true, enum: OH_STORY_ROLE_NAMES },\n runId: { type: \"string\", required: true },\n content: { type: \"array\", required: true, items: { type: \"json\" } }\n }\n },\n render: (_args, value) => [{ type: \"text\", text: resultText(value.content as unknown as ContentBlock[]) }]\n },\n isConcurrencySafe: () => true,\n async execute(args, exec) {\n if (exec.agent === undefined) throw new Error(\"oh_story_role requires a calling DSH Agent.\");\n const persona = personas.get(args.role);\n if (persona === undefined) throw new Error(`Oh Story Role ${args.role} is not bundled.`);\n const allowed = roleToolFilter(args.role).allow.filter((name) =>\n exec.agent?.ctx.tools.get(name, exec.agent) !== undefined);\n const runtime = subagents ?? exec.agent.ctx.get(\"subagents\");\n if (runtime === undefined) throw new Error(\"oh_story_role requires the DSH subagent runtime.\");\n const run = await runtime.start(\"spawn\", {\n // DSH persists this label in the child's subagent/descriptor; the\n // native hooks read the Role back from it before the child's first tool call.\n label: ohStoryRoleLabel(args.role),\n prompt: [{ type: \"text\", text: args.prompt }],\n parent: exec.agent,\n persona,\n toolFilter: { allow: allowed },\n maxDepth: 1,\n signal: exec.signal\n });\n if (run.localAgent !== undefined) markOhStoryRoleSession(run.localAgent.session, args.role);\n try {\n const result = await run.result;\n if (result.stopReason !== \"completed\") {\n throw new Error(`Oh Story Role ${args.role} ended with ${result.stopReason}${result.diagnostic === undefined ? \"\" : `: ${result.diagnostic}`}`);\n }\n return {\n role: args.role,\n runId: run.id,\n content: result.output as unknown as JsonValue[]\n };\n } finally {\n await run.dispose();\n }\n }\n });\n}\n\nexport async function registerOhStoryRoleTool(context: Context): Promise<void> {\n const [definition, referenceDefinition] = await Promise.all([\n createOhStoryRoleTool(context.subagents),\n createOhStoryReferenceTool()\n ]);\n context.tools.register(referenceDefinition);\n context.tools.guard(bundledReferenceGuard(referenceDefinition, context.tools));\n let dispose: (() => void) | undefined;\n const mount = (): void => { dispose ??= context.tools.register(definition); };\n const unmount = (): void => { dispose?.(); dispose = undefined; };\n context.on(\"subagent/provider-added\", (provider) => { if (provider.name === \"spawn\") mount(); });\n context.on(\"subagent/provider-removed\", (name) => { if (name === \"spawn\") unmount(); });\n if (context.subagents.getProvider(\"spawn\") !== undefined) mount();\n}\n", "import { readdir, readFile, realpath } from \"node:fs/promises\";\nimport { isAbsolute, join, relative, resolve } from \"node:path\";\nimport { defineTool, type ToolDefinition, type ToolGuard, type ToolRuntime } from \"@deepseek-ai/dsh-tools\";\nimport { defaultBundledSkillRoot } from \"./skill-provider.js\";\n\nexport const OH_STORY_REFERENCE_TOOL_NAME = \"oh_story_bundled_reference\";\n\ninterface BundledReference {\n readonly canonicalPath: string;\n readonly name: string;\n}\n\nasync function collectMarkdown(root: string, directory = root): Promise<string[]> {\n const entries = await readdir(directory, { withFileTypes: true });\n const nested = await Promise.all(entries.map(async (entry): Promise<string[]> => {\n const path = join(directory, entry.name);\n if (entry.isDirectory()) return collectMarkdown(root, path);\n return entry.isFile() && entry.name.endsWith(\".md\") ? [path] : [];\n }));\n return nested.flat();\n}\n\nasync function bundledReferences(storySetupRoot: string): Promise<readonly BundledReference[]> {\n const root = await realpath(resolve(storySetupRoot));\n const referenceRoot = await realpath(join(root, \"references\", \"agent-references\"));\n const referenceDirectory = relative(root, referenceRoot);\n if (referenceDirectory === \"\" || referenceDirectory.startsWith(\"..\") || isAbsolute(referenceDirectory)) {\n throw new Error(\"Bundled Oh Story reference directory escaped its package root.\");\n }\n const values = await Promise.all((await collectMarkdown(referenceRoot)).map(async (path): Promise<BundledReference> => {\n const canonicalPath = await realpath(path);\n const inside = relative(referenceRoot, canonicalPath);\n if (inside === \"\" || inside.startsWith(\"..\") || isAbsolute(inside)) {\n throw new Error(`Bundled Oh Story reference escaped its package root: ${path}`);\n }\n return {\n canonicalPath,\n name: `story-setup/references/agent-references/${inside.replaceAll(\"\\\\\", \"/\")}`\n };\n }));\n return values.sort((left, right) => left.name.localeCompare(right.name));\n}\n\nexport async function createOhStoryReferenceTool(\n storySetupRoot = join(defaultBundledSkillRoot(), \"story-setup\")\n): Promise<ToolDefinition> {\n const references = await bundledReferences(storySetupRoot);\n if (references.length === 0) throw new Error(\"No bundled Oh Story references were found.\");\n const paths = references.map((reference) => reference.name);\n const byName = new Map(references.map((reference) => [reference.name, reference.canonicalPath]));\n return defineTool({\n name: OH_STORY_REFERENCE_TOOL_NAME,\n description: \"Read one exact, pinned Oh Story story-setup reference bundled with this plugin. This does not resolve project Skills or workspace files.\",\n parameters: {\n reference: {\n type: \"string\",\n required: true,\n enum: paths,\n description: \"The exact story-setup reference path named by the active bundled Role.\"\n }\n },\n output: {\n schema: {\n type: \"object\",\n additionalProperties: false,\n properties: {\n reference: { type: \"string\", required: true },\n content: { type: \"string\", required: true }\n }\n },\n render: (_args, value) => [{\n type: \"text\",\n text: `Bundled Oh Story reference: ${value.reference}\\n\\n${value.content}`\n }]\n },\n isConcurrencySafe: () => true,\n async execute(args) {\n const path = byName.get(args.reference);\n if (path === undefined) throw new Error(`Oh Story reference is not bundled: ${args.reference}`);\n return { reference: args.reference, content: await readFile(path, \"utf8\") };\n }\n });\n}\n\n/** Deny a scoped same-name replacement instead of executing untrusted reference code. */\nexport function bundledReferenceGuard(\n definition: ToolDefinition,\n tools: Pick<ToolRuntime, \"get\">\n): ToolGuard {\n return (execution) => execution.name === OH_STORY_REFERENCE_TOOL_NAME\n && tools.get(OH_STORY_REFERENCE_TOOL_NAME, execution.agent) !== definition\n ? \"The pinned Oh Story reference tool was shadowed in this Agent scope.\"\n : undefined;\n}\n", "import type { Context } from \"@deepseek-ai/cordis\";\nimport { defineTool, type ToolDefinition } from \"@deepseek-ai/dsh-tools\";\nimport {\n OH_STORY_PRODUCTION_TOOL_NAME,\n PRODUCTION_INTENT_ACTIONS,\n PRODUCTION_INTENT_JOB_KINDS,\n PRODUCTION_INTENT_SECTIONS,\n validateProductionIntent,\n type ProductionIntentArgs\n} from \"./production-intent.js\";\n\nfunction intentMessage(intent: ProductionIntentArgs): string {\n if (intent.action === \"track_job\") return `\u5DF2\u628A ${intent.targetId ?? \"\u751F\u4EA7\u5BF9\u8C61\"} \u7684 ${intent.jobKind ?? \"\u5A92\u4F53\"} \u4EFB\u52A1\u6295\u5F71\u5230 ${intent.episode} \u7684\u4EFB\u52A1\u677F\u3002`;\n if (intent.action === \"set_sequence\") return `\u5DF2\u628A ${String(intent.shotIds?.length ?? 0)} \u4E2A\u955C\u5934\u7684\u987A\u5E8F\u53D1\u9001\u5230 ${intent.episode} \u6210\u7247\u89C6\u56FE\u3002`;\n if (intent.action === \"focus_target\") return `\u5DF2\u8BF7\u6C42 ${intent.episode} \u751F\u4EA7\u89C6\u56FE\u805A\u7126 ${intent.targetId ?? \"\u76EE\u6807\"}\u3002`;\n return `\u5DF2\u628A ${intent.action} \u754C\u9762\u610F\u56FE\u53D1\u9001\u5230 ${intent.episode} \u751F\u4EA7\u5DE5\u4F5C\u53F0\u3002`;\n}\n\nexport function createOhStoryProductionTool(): ToolDefinition {\n return defineTool({\n name: OH_STORY_PRODUCTION_TOOL_NAME,\n description: \"Operate the native oh-story short-drama production projection in the current DSH Session. It can open or focus semantic production targets, set an explicit shot order, or track a job the Agent is actually executing. It never controls cosmetic canvas layout, generates media, changes creator documents, or counts as creator confirmation for paid production.\",\n parameters: {\n action: { type: \"string\", required: true, enum: PRODUCTION_INTENT_ACTIONS, description: \"The exact production UI/task projection operation.\" },\n episode: { type: \"string\", required: true, description: \"Creator-first episode directory, for example \u5267\u96C6/EP001.\" },\n section: { type: \"string\", enum: PRODUCTION_INTENT_SECTIONS },\n targetId: { type: \"string\" },\n shotIds: { type: \"array\", items: { type: \"string\" } },\n jobId: { type: \"string\", description: \"Stable ID that must also appear in produced output filenames.\" },\n jobKind: { type: \"string\", enum: PRODUCTION_INTENT_JOB_KINDS },\n expectedOutputs: { type: \"integer\", description: \"Number of media files this job will produce. Repeat the count the creator approved when re-registering a batch; omit it to keep the count the workbench already recorded.\" },\n prompt: { type: \"string\", description: \"Exact prompt/specification for a tracked job; not a production authorization.\" }\n },\n output: {\n schema: {\n type: \"object\",\n additionalProperties: false,\n properties: {\n action: { type: \"string\", required: true, enum: PRODUCTION_INTENT_ACTIONS },\n episode: { type: \"string\", required: true },\n message: { type: \"string\", required: true }\n }\n },\n render: (_args, value) => [{ type: \"text\", text: value.message }]\n },\n isConcurrencySafe: () => true,\n execute(args) {\n const intent = validateProductionIntent(args);\n return Promise.resolve({ action: intent.action, episode: intent.episode, message: intentMessage(intent) });\n }\n });\n}\n\nexport function registerOhStoryProductionTool(context: Context): void {\n context.tools.register(createOhStoryProductionTool());\n}\n", "export const OH_STORY_PRODUCTION_TOOL_NAME = \"oh_story_production\";\n\nexport const PRODUCTION_INTENT_ACTIONS = [\n \"open_section\",\n \"focus_target\",\n \"set_sequence\",\n \"track_job\"\n] as const;\n\nexport const PRODUCTION_INTENT_SECTIONS = [\"shots\", \"assets\", \"tasks\", \"sequence\", \"canvas\"] as const;\nexport const PRODUCTION_INTENT_JOB_KINDS = [\"image\", \"video\", \"composition\"] as const;\n\nexport type ProductionIntentAction = typeof PRODUCTION_INTENT_ACTIONS[number];\nexport type ProductionIntentSection = typeof PRODUCTION_INTENT_SECTIONS[number];\nexport type ProductionIntentJobKind = typeof PRODUCTION_INTENT_JOB_KINDS[number];\n\nexport interface ProductionIntentArgs {\n readonly action: ProductionIntentAction;\n readonly episode: string;\n readonly section?: ProductionIntentSection | undefined;\n readonly targetId?: string | undefined;\n readonly shotIds?: readonly string[] | undefined;\n readonly jobId?: string | undefined;\n readonly jobKind?: ProductionIntentJobKind | undefined;\n readonly expectedOutputs?: number | undefined;\n readonly prompt?: string | undefined;\n}\n\nfunction requiredText(value: string | undefined, field: string): string {\n const normalized = value?.trim();\n if (!normalized) throw new Error(`oh_story_production ${field} is required for this action.`);\n if (normalized.length > 512) throw new Error(`oh_story_production ${field} is too long.`);\n return normalized;\n}\n\n/** Validate the cross-runtime UI intent without reading or mutating workspace state. */\nexport function validateProductionIntent(args: ProductionIntentArgs): ProductionIntentArgs {\n const episode = args.episode.trim().replaceAll(\"\\\\\", \"/\").replace(/\\/$/u, \"\");\n if (!/^\u5267\u96C6\\/EP\\d{3,}$/u.test(episode)) {\n throw new Error(\"oh_story_production episode must use the creator path form \u5267\u96C6/EP001.\");\n }\n if (args.action === \"open_section\") {\n if (args.section === undefined) throw new Error(\"oh_story_production section is required for open_section.\");\n return { action: args.action, episode, section: args.section };\n }\n if (args.action === \"focus_target\") {\n return { action: args.action, episode, targetId: requiredText(args.targetId, \"targetId\"), section: args.section };\n }\n if (args.action === \"set_sequence\") {\n const shotIds = args.shotIds?.map((value) => value.trim()).filter((value) => value !== \"\") ?? [];\n if (shotIds.length === 0) throw new Error(\"oh_story_production shotIds must contain at least one shot for set_sequence.\");\n if (shotIds.length > 500 || new Set(shotIds).size !== shotIds.length || shotIds.some((value) => !/^SHOT-[A-Z0-9-]+$/u.test(value))) {\n throw new Error(\"oh_story_production shotIds must be unique canonical SHOT-* identifiers.\");\n }\n return { action: args.action, episode, shotIds };\n }\n // Leave expectedOutputs/prompt undefined when the caller omits them: track_job re-registers a job the\n // workbench already created, and defaulting here would silently reset a batch's count to 1.\n const expectedOutputs = args.expectedOutputs;\n if (expectedOutputs !== undefined && (!Number.isInteger(expectedOutputs) || expectedOutputs < 1 || expectedOutputs > 500)) {\n throw new Error(\"oh_story_production expectedOutputs must be an integer between 1 and 500.\");\n }\n if (args.jobKind === undefined) throw new Error(\"oh_story_production jobKind is required for track_job.\");\n const prompt = args.prompt?.trim();\n return {\n action: args.action,\n episode,\n jobId: requiredText(args.jobId, \"jobId\"),\n targetId: requiredText(args.targetId, \"targetId\"),\n jobKind: args.jobKind,\n expectedOutputs,\n prompt: prompt === \"\" ? undefined : prompt\n };\n}\n", "import { createHash } from \"node:crypto\";\nimport { createReadStream } from \"node:fs\";\nimport { readFile as readNodeFile, realpath as nodeRealpath, stat as nodeStat } from \"node:fs/promises\";\nimport type { IncomingMessage, ServerResponse } from \"node:http\";\nimport { extname, isAbsolute, relative, resolve } from \"node:path\";\nimport type { Context } from \"@deepseek-ai/cordis\";\nimport type { Agent } from \"@deepseek-ai/dsh-agent\";\nimport { FsError, type FileSystem, type FsInfo, type FsTarget, type FsVersion } from \"@deepseek-ai/dsh-fs\";\nimport type {} from \"@deepseek-ai/dsh-host-webserver\";\nimport type { SandboxPolicyService } from \"@deepseek-ai/dsh-sandbox-policy\";\nimport { SessionId } from \"@deepseek-ai/dsh-session\";\nimport type {} from \"@deepseek-ai/dsh-typert-registry\";\nimport { type GameVerificationBinding, WorkspaceVerificationTracker } from \"./game-verification.js\";\nimport { dramaAdapterStatuses, ensureDramaAdapterConfig, type DramaAdapterStatus } from \"./drama-adapters.js\";\nimport { commandOutput, hostPython } from \"./host-python.js\";\nimport { defaultDramaSkillRoot, defaultNovelToGameSkillRoot } from \"./skill-provider.js\";\nimport { skipVideoDirectory, summarizeVideoProject, VIDEO_DIRECTORY, videoProjectRoot, visibleVideoPath, type VideoProjectSummary } from \"./video-project.js\";\nimport { isTrustedPreviewNavigation, isTrustedWorkspaceRequest } from \"./workspace-request-trust.js\";\n\nconst STORY_DIRECTORIES = [\"\u6B63\u6587\", \"\u5927\u7EB2\", \"\u8BBE\u5B9A\", \"\u8FFD\u8E2A\", \"\u5BF9\u6807\", \"\u53C2\u8003\u8D44\u6599\"] as const;\nconst DRAMA_DIRECTORIES = [\"\u8F93\u5165\", \"\u9879\u76EE\u5F00\u53D1\", \"\u8BBE\u5B9A\u96C6\", \"\u5267\u96C6\", \"\u4EA4\u4ED8\", \"\u521B\u4F5C\u8005\u51B3\u7B56\", \"\u5BA1\u67E5\"] as const;\nconst GAME_DIRECTORY = \"game-adaptations\";\n// Preview studios need only a small manifest-driven subset, so discover them before a very large\n// prose workspace can consume the shared listing budget.\nconst CREATIVE_DIRECTORIES = [VIDEO_DIRECTORY, GAME_DIRECTORY, ...STORY_DIRECTORIES, ...DRAMA_DIRECTORIES] as const;\nconst ROOT_FILES = new Set([\"short-drama.json\"]);\nconst EDITABLE_EXTENSIONS = new Set([\".md\", \".txt\", \".json\", \".jsonl\"]);\nconst GAME_EDITABLE_EXTENSIONS = new Set([...EDITABLE_EXTENSIONS, \".html\", \".css\", \".js\", \".mjs\", \".cjs\", \".ts\", \".tsx\", \".jsx\"]);\nconst VIDEO_EDITABLE_EXTENSIONS = new Set([...EDITABLE_EXTENSIONS, \".srt\", \".ass\"]);\nconst MEDIA_TYPES: ReadonlyMap<string, string> = new Map([\n [\".png\", \"image/png\"], [\".jpg\", \"image/jpeg\"], [\".jpeg\", \"image/jpeg\"], [\".webp\", \"image/webp\"], [\".gif\", \"image/gif\"],\n [\".mp4\", \"video/mp4\"], [\".webm\", \"video/webm\"], [\".mov\", \"video/quicktime\"], [\".mkv\", \"video/x-matroska\"],\n [\".mp3\", \"audio/mpeg\"], [\".wav\", \"audio/wav\"], [\".m4a\", \"audio/mp4\"], [\".aac\", \"audio/aac\"], [\".flac\", \"audio/flac\"]\n]);\nconst MEDIA_MAX_BYTES = 256 * 1_024 * 1_024;\nconst FILE_LIMIT = 1_000;\nconst PREVIEW_FILE_LIMIT = 32 * 1024 * 1024;\nconst BUNDLED_GAME_EXAMPLE = \"jin-ping-mei\";\nconst workspaceVerificationTracker = new WorkspaceVerificationTracker();\nlet videoPreflightCache: { readonly expires: number; readonly value: VideoPreflightSummary } | undefined;\nlet dramaPreflightCache: { readonly expires: number; readonly value: DramaPreflightSummary } | undefined;\n\ninterface WorkspaceRouteOptions {\n readonly maxBytes: number;\n readonly trustedHosts?: readonly string[];\n}\n\n/** Host-process capability probe. The Agent's execution world may differ; `video-recap --doctor` is authoritative there. */\ninterface VideoPreflightSummary {\n readonly python: { readonly ok: boolean; readonly version?: string | undefined };\n readonly ffmpeg: { readonly ok: boolean; readonly subtitles: boolean };\n readonly ffprobe: { readonly ok: boolean };\n readonly credentials: { readonly mimo: boolean; readonly fish: boolean; readonly indexTts: boolean; readonly ttsProvider: string };\n}\n\ninterface WorkspaceFile {\n readonly path: string;\n readonly bytes: number;\n readonly version: string;\n readonly kind: \"text\" | \"media\";\n readonly mimeType?: string | undefined;\n}\n\ninterface GameVerificationSummary {\n readonly status: \"NOT_RUN\" | \"FAIL\" | \"PASS\";\n readonly checks: Readonly<Record<string, \"NOT_RUN\" | \"FAIL\" | \"PASS\">>;\n readonly runId?: string | undefined;\n readonly limitations: readonly { readonly scope: string; readonly reason: string }[];\n readonly binding: GameVerificationBinding;\n readonly verifiedPreviewVersion?: string | undefined;\n}\n\ninterface GameProjectSummary {\n readonly id: string;\n readonly root: string;\n readonly title: string;\n readonly source: \"workspace\" | \"example\";\n readonly previewReady: boolean;\n readonly previewUrl?: string | undefined;\n readonly previewVersion: string;\n readonly verification: GameVerificationSummary;\n}\n\ninterface WorkspaceRealm {\n readonly agent: Agent;\n readonly fs: FileSystem;\n readonly sandboxPolicy: SandboxPolicyService;\n readonly cwd: string;\n readonly root: FsTarget;\n}\n\ninterface ReadFileResult {\n readonly content: string;\n readonly bytes: number;\n readonly version: FsVersion;\n}\n\nclass WorkspaceHttpError extends Error {\n constructor(readonly status: number, message: string) { super(message); }\n}\n\nfunction configured(...names: readonly string[]): boolean {\n return names.some((name) => (process.env[name] ?? \"\") !== \"\");\n}\n\n/**\n * Host-process view of short-drama production: which bundled media adapters\n * have their environment set, and where the adapter config the Agent passes to\n * `production_tool.py run` lives. Values never leave the process.\n */\ninterface DramaPreflightSummary {\n readonly python: { readonly ok: boolean; readonly version?: string | undefined };\n readonly adapterConfig: { readonly path: string; readonly generated: boolean; readonly ok: boolean };\n readonly adapters: readonly DramaAdapterStatus[];\n}\n\nlet dramaPreflightInFlight: Promise<DramaPreflightSummary> | undefined;\n\nasync function dramaPreflight(): Promise<DramaPreflightSummary> {\n if (dramaPreflightCache !== undefined && dramaPreflightCache.expires > Date.now()) return dramaPreflightCache.value;\n // One probe per cache miss: concurrent requests share the write instead of\n // racing it, and the write itself is atomic (temp file + rename).\n dramaPreflightInFlight ??= (async () => {\n try {\n const python = await hostPython();\n const adapterConfig = await ensureDramaAdapterConfig(defaultDramaSkillRoot(), { python: python.command });\n const value = { python: python.probe, adapterConfig, adapters: dramaAdapterStatuses() };\n dramaPreflightCache = { expires: Date.now() + 30_000, value };\n return value;\n } finally { dramaPreflightInFlight = undefined; }\n })();\n return dramaPreflightInFlight;\n}\n\nasync function videoPreflight(): Promise<VideoPreflightSummary> {\n if (videoPreflightCache !== undefined && videoPreflightCache.expires > Date.now()) return videoPreflightCache.value;\n const python = (await hostPython()).probe;\n const [ffmpegOutput, ffmpegFilters, ffprobeOutput] = await Promise.all([\n commandOutput(\"ffmpeg\", [\"-version\"]),\n commandOutput(\"ffmpeg\", [\"-hide_banner\", \"-filters\"]),\n commandOutput(\"ffprobe\", [\"-version\"])\n ]);\n const value = {\n python,\n ffmpeg: { ok: ffmpegOutput !== undefined, subtitles: /\\bsubtitles\\b/u.test(ffmpegFilters ?? \"\") },\n ffprobe: { ok: ffprobeOutput !== undefined },\n credentials: {\n // Upstream falls back to the shared MIMO_API_KEY only when a per-service key is unset.\n mimo: configured(\"MIMO_API_KEY\", \"MIMO_VIDEO_API_KEY\", \"MIMO_TTS_API_KEY\", \"MIMO_ASR_API_KEY\"),\n fish: configured(\"FISH_API_KEY\"),\n // index-tts fails before any request unless both are set (video-voiceover/references/index-tts.md).\n indexTts: configured(\"INDEX_TTS_ENDPOINT\") && configured(\"INDEX_TTS_VOICE\"),\n // Upstream accepts auto | mimo-tts | fish-audio | index-tts and defaults to auto (voiceover.py).\n ttsProvider: (process.env.TTS_PROVIDER ?? \"\").trim().toLowerCase() || \"auto\"\n }\n };\n videoPreflightCache = { expires: Date.now() + 30_000, value };\n return value;\n}\n\nfunction send(response: ServerResponse, status: number, value: unknown): void {\n const body = `${JSON.stringify(value)}\\n`;\n response.writeHead(status, {\n \"content-type\": \"application/json; charset=utf-8\",\n \"content-length\": Buffer.byteLength(body),\n \"cache-control\": \"no-store\",\n \"x-content-type-options\": \"nosniff\"\n });\n response.end(body);\n}\n\nexport interface ByteRange { readonly start: number; readonly end: number }\n\n/**\n * RFC 9110 14.2: a Range this server cannot parse or does not support is ignored (`undefined`, full\n * 200 response); only a well-formed but unsatisfiable range earns a 416 (`null`).\n */\nexport function parseByteRange(value: string | undefined, size: number): ByteRange | undefined | null {\n const match = value === undefined ? null : /^bytes=(\\d*)-(\\d*)$/u.exec(value.trim());\n if (match === null) return undefined;\n const left = match[1] ?? \"\";\n const right = match[2] ?? \"\";\n if (left === \"\") {\n const suffix = Number(right);\n if (right === \"\" || !Number.isSafeInteger(suffix)) return undefined;\n return suffix === 0 || size <= 0 ? null : { start: Math.max(0, size - suffix), end: size - 1 };\n }\n const start = Number(left);\n const requestedEnd = right === \"\" ? Number.MAX_SAFE_INTEGER : Number(right);\n if (!Number.isSafeInteger(start) || !Number.isSafeInteger(requestedEnd) || requestedEnd < start) return undefined;\n return start >= size ? null : { start, end: Math.min(requestedEnd, size - 1) };\n}\n\nfunction mediaHeaders(mimeType: string, size: number, range: ByteRange | undefined): Record<string, string | number> {\n const start = range?.start ?? 0;\n const end = range?.end ?? size - 1;\n return {\n \"content-type\": mimeType,\n \"content-length\": Math.max(0, end - start + 1),\n \"cache-control\": \"private, max-age=60\",\n \"accept-ranges\": \"bytes\",\n ...(range === undefined ? {} : { \"content-range\": `bytes ${String(start)}-${String(end)}/${String(size)}` }),\n \"x-content-type-options\": \"nosniff\"\n };\n}\n\nfunction sendMediaBytes(request: IncomingMessage, response: ServerResponse, bytes: Uint8Array, mimeType: string): void {\n const range = parseByteRange(typeof request.headers.range === \"string\" ? request.headers.range : undefined, bytes.byteLength);\n if (range === null) {\n response.writeHead(416, { \"content-range\": `bytes */${String(bytes.byteLength)}`, \"cache-control\": \"no-store\" });\n response.end();\n return;\n }\n const start = range?.start ?? 0;\n const end = range?.end ?? bytes.byteLength - 1;\n const body = bytes.subarray(start, end + 1);\n response.writeHead(range === undefined ? 200 : 206, mediaHeaders(mimeType, bytes.byteLength, range));\n response.end(request.method === \"HEAD\" ? undefined : Buffer.from(body));\n}\n\n/**\n * Resolve the target to a path this web host may open directly, or `undefined` when it may not.\n * `processPath` is canonical in the backend's execution world, which is not necessarily this\n * process's, so containment is re-checked against the host-visible workspace root: a remote path\n * that happens to exist locally never becomes a stream.\n */\nasync function hostWorkspaceFile(realm: WorkspaceRealm, target: FsTarget, expectedSize: number): Promise<string | undefined> {\n const [root, path] = await Promise.all([\n nodeRealpath(realm.fs.processPath(realm.root)),\n nodeRealpath(realm.fs.processPath(target))\n ]);\n const inside = relative(root, path);\n if (inside === \"\" || inside.startsWith(\"..\") || isAbsolute(inside)) return undefined;\n const local = await nodeStat(path);\n return local.isFile() && local.size === expectedSize ? path : undefined;\n}\n\nasync function sendWorkspaceMedia(request: IncomingMessage, response: ServerResponse, realm: WorkspaceRealm, target: FsTarget, info: FsInfo, mimeType: string): Promise<void> {\n const expectedSize = info.size;\n if (expectedSize !== undefined) {\n // A remote filesystem may expose a process path this web host cannot read; fall back to its\n // bounded binary API for modest files.\n const processPath = await hostWorkspaceFile(realm, target, expectedSize).catch(() => undefined);\n if (processPath !== undefined) {\n const range = parseByteRange(typeof request.headers.range === \"string\" ? request.headers.range : undefined, expectedSize);\n if (range === null) {\n response.writeHead(416, { \"content-range\": `bytes */${String(expectedSize)}`, \"cache-control\": \"no-store\" });\n response.end();\n return;\n }\n response.writeHead(range === undefined ? 200 : 206, mediaHeaders(mimeType, expectedSize, range));\n if (request.method === \"HEAD\") { response.end(); return; }\n const stream = createReadStream(processPath, range === undefined ? undefined : { start: range.start, end: range.end });\n request.once(\"close\", () => { if (!response.writableEnded) stream.destroy(); });\n stream.on(\"error\", () => { if (!response.headersSent) response.destroy(); else response.end(); });\n stream.pipe(response);\n return;\n }\n if (expectedSize > MEDIA_MAX_BYTES) throw new WorkspaceHttpError(413, \"\u8FDC\u7A0B\u5A92\u4F53\u8D85\u8FC7\u5DE5\u4F5C\u53F0\u56DE\u9000\u9884\u89C8\u5927\u5C0F\u9650\u5236\u3002\");\n }\n sendMediaBytes(request, response, await realm.fs.readBytes(target, undefined, MEDIA_MAX_BYTES), mimeType);\n}\n\nasync function jsonBody(request: IncomingMessage, maxBytes: number): Promise<Record<string, unknown>> {\n const chunks: Buffer[] = [];\n let size = 0;\n for await (const chunk of request as AsyncIterable<Uint8Array>) {\n const value = Buffer.from(chunk);\n size += value.byteLength;\n if (size > maxBytes) throw new WorkspaceHttpError(413, \"\u8BF7\u6C42\u5185\u5BB9\u8FC7\u5927\u3002\");\n chunks.push(value);\n }\n try {\n const value = JSON.parse(Buffer.concat(chunks).toString(\"utf8\")) as unknown;\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) throw new Error();\n return value as Record<string, unknown>;\n } catch {\n throw new WorkspaceHttpError(400, \"\u8BF7\u6C42\u5FC5\u987B\u662F JSON \u5BF9\u8C61\u3002\");\n }\n}\n\nfunction safeRelativePath(path: string): boolean {\n return path !== \"\"\n && !path.startsWith(\"/\")\n && !path.includes(\"\\\\\")\n && !path.split(\"/\").some((segment) => segment === \"\" || segment === \".\" || segment === \"..\");\n}\n\nfunction editablePath(path: string): boolean {\n const extensions = path.startsWith(`${GAME_DIRECTORY}/`) ? GAME_EDITABLE_EXTENSIONS\n : path.startsWith(`${VIDEO_DIRECTORY}/`) ? VIDEO_EDITABLE_EXTENSIONS\n : EDITABLE_EXTENSIONS;\n return extensions.has(extname(path).toLocaleLowerCase());\n}\n\nexport function assertCreativePath(path: string, kind: \"text\" | \"media\"): void {\n if (kind === \"text\" ? !editablePath(path) : !MEDIA_TYPES.has(extname(path).toLocaleLowerCase())) {\n throw new WorkspaceHttpError(415, kind === \"text\" ? \"\u5DE5\u4F5C\u53F0\u4E0D\u652F\u6301\u7F16\u8F91\u8BE5\u6587\u4EF6\u7C7B\u578B\u3002\" : \"\u76EE\u6807\u4E0D\u662F\u53D7\u652F\u6301\u7684\u77ED\u5267\u5A92\u4F53\u6587\u4EF6\u3002\");\n }\n if (!safeRelativePath(path)) {\n throw new WorkspaceHttpError(403, \"\u6587\u4EF6\u8DEF\u5F84\u4E0D\u5728\u521B\u4F5C\u5DE5\u4F5C\u53F0\u4E2D\u3002\");\n }\n const root = path.split(\"/\", 1)[0];\n if (!CREATIVE_DIRECTORIES.some((directory) => directory === root) && !ROOT_FILES.has(path)) {\n throw new WorkspaceHttpError(403, \"\u6587\u4EF6\u8DEF\u5F84\u4E0D\u5728\u521B\u4F5C\u5DE5\u4F5C\u53F0\u4E2D\u3002\");\n }\n}\n\nexport function mediaMimeTypeForPath(path: string): string | undefined {\n return MEDIA_TYPES.get(extname(path).toLocaleLowerCase());\n}\n\nasync function workspaceRealmForSession(context: Context, rawId: string): Promise<WorkspaceRealm> {\n if (rawId === \"\") throw new WorkspaceHttpError(400, \"\u7F3A\u5C11 DSH sessionId\u3002\");\n const lookup = context.typert.lookups.get(\"agent\");\n if (lookup === undefined) throw new WorkspaceHttpError(503, \"DSH Agent lookup \u5F53\u524D\u4E0D\u53EF\u7528\u3002\");\n let agent: Agent | undefined;\n try {\n agent = await lookup.resolve(SessionId(rawId)) as Agent | undefined;\n } catch {\n throw new WorkspaceHttpError(404, \"DSH \u4F1A\u8BDD\u4E0D\u53EF\u7528\u3002\");\n }\n if (agent === undefined) throw new WorkspaceHttpError(404, \"DSH \u4F1A\u8BDD\u4E0D\u53EF\u7528\u3002\");\n if (agent.session.header.parentSession !== undefined || agent.session.header.origin === \"subagent\") {\n throw new WorkspaceHttpError(403, \"\u5B50 Agent \u4F1A\u8BDD\u4E0D\u5F00\u653E\u521B\u4F5C\u7F16\u8F91\u5668\u3002\");\n }\n const cwd = agent.session.header.cwd;\n if (cwd === undefined) throw new WorkspaceHttpError(409, \"\u5F53\u524D DSH \u4F1A\u8BDD\u6CA1\u6709\u5DE5\u4F5C\u76EE\u5F55\u3002\");\n const fs = agent.ctx.get(\"fs\");\n const sandboxPolicy = agent.ctx.get(\"sandboxPolicy\");\n if (fs === undefined || sandboxPolicy === undefined) throw new WorkspaceHttpError(503, \"DSH \u6587\u4EF6\u7CFB\u7EDF\u5F53\u524D\u4E0D\u53EF\u7528\u3002\");\n return { agent, fs, sandboxPolicy, cwd, root: await fs.resolve(cwd) };\n}\n\nasync function workspaceRealm(context: Context, url: URL): Promise<WorkspaceRealm> {\n const rawId = url.searchParams.get(\"sessionId\");\n if (rawId === null) throw new WorkspaceHttpError(400, \"\u7F3A\u5C11 DSH sessionId\u3002\");\n return workspaceRealmForSession(context, rawId);\n}\n\nasync function creativeTarget(realm: WorkspaceRealm, path: string, kind: \"text\" | \"media\" = \"text\"): Promise<FsTarget> {\n assertCreativePath(path, kind);\n const target = await realm.fs.resolve(path, { cwd: realm.cwd });\n if (!realm.fs.contains(realm.root, target)) throw new WorkspaceHttpError(403, \"\u6587\u4EF6\u8DEF\u5F84\u79BB\u5F00\u4E86 DSH \u5DE5\u4F5C\u76EE\u5F55\u3002\");\n return target;\n}\n\nfunction requireRegularFile(info: FsInfo | undefined): FsInfo {\n if (info === undefined) throw new WorkspaceHttpError(404, \"\u6587\u4EF6\u4E0D\u5B58\u5728\u3002\");\n if (info.type !== \"file\") throw new WorkspaceHttpError(415, \"\u76EE\u6807\u4E0D\u662F\u53EF\u7F16\u8F91\u7684\u666E\u901A\u6587\u4EF6\u3002\");\n return info;\n}\n\n/** Read bytes and a matching opaque version, retrying if a writer wins the read window. */\nasync function readVersionedFile(fs: FileSystem, target: FsTarget, maxBytes: number): Promise<ReadFileResult> {\n for (let attempt = 0; attempt < 3; attempt += 1) {\n const before = requireRegularFile(await fs.stat(target));\n if (before.size !== undefined && before.size > maxBytes) throw new WorkspaceHttpError(413, \"\u6587\u4EF6\u8D85\u8FC7\u5DE5\u4F5C\u53F0\u5927\u5C0F\u9650\u5236\u3002\");\n const bytes = await fs.readBytes(target, undefined, maxBytes);\n const after = requireRegularFile(await fs.stat(target));\n if (before.version !== after.version) continue;\n let content: string;\n try {\n content = new TextDecoder(\"utf-8\", { fatal: true }).decode(bytes);\n } catch {\n throw new WorkspaceHttpError(415, \"\u6587\u4EF6\u4E0D\u662F\u6709\u6548\u7684 UTF-8 \u6587\u672C\u3002\");\n }\n return { content, bytes: bytes.byteLength, version: after.version };\n }\n throw new WorkspaceHttpError(409, \"\u6587\u4EF6\u6B63\u5728\u88AB\u4FEE\u6539\uFF0C\u8BF7\u91CD\u8BD5\u3002\");\n}\n\nasync function listFiles(realm: WorkspaceRealm): Promise<WorkspaceFile[]> {\n const files: WorkspaceFile[] = [];\n const walk = async (path: string, directory: FsTarget): Promise<void> => {\n for (const entry of await realm.fs.listDir(directory)) {\n if (entry.name.startsWith(\".\") || !realm.fs.contains(realm.root, entry.target)) continue;\n const childPath = `${path}/${entry.name}`;\n if (entry.type === \"directory\") {\n if (!skipVideoDirectory(childPath)) await walk(childPath, entry.target);\n }\n else if (entry.type === \"file\" && (editablePath(childPath) || MEDIA_TYPES.has(extname(entry.name).toLocaleLowerCase()))) {\n const info = entry.version === undefined || entry.size === undefined ? await realm.fs.stat(entry.target) : undefined;\n const version = entry.version ?? info?.version;\n const mimeType = MEDIA_TYPES.get(extname(entry.name).toLocaleLowerCase());\n if (version !== undefined && (!childPath.startsWith(`${VIDEO_DIRECTORY}/`) || visibleVideoPath(childPath))) {\n files.push({ path: childPath, bytes: entry.size ?? info?.size ?? 0, version, kind: mimeType === undefined ? \"text\" : \"media\", mimeType });\n }\n }\n if (files.length >= FILE_LIMIT) return;\n }\n };\n for (const directory of CREATIVE_DIRECTORIES) {\n const target = await realm.fs.resolve(directory, { cwd: realm.cwd });\n if (!realm.fs.contains(realm.root, target)) continue;\n const info = await realm.fs.stat(target);\n if (info?.type === \"directory\") await walk(directory, target);\n if (files.length >= FILE_LIMIT) break;\n }\n for (const path of ROOT_FILES) {\n const target = await creativeTarget(realm, path);\n const info = await realm.fs.stat(target);\n if (info?.type === \"file\") files.push({ path, bytes: info.size ?? 0, version: info.version, kind: \"text\" });\n }\n return files.sort((left, right) => left.path.localeCompare(right.path, \"zh-Hans-CN\"));\n}\n\nasync function metadata(realm: WorkspaceRealm, files: readonly WorkspaceFile[], path: string, maxBytes: number): Promise<{ readonly value: unknown; readonly error?: string }> {\n if (!files.some((file) => file.path === path)) return { value: null };\n try {\n const target = await creativeTarget(realm, path);\n return { value: JSON.parse((await readVersionedFile(realm.fs, target, maxBytes)).content) as unknown };\n } catch (error) {\n return { value: null, error: error instanceof SyntaxError ? `${path} \u4E0D\u662F\u6709\u6548\u7684 JSON\u3002` : `${path} \u6682\u65F6\u65E0\u6CD5\u8BFB\u53D6\u3002` };\n }\n}\n\nfunction token(value: string): string {\n return Buffer.from(value, \"utf8\").toString(\"base64url\");\n}\n\nfunction untoken(value: string): string {\n try { return Buffer.from(value, \"base64url\").toString(\"utf8\"); }\n catch { throw new WorkspaceHttpError(400, \"\u6E38\u620F\u9884\u89C8\u6807\u8BC6\u65E0\u6548\u3002\"); }\n}\n\nexport function gameRoot(path: string): boolean {\n // Reject only what is actually unsafe; fs.resolve + fs.contains remain the real boundary.\n // A stricter slug allowlist silently hid legitimate project names (spaces, \u00B7, leading _, NFD).\n const parts = path.split(\"/\");\n const name = parts[1];\n return parts.length === 2 && parts[0] === GAME_DIRECTORY && name !== undefined\n && name !== \"\" && name !== \".\" && name !== \"..\" && name.length <= 128\n && !name.startsWith(\".\") && !name.includes(\"\\\\\");\n}\n\nfunction normalizedVerification(\n value: unknown,\n binding: GameVerificationBinding,\n verifiedPreviewVersion?: string\n): GameVerificationSummary {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n return { status: \"NOT_RUN\", checks: {}, limitations: [], binding };\n }\n const record = value as Record<string, unknown>;\n const status = record.status === \"PASS\" || record.status === \"FAIL\" ? record.status : \"NOT_RUN\";\n const rawChecks = typeof record.checks === \"object\" && record.checks !== null && !Array.isArray(record.checks)\n ? record.checks as Record<string, unknown>\n : {};\n const checks: Record<string, \"NOT_RUN\" | \"FAIL\" | \"PASS\"> = {};\n for (const name of [\"launch\", \"render\", \"input\", \"coreLoop\", \"outcome\", \"restart\"]) {\n const check = rawChecks[name];\n checks[name] = check === \"PASS\" || check === \"FAIL\" ? check : \"NOT_RUN\";\n }\n const completeRun = typeof record.completeRun === \"object\" && record.completeRun !== null && !Array.isArray(record.completeRun)\n ? record.completeRun as Record<string, unknown>\n : {};\n const limitations = Array.isArray(record.limitations) ? record.limitations.flatMap((entry) => {\n if (typeof entry !== \"object\" || entry === null || Array.isArray(entry)) return [];\n const item = entry as Record<string, unknown>;\n return typeof item.scope === \"string\" && typeof item.reason === \"string\"\n ? [{ scope: item.scope, reason: item.reason }]\n : [];\n }) : [];\n return {\n status,\n checks,\n runId: typeof completeRun.id === \"string\" ? completeRun.id : undefined,\n limitations,\n binding,\n verifiedPreviewVersion\n };\n}\n\nasync function workspaceText(realm: WorkspaceRealm, path: string, maxBytes: number): Promise<string | undefined> {\n const target = await realm.fs.resolve(path, { cwd: realm.cwd });\n if (!realm.fs.contains(realm.root, target) || (await realm.fs.stat(target))?.type !== \"file\") return undefined;\n return (await readVersionedFile(realm.fs, target, maxBytes)).content;\n}\n\nasync function previewDigest(realm: WorkspaceRealm, projectRoot: string): Promise<{ readonly ready: boolean; readonly version: string }> {\n const appPath = `${projectRoot}/build/app`;\n const app = await realm.fs.resolve(appPath, { cwd: realm.cwd });\n if (!realm.fs.contains(realm.root, app) || (await realm.fs.stat(app))?.type !== \"directory\") return { ready: false, version: \"missing\" };\n const entries: string[] = [];\n let ready = false;\n const visit = async (directory: FsTarget, path: string): Promise<void> => {\n for (const entry of await realm.fs.listDir(directory)) {\n if (entry.name.startsWith(\".\") || !realm.fs.contains(app, entry.target)) continue;\n const childPath = path === \"\" ? entry.name : `${path}/${entry.name}`;\n if (entry.type === \"directory\") await visit(entry.target, childPath);\n else if (entry.type === \"file\") {\n const info = entry.version === undefined ? await realm.fs.stat(entry.target) : undefined;\n const version = entry.version ?? info?.version;\n if (version !== undefined) entries.push(`${childPath}\\0${version}`);\n if (childPath === \"index.html\") ready = true;\n }\n if (entries.length >= 5_000) return;\n }\n };\n await visit(app, \"\");\n return { ready, version: createHash(\"sha256\").update(entries.sort().join(\"\\n\")).digest(\"hex\").slice(0, 16) };\n}\n\nfunction headingTitle(content: string | undefined, fallback: string): string {\n const heading = content?.split(/\\r?\\n/u).find((line) => /^#\\s+/u.test(line));\n return heading?.replace(/^#\\s+/u, \"\").replace(/^PRODUCT_BRIEF\\s*[\u00B7\u30FB:]?\\s*/iu, \"\").trim() || fallback;\n}\n\nasync function workspaceGameProjects(\n realm: WorkspaceRealm,\n files: readonly WorkspaceFile[],\n sessionId: string,\n maxBytes: number\n): Promise<GameProjectSummary[]> {\n const roots = [...new Set(files.flatMap((file) => {\n const parts = file.path.split(\"/\");\n return parts[0] === GAME_DIRECTORY && parts[1] !== undefined ? [`${GAME_DIRECTORY}/${parts[1]}`] : [];\n }))].filter(gameRoot).sort();\n return Promise.all(roots.map(async (root) => {\n const id = root.slice(`${GAME_DIRECTORY}/`.length);\n const qaPath = `${root}/qa/verification.json`;\n const qaFile = files.find((file) => file.path === qaPath);\n // Isolate per-project metadata failures: an unreadable brief, a non-UTF-8 or oversized\n // verification file, or a build/app subtree removed mid-rebuild must degrade this one card,\n // never abort the shared workspace listing (which also carries the story and drama trees).\n const [brief, qa, preview] = await Promise.all([\n workspaceText(realm, `${root}/PRODUCT_BRIEF.md`, maxBytes).catch(() => undefined),\n workspaceText(realm, qaPath, maxBytes).catch(() => undefined),\n previewDigest(realm, root).catch(() => ({ ready: false, version: \"unavailable\" }))\n ]);\n let verification: unknown;\n try { verification = qa === undefined ? undefined : JSON.parse(qa) as unknown; }\n catch { verification = undefined; }\n const freshness = workspaceVerificationTracker.observe(`${sessionId}\\0${root}`, qaFile?.version, preview.version);\n return {\n id: `workspace:${id}`,\n root,\n title: headingTitle(brief, id),\n source: \"workspace\" as const,\n previewReady: preview.ready,\n previewUrl: preview.ready\n ? `/oh-story/game-preview/workspace/${token(sessionId)}/${token(root)}/index.html`\n : undefined,\n previewVersion: preview.version,\n verification: normalizedVerification(verification, freshness.binding, freshness.verifiedPreviewVersion)\n };\n }));\n}\n\nasync function workspaceVideoProjects(realm: WorkspaceRealm, files: readonly WorkspaceFile[], maxBytes: number): Promise<VideoProjectSummary[]> {\n const roots = [...new Set(files.flatMap((file) => {\n const root = videoProjectRoot(file.path);\n return root === undefined ? [] : [root];\n }))].sort((left, right) => left.localeCompare(right, \"zh-Hans-CN\"));\n return Promise.all(roots.map(async (root) => {\n const findPath = (name: string): string | undefined => files.find((file) => file.path.startsWith(`${root}/`) && file.path.split(\"/\").at(-1) === name)?.path;\n const readJson = async (name: string): Promise<unknown> => {\n const path = findPath(name);\n if (path === undefined) return undefined;\n const content = await workspaceText(realm, path, maxBytes).catch(() => undefined);\n if (content === undefined) return undefined;\n try { return JSON.parse(content) as unknown; }\n catch { return undefined; }\n };\n const [project, runManifest, assembly] = await Promise.all([\n readJson(\"project.json\"),\n readJson(\"recap_run_manifest.json\"),\n readJson(\"assembly_manifest.json\")\n ]);\n return summarizeVideoProject(root, files, { project, runManifest, assembly });\n }));\n}\n\nfunction bundledExampleRoot(): string {\n return resolve(defaultNovelToGameSkillRoot(), `../examples/${BUNDLED_GAME_EXAMPLE}`);\n}\n\nasync function bundledGameExample(): Promise<GameProjectSummary> {\n const root = bundledExampleRoot();\n const [example, verification, manifest] = await Promise.all([\n readNodeFile(resolve(root, \"example.json\"), \"utf8\"),\n readNodeFile(resolve(root, \"qa/verification.json\"), \"utf8\"),\n readNodeFile(resolve(defaultNovelToGameSkillRoot(), \"../manifest.json\"), \"utf8\")\n ]);\n const exampleJson = JSON.parse(example) as { readonly title?: unknown };\n const manifestJson = JSON.parse(manifest) as { readonly upstream?: { readonly commit?: unknown } };\n const previewVersion = typeof manifestJson.upstream?.commit === \"string\" ? manifestJson.upstream.commit.slice(0, 16) : \"bundled\";\n return {\n id: `example:${BUNDLED_GAME_EXAMPLE}`,\n root: `examples/${BUNDLED_GAME_EXAMPLE}`,\n title: typeof exampleJson.title === \"string\" ? exampleJson.title : \"\u91D1\u74F6\u6885 \u00B7 \u98CE\u6708\u603B\u8D26\",\n source: \"example\",\n previewReady: true,\n previewUrl: `/oh-story/game-preview/example/${BUNDLED_GAME_EXAMPLE}/index.html`,\n previewVersion,\n verification: normalizedVerification(JSON.parse(verification) as unknown, \"PINNED\", previewVersion)\n };\n}\n\nfunction previewContentType(path: string): string {\n switch (extname(path).toLocaleLowerCase()) {\n case \".html\": return \"text/html; charset=utf-8\";\n case \".css\": return \"text/css; charset=utf-8\";\n case \".js\":\n case \".mjs\": return \"text/javascript; charset=utf-8\";\n case \".json\": return \"application/json; charset=utf-8\";\n case \".svg\": return \"image/svg+xml\";\n case \".png\": return \"image/png\";\n case \".jpg\":\n case \".jpeg\": return \"image/jpeg\";\n case \".webp\": return \"image/webp\";\n case \".gif\": return \"image/gif\";\n case \".woff\": return \"font/woff\";\n case \".woff2\": return \"font/woff2\";\n case \".wasm\": return \"application/wasm\";\n case \".mp3\": return \"audio/mpeg\";\n case \".ogg\": return \"audio/ogg\";\n default: return \"application/octet-stream\";\n }\n}\n\nfunction previewAssetSources(request: IncomingMessage): string {\n const authority = request.headers.host;\n if (authority === undefined) return \"'none'\";\n const prefix = `${authority}/oh-story/game-preview/`;\n return `http://${prefix} https://${prefix}`;\n}\n\n/**\n * Emitted for EVERY preview response, not just HTML. previewContentType serves .svg as\n * image/svg+xml \u2014 an active document type \u2014 so a game that self-navigates its frame to a scripted\n * SVG would otherwise land in a document with no policy at all, while the iframe sandbox flags\n * (which do persist across that navigation) still grant it script execution. The `sandbox`\n * directive makes each response self-confining regardless of the iframe attribute.\n */\nexport function previewContentSecurityPolicy(assets: string): string {\n return [\n \"sandbox allow-scripts allow-forms allow-modals allow-downloads allow-same-origin\",\n \"default-src 'none'\",\n `script-src 'unsafe-inline' 'wasm-unsafe-eval' blob: ${assets}`,\n `style-src 'unsafe-inline' ${assets}`,\n `img-src data: blob: ${assets}`,\n `media-src data: blob: ${assets}`,\n `font-src data: ${assets}`,\n `connect-src ${assets}`,\n `worker-src blob: ${assets}`,\n `manifest-src ${assets}`,\n \"object-src 'none'\",\n \"base-uri 'none'\",\n \"form-action 'none'\",\n \"frame-ancestors 'self' http://127.0.0.1:* http://localhost:*\"\n ].join(\"; \");\n}\n\nfunction sendPreview(request: IncomingMessage, response: ServerResponse, path: string, bytes: Uint8Array): void {\n const assets = previewAssetSources(request);\n response.writeHead(200, {\n \"content-type\": previewContentType(path),\n \"content-length\": bytes.byteLength,\n \"cache-control\": \"no-store\",\n \"x-content-type-options\": \"nosniff\",\n \"cross-origin-resource-policy\": \"cross-origin\",\n \"access-control-allow-origin\": \"*\",\n \"content-security-policy\": previewContentSecurityPolicy(assets),\n });\n response.end(bytes);\n}\n\nasync function previewBytes(context: Context, pathname: string): Promise<{ readonly path: string; readonly bytes: Uint8Array }> {\n let segments: string[];\n try {\n segments = pathname.split(\"/\").slice(3).map((segment) => decodeURIComponent(segment));\n } catch {\n throw new WorkspaceHttpError(400, \"\u6E38\u620F\u9884\u89C8\u5730\u5740\u65E0\u6548\u3002\");\n }\n const kind = segments.shift();\n if (kind === \"example\") {\n const id = segments.shift();\n const path = segments.join(\"/\") || \"index.html\";\n if (id !== BUNDLED_GAME_EXAMPLE || !safeRelativePath(path)) throw new WorkspaceHttpError(404, \"\u6E38\u620F\u793A\u4F8B\u4E0D\u5B58\u5728\u3002\");\n const appRoot = resolve(bundledExampleRoot(), \"build/app\");\n const target = resolve(appRoot, path);\n const escaped = relative(appRoot, target);\n if (escaped.startsWith(\"..\") || isAbsolute(escaped)) throw new WorkspaceHttpError(403, \"\u9884\u89C8\u8D44\u6E90\u79BB\u5F00\u4E86\u6E38\u620F\u76EE\u5F55\u3002\");\n const info = await nodeStat(target).catch(() => undefined);\n if (!info?.isFile()) throw new WorkspaceHttpError(404, \"\u9884\u89C8\u8D44\u6E90\u4E0D\u5B58\u5728\u3002\");\n if (info.size > PREVIEW_FILE_LIMIT) throw new WorkspaceHttpError(413, \"\u9884\u89C8\u8D44\u6E90\u8FC7\u5927\u3002\");\n return { path, bytes: await readNodeFile(target) };\n }\n if (kind === \"workspace\") {\n const session = segments.shift();\n const project = segments.shift();\n const path = segments.join(\"/\") || \"index.html\";\n if (session === undefined || project === undefined || !safeRelativePath(path)) throw new WorkspaceHttpError(400, \"\u6E38\u620F\u9884\u89C8\u5730\u5740\u65E0\u6548\u3002\");\n const realm = await workspaceRealmForSession(context, untoken(session));\n const root = untoken(project);\n if (!gameRoot(root)) throw new WorkspaceHttpError(403, \"\u6E38\u620F\u9879\u76EE\u8DEF\u5F84\u65E0\u6548\u3002\");\n const appRoot = await realm.fs.resolve(`${root}/build/app`, { cwd: realm.cwd });\n const target = await realm.fs.resolve(`${root}/build/app/${path}`, { cwd: realm.cwd });\n if (!realm.fs.contains(realm.root, appRoot) || !realm.fs.contains(appRoot, target)) {\n throw new WorkspaceHttpError(403, \"\u9884\u89C8\u8D44\u6E90\u79BB\u5F00\u4E86\u6E38\u620F\u76EE\u5F55\u3002\");\n }\n const info = requireRegularFile(await realm.fs.stat(target));\n if (info.size !== undefined && info.size > PREVIEW_FILE_LIMIT) throw new WorkspaceHttpError(413, \"\u9884\u89C8\u8D44\u6E90\u8FC7\u5927\u3002\");\n return { path, bytes: await realm.fs.readBytes(target, undefined, PREVIEW_FILE_LIMIT) };\n }\n throw new WorkspaceHttpError(404, \"\u6E38\u620F\u9884\u89C8\u4E0D\u5B58\u5728\u3002\");\n}\n\nfunction mapFsError(error: unknown): WorkspaceHttpError | undefined {\n if (!(error instanceof FsError)) return undefined;\n switch (error.code) {\n case \"FS_NOT_FOUND\": return new WorkspaceHttpError(404, \"\u6587\u4EF6\u4E0D\u5B58\u5728\u3002\");\n case \"FS_TOO_LARGE\": return new WorkspaceHttpError(413, \"\u6587\u4EF6\u8D85\u8FC7\u5DE5\u4F5C\u53F0\u5927\u5C0F\u9650\u5236\u3002\");\n case \"FS_NOT_TEXT\":\n case \"FS_NOT_REGULAR_FILE\": return new WorkspaceHttpError(415, \"\u76EE\u6807\u4E0D\u662F\u53EF\u7F16\u8F91\u7684\u6587\u672C\u6587\u4EF6\u3002\");\n case \"FS_PERMISSION_DENIED\":\n case \"FS_SANDBOX_DENIED\": return new WorkspaceHttpError(403, \"\u5F53\u524D DSH \u6743\u9650\u4E0D\u5141\u8BB8\u4FEE\u6539\u8BE5\u6587\u4EF6\u3002\");\n case \"FS_STALE_VERSION\":\n case \"FS_NOT_OBSERVED\": return new WorkspaceHttpError(412, \"\u6587\u4EF6\u5DF2\u5728\u78C1\u76D8\u4E0A\u66F4\u65B0\u3002\u8BF7\u5904\u7406\u51B2\u7A81\u540E\u518D\u4FDD\u5B58\u3002\");\n case \"FS_ABORTED\": return new WorkspaceHttpError(409, \"\u6587\u4EF6\u64CD\u4F5C\u5DF2\u53D6\u6D88\u3002\");\n default: return new WorkspaceHttpError(500, \"DSH \u6587\u4EF6\u7CFB\u7EDF\u64CD\u4F5C\u5931\u8D25\u3002\");\n }\n}\n\nasync function handle(context: Context, request: IncomingMessage, response: ServerResponse, options: WorkspaceRouteOptions): Promise<void> {\n try {\n const url = new URL(request.url ?? \"/\", \"http://127.0.0.1\");\n const gamePreview = url.pathname.startsWith(\"/oh-story/game-preview/\");\n const trusted = gamePreview\n ? isTrustedPreviewNavigation(request, options.trustedHosts ?? [])\n : isTrustedWorkspaceRequest(request, options.trustedHosts ?? []);\n if (!trusted) throw new WorkspaceHttpError(403, \"\u8BF7\u6C42\u6765\u6E90\u4E0D\u53D7\u4FE1\u4EFB\u3002\");\n if (gamePreview && request.method === \"GET\") {\n const preview = await previewBytes(context, url.pathname);\n sendPreview(request, response, preview.path, preview.bytes);\n return;\n }\n if (url.pathname === \"/oh-story/workspace\" && request.method === \"GET\") {\n const realm = await workspaceRealm(context, url);\n const files = await listFiles(realm);\n const tracking = await metadata(realm, files, \"\u8FFD\u8E2A/_tracking-state.json\", options.maxBytes);\n const shortDrama = await metadata(realm, files, \"short-drama.json\", options.maxBytes);\n const metadataErrors = [tracking.error, shortDrama.error].filter((value): value is string => value !== undefined);\n const sessionId = url.searchParams.get(\"sessionId\");\n if (sessionId === null) throw new WorkspaceHttpError(400, \"\u7F3A\u5C11 DSH sessionId\u3002\");\n const games = [\n ...await workspaceGameProjects(realm, files, sessionId, options.maxBytes),\n await bundledGameExample()\n ];\n const videos = await workspaceVideoProjects(realm, files, options.maxBytes);\n send(response, 200, { cwd: realm.cwd, files, games, videos, tracking: tracking.value, shortDrama: shortDrama.value, metadataErrors, mode: \"dsh-session\" });\n return;\n }\n if (url.pathname === \"/oh-story/video-preflight\" && request.method === \"GET\") {\n send(response, 200, await videoPreflight());\n return;\n }\n if (url.pathname === \"/oh-story/drama-preflight\" && request.method === \"GET\") {\n send(response, 200, await dramaPreflight());\n return;\n }\n if (url.pathname === \"/oh-story/file\" && request.method === \"GET\") {\n const realm = await workspaceRealm(context, url);\n const path = url.searchParams.get(\"path\");\n if (path === null) throw new WorkspaceHttpError(400, \"\u7F3A\u5C11\u6587\u4EF6\u8DEF\u5F84\u3002\");\n const file = await readVersionedFile(realm.fs, await creativeTarget(realm, path), options.maxBytes);\n send(response, 200, { path, ...file });\n return;\n }\n if (url.pathname === \"/oh-story/media\" && (request.method === \"GET\" || request.method === \"HEAD\")) {\n const realm = await workspaceRealm(context, url);\n const path = url.searchParams.get(\"path\");\n if (path === null) throw new WorkspaceHttpError(400, \"\u7F3A\u5C11\u5A92\u4F53\u6587\u4EF6\u8DEF\u5F84\u3002\");\n const mimeType = mediaMimeTypeForPath(path);\n if (mimeType === undefined) throw new WorkspaceHttpError(415, \"\u76EE\u6807\u4E0D\u662F\u53D7\u652F\u6301\u7684\u77ED\u5267\u5A92\u4F53\u6587\u4EF6\u3002\");\n const target = await creativeTarget(realm, path, \"media\");\n const info = requireRegularFile(await realm.fs.stat(target));\n await sendWorkspaceMedia(request, response, realm, target, info, mimeType);\n return;\n }\n if (url.pathname === \"/oh-story/file\" && request.method === \"PUT\") {\n const realm = await workspaceRealm(context, url);\n const path = url.searchParams.get(\"path\");\n if (path === null) throw new WorkspaceHttpError(400, \"\u7F3A\u5C11\u6587\u4EF6\u8DEF\u5F84\u3002\");\n const input = await jsonBody(request, options.maxBytes * 6 + 1_024);\n if (typeof input.content !== \"string\") throw new WorkspaceHttpError(400, \"content \u5FC5\u987B\u662F\u5B57\u7B26\u4E32\u3002\");\n if (typeof input.baseVersion !== \"string\" || input.baseVersion === \"\") throw new WorkspaceHttpError(400, \"baseVersion \u5FC5\u987B\u662F\u6709\u6548\u7248\u672C\u3002\");\n if (Buffer.byteLength(input.content) > options.maxBytes) throw new WorkspaceHttpError(413, \"\u6587\u4EF6\u8D85\u8FC7\u5DE5\u4F5C\u53F0\u5927\u5C0F\u9650\u5236\u3002\");\n const outcome = await realm.fs.writeText(\n await creativeTarget(realm, path),\n input.content,\n { kind: \"replaceIfVersion\", version: input.baseVersion as FsVersion },\n undefined,\n realm.sandboxPolicy.resolve({ session: realm.agent.session })\n );\n send(response, 200, { path, content: outcome.after, bytes: Buffer.byteLength(outcome.after), version: outcome.version });\n return;\n }\n send(response, 404, { error: \"Oh Story route not found.\" });\n } catch (error) {\n const mapped = error instanceof WorkspaceHttpError ? error : mapFsError(error);\n if (mapped === undefined) context.logger(\"oh-story\").error(\"workspace route failed\", error);\n send(response, mapped?.status ?? 500, { error: mapped?.message ?? \"Oh Story workspace operation failed.\" });\n }\n}\n\n/** Mount the narrow editor API on DSH's official web-server extension seam. */\nexport function registerWorkspaceRoute(context: Context, options: WorkspaceRouteOptions): void {\n context.effect(() => context.webServer.register({\n kind: \"prefix\",\n path: \"/oh-story\",\n handler: (request, response) => handle(context, request, response, options)\n }), \"oh-story: DSH-session workspace API\");\n}\n", "export type GameVerificationBinding = \"CURRENT\" | \"PINNED\" | \"STALE\" | \"UNBOUND\";\n\nexport interface GameVerificationFreshness {\n readonly binding: Exclude<GameVerificationBinding, \"PINNED\">;\n readonly verifiedPreviewVersion?: string | undefined;\n}\n\ninterface Observation {\n readonly verificationRevision: string | undefined;\n readonly previewVersion: string;\n readonly bound: boolean;\n}\n\n/**\n * The upstream QA schema intentionally contains no build digest. Track what\n * this DSH process actually observes instead of pretending an imported PASS\n * belongs to the current build. A QA rewrite binds that run to the preview\n * visible at the same observation; later preview changes make it stale.\n */\nexport class WorkspaceVerificationTracker {\n readonly #observations = new Map<string, Observation>();\n\n observe(key: string, verificationRevision: string | undefined, previewVersion: string): GameVerificationFreshness {\n const previous = this.#observations.get(key);\n if (previous === undefined) {\n this.#remember(key, { verificationRevision, previewVersion, bound: false });\n return { binding: \"UNBOUND\" };\n }\n if (verificationRevision !== previous.verificationRevision) {\n const bound = verificationRevision !== undefined;\n this.#remember(key, { verificationRevision, previewVersion, bound });\n return bound ? { binding: \"CURRENT\", verifiedPreviewVersion: previewVersion } : { binding: \"UNBOUND\" };\n }\n if (!previous.bound) return { binding: \"UNBOUND\" };\n return previewVersion === previous.previewVersion\n ? { binding: \"CURRENT\", verifiedPreviewVersion: previous.previewVersion }\n : { binding: \"STALE\", verifiedPreviewVersion: previous.previewVersion };\n }\n\n #remember(key: string, observation: Observation): void {\n this.#observations.set(key, observation);\n if (this.#observations.size <= 500) return;\n const oldest = this.#observations.keys().next();\n if (!oldest.done) this.#observations.delete(oldest.value);\n }\n}\n", "import { basename, extname } from \"node:path\";\n\nexport const VIDEO_DIRECTORY = \"video-recaps\";\n\nexport interface VideoWorkspaceFile {\n readonly path: string;\n readonly bytes: number;\n readonly version: string;\n readonly kind: \"text\" | \"media\";\n readonly mimeType?: string | undefined;\n}\n\nexport interface VideoPreviewAsset {\n readonly role: \"source\" | \"edited\" | \"final\";\n readonly label: string;\n readonly path: string;\n readonly bytes: number;\n readonly version: string;\n readonly mimeType: string;\n}\n\nexport interface VideoArtifactSummary {\n readonly label: string;\n readonly path: string;\n readonly version: string;\n readonly kind: \"plan\" | \"script\" | \"subtitle\" | \"quality\" | \"manifest\";\n}\n\nexport interface VideoProjectSummary {\n readonly id: string;\n readonly root: string;\n readonly title: string;\n readonly state: \"not-started\" | \"working\" | \"waiting\" | \"ready\";\n readonly stage: string;\n readonly stageLabel: string;\n readonly nextArtifact?: string | undefined;\n readonly previews: readonly VideoPreviewAsset[];\n readonly artifacts: readonly VideoArtifactSummary[];\n}\n\nconst VIDEO_EXTENSIONS = new Set([\".mp4\", \".mov\", \".mkv\", \".webm\"]);\nconst SKIPPED_DIRECTORIES = new Set([\"frames\", \"tts_segments\", \"asr_chunks\", \"chunks\", \"cache\", \"tmp\", \".subtitle_measure\"]);\nconst VISIBLE_TEXT_FILES = new Set([\n \"project.json\",\n \"recap_run_manifest.json\",\n \"recap_phase.json\",\n \"agent_narration_brief.md\",\n \"recap_story_plan.json\",\n \"production_reference.json\",\n \"reference_measurements.json\",\n \"reference_breakdown.json\",\n \"visual_audio_board.json\",\n \"clip_plan.json\",\n \"clip_plan_validated.json\",\n \"narration.json\",\n \"narration_review.md\",\n \"tts_meta.json\",\n \"timeline.json\",\n \"assembly_manifest.json\",\n \"assembly_qc.json\",\n \"final_qc.json\",\n \"final_qc.md\",\n \"delivery_qc.json\",\n \"cut_delivery_qc.json\",\n \"recap_project.json\",\n \"resource_lock.json\",\n \"subtitles.srt\",\n \"subtitles.ass\"\n]);\n\nconst ARTIFACT_META: Readonly<Record<string, { readonly label: string; readonly kind: VideoArtifactSummary[\"kind\"] }>> = {\n \"recap_run_manifest.json\": { label: \"\u8FD0\u884C\u6E05\u5355\", kind: \"manifest\" },\n \"recap_phase.json\": { label: \"\u9636\u6BB5\u8D26\u672C\", kind: \"manifest\" },\n \"agent_narration_brief.md\": { label: \"\u89E3\u8BF4 Brief\", kind: \"plan\" },\n \"recap_story_plan.json\": { label: \"\u6545\u4E8B\u65B9\u6848\", kind: \"plan\" },\n \"production_reference.json\": { label: \"\u5236\u4F5C\u53C2\u8003\", kind: \"plan\" },\n \"reference_measurements.json\": { label: \"\u53C2\u8003\u6D4B\u91CF\", kind: \"quality\" },\n \"reference_breakdown.json\": { label: \"\u53C2\u8003\u62C6\u89E3\", kind: \"plan\" },\n \"visual_audio_board.json\": { label: \"\u97F3\u753B\u65B9\u6848\", kind: \"plan\" },\n \"clip_plan.json\": { label: \"\u526A\u8F91\u8BA1\u5212\", kind: \"plan\" },\n \"clip_plan_validated.json\": { label: \"\u5DF2\u6821\u9A8C\u526A\u8F91\u8BA1\u5212\", kind: \"plan\" },\n \"narration.json\": { label: \"\u89E3\u8BF4\u8BCD\", kind: \"script\" },\n \"narration_review.md\": { label: \"\u89E3\u8BF4\u590D\u6838\", kind: \"quality\" },\n \"timeline.json\": { label: \"\u6210\u7247\u65F6\u95F4\u7EBF\", kind: \"plan\" },\n \"assembly_manifest.json\": { label: \"\u5408\u6210\u6E05\u5355\", kind: \"manifest\" },\n \"assembly_qc.json\": { label: \"\u5408\u6210\u8D28\u68C0\", kind: \"quality\" },\n \"final_qc.json\": { label: \"\u6700\u7EC8\u8D28\u68C0\", kind: \"quality\" },\n \"final_qc.md\": { label: \"\u6700\u7EC8\u8D28\u68C0\u62A5\u544A\", kind: \"quality\" },\n \"delivery_qc.json\": { label: \"\u4EA4\u4ED8\u8D28\u68C0\", kind: \"quality\" },\n \"cut_delivery_qc.json\": { label: \"\u526A\u540E\u7247\u8D28\u68C0\", kind: \"quality\" },\n \"recap_project.json\": { label: \"\u9879\u76EE\u7ED1\u5B9A\", kind: \"manifest\" },\n \"resource_lock.json\": { label: \"\u8D44\u6E90\u9501\u5B9A\", kind: \"manifest\" },\n \"subtitles.srt\": { label: \"SRT \u5B57\u5E55\", kind: \"subtitle\" },\n \"subtitles.ass\": { label: \"ASS \u5B57\u5E55\", kind: \"subtitle\" }\n};\n\nexport function videoProjectRoot(path: string): string | undefined {\n const parts = path.split(\"/\");\n const name = parts[1];\n if (parts[0] !== VIDEO_DIRECTORY || name === undefined || name === \"\" || name === \".\" || name === \"..\" || name.startsWith(\".\") || name.includes(\"\\\\\") || name.length > 128) return undefined;\n return `${VIDEO_DIRECTORY}/${name}`;\n}\n\nexport function skipVideoDirectory(path: string): boolean {\n const parts = path.split(\"/\");\n return parts[0] === VIDEO_DIRECTORY && parts.length >= 3 && SKIPPED_DIRECTORIES.has(parts.at(-1) ?? \"\");\n}\n\nexport function visibleVideoPath(path: string): boolean {\n const root = videoProjectRoot(path);\n if (root === undefined || path === root) return false;\n const name = basename(path);\n const extension = extname(name).toLocaleLowerCase();\n if (VISIBLE_TEXT_FILES.has(name)) return true;\n if (!VIDEO_EXTENSIONS.has(extension)) return false;\n return path.startsWith(`${root}/sources/`)\n || path.startsWith(`${root}/outputs/`)\n || name === \"edited_source.mp4\"\n || /^recap_.+\\.(?:mp4|mov|webm)$/iu.test(name);\n}\n\nfunction record(value: unknown): Record<string, unknown> | undefined {\n return typeof value === \"object\" && value !== null && !Array.isArray(value) ? value as Record<string, unknown> : undefined;\n}\n\nfunction text(value: unknown): string | undefined {\n return typeof value === \"string\" && value.trim() !== \"\" ? value.trim() : undefined;\n}\n\nfunction referencedMedia(files: readonly VideoWorkspaceFile[], value: unknown): VideoWorkspaceFile | undefined {\n const path = text(value)?.replaceAll(\"\\\\\", \"/\");\n if (path === undefined) return undefined;\n const direct = files.find((file) => file.path === path || path.endsWith(`/${file.path}`));\n if (direct !== undefined) return direct;\n const name = path.split(\"/\").at(-1);\n const matching = files.filter((file) => file.path.split(\"/\").at(-1) === name);\n return matching.length === 1 ? matching[0] : undefined;\n}\n\nfunction previewAsset(file: VideoWorkspaceFile, role: VideoPreviewAsset[\"role\"], label: string): VideoPreviewAsset | undefined {\n return file.kind === \"media\" && file.mimeType?.startsWith(\"video/\") === true\n ? { role, label, path: file.path, bytes: file.bytes, version: file.version, mimeType: file.mimeType }\n : undefined;\n}\n\nexport function summarizeVideoProject(\n root: string,\n files: readonly VideoWorkspaceFile[],\n metadata: {\n readonly project?: unknown;\n readonly runManifest?: unknown;\n readonly assembly?: unknown;\n } = {}\n): VideoProjectSummary {\n const id = root.slice(`${VIDEO_DIRECTORY}/`.length);\n const projectFiles = files.filter((file) => file.path.startsWith(`${root}/`));\n const project = record(metadata.project);\n const manifest = record(metadata.runManifest);\n const settings = record(manifest?.settings);\n const assembly = record(metadata.assembly);\n const source = referencedMedia(projectFiles, manifest?.source_video)\n ?? projectFiles.find((file) => file.kind === \"media\" && file.path.startsWith(`${root}/sources/`) && file.mimeType?.startsWith(\"video/\") === true);\n const edited = projectFiles.find((file) => file.path.split(\"/\").at(-1) === \"edited_source.mp4\");\n const final = referencedMedia(projectFiles, assembly?.final_output)\n ?? projectFiles.filter((file) => file.kind === \"media\" && (file.path.startsWith(`${root}/outputs/`) || /^recap_.+\\.(?:mp4|mov|webm)$/iu.test(file.path.split(\"/\").at(-1) ?? \"\"))).at(-1);\n const previews = [\n source === undefined ? undefined : previewAsset(source, \"source\", \"\u539F\u7247\"),\n edited === undefined ? undefined : previewAsset(edited, \"edited\", \"\u526A\u540E\u7247\"),\n final === undefined ? undefined : previewAsset(final, \"final\", \"\u6700\u7EC8\u6210\u7247\")\n ].filter((value): value is VideoPreviewAsset => value !== undefined);\n const names = new Set(projectFiles.map((file) => file.path.split(\"/\").at(-1)));\n const cutMode = settings?.edit_mode === \"cut\" || names.has(\"clip_plan.json\") || edited !== undefined;\n // 0.6.0 records --audio-mode in the run manifest; source-mix and adopted-packet-copy never write\n // narration, so a cut goes straight from edited_source.mp4 to assembly and full has no pause at all.\n const narrated = (text(record(manifest?.audio)?.mode) ?? \"narration\") === \"narration\";\n let state: VideoProjectSummary[\"state\"] = \"not-started\";\n let stage = \"source\";\n let stageLabel = source === undefined ? \"\u7B49\u5F85\u5BFC\u5165\u89C6\u9891\" : \"\u53EF\u4EE5\u5F00\u59CB\";\n let nextArtifact: string | undefined;\n if (final !== undefined) {\n state = \"ready\"; stage = \"complete\"; stageLabel = \"\u6210\u7247\u5DF2\u5C31\u7EEA\";\n } else if (names.has(\"tts_meta.json\")) {\n state = \"working\"; stage = \"assemble\"; stageLabel = \"\u6B63\u5728\u5408\u6210\";\n } else if (names.has(\"narration.json\")) {\n state = \"working\"; stage = \"voiceover\"; stageLabel = \"\u914D\u97F3\u4E0E\u5408\u6210\";\n } else if (cutMode && edited !== undefined) {\n if (narrated) { state = \"waiting\"; stage = \"narration\"; stageLabel = \"\u7B49\u5F85\u89E3\u8BF4\u8BCD\"; nextArtifact = \"narration.json\"; }\n else { state = \"working\"; stage = \"assemble\"; stageLabel = \"\u6B63\u5728\u5408\u6210\"; }\n } else if (cutMode && names.has(\"clip_plan.json\")) {\n state = \"working\"; stage = \"cut\"; stageLabel = \"\u6B63\u5728\u526A\u8F91\";\n } else if (manifest !== undefined && !cutMode && !narrated) {\n state = \"working\"; stage = \"assemble\"; stageLabel = \"\u6B63\u5728\u5408\u6210\";\n } else if (manifest !== undefined) {\n state = \"waiting\";\n stage = cutMode ? \"clip-plan\" : \"narration\";\n stageLabel = cutMode ? \"\u7B49\u5F85\u526A\u8F91\u8BA1\u5212\" : \"\u7B49\u5F85\u89E3\u8BF4\u8BCD\";\n nextArtifact = cutMode ? \"clip_plan.json\" : \"narration.json\";\n }\n const artifacts = projectFiles.flatMap((file): VideoArtifactSummary[] => {\n const name = file.path.split(\"/\").at(-1) ?? \"\";\n const meta = ARTIFACT_META[name];\n return meta === undefined ? [] : [{ ...meta, path: file.path, version: file.version }];\n }).sort((left, right) => left.path.localeCompare(right.path, \"zh-Hans-CN\"));\n return {\n id,\n root,\n title: text(project?.title) ?? id,\n state,\n stage,\n stageLabel,\n nextArtifact,\n previews,\n artifacts\n };\n}\n", "import type { IncomingHttpHeaders } from \"node:http\";\n\ninterface WorkspaceTrustRequest {\n readonly headers: IncomingHttpHeaders | Headers;\n}\n\nfunction header(headers: IncomingHttpHeaders | Headers, name: string): string | undefined {\n if (headers instanceof Headers) return headers.get(name) ?? undefined;\n const value = headers[name];\n return typeof value === \"string\" ? value : undefined;\n}\n\nfunction parseAuthority(authority: string): URL | undefined {\n try { return new URL(`http://${authority}`); }\n catch { return undefined; }\n}\n\nfunction canonicalAuthority(entry: string, url: URL): string {\n const port = url.port !== \"\" ? url.port : new URL(`https://${entry}`).port;\n return port === \"\" ? url.hostname : `${url.hostname}:${port}`;\n}\n\nfunction isLoopbackHostname(hostname: string): boolean {\n if (hostname === \"localhost\" || hostname === \"[::1]\") return true;\n const parts = hostname.split(\".\");\n return parts.length === 4\n && parts[0] === \"127\"\n && parts.every((part) => /^\\d{1,3}$/u.test(part) && Number(part) <= 255);\n}\n\nfunction isTrustedAuthority(host: URL, trustedHosts: readonly string[]): boolean {\n return trustedHosts.some((entry) => {\n const candidate = parseAuthority(entry);\n if (candidate === undefined) return false;\n return canonicalAuthority(entry, candidate) === candidate.hostname\n ? candidate.hostname === host.hostname\n : candidate.host === host.host;\n });\n}\n\n/** Reject malformed declarations at plugin load instead of silently widening access. */\nexport function assertTrustedWorkspaceAuthority(entry: string): void {\n const url = parseAuthority(entry);\n if (url !== undefined && canonicalAuthority(entry, url) === entry.toLocaleLowerCase()) return;\n throw new Error(`oh-story: trustedHosts entry ${JSON.stringify(entry)} is not a bare host[:port] authority`);\n}\n\n/**\n * Same browser trust boundary as DSH's native API: every request must address a\n * loopback or explicitly trusted Host, and browser markers must be same-origin.\n */\nexport function isTrustedWorkspaceRequest(\n request: WorkspaceTrustRequest,\n trustedHosts: readonly string[]\n): boolean {\n const authority = header(request.headers, \"host\");\n if (authority === undefined) return false;\n const host = parseAuthority(authority);\n if (host === undefined) return false;\n if (!isLoopbackHostname(host.hostname) && !isTrustedAuthority(host, trustedHosts)) return false;\n if (header(request.headers, \"sec-fetch-site\") === \"cross-site\") return false;\n const origin = header(request.headers, \"origin\");\n if (origin === undefined) return true;\n try { return new URL(origin).host === host.host; }\n catch { return false; }\n}\n\n/**\n * Permit a generated-game document to navigate from one loopback alias to\n * another (127.0.0.1 \u2194 localhost). Subresources then become same-origin with\n * the isolated preview document and use the stricter path above.\n */\nexport function isTrustedPreviewNavigation(\n request: WorkspaceTrustRequest,\n trustedHosts: readonly string[]\n): boolean {\n if (isTrustedWorkspaceRequest(request, trustedHosts)) return true;\n const authority = header(request.headers, \"host\");\n if (authority === undefined) return false;\n const host = parseAuthority(authority);\n if (host === undefined || (!isLoopbackHostname(host.hostname) && !isTrustedAuthority(host, trustedHosts))) return false;\n return header(request.headers, \"origin\") === undefined\n && header(request.headers, \"sec-fetch-site\") === \"cross-site\"\n && header(request.headers, \"sec-fetch-mode\") === \"navigate\"\n && [\"document\", \"iframe\"].includes(header(request.headers, \"sec-fetch-dest\") ?? \"\");\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["dirname", "join", "resolve", "name", "name", "dirname", "resolve", "join", "readFile", "basename", "dirname", "join", "resolve", "fileURLToPath", "name", "name", "name", "record", "text", "reasons", "defineTool", "readdir", "readFile", "isAbsolute", "join", "relative", "resolve", "readdir", "join", "resolve", "relative", "isAbsolute", "readFile", "defineTool", "name", "defineTool", "defineTool", "createHash", "extname", "isAbsolute", "relative", "resolve", "basename", "name", "metadata", "name", "name", "target", "relative", "isAbsolute", "extname", "record", "createHash", "resolve"]
|
|
7
7
|
}
|