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.
- package/agent-agy/dist/agent.d.ts +4 -1
- package/agent-agy/dist/agent.js +15 -1
- package/agent-agy/dist/index.js +5 -8
- package/agent-agy/package.json +6 -6
- package/agent-agy-sdk/dist/agent.d.ts +4 -1
- package/agent-agy-sdk/dist/agent.js +15 -1
- package/agent-agy-sdk/dist/index.js +5 -8
- package/agent-agy-sdk/package.json +5 -5
- package/agent-claude/dist/agent.js +15 -1
- package/agent-claude/package.json +8 -8
- package/agent-codex/dist/agent.js +15 -1
- package/agent-codex/package.json +7 -7
- package/agent-codex-sdk/dist/agent.js +15 -1
- package/agent-codex-sdk/dist/index.js +5 -11
- package/agent-codex-sdk/package.json +7 -7
- package/agent-hermes/dist/agent.js +15 -1
- package/agent-hermes/dist/index.js +5 -8
- package/agent-hermes/package.json +7 -7
- package/agent-omp/dist/agent.js +26 -2
- package/agent-omp/package.json +8 -8
- package/agent-omp-sdk/dist/agent.d.ts +4 -1
- package/agent-omp-sdk/dist/agent.js +15 -1
- package/agent-omp-sdk/package.json +8 -8
- package/agent-pi/dist/agent.js +20 -2
- package/agent-pi/dist/index.js +5 -11
- package/agent-pi/package.json +7 -7
- package/package.json +21 -21
- package/remote/plugin.d.ts +93 -20
- package/remote/plugin.js +921 -452
- package/remote/provenance.json +15 -13
- package/superd-hub/dist/agent-model-face.d.ts +93 -0
- package/superd-hub/dist/agent-model-face.js +113 -0
- package/superd-hub/dist/index.d.ts +1 -0
- package/superd-hub/dist/index.js +1 -0
- package/superd-hub/dist/world-entry.js +30 -0
- package/superd-hub/package.json +14 -10
|
@@ -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.
|
|
30
|
-
"@deepseek-ai/dsh-agent-presets": ">=0.
|
|
31
|
-
"@deepseek-ai/dsh-llm": ">=0.
|
|
32
|
-
"@deepseek-ai/dsh-scope": ">=0.
|
|
33
|
-
"@deepseek-ai/dsh-session": ">=0.
|
|
34
|
-
"@deepseek-ai/dsh-session-persistence": ">=0.
|
|
35
|
-
"@deepseek-ai/dsh-typert-protocol": ">=0.
|
|
36
|
-
"@deepseek-ai/dsh-home-paths": ">=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": {
|
package/agent-pi/dist/agent.js
CHANGED
|
@@ -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
|
-
|
|
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 !== ""
|
package/agent-pi/dist/index.js
CHANGED
|
@@ -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
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
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
|
}
|
package/agent-pi/package.json
CHANGED
|
@@ -27,13 +27,13 @@
|
|
|
27
27
|
},
|
|
28
28
|
"peerDependencies": {
|
|
29
29
|
"@deepseek-ai/cordis": "^4.0.1",
|
|
30
|
-
"@deepseek-ai/dsh-agent": ">=0.
|
|
31
|
-
"@deepseek-ai/dsh-agent-presets": ">=0.
|
|
32
|
-
"@deepseek-ai/dsh-llm": ">=0.
|
|
33
|
-
"@deepseek-ai/dsh-scope": ">=0.
|
|
34
|
-
"@deepseek-ai/dsh-session": ">=0.
|
|
35
|
-
"@deepseek-ai/dsh-session-persistence": ">=0.
|
|
36
|
-
"@deepseek-ai/dsh-typert-protocol": ">=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.
|
|
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.
|
|
97
|
-
"@deepseek-ai/dsh-agent-presets": ">=0.
|
|
98
|
-
"@deepseek-ai/dsh-api-gateway": ">=0.
|
|
99
|
-
"@deepseek-ai/dsh-commands": ">=0.
|
|
100
|
-
"@deepseek-ai/dsh-home-paths": ">=0.
|
|
101
|
-
"@deepseek-ai/dsh-host-webserver": ">=0.
|
|
102
|
-
"@deepseek-ai/dsh-llm": ">=0.
|
|
103
|
-
"@deepseek-ai/dsh-scope": ">=0.
|
|
104
|
-
"@deepseek-ai/dsh-session": ">=0.
|
|
105
|
-
"@deepseek-ai/dsh-session-persistence": ">=0.
|
|
106
|
-
"@deepseek-ai/dsh-tools": ">=0.
|
|
107
|
-
"@deepseek-ai/dsh-typert-protocol": ">=0.
|
|
108
|
-
"@deepseek-ai/dsh-user-approval": ">=0.
|
|
109
|
-
"@deepseek-ai/dsh-user-questions": ">=0.
|
|
110
|
-
"@deepseek-ai/dsh-client-connection": ">=0.
|
|
111
|
-
"@deepseek-ai/dsh-app-boot": ">=0.
|
|
112
|
-
"@deepseek-ai/dsh-atomic-write": ">=0.
|
|
113
|
-
"@deepseek-ai/dsh-cmdline": ">=0.
|
|
114
|
-
"@deepseek-ai/dsh-plugin-manager": ">=0.
|
|
115
|
-
"@deepseek-ai/dsh-jobs": ">=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": {
|
package/remote/plugin.d.ts
CHANGED
|
@@ -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
|
-
/**
|
|
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
|
|
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
|
-
/** §
|
|
790
|
-
* 追加 stdin
|
|
791
|
-
*
|
|
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 & {
|