dsh-qoder-connect 0.1.5 → 0.1.8

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/lib/client.js CHANGED
@@ -230,6 +230,17 @@ window.__ModuleLoader__.load({
230
230
  const POLL_DEFAULT_MS = 3e5;
231
231
  /** Floor the schema also enforces; mirrored here for immediate UI feedback. */
232
232
  const POLL_MIN_MS = 6e4;
233
+ /** 10:00 UTC+8, the moment the upstream resets the daily campaign. */
234
+ const CHECK_IN_MINUTE_DEFAULT = 600;
235
+ /** Minutes past midnight (UTC+8), split for the two number fields. */
236
+ function splitMinutes(minutes) {
237
+ const safe = Number.isFinite(minutes) ? Math.trunc(minutes) : CHECK_IN_MINUTE_DEFAULT;
238
+ const clamped = safe < 0 || safe > 1439 ? CHECK_IN_MINUTE_DEFAULT : safe;
239
+ return {
240
+ hours: Math.floor(clamped / 60),
241
+ minutes: clamped % 60
242
+ };
243
+ }
233
244
  /** Read the section values out of a scope snapshot (defaults when absent). */
234
245
  function project(scope) {
235
246
  if (scope === void 0) return {
@@ -240,6 +251,8 @@ window.__ModuleLoader__.load({
240
251
  sidebarQuotaGlobal: false,
241
252
  autoCheckInCN: false,
242
253
  autoCheckInGlobal: false,
254
+ checkInMinuteCN: CHECK_IN_MINUTE_DEFAULT,
255
+ checkInMinuteGlobal: CHECK_IN_MINUTE_DEFAULT,
243
256
  quotaPollMs: POLL_DEFAULT_MS
244
257
  }
245
258
  };
@@ -253,6 +266,8 @@ window.__ModuleLoader__.load({
253
266
  sidebarQuotaGlobal: value.sidebarQuotaGlobal === true,
254
267
  autoCheckInCN: value.autoCheckInCN === true,
255
268
  autoCheckInGlobal: value.autoCheckInGlobal === true,
269
+ checkInMinuteCN: typeof value.checkInMinuteCN === "number" ? value.checkInMinuteCN : CHECK_IN_MINUTE_DEFAULT,
270
+ checkInMinuteGlobal: typeof value.checkInMinuteGlobal === "number" ? value.checkInMinuteGlobal : CHECK_IN_MINUTE_DEFAULT,
256
271
  quotaPollMs: typeof value.quotaPollMs === "number" ? value.quotaPollMs : POLL_DEFAULT_MS
257
272
  }
258
273
  };
@@ -278,13 +293,15 @@ window.__ModuleLoader__.load({
278
293
  sidebarQuotaGlobal: false,
279
294
  autoCheckInCN: false,
280
295
  autoCheckInGlobal: false,
296
+ checkInMinuteCN: CHECK_IN_MINUTE_DEFAULT,
297
+ checkInMinuteGlobal: CHECK_IN_MINUTE_DEFAULT,
281
298
  quotaPollMs: POLL_DEFAULT_MS
282
299
  }
283
300
  };
284
301
  function stableProject(scope) {
285
302
  if (scope === void 0) return UNAVAILABLE;
286
303
  const next = project(scope);
287
- if (cachedProjection === void 0 || cachedScope !== scope || cachedProjection.status !== next.status || cachedProjection.writable !== next.writable || cachedProjection.values.sidebarQuotaCN !== next.values.sidebarQuotaCN || cachedProjection.values.sidebarQuotaGlobal !== next.values.sidebarQuotaGlobal || cachedProjection.values.autoCheckInCN !== next.values.autoCheckInCN || cachedProjection.values.autoCheckInGlobal !== next.values.autoCheckInGlobal || cachedProjection.values.quotaPollMs !== next.values.quotaPollMs) {
304
+ if (cachedProjection === void 0 || cachedScope !== scope || cachedProjection.status !== next.status || cachedProjection.writable !== next.writable || cachedProjection.values.sidebarQuotaCN !== next.values.sidebarQuotaCN || cachedProjection.values.sidebarQuotaGlobal !== next.values.sidebarQuotaGlobal || cachedProjection.values.autoCheckInCN !== next.values.autoCheckInCN || cachedProjection.values.autoCheckInGlobal !== next.values.autoCheckInGlobal || cachedProjection.values.checkInMinuteCN !== next.values.checkInMinuteCN || cachedProjection.values.checkInMinuteGlobal !== next.values.checkInMinuteGlobal || cachedProjection.values.quotaPollMs !== next.values.quotaPollMs) {
288
305
  cachedScope = scope;
289
306
  cachedProjection = next;
290
307
  }
@@ -324,6 +341,106 @@ window.__ModuleLoader__.load({
324
341
  })]
325
342
  });
326
343
  }
344
+ /**
345
+ * One time row: the moment a variant checks in, as two typeable number fields.
346
+ *
347
+ * Deliberately NOT `<input type="time">`: that control's segments are spinners,
348
+ * and with an IME active (every Chinese/Japanese keyboard) the segments refuse
349
+ * typed digits, leaving only the tiny stepper arrows — unusable for the one
350
+ * thing this row exists to do. Two plain number fields accept typing under any
351
+ * input method; the value is committed on blur or Enter, so a half-typed
352
+ * field never writes a wrong moment to the host.
353
+ */
354
+ function TimeRow({ label, hint, value, disabled, onPick }) {
355
+ const split = splitMinutes(value);
356
+ const [hourDraft, setHourDraft] = (0, react.useState)(String(split.hours));
357
+ const [minuteDraft, setMinuteDraft] = (0, react.useState)(String(split.minutes).padStart(2, "0"));
358
+ (0, react.useEffect)(() => {
359
+ const next = splitMinutes(value);
360
+ setHourDraft(String(next.hours));
361
+ setMinuteDraft(String(next.minutes).padStart(2, "0"));
362
+ }, [value]);
363
+ const commit = () => {
364
+ const parsedHours = Number.parseInt(hourDraft, 10);
365
+ const parsedMinutes = Number.parseInt(minuteDraft, 10);
366
+ const hours = Number.isFinite(parsedHours) ? Math.min(23, Math.max(0, parsedHours)) : split.hours;
367
+ const minutes = Number.isFinite(parsedMinutes) ? Math.min(59, Math.max(0, parsedMinutes)) : split.minutes;
368
+ const next = hours * 60 + minutes;
369
+ if (next === value) {
370
+ setHourDraft(String(hours));
371
+ setMinuteDraft(String(minutes).padStart(2, "0"));
372
+ return;
373
+ }
374
+ onPick(next);
375
+ };
376
+ const onKeyDown = (event) => {
377
+ if (event.key === "Enter") {
378
+ event.preventDefault();
379
+ commit();
380
+ }
381
+ };
382
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
383
+ style: rowStyle$1,
384
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
385
+ style: rowTextStyle,
386
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
387
+ style: labelStyle$1,
388
+ children: label
389
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
390
+ style: hintStyle,
391
+ children: hint
392
+ })]
393
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
394
+ style: pollFieldStyle,
395
+ children: [
396
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
397
+ type: "number",
398
+ min: 0,
399
+ max: 23,
400
+ value: hourDraft,
401
+ disabled,
402
+ "aria-label": `${label} — hour`,
403
+ "data-checkin-part": "hour",
404
+ onChange: (event) => {
405
+ setHourDraft(event.target.value);
406
+ },
407
+ onBlur: commit,
408
+ onKeyDown,
409
+ style: {
410
+ ...timePartStyle,
411
+ opacity: disabled === true ? .45 : 1
412
+ }
413
+ }),
414
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
415
+ style: labelStyle$1,
416
+ children: ":"
417
+ }),
418
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
419
+ type: "number",
420
+ min: 0,
421
+ max: 59,
422
+ value: minuteDraft,
423
+ disabled,
424
+ "aria-label": `${label} — minute`,
425
+ "data-checkin-part": "minute",
426
+ onChange: (event) => {
427
+ setMinuteDraft(event.target.value);
428
+ },
429
+ onBlur: commit,
430
+ onKeyDown,
431
+ style: {
432
+ ...timePartStyle,
433
+ opacity: disabled === true ? .45 : 1
434
+ }
435
+ }),
436
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
437
+ style: hintStyle,
438
+ children: "UTC+8"
439
+ })
440
+ ]
441
+ })]
442
+ });
443
+ }
327
444
  /** The inner controls for sidebar quota settings. */
328
445
  function QuotaSettingsContent({ t = (key) => key, scope, signedIn }) {
329
446
  const subscribe = (0, react.useCallback)((onStoreChange) => {
@@ -411,6 +528,13 @@ window.__ModuleLoader__.load({
411
528
  disabledHint: t("quotaSignInRequired"),
412
529
  onToggle: (next) => write("autoCheckInCN", next)
413
530
  }),
531
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TimeRow, {
532
+ label: t("checkInTimeCN"),
533
+ hint: t("checkInTimeHint"),
534
+ value: projection.values.checkInMinuteCN,
535
+ disabled: !signed.cn,
536
+ onPick: (next) => write("checkInMinuteCN", next)
537
+ }),
414
538
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ToggleRow, {
415
539
  label: t("autoCheckInGlobal"),
416
540
  hint: t("autoCheckInHintGlobal"),
@@ -419,6 +543,13 @@ window.__ModuleLoader__.load({
419
543
  disabledHint: t("quotaSignInRequired"),
420
544
  onToggle: (next) => write("autoCheckInGlobal", next)
421
545
  }),
546
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TimeRow, {
547
+ label: t("checkInTimeGlobal"),
548
+ hint: t("checkInTimeHint"),
549
+ value: projection.values.checkInMinuteGlobal,
550
+ disabled: !signed.global,
551
+ onPick: (next) => write("checkInMinuteGlobal", next)
552
+ }),
422
553
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
423
554
  style: {
424
555
  ...rowStyle$1,
@@ -518,6 +649,20 @@ window.__ModuleLoader__.load({
518
649
  gap: 6,
519
650
  flex: "none"
520
651
  };
652
+ const timePartStyle = {
653
+ boxSizing: "border-box",
654
+ width: 56,
655
+ padding: "5px 8px",
656
+ borderWidth: "1px",
657
+ borderStyle: "solid",
658
+ borderColor: "var(--dsw-alias-border-l2)",
659
+ borderRadius: 8,
660
+ background: "var(--dsw-alias-bg-layer-2)",
661
+ color: "var(--dsw-alias-label-primary)",
662
+ font: "inherit",
663
+ fontSize: 13,
664
+ textAlign: "center"
665
+ };
521
666
  const inputStyle = {
522
667
  boxSizing: "border-box",
523
668
  width: 55,
@@ -1064,7 +1209,246 @@ window.__ModuleLoader__.load({
1064
1209
  if (tokens >= 1e3 && tokens % 1e3 === 0) return `${tokens / 1e3}K`;
1065
1210
  return String(tokens);
1066
1211
  }
1067
- function CheckInLogTable({ logs = [], t, onCheckIn, onRefresh, onClear, busy, checkingIn, clearing, disabled, notice }) {
1212
+ /**
1213
+ * Model visibility table with individual toggle switches and batch enable/disable controls.
1214
+ */
1215
+ function ModelSwitchTable({ models, disabledModels = [], t, disabled, onSetModelsEnabled }) {
1216
+ const [selected, setSelected] = (0, react.useState)(/* @__PURE__ */ new Set());
1217
+ const [searchQuery, setSearchQuery] = (0, react.useState)("");
1218
+ const disabledSet = (0, react.useMemo)(() => new Set(disabledModels), [disabledModels]);
1219
+ const list = (0, react.useMemo)(() => models ?? [], [models]);
1220
+ const filteredList = (0, react.useMemo)(() => {
1221
+ const q = searchQuery.trim().toLowerCase();
1222
+ if (!q) return list;
1223
+ return list.filter((m) => m.name.toLowerCase().includes(q) || m.id.toLowerCase().includes(q));
1224
+ }, [list, searchQuery]);
1225
+ const allFilteredSelected = filteredList.length > 0 && filteredList.every((m) => selected.has(m.id));
1226
+ const toggleSelectAll = () => {
1227
+ if (allFilteredSelected) {
1228
+ const next = new Set(selected);
1229
+ for (const m of filteredList) next.delete(m.id);
1230
+ setSelected(next);
1231
+ } else {
1232
+ const next = new Set(selected);
1233
+ for (const m of filteredList) next.add(m.id);
1234
+ setSelected(next);
1235
+ }
1236
+ };
1237
+ const toggleSelectOne = (id) => {
1238
+ const next = new Set(selected);
1239
+ if (next.has(id)) next.delete(id);
1240
+ else next.add(id);
1241
+ setSelected(next);
1242
+ };
1243
+ const handleBatch = (enabled) => {
1244
+ const targets = Array.from(selected);
1245
+ if (targets.length === 0) return;
1246
+ onSetModelsEnabled(targets, enabled);
1247
+ setSelected(/* @__PURE__ */ new Set());
1248
+ };
1249
+ if (list.length === 0) return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1250
+ style: quotaListStyle,
1251
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", {
1252
+ style: quotaTitleStyle,
1253
+ children: t("modelsHeading")
1254
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
1255
+ style: descriptionStyle,
1256
+ children: t("modelsNoModels")
1257
+ })]
1258
+ });
1259
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1260
+ style: quotaListStyle,
1261
+ children: [
1262
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1263
+ style: {
1264
+ display: "flex",
1265
+ flexDirection: "column",
1266
+ gap: 6
1267
+ },
1268
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", {
1269
+ style: quotaTitleStyle,
1270
+ children: t("modelsHeading")
1271
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
1272
+ style: descriptionStyle,
1273
+ children: t("modelsSubtitle")
1274
+ })]
1275
+ }),
1276
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1277
+ style: {
1278
+ display: "flex",
1279
+ alignItems: "center",
1280
+ gap: 8
1281
+ },
1282
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
1283
+ type: "text",
1284
+ value: searchQuery,
1285
+ placeholder: t("modelsSearchPlaceholder"),
1286
+ onChange: (e) => {
1287
+ setSearchQuery(e.currentTarget.value);
1288
+ },
1289
+ style: patInputStyle
1290
+ }), searchQuery ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1291
+ type: "button",
1292
+ style: buttonStyle$1,
1293
+ onClick: () => {
1294
+ setSearchQuery("");
1295
+ },
1296
+ children: t("cancel")
1297
+ }) : null]
1298
+ }),
1299
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1300
+ style: {
1301
+ display: "flex",
1302
+ alignItems: "center",
1303
+ justifyContent: "space-between",
1304
+ flexWrap: "wrap",
1305
+ gap: 8,
1306
+ padding: "6px 0",
1307
+ borderBottom: "1px solid var(--dsw-alias-border-l2)"
1308
+ },
1309
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
1310
+ style: {
1311
+ display: "inline-flex",
1312
+ alignItems: "center",
1313
+ gap: 8,
1314
+ cursor: "pointer",
1315
+ fontSize: 13,
1316
+ userSelect: "none"
1317
+ },
1318
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
1319
+ type: "checkbox",
1320
+ checked: allFilteredSelected,
1321
+ disabled: disabled || filteredList.length === 0,
1322
+ onChange: toggleSelectAll
1323
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: allFilteredSelected ? t("modelsDeselectAll") : t("modelsSelectAll") })]
1324
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1325
+ style: {
1326
+ display: "flex",
1327
+ alignItems: "center",
1328
+ gap: 8
1329
+ },
1330
+ children: [
1331
+ selected.size > 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1332
+ style: modelRateStyle,
1333
+ children: t("modelsSelectedCount", { count: selected.size })
1334
+ }) : null,
1335
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1336
+ type: "button",
1337
+ style: buttonStyle$1,
1338
+ disabled: disabled || selected.size === 0,
1339
+ onClick: () => {
1340
+ handleBatch(true);
1341
+ },
1342
+ children: t("modelsEnableSelected")
1343
+ }),
1344
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1345
+ type: "button",
1346
+ style: buttonStyle$1,
1347
+ disabled: disabled || selected.size === 0,
1348
+ onClick: () => {
1349
+ handleBatch(false);
1350
+ },
1351
+ children: t("modelsDisableSelected")
1352
+ })
1353
+ ]
1354
+ })]
1355
+ }),
1356
+ filteredList.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
1357
+ style: descriptionStyle,
1358
+ children: t("modelsNoMatch", { query: searchQuery.trim() })
1359
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1360
+ style: {
1361
+ display: "flex",
1362
+ flexDirection: "column",
1363
+ gap: 8
1364
+ },
1365
+ children: filteredList.map((model) => {
1366
+ const isModelEnabled = !disabledSet.has(model.id);
1367
+ const isChecked = selected.has(model.id);
1368
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1369
+ style: {
1370
+ display: "flex",
1371
+ alignItems: "center",
1372
+ justifyContent: "space-between",
1373
+ padding: "8px 10px",
1374
+ borderRadius: 6,
1375
+ background: "var(--dsw-alias-bg-layer-2)",
1376
+ gap: 12,
1377
+ opacity: isModelEnabled ? 1 : .65
1378
+ },
1379
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1380
+ style: {
1381
+ display: "inline-flex",
1382
+ alignItems: "center",
1383
+ gap: 10,
1384
+ minWidth: 0,
1385
+ flex: 1
1386
+ },
1387
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
1388
+ type: "checkbox",
1389
+ checked: isChecked,
1390
+ disabled,
1391
+ onChange: () => {
1392
+ toggleSelectOne(model.id);
1393
+ }
1394
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1395
+ style: {
1396
+ display: "flex",
1397
+ flexDirection: "column",
1398
+ minWidth: 0
1399
+ },
1400
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1401
+ style: {
1402
+ fontWeight: 500,
1403
+ fontSize: 13,
1404
+ color: "var(--dsw-alias-label-primary)"
1405
+ },
1406
+ children: model.name
1407
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1408
+ style: {
1409
+ fontSize: 11,
1410
+ color: "var(--dsw-alias-label-tertiary)"
1411
+ },
1412
+ children: model.id
1413
+ })]
1414
+ })]
1415
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1416
+ style: {
1417
+ display: "flex",
1418
+ alignItems: "center",
1419
+ gap: 10
1420
+ },
1421
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
1422
+ style: {
1423
+ display: "inline-flex",
1424
+ alignItems: "center",
1425
+ gap: 6,
1426
+ cursor: disabled ? "not-allowed" : "pointer",
1427
+ userSelect: "none"
1428
+ },
1429
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
1430
+ type: "checkbox",
1431
+ checked: isModelEnabled,
1432
+ disabled,
1433
+ onChange: (event) => {
1434
+ onSetModelsEnabled([model.id], event.currentTarget.checked);
1435
+ }
1436
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1437
+ style: {
1438
+ fontSize: 12,
1439
+ color: isModelEnabled ? "var(--dsw-alias-label-primary)" : "var(--dsw-alias-label-tertiary)"
1440
+ },
1441
+ children: isModelEnabled ? t("modelsEnabled") : t("modelsDisabled")
1442
+ })]
1443
+ })
1444
+ })]
1445
+ }, model.id);
1446
+ })
1447
+ })
1448
+ ]
1449
+ });
1450
+ }
1451
+ function CheckInLogTable({ logs = [], t, onCheckIn, onRefresh, onClear, busy, checkingIn, clearing, disabled, notice, nextRun }) {
1068
1452
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1069
1453
  style: quotaListStyle,
1070
1454
  children: [
@@ -1114,6 +1498,10 @@ window.__ModuleLoader__.load({
1114
1498
  style: bodyStyle,
1115
1499
  children: notice
1116
1500
  }),
1501
+ nextRun === void 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
1502
+ style: descriptionStyle,
1503
+ children: t("checkInNextRun", { time: formatTime(nextRun) })
1504
+ }),
1117
1505
  !logs || logs.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
1118
1506
  style: descriptionStyle,
1119
1507
  children: t("checkInLogEmpty")
@@ -1464,7 +1852,7 @@ window.__ModuleLoader__.load({
1464
1852
  const message = typeof value === "object" && value !== null && "error" in value ? String(value["error"]) : `HTTP ${response.status}`;
1465
1853
  throw new Error(message);
1466
1854
  }
1467
- if (action.action === "set-maximum-context-window" && (typeof value !== "object" || value === null || value["state"] !== "updated")) {
1855
+ if ((action.action === "set-maximum-context-window" || action.action === "set-models-enabled") && (typeof value !== "object" || value === null || value["state"] !== "updated")) {
1468
1856
  const reason = typeof value === "object" && value !== null && "reason" in value ? String(value["reason"]) : t("requestFailed");
1469
1857
  throw new Error(reason);
1470
1858
  }
@@ -1856,6 +2244,7 @@ window.__ModuleLoader__.load({
1856
2244
  children: [
1857
2245
  "status",
1858
2246
  "context",
2247
+ "models",
1859
2248
  "details",
1860
2249
  "checkin"
1861
2250
  ].map((id) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
@@ -1869,7 +2258,7 @@ window.__ModuleLoader__.load({
1869
2258
  ...tabStyle,
1870
2259
  ...tab === id ? tabActiveStyle : {}
1871
2260
  },
1872
- children: t(id === "status" ? "tabStatus" : id === "context" ? "tabContext" : id === "details" ? "tabDetails" : "tabCheckIn")
2261
+ children: t(id === "status" ? "tabStatus" : id === "context" ? "tabContext" : id === "models" ? "tabModels" : id === "details" ? "tabDetails" : "tabCheckIn")
1873
2262
  }, id))
1874
2263
  }),
1875
2264
  tab === "status" ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
@@ -1907,6 +2296,21 @@ window.__ModuleLoader__.load({
1907
2296
  });
1908
2297
  }
1909
2298
  })
2299
+ }) : tab === "models" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2300
+ style: tabPanelStyle,
2301
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ModelSwitchTable, {
2302
+ models: status.models,
2303
+ disabledModels: status.disabledModels,
2304
+ t,
2305
+ disabled: busy,
2306
+ onSetModelsEnabled: (models, enabled) => {
2307
+ control({
2308
+ action: "set-models-enabled",
2309
+ models,
2310
+ enabled
2311
+ });
2312
+ }
2313
+ })
1910
2314
  }) : tab === "details" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1911
2315
  style: tabPanelStyle,
1912
2316
  children: status.credits === void 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
@@ -1933,6 +2337,7 @@ window.__ModuleLoader__.load({
1933
2337
  clearing: clearingLogs,
1934
2338
  disabled: status.status !== "signed-in",
1935
2339
  ...checkInNotice === void 0 ? {} : { notice: checkInNotice },
2340
+ ...status.checkIn?.nextRunAt === void 0 ? {} : { nextRun: status.checkIn.nextRunAt },
1936
2341
  onCheckIn: () => {
1937
2342
  manualCheckIn();
1938
2343
  },
@@ -3212,6 +3617,7 @@ window.__ModuleLoader__.load({
3212
3617
  creditsHeading: "Remaining credit",
3213
3618
  tabStatus: "Status",
3214
3619
  tabContext: "Context window",
3620
+ tabModels: "Model visibility",
3215
3621
  tabDetails: "Credit details",
3216
3622
  tabCheckIn: "Check-in log",
3217
3623
  checkInLogTime: "Check-in time",
@@ -3224,6 +3630,7 @@ window.__ModuleLoader__.load({
3224
3630
  checkInRefreshing: "Refreshing…",
3225
3631
  checkInClear: "Clear logs",
3226
3632
  checkInClearing: "Clearing…",
3633
+ checkInNextRun: "Next automatic check-in: {time}",
3227
3634
  creditsDetailHeading: "By package",
3228
3635
  creditsUsed: "Used this cycle: {percent}%",
3229
3636
  creditsTotalUnlimited: "Total: Unlimited",
@@ -3247,6 +3654,19 @@ window.__ModuleLoader__.load({
3247
3654
  statusRefreshFailed: "Refresh failed: {message} — showing the last known state",
3248
3655
  statusResponseInvalid: "Qoder returned an unreadable status reply",
3249
3656
  accountHeading: "Account",
3657
+ modelsHeading: "Model visibility",
3658
+ modelsSubtitle: "Choose which models are exposed to the DeepSeek Harness model selector.",
3659
+ modelsSearchPlaceholder: "Search by model name or ID…",
3660
+ modelsSelectAll: "Select all",
3661
+ modelsDeselectAll: "Deselect all",
3662
+ modelsEnableSelected: "Enable selected",
3663
+ modelsDisableSelected: "Disable selected",
3664
+ modelsEnabled: "Enabled",
3665
+ modelsDisabled: "Disabled",
3666
+ modelsBatchActions: "Batch actions",
3667
+ modelsSelectedCount: "{count} selected",
3668
+ modelsNoModels: "No models available.",
3669
+ modelsNoMatch: "No models matching \"{query}\".",
3250
3670
  contextHeading: "Context window",
3251
3671
  contextUpTo: "up to {size}",
3252
3672
  contextDefault: "default {size}",
@@ -3288,8 +3708,11 @@ window.__ModuleLoader__.load({
3288
3708
  quotaToggleHint: "Show this account’s remaining credit in the sidebar footer.",
3289
3709
  autoCheckInCN: "Qoder (China) daily auto check-in (100 Credits)",
3290
3710
  autoCheckInGlobal: "Qoder Global (International) daily auto check-in",
3291
- autoCheckInHintCN: "Automatically check in daily at 10:00 (UTC+8) to claim 100 Credits for China account.",
3292
- autoCheckInHintGlobal: "Automatically check in daily at 10:00 (UTC+8) to claim available perks for Global account.",
3711
+ autoCheckInHintCN: "Automatically check in daily to claim 100 Credits for the China account.",
3712
+ autoCheckInHintGlobal: "Automatically check in daily to claim available perks for the Global account.",
3713
+ checkInTimeCN: "Check-in time (China)",
3714
+ checkInTimeGlobal: "Check-in time (Global)",
3715
+ checkInTimeHint: "The moment the automatic check-in runs each day, in UTC+8.",
3293
3716
  autoCheckInStatusClaimed: "Checked in today (+{amount} Credits)",
3294
3717
  autoCheckInStatusAlready: "Already checked in today",
3295
3718
  autoCheckInStatusNoCampaign: "No active benefit campaign today",
@@ -3365,6 +3788,7 @@ window.__ModuleLoader__.load({
3365
3788
  creditsHeading: "剩余额度",
3366
3789
  tabStatus: "状态",
3367
3790
  tabContext: "上下文窗口",
3791
+ tabModels: "模型开关",
3368
3792
  tabDetails: "额度明细",
3369
3793
  tabCheckIn: "签到日志",
3370
3794
  checkInLogTime: "签到时间",
@@ -3377,6 +3801,7 @@ window.__ModuleLoader__.load({
3377
3801
  checkInRefreshing: "正在刷新…",
3378
3802
  checkInClear: "清空日志",
3379
3803
  checkInClearing: "正在清空…",
3804
+ checkInNextRun: "下次自动签到:{time}",
3380
3805
  creditsDetailHeading: "按套餐",
3381
3806
  creditsUsed: "本轮已用 {percent}%",
3382
3807
  creditsTotalUnlimited: "合计:不限额",
@@ -3400,6 +3825,19 @@ window.__ModuleLoader__.load({
3400
3825
  statusRefreshFailed: "刷新失败:{message} — 当前显示的是上次成功获取的状态",
3401
3826
  statusResponseInvalid: "Qoder 返回的状态数据无法识别",
3402
3827
  accountHeading: "账号",
3828
+ modelsHeading: "模型开关",
3829
+ modelsSubtitle: "控制哪些模型在 DeepSeek Harness 模型选择器中可见并可供调用。",
3830
+ modelsSearchPlaceholder: "按模型名称或 ID 搜索…",
3831
+ modelsSelectAll: "全选",
3832
+ modelsDeselectAll: "取消全选",
3833
+ modelsEnableSelected: "批量开启",
3834
+ modelsDisableSelected: "批量关闭",
3835
+ modelsEnabled: "已开启",
3836
+ modelsDisabled: "已关闭",
3837
+ modelsBatchActions: "批量操作",
3838
+ modelsSelectedCount: "已选 {count} 项",
3839
+ modelsNoModels: "暂无可配置的模型。",
3840
+ modelsNoMatch: "未找到匹配“{query}”的模型。",
3403
3841
  contextHeading: "上下文窗口",
3404
3842
  contextUpTo: "最高 {size}",
3405
3843
  contextDefault: "默认 {size}",
@@ -3441,8 +3879,11 @@ window.__ModuleLoader__.load({
3441
3879
  quotaToggleHint: "在侧栏底部展示该账号的剩余额度。",
3442
3880
  autoCheckInCN: "Qoder(国内版)每日自动签到",
3443
3881
  autoCheckInGlobal: "Qoder Global(国际版)每日自动签到",
3444
- autoCheckInHintCN: "每天 10:00 (UTC+8) 自动签到领取 100 Credits 算力额度。",
3445
- autoCheckInHintGlobal: "每天 10:00 (UTC+8) 自动检测并领取国际版可用福利额度。",
3882
+ autoCheckInHintCN: "每天自动签到,为国内版账号领取 100 Credits 算力额度。",
3883
+ autoCheckInHintGlobal: "每天自动签到,为国际版账号领取可用福利额度。",
3884
+ checkInTimeCN: "签到时间(国内版)",
3885
+ checkInTimeGlobal: "签到时间(国际版)",
3886
+ checkInTimeHint: "每天执行自动签到的时刻,按北京时间(UTC+8)。",
3446
3887
  autoCheckInStatusClaimed: "今日已自动签到(+{amount} Credits)",
3447
3888
  autoCheckInStatusAlready: "今日已完成签到",
3448
3889
  autoCheckInStatusNoCampaign: "今日无可用签到福利活动",