beauticode-dsh 1.0.0 → 1.0.1
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 +21 -4
- package/cli.js +21 -4
- 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
|
@@ -125,12 +125,29 @@ function shouldCopy(source) {
|
|
|
125
125
|
return true;
|
|
126
126
|
}
|
|
127
127
|
|
|
128
|
+
async function sameInstalledVersion(dest) {
|
|
129
|
+
try {
|
|
130
|
+
const incoming = JSON.parse(await fsp.readFile(path.join(here, "package.json"), "utf8"));
|
|
131
|
+
const installed = JSON.parse(await fsp.readFile(path.join(dest, "package.json"), "utf8"));
|
|
132
|
+
return (
|
|
133
|
+
incoming.name === installed.name &&
|
|
134
|
+
incoming.version === installed.version &&
|
|
135
|
+
fs.existsSync(path.join(dest, "index.mjs")) &&
|
|
136
|
+
fs.existsSync(path.join(dest, "vendor", "adapter-dsh", "index.js"))
|
|
137
|
+
);
|
|
138
|
+
} catch {
|
|
139
|
+
return false;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
128
143
|
async function copyPackage(dest) {
|
|
144
|
+
if (await sameInstalledVersion(dest)) return false;
|
|
129
145
|
await fsp.rm(dest, { recursive: true, force: true });
|
|
130
146
|
await fsp.cp(here, dest, {
|
|
131
147
|
recursive: true,
|
|
132
148
|
filter: (source) => shouldCopy(source),
|
|
133
149
|
});
|
|
150
|
+
return true;
|
|
134
151
|
}
|
|
135
152
|
|
|
136
153
|
async function ensureEngine(dest) {
|
|
@@ -153,7 +170,7 @@ async function install(opts) {
|
|
|
153
170
|
const homePatch = path.join(dshHome, "cordis.patch.yml");
|
|
154
171
|
|
|
155
172
|
await fsp.mkdir(dest, { recursive: true });
|
|
156
|
-
await copyPackage(dest);
|
|
173
|
+
const copied = await copyPackage(dest);
|
|
157
174
|
await ensureEngine(dest);
|
|
158
175
|
const indexFile = path.join(dest, "index.mjs");
|
|
159
176
|
if (!fs.existsSync(indexFile)) {
|
|
@@ -161,13 +178,13 @@ async function install(opts) {
|
|
|
161
178
|
}
|
|
162
179
|
|
|
163
180
|
if (fs.existsSync(webPackage)) {
|
|
164
|
-
await writePatch(webPatch,
|
|
181
|
+
await writePatch(webPatch, fileUriInsert(toFileUri(indexFile)));
|
|
165
182
|
if (fs.existsSync(homePatch)) {
|
|
166
183
|
const homeRaw = await fsp.readFile(homePatch, "utf8");
|
|
167
184
|
if (hasBridge(homeRaw)) await removePatch(homePatch);
|
|
168
185
|
}
|
|
169
186
|
console.log(`已写入 ${webPatch}`);
|
|
170
|
-
console.log(
|
|
187
|
+
console.log(copied ? `插件已安装到 ${dest}` : `已复用已安装的插件 ${dest}`);
|
|
171
188
|
console.log("请自己运行:npx @deepseek-ai/dsh web");
|
|
172
189
|
return { dest, patch: webPatch };
|
|
173
190
|
}
|
|
@@ -175,7 +192,7 @@ async function install(opts) {
|
|
|
175
192
|
await fsp.mkdir(dshHome, { recursive: true });
|
|
176
193
|
await writePatch(homePatch, fileUriInsert(toFileUri(indexFile)));
|
|
177
194
|
console.log(`DSH web profile 还不存在,已写入 ${homePatch}`);
|
|
178
|
-
console.log(
|
|
195
|
+
console.log(copied ? `插件已安装到 ${dest}` : `已复用已安装的插件 ${dest}`);
|
|
179
196
|
console.log("请自己运行:npx @deepseek-ai/dsh web");
|
|
180
197
|
return { dest, patch: homePatch };
|
|
181
198
|
}
|
package/cli.js
CHANGED
|
@@ -125,12 +125,29 @@ function shouldCopy(source) {
|
|
|
125
125
|
return true;
|
|
126
126
|
}
|
|
127
127
|
|
|
128
|
+
async function sameInstalledVersion(dest) {
|
|
129
|
+
try {
|
|
130
|
+
const incoming = JSON.parse(await fsp.readFile(path.join(here, "package.json"), "utf8"));
|
|
131
|
+
const installed = JSON.parse(await fsp.readFile(path.join(dest, "package.json"), "utf8"));
|
|
132
|
+
return (
|
|
133
|
+
incoming.name === installed.name &&
|
|
134
|
+
incoming.version === installed.version &&
|
|
135
|
+
fs.existsSync(path.join(dest, "index.mjs")) &&
|
|
136
|
+
fs.existsSync(path.join(dest, "vendor", "adapter-dsh", "index.js"))
|
|
137
|
+
);
|
|
138
|
+
} catch {
|
|
139
|
+
return false;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
128
143
|
async function copyPackage(dest) {
|
|
144
|
+
if (await sameInstalledVersion(dest)) return false;
|
|
129
145
|
await fsp.rm(dest, { recursive: true, force: true });
|
|
130
146
|
await fsp.cp(here, dest, {
|
|
131
147
|
recursive: true,
|
|
132
148
|
filter: (source) => shouldCopy(source),
|
|
133
149
|
});
|
|
150
|
+
return true;
|
|
134
151
|
}
|
|
135
152
|
|
|
136
153
|
async function ensureEngine(dest) {
|
|
@@ -153,7 +170,7 @@ async function install(opts) {
|
|
|
153
170
|
const homePatch = path.join(dshHome, "cordis.patch.yml");
|
|
154
171
|
|
|
155
172
|
await fsp.mkdir(dest, { recursive: true });
|
|
156
|
-
await copyPackage(dest);
|
|
173
|
+
const copied = await copyPackage(dest);
|
|
157
174
|
await ensureEngine(dest);
|
|
158
175
|
const indexFile = path.join(dest, "index.mjs");
|
|
159
176
|
if (!fs.existsSync(indexFile)) {
|
|
@@ -161,13 +178,13 @@ async function install(opts) {
|
|
|
161
178
|
}
|
|
162
179
|
|
|
163
180
|
if (fs.existsSync(webPackage)) {
|
|
164
|
-
await writePatch(webPatch,
|
|
181
|
+
await writePatch(webPatch, fileUriInsert(toFileUri(indexFile)));
|
|
165
182
|
if (fs.existsSync(homePatch)) {
|
|
166
183
|
const homeRaw = await fsp.readFile(homePatch, "utf8");
|
|
167
184
|
if (hasBridge(homeRaw)) await removePatch(homePatch);
|
|
168
185
|
}
|
|
169
186
|
console.log(`已写入 ${webPatch}`);
|
|
170
|
-
console.log(
|
|
187
|
+
console.log(copied ? `插件已安装到 ${dest}` : `已复用已安装的插件 ${dest}`);
|
|
171
188
|
console.log("请自己运行:npx @deepseek-ai/dsh web");
|
|
172
189
|
return { dest, patch: webPatch };
|
|
173
190
|
}
|
|
@@ -175,7 +192,7 @@ async function install(opts) {
|
|
|
175
192
|
await fsp.mkdir(dshHome, { recursive: true });
|
|
176
193
|
await writePatch(homePatch, fileUriInsert(toFileUri(indexFile)));
|
|
177
194
|
console.log(`DSH web profile 还不存在,已写入 ${homePatch}`);
|
|
178
|
-
console.log(
|
|
195
|
+
console.log(copied ? `插件已安装到 ${dest}` : `已复用已安装的插件 ${dest}`);
|
|
179
196
|
console.log("请自己运行:npx @deepseek-ai/dsh web");
|
|
180
197
|
return { dest, patch: homePatch };
|
|
181
198
|
}
|
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
|