@computesdk/modal 1.2.2 → 1.2.3

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
@@ -171,10 +171,11 @@ var modal = (0, import_computesdk.createProvider)({
171
171
  );
172
172
  }
173
173
  },
174
- runCommand: async (modalSandbox, command, args = []) => {
174
+ runCommand: async (modalSandbox, command, args = [], options) => {
175
175
  const startTime = Date.now();
176
176
  try {
177
- const process2 = await modalSandbox.sandbox.exec([command, ...args], {
177
+ const { command: finalCommand, args: finalArgs, isBackground } = (0, import_computesdk.createBackgroundCommand)(command, args, options);
178
+ const process2 = await modalSandbox.sandbox.exec([finalCommand, ...finalArgs], {
178
179
  stdout: "pipe",
179
180
  stderr: "pipe"
180
181
  });
@@ -189,7 +190,10 @@ var modal = (0, import_computesdk.createProvider)({
189
190
  exitCode: exitCode || 0,
190
191
  executionTime: Date.now() - startTime,
191
192
  sandboxId: modalSandbox.sandboxId,
192
- provider: "modal"
193
+ provider: "modal",
194
+ isBackground,
195
+ // For background commands, we can't get a real PID, but we can indicate it's running
196
+ ...isBackground && { pid: -1 }
193
197
  };
194
198
  } catch (error) {
195
199
  return {
@@ -199,7 +203,9 @@ var modal = (0, import_computesdk.createProvider)({
199
203
  // Command not found exit code
200
204
  executionTime: Date.now() - startTime,
201
205
  sandboxId: modalSandbox.sandboxId,
202
- provider: "modal"
206
+ provider: "modal",
207
+ isBackground: false
208
+ // Error case, command didn't run as background
203
209
  };
204
210
  }
205
211
  },
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 } from 'computesdk';\nimport type { \n ExecutionResult, \n SandboxInfo, \n Runtime,\n CreateSandboxOptions,\n FileEntry\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 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[] = []): Promise<ExecutionResult> => {\n const startTime = Date.now();\n\n try {\n // Execute command using Modal's exec method with working pattern\n const process = await modalSandbox.sandbox.exec([command, ...args], {\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 };\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 };\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 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"]}
package/dist/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  // src/index.ts
2
- import { createProvider } from "computesdk";
2
+ import { createProvider, createBackgroundCommand } from "computesdk";
3
3
  import { App, Sandbox, initializeClient } from "modal";
4
4
  function detectRuntime(code) {
5
5
  if (code.includes("console.log") || code.includes("process.") || code.includes("require(") || code.includes("module.exports") || code.includes("__dirname") || code.includes("__filename") || code.includes("throw new Error") || // JavaScript error throwing
@@ -147,10 +147,11 @@ var modal = createProvider({
147
147
  );
148
148
  }
149
149
  },
150
- runCommand: async (modalSandbox, command, args = []) => {
150
+ runCommand: async (modalSandbox, command, args = [], options) => {
151
151
  const startTime = Date.now();
152
152
  try {
153
- const process2 = await modalSandbox.sandbox.exec([command, ...args], {
153
+ const { command: finalCommand, args: finalArgs, isBackground } = createBackgroundCommand(command, args, options);
154
+ const process2 = await modalSandbox.sandbox.exec([finalCommand, ...finalArgs], {
154
155
  stdout: "pipe",
155
156
  stderr: "pipe"
156
157
  });
@@ -165,7 +166,10 @@ var modal = createProvider({
165
166
  exitCode: exitCode || 0,
166
167
  executionTime: Date.now() - startTime,
167
168
  sandboxId: modalSandbox.sandboxId,
168
- provider: "modal"
169
+ provider: "modal",
170
+ isBackground,
171
+ // For background commands, we can't get a real PID, but we can indicate it's running
172
+ ...isBackground && { pid: -1 }
169
173
  };
170
174
  } catch (error) {
171
175
  return {
@@ -175,7 +179,9 @@ var modal = createProvider({
175
179
  // Command not found exit code
176
180
  executionTime: Date.now() - startTime,
177
181
  sandboxId: modalSandbox.sandboxId,
178
- provider: "modal"
182
+ provider: "modal",
183
+ isBackground: false
184
+ // Error case, command didn't run as background
179
185
  };
180
186
  }
181
187
  },
@@ -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 } from 'computesdk';\nimport type { \n ExecutionResult, \n SandboxInfo, \n Runtime,\n CreateSandboxOptions,\n FileEntry\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 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[] = []): Promise<ExecutionResult> => {\n const startTime = Date.now();\n\n try {\n // Execute command using Modal's exec method with working pattern\n const process = await modalSandbox.sandbox.exec([command, ...args], {\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 };\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 };\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 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"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@computesdk/modal",
3
- "version": "1.2.2",
3
+ "version": "1.2.3",
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.4.0"
22
+ "computesdk": "1.5.0"
23
23
  },
24
24
  "keywords": [
25
25
  "modal",