dsh-llm-ustc 0.1.0

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.
Files changed (47) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +69 -0
  3. package/cordis.patch.yml +4 -0
  4. package/lib/adapter.js +211 -0
  5. package/lib/adapter.js.map +1 -0
  6. package/lib/client.js +506 -0
  7. package/lib/config.js +17 -0
  8. package/lib/config.js.map +1 -0
  9. package/lib/constants.js +11 -0
  10. package/lib/constants.js.map +1 -0
  11. package/lib/helper.js +302 -0
  12. package/lib/helper.js.map +1 -0
  13. package/lib/index.js +43 -0
  14. package/lib/index.js.map +1 -0
  15. package/lib/model-catalog.js +59 -0
  16. package/lib/model-catalog.js.map +1 -0
  17. package/lib/native.js +47 -0
  18. package/lib/native.js.map +1 -0
  19. package/lib/state.js +97 -0
  20. package/lib/state.js.map +1 -0
  21. package/lib/types/adapter.d.ts +24 -0
  22. package/lib/types/adapter.d.ts.map +1 -0
  23. package/lib/types/client/index.d.ts +112 -0
  24. package/lib/types/client/index.d.ts.map +1 -0
  25. package/lib/types/config.d.ts +12 -0
  26. package/lib/types/config.d.ts.map +1 -0
  27. package/lib/types/constants.d.ts +11 -0
  28. package/lib/types/constants.d.ts.map +1 -0
  29. package/lib/types/helper.d.ts +51 -0
  30. package/lib/types/helper.d.ts.map +1 -0
  31. package/lib/types/index.d.ts +7 -0
  32. package/lib/types/index.d.ts.map +1 -0
  33. package/lib/types/model-catalog.d.ts +14 -0
  34. package/lib/types/model-catalog.d.ts.map +1 -0
  35. package/lib/types/native.d.ts +7 -0
  36. package/lib/types/native.d.ts.map +1 -0
  37. package/lib/types/state.d.ts +15 -0
  38. package/lib/types/state.d.ts.map +1 -0
  39. package/lib/types/types.d.ts +34 -0
  40. package/lib/types/types.d.ts.map +1 -0
  41. package/lib/types/web.d.ts +64 -0
  42. package/lib/types/web.d.ts.map +1 -0
  43. package/lib/types.js +2 -0
  44. package/lib/types.js.map +1 -0
  45. package/lib/web.js +221 -0
  46. package/lib/web.js.map +1 -0
  47. package/package.json +112 -0
package/lib/client.js ADDED
@@ -0,0 +1,506 @@
1
+ window.__ModuleLoader__.load({
2
+ id: "dsh-llm-ustc",
3
+ factory: (require) => {
4
+ var module = { exports: {} };
5
+ var exports = module.exports;
6
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
7
+ let react = require("react");
8
+ let _deepseek_ai_dsh_client_ui_primitives = require("@deepseek-ai/dsh-client-ui-primitives");
9
+ let react_jsx_runtime = require("react/jsx-runtime");
10
+ //#region src/client/index.tsx
11
+ const LOCALE_NS = "llm-ustc";
12
+ const SETTINGS_ROUTE = "/_dsh/llm-ustc/settings";
13
+ const en = {
14
+ title: "USTC LLM",
15
+ intro: "Manage the USTC API credential, model catalog, and iWAN access.",
16
+ expand: "Show settings",
17
+ collapse: "Hide settings",
18
+ apiKeyLabel: "USTC API Key",
19
+ apiKeyPlaceholder: "Enter a new key",
20
+ configured: "Configured",
21
+ readOnly: "The active credential or settings provider is read-only.",
22
+ save: "Save key",
23
+ saving: "Saving...",
24
+ remove: "Remove key",
25
+ iwan: "iWAN access",
26
+ beginOidc: "Start USTC sign-in",
27
+ startingOidc: "Starting...",
28
+ logoutIwan: "Sign out",
29
+ loggingOut: "Signing out...",
30
+ openLogin: "Open sign-in page",
31
+ callbackLabel: "Callback URL",
32
+ callbackPlaceholder: "Paste the complete com.panabit.mobile:// callback URL",
33
+ completeOidc: "Finish sign-in",
34
+ completingOidc: "Finishing...",
35
+ noLine: "Select a line",
36
+ selectLine: "Apply line",
37
+ applyingLine: "Applying...",
38
+ route: "Current route",
39
+ refreshRoute: "Refresh route",
40
+ directRoute: "Direct",
41
+ iwanRoute: "iWAN",
42
+ models: "Model catalog",
43
+ syncModels: "Sync models",
44
+ syncingModels: "Syncing...",
45
+ refreshedAt: "Refreshed",
46
+ never: "Never",
47
+ loading: "Loading...",
48
+ helperStopped: "Helper not started",
49
+ retry: "Retry"
50
+ };
51
+ const zh = {
52
+ title: "科大大模型",
53
+ intro: "管理科大 API 凭据、模型目录和 iWAN 访问。",
54
+ expand: "展开设置",
55
+ collapse: "收起设置",
56
+ apiKeyLabel: "科大 API Key",
57
+ apiKeyPlaceholder: "输入新的 Key",
58
+ configured: "已配置",
59
+ readOnly: "当前凭据或设置提供方为只读。",
60
+ save: "保存 Key",
61
+ saving: "正在保存...",
62
+ remove: "移除 Key",
63
+ iwan: "iWAN 访问",
64
+ beginOidc: "开始科大登录",
65
+ startingOidc: "正在启动...",
66
+ logoutIwan: "退出登录",
67
+ loggingOut: "正在退出...",
68
+ openLogin: "打开登录页面",
69
+ callbackLabel: "回调 URL",
70
+ callbackPlaceholder: "粘贴完整的 com.panabit.mobile:// 回调 URL",
71
+ completeOidc: "完成登录",
72
+ completingOidc: "正在完成...",
73
+ noLine: "选择线路",
74
+ selectLine: "应用线路",
75
+ applyingLine: "正在应用...",
76
+ route: "当前路由",
77
+ refreshRoute: "刷新路由",
78
+ directRoute: "直连",
79
+ iwanRoute: "iWAN",
80
+ models: "模型目录",
81
+ syncModels: "同步模型",
82
+ syncingModels: "正在同步...",
83
+ refreshedAt: "刷新时间",
84
+ never: "从未",
85
+ loading: "正在加载...",
86
+ helperStopped: "Helper 尚未启动",
87
+ retry: "重试"
88
+ };
89
+ async function apiRequest(request) {
90
+ const response = await fetch(SETTINGS_ROUTE, request === void 0 ? { credentials: "same-origin" } : {
91
+ method: "POST",
92
+ credentials: "same-origin",
93
+ headers: { "content-type": "application/json" },
94
+ body: JSON.stringify(request)
95
+ });
96
+ const body = await response.json();
97
+ if (!response.ok || !body.ok) throw new Error(body.error?.message ?? `USTC settings request failed (HTTP ${response.status})`);
98
+ return body.value;
99
+ }
100
+ var UstcSettingsController = class {
101
+ current = { status: "idle" };
102
+ listeners = /* @__PURE__ */ new Set();
103
+ generation = 0;
104
+ subscribe = (listener) => {
105
+ this.listeners.add(listener);
106
+ return () => {
107
+ this.listeners.delete(listener);
108
+ };
109
+ };
110
+ snapshot = () => this.current;
111
+ set(next) {
112
+ this.current = next;
113
+ for (const listener of this.listeners) listener();
114
+ }
115
+ async load() {
116
+ const generation = ++this.generation;
117
+ this.set({
118
+ ...this.current,
119
+ status: "loading",
120
+ action: "load",
121
+ error: void 0
122
+ });
123
+ try {
124
+ const snapshot = await apiRequest();
125
+ if (generation !== this.generation) return;
126
+ this.set({
127
+ status: "ready",
128
+ snapshot,
129
+ oidc: this.current.oidc
130
+ });
131
+ } catch (error) {
132
+ if (generation !== this.generation) return;
133
+ this.set({
134
+ ...this.current,
135
+ status: "error",
136
+ action: void 0,
137
+ error: messageOf(error)
138
+ });
139
+ }
140
+ }
141
+ refreshIfLoaded() {
142
+ if (this.current.status !== "idle" && this.current.action === void 0) this.load();
143
+ }
144
+ async run(action, request, apply) {
145
+ this.set({
146
+ ...this.current,
147
+ action,
148
+ error: void 0
149
+ });
150
+ try {
151
+ const value = await apiRequest({
152
+ action,
153
+ ...request
154
+ });
155
+ this.set(apply(value, this.current));
156
+ } catch (error) {
157
+ this.set({
158
+ ...this.current,
159
+ action: void 0,
160
+ error: messageOf(error)
161
+ });
162
+ }
163
+ }
164
+ mutateSnapshot(action, request = {}) {
165
+ return this.run(action, request, (snapshot, state) => ({
166
+ status: "ready",
167
+ snapshot,
168
+ oidc: state.oidc
169
+ }));
170
+ }
171
+ beginOidc() {
172
+ return this.run("beginOidc", {}, (oidc, state) => ({
173
+ ...state,
174
+ action: void 0,
175
+ oidc
176
+ }));
177
+ }
178
+ completeOidc(callbackUrl) {
179
+ return this.run("completeOidc", { callbackUrl }, (value) => ({
180
+ status: "ready",
181
+ snapshot: value.snapshot
182
+ }));
183
+ }
184
+ };
185
+ function messageOf(error) {
186
+ return error instanceof Error ? error.message : String(error);
187
+ }
188
+ function IwanSettingsItem({ controller, t }) {
189
+ if (controller === void 0 || t === void 0) return null;
190
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(UstcCard, {
191
+ controller,
192
+ t
193
+ });
194
+ }
195
+ function UstcCard({ controller, t }) {
196
+ const state = (0, react.useSyncExternalStore)(controller.subscribe, controller.snapshot, controller.snapshot);
197
+ const [open, setOpen] = (0, react.useState)(false);
198
+ (0, react.useEffect)(() => {
199
+ if (state.status === "idle") controller.load();
200
+ }, [controller, state.status]);
201
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("li", {
202
+ className: "ulu-card",
203
+ "data-open": open || void 0,
204
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
205
+ type: "button",
206
+ className: "ulu-card-header",
207
+ "aria-expanded": open,
208
+ "aria-label": `${t(open ? "collapse" : "expand")}: ${t("title")}`,
209
+ onClick: () => {
210
+ setOpen((value) => !value);
211
+ },
212
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
213
+ className: "ulu-card-head-text",
214
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
215
+ className: "ulu-card-name",
216
+ children: t("title")
217
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
218
+ className: "ulu-card-description",
219
+ children: t("intro")
220
+ })]
221
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronDownOutline14, { className: "ulu-card-chevron" })]
222
+ }), open ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
223
+ className: "ulu-card-body",
224
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(LoadedSettings, {
225
+ controller,
226
+ t,
227
+ state
228
+ })
229
+ }) : null]
230
+ });
231
+ }
232
+ function LoadedSettings({ controller, t, state }) {
233
+ const snapshot = state.snapshot;
234
+ const [apiKey, setApiKey] = (0, react.useState)("");
235
+ const [callbackUrl, setCallbackUrl] = (0, react.useState)("");
236
+ const [selectedServerId, setSelectedServerId] = (0, react.useState)("");
237
+ (0, react.useEffect)(() => {
238
+ setSelectedServerId(snapshot?.selectedServerId ?? "");
239
+ }, [snapshot?.selectedServerId]);
240
+ if ((state.status === "idle" || state.status === "loading") && snapshot === void 0) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
241
+ className: "ulu-loading",
242
+ children: t("loading")
243
+ });
244
+ if (snapshot === void 0) return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
245
+ className: "ulu-load-error",
246
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
247
+ className: "ulu-alert error",
248
+ children: state.error ?? t("helperStopped")
249
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
250
+ size: "sm",
251
+ variant: "outline",
252
+ onClick: () => {
253
+ controller.load();
254
+ },
255
+ children: t("retry")
256
+ })]
257
+ });
258
+ const busy = state.action !== void 0 && state.action !== "load";
259
+ const selectedExists = snapshot.iwan.servers.some((server) => server.id === selectedServerId);
260
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
261
+ className: "ulu-settings",
262
+ children: [
263
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
264
+ className: "ulu-status-row",
265
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("route") }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
266
+ className: "ulu-route-value",
267
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: snapshot.helper?.route === "iwan" ? t("iwanRoute") : t("directRoute") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tooltip, {
268
+ label: t("refreshRoute"),
269
+ side: "top",
270
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
271
+ className: "ulu-route-refresh",
272
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
273
+ type: "button",
274
+ variant: "toolbar",
275
+ size: "sm",
276
+ icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconRefreshOutline14, { className: state.action === "refreshRoute" ? "ulu-spin" : void 0 }),
277
+ "aria-label": t("refreshRoute"),
278
+ disabled: busy,
279
+ onClick: () => {
280
+ controller.mutateSnapshot("refreshRoute");
281
+ }
282
+ })
283
+ })
284
+ })]
285
+ })]
286
+ }),
287
+ !snapshot.writable || !snapshot.apiKey.writable || !snapshot.iwan.writable ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
288
+ className: "ulu-alert warning",
289
+ children: t("readOnly")
290
+ }) : null,
291
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
292
+ className: "ulu-section",
293
+ children: [
294
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
295
+ className: "ulu-section-title",
296
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", { children: t("apiKeyLabel") })
297
+ }),
298
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Input, {
299
+ type: "password",
300
+ autoComplete: "off",
301
+ "aria-label": t("apiKeyLabel"),
302
+ placeholder: snapshot.apiKey.configured ? t("configured") : t("apiKeyPlaceholder"),
303
+ value: apiKey,
304
+ onChange: (event) => {
305
+ setApiKey(event.target.value);
306
+ }
307
+ }),
308
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
309
+ className: "ulu-actions",
310
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
311
+ size: "sm",
312
+ variant: "primary",
313
+ disabled: busy || !snapshot.apiKey.writable || apiKey.trim().length === 0,
314
+ onClick: () => {
315
+ controller.mutateSnapshot("saveApiKey", { value: apiKey }).then(() => {
316
+ setApiKey("");
317
+ });
318
+ },
319
+ children: state.action === "saveApiKey" ? t("saving") : t("save")
320
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
321
+ size: "sm",
322
+ variant: "outline",
323
+ disabled: busy || !snapshot.apiKey.writable || !snapshot.apiKey.configured,
324
+ onClick: () => {
325
+ controller.mutateSnapshot("unsetApiKey");
326
+ },
327
+ children: t("remove")
328
+ })]
329
+ })
330
+ ]
331
+ }),
332
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
333
+ className: "ulu-section",
334
+ children: [
335
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
336
+ className: "ulu-section-title",
337
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", { children: t("iwan") }), snapshot.iwan.configured ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
338
+ size: "sm",
339
+ variant: "outline",
340
+ disabled: busy || !snapshot.iwan.writable || !snapshot.writable,
341
+ onClick: () => {
342
+ controller.mutateSnapshot("logoutIwan", { expectedRevision: snapshot.revision });
343
+ },
344
+ children: state.action === "logoutIwan" ? t("loggingOut") : t("logoutIwan")
345
+ }) : null]
346
+ }),
347
+ snapshot.iwan.configured ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
348
+ className: "ulu-login-row",
349
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
350
+ variant: "primary",
351
+ disabled: busy || !snapshot.iwan.writable,
352
+ onClick: () => {
353
+ controller.beginOidc();
354
+ },
355
+ children: state.action === "beginOidc" ? t("startingOidc") : t("beginOidc")
356
+ }), state.oidc === void 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
357
+ className: "ulu-link",
358
+ href: state.oidc.authUrl,
359
+ target: "_blank",
360
+ rel: "noopener noreferrer",
361
+ children: t("openLogin")
362
+ })]
363
+ }),
364
+ snapshot.iwan.configured || state.oidc === void 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
365
+ className: "ulu-row",
366
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
367
+ className: "ulu-field",
368
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
369
+ htmlFor: "ulu-callback-url",
370
+ children: t("callbackLabel")
371
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Input, {
372
+ id: "ulu-callback-url",
373
+ value: callbackUrl,
374
+ placeholder: t("callbackPlaceholder"),
375
+ onChange: (event) => {
376
+ setCallbackUrl(event.target.value);
377
+ }
378
+ })]
379
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
380
+ variant: "outline",
381
+ disabled: busy || callbackUrl.trim().length === 0,
382
+ onClick: () => {
383
+ controller.completeOidc(callbackUrl);
384
+ },
385
+ children: state.action === "completeOidc" ? t("completingOidc") : t("completeOidc")
386
+ })]
387
+ }),
388
+ snapshot.iwan.configured ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
389
+ className: "ulu-row",
390
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
391
+ className: "ulu-line-select",
392
+ "aria-label": t("noLine"),
393
+ value: selectedServerId,
394
+ onChange: (event) => {
395
+ setSelectedServerId(event.target.value);
396
+ },
397
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
398
+ value: "",
399
+ children: t("noLine")
400
+ }), snapshot.iwan.servers.map((server) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("option", {
401
+ value: server.id,
402
+ children: [
403
+ server.name,
404
+ " (",
405
+ server.endpoint,
406
+ ")"
407
+ ]
408
+ }, server.id))]
409
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
410
+ variant: "outline",
411
+ disabled: busy || !snapshot.writable || !selectedExists || selectedServerId === snapshot.selectedServerId,
412
+ onClick: () => {
413
+ controller.mutateSnapshot("selectServer", {
414
+ serverId: selectedServerId,
415
+ expectedRevision: snapshot.revision
416
+ });
417
+ },
418
+ children: state.action === "selectServer" ? t("applyingLine") : t("selectLine")
419
+ })]
420
+ }) : null
421
+ ]
422
+ }),
423
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
424
+ className: "ulu-section",
425
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
426
+ className: "ulu-section-title",
427
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", { children: t("models") }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", { children: [
428
+ t("refreshedAt"),
429
+ ": ",
430
+ snapshot.modelsUpdatedAt === void 0 ? t("never") : new Date(snapshot.modelsUpdatedAt).toLocaleString()
431
+ ] })] }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
432
+ size: "sm",
433
+ variant: "outline",
434
+ disabled: busy || !snapshot.apiKey.configured,
435
+ onClick: () => {
436
+ controller.mutateSnapshot("syncModels");
437
+ },
438
+ children: state.action === "syncModels" ? t("syncingModels") : t("syncModels")
439
+ })]
440
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
441
+ className: "ulu-model-list",
442
+ children: snapshot.models.map((model) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
443
+ className: "ulu-model-entry",
444
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("code", { children: model.id }), model.name === model.id ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: model.name })]
445
+ }, model.id))
446
+ })]
447
+ })
448
+ ]
449
+ });
450
+ }
451
+ const CSS = `
452
+ .ulu-card{list-style:none;border:1px solid var(--dsw-alias-border-l2);border-radius:12px;background:var(--dsw-alias-bg-layer-3);transition:border-color .16s,background .16s}.ulu-card:hover{border-color:var(--dsw-alias-label-dimmed)}.ulu-card[data-open=true]{border-color:var(--dsw-alias-label-dimmed);background:var(--dsw-alias-bg-layer-2)}
453
+ .ulu-card-header{appearance:none;display:flex;width:100%;align-items:center;gap:12px;padding:14px 16px;border:0;border-radius:12px;background:transparent;color:inherit;font:inherit;text-align:left;cursor:pointer}.ulu-card-header:focus-visible{outline:none;box-shadow:inset 2px 0 0 var(--dsw-alias-brand-primary)}.ulu-card-head-text{display:flex;min-width:0;flex:1;flex-direction:column;gap:4px}.ulu-card-name{color:var(--dsw-alias-label-primary);font-size:15px;font-weight:600;line-height:1.4}.ulu-card-description{color:var(--dsw-alias-label-tertiary);font-size:13px;line-height:1.5}.ulu-card-chevron{flex:none;color:var(--dsw-alias-label-tertiary);transition:transform .16s}.ulu-card[data-open=true] .ulu-card-chevron{transform:rotate(180deg)}.ulu-card-body{margin:0 16px;padding-bottom:8px;border-top:1px solid var(--dsw-alias-border-l2)}
454
+ .ulu-settings{color:var(--dsw-alias-label-primary)}
455
+ .ulu-section{display:grid;min-width:0;gap:6px;padding:12px 0;border-top:1px solid var(--dsw-alias-border-l2)}.ulu-section>*{min-width:0}.ulu-section-title{display:flex;min-width:0;align-items:center;justify-content:space-between;gap:14px}.ulu-section-title>div{min-width:0}.ulu-section-title h3{margin:0;color:var(--dsw-alias-label-primary);font-size:13px;font-weight:500;letter-spacing:0;line-height:1.5}.ulu-section-title p{max-width:620px;margin:3px 0 0;color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:1.5;overflow-wrap:anywhere}
456
+ .ulu-row{display:grid;min-width:0;grid-template-columns:minmax(0,1fr) auto;align-items:end;gap:10px}.ulu-field{display:grid;min-width:0;gap:6px}.ulu-field>*{min-width:0;max-width:100%;box-sizing:border-box}.ulu-field>label{color:var(--dsw-alias-label-primary);font-size:13px;font-weight:500;line-height:1.5}.ulu-field>span{width:100%}.ulu-line-select{box-sizing:border-box;width:100%;height:34px;padding:0 12px;border:1px solid var(--dsw-alias-border-l2);border-radius:8px;background:var(--dsw-alias-bg-layer-3);color:var(--dsw-alias-label-primary);font:inherit;font-size:13px}.ulu-line-select:focus-visible{border-color:var(--dsw-alias-brand-primary);outline:none}.ulu-actions,.ulu-login-row{display:flex;min-width:0;align-items:center;gap:8px;flex-wrap:wrap}.ulu-link{display:inline-flex;min-height:34px;align-items:center;color:var(--dsw-alias-brand-primary);font-size:12px;font-weight:500;text-decoration:none}.ulu-link:hover{text-decoration:underline}
457
+ .ulu-status-row{display:flex;min-height:34px;align-items:center;justify-content:space-between;gap:16px;color:var(--dsw-alias-label-secondary);font-size:12px}.ulu-status-row strong{color:var(--dsw-alias-label-primary);font-weight:500}.ulu-route-value{display:flex;align-items:center;gap:5px}.ulu-route-refresh{display:inline-flex}.ulu-route-refresh>button{width:28px;padding:0}.ulu-spin{animation:ulu-spin .7s linear infinite}@keyframes ulu-spin{to{transform:rotate(360deg)}}.ulu-alert{margin:0;padding:10px 0;border-top:1px solid var(--dsw-alias-border-l2);font-size:12px;line-height:1.5}.ulu-alert.warning{color:var(--dsw-alias-label-warning,#8c641b)}.ulu-alert.error{color:var(--dsw-alias-label-error,#a43d39)}
458
+ .ulu-loading{padding:16px 0;color:var(--dsw-alias-label-tertiary);font-size:12px}.ulu-load-error{display:flex;align-items:center;justify-content:space-between;gap:12px}.ulu-load-error .ulu-alert{flex:1;border-top:0}
459
+ .ulu-model-list{display:flex;max-height:300px;min-width:0;flex-direction:column;overflow:auto;border-top:1px solid var(--dsw-alias-border-l2)}.ulu-model-entry{display:grid;min-width:0;grid-template-columns:minmax(0,1.3fr) minmax(0,1fr);gap:8px;padding:9px 2px;border-bottom:1px solid var(--dsw-alias-border-l2);font-size:12px;line-height:18px}.ulu-model-entry code,.ulu-model-entry span{min-width:0;overflow-wrap:anywhere}.ulu-model-entry span{color:var(--dsw-alias-label-tertiary)}
460
+ `;
461
+ function installStyles() {
462
+ const id = "dsh-llm-ustc/client";
463
+ if (document.querySelector(`style[data-plugin-css="${id}"]`) !== null) return () => {};
464
+ const style = document.createElement("style");
465
+ style.dataset.pluginCss = id;
466
+ style.textContent = CSS;
467
+ document.head.appendChild(style);
468
+ return () => {
469
+ style.remove();
470
+ };
471
+ }
472
+ const inject = ["slots", "locale"];
473
+ function apply(ctx) {
474
+ ctx.effect(installStyles, "dsh-llm-ustc: styles");
475
+ ctx.effect(() => ctx.locale.register(LOCALE_NS, {
476
+ en,
477
+ zh
478
+ }), "dsh-llm-ustc: locale");
479
+ const t = ctx.locale.bind(LOCALE_NS);
480
+ const controller = new UstcSettingsController();
481
+ ctx.effect(() => {
482
+ const dispose = ctx.on("connection/reset", () => {
483
+ controller.refreshIfLoaded();
484
+ });
485
+ return () => {
486
+ dispose();
487
+ };
488
+ }, "dsh-llm-ustc: settings invalidations");
489
+ ctx.slots.inject("settings.plugin.item", () => ctx.slots.register({
490
+ name: "settings.plugin.item",
491
+ id: "llm-ustc",
492
+ order: 25,
493
+ inject: () => ({
494
+ controller,
495
+ t
496
+ })
497
+ }, IwanSettingsItem));
498
+ }
499
+ //#endregion
500
+ exports.UstcSettingsController = UstcSettingsController;
501
+ exports.apply = apply;
502
+ exports.inject = inject;
503
+
504
+ return module.exports;
505
+ },
506
+ });
package/lib/config.js ADDED
@@ -0,0 +1,17 @@
1
+ import z from '@deepseek-ai/schemastery';
2
+ export const Config = z.object({
3
+ selectedServerId: z.string(),
4
+ directReprobeSeconds: z.number().step(1).min(30).max(86_400).default(300),
5
+ });
6
+ export function resolveConfig(config) {
7
+ const directReprobeSeconds = config.directReprobeSeconds ?? 300;
8
+ if (!Number.isSafeInteger(directReprobeSeconds) || directReprobeSeconds < 30 || directReprobeSeconds > 86_400) {
9
+ throw new TypeError('llm-ustc.directReprobeSeconds must be an integer from 30 to 86400');
10
+ }
11
+ const selected = config.selectedServerId?.trim();
12
+ return {
13
+ ...(selected === undefined || selected.length === 0 ? {} : { selectedServerId: selected }),
14
+ directReprobeSeconds,
15
+ };
16
+ }
17
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,CAAC,MAAM,0BAA0B,CAAA;AAOxC,MAAM,CAAC,MAAM,MAAM,GAAc,CAAC,CAAC,MAAM,CAAC;IACxC,gBAAgB,EAAE,CAAC,CAAC,MAAM,EAAE;IAC5B,oBAAoB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC;CAC1E,CAAC,CAAA;AAOF,MAAM,UAAU,aAAa,CAAC,MAAc;IAC1C,MAAM,oBAAoB,GAAG,MAAM,CAAC,oBAAoB,IAAI,GAAG,CAAA;IAC/D,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,oBAAoB,CAAC,IAAI,oBAAoB,GAAG,EAAE,IAAI,oBAAoB,GAAG,MAAM,EAAE,CAAC;QAC9G,MAAM,IAAI,SAAS,CAAC,mEAAmE,CAAC,CAAA;IAC1F,CAAC;IACD,MAAM,QAAQ,GAAG,MAAM,CAAC,gBAAgB,EAAE,IAAI,EAAE,CAAA;IAChD,OAAO;QACL,GAAG,CAAC,QAAQ,KAAK,SAAS,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,gBAAgB,EAAE,QAAQ,EAAE,CAAC;QAC1F,oBAAoB;KACrB,CAAA;AACH,CAAC"}
@@ -0,0 +1,11 @@
1
+ export const PROVIDER = 'ustc';
2
+ export const PROVIDER_NAME = 'USTC LLM';
3
+ export const SETTINGS_NS = 'llm-ustc';
4
+ export const API_KEY_REF = 'USTC_LLM_API_KEY';
5
+ export const IWAN_CONFIG_REF = 'USTC_LLM_IWAN_CONFIG';
6
+ export const DEFAULT_MODEL = 'deepseek-v4-flash-ascend';
7
+ export const DEFAULT_CONTEXT_WINDOW = 262_144;
8
+ export const DEFAULT_MAX_TOKENS = 32_768;
9
+ export const HELPER_PROTOCOL = 'v1';
10
+ export const SETTINGS_ROUTE = '/_dsh/llm-ustc/settings';
11
+ //# sourceMappingURL=constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,QAAQ,GAAG,MAAM,CAAA;AAC9B,MAAM,CAAC,MAAM,aAAa,GAAG,UAAU,CAAA;AACvC,MAAM,CAAC,MAAM,WAAW,GAAG,UAAU,CAAA;AACrC,MAAM,CAAC,MAAM,WAAW,GAAG,kBAAkB,CAAA;AAC7C,MAAM,CAAC,MAAM,eAAe,GAAG,sBAAsB,CAAA;AACrD,MAAM,CAAC,MAAM,aAAa,GAAG,0BAA0B,CAAA;AACvD,MAAM,CAAC,MAAM,sBAAsB,GAAG,OAAO,CAAA;AAC7C,MAAM,CAAC,MAAM,kBAAkB,GAAG,MAAM,CAAA;AACxC,MAAM,CAAC,MAAM,eAAe,GAAG,IAAI,CAAA;AACnC,MAAM,CAAC,MAAM,cAAc,GAAG,yBAAyB,CAAA"}