dsh-cliproxyapi-pro 1.5.0 → 1.6.0
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/CHANGELOG.md +17 -0
- package/README.en.md +32 -17
- package/README.md +32 -17
- package/lib/client.js +634 -22
- package/lib/index.js +24 -9
- package/lib/updater.js +6 -3
- package/package.json +1 -1
package/lib/index.js
CHANGED
|
@@ -1695,18 +1695,33 @@ function admitRequest(ctx, req, res, expectedMethod) {
|
|
|
1695
1695
|
return true;
|
|
1696
1696
|
}
|
|
1697
1697
|
|
|
1698
|
-
/**
|
|
1698
|
+
/** Same authority, using the scheme the Origin itself declares (host comparison only). */
|
|
1699
|
+
function sameAuthorityOrigin(origin, host) {
|
|
1700
|
+
let originUrl;
|
|
1701
|
+
try { originUrl = new URL(origin); } catch { return false; }
|
|
1702
|
+
if (originUrl.protocol !== "http:" && originUrl.protocol !== "https:") return false;
|
|
1703
|
+
if (originUrl.username || originUrl.password) return false;
|
|
1704
|
+
try {
|
|
1705
|
+
return originUrl.host === new URL(`${originUrl.protocol}//${host}`).host;
|
|
1706
|
+
} catch {
|
|
1707
|
+
return false;
|
|
1708
|
+
}
|
|
1709
|
+
}
|
|
1710
|
+
|
|
1711
|
+
/**
|
|
1712
|
+
* Update writes need an authenticated browser request. The host connection
|
|
1713
|
+
* service already enforces the Host/Origin fence and its session cookie, so
|
|
1714
|
+
* this only narrows it: when a browser sends an Origin it must belong to this
|
|
1715
|
+
* listener. A carrier that omits Origin (the desktop shell proxies API calls
|
|
1716
|
+
* without it) is allowed, because the session cookie is still required and an
|
|
1717
|
+
* unauthenticated caller is rejected before reaching the route.
|
|
1718
|
+
*/
|
|
1699
1719
|
function admitUpdateRequest(ctx, req, res, method) {
|
|
1700
1720
|
if (!admitRequest(ctx, req, res, method)) return false;
|
|
1701
1721
|
if (method === "GET") return true;
|
|
1702
|
-
const
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
const target = new URL(`${protocol}//${req.headers.host}`);
|
|
1706
|
-
if (!req.headers.host || origin.origin !== target.origin || req.headers.origin !== origin.origin || origin.username || origin.password) {
|
|
1707
|
-
throw new Error("Origin mismatch");
|
|
1708
|
-
}
|
|
1709
|
-
} catch {
|
|
1722
|
+
const host = req.headers.host;
|
|
1723
|
+
const origin = req.headers.origin;
|
|
1724
|
+
if (host === undefined || origin !== undefined && !sameAuthorityOrigin(origin, host)) {
|
|
1710
1725
|
sendJson(res, 403, { ok: false, errorCode: "forbidden-origin", error: "Same-origin browser request required" });
|
|
1711
1726
|
return false;
|
|
1712
1727
|
}
|
package/lib/updater.js
CHANGED
|
@@ -13,8 +13,9 @@ export const UPDATE_REGISTRIES = Object.freeze({
|
|
|
13
13
|
export const UPDATE_TAGS = Object.freeze({ stable: "latest", beta: "beta", dev: "dev" });
|
|
14
14
|
export const UPDATE_INTERVAL_MS = 6 * 60 * 60 * 1000;
|
|
15
15
|
export const DEFAULT_UPDATE_SETTINGS = Object.freeze({
|
|
16
|
-
autoCheck: true, autoDownload: false, channel: "stable", region: "auto",
|
|
16
|
+
autoCheck: true, autoDownload: false, autoInstall: false, channel: "stable", region: "auto",
|
|
17
17
|
});
|
|
18
|
+
const BOOLEAN_SETTINGS = ["autoCheck", "autoDownload", "autoInstall"];
|
|
18
19
|
const MAX_METADATA_BYTES = 512 * 1024;
|
|
19
20
|
const MAX_PACKAGE_BYTES = 8 * 1024 * 1024;
|
|
20
21
|
const MAX_UNPACKED_BYTES = 16 * 1024 * 1024;
|
|
@@ -29,6 +30,8 @@ export function normalizeUpdateSettings(raw = {}) {
|
|
|
29
30
|
return {
|
|
30
31
|
autoCheck: typeof raw?.autoCheck === "boolean" ? raw.autoCheck : true,
|
|
31
32
|
autoDownload: raw?.autoDownload === true,
|
|
33
|
+
// Consumed by the Web client, which delegates installation to dshmarket.
|
|
34
|
+
autoInstall: raw?.autoInstall === true,
|
|
32
35
|
channel: Object.hasOwn(UPDATE_TAGS, raw?.channel ?? "") ? raw.channel : "stable",
|
|
33
36
|
region: ["auto", "global", "cn"].includes(raw?.region) ? raw.region : "auto",
|
|
34
37
|
};
|
|
@@ -38,7 +41,7 @@ export function loadUpdateSettings(file) {
|
|
|
38
41
|
try {
|
|
39
42
|
const raw = JSON.parse(readFileSync(file, "utf8"));
|
|
40
43
|
if (!raw || typeof raw !== "object" || Array.isArray(raw) || raw.version !== 1 ||
|
|
41
|
-
|
|
44
|
+
BOOLEAN_SETTINGS.some((key) => raw[key] !== undefined && typeof raw[key] !== "boolean") ||
|
|
42
45
|
raw.channel !== undefined && !Object.hasOwn(UPDATE_TAGS, raw.channel) ||
|
|
43
46
|
raw.region !== undefined && !["auto", "global", "cn"].includes(raw.region)) fail("invalid-settings");
|
|
44
47
|
return normalizeUpdateSettings(raw);
|
|
@@ -340,7 +343,7 @@ export function createPluginUpdater(deps) {
|
|
|
340
343
|
if (!patch || typeof patch !== "object" || Array.isArray(patch)) fail("invalid-settings");
|
|
341
344
|
if (Object.keys(patch).some((key) => !Object.hasOwn(DEFAULT_UPDATE_SETTINGS, key))) fail("invalid-settings");
|
|
342
345
|
if (Object.hasOwn(patch, "channel") && !Object.hasOwn(UPDATE_TAGS, patch.channel) || Object.hasOwn(patch, "region") && !["auto", "global", "cn"].includes(patch.region)) fail("invalid-settings");
|
|
343
|
-
for (const key of
|
|
346
|
+
for (const key of BOOLEAN_SETTINGS) if (Object.hasOwn(patch, key) && typeof patch[key] !== "boolean") fail("invalid-settings");
|
|
344
347
|
const next = normalizeUpdateSettings({ ...settings, ...patch });
|
|
345
348
|
saving = true;
|
|
346
349
|
try {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-cliproxyapi-pro",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.6.0",
|
|
4
4
|
"description": "Auto-discovery CLIProxyAPI provider and management UI for DeepSeek Harness — multiple accounts, dynamic model sync, capability detection, and visual settings.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"dsh",
|