dsh-codex-subscription 3.0.0-beta.2 → 3.0.0-beta.3
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 +3 -2
- package/README.md +3 -2
- package/lib/client.js +1 -1
- package/lib/index.js +86 -3
- package/package.json +1 -1
package/README.en.md
CHANGED
|
@@ -80,7 +80,7 @@ Subscription access, model controls, quota management, and image creation in one
|
|
|
80
80
|
|
|
81
81
|
| Feature | What you can do | Availability / setup |
|
|
82
82
|
| --- | --- | --- |
|
|
83
|
-
| **Phone remote control** | Drive the DSH on your computer from the Codex section of the ChatGPT mobile app: start, continue and archive conversations, switch model and permissions, answer approvals and questions; DeepSeek and any other DSH model work | Beta (3.0.0-beta.
|
|
83
|
+
| **Phone remote control** | Drive the DSH on your computer from the Codex section of the ChatGPT mobile app: start, continue and archive conversations, switch model and permissions, answer approvals and questions; DeepSeek and any other DSH model work | Beta (3.0.0-beta.3); off by default; Settings → Codex → Models & runtime → Phone remote control, pair by QR or manual code |
|
|
84
84
|
| **Codex independent subtasks** | Reuse subscription sign-in and workspace permissions; select allowed models and reasoning levels | Beta; DSH by default, Codex requires the optional component and model-selection setup |
|
|
85
85
|
| **Subtask component management** | Install, disable, or uninstall the official Codex subtask component from settings | Managed by supported DSH hosts; no extra login |
|
|
86
86
|
| **Cloud context compaction** | Continue long conversations using Codex compaction while retaining DSH history and native compaction | Beta / experimental; off by default, enabled requests use SSE |
|
|
@@ -161,9 +161,10 @@ Turn on **Settings → Codex → Models & runtime → Phone remote control** and
|
|
|
161
161
|
- browse, start, continue, interrupt and archive DSH conversations from the phone, with DeepSeek, Codex or any other DSH model;
|
|
162
162
|
- switch model, reasoning level and permissions (workspace write / full access) from the phone;
|
|
163
163
|
- when DSH needs a tool approval or asks you a question, it pops up on the phone; if the phone dropped, it is asked again when you return, otherwise the computer handles it;
|
|
164
|
+
- replies appear on the phone as they are written;
|
|
164
165
|
- model errors are shown on the phone.
|
|
165
166
|
|
|
166
|
-
Off by default. The computer must stay on, online and running DSH. This uses a ChatGPT capability OpenAI has not opened to third parties and may change at any time, hence Beta. Currently available in the pre-release `dsh-codex-subscription@3.0.0-beta.
|
|
167
|
+
Off by default. The computer must stay on, online and running DSH. This uses a ChatGPT capability OpenAI has not opened to third parties and may change at any time, hence Beta. Currently available in the pre-release `dsh-codex-subscription@3.0.0-beta.3`.
|
|
167
168
|
|
|
168
169
|
<p align="center"><img src="docs/assets/remote-control-en.png" width="560" alt="Official desktop app settings: phone remote control connected, showing a pairing QR code and manual code"></p>
|
|
169
170
|
|
package/README.md
CHANGED
|
@@ -80,7 +80,7 @@
|
|
|
80
80
|
|
|
81
81
|
| 功能 | 你可以做什么 | 使用方式 / 条件 |
|
|
82
82
|
| --- | --- | --- |
|
|
83
|
-
| **手机远程控制** | 在 ChatGPT 手机 App 的 Codex 里直接指挥电脑上的 DSH:新建、续聊、归档对话,切换模型和权限,回答审批和提问,DeepSeek 等任意 DSH 模型都能用 | Beta(3.0.0-beta.
|
|
83
|
+
| **手机远程控制** | 在 ChatGPT 手机 App 的 Codex 里直接指挥电脑上的 DSH:新建、续聊、归档对话,切换模型和权限,回答审批和提问,DeepSeek 等任意 DSH 模型都能用 | Beta(3.0.0-beta.3);默认关闭,设置 → Codex 订阅 → 模型与运行 → 手机远程控制,扫码或输入手动码配对 |
|
|
84
84
|
| **Codex 独立子任务** | 复用订阅登录和工作区权限执行独立任务,可指定允许的模型与推理档位 | Beta;默认 DSH,Codex 需安装可选组件并配置模型选择 |
|
|
85
85
|
| **子任务组件管理** | 在设置里安装、停用或卸载官方 Codex 子任务组件 | 由支持的 DSH 宿主管理,无需额外登录 |
|
|
86
86
|
| **云端上下文压缩** | 使用 Codex 云端压缩继续长对话,同时保留 DSH 历史与原生压缩 | Beta / 实验性;默认关闭,开启的请求使用 SSE |
|
|
@@ -161,9 +161,10 @@ dsh --profile headless "只回复:ok"
|
|
|
161
161
|
- 在手机上查看、新建、续聊、中断和归档 DSH 对话,DeepSeek、Codex 以及其他 DSH 模型都能用;
|
|
162
162
|
- 在手机上切换模型、推理档位和权限(工作区内修改 / 完全访问);
|
|
163
163
|
- DSH 需要批准工具调用或向你提问时,手机会直接弹出;手机掉线会在重新打开时再弹一次,否则交回电脑处理;
|
|
164
|
+
- 回复边生成边显示在手机上;
|
|
164
165
|
- 模型报错会显示在手机上。
|
|
165
166
|
|
|
166
|
-
默认关闭。电脑需要保持开机、联网并打开 DSH。这是 OpenAI 尚未向第三方开放的 ChatGPT 能力,随时可能变化,所以标为 Beta。目前在预发布版中提供:`dsh-codex-subscription@3.0.0-beta.
|
|
167
|
+
默认关闭。电脑需要保持开机、联网并打开 DSH。这是 OpenAI 尚未向第三方开放的 ChatGPT 能力,随时可能变化,所以标为 Beta。目前在预发布版中提供:`dsh-codex-subscription@3.0.0-beta.3`。
|
|
167
168
|
|
|
168
169
|
<p align="center"><img src="docs/assets/remote-control.png" width="560" alt="官方桌面版设置页:手机远程控制已连接,显示配对二维码和手动码"></p>
|
|
169
170
|
|
package/lib/client.js
CHANGED
|
@@ -9082,7 +9082,7 @@ window.__ModuleLoader__.load({
|
|
|
9082
9082
|
}
|
|
9083
9083
|
//#endregion
|
|
9084
9084
|
//#region src/version.js
|
|
9085
|
-
const PACKAGE_VERSION = "3.0.0-beta.
|
|
9085
|
+
const PACKAGE_VERSION = "3.0.0-beta.3";
|
|
9086
9086
|
//#endregion
|
|
9087
9087
|
//#region src/client-recovery.js
|
|
9088
9088
|
async function recoveryCall(rpc, endpoint, payload = {}, timeoutMs = 1e4) {
|
package/lib/index.js
CHANGED
|
@@ -2062,7 +2062,7 @@ function inheritedOriginalImageRef(session, assetId) {
|
|
|
2062
2062
|
}
|
|
2063
2063
|
//#endregion
|
|
2064
2064
|
//#region src/version.js
|
|
2065
|
-
const PACKAGE_VERSION = "3.0.0-beta.
|
|
2065
|
+
const PACKAGE_VERSION = "3.0.0-beta.3";
|
|
2066
2066
|
const USER_AGENT = `dsh-codex-subscription/${PACKAGE_VERSION}`;
|
|
2067
2067
|
//#endregion
|
|
2068
2068
|
//#region src/codex-images.js
|
|
@@ -2235,7 +2235,7 @@ async function readSessionImage(attachmentId, attachments, signal, messages) {
|
|
|
2235
2235
|
};
|
|
2236
2236
|
}
|
|
2237
2237
|
async function editImages(values, attachments, signal, messages) {
|
|
2238
|
-
if (!Array.isArray(values) || values.length === 0 || values.length > MAX_REFERENCE_IMAGES) throw new Error(`referenceImages must contain between 1 and ${MAX_REFERENCE_IMAGES} images`);
|
|
2238
|
+
if (!Array.isArray(values) || values.length === 0 || values.length > MAX_REFERENCE_IMAGES) throw new Error(`referenceImages must contain between 1 and ${MAX_REFERENCE_IMAGES} images; omit it to generate a new image`);
|
|
2239
2239
|
const available = messages === void 0 ? void 0 : sessionImageReferences(messages);
|
|
2240
2240
|
const references = values.map((value) => {
|
|
2241
2241
|
const id = normalizeAttachmentId(value?.attachmentId);
|
|
@@ -2481,6 +2481,10 @@ function createCodexImageTool(options) {
|
|
|
2481
2481
|
timeoutMs: 300 * 1e3,
|
|
2482
2482
|
isConcurrencySafe: () => false,
|
|
2483
2483
|
async execute(args, exec) {
|
|
2484
|
+
if (Array.isArray(args.referenceImages) && args.referenceImages.length === 0) {
|
|
2485
|
+
const { referenceImages: _empty, ...rest } = args;
|
|
2486
|
+
args = rest;
|
|
2487
|
+
}
|
|
2484
2488
|
assertImageOperation(options.getFeatures?.(), args.referenceImages !== void 0);
|
|
2485
2489
|
const defaults = readImageDefaults(options.getFeatures?.());
|
|
2486
2490
|
args = {
|
|
@@ -4164,6 +4168,61 @@ function createDshRemoteControl({ controller, agents, permissions = () => void 0
|
|
|
4164
4168
|
return decision === "accept" || decision === "acceptForSession" ? "allowed-once" : decision === "cancel" ? "cancelled" : "rejected";
|
|
4165
4169
|
}, () => next());
|
|
4166
4170
|
};
|
|
4171
|
+
const streams = /* @__PURE__ */ new Map();
|
|
4172
|
+
const onStream = (session, frame) => {
|
|
4173
|
+
const running = session ? active.get(session.id) : void 0;
|
|
4174
|
+
if (!running || !subscribers.has(session.id)) return;
|
|
4175
|
+
const id = session.id;
|
|
4176
|
+
if (frame.type === "start") {
|
|
4177
|
+
streams.delete(id);
|
|
4178
|
+
return;
|
|
4179
|
+
}
|
|
4180
|
+
if (frame.type === "end") {
|
|
4181
|
+
const stream = streams.get(id);
|
|
4182
|
+
if (stream && frame.outcome?.eventType !== "assistant/message") {
|
|
4183
|
+
streams.delete(id);
|
|
4184
|
+
stream.item.text = stream.text;
|
|
4185
|
+
emit(id, "item/completed", {
|
|
4186
|
+
threadId: id,
|
|
4187
|
+
turnId: running.turn.id,
|
|
4188
|
+
item: stream.item,
|
|
4189
|
+
completedAtMs: Date.now()
|
|
4190
|
+
});
|
|
4191
|
+
}
|
|
4192
|
+
return;
|
|
4193
|
+
}
|
|
4194
|
+
const chunk = frame.chunk;
|
|
4195
|
+
if (chunk?.type !== "text-delta" || typeof chunk.text !== "string" || chunk.text === "") return;
|
|
4196
|
+
let stream = streams.get(id);
|
|
4197
|
+
if (!stream) {
|
|
4198
|
+
stream = {
|
|
4199
|
+
item: {
|
|
4200
|
+
type: "agentMessage",
|
|
4201
|
+
id: randomUUID(),
|
|
4202
|
+
text: "",
|
|
4203
|
+
phase: null,
|
|
4204
|
+
memoryCitation: null,
|
|
4205
|
+
delivery: null
|
|
4206
|
+
},
|
|
4207
|
+
text: ""
|
|
4208
|
+
};
|
|
4209
|
+
streams.set(id, stream);
|
|
4210
|
+
running.turn.items.push(stream.item);
|
|
4211
|
+
emit(id, "item/started", {
|
|
4212
|
+
threadId: id,
|
|
4213
|
+
turnId: running.turn.id,
|
|
4214
|
+
item: stream.item,
|
|
4215
|
+
startedAtMs: Date.now()
|
|
4216
|
+
});
|
|
4217
|
+
}
|
|
4218
|
+
stream.text += chunk.text;
|
|
4219
|
+
emit(id, "item/agentMessage/delta", {
|
|
4220
|
+
threadId: id,
|
|
4221
|
+
turnId: running.turn.id,
|
|
4222
|
+
itemId: stream.item.id,
|
|
4223
|
+
delta: chunk.text
|
|
4224
|
+
});
|
|
4225
|
+
};
|
|
4167
4226
|
/** Forward committed assistant and tool events of a phone-started turn as items. */
|
|
4168
4227
|
const onSessionEvent = (session, event) => {
|
|
4169
4228
|
const running = active.get(session.id);
|
|
@@ -4196,9 +4255,27 @@ function createDshRemoteControl({ controller, agents, permissions = () => void 0
|
|
|
4196
4255
|
const items = projectTurns([{
|
|
4197
4256
|
role: "user",
|
|
4198
4257
|
id: "x",
|
|
4199
|
-
content: [
|
|
4258
|
+
content: [{
|
|
4259
|
+
type: "text",
|
|
4260
|
+
text: "x"
|
|
4261
|
+
}]
|
|
4200
4262
|
}, message]).flatMap((turn) => turn.items.slice(1));
|
|
4263
|
+
const stream = streams.get(session.id);
|
|
4264
|
+
streams.delete(session.id);
|
|
4265
|
+
let reuse = stream?.item;
|
|
4201
4266
|
for (const item of items) {
|
|
4267
|
+
if (reuse && item.type === "agentMessage") {
|
|
4268
|
+
const shown = reuse;
|
|
4269
|
+
reuse = void 0;
|
|
4270
|
+
shown.text = item.text;
|
|
4271
|
+
emit(session.id, "item/completed", {
|
|
4272
|
+
threadId: session.id,
|
|
4273
|
+
turnId: running.turn.id,
|
|
4274
|
+
item: shown,
|
|
4275
|
+
completedAtMs: Date.now()
|
|
4276
|
+
});
|
|
4277
|
+
continue;
|
|
4278
|
+
}
|
|
4202
4279
|
running.turn.items.push(item);
|
|
4203
4280
|
emit(session.id, "item/started", {
|
|
4204
4281
|
threadId: session.id,
|
|
@@ -4217,6 +4294,7 @@ function createDshRemoteControl({ controller, agents, permissions = () => void 0
|
|
|
4217
4294
|
return {
|
|
4218
4295
|
methods,
|
|
4219
4296
|
onSessionEvent,
|
|
4297
|
+
onStream,
|
|
4220
4298
|
onApproval,
|
|
4221
4299
|
onQuestion,
|
|
4222
4300
|
forget: (notify) => {
|
|
@@ -8191,6 +8269,11 @@ function apply(ctx, config = {}) {
|
|
|
8191
8269
|
methods: remoteBridge.methods,
|
|
8192
8270
|
onClose: (_client, notify) => remoteBridge.forget(notify)
|
|
8193
8271
|
});
|
|
8272
|
+
ctx.on("agent/assistant-stream", ({ agent, frame }) => {
|
|
8273
|
+
try {
|
|
8274
|
+
remoteBridge.onStream(agent?.session, frame);
|
|
8275
|
+
} catch {}
|
|
8276
|
+
});
|
|
8194
8277
|
ctx.on("session/event", (session, event) => {
|
|
8195
8278
|
try {
|
|
8196
8279
|
remoteBridge.onSessionEvent(session, event);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-codex-subscription",
|
|
3
|
-
"version": "3.0.0-beta.
|
|
3
|
+
"version": "3.0.0-beta.3",
|
|
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",
|