@lyogvce/dsh-codex-subscription 0.2.8 → 0.2.9
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 +85 -38
- package/lib/index.js +66 -28
- package/package.json +1 -1
package/lib/client.js
CHANGED
|
@@ -157,35 +157,49 @@ window.__ModuleLoader__.load({
|
|
|
157
157
|
loading: false,
|
|
158
158
|
error: null
|
|
159
159
|
};
|
|
160
|
+
let confirmedSessionFastModes = {};
|
|
161
|
+
let lastConfirmedFastSeq = 0;
|
|
162
|
+
const latestSeqBySession = new Map();
|
|
163
|
+
const pendingBySession = new Map();
|
|
160
164
|
let inflight = null;
|
|
161
165
|
let inflightForce = false;
|
|
162
166
|
let requestSeq = 0;
|
|
163
167
|
let fastModeSeq = 0;
|
|
168
|
+
let fastMutationEpoch = 0;
|
|
164
169
|
const listeners = new Set();
|
|
165
170
|
function setState(next) {
|
|
166
171
|
state = next;
|
|
167
172
|
for (const listener of listeners) listener();
|
|
168
173
|
}
|
|
174
|
+
function deriveSessionFastModes() {
|
|
175
|
+
if (pendingBySession.size === 0) return confirmedSessionFastModes;
|
|
176
|
+
const merged = { ...confirmedSessionFastModes };
|
|
177
|
+
for (const [k, pending] of pendingBySession) merged[k] = pending.enabled;
|
|
178
|
+
return merged;
|
|
179
|
+
}
|
|
180
|
+
function parseServerSessionFastModes(raw) {
|
|
181
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) return void 0;
|
|
182
|
+
const nextMap = {};
|
|
183
|
+
for (const [k, v] of Object.entries(raw)) if (typeof k === "string" && k !== "" && typeof v === "boolean") nextMap[k] = v;
|
|
184
|
+
return nextMap;
|
|
185
|
+
}
|
|
169
186
|
function mergeFastStateFromPayload(payload, allowSessionReplace) {
|
|
170
187
|
const defaultFastMode = typeof payload?.defaultFastMode === "boolean" ? payload.defaultFastMode : state.defaultFastMode;
|
|
171
|
-
if (allowSessionReplace
|
|
172
|
-
const
|
|
173
|
-
|
|
174
|
-
return {
|
|
175
|
-
defaultFastMode,
|
|
176
|
-
sessionFastModes: nextMap
|
|
177
|
-
};
|
|
188
|
+
if (allowSessionReplace) {
|
|
189
|
+
const parsedMap = parseServerSessionFastModes(payload?.sessionFastModes);
|
|
190
|
+
if (parsedMap !== void 0) confirmedSessionFastModes = parsedMap;
|
|
178
191
|
}
|
|
179
192
|
return {
|
|
180
193
|
defaultFastMode,
|
|
181
|
-
sessionFastModes:
|
|
194
|
+
sessionFastModes: deriveSessionFastModes()
|
|
182
195
|
};
|
|
183
196
|
}
|
|
184
197
|
async function refresh(force = false) {
|
|
185
198
|
if (!force && state.quota !== null && nowFn() - state.quota.fetchedAt < ttlMs) return;
|
|
186
199
|
if (inflight !== null && (!force || inflightForce)) return inflight;
|
|
187
200
|
const seq = ++requestSeq;
|
|
188
|
-
const
|
|
201
|
+
const canReplaceFastAtStart = pendingBySession.size === 0;
|
|
202
|
+
const fastEpochAtStart = fastMutationEpoch;
|
|
189
203
|
inflightForce = force;
|
|
190
204
|
setState({
|
|
191
205
|
...state,
|
|
@@ -210,7 +224,7 @@ window.__ModuleLoader__.load({
|
|
|
210
224
|
}
|
|
211
225
|
const payload = await response.json();
|
|
212
226
|
if (seq !== requestSeq) return;
|
|
213
|
-
const fastState = mergeFastStateFromPayload(payload,
|
|
227
|
+
const fastState = mergeFastStateFromPayload(payload, canReplaceFastAtStart && pendingBySession.size === 0 && fastEpochAtStart === fastMutationEpoch);
|
|
214
228
|
if (payload && payload.ok === true && payload.quota) setState({
|
|
215
229
|
quota: payload.quota,
|
|
216
230
|
...fastState,
|
|
@@ -248,12 +262,26 @@ window.__ModuleLoader__.load({
|
|
|
248
262
|
const nextFastMode = Boolean(enabled);
|
|
249
263
|
const key = normalizeCodexSessionId(sessionId) ?? DEFAULT_SESSION_KEY;
|
|
250
264
|
const seq = ++fastModeSeq;
|
|
265
|
+
fastMutationEpoch += 1;
|
|
266
|
+
latestSeqBySession.set(key, seq);
|
|
267
|
+
pendingBySession.set(key, {
|
|
268
|
+
seq,
|
|
269
|
+
enabled: nextFastMode
|
|
270
|
+
});
|
|
271
|
+
const rollback = (errorMsg) => {
|
|
272
|
+
if (latestSeqBySession.get(key) !== seq) return;
|
|
273
|
+
fastMutationEpoch += 1;
|
|
274
|
+
pendingBySession.delete(key);
|
|
275
|
+
setState({
|
|
276
|
+
...state,
|
|
277
|
+
sessionFastModes: deriveSessionFastModes(),
|
|
278
|
+
error: errorMsg
|
|
279
|
+
});
|
|
280
|
+
};
|
|
251
281
|
setState({
|
|
252
282
|
...state,
|
|
253
|
-
sessionFastModes:
|
|
254
|
-
|
|
255
|
-
[key]: nextFastMode
|
|
256
|
-
}
|
|
283
|
+
sessionFastModes: deriveSessionFastModes(),
|
|
284
|
+
error: null
|
|
257
285
|
});
|
|
258
286
|
try {
|
|
259
287
|
const response = await fetchFn(USAGE_ROUTE_PATH, {
|
|
@@ -267,13 +295,38 @@ window.__ModuleLoader__.load({
|
|
|
267
295
|
fastMode: nextFastMode
|
|
268
296
|
})
|
|
269
297
|
});
|
|
270
|
-
if (
|
|
298
|
+
if (latestSeqBySession.get(key) !== seq) return;
|
|
299
|
+
if (!response.ok) {
|
|
300
|
+
const errPayload = await response.json().catch(() => null);
|
|
301
|
+
rollback(typeof errPayload?.error === "string" && errPayload.error !== "" ? errPayload.error : `HTTP ${response.status}`);
|
|
302
|
+
return;
|
|
303
|
+
}
|
|
271
304
|
const payload = await response.json();
|
|
272
|
-
if (
|
|
305
|
+
if (latestSeqBySession.get(key) !== seq) return;
|
|
306
|
+
if (!payload || payload.ok === false) {
|
|
307
|
+
rollback(typeof payload?.error === "string" && payload.error !== "" ? payload.error : "Invalid response");
|
|
308
|
+
return;
|
|
309
|
+
}
|
|
310
|
+
fastMutationEpoch += 1;
|
|
311
|
+
pendingBySession.delete(key);
|
|
312
|
+
const parsedMap = parseServerSessionFastModes(payload.sessionFastModes);
|
|
313
|
+
if (seq > lastConfirmedFastSeq && parsedMap !== void 0) {
|
|
314
|
+
lastConfirmedFastSeq = seq;
|
|
315
|
+
confirmedSessionFastModes = parsedMap;
|
|
316
|
+
} else confirmedSessionFastModes = {
|
|
317
|
+
...confirmedSessionFastModes,
|
|
318
|
+
[key]: parsedMap?.[key] ?? nextFastMode
|
|
319
|
+
};
|
|
320
|
+
const defaultFastMode = typeof payload.defaultFastMode === "boolean" ? payload.defaultFastMode : state.defaultFastMode;
|
|
321
|
+
setState({
|
|
273
322
|
...state,
|
|
274
|
-
|
|
323
|
+
defaultFastMode,
|
|
324
|
+
sessionFastModes: deriveSessionFastModes(),
|
|
325
|
+
error: null
|
|
275
326
|
});
|
|
276
|
-
} catch {
|
|
327
|
+
} catch (error) {
|
|
328
|
+
rollback(safeErrorMessage(error));
|
|
329
|
+
}
|
|
277
330
|
}
|
|
278
331
|
return {
|
|
279
332
|
getSnapshot: () => state,
|
|
@@ -359,6 +412,18 @@ window.__ModuleLoader__.load({
|
|
|
359
412
|
getSnapshot: () => null,
|
|
360
413
|
subscribe: () => () => {}
|
|
361
414
|
};
|
|
415
|
+
function renderFastBolt(size) {
|
|
416
|
+
return h("svg", {
|
|
417
|
+
className: "dsh-codex-quota-fast-bolt",
|
|
418
|
+
viewBox: "0 0 12 12",
|
|
419
|
+
width: size,
|
|
420
|
+
height: size,
|
|
421
|
+
"aria-hidden": true
|
|
422
|
+
}, h("path", {
|
|
423
|
+
d: "M6.8 1L2.5 6.8h3.1L4.8 11l4.7-5.8H6.4L6.8 1z",
|
|
424
|
+
fill: "currentColor"
|
|
425
|
+
}));
|
|
426
|
+
}
|
|
362
427
|
function CodexQuotaPill(props) {
|
|
363
428
|
const { sessionId, quotaStore, getModelStore, useProjection, useSession, t, getLocale } = props;
|
|
364
429
|
const modelStore = getModelStore(sessionId);
|
|
@@ -462,16 +527,7 @@ window.__ModuleLoader__.load({
|
|
|
462
527
|
r: 5.5,
|
|
463
528
|
strokeDasharray: ringDash,
|
|
464
529
|
transform: "rotate(-90 7 7)"
|
|
465
|
-
})), isFastMode ? h("
|
|
466
|
-
className: "dsh-codex-quota-fast-bolt",
|
|
467
|
-
viewBox: "0 0 12 12",
|
|
468
|
-
width: 11,
|
|
469
|
-
height: 11,
|
|
470
|
-
"aria-hidden": true
|
|
471
|
-
}, h("path", {
|
|
472
|
-
d: "M6.8 1L2.5 6.8h3.1L4.8 11l4.7-5.8H6.4L6.8 1z",
|
|
473
|
-
fill: "currentColor"
|
|
474
|
-
})) : null, h("span", { className: "dsh-codex-quota-text" }, pillText)), open ? h("div", {
|
|
530
|
+
})), isFastMode ? renderFastBolt(11) : null, h("span", { className: "dsh-codex-quota-text" }, pillText)), open ? h("div", {
|
|
475
531
|
className: "dsh-codex-quota-popover",
|
|
476
532
|
role: "dialog",
|
|
477
533
|
"aria-label": t("quota.title"),
|
|
@@ -485,16 +541,7 @@ window.__ModuleLoader__.load({
|
|
|
485
541
|
onClick: () => {
|
|
486
542
|
quotaStore.refresh(true);
|
|
487
543
|
}
|
|
488
|
-
}, quotaSnap.loading ? t("quota.refreshing") : t("quota.refresh"))), quota !== null ? renderWindowSection(formatWindowTitle(quota.primary.windowSeconds, locale, DEFAULT_PRIMARY_WINDOW_SECONDS), quota.primary, primaryReached) : quotaSnap.loading || quotaSnap.error === null ? h("div", { className: "dsh-codex-quota-meta" }, t("quota.loading")) : null, quota?.secondary !== null && quota?.secondary !== void 0 ? renderWindowSection(formatWindowTitle(quota.secondary.windowSeconds, locale, DEFAULT_SECONDARY_WINDOW_SECONDS), quota.secondary, secondaryReached) : null, h("div", { className: "dsh-codex-fast-row" }, h("div", { className: "dsh-codex-fast-info" }, h("div", { className: "dsh-codex-fast-title" }, h("
|
|
489
|
-
className: "dsh-codex-quota-fast-bolt",
|
|
490
|
-
viewBox: "0 0 12 12",
|
|
491
|
-
width: 12,
|
|
492
|
-
height: 12,
|
|
493
|
-
"aria-hidden": true
|
|
494
|
-
}, h("path", {
|
|
495
|
-
d: "M6.8 1L2.5 6.8h3.1L4.8 11l4.7-5.8H6.4L6.8 1z",
|
|
496
|
-
fill: "currentColor"
|
|
497
|
-
})), h("span", null, t("quota.fastTitle"))), h("div", { className: "dsh-codex-fast-desc" }, t("quota.fastDesc"))), h("button", {
|
|
544
|
+
}, quotaSnap.loading ? t("quota.refreshing") : t("quota.refresh"))), quota !== null ? renderWindowSection(formatWindowTitle(quota.primary.windowSeconds, locale, DEFAULT_PRIMARY_WINDOW_SECONDS), quota.primary, primaryReached) : quotaSnap.loading || quotaSnap.error === null ? h("div", { className: "dsh-codex-quota-meta" }, t("quota.loading")) : null, quota?.secondary !== null && quota?.secondary !== void 0 ? renderWindowSection(formatWindowTitle(quota.secondary.windowSeconds, locale, DEFAULT_SECONDARY_WINDOW_SECONDS), quota.secondary, secondaryReached) : null, h("div", { className: "dsh-codex-fast-row" }, h("div", { className: "dsh-codex-fast-info" }, h("div", { className: "dsh-codex-fast-title" }, renderFastBolt(12), h("span", null, t("quota.fastTitle"))), h("div", { className: "dsh-codex-fast-desc" }, t("quota.fastDesc"))), h("button", {
|
|
498
545
|
type: "button",
|
|
499
546
|
role: "switch",
|
|
500
547
|
className: "dsh-codex-fast-switch",
|
package/lib/index.js
CHANGED
|
@@ -35,6 +35,8 @@ const DEFAULT_DISABLED_MODELS = Object.freeze([
|
|
|
35
35
|
function parseRawModelsCache(rawText) {
|
|
36
36
|
const parsed = JSON.parse(rawText);
|
|
37
37
|
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) throw new SyntaxError("models_cache.json root must be a JSON object");
|
|
38
|
+
const models = parsed.models;
|
|
39
|
+
if (!Array.isArray(models) || !models.some((entry) => entry !== null && typeof entry === "object" && typeof entry.slug === "string" && entry.slug.trim() !== "" && entry.visibility === "list")) throw new SyntaxError("models_cache.json must contain at least one visible model entry");
|
|
38
40
|
return parsed;
|
|
39
41
|
}
|
|
40
42
|
function normalizeCodexSessionId(sessionId) {
|
|
@@ -94,7 +96,7 @@ function resolveFastServiceTier(entry) {
|
|
|
94
96
|
if (entry.service_tiers.length === 0 && Array.isArray(entry.additional_speed_tiers)) return entry.additional_speed_tiers.some((t) => typeof t === "string" && t.trim().toLowerCase() === "fast") ? "priority" : void 0;
|
|
95
97
|
return;
|
|
96
98
|
}
|
|
97
|
-
if (Array.isArray(entry.additional_speed_tiers)
|
|
99
|
+
if (Array.isArray(entry.additional_speed_tiers)) return entry.additional_speed_tiers.some((t) => typeof t === "string" && t.trim().toLowerCase() === "fast") ? "priority" : void 0;
|
|
98
100
|
return "priority";
|
|
99
101
|
}
|
|
100
102
|
function parseModelsCache(rawCache, baseModels, disabledModels = [], contextWindows = {}) {
|
|
@@ -218,7 +220,7 @@ function sanitizeCodexPayload(payload, modelMeta, fastMode = false) {
|
|
|
218
220
|
const tier = modelMeta === void 0 ? "priority" : modelMeta.fastServiceTier;
|
|
219
221
|
if (typeof tier === "string" && tier !== "") cleaned.service_tier = tier;
|
|
220
222
|
else delete cleaned.service_tier;
|
|
221
|
-
} else
|
|
223
|
+
} else delete cleaned.service_tier;
|
|
222
224
|
const currentText = cleaned.text && typeof cleaned.text === "object" && !Array.isArray(cleaned.text) ? { ...cleaned.text } : void 0;
|
|
223
225
|
if (modelMeta?.supportVerbosity === false) {
|
|
224
226
|
if (currentText !== void 0) {
|
|
@@ -591,6 +593,12 @@ const DEFAULT_SESSION_KEY = "__default__";
|
|
|
591
593
|
function resolvePluginCacheDir(codexHome) {
|
|
592
594
|
return join(codexHome, PLUGIN_CACHE_DIR_NAME);
|
|
593
595
|
}
|
|
596
|
+
function sliceUtf8Prefix(buf, maxBytes) {
|
|
597
|
+
if (buf.length <= maxBytes) return buf;
|
|
598
|
+
let end = maxBytes;
|
|
599
|
+
while (end > 0 && (buf[end] & 192) === 128) end -= 1;
|
|
600
|
+
return buf.subarray(0, end);
|
|
601
|
+
}
|
|
594
602
|
function appendPluginLog(codexHome, ctx, level, event, detail) {
|
|
595
603
|
const line = `[${new Date().toISOString()}] [${level}] ${event} ${JSON.stringify(detail)}\n`;
|
|
596
604
|
if (level === "ERROR") {
|
|
@@ -598,6 +606,7 @@ function appendPluginLog(codexHome, ctx, level, event, detail) {
|
|
|
598
606
|
else console.error(`[dsh-codex-subscription] ${event}: ${JSON.stringify(detail)}`);
|
|
599
607
|
} else if (level === "WARN") {
|
|
600
608
|
if (typeof ctx.logger?.warn === "function") ctx.logger.warn(`[dsh-codex-subscription] ${event}: ${JSON.stringify(detail)}`);
|
|
609
|
+
else console.warn(`[dsh-codex-subscription] ${event}: ${JSON.stringify(detail)}`);
|
|
601
610
|
}
|
|
602
611
|
try {
|
|
603
612
|
const cacheDir = resolvePluginCacheDir(codexHome);
|
|
@@ -606,18 +615,24 @@ function appendPluginLog(codexHome, ctx, level, event, detail) {
|
|
|
606
615
|
mode: 448
|
|
607
616
|
});
|
|
608
617
|
const logPath = join(cacheDir, LOG_FILE_NAME);
|
|
618
|
+
const rawLineBuf = Buffer.from(line, "utf8");
|
|
619
|
+
const lineBuf = rawLineBuf.length <= MAX_LOG_FILE_BYTES ? rawLineBuf : Buffer.concat([sliceUtf8Prefix(rawLineBuf, 524287), Buffer.from("\n", "utf8")]);
|
|
620
|
+
let st;
|
|
609
621
|
try {
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
622
|
+
st = statSync(logPath);
|
|
623
|
+
} catch {
|
|
624
|
+
st = void 0;
|
|
625
|
+
}
|
|
626
|
+
if (st !== void 0 && st.size + lineBuf.length > MAX_LOG_FILE_BYTES) {
|
|
627
|
+
const buf = readFileSync(logPath);
|
|
628
|
+
const keepBudget = Math.max(0, Math.floor(MAX_LOG_FILE_BYTES / 2) - lineBuf.length);
|
|
629
|
+
const startOffset = Math.max(0, buf.length - keepBudget);
|
|
630
|
+
const newlineIdx = keepBudget > 0 ? buf.indexOf(10, startOffset) : -1;
|
|
631
|
+
const tail = newlineIdx >= 0 && newlineIdx + 1 < buf.length ? buf.subarray(newlineIdx + 1) : Buffer.alloc(0);
|
|
632
|
+
writeFileAtomicSync(logPath, Buffer.concat([tail, lineBuf]));
|
|
633
|
+
return;
|
|
634
|
+
}
|
|
635
|
+
appendFileSync(logPath, lineBuf, { mode: 384 });
|
|
621
636
|
} catch {}
|
|
622
637
|
}
|
|
623
638
|
function readBackupCache(codexHome) {
|
|
@@ -627,10 +642,12 @@ function readBackupCache(codexHome) {
|
|
|
627
642
|
return;
|
|
628
643
|
}
|
|
629
644
|
}
|
|
630
|
-
function writeBackupCache(codexHome, raw) {
|
|
645
|
+
function writeBackupCache(codexHome, ctx, raw) {
|
|
631
646
|
try {
|
|
632
647
|
writeFileAtomicSync(join(resolvePluginCacheDir(codexHome), BACKUP_CACHE_FILE_NAME), `${JSON.stringify(raw, null, 2)}\n`);
|
|
633
|
-
} catch {
|
|
648
|
+
} catch (error) {
|
|
649
|
+
appendPluginLog(codexHome, ctx, "WARN", "catalog.backup_write_error", { error: safeErrorMessage(error) });
|
|
650
|
+
}
|
|
634
651
|
}
|
|
635
652
|
function readPersistedSessionFastModes(codexHome) {
|
|
636
653
|
const result = new Map();
|
|
@@ -642,10 +659,12 @@ function readPersistedSessionFastModes(codexHome) {
|
|
|
642
659
|
} catch {}
|
|
643
660
|
return result;
|
|
644
661
|
}
|
|
645
|
-
function writePersistedSessionFastModes(codexHome, sessionFastModes) {
|
|
662
|
+
function writePersistedSessionFastModes(codexHome, ctx, sessionFastModes) {
|
|
646
663
|
try {
|
|
647
664
|
writeFileAtomicSync(join(resolvePluginCacheDir(codexHome), RUNTIME_STATE_FILE_NAME), `${JSON.stringify({ sessionFastModes: Object.fromEntries(sessionFastModes) }, null, 2)}\n`);
|
|
648
|
-
} catch {
|
|
665
|
+
} catch (error) {
|
|
666
|
+
appendPluginLog(codexHome, ctx, "WARN", "fast_mode.persist_error", { error: safeErrorMessage(error) });
|
|
667
|
+
}
|
|
649
668
|
}
|
|
650
669
|
const Config = z.object({
|
|
651
670
|
fastMode: z.boolean().default(false).description("新会话默认是否开启 Fast 极速模式(未填时默认 false;单会话可在右下角限额弹窗内独立切换)").volatile(),
|
|
@@ -706,7 +725,7 @@ function apply(ctx, config = {}) {
|
|
|
706
725
|
if (oldest === void 0) break;
|
|
707
726
|
sessionFastModes.delete(oldest);
|
|
708
727
|
}
|
|
709
|
-
writePersistedSessionFastModes(codexHome, sessionFastModes);
|
|
728
|
+
writePersistedSessionFastModes(codexHome, ctx, sessionFastModes);
|
|
710
729
|
appendPluginLog(codexHome, ctx, "INFO", "fast_mode.updated", {
|
|
711
730
|
sessionId: key,
|
|
712
731
|
fastMode: nextFastMode
|
|
@@ -719,6 +738,7 @@ function apply(ctx, config = {}) {
|
|
|
719
738
|
});
|
|
720
739
|
let fileSignature;
|
|
721
740
|
let cachedRaw;
|
|
741
|
+
let lastRejectedRaw;
|
|
722
742
|
let rawRevision = 0;
|
|
723
743
|
let snapshotSignature;
|
|
724
744
|
let currentCatalog = {
|
|
@@ -782,6 +802,7 @@ function apply(ctx, config = {}) {
|
|
|
782
802
|
const contextWindows = getContextWindows();
|
|
783
803
|
const setActiveRaw = (next) => {
|
|
784
804
|
cachedRaw = next;
|
|
805
|
+
lastRejectedRaw = void 0;
|
|
785
806
|
rawRevision += 1;
|
|
786
807
|
};
|
|
787
808
|
const tryRestoreFromBackup = (extra, minVersion) => {
|
|
@@ -820,16 +841,20 @@ function apply(ctx, config = {}) {
|
|
|
820
841
|
fileSignature = nextFileSig;
|
|
821
842
|
try {
|
|
822
843
|
const incomingRaw = parseRawModelsCache(readFileSync(cachePath, "utf8"));
|
|
823
|
-
if (cachedRaw !== void 0 && compareClientVersions(incomingRaw.client_version, cachedRaw.client_version) < 0)
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
844
|
+
if (cachedRaw !== void 0 && compareClientVersions(incomingRaw.client_version, cachedRaw.client_version) < 0) {
|
|
845
|
+
if (!isSameModelsCatalogPayload(lastRejectedRaw, incomingRaw)) {
|
|
846
|
+
lastRejectedRaw = incomingRaw;
|
|
847
|
+
appendPluginLog(codexHome, ctx, "WARN", "catalog.downgrade_rejected", {
|
|
848
|
+
cachePath,
|
|
849
|
+
keptVersion: cachedRaw.client_version ?? "0.163.0",
|
|
850
|
+
rejectedVersion: incomingRaw.client_version ?? "unknown",
|
|
851
|
+
incomingFetchedAt: incomingRaw.fetched_at ?? null
|
|
852
|
+
});
|
|
853
|
+
}
|
|
854
|
+
} else if (cachedRaw !== void 0 || !tryRestoreFromBackup({ diskVersion: incomingRaw.client_version ?? "unknown" }, incomingRaw.client_version)) {
|
|
830
855
|
if (!isSameModelsCatalogPayload(cachedRaw, incomingRaw)) {
|
|
831
856
|
setActiveRaw(incomingRaw);
|
|
832
|
-
writeBackupCache(codexHome, incomingRaw);
|
|
857
|
+
writeBackupCache(codexHome, ctx, incomingRaw);
|
|
833
858
|
appendPluginLog(codexHome, ctx, "INFO", "catalog.load", {
|
|
834
859
|
cachePath,
|
|
835
860
|
clientVersion: incomingRaw.client_version ?? "0.163.0",
|
|
@@ -917,8 +942,21 @@ function apply(ctx, config = {}) {
|
|
|
917
942
|
requestBody: "buffered",
|
|
918
943
|
fetch: async (request) => {
|
|
919
944
|
if (request.method === "POST") {
|
|
920
|
-
|
|
921
|
-
|
|
945
|
+
let body;
|
|
946
|
+
try {
|
|
947
|
+
body = await request.json();
|
|
948
|
+
} catch {
|
|
949
|
+
body = null;
|
|
950
|
+
}
|
|
951
|
+
const record = body !== null && typeof body === "object" && !Array.isArray(body) ? body : null;
|
|
952
|
+
if (record === null || typeof record.fastMode !== "boolean" || record.sessionId !== void 0 && typeof record.sessionId !== "string") return new Response(JSON.stringify({
|
|
953
|
+
ok: false,
|
|
954
|
+
error: "Invalid request body: boolean fastMode is required"
|
|
955
|
+
}), {
|
|
956
|
+
status: 400,
|
|
957
|
+
headers: { "content-type": "application/json" }
|
|
958
|
+
});
|
|
959
|
+
setSessionFastMode(record.sessionId, record.fastMode);
|
|
922
960
|
return new Response(JSON.stringify({
|
|
923
961
|
ok: true,
|
|
924
962
|
defaultFastMode: getConfigFastMode(),
|