dsh-opendesign-corouter 0.1.6 → 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 +11 -11
- package/lib/catalog.d.ts +2 -2
- package/lib/client.js +148 -60
- package/lib/device-auth.d.ts +1 -1
- package/lib/generated/typert.host.js +10 -6
- package/lib/generated/typert.remote-client.js +10 -6
- package/lib/index.js +34 -19
- package/lib/index.js.map +2 -2
- package/lib/remote.d.ts +1 -0
- package/package.json +1 -1
|
@@ -122,9 +122,9 @@ function amount(value, label, negative = false) {
|
|
|
122
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`);
|
|
123
123
|
return value;
|
|
124
124
|
}
|
|
125
|
-
function positiveInteger(value, label, max) {
|
|
125
|
+
function positiveInteger(value, label, max, min = 1) {
|
|
126
126
|
const result = count(value, label);
|
|
127
|
-
if (result
|
|
127
|
+
if (result < min || result > max) throw new Error(`${label} \u8D85\u51FA\u8303\u56F4`);
|
|
128
128
|
return result;
|
|
129
129
|
}
|
|
130
130
|
function parseEfforts(value) {
|
|
@@ -227,9 +227,9 @@ function parseStatusConfig(value) {
|
|
|
227
227
|
apiKeyEnv,
|
|
228
228
|
...value.apiProtocol === void 0 ? {} : { apiProtocol: member(value.apiProtocol, API_PROTOCOL_IDS, "\u63A8\u7406\u534F\u8BAE") },
|
|
229
229
|
...value.modelSettings === void 0 ? {} : { modelSettings: parseModelSettingsMap(value.modelSettings) },
|
|
230
|
-
...value.requestTimeoutMs === void 0 ? {} : { requestTimeoutMs: positiveInteger(value.requestTimeoutMs, "\u8BF7\u6C42\u8D85\u65F6", 36e5) },
|
|
231
|
-
...value.streamIdleTimeoutMs === void 0 ? {} : { streamIdleTimeoutMs: positiveInteger(value.streamIdleTimeoutMs, "\u6D41\u7A7A\u95F2\u8D85\u65F6", 18e5) },
|
|
232
|
-
...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) }
|
|
233
233
|
};
|
|
234
234
|
}
|
|
235
235
|
function parseStatus(value) {
|
|
@@ -242,9 +242,13 @@ function parseStatus(value) {
|
|
|
242
242
|
if (ids.has(model.id)) throw new Error(`\u6A21\u578B\u5217\u8868\u91CD\u590D\u4E86 id "${model.id}"`);
|
|
243
243
|
ids.add(model.id);
|
|
244
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");
|
|
245
248
|
return {
|
|
246
249
|
revision: text(value.revision, "\u914D\u7F6E\u7248\u672C", MAX_REVISION),
|
|
247
|
-
apiKeyConfigured
|
|
250
|
+
apiKeyConfigured,
|
|
251
|
+
...apiKeySource === void 0 ? {} : { apiKeySource },
|
|
248
252
|
...value.sessionSource === void 0 ? {} : { sessionSource: member(value.sessionSource, SESSION_SOURCES, "\u767B\u5F55\u6001\u6765\u6E90") },
|
|
249
253
|
quota: parseQuotaSnapshot(value.quota),
|
|
250
254
|
login: parseLoginState(value.login),
|
package/lib/index.js
CHANGED
|
@@ -302,7 +302,7 @@ var DEFAULT_BASE_URL = "https://amr-link.open-design.ai/v1";
|
|
|
302
302
|
var Config = Schema.object({
|
|
303
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(),
|
|
304
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(),
|
|
305
|
-
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(),
|
|
306
306
|
modelSettings: Schema.transform(Schema.dict(Schema.any()), parseModelSettingsMap).default({}).description("\u9010\u6A21\u578B\u542F\u7528\u72B6\u6001\u548C\u8BF7\u6C42\u53C2\u6570").volatile(),
|
|
307
307
|
useDesktopCredential: Schema.boolean().default(true).description("\u4F18\u5148\u8BFB\u53D6 OpenDesign \u684C\u9762\u7AEF\u767B\u5F55\u6001\u67E5\u8BE2\u989D\u5EA6").volatile(),
|
|
308
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(),
|
|
@@ -2200,7 +2200,7 @@ import { randomUUID } from "node:crypto";
|
|
|
2200
2200
|
|
|
2201
2201
|
// src/device-auth.ts
|
|
2202
2202
|
var DEVICE_AUTH_ENDPOINT = "https://amr-api.open-design.ai/api/v1/cli/device-authorizations";
|
|
2203
|
-
var DEVICE_AUTH_PLUGIN_VERSION = "0.1.
|
|
2203
|
+
var DEVICE_AUTH_PLUGIN_VERSION = "0.1.7";
|
|
2204
2204
|
var DEVICE_REQUEST_TIMEOUT_MS = 2e4;
|
|
2205
2205
|
var DEVICE_RESPONSE_MAX_BYTES = 65536;
|
|
2206
2206
|
var DEVICE_POLL_MIN_MS = 1e3;
|
|
@@ -3171,9 +3171,9 @@ function amount(value, label, negative = false) {
|
|
|
3171
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`);
|
|
3172
3172
|
return value;
|
|
3173
3173
|
}
|
|
3174
|
-
function positiveInteger(value, label, max) {
|
|
3174
|
+
function positiveInteger(value, label, max, min = 1) {
|
|
3175
3175
|
const result = count(value, label);
|
|
3176
|
-
if (result
|
|
3176
|
+
if (result < min || result > max) throw new Error(`${label} \u8D85\u51FA\u8303\u56F4`);
|
|
3177
3177
|
return result;
|
|
3178
3178
|
}
|
|
3179
3179
|
function parseEfforts(value) {
|
|
@@ -3276,9 +3276,9 @@ function parseStatusConfig(value) {
|
|
|
3276
3276
|
apiKeyEnv,
|
|
3277
3277
|
...value.apiProtocol === void 0 ? {} : { apiProtocol: member(value.apiProtocol, API_PROTOCOL_IDS, "\u63A8\u7406\u534F\u8BAE") },
|
|
3278
3278
|
...value.modelSettings === void 0 ? {} : { modelSettings: parseModelSettingsMap(value.modelSettings) },
|
|
3279
|
-
...value.requestTimeoutMs === void 0 ? {} : { requestTimeoutMs: positiveInteger(value.requestTimeoutMs, "\u8BF7\u6C42\u8D85\u65F6", 36e5) },
|
|
3280
|
-
...value.streamIdleTimeoutMs === void 0 ? {} : { streamIdleTimeoutMs: positiveInteger(value.streamIdleTimeoutMs, "\u6D41\u7A7A\u95F2\u8D85\u65F6", 18e5) },
|
|
3281
|
-
...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) }
|
|
3282
3282
|
};
|
|
3283
3283
|
}
|
|
3284
3284
|
function parseStatus(value) {
|
|
@@ -3291,9 +3291,13 @@ function parseStatus(value) {
|
|
|
3291
3291
|
if (ids.has(model.id)) throw new Error(`\u6A21\u578B\u5217\u8868\u91CD\u590D\u4E86 id "${model.id}"`);
|
|
3292
3292
|
ids.add(model.id);
|
|
3293
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");
|
|
3294
3297
|
return {
|
|
3295
3298
|
revision: text(value.revision, "\u914D\u7F6E\u7248\u672C", MAX_REVISION),
|
|
3296
|
-
apiKeyConfigured
|
|
3299
|
+
apiKeyConfigured,
|
|
3300
|
+
...apiKeySource === void 0 ? {} : { apiKeySource },
|
|
3297
3301
|
...value.sessionSource === void 0 ? {} : { sessionSource: member(value.sessionSource, SESSION_SOURCES, "\u767B\u5F55\u6001\u6765\u6E90") },
|
|
3298
3302
|
quota: parseQuotaSnapshot(value.quota),
|
|
3299
3303
|
login: parseLoginState(value.login),
|
|
@@ -3332,7 +3336,8 @@ var inject = ["llm"];
|
|
|
3332
3336
|
var API_KEY = credentialKey(name, "api-key");
|
|
3333
3337
|
var SESSION = credentialKey(name, "console");
|
|
3334
3338
|
var hash = (value) => createHash("sha256").update(JSON.stringify(value) ?? "").digest("hex");
|
|
3335
|
-
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" });
|
|
3336
3341
|
function grantOf(value) {
|
|
3337
3342
|
if (value?.kind !== "grant" || !record(value.payload)) return;
|
|
3338
3343
|
if (value.payload.kind === "device") return deviceGrant(value.payload);
|
|
@@ -3351,7 +3356,7 @@ var OpenDesignCoRouterService = class extends (_a = TypertRemoteService, _status
|
|
|
3351
3356
|
__publicField(this, "_lifetime", new AbortController());
|
|
3352
3357
|
__publicField(this, "_revision", randomUUID2());
|
|
3353
3358
|
__publicField(this, "_fingerprint", "");
|
|
3354
|
-
__publicField(this, "_quota",
|
|
3359
|
+
__publicField(this, "_quota", unreadQuota());
|
|
3355
3360
|
__publicField(this, "_quotaAt", 0);
|
|
3356
3361
|
__publicField(this, "_quotaConfig", "");
|
|
3357
3362
|
__publicField(this, "_quotaIdentity");
|
|
@@ -3417,15 +3422,15 @@ var OpenDesignCoRouterService = class extends (_a = TypertRemoteService, _status
|
|
|
3417
3422
|
async _key(ref, baseURL, apiRecord, sessionRecord) {
|
|
3418
3423
|
const credentials = this.ctx.get("credentials");
|
|
3419
3424
|
const ambient = credentials ? (await credentials.resolve(credentialRef(ref)))?.value : launchEnvironmentOf(this.ctx).get(ref)?.value;
|
|
3420
|
-
if (ambient?.trim()) return ambient;
|
|
3421
|
-
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" };
|
|
3422
3427
|
const grant = grantOf(sessionRecord);
|
|
3423
|
-
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;
|
|
3424
3429
|
}
|
|
3425
3430
|
async resolveApiKey(ref, baseURL = this._config().baseURL) {
|
|
3426
3431
|
const credentials = this.ctx.get("credentials");
|
|
3427
3432
|
const [apiRecord, sessionRecord] = await Promise.all([credentials?.readRecord(API_KEY), credentials?.readRecord(SESSION)]);
|
|
3428
|
-
return this._key(ref, baseURL, apiRecord, sessionRecord);
|
|
3433
|
+
return (await this._key(ref, baseURL, apiRecord, sessionRecord))?.key;
|
|
3429
3434
|
}
|
|
3430
3435
|
_invalidateModels() {
|
|
3431
3436
|
const changed = this._modelsUpdatedAt !== void 0;
|
|
@@ -3445,8 +3450,9 @@ var OpenDesignCoRouterService = class extends (_a = TypertRemoteService, _status
|
|
|
3445
3450
|
async _state() {
|
|
3446
3451
|
const credentials = this.ctx.get("credentials"), config = this._config();
|
|
3447
3452
|
const [apiRecord, sessionRecord] = await Promise.all([credentials?.readRecord(API_KEY), credentials?.readRecord(SESSION)]);
|
|
3448
|
-
const
|
|
3449
|
-
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 };
|
|
3450
3456
|
const modelsFingerprint = hash({ key, baseURL: config.baseURL });
|
|
3451
3457
|
if (modelsFingerprint !== this._modelsFingerprint) {
|
|
3452
3458
|
this._modelsFingerprint = modelsFingerprint;
|
|
@@ -3468,7 +3474,7 @@ var OpenDesignCoRouterService = class extends (_a = TypertRemoteService, _status
|
|
|
3468
3474
|
_invalidateQuota() {
|
|
3469
3475
|
this._quotaAt = 0;
|
|
3470
3476
|
this._quotaEpoch++;
|
|
3471
|
-
this._quota =
|
|
3477
|
+
this._quota = unreadQuota();
|
|
3472
3478
|
this._quotaIdentity = void 0;
|
|
3473
3479
|
this._quotaController?.abort();
|
|
3474
3480
|
this._quotaPending = void 0;
|
|
@@ -3483,6 +3489,7 @@ var OpenDesignCoRouterService = class extends (_a = TypertRemoteService, _status
|
|
|
3483
3489
|
return parseStatus({
|
|
3484
3490
|
revision: this._revision,
|
|
3485
3491
|
apiKeyConfigured: Boolean(state.key?.trim()),
|
|
3492
|
+
...state.keySource ? { apiKeySource: state.keySource } : {},
|
|
3486
3493
|
...this._quota.source ? { sessionSource: this._quota.source } : {},
|
|
3487
3494
|
quota: this._quota,
|
|
3488
3495
|
login: this._login.status(),
|
|
@@ -3507,7 +3514,7 @@ var OpenDesignCoRouterService = class extends (_a = TypertRemoteService, _status
|
|
|
3507
3514
|
if (this._modelsPending) return this._modelsPending;
|
|
3508
3515
|
const key = state.key;
|
|
3509
3516
|
if (!key?.trim()) {
|
|
3510
|
-
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";
|
|
3511
3518
|
return this.status();
|
|
3512
3519
|
}
|
|
3513
3520
|
const epoch = this._modelsEpoch;
|
|
@@ -3519,10 +3526,18 @@ var OpenDesignCoRouterService = class extends (_a = TypertRemoteService, _status
|
|
|
3519
3526
|
const models = await (this.dependencies.fetchModels ?? fetchModelCatalog)(state.config.baseURL, key, signal);
|
|
3520
3527
|
await this._state();
|
|
3521
3528
|
if (signal.aborted || epoch !== this._modelsEpoch) return this.status();
|
|
3529
|
+
const previousModels = this._models;
|
|
3530
|
+
const previousUpdatedAt = this._modelsUpdatedAt;
|
|
3522
3531
|
this._models = models;
|
|
3523
3532
|
this._modelsUpdatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
3524
3533
|
this._modelsError = void 0;
|
|
3525
|
-
|
|
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
|
+
}
|
|
3526
3541
|
} catch (error) {
|
|
3527
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";
|
|
3528
3543
|
}
|