@oh-story/dsh 0.1.0
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/LICENSE +21 -0
- package/README.md +38 -0
- package/cordis.patch.yml +3 -0
- package/lib/client.js +1201 -0
- package/lib/client.js.map +7 -0
- package/lib/drama/LICENSE.upstream +21 -0
- package/lib/drama/manifest.json +1012 -0
- package/lib/drama/skills/short-drama/SKILL.md +153 -0
- package/lib/drama/skills/short-drama/agents/openai.yaml +4 -0
- package/lib/drama/skills/short-drama/assets/creator-decision.example.jsonl +4 -0
- package/lib/drama/skills/short-drama/assets/production-observation.example.jsonl +2 -0
- package/lib/drama/skills/short-drama/assets/project-template/short-drama.json +36 -0
- package/lib/drama/skills/short-drama/assets/reference-observation.example.jsonl +2 -0
- package/lib/drama/skills/short-drama/references/audience-reveal.md +74 -0
- package/lib/drama/skills/short-drama/references/contract-and-ownership.md +94 -0
- package/lib/drama/skills/short-drama/references/creator-workflow.md +82 -0
- package/lib/drama/skills/short-drama/references/form-cards/Q/347/211/210/350/241/250/350/276/276.md +73 -0
- package/lib/drama/skills/short-drama/references/form-cards//344/272/214/347/273/264/345/212/250/346/200/201/346/274/253.md +74 -0
- package/lib/drama/skills/short-drama/references/form-cards//345/233/275/346/274/253/344/272/214/346/254/241/345/205/203.md +79 -0
- package/lib/drama/skills/short-drama/references/form-cards//345/256/236/346/213/215.md +75 -0
- package/lib/drama/skills/short-drama/references/form-cards//346/260/264/345/242/250/347/254/224/350/247/246.md +85 -0
- package/lib/drama/skills/short-drama/references/form-cards//351/243/216/346/240/274/345/214/226/344/270/211/347/273/264.md +72 -0
- package/lib/drama/skills/short-drama/references/knowhow-index.md +80 -0
- package/lib/drama/skills/short-drama/references/lifecycle-commands.md +130 -0
- package/lib/drama/skills/short-drama/references/look-development.md +52 -0
- package/lib/drama/skills/short-drama/references/pickup-and-alternate.md +58 -0
- package/lib/drama/skills/short-drama/references/production-form-profiles.md +126 -0
- package/lib/drama/skills/short-drama/references/reference-roles.md +142 -0
- package/lib/drama/skills/short-drama/references/runtime-preflight.md +27 -0
- package/lib/drama/skills/short-drama/scripts/project_tool.py +1963 -0
- package/lib/drama/skills/short-drama/scripts/selftest.py +287 -0
- package/lib/drama/skills/short-drama-assets/SKILL.md +187 -0
- package/lib/drama/skills/short-drama-assets/agents/openai.yaml +4 -0
- package/lib/drama/skills/short-drama-assets/assets/character-look.example.jsonl +3 -0
- package/lib/drama/skills/short-drama-assets/assets/continuity.example.jsonl +4 -0
- package/lib/drama/skills/short-drama-assets/assets/decisions.example.jsonl +5 -0
- package/lib/drama/skills/short-drama-assets/assets/location-view.example.jsonl +3 -0
- package/lib/drama/skills/short-drama-assets/assets/occurrences.example.jsonl +5 -0
- package/lib/drama/skills/short-drama-assets/assets/prop-state.example.jsonl +3 -0
- package/lib/drama/skills/short-drama-assets/examples/minimal/characters.jsonl +2 -0
- package/lib/drama/skills/short-drama-assets/examples/minimal/looks.jsonl +2 -0
- package/lib/drama/skills/short-drama-assets/references/asset-review-checklist.md +89 -0
- package/lib/drama/skills/short-drama-assets/references/character-and-look.md +164 -0
- package/lib/drama/skills/short-drama-assets/references/continuity-delta.md +123 -0
- package/lib/drama/skills/short-drama-assets/references/identity-vs-variant.md +146 -0
- package/lib/drama/skills/short-drama-assets/references/location-and-view.md +84 -0
- package/lib/drama/skills/short-drama-assets/references/occurrence-extraction.md +111 -0
- package/lib/drama/skills/short-drama-assets/references/prop-and-state.md +107 -0
- package/lib/drama/skills/short-drama-assets/references/stage-contract.md +136 -0
- package/lib/drama/skills/short-drama-assets/references/voice-direction.md +171 -0
- package/lib/drama/skills/short-drama-assets/scripts/asset_check.py +267 -0
- package/lib/drama/skills/short-drama-assets/scripts/selftest.py +89 -0
- package/lib/drama/skills/short-drama-develop/SKILL.md +157 -0
- package/lib/drama/skills/short-drama-develop/agents/openai.yaml +4 -0
- package/lib/drama/skills/short-drama-develop/assets/adaptation-map.example.jsonl +1 -0
- package/lib/drama/skills/short-drama-develop/assets/creative-brief.md +120 -0
- package/lib/drama/skills/short-drama-develop/assets/episode-map.jsonl +1 -0
- package/lib/drama/skills/short-drama-develop/assets/story-engine.md +181 -0
- package/lib/drama/skills/short-drama-develop/references/adaptation-craft.md +219 -0
- package/lib/drama/skills/short-drama-develop/references/creative-reference-intake.md +57 -0
- package/lib/drama/skills/short-drama-develop/references/director-brief-craft.md +113 -0
- package/lib/drama/skills/short-drama-develop/references/episode-design.md +509 -0
- package/lib/drama/skills/short-drama-develop/references/genre-and-hook-playbook.md +240 -0
- package/lib/drama/skills/short-drama-develop/references/genre-cards//344/272/262/345/255/220/351/232/220/347/247/230.md +112 -0
- package/lib/drama/skills/short-drama-develop/references/genre-cards//344/273/231/344/276/240/344/277/256/347/234/237.md +51 -0
- package/lib/drama/skills/short-drama-develop/references/genre-cards//345/212/250/344/275/234/344/273/273/345/212/241.md +51 -0
- package/lib/drama/skills/short-drama-develop/references/genre-cards//345/217/244/350/243/205/346/235/203/350/260/213.md +51 -0
- package/lib/drama/skills/short-drama-develop/references/genre-cards//345/244/215/344/273/207/346/211/223/350/204/270.md +51 -0
- package/lib/drama/skills/short-drama-develop/references/genre-cards//345/256/266/345/272/255/345/205/263/347/263/273.md +51 -0
- package/lib/drama/skills/short-drama-develop/references/genre-cards//346/202/254/347/226/221/350/247/204/345/210/231.md +51 -0
- package/lib/drama/skills/short-drama-develop/references/genre-cards//347/224/237/346/264/273/346/265/201.md +51 -0
- package/lib/drama/skills/short-drama-develop/references/genre-cards//347/240/264/351/225/234/351/207/215/345/234/206.md +109 -0
- package/lib/drama/skills/short-drama-develop/references/genre-cards//350/201/214/345/234/272/345/226/234/345/211/247.md +51 -0
- package/lib/drama/skills/short-drama-develop/references/genre-cards//350/261/252/351/227/250/345/251/232/346/201/213.md +51 -0
- package/lib/drama/skills/short-drama-develop/references/genre-cards//350/272/253/344/273/275/351/224/231/344/275/215.md +51 -0
- package/lib/drama/skills/short-drama-develop/references/genre-cards.md +92 -0
- package/lib/drama/skills/short-drama-develop/references/mechanism-loop.md +282 -0
- package/lib/drama/skills/short-drama-develop/references/multi-episode-intake.md +128 -0
- package/lib/drama/skills/short-drama-develop/references/premise-devices.md +211 -0
- package/lib/drama/skills/short-drama-develop/references/reveal-reversal-payoff.md +99 -0
- package/lib/drama/skills/short-drama-develop/references/serial-character-and-memory.md +293 -0
- package/lib/drama/skills/short-drama-develop/references/stage-contract.md +88 -0
- package/lib/drama/skills/short-drama-develop/references/story-craft.md +359 -0
- package/lib/drama/skills/short-drama-develop/scripts/episode_intake.py +699 -0
- package/lib/drama/skills/short-drama-develop/scripts/selftest.py +47 -0
- package/lib/drama/skills/short-drama-image-prompts/SKILL.md +181 -0
- package/lib/drama/skills/short-drama-image-prompts/agents/openai.yaml +4 -0
- package/lib/drama/skills/short-drama-image-prompts/assets/image-prompt-spec.jsonl.md +187 -0
- package/lib/drama/skills/short-drama-image-prompts/assets/image-prompts.md +37 -0
- package/lib/drama/skills/short-drama-image-prompts/assets/lookdev-frame-spec.jsonl.md +128 -0
- package/lib/drama/skills/short-drama-image-prompts/assets/lookdev-prompts.md +31 -0
- package/lib/drama/skills/short-drama-image-prompts/examples/minimal-image-prompt-specs.jsonl +2 -0
- package/lib/drama/skills/short-drama-image-prompts/references/character-and-look.md +154 -0
- package/lib/drama/skills/short-drama-image-prompts/references/common-recipe.md +231 -0
- package/lib/drama/skills/short-drama-image-prompts/references/edit-and-revision.md +122 -0
- package/lib/drama/skills/short-drama-image-prompts/references/location-plate.md +152 -0
- package/lib/drama/skills/short-drama-image-prompts/references/look-and-state-variant.md +96 -0
- package/lib/drama/skills/short-drama-image-prompts/references/lookdev-frame.md +38 -0
- package/lib/drama/skills/short-drama-image-prompts/references/production-sheet-recipes.md +177 -0
- package/lib/drama/skills/short-drama-image-prompts/references/prop-plate.md +140 -0
- package/lib/drama/skills/short-drama-image-prompts/references/review-and-fixtures.md +92 -0
- package/lib/drama/skills/short-drama-image-prompts/references/stage-contract.md +89 -0
- package/lib/drama/skills/short-drama-image-prompts/scripts/image_prompt_check.py +443 -0
- package/lib/drama/skills/short-drama-image-prompts/scripts/selftest.py +93 -0
- package/lib/drama/skills/short-drama-novel-analyze/SKILL.md +245 -0
- package/lib/drama/skills/short-drama-novel-analyze/agents/openai.yaml +4 -0
- package/lib/drama/skills/short-drama-novel-analyze/assets/episode-candidate.example.jsonl +3 -0
- package/lib/drama/skills/short-drama-novel-analyze/references/adaptation-triage.md +116 -0
- package/lib/drama/skills/short-drama-novel-analyze/references/adaptation-value.md +124 -0
- package/lib/drama/skills/short-drama-novel-analyze/references/aggregation-and-entities.md +155 -0
- package/lib/drama/skills/short-drama-novel-analyze/references/chapter-extraction.md +141 -0
- package/lib/drama/skills/short-drama-novel-analyze/references/stage-contract.md +67 -0
- package/lib/drama/skills/short-drama-novel-analyze/scripts/novel_index.py +651 -0
- package/lib/drama/skills/short-drama-novel-analyze/scripts/selftest.py +51 -0
- package/lib/drama/skills/short-drama-produce/SKILL.md +103 -0
- package/lib/drama/skills/short-drama-produce/agents/openai.yaml +4 -0
- package/lib/drama/skills/short-drama-produce/references/adapter-contract.md +140 -0
- package/lib/drama/skills/short-drama-produce/references/providers/gpt-image-2.md +24 -0
- package/lib/drama/skills/short-drama-produce/references/providers/minimax-music.md +25 -0
- package/lib/drama/skills/short-drama-produce/references/providers/seedance.md +40 -0
- package/lib/drama/skills/short-drama-produce/scripts/fixture_adapter.py +60 -0
- package/lib/drama/skills/short-drama-produce/scripts/production_tool.py +1635 -0
- package/lib/drama/skills/short-drama-produce/scripts/provider_adapters.py +964 -0
- package/lib/drama/skills/short-drama-produce/scripts/selftest.py +134 -0
- package/lib/drama/skills/short-drama-review/SKILL.md +178 -0
- package/lib/drama/skills/short-drama-review/agents/openai.yaml +4 -0
- package/lib/drama/skills/short-drama-review/assets/finding-template.jsonl +2 -0
- package/lib/drama/skills/short-drama-review/assets/supersession-decision.example.json +42 -0
- package/lib/drama/skills/short-drama-review/assets/verdict-template.json +32 -0
- package/lib/drama/skills/short-drama-review/examples/minimal-findings.jsonl +2 -0
- package/lib/drama/skills/short-drama-review/examples/minimal-verdict.json +34 -0
- package/lib/drama/skills/short-drama-review/references/anti-template-repair.md +114 -0
- package/lib/drama/skills/short-drama-review/references/production-quality-gates.md +270 -0
- package/lib/drama/skills/short-drama-review/references/project-calibration.md +85 -0
- package/lib/drama/skills/short-drama-review/references/review-method.md +82 -0
- package/lib/drama/skills/short-drama-review/references/rubric-assets-prompts.md +115 -0
- package/lib/drama/skills/short-drama-review/references/rubric-source-analysis.md +108 -0
- package/lib/drama/skills/short-drama-review/references/rubric-story-script.md +164 -0
- package/lib/drama/skills/short-drama-review/references/rubric-visual-motion.md +166 -0
- package/lib/drama/skills/short-drama-review/references/stage-contract.md +87 -0
- package/lib/drama/skills/short-drama-review/scripts/review_check.py +325 -0
- package/lib/drama/skills/short-drama-review/scripts/selftest.py +87 -0
- package/lib/drama/skills/short-drama-storyboard/SKILL.md +264 -0
- package/lib/drama/skills/short-drama-storyboard/agents/openai.yaml +4 -0
- package/lib/drama/skills/short-drama-storyboard/assets/coverage-audition.example.jsonl +2 -0
- package/lib/drama/skills/short-drama-storyboard/assets/coverage-template.json +49 -0
- package/lib/drama/skills/short-drama-storyboard/assets/keyframe-prompts.md +32 -0
- package/lib/drama/skills/short-drama-storyboard/assets/keyframe-template.jsonl +2 -0
- package/lib/drama/skills/short-drama-storyboard/assets/revision-lineage.fragment.json +12 -0
- package/lib/drama/skills/short-drama-storyboard/assets/scene-visual-plan.example.jsonl +2 -0
- package/lib/drama/skills/short-drama-storyboard/assets/shot-template.jsonl +2 -0
- package/lib/drama/skills/short-drama-storyboard/references/blocking-playbooks.md +241 -0
- package/lib/drama/skills/short-drama-storyboard/references/coverage-audition.md +39 -0
- package/lib/drama/skills/short-drama-storyboard/references/keyframe-craft.md +169 -0
- package/lib/drama/skills/short-drama-storyboard/references/production-shot-grammar.md +264 -0
- package/lib/drama/skills/short-drama-storyboard/references/review-and-fixtures.md +70 -0
- package/lib/drama/skills/short-drama-storyboard/references/scene-visual-plan.md +39 -0
- package/lib/drama/skills/short-drama-storyboard/references/screenplay-to-keyframe-example.md +157 -0
- package/lib/drama/skills/short-drama-storyboard/references/shot-craft.md +192 -0
- package/lib/drama/skills/short-drama-storyboard/references/shot-revision-identity.md +29 -0
- package/lib/drama/skills/short-drama-storyboard/references/stage-contract.md +110 -0
- package/lib/drama/skills/short-drama-storyboard/scripts/selftest.py +191 -0
- package/lib/drama/skills/short-drama-storyboard/scripts/storyboard_check.py +824 -0
- package/lib/drama/skills/short-drama-video-prompts/SKILL.md +245 -0
- package/lib/drama/skills/short-drama-video-prompts/agents/openai.yaml +4 -0
- package/lib/drama/skills/short-drama-video-prompts/assets/coverage-scope.fragment.json +21 -0
- package/lib/drama/skills/short-drama-video-prompts/assets/delivery-container.jsonl.md +101 -0
- package/lib/drama/skills/short-drama-video-prompts/assets/motion-spec.jsonl.md +212 -0
- package/lib/drama/skills/short-drama-video-prompts/assets/motion-terminal.example.jsonl +2 -0
- package/lib/drama/skills/short-drama-video-prompts/assets/music-spec.jsonl.md +31 -0
- package/lib/drama/skills/short-drama-video-prompts/assets/performance.fragment.json +38 -0
- package/lib/drama/skills/short-drama-video-prompts/assets/video-prompts.md +46 -0
- package/lib/drama/skills/short-drama-video-prompts/examples/minimal-music-specs.jsonl +2 -0
- package/lib/drama/skills/short-drama-video-prompts/references/camera-audio-continuity.md +240 -0
- package/lib/drama/skills/short-drama-video-prompts/references/delivery-profile.md +255 -0
- package/lib/drama/skills/short-drama-video-prompts/references/generability.md +93 -0
- package/lib/drama/skills/short-drama-video-prompts/references/motion-recipe.md +304 -0
- package/lib/drama/skills/short-drama-video-prompts/references/performance-action-timing.md +191 -0
- package/lib/drama/skills/short-drama-video-prompts/references/production-prompt-grammar.md +312 -0
- package/lib/drama/skills/short-drama-video-prompts/references/review-and-fixtures.md +168 -0
- package/lib/drama/skills/short-drama-video-prompts/references/stage-contract.md +110 -0
- package/lib/drama/skills/short-drama-video-prompts/scripts/container_check.py +329 -0
- package/lib/drama/skills/short-drama-video-prompts/scripts/motion_timing_check.py +450 -0
- package/lib/drama/skills/short-drama-video-prompts/scripts/music_spec_check.py +327 -0
- package/lib/drama/skills/short-drama-video-prompts/scripts/selftest.py +82 -0
- package/lib/drama/skills/short-drama-write/SKILL.md +284 -0
- package/lib/drama/skills/short-drama-write/agents/openai.yaml +4 -0
- package/lib/drama/skills/short-drama-write/assets/beats.jsonl +2 -0
- package/lib/drama/skills/short-drama-write/assets/episode-card-standalone.json +120 -0
- package/lib/drama/skills/short-drama-write/assets/episode-card.json +55 -0
- package/lib/drama/skills/short-drama-write/assets/screenplay.md +36 -0
- package/lib/drama/skills/short-drama-write/assets/voice-record-sheet.jsonl.md +89 -0
- package/lib/drama/skills/short-drama-write/references/dialogue-craft.md +519 -0
- package/lib/drama/skills/short-drama-write/references/production-format-dialect.md +273 -0
- package/lib/drama/skills/short-drama-write/references/scene-handoff-capsule.md +51 -0
- package/lib/drama/skills/short-drama-write/references/scene-sound-dramaturgy.md +43 -0
- package/lib/drama/skills/short-drama-write/references/screenplay-format.md +260 -0
- package/lib/drama/skills/short-drama-write/references/script-craft.md +558 -0
- package/lib/drama/skills/short-drama-write/references/stage-contract.md +94 -0
- package/lib/drama/skills/short-drama-write/references/substitutable-realization.md +107 -0
- package/lib/drama/skills/short-drama-write/scripts/duration_estimate.py +309 -0
- package/lib/drama/skills/short-drama-write/scripts/screenplay_index.py +1091 -0
- package/lib/drama/skills/short-drama-write/scripts/selftest.py +229 -0
- package/lib/drama/skills/short-drama-write/scripts/voice_sheet_check.py +416 -0
- package/lib/index.js +756 -0
- package/lib/index.js.map +7 -0
- package/lib/oh-story/LICENSE.upstream +21 -0
- package/lib/oh-story/manifest.json +1351 -0
- package/lib/oh-story/roles/chapter-extractor.md +314 -0
- package/lib/oh-story/roles/character-designer.md +169 -0
- package/lib/oh-story/roles/consistency-checker.md +190 -0
- package/lib/oh-story/roles/narrative-writer.md +294 -0
- package/lib/oh-story/roles/story-architect.md +195 -0
- package/lib/oh-story/roles/story-explorer.md +364 -0
- package/lib/oh-story/roles/story-researcher.md +304 -0
- package/lib/oh-story/skills/browser-cdp/SKILL.md +175 -0
- package/lib/oh-story/skills/story/SKILL.md +116 -0
- package/lib/oh-story/skills/story/VERSION +1 -0
- package/lib/oh-story/skills/story-cover/SKILL.md +327 -0
- package/lib/oh-story/skills/story-cover/references/cover-styles.md +210 -0
- package/lib/oh-story/skills/story-deslop/SKILL.md +445 -0
- package/lib/oh-story/skills/story-deslop/references/anti-ai-writing.md +582 -0
- package/lib/oh-story/skills/story-deslop/references/banned-words.md +147 -0
- package/lib/oh-story/skills/story-deslop/scripts/check-ai-patterns.js +1371 -0
- package/lib/oh-story/skills/story-deslop/scripts/check-degeneration.js +330 -0
- package/lib/oh-story/skills/story-deslop/scripts/check-outline-copy.js +241 -0
- package/lib/oh-story/skills/story-deslop/scripts/normalize-punctuation.js +410 -0
- package/lib/oh-story/skills/story-import/SKILL.md +634 -0
- package/lib/oh-story/skills/story-import/references/character-state-reverse.md +82 -0
- package/lib/oh-story/skills/story-import/references/format-and-structure.md +169 -0
- package/lib/oh-story/skills/story-import/references/length-routing.md +134 -0
- package/lib/oh-story/skills/story-import/references/state-tracking.md +108 -0
- package/lib/oh-story/skills/story-import/references/structure-mapping-long.md +442 -0
- package/lib/oh-story/skills/story-import/references/structure-mapping-short.md +175 -0
- package/lib/oh-story/skills/story-import/references/tracking-transaction.md +161 -0
- package/lib/oh-story/skills/story-import/scripts/tracking_commit.py +1139 -0
- package/lib/oh-story/skills/story-long-analyze/SKILL.md +329 -0
- package/lib/oh-story/skills/story-long-analyze/references/deconstruction-notes.md +270 -0
- package/lib/oh-story/skills/story-long-analyze/references/material-decomposition.md +530 -0
- package/lib/oh-story/skills/story-long-analyze/references/output-templates.md +559 -0
- package/lib/oh-story/skills/story-long-analyze/references/pipeline-ops.md +80 -0
- package/lib/oh-story/skills/story-long-analyze/references/style-profile-generator.md +149 -0
- package/lib/oh-story/skills/story-long-analyze/references/style-profile-protocol.md +133 -0
- package/lib/oh-story/skills/story-long-scan/SKILL.md +342 -0
- package/lib/oh-story/skills/story-long-scan/references/genre-trends.md +197 -0
- package/lib/oh-story/skills/story-long-scan/references/publishing-guide.md +114 -0
- package/lib/oh-story/skills/story-long-scan/references/reader-profiling.md +105 -0
- package/lib/oh-story/skills/story-long-scan/references/scan-output-format.md +207 -0
- package/lib/oh-story/skills/story-long-scan/references/topic-decision.md +78 -0
- package/lib/oh-story/skills/story-long-write/SKILL.md +327 -0
- package/lib/oh-story/skills/story-long-write/references/anti-ai-writing.md +582 -0
- package/lib/oh-story/skills/story-long-write/references/artifact-protocols.md +302 -0
- package/lib/oh-story/skills/story-long-write/references/banned-words.md +147 -0
- package/lib/oh-story/skills/story-long-write/references/character-basics.md +445 -0
- package/lib/oh-story/skills/story-long-write/references/character-design-methods.md +428 -0
- package/lib/oh-story/skills/story-long-write/references/character-relations.md +385 -0
- package/lib/oh-story/skills/story-long-write/references/commercial-core-methods.md +502 -0
- package/lib/oh-story/skills/story-long-write/references/cross-book-recall.md +62 -0
- package/lib/oh-story/skills/story-long-write/references/dialogue-mastery.md +282 -0
- package/lib/oh-story/skills/story-long-write/references/emotional-arc-design.md +426 -0
- package/lib/oh-story/skills/story-long-write/references/emotional-methods.md +209 -0
- package/lib/oh-story/skills/story-long-write/references/female-audience-writing.md +188 -0
- package/lib/oh-story/skills/story-long-write/references/format-and-structure.md +169 -0
- package/lib/oh-story/skills/story-long-write/references/genre-catalog.md +480 -0
- package/lib/oh-story/skills/story-long-write/references/genre-core-mechanics.md +415 -0
- package/lib/oh-story/skills/story-long-write/references/genre-prose-cards//344/270/234/346/226/271/344/273/231/344/276/240.md +51 -0
- package/lib/oh-story/skills/story-long-write/references/genre-prose-cards//344/274/240/347/273/237/347/216/204/345/271/273.md +51 -0
- package/lib/oh-story/skills/story-long-write/references/genre-prose-cards//345/216/206/345/217/262/345/217/244/344/273/243.md +51 -0
- package/lib/oh-story/skills/story-long-write/references/genre-prose-cards//345/216/206/345/217/262/350/204/221/346/264/236.md +51 -0
- package/lib/oh-story/skills/story-long-write/references/genre-prose-cards//345/217/214/347/224/267/344/270/273.md +53 -0
- package/lib/oh-story/skills/story-long-write/references/genre-prose-cards//345/217/244/350/250/200/350/204/221/346/264/236.md +51 -0
- package/lib/oh-story/skills/story-long-write/references/genre-prose-cards//345/217/244/351/243/216/344/270/226/346/203/205.md +51 -0
- package/lib/oh-story/skills/story-long-write/references/genre-prose-cards//345/245/263/351/242/221/346/202/254/347/226/221.md +51 -0
- package/lib/oh-story/skills/story-long-write/references/genre-prose-cards//345/245/263/351/242/221/347/247/215/347/224/260.md +51 -0
- package/lib/oh-story/skills/story-long-write/references/genre-prose-cards//345/256/253/346/226/227/345/256/205/346/226/227.md +51 -0
- package/lib/oh-story/skills/story-long-write/references/genre-prose-cards//345/271/264/344/273/243.md +53 -0
- package/lib/oh-story/skills/story-long-write/references/genre-prose-cards//345/277/253/347/251/277.md +51 -0
- package/lib/oh-story/skills/story-long-write/references/genre-prose-cards//346/202/254/347/226/221/347/201/265/345/274/202.md +51 -0
- package/lib/oh-story/skills/story-long-write/references/genre-prose-cards//346/202/254/347/226/221/350/204/221/346/264/236.md +51 -0
- package/lib/oh-story/skills/story-long-write/references/genre-prose-cards//346/210/230/347/245/236/350/265/230/345/251/277.md +51 -0
- package/lib/oh-story/skills/story-long-write/references/genre-prose-cards//346/212/227/346/210/230/350/260/215/346/210/230.md +51 -0
- package/lib/oh-story/skills/story-long-write/references/genre-prose-cards//346/230/237/345/205/211/347/222/200/347/222/250.md +51 -0
- package/lib/oh-story/skills/story-long-write/references/genre-prose-cards//346/260/221/345/233/275/350/250/200/346/203/205.md +51 -0
- package/lib/oh-story/skills/story-long-write/references/genre-prose-cards//346/270/270/346/210/217/344/275/223/350/202/262.md +51 -0
- package/lib/oh-story/skills/story-long-write/references/genre-prose-cards//347/216/204/345/271/273/350/204/221/346/264/236.md +53 -0
- package/lib/oh-story/skills/story-long-write/references/genre-prose-cards//347/216/204/345/271/273/350/250/200/346/203/205.md +51 -0
- package/lib/oh-story/skills/story-long-write/references/genre-prose-cards//347/216/260/350/250/200/350/204/221/346/264/236.md +51 -0
- package/lib/oh-story/skills/story-long-write/references/genre-prose-cards//347/247/221/345/271/273/346/234/253/344/270/226.md +51 -0
- package/lib/oh-story/skills/story-long-write/references/genre-prose-cards//350/201/214/345/234/272/345/251/232/346/201/213.md +51 -0
- package/lib/oh-story/skills/story-long-write/references/genre-prose-cards//350/245/277/346/226/271/345/245/207/345/271/273.md +51 -0
- package/lib/oh-story/skills/story-long-write/references/genre-prose-cards//350/261/252/351/227/250/346/200/273/350/243/201.md +53 -0
- package/lib/oh-story/skills/story-long-write/references/genre-prose-cards//351/203/275/345/270/202/344/277/256/347/234/237.md +51 -0
- package/lib/oh-story/skills/story-long-write/references/genre-prose-cards//351/203/275/345/270/202/346/227/245/345/270/270.md +53 -0
- package/lib/oh-story/skills/story-long-write/references/genre-prose-cards//351/203/275/345/270/202/347/247/215/347/224/260.md +51 -0
- package/lib/oh-story/skills/story-long-write/references/genre-prose-cards//351/203/275/345/270/202/350/204/221/346/264/236.md +53 -0
- package/lib/oh-story/skills/story-long-write/references/genre-prose-cards//351/203/275/345/270/202/351/253/230/346/255/246.md +53 -0
- package/lib/oh-story/skills/story-long-write/references/genre-prose-cards//351/235/222/346/230/245/347/224/234/345/256/240.md +51 -0
- package/lib/oh-story/skills/story-long-write/references/genre-prose-cards.md +91 -0
- package/lib/oh-story/skills/story-long-write/references/genre-readers.md +235 -0
- package/lib/oh-story/skills/story-long-write/references/genre-writing-formulas.md +444 -0
- package/lib/oh-story/skills/story-long-write/references/hooks-chapter.md +225 -0
- package/lib/oh-story/skills/story-long-write/references/hooks-paragraph.md +146 -0
- package/lib/oh-story/skills/story-long-write/references/hooks-suspense.md +352 -0
- package/lib/oh-story/skills/story-long-write/references/opening-design.md +349 -0
- package/lib/oh-story/skills/story-long-write/references/outline-conflict.md +457 -0
- package/lib/oh-story/skills/story-long-write/references/outline-methods.md +287 -0
- package/lib/oh-story/skills/story-long-write/references/outline-rhythm.md +389 -0
- package/lib/oh-story/skills/story-long-write/references/outline-structure-theory.md +326 -0
- package/lib/oh-story/skills/story-long-write/references/plot-core-methods.md +522 -0
- package/lib/oh-story/skills/story-long-write/references/plot-emotion-system.md +354 -0
- package/lib/oh-story/skills/story-long-write/references/plot-frameworks.md +711 -0
- package/lib/oh-story/skills/story-long-write/references/plot-special-topics.md +622 -0
- package/lib/oh-story/skills/story-long-write/references/quality-checklist.md +184 -0
- package/lib/oh-story/skills/story-long-write/references/reader-contract-and-progression.md +109 -0
- package/lib/oh-story/skills/story-long-write/references/reversal-toolkit.md +349 -0
- package/lib/oh-story/skills/story-long-write/references/state-tracking.md +108 -0
- package/lib/oh-story/skills/story-long-write/references/style-combat-face.md +409 -0
- package/lib/oh-story/skills/story-long-write/references/style-craft.md +347 -0
- package/lib/oh-story/skills/story-long-write/references/style-genre-modules.md +510 -0
- package/lib/oh-story/skills/story-long-write/references/tracking-transaction.md +161 -0
- package/lib/oh-story/skills/story-long-write/references/workflow-chapter.md +140 -0
- package/lib/oh-story/skills/story-long-write/references/workflow-daily.md +171 -0
- package/lib/oh-story/skills/story-long-write/references/workflow-revision.md +99 -0
- package/lib/oh-story/skills/story-long-write/references/workflow-setup.md +284 -0
- package/lib/oh-story/skills/story-long-write/references/writing-craft.md +421 -0
- package/lib/oh-story/skills/story-long-write/scripts/check-ai-patterns.js +1371 -0
- package/lib/oh-story/skills/story-long-write/scripts/check-degeneration.js +330 -0
- package/lib/oh-story/skills/story-long-write/scripts/check-outline-copy.js +241 -0
- package/lib/oh-story/skills/story-long-write/scripts/normalize-punctuation.js +410 -0
- package/lib/oh-story/skills/story-long-write/scripts/tracking_commit.py +1139 -0
- package/lib/oh-story/skills/story-review/SKILL.md +483 -0
- package/lib/oh-story/skills/story-review/references/anti-ai-writing.md +582 -0
- package/lib/oh-story/skills/story-review/references/banned-words.md +147 -0
- package/lib/oh-story/skills/story-review/references/character-relations.md +385 -0
- package/lib/oh-story/skills/story-review/references/dialogue-mastery.md +282 -0
- package/lib/oh-story/skills/story-review/references/plot-core-methods.md +522 -0
- package/lib/oh-story/skills/story-review/references/quality-checklist.md +250 -0
- package/lib/oh-story/skills/story-review/references/quality-rubric.md +55 -0
- package/lib/oh-story/skills/story-review/references/rubrics/fanqie.md +18 -0
- package/lib/oh-story/skills/story-review/references/rubrics/qidian.md +19 -0
- package/lib/oh-story/skills/story-review/references/rubrics/zhihu.md +20 -0
- package/lib/oh-story/skills/story-review/references/tracking-transaction.md +161 -0
- package/lib/oh-story/skills/story-review/scripts/check-ai-patterns.js +1371 -0
- package/lib/oh-story/skills/story-review/scripts/check-degeneration.js +330 -0
- package/lib/oh-story/skills/story-review/scripts/normalize-punctuation.js +410 -0
- package/lib/oh-story/skills/story-review/scripts/tracking_commit.py +1139 -0
- package/lib/oh-story/skills/story-setup/SKILL.md +495 -0
- package/lib/oh-story/skills/story-setup/references/agent-references/anti-ai-writing.md +582 -0
- package/lib/oh-story/skills/story-setup/references/agent-references/banned-words.md +147 -0
- package/lib/oh-story/skills/story-setup/references/agent-references/character-basics.md +445 -0
- package/lib/oh-story/skills/story-setup/references/agent-references/character-design-methods.md +428 -0
- package/lib/oh-story/skills/story-setup/references/agent-references/character-relations.md +385 -0
- package/lib/oh-story/skills/story-setup/references/agent-references/dialogue-mastery.md +282 -0
- package/lib/oh-story/skills/story-setup/references/agent-references/emotional-arc-design.md +426 -0
- package/lib/oh-story/skills/story-setup/references/agent-references/emotional-methods.md +179 -0
- package/lib/oh-story/skills/story-setup/references/agent-references/format-and-structure.md +169 -0
- package/lib/oh-story/skills/story-setup/references/agent-references/genre-catalog.md +480 -0
- package/lib/oh-story/skills/story-setup/references/agent-references/genre-core-mechanics.md +415 -0
- package/lib/oh-story/skills/story-setup/references/agent-references/genre-prose-cards//344/270/234/346/226/271/344/273/231/344/276/240.md +51 -0
- package/lib/oh-story/skills/story-setup/references/agent-references/genre-prose-cards//344/274/240/347/273/237/347/216/204/345/271/273.md +51 -0
- package/lib/oh-story/skills/story-setup/references/agent-references/genre-prose-cards//345/216/206/345/217/262/345/217/244/344/273/243.md +51 -0
- package/lib/oh-story/skills/story-setup/references/agent-references/genre-prose-cards//345/216/206/345/217/262/350/204/221/346/264/236.md +51 -0
- package/lib/oh-story/skills/story-setup/references/agent-references/genre-prose-cards//345/217/214/347/224/267/344/270/273.md +53 -0
- package/lib/oh-story/skills/story-setup/references/agent-references/genre-prose-cards//345/217/244/350/250/200/350/204/221/346/264/236.md +51 -0
- package/lib/oh-story/skills/story-setup/references/agent-references/genre-prose-cards//345/217/244/351/243/216/344/270/226/346/203/205.md +51 -0
- package/lib/oh-story/skills/story-setup/references/agent-references/genre-prose-cards//345/245/263/351/242/221/346/202/254/347/226/221.md +51 -0
- package/lib/oh-story/skills/story-setup/references/agent-references/genre-prose-cards//345/245/263/351/242/221/347/247/215/347/224/260.md +51 -0
- package/lib/oh-story/skills/story-setup/references/agent-references/genre-prose-cards//345/256/253/346/226/227/345/256/205/346/226/227.md +51 -0
- package/lib/oh-story/skills/story-setup/references/agent-references/genre-prose-cards//345/271/264/344/273/243.md +53 -0
- package/lib/oh-story/skills/story-setup/references/agent-references/genre-prose-cards//345/277/253/347/251/277.md +51 -0
- package/lib/oh-story/skills/story-setup/references/agent-references/genre-prose-cards//346/202/254/347/226/221/347/201/265/345/274/202.md +51 -0
- package/lib/oh-story/skills/story-setup/references/agent-references/genre-prose-cards//346/202/254/347/226/221/350/204/221/346/264/236.md +51 -0
- package/lib/oh-story/skills/story-setup/references/agent-references/genre-prose-cards//346/210/230/347/245/236/350/265/230/345/251/277.md +51 -0
- package/lib/oh-story/skills/story-setup/references/agent-references/genre-prose-cards//346/212/227/346/210/230/350/260/215/346/210/230.md +51 -0
- package/lib/oh-story/skills/story-setup/references/agent-references/genre-prose-cards//346/230/237/345/205/211/347/222/200/347/222/250.md +51 -0
- package/lib/oh-story/skills/story-setup/references/agent-references/genre-prose-cards//346/260/221/345/233/275/350/250/200/346/203/205.md +51 -0
- package/lib/oh-story/skills/story-setup/references/agent-references/genre-prose-cards//346/270/270/346/210/217/344/275/223/350/202/262.md +51 -0
- package/lib/oh-story/skills/story-setup/references/agent-references/genre-prose-cards//347/216/204/345/271/273/350/204/221/346/264/236.md +53 -0
- package/lib/oh-story/skills/story-setup/references/agent-references/genre-prose-cards//347/216/204/345/271/273/350/250/200/346/203/205.md +51 -0
- package/lib/oh-story/skills/story-setup/references/agent-references/genre-prose-cards//347/216/260/350/250/200/350/204/221/346/264/236.md +51 -0
- package/lib/oh-story/skills/story-setup/references/agent-references/genre-prose-cards//347/247/221/345/271/273/346/234/253/344/270/226.md +51 -0
- package/lib/oh-story/skills/story-setup/references/agent-references/genre-prose-cards//350/201/214/345/234/272/345/251/232/346/201/213.md +51 -0
- package/lib/oh-story/skills/story-setup/references/agent-references/genre-prose-cards//350/245/277/346/226/271/345/245/207/345/271/273.md +51 -0
- package/lib/oh-story/skills/story-setup/references/agent-references/genre-prose-cards//350/261/252/351/227/250/346/200/273/350/243/201.md +53 -0
- package/lib/oh-story/skills/story-setup/references/agent-references/genre-prose-cards//351/203/275/345/270/202/344/277/256/347/234/237.md +51 -0
- package/lib/oh-story/skills/story-setup/references/agent-references/genre-prose-cards//351/203/275/345/270/202/346/227/245/345/270/270.md +53 -0
- package/lib/oh-story/skills/story-setup/references/agent-references/genre-prose-cards//351/203/275/345/270/202/347/247/215/347/224/260.md +51 -0
- package/lib/oh-story/skills/story-setup/references/agent-references/genre-prose-cards//351/203/275/345/270/202/350/204/221/346/264/236.md +53 -0
- package/lib/oh-story/skills/story-setup/references/agent-references/genre-prose-cards//351/203/275/345/270/202/351/253/230/346/255/246.md +53 -0
- package/lib/oh-story/skills/story-setup/references/agent-references/genre-prose-cards//351/235/222/346/230/245/347/224/234/345/256/240.md +51 -0
- package/lib/oh-story/skills/story-setup/references/agent-references/genre-prose-cards.md +91 -0
- package/lib/oh-story/skills/story-setup/references/agent-references/genre-readers.md +235 -0
- package/lib/oh-story/skills/story-setup/references/agent-references/genre-writing-formulas.md +444 -0
- package/lib/oh-story/skills/story-setup/references/agent-references/hooks-chapter.md +225 -0
- package/lib/oh-story/skills/story-setup/references/agent-references/hooks-suspense.md +352 -0
- package/lib/oh-story/skills/story-setup/references/agent-references/opening-design.md +349 -0
- package/lib/oh-story/skills/story-setup/references/agent-references/outline-conflict.md +457 -0
- package/lib/oh-story/skills/story-setup/references/agent-references/outline-methods.md +287 -0
- package/lib/oh-story/skills/story-setup/references/agent-references/outline-rhythm.md +389 -0
- package/lib/oh-story/skills/story-setup/references/agent-references/plot-core-methods.md +522 -0
- package/lib/oh-story/skills/story-setup/references/agent-references/quality-checklist.md +247 -0
- package/lib/oh-story/skills/story-setup/references/agent-references/reversal-toolkit.md +349 -0
- package/lib/oh-story/skills/story-setup/references/agent-references/style-combat-face.md +409 -0
- package/lib/oh-story/skills/story-setup/references/agent-references/style-genre-modules.md +510 -0
- package/lib/oh-story/skills/story-setup/references/agent-references/writing-craft.md +421 -0
- package/lib/oh-story/skills/story-short-analyze/SKILL.md +278 -0
- package/lib/oh-story/skills/story-short-analyze/references/anti-ai-writing.md +582 -0
- package/lib/oh-story/skills/story-short-analyze/references/banned-words.md +147 -0
- package/lib/oh-story/skills/story-short-analyze/references/character-basics.md +453 -0
- package/lib/oh-story/skills/story-short-analyze/references/character-design-methods.md +438 -0
- package/lib/oh-story/skills/story-short-analyze/references/character-relations.md +395 -0
- package/lib/oh-story/skills/story-short-analyze/references/deconstruction-examples.md +79 -0
- package/lib/oh-story/skills/story-short-analyze/references/genre-catalog.md +490 -0
- package/lib/oh-story/skills/story-short-analyze/references/genre-core-mechanics.md +425 -0
- package/lib/oh-story/skills/story-short-analyze/references/genre-readers.md +245 -0
- package/lib/oh-story/skills/story-short-analyze/references/genre-writing-formulas.md +453 -0
- package/lib/oh-story/skills/story-short-analyze/references/genre-writing-techniques.md +475 -0
- package/lib/oh-story/skills/story-short-analyze/references/hooks-chapter.md +225 -0
- package/lib/oh-story/skills/story-short-analyze/references/hooks-paragraph.md +146 -0
- package/lib/oh-story/skills/story-short-analyze/references/hooks-suspense.md +352 -0
- package/lib/oh-story/skills/story-short-analyze/references/material-decomposition.md +685 -0
- package/lib/oh-story/skills/story-short-analyze/references/output-contract.md +165 -0
- package/lib/oh-story/skills/story-short-analyze/references/output-templates.md +561 -0
- package/lib/oh-story/skills/story-short-analyze/references/quality-checklist.md +242 -0
- package/lib/oh-story/skills/story-short-analyze/references/real-market-data.md +90 -0
- package/lib/oh-story/skills/story-short-analyze/references/zhihu-style.md +54 -0
- package/lib/oh-story/skills/story-short-scan/SKILL.md +212 -0
- package/lib/oh-story/skills/story-short-scan/references/real-market-data.md +90 -0
- package/lib/oh-story/skills/story-short-write/SKILL.md +433 -0
- package/lib/oh-story/skills/story-short-write/references/banned-words.md +147 -0
- package/lib/oh-story/skills/story-short-write/references/cross-book-recall.md +62 -0
- package/lib/oh-story/skills/story-short-write/references/dialogue-mastery.md +282 -0
- package/lib/oh-story/skills/story-short-write/references/emotional-methods.md +179 -0
- package/lib/oh-story/skills/story-short-write/references/genre-styles//344/270/226/346/203/205/346/211/223/350/204/270.md +159 -0
- package/lib/oh-story/skills/story-short-write/references/genre-styles//345/217/214/347/224/267/344/270/273.md +156 -0
- package/lib/oh-story/skills/story-short-write/references/genre-styles//345/244/215/344/273/207/346/211/223/350/204/270.md +163 -0
- package/lib/oh-story/skills/story-short-write/references/genre-styles//345/256/205/346/226/227/345/256/253/346/226/227.md +167 -0
- package/lib/oh-story/skills/story-short-write/references/genre-styles//346/200/273/350/243/201/350/261/252/351/227/250.md +178 -0
- package/lib/oh-story/skills/story-short-write/references/genre-styles//346/202/254/347/226/221.md +166 -0
- package/lib/oh-story/skills/story-short-write/references/genre-styles//346/260/221/344/277/227/346/200/252/350/260/210.md +159 -0
- package/lib/oh-story/skills/story-short-write/references/genre-styles//346/262/231/351/233/225/350/204/221/346/264/236.md +151 -0
- package/lib/oh-story/skills/story-short-write/references/genre-styles//347/224/234/345/256/240.md +153 -0
- package/lib/oh-story/skills/story-short-write/references/genre-styles//350/277/275/345/246/273/347/201/253/350/221/254/345/234/272.md +210 -0
- package/lib/oh-story/skills/story-short-write/references/genre-writing-formulas.md +444 -0
- package/lib/oh-story/skills/story-short-write/references/genre-writing-techniques.md +488 -0
- package/lib/oh-story/skills/story-short-write/references/hooks-chapter.md +225 -0
- package/lib/oh-story/skills/story-short-write/references/hooks-paragraph.md +146 -0
- package/lib/oh-story/skills/story-short-write/references/hooks-suspense.md +352 -0
- package/lib/oh-story/skills/story-short-write/references/output-contract.md +165 -0
- package/lib/oh-story/skills/story-short-write/references/quality-checklist.md +222 -0
- package/lib/oh-story/skills/story-short-write/references/reversal-toolkit.md +349 -0
- package/lib/oh-story/skills/story-short-write/references/short-craft.md +185 -0
- package/lib/oh-story/skills/story-short-write/references/short-deslop.md +133 -0
- package/lib/oh-story/skills/story-short-write/references/short-format.md +167 -0
- package/lib/oh-story/skills/story-short-write/references/submission-craft.md +35 -0
- package/lib/oh-story/skills/story-short-write/references/villain-and-reveal.md +158 -0
- package/lib/oh-story/skills/story-short-write/references/writing-workflow.md +153 -0
- package/lib/oh-story/skills/story-short-write/scripts/check-ai-patterns.js +1371 -0
- package/lib/oh-story/skills/story-short-write/scripts/check-degeneration.js +330 -0
- package/lib/oh-story/skills/story-short-write/scripts/check-outline-copy.js +241 -0
- package/lib/oh-story/skills/story-short-write/scripts/normalize-punctuation.js +410 -0
- package/lib/types/client/file-activity.d.ts +30 -0
- package/lib/types/client/file-activity.d.ts.map +1 -0
- package/lib/types/client/file-tree.d.ts +20 -0
- package/lib/types/client/file-tree.d.ts.map +1 -0
- package/lib/types/client/index.d.ts +12 -0
- package/lib/types/client/index.d.ts.map +1 -0
- package/lib/types/client/jsonl-preview.d.ts +15 -0
- package/lib/types/client/jsonl-preview.d.ts.map +1 -0
- package/lib/types/client/markdown-preview.d.ts +38 -0
- package/lib/types/client/markdown-preview.d.ts.map +1 -0
- package/lib/types/index.d.ts +25 -0
- package/lib/types/index.d.ts.map +1 -0
- package/lib/types/native-hooks.d.ts +16 -0
- package/lib/types/native-hooks.d.ts.map +1 -0
- package/lib/types/role-provider.d.ts +6 -0
- package/lib/types/role-provider.d.ts.map +1 -0
- package/lib/types/role-tool.d.ts +10 -0
- package/lib/types/role-tool.d.ts.map +1 -0
- package/lib/types/skill-provider.d.ts +15 -0
- package/lib/types/skill-provider.d.ts.map +1 -0
- package/lib/types/workspace-request-trust.d.ts +13 -0
- package/lib/types/workspace-request-trust.d.ts.map +1 -0
- package/lib/types/workspace-route.d.ts +10 -0
- package/lib/types/workspace-route.d.ts.map +1 -0
- package/lib/types/workspace-security.d.ts +9 -0
- package/lib/types/workspace-security.d.ts.map +1 -0
- package/package.json +107 -0
package/lib/index.js
ADDED
|
@@ -0,0 +1,756 @@
|
|
|
1
|
+
// src/index.ts
|
|
2
|
+
import z from "@deepseek-ai/schemastery";
|
|
3
|
+
|
|
4
|
+
// src/skill-provider.ts
|
|
5
|
+
import { readdir, readFile } from "node:fs/promises";
|
|
6
|
+
import { basename, dirname, isAbsolute, join, relative, resolve } from "node:path";
|
|
7
|
+
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
8
|
+
import {
|
|
9
|
+
BUNDLED_SKILL_RANK
|
|
10
|
+
} from "@deepseek-ai/dsh-skill";
|
|
11
|
+
var STORY_PROVIDER_NAME = "oh-story";
|
|
12
|
+
var DRAMA_PROVIDER_NAME = "short-drama";
|
|
13
|
+
var INVOCATION = { modelInvocable: true, userInvocable: true };
|
|
14
|
+
var DSH_SKILL_BRIDGE = [
|
|
15
|
+
"<oh-story-dsh-integration>",
|
|
16
|
+
"This Skill is a native contribution to the current DeepSeek Harness session.",
|
|
17
|
+
"DSH owns the workspace, model, preset, permissions, Session Log, tools, subagents, cancellation, resume, and Agent UI.",
|
|
18
|
+
"Never start another Agent runtime, session transport, Dashboard, SSE stream, polling loop, or model configuration.",
|
|
19
|
+
"All seven upstream Oh Story specialist Roles are bundled. Invoke one with oh_story_role and a self-contained prompt.",
|
|
20
|
+
"Never inspect .claude/agents, .codex/agents, .opencode/agents, or .story-deployed to decide whether a Role is available.",
|
|
21
|
+
"Use only DSH-visible tools. DSH sandbox and permission policy remain authoritative.",
|
|
22
|
+
"</oh-story-dsh-integration>"
|
|
23
|
+
].join("\n");
|
|
24
|
+
var DSH_SKILL_OVERRIDES = {
|
|
25
|
+
story: "The \u5C0F\u8BF4 workspace is an official DSH conversation view. Never start or open a second web application.",
|
|
26
|
+
"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/ZCode/OpenClaw/Reasonix files or a .story-deployed marker.",
|
|
27
|
+
"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.",
|
|
28
|
+
"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.",
|
|
29
|
+
"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.",
|
|
30
|
+
"story-import": "All named Roles are provided through oh_story_role. Do not require story-setup to deploy them.",
|
|
31
|
+
"story-deslop": "Use the bundled narrative-writer Role through oh_story_role when specialist review is useful. Never inspect platform agent directories.",
|
|
32
|
+
"story-short-analyze": "Use oh_story_role for specialist analysis. Never inspect platform agent directories or require external Agent deployment.",
|
|
33
|
+
"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.",
|
|
34
|
+
"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.",
|
|
35
|
+
"story-cover": "Use only image-generation or HTTP capabilities visible in the current DSH preset. Never assume a separate Codex or Claude runtime."
|
|
36
|
+
};
|
|
37
|
+
var DSH_DRAMA_BRIDGE = [
|
|
38
|
+
"<short-drama-dsh-integration>",
|
|
39
|
+
"This Skill is a native contribution to the current DeepSeek Harness session.",
|
|
40
|
+
"DSH owns the workspace, model, preset, permissions, Session Log, tools, approvals, cancellation, resume, and Agent UI.",
|
|
41
|
+
"The \u77ED\u5267 tab is the creator workspace. Never start dashboard_server.py, another web server, Dashboard, Agent runtime, session transport, or model configuration.",
|
|
42
|
+
"Use only tools visible in the current DSH preset and preserve the upstream project ownership, freshness, review, and explicit production-confirmation contracts.",
|
|
43
|
+
"Production credentials remain outside project files. Never treat a prior acceptance, preview, continuation request, or budget discussion as confirmation for a paid production run.",
|
|
44
|
+
"</short-drama-dsh-integration>"
|
|
45
|
+
].join("\n");
|
|
46
|
+
var DSH_DRAMA_OVERRIDES = {
|
|
47
|
+
"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.",
|
|
48
|
+
"short-drama-produce": "Use an upstream adapter only after the creator explicitly confirms the exact current job. DSH permissions and approval UI remain authoritative."
|
|
49
|
+
};
|
|
50
|
+
var DSH_NATIVE_SKILLS = {
|
|
51
|
+
story: `# story \u2014 DSH \u5C0F\u8BF4\u6D41\u7A0B\u5165\u53E3
|
|
52
|
+
|
|
53
|
+
\u5728\u5F53\u524D DSH Session \u5185\u5224\u65AD\u7528\u6237\u610F\u56FE\uFF0C\u5E76\u52A0\u8F7D\u6700\u5339\u914D\u7684 Oh Story Skill\uFF1A
|
|
54
|
+
|
|
55
|
+
- \u65B0\u5EFA\u6216\u4FEE\u590D\u5C0F\u8BF4\u5DE5\u7A0B\uFF1Astory-setup
|
|
56
|
+
- \u957F\u7BC7\u9009\u9898/\u626B\u699C/\u62C6\u6587/\u65E5\u66F4\uFF1Astory-long-scan\u3001story-long-analyze\u3001story-long-write
|
|
57
|
+
- \u77ED\u7BC7\u9009\u9898/\u62C6\u6587/\u5199\u4F5C\uFF1Astory-short-scan\u3001story-short-analyze\u3001story-short-write
|
|
58
|
+
- \u5BFC\u5165\u5DF2\u6709\u4F5C\u54C1\uFF1Astory-import
|
|
59
|
+
- \u5BA1\u7A3F\u4E0E\u53BB AI \u5473\uFF1Astory-review\u3001story-deslop
|
|
60
|
+
- \u5C01\u9762\uFF1Astory-cover
|
|
61
|
+
|
|
62
|
+
\u610F\u56FE\u660E\u786E\u65F6\u76F4\u63A5\u8FDB\u5165\u5BF9\u5E94 Skill\uFF1B\u4E0D\u660E\u786E\u65F6\u53EA\u95EE\u4E00\u4E2A\u4F1A\u6539\u53D8\u6D41\u7A0B\u7684\u95EE\u9898\u3002\u9879\u76EE\u6587\u4EF6\u3001
|
|
63
|
+
Agent\u3001\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
|
|
64
|
+
\u89C6\u56FE\u67E5\u770B\uFF0CAgent \u8FC7\u7A0B\u901A\u8FC7\u53F3\u4FA7\u52A8\u6001\u680F\u6216\u5B98\u65B9 Chat \u67E5\u770B\u3002\u7981\u6B62\u542F\u52A8\u72EC\u7ACB Dashboard\u3002`,
|
|
65
|
+
"story-setup": `# story-setup \u2014 DSH \u539F\u751F\u5C0F\u8BF4\u5DE5\u7A0B\u521D\u59CB\u5316
|
|
66
|
+
|
|
67
|
+
\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
|
|
68
|
+
|
|
69
|
+
1. \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
|
|
70
|
+
2. \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
|
|
71
|
+
3. \u957F\u7BC7\u6309\u9700\u5EFA\u7ACB \u6B63\u6587/\u3001\u8BBE\u5B9A/\u3001\u5927\u7EB2/\u3001\u8FFD\u8E2A/\uFF0C\u5E76\u51C6\u5907\u8FFD\u8E2A/_tracking-state.json\uFF1B
|
|
72
|
+
\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
|
|
73
|
+
4. \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
|
|
74
|
+
\u751F\u6210 .claude\u3001.codex\u3001.opencode\u3001.zcode\u3001AGENTS.md \u6216 .story-deployed\u3002
|
|
75
|
+
5. \u590D\u8FF0\u521B\u5EFA\u3001\u4FDD\u7559\u548C\u5F85\u7528\u6237\u786E\u8BA4\u7684\u6587\u4EF6\u3002\u4E0D\u8981\u914D\u7F6E\u6A21\u578B\u3001\u6743\u9650\u3001Hooks \u6216 Session\u3002
|
|
76
|
+
|
|
77
|
+
\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
|
|
78
|
+
\u53EA\u52A0\u8F7D\u5F53\u524D\u4EFB\u52A1\u9700\u8981\u7684\u6587\u4EF6\u3002`,
|
|
79
|
+
"browser-cdp": `# browser-cdp \u2014 DSH \u6D4F\u89C8\u5668\u80FD\u529B\u9002\u914D
|
|
80
|
+
|
|
81
|
+
\u672C Skill \u4E0D\u542F\u52A8 Chrome\u3001CDP \u7AEF\u53E3\u3001\u72EC\u7ACB\u6D4F\u89C8\u5668 Host \u6216 setup-cdp-chrome.js\u3002
|
|
82
|
+
\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
|
|
83
|
+
\u699C\u5355\u91C7\u96C6\u548C\u8D44\u6599\u6838\u9A8C\u3002\u4FDD\u6301\u4EE5\u4E0B\u539F\u5219\uFF1A
|
|
84
|
+
|
|
85
|
+
1. \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
|
|
86
|
+
2. \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
|
|
87
|
+
3. \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
|
|
88
|
+
4. \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`,
|
|
89
|
+
"story-long-scan": `# story-long-scan \u2014 DSH \u539F\u751F\u957F\u7BC7\u626B\u699C
|
|
90
|
+
|
|
91
|
+
\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
|
|
92
|
+
\u8BBF\u95EE\u63A7\u5236\u6216\u7AD9\u70B9\u9650\u5236\u3002
|
|
93
|
+
|
|
94
|
+
1. \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
|
|
95
|
+
2. \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
|
|
96
|
+
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
|
|
97
|
+
3. \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
|
|
98
|
+
\u4E0D\u628A\u641C\u7D22\u6458\u8981\u3001\u63A8\u65AD\u6216\u8FC7\u671F\u7F13\u5B58\u5199\u6210\u9875\u9762\u4E8B\u5B9E\u3002
|
|
99
|
+
4. \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
|
|
100
|
+
\u5DEE\u5F02\u5316\u5143\u7D20\u5206\u6790\u3002\u9700\u8981\u51B3\u7B56\u95E8\u7981\u65F6\u4F7F\u7528 references/topic-decision.md\u3002
|
|
101
|
+
5. \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
|
|
102
|
+
|
|
103
|
+
\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
|
|
104
|
+
\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`,
|
|
105
|
+
"story-short-scan": `# story-short-scan \u2014 DSH \u539F\u751F\u77ED\u7BC7\u626B\u699C
|
|
106
|
+
|
|
107
|
+
\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
|
|
108
|
+
\u6216 token\uFF0C\u4E5F\u4E0D\u7ED5\u8FC7\u9A8C\u8BC1\u7801\u3001\u767B\u5F55\u6216\u8BBF\u95EE\u63A7\u5236\u3002
|
|
109
|
+
|
|
110
|
+
1. \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
|
|
111
|
+
2. \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
|
|
112
|
+
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
|
|
113
|
+
3. \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
|
|
114
|
+
4. \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
|
|
115
|
+
\u7ED9\u6BCF\u4E2A\u8D8B\u52BF\u6807\u6CE8\u8BC1\u636E\u5F3A\u5EA6\u3001\u9971\u548C\u98CE\u9669\u548C\u6709\u6548\u671F\u3002
|
|
116
|
+
5. \u8F93\u51FA\u5E02\u573A\u6982\u51B5\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\u548C\u590D\u626B\u65F6\u95F4\u3002
|
|
117
|
+
|
|
118
|
+
\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
|
|
119
|
+
\u4E0D\u8981\u542F\u52A8 CDP\u3001\u72EC\u7ACB\u6D4F\u89C8\u5668\u6216\u5E76\u884C\u8FD0\u884C\u65F6\u3002`
|
|
120
|
+
};
|
|
121
|
+
function frontmatterValue(frontmatter, key) {
|
|
122
|
+
const match = new RegExp(`^${key}:\\s*(.+)$`, "mu").exec(frontmatter);
|
|
123
|
+
const raw = match?.[1]?.trim();
|
|
124
|
+
if (raw === void 0) return void 0;
|
|
125
|
+
if (raw.startsWith('"') && raw.endsWith('"')) {
|
|
126
|
+
try {
|
|
127
|
+
return JSON.parse(raw);
|
|
128
|
+
} catch {
|
|
129
|
+
return raw.slice(1, -1);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
return raw.replace(/^['"]|['"]$/gu, "");
|
|
133
|
+
}
|
|
134
|
+
function parseBundledSkill(source) {
|
|
135
|
+
const match = /^---\r?\n([\s\S]*?)\r?\n---\r?\n?/u.exec(source);
|
|
136
|
+
if (match?.[1] === void 0) throw new Error("Bundled skill is missing YAML frontmatter.");
|
|
137
|
+
const name2 = frontmatterValue(match[1], "name");
|
|
138
|
+
const description = frontmatterValue(match[1], "description");
|
|
139
|
+
if (!name2 || !/^[a-z0-9]+(?:-[a-z0-9]+)*$/u.test(name2)) throw new Error("Bundled skill has an invalid name.");
|
|
140
|
+
if (!description) throw new Error(`Bundled skill "${name2}" has no description.`);
|
|
141
|
+
return { name: name2, description, content: source.slice(match[0].length) };
|
|
142
|
+
}
|
|
143
|
+
function dshSkillContent(name2, content) {
|
|
144
|
+
const override = DSH_SKILL_OVERRIDES[name2];
|
|
145
|
+
const native = DSH_NATIVE_SKILLS[name2];
|
|
146
|
+
return `${DSH_SKILL_BRIDGE}${override === void 0 ? "" : `
|
|
147
|
+
<skill-specific-dsh-override>${override}</skill-specific-dsh-override>`}
|
|
148
|
+
|
|
149
|
+
${native ?? content}`;
|
|
150
|
+
}
|
|
151
|
+
function defaultBundledSkillRoot() {
|
|
152
|
+
const current = dirname(fileURLToPath(import.meta.url));
|
|
153
|
+
return basename(current) === "src" ? resolve(current, "../../knowledge/oh-story/skills") : resolve(current, "oh-story/skills");
|
|
154
|
+
}
|
|
155
|
+
function defaultDramaSkillRoot() {
|
|
156
|
+
const current = dirname(fileURLToPath(import.meta.url));
|
|
157
|
+
return basename(current) === "src" ? resolve(current, "../../knowledge/drama/skills") : resolve(current, "drama/skills");
|
|
158
|
+
}
|
|
159
|
+
function createBundledSkillProvider(providerName, skillRoot, content) {
|
|
160
|
+
const root = resolve(skillRoot);
|
|
161
|
+
return {
|
|
162
|
+
name: providerName,
|
|
163
|
+
async list() {
|
|
164
|
+
const directories = (await readdir(root, { withFileTypes: true })).filter((entry) => entry.isDirectory()).map((entry) => entry.name).sort();
|
|
165
|
+
return Promise.all(directories.map(async (directory) => {
|
|
166
|
+
const path = join(root, directory, "SKILL.md");
|
|
167
|
+
const parsed = parseBundledSkill(await readFile(path, "utf8"));
|
|
168
|
+
if (parsed.name !== directory) throw new Error(`Bundled skill directory "${directory}" does not match name "${parsed.name}".`);
|
|
169
|
+
return {
|
|
170
|
+
name: parsed.name,
|
|
171
|
+
description: parsed.description,
|
|
172
|
+
invocation: INVOCATION,
|
|
173
|
+
provider: providerName,
|
|
174
|
+
source: "bundled",
|
|
175
|
+
resourceBase: { kind: "directory", path: join(root, directory) },
|
|
176
|
+
rank: BUNDLED_SKILL_RANK,
|
|
177
|
+
locator: pathToFileURL(path),
|
|
178
|
+
path
|
|
179
|
+
};
|
|
180
|
+
}));
|
|
181
|
+
},
|
|
182
|
+
async get(candidate) {
|
|
183
|
+
if (candidate.provider !== providerName || typeof candidate.path !== "string") return void 0;
|
|
184
|
+
const path = resolve(candidate.path);
|
|
185
|
+
const relativePath = relative(root, path);
|
|
186
|
+
if (relativePath === "" || relativePath.startsWith("..") || isAbsolute(relativePath)) {
|
|
187
|
+
throw new Error("Bundled skill locator escaped the packaged skill root.");
|
|
188
|
+
}
|
|
189
|
+
const parsed = parseBundledSkill(await readFile(path, "utf8"));
|
|
190
|
+
if (parsed.name !== candidate.name) return void 0;
|
|
191
|
+
return {
|
|
192
|
+
name: parsed.name,
|
|
193
|
+
description: parsed.description,
|
|
194
|
+
invocation: INVOCATION,
|
|
195
|
+
provider: providerName,
|
|
196
|
+
source: "bundled",
|
|
197
|
+
resourceBase: { kind: "directory", path: join(root, parsed.name) },
|
|
198
|
+
path,
|
|
199
|
+
content: content(parsed.name, parsed.content)
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
function createOhStorySkillProvider(skillRoot = defaultBundledSkillRoot()) {
|
|
205
|
+
return createBundledSkillProvider(STORY_PROVIDER_NAME, skillRoot, dshSkillContent);
|
|
206
|
+
}
|
|
207
|
+
function dshDramaSkillContent(name2, content) {
|
|
208
|
+
const override = DSH_DRAMA_OVERRIDES[name2];
|
|
209
|
+
return `${DSH_DRAMA_BRIDGE}${override === void 0 ? "" : `
|
|
210
|
+
<skill-specific-dsh-override>${override}</skill-specific-dsh-override>`}
|
|
211
|
+
|
|
212
|
+
${content}`;
|
|
213
|
+
}
|
|
214
|
+
function createDramaSkillProvider(skillRoot = defaultDramaSkillRoot()) {
|
|
215
|
+
return createBundledSkillProvider(DRAMA_PROVIDER_NAME, skillRoot, dshDramaSkillContent);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// src/native-hooks.ts
|
|
219
|
+
import { access, readdir as readdir2 } from "node:fs/promises";
|
|
220
|
+
import { isAbsolute as isAbsolute2, relative as relative2, resolve as resolve2, sep } from "node:path";
|
|
221
|
+
import { createUserMessage } from "@deepseek-ai/dsh-llm";
|
|
222
|
+
var MUTATION_TOOLS = /* @__PURE__ */ new Set(["write", "edit", "str_replace_editor"]);
|
|
223
|
+
function mutationPath(name2, args) {
|
|
224
|
+
if (!MUTATION_TOOLS.has(name2) || typeof args !== "object" || args === null || Array.isArray(args)) return void 0;
|
|
225
|
+
const record = args;
|
|
226
|
+
if (name2 === "str_replace_editor") {
|
|
227
|
+
if (!(/* @__PURE__ */ new Set(["create", "str_replace", "insert"])).has(String(record.command))) return void 0;
|
|
228
|
+
return typeof record.path === "string" && record.path.trim() !== "" ? record.path : void 0;
|
|
229
|
+
}
|
|
230
|
+
return typeof record.file_path === "string" && record.file_path.trim() !== "" ? record.file_path : void 0;
|
|
231
|
+
}
|
|
232
|
+
function detectStoryMutation(name2, args, cwd) {
|
|
233
|
+
const path = mutationPath(name2, args);
|
|
234
|
+
if (cwd === void 0 || path === void 0) return void 0;
|
|
235
|
+
const root = resolve2(cwd);
|
|
236
|
+
const absolute = isAbsolute2(path) ? resolve2(path) : resolve2(root, path);
|
|
237
|
+
const offset = relative2(root, absolute);
|
|
238
|
+
if (offset === ".." || offset.startsWith(`..${sep}`) || isAbsolute2(offset)) return void 0;
|
|
239
|
+
const normalized = offset.replaceAll("\\", "/");
|
|
240
|
+
if (!normalized.startsWith("\u6B63\u6587/")) return void 0;
|
|
241
|
+
const chapterText = /第0*(\d+)章/u.exec(normalized)?.[1];
|
|
242
|
+
return { root, path: normalized, ...chapterText === void 0 ? {} : { chapter: Number(chapterText) } };
|
|
243
|
+
}
|
|
244
|
+
function storyMutation(exec) {
|
|
245
|
+
return detectStoryMutation(exec.name, exec.arguments, exec.agent?.session.header.cwd);
|
|
246
|
+
}
|
|
247
|
+
async function exists(path) {
|
|
248
|
+
return access(path).then(() => true, () => false);
|
|
249
|
+
}
|
|
250
|
+
async function hasChapterOutline(root, chapter) {
|
|
251
|
+
const entries = await readdir2(resolve2(root, "\u5927\u7EB2"), { withFileTypes: true }).catch(() => []);
|
|
252
|
+
return entries.some((entry) => entry.isFile() && Number(/^细纲_第0*(\d+)章.*\.md$/u.exec(entry.name)?.[1]) === chapter);
|
|
253
|
+
}
|
|
254
|
+
async function validateStoryMutation(mutation) {
|
|
255
|
+
const hasLongFormLayout = await exists(resolve2(mutation.root, "\u5927\u7EB2")) || await exists(resolve2(mutation.root, "\u8FFD\u8E2A"));
|
|
256
|
+
if (!hasLongFormLayout) return void 0;
|
|
257
|
+
if (!await exists(resolve2(mutation.root, "\u8FFD\u8E2A/_tracking-state.json"))) {
|
|
258
|
+
return void 0;
|
|
259
|
+
}
|
|
260
|
+
if (mutation.chapter !== void 0 && !await hasChapterOutline(mutation.root, mutation.chapter)) {
|
|
261
|
+
return `Oh Story \u963B\u6B62\u5199\u5165\u7B2C ${String(mutation.chapter)} \u7AE0\uFF1A\u672A\u627E\u5230\u5BF9\u5E94\u7684 \u5927\u7EB2/\u7EC6\u7EB2_\u7B2CXXX\u7AE0*.md\u3002\u8BF7\u5148\u5B8C\u6210\u7EC6\u7EB2\u3002`;
|
|
262
|
+
}
|
|
263
|
+
return void 0;
|
|
264
|
+
}
|
|
265
|
+
async function decideStoryMutation(exec, next) {
|
|
266
|
+
const mutation = storyMutation(exec);
|
|
267
|
+
if (mutation === void 0) return next();
|
|
268
|
+
const reason = await validateStoryMutation(mutation);
|
|
269
|
+
if (reason !== void 0) return { kind: "deny", reason };
|
|
270
|
+
return next();
|
|
271
|
+
}
|
|
272
|
+
function registerOhStoryHooks(context) {
|
|
273
|
+
context.on("tools/pre-execute", decideStoryMutation);
|
|
274
|
+
context.on("tools/post-execute", async (exec, result, next) => {
|
|
275
|
+
const mutation = storyMutation(exec);
|
|
276
|
+
const downstream = await next();
|
|
277
|
+
if (mutation === void 0 || result.isError || downstream.kind !== "accept") return downstream;
|
|
278
|
+
const reminder = createUserMessage({
|
|
279
|
+
source: { kind: "plugin", plugin: "oh-story" },
|
|
280
|
+
content: [{
|
|
281
|
+
type: "text",
|
|
282
|
+
text: `<oh-story-post-write>\u6B63\u6587 ${mutation.path} \u5DF2\u53D8\u66F4\u3002\u7EE7\u7EED\u5F53\u524D\u6B65\u9AA4\u524D\u6838\u5BF9\u5E76\u66F4\u65B0 _tracking-state.json \u53CA\u5BF9\u5E94\u6D3E\u751F Tracking \u89C6\u56FE\uFF1B\u4E0D\u8981\u628A\u8FD9\u6761\u63D0\u9192\u5F53\u4F5C\u7528\u6237\u7684\u65B0\u5199\u4F5C\u8981\u6C42\u3002</oh-story-post-write>`
|
|
283
|
+
}]
|
|
284
|
+
});
|
|
285
|
+
return {
|
|
286
|
+
...downstream,
|
|
287
|
+
additionalContexts: [...downstream.additionalContexts ?? [], reminder]
|
|
288
|
+
};
|
|
289
|
+
});
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
// src/role-tool.ts
|
|
293
|
+
import { defineTool } from "@deepseek-ai/dsh-tools";
|
|
294
|
+
|
|
295
|
+
// src/role-provider.ts
|
|
296
|
+
import { readFile as readFile2 } from "node:fs/promises";
|
|
297
|
+
import { basename as basename2, dirname as dirname2, join as join2, resolve as resolve3 } from "node:path";
|
|
298
|
+
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
299
|
+
var OH_STORY_ROLE_NAMES = [
|
|
300
|
+
"chapter-extractor",
|
|
301
|
+
"character-designer",
|
|
302
|
+
"consistency-checker",
|
|
303
|
+
"narrative-writer",
|
|
304
|
+
"story-architect",
|
|
305
|
+
"story-explorer",
|
|
306
|
+
"story-researcher"
|
|
307
|
+
];
|
|
308
|
+
function roleBody(source) {
|
|
309
|
+
const frontmatter = /^---\r?\n[\s\S]*?\r?\n---\r?\n?/u.exec(source);
|
|
310
|
+
return source.slice(frontmatter?.[0].length ?? 0).trim();
|
|
311
|
+
}
|
|
312
|
+
function defaultBundledRoleRoot() {
|
|
313
|
+
const current = dirname2(fileURLToPath2(import.meta.url));
|
|
314
|
+
return basename2(current) === "src" ? resolve3(current, "../../knowledge/oh-story/roles") : resolve3(current, "oh-story/roles");
|
|
315
|
+
}
|
|
316
|
+
async function loadBundledRole(name2, roleRoot = defaultBundledRoleRoot(), execution = "tool-free") {
|
|
317
|
+
const body = roleBody(await readFile2(join2(resolve3(roleRoot), `${name2}.md`), "utf8"));
|
|
318
|
+
if (body.length === 0) throw new Error(`Bundled role "${name2}" is empty.`);
|
|
319
|
+
const integration = execution === "tool-free" ? [
|
|
320
|
+
"You are running inside an Oh Story review-required DSH collaboration. The caller supplies every permitted input in the prompt.",
|
|
321
|
+
"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.",
|
|
322
|
+
"Return only the output contract requested by the caller; never claim to have changed the project."
|
|
323
|
+
] : [
|
|
324
|
+
"You are running as a native oh-story-dsh specialist. The current DSH workspace and visible tool set are your complete authority boundary.",
|
|
325
|
+
"Never inspect or require legacy .claude/.opencode/.codex agent deployment files; this exact pinned Role is already active.",
|
|
326
|
+
"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."
|
|
327
|
+
];
|
|
328
|
+
return [
|
|
329
|
+
`OH_STORY_DSH_ROLE:${name2}`,
|
|
330
|
+
...integration,
|
|
331
|
+
"",
|
|
332
|
+
body
|
|
333
|
+
].join("\n");
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
// src/role-tool.ts
|
|
337
|
+
var OH_STORY_ROLE_TOOL_NAME = "oh_story_role";
|
|
338
|
+
var roleTools = {
|
|
339
|
+
"chapter-extractor": ["read", "glob", "grep"],
|
|
340
|
+
"character-designer": ["read", "glob", "grep"],
|
|
341
|
+
"consistency-checker": ["read", "glob", "grep"],
|
|
342
|
+
"narrative-writer": ["read", "glob", "grep", "bash"],
|
|
343
|
+
"story-architect": ["read", "glob", "grep"],
|
|
344
|
+
"story-explorer": ["read", "glob", "grep"],
|
|
345
|
+
"story-researcher": ["read", "glob", "grep", "bash", "web_search", "web_fetch"]
|
|
346
|
+
};
|
|
347
|
+
function roleToolFilter(role) {
|
|
348
|
+
return { allow: roleTools[role] };
|
|
349
|
+
}
|
|
350
|
+
function resultText(output) {
|
|
351
|
+
return output.map((block) => block.type === "text" ? block.text : JSON.stringify(block)).join("\n");
|
|
352
|
+
}
|
|
353
|
+
async function createOhStoryRoleTool() {
|
|
354
|
+
const personas = /* @__PURE__ */ new Map();
|
|
355
|
+
await Promise.all(OH_STORY_ROLE_NAMES.map(async (role) => {
|
|
356
|
+
personas.set(role, await loadBundledRole(role, void 0, "native-tools"));
|
|
357
|
+
}));
|
|
358
|
+
return defineTool({
|
|
359
|
+
name: OH_STORY_ROLE_TOOL_NAME,
|
|
360
|
+
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.",
|
|
361
|
+
parameters: {
|
|
362
|
+
role: {
|
|
363
|
+
type: "string",
|
|
364
|
+
required: true,
|
|
365
|
+
enum: OH_STORY_ROLE_NAMES,
|
|
366
|
+
description: "The exact Oh Story Role to run."
|
|
367
|
+
},
|
|
368
|
+
prompt: {
|
|
369
|
+
type: "string",
|
|
370
|
+
required: true,
|
|
371
|
+
description: "A self-contained task. The child inherits the current DSH workspace but not the current in-flight turn."
|
|
372
|
+
}
|
|
373
|
+
},
|
|
374
|
+
output: {
|
|
375
|
+
schema: {
|
|
376
|
+
type: "object",
|
|
377
|
+
additionalProperties: false,
|
|
378
|
+
properties: {
|
|
379
|
+
role: { type: "string", required: true, enum: OH_STORY_ROLE_NAMES },
|
|
380
|
+
runId: { type: "string", required: true },
|
|
381
|
+
content: { type: "array", required: true, items: { type: "json" } }
|
|
382
|
+
}
|
|
383
|
+
},
|
|
384
|
+
render: (_args, value) => [{ type: "text", text: resultText(value.content) }]
|
|
385
|
+
},
|
|
386
|
+
isConcurrencySafe: () => true,
|
|
387
|
+
async execute(args, exec) {
|
|
388
|
+
if (exec.agent === void 0) throw new Error("oh_story_role requires a calling DSH Agent.");
|
|
389
|
+
const persona = personas.get(args.role);
|
|
390
|
+
if (persona === void 0) throw new Error(`Oh Story Role ${args.role} is not bundled.`);
|
|
391
|
+
const allowed = roleToolFilter(args.role).allow.filter((name2) => exec.agent?.ctx.tools.get(name2, exec.agent) !== void 0);
|
|
392
|
+
const run = await exec.agent.ctx.subagents.start("spawn", {
|
|
393
|
+
label: `oh-story:${args.role}`,
|
|
394
|
+
prompt: [{ type: "text", text: args.prompt }],
|
|
395
|
+
parent: exec.agent,
|
|
396
|
+
persona,
|
|
397
|
+
toolFilter: { allow: allowed },
|
|
398
|
+
maxDepth: 1,
|
|
399
|
+
signal: exec.signal
|
|
400
|
+
});
|
|
401
|
+
try {
|
|
402
|
+
const result = await run.result;
|
|
403
|
+
if (result.stopReason !== "completed") {
|
|
404
|
+
throw new Error(`Oh Story Role ${args.role} ended with ${result.stopReason}${result.diagnostic === void 0 ? "" : `: ${result.diagnostic}`}`);
|
|
405
|
+
}
|
|
406
|
+
return {
|
|
407
|
+
role: args.role,
|
|
408
|
+
runId: run.id,
|
|
409
|
+
content: result.output
|
|
410
|
+
};
|
|
411
|
+
} finally {
|
|
412
|
+
await run.dispose();
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
});
|
|
416
|
+
}
|
|
417
|
+
async function registerOhStoryRoleTool(context) {
|
|
418
|
+
const definition = await createOhStoryRoleTool();
|
|
419
|
+
let dispose;
|
|
420
|
+
const mount = () => {
|
|
421
|
+
dispose ??= context.tools.register(definition);
|
|
422
|
+
};
|
|
423
|
+
const unmount = () => {
|
|
424
|
+
dispose?.();
|
|
425
|
+
dispose = void 0;
|
|
426
|
+
};
|
|
427
|
+
context.on("subagent/provider-added", (provider) => {
|
|
428
|
+
if (provider.name === "spawn") mount();
|
|
429
|
+
});
|
|
430
|
+
context.on("subagent/provider-removed", (name2) => {
|
|
431
|
+
if (name2 === "spawn") unmount();
|
|
432
|
+
});
|
|
433
|
+
if (context.subagents.getProvider("spawn") !== void 0) mount();
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
// src/workspace-route.ts
|
|
437
|
+
import { createHash, randomUUID } from "node:crypto";
|
|
438
|
+
import { mkdir, readFile as readFile3, readdir as readdir3, rename, rm, stat, writeFile } from "node:fs/promises";
|
|
439
|
+
import { dirname as dirname3, extname, join as join3, relative as relative4, resolve as resolve5 } from "node:path";
|
|
440
|
+
import { SessionId } from "@deepseek-ai/dsh-session";
|
|
441
|
+
|
|
442
|
+
// src/workspace-security.ts
|
|
443
|
+
import { lstat, realpath } from "node:fs/promises";
|
|
444
|
+
import { isAbsolute as isAbsolute3, relative as relative3, resolve as resolve4, sep as sep2 } from "node:path";
|
|
445
|
+
var PathSecurityError = class extends Error {
|
|
446
|
+
constructor(message) {
|
|
447
|
+
super(message);
|
|
448
|
+
this.name = "PathSecurityError";
|
|
449
|
+
}
|
|
450
|
+
};
|
|
451
|
+
function isInside(root, candidate) {
|
|
452
|
+
const offset = relative3(root, candidate);
|
|
453
|
+
return offset === "" || !offset.startsWith(`..${sep2}`) && offset !== ".." && !isAbsolute3(offset);
|
|
454
|
+
}
|
|
455
|
+
async function canonicalWorkspaceRoot(root) {
|
|
456
|
+
const canonical = await realpath(root);
|
|
457
|
+
const info = await lstat(canonical);
|
|
458
|
+
if (!info.isDirectory()) throw new PathSecurityError("Workspace root must be a directory.");
|
|
459
|
+
return canonical;
|
|
460
|
+
}
|
|
461
|
+
async function resolveWorkspacePath(root, relativePath, options = {}) {
|
|
462
|
+
if (relativePath.includes("\0") || isAbsolute3(relativePath) || /^[A-Za-z]:[\\/]/u.test(relativePath)) {
|
|
463
|
+
throw new PathSecurityError("Only workspace-relative paths are allowed.");
|
|
464
|
+
}
|
|
465
|
+
const segments = relativePath.replaceAll("\\", "/").split("/");
|
|
466
|
+
if (segments.some((segment) => segment === ".." || segment === "")) {
|
|
467
|
+
throw new PathSecurityError("Path traversal and empty segments are not allowed.");
|
|
468
|
+
}
|
|
469
|
+
const canonicalRoot = await canonicalWorkspaceRoot(root);
|
|
470
|
+
const candidate = resolve4(canonicalRoot, ...segments);
|
|
471
|
+
if (!isInside(canonicalRoot, candidate)) throw new PathSecurityError("Path escapes the workspace.");
|
|
472
|
+
let cursor = canonicalRoot;
|
|
473
|
+
for (let index = 0; index < segments.length; index += 1) {
|
|
474
|
+
cursor = resolve4(cursor, segments[index] ?? "");
|
|
475
|
+
try {
|
|
476
|
+
const info = await lstat(cursor);
|
|
477
|
+
if (info.isSymbolicLink()) {
|
|
478
|
+
const target = await realpath(cursor);
|
|
479
|
+
if (!isInside(canonicalRoot, target)) throw new PathSecurityError("Symbolic link escapes the workspace.");
|
|
480
|
+
cursor = target;
|
|
481
|
+
}
|
|
482
|
+
if (index < segments.length - 1 && !info.isDirectory()) throw new PathSecurityError("A path parent is not a directory.");
|
|
483
|
+
if (index === segments.length - 1 && options.expect !== void 0) {
|
|
484
|
+
if (options.expect === "file" && !info.isFile()) throw new PathSecurityError("Expected a regular file.");
|
|
485
|
+
if (options.expect === "directory" && !info.isDirectory()) throw new PathSecurityError("Expected a directory.");
|
|
486
|
+
}
|
|
487
|
+
} catch (error) {
|
|
488
|
+
if (error instanceof PathSecurityError) throw error;
|
|
489
|
+
const code = error instanceof Error && "code" in error ? String(error.code) : "";
|
|
490
|
+
if (code === "ENOENT" && options.allowMissing === true && index === segments.length - 1) return cursor;
|
|
491
|
+
throw error;
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
const finalPath = await realpath(cursor);
|
|
495
|
+
if (!isInside(canonicalRoot, finalPath)) throw new PathSecurityError("Resolved path escapes the workspace.");
|
|
496
|
+
return finalPath;
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
// src/workspace-request-trust.ts
|
|
500
|
+
function header(headers, name2) {
|
|
501
|
+
if (headers instanceof Headers) return headers.get(name2) ?? void 0;
|
|
502
|
+
const value = headers[name2];
|
|
503
|
+
return typeof value === "string" ? value : void 0;
|
|
504
|
+
}
|
|
505
|
+
function parseAuthority(authority) {
|
|
506
|
+
try {
|
|
507
|
+
return new URL(`http://${authority}`);
|
|
508
|
+
} catch {
|
|
509
|
+
return void 0;
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
function canonicalAuthority(entry, url) {
|
|
513
|
+
const port = url.port !== "" ? url.port : new URL(`https://${entry}`).port;
|
|
514
|
+
return port === "" ? url.hostname : `${url.hostname}:${port}`;
|
|
515
|
+
}
|
|
516
|
+
function isLoopbackHostname(hostname) {
|
|
517
|
+
if (hostname === "localhost" || hostname === "[::1]") return true;
|
|
518
|
+
const parts = hostname.split(".");
|
|
519
|
+
return parts.length === 4 && parts[0] === "127" && parts.every((part) => /^\d{1,3}$/u.test(part) && Number(part) <= 255);
|
|
520
|
+
}
|
|
521
|
+
function isTrustedAuthority(host, trustedHosts) {
|
|
522
|
+
return trustedHosts.some((entry) => {
|
|
523
|
+
const candidate = parseAuthority(entry);
|
|
524
|
+
if (candidate === void 0) return false;
|
|
525
|
+
return canonicalAuthority(entry, candidate) === candidate.hostname ? candidate.hostname === host.hostname : candidate.host === host.host;
|
|
526
|
+
});
|
|
527
|
+
}
|
|
528
|
+
function assertTrustedWorkspaceAuthority(entry) {
|
|
529
|
+
const url = parseAuthority(entry);
|
|
530
|
+
if (url !== void 0 && canonicalAuthority(entry, url) === entry.toLocaleLowerCase()) return;
|
|
531
|
+
throw new Error(`oh-story: trustedHosts entry ${JSON.stringify(entry)} is not a bare host[:port] authority`);
|
|
532
|
+
}
|
|
533
|
+
function isTrustedWorkspaceRequest(request, trustedHosts) {
|
|
534
|
+
const authority = header(request.headers, "host");
|
|
535
|
+
if (authority === void 0) return false;
|
|
536
|
+
const host = parseAuthority(authority);
|
|
537
|
+
if (host === void 0) return false;
|
|
538
|
+
if (!isLoopbackHostname(host.hostname) && !isTrustedAuthority(host, trustedHosts)) return false;
|
|
539
|
+
if (header(request.headers, "sec-fetch-site") === "cross-site") return false;
|
|
540
|
+
const origin = header(request.headers, "origin");
|
|
541
|
+
if (origin === void 0) return true;
|
|
542
|
+
try {
|
|
543
|
+
return new URL(origin).host === host.host;
|
|
544
|
+
} catch {
|
|
545
|
+
return false;
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
// src/workspace-route.ts
|
|
550
|
+
var STORY_DIRECTORIES = ["\u6B63\u6587", "\u5927\u7EB2", "\u8BBE\u5B9A", "\u8FFD\u8E2A", "\u5BF9\u6807", "\u53C2\u8003\u8D44\u6599"];
|
|
551
|
+
var DRAMA_DIRECTORIES = ["\u8F93\u5165", "\u9879\u76EE\u5F00\u53D1", "\u8BBE\u5B9A\u96C6", "\u5267\u96C6", "\u4EA4\u4ED8", "\u521B\u4F5C\u8005\u51B3\u7B56", "\u5BA1\u67E5"];
|
|
552
|
+
var CREATIVE_DIRECTORIES = [...STORY_DIRECTORIES, ...DRAMA_DIRECTORIES];
|
|
553
|
+
var ROOT_FILES = /* @__PURE__ */ new Set(["short-drama.json"]);
|
|
554
|
+
var EDITABLE_EXTENSIONS = /* @__PURE__ */ new Set([".md", ".txt", ".json", ".jsonl"]);
|
|
555
|
+
var WorkspaceHttpError = class extends Error {
|
|
556
|
+
constructor(status, message) {
|
|
557
|
+
super(message);
|
|
558
|
+
this.status = status;
|
|
559
|
+
}
|
|
560
|
+
status;
|
|
561
|
+
};
|
|
562
|
+
function send(response, status, value) {
|
|
563
|
+
const body = `${JSON.stringify(value)}
|
|
564
|
+
`;
|
|
565
|
+
response.writeHead(status, {
|
|
566
|
+
"content-type": "application/json; charset=utf-8",
|
|
567
|
+
"content-length": Buffer.byteLength(body),
|
|
568
|
+
"cache-control": "no-store",
|
|
569
|
+
"x-content-type-options": "nosniff"
|
|
570
|
+
});
|
|
571
|
+
response.end(body);
|
|
572
|
+
}
|
|
573
|
+
function workspaceContentVersion(content) {
|
|
574
|
+
return createHash("sha256").update(content).digest("hex");
|
|
575
|
+
}
|
|
576
|
+
async function jsonBody(request, maxBytes) {
|
|
577
|
+
const chunks = [];
|
|
578
|
+
let size = 0;
|
|
579
|
+
for await (const chunk of request) {
|
|
580
|
+
const value = Buffer.from(chunk);
|
|
581
|
+
size += value.byteLength;
|
|
582
|
+
if (size > maxBytes) throw new WorkspaceHttpError(413, "\u8BF7\u6C42\u5185\u5BB9\u8FC7\u5927\u3002");
|
|
583
|
+
chunks.push(value);
|
|
584
|
+
}
|
|
585
|
+
try {
|
|
586
|
+
const value = JSON.parse(Buffer.concat(chunks).toString("utf8"));
|
|
587
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) throw new Error();
|
|
588
|
+
return value;
|
|
589
|
+
} catch {
|
|
590
|
+
throw new WorkspaceHttpError(400, "\u8BF7\u6C42\u5FC5\u987B\u662F JSON \u5BF9\u8C61\u3002");
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
function assertCreativePath(path) {
|
|
594
|
+
if (!EDITABLE_EXTENSIONS.has(extname(path).toLocaleLowerCase())) {
|
|
595
|
+
throw new WorkspaceHttpError(415, "\u5DE5\u4F5C\u53F0\u53EA\u7F16\u8F91 Markdown\u3001\u6587\u672C\u3001JSON \u548C JSONL \u6587\u4EF6\u3002");
|
|
596
|
+
}
|
|
597
|
+
if (path.split("/").some((segment) => segment === "" || segment === "..")) {
|
|
598
|
+
throw new WorkspaceHttpError(403, "\u6587\u4EF6\u8DEF\u5F84\u4E0D\u5728\u521B\u4F5C\u5DE5\u4F5C\u53F0\u4E2D\u3002");
|
|
599
|
+
}
|
|
600
|
+
const root = path.split("/", 1)[0];
|
|
601
|
+
if (!CREATIVE_DIRECTORIES.some((directory) => directory === root) && !ROOT_FILES.has(path)) {
|
|
602
|
+
throw new WorkspaceHttpError(403, "\u6587\u4EF6\u8DEF\u5F84\u4E0D\u5728\u521B\u4F5C\u5DE5\u4F5C\u53F0\u4E2D\u3002");
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
async function listFiles(root) {
|
|
606
|
+
const files = [];
|
|
607
|
+
const walk = async (directory) => {
|
|
608
|
+
const absolute = await resolveWorkspacePath(root, directory, { expect: "directory" });
|
|
609
|
+
for (const entry of await readdir3(absolute, { withFileTypes: true })) {
|
|
610
|
+
if (entry.isSymbolicLink() || entry.name.startsWith(".")) continue;
|
|
611
|
+
const path = `${directory}/${entry.name}`;
|
|
612
|
+
if (entry.isDirectory()) await walk(path);
|
|
613
|
+
else if (entry.isFile() && EDITABLE_EXTENSIONS.has(extname(entry.name).toLocaleLowerCase())) {
|
|
614
|
+
files.push({ path, bytes: (await stat(join3(absolute, entry.name))).size });
|
|
615
|
+
}
|
|
616
|
+
if (files.length >= 1e3) return;
|
|
617
|
+
}
|
|
618
|
+
};
|
|
619
|
+
for (const directory of CREATIVE_DIRECTORIES) await walk(directory).catch(() => void 0);
|
|
620
|
+
for (const path of ROOT_FILES) {
|
|
621
|
+
await resolveWorkspacePath(root, path, { expect: "file" }).then(async (absolute) => {
|
|
622
|
+
files.push({ path, bytes: (await stat(absolute)).size });
|
|
623
|
+
}).catch(() => void 0);
|
|
624
|
+
}
|
|
625
|
+
return files.sort((left, right) => left.path.localeCompare(right.path, "zh-Hans-CN"));
|
|
626
|
+
}
|
|
627
|
+
function sessionRoot(context, url) {
|
|
628
|
+
const id = url.searchParams.get("sessionId");
|
|
629
|
+
if (id === null || id === "") throw new WorkspaceHttpError(400, "\u7F3A\u5C11 DSH sessionId\u3002");
|
|
630
|
+
const session = context.sessions.get(SessionId(id));
|
|
631
|
+
if (session === void 0) throw new WorkspaceHttpError(404, "DSH \u4F1A\u8BDD\u4E0D\u53EF\u7528\u3002");
|
|
632
|
+
if (session.header.parentSession !== void 0) throw new WorkspaceHttpError(403, "\u5B50 Agent \u4F1A\u8BDD\u4E0D\u5F00\u653E\u5C0F\u8BF4\u7F16\u8F91\u5668\u3002");
|
|
633
|
+
const cwd = session.header.cwd;
|
|
634
|
+
if (cwd === void 0) throw new WorkspaceHttpError(409, "\u5F53\u524D DSH \u4F1A\u8BDD\u6CA1\u6709\u5DE5\u4F5C\u76EE\u5F55\u3002");
|
|
635
|
+
return canonicalWorkspaceRoot(cwd);
|
|
636
|
+
}
|
|
637
|
+
async function handle(context, request, response, options) {
|
|
638
|
+
try {
|
|
639
|
+
if (!isTrustedWorkspaceRequest(request, options.trustedHosts ?? [])) {
|
|
640
|
+
throw new WorkspaceHttpError(403, "\u8BF7\u6C42\u6765\u6E90\u4E0D\u53D7\u4FE1\u4EFB\u3002");
|
|
641
|
+
}
|
|
642
|
+
const url = new URL(request.url ?? "/", "http://127.0.0.1");
|
|
643
|
+
if (url.pathname === "/oh-story/workspace" && request.method === "GET") {
|
|
644
|
+
const root = await sessionRoot(context, url);
|
|
645
|
+
const files = await listFiles(root);
|
|
646
|
+
const trackingFile = files.find((file) => file.path === "\u8FFD\u8E2A/_tracking-state.json");
|
|
647
|
+
const tracking = trackingFile === void 0 ? null : JSON.parse(await readFile3(await resolveWorkspacePath(root, trackingFile.path, { expect: "file" }), "utf8"));
|
|
648
|
+
const dramaFile = files.find((file) => file.path === "short-drama.json");
|
|
649
|
+
const shortDrama = dramaFile === void 0 ? null : JSON.parse(await readFile3(await resolveWorkspacePath(root, dramaFile.path, { expect: "file" }), "utf8"));
|
|
650
|
+
send(response, 200, { cwd: root, files, tracking, shortDrama, mode: "dsh-session" });
|
|
651
|
+
return;
|
|
652
|
+
}
|
|
653
|
+
if (url.pathname === "/oh-story/file" && request.method === "GET") {
|
|
654
|
+
const root = await sessionRoot(context, url);
|
|
655
|
+
const path = url.searchParams.get("path");
|
|
656
|
+
if (path === null) throw new WorkspaceHttpError(400, "\u7F3A\u5C11\u6587\u4EF6\u8DEF\u5F84\u3002");
|
|
657
|
+
assertCreativePath(path);
|
|
658
|
+
const absolute = await resolveWorkspacePath(root, path, { expect: "file" });
|
|
659
|
+
const data = await readFile3(absolute);
|
|
660
|
+
if (data.byteLength > options.maxBytes) throw new WorkspaceHttpError(413, "\u6587\u4EF6\u8D85\u8FC7\u5DE5\u4F5C\u53F0\u5927\u5C0F\u9650\u5236\u3002");
|
|
661
|
+
send(response, 200, {
|
|
662
|
+
path,
|
|
663
|
+
content: data.toString("utf8"),
|
|
664
|
+
bytes: data.byteLength,
|
|
665
|
+
version: workspaceContentVersion(data)
|
|
666
|
+
});
|
|
667
|
+
return;
|
|
668
|
+
}
|
|
669
|
+
if (url.pathname === "/oh-story/file" && request.method === "PUT") {
|
|
670
|
+
const root = await sessionRoot(context, url);
|
|
671
|
+
const path = url.searchParams.get("path");
|
|
672
|
+
if (path === null) throw new WorkspaceHttpError(400, "\u7F3A\u5C11\u6587\u4EF6\u8DEF\u5F84\u3002");
|
|
673
|
+
assertCreativePath(path);
|
|
674
|
+
const input = await jsonBody(request, options.maxBytes * 6 + 1024);
|
|
675
|
+
if (typeof input.content !== "string") throw new WorkspaceHttpError(400, "content \u5FC5\u987B\u662F\u5B57\u7B26\u4E32\u3002");
|
|
676
|
+
if (typeof input.baseVersion !== "string") throw new WorkspaceHttpError(400, "baseVersion \u5FC5\u987B\u662F\u5B57\u7B26\u4E32\u3002");
|
|
677
|
+
if (Buffer.byteLength(input.content) > options.maxBytes) throw new WorkspaceHttpError(413, "\u6587\u4EF6\u8D85\u8FC7\u5DE5\u4F5C\u53F0\u5927\u5C0F\u9650\u5236\u3002");
|
|
678
|
+
const absolute = await resolveWorkspacePath(root, path, { expect: "file" });
|
|
679
|
+
const current = await readFile3(absolute);
|
|
680
|
+
if (workspaceContentVersion(current) !== input.baseVersion) {
|
|
681
|
+
throw new WorkspaceHttpError(412, "\u6587\u4EF6\u5DF2\u5728\u78C1\u76D8\u4E0A\u66F4\u65B0\u3002\u8BF7\u5237\u65B0\u5E76\u5408\u5E76\u540E\u518D\u4FDD\u5B58\u3002");
|
|
682
|
+
}
|
|
683
|
+
const parent = dirname3(absolute);
|
|
684
|
+
await mkdir(parent, { recursive: true });
|
|
685
|
+
const rootReal = await canonicalWorkspaceRoot(root);
|
|
686
|
+
const parentReal = await canonicalWorkspaceRoot(parent);
|
|
687
|
+
const offset = relative4(rootReal, parentReal);
|
|
688
|
+
if (offset === ".." || offset.startsWith("../")) throw new WorkspaceHttpError(403, "\u6587\u4EF6\u8DEF\u5F84\u79BB\u5F00\u4E86 DSH \u5DE5\u4F5C\u76EE\u5F55\u3002");
|
|
689
|
+
const temporary = resolve5(parent, `.${randomUUID()}.oh-story.tmp`);
|
|
690
|
+
try {
|
|
691
|
+
await writeFile(temporary, input.content, { encoding: "utf8", flag: "wx" });
|
|
692
|
+
if (workspaceContentVersion(await readFile3(absolute)) !== input.baseVersion) {
|
|
693
|
+
throw new WorkspaceHttpError(412, "\u6587\u4EF6\u5DF2\u5728\u78C1\u76D8\u4E0A\u66F4\u65B0\u3002\u8BF7\u5237\u65B0\u5E76\u5408\u5E76\u540E\u518D\u4FDD\u5B58\u3002");
|
|
694
|
+
}
|
|
695
|
+
await rename(temporary, absolute);
|
|
696
|
+
} finally {
|
|
697
|
+
await rm(temporary, { force: true });
|
|
698
|
+
}
|
|
699
|
+
send(response, 200, {
|
|
700
|
+
path,
|
|
701
|
+
content: input.content,
|
|
702
|
+
bytes: Buffer.byteLength(input.content),
|
|
703
|
+
version: workspaceContentVersion(input.content)
|
|
704
|
+
});
|
|
705
|
+
return;
|
|
706
|
+
}
|
|
707
|
+
send(response, 404, { error: "Oh Story route not found." });
|
|
708
|
+
} catch (error) {
|
|
709
|
+
if (error instanceof WorkspaceHttpError) send(response, error.status, { error: error.message });
|
|
710
|
+
else send(response, 500, { error: error instanceof Error ? error.message : String(error) });
|
|
711
|
+
}
|
|
712
|
+
}
|
|
713
|
+
function registerWorkspaceRoute(context, options) {
|
|
714
|
+
context.effect(() => context.webServer.register({
|
|
715
|
+
kind: "prefix",
|
|
716
|
+
path: "/oh-story",
|
|
717
|
+
handler: (request, response) => handle(context, request, response, options)
|
|
718
|
+
}), "oh-story: DSH-session workspace API");
|
|
719
|
+
}
|
|
720
|
+
|
|
721
|
+
// src/index.ts
|
|
722
|
+
var name = "oh-story";
|
|
723
|
+
var inject = ["sessions", "skills", "subagents", "tools", "webServer"];
|
|
724
|
+
var Config = z.object({
|
|
725
|
+
editorMaxBytes: z.natural().min(65536).max(8388608).default(2097152),
|
|
726
|
+
trustedHosts: z.array(String).default([])
|
|
727
|
+
});
|
|
728
|
+
async function apply(context, config = {}) {
|
|
729
|
+
const trustedHosts = config.trustedHosts ?? [];
|
|
730
|
+
for (const entry of trustedHosts) assertTrustedWorkspaceAuthority(entry);
|
|
731
|
+
context.skills.registerProvider(() => createOhStorySkillProvider());
|
|
732
|
+
context.skills.registerProvider(() => createDramaSkillProvider());
|
|
733
|
+
registerOhStoryHooks(context);
|
|
734
|
+
await registerOhStoryRoleTool(context);
|
|
735
|
+
registerWorkspaceRoute(context, { maxBytes: config.editorMaxBytes ?? 2097152, trustedHosts });
|
|
736
|
+
}
|
|
737
|
+
var index_default = { name, inject, Config, apply };
|
|
738
|
+
export {
|
|
739
|
+
Config,
|
|
740
|
+
OH_STORY_ROLE_NAMES,
|
|
741
|
+
OH_STORY_ROLE_TOOL_NAME,
|
|
742
|
+
apply,
|
|
743
|
+
createDramaSkillProvider,
|
|
744
|
+
createOhStoryRoleTool,
|
|
745
|
+
createOhStorySkillProvider,
|
|
746
|
+
index_default as default,
|
|
747
|
+
inject,
|
|
748
|
+
loadBundledRole,
|
|
749
|
+
name,
|
|
750
|
+
parseBundledSkill,
|
|
751
|
+
registerOhStoryHooks,
|
|
752
|
+
registerOhStoryRoleTool,
|
|
753
|
+
registerWorkspaceRoute,
|
|
754
|
+
roleToolFilter
|
|
755
|
+
};
|
|
756
|
+
//# sourceMappingURL=index.js.map
|