@artenx/dshb 0.1.8 → 0.1.9

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 { DockerBackend } from "./docker-backend.js";
2
- import { SubprocessHandle, SubprocessSpawnSpec, SubprocessTerminalHandle, SubprocessTerminalSpawnSpec } from "@deepseek-ai/dsh-subprocess";
2
+ import { SubprocessHandle, SubprocessSpawnSpec, SubprocessTerminalEnvironment, SubprocessTerminalHandle, SubprocessTerminalSpawnSpec } from "@deepseek-ai/dsh-subprocess";
3
3
  import { ShellExecRequest, ShellExecSpec, ShellProcess, ShellRunResult } from "@deepseek-ai/dsh-shell";
4
4
  //#region src/exec-docker/process-provider.d.ts
5
5
  declare class DockerShellExecutor {
@@ -12,6 +12,8 @@ declare class DockerShellExecutor {
12
12
  declare class DockerSubprocessRuntime {
13
13
  private readonly client;
14
14
  constructor(client: DockerBackend);
15
+ terminalEnvironment(signal?: AbortSignal): Promise<SubprocessTerminalEnvironment>;
16
+ resolveExecutable(command: string, env?: Readonly<Record<string, string>>, signal?: AbortSignal): Promise<string>;
15
17
  spawn(spec: SubprocessSpawnSpec): SubprocessHandle;
16
18
  spawnTerminal(spec: SubprocessTerminalSpawnSpec): Promise<SubprocessTerminalHandle>;
17
19
  }
@@ -1,3 +1,4 @@
1
+ import { SubprocessExecutableNotFoundError } from "@deepseek-ai/dsh-subprocess";
1
2
  //#region src/exec-docker/process-provider.ts
2
3
  var DockerShellExecutor = class {
3
4
  client;
@@ -49,6 +50,34 @@ var DockerSubprocessRuntime = class {
49
50
  constructor(client) {
50
51
  this.client = client;
51
52
  }
53
+ async terminalEnvironment(signal) {
54
+ signal?.throwIfAborted();
55
+ const result = await this.client.exec([
56
+ "sh",
57
+ "-c",
58
+ `user=$(id -un); shell=$(getent passwd "$user" 2>/dev/null | cut -d: -f7); if [ -z "$shell" ]; then shell=$(awk -F: -v user="$user" '$1 == user {print $7; exit}' /etc/passwd); fi; printf "%s" "$shell"`
59
+ ], "/");
60
+ signal?.throwIfAborted();
61
+ const defaultShell = result.stdout.trim().split("\n")[0];
62
+ return {
63
+ platform: "posix",
64
+ ...defaultShell ? { defaultShell } : {}
65
+ };
66
+ }
67
+ async resolveExecutable(command, env = {}, signal) {
68
+ signal?.throwIfAborted();
69
+ const result = await this.client.exec([
70
+ "sh",
71
+ "-c",
72
+ "command -v \"$1\"",
73
+ "sh",
74
+ command
75
+ ], "/", { ...env });
76
+ signal?.throwIfAborted();
77
+ const path = result.stdout.trim().split("\n")[0];
78
+ if (result.code !== 0 || !path) throw new SubprocessExecutableNotFoundError(`executable not found in Docker node: ${command}`);
79
+ return path;
80
+ }
52
81
  spawn(spec) {
53
82
  return {
54
83
  pid: -1,
@@ -1 +1 @@
1
- {"version":3,"file":"process-provider.js","names":[],"sources":["../../src/exec-docker/process-provider.ts"],"sourcesContent":["import type { DockerBackend } from './docker-backend.js'\nimport type { ShellExecRequest, ShellExecSpec, ShellProcess, ShellRunResult } from '@deepseek-ai/dsh-shell'\nimport type { CollectedOutput, SubprocessHandle, SubprocessOutcome, SubprocessSpawnSpec, SubprocessTerminalHandle, SubprocessTerminalSpawnSpec } from '@deepseek-ai/dsh-subprocess'\n\nexport class DockerShellExecutor {\n constructor(private readonly client: DockerBackend) {}\n\n resolve(request: ShellExecRequest): ShellExecSpec {\n return {\n command: request.command,\n workdir: request.workdir ?? '/',\n timeoutMs: request.timeoutMs ?? 60_000,\n stdoutMaxBytes: request.stdoutMaxBytes ?? 1024 * 1024,\n signal: request.signal,\n stdin: request.stdin,\n env: request.env,\n sandboxPolicy: request.sandboxPolicy,\n } as ShellExecSpec\n }\n\n async run(spec: ShellExecSpec): Promise<ShellRunResult> {\n const result = await this.client.exec(['bash', '-c', spec.command], spec.workdir, (spec.env ?? {}) as Record<string, string>, spec.stdin !== undefined ? Buffer.from(spec.stdin) : undefined)\n const collect = (text: string): CollectedOutput => ({ text, truncated: false })\n return {\n exitCode: result.code,\n signal: null,\n timedOut: false,\n aborted: false,\n timeoutMs: spec.timeoutMs,\n stdout: collect(result.stdout),\n stderr: collect(result.stderr),\n } as unknown as ShellRunResult\n }\n\n start(spec: ShellExecSpec): ShellProcess {\n const promise = this.run(spec)\n return {\n pid: -1,\n done: promise,\n kill: () => {\n void promise\n },\n } as unknown as ShellProcess\n }\n}\n\nexport class DockerSubprocessRuntime {\n constructor(private readonly client: DockerBackend) {}\n\n spawn(spec: SubprocessSpawnSpec): SubprocessHandle {\n const promise = this.client.exec(spec.argv as string[], spec.cwd, (spec.env ?? {}) as Record<string, string>)\n const handle: SubprocessHandle = {\n pid: -1,\n done: promise.then((r) => ({ exitCode: r.code, signal: null as NodeJS.Signals | null })),\n kill: () => {\n void promise\n },\n } as unknown as SubprocessHandle\n return handle\n }\n\n async spawnTerminal(spec: SubprocessTerminalSpawnSpec): Promise<SubprocessTerminalHandle> {\n if (spec.signal?.aborted) throw spec.signal.reason\n const pty = await this.client.pty(spec.argv as string[], spec.cwd, spec.cols, spec.rows, spec.env, spec.terminalType)\n if (spec.signal?.aborted) {\n pty.kill()\n throw spec.signal.reason\n }\n let settled = false\n const done = new Promise<SubprocessOutcome>((resolve, reject) => {\n const finish = (): void => {\n if (settled) return\n settled = true\n resolve({ exitCode: null, signal: null })\n }\n pty.stream.once('end', finish)\n pty.stream.once('close', finish)\n pty.stream.once('error', reject)\n })\n const handle: SubprocessTerminalHandle = {\n pid: -1,\n output: pty.stream as unknown as import('node:stream').Readable,\n done,\n write: (data) => new Promise<void>((resolve, reject) => {\n pty.stream.write(data, (error) => error ? reject(error) : resolve())\n }),\n resize: async (cols, rows) => pty.resize(cols, rows),\n inspectForeground: async () => undefined,\n inspectActivity: async () => ({ state: 'unknown', revision: 0 }),\n signalForeground: async () => { throw new Error('foreground signaling is unsupported for Docker terminals') },\n terminate: async () => {\n pty.kill()\n await done.catch(() => {})\n },\n }\n return handle\n }\n}\n"],"mappings":";AAIA,IAAa,sBAAb,MAAiC;CACF;CAA7B,YAAY,QAAwC;EAAvB,KAAA,SAAA;CAAwB;CAErD,QAAQ,SAA0C;EAChD,OAAO;GACL,SAAS,QAAQ;GACjB,SAAS,QAAQ,WAAW;GAC5B,WAAW,QAAQ,aAAa;GAChC,gBAAgB,QAAQ,kBAAkB;GAC1C,QAAQ,QAAQ;GAChB,OAAO,QAAQ;GACf,KAAK,QAAQ;GACb,eAAe,QAAQ;EACzB;CACF;CAEA,MAAM,IAAI,MAA8C;EACtD,MAAM,SAAS,MAAM,KAAK,OAAO,KAAK;GAAC;GAAQ;GAAM,KAAK;EAAO,GAAG,KAAK,SAAU,KAAK,OAAO,CAAC,GAA8B,KAAK,UAAU,KAAA,IAAY,OAAO,KAAK,KAAK,KAAK,IAAI,KAAA,CAAS;EAC5L,MAAM,WAAW,UAAmC;GAAE;GAAM,WAAW;EAAM;EAC7E,OAAO;GACL,UAAU,OAAO;GACjB,QAAQ;GACR,UAAU;GACV,SAAS;GACT,WAAW,KAAK;GAChB,QAAQ,QAAQ,OAAO,MAAM;GAC7B,QAAQ,QAAQ,OAAO,MAAM;EAC/B;CACF;CAEA,MAAM,MAAmC;EAEvC,OAAO;GACL,KAAK;GACL,MAHc,KAAK,IAAI,IAGX;GACZ,YAAY,CAEZ;EACF;CACF;AACF;AAEA,IAAa,0BAAb,MAAqC;CACN;CAA7B,YAAY,QAAwC;EAAvB,KAAA,SAAA;CAAwB;CAErD,MAAM,MAA6C;EASjD,OAAO;GANL,KAAK;GACL,MAHc,KAAK,OAAO,KAAK,KAAK,MAAkB,KAAK,KAAM,KAAK,OAAO,CAAC,CAGlE,CAAC,CAAC,MAAM,OAAO;IAAE,UAAU,EAAE;IAAM,QAAQ;GAA8B,EAAE;GACvF,YAAY,CAEZ;EAEU;CACd;CAEA,MAAM,cAAc,MAAsE;EACxF,IAAI,KAAK,QAAQ,SAAS,MAAM,KAAK,OAAO;EAC5C,MAAM,MAAM,MAAM,KAAK,OAAO,IAAI,KAAK,MAAkB,KAAK,KAAK,KAAK,MAAM,KAAK,MAAM,KAAK,KAAK,KAAK,YAAY;EACpH,IAAI,KAAK,QAAQ,SAAS;GACxB,IAAI,KAAK;GACT,MAAM,KAAK,OAAO;EACpB;EACA,IAAI,UAAU;EACd,MAAM,OAAO,IAAI,SAA4B,SAAS,WAAW;GAC/D,MAAM,eAAqB;IACzB,IAAI,SAAS;IACb,UAAU;IACV,QAAQ;KAAE,UAAU;KAAM,QAAQ;IAAK,CAAC;GAC1C;GACA,IAAI,OAAO,KAAK,OAAO,MAAM;GAC7B,IAAI,OAAO,KAAK,SAAS,MAAM;GAC/B,IAAI,OAAO,KAAK,SAAS,MAAM;EACjC,CAAC;EAiBD,OAAO;GAfL,KAAK;GACL,QAAQ,IAAI;GACZ;GACA,QAAQ,SAAS,IAAI,SAAe,SAAS,WAAW;IACtD,IAAI,OAAO,MAAM,OAAO,UAAU,QAAQ,OAAO,KAAK,IAAI,QAAQ,CAAC;GACrE,CAAC;GACD,QAAQ,OAAO,MAAM,SAAS,IAAI,OAAO,MAAM,IAAI;GACnD,mBAAmB,YAAY,KAAA;GAC/B,iBAAiB,aAAa;IAAE,OAAO;IAAW,UAAU;GAAE;GAC9D,kBAAkB,YAAY;IAAE,MAAM,IAAI,MAAM,0DAA0D;GAAE;GAC5G,WAAW,YAAY;IACrB,IAAI,KAAK;IACT,MAAM,KAAK,YAAY,CAAC,CAAC;GAC3B;EAEU;CACd;AACF"}
1
+ {"version":3,"file":"process-provider.js","names":[],"sources":["../../src/exec-docker/process-provider.ts"],"sourcesContent":["import type { DockerBackend } from './docker-backend.js'\nimport type { ShellExecRequest, ShellExecSpec, ShellProcess, ShellRunResult } from '@deepseek-ai/dsh-shell'\nimport { SubprocessExecutableNotFoundError, type CollectedOutput, type SubprocessHandle, type SubprocessOutcome, type SubprocessSpawnSpec, type SubprocessTerminalEnvironment, type SubprocessTerminalHandle, type SubprocessTerminalSpawnSpec } from '@deepseek-ai/dsh-subprocess'\n\nexport class DockerShellExecutor {\n constructor(private readonly client: DockerBackend) {}\n\n resolve(request: ShellExecRequest): ShellExecSpec {\n return {\n command: request.command,\n workdir: request.workdir ?? '/',\n timeoutMs: request.timeoutMs ?? 60_000,\n stdoutMaxBytes: request.stdoutMaxBytes ?? 1024 * 1024,\n signal: request.signal,\n stdin: request.stdin,\n env: request.env,\n sandboxPolicy: request.sandboxPolicy,\n } as ShellExecSpec\n }\n\n async run(spec: ShellExecSpec): Promise<ShellRunResult> {\n const result = await this.client.exec(['bash', '-c', spec.command], spec.workdir, (spec.env ?? {}) as Record<string, string>, spec.stdin !== undefined ? Buffer.from(spec.stdin) : undefined)\n const collect = (text: string): CollectedOutput => ({ text, truncated: false })\n return {\n exitCode: result.code,\n signal: null,\n timedOut: false,\n aborted: false,\n timeoutMs: spec.timeoutMs,\n stdout: collect(result.stdout),\n stderr: collect(result.stderr),\n } as unknown as ShellRunResult\n }\n\n start(spec: ShellExecSpec): ShellProcess {\n const promise = this.run(spec)\n return {\n pid: -1,\n done: promise,\n kill: () => {\n void promise\n },\n } as unknown as ShellProcess\n }\n}\n\nexport class DockerSubprocessRuntime {\n constructor(private readonly client: DockerBackend) {}\n\n async terminalEnvironment(signal?: AbortSignal): Promise<SubprocessTerminalEnvironment> {\n signal?.throwIfAborted()\n const script = `user=$(id -un); shell=$(getent passwd \"$user\" 2>/dev/null | cut -d: -f7); if [ -z \"$shell\" ]; then shell=$(awk -F: -v user=\"$user\" '$1 == user {print $7; exit}' /etc/passwd); fi; printf \"%s\" \"$shell\"`\n const result = await this.client.exec(['sh', '-c', script], '/')\n signal?.throwIfAborted()\n const defaultShell = result.stdout.trim().split('\\n')[0]\n return { platform: 'posix', ...(defaultShell ? { defaultShell } : {}) }\n }\n\n async resolveExecutable(command: string, env: Readonly<Record<string, string>> = {}, signal?: AbortSignal): Promise<string> {\n signal?.throwIfAborted()\n const result = await this.client.exec(['sh', '-c', 'command -v \"$1\"', 'sh', command], '/', { ...env })\n signal?.throwIfAborted()\n const path = result.stdout.trim().split('\\n')[0]\n if (result.code !== 0 || !path) throw new SubprocessExecutableNotFoundError(`executable not found in Docker node: ${command}`)\n return path\n }\n\n spawn(spec: SubprocessSpawnSpec): SubprocessHandle {\n const promise = this.client.exec(spec.argv as string[], spec.cwd, (spec.env ?? {}) as Record<string, string>)\n const handle: SubprocessHandle = {\n pid: -1,\n done: promise.then((r) => ({ exitCode: r.code, signal: null as NodeJS.Signals | null })),\n kill: () => {\n void promise\n },\n } as unknown as SubprocessHandle\n return handle\n }\n\n async spawnTerminal(spec: SubprocessTerminalSpawnSpec): Promise<SubprocessTerminalHandle> {\n if (spec.signal?.aborted) throw spec.signal.reason\n const pty = await this.client.pty(spec.argv as string[], spec.cwd, spec.cols, spec.rows, spec.env, spec.terminalType)\n if (spec.signal?.aborted) {\n pty.kill()\n throw spec.signal.reason\n }\n let settled = false\n const done = new Promise<SubprocessOutcome>((resolve, reject) => {\n const finish = (): void => {\n if (settled) return\n settled = true\n resolve({ exitCode: null, signal: null })\n }\n pty.stream.once('end', finish)\n pty.stream.once('close', finish)\n pty.stream.once('error', reject)\n })\n const handle: SubprocessTerminalHandle = {\n pid: -1,\n output: pty.stream as unknown as import('node:stream').Readable,\n done,\n write: (data) => new Promise<void>((resolve, reject) => {\n pty.stream.write(data, (error) => error ? reject(error) : resolve())\n }),\n resize: async (cols, rows) => pty.resize(cols, rows),\n inspectForeground: async () => undefined,\n inspectActivity: async () => ({ state: 'unknown', revision: 0 }),\n signalForeground: async () => { throw new Error('foreground signaling is unsupported for Docker terminals') },\n terminate: async () => {\n pty.kill()\n await done.catch(() => {})\n },\n }\n return handle\n }\n}\n"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  import { DockerBackend } from "./docker-backend.js";
2
2
  import { DockerFileSystem } from "./fs-provider.js";
3
- import { a as NodeTestReport, t as ExecutionWorldProvider } from "../types-C0TtEO7z.js";
3
+ import { a as NodeTestReport, t as ExecutionWorldProvider } from "../types-ekJQQ4x6.js";
4
4
  import { DockerShellExecutor, DockerSubprocessRuntime } from "./process-provider.js";
5
5
  //#region src/exec-docker/world.d.ts
6
6
  interface DockerNodeConfig {
@@ -1,5 +1,5 @@
1
1
  import { SshExecutor } from "./executor.js";
2
- import { SubprocessHandle, SubprocessSpawnSpec, SubprocessTerminalHandle, SubprocessTerminalSpawnSpec } from "@deepseek-ai/dsh-subprocess";
2
+ import { SubprocessHandle, SubprocessSpawnSpec, SubprocessTerminalEnvironment, SubprocessTerminalHandle, SubprocessTerminalSpawnSpec } from "@deepseek-ai/dsh-subprocess";
3
3
  import { ShellExecRequest, ShellExecSpec, ShellProcess, ShellRunResult } from "@deepseek-ai/dsh-shell";
4
4
  //#region src/exec-ssh/process-provider.d.ts
5
5
  declare class SshShellExecutor {
@@ -12,6 +12,8 @@ declare class SshShellExecutor {
12
12
  declare class SshSubprocessRuntime {
13
13
  private readonly executor;
14
14
  constructor(executor: SshExecutor);
15
+ terminalEnvironment(signal?: AbortSignal): Promise<SubprocessTerminalEnvironment>;
16
+ resolveExecutable(command: string, env?: Readonly<Record<string, string>>, signal?: AbortSignal): Promise<string>;
15
17
  spawn(spec: SubprocessSpawnSpec): SubprocessHandle;
16
18
  spawnTerminal(spec: SubprocessTerminalSpawnSpec): Promise<SubprocessTerminalHandle>;
17
19
  }
@@ -1,3 +1,4 @@
1
+ import { SubprocessExecutableNotFoundError } from "@deepseek-ai/dsh-subprocess";
1
2
  //#region src/exec-ssh/process-provider.ts
2
3
  var SshShellExecutor = class {
3
4
  executor;
@@ -49,6 +50,34 @@ var SshSubprocessRuntime = class {
49
50
  constructor(executor) {
50
51
  this.executor = executor;
51
52
  }
53
+ async terminalEnvironment(signal) {
54
+ signal?.throwIfAborted();
55
+ const result = await this.executor.exec([
56
+ "sh",
57
+ "-c",
58
+ `user=$(id -un); shell=$(getent passwd "$user" 2>/dev/null | cut -d: -f7); if [ -z "$shell" ]; then shell=$(awk -F: -v user="$user" '$1 == user {print $7; exit}' /etc/passwd); fi; printf "%s" "$shell"`
59
+ ], "/");
60
+ signal?.throwIfAborted();
61
+ const defaultShell = result.stdout.trim().split("\n")[0];
62
+ return {
63
+ platform: "posix",
64
+ ...defaultShell ? { defaultShell } : {}
65
+ };
66
+ }
67
+ async resolveExecutable(command, env = {}, signal) {
68
+ signal?.throwIfAborted();
69
+ const result = await this.executor.exec([
70
+ "sh",
71
+ "-c",
72
+ "command -v \"$1\"",
73
+ "sh",
74
+ command
75
+ ], "/", { ...env });
76
+ signal?.throwIfAborted();
77
+ const path = result.stdout.trim().split("\n")[0];
78
+ if (result.code !== 0 || !path) throw new SubprocessExecutableNotFoundError(`executable not found on SSH node: ${command}`);
79
+ return path;
80
+ }
52
81
  spawn(spec) {
53
82
  return {
54
83
  pid: -1,
@@ -1 +1 @@
1
- {"version":3,"file":"process-provider.js","names":[],"sources":["../../src/exec-ssh/process-provider.ts"],"sourcesContent":["import type { ShellExecRequest, ShellExecSpec, ShellProcess, ShellRunResult } from '@deepseek-ai/dsh-shell'\nimport type { CollectedOutput, SubprocessHandle, SubprocessOutcome, SubprocessSpawnSpec, SubprocessTerminalHandle, SubprocessTerminalSpawnSpec } from '@deepseek-ai/dsh-subprocess'\nimport type { SshExecutor } from './executor.js'\n\nexport class SshShellExecutor {\n constructor(private readonly executor: SshExecutor) {}\n\n resolve(request: ShellExecRequest): ShellExecSpec {\n return {\n command: request.command,\n workdir: request.workdir ?? '/',\n timeoutMs: request.timeoutMs ?? 60_000,\n stdoutMaxBytes: request.stdoutMaxBytes ?? 1024 * 1024,\n signal: request.signal,\n stdin: request.stdin,\n env: request.env,\n sandboxPolicy: request.sandboxPolicy,\n } as ShellExecSpec\n }\n\n async run(spec: ShellExecSpec): Promise<ShellRunResult> {\n const result = await this.executor.exec(['sh', '-c', spec.command], spec.workdir, (spec.env ?? {}) as Record<string, string>, spec.stdin !== undefined ? Buffer.from(spec.stdin) : undefined)\n const collect = (text: string): CollectedOutput => ({ text, truncated: false })\n return {\n exitCode: result.code,\n signal: (result.signal ?? null) as NodeJS.Signals | null,\n timedOut: false,\n aborted: false,\n timeoutMs: spec.timeoutMs,\n stdout: collect(result.stdout),\n stderr: collect(result.stderr),\n } as unknown as ShellRunResult\n }\n\n start(spec: ShellExecSpec): ShellProcess {\n const promise = this.run(spec)\n const proc: ShellProcess = {\n pid: -1,\n done: promise,\n kill: () => {\n void promise\n },\n } as unknown as ShellProcess\n return proc\n }\n}\n\nexport class SshSubprocessRuntime {\n constructor(private readonly executor: SshExecutor) {}\n\n spawn(spec: SubprocessSpawnSpec): SubprocessHandle {\n const promise = this.executor.exec(spec.argv as string[], spec.cwd, (spec.env ?? {}) as Record<string, string>)\n const handle: SubprocessHandle = {\n pid: -1,\n done: promise.then((r) => ({ exitCode: r.code, signal: (r.signal ?? null) as NodeJS.Signals | null })),\n kill: () => {\n void promise\n },\n } as unknown as SubprocessHandle\n return handle\n }\n\n async spawnTerminal(spec: SubprocessTerminalSpawnSpec): Promise<SubprocessTerminalHandle> {\n if (spec.signal?.aborted) throw spec.signal.reason\n const pty = await this.executor.pty(spec.argv as string[], spec.cwd, spec.env ?? {}, spec.cols, spec.rows, spec.terminalType)\n if (spec.signal?.aborted) {\n pty.kill()\n throw spec.signal.reason\n }\n let exitCode: number | null = null\n const done = new Promise<SubprocessOutcome>((resolve, reject) => {\n pty.channel.once('exit', (code) => {\n if (typeof code === 'number') exitCode = code\n })\n pty.channel.once('error', reject)\n pty.channel.once('close', () => resolve({ exitCode, signal: null }))\n })\n const handle: SubprocessTerminalHandle = {\n pid: -1,\n output: pty.channel,\n done,\n write: (data) => new Promise<void>((resolve, reject) => {\n pty.channel.write(data, (error) => error ? reject(error) : resolve())\n }),\n resize: async (cols, rows) => pty.resize(cols, rows),\n inspectForeground: async () => undefined,\n inspectActivity: async () => ({ state: 'unknown', revision: 0 }),\n signalForeground: async () => { throw new Error('foreground signaling is unsupported for SSH terminals') },\n terminate: async () => {\n pty.kill()\n await done.catch(() => {})\n },\n }\n return handle\n }\n}\n"],"mappings":";AAIA,IAAa,mBAAb,MAA8B;CACC;CAA7B,YAAY,UAAwC;EAAvB,KAAA,WAAA;CAAwB;CAErD,QAAQ,SAA0C;EAChD,OAAO;GACL,SAAS,QAAQ;GACjB,SAAS,QAAQ,WAAW;GAC5B,WAAW,QAAQ,aAAa;GAChC,gBAAgB,QAAQ,kBAAkB;GAC1C,QAAQ,QAAQ;GAChB,OAAO,QAAQ;GACf,KAAK,QAAQ;GACb,eAAe,QAAQ;EACzB;CACF;CAEA,MAAM,IAAI,MAA8C;EACtD,MAAM,SAAS,MAAM,KAAK,SAAS,KAAK;GAAC;GAAM;GAAM,KAAK;EAAO,GAAG,KAAK,SAAU,KAAK,OAAO,CAAC,GAA8B,KAAK,UAAU,KAAA,IAAY,OAAO,KAAK,KAAK,KAAK,IAAI,KAAA,CAAS;EAC5L,MAAM,WAAW,UAAmC;GAAE;GAAM,WAAW;EAAM;EAC7E,OAAO;GACL,UAAU,OAAO;GACjB,QAAS,OAAO,UAAU;GAC1B,UAAU;GACV,SAAS;GACT,WAAW,KAAK;GAChB,QAAQ,QAAQ,OAAO,MAAM;GAC7B,QAAQ,QAAQ,OAAO,MAAM;EAC/B;CACF;CAEA,MAAM,MAAmC;EASvC,OAAO;GANL,KAAK;GACL,MAHc,KAAK,IAAI,IAGX;GACZ,YAAY,CAEZ;EAEQ;CACZ;AACF;AAEA,IAAa,uBAAb,MAAkC;CACH;CAA7B,YAAY,UAAwC;EAAvB,KAAA,WAAA;CAAwB;CAErD,MAAM,MAA6C;EASjD,OAAO;GANL,KAAK;GACL,MAHc,KAAK,SAAS,KAAK,KAAK,MAAkB,KAAK,KAAM,KAAK,OAAO,CAAC,CAGpE,CAAC,CAAC,MAAM,OAAO;IAAE,UAAU,EAAE;IAAM,QAAS,EAAE,UAAU;GAA+B,EAAE;GACrG,YAAY,CAEZ;EAEU;CACd;CAEA,MAAM,cAAc,MAAsE;EACxF,IAAI,KAAK,QAAQ,SAAS,MAAM,KAAK,OAAO;EAC5C,MAAM,MAAM,MAAM,KAAK,SAAS,IAAI,KAAK,MAAkB,KAAK,KAAK,KAAK,OAAO,CAAC,GAAG,KAAK,MAAM,KAAK,MAAM,KAAK,YAAY;EAC5H,IAAI,KAAK,QAAQ,SAAS;GACxB,IAAI,KAAK;GACT,MAAM,KAAK,OAAO;EACpB;EACA,IAAI,WAA0B;EAC9B,MAAM,OAAO,IAAI,SAA4B,SAAS,WAAW;GAC/D,IAAI,QAAQ,KAAK,SAAS,SAAS;IACjC,IAAI,OAAO,SAAS,UAAU,WAAW;GAC3C,CAAC;GACD,IAAI,QAAQ,KAAK,SAAS,MAAM;GAChC,IAAI,QAAQ,KAAK,eAAe,QAAQ;IAAE;IAAU,QAAQ;GAAK,CAAC,CAAC;EACrE,CAAC;EAiBD,OAAO;GAfL,KAAK;GACL,QAAQ,IAAI;GACZ;GACA,QAAQ,SAAS,IAAI,SAAe,SAAS,WAAW;IACtD,IAAI,QAAQ,MAAM,OAAO,UAAU,QAAQ,OAAO,KAAK,IAAI,QAAQ,CAAC;GACtE,CAAC;GACD,QAAQ,OAAO,MAAM,SAAS,IAAI,OAAO,MAAM,IAAI;GACnD,mBAAmB,YAAY,KAAA;GAC/B,iBAAiB,aAAa;IAAE,OAAO;IAAW,UAAU;GAAE;GAC9D,kBAAkB,YAAY;IAAE,MAAM,IAAI,MAAM,uDAAuD;GAAE;GACzG,WAAW,YAAY;IACrB,IAAI,KAAK;IACT,MAAM,KAAK,YAAY,CAAC,CAAC;GAC3B;EAEU;CACd;AACF"}
1
+ {"version":3,"file":"process-provider.js","names":[],"sources":["../../src/exec-ssh/process-provider.ts"],"sourcesContent":["import type { ShellExecRequest, ShellExecSpec, ShellProcess, ShellRunResult } from '@deepseek-ai/dsh-shell'\nimport { SubprocessExecutableNotFoundError, type CollectedOutput, type SubprocessHandle, type SubprocessOutcome, type SubprocessSpawnSpec, type SubprocessTerminalEnvironment, type SubprocessTerminalHandle, type SubprocessTerminalSpawnSpec } from '@deepseek-ai/dsh-subprocess'\nimport type { SshExecutor } from './executor.js'\n\nexport class SshShellExecutor {\n constructor(private readonly executor: SshExecutor) {}\n\n resolve(request: ShellExecRequest): ShellExecSpec {\n return {\n command: request.command,\n workdir: request.workdir ?? '/',\n timeoutMs: request.timeoutMs ?? 60_000,\n stdoutMaxBytes: request.stdoutMaxBytes ?? 1024 * 1024,\n signal: request.signal,\n stdin: request.stdin,\n env: request.env,\n sandboxPolicy: request.sandboxPolicy,\n } as ShellExecSpec\n }\n\n async run(spec: ShellExecSpec): Promise<ShellRunResult> {\n const result = await this.executor.exec(['sh', '-c', spec.command], spec.workdir, (spec.env ?? {}) as Record<string, string>, spec.stdin !== undefined ? Buffer.from(spec.stdin) : undefined)\n const collect = (text: string): CollectedOutput => ({ text, truncated: false })\n return {\n exitCode: result.code,\n signal: (result.signal ?? null) as NodeJS.Signals | null,\n timedOut: false,\n aborted: false,\n timeoutMs: spec.timeoutMs,\n stdout: collect(result.stdout),\n stderr: collect(result.stderr),\n } as unknown as ShellRunResult\n }\n\n start(spec: ShellExecSpec): ShellProcess {\n const promise = this.run(spec)\n const proc: ShellProcess = {\n pid: -1,\n done: promise,\n kill: () => {\n void promise\n },\n } as unknown as ShellProcess\n return proc\n }\n}\n\nexport class SshSubprocessRuntime {\n constructor(private readonly executor: SshExecutor) {}\n\n async terminalEnvironment(signal?: AbortSignal): Promise<SubprocessTerminalEnvironment> {\n signal?.throwIfAborted()\n const script = `user=$(id -un); shell=$(getent passwd \"$user\" 2>/dev/null | cut -d: -f7); if [ -z \"$shell\" ]; then shell=$(awk -F: -v user=\"$user\" '$1 == user {print $7; exit}' /etc/passwd); fi; printf \"%s\" \"$shell\"`\n const result = await this.executor.exec(['sh', '-c', script], '/')\n signal?.throwIfAborted()\n const defaultShell = result.stdout.trim().split('\\n')[0]\n return { platform: 'posix', ...(defaultShell ? { defaultShell } : {}) }\n }\n\n async resolveExecutable(command: string, env: Readonly<Record<string, string>> = {}, signal?: AbortSignal): Promise<string> {\n signal?.throwIfAborted()\n const result = await this.executor.exec(['sh', '-c', 'command -v \"$1\"', 'sh', command], '/', { ...env })\n signal?.throwIfAborted()\n const path = result.stdout.trim().split('\\n')[0]\n if (result.code !== 0 || !path) throw new SubprocessExecutableNotFoundError(`executable not found on SSH node: ${command}`)\n return path\n }\n\n spawn(spec: SubprocessSpawnSpec): SubprocessHandle {\n const promise = this.executor.exec(spec.argv as string[], spec.cwd, (spec.env ?? {}) as Record<string, string>)\n const handle: SubprocessHandle = {\n pid: -1,\n done: promise.then((r) => ({ exitCode: r.code, signal: (r.signal ?? null) as NodeJS.Signals | null })),\n kill: () => {\n void promise\n },\n } as unknown as SubprocessHandle\n return handle\n }\n\n async spawnTerminal(spec: SubprocessTerminalSpawnSpec): Promise<SubprocessTerminalHandle> {\n if (spec.signal?.aborted) throw spec.signal.reason\n const pty = await this.executor.pty(spec.argv as string[], spec.cwd, spec.env ?? {}, spec.cols, spec.rows, spec.terminalType)\n if (spec.signal?.aborted) {\n pty.kill()\n throw spec.signal.reason\n }\n let exitCode: number | null = null\n const done = new Promise<SubprocessOutcome>((resolve, reject) => {\n pty.channel.once('exit', (code) => {\n if (typeof code === 'number') exitCode = code\n })\n pty.channel.once('error', reject)\n pty.channel.once('close', () => resolve({ exitCode, signal: null }))\n })\n const handle: SubprocessTerminalHandle = {\n pid: -1,\n output: pty.channel,\n done,\n write: (data) => new Promise<void>((resolve, reject) => {\n pty.channel.write(data, (error) => error ? reject(error) : resolve())\n }),\n resize: async (cols, rows) => pty.resize(cols, rows),\n inspectForeground: async () => undefined,\n inspectActivity: async () => ({ state: 'unknown', revision: 0 }),\n signalForeground: async () => { throw new Error('foreground signaling is unsupported for SSH terminals') },\n terminate: async () => {\n pty.kill()\n await done.catch(() => {})\n },\n }\n return handle\n }\n}\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { a as NodeTestReport, t as ExecutionWorldProvider } from "../types-C0TtEO7z.js";
1
+ import { a as NodeTestReport, t as ExecutionWorldProvider } from "../types-ekJQQ4x6.js";
2
2
  import { SshConnectionPool } from "./connection-pool.js";
3
3
  import { SshExecutor } from "./executor.js";
4
4
  import { SshFileSystem } from "./fs-provider.js";
@@ -1,4 +1,4 @@
1
- import { o as ShellDelegate } from "../types-C0TtEO7z.js";
1
+ import { o as ShellDelegate } from "../types-ekJQQ4x6.js";
2
2
  import { ShellExecSpec, ShellExecution, ShellExecutor } from "@deepseek-ai/dsh-shell";
3
3
  //#region src/router/decorate-shell.d.ts
4
4
  /**
@@ -1,4 +1,4 @@
1
- import { _ as WorkspaceBindings, a as NodeTestReport, t as ExecutionWorldProvider, v as WorldRef, y as WorldRegistry } from "../types-C0TtEO7z.js";
1
+ import { _ as WorkspaceBindings, a as NodeTestReport, t as ExecutionWorldProvider, v as WorldRef, y as WorldRegistry } from "../types-ekJQQ4x6.js";
2
2
  import { sharedWorldResolver } from "./resolve.js";
3
3
  import { Context } from "@deepseek-ai/cordis";
4
4
  //#region src/router/index.d.ts
@@ -14,6 +14,26 @@ function apply(ctx) {
14
14
  decorateFileSystem(ctx.fs);
15
15
  decorateSubprocess(ctx.subprocess);
16
16
  decorateShell(ctx.shell);
17
+ decorateTerminalController(ctx);
18
+ }
19
+ function decorateTerminalController(ctx) {
20
+ ctx.inject(["terminalController"], (terminalCtx) => {
21
+ const controller = terminalCtx.terminalController;
22
+ const originalExecution = controller.execution.bind(controller);
23
+ controller.execution = (agent) => {
24
+ const execution = originalExecution(agent);
25
+ const ref = sharedWorldResolver().resolve(agent.session.header.cwd);
26
+ if (ref.kind === "local") return execution;
27
+ if (ref.kind === "unrouted") throw new Error(`node ${ref.nodeId} world not available`);
28
+ const subprocess = Object.create(execution.subprocess);
29
+ subprocess.terminalEnvironment = ref.provider.subprocess.terminalEnvironment.bind(ref.provider.subprocess);
30
+ subprocess.resolveExecutable = ref.provider.subprocess.resolveExecutable.bind(ref.provider.subprocess);
31
+ return {
32
+ ...execution,
33
+ subprocess
34
+ };
35
+ };
36
+ });
17
37
  }
18
38
  //#endregion
19
39
  export { apply, inject, name, sharedWorldResolver };
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../src/router/index.ts"],"sourcesContent":["import type { Context } from '@deepseek-ai/cordis'\nimport { decorateFileSystem } from './decorate-fs.js'\nimport { decorateSubprocess } from './decorate-subprocess.js'\nimport { decorateShell } from './decorate-shell.js'\nimport { sharedWorldResolver } from './resolve.js'\n\nexport const name = 'dshb-router'\n\nexport const inject = ['fs', 'subprocess', 'shell']\n\nexport function apply(ctx: Context): void {\n ctx.provide('dshbRouter', sharedWorldResolver())\n decorateFileSystem(ctx.fs)\n decorateSubprocess(ctx.subprocess)\n decorateShell(ctx.shell)\n}\n\nexport { sharedWorldResolver } from './resolve.js'\nexport type { ExecutionWorldProvider, WorkspaceBindings, WorldRegistry, WorldRef, NodeTestReport } from './types.js'\n"],"mappings":";;;;;AAMA,MAAa,OAAO;AAEpB,MAAa,SAAS;CAAC;CAAM;CAAc;AAAO;AAElD,SAAgB,MAAM,KAAoB;CACxC,IAAI,QAAQ,cAAc,oBAAoB,CAAC;CAC/C,mBAAmB,IAAI,EAAE;CACzB,mBAAmB,IAAI,UAAU;CACjC,cAAc,IAAI,KAAK;AACzB"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../src/router/index.ts"],"sourcesContent":["import type { Context } from '@deepseek-ai/cordis'\nimport type { SubprocessRuntime } from '@deepseek-ai/dsh-subprocess'\nimport { decorateFileSystem } from './decorate-fs.js'\nimport { decorateSubprocess } from './decorate-subprocess.js'\nimport { decorateShell } from './decorate-shell.js'\nimport { sharedWorldResolver } from './resolve.js'\n\nexport const name = 'dshb-router'\n\nexport const inject = ['fs', 'subprocess', 'shell']\n\nexport function apply(ctx: Context): void {\n ctx.provide('dshbRouter', sharedWorldResolver())\n decorateFileSystem(ctx.fs)\n decorateSubprocess(ctx.subprocess)\n decorateShell(ctx.shell)\n decorateTerminalController(ctx)\n}\n\ninterface TerminalAgentLike {\n session: { header: { cwd: string } }\n}\n\ninterface TerminalControllerLike {\n execution(agent: TerminalAgentLike): { subprocess: SubprocessRuntime; sandboxPolicy: unknown }\n}\n\nfunction decorateTerminalController(ctx: Context): void {\n ctx.inject(['terminalController'], (terminalCtx: Context) => {\n const controller = (terminalCtx as unknown as { terminalController: TerminalControllerLike }).terminalController\n const originalExecution = controller.execution.bind(controller)\n\n controller.execution = (agent) => {\n const execution = originalExecution(agent)\n const ref = sharedWorldResolver().resolve(agent.session.header.cwd)\n if (ref.kind === 'local') return execution\n if (ref.kind === 'unrouted') throw new Error(`node ${ref.nodeId} world not available`)\n\n const subprocess = Object.create(execution.subprocess) as SubprocessRuntime\n subprocess.terminalEnvironment = ref.provider.subprocess.terminalEnvironment.bind(ref.provider.subprocess)\n subprocess.resolveExecutable = ref.provider.subprocess.resolveExecutable.bind(ref.provider.subprocess)\n return { ...execution, subprocess }\n }\n })\n}\n\nexport { sharedWorldResolver } from './resolve.js'\nexport type { ExecutionWorldProvider, WorkspaceBindings, WorldRegistry, WorldRef, NodeTestReport } from './types.js'\n"],"mappings":";;;;;AAOA,MAAa,OAAO;AAEpB,MAAa,SAAS;CAAC;CAAM;CAAc;AAAO;AAElD,SAAgB,MAAM,KAAoB;CACxC,IAAI,QAAQ,cAAc,oBAAoB,CAAC;CAC/C,mBAAmB,IAAI,EAAE;CACzB,mBAAmB,IAAI,UAAU;CACjC,cAAc,IAAI,KAAK;CACvB,2BAA2B,GAAG;AAChC;AAUA,SAAS,2BAA2B,KAAoB;CACtD,IAAI,OAAO,CAAC,oBAAoB,IAAI,gBAAyB;EAC3D,MAAM,aAAc,YAA0E;EAC9F,MAAM,oBAAoB,WAAW,UAAU,KAAK,UAAU;EAE9D,WAAW,aAAa,UAAU;GAChC,MAAM,YAAY,kBAAkB,KAAK;GACzC,MAAM,MAAM,oBAAoB,CAAC,CAAC,QAAQ,MAAM,QAAQ,OAAO,GAAG;GAClE,IAAI,IAAI,SAAS,SAAS,OAAO;GACjC,IAAI,IAAI,SAAS,YAAY,MAAM,IAAI,MAAM,QAAQ,IAAI,OAAO,qBAAqB;GAErF,MAAM,aAAa,OAAO,OAAO,UAAU,UAAU;GACrD,WAAW,sBAAsB,IAAI,SAAS,WAAW,oBAAoB,KAAK,IAAI,SAAS,UAAU;GACzG,WAAW,oBAAoB,IAAI,SAAS,WAAW,kBAAkB,KAAK,IAAI,SAAS,UAAU;GACrG,OAAO;IAAE,GAAG;IAAW;GAAW;EACpC;CACF,CAAC;AACH"}
@@ -1,4 +1,4 @@
1
- import { _ as WorkspaceBindings, v as WorldRef, y as WorldRegistry } from "../types-C0TtEO7z.js";
1
+ import { _ as WorkspaceBindings, v as WorldRef, y as WorldRegistry } from "../types-ekJQQ4x6.js";
2
2
  //#region src/router/resolve.d.ts
3
3
  interface BindingHit {
4
4
  nodeId: string;
@@ -1,2 +1,2 @@
1
- import { _ as WorkspaceBindings, a as NodeTestReport, c as ShellExecSpec, d as SubprocessDelegate, f as SubprocessHandle, g as SubprocessTerminalSpawnSpec, h as SubprocessTerminalHandle, i as FsTargetLike, l as ShellProcess, m as SubprocessSpawnSpec, n as FileSystem, o as ShellDelegate, p as SubprocessRuntime, r as FsDelegate, s as ShellExecRequest, t as ExecutionWorldProvider, u as ShellRunResult, v as WorldRef, y as WorldRegistry } from "../types-C0TtEO7z.js";
1
+ import { _ as WorkspaceBindings, a as NodeTestReport, c as ShellExecSpec, d as SubprocessDelegate, f as SubprocessHandle, g as SubprocessTerminalSpawnSpec, h as SubprocessTerminalHandle, i as FsTargetLike, l as ShellProcess, m as SubprocessSpawnSpec, n as FileSystem, o as ShellDelegate, p as SubprocessRuntime, r as FsDelegate, s as ShellExecRequest, t as ExecutionWorldProvider, u as ShellRunResult, v as WorldRef, y as WorldRegistry } from "../types-ekJQQ4x6.js";
2
2
  export { ExecutionWorldProvider, type FileSystem, FsDelegate, FsTargetLike, NodeTestReport, ShellDelegate, type ShellExecRequest, type ShellExecSpec, type ShellProcess, type ShellRunResult, SubprocessDelegate, type SubprocessHandle, type SubprocessRuntime, type SubprocessSpawnSpec, type SubprocessTerminalHandle, type SubprocessTerminalSpawnSpec, WorkspaceBindings, WorldRef, WorldRegistry };
@@ -1,5 +1,5 @@
1
+ import { SubprocessHandle as SubprocessHandle$1, SubprocessRuntime as SubprocessRuntime$1, SubprocessSpawnSpec as SubprocessSpawnSpec$1, SubprocessTerminalEnvironment, SubprocessTerminalHandle as SubprocessTerminalHandle$1, SubprocessTerminalSpawnSpec as SubprocessTerminalSpawnSpec$1 } from "@deepseek-ai/dsh-subprocess";
1
2
  import { FileSystem as FileSystem$1 } from "@deepseek-ai/dsh-fs";
2
- import { SubprocessHandle as SubprocessHandle$1, SubprocessRuntime as SubprocessRuntime$1, SubprocessSpawnSpec as SubprocessSpawnSpec$1, SubprocessTerminalHandle as SubprocessTerminalHandle$1, SubprocessTerminalSpawnSpec as SubprocessTerminalSpawnSpec$1 } from "@deepseek-ai/dsh-subprocess";
3
3
  import { ShellExecRequest as ShellExecRequest$1, ShellExecSpec as ShellExecSpec$1, ShellProcess as ShellProcess$1, ShellRunResult as ShellRunResult$1 } from "@deepseek-ai/dsh-shell";
4
4
  //#region src/router/types.d.ts
5
5
  interface NodeTestReport {
@@ -27,6 +27,8 @@ interface FsDelegate {
27
27
  }
28
28
  type FsTargetLike = string;
29
29
  interface SubprocessDelegate {
30
+ terminalEnvironment(signal?: AbortSignal): Promise<SubprocessTerminalEnvironment>;
31
+ resolveExecutable(command: string, env?: Readonly<Record<string, string>>, signal?: AbortSignal): Promise<string>;
30
32
  spawn(spec: SubprocessSpawnSpec$1): SubprocessHandle$1;
31
33
  spawnTerminal(spec: SubprocessTerminalSpawnSpec$1): Promise<SubprocessTerminalHandle$1>;
32
34
  }
@@ -64,4 +66,4 @@ type WorldRef = {
64
66
  };
65
67
  //#endregion
66
68
  export { WorkspaceBindings as _, NodeTestReport as a, ShellExecSpec$1 as c, SubprocessDelegate as d, SubprocessHandle$1 as f, SubprocessTerminalSpawnSpec$1 as g, SubprocessTerminalHandle$1 as h, FsTargetLike as i, ShellProcess$1 as l, SubprocessSpawnSpec$1 as m, FileSystem$1 as n, ShellDelegate as o, SubprocessRuntime$1 as p, FsDelegate as r, ShellExecRequest$1 as s, ExecutionWorldProvider as t, ShellRunResult$1 as u, WorldRef as v, WorldRegistry as y };
67
- //# sourceMappingURL=types-C0TtEO7z.d.ts.map
69
+ //# sourceMappingURL=types-ekJQQ4x6.d.ts.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@artenx/dshb",
3
- "version": "0.1.8",
3
+ "version": "0.1.9",
4
4
  "description": "Routes DSH filesystem, shell, subprocess, and PTY operations to local, SSH, and Docker execution nodes, with a node registry, an authentication gate, a mobile-aware management UI, and per-workspace custom project instructions.",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",