dsh-qoder-connect 0.2.3-alpha.1 → 0.2.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 +1 -1
- package/lib/client.js +20 -10
- package/lib/index.d.ts +11 -10
- package/lib/index.js +13 -17
- package/lib/{variants-CU8HDUwi.js → variants-BgysmR2W.js} +108 -33
- package/package.json +1 -1
package/lib/bin.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { D as
|
|
2
|
+
import { D as QoderCatalogStore, O as qoderCatalogPath, U as qoderCredentialIdentity, V as QoderCredentialStore, b as createQoderTransport, f as QODER_CONNECT_VERSION, i as variantFor, k as FALLBACK_QODER_MODELS, 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-BgysmR2W.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
|
@@ -422,10 +422,16 @@ window.__ModuleLoader__.load({
|
|
|
422
422
|
const POLL_MIN_MS = 6e4;
|
|
423
423
|
/** 10:00 UTC+8, the moment the upstream resets the daily campaign. */
|
|
424
424
|
const CHECK_IN_MINUTE_DEFAULT = 600;
|
|
425
|
+
/**
|
|
426
|
+
* Floor the Host schema also enforces: the daily benefit window opens at 10:00,
|
|
427
|
+
* so an earlier moment can never claim anything. Mirrored here for immediate UI
|
|
428
|
+
* feedback, the same way `POLL_MIN_MS` mirrors the poll floor.
|
|
429
|
+
*/
|
|
430
|
+
const EARLIEST_CHECK_IN_MINUTE = 600;
|
|
425
431
|
/** Minutes past midnight (UTC+8), split for the two number fields. */
|
|
426
432
|
function splitMinutes(minutes) {
|
|
427
433
|
const safe = Number.isFinite(minutes) ? Math.trunc(minutes) : CHECK_IN_MINUTE_DEFAULT;
|
|
428
|
-
const clamped = safe <
|
|
434
|
+
const clamped = safe < EARLIEST_CHECK_IN_MINUTE || safe > 1439 ? CHECK_IN_MINUTE_DEFAULT : safe;
|
|
429
435
|
return {
|
|
430
436
|
hours: Math.floor(clamped / 60),
|
|
431
437
|
minutes: clamped % 60
|
|
@@ -555,10 +561,11 @@ window.__ModuleLoader__.load({
|
|
|
555
561
|
const parsedMinutes = Number.parseInt(minuteDraft, 10);
|
|
556
562
|
const hours = Number.isFinite(parsedHours) ? Math.min(23, Math.max(0, parsedHours)) : split.hours;
|
|
557
563
|
const minutes = Number.isFinite(parsedMinutes) ? Math.min(59, Math.max(0, parsedMinutes)) : split.minutes;
|
|
558
|
-
const next = hours * 60 + minutes;
|
|
564
|
+
const next = Math.max(EARLIEST_CHECK_IN_MINUTE, hours * 60 + minutes);
|
|
559
565
|
if (next === value) {
|
|
560
|
-
|
|
561
|
-
|
|
566
|
+
const settled = splitMinutes(next);
|
|
567
|
+
setHourDraft(String(settled.hours));
|
|
568
|
+
setMinuteDraft(String(settled.minutes).padStart(2, "0"));
|
|
562
569
|
return;
|
|
563
570
|
}
|
|
564
571
|
onPick(next);
|
|
@@ -1753,17 +1760,17 @@ window.__ModuleLoader__.load({
|
|
|
1753
1760
|
height: 6,
|
|
1754
1761
|
borderRadius: "50%",
|
|
1755
1762
|
flexShrink: 0,
|
|
1756
|
-
background: log.status === "claimed" ? "var(--dsw-alias-status-success, #52c41a)" : log.status === "already-claimed" ? "var(--dsw-alias-status-info, #1890ff)" : log.status === "no-campaign" ? "var(--dsw-alias-label-tertiary, #999)" : "var(--dsw-alias-status-error, #f5222d)"
|
|
1757
|
-
} }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: log.status === "claimed" ? t("autoCheckInStatusClaimed", { amount: log.amount ?? 100 }) : log.status === "already-claimed" ? t("autoCheckInStatusAlready") : log.status === "no-campaign" ? t("autoCheckInStatusNoCampaign") : t("autoCheckInStatusError", { message: log.message ?? "" }) })]
|
|
1763
|
+
background: log.status === "claimed" ? "var(--dsw-alias-status-success, #52c41a)" : log.status === "already-claimed" ? "var(--dsw-alias-status-info, #1890ff)" : log.status === "no-campaign" || log.status === "before-window" ? "var(--dsw-alias-label-tertiary, #999)" : "var(--dsw-alias-status-error, #f5222d)"
|
|
1764
|
+
} }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: log.status === "claimed" ? t("autoCheckInStatusClaimed", { amount: log.amount ?? 100 }) : log.status === "already-claimed" ? t("autoCheckInStatusAlready") : log.status === "no-campaign" ? t("autoCheckInStatusNoCampaign") : log.status === "before-window" ? t("autoCheckInStatusBeforeWindow") : t("autoCheckInStatusError", { message: log.message ?? "" }) })]
|
|
1758
1765
|
}),
|
|
1759
1766
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1760
1767
|
style: {
|
|
1761
1768
|
flex: 1,
|
|
1762
1769
|
textAlign: "right",
|
|
1763
1770
|
fontWeight: 600,
|
|
1764
|
-
color: log.
|
|
1771
|
+
color: log.status === "claimed" ? "var(--dsw-alias-brand-primary)" : "inherit"
|
|
1765
1772
|
},
|
|
1766
|
-
children: log.
|
|
1773
|
+
children: log.status === "claimed" ? `+${log.amount ?? 100}` : "-"
|
|
1767
1774
|
})
|
|
1768
1775
|
]
|
|
1769
1776
|
}, log.id))]
|
|
@@ -1943,6 +1950,7 @@ window.__ModuleLoader__.load({
|
|
|
1943
1950
|
if (result.state === "claimed") setCheckInNotice(t("autoCheckInStatusClaimed", { amount: result.amount ?? 100 }));
|
|
1944
1951
|
else if (result.state === "already-claimed") setCheckInNotice(t("autoCheckInStatusAlready"));
|
|
1945
1952
|
else if (result.state === "no-campaign") setCheckInNotice(t("autoCheckInStatusNoCampaign"));
|
|
1953
|
+
else if (result.state === "before-window") setCheckInNotice(t("autoCheckInStatusBeforeWindow"));
|
|
1946
1954
|
else if (result.reason) setCheckInNotice(t("autoCheckInStatusError", { message: result.reason }));
|
|
1947
1955
|
} catch (error) {
|
|
1948
1956
|
if (mounted.current && controller.signal.aborted !== true) setCheckInNotice(error instanceof Error ? error.message : t("requestFailed"));
|
|
@@ -3957,10 +3965,11 @@ window.__ModuleLoader__.load({
|
|
|
3957
3965
|
autoCheckInHintGlobal: "Automatically check in daily to claim available perks for the Global account.",
|
|
3958
3966
|
checkInTimeCN: "Check-in time (China)",
|
|
3959
3967
|
checkInTimeGlobal: "Check-in time (Global)",
|
|
3960
|
-
checkInTimeHint: "The moment the automatic check-in runs each day, in UTC+8.",
|
|
3968
|
+
checkInTimeHint: "The moment the automatic check-in runs each day, in UTC+8. Earliest 10:00 — that is when the daily benefit window opens.",
|
|
3961
3969
|
autoCheckInStatusClaimed: "Checked in today (+{amount} Credits)",
|
|
3962
3970
|
autoCheckInStatusAlready: "Already checked in today",
|
|
3963
3971
|
autoCheckInStatusNoCampaign: "No active benefit campaign today",
|
|
3972
|
+
autoCheckInStatusBeforeWindow: "Benefit window not open yet",
|
|
3964
3973
|
autoCheckInStatusError: "Auto check-in error: {message}",
|
|
3965
3974
|
quotaSignInRequired: "Save a PAT for this variant first to enable this card.",
|
|
3966
3975
|
quotaPollLabel: "Refresh interval",
|
|
@@ -4128,10 +4137,11 @@ window.__ModuleLoader__.load({
|
|
|
4128
4137
|
autoCheckInHintGlobal: "每天自动签到,为国际版账号领取可用福利额度。",
|
|
4129
4138
|
checkInTimeCN: "签到时间(国内版)",
|
|
4130
4139
|
checkInTimeGlobal: "签到时间(国际版)",
|
|
4131
|
-
checkInTimeHint: "每天执行自动签到的时刻,按北京时间(UTC+8
|
|
4140
|
+
checkInTimeHint: "每天执行自动签到的时刻,按北京时间(UTC+8)。最早 10:00,每日福利窗口在此时开启。",
|
|
4132
4141
|
autoCheckInStatusClaimed: "今日已自动签到(+{amount} Credits)",
|
|
4133
4142
|
autoCheckInStatusAlready: "今日已完成签到",
|
|
4134
4143
|
autoCheckInStatusNoCampaign: "今日无可用签到福利活动",
|
|
4144
|
+
autoCheckInStatusBeforeWindow: "签到活动尚未开启",
|
|
4135
4145
|
autoCheckInStatusError: "自动签到出错:{message}",
|
|
4136
4146
|
quotaSignInRequired: "请先为该变体保存 PAT,再开启此开关。",
|
|
4137
4147
|
quotaPollLabel: "刷新间隔",
|
package/lib/index.d.ts
CHANGED
|
@@ -269,7 +269,7 @@ type QoderWebStatus = {
|
|
|
269
269
|
checkIn?: {
|
|
270
270
|
lastDate: string;
|
|
271
271
|
lastAt: number;
|
|
272
|
-
status: 'claimed' | 'already-claimed' | 'no-campaign' | 'error';
|
|
272
|
+
status: 'claimed' | 'already-claimed' | 'before-window' | 'no-campaign' | 'error';
|
|
273
273
|
amount?: number | undefined;
|
|
274
274
|
message?: string | undefined;
|
|
275
275
|
/**
|
|
@@ -284,7 +284,7 @@ type QoderWebStatus = {
|
|
|
284
284
|
id: string;
|
|
285
285
|
date: string;
|
|
286
286
|
timestamp: number;
|
|
287
|
-
status: 'claimed' | 'already-claimed' | 'no-campaign' | 'error';
|
|
287
|
+
status: 'claimed' | 'already-claimed' | 'before-window' | 'no-campaign' | 'error';
|
|
288
288
|
amount?: number | undefined;
|
|
289
289
|
campaignKey?: string | undefined;
|
|
290
290
|
message?: string | undefined;
|
|
@@ -747,7 +747,7 @@ interface QoderCheckInResult {
|
|
|
747
747
|
variantId: string;
|
|
748
748
|
date: string;
|
|
749
749
|
timestamp: number;
|
|
750
|
-
status: 'claimed' | 'already-claimed' | 'no-campaign' | 'error';
|
|
750
|
+
status: 'claimed' | 'already-claimed' | 'before-window' | 'no-campaign' | 'error';
|
|
751
751
|
amount?: number | undefined;
|
|
752
752
|
campaignKey?: string | undefined;
|
|
753
753
|
message?: string | undefined;
|
|
@@ -942,13 +942,14 @@ declare class QoderUpstreamClient {
|
|
|
942
942
|
/**
|
|
943
943
|
* One minimal reasoning-effort request, as the probe sweep needs it.
|
|
944
944
|
*
|
|
945
|
-
*
|
|
946
|
-
*
|
|
947
|
-
*
|
|
948
|
-
*
|
|
949
|
-
*
|
|
950
|
-
*
|
|
951
|
-
*
|
|
945
|
+
* A row that declares efforts is still checked locally, so an unlisted value
|
|
946
|
+
* costs no request. A row that declares none — the only kind detection is
|
|
947
|
+
* offered for — sends the value to the upstream and waits for its answer,
|
|
948
|
+
* because the endpoint is the only authority on spellings the catalog never
|
|
949
|
+
* lists. Either refusal is reported as an attributable 400 with code
|
|
950
|
+
* `UNSUPPORTED_REASONING_EFFORT`, and an accepted value costs exactly one
|
|
951
|
+
* streamed request, which this method ends after the first chunk arrives —
|
|
952
|
+
* see the module docs in `probe.ts`.
|
|
952
953
|
*/
|
|
953
954
|
probeEffort(model: string, effort: string | undefined, signal: AbortSignal): Promise<ProbeAttempt>;
|
|
954
955
|
}
|
package/lib/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { A as
|
|
1
|
+
import { A as QoderCatalog, B as QODER_PAT_ENV_GLOBAL, C as getMachineId, D as QoderCatalogStore, E as randomSentinel, F as QODER_PROBE_PATH, G as QODER_DATA_DIR_ENV, H as patTail, I as QODER_SETTINGS_FACE_PATH, J as qoderPluginDataDir, K as QODER_DATA_DIR_NAME, L as QODER_STATUS_PATH, M as QODER_GLOBAL_AUTH_PATH, N as QODER_GLOBAL_PROBE_PATH, O as qoderCatalogPath, P as QODER_GLOBAL_STATUS_PATH, R as QODER_AUTH_FILENAME, S as utc8WallClock, T as probeModel, U as qoderCredentialIdentity, V as QoderCredentialStore, W as qoderOwnAuthPath, Y as qoderStateDir, _ 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_AUTH_PATH, k as FALLBACK_QODER_MODELS, l as qoderHostHeartbeatPath, m as QoderUpstreamClient, n as GLOBAL_VARIANT, o as clearHostHeartbeat, p as KIND_STATUS, q as qoderMachineIdPath, r as QODER_VARIANTS, s as isHeartbeatProcessAlive, t as CHINA_VARIANT, u as readHostHeartbeat, v as normalizeCredits, w as PROBE_EFFORT_CANDIDATES, x as formatUtc8Date, y as validateApiKey, z as QODER_PAT_ENV_CN } from "./variants-BgysmR2W.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";
|
|
@@ -1366,20 +1366,12 @@ var JsonFileCheckInStore = class {
|
|
|
1366
1366
|
} catch {}
|
|
1367
1367
|
}
|
|
1368
1368
|
};
|
|
1369
|
-
/**
|
|
1370
|
-
* Returns the current date in YYYY-MM-DD standardized on UTC+8 (Beijing Time).
|
|
1371
|
-
*/
|
|
1372
|
-
function getUtc8DateString(nowMs = Date.now()) {
|
|
1373
|
-
const d = new Date(nowMs);
|
|
1374
|
-
const utc8 = new Date(d.getTime() + (d.getTimezoneOffset() + 480) * 6e4);
|
|
1375
|
-
return `${utc8.getFullYear()}-${String(utc8.getMonth() + 1).padStart(2, "0")}-${String(utc8.getDate()).padStart(2, "0")}`;
|
|
1376
|
-
}
|
|
1377
|
-
/** Clamp any stored/typed value onto a real minute of the day. */
|
|
1369
|
+
/** Clamp any stored/typed value onto a minute the plugin can actually honour. */
|
|
1378
1370
|
function normalizeCheckInMinute(value) {
|
|
1379
1371
|
if (typeof value !== "number" || !Number.isFinite(value)) return 600;
|
|
1380
1372
|
const whole = Math.trunc(value);
|
|
1381
1373
|
if (whole < 0 || whole > 1439) return 600;
|
|
1382
|
-
return whole;
|
|
1374
|
+
return Math.max(600, whole);
|
|
1383
1375
|
}
|
|
1384
1376
|
/**
|
|
1385
1377
|
* Calculates milliseconds until the next occurrence of `minuteOfDay` (UTC+8).
|
|
@@ -1389,8 +1381,7 @@ function normalizeCheckInMinute(value) {
|
|
|
1389
1381
|
*/
|
|
1390
1382
|
function msUntilNextCheckIn(minuteOfDay, nowMs = Date.now()) {
|
|
1391
1383
|
const minute = normalizeCheckInMinute(minuteOfDay);
|
|
1392
|
-
const
|
|
1393
|
-
const utc8Time = new Date(d.getTime() + (d.getTimezoneOffset() + 480) * 6e4);
|
|
1384
|
+
const utc8Time = utc8WallClock(nowMs);
|
|
1394
1385
|
const targetUtc8 = new Date(utc8Time.getTime());
|
|
1395
1386
|
targetUtc8.setHours(Math.floor(minute / 60), minute % 60, 5, 0);
|
|
1396
1387
|
let diff = targetUtc8.getTime() - utc8Time.getTime();
|
|
@@ -1405,8 +1396,7 @@ function msUntilNextCheckIn(minuteOfDay, nowMs = Date.now()) {
|
|
|
1405
1396
|
*/
|
|
1406
1397
|
function isPastCheckInTime(minuteOfDay, nowMs = Date.now()) {
|
|
1407
1398
|
const minute = normalizeCheckInMinute(minuteOfDay);
|
|
1408
|
-
const
|
|
1409
|
-
const utc8 = new Date(d.getTime() + (d.getTimezoneOffset() + 480) * 6e4);
|
|
1399
|
+
const utc8 = utc8WallClock(nowMs);
|
|
1410
1400
|
return utc8.getHours() * 60 + utc8.getMinutes() >= minute;
|
|
1411
1401
|
}
|
|
1412
1402
|
var CheckInScheduler = class {
|
|
@@ -1502,7 +1492,7 @@ var CheckInScheduler = class {
|
|
|
1502
1492
|
async sweepAll(isCatchUp, only) {
|
|
1503
1493
|
if (this.disposed) return;
|
|
1504
1494
|
const nowMs = this.now();
|
|
1505
|
-
const today =
|
|
1495
|
+
const today = formatUtc8Date(nowMs);
|
|
1506
1496
|
for (const target of this.targets) {
|
|
1507
1497
|
if (only !== void 0 && target.variantId !== only) continue;
|
|
1508
1498
|
if (!this.isEnabled(target.variantId)) continue;
|
|
@@ -1912,8 +1902,14 @@ const AUTO_CHECK_IN_FIELD = volatileField(z.boolean().default(false).description
|
|
|
1912
1902
|
* itself rejects an impossible time: a browser time input yields 0–1439, and
|
|
1913
1903
|
* anything outside that range fails Host validation instead of silently
|
|
1914
1904
|
* scheduling a request at a moment that never arrives.
|
|
1905
|
+
*
|
|
1906
|
+
* The floor is the window's own opening rather than midnight, because a moment
|
|
1907
|
+
* before 10:00 is impossible in the same sense: the upstream has not opened the
|
|
1908
|
+
* day's benefit yet, so the run can only read the *previous* window's status
|
|
1909
|
+
* and settle a day that was never claimed. Refusing the value is the point — it
|
|
1910
|
+
* is not a time this plugin could honour.
|
|
1915
1911
|
*/
|
|
1916
|
-
const CHECK_IN_MINUTE_FIELD = volatileField(z.number().default(600).min(
|
|
1912
|
+
const CHECK_IN_MINUTE_FIELD = volatileField(z.number().default(600).min(600).max(1439).description("每日自动签到的时刻(自 UTC+8 午夜起的分钟数,600 = 10:00;最早 10:00,即活动窗口开启时刻)"));
|
|
1917
1913
|
/**
|
|
1918
1914
|
* Quota poll interval: default 5 minutes, floor 1 minute. The status route
|
|
1919
1915
|
* performs a live upstream billing call per request with no cache, so an
|
|
@@ -760,17 +760,14 @@ function randomSentinel() {
|
|
|
760
760
|
return `probe_sentinel_${randomBytes(12).toString("hex")}`;
|
|
761
761
|
}
|
|
762
762
|
/**
|
|
763
|
-
* The
|
|
764
|
-
* (`src/qoder/transport/wire/serialize.ts`
|
|
763
|
+
* The code a refused effort arrives under, wherever it was refused
|
|
764
|
+
* (`src/qoder/transport/wire/serialize.ts` for a declared row, `probeEffort`
|
|
765
|
+
* for a refusal the endpoint issued itself).
|
|
765
766
|
*
|
|
766
|
-
*
|
|
767
|
-
*
|
|
768
|
-
*
|
|
769
|
-
*
|
|
770
|
-
* weigh; the sequence below still distinguishes "advertises and validates"
|
|
771
|
-
* (per-level refusals after an accepted baseline) from "accepts anything the
|
|
772
|
-
* catalog does not name" — the sentinel answers that question against the
|
|
773
|
-
* same vocabulary the request path will later enforce.
|
|
767
|
+
* Only a row that declares efforts can be refused locally. An undeclared row —
|
|
768
|
+
* the only kind a sweep is offered for — sends every candidate to the wire and
|
|
769
|
+
* lets the sentinel measure the endpoint rather than this plugin's own reading
|
|
770
|
+
* of the catalog.
|
|
774
771
|
*/
|
|
775
772
|
const INVALID_EFFORT_CODE = "UNSUPPORTED_REASONING_EFFORT";
|
|
776
773
|
/** Whether an attempt is an attributable rejection of the effort value. */
|
|
@@ -2082,7 +2079,8 @@ function stableChatRecordId(model, messages, tools, maxTokens) {
|
|
|
2082
2079
|
function validateQoderRequestShape(options, model) {
|
|
2083
2080
|
if (options.reasoningEffort !== void 0) {
|
|
2084
2081
|
const effort = String(options.reasoningEffort);
|
|
2085
|
-
|
|
2082
|
+
const declared = model?.reasoningEfforts;
|
|
2083
|
+
if (declared !== void 0 && declared.length > 0 && !declared.some((candidate) => candidate.id === effort)) throw new QoderLlmError(`Qoder model "${options.model}" does not advertise reasoning effort "${effort}".`, "UNSUPPORTED_REASONING_EFFORT");
|
|
2086
2084
|
}
|
|
2087
2085
|
if (options.messages.some((message) => contentHasImage(message.content)) && model?.supportsImages !== true) throw new QoderLlmError(`Qoder model "${options.model}" does not advertise image input.`, "UNSUPPORTED_CONTENT");
|
|
2088
2086
|
validateMessageShapes(options.messages);
|
|
@@ -2720,9 +2718,38 @@ var QoderUsageReader = class {
|
|
|
2720
2718
|
}
|
|
2721
2719
|
}
|
|
2722
2720
|
};
|
|
2721
|
+
/**
|
|
2722
|
+
* The UTC+8 wall clock of an instant, as a Date whose *local* fields hold it.
|
|
2723
|
+
*
|
|
2724
|
+
* Shifting by the host's own offset cancels the host timezone out, so the
|
|
2725
|
+
* result reads the same on a UTC+8 machine and on a UTC-5 one. Callers must
|
|
2726
|
+
* therefore use the local getters (`getHours`, `getFullYear`, …) on it.
|
|
2727
|
+
*/
|
|
2728
|
+
function utc8WallClock(atMs) {
|
|
2729
|
+
const d = new Date(atMs);
|
|
2730
|
+
return new Date(d.getTime() + (d.getTimezoneOffset() + 480) * 6e4);
|
|
2731
|
+
}
|
|
2732
|
+
/**
|
|
2733
|
+
* Format an epoch-ms instant as its UTC+8 calendar date, `YYYY-MM-DD`.
|
|
2734
|
+
*/
|
|
2735
|
+
function formatUtc8Date(atMs) {
|
|
2736
|
+
const utc8 = utc8WallClock(atMs);
|
|
2737
|
+
return `${utc8.getFullYear()}-${String(utc8.getMonth() + 1).padStart(2, "0")}-${String(utc8.getDate()).padStart(2, "0")}`;
|
|
2738
|
+
}
|
|
2723
2739
|
//#endregion
|
|
2724
2740
|
//#region src/qoder/transport/checkin.ts
|
|
2741
|
+
/** Qoder campaign inquiry and daily benefit check-in service. */
|
|
2725
2742
|
const defaultCheckInTimeoutMs = 15e3;
|
|
2743
|
+
/**
|
|
2744
|
+
* The longest span still recognised as one daily benefit window.
|
|
2745
|
+
*
|
|
2746
|
+
* Qoder's daily window runs 10:00 → 09:59 the next morning (86_340 s). The
|
|
2747
|
+
* slack above 24h absorbs a clock or rounding difference; a genuinely longer
|
|
2748
|
+
* campaign is *not* a daily window, and its start day says nothing about which
|
|
2749
|
+
* day one claim of it belongs to, so it must fall back to the calendar day
|
|
2750
|
+
* rather than mislabel every day of its run.
|
|
2751
|
+
*/
|
|
2752
|
+
const DAILY_WINDOW_MAX_MS = 864e5;
|
|
2726
2753
|
var QoderCheckInService = class {
|
|
2727
2754
|
authService;
|
|
2728
2755
|
fetchImpl;
|
|
@@ -2770,14 +2797,37 @@ var QoderCheckInService = class {
|
|
|
2770
2797
|
logCategory: "campaigns.claim"
|
|
2771
2798
|
});
|
|
2772
2799
|
}
|
|
2773
|
-
|
|
2774
|
-
|
|
2775
|
-
|
|
2776
|
-
|
|
2800
|
+
/**
|
|
2801
|
+
* Attribute the campaign the upstream is serving to a day, or say why it
|
|
2802
|
+
* cannot be attributed to today.
|
|
2803
|
+
*
|
|
2804
|
+
* The daily benefit window is 10:00 UTC+8 → 09:59 the next morning, so a
|
|
2805
|
+
* calendar date and the window's own date agree for only fourteen hours of
|
|
2806
|
+
* every twenty-four. Treating them as the same thing is what recorded a
|
|
2807
|
+
* pre-10:00 read of the *previous* window's `CLAIMED` against today.
|
|
2808
|
+
*/
|
|
2809
|
+
classifyCampaignWindow(campaign, nowMs, today) {
|
|
2810
|
+
const startAt = campaign.startAt;
|
|
2811
|
+
if (typeof startAt !== "number" || !Number.isFinite(startAt) || startAt <= 0) return { kind: "unknown" };
|
|
2812
|
+
const endAt = campaign.endAt;
|
|
2813
|
+
if (typeof endAt === "number" && Number.isFinite(endAt)) {
|
|
2814
|
+
const spanMs = (endAt - startAt) * 1e3;
|
|
2815
|
+
if (spanMs <= 0 || spanMs > DAILY_WINDOW_MAX_MS) return { kind: "unknown" };
|
|
2816
|
+
}
|
|
2817
|
+
const startMs = startAt * 1e3;
|
|
2818
|
+
if (startMs > nowMs) return { kind: "not-open" };
|
|
2819
|
+
const date = formatUtc8Date(startMs);
|
|
2820
|
+
return date === today ? {
|
|
2821
|
+
kind: "open",
|
|
2822
|
+
date
|
|
2823
|
+
} : {
|
|
2824
|
+
kind: "earlier",
|
|
2825
|
+
date
|
|
2826
|
+
};
|
|
2777
2827
|
}
|
|
2778
2828
|
async checkIn(pat, signal) {
|
|
2779
|
-
const today = this.getTodayDateString();
|
|
2780
2829
|
const nowMs = Date.now();
|
|
2830
|
+
const today = formatUtc8Date(nowMs);
|
|
2781
2831
|
if (!pat || typeof pat !== "string" || pat.trim() === "") return {
|
|
2782
2832
|
variantId: this.variantId,
|
|
2783
2833
|
date: today,
|
|
@@ -2794,10 +2844,20 @@ var QoderCheckInService = class {
|
|
|
2794
2844
|
status: "no-campaign",
|
|
2795
2845
|
message: "No claimable benefit campaign found for this region"
|
|
2796
2846
|
};
|
|
2797
|
-
|
|
2847
|
+
const campaignWindow = this.classifyCampaignWindow(benefitCampaign, nowMs, today);
|
|
2848
|
+
if (campaignWindow.kind === "not-open" || campaignWindow.kind === "earlier") return {
|
|
2798
2849
|
variantId: this.variantId,
|
|
2799
2850
|
date: today,
|
|
2800
2851
|
timestamp: nowMs,
|
|
2852
|
+
status: "before-window",
|
|
2853
|
+
campaignKey: benefitCampaign.campaignKey,
|
|
2854
|
+
message: campaignWindow.kind === "not-open" ? "Today's benefit window has not opened yet" : `Upstream is still serving the benefit window of ${campaignWindow.date}`
|
|
2855
|
+
};
|
|
2856
|
+
const windowDate = campaignWindow.kind === "open" ? campaignWindow.date : today;
|
|
2857
|
+
if (benefitCampaign.claimStatus === "CLAIMED") return {
|
|
2858
|
+
variantId: this.variantId,
|
|
2859
|
+
date: windowDate,
|
|
2860
|
+
timestamp: nowMs,
|
|
2801
2861
|
status: "already-claimed",
|
|
2802
2862
|
campaignKey: benefitCampaign.campaignKey,
|
|
2803
2863
|
amount: benefitCampaign.benefit?.amount ?? 100,
|
|
@@ -2809,7 +2869,7 @@ var QoderCheckInService = class {
|
|
|
2809
2869
|
const amount = claimResult.benefit?.amount ?? benefitCampaign.benefit?.amount ?? 100;
|
|
2810
2870
|
if (isClaimed) return {
|
|
2811
2871
|
variantId: this.variantId,
|
|
2812
|
-
date:
|
|
2872
|
+
date: windowDate,
|
|
2813
2873
|
timestamp: nowMs,
|
|
2814
2874
|
status: replayed ? "already-claimed" : "claimed",
|
|
2815
2875
|
amount,
|
|
@@ -4465,13 +4525,14 @@ var QoderUpstreamClient = class {
|
|
|
4465
4525
|
/**
|
|
4466
4526
|
* One minimal reasoning-effort request, as the probe sweep needs it.
|
|
4467
4527
|
*
|
|
4468
|
-
*
|
|
4469
|
-
*
|
|
4470
|
-
*
|
|
4471
|
-
*
|
|
4472
|
-
*
|
|
4473
|
-
*
|
|
4474
|
-
*
|
|
4528
|
+
* A row that declares efforts is still checked locally, so an unlisted value
|
|
4529
|
+
* costs no request. A row that declares none — the only kind detection is
|
|
4530
|
+
* offered for — sends the value to the upstream and waits for its answer,
|
|
4531
|
+
* because the endpoint is the only authority on spellings the catalog never
|
|
4532
|
+
* lists. Either refusal is reported as an attributable 400 with code
|
|
4533
|
+
* `UNSUPPORTED_REASONING_EFFORT`, and an accepted value costs exactly one
|
|
4534
|
+
* streamed request, which this method ends after the first chunk arrives —
|
|
4535
|
+
* see the module docs in `probe.ts`.
|
|
4475
4536
|
*/
|
|
4476
4537
|
async probeEffort(model, effort, signal) {
|
|
4477
4538
|
try {
|
|
@@ -4510,12 +4571,15 @@ var QoderUpstreamClient = class {
|
|
|
4510
4571
|
await iterator.return?.();
|
|
4511
4572
|
}
|
|
4512
4573
|
} catch (error) {
|
|
4513
|
-
if (error instanceof LlmError)
|
|
4514
|
-
status
|
|
4515
|
-
|
|
4516
|
-
|
|
4517
|
-
|
|
4518
|
-
|
|
4574
|
+
if (error instanceof LlmError) {
|
|
4575
|
+
const status = error.failure.status ?? defaultStatusForProbe(error.failure.code);
|
|
4576
|
+
return {
|
|
4577
|
+
status,
|
|
4578
|
+
streamed: false,
|
|
4579
|
+
errorCode: status === 400 && blamesReasoningEffort(error.failure.message) ? "UNSUPPORTED_REASONING_EFFORT" : error.failure.code,
|
|
4580
|
+
detail: error.failure.message.slice(0, 300)
|
|
4581
|
+
};
|
|
4582
|
+
}
|
|
4519
4583
|
return {
|
|
4520
4584
|
status: 0,
|
|
4521
4585
|
streamed: false,
|
|
@@ -4524,6 +4588,17 @@ var QoderUpstreamClient = class {
|
|
|
4524
4588
|
}
|
|
4525
4589
|
}
|
|
4526
4590
|
};
|
|
4591
|
+
/**
|
|
4592
|
+
* Whether an upstream 400 blames the `reasoning_effort` value it was sent.
|
|
4593
|
+
*
|
|
4594
|
+
* Qoder answers an impossible effort with a `provider_error` body whose nested
|
|
4595
|
+
* error names `invalid_parameter_error` and quotes `reasoning_effort`. Both
|
|
4596
|
+
* markers are required: a 400 naming only one of them is some other parameter
|
|
4597
|
+
* problem, and the sweep must not record it as a rejected level.
|
|
4598
|
+
*/
|
|
4599
|
+
function blamesReasoningEffort(message) {
|
|
4600
|
+
return message.includes("invalid_parameter_error") && message.includes("reasoning_effort");
|
|
4601
|
+
}
|
|
4527
4602
|
/** Statuses {@link probeEffort} reports for failures the transport raised pre-network. */
|
|
4528
4603
|
function defaultStatusForProbe(code) {
|
|
4529
4604
|
switch (code) {
|
|
@@ -4587,7 +4662,7 @@ const DEFAULT_MAX_TOKENS = 32768;
|
|
|
4587
4662
|
const DEFAULT_CONTEXT_WINDOW = 18e4;
|
|
4588
4663
|
//#endregion
|
|
4589
4664
|
//#region src/version.ts
|
|
4590
|
-
const QODER_CONNECT_VERSION = "0.2.3
|
|
4665
|
+
const QODER_CONNECT_VERSION = "0.2.3";
|
|
4591
4666
|
//#endregion
|
|
4592
4667
|
//#region src/host-heartbeat.ts
|
|
4593
4668
|
/**
|
|
@@ -4784,4 +4859,4 @@ function variantFor(id) {
|
|
|
4784
4859
|
return QODER_VARIANTS.find((variant) => variant.id === id);
|
|
4785
4860
|
}
|
|
4786
4861
|
//#endregion
|
|
4787
|
-
export {
|
|
4862
|
+
export { QoderCatalog as A, QODER_PAT_ENV_GLOBAL as B, getMachineId as C, QoderCatalogStore as D, randomSentinel as E, QODER_PROBE_PATH as F, QODER_DATA_DIR_ENV as G, patTail as H, QODER_SETTINGS_FACE_PATH as I, qoderPluginDataDir as J, QODER_DATA_DIR_NAME as K, QODER_STATUS_PATH as L, QODER_GLOBAL_AUTH_PATH as M, QODER_GLOBAL_PROBE_PATH as N, qoderCatalogPath as O, QODER_GLOBAL_STATUS_PATH as P, QODER_AUTH_FILENAME as R, utc8WallClock as S, probeModel as T, qoderCredentialIdentity as U, QoderCredentialStore as V, qoderOwnAuthPath as W, qoderStateDir as Y, modelInfoOf as _, QODER_HOST_HEARTBEAT_FILENAME as a, createQoderTransport as b, processStartTimeMs as c, writeHostHeartbeat as d, QODER_CONNECT_VERSION as f, kindFromQoderFailure as g, classifyUpstreamError as h, variantFor as i, QODER_AUTH_PATH as j, FALLBACK_QODER_MODELS as k, qoderHostHeartbeatPath as l, QoderUpstreamClient as m, GLOBAL_VARIANT as n, clearHostHeartbeat as o, KIND_STATUS as p, qoderMachineIdPath as q, QODER_VARIANTS as r, isHeartbeatProcessAlive as s, CHINA_VARIANT as t, readHostHeartbeat as u, normalizeCredits as v, PROBE_EFFORT_CANDIDATES as w, formatUtc8Date as x, validateApiKey as y, QODER_PAT_ENV_CN as z };
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "dsh-qoder-connect",
|
|
3
3
|
"displayName": "DSH Qoder Connect",
|
|
4
4
|
"description": "将 Qoder(国内版 / 国际版)的模型接入 DeepSeek Harness — bring Qoder (CN & international) models into DeepSeek Harness.",
|
|
5
|
-
"version": "0.2.3
|
|
5
|
+
"version": "0.2.3",
|
|
6
6
|
"author": "corrinehu",
|
|
7
7
|
"keywords": [
|
|
8
8
|
"dsh-plugin",
|