@eddyskywalker/dsh-chatgpt-subscription 0.1.6 → 0.1.7

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/CHANGELOG.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.1.7 - 2026-08-17
4
+
5
+ - 临时兼容 DSH `0.1.0-rc.6` 持久化 Bash 提示符不匹配(70倍命令提速):修补 PTY 会话在 `tool-bash-persistent` 设置 `__DSH_PERSISTENT_BASH_PROMPT__ ` 时的就绪判定,避免因底层硬编码 `dsh> ` 及 6 字符截断导致回退到 3.5 秒静默超时。代码统一标记为 `DSH_COMPAT_REMOVE(persistent-bash-prompt-mismatch)`,待 DSH 原生修复后可整体移除。
6
+
3
7
  ## 0.1.6 - 2026-08-17
4
8
 
5
9
  - 临时兼容 DSH `0.1.0-rc.6` 的子代理报告去重:当 `subagent-settled` 已携带与同一子代理排队 `subagent-report` 完全相同的最终内容时,删除重复报告,保留 settlement 通知;部分报告、不同内容和不同子代理不受影响。代码统一标记为 `DSH_COMPAT_REMOVE(subagent-report-settlement-dedup)`,待 DSH 原生修复后可整体移除。
package/README.md CHANGED
@@ -32,7 +32,8 @@
32
32
  - 原样转发 DSH 暴露的工具 schema;命令工具兼容 `pwsh` / `powershell`、`bash`、`sh` 与 `shell`,并按 PowerShell、Bash 或 POSIX sh 注入对应说明;
33
33
  - 429/5xx 由 DSH retry policy 接管;401 只强制刷新并重试一次,支持 `AbortSignal`;
34
34
  - Codex 与 Code review 多窗口额度,60 秒缓存、15 秒上游节流并遵守 `Retry-After`;
35
- - 临时兼容 DSH `0.1.0-rc.6` 的子代理最终报告去重:若 settlement 已向父 Agent 提供同一子代理、完全相同的最终内容,则删除仍在 inbox 中的重复 report;部分报告、不同内容和不同子代理不受影响。兼容代码以 `DSH_COMPAT_REMOVE(subagent-report-settlement-dedup)` 集中标记,待 DSH 原生修复后删除。
35
+ - 临时兼容 DSH `0.1.0-rc.6` 的子代理最终报告去重:若 settlement 已向父 Agent 提供同一子代理、完全相同的最终内容,则删除仍在 inbox 中的重复 report;部分报告、不同内容和不同子代理不受影响。兼容代码以 `DSH_COMPAT_REMOVE(subagent-report-settlement-dedup)` 集中标记,待 DSH 原生修复后删除;
36
+ - 临时兼容 DSH `0.1.0-rc.6` 持久化 Bash 提示符不匹配导致的命令执行延迟(70倍提速):上层 `tool-bash-persistent` 设置的 `__DSH_PERSISTENT_BASH_PROMPT__ ` 与底层 `terminal-bash` 期待的 `dsh> ` 提示符不一致导致无法命中 50ms 快速通道,本插件动态增强就绪检测以识别两类提示符,避免回退到 3.5s 静默超时。兼容代码以 `DSH_COMPAT_REMOVE(persistent-bash-prompt-mismatch)` 集中标记,待 DSH 原生修复后删除。
36
37
 
37
38
  **设置页**
38
39
 
@@ -161,3 +162,4 @@ npm pack --dry-run
161
162
  | Linux 凭据存储不可用 | 确认凭据属于当前用户且权限为 `0600`,父目录权限为 `0700`;修复权限或注销后重新登录 |
162
163
  | Linux 上工具调用语法错误 | 确认 DSH 暴露的是 `bash`、`sh` 或 `shell`,并使用相应的 Bash/POSIX 语法与 `/` 路径 |
163
164
  | 父 Agent 已收到子代理结果,但相同报告仍显示为排队消息 | 本插件为 DSH `0.1.0-rc.6` 提供临时 report/settlement 精确去重;升级或重载插件并新建会话后验证。若未来 DSH 已原生修复,可移除所有 `DSH_COMPAT_REMOVE(subagent-report-settlement-dedup)` 标记代码 |
165
+ | Bash/Linux 命令执行卡顿 3.5 秒以上 | DSH `0.1.0-rc.6` 中 persistent prompt 命名不匹配,本插件已内置热修复兼容;若未来 DSH 修复可移除所有 `DSH_COMPAT_REMOVE(persistent-bash-prompt-mismatch)` 标记代码 |
package/lib/index.js CHANGED
@@ -259,6 +259,125 @@ function installSubagentReportDedupCompat(ctx) {
259
259
  };
260
260
  }
261
261
  //#endregion
262
+ //#region src/host/bash-prompt-scheduling-compat.ts
263
+ /**
264
+ * DSH_COMPAT_REMOVE(persistent-bash-prompt-mismatch)
265
+ *
266
+ * Temporary compatibility shim for DSH 0.1.0-rc.6. The persistent bash tool
267
+ * (`@deepseek-ai/dsh-tool-bash-persistent`) configures the bash shell PS1 to
268
+ * `__DSH_PERSISTENT_BASH_PROMPT__ `, while the underlying PTY backend
269
+ * (`@deepseek-ai/dsh-terminal-bash`) only checks for a hardcoded `dsh> `
270
+ * prompt with a 6-character truncation limit.
271
+ *
272
+ * When the prompt does not match, `promptTextSeen` remains false and the PTY
273
+ * session falls back to the 3.5s idle silence timeout (`idleSilenceMs: 3000ms`
274
+ * + `handoffGraceMs: 500ms`) on every command execution.
275
+ *
276
+ * This compatibility module patches the PTY session `onData` handler so that
277
+ * both `dsh> ` and `__DSH_PERSISTENT_BASH_PROMPT__ ` (and its trimmed variants)
278
+ * satisfy `promptTextSeen`, restoring instant 50ms readiness settling.
279
+ *
280
+ * Remove this module, its installation in `src/index.ts`, and its focused test
281
+ * once upstream aligns `CONTROLLED_PROMPT` with persistent bash tools.
282
+ */
283
+ const DSH_BASH_PROMPT_COMPAT_MARKER = "__dshChatgptSubscriptionBashPromptCompatV1";
284
+ const KNOWN_CONTROLLED_PROMPTS = [
285
+ "dsh> ",
286
+ "dsh>",
287
+ "__DSH_PERSISTENT_BASH_PROMPT__ ",
288
+ "__DSH_PERSISTENT_BASH_PROMPT__"
289
+ ];
290
+ const MAX_PROMPT_BUFFER_LENGTH = 64;
291
+ function isKnownControlledPrompt(tail) {
292
+ if (!tail) return false;
293
+ const cleaned = tail.replaceAll(/[\x00-\x1f\x7f]/g, "").trim();
294
+ for (const known of KNOWN_CONTROLLED_PROMPTS) if (cleaned === known.replaceAll(/[\x00-\x1f\x7f]/g, "").trim()) return true;
295
+ return false;
296
+ }
297
+ function patchSessionOnData(target) {
298
+ const obj = target.prototype ?? target;
299
+ if (!obj || typeof obj.onData !== "function") return () => {};
300
+ const existing = obj.onData[DSH_BASH_PROMPT_COMPAT_MARKER];
301
+ if (existing) {
302
+ existing.owners += 1;
303
+ return () => {
304
+ existing.owners -= 1;
305
+ if (existing.owners <= 0 && obj.onData["__dshChatgptSubscriptionBashPromptCompatV1"] === existing) obj.onData = existing.originalOnData;
306
+ };
307
+ }
308
+ const originalOnData = obj.onData;
309
+ const record = {
310
+ originalOnData,
311
+ owners: 1
312
+ };
313
+ function wrapper(data) {
314
+ const sanitized = this.sanitizer.push(data);
315
+ this.appendOutput(sanitized.text);
316
+ if (sanitized.prompt) {
317
+ this.promptSeen = true;
318
+ this.promptTail = "";
319
+ this.lastOutputAt = Date.now();
320
+ }
321
+ if (this.promptSeen && sanitized.promptTail !== void 0) {
322
+ const remaining = Math.max(0, MAX_PROMPT_BUFFER_LENGTH - this.promptTail.length);
323
+ this.promptTail += sanitized.promptTail.slice(0, remaining);
324
+ if (sanitized.promptTail.length > remaining) this.promptTail = `${this.promptTail}\0`;
325
+ this.promptTextSeen = isKnownControlledPrompt(this.promptTail);
326
+ }
327
+ }
328
+ Object.defineProperty(wrapper, DSH_BASH_PROMPT_COMPAT_MARKER, { value: record });
329
+ obj.onData = wrapper;
330
+ return () => {
331
+ record.owners -= 1;
332
+ if (record.owners <= 0 && obj.onData === wrapper) obj.onData = originalOnData;
333
+ };
334
+ }
335
+ /**
336
+ * Installs the persistent bash prompt compatibility patch onto registered and
337
+ * future PTY backends.
338
+ */
339
+ function installBashPromptCompat(ctx) {
340
+ const disposers = [];
341
+ const patchBackend = (backend) => {
342
+ if (!backend) return;
343
+ if (typeof backend.createSession === "function") {
344
+ const originalCreate = backend.createSession;
345
+ backend.createSession = function(terminal, config) {
346
+ const session = originalCreate.call(this, terminal, config);
347
+ if (session) patchSessionOnData(session);
348
+ return session;
349
+ };
350
+ disposers.push(() => {
351
+ if (backend.createSession) backend.createSession = originalCreate;
352
+ });
353
+ }
354
+ };
355
+ const terminals = ctx.terminals;
356
+ if (terminals?.backends) {
357
+ for (const backend of terminals.backends.values()) patchBackend(backend);
358
+ if (typeof terminals.registerBackend === "function") {
359
+ const originalRegister = terminals.registerBackend;
360
+ terminals.registerBackend = function(backend) {
361
+ patchBackend(backend);
362
+ return originalRegister.call(this, backend);
363
+ };
364
+ disposers.push(() => {
365
+ if (terminals.registerBackend) terminals.registerBackend = originalRegister;
366
+ });
367
+ }
368
+ }
369
+ return () => {
370
+ while (disposers.length > 0) {
371
+ const dispose = disposers.pop();
372
+ try {
373
+ dispose?.();
374
+ } catch (error) {
375
+ ctx.logger.warn("[dsh-chatgpt-subscription] Could not remove bash prompt compatibility: " + (error instanceof Error ? error.message : String(error)));
376
+ }
377
+ }
378
+ };
379
+ }
380
+ //#endregion
262
381
  //#region src/compat.ts
263
382
  /**
264
383
  * Compatibility constants for the ChatGPT-backed Codex flow. The backend and
@@ -2208,7 +2327,9 @@ function apply(ctx) {
2208
2327
  const disposeRoutes = registerRoutes(ctx, oauth, usage);
2209
2328
  const disposeAdapter = ctx.llm.registerAdapter([PROVIDER_ID], adapter);
2210
2329
  const disposeSubagentReportCompat = installSubagentReportDedupCompat(ctx);
2330
+ const disposeBashPromptCompat = installBashPromptCompat(ctx);
2211
2331
  return () => {
2332
+ disposeBashPromptCompat();
2212
2333
  disposeSubagentReportCompat();
2213
2334
  disposeAdapter();
2214
2335
  disposeRoutes();
@@ -0,0 +1,51 @@
1
+ import type { Context } from '@deepseek-ai/cordis';
2
+ /**
3
+ * DSH_COMPAT_REMOVE(persistent-bash-prompt-mismatch)
4
+ *
5
+ * Temporary compatibility shim for DSH 0.1.0-rc.6. The persistent bash tool
6
+ * (`@deepseek-ai/dsh-tool-bash-persistent`) configures the bash shell PS1 to
7
+ * `__DSH_PERSISTENT_BASH_PROMPT__ `, while the underlying PTY backend
8
+ * (`@deepseek-ai/dsh-terminal-bash`) only checks for a hardcoded `dsh> `
9
+ * prompt with a 6-character truncation limit.
10
+ *
11
+ * When the prompt does not match, `promptTextSeen` remains false and the PTY
12
+ * session falls back to the 3.5s idle silence timeout (`idleSilenceMs: 3000ms`
13
+ * + `handoffGraceMs: 500ms`) on every command execution.
14
+ *
15
+ * This compatibility module patches the PTY session `onData` handler so that
16
+ * both `dsh> ` and `__DSH_PERSISTENT_BASH_PROMPT__ ` (and its trimmed variants)
17
+ * satisfy `promptTextSeen`, restoring instant 50ms readiness settling.
18
+ *
19
+ * Remove this module, its installation in `src/index.ts`, and its focused test
20
+ * once upstream aligns `CONTROLLED_PROMPT` with persistent bash tools.
21
+ */
22
+ export declare const DSH_BASH_PROMPT_COMPAT_MARKER: "__dshChatgptSubscriptionBashPromptCompatV1";
23
+ export declare const KNOWN_CONTROLLED_PROMPTS: readonly ["dsh> ", "dsh>", "__DSH_PERSISTENT_BASH_PROMPT__ ", "__DSH_PERSISTENT_BASH_PROMPT__"];
24
+ export declare function isKnownControlledPrompt(tail: string): boolean;
25
+ interface SanitizerResult {
26
+ text: string;
27
+ prompt?: boolean;
28
+ promptTail?: string;
29
+ }
30
+ interface SanitizerLike {
31
+ push(data: string): SanitizerResult;
32
+ }
33
+ export interface PtySessionLike {
34
+ sanitizer: SanitizerLike;
35
+ promptSeen: boolean;
36
+ promptTextSeen: boolean;
37
+ promptTail: string;
38
+ lastOutputAt: number;
39
+ appendOutput(text: string): void;
40
+ onData(data: string): void;
41
+ }
42
+ export declare function patchSessionOnData(target: {
43
+ prototype?: PtySessionLike;
44
+ } | PtySessionLike): () => void;
45
+ /**
46
+ * Installs the persistent bash prompt compatibility patch onto registered and
47
+ * future PTY backends.
48
+ */
49
+ export declare function installBashPromptCompat(ctx: Context): () => void;
50
+ export {};
51
+ //# sourceMappingURL=bash-prompt-scheduling-compat.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bash-prompt-scheduling-compat.d.ts","sourceRoot":"","sources":["../../../src/host/bash-prompt-scheduling-compat.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAElD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,6BAA6B,EACxC,4CAAqD,CAAA;AAEvD,eAAO,MAAM,wBAAwB,iGAK3B,CAAA;AAIV,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAQ7D;AAED,UAAU,eAAe;IACvB,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB;AAED,UAAU,aAAa;IACrB,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,CAAA;CACpC;AAED,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,aAAa,CAAA;IACxB,UAAU,EAAE,OAAO,CAAA;IACnB,cAAc,EAAE,OAAO,CAAA;IACvB,UAAU,EAAE,MAAM,CAAA;IAClB,YAAY,EAAE,MAAM,CAAA;IACpB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;IAChC,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;CAC3B;AAWD,wBAAgB,kBAAkB,CAAC,MAAM,EAAE;IAAE,SAAS,CAAC,EAAE,cAAc,CAAA;CAAE,GAAG,cAAc,GAAG,MAAM,IAAI,CAkDtG;AAaD;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,IAAI,CAwDhE"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAalD,eAAO,MAAM,MAAM,UAAgD,CAAA;AAEnE,wBAAgB,KAAK,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI,CAqBxC;AAED,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAA;AACtD,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAA;AACvD,OAAO,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAA;AAClF,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAA;AACrE,OAAO,EAAE,wBAAwB,EAAE,MAAM,gCAAgC,CAAA;AACzE,OAAO,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAA;AACjE,OAAO,EAAE,sBAAsB,EAAE,MAAM,+BAA+B,CAAA;AACtE,YAAY,EAAE,UAAU,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAclD,eAAO,MAAM,MAAM,UAAgD,CAAA;AAEnE,wBAAgB,KAAK,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI,CAwBxC;AAED,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAA;AACtD,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAA;AACvD,OAAO,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAA;AAClF,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAA;AACrE,OAAO,EAAE,wBAAwB,EAAE,MAAM,gCAAgC,CAAA;AACzE,OAAO,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAA;AACjE,OAAO,EAAE,sBAAsB,EAAE,MAAM,+BAA+B,CAAA;AACtE,YAAY,EAAE,UAAU,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eddyskywalker/dsh-chatgpt-subscription",
3
- "version": "0.1.6",
3
+ "version": "0.1.7",
4
4
  "description": "DSH provider plugin for Codex access through a ChatGPT subscription.",
5
5
  "author": {
6
6
  "name": "eddyskywalker",