beauticode-dsh 1.0.0 → 1.0.2

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
@@ -8,17 +8,17 @@
8
8
 
9
9
  beautiCode **不启动** DeepSeek Harness。请先自己运行 `dsh web`。
10
10
 
11
- 不需要 fork 仓库。发布到 npm 之后,一行安装:
11
+ 不需要 fork 仓库。一行安装:
12
12
 
13
13
  ```sh
14
- npx @beauticode/dsh-plugin
14
+ npx beauticode-dsh
15
15
  npx @deepseek-ai/dsh web
16
16
  ```
17
17
 
18
18
  已有 pnpm 时也可以:
19
19
 
20
20
  ```sh
21
- npx @deepseek-ai/dsh plugin --profile web add @beauticode/dsh-plugin
21
+ npx @deepseek-ai/dsh plugin --profile web add beauticode-dsh
22
22
  npx @deepseek-ai/dsh web
23
23
  ```
24
24
 
@@ -11,7 +11,23 @@ import os from "node:os";
11
11
  import path from "node:path";
12
12
  import { fileURLToPath, pathToFileURL } from "node:url";
13
13
 
14
- const here = path.dirname(fileURLToPath(import.meta.url));
14
+ function findPackageRoot(startDir) {
15
+ let dir = startDir;
16
+ for (let i = 0; i < 5; i += 1) {
17
+ if (
18
+ fs.existsSync(path.join(dir, "package.json")) &&
19
+ fs.existsSync(path.join(dir, "index.mjs"))
20
+ ) {
21
+ return dir;
22
+ }
23
+ const parent = path.dirname(dir);
24
+ if (parent === dir) break;
25
+ dir = parent;
26
+ }
27
+ return startDir;
28
+ }
29
+
30
+ const here = findPackageRoot(path.dirname(fileURLToPath(import.meta.url)));
15
31
  const pluginName = "beauticode-dsh";
16
32
  const bridgeId = "beauticode-bridge";
17
33
 
@@ -125,12 +141,29 @@ function shouldCopy(source) {
125
141
  return true;
126
142
  }
127
143
 
144
+ async function sameInstalledVersion(dest) {
145
+ try {
146
+ const incoming = JSON.parse(await fsp.readFile(path.join(here, "package.json"), "utf8"));
147
+ const installed = JSON.parse(await fsp.readFile(path.join(dest, "package.json"), "utf8"));
148
+ return (
149
+ incoming.name === installed.name &&
150
+ incoming.version === installed.version &&
151
+ fs.existsSync(path.join(dest, "index.mjs")) &&
152
+ fs.existsSync(path.join(dest, "vendor", "adapter-dsh", "index.js"))
153
+ );
154
+ } catch {
155
+ return false;
156
+ }
157
+ }
158
+
128
159
  async function copyPackage(dest) {
160
+ if (await sameInstalledVersion(dest)) return false;
129
161
  await fsp.rm(dest, { recursive: true, force: true });
130
162
  await fsp.cp(here, dest, {
131
163
  recursive: true,
132
164
  filter: (source) => shouldCopy(source),
133
165
  });
166
+ return true;
134
167
  }
135
168
 
136
169
  async function ensureEngine(dest) {
@@ -153,7 +186,7 @@ async function install(opts) {
153
186
  const homePatch = path.join(dshHome, "cordis.patch.yml");
154
187
 
155
188
  await fsp.mkdir(dest, { recursive: true });
156
- await copyPackage(dest);
189
+ const copied = await copyPackage(dest);
157
190
  await ensureEngine(dest);
158
191
  const indexFile = path.join(dest, "index.mjs");
159
192
  if (!fs.existsSync(indexFile)) {
@@ -161,13 +194,13 @@ async function install(opts) {
161
194
  }
162
195
 
163
196
  if (fs.existsSync(webPackage)) {
164
- await writePatch(webPatch, packageInsert());
197
+ await writePatch(webPatch, fileUriInsert(toFileUri(indexFile)));
165
198
  if (fs.existsSync(homePatch)) {
166
199
  const homeRaw = await fsp.readFile(homePatch, "utf8");
167
200
  if (hasBridge(homeRaw)) await removePatch(homePatch);
168
201
  }
169
202
  console.log(`已写入 ${webPatch}`);
170
- console.log(`插件已复制到 ${dest}`);
203
+ console.log(copied ? `插件已安装到 ${dest}` : `已复用已安装的插件 ${dest}`);
171
204
  console.log("请自己运行:npx @deepseek-ai/dsh web");
172
205
  return { dest, patch: webPatch };
173
206
  }
@@ -175,7 +208,7 @@ async function install(opts) {
175
208
  await fsp.mkdir(dshHome, { recursive: true });
176
209
  await writePatch(homePatch, fileUriInsert(toFileUri(indexFile)));
177
210
  console.log(`DSH web profile 还不存在,已写入 ${homePatch}`);
178
- console.log(`插件已复制到 ${dest}`);
211
+ console.log(copied ? `插件已安装到 ${dest}` : `已复用已安装的插件 ${dest}`);
179
212
  console.log("请自己运行:npx @deepseek-ai/dsh web");
180
213
  return { dest, patch: homePatch };
181
214
  }
package/cli.js CHANGED
@@ -11,7 +11,23 @@ import os from "node:os";
11
11
  import path from "node:path";
12
12
  import { fileURLToPath, pathToFileURL } from "node:url";
13
13
 
14
- const here = path.dirname(fileURLToPath(import.meta.url));
14
+ function findPackageRoot(startDir) {
15
+ let dir = startDir;
16
+ for (let i = 0; i < 5; i += 1) {
17
+ if (
18
+ fs.existsSync(path.join(dir, "package.json")) &&
19
+ fs.existsSync(path.join(dir, "index.mjs"))
20
+ ) {
21
+ return dir;
22
+ }
23
+ const parent = path.dirname(dir);
24
+ if (parent === dir) break;
25
+ dir = parent;
26
+ }
27
+ return startDir;
28
+ }
29
+
30
+ const here = findPackageRoot(path.dirname(fileURLToPath(import.meta.url)));
15
31
  const pluginName = "beauticode-dsh";
16
32
  const bridgeId = "beauticode-bridge";
17
33
 
@@ -125,12 +141,29 @@ function shouldCopy(source) {
125
141
  return true;
126
142
  }
127
143
 
144
+ async function sameInstalledVersion(dest) {
145
+ try {
146
+ const incoming = JSON.parse(await fsp.readFile(path.join(here, "package.json"), "utf8"));
147
+ const installed = JSON.parse(await fsp.readFile(path.join(dest, "package.json"), "utf8"));
148
+ return (
149
+ incoming.name === installed.name &&
150
+ incoming.version === installed.version &&
151
+ fs.existsSync(path.join(dest, "index.mjs")) &&
152
+ fs.existsSync(path.join(dest, "vendor", "adapter-dsh", "index.js"))
153
+ );
154
+ } catch {
155
+ return false;
156
+ }
157
+ }
158
+
128
159
  async function copyPackage(dest) {
160
+ if (await sameInstalledVersion(dest)) return false;
129
161
  await fsp.rm(dest, { recursive: true, force: true });
130
162
  await fsp.cp(here, dest, {
131
163
  recursive: true,
132
164
  filter: (source) => shouldCopy(source),
133
165
  });
166
+ return true;
134
167
  }
135
168
 
136
169
  async function ensureEngine(dest) {
@@ -153,7 +186,7 @@ async function install(opts) {
153
186
  const homePatch = path.join(dshHome, "cordis.patch.yml");
154
187
 
155
188
  await fsp.mkdir(dest, { recursive: true });
156
- await copyPackage(dest);
189
+ const copied = await copyPackage(dest);
157
190
  await ensureEngine(dest);
158
191
  const indexFile = path.join(dest, "index.mjs");
159
192
  if (!fs.existsSync(indexFile)) {
@@ -161,13 +194,13 @@ async function install(opts) {
161
194
  }
162
195
 
163
196
  if (fs.existsSync(webPackage)) {
164
- await writePatch(webPatch, packageInsert());
197
+ await writePatch(webPatch, fileUriInsert(toFileUri(indexFile)));
165
198
  if (fs.existsSync(homePatch)) {
166
199
  const homeRaw = await fsp.readFile(homePatch, "utf8");
167
200
  if (hasBridge(homeRaw)) await removePatch(homePatch);
168
201
  }
169
202
  console.log(`已写入 ${webPatch}`);
170
- console.log(`插件已复制到 ${dest}`);
203
+ console.log(copied ? `插件已安装到 ${dest}` : `已复用已安装的插件 ${dest}`);
171
204
  console.log("请自己运行:npx @deepseek-ai/dsh web");
172
205
  return { dest, patch: webPatch };
173
206
  }
@@ -175,7 +208,7 @@ async function install(opts) {
175
208
  await fsp.mkdir(dshHome, { recursive: true });
176
209
  await writePatch(homePatch, fileUriInsert(toFileUri(indexFile)));
177
210
  console.log(`DSH web profile 还不存在,已写入 ${homePatch}`);
178
- console.log(`插件已复制到 ${dest}`);
211
+ console.log(copied ? `插件已安装到 ${dest}` : `已复用已安装的插件 ${dest}`);
179
212
  console.log("请自己运行:npx @deepseek-ai/dsh web");
180
213
  return { dest, patch: homePatch };
181
214
  }
package/client.js CHANGED
@@ -189,7 +189,6 @@ html[data-bc-fish="true"] #root{opacity:0!important;visibility:hidden!important;
189
189
  function loadImage(url) {
190
190
  const image = new Image();
191
191
  image.alt = "";
192
- image.crossOrigin = "anonymous";
193
192
  image.decoding = "async";
194
193
  return new Promise((resolve, reject) => {
195
194
  image.onload = () => resolve(image);
@@ -298,7 +297,6 @@ html[data-bc-fish="true"] #root{opacity:0!important;visibility:hidden!important;
298
297
  video.playsInline = true;
299
298
  video.preload = "auto";
300
299
  video.poster = payload.imageUrl;
301
- video.crossOrigin = "anonymous";
302
300
  video.src = payload.videoUrl;
303
301
  node.replaceChildren(image, video);
304
302
  await waitForVideo(video);
package/host-apply.mjs CHANGED
@@ -10,7 +10,7 @@ import { canvasImagePath } from "./presets.mjs";
10
10
  const sessions = new Map();
11
11
 
12
12
  export const ENGINE_MISSING_MESSAGE =
13
- "beautiCode 插件未能加载本机导入引擎。请执行 npx @beauticode/dsh-plugin,或从完整安装目录加载桥接。";
13
+ "beautiCode 插件未能加载本机导入引擎。请执行 npx beauticode-dsh,或从完整安装目录加载桥接。";
14
14
 
15
15
  export function resolvePluginBaseUrl(ctx) {
16
16
  const port = ctx?.webServer?.port;
package/index.mjs CHANGED
@@ -168,12 +168,16 @@ function publicStatus(current, modes, clients, clientStates) {
168
168
  const playback =
169
169
  activeAcks.find((ack) => ack.ok === true && ack.playback?.hasVideo === true)
170
170
  ?.playback ?? null;
171
+ const failedAcks = activeAcks.filter((ack) => ack.ok !== true);
171
172
  return {
172
173
  ok: true,
173
174
  connectedClients: clients.size,
174
175
  current,
175
176
  readyClients: activeAcks.filter((ack) => ack.ok === true).length,
176
- failedClients: activeAcks.filter((ack) => ack.ok !== true).length,
177
+ failedClients: failedAcks.length,
178
+ lastRenderError:
179
+ failedAcks.find((ack) => typeof ack.error === "string" && ack.error)?.error ??
180
+ null,
177
181
  visibleClients: activeAcks.filter((ack) => ack.ok === true && ack.visible === true).length,
178
182
  modeReadyClients: modeReady.length,
179
183
  blockedClients: modeReady.filter((ack) => ack.blocked === true).length,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "beauticode-dsh",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "Cordis plugin: image/video backgrounds for DeepSeek Harness web.",
5
5
  "type": "module",
6
6
  "main": "./index.mjs",
@@ -120,9 +120,12 @@ export class DshHostApplier {
120
120
  };
121
121
  }
122
122
  if (currentMatches && last.failedClients > 0 && last.readyClients === 0) {
123
+ const detail = typeof last.lastRenderError === "string" && last.lastRenderError
124
+ ? ` (${last.lastRenderError})`
125
+ : "";
123
126
  return {
124
127
  status: "fail",
125
- reason: "DeepSeek Harness client failed to render the background.",
128
+ reason: `DeepSeek Harness client failed to render the background.${detail}`,
126
129
  details: { ...last },
127
130
  };
128
131
  }
@@ -50,12 +50,24 @@ async function hashOpenedFile(handle, size) {
50
50
  }
51
51
  return hash.digest("hex");
52
52
  }
53
- /** Exact match or app://* prefix (hub is loopback-only). */
53
+ function isLoopbackHttpOrigin(origin) {
54
+ try {
55
+ const url = new URL(origin);
56
+ return (url.protocol === "http:" &&
57
+ ["127.0.0.1", "localhost", "[::1]"].includes(url.hostname.toLowerCase()));
58
+ }
59
+ catch {
60
+ return false;
61
+ }
62
+ }
63
+ /** Exact match, loopback HTTP, or app://* prefix (hub is loopback-only). */
54
64
  function matchTrustedOrigin(origin, trusted) {
55
65
  if (!origin)
56
66
  return null;
57
67
  if (trusted.has(origin))
58
68
  return origin;
69
+ if (isLoopbackHttpOrigin(origin))
70
+ return origin;
59
71
  for (const prefix of TRUSTED_ORIGIN_PREFIXES) {
60
72
  if (origin.startsWith(prefix))
61
73
  return origin;
@@ -316,7 +328,7 @@ export class LoopbackMediaHub {
316
328
  queryToken = "";
317
329
  }
318
330
  const tokenOk = headerToken === pathToken || queryToken === pathToken;
319
- if ((origin && !trustedOrigin) || !tokenOk) {
331
+ if ((origin && !trustedOrigin && !isLoopbackHttpOrigin(origin)) || !tokenOk) {
320
332
  response.writeHead(403, { "Cache-Control": "no-store" });
321
333
  response.end();
322
334
  return;