dsh-codex-subscription 2.4.1 → 2.4.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 +2 -1
- package/README.md +2 -1
- package/lib/client.js +208 -7
- package/lib/index.js +107 -3
- package/package.json +1 -1
package/README.en.md
CHANGED
|
@@ -33,6 +33,7 @@ Subscription access, model controls, quota management, and image creation in one
|
|
|
33
33
|
| **Subscription sign-in** | Sign in to ChatGPT and use Codex subscription models without an API key | Normal chat needs no Codex CLI |
|
|
34
34
|
| **Model catalog sync** | Read available models and reasoning levels from your account, with manual refresh; models marked for retirement show their retirement date next to the model name, without automatically switching your selection | New models appear when your account offers them; the account catalog is the only source, so signed out or when it cannot be read no models are shown and no bundled list stands in |
|
|
35
35
|
| **Model list** | Show or hide individual models in the composer picker under Models & runtime | Display only; selected models and requests still work |
|
|
36
|
+
| **Default model** | Choose the model a new conversation opens with under Models & runtime → Models | Writes the DSH default model setting, the same one a model switch inside a chat writes; unset it to follow the DSH default |
|
|
36
37
|
| **Reasoning levels** | Choose supported reasoning effort in the composer | Levels vary by model |
|
|
37
38
|
| **Speed tiers** | Switch supported models between Standard and Fast; Ultrafast (Beta) too when the account catalog offers it, with a lightning indicator | Standard by default; Fast and Ultrafast increase usage, and Ultrafast is Pro 500 only today |
|
|
38
39
|
| **Response verbosity** | Request short, medium, or detailed responses | Follows the model default unless changed |
|
|
@@ -104,7 +105,7 @@ This plugin supports the latest DeepSeek Harness release recorded in its package
|
|
|
104
105
|
2. Paste this package name, with its version, into the **Package name or address** field:
|
|
105
106
|
|
|
106
107
|
```text
|
|
107
|
-
dsh-codex-subscription@2.4.
|
|
108
|
+
dsh-codex-subscription@2.4.2
|
|
108
109
|
```
|
|
109
110
|
|
|
110
111
|
3. Click **Install** and wait for completion. Follow the page instructions; save your work before restarting if requested.
|
package/README.md
CHANGED
|
@@ -33,6 +33,7 @@
|
|
|
33
33
|
| **订阅登录** | 直接登录 ChatGPT,使用 Codex 订阅模型,无需 API Key | 普通聊天无需 Codex CLI |
|
|
34
34
|
| **模型目录同步** | 自动读取账号可用模型与推理档位,支持手动刷新;目录标注退役的模型会在模型名称旁显示退役日期,不会自动切换你的选择 | 新型号以账号目录开放情况为准;模型只来自账号目录,未登录或读取失败时不显示任何模型,也不使用内置列表 |
|
|
35
35
|
| **模型列表** | 在“模型与运行”中逐个显示或隐藏输入框中的模型 | 仅影响列表显示;已选模型和请求不受影响 |
|
|
36
|
+
| **默认模型** | 在“模型与运行 → 模型”里选择每次新建会话默认使用的模型 | 写入 DSH 的默认模型设置,与在对话里切换模型是同一处;未设置时跟随 DSH 默认 |
|
|
36
37
|
| **推理等级** | 在输入框选择模型支持的推理档位 | 档位随模型变化 |
|
|
37
38
|
| **速度档位** | 在支持的模型上切换标准 / Fast;账号目录提供时还有 Ultrafast(Beta),输入框显示闪电标识 | 默认标准;Fast 和 Ultrafast 会增加用量消耗,Ultrafast 目前仅 Pro 500 |
|
|
38
39
|
| **输出详略** | 选择简短、适中或详细的回答偏好 | 默认跟随模型 |
|
|
@@ -104,7 +105,7 @@
|
|
|
104
105
|
2. 在 **包名或地址** 输入框中粘贴下面的包名(已带版本号):
|
|
105
106
|
|
|
106
107
|
```text
|
|
107
|
-
dsh-codex-subscription@2.4.
|
|
108
|
+
dsh-codex-subscription@2.4.2
|
|
108
109
|
```
|
|
109
110
|
|
|
110
111
|
3. 点击 **安装**,等待安装完成;按页面提示操作,需要重启时先保存工作。
|
package/lib/client.js
CHANGED
|
@@ -886,6 +886,8 @@ window.__ModuleLoader__.load({
|
|
|
886
886
|
"preferences/status",
|
|
887
887
|
"preferences/models",
|
|
888
888
|
"preferences/update",
|
|
889
|
+
"default-model/status",
|
|
890
|
+
"default-model/select",
|
|
889
891
|
"runtime/status",
|
|
890
892
|
"runtime/install",
|
|
891
893
|
"runtime/remove",
|
|
@@ -5541,6 +5543,14 @@ window.__ModuleLoader__.load({
|
|
|
5541
5543
|
advancedModelSearch: "模型与搜索",
|
|
5542
5544
|
modelsSectionTitle: "模型",
|
|
5543
5545
|
searchSectionTitle: "搜索",
|
|
5546
|
+
defaultModelTitle: "默认模型",
|
|
5547
|
+
defaultModelHint: "新建会话时默认使用的模型,与在对话里切换模型写的是同一处 DSH 默认模型设置。",
|
|
5548
|
+
defaultModelFollow: "跟随 DSH 默认",
|
|
5549
|
+
defaultModelFollowHint: "当前跟随 DSH 默认模型:{value}。选择一个 Codex 模型,之后每次新建会话都用它。",
|
|
5550
|
+
defaultModelUnknown: "未知",
|
|
5551
|
+
defaultModelUnavailable: "当前 DSH 版本没有提供默认模型服务,无法在这里设置。",
|
|
5552
|
+
defaultModelNoCatalog: "登录并加载模型后即可选择默认模型。",
|
|
5553
|
+
defaultModelFailed: "默认模型读取或保存失败,请重试,或改在对话中切换模型。",
|
|
5544
5554
|
inputImageDetail: "输入图片精度",
|
|
5545
5555
|
inputImageDetailHint: "控制发送给模型的图片精度,精度越高输入 token 用量越大。",
|
|
5546
5556
|
inputImageDetail_auto: "自动",
|
|
@@ -6099,6 +6109,14 @@ window.__ModuleLoader__.load({
|
|
|
6099
6109
|
advancedModelSearch: "Models and search",
|
|
6100
6110
|
modelsSectionTitle: "Models",
|
|
6101
6111
|
searchSectionTitle: "Search",
|
|
6112
|
+
defaultModelTitle: "Default model",
|
|
6113
|
+
defaultModelHint: "The model a new conversation opens with. This writes the same DSH default model setting as switching the model inside a chat.",
|
|
6114
|
+
defaultModelFollow: "Follow DSH default",
|
|
6115
|
+
defaultModelFollowHint: "Following the DSH default: {value}. Pick a Codex model to make every new conversation start with it.",
|
|
6116
|
+
defaultModelUnknown: "unknown",
|
|
6117
|
+
defaultModelUnavailable: "This DSH version provides no default-model service, so it cannot be set here.",
|
|
6118
|
+
defaultModelNoCatalog: "Sign in and load models to choose a default model.",
|
|
6119
|
+
defaultModelFailed: "Reading or saving the default model failed. Retry, or switch the model inside a chat.",
|
|
6102
6120
|
inputImageDetail: "Input image detail",
|
|
6103
6121
|
inputImageDetailHint: "Controls the detail level of images sent to the model. Higher detail uses more input tokens.",
|
|
6104
6122
|
inputImageDetail_auto: "Auto",
|
|
@@ -8088,7 +8106,6 @@ window.__ModuleLoader__.load({
|
|
|
8088
8106
|
verbosityModels = Array.isArray(value?.verbosityModels) ? value.verbosityModels : [];
|
|
8089
8107
|
fastModels = Array.isArray(value?.fastModels) ? value.fastModels : void 0;
|
|
8090
8108
|
ultrafastModels = Array.isArray(value?.ultrafastModels) ? value.ultrafastModels : [];
|
|
8091
|
-
ultrafastModels = Array.isArray(value?.ultrafastModels) ? value.ultrafastModels : [];
|
|
8092
8109
|
catalogStatus = value?.catalogStatus;
|
|
8093
8110
|
}
|
|
8094
8111
|
} else acceptFallback(value);
|
|
@@ -8138,6 +8155,21 @@ window.__ModuleLoader__.load({
|
|
|
8138
8155
|
}
|
|
8139
8156
|
}
|
|
8140
8157
|
};
|
|
8158
|
+
const accepted = (entries, wait = 1500) => new Promise((resolve) => {
|
|
8159
|
+
const matches = () => entries.every(([field, value]) => JSON.stringify(nativeSnapshot().value?.[field]) === JSON.stringify(value));
|
|
8160
|
+
if (matches()) return resolve(true);
|
|
8161
|
+
let timer;
|
|
8162
|
+
const stop = scope.subscribe(() => {
|
|
8163
|
+
if (!matches()) return;
|
|
8164
|
+
clearTimeout(timer);
|
|
8165
|
+
stop();
|
|
8166
|
+
resolve(true);
|
|
8167
|
+
});
|
|
8168
|
+
timer = setTimeout(() => {
|
|
8169
|
+
stop();
|
|
8170
|
+
resolve(matches());
|
|
8171
|
+
}, wait);
|
|
8172
|
+
});
|
|
8141
8173
|
const set = async (patch) => {
|
|
8142
8174
|
if (disposed || snapshot.status !== "ready" || snapshot.writable !== true) return;
|
|
8143
8175
|
const current = ++generation;
|
|
@@ -8154,8 +8186,7 @@ window.__ModuleLoader__.load({
|
|
|
8154
8186
|
await scope.set(field, value);
|
|
8155
8187
|
}
|
|
8156
8188
|
if (current !== generation) return;
|
|
8157
|
-
|
|
8158
|
-
error = entries.some(([field, value]) => JSON.stringify(accepted?.[field]) !== JSON.stringify(value));
|
|
8189
|
+
error = !await accepted(entries);
|
|
8159
8190
|
if (error) failedPatch = patch;
|
|
8160
8191
|
pendingPatch = void 0;
|
|
8161
8192
|
} else {
|
|
@@ -8196,6 +8227,97 @@ window.__ModuleLoader__.load({
|
|
|
8196
8227
|
};
|
|
8197
8228
|
}
|
|
8198
8229
|
//#endregion
|
|
8230
|
+
//#region src/default-model-controller.js
|
|
8231
|
+
const INITIAL = Object.freeze({
|
|
8232
|
+
status: "loading",
|
|
8233
|
+
available: false,
|
|
8234
|
+
managed: false,
|
|
8235
|
+
provider: void 0,
|
|
8236
|
+
model: void 0,
|
|
8237
|
+
reasoningEffort: void 0,
|
|
8238
|
+
saving: false,
|
|
8239
|
+
error: false
|
|
8240
|
+
});
|
|
8241
|
+
const adopt = (value) => ({
|
|
8242
|
+
status: "ready",
|
|
8243
|
+
error: false,
|
|
8244
|
+
available: value?.available === true,
|
|
8245
|
+
managed: value?.managed === true,
|
|
8246
|
+
provider: value?.provider,
|
|
8247
|
+
model: value?.model,
|
|
8248
|
+
reasoningEffort: value?.reasoningEffort
|
|
8249
|
+
});
|
|
8250
|
+
/**
|
|
8251
|
+
* Read and update the DSH default model behind one settings control. The Host
|
|
8252
|
+
* owns the value, so a load always replaces the local projection; a rejected
|
|
8253
|
+
* write keeps the last known value and only raises the error flag.
|
|
8254
|
+
*/
|
|
8255
|
+
function createDefaultModelController(rpc) {
|
|
8256
|
+
let snapshot = INITIAL;
|
|
8257
|
+
let disposed = false;
|
|
8258
|
+
let generation = 0;
|
|
8259
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
8260
|
+
const publish = (next) => {
|
|
8261
|
+
snapshot = Object.freeze({
|
|
8262
|
+
...snapshot,
|
|
8263
|
+
...next
|
|
8264
|
+
});
|
|
8265
|
+
for (const listener of listeners) listener();
|
|
8266
|
+
};
|
|
8267
|
+
const load = async () => {
|
|
8268
|
+
const current = ++generation;
|
|
8269
|
+
try {
|
|
8270
|
+
const value = unwrap(await rpc.call(CHANNEL, "default-model/status", {}));
|
|
8271
|
+
if (disposed || current !== generation) return;
|
|
8272
|
+
publish(adopt(value));
|
|
8273
|
+
} catch {
|
|
8274
|
+
if (disposed || current !== generation) return;
|
|
8275
|
+
publish({
|
|
8276
|
+
status: "error",
|
|
8277
|
+
error: true
|
|
8278
|
+
});
|
|
8279
|
+
}
|
|
8280
|
+
};
|
|
8281
|
+
const select = async (model) => {
|
|
8282
|
+
if (disposed) return false;
|
|
8283
|
+
const current = ++generation;
|
|
8284
|
+
publish({
|
|
8285
|
+
saving: true,
|
|
8286
|
+
error: false
|
|
8287
|
+
});
|
|
8288
|
+
try {
|
|
8289
|
+
const value = unwrap(await rpc.call(CHANNEL, "default-model/select", { model }));
|
|
8290
|
+
if (disposed || current !== generation) return false;
|
|
8291
|
+
publish({
|
|
8292
|
+
...adopt(value),
|
|
8293
|
+
saving: false
|
|
8294
|
+
});
|
|
8295
|
+
return true;
|
|
8296
|
+
} catch {
|
|
8297
|
+
if (disposed || current !== generation) return false;
|
|
8298
|
+
publish({
|
|
8299
|
+
saving: false,
|
|
8300
|
+
error: true
|
|
8301
|
+
});
|
|
8302
|
+
return false;
|
|
8303
|
+
}
|
|
8304
|
+
};
|
|
8305
|
+
return Object.freeze({
|
|
8306
|
+
getSnapshot: () => snapshot,
|
|
8307
|
+
subscribe: (listener) => {
|
|
8308
|
+
listeners.add(listener);
|
|
8309
|
+
return () => listeners.delete(listener);
|
|
8310
|
+
},
|
|
8311
|
+
load,
|
|
8312
|
+
select,
|
|
8313
|
+
dispose: () => {
|
|
8314
|
+
disposed = true;
|
|
8315
|
+
generation += 1;
|
|
8316
|
+
listeners.clear();
|
|
8317
|
+
}
|
|
8318
|
+
});
|
|
8319
|
+
}
|
|
8320
|
+
//#endregion
|
|
8199
8321
|
//#region src/account-status-controller.js
|
|
8200
8322
|
const DEFAULT_TIMEOUT_MS = 1e4;
|
|
8201
8323
|
const STATUS_ERROR_CODES = /* @__PURE__ */ new Set([
|
|
@@ -8481,7 +8603,7 @@ window.__ModuleLoader__.load({
|
|
|
8481
8603
|
}
|
|
8482
8604
|
//#endregion
|
|
8483
8605
|
//#region src/version.js
|
|
8484
|
-
const PACKAGE_VERSION = "2.4.
|
|
8606
|
+
const PACKAGE_VERSION = "2.4.2";
|
|
8485
8607
|
//#endregion
|
|
8486
8608
|
//#region src/client-recovery.js
|
|
8487
8609
|
async function recoveryCall(rpc, endpoint, payload = {}, timeoutMs = 1e4) {
|
|
@@ -9383,6 +9505,76 @@ window.__ModuleLoader__.load({
|
|
|
9383
9505
|
] });
|
|
9384
9506
|
}
|
|
9385
9507
|
//#endregion
|
|
9508
|
+
//#region src/default-model-preferences.jsx
|
|
9509
|
+
/**
|
|
9510
|
+
* Choose the model a new conversation opens with. DSH owns that selection, so
|
|
9511
|
+
* the control always shows the live value, including a model chosen in a chat
|
|
9512
|
+
* and any non-subscription default the user set elsewhere.
|
|
9513
|
+
*/
|
|
9514
|
+
function DefaultModelPreference({ preference, defaultModel, t }) {
|
|
9515
|
+
const snapshot = (0, react.useSyncExternalStore)(defaultModel.subscribe, defaultModel.getSnapshot);
|
|
9516
|
+
const models = usePreferenceSnapshot(preference).availableModels;
|
|
9517
|
+
const [open, setOpen] = (0, react.useState)(false);
|
|
9518
|
+
(0, react.useEffect)(() => {
|
|
9519
|
+
defaultModel.load();
|
|
9520
|
+
}, [defaultModel]);
|
|
9521
|
+
const selected = models.find((model) => model.id === snapshot.model);
|
|
9522
|
+
const label = snapshot.managed ? selected?.name ?? snapshot.model : t("defaultModelFollow");
|
|
9523
|
+
const current = snapshot.provider === void 0 ? t("defaultModelUnknown") : `${snapshot.provider} / ${snapshot.model ?? t("defaultModelUnknown")}`;
|
|
9524
|
+
const hint = snapshot.status === "error" ? t("defaultModelFailed") : snapshot.available !== true ? t("defaultModelUnavailable") : models.length === 0 ? t("defaultModelNoCatalog") : snapshot.managed ? t("defaultModelHint") : fill(t("defaultModelFollowHint"), { value: current });
|
|
9525
|
+
const items = models.map((model) => ({
|
|
9526
|
+
id: model.id,
|
|
9527
|
+
label: model.name
|
|
9528
|
+
}));
|
|
9529
|
+
const disabled = snapshot.saving || snapshot.available !== true || models.length === 0;
|
|
9530
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
9531
|
+
className: "codexSubscriptionPreference",
|
|
9532
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
9533
|
+
className: "codexSubscriptionPreferenceCopy",
|
|
9534
|
+
children: [
|
|
9535
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
9536
|
+
className: "codexSubscriptionPreferenceLabel",
|
|
9537
|
+
children: t("defaultModelTitle")
|
|
9538
|
+
}),
|
|
9539
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
9540
|
+
className: "codexSubscriptionPreferenceHint",
|
|
9541
|
+
children: hint
|
|
9542
|
+
}),
|
|
9543
|
+
snapshot.error ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
9544
|
+
className: "codexSubscriptionError",
|
|
9545
|
+
role: "alert",
|
|
9546
|
+
children: t("defaultModelFailed")
|
|
9547
|
+
}) : null
|
|
9548
|
+
]
|
|
9549
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Menu, {
|
|
9550
|
+
open,
|
|
9551
|
+
items,
|
|
9552
|
+
selectedId: snapshot.managed ? snapshot.model : void 0,
|
|
9553
|
+
onSelect: (value) => {
|
|
9554
|
+
setOpen(false);
|
|
9555
|
+
defaultModel.select(value);
|
|
9556
|
+
},
|
|
9557
|
+
onClose: () => setOpen(false),
|
|
9558
|
+
align: "end",
|
|
9559
|
+
side: "bottom",
|
|
9560
|
+
portal: true,
|
|
9561
|
+
compact: true,
|
|
9562
|
+
anchor: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
9563
|
+
className: "codexSubscriptionContextTrigger",
|
|
9564
|
+
type: "button",
|
|
9565
|
+
"aria-label": t("defaultModelTitle"),
|
|
9566
|
+
"aria-haspopup": "menu",
|
|
9567
|
+
"aria-expanded": open,
|
|
9568
|
+
"aria-busy": snapshot.saving || void 0,
|
|
9569
|
+
title: label,
|
|
9570
|
+
disabled,
|
|
9571
|
+
onClick: () => setOpen((value) => !value),
|
|
9572
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: label }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconChevronDownOutline14, {})]
|
|
9573
|
+
})
|
|
9574
|
+
})]
|
|
9575
|
+
});
|
|
9576
|
+
}
|
|
9577
|
+
//#endregion
|
|
9386
9578
|
//#region src/client-runtime-management.jsx
|
|
9387
9579
|
function RuntimeManagement({ rpc, preference, t }) {
|
|
9388
9580
|
const [state, setState] = (0, react.useState)();
|
|
@@ -9995,7 +10187,7 @@ window.__ModuleLoader__.load({
|
|
|
9995
10187
|
}) : null]
|
|
9996
10188
|
});
|
|
9997
10189
|
}
|
|
9998
|
-
function PreferencesCard({ preference, rpc, t, section = "display" }) {
|
|
10190
|
+
function PreferencesCard({ preference, rpc, t, defaultModel, section = "display" }) {
|
|
9999
10191
|
const snapshot = usePreferenceSnapshot(preference);
|
|
10000
10192
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
10001
10193
|
className: section === "advanced" ? "codexSubscriptionAdvancedPreferences" : "codexSubscriptionCard codexSubscriptionPreferencesCard",
|
|
@@ -10005,6 +10197,11 @@ window.__ModuleLoader__.load({
|
|
|
10005
10197
|
"aria-label": t("modelsSectionTitle"),
|
|
10006
10198
|
children: [
|
|
10007
10199
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", { children: t("modelsSectionTitle") }),
|
|
10200
|
+
defaultModel === void 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(DefaultModelPreference, {
|
|
10201
|
+
preference,
|
|
10202
|
+
defaultModel,
|
|
10203
|
+
t
|
|
10204
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: "codexSubscriptionDivider" })] }),
|
|
10008
10205
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(ModelCatalogStatus, {
|
|
10009
10206
|
preference,
|
|
10010
10207
|
t
|
|
@@ -11437,7 +11634,7 @@ window.__ModuleLoader__.load({
|
|
|
11437
11634
|
}
|
|
11438
11635
|
//#endregion
|
|
11439
11636
|
//#region src/client-section.jsx
|
|
11440
|
-
function CodexSection({ preference, rpc, accountStatus, t, diagnostics }) {
|
|
11637
|
+
function CodexSection({ preference, rpc, accountStatus, t, diagnostics, defaultModel }) {
|
|
11441
11638
|
const [tab, setTab] = (0, react.useState)("account");
|
|
11442
11639
|
const id = (0, react.useId)();
|
|
11443
11640
|
const tabs = [
|
|
@@ -11529,6 +11726,7 @@ window.__ModuleLoader__.load({
|
|
|
11529
11726
|
rpc,
|
|
11530
11727
|
preference,
|
|
11531
11728
|
t,
|
|
11729
|
+
defaultModel,
|
|
11532
11730
|
section: "advanced"
|
|
11533
11731
|
})
|
|
11534
11732
|
}),
|
|
@@ -11749,6 +11947,7 @@ window.__ModuleLoader__.load({
|
|
|
11749
11947
|
getSnapshot: () => ({ status: "unavailable" }),
|
|
11750
11948
|
subscribe: () => () => {}
|
|
11751
11949
|
}, rpc);
|
|
11950
|
+
const defaultModel = createDefaultModelController(rpc);
|
|
11752
11951
|
ctx.effect(() => {
|
|
11753
11952
|
let previous = JSON.stringify(preference.getSnapshot(), (key, value) => key.startsWith("image") || key === "" ? value : void 0);
|
|
11754
11953
|
return preference.subscribe(() => {
|
|
@@ -11769,6 +11968,7 @@ window.__ModuleLoader__.load({
|
|
|
11769
11968
|
return () => {
|
|
11770
11969
|
disposeReset?.();
|
|
11771
11970
|
preference.dispose();
|
|
11971
|
+
defaultModel.dispose();
|
|
11772
11972
|
accountStatus.dispose();
|
|
11773
11973
|
};
|
|
11774
11974
|
}, "codex-subscription: preferences and account status");
|
|
@@ -11793,7 +11993,8 @@ window.__ModuleLoader__.load({
|
|
|
11793
11993
|
rpc,
|
|
11794
11994
|
accountStatus,
|
|
11795
11995
|
t,
|
|
11796
|
-
diagnostics
|
|
11996
|
+
diagnostics,
|
|
11997
|
+
defaultModel
|
|
11797
11998
|
})
|
|
11798
11999
|
}, CodexSection));
|
|
11799
12000
|
const sessions = ctx.get("sessions");
|
package/lib/index.js
CHANGED
|
@@ -40,6 +40,90 @@ function createSettingsAdapter(ctx, schema, config, namespace) {
|
|
|
40
40
|
};
|
|
41
41
|
}
|
|
42
42
|
//#endregion
|
|
43
|
+
//#region src/default-model.js
|
|
44
|
+
/**
|
|
45
|
+
* DSH owns the model a freshly created agent starts on. This module is the
|
|
46
|
+
* subscription plugin's read/write surface over that service: the settings
|
|
47
|
+
* surface edits the single live selection instead of keeping a second copy, so
|
|
48
|
+
* what the user sees is exactly what the next conversation will use.
|
|
49
|
+
*/
|
|
50
|
+
const DEFAULT_MODEL_PROVIDER = "openai-codex";
|
|
51
|
+
const MODEL_ID = /^[a-zA-Z0-9][a-zA-Z0-9._:-]{0,127}$/u;
|
|
52
|
+
const EFFORT_ID = /^[a-z][a-z0-9_-]{0,31}$/u;
|
|
53
|
+
/** A rejected default-model request carrying its stable public reason. */
|
|
54
|
+
var DefaultModelError = class extends Error {
|
|
55
|
+
constructor(code, message) {
|
|
56
|
+
super(message);
|
|
57
|
+
this.name = "DefaultModelError";
|
|
58
|
+
this.code = code;
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
const validDefaultModelId = (value) => typeof value === "string" && MODEL_ID.test(value);
|
|
62
|
+
/** Project a live selection onto the settings-safe shape; unknown values drop out. */
|
|
63
|
+
function normalizeDefaultSelection(value) {
|
|
64
|
+
return {
|
|
65
|
+
provider: typeof value?.provider === "string" && value.provider.length > 0 && value.provider.length <= 128 ? value.provider : void 0,
|
|
66
|
+
model: validDefaultModelId(value?.model) ? value.model : void 0,
|
|
67
|
+
reasoningEffort: typeof value?.reasoningEffort === "string" && EFFORT_ID.test(value.reasoningEffort) ? value.reasoningEffort : void 0
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Sample the default-model service per call: the service can mount after this
|
|
72
|
+
* plugin. A write verifies its own read-back, because a deployment without a
|
|
73
|
+
* configuration editor ignores `saveSelection`; the user must see that instead
|
|
74
|
+
* of a selection that will never apply.
|
|
75
|
+
* @param resolveService - reads the optional DSH `agentDefaultModel` service.
|
|
76
|
+
* @param listModels - optional account catalog used to reject unknown models.
|
|
77
|
+
*/
|
|
78
|
+
function createDefaultModelController({ resolveService, listModels } = {}) {
|
|
79
|
+
const service = () => {
|
|
80
|
+
try {
|
|
81
|
+
return resolveService?.();
|
|
82
|
+
} catch {
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
const read = () => {
|
|
87
|
+
const current = service();
|
|
88
|
+
if (current === void 0 || typeof current.currentSelection !== "function") return void 0;
|
|
89
|
+
try {
|
|
90
|
+
return normalizeDefaultSelection(current.currentSelection());
|
|
91
|
+
} catch {
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
const status = () => {
|
|
96
|
+
const selection = read();
|
|
97
|
+
return {
|
|
98
|
+
available: selection !== void 0,
|
|
99
|
+
managed: selection?.provider === "openai-codex" && selection.model !== void 0,
|
|
100
|
+
...selection
|
|
101
|
+
};
|
|
102
|
+
};
|
|
103
|
+
const select = async (request) => {
|
|
104
|
+
const model = request?.model;
|
|
105
|
+
if (!validDefaultModelId(model)) throw new DefaultModelError("invalid-model", "Invalid default model");
|
|
106
|
+
const catalog = typeof listModels === "function" ? listModels() : void 0;
|
|
107
|
+
if (Array.isArray(catalog) && catalog.length > 0 && !catalog.includes(model)) throw new DefaultModelError("invalid-model", "Invalid default model");
|
|
108
|
+
const current = service();
|
|
109
|
+
if (current === void 0 || typeof current.saveSelection !== "function") throw new DefaultModelError("unavailable", "This DSH deployment cannot save a default model");
|
|
110
|
+
const previous = read();
|
|
111
|
+
const reasoningEffort = previous?.provider === "openai-codex" && previous.model === model ? previous.reasoningEffort : void 0;
|
|
112
|
+
await current.saveSelection({
|
|
113
|
+
provider: DEFAULT_MODEL_PROVIDER,
|
|
114
|
+
model,
|
|
115
|
+
...reasoningEffort === void 0 ? {} : { reasoningEffort }
|
|
116
|
+
});
|
|
117
|
+
const applied = read();
|
|
118
|
+
if (applied?.provider !== "openai-codex" || applied.model !== model) throw new DefaultModelError("unavailable", "The default model could not be saved");
|
|
119
|
+
return status();
|
|
120
|
+
};
|
|
121
|
+
return Object.freeze({
|
|
122
|
+
status,
|
|
123
|
+
select
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
//#endregion
|
|
43
127
|
//#region src/image-models.js
|
|
44
128
|
const DEFAULT_IMAGE_MODEL = "gpt-image-2";
|
|
45
129
|
const IMAGE_MODELS = Object.freeze({
|
|
@@ -1014,6 +1098,8 @@ const RPC_ENDPOINTS = Object.freeze([
|
|
|
1014
1098
|
"preferences/status",
|
|
1015
1099
|
"preferences/models",
|
|
1016
1100
|
"preferences/update",
|
|
1101
|
+
"default-model/status",
|
|
1102
|
+
"default-model/select",
|
|
1017
1103
|
"runtime/status",
|
|
1018
1104
|
"runtime/install",
|
|
1019
1105
|
"runtime/remove",
|
|
@@ -3068,7 +3154,7 @@ async function readSubscriptionCredentials(getAuth, readCredential, signal) {
|
|
|
3068
3154
|
}
|
|
3069
3155
|
//#endregion
|
|
3070
3156
|
//#region src/version.js
|
|
3071
|
-
const PACKAGE_VERSION = "2.4.
|
|
3157
|
+
const PACKAGE_VERSION = "2.4.2";
|
|
3072
3158
|
const USER_AGENT = `dsh-codex-subscription/${PACKAGE_VERSION}`;
|
|
3073
3159
|
//#endregion
|
|
3074
3160
|
//#region src/model-catalog.js
|
|
@@ -5795,8 +5881,21 @@ const publicError = (code, message) => ({
|
|
|
5795
5881
|
details: { issues: [] }
|
|
5796
5882
|
}
|
|
5797
5883
|
});
|
|
5798
|
-
function createSubscriptionRpcHandler({ authHandler, usageReader, resetCreditService, preferences, runtimeManagement, diagnosticsReader, modelCatalog, originalImages, resolveInheritedOriginal, closeConnections, onAccountChanged, onCleanupFailure }) {
|
|
5884
|
+
function createSubscriptionRpcHandler({ authHandler, usageReader, resetCreditService, preferences, defaultModel, runtimeManagement, diagnosticsReader, modelCatalog, originalImages, resolveInheritedOriginal, closeConnections, onAccountChanged, onCleanupFailure }) {
|
|
5799
5885
|
return async (endpoint, payload, signal) => {
|
|
5886
|
+
if (endpoint === "default-model/status" || endpoint === "default-model/select") try {
|
|
5887
|
+
signal.throwIfAborted();
|
|
5888
|
+
if (!defaultModel) return publicError("unavailable", "The default model is unavailable");
|
|
5889
|
+
return {
|
|
5890
|
+
ok: true,
|
|
5891
|
+
value: endpoint === "default-model/status" ? defaultModel.status() : await defaultModel.select({ model: payload?.model })
|
|
5892
|
+
};
|
|
5893
|
+
} catch (error) {
|
|
5894
|
+
if (signal.aborted) throw error;
|
|
5895
|
+
if (error?.code === "invalid-model") return publicError("invalid-input", "Invalid default model");
|
|
5896
|
+
if (error?.code === "unavailable") return publicError("unavailable", endpoint === "default-model/status" ? "The default model is unavailable" : "Could not save the default model");
|
|
5897
|
+
return publicError("internal", endpoint === "default-model/status" ? "Could not read the default model" : "Could not save the default model");
|
|
5898
|
+
}
|
|
5800
5899
|
if (endpoint === "storage/status" || endpoint === "storage/clear-forecast") try {
|
|
5801
5900
|
signal.throwIfAborted();
|
|
5802
5901
|
if (endpoint === "storage/clear-forecast") await usageReader.clear();
|
|
@@ -6085,6 +6184,10 @@ function apply(ctx, config = {}) {
|
|
|
6085
6184
|
fetch: (input, init) => network.fetch("catalog", input, init)
|
|
6086
6185
|
});
|
|
6087
6186
|
const connection = createSubscriptionConnection({ resolveMode: () => settings.get().connectionMode });
|
|
6187
|
+
const defaultModel = createDefaultModelController({
|
|
6188
|
+
resolveService: () => ctx.get?.("agentDefaultModel"),
|
|
6189
|
+
listModels: () => modelCatalog.getModels().map((model) => model.id)
|
|
6190
|
+
});
|
|
6088
6191
|
const compaction = createCompactionBridge({
|
|
6089
6192
|
enabled: () => settings.get().compactionMode === "cloud",
|
|
6090
6193
|
accountScope: async () => {
|
|
@@ -6395,6 +6498,7 @@ function apply(ctx, config = {}) {
|
|
|
6395
6498
|
usageReader,
|
|
6396
6499
|
resetCreditService,
|
|
6397
6500
|
preferences,
|
|
6501
|
+
defaultModel,
|
|
6398
6502
|
runtimeManagement,
|
|
6399
6503
|
onAccountChanged: quotaRetryHandler.notifyAccountChanged,
|
|
6400
6504
|
diagnosticsReader: () => createSubscriptionDiagnostics({
|
|
@@ -6436,4 +6540,4 @@ function apply(ctx, config = {}) {
|
|
|
6436
6540
|
}, "codex-subscription: DSH-trusted account RPC"));
|
|
6437
6541
|
}
|
|
6438
6542
|
//#endregion
|
|
6439
|
-
export { CODEX_IMAGE_GENERATION_URL, CODEX_IMAGE_TOOL_NAME, CODEX_RESET_CONSUME_URL, CODEX_RESET_CREDITS_URL, CODEX_USAGE_URL, CodexLoginCoordinator, Config, DshOAuthCredentialStore, apply, assertCodexAuthUrl, commandForCodexAuthUrl, createCodexAuthService, createCodexImageTool, createCodexResetCreditService, createCodexRpcHandler, createCodexUsageReader, createSearchProviderSwitcher, createSubscriptionDiagnostics, createSubscriptionRpcHandler, decodeCodexPng, inject, name, normalizeContextMode, normalizeCustomContextWindow, openCodexAuthUrl, parseCodexUsage };
|
|
6543
|
+
export { CODEX_IMAGE_GENERATION_URL, CODEX_IMAGE_TOOL_NAME, CODEX_RESET_CONSUME_URL, CODEX_RESET_CREDITS_URL, CODEX_USAGE_URL, CodexLoginCoordinator, Config, DEFAULT_MODEL_PROVIDER, DshOAuthCredentialStore, apply, assertCodexAuthUrl, commandForCodexAuthUrl, createCodexAuthService, createCodexImageTool, createCodexResetCreditService, createCodexRpcHandler, createCodexUsageReader, createDefaultModelController, createSearchProviderSwitcher, createSubscriptionDiagnostics, createSubscriptionRpcHandler, decodeCodexPng, inject, name, normalizeContextMode, normalizeCustomContextWindow, openCodexAuthUrl, parseCodexUsage };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-codex-subscription",
|
|
3
|
-
"version": "2.4.
|
|
3
|
+
"version": "2.4.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",
|