noumen 0.6.0 → 0.8.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 (137) hide show
  1. package/README.md +237 -93
  2. package/dist/a2a/index.d.ts +5 -7
  3. package/dist/a2a/index.js +3 -4
  4. package/dist/a2a/index.js.map +1 -1
  5. package/dist/acp/index.d.ts +5 -7
  6. package/dist/acp/index.js +0 -1
  7. package/dist/acp/index.js.map +1 -1
  8. package/dist/{agent-DWE4_P5X.d.ts → agent-D0gl-qYi.d.ts} +89 -34
  9. package/dist/{chunk-6MMYCGJQ.js → chunk-5HY4IYNT.js} +1529 -2321
  10. package/dist/chunk-5HY4IYNT.js.map +1 -0
  11. package/dist/chunk-BC5BLWBC.js +21 -0
  12. package/dist/chunk-BC5BLWBC.js.map +1 -0
  13. package/dist/{chunk-XZN4QZLK.js → chunk-CX4BL6PC.js} +25 -15
  14. package/dist/chunk-CX4BL6PC.js.map +1 -0
  15. package/dist/{chunk-5GEX6ZSB.js → chunk-HQISH4D7.js} +60 -1
  16. package/dist/chunk-HQISH4D7.js.map +1 -0
  17. package/dist/{chunk-Y45R3PQL.js → chunk-NUCJXOUV.js} +32 -18
  18. package/dist/{chunk-Y45R3PQL.js.map → chunk-NUCJXOUV.js.map} +1 -1
  19. package/dist/chunk-OPFFLQZL.js +40 -0
  20. package/dist/chunk-OPFFLQZL.js.map +1 -0
  21. package/dist/chunk-PDEAJ272.js +660 -0
  22. package/dist/chunk-PDEAJ272.js.map +1 -0
  23. package/dist/chunk-PKHLGGEC.js +115 -0
  24. package/dist/chunk-PKHLGGEC.js.map +1 -0
  25. package/dist/chunk-XQTNXRE7.js +176 -0
  26. package/dist/chunk-XQTNXRE7.js.map +1 -0
  27. package/dist/chunk-XZPAA5TO.js +817 -0
  28. package/dist/chunk-XZPAA5TO.js.map +1 -0
  29. package/dist/cli/index.js +77 -42
  30. package/dist/cli/index.js.map +1 -1
  31. package/dist/client/index.d.ts +1 -2
  32. package/dist/client/index.js +0 -2
  33. package/dist/client/index.js.map +1 -1
  34. package/dist/client-JJFLE6RT.js +9 -0
  35. package/dist/{computer-BPdxSo6X.d.ts → computer-DzMR92tK.d.ts} +1 -1
  36. package/dist/docker.d.ts +2 -2
  37. package/dist/docker.js +0 -1
  38. package/dist/docker.js.map +1 -1
  39. package/dist/e2b.d.ts +2 -2
  40. package/dist/e2b.js +0 -1
  41. package/dist/e2b.js.map +1 -1
  42. package/dist/freestyle.d.ts +2 -2
  43. package/dist/freestyle.js +0 -1
  44. package/dist/freestyle.js.map +1 -1
  45. package/dist/{headless-FFU2DESQ.js → headless-25DU4MJQ.js} +1 -3
  46. package/dist/{headless-FFU2DESQ.js.map → headless-25DU4MJQ.js.map} +1 -1
  47. package/dist/{history-snip-64GYP4ZL.js → history-snip-HAWNAYKY.js} +1 -2
  48. package/dist/index.d.ts +351 -72
  49. package/dist/index.js +54 -55
  50. package/dist/jsonrpc/index.js +0 -1
  51. package/dist/local.d.ts +168 -0
  52. package/dist/local.js +40 -0
  53. package/dist/local.js.map +1 -0
  54. package/dist/lsp/index.d.ts +4 -5
  55. package/dist/lsp/index.js +0 -1
  56. package/dist/{lsp-PS3BWIHC.js → lsp-3APWNKB2.js} +1 -2
  57. package/dist/{manager-DLXK63XC.js → manager-Z5EQ7YYV.js} +1 -2
  58. package/dist/mcp/index.d.ts +16 -8
  59. package/dist/mcp/index.js +5 -6
  60. package/dist/mcp/index.js.map +1 -1
  61. package/dist/{mcp-auth-AEI2R4ZC.js → mcp-auth-NOIQPF7W.js} +1 -2
  62. package/dist/{provider-factory-TUHU3DIG.js → provider-factory-KNBSHXJ6.js} +3 -3
  63. package/dist/{render-GRN4ZSSW.js → render-4VEODRK7.js} +1 -2
  64. package/dist/{resolve-6KUZNEYW.js → resolve-AGQZFMKD.js} +3 -3
  65. package/dist/sandbox-DAqQo0Tj.d.ts +49 -0
  66. package/dist/sandbox-index-ODNREIFA.js +32 -0
  67. package/dist/sandbox-index-ODNREIFA.js.map +1 -0
  68. package/dist/server/index.d.ts +18 -7
  69. package/dist/server/index.js +9 -5
  70. package/dist/server/index.js.map +1 -1
  71. package/dist/{server-BzNGKTP6.d.ts → server-DFXdlqyX.d.ts} +1 -1
  72. package/dist/{spinner-OJNR6NFO.js → spinner-72JEISPK.js} +1 -2
  73. package/dist/sprites.d.ts +2 -2
  74. package/dist/sprites.js +0 -1
  75. package/dist/sprites.js.map +1 -1
  76. package/dist/ssh.d.ts +2 -2
  77. package/dist/ssh.js +0 -1
  78. package/dist/ssh.js.map +1 -1
  79. package/dist/{types-DhXwOQwD.d.ts → types-BX4ALqoN.d.ts} +76 -4
  80. package/dist/{types-kiGBF35b.d.ts → types-DLZNyF5t.d.ts} +125 -1
  81. package/dist/unsandboxed.d.ts +59 -0
  82. package/dist/unsandboxed.js +32 -0
  83. package/dist/unsandboxed.js.map +1 -0
  84. package/dist/{uuid-RVN2T26F.js → uuid-CVTNAPEB.js} +1 -2
  85. package/dist/{zod-7YXKWYMC.js → zod-VKURGPRT.js} +1 -2
  86. package/package.json +35 -50
  87. package/dist/cache-BlBwXXPS.d.ts +0 -38
  88. package/dist/chunk-5GEX6ZSB.js.map +0 -1
  89. package/dist/chunk-6MMYCGJQ.js.map +0 -1
  90. package/dist/chunk-7IQCQI2G.js +0 -94
  91. package/dist/chunk-7IQCQI2G.js.map +0 -1
  92. package/dist/chunk-CCM2AXZG.js +0 -16
  93. package/dist/chunk-CCM2AXZG.js.map +0 -1
  94. package/dist/chunk-DGUM43GV.js +0 -11
  95. package/dist/chunk-HEQQQGK5.js +0 -131
  96. package/dist/chunk-HEQQQGK5.js.map +0 -1
  97. package/dist/chunk-I3JTUFPK.js +0 -171
  98. package/dist/chunk-I3JTUFPK.js.map +0 -1
  99. package/dist/chunk-XZN4QZLK.js.map +0 -1
  100. package/dist/chunk-ZXSDKBYB.js +0 -474
  101. package/dist/chunk-ZXSDKBYB.js.map +0 -1
  102. package/dist/client-CRRO2376.js +0 -10
  103. package/dist/providers/anthropic.d.ts +0 -19
  104. package/dist/providers/anthropic.js +0 -36
  105. package/dist/providers/anthropic.js.map +0 -1
  106. package/dist/providers/bedrock.d.ts +0 -39
  107. package/dist/providers/bedrock.js +0 -56
  108. package/dist/providers/bedrock.js.map +0 -1
  109. package/dist/providers/gemini.d.ts +0 -17
  110. package/dist/providers/gemini.js +0 -262
  111. package/dist/providers/gemini.js.map +0 -1
  112. package/dist/providers/ollama.d.ts +0 -13
  113. package/dist/providers/ollama.js +0 -20
  114. package/dist/providers/ollama.js.map +0 -1
  115. package/dist/providers/openai.d.ts +0 -21
  116. package/dist/providers/openai.js +0 -9
  117. package/dist/providers/openrouter.d.ts +0 -16
  118. package/dist/providers/openrouter.js +0 -24
  119. package/dist/providers/openrouter.js.map +0 -1
  120. package/dist/providers/vertex.d.ts +0 -42
  121. package/dist/providers/vertex.js +0 -68
  122. package/dist/providers/vertex.js.map +0 -1
  123. package/dist/sandbox-9qeMTNrD.d.ts +0 -126
  124. package/dist/types-CD0rUKKT.d.ts +0 -109
  125. package/dist/uuid-RVN2T26F.js.map +0 -1
  126. package/dist/zod-7YXKWYMC.js.map +0 -1
  127. /package/dist/{chunk-DGUM43GV.js.map → client-JJFLE6RT.js.map} +0 -0
  128. /package/dist/{client-CRRO2376.js.map → history-snip-HAWNAYKY.js.map} +0 -0
  129. /package/dist/{history-snip-64GYP4ZL.js.map → lsp-3APWNKB2.js.map} +0 -0
  130. /package/dist/{lsp-PS3BWIHC.js.map → manager-Z5EQ7YYV.js.map} +0 -0
  131. /package/dist/{manager-DLXK63XC.js.map → mcp-auth-NOIQPF7W.js.map} +0 -0
  132. /package/dist/{mcp-auth-AEI2R4ZC.js.map → provider-factory-KNBSHXJ6.js.map} +0 -0
  133. /package/dist/{provider-factory-TUHU3DIG.js.map → render-4VEODRK7.js.map} +0 -0
  134. /package/dist/{providers/openai.js.map → resolve-AGQZFMKD.js.map} +0 -0
  135. /package/dist/{render-GRN4ZSSW.js.map → spinner-72JEISPK.js.map} +0 -0
  136. /package/dist/{resolve-6KUZNEYW.js.map → uuid-CVTNAPEB.js.map} +0 -0
  137. /package/dist/{spinner-OJNR6NFO.js.map → zod-VKURGPRT.js.map} +0 -0
package/dist/ssh.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/virtual/ssh-fs.ts","../src/virtual/ssh-computer.ts","../src/virtual/ssh-sandbox.ts"],"sourcesContent":["import * as pathMod from \"node:path\";\nimport type { VirtualFs, FileEntry, FileStat, ReadOptions } from \"./fs.js\";\nimport type { SshClient, SshSftpSession } from \"./ssh-computer.js\";\n\nexport interface SshFsOptions {\n /** A connected ssh2 Client instance. */\n client: SshClient;\n /** Working directory for relative path resolution (default: /). */\n workingDir?: string;\n}\n\n/**\n * VirtualFs backed by SFTP file operations over SSH.\n *\n * Uses the ssh2 Client's SFTP subsystem for all file I/O. The SFTP session\n * is opened lazily on the first operation and reused for the lifetime of\n * the SshFs instance.\n *\n * Requires `ssh2` as an optional peer dependency.\n * The caller is responsible for the Client lifecycle.\n */\nexport class SshFs implements VirtualFs {\n private client: SshClient;\n private workingDir: string;\n private sftpSession: SshSftpSession | null = null;\n private sftpPromise: Promise<SshSftpSession> | null = null;\n\n constructor(opts: SshFsOptions) {\n this.client = opts.client;\n this.workingDir = opts.workingDir ?? \"/\";\n }\n\n private getSftp(): Promise<SshSftpSession> {\n if (this.sftpSession) return Promise.resolve(this.sftpSession);\n if (this.sftpPromise) return this.sftpPromise;\n this.sftpPromise = new Promise<SshSftpSession>((resolve, reject) => {\n this.client.sftp((err, sftp) => {\n if (err) {\n this.sftpPromise = null;\n reject(err);\n } else {\n this.sftpSession = sftp;\n resolve(sftp);\n }\n });\n });\n return this.sftpPromise;\n }\n\n private resolvePath(p: string): string {\n if (p.includes(\"\\0\")) {\n throw new Error(\"Path contains null bytes\");\n }\n const normalizedBase = this.workingDir.endsWith(\"/\")\n ? this.workingDir\n : this.workingDir + \"/\";\n if (p.startsWith(\"/\")) {\n const normalized = pathMod.normalize(p);\n if (\n normalized !== this.workingDir &&\n !normalized.startsWith(normalizedBase)\n ) {\n throw new Error(\n `Absolute path \"${p}\" is outside working directory \"${this.workingDir}\"`,\n );\n }\n return normalized;\n }\n const resolved = pathMod.resolve(this.workingDir, p);\n if (\n resolved !== this.workingDir &&\n !resolved.startsWith(normalizedBase)\n ) {\n throw new Error(\n `Path \"${p}\" escapes working directory \"${this.workingDir}\"`,\n );\n }\n return resolved;\n }\n\n async readFile(path: string, _opts?: ReadOptions): Promise<string> {\n const resolved = this.resolvePath(path);\n const sftp = await this.getSftp();\n return new Promise<string>((resolve, reject) => {\n sftp.readFile(resolved, { encoding: \"utf8\" }, (err, data) => {\n if (err) reject(new Error(`SshFs readFile failed: ${err.message}`));\n else resolve(data as string);\n });\n });\n }\n\n async readFileBytes(path: string, maxBytes?: number): Promise<Buffer> {\n const resolved = this.resolvePath(path);\n const sftp = await this.getSftp();\n\n if (maxBytes === undefined) {\n return new Promise<Buffer>((resolve, reject) => {\n sftp.readFile(resolved, (err, data) => {\n if (err) reject(new Error(`SshFs readFileBytes failed: ${err.message}`));\n else resolve(data);\n });\n });\n }\n\n return new Promise<Buffer>((resolve, reject) => {\n sftp.open(resolved, \"r\", (err, handle) => {\n if (err) {\n reject(new Error(`SshFs readFileBytes failed: ${err.message}`));\n return;\n }\n const buf = Buffer.alloc(maxBytes);\n sftp.read(handle, buf, 0, maxBytes, 0, (readErr, bytesRead, readBuf) => {\n sftp.close(handle, () => {});\n if (readErr) {\n reject(new Error(`SshFs readFileBytes failed: ${readErr.message}`));\n } else {\n resolve(readBuf.subarray(0, bytesRead));\n }\n });\n });\n });\n }\n\n async writeFile(path: string, content: string): Promise<void> {\n const resolved = this.resolvePath(path);\n const sftp = await this.getSftp();\n const dir = pathMod.dirname(resolved);\n await this.mkdirRecursive(sftp, dir);\n return new Promise<void>((resolve, reject) => {\n sftp.writeFile(resolved, content, (err) => {\n if (err) reject(new Error(`SshFs writeFile failed: ${err.message}`));\n else resolve();\n });\n });\n }\n\n async appendFile(path: string, content: string): Promise<void> {\n const resolved = this.resolvePath(path);\n const sftp = await this.getSftp();\n const dir = pathMod.dirname(resolved);\n await this.mkdirRecursive(sftp, dir);\n return new Promise<void>((resolve, reject) => {\n sftp.appendFile(resolved, content, (err) => {\n if (err) reject(new Error(`SshFs appendFile failed: ${err.message}`));\n else resolve();\n });\n });\n }\n\n async deleteFile(\n path: string,\n opts?: { recursive?: boolean },\n ): Promise<void> {\n const resolved = this.resolvePath(path);\n if (opts?.recursive) {\n const sftp = await this.getSftp();\n await this.rmRecursive(sftp, resolved);\n return;\n }\n const sftp = await this.getSftp();\n return new Promise<void>((resolve, reject) => {\n sftp.unlink(resolved, (err) => {\n if (err) reject(new Error(`SshFs deleteFile failed: ${err.message}`));\n else resolve();\n });\n });\n }\n\n async mkdir(path: string, opts?: { recursive?: boolean }): Promise<void> {\n const resolved = this.resolvePath(path);\n const sftp = await this.getSftp();\n if (opts?.recursive) {\n await this.mkdirRecursive(sftp, resolved);\n return;\n }\n return new Promise<void>((resolve, reject) => {\n sftp.mkdir(resolved, (err) => {\n if (err) reject(new Error(`SshFs mkdir failed: ${err.message}`));\n else resolve();\n });\n });\n }\n\n async readdir(\n path: string,\n _opts?: { recursive?: boolean },\n ): Promise<FileEntry[]> {\n const resolved = this.resolvePath(path);\n const sftp = await this.getSftp();\n return new Promise<FileEntry[]>((resolve, reject) => {\n sftp.readdir(resolved, (err, list) => {\n if (err) {\n reject(new Error(`SshFs readdir failed: ${err.message}`));\n return;\n }\n const entries: FileEntry[] = list.map((item) => ({\n name: item.filename,\n path: pathMod.join(resolved, item.filename),\n isDirectory: item.attrs.isDirectory(),\n isFile: item.attrs.isFile(),\n }));\n resolve(entries);\n });\n });\n }\n\n async exists(path: string): Promise<boolean> {\n const resolved = this.resolvePath(path);\n const sftp = await this.getSftp();\n return new Promise<boolean>((resolve) => {\n sftp.stat(resolved, (err) => {\n resolve(!err);\n });\n });\n }\n\n async stat(path: string): Promise<FileStat> {\n const resolved = this.resolvePath(path);\n const sftp = await this.getSftp();\n return new Promise<FileStat>((resolve, reject) => {\n sftp.stat(resolved, (err, stats) => {\n if (err) {\n reject(new Error(`SshFs stat failed: ${err.message}`));\n return;\n }\n resolve({\n size: stats.size,\n isDirectory: stats.isDirectory(),\n isFile: stats.isFile(),\n modifiedAt: stats.mtime > 0 ? new Date(stats.mtime * 1000) : undefined,\n });\n });\n });\n }\n\n private async mkdirRecursive(\n sftp: SshSftpSession,\n dir: string,\n ): Promise<void> {\n const parts = dir.split(\"/\").filter(Boolean);\n let current = \"/\";\n for (const part of parts) {\n current = pathMod.join(current, part);\n await new Promise<void>((resolve) => {\n sftp.mkdir(current, () => {\n resolve();\n });\n });\n }\n }\n\n private async rmRecursive(\n sftp: SshSftpSession,\n target: string,\n ): Promise<void> {\n const isDir = await new Promise<boolean>((resolve) => {\n sftp.stat(target, (err, stats) => {\n if (err) resolve(false);\n else resolve(stats.isDirectory());\n });\n });\n\n if (!isDir) {\n return new Promise<void>((resolve, reject) => {\n sftp.unlink(target, (err) => {\n if (err) reject(new Error(`SshFs deleteFile failed: ${err.message}`));\n else resolve();\n });\n });\n }\n\n const entries = await new Promise<Array<{ filename: string; attrs: { isDirectory(): boolean } }>>(\n (resolve, reject) => {\n sftp.readdir(target, (err, list) => {\n if (err) reject(new Error(`SshFs deleteFile failed: ${err.message}`));\n else resolve(list);\n });\n },\n );\n\n for (const entry of entries) {\n await this.rmRecursive(sftp, pathMod.join(target, entry.filename));\n }\n\n return new Promise<void>((resolve, reject) => {\n sftp.rmdir(target, (err) => {\n if (err) reject(new Error(`SshFs deleteFile failed: ${err.message}`));\n else resolve();\n });\n });\n }\n}\n","import type { VirtualComputer, ExecOptions, CommandResult } from \"./computer.js\";\n\n/**\n * Minimal subset of the ssh2 Channel interface used by SshComputer / SshFs.\n * Avoids a hard import of ssh2 at the module level.\n */\nexport interface SshChannel {\n on(event: string, listener: (...args: any[]) => void): SshChannel;\n stderr: { on(event: string, listener: (...args: any[]) => void): unknown };\n destroy?(): void;\n}\n\n/**\n * Minimal subset of the ssh2 SFTPWrapper interface used by SshFs.\n */\nexport interface SshSftpSession {\n readFile(\n path: string,\n callback: (err: Error | undefined, data: Buffer) => void,\n ): void;\n readFile(\n path: string,\n opts: { encoding: string },\n callback: (err: Error | undefined, data: string) => void,\n ): void;\n writeFile(\n path: string,\n data: string | Buffer,\n callback: (err: Error | undefined) => void,\n ): void;\n appendFile(\n path: string,\n data: string | Buffer,\n callback: (err: Error | undefined) => void,\n ): void;\n unlink(path: string, callback: (err: Error | undefined) => void): void;\n rmdir(path: string, callback: (err: Error | undefined) => void): void;\n mkdir(path: string, callback: (err: Error | undefined) => void): void;\n readdir(\n path: string,\n callback: (\n err: Error | undefined,\n list: Array<{\n filename: string;\n longname: string;\n attrs: { size: number; isDirectory(): boolean; isFile(): boolean; mtime: number; atime: number };\n }>,\n ) => void,\n ): void;\n stat(\n path: string,\n callback: (\n err: Error | undefined,\n stats: { size: number; isDirectory(): boolean; isFile(): boolean; mtime: number; atime: number },\n ) => void,\n ): void;\n open(\n path: string,\n flags: string,\n callback: (err: Error | undefined, handle: Buffer) => void,\n ): void;\n read(\n handle: Buffer,\n buffer: Buffer,\n offset: number,\n length: number,\n position: number,\n callback: (err: Error | undefined, bytesRead: number, buf: Buffer) => void,\n ): void;\n close(handle: Buffer, callback: (err: Error | undefined) => void): void;\n end(): void;\n}\n\n/**\n * Minimal subset of the ssh2 Client interface used by SshComputer and SshFs.\n * Avoids a hard import of ssh2 at the module level.\n */\nexport interface SshClient {\n exec(\n command: string,\n callback: (err: Error | undefined, channel: SshChannel) => void,\n ): void;\n exec(\n command: string,\n opts: Record<string, unknown>,\n callback: (err: Error | undefined, channel: SshChannel) => void,\n ): void;\n sftp(\n callback: (err: Error | undefined, sftp: SshSftpSession) => void,\n ): void;\n end(): void;\n on(event: string, listener: (...args: any[]) => void): this;\n}\n\nexport interface SshComputerOptions {\n /** A connected ssh2 Client instance. */\n client: SshClient;\n /** Default working directory for commands (default: /). */\n defaultCwd?: string;\n /** Default timeout in ms for commands (default: 30000). */\n defaultTimeout?: number;\n}\n\n/**\n * VirtualComputer backed by command execution over SSH.\n *\n * Requires `ssh2` as an optional peer dependency.\n * The caller is responsible for the Client lifecycle (connect, end).\n */\nexport class SshComputer implements VirtualComputer {\n private client: SshClient;\n private defaultCwd: string;\n private defaultTimeout: number;\n\n constructor(opts: SshComputerOptions) {\n this.client = opts.client;\n this.defaultCwd = opts.defaultCwd ?? \"/\";\n this.defaultTimeout = opts.defaultTimeout ?? 30_000;\n }\n\n async executeCommand(\n command: string,\n opts?: ExecOptions,\n ): Promise<CommandResult> {\n const cwd = opts?.cwd ?? this.defaultCwd;\n const timeout = opts?.timeout ?? this.defaultTimeout;\n\n let envPrefix = \"\";\n if (opts?.env) {\n envPrefix = Object.entries(opts.env)\n .map(([k, v]) => `${k}=${shellEscape(v)}`)\n .join(\" \") + \" \";\n }\n\n const fullCommand = `cd ${shellEscape(cwd)} && ${envPrefix}${command}`;\n\n return new Promise<CommandResult>((resolve, reject) => {\n this.client.exec(fullCommand, (err, channel) => {\n if (err) {\n reject(err);\n return;\n }\n\n const stdoutBufs: Buffer[] = [];\n const stderrBufs: Buffer[] = [];\n\n const timer = setTimeout(() => {\n channel.destroy?.();\n resolve({\n exitCode: 1,\n stdout: Buffer.concat(stdoutBufs).toString(\"utf-8\"),\n stderr:\n Buffer.concat(stderrBufs).toString(\"utf-8\") +\n \"\\n[timeout after \" + timeout + \"ms]\",\n });\n }, timeout);\n\n channel.on(\"data\", (chunk: Buffer) => {\n stdoutBufs.push(Buffer.from(chunk));\n });\n\n channel.stderr.on(\"data\", (chunk: Buffer) => {\n stderrBufs.push(Buffer.from(chunk));\n });\n\n channel.on(\"close\", (code: number) => {\n clearTimeout(timer);\n resolve({\n exitCode: code ?? 0,\n stdout: Buffer.concat(stdoutBufs).toString(\"utf-8\"),\n stderr: Buffer.concat(stderrBufs).toString(\"utf-8\"),\n });\n });\n\n channel.on(\"error\", (channelErr: Error) => {\n clearTimeout(timer);\n reject(channelErr);\n });\n });\n });\n }\n}\n\nfunction shellEscape(s: string): string {\n return `'${s.replace(/'/g, \"'\\\\''\")}'`;\n}\n","import type { Sandbox } from \"./sandbox.js\";\nimport { SshFs } from \"./ssh-fs.js\";\nimport { SshComputer, type SshClient } from \"./ssh-computer.js\";\nimport { createFsProxy, createComputerProxy } from \"./proxy.js\";\n\nexport interface SshSandboxOptions {\n /**\n * A pre-connected ssh2 Client instance. When provided the sandbox uses\n * this client directly — no auto-connect occurs and `dispose()` will\n * **not** call `client.end()`.\n *\n * When omitted, a new ssh2 Client is created and connected on the first\n * `init()` call using `host`, `port`, `username`, and the provided\n * credentials. The client is ended when `dispose()` is called.\n */\n client?: SshClient;\n /**\n * SSH hostname. Required when `client` is omitted; ignored when `client`\n * is provided.\n */\n host?: string;\n /** SSH port (default: 22). Only used during auto-connect. */\n port?: number;\n /** SSH username (default: \"root\"). Only used during auto-connect. */\n username?: string;\n /** Password for password-based authentication. Only used during auto-connect. */\n password?: string;\n /** Private key for key-based authentication (PEM string or Buffer). Only used during auto-connect. */\n privateKey?: string | Buffer;\n /** Passphrase for an encrypted private key. Only used during auto-connect. */\n passphrase?: string;\n /** Working directory on the remote host. */\n cwd?: string;\n /** Default timeout (ms) for shell commands. */\n defaultTimeout?: number;\n}\n\n/**\n * Create a `Sandbox` backed by a remote host over SSH.\n * Requires `ssh2` as an optional peer dependency.\n *\n * **Auto-connect:** When `client` is omitted and `host` is provided,\n * an ssh2 Client is created and connected lazily on the first `init()`\n * call. The connection identifier (`host:port`) is available through\n * `sandboxId()` for session persistence.\n *\n * **Explicit client:** When `client` is provided, `init()` binds it\n * immediately. `dispose()` is a no-op — the caller owns the client's\n * lifecycle.\n *\n * @example\n * ```ts\n * // Auto-connect with private key\n * const sandbox = SshSandbox({\n * host: \"dev.example.com\",\n * username: \"deploy\",\n * privateKey: fs.readFileSync(\"~/.ssh/id_ed25519\"),\n * cwd: \"/home/deploy/project\",\n * });\n *\n * // Explicit client (lifecycle managed externally)\n * const sandbox = SshSandbox({ client: myConnectedClient, cwd: \"/workspace\" });\n * ```\n */\nexport function SshSandbox(opts: SshSandboxOptions): Sandbox {\n if (opts.client) {\n const c = opts.client;\n return {\n fs: new SshFs({ client: c, workingDir: opts.cwd }),\n computer: new SshComputer({\n client: c,\n defaultCwd: opts.cwd,\n defaultTimeout: opts.defaultTimeout,\n }),\n sandboxId: () =>\n opts.host ? `${opts.host}:${opts.port ?? 22}` : undefined,\n };\n }\n\n if (!opts.host) {\n throw new Error(\"SshSandbox requires either `client` or `host`\");\n }\n\n const fsProxy = createFsProxy();\n const computerProxy = createComputerProxy();\n const identifier = `${opts.host}:${opts.port ?? 22}`;\n let clientRef: SshClient | null = null;\n let autoCreated = false;\n let initPromise: Promise<void> | null = null;\n\n async function doInit(): Promise<void> {\n const modName = \"ssh2\";\n const ssh2 = await import(/* webpackIgnore: true */ modName);\n const ClientClass =\n (ssh2 as any).Client ?? (ssh2 as any).default?.Client;\n if (!ClientClass) {\n throw new Error(\n \"Could not resolve Client class from 'ssh2' package\",\n );\n }\n\n const client: SshClient = new ClientClass();\n await new Promise<void>((resolve, reject) => {\n client.on(\"ready\", () => resolve());\n client.on(\"error\", (err: Error) => reject(err));\n (client as any).connect({\n host: opts.host,\n port: opts.port ?? 22,\n username: opts.username ?? \"root\",\n password: opts.password,\n privateKey: opts.privateKey,\n passphrase: opts.passphrase,\n });\n });\n\n clientRef = client;\n autoCreated = true;\n fsProxy.setTarget(new SshFs({ client, workingDir: opts.cwd }));\n computerProxy.setTarget(\n new SshComputer({\n client,\n defaultCwd: opts.cwd,\n defaultTimeout: opts.defaultTimeout,\n }),\n );\n }\n\n return {\n fs: fsProxy,\n computer: computerProxy,\n sandboxId: () => identifier,\n\n init(): Promise<void> {\n if (!initPromise) {\n initPromise = doInit().catch((err) => {\n initPromise = null;\n throw err;\n });\n }\n return initPromise;\n },\n\n async dispose(): Promise<void> {\n if (initPromise) {\n await initPromise.catch(() => {});\n }\n if (!autoCreated || !clientRef) return;\n try {\n clientRef.end();\n } catch {\n /* best-effort */\n }\n },\n };\n}\n"],"mappings":"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","names":["resolve","sftp","resolve","resolve"]}
1
+ {"version":3,"sources":["../src/virtual/ssh-fs.ts","../src/virtual/ssh-computer.ts","../src/virtual/ssh-sandbox.ts"],"sourcesContent":["import * as pathMod from \"node:path\";\nimport type { VirtualFs, FileEntry, FileStat, ReadOptions } from \"./fs.js\";\nimport type { SshClient, SshSftpSession } from \"./ssh-computer.js\";\n\nexport interface SshFsOptions {\n /** A connected ssh2 Client instance. */\n client: SshClient;\n /** Working directory for relative path resolution (default: /). */\n workingDir?: string;\n}\n\n/**\n * VirtualFs backed by SFTP file operations over SSH.\n *\n * Uses the ssh2 Client's SFTP subsystem for all file I/O. The SFTP session\n * is opened lazily on the first operation and reused for the lifetime of\n * the SshFs instance.\n *\n * Requires `ssh2` as an optional peer dependency.\n * The caller is responsible for the Client lifecycle.\n */\nexport class SshFs implements VirtualFs {\n private client: SshClient;\n private workingDir: string;\n private sftpSession: SshSftpSession | null = null;\n private sftpPromise: Promise<SshSftpSession> | null = null;\n\n constructor(opts: SshFsOptions) {\n this.client = opts.client;\n this.workingDir = opts.workingDir ?? \"/\";\n }\n\n private getSftp(): Promise<SshSftpSession> {\n if (this.sftpSession) return Promise.resolve(this.sftpSession);\n if (this.sftpPromise) return this.sftpPromise;\n this.sftpPromise = new Promise<SshSftpSession>((resolve, reject) => {\n this.client.sftp((err, sftp) => {\n if (err) {\n this.sftpPromise = null;\n reject(err);\n } else {\n this.sftpSession = sftp;\n resolve(sftp);\n }\n });\n });\n return this.sftpPromise;\n }\n\n private resolvePath(p: string): string {\n if (p.includes(\"\\0\")) {\n throw new Error(\"Path contains null bytes\");\n }\n const normalizedBase = this.workingDir.endsWith(\"/\")\n ? this.workingDir\n : this.workingDir + \"/\";\n if (p.startsWith(\"/\")) {\n const normalized = pathMod.normalize(p);\n if (\n normalized !== this.workingDir &&\n !normalized.startsWith(normalizedBase)\n ) {\n throw new Error(\n `Absolute path \"${p}\" is outside working directory \"${this.workingDir}\"`,\n );\n }\n return normalized;\n }\n const resolved = pathMod.resolve(this.workingDir, p);\n if (\n resolved !== this.workingDir &&\n !resolved.startsWith(normalizedBase)\n ) {\n throw new Error(\n `Path \"${p}\" escapes working directory \"${this.workingDir}\"`,\n );\n }\n return resolved;\n }\n\n async readFile(path: string, _opts?: ReadOptions): Promise<string> {\n const resolved = this.resolvePath(path);\n const sftp = await this.getSftp();\n return new Promise<string>((resolve, reject) => {\n sftp.readFile(resolved, { encoding: \"utf8\" }, (err, data) => {\n if (err) reject(new Error(`SshFs readFile failed: ${err.message}`));\n else resolve(data as string);\n });\n });\n }\n\n async readFileBytes(path: string, maxBytes?: number): Promise<Buffer> {\n const resolved = this.resolvePath(path);\n const sftp = await this.getSftp();\n\n if (maxBytes === undefined) {\n return new Promise<Buffer>((resolve, reject) => {\n sftp.readFile(resolved, (err, data) => {\n if (err) reject(new Error(`SshFs readFileBytes failed: ${err.message}`));\n else resolve(data);\n });\n });\n }\n\n return new Promise<Buffer>((resolve, reject) => {\n sftp.open(resolved, \"r\", (err, handle) => {\n if (err) {\n reject(new Error(`SshFs readFileBytes failed: ${err.message}`));\n return;\n }\n const buf = Buffer.alloc(maxBytes);\n sftp.read(handle, buf, 0, maxBytes, 0, (readErr, bytesRead, readBuf) => {\n sftp.close(handle, () => {});\n if (readErr) {\n reject(new Error(`SshFs readFileBytes failed: ${readErr.message}`));\n } else {\n resolve(readBuf.subarray(0, bytesRead));\n }\n });\n });\n });\n }\n\n async writeFile(path: string, content: string): Promise<void> {\n const resolved = this.resolvePath(path);\n const sftp = await this.getSftp();\n const dir = pathMod.dirname(resolved);\n await this.mkdirRecursive(sftp, dir);\n return new Promise<void>((resolve, reject) => {\n sftp.writeFile(resolved, content, (err) => {\n if (err) reject(new Error(`SshFs writeFile failed: ${err.message}`));\n else resolve();\n });\n });\n }\n\n async appendFile(path: string, content: string): Promise<void> {\n const resolved = this.resolvePath(path);\n const sftp = await this.getSftp();\n const dir = pathMod.dirname(resolved);\n await this.mkdirRecursive(sftp, dir);\n return new Promise<void>((resolve, reject) => {\n sftp.appendFile(resolved, content, (err) => {\n if (err) reject(new Error(`SshFs appendFile failed: ${err.message}`));\n else resolve();\n });\n });\n }\n\n async deleteFile(\n path: string,\n opts?: { recursive?: boolean },\n ): Promise<void> {\n const resolved = this.resolvePath(path);\n if (opts?.recursive) {\n const sftp = await this.getSftp();\n await this.rmRecursive(sftp, resolved);\n return;\n }\n const sftp = await this.getSftp();\n return new Promise<void>((resolve, reject) => {\n sftp.unlink(resolved, (err) => {\n if (err) reject(new Error(`SshFs deleteFile failed: ${err.message}`));\n else resolve();\n });\n });\n }\n\n async mkdir(path: string, opts?: { recursive?: boolean }): Promise<void> {\n const resolved = this.resolvePath(path);\n const sftp = await this.getSftp();\n if (opts?.recursive) {\n await this.mkdirRecursive(sftp, resolved);\n return;\n }\n return new Promise<void>((resolve, reject) => {\n sftp.mkdir(resolved, (err) => {\n if (err) reject(new Error(`SshFs mkdir failed: ${err.message}`));\n else resolve();\n });\n });\n }\n\n async readdir(\n path: string,\n _opts?: { recursive?: boolean },\n ): Promise<FileEntry[]> {\n const resolved = this.resolvePath(path);\n const sftp = await this.getSftp();\n return new Promise<FileEntry[]>((resolve, reject) => {\n sftp.readdir(resolved, (err, list) => {\n if (err) {\n reject(new Error(`SshFs readdir failed: ${err.message}`));\n return;\n }\n const entries: FileEntry[] = list.map((item) => ({\n name: item.filename,\n path: pathMod.join(resolved, item.filename),\n isDirectory: item.attrs.isDirectory(),\n isFile: item.attrs.isFile(),\n }));\n resolve(entries);\n });\n });\n }\n\n async exists(path: string): Promise<boolean> {\n const resolved = this.resolvePath(path);\n const sftp = await this.getSftp();\n return new Promise<boolean>((resolve) => {\n sftp.stat(resolved, (err) => {\n resolve(!err);\n });\n });\n }\n\n async stat(path: string): Promise<FileStat> {\n const resolved = this.resolvePath(path);\n const sftp = await this.getSftp();\n return new Promise<FileStat>((resolve, reject) => {\n sftp.stat(resolved, (err, stats) => {\n if (err) {\n reject(new Error(`SshFs stat failed: ${err.message}`));\n return;\n }\n resolve({\n size: stats.size,\n isDirectory: stats.isDirectory(),\n isFile: stats.isFile(),\n modifiedAt: stats.mtime > 0 ? new Date(stats.mtime * 1000) : undefined,\n });\n });\n });\n }\n\n private async mkdirRecursive(\n sftp: SshSftpSession,\n dir: string,\n ): Promise<void> {\n const parts = dir.split(\"/\").filter(Boolean);\n let current = \"/\";\n for (const part of parts) {\n current = pathMod.join(current, part);\n await new Promise<void>((resolve) => {\n sftp.mkdir(current, () => {\n resolve();\n });\n });\n }\n }\n\n private async rmRecursive(\n sftp: SshSftpSession,\n target: string,\n ): Promise<void> {\n const isDir = await new Promise<boolean>((resolve) => {\n sftp.stat(target, (err, stats) => {\n if (err) resolve(false);\n else resolve(stats.isDirectory());\n });\n });\n\n if (!isDir) {\n return new Promise<void>((resolve, reject) => {\n sftp.unlink(target, (err) => {\n if (err) reject(new Error(`SshFs deleteFile failed: ${err.message}`));\n else resolve();\n });\n });\n }\n\n const entries = await new Promise<Array<{ filename: string; attrs: { isDirectory(): boolean } }>>(\n (resolve, reject) => {\n sftp.readdir(target, (err, list) => {\n if (err) reject(new Error(`SshFs deleteFile failed: ${err.message}`));\n else resolve(list);\n });\n },\n );\n\n for (const entry of entries) {\n await this.rmRecursive(sftp, pathMod.join(target, entry.filename));\n }\n\n return new Promise<void>((resolve, reject) => {\n sftp.rmdir(target, (err) => {\n if (err) reject(new Error(`SshFs deleteFile failed: ${err.message}`));\n else resolve();\n });\n });\n }\n}\n","import type { VirtualComputer, ExecOptions, CommandResult } from \"./computer.js\";\n\n/**\n * Minimal subset of the ssh2 Channel interface used by SshComputer / SshFs.\n * Avoids a hard import of ssh2 at the module level.\n */\nexport interface SshChannel {\n on(event: string, listener: (...args: any[]) => void): SshChannel;\n stderr: { on(event: string, listener: (...args: any[]) => void): unknown };\n destroy?(): void;\n}\n\n/**\n * Minimal subset of the ssh2 SFTPWrapper interface used by SshFs.\n */\nexport interface SshSftpSession {\n readFile(\n path: string,\n callback: (err: Error | undefined, data: Buffer) => void,\n ): void;\n readFile(\n path: string,\n opts: { encoding: string },\n callback: (err: Error | undefined, data: string) => void,\n ): void;\n writeFile(\n path: string,\n data: string | Buffer,\n callback: (err: Error | undefined) => void,\n ): void;\n appendFile(\n path: string,\n data: string | Buffer,\n callback: (err: Error | undefined) => void,\n ): void;\n unlink(path: string, callback: (err: Error | undefined) => void): void;\n rmdir(path: string, callback: (err: Error | undefined) => void): void;\n mkdir(path: string, callback: (err: Error | undefined) => void): void;\n readdir(\n path: string,\n callback: (\n err: Error | undefined,\n list: Array<{\n filename: string;\n longname: string;\n attrs: { size: number; isDirectory(): boolean; isFile(): boolean; mtime: number; atime: number };\n }>,\n ) => void,\n ): void;\n stat(\n path: string,\n callback: (\n err: Error | undefined,\n stats: { size: number; isDirectory(): boolean; isFile(): boolean; mtime: number; atime: number },\n ) => void,\n ): void;\n open(\n path: string,\n flags: string,\n callback: (err: Error | undefined, handle: Buffer) => void,\n ): void;\n read(\n handle: Buffer,\n buffer: Buffer,\n offset: number,\n length: number,\n position: number,\n callback: (err: Error | undefined, bytesRead: number, buf: Buffer) => void,\n ): void;\n close(handle: Buffer, callback: (err: Error | undefined) => void): void;\n end(): void;\n}\n\n/**\n * Minimal subset of the ssh2 Client interface used by SshComputer and SshFs.\n * Avoids a hard import of ssh2 at the module level.\n */\nexport interface SshClient {\n exec(\n command: string,\n callback: (err: Error | undefined, channel: SshChannel) => void,\n ): void;\n exec(\n command: string,\n opts: Record<string, unknown>,\n callback: (err: Error | undefined, channel: SshChannel) => void,\n ): void;\n sftp(\n callback: (err: Error | undefined, sftp: SshSftpSession) => void,\n ): void;\n end(): void;\n on(event: string, listener: (...args: any[]) => void): this;\n}\n\nexport interface SshComputerOptions {\n /** A connected ssh2 Client instance. */\n client: SshClient;\n /** Default working directory for commands (default: /). */\n defaultCwd?: string;\n /** Default timeout in ms for commands (default: 30000). */\n defaultTimeout?: number;\n}\n\n/**\n * VirtualComputer backed by command execution over SSH.\n *\n * Requires `ssh2` as an optional peer dependency.\n * The caller is responsible for the Client lifecycle (connect, end).\n */\nexport class SshComputer implements VirtualComputer {\n private client: SshClient;\n private defaultCwd: string;\n private defaultTimeout: number;\n\n constructor(opts: SshComputerOptions) {\n this.client = opts.client;\n this.defaultCwd = opts.defaultCwd ?? \"/\";\n this.defaultTimeout = opts.defaultTimeout ?? 30_000;\n }\n\n async executeCommand(\n command: string,\n opts?: ExecOptions,\n ): Promise<CommandResult> {\n const cwd = opts?.cwd ?? this.defaultCwd;\n const timeout = opts?.timeout ?? this.defaultTimeout;\n\n let envPrefix = \"\";\n if (opts?.env) {\n envPrefix = Object.entries(opts.env)\n .map(([k, v]) => `${k}=${shellEscape(v)}`)\n .join(\" \") + \" \";\n }\n\n const fullCommand = `cd ${shellEscape(cwd)} && ${envPrefix}${command}`;\n\n return new Promise<CommandResult>((resolve, reject) => {\n this.client.exec(fullCommand, (err, channel) => {\n if (err) {\n reject(err);\n return;\n }\n\n const stdoutBufs: Buffer[] = [];\n const stderrBufs: Buffer[] = [];\n\n const timer = setTimeout(() => {\n channel.destroy?.();\n resolve({\n exitCode: 1,\n stdout: Buffer.concat(stdoutBufs).toString(\"utf-8\"),\n stderr:\n Buffer.concat(stderrBufs).toString(\"utf-8\") +\n \"\\n[timeout after \" + timeout + \"ms]\",\n });\n }, timeout);\n\n channel.on(\"data\", (chunk: Buffer) => {\n stdoutBufs.push(Buffer.from(chunk));\n });\n\n channel.stderr.on(\"data\", (chunk: Buffer) => {\n stderrBufs.push(Buffer.from(chunk));\n });\n\n channel.on(\"close\", (code: number) => {\n clearTimeout(timer);\n resolve({\n exitCode: code ?? 0,\n stdout: Buffer.concat(stdoutBufs).toString(\"utf-8\"),\n stderr: Buffer.concat(stderrBufs).toString(\"utf-8\"),\n });\n });\n\n channel.on(\"error\", (channelErr: Error) => {\n clearTimeout(timer);\n reject(channelErr);\n });\n });\n });\n }\n}\n\nfunction shellEscape(s: string): string {\n return `'${s.replace(/'/g, \"'\\\\''\")}'`;\n}\n","import type { Sandbox } from \"./sandbox.js\";\nimport { SshFs } from \"./ssh-fs.js\";\nimport { SshComputer, type SshClient } from \"./ssh-computer.js\";\nimport { createFsProxy, createComputerProxy } from \"./proxy.js\";\n\nexport interface SshSandboxOptions {\n /**\n * A pre-connected ssh2 Client instance. When provided the sandbox uses\n * this client directly — no auto-connect occurs and `dispose()` will\n * **not** call `client.end()`.\n *\n * When omitted, a new ssh2 Client is created and connected on the first\n * `init()` call using `host`, `port`, `username`, and the provided\n * credentials. The client is ended when `dispose()` is called.\n */\n client?: SshClient;\n /**\n * SSH hostname. Required when `client` is omitted; ignored when `client`\n * is provided.\n */\n host?: string;\n /** SSH port (default: 22). Only used during auto-connect. */\n port?: number;\n /** SSH username (default: \"root\"). Only used during auto-connect. */\n username?: string;\n /** Password for password-based authentication. Only used during auto-connect. */\n password?: string;\n /** Private key for key-based authentication (PEM string or Buffer). Only used during auto-connect. */\n privateKey?: string | Buffer;\n /** Passphrase for an encrypted private key. Only used during auto-connect. */\n passphrase?: string;\n /** Working directory on the remote host. */\n cwd?: string;\n /** Default timeout (ms) for shell commands. */\n defaultTimeout?: number;\n}\n\n/**\n * Create a `Sandbox` backed by a remote host over SSH.\n * Requires `ssh2` as an optional peer dependency.\n *\n * **Auto-connect:** When `client` is omitted and `host` is provided,\n * an ssh2 Client is created and connected lazily on the first `init()`\n * call. The connection identifier (`host:port`) is available through\n * `sandboxId()` for session persistence.\n *\n * **Explicit client:** When `client` is provided, `init()` binds it\n * immediately. `dispose()` is a no-op — the caller owns the client's\n * lifecycle.\n *\n * @example\n * ```ts\n * // Auto-connect with private key\n * const sandbox = SshSandbox({\n * host: \"dev.example.com\",\n * username: \"deploy\",\n * privateKey: fs.readFileSync(\"~/.ssh/id_ed25519\"),\n * cwd: \"/home/deploy/project\",\n * });\n *\n * // Explicit client (lifecycle managed externally)\n * const sandbox = SshSandbox({ client: myConnectedClient, cwd: \"/workspace\" });\n * ```\n */\nexport function SshSandbox(opts: SshSandboxOptions): Sandbox {\n if (opts.client) {\n const c = opts.client;\n return {\n fs: new SshFs({ client: c, workingDir: opts.cwd }),\n computer: new SshComputer({\n client: c,\n defaultCwd: opts.cwd,\n defaultTimeout: opts.defaultTimeout,\n }),\n sandboxId: () =>\n opts.host ? `${opts.host}:${opts.port ?? 22}` : undefined,\n };\n }\n\n if (!opts.host) {\n throw new Error(\"SshSandbox requires either `client` or `host`\");\n }\n\n const fsProxy = createFsProxy();\n const computerProxy = createComputerProxy();\n const identifier = `${opts.host}:${opts.port ?? 22}`;\n let clientRef: SshClient | null = null;\n let autoCreated = false;\n let initPromise: Promise<void> | null = null;\n\n async function doInit(): Promise<void> {\n const modName = \"ssh2\";\n const ssh2 = await import(/* webpackIgnore: true */ modName);\n const ClientClass =\n (ssh2 as any).Client ?? (ssh2 as any).default?.Client;\n if (!ClientClass) {\n throw new Error(\n \"Could not resolve Client class from 'ssh2' package\",\n );\n }\n\n const client: SshClient = new ClientClass();\n await new Promise<void>((resolve, reject) => {\n client.on(\"ready\", () => resolve());\n client.on(\"error\", (err: Error) => reject(err));\n (client as any).connect({\n host: opts.host,\n port: opts.port ?? 22,\n username: opts.username ?? \"root\",\n password: opts.password,\n privateKey: opts.privateKey,\n passphrase: opts.passphrase,\n });\n });\n\n clientRef = client;\n autoCreated = true;\n fsProxy.setTarget(new SshFs({ client, workingDir: opts.cwd }));\n computerProxy.setTarget(\n new SshComputer({\n client,\n defaultCwd: opts.cwd,\n defaultTimeout: opts.defaultTimeout,\n }),\n );\n }\n\n return {\n fs: fsProxy,\n computer: computerProxy,\n sandboxId: () => identifier,\n\n init(): Promise<void> {\n if (!initPromise) {\n initPromise = doInit().catch((err) => {\n initPromise = null;\n throw err;\n });\n }\n return initPromise;\n },\n\n async dispose(): Promise<void> {\n if (initPromise) {\n await initPromise.catch(() => {});\n }\n if (!autoCreated || !clientRef) return;\n try {\n clientRef.end();\n } catch {\n /* best-effort */\n }\n },\n };\n}\n"],"mappings":"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","names":["resolve","sftp","resolve","resolve"]}
@@ -1,6 +1,5 @@
1
- import { c as CheckpointConfig, F as FileCheckpointState, D as DiffStats, d as FileCheckpointSnapshot, S as StreamEvent, e as ContentPart } from './types-kiGBF35b.js';
2
- import { a as VirtualFs, V as VirtualComputer } from './computer-BPdxSo6X.js';
3
- import { a as PermissionMode, b as PermissionResult } from './types-CD0rUKKT.js';
1
+ import { V as VirtualFs, a as VirtualComputer } from './computer-DzMR92tK.js';
2
+ import { C as CheckpointConfig, F as FileCheckpointState, D as DiffStats, a as FileCheckpointSnapshot, b as PermissionMode, S as StreamEvent, c as PermissionResult, d as ContentPart } from './types-DLZNyF5t.js';
4
3
 
5
4
  /**
6
5
  * Zod integration utilities. Users bring their own `zod` dependency — these
@@ -46,6 +45,74 @@ declare function registerZodToJsonSchema(fn: (schema: unknown) => JsonSchemaType
46
45
  */
47
46
  declare function formatZodValidationError(toolName: string, issues: SafeParseResult["error"]): string;
48
47
 
48
+ /**
49
+ * Configuration for which dot-directory names the agent recognizes when
50
+ * reading and writing auxiliary state (context files, skills, sessions,
51
+ * tasks, checkpoints, CLI config, MCP auth tokens, etc).
52
+ *
53
+ * The list is ordered by preference:
54
+ * - `names[0]` is the canonical write target.
55
+ * - For single-file reads (e.g. `config.json`), callers use first-hit-wins
56
+ * across candidates in order.
57
+ * - For additive reads (e.g. rules, skills), every candidate is loaded and
58
+ * later entries in the list have higher precedence when resolving
59
+ * collisions (mirrors the context loader's layer ordering).
60
+ *
61
+ * The same list applies to both project scope (cwd ancestors) and user
62
+ * scope (home directory). There is intentionally no per-scope split — if
63
+ * a caller needs that, they can route through different resolvers.
64
+ */
65
+ interface DotDirConfig {
66
+ names: string[];
67
+ }
68
+ /**
69
+ * Default dot-directory configuration. Recognizes `.noumen` (canonical)
70
+ * and `.claude` (compatibility), preferring `.noumen` for writes.
71
+ */
72
+ declare const DEFAULT_DOT_DIRS: DotDirConfig;
73
+ /**
74
+ * Pure path resolver over a `DotDirConfig`. Does no I/O — callers pair it
75
+ * with `readFirstDotDir` / `readAllDotDirs` (VirtualFs helpers below) or
76
+ * their own filesystem code.
77
+ */
78
+ interface DotDirResolver {
79
+ /** The underlying configuration (exposed for permissions and logging). */
80
+ config: DotDirConfig;
81
+ /**
82
+ * Absolute paths for each candidate dot-dir under `base`, in preference
83
+ * order (most preferred first). `base` is appended with a `/` separator
84
+ * unless already present.
85
+ */
86
+ candidates(base: string): string[];
87
+ /** The canonical write target (`candidates(base)[0]`). */
88
+ writePath(base: string): string;
89
+ /**
90
+ * Each candidate joined with `rel`, in preference order. Use this for
91
+ * first-hit-wins reads (e.g. `config.json`).
92
+ */
93
+ joinRead(base: string, rel: string): string[];
94
+ /** Write path joined with `rel`. */
95
+ joinWrite(base: string, rel: string): string;
96
+ }
97
+ declare function createDotDirResolver(config?: DotDirConfig): DotDirResolver;
98
+ /**
99
+ * Read the first file that exists across the resolver's candidate paths
100
+ * under `base/<name>/<rel>`. Returns `null` if none match.
101
+ */
102
+ declare function readFirstDotDir(fs: VirtualFs, resolver: DotDirResolver, base: string, rel: string): Promise<{
103
+ path: string;
104
+ content: string;
105
+ } | null>;
106
+ /**
107
+ * Read every candidate file that exists under `base/<name>/<rel>`. Results
108
+ * are ordered from lowest to highest precedence (matching the context
109
+ * loader's layer-stacking convention where later entries win).
110
+ */
111
+ declare function readAllDotDirs(fs: VirtualFs, resolver: DotDirResolver, base: string, rel: string): Promise<Array<{
112
+ path: string;
113
+ content: string;
114
+ }>>;
115
+
49
116
  type HookEvent = "PreToolUse" | "PostToolUse" | "PostToolUseFailure" | "PreCompact" | "PostCompact" | "TurnStart" | "TurnEnd" | "SubagentStart" | "SubagentStop" | "SessionStart" | "SessionEnd" | "PermissionRequest" | "PermissionDenied" | "FileWrite" | "ModelSwitch" | "RetryAttempt" | "MemoryUpdate" | "Error";
50
117
  interface PreToolUseHookInput {
51
118
  event: "PreToolUse";
@@ -474,6 +541,11 @@ interface ToolContext {
474
541
  notifyHook?: (event: string, input: Record<string, unknown>) => Promise<void>;
475
542
  /** Abort signal — tools should check this to terminate early on user abort. */
476
543
  signal?: AbortSignal;
544
+ /**
545
+ * Dot-directory resolver — lets tools honor custom dot-dir configurations
546
+ * (e.g. Worktree writes under `<dotdir>/worktrees/<slug>`).
547
+ */
548
+ dotDirResolver?: DotDirResolver;
477
549
  }
478
550
  interface ToolParameterProperty {
479
551
  type: string;
@@ -556,4 +628,4 @@ interface Tool {
556
628
  call(args: Record<string, unknown>, ctx: ToolContext): Promise<ToolResult>;
557
629
  }
558
630
 
559
- export { type SessionEndHookInput as A, type SessionStartHookInput as B, type SubagentStartHookInput as C, DiagnosticRegistry as D, type SubagentStopHookInput as E, FileCheckpointManager as F, type Task as G, type HookDefinition as H, type TaskCreateInput as I, type JsonSchemaType as J, type TaskStatus as K, type LspServerConfig as L, type MemoryUpdateHookInput as M, type NotificationHookInput as N, type TaskUpdateInput as O, type PostToolUseFailureHookInput as P, type ToolParameters as Q, type RetryAttemptHookInput as R, type SubagentConfig as S, type Tool as T, formatZodValidationError as U, registerZodToJsonSchema as V, zodToJsonSchema as W, type ZodLikeSchema as Z, type LspServerState as a, type LspDiagnostic as b, type LspLocation as c, type LspOperation as d, LspServerManager as e, type LspSymbol as f, type ToolResult as g, type ToolContext as h, type SubagentRun as i, TaskStore as j, type FileStateCacheConfig as k, type HookEvent as l, type HookInput as m, type PostToolUseFailureHookOutput as n, type PostToolUseHookInput as o, type PostToolUseHookOutput as p, type PreToolUseHookInput as q, type PreToolUseHookOutput as r, type FileState as s, FileStateCache as t, type FileWriteHookInput as u, type HookOutput as v, type ModelSwitchHookInput as w, type PermissionDeniedHookInput as x, type PermissionRequestHookInput as y, type SafeParseResult as z };
631
+ export { readFirstDotDir as $, type PermissionDeniedHookInput as A, type PermissionRequestHookInput as B, type SafeParseResult as C, DiagnosticRegistry as D, type SessionEndHookInput as E, FileCheckpointManager as F, type SessionStartHookInput as G, type HookDefinition as H, type SubagentStartHookInput as I, type JsonSchemaType as J, type SubagentStopHookInput as K, type LspServerConfig as L, type MemoryUpdateHookInput as M, type NotificationHookInput as N, type Task as O, type PostToolUseFailureHookInput as P, type TaskCreateInput as Q, type RetryAttemptHookInput as R, type SubagentConfig as S, type Tool as T, type TaskStatus as U, type TaskUpdateInput as V, type ToolParameters as W, createDotDirResolver as X, formatZodValidationError as Y, type ZodLikeSchema as Z, readAllDotDirs as _, type LspServerState as a, registerZodToJsonSchema as a0, zodToJsonSchema as a1, type LspDiagnostic as b, type LspLocation as c, type LspOperation as d, LspServerManager as e, type LspSymbol as f, type ToolResult as g, type ToolContext as h, type DotDirResolver as i, type DotDirConfig as j, type SubagentRun as k, TaskStore as l, type FileStateCacheConfig as m, type HookEvent as n, type HookInput as o, type PostToolUseFailureHookOutput as p, type PostToolUseHookInput as q, type PostToolUseHookOutput as r, type PreToolUseHookInput as s, type PreToolUseHookOutput as t, DEFAULT_DOT_DIRS as u, type FileState as v, FileStateCache as w, type FileWriteHookInput as x, type HookOutput as y, type ModelSwitchHookInput as z };
@@ -574,6 +574,15 @@ interface ChatParams {
574
574
  system?: string;
575
575
  temperature?: number;
576
576
  thinking?: ThinkingConfig;
577
+ /**
578
+ * Fine-grained reasoning effort hint. Honored by providers whose
579
+ * reasoning-capable models expose an explicit effort knob (OpenAI
580
+ * GPT-5 / o-series today). Providers that don't recognise the knob
581
+ * ignore it. Use `"minimal"` for cheap structural calls (e.g.
582
+ * auto-title, classification) so the model doesn't burn the whole
583
+ * `max_tokens` budget on internal reasoning before emitting output.
584
+ */
585
+ reasoningEffort?: "minimal" | "low" | "medium" | "high";
577
586
  /** Constrain the model to produce structured output matching this schema. */
578
587
  outputFormat?: OutputFormat;
579
588
  /**
@@ -610,4 +619,119 @@ declare class ChatStreamError extends Error {
610
619
  });
611
620
  }
612
621
 
613
- export { type UserMessage as $, type AIProvider as A, type CustomTitleEntry as B, type ChatParams as C, type DiffStats as D, type Entry as E, type FileCheckpointState as F, type FileCheckpointBackup as G, type FileCheckpointEntry as H, type ImageContent as I, type JsonSchemaOutputFormat as J, type ImageUrlContent as K, type JsonObjectOutputFormat as L, type ModelPricing as M, type MemoryType as N, type OutputFormat as O, type MessageEntry as P, type MetadataEntry as Q, type RunOptions as R, type StreamEvent as S, type ToolDefinition as T, type UUID as U, type SerializedMessage as V, type SnipBoundaryEntry as W, type SummaryEntry as X, type SystemMessage as Y, type TextContent as Z, type ToolParameterProperty as _, type ChatStreamChunk as a, createCheckpointState as a0, type ChatMessage as b, type CheckpointConfig as c, type FileCheckpointSnapshot as d, type ContentPart as e, type ContentReplacementRecord as f, type SessionInfo as g, type UsageRecord as h, type CostSummary as i, type ModelUsageSummary as j, type ChatCompletionUsage as k, type ThinkingConfig as l, type MemoryConfig as m, type ToolResult as n, type ToolCallContent as o, type MemoryProvider as p, type MemoryEntry as q, type AssistantMessage as r, type ToolResultMessage as s, type ToolResultOverflowEntry as t, type AiTitleEntry as u, type ChatStreamChoice as v, type ChatStreamDelta as w, ChatStreamError as x, type CompactBoundaryEntry as y, type ContentReplacementEntry as z };
622
+ type PermissionMode = "default" | "plan" | "acceptEdits" | "auto" | "bypassPermissions" | "dontAsk";
623
+ type PermissionBehavior = "allow" | "deny" | "ask";
624
+ type PermissionRuleSource = "user" | "project" | "session" | "policy";
625
+ /** Precedence order: policy > project > user > session. */
626
+ declare const RULE_SOURCE_PRECEDENCE: PermissionRuleSource[];
627
+ interface PermissionRule {
628
+ toolName: string;
629
+ ruleContent?: string;
630
+ behavior: PermissionBehavior;
631
+ /** Where this rule came from. Higher-precedence sources override lower ones. */
632
+ source?: PermissionRuleSource;
633
+ }
634
+ type PermissionUpdate = {
635
+ type: "addRules";
636
+ rules: PermissionRule[];
637
+ } | {
638
+ type: "removeRules";
639
+ toolName: string;
640
+ behavior?: PermissionBehavior;
641
+ } | {
642
+ type: "setMode";
643
+ mode: PermissionMode;
644
+ } | {
645
+ type: "addDirectories";
646
+ directories: string[];
647
+ } | {
648
+ type: "removeDirectories";
649
+ directories: string[];
650
+ };
651
+ interface PermissionAllowResult<Input extends Record<string, unknown> = Record<string, unknown>> {
652
+ behavior: "allow";
653
+ updatedInput?: Input;
654
+ reason?: string;
655
+ }
656
+ interface PermissionDenyResult {
657
+ behavior: "deny";
658
+ message: string;
659
+ reason?: string;
660
+ }
661
+ interface PermissionAskResult {
662
+ behavior: "ask";
663
+ message: string;
664
+ reason?: string;
665
+ suggestions?: PermissionRule[];
666
+ }
667
+ interface PermissionPassthroughResult {
668
+ behavior: "passthrough";
669
+ message: string;
670
+ reason?: string;
671
+ suggestions?: PermissionRule[];
672
+ }
673
+ /**
674
+ * What `Tool.checkPermissions` returns. Includes `passthrough` for tools that
675
+ * have no opinion and want the global pipeline to decide.
676
+ */
677
+ type PermissionResult<Input extends Record<string, unknown> = Record<string, unknown>> = PermissionAllowResult<Input> | PermissionDenyResult | PermissionAskResult | PermissionPassthroughResult;
678
+ /**
679
+ * Final decision after the pipeline resolves. No `passthrough` — always
680
+ * one of allow / deny / ask.
681
+ */
682
+ type PermissionDecision<Input extends Record<string, unknown> = Record<string, unknown>> = PermissionAllowResult<Input> | PermissionDenyResult | PermissionAskResult;
683
+ interface PermissionRequest {
684
+ toolName: string;
685
+ input: Record<string, unknown>;
686
+ message: string;
687
+ suggestions?: PermissionRule[];
688
+ isReadOnly: boolean;
689
+ isDestructive: boolean;
690
+ /** Abort signal from the session — handlers should stop promptly when fired. */
691
+ signal?: AbortSignal;
692
+ }
693
+ interface PermissionResponse {
694
+ allow: boolean;
695
+ updatedInput?: Record<string, unknown>;
696
+ feedback?: string;
697
+ addRules?: PermissionRule[];
698
+ }
699
+ type PermissionHandler = (request: PermissionRequest) => Promise<PermissionResponse>;
700
+ interface AutoModeConfig {
701
+ /** Custom system prompt for the classifier. When omitted, uses a default. */
702
+ classifierPrompt?: string;
703
+ /** Model to use for classification. When omitted, uses the thread's model. */
704
+ classifierModel?: string;
705
+ }
706
+ interface DenialTrackingConfig {
707
+ /** Max consecutive denials before fallback (default: 3). */
708
+ maxConsecutive?: number;
709
+ /** Max total denials before fallback (default: 20). */
710
+ maxTotal?: number;
711
+ }
712
+ interface PermissionConfig {
713
+ mode?: PermissionMode;
714
+ rules?: PermissionRule[];
715
+ handler?: PermissionHandler;
716
+ workingDirectories?: string[];
717
+ /** Called when a permission update is applied (for host-side persistence). */
718
+ onPermissionUpdate?: (update: PermissionUpdate) => void;
719
+ /** Configuration for auto mode classifier. */
720
+ autoMode?: AutoModeConfig;
721
+ /** Configuration for denial tracking limits. */
722
+ denialTracking?: DenialTrackingConfig;
723
+ }
724
+ interface PermissionContext {
725
+ mode: PermissionMode;
726
+ rules: PermissionRule[];
727
+ workingDirectories: string[];
728
+ /**
729
+ * Ordered list of dot-directory names (e.g. `['.noumen', '.claude']`)
730
+ * whose contents are treated as dangerous paths for write/edit tools.
731
+ * When unset, defaults to the conservative built-in list
732
+ * (`['.noumen', '.claude']`) so non-agent callers stay protected.
733
+ */
734
+ dotDirNames?: string[];
735
+ }
736
+
737
+ export { type ImageContent as $, type AIProvider as A, type MemoryEntry as B, type CheckpointConfig as C, type DiffStats as D, type Entry as E, type FileCheckpointState as F, type AssistantMessage as G, type ToolResultMessage as H, type ToolResultOverflowEntry as I, type JsonSchemaOutputFormat as J, type AiTitleEntry as K, type ChatStreamChoice as L, type ModelPricing as M, type ChatStreamDelta as N, type OutputFormat as O, type PermissionResponse as P, ChatStreamError as Q, type RunOptions as R, type StreamEvent as S, type ToolDefinition as T, type UUID as U, type CompactBoundaryEntry as V, type ContentReplacementEntry as W, type CustomTitleEntry as X, type DenialTrackingConfig as Y, type FileCheckpointBackup as Z, type FileCheckpointEntry as _, type FileCheckpointSnapshot as a, type ImageUrlContent as a0, type JsonObjectOutputFormat as a1, type MemoryType as a2, type MessageEntry as a3, type MetadataEntry as a4, type PermissionAllowResult as a5, type PermissionAskResult as a6, type PermissionDenyResult as a7, type PermissionPassthroughResult as a8, type PermissionRequest as a9, type PermissionRuleSource as aa, RULE_SOURCE_PRECEDENCE as ab, type SerializedMessage as ac, type SnipBoundaryEntry as ad, type SummaryEntry as ae, type SystemMessage as af, type TextContent as ag, type ToolParameterProperty as ah, type UserMessage as ai, createCheckpointState as aj, type PermissionMode as b, type PermissionResult as c, type ContentPart as d, type ChatMessage as e, type ContentReplacementRecord as f, type SessionInfo as g, type UsageRecord as h, type CostSummary as i, type ModelUsageSummary as j, type ChatCompletionUsage as k, type PermissionHandler as l, type PermissionConfig as m, type ThinkingConfig as n, type MemoryConfig as o, type ToolResult as p, type ChatParams as q, type ChatStreamChunk as r, type ToolCallContent as s, type PermissionContext as t, type PermissionBehavior as u, type PermissionRule as v, type AutoModeConfig as w, type PermissionDecision as x, type PermissionUpdate as y, type MemoryProvider as z };
@@ -0,0 +1,59 @@
1
+ import { A as AgentOptions, a as Agent } from './agent-D0gl-qYi.js';
2
+ import { S as Sandbox } from './sandbox-DAqQo0Tj.js';
3
+ import './types-DLZNyF5t.js';
4
+ import './types-BX4ALqoN.js';
5
+ import './computer-DzMR92tK.js';
6
+ import './types-2kTLUCnD.js';
7
+ import '@modelcontextprotocol/sdk/client/index.js';
8
+ import '@modelcontextprotocol/sdk/client/auth.js';
9
+ import '@modelcontextprotocol/sdk/shared/auth.js';
10
+
11
+ interface UnsandboxedLocalOptions {
12
+ /** Working directory for both file resolution and command execution. */
13
+ cwd?: string;
14
+ /** Default timeout (ms) for shell commands. */
15
+ defaultTimeout?: number;
16
+ }
17
+ /**
18
+ * Create a `Sandbox` backed by the host filesystem and shell with **no
19
+ * OS-level isolation**. The agent can access anything the host process can.
20
+ *
21
+ * Use this for development or fully-trusted environments where sandboxing
22
+ * overhead is unwanted. For production use, prefer `LocalSandbox()` (which
23
+ * wraps commands with `@anthropic-ai/sandbox-runtime`).
24
+ */
25
+ declare function UnsandboxedLocal(opts?: UnsandboxedLocalOptions): Sandbox;
26
+
27
+ /**
28
+ * Options for {@link UnsandboxedAgent} — the full `AgentOptions` surface
29
+ * minus `sandbox`, plus an optional `unsandboxed` block for tuning the
30
+ * default-created {@link UnsandboxedLocal} (timeouts, etc.).
31
+ */
32
+ interface UnsandboxedAgentOptions extends Omit<AgentOptions, "sandbox"> {
33
+ /**
34
+ * Forwarded to {@link UnsandboxedLocal}. If `cwd` is omitted here it
35
+ * defaults to `opts.cwd` / `opts.options.cwd` / `process.cwd()`.
36
+ */
37
+ unsandboxed?: Omit<UnsandboxedLocalOptions, "cwd"> & {
38
+ cwd?: string;
39
+ };
40
+ }
41
+ /**
42
+ * Convenience factory that constructs an {@link Agent} backed by an
43
+ * {@link UnsandboxedLocal} sandbox. Equivalent to:
44
+ *
45
+ * ```ts
46
+ * new Agent({ ...opts, sandbox: UnsandboxedLocal({ cwd }) })
47
+ * ```
48
+ *
49
+ * Lives on the `noumen/unsandboxed` subpath rather than the root barrel
50
+ * so that `import { Agent } from "noumen"` never transitively pulls
51
+ * `node:child_process` into the module graph. Callers who want raw host
52
+ * access opt into that cost at the import line.
53
+ *
54
+ * For production, prefer {@link "./local".LocalAgent} (OS-level sandboxing)
55
+ * or a remote sandbox subpath.
56
+ */
57
+ declare function UnsandboxedAgent(opts: UnsandboxedAgentOptions): Agent;
58
+
59
+ export { UnsandboxedAgent, type UnsandboxedAgentOptions, UnsandboxedLocal, type UnsandboxedLocalOptions };
@@ -0,0 +1,32 @@
1
+ import {
2
+ UnsandboxedLocal
3
+ } from "./chunk-BC5BLWBC.js";
4
+ import "./chunk-XQTNXRE7.js";
5
+ import {
6
+ Agent
7
+ } from "./chunk-5HY4IYNT.js";
8
+ import "./chunk-42PHHZUA.js";
9
+ import "./chunk-OPFFLQZL.js";
10
+ import "./chunk-3HEYCV26.js";
11
+ import "./chunk-CX4BL6PC.js";
12
+ import "./chunk-3SK5GCI6.js";
13
+ import "./chunk-HQISH4D7.js";
14
+ import "./chunk-JACGEMTF.js";
15
+
16
+ // src/unsandboxed.ts
17
+ function UnsandboxedAgent(opts) {
18
+ const cwd = opts.unsandboxed?.cwd ?? opts.cwd ?? opts.options?.cwd ?? process.cwd();
19
+ const { unsandboxed, ...rest } = opts;
20
+ return new Agent({
21
+ ...rest,
22
+ sandbox: UnsandboxedLocal({
23
+ cwd,
24
+ defaultTimeout: unsandboxed?.defaultTimeout
25
+ })
26
+ });
27
+ }
28
+ export {
29
+ UnsandboxedAgent,
30
+ UnsandboxedLocal
31
+ };
32
+ //# sourceMappingURL=unsandboxed.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/unsandboxed.ts"],"sourcesContent":["// Unsandboxed local binding — raw host access, no isolation.\n//\n// Importing this subpath is the explicit opt-in to a sandbox that gives the\n// agent everything the host process has. The root barrel (`noumen`) does not\n// re-export this module, so reaching for unsandboxed execution always shows\n// up as a dedicated import line.\n//\n// import { UnsandboxedLocal } from \"noumen/unsandboxed\";\n\nimport { Agent, type AgentOptions } from \"./agent.js\";\nimport { UnsandboxedLocal, type UnsandboxedLocalOptions } from \"./virtual/unsandboxed.js\";\n\nexport {\n UnsandboxedLocal,\n type UnsandboxedLocalOptions,\n} from \"./virtual/unsandboxed.js\";\n\n/**\n * Options for {@link UnsandboxedAgent} — the full `AgentOptions` surface\n * minus `sandbox`, plus an optional `unsandboxed` block for tuning the\n * default-created {@link UnsandboxedLocal} (timeouts, etc.).\n */\nexport interface UnsandboxedAgentOptions extends Omit<AgentOptions, \"sandbox\"> {\n /**\n * Forwarded to {@link UnsandboxedLocal}. If `cwd` is omitted here it\n * defaults to `opts.cwd` / `opts.options.cwd` / `process.cwd()`.\n */\n unsandboxed?: Omit<UnsandboxedLocalOptions, \"cwd\"> & { cwd?: string };\n}\n\n/**\n * Convenience factory that constructs an {@link Agent} backed by an\n * {@link UnsandboxedLocal} sandbox. Equivalent to:\n *\n * ```ts\n * new Agent({ ...opts, sandbox: UnsandboxedLocal({ cwd }) })\n * ```\n *\n * Lives on the `noumen/unsandboxed` subpath rather than the root barrel\n * so that `import { Agent } from \"noumen\"` never transitively pulls\n * `node:child_process` into the module graph. Callers who want raw host\n * access opt into that cost at the import line.\n *\n * For production, prefer {@link \"./local\".LocalAgent} (OS-level sandboxing)\n * or a remote sandbox subpath.\n */\nexport function UnsandboxedAgent(opts: UnsandboxedAgentOptions): Agent {\n const cwd = opts.unsandboxed?.cwd ?? opts.cwd ?? opts.options?.cwd ?? process.cwd();\n const { unsandboxed, ...rest } = opts;\n return new Agent({\n ...rest,\n sandbox: UnsandboxedLocal({\n cwd,\n defaultTimeout: unsandboxed?.defaultTimeout,\n }),\n });\n}\n"],"mappings":";;;;;;;;;;;;;;;;AA8CO,SAAS,iBAAiB,MAAsC;AACrE,QAAM,MAAM,KAAK,aAAa,OAAO,KAAK,OAAO,KAAK,SAAS,OAAO,QAAQ,IAAI;AAClF,QAAM,EAAE,aAAa,GAAG,KAAK,IAAI;AACjC,SAAO,IAAI,MAAM;AAAA,IACf,GAAG;AAAA,IACH,SAAS,iBAAiB;AAAA,MACxB;AAAA,MACA,gBAAgB,aAAa;AAAA,IAC/B,CAAC;AAAA,EACH,CAAC;AACH;","names":[]}
@@ -1,8 +1,7 @@
1
1
  import {
2
2
  generateUUID
3
3
  } from "./chunk-3HEYCV26.js";
4
- import "./chunk-DGUM43GV.js";
5
4
  export {
6
5
  generateUUID
7
6
  };
8
- //# sourceMappingURL=uuid-RVN2T26F.js.map
7
+ //# sourceMappingURL=uuid-CVTNAPEB.js.map
@@ -3,10 +3,9 @@ import {
3
3
  registerZodToJsonSchema,
4
4
  zodToJsonSchema
5
5
  } from "./chunk-3SK5GCI6.js";
6
- import "./chunk-DGUM43GV.js";
7
6
  export {
8
7
  formatZodValidationError,
9
8
  registerZodToJsonSchema,
10
9
  zodToJsonSchema
11
10
  };
12
- //# sourceMappingURL=zod-7YXKWYMC.js.map
11
+ //# sourceMappingURL=zod-VKURGPRT.js.map