@computesdk/modal 1.4.5 → 1.4.7

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.
package/dist/index.js CHANGED
@@ -33,7 +33,7 @@ function detectRuntime(code) {
33
33
  if (code.includes("print(") || code.includes("import ") || code.includes("def ") || code.includes("sys.") || code.includes("json.") || code.includes('f"') || code.includes("f'") || code.includes("raise ")) {
34
34
  return "python";
35
35
  }
36
- return "python";
36
+ return "node";
37
37
  }
38
38
  var modal = (0, import_computesdk.createProvider)({
39
39
  name: "modal",
@@ -57,7 +57,7 @@ var modal = (0, import_computesdk.createProvider)({
57
57
  sandboxId = options.sandboxId;
58
58
  } else {
59
59
  const app = await import_modal.App.lookup("computesdk-modal", { createIfMissing: true });
60
- const image = await app.imageFromRegistry("python:3.13-slim");
60
+ const image = await app.imageFromRegistry("node:20-alpine");
61
61
  sandbox = await app.createSandbox(image);
62
62
  sandboxId = sandbox.sandboxId;
63
63
  }
@@ -128,13 +128,13 @@ var modal = (0, import_computesdk.createProvider)({
128
128
  let command;
129
129
  let shouldCleanupSandbox = false;
130
130
  if (detectedRuntime === "node") {
131
- const app = await import_modal.App.lookup("computesdk-modal", { createIfMissing: true });
132
- const nodeImage = await app.imageFromRegistry("node:20-alpine");
133
- executionSandbox = await app.createSandbox(nodeImage);
134
131
  command = ["node", "-e", code];
135
- shouldCleanupSandbox = true;
136
132
  } else {
133
+ const app = await import_modal.App.lookup("computesdk-modal", { createIfMissing: true });
134
+ const pythonImage = await app.imageFromRegistry("python:3.13-slim");
135
+ executionSandbox = await app.createSandbox(pythonImage);
137
136
  command = ["python3", "-c", code];
137
+ shouldCleanupSandbox = true;
138
138
  }
139
139
  const process2 = await executionSandbox.exec(command, {
140
140
  stdout: "pipe",
@@ -222,8 +222,8 @@ var modal = (0, import_computesdk.createProvider)({
222
222
  return {
223
223
  id: modalSandbox.sandboxId,
224
224
  provider: "modal",
225
- runtime: "python",
226
- // Modal default
225
+ runtime: "node",
226
+ // Modal default (now using Node.js)
227
227
  status,
228
228
  createdAt: /* @__PURE__ */ new Date(),
229
229
  timeout: 3e5,
@@ -335,7 +335,7 @@ var modal = (0, import_computesdk.createProvider)({
335
335
  },
336
336
  readdir: async (modalSandbox, path) => {
337
337
  try {
338
- const process2 = await modalSandbox.sandbox.exec(["ls", "-la", "--time-style=iso", path], {
338
+ const process2 = await modalSandbox.sandbox.exec(["ls", "-la", path], {
339
339
  stdout: "pipe",
340
340
  stderr: "pipe"
341
341
  });
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * Modal Provider - Factory-based Implementation\n * \n * Full-featured provider with serverless sandbox execution using the factory pattern.\n * Leverages Modal's JavaScript SDK for real sandbox management.\n * \n * Note: Modal's JavaScript SDK is in alpha. This implementation provides a working\n * foundation but may need updates as the Modal API evolves.\n */\n\nimport { createProvider, createBackgroundCommand } from 'computesdk';\nimport type { \n ExecutionResult, \n SandboxInfo, \n Runtime,\n CreateSandboxOptions,\n FileEntry,\n RunCommandOptions\n} from 'computesdk';\n\n// Import Modal SDK\nimport { App, Sandbox, initializeClient } from 'modal';\n\n/**\n * Modal-specific configuration options\n */\nexport interface ModalConfig {\n /** Modal API token ID - if not provided, will fallback to MODAL_TOKEN_ID environment variable */\n tokenId?: string;\n /** Modal API token secret - if not provided, will fallback to MODAL_TOKEN_SECRET environment variable */\n tokenSecret?: string;\n /** Default runtime environment */\n runtime?: Runtime;\n /** Execution timeout in milliseconds */\n timeout?: number;\n /** Modal environment (sandbox or main) */\n environment?: string;\n}\n\n/**\n * Modal sandbox interface - wraps Modal's Sandbox class\n */\ninterface ModalSandbox {\n sandbox: any; // Modal Sandbox instance (using any due to alpha SDK)\n sandboxId: string;\n}\n\n/**\n * Detect runtime from code content\n */\nfunction detectRuntime(code: string): Runtime {\n // Strong Node.js indicators\n if (code.includes('console.log') || \n code.includes('process.') ||\n code.includes('require(') ||\n code.includes('module.exports') ||\n code.includes('__dirname') ||\n code.includes('__filename') ||\n code.includes('throw new Error') || // JavaScript error throwing\n code.includes('new Error(')) {\n return 'node';\n }\n\n // Strong Python indicators \n if (code.includes('print(') || \n code.includes('import ') ||\n code.includes('def ') ||\n code.includes('sys.') ||\n code.includes('json.') ||\n code.includes('f\"') ||\n code.includes(\"f'\") ||\n code.includes('raise ')) {\n return 'python';\n }\n\n // Default to Python for Modal\n return 'python';\n}\n\n/**\n * Create a Modal provider instance using the factory pattern\n */\nexport const modal = createProvider<ModalSandbox, ModalConfig>({\n name: 'modal',\n methods: {\n sandbox: {\n // Collection operations (map to compute.sandbox.*)\n create: async (config: ModalConfig, options?: CreateSandboxOptions) => {\n // Validate API credentials\n const tokenId = config.tokenId || (typeof process !== 'undefined' && process.env?.MODAL_TOKEN_ID) || '';\n const tokenSecret = config.tokenSecret || (typeof process !== 'undefined' && process.env?.MODAL_TOKEN_SECRET) || '';\n\n if (!tokenId || !tokenSecret) {\n throw new Error(\n `Missing Modal API credentials. Provide 'tokenId' and 'tokenSecret' in config or set MODAL_TOKEN_ID and MODAL_TOKEN_SECRET environment variables. Get your credentials from https://modal.com/`\n );\n }\n\n try {\n // Initialize Modal client with credentials\n initializeClient({ tokenId, tokenSecret });\n\n let sandbox: any;\n let sandboxId: string;\n\n if (options?.sandboxId) {\n // Reconnect to existing Modal sandbox\n sandbox = await Sandbox.fromId(options.sandboxId);\n sandboxId = options.sandboxId;\n } else {\n // Create new Modal sandbox using working pattern from debug\n const app = await App.lookup('computesdk-modal', { createIfMissing: true });\n const image = await app.imageFromRegistry('python:3.13-slim');\n sandbox = await app.createSandbox(image);\n sandboxId = sandbox.sandboxId;\n }\n\n const modalSandbox: ModalSandbox = {\n sandbox,\n sandboxId\n };\n\n return {\n sandbox: modalSandbox,\n sandboxId\n };\n } catch (error) {\n if (error instanceof Error) {\n if (error.message.includes('unauthorized') || error.message.includes('credentials')) {\n throw new Error(\n `Modal authentication failed. Please check your MODAL_TOKEN_ID and MODAL_TOKEN_SECRET environment variables. Get your credentials from https://modal.com/`\n );\n }\n if (error.message.includes('quota') || error.message.includes('limit')) {\n throw new Error(\n `Modal quota exceeded. Please check your usage at https://modal.com/`\n );\n }\n }\n throw new Error(\n `Failed to create Modal sandbox: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n },\n\n getById: async (config: ModalConfig, sandboxId: string) => {\n const tokenId = config.tokenId || process.env.MODAL_TOKEN_ID!;\n const tokenSecret = config.tokenSecret || process.env.MODAL_TOKEN_SECRET!;\n\n try {\n initializeClient({ tokenId, tokenSecret });\n const sandbox = await Sandbox.fromId(sandboxId);\n\n const modalSandbox: ModalSandbox = {\n sandbox,\n sandboxId\n };\n\n return {\n sandbox: modalSandbox,\n sandboxId\n };\n } catch (error) {\n // Sandbox doesn't exist or can't be accessed\n return null;\n }\n },\n\n list: async (_config: ModalConfig) => {\n throw new Error(\n `Modal provider does not support listing sandboxes. Modal sandboxes are managed individually through the Modal console. Use getById to reconnect to specific sandboxes by ID.`\n );\n },\n\n destroy: async (_config: ModalConfig, sandboxId: string) => {\n try {\n const sandbox = await Sandbox.fromId(sandboxId);\n if (sandbox && typeof sandbox.terminate === 'function') {\n await sandbox.terminate();\n }\n } catch (error) {\n // Sandbox might already be terminated or doesn't exist\n // This is acceptable for destroy operations\n }\n },\n\n // Instance operations (map to individual Sandbox methods)\n runCode: async (modalSandbox: ModalSandbox, code: string, runtime?: Runtime): Promise<ExecutionResult> => {\n const startTime = Date.now();\n\n try {\n // Auto-detect runtime from code if not specified\n const detectedRuntime = runtime || detectRuntime(code);\n \n // Create appropriate sandbox and command for the runtime\n let executionSandbox = modalSandbox.sandbox;\n let command: string[];\n let shouldCleanupSandbox = false;\n \n if (detectedRuntime === 'node') {\n // For Node.js execution, create a Node.js sandbox dynamically\n const app = await App.lookup('computesdk-modal', { createIfMissing: true });\n const nodeImage = await app.imageFromRegistry('node:20-alpine');\n executionSandbox = await app.createSandbox(nodeImage);\n command = ['node', '-e', code];\n shouldCleanupSandbox = true; // Clean up temporary Node.js sandbox\n } else {\n // Use existing Python sandbox for Python code\n command = ['python3', '-c', code];\n }\n\n const process = await executionSandbox.exec(command, {\n stdout: 'pipe',\n stderr: 'pipe'\n });\n\n // Use working stream reading pattern from debug\n const [stdout, stderr] = await Promise.all([\n process.stdout.readText(),\n process.stderr.readText()\n ]);\n\n const exitCode = await process.wait();\n \n // Clean up temporary Node.js sandbox if created\n if (shouldCleanupSandbox && executionSandbox !== modalSandbox.sandbox) {\n try {\n await executionSandbox.terminate();\n } catch (e) {\n // Ignore cleanup errors\n }\n }\n\n // Check for syntax errors in stderr\n if (exitCode !== 0 && stderr && (\n stderr.includes('SyntaxError') || \n stderr.includes('invalid syntax')\n )) {\n throw new Error(`Syntax error: ${stderr.trim()}`);\n }\n\n return {\n stdout: stdout || '',\n stderr: stderr || '',\n exitCode: exitCode || 0,\n executionTime: Date.now() - startTime,\n sandboxId: modalSandbox.sandboxId,\n provider: 'modal'\n };\n } catch (error) {\n // Handle syntax errors and runtime errors\n if (error instanceof Error && error.message.includes('Syntax error')) {\n throw error; // Re-throw syntax errors\n }\n \n throw new Error(\n `Modal execution failed: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n },\n\n runCommand: async (modalSandbox: ModalSandbox, command: string, args: string[] = [], options?: RunCommandOptions): Promise<ExecutionResult> => {\n const startTime = Date.now();\n\n try {\n // Handle background command execution\n const { command: finalCommand, args: finalArgs, isBackground } = createBackgroundCommand(command, args, options);\n \n // Execute command using Modal's exec method with working pattern\n const process = await modalSandbox.sandbox.exec([finalCommand, ...finalArgs], {\n stdout: 'pipe',\n stderr: 'pipe'\n });\n\n // Use working stream reading pattern from debug\n const [stdout, stderr] = await Promise.all([\n process.stdout.readText(),\n process.stderr.readText()\n ]);\n\n const exitCode = await process.wait();\n\n return {\n stdout: stdout || '',\n stderr: stderr || '',\n exitCode: exitCode || 0,\n executionTime: Date.now() - startTime,\n sandboxId: modalSandbox.sandboxId,\n provider: 'modal',\n isBackground,\n // For background commands, we can't get a real PID, but we can indicate it's running\n ...(isBackground && { pid: -1 })\n };\n } catch (error) {\n // For command failures, return error info instead of throwing\n return {\n stdout: '',\n stderr: error instanceof Error ? error.message : String(error),\n exitCode: 127, // Command not found exit code\n executionTime: Date.now() - startTime,\n sandboxId: modalSandbox.sandboxId,\n provider: 'modal',\n isBackground: false // Error case, command didn't run as background\n };\n }\n },\n\n getInfo: async (modalSandbox: ModalSandbox): Promise<SandboxInfo> => {\n // Get actual sandbox status using Modal's poll method\n let status: 'running' | 'stopped' | 'error' = 'running';\n try {\n const pollResult = await modalSandbox.sandbox.poll();\n if (pollResult !== null) {\n // Sandbox has finished\n status = pollResult === 0 ? 'stopped' : 'error';\n }\n } catch (error) {\n // If polling fails, assume running\n status = 'running';\n }\n\n return {\n id: modalSandbox.sandboxId,\n provider: 'modal',\n runtime: 'python', // Modal default\n status,\n createdAt: new Date(),\n timeout: 300000,\n metadata: {\n modalSandboxId: modalSandbox.sandboxId,\n realModalImplementation: true\n }\n };\n },\n\n getUrl: async (modalSandbox: ModalSandbox, options: { port: number; protocol?: string }): Promise<string> => {\n try {\n // Use Modal's built-in tunnels method to get tunnel information\n const tunnels = await modalSandbox.sandbox.tunnels();\n const tunnel = tunnels[options.port];\n \n if (!tunnel) {\n throw new Error(`No tunnel found for port ${options.port}. Available ports: ${Object.keys(tunnels).join(', ')}`);\n }\n \n let url = tunnel.url;\n \n // If a specific protocol is requested, replace the URL's protocol\n if (options.protocol) {\n const urlObj = new URL(url);\n urlObj.protocol = options.protocol + ':';\n url = urlObj.toString();\n }\n \n return url;\n } catch (error) {\n throw new Error(\n `Failed to get Modal tunnel URL for port ${options.port}: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n },\n\n // Optional filesystem methods - Modal supports filesystem operations\n filesystem: {\n readFile: async (modalSandbox: ModalSandbox, path: string): Promise<string> => {\n try {\n // Use Modal's file open API to read files\n const file = await modalSandbox.sandbox.open(path);\n \n // Read the entire file content\n let content = '';\n if (file && typeof file.read === 'function') {\n const data = await file.read();\n content = typeof data === 'string' ? data : new TextDecoder().decode(data);\n }\n \n // Close the file if it has a close method\n if (file && typeof file.close === 'function') {\n await file.close();\n }\n \n return content;\n } catch (error) {\n // Fallback to using cat command with working stream pattern\n try {\n const process = await modalSandbox.sandbox.exec(['cat', path], {\n stdout: 'pipe',\n stderr: 'pipe'\n });\n\n const [content, stderr] = await Promise.all([\n process.stdout.readText(),\n process.stderr.readText()\n ]);\n\n const exitCode = await process.wait();\n\n if (exitCode !== 0) {\n throw new Error(`cat failed: ${stderr}`);\n }\n\n return content.trim(); // Remove extra newlines\n } catch (fallbackError) {\n throw new Error(`Failed to read file ${path}: ${error instanceof Error ? error.message : String(error)}`);\n }\n }\n },\n\n writeFile: async (modalSandbox: ModalSandbox, path: string, content: string): Promise<void> => {\n try {\n // Use Modal's file open API to write files\n const file = await modalSandbox.sandbox.open(path);\n \n // Write content to the file\n if (file && typeof file.write === 'function') {\n await file.write(content);\n }\n \n // Close the file if it has a close method\n if (file && typeof file.close === 'function') {\n await file.close();\n }\n } catch (error) {\n // Fallback to using shell command with proper escaping\n try {\n const process = await modalSandbox.sandbox.exec(['sh', '-c', `printf '%s' \"${content.replace(/\"/g, '\\\\\"')}\" > \"${path}\"`], {\n stdout: 'pipe',\n stderr: 'pipe'\n });\n\n const [, stderr] = await Promise.all([\n process.stdout.readText(),\n process.stderr.readText()\n ]);\n\n const exitCode = await process.wait();\n\n if (exitCode !== 0) {\n throw new Error(`write failed: ${stderr}`);\n }\n } catch (fallbackError) {\n throw new Error(`Failed to write file ${path}: ${error instanceof Error ? error.message : String(error)}`);\n }\n }\n },\n\n mkdir: async (modalSandbox: ModalSandbox, path: string): Promise<void> => {\n try {\n const process = await modalSandbox.sandbox.exec(['mkdir', '-p', path], {\n stdout: 'pipe',\n stderr: 'pipe'\n });\n\n const [, stderr] = await Promise.all([\n process.stdout.readText(),\n process.stderr.readText()\n ]);\n\n const exitCode = await process.wait();\n\n if (exitCode !== 0) {\n throw new Error(`mkdir failed: ${stderr}`);\n }\n } catch (error) {\n throw new Error(`Failed to create directory ${path}: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n\n readdir: async (modalSandbox: ModalSandbox, path: string): Promise<FileEntry[]> => {\n try {\n const process = await modalSandbox.sandbox.exec(['ls', '-la', '--time-style=iso', path], {\n stdout: 'pipe',\n stderr: 'pipe'\n });\n\n const [output, stderr] = await Promise.all([\n process.stdout.readText(),\n process.stderr.readText()\n ]);\n\n const exitCode = await process.wait();\n\n if (exitCode !== 0) {\n throw new Error(`ls failed: ${stderr}`);\n }\n\n const lines = output.split('\\n').slice(1); // Skip header\n\n return lines\n .filter((line: string) => line.trim())\n .map((line: string) => {\n const parts = line.trim().split(/\\s+/);\n const permissions = parts[0] || '';\n const size = parseInt(parts[4]) || 0;\n const dateStr = (parts[5] || '') + ' ' + (parts[6] || '');\n const date = dateStr.trim() ? new Date(dateStr) : new Date();\n const name = parts.slice(8).join(' ') || parts[parts.length - 1] || 'unknown';\n\n return {\n name,\n path: `${path}/${name}`.replace('//', '/'),\n isDirectory: permissions.startsWith('d'),\n size,\n lastModified: isNaN(date.getTime()) ? new Date() : date\n };\n });\n } catch (error) {\n throw new Error(`Failed to read directory ${path}: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n\n exists: async (modalSandbox: ModalSandbox, path: string): Promise<boolean> => {\n try {\n const process = await modalSandbox.sandbox.exec(['test', '-e', path]);\n const exitCode = await process.wait();\n return exitCode === 0;\n } catch (error) {\n return false;\n }\n },\n\n remove: async (modalSandbox: ModalSandbox, path: string): Promise<void> => {\n try {\n const process = await modalSandbox.sandbox.exec(['rm', '-rf', path], {\n stdout: 'pipe',\n stderr: 'pipe'\n });\n\n const [, stderr] = await Promise.all([\n process.stdout.readText(),\n process.stderr.readText()\n ]);\n\n const exitCode = await process.wait();\n\n if (exitCode !== 0) {\n throw new Error(`rm failed: ${stderr}`);\n }\n } catch (error) {\n throw new Error(`Failed to remove ${path}: ${error instanceof Error ? error.message : String(error)}`);\n }\n }\n },\n\n // Provider-specific typed getInstance method\n getInstance: (sandbox: ModalSandbox): ModalSandbox => {\n return sandbox;\n },\n\n }\n }\n});"],"mappings":"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","names":["process"]}
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * Modal Provider - Factory-based Implementation\n * \n * Full-featured provider with serverless sandbox execution using the factory pattern.\n * Leverages Modal's JavaScript SDK for real sandbox management.\n * \n * Note: Modal's JavaScript SDK is in alpha. This implementation provides a working\n * foundation but may need updates as the Modal API evolves.\n */\n\nimport { createProvider, createBackgroundCommand } from 'computesdk';\nimport type { \n ExecutionResult, \n SandboxInfo, \n Runtime,\n CreateSandboxOptions,\n FileEntry,\n RunCommandOptions\n} from 'computesdk';\n\n// Import Modal SDK\nimport { App, Sandbox, initializeClient } from 'modal';\n\n/**\n * Modal-specific configuration options\n */\nexport interface ModalConfig {\n /** Modal API token ID - if not provided, will fallback to MODAL_TOKEN_ID environment variable */\n tokenId?: string;\n /** Modal API token secret - if not provided, will fallback to MODAL_TOKEN_SECRET environment variable */\n tokenSecret?: string;\n /** Default runtime environment */\n runtime?: Runtime;\n /** Execution timeout in milliseconds */\n timeout?: number;\n /** Modal environment (sandbox or main) */\n environment?: string;\n}\n\n/**\n * Modal sandbox interface - wraps Modal's Sandbox class\n */\ninterface ModalSandbox {\n sandbox: any; // Modal Sandbox instance (using any due to alpha SDK)\n sandboxId: string;\n}\n\n/**\n * Detect runtime from code content\n */\nfunction detectRuntime(code: string): Runtime {\n // Strong Node.js indicators\n if (code.includes('console.log') || \n code.includes('process.') ||\n code.includes('require(') ||\n code.includes('module.exports') ||\n code.includes('__dirname') ||\n code.includes('__filename') ||\n code.includes('throw new Error') || // JavaScript error throwing\n code.includes('new Error(')) {\n return 'node';\n }\n\n // Strong Python indicators\n if (code.includes('print(') ||\n code.includes('import ') ||\n code.includes('def ') ||\n code.includes('sys.') ||\n code.includes('json.') ||\n code.includes('f\"') ||\n code.includes(\"f'\") ||\n code.includes('raise ')) {\n return 'python';\n }\n\n // Default to Node.js for Modal (now using Node.js base image)\n return 'node';\n}\n\n/**\n * Create a Modal provider instance using the factory pattern\n */\nexport const modal = createProvider<ModalSandbox, ModalConfig>({\n name: 'modal',\n methods: {\n sandbox: {\n // Collection operations (map to compute.sandbox.*)\n create: async (config: ModalConfig, options?: CreateSandboxOptions) => {\n // Validate API credentials\n const tokenId = config.tokenId || (typeof process !== 'undefined' && process.env?.MODAL_TOKEN_ID) || '';\n const tokenSecret = config.tokenSecret || (typeof process !== 'undefined' && process.env?.MODAL_TOKEN_SECRET) || '';\n\n if (!tokenId || !tokenSecret) {\n throw new Error(\n `Missing Modal API credentials. Provide 'tokenId' and 'tokenSecret' in config or set MODAL_TOKEN_ID and MODAL_TOKEN_SECRET environment variables. Get your credentials from https://modal.com/`\n );\n }\n\n try {\n // Initialize Modal client with credentials\n initializeClient({ tokenId, tokenSecret });\n\n let sandbox: any;\n let sandboxId: string;\n\n if (options?.sandboxId) {\n // Reconnect to existing Modal sandbox\n sandbox = await Sandbox.fromId(options.sandboxId);\n sandboxId = options.sandboxId;\n } else {\n // Create new Modal sandbox with Node.js (more appropriate for a Node.js SDK)\n const app = await App.lookup('computesdk-modal', { createIfMissing: true });\n const image = await app.imageFromRegistry('node:20-alpine');\n sandbox = await app.createSandbox(image);\n sandboxId = sandbox.sandboxId;\n }\n\n const modalSandbox: ModalSandbox = {\n sandbox,\n sandboxId\n };\n\n return {\n sandbox: modalSandbox,\n sandboxId\n };\n } catch (error) {\n if (error instanceof Error) {\n if (error.message.includes('unauthorized') || error.message.includes('credentials')) {\n throw new Error(\n `Modal authentication failed. Please check your MODAL_TOKEN_ID and MODAL_TOKEN_SECRET environment variables. Get your credentials from https://modal.com/`\n );\n }\n if (error.message.includes('quota') || error.message.includes('limit')) {\n throw new Error(\n `Modal quota exceeded. Please check your usage at https://modal.com/`\n );\n }\n }\n throw new Error(\n `Failed to create Modal sandbox: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n },\n\n getById: async (config: ModalConfig, sandboxId: string) => {\n const tokenId = config.tokenId || process.env.MODAL_TOKEN_ID!;\n const tokenSecret = config.tokenSecret || process.env.MODAL_TOKEN_SECRET!;\n\n try {\n initializeClient({ tokenId, tokenSecret });\n const sandbox = await Sandbox.fromId(sandboxId);\n\n const modalSandbox: ModalSandbox = {\n sandbox,\n sandboxId\n };\n\n return {\n sandbox: modalSandbox,\n sandboxId\n };\n } catch (error) {\n // Sandbox doesn't exist or can't be accessed\n return null;\n }\n },\n\n list: async (_config: ModalConfig) => {\n throw new Error(\n `Modal provider does not support listing sandboxes. Modal sandboxes are managed individually through the Modal console. Use getById to reconnect to specific sandboxes by ID.`\n );\n },\n\n destroy: async (_config: ModalConfig, sandboxId: string) => {\n try {\n const sandbox = await Sandbox.fromId(sandboxId);\n if (sandbox && typeof sandbox.terminate === 'function') {\n await sandbox.terminate();\n }\n } catch (error) {\n // Sandbox might already be terminated or doesn't exist\n // This is acceptable for destroy operations\n }\n },\n\n // Instance operations (map to individual Sandbox methods)\n runCode: async (modalSandbox: ModalSandbox, code: string, runtime?: Runtime): Promise<ExecutionResult> => {\n const startTime = Date.now();\n\n try {\n // Auto-detect runtime from code if not specified\n const detectedRuntime = runtime || detectRuntime(code);\n\n // Create appropriate sandbox and command for the runtime\n let executionSandbox = modalSandbox.sandbox;\n let command: string[];\n let shouldCleanupSandbox = false;\n\n if (detectedRuntime === 'node') {\n // Use existing Node.js sandbox (now the default)\n command = ['node', '-e', code];\n } else {\n // For Python execution, create a Python sandbox dynamically\n const app = await App.lookup('computesdk-modal', { createIfMissing: true });\n const pythonImage = await app.imageFromRegistry('python:3.13-slim');\n executionSandbox = await app.createSandbox(pythonImage);\n command = ['python3', '-c', code];\n shouldCleanupSandbox = true; // Clean up temporary Python sandbox\n }\n\n const process = await executionSandbox.exec(command, {\n stdout: 'pipe',\n stderr: 'pipe'\n });\n\n // Use working stream reading pattern from debug\n const [stdout, stderr] = await Promise.all([\n process.stdout.readText(),\n process.stderr.readText()\n ]);\n\n const exitCode = await process.wait();\n\n // Clean up temporary Python sandbox if created\n if (shouldCleanupSandbox && executionSandbox !== modalSandbox.sandbox) {\n try {\n await executionSandbox.terminate();\n } catch (e) {\n // Ignore cleanup errors\n }\n }\n\n // Check for syntax errors in stderr\n if (exitCode !== 0 && stderr && (\n stderr.includes('SyntaxError') ||\n stderr.includes('invalid syntax')\n )) {\n throw new Error(`Syntax error: ${stderr.trim()}`);\n }\n\n return {\n stdout: stdout || '',\n stderr: stderr || '',\n exitCode: exitCode || 0,\n executionTime: Date.now() - startTime,\n sandboxId: modalSandbox.sandboxId,\n provider: 'modal'\n };\n } catch (error) {\n // Handle syntax errors and runtime errors\n if (error instanceof Error && error.message.includes('Syntax error')) {\n throw error; // Re-throw syntax errors\n }\n\n throw new Error(\n `Modal execution failed: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n },\n\n runCommand: async (modalSandbox: ModalSandbox, command: string, args: string[] = [], options?: RunCommandOptions): Promise<ExecutionResult> => {\n const startTime = Date.now();\n\n try {\n // Handle background command execution\n const { command: finalCommand, args: finalArgs, isBackground } = createBackgroundCommand(command, args, options);\n \n // Execute command using Modal's exec method with working pattern\n const process = await modalSandbox.sandbox.exec([finalCommand, ...finalArgs], {\n stdout: 'pipe',\n stderr: 'pipe'\n });\n\n // Use working stream reading pattern from debug\n const [stdout, stderr] = await Promise.all([\n process.stdout.readText(),\n process.stderr.readText()\n ]);\n\n const exitCode = await process.wait();\n\n return {\n stdout: stdout || '',\n stderr: stderr || '',\n exitCode: exitCode || 0,\n executionTime: Date.now() - startTime,\n sandboxId: modalSandbox.sandboxId,\n provider: 'modal',\n isBackground,\n // For background commands, we can't get a real PID, but we can indicate it's running\n ...(isBackground && { pid: -1 })\n };\n } catch (error) {\n // For command failures, return error info instead of throwing\n return {\n stdout: '',\n stderr: error instanceof Error ? error.message : String(error),\n exitCode: 127, // Command not found exit code\n executionTime: Date.now() - startTime,\n sandboxId: modalSandbox.sandboxId,\n provider: 'modal',\n isBackground: false // Error case, command didn't run as background\n };\n }\n },\n\n getInfo: async (modalSandbox: ModalSandbox): Promise<SandboxInfo> => {\n // Get actual sandbox status using Modal's poll method\n let status: 'running' | 'stopped' | 'error' = 'running';\n try {\n const pollResult = await modalSandbox.sandbox.poll();\n if (pollResult !== null) {\n // Sandbox has finished\n status = pollResult === 0 ? 'stopped' : 'error';\n }\n } catch (error) {\n // If polling fails, assume running\n status = 'running';\n }\n\n return {\n id: modalSandbox.sandboxId,\n provider: 'modal',\n runtime: 'node', // Modal default (now using Node.js)\n status,\n createdAt: new Date(),\n timeout: 300000,\n metadata: {\n modalSandboxId: modalSandbox.sandboxId,\n realModalImplementation: true\n }\n };\n },\n\n getUrl: async (modalSandbox: ModalSandbox, options: { port: number; protocol?: string }): Promise<string> => {\n try {\n // Use Modal's built-in tunnels method to get tunnel information\n const tunnels = await modalSandbox.sandbox.tunnels();\n const tunnel = tunnels[options.port];\n \n if (!tunnel) {\n throw new Error(`No tunnel found for port ${options.port}. Available ports: ${Object.keys(tunnels).join(', ')}`);\n }\n \n let url = tunnel.url;\n \n // If a specific protocol is requested, replace the URL's protocol\n if (options.protocol) {\n const urlObj = new URL(url);\n urlObj.protocol = options.protocol + ':';\n url = urlObj.toString();\n }\n \n return url;\n } catch (error) {\n throw new Error(\n `Failed to get Modal tunnel URL for port ${options.port}: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n },\n\n // Optional filesystem methods - Modal supports filesystem operations\n filesystem: {\n readFile: async (modalSandbox: ModalSandbox, path: string): Promise<string> => {\n try {\n // Use Modal's file open API to read files\n const file = await modalSandbox.sandbox.open(path);\n \n // Read the entire file content\n let content = '';\n if (file && typeof file.read === 'function') {\n const data = await file.read();\n content = typeof data === 'string' ? data : new TextDecoder().decode(data);\n }\n \n // Close the file if it has a close method\n if (file && typeof file.close === 'function') {\n await file.close();\n }\n \n return content;\n } catch (error) {\n // Fallback to using cat command with working stream pattern\n try {\n const process = await modalSandbox.sandbox.exec(['cat', path], {\n stdout: 'pipe',\n stderr: 'pipe'\n });\n\n const [content, stderr] = await Promise.all([\n process.stdout.readText(),\n process.stderr.readText()\n ]);\n\n const exitCode = await process.wait();\n\n if (exitCode !== 0) {\n throw new Error(`cat failed: ${stderr}`);\n }\n\n return content.trim(); // Remove extra newlines\n } catch (fallbackError) {\n throw new Error(`Failed to read file ${path}: ${error instanceof Error ? error.message : String(error)}`);\n }\n }\n },\n\n writeFile: async (modalSandbox: ModalSandbox, path: string, content: string): Promise<void> => {\n try {\n // Use Modal's file open API to write files\n const file = await modalSandbox.sandbox.open(path);\n \n // Write content to the file\n if (file && typeof file.write === 'function') {\n await file.write(content);\n }\n \n // Close the file if it has a close method\n if (file && typeof file.close === 'function') {\n await file.close();\n }\n } catch (error) {\n // Fallback to using shell command with proper escaping\n try {\n const process = await modalSandbox.sandbox.exec(['sh', '-c', `printf '%s' \"${content.replace(/\"/g, '\\\\\"')}\" > \"${path}\"`], {\n stdout: 'pipe',\n stderr: 'pipe'\n });\n\n const [, stderr] = await Promise.all([\n process.stdout.readText(),\n process.stderr.readText()\n ]);\n\n const exitCode = await process.wait();\n\n if (exitCode !== 0) {\n throw new Error(`write failed: ${stderr}`);\n }\n } catch (fallbackError) {\n throw new Error(`Failed to write file ${path}: ${error instanceof Error ? error.message : String(error)}`);\n }\n }\n },\n\n mkdir: async (modalSandbox: ModalSandbox, path: string): Promise<void> => {\n try {\n const process = await modalSandbox.sandbox.exec(['mkdir', '-p', path], {\n stdout: 'pipe',\n stderr: 'pipe'\n });\n\n const [, stderr] = await Promise.all([\n process.stdout.readText(),\n process.stderr.readText()\n ]);\n\n const exitCode = await process.wait();\n\n if (exitCode !== 0) {\n throw new Error(`mkdir failed: ${stderr}`);\n }\n } catch (error) {\n throw new Error(`Failed to create directory ${path}: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n\n readdir: async (modalSandbox: ModalSandbox, path: string): Promise<FileEntry[]> => {\n try {\n // Use simple -l flag for BusyBox compatibility (Alpine/node:20-alpine uses BusyBox ls)\n const process = await modalSandbox.sandbox.exec(['ls', '-la', path], {\n stdout: 'pipe',\n stderr: 'pipe'\n });\n\n const [output, stderr] = await Promise.all([\n process.stdout.readText(),\n process.stderr.readText()\n ]);\n\n const exitCode = await process.wait();\n\n if (exitCode !== 0) {\n throw new Error(`ls failed: ${stderr}`);\n }\n\n const lines = output.split('\\n').slice(1); // Skip header\n\n return lines\n .filter((line: string) => line.trim())\n .map((line: string) => {\n const parts = line.trim().split(/\\s+/);\n const permissions = parts[0] || '';\n const size = parseInt(parts[4]) || 0;\n const dateStr = (parts[5] || '') + ' ' + (parts[6] || '');\n const date = dateStr.trim() ? new Date(dateStr) : new Date();\n const name = parts.slice(8).join(' ') || parts[parts.length - 1] || 'unknown';\n\n return {\n name,\n path: `${path}/${name}`.replace('//', '/'),\n isDirectory: permissions.startsWith('d'),\n size,\n lastModified: isNaN(date.getTime()) ? new Date() : date\n };\n });\n } catch (error) {\n throw new Error(`Failed to read directory ${path}: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n\n exists: async (modalSandbox: ModalSandbox, path: string): Promise<boolean> => {\n try {\n const process = await modalSandbox.sandbox.exec(['test', '-e', path]);\n const exitCode = await process.wait();\n return exitCode === 0;\n } catch (error) {\n return false;\n }\n },\n\n remove: async (modalSandbox: ModalSandbox, path: string): Promise<void> => {\n try {\n const process = await modalSandbox.sandbox.exec(['rm', '-rf', path], {\n stdout: 'pipe',\n stderr: 'pipe'\n });\n\n const [, stderr] = await Promise.all([\n process.stdout.readText(),\n process.stderr.readText()\n ]);\n\n const exitCode = await process.wait();\n\n if (exitCode !== 0) {\n throw new Error(`rm failed: ${stderr}`);\n }\n } catch (error) {\n throw new Error(`Failed to remove ${path}: ${error instanceof Error ? error.message : String(error)}`);\n }\n }\n },\n\n // Provider-specific typed getInstance method\n getInstance: (sandbox: ModalSandbox): ModalSandbox => {\n return sandbox;\n },\n\n }\n }\n});"],"mappings":"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","names":["process"]}
package/dist/index.mjs CHANGED
@@ -9,7 +9,7 @@ function detectRuntime(code) {
9
9
  if (code.includes("print(") || code.includes("import ") || code.includes("def ") || code.includes("sys.") || code.includes("json.") || code.includes('f"') || code.includes("f'") || code.includes("raise ")) {
10
10
  return "python";
11
11
  }
12
- return "python";
12
+ return "node";
13
13
  }
14
14
  var modal = createProvider({
15
15
  name: "modal",
@@ -33,7 +33,7 @@ var modal = createProvider({
33
33
  sandboxId = options.sandboxId;
34
34
  } else {
35
35
  const app = await App.lookup("computesdk-modal", { createIfMissing: true });
36
- const image = await app.imageFromRegistry("python:3.13-slim");
36
+ const image = await app.imageFromRegistry("node:20-alpine");
37
37
  sandbox = await app.createSandbox(image);
38
38
  sandboxId = sandbox.sandboxId;
39
39
  }
@@ -104,13 +104,13 @@ var modal = createProvider({
104
104
  let command;
105
105
  let shouldCleanupSandbox = false;
106
106
  if (detectedRuntime === "node") {
107
- const app = await App.lookup("computesdk-modal", { createIfMissing: true });
108
- const nodeImage = await app.imageFromRegistry("node:20-alpine");
109
- executionSandbox = await app.createSandbox(nodeImage);
110
107
  command = ["node", "-e", code];
111
- shouldCleanupSandbox = true;
112
108
  } else {
109
+ const app = await App.lookup("computesdk-modal", { createIfMissing: true });
110
+ const pythonImage = await app.imageFromRegistry("python:3.13-slim");
111
+ executionSandbox = await app.createSandbox(pythonImage);
113
112
  command = ["python3", "-c", code];
113
+ shouldCleanupSandbox = true;
114
114
  }
115
115
  const process2 = await executionSandbox.exec(command, {
116
116
  stdout: "pipe",
@@ -198,8 +198,8 @@ var modal = createProvider({
198
198
  return {
199
199
  id: modalSandbox.sandboxId,
200
200
  provider: "modal",
201
- runtime: "python",
202
- // Modal default
201
+ runtime: "node",
202
+ // Modal default (now using Node.js)
203
203
  status,
204
204
  createdAt: /* @__PURE__ */ new Date(),
205
205
  timeout: 3e5,
@@ -311,7 +311,7 @@ var modal = createProvider({
311
311
  },
312
312
  readdir: async (modalSandbox, path) => {
313
313
  try {
314
- const process2 = await modalSandbox.sandbox.exec(["ls", "-la", "--time-style=iso", path], {
314
+ const process2 = await modalSandbox.sandbox.exec(["ls", "-la", path], {
315
315
  stdout: "pipe",
316
316
  stderr: "pipe"
317
317
  });
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * Modal Provider - Factory-based Implementation\n * \n * Full-featured provider with serverless sandbox execution using the factory pattern.\n * Leverages Modal's JavaScript SDK for real sandbox management.\n * \n * Note: Modal's JavaScript SDK is in alpha. This implementation provides a working\n * foundation but may need updates as the Modal API evolves.\n */\n\nimport { createProvider, createBackgroundCommand } from 'computesdk';\nimport type { \n ExecutionResult, \n SandboxInfo, \n Runtime,\n CreateSandboxOptions,\n FileEntry,\n RunCommandOptions\n} from 'computesdk';\n\n// Import Modal SDK\nimport { App, Sandbox, initializeClient } from 'modal';\n\n/**\n * Modal-specific configuration options\n */\nexport interface ModalConfig {\n /** Modal API token ID - if not provided, will fallback to MODAL_TOKEN_ID environment variable */\n tokenId?: string;\n /** Modal API token secret - if not provided, will fallback to MODAL_TOKEN_SECRET environment variable */\n tokenSecret?: string;\n /** Default runtime environment */\n runtime?: Runtime;\n /** Execution timeout in milliseconds */\n timeout?: number;\n /** Modal environment (sandbox or main) */\n environment?: string;\n}\n\n/**\n * Modal sandbox interface - wraps Modal's Sandbox class\n */\ninterface ModalSandbox {\n sandbox: any; // Modal Sandbox instance (using any due to alpha SDK)\n sandboxId: string;\n}\n\n/**\n * Detect runtime from code content\n */\nfunction detectRuntime(code: string): Runtime {\n // Strong Node.js indicators\n if (code.includes('console.log') || \n code.includes('process.') ||\n code.includes('require(') ||\n code.includes('module.exports') ||\n code.includes('__dirname') ||\n code.includes('__filename') ||\n code.includes('throw new Error') || // JavaScript error throwing\n code.includes('new Error(')) {\n return 'node';\n }\n\n // Strong Python indicators \n if (code.includes('print(') || \n code.includes('import ') ||\n code.includes('def ') ||\n code.includes('sys.') ||\n code.includes('json.') ||\n code.includes('f\"') ||\n code.includes(\"f'\") ||\n code.includes('raise ')) {\n return 'python';\n }\n\n // Default to Python for Modal\n return 'python';\n}\n\n/**\n * Create a Modal provider instance using the factory pattern\n */\nexport const modal = createProvider<ModalSandbox, ModalConfig>({\n name: 'modal',\n methods: {\n sandbox: {\n // Collection operations (map to compute.sandbox.*)\n create: async (config: ModalConfig, options?: CreateSandboxOptions) => {\n // Validate API credentials\n const tokenId = config.tokenId || (typeof process !== 'undefined' && process.env?.MODAL_TOKEN_ID) || '';\n const tokenSecret = config.tokenSecret || (typeof process !== 'undefined' && process.env?.MODAL_TOKEN_SECRET) || '';\n\n if (!tokenId || !tokenSecret) {\n throw new Error(\n `Missing Modal API credentials. Provide 'tokenId' and 'tokenSecret' in config or set MODAL_TOKEN_ID and MODAL_TOKEN_SECRET environment variables. Get your credentials from https://modal.com/`\n );\n }\n\n try {\n // Initialize Modal client with credentials\n initializeClient({ tokenId, tokenSecret });\n\n let sandbox: any;\n let sandboxId: string;\n\n if (options?.sandboxId) {\n // Reconnect to existing Modal sandbox\n sandbox = await Sandbox.fromId(options.sandboxId);\n sandboxId = options.sandboxId;\n } else {\n // Create new Modal sandbox using working pattern from debug\n const app = await App.lookup('computesdk-modal', { createIfMissing: true });\n const image = await app.imageFromRegistry('python:3.13-slim');\n sandbox = await app.createSandbox(image);\n sandboxId = sandbox.sandboxId;\n }\n\n const modalSandbox: ModalSandbox = {\n sandbox,\n sandboxId\n };\n\n return {\n sandbox: modalSandbox,\n sandboxId\n };\n } catch (error) {\n if (error instanceof Error) {\n if (error.message.includes('unauthorized') || error.message.includes('credentials')) {\n throw new Error(\n `Modal authentication failed. Please check your MODAL_TOKEN_ID and MODAL_TOKEN_SECRET environment variables. Get your credentials from https://modal.com/`\n );\n }\n if (error.message.includes('quota') || error.message.includes('limit')) {\n throw new Error(\n `Modal quota exceeded. Please check your usage at https://modal.com/`\n );\n }\n }\n throw new Error(\n `Failed to create Modal sandbox: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n },\n\n getById: async (config: ModalConfig, sandboxId: string) => {\n const tokenId = config.tokenId || process.env.MODAL_TOKEN_ID!;\n const tokenSecret = config.tokenSecret || process.env.MODAL_TOKEN_SECRET!;\n\n try {\n initializeClient({ tokenId, tokenSecret });\n const sandbox = await Sandbox.fromId(sandboxId);\n\n const modalSandbox: ModalSandbox = {\n sandbox,\n sandboxId\n };\n\n return {\n sandbox: modalSandbox,\n sandboxId\n };\n } catch (error) {\n // Sandbox doesn't exist or can't be accessed\n return null;\n }\n },\n\n list: async (_config: ModalConfig) => {\n throw new Error(\n `Modal provider does not support listing sandboxes. Modal sandboxes are managed individually through the Modal console. Use getById to reconnect to specific sandboxes by ID.`\n );\n },\n\n destroy: async (_config: ModalConfig, sandboxId: string) => {\n try {\n const sandbox = await Sandbox.fromId(sandboxId);\n if (sandbox && typeof sandbox.terminate === 'function') {\n await sandbox.terminate();\n }\n } catch (error) {\n // Sandbox might already be terminated or doesn't exist\n // This is acceptable for destroy operations\n }\n },\n\n // Instance operations (map to individual Sandbox methods)\n runCode: async (modalSandbox: ModalSandbox, code: string, runtime?: Runtime): Promise<ExecutionResult> => {\n const startTime = Date.now();\n\n try {\n // Auto-detect runtime from code if not specified\n const detectedRuntime = runtime || detectRuntime(code);\n \n // Create appropriate sandbox and command for the runtime\n let executionSandbox = modalSandbox.sandbox;\n let command: string[];\n let shouldCleanupSandbox = false;\n \n if (detectedRuntime === 'node') {\n // For Node.js execution, create a Node.js sandbox dynamically\n const app = await App.lookup('computesdk-modal', { createIfMissing: true });\n const nodeImage = await app.imageFromRegistry('node:20-alpine');\n executionSandbox = await app.createSandbox(nodeImage);\n command = ['node', '-e', code];\n shouldCleanupSandbox = true; // Clean up temporary Node.js sandbox\n } else {\n // Use existing Python sandbox for Python code\n command = ['python3', '-c', code];\n }\n\n const process = await executionSandbox.exec(command, {\n stdout: 'pipe',\n stderr: 'pipe'\n });\n\n // Use working stream reading pattern from debug\n const [stdout, stderr] = await Promise.all([\n process.stdout.readText(),\n process.stderr.readText()\n ]);\n\n const exitCode = await process.wait();\n \n // Clean up temporary Node.js sandbox if created\n if (shouldCleanupSandbox && executionSandbox !== modalSandbox.sandbox) {\n try {\n await executionSandbox.terminate();\n } catch (e) {\n // Ignore cleanup errors\n }\n }\n\n // Check for syntax errors in stderr\n if (exitCode !== 0 && stderr && (\n stderr.includes('SyntaxError') || \n stderr.includes('invalid syntax')\n )) {\n throw new Error(`Syntax error: ${stderr.trim()}`);\n }\n\n return {\n stdout: stdout || '',\n stderr: stderr || '',\n exitCode: exitCode || 0,\n executionTime: Date.now() - startTime,\n sandboxId: modalSandbox.sandboxId,\n provider: 'modal'\n };\n } catch (error) {\n // Handle syntax errors and runtime errors\n if (error instanceof Error && error.message.includes('Syntax error')) {\n throw error; // Re-throw syntax errors\n }\n \n throw new Error(\n `Modal execution failed: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n },\n\n runCommand: async (modalSandbox: ModalSandbox, command: string, args: string[] = [], options?: RunCommandOptions): Promise<ExecutionResult> => {\n const startTime = Date.now();\n\n try {\n // Handle background command execution\n const { command: finalCommand, args: finalArgs, isBackground } = createBackgroundCommand(command, args, options);\n \n // Execute command using Modal's exec method with working pattern\n const process = await modalSandbox.sandbox.exec([finalCommand, ...finalArgs], {\n stdout: 'pipe',\n stderr: 'pipe'\n });\n\n // Use working stream reading pattern from debug\n const [stdout, stderr] = await Promise.all([\n process.stdout.readText(),\n process.stderr.readText()\n ]);\n\n const exitCode = await process.wait();\n\n return {\n stdout: stdout || '',\n stderr: stderr || '',\n exitCode: exitCode || 0,\n executionTime: Date.now() - startTime,\n sandboxId: modalSandbox.sandboxId,\n provider: 'modal',\n isBackground,\n // For background commands, we can't get a real PID, but we can indicate it's running\n ...(isBackground && { pid: -1 })\n };\n } catch (error) {\n // For command failures, return error info instead of throwing\n return {\n stdout: '',\n stderr: error instanceof Error ? error.message : String(error),\n exitCode: 127, // Command not found exit code\n executionTime: Date.now() - startTime,\n sandboxId: modalSandbox.sandboxId,\n provider: 'modal',\n isBackground: false // Error case, command didn't run as background\n };\n }\n },\n\n getInfo: async (modalSandbox: ModalSandbox): Promise<SandboxInfo> => {\n // Get actual sandbox status using Modal's poll method\n let status: 'running' | 'stopped' | 'error' = 'running';\n try {\n const pollResult = await modalSandbox.sandbox.poll();\n if (pollResult !== null) {\n // Sandbox has finished\n status = pollResult === 0 ? 'stopped' : 'error';\n }\n } catch (error) {\n // If polling fails, assume running\n status = 'running';\n }\n\n return {\n id: modalSandbox.sandboxId,\n provider: 'modal',\n runtime: 'python', // Modal default\n status,\n createdAt: new Date(),\n timeout: 300000,\n metadata: {\n modalSandboxId: modalSandbox.sandboxId,\n realModalImplementation: true\n }\n };\n },\n\n getUrl: async (modalSandbox: ModalSandbox, options: { port: number; protocol?: string }): Promise<string> => {\n try {\n // Use Modal's built-in tunnels method to get tunnel information\n const tunnels = await modalSandbox.sandbox.tunnels();\n const tunnel = tunnels[options.port];\n \n if (!tunnel) {\n throw new Error(`No tunnel found for port ${options.port}. Available ports: ${Object.keys(tunnels).join(', ')}`);\n }\n \n let url = tunnel.url;\n \n // If a specific protocol is requested, replace the URL's protocol\n if (options.protocol) {\n const urlObj = new URL(url);\n urlObj.protocol = options.protocol + ':';\n url = urlObj.toString();\n }\n \n return url;\n } catch (error) {\n throw new Error(\n `Failed to get Modal tunnel URL for port ${options.port}: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n },\n\n // Optional filesystem methods - Modal supports filesystem operations\n filesystem: {\n readFile: async (modalSandbox: ModalSandbox, path: string): Promise<string> => {\n try {\n // Use Modal's file open API to read files\n const file = await modalSandbox.sandbox.open(path);\n \n // Read the entire file content\n let content = '';\n if (file && typeof file.read === 'function') {\n const data = await file.read();\n content = typeof data === 'string' ? data : new TextDecoder().decode(data);\n }\n \n // Close the file if it has a close method\n if (file && typeof file.close === 'function') {\n await file.close();\n }\n \n return content;\n } catch (error) {\n // Fallback to using cat command with working stream pattern\n try {\n const process = await modalSandbox.sandbox.exec(['cat', path], {\n stdout: 'pipe',\n stderr: 'pipe'\n });\n\n const [content, stderr] = await Promise.all([\n process.stdout.readText(),\n process.stderr.readText()\n ]);\n\n const exitCode = await process.wait();\n\n if (exitCode !== 0) {\n throw new Error(`cat failed: ${stderr}`);\n }\n\n return content.trim(); // Remove extra newlines\n } catch (fallbackError) {\n throw new Error(`Failed to read file ${path}: ${error instanceof Error ? error.message : String(error)}`);\n }\n }\n },\n\n writeFile: async (modalSandbox: ModalSandbox, path: string, content: string): Promise<void> => {\n try {\n // Use Modal's file open API to write files\n const file = await modalSandbox.sandbox.open(path);\n \n // Write content to the file\n if (file && typeof file.write === 'function') {\n await file.write(content);\n }\n \n // Close the file if it has a close method\n if (file && typeof file.close === 'function') {\n await file.close();\n }\n } catch (error) {\n // Fallback to using shell command with proper escaping\n try {\n const process = await modalSandbox.sandbox.exec(['sh', '-c', `printf '%s' \"${content.replace(/\"/g, '\\\\\"')}\" > \"${path}\"`], {\n stdout: 'pipe',\n stderr: 'pipe'\n });\n\n const [, stderr] = await Promise.all([\n process.stdout.readText(),\n process.stderr.readText()\n ]);\n\n const exitCode = await process.wait();\n\n if (exitCode !== 0) {\n throw new Error(`write failed: ${stderr}`);\n }\n } catch (fallbackError) {\n throw new Error(`Failed to write file ${path}: ${error instanceof Error ? error.message : String(error)}`);\n }\n }\n },\n\n mkdir: async (modalSandbox: ModalSandbox, path: string): Promise<void> => {\n try {\n const process = await modalSandbox.sandbox.exec(['mkdir', '-p', path], {\n stdout: 'pipe',\n stderr: 'pipe'\n });\n\n const [, stderr] = await Promise.all([\n process.stdout.readText(),\n process.stderr.readText()\n ]);\n\n const exitCode = await process.wait();\n\n if (exitCode !== 0) {\n throw new Error(`mkdir failed: ${stderr}`);\n }\n } catch (error) {\n throw new Error(`Failed to create directory ${path}: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n\n readdir: async (modalSandbox: ModalSandbox, path: string): Promise<FileEntry[]> => {\n try {\n const process = await modalSandbox.sandbox.exec(['ls', '-la', '--time-style=iso', path], {\n stdout: 'pipe',\n stderr: 'pipe'\n });\n\n const [output, stderr] = await Promise.all([\n process.stdout.readText(),\n process.stderr.readText()\n ]);\n\n const exitCode = await process.wait();\n\n if (exitCode !== 0) {\n throw new Error(`ls failed: ${stderr}`);\n }\n\n const lines = output.split('\\n').slice(1); // Skip header\n\n return lines\n .filter((line: string) => line.trim())\n .map((line: string) => {\n const parts = line.trim().split(/\\s+/);\n const permissions = parts[0] || '';\n const size = parseInt(parts[4]) || 0;\n const dateStr = (parts[5] || '') + ' ' + (parts[6] || '');\n const date = dateStr.trim() ? new Date(dateStr) : new Date();\n const name = parts.slice(8).join(' ') || parts[parts.length - 1] || 'unknown';\n\n return {\n name,\n path: `${path}/${name}`.replace('//', '/'),\n isDirectory: permissions.startsWith('d'),\n size,\n lastModified: isNaN(date.getTime()) ? new Date() : date\n };\n });\n } catch (error) {\n throw new Error(`Failed to read directory ${path}: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n\n exists: async (modalSandbox: ModalSandbox, path: string): Promise<boolean> => {\n try {\n const process = await modalSandbox.sandbox.exec(['test', '-e', path]);\n const exitCode = await process.wait();\n return exitCode === 0;\n } catch (error) {\n return false;\n }\n },\n\n remove: async (modalSandbox: ModalSandbox, path: string): Promise<void> => {\n try {\n const process = await modalSandbox.sandbox.exec(['rm', '-rf', path], {\n stdout: 'pipe',\n stderr: 'pipe'\n });\n\n const [, stderr] = await Promise.all([\n process.stdout.readText(),\n process.stderr.readText()\n ]);\n\n const exitCode = await process.wait();\n\n if (exitCode !== 0) {\n throw new Error(`rm failed: ${stderr}`);\n }\n } catch (error) {\n throw new Error(`Failed to remove ${path}: ${error instanceof Error ? error.message : String(error)}`);\n }\n }\n },\n\n // Provider-specific typed getInstance method\n getInstance: (sandbox: ModalSandbox): ModalSandbox => {\n return sandbox;\n },\n\n }\n }\n});"],"mappings":"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","names":["process"]}
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * Modal Provider - Factory-based Implementation\n * \n * Full-featured provider with serverless sandbox execution using the factory pattern.\n * Leverages Modal's JavaScript SDK for real sandbox management.\n * \n * Note: Modal's JavaScript SDK is in alpha. This implementation provides a working\n * foundation but may need updates as the Modal API evolves.\n */\n\nimport { createProvider, createBackgroundCommand } from 'computesdk';\nimport type { \n ExecutionResult, \n SandboxInfo, \n Runtime,\n CreateSandboxOptions,\n FileEntry,\n RunCommandOptions\n} from 'computesdk';\n\n// Import Modal SDK\nimport { App, Sandbox, initializeClient } from 'modal';\n\n/**\n * Modal-specific configuration options\n */\nexport interface ModalConfig {\n /** Modal API token ID - if not provided, will fallback to MODAL_TOKEN_ID environment variable */\n tokenId?: string;\n /** Modal API token secret - if not provided, will fallback to MODAL_TOKEN_SECRET environment variable */\n tokenSecret?: string;\n /** Default runtime environment */\n runtime?: Runtime;\n /** Execution timeout in milliseconds */\n timeout?: number;\n /** Modal environment (sandbox or main) */\n environment?: string;\n}\n\n/**\n * Modal sandbox interface - wraps Modal's Sandbox class\n */\ninterface ModalSandbox {\n sandbox: any; // Modal Sandbox instance (using any due to alpha SDK)\n sandboxId: string;\n}\n\n/**\n * Detect runtime from code content\n */\nfunction detectRuntime(code: string): Runtime {\n // Strong Node.js indicators\n if (code.includes('console.log') || \n code.includes('process.') ||\n code.includes('require(') ||\n code.includes('module.exports') ||\n code.includes('__dirname') ||\n code.includes('__filename') ||\n code.includes('throw new Error') || // JavaScript error throwing\n code.includes('new Error(')) {\n return 'node';\n }\n\n // Strong Python indicators\n if (code.includes('print(') ||\n code.includes('import ') ||\n code.includes('def ') ||\n code.includes('sys.') ||\n code.includes('json.') ||\n code.includes('f\"') ||\n code.includes(\"f'\") ||\n code.includes('raise ')) {\n return 'python';\n }\n\n // Default to Node.js for Modal (now using Node.js base image)\n return 'node';\n}\n\n/**\n * Create a Modal provider instance using the factory pattern\n */\nexport const modal = createProvider<ModalSandbox, ModalConfig>({\n name: 'modal',\n methods: {\n sandbox: {\n // Collection operations (map to compute.sandbox.*)\n create: async (config: ModalConfig, options?: CreateSandboxOptions) => {\n // Validate API credentials\n const tokenId = config.tokenId || (typeof process !== 'undefined' && process.env?.MODAL_TOKEN_ID) || '';\n const tokenSecret = config.tokenSecret || (typeof process !== 'undefined' && process.env?.MODAL_TOKEN_SECRET) || '';\n\n if (!tokenId || !tokenSecret) {\n throw new Error(\n `Missing Modal API credentials. Provide 'tokenId' and 'tokenSecret' in config or set MODAL_TOKEN_ID and MODAL_TOKEN_SECRET environment variables. Get your credentials from https://modal.com/`\n );\n }\n\n try {\n // Initialize Modal client with credentials\n initializeClient({ tokenId, tokenSecret });\n\n let sandbox: any;\n let sandboxId: string;\n\n if (options?.sandboxId) {\n // Reconnect to existing Modal sandbox\n sandbox = await Sandbox.fromId(options.sandboxId);\n sandboxId = options.sandboxId;\n } else {\n // Create new Modal sandbox with Node.js (more appropriate for a Node.js SDK)\n const app = await App.lookup('computesdk-modal', { createIfMissing: true });\n const image = await app.imageFromRegistry('node:20-alpine');\n sandbox = await app.createSandbox(image);\n sandboxId = sandbox.sandboxId;\n }\n\n const modalSandbox: ModalSandbox = {\n sandbox,\n sandboxId\n };\n\n return {\n sandbox: modalSandbox,\n sandboxId\n };\n } catch (error) {\n if (error instanceof Error) {\n if (error.message.includes('unauthorized') || error.message.includes('credentials')) {\n throw new Error(\n `Modal authentication failed. Please check your MODAL_TOKEN_ID and MODAL_TOKEN_SECRET environment variables. Get your credentials from https://modal.com/`\n );\n }\n if (error.message.includes('quota') || error.message.includes('limit')) {\n throw new Error(\n `Modal quota exceeded. Please check your usage at https://modal.com/`\n );\n }\n }\n throw new Error(\n `Failed to create Modal sandbox: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n },\n\n getById: async (config: ModalConfig, sandboxId: string) => {\n const tokenId = config.tokenId || process.env.MODAL_TOKEN_ID!;\n const tokenSecret = config.tokenSecret || process.env.MODAL_TOKEN_SECRET!;\n\n try {\n initializeClient({ tokenId, tokenSecret });\n const sandbox = await Sandbox.fromId(sandboxId);\n\n const modalSandbox: ModalSandbox = {\n sandbox,\n sandboxId\n };\n\n return {\n sandbox: modalSandbox,\n sandboxId\n };\n } catch (error) {\n // Sandbox doesn't exist or can't be accessed\n return null;\n }\n },\n\n list: async (_config: ModalConfig) => {\n throw new Error(\n `Modal provider does not support listing sandboxes. Modal sandboxes are managed individually through the Modal console. Use getById to reconnect to specific sandboxes by ID.`\n );\n },\n\n destroy: async (_config: ModalConfig, sandboxId: string) => {\n try {\n const sandbox = await Sandbox.fromId(sandboxId);\n if (sandbox && typeof sandbox.terminate === 'function') {\n await sandbox.terminate();\n }\n } catch (error) {\n // Sandbox might already be terminated or doesn't exist\n // This is acceptable for destroy operations\n }\n },\n\n // Instance operations (map to individual Sandbox methods)\n runCode: async (modalSandbox: ModalSandbox, code: string, runtime?: Runtime): Promise<ExecutionResult> => {\n const startTime = Date.now();\n\n try {\n // Auto-detect runtime from code if not specified\n const detectedRuntime = runtime || detectRuntime(code);\n\n // Create appropriate sandbox and command for the runtime\n let executionSandbox = modalSandbox.sandbox;\n let command: string[];\n let shouldCleanupSandbox = false;\n\n if (detectedRuntime === 'node') {\n // Use existing Node.js sandbox (now the default)\n command = ['node', '-e', code];\n } else {\n // For Python execution, create a Python sandbox dynamically\n const app = await App.lookup('computesdk-modal', { createIfMissing: true });\n const pythonImage = await app.imageFromRegistry('python:3.13-slim');\n executionSandbox = await app.createSandbox(pythonImage);\n command = ['python3', '-c', code];\n shouldCleanupSandbox = true; // Clean up temporary Python sandbox\n }\n\n const process = await executionSandbox.exec(command, {\n stdout: 'pipe',\n stderr: 'pipe'\n });\n\n // Use working stream reading pattern from debug\n const [stdout, stderr] = await Promise.all([\n process.stdout.readText(),\n process.stderr.readText()\n ]);\n\n const exitCode = await process.wait();\n\n // Clean up temporary Python sandbox if created\n if (shouldCleanupSandbox && executionSandbox !== modalSandbox.sandbox) {\n try {\n await executionSandbox.terminate();\n } catch (e) {\n // Ignore cleanup errors\n }\n }\n\n // Check for syntax errors in stderr\n if (exitCode !== 0 && stderr && (\n stderr.includes('SyntaxError') ||\n stderr.includes('invalid syntax')\n )) {\n throw new Error(`Syntax error: ${stderr.trim()}`);\n }\n\n return {\n stdout: stdout || '',\n stderr: stderr || '',\n exitCode: exitCode || 0,\n executionTime: Date.now() - startTime,\n sandboxId: modalSandbox.sandboxId,\n provider: 'modal'\n };\n } catch (error) {\n // Handle syntax errors and runtime errors\n if (error instanceof Error && error.message.includes('Syntax error')) {\n throw error; // Re-throw syntax errors\n }\n\n throw new Error(\n `Modal execution failed: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n },\n\n runCommand: async (modalSandbox: ModalSandbox, command: string, args: string[] = [], options?: RunCommandOptions): Promise<ExecutionResult> => {\n const startTime = Date.now();\n\n try {\n // Handle background command execution\n const { command: finalCommand, args: finalArgs, isBackground } = createBackgroundCommand(command, args, options);\n \n // Execute command using Modal's exec method with working pattern\n const process = await modalSandbox.sandbox.exec([finalCommand, ...finalArgs], {\n stdout: 'pipe',\n stderr: 'pipe'\n });\n\n // Use working stream reading pattern from debug\n const [stdout, stderr] = await Promise.all([\n process.stdout.readText(),\n process.stderr.readText()\n ]);\n\n const exitCode = await process.wait();\n\n return {\n stdout: stdout || '',\n stderr: stderr || '',\n exitCode: exitCode || 0,\n executionTime: Date.now() - startTime,\n sandboxId: modalSandbox.sandboxId,\n provider: 'modal',\n isBackground,\n // For background commands, we can't get a real PID, but we can indicate it's running\n ...(isBackground && { pid: -1 })\n };\n } catch (error) {\n // For command failures, return error info instead of throwing\n return {\n stdout: '',\n stderr: error instanceof Error ? error.message : String(error),\n exitCode: 127, // Command not found exit code\n executionTime: Date.now() - startTime,\n sandboxId: modalSandbox.sandboxId,\n provider: 'modal',\n isBackground: false // Error case, command didn't run as background\n };\n }\n },\n\n getInfo: async (modalSandbox: ModalSandbox): Promise<SandboxInfo> => {\n // Get actual sandbox status using Modal's poll method\n let status: 'running' | 'stopped' | 'error' = 'running';\n try {\n const pollResult = await modalSandbox.sandbox.poll();\n if (pollResult !== null) {\n // Sandbox has finished\n status = pollResult === 0 ? 'stopped' : 'error';\n }\n } catch (error) {\n // If polling fails, assume running\n status = 'running';\n }\n\n return {\n id: modalSandbox.sandboxId,\n provider: 'modal',\n runtime: 'node', // Modal default (now using Node.js)\n status,\n createdAt: new Date(),\n timeout: 300000,\n metadata: {\n modalSandboxId: modalSandbox.sandboxId,\n realModalImplementation: true\n }\n };\n },\n\n getUrl: async (modalSandbox: ModalSandbox, options: { port: number; protocol?: string }): Promise<string> => {\n try {\n // Use Modal's built-in tunnels method to get tunnel information\n const tunnels = await modalSandbox.sandbox.tunnels();\n const tunnel = tunnels[options.port];\n \n if (!tunnel) {\n throw new Error(`No tunnel found for port ${options.port}. Available ports: ${Object.keys(tunnels).join(', ')}`);\n }\n \n let url = tunnel.url;\n \n // If a specific protocol is requested, replace the URL's protocol\n if (options.protocol) {\n const urlObj = new URL(url);\n urlObj.protocol = options.protocol + ':';\n url = urlObj.toString();\n }\n \n return url;\n } catch (error) {\n throw new Error(\n `Failed to get Modal tunnel URL for port ${options.port}: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n },\n\n // Optional filesystem methods - Modal supports filesystem operations\n filesystem: {\n readFile: async (modalSandbox: ModalSandbox, path: string): Promise<string> => {\n try {\n // Use Modal's file open API to read files\n const file = await modalSandbox.sandbox.open(path);\n \n // Read the entire file content\n let content = '';\n if (file && typeof file.read === 'function') {\n const data = await file.read();\n content = typeof data === 'string' ? data : new TextDecoder().decode(data);\n }\n \n // Close the file if it has a close method\n if (file && typeof file.close === 'function') {\n await file.close();\n }\n \n return content;\n } catch (error) {\n // Fallback to using cat command with working stream pattern\n try {\n const process = await modalSandbox.sandbox.exec(['cat', path], {\n stdout: 'pipe',\n stderr: 'pipe'\n });\n\n const [content, stderr] = await Promise.all([\n process.stdout.readText(),\n process.stderr.readText()\n ]);\n\n const exitCode = await process.wait();\n\n if (exitCode !== 0) {\n throw new Error(`cat failed: ${stderr}`);\n }\n\n return content.trim(); // Remove extra newlines\n } catch (fallbackError) {\n throw new Error(`Failed to read file ${path}: ${error instanceof Error ? error.message : String(error)}`);\n }\n }\n },\n\n writeFile: async (modalSandbox: ModalSandbox, path: string, content: string): Promise<void> => {\n try {\n // Use Modal's file open API to write files\n const file = await modalSandbox.sandbox.open(path);\n \n // Write content to the file\n if (file && typeof file.write === 'function') {\n await file.write(content);\n }\n \n // Close the file if it has a close method\n if (file && typeof file.close === 'function') {\n await file.close();\n }\n } catch (error) {\n // Fallback to using shell command with proper escaping\n try {\n const process = await modalSandbox.sandbox.exec(['sh', '-c', `printf '%s' \"${content.replace(/\"/g, '\\\\\"')}\" > \"${path}\"`], {\n stdout: 'pipe',\n stderr: 'pipe'\n });\n\n const [, stderr] = await Promise.all([\n process.stdout.readText(),\n process.stderr.readText()\n ]);\n\n const exitCode = await process.wait();\n\n if (exitCode !== 0) {\n throw new Error(`write failed: ${stderr}`);\n }\n } catch (fallbackError) {\n throw new Error(`Failed to write file ${path}: ${error instanceof Error ? error.message : String(error)}`);\n }\n }\n },\n\n mkdir: async (modalSandbox: ModalSandbox, path: string): Promise<void> => {\n try {\n const process = await modalSandbox.sandbox.exec(['mkdir', '-p', path], {\n stdout: 'pipe',\n stderr: 'pipe'\n });\n\n const [, stderr] = await Promise.all([\n process.stdout.readText(),\n process.stderr.readText()\n ]);\n\n const exitCode = await process.wait();\n\n if (exitCode !== 0) {\n throw new Error(`mkdir failed: ${stderr}`);\n }\n } catch (error) {\n throw new Error(`Failed to create directory ${path}: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n\n readdir: async (modalSandbox: ModalSandbox, path: string): Promise<FileEntry[]> => {\n try {\n // Use simple -l flag for BusyBox compatibility (Alpine/node:20-alpine uses BusyBox ls)\n const process = await modalSandbox.sandbox.exec(['ls', '-la', path], {\n stdout: 'pipe',\n stderr: 'pipe'\n });\n\n const [output, stderr] = await Promise.all([\n process.stdout.readText(),\n process.stderr.readText()\n ]);\n\n const exitCode = await process.wait();\n\n if (exitCode !== 0) {\n throw new Error(`ls failed: ${stderr}`);\n }\n\n const lines = output.split('\\n').slice(1); // Skip header\n\n return lines\n .filter((line: string) => line.trim())\n .map((line: string) => {\n const parts = line.trim().split(/\\s+/);\n const permissions = parts[0] || '';\n const size = parseInt(parts[4]) || 0;\n const dateStr = (parts[5] || '') + ' ' + (parts[6] || '');\n const date = dateStr.trim() ? new Date(dateStr) : new Date();\n const name = parts.slice(8).join(' ') || parts[parts.length - 1] || 'unknown';\n\n return {\n name,\n path: `${path}/${name}`.replace('//', '/'),\n isDirectory: permissions.startsWith('d'),\n size,\n lastModified: isNaN(date.getTime()) ? new Date() : date\n };\n });\n } catch (error) {\n throw new Error(`Failed to read directory ${path}: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n\n exists: async (modalSandbox: ModalSandbox, path: string): Promise<boolean> => {\n try {\n const process = await modalSandbox.sandbox.exec(['test', '-e', path]);\n const exitCode = await process.wait();\n return exitCode === 0;\n } catch (error) {\n return false;\n }\n },\n\n remove: async (modalSandbox: ModalSandbox, path: string): Promise<void> => {\n try {\n const process = await modalSandbox.sandbox.exec(['rm', '-rf', path], {\n stdout: 'pipe',\n stderr: 'pipe'\n });\n\n const [, stderr] = await Promise.all([\n process.stdout.readText(),\n process.stderr.readText()\n ]);\n\n const exitCode = await process.wait();\n\n if (exitCode !== 0) {\n throw new Error(`rm failed: ${stderr}`);\n }\n } catch (error) {\n throw new Error(`Failed to remove ${path}: ${error instanceof Error ? error.message : String(error)}`);\n }\n }\n },\n\n // Provider-specific typed getInstance method\n getInstance: (sandbox: ModalSandbox): ModalSandbox => {\n return sandbox;\n },\n\n }\n }\n});"],"mappings":"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","names":["process"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@computesdk/modal",
3
- "version": "1.4.5",
3
+ "version": "1.4.7",
4
4
  "description": "Modal provider for ComputeSDK",
5
5
  "author": "Garrison",
6
6
  "license": "MIT",
@@ -19,7 +19,7 @@
19
19
  ],
20
20
  "dependencies": {
21
21
  "modal": "^0.3.16",
22
- "computesdk": "1.8.5"
22
+ "computesdk": "1.8.7"
23
23
  },
24
24
  "keywords": [
25
25
  "modal",
@@ -47,7 +47,7 @@
47
47
  "tsup": "^8.0.0",
48
48
  "typescript": "^5.0.0",
49
49
  "vitest": "^1.0.0",
50
- "@computesdk/test-utils": "1.4.0"
50
+ "@computesdk/test-utils": "1.4.1"
51
51
  },
52
52
  "scripts": {
53
53
  "build": "tsup",