dsh-qoder-plugin 0.6.0 → 0.6.4
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 +1 -1
- package/lib/client.js +250 -151
- package/lib/index.js +1 -1
- package/lib/{variants-D6eeKFyY.js → variants--jTtaG59.js} +1 -1
- package/package.json +1 -1
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
|
|
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--jTtaG59.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
|
|
198
|
-
*
|
|
199
|
-
* the
|
|
200
|
-
*
|
|
201
|
-
*
|
|
202
|
-
*
|
|
203
|
-
*
|
|
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
|
-
|
|
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
|
|
265
|
+
* The value a live drag reports.
|
|
239
266
|
*
|
|
240
|
-
*
|
|
241
|
-
*
|
|
242
|
-
*
|
|
243
|
-
*
|
|
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
|
-
/**
|
|
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:
|
|
313
|
+
* End of drag: settle on the offer nearest the pointer.
|
|
283
314
|
*
|
|
284
|
-
*
|
|
285
|
-
*
|
|
286
|
-
*
|
|
287
|
-
*
|
|
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.
|
|
350
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
320
351
|
className: "qdp-sliderField",
|
|
321
352
|
"data-testid": testId,
|
|
322
|
-
children:
|
|
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: [
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
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
|
-
})
|
|
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,20 +457,19 @@ window.__ModuleLoader__.load({
|
|
|
405
457
|
return `${factor.toFixed(1)}x`;
|
|
406
458
|
}
|
|
407
459
|
/**
|
|
408
|
-
* The reasoning-effort tag's text
|
|
409
|
-
*
|
|
460
|
+
* The reasoning-effort tag's text: the levels the model can reason at, plus the
|
|
461
|
+
* upstream default.
|
|
410
462
|
*
|
|
411
|
-
*
|
|
412
|
-
*
|
|
413
|
-
*
|
|
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
|
|
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
|
-
|
|
420
|
-
const fallback = model.defaultReasoningEffort !== void 0 && efforts.includes(model.defaultReasoningEffort) ? `(${t("modelEffortsDefault", { name: nameOf(model.defaultReasoningEffort) })})` : "";
|
|
421
|
-
return t("modelEfforts", { levels }) + fallback;
|
|
472
|
+
return efforts.map(nameOf).join(" · ") + (model.defaultReasoningEffort !== void 0 && efforts.includes(model.defaultReasoningEffort) ? ` (${t("modelEffortsDefault", { name: nameOf(model.defaultReasoningEffort) })})` : "");
|
|
422
473
|
}
|
|
423
474
|
/** Round an axis end up to a clean K/M boundary so tick labels stay readable. */
|
|
424
475
|
function roundUpAxis(value) {
|
|
@@ -446,19 +497,17 @@ window.__ModuleLoader__.load({
|
|
|
446
497
|
const clampWindow = (value, min, max) => Math.min(max, Math.max(min, value));
|
|
447
498
|
const uniqueSorted = (ids) => [...new Set(ids)].sort((a, b) => a.localeCompare(b));
|
|
448
499
|
/**
|
|
449
|
-
*
|
|
450
|
-
*
|
|
451
|
-
*
|
|
452
|
-
*
|
|
500
|
+
* The windows this row offers as tiers, clipped to the shared axis.
|
|
501
|
+
*
|
|
502
|
+
* These are exactly the values the slider lands on and the marks it draws; the
|
|
503
|
+
* shared axis ENDS are deliberately not added. On a row whose narrowest offer
|
|
504
|
+
* sits close to the global minimum (the international roster's Performance
|
|
505
|
+
* offers 272K while the shared minimum is 200K) the extra minimum label
|
|
506
|
+
* overlapped the row's own first label. The scale is still shared, so a 400K on
|
|
507
|
+
* one row keeps lining up with a 400K on the next.
|
|
453
508
|
*/
|
|
454
|
-
function
|
|
455
|
-
|
|
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);
|
|
509
|
+
function rowTiers(model, min, max) {
|
|
510
|
+
return declaredWindows(model).filter((value) => value >= min && value <= max);
|
|
462
511
|
}
|
|
463
512
|
/**
|
|
464
513
|
* Signature of everything the draft is based on. When it changes the draft is
|
|
@@ -557,6 +606,7 @@ window.__ModuleLoader__.load({
|
|
|
557
606
|
children: [
|
|
558
607
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { "aria-hidden": "true" }),
|
|
559
608
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("modelNameColumn") }),
|
|
609
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("effortsHeading") }),
|
|
560
610
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("contextHeading") })
|
|
561
611
|
]
|
|
562
612
|
}), list.map((model) => {
|
|
@@ -566,6 +616,7 @@ window.__ModuleLoader__.load({
|
|
|
566
616
|
const value = draft.windows[model.id] ?? baseline;
|
|
567
617
|
const current = value === void 0 ? void 0 : clampWindow(value, minWindow, axisMax);
|
|
568
618
|
const effortsText = effortsTagText(model, t);
|
|
619
|
+
const tiers = rowTiers(model, minWindow, axisMax);
|
|
569
620
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
570
621
|
className: "qdp-modelRow",
|
|
571
622
|
"data-model-id": model.id,
|
|
@@ -593,13 +644,16 @@ window.__ModuleLoader__.load({
|
|
|
593
644
|
})
|
|
594
645
|
}),
|
|
595
646
|
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
647
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
598
648
|
className: "qdp-modelMeta",
|
|
599
649
|
children: model.id
|
|
600
650
|
})
|
|
601
651
|
]
|
|
602
652
|
}),
|
|
653
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
654
|
+
className: "qdp-modelEfforts",
|
|
655
|
+
children: effortsText
|
|
656
|
+
}),
|
|
603
657
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
604
658
|
className: "qdp-modelAxis",
|
|
605
659
|
children: current === void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
@@ -614,8 +668,8 @@ window.__ModuleLoader__.load({
|
|
|
614
668
|
disabled: controlsDisabled,
|
|
615
669
|
onChange: (next) => changeWindow(model, next),
|
|
616
670
|
valueText: formatTokens(current),
|
|
617
|
-
|
|
618
|
-
ticks:
|
|
671
|
+
snapTo: tiers,
|
|
672
|
+
ticks: tiers,
|
|
619
673
|
format: formatTokens,
|
|
620
674
|
testId: `qdp-window-${model.id}`
|
|
621
675
|
})
|
|
@@ -2083,6 +2137,36 @@ window.__ModuleLoader__.load({
|
|
|
2083
2137
|
})
|
|
2084
2138
|
})]
|
|
2085
2139
|
}),
|
|
2140
|
+
settings.status === "unavailable" ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2141
|
+
className: "qdp-row",
|
|
2142
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2143
|
+
className: "qdp-rowText",
|
|
2144
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2145
|
+
className: "qdp-rowTitle",
|
|
2146
|
+
children: t("quotaPollLabel")
|
|
2147
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2148
|
+
className: "qdp-rowDesc",
|
|
2149
|
+
children: t("quotaPollHint")
|
|
2150
|
+
})]
|
|
2151
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2152
|
+
className: "qdp-rowControl",
|
|
2153
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(QdpInput, {
|
|
2154
|
+
className: "qdp-inputShort",
|
|
2155
|
+
type: "number",
|
|
2156
|
+
min: 1,
|
|
2157
|
+
step: 1,
|
|
2158
|
+
value: pollMinutes,
|
|
2159
|
+
"aria-label": t("quotaPollLabel"),
|
|
2160
|
+
onChange: (event) => {
|
|
2161
|
+
const minutes = Number.parseInt(event.target.value, 10);
|
|
2162
|
+
if (Number.isFinite(minutes) && minutes >= 1) writePollMinutes(minutes);
|
|
2163
|
+
}
|
|
2164
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2165
|
+
className: "qdp-caption",
|
|
2166
|
+
children: t("quotaPollUnit")
|
|
2167
|
+
})]
|
|
2168
|
+
})]
|
|
2169
|
+
}),
|
|
2086
2170
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2087
2171
|
className: "qdp-row",
|
|
2088
2172
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
@@ -2125,36 +2209,6 @@ window.__ModuleLoader__.load({
|
|
|
2125
2209
|
})
|
|
2126
2210
|
})]
|
|
2127
2211
|
}),
|
|
2128
|
-
settings.status === "unavailable" ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2129
|
-
className: "qdp-row",
|
|
2130
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2131
|
-
className: "qdp-rowText",
|
|
2132
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2133
|
-
className: "qdp-rowTitle",
|
|
2134
|
-
children: t("quotaPollLabel")
|
|
2135
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2136
|
-
className: "qdp-rowDesc",
|
|
2137
|
-
children: t("quotaPollHint")
|
|
2138
|
-
})]
|
|
2139
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2140
|
-
className: "qdp-rowControl",
|
|
2141
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(QdpInput, {
|
|
2142
|
-
className: "qdp-inputShort",
|
|
2143
|
-
type: "number",
|
|
2144
|
-
min: 1,
|
|
2145
|
-
step: 1,
|
|
2146
|
-
value: pollMinutes,
|
|
2147
|
-
"aria-label": t("quotaPollLabel"),
|
|
2148
|
-
onChange: (event) => {
|
|
2149
|
-
const minutes = Number.parseInt(event.target.value, 10);
|
|
2150
|
-
if (Number.isFinite(minutes) && minutes >= 1) writePollMinutes(minutes);
|
|
2151
|
-
}
|
|
2152
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2153
|
-
className: "qdp-caption",
|
|
2154
|
-
children: t("quotaPollUnit")
|
|
2155
|
-
})]
|
|
2156
|
-
})]
|
|
2157
|
-
}),
|
|
2158
2212
|
settings.status === "ready" && !settings.writable ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
2159
2213
|
className: "qdp-error",
|
|
2160
2214
|
children: t("quotaSettingsSaveFailed")
|
|
@@ -3592,56 +3646,66 @@ window.__ModuleLoader__.load({
|
|
|
3592
3646
|
|
|
3593
3647
|
/* ---------------------------------------------------------------- sliders */
|
|
3594
3648
|
|
|
3649
|
+
/* The official Qoder model-settings slider: a 56 px field, an 18 px rail on the
|
|
3650
|
+
vertical centre, a 2 × 12 px grab tick at the fill's edge and a 12 px label
|
|
3651
|
+
row hanging 40 px below the field's top. The rail is a soft neutral and the
|
|
3652
|
+
fill a 42 % brand tint, so the grab tick reads as the only strong mark. */
|
|
3595
3653
|
.qdp-slider {
|
|
3596
3654
|
position: relative;
|
|
3597
|
-
|
|
3598
|
-
|
|
3599
|
-
height:
|
|
3600
|
-
padding: 0 2px;
|
|
3655
|
+
width: 100%;
|
|
3656
|
+
max-width: 252px;
|
|
3657
|
+
height: 56px;
|
|
3601
3658
|
border-radius: var(--dsw-radius-xs);
|
|
3602
3659
|
cursor: pointer;
|
|
3603
3660
|
touch-action: none;
|
|
3604
3661
|
user-select: none;
|
|
3605
3662
|
}
|
|
3606
3663
|
.qdp-slider[aria-disabled='true'] {
|
|
3607
|
-
opacity: 0.
|
|
3664
|
+
opacity: 0.55;
|
|
3608
3665
|
cursor: default;
|
|
3609
3666
|
}
|
|
3610
3667
|
.qdp-sliderTrack {
|
|
3611
|
-
position:
|
|
3612
|
-
|
|
3613
|
-
|
|
3614
|
-
|
|
3615
|
-
|
|
3616
|
-
|
|
3668
|
+
position: absolute;
|
|
3669
|
+
top: 50%;
|
|
3670
|
+
right: 0;
|
|
3671
|
+
left: 0;
|
|
3672
|
+
height: 18px;
|
|
3673
|
+
transform: translateY(-50%);
|
|
3617
3674
|
}
|
|
3675
|
+
.qdp-sliderRail,
|
|
3618
3676
|
.qdp-sliderFill {
|
|
3619
3677
|
position: absolute;
|
|
3620
3678
|
top: 0;
|
|
3621
3679
|
left: 0;
|
|
3622
3680
|
height: 100%;
|
|
3623
|
-
border-radius:
|
|
3624
|
-
|
|
3625
|
-
|
|
3626
|
-
|
|
3627
|
-
|
|
3628
|
-
|
|
3681
|
+
border-radius: var(--dsw-radius-xs);
|
|
3682
|
+
}
|
|
3683
|
+
.qdp-sliderRail {
|
|
3684
|
+
background: var(--dsw-alias-interactive-bg-hover);
|
|
3685
|
+
}
|
|
3686
|
+
/* The chosen stretch is a quiet neutral, exactly like the upstream rail: the
|
|
3687
|
+
strong mark on the control is the grab tick, not a saturated fill. */
|
|
3688
|
+
.qdp-sliderFill {
|
|
3689
|
+
background: var(--dsw-alias-border-l3);
|
|
3629
3690
|
}
|
|
3630
3691
|
.qdp-sliderThumb {
|
|
3631
3692
|
position: absolute;
|
|
3632
|
-
top:
|
|
3633
|
-
width:
|
|
3634
|
-
height:
|
|
3635
|
-
border-radius:
|
|
3693
|
+
top: 3px;
|
|
3694
|
+
width: 2px;
|
|
3695
|
+
height: 12px;
|
|
3696
|
+
border-radius: 1px;
|
|
3636
3697
|
background: var(--dsw-alias-state-business-primary);
|
|
3637
|
-
transform: translate(-50%, -50%);
|
|
3638
3698
|
}
|
|
3639
3699
|
|
|
3640
3700
|
/* ----------------------------------------------------------------- models */
|
|
3641
3701
|
|
|
3642
3702
|
.qdp-modelScroll {
|
|
3643
3703
|
max-height: 420px;
|
|
3704
|
+
/* Vertical scrolling only: a horizontal bar under the roster was pure noise,
|
|
3705
|
+
and the extra right padding keeps the scrollbar off the context slider. */
|
|
3706
|
+
overflow-x: hidden;
|
|
3644
3707
|
overflow-y: auto;
|
|
3708
|
+
padding-right: 12px;
|
|
3645
3709
|
overscroll-behavior: contain;
|
|
3646
3710
|
}
|
|
3647
3711
|
.qdp-modelColumns {
|
|
@@ -3649,8 +3713,8 @@ window.__ModuleLoader__.load({
|
|
|
3649
3713
|
top: 0;
|
|
3650
3714
|
z-index: 1;
|
|
3651
3715
|
display: grid;
|
|
3652
|
-
grid-template-columns: auto minmax(0, 1fr) 232px;
|
|
3653
|
-
gap:
|
|
3716
|
+
grid-template-columns: auto minmax(0, 1fr) minmax(0, 1.15fr) 232px;
|
|
3717
|
+
gap: 12px;
|
|
3654
3718
|
align-items: center;
|
|
3655
3719
|
padding: 4px 0 4px;
|
|
3656
3720
|
border-bottom: 0.5px solid var(--dsw-alias-border-l2);
|
|
@@ -3660,8 +3724,8 @@ window.__ModuleLoader__.load({
|
|
|
3660
3724
|
}
|
|
3661
3725
|
.qdp-modelRow {
|
|
3662
3726
|
display: grid;
|
|
3663
|
-
grid-template-columns: auto minmax(0, 1fr) 232px;
|
|
3664
|
-
gap:
|
|
3727
|
+
grid-template-columns: auto minmax(0, 1fr) minmax(0, 1.15fr) 232px;
|
|
3728
|
+
gap: 12px;
|
|
3665
3729
|
align-items: center;
|
|
3666
3730
|
min-height: 44px;
|
|
3667
3731
|
padding: 6px 0;
|
|
@@ -3708,34 +3772,67 @@ window.__ModuleLoader__.load({
|
|
|
3708
3772
|
color: var(--dsw-alias-label-caption);
|
|
3709
3773
|
font-variant-numeric: tabular-nums;
|
|
3710
3774
|
}
|
|
3775
|
+
/* The effort column: the tiers themselves, no "Efforts:" prefix — the column
|
|
3776
|
+
header says what they are. */
|
|
3777
|
+
.qdp-modelEfforts {
|
|
3778
|
+
min-width: 0;
|
|
3779
|
+
font: var(--dsw-font-xxs-12);
|
|
3780
|
+
color: var(--dsw-alias-label-secondary);
|
|
3781
|
+
font-variant-numeric: tabular-nums;
|
|
3782
|
+
overflow-wrap: anywhere;
|
|
3783
|
+
}
|
|
3711
3784
|
.qdp-modelAxis {
|
|
3712
3785
|
min-width: 0;
|
|
3713
3786
|
}
|
|
3714
3787
|
.qdp-sliderField {
|
|
3715
3788
|
position: relative;
|
|
3716
|
-
display: flex;
|
|
3717
|
-
flex-direction: column;
|
|
3718
|
-
gap: 2px;
|
|
3719
3789
|
min-width: 0;
|
|
3720
3790
|
}
|
|
3721
3791
|
.qdp-windowTicks {
|
|
3722
|
-
position:
|
|
3792
|
+
position: absolute;
|
|
3793
|
+
top: 40px;
|
|
3794
|
+
right: 0;
|
|
3795
|
+
left: 0;
|
|
3723
3796
|
height: 12px;
|
|
3724
|
-
|
|
3797
|
+
pointer-events: none;
|
|
3725
3798
|
}
|
|
3799
|
+
/* Hairline ruler under the rail: 33 marks across the field, every eighth one
|
|
3800
|
+
taller and a step darker, matching the official scale. */
|
|
3801
|
+
.qdp-windowTickMark {
|
|
3802
|
+
position: absolute;
|
|
3803
|
+
top: 50%;
|
|
3804
|
+
width: 1px;
|
|
3805
|
+
height: 7px;
|
|
3806
|
+
border-radius: 999px;
|
|
3807
|
+
background: var(--dsw-alias-label-caption);
|
|
3808
|
+
transform: translate(-50%, -50%);
|
|
3809
|
+
}
|
|
3810
|
+
.qdp-windowTickMarkMajor {
|
|
3811
|
+
height: 10px;
|
|
3812
|
+
background: var(--dsw-alias-label-tertiary);
|
|
3813
|
+
}
|
|
3814
|
+
/* Tier labels sit on the field colour so the ruler passes behind them. */
|
|
3726
3815
|
.qdp-windowTick {
|
|
3727
3816
|
position: absolute;
|
|
3728
|
-
|
|
3817
|
+
top: 50%;
|
|
3818
|
+
padding: 0 4px;
|
|
3819
|
+
background: var(--dsw-alias-settings-card-fill);
|
|
3729
3820
|
font: var(--dsw-font-xxxs-11);
|
|
3821
|
+
font-size: 9px;
|
|
3822
|
+
line-height: 12px;
|
|
3730
3823
|
color: var(--dsw-alias-label-tertiary);
|
|
3731
3824
|
font-variant-numeric: tabular-nums;
|
|
3732
3825
|
white-space: nowrap;
|
|
3733
3826
|
}
|
|
3734
|
-
|
|
3735
|
-
|
|
3827
|
+
/* The window in force is the only dark number: the other tiers are offers the
|
|
3828
|
+
user has not selected, so they keep the tertiary (grey) tone. */
|
|
3829
|
+
.qdp-windowTickActive {
|
|
3830
|
+
color: var(--dsw-alias-label-primary);
|
|
3831
|
+
font-weight: 500;
|
|
3736
3832
|
}
|
|
3737
|
-
.
|
|
3738
|
-
|
|
3833
|
+
/* A disabled slider greys every label, the active one included. */
|
|
3834
|
+
.qdp-slider[aria-disabled='true'] .qdp-windowTick {
|
|
3835
|
+
color: var(--dsw-alias-label-caption);
|
|
3739
3836
|
}
|
|
3740
3837
|
|
|
3741
3838
|
/* --------------------------------------------------------------- save bar */
|
|
@@ -4113,6 +4210,7 @@ window.__ModuleLoader__.load({
|
|
|
4113
4210
|
modelsNoModels: "No models available.",
|
|
4114
4211
|
modelsNoMatch: "No models matching \"{query}\".",
|
|
4115
4212
|
modelNameColumn: "Model name",
|
|
4213
|
+
effortsHeading: "Reasoning effort",
|
|
4116
4214
|
contextHeading: "Context window",
|
|
4117
4215
|
contextUpTo: "up to {size}",
|
|
4118
4216
|
contextDefault: "default {size}",
|
|
@@ -4157,17 +4255,17 @@ window.__ModuleLoader__.load({
|
|
|
4157
4255
|
quotaToggleHint: "Show this account’s remaining credit in the sidebar footer.",
|
|
4158
4256
|
autoCheckInCN: "Qoder (China) daily auto check-in (100 Credits)",
|
|
4159
4257
|
autoCheckInGlobal: "Qoder Global (International) daily auto check-in",
|
|
4160
|
-
autoCheckInHintCN: "
|
|
4161
|
-
autoCheckInHintGlobal: "
|
|
4162
|
-
checkInTimeHint: "The
|
|
4258
|
+
autoCheckInHintCN: "Check in automatically every day; during campaigns this earns 100 Credits of compute for the China and Global accounts.",
|
|
4259
|
+
autoCheckInHintGlobal: "Check in automatically every day; during campaigns this earns 100 Credits of compute for the China and Global accounts.",
|
|
4260
|
+
checkInTimeHint: "The time the automatic check-in runs each day, Beijing time (UTC+8), refreshing at 10:00 daily.",
|
|
4163
4261
|
autoCheckInStatusClaimed: "Checked in today (+{amount} Credits)",
|
|
4164
4262
|
autoCheckInStatusAlready: "Already checked in today",
|
|
4165
4263
|
autoCheckInStatusNoCampaign: "No active benefit campaign today",
|
|
4166
4264
|
checkInNeedsClient: "Qoder's daily campaign needs the Qoder desktop app on this machine: the international service only serves it to requests carrying a client-minted device identity. Install Qoder and try again.",
|
|
4167
4265
|
autoCheckInStatusError: "Auto check-in error: {message}",
|
|
4168
4266
|
quotaSignInRequired: "Save a PAT for this variant first to enable this card.",
|
|
4169
|
-
quotaPollLabel: "
|
|
4170
|
-
quotaPollHint: "
|
|
4267
|
+
quotaPollLabel: "Credit refresh interval",
|
|
4268
|
+
quotaPollHint: "How often the remaining-credit label refreshes; a longer interval is kinder to the billing endpoint.",
|
|
4171
4269
|
quotaPollUnit: "min",
|
|
4172
4270
|
quotaSettingsSave: "Save",
|
|
4173
4271
|
quotaSettingsSaving: "Saving…",
|
|
@@ -4212,10 +4310,9 @@ window.__ModuleLoader__.load({
|
|
|
4212
4310
|
modelsSaveFailed: "Save failed: {message}",
|
|
4213
4311
|
contextWindowAria: "Context window size",
|
|
4214
4312
|
variantSwitcherAria: "Qoder version",
|
|
4215
|
-
quotaReadoutEnabledLabel: "
|
|
4216
|
-
quotaReadoutEnabledDesc: "
|
|
4313
|
+
quotaReadoutEnabledLabel: "Credits in the dialog",
|
|
4314
|
+
quotaReadoutEnabledDesc: "Show the remaining credits on the composer toolbar; click to expand the details panel.",
|
|
4217
4315
|
checkInTime: "Check-in time",
|
|
4218
|
-
modelEfforts: "Efforts: {levels}",
|
|
4219
4316
|
modelEffortsDefault: "default {name}",
|
|
4220
4317
|
effortMinimal: "minimal",
|
|
4221
4318
|
effortLow: "low",
|
|
@@ -4223,6 +4320,7 @@ window.__ModuleLoader__.load({
|
|
|
4223
4320
|
effortHigh: "high",
|
|
4224
4321
|
effortXhigh: "xhigh",
|
|
4225
4322
|
effortMax: "max",
|
|
4323
|
+
effortsUnsupported: "not supported",
|
|
4226
4324
|
accountCurrent: "In use",
|
|
4227
4325
|
creditsRemaining: "Remaining credit",
|
|
4228
4326
|
checkInStatus: "Check-in",
|
|
@@ -4324,6 +4422,7 @@ window.__ModuleLoader__.load({
|
|
|
4324
4422
|
modelsNoModels: "暂无可配置的模型。",
|
|
4325
4423
|
modelsNoMatch: "未找到匹配“{query}”的模型。",
|
|
4326
4424
|
modelNameColumn: "模型名称",
|
|
4425
|
+
effortsHeading: "思考强度",
|
|
4327
4426
|
contextHeading: "上下文窗口",
|
|
4328
4427
|
contextUpTo: "最高 {size}",
|
|
4329
4428
|
contextDefault: "默认 {size}",
|
|
@@ -4368,17 +4467,17 @@ window.__ModuleLoader__.load({
|
|
|
4368
4467
|
quotaToggleHint: "在侧栏底部展示该账号的剩余额度。",
|
|
4369
4468
|
autoCheckInCN: "Qoder(国内版)每日自动签到",
|
|
4370
4469
|
autoCheckInGlobal: "Qoder Global(国际版)每日自动签到",
|
|
4371
|
-
autoCheckInHintCN: "
|
|
4372
|
-
autoCheckInHintGlobal: "
|
|
4373
|
-
checkInTimeHint: "每天执行自动签到的时刻,按北京时间(UTC+8
|
|
4470
|
+
autoCheckInHintCN: "每天自动签到,活动期间为国内版和国际版账号领取 100 Credits 算力额度。",
|
|
4471
|
+
autoCheckInHintGlobal: "每天自动签到,活动期间为国内版和国际版账号领取 100 Credits 算力额度。",
|
|
4472
|
+
checkInTimeHint: "每天执行自动签到的时刻,按北京时间(UTC+8)于每日 10:00 刷新。",
|
|
4374
4473
|
autoCheckInStatusClaimed: "今日已自动签到(+{amount} Credits)",
|
|
4375
4474
|
autoCheckInStatusAlready: "今日已完成签到",
|
|
4376
4475
|
autoCheckInStatusNoCampaign: "今日无可用签到福利活动",
|
|
4377
4476
|
checkInNeedsClient: "每日签到需要本机安装 Qoder 桌面客户端:国际版只对携带客户端设备身份的请求下发该活动。安装 Qoder 后重试即可。",
|
|
4378
4477
|
autoCheckInStatusError: "自动签到出错:{message}",
|
|
4379
4478
|
quotaSignInRequired: "请先为该变体保存 PAT,再开启此开关。",
|
|
4380
|
-
quotaPollLabel: "
|
|
4381
|
-
quotaPollHint: "
|
|
4479
|
+
quotaPollLabel: "积分刷新间隔",
|
|
4480
|
+
quotaPollHint: "剩余积分标签的刷新频率,间隔越长对计费接口越友好。",
|
|
4382
4481
|
quotaPollUnit: "分钟",
|
|
4383
4482
|
quotaSettingsSave: "保存",
|
|
4384
4483
|
quotaSettingsSaving: "保存中…",
|
|
@@ -4423,17 +4522,17 @@ window.__ModuleLoader__.load({
|
|
|
4423
4522
|
modelsSaveFailed: "保存失败:{message}",
|
|
4424
4523
|
contextWindowAria: "上下文窗口大小",
|
|
4425
4524
|
variantSwitcherAria: "Qoder 版本",
|
|
4426
|
-
quotaReadoutEnabledLabel: "
|
|
4427
|
-
quotaReadoutEnabledDesc: "
|
|
4525
|
+
quotaReadoutEnabledLabel: "对话框显示积分",
|
|
4526
|
+
quotaReadoutEnabledDesc: "在输入框工具条上展示剩余积分,点击可展开明细面板。",
|
|
4428
4527
|
checkInTime: "签到时间",
|
|
4429
|
-
|
|
4430
|
-
|
|
4431
|
-
|
|
4432
|
-
|
|
4433
|
-
|
|
4434
|
-
|
|
4435
|
-
|
|
4436
|
-
|
|
4528
|
+
modelEffortsDefault: "default {name}",
|
|
4529
|
+
effortMinimal: "minimal",
|
|
4530
|
+
effortLow: "low",
|
|
4531
|
+
effortMedium: "medium",
|
|
4532
|
+
effortHigh: "high",
|
|
4533
|
+
effortXhigh: "xhigh",
|
|
4534
|
+
effortMax: "max",
|
|
4535
|
+
effortsUnsupported: "not supported",
|
|
4437
4536
|
accountCurrent: "当前使用",
|
|
4438
4537
|
creditsRemaining: "剩余积分",
|
|
4439
4538
|
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
|
|
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--jTtaG59.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.
|
|
4770
|
+
const QODER_CONNECT_VERSION = "0.6.4";
|
|
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.
|
|
5
|
+
"version": "0.6.4",
|
|
6
6
|
"author": "corrinehu",
|
|
7
7
|
"keywords": [
|
|
8
8
|
"dsh-plugin",
|