@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/README.md +6 -6
- package/lib/client.js +147 -96
- package/lib/client.js.map +3 -3
- package/lib/index.js +16 -12
- package/lib/index.js.map +2 -2
- package/lib/types/client/game-preview-state.d.ts +34 -0
- package/lib/types/client/game-preview-state.d.ts.map +1 -0
- package/lib/types/client/index.d.ts.map +1 -1
- package/lib/types/client/video-studio.d.ts +24 -0
- package/lib/types/client/video-studio.d.ts.map +1 -1
- package/lib/types/host-python.d.ts +10 -3
- package/lib/types/host-python.d.ts.map +1 -1
- package/lib/types/workspace-route.d.ts +6 -0
- package/lib/types/workspace-route.d.ts.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
- 13 个 Oh Story 0.9.0 小说 Skills 与 7 个专业 Roles;
|
|
10
10
|
- 11 个 Drama Skills 0.9.0 短剧流程,每集按请求维护最多五份创作 Markdown(剧本、视觉设定、分镜、图片提示词、视频提示词),成片装配另写《剪辑单.md》;
|
|
11
|
-
- 7 个 NovelToGame 0.6.0 Skills、`game-adaptations/<project>` 产物协议与《金瓶梅 · 风月总账》ADV
|
|
11
|
+
- 7 个 NovelToGame 0.6.0 Skills、`game-adaptations/<project>` 产物协议与《金瓶梅 · 风月总账》ADV 可玩构建(18+,欢迎卡「先玩内置示例」即可试玩);
|
|
12
12
|
- 7 个 video-recap-skills 0.6.2 Skills(3 个用户入口)、`video-recaps/<project>` 项目约定与轻量视频预览工作台;
|
|
13
13
|
- 小说协议 hooks 与安全的 Session workspace 文件路由;
|
|
14
14
|
- 小说/短剧的文件树、编辑器、Chat 三栏工作台,以及游戏/视频的“左侧工作台 + 右侧 Chat”制作面板;
|
|
@@ -23,14 +23,14 @@
|
|
|
23
23
|
安装命令会临时提供 pnpm;只安装 Node.js 的机器也能执行。DSH 的 `plugin add` 内部需要 pnpm,单独运行 `npx @deepseek-ai/dsh ... plugin add` 不会自动补上它。
|
|
24
24
|
|
|
25
25
|
```bash
|
|
26
|
-
npx -y --package pnpm@11.7.0 --package @deepseek-ai/dsh@0.2.1-rc.2 dsh plugin --profile web add @oh-story/dsh@0.1.
|
|
26
|
+
npx -y --package pnpm@11.7.0 --package @deepseek-ai/dsh@0.2.1-rc.2 dsh plugin --profile web add @oh-story/dsh@0.1.18 &&
|
|
27
27
|
npx -y @deepseek-ai/dsh@0.2.1-rc.2 web
|
|
28
28
|
```
|
|
29
29
|
|
|
30
30
|
也可以直接安装 GitHub Release 中的预构建包:
|
|
31
31
|
|
|
32
32
|
```bash
|
|
33
|
-
npx -y --package pnpm@11.7.0 --package @deepseek-ai/dsh@0.2.1-rc.2 dsh plugin --profile web add https://github.com/zenstory-ai/oh-story-dsh/releases/download/v0.1.
|
|
33
|
+
npx -y --package pnpm@11.7.0 --package @deepseek-ai/dsh@0.2.1-rc.2 dsh plugin --profile web add https://github.com/zenstory-ai/oh-story-dsh/releases/download/v0.1.18/oh-story-dsh-0.1.18.tgz &&
|
|
34
34
|
npx -y @deepseek-ai/dsh@0.2.1-rc.2 web
|
|
35
35
|
```
|
|
36
36
|
|
|
@@ -66,9 +66,9 @@ npx -y @deepseek-ai/dsh@0.2.1-rc.2 web
|
|
|
66
66
|
给 /path/to/video.mp4 做一个 3 分钟中文解说成片,保留关键原声,字幕烧进画面。
|
|
67
67
|
```
|
|
68
68
|
|
|
69
|
-
宿主机需要 Python 3.10+、`PATH` 上的 ffmpeg/ffprobe,以及 `MIMO_API_KEY`;Fish Audio TTS 另需 `FISH_API_KEY`,自建 IndexTTS 需 `INDEX_TTS_ENDPOINT` 与 `INDEX_TTS_VOICE`(`TTS_PROVIDER=index-tts`)。Debian/Ubuntu 用 `sudo apt install ffmpeg`;有 libass `subtitles` 滤镜时烧录字幕,没有时交付外部 SRT(也可另装带 libass
|
|
69
|
+
宿主机需要 Python 3.10+、`PATH` 上的 ffmpeg/ffprobe,以及 `MIMO_API_KEY`;Fish Audio TTS 另需 `FISH_API_KEY`,自建 IndexTTS 需 `INDEX_TTS_ENDPOINT` 与 `INDEX_TTS_VOICE`(`TTS_PROVIDER=index-tts`)。Debian/Ubuntu 用 `sudo apt install ffmpeg`;有 libass `subtitles` 滤镜时烧录字幕,没有时交付外部 SRT(也可另装带 libass 的构建)。Key 与 `PATH` 在启动 DSH 的终端里设置,重启后生效。视频空状态和「产物」页的「运行环境」检查只报告 DSH Host 进程是否就绪,不返回 Key 内容,密钥也不会写入项目;Agent 实际的执行世界以 `video-recap --doctor` 为准。
|
|
70
70
|
|
|
71
|
-
短剧生产的图片、视频、语音与音乐不由 DeepSeek 生成,而是由 `short-drama-produce` 调用 GPT Image 2(`OPENAI_API_KEY`)、Seedance(`ARK_API_KEY` + `SEEDANCE_MODEL`)、MiniMax H3(`MINIMAX_API_KEY` + `MINIMAX_VIDEO_MODEL` + `MINIMAX_VIDEO_RESOLUTIONS` + `MINIMAX_VIDEO_MIN_DURATION`/`MINIMAX_VIDEO_MAX_DURATION`)、MiniMax Speech(`MINIMAX_API_KEY`)或 MiniMax Music(`MINIMAX_API_KEY
|
|
71
|
+
短剧生产的图片、视频、语音与音乐不由 DeepSeek 生成,而是由 `short-drama-produce` 调用 GPT Image 2(`OPENAI_API_KEY`)、Seedance(`ARK_API_KEY` + `SEEDANCE_MODEL`)、MiniMax H3(`MINIMAX_API_KEY` + `MINIMAX_VIDEO_MODEL` + `MINIMAX_VIDEO_RESOLUTIONS` + `MINIMAX_VIDEO_MIN_DURATION`/`MINIMAX_VIDEO_MAX_DURATION`)、MiniMax Speech(`MINIMAX_API_KEY`)或 MiniMax Music(`MINIMAX_API_KEY`)生成;生产与检查脚本需要 Python 3.9+;Key 在启动 DSH 前写入环境变量,「生产」视图会显示 Python 与每个供应商是否就绪,插件只向界面返回配置是否存在,不返回 Key 的值。内置 adapter 会自动登记到一份不含凭据的配置文件,自定义时用 `OH_STORY_DRAMA_ADAPTER_CONFIG` 指向自己的文件。
|
|
72
72
|
|
|
73
73
|
声音参考需要额外显式配置:自动生成的通用 profile 不声明 `reference_audio`,因为环境变量里的具体模型未必支持声音输入;只有确认所选模型支持后,才在项目外的自定义 adapter 配置里为该 profile 声明 `reference_roles`(包含 `reference_audio`),并用 `OH_STORY_DRAMA_ADAPTER_CONFIG` 指向它。未声明时会在付费提交前拒绝,不会静默丢掉声音。
|
|
74
74
|
|
|
@@ -90,7 +90,7 @@ Oh Story 0.9.0 按写书步骤重整参考资料,书稿、设定、追踪和
|
|
|
90
90
|
插件装进哪个 profile,那个 profile 的每个 Session 都能发现创作 Skills,具体指令在使用时读取;工作台只在有创作项目时显示。想让原版 `web` 保持干净、只在创作时打开工作台,就装进独立 profile:
|
|
91
91
|
|
|
92
92
|
```bash
|
|
93
|
-
npx -y --package pnpm@11.7.0 --package @deepseek-ai/dsh@0.2.1-rc.2 dsh plugin --profile story add @oh-story/dsh@0.1.
|
|
93
|
+
npx -y --package pnpm@11.7.0 --package @deepseek-ai/dsh@0.2.1-rc.2 dsh plugin --profile story add @oh-story/dsh@0.1.18
|
|
94
94
|
```
|
|
95
95
|
|
|
96
96
|
新 profile 默认没有界面。编辑 `~/.dsh/profiles/story/package.json`,把 `dsh.profile.bundles` 改成 `["@deepseek-ai/dsh-base", "@deepseek-ai/dsh-web-app", "@oh-story/dsh"]`。
|
package/lib/client.js
CHANGED
|
@@ -1312,7 +1312,7 @@ function ProductionStatus({ sessionId, diagnostics, onNavigate }) {
|
|
|
1312
1312
|
}, children: [
|
|
1313
1313
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("i", { "aria-hidden": "true" }),
|
|
1314
1314
|
"\u751F\u6210\u73AF\u5883",
|
|
1315
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("em", { children: typeof preflight != "object" ? "\u68C0\u67E5\u4E2D\u2026" : preflight.python.ok ? `${String(configured)}/${String(total)} \u4F9B\u5E94\u5546\u5DF2\u914D\u7F6E` :
|
|
1315
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("em", { children: typeof preflight != "object" ? "\u68C0\u67E5\u4E2D\u2026" : preflight.python.ok ? `${String(configured)}/${String(total)} \u4F9B\u5E94\u5546\u5DF2\u914D\u7F6E` : `\u9700\u8981 Python ${preflight.python.minimum}+` }),
|
|
1316
1316
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("b", { "aria-hidden": "true" })
|
|
1317
1317
|
] }),
|
|
1318
1318
|
diagnostics.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("button", { type: "button", className: "oh-story-status-pill", "data-tone": protocolErrors > 0 ? "error" : "warning", "aria-expanded": open === "diagnostics", "aria-controls": "oh-story-production-diagnostics", onClick: () => {
|
|
@@ -1329,7 +1329,7 @@ function ProductionStatus({ sessionId, diagnostics, onNavigate }) {
|
|
|
1329
1329
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("i", { "aria-hidden": "true" }),
|
|
1330
1330
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: "\u8FD0\u884C" }),
|
|
1331
1331
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("strong", { children: "Python" }),
|
|
1332
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("small", { children: preflight.python.ok ? preflight.python.version : `${preflight.python.version ?? "\u672A\u627E\u5230"} \xB7
|
|
1332
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("small", { children: preflight.python.ok ? preflight.python.version : `${preflight.python.version ?? "\u672A\u627E\u5230"} \xB7 \u77ED\u5267\u811A\u672C\u9700\u8981 ${preflight.python.minimum}+` })
|
|
1333
1333
|
] }),
|
|
1334
1334
|
preflight.adapters.map((adapter) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("li", { "data-ready": adapter.configured || void 0, children: [
|
|
1335
1335
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("i", { "aria-hidden": "true" }),
|
|
@@ -1958,8 +1958,63 @@ function VideoPreview({ project, sessionId, running }) {
|
|
|
1958
1958
|
) })
|
|
1959
1959
|
] });
|
|
1960
1960
|
}
|
|
1961
|
+
function VideoEnvironmentReport({ preflight }) {
|
|
1962
|
+
let fish = preflight.credentials.ttsProvider === "fish-audio" || preflight.credentials.ttsProvider === "auto" && !preflight.credentials.mimo;
|
|
1963
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
|
|
1964
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { "data-ready": preflight.python.ok || void 0, children: [
|
|
1965
|
+
"Python ",
|
|
1966
|
+
preflight.python.version ?? "\u672A\u627E\u5230",
|
|
1967
|
+
preflight.python.ok ? "" : ` \xB7 \u9700\u8981 ${preflight.python.minimum}+`
|
|
1968
|
+
] }),
|
|
1969
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { "data-ready": preflight.ffmpeg.ok && preflight.ffmpeg.subtitles || void 0, children: [
|
|
1970
|
+
"ffmpeg ",
|
|
1971
|
+
preflight.ffmpeg.ok ? preflight.ffmpeg.subtitles ? "\xB7 libass" : "\xB7 \u7F3A\u5B57\u5E55\u6EE4\u955C" : "\u672A\u627E\u5230"
|
|
1972
|
+
] }),
|
|
1973
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { "data-ready": preflight.ffprobe.ok || void 0, children: [
|
|
1974
|
+
"ffprobe ",
|
|
1975
|
+
preflight.ffprobe.ok ? "\u53EF\u7528" : "\u672A\u627E\u5230"
|
|
1976
|
+
] }),
|
|
1977
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { "data-ready": preflight.credentials.mimo || void 0, children: [
|
|
1978
|
+
"MiMo Key ",
|
|
1979
|
+
preflight.credentials.mimo ? "\u5DF2\u914D\u7F6E" : "\u672A\u914D\u7F6E"
|
|
1980
|
+
] }),
|
|
1981
|
+
fish && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { "data-ready": preflight.credentials.fish || void 0, children: [
|
|
1982
|
+
"Fish Key ",
|
|
1983
|
+
preflight.credentials.fish ? "\u5DF2\u914D\u7F6E" : "\u672A\u914D\u7F6E"
|
|
1984
|
+
] }),
|
|
1985
|
+
preflight.credentials.ttsProvider === "index-tts" && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { "data-ready": preflight.credentials.indexTts || void 0, children: [
|
|
1986
|
+
"IndexTTS ",
|
|
1987
|
+
preflight.credentials.indexTts ? "\u5DF2\u914D\u7F6E" : "\u7F3A INDEX_TTS_ENDPOINT / INDEX_TTS_VOICE"
|
|
1988
|
+
] }),
|
|
1989
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("em", { children: [
|
|
1990
|
+
"Key \u4E0E PATH \u5728\u542F\u52A8 DSH \u7684\u7EC8\u7AEF\u91CC\u8BBE\u7F6E\uFF0C\u91CD\u542F DSH \u540E\u751F\u6548\u3002\u8FD9\u91CC\u68C0\u67E5 DSH Host \u8FDB\u7A0B\uFF1BAgent \u6267\u884C\u4E16\u754C\u4EE5 ",
|
|
1991
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("code", { children: "video-recap --doctor" }),
|
|
1992
|
+
" \u4E3A\u51C6\u3002"
|
|
1993
|
+
] })
|
|
1994
|
+
] });
|
|
1995
|
+
}
|
|
1996
|
+
function VideoEnvironment({ sessionId }) {
|
|
1997
|
+
let [preflight, setPreflight] = (0, import_react3.useState)(), [attempt, setAttempt] = (0, import_react3.useState)(0);
|
|
1998
|
+
return (0, import_react3.useEffect)(() => {
|
|
1999
|
+
let controller = new AbortController();
|
|
2000
|
+
return fetch(endpoint("video-preflight", sessionId), { signal: controller.signal }).then(async (response) => {
|
|
2001
|
+
if (!response.ok) throw new Error(`HTTP ${String(response.status)}`);
|
|
2002
|
+
let summary = await response.json();
|
|
2003
|
+
controller.signal.aborted || setPreflight(summary);
|
|
2004
|
+
}).catch(() => {
|
|
2005
|
+
controller.signal.aborted || setPreflight("failed");
|
|
2006
|
+
}), () => {
|
|
2007
|
+
controller.abort();
|
|
2008
|
+
};
|
|
2009
|
+
}, [attempt, sessionId]), /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "oh-video-environment", role: "group", "aria-label": "\u89C6\u9891\u8FD0\u884C\u73AF\u5883", children: [
|
|
2010
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("strong", { children: "\u8FD0\u884C\u73AF\u5883" }),
|
|
2011
|
+
typeof preflight == "object" ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(VideoEnvironmentReport, { preflight }) : preflight === "failed" ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { type: "button", onClick: () => {
|
|
2012
|
+
setPreflight(void 0), setAttempt((value) => value + 1);
|
|
2013
|
+
}, children: "\u73AF\u5883\u68C0\u67E5\u5931\u8D25 \xB7 \u91CD\u8BD5" }) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("em", { children: "\u6B63\u5728\u68C0\u67E5 Python\u3001ffmpeg \u4E0E MiMo Key\u2026" })
|
|
2014
|
+
] });
|
|
2015
|
+
}
|
|
1961
2016
|
function VideoArtifacts({ project, sessionId }) {
|
|
1962
|
-
let [selected, setSelected] = (0, import_react3.useState)(preferredArtifact(project)?.path), [content, setContent] = (0, import_react3.useState)(), [error, setError] = (0, import_react3.useState)()
|
|
2017
|
+
let [selected, setSelected] = (0, import_react3.useState)(preferredArtifact(project)?.path), [content, setContent] = (0, import_react3.useState)(), [error, setError] = (0, import_react3.useState)();
|
|
1963
2018
|
(0, import_react3.useEffect)(() => {
|
|
1964
2019
|
setSelected(preferredArtifact(project)?.path);
|
|
1965
2020
|
}, [project.id]), (0, import_react3.useEffect)(() => {
|
|
@@ -1985,47 +2040,7 @@ function VideoArtifacts({ project, sessionId }) {
|
|
|
1985
2040
|
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("strong", { children: "\u9879\u76EE\u4EA7\u7269" }),
|
|
1986
2041
|
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: project.artifacts.length })
|
|
1987
2042
|
] }),
|
|
1988
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.
|
|
1989
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("strong", { children: "\u8FD0\u884C\u73AF\u5883" }),
|
|
1990
|
-
typeof preflight == "object" ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
|
|
1991
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { "data-ready": preflight.python.ok || void 0, children: [
|
|
1992
|
-
"Python ",
|
|
1993
|
-
preflight.python.version ?? "\u672A\u627E\u5230"
|
|
1994
|
-
] }),
|
|
1995
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { "data-ready": preflight.ffmpeg.ok && preflight.ffmpeg.subtitles || void 0, children: [
|
|
1996
|
-
"ffmpeg ",
|
|
1997
|
-
preflight.ffmpeg.subtitles ? "\xB7 libass" : "\xB7 \u7F3A\u5B57\u5E55\u6EE4\u955C"
|
|
1998
|
-
] }),
|
|
1999
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { "data-ready": preflight.ffprobe.ok || void 0, children: [
|
|
2000
|
-
"ffprobe ",
|
|
2001
|
-
preflight.ffprobe.ok ? "\u53EF\u7528" : "\u672A\u627E\u5230"
|
|
2002
|
-
] }),
|
|
2003
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { "data-ready": preflight.credentials.mimo || void 0, children: [
|
|
2004
|
-
"MiMo Key ",
|
|
2005
|
-
preflight.credentials.mimo ? "\u5DF2\u914D\u7F6E" : "\u672A\u914D\u7F6E"
|
|
2006
|
-
] }),
|
|
2007
|
-
(preflight.credentials.ttsProvider === "fish-audio" || preflight.credentials.ttsProvider === "auto" && !preflight.credentials.mimo) && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { "data-ready": preflight.credentials.fish || void 0, children: [
|
|
2008
|
-
"Fish Key ",
|
|
2009
|
-
preflight.credentials.fish ? "\u5DF2\u914D\u7F6E" : "\u672A\u914D\u7F6E"
|
|
2010
|
-
] }),
|
|
2011
|
-
preflight.credentials.ttsProvider === "index-tts" && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { "data-ready": preflight.credentials.indexTts || void 0, children: [
|
|
2012
|
-
"IndexTTS ",
|
|
2013
|
-
preflight.credentials.indexTts ? "\u5DF2\u914D\u7F6E" : "\u7F3A INDEX_TTS_ENDPOINT / INDEX_TTS_VOICE"
|
|
2014
|
-
] }),
|
|
2015
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("em", { children: [
|
|
2016
|
-
"DSH Host \u8FDB\u7A0B\u73AF\u5883\uFF1BAgent \u6267\u884C\u4E16\u754C\u4EE5 ",
|
|
2017
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("code", { children: "video-recap --doctor" }),
|
|
2018
|
-
" \u4E3A\u51C6\u3002"
|
|
2019
|
-
] })
|
|
2020
|
-
] }) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { type: "button", onClick: () => {
|
|
2021
|
-
fetch(endpoint("video-preflight", sessionId)).then(async (response) => {
|
|
2022
|
-
if (!response.ok) throw new Error(`HTTP ${String(response.status)}`);
|
|
2023
|
-
setPreflight(await response.json());
|
|
2024
|
-
}).catch(() => {
|
|
2025
|
-
setPreflight("failed");
|
|
2026
|
-
});
|
|
2027
|
-
}, children: preflight === "failed" ? "\u73AF\u5883\u68C0\u67E5\u5931\u8D25 \xB7 \u91CD\u8BD5" : "\u68C0\u67E5\u73AF\u5883" })
|
|
2028
|
-
] }),
|
|
2043
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(VideoEnvironment, { sessionId }),
|
|
2029
2044
|
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("nav", { children: [
|
|
2030
2045
|
project.artifacts.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { children: "\u6D41\u6C34\u7EBF\u542F\u52A8\u540E\uFF0C\u5173\u952E\u4EA7\u7269\u4F1A\u51FA\u73B0\u5728\u8FD9\u91CC\u3002" }),
|
|
2031
2046
|
project.artifacts.map((artifact) => /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
@@ -2135,8 +2150,9 @@ function VideoStudio({
|
|
|
2135
2150
|
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("p", { children: [
|
|
2136
2151
|
"\u5728\u53F3\u4FA7 Chat \u544A\u8BC9 Agent \u8981\u5904\u7406\u7684\u89C6\u9891\uFF1B\u9879\u76EE\u4F1A\u521B\u5EFA\u5728 ",
|
|
2137
2152
|
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("code", { children: "video-recaps/<\u9879\u76EE>/" }),
|
|
2138
|
-
"\u3002"
|
|
2139
|
-
] })
|
|
2153
|
+
"\u3002\u5F00\u59CB\u524D\u5148\u770B\u4E0B\u9762\u7684\u8FD0\u884C\u73AF\u5883\uFF1A\u7F3A\u9879\u65F6\u6D41\u6C34\u7EBF\u4F1A\u5728\u5904\u7406\u524D\u505C\u4E0B\u3002"
|
|
2154
|
+
] }),
|
|
2155
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(VideoEnvironment, { sessionId })
|
|
2140
2156
|
] }) : /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "oh-video-panels", children: [
|
|
2141
2157
|
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { role: "tabpanel", id: `${tabsId}-preview-panel`, "aria-labelledby": `${tabsId}-preview-tab`, hidden: tab !== "preview", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(VideoPreview, { project, sessionId, running }, project.id) }),
|
|
2142
2158
|
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { role: "tabpanel", id: `${tabsId}-artifacts-panel`, "aria-labelledby": `${tabsId}-artifacts-tab`, hidden: tab !== "artifacts", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(VideoArtifacts, { project, sessionId }) })
|
|
@@ -2179,6 +2195,18 @@ function workbenchPreferenceStorage() {
|
|
|
2179
2195
|
}
|
|
2180
2196
|
}
|
|
2181
2197
|
|
|
2198
|
+
// src/client/game-preview-state.ts
|
|
2199
|
+
function gamePreviewStatus(state) {
|
|
2200
|
+
let failed = state.frameError || state.probe === "failed";
|
|
2201
|
+
return state.building ? { tone: "building", label: "Agent \u6B63\u5728\u66F4\u65B0\u6E38\u620F\u6587\u4EF6 \xB7 \u5F53\u524D\u9884\u89C8\u4FDD\u6301\u4E0D\u53D8" } : state.pending ? { tone: state.frameLoaded && !failed ? "ready" : "loading", label: "\u65B0\u7248\u672C\u5DF2\u5C31\u7EEA \xB7 \u7531\u4F60\u51B3\u5B9A\u4F55\u65F6\u8F7D\u5165" } : failed ? { tone: "error", label: "\u9884\u89C8\u8F7D\u5165\u5931\u8D25 \xB7 \u53EF\u91CD\u65B0\u8F7D\u5165" } : state.frameLoaded ? { tone: "ready", label: state.isolated ? "\u9884\u89C8\u5DF2\u8F7D\u5165" : "\u9884\u89C8\u5DF2\u8F7D\u5165 \xB7 \u5F53\u524D\u90E8\u7F72\u65E0\u6CD5\u9694\u79BB\u6765\u6E90\uFF0C\u5B58\u6863\u529F\u80FD\u4E0D\u53EF\u7528" } : { tone: "loading", label: "\u6B63\u5728\u8F7D\u5165\u9884\u89C8\u2026" };
|
|
2202
|
+
}
|
|
2203
|
+
function previewUrls(path, version, revision, origin) {
|
|
2204
|
+
let url = new URL(path, origin);
|
|
2205
|
+
url.searchParams.set("build", version), url.searchParams.set("reload", String(revision));
|
|
2206
|
+
let probeHref = url.toString();
|
|
2207
|
+
return url.hostname === "127.0.0.1" ? url.hostname = "localhost" : url.hostname === "localhost" && (url.hostname = "127.0.0.1"), { href: url.toString(), probeHref, isolated: url.origin !== new URL(origin).origin };
|
|
2208
|
+
}
|
|
2209
|
+
|
|
2182
2210
|
// inline-css:/home/runner/work/oh-story-dsh/oh-story-dsh/packages/dsh-plugin/src/client/plugin.css
|
|
2183
2211
|
var plugin_default = `.oh-story-bridge-marker { display: none; }
|
|
2184
2212
|
.oh-story-welcome {
|
|
@@ -2198,6 +2226,10 @@ var plugin_default = `.oh-story-bridge-marker { display: none; }
|
|
|
2198
2226
|
.oh-story-welcome h2 { margin: 0 0 8px; font-size: 20px; }
|
|
2199
2227
|
.oh-story-welcome p { margin: 8px 0 0; }
|
|
2200
2228
|
.oh-story-welcome ol { margin: 12px 0; padding-left: 24px; }
|
|
2229
|
+
.oh-story-welcome-example { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 12px; padding-top: 12px; border-top: 1px solid var(--dsw-alias-border-l2); }
|
|
2230
|
+
.oh-story-welcome-example button { min-height: 32px; border: 1px solid var(--dsw-alias-border-l2); border-radius: 8px; padding: 4px 12px; color: inherit; background: var(--dsw-alias-bg-layer-1); cursor: pointer; font: inherit; font-weight: 600; }
|
|
2231
|
+
.oh-story-welcome-example button:hover { background: var(--dsw-alias-button-ghost-active-fill); }
|
|
2232
|
+
.oh-story-welcome-example span { color: var(--dsw-alias-label-secondary); font-size: 12px; }
|
|
2201
2233
|
.oh-story-split-surface { display: contents; font-family: var(--dsw-font-family); }
|
|
2202
2234
|
|
|
2203
2235
|
/* Collapsed, the plugin owns nothing but this control: DSH renders the
|
|
@@ -2462,20 +2494,9 @@ var plugin_default = `.oh-story-bridge-marker { display: none; }
|
|
|
2462
2494
|
.oh-game-reload { display: inline-flex; align-items: center; gap: 5px; }
|
|
2463
2495
|
.oh-game-reload b { font: inherit; font-weight: 500; }
|
|
2464
2496
|
.oh-game-preview-shell iframe { width: 100%; height: 100%; min-width: 0; min-height: 0; border: 0; background: var(--game-stage); }
|
|
2465
|
-
.oh-game-focus-hint {
|
|
2466
|
-
position: absolute;
|
|
2467
|
-
right: 10px;
|
|
2468
|
-
bottom: 10px;
|
|
2469
|
-
z-index: 2;
|
|
2470
|
-
padding: 4px 8px;
|
|
2471
|
-
border: 1px solid rgb(255 255 255 / 12%);
|
|
2472
|
-
border-radius: 6px;
|
|
2473
|
-
color: rgb(255 255 255 / 62%);
|
|
2474
|
-
background: rgb(8 10 9 / 82%);
|
|
2475
|
-
pointer-events: none;
|
|
2476
|
-
font-size: 10px;
|
|
2477
|
-
}
|
|
2497
|
+
.oh-game-focus-hint { flex: none; margin-left: auto; color: rgb(255 255 255 / 52%); font-size: 10px; white-space: nowrap; }
|
|
2478
2498
|
.oh-game-focus-hint[data-focused] { color: var(--game-accent); }
|
|
2499
|
+
.oh-game-studio[data-oh-game-narrow] .oh-game-focus-hint { display: none; }
|
|
2479
2500
|
|
|
2480
2501
|
.oh-game-preview-empty,
|
|
2481
2502
|
.oh-game-design-empty {
|
|
@@ -3158,7 +3179,8 @@ var plugin_default = `.oh-story-bridge-marker { display: none; }
|
|
|
3158
3179
|
[data-conversation-scroll][data-oh-story-workbench="game"][data-oh-story-layout="compact"] .oh-game-preview-status button { min-height: 36px; }
|
|
3159
3180
|
[data-conversation-scroll][data-oh-story-workbench="game"][data-oh-story-layout="compact"] .oh-game-reload b { display: none; }
|
|
3160
3181
|
[data-conversation-scroll][data-oh-story-workbench="game"][data-oh-story-layout="compact"] .oh-game-preview-status { padding-left: 8px; }
|
|
3161
|
-
[data-conversation-scroll][data-oh-story-workbench="game"][data-oh-story-layout="compact"] .oh-game-preview-status >
|
|
3182
|
+
[data-conversation-scroll][data-oh-story-workbench="game"][data-oh-story-layout="compact"] .oh-game-preview-status > .oh-game-runtime-state { max-width: 40%; }
|
|
3183
|
+
[data-conversation-scroll][data-oh-story-workbench="game"][data-oh-story-layout="compact"] .oh-game-focus-hint { display: none; }
|
|
3162
3184
|
.oh-game-runtime-state > em { display: block; overflow: hidden; min-width: 0; font-style: normal; text-overflow: ellipsis; white-space: nowrap; }
|
|
3163
3185
|
|
|
3164
3186
|
/* DSH may keep its navigation drawer open at a 500 px browser viewport,
|
|
@@ -3196,7 +3218,7 @@ var plugin_default = `.oh-story-bridge-marker { display: none; }
|
|
|
3196
3218
|
padding-right: 6px;
|
|
3197
3219
|
padding-left: 6px;
|
|
3198
3220
|
}
|
|
3199
|
-
[data-conversation-scroll][data-oh-story-workbench="game"][data-oh-story-layout="compact"] .oh-game-studio[data-oh-game-narrow] .oh-game-preview-status >
|
|
3221
|
+
[data-conversation-scroll][data-oh-story-workbench="game"][data-oh-story-layout="compact"] .oh-game-studio[data-oh-game-narrow] .oh-game-preview-status > .oh-game-runtime-state { max-width: 36%; }
|
|
3200
3222
|
|
|
3201
3223
|
@media (prefers-reduced-motion: reduce) {
|
|
3202
3224
|
.oh-game-preview-shell[data-state="building"] { animation: none; }
|
|
@@ -3364,6 +3386,10 @@ var plugin_default = `.oh-story-bridge-marker { display: none; }
|
|
|
3364
3386
|
.oh-video-prompt-example { max-width: 560px; margin-top: 10px; padding: 12px 14px; border: 1px solid rgb(255 255 255 / 11%); border-radius: 9px; background: rgb(255 255 255 / 4%); text-align: left; }
|
|
3365
3387
|
.oh-video-prompt-example span { display: block; margin-bottom: 4px; color: var(--video-accent); font-size: 10px; font-weight: 600; }
|
|
3366
3388
|
.oh-video-prompt-example q { quotes: none; }
|
|
3389
|
+
.oh-video-preview-empty .oh-video-environment { width: min(100%, 420px); box-sizing: border-box; margin: 10px 0 0; border-color: rgb(255 255 255 / 11%); background: rgb(255 255 255 / 4%); text-align: left; }
|
|
3390
|
+
.oh-video-preview-empty .oh-video-environment strong { color: rgb(255 255 255 / 92%); }
|
|
3391
|
+
.oh-video-preview-empty .oh-video-environment span,
|
|
3392
|
+
.oh-video-preview-empty .oh-video-environment em { color: rgb(244 248 255 / 70%); font-size: 11px; }
|
|
3367
3393
|
|
|
3368
3394
|
.oh-video-artifacts { display: grid; min-width: 0; min-height: 0; flex: 1; grid-template-columns: minmax(150px, 220px) minmax(0, 1fr); overflow: hidden; }
|
|
3369
3395
|
.oh-video-artifacts > aside { display: flex; min-height: 0; flex-direction: column; overflow: hidden; padding: 8px; border-right: 1px solid var(--os-border); background: var(--dsw-alias-bg-layer-1); }
|
|
@@ -3600,44 +3626,53 @@ function FileTreeNodes({
|
|
|
3600
3626
|
] }, node.path);
|
|
3601
3627
|
}) });
|
|
3602
3628
|
}
|
|
3603
|
-
|
|
3604
|
-
|
|
3629
|
+
var LIVE_WORKSPACE_REFRESH_MS = 4e3;
|
|
3630
|
+
function useWorkspace(sessionId, live) {
|
|
3631
|
+
let [version, setVersion] = (0, import_react4.useState)(0), [workspace, setWorkspace] = (0, import_react4.useState)(), [error, setError] = (0, import_react4.useState)(), [loading, setLoading] = (0, import_react4.useState)(!0), listed = (0, import_react4.useRef)(void 0), inFlight = (0, import_react4.useRef)(void 0), reload = (0, import_react4.useCallback)(() => {
|
|
3605
3632
|
setLoading(!0), setVersion((value) => value + 1);
|
|
3606
3633
|
}, []);
|
|
3607
3634
|
return (0, import_react4.useEffect)(() => {
|
|
3608
3635
|
let controller = new AbortController();
|
|
3609
|
-
return
|
|
3636
|
+
return inFlight.current = controller, fetch(endpoint("workspace", sessionId), { signal: controller.signal }).then((response) => json(response)).then((payload) => {
|
|
3637
|
+
setError(void 0);
|
|
3638
|
+
let text = JSON.stringify(payload);
|
|
3639
|
+
text !== listed.current && (listed.current = text, setWorkspace(payload));
|
|
3640
|
+
}).catch((reason) => {
|
|
3610
3641
|
controller.signal.aborted || setError(reason instanceof Error ? reason.message : String(reason));
|
|
3611
3642
|
}).finally(() => {
|
|
3612
|
-
controller.signal.aborted || setLoading(!1);
|
|
3643
|
+
inFlight.current === controller && (inFlight.current = void 0), controller.signal.aborted || setLoading(!1);
|
|
3613
3644
|
}), () => {
|
|
3614
3645
|
controller.abort();
|
|
3615
3646
|
};
|
|
3616
|
-
}, [sessionId, version]),
|
|
3617
|
-
|
|
3618
|
-
|
|
3619
|
-
|
|
3620
|
-
|
|
3647
|
+
}, [sessionId, version]), (0, import_react4.useEffect)(() => {
|
|
3648
|
+
if (!live) return;
|
|
3649
|
+
let timer = globalThis.setInterval(() => {
|
|
3650
|
+
inFlight.current !== void 0 || globalThis.document.visibilityState === "hidden" || setVersion((value) => value + 1);
|
|
3651
|
+
}, LIVE_WORKSPACE_REFRESH_MS);
|
|
3652
|
+
return () => {
|
|
3653
|
+
globalThis.clearInterval(timer);
|
|
3654
|
+
};
|
|
3655
|
+
}, [live]), { workspace, error, loading, reload };
|
|
3621
3656
|
}
|
|
3622
|
-
function PreviewProbe({ href,
|
|
3623
|
-
let
|
|
3657
|
+
function PreviewProbe({ href, onResult }) {
|
|
3658
|
+
let resultRef = (0, import_react4.useRef)(onResult);
|
|
3624
3659
|
return (0, import_react4.useEffect)(() => {
|
|
3625
|
-
|
|
3626
|
-
}, [
|
|
3660
|
+
resultRef.current = onResult;
|
|
3661
|
+
}, [onResult]), (0, import_react4.useEffect)(() => {
|
|
3627
3662
|
let controller = new AbortController();
|
|
3628
3663
|
return fetch(href, { signal: controller.signal }).then((response) => {
|
|
3629
3664
|
if (controller.signal.aborted) return;
|
|
3630
3665
|
let type = response.headers.get("content-type") ?? "";
|
|
3631
|
-
(
|
|
3666
|
+
resultRef.current(href, response.ok && type.includes("text/html") ? "ok" : "failed");
|
|
3632
3667
|
}).catch(() => {
|
|
3633
|
-
controller.signal.aborted ||
|
|
3668
|
+
controller.signal.aborted || resultRef.current(href, "failed");
|
|
3634
3669
|
}), () => {
|
|
3635
3670
|
controller.abort();
|
|
3636
3671
|
};
|
|
3637
3672
|
}, [href]), null;
|
|
3638
3673
|
}
|
|
3639
3674
|
function GamePreview({ project, building }) {
|
|
3640
|
-
let shellRef = (0, import_react4.useRef)(null), fullscreenButtonRef = (0, import_react4.useRef)(null), restoreFullscreenFocus = (0, import_react4.useRef)(!1), [focused, setFocused] = (0, import_react4.useState)(!1), [loaded, setLoaded] = (0, import_react4.useState)(!1), [loadError, setLoadError] = (0, import_react4.useState)(!1), [revision, setRevision] = (0, import_react4.useState)(0), [loadedVersion, setLoadedVersion] = (0, import_react4.useState)(project.previewVersion);
|
|
3675
|
+
let shellRef = (0, import_react4.useRef)(null), fullscreenButtonRef = (0, import_react4.useRef)(null), restoreFullscreenFocus = (0, import_react4.useRef)(!1), [focused, setFocused] = (0, import_react4.useState)(!1), [loaded, setLoaded] = (0, import_react4.useState)(!1), [loadError, setLoadError] = (0, import_react4.useState)(!1), [probe, setProbe] = (0, import_react4.useState)(), [revision, setRevision] = (0, import_react4.useState)(0), [loadedVersion, setLoadedVersion] = (0, import_react4.useState)(project.previewVersion);
|
|
3641
3676
|
if ((0, import_react4.useEffect)(() => {
|
|
3642
3677
|
let document = shellRef.current?.ownerDocument;
|
|
3643
3678
|
if (document === void 0) return;
|
|
@@ -3662,33 +3697,42 @@ function GamePreview({ project, building }) {
|
|
|
3662
3697
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("q", { children: "\u628A\u300A\u4F5C\u54C1\u540D\u300B\u6539\u7F16\u6210\u7F51\u9875\u4E92\u52A8\u6E38\u620F\uFF0C\u76EE\u6807\u73A9\u5BB6\u662F\u2026\u2026\uFF0C\u6838\u5FC3\u73A9\u6CD5\u662F\u2026\u2026\uFF0C\u5E0C\u671B\u6574\u4F53\u98CE\u683C\u2026\u2026" })
|
|
3663
3698
|
] })
|
|
3664
3699
|
] });
|
|
3665
|
-
let preview =
|
|
3700
|
+
let preview = previewUrls(project.previewUrl, loadedVersion, revision, globalThis.location.origin), pending = project.previewVersion !== loadedVersion, reload = () => {
|
|
3666
3701
|
setLoaded(!1), setLoadError(!1), setLoadedVersion(project.previewVersion), setRevision((value) => value + 1);
|
|
3667
3702
|
}, refresh = () => {
|
|
3668
3703
|
setLoaded(!1), setLoadError(!1), setRevision((value) => value + 1);
|
|
3669
|
-
},
|
|
3670
|
-
|
|
3704
|
+
}, status = gamePreviewStatus({
|
|
3705
|
+
frameLoaded: loaded,
|
|
3706
|
+
frameError: loadError,
|
|
3707
|
+
// A result for an earlier URL describes a build the frame no longer shows.
|
|
3708
|
+
probe: probe?.href === preview.probeHref ? probe.result : "pending",
|
|
3709
|
+
building,
|
|
3710
|
+
pending,
|
|
3711
|
+
isolated: preview.isolated
|
|
3712
|
+
}), runtimeState = status.label, fullscreen = () => {
|
|
3713
|
+
let shell = shellRef.current;
|
|
3714
|
+
shell !== null && (restoreFullscreenFocus.current = !0, shell.requestFullscreen().catch(() => {
|
|
3715
|
+
restoreFullscreenFocus.current = !1;
|
|
3716
|
+
}));
|
|
3717
|
+
};
|
|
3718
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { ref: shellRef, className: "oh-game-preview-shell", "data-state": status.tone, children: [
|
|
3671
3719
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "oh-game-preview-status", children: [
|
|
3672
3720
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "oh-game-runtime-state", role: "status", "aria-live": "polite", title: runtimeState, children: [
|
|
3673
3721
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("i", { "aria-hidden": !0 }),
|
|
3674
3722
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("em", { children: runtimeState })
|
|
3675
3723
|
] }),
|
|
3724
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "oh-game-focus-hint", "data-focused": focused || void 0, children: focused ? "\u6E38\u620F\u6B63\u5728\u63A5\u6536\u952E\u9F20\u8F93\u5165" : "\u70B9\u51FB\u753B\u9762\u8FDB\u5165\u8BD5\u73A9" }),
|
|
3676
3725
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { children: [
|
|
3677
3726
|
pending && !building && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { type: "button", onClick: reload, children: "\u8F7D\u5165\u65B0\u7248\u672C" }),
|
|
3678
3727
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("button", { className: "oh-game-reload", type: "button", onClick: refresh, "aria-label": "\u91CD\u65B0\u8F7D\u5165\u6E38\u620F", children: [
|
|
3679
3728
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { "aria-hidden": !0, children: "\u21BB" }),
|
|
3680
3729
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("b", { children: "\u5237\u65B0" })
|
|
3681
3730
|
] }),
|
|
3682
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { ref: fullscreenButtonRef, type: "button", onClick:
|
|
3683
|
-
let shell = shellRef.current;
|
|
3684
|
-
shell !== null && (restoreFullscreenFocus.current = !0, shell.requestFullscreen().catch(() => {
|
|
3685
|
-
restoreFullscreenFocus.current = !1;
|
|
3686
|
-
}));
|
|
3687
|
-
}, children: "\u5168\u5C4F\u8BD5\u73A9" })
|
|
3731
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { ref: fullscreenButtonRef, type: "button", onClick: fullscreen, children: "\u5168\u5C4F\u8BD5\u73A9" })
|
|
3688
3732
|
] })
|
|
3689
3733
|
] }),
|
|
3690
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(PreviewProbe, { href: preview.
|
|
3691
|
-
|
|
3734
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(PreviewProbe, { href: preview.probeHref, onResult: (href, result) => {
|
|
3735
|
+
setProbe({ href, result });
|
|
3692
3736
|
} }),
|
|
3693
3737
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
3694
3738
|
"iframe",
|
|
@@ -3700,7 +3744,7 @@ function GamePreview({ project, building }) {
|
|
|
3700
3744
|
allowFullScreen: !0,
|
|
3701
3745
|
referrerPolicy: "no-referrer",
|
|
3702
3746
|
onLoad: () => {
|
|
3703
|
-
|
|
3747
|
+
setLoaded(!0);
|
|
3704
3748
|
},
|
|
3705
3749
|
onError: () => {
|
|
3706
3750
|
setLoaded(!1), setLoadError(!0);
|
|
@@ -3713,8 +3757,7 @@ function GamePreview({ project, building }) {
|
|
|
3713
3757
|
}
|
|
3714
3758
|
},
|
|
3715
3759
|
`${project.id}:${loadedVersion}:${String(revision)}`
|
|
3716
|
-
)
|
|
3717
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "oh-game-focus-hint", "data-focused": focused || void 0, children: focused ? "\u6E38\u620F\u6B63\u5728\u63A5\u6536\u952E\u9F20\u8F93\u5165" : "\u70B9\u51FB\u753B\u9762\u8FDB\u5165\u8BD5\u73A9" })
|
|
3760
|
+
)
|
|
3718
3761
|
] });
|
|
3719
3762
|
}
|
|
3720
3763
|
function GameDesign({
|
|
@@ -3878,8 +3921,12 @@ function CreativeWorkbench({
|
|
|
3878
3921
|
let path = creativeRelativePath(activity2.path, workspace?.cwd);
|
|
3879
3922
|
return path === void 0 ? [] : [{ activity: activity2, path }];
|
|
3880
3923
|
}), [activities, workspace?.cwd]), primaryActivity = normalizedActivities.at(-1), activityPaths = (0, import_react4.useMemo)(() => new Set(normalizedActivities.map((value) => value.path)), [normalizedActivities]), settledPath = settledMutation === void 0 ? void 0 : creativeRelativePath(settledMutation.slice(settledMutation.indexOf("\0") + 1), workspace?.cwd), activity = primaryActivity?.activity, activityPath = primaryActivity?.path, workbench = useStore((memory) => memory.workbench), setWorkbench = actions.setWorkbench, gameTab = useStore((memory) => memory.gameTab), setGameTab = actions.setGameTab, gameProjectId = useStore((memory) => memory.gameProjectId), setGameProjectId = actions.setGameProjectId, gamePane = useStore((memory) => memory.gamePane), setGamePane = actions.setGamePane, videoTab = useStore((memory) => memory.videoTab), setVideoTab = actions.setVideoTab, videoProjectId = useStore((memory) => memory.videoProjectId), setVideoProjectId = actions.setVideoProjectId, videoPane = useStore((memory) => memory.videoPane), setVideoPane = actions.setVideoPane, selected = useStore((memory) => memory.selected), setSelected = actions.setSelected, buffers = useStore((memory) => memory.buffers), setBuffers = actions.setBuffers, buffersRef = (0, import_react4.useRef)({}), expanded = useStore((memory) => memory.expanded), setExpanded = actions.setExpanded, productionSection = useStore((memory) => memory.productionSection), setProductionSection = actions.setProductionSection, productionSelectedIds = useStore((memory) => memory.productionSelectedIds), productionJobsByEpisode = useStore((memory) => memory.productionJobs), productionSelectionsByEpisode = useStore((memory) => memory.productionSelections), productionReferencesByEpisode = useStore((memory) => memory.productionReferences), productionSequenceByEpisode = useStore((memory) => memory.productionSequence), productionCanvasByEpisode = useStore((memory) => memory.productionCanvas), productionViewportByEpisode = useStore((memory) => memory.productionViewport), productionIntentCalls = useStore((memory) => memory.productionIntentCalls), surfaceRef = (0, import_react4.useRef)(null), setWorkbenchPreference = actions.setWorkbenchPreference, applyWorkbenchPreference = (0, import_react4.useCallback)((preference) => {
|
|
3881
|
-
setWorkbenchPreference(preference)
|
|
3882
|
-
|
|
3924
|
+
setWorkbenchPreference(preference);
|
|
3925
|
+
let storage = workbenchPreferenceStorage();
|
|
3926
|
+
(creativeProject || readWorkbenchPreference(storage, workspace?.cwd) !== void 0) && writeWorkbenchPreference(storage, workspace?.cwd, preference);
|
|
3927
|
+
}, [creativeProject, setWorkbenchPreference, workspace?.cwd]), exampleGameId = workspace?.games.find((game) => game.source === "example")?.id, playExample = exampleGameId === void 0 ? void 0 : () => {
|
|
3928
|
+
setGameProjectId(exampleGameId), setGameTab("preview"), setWorkbench("game"), applyWorkbenchPreference("open");
|
|
3929
|
+
}, compactTabsId = (0, import_react4.useId)(), compactStudioId = `${compactTabsId}-studio-panel`, compactVideoStudioId = `${compactTabsId}-video-studio-panel`, compactChatId = `${compactTabsId}-chat-panel`, navRef = (0, import_react4.useRef)(null), activityBases = (0, import_react4.useRef)(/* @__PURE__ */ new Map()), previousSignals = (0, import_react4.useRef)(/* @__PURE__ */ new Set()), consumedSettledMutation = useStore((memory) => memory.settledMutation), liveTurns = (0, import_react4.useRef)(/* @__PURE__ */ new Set());
|
|
3883
3930
|
liveTurn !== void 0 && liveTurns.current.add(liveTurn);
|
|
3884
3931
|
let saveLocks = (0, import_react4.useRef)(/* @__PURE__ */ new Set()), buffer = selected === void 0 ? void 0 : buffers[selected], selectedFile = workspace?.files.find((file) => file.path === selected), selectedMedia = selectedFile?.kind === "media", dirty = buffer?.source === "human" && buffer.content !== buffer.saved, saving = buffer?.saving === !0, fileError = buffer?.error, conflict = buffer?.conflict, selectedLower = selected?.toLocaleLowerCase(), markdown = selectedLower?.endsWith(".md") === !0, jsonl = selectedLower?.endsWith(".jsonl") === !0, structured = jsonl || selectedLower?.endsWith(".json") === !0, previewable = markdown || jsonl, episodeDirectory = episodeDirectoryForPath(selected), productionAvailable = selected !== void 0 && isCreatorDocumentPath(selected) && episodeDirectory !== void 0, editorModes = productionAvailable ? EDITOR_MODES : EDITOR_MODES.filter((mode) => mode !== "production"), episodeDocumentPaths = (0, import_react4.useMemo)(
|
|
3885
3932
|
() => episodeDirectory === void 0 ? [] : creatorDocumentPaths(workspace?.files.filter((file) => file.kind === "text") ?? [], episodeDirectory),
|
|
@@ -4583,7 +4630,7 @@ function CreativeWorkbench({
|
|
|
4583
4630
|
)
|
|
4584
4631
|
] })
|
|
4585
4632
|
] })
|
|
4586
|
-
] }) : !creativeProject && error === void 0 ? welcome ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(WelcomeGuide, {}) : null : /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { ref: surfaceRef, className: "oh-story-split-surface", "data-open": "false", children: [
|
|
4633
|
+
] }) : !creativeProject && error === void 0 ? welcome ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(WelcomeGuide, { onPlayExample: playExample }) : null : /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { ref: surfaceRef, className: "oh-story-split-surface", "data-open": "false", children: [
|
|
4587
4634
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("style", { children: plugin_default }),
|
|
4588
4635
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("button", { className: "oh-story-launcher", type: "button", title: error ?? "\u6253\u5F00\u521B\u4F5C\u5DE5\u4F5C\u53F0", "aria-label": "\u6253\u5F00\u521B\u4F5C\u5DE5\u4F5C\u53F0", onClick: () => {
|
|
4589
4636
|
applyWorkbenchPreference("open");
|
|
@@ -4615,7 +4662,7 @@ function SessionWorkbenchBridge({ sessionId, useSession, useSessions, useProject
|
|
|
4615
4662
|
let marker = (0, import_react4.useRef)(null), [target, setTarget] = (0, import_react4.useState)(), runningCalls = useChat((snapshot) => snapshot.legacy.runningCalls), partial = useChat((snapshot) => streamingAssistant(snapshot.timeline)), undispatched = useChat((snapshot) => undispatchedCalls(snapshot), sameUndispatchedCalls), settledMutation = useChat((snapshot) => latestSettledMutation(snapshot)), settledMutationTurn = useChat((snapshot) => latestSettledMutationTurn(snapshot)), liveTurn = useChat((snapshot) => openTurn(snapshot)), workbench = useStore((memory) => memory.workbench), gamePane = useStore((memory) => memory.gamePane), videoPane = useStore((memory) => memory.videoPane), sessionRunning = useSession((snapshot) => snapshot.running), inboxRows = useProjection("inbox", (inbox) => inbox?.["next-turn"]), pendingSubmissions = useSession((snapshot) => snapshot.pendingSubmissions), productionQueue = (0, import_react4.useMemo)(() => productionQueueFromInbox(
|
|
4616
4663
|
inboxRows,
|
|
4617
4664
|
new Set(pendingSubmissions.filter((item) => item.placement === "transcript").map((item) => item.requestId))
|
|
4618
|
-
), [inboxRows, pendingSubmissions]), chat = useChat((snapshot) => snapshot), productionIntents = (0, import_react4.useMemo)(() => settledProductionIntents(chat), [chat]), { workspace, error, loading: workspaceLoading, reload } = useWorkspace(sessionId), chosenPreference = useStore((memory) => memory.workbenchPreference), creativeProject = hasCreativeProject(workspace), welcome = useSessions((state) => state.byId[sessionId]?.blank === !0) && workspace !== void 0 && !workspaceLoading && !creativeProject, storedPreference = (0, import_react4.useMemo)(
|
|
4665
|
+
), [inboxRows, pendingSubmissions]), chat = useChat((snapshot) => snapshot), productionIntents = (0, import_react4.useMemo)(() => settledProductionIntents(chat), [chat]), { workspace, error, loading: workspaceLoading, reload } = useWorkspace(sessionId, sessionRunning), chosenPreference = useStore((memory) => memory.workbenchPreference), creativeProject = hasCreativeProject(workspace), welcome = useSessions((state) => state.byId[sessionId]?.blank === !0) && workspace !== void 0 && !workspaceLoading && !creativeProject, storedPreference = (0, import_react4.useMemo)(
|
|
4619
4666
|
() => readWorkbenchPreference(workbenchPreferenceStorage(), workspace?.cwd),
|
|
4620
4667
|
[workspace?.cwd]
|
|
4621
4668
|
), open = resolveWorkbenchOpen(chosenPreference ?? storedPreference, creativeProject);
|
|
@@ -4713,7 +4760,7 @@ function SessionWorkbenchBridge({ sessionId, useSession, useSessions, useProject
|
|
|
4713
4760
|
), target)
|
|
4714
4761
|
] });
|
|
4715
4762
|
}
|
|
4716
|
-
function WelcomeGuide() {
|
|
4763
|
+
function WelcomeGuide({ onPlayExample }) {
|
|
4717
4764
|
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("section", { className: "oh-story-welcome", "aria-label": "Oh Story \u4F7F\u7528\u5F15\u5BFC", children: [
|
|
4718
4765
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("style", { children: plugin_default }),
|
|
4719
4766
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("h2", { children: "Oh Story \u5DF2\u52A0\u8F7D" }),
|
|
@@ -4732,6 +4779,10 @@ function WelcomeGuide() {
|
|
|
4732
4779
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("li", { children: "\u4E0D\u9009\u6587\u4EF6\u5939\u4E5F\u80FD\u5F00\u59CB\uFF1A\u4F5C\u54C1\u4F1A\u5199\u8FDB DSH \u81EA\u52A8\u5EFA\u7ACB\u7684\u300C\u9ED8\u8BA4\u5DE5\u4F5C\u533A / Default workspace\u300D\u3002" }),
|
|
4733
4780
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("li", { children: "\u60F3\u653E\u8FDB\u81EA\u5DF1\u7684\u4F5C\u54C1\u6587\u4EF6\u5939\uFF1A\u70B9\u51FB\u5DE6\u4FA7\u300C\u5DE5\u4F5C\u533A / Workspaces\u300D\u65C1\u7684\u300C\u6DFB\u52A0\u5DE5\u4F5C\u533A / Add workspace\u300D\uFF0C\u5728\u7CFB\u7EDF\u5F39\u51FA\u7684\u6587\u4EF6\u5939\u7A97\u53E3\u91CC\u9009\u62E9\uFF0C\u518D\u5728\u4E0B\u65B9\u300C\u9009\u62E9\u5DE5\u4F5C\u533A / Choose workspace\u300D\u4E2D\u9009\u4E2D\u5B83\u3002" }),
|
|
4734
4781
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("li", { children: "\u8F93\u5165\u6846\u53F3\u4E0B\u89D2\u663E\u793A\u6A21\u578B\u540D\u5C31\u8BF4\u660E\u5DF2\u914D\u7F6E\u597D\uFF1B\u6CA1\u6709\u6A21\u578B\u65F6\uFF0C\u5728\u300C\u8BBE\u7F6E \u2192 \u6A21\u578B\u300D\u586B\u5165 API Key\u3002\u53EA\u67E5\u770B\u5DF2\u6709\u4F5C\u54C1\u65E0\u9700 API Key\u3002" })
|
|
4782
|
+
] }),
|
|
4783
|
+
onPlayExample !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "oh-story-welcome-example", children: [
|
|
4784
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { type: "button", onClick: onPlayExample, children: "\u5148\u73A9\u5185\u7F6E\u793A\u4F8B\u300A\u91D1\u74F6\u6885 \xB7 \u98CE\u6708\u603B\u8D26\u300B" }),
|
|
4785
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: "\u968F\u63D2\u4EF6\u9644\u5E26\u7684\u5B8C\u6574 ADV \u6E38\u620F\uFF0C\u4E0D\u7528 API Key\u3002\u5185\u5BB9 18+\uFF0C\u8FDB\u5165\u524D\u4F1A\u786E\u8BA4\u5E74\u9F84\u3002" })
|
|
4735
4786
|
] })
|
|
4736
4787
|
] });
|
|
4737
4788
|
}
|