@oh-story/dsh 0.1.17 → 0.1.18

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/lib/index.js CHANGED
@@ -489,6 +489,8 @@ function createVideoRecapSkillProvider(skillRoot = defaultVideoRecapSkillRoot())
489
489
  import { execFile } from "node:child_process";
490
490
  import { promisify } from "node:util";
491
491
  var execFileAsync = promisify(execFile);
492
+ var DRAMA_PYTHON = [3, 9];
493
+ var VIDEO_PYTHON = [3, 10];
492
494
  async function commandOutput(command, args) {
493
495
  try {
494
496
  const { stdout, stderr } = await execFileAsync(command, [...args], { encoding: "utf8", timeout: 5e3, maxBuffer: 4 * 1024 * 1024 });
@@ -497,21 +499,22 @@ async function commandOutput(command, args) {
497
499
  return void 0;
498
500
  }
499
501
  }
500
- function pythonVersion(value) {
502
+ function pythonVersion(value, floor) {
503
+ const minimum = `${String(floor[0])}.${String(floor[1])}`;
501
504
  const match = /Python\s+(\d+)\.(\d+)(?:\.(\d+))?/u.exec(value ?? "");
502
- if (match === null) return { ok: false };
505
+ if (match === null) return { ok: false, minimum };
503
506
  const major = Number(match[1]);
504
507
  const minor = Number(match[2]);
505
- return { ok: major > 3 || major === 3 && minor >= 10, version: match[0].replace(/^Python\s+/u, "") };
508
+ return { ok: major > floor[0] || major === floor[0] && minor >= floor[1], version: match[0].replace(/^Python\s+/u, ""), minimum };
506
509
  }
507
- async function hostPython(probe = commandOutput) {
510
+ async function hostPython(floor, probe = commandOutput) {
508
511
  let fallback;
509
512
  for (const command of ["python3", "python"]) {
510
- const parsed = pythonVersion(await probe(command, ["--version"]));
513
+ const parsed = pythonVersion(await probe(command, ["--version"]), floor);
511
514
  if (parsed.ok) return { command, probe: parsed };
512
515
  if (parsed.version !== void 0) fallback ??= { command, probe: parsed };
513
516
  }
514
- return fallback ?? { command: "python3", probe: { ok: false } };
517
+ return fallback ?? { command: "python3", probe: { ok: false, minimum: pythonVersion(void 0, floor).minimum } };
515
518
  }
516
519
 
517
520
  // src/native-hooks.ts
@@ -1482,7 +1485,7 @@ async function dramaPreflight() {
1482
1485
  if (dramaPreflightCache !== void 0 && dramaPreflightCache.expires > Date.now()) return dramaPreflightCache.value;
1483
1486
  dramaPreflightInFlight ??= (async () => {
1484
1487
  try {
1485
- const python = await hostPython();
1488
+ const python = await hostPython(DRAMA_PYTHON);
1486
1489
  const adapterConfig = await ensureDramaAdapterConfig(defaultDramaSkillRoot(), { python: python.command });
1487
1490
  const value = { python: python.probe, adapterConfig, adapters: dramaAdapterStatuses() };
1488
1491
  dramaPreflightCache = { expires: Date.now() + 3e4, value };
@@ -1495,7 +1498,7 @@ async function dramaPreflight() {
1495
1498
  }
1496
1499
  async function videoPreflight() {
1497
1500
  if (videoPreflightCache !== void 0 && videoPreflightCache.expires > Date.now()) return videoPreflightCache.value;
1498
- const python = (await hostPython()).probe;
1501
+ const python = (await hostPython(VIDEO_PYTHON)).probe;
1499
1502
  const [ffmpegOutput, ffmpegFilters, ffprobeOutput] = await Promise.all([
1500
1503
  commandOutput("ffmpeg", ["-version"]),
1501
1504
  commandOutput("ffmpeg", ["-hide_banner", "-filters"]),
@@ -1815,9 +1818,10 @@ async function previewDigest(realm, projectRoot) {
1815
1818
  await visit(app, "");
1816
1819
  return { ready, version: createHash2("sha256").update(entries.sort().join("\n")).digest("hex").slice(0, 16) };
1817
1820
  }
1818
- function headingTitle(content, fallback) {
1821
+ function gameProjectTitle(content, fallback) {
1819
1822
  const heading = content?.split(/\r?\n/u).find((line) => /^#\s+/u.test(line));
1820
- return heading?.replace(/^#\s+/u, "").replace(/^PRODUCT_BRIEF\s*[·・:]?\s*/iu, "").trim() || fallback;
1823
+ const title = heading?.replace(/^#\s+/u, "").replace(/^(?:PRODUCT[_ ]BRIEF|产品简报)/iu, "").replace(/^[\s·・::|—–-]+/u, "").trim().replace(/^《([^《》]+)》$/u, "$1").trim();
1824
+ return title || fallback;
1821
1825
  }
1822
1826
  async function workspaceGameProjects(realm, files, sessionId, maxBytes) {
1823
1827
  const roots = [...new Set(files.flatMap((file) => {
@@ -1843,7 +1847,7 @@ async function workspaceGameProjects(realm, files, sessionId, maxBytes) {
1843
1847
  return {
1844
1848
  id: `workspace:${id}`,
1845
1849
  root,
1846
- title: headingTitle(brief, id),
1850
+ title: gameProjectTitle(brief, id),
1847
1851
  source: "workspace",
1848
1852
  previewReady: preview.ready,
1849
1853
  previewUrl: preview.ready ? `/oh-story/game-preview/workspace/${token(sessionId)}/${token(root)}/index.html` : void 0,
@@ -2142,7 +2146,7 @@ async function apply(context, config = {}) {
2142
2146
  registerOhStoryProductionTool(context);
2143
2147
  await registerOhStoryRoleTool(context);
2144
2148
  registerWorkspaceRoute(context, { maxBytes: config.editorMaxBytes ?? 2097152, trustedHosts });
2145
- await ensureDramaAdapterConfig(defaultDramaSkillRoot(), { python: (await hostPython()).command });
2149
+ await ensureDramaAdapterConfig(defaultDramaSkillRoot(), { python: (await hostPython(DRAMA_PYTHON)).command });
2146
2150
  }
2147
2151
  var index_default = { name, inject, Config, apply };
2148
2152
  export {