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 +3 -3
- package/bin/beauticode-dsh +38 -5
- package/cli.js +38 -5
- package/client.js +0 -2
- package/host-apply.mjs +1 -1
- package/index.mjs +5 -1
- package/package.json +1 -1
- package/vendor/adapter-dsh/bridge.js +4 -1
- package/vendor/core/media-server.js +14 -2
- package/themes/internal-beyond/bg-canvas.png +0 -0
package/README.zh-CN.md
CHANGED
|
@@ -8,17 +8,17 @@
|
|
|
8
8
|
|
|
9
9
|
beautiCode **不启动** DeepSeek Harness。请先自己运行 `dsh web`。
|
|
10
10
|
|
|
11
|
-
不需要 fork
|
|
11
|
+
不需要 fork 仓库。一行安装:
|
|
12
12
|
|
|
13
13
|
```sh
|
|
14
|
-
npx
|
|
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
|
|
21
|
+
npx @deepseek-ai/dsh plugin --profile web add beauticode-dsh
|
|
22
22
|
npx @deepseek-ai/dsh web
|
|
23
23
|
```
|
|
24
24
|
|
package/bin/beauticode-dsh
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
|
-
|
|
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,
|
|
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(
|
|
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(
|
|
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
|
-
|
|
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,
|
|
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(
|
|
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(
|
|
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
|
|
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:
|
|
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
|
@@ -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:
|
|
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
|
-
|
|
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;
|
|
Binary file
|