beauticode-dsh 1.0.14 → 1.0.16

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
 
@@ -40,7 +40,7 @@ npx @deepseek-ai/dsh web
40
40
 
41
41
  手动接入时:
42
42
 
43
- 1. 修改 `cordis.patch.yml` 中的插件接入项;优先使用上面的安装命令自动完成接线。
43
+ 1. 修改 `cordis.patch.yml` 中的插件接入项;优先使用上面的安装命令自动完成接线。
44
44
  2. 确保 DSH 和 beautiCode 使用相同的 `BEAUTICODE_DATA_ROOT`。
45
45
  3. 自己运行 `dsh web`(或带 `--patch`)。
46
46
  4. 打开页面后用侧栏「背景」,或输入 `/bg <本机绝对路径>`,或直接跟 AI 说把某个视频/图片设为背景。
package/agent.mjs CHANGED
@@ -61,20 +61,20 @@ async function chineseError(error) {
61
61
  return raw || "操作失败。";
62
62
  }
63
63
 
64
- async function unwrapApplyResult(result, fallbackMode, message) {
65
- if (!result || result.ok === false) {
66
- const failure = new Error(await chineseError(result?.error || "操作失败。"));
67
- if (result?.sourceMode != null) failure.sourceMode = result.sourceMode;
68
- if (result?.timings != null) failure.timings = result.timings;
69
- throw failure;
70
- }
71
- return {
72
- ok: true,
73
- generation: result.generation ?? null,
74
- mode: result.mode ?? fallbackMode,
75
- sourceMode: result.sourceMode ?? null,
76
- timings: result.timings ?? null,
77
- message,
64
+ async function unwrapApplyResult(result, fallbackMode, message) {
65
+ if (!result || result.ok === false) {
66
+ const failure = new Error(await chineseError(result?.error || "操作失败。"));
67
+ if (result?.sourceMode != null) failure.sourceMode = result.sourceMode;
68
+ if (result?.timings != null) failure.timings = result.timings;
69
+ throw failure;
70
+ }
71
+ return {
72
+ ok: true,
73
+ generation: result.generation ?? null,
74
+ mode: result.mode ?? fallbackMode,
75
+ sourceMode: result.sourceMode ?? null,
76
+ timings: result.timings ?? null,
77
+ message,
78
78
  ...(result.theme
79
79
  ? {
80
80
  theme: {
@@ -103,7 +103,7 @@ function normalizeActionOptions(dataRootOrOptions) {
103
103
  : {};
104
104
  }
105
105
 
106
- function unwrapApply(result, fallbackMode, message) {
106
+ function unwrapApply(result, fallbackMode, message) {
107
107
  if (!result || result.ok === false) {
108
108
  fail(result?.error || "操作失败。");
109
109
  }
@@ -121,24 +121,24 @@ function unwrapApply(result, fallbackMode, message) {
121
121
  },
122
122
  }
123
123
  : {}),
124
- };
125
- }
126
-
127
- function presentStatus(status) {
128
- const background = status.manifest?.background ?? status.background ?? null;
129
- return {
124
+ };
125
+ }
126
+
127
+ function presentStatus(status) {
128
+ const background = status.manifest?.background ?? status.background ?? null;
129
+ return {
130
130
  ok: true,
131
131
  hostReady: status.hostReady === true || status.sessions > 0,
132
132
  sessions: status.sessions ?? 0,
133
133
  fish: status.fish === true,
134
134
  muted: status.muted !== false,
135
135
  tone: status.tone ?? "dark",
136
- background,
137
- sourceMode: background
138
- ? background.source?.kind === "local"
139
- ? "local"
140
- : "managed"
141
- : "clear",
136
+ background,
137
+ sourceMode: background
138
+ ? background.source?.kind === "local"
139
+ ? "local"
140
+ : "managed"
141
+ : "clear",
142
142
  themeId: typeof status.themeId === "string" && status.themeId ? status.themeId : null,
143
143
  message: formatStatusText(status),
144
144
  };
@@ -178,26 +178,26 @@ export function createBeauticodeActions(dataRootOrOptions) {
178
178
  }
179
179
  const effects = effectsForPreset(options?.effects?.preset) || options?.effects || null;
180
180
  const persistTheme = options?.persistTheme !== false;
181
- const themeName =
182
- String(options?.themeName ?? "").trim() ||
183
- themeNameFromFilePath(inspected.path, "图片");
184
- const source = options?.source === "managed" ? "managed" : "local";
185
- const input = { type: "image", imagePath: inspected.path, source };
186
- if (effects) input.effects = effects;
187
- const resolved = await backend();
188
- if (resolved.kind === "tray") {
189
- const result = await request({
190
- method: "POST",
191
- path: persistTheme ? "/theme/apply" : "/apply/image",
192
- body: persistTheme
193
- ? { name: themeName, input }
194
- : {
195
- imagePath: inspected.path,
196
- source,
197
- ...(effects ? { effects } : {}),
198
- },
199
- signal,
200
- });
181
+ const themeName =
182
+ String(options?.themeName ?? "").trim() ||
183
+ themeNameFromFilePath(inspected.path, "图片");
184
+ const source = options?.source === "managed" ? "managed" : "local";
185
+ const input = { type: "image", imagePath: inspected.path, source };
186
+ if (effects) input.effects = effects;
187
+ const resolved = await backend();
188
+ if (resolved.kind === "tray") {
189
+ const result = await request({
190
+ method: "POST",
191
+ path: persistTheme ? "/theme/apply" : "/apply/image",
192
+ body: persistTheme
193
+ ? { name: themeName, input }
194
+ : {
195
+ imagePath: inspected.path,
196
+ source,
197
+ ...(effects ? { effects } : {}),
198
+ },
199
+ signal,
200
+ });
201
201
  return unwrapApplyResult(
202
202
  result,
203
203
  "image",
@@ -205,10 +205,10 @@ export function createBeauticodeActions(dataRootOrOptions) {
205
205
  ? `已将「${result.theme?.name || themeName}」设为背景。`
206
206
  : "已将图片设为背景。",
207
207
  );
208
- }
209
- const applied = persistTheme
210
- ? await resolved.session.applyAndSaveTheme(input, themeName)
211
- : await resolved.session.apply(input);
208
+ }
209
+ const applied = persistTheme
210
+ ? await resolved.session.applyAndSaveTheme(input, themeName)
211
+ : await resolved.session.apply(input);
212
212
  return unwrapApplyResult(
213
213
  applied,
214
214
  "image",
@@ -261,12 +261,12 @@ export function createBeauticodeActions(dataRootOrOptions) {
261
261
  fail("beauticode_apply_video 只接受 .mp4 文件。");
262
262
  }
263
263
  const persistTheme = input?.persistTheme !== false;
264
- const themeName =
265
- String(input?.themeName ?? "").trim() ||
266
- themeNameFromFilePath(inspected.path, "视频");
267
- const source = input?.source === "managed" ? "managed" : "local";
268
- const body = { videoPath: inspected.path, persistTheme, themeName, source };
269
- const localInput = { type: "video", videoPath: inspected.path, source };
264
+ const themeName =
265
+ String(input?.themeName ?? "").trim() ||
266
+ themeNameFromFilePath(inspected.path, "视频");
267
+ const source = input?.source === "managed" ? "managed" : "local";
268
+ const body = { videoPath: inspected.path, persistTheme, themeName, source };
269
+ const localInput = { type: "video", videoPath: inspected.path, source };
270
270
  if (typeof input.poster === "string" && input.poster.trim()) {
271
271
  const poster = await inspectLocalMedia(input.poster);
272
272
  if (!poster.ok) fail(poster.error);
@@ -282,14 +282,14 @@ export function createBeauticodeActions(dataRootOrOptions) {
282
282
  body.startAt = startAt;
283
283
  localInput.startAt = startAt;
284
284
  }
285
- const resolved = await backend();
286
- if (resolved.kind === "tray") {
287
- const result = await request({
288
- method: "POST",
289
- path: persistTheme ? "/theme/apply" : "/apply/video",
290
- body: persistTheme ? { name: themeName, input: localInput } : body,
291
- signal,
292
- });
285
+ const resolved = await backend();
286
+ if (resolved.kind === "tray") {
287
+ const result = await request({
288
+ method: "POST",
289
+ path: persistTheme ? "/theme/apply" : "/apply/video",
290
+ body: persistTheme ? { name: themeName, input: localInput } : body,
291
+ signal,
292
+ });
293
293
  return unwrapApplyResult(
294
294
  result,
295
295
  "video",
@@ -297,10 +297,10 @@ export function createBeauticodeActions(dataRootOrOptions) {
297
297
  ? `已将「${result.theme?.name || themeName}」设为背景。`
298
298
  : "已将视频设为背景。",
299
299
  );
300
- }
301
- const applied = persistTheme
302
- ? await resolved.session.applyAndSaveTheme(localInput, themeName)
303
- : await resolved.session.apply(localInput);
300
+ }
301
+ const applied = persistTheme
302
+ ? await resolved.session.applyAndSaveTheme(localInput, themeName)
303
+ : await resolved.session.apply(localInput);
304
304
  return unwrapApplyResult(
305
305
  applied,
306
306
  "video",