@snappedly-tools/shipyard 0.4.4 → 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.
@@ -0,0 +1,78 @@
1
+ import { MAX_TAIL_CHARS, collectProcessOutput } from './chunk-ACD46ZM4.js';
2
+ import { spawn } from 'child_process';
3
+
4
+ var noSandbox = (options) => ({
5
+ tag: "none",
6
+ name: "no-sandbox",
7
+ env: options?.env ?? {},
8
+ create: async (createOptions) => {
9
+ const worktreePath = createOptions.worktreePath;
10
+ const processEnv = { ...process.env, ...createOptions.env };
11
+ const maxOutputTailChars = options?.maxOutputTailChars ?? MAX_TAIL_CHARS;
12
+ const handle = {
13
+ worktreePath,
14
+ exec: (command, opts) => {
15
+ const cwd = opts?.cwd ?? worktreePath;
16
+ const isWindows = process.platform === "win32";
17
+ const shellCmd = isWindows ? "cmd.exe" : "sh";
18
+ const shellArgs = isWindows ? ["/d", "/s", "/c", command] : ["-c", command];
19
+ return new Promise((resolve, reject) => {
20
+ const proc = spawn(shellCmd, shellArgs, {
21
+ cwd,
22
+ env: processEnv,
23
+ signal: opts?.signal,
24
+ stdio: [
25
+ opts?.stdin !== void 0 ? "pipe" : "ignore",
26
+ "pipe",
27
+ "pipe"
28
+ ],
29
+ windowsVerbatimArguments: isWindows
30
+ });
31
+ if (opts?.stdin !== void 0) {
32
+ proc.stdin.write(opts.stdin);
33
+ proc.stdin.end();
34
+ }
35
+ proc.on("error", (error) => {
36
+ reject(new Error(`exec failed: ${error.message}`));
37
+ });
38
+ collectProcessOutput(
39
+ {
40
+ stdout: proc.stdout,
41
+ stderr: proc.stderr,
42
+ kill: () => proc.kill("SIGKILL"),
43
+ onClose: (listener) => proc.on("close", listener)
44
+ },
45
+ { ...opts, maxOutputTailChars },
46
+ resolve,
47
+ reject
48
+ );
49
+ });
50
+ },
51
+ interactiveExec: (args, opts) => {
52
+ return new Promise((resolve, reject) => {
53
+ const [cmd, ...rest] = args;
54
+ const proc = spawn(cmd, rest, {
55
+ cwd: opts.cwd ?? worktreePath,
56
+ env: processEnv,
57
+ stdio: [opts.stdin, opts.stdout, opts.stderr],
58
+ shell: process.platform === "win32",
59
+ signal: opts.signal
60
+ });
61
+ proc.on("error", (error) => {
62
+ reject(new Error(`exec failed: ${error.message}`));
63
+ });
64
+ proc.on("close", (code) => {
65
+ resolve({ exitCode: code ?? 0 });
66
+ });
67
+ });
68
+ },
69
+ close: async () => {
70
+ }
71
+ };
72
+ return handle;
73
+ }
74
+ });
75
+
76
+ export { noSandbox };
77
+ //# sourceMappingURL=chunk-SOJTAJTF.js.map
78
+ //# sourceMappingURL=chunk-SOJTAJTF.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/sandboxes/no-sandbox.ts"],"names":[],"mappings":"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","file":"chunk-SOJTAJTF.js","sourcesContent":["/**\n * No-sandbox provider — runs the agent directly on the host with no container isolation.\n *\n * Usage:\n * import { noSandbox } from \"@snappedly-tools/shipyard/sandboxes/no-sandbox\";\n * await run({ agent: codex(CODEX_MODELS.routine), sandbox: noSandbox(), prompt: \"...\" });\n *\n * Accepted by `run()`, `interactive()`, and `createSandbox()`. It skips\n * container isolation entirely and does not pass\n * `--dangerously-skip-permissions` to the agent.\n */\n\nimport { spawn, type StdioOptions } from \"node:child_process\";\nimport type {\n NoSandboxProvider,\n NoSandboxHandle,\n ExecResult,\n InteractiveExecOptions,\n} from \"../SandboxProvider.js\";\nimport { MAX_TAIL_CHARS } from \"../boundedTail.js\";\nimport { collectProcessOutput } from \"../processOutput.js\";\n\nexport interface NoSandboxOptions {\n /** Environment variables injected by this provider. Merged at launch time. */\n readonly env?: Record<string, string>;\n /**\n * Maximum number of characters of streamed `exec` output retained per stream\n * (stdout and stderr) when an `onLine` callback is supplied (default: 64KiB).\n *\n * Output is delivered live to `onLine` regardless; this only bounds the tail\n * returned in `ExecResult`, preventing a long-running agent's output from\n * overflowing V8's max string length and crashing the run.\n */\n readonly maxOutputTailChars?: number;\n}\n\n/**\n * Create a no-sandbox provider.\n *\n * The returned provider runs the agent directly on the host. All three\n * branch strategies are supported (head, merge-to-head, branch),\n * defaulting to head.\n */\nexport const noSandbox = (options?: NoSandboxOptions): NoSandboxProvider => ({\n tag: \"none\",\n name: \"no-sandbox\",\n env: options?.env ?? {},\n create: async (createOptions): Promise<NoSandboxHandle> => {\n const worktreePath = createOptions.worktreePath;\n const processEnv = { ...process.env, ...createOptions.env };\n const maxOutputTailChars = options?.maxOutputTailChars ?? MAX_TAIL_CHARS;\n\n const handle: NoSandboxHandle = {\n worktreePath,\n\n exec: (\n command: string,\n opts?: {\n onLine?: (line: string) => void;\n cwd?: string;\n sudo?: boolean;\n stdin?: string;\n signal?: AbortSignal;\n maxOutputBytes?: number;\n },\n ): Promise<ExecResult> => {\n // sudo is a no-op for no-sandbox — the user is already on the host\n const cwd = opts?.cwd ?? worktreePath;\n const isWindows = process.platform === \"win32\";\n // PowerShell and cmd.exe don't ship `sh`, so on Windows route the\n // command string through cmd.exe instead. `/d` skips AutoRun, `/s`\n // preserves the quoted command verbatim, `/c` runs it and exits.\n // `windowsVerbatimArguments` keeps Node from re-quoting our args.\n const shellCmd = isWindows ? \"cmd.exe\" : \"sh\";\n const shellArgs = isWindows\n ? [\"/d\", \"/s\", \"/c\", command]\n : [\"-c\", command];\n\n return new Promise((resolve, reject) => {\n const proc = spawn(shellCmd, shellArgs, {\n cwd,\n env: processEnv,\n signal: opts?.signal,\n stdio: [\n opts?.stdin !== undefined ? \"pipe\" : \"ignore\",\n \"pipe\",\n \"pipe\",\n ],\n windowsVerbatimArguments: isWindows,\n });\n\n if (opts?.stdin !== undefined) {\n proc.stdin!.write(opts.stdin);\n proc.stdin!.end();\n }\n\n proc.on(\"error\", (error) => {\n reject(new Error(`exec failed: ${error.message}`));\n });\n\n collectProcessOutput(\n {\n stdout: proc.stdout!,\n stderr: proc.stderr!,\n kill: () => proc.kill(\"SIGKILL\"),\n onClose: (listener) => proc.on(\"close\", listener),\n },\n { ...opts, maxOutputTailChars },\n resolve,\n reject,\n );\n });\n },\n\n interactiveExec: (\n args: string[],\n opts: InteractiveExecOptions,\n ): Promise<{ exitCode: number }> => {\n return new Promise((resolve, reject) => {\n const [cmd, ...rest] = args;\n // Agent CLIs on Windows are typically installed as `.cmd`/`.ps1`\n // npm wrappers; bare `spawn(\"claude\", …)` only resolves `.exe`\n // without `shell: true`, so let cmd.exe handle PATHEXT lookup.\n const proc = spawn(cmd!, rest, {\n cwd: opts.cwd ?? worktreePath,\n env: processEnv,\n stdio: [opts.stdin, opts.stdout, opts.stderr] as StdioOptions,\n shell: process.platform === \"win32\",\n signal: opts.signal,\n });\n\n proc.on(\"error\", (error: Error) => {\n reject(new Error(`exec failed: ${error.message}`));\n });\n\n proc.on(\"close\", (code: number | null) => {\n resolve({ exitCode: code ?? 0 });\n });\n });\n },\n\n close: async (): Promise<void> => {\n // No-op — no container to tear down\n },\n };\n\n return handle;\n },\n});\n"]}