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
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
|
}
|
|
@@ -20047,9 +20054,9 @@ function amount(value, label, negative = false) {
|
|
|
20047
20054
|
if (typeof value !== "number" || !Number.isFinite(value) || !negative && value < 0) throw new Error(`${label} \u5FC5\u987B\u662F${negative ? "" : "\u975E\u8D1F"}\u6709\u9650\u6570\u5B57`);
|
|
20048
20055
|
return value;
|
|
20049
20056
|
}
|
|
20050
|
-
function positiveInteger(value, label, max) {
|
|
20057
|
+
function positiveInteger(value, label, max, min = 1) {
|
|
20051
20058
|
const result = count(value, label);
|
|
20052
|
-
if (result
|
|
20059
|
+
if (result < min || result > max) throw new Error(`${label} \u8D85\u51FA\u8303\u56F4`);
|
|
20053
20060
|
return result;
|
|
20054
20061
|
}
|
|
20055
20062
|
function parseEfforts(value) {
|
|
@@ -20152,9 +20159,9 @@ function parseStatusConfig(value) {
|
|
|
20152
20159
|
apiKeyEnv,
|
|
20153
20160
|
...value.apiProtocol === void 0 ? {} : { apiProtocol: member(value.apiProtocol, API_PROTOCOL_IDS, "\u63A8\u7406\u534F\u8BAE") },
|
|
20154
20161
|
...value.modelSettings === void 0 ? {} : { modelSettings: parseModelSettingsMap(value.modelSettings) },
|
|
20155
|
-
...value.requestTimeoutMs === void 0 ? {} : { requestTimeoutMs: positiveInteger(value.requestTimeoutMs, "\u8BF7\u6C42\u8D85\u65F6", 36e5) },
|
|
20156
|
-
...value.streamIdleTimeoutMs === void 0 ? {} : { streamIdleTimeoutMs: positiveInteger(value.streamIdleTimeoutMs, "\u6D41\u7A7A\u95F2\u8D85\u65F6", 18e5) },
|
|
20157
|
-
...value.quotaRefreshSeconds === void 0 ? {} : { quotaRefreshSeconds: positiveInteger(value.quotaRefreshSeconds, "\u81EA\u52A8\u5237\u65B0\u95F4\u9694", 3600) }
|
|
20162
|
+
...value.requestTimeoutMs === void 0 ? {} : { requestTimeoutMs: positiveInteger(value.requestTimeoutMs, "\u8BF7\u6C42\u8D85\u65F6", 36e5, 1e3) },
|
|
20163
|
+
...value.streamIdleTimeoutMs === void 0 ? {} : { streamIdleTimeoutMs: positiveInteger(value.streamIdleTimeoutMs, "\u6D41\u7A7A\u95F2\u8D85\u65F6", 18e5, 1e3) },
|
|
20164
|
+
...value.quotaRefreshSeconds === void 0 ? {} : { quotaRefreshSeconds: positiveInteger(value.quotaRefreshSeconds, "\u81EA\u52A8\u5237\u65B0\u95F4\u9694", 3600, 5) }
|
|
20158
20165
|
};
|
|
20159
20166
|
}
|
|
20160
20167
|
function parseStatus(value) {
|
|
@@ -20167,9 +20174,13 @@ function parseStatus(value) {
|
|
|
20167
20174
|
if (ids.has(model.id)) throw new Error(`\u6A21\u578B\u5217\u8868\u91CD\u590D\u4E86 id "${model.id}"`);
|
|
20168
20175
|
ids.add(model.id);
|
|
20169
20176
|
}
|
|
20177
|
+
const apiKeyConfigured = flag(value.apiKeyConfigured, "\u51ED\u636E\u662F\u5426\u5C31\u7EEA");
|
|
20178
|
+
const apiKeySource = value.apiKeySource === void 0 ? void 0 : member(value.apiKeySource, ["reference", "stored", "device"], "\u63A8\u7406\u51ED\u636E\u6765\u6E90");
|
|
20179
|
+
if (!apiKeyConfigured && apiKeySource !== void 0) throw new Error("\u672A\u914D\u7F6E\u51ED\u636E\u65F6\u4E0D\u80FD\u6307\u5B9A\u63A8\u7406\u51ED\u636E\u6765\u6E90");
|
|
20170
20180
|
return {
|
|
20171
20181
|
revision: text(value.revision, "\u914D\u7F6E\u7248\u672C", MAX_REVISION),
|
|
20172
|
-
apiKeyConfigured
|
|
20182
|
+
apiKeyConfigured,
|
|
20183
|
+
...apiKeySource === void 0 ? {} : { apiKeySource },
|
|
20173
20184
|
...value.sessionSource === void 0 ? {} : { sessionSource: member(value.sessionSource, SESSION_SOURCES, "\u767B\u5F55\u6001\u6765\u6E90") },
|
|
20174
20185
|
quota: parseQuotaSnapshot(value.quota),
|
|
20175
20186
|
login: parseLoginState(value.login),
|
|
@@ -20257,7 +20268,7 @@ var LOGIN_LABELS = {
|
|
|
20257
20268
|
};
|
|
20258
20269
|
var QUOTA_LABELS = {
|
|
20259
20270
|
ok: "\u989D\u5EA6\u4FE1\u606F\u5DF2\u66F4\u65B0",
|
|
20260
|
-
partial: "\
|
|
20271
|
+
partial: "\u989D\u5EA6\u6570\u636E\u6682\u672A\u5B8C\u6574",
|
|
20261
20272
|
"need-login": "\u9700\u8981\u767B\u5F55\u540E\u8BFB\u53D6\u989D\u5EA6",
|
|
20262
20273
|
error: "\u6682\u65F6\u65E0\u6CD5\u8BFB\u53D6\u989D\u5EA6"
|
|
20263
20274
|
};
|
|
@@ -20271,7 +20282,9 @@ function installStyles() {
|
|
|
20271
20282
|
.odc-tab{flex:none;border:1px solid transparent;border-radius:8px;padding:7px 13px;background:transparent;color:var(--dsw-alias-label-secondary,inherit);font:inherit;cursor:pointer}.odc-tab:hover{background:var(--dsw-alias-bg-layer-1,transparent)}.odc-tab[aria-selected=true]{color:var(--dsw-alias-label-primary,inherit);border-color:var(--dsw-alias-border-l3,transparent);background:var(--dsw-alias-bg-layer-1,transparent)}
|
|
20272
20283
|
.odc-panel{display:grid;gap:14px}.odc-card{min-width:0;padding:15px;border:1px solid var(--dsw-alias-border-l4,transparent);border-radius:12px;background:var(--dsw-alias-bg-layer-1,transparent)}.odc-card>p{margin-top:6px}.odc-card-head,.odc-row{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap}.odc-card-head{margin-bottom:12px}
|
|
20273
20284
|
.odc-quota-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:10px}.odc-metric{display:grid;align-content:start;gap:5px;min-height:96px}.odc-metric-value{font-size:20px;font-weight:650;font-variant-numeric:tabular-nums;overflow-wrap:anywhere}.odc-metric-value.odc-metric-text{font-size:13px;font-weight:600;line-height:1.55}.odc-quota-grid+.odc-quota-grid{margin-top:10px}
|
|
20274
|
-
.odc-label,.odc-hint,.odc-meta{color:var(--dsw-alias-label-secondary,inherit);font-size:11px;line-height:1.6}.odc-meta{margin-top:10px!important}
|
|
20285
|
+
.odc-label,.odc-hint,.odc-meta{color:var(--dsw-alias-label-secondary,inherit);font-size:11px;line-height:1.6}.odc-meta{margin-top:10px!important}
|
|
20286
|
+
.odc-window{display:grid;gap:10px;margin-top:12px;padding:14px;border-radius:10px;background:var(--dsw-alias-bg-layer-2,transparent);min-width:0}.odc-window-head{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap}.odc-window h4{margin:0;font-size:13px;font-weight:600}.odc-window-remaining{display:flex;align-items:baseline;gap:6px;font-variant-numeric:tabular-nums;white-space:nowrap}.odc-window-remaining strong{font-size:22px;line-height:1.2}.odc-window progress{display:block;width:100%;height:8px;accent-color:var(--dsw-alias-brand-primary,Highlight)}
|
|
20287
|
+
.odc-window-usage{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:10px;margin:0}.odc-window-usage>div{display:grid;gap:3px;min-width:0}.odc-window dt,.odc-quota-footer dt{color:var(--dsw-alias-label-secondary,inherit);font-size:11px}.odc-window dd,.odc-quota-footer dd{margin:0;min-width:0;overflow-wrap:anywhere;font-variant-numeric:tabular-nums}.odc-window-reset{display:grid;gap:3px;padding-top:10px;border-top:1px solid var(--dsw-alias-border-l4,transparent)}.odc-window-reset time{font-size:12px}.odc-window-details>summary{cursor:pointer;font-size:11px;color:var(--dsw-alias-label-secondary,inherit);min-height:32px;padding:6px 0}.odc-window-details dl{display:grid;gap:8px;margin:6px 0 0}.odc-window-details dl>div{display:grid;gap:3px}.odc-quota-footer{display:grid;gap:8px;margin:0;padding-top:10px;border-top:1px solid var(--dsw-alias-border-l4,transparent)}.odc-quota-footer>div{display:grid;grid-template-columns:72px minmax(0,1fr);gap:10px}.odc-quota-footer dd{font-size:11px;color:var(--dsw-alias-label-secondary,inherit)}
|
|
20275
20288
|
.odc-button{display:inline-flex;align-items:center;justify-content:center;min-height:32px;padding:6px 12px;border:1px solid var(--dsw-alias-border-l3,transparent);border-radius:8px;background:var(--dsw-alias-bg-layer-2,transparent);color:var(--dsw-alias-label-primary,inherit);font:inherit;font-size:12px;cursor:pointer}.odc-button:hover:not(:disabled){border-color:var(--dsw-alias-brand-primary,Highlight)}.odc-button-primary{background:var(--dsw-alias-button-primary-fill,var(--dsw-alias-brand-primary,Highlight));color:var(--dsw-alias-label-primary-foreground,HighlightText);border-color:transparent}.odc-button-primary:hover:not(:disabled){background:var(--dsw-alias-button-primary-hover,var(--dsw-alias-brand-primary,Highlight))}.odc-button:disabled{opacity:.55;cursor:not-allowed}.odc-button-small{min-height:26px;padding:3px 9px;font-size:11px}.odc-actions{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
|
|
20276
20289
|
.odc-notice{padding:9px 11px;border-radius:8px;background:var(--dsw-alias-bg-layer-2,transparent);font-size:12px;line-height:1.6}.odc-notice[data-kind=error]{color:var(--dsw-alias-state-error-primary,inherit);color:color-mix(in srgb,var(--dsw-alias-state-error-primary,CanvasText) 85%,var(--dsw-alias-label-primary,CanvasText))}
|
|
20277
20290
|
.odc-model-groups{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px;margin-top:12px}.odc-model-list{display:grid;gap:6px;margin:10px 0 0;padding:0;list-style:none}.odc-model-item{padding:9px 10px;border-radius:8px;background:var(--dsw-alias-bg-layer-2,transparent);min-width:0}.odc-model-head{display:flex;align-items:flex-start;justify-content:space-between;gap:8px;flex-wrap:wrap}.odc-model-switch{min-width:0;flex:1 1 190px}.odc-model-item strong,.odc-model-item code{display:block;overflow-wrap:anywhere}.odc-model-item strong{font-size:12px;font-weight:600}.odc-model-item code{margin-top:2px;color:var(--dsw-alias-label-secondary,inherit);font-size:11px}.odc-model-meta{margin-top:6px!important;color:var(--dsw-alias-label-secondary,inherit);font-size:11px;overflow-wrap:anywhere}.odc-model-count{color:var(--dsw-alias-label-secondary,inherit);font-size:11px;font-weight:400}.odc-chip{display:inline-flex;align-items:center;padding:1px 7px;border:1px solid var(--dsw-alias-border-l3,transparent);border-radius:999px;color:var(--dsw-alias-label-secondary,inherit);font-size:10px;line-height:1.6}
|
|
@@ -20464,19 +20477,49 @@ function QuotaView({ quota, nextAutoRefreshAt, refreshIntervalSeconds }) {
|
|
|
20464
20477
|
React.Fragment,
|
|
20465
20478
|
null,
|
|
20466
20479
|
h("p", { className: "odc-metric-value" }, "\u2014"),
|
|
20467
|
-
h("p", { className: "odc-hint" }, "\
|
|
20468
|
-
) : quota.windows.map((window, index) =>
|
|
20469
|
-
|
|
20470
|
-
|
|
20471
|
-
h(
|
|
20472
|
-
"
|
|
20473
|
-
{ className: "odc-
|
|
20474
|
-
h(
|
|
20475
|
-
|
|
20476
|
-
|
|
20477
|
-
|
|
20478
|
-
|
|
20479
|
-
|
|
20480
|
+
h("p", { className: "odc-hint" }, "\u6682\u65F6\u65E0\u6CD5\u83B7\u53D6\u989D\u5EA6\u7A97\u53E3\u3002")
|
|
20481
|
+
) : quota.windows.map((window, index) => {
|
|
20482
|
+
const label = windowLabel(window.durationSeconds);
|
|
20483
|
+
const remainingPercent = Math.max(0, Math.min(100, 100 - window.percent));
|
|
20484
|
+
return h(
|
|
20485
|
+
"section",
|
|
20486
|
+
{ className: "odc-window", key: `${window.durationSeconds}-${index}`, "aria-label": label },
|
|
20487
|
+
h(
|
|
20488
|
+
"div",
|
|
20489
|
+
{ className: "odc-window-head" },
|
|
20490
|
+
h("h4", null, label),
|
|
20491
|
+
h(
|
|
20492
|
+
"div",
|
|
20493
|
+
{ className: "odc-window-remaining" },
|
|
20494
|
+
h("strong", null, `${remainingPercent.toFixed(1)}%`),
|
|
20495
|
+
h("span", { className: "odc-label" }, "\u5269\u4F59")
|
|
20496
|
+
)
|
|
20497
|
+
),
|
|
20498
|
+
h("progress", { max: 100, value: remainingPercent, "aria-label": `${label}\u5269\u4F59\u989D\u5EA6` }),
|
|
20499
|
+
h(
|
|
20500
|
+
"dl",
|
|
20501
|
+
{ className: "odc-window-usage", "aria-label": "\u7A97\u53E3\u7528\u91CF\u660E\u7EC6" },
|
|
20502
|
+
[{ label: "\u5DF2\u7528", value: window.used }, { label: "\u4E0A\u9650", value: window.limit }, { label: "\u5269\u4F59", value: window.remaining ?? "\u2014" }].map((item) => h("div", { key: item.label }, h("dt", null, item.label), h("dd", null, item.value)))
|
|
20503
|
+
),
|
|
20504
|
+
h(
|
|
20505
|
+
"div",
|
|
20506
|
+
{ className: "odc-window-reset" },
|
|
20507
|
+
h("span", { className: "odc-label" }, "\u4E0B\u6B21\u6062\u590D"),
|
|
20508
|
+
window.resetsAt === void 0 ? h("span", null, "\u2014") : h("time", { dateTime: window.resetsAt }, formatTime(window.resetsAt))
|
|
20509
|
+
),
|
|
20510
|
+
window.windowStart === void 0 && window.resetMode === void 0 ? null : h(
|
|
20511
|
+
"details",
|
|
20512
|
+
{ className: "odc-window-details" },
|
|
20513
|
+
h("summary", null, "\u7A97\u53E3\u8BE6\u60C5"),
|
|
20514
|
+
h(
|
|
20515
|
+
"dl",
|
|
20516
|
+
null,
|
|
20517
|
+
window.windowStart === void 0 ? null : h("div", null, h("dt", null, "\u7A97\u53E3\u5F00\u59CB"), h("dd", null, h("time", { dateTime: window.windowStart }, formatTime(window.windowStart)))),
|
|
20518
|
+
window.resetMode === void 0 ? null : h("div", null, h("dt", null, "\u91CD\u7F6E\u65B9\u5F0F"), h("dd", null, RESET_MODE_LABELS[window.resetMode] ?? window.resetMode))
|
|
20519
|
+
)
|
|
20520
|
+
)
|
|
20521
|
+
);
|
|
20522
|
+
})
|
|
20480
20523
|
),
|
|
20481
20524
|
h("div", { className: "odc-quota-grid" }, metrics.map((metric) => h(
|
|
20482
20525
|
"div",
|
|
@@ -20492,12 +20535,17 @@ function QuotaView({ quota, nextAutoRefreshAt, refreshIntervalSeconds }) {
|
|
|
20492
20535
|
h("strong", { className: "odc-metric-value odc-metric-text" }, metric.value),
|
|
20493
20536
|
h("span", { className: "odc-hint" }, metric.hint)
|
|
20494
20537
|
))),
|
|
20495
|
-
h(
|
|
20538
|
+
h(
|
|
20539
|
+
"dl",
|
|
20540
|
+
{ className: "odc-quota-footer", "aria-label": "\u989D\u5EA6\u6570\u636E\u6765\u6E90\u4E0E\u66F4\u65B0\u65F6\u95F4" },
|
|
20541
|
+
h("div", null, h("dt", null, "\u6700\u8FD1\u66F4\u65B0"), h("dd", null, h("time", { dateTime: quota.updatedAt }, formatTime(quota.updatedAt)))),
|
|
20542
|
+
quota.source === void 0 ? null : h("div", null, h("dt", null, "\u6570\u636E\u6765\u6E90"), h("dd", null, SOURCE_LABELS[quota.source]))
|
|
20543
|
+
),
|
|
20496
20544
|
h(
|
|
20497
20545
|
"details",
|
|
20498
20546
|
{ className: "odc-model-details" },
|
|
20499
20547
|
h("summary", null, "\u5982\u4F55\u7406\u89E3\u8FD9\u4E9B\u989D\u5EA6\uFF1F"),
|
|
20500
|
-
h("p", { className: "odc-hint" }, "\u8D60\u9001\u7A97\u53E3\
|
|
20548
|
+
h("p", { className: "odc-hint" }, "\u8D60\u9001\u7A97\u53E3\u663E\u793A\u5468\u671F\u5185\u7684\u4F7F\u7528\u91CF\u3002\u5957\u9910\u4F59\u989D\u548C\u5145\u503C / \u8D60\u9001\u91D1\u989D\u662F\u94B1\u5305\u7684\u4E0D\u540C\u5206\u6C60\uFF0C\u603B\u989D\u5EA6\u662F\u94B1\u5305\u5408\u8BA1\u3002\u2014 \u8868\u793A\u6682\u65E0\u6570\u636E\u3002")
|
|
20501
20549
|
),
|
|
20502
20550
|
quota.note !== void 0 ? h("p", { className: "odc-notice", "data-kind": quota.state === "error" ? "error" : "status", role: quota.state === "error" ? "alert" : "status" }, quota.note) : null
|
|
20503
20551
|
);
|
|
@@ -20578,7 +20626,7 @@ function Overview({ status, busy, onRefresh, nextAutoRefreshAt, refreshIntervalS
|
|
|
20578
20626
|
h(
|
|
20579
20627
|
"div",
|
|
20580
20628
|
{ className: "odc-card-head" },
|
|
20581
|
-
h("div", null, h("h3", null, "\u989D\u5EA6\u6982\u89C8"), h("p", { className: "odc-hint" }, "\u5957\u9910\
|
|
20629
|
+
h("div", null, h("h3", null, "\u989D\u5EA6\u6982\u89C8"), h("p", { className: "odc-hint" }, "\u67E5\u770B\u5957\u9910\u7528\u91CF\u3001\u8BA2\u9605\u4F59\u989D\u548C\u5145\u503C\u4F59\u989D\u3002")),
|
|
20582
20630
|
h("button", { className: "odc-button", type: "button", disabled: busy, onClick: onRefresh }, busy ? "\u5237\u65B0\u4E2D\u2026" : "\u5237\u65B0\u989D\u5EA6")
|
|
20583
20631
|
),
|
|
20584
20632
|
h(QuotaView, { quota: status?.quota, nextAutoRefreshAt, refreshIntervalSeconds })
|
|
@@ -20852,7 +20900,7 @@ function Models({ status, formSnapshot, setFormField, pendingField, onRefreshMod
|
|
|
20852
20900
|
saving.current = false;
|
|
20853
20901
|
}
|
|
20854
20902
|
};
|
|
20855
|
-
const source = status?.modelsSource === "openai" ? "
|
|
20903
|
+
const source = status?.modelsSource === "openai" ? "\u5F53\u524D\u7F51\u5173" : status?.modelsSource === "builtin" ? "\u5185\u7F6E\u76EE\u5F55" : "\u5C1A\u672A\u786E\u8BA4";
|
|
20856
20904
|
const updated = status?.modelsUpdatedAt === void 0 ? "" : ` \xB7 \u66F4\u65B0\u4E8E ${formatTime(status.modelsUpdatedAt)}`;
|
|
20857
20905
|
const models = status?.models ?? [];
|
|
20858
20906
|
return h(
|
|
@@ -20865,7 +20913,7 @@ function Models({ status, formSnapshot, setFormField, pendingField, onRefreshMod
|
|
|
20865
20913
|
"div",
|
|
20866
20914
|
null,
|
|
20867
20915
|
h("h3", null, "\u53EF\u7528\u6A21\u578B"),
|
|
20868
|
-
h("p", { className: "odc-hint" }, "\
|
|
20916
|
+
h("p", { className: "odc-hint" }, "\u6309\u5206\u7EC4\u641C\u7D22\u6A21\u578B\uFF0C\u8BBE\u7F6E\u542F\u7528\u72B6\u6001\u4E0E\u9ED8\u8BA4\u53C2\u6570\u3002")
|
|
20869
20917
|
),
|
|
20870
20918
|
h(
|
|
20871
20919
|
"div",
|
|
@@ -20875,8 +20923,9 @@ function Models({ status, formSnapshot, setFormField, pendingField, onRefreshMod
|
|
|
20875
20923
|
className: "odc-button",
|
|
20876
20924
|
type: "button",
|
|
20877
20925
|
disabled: refreshingModels || status === void 0 || status.apiKeyConfigured === false,
|
|
20878
|
-
onClick: onRefreshModels
|
|
20879
|
-
|
|
20926
|
+
onClick: onRefreshModels,
|
|
20927
|
+
title: "\u4ECE\u5F53\u524D\u914D\u7F6E\u7684\u7F51\u5173\u8BFB\u53D6\u53EF\u7528\u6A21\u578B\u76EE\u5F55"
|
|
20928
|
+
}, refreshingModels ? "\u6B63\u5728\u5237\u65B0\u6A21\u578B\u2026" : "\u5237\u65B0\u6A21\u578B\u76EE\u5F55")
|
|
20880
20929
|
)
|
|
20881
20930
|
),
|
|
20882
20931
|
status?.apiKeyConfigured === false ? h("p", { className: "odc-hint" }, "\u5237\u65B0\u6A21\u578B\u9700\u8981\u53EF\u7528\u7684 API Key\uFF1B\u4FDD\u5B58 Key \u540E\u91CD\u8BD5\u3002") : null,
|
|
@@ -20885,8 +20934,8 @@ function Models({ status, formSnapshot, setFormField, pendingField, onRefreshMod
|
|
|
20885
20934
|
models.length === 0 ? h("p", { className: "odc-hint", role: "status" }, "\u6682\u65E0\u53EF\u7528\u6A21\u578B\uFF1B\u53EF\u5237\u65B0\u6A21\u578B\u5217\u8868\u540E\u91CD\u8BD5\u3002") : h(
|
|
20886
20935
|
"div",
|
|
20887
20936
|
{ className: "odc-model-groups" },
|
|
20888
|
-
h(ModelGroup, { title: "\u5957\u9910\u8D60\u9001
|
|
20889
|
-
h(ModelGroup, { title: "\u4ED8\u8D39
|
|
20937
|
+
h(ModelGroup, { title: "\u5957\u9910\u8D60\u9001\u6A21\u578B", group: "plan", models, settingsMap, authoritative, writable, pending, onCommit: commit }),
|
|
20938
|
+
h(ModelGroup, { title: "\u4ED8\u8D39\u6A21\u578B", group: "paid", models, settingsMap, authoritative, writable, pending, onCommit: commit })
|
|
20890
20939
|
)
|
|
20891
20940
|
);
|
|
20892
20941
|
}
|
|
@@ -20978,12 +21027,12 @@ function Advanced({ status, formSnapshot, setFormField, pendingField }) {
|
|
|
20978
21027
|
"section",
|
|
20979
21028
|
{ className: "odc-card" },
|
|
20980
21029
|
h("h3", null, "\u7A7A\u8F6E\u76D1\u63A7"),
|
|
20981
|
-
h("p", { className: "odc-hint" }, "\
|
|
21030
|
+
h("p", { className: "odc-hint" }, "\u68C0\u6D4B\u5957\u9910\u8D60\u9001\u6A21\u578B\u5728\u5DE5\u5177\u5BF9\u8BDD\u4E2D\u8FD4\u56DE\u7684\u7A7A\u56DE\u7B54\u3002"),
|
|
20982
21031
|
h("div", { style: { marginTop: 14 } }, h(Switch, {
|
|
20983
21032
|
checked: formSnapshot.value?.emptyTurnGuard ?? status?.config.emptyTurnGuard ?? true,
|
|
20984
21033
|
disabled: !writable || pendingField.includes("emptyTurnGuard"),
|
|
20985
21034
|
label: "\u542F\u7528\u7A7A\u8F6E\u76D1\u63A7",
|
|
20986
|
-
hint: `\
|
|
21035
|
+
hint: `\u5DF2\u68C0\u6D4B\u5230 ${status?.guardedTurns ?? "\u2014"} \u6B21\u7A7A\u56DE\u7B54\u3002\u81EA\u52A8\u91CD\u8BD5\u7531 DSH \u7684\u91CD\u8BD5\u8BBE\u7F6E\u63A7\u5236\uFF0C\u91CD\u8BD5\u53EF\u80FD\u989D\u5916\u6D88\u8017\u989D\u5EA6\u3002`,
|
|
20987
21036
|
onChange: (checked) => {
|
|
20988
21037
|
void setFormField("emptyTurnGuard", checked);
|
|
20989
21038
|
}
|
|
@@ -20993,7 +21042,7 @@ function Advanced({ status, formSnapshot, setFormField, pendingField }) {
|
|
|
20993
21042
|
"section",
|
|
20994
21043
|
{ className: "odc-card" },
|
|
20995
21044
|
h("h3", null, "\u63A8\u7406\u534F\u8BAE"),
|
|
20996
|
-
h("p", { className: "odc-hint" }, "\
|
|
21045
|
+
h("p", { className: "odc-hint" }, "\u9009\u62E9\u5F53\u524D\u7F51\u5173\u652F\u6301\u7684\u63A8\u7406\u534F\u8BAE\u3002\u6A21\u578B\u76EE\u5F55\u59CB\u7EC8\u4ECE\u8BE5\u7F51\u5173\u8BFB\u53D6\u3002"),
|
|
20997
21046
|
h(
|
|
20998
21047
|
"div",
|
|
20999
21048
|
{ className: "odc-field" },
|
|
@@ -21041,7 +21090,7 @@ function Advanced({ status, formSnapshot, setFormField, pendingField }) {
|
|
|
21041
21090
|
className: "odc-input",
|
|
21042
21091
|
type: "text",
|
|
21043
21092
|
value: apiKeyEnv,
|
|
21044
|
-
disabled: !writable,
|
|
21093
|
+
disabled: !writable || pendingField.includes("apiKeyEnv"),
|
|
21045
21094
|
autoCapitalize: "off",
|
|
21046
21095
|
spellCheck: false,
|
|
21047
21096
|
onChange: (event) => setApiKeyEnv(event.target.value)
|
|
@@ -21061,7 +21110,7 @@ function Advanced({ status, formSnapshot, setFormField, pendingField }) {
|
|
|
21061
21110
|
"section",
|
|
21062
21111
|
{ className: "odc-card" },
|
|
21063
21112
|
h("h3", null, "\u8BF7\u6C42\u65F6\u9650\u4E0E\u81EA\u52A8\u5237\u65B0"),
|
|
21064
|
-
h("p", { className: "odc-hint" }, "\
|
|
21113
|
+
h("p", { className: "odc-hint" }, "\u8F93\u5165\u6709\u6548\u8303\u56F4\u5185\u7684\u6574\u6570\uFF0C\u79BB\u5F00\u8F93\u5165\u6846\u540E\u4FDD\u5B58\u3002"),
|
|
21065
21114
|
h(NumberField, {
|
|
21066
21115
|
id: "odc-request-timeout",
|
|
21067
21116
|
label: "\u8BF7\u6C42\u603B\u8D85\u65F6\uFF08\u6BEB\u79D2\uFF09",
|
|
@@ -21112,14 +21161,32 @@ function loginInFlight(state) {
|
|
|
21112
21161
|
var ACTIVATION_OPEN_LABELS = {
|
|
21113
21162
|
opened: "\u5DF2\u5728\u65B0\u7A97\u53E3\u6253\u5F00\u5B98\u65B9\u6388\u6743\u9875\uFF1B\u8BF7\u5728\u8BE5\u7A97\u53E3\u786E\u8BA4\u8BBE\u5907\u7801\u3002",
|
|
21114
21163
|
"no-link": "\u6388\u6743\u7801\u5DF2\u5931\u6548\uFF0C\u8BF7\u91CD\u65B0\u7533\u8BF7\u3002",
|
|
21115
|
-
"invalid-url": "\u6388\u6743\u94FE\u63A5\
|
|
21164
|
+
"invalid-url": "\u6388\u6743\u94FE\u63A5\u65E0\u6548\uFF0C\u8BF7\u53D6\u6D88\u5E76\u91CD\u65B0\u5F00\u59CB\u767B\u5F55\u3002",
|
|
21116
21165
|
unavailable: "\u65E0\u6CD5\u542F\u52A8\u4E34\u65F6\u6D4F\u89C8\u5668\uFF0C\u8BF7\u786E\u8BA4\u5DF2\u5B89\u88C5 Chrome\uFF1B\u4E5F\u53EF\u590D\u5236\u94FE\u63A5\u624B\u52A8\u6253\u5F00\u3002",
|
|
21117
21166
|
failed: "\u4E34\u65F6\u6D4F\u89C8\u5668\u7A97\u53E3\u672A\u80FD\u6253\u5F00\uFF0C\u8BF7\u590D\u5236\u94FE\u63A5\u624B\u52A8\u6253\u5F00\u3002"
|
|
21118
21167
|
};
|
|
21119
21168
|
function LoginApproval({ login, onOpen, opening, notice }) {
|
|
21169
|
+
const mounted = useMounted();
|
|
21170
|
+
const copyVersion = React.useRef(0);
|
|
21171
|
+
const [copyState, setCopyState] = React.useState("idle");
|
|
21172
|
+
React.useEffect(() => {
|
|
21173
|
+
copyVersion.current += 1;
|
|
21174
|
+
setCopyState("idle");
|
|
21175
|
+
}, [login?.jobId, login?.state, login?.activationUrl]);
|
|
21120
21176
|
if (login?.state !== "waiting" || login.userCode === void 0 || login.expiresAt === void 0) return null;
|
|
21121
21177
|
const url2 = validateActivationUrl(login.activationUrl, login.userCode);
|
|
21122
21178
|
if (url2 === null) return null;
|
|
21179
|
+
const copyLink = async () => {
|
|
21180
|
+
const version2 = ++copyVersion.current;
|
|
21181
|
+
setCopyState("copying");
|
|
21182
|
+
try {
|
|
21183
|
+
if (typeof navigator.clipboard?.writeText !== "function") throw new Error("clipboard-unavailable");
|
|
21184
|
+
await navigator.clipboard.writeText(url2);
|
|
21185
|
+
if (mounted.current && version2 === copyVersion.current) setCopyState("copied");
|
|
21186
|
+
} catch {
|
|
21187
|
+
if (mounted.current && version2 === copyVersion.current) setCopyState("manual");
|
|
21188
|
+
}
|
|
21189
|
+
};
|
|
21123
21190
|
return h(
|
|
21124
21191
|
"div",
|
|
21125
21192
|
{ className: "odc-readonly", "aria-label": "\u8BBE\u5907\u6388\u6743" },
|
|
@@ -21136,14 +21203,24 @@ function LoginApproval({ login, onOpen, opening, notice }) {
|
|
|
21136
21203
|
onOpen?.();
|
|
21137
21204
|
}
|
|
21138
21205
|
}, opening === true ? "\u6B63\u5728\u6253\u5F00\u2026" : "\u5728\u65B0\u7A97\u53E3\u6253\u5F00\u6388\u6743\u9875"),
|
|
21139
|
-
h("
|
|
21206
|
+
h("button", { className: "odc-button", type: "button", disabled: copyState === "copying", onClick: () => {
|
|
21207
|
+
void copyLink();
|
|
21208
|
+
} }, copyState === "copying" ? "\u6B63\u5728\u590D\u5236\u2026" : "\u590D\u5236\u6388\u6743\u94FE\u63A5"),
|
|
21209
|
+
h("a", { className: "odc-link", href: url2, target: "_blank", rel: "noreferrer noopener" }, "\u5B98\u65B9\u6388\u6743\u9875")
|
|
21140
21210
|
),
|
|
21211
|
+
copyState === "copied" ? h("p", { className: "odc-hint", role: "status" }, "\u94FE\u63A5\u5DF2\u590D\u5236\uFF0C\u53EF\u5728\u5E38\u7528\u6D4F\u89C8\u5668\u4E2D\u7C98\u8D34\u6253\u5F00\u3002") : null,
|
|
21212
|
+
copyState === "manual" ? h(
|
|
21213
|
+
"label",
|
|
21214
|
+
{ className: "odc-field" },
|
|
21215
|
+
h("span", null, "\u8BF7\u9009\u62E9\u5E76\u590D\u5236\u6388\u6743\u94FE\u63A5"),
|
|
21216
|
+
h("input", { className: "odc-input", type: "text", readOnly: true, value: url2, onFocus: (event) => event.target.select() })
|
|
21217
|
+
) : null,
|
|
21141
21218
|
notice ? h(NoticeView, { notice }) : null,
|
|
21142
21219
|
h("p", { className: "odc-hint" }, `\u6388\u6743\u7801\u6709\u6548\u81F3 ${formatTime(login.expiresAt)}\u3002\u5728\u6388\u6743\u7A97\u53E3\u786E\u8BA4\u540E\uFF0C\u8FD4\u56DE\u6B64\u9875\u67E5\u770B\u7ED3\u679C\u3002`),
|
|
21143
|
-
h("p", { className: "odc-hint" }, "\
|
|
21220
|
+
h("p", { className: "odc-hint" }, "\u4E34\u65F6 Chrome \u7A97\u53E3\u9700\u8981\u5355\u72EC\u767B\u5F55\uFF1B\u4E5F\u53EF\u590D\u5236\u94FE\u63A5\u5230\u5DF2\u767B\u5F55\u7684\u5E38\u7528\u6D4F\u89C8\u5668\u3002\u4EC5\u786E\u8BA4\u4F60\u672C\u4EBA\u53D1\u8D77\u7684\u6388\u6743\u3002")
|
|
21144
21221
|
);
|
|
21145
21222
|
}
|
|
21146
|
-
function Connection({ status, formSnapshot, setFormField, pendingField, caller,
|
|
21223
|
+
function Connection({ status, formSnapshot, setFormField, pendingField, caller, onLoginStatus, onStatus }) {
|
|
21147
21224
|
const mounted = useMounted();
|
|
21148
21225
|
const actionVersion = React.useRef(0);
|
|
21149
21226
|
const [busy, setBusy] = React.useState(false);
|
|
@@ -21154,6 +21231,7 @@ function Connection({ status, formSnapshot, setFormField, pendingField, caller,
|
|
|
21154
21231
|
const [activationNotice, setActivationNotice] = React.useState(null);
|
|
21155
21232
|
const activationJob = React.useRef(null);
|
|
21156
21233
|
const activationToken = React.useRef(0);
|
|
21234
|
+
const autoOpenPending = React.useRef(false);
|
|
21157
21235
|
React.useEffect(() => () => {
|
|
21158
21236
|
actionVersion.current += 1;
|
|
21159
21237
|
}, []);
|
|
@@ -21172,15 +21250,17 @@ function Connection({ status, formSnapshot, setFormField, pendingField, caller,
|
|
|
21172
21250
|
if (status === void 0 || busy || keyBusy) return;
|
|
21173
21251
|
const version2 = ++actionVersion.current;
|
|
21174
21252
|
setBusy(true);
|
|
21253
|
+
autoOpenPending.current = true;
|
|
21175
21254
|
setNotice({ kind: "status", text: "\u6B63\u5728\u7533\u8BF7\u8BBE\u5907\u6388\u6743\u2026" });
|
|
21176
21255
|
try {
|
|
21177
21256
|
const next = await caller("startLogin", { expectedRevision: status.revision });
|
|
21178
21257
|
if (!mounted.current || version2 !== actionVersion.current) return;
|
|
21258
|
+
onLoginStatus(next);
|
|
21179
21259
|
setNotice(null);
|
|
21180
21260
|
setActivationNotice(null);
|
|
21181
|
-
await (next.state === "success" ? refreshAfterLogin() : loadStatus());
|
|
21182
21261
|
} catch {
|
|
21183
|
-
|
|
21262
|
+
autoOpenPending.current = false;
|
|
21263
|
+
if (mounted.current && version2 === actionVersion.current) setNotice({ kind: "error", text: "\u767B\u5F55\u8BF7\u6C42\u6682\u672A\u786E\u8BA4\uFF0C\u8BF7\u91CD\u8BD5\u3002" });
|
|
21184
21264
|
} finally {
|
|
21185
21265
|
if (mounted.current && version2 === actionVersion.current) setBusy(false);
|
|
21186
21266
|
}
|
|
@@ -21190,10 +21270,11 @@ function Connection({ status, formSnapshot, setFormField, pendingField, caller,
|
|
|
21190
21270
|
const version2 = ++actionVersion.current;
|
|
21191
21271
|
setBusy(true);
|
|
21192
21272
|
try {
|
|
21193
|
-
await caller("cancelLogin", { jobId: login.jobId });
|
|
21273
|
+
const next = await caller("cancelLogin", { jobId: login.jobId });
|
|
21194
21274
|
if (!mounted.current || version2 !== actionVersion.current) return;
|
|
21195
|
-
|
|
21196
|
-
|
|
21275
|
+
autoOpenPending.current = false;
|
|
21276
|
+
onLoginStatus(next);
|
|
21277
|
+
setNotice({ kind: "status", text: next.message ?? LOGIN_LABELS[next.state] });
|
|
21197
21278
|
} catch {
|
|
21198
21279
|
if (mounted.current && version2 === actionVersion.current) setNotice({ kind: "error", text: "\u53D6\u6D88\u672A\u5B8C\u6210\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002" });
|
|
21199
21280
|
} finally {
|
|
@@ -21210,15 +21291,15 @@ function Connection({ status, formSnapshot, setFormField, pendingField, caller,
|
|
|
21210
21291
|
setKeyBusy(true);
|
|
21211
21292
|
setNotice(null);
|
|
21212
21293
|
try {
|
|
21213
|
-
await caller("saveApiKey", { value: apiKey, expectedRevision: status.revision });
|
|
21294
|
+
const next = await caller("saveApiKey", { value: apiKey, expectedRevision: status.revision });
|
|
21214
21295
|
if (!mounted.current || version2 !== actionVersion.current) return;
|
|
21215
21296
|
setApiKey("");
|
|
21216
|
-
|
|
21217
|
-
|
|
21297
|
+
onStatus(next);
|
|
21298
|
+
setNotice({ kind: "status", text: next.apiKeySource === "reference" ? `API Key \u5DF2\u4FDD\u5B58\uFF1B\u5F53\u524D\u4ECD\u4F18\u5148\u4F7F\u7528\u73AF\u5883\u6216\u51ED\u636E\u5F15\u7528 ${next.config.apiKeyEnv}\u3002` : next.apiKeySource === "stored" ? "API Key \u5DF2\u4FDD\u5B58\u5E76\u7528\u4E8E\u5F53\u524D\u7F51\u5173\u3002" : "API Key \u5DF2\u4FDD\u5B58\u3002" });
|
|
21218
21299
|
} catch {
|
|
21219
21300
|
if (!mounted.current || version2 !== actionVersion.current) return;
|
|
21220
21301
|
setApiKey("");
|
|
21221
|
-
setNotice({ kind: "error", text: "
|
|
21302
|
+
setNotice({ kind: "error", text: "\u4FDD\u5B58\u7ED3\u679C\u6682\u672A\u786E\u8BA4\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002" });
|
|
21222
21303
|
} finally {
|
|
21223
21304
|
if (mounted.current && version2 === actionVersion.current) setKeyBusy(false);
|
|
21224
21305
|
}
|
|
@@ -21240,7 +21321,17 @@ function Connection({ status, formSnapshot, setFormField, pendingField, caller,
|
|
|
21240
21321
|
if (mounted.current && activationToken.current === token) setOpening(false);
|
|
21241
21322
|
}
|
|
21242
21323
|
};
|
|
21324
|
+
React.useEffect(() => {
|
|
21325
|
+
if (!autoOpenPending.current || busy || keyBusy || opening || status === void 0) return;
|
|
21326
|
+
if (state === "waiting") {
|
|
21327
|
+
autoOpenPending.current = false;
|
|
21328
|
+
void openActivation();
|
|
21329
|
+
} else if (state === "error" || state === "cancelled" || state === "success") {
|
|
21330
|
+
autoOpenPending.current = false;
|
|
21331
|
+
}
|
|
21332
|
+
}, [state, login?.jobId, busy, keyBusy, opening, status]);
|
|
21243
21333
|
const desktopChecked = formSnapshot.value?.useDesktopCredential ?? status?.config.useDesktopCredential ?? true;
|
|
21334
|
+
const keySource = status?.apiKeySource === "reference" ? `\u73AF\u5883\u6216\u51ED\u636E\u5F15\u7528\uFF08${status.config.apiKeyEnv}\uFF09` : status?.apiKeySource === "stored" ? "\u5DF2\u4FDD\u5B58\u7684 API Key" : status?.apiKeySource === "device" ? "\u8BBE\u5907\u6388\u6743" : status?.apiKeyConfigured ? "\u5C1A\u672A\u786E\u8BA4" : "\u672A\u914D\u7F6E";
|
|
21244
21335
|
return h(
|
|
21245
21336
|
React.Fragment,
|
|
21246
21337
|
null,
|
|
@@ -21256,7 +21347,7 @@ function Connection({ status, formSnapshot, setFormField, pendingField, caller,
|
|
|
21256
21347
|
checked: desktopChecked,
|
|
21257
21348
|
disabled: formSnapshot.status !== "ready" || formSnapshot.value === void 0 || !formSnapshot.writable || pendingField.includes("useDesktopCredential"),
|
|
21258
21349
|
label: "\u4F18\u5148\u4F7F\u7528\u684C\u9762\u767B\u5F55\u6001",
|
|
21259
|
-
hint: "\
|
|
21350
|
+
hint: "\u4F18\u5148\u663E\u793A\u684C\u9762\u7AEF\u767B\u5F55\u8D26\u53F7\u7684\u989D\u5EA6\u3002",
|
|
21260
21351
|
onChange: (checked) => {
|
|
21261
21352
|
void setFormField("useDesktopCredential", checked);
|
|
21262
21353
|
}
|
|
@@ -21289,8 +21380,9 @@ function Connection({ status, formSnapshot, setFormField, pendingField, caller,
|
|
|
21289
21380
|
h(
|
|
21290
21381
|
"section",
|
|
21291
21382
|
{ className: "odc-card" },
|
|
21292
|
-
h("h3", null, "API Key
|
|
21293
|
-
h("p", { className: "odc-
|
|
21383
|
+
h("h3", null, "API Key"),
|
|
21384
|
+
h("p", { className: "odc-meta", "aria-label": "\u5F53\u524D\u751F\u6548\u7684\u63A8\u7406\u51ED\u636E\u6765\u6E90" }, `\u5F53\u524D\u751F\u6548\u6765\u6E90\uFF1A${keySource}`),
|
|
21385
|
+
h("p", { className: "odc-hint" }, status?.apiKeyConfigured === true ? "\u5F53\u524D\u7F51\u5173\u5DF2\u914D\u7F6E\u63A8\u7406\u51ED\u636E\u3002\u53EF\u5728\u6B64\u4FDD\u5B58\u63D2\u4EF6\u4E13\u7528\u7684 API Key\u3002" : "\u5F53\u524D\u7F51\u5173\u5C1A\u65E0\u63A8\u7406\u51ED\u636E\u3002\u53EF\u5B8C\u6210\u8BBE\u5907\u6388\u6743\u4EE5\u4F7F\u7528\u5B98\u65B9\u7F51\u5173\uFF0C\u6216\u4E3A\u5F53\u524D\u7F51\u5173\u5355\u72EC\u4FDD\u5B58 API Key\u3002"),
|
|
21294
21386
|
h(
|
|
21295
21387
|
"form",
|
|
21296
21388
|
{ onSubmit: (event) => {
|
|
@@ -21359,6 +21451,19 @@ function SettingsPage({ caller, form }) {
|
|
|
21359
21451
|
...acceptedFormSnapshot,
|
|
21360
21452
|
value: acceptedFormSnapshot.value === void 0 ? void 0 : { ...acceptedFormSnapshot.value, ...pendingValues }
|
|
21361
21453
|
}), [acceptedFormSnapshot, pendingValues]);
|
|
21454
|
+
const acceptLoginStatus = React.useCallback((login) => {
|
|
21455
|
+
statusVersion.current += 1;
|
|
21456
|
+
loginVersion.current += 1;
|
|
21457
|
+
setStatus((previous) => previous === void 0 ? previous : { ...previous, login });
|
|
21458
|
+
setError(void 0);
|
|
21459
|
+
}, []);
|
|
21460
|
+
const acceptStatus = React.useCallback((next) => {
|
|
21461
|
+
statusVersion.current += 1;
|
|
21462
|
+
loginVersion.current += 1;
|
|
21463
|
+
setStatus(next);
|
|
21464
|
+
setModelsNotice(null);
|
|
21465
|
+
setError(void 0);
|
|
21466
|
+
}, []);
|
|
21362
21467
|
const loadStatus = React.useCallback(async () => {
|
|
21363
21468
|
const version2 = ++statusVersion.current;
|
|
21364
21469
|
try {
|
|
@@ -21461,7 +21566,7 @@ function SettingsPage({ caller, form }) {
|
|
|
21461
21566
|
if (!mounted.current || version2 !== modelsVersion.current) return;
|
|
21462
21567
|
setStatus(next);
|
|
21463
21568
|
setError(void 0);
|
|
21464
|
-
setModelsNotice(next.modelsError === void 0 ? { kind: "status", text: `\u5DF2\u4ECE
|
|
21569
|
+
setModelsNotice(next.modelsError === void 0 ? { kind: "status", text: `\u5DF2\u4ECE\u5F53\u524D\u7F51\u5173\u5237\u65B0\u6A21\u578B\u76EE\u5F55\uFF0C\u5171 ${next.models.length} \u4E2A\u6A21\u578B\u3002` } : null);
|
|
21465
21570
|
} catch {
|
|
21466
21571
|
if (mounted.current && version2 === modelsVersion.current) setModelsNotice({ kind: "error", text: "\u6A21\u578B\u5237\u65B0\u672A\u5B8C\u6210\uFF0C\u8BF7\u68C0\u67E5\u51ED\u636E\u3001\u7F51\u5173\u4E0E\u7F51\u7EDC\u540E\u91CD\u8BD5\u3002" });
|
|
21467
21572
|
} finally {
|
|
@@ -21482,10 +21587,7 @@ function SettingsPage({ caller, form }) {
|
|
|
21482
21587
|
const login = await caller("loginStatus");
|
|
21483
21588
|
if (stopped || !mounted.current || version2 !== loginVersion.current) return;
|
|
21484
21589
|
setStatus((previous) => previous === void 0 ? previous : { ...previous, login });
|
|
21485
|
-
if (!loginInFlight(login.state))
|
|
21486
|
-
if (login.state === "success") void refresh();
|
|
21487
|
-
else void loadStatus();
|
|
21488
|
-
}
|
|
21590
|
+
if (!loginInFlight(login.state) && login.state !== "success") void loadStatus();
|
|
21489
21591
|
} catch {
|
|
21490
21592
|
}
|
|
21491
21593
|
};
|
|
@@ -21499,6 +21601,11 @@ function SettingsPage({ caller, form }) {
|
|
|
21499
21601
|
loginVersion.current += 1;
|
|
21500
21602
|
};
|
|
21501
21603
|
}, [caller, loadStatus, loginActive, mounted, refresh]);
|
|
21604
|
+
React.useEffect(() => {
|
|
21605
|
+
if (loginState !== "success") return;
|
|
21606
|
+
void loadStatus();
|
|
21607
|
+
void refresh(true);
|
|
21608
|
+
}, [loginState, status?.login.jobId, loadStatus, refresh]);
|
|
21502
21609
|
const configuredSeconds = formSnapshot.value?.quotaRefreshSeconds ?? status?.config.quotaRefreshSeconds;
|
|
21503
21610
|
const refreshIntervalSeconds = configuredSeconds === void 0 ? DEFAULT_QUOTA_REFRESH_SECONDS : normaliseQuotaRefreshSeconds(configuredSeconds);
|
|
21504
21611
|
const quotaNextRefreshAt = status?.quota.nextRefreshAt;
|
|
@@ -21544,7 +21651,7 @@ function SettingsPage({ caller, form }) {
|
|
|
21544
21651
|
notice: modelsNotice
|
|
21545
21652
|
});
|
|
21546
21653
|
} else if (tab === "connection") {
|
|
21547
|
-
content = h(Connection, { status, formSnapshot, setFormField, pendingField, caller,
|
|
21654
|
+
content = h(Connection, { status, formSnapshot, setFormField, pendingField, caller, onLoginStatus: acceptLoginStatus, onStatus: acceptStatus });
|
|
21548
21655
|
} else {
|
|
21549
21656
|
content = h(Advanced, { status, formSnapshot, setFormField, pendingField });
|
|
21550
21657
|
}
|
|
@@ -21552,7 +21659,7 @@ function SettingsPage({ caller, form }) {
|
|
|
21552
21659
|
"div",
|
|
21553
21660
|
{ className: "odc-settings" },
|
|
21554
21661
|
h("h2", null, "OpenDesign CoRouter"),
|
|
21555
|
-
h("p", { className: "odc-intro" }, "\
|
|
21662
|
+
h("p", { className: "odc-intro" }, "\u67E5\u770B\u989D\u5EA6\uFF0C\u7BA1\u7406\u6A21\u578B\u3001\u8FDE\u63A5\u4E0E\u8BF7\u6C42\u8BBE\u7F6E\u3002"),
|
|
21556
21663
|
h("div", { className: "odc-tabs", role: "tablist", "aria-label": "CoRouter \u8BBE\u7F6E\u5206\u7C7B" }, TABS.map((item, index) => h("button", {
|
|
21557
21664
|
key: item.id,
|
|
21558
21665
|
ref: (node2) => {
|
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.7";
|
|
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
|
}
|
|
@@ -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),
|