{"version":3,"file":"ai-DeFa8yPk.mjs","names":["stdoutController!: ReadableStreamDefaultController<Uint8Array>","stderrController!: ReadableStreamDefaultController<Uint8Array>"],"sources":["../src/ai/index.ts"],"sourcesContent":["import { jsonSchema, tool } from \"ai\";\nimport type { Experimental_SandboxProcess, Experimental_SandboxSession, Tool, ToolSet } from \"ai\";\nimport { isSandboxError, normalizeError, SandboxError } from \"../core/errors\";\nimport type { Sandbox, SandboxProcess } from \"../core/types\";\n\nexport interface AISandboxSessionOptions {\n  description?: string;\n}\n\nexport type SandboxToolApproval = \"mutations\" | \"always\" | \"never\";\n\nexport type SandboxToolApprovalConfiguration = Readonly<{\n  bash: \"user-approval\" | \"not-applicable\";\n  read_file: \"user-approval\" | \"not-applicable\";\n  write_file: \"user-approval\" | \"not-applicable\";\n}>;\n\n/**\n * Adapt a sandbox-sdk sandbox to AI SDK 7's experimental sandbox contract.\n * The caller continues to own the original sandbox and must stop it.\n */\nexport function toAISandboxSession(\n  sandbox: Sandbox,\n  options: AISandboxSessionOptions = {},\n): Experimental_SandboxSession {\n  const read = async (path: string, abortSignal?: AbortSignal): Promise<Uint8Array | null> => {\n    throwIfAborted(abortSignal);\n    try {\n      const bytes = await sandbox.files.read(path);\n      throwIfAborted(abortSignal);\n      return bytes;\n    } catch (error) {\n      if (isSandboxError(error) && error.code === \"not_found\") return null;\n      throw normalizeError(sandbox.provider, \"ai.readFile\", error);\n    }\n  };\n\n  return {\n    description:\n      options.description ??\n      `${sandbox.provider} sandbox ${sandbox.id}; default working directory: ${sandbox.cwd}`,\n    async readFile({ path, abortSignal }) {\n      const bytes = await read(path, abortSignal);\n      return bytes === null ? null : bytesToStream(bytes);\n    },\n    readBinaryFile: ({ path, abortSignal }) => read(path, abortSignal),\n    async readTextFile({ path, encoding = \"utf-8\", startLine, endLine, abortSignal }) {\n      const bytes = await read(path, abortSignal);\n      if (bytes === null) return null;\n      const content = decode(bytes, encoding);\n      if (startLine === undefined && endLine === undefined) return content;\n      validateLineRange(startLine, endLine);\n      return content\n        .split(\"\\n\")\n        .slice((startLine ?? 1) - 1, endLine)\n        .join(\"\\n\");\n    },\n    async writeFile({ path, content, abortSignal }) {\n      throwIfAborted(abortSignal);\n      await sandbox.files.write(path, abortableStream(content, abortSignal));\n      throwIfAborted(abortSignal);\n    },\n    async writeBinaryFile({ path, content, abortSignal }) {\n      throwIfAborted(abortSignal);\n      await sandbox.files.write(path, content);\n      throwIfAborted(abortSignal);\n    },\n    async writeTextFile({ path, content, encoding = \"utf-8\", abortSignal }) {\n      throwIfAborted(abortSignal);\n      await sandbox.files.write(path, encode(content, encoding));\n      throwIfAborted(abortSignal);\n    },\n    async run({ command, workingDirectory, env, abortSignal }) {\n      const result = await sandbox.run(command, {\n        cwd: workingDirectory,\n        env,\n        signal: abortSignal,\n      });\n      return { exitCode: result.exitCode, stdout: result.stdout, stderr: result.stderr };\n    },\n    async spawn({ command, workingDirectory, env, abortSignal }) {\n      const process = await sandbox.processes.start(command, {\n        cwd: workingDirectory,\n        env,\n        signal: abortSignal,\n      });\n      return toAIProcess(process, abortSignal);\n    },\n  };\n}\n\ntype BashInput = { command: string; workingDirectory?: string; env?: Record<string, string> };\ntype ReadFileInput = { path: string; encoding?: string; startLine?: number; endLine?: number };\ntype WriteFileInput = { path: string; content: string; encoding?: string };\n\nexport type SandboxTools = ToolSet & {\n  bash: Tool<BashInput, { exitCode: number; stdout: string; stderr: string }>;\n  read_file: Tool<ReadFileInput, { content: string | null }>;\n  write_file: Tool<WriteFileInput, { written: true }>;\n};\n\n/** Ready-made AI SDK tools that execute only through `experimental_sandbox`. */\nexport function createSandboxTools(): SandboxTools {\n  return {\n    bash: tool({\n      description: \"Run a shell command in the sandbox.\",\n      inputSchema: jsonSchema<BashInput>({\n        type: \"object\",\n        properties: {\n          command: { type: \"string\" },\n          workingDirectory: { type: \"string\" },\n          env: { type: \"object\", additionalProperties: { type: \"string\" } },\n        },\n        required: [\"command\"],\n        additionalProperties: false,\n      }),\n      async execute(input, context) {\n        const sandbox = requireSandbox(context.experimental_sandbox);\n        return sandbox.run({\n          command: input.command,\n          workingDirectory: input.workingDirectory,\n          env: input.env,\n          abortSignal: context.abortSignal,\n        });\n      },\n    }),\n    read_file: tool({\n      description: \"Read a text file from the sandbox. Missing files return null.\",\n      inputSchema: jsonSchema<ReadFileInput>({\n        type: \"object\",\n        properties: {\n          path: { type: \"string\" },\n          encoding: { type: \"string\" },\n          startLine: { type: \"integer\", minimum: 1 },\n          endLine: { type: \"integer\", minimum: 1 },\n        },\n        required: [\"path\"],\n        additionalProperties: false,\n      }),\n      async execute(input, context) {\n        const sandbox = requireSandbox(context.experimental_sandbox);\n        return {\n          content: await sandbox.readTextFile({\n            ...input,\n            abortSignal: context.abortSignal,\n          }),\n        };\n      },\n    }),\n    write_file: tool({\n      description: \"Write a text file in the sandbox, creating parent directories.\",\n      inputSchema: jsonSchema<WriteFileInput>({\n        type: \"object\",\n        properties: {\n          path: { type: \"string\" },\n          content: { type: \"string\" },\n          encoding: { type: \"string\" },\n        },\n        required: [\"path\", \"content\"],\n        additionalProperties: false,\n      }),\n      async execute(input, context) {\n        const sandbox = requireSandbox(context.experimental_sandbox);\n        await sandbox.writeTextFile({ ...input, abortSignal: context.abortSignal });\n        return { written: true as const };\n      },\n    }),\n  };\n}\n\n/** Create the AI SDK 7 `toolApproval` policy for the ready-made sandbox tools. */\nexport function createSandboxToolApproval(\n  approval: SandboxToolApproval = \"mutations\",\n): SandboxToolApprovalConfiguration {\n  const status = (mutation: boolean) =>\n    approval === \"always\" || (approval === \"mutations\" && mutation)\n      ? (\"user-approval\" as const)\n      : (\"not-applicable\" as const);\n\n  return {\n    bash: status(true),\n    read_file: status(false),\n    write_file: status(true),\n  };\n}\n\nfunction requireSandbox(\n  value: Experimental_SandboxSession | undefined,\n): Experimental_SandboxSession {\n  if (!value) {\n    throw new SandboxError({\n      code: \"invalid_input\",\n      provider: \"ai\",\n      operation: \"tool.execute\",\n      message: \"experimental_sandbox is required to execute sandbox tools\",\n    });\n  }\n  return value;\n}\n\nfunction toAIProcess(\n  process: SandboxProcess,\n  abortSignal?: AbortSignal,\n): Experimental_SandboxProcess {\n  let stdoutController!: ReadableStreamDefaultController<Uint8Array>;\n  let stderrController!: ReadableStreamDefaultController<Uint8Array>;\n  const stdout = new ReadableStream<Uint8Array>({\n    start: (controller) => (stdoutController = controller),\n  });\n  const stderr = new ReadableStream<Uint8Array>({\n    start: (controller) => (stderrController = controller),\n  });\n  const pump = (async () => {\n    try {\n      for await (const event of process.output()) {\n        const bytes =\n          typeof event.data === \"string\" ? new TextEncoder().encode(event.data) : event.data;\n        (event.stream === \"stdout\" ? stdoutController : stderrController).enqueue(bytes);\n      }\n      stdoutController.close();\n      stderrController.close();\n    } catch (error) {\n      stdoutController.error(error);\n      stderrController.error(error);\n    }\n  })();\n  const abort = () => void process.kill();\n  abortSignal?.addEventListener(\"abort\", abort, { once: true });\n  return {\n    pid: Number.isFinite(Number(process.id)) ? Number(process.id) : undefined,\n    stdout,\n    stderr,\n    async wait() {\n      try {\n        const result = await process.wait();\n        await pump;\n        if (abortSignal?.aborted) throw abortSignal.reason;\n        return result;\n      } finally {\n        abortSignal?.removeEventListener(\"abort\", abort);\n      }\n    },\n    kill: () => process.kill(),\n  };\n}\n\nfunction bytesToStream(bytes: Uint8Array): ReadableStream<Uint8Array> {\n  return new ReadableStream({\n    start(controller) {\n      controller.enqueue(bytes);\n      controller.close();\n    },\n  });\n}\n\nfunction abortableStream(\n  stream: ReadableStream<Uint8Array>,\n  signal?: AbortSignal,\n): ReadableStream<Uint8Array> {\n  if (!signal) return stream;\n  return stream.pipeThrough(\n    new TransformStream({\n      transform(chunk, controller) {\n        throwIfAborted(signal);\n        controller.enqueue(chunk);\n      },\n    }),\n    { signal },\n  );\n}\n\nfunction validateLineRange(startLine?: number, endLine?: number): void {\n  if (\n    (startLine !== undefined && (!Number.isInteger(startLine) || startLine < 1)) ||\n    (endLine !== undefined && (!Number.isInteger(endLine) || endLine < 1)) ||\n    (startLine !== undefined && endLine !== undefined && endLine < startLine)\n  ) {\n    throw new SandboxError({\n      code: \"invalid_input\",\n      provider: \"ai\",\n      operation: \"readTextFile\",\n      message: \"Line ranges must be positive, 1-based, inclusive, and ordered\",\n    });\n  }\n}\n\nfunction decode(bytes: Uint8Array, encoding: string): string {\n  try {\n    return encoding.toLowerCase() === \"utf-8\" || encoding.toLowerCase() === \"utf8\"\n      ? new TextDecoder(\"utf-8\", { fatal: true }).decode(bytes)\n      : Buffer.from(bytes).toString(encoding as BufferEncoding);\n  } catch (error) {\n    throw normalizeError(\"ai\", \"files.decode\", error, \"invalid_input\");\n  }\n}\n\nfunction encode(value: string, encoding: string): Uint8Array {\n  try {\n    return encoding.toLowerCase() === \"utf-8\" || encoding.toLowerCase() === \"utf8\"\n      ? new TextEncoder().encode(value)\n      : new Uint8Array(Buffer.from(value, encoding as BufferEncoding));\n  } catch (error) {\n    throw normalizeError(\"ai\", \"files.encode\", error, \"invalid_input\");\n  }\n}\n\nfunction throwIfAborted(signal?: AbortSignal): void {\n  if (signal?.aborted)\n    throw signal.reason ?? new DOMException(\"The operation was aborted\", \"AbortError\");\n}\n"],"mappings":"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"}