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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "super-dsh",
3
- "version": "0.3.2-d",
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",
@@ -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
- declare function tailWindow(text: string, cap: number, stats?: OutputStats): {
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, tailWindow };
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
- function tailWindow(text, cap, stats) {
2870
- let tail = text.slice(-cap);
2871
- if (tail.charCodeAt(0) >= 56320 && tail.charCodeAt(0) <= 57343) tail = tail.slice(1);
2872
- const returned = stats?.unit === "bytes" ? Buffer.byteLength(tail) : tail.length;
2873
- const total = stats?.total ?? text.length;
2874
- const updated = stats === void 0 ? {} : { stats: {
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 (total <= returned) return {
2879
- text: tail,
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: `[truncated: showing last ${returned} of ${total} ${stats?.unit === "bytes" ? "bytes" : "chars"}${stats !== void 0 && stats.dropped > 0 ? `; retained ${stats.retained}, dropped head ${stats.dropped}, retention limit ${stats.retentionLimit} ${stats.unit === "bytes" ? "bytes" : "UTF-16 code units"}` : ""}]\n${tail}`,
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 = tailWindow(stdout.text, cap, stdout.stats);
4169
- const err = tailWindow(stderr.text, cap, stderr.stats);
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, cap);
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, cap);
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, cap);
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, cap);
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, cap);
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, cap);
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, cap);
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, cap) {
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 = tailWindow(r.output, cap, r.outputStats?.stdout);
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, cap) {
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 = tailWindow(r.stdout, cap, r.outputStats?.stdout);
4906
- const err = r.stderr.length > 0 ? tailWindow(r.stderr, cap, r.outputStats?.stderr) : void 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, cap) {
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 = tailWindow(stdout.text, cap, stdout.stats);
4931
- const err = tailWindow(stderr.text, cap, stderr.stats);
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 may truncate (~30k chars per read); redirect bulk output to files.
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; returned tail only");
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, tailWindow };
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 };
@@ -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": "89a690159bc64056c6b740ae76722b13a922f36cb2fc908adbbe2ccce1b9ebb3",
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": "e2590293fe44c2997f6d65e0d6828aa67e51e0fc6d12cb71726063eec2f922b2",
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": "058c35172c32b347b14d5ea6db89234ccdde6f13d94eea550c5f2b8f31726288",
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": "e2dda347880a8787196720e71f32da473f9135ba6ab9a21cb22a7241628c0744",
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": "92ea2007e5eb9907031de1cf0c53b30758804def9ebb957900cd3fb58d92be90",
75
- "plugin.js": "c98040cb2f1e9d4e15f1c0aa61d3b0213e9281aa254baff92ab40549e0e22d48"
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
- /** Per-stream returned tail: at most 30,000 bytes, beginning on a UTF8 boundary. */
31
- export declare const EXEC_TAIL_WINDOW = 30000;
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;
@@ -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 (better-dash lesson, spec §8.1): return the LAST 30k of
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
- /** Per-stream returned tail: at most 30,000 bytes, beginning on a UTF8 boundary. */
19
- export const EXEC_TAIL_WINDOW = 30_000;
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(EXEC_TAIL_WINDOW), errTail = stderr.tail(EXEC_TAIL_WINDOW);
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, EXEC_TAIL_WINDOW } from './exec.js';
40
- import { tailWindow } from '../../remote/plugin.js';
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 (last 30k), stderr, durationMs, truncated, 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 (tail 30k), 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' +
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: the last 30k of stdout' },
288
- stderr: { type: 'json', description: 'exec: the last 30k of stderr' },
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 = tailWindow(r.output, EXEC_TAIL_WINDOW, r.outputStats?.stdout);
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',