dsh-opendesign-corouter 0.1.5 → 0.1.6
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.md +4 -4
- package/lib/catalog.d.ts +9 -8
- package/lib/client.js +23 -4
- package/lib/device-auth.d.ts +3 -3
- package/lib/generated/typert.host.js +11 -4
- package/lib/generated/typert.remote-client.js +11 -4
- package/lib/index.js +24 -10
- package/lib/index.js.map +2 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -32,7 +32,7 @@ dsh plugin --profile web add dsh-opendesign-corouter
|
|
|
32
32
|
也可打开 [Actions → CI](https://github.com/KouzakiUmi/dsh-opendesign-corouter/actions/workflows/ci.yml),从成功构建下载 **`dsh-opendesign-corouter-build`** artifact。登录 GitHub 后解压 ZIP,取得 `.tgz` 与 `.sha256`,再安装本地包:
|
|
33
33
|
|
|
34
34
|
```console
|
|
35
|
-
dsh plugin --profile web add /absolute/path/to/dsh-opendesign-corouter-0.1.
|
|
35
|
+
dsh plugin --profile web add /absolute/path/to/dsh-opendesign-corouter-0.1.6.tgz
|
|
36
36
|
```
|
|
37
37
|
|
|
38
38
|
`web` 只是示例,请替换为目标 Profile。Desktop 使用桌面安装器提供的 `dsh` 入口;独立公共 CLI 不能代管保留的 `desktop` Profile。安装后的启用与重载按目标 DSH 的管理流程进行。
|
|
@@ -40,7 +40,7 @@ dsh plugin --profile web add /absolute/path/to/dsh-opendesign-corouter-0.1.5.tgz
|
|
|
40
40
|
### 2. 配置连接
|
|
41
41
|
|
|
42
42
|
1. 打开 **设置 → OpenDesign CoRouter → 连接与登录**。
|
|
43
|
-
2. 点击
|
|
43
|
+
2. 点击 **开始设备授权**,取得授权码后自动打开临时 Chrome 官方授权页,核对并确认;打开失败可用 **在新窗口打开授权页** 重试,也可复制链接到常用浏览器,或单独配置工作空间 API Key / 沿用 `COROUTER_API_KEY`。
|
|
44
44
|
3. 返回设置页等待保存成功。额度默认优先读取桌面登录态;要明确使用设备授权的账号,可关闭桌面优先。
|
|
45
45
|
4. 回到模型选择器,选择 **OpenDesign CoRouter · 套餐赠送** 或 **OpenDesign CoRouter · 付费模型**。
|
|
46
46
|
|
|
@@ -52,8 +52,8 @@ dsh plugin --profile web add /absolute/path/to/dsh-opendesign-corouter-0.1.5.tgz
|
|
|
52
52
|
|
|
53
53
|
| Provider | 模型数 | 用途 |
|
|
54
54
|
| --- | ---: | --- |
|
|
55
|
-
| `opendesign-corouter-plan` |
|
|
56
|
-
| `opendesign-corouter-paid` |
|
|
55
|
+
| `opendesign-corouter-plan` | 13 | Core / Design Plan 附赠通道,含预检确认覆盖的 MiniMax M3.1 Flash |
|
|
56
|
+
| `opendesign-corouter-paid` | 25 | Plan 套餐模型及其他钱包付费模型 |
|
|
57
57
|
|
|
58
58
|
上表为内置目录。模型页可从 OpenAI `/models` 端口刷新,逐个启用或停用模型,并配置温度、top-p、默认输出上限、上下文预算及思考深度。停用同时影响模型选择器和直接调用;参数会保存并应用到实际请求。媒体生成接口不在对话目录中,未知能力不按名称猜测。
|
|
59
59
|
|
package/lib/catalog.d.ts
CHANGED
|
@@ -16,16 +16,17 @@
|
|
|
16
16
|
* 分组语义(重要):`plan`/`paid` 是**本插件本地目录分类**,用于把“套餐赠送通道”与
|
|
17
17
|
* “其余付费通道”拆成两个 Provider,不是上游强制计费契约。最终可用性、扣哪个额度池、
|
|
18
18
|
* 是否先扣 Design Plan 额度再用套餐模型/钱包额度,全部由服务端按账号套餐决定。
|
|
19
|
-
*
|
|
20
|
-
*
|
|
19
|
+
* 2026-10-27 官方 GET /v1/models 实测补齐五个 ID,现为 plan 13 + paid 25。
|
|
20
|
+
* 同日桌面 Vela 按模型 billing preflight:M3.1 Flash 的 modelCovered=true /
|
|
21
|
+
* funding=coding_plan,新增于附赠通道;其余四项为 false / wallet,归付费通道。
|
|
22
|
+
* 此分类以当次工作区证据为依据,不保证其他账号或未来套餐权益。
|
|
23
|
+
* 新增项证据及名称来源见 docs/client-evidence.md;不从型号名推断能力。
|
|
21
24
|
*
|
|
22
|
-
*
|
|
23
|
-
* - 套餐模型组中尚未公开精确 ID 的 `Muse Spark 1.3`、`Gemini 4 Argon`:
|
|
24
|
-
* 前者详情页没有 `data-model`/模型 ID,后者在模型目录里没有详情页。
|
|
25
|
+
* 未收录:
|
|
25
26
|
* - 媒体模型 `GPT Image 2`、`Nano Banana 2`、`Seedream 5 Lite / Pro`:
|
|
26
27
|
* 走 `/api/v1/media/*`,不应出现在对话模型列表里,避免选中后 chat 请求必败。
|
|
27
28
|
*
|
|
28
|
-
* `paid`
|
|
29
|
+
* `paid` 25 款及新增 M3.1 Flash 的能力字段一律缺省:没有可核实的能力数值,
|
|
29
30
|
* 不按名称推断图像能力,也不给未知项填 `['text']` 谎称不支持图像。
|
|
30
31
|
*/
|
|
31
32
|
export interface CatalogModel {
|
|
@@ -38,8 +39,8 @@ export interface CatalogModel {
|
|
|
38
39
|
reasoningEfforts?: readonly string[];
|
|
39
40
|
}
|
|
40
41
|
/**
|
|
41
|
-
*
|
|
42
|
-
* 其余
|
|
42
|
+
* `plan` 为官网 12 款 Core / Design Plan 模型,加预检确认覆盖的 M3.1 Flash;
|
|
43
|
+
* 其余 25 项归 `paid`(Plan / 钱包付费通道)。
|
|
43
44
|
*/
|
|
44
45
|
export declare const MODELS: readonly CatalogModel[];
|
|
45
46
|
export declare function modelsFor(group: 'plan' | 'paid'): readonly CatalogModel[];
|
package/lib/client.js
CHANGED
|
@@ -19927,22 +19927,29 @@ function record2(value) {
|
|
|
19927
19927
|
}
|
|
19928
19928
|
|
|
19929
19929
|
// src/device-auth.ts
|
|
19930
|
-
function validateActivationUrl(value, userCode) {
|
|
19930
|
+
function validateActivationUrl(value, userCode, deviceId) {
|
|
19931
19931
|
if (typeof value !== "string" || value.length > 512 || !/^https:\/\/open-design\.ai\/cloud\/cli\/activate(?:\?[^#]*)?$/u.test(value) || /[\s\\]/u.test(value)) return null;
|
|
19932
19932
|
try {
|
|
19933
19933
|
const url2 = new URL(value);
|
|
19934
19934
|
if (url2.origin !== "https://open-design.ai" || url2.pathname !== "/cloud/cli/activate" || url2.username || url2.password || url2.hash) return null;
|
|
19935
19935
|
const entries = [...url2.searchParams];
|
|
19936
|
-
if (entries.length
|
|
19937
|
-
|
|
19936
|
+
if (entries.length === 2) {
|
|
19937
|
+
if (entries.some(([key]) => key !== "deviceId" && key !== "userCode")) return null;
|
|
19938
|
+
const id = url2.searchParams.get("deviceId");
|
|
19939
|
+
const code = url2.searchParams.get("userCode");
|
|
19940
|
+
if (!validDeviceId(id) || !validUserCode(code) || deviceId !== void 0 && id !== deviceId || userCode !== void 0 && code !== userCode) return null;
|
|
19941
|
+
} else if (entries.length === 1) {
|
|
19938
19942
|
const entry = entries[0];
|
|
19939
19943
|
if (!["code", "user_code"].includes(entry[0]) || !validUserCode(entry[1]) || userCode !== void 0 && entry[1] !== userCode) return null;
|
|
19940
|
-
}
|
|
19944
|
+
} else if (entries.length > 2) return null;
|
|
19941
19945
|
return url2.href;
|
|
19942
19946
|
} catch {
|
|
19943
19947
|
return null;
|
|
19944
19948
|
}
|
|
19945
19949
|
}
|
|
19950
|
+
function validDeviceId(value) {
|
|
19951
|
+
return typeof value === "string" && /^[a-z0-9_-]{1,200}$/iu.test(value);
|
|
19952
|
+
}
|
|
19946
19953
|
function validUserCode(value) {
|
|
19947
19954
|
return typeof value === "string" && /^[a-z0-9][a-z0-9-]{3,31}$/iu.test(value);
|
|
19948
19955
|
}
|
|
@@ -21154,6 +21161,7 @@ function Connection({ status, formSnapshot, setFormField, pendingField, caller,
|
|
|
21154
21161
|
const [activationNotice, setActivationNotice] = React.useState(null);
|
|
21155
21162
|
const activationJob = React.useRef(null);
|
|
21156
21163
|
const activationToken = React.useRef(0);
|
|
21164
|
+
const autoOpenPending = React.useRef(false);
|
|
21157
21165
|
React.useEffect(() => () => {
|
|
21158
21166
|
actionVersion.current += 1;
|
|
21159
21167
|
}, []);
|
|
@@ -21172,6 +21180,7 @@ function Connection({ status, formSnapshot, setFormField, pendingField, caller,
|
|
|
21172
21180
|
if (status === void 0 || busy || keyBusy) return;
|
|
21173
21181
|
const version2 = ++actionVersion.current;
|
|
21174
21182
|
setBusy(true);
|
|
21183
|
+
autoOpenPending.current = true;
|
|
21175
21184
|
setNotice({ kind: "status", text: "\u6B63\u5728\u7533\u8BF7\u8BBE\u5907\u6388\u6743\u2026" });
|
|
21176
21185
|
try {
|
|
21177
21186
|
const next = await caller("startLogin", { expectedRevision: status.revision });
|
|
@@ -21180,6 +21189,7 @@ function Connection({ status, formSnapshot, setFormField, pendingField, caller,
|
|
|
21180
21189
|
setActivationNotice(null);
|
|
21181
21190
|
await (next.state === "success" ? refreshAfterLogin() : loadStatus());
|
|
21182
21191
|
} catch {
|
|
21192
|
+
autoOpenPending.current = false;
|
|
21183
21193
|
if (mounted.current && version2 === actionVersion.current) setNotice({ kind: "error", text: "\u65E0\u6CD5\u542F\u52A8\u767B\u5F55\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002" });
|
|
21184
21194
|
} finally {
|
|
21185
21195
|
if (mounted.current && version2 === actionVersion.current) setBusy(false);
|
|
@@ -21240,6 +21250,15 @@ function Connection({ status, formSnapshot, setFormField, pendingField, caller,
|
|
|
21240
21250
|
if (mounted.current && activationToken.current === token) setOpening(false);
|
|
21241
21251
|
}
|
|
21242
21252
|
};
|
|
21253
|
+
React.useEffect(() => {
|
|
21254
|
+
if (!autoOpenPending.current || busy || keyBusy) return;
|
|
21255
|
+
if (state === "waiting") {
|
|
21256
|
+
autoOpenPending.current = false;
|
|
21257
|
+
void openActivation();
|
|
21258
|
+
} else if (state === "error" || state === "cancelled" || state === "success") {
|
|
21259
|
+
autoOpenPending.current = false;
|
|
21260
|
+
}
|
|
21261
|
+
}, [state, login?.jobId, busy, keyBusy]);
|
|
21243
21262
|
const desktopChecked = formSnapshot.value?.useDesktopCredential ?? status?.config.useDesktopCredential ?? true;
|
|
21244
21263
|
return h(
|
|
21245
21264
|
React.Fragment,
|
package/lib/device-auth.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ export interface DeviceTokens {
|
|
|
3
3
|
runtimeKey: string;
|
|
4
4
|
}
|
|
5
5
|
export declare const DEVICE_AUTH_ENDPOINT = "https://amr-api.open-design.ai/api/v1/cli/device-authorizations";
|
|
6
|
-
export declare const DEVICE_AUTH_PLUGIN_VERSION = "0.1.
|
|
6
|
+
export declare const DEVICE_AUTH_PLUGIN_VERSION = "0.1.6";
|
|
7
7
|
export declare const DEVICE_REQUEST_TIMEOUT_MS = 20000;
|
|
8
8
|
/** One bounded launch step of the temporary activation window. */
|
|
9
9
|
export declare const DEVICE_OPEN_TIMEOUT_MS = 30000;
|
|
@@ -14,8 +14,8 @@ export declare class DeviceAuthError extends Error {
|
|
|
14
14
|
readonly code: string;
|
|
15
15
|
constructor(code: string);
|
|
16
16
|
}
|
|
17
|
-
/** Strict public-link allowlist:
|
|
18
|
-
export declare function validateActivationUrl(value: unknown, userCode?: string): string | null;
|
|
17
|
+
/** Strict public-link allowlist: a legacy code or the public deviceId/userCode pair. */
|
|
18
|
+
export declare function validateActivationUrl(value: unknown, userCode?: string, deviceId?: string): string | null;
|
|
19
19
|
export interface DeviceAuthorization {
|
|
20
20
|
deviceId: string;
|
|
21
21
|
deviceSecret: string;
|
|
@@ -8,22 +8,29 @@ function record(value) {
|
|
|
8
8
|
}
|
|
9
9
|
|
|
10
10
|
// src/device-auth.ts
|
|
11
|
-
function validateActivationUrl(value, userCode) {
|
|
11
|
+
function validateActivationUrl(value, userCode, deviceId) {
|
|
12
12
|
if (typeof value !== "string" || value.length > 512 || !/^https:\/\/open-design\.ai\/cloud\/cli\/activate(?:\?[^#]*)?$/u.test(value) || /[\s\\]/u.test(value)) return null;
|
|
13
13
|
try {
|
|
14
14
|
const url = new URL(value);
|
|
15
15
|
if (url.origin !== "https://open-design.ai" || url.pathname !== "/cloud/cli/activate" || url.username || url.password || url.hash) return null;
|
|
16
16
|
const entries = [...url.searchParams];
|
|
17
|
-
if (entries.length
|
|
18
|
-
|
|
17
|
+
if (entries.length === 2) {
|
|
18
|
+
if (entries.some(([key]) => key !== "deviceId" && key !== "userCode")) return null;
|
|
19
|
+
const id = url.searchParams.get("deviceId");
|
|
20
|
+
const code = url.searchParams.get("userCode");
|
|
21
|
+
if (!validDeviceId(id) || !validUserCode(code) || deviceId !== void 0 && id !== deviceId || userCode !== void 0 && code !== userCode) return null;
|
|
22
|
+
} else if (entries.length === 1) {
|
|
19
23
|
const entry = entries[0];
|
|
20
24
|
if (!["code", "user_code"].includes(entry[0]) || !validUserCode(entry[1]) || userCode !== void 0 && entry[1] !== userCode) return null;
|
|
21
|
-
}
|
|
25
|
+
} else if (entries.length > 2) return null;
|
|
22
26
|
return url.href;
|
|
23
27
|
} catch {
|
|
24
28
|
return null;
|
|
25
29
|
}
|
|
26
30
|
}
|
|
31
|
+
function validDeviceId(value) {
|
|
32
|
+
return typeof value === "string" && /^[a-z0-9_-]{1,200}$/iu.test(value);
|
|
33
|
+
}
|
|
27
34
|
function validUserCode(value) {
|
|
28
35
|
return typeof value === "string" && /^[a-z0-9][a-z0-9-]{3,31}$/iu.test(value);
|
|
29
36
|
}
|
|
@@ -8,22 +8,29 @@ function record(value) {
|
|
|
8
8
|
}
|
|
9
9
|
|
|
10
10
|
// src/device-auth.ts
|
|
11
|
-
function validateActivationUrl(value, userCode) {
|
|
11
|
+
function validateActivationUrl(value, userCode, deviceId) {
|
|
12
12
|
if (typeof value !== "string" || value.length > 512 || !/^https:\/\/open-design\.ai\/cloud\/cli\/activate(?:\?[^#]*)?$/u.test(value) || /[\s\\]/u.test(value)) return null;
|
|
13
13
|
try {
|
|
14
14
|
const url = new URL(value);
|
|
15
15
|
if (url.origin !== "https://open-design.ai" || url.pathname !== "/cloud/cli/activate" || url.username || url.password || url.hash) return null;
|
|
16
16
|
const entries = [...url.searchParams];
|
|
17
|
-
if (entries.length
|
|
18
|
-
|
|
17
|
+
if (entries.length === 2) {
|
|
18
|
+
if (entries.some(([key]) => key !== "deviceId" && key !== "userCode")) return null;
|
|
19
|
+
const id = url.searchParams.get("deviceId");
|
|
20
|
+
const code = url.searchParams.get("userCode");
|
|
21
|
+
if (!validDeviceId(id) || !validUserCode(code) || deviceId !== void 0 && id !== deviceId || userCode !== void 0 && code !== userCode) return null;
|
|
22
|
+
} else if (entries.length === 1) {
|
|
19
23
|
const entry = entries[0];
|
|
20
24
|
if (!["code", "user_code"].includes(entry[0]) || !validUserCode(entry[1]) || userCode !== void 0 && entry[1] !== userCode) return null;
|
|
21
|
-
}
|
|
25
|
+
} else if (entries.length > 2) return null;
|
|
22
26
|
return url.href;
|
|
23
27
|
} catch {
|
|
24
28
|
return null;
|
|
25
29
|
}
|
|
26
30
|
}
|
|
31
|
+
function validDeviceId(value) {
|
|
32
|
+
return typeof value === "string" && /^[a-z0-9_-]{1,200}$/iu.test(value);
|
|
33
|
+
}
|
|
27
34
|
function validUserCode(value) {
|
|
28
35
|
return typeof value === "string" && /^[a-z0-9][a-z0-9-]{3,31}$/iu.test(value);
|
|
29
36
|
}
|
package/lib/index.js
CHANGED
|
@@ -159,7 +159,7 @@ var MODELS = [
|
|
|
159
159
|
reasoningEfforts: EFFORTS_LOW_HIGH
|
|
160
160
|
},
|
|
161
161
|
{ id: "glm-5.2", name: "GLM-5.2", group: "paid" },
|
|
162
|
-
// ── Moonshot(
|
|
162
|
+
// ── Moonshot(3) ───────────────────────────────────────────
|
|
163
163
|
{
|
|
164
164
|
id: "kimi-k2.7-code",
|
|
165
165
|
name: "Kimi K2.7 Code",
|
|
@@ -170,7 +170,9 @@ var MODELS = [
|
|
|
170
170
|
reasoningEfforts: EFFORTS_STD
|
|
171
171
|
},
|
|
172
172
|
{ id: "kimi-k3", name: "Kimi K3", group: "paid" },
|
|
173
|
-
|
|
173
|
+
{ id: "kimi-k3.1-pro", name: "Kimi K3.1 Pro", group: "paid" },
|
|
174
|
+
// ── Google(3) ─────────────────────────────────────────────
|
|
175
|
+
{ id: "gemini-4-argon", name: "Gemini 4 Argon", group: "paid" },
|
|
174
176
|
{ id: "gemini-3.8-flash", name: "Gemini 3.8 Flash", group: "paid" },
|
|
175
177
|
{ id: "gemini-3.7-flash", name: "Gemini 3.7 Flash", group: "paid" },
|
|
176
178
|
// ── xAI(3) ────────────────────────────────────────────────
|
|
@@ -207,7 +209,11 @@ var MODELS = [
|
|
|
207
209
|
reasoningEfforts: EFFORTS_STD
|
|
208
210
|
},
|
|
209
211
|
// ── Alibaba(1) ────────────────────────────────────────────
|
|
210
|
-
{ id: "qwen3.7-max", name: "Qwen3.7 Max", group: "paid" }
|
|
212
|
+
{ id: "qwen3.7-max", name: "Qwen3.7 Max", group: "paid" },
|
|
213
|
+
// Official API additions; display labels for undocumented entries are local formatting.
|
|
214
|
+
{ id: "minimax-m3.1-flash", name: "MiniMax M3.1 Flash", group: "plan" },
|
|
215
|
+
{ id: "muse-spark-1.3", name: "Muse Spark 1.3", group: "paid" },
|
|
216
|
+
{ id: "muse-wonder", name: "Muse Wonder", group: "paid" }
|
|
211
217
|
];
|
|
212
218
|
var BY_ID = new Map(MODELS.map((model) => [model.id, model]));
|
|
213
219
|
function findModel(id) {
|
|
@@ -2194,7 +2200,7 @@ import { randomUUID } from "node:crypto";
|
|
|
2194
2200
|
|
|
2195
2201
|
// src/device-auth.ts
|
|
2196
2202
|
var DEVICE_AUTH_ENDPOINT = "https://amr-api.open-design.ai/api/v1/cli/device-authorizations";
|
|
2197
|
-
var DEVICE_AUTH_PLUGIN_VERSION = "0.1.
|
|
2203
|
+
var DEVICE_AUTH_PLUGIN_VERSION = "0.1.6";
|
|
2198
2204
|
var DEVICE_REQUEST_TIMEOUT_MS = 2e4;
|
|
2199
2205
|
var DEVICE_RESPONSE_MAX_BYTES = 65536;
|
|
2200
2206
|
var DEVICE_POLL_MIN_MS = 1e3;
|
|
@@ -2206,17 +2212,21 @@ var DeviceAuthError = class extends Error {
|
|
|
2206
2212
|
}
|
|
2207
2213
|
code;
|
|
2208
2214
|
};
|
|
2209
|
-
function validateActivationUrl(value, userCode) {
|
|
2215
|
+
function validateActivationUrl(value, userCode, deviceId) {
|
|
2210
2216
|
if (typeof value !== "string" || value.length > 512 || !/^https:\/\/open-design\.ai\/cloud\/cli\/activate(?:\?[^#]*)?$/u.test(value) || /[\s\\]/u.test(value)) return null;
|
|
2211
2217
|
try {
|
|
2212
2218
|
const url = new URL(value);
|
|
2213
2219
|
if (url.origin !== "https://open-design.ai" || url.pathname !== "/cloud/cli/activate" || url.username || url.password || url.hash) return null;
|
|
2214
2220
|
const entries = [...url.searchParams];
|
|
2215
|
-
if (entries.length
|
|
2216
|
-
|
|
2221
|
+
if (entries.length === 2) {
|
|
2222
|
+
if (entries.some(([key]) => key !== "deviceId" && key !== "userCode")) return null;
|
|
2223
|
+
const id = url.searchParams.get("deviceId");
|
|
2224
|
+
const code = url.searchParams.get("userCode");
|
|
2225
|
+
if (!validDeviceId(id) || !validUserCode(code) || deviceId !== void 0 && id !== deviceId || userCode !== void 0 && code !== userCode) return null;
|
|
2226
|
+
} else if (entries.length === 1) {
|
|
2217
2227
|
const entry = entries[0];
|
|
2218
2228
|
if (!["code", "user_code"].includes(entry[0]) || !validUserCode(entry[1]) || userCode !== void 0 && entry[1] !== userCode) return null;
|
|
2219
|
-
}
|
|
2229
|
+
} else if (entries.length > 2) return null;
|
|
2220
2230
|
return url.href;
|
|
2221
2231
|
} catch {
|
|
2222
2232
|
return null;
|
|
@@ -2225,6 +2235,9 @@ function validateActivationUrl(value, userCode) {
|
|
|
2225
2235
|
function object(value) {
|
|
2226
2236
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
2227
2237
|
}
|
|
2238
|
+
function validDeviceId(value) {
|
|
2239
|
+
return typeof value === "string" && /^[a-z0-9_-]{1,200}$/iu.test(value);
|
|
2240
|
+
}
|
|
2228
2241
|
function validUserCode(value) {
|
|
2229
2242
|
return typeof value === "string" && /^[a-z0-9][a-z0-9-]{3,31}$/iu.test(value);
|
|
2230
2243
|
}
|
|
@@ -2232,8 +2245,8 @@ function secret(value) {
|
|
|
2232
2245
|
return typeof value === "string" && value.length > 0 && value.length <= 8192 && /^[\x21-\x7e]+$/u.test(value);
|
|
2233
2246
|
}
|
|
2234
2247
|
function parseDeviceAuthorization(value) {
|
|
2235
|
-
if (!object(value) ||
|
|
2236
|
-
const activationUrl = validateActivationUrl(value.activationUrl, value.userCode);
|
|
2248
|
+
if (!object(value) || !validDeviceId(value.deviceId) || !secret(value.deviceSecret) || !validUserCode(value.userCode)) throw new DeviceAuthError("opendesign/login-response");
|
|
2249
|
+
const activationUrl = validateActivationUrl(value.activationUrl, value.userCode, value.deviceId);
|
|
2237
2250
|
if (!activationUrl || value.userCode.toLowerCase().includes(value.deviceSecret.toLowerCase()) || decodeURIComponent(activationUrl).toLowerCase().includes(value.deviceSecret.toLowerCase())) throw new DeviceAuthError("opendesign/login-response");
|
|
2238
2251
|
const expiresAt = typeof value.expiresAt === "string" && /^\d{4}-\d\d-\d\dT\d\d:\d\d:\d\d(?:\.\d{1,3})?(?:Z|[+-]\d\d:\d\d)$/u.test(value.expiresAt) ? Date.parse(value.expiresAt) : NaN;
|
|
2239
2252
|
if (!Number.isFinite(expiresAt) || typeof value.pollIntervalSeconds !== "number" || !Number.isFinite(value.pollIntervalSeconds) || value.pollIntervalSeconds <= 0) throw new DeviceAuthError("opendesign/login-response");
|
|
@@ -2252,6 +2265,7 @@ function parseDevicePoll(value) {
|
|
|
2252
2265
|
if (["expired", "cancelled", "canceled", "denied", "rejected", "failed", "error"].includes(state)) throw new DeviceAuthError(state === "expired" ? "opendesign/login-expired" : "opendesign/login-denied");
|
|
2253
2266
|
if (value.error !== void 0 && value.error !== null && value.error !== "") throw new DeviceAuthError("opendesign/login-response");
|
|
2254
2267
|
const user = object(value.user) ? value.user : {};
|
|
2268
|
+
if ((state === "pending" || state === "authorization_pending") && [value.controlKey, value.runtimeKey, user.controlKey, user.runtimeKey].every((key) => key === void 0 || key === null)) return { state: "pending" };
|
|
2255
2269
|
const topPresent = value.controlKey !== void 0 || value.runtimeKey !== void 0;
|
|
2256
2270
|
const source = topPresent ? value : user;
|
|
2257
2271
|
if (source.controlKey !== void 0 || source.runtimeKey !== void 0) {
|