dsh-codex-subscription 2.4.1 → 2.5.0
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 +9 -4
- package/README.md +12 -1
- package/lib/client.js +312 -43
- package/lib/index.js +2170 -2034
- 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.
|
|
108
|
+
dsh-codex-subscription@2.5.0
|
|
108
109
|
```
|
|
109
110
|
|
|
110
111
|
3. Click **Install** and wait for completion. Follow the page instructions; save your work before restarting if requested.
|
|
@@ -219,11 +220,15 @@ Here the reference image is attached to the message and the model copies it on t
|
|
|
219
220
|
|
|
220
221
|
The SVG runs have finer hair highlights, lace trim and lettering, and Sol was almost 9 minutes faster with SVG than stroke by stroke; Astra spent about 3 extra minutes on SVG for clearly richer detail. Neither model got the face shape right (too long and flat) or the small whale motif on the apron, though Sol's whale looks more like a whale.
|
|
221
222
|
|
|
222
|
-
The
|
|
223
|
+
**The same challenge again, with the model checking itself against the reference**
|
|
223
224
|
|
|
224
|
-
|
|
225
|
+
Same prompt and the same way of attaching the image as above; the plugin just gives the model two more things. It can use `reference` to put the image attached in the chat onto the board as a hidden picture layer, and while previewing it can turn on `compare` (the drawing and the reference blended 50/50, so position errors show up as ghosting) and `grid` (a labelled line every 100 pixels). Same Astra Medium on the official desktop app, one run, no image generation: 20 min 57 s, 7 drawing layers and 686 native strokes. The model also generated hair strands and lace with scripts, and checked against the overlay several times while drawing, fixing lettering and lace overlaps.
|
|
225
226
|
|
|
226
|
-
|
|
227
|
+
<table>
|
|
228
|
+
<tr><td><img src="docs/assets/sketch-niang-astra-compare.webp" alt="Astra Medium with overlay checks" width="380"><br><sub><b>Astra Medium</b> · 20 min 57 s · 686 strokes</sub></td><td><img src="docs/assets/sketch-niang-astra-overlay.webp" alt="The overlay preview the model saw" width="260"><br><sub>The overlay the model saw: ghosting on the lettering and hair edges is the error</sub></td></tr>
|
|
229
|
+
</table>
|
|
230
|
+
|
|
231
|
+
The face shape, hair flow, lace, hand and speech-bubble lettering are all closer to the reference than the two Astra runs above, at about twice the time of the SVG run. This is a single run; other prompts and references may behave differently.
|
|
227
232
|
|
|
228
233
|
<details>
|
|
229
234
|
<summary>View Images & sketch settings</summary>
|
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.
|
|
108
|
+
dsh-codex-subscription@2.5.0
|
|
108
109
|
```
|
|
109
110
|
|
|
110
111
|
3. 点击 **安装**,等待安装完成;按页面提示操作,需要重启时先保存工作。
|
|
@@ -221,6 +222,16 @@ Sol Xhigh 约 28 分钟,Astra Low 约 5 分钟。两者都保留了主峰、
|
|
|
221
222
|
|
|
222
223
|
SVG 版的发丝高光、蕾丝褶边和手写字更精细,Sol 用 SVG 还比逐笔绘制快了近 9 分钟;Astra 用 SVG 多花约 3 分钟,换来明显更丰富的细节。两个模型都没能画准脸型(偏长偏平)和围裙上的小鲸鱼图案,Sol 的鲸鱼更像鲸。
|
|
223
224
|
|
|
225
|
+
**同一题再跑一次:让模型自己叠图对照**
|
|
226
|
+
|
|
227
|
+
这一次提示词和附件方式都和上面一样,只是插件多了两样东西:模型可以用 `reference` 把聊天里附的参考图放进画板(作为隐藏的图片图层),并且在预览时打开 `compare`(把画作和参考图各占 50% 叠在一起,位置偏差会显示成重影)和 `grid`(每 100 像素一条带数字的网格)。同一题、同一个 Astra Medium,在官方桌面版上跑了一次,没有调用生图,共 20 分 57 秒、7 个绘画图层、686 条原生笔画;模型还用脚本批量生成了发丝和花边,并在画的过程中多次叠图检查、修正文字和蕾丝遮挡。
|
|
228
|
+
|
|
229
|
+
<table>
|
|
230
|
+
<tr><td><img src="docs/assets/sketch-niang-astra-compare.webp" alt="Astra Medium 叠图对照版" width="380"><br><sub><b>Astra Medium</b> · 20 分 57 秒 · 686 笔</sub></td><td><img src="docs/assets/sketch-niang-astra-overlay.webp" alt="模型看到的叠图对照预览" width="260"><br><sub>模型看到的叠图预览:文字和发丝边缘的重影就是偏差</sub></td></tr>
|
|
231
|
+
</table>
|
|
232
|
+
|
|
233
|
+
脸型、长发走向、蕾丝、手和气泡字都比上面的两个 Astra 版更接近参考图,耗时约是 SVG 版的两倍。这是单次运行,不同提示词和参考图的效果可能不同。
|
|
234
|
+
|
|
224
235
|
<details>
|
|
225
236
|
<summary>展开三道题的完整提示词</summary>
|
|
226
237
|
|
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",
|
|
@@ -3325,11 +3327,22 @@ window.__ModuleLoader__.load({
|
|
|
3325
3327
|
}
|
|
3326
3328
|
if (request.documentId !== current.documentId) throw Error("Document changed; inspect again");
|
|
3327
3329
|
if (pending || adapter.busy()) throw Error("Sketch is being edited; retry after it settles");
|
|
3328
|
-
if (request.action === "preview")
|
|
3329
|
-
|
|
3330
|
-
|
|
3331
|
-
|
|
3332
|
-
|
|
3330
|
+
if (request.action === "preview") {
|
|
3331
|
+
for (const key of ["compare", "grid"]) if (request[key] !== void 0 && typeof request[key] !== "boolean") throw Error(`${key} must be true or false`);
|
|
3332
|
+
return {
|
|
3333
|
+
...current,
|
|
3334
|
+
png: await adapter.preview({
|
|
3335
|
+
compare: request.compare === true,
|
|
3336
|
+
grid: request.grid === true
|
|
3337
|
+
}),
|
|
3338
|
+
...request.grid ? { gridStep: 100 } : {}
|
|
3339
|
+
};
|
|
3340
|
+
}
|
|
3341
|
+
if (![
|
|
3342
|
+
"apply",
|
|
3343
|
+
"save",
|
|
3344
|
+
"reference"
|
|
3345
|
+
].includes(request.action)) throw Error("Unknown sketch action");
|
|
3333
3346
|
if (typeof request.requestId !== "string" || !request.requestId.length || request.requestId.length > 100) throw Error("A unique requestId is required");
|
|
3334
3347
|
const key = `${current.documentId}:${request.requestId}`, fingerprint = JSON.stringify({
|
|
3335
3348
|
...request,
|
|
@@ -3359,6 +3372,14 @@ window.__ModuleLoader__.load({
|
|
|
3359
3372
|
layer: l.id,
|
|
3360
3373
|
id: s.id
|
|
3361
3374
|
})));
|
|
3375
|
+
} else if (request.action === "reference") {
|
|
3376
|
+
if (typeof request.image !== "string" || !/^data:image\/(png|jpeg|webp);base64,/.test(request.image) || request.image.length > 19e5) throw Error("A PNG, JPEG or WebP reference image is required");
|
|
3377
|
+
pending = true;
|
|
3378
|
+
try {
|
|
3379
|
+
await adapter.addReference(request.image, typeof request.name === "string" ? request.name.slice(0, 40) : "reference");
|
|
3380
|
+
} finally {
|
|
3381
|
+
pending = false;
|
|
3382
|
+
}
|
|
3362
3383
|
} else {
|
|
3363
3384
|
if (request.name !== void 0 && (typeof request.name !== "string" || request.name.length > 60)) throw Error("Invalid draft name");
|
|
3364
3385
|
pending = true;
|
|
@@ -3643,7 +3664,7 @@ window.__ModuleLoader__.load({
|
|
|
3643
3664
|
name: row.name
|
|
3644
3665
|
});
|
|
3645
3666
|
};
|
|
3646
|
-
const importImage = async (file) => {
|
|
3667
|
+
const importImage = async (file, { visible = true } = {}) => {
|
|
3647
3668
|
if (file.name?.toLowerCase().endsWith(".psd") || file.name?.toLowerCase().endsWith(".dsh-sketch.json")) {
|
|
3648
3669
|
if (file.size > 32 * 1024 * 1024) throw Error("File exceeds 32 MB");
|
|
3649
3670
|
if (file.name.toLowerCase().endsWith(".psd") && !await confirmPsd()) return;
|
|
@@ -3661,7 +3682,7 @@ window.__ModuleLoader__.load({
|
|
|
3661
3682
|
const layer = {
|
|
3662
3683
|
id: doc.current.nextId,
|
|
3663
3684
|
name: file.name?.slice(0, 40) || t("sketchImport"),
|
|
3664
|
-
visible
|
|
3685
|
+
visible,
|
|
3665
3686
|
strokes: [],
|
|
3666
3687
|
image: {
|
|
3667
3688
|
src: image.src,
|
|
@@ -3676,7 +3697,7 @@ window.__ModuleLoader__.load({
|
|
|
3676
3697
|
doc.current = {
|
|
3677
3698
|
...doc.current,
|
|
3678
3699
|
nextId: layer.id + 1,
|
|
3679
|
-
active: layer.id,
|
|
3700
|
+
active: visible ? layer.id : doc.current.active,
|
|
3680
3701
|
layers: [...doc.current.layers, layer]
|
|
3681
3702
|
};
|
|
3682
3703
|
schedule();
|
|
@@ -3880,6 +3901,60 @@ window.__ModuleLoader__.load({
|
|
|
3880
3901
|
}
|
|
3881
3902
|
}
|
|
3882
3903
|
//#endregion
|
|
3904
|
+
//#region src/sketch-preview.js
|
|
3905
|
+
const GRID_STEP = 100;
|
|
3906
|
+
function composeSketchPreview({ doc, images, width, height, options = {}, makeSurface, paintLayers }) {
|
|
3907
|
+
const surface = makeSurface(width, height), context = surface.getContext("2d");
|
|
3908
|
+
if (options.compare) {
|
|
3909
|
+
if (!doc.layers.some((layer) => layer.image)) throw Error("compare needs a reference picture layer on the board; ask the user to add the reference with the pictures button");
|
|
3910
|
+
const reference = makeSurface(width, height), drawing = makeSurface(width, height);
|
|
3911
|
+
paintLayers(reference.getContext("2d"), {
|
|
3912
|
+
...doc,
|
|
3913
|
+
layers: doc.layers.map((layer) => ({
|
|
3914
|
+
...layer,
|
|
3915
|
+
strokes: [],
|
|
3916
|
+
visible: Boolean(layer.image)
|
|
3917
|
+
}))
|
|
3918
|
+
}, /* @__PURE__ */ new Map(), width, height, void 0, images);
|
|
3919
|
+
paintLayers(drawing.getContext("2d"), {
|
|
3920
|
+
...doc,
|
|
3921
|
+
layers: doc.layers.map((layer) => ({
|
|
3922
|
+
...layer,
|
|
3923
|
+
image: void 0
|
|
3924
|
+
}))
|
|
3925
|
+
}, /* @__PURE__ */ new Map(), width, height, void 0, images);
|
|
3926
|
+
context.drawImage(reference, 0, 0);
|
|
3927
|
+
context.globalAlpha = .5;
|
|
3928
|
+
context.drawImage(drawing, 0, 0);
|
|
3929
|
+
context.globalAlpha = 1;
|
|
3930
|
+
} else paintLayers(context, doc, /* @__PURE__ */ new Map(), width, height, void 0, images);
|
|
3931
|
+
if (options.grid) paintGrid(context, width, height);
|
|
3932
|
+
return surface.toDataURL("image/png");
|
|
3933
|
+
}
|
|
3934
|
+
function paintGrid(context, width, height) {
|
|
3935
|
+
context.save();
|
|
3936
|
+
context.lineWidth = 1;
|
|
3937
|
+
context.strokeStyle = "rgba(214,0,120,0.45)";
|
|
3938
|
+
context.fillStyle = "rgba(214,0,120,0.9)";
|
|
3939
|
+
context.font = "12px sans-serif";
|
|
3940
|
+
context.textBaseline = "top";
|
|
3941
|
+
for (let x = GRID_STEP; x < width; x += GRID_STEP) {
|
|
3942
|
+
context.beginPath();
|
|
3943
|
+
context.moveTo(x + .5, 0);
|
|
3944
|
+
context.lineTo(x + .5, height);
|
|
3945
|
+
context.stroke();
|
|
3946
|
+
context.fillText(String(x), x + 3, 2);
|
|
3947
|
+
}
|
|
3948
|
+
for (let y = GRID_STEP; y < height; y += GRID_STEP) {
|
|
3949
|
+
context.beginPath();
|
|
3950
|
+
context.moveTo(0, y + .5);
|
|
3951
|
+
context.lineTo(width, y + .5);
|
|
3952
|
+
context.stroke();
|
|
3953
|
+
context.fillText(String(y), 3, y + 2);
|
|
3954
|
+
}
|
|
3955
|
+
context.restore();
|
|
3956
|
+
}
|
|
3957
|
+
//#endregion
|
|
3883
3958
|
//#region src/sketch-files.jsx
|
|
3884
3959
|
function SketchFiles({ save, load, fresh, importImage, download, hasContent, disabled, t, runOperation }) {
|
|
3885
3960
|
const [open, setOpen] = (0, react.useState)(false), [rows, setRows] = (0, react.useState)([]), [name, setName] = (0, react.useState)(""), [remove, setRemove] = (0, react.useState)(null), [working, setWorking] = (0, react.useState)(false);
|
|
@@ -4099,7 +4174,7 @@ window.__ModuleLoader__.load({
|
|
|
4099
4174
|
}
|
|
4100
4175
|
//#endregion
|
|
4101
4176
|
//#region src/sketch-agent-run.js
|
|
4102
|
-
function createSketchAgentRun({ execute, open, changed, busy = () => false,
|
|
4177
|
+
function createSketchAgentRun({ execute, open, changed, busy = () => false, idleMs = 18e4 }) {
|
|
4103
4178
|
let state = "idle", generation = 0, runNumber = 0, pending = false, runId, timer, completed;
|
|
4104
4179
|
const update = (next) => {
|
|
4105
4180
|
state = next;
|
|
@@ -4163,15 +4238,10 @@ window.__ModuleLoader__.load({
|
|
|
4163
4238
|
...value,
|
|
4164
4239
|
runId
|
|
4165
4240
|
};
|
|
4166
|
-
const result = previewEnabled() ? await execute({
|
|
4167
|
-
action: "preview",
|
|
4168
|
-
documentId: value.documentId
|
|
4169
|
-
}) : value;
|
|
4170
|
-
if (version !== generation) throw Error("Drawing interrupted");
|
|
4171
4241
|
completed = {
|
|
4172
4242
|
key: JSON.stringify(request),
|
|
4173
4243
|
value: {
|
|
4174
|
-
...
|
|
4244
|
+
...value,
|
|
4175
4245
|
runId
|
|
4176
4246
|
}
|
|
4177
4247
|
};
|
|
@@ -4292,7 +4362,7 @@ window.__ModuleLoader__.load({
|
|
|
4292
4362
|
}
|
|
4293
4363
|
//#endregion
|
|
4294
4364
|
//#region src/sketch-studio.jsx
|
|
4295
|
-
function SketchStudio({ open, agentEnabled,
|
|
4365
|
+
function SketchStudio({ open, agentEnabled, onOpen, onClose, attachSketch, enabled, t, incoming, sessionId, rpc, sessionState }) {
|
|
4296
4366
|
const localSession = (0, react.useRef)(null);
|
|
4297
4367
|
const psdImport = useSketchImportConfirm(t);
|
|
4298
4368
|
localSession.current ??= sessionState ?? createSketchSessionState();
|
|
@@ -4589,7 +4659,6 @@ window.__ModuleLoader__.load({
|
|
|
4589
4659
|
setNoticeHidden(false);
|
|
4590
4660
|
},
|
|
4591
4661
|
available: () => enabled && agentEnabled,
|
|
4592
|
-
previewEnabled: () => agentPreview,
|
|
4593
4662
|
open: () => onOpen(),
|
|
4594
4663
|
busy: () => operationGate.current.running || busy || Boolean(active.current) || Boolean(textEdit) || sizeGesture.current,
|
|
4595
4664
|
document: () => doc.current,
|
|
@@ -4623,9 +4692,24 @@ window.__ModuleLoader__.load({
|
|
|
4623
4692
|
setError("");
|
|
4624
4693
|
schedule();
|
|
4625
4694
|
},
|
|
4626
|
-
preview: async () => {
|
|
4627
|
-
|
|
4628
|
-
return
|
|
4695
|
+
preview: async (options) => {
|
|
4696
|
+
const w = doc.current.width ?? 1024, h = doc.current.height ?? 1024;
|
|
4697
|
+
return composeSketchPreview({
|
|
4698
|
+
doc: doc.current,
|
|
4699
|
+
images: images.current,
|
|
4700
|
+
width: w,
|
|
4701
|
+
height: h,
|
|
4702
|
+
options,
|
|
4703
|
+
paintLayers: paintSketchLayers,
|
|
4704
|
+
makeSurface: (width, height) => Object.assign(document.createElement("canvas"), {
|
|
4705
|
+
width,
|
|
4706
|
+
height
|
|
4707
|
+
})
|
|
4708
|
+
});
|
|
4709
|
+
},
|
|
4710
|
+
addReference: async (dataUrl, name) => {
|
|
4711
|
+
const blob = await (await fetch(dataUrl)).blob();
|
|
4712
|
+
await importImage(new File([blob], name, { type: blob.type }), { visible: false });
|
|
4629
4713
|
},
|
|
4630
4714
|
save
|
|
4631
4715
|
});
|
|
@@ -4634,8 +4718,7 @@ window.__ModuleLoader__.load({
|
|
|
4634
4718
|
execute: (request) => agentSession.current(request),
|
|
4635
4719
|
open: () => agentAdapter.current.open(),
|
|
4636
4720
|
changed: (state) => agentAdapter.current.changed?.(state),
|
|
4637
|
-
busy: () => agentAdapter.current.busy()
|
|
4638
|
-
previewEnabled: () => agentAdapter.current.previewEnabled()
|
|
4721
|
+
busy: () => agentAdapter.current.busy()
|
|
4639
4722
|
});
|
|
4640
4723
|
(0, react.useEffect)(() => {
|
|
4641
4724
|
if (!enabled || !agentEnabled || !hydrated) return;
|
|
@@ -5315,7 +5398,6 @@ window.__ModuleLoader__.load({
|
|
|
5315
5398
|
}), [registerOpen]);
|
|
5316
5399
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SketchStudio, {
|
|
5317
5400
|
sessionState,
|
|
5318
|
-
agentPreview: settings.imageSketchAgentPreview,
|
|
5319
5401
|
agentEnabled: settings.imageSketchAgent,
|
|
5320
5402
|
onOpen: () => {
|
|
5321
5403
|
opener.current = document.activeElement;
|
|
@@ -5541,6 +5623,14 @@ window.__ModuleLoader__.load({
|
|
|
5541
5623
|
advancedModelSearch: "模型与搜索",
|
|
5542
5624
|
modelsSectionTitle: "模型",
|
|
5543
5625
|
searchSectionTitle: "搜索",
|
|
5626
|
+
defaultModelTitle: "默认模型",
|
|
5627
|
+
defaultModelHint: "新建会话时默认使用的模型,与在对话里切换模型写的是同一处 DSH 默认模型设置。",
|
|
5628
|
+
defaultModelFollow: "跟随 DSH 默认",
|
|
5629
|
+
defaultModelFollowHint: "当前跟随 DSH 默认模型:{value}。选择一个 Codex 模型,之后每次新建会话都用它。",
|
|
5630
|
+
defaultModelUnknown: "未知",
|
|
5631
|
+
defaultModelUnavailable: "当前 DSH 版本没有提供默认模型服务,无法在这里设置。",
|
|
5632
|
+
defaultModelNoCatalog: "登录并加载模型后即可选择默认模型。",
|
|
5633
|
+
defaultModelFailed: "默认模型读取或保存失败,请重试,或改在对话中切换模型。",
|
|
5544
5634
|
inputImageDetail: "输入图片精度",
|
|
5545
5635
|
inputImageDetailHint: "控制发送给模型的图片精度,精度越高输入 token 用量越大。",
|
|
5546
5636
|
inputImageDetail_auto: "自动",
|
|
@@ -5703,10 +5793,6 @@ window.__ModuleLoader__.load({
|
|
|
5703
5793
|
sketchRun_failed: "绘制失败",
|
|
5704
5794
|
sketchRunStop: "停止绘制",
|
|
5705
5795
|
sketchRunResume: "允许继续绘制",
|
|
5706
|
-
sketchAgentPreview: "完成后返回预览 · Beta",
|
|
5707
|
-
sketchAgentPreviewHint: "默认关闭;完成绘制后向模型返回画布图片,会增加图片输入用量。",
|
|
5708
|
-
sketchAgentPreview_on: "开启",
|
|
5709
|
-
sketchAgentPreview_off: "关闭",
|
|
5710
5796
|
sketchAgent_on: "开启",
|
|
5711
5797
|
sketchAgent_off: "关闭",
|
|
5712
5798
|
imageSettings: "图片",
|
|
@@ -5912,7 +5998,6 @@ window.__ModuleLoader__.load({
|
|
|
5912
5998
|
diagnosticsHint: "遇到问题时生成报告,可复制后用于反馈。不含登录凭据和账号标识。",
|
|
5913
5999
|
sketchCanvasSetting: "画板入口",
|
|
5914
6000
|
sketchAgentSetting: "Agent 绘图",
|
|
5915
|
-
sketchAgentPreviewSetting: "完成后返回预览",
|
|
5916
6001
|
quotaShowIndicator: "显示额度",
|
|
5917
6002
|
quotaIndicatorHint: "输入框只显示图标,点击查看详情。关闭时暂停续航采样。",
|
|
5918
6003
|
quotaForecastOptional: "续航预测 · 实验",
|
|
@@ -6099,6 +6184,14 @@ window.__ModuleLoader__.load({
|
|
|
6099
6184
|
advancedModelSearch: "Models and search",
|
|
6100
6185
|
modelsSectionTitle: "Models",
|
|
6101
6186
|
searchSectionTitle: "Search",
|
|
6187
|
+
defaultModelTitle: "Default model",
|
|
6188
|
+
defaultModelHint: "The model a new conversation opens with. This writes the same DSH default model setting as switching the model inside a chat.",
|
|
6189
|
+
defaultModelFollow: "Follow DSH default",
|
|
6190
|
+
defaultModelFollowHint: "Following the DSH default: {value}. Pick a Codex model to make every new conversation start with it.",
|
|
6191
|
+
defaultModelUnknown: "unknown",
|
|
6192
|
+
defaultModelUnavailable: "This DSH version provides no default-model service, so it cannot be set here.",
|
|
6193
|
+
defaultModelNoCatalog: "Sign in and load models to choose a default model.",
|
|
6194
|
+
defaultModelFailed: "Reading or saving the default model failed. Retry, or switch the model inside a chat.",
|
|
6102
6195
|
inputImageDetail: "Input image detail",
|
|
6103
6196
|
inputImageDetailHint: "Controls the detail level of images sent to the model. Higher detail uses more input tokens.",
|
|
6104
6197
|
inputImageDetail_auto: "Auto",
|
|
@@ -6261,10 +6354,6 @@ window.__ModuleLoader__.load({
|
|
|
6261
6354
|
sketchRun_failed: "Drawing failed",
|
|
6262
6355
|
sketchRunStop: "Stop drawing",
|
|
6263
6356
|
sketchRunResume: "Allow drawing again",
|
|
6264
|
-
sketchAgentPreview: "Preview on completion · Beta",
|
|
6265
|
-
sketchAgentPreviewHint: "Off by default. Returns the canvas to the model on completion, adding image input usage.",
|
|
6266
|
-
sketchAgentPreview_on: "On",
|
|
6267
|
-
sketchAgentPreview_off: "Off",
|
|
6268
6357
|
sketchAgent_on: "On",
|
|
6269
6358
|
sketchAgent_off: "Off",
|
|
6270
6359
|
imageSettings: "Images",
|
|
@@ -6470,7 +6559,6 @@ window.__ModuleLoader__.load({
|
|
|
6470
6559
|
diagnosticsHint: "Generate a report to copy into a support request. Sign-in credentials and account identifiers are excluded.",
|
|
6471
6560
|
sketchCanvasSetting: "Board entry",
|
|
6472
6561
|
sketchAgentSetting: "Agent drawing",
|
|
6473
|
-
sketchAgentPreviewSetting: "Return preview on completion",
|
|
6474
6562
|
quotaShowIndicator: "Show quota",
|
|
6475
6563
|
quotaIndicatorHint: "Show an icon in the composer; click for details. Hiding it pauses forecast sampling.",
|
|
6476
6564
|
quotaForecastOptional: "Runway forecast · Experimental",
|
|
@@ -7778,8 +7866,7 @@ window.__ModuleLoader__.load({
|
|
|
7778
7866
|
imageViewer: true,
|
|
7779
7867
|
imageAnnotations: true,
|
|
7780
7868
|
imageSketch: false,
|
|
7781
|
-
imageSketchAgent: false
|
|
7782
|
-
imageSketchAgentPreview: false
|
|
7869
|
+
imageSketchAgent: false
|
|
7783
7870
|
});
|
|
7784
7871
|
function readImageFeatures(value = {}) {
|
|
7785
7872
|
return Object.fromEntries(Object.entries(IMAGE_FEATURE_DEFAULTS).map(([key, fallback]) => [key, typeof value?.[key] === "boolean" ? value[key] : fallback]));
|
|
@@ -8088,7 +8175,6 @@ window.__ModuleLoader__.load({
|
|
|
8088
8175
|
verbosityModels = Array.isArray(value?.verbosityModels) ? value.verbosityModels : [];
|
|
8089
8176
|
fastModels = Array.isArray(value?.fastModels) ? value.fastModels : void 0;
|
|
8090
8177
|
ultrafastModels = Array.isArray(value?.ultrafastModels) ? value.ultrafastModels : [];
|
|
8091
|
-
ultrafastModels = Array.isArray(value?.ultrafastModels) ? value.ultrafastModels : [];
|
|
8092
8178
|
catalogStatus = value?.catalogStatus;
|
|
8093
8179
|
}
|
|
8094
8180
|
} else acceptFallback(value);
|
|
@@ -8138,6 +8224,21 @@ window.__ModuleLoader__.load({
|
|
|
8138
8224
|
}
|
|
8139
8225
|
}
|
|
8140
8226
|
};
|
|
8227
|
+
const accepted = (entries, wait = 1500) => new Promise((resolve) => {
|
|
8228
|
+
const matches = () => entries.every(([field, value]) => JSON.stringify(nativeSnapshot().value?.[field]) === JSON.stringify(value));
|
|
8229
|
+
if (matches()) return resolve(true);
|
|
8230
|
+
let timer;
|
|
8231
|
+
const stop = scope.subscribe(() => {
|
|
8232
|
+
if (!matches()) return;
|
|
8233
|
+
clearTimeout(timer);
|
|
8234
|
+
stop();
|
|
8235
|
+
resolve(true);
|
|
8236
|
+
});
|
|
8237
|
+
timer = setTimeout(() => {
|
|
8238
|
+
stop();
|
|
8239
|
+
resolve(matches());
|
|
8240
|
+
}, wait);
|
|
8241
|
+
});
|
|
8141
8242
|
const set = async (patch) => {
|
|
8142
8243
|
if (disposed || snapshot.status !== "ready" || snapshot.writable !== true) return;
|
|
8143
8244
|
const current = ++generation;
|
|
@@ -8154,8 +8255,7 @@ window.__ModuleLoader__.load({
|
|
|
8154
8255
|
await scope.set(field, value);
|
|
8155
8256
|
}
|
|
8156
8257
|
if (current !== generation) return;
|
|
8157
|
-
|
|
8158
|
-
error = entries.some(([field, value]) => JSON.stringify(accepted?.[field]) !== JSON.stringify(value));
|
|
8258
|
+
error = !await accepted(entries);
|
|
8159
8259
|
if (error) failedPatch = patch;
|
|
8160
8260
|
pendingPatch = void 0;
|
|
8161
8261
|
} else {
|
|
@@ -8196,6 +8296,97 @@ window.__ModuleLoader__.load({
|
|
|
8196
8296
|
};
|
|
8197
8297
|
}
|
|
8198
8298
|
//#endregion
|
|
8299
|
+
//#region src/default-model-controller.js
|
|
8300
|
+
const INITIAL = Object.freeze({
|
|
8301
|
+
status: "loading",
|
|
8302
|
+
available: false,
|
|
8303
|
+
managed: false,
|
|
8304
|
+
provider: void 0,
|
|
8305
|
+
model: void 0,
|
|
8306
|
+
reasoningEffort: void 0,
|
|
8307
|
+
saving: false,
|
|
8308
|
+
error: false
|
|
8309
|
+
});
|
|
8310
|
+
const adopt = (value) => ({
|
|
8311
|
+
status: "ready",
|
|
8312
|
+
error: false,
|
|
8313
|
+
available: value?.available === true,
|
|
8314
|
+
managed: value?.managed === true,
|
|
8315
|
+
provider: value?.provider,
|
|
8316
|
+
model: value?.model,
|
|
8317
|
+
reasoningEffort: value?.reasoningEffort
|
|
8318
|
+
});
|
|
8319
|
+
/**
|
|
8320
|
+
* Read and update the DSH default model behind one settings control. The Host
|
|
8321
|
+
* owns the value, so a load always replaces the local projection; a rejected
|
|
8322
|
+
* write keeps the last known value and only raises the error flag.
|
|
8323
|
+
*/
|
|
8324
|
+
function createDefaultModelController(rpc) {
|
|
8325
|
+
let snapshot = INITIAL;
|
|
8326
|
+
let disposed = false;
|
|
8327
|
+
let generation = 0;
|
|
8328
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
8329
|
+
const publish = (next) => {
|
|
8330
|
+
snapshot = Object.freeze({
|
|
8331
|
+
...snapshot,
|
|
8332
|
+
...next
|
|
8333
|
+
});
|
|
8334
|
+
for (const listener of listeners) listener();
|
|
8335
|
+
};
|
|
8336
|
+
const load = async () => {
|
|
8337
|
+
const current = ++generation;
|
|
8338
|
+
try {
|
|
8339
|
+
const value = unwrap(await rpc.call(CHANNEL, "default-model/status", {}));
|
|
8340
|
+
if (disposed || current !== generation) return;
|
|
8341
|
+
publish(adopt(value));
|
|
8342
|
+
} catch {
|
|
8343
|
+
if (disposed || current !== generation) return;
|
|
8344
|
+
publish({
|
|
8345
|
+
status: "error",
|
|
8346
|
+
error: true
|
|
8347
|
+
});
|
|
8348
|
+
}
|
|
8349
|
+
};
|
|
8350
|
+
const select = async (model) => {
|
|
8351
|
+
if (disposed) return false;
|
|
8352
|
+
const current = ++generation;
|
|
8353
|
+
publish({
|
|
8354
|
+
saving: true,
|
|
8355
|
+
error: false
|
|
8356
|
+
});
|
|
8357
|
+
try {
|
|
8358
|
+
const value = unwrap(await rpc.call(CHANNEL, "default-model/select", { model }));
|
|
8359
|
+
if (disposed || current !== generation) return false;
|
|
8360
|
+
publish({
|
|
8361
|
+
...adopt(value),
|
|
8362
|
+
saving: false
|
|
8363
|
+
});
|
|
8364
|
+
return true;
|
|
8365
|
+
} catch {
|
|
8366
|
+
if (disposed || current !== generation) return false;
|
|
8367
|
+
publish({
|
|
8368
|
+
saving: false,
|
|
8369
|
+
error: true
|
|
8370
|
+
});
|
|
8371
|
+
return false;
|
|
8372
|
+
}
|
|
8373
|
+
};
|
|
8374
|
+
return Object.freeze({
|
|
8375
|
+
getSnapshot: () => snapshot,
|
|
8376
|
+
subscribe: (listener) => {
|
|
8377
|
+
listeners.add(listener);
|
|
8378
|
+
return () => listeners.delete(listener);
|
|
8379
|
+
},
|
|
8380
|
+
load,
|
|
8381
|
+
select,
|
|
8382
|
+
dispose: () => {
|
|
8383
|
+
disposed = true;
|
|
8384
|
+
generation += 1;
|
|
8385
|
+
listeners.clear();
|
|
8386
|
+
}
|
|
8387
|
+
});
|
|
8388
|
+
}
|
|
8389
|
+
//#endregion
|
|
8199
8390
|
//#region src/account-status-controller.js
|
|
8200
8391
|
const DEFAULT_TIMEOUT_MS = 1e4;
|
|
8201
8392
|
const STATUS_ERROR_CODES = /* @__PURE__ */ new Set([
|
|
@@ -8481,7 +8672,7 @@ window.__ModuleLoader__.load({
|
|
|
8481
8672
|
}
|
|
8482
8673
|
//#endregion
|
|
8483
8674
|
//#region src/version.js
|
|
8484
|
-
const PACKAGE_VERSION = "2.
|
|
8675
|
+
const PACKAGE_VERSION = "2.5.0";
|
|
8485
8676
|
//#endregion
|
|
8486
8677
|
//#region src/client-recovery.js
|
|
8487
8678
|
async function recoveryCall(rpc, endpoint, payload = {}, timeoutMs = 1e4) {
|
|
@@ -9080,7 +9271,6 @@ window.__ModuleLoader__.load({
|
|
|
9080
9271
|
imageEntryPoints: ["imageShortcut"],
|
|
9081
9272
|
sketchCanvas: ["imageSketch"],
|
|
9082
9273
|
sketchAgent: ["imageSketchAgent"],
|
|
9083
|
-
sketchAgentPreview: ["imageSketchAgentPreview"],
|
|
9084
9274
|
imageBrowsing: ["imageViewer", "imageAnnotations"]
|
|
9085
9275
|
});
|
|
9086
9276
|
function imageGroupValue(snapshot, group) {
|
|
@@ -9383,6 +9573,76 @@ window.__ModuleLoader__.load({
|
|
|
9383
9573
|
] });
|
|
9384
9574
|
}
|
|
9385
9575
|
//#endregion
|
|
9576
|
+
//#region src/default-model-preferences.jsx
|
|
9577
|
+
/**
|
|
9578
|
+
* Choose the model a new conversation opens with. DSH owns that selection, so
|
|
9579
|
+
* the control always shows the live value, including a model chosen in a chat
|
|
9580
|
+
* and any non-subscription default the user set elsewhere.
|
|
9581
|
+
*/
|
|
9582
|
+
function DefaultModelPreference({ preference, defaultModel, t }) {
|
|
9583
|
+
const snapshot = (0, react.useSyncExternalStore)(defaultModel.subscribe, defaultModel.getSnapshot);
|
|
9584
|
+
const models = usePreferenceSnapshot(preference).availableModels;
|
|
9585
|
+
const [open, setOpen] = (0, react.useState)(false);
|
|
9586
|
+
(0, react.useEffect)(() => {
|
|
9587
|
+
defaultModel.load();
|
|
9588
|
+
}, [defaultModel]);
|
|
9589
|
+
const selected = models.find((model) => model.id === snapshot.model);
|
|
9590
|
+
const label = snapshot.managed ? selected?.name ?? snapshot.model : t("defaultModelFollow");
|
|
9591
|
+
const current = snapshot.provider === void 0 ? t("defaultModelUnknown") : `${snapshot.provider} / ${snapshot.model ?? t("defaultModelUnknown")}`;
|
|
9592
|
+
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 });
|
|
9593
|
+
const items = models.map((model) => ({
|
|
9594
|
+
id: model.id,
|
|
9595
|
+
label: model.name
|
|
9596
|
+
}));
|
|
9597
|
+
const disabled = snapshot.saving || snapshot.available !== true || models.length === 0;
|
|
9598
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
9599
|
+
className: "codexSubscriptionPreference",
|
|
9600
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
9601
|
+
className: "codexSubscriptionPreferenceCopy",
|
|
9602
|
+
children: [
|
|
9603
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
9604
|
+
className: "codexSubscriptionPreferenceLabel",
|
|
9605
|
+
children: t("defaultModelTitle")
|
|
9606
|
+
}),
|
|
9607
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
9608
|
+
className: "codexSubscriptionPreferenceHint",
|
|
9609
|
+
children: hint
|
|
9610
|
+
}),
|
|
9611
|
+
snapshot.error ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
9612
|
+
className: "codexSubscriptionError",
|
|
9613
|
+
role: "alert",
|
|
9614
|
+
children: t("defaultModelFailed")
|
|
9615
|
+
}) : null
|
|
9616
|
+
]
|
|
9617
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Menu, {
|
|
9618
|
+
open,
|
|
9619
|
+
items,
|
|
9620
|
+
selectedId: snapshot.managed ? snapshot.model : void 0,
|
|
9621
|
+
onSelect: (value) => {
|
|
9622
|
+
setOpen(false);
|
|
9623
|
+
defaultModel.select(value);
|
|
9624
|
+
},
|
|
9625
|
+
onClose: () => setOpen(false),
|
|
9626
|
+
align: "end",
|
|
9627
|
+
side: "bottom",
|
|
9628
|
+
portal: true,
|
|
9629
|
+
compact: true,
|
|
9630
|
+
anchor: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
9631
|
+
className: "codexSubscriptionContextTrigger",
|
|
9632
|
+
type: "button",
|
|
9633
|
+
"aria-label": t("defaultModelTitle"),
|
|
9634
|
+
"aria-haspopup": "menu",
|
|
9635
|
+
"aria-expanded": open,
|
|
9636
|
+
"aria-busy": snapshot.saving || void 0,
|
|
9637
|
+
title: label,
|
|
9638
|
+
disabled,
|
|
9639
|
+
onClick: () => setOpen((value) => !value),
|
|
9640
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: label }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconChevronDownOutline14, {})]
|
|
9641
|
+
})
|
|
9642
|
+
})]
|
|
9643
|
+
});
|
|
9644
|
+
}
|
|
9645
|
+
//#endregion
|
|
9386
9646
|
//#region src/client-runtime-management.jsx
|
|
9387
9647
|
function RuntimeManagement({ rpc, preference, t }) {
|
|
9388
9648
|
const [state, setState] = (0, react.useState)();
|
|
@@ -9995,7 +10255,7 @@ window.__ModuleLoader__.load({
|
|
|
9995
10255
|
}) : null]
|
|
9996
10256
|
});
|
|
9997
10257
|
}
|
|
9998
|
-
function PreferencesCard({ preference, rpc, t, section = "display" }) {
|
|
10258
|
+
function PreferencesCard({ preference, rpc, t, defaultModel, section = "display" }) {
|
|
9999
10259
|
const snapshot = usePreferenceSnapshot(preference);
|
|
10000
10260
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
10001
10261
|
className: section === "advanced" ? "codexSubscriptionAdvancedPreferences" : "codexSubscriptionCard codexSubscriptionPreferencesCard",
|
|
@@ -10005,6 +10265,11 @@ window.__ModuleLoader__.load({
|
|
|
10005
10265
|
"aria-label": t("modelsSectionTitle"),
|
|
10006
10266
|
children: [
|
|
10007
10267
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", { children: t("modelsSectionTitle") }),
|
|
10268
|
+
defaultModel === void 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(DefaultModelPreference, {
|
|
10269
|
+
preference,
|
|
10270
|
+
defaultModel,
|
|
10271
|
+
t
|
|
10272
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: "codexSubscriptionDivider" })] }),
|
|
10008
10273
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(ModelCatalogStatus, {
|
|
10009
10274
|
preference,
|
|
10010
10275
|
t
|
|
@@ -11437,7 +11702,7 @@ window.__ModuleLoader__.load({
|
|
|
11437
11702
|
}
|
|
11438
11703
|
//#endregion
|
|
11439
11704
|
//#region src/client-section.jsx
|
|
11440
|
-
function CodexSection({ preference, rpc, accountStatus, t, diagnostics }) {
|
|
11705
|
+
function CodexSection({ preference, rpc, accountStatus, t, diagnostics, defaultModel }) {
|
|
11441
11706
|
const [tab, setTab] = (0, react.useState)("account");
|
|
11442
11707
|
const id = (0, react.useId)();
|
|
11443
11708
|
const tabs = [
|
|
@@ -11529,6 +11794,7 @@ window.__ModuleLoader__.load({
|
|
|
11529
11794
|
rpc,
|
|
11530
11795
|
preference,
|
|
11531
11796
|
t,
|
|
11797
|
+
defaultModel,
|
|
11532
11798
|
section: "advanced"
|
|
11533
11799
|
})
|
|
11534
11800
|
}),
|
|
@@ -11749,6 +12015,7 @@ window.__ModuleLoader__.load({
|
|
|
11749
12015
|
getSnapshot: () => ({ status: "unavailable" }),
|
|
11750
12016
|
subscribe: () => () => {}
|
|
11751
12017
|
}, rpc);
|
|
12018
|
+
const defaultModel = createDefaultModelController(rpc);
|
|
11752
12019
|
ctx.effect(() => {
|
|
11753
12020
|
let previous = JSON.stringify(preference.getSnapshot(), (key, value) => key.startsWith("image") || key === "" ? value : void 0);
|
|
11754
12021
|
return preference.subscribe(() => {
|
|
@@ -11769,6 +12036,7 @@ window.__ModuleLoader__.load({
|
|
|
11769
12036
|
return () => {
|
|
11770
12037
|
disposeReset?.();
|
|
11771
12038
|
preference.dispose();
|
|
12039
|
+
defaultModel.dispose();
|
|
11772
12040
|
accountStatus.dispose();
|
|
11773
12041
|
};
|
|
11774
12042
|
}, "codex-subscription: preferences and account status");
|
|
@@ -11793,7 +12061,8 @@ window.__ModuleLoader__.load({
|
|
|
11793
12061
|
rpc,
|
|
11794
12062
|
accountStatus,
|
|
11795
12063
|
t,
|
|
11796
|
-
diagnostics
|
|
12064
|
+
diagnostics,
|
|
12065
|
+
defaultModel
|
|
11797
12066
|
})
|
|
11798
12067
|
}, CodexSection));
|
|
11799
12068
|
const sessions = ctx.get("sessions");
|