dsh-qoder-plugin 0.6.0 → 0.6.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/lib/bin.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { B as QoderCredentialStore, D as qoderCatalogPath, E as QoderCatalogStore, H as qoderCredentialIdentity, O as FALLBACK_QODER_MODELS, b as createQoderTransport, f as QODER_CONNECT_VERSION, i as variantFor, l as qoderHostHeartbeatPath, m as QoderUpstreamClient, r as QODER_VARIANTS, s as isHeartbeatProcessAlive, t as CHINA_VARIANT, u as readHostHeartbeat, y as validateApiKey } from "./variants-D6eeKFyY.js";
2
+ import { B as QoderCredentialStore, D as qoderCatalogPath, E as QoderCatalogStore, H as qoderCredentialIdentity, O as FALLBACK_QODER_MODELS, b as createQoderTransport, f as QODER_CONNECT_VERSION, i as variantFor, l as qoderHostHeartbeatPath, m as QoderUpstreamClient, r as QODER_VARIANTS, s as isHeartbeatProcessAlive, t as CHINA_VARIANT, u as readHostHeartbeat, y as validateApiKey } from "./variants-CATiqb4o.js";
3
3
  import { readFile } from "node:fs/promises";
4
4
  import { realpathSync } from "node:fs";
5
5
  import { fileURLToPath } from "node:url";
package/lib/client.js CHANGED
@@ -193,21 +193,40 @@ window.__ModuleLoader__.load({
193
193
  className: cx("qdp-iconButton", className)
194
194
  });
195
195
  }
196
+ /** Hairline marks under the rail — 33 marks, one every 3.125 % of the field. */
197
+ const SLIDER_RULER_MARKS = 33;
196
198
  /**
197
- * Context-window slider: a thick filled rail with a narrow vertical grab handle
198
- * at the fill's edge (the Qoder model-settings look). Pointer drags anywhere on
199
- * the surface jump and follow the pointer CONTINUOUSLY; arrows,
200
- * PageUp/PageDown and Home/End keep it keyboard operable. With `snapTo` the
201
- * value is snapped to the nearest offered window when the drag ENDS, so a
202
- * moving handle is a free position while a saved one is always an offer. The
203
- * component is fully controlled — it never writes anything by itself.
199
+ * Context-window slider, replicating the Qoder model-settings control.
200
+ *
201
+ * Geometry follows the upstream component: a 56 px field whose 18 px rail sits
202
+ * on the vertical centre and whose 12 px label row hangs 40 px below the field's
203
+ * top, 33 hairlines along the rail (every eighth one taller and darker) and a
204
+ * 2×12 px grab tick at the fill's edge. The scale starts at zero — a window's
205
+ * position is `value / max`, so 200K sits at 20 % of a 1M axis exactly as in the
206
+ * official table — and the rail itself stops at the widest offered window. Only
207
+ * the offered windows carry a label (9 px, sitting on the field colour so the
208
+ * hairlines pass behind); the one in force is the dark, medium-weight label.
209
+ *
210
+ * With `snapTo` a pointer drag moves the grab tick one tier at a time (it lands
211
+ * only on the offered windows); without offers it follows the pointer quantized
212
+ * to `step`. Arrows, PageUp/PageDown and Home/End keep it keyboard operable,
213
+ * with arrows walking the offers one by one. The component is fully controlled —
214
+ * it never writes anything by itself.
204
215
  */
205
216
  function QdpSlider({ label, value, min, max, step = 1e3, disabled, onChange, valueText, ticks, format, snapTo, testId }) {
206
217
  const formatValue = (raw) => format !== void 0 ? format(raw) : raw === value && valueText !== void 0 ? valueText : String(raw);
207
- const percentOf = (raw) => span > 0 ? Math.min(100, Math.max(0, (raw - min) / span * 100)) : 0;
218
+ /**
219
+ * Position of a window on the field, in percent.
220
+ *
221
+ * The official control's axis starts at zero (`value / maxValue`), not at the
222
+ * smallest window, so a 200K window covers the first fifth of a 1M axis on
223
+ * every row and equal windows line up across rows.
224
+ */
225
+ const percentOf = (raw) => max > 0 ? Math.min(100, Math.max(0, raw / max * 100)) : 0;
226
+ /** Label/tick transforms that keep the end marks inside the field. */
227
+ const edgeTransform = (percent) => percent >= 99.5 ? "translate(-100%, -50%)" : percent <= .5 ? "translate(0, -50%)" : "translate(-50%, -50%)";
208
228
  const trackRef = (0, react.useRef)(null);
209
229
  const span = max > min ? max - min : 0;
210
- const ratio = span > 0 ? Math.min(1, Math.max(0, (value - min) / span)) : 0;
211
230
  /** The offered values that actually fit the shared axis, ascending. */
212
231
  const anchors = (0, react.useMemo)(() => {
213
232
  if (snapTo === void 0 || snapTo.length === 0) return void 0;
@@ -218,6 +237,14 @@ window.__ModuleLoader__.load({
218
237
  min,
219
238
  snapTo
220
239
  ]);
240
+ /** Where the grab tick and the filled rail end. */
241
+ const fillPercent = percentOf(value);
242
+ /**
243
+ * The rail stops at the widest offered window, not at the axis end: a row that
244
+ * offers only 200K / 400K draws a shorter rail instead of empty track beyond
245
+ * its last tier (the official control behaves the same way).
246
+ */
247
+ const railPercent = percentOf(anchors === void 0 ? max : anchors[anchors.length - 1] ?? max);
221
248
  const snap = (0, react.useCallback)((raw) => {
222
249
  const clamped = Math.min(max, Math.max(min, raw));
223
250
  if (anchors !== void 0) {
@@ -235,24 +262,28 @@ window.__ModuleLoader__.load({
235
262
  step
236
263
  ]);
237
264
  /**
238
- * The value a live drag reports: clamped, then quantized to `step` only.
265
+ * The value a live drag reports.
239
266
  *
240
- * Deliberately NOT `snap`: dragging must not jump between the offered
241
- * windows, or the handle feels ratcheted. `step` (1 000 tokens by default) is
242
- * fine enough that the movement reads as continuous, while keeping the
243
- * displayed number free of round-off noise.
267
+ * With `snapTo` the drag advances tier by tier: every pointer move reports the
268
+ * nearest offered window, so the handle is never parked between two tiers
269
+ * (one slide, one context size) and the number under it is always a window the
270
+ * upstream declares. Without offers the drag is quantized to `step`, keeping
271
+ * the displayed number free of round-off noise.
244
272
  */
245
273
  const free = (0, react.useCallback)((raw) => {
274
+ if (anchors !== void 0) return snap(raw);
246
275
  const clamped = Math.min(max, Math.max(min, raw));
247
276
  if (step <= 0) return clamped;
248
277
  const stepped = min + Math.round((clamped - min) / step) * step;
249
278
  return Math.min(max, Math.max(min, stepped));
250
279
  }, [
280
+ anchors,
251
281
  max,
252
282
  min,
283
+ snap,
253
284
  step
254
285
  ]);
255
- /** Continuous position of the drag in flight; the release handler snaps it. */
286
+ /** Pointer position of the drag in flight, kept for the release settle. */
256
287
  const lastRaw = (0, react.useRef)(void 0);
257
288
  const fromClientX = (0, react.useCallback)((clientX) => {
258
289
  const element = trackRef.current;
@@ -279,12 +310,12 @@ window.__ModuleLoader__.load({
279
310
  fromClientX(event.clientX);
280
311
  };
281
312
  /**
282
- * End of drag: snap to the nearest offer.
313
+ * End of drag: settle on the offer nearest the pointer.
283
314
  *
284
- * `lastRaw` is the continuous position the drag ended at, not `value` — the
285
- * controlled parent may still be rendering the previous tick when the release
286
- * lands, so reading the raw pointer position is what makes the snap land
287
- * where the user let go.
315
+ * A drag that has offers already reports one on every move, so this only
316
+ * matters for the last finger position: `lastRaw` is the pointer position the
317
+ * drag ended at, not `value` — the controlled parent may still be rendering
318
+ * the previous tick when the release lands.
288
319
  */
289
320
  const release = (event) => {
290
321
  if (event.currentTarget.hasPointerCapture(event.pointerId)) event.currentTarget.releasePointerCapture(event.pointerId);
@@ -316,10 +347,10 @@ window.__ModuleLoader__.load({
316
347
  event.preventDefault();
317
348
  if (next !== value) onChange(next);
318
349
  };
319
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
350
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
320
351
  className: "qdp-sliderField",
321
352
  "data-testid": testId,
322
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
353
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
323
354
  className: "qdp-slider",
324
355
  role: "slider",
325
356
  "aria-label": label,
@@ -334,25 +365,46 @@ window.__ModuleLoader__.load({
334
365
  onPointerUp: release,
335
366
  onPointerCancel: release,
336
367
  onKeyDown,
337
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
368
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
338
369
  className: "qdp-sliderTrack",
339
370
  ref: trackRef,
340
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
341
- className: "qdp-sliderFill",
342
- style: { width: `${(ratio * 100).toFixed(2)}%` }
343
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
344
- className: "qdp-sliderThumb",
345
- style: { left: `${(ratio * 100).toFixed(2)}%` }
371
+ children: [
372
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
373
+ className: "qdp-sliderRail",
374
+ style: { width: `${railPercent.toFixed(2)}%` }
375
+ }),
376
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
377
+ className: "qdp-sliderFill",
378
+ style: { width: `${fillPercent.toFixed(2)}%` }
379
+ }),
380
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
381
+ className: "qdp-sliderThumb",
382
+ style: { left: `calc(${fillPercent.toFixed(2)}% - 5px)` }
383
+ })
384
+ ]
385
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
386
+ className: "qdp-windowTicks",
387
+ children: [Array.from({ length: SLIDER_RULER_MARKS }, (_, index) => {
388
+ const percent = index / 32 * 100;
389
+ if (percent > railPercent + .01) return null;
390
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
391
+ "aria-hidden": "true",
392
+ className: cx("qdp-windowTickMark", index % 8 === 0 && "qdp-windowTickMarkMajor"),
393
+ style: { left: `${percent.toFixed(2)}%` }
394
+ }, `mark-${index}`);
395
+ }), (ticks ?? []).map((tick) => {
396
+ const percent = percentOf(tick);
397
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
398
+ className: cx("qdp-windowTick", tick === value && "qdp-windowTickActive"),
399
+ style: {
400
+ left: `${percent.toFixed(2)}%`,
401
+ transform: edgeTransform(percent)
402
+ },
403
+ children: formatValue(tick)
404
+ }, tick);
346
405
  })]
347
- })
348
- }), ticks !== void 0 && ticks.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
349
- className: "qdp-windowTicks",
350
- children: ticks.map((tick) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
351
- className: "qdp-windowTick",
352
- style: { left: `${percentOf(tick).toFixed(2)}%` },
353
- children: formatValue(tick)
354
- }, tick))
355
- })]
406
+ })]
407
+ })
356
408
  });
357
409
  }
358
410
  //#endregion
@@ -405,19 +457,20 @@ window.__ModuleLoader__.load({
405
457
  return `${factor.toFixed(1)}x`;
406
458
  }
407
459
  /**
408
- * The reasoning-effort tag's text, or `undefined` when the model advertises no
409
- * selectable efforts.
460
+ * The reasoning-effort tag's text: the levels the model can reason at, plus the
461
+ * upstream default.
410
462
  *
411
- * Wire ids are translated through the locale (unknown ids fall back to their
412
- * raw spelling), and the upstream's default effort is called out so the user
413
- * can see which level the model actually runs at until they change it.
463
+ * The tag speaks the upstream's English wire vocabulary (`low`, `high`,
464
+ * `xhigh`, `max`, …) in every UI language — the words are model parameters, and
465
+ * the official Qoder app lists them untranslated. A model that advertises no
466
+ * selectable effort says so instead of drawing an empty tag.
414
467
  */
415
468
  function effortsTagText(model, t) {
416
469
  const efforts = (model.reasoningEfforts ?? []).filter((id) => id !== "");
417
- if (efforts.length === 0) return void 0;
470
+ if (efforts.length === 0) return t("effortsUnsupported");
418
471
  const nameOf = (id) => id === "low" ? t("effortLow") : id === "medium" ? t("effortMedium") : id === "high" ? t("effortHigh") : id === "xhigh" ? t("effortXhigh") : id === "max" ? t("effortMax") : id === "minimal" ? t("effortMinimal") : id;
419
472
  const levels = efforts.map(nameOf).join(" · ");
420
- const fallback = model.defaultReasoningEffort !== void 0 && efforts.includes(model.defaultReasoningEffort) ? `(${t("modelEffortsDefault", { name: nameOf(model.defaultReasoningEffort) })})` : "";
473
+ const fallback = model.defaultReasoningEffort !== void 0 && efforts.includes(model.defaultReasoningEffort) ? ` (${t("modelEffortsDefault", { name: nameOf(model.defaultReasoningEffort) })})` : "";
421
474
  return t("modelEfforts", { levels }) + fallback;
422
475
  }
423
476
  /** Round an axis end up to a clean K/M boundary so tick labels stay readable. */
@@ -446,19 +499,17 @@ window.__ModuleLoader__.load({
446
499
  const clampWindow = (value, min, max) => Math.min(max, Math.max(min, value));
447
500
  const uniqueSorted = (ids) => [...new Set(ids)].sort((a, b) => a.localeCompare(b));
448
501
  /**
449
- * Marks under a row's track: the model's declared windows plus both axis ends,
450
- * so the shared scale stays readable (contract: min on the left, axisMax on the
451
- * right). The endpoint labels are the same on every row, which is what lets a
452
- * 400K on one row line up with a 400K on the next.
502
+ * The windows this row offers as tiers, clipped to the shared axis.
503
+ *
504
+ * These are exactly the values the slider lands on and the marks it draws; the
505
+ * shared axis ENDS are deliberately not added. On a row whose narrowest offer
506
+ * sits close to the global minimum (the international roster's Performance
507
+ * offers 272K while the shared minimum is 200K) the extra minimum label
508
+ * overlapped the row's own first label. The scale is still shared, so a 400K on
509
+ * one row keeps lining up with a 400K on the next.
453
510
  */
454
- function rowTicks(model, min, max) {
455
- const declared = declaredWindows(model);
456
- const marks = declared.length > 0 ? [
457
- min,
458
- ...declared,
459
- max
460
- ] : [min, max];
461
- return [...new Set(marks)].filter((value) => value >= min && value <= max).sort((a, b) => a - b);
511
+ function rowTiers(model, min, max) {
512
+ return declaredWindows(model).filter((value) => value >= min && value <= max);
462
513
  }
463
514
  /**
464
515
  * Signature of everything the draft is based on. When it changes the draft is
@@ -566,6 +617,7 @@ window.__ModuleLoader__.load({
566
617
  const value = draft.windows[model.id] ?? baseline;
567
618
  const current = value === void 0 ? void 0 : clampWindow(value, minWindow, axisMax);
568
619
  const effortsText = effortsTagText(model, t);
620
+ const tiers = rowTiers(model, minWindow, axisMax);
569
621
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
570
622
  className: "qdp-modelRow",
571
623
  "data-model-id": model.id,
@@ -593,11 +645,11 @@ window.__ModuleLoader__.load({
593
645
  })
594
646
  }),
595
647
  model.priceFactor === void 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(QdpTag, { children: formatRate(model.priceFactor) }),
596
- effortsText === void 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(QdpTag, { children: effortsText }),
597
648
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
598
649
  className: "qdp-modelMeta",
599
650
  children: model.id
600
- })
651
+ }),
652
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(QdpTag, { children: effortsText })
601
653
  ]
602
654
  }),
603
655
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
@@ -614,8 +666,8 @@ window.__ModuleLoader__.load({
614
666
  disabled: controlsDisabled,
615
667
  onChange: (next) => changeWindow(model, next),
616
668
  valueText: formatTokens(current),
617
- ...model.supportedContextWindows === void 0 ? {} : { snapTo: model.supportedContextWindows },
618
- ticks: rowTicks(model, minWindow, axisMax),
669
+ snapTo: tiers,
670
+ ticks: tiers,
619
671
  format: formatTokens,
620
672
  testId: `qdp-window-${model.id}`
621
673
  })
@@ -3592,49 +3644,55 @@ window.__ModuleLoader__.load({
3592
3644
 
3593
3645
  /* ---------------------------------------------------------------- sliders */
3594
3646
 
3647
+ /* The official Qoder model-settings slider: a 56 px field, an 18 px rail on the
3648
+ vertical centre, a 2 × 12 px grab tick at the fill's edge and a 12 px label
3649
+ row hanging 40 px below the field's top. The rail is a soft neutral and the
3650
+ fill a 42 % brand tint, so the grab tick reads as the only strong mark. */
3595
3651
  .qdp-slider {
3596
3652
  position: relative;
3597
- display: flex;
3598
- align-items: center;
3599
- height: 32px;
3600
- padding: 0 2px;
3653
+ width: 100%;
3654
+ max-width: 252px;
3655
+ height: 56px;
3601
3656
  border-radius: var(--dsw-radius-xs);
3602
3657
  cursor: pointer;
3603
3658
  touch-action: none;
3604
3659
  user-select: none;
3605
3660
  }
3606
3661
  .qdp-slider[aria-disabled='true'] {
3607
- opacity: 0.5;
3662
+ opacity: 0.55;
3608
3663
  cursor: default;
3609
3664
  }
3610
3665
  .qdp-sliderTrack {
3611
- position: relative;
3612
- width: 100%;
3613
- height: 12px;
3614
- border-radius: 999px;
3615
- corner-shape: round;
3616
- background: var(--dsw-alias-interactive-bg-hover);
3666
+ position: absolute;
3667
+ top: 50%;
3668
+ right: 0;
3669
+ left: 0;
3670
+ height: 18px;
3671
+ transform: translateY(-50%);
3617
3672
  }
3673
+ .qdp-sliderRail,
3618
3674
  .qdp-sliderFill {
3619
3675
  position: absolute;
3620
3676
  top: 0;
3621
3677
  left: 0;
3622
3678
  height: 100%;
3623
- border-radius: 999px;
3624
- corner-shape: round;
3625
- /* A solid, readable bar (the Qoder model-settings look): the fill is a
3626
- strong brand tint, the handle the same colour at full strength. */
3627
- background: var(--dsw-alias-state-business-primary);
3628
- opacity: 0.42;
3679
+ border-radius: var(--dsw-radius-xs);
3680
+ }
3681
+ .qdp-sliderRail {
3682
+ background: var(--dsw-alias-interactive-bg-hover);
3683
+ }
3684
+ /* The chosen stretch is a quiet neutral, exactly like the upstream rail: the
3685
+ strong mark on the control is the grab tick, not a saturated fill. */
3686
+ .qdp-sliderFill {
3687
+ background: var(--dsw-alias-border-l3);
3629
3688
  }
3630
3689
  .qdp-sliderThumb {
3631
3690
  position: absolute;
3632
- top: 50%;
3633
- width: 4px;
3634
- height: 20px;
3635
- border-radius: 2px;
3691
+ top: 3px;
3692
+ width: 2px;
3693
+ height: 12px;
3694
+ border-radius: 1px;
3636
3695
  background: var(--dsw-alias-state-business-primary);
3637
- transform: translate(-50%, -50%);
3638
3696
  }
3639
3697
 
3640
3698
  /* ----------------------------------------------------------------- models */
@@ -3713,29 +3771,53 @@ window.__ModuleLoader__.load({
3713
3771
  }
3714
3772
  .qdp-sliderField {
3715
3773
  position: relative;
3716
- display: flex;
3717
- flex-direction: column;
3718
- gap: 2px;
3719
3774
  min-width: 0;
3720
3775
  }
3721
3776
  .qdp-windowTicks {
3722
- position: relative;
3777
+ position: absolute;
3778
+ top: 40px;
3779
+ right: 0;
3780
+ left: 0;
3723
3781
  height: 12px;
3724
- margin: 0 2px;
3782
+ pointer-events: none;
3783
+ }
3784
+ /* Hairline ruler under the rail: 33 marks across the field, every eighth one
3785
+ taller and a step darker, matching the official scale. */
3786
+ .qdp-windowTickMark {
3787
+ position: absolute;
3788
+ top: 50%;
3789
+ width: 1px;
3790
+ height: 6px;
3791
+ border-radius: 999px;
3792
+ background: var(--dsw-alias-border-l2);
3793
+ transform: translate(-50%, -50%);
3725
3794
  }
3795
+ .qdp-windowTickMarkMajor {
3796
+ height: 8px;
3797
+ background: var(--dsw-alias-border-l3);
3798
+ }
3799
+ /* Tier labels sit on the field colour so the ruler passes behind them. */
3726
3800
  .qdp-windowTick {
3727
3801
  position: absolute;
3728
- transform: translateX(-50%);
3802
+ top: 50%;
3803
+ padding: 0 4px;
3804
+ background: var(--dsw-alias-settings-card-fill);
3729
3805
  font: var(--dsw-font-xxxs-11);
3806
+ font-size: 9px;
3807
+ line-height: 12px;
3730
3808
  color: var(--dsw-alias-label-tertiary);
3731
3809
  font-variant-numeric: tabular-nums;
3732
3810
  white-space: nowrap;
3733
3811
  }
3734
- .qdp-windowTick:first-child {
3735
- transform: none;
3812
+ /* The window in force is the only dark number: the other tiers are offers the
3813
+ user has not selected, so they keep the tertiary (grey) tone. */
3814
+ .qdp-windowTickActive {
3815
+ color: var(--dsw-alias-label-primary);
3816
+ font-weight: 500;
3736
3817
  }
3737
- .qdp-windowTick:last-child {
3738
- transform: translateX(-100%);
3818
+ /* A disabled slider greys every label, the active one included. */
3819
+ .qdp-slider[aria-disabled='true'] .qdp-windowTick {
3820
+ color: var(--dsw-alias-label-caption);
3739
3821
  }
3740
3822
 
3741
3823
  /* --------------------------------------------------------------- save bar */
@@ -4223,6 +4305,7 @@ window.__ModuleLoader__.load({
4223
4305
  effortHigh: "high",
4224
4306
  effortXhigh: "xhigh",
4225
4307
  effortMax: "max",
4308
+ effortsUnsupported: "not supported",
4226
4309
  accountCurrent: "In use",
4227
4310
  creditsRemaining: "Remaining credit",
4228
4311
  checkInStatus: "Check-in",
@@ -4426,14 +4509,15 @@ window.__ModuleLoader__.load({
4426
4509
  quotaReadoutEnabledLabel: "在对话框显示积分",
4427
4510
  quotaReadoutEnabledDesc: "在输入框工具条上显示剩余积分标签,点击可展开明细面板。",
4428
4511
  checkInTime: "签到时间",
4429
- modelEfforts: "思考:{levels}",
4430
- modelEffortsDefault: "默认{name}",
4431
- effortMinimal: "最低",
4432
- effortLow: "低",
4433
- effortMedium: "中",
4434
- effortHigh: "高",
4435
- effortXhigh: "超高",
4436
- effortMax: "最大",
4512
+ modelEfforts: "Efforts: {levels}",
4513
+ modelEffortsDefault: "default {name}",
4514
+ effortMinimal: "minimal",
4515
+ effortLow: "low",
4516
+ effortMedium: "medium",
4517
+ effortHigh: "high",
4518
+ effortXhigh: "xhigh",
4519
+ effortMax: "max",
4520
+ effortsUnsupported: "not supported",
4437
4521
  accountCurrent: "当前使用",
4438
4522
  creditsRemaining: "剩余积分",
4439
4523
  checkInStatus: "签到状态",
package/lib/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { A as QODER_AUTH_PATH, B as QoderCredentialStore, C as PROBE_EFFORT_CANDIDATES, D as qoderCatalogPath, E as QoderCatalogStore, F as QODER_SETTINGS_FACE_PATH, G as QODER_DATA_DIR_NAME, H as qoderCredentialIdentity, I as QODER_STATUS_PATH, J as qoderStateDir, K as qoderMachineIdPath, L as QODER_AUTH_FILENAME, M as QODER_GLOBAL_PROBE_PATH, N as QODER_GLOBAL_STATUS_PATH, O as FALLBACK_QODER_MODELS, P as QODER_PROBE_PATH, R as QODER_PAT_ENV_CN, S as getMachineId, T as randomSentinel, U as qoderOwnAuthPath, V as patTail, W as QODER_DATA_DIR_ENV, _ as modelInfoOf, a as QODER_HOST_HEARTBEAT_FILENAME, b as createQoderTransport, c as processStartTimeMs, d as writeHostHeartbeat, f as QODER_CONNECT_VERSION, g as kindFromQoderFailure, h as classifyUpstreamError, i as variantFor, j as QODER_GLOBAL_AUTH_PATH, k as QoderCatalog, l as qoderHostHeartbeatPath, m as QoderUpstreamClient, n as GLOBAL_VARIANT, o as clearHostHeartbeat, p as KIND_STATUS, q as qoderPluginDataDir, r as QODER_VARIANTS, s as isHeartbeatProcessAlive, t as CHINA_VARIANT, u as readHostHeartbeat, v as normalizeCredits, w as probeModel, x as getClaimWindowDateString, y as validateApiKey, z as QODER_PAT_ENV_GLOBAL } from "./variants-D6eeKFyY.js";
1
+ import { A as QODER_AUTH_PATH, B as QoderCredentialStore, C as PROBE_EFFORT_CANDIDATES, D as qoderCatalogPath, E as QoderCatalogStore, F as QODER_SETTINGS_FACE_PATH, G as QODER_DATA_DIR_NAME, H as qoderCredentialIdentity, I as QODER_STATUS_PATH, J as qoderStateDir, K as qoderMachineIdPath, L as QODER_AUTH_FILENAME, M as QODER_GLOBAL_PROBE_PATH, N as QODER_GLOBAL_STATUS_PATH, O as FALLBACK_QODER_MODELS, P as QODER_PROBE_PATH, R as QODER_PAT_ENV_CN, S as getMachineId, T as randomSentinel, U as qoderOwnAuthPath, V as patTail, W as QODER_DATA_DIR_ENV, _ as modelInfoOf, a as QODER_HOST_HEARTBEAT_FILENAME, b as createQoderTransport, c as processStartTimeMs, d as writeHostHeartbeat, f as QODER_CONNECT_VERSION, g as kindFromQoderFailure, h as classifyUpstreamError, i as variantFor, j as QODER_GLOBAL_AUTH_PATH, k as QoderCatalog, l as qoderHostHeartbeatPath, m as QoderUpstreamClient, n as GLOBAL_VARIANT, o as clearHostHeartbeat, p as KIND_STATUS, q as qoderPluginDataDir, r as QODER_VARIANTS, s as isHeartbeatProcessAlive, t as CHINA_VARIANT, u as readHostHeartbeat, v as normalizeCredits, w as probeModel, x as getClaimWindowDateString, y as validateApiKey, z as QODER_PAT_ENV_GLOBAL } from "./variants-CATiqb4o.js";
2
2
  import z from "@deepseek-ai/schemastery";
3
3
  import { createHash, randomBytes, timingSafeEqual } from "node:crypto";
4
4
  import { dirname, join, resolve } from "node:path";
@@ -4767,7 +4767,7 @@ const DEFAULT_MAX_TOKENS = 32768;
4767
4767
  const DEFAULT_CONTEXT_WINDOW = 18e4;
4768
4768
  //#endregion
4769
4769
  //#region src/version.ts
4770
- const QODER_CONNECT_VERSION = "0.6.0";
4770
+ const QODER_CONNECT_VERSION = "0.6.3";
4771
4771
  //#endregion
4772
4772
  //#region src/host-heartbeat.ts
4773
4773
  /**
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "dsh-qoder-plugin",
3
3
  "displayName": "dsh-qoder-plugin",
4
4
  "description": "把 Qoder 模型接入 DeepSeek Harness:用 PAT 调用与 Qoder CLI 同源的模型服务,支持国内版 / 国际版双区域、模型开关、上下文窗口与每日签到,并提供只读的额度概览。",
5
- "version": "0.6.0",
5
+ "version": "0.6.3",
6
6
  "author": "corrinehu",
7
7
  "keywords": [
8
8
  "dsh-plugin",