@nimbus-sh/core 0.3.0 → 0.5.0

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.
Files changed (155) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +140 -0
  3. package/dist/_shared/error-text.d.ts +15 -0
  4. package/dist/_shared/error-text.d.ts.map +1 -0
  5. package/dist/_shared/error-text.js +21 -0
  6. package/dist/_shared/exports-resolver.d.ts +19 -7
  7. package/dist/_shared/exports-resolver.d.ts.map +1 -1
  8. package/dist/_shared/exports-resolver.js +1 -1
  9. package/dist/_shared/retry.d.ts.map +1 -1
  10. package/dist/_shared/retry.js +3 -1
  11. package/dist/_shared/tarball-stream.d.ts +93 -0
  12. package/dist/_shared/tarball-stream.d.ts.map +1 -0
  13. package/dist/_shared/tarball-stream.js +235 -0
  14. package/dist/_shared/tarball.d.ts +17 -0
  15. package/dist/_shared/tarball.d.ts.map +1 -0
  16. package/dist/_shared/tarball.js +39 -0
  17. package/dist/_shared/w7-frame.js +2 -1
  18. package/dist/constants.d.ts.map +1 -1
  19. package/dist/constants.js +30 -16
  20. package/dist/observability/oom-classify.d.ts +1 -1
  21. package/dist/observability/oom-classify.d.ts.map +1 -1
  22. package/dist/observability/oom-classify.js +7 -0
  23. package/dist/observability/oom-discriminator.d.ts +1 -1
  24. package/dist/runtime/clang-runner.d.ts +38 -0
  25. package/dist/runtime/clang-runner.d.ts.map +1 -0
  26. package/dist/runtime/clang-runner.js +866 -0
  27. package/dist/runtime/esbuild-service.d.ts +4 -3
  28. package/dist/runtime/esbuild-service.d.ts.map +1 -1
  29. package/dist/runtime/esbuild-service.js +9 -4
  30. package/dist/runtime/facet-host.d.ts +12 -0
  31. package/dist/runtime/facet-host.d.ts.map +1 -1
  32. package/dist/runtime/installed-runtimes.d.ts +4 -3
  33. package/dist/runtime/installed-runtimes.d.ts.map +1 -1
  34. package/dist/runtime/local-facet-host.d.ts.map +1 -1
  35. package/dist/runtime/local-facet-host.js +29 -9
  36. package/dist/runtime/long-running-handle.d.ts +3 -3
  37. package/dist/runtime/long-running-handle.d.ts.map +1 -1
  38. package/dist/runtime/os-contracts.d.ts +7 -5
  39. package/dist/runtime/os-contracts.d.ts.map +1 -1
  40. package/dist/runtime/port-registry.d.ts +28 -0
  41. package/dist/runtime/port-registry.d.ts.map +1 -1
  42. package/dist/runtime/port-registry.js +79 -9
  43. package/dist/runtime/process-logs.d.ts +9 -1
  44. package/dist/runtime/process-logs.d.ts.map +1 -1
  45. package/dist/runtime/project-detect.d.ts +6 -1
  46. package/dist/runtime/project-detect.d.ts.map +1 -1
  47. package/dist/runtime/require-resolver.d.ts.map +1 -1
  48. package/dist/runtime/require-resolver.js +3 -4
  49. package/dist/runtime/ruby-gems.d.ts +30 -0
  50. package/dist/runtime/ruby-gems.d.ts.map +1 -0
  51. package/dist/runtime/ruby-gems.js +636 -0
  52. package/dist/runtime/ruby-runner.d.ts +127 -0
  53. package/dist/runtime/ruby-runner.d.ts.map +1 -0
  54. package/dist/runtime/ruby-runner.js +1357 -0
  55. package/dist/runtime/runtime-registry.d.ts +4 -3
  56. package/dist/runtime/runtime-registry.d.ts.map +1 -1
  57. package/dist/runtime/runtime-registry.js +2 -1
  58. package/dist/runtime/session-process-supervisor.d.ts +15 -0
  59. package/dist/runtime/session-process-supervisor.d.ts.map +1 -1
  60. package/dist/runtime/session-process-supervisor.js +30 -0
  61. package/dist/runtime/sqlite-runtime-fs-bridge.js +1 -5
  62. package/dist/runtime/virtual-socket-kernel.d.ts.map +1 -1
  63. package/dist/runtime/virtual-socket-kernel.generated.d.ts +1 -1
  64. package/dist/runtime/virtual-socket-kernel.generated.d.ts.map +1 -1
  65. package/dist/runtime/virtual-socket-kernel.generated.js +2 -2
  66. package/dist/runtime/virtual-socket-kernel.js +10 -5
  67. package/dist/runtime/wasm-runner.d.ts.map +1 -1
  68. package/dist/runtime/wasm-runner.js +22 -14
  69. package/dist/shell/features.d.ts.map +1 -1
  70. package/dist/shell/features.js +5 -4
  71. package/dist/shell/unix-commands.d.ts +14 -1
  72. package/dist/shell/unix-commands.d.ts.map +1 -1
  73. package/dist/shell/unix-commands.js +115 -69
  74. package/dist/substrate/lifo/commands/net/ip.d.ts.map +1 -1
  75. package/dist/substrate/lifo/commands/system/ps.d.ts +2 -1
  76. package/dist/substrate/lifo/commands/system/ps.d.ts.map +1 -1
  77. package/dist/substrate/lifo/kernel/ServiceManager.d.ts.map +1 -1
  78. package/dist/substrate/lifo/kernel/ServiceManager.js +0 -2
  79. package/dist/substrate/lifo/kernel/network/NetworkStack.d.ts +22 -11
  80. package/dist/substrate/lifo/kernel/network/NetworkStack.d.ts.map +1 -1
  81. package/dist/substrate/lifo/kernel/network/NetworkStack.js +0 -2
  82. package/dist/substrate/lifo/kernel/network/tunnel/WebSocketTunnel.d.ts +2 -1
  83. package/dist/substrate/lifo/kernel/network/tunnel/WebSocketTunnel.d.ts.map +1 -1
  84. package/dist/substrate/lifo/kernel/network/tunnel/WebSocketTunnel.js +3 -4
  85. package/dist/substrate/lifo/kernel/vfs/VFS.d.ts +17 -0
  86. package/dist/substrate/lifo/kernel/vfs/VFS.d.ts.map +1 -1
  87. package/dist/substrate/lifo/kernel/vfs/VFS.js +33 -0
  88. package/dist/substrate/lifo/node-compat/esbuild.d.ts.map +1 -1
  89. package/dist/substrate/lifo/node-compat/esbuild.js +2 -4
  90. package/dist/substrate/lifo/node-compat/index.d.ts.map +1 -1
  91. package/dist/substrate/lifo/node-compat/index.js +3 -2
  92. package/dist/substrate/lifo/node-compat/loose-equality.d.ts +19 -0
  93. package/dist/substrate/lifo/node-compat/loose-equality.d.ts.map +1 -0
  94. package/dist/substrate/lifo/node-compat/loose-equality.js +91 -0
  95. package/dist/substrate/lifo/node-compat/process.d.ts.map +1 -1
  96. package/dist/substrate/lifo/node-compat/process.js +6 -3
  97. package/dist/substrate/lifo/shell/Shell.d.ts +19 -0
  98. package/dist/substrate/lifo/shell/Shell.d.ts.map +1 -1
  99. package/dist/substrate/lifo/shell/Shell.js +86 -75
  100. package/dist/substrate/lifo/shell/lexer.d.ts +9 -0
  101. package/dist/substrate/lifo/shell/lexer.d.ts.map +1 -1
  102. package/dist/substrate/lifo/shell/lexer.js +40 -0
  103. package/dist/vfs/seed-project.d.ts.map +1 -1
  104. package/dist/vfs/seed-project.js +8 -2
  105. package/dist/vfs/sqlite-vfs.d.ts +61 -1
  106. package/dist/vfs/sqlite-vfs.d.ts.map +1 -1
  107. package/dist/vfs/sqlite-vfs.js +199 -35
  108. package/dist/workspace/nimbus-workspace.d.ts.map +1 -1
  109. package/dist/workspace/nimbus-workspace.js +9 -2
  110. package/package.json +4 -2
  111. package/src/_shared/error-text.ts +21 -0
  112. package/src/_shared/exports-resolver.ts +24 -4
  113. package/src/_shared/retry.ts +4 -2
  114. package/src/_shared/tarball-stream.ts +263 -0
  115. package/src/_shared/tarball.ts +46 -0
  116. package/src/_shared/w7-frame.ts +2 -1
  117. package/src/constants.ts +30 -16
  118. package/src/observability/oom-classify.ts +7 -0
  119. package/src/observability/oom-discriminator.ts +1 -1
  120. package/src/runtime/clang-runner.ts +924 -0
  121. package/src/runtime/esbuild-service.ts +16 -11
  122. package/src/runtime/facet-host.ts +12 -0
  123. package/src/runtime/installed-runtimes.ts +4 -3
  124. package/src/runtime/local-facet-host.ts +28 -8
  125. package/src/runtime/long-running-handle.ts +3 -3
  126. package/src/runtime/os-contracts.ts +7 -5
  127. package/src/runtime/port-registry.ts +97 -9
  128. package/src/runtime/process-logs.ts +12 -3
  129. package/src/runtime/project-detect.ts +7 -1
  130. package/src/runtime/require-resolver.ts +7 -7
  131. package/src/runtime/ruby-gems.ts +682 -0
  132. package/src/runtime/ruby-runner.ts +1484 -0
  133. package/src/runtime/runtime-registry.ts +9 -7
  134. package/src/runtime/session-process-supervisor.ts +27 -0
  135. package/src/runtime/sqlite-runtime-fs-bridge.ts +9 -6
  136. package/src/runtime/virtual-socket-kernel.generated.ts +2 -2
  137. package/src/runtime/virtual-socket-kernel.ts +10 -5
  138. package/src/runtime/wasm-runner.ts +55 -29
  139. package/src/shell/features.ts +5 -4
  140. package/src/shell/unix-commands.ts +273 -128
  141. package/src/substrate/lifo/commands/net/ip.ts +15 -15
  142. package/src/substrate/lifo/commands/system/ps.ts +2 -1
  143. package/src/substrate/lifo/kernel/ServiceManager.ts +0 -2
  144. package/src/substrate/lifo/kernel/network/NetworkStack.ts +24 -17
  145. package/src/substrate/lifo/kernel/network/tunnel/WebSocketTunnel.ts +37 -12
  146. package/src/substrate/lifo/kernel/vfs/VFS.ts +34 -0
  147. package/src/substrate/lifo/node-compat/esbuild.ts +16 -8
  148. package/src/substrate/lifo/node-compat/index.ts +3 -2
  149. package/src/substrate/lifo/node-compat/loose-equality.ts +81 -0
  150. package/src/substrate/lifo/node-compat/process.ts +5 -2
  151. package/src/substrate/lifo/shell/Shell.ts +92 -70
  152. package/src/substrate/lifo/shell/lexer.ts +38 -0
  153. package/src/vfs/seed-project.ts +10 -3
  154. package/src/vfs/sqlite-vfs.ts +209 -36
  155. package/src/workspace/nimbus-workspace.ts +10 -1
@@ -11,5 +11,18 @@
11
11
  * touch, stat, file, xxd, base64, sha256sum, id, hostname, realpath
12
12
  */
13
13
  import type { SqliteVFS } from '../vfs/sqlite-vfs.js';
14
- export declare function registerUnixCommands(registry: any, sqliteVfs: SqliteVFS): void;
14
+ import type { Command } from '../substrate/lifo/commands/types.js';
15
+ /**
16
+ * The registry these commands dispatch through: registration, and name
17
+ * resolution for `which`, `type`, `command`, `find -exec` and `xargs`.
18
+ * `resolve` answers `unknown` because the registry holds whatever any module
19
+ * registered — and the worker's npm-bin fallback replaces the method outright
20
+ * — so what comes back is a command only once it has been checked.
21
+ */
22
+ type UnixCommandRegistry = {
23
+ register(name: string, handler: Command): void;
24
+ resolve(name: string): unknown;
25
+ };
26
+ export declare function registerUnixCommands(registry: UnixCommandRegistry, sqliteVfs: SqliteVFS): void;
27
+ export {};
15
28
  //# sourceMappingURL=unix-commands.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"unix-commands.d.ts","sourceRoot":"","sources":["../../src/shell/unix-commands.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAmB,SAAS,EAAE,MAAM,sBAAsB,CAAC;AA0jIvE,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,GAAG,EACb,SAAS,EAAE,SAAS,GACnB,IAAI,CAoKN"}
1
+ {"version":3,"file":"unix-commands.d.ts","sourceRoot":"","sources":["../../src/shell/unix-commands.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAmB,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAavE,OAAO,KAAK,EAAE,OAAO,EAAsB,MAAM,qCAAqC,CAAC;AAoFvF;;;;;;GAMG;AACH,KAAK,mBAAmB,GAAG;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;IAC/C,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;CAChC,CAAC;AAgmIF,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,mBAAmB,EAC7B,SAAS,EAAE,SAAS,GACnB,IAAI,CAoKN"}
@@ -13,13 +13,31 @@
13
13
  import { getSymlinkRegistry } from '../vfs/symlink-registry.js';
14
14
  import { requireVfsCred } from '../runtime/os-contracts.js';
15
15
  import { dec, enc } from '../_shared/bytes.js';
16
+ import { errorText } from '../_shared/error-text.js';
16
17
  import { NIMBUS_VERSION } from '../constants.js';
17
18
  import { SinkWriter, streamRange } from '../_shared/byte-stream.js';
18
- import { fileTypeChar, isCharacterDevice } from '../substrate/lifo/kernel/vfs/index.js';
19
+ import { fileTypeChar, isCharacterDevice, } from '../substrate/lifo/kernel/vfs/index.js';
19
20
  import { runSed } from '../substrate/lifo/commands/text/sed.js';
20
21
  import { parseArgs } from '../substrate/lifo/utils/args.js';
21
22
  import { findUnixGroupName, findUnixUserName, parseChownOwnership, } from './unix-accounts.js';
22
23
  import { createSuCommand, createSudoCommand, createUmaskCommand } from './elevation-commands.js';
24
+ /**
25
+ * A resolved entry as a command this module can run. Every handler in the
26
+ * registry takes a command context; the ones registered below read the string
27
+ * `wrap` leaves in `stdin`, and a command dispatched from here is handed that
28
+ * string rather than a reader.
29
+ */
30
+ function asResolvedCommand(resolved) {
31
+ return typeof resolved === 'function' ? resolved : null;
32
+ }
33
+ /**
34
+ * stdin as text. `wrap` drains the shell's stream into `ctx.stdin` before a
35
+ * command body runs, so a command that does not read a stream itself sees the
36
+ * string it left there, and nothing at all when there was no stdin.
37
+ */
38
+ function stdinText(ctx) {
39
+ return typeof ctx.stdin === 'string' ? ctx.stdin : undefined;
40
+ }
23
41
  function unixVfsFor(sqliteVfs, cred) {
24
42
  return {
25
43
  ...sqliteVfs.as(cred),
@@ -225,7 +243,7 @@ function _pathLookup(vfs, name, envPath) {
225
243
  async function _registryResolved(registry, name, options = {}) {
226
244
  try {
227
245
  const resolved = typeof registry.resolve === 'function'
228
- ? await registry.resolve(name)
246
+ ? asResolvedCommand(await registry.resolve(name))
229
247
  : null;
230
248
  if (resolved && (options.includeInstallHints || !isRuntimeInstallHintHandler(resolved))) {
231
249
  return resolved;
@@ -407,7 +425,7 @@ function mkCommand(vfs, registry) {
407
425
  // because we're calling the resolved cmd not the alias name.
408
426
  const name = args[0];
409
427
  try {
410
- const resolved = await registry.resolve(name);
428
+ const resolved = asResolvedCommand(await registry.resolve(name));
411
429
  if (!resolved) {
412
430
  ctx.stderr.write(`command: ${name}: not found\n`);
413
431
  return 127;
@@ -417,7 +435,7 @@ function mkCommand(vfs, registry) {
417
435
  return typeof code === 'number' ? code : 0;
418
436
  }
419
437
  catch (e) {
420
- ctx.stderr.write(`command: ${name}: ${e?.message || e}\n`);
438
+ ctx.stderr.write(`command: ${name}: ${errorText(e)}\n`);
421
439
  return 1;
422
440
  }
423
441
  };
@@ -447,7 +465,9 @@ function mkType(_vfs, registry) {
447
465
  let exit = 0;
448
466
  for (const name of ctx.args) {
449
467
  try {
450
- const resolved = typeof registry.resolve === 'function' ? await registry.resolve(name) : null;
468
+ const resolved = typeof registry.resolve === 'function'
469
+ ? asResolvedCommand(await registry.resolve(name))
470
+ : null;
451
471
  if (resolved && !isRuntimeInstallHintHandler(resolved)) {
452
472
  ctx.stdout.write(`${name} is a shell builtin\n`);
453
473
  }
@@ -824,7 +844,7 @@ function mkFind(vfs, registry) {
824
844
  return false;
825
845
  let target;
826
846
  try {
827
- target = await registry.resolve(name);
847
+ target = asResolvedCommand(await registry.resolve(name));
828
848
  }
829
849
  catch {
830
850
  target = null;
@@ -852,7 +872,7 @@ function mkFind(vfs, registry) {
852
872
  return code === 0;
853
873
  }
854
874
  catch (e) {
855
- ctx.stderr.write(`find: ${name}: ${e?.message || e}\n`);
875
+ ctx.stderr.write(`find: ${name}: ${errorText(e)}\n`);
856
876
  return false;
857
877
  }
858
878
  };
@@ -1018,7 +1038,7 @@ function mkFind(vfs, registry) {
1018
1038
  return true;
1019
1039
  }
1020
1040
  catch (err) {
1021
- ctx.stderr.write(`find: cannot delete '${e.display}': ${err?.message || err}\n`);
1041
+ ctx.stderr.write(`find: cannot delete '${e.display}': ${errorText(err)}\n`);
1022
1042
  return false;
1023
1043
  }
1024
1044
  };
@@ -1386,8 +1406,9 @@ function mkGrep(vfs) {
1386
1406
  }
1387
1407
  else if (targets.length === 0) {
1388
1408
  // Read from stdin (if piped) — single virtual "file" with no label.
1389
- if (ctx.stdin) {
1390
- processLines(ctx.stdin.split('\n'), '');
1409
+ const piped = stdinText(ctx);
1410
+ if (piped) {
1411
+ processLines(piped.split('\n'), '');
1391
1412
  }
1392
1413
  }
1393
1414
  else {
@@ -1454,8 +1475,10 @@ function mkHead(_vfs) {
1454
1475
  break;
1455
1476
  buffered += chunk;
1456
1477
  // Process complete lines while we have them.
1457
- let nlIdx;
1458
- while (emitted < n && (nlIdx = buffered.indexOf('\n')) !== -1) {
1478
+ while (emitted < n) {
1479
+ const nlIdx = buffered.indexOf('\n');
1480
+ if (nlIdx === -1)
1481
+ break;
1459
1482
  out.push(buffered.substring(0, nlIdx));
1460
1483
  buffered = buffered.substring(nlIdx + 1);
1461
1484
  emitted++;
@@ -1669,8 +1692,9 @@ function mkTail(vfs) {
1669
1692
  ctx.stdout.write(selected.join('\n') + '\n');
1670
1693
  };
1671
1694
  if (files.length === 0) {
1672
- if (ctx.stdin)
1673
- emit(ctx.stdin);
1695
+ const piped = stdinText(ctx);
1696
+ if (piped)
1697
+ emit(piped);
1674
1698
  return 0;
1675
1699
  }
1676
1700
  const label = verbose || files.length > 1;
@@ -1793,7 +1817,7 @@ function mkWc(vfs) {
1793
1817
  ctx.stdout.write(counts.map((c) => String(c).padStart(width)).join(' ') + (label ? ' ' + label : '') + '\n');
1794
1818
  };
1795
1819
  if (files.length === 0) {
1796
- const bytes = enc.encode(ctx.stdin ?? '');
1820
+ const bytes = enc.encode(stdinText(ctx) ?? '');
1797
1821
  // Nothing bounds a stream's counts ahead of time, so a multi-column
1798
1822
  // report over standard input uses the fixed width GNU falls back to.
1799
1823
  emit(measure(bytes), columns === 1 ? 0 : 7, '');
@@ -1839,7 +1863,7 @@ function mkSort(vfs) {
1839
1863
  ctx.stderr.write(`sort: invalid option -- '${unknown[0].replace(/^-+/, '')}'\n`);
1840
1864
  return 1;
1841
1865
  }
1842
- let input = ctx.stdin || '';
1866
+ let input = stdinText(ctx) || '';
1843
1867
  if (positional.length > 0 && !input) {
1844
1868
  try {
1845
1869
  input = vfs.readFileString(resolvePath(ctx.cwd, positional[0]));
@@ -1890,7 +1914,7 @@ function mkUniq(vfs) {
1890
1914
  }
1891
1915
  // File operands were ignored outright, so `uniq file` read stdin and
1892
1916
  // printed nothing at all.
1893
- let input = ctx.stdin || '';
1917
+ let input = stdinText(ctx) || '';
1894
1918
  if (positional.length > 0 && positional[0] !== '-') {
1895
1919
  try {
1896
1920
  input = vfs.readFileString(resolvePath(ctx.cwd, positional[0]));
@@ -1942,7 +1966,7 @@ function mkSed(vfs) {
1942
1966
  vfs,
1943
1967
  stdout: ctx.stdout,
1944
1968
  stderr: ctx.stderr,
1945
- stdin: ctx.stdin === undefined ? undefined : stringInput(ctx.stdin),
1969
+ stdin: typeof ctx.stdin === 'string' ? stringInput(ctx.stdin) : undefined,
1946
1970
  });
1947
1971
  }
1948
1972
  function stringInput(text) {
@@ -2018,7 +2042,7 @@ function mkAwk(vfs) {
2018
2042
  }
2019
2043
  }
2020
2044
  const program = programArgs[0] || '';
2021
- let input = ctx.stdin || '';
2045
+ let input = stdinText(ctx) || '';
2022
2046
  if (fileArgs.length > 0 && !input) {
2023
2047
  try {
2024
2048
  input = vfs.readFileString(resolvePath(ctx.cwd, fileArgs[0]));
@@ -2107,7 +2131,7 @@ function mkAwk(vfs) {
2107
2131
  re = new RegExp(patSrc);
2108
2132
  }
2109
2133
  catch (e) {
2110
- ctx.stderr.write(`awk: bad regex /${patSrc}/: ${e?.message || e}\n`);
2134
+ ctx.stderr.write(`awk: bad regex /${patSrc}/: ${errorText(e)}\n`);
2111
2135
  return 1;
2112
2136
  }
2113
2137
  blocks.push({ kind: 'PATTERN', pattern: re, body });
@@ -2277,7 +2301,7 @@ function mkAwk(vfs) {
2277
2301
  return v;
2278
2302
  }
2279
2303
  catch (e) {
2280
- throw new Error(`expr error: ${e?.message || e} in "${expr}"`);
2304
+ throw new Error(`expr error: ${errorText(e)} in "${expr}"`);
2281
2305
  }
2282
2306
  }
2283
2307
  function stripStringsForScan(s) {
@@ -2723,7 +2747,7 @@ function mkAwk(vfs) {
2723
2747
  runBlock(b);
2724
2748
  }
2725
2749
  catch (e) {
2726
- ctx.stderr.write(`awk: ${e?.message || e}\n`);
2750
+ ctx.stderr.write(`awk: ${errorText(e)}\n`);
2727
2751
  return 1;
2728
2752
  }
2729
2753
  return 0;
@@ -2753,7 +2777,10 @@ function mkAwk(vfs) {
2753
2777
  */
2754
2778
  function mkXargs(vfs, registry) {
2755
2779
  return async (ctx) => {
2756
- const input = (ctx.stdin || '').trim();
2780
+ // NOT trimmed: `-0` exists so a name may carry the whitespace a split
2781
+ // would eat, and trimming the stream rewrites its first and last item.
2782
+ // The default split already drops the empties a trim would have removed.
2783
+ const input = stdinText(ctx) || '';
2757
2784
  if (!input)
2758
2785
  return 0;
2759
2786
  // Parse flags first
@@ -2799,9 +2826,9 @@ function mkXargs(vfs, registry) {
2799
2826
  // Resolve target command from registry (handles both eager + lazy maps).
2800
2827
  let target;
2801
2828
  try {
2802
- target = await registry.resolve(cmdName);
2829
+ target = asResolvedCommand(await registry.resolve(cmdName));
2803
2830
  }
2804
- catch (_e) {
2831
+ catch {
2805
2832
  target = null;
2806
2833
  }
2807
2834
  if (!target) {
@@ -2836,7 +2863,7 @@ function mkXargs(vfs, registry) {
2836
2863
  exit = code;
2837
2864
  }
2838
2865
  catch (e) {
2839
- ctx.stderr.write(`xargs: ${cmdName}: ${e?.message || e}\n`);
2866
+ ctx.stderr.write(`xargs: ${cmdName}: ${errorText(e)}\n`);
2840
2867
  exit = 1;
2841
2868
  }
2842
2869
  }
@@ -2852,7 +2879,7 @@ function mkXargs(vfs, registry) {
2852
2879
  exit = code;
2853
2880
  }
2854
2881
  catch (e) {
2855
- ctx.stderr.write(`xargs: ${cmdName}: ${e?.message || e}\n`);
2882
+ ctx.stderr.write(`xargs: ${cmdName}: ${errorText(e)}\n`);
2856
2883
  exit = 1;
2857
2884
  }
2858
2885
  if (!Number.isFinite(batchSize))
@@ -2864,7 +2891,7 @@ function mkXargs(vfs, registry) {
2864
2891
  }
2865
2892
  function mkTee(vfs) {
2866
2893
  return (ctx) => {
2867
- const input = ctx.stdin || '';
2894
+ const input = stdinText(ctx) || '';
2868
2895
  const append = ctx.args.includes('-a');
2869
2896
  const files = ctx.args.filter(a => !a.startsWith('-'));
2870
2897
  ctx.stdout.write(input);
@@ -2978,7 +3005,10 @@ function mkDiff(vfs) {
2978
3005
  return hasDiff ? 1 : 0;
2979
3006
  }
2980
3007
  catch (e) {
2981
- ctx.stderr.write(`diff: ${e.message}\n`);
3008
+ // `diff` reports the thrown value's `message`, whatever it holds, rather
3009
+ // than the value: a throw carrying none has always printed `undefined`.
3010
+ const message = typeof e === 'object' && e !== null && 'message' in e ? e.message : undefined;
3011
+ ctx.stderr.write(`diff: ${String(message)}\n`);
2982
3012
  return 2;
2983
3013
  }
2984
3014
  };
@@ -3000,6 +3030,36 @@ function mkDiff(vfs) {
3000
3030
  * (rmdir recursive when -r). Translate raw errors so the unix-command
3001
3031
  * contract is honoured.
3002
3032
  */
3033
+ /** The single-character backslash escapes `echo -e` and `printf` both expand. */
3034
+ const BACKSLASH_ESCAPES = {
3035
+ '\\': '\\',
3036
+ n: '\n',
3037
+ t: '\t',
3038
+ r: '\r',
3039
+ a: '\x07',
3040
+ b: '\b',
3041
+ f: '\f',
3042
+ v: '\v',
3043
+ };
3044
+ /**
3045
+ * Expand POSIX backslash escapes in one pass.
3046
+ *
3047
+ * A pass per escape needs somewhere to park a literal `\` so the later passes
3048
+ * cannot read it as the start of an escape, and whatever character that is, the
3049
+ * text may hold one already — or an earlier escape may have just produced one.
3050
+ * NUL was the parking spot, so `printf 'a\0b'` and `echo -e 'a\x00b'` both came
3051
+ * back as `a\b`: the NUL they had just produced was restored as a backslash.
3052
+ * One left-to-right pass consumes `\\` as a unit and needs no parking spot.
3053
+ */
3054
+ function expandBackslashEscapes(text) {
3055
+ return text.replace(/\\(?:([\\ntrabfv])|0([0-7]{1,3})?|x([0-9a-fA-F]{1,2}))/g, (_match, simple, octal, hex) => {
3056
+ if (simple !== undefined)
3057
+ return BACKSLASH_ESCAPES[simple];
3058
+ if (hex !== undefined)
3059
+ return String.fromCharCode(parseInt(hex, 16));
3060
+ return String.fromCharCode(octal ? parseInt(octal, 8) : 0);
3061
+ });
3062
+ }
3003
3063
  /**
3004
3064
  * shell compatibilityb (2026-05-11): registry-level echo so `X | xargs echo`
3005
3065
  * resolves. `echo` is a Shell.builtins entry, NOT in the
@@ -3053,18 +3113,7 @@ function mkEcho() {
3053
3113
  }
3054
3114
  let out = args.slice(i).join(' ');
3055
3115
  if (interpretEscapes) {
3056
- out = out
3057
- .replace(/\\\\/g, '\u0000')
3058
- .replace(/\\n/g, '\n')
3059
- .replace(/\\t/g, '\t')
3060
- .replace(/\\r/g, '\r')
3061
- .replace(/\\b/g, '\b')
3062
- .replace(/\\f/g, '\f')
3063
- .replace(/\\v/g, '\v')
3064
- .replace(/\\a/g, '\x07')
3065
- .replace(/\\0([0-7]{1,3})?/g, (_m, oct) => String.fromCharCode(oct ? parseInt(oct, 8) : 0))
3066
- .replace(/\\x([0-9a-fA-F]{1,2})/g, (_m, hex) => String.fromCharCode(parseInt(hex, 16)))
3067
- .replace(/\u0000/g, '\\');
3116
+ out = expandBackslashEscapes(out);
3068
3117
  }
3069
3118
  ctx.stdout.write(suppressNewline ? out : out + '\n');
3070
3119
  return 0;
@@ -3121,7 +3170,7 @@ function mkLs(vfs) {
3121
3170
  // mounts like /dev) with fallback to closure-captured SqliteVFS.
3122
3171
  let real = [];
3123
3172
  try {
3124
- if (kvfs && typeof kvfs.readdirStat === 'function') {
3173
+ if (kvfs && 'readdirStat' in kvfs && typeof kvfs.readdirStat === 'function') {
3125
3174
  real = kvfs.readdirStat(fp);
3126
3175
  }
3127
3176
  else {
@@ -3250,7 +3299,7 @@ function mkLs(vfs) {
3250
3299
  }
3251
3300
  }
3252
3301
  catch (e) {
3253
- ctx.stderr.write(`ls: cannot access '${arg}': ${e?.message || e}\n`);
3302
+ ctx.stderr.write(`ls: cannot access '${arg}': ${errorText(e)}\n`);
3254
3303
  exit = 1;
3255
3304
  }
3256
3305
  }
@@ -3304,8 +3353,9 @@ function mkCat(vfs) {
3304
3353
  return (ctx) => {
3305
3354
  const files = ctx.args.filter(a => !a.startsWith('-'));
3306
3355
  if (files.length === 0) {
3307
- if (ctx.stdin)
3308
- ctx.stdout.write(ctx.stdin);
3356
+ const piped = stdinText(ctx);
3357
+ if (piped)
3358
+ ctx.stdout.write(piped);
3309
3359
  return 0;
3310
3360
  }
3311
3361
  // Resolve both native VFS symlinks and the legacy registry before reads.
@@ -3409,7 +3459,7 @@ function mkRm(vfs) {
3409
3459
  // permission errors) must still surface. Pre-fix the broad
3410
3460
  // `if (force) continue` masked the readdir-iteration bug that
3411
3461
  // left directories undeleted.
3412
- const msg = String(e?.message || e);
3462
+ const msg = errorText(e);
3413
3463
  if (force && /ENOENT/.test(msg))
3414
3464
  continue;
3415
3465
  ctx.stderr.write(`rm: cannot remove '${t}': ${fsErrorMessage(e)}\n`);
@@ -3431,14 +3481,21 @@ function mkTouch(vfs) {
3431
3481
  if (dir && !targetVfs.exists(dir))
3432
3482
  targetVfs.mkdir(dir, { recursive: true });
3433
3483
  }
3434
- if (targetVfs.exists(fp) && !targetVfs.isDirectory(fp)) {
3484
+ if (!targetVfs.exists(fp)) {
3485
+ targetVfs.writeFile(fp, '');
3486
+ continue;
3487
+ }
3488
+ // Every view reaching here implements `isDirectory`: the lifo VFS gained
3489
+ // it alongside `isFile`, which is what stopped `touch` failing on an
3490
+ // existing file. The `stat` fallback this replaced narrowed to `never`
3491
+ // once the surface was typed — the type system reporting that the guard
3492
+ // it sat behind can no longer be false.
3493
+ const isDirectory = targetVfs.isDirectory(fp);
3494
+ if (!isDirectory) {
3435
3495
  // Update mtime by re-writing the same content
3436
3496
  const content = targetVfs.readFile(fp);
3437
3497
  targetVfs.writeFile(fp, content);
3438
3498
  }
3439
- else if (!targetVfs.exists(fp)) {
3440
- targetVfs.writeFile(fp, '');
3441
- }
3442
3499
  }
3443
3500
  return 0;
3444
3501
  };
@@ -3546,8 +3603,8 @@ function expandStatFormat(format, expand) {
3546
3603
  for (let i = 0; i < format.length; i++) {
3547
3604
  const ch = format[i];
3548
3605
  if (ch === '\\' && i + 1 < format.length) {
3549
- const escape = format[++i];
3550
- out += escape === 'n' ? '\n' : escape === 't' ? '\t' : escape === '0' ? '\0' : escape;
3606
+ const esc = format[++i];
3607
+ out += esc === 'n' ? '\n' : esc === 't' ? '\t' : esc === '0' ? '\0' : esc;
3551
3608
  continue;
3552
3609
  }
3553
3610
  if (ch !== '%') {
@@ -3773,7 +3830,7 @@ function mkBase64(vfs) {
3773
3830
  }
3774
3831
  }
3775
3832
  else {
3776
- bytes = enc.encode(ctx.stdin ?? '');
3833
+ bytes = enc.encode(stdinText(ctx) ?? '');
3777
3834
  }
3778
3835
  if (flags.decode) {
3779
3836
  const source = dec.decode(bytes).replace(/\s+/g, '');
@@ -3968,18 +4025,7 @@ function mkPrintf() {
3968
4025
  const rawFmt = ctx.args[0];
3969
4026
  const vals = ctx.args.slice(1);
3970
4027
  // Process backslash escapes in the format string first.
3971
- const fmt = rawFmt
3972
- .replace(/\\\\/g, '\u0000') // protect literal \\\\
3973
- .replace(/\\n/g, '\n')
3974
- .replace(/\\t/g, '\t')
3975
- .replace(/\\r/g, '\r')
3976
- .replace(/\\a/g, '\x07')
3977
- .replace(/\\b/g, '\b')
3978
- .replace(/\\f/g, '\f')
3979
- .replace(/\\v/g, '\v')
3980
- .replace(/\\0([0-7]{1,3})?/g, (_m, oct) => String.fromCharCode(oct ? parseInt(oct, 8) : 0))
3981
- .replace(/\\x([0-9a-fA-F]{1,2})/g, (_m, hex) => String.fromCharCode(parseInt(hex, 16)))
3982
- .replace(/\u0000/g, '\\');
4028
+ const fmt = expandBackslashEscapes(rawFmt);
3983
4029
  let out = '';
3984
4030
  let argIdx = 0;
3985
4031
  function applyFormat() {
@@ -4279,7 +4325,7 @@ function mkSha256sum(vfs) {
4279
4325
  if (flags.check)
4280
4326
  return verifySha256Sums(ctx, vfs, positional, digest, flags.status === true);
4281
4327
  if (positional.length === 0 || (positional.length === 1 && positional[0] === '-')) {
4282
- ctx.stdout.write(`${await digest(enc.encode(ctx.stdin ?? ''))} -\n`);
4328
+ ctx.stdout.write(`${await digest(enc.encode(stdinText(ctx) ?? ''))} -\n`);
4283
4329
  return 0;
4284
4330
  }
4285
4331
  let exit = 0;
@@ -4480,7 +4526,7 @@ function wrapStreaming(fn) {
4480
4526
  return await result;
4481
4527
  }
4482
4528
  catch (e) {
4483
- ctx.stderr.write(`${e?.message || e}\n`);
4529
+ ctx.stderr.write(`${errorText(e)}\n`);
4484
4530
  return 1;
4485
4531
  }
4486
4532
  };
@@ -4533,7 +4579,7 @@ function wrap(fn) {
4533
4579
  return await result;
4534
4580
  }
4535
4581
  catch (e) {
4536
- ctx.stderr.write(`${e?.message || e}\n`);
4582
+ ctx.stderr.write(`${errorText(e)}\n`);
4537
4583
  return 1;
4538
4584
  }
4539
4585
  };
@@ -4652,7 +4698,7 @@ export function registerUnixCommands(registry, sqliteVfs) {
4652
4698
  vfs.writeFile(linkFp, content);
4653
4699
  }
4654
4700
  catch (e) {
4655
- ctx.stderr.write(`ln: ${target}: ${e?.message || e}\n`);
4701
+ ctx.stderr.write(`ln: ${target}: ${errorText(e)}\n`);
4656
4702
  return 1;
4657
4703
  }
4658
4704
  return 0;
@@ -1 +1 @@
1
- {"version":3,"file":"ip.d.ts","sourceRoot":"","sources":["../../../../../src/substrate/lifo/commands/net/ip.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAE3C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAIpD;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CA4CvD"}
1
+ {"version":3,"file":"ip.d.ts","sourceRoot":"","sources":["../../../../../src/substrate/lifo/commands/net/ip.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAkB,MAAM,aAAa,CAAC;AAE3D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAIpD;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CA4CvD"}
@@ -1,5 +1,6 @@
1
1
  import type { Command } from '../types.js';
2
2
  import type { ProcessRegistry } from '../../shell/ProcessRegistry.js';
3
+ import type { JobTable } from '../../shell/jobs.js';
3
4
  export declare function createPsCommand(processRegistry: ProcessRegistry): Command;
4
- export declare function createPsCommandFromJobTable(jobTable: any): Command;
5
+ export declare function createPsCommandFromJobTable(jobTable: JobTable): Command;
5
6
  //# sourceMappingURL=ps.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ps.d.ts","sourceRoot":"","sources":["../../../../../src/substrate/lifo/commands/system/ps.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AAEtE,wBAAgB,eAAe,CAAC,eAAe,EAAE,eAAe,GAAG,OAAO,CAgBzE;AAGD,wBAAgB,2BAA2B,CAAC,QAAQ,EAAE,GAAG,GAAG,OAAO,CAuBlE"}
1
+ {"version":3,"file":"ps.d.ts","sourceRoot":"","sources":["../../../../../src/substrate/lifo/commands/system/ps.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AACtE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAEpD,wBAAgB,eAAe,CAAC,eAAe,EAAE,eAAe,GAAG,OAAO,CAgBzE;AAGD,wBAAgB,2BAA2B,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAuBvE"}
@@ -1 +1 @@
1
- {"version":3,"file":"ServiceManager.d.ts","sourceRoot":"","sources":["../../../../src/substrate/lifo/kernel/ServiceManager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAK/D,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,OAAO,CAAC;IAChB,MAAM,EAAE,QAAQ,GAAG,UAAU,GAAG,QAAQ,GAAG,YAAY,CAAC;IACxD,GAAG,EAAE,SAAS,GAAG,MAAM,GAAG,QAAQ,GAAG,WAAW,GAAG,cAAc,CAAC;IAClE,OAAO,EAAE,OAAO,CAAC;IACjB,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB;AAmBD,qBAAa,cAAc;IACzB,OAAO,CAAC,GAAG,CAAM;IACjB,OAAO,CAAC,QAAQ,CAAkB;IAClC,OAAO,CAAC,UAAU,CAAyB;IAC3C,OAAO,CAAC,QAAQ,CAAqC;IACrD,OAAO,CAAC,SAAS,CAA+B;gBAEpC,GAAG,EAAE,GAAG,EAAE,QAAQ,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;IAMnF,kCAAkC;IAClC,YAAY,IAAI,IAAI;IAIpB,OAAO,CAAC,WAAW;IAgBnB,OAAO,CAAC,QAAQ;IAIV,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,EAAE,EAAE,OAAO,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IAyFpE,OAAO,CAAC,iBAAiB;IAgBnB,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,EAAE,EAAE,OAAO,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IAmD7D,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,EAAE,EAAE,OAAO,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IAStE,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW;IAwDjC,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG;QAAE,EAAE,EAAE,OAAO,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE;IAiBtD,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG;QAAE,EAAE,EAAE,OAAO,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE;IAiBvD,OAAO,CAAC,SAAS;IAIjB,SAAS,IAAI,WAAW,EAAE;IA2BpB,mBAAmB,IAAI,OAAO,CAAC,IAAI,CAAC;CAW3C"}
1
+ {"version":3,"file":"ServiceManager.d.ts","sourceRoot":"","sources":["../../../../src/substrate/lifo/kernel/ServiceManager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAK/D,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,OAAO,CAAC;IAChB,MAAM,EAAE,QAAQ,GAAG,UAAU,GAAG,QAAQ,GAAG,YAAY,CAAC;IACxD,GAAG,EAAE,SAAS,GAAG,MAAM,GAAG,QAAQ,GAAG,WAAW,GAAG,cAAc,CAAC;IAClE,OAAO,EAAE,OAAO,CAAC;IACjB,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB;AAmBD,qBAAa,cAAc;IACzB,OAAO,CAAC,GAAG,CAAM;IACjB,OAAO,CAAC,QAAQ,CAAkB;IAClC,OAAO,CAAC,UAAU,CAAyB;IAC3C,OAAO,CAAC,QAAQ,CAAqC;IACrD,OAAO,CAAC,SAAS,CAA+B;gBAEpC,GAAG,EAAE,GAAG,EAAE,QAAQ,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;IAMnF,kCAAkC;IAClC,YAAY,IAAI,IAAI;IAIpB,OAAO,CAAC,WAAW;IAgBnB,OAAO,CAAC,QAAQ;IAIV,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,EAAE,EAAE,OAAO,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IAyFpE,OAAO,CAAC,iBAAiB;IAgBnB,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,EAAE,EAAE,OAAO,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IAiD7D,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,EAAE,EAAE,OAAO,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IAStE,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW;IAwDjC,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG;QAAE,EAAE,EAAE,OAAO,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE;IAiBtD,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG;QAAE,EAAE,EAAE,OAAO,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE;IAiBvD,OAAO,CAAC,SAAS;IAIjB,SAAS,IAAI,WAAW,EAAE;IA2BpB,mBAAmB,IAAI,OAAO,CAAC,IAAI,CAAC;CAW3C"}
@@ -137,8 +137,6 @@ export class ServiceManager {
137
137
  svc.restartTimer = null;
138
138
  }
139
139
  if (svc.exitCode !== null) {
140
- // Already stopped
141
- svc.exitCode = svc.exitCode;
142
140
  return { ok: true, message: '' };
143
141
  }
144
142
  // If there's an ExecStop command, try to run it
@@ -3,6 +3,16 @@ import { NetworkNamespace } from './NetworkNamespace.js';
3
3
  import { DNSResolver } from './DNSResolver.js';
4
4
  import { Socket } from './Socket.js';
5
5
  import type { IPAddress, SocketType, SocketAddress, Packet, RouteEntry, NetworkTunnel } from './types.js';
6
+ import type { VETHPair } from './tunnel/VETHPair.js';
7
+ import type { Bridge } from './Bridge.js';
8
+ /**
9
+ * A tunnel as the stack holds it. `NetworkTunnel` declares its interface as the
10
+ * plain device record; namespaces hold the concrete device, which is what every
11
+ * tunnel implementation exposes (see `BaseTunnel`).
12
+ */
13
+ type BoundTunnel = Omit<NetworkTunnel, 'interface'> & {
14
+ interface: NetworkInterface;
15
+ };
6
16
  /**
7
17
  * Virtual network stack
8
18
  * Provides Linux-like networking with interfaces, routing, sockets, DNS, and tunneling
@@ -117,7 +127,7 @@ export declare class NetworkStack {
117
127
  /**
118
128
  * Add tunnel to network stack
119
129
  */
120
- addTunnel(name: string, tunnel: NetworkTunnel): void;
130
+ addTunnel(name: string, tunnel: BoundTunnel): void;
121
131
  /**
122
132
  * Remove tunnel from network stack
123
133
  */
@@ -125,19 +135,19 @@ export declare class NetworkStack {
125
135
  /**
126
136
  * Get tunnel by name
127
137
  */
128
- getTunnel(name: string): NetworkTunnel | undefined;
138
+ getTunnel(name: string): BoundTunnel | undefined;
129
139
  /**
130
140
  * Get all tunnels
131
141
  */
132
- getAllTunnels(): NetworkTunnel[];
142
+ getAllTunnels(): BoundTunnel[];
133
143
  /**
134
144
  * Get tunnels by namespace
135
145
  */
136
- getTunnelsByNamespace(namespace: string): NetworkTunnel[];
146
+ getTunnelsByNamespace(namespace: string): BoundTunnel[];
137
147
  /**
138
148
  * Add VETH pair
139
149
  */
140
- addVETHPair(id: string, vethPair: any): void;
150
+ addVETHPair(id: string, vethPair: VETHPair): void;
141
151
  /**
142
152
  * Remove VETH pair
143
153
  */
@@ -145,11 +155,11 @@ export declare class NetworkStack {
145
155
  /**
146
156
  * Get VETH pair by ID or interface name
147
157
  */
148
- getVETHPair(idOrName: string): any | undefined;
158
+ getVETHPair(idOrName: string): VETHPair | undefined;
149
159
  /**
150
160
  * Get all VETH pairs
151
161
  */
152
- getAllVETHPairs(): any[];
162
+ getAllVETHPairs(): VETHPair[];
153
163
  /**
154
164
  * Generate next tunnel ID
155
165
  */
@@ -157,7 +167,7 @@ export declare class NetworkStack {
157
167
  /**
158
168
  * Add bridge to network stack
159
169
  */
160
- addBridge(name: string, bridge: any): void;
170
+ addBridge(name: string, bridge: Bridge): void;
161
171
  /**
162
172
  * Remove bridge from network stack
163
173
  */
@@ -165,14 +175,15 @@ export declare class NetworkStack {
165
175
  /**
166
176
  * Get bridge by name
167
177
  */
168
- getBridge(name: string): any | undefined;
178
+ getBridge(name: string): Bridge | undefined;
169
179
  /**
170
180
  * Get all bridges
171
181
  */
172
- getAllBridges(): any[];
182
+ getAllBridges(): Bridge[];
173
183
  /**
174
184
  * Get bridges by namespace
175
185
  */
176
- getBridgesByNamespace(namespace: string): any[];
186
+ getBridgesByNamespace(namespace: string): Bridge[];
177
187
  }
188
+ export {};
178
189
  //# sourceMappingURL=NetworkStack.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"NetworkStack.d.ts","sourceRoot":"","sources":["../../../../../src/substrate/lifo/kernel/network/NetworkStack.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"NetworkStack.d.ts","sourceRoot":"","sources":["../../../../../src/substrate/lifo/kernel/network/NetworkStack.ts"],"names":[],"mappings":"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"}
@@ -300,8 +300,6 @@ export class NetworkStack {
300
300
  throw new Error(`Tunnel ${name} already exists`);
301
301
  }
302
302
  this.tunnels.set(name, tunnel);
303
- // Add tunnel interface to namespace
304
- // Cast to NetworkInterface class since tunnel.interface is the concrete class
305
303
  const ns = this.namespaces.get(tunnel.interface.namespace);
306
304
  if (ns) {
307
305
  ns.addInterface(tunnel.interface);
@@ -1,6 +1,7 @@
1
1
  import type { Packet } from '../types.js';
2
2
  import type { NetworkStack } from '../NetworkStack.js';
3
3
  import { BaseTunnel } from './BaseTunnel.js';
4
+ import type { VirtualRequestHandler } from '../../index.js';
4
5
  /**
5
6
  * WebSocket Tunnel - Bridge virtual network to external WebSocket server
6
7
  *
@@ -23,7 +24,7 @@ export declare class WebSocketTunnel extends BaseTunnel {
23
24
  private isReconnecting;
24
25
  private packetQueue;
25
26
  private waitingResolvers;
26
- constructor(id: string, wsUrl: string, networkStack: NetworkStack, portRegistry?: Map<number, any>, namespace?: string, defaultPort?: number | null);
27
+ constructor(id: string, wsUrl: string, networkStack: NetworkStack, portRegistry?: Map<number, VirtualRequestHandler>, namespace?: string, defaultPort?: number | null);
27
28
  protected getTunnelPrefix(): string;
28
29
  /**
29
30
  * Bring tunnel up - connect to WebSocket server