super-dsh 0.3.2-e → 0.3.3-b

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.
@@ -4,7 +4,7 @@ import { LlmAttemptId, ToolCallId, QUOTA_EXCEEDED_CODE, createAssistantMessage,
4
4
  import { createScope } from "@deepseek-ai/dsh-scope";
5
5
  import { ompPermissionCommand } from "./permission.js";
6
6
  import { getBridgeStore } from "./store/index.js";
7
- import { withSystemHead } from "../../superd-hub/dist/index.js";
7
+ import { createAgentModelFace, withSystemHead } from "../../superd-hub/dist/index.js";
8
8
  /**
9
9
  * v2 live assistant-stream publication for the OMP bridge — the same frame
10
10
  * protocol the reference loop's AssistantStreamAttempt speaks (start marker,
@@ -254,6 +254,9 @@ export class OmpAgent {
254
254
  session;
255
255
  inbox;
256
256
  ctx;
257
+ /** Durable model selection (0.2.2 Agent face): the shared hub face over
258
+ * `model/selection` events — see superd-hub agent-model-face.ts. */
259
+ model;
257
260
  #rpc;
258
261
  #loopCtx;
259
262
  #scope;
@@ -304,6 +307,17 @@ export class OmpAgent {
304
307
  this.id = id;
305
308
  this.options = options;
306
309
  this.session = withSystemHead(session, () => createSystemMessage(""));
310
+ this.model = createAgentModelFace({
311
+ session: this.session,
312
+ options: this.options,
313
+ appendSelection: (selection) => {
314
+ this.session.append("model/selection", selection);
315
+ },
316
+ readDefault: () => {
317
+ const service = this.ctx.get("agentDefaultModel");
318
+ return service?.currentSelection?.();
319
+ },
320
+ });
307
321
  this.#rpc = rpc;
308
322
  this.#onIdleExit = onIdleExit;
309
323
  this.#dispatch = agentEvents(loopCtx, this);
@@ -26,14 +26,14 @@
26
26
  "dependencies": {},
27
27
  "peerDependencies": {
28
28
  "@deepseek-ai/cordis": "^4.0.1",
29
- "@deepseek-ai/dsh-agent": ">=0.1.5-0 <0.3.0-0",
30
- "@deepseek-ai/dsh-agent-presets": ">=0.1.5-0 <0.3.0-0",
31
- "@deepseek-ai/dsh-llm": ">=0.1.5-0 <0.3.0-0",
32
- "@deepseek-ai/dsh-scope": ">=0.1.5-0 <0.3.0-0",
33
- "@deepseek-ai/dsh-session": ">=0.1.5-0 <0.3.0-0",
34
- "@deepseek-ai/dsh-session-persistence": ">=0.1.5-0 <0.3.0-0",
35
- "@deepseek-ai/dsh-typert-protocol": ">=0.1.5-0 <0.3.0-0",
36
- "@deepseek-ai/dsh-home-paths": ">=0.1.5-0 <0.3.0-0",
29
+ "@deepseek-ai/dsh-agent": ">=0.2.2-0 <1.0.0-0",
30
+ "@deepseek-ai/dsh-agent-presets": ">=0.2.2-0 <1.0.0-0",
31
+ "@deepseek-ai/dsh-llm": ">=0.2.2-0 <1.0.0-0",
32
+ "@deepseek-ai/dsh-scope": ">=0.2.2-0 <1.0.0-0",
33
+ "@deepseek-ai/dsh-session": ">=0.2.2-0 <1.0.0-0",
34
+ "@deepseek-ai/dsh-session-persistence": ">=0.2.2-0 <1.0.0-0",
35
+ "@deepseek-ai/dsh-typert-protocol": ">=0.2.2-0 <1.0.0-0",
36
+ "@deepseek-ai/dsh-home-paths": ">=0.2.2-0 <1.0.0-0",
37
37
  "@pgmi-builds/superd-hub": "*"
38
38
  },
39
39
  "peerDependenciesMeta": {
@@ -3,7 +3,7 @@ import { randomUUID } from "node:crypto";
3
3
  import { agentEvents } from "@deepseek-ai/dsh-agent";
4
4
  import { Inbox } from "./inbox.js";
5
5
  import { LlmAttemptId, ToolCallId, QUOTA_EXCEEDED_CODE, createAssistantMessage, createSystemMessage, createToolResultMessage, createUserMessage } from "@deepseek-ai/dsh-llm";
6
- import { withSystemHead } from "../../superd-hub/dist/index.js";
6
+ import { createAgentModelFace, recordedModelSelection, withSystemHead } from "../../superd-hub/dist/index.js";
7
7
  import { createScope } from "@deepseek-ai/dsh-scope";
8
8
  import { PI_IDLE_EXIT_MS } from "./knobs.js";
9
9
  import { trace } from "./knobs.js";
@@ -176,6 +176,9 @@ export class PiAgent {
176
176
  session;
177
177
  inbox;
178
178
  ctx;
179
+ /** Durable model selection (0.2.2 Agent face): the shared hub face over
180
+ * `model/selection` events — see superd-hub agent-model-face.ts. */
181
+ model;
179
182
  #client;
180
183
  #loopCtx;
181
184
  #scope;
@@ -237,6 +240,17 @@ export class PiAgent {
237
240
  this.id = id;
238
241
  this.options = options;
239
242
  this.session = withSystemHead(session, () => createSystemMessage(""));
243
+ this.model = createAgentModelFace({
244
+ session: this.session,
245
+ options: this.options,
246
+ appendSelection: (selection) => {
247
+ this.session.append("model/selection", selection);
248
+ },
249
+ readDefault: () => {
250
+ const service = this.ctx.get("agentDefaultModel");
251
+ return service?.currentSelection?.();
252
+ },
253
+ });
240
254
  this.#client = client;
241
255
  this.#onIdleExit = onIdleExit;
242
256
  this.#runtimeInfo = runtimeInfo;
@@ -522,7 +536,11 @@ export class PiAgent {
522
536
  * LIVE (an upgrade over the codex SDK line's next-turn switch).
523
537
  */
524
538
  async #syncModelSelection() {
525
- const persisted = this.session.requestHeader()?.config;
539
+ // 0.2.2: the recorded-selection fold (pending ?? last-used) leads the
540
+ // waterfall, so a `model.select` switch lands on the NEXT turn — the
541
+ // native precedence (pending retires only on a matching request header).
542
+ const recorded = recordedModelSelection(this.session.snapshotEvents());
543
+ const persisted = recorded ?? this.session.requestHeader()?.config;
526
544
  const service = this.ctx.get("agentDefaultModel");
527
545
  const selection = service?.currentSelection();
528
546
  const target = persisted !== undefined && persisted.provider !== "" && persisted.model !== ""
@@ -29,7 +29,6 @@ import { bindForeignHub } from '@pgmi-builds/superd-hub/foreign-hub';
29
29
  import { realpathSync, statSync } from "node:fs";
30
30
  import { join } from "node:path";
31
31
  import { Service } from "@deepseek-ai/cordis";
32
- import { installModelSelection } from "@deepseek-ai/dsh-agent";
33
32
  import { SessionLogOffset, SessionPreparation, interruptedTurnClosers, } from "@deepseek-ai/dsh-session";
34
33
  import { PiSessionClient } from "./pi-client.js";
35
34
  import { PiAgent } from "./agent.js";
@@ -514,16 +513,11 @@ async function setupAndPublish(loopCtx, ownerCtx, id, agentOptions, setup, sessi
514
513
  const route = runtimeInfo?.routeContext(agentOptions);
515
514
  if (route !== undefined) {
516
515
  const selection = { provider: route.provider, model: route.model };
517
- let picked = selection;
518
- installModelSelection(agent.ctx, {
519
- get current() { return picked; },
520
- set current(next) { picked = next; },
521
- assembled: undefined,
522
- });
523
- // `model/selection` is contributed to `SessionEventMap` by the upstream
524
- // session-controller package (declaration merging); this adapter does
525
- // not depend on it, so the append goes through a narrow local cast.
526
- session.append("model/selection", selection);
516
+ // 0.2.2: installModelSelection dropped its injected-ref parameter — the
517
+ // durable face (`agent.model`, the same mechanism session/selectModel
518
+ // uses) carries the pin: select() appends the typed, deduped
519
+ // `model/selection` event.
520
+ agent.model.select(selection);
527
521
  trace(`session route pinned: ${route.provider}/${route.model}`);
528
522
  }
529
523
  }
@@ -27,13 +27,13 @@
27
27
  },
28
28
  "peerDependencies": {
29
29
  "@deepseek-ai/cordis": "^4.0.1",
30
- "@deepseek-ai/dsh-agent": ">=0.1.5-0 <0.3.0-0",
31
- "@deepseek-ai/dsh-agent-presets": ">=0.1.5-0 <0.3.0-0",
32
- "@deepseek-ai/dsh-llm": ">=0.1.5-0 <0.3.0-0",
33
- "@deepseek-ai/dsh-scope": ">=0.1.5-0 <0.3.0-0",
34
- "@deepseek-ai/dsh-session": ">=0.1.5-0 <0.3.0-0",
35
- "@deepseek-ai/dsh-session-persistence": ">=0.1.5-0 <0.3.0-0",
36
- "@deepseek-ai/dsh-typert-protocol": ">=0.1.5-0 <0.3.0-0",
30
+ "@deepseek-ai/dsh-agent": ">=0.2.2-0 <1.0.0-0",
31
+ "@deepseek-ai/dsh-agent-presets": ">=0.2.2-0 <1.0.0-0",
32
+ "@deepseek-ai/dsh-llm": ">=0.2.2-0 <1.0.0-0",
33
+ "@deepseek-ai/dsh-scope": ">=0.2.2-0 <1.0.0-0",
34
+ "@deepseek-ai/dsh-session": ">=0.2.2-0 <1.0.0-0",
35
+ "@deepseek-ai/dsh-session-persistence": ">=0.2.2-0 <1.0.0-0",
36
+ "@deepseek-ai/dsh-typert-protocol": ">=0.2.2-0 <1.0.0-0",
37
37
  "@pgmi-builds/superd-hub": "*"
38
38
  },
39
39
  "peerDependenciesMeta": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "super-dsh",
3
- "version": "0.3.2-e",
3
+ "version": "0.3.3-b",
4
4
  "description": "Super D for the DeepSeek Harness (DSH) — one dsh plugin that mounts the superd hub (runtime selector, roster, per-runtime agents) and joins local foreign-agent runtimes (OMP, Codex, Claude, Pi, Hermes, Antigravity) into the DSH Web UI. Each runtime keeps its native home and session store; the hub only bridges.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -93,26 +93,26 @@
93
93
  },
94
94
  "peerDependencies": {
95
95
  "@deepseek-ai/cordis": "^4.0.1",
96
- "@deepseek-ai/dsh-agent": ">=0.1.5-0 <0.3.0-0",
97
- "@deepseek-ai/dsh-agent-presets": ">=0.1.5-0 <0.3.0-0",
98
- "@deepseek-ai/dsh-api-gateway": ">=0.1.5-0 <0.3.0-0",
99
- "@deepseek-ai/dsh-commands": ">=0.1.5-0 <0.3.0-0",
100
- "@deepseek-ai/dsh-home-paths": ">=0.1.5-0 <0.3.0-0",
101
- "@deepseek-ai/dsh-host-webserver": ">=0.1.5-0 <0.3.0-0",
102
- "@deepseek-ai/dsh-llm": ">=0.1.5-0 <0.3.0-0",
103
- "@deepseek-ai/dsh-scope": ">=0.1.5-0 <0.3.0-0",
104
- "@deepseek-ai/dsh-session": ">=0.1.5-0 <0.3.0-0",
105
- "@deepseek-ai/dsh-session-persistence": ">=0.1.5-0 <0.3.0-0",
106
- "@deepseek-ai/dsh-tools": ">=0.1.5-0 <0.3.0-0",
107
- "@deepseek-ai/dsh-typert-protocol": ">=0.1.5-0 <0.3.0-0",
108
- "@deepseek-ai/dsh-user-approval": ">=0.1.5-0 <0.3.0-0",
109
- "@deepseek-ai/dsh-user-questions": ">=0.1.5-0 <0.3.0-0",
110
- "@deepseek-ai/dsh-client-connection": ">=0.1.5-0 <0.3.0-0",
111
- "@deepseek-ai/dsh-app-boot": ">=0.1.5-0 <0.3.0-0",
112
- "@deepseek-ai/dsh-atomic-write": ">=0.1.5-0 <0.3.0-0",
113
- "@deepseek-ai/dsh-cmdline": ">=0.1.5-0 <0.3.0-0",
114
- "@deepseek-ai/dsh-plugin-manager": ">=0.1.5-0 <0.3.0-0",
115
- "@deepseek-ai/dsh-jobs": ">=0.1.5-0 <0.3.0-0"
96
+ "@deepseek-ai/dsh-agent": ">=0.2.2-0 <1.0.0-0",
97
+ "@deepseek-ai/dsh-agent-presets": ">=0.2.2-0 <1.0.0-0",
98
+ "@deepseek-ai/dsh-api-gateway": ">=0.2.2-0 <1.0.0-0",
99
+ "@deepseek-ai/dsh-commands": ">=0.2.2-0 <1.0.0-0",
100
+ "@deepseek-ai/dsh-home-paths": ">=0.2.2-0 <1.0.0-0",
101
+ "@deepseek-ai/dsh-host-webserver": ">=0.2.2-0 <1.0.0-0",
102
+ "@deepseek-ai/dsh-llm": ">=0.2.2-0 <1.0.0-0",
103
+ "@deepseek-ai/dsh-scope": ">=0.2.2-0 <1.0.0-0",
104
+ "@deepseek-ai/dsh-session": ">=0.2.2-0 <1.0.0-0",
105
+ "@deepseek-ai/dsh-session-persistence": ">=0.2.2-0 <1.0.0-0",
106
+ "@deepseek-ai/dsh-tools": ">=0.2.2-0 <1.0.0-0",
107
+ "@deepseek-ai/dsh-typert-protocol": ">=0.2.2-0 <1.0.0-0",
108
+ "@deepseek-ai/dsh-user-approval": ">=0.2.2-0 <1.0.0-0",
109
+ "@deepseek-ai/dsh-user-questions": ">=0.2.2-0 <1.0.0-0",
110
+ "@deepseek-ai/dsh-client-connection": ">=0.2.2-0 <1.0.0-0",
111
+ "@deepseek-ai/dsh-app-boot": ">=0.2.2-0 <1.0.0-0",
112
+ "@deepseek-ai/dsh-atomic-write": ">=0.2.2-0 <1.0.0-0",
113
+ "@deepseek-ai/dsh-cmdline": ">=0.2.2-0 <1.0.0-0",
114
+ "@deepseek-ai/dsh-plugin-manager": ">=0.2.2-0 <1.0.0-0",
115
+ "@deepseek-ai/dsh-jobs": ">=0.2.2-0 <1.0.0-0"
116
116
  },
117
117
  "peerDependenciesMeta": {
118
118
  "@deepseek-ai/cordis": {
@@ -225,9 +225,13 @@ interface ProcessOptions {
225
225
  onOutput?: () => void;
226
226
  /** Overlay on process.env (tool-built values only, e.g. RSYNC_RSH). */
227
227
  env?: NodeJS.ProcessEnv;
228
+ /** Task E(SSH MUX):取消(timeout 或显式 cancel)即同步回调,不等 close。mux master 会经
229
+ * fd-passing 持有被杀客户端的会话 fd 直到远端会话结束——若远端清理 killer 等 close 后才发射,
230
+ * 就成了「close 等远端结束、远端结束等 killer」死锁。此处先行启动 killer 才能解开 close。至多一次。 */
231
+ onCancel?: () => void;
228
232
  }
229
233
  /** Real detached process. Completion includes group cleanup, even after its leader closes. */
230
- declare function startBinaryProcess(argv: string[], options?: Pick<ProcessOptions, 'cwd' | 'timeoutSec' | 'env'>): {
234
+ declare function startBinaryProcess(argv: string[], options?: Pick<ProcessOptions, 'cwd' | 'timeoutSec' | 'env' | 'onCancel'>): {
231
235
  stdout: Readable;
232
236
  stderr: Readable;
233
237
  stdin: Writable;
@@ -334,15 +338,6 @@ interface PtyDispatchResult {
334
338
  running?: boolean;
335
339
  job?: PtyRunningJob;
336
340
  }
337
- /** 账本条目(§5):commandId / 摘要 / exit / 耗时;保留最近 20 条(user 定案)。 */
338
- interface LedgerEntry {
339
- commandId: string;
340
- jobId?: string;
341
- summary: string;
342
- exit: number | null;
343
- durationMs: number;
344
- running: boolean;
345
- }
346
341
  type PtyState = 'cold' | 'starting' | 'ready' | 'dead' | 'disposed';
347
342
  /** 会话运行时快照(status 面消费,Ruling 16 词汇源)。 */
348
343
  interface SessionSnapshot {
@@ -361,12 +356,11 @@ declare class PtySession {
361
356
  private deathWaiters;
362
357
  private diag;
363
358
  private inFlight;
359
+ private cmdSeq;
364
360
  /** P4/P5:当前占用前台的 detached job(background/超时 handoff)。非 null 时新命令拒绝(Q6)。 */
365
361
  private detachedJob;
366
362
  /** §3.2(2026-10-25):当前占用会话的命令——dispatch 同步占位,settle/cleanup 释放;input 的唯一写入对象。 */
367
363
  private activeCommand;
368
- /** 账本(§5):本会话最近 20 条命令(FIFO,超出丢最旧)。 */
369
- private ledger;
370
364
  /** env 侧信道基线(init E 帧);undefined = 侧信道不可用(不报假 delta)。 */
371
365
  private envBaseline;
372
366
  /** idle 起点(ready / settle 时重置);null = 尚无 idle 时钟(cold 或已 dispose)。 */
@@ -387,7 +381,12 @@ declare class PtySession {
387
381
  get lastCwd(): string | null;
388
382
  /** 占用前台的 detached job 的 commandId(无 = null;close 拒绝与 busy 文案共用)。 */
389
383
  get detachedCommandId(): string | null;
390
- /** job 通道收养后回填 jobId(timeout handoff 时 registry id ≠ commandId,账本如实记录两者);运行中的命令同步携带(input 回执用)。 */
384
+ /** handoff/card 面(2026-11-01 默认 PTY 轮):当前占用会话的命令与可选 job 句柄;无 = null。 */
385
+ get active(): {
386
+ commandId: string;
387
+ jobId?: string;
388
+ } | null;
389
+ /** job 通道收养后回填 jobId(timeout handoff 时 registry id ≠ commandId);运行中的命令同步携带(stdin-only 写入回执用)。 */
391
390
  attachJob(commandId: string, jobId: string): void;
392
391
  /** Workbench 身份(§3):id + 可选 label + connection + byo 标记。 */
393
392
  get identity(): {
@@ -397,8 +396,6 @@ declare class PtySession {
397
396
  byo: boolean;
398
397
  builtOn: boolean;
399
398
  };
400
- /** 账本快照(session card 面,只读)。 */
401
- ledgerSnapshot(): readonly LedgerEntry[];
402
399
  /** spawn 创建原文(仅 BYO 会话;v2 起仅存档,不参与复用判定)。 */
403
400
  get origin(): string | undefined;
404
401
  /** status 面快照:state + busy(有命令在跑)+ idleMs(上次 settle 至今)+ pid(进程组头,kill 兜底可观测)。 */
@@ -597,6 +594,41 @@ interface RsyncReceipt extends RunResult {
597
594
  */
598
595
  declare function runRsync(request: RsyncRequest, source: RsyncEndpoint, destination: RsyncEndpoint, signal: AbortSignal, options?: RelayRsyncOptions): Promise<RsyncReceipt>;
599
596
  //#endregion
597
+ //#region src/remote/ssh-mux.d.ts
598
+ interface SshMuxIdentity {
599
+ /** 原始 target 串(如 `ssh:dev4` / `dev4`)——同一 effective 身份不同拼法也不串 socket。 */
600
+ target: string;
601
+ connection: SshConnection;
602
+ }
603
+ interface SshMuxOptions {
604
+ persistSec?: number;
605
+ /** socket 目录根(默认 os.tmpdir());测试注入口。 */
606
+ rootDir?: string;
607
+ runner?: (argv: string[], opts?: {
608
+ timeoutSec?: number;
609
+ }) => Promise<{
610
+ exit: number | null;
611
+ }>;
612
+ }
613
+ /** 每 Agent 一个(driver 私有):tool-owned 0700 socket 目录 + 按连接身份的 socket 名。
614
+ * 目录名含随机 owner 后缀,跨 Agent 天然不共享;dispose 逐 socket `-O exit` 后整目录删除。 */
615
+ declare class SshMux {
616
+ private readonly persistSec;
617
+ private readonly rootDir;
618
+ private readonly runner;
619
+ private readonly owner;
620
+ private readonly sockets;
621
+ private dir;
622
+ private disposal;
623
+ constructor(options?: SshMuxOptions);
624
+ /** 注入 SSH argv 的 MUX 选项(trusted internal argv,非模型输入)。目录懒建(纯 docker/hub
625
+ * Agent 永不触盘);超限/已 dispose 返回 [] = 诚实退化为普通连接。 */
626
+ argvFor(identity: SshMuxIdentity): string[];
627
+ /** Teardown:先 `-O exit` 逐 socket 礼貌拆除 master(不拨号、5s 上限、错误全吞——
628
+ * master 已死/残 socket 属正常),再删目录。单飞(重复调用同一 Promise)。 */
629
+ dispose(): Promise<void>;
630
+ }
631
+ //#endregion
600
632
  //#region src/remote/oneshot.d.ts
601
633
  interface OneShotOptions {
602
634
  stdin?: string;
@@ -616,6 +648,8 @@ interface ProbeOptions {
616
648
  connectTimeoutSec?: number;
617
649
  hardTimeoutSec?: number;
618
650
  runner?: (argv: string[], opts?: OneShotOptions) => Promise<OneShotResult>;
651
+ /** Task E:SSH 探测与 oneshot 执行链共用 MUX(同一身份 → 同一 master,探测零额外握手)。 */
652
+ muxArgvFor?: (plan: TargetPlan) => readonly string[];
619
653
  }
620
654
  //#endregion
621
655
  //#region src/remote/roster.d.ts
@@ -680,6 +714,7 @@ interface RemoteDriverOptions {
680
714
  onAudit?: (r: RemoteAuditRecord) => void;
681
715
  oneshotArgvFor?: (plan: TargetPlan, cmd: string, options: {
682
716
  cleanupTag?: string;
717
+ muxArgv?: readonly string[];
683
718
  }) => string[];
684
719
  ptyArgvFor?: (plan: TargetPlan) => string[];
685
720
  spawnArgvFor?: (spawnCommand: string) => string[];
@@ -688,6 +723,8 @@ interface RemoteDriverOptions {
688
723
  probeRunner?: ProbeOptions['runner'];
689
724
  /** 测试/验收缝:helper 资产来源(默认 lib 旁挂 helper-bin);显式 null 强制 shim 路径。 */
690
725
  helperAssetsFor?: () => HelperAssets | null;
726
+ /** 测试/验收缝:SSH oneshot MUX 状态(默认每 driver 一个 SshMux = 每 Agent 隔离)。 */
727
+ sshMux?: SshMux;
691
728
  /** 测试缝:roster 扫描执行器(裸名解析复用)。 */
692
729
  rosterRunner?: RosterOptions['runner'];
693
730
  /** 测试缝:ssh config 读取(裸名解析复用)。 */
@@ -703,6 +740,10 @@ declare function hubPtyAssets(): {
703
740
  declare class RemoteDriver {
704
741
  private readonly opts;
705
742
  private readonly pool;
743
+ /** 默认 PTY 槽(spec remote-default-pty §1):sessionKey → 归一 machineKey → pool key。
744
+ * 会话本体是普通 PtySession(id 创建即认领,roster 全可见);槽登记在 dispose/TTL 后悬空,
745
+ * 取槽时经 pool.get(disposed 视同出池)惰性清理。 */
746
+ private readonly defaultSlots;
706
747
  private readonly labels;
707
748
  private readonly hubOwner;
708
749
  private readonly hubProviders;
@@ -715,6 +756,7 @@ declare class RemoteDriver {
715
756
  private readonly runnerOf;
716
757
  private disposal;
717
758
  private readonly ptyIdleTtlSec;
759
+ private readonly mux;
718
760
  constructor(opts?: RemoteDriverOptions);
719
761
  call(params: RemoteCallParams, callCtx?: {
720
762
  sessionKey?: string;
@@ -753,6 +795,10 @@ declare class RemoteDriver {
753
795
  private planOf;
754
796
  /** ssh:<name> 的池感知解析:BYO 身份 → 其 connection;否则按 config 别名/主机名。 */
755
797
  private sshPlanFor;
798
+ /** Task E MUX 身份:仅 SSH plan 注入(docker/incus/hub 返回 undefined)。身份键 = 原始
799
+ * target 串 + 有效连接字段(host/user/port/key/ProxyJump)——同身份共享 master,跨身份
800
+ * 不串 socket;目录/寿命/拆除全部由 SshMux 自持。 */
801
+ private muxArgvFor;
756
802
  /** BYO ssh 注册(v2:无 spec 对比——label 占用即拒;注册成功才认领)。返回实际名(label 或 s-id)。 */
757
803
  private registerByoSsh;
758
804
  /** PTY 会话创建(native/spawn 同一形状):上限 → label 认领 → 惰性会话(失败由 onDead 释放 label)。 */
@@ -760,8 +806,36 @@ declare class RemoteDriver {
760
806
  private ttlMinutes;
761
807
  /** connection 由 BYO ssh 身份建立 → card 面标 `(built on)`(与 roster 同词,R2 复核 P2-10)。 */
762
808
  private isBuiltOn;
763
- /** PTY 创建形唯一实现(execute 与 background 预建共用):spawn BYO / ssh BYO / native `<transport>:pty`。 */
809
+ /** PTY 创建形唯一实现(execute 与 background 预建共用):spawn BYO(spec 2026-11-01:native `:pty`/hub-pty 创建语法已删,machine 会话经默认槽 + handoff)。 */
764
810
  private createPtyLane;
811
+ /** 池条目的槽键归一:同一实体(host/container/machine 身份)跨裸名/前缀/撞名前缀共享同一默认槽。 */
812
+ private machineKeyOfEntry;
813
+ /** 默认槽的 machine 规格:归一 key + 创建 argv + 展示 connection(hub 每次经 ptyEndpoint 重验 pairing,P10)。 */
814
+ private machineSlotSpec;
815
+ /** 取/懒建 machine 的默认 PTY 槽:dead/disposed 槽惰性重建;id 创建即认领(roster 全可见 + 防撞)。 */
816
+ private defaultSlot;
817
+ private releaseDefaultSlot;
818
+ /** 按池键反查并解绑默认槽(background 提交即 handoff 用);非槽会话无操作。 */
819
+ private releaseSlotByPoolKey;
820
+ /** roster/status 面:本 session 的默认槽标注(session id → machineKey;悬空条目过滤)。 */
821
+ private defaultMarks;
822
+ /** spec §1 handoff(2026-11-01 二/三轮裁决):把 machine 默认 PTY 解绑成可寻址 pty:<id>——同引用移动
823
+ * (不重启、不复制输出流);fresh(尚无默认槽)= 后台创建空闲 shell 再隔离(默认 PTY 思维模型恒
824
+ * ready,创建时机是实现细节);busy = 附当前命令与 job 句柄。machine 下次 exec 按需新建默认 PTY。 */
825
+ handoff(target: string, callCtx?: {
826
+ sessionKey?: string;
827
+ }): Promise<RemoteCallResult>;
828
+ /** close 统一入口(spec §1 + 三轮补充裁决):machine target 只关默认槽;pty selector 关该会话;
829
+ * 不存在 job 定位——取消运行中命令的唯一入口是官方 job_kill。 */
830
+ close(target: string, sessionKey: string, force?: boolean): Promise<{
831
+ session: string;
832
+ connection: string;
833
+ closed: boolean;
834
+ reason?: string;
835
+ killed: string[];
836
+ message?: string;
837
+ }>;
838
+ private closeDefault;
765
839
  /** background PTY lane:会话先占位(不拨号)再进官方 jobs registry——首回执必须能寻址;
766
840
  * registry 拒绝时把新建的会话拆掉(复用形的会话绝不拆)。返回 undefined = 走普通 oneshot job。 */
767
841
  preparePtyLane(params: RemoteCallParams, callCtx?: {
@@ -786,10 +860,9 @@ declare class RemoteDriver {
786
860
  };
787
861
  /** job 通道收养回填(timeout handoff 时 registry id ≠ commandId,账本记录两者)。 */
788
862
  attachPtyJob(commandId: string, jobId: string, sessionKey: string): void;
789
- /** §3.1(2026-10-25)interactive-stdin:input 动作——向已有 live PTY 的当前运行命令
790
- * 追加 stdin。只解析池内已存在的会话(pty:<id|label> / 裸 label 命中 pty 项),
791
- * 不触发发现、拨号、创建或重连;machine target 与创建形(:pty 后缀,含 hub:<m4>:pty)
792
- * 一律明确拒绝并给出可恢复指引。回执附 connection/label 供工具层渲染。 */
863
+ /** spec remote-default-pty §1(2026-11-01):exec stdin-only 写入核心——向已有 live PTY 的当前运行命令
864
+ * 追加 exact-byte stdin。寻址:pty:<id|label> / 裸 label 命中 pty 项 / machine target(其默认槽的
865
+ * 当前命令,无槽不懒建、如实报错)。不触发拨号、创建或重连;回执附 connection/label 供工具层渲染。 */
793
866
  input(target: string, options: PtyInputOptions, callCtx?: {
794
867
  sessionKey?: string;
795
868
  }): Promise<PtyInputReceipt & {