dsh-opendesign-corouter 0.1.1 → 0.1.2
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 +6 -4
- package/lib/adapter.d.ts +3 -0
- package/lib/client.d.ts +117 -12
- package/lib/client.js +834 -123
- package/lib/config.d.ts +11 -0
- package/lib/generated/typert.host.js +100 -11
- package/lib/generated/typert.remote-client.d.ts +2 -0
- package/lib/generated/typert.remote-client.js +100 -11
- package/lib/index.d.ts +16 -0
- package/lib/index.js +1532 -203
- package/lib/index.js.map +4 -4
- package/lib/model-discovery.d.ts +39 -0
- package/lib/model-settings.d.ts +45 -0
- package/lib/protocol-options.d.ts +11 -0
- package/lib/protocols/chat-completions.d.ts +10 -0
- package/lib/protocols/errors.d.ts +45 -0
- package/lib/protocols/headers.d.ts +14 -0
- package/lib/protocols/index.d.ts +17 -0
- package/lib/protocols/messages.d.ts +29 -0
- package/lib/protocols/parts.d.ts +22 -0
- package/lib/protocols/responses.d.ts +32 -0
- package/lib/protocols/sse.d.ts +25 -0
- package/lib/protocols/types.d.ts +39 -0
- package/lib/protocols/usage.d.ts +34 -0
- package/lib/quota.d.ts +21 -1
- package/lib/remote.d.ts +14 -0
- package/lib/stream.d.ts +11 -3
- package/package.json +1 -1
package/lib/client.js
CHANGED
|
@@ -31,13 +31,27 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
31
31
|
// src/client.ts
|
|
32
32
|
var client_exports = {};
|
|
33
33
|
__export(client_exports, {
|
|
34
|
+
Advanced: () => Advanced,
|
|
35
|
+
ModelRow: () => ModelRow,
|
|
36
|
+
Models: () => Models,
|
|
37
|
+
Overview: () => Overview,
|
|
34
38
|
QuotaView: () => QuotaView,
|
|
35
39
|
SettingsPage: () => SettingsPage,
|
|
36
40
|
apply: () => apply,
|
|
41
|
+
formatTime: () => formatTime,
|
|
42
|
+
formatTokens: () => formatTokens,
|
|
37
43
|
formatUsd: () => formatUsd,
|
|
38
44
|
inject: () => inject,
|
|
45
|
+
modelEnabled: () => modelEnabled,
|
|
46
|
+
modelSettingsEntry: () => modelSettingsEntry,
|
|
39
47
|
name: () => name,
|
|
40
|
-
|
|
48
|
+
nextWindowResetAt: () => nextWindowResetAt,
|
|
49
|
+
normaliseQuotaRefreshSeconds: () => normaliseQuotaRefreshSeconds,
|
|
50
|
+
parseNumberInput: () => parseNumberInput,
|
|
51
|
+
protocolEndpoint: () => protocolEndpoint,
|
|
52
|
+
quotaAutoRefresh: () => quotaAutoRefresh,
|
|
53
|
+
tabAfter: () => tabAfter,
|
|
54
|
+
writeModelSettings: () => writeModelSettings
|
|
41
55
|
});
|
|
42
56
|
module.exports = __toCommonJS(client_exports);
|
|
43
57
|
var React = __toESM(require("react"), 1);
|
|
@@ -19911,6 +19925,77 @@ function record2(value) {
|
|
|
19911
19925
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
19912
19926
|
}
|
|
19913
19927
|
|
|
19928
|
+
// src/protocol-options.ts
|
|
19929
|
+
var API_PROTOCOL_IDS = ["chat-completions", "responses", "messages"];
|
|
19930
|
+
function openAiBaseURL(baseURL) {
|
|
19931
|
+
const base = baseURL.replace(/\/+$/u, "");
|
|
19932
|
+
return new URL(base).pathname === "/" ? `${base}/v1` : base;
|
|
19933
|
+
}
|
|
19934
|
+
function inferenceEndpoint(baseURL, protocol) {
|
|
19935
|
+
const suffix = protocol === "responses" ? "/responses" : protocol === "messages" ? "/messages" : "/chat/completions";
|
|
19936
|
+
return baseURL.trim() === "" ? suffix : `${openAiBaseURL(baseURL.trim())}${suffix}`;
|
|
19937
|
+
}
|
|
19938
|
+
var API_PROTOCOL_OPTIONS = [
|
|
19939
|
+
{ id: "chat-completions", name: "OpenAI Chat Completions", description: "\u4F7F\u7528 Chat Completions \u8BF7\u6C42\u4E0E\u6D41\u5F0F\u54CD\u5E94\u3002" },
|
|
19940
|
+
{ id: "responses", name: "OpenAI Responses", description: "\u4F7F\u7528 Responses \u8BF7\u6C42\u4E0E\u6D41\u5F0F\u54CD\u5E94\u3002" },
|
|
19941
|
+
{ id: "messages", name: "Anthropic Messages", description: "\u4F7F\u7528 Messages \u8BF7\u6C42\u4E0E\u6D41\u5F0F\u54CD\u5E94\u3002" }
|
|
19942
|
+
];
|
|
19943
|
+
|
|
19944
|
+
// src/model-settings.ts
|
|
19945
|
+
var MAX_ENTRIES = 512;
|
|
19946
|
+
var MAX_MODEL_ID_LENGTH = 128;
|
|
19947
|
+
var MODEL_ID = /^[A-Za-z0-9._:/-]{1,128}$/u;
|
|
19948
|
+
var MAX_TEMPERATURE = 2;
|
|
19949
|
+
var MAX_TOP_P = 1;
|
|
19950
|
+
var MAX_TOKENS = 1e7;
|
|
19951
|
+
var MAX_CONTEXT_WINDOW = 1e8;
|
|
19952
|
+
var REASONING_EFFORTS = ["none", "minimal", "low", "medium", "high", "xhigh", "ultra", "max"];
|
|
19953
|
+
var RESERVED_KEYS = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
|
|
19954
|
+
var SETTINGS_FIELDS = /* @__PURE__ */ new Set(["enabled", "temperature", "topP", "maxTokens", "contextWindow", "reasoningEffort"]);
|
|
19955
|
+
function flag(value) {
|
|
19956
|
+
if (typeof value !== "boolean") throw new Error("\u6A21\u578B\u8BBE\u7F6E\u7684 enabled \u5FC5\u987B\u662F\u5E03\u5C14\u503C");
|
|
19957
|
+
return value;
|
|
19958
|
+
}
|
|
19959
|
+
function bounded(value, max, label) {
|
|
19960
|
+
if (typeof value !== "number" || !Number.isFinite(value) || value < 0 || value > max) throw new Error(`\u6A21\u578B\u8BBE\u7F6E\u7684 ${label} \u5FC5\u987B\u662F 0 \u5230 ${max} \u4E4B\u95F4\u7684\u6709\u9650\u6570\u5B57`);
|
|
19961
|
+
return value;
|
|
19962
|
+
}
|
|
19963
|
+
function capacity(value, max, label) {
|
|
19964
|
+
if (typeof value !== "number" || !Number.isSafeInteger(value) || value < 1 || value > max) throw new Error(`\u6A21\u578B\u8BBE\u7F6E\u7684 ${label} \u5FC5\u987B\u662F 1 \u5230 ${max} \u4E4B\u95F4\u7684\u6574\u6570`);
|
|
19965
|
+
return value;
|
|
19966
|
+
}
|
|
19967
|
+
function effort(value) {
|
|
19968
|
+
const hit = REASONING_EFFORTS.find((candidate) => candidate === value);
|
|
19969
|
+
if (hit === void 0) throw new Error("\u6A21\u578B\u8BBE\u7F6E\u7684 reasoningEffort \u4E0D\u5728\u5141\u8BB8\u7684\u53D6\u503C\u5185");
|
|
19970
|
+
return hit;
|
|
19971
|
+
}
|
|
19972
|
+
function settingsOf(value) {
|
|
19973
|
+
if (!record2(value)) throw new Error("\u6BCF\u4E2A\u6A21\u578B\u7684\u8BBE\u7F6E\u5FC5\u987B\u662F\u5BF9\u8C61");
|
|
19974
|
+
for (const field of Object.keys(value)) {
|
|
19975
|
+
if (!SETTINGS_FIELDS.has(field)) throw new Error("\u6A21\u578B\u8BBE\u7F6E\u542B\u6709\u4E0D\u652F\u6301\u7684\u5B57\u6BB5");
|
|
19976
|
+
}
|
|
19977
|
+
const out = {};
|
|
19978
|
+
if (value.enabled !== void 0) out.enabled = flag(value.enabled);
|
|
19979
|
+
if (value.temperature !== void 0) out.temperature = bounded(value.temperature, MAX_TEMPERATURE, "temperature");
|
|
19980
|
+
if (value.topP !== void 0) out.topP = bounded(value.topP, MAX_TOP_P, "topP");
|
|
19981
|
+
if (value.maxTokens !== void 0) out.maxTokens = capacity(value.maxTokens, MAX_TOKENS, "maxTokens");
|
|
19982
|
+
if (value.contextWindow !== void 0) out.contextWindow = capacity(value.contextWindow, MAX_CONTEXT_WINDOW, "contextWindow");
|
|
19983
|
+
if (value.reasoningEffort !== void 0) out.reasoningEffort = effort(value.reasoningEffort);
|
|
19984
|
+
return out;
|
|
19985
|
+
}
|
|
19986
|
+
function parseModelSettingsMap(value) {
|
|
19987
|
+
if (!record2(value)) throw new Error("\u6A21\u578B\u8BBE\u7F6E\u5FC5\u987B\u662F\u5BF9\u8C61");
|
|
19988
|
+
const keys = Object.keys(value);
|
|
19989
|
+
if (keys.length > MAX_ENTRIES) throw new Error(`\u6A21\u578B\u8BBE\u7F6E\u6700\u591A\u5141\u8BB8 ${MAX_ENTRIES} \u4E2A\u6A21\u578B`);
|
|
19990
|
+
const out = {};
|
|
19991
|
+
for (const id of keys) {
|
|
19992
|
+
if (RESERVED_KEYS.has(id)) throw new Error("\u6A21\u578B\u8BBE\u7F6E\u4E0D\u5141\u8BB8\u4FDD\u7559\u5B57\u6BB5\u540D");
|
|
19993
|
+
if (!MODEL_ID.test(id)) throw new Error(`\u6A21\u578B ID \u5FC5\u987B\u662F 1\u2013${MAX_MODEL_ID_LENGTH} \u4F4D\u5B57\u6BCD\u3001\u6570\u5B57\u6216 . _ : / -`);
|
|
19994
|
+
out[id] = settingsOf(value[id]);
|
|
19995
|
+
}
|
|
19996
|
+
return out;
|
|
19997
|
+
}
|
|
19998
|
+
|
|
19914
19999
|
// src/remote.ts
|
|
19915
20000
|
var MAX_REVISION = 256;
|
|
19916
20001
|
var MAX_JOB_ID = 128;
|
|
@@ -19924,7 +20009,7 @@ var MAX_WINDOWS = 64;
|
|
|
19924
20009
|
var MAX_API_KEY = 16384;
|
|
19925
20010
|
var HTTP_ASCII = /^[\x21-\x7e]+$/u;
|
|
19926
20011
|
var ENV_REF = /^[A-Za-z_][A-Za-z0-9_]*$/u;
|
|
19927
|
-
var
|
|
20012
|
+
var MODEL_ID2 = /^[A-Za-z0-9._:/-]{1,128}$/u;
|
|
19928
20013
|
var LOGIN_PHASES = ["idle", "launching", "waiting", "verifying", "success", "cancelled", "error"];
|
|
19929
20014
|
var QUOTA_STATES = ["ok", "partial", "need-login", "error"];
|
|
19930
20015
|
var SESSION_SOURCES = ["desktop", "login", "environment"];
|
|
@@ -19938,7 +20023,7 @@ function isoTime(value, label) {
|
|
|
19938
20023
|
if (!Number.isFinite(Date.parse(time3))) throw new Error(`${label} \u5FC5\u987B\u662F ISO \u65F6\u95F4\u5B57\u7B26\u4E32`);
|
|
19939
20024
|
return time3;
|
|
19940
20025
|
}
|
|
19941
|
-
function
|
|
20026
|
+
function flag2(value, label) {
|
|
19942
20027
|
if (typeof value !== "boolean") throw new Error(`${label} \u5FC5\u987B\u662F\u5E03\u5C14\u503C`);
|
|
19943
20028
|
return value;
|
|
19944
20029
|
}
|
|
@@ -19950,6 +20035,15 @@ function amount(value, label, negative = false) {
|
|
|
19950
20035
|
if (typeof value !== "number" || !Number.isFinite(value) || !negative && value < 0) throw new Error(`${label} \u5FC5\u987B\u662F${negative ? "" : "\u975E\u8D1F"}\u6709\u9650\u6570\u5B57`);
|
|
19951
20036
|
return value;
|
|
19952
20037
|
}
|
|
20038
|
+
function positiveInteger(value, label, max) {
|
|
20039
|
+
const result = count(value, label);
|
|
20040
|
+
if (result === 0 || result > max) throw new Error(`${label} \u8D85\u51FA\u8303\u56F4`);
|
|
20041
|
+
return result;
|
|
20042
|
+
}
|
|
20043
|
+
function parseEfforts(value) {
|
|
20044
|
+
if (!Array.isArray(value) || value.length > 16) throw new Error("\u6A21\u578B\u601D\u8003\u6863\u4F4D\u683C\u5F0F\u65E0\u6548");
|
|
20045
|
+
return value.map((item) => text(item, "\u601D\u8003\u6863\u4F4D", 32));
|
|
20046
|
+
}
|
|
19953
20047
|
function member(value, allowed, label) {
|
|
19954
20048
|
const hit = allowed.find((candidate) => candidate === value);
|
|
19955
20049
|
if (hit === void 0) throw new Error(`${label} \u4E0D\u5728\u5141\u8BB8\u7684\u53D6\u503C\u5185`);
|
|
@@ -19967,7 +20061,9 @@ function parseQuotaWindow(value) {
|
|
|
19967
20061
|
limit,
|
|
19968
20062
|
...value.remaining === void 0 ? {} : { remaining: amount(value.remaining, "\u5269\u4F59\u989D\u5EA6") },
|
|
19969
20063
|
percent: Math.min(100, Math.max(0, amount(value.percent, "\u5DF2\u7528\u767E\u5206\u6BD4"))),
|
|
19970
|
-
...value.resetsAt === void 0 ? {} : { resetsAt: isoTime(value.resetsAt, "\u989D\u5EA6\u91CD\u7F6E\u65F6\u95F4") }
|
|
20064
|
+
...value.resetsAt === void 0 ? {} : { resetsAt: isoTime(value.resetsAt, "\u989D\u5EA6\u91CD\u7F6E\u65F6\u95F4") },
|
|
20065
|
+
...value.windowStart === void 0 ? {} : { windowStart: isoTime(value.windowStart, "\u989D\u5EA6\u7A97\u53E3\u5F00\u59CB\u65F6\u95F4") },
|
|
20066
|
+
...value.resetMode === void 0 ? {} : { resetMode: text(value.resetMode, "\u989D\u5EA6\u5237\u65B0\u65B9\u5F0F", 128) }
|
|
19971
20067
|
};
|
|
19972
20068
|
}
|
|
19973
20069
|
function parseQuotaSnapshot(value) {
|
|
@@ -19980,8 +20076,14 @@ function parseQuotaSnapshot(value) {
|
|
|
19980
20076
|
state: member(value.state, QUOTA_STATES, "\u989D\u5EA6\u72B6\u6001"),
|
|
19981
20077
|
...value.source === void 0 ? {} : { source: member(value.source, SESSION_SOURCES, "\u989D\u5EA6\u6765\u6E90") },
|
|
19982
20078
|
updatedAt: isoTime(value.updatedAt, "\u989D\u5EA6\u66F4\u65B0\u65F6\u95F4"),
|
|
20079
|
+
...value.subscriptionPeriodStart === void 0 ? {} : { subscriptionPeriodStart: isoTime(value.subscriptionPeriodStart, "\u8BA2\u9605\u5468\u671F\u5F00\u59CB\u65F6\u95F4") },
|
|
20080
|
+
...value.subscriptionPeriodEnd === void 0 ? {} : { subscriptionPeriodEnd: isoTime(value.subscriptionPeriodEnd, "\u8BA2\u9605\u5468\u671F\u7ED3\u675F\u65F6\u95F4") },
|
|
20081
|
+
...value.nextRefreshAt === void 0 ? {} : { nextRefreshAt: isoTime(value.nextRefreshAt, "\u4E0B\u6B21\u81EA\u52A8\u5237\u65B0\u65F6\u95F4") },
|
|
20082
|
+
...value.stale === void 0 ? {} : { stale: flag2(value.stale, "\u5386\u53F2\u989D\u5EA6\u8BFB\u6570") },
|
|
20083
|
+
...value.refreshFailures === void 0 ? {} : { refreshFailures: count(value.refreshFailures, "\u8FDE\u7EED\u5237\u65B0\u5931\u8D25\u6B21\u6570") },
|
|
20084
|
+
...value.autoRefreshPaused === void 0 ? {} : { autoRefreshPaused: flag2(value.autoRefreshPaused, "\u81EA\u52A8\u5237\u65B0\u6682\u505C\u72B6\u6001") },
|
|
19983
20085
|
...value.tier === void 0 ? {} : { tier: text(value.tier, "\u5957\u9910\u540D", MAX_TIER) },
|
|
19984
|
-
...value.eligible === void 0 ? {} : { eligible:
|
|
20086
|
+
...value.eligible === void 0 ? {} : { eligible: flag2(value.eligible, "\u5957\u9910\u8D44\u683C") },
|
|
19985
20087
|
windows: windows.map(parseQuotaWindow),
|
|
19986
20088
|
balances: {
|
|
19987
20089
|
...balances.subscriptionUsd === void 0 ? {} : { subscriptionUsd: amount(balances.subscriptionUsd, "\u8BA2\u9605\u4F59\u989D") },
|
|
@@ -20006,11 +20108,15 @@ function parseLoginState(value) {
|
|
|
20006
20108
|
function parseStatusModel(value) {
|
|
20007
20109
|
if (!record2(value)) throw new Error("\u6A21\u578B\u6761\u76EE\u5FC5\u987B\u662F\u5BF9\u8C61");
|
|
20008
20110
|
const id = text(value.id, "\u6A21\u578B id", 128);
|
|
20009
|
-
if (!
|
|
20111
|
+
if (!MODEL_ID2.test(id)) throw new Error("\u6A21\u578B id \u542B\u4E0D\u5141\u8BB8\u7684\u5B57\u7B26");
|
|
20010
20112
|
return {
|
|
20011
20113
|
id,
|
|
20012
20114
|
name: text(value.name, "\u6A21\u578B\u540D", 128),
|
|
20013
|
-
group: member(value.group, MODEL_GROUPS, "\u6A21\u578B\u5206\u7EC4")
|
|
20115
|
+
group: member(value.group, MODEL_GROUPS, "\u6A21\u578B\u5206\u7EC4"),
|
|
20116
|
+
...value.enabled === void 0 ? {} : { enabled: flag2(value.enabled, "\u6A21\u578B\u542F\u7528\u72B6\u6001") },
|
|
20117
|
+
...value.contextWindow === void 0 ? {} : { contextWindow: positiveInteger(value.contextWindow, "\u4E0A\u4E0B\u6587\u9884\u7B97", 1e8) },
|
|
20118
|
+
...value.maxOutputTokens === void 0 ? {} : { maxOutputTokens: positiveInteger(value.maxOutputTokens, "\u6700\u5927\u8F93\u51FA", 1e7) },
|
|
20119
|
+
...value.reasoningEfforts === void 0 ? {} : { reasoningEfforts: parseEfforts(value.reasoningEfforts) }
|
|
20014
20120
|
};
|
|
20015
20121
|
}
|
|
20016
20122
|
function parseStatusConfig(value) {
|
|
@@ -20018,10 +20124,15 @@ function parseStatusConfig(value) {
|
|
|
20018
20124
|
const apiKeyEnv = text(value.apiKeyEnv, "\u51ED\u636E\u5F15\u7528\u540D", MAX_ENV_REF);
|
|
20019
20125
|
if (!ENV_REF.test(apiKeyEnv)) throw new Error("\u51ED\u636E\u5F15\u7528\u540D\u5FC5\u987B\u662F\u5408\u6CD5\u6807\u8BC6\u7B26");
|
|
20020
20126
|
return {
|
|
20021
|
-
emptyTurnGuard:
|
|
20022
|
-
useDesktopCredential:
|
|
20127
|
+
emptyTurnGuard: flag2(value.emptyTurnGuard, "\u7A7A\u8F6E\u4FDD\u62A4\u5F00\u5173"),
|
|
20128
|
+
useDesktopCredential: flag2(value.useDesktopCredential, "\u684C\u9762\u767B\u5F55\u6001\u5F00\u5173"),
|
|
20023
20129
|
baseURL: text(value.baseURL, "\u63A8\u7406\u5730\u5740", MAX_BASE_URL),
|
|
20024
|
-
apiKeyEnv
|
|
20130
|
+
apiKeyEnv,
|
|
20131
|
+
...value.apiProtocol === void 0 ? {} : { apiProtocol: member(value.apiProtocol, API_PROTOCOL_IDS, "\u63A8\u7406\u534F\u8BAE") },
|
|
20132
|
+
...value.modelSettings === void 0 ? {} : { modelSettings: parseModelSettingsMap(value.modelSettings) },
|
|
20133
|
+
...value.requestTimeoutMs === void 0 ? {} : { requestTimeoutMs: positiveInteger(value.requestTimeoutMs, "\u8BF7\u6C42\u8D85\u65F6", 36e5) },
|
|
20134
|
+
...value.streamIdleTimeoutMs === void 0 ? {} : { streamIdleTimeoutMs: positiveInteger(value.streamIdleTimeoutMs, "\u6D41\u7A7A\u95F2\u8D85\u65F6", 18e5) },
|
|
20135
|
+
...value.quotaRefreshSeconds === void 0 ? {} : { quotaRefreshSeconds: positiveInteger(value.quotaRefreshSeconds, "\u81EA\u52A8\u5237\u65B0\u95F4\u9694", 3600) }
|
|
20025
20136
|
};
|
|
20026
20137
|
}
|
|
20027
20138
|
function parseStatus(value) {
|
|
@@ -20036,13 +20147,16 @@ function parseStatus(value) {
|
|
|
20036
20147
|
}
|
|
20037
20148
|
return {
|
|
20038
20149
|
revision: text(value.revision, "\u914D\u7F6E\u7248\u672C", MAX_REVISION),
|
|
20039
|
-
apiKeyConfigured:
|
|
20150
|
+
apiKeyConfigured: flag2(value.apiKeyConfigured, "\u51ED\u636E\u662F\u5426\u5C31\u7EEA"),
|
|
20040
20151
|
...value.sessionSource === void 0 ? {} : { sessionSource: member(value.sessionSource, SESSION_SOURCES, "\u767B\u5F55\u6001\u6765\u6E90") },
|
|
20041
20152
|
quota: parseQuotaSnapshot(value.quota),
|
|
20042
20153
|
login: parseLoginState(value.login),
|
|
20043
20154
|
config: parseStatusConfig(value.config),
|
|
20044
20155
|
guardedTurns: count(value.guardedTurns, "\u5DF2\u62E6\u622A\u7A7A\u8F6E\u6570"),
|
|
20045
|
-
models: parsed
|
|
20156
|
+
models: parsed,
|
|
20157
|
+
...value.modelsSource === void 0 ? {} : { modelsSource: member(value.modelsSource, ["builtin", "openai"], "\u6A21\u578B\u76EE\u5F55\u6765\u6E90") },
|
|
20158
|
+
...value.modelsUpdatedAt === void 0 ? {} : { modelsUpdatedAt: isoTime(value.modelsUpdatedAt, "\u6A21\u578B\u66F4\u65B0\u65F6\u95F4") },
|
|
20159
|
+
...value.modelsError === void 0 ? {} : { modelsError: text(value.modelsError, "\u6A21\u578B\u66F4\u65B0\u63D0\u793A", MAX_MESSAGE) }
|
|
20046
20160
|
};
|
|
20047
20161
|
}
|
|
20048
20162
|
function parseStartLoginRequest(value) {
|
|
@@ -20071,7 +20185,9 @@ var CancelLoginRequestCodec = { mode: "strict", typeSymbol: "dsh-opendesign-coro
|
|
|
20071
20185
|
var SaveApiKeyRequestCodec = { mode: "strict", typeSymbol: "dsh-opendesign-corouter#SaveApiKeyRequest", create: () => external_exports.unknown().transform((value) => parseSaveApiKeyRequest(value)) };
|
|
20072
20186
|
var TYPERT_REMOTE = createTypertRemoteInfo({ package: "dsh-opendesign-corouter", methods: {
|
|
20073
20187
|
"openDesignCoRouter/status": { service: "openDesignCoRouter", invocation: { kind: "direct" }, parameters: [], result: StatusCodec },
|
|
20188
|
+
"openDesignCoRouter/refreshModels": { service: "openDesignCoRouter", invocation: { kind: "direct" }, parameters: [], result: StatusCodec },
|
|
20074
20189
|
"openDesignCoRouter/refreshQuota": { service: "openDesignCoRouter", invocation: { kind: "direct" }, parameters: [], result: QuotaSnapshotCodec },
|
|
20190
|
+
"openDesignCoRouter/refreshQuotaNow": { service: "openDesignCoRouter", invocation: { kind: "direct" }, parameters: [], result: QuotaSnapshotCodec },
|
|
20075
20191
|
"openDesignCoRouter/startLogin": { service: "openDesignCoRouter", invocation: { kind: "direct" }, parameters: [{ name: "input", source: "json", codec: StartLoginRequestCodec, strictCodec: StartLoginRequestCodec }], result: LoginStateCodec },
|
|
20076
20192
|
"openDesignCoRouter/loginStatus": { service: "openDesignCoRouter", invocation: { kind: "direct" }, parameters: [], result: LoginStateCodec },
|
|
20077
20193
|
"openDesignCoRouter/cancelLogin": { service: "openDesignCoRouter", invocation: { kind: "direct" }, parameters: [{ name: "input", source: "json", codec: CancelLoginRequestCodec, strictCodec: CancelLoginRequestCodec }], result: LoginStateCodec },
|
|
@@ -20089,6 +20205,17 @@ var TABS = [
|
|
|
20089
20205
|
{ id: "connection", label: "\u8FDE\u63A5\u4E0E\u767B\u5F55" },
|
|
20090
20206
|
{ id: "advanced", label: "\u9AD8\u7EA7" }
|
|
20091
20207
|
];
|
|
20208
|
+
var DEFAULT_QUOTA_REFRESH_SECONDS = 60;
|
|
20209
|
+
var MIN_QUOTA_REFRESH_SECONDS = 5;
|
|
20210
|
+
var MAX_QUOTA_REFRESH_SECONDS = 3600;
|
|
20211
|
+
var DEFAULT_REQUEST_TIMEOUT_MS = 18e5;
|
|
20212
|
+
var MIN_REQUEST_TIMEOUT_MS = 1e3;
|
|
20213
|
+
var MAX_REQUEST_TIMEOUT_MS = 36e5;
|
|
20214
|
+
var DEFAULT_STREAM_IDLE_TIMEOUT_MS = 3e5;
|
|
20215
|
+
var MIN_STREAM_IDLE_TIMEOUT_MS = 1e3;
|
|
20216
|
+
var MAX_STREAM_IDLE_TIMEOUT_MS = 18e5;
|
|
20217
|
+
var MAX_OUTPUT_TOKENS = 1e7;
|
|
20218
|
+
var MAX_CONTEXT_WINDOW2 = 1e8;
|
|
20092
20219
|
var GENERIC_ERROR = "\u64CD\u4F5C\u672A\u5B8C\u6210\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002";
|
|
20093
20220
|
var LOGIN_LABELS = {
|
|
20094
20221
|
idle: "\u5C1A\u672A\u5F00\u59CB\u72EC\u7ACB\u767B\u5F55",
|
|
@@ -20114,13 +20241,17 @@ function installStyles() {
|
|
|
20114
20241
|
.odc-intro{margin:6px 0 18px!important;color:var(--dsw-alias-label-secondary,inherit);font-size:12px}.odc-tabs{display:flex;gap:4px;overflow-x:auto;margin:0 0 16px;padding:0 0 8px;border-bottom:1px solid var(--dsw-alias-border-l4,transparent)}
|
|
20115
20242
|
.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)}
|
|
20116
20243
|
.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}
|
|
20117
|
-
.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-
|
|
20118
|
-
.odc-
|
|
20244
|
+
.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}
|
|
20245
|
+
.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}.odc-window{display:grid;gap:7px;margin-top:10px}.odc-window progress{width:100%;height:7px;accent-color:var(--dsw-alias-brand-primary,Highlight)}
|
|
20246
|
+
.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}
|
|
20119
20247
|
.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))}
|
|
20120
|
-
.odc-model-groups{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap: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-item strong,.odc-model-item code{display:block;overflow-wrap:anywhere}.odc-model-item code{margin-top:2px;color:var(--dsw-alias-label-secondary,inherit);font-size:11px}.odc-model-count{color:var(--dsw-alias-label-secondary,inherit);font-size:11px;font-weight:400}
|
|
20121
|
-
.odc-
|
|
20122
|
-
.odc-
|
|
20123
|
-
.odc-
|
|
20248
|
+
.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}
|
|
20249
|
+
.odc-model-details{margin-top:8px}.odc-model-details>summary{cursor:pointer;color:var(--dsw-alias-label-secondary,inherit);font-size:11px;line-height:1.7}.odc-model-editor{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:2px 10px;margin-top:8px}
|
|
20250
|
+
.odc-field{display:grid;gap:6px;margin-top:14px}.odc-field-compact{margin-top:8px}.odc-field label,.odc-switch-text{font-size:12px;font-weight:550}.odc-input{width:100%;min-width:0;min-height:34px;padding:7px 9px;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}.odc-field-compact .odc-input{min-height:30px;padding:5px 8px;font-size:11px}.odc-input::placeholder{color:var(--dsw-alias-label-secondary,inherit);opacity:1}.odc-input:disabled{opacity:.55}
|
|
20251
|
+
.odc-switch{display:flex;align-items:flex-start;gap:10px;cursor:pointer}.odc-switch input{width:16px;height:16px;flex:none;margin:2px 0 0;accent-color:var(--dsw-alias-brand-primary,Highlight)}.odc-switch>span{display:grid;gap:4px;min-width:0}.odc-switch:has(input:disabled){cursor:not-allowed;opacity:.6}.odc-divider{height:1px;border:0;background:var(--dsw-alias-border-l4,transparent);margin:2px 0}.odc-link{color:var(--dsw-alias-brand-primary,inherit);text-underline-offset:3px}
|
|
20252
|
+
.odc-readonly{display:grid;gap:10px;margin-top:14px;padding:10px 12px;border-radius:8px;background:var(--dsw-alias-bg-layer-2,transparent)}.odc-code{display:block;min-width:0;color:var(--dsw-alias-label-primary,inherit);font-family:ui-monospace,'Cascadia Mono',Consolas,monospace;font-size:11px;line-height:1.6;overflow-wrap:anywhere}
|
|
20253
|
+
.odc-field-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))}
|
|
20254
|
+
.odc-settings :focus-visible{outline:2px solid var(--dsw-alias-brand-primary,Highlight);outline-offset:3px}@media(max-width:680px){.odc-quota-grid{grid-template-columns:repeat(2,minmax(0,1fr))}.odc-model-groups{grid-template-columns:1fr}.odc-model-editor{grid-template-columns:1fr}}@media(max-width:380px){.odc-quota-grid{grid-template-columns:1fr}.odc-card{padding:12px}}
|
|
20124
20255
|
`;
|
|
20125
20256
|
document.head.append(style);
|
|
20126
20257
|
return () => style.remove();
|
|
@@ -20218,19 +20349,65 @@ function formatTime(value) {
|
|
|
20218
20349
|
const date5 = new Date(value);
|
|
20219
20350
|
return Number.isFinite(date5.getTime()) ? date5.toLocaleString("zh-CN", { hour12: false }) : "\u2014";
|
|
20220
20351
|
}
|
|
20352
|
+
function formatTokens(value) {
|
|
20353
|
+
if (value === void 0 || !Number.isFinite(value)) return "\u2014";
|
|
20354
|
+
return new Intl.NumberFormat("zh-CN").format(value);
|
|
20355
|
+
}
|
|
20221
20356
|
function windowLabel(seconds) {
|
|
20222
20357
|
if (seconds % 86400 === 0) return `${seconds / 86400} \u5929\u8D60\u9001\u7A97\u53E3`;
|
|
20223
20358
|
if (seconds % 3600 === 0) return `${seconds / 3600} \u5C0F\u65F6\u8D60\u9001\u7A97\u53E3`;
|
|
20224
20359
|
if (seconds % 60 === 0) return `${seconds / 60} \u5206\u949F\u8D60\u9001\u7A97\u53E3`;
|
|
20225
20360
|
return `${seconds} \u79D2\u8D60\u9001\u7A97\u53E3`;
|
|
20226
20361
|
}
|
|
20227
|
-
function
|
|
20362
|
+
function nextWindowResetAt(windows, now) {
|
|
20363
|
+
let earliest;
|
|
20364
|
+
let earliestMs = Number.POSITIVE_INFINITY;
|
|
20365
|
+
for (const window of windows) {
|
|
20366
|
+
if (window.resetsAt === void 0) continue;
|
|
20367
|
+
const ms = Date.parse(window.resetsAt);
|
|
20368
|
+
if (!Number.isFinite(ms) || ms <= now || ms >= earliestMs) continue;
|
|
20369
|
+
earliest = window.resetsAt;
|
|
20370
|
+
earliestMs = ms;
|
|
20371
|
+
}
|
|
20372
|
+
return earliest;
|
|
20373
|
+
}
|
|
20374
|
+
var SOURCE_LABELS = {
|
|
20375
|
+
desktop: "\u684C\u9762\u767B\u5F55\u6001",
|
|
20376
|
+
login: "\u72EC\u7ACB\u767B\u5F55",
|
|
20377
|
+
environment: "\u73AF\u5883\u51ED\u636E"
|
|
20378
|
+
};
|
|
20379
|
+
var RESET_MODE_LABELS = {
|
|
20380
|
+
activity_triggered: "\u6309\u4F7F\u7528\u89E6\u53D1",
|
|
20381
|
+
anchored_recurring: "\u56FA\u5B9A\u5468\u671F"
|
|
20382
|
+
};
|
|
20383
|
+
function QuotaView({ quota, nextAutoRefreshAt, refreshIntervalSeconds }) {
|
|
20228
20384
|
if (quota === void 0) return h("p", { className: "odc-hint", role: "status" }, "\u6B63\u5728\u8BFB\u53D6\u989D\u5EA6\u2026");
|
|
20229
20385
|
const metrics = [
|
|
20230
20386
|
{ label: "\u5957\u9910\u4F59\u989D", value: formatUsd(quota.balances.subscriptionUsd), hint: "\u8BA2\u9605\u5269\u4F59\u53EF\u7528\u91D1\u989D" },
|
|
20231
20387
|
{ label: "\u5145\u503C / \u8D60\u9001\u91D1\u989D", value: formatUsd(quota.balances.rechargeUsd), hint: "\u5145\u503C\u4E0E\u8D60\u9001\u7684\u53EF\u7528\u91D1\u989D" },
|
|
20232
20388
|
{ label: "\u603B\u989D\u5EA6", value: formatUsd(quota.balances.totalUsd), hint: "\u94B1\u5305\u5F53\u524D\u53EF\u7528\u603B\u989D" }
|
|
20233
20389
|
];
|
|
20390
|
+
const timing = [
|
|
20391
|
+
{
|
|
20392
|
+
label: "\u8BA2\u9605\u8D26\u671F\u7ED3\u675F",
|
|
20393
|
+
value: formatTime(quota.subscriptionPeriodEnd),
|
|
20394
|
+
hint: `\u8D26\u671F\u5F00\u59CB\uFF1A${formatTime(quota.subscriptionPeriodStart)} \xB7 \u672A\u77E5\u65F6\u95F4\u4E0D\u63A8\u65AD`
|
|
20395
|
+
},
|
|
20396
|
+
{
|
|
20397
|
+
label: "\u4E0B\u6B21\u989D\u5EA6\u6062\u590D",
|
|
20398
|
+
value: formatTime(nextWindowResetAt(quota.windows, Date.now())),
|
|
20399
|
+
hint: "\u53EA\u53D6\u7A97\u53E3 resetsAt \u4E2D\u6700\u65E9\u7684\u672A\u5230\u671F\u65F6\u95F4\uFF1B\u65E0\u7A97\u53E3\u6216\u672A\u77E5\u65F6\u4FDD\u6301 \u2014"
|
|
20400
|
+
},
|
|
20401
|
+
{
|
|
20402
|
+
label: "\u4E0B\u6B21\u81EA\u52A8\u5237\u65B0",
|
|
20403
|
+
value: formatTime(quota.state === "need-login" || quota.autoRefreshPaused ? void 0 : nextAutoRefreshAt),
|
|
20404
|
+
hint: quota.state === "need-login" ? "\u767B\u5F55\u540E\u81EA\u52A8\u5237\u65B0" : quota.autoRefreshPaused ? "\u8FDE\u7EED\u5931\u8D25\uFF0C\u81EA\u52A8\u91CD\u8BD5\u5DF2\u6682\u505C\uFF1B\u70B9\u51FB\u5237\u65B0\u989D\u5EA6\u91CD\u8BD5" : refreshIntervalSeconds === void 0 ? "\u672A\u542F\u7528\u81EA\u52A8\u5237\u65B0" : quota.refreshFailures ? `\u5237\u65B0\u5931\u8D25 ${quota.refreshFailures} \u6B21\uFF0C\u6B63\u5728\u5EF6\u8FDF\u91CD\u8BD5` : `\u6BCF ${refreshIntervalSeconds} \u79D2\u81EA\u52A8\u5237\u65B0`
|
|
20405
|
+
}
|
|
20406
|
+
];
|
|
20407
|
+
const tierLine = [
|
|
20408
|
+
quota.tier === void 0 ? void 0 : `\u5F53\u524D\u5957\u9910\uFF1A${quota.tier}`,
|
|
20409
|
+
quota.eligible === void 0 ? void 0 : `\u5957\u9910\u8D44\u683C\uFF1A${quota.eligible ? "\u5DF2\u5F00\u901A" : "\u672A\u5F00\u901A"}`
|
|
20410
|
+
].filter((value) => value !== void 0).join(" \xB7 ");
|
|
20234
20411
|
return h(
|
|
20235
20412
|
React.Fragment,
|
|
20236
20413
|
null,
|
|
@@ -20240,10 +20417,25 @@ function QuotaView({ quota }) {
|
|
|
20240
20417
|
h(
|
|
20241
20418
|
"div",
|
|
20242
20419
|
{ className: "odc-card-head" },
|
|
20243
|
-
h(
|
|
20244
|
-
|
|
20420
|
+
h(
|
|
20421
|
+
"div",
|
|
20422
|
+
null,
|
|
20423
|
+
h("h3", null, "\u5957\u9910\u8D60\u9001\u7A97\u53E3"),
|
|
20424
|
+
tierLine === "" ? null : h("p", { className: "odc-hint" }, tierLine)
|
|
20425
|
+
),
|
|
20426
|
+
h(
|
|
20427
|
+
"div",
|
|
20428
|
+
{ className: "odc-actions" },
|
|
20429
|
+
h("span", { className: "odc-label" }, QUOTA_LABELS[quota.state]),
|
|
20430
|
+
quota.stale ? h("span", { className: "odc-chip" }, "\u4E0A\u6B21\u6210\u529F\u8BFB\u6570") : null
|
|
20431
|
+
)
|
|
20245
20432
|
),
|
|
20246
|
-
quota.windows.length === 0 ? h("p", { className: "odc-
|
|
20433
|
+
quota.windows.length === 0 ? quota.eligible === false ? h("p", { className: "odc-hint", role: "status" }, "\u5F53\u524D\u8D26\u53F7\u672A\u5F00\u901A Design Plan\uFF0C\u6CA1\u6709\u8D60\u9001\u989D\u5EA6\u7A97\u53E3\u3002") : h(
|
|
20434
|
+
React.Fragment,
|
|
20435
|
+
null,
|
|
20436
|
+
h("p", { className: "odc-metric-value" }, "\u2014"),
|
|
20437
|
+
h("p", { className: "odc-hint" }, "\u989D\u5EA6\u7A97\u53E3\u6682\u4E0D\u53EF\u786E\u8BA4\uFF1B\u4E0D\u6309 0 \u586B\u5145\u3002")
|
|
20438
|
+
) : quota.windows.map((window, index) => h(
|
|
20247
20439
|
"div",
|
|
20248
20440
|
{ className: "odc-window", key: `${window.durationSeconds}-${index}` },
|
|
20249
20441
|
h(
|
|
@@ -20253,7 +20445,7 @@ function QuotaView({ quota }) {
|
|
|
20253
20445
|
h("span", { className: "odc-label" }, `\u5DF2\u7528 ${window.percent.toFixed(1)}% \xB7 \u5269\u4F59 ${window.remaining ?? "\u2014"}`)
|
|
20254
20446
|
),
|
|
20255
20447
|
h("progress", { max: 100, value: window.percent, "aria-label": `${windowLabel(window.durationSeconds)}\u5DF2\u7528\u989D\u5EA6` }),
|
|
20256
|
-
h("span", { className: "odc-meta" }, `\u5DF2\u7528 ${window.used} / \u4E0A\u9650 ${window.limit} \xB7 \
|
|
20448
|
+
h("span", { className: "odc-meta" }, `\u5DF2\u7528 ${window.used} / \u4E0A\u9650 ${window.limit} \xB7 \u6062\u590D ${formatTime(window.resetsAt)}${window.windowStart === void 0 ? "" : ` \xB7 \u7A97\u53E3\u5F00\u59CB ${formatTime(window.windowStart)}`}${window.resetMode === void 0 ? "" : ` \xB7 \u91CD\u7F6E\u65B9\u5F0F ${RESET_MODE_LABELS[window.resetMode] ?? window.resetMode}`}`)
|
|
20257
20449
|
))
|
|
20258
20450
|
),
|
|
20259
20451
|
h("div", { className: "odc-quota-grid" }, metrics.map((metric) => h(
|
|
@@ -20263,11 +20455,77 @@ function QuotaView({ quota }) {
|
|
|
20263
20455
|
h("strong", { className: "odc-metric-value" }, metric.value),
|
|
20264
20456
|
h("span", { className: "odc-hint" }, metric.hint)
|
|
20265
20457
|
))),
|
|
20266
|
-
h("
|
|
20458
|
+
h("div", { className: "odc-quota-grid" }, timing.map((metric) => h(
|
|
20459
|
+
"div",
|
|
20460
|
+
{ className: "odc-card odc-metric", key: metric.label },
|
|
20461
|
+
h("span", { className: "odc-label" }, metric.label),
|
|
20462
|
+
h("strong", { className: "odc-metric-value odc-metric-text" }, metric.value),
|
|
20463
|
+
h("span", { className: "odc-hint" }, metric.hint)
|
|
20464
|
+
))),
|
|
20465
|
+
h("p", { className: "odc-meta" }, `\u66F4\u65B0\u4E8E ${formatTime(quota.updatedAt)}${quota.source !== void 0 ? ` \xB7 \u6765\u6E90\uFF1A${SOURCE_LABELS[quota.source]}\uFF08\u53EA\u8BFB\u5C55\u793A\uFF09` : ""}`),
|
|
20466
|
+
h("p", { className: "odc-hint" }, "\u989D\u5EA6\u6570\u636E\u53EA\u8BFB\u5C55\u793A\uFF0C\u4E0D\u5199\u5165\u8D26\u53F7\u6216\u684C\u9762\u51ED\u636E\uFF1B\u684C\u9762\u767B\u5F55\u6001\u4E0D\u53EF\u7528\u65F6\u4F1A\u81EA\u52A8\u56DE\u9000\u5230\u5DF2\u4FDD\u5B58\u4F1A\u8BDD\u3002"),
|
|
20267
20467
|
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
|
|
20268
20468
|
);
|
|
20269
20469
|
}
|
|
20270
|
-
function
|
|
20470
|
+
function writeModelSettings(map2, id, next) {
|
|
20471
|
+
const out = { ...map2 ?? {} };
|
|
20472
|
+
if (next === void 0) {
|
|
20473
|
+
delete out[id];
|
|
20474
|
+
return out;
|
|
20475
|
+
}
|
|
20476
|
+
const entry = {};
|
|
20477
|
+
if (next.enabled !== void 0) entry.enabled = next.enabled;
|
|
20478
|
+
if (next.temperature !== void 0) entry.temperature = next.temperature;
|
|
20479
|
+
if (next.topP !== void 0) entry.topP = next.topP;
|
|
20480
|
+
if (next.maxTokens !== void 0) entry.maxTokens = next.maxTokens;
|
|
20481
|
+
if (next.contextWindow !== void 0) entry.contextWindow = next.contextWindow;
|
|
20482
|
+
if (next.reasoningEffort !== void 0) entry.reasoningEffort = next.reasoningEffort;
|
|
20483
|
+
if (Object.keys(entry).length === 0) delete out[id];
|
|
20484
|
+
else out[id] = entry;
|
|
20485
|
+
return out;
|
|
20486
|
+
}
|
|
20487
|
+
function modelSettingsEntry(map2, id) {
|
|
20488
|
+
return { ...map2?.[id] ?? {} };
|
|
20489
|
+
}
|
|
20490
|
+
function modelEnabled(model, settings, authoritative = true) {
|
|
20491
|
+
if (settings?.enabled !== void 0) return settings.enabled;
|
|
20492
|
+
if (authoritative) return true;
|
|
20493
|
+
return model.enabled !== false;
|
|
20494
|
+
}
|
|
20495
|
+
var DECIMAL_TEXT = /^[+-]?(?:\d+(?:\.\d*)?|\.\d+)$/u;
|
|
20496
|
+
function parseNumberInput(raw, spec) {
|
|
20497
|
+
const text2 = raw.trim();
|
|
20498
|
+
if (text2 === "") {
|
|
20499
|
+
return spec.allowEmpty === true ? { ok: true, value: void 0 } : { ok: false, message: `${spec.label}\u4E0D\u80FD\u4E3A\u7A7A\u3002` };
|
|
20500
|
+
}
|
|
20501
|
+
const integral = spec.integer === true;
|
|
20502
|
+
const value = DECIMAL_TEXT.test(text2) ? Number(text2) : Number.NaN;
|
|
20503
|
+
if (!DECIMAL_TEXT.test(text2) || !Number.isFinite(value) || value < spec.min || value > spec.max || integral && !Number.isSafeInteger(value)) {
|
|
20504
|
+
return {
|
|
20505
|
+
ok: false,
|
|
20506
|
+
message: `${spec.label}\u9700\u4E3A ${spec.min} \u5230 ${spec.max} \u4E4B\u95F4\u7684${integral ? "\u6574\u6570" : "\u6570\u5B57"}${spec.allowEmpty === true ? "\uFF0C\u6216\u7559\u7A7A\u7EE7\u627F\u9ED8\u8BA4\u3002" : "\u3002"}`
|
|
20507
|
+
};
|
|
20508
|
+
}
|
|
20509
|
+
return { ok: true, value };
|
|
20510
|
+
}
|
|
20511
|
+
function protocolEndpoint(baseURL, protocol) {
|
|
20512
|
+
return inferenceEndpoint(baseURL, protocol);
|
|
20513
|
+
}
|
|
20514
|
+
function normaliseQuotaRefreshSeconds(value) {
|
|
20515
|
+
if (value === void 0 || !Number.isSafeInteger(value) || value < MIN_QUOTA_REFRESH_SECONDS || value > MAX_QUOTA_REFRESH_SECONDS) return void 0;
|
|
20516
|
+
return value;
|
|
20517
|
+
}
|
|
20518
|
+
function quotaAutoRefresh(secondsRaw, nextRefreshAt, now, backingOff = false) {
|
|
20519
|
+
const intervalSeconds = normaliseQuotaRefreshSeconds(secondsRaw);
|
|
20520
|
+
if (intervalSeconds === void 0) return void 0;
|
|
20521
|
+
const intervalMs = intervalSeconds * 1e3;
|
|
20522
|
+
const planMs = nextRefreshAt === void 0 ? Number.NaN : Date.parse(nextRefreshAt);
|
|
20523
|
+
const planDelay = Number.isFinite(planMs) ? planMs - now : Number.POSITIVE_INFINITY;
|
|
20524
|
+
const plannedDelay = Math.max(1e3, Math.floor(planDelay) + 500);
|
|
20525
|
+
const delayMs = Number.isFinite(planDelay) && planDelay > 0 ? backingOff ? plannedDelay : Math.min(intervalMs, plannedDelay) : intervalMs;
|
|
20526
|
+
return { delayMs, at: new Date(now + delayMs).toISOString(), intervalSeconds };
|
|
20527
|
+
}
|
|
20528
|
+
function Overview({ status, busy, onRefresh, nextAutoRefreshAt, refreshIntervalSeconds }) {
|
|
20271
20529
|
return h(
|
|
20272
20530
|
React.Fragment,
|
|
20273
20531
|
null,
|
|
@@ -20277,14 +20535,211 @@ function Overview({ status, busy, onRefresh }) {
|
|
|
20277
20535
|
h("div", null, h("h3", null, "\u989D\u5EA6\u6982\u89C8"), h("p", { className: "odc-hint" }, "\u5957\u9910\u7A97\u53E3\u4E0E\u94B1\u5305\u4F59\u989D\u5206\u5F00\u8BA1\u91CF\uFF1B\u672A\u77E5\u6570\u636E\u4E0D\u505A\u63A8\u7B97\u3002")),
|
|
20278
20536
|
h("button", { className: "odc-button", type: "button", disabled: busy, onClick: onRefresh }, busy ? "\u5237\u65B0\u4E2D\u2026" : "\u5237\u65B0\u989D\u5EA6")
|
|
20279
20537
|
),
|
|
20280
|
-
h(QuotaView, { quota: status?.quota })
|
|
20538
|
+
h(QuotaView, { quota: status?.quota, nextAutoRefreshAt, refreshIntervalSeconds })
|
|
20539
|
+
);
|
|
20540
|
+
}
|
|
20541
|
+
var NUMERIC_FIELDS = {
|
|
20542
|
+
temperature: { label: "\u6E29\u5EA6", hint: "0\u20132\uFF1B\u7559\u7A7A\u7EE7\u627F\u9ED8\u8BA4\u3002", min: 0, max: 2 },
|
|
20543
|
+
topP: { label: "Top P", hint: "0\u20131\uFF1B\u7559\u7A7A\u7EE7\u627F\u9ED8\u8BA4\u3002", min: 0, max: 1 },
|
|
20544
|
+
maxTokens: { label: "\u6700\u5927\u8F93\u51FA\uFF08tokens\uFF09", hint: "\u6B63\u6574\u6570\uFF1B\u7559\u7A7A\u7EE7\u627F\u76EE\u5F55\u9ED8\u8BA4\u3002", min: 1, max: MAX_OUTPUT_TOKENS, integer: true },
|
|
20545
|
+
contextWindow: { label: "\u4E0A\u4E0B\u6587\u9884\u7B97\uFF08tokens\uFF09", hint: "\u6B63\u6574\u6570\uFF1B\u7559\u7A7A\u7EE7\u627F\u76EE\u5F55\u9ED8\u8BA4\u3002", min: 1, max: MAX_CONTEXT_WINDOW2, integer: true }
|
|
20546
|
+
};
|
|
20547
|
+
var NUMERIC_ORDER = ["temperature", "topP", "maxTokens", "contextWindow"];
|
|
20548
|
+
function OptionalNumberField({ id, field, value, disabled, resetToken, onSave }) {
|
|
20549
|
+
const spec = NUMERIC_FIELDS[field];
|
|
20550
|
+
const mounted = useMounted();
|
|
20551
|
+
const [draft, setDraft] = React.useState(void 0);
|
|
20552
|
+
const [error62, setError] = React.useState(void 0);
|
|
20553
|
+
React.useEffect(() => {
|
|
20554
|
+
setDraft(void 0);
|
|
20555
|
+
setError(void 0);
|
|
20556
|
+
}, [value, resetToken]);
|
|
20557
|
+
const commit = async () => {
|
|
20558
|
+
if (disabled || draft === void 0) return;
|
|
20559
|
+
const result = parseNumberInput(draft, {
|
|
20560
|
+
label: spec.label,
|
|
20561
|
+
min: spec.min,
|
|
20562
|
+
max: spec.max,
|
|
20563
|
+
...spec.integer === true ? { integer: true } : {},
|
|
20564
|
+
allowEmpty: true
|
|
20565
|
+
});
|
|
20566
|
+
if (!result.ok) {
|
|
20567
|
+
setError(result.message);
|
|
20568
|
+
return;
|
|
20569
|
+
}
|
|
20570
|
+
if (result.value === value) {
|
|
20571
|
+
setDraft(void 0);
|
|
20572
|
+
setError(void 0);
|
|
20573
|
+
return;
|
|
20574
|
+
}
|
|
20575
|
+
const saved = await onSave(result.value);
|
|
20576
|
+
if (!mounted.current) return;
|
|
20577
|
+
if (saved) {
|
|
20578
|
+
setDraft(void 0);
|
|
20579
|
+
setError(void 0);
|
|
20580
|
+
} else setError("\u8BBE\u7F6E\u672A\u4FDD\u5B58\uFF0C\u8BF7\u91CD\u8BD5\u3002");
|
|
20581
|
+
};
|
|
20582
|
+
return h(
|
|
20583
|
+
"div",
|
|
20584
|
+
{ className: "odc-field odc-field-compact" },
|
|
20585
|
+
h("label", { htmlFor: id }, spec.label),
|
|
20586
|
+
h("input", {
|
|
20587
|
+
id,
|
|
20588
|
+
className: "odc-input",
|
|
20589
|
+
type: "number",
|
|
20590
|
+
inputMode: "decimal",
|
|
20591
|
+
min: spec.min,
|
|
20592
|
+
max: spec.max,
|
|
20593
|
+
step: spec.integer === true ? 1 : 0.1,
|
|
20594
|
+
value: draft ?? (value === void 0 ? "" : String(value)),
|
|
20595
|
+
disabled,
|
|
20596
|
+
"aria-invalid": error62 !== void 0,
|
|
20597
|
+
"aria-describedby": `${id}-hint`,
|
|
20598
|
+
onChange: (event) => setDraft(event.target.value),
|
|
20599
|
+
onBlur: () => {
|
|
20600
|
+
void commit();
|
|
20601
|
+
}
|
|
20602
|
+
}),
|
|
20603
|
+
h("small", {
|
|
20604
|
+
className: error62 === void 0 ? "odc-hint" : "odc-hint odc-field-error",
|
|
20605
|
+
id: `${id}-hint`,
|
|
20606
|
+
...error62 === void 0 ? {} : { role: "alert" }
|
|
20607
|
+
}, error62 ?? spec.hint)
|
|
20608
|
+
);
|
|
20609
|
+
}
|
|
20610
|
+
function EffortField({ id, model, value, disabled, onChange }) {
|
|
20611
|
+
const mounted = useMounted();
|
|
20612
|
+
const [error62, setError] = React.useState(void 0);
|
|
20613
|
+
const listed = model.reasoningEfforts ?? [];
|
|
20614
|
+
const options = value === void 0 || listed.includes(value) ? listed : [...listed, value];
|
|
20615
|
+
const unknown2 = options.length === 0;
|
|
20616
|
+
return h(
|
|
20617
|
+
"div",
|
|
20618
|
+
{ className: "odc-field odc-field-compact" },
|
|
20619
|
+
h("label", { htmlFor: id }, "\u9ED8\u8BA4\u601D\u8003\u6DF1\u5EA6"),
|
|
20620
|
+
h("select", {
|
|
20621
|
+
id,
|
|
20622
|
+
className: "odc-input",
|
|
20623
|
+
value: value ?? "",
|
|
20624
|
+
disabled: disabled || unknown2,
|
|
20625
|
+
"aria-describedby": `${id}-hint`,
|
|
20626
|
+
onChange: (event) => {
|
|
20627
|
+
const next = event.target.value;
|
|
20628
|
+
void (async () => {
|
|
20629
|
+
const saved = await onChange(next);
|
|
20630
|
+
if (mounted.current && !saved) setError("\u8BBE\u7F6E\u672A\u4FDD\u5B58\uFF0C\u8BF7\u91CD\u8BD5\u3002");
|
|
20631
|
+
})();
|
|
20632
|
+
}
|
|
20633
|
+
}, [
|
|
20634
|
+
h("option", { key: "", value: "" }, "\u7EE7\u627F\u9ED8\u8BA4"),
|
|
20635
|
+
...options.map((effort2) => h("option", { key: effort2, value: effort2 }, effort2))
|
|
20636
|
+
]),
|
|
20637
|
+
h("small", {
|
|
20638
|
+
className: error62 === void 0 ? "odc-hint" : "odc-hint odc-field-error",
|
|
20639
|
+
id: `${id}-hint`,
|
|
20640
|
+
...error62 === void 0 ? {} : { role: "alert" }
|
|
20641
|
+
}, error62 ?? (unknown2 ? "\u8BE5\u6A21\u578B\u76EE\u5F55\u672A\u63D0\u4F9B\u601D\u8003\u6863\u4F4D\uFF0C\u65E0\u6CD5\u8986\u76D6\u3002" : "\u53EA\u5217\u51FA\u8BE5\u6A21\u578B\u5DF2\u77E5\u6863\u4F4D\uFF1B\u7559\u7A7A\u7EE7\u627F\u9ED8\u8BA4\u3002"))
|
|
20642
|
+
);
|
|
20643
|
+
}
|
|
20644
|
+
function ModelRow({ model, settings, authoritative, writable, pending, onCommit }) {
|
|
20645
|
+
const id = React.useId();
|
|
20646
|
+
const mounted = useMounted();
|
|
20647
|
+
const [error62, setError] = React.useState(void 0);
|
|
20648
|
+
const [resetToken, setResetToken] = React.useState(0);
|
|
20649
|
+
const enabled = modelEnabled(model, settings, authoritative);
|
|
20650
|
+
const hasOverrides = Object.keys(settings).length > 0;
|
|
20651
|
+
const commit = async (next) => {
|
|
20652
|
+
const saved = await onCommit(next);
|
|
20653
|
+
if (mounted.current && !saved) setError("\u8BBE\u7F6E\u672A\u4FDD\u5B58\uFF0C\u8BF7\u91CD\u8BD5\u3002");
|
|
20654
|
+
return saved;
|
|
20655
|
+
};
|
|
20656
|
+
const saveField = async (key, value) => {
|
|
20657
|
+
const next = { ...settings };
|
|
20658
|
+
if (value === void 0) delete next[key];
|
|
20659
|
+
else next[key] = value;
|
|
20660
|
+
setError(void 0);
|
|
20661
|
+
return commit(next);
|
|
20662
|
+
};
|
|
20663
|
+
const reset = async () => {
|
|
20664
|
+
setError(void 0);
|
|
20665
|
+
setResetToken((token) => token + 1);
|
|
20666
|
+
await commit(void 0);
|
|
20667
|
+
};
|
|
20668
|
+
const facts = [
|
|
20669
|
+
`\u4E0A\u4E0B\u6587 ${formatTokens(model.contextWindow)}`,
|
|
20670
|
+
`\u6700\u5927\u8F93\u51FA ${formatTokens(model.maxOutputTokens)}`,
|
|
20671
|
+
...model.reasoningEfforts === void 0 || model.reasoningEfforts.length === 0 ? [] : [`\u601D\u8003\u6863\u4F4D ${model.reasoningEfforts.join(" / ")}`]
|
|
20672
|
+
].join(" \xB7 ");
|
|
20673
|
+
return h(
|
|
20674
|
+
"li",
|
|
20675
|
+
{ className: "odc-model-item" },
|
|
20676
|
+
h(
|
|
20677
|
+
"div",
|
|
20678
|
+
{ className: "odc-model-head" },
|
|
20679
|
+
h(
|
|
20680
|
+
"label",
|
|
20681
|
+
{ className: "odc-switch odc-model-switch" },
|
|
20682
|
+
h("input", {
|
|
20683
|
+
type: "checkbox",
|
|
20684
|
+
checked: enabled,
|
|
20685
|
+
disabled: !writable || pending,
|
|
20686
|
+
onChange: (event) => {
|
|
20687
|
+
void commit({ ...settings, enabled: event.target.checked });
|
|
20688
|
+
}
|
|
20689
|
+
}),
|
|
20690
|
+
h("span", null, h("strong", null, model.name), h("code", null, model.id))
|
|
20691
|
+
),
|
|
20692
|
+
h(
|
|
20693
|
+
"div",
|
|
20694
|
+
{ className: "odc-actions" },
|
|
20695
|
+
enabled ? null : h("span", { className: "odc-chip" }, "\u5DF2\u7981\u7528"),
|
|
20696
|
+
h("button", { className: "odc-button odc-button-small", type: "button", disabled: !writable || pending || !hasOverrides, onClick: () => {
|
|
20697
|
+
void reset();
|
|
20698
|
+
} }, "\u91CD\u7F6E")
|
|
20699
|
+
)
|
|
20700
|
+
),
|
|
20701
|
+
h("p", { className: "odc-model-meta" }, facts),
|
|
20702
|
+
h(
|
|
20703
|
+
"details",
|
|
20704
|
+
{ className: "odc-model-details" },
|
|
20705
|
+
h("summary", { "aria-label": `${model.name} \u53C2\u6570\u8BBE\u7F6E` }, "\u53C2\u6570\u8BBE\u7F6E"),
|
|
20706
|
+
h(
|
|
20707
|
+
"div",
|
|
20708
|
+
{ className: "odc-model-editor" },
|
|
20709
|
+
NUMERIC_ORDER.map((key) => h(OptionalNumberField, {
|
|
20710
|
+
key,
|
|
20711
|
+
id: `${id}-${key}`,
|
|
20712
|
+
field: key,
|
|
20713
|
+
value: settings[key],
|
|
20714
|
+
disabled: !writable || pending,
|
|
20715
|
+
resetToken,
|
|
20716
|
+
onSave: (value) => saveField(key, value)
|
|
20717
|
+
})),
|
|
20718
|
+
h(EffortField, {
|
|
20719
|
+
id: `${id}-effort`,
|
|
20720
|
+
model,
|
|
20721
|
+
value: settings.reasoningEffort,
|
|
20722
|
+
disabled: !writable || pending,
|
|
20723
|
+
onChange: async (value) => {
|
|
20724
|
+
const next = { ...settings };
|
|
20725
|
+
if (value === "") delete next.reasoningEffort;
|
|
20726
|
+
else next.reasoningEffort = value;
|
|
20727
|
+
setError(void 0);
|
|
20728
|
+
return commit(next);
|
|
20729
|
+
}
|
|
20730
|
+
})
|
|
20731
|
+
)
|
|
20732
|
+
),
|
|
20733
|
+
error62 !== void 0 ? h("p", { className: "odc-hint odc-field-error", role: "alert" }, error62) : null
|
|
20281
20734
|
);
|
|
20282
20735
|
}
|
|
20283
|
-
function ModelGroup({ title, group, models }) {
|
|
20736
|
+
function ModelGroup({ title, group, models, settingsMap, authoritative, writable, pending, onCommit }) {
|
|
20284
20737
|
const [query, setQuery] = React.useState("");
|
|
20285
20738
|
const id = React.useId();
|
|
20286
20739
|
const normalized = query.trim().toLocaleLowerCase();
|
|
20287
|
-
const
|
|
20740
|
+
const groupModels = models.filter((model) => model.group === group);
|
|
20741
|
+
const filtered = groupModels.filter((model) => normalized === "" || `${model.name} ${model.id}`.toLocaleLowerCase().includes(normalized));
|
|
20742
|
+
const enabledCount = groupModels.filter((model) => modelEnabled(model, settingsMap[model.id], authoritative)).length;
|
|
20288
20743
|
return h(
|
|
20289
20744
|
"section",
|
|
20290
20745
|
{ className: "odc-card", "aria-labelledby": `${id}-title` },
|
|
@@ -20292,7 +20747,7 @@ function ModelGroup({ title, group, models }) {
|
|
|
20292
20747
|
"div",
|
|
20293
20748
|
{ className: "odc-card-head" },
|
|
20294
20749
|
h("h3", { id: `${id}-title` }, title),
|
|
20295
|
-
h("span", { className: "odc-model-count" }, `${
|
|
20750
|
+
h("span", { className: "odc-model-count" }, `${enabledCount} / ${groupModels.length} \u5DF2\u542F\u7528`)
|
|
20296
20751
|
),
|
|
20297
20752
|
h("label", { className: "odc-label", htmlFor: `${id}-search` }, `\u641C\u7D22${title}`),
|
|
20298
20753
|
h("input", {
|
|
@@ -20303,25 +20758,280 @@ function ModelGroup({ title, group, models }) {
|
|
|
20303
20758
|
placeholder: "\u8F93\u5165\u6A21\u578B\u540D\u79F0\u6216 ID",
|
|
20304
20759
|
onChange: (event) => setQuery(event.target.value)
|
|
20305
20760
|
}),
|
|
20306
|
-
filtered.length === 0 ? h("p", { className: "odc-hint", role: "status" }, "\u6CA1\u6709\u5339\u914D\u7684\u6A21\u578B\u3002") : h("ul", { className: "odc-model-list" }, filtered.map((model) => h(
|
|
20307
|
-
|
|
20308
|
-
|
|
20309
|
-
|
|
20310
|
-
|
|
20311
|
-
|
|
20312
|
-
|
|
20761
|
+
filtered.length === 0 ? h("p", { className: "odc-hint", role: "status" }, "\u6CA1\u6709\u5339\u914D\u7684\u6A21\u578B\u3002") : h("ul", { className: "odc-model-list" }, filtered.map((model) => h(ModelRow, {
|
|
20762
|
+
key: model.id,
|
|
20763
|
+
model,
|
|
20764
|
+
settings: modelSettingsEntry(settingsMap, model.id),
|
|
20765
|
+
authoritative,
|
|
20766
|
+
writable,
|
|
20767
|
+
pending,
|
|
20768
|
+
onCommit: (next) => onCommit(model.id, next)
|
|
20769
|
+
})))
|
|
20313
20770
|
);
|
|
20314
20771
|
}
|
|
20315
|
-
function Models({
|
|
20772
|
+
function Models({ status, formSnapshot, setFormField, pendingField, onRefreshModels, refreshingModels, notice }) {
|
|
20773
|
+
const formReady = formSnapshot.status === "ready" && formSnapshot.value !== void 0;
|
|
20774
|
+
const settingsMap = formReady ? formSnapshot.value?.modelSettings ?? {} : status?.config.modelSettings ?? {};
|
|
20775
|
+
const authoritative = formReady || status?.config.modelSettings !== void 0;
|
|
20776
|
+
const writable = formSnapshot.writable;
|
|
20777
|
+
const pending = pendingField === "modelSettings";
|
|
20778
|
+
const latestSettings = React.useRef(settingsMap);
|
|
20779
|
+
React.useEffect(() => {
|
|
20780
|
+
latestSettings.current = settingsMap;
|
|
20781
|
+
}, [settingsMap]);
|
|
20782
|
+
const saving = React.useRef(false);
|
|
20783
|
+
const commit = async (id, next) => {
|
|
20784
|
+
if (!writable || saving.current) return false;
|
|
20785
|
+
saving.current = true;
|
|
20786
|
+
try {
|
|
20787
|
+
return await setFormField("modelSettings", writeModelSettings(latestSettings.current, id, next));
|
|
20788
|
+
} finally {
|
|
20789
|
+
saving.current = false;
|
|
20790
|
+
}
|
|
20791
|
+
};
|
|
20792
|
+
const source = status?.modelsSource === "openai" ? "OpenAI /models \u53D1\u73B0" : status?.modelsSource === "builtin" ? "\u5185\u7F6E\u76EE\u5F55" : "\u5C1A\u672A\u786E\u8BA4";
|
|
20793
|
+
const updated = status?.modelsUpdatedAt === void 0 ? "" : ` \xB7 \u66F4\u65B0\u4E8E ${formatTime(status.modelsUpdatedAt)}`;
|
|
20794
|
+
const models = status?.models ?? [];
|
|
20316
20795
|
return h(
|
|
20317
20796
|
React.Fragment,
|
|
20318
20797
|
null,
|
|
20319
|
-
h("div", null, h("h3", null, "\u53EF\u7528\u6A21\u578B"), h("p", { className: "odc-hint" }, "\u4E24\u4E2A Provider \u72EC\u7ACB\u7B5B\u9009\u3002\u8FD9\u91CC\u4EC5\u5C55\u793A\u76EE\u5F55\uFF0C\u4E0D\u4FEE\u6539 API \u6216\u5F53\u524D\u4F1A\u8BDD\u6A21\u578B\u3002")),
|
|
20320
20798
|
h(
|
|
20799
|
+
"div",
|
|
20800
|
+
{ className: "odc-card-head" },
|
|
20801
|
+
h(
|
|
20802
|
+
"div",
|
|
20803
|
+
null,
|
|
20804
|
+
h("h3", null, "\u53EF\u7528\u6A21\u578B"),
|
|
20805
|
+
h("p", { className: "odc-hint" }, "\u4E24\u4E2A Provider \u72EC\u7ACB\u7B5B\u9009\u3002\u9010\u6A21\u578B\u7684\u542F\u7528\u4E0E\u53C2\u6570\u4F1A\u4FDD\u5B58\u5230\u63D2\u4EF6\u8BBE\u7F6E\uFF0C\u53EA\u5F71\u54CD\u672C\u63D2\u4EF6\u7684\u6A21\u578B\u9009\u62E9\u4E0E\u8BF7\u6C42\u3002")
|
|
20806
|
+
),
|
|
20807
|
+
h(
|
|
20808
|
+
"div",
|
|
20809
|
+
{ className: "odc-actions" },
|
|
20810
|
+
h("span", { className: "odc-label", role: "status" }, `\u6765\u6E90\uFF1A${source}${updated}`),
|
|
20811
|
+
h("button", {
|
|
20812
|
+
className: "odc-button",
|
|
20813
|
+
type: "button",
|
|
20814
|
+
disabled: refreshingModels || status === void 0 || status.apiKeyConfigured === false,
|
|
20815
|
+
onClick: onRefreshModels
|
|
20816
|
+
}, refreshingModels ? "\u6B63\u5728\u5237\u65B0\u6A21\u578B\u2026" : "\u4ECE OpenAI \u5237\u65B0\u6A21\u578B")
|
|
20817
|
+
)
|
|
20818
|
+
),
|
|
20819
|
+
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,
|
|
20820
|
+
status?.modelsError !== void 0 ? h("p", { className: "odc-notice", "data-kind": "error", role: "alert" }, status.modelsError) : null,
|
|
20821
|
+
h(NoticeView, { notice }),
|
|
20822
|
+
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(
|
|
20321
20823
|
"div",
|
|
20322
20824
|
{ className: "odc-model-groups" },
|
|
20323
|
-
h(ModelGroup, { title: "\u5957\u9910\u8D60\u9001 Provider", group: "plan", models
|
|
20324
|
-
h(ModelGroup, { title: "\u4ED8\u8D39 Provider", group: "paid", models
|
|
20825
|
+
h(ModelGroup, { title: "\u5957\u9910\u8D60\u9001 Provider", group: "plan", models, settingsMap, authoritative, writable, pending, onCommit: commit }),
|
|
20826
|
+
h(ModelGroup, { title: "\u4ED8\u8D39 Provider", group: "paid", models, settingsMap, authoritative, writable, pending, onCommit: commit })
|
|
20827
|
+
)
|
|
20828
|
+
);
|
|
20829
|
+
}
|
|
20830
|
+
function NumberField({ id, label, hint, value, min, max, integer: integer2, disabled, onCommit }) {
|
|
20831
|
+
const mounted = useMounted();
|
|
20832
|
+
const [draft, setDraft] = React.useState(String(value));
|
|
20833
|
+
const [error62, setError] = React.useState(void 0);
|
|
20834
|
+
React.useEffect(() => {
|
|
20835
|
+
setDraft(String(value));
|
|
20836
|
+
setError(void 0);
|
|
20837
|
+
}, [value]);
|
|
20838
|
+
const commit = async () => {
|
|
20839
|
+
const result = parseNumberInput(draft, { label, min, max, ...integer2 ? { integer: true } : {} });
|
|
20840
|
+
if (!result.ok) {
|
|
20841
|
+
setError(result.message);
|
|
20842
|
+
return;
|
|
20843
|
+
}
|
|
20844
|
+
if (result.value === void 0 || result.value === value) {
|
|
20845
|
+
setDraft(String(value));
|
|
20846
|
+
setError(void 0);
|
|
20847
|
+
return;
|
|
20848
|
+
}
|
|
20849
|
+
const saved = await onCommit(result.value);
|
|
20850
|
+
if (!mounted.current) return;
|
|
20851
|
+
if (saved) setError(void 0);
|
|
20852
|
+
else setError("\u8BBE\u7F6E\u672A\u4FDD\u5B58\uFF0C\u8BF7\u91CD\u8BD5\u3002");
|
|
20853
|
+
};
|
|
20854
|
+
return h(
|
|
20855
|
+
"div",
|
|
20856
|
+
{ className: "odc-field" },
|
|
20857
|
+
h("label", { htmlFor: id }, label),
|
|
20858
|
+
h("input", {
|
|
20859
|
+
id,
|
|
20860
|
+
className: "odc-input",
|
|
20861
|
+
type: "number",
|
|
20862
|
+
inputMode: "numeric",
|
|
20863
|
+
min,
|
|
20864
|
+
max,
|
|
20865
|
+
step: integer2 ? 1 : 0.1,
|
|
20866
|
+
value: draft,
|
|
20867
|
+
disabled,
|
|
20868
|
+
"aria-invalid": error62 !== void 0,
|
|
20869
|
+
"aria-describedby": `${id}-hint`,
|
|
20870
|
+
onChange: (event) => setDraft(event.target.value),
|
|
20871
|
+
onBlur: () => {
|
|
20872
|
+
void commit();
|
|
20873
|
+
}
|
|
20874
|
+
}),
|
|
20875
|
+
h("small", {
|
|
20876
|
+
className: error62 === void 0 ? "odc-hint" : "odc-hint odc-field-error",
|
|
20877
|
+
id: `${id}-hint`,
|
|
20878
|
+
...error62 === void 0 ? {} : { role: "alert" }
|
|
20879
|
+
}, error62 ?? hint)
|
|
20880
|
+
);
|
|
20881
|
+
}
|
|
20882
|
+
function Advanced({ status, formSnapshot, setFormField, pendingField }) {
|
|
20883
|
+
const [apiKeyEnv, setApiKeyEnv] = React.useState(status?.config.apiKeyEnv ?? "");
|
|
20884
|
+
const [keyNotice, setKeyNotice] = React.useState(null);
|
|
20885
|
+
const mounted = useMounted();
|
|
20886
|
+
React.useEffect(() => {
|
|
20887
|
+
setApiKeyEnv(formSnapshot.value?.apiKeyEnv ?? status?.config.apiKeyEnv ?? "");
|
|
20888
|
+
}, [formSnapshot.value?.apiKeyEnv, status?.config.apiKeyEnv]);
|
|
20889
|
+
const writable = formSnapshot.writable;
|
|
20890
|
+
const configuredProtocol = formSnapshot.value?.apiProtocol ?? status?.config.apiProtocol;
|
|
20891
|
+
const protocol = configuredProtocol !== void 0 && API_PROTOCOL_OPTIONS.some((option) => option.id === configuredProtocol) ? configuredProtocol : "chat-completions";
|
|
20892
|
+
const baseURL = formSnapshot.value?.baseURL ?? status?.config.baseURL ?? "";
|
|
20893
|
+
const requestTimeout = formSnapshot.value?.requestTimeoutMs ?? status?.config.requestTimeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS;
|
|
20894
|
+
const streamIdleTimeout = formSnapshot.value?.streamIdleTimeoutMs ?? status?.config.streamIdleTimeoutMs ?? DEFAULT_STREAM_IDLE_TIMEOUT_MS;
|
|
20895
|
+
const refreshSeconds = formSnapshot.value?.quotaRefreshSeconds ?? status?.config.quotaRefreshSeconds ?? DEFAULT_QUOTA_REFRESH_SECONDS;
|
|
20896
|
+
const selected = API_PROTOCOL_OPTIONS.find((option) => option.id === protocol);
|
|
20897
|
+
const saveKeyRef = async () => {
|
|
20898
|
+
const value = apiKeyEnv.trim();
|
|
20899
|
+
if (value === "") {
|
|
20900
|
+
setKeyNotice({ kind: "error", text: "\u914D\u7F6E\u503C\u4E0D\u80FD\u4E3A\u7A7A\u3002" });
|
|
20901
|
+
return;
|
|
20902
|
+
}
|
|
20903
|
+
setKeyNotice(null);
|
|
20904
|
+
try {
|
|
20905
|
+
const accepted = await setFormField("apiKeyEnv", value);
|
|
20906
|
+
if (mounted.current) setKeyNotice(accepted ? { kind: "status", text: "\u914D\u7F6E\u5DF2\u4FDD\u5B58\u3002" } : { kind: "error", text: "\u914D\u7F6E\u672A\u4FDD\u5B58\uFF0C\u8BF7\u5237\u65B0\u540E\u91CD\u8BD5\u3002" });
|
|
20907
|
+
} catch {
|
|
20908
|
+
if (mounted.current) setKeyNotice({ kind: "error", text: GENERIC_ERROR });
|
|
20909
|
+
}
|
|
20910
|
+
};
|
|
20911
|
+
return h(
|
|
20912
|
+
React.Fragment,
|
|
20913
|
+
null,
|
|
20914
|
+
h(
|
|
20915
|
+
"section",
|
|
20916
|
+
{ className: "odc-card" },
|
|
20917
|
+
h("h3", null, "\u7A7A\u8F6E\u76D1\u63A7"),
|
|
20918
|
+
h("p", { className: "odc-hint" }, "\u72EC\u7ACB\u76D1\u63A7\u5957\u9910\u8D60\u9001\u6A21\u578B\u7684\u7A7A\u8F6E\u6216\u534F\u8BAE\u6B8B\u6E23\uFF1B\u4E0D\u5F71\u54CD\u4ED8\u8D39 Provider \u7684\u5F00\u5173\u3002"),
|
|
20919
|
+
h("div", { style: { marginTop: 14 } }, h(Switch, {
|
|
20920
|
+
checked: formSnapshot.value?.emptyTurnGuard ?? status?.config.emptyTurnGuard ?? true,
|
|
20921
|
+
disabled: !writable || pendingField === "emptyTurnGuard",
|
|
20922
|
+
label: "\u542F\u7528\u7A7A\u8F6E\u76D1\u63A7",
|
|
20923
|
+
hint: `\u672C\u6B21\u8FD0\u884C\u5DF2\u62E6\u622A ${status?.guardedTurns ?? "\u2014"} \u8F6E\u3002\u68C0\u6D4B\u540E\u7531\u5BBF\u4E3B\u91CD\u8BD5\u7B56\u7565\u5904\u7406\uFF0C\u5BBF\u4E3B\u91CD\u8BD5\u4F1A\u989D\u5916\u6D88\u8017\u989D\u5EA6\u3002`,
|
|
20924
|
+
onChange: (checked) => {
|
|
20925
|
+
void setFormField("emptyTurnGuard", checked);
|
|
20926
|
+
}
|
|
20927
|
+
}))
|
|
20928
|
+
),
|
|
20929
|
+
h(
|
|
20930
|
+
"section",
|
|
20931
|
+
{ className: "odc-card" },
|
|
20932
|
+
h("h3", null, "\u63A8\u7406\u534F\u8BAE"),
|
|
20933
|
+
h("p", { className: "odc-hint" }, "\u63D2\u4EF6\u6309\u6240\u9009\u534F\u8BAE\u7EC4\u88C5\u8BF7\u6C42\uFF1B\u6A21\u578B\u53D1\u73B0\u59CB\u7EC8\u8BFB\u53D6 OpenAI /models\uFF0C\u4E0E\u8FD9\u91CC\u7684\u9009\u62E9\u65E0\u5173\u3002"),
|
|
20934
|
+
h(
|
|
20935
|
+
"div",
|
|
20936
|
+
{ className: "odc-field" },
|
|
20937
|
+
h("label", { htmlFor: "odc-api-protocol" }, "API \u534F\u8BAE"),
|
|
20938
|
+
h("select", {
|
|
20939
|
+
id: "odc-api-protocol",
|
|
20940
|
+
className: "odc-input",
|
|
20941
|
+
value: protocol,
|
|
20942
|
+
disabled: !writable || pendingField === "apiProtocol",
|
|
20943
|
+
onChange: (event) => {
|
|
20944
|
+
void setFormField("apiProtocol", event.target.value);
|
|
20945
|
+
}
|
|
20946
|
+
}, API_PROTOCOL_OPTIONS.map((option) => h("option", { key: option.id, value: option.id }, option.name))),
|
|
20947
|
+
h("small", { className: "odc-hint" }, selected?.description ?? "\u9009\u62E9\u4E0E\u7F51\u5173\u517C\u5BB9\u7684\u63A8\u7406\u534F\u8BAE\u3002")
|
|
20948
|
+
),
|
|
20949
|
+
h(
|
|
20950
|
+
"div",
|
|
20951
|
+
{ className: "odc-readonly" },
|
|
20952
|
+
h(
|
|
20953
|
+
"div",
|
|
20954
|
+
null,
|
|
20955
|
+
h("span", { className: "odc-label" }, "\u5F53\u524D\u7F51\u5173\u5730\u5740\uFF08\u53EA\u8BFB\uFF09"),
|
|
20956
|
+
h("code", { className: "odc-code" }, baseURL === "" ? "\u2014" : baseURL)
|
|
20957
|
+
),
|
|
20958
|
+
h(
|
|
20959
|
+
"div",
|
|
20960
|
+
null,
|
|
20961
|
+
h("span", { className: "odc-label" }, "\u5F53\u524D\u63A8\u7406\u8DEF\u5F84\uFF08\u53EA\u8BFB\uFF09"),
|
|
20962
|
+
h("code", { className: "odc-code" }, protocolEndpoint(baseURL, protocol))
|
|
20963
|
+
),
|
|
20964
|
+
h("small", { className: "odc-hint" }, "\u5730\u5740\u7531\u63D2\u4EF6\u914D\u7F6E\u63D0\u4F9B\uFF0C\u65E0\u9700\u5728\u6B64\u586B\u5199\uFF1B\u5207\u6362\u534F\u8BAE\u53EA\u6539\u53D8\u8BF7\u6C42\u8DEF\u5F84\u4E0E\u62A5\u6587\u683C\u5F0F\u3002")
|
|
20965
|
+
)
|
|
20966
|
+
),
|
|
20967
|
+
h(
|
|
20968
|
+
"section",
|
|
20969
|
+
{ className: "odc-card" },
|
|
20970
|
+
h("h3", null, "\u51ED\u636E\u4E0E\u7F51\u5173"),
|
|
20971
|
+
h("p", { className: "odc-hint" }, "\u8FD9\u91CC\u53EA\u4FDD\u5B58\u51ED\u636E\u5F15\u7528\u540D\u79F0\uFF0C\u4E0D\u586B\u5199 Key \u672C\u8EAB\uFF1B\u7F51\u5173\u5730\u5740\u7531\u63D2\u4EF6\u914D\u7F6E\u6258\u7BA1\u3002"),
|
|
20972
|
+
h(
|
|
20973
|
+
"div",
|
|
20974
|
+
{ className: "odc-field" },
|
|
20975
|
+
h("label", { htmlFor: "odc-api-key-env" }, "API Key \u73AF\u5883\u53D8\u91CF / \u51ED\u636E\u5F15\u7528\u540D"),
|
|
20976
|
+
h("input", {
|
|
20977
|
+
id: "odc-api-key-env",
|
|
20978
|
+
className: "odc-input",
|
|
20979
|
+
type: "text",
|
|
20980
|
+
value: apiKeyEnv,
|
|
20981
|
+
disabled: !writable,
|
|
20982
|
+
autoCapitalize: "off",
|
|
20983
|
+
spellCheck: false,
|
|
20984
|
+
onChange: (event) => setApiKeyEnv(event.target.value)
|
|
20985
|
+
}),
|
|
20986
|
+
h("small", { className: "odc-hint" }, "\u5F15\u7528\u540D\u5BF9\u5E94\u7684\u51ED\u636E\u4ECD\u4F18\u5148\u4E8E\u672C\u63D2\u4EF6\u4FDD\u5B58\u7684 Key\u3002")
|
|
20987
|
+
),
|
|
20988
|
+
h(
|
|
20989
|
+
"div",
|
|
20990
|
+
{ className: "odc-actions", style: { marginTop: 10 } },
|
|
20991
|
+
h("button", { className: "odc-button", type: "button", disabled: !writable || pendingField === "apiKeyEnv", onClick: () => {
|
|
20992
|
+
void saveKeyRef();
|
|
20993
|
+
} }, "\u4FDD\u5B58\u5F15\u7528\u540D")
|
|
20994
|
+
),
|
|
20995
|
+
h(NoticeView, { notice: keyNotice })
|
|
20996
|
+
),
|
|
20997
|
+
h(
|
|
20998
|
+
"section",
|
|
20999
|
+
{ className: "odc-card" },
|
|
21000
|
+
h("h3", null, "\u8BF7\u6C42\u65F6\u9650\u4E0E\u81EA\u52A8\u5237\u65B0"),
|
|
21001
|
+
h("p", { className: "odc-hint" }, "\u6570\u503C\u5728\u79BB\u5F00\u8F93\u5165\u6846\u65F6\u6821\u9A8C\u5E76\u4FDD\u5B58\uFF1B\u7559\u7A7A\u6216\u8D8A\u754C\u4E0D\u4F1A\u5199\u5165\u3002"),
|
|
21002
|
+
h(NumberField, {
|
|
21003
|
+
id: "odc-request-timeout",
|
|
21004
|
+
label: "\u8BF7\u6C42\u603B\u8D85\u65F6\uFF08\u6BEB\u79D2\uFF09",
|
|
21005
|
+
hint: "\u4ECE\u53D1\u51FA\u8BF7\u6C42\u5230\u54CD\u5E94\u7ED3\u675F\u7684\u4E0A\u9650\uFF0C1000\u20133600000\u3002",
|
|
21006
|
+
value: requestTimeout,
|
|
21007
|
+
min: MIN_REQUEST_TIMEOUT_MS,
|
|
21008
|
+
max: MAX_REQUEST_TIMEOUT_MS,
|
|
21009
|
+
integer: true,
|
|
21010
|
+
disabled: !writable || pendingField === "requestTimeoutMs",
|
|
21011
|
+
onCommit: (value) => setFormField("requestTimeoutMs", value)
|
|
21012
|
+
}),
|
|
21013
|
+
h(NumberField, {
|
|
21014
|
+
id: "odc-stream-idle-timeout",
|
|
21015
|
+
label: "\u6D41\u5F0F\u7A7A\u95F2\u8D85\u65F6\uFF08\u6BEB\u79D2\uFF09",
|
|
21016
|
+
hint: "\u6D41\u5F0F\u54CD\u5E94\u65E0\u65B0\u6570\u636E\u7684\u6700\u957F\u7B49\u5F85\uFF0C1000\u20131800000\u3002",
|
|
21017
|
+
value: streamIdleTimeout,
|
|
21018
|
+
min: MIN_STREAM_IDLE_TIMEOUT_MS,
|
|
21019
|
+
max: MAX_STREAM_IDLE_TIMEOUT_MS,
|
|
21020
|
+
integer: true,
|
|
21021
|
+
disabled: !writable || pendingField === "streamIdleTimeoutMs",
|
|
21022
|
+
onCommit: (value) => setFormField("streamIdleTimeoutMs", value)
|
|
21023
|
+
}),
|
|
21024
|
+
h(NumberField, {
|
|
21025
|
+
id: "odc-quota-refresh",
|
|
21026
|
+
label: "\u989D\u5EA6\u81EA\u52A8\u5237\u65B0\u95F4\u9694\uFF08\u79D2\uFF09",
|
|
21027
|
+
hint: `5\u20133600\uFF1B\u9ED8\u8BA4 ${DEFAULT_QUOTA_REFRESH_SECONDS} \u79D2\uFF0C\u9875\u9762\u5173\u95ED\u540E\u505C\u6B62\u3002`,
|
|
21028
|
+
value: refreshSeconds,
|
|
21029
|
+
min: MIN_QUOTA_REFRESH_SECONDS,
|
|
21030
|
+
max: MAX_QUOTA_REFRESH_SECONDS,
|
|
21031
|
+
integer: true,
|
|
21032
|
+
disabled: !writable || pendingField === "quotaRefreshSeconds",
|
|
21033
|
+
onCommit: (value) => setFormField("quotaRefreshSeconds", value)
|
|
21034
|
+
})
|
|
20325
21035
|
)
|
|
20326
21036
|
);
|
|
20327
21037
|
}
|
|
@@ -20483,79 +21193,6 @@ function Connection({ status, formSnapshot, setFormField, pendingField, caller,
|
|
|
20483
21193
|
)
|
|
20484
21194
|
);
|
|
20485
21195
|
}
|
|
20486
|
-
function Advanced({ status, formSnapshot, setFormField, pendingField }) {
|
|
20487
|
-
const [baseURL, setBaseURL] = React.useState(status?.config.baseURL ?? "");
|
|
20488
|
-
const [apiKeyEnv, setApiKeyEnv] = React.useState(status?.config.apiKeyEnv ?? "");
|
|
20489
|
-
const [notice, setNotice] = React.useState(null);
|
|
20490
|
-
const mounted = useMounted();
|
|
20491
|
-
React.useEffect(() => {
|
|
20492
|
-
setBaseURL(formSnapshot.value?.baseURL ?? status?.config.baseURL ?? "");
|
|
20493
|
-
}, [formSnapshot.value?.baseURL, status?.config.baseURL]);
|
|
20494
|
-
React.useEffect(() => {
|
|
20495
|
-
setApiKeyEnv(formSnapshot.value?.apiKeyEnv ?? status?.config.apiKeyEnv ?? "");
|
|
20496
|
-
}, [formSnapshot.value?.apiKeyEnv, status?.config.apiKeyEnv]);
|
|
20497
|
-
const saveText = async (field) => {
|
|
20498
|
-
const value = field === "baseURL" ? baseURL.trim() : apiKeyEnv.trim();
|
|
20499
|
-
if (value === "") {
|
|
20500
|
-
setNotice({ kind: "error", text: "\u914D\u7F6E\u503C\u4E0D\u80FD\u4E3A\u7A7A\u3002" });
|
|
20501
|
-
return;
|
|
20502
|
-
}
|
|
20503
|
-
setNotice(null);
|
|
20504
|
-
try {
|
|
20505
|
-
const accepted = await setFormField(field, value);
|
|
20506
|
-
if (mounted.current) setNotice(accepted ? { kind: "status", text: "\u914D\u7F6E\u5DF2\u4FDD\u5B58\u3002" } : { kind: "error", text: "\u914D\u7F6E\u672A\u4FDD\u5B58\uFF0C\u8BF7\u5237\u65B0\u540E\u91CD\u8BD5\u3002" });
|
|
20507
|
-
} catch {
|
|
20508
|
-
if (mounted.current) setNotice({ kind: "error", text: GENERIC_ERROR });
|
|
20509
|
-
}
|
|
20510
|
-
};
|
|
20511
|
-
const disabled = !formSnapshot.writable;
|
|
20512
|
-
return h(
|
|
20513
|
-
React.Fragment,
|
|
20514
|
-
null,
|
|
20515
|
-
h(
|
|
20516
|
-
"section",
|
|
20517
|
-
{ className: "odc-card" },
|
|
20518
|
-
h("h3", null, "\u7A7A\u8F6E\u76D1\u63A7"),
|
|
20519
|
-
h("p", { className: "odc-hint" }, "\u72EC\u7ACB\u76D1\u63A7\u5957\u9910\u8D60\u9001\u6A21\u578B\u7684\u7A7A\u8F6E\u6216\u534F\u8BAE\u6B8B\u6E23\uFF1B\u4E0D\u5F71\u54CD\u4ED8\u8D39 Provider \u7684\u5F00\u5173\u3002"),
|
|
20520
|
-
h("div", { style: { marginTop: 14 } }, h(Switch, {
|
|
20521
|
-
checked: formSnapshot.value?.emptyTurnGuard ?? status?.config.emptyTurnGuard ?? true,
|
|
20522
|
-
disabled: disabled || pendingField === "emptyTurnGuard",
|
|
20523
|
-
label: "\u542F\u7528\u7A7A\u8F6E\u76D1\u63A7",
|
|
20524
|
-
hint: `\u672C\u6B21\u8FD0\u884C\u5DF2\u62E6\u622A ${status?.guardedTurns ?? "\u2014"} \u8F6E\u3002\u68C0\u6D4B\u540E\u7531\u5BBF\u4E3B\u91CD\u8BD5\u7B56\u7565\u5904\u7406\uFF0C\u5BBF\u4E3B\u91CD\u8BD5\u4F1A\u989D\u5916\u6D88\u8017\u989D\u5EA6\u3002`,
|
|
20525
|
-
onChange: (checked) => {
|
|
20526
|
-
void setFormField("emptyTurnGuard", checked);
|
|
20527
|
-
}
|
|
20528
|
-
}))
|
|
20529
|
-
),
|
|
20530
|
-
h(
|
|
20531
|
-
"section",
|
|
20532
|
-
{ className: "odc-card" },
|
|
20533
|
-
h("h3", null, "\u63A8\u7406\u8FDE\u63A5"),
|
|
20534
|
-
h("p", { className: "odc-hint" }, formSnapshot.status === "unavailable" ? "\u5BBF\u4E3B\u672A\u5F00\u653E\u6B64\u914D\u7F6E\u8868\u5355\u3002" : "\u5B57\u6BB5\u7531\u5BBF\u4E3B\u914D\u7F6E\u8868\u5355\u6821\u9A8C\u5E76\u6301\u4E45\u5316\uFF1B\u65E0\u9700\u989D\u5916\u7684\u4FDD\u5B58\u63A5\u53E3\u3002"),
|
|
20535
|
-
h(
|
|
20536
|
-
"div",
|
|
20537
|
-
{ className: "odc-field" },
|
|
20538
|
-
h("label", { htmlFor: "odc-base-url" }, "Base URL"),
|
|
20539
|
-
h("input", { id: "odc-base-url", className: "odc-input", type: "url", value: baseURL, disabled, onChange: (event) => setBaseURL(event.target.value) }),
|
|
20540
|
-
h("small", { className: "odc-hint" }, "\u4EC5\u7528\u4E8E OpenAI \u517C\u5BB9\u63A8\u7406\uFF0C\u4E0D\u7528\u4E8E\u63A7\u5236\u53F0\u767B\u5F55\u6216\u989D\u5EA6\u67E5\u8BE2\u3002")
|
|
20541
|
-
),
|
|
20542
|
-
h("div", { className: "odc-actions", style: { marginTop: 10 } }, h("button", { className: "odc-button", type: "button", disabled: disabled || pendingField === "baseURL", onClick: () => {
|
|
20543
|
-
void saveText("baseURL");
|
|
20544
|
-
} }, "\u4FDD\u5B58 Base URL")),
|
|
20545
|
-
h(
|
|
20546
|
-
"div",
|
|
20547
|
-
{ className: "odc-field" },
|
|
20548
|
-
h("label", { htmlFor: "odc-api-key-env" }, "API Key \u73AF\u5883\u53D8\u91CF / \u51ED\u636E\u5F15\u7528\u540D"),
|
|
20549
|
-
h("input", { id: "odc-api-key-env", className: "odc-input", type: "text", value: apiKeyEnv, disabled, autoCapitalize: "off", spellCheck: false, onChange: (event) => setApiKeyEnv(event.target.value) }),
|
|
20550
|
-
h("small", { className: "odc-hint" }, "\u8FD9\u91CC\u53EA\u4FDD\u5B58\u5F15\u7528\u540D\u79F0\uFF0C\u4E0D\u586B\u5199 Key \u672C\u8EAB\u3002")
|
|
20551
|
-
),
|
|
20552
|
-
h("div", { className: "odc-actions", style: { marginTop: 10 } }, h("button", { className: "odc-button", type: "button", disabled: disabled || pendingField === "apiKeyEnv", onClick: () => {
|
|
20553
|
-
void saveText("apiKeyEnv");
|
|
20554
|
-
} }, "\u4FDD\u5B58\u5F15\u7528\u540D")),
|
|
20555
|
-
h(NoticeView, { notice })
|
|
20556
|
-
)
|
|
20557
|
-
);
|
|
20558
|
-
}
|
|
20559
21196
|
function tabAfter(current, key) {
|
|
20560
21197
|
const index = TABS.findIndex((tab) => tab.id === current);
|
|
20561
21198
|
if (key === "Home") return TABS[0].id;
|
|
@@ -20571,11 +21208,15 @@ function SettingsPage({ caller, form }) {
|
|
|
20571
21208
|
const [error62, setError] = React.useState();
|
|
20572
21209
|
const [loading, setLoading] = React.useState(true);
|
|
20573
21210
|
const [refreshing, setRefreshing] = React.useState(false);
|
|
21211
|
+
const [refreshingModels, setRefreshingModels] = React.useState(false);
|
|
21212
|
+
const [modelsNotice, setModelsNotice] = React.useState(null);
|
|
20574
21213
|
const [pendingField, setPendingField] = React.useState(null);
|
|
20575
21214
|
const [formNotice, setFormNotice] = React.useState(null);
|
|
21215
|
+
const [scheduleTick, setScheduleTick] = React.useState(0);
|
|
20576
21216
|
const statusVersion = React.useRef(0);
|
|
20577
21217
|
const quotaVersion = React.useRef(0);
|
|
20578
21218
|
const loginVersion = React.useRef(0);
|
|
21219
|
+
const modelsVersion = React.useRef(0);
|
|
20579
21220
|
const tabRefs = React.useRef([]);
|
|
20580
21221
|
const baseId = React.useId();
|
|
20581
21222
|
const formSnapshot = useFormSnapshot(form);
|
|
@@ -20593,14 +21234,18 @@ function SettingsPage({ caller, form }) {
|
|
|
20593
21234
|
}
|
|
20594
21235
|
}, [caller, mounted]);
|
|
20595
21236
|
const refreshBusy = React.useRef(false);
|
|
20596
|
-
const
|
|
20597
|
-
|
|
21237
|
+
const forcedRefreshPending = React.useRef(false);
|
|
21238
|
+
const refresh = React.useCallback(async (force = false) => {
|
|
21239
|
+
if (refreshBusy.current) {
|
|
21240
|
+
if (force) forcedRefreshPending.current = true;
|
|
21241
|
+
return;
|
|
21242
|
+
}
|
|
20598
21243
|
refreshBusy.current = true;
|
|
20599
21244
|
const version2 = ++quotaVersion.current;
|
|
20600
21245
|
setRefreshing(true);
|
|
20601
21246
|
setError(void 0);
|
|
20602
21247
|
try {
|
|
20603
|
-
const quota = await caller("refreshQuota");
|
|
21248
|
+
const quota = await caller(force ? "refreshQuotaNow" : "refreshQuota");
|
|
20604
21249
|
if (!mounted.current || version2 !== quotaVersion.current) return;
|
|
20605
21250
|
setStatus((previous) => previous === void 0 ? previous : { ...previous, quota });
|
|
20606
21251
|
await loadStatus();
|
|
@@ -20610,6 +21255,10 @@ function SettingsPage({ caller, form }) {
|
|
|
20610
21255
|
if (mounted.current && version2 === quotaVersion.current) {
|
|
20611
21256
|
refreshBusy.current = false;
|
|
20612
21257
|
setRefreshing(false);
|
|
21258
|
+
if (forcedRefreshPending.current) {
|
|
21259
|
+
forcedRefreshPending.current = false;
|
|
21260
|
+
void refresh(true);
|
|
21261
|
+
}
|
|
20613
21262
|
}
|
|
20614
21263
|
}
|
|
20615
21264
|
}, [caller, loadStatus, mounted]);
|
|
@@ -20619,7 +21268,9 @@ function SettingsPage({ caller, form }) {
|
|
|
20619
21268
|
statusVersion.current += 1;
|
|
20620
21269
|
quotaVersion.current += 1;
|
|
20621
21270
|
loginVersion.current += 1;
|
|
21271
|
+
modelsVersion.current += 1;
|
|
20622
21272
|
refreshBusy.current = false;
|
|
21273
|
+
forcedRefreshPending.current = false;
|
|
20623
21274
|
};
|
|
20624
21275
|
}, [refresh]);
|
|
20625
21276
|
const setFormField = React.useCallback(async (field, value) => {
|
|
@@ -20628,6 +21279,7 @@ function SettingsPage({ caller, form }) {
|
|
|
20628
21279
|
try {
|
|
20629
21280
|
const accepted = await form.set(field, value);
|
|
20630
21281
|
if (mounted.current) setFormNotice(accepted ? { kind: "status", text: "\u8BBE\u7F6E\u5DF2\u4FDD\u5B58\u3002" } : { kind: "error", text: "\u8BBE\u7F6E\u672A\u4FDD\u5B58\uFF0C\u8BF7\u91CD\u8BD5\u3002" });
|
|
21282
|
+
if (accepted && (field === "useDesktopCredential" || field === "quotaRefreshSeconds")) await refresh(true);
|
|
20631
21283
|
return accepted;
|
|
20632
21284
|
} catch {
|
|
20633
21285
|
if (mounted.current) setFormNotice({ kind: "error", text: GENERIC_ERROR });
|
|
@@ -20635,7 +21287,29 @@ function SettingsPage({ caller, form }) {
|
|
|
20635
21287
|
} finally {
|
|
20636
21288
|
if (mounted.current) setPendingField(null);
|
|
20637
21289
|
}
|
|
20638
|
-
}, [form, mounted]);
|
|
21290
|
+
}, [form, mounted, refresh]);
|
|
21291
|
+
const refreshModelsBusy = React.useRef(false);
|
|
21292
|
+
const refreshModels = React.useCallback(async () => {
|
|
21293
|
+
if (refreshModelsBusy.current) return;
|
|
21294
|
+
refreshModelsBusy.current = true;
|
|
21295
|
+
const version2 = ++modelsVersion.current;
|
|
21296
|
+
setRefreshingModels(true);
|
|
21297
|
+
setModelsNotice(null);
|
|
21298
|
+
try {
|
|
21299
|
+
const next = await caller("refreshModels");
|
|
21300
|
+
if (!mounted.current || version2 !== modelsVersion.current) return;
|
|
21301
|
+
setStatus(next);
|
|
21302
|
+
setError(void 0);
|
|
21303
|
+
setModelsNotice(next.modelsError === void 0 ? { kind: "status", text: `\u5DF2\u4ECE OpenAI \u5237\u65B0\u6A21\u578B\u5217\u8868\uFF0C\u5171 ${next.models.length} \u4E2A\u6A21\u578B\u3002` } : null);
|
|
21304
|
+
} catch {
|
|
21305
|
+
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" });
|
|
21306
|
+
} finally {
|
|
21307
|
+
if (mounted.current && version2 === modelsVersion.current) {
|
|
21308
|
+
setRefreshingModels(false);
|
|
21309
|
+
refreshModelsBusy.current = false;
|
|
21310
|
+
}
|
|
21311
|
+
}
|
|
21312
|
+
}, [caller, mounted]);
|
|
20639
21313
|
const loginState = status?.login.state;
|
|
20640
21314
|
const loginActive = loginState !== void 0 && loginInFlight(loginState);
|
|
20641
21315
|
React.useEffect(() => {
|
|
@@ -20664,17 +21338,54 @@ function SettingsPage({ caller, form }) {
|
|
|
20664
21338
|
loginVersion.current += 1;
|
|
20665
21339
|
};
|
|
20666
21340
|
}, [caller, loadStatus, loginActive, mounted, refresh]);
|
|
21341
|
+
const configuredSeconds = formSnapshot.value?.quotaRefreshSeconds ?? status?.config.quotaRefreshSeconds;
|
|
21342
|
+
const refreshIntervalSeconds = configuredSeconds === void 0 ? DEFAULT_QUOTA_REFRESH_SECONDS : normaliseQuotaRefreshSeconds(configuredSeconds);
|
|
21343
|
+
const quotaNextRefreshAt = status?.quota.nextRefreshAt;
|
|
21344
|
+
const schedule = React.useMemo(
|
|
21345
|
+
() => status?.quota.state === "need-login" || status?.quota.autoRefreshPaused ? void 0 : quotaAutoRefresh(refreshIntervalSeconds, quotaNextRefreshAt, Date.now(), Boolean(status?.quota.refreshFailures)),
|
|
21346
|
+
[refreshIntervalSeconds, quotaNextRefreshAt, status?.quota.state, status?.quota.autoRefreshPaused, status?.quota.refreshFailures, scheduleTick]
|
|
21347
|
+
);
|
|
21348
|
+
React.useEffect(() => {
|
|
21349
|
+
if (schedule === void 0) return;
|
|
21350
|
+
const timer = setTimeout(() => {
|
|
21351
|
+
void refresh().finally(() => {
|
|
21352
|
+
if (mounted.current) setScheduleTick((tick) => tick + 1);
|
|
21353
|
+
});
|
|
21354
|
+
}, schedule.delayMs);
|
|
21355
|
+
return () => clearTimeout(timer);
|
|
21356
|
+
}, [schedule, refresh, mounted]);
|
|
20667
21357
|
const selectTab = (next) => {
|
|
20668
21358
|
setTab(next);
|
|
20669
21359
|
if (next === "overview" && tab !== "overview") void refresh();
|
|
20670
21360
|
};
|
|
20671
21361
|
let content;
|
|
20672
|
-
if (tab === "overview")
|
|
20673
|
-
|
|
20674
|
-
|
|
20675
|
-
|
|
20676
|
-
|
|
20677
|
-
|
|
21362
|
+
if (tab === "overview") {
|
|
21363
|
+
content = h(Overview, {
|
|
21364
|
+
status,
|
|
21365
|
+
busy: refreshing,
|
|
21366
|
+
onRefresh: () => {
|
|
21367
|
+
void refresh(true);
|
|
21368
|
+
},
|
|
21369
|
+
nextAutoRefreshAt: schedule?.at,
|
|
21370
|
+
refreshIntervalSeconds
|
|
21371
|
+
});
|
|
21372
|
+
} else if (tab === "models") {
|
|
21373
|
+
content = h(Models, {
|
|
21374
|
+
status,
|
|
21375
|
+
formSnapshot,
|
|
21376
|
+
setFormField,
|
|
21377
|
+
pendingField,
|
|
21378
|
+
onRefreshModels: () => {
|
|
21379
|
+
void refreshModels();
|
|
21380
|
+
},
|
|
21381
|
+
refreshingModels,
|
|
21382
|
+
notice: modelsNotice
|
|
21383
|
+
});
|
|
21384
|
+
} else if (tab === "connection") {
|
|
21385
|
+
content = h(Connection, { status, formSnapshot, setFormField, pendingField, caller, loadStatus, refreshAfterLogin: refresh });
|
|
21386
|
+
} else {
|
|
21387
|
+
content = h(Advanced, { status, formSnapshot, setFormField, pendingField });
|
|
21388
|
+
}
|
|
20678
21389
|
return h(
|
|
20679
21390
|
"div",
|
|
20680
21391
|
{ className: "odc-settings" },
|