beauticode-dsh 1.0.23 → 1.0.25

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.zh-CN.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  该 Cordis 插件向 DSH Web 注入 beautiCode 浏览器客户端,并提供本机鉴权接口。支持图片、MP4、播放位置、静音、摸鱼模式以及清除背景。
4
4
 
5
- 装好插件并运行 `dsh web` 后,侧栏「设置」上方会出现「背景」:在 Windows 上点击图片或视频会打开系统文件选择器,选好后在页面内命名,背景立即应用并进入已保存主题;也可以清除、开关声音、切换或删除主题,以及打开「皮肤中心」安装已审核的社区皮肤。本地导入只在 Node 端保存绝对路径,并通过带 Range 支持的回环媒体服务读取原文件,不复制用户选择的图片或整段视频主文件。Windows 强制使用本地引用;原生选择器不可用时会明确报错,不会静默上传或复制媒体。非 Windows 环境保留兼容上传,并明确提示该模式会保存托管副本。网页控制台没有摸鱼;浅色/深色跟 DSH 自己的外观走。下次打开会恢复上次背景。设置 `BEAUTICODE_SKIN_CENTER` 或填写 `skin-center.json` 后,皮肤中心才会显示远程目录。
5
+ 装好插件并运行 `dsh web` 后,侧栏「设置」上方会出现「背景」:在 Windows 上点击图片或视频会打开系统文件选择器,选好后在页面内命名,背景立即应用并进入已保存主题;也可以清除、开关声音、用阴影滑条调节背景明暗(恢复默认则回到对话自动纱)、切换或删除主题,以及打开「皮肤中心」安装已审核的社区皮肤。本地导入只在 Node 端保存绝对路径,并通过带 Range 支持的回环媒体服务读取原文件,不复制用户选择的图片或整段视频主文件。Windows 强制使用本地引用;原生选择器不可用时会明确报错,不会静默上传或复制媒体。非 Windows 环境保留兼容上传,并明确提示该模式会保存托管副本。网页控制台没有摸鱼;浅色/深色跟 DSH 自己的外观走。下次打开会恢复上次背景。设置 `BEAUTICODE_SKIN_CENTER` 或填写 `skin-center.json` 后,皮肤中心才会显示远程目录。
6
6
 
7
7
  插件也会注册对话工具(`beauticode_*`)和斜杠命令(`/bg`、`/bg-theme`、`/bg-clear`)。不需要托盘;托盘若已在跑则复用它。
8
8
 
package/atmosphere.js CHANGED
@@ -1,4 +1,5 @@
1
- (() => {
1
+ //hello,starstreaming
2
+ (() => {
2
3
  "use strict";
3
4
 
4
5
  const STYLE_ID = "beauticode-atmosphere-style";
package/client.js CHANGED
@@ -86,6 +86,24 @@ html[data-bc-active="true"]:has(#root [data-phase="active"]) #beauticode-bg-stag
86
86
  html[data-bc-active="true"]:has(#root [data-phase="settling"]) #beauticode-bg-stage::after{background:rgba(0,0,0,.42)}
87
87
  html[data-bc-resolved-tone="light"][data-bc-active="true"]:has(#root [data-phase="active"]) #beauticode-bg-stage::after,
88
88
  html[data-bc-resolved-tone="light"][data-bc-active="true"]:has(#root [data-phase="settling"]) #beauticode-bg-stage::after{background:rgba(255,255,255,.22)}
89
+ html[data-bc-dim-user="true"][data-bc-active="true"]:has(#root [data-phase="active"]) body,
90
+ html[data-bc-dim-user="true"][data-bc-active="true"]:has(#root [data-phase="settling"]) body{
91
+ --dsw-alias-bg-base:rgba(17,20,27,.10);
92
+ --dsw-alias-bg-layer-1:rgba(26,30,39,.28);
93
+ --dsw-alias-bg-layer-2:rgba(35,40,51,.32);
94
+ --dsw-alias-bg-overlay:rgba(17,20,27,.12);
95
+ --dsw-specific-sidebar-fill:rgba(23,27,35,.28);
96
+ }
97
+ html[data-bc-resolved-tone="light"][data-bc-dim-user="true"][data-bc-active="true"]:has(#root [data-phase="active"]) body,
98
+ html[data-bc-resolved-tone="light"][data-bc-dim-user="true"][data-bc-active="true"]:has(#root [data-phase="settling"]) body{
99
+ --dsw-alias-bg-base:rgba(248,250,252,.12);
100
+ --dsw-alias-bg-layer-1:rgba(255,255,255,.28);
101
+ --dsw-alias-bg-layer-2:rgba(248,250,252,.32);
102
+ --dsw-alias-bg-overlay:rgba(255,255,255,.14);
103
+ --dsw-specific-sidebar-fill:rgba(255,255,255,.28);
104
+ }
105
+ html[data-bc-dim-user="true"][data-bc-active="true"] #beauticode-bg-stage::after{background:rgba(0,0,0,var(--bc-dim))!important}
106
+ html[data-bc-resolved-tone="light"][data-bc-dim-user="true"][data-bc-active="true"] #beauticode-bg-stage::after{background:rgba(255,255,255,var(--bc-dim))!important}
89
107
  html[data-bc-fish="true"] #beauticode-bg-stage::after{background:transparent!important}
90
108
  #beauticode-bg-stage .beauticode-media-slot{position:absolute;inset:0;z-index:0;opacity:1;overflow:hidden;pointer-events:none;transition:opacity ${CROSSFADE_MS}ms ease;will-change:opacity}
91
109
  #beauticode-bg-stage .beauticode-media-slot[data-bc-role="current"]{z-index:1;opacity:1}
@@ -108,6 +126,75 @@ html[data-bc-fish="true"] #root{opacity:0!important;visibility:hidden!important;
108
126
  `;
109
127
  document.head.append(style);
110
128
 
129
+ const DIM_STORAGE_KEY = "beauticode-dim";
130
+ let userDim = null;
131
+
132
+ function clampDim(value) {
133
+ const n = Number(value);
134
+ if (!Number.isFinite(n) || n < 0 || n > 1) return null;
135
+ return n;
136
+ }
137
+
138
+ function readStoredDim() {
139
+ try {
140
+ const raw = globalThis.localStorage?.getItem(DIM_STORAGE_KEY);
141
+ if (raw == null || raw === "") return null;
142
+ return clampDim(raw);
143
+ } catch {
144
+ return null;
145
+ }
146
+ }
147
+
148
+ function writeStoredDim(value) {
149
+ try {
150
+ if (value == null) globalThis.localStorage?.removeItem(DIM_STORAGE_KEY);
151
+ else globalThis.localStorage?.setItem(DIM_STORAGE_KEY, String(value));
152
+ } catch {
153
+ /* private mode / quota */
154
+ }
155
+ }
156
+
157
+ function applyUserDim(value) {
158
+ const root = document.documentElement;
159
+ if (value == null) {
160
+ delete root.dataset.bcDimUser;
161
+ root.removeAttribute("data-bc-dim-user");
162
+ root.style.removeProperty?.("--bc-dim");
163
+ return null;
164
+ }
165
+ root.dataset.bcDimUser = "true";
166
+ root.style.setProperty?.("--bc-dim", String(value));
167
+ return value;
168
+ }
169
+
170
+ function getUserDim() {
171
+ return userDim;
172
+ }
173
+
174
+ function setUserDim(value) {
175
+ const next = clampDim(value);
176
+ if (next == null) return userDim;
177
+ userDim = next;
178
+ writeStoredDim(next);
179
+ applyUserDim(next);
180
+ return next;
181
+ }
182
+
183
+ function clearUserDim() {
184
+ userDim = null;
185
+ writeStoredDim(null);
186
+ applyUserDim(null);
187
+ return null;
188
+ }
189
+
190
+ userDim = readStoredDim();
191
+ if (userDim != null) applyUserDim(userDim);
192
+ globalThis.BeauticodeBackgroundDim = {
193
+ get: getUserDim,
194
+ set: setUserDim,
195
+ clear: clearUserDim,
196
+ };
197
+
111
198
  // Chromium builds its media stack lazily; the first <video> of a fresh
112
199
  // profile pays decoder/GPU/audio init inside the first import's verify
113
200
  // deadline. One muted playback of the bundled frame pays that cost early.
package/console.js CHANGED
@@ -30,6 +30,12 @@ body:not([data-ds-dark-theme]) #beauticode-console-pop{background:#f3f0e9;color:
30
30
  #beauticode-console-pop .bc-import small{display:block;color:#717579;font-size:10px;line-height:14px}
31
31
  #beauticode-console-pop .bc-arrow{font-size:16px;text-align:right}
32
32
  #beauticode-console-pop .bc-controls{display:flex;align-items:center;gap:12px;padding:9px 0;border-bottom:1px solid #c8c5be}
33
+ #beauticode-console-pop .bc-dim{display:flex;flex-wrap:wrap;align-items:center;gap:8px 12px;padding:8px 0;border-bottom:1px solid #c8c5be}
34
+ #beauticode-console-pop .bc-dim-label{color:#686d71;font:10px ui-monospace,"Cascadia Mono",monospace}
35
+ #beauticode-console-pop .bc-dim-slider{-webkit-appearance:none;appearance:none;flex:1;min-width:72px;height:4px;margin:0;padding:0;background:#c8c5be;border-radius:0}
36
+ #beauticode-console-pop .bc-dim-slider::-webkit-slider-runnable-track{height:4px;background:#c8c5be;border-radius:0}
37
+ #beauticode-console-pop .bc-dim-slider::-webkit-slider-thumb{-webkit-appearance:none;width:10px;height:10px;margin-top:-3px;background:#252a30;border:0;border-radius:0;cursor:pointer}
38
+ #beauticode-console-pop .bc-dim-value{min-width:2.6em;color:#686d71;font:10px/15px ui-monospace,"Cascadia Mono",monospace;text-align:right}
33
39
  #beauticode-console-pop .bc-link{cursor:pointer;height:auto;padding:0;border:0;background:transparent;color:#595e62;font-size:11px;line-height:18px;text-decoration:underline;text-underline-offset:3px}
34
40
  #beauticode-console-pop .bc-link:hover{color:#171a1d}
35
41
  #beauticode-console-pop .bc-theme-toggle{cursor:pointer;display:flex;align-items:center;justify-content:space-between;width:100%;height:31px;padding:8px 0 4px;border:0;background:transparent;color:#686d71;font:10px ui-monospace,"Cascadia Mono",monospace;letter-spacing:.08em;text-align:left}
@@ -84,6 +90,12 @@ body:not([data-ds-dark-theme]) #beauticode-console-pop{background:#f3f0e9;color:
84
90
  '<button type="button" class="bc-btn bc-link" data-act="clear">清除背景</button>' +
85
91
  '<button type="button" class="bc-btn bc-link" data-act="gallery">打开皮肤中心</button>' +
86
92
  "</div>" +
93
+ '<div class="bc-dim">' +
94
+ '<span class="bc-dim-label">阴影</span>' +
95
+ '<input type="range" class="bc-dim-slider" min="0" max="100" step="1" value="42" aria-label="背景阴影"/>' +
96
+ '<span class="bc-dim-value">自动</span>' +
97
+ '<button type="button" class="bc-btn bc-link" data-act="dim-reset" hidden>恢复默认</button>' +
98
+ "</div>" +
87
99
  '<div class="bc-themes" hidden>' +
88
100
  '<button type="button" class="bc-theme-toggle" aria-expanded="true"><span>SAVED / 00</span><span>−</span></button>' +
89
101
  '<div class="bc-theme-list" hidden></div>' +
@@ -99,15 +111,33 @@ body:not([data-ds-dark-theme]) #beauticode-console-pop{background:#f3f0e9;color:
99
111
  const trigger = host.querySelector(".bc-trigger");
100
112
  const statusEl = pop.querySelector(".bc-status");
101
113
  const soundBtn = pop.querySelector('[data-act="sound"]');
114
+ const dimSlider = pop.querySelector(".bc-dim-slider");
115
+ const dimValue = pop.querySelector(".bc-dim-value");
116
+ const dimReset = pop.querySelector('[data-act="dim-reset"]');
102
117
  const themesBox = pop.querySelector(".bc-themes");
103
118
  const themeToggle = pop.querySelector(".bc-theme-toggle");
104
119
  const themeList = pop.querySelector(".bc-theme-list");
105
120
  const msgEl = pop.querySelector(".bc-msg");
121
+ const AUTO_DIM_PERCENT = 42;
106
122
  let busy = false;
107
123
  let muted = true;
108
124
  let currentThemeId = "";
109
125
  let themesExpanded = true;
110
126
 
127
+ function renderDim() {
128
+ const current = globalThis.BeauticodeBackgroundDim?.get?.() ?? null;
129
+ if (current == null) {
130
+ dimSlider.value = String(AUTO_DIM_PERCENT);
131
+ dimValue.textContent = "自动";
132
+ dimReset.hidden = true;
133
+ return;
134
+ }
135
+ const percent = Math.round(current * 100);
136
+ dimSlider.value = String(percent);
137
+ dimValue.textContent = `${percent}%`;
138
+ dimReset.hidden = false;
139
+ }
140
+
111
141
  function findSettingsTrigger() {
112
142
  const buttons = [...document.querySelectorAll('button[aria-haspopup="dialog"]')];
113
143
  const candidates = buttons.filter((button) => {
@@ -126,11 +156,30 @@ body:not([data-ds-dark-theme]) #beauticode-console-pop{background:#f3f0e9;color:
126
156
  pop.style.bottom = `${Math.round(window.innerHeight - rect.top + 8)}px`;
127
157
  }
128
158
 
159
+ function isContents(node) {
160
+ if (!node) return false;
161
+ if (node.style?.display === "contents") return true;
162
+ if (typeof getComputedStyle === "function") {
163
+ try {
164
+ return getComputedStyle(node).display === "contents";
165
+ } catch {
166
+ return false;
167
+ }
168
+ }
169
+ return false;
170
+ }
171
+
172
+ function layoutParent(node) {
173
+ let current = node?.parentElement ?? null;
174
+ while (current && isContents(current)) current = current.parentElement;
175
+ return current;
176
+ }
177
+
129
178
  function place() {
130
179
  const settings = findSettingsTrigger();
131
- const row = settings?.parentElement;
132
- const settingsArea = row?.parentElement;
133
- const footArea = settingsArea?.parentElement;
180
+ const row = layoutParent(settings);
181
+ const settingsArea = layoutParent(row);
182
+ const footArea = layoutParent(settingsArea);
134
183
  if (!settings || !settingsArea || !footArea) {
135
184
  if (host.parentElement) host.remove();
136
185
  return;
@@ -458,6 +507,18 @@ body:not([data-ds-dark-theme]) #beauticode-console-pop{background:#f3f0e9;color:
458
507
  }),
459
508
  );
460
509
  });
510
+ dimSlider.addEventListener("input", () => {
511
+ const n = Number(dimSlider.value);
512
+ if (!Number.isFinite(n)) return;
513
+ globalThis.BeauticodeBackgroundDim?.set?.(n / 100);
514
+ renderDim();
515
+ });
516
+ dimReset.addEventListener("click", (event) => {
517
+ event.stopPropagation();
518
+ globalThis.BeauticodeBackgroundDim?.clear?.();
519
+ renderDim();
520
+ });
521
+ renderDim();
461
522
  themeToggle.addEventListener("click", (event) => {
462
523
  event.stopPropagation();
463
524
  themesExpanded = !themesExpanded;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "beauticode-dsh",
3
- "version": "1.0.23",
3
+ "version": "1.0.25",
4
4
  "description": "Cordis plugin: image/video backgrounds for DeepSeek Harness web.",
5
5
  "type": "module",
6
6
  "main": "./index.mjs",
@@ -1,6 +1,6 @@
1
1
  import fs from "node:fs/promises";
2
2
  import path from "node:path";
3
- import { MAX_INLINE_DATA_URL_BYTES, MAX_VIDEO_POSTER_INLINE_BYTES, } from "./constants.js";
3
+ import { MAX_INLINE_DATA_URL_BYTES } from "./constants.js";
4
4
  import { isLocalBackgroundSource, resolveBackgroundImagePath, resolveBackgroundVideoPath, } from "./media-source.js";
5
5
  import { detectImageMime } from "./media-validation.js";
6
6
  // Cold-first-access symptoms reported by the renderer while the OS is still
@@ -286,13 +286,7 @@ export async function buildHostApplyPayload(store, manifest, staged, cssText, vi
286
286
  const imagePath = resolveBackgroundImagePath(store.paths.activeDir, manifest.background);
287
287
  if (!imagePath)
288
288
  throw new Error("Background has no image source.");
289
- const imageStat = await fs.stat(imagePath).catch(() => null);
290
- const skipInlinePoster = manifest.background.type === "video" &&
291
- imageStat != null &&
292
- imageStat.size > MAX_VIDEO_POSTER_INLINE_BYTES;
293
- const imageDataUrl = opts.includeImageDataUrl === false || skipInlinePoster
294
- ? null
295
- : await fileToDataUrl(imagePath);
289
+ const imageDataUrl = opts.includeImageDataUrl === false ? null : await fileToDataUrl(imagePath);
296
290
  const imageUrl = staged?.image?.srcUrl ?? null;
297
291
  if (manifest.background.type === "image") {
298
292
  return {
@@ -9,11 +9,6 @@ export const MAX_VIDEO_BYTES = 800 * 1024 * 1024;
9
9
  * Keep this equal to MAX_IMAGE_BYTES so every accepted image can publish.
10
10
  */
11
11
  export const MAX_INLINE_DATA_URL_BYTES = MAX_IMAGE_BYTES;
12
- /**
13
- * Keep a large video poster out of the Codex Runtime.evaluate payload.
14
- * The first decoded video frame replaces the poster after the blob attaches.
15
- */
16
- export const MAX_VIDEO_POSTER_INLINE_BYTES = 1024 * 1024;
17
12
  export const COMMIT_MARKER_NAME = ".beauticode-commit-in-progress";
18
13
  export const COMMIT_MARKER_STALE_MS = 120_000;
19
14
  export const MEDIA_TOKEN_HEADER = "x-beauticode-media-token";