diff --git a/README.md b/README.md
index 3174529..60bfb6c 100644
--- a/README.md
+++ b/README.md
@@ -108,10 +108,12 @@ npx @deepseek-ai/dsh plugin --profile web add file:%CD%/integrations/deepseek-ha
需要 Codex Desktop、系统托盘或懒得留源码时,再下 [Windows 安装包](https://github.com/starsstreaming/beautiCode/releases/latest)。
-运行:
+然后自己启动:
-```text
-beautiCode-Setup-1.0.1-win-x64.exe
+```sh
+dsh web
+# 未把 dsh 装到 PATH 时:
+npx @deepseek-ai/dsh web
```
安装包自带 Node.js,不需要另外安装 Node.js、npm 或 pnpm。安装结束时会自动写入 DSH 插件。若你改过安装目录,以安装文件夹里的 `集成说明.txt` 为准。
diff --git a/apps/tray/session-host.mjs b/apps/tray/session-host.mjs
index 3c044fb..e7bb49b 100644
--- a/apps/tray/session-host.mjs
+++ b/apps/tray/session-host.mjs
@@ -22,6 +22,7 @@
* POST /discover {}
* POST /shutdown {}
*/
+import fs from "node:fs";
import http from "node:http";
import process from "node:process";
import path from "node:path";
@@ -118,6 +119,25 @@ if (portArg) {
sessionOpts.autoDiscover = false;
}
if (dataRoot) sessionOpts.dataRoot = path.resolve(dataRoot);
+const bundledGalleryHi = path.join(
+ repoRoot,
+ "assets",
+ "themes",
+ "internal-beyond",
+ "bg-canvas-4k.png",
+);
+const bundledGalleryLo = path.join(
+ repoRoot,
+ "assets",
+ "themes",
+ "internal-beyond",
+ "bg-canvas.png",
+);
+if (fs.existsSync(bundledGalleryHi)) {
+ sessionOpts.bundledGalleryImagePath = bundledGalleryHi;
+} else if (fs.existsSync(bundledGalleryLo)) {
+ sessionOpts.bundledGalleryImagePath = bundledGalleryLo;
+}
const SessionClass = hostKind === "dsh" ? adapter.DshSession : adapter.BeautiSession;
const session = new SessionClass(sessionOpts);
@@ -172,6 +192,7 @@ function publicTheme(theme) {
name: theme.name,
type: theme.type,
savedAt: theme.savedAt,
+ ...(theme.bundled ? { bundled: true } : {}),
...(typeof theme.videoPositionSec === "number"
? { videoPositionSec: theme.videoPositionSec }
: {}),
@@ -287,10 +308,14 @@ const server = http.createServer(
send(res, 400, { ok: false, error: "必须提供 imagePath。" });
return;
}
- const result = await session.apply({
+ const imageInput = {
type: "image",
imagePath: path.resolve(body.imagePath),
- });
+ };
+ if (body.effects && typeof body.effects === "object") {
+ imageInput.effects = body.effects;
+ }
+ const result = await session.apply(imageInput);
send(res, result.ok ? 200 : 422, result);
return;
}
diff --git a/apps/tray/start-tray.ps1 b/apps/tray/start-tray.ps1
index 26d8f0a..2299588 100644
--- a/apps/tray/start-tray.ps1
+++ b/apps/tray/start-tray.ps1
@@ -1936,15 +1936,13 @@ function Rebuild-BcTrayMenu {
})
[void]$savedMenu.DropDownItems.Add($item)
}
- [void]$savedMenu.DropDownItems.Add(
- (New-Object System.Windows.Forms.ToolStripSeparator)
- )
$deleteMenu = New-Object System.Windows.Forms.ToolStripMenuItem
$deleteMenu.Text = $L.DeleteTheme
foreach ($theme in $themes) {
$deleteId = [string]$theme.id
$deleteName = [string]$theme.name
if (-not $deleteId) { continue }
+ if ($theme.bundled -eq $true) { continue }
$deleteItem = New-Object System.Windows.Forms.ToolStripMenuItem
$deleteItem.Text = $deleteName
$deleteItem.Tag = $deleteId
@@ -1973,7 +1971,12 @@ function Rebuild-BcTrayMenu {
})
[void]$deleteMenu.DropDownItems.Add($deleteItem)
}
- [void]$savedMenu.DropDownItems.Add($deleteMenu)
+ if ($deleteMenu.DropDownItems.Count -gt 0) {
+ [void]$savedMenu.DropDownItems.Add(
+ (New-Object System.Windows.Forms.ToolStripSeparator)
+ )
+ [void]$savedMenu.DropDownItems.Add($deleteMenu)
+ }
}
} catch {
$empty = New-Object System.Windows.Forms.ToolStripMenuItem
diff --git a/assets/themes/internal-beyond/NOTICE.md b/assets/themes/internal-beyond/NOTICE.md
new file mode 100644
index 0000000..1bcaa71
--- /dev/null
+++ b/assets/themes/internal-beyond/NOTICE.md
@@ -0,0 +1,9 @@
+# Internal / Infernal atmosphere assets
+
+`bg-internal.jpg`, `bg-infernal.jpg`, `bg-canvas.png`, and the local
+`bg-canvas-4k.png` (Real-ESRGAN 4x then 3840×2160) are visual materials
+from [Internal Beyond](https://github.com/Sui-IB/InternalBeyond) by Sui.
+
+They remain under that project's CC BY-NC-SA 4.0 terms for visual assets.
+BeautiCode ships them as bundled workspace themes for local, non-commercial use.
+The project name, logo, and character identity are not licensed here.
diff --git a/assets/themes/internal-beyond/bg-canvas-4k.png b/assets/themes/internal-beyond/bg-canvas-4k.png
new file mode 100644
index 0000000..1755a1c
Binary files /dev/null and b/assets/themes/internal-beyond/bg-canvas-4k.png differ
diff --git a/assets/themes/internal-beyond/bg-canvas.png b/assets/themes/internal-beyond/bg-canvas.png
new file mode 100644
index 0000000..71ca5c3
Binary files /dev/null and b/assets/themes/internal-beyond/bg-canvas.png differ
diff --git a/assets/themes/internal-beyond/bg-infernal.jpg b/assets/themes/internal-beyond/bg-infernal.jpg
new file mode 100644
index 0000000..80f37e7
Binary files /dev/null and b/assets/themes/internal-beyond/bg-infernal.jpg differ
diff --git a/assets/themes/internal-beyond/bg-internal.jpg b/assets/themes/internal-beyond/bg-internal.jpg
new file mode 100644
index 0000000..707bd96
Binary files /dev/null and b/assets/themes/internal-beyond/bg-internal.jpg differ
diff --git a/integrations/deepseek-harness/README.zh-CN.md b/integrations/deepseek-harness/README.zh-CN.md
index 49ed217..9d11012 100644
--- a/integrations/deepseek-harness/README.zh-CN.md
+++ b/integrations/deepseek-harness/README.zh-CN.md
@@ -8,7 +8,14 @@
beautiCode **不启动** DeepSeek Harness。请先自己运行 `dsh web`。
-安装包和托盘会把插件写入你的 DSH profile,不需要 pnpm。源码环境也可以手动(`dsh plugin add` 需要 pnpm):
+推荐在仓库根目录一键写入插件(不需要 pnpm):
+
+```powershell
+powershell -NoProfile -ExecutionPolicy Bypass -File .\scripts\install-dsh-plugin.ps1
+npx @deepseek-ai/dsh web
+```
+
+也可以手动(`dsh plugin add` 需要 pnpm):
```sh
dsh plugin --profile web add file:%CD%/integrations/deepseek-harness
diff --git a/integrations/deepseek-harness/agent.mjs b/integrations/deepseek-harness/agent.mjs
index b5ab556..f4b1810 100644
--- a/integrations/deepseek-harness/agent.mjs
+++ b/integrations/deepseek-harness/agent.mjs
@@ -6,6 +6,7 @@ import {
stripPathQuotes,
} from "./control-client.mjs";
import { resolveApplyBackend, stopInProcessSession } from "./host-apply.mjs";
+import { ATMOSPHERE_PRESETS, effectsForPreset, presetImagePath } from "./presets.mjs";
const APPLY_TIMEOUT_MS = 180_000;
const QUICK_TIMEOUT_MS = 15_000;
@@ -98,30 +99,66 @@ export function createBeauticodeActions(dataRootOrOptions) {
}
return {
- async applyImage(imagePath, signal) {
+ async applyImage(imagePath, signal, options) {
const inspected = await inspectLocalMedia(imagePath);
if (!inspected.ok) fail(inspected.error);
if (inspected.kind !== "image") {
fail("beauticode_apply_image 只接受图片文件。");
}
+ const effects = effectsForPreset(options?.effects?.preset) || options?.effects || null;
+ const input = { type: "image", imagePath: inspected.path };
+ if (effects) input.effects = effects;
const resolved = await backend();
if (resolved.kind === "tray") {
+ const body = { imagePath: inspected.path };
+ if (effects) body.effects = effects;
return unwrapApply(
await request({
method: "POST",
path: "/apply/image",
- body: { imagePath: inspected.path },
+ body,
signal,
}),
"image",
"已将图片设为背景。",
);
}
- return unwrapApply(
- await resolved.session.apply({ type: "image", imagePath: inspected.path }),
- "image",
- "已将图片设为背景。",
- );
+ return unwrapApply(await resolved.session.apply(input), "image", "已将图片设为背景。");
+ },
+
+ async applyPreset(id, signal) {
+ const preset = ATMOSPHERE_PRESETS[id];
+ const imagePath = presetImagePath(id);
+ if (!preset || !imagePath) fail("未找到内置主题文件。");
+ const result = await this.applyImage(imagePath, signal, {
+ effects: effectsForPreset(id),
+ });
+ try {
+ await this.setTone(preset.tone, signal);
+ } catch {
+ /* tone is best-effort; the wallpaper still applied */
+ }
+ return {
+ ...result,
+ atmosphere: id,
+ message: `已应用 ${preset.name} 活壁纸。`,
+ };
+ },
+
+ async setTone(tone, signal) {
+ const resolved = await backend();
+ const result =
+ resolved.kind === "tray"
+ ? await request({
+ method: "POST",
+ path: "/mode/tone",
+ body: { tone },
+ signal,
+ timeoutMs: QUICK_TIMEOUT_MS,
+ })
+ : await resolved.session.setBackgroundTone(tone);
+ if (result.ok === false) fail(result.error || "无法切换背景色调。");
+ return { ok: true, tone: result.tone ?? tone };
},
async applyVideo(input, signal) {
diff --git a/integrations/deepseek-harness/atmosphere.js b/integrations/deepseek-harness/atmosphere.js
new file mode 100644
index 0000000..19338c7
--- /dev/null
+++ b/integrations/deepseek-harness/atmosphere.js
@@ -0,0 +1,306 @@
+(() => {
+ "use strict";
+
+ const STYLE_ID = "beauticode-atmosphere-style";
+ const ROOT_ID = "beauticode-gallery-bg";
+ const CANVAS_URL =
+ (typeof globalThis !== "undefined" && globalThis.__BEAUTICODE_CANVAS_URL) ||
+ "/__beauticode/themes/bg-canvas.png?v=uhd";
+
+ function createWaterSim(simWidth, simHeight) {
+ const width = Math.max(24, simWidth | 0);
+ const height = Math.max(16, simHeight | 0);
+ let current = new Float32Array(width * height);
+ let next = new Float32Array(width * height);
+ let clock = 0;
+
+ function poke(cx, cy, strength, radius) {
+ const x0 = cx | 0;
+ const y0 = cy | 0;
+ const rad = Math.max(1, radius);
+ const r2 = rad * rad;
+ const reach = Math.ceil(rad);
+ for (let y = -reach; y <= reach; y += 1) {
+ for (let x = -reach; x <= reach; x += 1) {
+ const px = x0 + x;
+ const py = y0 + y;
+ if (px < 1 || py < 1 || px >= width - 1 || py >= height - 1) continue;
+ const falloff = (x * x + y * y) / r2;
+ if (falloff > 1) continue;
+ current[py * width + px] += strength * (0.5 + 0.5 * Math.cos(Math.PI * Math.sqrt(falloff)));
+ }
+ }
+ }
+
+ function step(dt) {
+ clock += dt;
+ for (let y = 1; y < height - 1; y += 1) {
+ let i = y * width + 1;
+ for (let x = 1; x < width - 1; x += 1, i += 1) {
+ next[i] =
+ ((current[i - 1] + current[i + 1] + current[i - width] + current[i + width]) * 0.5 -
+ next[i]) *
+ 0.9855 +
+ 0.0024 * Math.sin(clock * 0.7 + x * 0.05 + y * 0.021) +
+ 0.0019 * Math.sin(clock * 0.43 - x * 0.023 + y * 0.041);
+ }
+ }
+ const swap = current;
+ current = next;
+ next = swap;
+ }
+
+ return {
+ width,
+ height,
+ poke,
+ step,
+ heights() {
+ return current;
+ },
+ };
+ }
+
+ function ensureStyle() {
+ if (typeof document === "undefined") return null;
+ let style = document.getElementById(STYLE_ID);
+ if (!style) {
+ style = document.createElement("style");
+ style.id = STYLE_ID;
+ document.head.append(style);
+ }
+ style.textContent = `
+#beauticode-gallery-bg{position:fixed;inset:0;z-index:0;overflow:hidden;pointer-events:none;background:#0b1018}
+#beauticode-gallery-bg img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;object-position:center center;display:block;pointer-events:none;z-index:0;image-rendering:auto;-webkit-backface-visibility:hidden}
+#beauticode-gallery-bg canvas{position:absolute;inset:0;width:100%;height:100%;pointer-events:none;z-index:1;mix-blend-mode:soft-light;opacity:.32}
+html[data-bc-gallery="true"] #beauticode-bg-stage{background:transparent!important}
+html[data-bc-gallery="true"] #beauticode-bg-stage::after{display:none!important;background:transparent!important}
+html[data-bc-gallery="true"],html[data-bc-gallery="true"] body{background:transparent!important}
+html[data-bc-gallery="true"] body{
+ --dsw-alias-bg-base:rgba(17,20,27,.10);
+ --dsw-alias-bg-layer-1:rgba(26,30,39,.28);
+ --dsw-alias-bg-layer-2:rgba(35,40,51,.32);
+ --dsw-alias-bg-overlay:rgba(17,20,27,.12);
+ --dsw-specific-sidebar-fill:rgba(23,27,35,.28);
+}
+html[data-bc-resolved-tone="light"][data-bc-gallery="true"] body{
+ --dsw-alias-bg-base:rgba(248,250,252,.12);
+ --dsw-alias-bg-layer-1:rgba(255,255,255,.28);
+ --dsw-alias-bg-layer-2:rgba(248,250,252,.32);
+ --dsw-alias-bg-overlay:rgba(255,255,255,.14);
+ --dsw-specific-sidebar-fill:rgba(255,255,255,.28);
+}
+html[data-bc-gallery="true"] #root{position:relative;z-index:1;background:transparent!important}
+html[data-bc-gallery="true"] [class*="_fade"]{display:none!important}
+html[data-bc-gallery="true"] #beauticode-bg-stage>img,
+html[data-bc-gallery="true"] #beauticode-bg-stage>video{opacity:0!important}
+html[data-bc-fish="true"] #root{opacity:0!important;visibility:hidden!important;pointer-events:none!important}
+`;
+ return style;
+ }
+
+ const runtime = {
+ windowMode: "closed",
+ layer: null,
+ token: 0,
+ loop: 0,
+ lastTick: 0,
+ };
+
+ function stopLoop() {
+ if (runtime.loop) {
+ cancelAnimationFrame(runtime.loop);
+ runtime.loop = 0;
+ }
+ }
+
+ function attachWater(canvas) {
+ const dpr = () => Math.max(1, Math.min(2, window.devicePixelRatio || 1));
+ let sim = null;
+ let output = null;
+ let work = null;
+ let last = null;
+
+ function sizeSim() {
+ const width = Math.max(32, canvas.clientWidth || window.innerWidth || 1);
+ const height = Math.max(32, canvas.clientHeight || window.innerHeight || 1);
+ const pixel = dpr();
+ canvas.width = Math.round(width * pixel);
+ canvas.height = Math.round(height * pixel);
+ const simWidth = Math.max(80, Math.min(420, Math.round(width / 4)));
+ const simHeight = Math.max(45, Math.round(simWidth * (height / width)));
+ sim = createWaterSim(simWidth, simHeight);
+ output = null;
+ work = null;
+ }
+
+ function localPoint(event) {
+ const rect = canvas.getBoundingClientRect();
+ if (!rect.width || !rect.height || !sim) return null;
+ return {
+ x: ((event.clientX - rect.left) / rect.width) * sim.width,
+ y: ((event.clientY - rect.top) / rect.height) * sim.height,
+ };
+ }
+
+ function follow(event) {
+ if (!sim) return;
+ const point = localPoint(event);
+ if (!point) return;
+ if (last) {
+ const dx = point.x - last.x;
+ const dy = point.y - last.y;
+ const dist = Math.hypot(dx, dy);
+ const steps = Math.max(1, Math.min(8, Math.ceil(dist / 6)));
+ const strength = 0.55 + Math.min(1.8, dist / 18);
+ for (let i = 1; i <= steps; i += 1) {
+ const t = i / steps;
+ sim.poke(last.x + dx * t, last.y + dy * t, strength / steps, 2.4);
+ }
+ } else {
+ sim.poke(point.x, point.y, 0.7, 2.2);
+ }
+ last = point;
+ }
+
+ function render() {
+ if (!sim) return;
+ sim.step(0.033);
+ const ctx = canvas.getContext("2d");
+ if (!output) output = ctx.createImageData(sim.width, sim.height);
+ const dest = output.data;
+ const heights = sim.heights();
+ for (let y = 0; y < sim.height; y += 1) {
+ const up = y > 0 ? y - 1 : y;
+ const down = y < sim.height - 1 ? y + 1 : y;
+ for (let x = 0; x < sim.width; x += 1) {
+ const i = y * sim.width + x;
+ const gx = heights[x > 0 ? i - 1 : i] - heights[x < sim.width - 1 ? i + 1 : i];
+ const gy = heights[up * sim.width + x] - heights[down * sim.width + x];
+ const di = i * 4;
+ let alpha = gy * 160;
+ if (alpha >= 0) {
+ dest[di] = 224;
+ dest[di + 1] = 238;
+ dest[di + 2] = 255;
+ dest[di + 3] = alpha > 110 ? 110 : alpha;
+ } else {
+ alpha = -alpha;
+ dest[di] = 8;
+ dest[di + 1] = 16;
+ dest[di + 2] = 32;
+ dest[di + 3] = alpha > 90 ? 90 : alpha;
+ }
+ }
+ }
+ if (!work) {
+ work = document.createElement("canvas");
+ work.width = sim.width;
+ work.height = sim.height;
+ }
+ work.getContext("2d").putImageData(output, 0, 0);
+ const pixel = dpr();
+ ctx.setTransform(pixel, 0, 0, pixel, 0, 0);
+ ctx.imageSmoothingEnabled = true;
+ if (ctx.imageSmoothingQuality) ctx.imageSmoothingQuality = "high";
+ ctx.clearRect(0, 0, canvas.clientWidth, canvas.clientHeight);
+ ctx.drawImage(work, 0, 0, canvas.clientWidth, canvas.clientHeight);
+ }
+
+ sizeSim();
+ window.addEventListener("pointermove", follow, { passive: true });
+ window.addEventListener("resize", sizeSim);
+
+ return {
+ render,
+ destroy() {
+ window.removeEventListener("pointermove", follow);
+ window.removeEventListener("resize", sizeSim);
+ },
+ };
+ }
+
+ function markPage(on) {
+ const root = document.documentElement;
+ if (on) {
+ root.dataset.bcGallery = "true";
+ root.dataset.bcActive = "true";
+ } else {
+ delete root.dataset.bcGallery;
+ if (!document.querySelector("#beauticode-bg-stage img, #beauticode-bg-stage video")) {
+ root.removeAttribute("data-bc-active");
+ }
+ }
+ }
+
+ function closeLayer() {
+ stopLoop();
+ runtime.layer?.water?.destroy();
+ runtime.layer?.node.remove();
+ runtime.layer = null;
+ markPage(false);
+ }
+
+ async function openLayer() {
+ const token = (runtime.token += 1);
+ ensureStyle();
+ closeLayer();
+ markPage(true);
+ const node = document.createElement("div");
+ node.id = ROOT_ID;
+ node.setAttribute("aria-hidden", "true");
+ const image = document.createElement("img");
+ image.alt = "";
+ image.decoding = "async";
+ image.fetchPriority = "high";
+ image.draggable = false;
+ const canvas = document.createElement("canvas");
+ node.append(image, canvas);
+ document.body.prepend(node);
+
+ await new Promise((resolve) => {
+ image.onload = resolve;
+ image.onerror = resolve;
+ image.src = CANVAS_URL;
+ });
+ if (token !== runtime.token || runtime.windowMode === "closed") {
+ node.remove();
+ return;
+ }
+
+ const water = attachWater(canvas);
+ runtime.layer = { node, water };
+ const tick = (ts) => {
+ if (!runtime.layer) return;
+ if (ts - runtime.lastTick > 32) {
+ runtime.lastTick = ts;
+ water.render();
+ }
+ runtime.loop = requestAnimationFrame(tick);
+ };
+ runtime.loop = requestAnimationFrame(tick);
+ }
+
+ function setWindowMode(mode) {
+ const next = mode === "on" || mode === "window" || mode === "full" ? "on" : "closed";
+ runtime.windowMode = next;
+ if (next === "closed") closeLayer();
+ else void openLayer();
+ return next;
+ }
+
+ function getState() {
+ return { windowMode: runtime.windowMode };
+ }
+
+ const api = {
+ createWaterSim,
+ setWindowMode,
+ getState,
+ };
+
+ globalThis.BeauticodeAtmosphere = api;
+ if (typeof module !== "undefined" && module.exports) {
+ module.exports = api;
+ }
+})();
diff --git a/integrations/deepseek-harness/client.js b/integrations/deepseek-harness/client.js
index 7c6f34a..359332f 100644
--- a/integrations/deepseek-harness/client.js
+++ b/integrations/deepseek-harness/client.js
@@ -247,10 +247,16 @@ html[data-bc-fish="true"] #root{opacity:0!important;visibility:hidden!important;
}
}
+ function syncGallery(payload) {
+ const on = payload?.atmosphere?.preset === "gallery";
+ globalThis.BeauticodeAtmosphere?.setWindowMode?.(on ? "on" : "closed");
+ }
+
async function applyBackground(payload) {
if (!Number.isSafeInteger(payload?.generation)) return;
activePayload = payload;
document.documentElement.dataset.bcGeneration = String(payload.generation);
+ syncGallery(payload);
if (payload.media === "clear") {
desiredModes.fish = false;
playbackBlocked = false;
@@ -258,6 +264,9 @@ html[data-bc-fish="true"] #root{opacity:0!important;visibility:hidden!important;
document.documentElement.removeAttribute("data-bc-media");
document.documentElement.removeAttribute("data-bc-fish");
document.getElementById("beauticode-bg-stage")?.remove();
+ if (document.documentElement.dataset.bcGallery === "true") {
+ document.documentElement.dataset.bcActive = "true";
+ }
await acknowledgeRender(payload, true, false);
await acknowledgeMode();
return;
diff --git a/integrations/deepseek-harness/console.js b/integrations/deepseek-harness/console.js
index 4a52384..31e6c27 100644
--- a/integrations/deepseek-harness/console.js
+++ b/integrations/deepseek-harness/console.js
@@ -142,8 +142,16 @@ body:not([data-ds-dark-theme]) #beauticode-console-pop .bc-theme-item:hover{back
statusEl.textContent = data?.error || "未就绪";
return;
}
- const label = data.media === "video" ? "视频" : data.media === "image" ? "图片" : "无背景";
+ const label =
+ data.atmosphere === "gallery"
+ ? "画窗"
+ : data.media === "video"
+ ? "视频"
+ : data.media === "image"
+ ? "图片"
+ : "无背景";
statusEl.textContent = label;
+ if (data.atmosphere === "gallery") currentThemeId = "builtin-gallery";
muted = data.muted !== false;
soundBtn.classList.toggle("on", !muted);
soundBtn.textContent = muted ? "声音" : "声音开";
@@ -229,6 +237,7 @@ body:not([data-ds-dark-theme]) #beauticode-console-pop .bc-theme-item:hover{back
fileInput.click();
});
pop.querySelector('[data-act="clear"]').addEventListener("click", () => {
+ currentThemeId = "";
void run(() => request("/__beauticode/ui/clear", { method: "POST" }));
});
soundBtn.addEventListener("click", () => {
@@ -252,6 +261,9 @@ body:not([data-ds-dark-theme]) #beauticode-console-pop .bc-theme-item:hover{back
currentThemeId = item.getAttribute("data-theme-id") || "";
themeList.hidden = true;
themeToggle.setAttribute("aria-expanded", "false");
+ globalThis.BeauticodeAtmosphere?.setWindowMode?.(
+ currentThemeId === "builtin-gallery" ? "on" : "closed",
+ );
void run(() =>
request("/__beauticode/ui/theme/use", {
method: "POST",
@@ -264,6 +276,7 @@ body:not([data-ds-dark-theme]) #beauticode-console-pop .bc-theme-item:hover{back
const file = fileInput.files?.[0];
fileInput.value = "";
if (!file) return;
+ currentThemeId = "";
void run(() =>
request("/__beauticode/ui/import", {
method: "POST",
diff --git a/integrations/deepseek-harness/host-apply.mjs b/integrations/deepseek-harness/host-apply.mjs
index 2e4d04d..87fa10d 100644
--- a/integrations/deepseek-harness/host-apply.mjs
+++ b/integrations/deepseek-harness/host-apply.mjs
@@ -5,6 +5,7 @@ import {
readDshControlFile,
readTrayClaim,
} from "./control-client.mjs";
+import { canvasImagePath } from "./presets.mjs";
const sessions = new Map();
@@ -91,6 +92,7 @@ export async function ensureInProcessSession(options) {
dataRoot,
baseUrl,
verifyDeadlineMs: 30_000,
+ bundledGalleryImagePath: canvasImagePath() || undefined,
});
try {
await session.start();
diff --git a/integrations/deepseek-harness/index.mjs b/integrations/deepseek-harness/index.mjs
index a1ba26c..2284179 100644
--- a/integrations/deepseek-harness/index.mjs
+++ b/integrations/deepseek-harness/index.mjs
@@ -6,6 +6,7 @@ import { fileURLToPath } from "node:url";
import { registerAgentSurfaces } from "./agent.mjs";
import { resolvePluginBaseUrl } from "./host-apply.mjs";
import { createBeauticodeUi } from "./ui-host.mjs";
+import { canvasImagePath, iceFrostImagePath, normalizeAtmosphere } from "./presets.mjs";
export const name = "beauticode-bridge";
export const inject = ["webServer"];
@@ -127,13 +128,15 @@ function validLoopbackMediaUrl(value) {
function validApplyPayload(body) {
if (!Number.isSafeInteger(body.generation) || body.generation < 0) return false;
if (!["image", "video", "clear"].includes(body.media)) return false;
+ if (body.atmosphere != null && !normalizeAtmosphere(body.atmosphere)) return false;
if (body.media === "clear") {
- return body.imageUrl == null && body.videoUrl == null && body.startAt == null;
+ return body.imageUrl == null && body.videoUrl == null && body.startAt == null && body.atmosphere == null;
}
if (!validLoopbackMediaUrl(body.imageUrl)) return false;
if (body.media === "image") return body.videoUrl == null && body.startAt == null;
return (
validLoopbackMediaUrl(body.videoUrl) &&
+ body.atmosphere == null &&
(body.startAt == null || (Number.isFinite(body.startAt) && body.startAt >= 0))
);
}
@@ -206,6 +209,7 @@ export function apply(ctx, config = {}) {
const disposeTap = ctx.webServer.tapIndex((html) => {
if (html.includes("data-beauticode-bridge")) return html;
const script =
+ '' +
'' +
'';
return html.includes("