super-dsh 0.3.1-a → 0.3.1-b

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "super-dsh",
3
- "version": "0.3.1-a",
3
+ "version": "0.3.1-b",
4
4
  "description": "Super D for the DeepSeek Harness (DSH) — one dsh plugin that mounts the superd hub (runtime selector, roster, per-runtime agents) and joins local foreign-agent runtimes (OMP, Codex, Claude, Pi, Hermes, Antigravity) into the DSH Web UI. Each runtime keeps its native home and session store; the hub only bridges.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -0,0 +1,35 @@
1
+ {
2
+ "format": 1,
3
+ "name": "superd-run",
4
+ "ver": "0.3.1-b",
5
+ "protocol": 1,
6
+ "targets": {
7
+ "aarch64-apple-darwin": {
8
+ "file": "superd-run",
9
+ "bytes": 337808,
10
+ "sha256": "715c2d7bd935f3b4cc4ae0ffb10d3fab946bb62d93f592ccfe2a7446669ff76b"
11
+ },
12
+ "aarch64-unknown-linux-musl": {
13
+ "file": "superd-run",
14
+ "bytes": 397416,
15
+ "sha256": "22ac1c7f913092d8ca8d312b93528dd2263200f9670dc183fd215bc89d2bac68"
16
+ },
17
+ "x86_64-pc-windows-gnu": {
18
+ "file": "superd-run.exe",
19
+ "bytes": 336896,
20
+ "sha256": "a638479e1ccb1c4e185085100450962e39164158a76097b5087d2a3bb8880ac0"
21
+ },
22
+ "x86_64-unknown-linux-musl": {
23
+ "file": "superd-run",
24
+ "bytes": 447152,
25
+ "sha256": "79e42879509bb87d2fe9888d282151fd17113203d3172f59a16fcb5a180ba057"
26
+ }
27
+ },
28
+ "sources": {
29
+ "Cargo.toml": "129ab8360e9da872f9dfd6e713d81fe1389735a74d781f3d9c15e110f92d2757",
30
+ "build.rs": "c4fb356956b1ec700e99bdeca07d657a7d3b2a4026582db136411676da3d125e",
31
+ "src/main.rs": "47f1648ea1abc30583839edab219a9062c83d57be981c0505ab6bf79c6fbff54",
32
+ "src/unix.rs": "56c5f523b7b1a9efd50ef24ccdabc024bc065dd2f904fdbecdf0ca49fe7f3393",
33
+ "src/windows.rs": "6c1537424b1adc05ed17c7cf8bf376fb5711602b9da1697d596155bf21d541da"
34
+ }
35
+ }
@@ -213,6 +213,23 @@ interface RsyncReceipt extends RunResult {
213
213
  */
214
214
  declare function runRsync(request: RsyncRequest, source: RsyncEndpoint, destination: RsyncEndpoint, signal: AbortSignal, options?: RelayRsyncOptions): Promise<RsyncReceipt>;
215
215
  //#endregion
216
+ //#region src/remote/helper.d.ts
217
+ interface HelperManifest {
218
+ format: 1;
219
+ name: string;
220
+ ver: string;
221
+ protocol: number;
222
+ targets: Record<string, {
223
+ file: string;
224
+ bytes: number;
225
+ sha256: string;
226
+ }>;
227
+ }
228
+ interface HelperAssets {
229
+ dir: string;
230
+ manifest: HelperManifest;
231
+ }
232
+ //#endregion
216
233
  //#region src/remote/process.d.ts
217
234
  declare const PROCESS_CLEANUP_BOUND_MS: number;
218
235
  interface ProcessOptions {
@@ -287,6 +304,8 @@ interface RemoteCallResult {
287
304
  session?: string;
288
305
  /** 引导/教学行(同 label 重复给 spawn 时的「可省略 spawn」提示等);无则省略。 */
289
306
  notice?: string;
307
+ /** oneshot 监督路径的如实标注:`superd-run <ver> (<triple>)` 或 `posix-shim`(spec remote-rescope §5)。 */
308
+ runner?: string;
290
309
  }
291
310
  interface RemoteAuditRecord {
292
311
  target: string;
@@ -311,6 +330,8 @@ interface RemoteDriverOptions {
311
330
  ptyArgvFor?: (plan: TargetPlan) => string[];
312
331
  spawnArgvFor?: (spawnCommand: string) => string[];
313
332
  probeRunner?: ProbeOptions['runner'];
333
+ /** 测试/验收缝:helper 资产来源(默认 lib 旁挂 helper-bin);显式 null 强制 shim 路径。 */
334
+ helperAssetsFor?: () => HelperAssets | null;
314
335
  /** 测试缝:roster 扫描执行器(bare-name 解析复用)。 */
315
336
  rosterRunner?: RosterOptions['runner'];
316
337
  /** 测试缝:ssh config 读取(bare-name 解析复用)。 */
@@ -327,6 +348,9 @@ declare class RemoteDriver {
327
348
  private readonly starting;
328
349
  private readonly fileAbort;
329
350
  private disposed;
351
+ /** undefined = 未尝试;null = 资产缺失(shim-only);registry = 每 target sticky 状态机。 */
352
+ private helpers;
353
+ private readonly runnerOf;
330
354
  private disposal;
331
355
  constructor(opts?: RemoteDriverOptions);
332
356
  call(params: RemoteCallParams, callCtx?: {
@@ -350,6 +374,10 @@ declare class RemoteDriver {
350
374
  start(input: RemoteInput, signal: AbortSignal): Promise<RemoteProcess>;
351
375
  private startPrepared;
352
376
  private nativeProcess;
377
+ /** Helper bootstrap is best-effort and sticky: any failure parks null for this driver
378
+ * lifetime and the shim stays the path. First call to a target pays probe (+ upload). */
379
+ private ensureHelper;
380
+ private helperExec;
353
381
  private own;
354
382
  /** Ruling 16/17:on-demand 探测 + 会话层,两行如实陈述。 */
355
383
  /**
package/remote/plugin.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { Context } from "@deepseek-ai/cordis";
2
- import { chmod, lstat, mkdir, mkdtemp, open, readFile, readdir, readlink, rename, rm, symlink, writeFile } from "node:fs/promises";
3
- import { constants, createReadStream, createWriteStream, mkdirSync, statSync } from "node:fs";
2
+ import { chmod, lstat, mkdir, mkdtemp, open, readFile, readdir, readlink, rename, rm, stat, symlink, writeFile } from "node:fs/promises";
3
+ import { constants, createReadStream, createWriteStream, mkdirSync, readFileSync, statSync } from "node:fs";
4
4
  import { pipeline } from "node:stream/promises";
5
5
  import { dirname, isAbsolute, join, posix, resolve } from "node:path";
6
6
  import { Readable } from "node:stream";
@@ -8,6 +8,7 @@ import { createHash, randomBytes, randomUUID } from "node:crypto";
8
8
  import { homedir, tmpdir } from "node:os";
9
9
  import { spawn } from "node:child_process";
10
10
  import { createConnection, createServer } from "node:net";
11
+ import { fileURLToPath } from "node:url";
11
12
  import { defineTool } from "@deepseek-ai/dsh-tools";
12
13
 
13
14
  //#region third_party/schemastery/node_modules/@deepseek-ai/cosmokit/lib/index.js
@@ -1631,6 +1632,7 @@ async function nativeCopy(request, endpoints, signal, options = {}) {
1631
1632
  const argv = [
1632
1633
  "scp",
1633
1634
  ...identityArgv(connection),
1635
+ ...await recursiveFlag(endpoints.src.path, oneShot, "-r"),
1634
1636
  ...oneShot,
1635
1637
  endpoints.src.path,
1636
1638
  scpSpec(connection, endpoints.dst.path)
@@ -1663,7 +1665,7 @@ async function nativeCopy(request, endpoints, signal, options = {}) {
1663
1665
  dstSpec = scpSpec(destination, endpoints.dst.path);
1664
1666
  extra = identityArgv(source);
1665
1667
  } else {
1666
- config = await tempSshConfig(source, destination);
1668
+ config = await tempSshConfig(source, destination, runNative);
1667
1669
  extra = ["-F", config.path];
1668
1670
  srcSpec = `superd-scp3-source:${endpoints.src.path}`;
1669
1671
  dstSpec = `superd-scp3-destination:${endpoints.dst.path}`;
@@ -1695,7 +1697,9 @@ async function nativeCopy(request, endpoints, signal, options = {}) {
1695
1697
  endpoints.src.path,
1696
1698
  `${containerOf(endpoints.dst.plan)}:${endpoints.dst.path}`
1697
1699
  ];
1698
- return finish("docker cp", [argv], [await runNative(wrap(argv), signal)]);
1700
+ const result = await runNative(wrap(argv), signal);
1701
+ withSymlinkHint(result);
1702
+ return finish("docker cp", [argv], [result]);
1699
1703
  }
1700
1704
  if (s === "docker" && t === "local") {
1701
1705
  const argv = [
@@ -1705,13 +1709,16 @@ async function nativeCopy(request, endpoints, signal, options = {}) {
1705
1709
  `${containerOf(endpoints.src.plan)}:${endpoints.src.path}`,
1706
1710
  endpoints.dst.path
1707
1711
  ];
1708
- return finish("docker cp", [argv], [await runNative(wrap(argv), signal)]);
1712
+ const result = await runNative(wrap(argv), signal);
1713
+ withSymlinkHint(result);
1714
+ return finish("docker cp", [argv], [result]);
1709
1715
  }
1710
1716
  if (s === "local" && t === "incus") {
1711
1717
  const argv = [
1712
1718
  "incus",
1713
1719
  "file",
1714
1720
  "push",
1721
+ ...await recursiveFlag(endpoints.src.path, oneShot, "-r"),
1715
1722
  ...oneShot,
1716
1723
  endpoints.src.path,
1717
1724
  `${containerOf(endpoints.dst.plan)}${endpoints.dst.path}`
@@ -1805,30 +1812,100 @@ function segmentArgv(plan, remote, staged, opts, leg) {
1805
1812
  }
1806
1813
  /** Distinguishing identities for scp -3: an origin-only temp config maps two
1807
1814
  * synthetic aliases; keys are referenced in place, never copied to any remote. */
1808
- async function tempSshConfig(source, destination) {
1809
- for (const c of [source, destination]) for (const [field, value] of [
1810
- ["host", c.host],
1811
- ["user", c.user],
1812
- ["key", c.key],
1813
- ["proxyJump", c.proxyJump]
1814
- ]) if (value !== void 0 && /[\r\n]/.test(value)) throw new Error(`remote: scp -3 temp config rejects newline in SSH ${field} (no config injection)`);
1815
+ /** D8 (2026-10-14 user adoption, third acceptance round): a LOCAL directory source gets
1816
+ * the route's recursive flag appended automatically — scp / incus file push refuse
1817
+ * directories without it. The appended flag lands in the executed argv, which the
1818
+ * receipt shows verbatim: disclosure by receipt, never silent. Remote sources stay
1819
+ * caller-explicit (we do not dial just to stat); an explicit caller flag wins. */
1820
+ async function recursiveFlag(localPath, callerArgv, flag) {
1821
+ if (callerArgv.includes(flag) || callerArgv.includes("--recursive")) return [];
1822
+ try {
1823
+ if ((await stat(localPath)).isDirectory()) return [flag];
1824
+ } catch {}
1825
+ return [];
1826
+ }
1827
+ /** docker cp follows symlinks only with -L; its native error ("invalid symlink")
1828
+ * names no remedy. Append the one-line hint on that failure path (F5, 2026-10-14). */
1829
+ function withSymlinkHint(result) {
1830
+ if (result.exit !== 0 && /invalid symlink/i.test(result.stderr)) result.stderr = `${result.stderr}\nhint: docker cp follows symlinks only with -L — pass argv:["-L"] (e.g. /etc/os-release is a symlink)`;
1831
+ }
1832
+ async function tempSshConfig(source, destination, runNative$1) {
1833
+ const resolvedSource = await resolveThroughOriginConfig(source, runNative$1);
1834
+ const resolvedDestination = await resolveThroughOriginConfig(destination, runNative$1);
1835
+ for (const { connection: c, identityFiles } of [resolvedSource, resolvedDestination]) {
1836
+ for (const [field, value] of [
1837
+ ["host", c.host],
1838
+ ["user", c.user],
1839
+ ["key", c.key],
1840
+ ["proxyJump", c.proxyJump]
1841
+ ]) if (value !== void 0 && /[\r\n]/.test(value)) throw new Error(`remote: scp -3 temp config rejects newline in SSH ${field} (no config injection)`);
1842
+ for (const idFile of identityFiles) if (/[\r\n]/.test(idFile)) throw new Error("remote: scp -3 temp config rejects newline in resolved IdentityFile (no config injection)");
1843
+ }
1815
1844
  const dir = await mkdtemp(join(tmpdir(), "superd-scp3-"));
1816
1845
  const path = join(dir, "config");
1817
- const block = (name$1, c) => {
1846
+ const block = (name$1, c, identityFiles) => {
1818
1847
  const lines = [`Host ${name$1}`, ` HostName ${c.host.replace(/^.*@/, "")}`];
1819
1848
  if (c.user !== void 0) lines.push(` User ${c.user}`);
1820
1849
  if (c.port !== void 0) lines.push(` Port ${String(c.port)}`);
1821
- if (c.key !== void 0) lines.push(` IdentityFile ${c.key}`);
1850
+ for (const idFile of [c.key !== void 0 ? [c.key] : [], identityFiles].flat()) lines.push(` IdentityFile ${idFile}`);
1822
1851
  if (c.proxyJump !== void 0) lines.push(` ProxyJump ${c.proxyJump}`);
1823
1852
  return lines.join("\n");
1824
1853
  };
1825
- await writeFile(path, `${block("superd-scp3-source", source)}\n${block("superd-scp3-destination", destination)}\n`, { mode: 384 });
1854
+ await writeFile(path, `${block("superd-scp3-source", resolvedSource.connection, resolvedSource.identityFiles)}\n${block("superd-scp3-destination", resolvedDestination.connection, resolvedDestination.identityFiles)}\n`, { mode: 384 });
1826
1855
  await chmod(path, 384);
1827
1856
  return {
1828
1857
  path,
1829
1858
  dir
1830
1859
  };
1831
1860
  }
1861
+ /** Effective fields for one connection per the origin's own ssh config (ssh -G,
1862
+ * prints resolved settings without dialing). Explicit fields win; empty/none
1863
+ * proxyjump is dropped. IdentityFile PATHS from the config are returned separately
1864
+ * for inlining into the temp config — a path is not key material and stays on the
1865
+ * origin (F1, 2026-10-14: dev4's only authorized key lived in config, not the agent;
1866
+ * dropping it made scp -3 fail with a bare Permission denied). */
1867
+ async function resolveThroughOriginConfig(c, runNative$1) {
1868
+ let probe;
1869
+ try {
1870
+ probe = await runNative$1([
1871
+ "ssh",
1872
+ "-G",
1873
+ c.host
1874
+ ], new AbortController().signal);
1875
+ } catch {
1876
+ probe = void 0;
1877
+ }
1878
+ if (probe === void 0 || probe.exit !== 0) return {
1879
+ connection: c,
1880
+ identityFiles: []
1881
+ };
1882
+ const lines = probe.stdout.split("\n").map((line) => line.trim()).filter((line) => line.length > 0);
1883
+ const pick$1 = (key) => lines.find((line) => line.startsWith(`${key} `))?.slice(key.length + 1).trim() || void 0;
1884
+ const home = process.env.HOME ?? "";
1885
+ const compiledDefault = (path) => path === "none" || [
1886
+ "id_rsa",
1887
+ "id_ecdsa",
1888
+ "id_ecdsa_sk",
1889
+ "id_ed25519",
1890
+ "id_ed25519_sk"
1891
+ ].some((name$1) => path === `~/.ssh/${name$1}` || home !== "" && path === `${home}/.ssh/${name$1}`);
1892
+ const identityFiles = [...new Set(lines.filter((line) => line.startsWith("identityfile ")).map((line) => line.slice(13).trim()).filter((path) => path !== "" && !compiledDefault(path)))];
1893
+ const host = (pick$1("hostname") ?? c.host).replace(/^.*@/, "");
1894
+ const user = c.user ?? pick$1("user");
1895
+ const portText = pick$1("port");
1896
+ const port = c.port ?? (portText !== void 0 && /^\d+$/.test(portText) ? Number(portText) : void 0);
1897
+ const proxyJumpRaw = c.proxyJump ?? pick$1("proxyjump");
1898
+ return {
1899
+ connection: {
1900
+ host,
1901
+ ...user !== void 0 && user !== "" ? { user } : {},
1902
+ ...port !== void 0 && Number.isInteger(port) && port > 0 ? { port } : {},
1903
+ ...c.key !== void 0 ? { key: c.key } : {},
1904
+ ...proxyJumpRaw !== void 0 && proxyJumpRaw !== "" && proxyJumpRaw.toLowerCase() !== "none" ? { proxyJump: proxyJumpRaw } : {}
1905
+ },
1906
+ identityFiles
1907
+ };
1908
+ }
1832
1909
 
1833
1910
  //#endregion
1834
1911
  //#region src/remote/ssh-rsync-native-relay.ts
@@ -2015,12 +2092,16 @@ async function forwardRoute(argv, source, destination, signal, options) {
2015
2092
  return await removeRemoteTemp(destination.connection, temp, wrap) ? "released" : "unknown";
2016
2093
  };
2017
2094
  try {
2095
+ signal.throwIfAborted();
2096
+ const daemonState = await waitForDaemonReady(destinationChild, 5e3);
2097
+ if (daemonState === "exited") throw new Error(`dual-SSH rsync destination daemon exited before serving${relayDetail(destinationChild, sourceHold)}`);
2098
+ if (daemonState === "timeout") throw new Error(`dual-SSH rsync destination daemon never announced readiness${relayDetail(destinationChild, sourceHold)}`);
2018
2099
  signal.throwIfAborted();
2019
2100
  if (!await originPortOpen(originPort, 15e3)) throw new Error(`dual-SSH rsync destination daemon never became reachable${relayDetail(destinationChild, sourceHold)}`);
2020
2101
  signal.throwIfAborted();
2021
2102
  const runArgv = relaySsh(source.connection, [], rsyncClientCommand(argv, source.path, sourcePort));
2022
2103
  const result = await runNative(wrap(runArgv), signal);
2023
- if (result.exit === 255) result.stderr = (result.stderr + relayDetail(destinationChild, sourceHold)).slice(-OUTPUT_LIMIT);
2104
+ if (result.exit !== 0) result.stderr = (result.stderr + relayDetail(destinationChild, sourceHold)).slice(-OUTPUT_LIMIT);
2024
2105
  if (result.exit !== 0 && /remote port forwarding failed|administratively prohibited|could not request (local|remote) forwarding/.test(relayDetail(destinationChild, sourceHold))) throw new Error(`dual-SSH rsync forwarding route refused by an endpoint: ${relayDetail(destinationChild, sourceHold)}`);
2025
2106
  return {
2026
2107
  ...result,
@@ -2045,6 +2126,19 @@ async function forwardRoute(argv, source, destination, signal, options) {
2045
2126
  await Promise.allSettled([destinationChild.stop(), sourceHold.stop()]);
2046
2127
  }
2047
2128
  }
2129
+ /** Wait until the destination daemon script announces itself (stderr marker,
2130
+ * printed after its directory check and right before the daemon exec) or exits.
2131
+ * 'ready' only when the daemon is actually about to serve — closes the 0.3.1-e
2132
+ * race where -L opens at session start but the script dies ~150ms later. */
2133
+ async function waitForDaemonReady(held, budgetMs) {
2134
+ const deadline = Date.now() + budgetMs;
2135
+ for (;;) {
2136
+ if (/^SUPERD-RSYNC-TMP \S+$/m.test(held.stderrSink.text)) return "ready";
2137
+ if (held.child.exitCode !== null) return "exited";
2138
+ if (Date.now() >= deadline) return "timeout";
2139
+ await new Promise((resolve$1) => setTimeout(resolve$1, 50));
2140
+ }
2141
+ }
2048
2142
  function relayDetail(...held) {
2049
2143
  const detail = held.map((child) => child.stderrSink.text).filter(Boolean).join("\n");
2050
2144
  return detail ? `\n[relay stderr]\n${detail}` : "";
@@ -2381,6 +2475,96 @@ async function runOneShot(argv, opts = {}) {
2381
2475
  };
2382
2476
  }
2383
2477
 
2478
+ //#endregion
2479
+ //#region src/remote/helper.ts
2480
+ /** Reads helper-bin/MANIFEST.json next to the compiled module (lib/remote in the npm
2481
+ * package, super-dsh/remote in the Super closure — same relative layout). Missing or
2482
+ * malformed assets ⇒ null ⇒ shim-only mode; never throws. */
2483
+ function helperAssets(baseDir) {
2484
+ const dir = baseDir ?? join(dirname(fileURLToPath(import.meta.url)), "helper-bin");
2485
+ try {
2486
+ const manifest = JSON.parse(readFileSync(join(dir, "MANIFEST.json"), "utf8"));
2487
+ if (manifest?.format !== 1 || typeof manifest.ver !== "string" || typeof manifest.protocol !== "number" || !manifest.targets || typeof manifest.targets !== "object") return null;
2488
+ return {
2489
+ dir,
2490
+ manifest
2491
+ };
2492
+ } catch {
2493
+ return null;
2494
+ }
2495
+ }
2496
+ /** `uname -s`/`uname -m` → shipped target triple. Unknown combos ⇒ null (shim). */
2497
+ function archTriple(sys, machine, shipped) {
2498
+ const s = sys.trim().toLowerCase(), m = machine.trim().toLowerCase();
2499
+ const candidates = s === "linux" ? m === "x86_64" || m === "amd64" ? "x86_64-unknown-linux-musl" : m === "aarch64" || m === "arm64" ? "aarch64-unknown-linux-musl" : null : s === "darwin" ? m === "arm64" || m === "aarch64" ? "aarch64-apple-darwin" : null : null;
2500
+ if (candidates === null) return null;
2501
+ return shipped.has(candidates) ? candidates : null;
2502
+ }
2503
+ function planKey(plan) {
2504
+ switch (plan.kind) {
2505
+ case "ssh": {
2506
+ const c = plan.connection;
2507
+ const host = c?.host ?? plan.host;
2508
+ return `ssh|${c?.user ? c.user + "@" : ""}${host}${c?.port ? ":" + c.port : ""}${c?.proxyJump ? "|" + c.proxyJump : ""}`;
2509
+ }
2510
+ case "docker": return `docker|${plan.container}`;
2511
+ case "incus": return `incus|${plan.container}`;
2512
+ }
2513
+ }
2514
+ const PROBE_RE = /^SUPERD-PROBE (\S+) (\S+)$/m;
2515
+ const READY_RE = /^SUPERD-READY (\S+)$/m;
2516
+ var HelperRegistry = class {
2517
+ states = /* @__PURE__ */ new Map();
2518
+ constructor(assets, exec, probeArgv, uploadArgv) {
2519
+ this.assets = assets;
2520
+ this.exec = exec;
2521
+ this.probeArgv = probeArgv;
2522
+ this.uploadArgv = uploadArgv;
2523
+ }
2524
+ /** Never throws: any bootstrap failure resolves null (sticky) and the caller stays on the shim. */
2525
+ ensure(plan) {
2526
+ if (plan.kind !== "ssh" && plan.kind !== "docker" && plan.kind !== "incus") return Promise.resolve(null);
2527
+ const key = planKey(plan);
2528
+ let entry = this.states.get(key);
2529
+ if (entry === void 0) {
2530
+ entry = this.bootstrap(plan).catch(() => null);
2531
+ entry.catch(() => {});
2532
+ this.states.set(key, entry);
2533
+ }
2534
+ return entry;
2535
+ }
2536
+ async bootstrap(plan) {
2537
+ const { manifest } = this.assets;
2538
+ const first = await this.exec(this.probeArgv(plan, this.assets), { timeoutSec: 15 });
2539
+ const ready = this.parseReady(first.stdout, manifest.ver, manifest.protocol);
2540
+ if (ready !== null) return ready;
2541
+ const probe = PROBE_RE.exec(first.stdout);
2542
+ if (probe === null || first.exit !== 90 && first.exit !== 0) return null;
2543
+ const triple = archTriple(probe[1], probe[2], new Set(Object.keys(manifest.targets)));
2544
+ if (triple === null) return null;
2545
+ const target = manifest.targets[triple];
2546
+ const binary = await readFile(join(this.assets.dir, triple, target.file));
2547
+ if ((await this.exec(this.uploadArgv(plan, triple, target.file, this.assets), {
2548
+ stdin: binary,
2549
+ timeoutSec: 60
2550
+ })).exit !== 0) return null;
2551
+ const second = await this.exec(this.probeArgv(plan, this.assets), { timeoutSec: 15 });
2552
+ return this.parseReady(second.stdout, manifest.ver, manifest.protocol);
2553
+ }
2554
+ parseReady(stdout, ver, protocol) {
2555
+ const ready = READY_RE.exec(stdout);
2556
+ const banner = /^SUPERD-RUN proto=(\d+) name=superd-run ver=(\S+) target=(\S+)/m.exec(stdout);
2557
+ if (ready === null || banner === null) return null;
2558
+ if (banner[1] !== String(protocol) || banner[2] !== ver) return null;
2559
+ return {
2560
+ binPath: ready[1],
2561
+ triple: banner[3],
2562
+ ver,
2563
+ protocol
2564
+ };
2565
+ }
2566
+ };
2567
+
2384
2568
  //#endregion
2385
2569
  //#region src/remote/transports.ts
2386
2570
  /** POSIX 单引号机械转义(唯一一层转义,spec §三"一层机械转义")。 */
@@ -2460,6 +2644,104 @@ function buildSpawnArgv(spawnCommand) {
2460
2644
  "/dev/null"
2461
2645
  ];
2462
2646
  }
2647
+ /** superd-run helper argv (spec: docs/specs/remote-rescope §5). Probe and upload are single
2648
+ * `sh -c` hops (busybox/alpine/darwin-safe); run/killgroup over ssh go through exactly one
2649
+ * remote-shell parse, same discipline as buildOneShotArgv. */
2650
+ function buildHelperProbeArgv(plan, assets) {
2651
+ const { ver, targets } = assets.manifest;
2652
+ return helperShellArgv(plan, `${Object.entries(targets).map(([triple, t]) => `d="$HOME/.cache/superd/run/${triple}-${ver}"; [ -x "$d/${t.file}" ] && { echo "SUPERD-READY $d/${t.file}"; "$d/${t.file}" banner; exit 0; };`).join(" ")} echo "SUPERD-PROBE $(uname -s 2>/dev/null || echo unknown) $(uname -m 2>/dev/null || echo unknown)"; exit 90`);
2653
+ }
2654
+ function buildHelperUploadArgv(plan, triple, file, assets) {
2655
+ const dir = `$HOME/.cache/superd/run/${triple}-${assets.manifest.ver}`;
2656
+ return helperShellArgv(plan, `mkdir -p "${dir}" && cat > "${dir}/${file}.tmp" && chmod 0755 "${dir}/${file}.tmp" && mv -f "${dir}/${file}.tmp" "${dir}/${file}"`);
2657
+ }
2658
+ function buildHelperOneShotArgv(plan, binPath, options) {
2659
+ const { tag, cmd } = options;
2660
+ switch (plan.kind) {
2661
+ case "ssh": return sshArgv(plan.connection ?? { host: plan.host }, { command: `exec ${shQuote(binPath)} run --tag ${shQuote(tag)} -- bash -lc ${shQuote(cmd)}` });
2662
+ case "docker": return [
2663
+ "docker",
2664
+ "exec",
2665
+ "-i",
2666
+ "--",
2667
+ plan.container,
2668
+ binPath,
2669
+ "run",
2670
+ "--tag",
2671
+ tag,
2672
+ "--",
2673
+ "bash",
2674
+ "-lc",
2675
+ cmd
2676
+ ];
2677
+ case "incus": return [
2678
+ "incus",
2679
+ "exec",
2680
+ "--force-noninteractive",
2681
+ plan.container,
2682
+ "--",
2683
+ binPath,
2684
+ "run",
2685
+ "--tag",
2686
+ tag,
2687
+ "--",
2688
+ "bash",
2689
+ "-lc",
2690
+ cmd
2691
+ ];
2692
+ }
2693
+ }
2694
+ function buildHelperKillgroupArgv(plan, binPath, tag) {
2695
+ switch (plan.kind) {
2696
+ case "ssh": return sshArgv(plan.connection ?? { host: plan.host }, { command: `${shQuote(binPath)} killgroup --tag ${shQuote(tag)}` });
2697
+ case "docker": return [
2698
+ "docker",
2699
+ "exec",
2700
+ "--",
2701
+ plan.container,
2702
+ binPath,
2703
+ "killgroup",
2704
+ "--tag",
2705
+ tag
2706
+ ];
2707
+ case "incus": return [
2708
+ "incus",
2709
+ "exec",
2710
+ "--force-noninteractive",
2711
+ plan.container,
2712
+ "--",
2713
+ binPath,
2714
+ "killgroup",
2715
+ "--tag",
2716
+ tag
2717
+ ];
2718
+ }
2719
+ }
2720
+ function helperShellArgv(plan, script) {
2721
+ switch (plan.kind) {
2722
+ case "ssh": return sshArgv(plan.connection ?? { host: plan.host }, { command: script });
2723
+ case "docker": return [
2724
+ "docker",
2725
+ "exec",
2726
+ "-i",
2727
+ "--",
2728
+ plan.container,
2729
+ "sh",
2730
+ "-c",
2731
+ script
2732
+ ];
2733
+ case "incus": return [
2734
+ "incus",
2735
+ "exec",
2736
+ "--force-noninteractive",
2737
+ plan.container,
2738
+ "--",
2739
+ "sh",
2740
+ "-c",
2741
+ script
2742
+ ];
2743
+ }
2744
+ }
2463
2745
 
2464
2746
  //#endregion
2465
2747
  //#region src/remote/nonce-framing.ts
@@ -3189,6 +3471,9 @@ var RemoteDriver = class {
3189
3471
  starting = /* @__PURE__ */ new Set();
3190
3472
  fileAbort = new AbortController();
3191
3473
  disposed = false;
3474
+ /** undefined = 未尝试;null = 资产缺失(shim-only);registry = 每 target sticky 状态机。 */
3475
+ helpers;
3476
+ runnerOf = /* @__PURE__ */ new WeakMap();
3192
3477
  disposal;
3193
3478
  constructor(opts = {}) {
3194
3479
  this.opts = opts;
@@ -3381,12 +3666,32 @@ var RemoteDriver = class {
3381
3666
  if (signal.aborted || this.disposed) process$1.cancel("owner closed during start");
3382
3667
  return process$1;
3383
3668
  }
3384
- nativeProcess(plan, params, timeoutSec, signal = this.fileAbort.signal) {
3669
+ async nativeProcess(plan, params, timeoutSec, signal = this.fileAbort.signal) {
3385
3670
  const cleanupTag = randomUUID().slice(0, 8);
3671
+ const helper = await this.ensureHelper(plan);
3672
+ if (helper !== null && !this.disposed) {
3673
+ const process$2 = startOneShot(buildHelperOneShotArgv(plan, helper.binPath, {
3674
+ tag: cleanupTag,
3675
+ cmd: params.cmd
3676
+ }), {
3677
+ stdin: params.stdin,
3678
+ timeoutSec
3679
+ });
3680
+ this.runnerOf.set(process$2, `superd-run ${helper.ver} (${helper.triple})`);
3681
+ process$2.done.then((result) => {
3682
+ if (!result.cancelled && !result.timedOut) return;
3683
+ startOneShot(buildHelperKillgroupArgv(plan, helper.binPath, cleanupTag), { timeoutSec: 15 }).done.catch(() => {});
3684
+ }).catch(() => {});
3685
+ const tracked = Promise.resolve(process$2);
3686
+ this.starting.add(tracked);
3687
+ tracked.then(() => this.starting.delete(tracked), () => this.starting.delete(tracked));
3688
+ return tracked;
3689
+ }
3386
3690
  const process$1 = startOneShot((this.opts.oneshotArgvFor ?? buildOneShotArgv)(plan, params.cmd, { cleanupTag }), {
3387
3691
  stdin: params.stdin,
3388
3692
  timeoutSec
3389
3693
  });
3694
+ this.runnerOf.set(process$1, "posix-shim");
3390
3695
  process$1.done.then((result) => {
3391
3696
  if (!result.cancelled && !result.timedOut) return;
3392
3697
  const pidfile = `"\${TMPDIR:-/tmp}/superd-oneshot-${cleanupTag}.pgid"`;
@@ -3398,6 +3703,38 @@ var RemoteDriver = class {
3398
3703
  work.then(() => this.starting.delete(work), () => this.starting.delete(work));
3399
3704
  return work;
3400
3705
  }
3706
+ /** Helper bootstrap is best-effort and sticky: any failure parks null for this driver
3707
+ * lifetime and the shim stays the path. First call to a target pays probe (+ upload). */
3708
+ async ensureHelper(plan) {
3709
+ if (this.helpers === void 0) {
3710
+ const assets = this.opts.helperAssetsFor?.() ?? helperAssets();
3711
+ this.helpers = assets === null ? null : new HelperRegistry(assets, (argv, options) => this.helperExec(argv, options), buildHelperProbeArgv, buildHelperUploadArgv);
3712
+ }
3713
+ if (this.helpers === null || this.disposed) return null;
3714
+ try {
3715
+ return await this.helpers.ensure(plan);
3716
+ } catch {
3717
+ return null;
3718
+ }
3719
+ }
3720
+ async helperExec(argv, options) {
3721
+ this.assertOpen();
3722
+ const stdin = options?.stdin;
3723
+ if (stdin !== void 0) {
3724
+ const proc$1 = startBinaryProcess(argv, { timeoutSec: options?.timeoutSec });
3725
+ proc$1.stdin.on("error", () => {});
3726
+ proc$1.stdin.end(stdin);
3727
+ return {
3728
+ exit: (await proc$1.done).exit,
3729
+ stdout: ""
3730
+ };
3731
+ }
3732
+ const proc = startOneShot(argv, { timeoutSec: options?.timeoutSec });
3733
+ return {
3734
+ exit: (await proc.done).exit,
3735
+ stdout: proc.read("stdout", 0).text
3736
+ };
3737
+ }
3401
3738
  own(process$1) {
3402
3739
  this.processes.add(process$1);
3403
3740
  process$1.done.then(() => this.processes.delete(process$1));
@@ -3675,7 +4012,8 @@ var RemoteDriver = class {
3675
4012
  stderr: err?.stats ?? r$1.outputStats?.stderr
3676
4013
  } } : {},
3677
4014
  durationMs: r$1.durationMs,
3678
- ...out$1.truncated !== void 0 ? { truncated: out$1.truncated } : {}
4015
+ ...out$1.truncated !== void 0 ? { truncated: out$1.truncated } : {},
4016
+ ...this.runnerOf.get(process$1) === void 0 ? {} : { runner: this.runnerOf.get(process$1) }
3679
4017
  };
3680
4018
  }
3681
4019
  const argv = (this.opts.ptyArgvFor ?? buildPtyArgv)(routing.plan);
@@ -3838,9 +4176,9 @@ const REMOTE_TOOL_DESCRIPTION = `Remote execution and file transfer over ssh / d
3838
4176
  {target:"byop:lbl", spawn, cmd} → create the named shell once; reuse as {target:"byop:lbl", cmd} (no spawn)
3839
4177
  Bare names resolve ssh config → docker → incus → live pty; unmatched goes to ssh and its native error surfaces. Prefixes ssh: / docker: / incus: / byop: force a channel. byop: same spawn repeated is reused; a different spawn is refused ([E_LABEL_CONFLICT], nothing runs); unknown or idle-expired → [E_NO_SESSION] (spawn is not retained — pass it again); a failed spawn frees the label.
3840
4178
 
3841
- oneshot: stateless bash -lc, stdout/stderr separate, exit code verbatim; the endpoint needs bash only (no Python). A POSIX wrapper reaps backgrounded children on completion and kills the whole group on timeout/cancel — they never outlive the call or hold the channel. pty: one shell per (agent, target); cwd/env survive, streams merge, Ctrl-C interrupts without killing, idle reap after 600s.
4179
+ oneshot: stateless bash -lc, stdout/stderr separate, exit code verbatim. Supervision prefers a pinned superd-run helper cached on the endpoint (~/.cache/superd/run; first call uploads it over the same exec lane) and falls back to a POSIX wrapper everywhere else — the result field "runner" says which ran. Helper or wrapper, backgrounded children are reaped on completion and the whole group is killed on timeout/cancel; the endpoint needs bash only (no Python).
3842
4180
 
3843
- Files — {action:"copy" | "rsync", src:"[target:]abs", dst:"[target:]abs", argv:["-a"]}: argv tokens pass verbatim before src/dst — no whitelist, no forced defaults (dry run = pass "--dry-run" yourself); the CLI's own exit code and stderr come back in the receipt. copy: local↔SSH scp; SSH↔SSH scp -3 through the origin (identities stay local); docker cp; incus file push/pull; any other pair = two commands with origin staging (per-half options via pullArgv/pushArgv, exclusive with argv); scp -R refused; success is NOT independently verified; verify/mkdir only on the Hub↔local lane. rsync: local↔SSH, or SSH↔SSH with one protocol conversation between the peers (real delta; forwarding denied → honest error, never full copy). rsync src trailing slash copies contents, no slash the directory itself.
4181
+ Files — {action:"copy" | "rsync", src:"[target:]abs", dst:"[target:]abs", argv:["-a"]}: argv tokens pass verbatim before src/dst — no whitelist, no forced defaults (dry run = pass "--dry-run" yourself); the CLI's own exit code and stderr come back in the receipt. copy: local↔SSH scp; SSH↔SSH scp -3 through the origin (identities stay local); docker cp; incus file push/pull; any other pair = two commands with origin staging (per-half options via pullArgv/pushArgv, exclusive with argv); scp -R (uppercase — scp's remote-client mode) is refused; copy of a directory from a LOCAL source auto-appends the route's recursive flag (-r, shown in the receipt argv); from a REMOTE source pass -r yourself or use rsync; success is NOT independently verified; verify/mkdir only on the Hub↔local lane. rsync: local↔SSH, or SSH↔SSH with one protocol conversation between the peers (real delta; forwarding denied → honest error, never full copy). rsync src trailing slash copies contents, no slash the directory itself.
3844
4182
 
3845
4183
  Output: pty tails at ~30k chars ("[truncated: …]" header) — redirect bulk output to a file. Hard retention 4,000,000 UTF-16 units per stream (Hub 4MiB bytes); outputStats reports the rest; restart cannot recover discarded output. stdin feeds the command; timeout (seconds) interrupts then kills. run_in_background:true (oneshot) → jobId for job_output/job_kill. Native transport errors pass through verbatim — self-correct from them.`;
3846
4184
  function createRemoteTool(driver, opts = {}) {
@@ -3865,7 +4203,7 @@ function createRemoteTool(driver, opts = {}) {
3865
4203
  argv: {
3866
4204
  type: "array",
3867
4205
  items: { type: "string" },
3868
- description: "Ordered native CLI options and values for one-command routes (e.g. rsync [\"-a\",\"--partial\",\"--dry-run\"], scp [\"-p\"], docker cp [\"-a\"], incus file push/pull). One element = one argv token, appended verbatim before src/dst; no shell parsing, no whitelist, no forced defaults — unknown options fail in the native CLI itself. rsync only (SSH endpoints): explicit -e/--rsh overrides the tool's SSH wiring. Two-segment cross-endpoint copy uses pullArgv/pushArgv instead."
4206
+ description: "Ordered native CLI options and values for one-command routes (e.g. rsync [\"-a\",\"--partial\",\"--dry-run\"], scp [\"-p\",\"-r\"], docker cp [\"-a\"], incus file push/pull). One element = one argv token, appended verbatim before src/dst; no shell parsing, no whitelist, no forced defaults — unknown options fail in the native CLI itself. rsync only (SSH endpoints): explicit -e/--rsh overrides the tool's SSH wiring. docker cp: pass -L to follow symlinks (a symlink source like /etc/os-release fails without it). Two-segment cross-endpoint copy uses pullArgv/pushArgv instead."
3869
4207
  },
3870
4208
  pullArgv: {
3871
4209
  type: "array",
@@ -3980,7 +4318,11 @@ function createRemoteTool(driver, opts = {}) {
3980
4318
  outputStats: { type: "json" },
3981
4319
  outputStatsUnavailable: { type: "boolean" },
3982
4320
  session: { type: "string" },
3983
- notice: { type: "string" }
4321
+ notice: { type: "string" },
4322
+ runner: {
4323
+ type: "string",
4324
+ description: "oneshot supervision path: superd-run <ver> (<triple>) or posix-shim"
4325
+ }
3984
4326
  }
3985
4327
  },
3986
4328
  render: (_args, value) => [{
@@ -4026,6 +4368,7 @@ function createRemoteTool(driver, opts = {}) {
4026
4368
  durationMs: Date.now() - start
4027
4369
  };
4028
4370
  }
4371
+ const copyStart = Date.now();
4029
4372
  const receipt = await driver.copy({
4030
4373
  src: args.src,
4031
4374
  dst: args.dst,
@@ -4035,12 +4378,14 @@ function createRemoteTool(driver, opts = {}) {
4035
4378
  ...args.pullArgv === void 0 ? {} : { pullArgv: args.pullArgv },
4036
4379
  ...args.pushArgv === void 0 ? {} : { pushArgv: args.pushArgv }
4037
4380
  }, exec.signal, { sessionKey: getSessionKey(exec) });
4381
+ const exits = receipt.exits ?? [];
4382
+ if (exits.some((code) => code !== 0)) throw new Error(JSON.stringify(receipt));
4038
4383
  return {
4039
4384
  kind: "copy",
4040
4385
  text: JSON.stringify(receipt),
4041
4386
  receipt,
4042
- exit: null,
4043
- durationMs: 0
4387
+ exit: exits.length > 0 ? 0 : null,
4388
+ durationMs: Date.now() - copyStart
4044
4389
  };
4045
4390
  }
4046
4391
  if ([
@@ -4126,6 +4471,7 @@ function createRemoteTool(driver, opts = {}) {
4126
4471
  if (r.outputStatsUnavailable) v.outputStatsUnavailable = true;
4127
4472
  if (r.session !== void 0) v.session = r.session;
4128
4473
  if (r.notice !== void 0) v.notice = r.notice;
4474
+ if (r.runner !== void 0) v.runner = r.runner;
4129
4475
  return v;
4130
4476
  }
4131
4477
  });
@@ -4150,7 +4496,8 @@ function renderValue(v) {
4150
4496
  const suffix = markers.length > 0 ? ` · ${markers.join(" · ")}` : "";
4151
4497
  const cwdTag = typeof v.cwd === "string" && v.cwd.length > 0 ? ` · cwd ${v.cwd}` : "";
4152
4498
  const sessionTag = typeof v.session === "string" && v.session.length > 0 ? ` · ${v.session}` : "";
4153
- parts.push(`[exit ${v.exit} · ${secs}s${suffix}${cwdTag}${sessionTag}]`);
4499
+ const runnerTag = typeof v.runner === "string" && v.runner.length > 0 ? ` · runner ${v.runner}` : "";
4500
+ parts.push(`[exit ${v.exit} · ${secs}s${suffix}${cwdTag}${sessionTag}${runnerTag}]`);
4154
4501
  if (v.stderr !== void 0 && v.stderr.length > 0) parts.push("[stderr]", v.stderr);
4155
4502
  return parts.join("\n");
4156
4503
  }
@@ -6,13 +6,14 @@
6
6
  "better-dsh/src/remote/agent-registration.ts": "459301354ea1ab713984bb01bc491a080256d4e983e55ff074e2665c3213d355",
7
7
  "better-dsh/src/remote/archive.ts": "fd32f96dc63421be7d56eb545badf355c6ee2498599605ffa48958b9efca9a63",
8
8
  "better-dsh/src/remote/copy.ts": "bd6f290d3f8ec3e33f9980f160b26390a3be38ead891b81de7cf610940a7af87",
9
- "better-dsh/src/remote/driver.ts": "f56d68f0eded0f4c145f6442170630a5f38d2e2a340be717adc97380d5a463ce",
9
+ "better-dsh/src/remote/driver.ts": "ba44b100228e54681a243d4b739aba14d2b5efe98c238220f1029cf9afba5e2b",
10
10
  "better-dsh/src/remote/endpoints.ts": "315b6c37e6e5dbd51301aa971566b8345593560e1f2ba299e71143e147a8a17c",
11
11
  "better-dsh/src/remote/file-worker.ts": "31ac019a944cf7fdcd0ff044f8b330d923bf4d384c77056f9b7e3032bc8c9598",
12
+ "better-dsh/src/remote/helper.ts": "789a802610fc480bb1c922dd284787ca22d7394fa906c729ee33d78ade79973c",
12
13
  "better-dsh/src/remote/hub-contract.ts": "4bd333f3ef3e94305a64f04c03948a9dae4bbf5268b0d26d9de99770be2d8ac9",
13
14
  "better-dsh/src/remote/input.ts": "7e543adb0973c25cbd24103c2d838db0fdacdd32525278d789004fc237dcd924",
14
15
  "better-dsh/src/remote/jobs.ts": "9587f2694426fcf00ff33d9db164d5b15ea659aed7dbcb1df2640fa3f08b2149",
15
- "better-dsh/src/remote/native-copy.ts": "49e1e1384c05637421f62d0eb562d9d5dfe00185ff2f6a15ae71d6881546d7fd",
16
+ "better-dsh/src/remote/native-copy.ts": "0c2045330c1007e49251643971d5edb9ef887a4964493450fd4184319d347b6e",
16
17
  "better-dsh/src/remote/nonce-framing.ts": "5592fec76cec0c1e1ac75f4806d0904cd111bf2061b1fada4f0dfa12014d1233",
17
18
  "better-dsh/src/remote/oneshot.ts": "99f2c809ba1159c7865ec3cff2e6d7b1f165a7f03185a6fc9505c1a534ba57bc",
18
19
  "better-dsh/src/remote/output-ring.ts": "a79104bd3dcddab06a3fe7e52d239a70becd4f2dcddd0c9b6513f5fe3c4ed0bc",
@@ -23,12 +24,12 @@
23
24
  "better-dsh/src/remote/rsync.ts": "21f10f0a24fd5148e298c938aaabeff85c96becc76317a1d3cc5c2e8a517c7c0",
24
25
  "better-dsh/src/remote/ssh-config.ts": "71ce833be5c934430e8a9ca982af055fccb71d6c3e64513ae83e7937b070e446",
25
26
  "better-dsh/src/remote/ssh-process.ts": "9b4d754af5af0fe6a903e683642e94842f8662358b72467d41f2288e1e67fd79",
26
- "better-dsh/src/remote/ssh-rsync-native-relay.ts": "3376cd389f11c6057408709ac65a58c8922ba04fd0b226feff5be8a84b6b04b5",
27
+ "better-dsh/src/remote/ssh-rsync-native-relay.ts": "3a30f65f1c548badd1e8a6018c4f7cacd8f75e2aec4d7b7181b03fc04f180f27",
27
28
  "better-dsh/src/remote/ssh-targets.ts": "d463357d03fec88f9cdc3c47bba85ae9213f2641b2c08689fe9a7af42fe8bcd4",
28
29
  "better-dsh/src/remote/status.ts": "54264917bd50401c5a2f2ff9df325af7a5e790597e6307fcdc46a8455d18b530",
29
30
  "better-dsh/src/remote/target.ts": "965a04b3561aa56ee089876a869fd2116b1773ef34b053b3006905fcde063a43",
30
- "better-dsh/src/remote/tool.ts": "a9a17c37a9554e1184a644160c5677eac08fced8e89358fce60092c86cfb142f",
31
- "better-dsh/src/remote/transports.ts": "c7dbe00f827aee9925146667a9a9f331527c3c1867d6f7f2a0ceedebcce1e225",
31
+ "better-dsh/src/remote/tool.ts": "997edf11d0512866682ee87ddd0a6b5e060db0c222d97d7544b2a52a5e8749bc",
32
+ "better-dsh/src/remote/transports.ts": "258aa92224a310d632c53a326d2e3d3d2b0f0f1bf2f9ceeb554bded03581ae18",
32
33
  "better-dsh/third_party/schemastery/lib/index.cjs": "aca1c1a47c7b6034feee01501aefca3e6dd97a0bac4fe334fd30647ae5a9e480",
33
34
  "better-dsh/third_party/schemastery/lib/index.d.mts": "66847f605af58c42575333c825eefdec4ad38278ad6cb260e37aa0cc63803bbd",
34
35
  "better-dsh/third_party/schemastery/lib/index.mjs": "cfcbe46c7416bdb35ce891c252152bbf519e08199bede5930dd7cb880c65f1ef",
@@ -56,7 +57,16 @@
56
57
  },
57
58
  "outputs": {
58
59
  "file-worker.js": "f84f5b48de915949d85c3d0340a343cc5901218c3bc2dafdf5cecaa244f7b6e3",
59
- "plugin.d.ts": "a1ea4b56c323bb1409c72160ccb75c54e6cfa73fb790505f51dce78caa148966",
60
- "plugin.js": "c5ff1c08b5548609517adaec736238425ee1753a4b65385c226af581f3508f70"
60
+ "helper-bin/MANIFEST.json": "c8c13fffd331abbdcfb29783e2ebcbe1ba9737d56ed495df2d78788c6b6c7d94",
61
+ "helper-bin/aarch64-apple-darwin/BUILT-VER": "0d13f4cceb4520b0970f93ee648432615239279700de836661c63f2c89ac41dd",
62
+ "helper-bin/aarch64-apple-darwin/superd-run": "715c2d7bd935f3b4cc4ae0ffb10d3fab946bb62d93f592ccfe2a7446669ff76b",
63
+ "helper-bin/aarch64-unknown-linux-musl/BUILT-VER": "0d13f4cceb4520b0970f93ee648432615239279700de836661c63f2c89ac41dd",
64
+ "helper-bin/aarch64-unknown-linux-musl/superd-run": "22ac1c7f913092d8ca8d312b93528dd2263200f9670dc183fd215bc89d2bac68",
65
+ "helper-bin/x86_64-pc-windows-gnu/BUILT-VER": "0d13f4cceb4520b0970f93ee648432615239279700de836661c63f2c89ac41dd",
66
+ "helper-bin/x86_64-pc-windows-gnu/superd-run.exe": "a638479e1ccb1c4e185085100450962e39164158a76097b5087d2a3bb8880ac0",
67
+ "helper-bin/x86_64-unknown-linux-musl/BUILT-VER": "0d13f4cceb4520b0970f93ee648432615239279700de836661c63f2c89ac41dd",
68
+ "helper-bin/x86_64-unknown-linux-musl/superd-run": "79e42879509bb87d2fe9888d282151fd17113203d3172f59a16fcb5a180ba057",
69
+ "plugin.d.ts": "b58e5a7148767a28ecc87b4fe1a39ff287ddba5cf6d1e538f6242dfb4d0485f8",
70
+ "plugin.js": "d97c93d87242aaac376858206cd3407f4283dd9b0036a190329efb26e305a04a"
61
71
  }
62
72
  }