dsh-codex-subscription 2.2.1 → 2.2.2
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 +10 -6
- package/README.md +10 -6
- package/lib/client.js +1884 -1588
- package/lib/index.js +84 -5
- package/package.json +1 -1
package/lib/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { createRequire } from "node:module";
|
|
2
2
|
import { createHash, randomBytes, randomUUID } from "node:crypto";
|
|
3
|
-
import { closeOpenAICodexWebSocketSessions, resetOpenAICodexWebSocketDebugStats } from "@earendil-works/pi-ai/api/openai-codex-responses";
|
|
3
|
+
import { closeOpenAICodexWebSocketSessions, getOpenAICodexWebSocketDebugStats, resetOpenAICodexWebSocketDebugStats } from "@earendil-works/pi-ai/api/openai-codex-responses";
|
|
4
4
|
import { execFile, spawn } from "node:child_process";
|
|
5
5
|
import { request } from "node:https";
|
|
6
6
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
@@ -662,6 +662,21 @@ function createSubscriptionConnection({ resolveMode = () => "sse", resolveProxy
|
|
|
662
662
|
const namespace = randomUUID();
|
|
663
663
|
const sessions = /* @__PURE__ */ new Set();
|
|
664
664
|
return {
|
|
665
|
+
snapshot() {
|
|
666
|
+
const totals = Object.fromEntries([
|
|
667
|
+
"requests",
|
|
668
|
+
"connectionsCreated",
|
|
669
|
+
"connectionsReused",
|
|
670
|
+
"deltaRequests",
|
|
671
|
+
"websocketFailures",
|
|
672
|
+
"sseFallbacks"
|
|
673
|
+
].map((key) => [key, 0]));
|
|
674
|
+
for (const session of sessions) {
|
|
675
|
+
const stats = getOpenAICodexWebSocketDebugStats(session);
|
|
676
|
+
for (const key of Object.keys(totals)) if (Number.isSafeInteger(stats?.[key]) && stats[key] >= 0) totals[key] = Math.min(Number.MAX_SAFE_INTEGER, totals[key] + stats[key]);
|
|
677
|
+
}
|
|
678
|
+
return totals;
|
|
679
|
+
},
|
|
665
680
|
async prepare(options = {}) {
|
|
666
681
|
if (resolveMode() !== "websocket") return { options: {
|
|
667
682
|
...options,
|
|
@@ -716,6 +731,11 @@ const MAX_BYTES = 2 * 1024 * 1024;
|
|
|
716
731
|
const MAX_AGE_MS = 10080 * 60 * 1e3;
|
|
717
732
|
function createCompactionBridge({ enabled = () => false, threshold = () => 1e5, accountScope, diagnostic = () => {}, now = Date.now }) {
|
|
718
733
|
const scope = new AsyncLocalStorage();
|
|
734
|
+
const stats = {
|
|
735
|
+
requests: 0,
|
|
736
|
+
checkpointsSaved: 0,
|
|
737
|
+
checkpointsReused: 0
|
|
738
|
+
};
|
|
719
739
|
const wrapStream = (factory, options) => (async function* () {
|
|
720
740
|
if (!enabled() || options.provider !== "openai-codex") {
|
|
721
741
|
yield* factory(options);
|
|
@@ -775,6 +795,7 @@ function createCompactionBridge({ enabled = () => false, threshold = () => 1e5,
|
|
|
775
795
|
}
|
|
776
796
|
}
|
|
777
797
|
};
|
|
798
|
+
stats.checkpointsSaved = Math.min(Number.MAX_SAFE_INTEGER, stats.checkpointsSaved + 1);
|
|
778
799
|
}
|
|
779
800
|
yield event;
|
|
780
801
|
}
|
|
@@ -783,6 +804,7 @@ function createCompactionBridge({ enabled = () => false, threshold = () => 1e5,
|
|
|
783
804
|
}
|
|
784
805
|
})();
|
|
785
806
|
return {
|
|
807
|
+
snapshot: () => ({ ...stats }),
|
|
786
808
|
wrapAdapter(adapter) {
|
|
787
809
|
return new Proxy(adapter, { get(target, property) {
|
|
788
810
|
if (property === "stream") return (options) => wrapStream((o) => target.stream(o), options);
|
|
@@ -800,6 +822,11 @@ function createCompactionBridge({ enabled = () => false, threshold = () => 1e5,
|
|
|
800
822
|
preparePayload(payload, contextWindow) {
|
|
801
823
|
const state = scope.getStore();
|
|
802
824
|
if (!state) return payload;
|
|
825
|
+
if (!state.counted) {
|
|
826
|
+
state.counted = true;
|
|
827
|
+
stats.requests = Math.min(Number.MAX_SAFE_INTEGER, stats.requests + 1);
|
|
828
|
+
if (state.suffix) stats.checkpointsReused = Math.min(Number.MAX_SAFE_INTEGER, stats.checkpointsReused + 1);
|
|
829
|
+
}
|
|
803
830
|
const configured = threshold();
|
|
804
831
|
if (!Number.isSafeInteger(configured) || configured < 1e3) throw new Error("Invalid compaction threshold");
|
|
805
832
|
const limit = Number.isFinite(contextWindow) && contextWindow >= 2e3 ? Math.min(configured, Math.floor(contextWindow / 2)) : configured;
|
|
@@ -902,6 +929,8 @@ const RPC_ENDPOINTS = Object.freeze([
|
|
|
902
929
|
"runtime/install",
|
|
903
930
|
"runtime/remove",
|
|
904
931
|
"runtime/cancel",
|
|
932
|
+
"storage/status",
|
|
933
|
+
"storage/clear-forecast",
|
|
905
934
|
"reset-credit/inspect",
|
|
906
935
|
"reset-credit/prepare",
|
|
907
936
|
"reset-credit/consume",
|
|
@@ -2832,7 +2861,7 @@ function openaiCodexSubscriptionProvider({ resolveSpeedMode = () => void 0, reso
|
|
|
2832
2861
|
Object.freeze(["0.82.1", "0.85.1"]);
|
|
2833
2862
|
//#endregion
|
|
2834
2863
|
//#region src/version.js
|
|
2835
|
-
const PACKAGE_VERSION = "2.2.
|
|
2864
|
+
const PACKAGE_VERSION = "2.2.2";
|
|
2836
2865
|
const USER_AGENT = `dsh-codex-subscription/${PACKAGE_VERSION}`;
|
|
2837
2866
|
//#endregion
|
|
2838
2867
|
//#region src/model-catalog.js
|
|
@@ -2996,6 +3025,7 @@ function createOfficialModelCatalog(options = {}) {
|
|
|
2996
3025
|
etag = nonEmpty$2(response.headers.get("etag")) ?? etag;
|
|
2997
3026
|
revision += 1;
|
|
2998
3027
|
outcome = "ok";
|
|
3028
|
+
options.onUpdated?.();
|
|
2999
3029
|
return true;
|
|
3000
3030
|
})();
|
|
3001
3031
|
let rejectAborted;
|
|
@@ -3048,6 +3078,7 @@ function createOfficialModelCatalog(options = {}) {
|
|
|
3048
3078
|
etag = void 0;
|
|
3049
3079
|
refreshStatus = "idle";
|
|
3050
3080
|
revision += 1;
|
|
3081
|
+
options.onUpdated?.();
|
|
3051
3082
|
}
|
|
3052
3083
|
});
|
|
3053
3084
|
}
|
|
@@ -3700,7 +3731,7 @@ function createCodexImageTool(options) {
|
|
|
3700
3731
|
localPath: options.originalImages.originalPath(original.assetId),
|
|
3701
3732
|
...metadata.background === void 0 ? {} : { background: metadata.background },
|
|
3702
3733
|
...metadata.quality === void 0 ? {} : { quality: metadata.quality },
|
|
3703
|
-
|
|
3734
|
+
size: `${original.width}x${original.height}`
|
|
3704
3735
|
};
|
|
3705
3736
|
if (exec.parent !== void 0) exec.deferContext(createUserMessage({
|
|
3706
3737
|
content: imageContent(result),
|
|
@@ -3926,7 +3957,7 @@ function safeRequests(network) {
|
|
|
3926
3957
|
return result;
|
|
3927
3958
|
}
|
|
3928
3959
|
/** Build a support report that deliberately excludes OAuth and account metadata. */
|
|
3929
|
-
async function createSubscriptionDiagnostics({ auth, preferences, login = { phase: "idle" }, network, modelCatalog }) {
|
|
3960
|
+
async function createSubscriptionDiagnostics({ auth, preferences, login = { phase: "idle" }, network, modelCatalog, connection, compaction }) {
|
|
3930
3961
|
let account = { status: "unknown" };
|
|
3931
3962
|
const issues = [];
|
|
3932
3963
|
try {
|
|
@@ -3964,6 +3995,19 @@ async function createSubscriptionDiagnostics({ auth, preferences, login = { phas
|
|
|
3964
3995
|
account,
|
|
3965
3996
|
login,
|
|
3966
3997
|
requests: safeRequests(network),
|
|
3998
|
+
...connection ? { websocket: safeCounters(connection, [
|
|
3999
|
+
"requests",
|
|
4000
|
+
"connectionsCreated",
|
|
4001
|
+
"connectionsReused",
|
|
4002
|
+
"deltaRequests",
|
|
4003
|
+
"websocketFailures",
|
|
4004
|
+
"sseFallbacks"
|
|
4005
|
+
]) } : {},
|
|
4006
|
+
...compaction ? { compaction: safeCounters(compaction, [
|
|
4007
|
+
"requests",
|
|
4008
|
+
"checkpointsSaved",
|
|
4009
|
+
"checkpointsReused"
|
|
4010
|
+
]) } : {},
|
|
3967
4011
|
...catalog && ["fallback", "online"].includes(catalog.source) && [
|
|
3968
4012
|
"idle",
|
|
3969
4013
|
"refreshing",
|
|
@@ -3986,6 +4030,10 @@ async function createSubscriptionDiagnostics({ auth, preferences, login = { phas
|
|
|
3986
4030
|
issues
|
|
3987
4031
|
};
|
|
3988
4032
|
}
|
|
4033
|
+
function safeCounters(source, keys) {
|
|
4034
|
+
const values = source.snapshot();
|
|
4035
|
+
return Object.fromEntries(keys.filter((key) => Number.isSafeInteger(values?.[key]) && values[key] >= 0).map((key) => [key, values[key]]));
|
|
4036
|
+
}
|
|
3989
4037
|
//#endregion
|
|
3990
4038
|
//#region src/usage.js
|
|
3991
4039
|
const CODEX_USAGE_URL = "https://chatgpt.com/backend-api/wham/usage";
|
|
@@ -4683,6 +4731,7 @@ function createQuotaForecastReader({ reader, enabled, now = Date.now, scope = ()
|
|
|
4683
4731
|
return current === generation ? forecast.usage : usage;
|
|
4684
4732
|
},
|
|
4685
4733
|
clear: () => clearHistory(),
|
|
4734
|
+
storage: () => stateStore.usage(),
|
|
4686
4735
|
clearCache() {
|
|
4687
4736
|
generation += 1;
|
|
4688
4737
|
reader.clear();
|
|
@@ -4768,6 +4817,22 @@ var QuotaForecastStateStore = class {
|
|
|
4768
4817
|
async clear() {
|
|
4769
4818
|
await rm(this.filename, { force: true });
|
|
4770
4819
|
}
|
|
4820
|
+
async usage() {
|
|
4821
|
+
try {
|
|
4822
|
+
const info = await lstat(this.filename);
|
|
4823
|
+
if (!info.isFile() || info.isSymbolicLink()) throw Error("Unexpected forecast cache entry");
|
|
4824
|
+
return {
|
|
4825
|
+
bytes: info.size,
|
|
4826
|
+
limit: this.maxBytes
|
|
4827
|
+
};
|
|
4828
|
+
} catch (error) {
|
|
4829
|
+
if (error.code === "ENOENT") return {
|
|
4830
|
+
bytes: 0,
|
|
4831
|
+
limit: this.maxBytes
|
|
4832
|
+
};
|
|
4833
|
+
throw error;
|
|
4834
|
+
}
|
|
4835
|
+
}
|
|
4771
4836
|
};
|
|
4772
4837
|
//#endregion
|
|
4773
4838
|
//#region src/reset-credits.js
|
|
@@ -5066,6 +5131,17 @@ const publicError = (code, message) => ({
|
|
|
5066
5131
|
});
|
|
5067
5132
|
function createSubscriptionRpcHandler({ authHandler, usageReader, resetCreditService, preferences, runtimeManagement, diagnosticsReader, modelCatalog, originalImages, resolveInheritedOriginal, closeConnections, onAccountChanged }) {
|
|
5068
5133
|
return async (endpoint, payload, signal) => {
|
|
5134
|
+
if (endpoint === "storage/status" || endpoint === "storage/clear-forecast") try {
|
|
5135
|
+
signal.throwIfAborted();
|
|
5136
|
+
if (endpoint === "storage/clear-forecast") await usageReader.clear();
|
|
5137
|
+
return {
|
|
5138
|
+
ok: true,
|
|
5139
|
+
value: await usageReader.storage()
|
|
5140
|
+
};
|
|
5141
|
+
} catch (error) {
|
|
5142
|
+
if (signal.aborted) throw error;
|
|
5143
|
+
return publicError("operation-error", "Could not manage forecast cache");
|
|
5144
|
+
}
|
|
5069
5145
|
if ([
|
|
5070
5146
|
"runtime/status",
|
|
5071
5147
|
"runtime/install",
|
|
@@ -5329,6 +5405,7 @@ function apply(ctx, config = {}) {
|
|
|
5329
5405
|
});
|
|
5330
5406
|
ctx.effect(() => ctx.on?.("plugin-manager/install-state", (value) => runtimeManagement.progress(value)));
|
|
5331
5407
|
const modelCatalog = createOfficialModelCatalog({
|
|
5408
|
+
onUpdated: () => ctx.llm.emitAdaptersUpdated?.(),
|
|
5332
5409
|
getAuth: (options) => resolveAuth(options),
|
|
5333
5410
|
readCredential: (options) => store.read(PROVIDER, options),
|
|
5334
5411
|
baseModels: () => baseProvider.getModels(),
|
|
@@ -5635,7 +5712,9 @@ function apply(ctx, config = {}) {
|
|
|
5635
5712
|
preferences,
|
|
5636
5713
|
login: coordinator.supportState(),
|
|
5637
5714
|
network,
|
|
5638
|
-
modelCatalog
|
|
5715
|
+
modelCatalog,
|
|
5716
|
+
connection,
|
|
5717
|
+
compaction
|
|
5639
5718
|
}),
|
|
5640
5719
|
modelCatalog,
|
|
5641
5720
|
closeConnections: () => connection.dispose(),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-codex-subscription",
|
|
3
|
-
"version": "2.2.
|
|
3
|
+
"version": "2.2.2",
|
|
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",
|