dsh-qoder-connect 0.1.4 → 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/README.en.md +13 -0
- package/README.md +13 -0
- package/assets/7.png +0 -0
- package/lib/bin.js +1 -1
- package/lib/client.js +739 -5
- package/lib/index.d.ts +97 -4
- package/lib/index.js +508 -41
- package/lib/{variants-CSeJqJpR.js → variants-DE76gF0Y.js} +186 -2
- package/package.json +1 -1
|
@@ -502,11 +502,18 @@ var QoderCatalog = class {
|
|
|
502
502
|
useMaximumContextWindow = false;
|
|
503
503
|
/** Per-model window overrides (model id → tokens); an override wins over the preference. */
|
|
504
504
|
modelContextWindows = {};
|
|
505
|
+
/** Disabled model IDs (blacklist); disabled models are filtered out from current(). */
|
|
506
|
+
disabledModels = /* @__PURE__ */ new Set();
|
|
505
507
|
constructor(initial = FALLBACK_QODER_MODELS) {
|
|
506
508
|
this.models = initial;
|
|
507
509
|
}
|
|
508
|
-
/** Current entries; empty while the variant has no usable credential. */
|
|
510
|
+
/** Current entries; empty while the variant has no usable credential, excluding disabled models. */
|
|
509
511
|
current() {
|
|
512
|
+
if (!this.visible) return [];
|
|
513
|
+
return this.all().filter((model) => !this.disabledModels.has(model.id));
|
|
514
|
+
}
|
|
515
|
+
/** All configured entries including disabled ones; empty while the variant has no usable credential. */
|
|
516
|
+
all() {
|
|
510
517
|
if (!this.visible) return [];
|
|
511
518
|
return this.models.map((model) => {
|
|
512
519
|
const override = this.modelContextWindows[model.id];
|
|
@@ -557,6 +564,20 @@ var QoderCatalog = class {
|
|
|
557
564
|
return true;
|
|
558
565
|
}
|
|
559
566
|
/**
|
|
567
|
+
* Replace the disabled model IDs wholesale. Returns whether the set
|
|
568
|
+
* changed, so the caller can skip an invalidation over an identical write.
|
|
569
|
+
*/
|
|
570
|
+
setDisabledModels(disabledModels) {
|
|
571
|
+
const next = new Set(disabledModels);
|
|
572
|
+
if (next.size === this.disabledModels.size && [...next].every((id) => this.disabledModels.has(id))) return false;
|
|
573
|
+
this.disabledModels = next;
|
|
574
|
+
return true;
|
|
575
|
+
}
|
|
576
|
+
/** Current disabled model IDs. */
|
|
577
|
+
getDisabledModels() {
|
|
578
|
+
return Array.from(this.disabledModels);
|
|
579
|
+
}
|
|
580
|
+
/**
|
|
560
581
|
* Models to fall back to when the upstream fetch fails; ignores
|
|
561
582
|
* visibility, because the caller asking for the fallback already knows the
|
|
562
583
|
* credential state.
|
|
@@ -876,6 +897,14 @@ function getQoderUserStatusUrl(region = "global") {
|
|
|
876
897
|
const { openApiUrl } = resolveQoderEndpoints(region);
|
|
877
898
|
return `${openApiUrl}/api/v3/user/status`;
|
|
878
899
|
}
|
|
900
|
+
function getQoderCampaignsUrl(region = "global") {
|
|
901
|
+
const { openApiUrl } = resolveQoderEndpoints(region);
|
|
902
|
+
return `${openApiUrl}/sash/api/v1/me/campaigns`;
|
|
903
|
+
}
|
|
904
|
+
function getQoderClaimCampaignUrl(region = "global", campaignId) {
|
|
905
|
+
const { openApiUrl } = resolveQoderEndpoints(region);
|
|
906
|
+
return `${openApiUrl}/sash/api/v1/me/campaigns/${encodeURIComponent(campaignId)}/claim`;
|
|
907
|
+
}
|
|
879
908
|
//#endregion
|
|
880
909
|
//#region src/qoder/errors.ts
|
|
881
910
|
/**
|
|
@@ -2359,6 +2388,7 @@ var QoderUsageReader = class {
|
|
|
2359
2388
|
return {
|
|
2360
2389
|
userQuota: normalizeQuota(data.userQuota),
|
|
2361
2390
|
orgResourcePackage: normalizeQuota(data.orgResourcePackage),
|
|
2391
|
+
addOnQuota: normalizeQuota(data.addOnQuota),
|
|
2362
2392
|
totalUsagePercentage: typeof data.totalUsagePercentage === "number" ? data.totalUsagePercentage : void 0,
|
|
2363
2393
|
isQuotaExceeded: typeof data.isQuotaExceeded === "boolean" ? data.isQuotaExceeded : false,
|
|
2364
2394
|
expiresAt: normalizeExpiresAt(data.expiresAt),
|
|
@@ -2408,6 +2438,135 @@ var QoderUsageReader = class {
|
|
|
2408
2438
|
}
|
|
2409
2439
|
};
|
|
2410
2440
|
//#endregion
|
|
2441
|
+
//#region src/qoder/transport/checkin.ts
|
|
2442
|
+
const defaultCheckInTimeoutMs = 15e3;
|
|
2443
|
+
var QoderCheckInService = class {
|
|
2444
|
+
authService;
|
|
2445
|
+
fetchImpl;
|
|
2446
|
+
region;
|
|
2447
|
+
variantId;
|
|
2448
|
+
logger;
|
|
2449
|
+
timeoutMs;
|
|
2450
|
+
constructor(options) {
|
|
2451
|
+
this.authService = options.authService;
|
|
2452
|
+
this.fetchImpl = options.fetch ?? globalThis.fetch;
|
|
2453
|
+
this.region = options.region ?? "china";
|
|
2454
|
+
this.variantId = options.variantId ?? "qoder";
|
|
2455
|
+
this.logger = options.logger;
|
|
2456
|
+
this.timeoutMs = options.timeoutMs ?? defaultCheckInTimeoutMs;
|
|
2457
|
+
}
|
|
2458
|
+
async fetchCampaigns(token, signal) {
|
|
2459
|
+
const url = getQoderCampaignsUrl(this.region);
|
|
2460
|
+
const data = await openApiJsonRequest(this.fetchImpl, {
|
|
2461
|
+
url,
|
|
2462
|
+
token,
|
|
2463
|
+
headers: { "cosy-clienttype": "10" },
|
|
2464
|
+
signal,
|
|
2465
|
+
timeoutMs: this.timeoutMs,
|
|
2466
|
+
logger: this.logger,
|
|
2467
|
+
operation: "Campaigns",
|
|
2468
|
+
logCategory: "campaigns.list"
|
|
2469
|
+
});
|
|
2470
|
+
return Array.isArray(data?.campaigns) ? data.campaigns : [];
|
|
2471
|
+
}
|
|
2472
|
+
async claimCampaign(token, campaignId, signal) {
|
|
2473
|
+
const url = getQoderClaimCampaignUrl(this.region, campaignId);
|
|
2474
|
+
const { openApiUrl } = resolveQoderEndpoints(this.region);
|
|
2475
|
+
return openApiJsonRequest(this.fetchImpl, {
|
|
2476
|
+
url,
|
|
2477
|
+
method: "POST",
|
|
2478
|
+
token,
|
|
2479
|
+
headers: {
|
|
2480
|
+
origin: openApiUrl,
|
|
2481
|
+
"cosy-clienttype": "10"
|
|
2482
|
+
},
|
|
2483
|
+
signal,
|
|
2484
|
+
timeoutMs: this.timeoutMs,
|
|
2485
|
+
logger: this.logger,
|
|
2486
|
+
operation: "ClaimCampaign",
|
|
2487
|
+
logCategory: "campaigns.claim"
|
|
2488
|
+
});
|
|
2489
|
+
}
|
|
2490
|
+
getTodayDateString() {
|
|
2491
|
+
const now = /* @__PURE__ */ new Date();
|
|
2492
|
+
const utc8Time = new Date(now.getTime() + (now.getTimezoneOffset() + 480) * 6e4);
|
|
2493
|
+
return `${utc8Time.getFullYear()}-${String(utc8Time.getMonth() + 1).padStart(2, "0")}-${String(utc8Time.getDate()).padStart(2, "0")}`;
|
|
2494
|
+
}
|
|
2495
|
+
async checkIn(pat, signal) {
|
|
2496
|
+
const today = this.getTodayDateString();
|
|
2497
|
+
const nowMs = Date.now();
|
|
2498
|
+
if (!pat || typeof pat !== "string" || pat.trim() === "") return {
|
|
2499
|
+
variantId: this.variantId,
|
|
2500
|
+
date: today,
|
|
2501
|
+
timestamp: nowMs,
|
|
2502
|
+
status: "error",
|
|
2503
|
+
message: "No PAT available"
|
|
2504
|
+
};
|
|
2505
|
+
const executeWithToken = async (authToken) => {
|
|
2506
|
+
const benefitCampaign = (await this.fetchCampaigns(authToken, signal)).find((c) => c.actionType === "CLAIM_BENEFIT");
|
|
2507
|
+
if (!benefitCampaign) return {
|
|
2508
|
+
variantId: this.variantId,
|
|
2509
|
+
date: today,
|
|
2510
|
+
timestamp: nowMs,
|
|
2511
|
+
status: "no-campaign",
|
|
2512
|
+
message: "No claimable benefit campaign found for this region"
|
|
2513
|
+
};
|
|
2514
|
+
if (benefitCampaign.claimStatus === "CLAIMED") return {
|
|
2515
|
+
variantId: this.variantId,
|
|
2516
|
+
date: today,
|
|
2517
|
+
timestamp: nowMs,
|
|
2518
|
+
status: "already-claimed",
|
|
2519
|
+
campaignKey: benefitCampaign.campaignKey,
|
|
2520
|
+
amount: benefitCampaign.benefit?.amount ?? 100,
|
|
2521
|
+
message: "Already claimed today"
|
|
2522
|
+
};
|
|
2523
|
+
const claimResult = await this.claimCampaign(authToken, benefitCampaign.campaignId, signal);
|
|
2524
|
+
const isClaimed = claimResult.status === "CLAIMED";
|
|
2525
|
+
const replayed = Boolean(claimResult.replayed);
|
|
2526
|
+
const amount = claimResult.benefit?.amount ?? benefitCampaign.benefit?.amount ?? 100;
|
|
2527
|
+
if (isClaimed) return {
|
|
2528
|
+
variantId: this.variantId,
|
|
2529
|
+
date: today,
|
|
2530
|
+
timestamp: nowMs,
|
|
2531
|
+
status: replayed ? "already-claimed" : "claimed",
|
|
2532
|
+
amount,
|
|
2533
|
+
campaignKey: benefitCampaign.campaignKey,
|
|
2534
|
+
message: replayed ? "Already claimed today" : `Successfully claimed ${amount} credits`
|
|
2535
|
+
};
|
|
2536
|
+
return {
|
|
2537
|
+
variantId: this.variantId,
|
|
2538
|
+
date: today,
|
|
2539
|
+
timestamp: nowMs,
|
|
2540
|
+
status: "error",
|
|
2541
|
+
campaignKey: benefitCampaign.campaignKey,
|
|
2542
|
+
message: `Claim returned status ${claimResult.status ?? "unknown"}`
|
|
2543
|
+
};
|
|
2544
|
+
};
|
|
2545
|
+
try {
|
|
2546
|
+
const creds = await this.authService.getCredentials(pat, signal);
|
|
2547
|
+
try {
|
|
2548
|
+
return await executeWithToken(creds.authToken);
|
|
2549
|
+
} catch (innerError) {
|
|
2550
|
+
if (isQoderAuthRejection(innerError)) {
|
|
2551
|
+
this.logger?.warn?.(`[Qoder CheckIn] Auth token rejected, retrying with fresh exchange`);
|
|
2552
|
+
return await executeWithToken((await this.authService.exchangeFresh(pat, signal)).authToken);
|
|
2553
|
+
}
|
|
2554
|
+
throw innerError;
|
|
2555
|
+
}
|
|
2556
|
+
} catch (error) {
|
|
2557
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
2558
|
+
this.logger?.error?.(`[Qoder CheckIn] Check-in failed: ${message}`);
|
|
2559
|
+
return {
|
|
2560
|
+
variantId: this.variantId,
|
|
2561
|
+
date: today,
|
|
2562
|
+
timestamp: nowMs,
|
|
2563
|
+
status: "error",
|
|
2564
|
+
message
|
|
2565
|
+
};
|
|
2566
|
+
}
|
|
2567
|
+
}
|
|
2568
|
+
};
|
|
2569
|
+
//#endregion
|
|
2411
2570
|
//#region src/qoder/transport/wire/encoding.ts
|
|
2412
2571
|
/**
|
|
2413
2572
|
* Qoder WAF Body encoding algorithm.
|
|
@@ -3058,6 +3217,7 @@ var DefaultQoderTransport = class {
|
|
|
3058
3217
|
metadataTimeoutMs;
|
|
3059
3218
|
auth;
|
|
3060
3219
|
usage;
|
|
3220
|
+
checkInService;
|
|
3061
3221
|
modelFlights = new SingleFlight();
|
|
3062
3222
|
attachments;
|
|
3063
3223
|
imageUploader;
|
|
@@ -3119,6 +3279,13 @@ var DefaultQoderTransport = class {
|
|
|
3119
3279
|
region: this.region,
|
|
3120
3280
|
timeoutMs: this.metadataTimeoutMs
|
|
3121
3281
|
});
|
|
3282
|
+
this.checkInService = new QoderCheckInService({
|
|
3283
|
+
authService: this.auth,
|
|
3284
|
+
fetch: this.fetchImpl,
|
|
3285
|
+
logger: this.logger,
|
|
3286
|
+
region: this.region,
|
|
3287
|
+
timeoutMs: this.metadataTimeoutMs
|
|
3288
|
+
});
|
|
3122
3289
|
}
|
|
3123
3290
|
stream(options, model) {
|
|
3124
3291
|
return this.generate(options, model);
|
|
@@ -3184,6 +3351,10 @@ var DefaultQoderTransport = class {
|
|
|
3184
3351
|
signal: options?.signal
|
|
3185
3352
|
});
|
|
3186
3353
|
}
|
|
3354
|
+
async checkIn(signal) {
|
|
3355
|
+
const pat = await this.requirePat(signal);
|
|
3356
|
+
return this.checkInService.checkIn(pat, signal);
|
|
3357
|
+
}
|
|
3187
3358
|
async requirePat(signal) {
|
|
3188
3359
|
if (signal?.aborted) throw aborted("Qoder request was aborted.");
|
|
3189
3360
|
const pat = (await this.resolvePat()).trim();
|
|
@@ -3838,6 +4009,13 @@ var QoderUpstreamClient = class {
|
|
|
3838
4009
|
size: org.total,
|
|
3839
4010
|
...usage.expiresAt === void 0 ? {} : { packageEndTime: usage.expiresAt }
|
|
3840
4011
|
});
|
|
4012
|
+
const addOn = usage.addOnQuota;
|
|
4013
|
+
if (addOn !== void 0) accounts.push({
|
|
4014
|
+
packageName: "赠送额度",
|
|
4015
|
+
remain: addOn.remaining,
|
|
4016
|
+
size: addOn.total,
|
|
4017
|
+
...usage.expiresAt === void 0 ? {} : { packageEndTime: usage.expiresAt }
|
|
4018
|
+
});
|
|
3841
4019
|
const unlimited = usage.isQuotaExceeded === false && personal !== void 0 && personal.total === 0;
|
|
3842
4020
|
return {
|
|
3843
4021
|
total: usage.totalUsagePercentage ?? personal?.percentage ?? 0,
|
|
@@ -3848,6 +4026,12 @@ var QoderUpstreamClient = class {
|
|
|
3848
4026
|
};
|
|
3849
4027
|
}
|
|
3850
4028
|
/**
|
|
4029
|
+
* Run daily benefit check-in for this client's variant.
|
|
4030
|
+
*/
|
|
4031
|
+
async checkIn(signal) {
|
|
4032
|
+
return this.transport.checkIn(signal);
|
|
4033
|
+
}
|
|
4034
|
+
/**
|
|
3851
4035
|
* Stream one translated chat-completions request.
|
|
3852
4036
|
*
|
|
3853
4037
|
* The first transport chunk is pulled before the response is constructed:
|
|
@@ -4082,7 +4266,7 @@ const DEFAULT_MAX_TOKENS = 32768;
|
|
|
4082
4266
|
const DEFAULT_CONTEXT_WINDOW = 18e4;
|
|
4083
4267
|
//#endregion
|
|
4084
4268
|
//#region src/version.ts
|
|
4085
|
-
const QODER_CONNECT_VERSION = "0.1.
|
|
4269
|
+
const QODER_CONNECT_VERSION = "0.1.8";
|
|
4086
4270
|
//#endregion
|
|
4087
4271
|
//#region src/host-heartbeat.ts
|
|
4088
4272
|
/**
|
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.1.
|
|
5
|
+
"version": "0.1.8",
|
|
6
6
|
"author": "corrinehu",
|
|
7
7
|
"keywords": [
|
|
8
8
|
"dsh-plugin",
|