dsh-opendesign-corouter 0.1.1 → 0.1.3
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 +118 -12
- package/lib/client.js +904 -137
- package/lib/config.d.ts +11 -0
- package/lib/generated/typert.host.js +83 -5
- package/lib/generated/typert.remote-client.d.ts +2 -0
- package/lib/generated/typert.remote-client.js +83 -5
- package/lib/index.d.ts +16 -0
- package/lib/index.js +1531 -192
- package/lib/index.js.map +4 -4
- package/lib/login.d.ts +2 -0
- 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/config.d.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import Schema from '@deepseek-ai/schemastery';
|
|
2
|
+
import { type ApiProtocol } from './protocol-options.js';
|
|
3
|
+
import { type ModelSettingsMap } from './model-settings.js';
|
|
2
4
|
export declare const SETTINGS_NS = "llm-opendesign-corouter";
|
|
3
5
|
export declare const PLAN_PROVIDER = "opendesign-corouter-plan";
|
|
4
6
|
export declare const PAID_PROVIDER = "opendesign-corouter-paid";
|
|
@@ -6,15 +8,21 @@ export declare const DEFAULT_BASE_URL = "https://amr-link.open-design.ai/v1";
|
|
|
6
8
|
export declare const Config: Schema<Schemastery.ObjectS<NoInfer<{
|
|
7
9
|
apiKeyEnv: Schema<string, string, "volatile-defined">;
|
|
8
10
|
baseURL: Schema<string, string, "volatile-defined">;
|
|
11
|
+
apiProtocol: Schema<"chat-completions" | "responses" | "messages", "chat-completions" | "responses" | "messages", "volatile-defined">;
|
|
12
|
+
modelSettings: Schema<NoInfer<import("@deepseek-ai/cosmokit").Dict<unknown, string>>, NoInfer<ModelSettingsMap>, "volatile-defined">;
|
|
9
13
|
useDesktopCredential: Schema<boolean, boolean, "volatile-defined">;
|
|
10
14
|
emptyTurnGuard: Schema<boolean, boolean, "volatile-defined">;
|
|
15
|
+
quotaRefreshSeconds: Schema<number, number, "volatile-defined">;
|
|
11
16
|
requestTimeoutMs: Schema<number, number, "volatile-defined">;
|
|
12
17
|
streamIdleTimeoutMs: Schema<number, number, "volatile-defined">;
|
|
13
18
|
}>>, Schemastery.ObjectT<NoInfer<{
|
|
14
19
|
apiKeyEnv: Schema<string, string, "volatile-defined">;
|
|
15
20
|
baseURL: Schema<string, string, "volatile-defined">;
|
|
21
|
+
apiProtocol: Schema<"chat-completions" | "responses" | "messages", "chat-completions" | "responses" | "messages", "volatile-defined">;
|
|
22
|
+
modelSettings: Schema<NoInfer<import("@deepseek-ai/cosmokit").Dict<unknown, string>>, NoInfer<ModelSettingsMap>, "volatile-defined">;
|
|
16
23
|
useDesktopCredential: Schema<boolean, boolean, "volatile-defined">;
|
|
17
24
|
emptyTurnGuard: Schema<boolean, boolean, "volatile-defined">;
|
|
25
|
+
quotaRefreshSeconds: Schema<number, number, "volatile-defined">;
|
|
18
26
|
requestTimeoutMs: Schema<number, number, "volatile-defined">;
|
|
19
27
|
streamIdleTimeoutMs: Schema<number, number, "volatile-defined">;
|
|
20
28
|
}>>, "plain">;
|
|
@@ -26,6 +34,9 @@ export interface RuntimeConfig {
|
|
|
26
34
|
emptyTurnGuard: boolean;
|
|
27
35
|
requestTimeoutMs: number;
|
|
28
36
|
streamIdleTimeoutMs: number;
|
|
37
|
+
apiProtocol?: ApiProtocol;
|
|
38
|
+
modelSettings?: ModelSettingsMap;
|
|
39
|
+
quotaRefreshSeconds?: number;
|
|
29
40
|
}
|
|
30
41
|
export declare function assertBaseURL(raw: string): string;
|
|
31
42
|
export declare function readConfig(config: LiveConfig): RuntimeConfig;
|
|
@@ -7,6 +7,53 @@ function record(value) {
|
|
|
7
7
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
+
// src/protocol-options.ts
|
|
11
|
+
var API_PROTOCOL_IDS = ["chat-completions", "responses", "messages"];
|
|
12
|
+
|
|
13
|
+
// src/model-settings.ts
|
|
14
|
+
function parseModelSettingsMap(value) {
|
|
15
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) throw new Error("\u6A21\u578B\u8BBE\u7F6E\u5FC5\u987B\u662F\u5BF9\u8C61");
|
|
16
|
+
const keys = Object.keys(value);
|
|
17
|
+
if (keys.length > 512) throw new Error("\u6A21\u578B\u8BBE\u7F6E\u6700\u591A\u5141\u8BB8 512 \u4E2A\u6A21\u578B");
|
|
18
|
+
const fields = /* @__PURE__ */ new Set(["enabled", "temperature", "topP", "maxTokens", "contextWindow", "reasoningEffort"]);
|
|
19
|
+
const efforts = ["none", "minimal", "low", "medium", "high", "xhigh", "ultra", "max"];
|
|
20
|
+
const out = {};
|
|
21
|
+
for (const id of keys) {
|
|
22
|
+
if (["__proto__", "constructor", "prototype"].includes(id)) throw new Error("\u6A21\u578B\u8BBE\u7F6E\u4E0D\u5141\u8BB8\u4FDD\u7559\u5B57\u6BB5\u540D");
|
|
23
|
+
if (!/^[A-Za-z0-9._:/-]{1,128}$/u.test(id)) throw new Error("\u6A21\u578B ID \u5FC5\u987B\u662F 1\u2013128 \u4F4D\u5B57\u6BCD\u3001\u6570\u5B57\u6216 . _ : / -");
|
|
24
|
+
const entry = value[id];
|
|
25
|
+
if (entry === null || typeof entry !== "object" || Array.isArray(entry)) throw new Error("\u6BCF\u4E2A\u6A21\u578B\u7684\u8BBE\u7F6E\u5FC5\u987B\u662F\u5BF9\u8C61");
|
|
26
|
+
const settings = entry;
|
|
27
|
+
for (const field of Object.keys(settings)) {
|
|
28
|
+
if (!fields.has(field)) throw new Error("\u6A21\u578B\u8BBE\u7F6E\u542B\u6709\u4E0D\u652F\u6301\u7684\u5B57\u6BB5");
|
|
29
|
+
}
|
|
30
|
+
const parsed = {};
|
|
31
|
+
if (settings.enabled !== void 0) {
|
|
32
|
+
if (typeof settings.enabled !== "boolean") throw new Error("\u6A21\u578B\u8BBE\u7F6E\u7684 enabled \u5FC5\u987B\u662F\u5E03\u5C14\u503C");
|
|
33
|
+
parsed.enabled = settings.enabled;
|
|
34
|
+
}
|
|
35
|
+
for (const [field, max] of [["temperature", 2], ["topP", 1]]) {
|
|
36
|
+
const item = settings[field];
|
|
37
|
+
if (item === void 0) continue;
|
|
38
|
+
if (typeof item !== "number" || !Number.isFinite(item) || item < 0 || item > max) throw new Error(`\u6A21\u578B\u8BBE\u7F6E\u7684 ${field} \u5FC5\u987B\u662F 0 \u5230 ${max} \u4E4B\u95F4\u7684\u6709\u9650\u6570\u5B57`);
|
|
39
|
+
parsed[field] = item;
|
|
40
|
+
}
|
|
41
|
+
for (const [field, max] of [["maxTokens", 1e7], ["contextWindow", 1e8]]) {
|
|
42
|
+
const item = settings[field];
|
|
43
|
+
if (item === void 0) continue;
|
|
44
|
+
if (typeof item !== "number" || !Number.isSafeInteger(item) || item < 1 || item > max) throw new Error(`\u6A21\u578B\u8BBE\u7F6E\u7684 ${field} \u5FC5\u987B\u662F 1 \u5230 ${max} \u4E4B\u95F4\u7684\u6574\u6570`);
|
|
45
|
+
parsed[field] = item;
|
|
46
|
+
}
|
|
47
|
+
if (settings.reasoningEffort !== void 0) {
|
|
48
|
+
if (typeof settings.reasoningEffort !== "string" || !efforts.includes(settings.reasoningEffort)) throw new Error("\u6A21\u578B\u8BBE\u7F6E\u7684 reasoningEffort \u4E0D\u5728\u5141\u8BB8\u7684\u53D6\u503C\u5185");
|
|
49
|
+
parsed.reasoningEffort = settings.reasoningEffort;
|
|
50
|
+
}
|
|
51
|
+
if (parsed.maxTokens !== void 0 && parsed.contextWindow !== void 0 && parsed.maxTokens >= parsed.contextWindow) throw new Error("\u6A21\u578B\u8BBE\u7F6E\u7684 maxTokens \u5FC5\u987B\u5C0F\u4E8E contextWindow");
|
|
52
|
+
out[id] = parsed;
|
|
53
|
+
}
|
|
54
|
+
return out;
|
|
55
|
+
}
|
|
56
|
+
|
|
10
57
|
// src/remote.ts
|
|
11
58
|
var MAX_REVISION = 256;
|
|
12
59
|
var MAX_JOB_ID = 128;
|
|
@@ -20,7 +67,7 @@ var MAX_WINDOWS = 64;
|
|
|
20
67
|
var MAX_API_KEY = 16384;
|
|
21
68
|
var HTTP_ASCII = /^[\x21-\x7e]+$/u;
|
|
22
69
|
var ENV_REF = /^[A-Za-z_][A-Za-z0-9_]*$/u;
|
|
23
|
-
var MODEL_ID = /^[A-Za-z0-9._
|
|
70
|
+
var MODEL_ID = /^[A-Za-z0-9._:/-]{1,128}$/u;
|
|
24
71
|
var LOGIN_PHASES = ["idle", "launching", "waiting", "verifying", "success", "cancelled", "error"];
|
|
25
72
|
var QUOTA_STATES = ["ok", "partial", "need-login", "error"];
|
|
26
73
|
var SESSION_SOURCES = ["desktop", "login", "environment"];
|
|
@@ -46,6 +93,15 @@ function amount(value, label, negative = false) {
|
|
|
46
93
|
if (typeof value !== "number" || !Number.isFinite(value) || !negative && value < 0) throw new Error(`${label} \u5FC5\u987B\u662F${negative ? "" : "\u975E\u8D1F"}\u6709\u9650\u6570\u5B57`);
|
|
47
94
|
return value;
|
|
48
95
|
}
|
|
96
|
+
function positiveInteger(value, label, max) {
|
|
97
|
+
const result = count(value, label);
|
|
98
|
+
if (result === 0 || result > max) throw new Error(`${label} \u8D85\u51FA\u8303\u56F4`);
|
|
99
|
+
return result;
|
|
100
|
+
}
|
|
101
|
+
function parseEfforts(value) {
|
|
102
|
+
if (!Array.isArray(value) || value.length > 16) throw new Error("\u6A21\u578B\u601D\u8003\u6863\u4F4D\u683C\u5F0F\u65E0\u6548");
|
|
103
|
+
return value.map((item) => text(item, "\u601D\u8003\u6863\u4F4D", 32));
|
|
104
|
+
}
|
|
49
105
|
function member(value, allowed, label) {
|
|
50
106
|
const hit = allowed.find((candidate) => candidate === value);
|
|
51
107
|
if (hit === void 0) throw new Error(`${label} \u4E0D\u5728\u5141\u8BB8\u7684\u53D6\u503C\u5185`);
|
|
@@ -63,7 +119,9 @@ function parseQuotaWindow(value) {
|
|
|
63
119
|
limit,
|
|
64
120
|
...value.remaining === void 0 ? {} : { remaining: amount(value.remaining, "\u5269\u4F59\u989D\u5EA6") },
|
|
65
121
|
percent: Math.min(100, Math.max(0, amount(value.percent, "\u5DF2\u7528\u767E\u5206\u6BD4"))),
|
|
66
|
-
...value.resetsAt === void 0 ? {} : { resetsAt: isoTime(value.resetsAt, "\u989D\u5EA6\u91CD\u7F6E\u65F6\u95F4") }
|
|
122
|
+
...value.resetsAt === void 0 ? {} : { resetsAt: isoTime(value.resetsAt, "\u989D\u5EA6\u91CD\u7F6E\u65F6\u95F4") },
|
|
123
|
+
...value.windowStart === void 0 ? {} : { windowStart: isoTime(value.windowStart, "\u989D\u5EA6\u7A97\u53E3\u5F00\u59CB\u65F6\u95F4") },
|
|
124
|
+
...value.resetMode === void 0 ? {} : { resetMode: text(value.resetMode, "\u989D\u5EA6\u5237\u65B0\u65B9\u5F0F", 128) }
|
|
67
125
|
};
|
|
68
126
|
}
|
|
69
127
|
function parseQuotaSnapshot(value) {
|
|
@@ -76,6 +134,12 @@ function parseQuotaSnapshot(value) {
|
|
|
76
134
|
state: member(value.state, QUOTA_STATES, "\u989D\u5EA6\u72B6\u6001"),
|
|
77
135
|
...value.source === void 0 ? {} : { source: member(value.source, SESSION_SOURCES, "\u989D\u5EA6\u6765\u6E90") },
|
|
78
136
|
updatedAt: isoTime(value.updatedAt, "\u989D\u5EA6\u66F4\u65B0\u65F6\u95F4"),
|
|
137
|
+
...value.subscriptionPeriodStart === void 0 ? {} : { subscriptionPeriodStart: isoTime(value.subscriptionPeriodStart, "\u8BA2\u9605\u5468\u671F\u5F00\u59CB\u65F6\u95F4") },
|
|
138
|
+
...value.subscriptionPeriodEnd === void 0 ? {} : { subscriptionPeriodEnd: isoTime(value.subscriptionPeriodEnd, "\u8BA2\u9605\u5468\u671F\u7ED3\u675F\u65F6\u95F4") },
|
|
139
|
+
...value.nextRefreshAt === void 0 ? {} : { nextRefreshAt: isoTime(value.nextRefreshAt, "\u4E0B\u6B21\u81EA\u52A8\u5237\u65B0\u65F6\u95F4") },
|
|
140
|
+
...value.stale === void 0 ? {} : { stale: flag(value.stale, "\u5386\u53F2\u989D\u5EA6\u8BFB\u6570") },
|
|
141
|
+
...value.refreshFailures === void 0 ? {} : { refreshFailures: count(value.refreshFailures, "\u8FDE\u7EED\u5237\u65B0\u5931\u8D25\u6B21\u6570") },
|
|
142
|
+
...value.autoRefreshPaused === void 0 ? {} : { autoRefreshPaused: flag(value.autoRefreshPaused, "\u81EA\u52A8\u5237\u65B0\u6682\u505C\u72B6\u6001") },
|
|
79
143
|
...value.tier === void 0 ? {} : { tier: text(value.tier, "\u5957\u9910\u540D", MAX_TIER) },
|
|
80
144
|
...value.eligible === void 0 ? {} : { eligible: flag(value.eligible, "\u5957\u9910\u8D44\u683C") },
|
|
81
145
|
windows: windows.map(parseQuotaWindow),
|
|
@@ -106,7 +170,11 @@ function parseStatusModel(value) {
|
|
|
106
170
|
return {
|
|
107
171
|
id,
|
|
108
172
|
name: text(value.name, "\u6A21\u578B\u540D", 128),
|
|
109
|
-
group: member(value.group, MODEL_GROUPS, "\u6A21\u578B\u5206\u7EC4")
|
|
173
|
+
group: member(value.group, MODEL_GROUPS, "\u6A21\u578B\u5206\u7EC4"),
|
|
174
|
+
...value.enabled === void 0 ? {} : { enabled: flag(value.enabled, "\u6A21\u578B\u542F\u7528\u72B6\u6001") },
|
|
175
|
+
...value.contextWindow === void 0 ? {} : { contextWindow: positiveInteger(value.contextWindow, "\u4E0A\u4E0B\u6587\u9884\u7B97", 1e8) },
|
|
176
|
+
...value.maxOutputTokens === void 0 ? {} : { maxOutputTokens: positiveInteger(value.maxOutputTokens, "\u6700\u5927\u8F93\u51FA", 1e7) },
|
|
177
|
+
...value.reasoningEfforts === void 0 ? {} : { reasoningEfforts: parseEfforts(value.reasoningEfforts) }
|
|
110
178
|
};
|
|
111
179
|
}
|
|
112
180
|
function parseStatusConfig(value) {
|
|
@@ -117,7 +185,12 @@ function parseStatusConfig(value) {
|
|
|
117
185
|
emptyTurnGuard: flag(value.emptyTurnGuard, "\u7A7A\u8F6E\u4FDD\u62A4\u5F00\u5173"),
|
|
118
186
|
useDesktopCredential: flag(value.useDesktopCredential, "\u684C\u9762\u767B\u5F55\u6001\u5F00\u5173"),
|
|
119
187
|
baseURL: text(value.baseURL, "\u63A8\u7406\u5730\u5740", MAX_BASE_URL),
|
|
120
|
-
apiKeyEnv
|
|
188
|
+
apiKeyEnv,
|
|
189
|
+
...value.apiProtocol === void 0 ? {} : { apiProtocol: member(value.apiProtocol, API_PROTOCOL_IDS, "\u63A8\u7406\u534F\u8BAE") },
|
|
190
|
+
...value.modelSettings === void 0 ? {} : { modelSettings: parseModelSettingsMap(value.modelSettings) },
|
|
191
|
+
...value.requestTimeoutMs === void 0 ? {} : { requestTimeoutMs: positiveInteger(value.requestTimeoutMs, "\u8BF7\u6C42\u8D85\u65F6", 36e5) },
|
|
192
|
+
...value.streamIdleTimeoutMs === void 0 ? {} : { streamIdleTimeoutMs: positiveInteger(value.streamIdleTimeoutMs, "\u6D41\u7A7A\u95F2\u8D85\u65F6", 18e5) },
|
|
193
|
+
...value.quotaRefreshSeconds === void 0 ? {} : { quotaRefreshSeconds: positiveInteger(value.quotaRefreshSeconds, "\u81EA\u52A8\u5237\u65B0\u95F4\u9694", 3600) }
|
|
121
194
|
};
|
|
122
195
|
}
|
|
123
196
|
function parseStatus(value) {
|
|
@@ -138,7 +211,10 @@ function parseStatus(value) {
|
|
|
138
211
|
login: parseLoginState(value.login),
|
|
139
212
|
config: parseStatusConfig(value.config),
|
|
140
213
|
guardedTurns: count(value.guardedTurns, "\u5DF2\u62E6\u622A\u7A7A\u8F6E\u6570"),
|
|
141
|
-
models: parsed
|
|
214
|
+
models: parsed,
|
|
215
|
+
...value.modelsSource === void 0 ? {} : { modelsSource: member(value.modelsSource, ["builtin", "openai"], "\u6A21\u578B\u76EE\u5F55\u6765\u6E90") },
|
|
216
|
+
...value.modelsUpdatedAt === void 0 ? {} : { modelsUpdatedAt: isoTime(value.modelsUpdatedAt, "\u6A21\u578B\u66F4\u65B0\u65F6\u95F4") },
|
|
217
|
+
...value.modelsError === void 0 ? {} : { modelsError: text(value.modelsError, "\u6A21\u578B\u66F4\u65B0\u63D0\u793A", MAX_MESSAGE) }
|
|
142
218
|
};
|
|
143
219
|
}
|
|
144
220
|
function parseStartLoginRequest(value) {
|
|
@@ -167,7 +243,9 @@ var CancelLoginRequestCodec = { mode: "strict", typeSymbol: "dsh-opendesign-coro
|
|
|
167
243
|
var SaveApiKeyRequestCodec = { mode: "strict", typeSymbol: "dsh-opendesign-corouter#SaveApiKeyRequest", create: () => z.unknown().transform((value) => parseSaveApiKeyRequest(value)) };
|
|
168
244
|
var TYPERT_REMOTE = createTypertRemoteInfo({ package: "dsh-opendesign-corouter", methods: {
|
|
169
245
|
"openDesignCoRouter/status": { service: "openDesignCoRouter", invocation: { kind: "direct" }, parameters: [], result: StatusCodec },
|
|
246
|
+
"openDesignCoRouter/refreshModels": { service: "openDesignCoRouter", invocation: { kind: "direct" }, parameters: [], result: StatusCodec },
|
|
170
247
|
"openDesignCoRouter/refreshQuota": { service: "openDesignCoRouter", invocation: { kind: "direct" }, parameters: [], result: QuotaSnapshotCodec },
|
|
248
|
+
"openDesignCoRouter/refreshQuotaNow": { service: "openDesignCoRouter", invocation: { kind: "direct" }, parameters: [], result: QuotaSnapshotCodec },
|
|
171
249
|
"openDesignCoRouter/startLogin": { service: "openDesignCoRouter", invocation: { kind: "direct" }, parameters: [{ name: "input", source: "json", codec: StartLoginRequestCodec, strictCodec: StartLoginRequestCodec }], result: LoginStateCodec },
|
|
172
250
|
"openDesignCoRouter/loginStatus": { service: "openDesignCoRouter", invocation: { kind: "direct" }, parameters: [], result: LoginStateCodec },
|
|
173
251
|
"openDesignCoRouter/cancelLogin": { service: "openDesignCoRouter", invocation: { kind: "direct" }, parameters: [{ name: "input", source: "json", codec: CancelLoginRequestCodec, strictCodec: CancelLoginRequestCodec }], result: LoginStateCodec },
|
|
@@ -2,7 +2,9 @@ import type { RemoteResult } from '@deepseek-ai/dsh-typert-protocol';
|
|
|
2
2
|
import type { Status, QuotaSnapshot, LoginState, StartLoginRequest, CancelLoginRequest, SaveApiKeyRequest } from '../remote.js';
|
|
3
3
|
export type CoRouterRemote = {
|
|
4
4
|
status: () => Promise<RemoteResult<Status>>;
|
|
5
|
+
refreshModels: () => Promise<RemoteResult<Status>>;
|
|
5
6
|
refreshQuota: () => Promise<RemoteResult<QuotaSnapshot>>;
|
|
7
|
+
refreshQuotaNow: () => Promise<RemoteResult<QuotaSnapshot>>;
|
|
6
8
|
startLogin: (input: StartLoginRequest) => Promise<RemoteResult<LoginState>>;
|
|
7
9
|
loginStatus: () => Promise<RemoteResult<LoginState>>;
|
|
8
10
|
cancelLogin: (input: CancelLoginRequest) => Promise<RemoteResult<LoginState>>;
|
|
@@ -7,6 +7,53 @@ function record(value) {
|
|
|
7
7
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
+
// src/protocol-options.ts
|
|
11
|
+
var API_PROTOCOL_IDS = ["chat-completions", "responses", "messages"];
|
|
12
|
+
|
|
13
|
+
// src/model-settings.ts
|
|
14
|
+
function parseModelSettingsMap(value) {
|
|
15
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) throw new Error("\u6A21\u578B\u8BBE\u7F6E\u5FC5\u987B\u662F\u5BF9\u8C61");
|
|
16
|
+
const keys = Object.keys(value);
|
|
17
|
+
if (keys.length > 512) throw new Error("\u6A21\u578B\u8BBE\u7F6E\u6700\u591A\u5141\u8BB8 512 \u4E2A\u6A21\u578B");
|
|
18
|
+
const fields = /* @__PURE__ */ new Set(["enabled", "temperature", "topP", "maxTokens", "contextWindow", "reasoningEffort"]);
|
|
19
|
+
const efforts = ["none", "minimal", "low", "medium", "high", "xhigh", "ultra", "max"];
|
|
20
|
+
const out = {};
|
|
21
|
+
for (const id of keys) {
|
|
22
|
+
if (["__proto__", "constructor", "prototype"].includes(id)) throw new Error("\u6A21\u578B\u8BBE\u7F6E\u4E0D\u5141\u8BB8\u4FDD\u7559\u5B57\u6BB5\u540D");
|
|
23
|
+
if (!/^[A-Za-z0-9._:/-]{1,128}$/u.test(id)) throw new Error("\u6A21\u578B ID \u5FC5\u987B\u662F 1\u2013128 \u4F4D\u5B57\u6BCD\u3001\u6570\u5B57\u6216 . _ : / -");
|
|
24
|
+
const entry = value[id];
|
|
25
|
+
if (entry === null || typeof entry !== "object" || Array.isArray(entry)) throw new Error("\u6BCF\u4E2A\u6A21\u578B\u7684\u8BBE\u7F6E\u5FC5\u987B\u662F\u5BF9\u8C61");
|
|
26
|
+
const settings = entry;
|
|
27
|
+
for (const field of Object.keys(settings)) {
|
|
28
|
+
if (!fields.has(field)) throw new Error("\u6A21\u578B\u8BBE\u7F6E\u542B\u6709\u4E0D\u652F\u6301\u7684\u5B57\u6BB5");
|
|
29
|
+
}
|
|
30
|
+
const parsed = {};
|
|
31
|
+
if (settings.enabled !== void 0) {
|
|
32
|
+
if (typeof settings.enabled !== "boolean") throw new Error("\u6A21\u578B\u8BBE\u7F6E\u7684 enabled \u5FC5\u987B\u662F\u5E03\u5C14\u503C");
|
|
33
|
+
parsed.enabled = settings.enabled;
|
|
34
|
+
}
|
|
35
|
+
for (const [field, max] of [["temperature", 2], ["topP", 1]]) {
|
|
36
|
+
const item = settings[field];
|
|
37
|
+
if (item === void 0) continue;
|
|
38
|
+
if (typeof item !== "number" || !Number.isFinite(item) || item < 0 || item > max) throw new Error(`\u6A21\u578B\u8BBE\u7F6E\u7684 ${field} \u5FC5\u987B\u662F 0 \u5230 ${max} \u4E4B\u95F4\u7684\u6709\u9650\u6570\u5B57`);
|
|
39
|
+
parsed[field] = item;
|
|
40
|
+
}
|
|
41
|
+
for (const [field, max] of [["maxTokens", 1e7], ["contextWindow", 1e8]]) {
|
|
42
|
+
const item = settings[field];
|
|
43
|
+
if (item === void 0) continue;
|
|
44
|
+
if (typeof item !== "number" || !Number.isSafeInteger(item) || item < 1 || item > max) throw new Error(`\u6A21\u578B\u8BBE\u7F6E\u7684 ${field} \u5FC5\u987B\u662F 1 \u5230 ${max} \u4E4B\u95F4\u7684\u6574\u6570`);
|
|
45
|
+
parsed[field] = item;
|
|
46
|
+
}
|
|
47
|
+
if (settings.reasoningEffort !== void 0) {
|
|
48
|
+
if (typeof settings.reasoningEffort !== "string" || !efforts.includes(settings.reasoningEffort)) throw new Error("\u6A21\u578B\u8BBE\u7F6E\u7684 reasoningEffort \u4E0D\u5728\u5141\u8BB8\u7684\u53D6\u503C\u5185");
|
|
49
|
+
parsed.reasoningEffort = settings.reasoningEffort;
|
|
50
|
+
}
|
|
51
|
+
if (parsed.maxTokens !== void 0 && parsed.contextWindow !== void 0 && parsed.maxTokens >= parsed.contextWindow) throw new Error("\u6A21\u578B\u8BBE\u7F6E\u7684 maxTokens \u5FC5\u987B\u5C0F\u4E8E contextWindow");
|
|
52
|
+
out[id] = parsed;
|
|
53
|
+
}
|
|
54
|
+
return out;
|
|
55
|
+
}
|
|
56
|
+
|
|
10
57
|
// src/remote.ts
|
|
11
58
|
var MAX_REVISION = 256;
|
|
12
59
|
var MAX_JOB_ID = 128;
|
|
@@ -20,7 +67,7 @@ var MAX_WINDOWS = 64;
|
|
|
20
67
|
var MAX_API_KEY = 16384;
|
|
21
68
|
var HTTP_ASCII = /^[\x21-\x7e]+$/u;
|
|
22
69
|
var ENV_REF = /^[A-Za-z_][A-Za-z0-9_]*$/u;
|
|
23
|
-
var MODEL_ID = /^[A-Za-z0-9._
|
|
70
|
+
var MODEL_ID = /^[A-Za-z0-9._:/-]{1,128}$/u;
|
|
24
71
|
var LOGIN_PHASES = ["idle", "launching", "waiting", "verifying", "success", "cancelled", "error"];
|
|
25
72
|
var QUOTA_STATES = ["ok", "partial", "need-login", "error"];
|
|
26
73
|
var SESSION_SOURCES = ["desktop", "login", "environment"];
|
|
@@ -46,6 +93,15 @@ function amount(value, label, negative = false) {
|
|
|
46
93
|
if (typeof value !== "number" || !Number.isFinite(value) || !negative && value < 0) throw new Error(`${label} \u5FC5\u987B\u662F${negative ? "" : "\u975E\u8D1F"}\u6709\u9650\u6570\u5B57`);
|
|
47
94
|
return value;
|
|
48
95
|
}
|
|
96
|
+
function positiveInteger(value, label, max) {
|
|
97
|
+
const result = count(value, label);
|
|
98
|
+
if (result === 0 || result > max) throw new Error(`${label} \u8D85\u51FA\u8303\u56F4`);
|
|
99
|
+
return result;
|
|
100
|
+
}
|
|
101
|
+
function parseEfforts(value) {
|
|
102
|
+
if (!Array.isArray(value) || value.length > 16) throw new Error("\u6A21\u578B\u601D\u8003\u6863\u4F4D\u683C\u5F0F\u65E0\u6548");
|
|
103
|
+
return value.map((item) => text(item, "\u601D\u8003\u6863\u4F4D", 32));
|
|
104
|
+
}
|
|
49
105
|
function member(value, allowed, label) {
|
|
50
106
|
const hit = allowed.find((candidate) => candidate === value);
|
|
51
107
|
if (hit === void 0) throw new Error(`${label} \u4E0D\u5728\u5141\u8BB8\u7684\u53D6\u503C\u5185`);
|
|
@@ -63,7 +119,9 @@ function parseQuotaWindow(value) {
|
|
|
63
119
|
limit,
|
|
64
120
|
...value.remaining === void 0 ? {} : { remaining: amount(value.remaining, "\u5269\u4F59\u989D\u5EA6") },
|
|
65
121
|
percent: Math.min(100, Math.max(0, amount(value.percent, "\u5DF2\u7528\u767E\u5206\u6BD4"))),
|
|
66
|
-
...value.resetsAt === void 0 ? {} : { resetsAt: isoTime(value.resetsAt, "\u989D\u5EA6\u91CD\u7F6E\u65F6\u95F4") }
|
|
122
|
+
...value.resetsAt === void 0 ? {} : { resetsAt: isoTime(value.resetsAt, "\u989D\u5EA6\u91CD\u7F6E\u65F6\u95F4") },
|
|
123
|
+
...value.windowStart === void 0 ? {} : { windowStart: isoTime(value.windowStart, "\u989D\u5EA6\u7A97\u53E3\u5F00\u59CB\u65F6\u95F4") },
|
|
124
|
+
...value.resetMode === void 0 ? {} : { resetMode: text(value.resetMode, "\u989D\u5EA6\u5237\u65B0\u65B9\u5F0F", 128) }
|
|
67
125
|
};
|
|
68
126
|
}
|
|
69
127
|
function parseQuotaSnapshot(value) {
|
|
@@ -76,6 +134,12 @@ function parseQuotaSnapshot(value) {
|
|
|
76
134
|
state: member(value.state, QUOTA_STATES, "\u989D\u5EA6\u72B6\u6001"),
|
|
77
135
|
...value.source === void 0 ? {} : { source: member(value.source, SESSION_SOURCES, "\u989D\u5EA6\u6765\u6E90") },
|
|
78
136
|
updatedAt: isoTime(value.updatedAt, "\u989D\u5EA6\u66F4\u65B0\u65F6\u95F4"),
|
|
137
|
+
...value.subscriptionPeriodStart === void 0 ? {} : { subscriptionPeriodStart: isoTime(value.subscriptionPeriodStart, "\u8BA2\u9605\u5468\u671F\u5F00\u59CB\u65F6\u95F4") },
|
|
138
|
+
...value.subscriptionPeriodEnd === void 0 ? {} : { subscriptionPeriodEnd: isoTime(value.subscriptionPeriodEnd, "\u8BA2\u9605\u5468\u671F\u7ED3\u675F\u65F6\u95F4") },
|
|
139
|
+
...value.nextRefreshAt === void 0 ? {} : { nextRefreshAt: isoTime(value.nextRefreshAt, "\u4E0B\u6B21\u81EA\u52A8\u5237\u65B0\u65F6\u95F4") },
|
|
140
|
+
...value.stale === void 0 ? {} : { stale: flag(value.stale, "\u5386\u53F2\u989D\u5EA6\u8BFB\u6570") },
|
|
141
|
+
...value.refreshFailures === void 0 ? {} : { refreshFailures: count(value.refreshFailures, "\u8FDE\u7EED\u5237\u65B0\u5931\u8D25\u6B21\u6570") },
|
|
142
|
+
...value.autoRefreshPaused === void 0 ? {} : { autoRefreshPaused: flag(value.autoRefreshPaused, "\u81EA\u52A8\u5237\u65B0\u6682\u505C\u72B6\u6001") },
|
|
79
143
|
...value.tier === void 0 ? {} : { tier: text(value.tier, "\u5957\u9910\u540D", MAX_TIER) },
|
|
80
144
|
...value.eligible === void 0 ? {} : { eligible: flag(value.eligible, "\u5957\u9910\u8D44\u683C") },
|
|
81
145
|
windows: windows.map(parseQuotaWindow),
|
|
@@ -106,7 +170,11 @@ function parseStatusModel(value) {
|
|
|
106
170
|
return {
|
|
107
171
|
id,
|
|
108
172
|
name: text(value.name, "\u6A21\u578B\u540D", 128),
|
|
109
|
-
group: member(value.group, MODEL_GROUPS, "\u6A21\u578B\u5206\u7EC4")
|
|
173
|
+
group: member(value.group, MODEL_GROUPS, "\u6A21\u578B\u5206\u7EC4"),
|
|
174
|
+
...value.enabled === void 0 ? {} : { enabled: flag(value.enabled, "\u6A21\u578B\u542F\u7528\u72B6\u6001") },
|
|
175
|
+
...value.contextWindow === void 0 ? {} : { contextWindow: positiveInteger(value.contextWindow, "\u4E0A\u4E0B\u6587\u9884\u7B97", 1e8) },
|
|
176
|
+
...value.maxOutputTokens === void 0 ? {} : { maxOutputTokens: positiveInteger(value.maxOutputTokens, "\u6700\u5927\u8F93\u51FA", 1e7) },
|
|
177
|
+
...value.reasoningEfforts === void 0 ? {} : { reasoningEfforts: parseEfforts(value.reasoningEfforts) }
|
|
110
178
|
};
|
|
111
179
|
}
|
|
112
180
|
function parseStatusConfig(value) {
|
|
@@ -117,7 +185,12 @@ function parseStatusConfig(value) {
|
|
|
117
185
|
emptyTurnGuard: flag(value.emptyTurnGuard, "\u7A7A\u8F6E\u4FDD\u62A4\u5F00\u5173"),
|
|
118
186
|
useDesktopCredential: flag(value.useDesktopCredential, "\u684C\u9762\u767B\u5F55\u6001\u5F00\u5173"),
|
|
119
187
|
baseURL: text(value.baseURL, "\u63A8\u7406\u5730\u5740", MAX_BASE_URL),
|
|
120
|
-
apiKeyEnv
|
|
188
|
+
apiKeyEnv,
|
|
189
|
+
...value.apiProtocol === void 0 ? {} : { apiProtocol: member(value.apiProtocol, API_PROTOCOL_IDS, "\u63A8\u7406\u534F\u8BAE") },
|
|
190
|
+
...value.modelSettings === void 0 ? {} : { modelSettings: parseModelSettingsMap(value.modelSettings) },
|
|
191
|
+
...value.requestTimeoutMs === void 0 ? {} : { requestTimeoutMs: positiveInteger(value.requestTimeoutMs, "\u8BF7\u6C42\u8D85\u65F6", 36e5) },
|
|
192
|
+
...value.streamIdleTimeoutMs === void 0 ? {} : { streamIdleTimeoutMs: positiveInteger(value.streamIdleTimeoutMs, "\u6D41\u7A7A\u95F2\u8D85\u65F6", 18e5) },
|
|
193
|
+
...value.quotaRefreshSeconds === void 0 ? {} : { quotaRefreshSeconds: positiveInteger(value.quotaRefreshSeconds, "\u81EA\u52A8\u5237\u65B0\u95F4\u9694", 3600) }
|
|
121
194
|
};
|
|
122
195
|
}
|
|
123
196
|
function parseStatus(value) {
|
|
@@ -138,7 +211,10 @@ function parseStatus(value) {
|
|
|
138
211
|
login: parseLoginState(value.login),
|
|
139
212
|
config: parseStatusConfig(value.config),
|
|
140
213
|
guardedTurns: count(value.guardedTurns, "\u5DF2\u62E6\u622A\u7A7A\u8F6E\u6570"),
|
|
141
|
-
models: parsed
|
|
214
|
+
models: parsed,
|
|
215
|
+
...value.modelsSource === void 0 ? {} : { modelsSource: member(value.modelsSource, ["builtin", "openai"], "\u6A21\u578B\u76EE\u5F55\u6765\u6E90") },
|
|
216
|
+
...value.modelsUpdatedAt === void 0 ? {} : { modelsUpdatedAt: isoTime(value.modelsUpdatedAt, "\u6A21\u578B\u66F4\u65B0\u65F6\u95F4") },
|
|
217
|
+
...value.modelsError === void 0 ? {} : { modelsError: text(value.modelsError, "\u6A21\u578B\u66F4\u65B0\u63D0\u793A", MAX_MESSAGE) }
|
|
142
218
|
};
|
|
143
219
|
}
|
|
144
220
|
function parseStartLoginRequest(value) {
|
|
@@ -167,7 +243,9 @@ var CancelLoginRequestCodec = { mode: "strict", typeSymbol: "dsh-opendesign-coro
|
|
|
167
243
|
var SaveApiKeyRequestCodec = { mode: "strict", typeSymbol: "dsh-opendesign-corouter#SaveApiKeyRequest", create: () => z.unknown().transform((value) => parseSaveApiKeyRequest(value)) };
|
|
168
244
|
var TYPERT_REMOTE = createTypertRemoteInfo({ package: "dsh-opendesign-corouter", methods: {
|
|
169
245
|
"openDesignCoRouter/status": { service: "openDesignCoRouter", invocation: { kind: "direct" }, parameters: [], result: StatusCodec },
|
|
246
|
+
"openDesignCoRouter/refreshModels": { service: "openDesignCoRouter", invocation: { kind: "direct" }, parameters: [], result: StatusCodec },
|
|
170
247
|
"openDesignCoRouter/refreshQuota": { service: "openDesignCoRouter", invocation: { kind: "direct" }, parameters: [], result: QuotaSnapshotCodec },
|
|
248
|
+
"openDesignCoRouter/refreshQuotaNow": { service: "openDesignCoRouter", invocation: { kind: "direct" }, parameters: [], result: QuotaSnapshotCodec },
|
|
171
249
|
"openDesignCoRouter/startLogin": { service: "openDesignCoRouter", invocation: { kind: "direct" }, parameters: [{ name: "input", source: "json", codec: StartLoginRequestCodec, strictCodec: StartLoginRequestCodec }], result: LoginStateCodec },
|
|
172
250
|
"openDesignCoRouter/loginStatus": { service: "openDesignCoRouter", invocation: { kind: "direct" }, parameters: [], result: LoginStateCodec },
|
|
173
251
|
"openDesignCoRouter/cancelLogin": { service: "openDesignCoRouter", invocation: { kind: "direct" }, parameters: [{ name: "input", source: "json", codec: CancelLoginRequestCodec, strictCodec: CancelLoginRequestCodec }], result: LoginStateCodec },
|
package/lib/index.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import type { Context } from '@deepseek-ai/cordis';
|
|
2
2
|
import { TypertRemoteService } from '@deepseek-ai/dsh-typert-protocol';
|
|
3
|
+
import { fetchModelCatalog } from './model-discovery.js';
|
|
4
|
+
import type { CatalogModel } from './catalog.js';
|
|
3
5
|
import { readConfig, type LiveConfig } from './config.js';
|
|
4
6
|
import { resolveSession } from './auth.js';
|
|
5
7
|
import { readQuota, type QuotaSnapshot } from './quota.js';
|
|
@@ -14,6 +16,8 @@ export interface HostDependencies {
|
|
|
14
16
|
resolveSession: typeof resolveSession;
|
|
15
17
|
readQuota: typeof readQuota;
|
|
16
18
|
readDesktopQuota: typeof readDesktopQuota;
|
|
19
|
+
fetchModels?: typeof fetchModelCatalog;
|
|
20
|
+
modelsChanged?: () => void;
|
|
17
21
|
}
|
|
18
22
|
export declare class OpenDesignCoRouterService extends TypertRemoteService {
|
|
19
23
|
readonly dependencies: HostDependencies;
|
|
@@ -25,10 +29,19 @@ export declare class OpenDesignCoRouterService extends TypertRemoteService {
|
|
|
25
29
|
private _quota;
|
|
26
30
|
private _quotaAt;
|
|
27
31
|
private _quotaConfig;
|
|
32
|
+
private _quotaIdentity;
|
|
28
33
|
private _quotaEpoch;
|
|
29
34
|
private _quotaPending;
|
|
30
35
|
private _quotaController;
|
|
31
36
|
guardedTurns: number;
|
|
37
|
+
private _models;
|
|
38
|
+
private _modelsUpdatedAt;
|
|
39
|
+
private _modelsError;
|
|
40
|
+
private _modelsFingerprint;
|
|
41
|
+
private _modelsEpoch;
|
|
42
|
+
private _modelsPending;
|
|
43
|
+
private _modelsController;
|
|
44
|
+
modelCatalog(): readonly CatalogModel[];
|
|
32
45
|
constructor(ctx: Context, config: () => ReturnType<typeof readConfig>, dependencies?: HostDependencies);
|
|
33
46
|
private _credentials;
|
|
34
47
|
resolveApiKey(ref: string): Promise<string | undefined>;
|
|
@@ -37,7 +50,10 @@ export declare class OpenDesignCoRouterService extends TypertRemoteService {
|
|
|
37
50
|
private _expect;
|
|
38
51
|
private _invalidateQuota;
|
|
39
52
|
status(): Promise<Status>;
|
|
53
|
+
refreshModels(): Promise<Status>;
|
|
40
54
|
refreshQuota(): Promise<QuotaSnapshot>;
|
|
55
|
+
refreshQuotaNow(): Promise<QuotaSnapshot>;
|
|
56
|
+
private _refreshQuota;
|
|
41
57
|
private _readQuota;
|
|
42
58
|
startLogin(input: StartLoginRequest): Promise<LoginState>;
|
|
43
59
|
loginStatus(): LoginState;
|