dsh-codex-subscription 1.14.3 → 1.14.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/client.js +2147 -2004
- package/lib/index.js +93 -24
- package/package.json +3 -3
package/lib/index.js
CHANGED
|
@@ -1345,7 +1345,7 @@ function openaiCodexSubscriptionProvider({ resolveSpeedMode = () => void 0, reso
|
|
|
1345
1345
|
}
|
|
1346
1346
|
//#endregion
|
|
1347
1347
|
//#region src/version.js
|
|
1348
|
-
const PACKAGE_VERSION = "1.14.
|
|
1348
|
+
const PACKAGE_VERSION = "1.14.4";
|
|
1349
1349
|
const USER_AGENT = `dsh-codex-subscription/${PACKAGE_VERSION}`;
|
|
1350
1350
|
//#endregion
|
|
1351
1351
|
//#region src/model-catalog.js
|
|
@@ -1429,10 +1429,13 @@ function createOfficialModelCatalog(options = {}) {
|
|
|
1429
1429
|
let revision = 0;
|
|
1430
1430
|
let refreshing;
|
|
1431
1431
|
let generation = 0;
|
|
1432
|
+
let refreshStatus = "idle";
|
|
1432
1433
|
const refresh = ({ signal } = {}) => {
|
|
1433
1434
|
if (signal?.aborted) return Promise.reject(signal.reason ?? /* @__PURE__ */ new Error("Codex model catalog refresh aborted"));
|
|
1434
1435
|
if (refreshing?.generation === generation) return refreshing.promise;
|
|
1435
1436
|
const currentGeneration = generation;
|
|
1437
|
+
refreshStatus = "refreshing";
|
|
1438
|
+
let outcome = "idle";
|
|
1436
1439
|
const controller = new AbortController();
|
|
1437
1440
|
const abort = () => {
|
|
1438
1441
|
if (!controller.signal.aborted) controller.abort(signal?.reason ?? /* @__PURE__ */ new Error("Codex model catalog refresh aborted"));
|
|
@@ -1464,7 +1467,10 @@ function createOfficialModelCatalog(options = {}) {
|
|
|
1464
1467
|
signal: requestSignal
|
|
1465
1468
|
});
|
|
1466
1469
|
if (currentGeneration !== generation || requestSignal.aborted) return false;
|
|
1467
|
-
if (response.status === 304)
|
|
1470
|
+
if (response.status === 304) {
|
|
1471
|
+
outcome = "ok";
|
|
1472
|
+
return false;
|
|
1473
|
+
}
|
|
1468
1474
|
if (!response.ok) throw new Error(`Codex model catalog failed (HTTP ${response.status})`);
|
|
1469
1475
|
const remote = parseOfficialModelCatalog(await response.json());
|
|
1470
1476
|
if (currentGeneration !== generation || requestSignal.aborted) return false;
|
|
@@ -1477,6 +1483,7 @@ function createOfficialModelCatalog(options = {}) {
|
|
|
1477
1483
|
metadata = new Map(remote.map((model) => [model.id, model]));
|
|
1478
1484
|
etag = nonEmpty$2(response.headers.get("etag")) ?? etag;
|
|
1479
1485
|
revision += 1;
|
|
1486
|
+
outcome = "ok";
|
|
1480
1487
|
return true;
|
|
1481
1488
|
})();
|
|
1482
1489
|
let rejectAborted;
|
|
@@ -1487,11 +1494,17 @@ function createOfficialModelCatalog(options = {}) {
|
|
|
1487
1494
|
});
|
|
1488
1495
|
timer = scheduleTimeout(() => controller.abort(timeoutError), timeoutMs);
|
|
1489
1496
|
timer.unref?.();
|
|
1490
|
-
const promise = Promise.race([work, abortPromise]).
|
|
1497
|
+
const promise = Promise.race([work, abortPromise]).catch((error) => {
|
|
1498
|
+
outcome = "failed";
|
|
1499
|
+
throw error;
|
|
1500
|
+
}).finally(() => {
|
|
1491
1501
|
cancelTimeout(timer);
|
|
1492
1502
|
signal?.removeEventListener("abort", abort);
|
|
1493
1503
|
requestSignal.removeEventListener("abort", rejectAborted);
|
|
1494
|
-
if (refreshing?.promise === promise)
|
|
1504
|
+
if (refreshing?.promise === promise) {
|
|
1505
|
+
refreshing = void 0;
|
|
1506
|
+
refreshStatus = outcome;
|
|
1507
|
+
}
|
|
1495
1508
|
});
|
|
1496
1509
|
refreshing = {
|
|
1497
1510
|
generation: currentGeneration,
|
|
@@ -1505,6 +1518,10 @@ function createOfficialModelCatalog(options = {}) {
|
|
|
1505
1518
|
getModels: (fallback) => models ?? fallback,
|
|
1506
1519
|
metadata: (modelId) => metadata.get(modelId),
|
|
1507
1520
|
revision: () => revision,
|
|
1521
|
+
status: () => ({
|
|
1522
|
+
source: models === void 0 ? "fallback" : "online",
|
|
1523
|
+
refresh: refreshStatus
|
|
1524
|
+
}),
|
|
1508
1525
|
clear() {
|
|
1509
1526
|
generation += 1;
|
|
1510
1527
|
const flight = refreshing;
|
|
@@ -1513,6 +1530,7 @@ function createOfficialModelCatalog(options = {}) {
|
|
|
1513
1530
|
models = void 0;
|
|
1514
1531
|
metadata = /* @__PURE__ */ new Map();
|
|
1515
1532
|
etag = void 0;
|
|
1533
|
+
refreshStatus = "idle";
|
|
1516
1534
|
revision += 1;
|
|
1517
1535
|
}
|
|
1518
1536
|
});
|
|
@@ -2268,7 +2286,8 @@ var OriginalImageStore = class {
|
|
|
2268
2286
|
await Promise.all([assertPrivateFile(metadataFile), assertPrivateFile(originalFile)]);
|
|
2269
2287
|
const metadata = parseMetadata(await readFile(metadataFile, "utf8"));
|
|
2270
2288
|
if (metadata === void 0 || metadata.image.assetId !== assetId || metadata.sessionId !== sessionId && !originalImageRefsEqual(metadata.image, inherited)) return void 0;
|
|
2271
|
-
const
|
|
2289
|
+
const buffer = await readFile(originalFile);
|
|
2290
|
+
const data = new Uint8Array(buffer.buffer, buffer.byteOffset, buffer.byteLength);
|
|
2272
2291
|
const dimensions = pngDimensions(data);
|
|
2273
2292
|
if (data.byteLength !== metadata.image.bytes || digest(data) !== metadata.image.sha256 || dimensions.width !== metadata.image.width || dimensions.height !== metadata.image.height) return void 0;
|
|
2274
2293
|
return {
|
|
@@ -2284,10 +2303,11 @@ var OriginalImageStore = class {
|
|
|
2284
2303
|
const stored = await this.read(sessionId, assetId, inherited);
|
|
2285
2304
|
if (stored === void 0 || offset >= stored.data.byteLength || offset % 4194304 !== 0) return void 0;
|
|
2286
2305
|
const end = Math.min(stored.data.byteLength, offset + ORIGINAL_IMAGE_CHUNK_BYTES);
|
|
2306
|
+
const chunk = Buffer.from(stored.data.buffer, stored.data.byteOffset + offset, end - offset);
|
|
2287
2307
|
return {
|
|
2288
2308
|
ref: stored.ref,
|
|
2289
2309
|
offset,
|
|
2290
|
-
encoded:
|
|
2310
|
+
encoded: chunk.toString("base64"),
|
|
2291
2311
|
done: end === stored.data.byteLength
|
|
2292
2312
|
};
|
|
2293
2313
|
}
|
|
@@ -2297,6 +2317,7 @@ var OriginalImageStore = class {
|
|
|
2297
2317
|
const requestAreas = /* @__PURE__ */ new Set([
|
|
2298
2318
|
"login",
|
|
2299
2319
|
"model",
|
|
2320
|
+
"catalog",
|
|
2300
2321
|
"quota",
|
|
2301
2322
|
"quota-reset",
|
|
2302
2323
|
"search",
|
|
@@ -2342,7 +2363,7 @@ function safeRequests(network) {
|
|
|
2342
2363
|
return result;
|
|
2343
2364
|
}
|
|
2344
2365
|
/** Build a support report that deliberately excludes OAuth and account metadata. */
|
|
2345
|
-
async function createSubscriptionDiagnostics({ auth, preferences, login = { phase: "idle" }, network }) {
|
|
2366
|
+
async function createSubscriptionDiagnostics({ auth, preferences, login = { phase: "idle" }, network, modelCatalog }) {
|
|
2346
2367
|
let account = { status: "unknown" };
|
|
2347
2368
|
const issues = [];
|
|
2348
2369
|
try {
|
|
@@ -2351,6 +2372,7 @@ async function createSubscriptionDiagnostics({ auth, preferences, login = { phas
|
|
|
2351
2372
|
issues.push({ code: "account-status-unavailable" });
|
|
2352
2373
|
}
|
|
2353
2374
|
const preference = preferences.status();
|
|
2375
|
+
const catalog = modelCatalog?.status?.();
|
|
2354
2376
|
return {
|
|
2355
2377
|
schemaVersion: 3,
|
|
2356
2378
|
package: "dsh-codex-subscription",
|
|
@@ -2363,6 +2385,15 @@ async function createSubscriptionDiagnostics({ auth, preferences, login = { phas
|
|
|
2363
2385
|
account,
|
|
2364
2386
|
login,
|
|
2365
2387
|
requests: safeRequests(network),
|
|
2388
|
+
...catalog && ["fallback", "online"].includes(catalog.source) && [
|
|
2389
|
+
"idle",
|
|
2390
|
+
"refreshing",
|
|
2391
|
+
"ok",
|
|
2392
|
+
"failed"
|
|
2393
|
+
].includes(catalog.refresh) ? { catalog: {
|
|
2394
|
+
source: catalog.source,
|
|
2395
|
+
refresh: catalog.refresh
|
|
2396
|
+
} } : {},
|
|
2366
2397
|
configuration: {
|
|
2367
2398
|
contextMode: preference.contextMode,
|
|
2368
2399
|
quickQuotaMode: preference.quickQuotaMode,
|
|
@@ -2749,40 +2780,67 @@ function forecastUsage(usage, state = { windows: {} }, now = Date.now(), options
|
|
|
2749
2780
|
function createQuotaForecastReader({ reader, enabled, now = Date.now, scope = () => "default", stateStore }) {
|
|
2750
2781
|
let state = { windows: {} };
|
|
2751
2782
|
let loaded = false;
|
|
2783
|
+
let loading;
|
|
2784
|
+
let generation = 0;
|
|
2785
|
+
let historyGeneration = 0;
|
|
2786
|
+
let persistence = Promise.resolve();
|
|
2787
|
+
const persist = (operation) => {
|
|
2788
|
+
const pending = persistence.then(operation);
|
|
2789
|
+
persistence = pending.catch(() => {});
|
|
2790
|
+
return pending;
|
|
2791
|
+
};
|
|
2752
2792
|
const load = async () => {
|
|
2753
2793
|
if (loaded) return;
|
|
2794
|
+
if (loading) return loading;
|
|
2795
|
+
const current = historyGeneration;
|
|
2796
|
+
const pending = Promise.resolve().then(() => stateStore?.load?.()).then((restored) => {
|
|
2797
|
+
if (current !== historyGeneration) return;
|
|
2798
|
+
if (restored?.windows !== null && typeof restored?.windows === "object") state = restored;
|
|
2799
|
+
loaded = true;
|
|
2800
|
+
}).finally(() => {
|
|
2801
|
+
if (loading === pending) loading = void 0;
|
|
2802
|
+
});
|
|
2803
|
+
loading = pending;
|
|
2804
|
+
return pending;
|
|
2805
|
+
};
|
|
2806
|
+
const clearHistory = (clearReader = true) => {
|
|
2807
|
+
generation += 1;
|
|
2808
|
+
historyGeneration += 1;
|
|
2809
|
+
state = { windows: {} };
|
|
2754
2810
|
loaded = true;
|
|
2755
|
-
|
|
2756
|
-
|
|
2811
|
+
if (clearReader) reader.clear();
|
|
2812
|
+
return persist(() => stateStore?.clear?.());
|
|
2757
2813
|
};
|
|
2758
2814
|
return Object.freeze({
|
|
2759
2815
|
async read(options) {
|
|
2816
|
+
const current = generation;
|
|
2817
|
+
const account = await scope();
|
|
2760
2818
|
const usage = await reader.read(options);
|
|
2819
|
+
if (current !== generation) return usage;
|
|
2761
2820
|
await load();
|
|
2821
|
+
const activeAccount = await scope();
|
|
2822
|
+
if (current !== generation || account !== activeAccount) return usage;
|
|
2762
2823
|
if (!enabled()) {
|
|
2763
|
-
|
|
2764
|
-
await stateStore?.clear?.();
|
|
2824
|
+
await clearHistory(false);
|
|
2765
2825
|
return usage;
|
|
2766
2826
|
}
|
|
2767
|
-
const forecast = forecastUsage(usage, state, now(), { scope:
|
|
2827
|
+
const forecast = forecastUsage(usage, state, now(), { scope: account });
|
|
2768
2828
|
state = forecast.state;
|
|
2769
|
-
if (forecast.changed) await stateStore?.save?.(state);
|
|
2770
|
-
return forecast.usage;
|
|
2771
|
-
},
|
|
2772
|
-
async clear() {
|
|
2773
|
-
state = { windows: {} };
|
|
2774
|
-
loaded = true;
|
|
2775
|
-
reader.clear();
|
|
2776
|
-
await stateStore?.clear?.();
|
|
2829
|
+
if (forecast.changed) await persist(() => stateStore?.save?.(forecast.state));
|
|
2830
|
+
return current === generation ? forecast.usage : usage;
|
|
2777
2831
|
},
|
|
2832
|
+
clear: () => clearHistory(),
|
|
2778
2833
|
clearCache() {
|
|
2834
|
+
generation += 1;
|
|
2779
2835
|
reader.clear();
|
|
2780
2836
|
},
|
|
2781
2837
|
async clearScope(targetScope) {
|
|
2838
|
+
generation += 1;
|
|
2782
2839
|
await load();
|
|
2783
2840
|
const prefix = `[${JSON.stringify(cleanSegment(targetScope))},`;
|
|
2784
2841
|
state = { windows: Object.fromEntries(Object.entries(state.windows).filter(([key]) => !key.startsWith(prefix))) };
|
|
2785
|
-
|
|
2842
|
+
const snapshot = state;
|
|
2843
|
+
await persist(() => stateStore?.save?.(snapshot));
|
|
2786
2844
|
}
|
|
2787
2845
|
});
|
|
2788
2846
|
}
|
|
@@ -3547,12 +3605,22 @@ function apply(ctx) {
|
|
|
3547
3605
|
stateStore: new QuotaForecastStateStore({ filename: dshHomePath("state", "codex-subscription", "quota-forecast.json") })
|
|
3548
3606
|
});
|
|
3549
3607
|
ctx.effect(() => {
|
|
3608
|
+
let forecasting = false;
|
|
3550
3609
|
const warmForecast = (value) => {
|
|
3551
|
-
if (normalizeQuickQuotaMode(value["quickQuotaMode"], value["quickQuotaVisible"])
|
|
3610
|
+
if (!(normalizeQuickQuotaMode(value["quickQuotaMode"], value["quickQuotaVisible"]) === "forecast")) {
|
|
3611
|
+
if (forecasting) usageReader.clear().catch((error) => ctx.logger?.debug?.("could not clear Codex quota forecast: %s", error.message));
|
|
3612
|
+
forecasting = false;
|
|
3613
|
+
return;
|
|
3614
|
+
}
|
|
3615
|
+
forecasting = true;
|
|
3552
3616
|
usageReader.read().catch((error) => ctx.logger?.debug?.("could not warm Codex quota forecast: %s", error.message));
|
|
3553
3617
|
};
|
|
3554
3618
|
warmForecast(settings.get());
|
|
3555
|
-
|
|
3619
|
+
const unwatch = settings.watch(warmForecast);
|
|
3620
|
+
return () => {
|
|
3621
|
+
unwatch();
|
|
3622
|
+
usageReader.clearCache();
|
|
3623
|
+
};
|
|
3556
3624
|
}, "codex-subscription: quota forecast warm-up");
|
|
3557
3625
|
const resetCreditService = createCodexResetCreditService({
|
|
3558
3626
|
getAuth: resolveAuth,
|
|
@@ -3569,7 +3637,8 @@ function apply(ctx) {
|
|
|
3569
3637
|
auth,
|
|
3570
3638
|
preferences,
|
|
3571
3639
|
login: coordinator.supportState(),
|
|
3572
|
-
network
|
|
3640
|
+
network,
|
|
3641
|
+
modelCatalog
|
|
3573
3642
|
}),
|
|
3574
3643
|
modelCatalog,
|
|
3575
3644
|
originalImages,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-codex-subscription",
|
|
3
|
-
"version": "1.14.
|
|
3
|
+
"version": "1.14.4",
|
|
4
4
|
"description": "Use ChatGPT and Codex subscriptions in DeepSeek Harness with OAuth, quota, safe resets, web search, images, and Fast mode",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./lib/index.js",
|
|
@@ -127,8 +127,8 @@
|
|
|
127
127
|
},
|
|
128
128
|
"scripts": {
|
|
129
129
|
"build": "tsdown --config tsdown.config.mjs",
|
|
130
|
-
"test:behavior": "node
|
|
131
|
-
"test:delivery": "node
|
|
130
|
+
"test:behavior": "node scripts/run-tests.mjs behavior",
|
|
131
|
+
"test:delivery": "node scripts/run-tests.mjs delivery",
|
|
132
132
|
"test": "node --test tests/*.test.mjs",
|
|
133
133
|
"check": "pnpm run test && pnpm run build && pnpm pack --pack-destination .artifacts"
|
|
134
134
|
}
|