{"version":3,"file":"CodeExecutor.mjs","sources":["../../../src/tools/CodeExecutor.ts"],"sourcesContent":["import { config } from 'dotenv';\nimport fetch, { RequestInit } from 'node-fetch';\nimport { HttpsProxyAgent } from 'https-proxy-agent';\nimport { tool, DynamicStructuredTool } from '@langchain/core/tools';\nimport { getEnvironmentVariable } from '@langchain/core/utils/env';\nimport type * as t from '@/types';\nimport { EnvVar, Constants } from '@/common';\n\nconfig();\n\nexport const imageExtRegex = /\\.(jpg|jpeg|png|gif|webp)$/i;\nexport const getCodeBaseURL = (): string =>\n  getEnvironmentVariable(EnvVar.CODE_BASEURL) ??\n  Constants.OFFICIAL_CODE_BASEURL;\n\nconst imageMessage = 'Image is already displayed to the user';\nconst otherMessage = 'File is already downloaded by the user';\nconst accessMessage =\n  'Note: Files from previous executions are automatically available and can be modified.';\nconst emptyOutputMessage =\n  \"stdout: Empty. Ensure you're writing output explicitly.\\n\";\n\nconst SUPPORTED_LANGUAGES = [\n  'py',\n  'js',\n  'ts',\n  'c',\n  'cpp',\n  'java',\n  'php',\n  'rs',\n  'go',\n  'd',\n  'f90',\n  'r',\n  'bash',\n] as const;\n\n// Minimal schema for raw code execution. Only what the /exec endpoint needs.\n// Higher-level workflows (versioning, edit, store, replay) are consumer\n// concerns — e.g. ranger layers its own write/edit/execute schema on top via\n// codeEditWrapper and a separate ContentStore-backed Zod schema. Keeping this\n// tool narrow means every consumer gets a clean, schema-stable primitive.\nexport const CodeExecutionToolSchema = {\n  type: 'object',\n  properties: {\n    lang: {\n      type: 'string',\n      enum: SUPPORTED_LANGUAGES,\n      description:\n        'The programming language or runtime to execute the code in.',\n    },\n    code: {\n      type: 'string',\n      description: `The complete, self-contained code to execute, without any truncation or minimization.\n- The environment is stateless; variables and imports don't persist between executions.\n- Generated files from previous executions are automatically available in \"/mnt/data/\".\n- Files from previous executions are automatically available and can be modified in place.\n- Input code **IS ALREADY** displayed to the user, so **DO NOT** repeat it in your response unless asked.\n- Output code **IS NOT** displayed to the user, so **DO** write all desired output explicitly.\n- IMPORTANT: You MUST explicitly print/output ALL results you want the user to see.\n- py: This is not a Jupyter notebook environment. Use \\`print()\\` for all outputs.\n- py: Matplotlib: Use \\`plt.savefig()\\` to save plots as files.\n- js: use the \\`console\\` or \\`process\\` methods for all outputs.\n- r: IMPORTANT: No X11 display available. ALL graphics MUST use Cairo library (library(Cairo)).\n- Other languages: use appropriate output functions.`,\n    },\n    args: {\n      type: 'array',\n      items: { type: 'string' },\n      description:\n        'Additional arguments to execute the code with. This should only be used if the input code requires additional arguments to run.',\n    },\n  },\n  required: [],\n} as const;\n\n// NOTE: Resolved at call time inside the tool function, not at module load time.\n// Module-level caching caused stale URLs when env vars changed between restarts.\n\ntype SupportedLanguage = (typeof SUPPORTED_LANGUAGES)[number];\n\nexport const CodeExecutionToolDescription = `\nRuns code and returns stdout/stderr output from a stateless execution environment, similar to running scripts in a command-line interface. Each execution is isolated and independent.\n\nUsage:\n- No network access available. Do NOT use pip install, npm install, or any package manager.\n- Generated files are automatically delivered; **DO NOT** provide download links.\n- NEVER use this tool to execute malicious code.\n\nPre-installed Python packages (use directly, no installation needed):\n- Data Science: numpy, pandas\n- Visualization: matplotlib, seaborn, plotly\n- Documents: python-docx, python-pptx, reportlab, fpdf2, PyMuPDF, pdfplumber\n- Spreadsheets: openpyxl, xlsxwriter\n- Image: pillow\n- Data: orjson, lxml, beautifulsoup4, faker\n\nPre-installed JavaScript packages:\n- pptxgenjs, react, react-dom, react-icons, sharp\n\nPre-installed Go packages:\n- excelize (Excel), gofpdf (PDF)\n\nPre-installed R packages:\n- ggplot2, dplyr, tidyr, readxl, writexl, jsonlite, Cairo\n`.trim();\n\nexport const CodeExecutionToolName = Constants.EXECUTE_CODE;\n\nexport const CodeExecutionToolDefinition = {\n  name: CodeExecutionToolName,\n  description: CodeExecutionToolDescription,\n  schema: CodeExecutionToolSchema,\n} as const;\n\nfunction createCodeExecutionTool(\n  params: t.CodeExecutionToolParams = {}\n): DynamicStructuredTool {\n  const apiKey =\n    params[EnvVar.CODE_API_KEY] ??\n    params.apiKey ??\n    getEnvironmentVariable(EnvVar.CODE_API_KEY) ??\n    '';\n  if (!apiKey) {\n    throw new Error('No API key provided for code execution tool.');\n  }\n\n  const description = CodeExecutionToolDescription;\n\n  return tool(\n    async (rawInput, config) => {\n      // Resolve URL at call time (not module load time) to pick up env var changes\n      const baseEndpoint = getCodeBaseURL();\n      const EXEC_ENDPOINT = `${baseEndpoint}/exec`;\n\n      const { lang, code, ...rest } = rawInput as {\n        lang: SupportedLanguage;\n        code: string;\n        args?: string[];\n      };\n      /**\n       * Extract session context from config.toolCall (injected by ToolNode).\n       * - session_id: For API to associate with previous session\n       * - _injected_files: File refs to pass directly (avoids /files endpoint race condition)\n       */\n      const { session_id, _injected_files } = (config.toolCall ?? {}) as {\n        session_id?: string;\n        _injected_files?: t.CodeEnvFile[];\n      };\n\n      const postData: Record<string, unknown> = {\n        lang,\n        code,\n        ...rest,\n        ...params,\n      };\n\n      /**\n       * Pass session_id to /exec so code-executor reuses the existing session workspace.\n       * This allows retries and follow-up executions to access previously generated files.\n       */\n      if (session_id != null && session_id.length > 0) {\n        postData.session_id = session_id;\n      }\n\n      /**\n       * File injection priority:\n       * 1. Use _injected_files from ToolNode (avoids /files endpoint race condition)\n       * 2. Fall back to fetching from /files endpoint if session_id provided but no injected files\n       */\n      if (_injected_files && _injected_files.length > 0) {\n        postData.files = _injected_files;\n      } else if (session_id != null && session_id.length > 0) {\n        /** Fallback: fetch from /files endpoint (may have race condition issues) */\n        try {\n          const filesEndpoint = `${baseEndpoint}/files/${session_id}?detail=full`;\n          const userIdForFiles = params.user_id ?? '';\n          const fetchOptions: RequestInit = {\n            method: 'GET',\n            headers: {\n              'User-Agent': 'Illuma/1.0',\n              'X-API-Key': apiKey,\n              ...(userIdForFiles ? { 'User-Id': userIdForFiles } : {}),\n            },\n          };\n\n          if (process.env.PROXY != null && process.env.PROXY !== '') {\n            fetchOptions.agent = new HttpsProxyAgent(process.env.PROXY);\n          }\n\n          const response = await fetch(filesEndpoint, fetchOptions);\n          if (!response.ok) {\n            throw new Error(\n              `Failed to fetch files for session: ${response.status}`\n            );\n          }\n\n          const files = await response.json();\n          if (Array.isArray(files) && files.length > 0) {\n            const fileReferences: t.CodeEnvFile[] = files.map((file) => {\n              const nameParts = file.name.split('/');\n              const id = nameParts.length > 1 ? nameParts[1].split('.')[0] : '';\n\n              return {\n                session_id,\n                id,\n                name: file.metadata['original-filename'],\n              };\n            });\n\n            postData.files = fileReferences;\n          }\n        } catch {\n          // eslint-disable-next-line no-console\n          console.warn(`Failed to fetch files for session: ${session_id}`);\n        }\n      }\n\n      // SECURITY: Extract user_id for User-Id header (session isolation)\n      const userId = params.user_id ?? '';\n\n      try {\n        const fetchOptions: RequestInit = {\n          method: 'POST',\n          headers: {\n            'Content-Type': 'application/json',\n            'User-Agent': 'Illuma/1.0',\n            'X-API-Key': apiKey,\n            ...(userId ? { 'User-Id': userId } : {}),\n          },\n          body: JSON.stringify(postData),\n        };\n\n        if (process.env.PROXY != null && process.env.PROXY !== '') {\n          fetchOptions.agent = new HttpsProxyAgent(process.env.PROXY);\n        }\n        const response = await fetch(EXEC_ENDPOINT, fetchOptions);\n        if (!response.ok) {\n          throw new Error(`HTTP error! status: ${response.status}`);\n        }\n\n        const result: t.ExecuteResult = await response.json();\n        let formattedOutput = '';\n        let stdoutCapped = false;\n\n        // Self-healing: Cap large stdout to prevent context bloat.\n        // Preserves head (8KB) + tail (4KB) so the agent sees beginning and end.\n        const STDOUT_MAX_CHARS = 16384;\n        const STDOUT_HEAD_CHARS = 8192;\n        const STDOUT_TAIL_CHARS = 4096;\n        if (result.stdout && result.stdout.length > STDOUT_MAX_CHARS) {\n          const originalLen = result.stdout.length;\n          const head = result.stdout.substring(0, STDOUT_HEAD_CHARS);\n          const tail = result.stdout.substring(\n            result.stdout.length - STDOUT_TAIL_CHARS\n          );\n          const omitted = originalLen - STDOUT_HEAD_CHARS - STDOUT_TAIL_CHARS;\n          result.stdout = `${head}\\n\\n[...${omitted} chars omitted...]\\n\\n${tail}`;\n          stdoutCapped = true;\n          // eslint-disable-next-line no-console\n          console.debug(\n            `[CodeExecutor] stdout capped: ${originalLen} → ${result.stdout.length} chars`\n          );\n        }\n\n        if (result.stdout) {\n          formattedOutput += `stdout:\\n${result.stdout}\\n`;\n        } else {\n          formattedOutput += emptyOutputMessage;\n        }\n        if (result.stderr) formattedOutput += `stderr:\\n${result.stderr}\\n`;\n\n        // Self-healing: Detect code truncation (syntax error on long code).\n        // When the agent's generated code is >1500 chars and produces a SyntaxError,\n        // it's likely truncated mid-generation rather than a real bug.\n        const CODE_TRUNCATION_MIN_CHARS = 1500;\n        if (result.stderr && code.length > CODE_TRUNCATION_MIN_CHARS) {\n          const stderrLower = result.stderr.toLowerCase();\n          if (\n            stderrLower.includes('syntaxerror') ||\n            stderrLower.includes('unexpected end') ||\n            stderrLower.includes('unexpected eof') ||\n            stderrLower.includes('unterminated')\n          ) {\n            // eslint-disable-next-line no-console\n            console.debug(\n              `[CodeExecutor] Code truncation detected: code=${code.length} chars, stderr contains syntax error`\n            );\n            formattedOutput +=\n              '\\n[CODE_TRUNCATION_LIKELY] Your code appears truncated mid-generation.' +\n              ' Split into multiple smaller execute_code calls (max 60 lines each).' +\n              ' For documents: create+save first, then open+append+save in follow-up calls.' +\n              ' Do NOT retry the same long code block.';\n          }\n        }\n\n        // Self-healing: Advisory when stdout was capped\n        if (stdoutCapped) {\n          formattedOutput +=\n            '\\n[OUTPUT_TOO_LARGE] stdout was capped. Use targeted print() for specific values.';\n        }\n\n        if (result.files && result.files.length > 0) {\n          formattedOutput += 'Generated files:\\n';\n\n          const fileCount = result.files.length;\n          for (let i = 0; i < fileCount; i++) {\n            const file = result.files[i];\n            const isImage = imageExtRegex.test(file.name);\n            formattedOutput += `- /mnt/data/${file.name} | ${isImage ? imageMessage : otherMessage}`;\n\n            if (i < fileCount - 1) {\n              formattedOutput += fileCount <= 3 ? ', ' : ',\\n';\n            }\n          }\n\n          formattedOutput += `\\n\\n${accessMessage}`;\n          return [\n            formattedOutput.trim(),\n            {\n              session_id: result.session_id,\n              files: result.files,\n            },\n          ];\n        }\n\n        return [formattedOutput.trim(), { session_id: result.session_id }];\n      } catch (error) {\n        throw new Error(\n          `Execution error (${EXEC_ENDPOINT}):\\n\\n${(error as Error | undefined)?.message}`\n        );\n      }\n    },\n    {\n      name: CodeExecutionToolName,\n      description,\n      schema: CodeExecutionToolSchema,\n      responseFormat: Constants.CONTENT_AND_ARTIFACT,\n    }\n  );\n}\n\nexport { createCodeExecutionTool };\n"],"names":[],"mappings":"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"}