@oh-story/dsh 0.1.2 → 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -3
- package/lib/client.js +27 -11
- package/lib/client.js.map +2 -2
- package/lib/drama/manifest.json +141 -136
- package/lib/drama/skills/short-drama/SKILL.md +55 -122
- package/lib/drama/skills/short-drama/references/audience-reveal.md +14 -67
- package/lib/drama/skills/short-drama/references/contract-and-ownership.md +24 -78
- package/lib/drama/skills/short-drama/references/creator-documents.md +79 -0
- package/lib/drama/skills/short-drama/references/creator-workflow.md +51 -77
- package/lib/drama/skills/short-drama/references/knowhow-index.md +2 -0
- package/lib/drama/skills/short-drama/references/look-development.md +2 -3
- package/lib/drama/skills/short-drama/references/pickup-and-alternate.md +14 -48
- package/lib/drama/skills/short-drama/references/production-form-profiles.md +1 -1
- package/lib/drama/skills/short-drama/references/reference-roles.md +29 -135
- package/lib/drama/skills/short-drama/references/runtime-preflight.md +13 -19
- package/lib/drama/skills/short-drama-assets/SKILL.md +40 -161
- package/lib/drama/skills/short-drama-assets/references/asset-review-checklist.md +18 -25
- package/lib/drama/skills/short-drama-assets/references/character-and-look.md +13 -15
- package/lib/drama/skills/short-drama-assets/references/continuity-delta.md +11 -14
- package/lib/drama/skills/short-drama-assets/references/identity-vs-variant.md +5 -12
- package/lib/drama/skills/short-drama-assets/references/occurrence-extraction.md +8 -11
- package/lib/drama/skills/short-drama-assets/references/prop-and-state.md +2 -2
- package/lib/drama/skills/short-drama-assets/references/stage-contract.md +10 -105
- package/lib/drama/skills/short-drama-assets/references/voice-direction.md +12 -32
- package/lib/drama/skills/short-drama-image-prompts/SKILL.md +41 -155
- package/lib/drama/skills/short-drama-image-prompts/references/character-and-look.md +12 -13
- package/lib/drama/skills/short-drama-image-prompts/references/common-recipe.md +10 -12
- package/lib/drama/skills/short-drama-image-prompts/references/edit-and-revision.md +39 -51
- package/lib/drama/skills/short-drama-image-prompts/references/location-plate.md +3 -4
- package/lib/drama/skills/short-drama-image-prompts/references/look-and-state-variant.md +15 -14
- package/lib/drama/skills/short-drama-image-prompts/references/lookdev-frame.md +11 -15
- package/lib/drama/skills/short-drama-image-prompts/references/production-sheet-recipes.md +1 -1
- package/lib/drama/skills/short-drama-image-prompts/references/prop-plate.md +4 -7
- package/lib/drama/skills/short-drama-image-prompts/references/review-and-fixtures.md +23 -23
- package/lib/drama/skills/short-drama-image-prompts/references/stage-contract.md +6 -65
- package/lib/drama/skills/short-drama-produce/SKILL.md +26 -10
- package/lib/drama/skills/short-drama-review/SKILL.md +61 -123
- package/lib/drama/skills/short-drama-review/references/anti-template-repair.md +10 -15
- package/lib/drama/skills/short-drama-review/references/production-quality-gates.md +15 -16
- package/lib/drama/skills/short-drama-review/references/project-calibration.md +7 -9
- package/lib/drama/skills/short-drama-review/references/review-method.md +8 -9
- package/lib/drama/skills/short-drama-review/references/rubric-assets-prompts.md +9 -13
- package/lib/drama/skills/short-drama-review/references/rubric-story-script.md +104 -4
- package/lib/drama/skills/short-drama-review/references/rubric-visual-motion.md +15 -19
- package/lib/drama/skills/short-drama-review/references/stage-contract.md +4 -63
- package/lib/drama/skills/short-drama-storyboard/SKILL.md +49 -240
- package/lib/drama/skills/short-drama-storyboard/references/blocking-playbooks.md +9 -34
- package/lib/drama/skills/short-drama-storyboard/references/comic-keyframe-lexicon.md +156 -0
- package/lib/drama/skills/short-drama-storyboard/references/coverage-audition.md +5 -10
- package/lib/drama/skills/short-drama-storyboard/references/keyframe-craft.md +8 -7
- package/lib/drama/skills/short-drama-storyboard/references/review-and-fixtures.md +24 -62
- package/lib/drama/skills/short-drama-storyboard/references/scene-visual-plan.md +16 -25
- package/lib/drama/skills/short-drama-storyboard/references/screenplay-to-keyframe-example.md +5 -23
- package/lib/drama/skills/short-drama-storyboard/references/shot-craft.md +8 -10
- package/lib/drama/skills/short-drama-storyboard/references/shot-revision-identity.md +9 -13
- package/lib/drama/skills/short-drama-storyboard/references/stage-contract.md +11 -71
- package/lib/drama/skills/short-drama-video-prompts/SKILL.md +44 -219
- package/lib/drama/skills/short-drama-video-prompts/references/camera-audio-continuity.md +10 -8
- package/lib/drama/skills/short-drama-video-prompts/references/delivery-profile.md +3 -5
- package/lib/drama/skills/short-drama-video-prompts/references/generability.md +2 -2
- package/lib/drama/skills/short-drama-video-prompts/references/motion-recipe.md +13 -23
- package/lib/drama/skills/short-drama-video-prompts/references/performance-action-timing.md +8 -11
- package/lib/drama/skills/short-drama-video-prompts/references/production-prompt-grammar.md +2 -3
- package/lib/drama/skills/short-drama-video-prompts/references/review-and-fixtures.md +34 -63
- package/lib/drama/skills/short-drama-video-prompts/references/stage-contract.md +13 -72
- package/lib/drama/skills/short-drama-write/SKILL.md +73 -268
- package/lib/drama/skills/short-drama-write/references/dialogue-craft.md +7 -0
- package/lib/drama/skills/short-drama-write/references/scene-handoff-capsule.md +17 -43
- package/lib/drama/skills/short-drama-write/references/screenplay-format.md +15 -15
- package/lib/drama/skills/short-drama-write/references/script-craft.md +208 -21
- package/lib/drama/skills/short-drama-write/references/stage-contract.md +11 -70
- package/lib/index.js +107 -14
- package/lib/index.js.map +4 -4
- package/lib/oh-story/manifest.json +26 -26
- package/lib/oh-story/roles/character-designer.md +4 -4
- package/lib/oh-story/roles/narrative-writer.md +11 -11
- package/lib/oh-story/roles/story-architect.md +20 -14
- package/lib/oh-story/roles/story-explorer.md +8 -5
- package/lib/oh-story/skills/story-import/SKILL.md +5 -1
- package/lib/oh-story/skills/story-import/references/structure-mapping-long.md +1 -1
- package/lib/oh-story/skills/story-long-write/references/artifact-protocols.md +1 -1
- package/lib/oh-story/skills/story-long-write/references/outline-structure-theory.md +1 -1
- package/lib/oh-story/skills/story-long-write/references/workflow-chapter.md +1 -1
- package/lib/oh-story/skills/story-long-write/references/workflow-daily.md +1 -0
- package/lib/oh-story/skills/story-long-write/references/workflow-setup.md +11 -5
- package/lib/oh-story/skills/story-setup/SKILL.md +12 -9
- package/lib/types/client/file-activity.d.ts +5 -0
- package/lib/types/client/file-activity.d.ts.map +1 -1
- package/lib/types/client/index.d.ts.map +1 -1
- package/lib/types/index.d.ts +2 -1
- package/lib/types/index.d.ts.map +1 -1
- package/lib/types/reference-tool.d.ts +6 -0
- package/lib/types/reference-tool.d.ts.map +1 -0
- package/lib/types/role-provider.d.ts.map +1 -1
- package/lib/types/role-tool.d.ts +3 -1
- package/lib/types/role-tool.d.ts.map +1 -1
- package/lib/types/skill-provider.d.ts.map +1 -1
- package/package.json +3 -2
- package/lib/drama/skills/short-drama/references/lifecycle-commands.md +0 -130
package/lib/index.js
CHANGED
|
@@ -39,13 +39,16 @@ var DSH_DRAMA_BRIDGE = [
|
|
|
39
39
|
"This Skill is a native contribution to the current DeepSeek Harness session.",
|
|
40
40
|
"DSH owns the workspace, model, preset, permissions, Session Log, tools, approvals, cancellation, resume, and Agent UI.",
|
|
41
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
|
+
"Drama Skills v0.6 uses a creator-first contract: each episode keeps only the requested documents, up to five creator-facing sources at \u5267\u96C6/<EP>/\u5267\u672C.md, \u89C6\u89C9\u8BBE\u5B9A.md, \u5206\u955C.md, \u56FE\u7247\u63D0\u793A\u8BCD.md, and \u89C6\u9891\u63D0\u793A\u8BCD.md. Never precreate empty documents, backfill nominal stages, or start work the creator did not request. Persisted reviews use creator-readable Markdown under \u5BA1\u67E5/; an oral review writes nothing.",
|
|
43
|
+
"For a v0.6 project, never create a parallel JSON/JSONL lifecycle truth, indexes, fingerprints, coverage tables, or QA records merely because legacy maintenance scripts and templates remain bundled.",
|
|
44
|
+
"Never upgrade a v0.5 structured project in place or mix both contracts in one project root. Keep legacy production/audit artifacts read-only and pinned to v0.5; migrate only into a new creator-first root with manual per-episode creator confirmation.",
|
|
42
45
|
"Use only tools visible in the current DSH preset and preserve the upstream project ownership, freshness, review, and explicit production-confirmation contracts.",
|
|
43
46
|
"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
47
|
"</short-drama-dsh-integration>"
|
|
45
48
|
].join("\n");
|
|
46
49
|
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."
|
|
50
|
+
"short-drama": "A dashboard request means focus or use the native \u77ED\u5267 tab in this DSH Session. Do not run the bundled standalone Dashboard script. New projects follow only the v0.6 creator-first contract and create only documents required by the current request.",
|
|
51
|
+
"short-drama-produce": "Use an upstream adapter only after the creator explicitly confirms the exact current job. Its source must be the current creator-first Markdown and its output belongs under \u5267\u96C6/<EP>/\u5236\u4F5C\u6210\u679C/. DSH permissions and approval UI remain authoritative."
|
|
49
52
|
};
|
|
50
53
|
var DSH_NATIVE_SKILLS = {
|
|
51
54
|
story: `# story \u2014 DSH \u5C0F\u8BF4\u6D41\u7A0B\u5165\u53E3
|
|
@@ -320,11 +323,89 @@ function registerOhStoryHooks(context) {
|
|
|
320
323
|
}
|
|
321
324
|
|
|
322
325
|
// src/role-tool.ts
|
|
326
|
+
import { defineTool as defineTool2 } from "@deepseek-ai/dsh-tools";
|
|
327
|
+
|
|
328
|
+
// src/reference-tool.ts
|
|
329
|
+
import { readdir as readdir2, readFile as readFile2, realpath } from "node:fs/promises";
|
|
330
|
+
import { isAbsolute as isAbsolute2, join as join2, relative as relative2, resolve as resolve2 } from "node:path";
|
|
323
331
|
import { defineTool } from "@deepseek-ai/dsh-tools";
|
|
332
|
+
var OH_STORY_REFERENCE_TOOL_NAME = "oh_story_bundled_reference";
|
|
333
|
+
async function collectMarkdown(root, directory = root) {
|
|
334
|
+
const entries = await readdir2(directory, { withFileTypes: true });
|
|
335
|
+
const nested = await Promise.all(entries.map(async (entry) => {
|
|
336
|
+
const path = join2(directory, entry.name);
|
|
337
|
+
if (entry.isDirectory()) return collectMarkdown(root, path);
|
|
338
|
+
return entry.isFile() && entry.name.endsWith(".md") ? [path] : [];
|
|
339
|
+
}));
|
|
340
|
+
return nested.flat();
|
|
341
|
+
}
|
|
342
|
+
async function bundledReferences(storySetupRoot) {
|
|
343
|
+
const root = await realpath(resolve2(storySetupRoot));
|
|
344
|
+
const referenceRoot = await realpath(join2(root, "references", "agent-references"));
|
|
345
|
+
const referenceDirectory = relative2(root, referenceRoot);
|
|
346
|
+
if (referenceDirectory === "" || referenceDirectory.startsWith("..") || isAbsolute2(referenceDirectory)) {
|
|
347
|
+
throw new Error("Bundled Oh Story reference directory escaped its package root.");
|
|
348
|
+
}
|
|
349
|
+
const values = await Promise.all((await collectMarkdown(referenceRoot)).map(async (path) => {
|
|
350
|
+
const canonicalPath = await realpath(path);
|
|
351
|
+
const inside = relative2(referenceRoot, canonicalPath);
|
|
352
|
+
if (inside === "" || inside.startsWith("..") || isAbsolute2(inside)) {
|
|
353
|
+
throw new Error(`Bundled Oh Story reference escaped its package root: ${path}`);
|
|
354
|
+
}
|
|
355
|
+
return {
|
|
356
|
+
canonicalPath,
|
|
357
|
+
name: `story-setup/references/agent-references/${inside.replaceAll("\\", "/")}`
|
|
358
|
+
};
|
|
359
|
+
}));
|
|
360
|
+
return values.sort((left, right) => left.name.localeCompare(right.name));
|
|
361
|
+
}
|
|
362
|
+
async function createOhStoryReferenceTool(storySetupRoot = join2(defaultBundledSkillRoot(), "story-setup")) {
|
|
363
|
+
const references = await bundledReferences(storySetupRoot);
|
|
364
|
+
if (references.length === 0) throw new Error("No bundled Oh Story references were found.");
|
|
365
|
+
const paths = references.map((reference) => reference.name);
|
|
366
|
+
const byName = new Map(references.map((reference) => [reference.name, reference.canonicalPath]));
|
|
367
|
+
return defineTool({
|
|
368
|
+
name: OH_STORY_REFERENCE_TOOL_NAME,
|
|
369
|
+
description: "Read one exact, pinned Oh Story story-setup reference bundled with this plugin. This does not resolve project Skills or workspace files.",
|
|
370
|
+
parameters: {
|
|
371
|
+
reference: {
|
|
372
|
+
type: "string",
|
|
373
|
+
required: true,
|
|
374
|
+
enum: paths,
|
|
375
|
+
description: "The exact story-setup reference path named by the active bundled Role."
|
|
376
|
+
}
|
|
377
|
+
},
|
|
378
|
+
output: {
|
|
379
|
+
schema: {
|
|
380
|
+
type: "object",
|
|
381
|
+
additionalProperties: false,
|
|
382
|
+
properties: {
|
|
383
|
+
reference: { type: "string", required: true },
|
|
384
|
+
content: { type: "string", required: true }
|
|
385
|
+
}
|
|
386
|
+
},
|
|
387
|
+
render: (_args, value) => [{
|
|
388
|
+
type: "text",
|
|
389
|
+
text: `Bundled Oh Story reference: ${value.reference}
|
|
390
|
+
|
|
391
|
+
${value.content}`
|
|
392
|
+
}]
|
|
393
|
+
},
|
|
394
|
+
isConcurrencySafe: () => true,
|
|
395
|
+
async execute(args) {
|
|
396
|
+
const path = byName.get(args.reference);
|
|
397
|
+
if (path === void 0) throw new Error(`Oh Story reference is not bundled: ${args.reference}`);
|
|
398
|
+
return { reference: args.reference, content: await readFile2(path, "utf8") };
|
|
399
|
+
}
|
|
400
|
+
});
|
|
401
|
+
}
|
|
402
|
+
function bundledReferenceGuard(definition, tools) {
|
|
403
|
+
return (execution) => execution.name === OH_STORY_REFERENCE_TOOL_NAME && tools.get(OH_STORY_REFERENCE_TOOL_NAME, execution.agent) !== definition ? "The pinned Oh Story reference tool was shadowed in this Agent scope." : void 0;
|
|
404
|
+
}
|
|
324
405
|
|
|
325
406
|
// src/role-provider.ts
|
|
326
|
-
import { readFile as
|
|
327
|
-
import { basename as basename2, dirname as dirname2, join as
|
|
407
|
+
import { readFile as readFile3 } from "node:fs/promises";
|
|
408
|
+
import { basename as basename2, dirname as dirname2, join as join3, resolve as resolve3 } from "node:path";
|
|
328
409
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
329
410
|
var OH_STORY_ROLE_NAMES = [
|
|
330
411
|
"chapter-extractor",
|
|
@@ -341,10 +422,10 @@ function roleBody(source) {
|
|
|
341
422
|
}
|
|
342
423
|
function defaultBundledRoleRoot() {
|
|
343
424
|
const current = dirname2(fileURLToPath2(import.meta.url));
|
|
344
|
-
return basename2(current) === "src" ?
|
|
425
|
+
return basename2(current) === "src" ? resolve3(current, "../../knowledge/oh-story/roles") : resolve3(current, "oh-story/roles");
|
|
345
426
|
}
|
|
346
427
|
async function loadBundledRole(name2, roleRoot = defaultBundledRoleRoot(), execution = "tool-free") {
|
|
347
|
-
const body = roleBody(await
|
|
428
|
+
const body = roleBody(await readFile3(join3(resolve3(roleRoot), `${name2}.md`), "utf8"));
|
|
348
429
|
if (body.length === 0) throw new Error(`Bundled role "${name2}" is empty.`);
|
|
349
430
|
const integration = execution === "tool-free" ? [
|
|
350
431
|
"You are running inside an Oh Story review-required DSH collaboration. The caller supplies every permitted input in the prompt.",
|
|
@@ -353,6 +434,8 @@ async function loadBundledRole(name2, roleRoot = defaultBundledRoleRoot(), execu
|
|
|
353
434
|
] : [
|
|
354
435
|
"You are running as a native oh-story-dsh specialist. The current DSH workspace and visible tool set are your complete authority boundary.",
|
|
355
436
|
"Never inspect or require legacy .claude/.opencode/.codex agent deployment files; this exact pinned Role is already active.",
|
|
437
|
+
"Bundled story-setup references are pinned plugin resources, not project files or project Skills. When the upstream Role marks one mandatory, call oh_story_bundled_reference with the exact story-setup/references/agent-references path, then use only the returned content.",
|
|
438
|
+
"If oh_story_bundled_reference or a required bundled reference is unavailable, report the missing reference to the caller. Never call the generic skill tool, fall back to a legacy platform path, or claim that an unread reference was used.",
|
|
356
439
|
"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."
|
|
357
440
|
];
|
|
358
441
|
return [
|
|
@@ -367,10 +450,10 @@ async function loadBundledRole(name2, roleRoot = defaultBundledRoleRoot(), execu
|
|
|
367
450
|
var OH_STORY_ROLE_TOOL_NAME = "oh_story_role";
|
|
368
451
|
var roleTools = {
|
|
369
452
|
"chapter-extractor": ["read", "glob", "grep"],
|
|
370
|
-
"character-designer": ["read", "glob", "grep", "write", "edit"],
|
|
371
|
-
"consistency-checker": ["read", "glob", "grep"],
|
|
372
|
-
"narrative-writer": ["read", "glob", "grep", "write", "edit", "bash"],
|
|
373
|
-
"story-architect": ["read", "glob", "grep", "write", "edit"],
|
|
453
|
+
"character-designer": [OH_STORY_REFERENCE_TOOL_NAME, "read", "glob", "grep", "write", "edit"],
|
|
454
|
+
"consistency-checker": [OH_STORY_REFERENCE_TOOL_NAME, "read", "glob", "grep"],
|
|
455
|
+
"narrative-writer": [OH_STORY_REFERENCE_TOOL_NAME, "read", "glob", "grep", "write", "edit", "bash"],
|
|
456
|
+
"story-architect": [OH_STORY_REFERENCE_TOOL_NAME, "read", "glob", "grep", "write", "edit"],
|
|
374
457
|
"story-explorer": ["read", "glob", "grep"],
|
|
375
458
|
"story-researcher": ["read", "glob", "grep", "bash", "write", "web_search", "web_fetch"]
|
|
376
459
|
};
|
|
@@ -380,12 +463,12 @@ function roleToolFilter(role) {
|
|
|
380
463
|
function resultText(output) {
|
|
381
464
|
return output.map((block) => block.type === "text" ? block.text : JSON.stringify(block)).join("\n");
|
|
382
465
|
}
|
|
383
|
-
async function createOhStoryRoleTool() {
|
|
466
|
+
async function createOhStoryRoleTool(subagents) {
|
|
384
467
|
const personas = /* @__PURE__ */ new Map();
|
|
385
468
|
await Promise.all(OH_STORY_ROLE_NAMES.map(async (role) => {
|
|
386
469
|
personas.set(role, await loadBundledRole(role, void 0, "native-tools"));
|
|
387
470
|
}));
|
|
388
|
-
return
|
|
471
|
+
return defineTool2({
|
|
389
472
|
name: OH_STORY_ROLE_TOOL_NAME,
|
|
390
473
|
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.",
|
|
391
474
|
parameters: {
|
|
@@ -419,7 +502,9 @@ async function createOhStoryRoleTool() {
|
|
|
419
502
|
const persona = personas.get(args.role);
|
|
420
503
|
if (persona === void 0) throw new Error(`Oh Story Role ${args.role} is not bundled.`);
|
|
421
504
|
const allowed = roleToolFilter(args.role).allow.filter((name2) => exec.agent?.ctx.tools.get(name2, exec.agent) !== void 0);
|
|
422
|
-
const
|
|
505
|
+
const runtime = subagents ?? exec.agent.ctx.get("subagents");
|
|
506
|
+
if (runtime === void 0) throw new Error("oh_story_role requires the DSH subagent runtime.");
|
|
507
|
+
const run = await runtime.start("spawn", {
|
|
423
508
|
label: `oh-story:${args.role}`,
|
|
424
509
|
prompt: [{ type: "text", text: args.prompt }],
|
|
425
510
|
parent: exec.agent,
|
|
@@ -445,7 +530,12 @@ async function createOhStoryRoleTool() {
|
|
|
445
530
|
});
|
|
446
531
|
}
|
|
447
532
|
async function registerOhStoryRoleTool(context) {
|
|
448
|
-
const definition = await
|
|
533
|
+
const [definition, referenceDefinition] = await Promise.all([
|
|
534
|
+
createOhStoryRoleTool(context.subagents),
|
|
535
|
+
createOhStoryReferenceTool()
|
|
536
|
+
]);
|
|
537
|
+
context.tools.register(referenceDefinition);
|
|
538
|
+
context.tools.guard(bundledReferenceGuard(referenceDefinition, context.tools));
|
|
449
539
|
let dispose;
|
|
450
540
|
const mount = () => {
|
|
451
541
|
dispose ??= context.tools.register(definition);
|
|
@@ -755,10 +845,13 @@ async function apply(context, config = {}) {
|
|
|
755
845
|
var index_default = { name, inject, Config, apply };
|
|
756
846
|
export {
|
|
757
847
|
Config,
|
|
848
|
+
OH_STORY_REFERENCE_TOOL_NAME,
|
|
758
849
|
OH_STORY_ROLE_NAMES,
|
|
759
850
|
OH_STORY_ROLE_TOOL_NAME,
|
|
760
851
|
apply,
|
|
852
|
+
bundledReferenceGuard,
|
|
761
853
|
createDramaSkillProvider,
|
|
854
|
+
createOhStoryReferenceTool,
|
|
762
855
|
createOhStoryRoleTool,
|
|
763
856
|
createOhStorySkillProvider,
|
|
764
857
|
index_default as default,
|
package/lib/index.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
|
-
"sources": ["../src/index.ts", "../src/skill-provider.ts", "../src/native-hooks.ts", "../src/role-tool.ts", "../src/role-provider.ts", "../src/workspace-route.ts", "../src/workspace-request-trust.ts"],
|
|
4
|
-
"sourcesContent": ["import type { Context } from \"@deepseek-ai/cordis\";\nimport type {} from \"@deepseek-ai/dsh-host-webserver\";\nimport type {} from \"@deepseek-ai/dsh-skill\";\nimport type {} from \"@deepseek-ai/dsh-subagent\";\nimport type {} from \"@deepseek-ai/dsh-tools\";\nimport z from \"@deepseek-ai/schemastery\";\nimport { createDramaSkillProvider, createOhStorySkillProvider } from \"./skill-provider.js\";\nimport { registerOhStoryHooks } from \"./native-hooks.js\";\nimport { registerOhStoryRoleTool } from \"./role-tool.js\";\nimport { registerWorkspaceRoute } from \"./workspace-route.js\";\nimport { assertTrustedWorkspaceAuthority } from \"./workspace-request-trust.js\";\n\nexport { createDramaSkillProvider, createOhStorySkillProvider, parseBundledSkill } from \"./skill-provider.js\";\nexport { OH_STORY_ROLE_NAMES, loadBundledRole } from \"./role-provider.js\";\nexport { createOhStoryRoleTool, OH_STORY_ROLE_TOOL_NAME, registerOhStoryRoleTool, roleToolFilter } from \"./role-tool.js\";\nexport { registerWorkspaceRoute } from \"./workspace-route.js\";\nexport { registerOhStoryHooks } from \"./native-hooks.js\";\n\nexport const name = \"oh-story\";\nexport const inject = [\"skills\", \"subagents\", \"tools\", \"typert\", \"webServer\"];\n\n/** DSH owns models, providers, presets, permissions, roots, runs, and sessions. */\nexport interface Config {\n readonly editorMaxBytes?: number;\n readonly trustedHosts?: string[];\n}\n\nexport const Config = z.object({\n editorMaxBytes: z.natural().min(65_536).max(8_388_608).default(2_097_152),\n trustedHosts: z.array(String).default([])\n}) as z<Config>;\n\n/** Mount only domain contributions into the current DSH process. */\nexport async function apply(context: Context, config: Config = {}): Promise<void> {\n const trustedHosts = config.trustedHosts ?? [];\n for (const entry of trustedHosts) assertTrustedWorkspaceAuthority(entry);\n context.skills.registerProvider(() => createOhStorySkillProvider());\n context.skills.registerProvider(() => createDramaSkillProvider());\n registerOhStoryHooks(context);\n await registerOhStoryRoleTool(context);\n registerWorkspaceRoute(context, { maxBytes: config.editorMaxBytes ?? 2_097_152, trustedHosts });\n}\n\nexport default { name, inject, Config, apply };\n", "import { readdir, readFile } from \"node:fs/promises\";\nimport { basename, dirname, isAbsolute, join, relative, resolve } from \"node:path\";\nimport { fileURLToPath, pathToFileURL } from \"node:url\";\nimport {\n BUNDLED_SKILL_RANK,\n type SkillCandidate,\n type SkillDefinition,\n type SkillProvider\n} from \"@deepseek-ai/dsh-skill\";\n\nconst STORY_PROVIDER_NAME = \"oh-story\";\nconst DRAMA_PROVIDER_NAME = \"short-drama\";\nconst INVOCATION = { modelInvocable: true, userInvocable: true } as const;\nconst DSH_SKILL_BRIDGE = [\n \"<oh-story-dsh-integration>\",\n \"This Skill is a native contribution to the current DeepSeek Harness session.\",\n \"DSH owns the workspace, model, preset, permissions, Session Log, tools, subagents, cancellation, resume, and Agent UI.\",\n \"Never start another Agent runtime, session transport, Dashboard, SSE stream, polling loop, or model configuration.\",\n \"All seven upstream Oh Story specialist Roles are bundled. Invoke one with oh_story_role and a self-contained prompt.\",\n \"Never inspect .claude/agents, .codex/agents, .opencode/agents, or .story-deployed to decide whether a Role is available.\",\n \"Use only DSH-visible tools. DSH sandbox and permission policy remain authoritative.\",\n \"</oh-story-dsh-integration>\"\n].join(\"\\n\");\nconst DSH_SKILL_OVERRIDES: Readonly<Partial<Record<string, string>>> = {\n story: \"The \u5C0F\u8BF4 workspace is an official DSH conversation view. Never start or open a second web application.\",\n \"story-setup\": \"Initialize or validate novel project data only. DSH already supplies Skills, Roles, hooks, tools, permissions, sessions, and UI; never deploy Claude/OpenCode/Codex/ZCode/OpenClaw/Reasonix files or a .story-deployed marker.\",\n \"story-long-analyze\": \"Use oh_story_role for chapter extraction or specialist analysis. Never inspect platform agent directories or require a deployed external Agent definition.\",\n \"story-long-write\": \"All named Roles are provided through oh_story_role. Do not check platform agent files. Keep the upstream writing, Tracking, lint, outline, revision, and quality workflows.\",\n \"story-review\": \"All named reviewer Roles are provided through oh_story_role. Do not check platform agent files; full/lean review may use the bundled Roles directly.\",\n \"story-import\": \"All named Roles are provided through oh_story_role. Do not require story-setup to deploy them.\",\n \"story-deslop\": \"Use the bundled narrative-writer Role through oh_story_role when specialist review is useful. Never inspect platform agent directories.\",\n \"story-short-analyze\": \"Use oh_story_role for specialist analysis. Never inspect platform agent directories or require external Agent deployment.\",\n \"story-short-write\": \"All named Roles are provided through oh_story_role. Do not inspect platform agent files; preserve the upstream short-fiction workflow and quality gates.\",\n \"browser-cdp\": \"Use only browser or web capabilities visible in the current DSH preset. Do not start a parallel browser host; if no compatible capability is visible, explain the limitation.\",\n \"story-cover\": \"Use only image-generation or HTTP capabilities visible in the current DSH preset. Never assume a separate Codex or Claude runtime.\"\n};\nconst DSH_DRAMA_BRIDGE = [\n \"<short-drama-dsh-integration>\",\n \"This Skill is a native contribution to the current DeepSeek Harness session.\",\n \"DSH owns the workspace, model, preset, permissions, Session Log, tools, approvals, cancellation, resume, and Agent UI.\",\n \"The \u77ED\u5267 tab is the creator workspace. Never start dashboard_server.py, another web server, Dashboard, Agent runtime, session transport, or model configuration.\",\n \"Use only tools visible in the current DSH preset and preserve the upstream project ownership, freshness, review, and explicit production-confirmation contracts.\",\n \"Production credentials remain outside project files. Never treat a prior acceptance, preview, continuation request, or budget discussion as confirmation for a paid production run.\",\n \"</short-drama-dsh-integration>\"\n].join(\"\\n\");\nconst DSH_DRAMA_OVERRIDES: Readonly<Partial<Record<string, string>>> = {\n \"short-drama\": \"A dashboard request means focus or use the native \u77ED\u5267 tab in this DSH Session. Do not run the bundled standalone Dashboard script.\",\n \"short-drama-produce\": \"Use an upstream adapter only after the creator explicitly confirms the exact current job. DSH permissions and approval UI remain authoritative.\"\n};\n\nconst DSH_NATIVE_SKILLS: Readonly<Partial<Record<string, string>>> = {\n story: `# story \u2014 DSH \u5C0F\u8BF4\u6D41\u7A0B\u5165\u53E3\n\n\u5728\u5F53\u524D DSH Session \u5185\u5224\u65AD\u7528\u6237\u610F\u56FE\uFF0C\u5E76\u52A0\u8F7D\u6700\u5339\u914D\u7684 Oh Story Skill\uFF1A\n\n- \u65B0\u5EFA\u6216\u4FEE\u590D\u5C0F\u8BF4\u5DE5\u7A0B\uFF1Astory-setup\n- \u957F\u7BC7\u9009\u9898/\u626B\u699C/\u62C6\u6587/\u65E5\u66F4\uFF1Astory-long-scan\u3001story-long-analyze\u3001story-long-write\n- \u77ED\u7BC7\u9009\u9898/\u62C6\u6587/\u5199\u4F5C\uFF1Astory-short-scan\u3001story-short-analyze\u3001story-short-write\n- \u5BFC\u5165\u5DF2\u6709\u4F5C\u54C1\uFF1Astory-import\n- \u5BA1\u7A3F\u4E0E\u53BB AI \u5473\uFF1Astory-review\u3001story-deslop\n- \u5C01\u9762\uFF1Astory-cover\n\n\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\nAgent\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\n\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`,\n \"story-setup\": `# story-setup \u2014 DSH \u539F\u751F\u5C0F\u8BF4\u5DE5\u7A0B\u521D\u59CB\u5316\n\n\u53EA\u521D\u59CB\u5316\u6216\u6821\u9A8C\u5F53\u524D DSH workspace \u4E2D\u7684\u5C0F\u8BF4\u6570\u636E\uFF0C\u4E0D\u90E8\u7F72\u4EFB\u4F55 Agent \u5E73\u53F0\u6587\u4EF6\u3002\n\n1. \u68C0\u67E5\u73B0\u6709\u6B63\u6587\u3001\u8BBE\u5B9A\u3001\u5927\u7EB2\u548C\u8FFD\u8E2A\u6587\u4EF6\uFF0C\u5DF2\u6709\u5185\u5BB9\u7EDD\u4E0D\u8986\u76D6\u3002\n2. \u6839\u636E\u7528\u6237\u58F0\u660E\u4E0E\u73B0\u6709\u7ED3\u6784\u5224\u65AD\u957F\u7BC7/\u77ED\u7BC7\uFF1B\u65E0\u6CD5\u53EF\u9760\u5224\u65AD\u65F6\u8BF7\u6C42\u786E\u8BA4\u3002\n3. \u957F\u7BC7\u6309\u9700\u5EFA\u7ACB \u6B63\u6587/\u3001\u8BBE\u5B9A/\u3001\u5927\u7EB2/\u3001\u8FFD\u8E2A/\uFF0C\u5E76\u51C6\u5907\u8FFD\u8E2A/_tracking-state.json\uFF1B\n \u7B2C\u4E00\u7AE0\u6B63\u6587\u843D\u76D8\u524D\u5FC5\u987B\u6709\u5BF9\u5E94\u7EC6\u7EB2\u3002\u77ED\u7BC7\u4FDD\u6301\u8F7B\u91CF\u7ED3\u6784\uFF0C\u4E0D\u5F3A\u52A0\u957F\u7BC7 Tracking\u3002\n4. \u9700\u8981\u67B6\u6784\u3001\u89D2\u8272\u6216\u7814\u7A76\u5DE5\u4F5C\u65F6\uFF0C\u901A\u8FC7 oh_story_role \u8C03\u7528\u5DF2\u6253\u5305 Role\uFF1B\u4E0D\u8981\u68C0\u67E5\u6216\n \u751F\u6210 .claude\u3001.codex\u3001.opencode\u3001.zcode\u3001AGENTS.md \u6216 .story-deployed\u3002\n5. \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\n\n\u9898\u6750\u3001\u89D2\u8272\u3001\u8282\u594F\u3001\u51B2\u7A81\u3001\u5F00\u7BC7\u548C\u5199\u4F5C\u65B9\u6CD5\u8D44\u6599\u4F4D\u4E8E references/agent-references/\uFF1B\n\u53EA\u52A0\u8F7D\u5F53\u524D\u4EFB\u52A1\u9700\u8981\u7684\u6587\u4EF6\u3002`,\n \"browser-cdp\": `# browser-cdp \u2014 DSH \u6D4F\u89C8\u5668\u80FD\u529B\u9002\u914D\n\n\u672C Skill \u4E0D\u542F\u52A8 Chrome\u3001CDP \u7AEF\u53E3\u3001\u72EC\u7ACB\u6D4F\u89C8\u5668 Host \u6216 setup-cdp-chrome.js\u3002\n\u4EC5\u4F7F\u7528\u5F53\u524D DSH Preset \u5DF2\u66B4\u9732\u7684 web_search\u3001web_fetch \u6216\u6D4F\u89C8\u5668\u5DE5\u5177\u5B8C\u6210\u7F51\u9875\u8BFB\u53D6\u3001\n\u699C\u5355\u91C7\u96C6\u548C\u8D44\u6599\u6838\u9A8C\u3002\u4FDD\u6301\u4EE5\u4E0B\u539F\u5219\uFF1A\n\n1. \u4F18\u5148\u4F7F\u7528\u7ED3\u6784\u5316\u641C\u7D22/\u6293\u53D6\u5DE5\u5177\uFF1B\u9700\u8981\u767B\u5F55\u6001\u6216\u4EA4\u4E92\u9875\u9762\u65F6\u624D\u4F7F\u7528\u53EF\u89C1\u6D4F\u89C8\u5668\u80FD\u529B\u3002\n2. \u5C0A\u91CD\u7AD9\u70B9\u6761\u6B3E\u3001\u8BBF\u95EE\u9891\u7387\u4E0E\u7528\u6237\u6388\u6743\uFF1B\u4E0D\u7ED5\u8FC7\u9A8C\u8BC1\u7801\u3001\u4ED8\u8D39\u5899\u6216\u8BBF\u95EE\u63A7\u5236\u3002\n3. \u8BB0\u5F55\u6765\u6E90 URL\u3001\u91C7\u96C6\u65F6\u95F4\u3001\u5931\u8D25\u9879\u548C\u6570\u636E\u8D28\u91CF\uFF0C\u4E0D\u628A\u63A8\u65AD\u5199\u6210\u9875\u9762\u4E8B\u5B9E\u3002\n4. \u5F53\u524D Preset \u6CA1\u6709\u517C\u5BB9\u80FD\u529B\u65F6\uFF0C\u8BF4\u660E\u7F3A\u5931\u80FD\u529B\u548C\u53EF\u884C\u7684\u624B\u5DE5\u6B65\u9AA4\uFF0C\u4E0D\u53E6\u8D77\u8FD0\u884C\u65F6\u3002`,\n \"story-long-scan\": `# story-long-scan \u2014 DSH \u539F\u751F\u957F\u7BC7\u626B\u699C\n\n\u57FA\u4E8E\u53EF\u6838\u9A8C\u6837\u672C\u8BC6\u522B\u957F\u7BC7\u7F51\u6587\u8D8B\u52BF\uFF0C\u4E0D\u8FD0\u884C\u6253\u5305\u811A\u672C\u3001\u4E0D\u63D0\u53D6\u767B\u5F55\u51ED\u636E\uFF0C\u4E5F\u4E0D\u7ED5\u8FC7\u9A8C\u8BC1\u7801\u3001\n\u8BBF\u95EE\u63A7\u5236\u6216\u7AD9\u70B9\u9650\u5236\u3002\n\n1. \u660E\u786E\u5E73\u53F0\u3001\u9891\u9053\u548C\u9898\u6750\u65B9\u5411\uFF1B\u53EA\u6709\u7B54\u6848\u4F1A\u6539\u53D8\u91C7\u6837\u8303\u56F4\u65F6\u624D\u95EE\u4E00\u4E2A\u95EE\u9898\u3002\n2. \u6570\u636E\u6765\u6E90\u4F9D\u6B21\u4E3A\uFF1A\u7528\u6237\u63D0\u4F9B\u7684\u6570\u636E\u6216\u94FE\u63A5\u3001\u5F53\u524D DSH Preset \u53EF\u89C1\u7684\u7F51\u9875\u5DE5\u5177\u3001\n references/genre-trends.md \u4E2D\u7684\u5386\u53F2\u8D8B\u52BF\u3002\u65E0\u6CD5\u83B7\u53D6\u5B9E\u65F6\u6570\u636E\u65F6\u5FC5\u987B\u660E\u786E\u6807\u4E3A\u5386\u53F2\u5047\u8BBE\u3002\n3. \u6BCF\u4E2A\u6837\u672C\u8BB0\u5F55\u6765\u6E90 URL\u3001\u91C7\u96C6\u65E5\u671F\u3001\u699C\u5355\u53E3\u5F84\u3001\u6709\u6548\u6761\u76EE\u6570\u3001\u7F3A\u5931\u5B57\u6BB5\u548C\u5F02\u5E38\u9879\uFF1B\n \u4E0D\u628A\u641C\u7D22\u6458\u8981\u3001\u63A8\u65AD\u6216\u8FC7\u671F\u7F13\u5B58\u5199\u6210\u9875\u9762\u4E8B\u5B9E\u3002\n4. \u6309\u9898\u6750\u5206\u5E03\u3001\u65B0\u9898\u6750\u4FE1\u53F7\u3001\u7ECF\u5178\u9898\u6750\u53D8\u5316\u3001\u7BC7\u5E45\u4E0E\u66F4\u65B0\u3001\u4E66\u540D\u6A21\u5F0F\u3001\u5F00\u5934\u5356\u70B9\u548C\n \u5DEE\u5F02\u5316\u5143\u7D20\u5206\u6790\u3002\u9700\u8981\u51B3\u7B56\u95E8\u7981\u65F6\u4F7F\u7528 references/topic-decision.md\u3002\n5. \u8F93\u51FA\u5E02\u573A\u6982\u51B5\u3001\u9898\u6750\u70ED\u5EA6\u3001\u8BC1\u636E\u4E0E\u53EF\u4FE1\u5EA6\u3001\u98CE\u9669\u3001\u4E09\u9879\u53EF\u6267\u884C\u65B9\u5411\u548C\u4E0B\u6B21\u590D\u626B\u65F6\u95F4\u3002\n\n\u5F53\u524D Preset \u6CA1\u6709\u7F51\u9875\u80FD\u529B\u4E14\u7528\u6237\u4E5F\u672A\u63D0\u4F9B\u6837\u672C\u65F6\uFF0C\u4F7F\u7528\u5185\u7F6E\u53C2\u8003\u5B8C\u6210\u65B9\u6CD5\u8BBA\u5206\u6790\uFF0C\n\u5E76\u5217\u51FA\u4ECD\u9700\u6838\u9A8C\u7684\u699C\u5355\uFF1B\u4E0D\u8981\u542F\u52A8 CDP\u3001\u72EC\u7ACB\u6D4F\u89C8\u5668\u6216\u5E76\u884C\u8FD0\u884C\u65F6\u3002`,\n \"story-short-scan\": `# story-short-scan \u2014 DSH \u539F\u751F\u77ED\u7BC7\u626B\u699C\n\n\u57FA\u4E8E\u53EF\u6838\u9A8C\u6837\u672C\u8BC6\u522B\u77ED\u7BC7\u5E02\u573A\u7684\u60C5\u7EEA\u3001\u9898\u6750\u4E0E\u4F20\u64AD\u4FE1\u53F7\uFF0C\u4E0D\u8FD0\u884C\u6253\u5305\u811A\u672C\u3001\u4E0D\u8BFB\u53D6 Cookie\n\u6216 token\uFF0C\u4E5F\u4E0D\u7ED5\u8FC7\u9A8C\u8BC1\u7801\u3001\u767B\u5F55\u6216\u8BBF\u95EE\u63A7\u5236\u3002\n\n1. \u660E\u786E\u5E73\u53F0\u4E0E\u65B9\u5411\uFF1B\u53EA\u6709\u7B54\u6848\u4F1A\u6539\u53D8\u91C7\u6837\u8303\u56F4\u65F6\u624D\u95EE\u4E00\u4E2A\u95EE\u9898\u3002\n2. \u6570\u636E\u6765\u6E90\u4F9D\u6B21\u4E3A\uFF1A\u7528\u6237\u63D0\u4F9B\u7684\u6570\u636E\u6216\u94FE\u63A5\u3001\u5F53\u524D DSH Preset \u53EF\u89C1\u7684\u7F51\u9875\u5DE5\u5177\u3001\n references/real-market-data.md \u4E2D\u7684\u5386\u53F2\u8D44\u6599\u3002\u65E0\u6CD5\u8054\u7F51\u65F6\u5FC5\u987B\u628A\u7ED3\u8BBA\u6807\u4E3A\u5019\u9009\u5047\u8BBE\u3002\n3. \u8BB0\u5F55\u6765\u6E90 URL\u3001\u91C7\u96C6\u65E5\u671F\u3001\u699C\u5355\u53E3\u5F84\u3001\u6709\u6548\u6837\u672C\u6570\u3001\u7F3A\u5931\u5B57\u6BB5\u548C\u5F02\u5E38\u9879\u3002\n4. \u5206\u6790\u60C5\u7EEA\u7C7B\u578B\u3001\u9898\u6750\u70ED\u70B9\u3001\u7BC7\u5E45\u3001\u5F00\u5934\u3001\u7ED3\u5C3E\u3001\u6807\u9898\u3001\u4EBA\u8BBE\u4E0E\u4F20\u64AD\u89E6\u53D1\u70B9\uFF1B\n \u7ED9\u6BCF\u4E2A\u8D8B\u52BF\u6807\u6CE8\u8BC1\u636E\u5F3A\u5EA6\u3001\u9971\u548C\u98CE\u9669\u548C\u6709\u6548\u671F\u3002\n5. \u8F93\u51FA\u5E02\u573A\u6982\u51B5\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\n\n\u5F53\u524D Preset \u6CA1\u6709\u7F51\u9875\u80FD\u529B\u4E14\u7528\u6237\u4E5F\u672A\u63D0\u4F9B\u6837\u672C\u65F6\uFF0C\u53EA\u505A\u5386\u53F2\u8D44\u6599\u5206\u6790\u5E76\u5217\u51FA\u9A8C\u8BC1\u52A8\u4F5C\uFF1B\n\u4E0D\u8981\u542F\u52A8 CDP\u3001\u72EC\u7ACB\u6D4F\u89C8\u5668\u6216\u5E76\u884C\u8FD0\u884C\u65F6\u3002`\n};\n\ninterface ParsedSkill {\n readonly name: string;\n readonly description: string;\n readonly content: string;\n}\n\nfunction frontmatterValue(frontmatter: string, key: string): string | undefined {\n const match = new RegExp(`^${key}:\\\\s*(.+)$`, \"mu\").exec(frontmatter);\n const raw = match?.[1]?.trim();\n if (raw === undefined) return undefined;\n if (raw.startsWith(\"\\\"\") && raw.endsWith(\"\\\"\")) {\n try { return JSON.parse(raw) as string; }\n catch { return raw.slice(1, -1); }\n }\n return raw.replace(/^['\"]|['\"]$/gu, \"\");\n}\n\nexport function parseBundledSkill(source: string): ParsedSkill {\n const match = /^---\\r?\\n([\\s\\S]*?)\\r?\\n---\\r?\\n?/u.exec(source);\n if (match?.[1] === undefined) throw new Error(\"Bundled skill is missing YAML frontmatter.\");\n const name = frontmatterValue(match[1], \"name\");\n const description = frontmatterValue(match[1], \"description\");\n if (!name || !/^[a-z0-9]+(?:-[a-z0-9]+)*$/u.test(name)) throw new Error(\"Bundled skill has an invalid name.\");\n if (!description) throw new Error(`Bundled skill \"${name}\" has no description.`);\n return { name, description, content: source.slice(match[0].length) };\n}\n\nexport function dshSkillContent(name: string, content: string): string {\n const override = DSH_SKILL_OVERRIDES[name];\n const native = DSH_NATIVE_SKILLS[name];\n return `${DSH_SKILL_BRIDGE}${override === undefined ? \"\" : `\\n<skill-specific-dsh-override>${override}</skill-specific-dsh-override>`}\\n\\n${native ?? content}`;\n}\n\nexport function defaultBundledSkillRoot(): string {\n const current = dirname(fileURLToPath(import.meta.url));\n return basename(current) === \"src\"\n ? resolve(current, \"../../knowledge/oh-story/skills\")\n : resolve(current, \"oh-story/skills\");\n}\n\nexport function defaultDramaSkillRoot(): string {\n const current = dirname(fileURLToPath(import.meta.url));\n return basename(current) === \"src\"\n ? resolve(current, \"../../knowledge/drama/skills\")\n : resolve(current, \"drama/skills\");\n}\n\nfunction createBundledSkillProvider(\n providerName: string,\n skillRoot: string,\n content: (name: string, source: string) => string\n): SkillProvider {\n const root = resolve(skillRoot);\n return {\n name: providerName,\n async list(): Promise<readonly SkillCandidate[]> {\n const directories = (await readdir(root, { withFileTypes: true }))\n .filter((entry) => entry.isDirectory())\n .map((entry) => entry.name)\n .sort();\n return Promise.all(directories.map(async (directory): Promise<SkillCandidate> => {\n const path = join(root, directory, \"SKILL.md\");\n const parsed = parseBundledSkill(await readFile(path, \"utf8\"));\n if (parsed.name !== directory) throw new Error(`Bundled skill directory \"${directory}\" does not match name \"${parsed.name}\".`);\n return {\n name: parsed.name,\n description: parsed.description,\n invocation: INVOCATION,\n provider: providerName,\n source: \"bundled\",\n resourceBase: { kind: \"directory\", path: join(root, directory) },\n rank: BUNDLED_SKILL_RANK,\n locator: pathToFileURL(path),\n path\n };\n }));\n },\n async get(candidate): Promise<SkillDefinition | undefined> {\n if (candidate.provider !== providerName || typeof candidate.path !== \"string\") return undefined;\n const path = resolve(candidate.path);\n const relativePath = relative(root, path);\n if (relativePath === \"\" || relativePath.startsWith(\"..\") || isAbsolute(relativePath)) {\n throw new Error(\"Bundled skill locator escaped the packaged skill root.\");\n }\n const parsed = parseBundledSkill(await readFile(path, \"utf8\"));\n if (parsed.name !== candidate.name) return undefined;\n return {\n name: parsed.name,\n description: parsed.description,\n invocation: INVOCATION,\n provider: providerName,\n source: \"bundled\",\n resourceBase: { kind: \"directory\", path: join(root, parsed.name) },\n path,\n content: content(parsed.name, parsed.content)\n };\n }\n };\n}\n\nexport function createOhStorySkillProvider(skillRoot = defaultBundledSkillRoot()): SkillProvider {\n return createBundledSkillProvider(STORY_PROVIDER_NAME, skillRoot, dshSkillContent);\n}\n\nexport function dshDramaSkillContent(name: string, content: string): string {\n const override = DSH_DRAMA_OVERRIDES[name];\n return `${DSH_DRAMA_BRIDGE}${override === undefined ? \"\" : `\\n<skill-specific-dsh-override>${override}</skill-specific-dsh-override>`}\\n\\n${content}`;\n}\n\nexport function createDramaSkillProvider(skillRoot = defaultDramaSkillRoot()): SkillProvider {\n return createBundledSkillProvider(DRAMA_PROVIDER_NAME, skillRoot, dshDramaSkillContent);\n}\n", "import type { Context } from \"@deepseek-ai/cordis\";\nimport type { FileSystem, FsTarget } from \"@deepseek-ai/dsh-fs\";\nimport { createUserMessage } from \"@deepseek-ai/dsh-llm\";\nimport type { PostToolDecision, PreToolDecision, ToolExecution } from \"@deepseek-ai/dsh-tools\";\n\nconst MUTATION_TOOLS = new Set([\"write\", \"edit\", \"str_replace_editor\"]);\n\nexport interface StoryMutation {\n readonly root: string;\n readonly path: string;\n readonly chapter?: number;\n}\n\nfunction mutationPath(name: string, args: unknown): string | undefined {\n if (!MUTATION_TOOLS.has(name) || typeof args !== \"object\" || args === null || Array.isArray(args)) return undefined;\n const record = args as Record<string, unknown>;\n if (name === \"str_replace_editor\") {\n if (!new Set([\"create\", \"str_replace\", \"insert\"]).has(String(record.command))) return undefined;\n return typeof record.path === \"string\" && record.path.trim() !== \"\" ? record.path : undefined;\n }\n return typeof record.file_path === \"string\" && record.file_path.trim() !== \"\" ? record.file_path : undefined;\n}\n\nfunction normalizedRelativePath(path: string): string | undefined {\n const segments: string[] = [];\n for (const part of path.split(\"/\")) {\n if (part === \"\" || part === \".\") continue;\n if (part === \"..\") {\n if (segments.length === 0) return undefined;\n segments.pop();\n } else segments.push(part);\n }\n return segments.join(\"/\");\n}\n\nexport function detectStoryMutation(name: string, args: unknown, cwd: string | undefined): StoryMutation | undefined {\n const rawPath = mutationPath(name, args);\n if (cwd === undefined || rawPath === undefined) return undefined;\n const root = cwd.replaceAll(\"\\\\\", \"/\").replace(/\\/$/u, \"\");\n const candidate = rawPath.replaceAll(\"\\\\\", \"/\");\n const absolute = candidate.startsWith(\"/\") || /^[a-z]:\\//iu.test(candidate) || /^[a-z][a-z\\d+.-]*:\\/\\//iu.test(candidate);\n const insideRoot = /^[a-z]:\\//iu.test(root)\n ? candidate.toLowerCase().startsWith(`${root.toLowerCase()}/`)\n : candidate.startsWith(`${root}/`);\n if (absolute && !insideRoot) return undefined;\n const normalized = normalizedRelativePath(absolute ? candidate.slice(root.length + 1) : candidate);\n if (normalized === undefined) return undefined;\n if (!normalized.startsWith(\"\u6B63\u6587/\")) return undefined;\n const chapterText = /\u7B2C0*(\\d+)\u7AE0/u.exec(normalized)?.[1];\n return { root, path: normalized, ...(chapterText === undefined ? {} : { chapter: Number(chapterText) }) };\n}\n\ntype StoryFileSystem = Pick<FileSystem, \"resolve\" | \"contains\" | \"stat\" | \"listDir\">;\n\nasync function storyMutation(exec: ToolExecution, fs: StoryFileSystem): Promise<StoryMutation | undefined> {\n const cwd = exec.agent?.session.header.cwd;\n const path = mutationPath(exec.name, exec.arguments);\n if (cwd === undefined || path === undefined) return undefined;\n try {\n const [rootTarget, mutationTarget] = await Promise.all([\n fs.resolve(cwd, { signal: exec.signal }),\n fs.resolve(path, { cwd, signal: exec.signal })\n ]);\n if (!fs.contains(rootTarget, mutationTarget)) return undefined;\n } catch { return undefined; }\n return detectStoryMutation(exec.name, exec.arguments, cwd);\n}\n\nasync function target(fs: StoryFileSystem, root: string, path: string, signal?: AbortSignal): Promise<FsTarget> {\n return fs.resolve(path, { cwd: root, ...(signal === undefined ? {} : { signal }) });\n}\n\nasync function exists(fs: StoryFileSystem, root: string, path: string, signal?: AbortSignal): Promise<boolean> {\n return target(fs, root, path, signal)\n .then((value) => fs.stat(value, signal))\n .then((info) => info !== undefined, () => false);\n}\n\nasync function hasChapterOutline(fs: StoryFileSystem, root: string, chapter: number, signal?: AbortSignal): Promise<boolean> {\n const entries = await target(fs, root, \"\u5927\u7EB2\", signal)\n .then((directory) => fs.listDir(directory, signal))\n .catch(() => []);\n return entries.some((entry) => entry.type === \"file\"\n && Number(/^\u7EC6\u7EB2_\u7B2C0*(\\d+)\u7AE0.*\\.md$/u.exec(entry.name)?.[1]) === chapter);\n}\n\nexport async function validateStoryMutation(\n fs: StoryFileSystem,\n mutation: StoryMutation,\n signal?: AbortSignal\n): Promise<string | undefined> {\n const hasLongFormLayout = await exists(fs, mutation.root, \"\u5927\u7EB2\", signal)\n || await exists(fs, mutation.root, \"\u8FFD\u8E2A\", signal);\n if (!hasLongFormLayout) return undefined;\n if (!(await exists(fs, mutation.root, \"\u8FFD\u8E2A/_tracking-state.json\", signal))) {\n // Setup/import must be able to bootstrap an existing manuscript before the\n // canonical Tracking file exists. The Skill remains responsible for\n // creating it; hard guards begin once the project has committed Tracking.\n return undefined;\n }\n if (mutation.chapter !== undefined && !(await hasChapterOutline(fs, mutation.root, mutation.chapter, signal))) {\n 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`;\n }\n return undefined;\n}\n\nexport async function decideStoryMutation(\n exec: ToolExecution,\n next: () => Promise<PreToolDecision>\n): Promise<PreToolDecision> {\n const fs = exec.agent?.ctx.get(\"fs\");\n if (fs === undefined) return next();\n const mutation = await storyMutation(exec, fs);\n if (mutation === undefined) return next();\n const reason = await validateStoryMutation(fs, mutation, exec.signal);\n if (reason !== undefined) return { kind: \"deny\", reason };\n return next();\n}\n\n/**\n * Native DSH equivalents of the upstream prose guards. They join DSH's typed\n * tool waterfall, so decisions remain visible in the official approval/tool UI.\n */\nexport function registerOhStoryHooks(context: Context): void {\n context.on(\"tools/pre-execute\", decideStoryMutation);\n\n context.on(\"tools/post-execute\", async (exec, result, next): Promise<PostToolDecision> => {\n const downstream = await next();\n if (result.isError || downstream.kind !== \"accept\") return downstream;\n const fs = exec.agent?.ctx.get(\"fs\");\n const mutation = fs === undefined ? undefined : await storyMutation(exec, fs);\n if (mutation === undefined) return downstream;\n const reminder = createUserMessage({\n source: { kind: \"plugin\", plugin: \"oh-story\" },\n content: [{\n type: \"text\",\n 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>`\n }]\n });\n return {\n ...downstream,\n additionalContexts: [...downstream.additionalContexts ?? [], reminder]\n };\n });\n}\n", "import type { Context } from \"@deepseek-ai/cordis\";\nimport type { ContentBlock } from \"@deepseek-ai/dsh-llm\";\nimport type { JsonValue } from \"@deepseek-ai/dsh-session\";\nimport { defineTool, type ToolDefinition } from \"@deepseek-ai/dsh-tools\";\nimport { OH_STORY_ROLE_NAMES, loadBundledRole, type OhStoryRoleName } from \"./role-provider.js\";\n\nexport const OH_STORY_ROLE_TOOL_NAME = \"oh_story_role\";\n\nconst roleTools: Readonly<Record<OhStoryRoleName, readonly string[]>> = {\n \"chapter-extractor\": [\"read\", \"glob\", \"grep\"],\n \"character-designer\": [\"read\", \"glob\", \"grep\", \"write\", \"edit\"],\n \"consistency-checker\": [\"read\", \"glob\", \"grep\"],\n \"narrative-writer\": [\"read\", \"glob\", \"grep\", \"write\", \"edit\", \"bash\"],\n \"story-architect\": [\"read\", \"glob\", \"grep\", \"write\", \"edit\"],\n \"story-explorer\": [\"read\", \"glob\", \"grep\"],\n \"story-researcher\": [\"read\", \"glob\", \"grep\", \"bash\", \"write\", \"web_search\", \"web_fetch\"]\n};\n\nexport function roleToolFilter(role: OhStoryRoleName): { readonly allow: readonly string[] } {\n return { allow: roleTools[role] };\n}\n\nfunction resultText(output: readonly ContentBlock[]): string {\n return output.map((block) => block.type === \"text\" ? block.text : JSON.stringify(block)).join(\"\\n\");\n}\n\nexport async function createOhStoryRoleTool(): Promise<ToolDefinition> {\n const personas = new Map<OhStoryRoleName, string>();\n await Promise.all(OH_STORY_ROLE_NAMES.map(async (role) => {\n personas.set(role, await loadBundledRole(role, undefined, \"native-tools\"));\n }));\n return defineTool({\n name: OH_STORY_ROLE_TOOL_NAME,\n description: \"Run one focused Oh Story specialist as a child of the current DSH Agent. The child inherits DSH model, workspace, permissions, lifecycle, and UI.\",\n parameters: {\n role: {\n type: \"string\",\n required: true,\n enum: OH_STORY_ROLE_NAMES,\n description: \"The exact Oh Story Role to run.\"\n },\n prompt: {\n type: \"string\",\n required: true,\n description: \"A self-contained task. The child inherits the current DSH workspace but not the current in-flight turn.\"\n }\n },\n output: {\n schema: {\n type: \"object\",\n additionalProperties: false,\n properties: {\n role: { type: \"string\", required: true, enum: OH_STORY_ROLE_NAMES },\n runId: { type: \"string\", required: true },\n content: { type: \"array\", required: true, items: { type: \"json\" } }\n }\n },\n render: (_args, value) => [{ type: \"text\", text: resultText(value.content as unknown as ContentBlock[]) }]\n },\n isConcurrencySafe: () => true,\n async execute(args, exec) {\n if (exec.agent === undefined) throw new Error(\"oh_story_role requires a calling DSH Agent.\");\n const persona = personas.get(args.role);\n if (persona === undefined) throw new Error(`Oh Story Role ${args.role} is not bundled.`);\n const allowed = roleToolFilter(args.role).allow.filter((name) =>\n exec.agent?.ctx.tools.get(name, exec.agent) !== undefined);\n const run = await exec.agent.ctx.subagents.start(\"spawn\", {\n label: `oh-story:${args.role}`,\n prompt: [{ type: \"text\", text: args.prompt }],\n parent: exec.agent,\n persona,\n toolFilter: { allow: allowed },\n maxDepth: 1,\n signal: exec.signal\n });\n try {\n const result = await run.result;\n if (result.stopReason !== \"completed\") {\n throw new Error(`Oh Story Role ${args.role} ended with ${result.stopReason}${result.diagnostic === undefined ? \"\" : `: ${result.diagnostic}`}`);\n }\n return {\n role: args.role,\n runId: run.id,\n content: result.output as unknown as JsonValue[]\n };\n } finally {\n await run.dispose();\n }\n }\n });\n}\n\nexport async function registerOhStoryRoleTool(context: Context): Promise<void> {\n const definition = await createOhStoryRoleTool();\n let dispose: (() => void) | undefined;\n const mount = (): void => { dispose ??= context.tools.register(definition); };\n const unmount = (): void => { dispose?.(); dispose = undefined; };\n context.on(\"subagent/provider-added\", (provider) => { if (provider.name === \"spawn\") mount(); });\n context.on(\"subagent/provider-removed\", (name) => { if (name === \"spawn\") unmount(); });\n if (context.subagents.getProvider(\"spawn\") !== undefined) mount();\n}\n", "import { readFile } from \"node:fs/promises\";\nimport { basename, dirname, join, resolve } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nexport const OH_STORY_ROLE_NAMES = [\n \"chapter-extractor\",\n \"character-designer\",\n \"consistency-checker\",\n \"narrative-writer\",\n \"story-architect\",\n \"story-explorer\",\n \"story-researcher\"\n] as const;\n\nexport type OhStoryRoleName = typeof OH_STORY_ROLE_NAMES[number];\nexport type OhStoryRoleExecution = \"tool-free\" | \"native-tools\";\n\nfunction roleBody(source: string): string {\n const frontmatter = /^---\\r?\\n[\\s\\S]*?\\r?\\n---\\r?\\n?/u.exec(source);\n return source.slice(frontmatter?.[0].length ?? 0).trim();\n}\n\nexport function defaultBundledRoleRoot(): string {\n const current = dirname(fileURLToPath(import.meta.url));\n return basename(current) === \"src\"\n ? resolve(current, \"../../knowledge/oh-story/roles\")\n : resolve(current, \"oh-story/roles\");\n}\n\nexport async function loadBundledRole(\n name: OhStoryRoleName,\n roleRoot = defaultBundledRoleRoot(),\n execution: OhStoryRoleExecution = \"tool-free\"\n): Promise<string> {\n const body = roleBody(await readFile(join(resolve(roleRoot), `${name}.md`), \"utf8\"));\n if (body.length === 0) throw new Error(`Bundled role \"${name}\" is empty.`);\n const integration = execution === \"tool-free\"\n ? [\n \"You are running inside an Oh Story review-required DSH collaboration. The caller supplies every permitted input in the prompt.\",\n \"Do not read or write project files, do not call tools, and do not follow legacy .claude/.codex path or deployment instructions in the upstream role text.\",\n \"Return only the output contract requested by the caller; never claim to have changed the project.\"\n ]\n : [\n \"You are running as a native oh-story-dsh specialist. The current DSH workspace and visible tool set are your complete authority boundary.\",\n \"Never inspect or require legacy .claude/.opencode/.codex agent deployment files; this exact pinned Role is already active.\",\n \"Use only the tools actually visible to you. Mutate files only when the caller explicitly requests it and your visible DSH tools permit it; otherwise return findings to the caller.\"\n ];\n return [\n `OH_STORY_DSH_ROLE:${name}`,\n ...integration,\n \"\",\n body\n ].join(\"\\n\");\n}\n", "import type { IncomingMessage, ServerResponse } from \"node:http\";\nimport { extname } from \"node:path\";\nimport type { Context } from \"@deepseek-ai/cordis\";\nimport type { Agent } from \"@deepseek-ai/dsh-agent\";\nimport { FsError, type FileSystem, type FsInfo, type FsTarget, type FsVersion } from \"@deepseek-ai/dsh-fs\";\nimport type {} from \"@deepseek-ai/dsh-host-webserver\";\nimport type { SandboxPolicyService } from \"@deepseek-ai/dsh-sandbox-policy\";\nimport { SessionId } from \"@deepseek-ai/dsh-session\";\nimport type {} from \"@deepseek-ai/dsh-typert-registry\";\nimport { isTrustedWorkspaceRequest } from \"./workspace-request-trust.js\";\n\nconst STORY_DIRECTORIES = [\"\u6B63\u6587\", \"\u5927\u7EB2\", \"\u8BBE\u5B9A\", \"\u8FFD\u8E2A\", \"\u5BF9\u6807\", \"\u53C2\u8003\u8D44\u6599\"] as const;\nconst DRAMA_DIRECTORIES = [\"\u8F93\u5165\", \"\u9879\u76EE\u5F00\u53D1\", \"\u8BBE\u5B9A\u96C6\", \"\u5267\u96C6\", \"\u4EA4\u4ED8\", \"\u521B\u4F5C\u8005\u51B3\u7B56\", \"\u5BA1\u67E5\"] as const;\nconst CREATIVE_DIRECTORIES = [...STORY_DIRECTORIES, ...DRAMA_DIRECTORIES] as const;\nconst ROOT_FILES = new Set([\"short-drama.json\"]);\nconst EDITABLE_EXTENSIONS = new Set([\".md\", \".txt\", \".json\", \".jsonl\"]);\nconst FILE_LIMIT = 1_000;\n\ninterface WorkspaceRouteOptions {\n readonly maxBytes: number;\n readonly trustedHosts?: readonly string[];\n}\n\ninterface WorkspaceFile {\n readonly path: string;\n readonly bytes: number;\n readonly version: string;\n}\n\ninterface WorkspaceRealm {\n readonly agent: Agent;\n readonly fs: FileSystem;\n readonly sandboxPolicy: SandboxPolicyService;\n readonly cwd: string;\n readonly root: FsTarget;\n}\n\ninterface ReadFileResult {\n readonly content: string;\n readonly bytes: number;\n readonly version: FsVersion;\n}\n\nclass WorkspaceHttpError extends Error {\n constructor(readonly status: number, message: string) { super(message); }\n}\n\nfunction send(response: ServerResponse, status: number, value: unknown): void {\n const body = `${JSON.stringify(value)}\\n`;\n response.writeHead(status, {\n \"content-type\": \"application/json; charset=utf-8\",\n \"content-length\": Buffer.byteLength(body),\n \"cache-control\": \"no-store\",\n \"x-content-type-options\": \"nosniff\"\n });\n response.end(body);\n}\n\nasync function jsonBody(request: IncomingMessage, maxBytes: number): Promise<Record<string, unknown>> {\n const chunks: Buffer[] = [];\n let size = 0;\n for await (const chunk of request as AsyncIterable<Uint8Array>) {\n const value = Buffer.from(chunk);\n size += value.byteLength;\n if (size > maxBytes) throw new WorkspaceHttpError(413, \"\u8BF7\u6C42\u5185\u5BB9\u8FC7\u5927\u3002\");\n chunks.push(value);\n }\n try {\n const value = JSON.parse(Buffer.concat(chunks).toString(\"utf8\")) as unknown;\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) throw new Error();\n return value as Record<string, unknown>;\n } catch {\n throw new WorkspaceHttpError(400, \"\u8BF7\u6C42\u5FC5\u987B\u662F JSON \u5BF9\u8C61\u3002\");\n }\n}\n\nfunction assertCreativePath(path: string): void {\n if (!EDITABLE_EXTENSIONS.has(extname(path).toLocaleLowerCase())) {\n throw new WorkspaceHttpError(415, \"\u5DE5\u4F5C\u53F0\u53EA\u7F16\u8F91 Markdown\u3001\u6587\u672C\u3001JSON \u548C JSONL \u6587\u4EF6\u3002\");\n }\n if (path.startsWith(\"/\") || path.includes(\"\\\\\") || path.split(\"/\").some((segment) => segment === \"\" || segment === \".\" || segment === \"..\")) {\n throw new WorkspaceHttpError(403, \"\u6587\u4EF6\u8DEF\u5F84\u4E0D\u5728\u521B\u4F5C\u5DE5\u4F5C\u53F0\u4E2D\u3002\");\n }\n const root = path.split(\"/\", 1)[0];\n if (!CREATIVE_DIRECTORIES.some((directory) => directory === root) && !ROOT_FILES.has(path)) {\n throw new WorkspaceHttpError(403, \"\u6587\u4EF6\u8DEF\u5F84\u4E0D\u5728\u521B\u4F5C\u5DE5\u4F5C\u53F0\u4E2D\u3002\");\n }\n}\n\nasync function workspaceRealm(context: Context, url: URL): Promise<WorkspaceRealm> {\n const rawId = url.searchParams.get(\"sessionId\");\n if (rawId === null || rawId === \"\") throw new WorkspaceHttpError(400, \"\u7F3A\u5C11 DSH sessionId\u3002\");\n const lookup = context.typert.lookups.get(\"agent\");\n if (lookup === undefined) throw new WorkspaceHttpError(503, \"DSH Agent lookup \u5F53\u524D\u4E0D\u53EF\u7528\u3002\");\n let agent: Agent | undefined;\n try {\n agent = await lookup.resolve(SessionId(rawId)) as Agent | undefined;\n } catch {\n throw new WorkspaceHttpError(404, \"DSH \u4F1A\u8BDD\u4E0D\u53EF\u7528\u3002\");\n }\n if (agent === undefined) throw new WorkspaceHttpError(404, \"DSH \u4F1A\u8BDD\u4E0D\u53EF\u7528\u3002\");\n if (agent.session.header.parentSession !== undefined || agent.session.header.origin === \"subagent\") {\n throw new WorkspaceHttpError(403, \"\u5B50 Agent \u4F1A\u8BDD\u4E0D\u5F00\u653E\u521B\u4F5C\u7F16\u8F91\u5668\u3002\");\n }\n const cwd = agent.session.header.cwd;\n if (cwd === undefined) throw new WorkspaceHttpError(409, \"\u5F53\u524D DSH \u4F1A\u8BDD\u6CA1\u6709\u5DE5\u4F5C\u76EE\u5F55\u3002\");\n const fs = agent.ctx.get(\"fs\");\n const sandboxPolicy = agent.ctx.get(\"sandboxPolicy\");\n if (fs === undefined || sandboxPolicy === undefined) throw new WorkspaceHttpError(503, \"DSH \u6587\u4EF6\u7CFB\u7EDF\u5F53\u524D\u4E0D\u53EF\u7528\u3002\");\n return { agent, fs, sandboxPolicy, cwd, root: await fs.resolve(cwd) };\n}\n\nasync function creativeTarget(realm: WorkspaceRealm, path: string): Promise<FsTarget> {\n assertCreativePath(path);\n const target = await realm.fs.resolve(path, { cwd: realm.cwd });\n if (!realm.fs.contains(realm.root, target)) throw new WorkspaceHttpError(403, \"\u6587\u4EF6\u8DEF\u5F84\u79BB\u5F00\u4E86 DSH \u5DE5\u4F5C\u76EE\u5F55\u3002\");\n return target;\n}\n\nfunction requireRegularFile(info: FsInfo | undefined): FsInfo {\n if (info === undefined) throw new WorkspaceHttpError(404, \"\u6587\u4EF6\u4E0D\u5B58\u5728\u3002\");\n if (info.type !== \"file\") throw new WorkspaceHttpError(415, \"\u76EE\u6807\u4E0D\u662F\u53EF\u7F16\u8F91\u7684\u666E\u901A\u6587\u4EF6\u3002\");\n return info;\n}\n\n/** Read bytes and a matching opaque version, retrying if a writer wins the read window. */\nasync function readVersionedFile(fs: FileSystem, target: FsTarget, maxBytes: number): Promise<ReadFileResult> {\n for (let attempt = 0; attempt < 3; attempt += 1) {\n const before = requireRegularFile(await fs.stat(target));\n if (before.size !== undefined && before.size > maxBytes) throw new WorkspaceHttpError(413, \"\u6587\u4EF6\u8D85\u8FC7\u5DE5\u4F5C\u53F0\u5927\u5C0F\u9650\u5236\u3002\");\n const bytes = await fs.readBytes(target, undefined, maxBytes);\n const after = requireRegularFile(await fs.stat(target));\n if (before.version !== after.version) continue;\n let content: string;\n try {\n content = new TextDecoder(\"utf-8\", { fatal: true }).decode(bytes);\n } catch {\n throw new WorkspaceHttpError(415, \"\u6587\u4EF6\u4E0D\u662F\u6709\u6548\u7684 UTF-8 \u6587\u672C\u3002\");\n }\n return { content, bytes: bytes.byteLength, version: after.version };\n }\n throw new WorkspaceHttpError(409, \"\u6587\u4EF6\u6B63\u5728\u88AB\u4FEE\u6539\uFF0C\u8BF7\u91CD\u8BD5\u3002\");\n}\n\nasync function listFiles(realm: WorkspaceRealm): Promise<WorkspaceFile[]> {\n const files: WorkspaceFile[] = [];\n const walk = async (path: string, directory: FsTarget): Promise<void> => {\n for (const entry of await realm.fs.listDir(directory)) {\n if (entry.name.startsWith(\".\") || !realm.fs.contains(realm.root, entry.target)) continue;\n const childPath = `${path}/${entry.name}`;\n if (entry.type === \"directory\") await walk(childPath, entry.target);\n else if (entry.type === \"file\" && EDITABLE_EXTENSIONS.has(extname(entry.name).toLocaleLowerCase())) {\n const info = entry.version === undefined || entry.size === undefined ? await realm.fs.stat(entry.target) : undefined;\n const version = entry.version ?? info?.version;\n if (version !== undefined) files.push({ path: childPath, bytes: entry.size ?? info?.size ?? 0, version });\n }\n if (files.length >= FILE_LIMIT) return;\n }\n };\n for (const directory of CREATIVE_DIRECTORIES) {\n const target = await realm.fs.resolve(directory, { cwd: realm.cwd });\n if (!realm.fs.contains(realm.root, target)) continue;\n const info = await realm.fs.stat(target);\n if (info?.type === \"directory\") await walk(directory, target);\n if (files.length >= FILE_LIMIT) break;\n }\n for (const path of ROOT_FILES) {\n const target = await creativeTarget(realm, path);\n const info = await realm.fs.stat(target);\n if (info?.type === \"file\") files.push({ path, bytes: info.size ?? 0, version: info.version });\n }\n return files.sort((left, right) => left.path.localeCompare(right.path, \"zh-Hans-CN\"));\n}\n\nasync function metadata(realm: WorkspaceRealm, files: readonly WorkspaceFile[], path: string, maxBytes: number): Promise<{ readonly value: unknown; readonly error?: string }> {\n if (!files.some((file) => file.path === path)) return { value: null };\n try {\n const target = await creativeTarget(realm, path);\n return { value: JSON.parse((await readVersionedFile(realm.fs, target, maxBytes)).content) as unknown };\n } catch (error) {\n return { value: null, error: error instanceof SyntaxError ? `${path} \u4E0D\u662F\u6709\u6548\u7684 JSON\u3002` : `${path} \u6682\u65F6\u65E0\u6CD5\u8BFB\u53D6\u3002` };\n }\n}\n\nfunction mapFsError(error: unknown): WorkspaceHttpError | undefined {\n if (!(error instanceof FsError)) return undefined;\n switch (error.code) {\n case \"FS_NOT_FOUND\": return new WorkspaceHttpError(404, \"\u6587\u4EF6\u4E0D\u5B58\u5728\u3002\");\n case \"FS_TOO_LARGE\": return new WorkspaceHttpError(413, \"\u6587\u4EF6\u8D85\u8FC7\u5DE5\u4F5C\u53F0\u5927\u5C0F\u9650\u5236\u3002\");\n case \"FS_NOT_TEXT\":\n case \"FS_NOT_REGULAR_FILE\": return new WorkspaceHttpError(415, \"\u76EE\u6807\u4E0D\u662F\u53EF\u7F16\u8F91\u7684\u6587\u672C\u6587\u4EF6\u3002\");\n case \"FS_PERMISSION_DENIED\":\n case \"FS_SANDBOX_DENIED\": return new WorkspaceHttpError(403, \"\u5F53\u524D DSH \u6743\u9650\u4E0D\u5141\u8BB8\u4FEE\u6539\u8BE5\u6587\u4EF6\u3002\");\n case \"FS_STALE_VERSION\":\n case \"FS_NOT_OBSERVED\": return new WorkspaceHttpError(412, \"\u6587\u4EF6\u5DF2\u5728\u78C1\u76D8\u4E0A\u66F4\u65B0\u3002\u8BF7\u5904\u7406\u51B2\u7A81\u540E\u518D\u4FDD\u5B58\u3002\");\n case \"FS_ABORTED\": return new WorkspaceHttpError(409, \"\u6587\u4EF6\u64CD\u4F5C\u5DF2\u53D6\u6D88\u3002\");\n default: return new WorkspaceHttpError(500, \"DSH \u6587\u4EF6\u7CFB\u7EDF\u64CD\u4F5C\u5931\u8D25\u3002\");\n }\n}\n\nasync function handle(context: Context, request: IncomingMessage, response: ServerResponse, options: WorkspaceRouteOptions): Promise<void> {\n try {\n if (!isTrustedWorkspaceRequest(request, options.trustedHosts ?? [])) throw new WorkspaceHttpError(403, \"\u8BF7\u6C42\u6765\u6E90\u4E0D\u53D7\u4FE1\u4EFB\u3002\");\n const url = new URL(request.url ?? \"/\", \"http://127.0.0.1\");\n if (url.pathname === \"/oh-story/workspace\" && request.method === \"GET\") {\n const realm = await workspaceRealm(context, url);\n const files = await listFiles(realm);\n const tracking = await metadata(realm, files, \"\u8FFD\u8E2A/_tracking-state.json\", options.maxBytes);\n const shortDrama = await metadata(realm, files, \"short-drama.json\", options.maxBytes);\n const metadataErrors = [tracking.error, shortDrama.error].filter((value): value is string => value !== undefined);\n send(response, 200, { cwd: realm.cwd, files, tracking: tracking.value, shortDrama: shortDrama.value, metadataErrors, mode: \"dsh-session\" });\n return;\n }\n if (url.pathname === \"/oh-story/file\" && request.method === \"GET\") {\n const realm = await workspaceRealm(context, url);\n const path = url.searchParams.get(\"path\");\n if (path === null) throw new WorkspaceHttpError(400, \"\u7F3A\u5C11\u6587\u4EF6\u8DEF\u5F84\u3002\");\n const file = await readVersionedFile(realm.fs, await creativeTarget(realm, path), options.maxBytes);\n send(response, 200, { path, ...file });\n return;\n }\n if (url.pathname === \"/oh-story/file\" && request.method === \"PUT\") {\n const realm = await workspaceRealm(context, url);\n const path = url.searchParams.get(\"path\");\n if (path === null) throw new WorkspaceHttpError(400, \"\u7F3A\u5C11\u6587\u4EF6\u8DEF\u5F84\u3002\");\n const input = await jsonBody(request, options.maxBytes * 6 + 1_024);\n if (typeof input.content !== \"string\") throw new WorkspaceHttpError(400, \"content \u5FC5\u987B\u662F\u5B57\u7B26\u4E32\u3002\");\n if (typeof input.baseVersion !== \"string\" || input.baseVersion === \"\") throw new WorkspaceHttpError(400, \"baseVersion \u5FC5\u987B\u662F\u6709\u6548\u7248\u672C\u3002\");\n if (Buffer.byteLength(input.content) > options.maxBytes) throw new WorkspaceHttpError(413, \"\u6587\u4EF6\u8D85\u8FC7\u5DE5\u4F5C\u53F0\u5927\u5C0F\u9650\u5236\u3002\");\n const outcome = await realm.fs.writeText(\n await creativeTarget(realm, path),\n input.content,\n { kind: \"replaceIfVersion\", version: input.baseVersion as FsVersion },\n undefined,\n realm.sandboxPolicy.resolve({ session: realm.agent.session })\n );\n send(response, 200, { path, content: outcome.after, bytes: Buffer.byteLength(outcome.after), version: outcome.version });\n return;\n }\n send(response, 404, { error: \"Oh Story route not found.\" });\n } catch (error) {\n const mapped = error instanceof WorkspaceHttpError ? error : mapFsError(error);\n if (mapped === undefined) context.logger(\"oh-story\").error(\"workspace route failed\", error);\n send(response, mapped?.status ?? 500, { error: mapped?.message ?? \"Oh Story workspace operation failed.\" });\n }\n}\n\n/** Mount the narrow editor API on DSH's official web-server extension seam. */\nexport function registerWorkspaceRoute(context: Context, options: WorkspaceRouteOptions): void {\n context.effect(() => context.webServer.register({\n kind: \"prefix\",\n path: \"/oh-story\",\n handler: (request, response) => handle(context, request, response, options)\n }), \"oh-story: DSH-session workspace API\");\n}\n", "import type { IncomingHttpHeaders } from \"node:http\";\n\ninterface WorkspaceTrustRequest {\n readonly headers: IncomingHttpHeaders | Headers;\n}\n\nfunction header(headers: IncomingHttpHeaders | Headers, name: string): string | undefined {\n if (headers instanceof Headers) return headers.get(name) ?? undefined;\n const value = headers[name];\n return typeof value === \"string\" ? value : undefined;\n}\n\nfunction parseAuthority(authority: string): URL | undefined {\n try { return new URL(`http://${authority}`); }\n catch { return undefined; }\n}\n\nfunction canonicalAuthority(entry: string, url: URL): string {\n const port = url.port !== \"\" ? url.port : new URL(`https://${entry}`).port;\n return port === \"\" ? url.hostname : `${url.hostname}:${port}`;\n}\n\nfunction isLoopbackHostname(hostname: string): boolean {\n if (hostname === \"localhost\" || hostname === \"[::1]\") return true;\n const parts = hostname.split(\".\");\n return parts.length === 4\n && parts[0] === \"127\"\n && parts.every((part) => /^\\d{1,3}$/u.test(part) && Number(part) <= 255);\n}\n\nfunction isTrustedAuthority(host: URL, trustedHosts: readonly string[]): boolean {\n return trustedHosts.some((entry) => {\n const candidate = parseAuthority(entry);\n if (candidate === undefined) return false;\n return canonicalAuthority(entry, candidate) === candidate.hostname\n ? candidate.hostname === host.hostname\n : candidate.host === host.host;\n });\n}\n\n/** Reject malformed declarations at plugin load instead of silently widening access. */\nexport function assertTrustedWorkspaceAuthority(entry: string): void {\n const url = parseAuthority(entry);\n if (url !== undefined && canonicalAuthority(entry, url) === entry.toLocaleLowerCase()) return;\n throw new Error(`oh-story: trustedHosts entry ${JSON.stringify(entry)} is not a bare host[:port] authority`);\n}\n\n/**\n * Same browser trust boundary as DSH's native API: every request must address a\n * loopback or explicitly trusted Host, and browser markers must be same-origin.\n */\nexport function isTrustedWorkspaceRequest(\n request: WorkspaceTrustRequest,\n trustedHosts: readonly string[]\n): boolean {\n const authority = header(request.headers, \"host\");\n if (authority === undefined) return false;\n const host = parseAuthority(authority);\n if (host === undefined) return false;\n if (!isLoopbackHostname(host.hostname) && !isTrustedAuthority(host, trustedHosts)) return false;\n if (header(request.headers, \"sec-fetch-site\") === \"cross-site\") return false;\n const origin = header(request.headers, \"origin\");\n if (origin === undefined) return true;\n try { return new URL(origin).host === host.host; }\n catch { return false; }\n}\n"],
|
|
5
|
-
"mappings": ";AAKA,OAAO,OAAO;;;ACLd,SAAS,SAAS,gBAAgB;AAClC,SAAS,UAAU,SAAS,YAAY,MAAM,UAAU,eAAe;AACvE,SAAS,eAAe,qBAAqB;AAC7C;AAAA,EACE;AAAA,OAIK;AAEP,IAAM,sBAAsB;AAC5B,IAAM,sBAAsB;AAC5B,IAAM,aAAa,EAAE,gBAAgB,MAAM,eAAe,KAAK;AAC/D,IAAM,mBAAmB;AAAA,EACvB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,EAAE,KAAK,IAAI;AACX,IAAM,sBAAiE;AAAA,EACrE,OAAO;AAAA,EACP,eAAe;AAAA,EACf,sBAAsB;AAAA,EACtB,oBAAoB;AAAA,EACpB,gBAAgB;AAAA,EAChB,gBAAgB;AAAA,EAChB,gBAAgB;AAAA,EAChB,uBAAuB;AAAA,EACvB,qBAAqB;AAAA,EACrB,eAAe;AAAA,EACf,eAAe;AACjB;AACA,IAAM,mBAAmB;AAAA,EACvB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,EAAE,KAAK,IAAI;AACX,IAAM,sBAAiE;AAAA,EACrE,eAAe;AAAA,EACf,uBAAuB;AACzB;AAEA,IAAM,oBAA+D;AAAA,EACnE,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcP,eAAe;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcf,eAAe;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUf,mBAAmB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAgBnB,oBAAoB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAetB;AAQA,SAAS,iBAAiB,aAAqB,KAAiC;AAC9E,QAAM,QAAQ,IAAI,OAAO,IAAI,GAAG,cAAc,IAAI,EAAE,KAAK,WAAW;AACpE,QAAM,MAAM,QAAQ,CAAC,GAAG,KAAK;AAC7B,MAAI,QAAQ,OAAW,QAAO;AAC9B,MAAI,IAAI,WAAW,GAAI,KAAK,IAAI,SAAS,GAAI,GAAG;AAC9C,QAAI;AAAE,aAAO,KAAK,MAAM,GAAG;AAAA,IAAa,QAClC;AAAE,aAAO,IAAI,MAAM,GAAG,EAAE;AAAA,IAAG;AAAA,EACnC;AACA,SAAO,IAAI,QAAQ,iBAAiB,EAAE;AACxC;AAEO,SAAS,kBAAkB,QAA6B;AAC7D,QAAM,QAAQ,qCAAqC,KAAK,MAAM;AAC9D,MAAI,QAAQ,CAAC,MAAM,OAAW,OAAM,IAAI,MAAM,4CAA4C;AAC1F,QAAMA,QAAO,iBAAiB,MAAM,CAAC,GAAG,MAAM;AAC9C,QAAM,cAAc,iBAAiB,MAAM,CAAC,GAAG,aAAa;AAC5D,MAAI,CAACA,SAAQ,CAAC,8BAA8B,KAAKA,KAAI,EAAG,OAAM,IAAI,MAAM,oCAAoC;AAC5G,MAAI,CAAC,YAAa,OAAM,IAAI,MAAM,kBAAkBA,KAAI,uBAAuB;AAC/E,SAAO,EAAE,MAAAA,OAAM,aAAa,SAAS,OAAO,MAAM,MAAM,CAAC,EAAE,MAAM,EAAE;AACrE;AAEO,SAAS,gBAAgBA,OAAc,SAAyB;AACrE,QAAM,WAAW,oBAAoBA,KAAI;AACzC,QAAM,SAAS,kBAAkBA,KAAI;AACrC,SAAO,GAAG,gBAAgB,GAAG,aAAa,SAAY,KAAK;AAAA,+BAAkC,QAAQ,gCAAgC;AAAA;AAAA,EAAO,UAAU,OAAO;AAC/J;AAEO,SAAS,0BAAkC;AAChD,QAAM,UAAU,QAAQ,cAAc,YAAY,GAAG,CAAC;AACtD,SAAO,SAAS,OAAO,MAAM,QACzB,QAAQ,SAAS,iCAAiC,IAClD,QAAQ,SAAS,iBAAiB;AACxC;AAEO,SAAS,wBAAgC;AAC9C,QAAM,UAAU,QAAQ,cAAc,YAAY,GAAG,CAAC;AACtD,SAAO,SAAS,OAAO,MAAM,QACzB,QAAQ,SAAS,8BAA8B,IAC/C,QAAQ,SAAS,cAAc;AACrC;AAEA,SAAS,2BACP,cACA,WACA,SACe;AACf,QAAM,OAAO,QAAQ,SAAS;AAC9B,SAAO;AAAA,IACL,MAAM;AAAA,IACN,MAAM,OAA2C;AAC/C,YAAM,eAAe,MAAM,QAAQ,MAAM,EAAE,eAAe,KAAK,CAAC,GAC7D,OAAO,CAAC,UAAU,MAAM,YAAY,CAAC,EACrC,IAAI,CAAC,UAAU,MAAM,IAAI,EACzB,KAAK;AACR,aAAO,QAAQ,IAAI,YAAY,IAAI,OAAO,cAAuC;AAC/E,cAAM,OAAO,KAAK,MAAM,WAAW,UAAU;AAC7C,cAAM,SAAS,kBAAkB,MAAM,SAAS,MAAM,MAAM,CAAC;AAC7D,YAAI,OAAO,SAAS,UAAW,OAAM,IAAI,MAAM,4BAA4B,SAAS,0BAA0B,OAAO,IAAI,IAAI;AAC7H,eAAO;AAAA,UACL,MAAM,OAAO;AAAA,UACb,aAAa,OAAO;AAAA,UACpB,YAAY;AAAA,UACZ,UAAU;AAAA,UACV,QAAQ;AAAA,UACR,cAAc,EAAE,MAAM,aAAa,MAAM,KAAK,MAAM,SAAS,EAAE;AAAA,UAC/D,MAAM;AAAA,UACN,SAAS,cAAc,IAAI;AAAA,UAC3B;AAAA,QACF;AAAA,MACF,CAAC,CAAC;AAAA,IACJ;AAAA,IACA,MAAM,IAAI,WAAiD;AACzD,UAAI,UAAU,aAAa,gBAAgB,OAAO,UAAU,SAAS,SAAU,QAAO;AACtF,YAAM,OAAO,QAAQ,UAAU,IAAI;AACnC,YAAM,eAAe,SAAS,MAAM,IAAI;AACxC,UAAI,iBAAiB,MAAM,aAAa,WAAW,IAAI,KAAK,WAAW,YAAY,GAAG;AACpF,cAAM,IAAI,MAAM,wDAAwD;AAAA,MAC1E;AACA,YAAM,SAAS,kBAAkB,MAAM,SAAS,MAAM,MAAM,CAAC;AAC7D,UAAI,OAAO,SAAS,UAAU,KAAM,QAAO;AAC3C,aAAO;AAAA,QACL,MAAM,OAAO;AAAA,QACb,aAAa,OAAO;AAAA,QACpB,YAAY;AAAA,QACZ,UAAU;AAAA,QACV,QAAQ;AAAA,QACR,cAAc,EAAE,MAAM,aAAa,MAAM,KAAK,MAAM,OAAO,IAAI,EAAE;AAAA,QACjE;AAAA,QACA,SAAS,QAAQ,OAAO,MAAM,OAAO,OAAO;AAAA,MAC9C;AAAA,IACF;AAAA,EACF;AACF;AAEO,SAAS,2BAA2B,YAAY,wBAAwB,GAAkB;AAC/F,SAAO,2BAA2B,qBAAqB,WAAW,eAAe;AACnF;AAEO,SAAS,qBAAqBA,OAAc,SAAyB;AAC1E,QAAM,WAAW,oBAAoBA,KAAI;AACzC,SAAO,GAAG,gBAAgB,GAAG,aAAa,SAAY,KAAK;AAAA,+BAAkC,QAAQ,gCAAgC;AAAA;AAAA,EAAO,OAAO;AACrJ;AAEO,SAAS,yBAAyB,YAAY,sBAAsB,GAAkB;AAC3F,SAAO,2BAA2B,qBAAqB,WAAW,oBAAoB;AACxF;;;ACvOA,SAAS,yBAAyB;AAGlC,IAAM,iBAAiB,oBAAI,IAAI,CAAC,SAAS,QAAQ,oBAAoB,CAAC;AAQtE,SAAS,aAAaC,OAAc,MAAmC;AACrE,MAAI,CAAC,eAAe,IAAIA,KAAI,KAAK,OAAO,SAAS,YAAY,SAAS,QAAQ,MAAM,QAAQ,IAAI,EAAG,QAAO;AAC1G,QAAM,SAAS;AACf,MAAIA,UAAS,sBAAsB;AACjC,QAAI,EAAC,oBAAI,IAAI,CAAC,UAAU,eAAe,QAAQ,CAAC,GAAE,IAAI,OAAO,OAAO,OAAO,CAAC,EAAG,QAAO;AACtF,WAAO,OAAO,OAAO,SAAS,YAAY,OAAO,KAAK,KAAK,MAAM,KAAK,OAAO,OAAO;AAAA,EACtF;AACA,SAAO,OAAO,OAAO,cAAc,YAAY,OAAO,UAAU,KAAK,MAAM,KAAK,OAAO,YAAY;AACrG;AAEA,SAAS,uBAAuB,MAAkC;AAChE,QAAM,WAAqB,CAAC;AAC5B,aAAW,QAAQ,KAAK,MAAM,GAAG,GAAG;AAClC,QAAI,SAAS,MAAM,SAAS,IAAK;AACjC,QAAI,SAAS,MAAM;AACjB,UAAI,SAAS,WAAW,EAAG,QAAO;AAClC,eAAS,IAAI;AAAA,IACf,MAAO,UAAS,KAAK,IAAI;AAAA,EAC3B;AACA,SAAO,SAAS,KAAK,GAAG;AAC1B;AAEO,SAAS,oBAAoBA,OAAc,MAAe,KAAoD;AACnH,QAAM,UAAU,aAAaA,OAAM,IAAI;AACvC,MAAI,QAAQ,UAAa,YAAY,OAAW,QAAO;AACvD,QAAM,OAAO,IAAI,WAAW,MAAM,GAAG,EAAE,QAAQ,QAAQ,EAAE;AACzD,QAAM,YAAY,QAAQ,WAAW,MAAM,GAAG;AAC9C,QAAM,WAAW,UAAU,WAAW,GAAG,KAAK,cAAc,KAAK,SAAS,KAAK,2BAA2B,KAAK,SAAS;AACxH,QAAM,aAAa,cAAc,KAAK,IAAI,IACtC,UAAU,YAAY,EAAE,WAAW,GAAG,KAAK,YAAY,CAAC,GAAG,IAC3D,UAAU,WAAW,GAAG,IAAI,GAAG;AACnC,MAAI,YAAY,CAAC,WAAY,QAAO;AACpC,QAAM,aAAa,uBAAuB,WAAW,UAAU,MAAM,KAAK,SAAS,CAAC,IAAI,SAAS;AACjG,MAAI,eAAe,OAAW,QAAO;AACrC,MAAI,CAAC,WAAW,WAAW,eAAK,EAAG,QAAO;AAC1C,QAAM,cAAc,aAAa,KAAK,UAAU,IAAI,CAAC;AACrD,SAAO,EAAE,MAAM,MAAM,YAAY,GAAI,gBAAgB,SAAY,CAAC,IAAI,EAAE,SAAS,OAAO,WAAW,EAAE,EAAG;AAC1G;AAIA,eAAe,cAAc,MAAqB,IAAyD;AACzG,QAAM,MAAM,KAAK,OAAO,QAAQ,OAAO;AACvC,QAAM,OAAO,aAAa,KAAK,MAAM,KAAK,SAAS;AACnD,MAAI,QAAQ,UAAa,SAAS,OAAW,QAAO;AACpD,MAAI;AACF,UAAM,CAAC,YAAY,cAAc,IAAI,MAAM,QAAQ,IAAI;AAAA,MACrD,GAAG,QAAQ,KAAK,EAAE,QAAQ,KAAK,OAAO,CAAC;AAAA,MACvC,GAAG,QAAQ,MAAM,EAAE,KAAK,QAAQ,KAAK,OAAO,CAAC;AAAA,IAC/C,CAAC;AACD,QAAI,CAAC,GAAG,SAAS,YAAY,cAAc,EAAG,QAAO;AAAA,EACvD,QAAQ;AAAE,WAAO;AAAA,EAAW;AAC5B,SAAO,oBAAoB,KAAK,MAAM,KAAK,WAAW,GAAG;AAC3D;AAEA,eAAe,OAAO,IAAqB,MAAc,MAAc,QAAyC;AAC9G,SAAO,GAAG,QAAQ,MAAM,EAAE,KAAK,MAAM,GAAI,WAAW,SAAY,CAAC,IAAI,EAAE,OAAO,EAAG,CAAC;AACpF;AAEA,eAAe,OAAO,IAAqB,MAAc,MAAc,QAAwC;AAC7G,SAAO,OAAO,IAAI,MAAM,MAAM,MAAM,EACjC,KAAK,CAAC,UAAU,GAAG,KAAK,OAAO,MAAM,CAAC,EACtC,KAAK,CAAC,SAAS,SAAS,QAAW,MAAM,KAAK;AACnD;AAEA,eAAe,kBAAkB,IAAqB,MAAc,SAAiB,QAAwC;AAC3H,QAAM,UAAU,MAAM,OAAO,IAAI,MAAM,gBAAM,MAAM,EAChD,KAAK,CAAC,cAAc,GAAG,QAAQ,WAAW,MAAM,CAAC,EACjD,MAAM,MAAM,CAAC,CAAC;AACjB,SAAO,QAAQ,KAAK,CAAC,UAAU,MAAM,SAAS,UACzC,OAAO,wBAAwB,KAAK,MAAM,IAAI,IAAI,CAAC,CAAC,MAAM,OAAO;AACxE;AAEA,eAAsB,sBACpB,IACA,UACA,QAC6B;AAC7B,QAAM,oBAAoB,MAAM,OAAO,IAAI,SAAS,MAAM,gBAAM,MAAM,KACjE,MAAM,OAAO,IAAI,SAAS,MAAM,gBAAM,MAAM;AACjD,MAAI,CAAC,kBAAmB,QAAO;AAC/B,MAAI,CAAE,MAAM,OAAO,IAAI,SAAS,MAAM,qCAA2B,MAAM,GAAI;AAIzE,WAAO;AAAA,EACT;AACA,MAAI,SAAS,YAAY,UAAa,CAAE,MAAM,kBAAkB,IAAI,SAAS,MAAM,SAAS,SAAS,MAAM,GAAI;AAC7G,WAAO,2CAAkB,OAAO,SAAS,OAAO,CAAC;AAAA,EACnD;AACA,SAAO;AACT;AAEA,eAAsB,oBACpB,MACA,MAC0B;AAC1B,QAAM,KAAK,KAAK,OAAO,IAAI,IAAI,IAAI;AACnC,MAAI,OAAO,OAAW,QAAO,KAAK;AAClC,QAAM,WAAW,MAAM,cAAc,MAAM,EAAE;AAC7C,MAAI,aAAa,OAAW,QAAO,KAAK;AACxC,QAAM,SAAS,MAAM,sBAAsB,IAAI,UAAU,KAAK,MAAM;AACpE,MAAI,WAAW,OAAW,QAAO,EAAE,MAAM,QAAQ,OAAO;AACxD,SAAO,KAAK;AACd;AAMO,SAAS,qBAAqB,SAAwB;AAC3D,UAAQ,GAAG,qBAAqB,mBAAmB;AAEnD,UAAQ,GAAG,sBAAsB,OAAO,MAAM,QAAQ,SAAoC;AACxF,UAAM,aAAa,MAAM,KAAK;AAC9B,QAAI,OAAO,WAAW,WAAW,SAAS,SAAU,QAAO;AAC3D,UAAM,KAAK,KAAK,OAAO,IAAI,IAAI,IAAI;AACnC,UAAM,WAAW,OAAO,SAAY,SAAY,MAAM,cAAc,MAAM,EAAE;AAC5E,QAAI,aAAa,OAAW,QAAO;AACnC,UAAM,WAAW,kBAAkB;AAAA,MACjC,QAAQ,EAAE,MAAM,UAAU,QAAQ,WAAW;AAAA,MAC7C,SAAS,CAAC;AAAA,QACR,MAAM;AAAA,QACN,MAAM,qCAA2B,SAAS,IAAI;AAAA,MAChD,CAAC;AAAA,IACH,CAAC;AACD,WAAO;AAAA,MACL,GAAG;AAAA,MACH,oBAAoB,CAAC,GAAG,WAAW,sBAAsB,CAAC,GAAG,QAAQ;AAAA,IACvE;AAAA,EACF,CAAC;AACH;;;AC7IA,SAAS,kBAAuC;;;ACHhD,SAAS,YAAAC,iBAAgB;AACzB,SAAS,YAAAC,WAAU,WAAAC,UAAS,QAAAC,OAAM,WAAAC,gBAAe;AACjD,SAAS,iBAAAC,sBAAqB;AAEvB,IAAM,sBAAsB;AAAA,EACjC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAKA,SAAS,SAAS,QAAwB;AACxC,QAAM,cAAc,mCAAmC,KAAK,MAAM;AAClE,SAAO,OAAO,MAAM,cAAc,CAAC,EAAE,UAAU,CAAC,EAAE,KAAK;AACzD;AAEO,SAAS,yBAAiC;AAC/C,QAAM,UAAUH,SAAQG,eAAc,YAAY,GAAG,CAAC;AACtD,SAAOJ,UAAS,OAAO,MAAM,QACzBG,SAAQ,SAAS,gCAAgC,IACjDA,SAAQ,SAAS,gBAAgB;AACvC;AAEA,eAAsB,gBACpBE,OACA,WAAW,uBAAuB,GAClC,YAAkC,aACjB;AACjB,QAAM,OAAO,SAAS,MAAMN,UAASG,MAAKC,SAAQ,QAAQ,GAAG,GAAGE,KAAI,KAAK,GAAG,MAAM,CAAC;AACnF,MAAI,KAAK,WAAW,EAAG,OAAM,IAAI,MAAM,iBAAiBA,KAAI,aAAa;AACzE,QAAM,cAAc,cAAc,cAC9B;AAAA,IACE;AAAA,IACA;AAAA,IACA;AAAA,EACF,IACA;AAAA,IACE;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACJ,SAAO;AAAA,IACL,qBAAqBA,KAAI;AAAA,IACzB,GAAG;AAAA,IACH;AAAA,IACA;AAAA,EACF,EAAE,KAAK,IAAI;AACb;;;AD/CO,IAAM,0BAA0B;AAEvC,IAAM,YAAkE;AAAA,EACtE,qBAAqB,CAAC,QAAQ,QAAQ,MAAM;AAAA,EAC5C,sBAAsB,CAAC,QAAQ,QAAQ,QAAQ,SAAS,MAAM;AAAA,EAC9D,uBAAuB,CAAC,QAAQ,QAAQ,MAAM;AAAA,EAC9C,oBAAoB,CAAC,QAAQ,QAAQ,QAAQ,SAAS,QAAQ,MAAM;AAAA,EACpE,mBAAmB,CAAC,QAAQ,QAAQ,QAAQ,SAAS,MAAM;AAAA,EAC3D,kBAAkB,CAAC,QAAQ,QAAQ,MAAM;AAAA,EACzC,oBAAoB,CAAC,QAAQ,QAAQ,QAAQ,QAAQ,SAAS,cAAc,WAAW;AACzF;AAEO,SAAS,eAAe,MAA8D;AAC3F,SAAO,EAAE,OAAO,UAAU,IAAI,EAAE;AAClC;AAEA,SAAS,WAAW,QAAyC;AAC3D,SAAO,OAAO,IAAI,CAAC,UAAU,MAAM,SAAS,SAAS,MAAM,OAAO,KAAK,UAAU,KAAK,CAAC,EAAE,KAAK,IAAI;AACpG;AAEA,eAAsB,wBAAiD;AACrE,QAAM,WAAW,oBAAI,IAA6B;AAClD,QAAM,QAAQ,IAAI,oBAAoB,IAAI,OAAO,SAAS;AACxD,aAAS,IAAI,MAAM,MAAM,gBAAgB,MAAM,QAAW,cAAc,CAAC;AAAA,EAC3E,CAAC,CAAC;AACF,SAAO,WAAW;AAAA,IAChB,MAAM;AAAA,IACN,aAAa;AAAA,IACb,YAAY;AAAA,MACV,MAAM;AAAA,QACJ,MAAM;AAAA,QACN,UAAU;AAAA,QACV,MAAM;AAAA,QACN,aAAa;AAAA,MACf;AAAA,MACA,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,UAAU;AAAA,QACV,aAAa;AAAA,MACf;AAAA,IACF;AAAA,IACA,QAAQ;AAAA,MACN,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,sBAAsB;AAAA,QACtB,YAAY;AAAA,UACV,MAAM,EAAE,MAAM,UAAU,UAAU,MAAM,MAAM,oBAAoB;AAAA,UAClE,OAAO,EAAE,MAAM,UAAU,UAAU,KAAK;AAAA,UACxC,SAAS,EAAE,MAAM,SAAS,UAAU,MAAM,OAAO,EAAE,MAAM,OAAO,EAAE;AAAA,QACpE;AAAA,MACF;AAAA,MACA,QAAQ,CAAC,OAAO,UAAU,CAAC,EAAE,MAAM,QAAQ,MAAM,WAAW,MAAM,OAAoC,EAAE,CAAC;AAAA,IAC3G;AAAA,IACA,mBAAmB,MAAM;AAAA,IACzB,MAAM,QAAQ,MAAM,MAAM;AACxB,UAAI,KAAK,UAAU,OAAW,OAAM,IAAI,MAAM,6CAA6C;AAC3F,YAAM,UAAU,SAAS,IAAI,KAAK,IAAI;AACtC,UAAI,YAAY,OAAW,OAAM,IAAI,MAAM,iBAAiB,KAAK,IAAI,kBAAkB;AACvF,YAAM,UAAU,eAAe,KAAK,IAAI,EAAE,MAAM,OAAO,CAACC,UACtD,KAAK,OAAO,IAAI,MAAM,IAAIA,OAAM,KAAK,KAAK,MAAM,MAAS;AAC3D,YAAM,MAAM,MAAM,KAAK,MAAM,IAAI,UAAU,MAAM,SAAS;AAAA,QACxD,OAAO,YAAY,KAAK,IAAI;AAAA,QAC5B,QAAQ,CAAC,EAAE,MAAM,QAAQ,MAAM,KAAK,OAAO,CAAC;AAAA,QAC5C,QAAQ,KAAK;AAAA,QACb;AAAA,QACA,YAAY,EAAE,OAAO,QAAQ;AAAA,QAC7B,UAAU;AAAA,QACV,QAAQ,KAAK;AAAA,MACf,CAAC;AACD,UAAI;AACF,cAAM,SAAS,MAAM,IAAI;AACzB,YAAI,OAAO,eAAe,aAAa;AACrC,gBAAM,IAAI,MAAM,iBAAiB,KAAK,IAAI,eAAe,OAAO,UAAU,GAAG,OAAO,eAAe,SAAY,KAAK,KAAK,OAAO,UAAU,EAAE,EAAE;AAAA,QAChJ;AACA,eAAO;AAAA,UACL,MAAM,KAAK;AAAA,UACX,OAAO,IAAI;AAAA,UACX,SAAS,OAAO;AAAA,QAClB;AAAA,MACF,UAAE;AACA,cAAM,IAAI,QAAQ;AAAA,MACpB;AAAA,IACF;AAAA,EACF,CAAC;AACH;AAEA,eAAsB,wBAAwB,SAAiC;AAC7E,QAAM,aAAa,MAAM,sBAAsB;AAC/C,MAAI;AACJ,QAAM,QAAQ,MAAY;AAAE,gBAAY,QAAQ,MAAM,SAAS,UAAU;AAAA,EAAG;AAC5E,QAAM,UAAU,MAAY;AAAE,cAAU;AAAG,cAAU;AAAA,EAAW;AAChE,UAAQ,GAAG,2BAA2B,CAAC,aAAa;AAAE,QAAI,SAAS,SAAS,QAAS,OAAM;AAAA,EAAG,CAAC;AAC/F,UAAQ,GAAG,6BAA6B,CAACA,UAAS;AAAE,QAAIA,UAAS,QAAS,SAAQ;AAAA,EAAG,CAAC;AACtF,MAAI,QAAQ,UAAU,YAAY,OAAO,MAAM,OAAW,OAAM;AAClE;;;AEnGA,SAAS,eAAe;AAGxB,SAAS,eAA4E;AAGrF,SAAS,iBAAiB;;;ACD1B,SAAS,OAAO,SAAwCC,OAAkC;AACxF,MAAI,mBAAmB,QAAS,QAAO,QAAQ,IAAIA,KAAI,KAAK;AAC5D,QAAM,QAAQ,QAAQA,KAAI;AAC1B,SAAO,OAAO,UAAU,WAAW,QAAQ;AAC7C;AAEA,SAAS,eAAe,WAAoC;AAC1D,MAAI;AAAE,WAAO,IAAI,IAAI,UAAU,SAAS,EAAE;AAAA,EAAG,QACvC;AAAE,WAAO;AAAA,EAAW;AAC5B;AAEA,SAAS,mBAAmB,OAAe,KAAkB;AAC3D,QAAM,OAAO,IAAI,SAAS,KAAK,IAAI,OAAO,IAAI,IAAI,WAAW,KAAK,EAAE,EAAE;AACtE,SAAO,SAAS,KAAK,IAAI,WAAW,GAAG,IAAI,QAAQ,IAAI,IAAI;AAC7D;AAEA,SAAS,mBAAmB,UAA2B;AACrD,MAAI,aAAa,eAAe,aAAa,QAAS,QAAO;AAC7D,QAAM,QAAQ,SAAS,MAAM,GAAG;AAChC,SAAO,MAAM,WAAW,KACnB,MAAM,CAAC,MAAM,SACb,MAAM,MAAM,CAAC,SAAS,aAAa,KAAK,IAAI,KAAK,OAAO,IAAI,KAAK,GAAG;AAC3E;AAEA,SAAS,mBAAmB,MAAW,cAA0C;AAC/E,SAAO,aAAa,KAAK,CAAC,UAAU;AAClC,UAAM,YAAY,eAAe,KAAK;AACtC,QAAI,cAAc,OAAW,QAAO;AACpC,WAAO,mBAAmB,OAAO,SAAS,MAAM,UAAU,WACtD,UAAU,aAAa,KAAK,WAC5B,UAAU,SAAS,KAAK;AAAA,EAC9B,CAAC;AACH;AAGO,SAAS,gCAAgC,OAAqB;AACnE,QAAM,MAAM,eAAe,KAAK;AAChC,MAAI,QAAQ,UAAa,mBAAmB,OAAO,GAAG,MAAM,MAAM,kBAAkB,EAAG;AACvF,QAAM,IAAI,MAAM,gCAAgC,KAAK,UAAU,KAAK,CAAC,sCAAsC;AAC7G;AAMO,SAAS,0BACd,SACA,cACS;AACT,QAAM,YAAY,OAAO,QAAQ,SAAS,MAAM;AAChD,MAAI,cAAc,OAAW,QAAO;AACpC,QAAM,OAAO,eAAe,SAAS;AACrC,MAAI,SAAS,OAAW,QAAO;AAC/B,MAAI,CAAC,mBAAmB,KAAK,QAAQ,KAAK,CAAC,mBAAmB,MAAM,YAAY,EAAG,QAAO;AAC1F,MAAI,OAAO,QAAQ,SAAS,gBAAgB,MAAM,aAAc,QAAO;AACvE,QAAM,SAAS,OAAO,QAAQ,SAAS,QAAQ;AAC/C,MAAI,WAAW,OAAW,QAAO;AACjC,MAAI;AAAE,WAAO,IAAI,IAAI,MAAM,EAAE,SAAS,KAAK;AAAA,EAAM,QAC3C;AAAE,WAAO;AAAA,EAAO;AACxB;;;ADtDA,IAAM,oBAAoB,CAAC,gBAAM,gBAAM,gBAAM,gBAAM,gBAAM,0BAAM;AAC/D,IAAM,oBAAoB,CAAC,gBAAM,4BAAQ,sBAAO,gBAAM,gBAAM,kCAAS,cAAI;AACzE,IAAM,uBAAuB,CAAC,GAAG,mBAAmB,GAAG,iBAAiB;AACxE,IAAM,aAAa,oBAAI,IAAI,CAAC,kBAAkB,CAAC;AAC/C,IAAM,sBAAsB,oBAAI,IAAI,CAAC,OAAO,QAAQ,SAAS,QAAQ,CAAC;AACtE,IAAM,aAAa;AA2BnB,IAAM,qBAAN,cAAiC,MAAM;AAAA,EACrC,YAAqB,QAAgB,SAAiB;AAAE,UAAM,OAAO;AAAhD;AAAA,EAAmD;AAAA,EAAnD;AACvB;AAEA,SAAS,KAAK,UAA0B,QAAgB,OAAsB;AAC5E,QAAM,OAAO,GAAG,KAAK,UAAU,KAAK,CAAC;AAAA;AACrC,WAAS,UAAU,QAAQ;AAAA,IACzB,gBAAgB;AAAA,IAChB,kBAAkB,OAAO,WAAW,IAAI;AAAA,IACxC,iBAAiB;AAAA,IACjB,0BAA0B;AAAA,EAC5B,CAAC;AACD,WAAS,IAAI,IAAI;AACnB;AAEA,eAAe,SAAS,SAA0B,UAAoD;AACpG,QAAM,SAAmB,CAAC;AAC1B,MAAI,OAAO;AACX,mBAAiB,SAAS,SAAsC;AAC9D,UAAM,QAAQ,OAAO,KAAK,KAAK;AAC/B,YAAQ,MAAM;AACd,QAAI,OAAO,SAAU,OAAM,IAAI,mBAAmB,KAAK,4CAAS;AAChE,WAAO,KAAK,KAAK;AAAA,EACnB;AACA,MAAI;AACF,UAAM,QAAQ,KAAK,MAAM,OAAO,OAAO,MAAM,EAAE,SAAS,MAAM,CAAC;AAC/D,QAAI,OAAO,UAAU,YAAY,UAAU,QAAQ,MAAM,QAAQ,KAAK,EAAG,OAAM,IAAI,MAAM;AACzF,WAAO;AAAA,EACT,QAAQ;AACN,UAAM,IAAI,mBAAmB,KAAK,wDAAgB;AAAA,EACpD;AACF;AAEA,SAAS,mBAAmB,MAAoB;AAC9C,MAAI,CAAC,oBAAoB,IAAI,QAAQ,IAAI,EAAE,kBAAkB,CAAC,GAAG;AAC/D,UAAM,IAAI,mBAAmB,KAAK,2GAAqC;AAAA,EACzE;AACA,MAAI,KAAK,WAAW,GAAG,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,MAAM,GAAG,EAAE,KAAK,CAAC,YAAY,YAAY,MAAM,YAAY,OAAO,YAAY,IAAI,GAAG;AAC3I,UAAM,IAAI,mBAAmB,KAAK,gFAAe;AAAA,EACnD;AACA,QAAM,OAAO,KAAK,MAAM,KAAK,CAAC,EAAE,CAAC;AACjC,MAAI,CAAC,qBAAqB,KAAK,CAAC,cAAc,cAAc,IAAI,KAAK,CAAC,WAAW,IAAI,IAAI,GAAG;AAC1F,UAAM,IAAI,mBAAmB,KAAK,gFAAe;AAAA,EACnD;AACF;AAEA,eAAe,eAAe,SAAkB,KAAmC;AACjF,QAAM,QAAQ,IAAI,aAAa,IAAI,WAAW;AAC9C,MAAI,UAAU,QAAQ,UAAU,GAAI,OAAM,IAAI,mBAAmB,KAAK,kCAAmB;AACzF,QAAM,SAAS,QAAQ,OAAO,QAAQ,IAAI,OAAO;AACjD,MAAI,WAAW,OAAW,OAAM,IAAI,mBAAmB,KAAK,uDAAyB;AACrF,MAAI;AACJ,MAAI;AACF,YAAQ,MAAM,OAAO,QAAQ,UAAU,KAAK,CAAC;AAAA,EAC/C,QAAQ;AACN,UAAM,IAAI,mBAAmB,KAAK,0CAAY;AAAA,EAChD;AACA,MAAI,UAAU,OAAW,OAAM,IAAI,mBAAmB,KAAK,0CAAY;AACvE,MAAI,MAAM,QAAQ,OAAO,kBAAkB,UAAa,MAAM,QAAQ,OAAO,WAAW,YAAY;AAClG,UAAM,IAAI,mBAAmB,KAAK,iFAAqB;AAAA,EACzD;AACA,QAAM,MAAM,MAAM,QAAQ,OAAO;AACjC,MAAI,QAAQ,OAAW,OAAM,IAAI,mBAAmB,KAAK,yEAAkB;AAC3E,QAAM,KAAK,MAAM,IAAI,IAAI,IAAI;AAC7B,QAAM,gBAAgB,MAAM,IAAI,IAAI,eAAe;AACnD,MAAI,OAAO,UAAa,kBAAkB,OAAW,OAAM,IAAI,mBAAmB,KAAK,kEAAgB;AACvG,SAAO,EAAE,OAAO,IAAI,eAAe,KAAK,MAAM,MAAM,GAAG,QAAQ,GAAG,EAAE;AACtE;AAEA,eAAe,eAAe,OAAuB,MAAiC;AACpF,qBAAmB,IAAI;AACvB,QAAMC,UAAS,MAAM,MAAM,GAAG,QAAQ,MAAM,EAAE,KAAK,MAAM,IAAI,CAAC;AAC9D,MAAI,CAAC,MAAM,GAAG,SAAS,MAAM,MAAMA,OAAM,EAAG,OAAM,IAAI,mBAAmB,KAAK,+EAAmB;AACjG,SAAOA;AACT;AAEA,SAAS,mBAAmB,MAAkC;AAC5D,MAAI,SAAS,OAAW,OAAM,IAAI,mBAAmB,KAAK,sCAAQ;AAClE,MAAI,KAAK,SAAS,OAAQ,OAAM,IAAI,mBAAmB,KAAK,gFAAe;AAC3E,SAAO;AACT;AAGA,eAAe,kBAAkB,IAAgBA,SAAkB,UAA2C;AAC5G,WAAS,UAAU,GAAG,UAAU,GAAG,WAAW,GAAG;AAC/C,UAAM,SAAS,mBAAmB,MAAM,GAAG,KAAKA,OAAM,CAAC;AACvD,QAAI,OAAO,SAAS,UAAa,OAAO,OAAO,SAAU,OAAM,IAAI,mBAAmB,KAAK,0EAAc;AACzG,UAAM,QAAQ,MAAM,GAAG,UAAUA,SAAQ,QAAW,QAAQ;AAC5D,UAAM,QAAQ,mBAAmB,MAAM,GAAG,KAAKA,OAAM,CAAC;AACtD,QAAI,OAAO,YAAY,MAAM,QAAS;AACtC,QAAI;AACJ,QAAI;AACF,gBAAU,IAAI,YAAY,SAAS,EAAE,OAAO,KAAK,CAAC,EAAE,OAAO,KAAK;AAAA,IAClE,QAAQ;AACN,YAAM,IAAI,mBAAmB,KAAK,qEAAmB;AAAA,IACvD;AACA,WAAO,EAAE,SAAS,OAAO,MAAM,YAAY,SAAS,MAAM,QAAQ;AAAA,EACpE;AACA,QAAM,IAAI,mBAAmB,KAAK,0EAAc;AAClD;AAEA,eAAe,UAAU,OAAiD;AACxE,QAAM,QAAyB,CAAC;AAChC,QAAM,OAAO,OAAO,MAAc,cAAuC;AACvE,eAAW,SAAS,MAAM,MAAM,GAAG,QAAQ,SAAS,GAAG;AACrD,UAAI,MAAM,KAAK,WAAW,GAAG,KAAK,CAAC,MAAM,GAAG,SAAS,MAAM,MAAM,MAAM,MAAM,EAAG;AAChF,YAAM,YAAY,GAAG,IAAI,IAAI,MAAM,IAAI;AACvC,UAAI,MAAM,SAAS,YAAa,OAAM,KAAK,WAAW,MAAM,MAAM;AAAA,eACzD,MAAM,SAAS,UAAU,oBAAoB,IAAI,QAAQ,MAAM,IAAI,EAAE,kBAAkB,CAAC,GAAG;AAClG,cAAM,OAAO,MAAM,YAAY,UAAa,MAAM,SAAS,SAAY,MAAM,MAAM,GAAG,KAAK,MAAM,MAAM,IAAI;AAC3G,cAAM,UAAU,MAAM,WAAW,MAAM;AACvC,YAAI,YAAY,OAAW,OAAM,KAAK,EAAE,MAAM,WAAW,OAAO,MAAM,QAAQ,MAAM,QAAQ,GAAG,QAAQ,CAAC;AAAA,MAC1G;AACA,UAAI,MAAM,UAAU,WAAY;AAAA,IAClC;AAAA,EACF;AACA,aAAW,aAAa,sBAAsB;AAC5C,UAAMA,UAAS,MAAM,MAAM,GAAG,QAAQ,WAAW,EAAE,KAAK,MAAM,IAAI,CAAC;AACnE,QAAI,CAAC,MAAM,GAAG,SAAS,MAAM,MAAMA,OAAM,EAAG;AAC5C,UAAM,OAAO,MAAM,MAAM,GAAG,KAAKA,OAAM;AACvC,QAAI,MAAM,SAAS,YAAa,OAAM,KAAK,WAAWA,OAAM;AAC5D,QAAI,MAAM,UAAU,WAAY;AAAA,EAClC;AACA,aAAW,QAAQ,YAAY;AAC7B,UAAMA,UAAS,MAAM,eAAe,OAAO,IAAI;AAC/C,UAAM,OAAO,MAAM,MAAM,GAAG,KAAKA,OAAM;AACvC,QAAI,MAAM,SAAS,OAAQ,OAAM,KAAK,EAAE,MAAM,OAAO,KAAK,QAAQ,GAAG,SAAS,KAAK,QAAQ,CAAC;AAAA,EAC9F;AACA,SAAO,MAAM,KAAK,CAAC,MAAM,UAAU,KAAK,KAAK,cAAc,MAAM,MAAM,YAAY,CAAC;AACtF;AAEA,eAAe,SAAS,OAAuB,OAAiC,MAAc,UAAiF;AAC7K,MAAI,CAAC,MAAM,KAAK,CAAC,SAAS,KAAK,SAAS,IAAI,EAAG,QAAO,EAAE,OAAO,KAAK;AACpE,MAAI;AACF,UAAMA,UAAS,MAAM,eAAe,OAAO,IAAI;AAC/C,WAAO,EAAE,OAAO,KAAK,OAAO,MAAM,kBAAkB,MAAM,IAAIA,SAAQ,QAAQ,GAAG,OAAO,EAAa;AAAA,EACvG,SAAS,OAAO;AACd,WAAO,EAAE,OAAO,MAAM,OAAO,iBAAiB,cAAc,GAAG,IAAI,+CAAiB,GAAG,IAAI,8CAAW;AAAA,EACxG;AACF;AAEA,SAAS,WAAW,OAAgD;AAClE,MAAI,EAAE,iBAAiB,SAAU,QAAO;AACxC,UAAQ,MAAM,MAAM;AAAA,IAClB,KAAK;AAAgB,aAAO,IAAI,mBAAmB,KAAK,sCAAQ;AAAA,IAChE,KAAK;AAAgB,aAAO,IAAI,mBAAmB,KAAK,0EAAc;AAAA,IACtE,KAAK;AAAA,IACL,KAAK;AAAuB,aAAO,IAAI,mBAAmB,KAAK,gFAAe;AAAA,IAC9E,KAAK;AAAA,IACL,KAAK;AAAqB,aAAO,IAAI,mBAAmB,KAAK,qFAAoB;AAAA,IACjF,KAAK;AAAA,IACL,KAAK;AAAmB,aAAO,IAAI,mBAAmB,KAAK,0HAAsB;AAAA,IACjF,KAAK;AAAc,aAAO,IAAI,mBAAmB,KAAK,kDAAU;AAAA,IAChE;AAAS,aAAO,IAAI,mBAAmB,KAAK,4DAAe;AAAA,EAC7D;AACF;AAEA,eAAe,OAAO,SAAkB,SAA0B,UAA0B,SAA+C;AACzI,MAAI;AACF,QAAI,CAAC,0BAA0B,SAAS,QAAQ,gBAAgB,CAAC,CAAC,EAAG,OAAM,IAAI,mBAAmB,KAAK,wDAAW;AAClH,UAAM,MAAM,IAAI,IAAI,QAAQ,OAAO,KAAK,kBAAkB;AAC1D,QAAI,IAAI,aAAa,yBAAyB,QAAQ,WAAW,OAAO;AACtE,YAAM,QAAQ,MAAM,eAAe,SAAS,GAAG;AAC/C,YAAM,QAAQ,MAAM,UAAU,KAAK;AACnC,YAAM,WAAW,MAAM,SAAS,OAAO,OAAO,qCAA2B,QAAQ,QAAQ;AACzF,YAAM,aAAa,MAAM,SAAS,OAAO,OAAO,oBAAoB,QAAQ,QAAQ;AACpF,YAAM,iBAAiB,CAAC,SAAS,OAAO,WAAW,KAAK,EAAE,OAAO,CAAC,UAA2B,UAAU,MAAS;AAChH,WAAK,UAAU,KAAK,EAAE,KAAK,MAAM,KAAK,OAAO,UAAU,SAAS,OAAO,YAAY,WAAW,OAAO,gBAAgB,MAAM,cAAc,CAAC;AAC1I;AAAA,IACF;AACA,QAAI,IAAI,aAAa,oBAAoB,QAAQ,WAAW,OAAO;AACjE,YAAM,QAAQ,MAAM,eAAe,SAAS,GAAG;AAC/C,YAAM,OAAO,IAAI,aAAa,IAAI,MAAM;AACxC,UAAI,SAAS,KAAM,OAAM,IAAI,mBAAmB,KAAK,4CAAS;AAC9D,YAAM,OAAO,MAAM,kBAAkB,MAAM,IAAI,MAAM,eAAe,OAAO,IAAI,GAAG,QAAQ,QAAQ;AAClG,WAAK,UAAU,KAAK,EAAE,MAAM,GAAG,KAAK,CAAC;AACrC;AAAA,IACF;AACA,QAAI,IAAI,aAAa,oBAAoB,QAAQ,WAAW,OAAO;AACjE,YAAM,QAAQ,MAAM,eAAe,SAAS,GAAG;AAC/C,YAAM,OAAO,IAAI,aAAa,IAAI,MAAM;AACxC,UAAI,SAAS,KAAM,OAAM,IAAI,mBAAmB,KAAK,4CAAS;AAC9D,YAAM,QAAQ,MAAM,SAAS,SAAS,QAAQ,WAAW,IAAI,IAAK;AAClE,UAAI,OAAO,MAAM,YAAY,SAAU,OAAM,IAAI,mBAAmB,KAAK,oDAAiB;AAC1F,UAAI,OAAO,MAAM,gBAAgB,YAAY,MAAM,gBAAgB,GAAI,OAAM,IAAI,mBAAmB,KAAK,8DAAsB;AAC/H,UAAI,OAAO,WAAW,MAAM,OAAO,IAAI,QAAQ,SAAU,OAAM,IAAI,mBAAmB,KAAK,0EAAc;AACzG,YAAM,UAAU,MAAM,MAAM,GAAG;AAAA,QAC7B,MAAM,eAAe,OAAO,IAAI;AAAA,QAChC,MAAM;AAAA,QACN,EAAE,MAAM,oBAAoB,SAAS,MAAM,YAAyB;AAAA,QACpE;AAAA,QACA,MAAM,cAAc,QAAQ,EAAE,SAAS,MAAM,MAAM,QAAQ,CAAC;AAAA,MAC9D;AACA,WAAK,UAAU,KAAK,EAAE,MAAM,SAAS,QAAQ,OAAO,OAAO,OAAO,WAAW,QAAQ,KAAK,GAAG,SAAS,QAAQ,QAAQ,CAAC;AACvH;AAAA,IACF;AACA,SAAK,UAAU,KAAK,EAAE,OAAO,4BAA4B,CAAC;AAAA,EAC5D,SAAS,OAAO;AACd,UAAM,SAAS,iBAAiB,qBAAqB,QAAQ,WAAW,KAAK;AAC7E,QAAI,WAAW,OAAW,SAAQ,OAAO,UAAU,EAAE,MAAM,0BAA0B,KAAK;AAC1F,SAAK,UAAU,QAAQ,UAAU,KAAK,EAAE,OAAO,QAAQ,WAAW,uCAAuC,CAAC;AAAA,EAC5G;AACF;AAGO,SAAS,uBAAuB,SAAkB,SAAsC;AAC7F,UAAQ,OAAO,MAAM,QAAQ,UAAU,SAAS;AAAA,IAC9C,MAAM;AAAA,IACN,MAAM;AAAA,IACN,SAAS,CAAC,SAAS,aAAa,OAAO,SAAS,SAAS,UAAU,OAAO;AAAA,EAC5E,CAAC,GAAG,qCAAqC;AAC3C;;;AL5OO,IAAM,OAAO;AACb,IAAM,SAAS,CAAC,UAAU,aAAa,SAAS,UAAU,WAAW;AAQrE,IAAM,SAAS,EAAE,OAAO;AAAA,EAC7B,gBAAgB,EAAE,QAAQ,EAAE,IAAI,KAAM,EAAE,IAAI,OAAS,EAAE,QAAQ,OAAS;AAAA,EACxE,cAAc,EAAE,MAAM,MAAM,EAAE,QAAQ,CAAC,CAAC;AAC1C,CAAC;AAGD,eAAsB,MAAM,SAAkB,SAAiB,CAAC,GAAkB;AAChF,QAAM,eAAe,OAAO,gBAAgB,CAAC;AAC7C,aAAW,SAAS,aAAc,iCAAgC,KAAK;AACvE,UAAQ,OAAO,iBAAiB,MAAM,2BAA2B,CAAC;AAClE,UAAQ,OAAO,iBAAiB,MAAM,yBAAyB,CAAC;AAChE,uBAAqB,OAAO;AAC5B,QAAM,wBAAwB,OAAO;AACrC,yBAAuB,SAAS,EAAE,UAAU,OAAO,kBAAkB,SAAW,aAAa,CAAC;AAChG;AAEA,IAAO,gBAAQ,EAAE,MAAM,QAAQ,QAAQ,MAAM;",
|
|
6
|
-
"names": ["name", "name", "readFile", "basename", "dirname", "join", "resolve", "fileURLToPath", "name", "name", "name", "target"]
|
|
3
|
+
"sources": ["../src/index.ts", "../src/skill-provider.ts", "../src/native-hooks.ts", "../src/role-tool.ts", "../src/reference-tool.ts", "../src/role-provider.ts", "../src/workspace-route.ts", "../src/workspace-request-trust.ts"],
|
|
4
|
+
"sourcesContent": ["import type { Context } from \"@deepseek-ai/cordis\";\nimport type {} from \"@deepseek-ai/dsh-host-webserver\";\nimport type {} from \"@deepseek-ai/dsh-skill\";\nimport type {} from \"@deepseek-ai/dsh-subagent\";\nimport type {} from \"@deepseek-ai/dsh-tools\";\nimport z from \"@deepseek-ai/schemastery\";\nimport { createDramaSkillProvider, createOhStorySkillProvider } from \"./skill-provider.js\";\nimport { registerOhStoryHooks } from \"./native-hooks.js\";\nimport { registerOhStoryRoleTool } from \"./role-tool.js\";\nimport { registerWorkspaceRoute } from \"./workspace-route.js\";\nimport { assertTrustedWorkspaceAuthority } from \"./workspace-request-trust.js\";\n\nexport { createDramaSkillProvider, createOhStorySkillProvider, parseBundledSkill } from \"./skill-provider.js\";\nexport { OH_STORY_ROLE_NAMES, loadBundledRole } from \"./role-provider.js\";\nexport { createOhStoryRoleTool, OH_STORY_ROLE_TOOL_NAME, registerOhStoryRoleTool, roleToolFilter, type OhStoryRoleSubagents } from \"./role-tool.js\";\nexport { bundledReferenceGuard, createOhStoryReferenceTool, OH_STORY_REFERENCE_TOOL_NAME } from \"./reference-tool.js\";\nexport { registerWorkspaceRoute } from \"./workspace-route.js\";\nexport { registerOhStoryHooks } from \"./native-hooks.js\";\n\nexport const name = \"oh-story\";\nexport const inject = [\"skills\", \"subagents\", \"tools\", \"typert\", \"webServer\"];\n\n/** DSH owns models, providers, presets, permissions, roots, runs, and sessions. */\nexport interface Config {\n readonly editorMaxBytes?: number;\n readonly trustedHosts?: string[];\n}\n\nexport const Config = z.object({\n editorMaxBytes: z.natural().min(65_536).max(8_388_608).default(2_097_152),\n trustedHosts: z.array(String).default([])\n}) as z<Config>;\n\n/** Mount only domain contributions into the current DSH process. */\nexport async function apply(context: Context, config: Config = {}): Promise<void> {\n const trustedHosts = config.trustedHosts ?? [];\n for (const entry of trustedHosts) assertTrustedWorkspaceAuthority(entry);\n context.skills.registerProvider(() => createOhStorySkillProvider());\n context.skills.registerProvider(() => createDramaSkillProvider());\n registerOhStoryHooks(context);\n await registerOhStoryRoleTool(context);\n registerWorkspaceRoute(context, { maxBytes: config.editorMaxBytes ?? 2_097_152, trustedHosts });\n}\n\nexport default { name, inject, Config, apply };\n", "import { readdir, readFile } from \"node:fs/promises\";\nimport { basename, dirname, isAbsolute, join, relative, resolve } from \"node:path\";\nimport { fileURLToPath, pathToFileURL } from \"node:url\";\nimport {\n BUNDLED_SKILL_RANK,\n type SkillCandidate,\n type SkillDefinition,\n type SkillProvider\n} from \"@deepseek-ai/dsh-skill\";\n\nconst STORY_PROVIDER_NAME = \"oh-story\";\nconst DRAMA_PROVIDER_NAME = \"short-drama\";\nconst INVOCATION = { modelInvocable: true, userInvocable: true } as const;\nconst DSH_SKILL_BRIDGE = [\n \"<oh-story-dsh-integration>\",\n \"This Skill is a native contribution to the current DeepSeek Harness session.\",\n \"DSH owns the workspace, model, preset, permissions, Session Log, tools, subagents, cancellation, resume, and Agent UI.\",\n \"Never start another Agent runtime, session transport, Dashboard, SSE stream, polling loop, or model configuration.\",\n \"All seven upstream Oh Story specialist Roles are bundled. Invoke one with oh_story_role and a self-contained prompt.\",\n \"Never inspect .claude/agents, .codex/agents, .opencode/agents, or .story-deployed to decide whether a Role is available.\",\n \"Use only DSH-visible tools. DSH sandbox and permission policy remain authoritative.\",\n \"</oh-story-dsh-integration>\"\n].join(\"\\n\");\nconst DSH_SKILL_OVERRIDES: Readonly<Partial<Record<string, string>>> = {\n story: \"The \u5C0F\u8BF4 workspace is an official DSH conversation view. Never start or open a second web application.\",\n \"story-setup\": \"Initialize or validate novel project data only. DSH already supplies Skills, Roles, hooks, tools, permissions, sessions, and UI; never deploy Claude/OpenCode/Codex/ZCode/OpenClaw/Reasonix files or a .story-deployed marker.\",\n \"story-long-analyze\": \"Use oh_story_role for chapter extraction or specialist analysis. Never inspect platform agent directories or require a deployed external Agent definition.\",\n \"story-long-write\": \"All named Roles are provided through oh_story_role. Do not check platform agent files. Keep the upstream writing, Tracking, lint, outline, revision, and quality workflows.\",\n \"story-review\": \"All named reviewer Roles are provided through oh_story_role. Do not check platform agent files; full/lean review may use the bundled Roles directly.\",\n \"story-import\": \"All named Roles are provided through oh_story_role. Do not require story-setup to deploy them.\",\n \"story-deslop\": \"Use the bundled narrative-writer Role through oh_story_role when specialist review is useful. Never inspect platform agent directories.\",\n \"story-short-analyze\": \"Use oh_story_role for specialist analysis. Never inspect platform agent directories or require external Agent deployment.\",\n \"story-short-write\": \"All named Roles are provided through oh_story_role. Do not inspect platform agent files; preserve the upstream short-fiction workflow and quality gates.\",\n \"browser-cdp\": \"Use only browser or web capabilities visible in the current DSH preset. Do not start a parallel browser host; if no compatible capability is visible, explain the limitation.\",\n \"story-cover\": \"Use only image-generation or HTTP capabilities visible in the current DSH preset. Never assume a separate Codex or Claude runtime.\"\n};\nconst DSH_DRAMA_BRIDGE = [\n \"<short-drama-dsh-integration>\",\n \"This Skill is a native contribution to the current DeepSeek Harness session.\",\n \"DSH owns the workspace, model, preset, permissions, Session Log, tools, approvals, cancellation, resume, and Agent UI.\",\n \"The \u77ED\u5267 tab is the creator workspace. Never start dashboard_server.py, another web server, Dashboard, Agent runtime, session transport, or model configuration.\",\n \"Drama Skills v0.6 uses a creator-first contract: each episode keeps only the requested documents, up to five creator-facing sources at \u5267\u96C6/<EP>/\u5267\u672C.md, \u89C6\u89C9\u8BBE\u5B9A.md, \u5206\u955C.md, \u56FE\u7247\u63D0\u793A\u8BCD.md, and \u89C6\u9891\u63D0\u793A\u8BCD.md. Never precreate empty documents, backfill nominal stages, or start work the creator did not request. Persisted reviews use creator-readable Markdown under \u5BA1\u67E5/; an oral review writes nothing.\",\n \"For a v0.6 project, never create a parallel JSON/JSONL lifecycle truth, indexes, fingerprints, coverage tables, or QA records merely because legacy maintenance scripts and templates remain bundled.\",\n \"Never upgrade a v0.5 structured project in place or mix both contracts in one project root. Keep legacy production/audit artifacts read-only and pinned to v0.5; migrate only into a new creator-first root with manual per-episode creator confirmation.\",\n \"Use only tools visible in the current DSH preset and preserve the upstream project ownership, freshness, review, and explicit production-confirmation contracts.\",\n \"Production credentials remain outside project files. Never treat a prior acceptance, preview, continuation request, or budget discussion as confirmation for a paid production run.\",\n \"</short-drama-dsh-integration>\"\n].join(\"\\n\");\nconst DSH_DRAMA_OVERRIDES: Readonly<Partial<Record<string, string>>> = {\n \"short-drama\": \"A dashboard request means focus or use the native \u77ED\u5267 tab in this DSH Session. Do not run the bundled standalone Dashboard script. New projects follow only the v0.6 creator-first contract and create only documents required by the current request.\",\n \"short-drama-produce\": \"Use an upstream adapter only after the creator explicitly confirms the exact current job. Its source must be the current creator-first Markdown and its output belongs under \u5267\u96C6/<EP>/\u5236\u4F5C\u6210\u679C/. DSH permissions and approval UI remain authoritative.\"\n};\n\nconst DSH_NATIVE_SKILLS: Readonly<Partial<Record<string, string>>> = {\n story: `# story \u2014 DSH \u5C0F\u8BF4\u6D41\u7A0B\u5165\u53E3\n\n\u5728\u5F53\u524D DSH Session \u5185\u5224\u65AD\u7528\u6237\u610F\u56FE\uFF0C\u5E76\u52A0\u8F7D\u6700\u5339\u914D\u7684 Oh Story Skill\uFF1A\n\n- \u65B0\u5EFA\u6216\u4FEE\u590D\u5C0F\u8BF4\u5DE5\u7A0B\uFF1Astory-setup\n- \u957F\u7BC7\u9009\u9898/\u626B\u699C/\u62C6\u6587/\u65E5\u66F4\uFF1Astory-long-scan\u3001story-long-analyze\u3001story-long-write\n- \u77ED\u7BC7\u9009\u9898/\u62C6\u6587/\u5199\u4F5C\uFF1Astory-short-scan\u3001story-short-analyze\u3001story-short-write\n- \u5BFC\u5165\u5DF2\u6709\u4F5C\u54C1\uFF1Astory-import\n- \u5BA1\u7A3F\u4E0E\u53BB AI \u5473\uFF1Astory-review\u3001story-deslop\n- \u5C01\u9762\uFF1Astory-cover\n\n\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\nAgent\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\n\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`,\n \"story-setup\": `# story-setup \u2014 DSH \u539F\u751F\u5C0F\u8BF4\u5DE5\u7A0B\u521D\u59CB\u5316\n\n\u53EA\u521D\u59CB\u5316\u6216\u6821\u9A8C\u5F53\u524D DSH workspace \u4E2D\u7684\u5C0F\u8BF4\u6570\u636E\uFF0C\u4E0D\u90E8\u7F72\u4EFB\u4F55 Agent \u5E73\u53F0\u6587\u4EF6\u3002\n\n1. \u68C0\u67E5\u73B0\u6709\u6B63\u6587\u3001\u8BBE\u5B9A\u3001\u5927\u7EB2\u548C\u8FFD\u8E2A\u6587\u4EF6\uFF0C\u5DF2\u6709\u5185\u5BB9\u7EDD\u4E0D\u8986\u76D6\u3002\n2. \u6839\u636E\u7528\u6237\u58F0\u660E\u4E0E\u73B0\u6709\u7ED3\u6784\u5224\u65AD\u957F\u7BC7/\u77ED\u7BC7\uFF1B\u65E0\u6CD5\u53EF\u9760\u5224\u65AD\u65F6\u8BF7\u6C42\u786E\u8BA4\u3002\n3. \u957F\u7BC7\u6309\u9700\u5EFA\u7ACB \u6B63\u6587/\u3001\u8BBE\u5B9A/\u3001\u5927\u7EB2/\u3001\u8FFD\u8E2A/\uFF0C\u5E76\u51C6\u5907\u8FFD\u8E2A/_tracking-state.json\uFF1B\n \u7B2C\u4E00\u7AE0\u6B63\u6587\u843D\u76D8\u524D\u5FC5\u987B\u6709\u5BF9\u5E94\u7EC6\u7EB2\u3002\u77ED\u7BC7\u4FDD\u6301\u8F7B\u91CF\u7ED3\u6784\uFF0C\u4E0D\u5F3A\u52A0\u957F\u7BC7 Tracking\u3002\n4. \u9700\u8981\u67B6\u6784\u3001\u89D2\u8272\u6216\u7814\u7A76\u5DE5\u4F5C\u65F6\uFF0C\u901A\u8FC7 oh_story_role \u8C03\u7528\u5DF2\u6253\u5305 Role\uFF1B\u4E0D\u8981\u68C0\u67E5\u6216\n \u751F\u6210 .claude\u3001.codex\u3001.opencode\u3001.zcode\u3001AGENTS.md \u6216 .story-deployed\u3002\n5. \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\n\n\u9898\u6750\u3001\u89D2\u8272\u3001\u8282\u594F\u3001\u51B2\u7A81\u3001\u5F00\u7BC7\u548C\u5199\u4F5C\u65B9\u6CD5\u8D44\u6599\u4F4D\u4E8E references/agent-references/\uFF1B\n\u53EA\u52A0\u8F7D\u5F53\u524D\u4EFB\u52A1\u9700\u8981\u7684\u6587\u4EF6\u3002`,\n \"browser-cdp\": `# browser-cdp \u2014 DSH \u6D4F\u89C8\u5668\u80FD\u529B\u9002\u914D\n\n\u672C Skill \u4E0D\u542F\u52A8 Chrome\u3001CDP \u7AEF\u53E3\u3001\u72EC\u7ACB\u6D4F\u89C8\u5668 Host \u6216 setup-cdp-chrome.js\u3002\n\u4EC5\u4F7F\u7528\u5F53\u524D DSH Preset \u5DF2\u66B4\u9732\u7684 web_search\u3001web_fetch \u6216\u6D4F\u89C8\u5668\u5DE5\u5177\u5B8C\u6210\u7F51\u9875\u8BFB\u53D6\u3001\n\u699C\u5355\u91C7\u96C6\u548C\u8D44\u6599\u6838\u9A8C\u3002\u4FDD\u6301\u4EE5\u4E0B\u539F\u5219\uFF1A\n\n1. \u4F18\u5148\u4F7F\u7528\u7ED3\u6784\u5316\u641C\u7D22/\u6293\u53D6\u5DE5\u5177\uFF1B\u9700\u8981\u767B\u5F55\u6001\u6216\u4EA4\u4E92\u9875\u9762\u65F6\u624D\u4F7F\u7528\u53EF\u89C1\u6D4F\u89C8\u5668\u80FD\u529B\u3002\n2. \u5C0A\u91CD\u7AD9\u70B9\u6761\u6B3E\u3001\u8BBF\u95EE\u9891\u7387\u4E0E\u7528\u6237\u6388\u6743\uFF1B\u4E0D\u7ED5\u8FC7\u9A8C\u8BC1\u7801\u3001\u4ED8\u8D39\u5899\u6216\u8BBF\u95EE\u63A7\u5236\u3002\n3. \u8BB0\u5F55\u6765\u6E90 URL\u3001\u91C7\u96C6\u65F6\u95F4\u3001\u5931\u8D25\u9879\u548C\u6570\u636E\u8D28\u91CF\uFF0C\u4E0D\u628A\u63A8\u65AD\u5199\u6210\u9875\u9762\u4E8B\u5B9E\u3002\n4. \u5F53\u524D Preset \u6CA1\u6709\u517C\u5BB9\u80FD\u529B\u65F6\uFF0C\u8BF4\u660E\u7F3A\u5931\u80FD\u529B\u548C\u53EF\u884C\u7684\u624B\u5DE5\u6B65\u9AA4\uFF0C\u4E0D\u53E6\u8D77\u8FD0\u884C\u65F6\u3002`,\n \"story-long-scan\": `# story-long-scan \u2014 DSH \u539F\u751F\u957F\u7BC7\u626B\u699C\n\n\u57FA\u4E8E\u53EF\u6838\u9A8C\u6837\u672C\u8BC6\u522B\u957F\u7BC7\u7F51\u6587\u8D8B\u52BF\uFF0C\u4E0D\u8FD0\u884C\u6253\u5305\u811A\u672C\u3001\u4E0D\u63D0\u53D6\u767B\u5F55\u51ED\u636E\uFF0C\u4E5F\u4E0D\u7ED5\u8FC7\u9A8C\u8BC1\u7801\u3001\n\u8BBF\u95EE\u63A7\u5236\u6216\u7AD9\u70B9\u9650\u5236\u3002\n\n1. \u660E\u786E\u5E73\u53F0\u3001\u9891\u9053\u548C\u9898\u6750\u65B9\u5411\uFF1B\u53EA\u6709\u7B54\u6848\u4F1A\u6539\u53D8\u91C7\u6837\u8303\u56F4\u65F6\u624D\u95EE\u4E00\u4E2A\u95EE\u9898\u3002\n2. \u6570\u636E\u6765\u6E90\u4F9D\u6B21\u4E3A\uFF1A\u7528\u6237\u63D0\u4F9B\u7684\u6570\u636E\u6216\u94FE\u63A5\u3001\u5F53\u524D DSH Preset \u53EF\u89C1\u7684\u7F51\u9875\u5DE5\u5177\u3001\n references/genre-trends.md \u4E2D\u7684\u5386\u53F2\u8D8B\u52BF\u3002\u65E0\u6CD5\u83B7\u53D6\u5B9E\u65F6\u6570\u636E\u65F6\u5FC5\u987B\u660E\u786E\u6807\u4E3A\u5386\u53F2\u5047\u8BBE\u3002\n3. \u6BCF\u4E2A\u6837\u672C\u8BB0\u5F55\u6765\u6E90 URL\u3001\u91C7\u96C6\u65E5\u671F\u3001\u699C\u5355\u53E3\u5F84\u3001\u6709\u6548\u6761\u76EE\u6570\u3001\u7F3A\u5931\u5B57\u6BB5\u548C\u5F02\u5E38\u9879\uFF1B\n \u4E0D\u628A\u641C\u7D22\u6458\u8981\u3001\u63A8\u65AD\u6216\u8FC7\u671F\u7F13\u5B58\u5199\u6210\u9875\u9762\u4E8B\u5B9E\u3002\n4. \u6309\u9898\u6750\u5206\u5E03\u3001\u65B0\u9898\u6750\u4FE1\u53F7\u3001\u7ECF\u5178\u9898\u6750\u53D8\u5316\u3001\u7BC7\u5E45\u4E0E\u66F4\u65B0\u3001\u4E66\u540D\u6A21\u5F0F\u3001\u5F00\u5934\u5356\u70B9\u548C\n \u5DEE\u5F02\u5316\u5143\u7D20\u5206\u6790\u3002\u9700\u8981\u51B3\u7B56\u95E8\u7981\u65F6\u4F7F\u7528 references/topic-decision.md\u3002\n5. \u8F93\u51FA\u5E02\u573A\u6982\u51B5\u3001\u9898\u6750\u70ED\u5EA6\u3001\u8BC1\u636E\u4E0E\u53EF\u4FE1\u5EA6\u3001\u98CE\u9669\u3001\u4E09\u9879\u53EF\u6267\u884C\u65B9\u5411\u548C\u4E0B\u6B21\u590D\u626B\u65F6\u95F4\u3002\n\n\u5F53\u524D Preset \u6CA1\u6709\u7F51\u9875\u80FD\u529B\u4E14\u7528\u6237\u4E5F\u672A\u63D0\u4F9B\u6837\u672C\u65F6\uFF0C\u4F7F\u7528\u5185\u7F6E\u53C2\u8003\u5B8C\u6210\u65B9\u6CD5\u8BBA\u5206\u6790\uFF0C\n\u5E76\u5217\u51FA\u4ECD\u9700\u6838\u9A8C\u7684\u699C\u5355\uFF1B\u4E0D\u8981\u542F\u52A8 CDP\u3001\u72EC\u7ACB\u6D4F\u89C8\u5668\u6216\u5E76\u884C\u8FD0\u884C\u65F6\u3002`,\n \"story-short-scan\": `# story-short-scan \u2014 DSH \u539F\u751F\u77ED\u7BC7\u626B\u699C\n\n\u57FA\u4E8E\u53EF\u6838\u9A8C\u6837\u672C\u8BC6\u522B\u77ED\u7BC7\u5E02\u573A\u7684\u60C5\u7EEA\u3001\u9898\u6750\u4E0E\u4F20\u64AD\u4FE1\u53F7\uFF0C\u4E0D\u8FD0\u884C\u6253\u5305\u811A\u672C\u3001\u4E0D\u8BFB\u53D6 Cookie\n\u6216 token\uFF0C\u4E5F\u4E0D\u7ED5\u8FC7\u9A8C\u8BC1\u7801\u3001\u767B\u5F55\u6216\u8BBF\u95EE\u63A7\u5236\u3002\n\n1. \u660E\u786E\u5E73\u53F0\u4E0E\u65B9\u5411\uFF1B\u53EA\u6709\u7B54\u6848\u4F1A\u6539\u53D8\u91C7\u6837\u8303\u56F4\u65F6\u624D\u95EE\u4E00\u4E2A\u95EE\u9898\u3002\n2. \u6570\u636E\u6765\u6E90\u4F9D\u6B21\u4E3A\uFF1A\u7528\u6237\u63D0\u4F9B\u7684\u6570\u636E\u6216\u94FE\u63A5\u3001\u5F53\u524D DSH Preset \u53EF\u89C1\u7684\u7F51\u9875\u5DE5\u5177\u3001\n references/real-market-data.md \u4E2D\u7684\u5386\u53F2\u8D44\u6599\u3002\u65E0\u6CD5\u8054\u7F51\u65F6\u5FC5\u987B\u628A\u7ED3\u8BBA\u6807\u4E3A\u5019\u9009\u5047\u8BBE\u3002\n3. \u8BB0\u5F55\u6765\u6E90 URL\u3001\u91C7\u96C6\u65E5\u671F\u3001\u699C\u5355\u53E3\u5F84\u3001\u6709\u6548\u6837\u672C\u6570\u3001\u7F3A\u5931\u5B57\u6BB5\u548C\u5F02\u5E38\u9879\u3002\n4. \u5206\u6790\u60C5\u7EEA\u7C7B\u578B\u3001\u9898\u6750\u70ED\u70B9\u3001\u7BC7\u5E45\u3001\u5F00\u5934\u3001\u7ED3\u5C3E\u3001\u6807\u9898\u3001\u4EBA\u8BBE\u4E0E\u4F20\u64AD\u89E6\u53D1\u70B9\uFF1B\n \u7ED9\u6BCF\u4E2A\u8D8B\u52BF\u6807\u6CE8\u8BC1\u636E\u5F3A\u5EA6\u3001\u9971\u548C\u98CE\u9669\u548C\u6709\u6548\u671F\u3002\n5. \u8F93\u51FA\u5E02\u573A\u6982\u51B5\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\n\n\u5F53\u524D Preset \u6CA1\u6709\u7F51\u9875\u80FD\u529B\u4E14\u7528\u6237\u4E5F\u672A\u63D0\u4F9B\u6837\u672C\u65F6\uFF0C\u53EA\u505A\u5386\u53F2\u8D44\u6599\u5206\u6790\u5E76\u5217\u51FA\u9A8C\u8BC1\u52A8\u4F5C\uFF1B\n\u4E0D\u8981\u542F\u52A8 CDP\u3001\u72EC\u7ACB\u6D4F\u89C8\u5668\u6216\u5E76\u884C\u8FD0\u884C\u65F6\u3002`\n};\n\ninterface ParsedSkill {\n readonly name: string;\n readonly description: string;\n readonly content: string;\n}\n\nfunction frontmatterValue(frontmatter: string, key: string): string | undefined {\n const match = new RegExp(`^${key}:\\\\s*(.+)$`, \"mu\").exec(frontmatter);\n const raw = match?.[1]?.trim();\n if (raw === undefined) return undefined;\n if (raw.startsWith(\"\\\"\") && raw.endsWith(\"\\\"\")) {\n try { return JSON.parse(raw) as string; }\n catch { return raw.slice(1, -1); }\n }\n return raw.replace(/^['\"]|['\"]$/gu, \"\");\n}\n\nexport function parseBundledSkill(source: string): ParsedSkill {\n const match = /^---\\r?\\n([\\s\\S]*?)\\r?\\n---\\r?\\n?/u.exec(source);\n if (match?.[1] === undefined) throw new Error(\"Bundled skill is missing YAML frontmatter.\");\n const name = frontmatterValue(match[1], \"name\");\n const description = frontmatterValue(match[1], \"description\");\n if (!name || !/^[a-z0-9]+(?:-[a-z0-9]+)*$/u.test(name)) throw new Error(\"Bundled skill has an invalid name.\");\n if (!description) throw new Error(`Bundled skill \"${name}\" has no description.`);\n return { name, description, content: source.slice(match[0].length) };\n}\n\nexport function dshSkillContent(name: string, content: string): string {\n const override = DSH_SKILL_OVERRIDES[name];\n const native = DSH_NATIVE_SKILLS[name];\n return `${DSH_SKILL_BRIDGE}${override === undefined ? \"\" : `\\n<skill-specific-dsh-override>${override}</skill-specific-dsh-override>`}\\n\\n${native ?? content}`;\n}\n\nexport function defaultBundledSkillRoot(): string {\n const current = dirname(fileURLToPath(import.meta.url));\n return basename(current) === \"src\"\n ? resolve(current, \"../../knowledge/oh-story/skills\")\n : resolve(current, \"oh-story/skills\");\n}\n\nexport function defaultDramaSkillRoot(): string {\n const current = dirname(fileURLToPath(import.meta.url));\n return basename(current) === \"src\"\n ? resolve(current, \"../../knowledge/drama/skills\")\n : resolve(current, \"drama/skills\");\n}\n\nfunction createBundledSkillProvider(\n providerName: string,\n skillRoot: string,\n content: (name: string, source: string) => string\n): SkillProvider {\n const root = resolve(skillRoot);\n return {\n name: providerName,\n async list(): Promise<readonly SkillCandidate[]> {\n const directories = (await readdir(root, { withFileTypes: true }))\n .filter((entry) => entry.isDirectory())\n .map((entry) => entry.name)\n .sort();\n return Promise.all(directories.map(async (directory): Promise<SkillCandidate> => {\n const path = join(root, directory, \"SKILL.md\");\n const parsed = parseBundledSkill(await readFile(path, \"utf8\"));\n if (parsed.name !== directory) throw new Error(`Bundled skill directory \"${directory}\" does not match name \"${parsed.name}\".`);\n return {\n name: parsed.name,\n description: parsed.description,\n invocation: INVOCATION,\n provider: providerName,\n source: \"bundled\",\n resourceBase: { kind: \"directory\", path: join(root, directory) },\n rank: BUNDLED_SKILL_RANK,\n locator: pathToFileURL(path),\n path\n };\n }));\n },\n async get(candidate): Promise<SkillDefinition | undefined> {\n if (candidate.provider !== providerName || typeof candidate.path !== \"string\") return undefined;\n const path = resolve(candidate.path);\n const relativePath = relative(root, path);\n if (relativePath === \"\" || relativePath.startsWith(\"..\") || isAbsolute(relativePath)) {\n throw new Error(\"Bundled skill locator escaped the packaged skill root.\");\n }\n const parsed = parseBundledSkill(await readFile(path, \"utf8\"));\n if (parsed.name !== candidate.name) return undefined;\n return {\n name: parsed.name,\n description: parsed.description,\n invocation: INVOCATION,\n provider: providerName,\n source: \"bundled\",\n resourceBase: { kind: \"directory\", path: join(root, parsed.name) },\n path,\n content: content(parsed.name, parsed.content)\n };\n }\n };\n}\n\nexport function createOhStorySkillProvider(skillRoot = defaultBundledSkillRoot()): SkillProvider {\n return createBundledSkillProvider(STORY_PROVIDER_NAME, skillRoot, dshSkillContent);\n}\n\nexport function dshDramaSkillContent(name: string, content: string): string {\n const override = DSH_DRAMA_OVERRIDES[name];\n return `${DSH_DRAMA_BRIDGE}${override === undefined ? \"\" : `\\n<skill-specific-dsh-override>${override}</skill-specific-dsh-override>`}\\n\\n${content}`;\n}\n\nexport function createDramaSkillProvider(skillRoot = defaultDramaSkillRoot()): SkillProvider {\n return createBundledSkillProvider(DRAMA_PROVIDER_NAME, skillRoot, dshDramaSkillContent);\n}\n", "import type { Context } from \"@deepseek-ai/cordis\";\nimport type { FileSystem, FsTarget } from \"@deepseek-ai/dsh-fs\";\nimport { createUserMessage } from \"@deepseek-ai/dsh-llm\";\nimport type { PostToolDecision, PreToolDecision, ToolExecution } from \"@deepseek-ai/dsh-tools\";\n\nconst MUTATION_TOOLS = new Set([\"write\", \"edit\", \"str_replace_editor\"]);\n\nexport interface StoryMutation {\n readonly root: string;\n readonly path: string;\n readonly chapter?: number;\n}\n\nfunction mutationPath(name: string, args: unknown): string | undefined {\n if (!MUTATION_TOOLS.has(name) || typeof args !== \"object\" || args === null || Array.isArray(args)) return undefined;\n const record = args as Record<string, unknown>;\n if (name === \"str_replace_editor\") {\n if (!new Set([\"create\", \"str_replace\", \"insert\"]).has(String(record.command))) return undefined;\n return typeof record.path === \"string\" && record.path.trim() !== \"\" ? record.path : undefined;\n }\n return typeof record.file_path === \"string\" && record.file_path.trim() !== \"\" ? record.file_path : undefined;\n}\n\nfunction normalizedRelativePath(path: string): string | undefined {\n const segments: string[] = [];\n for (const part of path.split(\"/\")) {\n if (part === \"\" || part === \".\") continue;\n if (part === \"..\") {\n if (segments.length === 0) return undefined;\n segments.pop();\n } else segments.push(part);\n }\n return segments.join(\"/\");\n}\n\nexport function detectStoryMutation(name: string, args: unknown, cwd: string | undefined): StoryMutation | undefined {\n const rawPath = mutationPath(name, args);\n if (cwd === undefined || rawPath === undefined) return undefined;\n const root = cwd.replaceAll(\"\\\\\", \"/\").replace(/\\/$/u, \"\");\n const candidate = rawPath.replaceAll(\"\\\\\", \"/\");\n const absolute = candidate.startsWith(\"/\") || /^[a-z]:\\//iu.test(candidate) || /^[a-z][a-z\\d+.-]*:\\/\\//iu.test(candidate);\n const insideRoot = /^[a-z]:\\//iu.test(root)\n ? candidate.toLowerCase().startsWith(`${root.toLowerCase()}/`)\n : candidate.startsWith(`${root}/`);\n if (absolute && !insideRoot) return undefined;\n const normalized = normalizedRelativePath(absolute ? candidate.slice(root.length + 1) : candidate);\n if (normalized === undefined) return undefined;\n if (!normalized.startsWith(\"\u6B63\u6587/\")) return undefined;\n const chapterText = /\u7B2C0*(\\d+)\u7AE0/u.exec(normalized)?.[1];\n return { root, path: normalized, ...(chapterText === undefined ? {} : { chapter: Number(chapterText) }) };\n}\n\ntype StoryFileSystem = Pick<FileSystem, \"resolve\" | \"contains\" | \"stat\" | \"listDir\">;\n\nasync function storyMutation(exec: ToolExecution, fs: StoryFileSystem): Promise<StoryMutation | undefined> {\n const cwd = exec.agent?.session.header.cwd;\n const path = mutationPath(exec.name, exec.arguments);\n if (cwd === undefined || path === undefined) return undefined;\n try {\n const [rootTarget, mutationTarget] = await Promise.all([\n fs.resolve(cwd, { signal: exec.signal }),\n fs.resolve(path, { cwd, signal: exec.signal })\n ]);\n if (!fs.contains(rootTarget, mutationTarget)) return undefined;\n } catch { return undefined; }\n return detectStoryMutation(exec.name, exec.arguments, cwd);\n}\n\nasync function target(fs: StoryFileSystem, root: string, path: string, signal?: AbortSignal): Promise<FsTarget> {\n return fs.resolve(path, { cwd: root, ...(signal === undefined ? {} : { signal }) });\n}\n\nasync function exists(fs: StoryFileSystem, root: string, path: string, signal?: AbortSignal): Promise<boolean> {\n return target(fs, root, path, signal)\n .then((value) => fs.stat(value, signal))\n .then((info) => info !== undefined, () => false);\n}\n\nasync function hasChapterOutline(fs: StoryFileSystem, root: string, chapter: number, signal?: AbortSignal): Promise<boolean> {\n const entries = await target(fs, root, \"\u5927\u7EB2\", signal)\n .then((directory) => fs.listDir(directory, signal))\n .catch(() => []);\n return entries.some((entry) => entry.type === \"file\"\n && Number(/^\u7EC6\u7EB2_\u7B2C0*(\\d+)\u7AE0.*\\.md$/u.exec(entry.name)?.[1]) === chapter);\n}\n\nexport async function validateStoryMutation(\n fs: StoryFileSystem,\n mutation: StoryMutation,\n signal?: AbortSignal\n): Promise<string | undefined> {\n const hasLongFormLayout = await exists(fs, mutation.root, \"\u5927\u7EB2\", signal)\n || await exists(fs, mutation.root, \"\u8FFD\u8E2A\", signal);\n if (!hasLongFormLayout) return undefined;\n if (!(await exists(fs, mutation.root, \"\u8FFD\u8E2A/_tracking-state.json\", signal))) {\n // Setup/import must be able to bootstrap an existing manuscript before the\n // canonical Tracking file exists. The Skill remains responsible for\n // creating it; hard guards begin once the project has committed Tracking.\n return undefined;\n }\n if (mutation.chapter !== undefined && !(await hasChapterOutline(fs, mutation.root, mutation.chapter, signal))) {\n 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`;\n }\n return undefined;\n}\n\nexport async function decideStoryMutation(\n exec: ToolExecution,\n next: () => Promise<PreToolDecision>\n): Promise<PreToolDecision> {\n const fs = exec.agent?.ctx.get(\"fs\");\n if (fs === undefined) return next();\n const mutation = await storyMutation(exec, fs);\n if (mutation === undefined) return next();\n const reason = await validateStoryMutation(fs, mutation, exec.signal);\n if (reason !== undefined) return { kind: \"deny\", reason };\n return next();\n}\n\n/**\n * Native DSH equivalents of the upstream prose guards. They join DSH's typed\n * tool waterfall, so decisions remain visible in the official approval/tool UI.\n */\nexport function registerOhStoryHooks(context: Context): void {\n context.on(\"tools/pre-execute\", decideStoryMutation);\n\n context.on(\"tools/post-execute\", async (exec, result, next): Promise<PostToolDecision> => {\n const downstream = await next();\n if (result.isError || downstream.kind !== \"accept\") return downstream;\n const fs = exec.agent?.ctx.get(\"fs\");\n const mutation = fs === undefined ? undefined : await storyMutation(exec, fs);\n if (mutation === undefined) return downstream;\n const reminder = createUserMessage({\n source: { kind: \"plugin\", plugin: \"oh-story\" },\n content: [{\n type: \"text\",\n 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>`\n }]\n });\n return {\n ...downstream,\n additionalContexts: [...downstream.additionalContexts ?? [], reminder]\n };\n });\n}\n", "import type { Context } from \"@deepseek-ai/cordis\";\nimport type { ContentBlock } from \"@deepseek-ai/dsh-llm\";\nimport type { JsonValue } from \"@deepseek-ai/dsh-session\";\nimport type { SubagentRuntime } from \"@deepseek-ai/dsh-subagent\";\nimport { defineTool, type ToolDefinition } from \"@deepseek-ai/dsh-tools\";\nimport {\n bundledReferenceGuard,\n createOhStoryReferenceTool,\n OH_STORY_REFERENCE_TOOL_NAME\n} from \"./reference-tool.js\";\nimport { OH_STORY_ROLE_NAMES, loadBundledRole, type OhStoryRoleName } from \"./role-provider.js\";\n\nexport const OH_STORY_ROLE_TOOL_NAME = \"oh_story_role\";\nexport type OhStoryRoleSubagents = Pick<SubagentRuntime, \"start\">;\n\nconst roleTools: Readonly<Record<OhStoryRoleName, readonly string[]>> = {\n \"chapter-extractor\": [\"read\", \"glob\", \"grep\"],\n \"character-designer\": [OH_STORY_REFERENCE_TOOL_NAME, \"read\", \"glob\", \"grep\", \"write\", \"edit\"],\n \"consistency-checker\": [OH_STORY_REFERENCE_TOOL_NAME, \"read\", \"glob\", \"grep\"],\n \"narrative-writer\": [OH_STORY_REFERENCE_TOOL_NAME, \"read\", \"glob\", \"grep\", \"write\", \"edit\", \"bash\"],\n \"story-architect\": [OH_STORY_REFERENCE_TOOL_NAME, \"read\", \"glob\", \"grep\", \"write\", \"edit\"],\n \"story-explorer\": [\"read\", \"glob\", \"grep\"],\n \"story-researcher\": [\"read\", \"glob\", \"grep\", \"bash\", \"write\", \"web_search\", \"web_fetch\"]\n};\n\nexport function roleToolFilter(role: OhStoryRoleName): { readonly allow: readonly string[] } {\n return { allow: roleTools[role] };\n}\n\nfunction resultText(output: readonly ContentBlock[]): string {\n return output.map((block) => block.type === \"text\" ? block.text : JSON.stringify(block)).join(\"\\n\");\n}\n\nexport async function createOhStoryRoleTool(subagents?: OhStoryRoleSubagents): Promise<ToolDefinition> {\n const personas = new Map<OhStoryRoleName, string>();\n await Promise.all(OH_STORY_ROLE_NAMES.map(async (role) => {\n personas.set(role, await loadBundledRole(role, undefined, \"native-tools\"));\n }));\n return defineTool({\n name: OH_STORY_ROLE_TOOL_NAME,\n description: \"Run one focused Oh Story specialist as a child of the current DSH Agent. The child inherits DSH model, workspace, permissions, lifecycle, and UI.\",\n parameters: {\n role: {\n type: \"string\",\n required: true,\n enum: OH_STORY_ROLE_NAMES,\n description: \"The exact Oh Story Role to run.\"\n },\n prompt: {\n type: \"string\",\n required: true,\n description: \"A self-contained task. The child inherits the current DSH workspace but not the current in-flight turn.\"\n }\n },\n output: {\n schema: {\n type: \"object\",\n additionalProperties: false,\n properties: {\n role: { type: \"string\", required: true, enum: OH_STORY_ROLE_NAMES },\n runId: { type: \"string\", required: true },\n content: { type: \"array\", required: true, items: { type: \"json\" } }\n }\n },\n render: (_args, value) => [{ type: \"text\", text: resultText(value.content as unknown as ContentBlock[]) }]\n },\n isConcurrencySafe: () => true,\n async execute(args, exec) {\n if (exec.agent === undefined) throw new Error(\"oh_story_role requires a calling DSH Agent.\");\n const persona = personas.get(args.role);\n if (persona === undefined) throw new Error(`Oh Story Role ${args.role} is not bundled.`);\n const allowed = roleToolFilter(args.role).allow.filter((name) =>\n exec.agent?.ctx.tools.get(name, exec.agent) !== undefined);\n const runtime = subagents ?? exec.agent.ctx.get(\"subagents\");\n if (runtime === undefined) throw new Error(\"oh_story_role requires the DSH subagent runtime.\");\n const run = await runtime.start(\"spawn\", {\n label: `oh-story:${args.role}`,\n prompt: [{ type: \"text\", text: args.prompt }],\n parent: exec.agent,\n persona,\n toolFilter: { allow: allowed },\n maxDepth: 1,\n signal: exec.signal\n });\n try {\n const result = await run.result;\n if (result.stopReason !== \"completed\") {\n throw new Error(`Oh Story Role ${args.role} ended with ${result.stopReason}${result.diagnostic === undefined ? \"\" : `: ${result.diagnostic}`}`);\n }\n return {\n role: args.role,\n runId: run.id,\n content: result.output as unknown as JsonValue[]\n };\n } finally {\n await run.dispose();\n }\n }\n });\n}\n\nexport async function registerOhStoryRoleTool(context: Context): Promise<void> {\n const [definition, referenceDefinition] = await Promise.all([\n createOhStoryRoleTool(context.subagents),\n createOhStoryReferenceTool()\n ]);\n context.tools.register(referenceDefinition);\n context.tools.guard(bundledReferenceGuard(referenceDefinition, context.tools));\n let dispose: (() => void) | undefined;\n const mount = (): void => { dispose ??= context.tools.register(definition); };\n const unmount = (): void => { dispose?.(); dispose = undefined; };\n context.on(\"subagent/provider-added\", (provider) => { if (provider.name === \"spawn\") mount(); });\n context.on(\"subagent/provider-removed\", (name) => { if (name === \"spawn\") unmount(); });\n if (context.subagents.getProvider(\"spawn\") !== undefined) mount();\n}\n", "import { readdir, readFile, realpath } from \"node:fs/promises\";\nimport { isAbsolute, join, relative, resolve } from \"node:path\";\nimport { defineTool, type ToolDefinition, type ToolGuard, type ToolRuntime } from \"@deepseek-ai/dsh-tools\";\nimport { defaultBundledSkillRoot } from \"./skill-provider.js\";\n\nexport const OH_STORY_REFERENCE_TOOL_NAME = \"oh_story_bundled_reference\";\n\ninterface BundledReference {\n readonly canonicalPath: string;\n readonly name: string;\n}\n\nasync function collectMarkdown(root: string, directory = root): Promise<string[]> {\n const entries = await readdir(directory, { withFileTypes: true });\n const nested = await Promise.all(entries.map(async (entry): Promise<string[]> => {\n const path = join(directory, entry.name);\n if (entry.isDirectory()) return collectMarkdown(root, path);\n return entry.isFile() && entry.name.endsWith(\".md\") ? [path] : [];\n }));\n return nested.flat();\n}\n\nasync function bundledReferences(storySetupRoot: string): Promise<readonly BundledReference[]> {\n const root = await realpath(resolve(storySetupRoot));\n const referenceRoot = await realpath(join(root, \"references\", \"agent-references\"));\n const referenceDirectory = relative(root, referenceRoot);\n if (referenceDirectory === \"\" || referenceDirectory.startsWith(\"..\") || isAbsolute(referenceDirectory)) {\n throw new Error(\"Bundled Oh Story reference directory escaped its package root.\");\n }\n const values = await Promise.all((await collectMarkdown(referenceRoot)).map(async (path): Promise<BundledReference> => {\n const canonicalPath = await realpath(path);\n const inside = relative(referenceRoot, canonicalPath);\n if (inside === \"\" || inside.startsWith(\"..\") || isAbsolute(inside)) {\n throw new Error(`Bundled Oh Story reference escaped its package root: ${path}`);\n }\n return {\n canonicalPath,\n name: `story-setup/references/agent-references/${inside.replaceAll(\"\\\\\", \"/\")}`\n };\n }));\n return values.sort((left, right) => left.name.localeCompare(right.name));\n}\n\nexport async function createOhStoryReferenceTool(\n storySetupRoot = join(defaultBundledSkillRoot(), \"story-setup\")\n): Promise<ToolDefinition> {\n const references = await bundledReferences(storySetupRoot);\n if (references.length === 0) throw new Error(\"No bundled Oh Story references were found.\");\n const paths = references.map((reference) => reference.name);\n const byName = new Map(references.map((reference) => [reference.name, reference.canonicalPath]));\n return defineTool({\n name: OH_STORY_REFERENCE_TOOL_NAME,\n description: \"Read one exact, pinned Oh Story story-setup reference bundled with this plugin. This does not resolve project Skills or workspace files.\",\n parameters: {\n reference: {\n type: \"string\",\n required: true,\n enum: paths,\n description: \"The exact story-setup reference path named by the active bundled Role.\"\n }\n },\n output: {\n schema: {\n type: \"object\",\n additionalProperties: false,\n properties: {\n reference: { type: \"string\", required: true },\n content: { type: \"string\", required: true }\n }\n },\n render: (_args, value) => [{\n type: \"text\",\n text: `Bundled Oh Story reference: ${value.reference}\\n\\n${value.content}`\n }]\n },\n isConcurrencySafe: () => true,\n async execute(args) {\n const path = byName.get(args.reference);\n if (path === undefined) throw new Error(`Oh Story reference is not bundled: ${args.reference}`);\n return { reference: args.reference, content: await readFile(path, \"utf8\") };\n }\n });\n}\n\n/** Deny a scoped same-name replacement instead of executing untrusted reference code. */\nexport function bundledReferenceGuard(\n definition: ToolDefinition,\n tools: Pick<ToolRuntime, \"get\">\n): ToolGuard {\n return (execution) => execution.name === OH_STORY_REFERENCE_TOOL_NAME\n && tools.get(OH_STORY_REFERENCE_TOOL_NAME, execution.agent) !== definition\n ? \"The pinned Oh Story reference tool was shadowed in this Agent scope.\"\n : undefined;\n}\n", "import { readFile } from \"node:fs/promises\";\nimport { basename, dirname, join, resolve } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nexport const OH_STORY_ROLE_NAMES = [\n \"chapter-extractor\",\n \"character-designer\",\n \"consistency-checker\",\n \"narrative-writer\",\n \"story-architect\",\n \"story-explorer\",\n \"story-researcher\"\n] as const;\n\nexport type OhStoryRoleName = typeof OH_STORY_ROLE_NAMES[number];\nexport type OhStoryRoleExecution = \"tool-free\" | \"native-tools\";\n\nfunction roleBody(source: string): string {\n const frontmatter = /^---\\r?\\n[\\s\\S]*?\\r?\\n---\\r?\\n?/u.exec(source);\n return source.slice(frontmatter?.[0].length ?? 0).trim();\n}\n\nexport function defaultBundledRoleRoot(): string {\n const current = dirname(fileURLToPath(import.meta.url));\n return basename(current) === \"src\"\n ? resolve(current, \"../../knowledge/oh-story/roles\")\n : resolve(current, \"oh-story/roles\");\n}\n\nexport async function loadBundledRole(\n name: OhStoryRoleName,\n roleRoot = defaultBundledRoleRoot(),\n execution: OhStoryRoleExecution = \"tool-free\"\n): Promise<string> {\n const body = roleBody(await readFile(join(resolve(roleRoot), `${name}.md`), \"utf8\"));\n if (body.length === 0) throw new Error(`Bundled role \"${name}\" is empty.`);\n const integration = execution === \"tool-free\"\n ? [\n \"You are running inside an Oh Story review-required DSH collaboration. The caller supplies every permitted input in the prompt.\",\n \"Do not read or write project files, do not call tools, and do not follow legacy .claude/.codex path or deployment instructions in the upstream role text.\",\n \"Return only the output contract requested by the caller; never claim to have changed the project.\"\n ]\n : [\n \"You are running as a native oh-story-dsh specialist. The current DSH workspace and visible tool set are your complete authority boundary.\",\n \"Never inspect or require legacy .claude/.opencode/.codex agent deployment files; this exact pinned Role is already active.\",\n \"Bundled story-setup references are pinned plugin resources, not project files or project Skills. When the upstream Role marks one mandatory, call oh_story_bundled_reference with the exact story-setup/references/agent-references path, then use only the returned content.\",\n \"If oh_story_bundled_reference or a required bundled reference is unavailable, report the missing reference to the caller. Never call the generic skill tool, fall back to a legacy platform path, or claim that an unread reference was used.\",\n \"Use only the tools actually visible to you. Mutate files only when the caller explicitly requests it and your visible DSH tools permit it; otherwise return findings to the caller.\"\n ];\n return [\n `OH_STORY_DSH_ROLE:${name}`,\n ...integration,\n \"\",\n body\n ].join(\"\\n\");\n}\n", "import type { IncomingMessage, ServerResponse } from \"node:http\";\nimport { extname } from \"node:path\";\nimport type { Context } from \"@deepseek-ai/cordis\";\nimport type { Agent } from \"@deepseek-ai/dsh-agent\";\nimport { FsError, type FileSystem, type FsInfo, type FsTarget, type FsVersion } from \"@deepseek-ai/dsh-fs\";\nimport type {} from \"@deepseek-ai/dsh-host-webserver\";\nimport type { SandboxPolicyService } from \"@deepseek-ai/dsh-sandbox-policy\";\nimport { SessionId } from \"@deepseek-ai/dsh-session\";\nimport type {} from \"@deepseek-ai/dsh-typert-registry\";\nimport { isTrustedWorkspaceRequest } from \"./workspace-request-trust.js\";\n\nconst STORY_DIRECTORIES = [\"\u6B63\u6587\", \"\u5927\u7EB2\", \"\u8BBE\u5B9A\", \"\u8FFD\u8E2A\", \"\u5BF9\u6807\", \"\u53C2\u8003\u8D44\u6599\"] as const;\nconst DRAMA_DIRECTORIES = [\"\u8F93\u5165\", \"\u9879\u76EE\u5F00\u53D1\", \"\u8BBE\u5B9A\u96C6\", \"\u5267\u96C6\", \"\u4EA4\u4ED8\", \"\u521B\u4F5C\u8005\u51B3\u7B56\", \"\u5BA1\u67E5\"] as const;\nconst CREATIVE_DIRECTORIES = [...STORY_DIRECTORIES, ...DRAMA_DIRECTORIES] as const;\nconst ROOT_FILES = new Set([\"short-drama.json\"]);\nconst EDITABLE_EXTENSIONS = new Set([\".md\", \".txt\", \".json\", \".jsonl\"]);\nconst FILE_LIMIT = 1_000;\n\ninterface WorkspaceRouteOptions {\n readonly maxBytes: number;\n readonly trustedHosts?: readonly string[];\n}\n\ninterface WorkspaceFile {\n readonly path: string;\n readonly bytes: number;\n readonly version: string;\n}\n\ninterface WorkspaceRealm {\n readonly agent: Agent;\n readonly fs: FileSystem;\n readonly sandboxPolicy: SandboxPolicyService;\n readonly cwd: string;\n readonly root: FsTarget;\n}\n\ninterface ReadFileResult {\n readonly content: string;\n readonly bytes: number;\n readonly version: FsVersion;\n}\n\nclass WorkspaceHttpError extends Error {\n constructor(readonly status: number, message: string) { super(message); }\n}\n\nfunction send(response: ServerResponse, status: number, value: unknown): void {\n const body = `${JSON.stringify(value)}\\n`;\n response.writeHead(status, {\n \"content-type\": \"application/json; charset=utf-8\",\n \"content-length\": Buffer.byteLength(body),\n \"cache-control\": \"no-store\",\n \"x-content-type-options\": \"nosniff\"\n });\n response.end(body);\n}\n\nasync function jsonBody(request: IncomingMessage, maxBytes: number): Promise<Record<string, unknown>> {\n const chunks: Buffer[] = [];\n let size = 0;\n for await (const chunk of request as AsyncIterable<Uint8Array>) {\n const value = Buffer.from(chunk);\n size += value.byteLength;\n if (size > maxBytes) throw new WorkspaceHttpError(413, \"\u8BF7\u6C42\u5185\u5BB9\u8FC7\u5927\u3002\");\n chunks.push(value);\n }\n try {\n const value = JSON.parse(Buffer.concat(chunks).toString(\"utf8\")) as unknown;\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) throw new Error();\n return value as Record<string, unknown>;\n } catch {\n throw new WorkspaceHttpError(400, \"\u8BF7\u6C42\u5FC5\u987B\u662F JSON \u5BF9\u8C61\u3002\");\n }\n}\n\nfunction assertCreativePath(path: string): void {\n if (!EDITABLE_EXTENSIONS.has(extname(path).toLocaleLowerCase())) {\n throw new WorkspaceHttpError(415, \"\u5DE5\u4F5C\u53F0\u53EA\u7F16\u8F91 Markdown\u3001\u6587\u672C\u3001JSON \u548C JSONL \u6587\u4EF6\u3002\");\n }\n if (path.startsWith(\"/\") || path.includes(\"\\\\\") || path.split(\"/\").some((segment) => segment === \"\" || segment === \".\" || segment === \"..\")) {\n throw new WorkspaceHttpError(403, \"\u6587\u4EF6\u8DEF\u5F84\u4E0D\u5728\u521B\u4F5C\u5DE5\u4F5C\u53F0\u4E2D\u3002\");\n }\n const root = path.split(\"/\", 1)[0];\n if (!CREATIVE_DIRECTORIES.some((directory) => directory === root) && !ROOT_FILES.has(path)) {\n throw new WorkspaceHttpError(403, \"\u6587\u4EF6\u8DEF\u5F84\u4E0D\u5728\u521B\u4F5C\u5DE5\u4F5C\u53F0\u4E2D\u3002\");\n }\n}\n\nasync function workspaceRealm(context: Context, url: URL): Promise<WorkspaceRealm> {\n const rawId = url.searchParams.get(\"sessionId\");\n if (rawId === null || rawId === \"\") throw new WorkspaceHttpError(400, \"\u7F3A\u5C11 DSH sessionId\u3002\");\n const lookup = context.typert.lookups.get(\"agent\");\n if (lookup === undefined) throw new WorkspaceHttpError(503, \"DSH Agent lookup \u5F53\u524D\u4E0D\u53EF\u7528\u3002\");\n let agent: Agent | undefined;\n try {\n agent = await lookup.resolve(SessionId(rawId)) as Agent | undefined;\n } catch {\n throw new WorkspaceHttpError(404, \"DSH \u4F1A\u8BDD\u4E0D\u53EF\u7528\u3002\");\n }\n if (agent === undefined) throw new WorkspaceHttpError(404, \"DSH \u4F1A\u8BDD\u4E0D\u53EF\u7528\u3002\");\n if (agent.session.header.parentSession !== undefined || agent.session.header.origin === \"subagent\") {\n throw new WorkspaceHttpError(403, \"\u5B50 Agent \u4F1A\u8BDD\u4E0D\u5F00\u653E\u521B\u4F5C\u7F16\u8F91\u5668\u3002\");\n }\n const cwd = agent.session.header.cwd;\n if (cwd === undefined) throw new WorkspaceHttpError(409, \"\u5F53\u524D DSH \u4F1A\u8BDD\u6CA1\u6709\u5DE5\u4F5C\u76EE\u5F55\u3002\");\n const fs = agent.ctx.get(\"fs\");\n const sandboxPolicy = agent.ctx.get(\"sandboxPolicy\");\n if (fs === undefined || sandboxPolicy === undefined) throw new WorkspaceHttpError(503, \"DSH \u6587\u4EF6\u7CFB\u7EDF\u5F53\u524D\u4E0D\u53EF\u7528\u3002\");\n return { agent, fs, sandboxPolicy, cwd, root: await fs.resolve(cwd) };\n}\n\nasync function creativeTarget(realm: WorkspaceRealm, path: string): Promise<FsTarget> {\n assertCreativePath(path);\n const target = await realm.fs.resolve(path, { cwd: realm.cwd });\n if (!realm.fs.contains(realm.root, target)) throw new WorkspaceHttpError(403, \"\u6587\u4EF6\u8DEF\u5F84\u79BB\u5F00\u4E86 DSH \u5DE5\u4F5C\u76EE\u5F55\u3002\");\n return target;\n}\n\nfunction requireRegularFile(info: FsInfo | undefined): FsInfo {\n if (info === undefined) throw new WorkspaceHttpError(404, \"\u6587\u4EF6\u4E0D\u5B58\u5728\u3002\");\n if (info.type !== \"file\") throw new WorkspaceHttpError(415, \"\u76EE\u6807\u4E0D\u662F\u53EF\u7F16\u8F91\u7684\u666E\u901A\u6587\u4EF6\u3002\");\n return info;\n}\n\n/** Read bytes and a matching opaque version, retrying if a writer wins the read window. */\nasync function readVersionedFile(fs: FileSystem, target: FsTarget, maxBytes: number): Promise<ReadFileResult> {\n for (let attempt = 0; attempt < 3; attempt += 1) {\n const before = requireRegularFile(await fs.stat(target));\n if (before.size !== undefined && before.size > maxBytes) throw new WorkspaceHttpError(413, \"\u6587\u4EF6\u8D85\u8FC7\u5DE5\u4F5C\u53F0\u5927\u5C0F\u9650\u5236\u3002\");\n const bytes = await fs.readBytes(target, undefined, maxBytes);\n const after = requireRegularFile(await fs.stat(target));\n if (before.version !== after.version) continue;\n let content: string;\n try {\n content = new TextDecoder(\"utf-8\", { fatal: true }).decode(bytes);\n } catch {\n throw new WorkspaceHttpError(415, \"\u6587\u4EF6\u4E0D\u662F\u6709\u6548\u7684 UTF-8 \u6587\u672C\u3002\");\n }\n return { content, bytes: bytes.byteLength, version: after.version };\n }\n throw new WorkspaceHttpError(409, \"\u6587\u4EF6\u6B63\u5728\u88AB\u4FEE\u6539\uFF0C\u8BF7\u91CD\u8BD5\u3002\");\n}\n\nasync function listFiles(realm: WorkspaceRealm): Promise<WorkspaceFile[]> {\n const files: WorkspaceFile[] = [];\n const walk = async (path: string, directory: FsTarget): Promise<void> => {\n for (const entry of await realm.fs.listDir(directory)) {\n if (entry.name.startsWith(\".\") || !realm.fs.contains(realm.root, entry.target)) continue;\n const childPath = `${path}/${entry.name}`;\n if (entry.type === \"directory\") await walk(childPath, entry.target);\n else if (entry.type === \"file\" && EDITABLE_EXTENSIONS.has(extname(entry.name).toLocaleLowerCase())) {\n const info = entry.version === undefined || entry.size === undefined ? await realm.fs.stat(entry.target) : undefined;\n const version = entry.version ?? info?.version;\n if (version !== undefined) files.push({ path: childPath, bytes: entry.size ?? info?.size ?? 0, version });\n }\n if (files.length >= FILE_LIMIT) return;\n }\n };\n for (const directory of CREATIVE_DIRECTORIES) {\n const target = await realm.fs.resolve(directory, { cwd: realm.cwd });\n if (!realm.fs.contains(realm.root, target)) continue;\n const info = await realm.fs.stat(target);\n if (info?.type === \"directory\") await walk(directory, target);\n if (files.length >= FILE_LIMIT) break;\n }\n for (const path of ROOT_FILES) {\n const target = await creativeTarget(realm, path);\n const info = await realm.fs.stat(target);\n if (info?.type === \"file\") files.push({ path, bytes: info.size ?? 0, version: info.version });\n }\n return files.sort((left, right) => left.path.localeCompare(right.path, \"zh-Hans-CN\"));\n}\n\nasync function metadata(realm: WorkspaceRealm, files: readonly WorkspaceFile[], path: string, maxBytes: number): Promise<{ readonly value: unknown; readonly error?: string }> {\n if (!files.some((file) => file.path === path)) return { value: null };\n try {\n const target = await creativeTarget(realm, path);\n return { value: JSON.parse((await readVersionedFile(realm.fs, target, maxBytes)).content) as unknown };\n } catch (error) {\n return { value: null, error: error instanceof SyntaxError ? `${path} \u4E0D\u662F\u6709\u6548\u7684 JSON\u3002` : `${path} \u6682\u65F6\u65E0\u6CD5\u8BFB\u53D6\u3002` };\n }\n}\n\nfunction mapFsError(error: unknown): WorkspaceHttpError | undefined {\n if (!(error instanceof FsError)) return undefined;\n switch (error.code) {\n case \"FS_NOT_FOUND\": return new WorkspaceHttpError(404, \"\u6587\u4EF6\u4E0D\u5B58\u5728\u3002\");\n case \"FS_TOO_LARGE\": return new WorkspaceHttpError(413, \"\u6587\u4EF6\u8D85\u8FC7\u5DE5\u4F5C\u53F0\u5927\u5C0F\u9650\u5236\u3002\");\n case \"FS_NOT_TEXT\":\n case \"FS_NOT_REGULAR_FILE\": return new WorkspaceHttpError(415, \"\u76EE\u6807\u4E0D\u662F\u53EF\u7F16\u8F91\u7684\u6587\u672C\u6587\u4EF6\u3002\");\n case \"FS_PERMISSION_DENIED\":\n case \"FS_SANDBOX_DENIED\": return new WorkspaceHttpError(403, \"\u5F53\u524D DSH \u6743\u9650\u4E0D\u5141\u8BB8\u4FEE\u6539\u8BE5\u6587\u4EF6\u3002\");\n case \"FS_STALE_VERSION\":\n case \"FS_NOT_OBSERVED\": return new WorkspaceHttpError(412, \"\u6587\u4EF6\u5DF2\u5728\u78C1\u76D8\u4E0A\u66F4\u65B0\u3002\u8BF7\u5904\u7406\u51B2\u7A81\u540E\u518D\u4FDD\u5B58\u3002\");\n case \"FS_ABORTED\": return new WorkspaceHttpError(409, \"\u6587\u4EF6\u64CD\u4F5C\u5DF2\u53D6\u6D88\u3002\");\n default: return new WorkspaceHttpError(500, \"DSH \u6587\u4EF6\u7CFB\u7EDF\u64CD\u4F5C\u5931\u8D25\u3002\");\n }\n}\n\nasync function handle(context: Context, request: IncomingMessage, response: ServerResponse, options: WorkspaceRouteOptions): Promise<void> {\n try {\n if (!isTrustedWorkspaceRequest(request, options.trustedHosts ?? [])) throw new WorkspaceHttpError(403, \"\u8BF7\u6C42\u6765\u6E90\u4E0D\u53D7\u4FE1\u4EFB\u3002\");\n const url = new URL(request.url ?? \"/\", \"http://127.0.0.1\");\n if (url.pathname === \"/oh-story/workspace\" && request.method === \"GET\") {\n const realm = await workspaceRealm(context, url);\n const files = await listFiles(realm);\n const tracking = await metadata(realm, files, \"\u8FFD\u8E2A/_tracking-state.json\", options.maxBytes);\n const shortDrama = await metadata(realm, files, \"short-drama.json\", options.maxBytes);\n const metadataErrors = [tracking.error, shortDrama.error].filter((value): value is string => value !== undefined);\n send(response, 200, { cwd: realm.cwd, files, tracking: tracking.value, shortDrama: shortDrama.value, metadataErrors, mode: \"dsh-session\" });\n return;\n }\n if (url.pathname === \"/oh-story/file\" && request.method === \"GET\") {\n const realm = await workspaceRealm(context, url);\n const path = url.searchParams.get(\"path\");\n if (path === null) throw new WorkspaceHttpError(400, \"\u7F3A\u5C11\u6587\u4EF6\u8DEF\u5F84\u3002\");\n const file = await readVersionedFile(realm.fs, await creativeTarget(realm, path), options.maxBytes);\n send(response, 200, { path, ...file });\n return;\n }\n if (url.pathname === \"/oh-story/file\" && request.method === \"PUT\") {\n const realm = await workspaceRealm(context, url);\n const path = url.searchParams.get(\"path\");\n if (path === null) throw new WorkspaceHttpError(400, \"\u7F3A\u5C11\u6587\u4EF6\u8DEF\u5F84\u3002\");\n const input = await jsonBody(request, options.maxBytes * 6 + 1_024);\n if (typeof input.content !== \"string\") throw new WorkspaceHttpError(400, \"content \u5FC5\u987B\u662F\u5B57\u7B26\u4E32\u3002\");\n if (typeof input.baseVersion !== \"string\" || input.baseVersion === \"\") throw new WorkspaceHttpError(400, \"baseVersion \u5FC5\u987B\u662F\u6709\u6548\u7248\u672C\u3002\");\n if (Buffer.byteLength(input.content) > options.maxBytes) throw new WorkspaceHttpError(413, \"\u6587\u4EF6\u8D85\u8FC7\u5DE5\u4F5C\u53F0\u5927\u5C0F\u9650\u5236\u3002\");\n const outcome = await realm.fs.writeText(\n await creativeTarget(realm, path),\n input.content,\n { kind: \"replaceIfVersion\", version: input.baseVersion as FsVersion },\n undefined,\n realm.sandboxPolicy.resolve({ session: realm.agent.session })\n );\n send(response, 200, { path, content: outcome.after, bytes: Buffer.byteLength(outcome.after), version: outcome.version });\n return;\n }\n send(response, 404, { error: \"Oh Story route not found.\" });\n } catch (error) {\n const mapped = error instanceof WorkspaceHttpError ? error : mapFsError(error);\n if (mapped === undefined) context.logger(\"oh-story\").error(\"workspace route failed\", error);\n send(response, mapped?.status ?? 500, { error: mapped?.message ?? \"Oh Story workspace operation failed.\" });\n }\n}\n\n/** Mount the narrow editor API on DSH's official web-server extension seam. */\nexport function registerWorkspaceRoute(context: Context, options: WorkspaceRouteOptions): void {\n context.effect(() => context.webServer.register({\n kind: \"prefix\",\n path: \"/oh-story\",\n handler: (request, response) => handle(context, request, response, options)\n }), \"oh-story: DSH-session workspace API\");\n}\n", "import type { IncomingHttpHeaders } from \"node:http\";\n\ninterface WorkspaceTrustRequest {\n readonly headers: IncomingHttpHeaders | Headers;\n}\n\nfunction header(headers: IncomingHttpHeaders | Headers, name: string): string | undefined {\n if (headers instanceof Headers) return headers.get(name) ?? undefined;\n const value = headers[name];\n return typeof value === \"string\" ? value : undefined;\n}\n\nfunction parseAuthority(authority: string): URL | undefined {\n try { return new URL(`http://${authority}`); }\n catch { return undefined; }\n}\n\nfunction canonicalAuthority(entry: string, url: URL): string {\n const port = url.port !== \"\" ? url.port : new URL(`https://${entry}`).port;\n return port === \"\" ? url.hostname : `${url.hostname}:${port}`;\n}\n\nfunction isLoopbackHostname(hostname: string): boolean {\n if (hostname === \"localhost\" || hostname === \"[::1]\") return true;\n const parts = hostname.split(\".\");\n return parts.length === 4\n && parts[0] === \"127\"\n && parts.every((part) => /^\\d{1,3}$/u.test(part) && Number(part) <= 255);\n}\n\nfunction isTrustedAuthority(host: URL, trustedHosts: readonly string[]): boolean {\n return trustedHosts.some((entry) => {\n const candidate = parseAuthority(entry);\n if (candidate === undefined) return false;\n return canonicalAuthority(entry, candidate) === candidate.hostname\n ? candidate.hostname === host.hostname\n : candidate.host === host.host;\n });\n}\n\n/** Reject malformed declarations at plugin load instead of silently widening access. */\nexport function assertTrustedWorkspaceAuthority(entry: string): void {\n const url = parseAuthority(entry);\n if (url !== undefined && canonicalAuthority(entry, url) === entry.toLocaleLowerCase()) return;\n throw new Error(`oh-story: trustedHosts entry ${JSON.stringify(entry)} is not a bare host[:port] authority`);\n}\n\n/**\n * Same browser trust boundary as DSH's native API: every request must address a\n * loopback or explicitly trusted Host, and browser markers must be same-origin.\n */\nexport function isTrustedWorkspaceRequest(\n request: WorkspaceTrustRequest,\n trustedHosts: readonly string[]\n): boolean {\n const authority = header(request.headers, \"host\");\n if (authority === undefined) return false;\n const host = parseAuthority(authority);\n if (host === undefined) return false;\n if (!isLoopbackHostname(host.hostname) && !isTrustedAuthority(host, trustedHosts)) return false;\n if (header(request.headers, \"sec-fetch-site\") === \"cross-site\") return false;\n const origin = header(request.headers, \"origin\");\n if (origin === undefined) return true;\n try { return new URL(origin).host === host.host; }\n catch { return false; }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["name", "name", "defineTool", "readdir", "readFile", "isAbsolute", "join", "relative", "resolve", "readdir", "join", "resolve", "relative", "isAbsolute", "readFile", "readFile", "basename", "dirname", "join", "resolve", "fileURLToPath", "name", "defineTool", "name", "name", "target"]
|
|
7
7
|
}
|