dsh-codex-subscription 2.1.1-beta.1 → 2.1.1
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 +4 -5
- package/README.md +4 -5
- package/compatibility.json +2 -1
- package/lib/client.js +177 -18
- package/lib/index.js +241 -18
- package/package.json +16 -16
package/README.en.md
CHANGED
|
@@ -130,10 +130,9 @@ Restart DSH manually after installation, then:
|
|
|
130
130
|
- Optional percentage, progress bar, or Beta runway estimate for the selected Codex model (off by default);
|
|
131
131
|
- Standard or Fast mode for supported Codex models directly in the composer;
|
|
132
132
|
- Standard, Extended, and per-model Custom context windows; Custom accepts a full numeric token count, stays within each audited model capacity, and feeds DSH's native agent compaction policy;
|
|
133
|
-
- A copyable support report and direct feedback link in Settings; the report includes bounded request stages, HTTP/transport classes, elapsed ranges, and route source types while excluding OAuth credentials, account identifiers,
|
|
133
|
+
- A copyable support report and direct feedback link in Settings; the report includes bounded request stages, HTTP/transport classes, elapsed ranges, and route source types while excluding OAuth credentials, account identifiers, and authorization timestamps;
|
|
134
134
|
- Visible errors when subscription routing is unavailable, with no silent paid fallback.
|
|
135
135
|
|
|
136
|
-
The plugin can follow an existing HTTPS proxy from the process environment or operating-system proxy settings for official OpenAI and ChatGPT requests. It does not provide a proxy, relay, node list, or system-proxy configuration.
|
|
137
136
|
|
|
138
137
|
### GPT-6 Astra context
|
|
139
138
|
|
|
@@ -249,8 +248,8 @@ see the [OpenAI Codex Speed documentation](https://learn.chatgpt.com/docs/agent-
|
|
|
249
248
|
|
|
250
249
|
Opt in under **Advanced & diagnostics**. SSE and DSH subtasks remain the defaults:
|
|
251
250
|
|
|
252
|
-
- **WebSocket** reuses connections and eligible context transfers
|
|
253
|
-
- **Codex independent subtasks** reuse your subscription login and the official DSH Codex runtime, without a separate login or CLI setup. They
|
|
251
|
+
- **WebSocket** reuses connections and eligible context transfers. Failed handshakes can fall back to SSE; interrupted responses surface an error without automatic replay. Applies to the next request, does not expand context limits, and is not guaranteed to be faster.
|
|
252
|
+
- **Codex independent subtasks** reuse your subscription login and the official DSH Codex runtime, without a separate login or CLI setup. They inherit the current subscription model and workspace permissions by default. Enable DSH subtask model selection, configure allowed models and start a new session to specify the child model and reasoning effort in chat. Non-subscription sessions must explicitly select a subscription model. Shared-context subtasks remain with DSH.
|
|
254
253
|
|
|
255
254
|
## Update and uninstall
|
|
256
255
|
|
|
@@ -296,7 +295,7 @@ npx -y @deepseek-ai/dsh@0.1.5-rc.1 plugin --profile web remove dsh-codex-subscri
|
|
|
296
295
|
- **`dsh` is not recognized:** the official npm route does not create a global `dsh` command; use the complete `npx -y @deepseek-ai/dsh@0.1.5-rc.1 ...` command above;
|
|
297
296
|
- **More than one DSH exists:** run the standard command from the intended DSH environment so that product selects the corresponding profile;
|
|
298
297
|
- **Setup still fails:** confirm the command is running in the intended DSH environment. Do not delete the profile or change the system PATH to force an install.
|
|
299
|
-
- **Need to report a problem:** generate a **Support diagnostics** report at the bottom of Settings, then open the [bug report form](https://github.com/WSL043/dsh-codex-subscription/issues/new?template=install-problem.yml). The report includes the OS/runtime, bounded sign-in phase, and safe request-failure categories, but excludes credentials, account identifiers,
|
|
298
|
+
- **Need to report a problem:** generate a **Support diagnostics** report at the bottom of Settings, then open the [bug report form](https://github.com/WSL043/dsh-codex-subscription/issues/new?template=install-problem.yml). The report includes the OS/runtime, bounded sign-in phase, and safe request-failure categories, but excludes credentials, account identifiers, raw responses, and full logs. Paste it into the required diagnostics field; never attach sign-in URLs, authorization codes, or browser callback addresses.
|
|
300
299
|
|
|
301
300
|
The ChatGPT Codex backend and DSH can change independently. This community project is not affiliated with or endorsed by DeepSeek or OpenAI.
|
|
302
301
|
|
package/README.md
CHANGED
|
@@ -131,10 +131,9 @@ dsh --profile web --dump-config
|
|
|
131
131
|
- 输入框可用百分比、进度条或可选的 Beta 续航预测显示当前 Codex 模型的剩余额度(默认关闭);
|
|
132
132
|
- 输入框可为支持的 Codex 模型切换标准或高速模式;
|
|
133
133
|
- 上下文窗口提供标准、扩展和逐模型自定义;自定义直接填写完整 Token 数值,并在已审核的模型容量内交给 DSH 原生 Agent 压缩策略处理;
|
|
134
|
-
- 设置页可生成并复制无敏感信息的支持诊断,并直接打开反馈入口;报告包含有限的请求阶段、HTTP/网络分类、耗时区间和路由来源类型,但不包含 OAuth
|
|
134
|
+
- 设置页可生成并复制无敏感信息的支持诊断,并直接打开反馈入口;报告包含有限的请求阶段、HTTP/网络分类、耗时区间和路由来源类型,但不包含 OAuth 凭据、账号标识或授权时间;
|
|
135
135
|
- 订阅路由不可用时明确报错,不会静默切换到其他付费路由。
|
|
136
136
|
|
|
137
|
-
对于 OpenAI 与 ChatGPT 官方请求,插件可以沿用进程环境或操作系统中已有的 HTTPS 代理。插件本身不提供代理、转发服务、节点列表,也不会修改系统代理设置。
|
|
138
137
|
|
|
139
138
|
### GPT-6 Astra 上下文
|
|
140
139
|
|
|
@@ -248,8 +247,8 @@ ChatGPT 返回可用重置卡时,设置页会把每张卡分别显示为紧凑
|
|
|
248
247
|
|
|
249
248
|
在 **高级与诊断** 中按需开启,默认仍使用 SSE 和 DSH 子任务:
|
|
250
249
|
|
|
251
|
-
- **WebSocket
|
|
252
|
-
- **Codex 独立子任务**:复用订阅登录和官方 DSH Codex 运行时,无需另行登录或配置 CLI
|
|
250
|
+
- **WebSocket**:复用连接和可复用的上下文传输;握手失败可回退 SSE,已开始的响应中断会报错,不自动重放。下次请求生效,不增加模型上下文容量,也不保证更快。
|
|
251
|
+
- **Codex 独立子任务**:复用订阅登录和官方 DSH Codex 运行时,无需另行登录或配置 CLI。默认继承当前订阅模型及工作区权限。开启 DSH 子任务模型选择、配置允许模型并新建会话后,可在聊天中指定子任务模型与推理档位;非订阅会话需明确选择订阅模型。共享上下文的子任务仍交给 DSH。
|
|
253
252
|
|
|
254
253
|
## 更新与卸载
|
|
255
254
|
|
|
@@ -295,7 +294,7 @@ npx -y @deepseek-ai/dsh@0.1.5-rc.1 plugin --profile web remove dsh-codex-subscri
|
|
|
295
294
|
- **`dsh` 无法识别**:官方 npm 方式本来就不会创建全局 `dsh` 命令,请使用上面的完整 `npx -y @deepseek-ai/dsh@0.1.5-rc.1 ...` 命令;
|
|
296
295
|
- **电脑上有多个 DSH**:请从目标 DSH 环境运行标准命令,由该产品自身选择对应 profile;
|
|
297
296
|
- **安装仍然失败**:确认命令是在目标 DSH 环境中运行,不要删除 profile 或随意修改系统 PATH。
|
|
298
|
-
- **需要提交问题**:在设置页底部生成“支持诊断”,然后打开[使用问题表单](https://github.com/WSL043/dsh-codex-subscription/issues/new?template=install-problem.yml)
|
|
297
|
+
- **需要提交问题**:在设置页底部生成“支持诊断”,然后打开[使用问题表单](https://github.com/WSL043/dsh-codex-subscription/issues/new?template=install-problem.yml)。报告包含系统/运行时、有限的登录阶段和安全的请求失败分类,但不含凭据、账号标识、原始响应或完整日志;请粘贴到必填诊断栏,且不要附上登录链接、授权码或浏览器回调地址。
|
|
299
298
|
|
|
300
299
|
## 边界与支持
|
|
301
300
|
|
package/compatibility.json
CHANGED
package/lib/client.js
CHANGED
|
@@ -105,6 +105,65 @@ window.__ModuleLoader__.load({
|
|
|
105
105
|
context.fillStyle = context.strokeStyle;
|
|
106
106
|
}
|
|
107
107
|
//#endregion
|
|
108
|
+
//#region src/sketch-text.js
|
|
109
|
+
const cache = /* @__PURE__ */ new WeakMap();
|
|
110
|
+
function layoutSketchText(stroke, context, width, height) {
|
|
111
|
+
const saved = cache.get(stroke);
|
|
112
|
+
if (saved?.width === width && saved?.height === height) return saved.layout;
|
|
113
|
+
const [a, b] = stroke.points;
|
|
114
|
+
const x = Math.min(a.x, b.x) * width, y = Math.min(a.y, b.y) * height;
|
|
115
|
+
const w = Math.abs(b.x - a.x) * width, h = Math.abs(b.y - a.y) * height;
|
|
116
|
+
const wrap = (size) => {
|
|
117
|
+
context.font = `${size}px system-ui, sans-serif`;
|
|
118
|
+
const lines = [];
|
|
119
|
+
for (const paragraph of stroke.text.split("\n")) {
|
|
120
|
+
let line = "";
|
|
121
|
+
for (const char of paragraph) {
|
|
122
|
+
if (line && context.measureText(line + char).width > w) {
|
|
123
|
+
lines.push(line);
|
|
124
|
+
line = "";
|
|
125
|
+
}
|
|
126
|
+
line += char;
|
|
127
|
+
}
|
|
128
|
+
lines.push(line);
|
|
129
|
+
}
|
|
130
|
+
return lines;
|
|
131
|
+
};
|
|
132
|
+
let size = stroke.width, lines = wrap(size);
|
|
133
|
+
if (lines.length * size * 1.2 > h || lines.some((line) => context.measureText(line).width > w)) {
|
|
134
|
+
let low = 0, high = size;
|
|
135
|
+
for (let i = 0; i < 14; i++) {
|
|
136
|
+
const mid = (low + high) / 2, candidate = wrap(mid);
|
|
137
|
+
if (candidate.length * mid * 1.2 <= h && candidate.every((line) => context.measureText(line).width <= w)) low = mid;
|
|
138
|
+
else high = mid;
|
|
139
|
+
}
|
|
140
|
+
size = low;
|
|
141
|
+
lines = wrap(size);
|
|
142
|
+
}
|
|
143
|
+
const layout = {
|
|
144
|
+
x,
|
|
145
|
+
y,
|
|
146
|
+
size,
|
|
147
|
+
lines
|
|
148
|
+
};
|
|
149
|
+
cache.set(stroke, {
|
|
150
|
+
width,
|
|
151
|
+
height,
|
|
152
|
+
layout
|
|
153
|
+
});
|
|
154
|
+
return layout;
|
|
155
|
+
}
|
|
156
|
+
function newTextBounds(point) {
|
|
157
|
+
const a = {
|
|
158
|
+
x: Math.min(point.x, .65),
|
|
159
|
+
y: Math.min(point.y, .85)
|
|
160
|
+
};
|
|
161
|
+
return [a, {
|
|
162
|
+
x: a.x + .35,
|
|
163
|
+
y: a.y + .15
|
|
164
|
+
}];
|
|
165
|
+
}
|
|
166
|
+
//#endregion
|
|
108
167
|
//#region src/sketch-document.js
|
|
109
168
|
const SKETCH_SIZE = 1024;
|
|
110
169
|
const MAX_SKETCH_STROKES = 2e3;
|
|
@@ -134,11 +193,10 @@ window.__ModuleLoader__.load({
|
|
|
134
193
|
context.beginPath();
|
|
135
194
|
const last = stroke.points.at(-1);
|
|
136
195
|
if (stroke.shape === "text") {
|
|
137
|
-
const
|
|
138
|
-
const lines = stroke.text.split("\n"), fontSize = Math.min(stroke.width, h / Math.max(1, lines.length) / 1.2);
|
|
196
|
+
const { x, y, lines, size: fontSize } = layoutSketchText(stroke, context, size, height);
|
|
139
197
|
context.font = `${fontSize}px system-ui, sans-serif`;
|
|
140
198
|
context.textBaseline = "top";
|
|
141
|
-
lines.forEach((line, i) => context.fillText(line, x, y + i * fontSize * 1.2
|
|
199
|
+
lines.forEach((line, i) => context.fillText(line, x, y + i * fontSize * 1.2));
|
|
142
200
|
} else if (stroke.shape === "arrow") {
|
|
143
201
|
const x = last.x * size, y = last.y * height, a = Math.atan2(y - first.y * height, x - first.x * size), head = Math.min(Math.hypot(x - first.x * size, y - first.y * height) * .4, Math.max(12, stroke.width * 3));
|
|
144
202
|
context.moveTo(first.x * size, first.y * height);
|
|
@@ -1372,8 +1430,8 @@ window.__ModuleLoader__.load({
|
|
|
1372
1430
|
scaleX: Math.max(.001, point.x - box.x) / Math.max(.001, box.width),
|
|
1373
1431
|
scaleY: Math.max(.001, point.y - box.y) / Math.max(.001, box.height)
|
|
1374
1432
|
}) : transformObject(gesture.object, {
|
|
1375
|
-
dx: point.x - gesture.start.x,
|
|
1376
|
-
dy: point.y - gesture.start.y
|
|
1433
|
+
dx: Math.max(-box.x, Math.min(1 - box.x - box.width, point.x - gesture.start.x)),
|
|
1434
|
+
dy: Math.max(-box.y, Math.min(1 - box.y - box.height, point.y - gesture.start.y))
|
|
1377
1435
|
});
|
|
1378
1436
|
doc = {
|
|
1379
1437
|
...doc,
|
|
@@ -1585,10 +1643,47 @@ window.__ModuleLoader__.load({
|
|
|
1585
1643
|
bitmap.close();
|
|
1586
1644
|
}
|
|
1587
1645
|
}
|
|
1646
|
+
//#endregion
|
|
1647
|
+
//#region src/sketch-presets.js
|
|
1648
|
+
const SKETCH_PRESETS = [
|
|
1649
|
+
"triangle",
|
|
1650
|
+
"diamond",
|
|
1651
|
+
"star"
|
|
1652
|
+
];
|
|
1653
|
+
function expandSketchPreset(command) {
|
|
1654
|
+
if (!SKETCH_PRESETS.includes(command.shape)) return command;
|
|
1655
|
+
const points = command.points;
|
|
1656
|
+
if (!Array.isArray(points) || points.length !== 2 || points.some((p) => !p || ![p.x, p.y].every((v) => Number.isFinite(v) && v >= 0 && v <= 1))) throw Error("Shape preset requires two normalized bounding-box corners");
|
|
1657
|
+
const [a, b] = points, x = Math.min(a.x, b.x), y = Math.min(a.y, b.y);
|
|
1658
|
+
const w = Math.abs(a.x - b.x), h = Math.abs(a.y - b.y);
|
|
1659
|
+
if (!w || !h) throw Error("Shape preset requires a non-empty box");
|
|
1660
|
+
const vertices = command.shape === "triangle" ? [
|
|
1661
|
+
[.5, 0],
|
|
1662
|
+
[1, 1],
|
|
1663
|
+
[0, 1]
|
|
1664
|
+
] : command.shape === "diamond" ? [
|
|
1665
|
+
[.5, 0],
|
|
1666
|
+
[1, .5],
|
|
1667
|
+
[.5, 1],
|
|
1668
|
+
[0, .5]
|
|
1669
|
+
] : Array.from({ length: 10 }, (_, i) => {
|
|
1670
|
+
const angle = i * Math.PI / 5 - Math.PI / 2, radius = i % 2 ? .22 : .5;
|
|
1671
|
+
return [.5 + Math.cos(angle) * radius, .5 + Math.sin(angle) * radius];
|
|
1672
|
+
});
|
|
1673
|
+
return {
|
|
1674
|
+
...command,
|
|
1675
|
+
shape: "polygon",
|
|
1676
|
+
points: vertices.map(([u, v]) => ({
|
|
1677
|
+
x: x + u * w,
|
|
1678
|
+
y: y + v * h
|
|
1679
|
+
}))
|
|
1680
|
+
};
|
|
1681
|
+
}
|
|
1588
1682
|
const SKETCH_COMMAND_HELP = {
|
|
1589
1683
|
coordinates: "Assign short meaningful stroke id values for later edits. Text uses two opposite box corners and text content; width is font size in pixels, automatic fitting within the box. Arrow uses two endpoints. Normalized x/y in [0,1]; width is canvas pixels. Read documentId and revision before editing.",
|
|
1590
1684
|
shapes: "line: exactly two endpoints; rectangle/circle (ellipse alias accepted): exactly two opposite bounding-box corners (circle draws an ellipse within that box); polygon: three or more vertices, closed automatically; pen: ordered path points. bezier: start point, then groups of control1/control2/end; use 4 points for one cubic curve, max 64 segments. Prefer bezier for smooth designed curves instead of many pen samples. fill:true closes and fills the curve. fill:true fills rectangle/circle/polygon. Layers and strokes paint in list order, later ones on top. All commands needed for drawing are described here; no source-code search is required.",
|
|
1591
1685
|
commands: {
|
|
1686
|
+
preset: "triangle/diamond/star: {op:\"stroke\",id:\"badge\",shape:\"star\",points:[{x:0.1,y:0.1},{x:0.3,y:0.3}],color:\"#ffcc00\",fill:true}. Two opposite box corners; stored as editable polygon. Inspect objectId for one object without repeating full help.",
|
|
1592
1687
|
stroke: "{op:\"stroke\",layer:1,shape:\"pen|line|arrow|text|rectangle|circle|polygon|bezier\",color:\"#rrggbb\",width:2,opacity:1,fill:false,points:[{x:0.1,y:0.1},...]}",
|
|
1593
1688
|
layer: "Add: {op:\"layer\",action:\"add\",value:\"name\"}; optional id is the NEW unique integer ID, otherwise allocated automatically. after is the existing insertion anchor, defaults to active layer. Other actions: {op:\"layer\",action:\"select|rename|visible|duplicate|up|down|delete|clear\",id:1,value:\"name\"}; id targets an existing layer.",
|
|
1594
1689
|
curve: "Prefer {op:\"stroke\",shape:\"bezier\",start:{x:0,y:0},segments:[{control1:{x:0.2,y:0},control2:{x:0.8,y:1},end:{x:1,y:1}}],color:\"#123456\"}. Each segment has exactly two controls and an endpoint; no point counting required. Legacy points arrays still accepted. Do not provide both forms.",
|
|
@@ -1606,8 +1701,9 @@ window.__ModuleLoader__.load({
|
|
|
1606
1701
|
function applySketchCommands(source, commands) {
|
|
1607
1702
|
if (!Array.isArray(commands) || !commands.length || commands.length > 256) throw Error("Expected 1–256 commands");
|
|
1608
1703
|
let doc = identifyObjects(source);
|
|
1609
|
-
for (
|
|
1704
|
+
for (let command of commands) {
|
|
1610
1705
|
if (!command || typeof command !== "object") throw Error("Invalid command");
|
|
1706
|
+
if (command.op === "stroke") command = expandSketchPreset(command);
|
|
1611
1707
|
if (command.op === "resize") {
|
|
1612
1708
|
doc = resizeSketch(doc, command.ratio);
|
|
1613
1709
|
continue;
|
|
@@ -1779,12 +1875,12 @@ window.__ModuleLoader__.load({
|
|
|
1779
1875
|
return {
|
|
1780
1876
|
...current,
|
|
1781
1877
|
protocolVersion: 2,
|
|
1782
|
-
objects: objects.slice(offset, offset + 50),
|
|
1878
|
+
objects: request.objectId ? [] : objects.slice(offset, offset + 50),
|
|
1783
1879
|
objectCount: objects.length,
|
|
1784
|
-
|
|
1880
|
+
...!request.objectId && offset + 50 < objects.length ? { nextOffset: offset + 50 } : {},
|
|
1785
1881
|
...request.objectId ? { object: adapter.object?.(request.objectId, request.layer) } : {},
|
|
1786
1882
|
recentRequests: [...completed.values()].slice(-8).map((entry) => entry.receipt),
|
|
1787
|
-
help: SKETCH_COMMAND_HELP
|
|
1883
|
+
...!request.objectId && offset === 0 ? { help: SKETCH_COMMAND_HELP } : {}
|
|
1788
1884
|
};
|
|
1789
1885
|
}
|
|
1790
1886
|
if (request.documentId !== current.documentId) throw Error("Document changed; inspect again");
|
|
@@ -3735,6 +3831,12 @@ window.__ModuleLoader__.load({
|
|
|
3735
3831
|
width: SKETCH_SIZE,
|
|
3736
3832
|
height: SKETCH_SIZE,
|
|
3737
3833
|
"aria-label": t("sketchTitle"),
|
|
3834
|
+
onDoubleClick: () => {
|
|
3835
|
+
if (!busy && !agentRun.current?.locked && tool === "select" && selected?.shape === "text") setTextEdit({
|
|
3836
|
+
selection,
|
|
3837
|
+
value: selected.text
|
|
3838
|
+
});
|
|
3839
|
+
},
|
|
3738
3840
|
onPointerDown: (event) => {
|
|
3739
3841
|
if (busy || !enabled || active.current) return;
|
|
3740
3842
|
if (navigation.down(event)) return;
|
|
@@ -3928,10 +4030,7 @@ window.__ModuleLoader__.load({
|
|
|
3928
4030
|
try {
|
|
3929
4031
|
if (textEdit.selection) editObject({ text: textEdit.value });
|
|
3930
4032
|
else {
|
|
3931
|
-
const a = textEdit.point,
|
|
3932
|
-
x: Math.min(1, a.x + .35),
|
|
3933
|
-
y: Math.min(1, a.y + .15)
|
|
3934
|
-
}, id = crypto.randomUUID();
|
|
4033
|
+
const [a, b] = newTextBounds(textEdit.point), id = crypto.randomUUID();
|
|
3935
4034
|
const next = applySketchCommands(doc.current, [{
|
|
3936
4035
|
op: "stroke",
|
|
3937
4036
|
id,
|
|
@@ -3960,6 +4059,18 @@ window.__ModuleLoader__.load({
|
|
|
3960
4059
|
autoFocus: true,
|
|
3961
4060
|
"aria-label": t("sketchText"),
|
|
3962
4061
|
maxLength: 500,
|
|
4062
|
+
onKeyDown: (event) => {
|
|
4063
|
+
if (event.nativeEvent.isComposing) return;
|
|
4064
|
+
if (event.key === "Escape") {
|
|
4065
|
+
event.preventDefault();
|
|
4066
|
+
event.stopPropagation();
|
|
4067
|
+
setTextEdit(null);
|
|
4068
|
+
}
|
|
4069
|
+
if (event.key === "Enter" && (event.ctrlKey || event.metaKey)) {
|
|
4070
|
+
event.preventDefault();
|
|
4071
|
+
event.currentTarget.form.requestSubmit();
|
|
4072
|
+
}
|
|
4073
|
+
},
|
|
3963
4074
|
value: textEdit.value,
|
|
3964
4075
|
onChange: (e) => setTextEdit({
|
|
3965
4076
|
...textEdit,
|
|
@@ -4351,13 +4462,17 @@ window.__ModuleLoader__.load({
|
|
|
4351
4462
|
//#endregion
|
|
4352
4463
|
//#region src/client-locales.js
|
|
4353
4464
|
const zh = {
|
|
4465
|
+
compactionTitle: "云端压缩",
|
|
4466
|
+
compaction_dsh: "关闭",
|
|
4467
|
+
compaction_cloud: "开启",
|
|
4468
|
+
compactionHint: "实验功能,默认关闭。长上下文由 Codex 压缩后继续请求,保留 DSH 历史与原生压缩。开启时该请求使用 SSE;历史改变后重新建立压缩状态。",
|
|
4354
4469
|
advancedModelSearch: "模型与搜索",
|
|
4355
4470
|
subagentBackendTitle: "独立子任务",
|
|
4356
4471
|
subagentBackend_dsh: "DSH",
|
|
4357
4472
|
subagentBackend_codex: "Codex",
|
|
4358
4473
|
connectionTitle: "连接方式",
|
|
4359
|
-
connectionHint: "默认 SSE。WebSocket
|
|
4360
|
-
subagentBackendHint: "Codex
|
|
4474
|
+
connectionHint: "默认 SSE。WebSocket 实验性复用连接与上下文传输;连接失败可回退 SSE。下次请求生效,不扩大上下文容量。",
|
|
4475
|
+
subagentBackendHint: "Codex 复用订阅登录和工作区权限;默认继承当前订阅模型。开启 DSH 子任务模型选择并新建会话后,可在聊天中指定允许的订阅模型与推理档位;非订阅会话需指定。共享上下文子任务仍用 DSH。",
|
|
4361
4476
|
subagentBackendUnavailable: "当前宿主缺少子代理服务,请更新 DSH。",
|
|
4362
4477
|
sketchRecovered: "已恢复未保存草稿",
|
|
4363
4478
|
sketchRecoveryFailed: "恢复检查点保存失败,请手动保存或导出草稿。",
|
|
@@ -4775,13 +4890,17 @@ window.__ModuleLoader__.load({
|
|
|
4775
4890
|
imageRemoveAnnotation: "删除标注"
|
|
4776
4891
|
};
|
|
4777
4892
|
const en = {
|
|
4893
|
+
compactionTitle: "Cloud compaction",
|
|
4894
|
+
compaction_dsh: "Off",
|
|
4895
|
+
compaction_cloud: "On",
|
|
4896
|
+
compactionHint: "Experimental, off by default. Codex compacts long requests while DSH history and native compaction remain available. These requests use SSE; changed history invalidates previous checkpoints.",
|
|
4778
4897
|
advancedModelSearch: "Models and search",
|
|
4779
4898
|
subagentBackendTitle: "Independent subtasks",
|
|
4780
4899
|
subagentBackend_dsh: "DSH",
|
|
4781
4900
|
subagentBackend_codex: "Codex",
|
|
4782
4901
|
connectionTitle: "Connection",
|
|
4783
|
-
connectionHint: "SSE by default. Experimental WebSocket reuses connections and context transfers
|
|
4784
|
-
subagentBackendHint: "Codex
|
|
4902
|
+
connectionHint: "SSE by default. Experimental WebSocket reuses connections and context transfers and can fall back to SSE on connection failure. Applies to the next request; context limits stay the same.",
|
|
4903
|
+
subagentBackendHint: "Codex reuses subscription login and workspace permissions, inheriting the current subscription model by default. Enable DSH subtask model selection and start a new session to request an allowed subscription model and reasoning effort in chat; other model sessions require an explicit selection. Shared-context subtasks stay in DSH.",
|
|
4785
4904
|
subagentBackendUnavailable: "Subagent services are unavailable. Update DSH to use this option.",
|
|
4786
4905
|
sketchRecovered: "Unsaved sketch recovered",
|
|
4787
4906
|
sketchRecoveryFailed: "Recovery checkpoint failed. Save or export your draft.",
|
|
@@ -6567,6 +6686,7 @@ window.__ModuleLoader__.load({
|
|
|
6567
6686
|
status: current.status,
|
|
6568
6687
|
...capabilities,
|
|
6569
6688
|
connectionMode: value?.connectionMode === "websocket" ? "websocket" : "sse",
|
|
6689
|
+
compactionMode: value?.compactionMode === "cloud" ? "cloud" : "dsh",
|
|
6570
6690
|
subagentBackend: value?.subagentBackend === "codex" ? "codex" : "dsh",
|
|
6571
6691
|
subagentBackendAvailable,
|
|
6572
6692
|
quickQuotaMode: normalizeQuickQuotaMode(value?.[QUICK_QUOTA_MODE_FIELD], value?.[LEGACY_QUICK_QUOTA_FIELD]),
|
|
@@ -6614,6 +6734,7 @@ window.__ModuleLoader__.load({
|
|
|
6614
6734
|
status: "ready",
|
|
6615
6735
|
value: {
|
|
6616
6736
|
connectionMode: value?.connectionMode === "websocket" ? "websocket" : "sse",
|
|
6737
|
+
compactionMode: value?.compactionMode === "cloud" ? "cloud" : "dsh",
|
|
6617
6738
|
subagentBackend: value?.subagentBackend === "codex" ? "codex" : "dsh",
|
|
6618
6739
|
...readCapabilitySettings(value),
|
|
6619
6740
|
[QUICK_QUOTA_MODE_FIELD]: normalizeQuickQuotaMode(value?.[QUICK_QUOTA_MODE_FIELD], value?.[LEGACY_QUICK_QUOTA_FIELD]),
|
|
@@ -7025,7 +7146,7 @@ window.__ModuleLoader__.load({
|
|
|
7025
7146
|
}
|
|
7026
7147
|
//#endregion
|
|
7027
7148
|
//#region src/version.js
|
|
7028
|
-
const PACKAGE_VERSION = "2.1.1
|
|
7149
|
+
const PACKAGE_VERSION = "2.1.1";
|
|
7029
7150
|
//#endregion
|
|
7030
7151
|
//#region src/client-recovery.js
|
|
7031
7152
|
async function recoveryCall(rpc, endpoint, payload = {}, timeoutMs = 1e4) {
|
|
@@ -8212,6 +8333,44 @@ window.__ModuleLoader__.load({
|
|
|
8212
8333
|
})]
|
|
8213
8334
|
})
|
|
8214
8335
|
}),
|
|
8336
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("section", {
|
|
8337
|
+
className: "codexSubscriptionCard codexSubscriptionPreferencesCard",
|
|
8338
|
+
"aria-label": t("compactionTitle"),
|
|
8339
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
8340
|
+
className: "codexSubscriptionPreference",
|
|
8341
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
8342
|
+
className: "codexSubscriptionPreferenceCopy",
|
|
8343
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
8344
|
+
className: "codexSubscriptionPreferenceLabel",
|
|
8345
|
+
children: [
|
|
8346
|
+
t("compactionTitle"),
|
|
8347
|
+
" ",
|
|
8348
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: "Beta" })
|
|
8349
|
+
]
|
|
8350
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
8351
|
+
className: "codexSubscriptionPreferenceHint",
|
|
8352
|
+
children: t("compactionHint")
|
|
8353
|
+
})]
|
|
8354
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
8355
|
+
className: "codexSubscriptionQuotaModes",
|
|
8356
|
+
role: "radiogroup",
|
|
8357
|
+
"aria-label": t("compactionTitle"),
|
|
8358
|
+
"aria-busy": snapshot.saving || void 0,
|
|
8359
|
+
children: ["dsh", "cloud"].map((value) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
8360
|
+
className: "codexSubscriptionQuotaMode",
|
|
8361
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
8362
|
+
type: "radio",
|
|
8363
|
+
name: "codex-compaction-mode",
|
|
8364
|
+
checked: snapshot.compactionMode === value,
|
|
8365
|
+
disabled: !snapshot.writable,
|
|
8366
|
+
onChange: () => {
|
|
8367
|
+
preference.set({ compactionMode: value });
|
|
8368
|
+
}
|
|
8369
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t(`compaction_${value}`) })]
|
|
8370
|
+
}, value))
|
|
8371
|
+
})]
|
|
8372
|
+
})
|
|
8373
|
+
}),
|
|
8215
8374
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("section", {
|
|
8216
8375
|
className: "codexSubscriptionCard codexSubscriptionPreferencesCard",
|
|
8217
8376
|
"aria-label": t("subagentBackendTitle"),
|
package/lib/index.js
CHANGED
|
@@ -288,6 +288,11 @@ const supportsCodexFastMode = (modelId) => typeof modelId === "string" && (/^gpt
|
|
|
288
288
|
//#endregion
|
|
289
289
|
//#region src/preference-fields.js
|
|
290
290
|
const PREFERENCE_FIELDS = Object.freeze({
|
|
291
|
+
compactionMode: {
|
|
292
|
+
choices: ["dsh", "cloud"],
|
|
293
|
+
default: "dsh",
|
|
294
|
+
error: "Invalid compaction mode"
|
|
295
|
+
},
|
|
291
296
|
connectionMode: {
|
|
292
297
|
choices: ["sse", "websocket"],
|
|
293
298
|
default: "sse",
|
|
@@ -530,7 +535,8 @@ async function withCodexNetwork(run, options = {}) {
|
|
|
530
535
|
}
|
|
531
536
|
const route = await proxy;
|
|
532
537
|
scopedOptions.onRoute?.(route.source);
|
|
533
|
-
|
|
538
|
+
const response = await (route.url === void 0 ? baseFetch(input, init) : proxyFetch(input, init, route.url));
|
|
539
|
+
return scopedOptions.transformResponse?.(response, target) ?? response;
|
|
534
540
|
};
|
|
535
541
|
globalThis.fetch = scopedFetch;
|
|
536
542
|
}
|
|
@@ -656,6 +662,190 @@ function createSubscriptionConnection({ resolveMode = () => "sse", resolveProxy
|
|
|
656
662
|
};
|
|
657
663
|
}
|
|
658
664
|
//#endregion
|
|
665
|
+
//#region src/subscription-compaction.js
|
|
666
|
+
/** Experimental SSE bridge; callers must explicitly opt in. */
|
|
667
|
+
const clone$2 = (value) => JSON.parse(JSON.stringify(value));
|
|
668
|
+
const hash = (value) => createHash("sha256").update(JSON.stringify(value)).digest("hex");
|
|
669
|
+
const key = "codexCompactionV1";
|
|
670
|
+
const historyHash = (messages) => hash(messages.map(({ source, ...message }) => ({
|
|
671
|
+
...message,
|
|
672
|
+
source: source && {
|
|
673
|
+
kind: source.kind,
|
|
674
|
+
provider: source.provider,
|
|
675
|
+
model: source.model
|
|
676
|
+
}
|
|
677
|
+
})));
|
|
678
|
+
const MAX_BYTES = 2 * 1024 * 1024;
|
|
679
|
+
const MAX_AGE_MS = 10080 * 60 * 1e3;
|
|
680
|
+
function createCompactionBridge({ enabled = () => false, threshold = () => 1e5, accountScope, diagnostic = () => {}, now = Date.now }) {
|
|
681
|
+
const scope = new AsyncLocalStorage();
|
|
682
|
+
const wrapStream = (factory, options) => (async function* () {
|
|
683
|
+
if (!enabled() || options.provider !== "openai-codex") {
|
|
684
|
+
yield* factory(options);
|
|
685
|
+
return;
|
|
686
|
+
}
|
|
687
|
+
const identity = await accountScope(options);
|
|
688
|
+
if (!identity) throw new Error("Compaction requires a stable account identity");
|
|
689
|
+
const state = {
|
|
690
|
+
identity: hash([identity, options.model]),
|
|
691
|
+
original: options.messages,
|
|
692
|
+
blocks: [],
|
|
693
|
+
suffix: void 0,
|
|
694
|
+
completed: false
|
|
695
|
+
};
|
|
696
|
+
let messages = options.messages;
|
|
697
|
+
for (let i = messages.length - 1; i >= 0; i--) {
|
|
698
|
+
const candidate = messages[i].source?.replayState?.response?.[key];
|
|
699
|
+
if (!candidate) continue;
|
|
700
|
+
if (Number.isFinite(candidate.createdAt) && candidate.createdAt <= now() && now() - candidate.createdAt <= MAX_AGE_MS && candidate.scope === state.identity && candidate.prefix === historyHash(messages.slice(0, i)) && candidate.content === hash(messages[i].content) && Array.isArray(candidate.items) && candidate.items[0]?.type === "compaction" && typeof candidate.items[0].encrypted_content === "string" && candidate.digest === hash(candidate.items) && JSON.stringify(candidate.items).length <= MAX_BYTES) {
|
|
701
|
+
state.suffix = clone$2(candidate.items);
|
|
702
|
+
messages = [...messages.slice(0, i + 1).filter((m) => m.role === "system"), ...messages.slice(i + 1)];
|
|
703
|
+
}
|
|
704
|
+
break;
|
|
705
|
+
}
|
|
706
|
+
const iterator = scope.run(state, () => factory({
|
|
707
|
+
...options,
|
|
708
|
+
messages
|
|
709
|
+
})[Symbol.asyncIterator]());
|
|
710
|
+
try {
|
|
711
|
+
while (true) {
|
|
712
|
+
const result = await scope.run(state, () => iterator.next());
|
|
713
|
+
if (result.done) break;
|
|
714
|
+
let event = result.value;
|
|
715
|
+
if (event.type === "block-end") state.blocks[event.index] = clone$2(event.block);
|
|
716
|
+
if (event.type === "finish") diagnostic({
|
|
717
|
+
completed: state.completed,
|
|
718
|
+
captured: state.captured?.length ?? 0,
|
|
719
|
+
replay: !!event.replayState
|
|
720
|
+
});
|
|
721
|
+
if (event.type === "finish" && ["stop", "tool-calls"].includes(event.reason?.kind) && !options.signal?.aborted && state.completed && state.captured?.length && event.replayState) {
|
|
722
|
+
const items = state.captured;
|
|
723
|
+
const checkpoint = {
|
|
724
|
+
createdAt: now(),
|
|
725
|
+
scope: state.identity,
|
|
726
|
+
prefix: historyHash(state.original),
|
|
727
|
+
content: hash(state.blocks.filter(Boolean)),
|
|
728
|
+
items,
|
|
729
|
+
digest: hash(items)
|
|
730
|
+
};
|
|
731
|
+
event = {
|
|
732
|
+
...event,
|
|
733
|
+
replayState: {
|
|
734
|
+
...event.replayState,
|
|
735
|
+
response: {
|
|
736
|
+
...event.replayState.response,
|
|
737
|
+
[key]: checkpoint
|
|
738
|
+
}
|
|
739
|
+
}
|
|
740
|
+
};
|
|
741
|
+
}
|
|
742
|
+
yield event;
|
|
743
|
+
}
|
|
744
|
+
} finally {
|
|
745
|
+
await scope.run(state, () => iterator.return?.());
|
|
746
|
+
}
|
|
747
|
+
})();
|
|
748
|
+
return {
|
|
749
|
+
wrapAdapter(adapter) {
|
|
750
|
+
return new Proxy(adapter, { get(target, property) {
|
|
751
|
+
if (property === "stream") return (options) => wrapStream((o) => target.stream(o), options);
|
|
752
|
+
if (property === "prepareCall") return async (...args) => {
|
|
753
|
+
const call = await target.prepareCall(...args);
|
|
754
|
+
return {
|
|
755
|
+
...call,
|
|
756
|
+
stream: (options) => wrapStream((o) => call.stream(o), options)
|
|
757
|
+
};
|
|
758
|
+
};
|
|
759
|
+
const value = Reflect.get(target, property, target);
|
|
760
|
+
return typeof value === "function" ? value.bind(target) : value;
|
|
761
|
+
} });
|
|
762
|
+
},
|
|
763
|
+
preparePayload(payload, contextWindow) {
|
|
764
|
+
const state = scope.getStore();
|
|
765
|
+
if (!state) return payload;
|
|
766
|
+
const configured = threshold();
|
|
767
|
+
if (!Number.isSafeInteger(configured) || configured < 1e3) throw new Error("Invalid compaction threshold");
|
|
768
|
+
const limit = Number.isFinite(contextWindow) && contextWindow >= 2e3 ? Math.min(configured, Math.floor(contextWindow / 2)) : configured;
|
|
769
|
+
if (!Number.isSafeInteger(limit) || limit < 1e3) throw new Error("Invalid compaction threshold");
|
|
770
|
+
return {
|
|
771
|
+
...payload,
|
|
772
|
+
input: [...state.suffix ?? [], ...payload.input],
|
|
773
|
+
context_management: [{
|
|
774
|
+
type: "compaction",
|
|
775
|
+
compact_threshold: limit
|
|
776
|
+
}]
|
|
777
|
+
};
|
|
778
|
+
},
|
|
779
|
+
requestOptions(options) {
|
|
780
|
+
return scope.getStore() ? {
|
|
781
|
+
...options,
|
|
782
|
+
transport: "sse"
|
|
783
|
+
} : options;
|
|
784
|
+
},
|
|
785
|
+
networkOptions(options) {
|
|
786
|
+
const state = scope.getStore();
|
|
787
|
+
if (!state) return options;
|
|
788
|
+
return {
|
|
789
|
+
...options,
|
|
790
|
+
websocket: false,
|
|
791
|
+
transformResponse: (response, target) => {
|
|
792
|
+
if (target.hostname !== "chatgpt.com" || target.pathname !== "/backend-api/codex/responses" || !response.ok || !response.body) return response;
|
|
793
|
+
state.completed = false;
|
|
794
|
+
state.captured = void 0;
|
|
795
|
+
let buffer = "", oversized = false;
|
|
796
|
+
const decoder = new TextDecoder();
|
|
797
|
+
const observe = (line) => {
|
|
798
|
+
if (!line.startsWith("data:")) return;
|
|
799
|
+
const data = line.slice(5).trim();
|
|
800
|
+
if (data === "[DONE]") return;
|
|
801
|
+
let event;
|
|
802
|
+
try {
|
|
803
|
+
event = JSON.parse(data);
|
|
804
|
+
} catch {
|
|
805
|
+
return;
|
|
806
|
+
}
|
|
807
|
+
if (event.type === "response.output_item.done") {
|
|
808
|
+
if (event.item?.type === "compaction") state.captured = [clone$2(event.item)];
|
|
809
|
+
else if (state.captured) state.captured.push(clone$2(event.item));
|
|
810
|
+
if (state.captured && JSON.stringify(state.captured).length > MAX_BYTES) {
|
|
811
|
+
state.captured = void 0;
|
|
812
|
+
oversized = true;
|
|
813
|
+
}
|
|
814
|
+
}
|
|
815
|
+
if (event.type === "response.completed" && event.response?.status === "completed") state.completed = !oversized;
|
|
816
|
+
};
|
|
817
|
+
const stream = response.body.pipeThrough(new TransformStream({
|
|
818
|
+
transform(bytes, controller) {
|
|
819
|
+
controller.enqueue(bytes);
|
|
820
|
+
if (oversized) return;
|
|
821
|
+
buffer += decoder.decode(bytes, { stream: true });
|
|
822
|
+
let index;
|
|
823
|
+
while ((index = buffer.indexOf("\n")) >= 0) {
|
|
824
|
+
observe(buffer.slice(0, index).trimEnd());
|
|
825
|
+
buffer = buffer.slice(index + 1);
|
|
826
|
+
}
|
|
827
|
+
if (buffer.length > MAX_BYTES) {
|
|
828
|
+
buffer = "";
|
|
829
|
+
oversized = true;
|
|
830
|
+
state.captured = void 0;
|
|
831
|
+
}
|
|
832
|
+
},
|
|
833
|
+
flush() {
|
|
834
|
+
buffer += decoder.decode();
|
|
835
|
+
if (!oversized && buffer) observe(buffer.trimEnd());
|
|
836
|
+
}
|
|
837
|
+
}));
|
|
838
|
+
return new Response(stream, {
|
|
839
|
+
status: response.status,
|
|
840
|
+
statusText: response.statusText,
|
|
841
|
+
headers: response.headers
|
|
842
|
+
});
|
|
843
|
+
}
|
|
844
|
+
};
|
|
845
|
+
}
|
|
846
|
+
};
|
|
847
|
+
}
|
|
848
|
+
//#endregion
|
|
659
849
|
//#region src/rpc-contract.js
|
|
660
850
|
const RPC_ENDPOINTS = Object.freeze([
|
|
661
851
|
"status",
|
|
@@ -851,16 +1041,34 @@ const MODES = /* @__PURE__ */ new Set([
|
|
|
851
1041
|
"workspace-write",
|
|
852
1042
|
"danger-full-access"
|
|
853
1043
|
]);
|
|
854
|
-
function subagentThreadPolicy(parent, policy) {
|
|
1044
|
+
function subagentThreadPolicy(parent, policy, requested = {}) {
|
|
855
1045
|
if (!MODES.has(policy?.mode)) throw new Error("DSH subagent sandbox policy is unavailable");
|
|
856
1046
|
const selected = parent.session.requestHeader?.()?.config ?? parent.options ?? {};
|
|
857
|
-
const
|
|
1047
|
+
for (const key of Object.keys(requested)) if (![
|
|
1048
|
+
"provider",
|
|
1049
|
+
"model",
|
|
1050
|
+
"reasoningEffort"
|
|
1051
|
+
].includes(key)) throw new Error("Unsupported Codex child option: " + key);
|
|
1052
|
+
if (requested.provider !== void 0 && requested.provider !== "openai-codex") throw new Error("Codex subtasks require the openai-codex provider");
|
|
1053
|
+
const model = requested.model ?? (selected.provider === "openai-codex" ? selected.model : void 0);
|
|
1054
|
+
if (typeof model !== "string" || !model.trim()) throw new Error("Select an openai-codex model for this subtask; the parent model cannot be inherited");
|
|
1055
|
+
const effort = requested.reasoningEffort ?? (requested.model === void 0 ? selected.reasoningEffort : void 0);
|
|
1056
|
+
if (effort !== void 0 && ![
|
|
1057
|
+
"none",
|
|
1058
|
+
"minimal",
|
|
1059
|
+
"low",
|
|
1060
|
+
"medium",
|
|
1061
|
+
"high",
|
|
1062
|
+
"xhigh",
|
|
1063
|
+
"max",
|
|
1064
|
+
"ultra"
|
|
1065
|
+
].includes(effort)) throw new Error("Unsupported Codex reasoning effort");
|
|
858
1066
|
return {
|
|
859
|
-
model
|
|
1067
|
+
model,
|
|
860
1068
|
modelProvider: "openai",
|
|
861
1069
|
approvalPolicy: "never",
|
|
862
1070
|
sandbox: policy.mode,
|
|
863
|
-
config:
|
|
1071
|
+
config: effort === void 0 ? {} : { model_reasoning_effort: effort }
|
|
864
1072
|
};
|
|
865
1073
|
}
|
|
866
1074
|
/** Reuse the official DSH process/turn provider; keep only subscription auth here. */
|
|
@@ -876,7 +1084,7 @@ function createSubscriptionSubagent({ ctx, nativeHome, resolveAuth, store, refre
|
|
|
876
1084
|
provider: {
|
|
877
1085
|
name: SUBAGENT_PROVIDER,
|
|
878
1086
|
capabilities: {
|
|
879
|
-
agentOptions:
|
|
1087
|
+
agentOptions: true,
|
|
880
1088
|
outputSchema: false,
|
|
881
1089
|
depthLimit: false,
|
|
882
1090
|
toolFilter: false,
|
|
@@ -890,7 +1098,7 @@ function createSubscriptionSubagent({ ctx, nativeHome, resolveAuth, store, refre
|
|
|
890
1098
|
const signal = AbortSignal.any([request.signal, controller.signal]);
|
|
891
1099
|
let run;
|
|
892
1100
|
try {
|
|
893
|
-
const thread = subagentThreadPolicy(request.parent, ctx.sandboxPolicy.resolve({ session: request.parent.session }));
|
|
1101
|
+
const thread = subagentThreadPolicy(request.parent, ctx.sandboxPolicy.resolve({ session: request.parent.session }), request.agentOptions);
|
|
894
1102
|
const getTokens = await createSubagentTokens({
|
|
895
1103
|
resolveAuth,
|
|
896
1104
|
store,
|
|
@@ -935,6 +1143,7 @@ function createSubscriptionSubagent({ ctx, nativeHome, resolveAuth, store, refre
|
|
|
935
1143
|
});
|
|
936
1144
|
run = await delegate.start({
|
|
937
1145
|
...request,
|
|
1146
|
+
agentOptions: void 0,
|
|
938
1147
|
signal
|
|
939
1148
|
});
|
|
940
1149
|
const result = run.result.finally(() => active.delete(controller));
|
|
@@ -972,7 +1181,7 @@ function createSubagentBackendSwitcher({ entries, prepare, persist }) {
|
|
|
972
1181
|
const convert = (config) => ({
|
|
973
1182
|
...config,
|
|
974
1183
|
provider: SUBAGENT_PROVIDER,
|
|
975
|
-
modelSelectionSettings:
|
|
1184
|
+
modelSelectionSettings: true,
|
|
976
1185
|
backgroundMode: "one-shot",
|
|
977
1186
|
maxDepth: "provider-managed"
|
|
978
1187
|
});
|
|
@@ -1260,7 +1469,10 @@ const sketchCommandArray = {
|
|
|
1260
1469
|
"ellipse",
|
|
1261
1470
|
"polygon",
|
|
1262
1471
|
"bezier",
|
|
1263
|
-
"eraser"
|
|
1472
|
+
"eraser",
|
|
1473
|
+
"triangle",
|
|
1474
|
+
"diamond",
|
|
1475
|
+
"star"
|
|
1264
1476
|
]
|
|
1265
1477
|
},
|
|
1266
1478
|
...style,
|
|
@@ -2297,7 +2509,7 @@ const FAST_SERVICE_TIER = "priority";
|
|
|
2297
2509
|
* persistence, headers, transport, and model behavior remain owned by the
|
|
2298
2510
|
* original provider.
|
|
2299
2511
|
*/
|
|
2300
|
-
function openaiCodexSubscriptionProvider({ resolveSpeedMode = () => void 0, resolveOutputVerbosity = () => OUTPUT_VERBOSITY_DEFAULT, resolveContextMode = () => void 0, resolveCustomContextWindow = () => void 0, catalog, connection, runNetwork = (_area, operation) => operation() } = {}) {
|
|
2512
|
+
function openaiCodexSubscriptionProvider({ resolveSpeedMode = () => void 0, resolveOutputVerbosity = () => OUTPUT_VERBOSITY_DEFAULT, resolveContextMode = () => void 0, resolveCustomContextWindow = () => void 0, catalog, connection, compaction, runNetwork = (_area, operation) => operation() } = {}) {
|
|
2301
2513
|
const provider = createOpenAICodexProvider();
|
|
2302
2514
|
const requestToken = Object.freeze({
|
|
2303
2515
|
name: "DSH-managed Codex OAuth request token",
|
|
@@ -2331,11 +2543,12 @@ function openaiCodexSubscriptionProvider({ resolveSpeedMode = () => void 0, reso
|
|
|
2331
2543
|
} },
|
|
2332
2544
|
...fast ? { service_tier: FAST_SERVICE_TIER } : {}
|
|
2333
2545
|
};
|
|
2334
|
-
const
|
|
2546
|
+
const managed = compaction?.preparePayload(preferred, model?.contextWindow) ?? preferred;
|
|
2547
|
+
const next = await onPayload?.(managed, requestModel);
|
|
2335
2548
|
return {
|
|
2336
|
-
...next ??
|
|
2549
|
+
...next ?? managed,
|
|
2337
2550
|
...textVerbosity === void 0 ? {} : { text: {
|
|
2338
|
-
...(next ??
|
|
2551
|
+
...(next ?? managed).text ?? {},
|
|
2339
2552
|
verbosity: textVerbosity
|
|
2340
2553
|
} },
|
|
2341
2554
|
...fast ? { service_tier: FAST_SERVICE_TIER } : {}
|
|
@@ -2366,12 +2579,12 @@ function openaiCodexSubscriptionProvider({ resolveSpeedMode = () => void 0, reso
|
|
|
2366
2579
|
const step = async (method, value) => {
|
|
2367
2580
|
const request = await (prepared ??= connection?.prepare(options) ?? Promise.resolve({ options }));
|
|
2368
2581
|
return runNetwork("model", () => {
|
|
2369
|
-
iterator ??= factory(request.options)[Symbol.asyncIterator]();
|
|
2582
|
+
iterator ??= factory(compaction?.requestOptions(request.options) ?? request.options)[Symbol.asyncIterator]();
|
|
2370
2583
|
return iterator[method]?.(value) ?? (method === "throw" ? Promise.reject(value) : Promise.resolve({
|
|
2371
2584
|
done: true,
|
|
2372
2585
|
value
|
|
2373
2586
|
}));
|
|
2374
|
-
}, request.network);
|
|
2587
|
+
}, compaction?.networkOptions(request.network) ?? request.network);
|
|
2375
2588
|
};
|
|
2376
2589
|
return {
|
|
2377
2590
|
[Symbol.asyncIterator]() {
|
|
@@ -2399,7 +2612,7 @@ function openaiCodexSubscriptionProvider({ resolveSpeedMode = () => void 0, reso
|
|
|
2399
2612
|
Object.freeze(["0.82.1", "0.85.1"]);
|
|
2400
2613
|
//#endregion
|
|
2401
2614
|
//#region src/version.js
|
|
2402
|
-
const PACKAGE_VERSION = "2.1.1
|
|
2615
|
+
const PACKAGE_VERSION = "2.1.1";
|
|
2403
2616
|
const USER_AGENT = `dsh-codex-subscription/${PACKAGE_VERSION}`;
|
|
2404
2617
|
//#endregion
|
|
2405
2618
|
//#region src/model-catalog.js
|
|
@@ -4643,7 +4856,7 @@ function apply(ctx) {
|
|
|
4643
4856
|
...Object.fromEntries(Object.entries(IMAGE_FEATURE_DEFAULTS).map(([key, value]) => [key, z.boolean().default(value)])),
|
|
4644
4857
|
[CUSTOM_CONTEXT_OVERRIDES_FIELD]: z.dict(z.number().step(1).min(1).max(MAX_CONTEXT_BUDGET)).default({}),
|
|
4645
4858
|
[SEARCH_MODE_FIELD]: z.union(SEARCH_MODES).default("live"),
|
|
4646
|
-
[SEARCH_DOMAINS_FIELD]: z.transform(z.array(z.string()).max(20),
|
|
4859
|
+
[SEARCH_DOMAINS_FIELD]: z.transform(z.array(z.string()).max(20), normalizeSearchDomains).default([]),
|
|
4647
4860
|
...Object.fromEntries(QUOTA_THRESHOLD_FIELDS.map((key) => [key, z.number().step(1).min(1).max(100).default(20)])),
|
|
4648
4861
|
[QUOTA_ALERTS_FIELD]: z.union(QUOTA_ALERT_MODES).default("important"),
|
|
4649
4862
|
[LEGACY_QUICK_QUOTA_FIELD]: z.boolean(),
|
|
@@ -4672,9 +4885,18 @@ function apply(ctx) {
|
|
|
4672
4885
|
fetch: (input, init) => network.fetch("catalog", input, init)
|
|
4673
4886
|
});
|
|
4674
4887
|
const connection = createSubscriptionConnection({ resolveMode: () => settings.get().connectionMode });
|
|
4888
|
+
const compaction = createCompactionBridge({
|
|
4889
|
+
enabled: () => settings.get().compactionMode === "cloud",
|
|
4890
|
+
accountScope: async () => {
|
|
4891
|
+
await resolveAuth();
|
|
4892
|
+
const credential = await store.read(PROVIDER);
|
|
4893
|
+
return credential?.type === "oauth" ? credential.accountId : void 0;
|
|
4894
|
+
}
|
|
4895
|
+
});
|
|
4675
4896
|
ctx.effect(() => () => connection.dispose());
|
|
4676
4897
|
const provider = openaiCodexSubscriptionProvider({
|
|
4677
4898
|
connection,
|
|
4899
|
+
compaction,
|
|
4678
4900
|
resolveSpeedMode: () => settings.get()[SPEED_MODE_FIELD],
|
|
4679
4901
|
resolveOutputVerbosity: () => normalizeOutputVerbosity(settings.get()[OUTPUT_VERBOSITY_FIELD]),
|
|
4680
4902
|
resolveContextMode: () => normalizeContextMode(settings.get()[CONTEXT_MODE_FIELD]),
|
|
@@ -4690,6 +4912,7 @@ function apply(ctx) {
|
|
|
4690
4912
|
});
|
|
4691
4913
|
const preferences = {
|
|
4692
4914
|
status: () => ({
|
|
4915
|
+
compactionMode: settings.get().compactionMode ?? "dsh",
|
|
4693
4916
|
connectionMode: settings.get().connectionMode ?? "sse",
|
|
4694
4917
|
subagentBackend: settings.get().subagentBackend ?? "dsh",
|
|
4695
4918
|
subagentBackendAvailable: subagentBackend !== void 0,
|
|
@@ -4826,7 +5049,7 @@ function apply(ctx) {
|
|
|
4826
5049
|
auth: adapterAuth,
|
|
4827
5050
|
resolveAttachments: () => ctx.get?.("attachments")
|
|
4828
5051
|
});
|
|
4829
|
-
ctx.llm.registerAdapter([PROVIDER], adapter);
|
|
5052
|
+
ctx.llm.registerAdapter([PROVIDER], compaction.wrapAdapter(adapter));
|
|
4830
5053
|
const currentAgent = () => ctx.get?.("agents")?.currentInitiator?.();
|
|
4831
5054
|
const codexSearch = createCodexSearchProvider({
|
|
4832
5055
|
resolvePreferences: () => readCapabilitySettings(settings.get()),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-codex-subscription",
|
|
3
|
-
"version": "2.1.1
|
|
3
|
+
"version": "2.1.1",
|
|
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",
|
|
@@ -74,21 +74,21 @@
|
|
|
74
74
|
},
|
|
75
75
|
"peerDependencies": {
|
|
76
76
|
"@deepseek-ai/cordis": "4.0.1 || 4.0.2",
|
|
77
|
-
"@deepseek-ai/dsh-api-remotes": "0.1.2-rc.1 || 0.1.5-
|
|
78
|
-
"@deepseek-ai/dsh-client-connection": "0.1.2-rc.1 || 0.1.5-
|
|
79
|
-
"@deepseek-ai/dsh-client-locale": "0.1.2-rc.1 || 0.1.5-
|
|
80
|
-
"@deepseek-ai/dsh-client-ui-conversation": "0.1.2-rc.1 || 0.1.5-
|
|
81
|
-
"@deepseek-ai/dsh-client-ui-model-selection": "0.1.2-rc.1 || 0.1.5-
|
|
82
|
-
"@deepseek-ai/dsh-client-ui-primitives": "0.1.2-rc.1 || 0.1.5-
|
|
83
|
-
"@deepseek-ai/dsh-client-ui-settings": "0.1.2-rc.1 || 0.1.5-
|
|
84
|
-
"@deepseek-ai/dsh-client-ui-slots": "0.1.2-rc.1 || 0.1.5-
|
|
85
|
-
"@deepseek-ai/dsh-client-ui-tool": "0.1.2-rc.1 || 0.1.5-
|
|
86
|
-
"@deepseek-ai/dsh-credentials": "0.1.2-rc.1 || 0.1.5-
|
|
87
|
-
"@deepseek-ai/dsh-llm": "0.1.2-rc.1 || 0.1.5-
|
|
88
|
-
"@deepseek-ai/dsh-llm-pi-ai": "0.1.2-rc.1 || 0.1.5-
|
|
89
|
-
"@deepseek-ai/dsh-settings": "0.1.2-rc.1 || 0.1.5-
|
|
90
|
-
"@deepseek-ai/dsh-tools": "0.1.2-rc.1 || 0.1.5-
|
|
91
|
-
"@deepseek-ai/dsh-web": "0.1.2-rc.1 || 0.1.5-
|
|
77
|
+
"@deepseek-ai/dsh-api-remotes": "0.1.2-rc.1 || 0.1.5-alpha.1 || 0.1.5-alpha.2 || 0.1.5-rc.1 || 0.1.6-alpha.1",
|
|
78
|
+
"@deepseek-ai/dsh-client-connection": "0.1.2-rc.1 || 0.1.5-alpha.1 || 0.1.5-alpha.2 || 0.1.5-rc.1 || 0.1.6-alpha.1",
|
|
79
|
+
"@deepseek-ai/dsh-client-locale": "0.1.2-rc.1 || 0.1.5-alpha.1 || 0.1.5-alpha.2 || 0.1.5-rc.1 || 0.1.6-alpha.1",
|
|
80
|
+
"@deepseek-ai/dsh-client-ui-conversation": "0.1.2-rc.1 || 0.1.5-alpha.1 || 0.1.5-alpha.2 || 0.1.5-rc.1 || 0.1.6-alpha.1",
|
|
81
|
+
"@deepseek-ai/dsh-client-ui-model-selection": "0.1.2-rc.1 || 0.1.5-alpha.1 || 0.1.5-alpha.2 || 0.1.5-rc.1 || 0.1.6-alpha.1",
|
|
82
|
+
"@deepseek-ai/dsh-client-ui-primitives": "0.1.2-rc.1 || 0.1.5-alpha.1 || 0.1.5-alpha.2 || 0.1.5-rc.1 || 0.1.6-alpha.1",
|
|
83
|
+
"@deepseek-ai/dsh-client-ui-settings": "0.1.2-rc.1 || 0.1.5-alpha.1 || 0.1.5-alpha.2 || 0.1.5-rc.1 || 0.1.6-alpha.1",
|
|
84
|
+
"@deepseek-ai/dsh-client-ui-slots": "0.1.2-rc.1 || 0.1.5-alpha.1 || 0.1.5-alpha.2 || 0.1.5-rc.1 || 0.1.6-alpha.1",
|
|
85
|
+
"@deepseek-ai/dsh-client-ui-tool": "0.1.2-rc.1 || 0.1.5-alpha.1 || 0.1.5-alpha.2 || 0.1.5-rc.1 || 0.1.6-alpha.1",
|
|
86
|
+
"@deepseek-ai/dsh-credentials": "0.1.2-rc.1 || 0.1.5-alpha.1 || 0.1.5-alpha.2 || 0.1.5-rc.1 || 0.1.6-alpha.1",
|
|
87
|
+
"@deepseek-ai/dsh-llm": "0.1.2-rc.1 || 0.1.5-alpha.1 || 0.1.5-alpha.2 || 0.1.5-rc.1 || 0.1.6-alpha.1",
|
|
88
|
+
"@deepseek-ai/dsh-llm-pi-ai": "0.1.2-rc.1 || 0.1.5-alpha.1 || 0.1.5-alpha.2 || 0.1.5-rc.1 || 0.1.6-alpha.1",
|
|
89
|
+
"@deepseek-ai/dsh-settings": "0.1.2-rc.1 || 0.1.5-alpha.1 || 0.1.5-alpha.2 || 0.1.5-rc.1 || 0.1.6-alpha.1",
|
|
90
|
+
"@deepseek-ai/dsh-tools": "0.1.2-rc.1 || 0.1.5-alpha.1 || 0.1.5-alpha.2 || 0.1.5-rc.1 || 0.1.6-alpha.1",
|
|
91
|
+
"@deepseek-ai/dsh-web": "0.1.2-rc.1 || 0.1.5-alpha.1 || 0.1.5-alpha.2 || 0.1.5-rc.1 || 0.1.6-alpha.1",
|
|
92
92
|
"@deepseek-ai/schemastery": "3.18.1 || ^3.18.2",
|
|
93
93
|
"@earendil-works/pi-ai": "0.82.1 || 0.85.1",
|
|
94
94
|
"react": "^18.2.0",
|