super-dsh 0.3.1 → 0.3.2-e
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/client/index.js +135 -14
- package/package.json +1 -1
- package/remote/helper-bin/MANIFEST.json +35 -0
- package/remote/helper-bin/aarch64-apple-darwin/BUILT-VER +1 -0
- package/remote/helper-bin/aarch64-apple-darwin/superd-run +0 -0
- package/remote/helper-bin/aarch64-unknown-linux-musl/BUILT-VER +1 -0
- package/remote/helper-bin/aarch64-unknown-linux-musl/superd-run +0 -0
- package/remote/helper-bin/x86_64-pc-windows-gnu/BUILT-VER +1 -0
- package/remote/helper-bin/x86_64-pc-windows-gnu/superd-run.exe +0 -0
- package/remote/helper-bin/x86_64-unknown-linux-musl/BUILT-VER +1 -0
- package/remote/helper-bin/x86_64-unknown-linux-musl/superd-run +0 -0
- package/remote/hub-pty-pump.mjs +97 -0
- package/remote/plugin.d.ts +523 -199
- package/remote/plugin.js +2530 -768
- package/remote/provenance.json +36 -21
- package/superd-hub/dist/a2a-host.d.ts +11 -3
- package/superd-hub/dist/a2a-host.js +7 -7
- package/superd-hub/dist/a2a-row.js +7 -1
- package/superd-hub/dist/carrier.d.ts +9 -7
- package/superd-hub/dist/carrier.js +3 -3
- package/superd-hub/dist/client/pill-geometry.d.ts +70 -0
- package/superd-hub/dist/client/pill-geometry.js +49 -0
- package/superd-hub/dist/client/switch.d.ts +15 -0
- package/superd-hub/dist/client/switch.js +54 -1
- package/superd-hub/dist/companions.js +8 -6
- package/superd-hub/dist/exec.d.ts +3 -2
- package/superd-hub/dist/exec.js +6 -5
- package/superd-hub/dist/fusion-transport.d.ts +18 -1
- package/superd-hub/dist/fusion-transport.js +44 -5
- package/superd-hub/dist/gateway.js +8 -1
- package/superd-hub/dist/hub-route.d.ts +5 -2
- package/superd-hub/dist/hub-route.js +6 -6
- package/superd-hub/dist/hub-tool.d.ts +1 -1
- package/superd-hub/dist/hub-tool.js +6 -6
- package/superd-hub/dist/remote-provider.js +70 -36
- package/superd-hub/dist/rpc.d.ts +5 -0
- package/superd-hub/dist/rpc.js +20 -1
- package/superd-hub/dist/switch-core.d.ts +41 -0
- package/superd-hub/dist/switch-core.js +40 -0
- package/superd-hub/dist/targets.d.ts +7 -0
- package/superd-hub/dist/world-lifecycle.js +1 -1
- package/superd-hub/lib/client/index.js +135 -14
- package/superd-hub/dist/exec-pty-channel.d.ts +0 -58
- package/superd-hub/dist/exec-pty-channel.js +0 -162
- package/superd-hub/dist/exec-pty-framing.d.ts +0 -34
- package/superd-hub/dist/exec-pty-framing.js +0 -89
- package/superd-hub/dist/exec-pty-session.d.ts +0 -78
- package/superd-hub/dist/exec-pty-session.js +0 -228
package/remote/plugin.d.ts
CHANGED
|
@@ -90,22 +90,403 @@ interface SshConnection {
|
|
|
90
90
|
readonly key?: string;
|
|
91
91
|
readonly proxyJump?: string;
|
|
92
92
|
}
|
|
93
|
-
/** One instance per Agent-owned driver; destroyed with its Agent/plugin owners. */
|
|
94
|
-
declare class SshTargets {
|
|
95
|
-
private readonly targets;
|
|
96
|
-
register(label: string, connection: SshConnection): SshConnection;
|
|
97
|
-
get(label: string): SshConnection | undefined;
|
|
98
|
-
entries(): ReadonlyArray<readonly [string, SshConnection]>;
|
|
99
|
-
clear(): void;
|
|
100
|
-
}
|
|
101
93
|
/** Shared by execution, probes and file/relay consumers. extraArgs is trusted
|
|
102
|
-
* internal SSH argv (e.g. forwarding), never a model-provided shell string.
|
|
94
|
+
* internal SSH argv (e.g. forwarding), never a model-provided shell string.
|
|
95
|
+
* Identity assembly lives in ssh-argv.ts (the ONE policy — 2026-10-17 ruling);
|
|
96
|
+
* this wrapper only picks the tty/batch dialect base. */
|
|
103
97
|
declare function sshArgv(connection: SshConnection, options?: {
|
|
104
98
|
tty?: boolean;
|
|
105
99
|
extraArgs?: readonly string[];
|
|
106
100
|
command?: string;
|
|
107
101
|
}): string[];
|
|
108
102
|
//#endregion
|
|
103
|
+
//#region src/remote/hub-contract.d.ts
|
|
104
|
+
/** Owned structural boundary. Better never imports or depends on Super. */
|
|
105
|
+
interface RemoteInput {
|
|
106
|
+
target?: string;
|
|
107
|
+
spawn?: string;
|
|
108
|
+
ssh?: SshConnection;
|
|
109
|
+
cmd?: string;
|
|
110
|
+
scriptPath?: string;
|
|
111
|
+
stdin?: string;
|
|
112
|
+
mode?: 'oneshot' | 'pty';
|
|
113
|
+
timeout?: number;
|
|
114
|
+
}
|
|
115
|
+
interface PreparedRemoteInput {
|
|
116
|
+
target?: string;
|
|
117
|
+
spawn?: string;
|
|
118
|
+
ssh?: SshConnection;
|
|
119
|
+
cmd: string;
|
|
120
|
+
stdin?: string;
|
|
121
|
+
mode?: 'oneshot' | 'pty';
|
|
122
|
+
timeout?: number;
|
|
123
|
+
}
|
|
124
|
+
/** Counters exclude diagnostic banners. dropped is ring eviction; total-returned is all omitted output. */
|
|
125
|
+
type OutputStats = {
|
|
126
|
+
unit: 'utf16' | 'bytes';
|
|
127
|
+
total: number;
|
|
128
|
+
retained: number;
|
|
129
|
+
dropped: number;
|
|
130
|
+
returned: number;
|
|
131
|
+
retentionLimit: number;
|
|
132
|
+
};
|
|
133
|
+
type StreamOutputStats = {
|
|
134
|
+
stdout: OutputStats;
|
|
135
|
+
stderr?: OutputStats;
|
|
136
|
+
};
|
|
137
|
+
interface RemoteProcess {
|
|
138
|
+
cancel(reason?: string): void;
|
|
139
|
+
done: Promise<{
|
|
140
|
+
exit: number | null;
|
|
141
|
+
timedOut: boolean;
|
|
142
|
+
durationMs: number;
|
|
143
|
+
cancelled?: boolean;
|
|
144
|
+
}>;
|
|
145
|
+
/** diagnostic is executor-generated text, not process output; excluded from byte cursor and counters. */
|
|
146
|
+
read(channel: 'stdout' | 'stderr', fromByte: number): {
|
|
147
|
+
text: string;
|
|
148
|
+
nextOffset: number;
|
|
149
|
+
lossy: boolean;
|
|
150
|
+
stats?: OutputStats;
|
|
151
|
+
diagnostic?: string;
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
interface BinaryFileEndpoint {
|
|
155
|
+
exportTree(path: string, signal: AbortSignal): Promise<NodeJS.ReadableStream>;
|
|
156
|
+
importTree(path: string, source: NodeJS.ReadableStream, options: {
|
|
157
|
+
mkdir: boolean;
|
|
158
|
+
signal: AbortSignal;
|
|
159
|
+
}): Promise<void>;
|
|
160
|
+
digest(path: string, signal: AbortSignal, selection?: readonly string[]): Promise<{
|
|
161
|
+
sha256: string;
|
|
162
|
+
bytes: number;
|
|
163
|
+
entries: number;
|
|
164
|
+
}>;
|
|
165
|
+
}
|
|
166
|
+
interface HubTarget {
|
|
167
|
+
id: string;
|
|
168
|
+
label: string;
|
|
169
|
+
execEnabled: boolean;
|
|
170
|
+
}
|
|
171
|
+
interface HubRemoteTransport {
|
|
172
|
+
protocol: 1;
|
|
173
|
+
listTargets(): readonly HubTarget[];
|
|
174
|
+
start(machine: string, input: PreparedRemoteInput, owner: string): Promise<RemoteProcess>;
|
|
175
|
+
/** Hub PTY 端点(0.3.2-c):url = ws(s)://<origin>/api/superd/exec/pty;cookie = pairing 凭据;
|
|
176
|
+
* wsPath = transport 侧(superd-hub 上下文,分叉的 proven 解析链)解析好的 ws 模块绝对路径。 */
|
|
177
|
+
ptyEndpoint(machine: string): {
|
|
178
|
+
url: string;
|
|
179
|
+
cookie: string;
|
|
180
|
+
wsPath: string;
|
|
181
|
+
};
|
|
182
|
+
fileEndpoint(machine: string): BinaryFileEndpoint;
|
|
183
|
+
releaseOwner(owner: string): Promise<void>;
|
|
184
|
+
}
|
|
185
|
+
//#endregion
|
|
186
|
+
//#region src/remote/output-ring.d.ts
|
|
187
|
+
/** Byte-addressed decoded output: mid-codepoint cursors skip forward and explicitly report loss. */
|
|
188
|
+
declare function readUtf8Tail(bytes: Buffer, totalBytes: number, fromByte: number): {
|
|
189
|
+
text: string;
|
|
190
|
+
nextOffset: number;
|
|
191
|
+
lossy: boolean;
|
|
192
|
+
};
|
|
193
|
+
/** Native/PTY retention is UTF16 units; cursor offsets remain real UTF8 bytes. Input is decoded text. */
|
|
194
|
+
declare class Utf16TailRing {
|
|
195
|
+
readonly capacity: number;
|
|
196
|
+
text: string;
|
|
197
|
+
total: number;
|
|
198
|
+
private totalBytes;
|
|
199
|
+
constructor(capacity?: number);
|
|
200
|
+
push(text: string): void;
|
|
201
|
+
stats(returned?: number): OutputStats;
|
|
202
|
+
read(fromByte: number): ReturnType<typeof readUtf8Tail>;
|
|
203
|
+
}
|
|
204
|
+
/** Raw byte retention for Hub oneshot. Tail/read starts skip partial UTF8 prefixes, never invent replacement characters. */
|
|
205
|
+
declare class ByteTailRing {
|
|
206
|
+
readonly capacity: number;
|
|
207
|
+
total: number;
|
|
208
|
+
private chunks;
|
|
209
|
+
private retained;
|
|
210
|
+
constructor(capacity?: number);
|
|
211
|
+
push(chunk: Buffer): void;
|
|
212
|
+
tail(maxBytes?: number): Buffer;
|
|
213
|
+
stats(returned?: number): OutputStats;
|
|
214
|
+
read(fromByte: number): ReturnType<typeof readUtf8Tail>;
|
|
215
|
+
}
|
|
216
|
+
//#endregion
|
|
217
|
+
//#region src/remote/process.d.ts
|
|
218
|
+
declare const PROCESS_CLEANUP_BOUND_MS: number;
|
|
219
|
+
interface ProcessOptions {
|
|
220
|
+
stdin?: string;
|
|
221
|
+
timeoutSec?: number;
|
|
222
|
+
cwd?: string;
|
|
223
|
+
/** Hub retains raw bytes; native transports retain decoded UTF16 units. */
|
|
224
|
+
unit?: 'bytes' | 'utf16';
|
|
225
|
+
onOutput?: () => void;
|
|
226
|
+
/** Overlay on process.env (tool-built values only, e.g. RSYNC_RSH). */
|
|
227
|
+
env?: NodeJS.ProcessEnv;
|
|
228
|
+
}
|
|
229
|
+
/** Real detached process. Completion includes group cleanup, even after its leader closes. */
|
|
230
|
+
declare function startBinaryProcess(argv: string[], options?: Pick<ProcessOptions, 'cwd' | 'timeoutSec' | 'env'>): {
|
|
231
|
+
stdout: Readable;
|
|
232
|
+
stderr: Readable;
|
|
233
|
+
stdin: Writable;
|
|
234
|
+
cancel(): void;
|
|
235
|
+
done: RemoteProcess['done'];
|
|
236
|
+
diagnostic(): string | undefined;
|
|
237
|
+
};
|
|
238
|
+
/** Text adapter over the same owned process-group lifecycle as binary pipelines. */
|
|
239
|
+
declare function startOneShot(argv: string[], options?: ProcessOptions): RemoteProcess;
|
|
240
|
+
//#endregion
|
|
241
|
+
//#region src/remote/nonce-framing.d.ts
|
|
242
|
+
/** 0.3.2-e:自有 30K 返回窗口已删(原生 agent runtime 的 spill/输出保护接管模型上下文
|
|
243
|
+
* 尺寸)。本 helper 只做 retention 披露:ring 留存(4M UTF-16 / 4MiB bytes)未驱逐时
|
|
244
|
+
* 全量透传(returned=retained,无 banner);驱逐(dropped>0,仅 >4M 输出发生)时打一行
|
|
245
|
+
* banner 且 truncated=原始总量。text 已是 ring 尾部,不再二次裁剪。 */
|
|
246
|
+
declare function disclose(text: string, stats?: OutputStats): {
|
|
247
|
+
text: string;
|
|
248
|
+
truncated?: number;
|
|
249
|
+
stats?: OutputStats;
|
|
250
|
+
};
|
|
251
|
+
interface EnvDelta {
|
|
252
|
+
added: string[];
|
|
253
|
+
changed: string[];
|
|
254
|
+
removed: string[];
|
|
255
|
+
}
|
|
256
|
+
//#endregion
|
|
257
|
+
//#region src/remote/pty-session.d.ts
|
|
258
|
+
interface PtySessionOptions {
|
|
259
|
+
key: string;
|
|
260
|
+
argv: string[];
|
|
261
|
+
/** Workbench 身份(§3):自动 id(p-xxxx)+ 可选 label + connection 展示名(ssh:dev4 / docker:c / BYOP)。 */
|
|
262
|
+
id: string;
|
|
263
|
+
label?: string;
|
|
264
|
+
connection: string;
|
|
265
|
+
byo?: boolean;
|
|
266
|
+
/** connection 来自 BYO ssh 身份(card 面标 `(built on)`,与 roster 同词)。 */
|
|
267
|
+
builtOn?: boolean;
|
|
268
|
+
/** spawn 原文(BYO 会话存档;v2 无 spec 对比——不再参与复用判定,仅供回执/账本溯源)。 */
|
|
269
|
+
origin?: string;
|
|
270
|
+
idleTtlSec: number;
|
|
271
|
+
initTimeoutSec?: number;
|
|
272
|
+
/** 池回调:会话彻底出池(dispose)时触发;进程意外死亡不出池(Ruling 7)。 */
|
|
273
|
+
onDead?: () => void;
|
|
274
|
+
}
|
|
275
|
+
interface PtyDispatchOptions {
|
|
276
|
+
stdin?: string;
|
|
277
|
+
timeoutSec?: number; /** 账本键:driver 分配(background 通道预传入 registry jobId;同步命令同格式本地生成)——一个命令永远只有一个 id。 */
|
|
278
|
+
commandId: string; /** P5:立即回执 running job,不等帧(run_in_background 与超时 handoff 共用同一条 job 通道)。 */
|
|
279
|
+
background?: boolean; /** background 通道预传入的 registry jobId(此时与 commandId 字面相等):账本与 input 回执如实携带,免 driver 侧二次回填。 */
|
|
280
|
+
jobId?: string;
|
|
281
|
+
}
|
|
282
|
+
/** §3.3(2026-10-25)interactive-stdin:input 动作的选项与回执(写入成功才回执)。 */
|
|
283
|
+
interface PtyInputOptions {
|
|
284
|
+
stdin: string;
|
|
285
|
+
commandId?: string;
|
|
286
|
+
}
|
|
287
|
+
interface PtyInputReceipt {
|
|
288
|
+
/** 模型面会话名(pty:<id>)。 */
|
|
289
|
+
session: string;
|
|
290
|
+
commandId: string;
|
|
291
|
+
/** 存在官方 job 时才有(background 预传 / timeout handoff 收养回填)。 */
|
|
292
|
+
jobId?: string;
|
|
293
|
+
/** 实际写入的 UTF-8 字节数。 */
|
|
294
|
+
writtenBytes: number;
|
|
295
|
+
}
|
|
296
|
+
/** detached job 的完成结果(frame 或会话死亡时结算;与 dispatch 回执同构)。 */
|
|
297
|
+
interface PtyJobResult {
|
|
298
|
+
output: string;
|
|
299
|
+
outputStats?: StreamOutputStats;
|
|
300
|
+
exit: number | null;
|
|
301
|
+
cwd: string | null;
|
|
302
|
+
timedOut: boolean;
|
|
303
|
+
commandId: string;
|
|
304
|
+
envDelta?: EnvDelta;
|
|
305
|
+
}
|
|
306
|
+
/** P4/P5(2026-10-19)running job 句柄:byte-cursor 增量读 + P8 显式中断 + 完成时帧结算。 */
|
|
307
|
+
interface PtyRunningJob {
|
|
308
|
+
/** 账本键:与 jobId 同构(background 通道预传入 registry id;同步完成命令用同格式生成 id)。 */
|
|
309
|
+
commandId: string;
|
|
310
|
+
/** Byte-cursor incremental read over the command's merged output (tail-ring retention; lossy reports eviction). */
|
|
311
|
+
read: (fromByte: number) => {
|
|
312
|
+
text: string;
|
|
313
|
+
nextOffset: number;
|
|
314
|
+
lossy: boolean;
|
|
315
|
+
};
|
|
316
|
+
stats: () => OutputStats;
|
|
317
|
+
/** P8 两段式 ^C 中断(会话存活;trap-INT 走宽限 group-kill 兜底)。 */
|
|
318
|
+
interrupt: () => void;
|
|
319
|
+
/** Settles on the exit frame, or with exit null when the session dies. */
|
|
320
|
+
done: Promise<PtyJobResult>;
|
|
321
|
+
}
|
|
322
|
+
interface PtyDispatchResult {
|
|
323
|
+
output: string;
|
|
324
|
+
outputStats?: StreamOutputStats;
|
|
325
|
+
exit: number | null;
|
|
326
|
+
cwd: string | null;
|
|
327
|
+
timedOut: boolean;
|
|
328
|
+
reconnected: boolean;
|
|
329
|
+
durationMs: number;
|
|
330
|
+
commandId: string;
|
|
331
|
+
/** env delta(E 帧侧信道):只回名字 + 变动标记,值不回传;init 侧信道失败时省略。 */
|
|
332
|
+
envDelta?: EnvDelta;
|
|
333
|
+
/** P4/P5:true = 命令仍在前台运行,本回执是 handoff(job 句柄随行)。 */
|
|
334
|
+
running?: boolean;
|
|
335
|
+
job?: PtyRunningJob;
|
|
336
|
+
}
|
|
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
|
+
type PtyState = 'cold' | 'starting' | 'ready' | 'dead' | 'disposed';
|
|
347
|
+
/** 会话运行时快照(status 面消费,Ruling 16 词汇源)。 */
|
|
348
|
+
interface SessionSnapshot {
|
|
349
|
+
state: PtyState;
|
|
350
|
+
busy: boolean;
|
|
351
|
+
idleMs: number | null;
|
|
352
|
+
pid: number | null;
|
|
353
|
+
}
|
|
354
|
+
declare class PtySession {
|
|
355
|
+
private readonly opts;
|
|
356
|
+
private proc;
|
|
357
|
+
private state;
|
|
358
|
+
private startPromise;
|
|
359
|
+
private idleTimer;
|
|
360
|
+
private onChunk;
|
|
361
|
+
private deathWaiters;
|
|
362
|
+
private diag;
|
|
363
|
+
private inFlight;
|
|
364
|
+
/** P4/P5:当前占用前台的 detached job(background/超时 handoff)。非 null 时新命令拒绝(Q6)。 */
|
|
365
|
+
private detachedJob;
|
|
366
|
+
/** §3.2(2026-10-25):当前占用会话的命令——dispatch 同步占位,settle/cleanup 释放;input 的唯一写入对象。 */
|
|
367
|
+
private activeCommand;
|
|
368
|
+
/** 账本(§5):本会话最近 20 条命令(FIFO,超出丢最旧)。 */
|
|
369
|
+
private ledger;
|
|
370
|
+
/** env 侧信道基线(init E 帧);undefined = 侧信道不可用(不报假 delta)。 */
|
|
371
|
+
private envBaseline;
|
|
372
|
+
/** idle 起点(ready / settle 时重置);null = 尚无 idle 时钟(cold 或已 dispose)。 */
|
|
373
|
+
private idleSince;
|
|
374
|
+
/** 意外死亡后的回收定时器(R2):ready 过的会话先留池供 reconnect,超时仍无人寻址则出池。 */
|
|
375
|
+
private deathTimer;
|
|
376
|
+
private lastCwdSeen;
|
|
377
|
+
/** 是否曾成功初始化(ready 过)。决定死亡语义:ready 过 → reconnect(留池);从未 ready → 出池(见 start())。 */
|
|
378
|
+
private everReady;
|
|
379
|
+
private disposal;
|
|
380
|
+
private procClose;
|
|
381
|
+
private groupCleanup;
|
|
382
|
+
constructor(opts: PtySessionOptions);
|
|
383
|
+
get sessionState(): PtyState;
|
|
384
|
+
/** 池键(driver 的 ttl/inspect 用)。 */
|
|
385
|
+
get key(): string;
|
|
386
|
+
/** 最近帧 cwd(card 面);从未执行过 = null。 */
|
|
387
|
+
get lastCwd(): string | null;
|
|
388
|
+
/** 占用前台的 detached job 的 commandId(无 = null;close 拒绝与 busy 文案共用)。 */
|
|
389
|
+
get detachedCommandId(): string | null;
|
|
390
|
+
/** job 通道收养后回填 jobId(timeout handoff 时 registry id ≠ commandId,账本如实记录两者);运行中的命令同步携带(input 回执用)。 */
|
|
391
|
+
attachJob(commandId: string, jobId: string): void;
|
|
392
|
+
/** Workbench 身份(§3):id + 可选 label + connection + byo 标记。 */
|
|
393
|
+
get identity(): {
|
|
394
|
+
id: string;
|
|
395
|
+
label?: string;
|
|
396
|
+
connection: string;
|
|
397
|
+
byo: boolean;
|
|
398
|
+
builtOn: boolean;
|
|
399
|
+
};
|
|
400
|
+
/** 账本快照(session card 面,只读)。 */
|
|
401
|
+
ledgerSnapshot(): readonly LedgerEntry[];
|
|
402
|
+
/** spawn 创建原文(仅 BYO 会话;v2 起仅存档,不参与复用判定)。 */
|
|
403
|
+
get origin(): string | undefined;
|
|
404
|
+
/** status 面快照:state + busy(有命令在跑)+ idleMs(上次 settle 至今)+ pid(进程组头,kill 兜底可观测)。 */
|
|
405
|
+
get snapshot(): SessionSnapshot;
|
|
406
|
+
/** 预热创建(创建形无 cmd):真正拨号到 init 帧——「会话已就绪」必须是真的,
|
|
407
|
+
* 而且只有 ready 过才挂 idle 回收(cold 会话没有 timer,会永远占配额)。 */
|
|
408
|
+
warm(): Promise<void>;
|
|
409
|
+
/** 同一会话命令占位制(2026-10-25 interactive-stdin 轮):dispatch 入口**同步**建立
|
|
410
|
+
* 命令占位(activeCommand + inFlight + 账本条目)——上一条命令仍在运行(同步等待 /
|
|
411
|
+
* 等输入 / detached job)时新 cmd 立即 E_SESSION_BUSY;原「纯同步并发排 FIFO」语义
|
|
412
|
+
* 废除(排队会让等输入的命令与补输入动作互相卡死,也给 busy 留下绕行窗口)。
|
|
413
|
+
* P4/P5:超时不杀命令而是 handoff 成 running job;background 立即回执;P8 显式
|
|
414
|
+
* interrupt 保留在 job.interrupt;死亡/冷态先重启(reconnect 语义不变)。 */
|
|
415
|
+
dispatch(cmd: string, dOpts: PtyDispatchOptions): Promise<PtyDispatchResult>;
|
|
416
|
+
/** §3.1(2026-10-25)interactive-stdin:向当前运行中的命令追加 stdin——只写既有通道
|
|
417
|
+
* 与身份,不新建命令、账本条目或输出游标;不重连、不重放(dead/disposed 明确拒绝)。
|
|
418
|
+
* 校验与写入全同步:多次 input 按调用顺序整段写入不交错;写入失败如实抛错(私有
|
|
419
|
+
* write() 的静默忽略不适用于回执语义)。stdin:"" 是零字节写入,不是 EOF。 */
|
|
420
|
+
input(options: PtyInputOptions): Promise<PtyInputReceipt>;
|
|
421
|
+
/** TTL / row teardown:尽力 exit,1s 后杀组,出池。 */
|
|
422
|
+
dispose(): Promise<void>;
|
|
423
|
+
private write;
|
|
424
|
+
private start;
|
|
425
|
+
private doStart;
|
|
426
|
+
private markDead;
|
|
427
|
+
private resetIdleTimer;
|
|
428
|
+
private clearIdleTimer;
|
|
429
|
+
/** 意外死亡后的回收:留池只换取一次 reconnect 机会,不得超过一段 idle TTL(R2 复核 P0)。
|
|
430
|
+
* 否则死会话永久占 label + 永久计入 10 配额,Agent 再也开不出新会话。 */
|
|
431
|
+
private armDeathReaper;
|
|
432
|
+
private clearDeathTimer;
|
|
433
|
+
private killTree;
|
|
434
|
+
/** A direct child's close is not proof that its detached process group is gone. */
|
|
435
|
+
private reapGroup;
|
|
436
|
+
}
|
|
437
|
+
//#endregion
|
|
438
|
+
//#region src/remote/target.d.ts
|
|
439
|
+
/** 解析后的传输计划:三种 CLI 传输之一。 */
|
|
440
|
+
type TargetPlan = {
|
|
441
|
+
kind: 'ssh';
|
|
442
|
+
host: string;
|
|
443
|
+
connection?: SshConnection;
|
|
444
|
+
} | {
|
|
445
|
+
kind: 'docker';
|
|
446
|
+
container: string;
|
|
447
|
+
} | {
|
|
448
|
+
kind: 'incus';
|
|
449
|
+
container: string;
|
|
450
|
+
};
|
|
451
|
+
//#endregion
|
|
452
|
+
//#region src/remote/helper.d.ts
|
|
453
|
+
interface HelperManifest {
|
|
454
|
+
format: 1;
|
|
455
|
+
name: string;
|
|
456
|
+
ver: string;
|
|
457
|
+
protocol: number;
|
|
458
|
+
targets: Record<string, {
|
|
459
|
+
file: string;
|
|
460
|
+
bytes: number;
|
|
461
|
+
sha256: string;
|
|
462
|
+
}>;
|
|
463
|
+
}
|
|
464
|
+
interface HelperAssets {
|
|
465
|
+
dir: string;
|
|
466
|
+
manifest: HelperManifest;
|
|
467
|
+
}
|
|
468
|
+
//#endregion
|
|
469
|
+
//#region src/remote/transports.d.ts
|
|
470
|
+
/** Hub PTY 端点事实(ptyEndpoint 的返回形;结构类型,不引 superd-hub)。wsPath 由 transport
|
|
471
|
+
* 侧解析成绝对路径(superd-hub 上下文 = 分叉验证过的解析链;闭包/泵内绝不做按名解析赌注)。 */
|
|
472
|
+
interface HubPtyEndpoint {
|
|
473
|
+
url: string;
|
|
474
|
+
cookie: string;
|
|
475
|
+
wsPath: string;
|
|
476
|
+
}
|
|
477
|
+
/** Hub PTY(0.3.2-c;0.3.2-d F4 修正):会话子进程 = 本地 `script` PTY 托管的 WS 字节泵
|
|
478
|
+
* (hub-pty-pump.mjs)。与 docker exec 的嵌套 PTY 同形,但泵是哑 node 子进程、不像
|
|
479
|
+
* `ssh -tt` / `docker exec -it` 那样作为前台子进程自己把本地 tty 置 raw——所以本地包装必须
|
|
480
|
+
* `stty raw`:canonical+ISIG 下 0x03 在本地变 SIGINT 杀泵、0x04 变 EOF 结束泵 stdin
|
|
481
|
+
* (F4:input ^C/^D 与 job_kill 会打死整条会话)。raw 只作用于本地半段;对端 script PTY
|
|
482
|
+
* 保持 canonical,^C/^D 在对端产生 SIGINT/EOF 正是我们要的语义(字节原样过线,解释权在
|
|
483
|
+
* 对端)。kill 链 session 组杀 → 泵死 → WS 关 → 对端组杀,双向自然闭合。连接事实走 wrapper
|
|
484
|
+
* 内 env 赋值(cookie 不进 argv、不落 ps)。 */
|
|
485
|
+
declare function buildHubPtyArgv(endpoint: HubPtyEndpoint, assets: {
|
|
486
|
+
pumpPath: string;
|
|
487
|
+
nodePath?: string;
|
|
488
|
+
}): string[];
|
|
489
|
+
//#endregion
|
|
109
490
|
//#region src/remote/copy.d.ts
|
|
110
491
|
interface CopyRequest {
|
|
111
492
|
src: string;
|
|
@@ -117,7 +498,12 @@ interface TransferReceipt {
|
|
|
117
498
|
action: 'copy';
|
|
118
499
|
src: string;
|
|
119
500
|
dst: string;
|
|
120
|
-
|
|
501
|
+
route: 'hub-staged';
|
|
502
|
+
/** S4: tier actually performed — sha256 digests ran and matched, or explicitly skipped. */
|
|
503
|
+
verification: 'sha256' | 'not-applicable';
|
|
504
|
+
/** S3 unified failure envelope. */
|
|
505
|
+
ok: boolean;
|
|
506
|
+
reason?: 'digest-mismatch' | 'staging-error' | 'aborted';
|
|
121
507
|
sourceDigest?: string;
|
|
122
508
|
destinationDigest?: string;
|
|
123
509
|
bytes: number;
|
|
@@ -127,20 +513,6 @@ interface TransferReceipt {
|
|
|
127
513
|
error?: string;
|
|
128
514
|
}
|
|
129
515
|
//#endregion
|
|
130
|
-
//#region src/remote/target.d.ts
|
|
131
|
-
/** 解析后的传输计划:三种 CLI 传输之一。 */
|
|
132
|
-
type TargetPlan = {
|
|
133
|
-
kind: 'ssh';
|
|
134
|
-
host: string;
|
|
135
|
-
connection?: SshConnection;
|
|
136
|
-
} | {
|
|
137
|
-
kind: 'docker';
|
|
138
|
-
container: string;
|
|
139
|
-
} | {
|
|
140
|
-
kind: 'incus';
|
|
141
|
-
container: string;
|
|
142
|
-
};
|
|
143
|
-
//#endregion
|
|
144
516
|
//#region src/remote/native-copy.d.ts
|
|
145
517
|
interface NativeCopyReceipt {
|
|
146
518
|
action: 'copy';
|
|
@@ -154,8 +526,16 @@ interface NativeCopyReceipt {
|
|
|
154
526
|
stdout: string[];
|
|
155
527
|
stderr: string[];
|
|
156
528
|
outputTruncated: boolean;
|
|
157
|
-
/**
|
|
158
|
-
|
|
529
|
+
/** S3/S4 (spec §3.3): verification names the tier actually performed — native routes are exit-code-only (D1=A). */
|
|
530
|
+
verification: 'native-exit-only';
|
|
531
|
+
/** S3 unified failure envelope: all native exits zero. */
|
|
532
|
+
ok: boolean;
|
|
533
|
+
/** Failure class when ok is false. */
|
|
534
|
+
reason?: 'non-zero-exit' | 'aborted';
|
|
535
|
+
/** Human context, e.g. two-segment 'push not started: pull failed' (prose moved out of route, S8). */
|
|
536
|
+
note?: string;
|
|
537
|
+
/** D3 mkdir pre-hop outcome: true = created this call, false = already existed, 'n-a' = skipped or unavailable (detail in note). */
|
|
538
|
+
created?: true | false | 'n-a';
|
|
159
539
|
/** Tool-owned staging/config release: released on normal/observed exit, unknown when a channel was lost. */
|
|
160
540
|
cleanup: 'released' | 'unknown' | 'none-required';
|
|
161
541
|
}
|
|
@@ -203,6 +583,10 @@ interface RsyncReceipt extends RunResult {
|
|
|
203
583
|
transferredBytes?: number;
|
|
204
584
|
/** Two-SSH route actually used, when applicable. */
|
|
205
585
|
route?: 'local-ssh' | 'ssh-ssh-forward' | 'ssh-ssh-stdio';
|
|
586
|
+
/** S3/S4: exit-code-only tier (D1=A) + unified failure envelope. */
|
|
587
|
+
verification: 'native-exit-only';
|
|
588
|
+
ok: boolean;
|
|
589
|
+
reason?: 'non-zero-exit' | 'aborted';
|
|
206
590
|
}
|
|
207
591
|
/**
|
|
208
592
|
* Native rsync with ordered caller options. Local↔SSH runs rsync directly with
|
|
@@ -213,30 +597,6 @@ interface RsyncReceipt extends RunResult {
|
|
|
213
597
|
*/
|
|
214
598
|
declare function runRsync(request: RsyncRequest, source: RsyncEndpoint, destination: RsyncEndpoint, signal: AbortSignal, options?: RelayRsyncOptions): Promise<RsyncReceipt>;
|
|
215
599
|
//#endregion
|
|
216
|
-
//#region src/remote/process.d.ts
|
|
217
|
-
declare const PROCESS_CLEANUP_BOUND_MS: number;
|
|
218
|
-
interface ProcessOptions {
|
|
219
|
-
stdin?: string;
|
|
220
|
-
timeoutSec?: number;
|
|
221
|
-
cwd?: string;
|
|
222
|
-
/** Hub retains raw bytes; native transports retain decoded UTF16 units. */
|
|
223
|
-
unit?: 'bytes' | 'utf16';
|
|
224
|
-
onOutput?: () => void;
|
|
225
|
-
/** Overlay on process.env (tool-built values only, e.g. RSYNC_RSH). */
|
|
226
|
-
env?: NodeJS.ProcessEnv;
|
|
227
|
-
}
|
|
228
|
-
/** Real detached process. Completion includes group cleanup, even after its leader closes. */
|
|
229
|
-
declare function startBinaryProcess(argv: string[], options?: Pick<ProcessOptions, 'cwd' | 'timeoutSec' | 'env'>): {
|
|
230
|
-
stdout: Readable;
|
|
231
|
-
stderr: Readable;
|
|
232
|
-
stdin: Writable;
|
|
233
|
-
cancel(): void;
|
|
234
|
-
done: RemoteProcess['done'];
|
|
235
|
-
diagnostic(): string | undefined;
|
|
236
|
-
};
|
|
237
|
-
/** Text adapter over the same owned process-group lifecycle as binary pipelines. */
|
|
238
|
-
declare function startOneShot(argv: string[], options?: ProcessOptions): RemoteProcess;
|
|
239
|
-
//#endregion
|
|
240
600
|
//#region src/remote/oneshot.d.ts
|
|
241
601
|
interface OneShotOptions {
|
|
242
602
|
stdin?: string;
|
|
@@ -260,7 +620,6 @@ interface ProbeOptions {
|
|
|
260
620
|
//#endregion
|
|
261
621
|
//#region src/remote/roster.d.ts
|
|
262
622
|
interface RosterOptions {
|
|
263
|
-
byosshLabels?: readonly string[];
|
|
264
623
|
/** 测试缝:替代 runOneShot 的容器扫描执行器。 */
|
|
265
624
|
runner?: (argv: string[], opts?: OneShotOptions) => Promise<OneShotResult>;
|
|
266
625
|
/** 测试缝:替代 ~/.ssh/config 读取。 */
|
|
@@ -283,10 +642,25 @@ interface RemoteCallResult {
|
|
|
283
642
|
truncated?: number;
|
|
284
643
|
outputStats?: StreamOutputStats;
|
|
285
644
|
outputStatsUnavailable?: boolean;
|
|
286
|
-
/**
|
|
645
|
+
/** §5.2 回执字段序:session(+label)→ connection → commandId → state 字段(cwd/envDelta/ttlSec/exit)。 */
|
|
287
646
|
session?: string;
|
|
288
|
-
|
|
647
|
+
label?: string;
|
|
648
|
+
connection?: string;
|
|
649
|
+
/** (byo-pty)/(byo-ssh) 来源标注(创建回执与 roster/card;native 回执省略)。 */
|
|
650
|
+
byoTag?: 'byo-pty' | 'byo-ssh';
|
|
651
|
+
commandId?: string;
|
|
652
|
+
envDelta?: EnvDelta;
|
|
653
|
+
/** 引导/教学行;无则省略。 */
|
|
289
654
|
notice?: string;
|
|
655
|
+
/** oneshot 监督路径的如实标注:`superd-run <ver> (<triple>)` 或 `posix-shim`(spec remote-rescope §5)。 */
|
|
656
|
+
runner?: string;
|
|
657
|
+
/** P4/P5(2026-10-19):true = pty 命令仍在前台运行(回执 = handoff),ptyJob 随行供 job 通道接管。 */
|
|
658
|
+
running?: boolean;
|
|
659
|
+
ptyJob?: PtyRunningJob;
|
|
660
|
+
/** 本会话 idle TTL 剩余(秒);回执即状态快照(P2/P3:状态留在上下文里)。 */
|
|
661
|
+
ttlSec?: number;
|
|
662
|
+
/** 预热(创建形无 cmd)回执 = true。 */
|
|
663
|
+
created?: boolean;
|
|
290
664
|
}
|
|
291
665
|
interface RemoteAuditRecord {
|
|
292
666
|
target: string;
|
|
@@ -303,39 +677,54 @@ interface RemoteDriverOptions {
|
|
|
303
677
|
getHub?: () => HubRemoteTransport | undefined;
|
|
304
678
|
execTimeoutSec?: number;
|
|
305
679
|
idleTtlSec?: number;
|
|
306
|
-
maxOutputChars?: number;
|
|
307
680
|
onAudit?: (r: RemoteAuditRecord) => void;
|
|
308
681
|
oneshotArgvFor?: (plan: TargetPlan, cmd: string, options: {
|
|
309
682
|
cleanupTag?: string;
|
|
310
683
|
}) => string[];
|
|
311
684
|
ptyArgvFor?: (plan: TargetPlan) => string[];
|
|
312
685
|
spawnArgvFor?: (spawnCommand: string) => string[];
|
|
686
|
+
/** 测试/验收缝:hub PTY 泵 argv(默认 buildHubPtyArgv + 宿主树 ws 解析)。 */
|
|
687
|
+
hubPtyArgvFor?: (endpoint: HubPtyEndpoint) => string[];
|
|
313
688
|
probeRunner?: ProbeOptions['runner'];
|
|
314
|
-
/**
|
|
689
|
+
/** 测试/验收缝:helper 资产来源(默认 lib 旁挂 helper-bin);显式 null 强制 shim 路径。 */
|
|
690
|
+
helperAssetsFor?: () => HelperAssets | null;
|
|
691
|
+
/** 测试缝:roster 扫描执行器(裸名解析复用)。 */
|
|
315
692
|
rosterRunner?: RosterOptions['runner'];
|
|
316
|
-
/** 测试缝:ssh config
|
|
693
|
+
/** 测试缝:ssh config 读取(裸名解析复用)。 */
|
|
317
694
|
sshConfigReader?: () => Promise<string>;
|
|
318
695
|
}
|
|
319
|
-
/**
|
|
696
|
+
/** hub PTY 泵资产:pump 与本模块同目录(npm 包与 Super 闭包同构,helper.ts 同款纪律)。
|
|
697
|
+
* ws 模块路径由 transport 侧(superd-hub 上下文,分叉的 proven 解析链)解析后经
|
|
698
|
+
* ptyEndpoint 传入——闭包自身子树无可解析的 ws,按名解析不在闭包里做(0.3.2-c 定稿)。 */
|
|
699
|
+
declare function hubPtyAssets(): {
|
|
700
|
+
pumpPath: string;
|
|
701
|
+
};
|
|
702
|
+
/** 双轨调度器:参数校验 → 目标语法(parseTargetForm)→ 统一 label 池 → oneshot 子进程 / pty 会话池。 */
|
|
320
703
|
declare class RemoteDriver {
|
|
321
704
|
private readonly opts;
|
|
322
|
-
private readonly sshTargets;
|
|
323
705
|
private readonly pool;
|
|
706
|
+
private readonly labels;
|
|
324
707
|
private readonly hubOwner;
|
|
325
708
|
private readonly hubProviders;
|
|
326
709
|
private readonly processes;
|
|
327
710
|
private readonly starting;
|
|
328
711
|
private readonly fileAbort;
|
|
329
712
|
private disposed;
|
|
713
|
+
/** undefined = 未尝试;null = 资产缺失(shim-only);registry = 每 target sticky 状态机。 */
|
|
714
|
+
private helpers;
|
|
715
|
+
private readonly runnerOf;
|
|
330
716
|
private disposal;
|
|
717
|
+
private readonly ptyIdleTtlSec;
|
|
331
718
|
constructor(opts?: RemoteDriverOptions);
|
|
332
719
|
call(params: RemoteCallParams, callCtx?: {
|
|
333
720
|
sessionKey?: string;
|
|
721
|
+
ptyBackground?: boolean;
|
|
722
|
+
commandId?: string;
|
|
334
723
|
}): Promise<RemoteCallResult>;
|
|
335
|
-
/**
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
724
|
+
/** 参数互斥矩阵(§2):spawn/ssh 是 BYO 入口(参数在场即 BYO),只与对应形态的 target 配对。 */
|
|
725
|
+
private validate;
|
|
726
|
+
private execute;
|
|
727
|
+
/** Native-first copy routing (spec: remote-native-shortcut) — unchanged by the workbench round. */
|
|
339
728
|
copy(request: CopyRequest & {
|
|
340
729
|
argv?: unknown;
|
|
341
730
|
pullArgv?: unknown;
|
|
@@ -347,160 +736,96 @@ declare class RemoteDriver {
|
|
|
347
736
|
sessionKey?: string;
|
|
348
737
|
}): Promise<RsyncReceipt>;
|
|
349
738
|
/** Only called from JobSpec.run: admission precedes local file reads and discovery. */
|
|
350
|
-
start(input: RemoteInput, signal: AbortSignal
|
|
739
|
+
start(input: RemoteInput, signal: AbortSignal, callCtx?: {
|
|
740
|
+
sessionKey?: string;
|
|
741
|
+
}): Promise<RemoteProcess>;
|
|
351
742
|
private startPrepared;
|
|
352
743
|
private nativeProcess;
|
|
744
|
+
/** Helper bootstrap is best-effort and sticky: any failure parks null for this driver
|
|
745
|
+
* lifetime and the shim stays the path. First call to a target pays probe (+ upload). */
|
|
746
|
+
private ensureHelper;
|
|
747
|
+
private helperExec;
|
|
353
748
|
private own;
|
|
354
|
-
/**
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
private
|
|
361
|
-
/**
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
749
|
+
/** 现场采集机器面并 merge 进本 session 注册表(ssh → docker → incus → hub,迟到者加前缀)。错误逐段吞掉(roster 另行如实呈现)。 */
|
|
750
|
+
private refreshMachines;
|
|
751
|
+
/** 池寻址:命中即回;miss 现场采集一次再寻址(docker 容器名不经 roster 也可达)。 */
|
|
752
|
+
private resolvePoolEntry;
|
|
753
|
+
private planOf;
|
|
754
|
+
/** ssh:<name> 的池感知解析:BYO 身份 → 其 connection;否则按 config 别名/主机名。 */
|
|
755
|
+
private sshPlanFor;
|
|
756
|
+
/** BYO ssh 注册(v2:无 spec 对比——label 占用即拒;注册成功才认领)。返回实际名(label 或 s-id)。 */
|
|
757
|
+
private registerByoSsh;
|
|
758
|
+
/** PTY 会话创建(native/spawn 同一形状):上限 → label 认领 → 惰性会话(失败由 onDead 释放 label)。 */
|
|
759
|
+
private createSession;
|
|
760
|
+
private ttlMinutes;
|
|
761
|
+
/** connection 由 BYO ssh 身份建立 → card 面标 `(built on)`(与 roster 同词,R2 复核 P2-10)。 */
|
|
762
|
+
private isBuiltOn;
|
|
763
|
+
/** PTY 创建形唯一实现(execute 与 background 预建共用):spawn BYO / ssh BYO / native `<transport>:pty`。 */
|
|
764
|
+
private createPtyLane;
|
|
765
|
+
/** background PTY lane:会话先占位(不拨号)再进官方 jobs registry——首回执必须能寻址;
|
|
766
|
+
* registry 拒绝时把新建的会话拆掉(复用形的会话绝不拆)。返回 undefined = 走普通 oneshot job。 */
|
|
767
|
+
preparePtyLane(params: RemoteCallParams, callCtx?: {
|
|
768
|
+
sessionKey?: string;
|
|
769
|
+
}): Promise<{
|
|
770
|
+
input: RemoteInput;
|
|
771
|
+
session: string;
|
|
772
|
+
connection: string;
|
|
773
|
+
label?: string;
|
|
774
|
+
cleanup: () => void;
|
|
775
|
+
} | undefined>;
|
|
776
|
+
/** `pty:<id|label>` 寻址:先 id 后 label;miss 给重建形式。 */
|
|
777
|
+
private resolvePty;
|
|
778
|
+
/** §6 close:默认撞 detached job 报错(列杀法);force = 杀组+关闭(披露 killed)。幂等 not-found。 */
|
|
779
|
+
closePty(selector: string, sessionKey: string, force?: boolean): {
|
|
780
|
+
session: string;
|
|
781
|
+
connection: string;
|
|
782
|
+
closed: boolean;
|
|
783
|
+
reason?: string;
|
|
784
|
+
killed: string[];
|
|
785
|
+
message?: string;
|
|
786
|
+
};
|
|
787
|
+
/** job 通道收养回填(timeout handoff 时 registry id ≠ commandId,账本记录两者)。 */
|
|
788
|
+
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 供工具层渲染。 */
|
|
793
|
+
input(target: string, options: PtyInputOptions, callCtx?: {
|
|
794
|
+
sessionKey?: string;
|
|
795
|
+
}): Promise<PtyInputReceipt & {
|
|
796
|
+
connection: string;
|
|
797
|
+
label?: string;
|
|
798
|
+
}>;
|
|
799
|
+
private dispatchPty;
|
|
800
|
+
/** 预热(创建形无 cmd)回执:§3——无 commandId/envDelta;timeout 忽略。 */
|
|
801
|
+
private warmReceipt;
|
|
802
|
+
/** session card 回执(`pty:<id|label>` 无 cmd):connection/state/cwd + 最近 20 条账本(不带输出尾,§9 Q7)。 */
|
|
803
|
+
private cardReceipt;
|
|
804
|
+
private oneshot;
|
|
805
|
+
private hubOneshot;
|
|
806
|
+
private hubOneshotProcess;
|
|
807
|
+
/** Ruling P19 + §2.5:roster = 注意力入口——本地扫描刷新统一池,零拨号;机器面公共,会话面 caller-scoped。 */
|
|
365
808
|
roster(callCtx?: {
|
|
366
809
|
sessionKey?: string;
|
|
367
810
|
}): Promise<string>;
|
|
811
|
+
/** status probe(target 无 cmd):机器面 = probe + 该 connection 上的会话;pty selector = session card。 */
|
|
368
812
|
status(target: string, callCtx?: {
|
|
369
813
|
sessionKey?: string;
|
|
370
814
|
}): Promise<string>;
|
|
371
|
-
/**
|
|
372
|
-
private ptyStatus;
|
|
373
|
-
/** Ruling 13:审计 best-effort——钩子抛错不得影响命令路径(成功被毒化成失败+双重审计)。 */
|
|
815
|
+
/** Ruling 13:审计 best-effort——钩子抛错不得影响命令路径。 */
|
|
374
816
|
private audit;
|
|
375
|
-
/**
|
|
376
|
-
registerSsh(target: string, connection: SshConnection): string;
|
|
377
|
-
private byosshPlan;
|
|
378
|
-
/** Single target resolver for later copy/rsync; BYO identities cannot be
|
|
379
|
-
* independently re-resolved through the origin's alias table. */
|
|
817
|
+
/** Single target resolver for later copy/rsync; PTY sessions are not filesystem connections. */
|
|
380
818
|
resolveConnectionTarget(target: string, callCtx?: {
|
|
381
819
|
sessionKey?: string;
|
|
382
820
|
}): Promise<TargetPlan>;
|
|
383
|
-
|
|
384
|
-
private
|
|
385
|
-
/** BYO-PTY 通道:label 即池键(agent 前缀之外),spawn 只在 label 尚不存在时被接受。
|
|
386
|
-
* 三分支 —— 建(无会话)/ 复用(无 spawn,或有 spawn 且与创建来源相同)/ **冲突(有 spawn 且来源不同:不执行任何命令)**。 */
|
|
387
|
-
private ptyCall;
|
|
821
|
+
/** P2/P3:回执即状态快照——idle TTL 剩余随每次 pty 回执带回。 */
|
|
822
|
+
private ptyTtl;
|
|
388
823
|
hasHub(): boolean;
|
|
389
824
|
private requireHub;
|
|
390
825
|
private assertOpen;
|
|
391
826
|
dispose(): Promise<void>;
|
|
392
827
|
}
|
|
393
828
|
//#endregion
|
|
394
|
-
//#region src/remote/hub-contract.d.ts
|
|
395
|
-
interface RemoteInput {
|
|
396
|
-
target?: string;
|
|
397
|
-
spawn?: string;
|
|
398
|
-
ssh?: SshConnection;
|
|
399
|
-
cmd?: string;
|
|
400
|
-
script?: string;
|
|
401
|
-
stdin?: string;
|
|
402
|
-
mode?: 'oneshot' | 'pty';
|
|
403
|
-
timeout?: number;
|
|
404
|
-
}
|
|
405
|
-
interface PreparedRemoteInput {
|
|
406
|
-
target: string;
|
|
407
|
-
spawn?: string;
|
|
408
|
-
ssh?: SshConnection;
|
|
409
|
-
cmd: string;
|
|
410
|
-
stdin?: string;
|
|
411
|
-
mode?: 'oneshot' | 'pty';
|
|
412
|
-
timeout?: number;
|
|
413
|
-
}
|
|
414
|
-
/** Counters exclude diagnostic banners. dropped is ring eviction; total-returned is all omitted output. */
|
|
415
|
-
type OutputStats = {
|
|
416
|
-
unit: 'utf16' | 'bytes';
|
|
417
|
-
total: number;
|
|
418
|
-
retained: number;
|
|
419
|
-
dropped: number;
|
|
420
|
-
returned: number;
|
|
421
|
-
retentionLimit: number;
|
|
422
|
-
};
|
|
423
|
-
type StreamOutputStats = {
|
|
424
|
-
stdout: OutputStats;
|
|
425
|
-
stderr?: OutputStats;
|
|
426
|
-
};
|
|
427
|
-
interface RemoteProcess {
|
|
428
|
-
cancel(reason?: string): void;
|
|
429
|
-
done: Promise<{
|
|
430
|
-
exit: number | null;
|
|
431
|
-
timedOut: boolean;
|
|
432
|
-
durationMs: number;
|
|
433
|
-
cancelled?: boolean;
|
|
434
|
-
}>;
|
|
435
|
-
/** diagnostic is executor-generated text, not process output; excluded from byte cursor and counters. */
|
|
436
|
-
read(channel: 'stdout' | 'stderr', fromByte: number): {
|
|
437
|
-
text: string;
|
|
438
|
-
nextOffset: number;
|
|
439
|
-
lossy: boolean;
|
|
440
|
-
stats?: OutputStats;
|
|
441
|
-
diagnostic?: string;
|
|
442
|
-
};
|
|
443
|
-
}
|
|
444
|
-
interface BinaryFileEndpoint {
|
|
445
|
-
exportTree(path: string, signal: AbortSignal): Promise<NodeJS.ReadableStream>;
|
|
446
|
-
importTree(path: string, source: NodeJS.ReadableStream, options: {
|
|
447
|
-
mkdir: boolean;
|
|
448
|
-
signal: AbortSignal;
|
|
449
|
-
}): Promise<void>;
|
|
450
|
-
digest(path: string, signal: AbortSignal, selection?: readonly string[]): Promise<{
|
|
451
|
-
sha256: string;
|
|
452
|
-
bytes: number;
|
|
453
|
-
entries: number;
|
|
454
|
-
}>;
|
|
455
|
-
}
|
|
456
|
-
interface HubTarget {
|
|
457
|
-
id: string;
|
|
458
|
-
label: string;
|
|
459
|
-
execEnabled: boolean;
|
|
460
|
-
}
|
|
461
|
-
interface HubRemoteTransport {
|
|
462
|
-
protocol: 1;
|
|
463
|
-
listTargets(): readonly HubTarget[];
|
|
464
|
-
start(machine: string, input: PreparedRemoteInput, owner: string): Promise<RemoteProcess>;
|
|
465
|
-
pty(machine: string, cmd: string, owner: string, options: {
|
|
466
|
-
stdin?: string;
|
|
467
|
-
timeout?: number;
|
|
468
|
-
}): Promise<RemoteCallResult>;
|
|
469
|
-
fileEndpoint(machine: string): BinaryFileEndpoint;
|
|
470
|
-
releaseOwner(owner: string): Promise<void>;
|
|
471
|
-
}
|
|
472
|
-
//#endregion
|
|
473
|
-
//#region src/remote/output-ring.d.ts
|
|
474
|
-
/** Byte-addressed decoded output: mid-codepoint cursors skip forward and explicitly report loss. */
|
|
475
|
-
declare function readUtf8Tail(bytes: Buffer, totalBytes: number, fromByte: number): {
|
|
476
|
-
text: string;
|
|
477
|
-
nextOffset: number;
|
|
478
|
-
lossy: boolean;
|
|
479
|
-
};
|
|
480
|
-
/** Native/PTY retention is UTF16 units; cursor offsets remain real UTF8 bytes. Input is decoded text. */
|
|
481
|
-
declare class Utf16TailRing {
|
|
482
|
-
readonly capacity: number;
|
|
483
|
-
text: string;
|
|
484
|
-
total: number;
|
|
485
|
-
private totalBytes;
|
|
486
|
-
constructor(capacity?: number);
|
|
487
|
-
push(text: string): void;
|
|
488
|
-
stats(returned?: number): OutputStats;
|
|
489
|
-
read(fromByte: number): ReturnType<typeof readUtf8Tail>;
|
|
490
|
-
}
|
|
491
|
-
/** Raw byte retention for Hub oneshot. Tail/read starts skip partial UTF8 prefixes, never invent replacement characters. */
|
|
492
|
-
declare class ByteTailRing {
|
|
493
|
-
readonly capacity: number;
|
|
494
|
-
total: number;
|
|
495
|
-
private chunks;
|
|
496
|
-
private retained;
|
|
497
|
-
constructor(capacity?: number);
|
|
498
|
-
push(chunk: Buffer): void;
|
|
499
|
-
tail(maxBytes?: number): Buffer;
|
|
500
|
-
stats(returned?: number): OutputStats;
|
|
501
|
-
read(fromByte: number): ReturnType<typeof readUtf8Tail>;
|
|
502
|
-
}
|
|
503
|
-
//#endregion
|
|
504
829
|
//#region src/remote/jobs.d.ts
|
|
505
830
|
declare module '@deepseek-ai/dsh-jobs' {
|
|
506
831
|
interface JobKindMap {
|
|
@@ -539,7 +864,6 @@ declare const inject: string[];
|
|
|
539
864
|
interface RemoteRowConfig {
|
|
540
865
|
execTimeoutSec: number;
|
|
541
866
|
idleTtlSec: number;
|
|
542
|
-
maxOutputChars: number;
|
|
543
867
|
}
|
|
544
868
|
type RemoteConfigValidator = ((value?: unknown) => RemoteRowConfig) & StandardSchemaV1<unknown, RemoteRowConfig> & NativeConfigSchema;
|
|
545
869
|
declare const Config: RemoteConfigValidator;
|
|
@@ -552,4 +876,4 @@ declare const _default: {
|
|
|
552
876
|
apply: (ctx: Context, config: RemoteRowConfig) => (() => void);
|
|
553
877
|
};
|
|
554
878
|
//#endregion
|
|
555
|
-
export { type BinaryFileEndpoint, ByteTailRing, Config, FILE_FRAME_BYTES, FILE_MAX_ENTRIES, FILE_MAX_METADATA, type HubRemoteTransport, type HubTarget, type OutputStats, PROCESS_CLEANUP_BOUND_MS, type PreparedRemoteInput, RemoteConfigValidator, type RemoteInput, type RemoteProcess, RemoteRowConfig, type RsyncEndpoint, type RsyncReceipt, type RsyncRequest, type SshConnection,
|
|
879
|
+
export { type BinaryFileEndpoint, ByteTailRing, Config, FILE_FRAME_BYTES, FILE_MAX_ENTRIES, FILE_MAX_METADATA, type HubPtyEndpoint, type HubRemoteTransport, type HubTarget, type OutputStats, PROCESS_CLEANUP_BOUND_MS, type PreparedRemoteInput, type PtyDispatchResult, PtySession, RemoteConfigValidator, type RemoteInput, type RemoteProcess, RemoteRowConfig, type RsyncEndpoint, type RsyncReceipt, type RsyncRequest, type SshConnection, type StreamOutputStats, Utf16TailRing, apply, buildHubPtyArgv, checkAbsolute, checkSelection, _default as default, disclose, hubPtyAssets, inject, localFileEndpoint, name, readUtf8Tail, runFileWorker, runRsync, sshArgv, startBinaryProcess, startOneShot, startRemoteJob };
|