better-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.
@@ -1,5 +1,5 @@
1
1
  import { t as Schema } from "../index-DTDXUe6m.js";
2
- import { r as MobileConfig } from "../web-trust-C_Y6o8Z2.js";
2
+ import { r as MobileConfig } from "../web-trust-Dej_RI2B.js";
3
3
  import { Context } from "@deepseek-ai/cordis";
4
4
 
5
5
  //#region src/mobile/plugin.d.ts
@@ -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
+ }
@@ -136,6 +136,23 @@ interface RsyncReceipt extends RunResult {
136
136
  */
137
137
  declare function runRsync(request: RsyncRequest, source: RsyncEndpoint, destination: RsyncEndpoint, signal: AbortSignal, options?: RelayRsyncOptions): Promise<RsyncReceipt>;
138
138
  //#endregion
139
+ //#region src/remote/helper.d.ts
140
+ interface HelperManifest {
141
+ format: 1;
142
+ name: string;
143
+ ver: string;
144
+ protocol: number;
145
+ targets: Record<string, {
146
+ file: string;
147
+ bytes: number;
148
+ sha256: string;
149
+ }>;
150
+ }
151
+ interface HelperAssets {
152
+ dir: string;
153
+ manifest: HelperManifest;
154
+ }
155
+ //#endregion
139
156
  //#region src/remote/process.d.ts
140
157
  declare const PROCESS_CLEANUP_BOUND_MS: number;
141
158
  interface ProcessOptions {
@@ -210,6 +227,8 @@ interface RemoteCallResult {
210
227
  session?: string;
211
228
  /** 引导/教学行(同 label 重复给 spawn 时的「可省略 spawn」提示等);无则省略。 */
212
229
  notice?: string;
230
+ /** oneshot 监督路径的如实标注:`superd-run <ver> (<triple>)` 或 `posix-shim`(spec remote-rescope §5)。 */
231
+ runner?: string;
213
232
  }
214
233
  interface RemoteAuditRecord {
215
234
  target: string;
@@ -234,6 +253,8 @@ interface RemoteDriverOptions {
234
253
  ptyArgvFor?: (plan: TargetPlan) => string[];
235
254
  spawnArgvFor?: (spawnCommand: string) => string[];
236
255
  probeRunner?: ProbeOptions['runner'];
256
+ /** 测试/验收缝:helper 资产来源(默认 lib 旁挂 helper-bin);显式 null 强制 shim 路径。 */
257
+ helperAssetsFor?: () => HelperAssets | null;
237
258
  /** 测试缝:roster 扫描执行器(bare-name 解析复用)。 */
238
259
  rosterRunner?: RosterOptions['runner'];
239
260
  /** 测试缝:ssh config 读取(bare-name 解析复用)。 */
@@ -250,6 +271,9 @@ declare class RemoteDriver {
250
271
  private readonly starting;
251
272
  private readonly fileAbort;
252
273
  private disposed;
274
+ /** undefined = 未尝试;null = 资产缺失(shim-only);registry = 每 target sticky 状态机。 */
275
+ private helpers;
276
+ private readonly runnerOf;
253
277
  private disposal;
254
278
  constructor(opts?: RemoteDriverOptions);
255
279
  call(params: RemoteCallParams, callCtx?: {
@@ -273,6 +297,10 @@ declare class RemoteDriver {
273
297
  start(input: RemoteInput, signal: AbortSignal): Promise<RemoteProcess>;
274
298
  private startPrepared;
275
299
  private nativeProcess;
300
+ /** Helper bootstrap is best-effort and sticky: any failure parks null for this driver
301
+ * lifetime and the shim stays the path. First call to a target pays probe (+ upload). */
302
+ private ensureHelper;
303
+ private helperExec;
276
304
  private own;
277
305
  /** Ruling 16/17:on-demand 探测 + 会话层,两行如实陈述。 */
278
306
  /**
@@ -1,12 +1,13 @@
1
1
  import { t as Schema } from "../lib-C8_jXvwA.js";
2
2
  import { Context } from "@deepseek-ai/cordis";
3
3
  import { createHash, randomBytes, randomUUID } from "node:crypto";
4
- import { constants, createReadStream, createWriteStream, mkdirSync, statSync } from "node:fs";
4
+ import { constants, createReadStream, createWriteStream, mkdirSync, readFileSync, statSync } from "node:fs";
5
5
  import { dirname, isAbsolute, join, posix, resolve } from "node:path";
6
6
  import { spawn } from "node:child_process";
7
+ import { fileURLToPath } from "node:url";
7
8
  import { homedir, tmpdir } from "node:os";
8
9
  import { defineTool } from "@deepseek-ai/dsh-tools";
9
- import { chmod, lstat, mkdir, mkdtemp, open, readFile, readdir, readlink, rename, rm, symlink, writeFile } from "node:fs/promises";
10
+ import { chmod, lstat, mkdir, mkdtemp, open, readFile, readdir, readlink, rename, rm, stat, symlink, writeFile } from "node:fs/promises";
10
11
  import { pipeline } from "node:stream/promises";
11
12
  import { Readable } from "node:stream";
12
13
  import { createConnection, createServer } from "node:net";
@@ -739,6 +740,7 @@ async function nativeCopy(request, endpoints, signal, options = {}) {
739
740
  const argv = [
740
741
  "scp",
741
742
  ...identityArgv(connection),
743
+ ...await recursiveFlag(endpoints.src.path, oneShot, "-r"),
742
744
  ...oneShot,
743
745
  endpoints.src.path,
744
746
  scpSpec(connection, endpoints.dst.path)
@@ -771,7 +773,7 @@ async function nativeCopy(request, endpoints, signal, options = {}) {
771
773
  dstSpec = scpSpec(destination, endpoints.dst.path);
772
774
  extra = identityArgv(source);
773
775
  } else {
774
- config = await tempSshConfig(source, destination);
776
+ config = await tempSshConfig(source, destination, runNative);
775
777
  extra = ["-F", config.path];
776
778
  srcSpec = `superd-scp3-source:${endpoints.src.path}`;
777
779
  dstSpec = `superd-scp3-destination:${endpoints.dst.path}`;
@@ -803,7 +805,9 @@ async function nativeCopy(request, endpoints, signal, options = {}) {
803
805
  endpoints.src.path,
804
806
  `${containerOf(endpoints.dst.plan)}:${endpoints.dst.path}`
805
807
  ];
806
- return finish("docker cp", [argv], [await runNative(wrap(argv), signal)]);
808
+ const result = await runNative(wrap(argv), signal);
809
+ withSymlinkHint(result);
810
+ return finish("docker cp", [argv], [result]);
807
811
  }
808
812
  if (s === "docker" && t === "local") {
809
813
  const argv = [
@@ -813,13 +817,16 @@ async function nativeCopy(request, endpoints, signal, options = {}) {
813
817
  `${containerOf(endpoints.src.plan)}:${endpoints.src.path}`,
814
818
  endpoints.dst.path
815
819
  ];
816
- return finish("docker cp", [argv], [await runNative(wrap(argv), signal)]);
820
+ const result = await runNative(wrap(argv), signal);
821
+ withSymlinkHint(result);
822
+ return finish("docker cp", [argv], [result]);
817
823
  }
818
824
  if (s === "local" && t === "incus") {
819
825
  const argv = [
820
826
  "incus",
821
827
  "file",
822
828
  "push",
829
+ ...await recursiveFlag(endpoints.src.path, oneShot, "-r"),
823
830
  ...oneShot,
824
831
  endpoints.src.path,
825
832
  `${containerOf(endpoints.dst.plan)}${endpoints.dst.path}`
@@ -913,30 +920,100 @@ function segmentArgv(plan, remote, staged, opts, leg) {
913
920
  }
914
921
  /** Distinguishing identities for scp -3: an origin-only temp config maps two
915
922
  * synthetic aliases; keys are referenced in place, never copied to any remote. */
916
- async function tempSshConfig(source, destination) {
917
- for (const c of [source, destination]) for (const [field, value] of [
918
- ["host", c.host],
919
- ["user", c.user],
920
- ["key", c.key],
921
- ["proxyJump", c.proxyJump]
922
- ]) if (value !== void 0 && /[\r\n]/.test(value)) throw new Error(`remote: scp -3 temp config rejects newline in SSH ${field} (no config injection)`);
923
+ /** D8 (2026-10-14 user adoption, third acceptance round): a LOCAL directory source gets
924
+ * the route's recursive flag appended automatically — scp / incus file push refuse
925
+ * directories without it. The appended flag lands in the executed argv, which the
926
+ * receipt shows verbatim: disclosure by receipt, never silent. Remote sources stay
927
+ * caller-explicit (we do not dial just to stat); an explicit caller flag wins. */
928
+ async function recursiveFlag(localPath, callerArgv, flag) {
929
+ if (callerArgv.includes(flag) || callerArgv.includes("--recursive")) return [];
930
+ try {
931
+ if ((await stat(localPath)).isDirectory()) return [flag];
932
+ } catch {}
933
+ return [];
934
+ }
935
+ /** docker cp follows symlinks only with -L; its native error ("invalid symlink")
936
+ * names no remedy. Append the one-line hint on that failure path (F5, 2026-10-14). */
937
+ function withSymlinkHint(result) {
938
+ 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)`;
939
+ }
940
+ async function tempSshConfig(source, destination, runNative$1) {
941
+ const resolvedSource = await resolveThroughOriginConfig(source, runNative$1);
942
+ const resolvedDestination = await resolveThroughOriginConfig(destination, runNative$1);
943
+ for (const { connection: c, identityFiles } of [resolvedSource, resolvedDestination]) {
944
+ for (const [field, value] of [
945
+ ["host", c.host],
946
+ ["user", c.user],
947
+ ["key", c.key],
948
+ ["proxyJump", c.proxyJump]
949
+ ]) if (value !== void 0 && /[\r\n]/.test(value)) throw new Error(`remote: scp -3 temp config rejects newline in SSH ${field} (no config injection)`);
950
+ 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)");
951
+ }
923
952
  const dir = await mkdtemp(join(tmpdir(), "superd-scp3-"));
924
953
  const path$1 = join(dir, "config");
925
- const block = (name$1, c) => {
954
+ const block = (name$1, c, identityFiles) => {
926
955
  const lines = [`Host ${name$1}`, ` HostName ${c.host.replace(/^.*@/, "")}`];
927
956
  if (c.user !== void 0) lines.push(` User ${c.user}`);
928
957
  if (c.port !== void 0) lines.push(` Port ${String(c.port)}`);
929
- if (c.key !== void 0) lines.push(` IdentityFile ${c.key}`);
958
+ for (const idFile of [c.key !== void 0 ? [c.key] : [], identityFiles].flat()) lines.push(` IdentityFile ${idFile}`);
930
959
  if (c.proxyJump !== void 0) lines.push(` ProxyJump ${c.proxyJump}`);
931
960
  return lines.join("\n");
932
961
  };
933
- await writeFile(path$1, `${block("superd-scp3-source", source)}\n${block("superd-scp3-destination", destination)}\n`, { mode: 384 });
962
+ await writeFile(path$1, `${block("superd-scp3-source", resolvedSource.connection, resolvedSource.identityFiles)}\n${block("superd-scp3-destination", resolvedDestination.connection, resolvedDestination.identityFiles)}\n`, { mode: 384 });
934
963
  await chmod(path$1, 384);
935
964
  return {
936
965
  path: path$1,
937
966
  dir
938
967
  };
939
968
  }
969
+ /** Effective fields for one connection per the origin's own ssh config (ssh -G,
970
+ * prints resolved settings without dialing). Explicit fields win; empty/none
971
+ * proxyjump is dropped. IdentityFile PATHS from the config are returned separately
972
+ * for inlining into the temp config — a path is not key material and stays on the
973
+ * origin (F1, 2026-10-14: dev4's only authorized key lived in config, not the agent;
974
+ * dropping it made scp -3 fail with a bare Permission denied). */
975
+ async function resolveThroughOriginConfig(c, runNative$1) {
976
+ let probe;
977
+ try {
978
+ probe = await runNative$1([
979
+ "ssh",
980
+ "-G",
981
+ c.host
982
+ ], new AbortController().signal);
983
+ } catch {
984
+ probe = void 0;
985
+ }
986
+ if (probe === void 0 || probe.exit !== 0) return {
987
+ connection: c,
988
+ identityFiles: []
989
+ };
990
+ const lines = probe.stdout.split("\n").map((line) => line.trim()).filter((line) => line.length > 0);
991
+ const pick = (key) => lines.find((line) => line.startsWith(`${key} `))?.slice(key.length + 1).trim() || void 0;
992
+ const home = process.env.HOME ?? "";
993
+ const compiledDefault = (path$1) => path$1 === "none" || [
994
+ "id_rsa",
995
+ "id_ecdsa",
996
+ "id_ecdsa_sk",
997
+ "id_ed25519",
998
+ "id_ed25519_sk"
999
+ ].some((name$1) => path$1 === `~/.ssh/${name$1}` || home !== "" && path$1 === `${home}/.ssh/${name$1}`);
1000
+ const identityFiles = [...new Set(lines.filter((line) => line.startsWith("identityfile ")).map((line) => line.slice(13).trim()).filter((path$1) => path$1 !== "" && !compiledDefault(path$1)))];
1001
+ const host = (pick("hostname") ?? c.host).replace(/^.*@/, "");
1002
+ const user = c.user ?? pick("user");
1003
+ const portText = pick("port");
1004
+ const port = c.port ?? (portText !== void 0 && /^\d+$/.test(portText) ? Number(portText) : void 0);
1005
+ const proxyJumpRaw = c.proxyJump ?? pick("proxyjump");
1006
+ return {
1007
+ connection: {
1008
+ host,
1009
+ ...user !== void 0 && user !== "" ? { user } : {},
1010
+ ...port !== void 0 && Number.isInteger(port) && port > 0 ? { port } : {},
1011
+ ...c.key !== void 0 ? { key: c.key } : {},
1012
+ ...proxyJumpRaw !== void 0 && proxyJumpRaw !== "" && proxyJumpRaw.toLowerCase() !== "none" ? { proxyJump: proxyJumpRaw } : {}
1013
+ },
1014
+ identityFiles
1015
+ };
1016
+ }
940
1017
 
941
1018
  //#endregion
942
1019
  //#region src/remote/ssh-rsync-native-relay.ts
@@ -1123,12 +1200,16 @@ async function forwardRoute(argv, source, destination, signal, options) {
1123
1200
  return await removeRemoteTemp(destination.connection, temp, wrap) ? "released" : "unknown";
1124
1201
  };
1125
1202
  try {
1203
+ signal.throwIfAborted();
1204
+ const daemonState = await waitForDaemonReady(destinationChild, 5e3);
1205
+ if (daemonState === "exited") throw new Error(`dual-SSH rsync destination daemon exited before serving${relayDetail(destinationChild, sourceHold)}`);
1206
+ if (daemonState === "timeout") throw new Error(`dual-SSH rsync destination daemon never announced readiness${relayDetail(destinationChild, sourceHold)}`);
1126
1207
  signal.throwIfAborted();
1127
1208
  if (!await originPortOpen(originPort, 15e3)) throw new Error(`dual-SSH rsync destination daemon never became reachable${relayDetail(destinationChild, sourceHold)}`);
1128
1209
  signal.throwIfAborted();
1129
1210
  const runArgv = relaySsh(source.connection, [], rsyncClientCommand(argv, source.path, sourcePort));
1130
1211
  const result = await runNative(wrap(runArgv), signal);
1131
- if (result.exit === 255) result.stderr = (result.stderr + relayDetail(destinationChild, sourceHold)).slice(-OUTPUT_LIMIT);
1212
+ if (result.exit !== 0) result.stderr = (result.stderr + relayDetail(destinationChild, sourceHold)).slice(-OUTPUT_LIMIT);
1132
1213
  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)}`);
1133
1214
  return {
1134
1215
  ...result,
@@ -1153,6 +1234,19 @@ async function forwardRoute(argv, source, destination, signal, options) {
1153
1234
  await Promise.allSettled([destinationChild.stop(), sourceHold.stop()]);
1154
1235
  }
1155
1236
  }
1237
+ /** Wait until the destination daemon script announces itself (stderr marker,
1238
+ * printed after its directory check and right before the daemon exec) or exits.
1239
+ * 'ready' only when the daemon is actually about to serve — closes the 0.3.1-e
1240
+ * race where -L opens at session start but the script dies ~150ms later. */
1241
+ async function waitForDaemonReady(held, budgetMs) {
1242
+ const deadline = Date.now() + budgetMs;
1243
+ for (;;) {
1244
+ if (/^SUPERD-RSYNC-TMP \S+$/m.test(held.stderrSink.text)) return "ready";
1245
+ if (held.child.exitCode !== null) return "exited";
1246
+ if (Date.now() >= deadline) return "timeout";
1247
+ await new Promise((resolve$1) => setTimeout(resolve$1, 50));
1248
+ }
1249
+ }
1156
1250
  function relayDetail(...held) {
1157
1251
  const detail = held.map((child) => child.stderrSink.text).filter(Boolean).join("\n");
1158
1252
  return detail ? `\n[relay stderr]\n${detail}` : "";
@@ -1489,6 +1583,96 @@ async function runOneShot(argv, opts = {}) {
1489
1583
  };
1490
1584
  }
1491
1585
 
1586
+ //#endregion
1587
+ //#region src/remote/helper.ts
1588
+ /** Reads helper-bin/MANIFEST.json next to the compiled module (lib/remote in the npm
1589
+ * package, super-dsh/remote in the Super closure — same relative layout). Missing or
1590
+ * malformed assets ⇒ null ⇒ shim-only mode; never throws. */
1591
+ function helperAssets(baseDir) {
1592
+ const dir = baseDir ?? join(dirname(fileURLToPath(import.meta.url)), "helper-bin");
1593
+ try {
1594
+ const manifest = JSON.parse(readFileSync(join(dir, "MANIFEST.json"), "utf8"));
1595
+ if (manifest?.format !== 1 || typeof manifest.ver !== "string" || typeof manifest.protocol !== "number" || !manifest.targets || typeof manifest.targets !== "object") return null;
1596
+ return {
1597
+ dir,
1598
+ manifest
1599
+ };
1600
+ } catch {
1601
+ return null;
1602
+ }
1603
+ }
1604
+ /** `uname -s`/`uname -m` → shipped target triple. Unknown combos ⇒ null (shim). */
1605
+ function archTriple(sys, machine, shipped) {
1606
+ const s = sys.trim().toLowerCase(), m = machine.trim().toLowerCase();
1607
+ 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;
1608
+ if (candidates === null) return null;
1609
+ return shipped.has(candidates) ? candidates : null;
1610
+ }
1611
+ function planKey(plan) {
1612
+ switch (plan.kind) {
1613
+ case "ssh": {
1614
+ const c = plan.connection;
1615
+ const host = c?.host ?? plan.host;
1616
+ return `ssh|${c?.user ? c.user + "@" : ""}${host}${c?.port ? ":" + c.port : ""}${c?.proxyJump ? "|" + c.proxyJump : ""}`;
1617
+ }
1618
+ case "docker": return `docker|${plan.container}`;
1619
+ case "incus": return `incus|${plan.container}`;
1620
+ }
1621
+ }
1622
+ const PROBE_RE = /^SUPERD-PROBE (\S+) (\S+)$/m;
1623
+ const READY_RE = /^SUPERD-READY (\S+)$/m;
1624
+ var HelperRegistry = class {
1625
+ states = /* @__PURE__ */ new Map();
1626
+ constructor(assets, exec, probeArgv, uploadArgv) {
1627
+ this.assets = assets;
1628
+ this.exec = exec;
1629
+ this.probeArgv = probeArgv;
1630
+ this.uploadArgv = uploadArgv;
1631
+ }
1632
+ /** Never throws: any bootstrap failure resolves null (sticky) and the caller stays on the shim. */
1633
+ ensure(plan) {
1634
+ if (plan.kind !== "ssh" && plan.kind !== "docker" && plan.kind !== "incus") return Promise.resolve(null);
1635
+ const key = planKey(plan);
1636
+ let entry = this.states.get(key);
1637
+ if (entry === void 0) {
1638
+ entry = this.bootstrap(plan).catch(() => null);
1639
+ entry.catch(() => {});
1640
+ this.states.set(key, entry);
1641
+ }
1642
+ return entry;
1643
+ }
1644
+ async bootstrap(plan) {
1645
+ const { manifest } = this.assets;
1646
+ const first = await this.exec(this.probeArgv(plan, this.assets), { timeoutSec: 15 });
1647
+ const ready = this.parseReady(first.stdout, manifest.ver, manifest.protocol);
1648
+ if (ready !== null) return ready;
1649
+ const probe = PROBE_RE.exec(first.stdout);
1650
+ if (probe === null || first.exit !== 90 && first.exit !== 0) return null;
1651
+ const triple = archTriple(probe[1], probe[2], new Set(Object.keys(manifest.targets)));
1652
+ if (triple === null) return null;
1653
+ const target = manifest.targets[triple];
1654
+ const binary = await readFile(join(this.assets.dir, triple, target.file));
1655
+ if ((await this.exec(this.uploadArgv(plan, triple, target.file, this.assets), {
1656
+ stdin: binary,
1657
+ timeoutSec: 60
1658
+ })).exit !== 0) return null;
1659
+ const second = await this.exec(this.probeArgv(plan, this.assets), { timeoutSec: 15 });
1660
+ return this.parseReady(second.stdout, manifest.ver, manifest.protocol);
1661
+ }
1662
+ parseReady(stdout, ver, protocol) {
1663
+ const ready = READY_RE.exec(stdout);
1664
+ const banner = /^SUPERD-RUN proto=(\d+) name=superd-run ver=(\S+) target=(\S+)/m.exec(stdout);
1665
+ if (ready === null || banner === null) return null;
1666
+ if (banner[1] !== String(protocol) || banner[2] !== ver) return null;
1667
+ return {
1668
+ binPath: ready[1],
1669
+ triple: banner[3],
1670
+ ver,
1671
+ protocol
1672
+ };
1673
+ }
1674
+ };
1675
+
1492
1676
  //#endregion
1493
1677
  //#region src/remote/transports.ts
1494
1678
  /** POSIX 单引号机械转义(唯一一层转义,spec §三"一层机械转义")。 */
@@ -1568,6 +1752,104 @@ function buildSpawnArgv(spawnCommand) {
1568
1752
  "/dev/null"
1569
1753
  ];
1570
1754
  }
1755
+ /** superd-run helper argv (spec: docs/specs/remote-rescope §5). Probe and upload are single
1756
+ * `sh -c` hops (busybox/alpine/darwin-safe); run/killgroup over ssh go through exactly one
1757
+ * remote-shell parse, same discipline as buildOneShotArgv. */
1758
+ function buildHelperProbeArgv(plan, assets) {
1759
+ const { ver, targets } = assets.manifest;
1760
+ 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`);
1761
+ }
1762
+ function buildHelperUploadArgv(plan, triple, file, assets) {
1763
+ const dir = `$HOME/.cache/superd/run/${triple}-${assets.manifest.ver}`;
1764
+ return helperShellArgv(plan, `mkdir -p "${dir}" && cat > "${dir}/${file}.tmp" && chmod 0755 "${dir}/${file}.tmp" && mv -f "${dir}/${file}.tmp" "${dir}/${file}"`);
1765
+ }
1766
+ function buildHelperOneShotArgv(plan, binPath, options) {
1767
+ const { tag, cmd } = options;
1768
+ switch (plan.kind) {
1769
+ case "ssh": return sshArgv(plan.connection ?? { host: plan.host }, { command: `exec ${shQuote(binPath)} run --tag ${shQuote(tag)} -- bash -lc ${shQuote(cmd)}` });
1770
+ case "docker": return [
1771
+ "docker",
1772
+ "exec",
1773
+ "-i",
1774
+ "--",
1775
+ plan.container,
1776
+ binPath,
1777
+ "run",
1778
+ "--tag",
1779
+ tag,
1780
+ "--",
1781
+ "bash",
1782
+ "-lc",
1783
+ cmd
1784
+ ];
1785
+ case "incus": return [
1786
+ "incus",
1787
+ "exec",
1788
+ "--force-noninteractive",
1789
+ plan.container,
1790
+ "--",
1791
+ binPath,
1792
+ "run",
1793
+ "--tag",
1794
+ tag,
1795
+ "--",
1796
+ "bash",
1797
+ "-lc",
1798
+ cmd
1799
+ ];
1800
+ }
1801
+ }
1802
+ function buildHelperKillgroupArgv(plan, binPath, tag) {
1803
+ switch (plan.kind) {
1804
+ case "ssh": return sshArgv(plan.connection ?? { host: plan.host }, { command: `${shQuote(binPath)} killgroup --tag ${shQuote(tag)}` });
1805
+ case "docker": return [
1806
+ "docker",
1807
+ "exec",
1808
+ "--",
1809
+ plan.container,
1810
+ binPath,
1811
+ "killgroup",
1812
+ "--tag",
1813
+ tag
1814
+ ];
1815
+ case "incus": return [
1816
+ "incus",
1817
+ "exec",
1818
+ "--force-noninteractive",
1819
+ plan.container,
1820
+ "--",
1821
+ binPath,
1822
+ "killgroup",
1823
+ "--tag",
1824
+ tag
1825
+ ];
1826
+ }
1827
+ }
1828
+ function helperShellArgv(plan, script) {
1829
+ switch (plan.kind) {
1830
+ case "ssh": return sshArgv(plan.connection ?? { host: plan.host }, { command: script });
1831
+ case "docker": return [
1832
+ "docker",
1833
+ "exec",
1834
+ "-i",
1835
+ "--",
1836
+ plan.container,
1837
+ "sh",
1838
+ "-c",
1839
+ script
1840
+ ];
1841
+ case "incus": return [
1842
+ "incus",
1843
+ "exec",
1844
+ "--force-noninteractive",
1845
+ plan.container,
1846
+ "--",
1847
+ "sh",
1848
+ "-c",
1849
+ script
1850
+ ];
1851
+ }
1852
+ }
1571
1853
 
1572
1854
  //#endregion
1573
1855
  //#region src/remote/nonce-framing.ts
@@ -2297,6 +2579,9 @@ var RemoteDriver = class {
2297
2579
  starting = /* @__PURE__ */ new Set();
2298
2580
  fileAbort = new AbortController();
2299
2581
  disposed = false;
2582
+ /** undefined = 未尝试;null = 资产缺失(shim-only);registry = 每 target sticky 状态机。 */
2583
+ helpers;
2584
+ runnerOf = /* @__PURE__ */ new WeakMap();
2300
2585
  disposal;
2301
2586
  constructor(opts = {}) {
2302
2587
  this.opts = opts;
@@ -2489,12 +2774,32 @@ var RemoteDriver = class {
2489
2774
  if (signal.aborted || this.disposed) process$1.cancel("owner closed during start");
2490
2775
  return process$1;
2491
2776
  }
2492
- nativeProcess(plan, params, timeoutSec, signal = this.fileAbort.signal) {
2777
+ async nativeProcess(plan, params, timeoutSec, signal = this.fileAbort.signal) {
2493
2778
  const cleanupTag = randomUUID().slice(0, 8);
2779
+ const helper = await this.ensureHelper(plan);
2780
+ if (helper !== null && !this.disposed) {
2781
+ const process$2 = startOneShot(buildHelperOneShotArgv(plan, helper.binPath, {
2782
+ tag: cleanupTag,
2783
+ cmd: params.cmd
2784
+ }), {
2785
+ stdin: params.stdin,
2786
+ timeoutSec
2787
+ });
2788
+ this.runnerOf.set(process$2, `superd-run ${helper.ver} (${helper.triple})`);
2789
+ process$2.done.then((result) => {
2790
+ if (!result.cancelled && !result.timedOut) return;
2791
+ startOneShot(buildHelperKillgroupArgv(plan, helper.binPath, cleanupTag), { timeoutSec: 15 }).done.catch(() => {});
2792
+ }).catch(() => {});
2793
+ const tracked = Promise.resolve(process$2);
2794
+ this.starting.add(tracked);
2795
+ tracked.then(() => this.starting.delete(tracked), () => this.starting.delete(tracked));
2796
+ return tracked;
2797
+ }
2494
2798
  const process$1 = startOneShot((this.opts.oneshotArgvFor ?? buildOneShotArgv)(plan, params.cmd, { cleanupTag }), {
2495
2799
  stdin: params.stdin,
2496
2800
  timeoutSec
2497
2801
  });
2802
+ this.runnerOf.set(process$1, "posix-shim");
2498
2803
  process$1.done.then((result) => {
2499
2804
  if (!result.cancelled && !result.timedOut) return;
2500
2805
  const pidfile = `"\${TMPDIR:-/tmp}/superd-oneshot-${cleanupTag}.pgid"`;
@@ -2506,6 +2811,38 @@ var RemoteDriver = class {
2506
2811
  work.then(() => this.starting.delete(work), () => this.starting.delete(work));
2507
2812
  return work;
2508
2813
  }
2814
+ /** Helper bootstrap is best-effort and sticky: any failure parks null for this driver
2815
+ * lifetime and the shim stays the path. First call to a target pays probe (+ upload). */
2816
+ async ensureHelper(plan) {
2817
+ if (this.helpers === void 0) {
2818
+ const assets = this.opts.helperAssetsFor?.() ?? helperAssets();
2819
+ this.helpers = assets === null ? null : new HelperRegistry(assets, (argv, options) => this.helperExec(argv, options), buildHelperProbeArgv, buildHelperUploadArgv);
2820
+ }
2821
+ if (this.helpers === null || this.disposed) return null;
2822
+ try {
2823
+ return await this.helpers.ensure(plan);
2824
+ } catch {
2825
+ return null;
2826
+ }
2827
+ }
2828
+ async helperExec(argv, options) {
2829
+ this.assertOpen();
2830
+ const stdin = options?.stdin;
2831
+ if (stdin !== void 0) {
2832
+ const proc$1 = startBinaryProcess(argv, { timeoutSec: options?.timeoutSec });
2833
+ proc$1.stdin.on("error", () => {});
2834
+ proc$1.stdin.end(stdin);
2835
+ return {
2836
+ exit: (await proc$1.done).exit,
2837
+ stdout: ""
2838
+ };
2839
+ }
2840
+ const proc = startOneShot(argv, { timeoutSec: options?.timeoutSec });
2841
+ return {
2842
+ exit: (await proc.done).exit,
2843
+ stdout: proc.read("stdout", 0).text
2844
+ };
2845
+ }
2509
2846
  own(process$1) {
2510
2847
  this.processes.add(process$1);
2511
2848
  process$1.done.then(() => this.processes.delete(process$1));
@@ -2783,7 +3120,8 @@ var RemoteDriver = class {
2783
3120
  stderr: err?.stats ?? r$1.outputStats?.stderr
2784
3121
  } } : {},
2785
3122
  durationMs: r$1.durationMs,
2786
- ...out$1.truncated !== void 0 ? { truncated: out$1.truncated } : {}
3123
+ ...out$1.truncated !== void 0 ? { truncated: out$1.truncated } : {},
3124
+ ...this.runnerOf.get(process$1) === void 0 ? {} : { runner: this.runnerOf.get(process$1) }
2787
3125
  };
2788
3126
  }
2789
3127
  const argv = (this.opts.ptyArgvFor ?? buildPtyArgv)(routing.plan);
@@ -2946,9 +3284,9 @@ const REMOTE_TOOL_DESCRIPTION = `Remote execution and file transfer over ssh / d
2946
3284
  {target:"byop:lbl", spawn, cmd} → create the named shell once; reuse as {target:"byop:lbl", cmd} (no spawn)
2947
3285
  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.
2948
3286
 
2949
- 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.
3287
+ 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).
2950
3288
 
2951
- 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.
3289
+ 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.
2952
3290
 
2953
3291
  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.`;
2954
3292
  function createRemoteTool(driver, opts = {}) {
@@ -2973,7 +3311,7 @@ function createRemoteTool(driver, opts = {}) {
2973
3311
  argv: {
2974
3312
  type: "array",
2975
3313
  items: { type: "string" },
2976
- 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."
3314
+ 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."
2977
3315
  },
2978
3316
  pullArgv: {
2979
3317
  type: "array",
@@ -3088,7 +3426,11 @@ function createRemoteTool(driver, opts = {}) {
3088
3426
  outputStats: { type: "json" },
3089
3427
  outputStatsUnavailable: { type: "boolean" },
3090
3428
  session: { type: "string" },
3091
- notice: { type: "string" }
3429
+ notice: { type: "string" },
3430
+ runner: {
3431
+ type: "string",
3432
+ description: "oneshot supervision path: superd-run <ver> (<triple>) or posix-shim"
3433
+ }
3092
3434
  }
3093
3435
  },
3094
3436
  render: (_args, value) => [{
@@ -3134,6 +3476,7 @@ function createRemoteTool(driver, opts = {}) {
3134
3476
  durationMs: Date.now() - start
3135
3477
  };
3136
3478
  }
3479
+ const copyStart = Date.now();
3137
3480
  const receipt = await driver.copy({
3138
3481
  src: args.src,
3139
3482
  dst: args.dst,
@@ -3143,12 +3486,14 @@ function createRemoteTool(driver, opts = {}) {
3143
3486
  ...args.pullArgv === void 0 ? {} : { pullArgv: args.pullArgv },
3144
3487
  ...args.pushArgv === void 0 ? {} : { pushArgv: args.pushArgv }
3145
3488
  }, exec.signal, { sessionKey: getSessionKey(exec) });
3489
+ const exits = receipt.exits ?? [];
3490
+ if (exits.some((code) => code !== 0)) throw new Error(JSON.stringify(receipt));
3146
3491
  return {
3147
3492
  kind: "copy",
3148
3493
  text: JSON.stringify(receipt),
3149
3494
  receipt,
3150
- exit: null,
3151
- durationMs: 0
3495
+ exit: exits.length > 0 ? 0 : null,
3496
+ durationMs: Date.now() - copyStart
3152
3497
  };
3153
3498
  }
3154
3499
  if ([
@@ -3234,6 +3579,7 @@ function createRemoteTool(driver, opts = {}) {
3234
3579
  if (r.outputStatsUnavailable) v.outputStatsUnavailable = true;
3235
3580
  if (r.session !== void 0) v.session = r.session;
3236
3581
  if (r.notice !== void 0) v.notice = r.notice;
3582
+ if (r.runner !== void 0) v.runner = r.runner;
3237
3583
  return v;
3238
3584
  }
3239
3585
  });
@@ -3258,7 +3604,8 @@ function renderValue(v) {
3258
3604
  const suffix = markers.length > 0 ? ` · ${markers.join(" · ")}` : "";
3259
3605
  const cwdTag = typeof v.cwd === "string" && v.cwd.length > 0 ? ` · cwd ${v.cwd}` : "";
3260
3606
  const sessionTag = typeof v.session === "string" && v.session.length > 0 ? ` · ${v.session}` : "";
3261
- parts.push(`[exit ${v.exit} · ${secs}s${suffix}${cwdTag}${sessionTag}]`);
3607
+ const runnerTag = typeof v.runner === "string" && v.runner.length > 0 ? ` · runner ${v.runner}` : "";
3608
+ parts.push(`[exit ${v.exit} · ${secs}s${suffix}${cwdTag}${sessionTag}${runnerTag}]`);
3262
3609
  if (v.stderr !== void 0 && v.stderr.length > 0) parts.push("[stderr]", v.stderr);
3263
3610
  return parts.join("\n");
3264
3611
  }
@@ -1,6 +1,6 @@
1
+ import { t as Schema } from "../index-DTDXUe6m.js";
1
2
  import { Context } from "@deepseek-ai/cordis";
2
3
  import { ToolDefinition } from "@deepseek-ai/dsh-tools";
3
- import * as _deepseek_ai_schemastery11 from "@deepseek-ai/schemastery";
4
4
 
5
5
  //#region src/url-schemes/tools/write.d.ts
6
6
 
@@ -50,12 +50,12 @@ declare const inject: string[];
50
50
  * real patch-line config. Schema-level defaults (both ON — the service is
51
51
  * opt-out) survive every overlay layer, per the v0.2.2a ruling.
52
52
  */
53
- declare const Config: _deepseek_ai_schemastery11.default<Schemastery.ObjectS<NoInfer<{
54
- urlSchemes: _deepseek_ai_schemastery11.default<boolean, boolean, "defined">;
55
- hashline: _deepseek_ai_schemastery11.default<boolean, boolean, "defined">;
53
+ declare const Config: Schema<Schemastery.ObjectS<NoInfer<{
54
+ urlSchemes: Schema<boolean, boolean, "defined">;
55
+ hashline: Schema<boolean, boolean, "defined">;
56
56
  }>>, Schemastery.ObjectT<NoInfer<{
57
- urlSchemes: _deepseek_ai_schemastery11.default<boolean, boolean, "defined">;
58
- hashline: _deepseek_ai_schemastery11.default<boolean, boolean, "defined">;
57
+ urlSchemes: Schema<boolean, boolean, "defined">;
58
+ hashline: Schema<boolean, boolean, "defined">;
59
59
  }>>, "plain">;
60
60
  /** Register the four URL-aware tools on one agent's own scope layer. */
61
61
  /**
@@ -75,12 +75,12 @@ declare function apply(ctx: Context, config: UrlSchemesConfig | undefined): void
75
75
  declare const _default: {
76
76
  name: string;
77
77
  inject: string[];
78
- Config: _deepseek_ai_schemastery11.default<Schemastery.ObjectS<NoInfer<{
79
- urlSchemes: _deepseek_ai_schemastery11.default<boolean, boolean, "defined">;
80
- hashline: _deepseek_ai_schemastery11.default<boolean, boolean, "defined">;
78
+ Config: Schema<Schemastery.ObjectS<NoInfer<{
79
+ urlSchemes: Schema<boolean, boolean, "defined">;
80
+ hashline: Schema<boolean, boolean, "defined">;
81
81
  }>>, Schemastery.ObjectT<NoInfer<{
82
- urlSchemes: _deepseek_ai_schemastery11.default<boolean, boolean, "defined">;
83
- hashline: _deepseek_ai_schemastery11.default<boolean, boolean, "defined">;
82
+ urlSchemes: Schema<boolean, boolean, "defined">;
83
+ hashline: Schema<boolean, boolean, "defined">;
84
84
  }>>, "plain">;
85
85
  apply: typeof apply;
86
86
  };
@@ -1,7 +1,7 @@
1
+ import { t as Schema } from "./index-DTDXUe6m.js";
1
2
  import { Context } from "@deepseek-ai/cordis";
2
3
  import { IncomingMessage } from "node:http";
3
4
  import { CredentialRecord } from "@deepseek-ai/dsh-credentials";
4
- import * as _deepseek_ai_schemastery21 from "@deepseek-ai/schemastery";
5
5
 
6
6
  //#region src/web-password.d.ts
7
7
 
@@ -123,10 +123,10 @@ interface WebPasswordConfig {
123
123
  /** Absolute browser-session lifetime in days. Default: 30 (the native default). */
124
124
  cookieMaxAgeDays?: number;
125
125
  }
126
- declare const Config: _deepseek_ai_schemastery21.default<Schemastery.ObjectS<NoInfer<{
127
- cookieMaxAgeDays: _deepseek_ai_schemastery21.default<number, number, "defined">;
126
+ declare const Config: Schema<Schemastery.ObjectS<NoInfer<{
127
+ cookieMaxAgeDays: Schema<number, number, "defined">;
128
128
  }>>, Schemastery.ObjectT<NoInfer<{
129
- cookieMaxAgeDays: _deepseek_ai_schemastery21.default<number, number, "defined">;
129
+ cookieMaxAgeDays: Schema<number, number, "defined">;
130
130
  }>>, "plain">;
131
131
  /** Cordis plugin name; also the scope of this row's credential record. */
132
132
  declare const name = "dashr-web-password";
@@ -145,10 +145,10 @@ declare function apply(ctx: Context, config?: WebPasswordConfig): void;
145
145
  declare const _default: {
146
146
  name: string;
147
147
  inject: string[];
148
- Config: _deepseek_ai_schemastery21.default<Schemastery.ObjectS<NoInfer<{
149
- cookieMaxAgeDays: _deepseek_ai_schemastery21.default<number, number, "defined">;
148
+ Config: Schema<Schemastery.ObjectS<NoInfer<{
149
+ cookieMaxAgeDays: Schema<number, number, "defined">;
150
150
  }>>, Schemastery.ObjectT<NoInfer<{
151
- cookieMaxAgeDays: _deepseek_ai_schemastery21.default<number, number, "defined">;
151
+ cookieMaxAgeDays: Schema<number, number, "defined">;
152
152
  }>>, "plain">;
153
153
  apply: typeof apply;
154
154
  };
@@ -1,5 +1,5 @@
1
+ import { t as Schema } from "./index-DTDXUe6m.js";
1
2
  import { Context } from "@deepseek-ai/cordis";
2
- import * as _deepseek_ai_schemastery0 from "@deepseek-ai/schemastery";
3
3
 
4
4
  //#region src/web-trust.d.ts
5
5
 
@@ -76,12 +76,12 @@ interface TrustConfig {
76
76
  trustedPageAuthorities?: readonly string[];
77
77
  }
78
78
  /** Row config schema (schema-level default derives from `DSH_TRUSTED_HOSTS`). */
79
- declare const Config: _deepseek_ai_schemastery0.default<Schemastery.ObjectS<NoInfer<{
80
- trustAllHosts: _deepseek_ai_schemastery0.default<boolean, boolean, "defined">;
81
- trustedPageAuthorities: _deepseek_ai_schemastery0.default<string[], string[], "defined">;
79
+ declare const Config: Schema<Schemastery.ObjectS<NoInfer<{
80
+ trustAllHosts: Schema<boolean, boolean, "defined">;
81
+ trustedPageAuthorities: Schema<string[], string[], "defined">;
82
82
  }>>, Schemastery.ObjectT<NoInfer<{
83
- trustAllHosts: _deepseek_ai_schemastery0.default<boolean, boolean, "defined">;
84
- trustedPageAuthorities: _deepseek_ai_schemastery0.default<string[], string[], "defined">;
83
+ trustAllHosts: Schema<boolean, boolean, "defined">;
84
+ trustedPageAuthorities: Schema<string[], string[], "defined">;
85
85
  }>>, "plain">;
86
86
  /** Cordis plugin name. */
87
87
  declare const name = "dashr-web-trust";
@@ -100,12 +100,12 @@ declare function apply(ctx: Context, config: TrustConfig | undefined): void;
100
100
  declare const _default: {
101
101
  name: string;
102
102
  inject: string[];
103
- Config: _deepseek_ai_schemastery0.default<Schemastery.ObjectS<NoInfer<{
104
- trustAllHosts: _deepseek_ai_schemastery0.default<boolean, boolean, "defined">;
105
- trustedPageAuthorities: _deepseek_ai_schemastery0.default<string[], string[], "defined">;
103
+ Config: Schema<Schemastery.ObjectS<NoInfer<{
104
+ trustAllHosts: Schema<boolean, boolean, "defined">;
105
+ trustedPageAuthorities: Schema<string[], string[], "defined">;
106
106
  }>>, Schemastery.ObjectT<NoInfer<{
107
- trustAllHosts: _deepseek_ai_schemastery0.default<boolean, boolean, "defined">;
108
- trustedPageAuthorities: _deepseek_ai_schemastery0.default<string[], string[], "defined">;
107
+ trustAllHosts: Schema<boolean, boolean, "defined">;
108
+ trustedPageAuthorities: Schema<string[], string[], "defined">;
109
109
  }>>, "plain">;
110
110
  apply: typeof apply;
111
111
  };
@@ -1,2 +1,3 @@
1
- import { a as _default, c as buildTrustScript, d as name, i as TrustConfig, l as deriveDefaultPageAuthorities, n as Config, o as apply, r as MobileConfig, s as buildMobileScript, t as BootScriptRow, u as inject } from "./web-trust-C_Y6o8Z2.js";
1
+ import "./index-DTDXUe6m.js";
2
+ import { a as _default, c as buildTrustScript, d as name, i as TrustConfig, l as deriveDefaultPageAuthorities, n as Config, o as apply, r as MobileConfig, s as buildMobileScript, t as BootScriptRow, u as inject } from "./web-trust-Dej_RI2B.js";
2
3
  export { BootScriptRow, Config, MobileConfig, TrustConfig, apply, buildMobileScript, buildTrustScript, _default as default, deriveDefaultPageAuthorities, inject, name };
@@ -1,15 +1,15 @@
1
+ import { t as Schema } from "./index-DTDXUe6m.js";
1
2
  import { Context } from "@deepseek-ai/cordis";
2
- import * as _deepseek_ai_schemastery9 from "@deepseek-ai/schemastery";
3
3
 
4
4
  //#region src/welcome-notice.d.ts
5
5
  declare const name = "dashr-welcome-notice";
6
6
  declare const inject: string[];
7
- declare const Config: _deepseek_ai_schemastery9.default<NoInfer<Schemastery.ObjectS<{}>>, NoInfer<Schemastery.ObjectT<{}>>, "volatile">;
7
+ declare const Config: Schema<NoInfer<Schemastery.ObjectS<{}>>, NoInfer<Schemastery.ObjectT<{}>>, "volatile">;
8
8
  declare function apply(ctx: Context): void;
9
9
  declare const _default: {
10
10
  name: string;
11
11
  inject: string[];
12
- Config: _deepseek_ai_schemastery9.default<NoInfer<Schemastery.ObjectS<{}>>, NoInfer<Schemastery.ObjectT<{}>>, "volatile">;
12
+ Config: Schema<NoInfer<Schemastery.ObjectS<{}>>, NoInfer<Schemastery.ObjectT<{}>>, "volatile">;
13
13
  apply: typeof apply;
14
14
  };
15
15
  //#endregion
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "better-dsh",
3
- "version": "0.3.1-a",
3
+ "version": "0.3.1-b",
4
4
  "description": "Make your dsh ready for serious coding tasks. (Tools x Schemas)^REPL. `skill://`, `ctx://`, `agent://`, `dvc://`, `dsh://`, Python REPL, Context as Variables, cross compactions recallable, full context revive. `hash-edit`, `dvc://browser`, subagent as function, workflow as function.",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",
@@ -75,7 +75,7 @@
75
75
  ],
76
76
  "scripts": {
77
77
  "prebuild": "node scripts/copy-docs.mjs",
78
- "build": "tsdown && npm run build-client && node scripts/copy-kernel-bridge.mjs && node scripts/copy-ast-assets.mjs",
78
+ "build": "tsdown && npm run build-client && node scripts/copy-kernel-bridge.mjs && node scripts/copy-ast-assets.mjs && node scripts/copy-helper-bins.mjs",
79
79
  "typecheck": "npm run typecheck:host && npm run typecheck:client",
80
80
  "typecheck:host": "tsc --noEmit",
81
81
  "typecheck:client": "tsc -p tsconfig.client.json",