dsh-opendesign-corouter 0.1.5 → 0.1.7
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 +14 -14
- package/lib/catalog.d.ts +11 -10
- package/lib/client.js +169 -62
- package/lib/device-auth.d.ts +3 -3
- package/lib/generated/typert.host.js +21 -10
- package/lib/generated/typert.remote-client.js +21 -10
- package/lib/index.js +57 -28
- package/lib/index.js.map +2 -2
- package/lib/remote.d.ts +1 -0
- package/package.json +1 -1
|
@@ -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
|
}
|
|
@@ -115,9 +122,9 @@ function amount(value, label, negative = false) {
|
|
|
115
122
|
if (typeof value !== "number" || !Number.isFinite(value) || !negative && value < 0) throw new Error(`${label} \u5FC5\u987B\u662F${negative ? "" : "\u975E\u8D1F"}\u6709\u9650\u6570\u5B57`);
|
|
116
123
|
return value;
|
|
117
124
|
}
|
|
118
|
-
function positiveInteger(value, label, max) {
|
|
125
|
+
function positiveInteger(value, label, max, min = 1) {
|
|
119
126
|
const result = count(value, label);
|
|
120
|
-
if (result
|
|
127
|
+
if (result < min || result > max) throw new Error(`${label} \u8D85\u51FA\u8303\u56F4`);
|
|
121
128
|
return result;
|
|
122
129
|
}
|
|
123
130
|
function parseEfforts(value) {
|
|
@@ -220,9 +227,9 @@ function parseStatusConfig(value) {
|
|
|
220
227
|
apiKeyEnv,
|
|
221
228
|
...value.apiProtocol === void 0 ? {} : { apiProtocol: member(value.apiProtocol, API_PROTOCOL_IDS, "\u63A8\u7406\u534F\u8BAE") },
|
|
222
229
|
...value.modelSettings === void 0 ? {} : { modelSettings: parseModelSettingsMap(value.modelSettings) },
|
|
223
|
-
...value.requestTimeoutMs === void 0 ? {} : { requestTimeoutMs: positiveInteger(value.requestTimeoutMs, "\u8BF7\u6C42\u8D85\u65F6", 36e5) },
|
|
224
|
-
...value.streamIdleTimeoutMs === void 0 ? {} : { streamIdleTimeoutMs: positiveInteger(value.streamIdleTimeoutMs, "\u6D41\u7A7A\u95F2\u8D85\u65F6", 18e5) },
|
|
225
|
-
...value.quotaRefreshSeconds === void 0 ? {} : { quotaRefreshSeconds: positiveInteger(value.quotaRefreshSeconds, "\u81EA\u52A8\u5237\u65B0\u95F4\u9694", 3600) }
|
|
230
|
+
...value.requestTimeoutMs === void 0 ? {} : { requestTimeoutMs: positiveInteger(value.requestTimeoutMs, "\u8BF7\u6C42\u8D85\u65F6", 36e5, 1e3) },
|
|
231
|
+
...value.streamIdleTimeoutMs === void 0 ? {} : { streamIdleTimeoutMs: positiveInteger(value.streamIdleTimeoutMs, "\u6D41\u7A7A\u95F2\u8D85\u65F6", 18e5, 1e3) },
|
|
232
|
+
...value.quotaRefreshSeconds === void 0 ? {} : { quotaRefreshSeconds: positiveInteger(value.quotaRefreshSeconds, "\u81EA\u52A8\u5237\u65B0\u95F4\u9694", 3600, 5) }
|
|
226
233
|
};
|
|
227
234
|
}
|
|
228
235
|
function parseStatus(value) {
|
|
@@ -235,9 +242,13 @@ function parseStatus(value) {
|
|
|
235
242
|
if (ids.has(model.id)) throw new Error(`\u6A21\u578B\u5217\u8868\u91CD\u590D\u4E86 id "${model.id}"`);
|
|
236
243
|
ids.add(model.id);
|
|
237
244
|
}
|
|
245
|
+
const apiKeyConfigured = flag(value.apiKeyConfigured, "\u51ED\u636E\u662F\u5426\u5C31\u7EEA");
|
|
246
|
+
const apiKeySource = value.apiKeySource === void 0 ? void 0 : member(value.apiKeySource, ["reference", "stored", "device"], "\u63A8\u7406\u51ED\u636E\u6765\u6E90");
|
|
247
|
+
if (!apiKeyConfigured && apiKeySource !== void 0) throw new Error("\u672A\u914D\u7F6E\u51ED\u636E\u65F6\u4E0D\u80FD\u6307\u5B9A\u63A8\u7406\u51ED\u636E\u6765\u6E90");
|
|
238
248
|
return {
|
|
239
249
|
revision: text(value.revision, "\u914D\u7F6E\u7248\u672C", MAX_REVISION),
|
|
240
|
-
apiKeyConfigured
|
|
250
|
+
apiKeyConfigured,
|
|
251
|
+
...apiKeySource === void 0 ? {} : { apiKeySource },
|
|
241
252
|
...value.sessionSource === void 0 ? {} : { sessionSource: member(value.sessionSource, SESSION_SOURCES, "\u767B\u5F55\u6001\u6765\u6E90") },
|
|
242
253
|
quota: parseQuotaSnapshot(value.quota),
|
|
243
254
|
login: parseLoginState(value.login),
|
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) {
|
|
@@ -296,7 +302,7 @@ var DEFAULT_BASE_URL = "https://amr-link.open-design.ai/v1";
|
|
|
296
302
|
var Config = Schema.object({
|
|
297
303
|
apiKeyEnv: Schema.string().max(128).pattern(/^[A-Za-z_][A-Za-z0-9_]*$/u).default("COROUTER_API_KEY").description("CoRouter API Key \u7684\u73AF\u5883\u53D8\u91CF\u6216 DSH \u51ED\u636E\u5F15\u7528\u540D").volatile(),
|
|
298
304
|
baseURL: Schema.transform(Schema.string(), assertBaseURL).default(DEFAULT_BASE_URL).description("CoRouter \u7F51\u5173\u5730\u5740\uFF1B\u4E0D\u7528\u4E8E\u63A7\u5236\u53F0\u767B\u5F55\u6216\u989D\u5EA6\u67E5\u8BE2").volatile(),
|
|
299
|
-
apiProtocol: Schema.union(API_PROTOCOL_IDS).default("chat-completions").description("\u63A8\u7406
|
|
305
|
+
apiProtocol: Schema.union(API_PROTOCOL_IDS).default("chat-completions").description("\u7F51\u5173\u652F\u6301\u7684\u63A8\u7406\u534F\u8BAE\uFF1B\u6A21\u578B\u76EE\u5F55\u901A\u8FC7\u8BE5\u7F51\u5173\u7684\u517C\u5BB9\u63A5\u53E3\u8BFB\u53D6").volatile(),
|
|
300
306
|
modelSettings: Schema.transform(Schema.dict(Schema.any()), parseModelSettingsMap).default({}).description("\u9010\u6A21\u578B\u542F\u7528\u72B6\u6001\u548C\u8BF7\u6C42\u53C2\u6570").volatile(),
|
|
301
307
|
useDesktopCredential: Schema.boolean().default(true).description("\u4F18\u5148\u8BFB\u53D6 OpenDesign \u684C\u9762\u7AEF\u767B\u5F55\u6001\u67E5\u8BE2\u989D\u5EA6").volatile(),
|
|
302
308
|
emptyTurnGuard: Schema.boolean().default(true).description("\u76D1\u63A7\u5957\u9910\u8D60\u9001\u6A21\u578B\u7684\u7A7A\u8F6E/\u534F\u8BAE\u6B8B\u6E23\uFF1B\u7531\u5BBF\u4E3B\u91CD\u8BD5\u7B56\u7565\u5904\u7406\uFF0C\u53EF\u80FD\u989D\u5916\u6D88\u8017\u8D60\u9001\u989D\u5EA6").volatile(),
|
|
@@ -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.7";
|
|
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) {
|
|
@@ -3157,9 +3171,9 @@ function amount(value, label, negative = false) {
|
|
|
3157
3171
|
if (typeof value !== "number" || !Number.isFinite(value) || !negative && value < 0) throw new Error(`${label} \u5FC5\u987B\u662F${negative ? "" : "\u975E\u8D1F"}\u6709\u9650\u6570\u5B57`);
|
|
3158
3172
|
return value;
|
|
3159
3173
|
}
|
|
3160
|
-
function positiveInteger(value, label, max) {
|
|
3174
|
+
function positiveInteger(value, label, max, min = 1) {
|
|
3161
3175
|
const result = count(value, label);
|
|
3162
|
-
if (result
|
|
3176
|
+
if (result < min || result > max) throw new Error(`${label} \u8D85\u51FA\u8303\u56F4`);
|
|
3163
3177
|
return result;
|
|
3164
3178
|
}
|
|
3165
3179
|
function parseEfforts(value) {
|
|
@@ -3262,9 +3276,9 @@ function parseStatusConfig(value) {
|
|
|
3262
3276
|
apiKeyEnv,
|
|
3263
3277
|
...value.apiProtocol === void 0 ? {} : { apiProtocol: member(value.apiProtocol, API_PROTOCOL_IDS, "\u63A8\u7406\u534F\u8BAE") },
|
|
3264
3278
|
...value.modelSettings === void 0 ? {} : { modelSettings: parseModelSettingsMap(value.modelSettings) },
|
|
3265
|
-
...value.requestTimeoutMs === void 0 ? {} : { requestTimeoutMs: positiveInteger(value.requestTimeoutMs, "\u8BF7\u6C42\u8D85\u65F6", 36e5) },
|
|
3266
|
-
...value.streamIdleTimeoutMs === void 0 ? {} : { streamIdleTimeoutMs: positiveInteger(value.streamIdleTimeoutMs, "\u6D41\u7A7A\u95F2\u8D85\u65F6", 18e5) },
|
|
3267
|
-
...value.quotaRefreshSeconds === void 0 ? {} : { quotaRefreshSeconds: positiveInteger(value.quotaRefreshSeconds, "\u81EA\u52A8\u5237\u65B0\u95F4\u9694", 3600) }
|
|
3279
|
+
...value.requestTimeoutMs === void 0 ? {} : { requestTimeoutMs: positiveInteger(value.requestTimeoutMs, "\u8BF7\u6C42\u8D85\u65F6", 36e5, 1e3) },
|
|
3280
|
+
...value.streamIdleTimeoutMs === void 0 ? {} : { streamIdleTimeoutMs: positiveInteger(value.streamIdleTimeoutMs, "\u6D41\u7A7A\u95F2\u8D85\u65F6", 18e5, 1e3) },
|
|
3281
|
+
...value.quotaRefreshSeconds === void 0 ? {} : { quotaRefreshSeconds: positiveInteger(value.quotaRefreshSeconds, "\u81EA\u52A8\u5237\u65B0\u95F4\u9694", 3600, 5) }
|
|
3268
3282
|
};
|
|
3269
3283
|
}
|
|
3270
3284
|
function parseStatus(value) {
|
|
@@ -3277,9 +3291,13 @@ function parseStatus(value) {
|
|
|
3277
3291
|
if (ids.has(model.id)) throw new Error(`\u6A21\u578B\u5217\u8868\u91CD\u590D\u4E86 id "${model.id}"`);
|
|
3278
3292
|
ids.add(model.id);
|
|
3279
3293
|
}
|
|
3294
|
+
const apiKeyConfigured = flag(value.apiKeyConfigured, "\u51ED\u636E\u662F\u5426\u5C31\u7EEA");
|
|
3295
|
+
const apiKeySource = value.apiKeySource === void 0 ? void 0 : member(value.apiKeySource, ["reference", "stored", "device"], "\u63A8\u7406\u51ED\u636E\u6765\u6E90");
|
|
3296
|
+
if (!apiKeyConfigured && apiKeySource !== void 0) throw new Error("\u672A\u914D\u7F6E\u51ED\u636E\u65F6\u4E0D\u80FD\u6307\u5B9A\u63A8\u7406\u51ED\u636E\u6765\u6E90");
|
|
3280
3297
|
return {
|
|
3281
3298
|
revision: text(value.revision, "\u914D\u7F6E\u7248\u672C", MAX_REVISION),
|
|
3282
|
-
apiKeyConfigured
|
|
3299
|
+
apiKeyConfigured,
|
|
3300
|
+
...apiKeySource === void 0 ? {} : { apiKeySource },
|
|
3283
3301
|
...value.sessionSource === void 0 ? {} : { sessionSource: member(value.sessionSource, SESSION_SOURCES, "\u767B\u5F55\u6001\u6765\u6E90") },
|
|
3284
3302
|
quota: parseQuotaSnapshot(value.quota),
|
|
3285
3303
|
login: parseLoginState(value.login),
|
|
@@ -3318,7 +3336,8 @@ var inject = ["llm"];
|
|
|
3318
3336
|
var API_KEY = credentialKey(name, "api-key");
|
|
3319
3337
|
var SESSION = credentialKey(name, "console");
|
|
3320
3338
|
var hash = (value) => createHash("sha256").update(JSON.stringify(value) ?? "").digest("hex");
|
|
3321
|
-
var needLogin = () => ({ state: "need-login", updatedAt: (/* @__PURE__ */ new Date()).toISOString(), windows: [], balances: {}, note: "\
|
|
3339
|
+
var needLogin = () => ({ state: "need-login", updatedAt: (/* @__PURE__ */ new Date()).toISOString(), windows: [], balances: {}, note: "\u8BF7\u5728\u8FDE\u63A5\u4E0E\u767B\u5F55\u9875\u5B8C\u6210\u8D26\u53F7\u6388\u6743\u540E\u8BFB\u53D6\u989D\u5EA6\u3002" });
|
|
3340
|
+
var unreadQuota = () => ({ state: "partial", updatedAt: (/* @__PURE__ */ new Date()).toISOString(), windows: [], balances: {}, note: "\u989D\u5EA6\u5C1A\u672A\u8BFB\u53D6\uFF0C\u8BF7\u5237\u65B0\u989D\u5EA6\u3002" });
|
|
3322
3341
|
function grantOf(value) {
|
|
3323
3342
|
if (value?.kind !== "grant" || !record(value.payload)) return;
|
|
3324
3343
|
if (value.payload.kind === "device") return deviceGrant(value.payload);
|
|
@@ -3337,7 +3356,7 @@ var OpenDesignCoRouterService = class extends (_a = TypertRemoteService, _status
|
|
|
3337
3356
|
__publicField(this, "_lifetime", new AbortController());
|
|
3338
3357
|
__publicField(this, "_revision", randomUUID2());
|
|
3339
3358
|
__publicField(this, "_fingerprint", "");
|
|
3340
|
-
__publicField(this, "_quota",
|
|
3359
|
+
__publicField(this, "_quota", unreadQuota());
|
|
3341
3360
|
__publicField(this, "_quotaAt", 0);
|
|
3342
3361
|
__publicField(this, "_quotaConfig", "");
|
|
3343
3362
|
__publicField(this, "_quotaIdentity");
|
|
@@ -3403,15 +3422,15 @@ var OpenDesignCoRouterService = class extends (_a = TypertRemoteService, _status
|
|
|
3403
3422
|
async _key(ref, baseURL, apiRecord, sessionRecord) {
|
|
3404
3423
|
const credentials = this.ctx.get("credentials");
|
|
3405
3424
|
const ambient = credentials ? (await credentials.resolve(credentialRef(ref)))?.value : launchEnvironmentOf(this.ctx).get(ref)?.value;
|
|
3406
|
-
if (ambient?.trim()) return ambient;
|
|
3407
|
-
if (apiRecord?.kind === "api-key" && apiRecord.key?.trim()) return apiRecord.key;
|
|
3425
|
+
if (ambient?.trim()) return { key: ambient, source: "reference" };
|
|
3426
|
+
if (apiRecord?.kind === "api-key" && apiRecord.key?.trim()) return { key: apiRecord.key, source: "stored" };
|
|
3408
3427
|
const grant = grantOf(sessionRecord);
|
|
3409
|
-
return isOfficialRuntimeUrl(baseURL) && grant && "kind" in grant && grant.kind === "device" ? grant.runtimeKey : void 0;
|
|
3428
|
+
return isOfficialRuntimeUrl(baseURL) && grant && "kind" in grant && grant.kind === "device" ? { key: grant.runtimeKey, source: "device" } : void 0;
|
|
3410
3429
|
}
|
|
3411
3430
|
async resolveApiKey(ref, baseURL = this._config().baseURL) {
|
|
3412
3431
|
const credentials = this.ctx.get("credentials");
|
|
3413
3432
|
const [apiRecord, sessionRecord] = await Promise.all([credentials?.readRecord(API_KEY), credentials?.readRecord(SESSION)]);
|
|
3414
|
-
return this._key(ref, baseURL, apiRecord, sessionRecord);
|
|
3433
|
+
return (await this._key(ref, baseURL, apiRecord, sessionRecord))?.key;
|
|
3415
3434
|
}
|
|
3416
3435
|
_invalidateModels() {
|
|
3417
3436
|
const changed = this._modelsUpdatedAt !== void 0;
|
|
@@ -3431,8 +3450,9 @@ var OpenDesignCoRouterService = class extends (_a = TypertRemoteService, _status
|
|
|
3431
3450
|
async _state() {
|
|
3432
3451
|
const credentials = this.ctx.get("credentials"), config = this._config();
|
|
3433
3452
|
const [apiRecord, sessionRecord] = await Promise.all([credentials?.readRecord(API_KEY), credentials?.readRecord(SESSION)]);
|
|
3434
|
-
const
|
|
3435
|
-
const
|
|
3453
|
+
const resolved = await this._key(config.apiKeyEnv, config.baseURL, apiRecord, sessionRecord);
|
|
3454
|
+
const key = resolved?.key;
|
|
3455
|
+
const state = { apiRecord, sessionRecord, key, keySource: resolved?.source, config };
|
|
3436
3456
|
const modelsFingerprint = hash({ key, baseURL: config.baseURL });
|
|
3437
3457
|
if (modelsFingerprint !== this._modelsFingerprint) {
|
|
3438
3458
|
this._modelsFingerprint = modelsFingerprint;
|
|
@@ -3454,7 +3474,7 @@ var OpenDesignCoRouterService = class extends (_a = TypertRemoteService, _status
|
|
|
3454
3474
|
_invalidateQuota() {
|
|
3455
3475
|
this._quotaAt = 0;
|
|
3456
3476
|
this._quotaEpoch++;
|
|
3457
|
-
this._quota =
|
|
3477
|
+
this._quota = unreadQuota();
|
|
3458
3478
|
this._quotaIdentity = void 0;
|
|
3459
3479
|
this._quotaController?.abort();
|
|
3460
3480
|
this._quotaPending = void 0;
|
|
@@ -3469,6 +3489,7 @@ var OpenDesignCoRouterService = class extends (_a = TypertRemoteService, _status
|
|
|
3469
3489
|
return parseStatus({
|
|
3470
3490
|
revision: this._revision,
|
|
3471
3491
|
apiKeyConfigured: Boolean(state.key?.trim()),
|
|
3492
|
+
...state.keySource ? { apiKeySource: state.keySource } : {},
|
|
3472
3493
|
...this._quota.source ? { sessionSource: this._quota.source } : {},
|
|
3473
3494
|
quota: this._quota,
|
|
3474
3495
|
login: this._login.status(),
|
|
@@ -3493,7 +3514,7 @@ var OpenDesignCoRouterService = class extends (_a = TypertRemoteService, _status
|
|
|
3493
3514
|
if (this._modelsPending) return this._modelsPending;
|
|
3494
3515
|
const key = state.key;
|
|
3495
3516
|
if (!key?.trim()) {
|
|
3496
|
-
this._modelsError = "\u8BF7\u5148\u914D\u7F6E API Key\uFF0C\u518D\u4ECE
|
|
3517
|
+
this._modelsError = "\u8BF7\u5148\u914D\u7F6E API Key\uFF0C\u518D\u4ECE\u5F53\u524D\u7F51\u5173\u8BFB\u53D6\u6A21\u578B\u76EE\u5F55\u3002";
|
|
3497
3518
|
return this.status();
|
|
3498
3519
|
}
|
|
3499
3520
|
const epoch = this._modelsEpoch;
|
|
@@ -3505,10 +3526,18 @@ var OpenDesignCoRouterService = class extends (_a = TypertRemoteService, _status
|
|
|
3505
3526
|
const models = await (this.dependencies.fetchModels ?? fetchModelCatalog)(state.config.baseURL, key, signal);
|
|
3506
3527
|
await this._state();
|
|
3507
3528
|
if (signal.aborted || epoch !== this._modelsEpoch) return this.status();
|
|
3529
|
+
const previousModels = this._models;
|
|
3530
|
+
const previousUpdatedAt = this._modelsUpdatedAt;
|
|
3508
3531
|
this._models = models;
|
|
3509
3532
|
this._modelsUpdatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
3510
3533
|
this._modelsError = void 0;
|
|
3511
|
-
|
|
3534
|
+
try {
|
|
3535
|
+
this.dependencies.modelsChanged?.();
|
|
3536
|
+
} catch {
|
|
3537
|
+
this._models = previousModels;
|
|
3538
|
+
this._modelsUpdatedAt = previousUpdatedAt;
|
|
3539
|
+
this._modelsError = "\u6A21\u578B\u76EE\u5F55\u5DF2\u8BFB\u53D6\uFF0C\u4F46\u6A21\u578B\u9009\u62E9\u5668\u66F4\u65B0\u5931\u8D25\uFF0C\u8BF7\u91CD\u8BD5\u3002";
|
|
3540
|
+
}
|
|
3512
3541
|
} catch (error) {
|
|
3513
3542
|
if (!signal.aborted && epoch === this._modelsEpoch) this._modelsError = error instanceof ModelDiscoveryError ? error.message : "\u6A21\u578B\u5217\u8868\u66F4\u65B0\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002";
|
|
3514
3543
|
}
|