super-dsh 0.3.2-d → 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/package.json +1 -1
- package/remote/plugin.d.ts +6 -4
- package/remote/plugin.js +35 -35
- package/remote/provenance.json +6 -6
- package/superd-hub/dist/exec.d.ts +3 -2
- package/superd-hub/dist/exec.js +6 -5
- package/superd-hub/dist/hub-tool.js +6 -6
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "super-dsh",
|
|
3
|
-
"version": "0.3.2-
|
|
3
|
+
"version": "0.3.2-e",
|
|
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",
|
package/remote/plugin.d.ts
CHANGED
|
@@ -239,7 +239,11 @@ declare function startBinaryProcess(argv: string[], options?: Pick<ProcessOption
|
|
|
239
239
|
declare function startOneShot(argv: string[], options?: ProcessOptions): RemoteProcess;
|
|
240
240
|
//#endregion
|
|
241
241
|
//#region src/remote/nonce-framing.d.ts
|
|
242
|
-
|
|
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): {
|
|
243
247
|
text: string;
|
|
244
248
|
truncated?: number;
|
|
245
249
|
stats?: OutputStats;
|
|
@@ -673,7 +677,6 @@ interface RemoteDriverOptions {
|
|
|
673
677
|
getHub?: () => HubRemoteTransport | undefined;
|
|
674
678
|
execTimeoutSec?: number;
|
|
675
679
|
idleTtlSec?: number;
|
|
676
|
-
maxOutputChars?: number;
|
|
677
680
|
onAudit?: (r: RemoteAuditRecord) => void;
|
|
678
681
|
oneshotArgvFor?: (plan: TargetPlan, cmd: string, options: {
|
|
679
682
|
cleanupTag?: string;
|
|
@@ -861,7 +864,6 @@ declare const inject: string[];
|
|
|
861
864
|
interface RemoteRowConfig {
|
|
862
865
|
execTimeoutSec: number;
|
|
863
866
|
idleTtlSec: number;
|
|
864
|
-
maxOutputChars: number;
|
|
865
867
|
}
|
|
866
868
|
type RemoteConfigValidator = ((value?: unknown) => RemoteRowConfig) & StandardSchemaV1<unknown, RemoteRowConfig> & NativeConfigSchema;
|
|
867
869
|
declare const Config: RemoteConfigValidator;
|
|
@@ -874,4 +876,4 @@ declare const _default: {
|
|
|
874
876
|
apply: (ctx: Context, config: RemoteRowConfig) => (() => void);
|
|
875
877
|
};
|
|
876
878
|
//#endregion
|
|
877
|
-
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, hubPtyAssets, inject, localFileEndpoint, name, readUtf8Tail, runFileWorker, runRsync, sshArgv, startBinaryProcess, startOneShot, startRemoteJob
|
|
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 };
|
package/remote/plugin.js
CHANGED
|
@@ -2866,22 +2866,25 @@ function stripAnsi(s) {
|
|
|
2866
2866
|
function normalizePtyText(s) {
|
|
2867
2867
|
return stripAnsi(s).replace(/\r\n/g, "\n").replace(/\r/g, "");
|
|
2868
2868
|
}
|
|
2869
|
-
|
|
2870
|
-
|
|
2871
|
-
|
|
2872
|
-
|
|
2873
|
-
|
|
2874
|
-
|
|
2869
|
+
/** 0.3.2-e:自有 30K 返回窗口已删(原生 agent runtime 的 spill/输出保护接管模型上下文
|
|
2870
|
+
* 尺寸)。本 helper 只做 retention 披露:ring 留存(4M UTF-16 / 4MiB bytes)未驱逐时
|
|
2871
|
+
* 全量透传(returned=retained,无 banner);驱逐(dropped>0,仅 >4M 输出发生)时打一行
|
|
2872
|
+
* banner 且 truncated=原始总量。text 已是 ring 尾部,不再二次裁剪。 */
|
|
2873
|
+
function disclose(text, stats) {
|
|
2874
|
+
if (stats === void 0) return { text };
|
|
2875
|
+
const returned = stats.retained;
|
|
2876
|
+
const updated = { stats: {
|
|
2875
2877
|
...stats,
|
|
2876
2878
|
returned
|
|
2877
2879
|
} };
|
|
2878
|
-
if (
|
|
2879
|
-
text
|
|
2880
|
+
if (stats.dropped <= 0) return {
|
|
2881
|
+
text,
|
|
2880
2882
|
...updated
|
|
2881
2883
|
};
|
|
2884
|
+
const unit = stats.unit === "bytes" ? "bytes" : "chars";
|
|
2882
2885
|
return {
|
|
2883
|
-
text: `[
|
|
2884
|
-
truncated: total,
|
|
2886
|
+
text: `[retention tail: showing last ${stats.retained} of ${stats.total} ${unit}; dropped head ${stats.dropped}, retention limit ${stats.retentionLimit} ${stats.unit === "bytes" ? "bytes" : "UTF-16 code units"}]\n${text}`,
|
|
2887
|
+
truncated: stats.total,
|
|
2885
2888
|
...updated
|
|
2886
2889
|
};
|
|
2887
2890
|
}
|
|
@@ -4149,7 +4152,6 @@ var RemoteDriver = class {
|
|
|
4149
4152
|
}
|
|
4150
4153
|
async execute(params, form, callCtx) {
|
|
4151
4154
|
const timeoutSec = params.timeout ?? this.opts.execTimeoutSec ?? 120;
|
|
4152
|
-
const cap = this.opts.maxOutputChars ?? 3e4;
|
|
4153
4155
|
const sessionKey = callCtx.sessionKey ?? "no-session";
|
|
4154
4156
|
const hasCmd = params.cmd !== void 0 && params.cmd.length > 0;
|
|
4155
4157
|
params.spawn !== void 0 && params.spawn.length;
|
|
@@ -4165,8 +4167,8 @@ var RemoteDriver = class {
|
|
|
4165
4167
|
if (this.disposed) process$1.cancel("owner disposed");
|
|
4166
4168
|
const result = await process$1.done;
|
|
4167
4169
|
const stdout = process$1.read("stdout", 0), stderr = process$1.read("stderr", 0);
|
|
4168
|
-
const out =
|
|
4169
|
-
const err =
|
|
4170
|
+
const out = disclose(stdout.text, stdout.stats);
|
|
4171
|
+
const err = disclose(stderr.text, stderr.stats);
|
|
4170
4172
|
return {
|
|
4171
4173
|
...result,
|
|
4172
4174
|
mode: "oneshot",
|
|
@@ -4191,7 +4193,7 @@ var RemoteDriver = class {
|
|
|
4191
4193
|
await session.warm();
|
|
4192
4194
|
return this.warmReceipt(session);
|
|
4193
4195
|
}
|
|
4194
|
-
return await this.dispatchPty(session, params, callCtx, timeoutSec
|
|
4196
|
+
return await this.dispatchPty(session, params, callCtx, timeoutSec);
|
|
4195
4197
|
}
|
|
4196
4198
|
if (params.ssh !== void 0) {
|
|
4197
4199
|
const label = form.form === "direct" || form.form === "bare" ? form.name : void 0;
|
|
@@ -4212,28 +4214,28 @@ var RemoteDriver = class {
|
|
|
4212
4214
|
kind: "ssh",
|
|
4213
4215
|
host: normalizeSshConnection(params.ssh).host,
|
|
4214
4216
|
connection: normalizeSshConnection(params.ssh)
|
|
4215
|
-
}, `ssh:${name$1}`, params, timeoutSec
|
|
4217
|
+
}, `ssh:${name$1}`, params, timeoutSec);
|
|
4216
4218
|
}
|
|
4217
4219
|
if (form.form === "pty-selector" && form.idOrLabel === void 0) throw new Error("[E_PARAMS] remote: \"pty\" alone selects nothing — append an id/label (pty:pty-1a2b, pty:build) or pass spawn to create one");
|
|
4218
4220
|
if (form.form === "pty-selector") {
|
|
4219
4221
|
const session = this.resolvePty(form.idOrLabel, sessionKey);
|
|
4220
4222
|
if (!hasCmd) return this.cardReceipt(session);
|
|
4221
|
-
return await this.dispatchPty(session, params, callCtx, timeoutSec
|
|
4223
|
+
return await this.dispatchPty(session, params, callCtx, timeoutSec);
|
|
4222
4224
|
}
|
|
4223
4225
|
if (form.form === "direct") {
|
|
4224
4226
|
const plan$1 = form.transport === "ssh" ? this.sshPlanFor(form.name, sessionKey) : resolveTarget(`${form.transport}:${form.name}`);
|
|
4225
|
-
return await this.oneshot(plan$1, `${form.transport}:${form.name}`, params, timeoutSec
|
|
4227
|
+
return await this.oneshot(plan$1, `${form.transport}:${form.name}`, params, timeoutSec);
|
|
4226
4228
|
}
|
|
4227
4229
|
if (form.form !== "bare") throw new Error("[E_INTERNAL] remote: unreachable target form after routing");
|
|
4228
4230
|
const entry = await this.resolvePoolEntry(form.name, sessionKey);
|
|
4229
4231
|
if (entry.kind === "pty") {
|
|
4230
4232
|
const session = this.resolvePty(form.name, sessionKey);
|
|
4231
4233
|
if (!hasCmd) return this.cardReceipt(session);
|
|
4232
|
-
return await this.dispatchPty(session, params, callCtx, timeoutSec
|
|
4234
|
+
return await this.dispatchPty(session, params, callCtx, timeoutSec);
|
|
4233
4235
|
}
|
|
4234
|
-
if (entry.kind === "hub") return await this.hubOneshot(entry.machine, `hub:${entry.machine}`, params, timeoutSec
|
|
4236
|
+
if (entry.kind === "hub") return await this.hubOneshot(entry.machine, `hub:${entry.machine}`, params, timeoutSec);
|
|
4235
4237
|
const plan = this.planOf(entry);
|
|
4236
|
-
return await this.oneshot(plan, form.name, params, timeoutSec
|
|
4238
|
+
return await this.oneshot(plan, form.name, params, timeoutSec);
|
|
4237
4239
|
}
|
|
4238
4240
|
/** Native-first copy routing (spec: remote-native-shortcut) — unchanged by the workbench round. */
|
|
4239
4241
|
copy(request, signal, callCtx = {}) {
|
|
@@ -4802,7 +4804,7 @@ var RemoteDriver = class {
|
|
|
4802
4804
|
...id.label !== void 0 ? { label: id.label } : {}
|
|
4803
4805
|
};
|
|
4804
4806
|
}
|
|
4805
|
-
async dispatchPty(session, params, callCtx, timeoutSec
|
|
4807
|
+
async dispatchPty(session, params, callCtx, timeoutSec) {
|
|
4806
4808
|
const hubConn = session.identity.connection;
|
|
4807
4809
|
if (hubConn.startsWith("hub:")) {
|
|
4808
4810
|
const hub = this.requireHub();
|
|
@@ -4819,7 +4821,7 @@ var RemoteDriver = class {
|
|
|
4819
4821
|
jobId: commandId
|
|
4820
4822
|
} : {}
|
|
4821
4823
|
});
|
|
4822
|
-
const out =
|
|
4824
|
+
const out = disclose(r.output, r.outputStats?.stdout);
|
|
4823
4825
|
const id = session.identity;
|
|
4824
4826
|
return {
|
|
4825
4827
|
mode: "pty",
|
|
@@ -4887,7 +4889,7 @@ var RemoteDriver = class {
|
|
|
4887
4889
|
...this.ptyTtl(session.key)
|
|
4888
4890
|
};
|
|
4889
4891
|
}
|
|
4890
|
-
async oneshot(plan, display, params, timeoutSec
|
|
4892
|
+
async oneshot(plan, display, params, timeoutSec) {
|
|
4891
4893
|
this.assertOpen();
|
|
4892
4894
|
const process$1 = this.own(await this.nativeProcess(plan, params, timeoutSec));
|
|
4893
4895
|
if (this.disposed) process$1.cancel("owner disposed");
|
|
@@ -4902,8 +4904,8 @@ var RemoteDriver = class {
|
|
|
4902
4904
|
stderr: stderr.stats
|
|
4903
4905
|
}
|
|
4904
4906
|
};
|
|
4905
|
-
const out =
|
|
4906
|
-
const err = r.stderr.length > 0 ?
|
|
4907
|
+
const out = disclose(r.stdout, r.outputStats?.stdout);
|
|
4908
|
+
const err = r.stderr.length > 0 ? disclose(r.stderr, r.outputStats?.stderr) : void 0;
|
|
4907
4909
|
return {
|
|
4908
4910
|
mode: "oneshot",
|
|
4909
4911
|
target: display,
|
|
@@ -4922,13 +4924,13 @@ var RemoteDriver = class {
|
|
|
4922
4924
|
...this.runnerOf.get(process$1) === void 0 ? {} : { runner: this.runnerOf.get(process$1) }
|
|
4923
4925
|
};
|
|
4924
4926
|
}
|
|
4925
|
-
async hubOneshot(machine, display, params, timeoutSec
|
|
4927
|
+
async hubOneshot(machine, display, params, timeoutSec) {
|
|
4926
4928
|
const process$1 = this.own(await this.hubOneshotProcess(machine, params));
|
|
4927
4929
|
if (this.disposed) process$1.cancel("owner disposed");
|
|
4928
4930
|
const result = await process$1.done;
|
|
4929
4931
|
const stdout = process$1.read("stdout", 0), stderr = process$1.read("stderr", 0);
|
|
4930
|
-
const out =
|
|
4931
|
-
const err =
|
|
4932
|
+
const out = disclose(stdout.text, stdout.stats);
|
|
4933
|
+
const err = disclose(stderr.text, stderr.stats);
|
|
4932
4934
|
return {
|
|
4933
4935
|
...result,
|
|
4934
4936
|
mode: "oneshot",
|
|
@@ -5270,7 +5272,7 @@ PTY:
|
|
|
5270
5272
|
- input is verbatim: "\\n" submits; "\\u0003" Ctrl-C; "\\u0004" Ctrl-D; "" writes nothing. Ctrl-D follows terminal EOF rules.
|
|
5271
5273
|
- commandId, if supplied, must match running command.
|
|
5272
5274
|
- Input receipt confirms write only; read result via SAME job.
|
|
5273
|
-
- Output
|
|
5275
|
+
- Output returns in full up to retention (4M chars per stream; Hub oneshot 4MiB bytes) — beyond it the retained tail plus outputStats. Redirect bulk output to files.
|
|
5274
5276
|
- Idle expiry: 15 min; running commands exempt.
|
|
5275
5277
|
|
|
5276
5278
|
Oneshot:
|
|
@@ -5735,7 +5737,7 @@ function renderValue(v) {
|
|
|
5735
5737
|
markers.push(`${secs}s`);
|
|
5736
5738
|
if (v.running === true) markers.push(`still running — poll job_output${v.jobId !== void 0 ? ` ${v.jobId}` : ""}`);
|
|
5737
5739
|
if (v.truncated !== void 0) markers.push(`truncated, ${v.outputStatsUnavailable ? "returned peer tail" : "original"} ${v.truncated} ${v.outputStats?.stdout.unit === "bytes" ? "bytes" : "chars"}`);
|
|
5738
|
-
if (v.outputStatsUnavailable) markers.push("peer output totals/retention unavailable
|
|
5740
|
+
if (v.outputStatsUnavailable) markers.push("peer output totals/retention unavailable");
|
|
5739
5741
|
parts.push(`[${markers.join(" · ")}]`);
|
|
5740
5742
|
if (v.runner === "posix-shim" && (v.exit !== null && v.exit !== 0 || v.timedOut === true)) parts.push("note: this oneshot ran through the POSIX fallback on this target; PTY lanes use an independent lane and may still work here");
|
|
5741
5743
|
if (v.stderr !== void 0 && v.stderr.length > 0) parts.push("[stderr]", v.stderr);
|
|
@@ -6001,12 +6003,10 @@ const name = "dashr-remote";
|
|
|
6001
6003
|
const inject = [];
|
|
6002
6004
|
const Config = Schema.object({
|
|
6003
6005
|
execTimeoutSec: Schema.natural().min(1).default(120),
|
|
6004
|
-
idleTtlSec: Schema.natural().min(1).default(REMOTE_PTY_IDLE_TTL_SEC)
|
|
6005
|
-
maxOutputChars: Schema.natural().min(1).default(3e4)
|
|
6006
|
+
idleTtlSec: Schema.natural().min(1).default(REMOTE_PTY_IDLE_TTL_SEC)
|
|
6006
6007
|
}).default({
|
|
6007
6008
|
execTimeoutSec: 120,
|
|
6008
|
-
idleTtlSec: REMOTE_PTY_IDLE_TTL_SEC
|
|
6009
|
-
maxOutputChars: 3e4
|
|
6009
|
+
idleTtlSec: REMOTE_PTY_IDLE_TTL_SEC
|
|
6010
6010
|
});
|
|
6011
6011
|
/** MUST stay an arrow(RM0 plugin.ts 同注:function 声明会被 cordis 当构造器 new 掉,返回的 disposer 丢失)。 */
|
|
6012
6012
|
const apply = (ctx, config) => {
|
|
@@ -6020,4 +6020,4 @@ var plugin_default = {
|
|
|
6020
6020
|
};
|
|
6021
6021
|
|
|
6022
6022
|
//#endregion
|
|
6023
|
-
export { ByteTailRing, Config, FILE_FRAME_BYTES, FILE_MAX_ENTRIES, FILE_MAX_METADATA, PROCESS_CLEANUP_BOUND_MS, PtySession, Utf16TailRing, apply, buildHubPtyArgv, checkAbsolute, checkSelection, plugin_default as default, hubPtyAssets, inject, localFileEndpoint, name, readUtf8Tail, runFileWorker, runRsync, sshArgv, startBinaryProcess, startOneShot, startRemoteJob
|
|
6023
|
+
export { ByteTailRing, Config, FILE_FRAME_BYTES, FILE_MAX_ENTRIES, FILE_MAX_METADATA, PROCESS_CLEANUP_BOUND_MS, PtySession, Utf16TailRing, apply, buildHubPtyArgv, checkAbsolute, checkSelection, plugin_default as default, disclose, hubPtyAssets, inject, localFileEndpoint, name, readUtf8Tail, runFileWorker, runRsync, sshArgv, startBinaryProcess, startOneShot, startRemoteJob };
|
package/remote/provenance.json
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
"better-dsh/src/remote/agent-registration.ts": "cb08eb9f5d592201054410da69b3bf383e2604899d9494a8cbd8ba2f86b3f7ad",
|
|
7
7
|
"better-dsh/src/remote/archive.ts": "fd32f96dc63421be7d56eb545badf355c6ee2498599605ffa48958b9efca9a63",
|
|
8
8
|
"better-dsh/src/remote/copy.ts": "ab2aec5ee8df814f4bc568370977d229c402489248c738eff147431a52650c52",
|
|
9
|
-
"better-dsh/src/remote/driver.ts": "
|
|
9
|
+
"better-dsh/src/remote/driver.ts": "8bfa05e056b9099a1d9fcdf6cb67d15ec6e9a895ea061ea2e65cd3a513fe4fdf",
|
|
10
10
|
"better-dsh/src/remote/endpoints.ts": "e4ab0fa1afcee815ad78976eba4036e2ed2b21eaea11f7451874b56229f12eac",
|
|
11
11
|
"better-dsh/src/remote/file-worker.ts": "31ac019a944cf7fdcd0ff044f8b330d923bf4d384c77056f9b7e3032bc8c9598",
|
|
12
12
|
"better-dsh/src/remote/helper.ts": "789a802610fc480bb1c922dd284787ca22d7394fa906c729ee33d78ade79973c",
|
|
@@ -16,10 +16,10 @@
|
|
|
16
16
|
"better-dsh/src/remote/jobs.ts": "4556bd9f30580a8bf90800c7a945282e276abb548df6db7fe95e7091bb1543c6",
|
|
17
17
|
"better-dsh/src/remote/labels.ts": "d9dcfdc1c6bb292b37d3250e7897b239c416b55b3102943bcc4f1d0ce7d2e709",
|
|
18
18
|
"better-dsh/src/remote/native-copy.ts": "3f8691abb14dfb7a94e956956fb4d182b7732ffbe70f1a8ff7dec5dd2b9afb7c",
|
|
19
|
-
"better-dsh/src/remote/nonce-framing.ts": "
|
|
19
|
+
"better-dsh/src/remote/nonce-framing.ts": "2f2f80d6aa9934f96ba171d575dbe4cddbe2e127da3b0eec3032c5ea522cadc3",
|
|
20
20
|
"better-dsh/src/remote/oneshot.ts": "99f2c809ba1159c7865ec3cff2e6d7b1f165a7f03185a6fc9505c1a534ba57bc",
|
|
21
21
|
"better-dsh/src/remote/output-ring.ts": "a79104bd3dcddab06a3fe7e52d239a70becd4f2dcddd0c9b6513f5fe3c4ed0bc",
|
|
22
|
-
"better-dsh/src/remote/plugin.ts": "
|
|
22
|
+
"better-dsh/src/remote/plugin.ts": "da6b985cd013ffc253ee8cf5605dc2d729e26534139dd28269db5d246511fac9",
|
|
23
23
|
"better-dsh/src/remote/process.ts": "f4491c76457b662703e0b1e4a876299b9c8b7b3da5b304c6baee5576017de448",
|
|
24
24
|
"better-dsh/src/remote/pty-session.ts": "3cb07345b90f0e54cbcea00204ae0b5346d9bb6edf3a784f009fc1b07357f799",
|
|
25
25
|
"better-dsh/src/remote/roster.ts": "b84f75edc87550bb96803042487cfd7c39135b1710ff9715dd5ca402df0aa378",
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"better-dsh/src/remote/ssh-targets.ts": "2a7e754fc26cf34e05ffb5d7f7406f35c09fd0770684db904dbf4c56d2c00beb",
|
|
32
32
|
"better-dsh/src/remote/status.ts": "e144c1cf98388dbaca8dab5622e6e37ceac85d898119e37d07f88e129113a82e",
|
|
33
33
|
"better-dsh/src/remote/target.ts": "bce47c6c61975a52e5cb77a6b727f68cbe78ecdcb3866c237fb932444ecc954e",
|
|
34
|
-
"better-dsh/src/remote/tool.ts": "
|
|
34
|
+
"better-dsh/src/remote/tool.ts": "ecb431c4b1dfa4981063ea78b90288ac9ac12070c08a113b51602f18887f194b",
|
|
35
35
|
"better-dsh/src/remote/transfer-tool.ts": "d02b216a31314e98fdf6933230b57adce58b9c8aebe9798aae7be808105b41e2",
|
|
36
36
|
"better-dsh/src/remote/transports.ts": "8a7190d6013f12901d9007e6b30708645baa4aa0770fcb1087ae6fcde656a8d0",
|
|
37
37
|
"better-dsh/third_party/schemastery/lib/index.cjs": "aca1c1a47c7b6034feee01501aefca3e6dd97a0bac4fe334fd30647ae5a9e480",
|
|
@@ -71,7 +71,7 @@
|
|
|
71
71
|
"helper-bin/x86_64-unknown-linux-musl/BUILT-VER": "8601d3c2ff79795c9657b02080afffe91c42775534dd6687c6dbdc0f4924db70",
|
|
72
72
|
"helper-bin/x86_64-unknown-linux-musl/superd-run": "05b428657942abf22a0ad609433d5cab6b6182fe389851345459a0274b5a6533",
|
|
73
73
|
"hub-pty-pump.mjs": "dfe0cb331cc585eb4d858fbb6d8f3ff22414f3ee55109c933df0fc14502aee5c",
|
|
74
|
-
"plugin.d.ts": "
|
|
75
|
-
"plugin.js": "
|
|
74
|
+
"plugin.d.ts": "da9bfcbb1a0f37bd2994452ac4cfed284615e5cea45c05ff97569474a442e91f",
|
|
75
|
+
"plugin.js": "8dd1843f2c57097a1bbcfeddaf50193985bf25b942cc784ca501311d16aae7f3"
|
|
76
76
|
}
|
|
77
77
|
}
|
|
@@ -27,8 +27,9 @@ export interface OneShotExecResult {
|
|
|
27
27
|
*/
|
|
28
28
|
outcome: 'exited' | 'signaled' | 'timeout' | 'spawn-error';
|
|
29
29
|
}
|
|
30
|
-
/**
|
|
31
|
-
|
|
30
|
+
/** 0.3.2-e: the 30K returned-tail window is REMOVED — output returns in full up to
|
|
31
|
+
* retention and model-context sizing is the native agent runtime's job (spill policy
|
|
32
|
+
* or its foreign equivalent). Retention below stays the memory-safety bound. */
|
|
32
33
|
/** Hub oneshot per-stream raw-byte retention: 4MiB, distinct from native/PTy UTF16 caps. */
|
|
33
34
|
export declare const EXEC_RING_HARD_CAP: number;
|
|
34
35
|
export declare const EXEC_DEFAULT_TIMEOUT_SEC = 120;
|
package/superd-hub/dist/exec.js
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
// tool); it never decides policy — auth is the shared /api fence's, and the
|
|
6
6
|
// initiator-side per-machine knob lives on the caller's registry row.
|
|
7
7
|
//
|
|
8
|
-
// Output discipline (
|
|
8
|
+
// Output discipline (0.3.2-e): return output IN FULL up to the 4MiB retention ring;
|
|
9
9
|
// each stream, retain at most 4M per stream while running (the tail of a
|
|
10
10
|
// capped ring is still the tail of the stream), mark `truncated` whenever a
|
|
11
11
|
// stream's total exceeded what is returned. Kill discipline: SIGTERM to the
|
|
@@ -15,8 +15,9 @@ import { spawn } from 'node:child_process';
|
|
|
15
15
|
import { ByteTailRing } from '../../remote/plugin.js';
|
|
16
16
|
/** Shared-channel Fetch route path this API owns. */
|
|
17
17
|
export const EXEC_API_BASE = '/api/superd/exec';
|
|
18
|
-
/**
|
|
19
|
-
|
|
18
|
+
/** 0.3.2-e: the 30K returned-tail window is REMOVED — output returns in full up to
|
|
19
|
+
* retention and model-context sizing is the native agent runtime's job (spill policy
|
|
20
|
+
* or its foreign equivalent). Retention below stays the memory-safety bound. */
|
|
20
21
|
/** Hub oneshot per-stream raw-byte retention: 4MiB, distinct from native/PTy UTF16 caps. */
|
|
21
22
|
export const EXEC_RING_HARD_CAP = 4 * 1024 * 1024;
|
|
22
23
|
export const EXEC_DEFAULT_TIMEOUT_SEC = 120;
|
|
@@ -109,7 +110,7 @@ export async function runOneShotExec(input, log) {
|
|
|
109
110
|
clearTimeout(killTimer);
|
|
110
111
|
if (graceTimer !== undefined)
|
|
111
112
|
clearTimeout(graceTimer);
|
|
112
|
-
const outTail = stdout.tail(
|
|
113
|
+
const outTail = stdout.tail(), errTail = stderr.tail();
|
|
113
114
|
const outText = outTail.toString('utf8');
|
|
114
115
|
const errText = spawnError !== undefined
|
|
115
116
|
? `exec: spawn failed — ${spawnError}${input.cwd === undefined ? '' : ` (cwd: ${input.cwd})`}`
|
|
@@ -127,7 +128,7 @@ export async function runOneShotExec(input, log) {
|
|
|
127
128
|
stdout: outText,
|
|
128
129
|
stderr: errText,
|
|
129
130
|
durationMs: Date.now() - started,
|
|
130
|
-
truncated: stdout.total > outTail.length || stderr.total > errTail.length,
|
|
131
|
+
truncated: stdout.total > outTail.length || stderr.total > errTail.length, // 0.3.2-e: true 仅当 retention 驱逐(>4MiB)
|
|
131
132
|
outputStats: { stdout: stdout.stats(outTail.length), stderr: stderr.stats(errTail.length) },
|
|
132
133
|
timedOut,
|
|
133
134
|
outcome,
|
|
@@ -36,8 +36,8 @@
|
|
|
36
36
|
* - `exec` is the P4 placeholder leg: `"not yet implemented: exec (P4)"`.
|
|
37
37
|
*/
|
|
38
38
|
import { defineTool } from '@deepseek-ai/dsh-tools';
|
|
39
|
-
import { parseOneShotExecBody
|
|
40
|
-
import {
|
|
39
|
+
import { parseOneShotExecBody } from './exec.js';
|
|
40
|
+
import { disclose } from '../../remote/plugin.js';
|
|
41
41
|
// F2 (0.1.7-n, PC 0.1.7-m first-person): the wire/registry sentinel stays
|
|
42
42
|
// '[undefined]', but the DISPLAY surface must not show it to a human — D17
|
|
43
43
|
// already sanctions display-layer beautification.
|
|
@@ -190,7 +190,7 @@ const DESCRIPTION = 'SuperD Hub — agent-to-agent messaging across the Super D
|
|
|
190
190
|
' {action:"send", agent?, conversationId?, title?, message, delivery?} → open-or-resume: omit conversationId to OPEN (then agent = the recipient, REQUIRED; title optional; message is the first turn); pass conversationId to RESUME (agent optional — the hub derives the route; a wrong agent is refused). Receipt {outcome: delivered|accepted|failed, messageId, conversationId, sessionId, created, error?, note?}: `delivered` = end-to-end complete; `accepted` = the hub took it and the SAME in-flight request keeps running (its `delivered`/`undelivered` outcome arrives as a notice — do not resend); `failed` = immediate rejection.\n' +
|
|
191
191
|
' {action:"read"} → sweep messages buffered for this session while it was not live.\n' +
|
|
192
192
|
' {action:"stop", conversationId, agent?, scope?} → cancel the conversation\'s ACTIVE turn (the session owner is derived from the conversation id; agent is optional). `stopped:true` means this call cancelled a live turn; a turn that finished on its own is IDLE, never `stopped` — so stop answers stopped:false with a note when nothing was running.\n' +
|
|
193
|
-
' {action:"exec", cmd, machine?, cwd?, stdin?, timeoutSec?, mode?} → run one shell command on a remote machine (machine required; self/local execution disabled unless localExec is explicitly enabled). mode "oneshot" (default): {exit, stdout (
|
|
193
|
+
' {action:"exec", cmd, machine?, cwd?, stdin?, timeoutSec?, mode?} → run one shell command on a remote machine (machine required; self/local execution disabled unless localExec is explicitly enabled). mode "oneshot" (default): {exit, stdout (full up to 4MiB retention; beyond it the retained tail plus outputStats), stderr, durationMs, truncated (retention eviction only), timedOut, outcome}; cwd sets its working directory. String stdin is piped and closed in oneshot; in PTY it is written immediately after cmd (REPL input, not script mode). Hub oneshot hard retention is 4MiB bytes per stream, PTY is 4,000,000 UTF-16 code units. outputStats reports real total/retained/dropped/returned and units; discarded head cannot be recovered by restarting. mode "pty": a PERSISTENT shell per (your session, machine) — the shell OWNS its cwd and env and they SURVIVE across dispatches (cd once inside the command, then keep working); {output (full up to 4M UTF-16 units; beyond it the retained tail plus outputStats), exit, cwd, timedOut, reconnected, durationMs}. cwd is oneshot-only: passing it with mode "pty" is refused (use `cd <dir> && …` inside the command). Prefer oneshot for independent commands; pty when shell state matters.\n' +
|
|
194
194
|
'Addresses are "<m4>-<a6>" (machine-agent); call agents first to list valid ids. delivery: "queue" (default) is injected into the peer\'s session as a waking turn — it never interrupts an active turn, it queues behind it; "steer" submits steering for the peer\'s nearest step boundary — use it only when urgency demands. NEVER poll for a reply: the peer\'s reply arrives in this conversation as a new message WHEN THE PEER SENDS one (peers that never use the channel get their last output at turn end delivered as their reply instead, form=transcript); a turn that ends with no channel artifact yields one notice whose reason= distinguishes peer-silent (ended, said nothing) / peer-error (stream died or turn aborted) / stopped-by-initiator (you stopped it). read only sweeps what was buffered while this session was down. stop is a hard stop of the peer\'s active turn (the UI stop button); scope "session" degrades to turn-only — no session-close exists upstream — and the conversation stays resumable: send again to resume it. agent_status reads a cache refreshed by the 5-minute sweep (collectedAt says when); the window is alive-first, ≤5 rows, newest first, and not being in it implies nothing; a `note` says why when the window has no collection behind it (the last collection failed, or none has happened yet). MESSAGING HAS NO STATUS QUERY: to check whether a peer is idle or running, call agent_status (a 5-minute cache — never a delivery receipt); if that is not enough and you cannot wait, send another message.';
|
|
195
195
|
/**
|
|
196
196
|
* Build the one SuperD Hub tool.
|
|
@@ -284,8 +284,8 @@ export function createSuperdHubTool(deps) {
|
|
|
284
284
|
count: { type: 'integer' },
|
|
285
285
|
messages: { type: 'json', description: 'read sweep: buffered messages with from as "<m4>-<a6>"' },
|
|
286
286
|
exit: { type: 'json', description: 'exec: the command exit code (null when killed by timeout/signal)' },
|
|
287
|
-
stdout: { type: 'json', description: 'exec:
|
|
288
|
-
stderr: { type: 'json', description: 'exec:
|
|
287
|
+
stdout: { type: 'json', description: 'exec: full stdout up to retention (4MiB bytes; PTY 4,000,000 UTF-16 units)' },
|
|
288
|
+
stderr: { type: 'json', description: 'exec: full stderr up to retention (4MiB bytes)' },
|
|
289
289
|
durationMs: { type: 'integer', description: 'exec: wall-clock duration' },
|
|
290
290
|
outputStats: { type: 'json', description: 'exec per-stream counters with explicit bytes/utf16 units; total, retained, dropped head, returned payload (excludes banners), retentionLimit. Absent on older peers: exact metrics unavailable.' },
|
|
291
291
|
truncated: { type: 'boolean', description: 'exec: a stream\'s total output exceeded the returned tail window' },
|
|
@@ -422,7 +422,7 @@ export function createSuperdHubTool(deps) {
|
|
|
422
422
|
const machine = args.machine ?? deps.exec.selfM4();
|
|
423
423
|
try {
|
|
424
424
|
const r = await deps.exec.pty(sessionKey, machine, args.cmd, { ...(args.timeoutSec === undefined ? {} : { timeoutSec: args.timeoutSec }), ...(args.stdin === undefined ? {} : { stdin: args.stdin }) });
|
|
425
|
-
const out =
|
|
425
|
+
const out = disclose(r.output, r.outputStats?.stdout); // 0.3.2-e: 全量返回,仅 retention 驱逐打 banner
|
|
426
426
|
return {
|
|
427
427
|
action,
|
|
428
428
|
mode: 'pty',
|