@elizaos/plugin-shell 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +352 -0
- package/dist/index.d.ts +106 -0
- package/dist/index.js +1071 -0
- package/dist/index.js.map +1 -0
- package/package.json +39 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/services/shellService.ts","../src/environment.ts","../src/utils/pathUtils.ts","../src/actions/executeCommand.ts","../src/actions/clearHistory.ts","../src/providers/shellHistoryProvider.ts","../src/index.ts"],"sourcesContent":["import {\n type IAgentRuntime,\n Service,\n logger,\n} from '@elizaos/core';\nimport spawn from 'cross-spawn';\nimport path from 'path';\nimport { loadShellConfig, type ShellConfig } from '../environment';\nimport {\n validatePath,\n isSafeCommand,\n isForbiddenCommand,\n} from '../utils/pathUtils';\n\nexport interface CommandResult {\n success: boolean;\n stdout: string;\n stderr: string;\n exitCode: number | null;\n error?: string;\n executedIn: string;\n}\n\nexport interface CommandHistoryEntry {\n command: string;\n stdout: string;\n stderr: string;\n exitCode: number | null;\n timestamp: number;\n workingDirectory: string;\n fileOperations?: FileOperation[];\n}\n\nexport interface FileOperation {\n type: 'create' | 'write' | 'read' | 'delete' | 'mkdir' | 'move' | 'copy';\n target: string;\n secondaryTarget?: string; // For move/copy operations\n}\n\nexport class ShellService extends Service {\n public static serviceType = 'shell';\n private shellConfig: ShellConfig;\n private currentDirectory: string;\n private commandHistory: Map<string, CommandHistoryEntry[]>; // conversationId -> history\n private maxHistoryPerConversation = 100;\n\n constructor(runtime: IAgentRuntime) {\n super();\n this.runtime = runtime;\n this.shellConfig = loadShellConfig();\n this.currentDirectory = this.shellConfig.allowedDirectory;\n this.commandHistory = new Map();\n }\n\n static async start(runtime: IAgentRuntime): Promise<ShellService> {\n const instance = new ShellService(runtime);\n logger.info('Shell service initialized with history tracking');\n return instance;\n }\n\n async stop(): Promise<void> {\n // Cleanup if needed\n logger.info('Shell service stopped');\n }\n\n get capabilityDescription(): string {\n return 'Execute shell commands within a restricted directory with history tracking';\n }\n\n /**\n * Executes a shell command within the allowed directory\n * @param command The command to execute\n * @param conversationId Optional conversation ID for history tracking\n * @returns The command execution result\n */\n async executeCommand(command: string, conversationId?: string): Promise<CommandResult> {\n // Check if shell is enabled\n if (!this.shellConfig.enabled) {\n return {\n success: false,\n stdout: '',\n stderr: 'Shell plugin is disabled. Set SHELL_ENABLED=true to enable.',\n exitCode: 1,\n error: 'Shell plugin disabled',\n executedIn: this.currentDirectory,\n };\n }\n\n // Basic command validation\n if (!command || typeof command !== 'string') {\n return {\n success: false,\n stdout: '',\n stderr: 'Invalid command',\n exitCode: 1,\n error: 'Command must be a non-empty string',\n executedIn: this.currentDirectory,\n };\n }\n\n const trimmedCommand = command.trim();\n\n // Check for dangerous patterns\n if (!isSafeCommand(trimmedCommand)) {\n return {\n success: false,\n stdout: '',\n stderr: 'Command contains forbidden patterns',\n exitCode: 1,\n error: 'Security policy violation',\n executedIn: this.currentDirectory,\n };\n }\n\n // Check for forbidden commands\n if (isForbiddenCommand(trimmedCommand, this.shellConfig.forbiddenCommands)) {\n return {\n success: false,\n stdout: '',\n stderr: `Command is forbidden by security policy`,\n exitCode: 1,\n error: 'Forbidden command',\n executedIn: this.currentDirectory,\n };\n }\n\n // Handle cd command specially to track directory changes\n if (trimmedCommand.startsWith('cd ')) {\n const result = await this.handleCdCommand(trimmedCommand);\n this.addToHistory(conversationId, trimmedCommand, result);\n return result;\n }\n\n // Execute the command\n const result = await this.runCommand(trimmedCommand);\n \n // Track file operations if successful\n if (result.success) {\n const fileOps = this.detectFileOperations(trimmedCommand, this.currentDirectory);\n if (fileOps && conversationId) {\n this.addToHistory(conversationId, trimmedCommand, result, fileOps);\n } else {\n this.addToHistory(conversationId, trimmedCommand, result);\n }\n } else {\n this.addToHistory(conversationId, trimmedCommand, result);\n }\n \n return result;\n }\n\n /**\n * Handles the cd command to change directory within allowed bounds\n * @param command The cd command\n * @returns The command result\n */\n private async handleCdCommand(command: string): Promise<CommandResult> {\n const parts = command.split(/\\s+/);\n if (parts.length < 2) {\n // cd without arguments goes to allowed directory\n this.currentDirectory = this.shellConfig.allowedDirectory;\n return {\n success: true,\n stdout: `Changed directory to: ${this.currentDirectory}`,\n stderr: '',\n exitCode: 0,\n executedIn: this.currentDirectory,\n };\n }\n\n const targetPath = parts.slice(1).join(' ');\n const validatedPath = validatePath(\n targetPath,\n this.shellConfig.allowedDirectory,\n this.currentDirectory\n );\n\n if (!validatedPath) {\n return {\n success: false,\n stdout: '',\n stderr: 'Cannot navigate outside allowed directory',\n exitCode: 1,\n error: 'Permission denied',\n executedIn: this.currentDirectory,\n };\n }\n\n // Update current directory\n this.currentDirectory = validatedPath;\n return {\n success: true,\n stdout: `Changed directory to: ${this.currentDirectory}`,\n stderr: '',\n exitCode: 0,\n executedIn: this.currentDirectory,\n };\n }\n\n /**\n * Runs a command using cross-spawn\n * @param command The command to run\n * @returns The command result\n */\n private async runCommand(command: string): Promise<CommandResult> {\n return new Promise((resolve) => {\n // For complex commands with redirects or quotes, we need to use shell\n const useShell = command.includes('>') || command.includes('<') || command.includes('|');\n \n let cmd: string;\n let args: string[];\n \n if (useShell) {\n // Use sh -c for commands with redirects/pipes\n cmd = 'sh';\n args = ['-c', command];\n logger.info(`Executing shell command: sh -c \"${command}\" in ${this.currentDirectory}`);\n } else {\n // For simple commands, split and execute directly\n const parts = command.split(/\\s+/);\n cmd = parts[0];\n args = parts.slice(1);\n logger.info(`Executing command: ${cmd} ${args.join(' ')} in ${this.currentDirectory}`);\n }\n\n let stdout = '';\n let stderr = '';\n let timedOut = false;\n\n // Spawn the process\n const child = spawn(cmd, args, {\n cwd: this.currentDirectory,\n env: process.env,\n // Only use shell: false for direct commands, not for sh -c\n shell: false,\n });\n\n // Set timeout\n const timeout = setTimeout(() => {\n timedOut = true;\n child.kill('SIGTERM');\n // Force kill after 5 seconds if process doesn't terminate\n setTimeout(() => {\n if (!child.killed) {\n child.kill('SIGKILL');\n }\n }, 5000);\n }, this.shellConfig.timeout);\n\n // Capture stdout\n if (child.stdout) {\n child.stdout.on('data', (data) => {\n stdout += data.toString();\n });\n }\n\n // Capture stderr\n if (child.stderr) {\n child.stderr.on('data', (data) => {\n stderr += data.toString();\n });\n }\n\n // Handle process exit\n child.on('exit', (code) => {\n clearTimeout(timeout);\n\n if (timedOut) {\n resolve({\n success: false,\n stdout,\n stderr: stderr + '\\nCommand timed out',\n exitCode: code,\n error: 'Command execution timeout',\n executedIn: this.currentDirectory,\n });\n return;\n }\n\n resolve({\n success: code === 0,\n stdout,\n stderr,\n exitCode: code,\n executedIn: this.currentDirectory,\n });\n });\n\n // Handle spawn errors\n child.on('error', (err) => {\n clearTimeout(timeout);\n resolve({\n success: false,\n stdout,\n stderr: err.message,\n exitCode: 1,\n error: 'Failed to execute command',\n executedIn: this.currentDirectory,\n });\n });\n });\n }\n\n /**\n * Adds a command to the history\n */\n private addToHistory(\n conversationId: string | undefined, \n command: string, \n result: CommandResult,\n fileOperations?: FileOperation[]\n ): void {\n if (!conversationId) return;\n\n const historyEntry: CommandHistoryEntry = {\n command,\n stdout: result.stdout,\n stderr: result.stderr,\n exitCode: result.exitCode,\n timestamp: Date.now(),\n workingDirectory: result.executedIn,\n fileOperations\n };\n\n if (!this.commandHistory.has(conversationId)) {\n this.commandHistory.set(conversationId, []);\n }\n\n const history = this.commandHistory.get(conversationId)!;\n history.push(historyEntry);\n\n // Trim history if it exceeds max length\n if (history.length > this.maxHistoryPerConversation) {\n history.shift();\n }\n }\n\n /**\n * Detects file operations from a command\n */\n private detectFileOperations(command: string, cwd: string): FileOperation[] | undefined {\n const operations: FileOperation[] = [];\n const parts = command.trim().split(/\\s+/);\n const cmd = parts[0].toLowerCase();\n\n // File creation/writing\n if (cmd === 'touch' && parts.length > 1) {\n operations.push({\n type: 'create',\n target: this.resolvePath(parts[1], cwd)\n });\n } else if (cmd === 'echo' && command.includes('>')) {\n const match = command.match(/>\\s*([^\\s]+)$/);\n if (match) {\n operations.push({\n type: 'write',\n target: this.resolvePath(match[1], cwd)\n });\n }\n } else if (cmd === 'mkdir' && parts.length > 1) {\n operations.push({\n type: 'mkdir',\n target: this.resolvePath(parts[1], cwd)\n });\n } else if (cmd === 'cat' && parts.length > 1 && !command.includes('>')) {\n operations.push({\n type: 'read',\n target: this.resolvePath(parts[1], cwd)\n });\n } else if (cmd === 'mv' && parts.length > 2) {\n operations.push({\n type: 'move',\n target: this.resolvePath(parts[1], cwd),\n secondaryTarget: this.resolvePath(parts[2], cwd)\n });\n } else if (cmd === 'cp' && parts.length > 2) {\n operations.push({\n type: 'copy',\n target: this.resolvePath(parts[1], cwd),\n secondaryTarget: this.resolvePath(parts[2], cwd)\n });\n }\n\n return operations.length > 0 ? operations : undefined;\n }\n\n /**\n * Resolves a path relative to the current working directory\n */\n private resolvePath(filePath: string, cwd: string): string {\n if (path.isAbsolute(filePath)) {\n return filePath;\n }\n return path.join(cwd, filePath);\n }\n\n /**\n * Gets command history for a conversation\n */\n getCommandHistory(conversationId: string, limit?: number): CommandHistoryEntry[] {\n const history = this.commandHistory.get(conversationId) || [];\n if (limit && limit > 0) {\n return history.slice(-limit);\n }\n return history;\n }\n\n /**\n * Clears command history for a conversation\n */\n clearCommandHistory(conversationId: string): void {\n this.commandHistory.delete(conversationId);\n logger.info(`Cleared command history for conversation: ${conversationId}`);\n }\n\n /**\n * Gets the current working directory\n * @param conversationId Optional conversation ID to get conversation-specific directory\n * @returns The current directory path\n */\n getCurrentDirectory(_conversationId?: string): string {\n // For now, we use a global current directory\n // Could be enhanced to track per-conversation directories\n return this.currentDirectory;\n }\n\n /**\n * Gets the allowed directory\n * @returns The allowed directory path\n */\n getAllowedDirectory(): string {\n return this.shellConfig.allowedDirectory;\n }\n} ","import { logger } from '@elizaos/core';\nimport joi from 'joi';\nimport path from 'path';\nimport fs from 'fs';\n\n/**\n * Shell plugin environment configuration\n */\nexport interface ShellConfig {\n enabled: boolean;\n allowedDirectory: string;\n timeout: number;\n forbiddenCommands: string[];\n}\n\n// Environment validation schema\nconst configSchema = joi.object({\n enabled: joi.boolean().required(),\n allowedDirectory: joi.string().when('enabled', {\n is: true,\n then: joi.required(),\n otherwise: joi.optional(),\n }),\n timeout: joi.number().positive().default(30000),\n forbiddenCommands: joi.array().items(joi.string()).required(),\n});\n\n/**\n * Default forbidden commands for safety\n */\nconst DEFAULT_FORBIDDEN_COMMANDS = [\n 'rm -rf /', // Only block dangerous rm commands, not all rm\n 'rmdir',\n 'chmod 777', // Only block dangerous chmod, not all chmod\n 'chown',\n 'chgrp',\n 'shutdown',\n 'reboot',\n 'halt',\n 'poweroff',\n 'kill -9', // Only block force kill, not all kill\n 'killall',\n 'pkill',\n 'sudo rm -rf', // Block dangerous sudo commands\n 'su',\n 'passwd',\n 'useradd',\n 'userdel',\n 'groupadd',\n 'groupdel',\n 'format',\n 'fdisk',\n 'mkfs',\n 'dd if=/dev/zero', // Only block dangerous dd\n 'shred',\n ':(){:|:&};:', // Fork bomb\n];\n\n/**\n * Loads and validates the shell plugin configuration\n * @returns The validated configuration\n */\nexport function loadShellConfig(): ShellConfig {\n const enabled = process.env.SHELL_ENABLED === 'true';\n const allowedDirectory = process.env.SHELL_ALLOWED_DIRECTORY || process.cwd();\n const timeout = parseInt(process.env.SHELL_TIMEOUT || '30000', 10);\n \n // Parse forbidden commands\n const customForbidden = process.env.SHELL_FORBIDDEN_COMMANDS\n ? process.env.SHELL_FORBIDDEN_COMMANDS.split(',').map((cmd) => cmd.trim())\n : [];\n \n // Combine default and custom forbidden commands\n const forbiddenCommands = [...new Set([...DEFAULT_FORBIDDEN_COMMANDS, ...customForbidden])];\n\n const config: ShellConfig = {\n enabled,\n allowedDirectory,\n timeout,\n forbiddenCommands,\n };\n\n // Validate configuration\n const { error, value } = configSchema.validate(config);\n if (error) {\n throw new Error(`Shell plugin configuration error: ${error.message}`);\n }\n\n // Additional validation for allowed directory\n if (enabled && allowedDirectory) {\n try {\n // Check if directory exists\n const stats = fs.statSync(allowedDirectory);\n if (!stats.isDirectory()) {\n throw new Error(`SHELL_ALLOWED_DIRECTORY is not a directory: ${allowedDirectory}`);\n }\n \n // Resolve to absolute path\n value.allowedDirectory = path.resolve(allowedDirectory);\n \n logger.info(`Shell plugin enabled with allowed directory: ${value.allowedDirectory}`);\n } catch (error: any) {\n if (error.code === 'ENOENT') {\n throw new Error(`SHELL_ALLOWED_DIRECTORY does not exist: ${allowedDirectory}`);\n }\n throw error;\n }\n }\n\n if (!enabled) {\n logger.info('Shell plugin is disabled. Set SHELL_ENABLED=true to enable.');\n }\n\n return value as ShellConfig;\n} ","import path from 'path';\nimport { logger } from '@elizaos/core';\n\n/**\n * Normalizes a path and ensures it's within the allowed directory\n * @param commandPath The path from the command\n * @param allowedDir The allowed directory\n * @param currentDir The current working directory\n * @returns The normalized absolute path or null if invalid\n */\nexport function validatePath(\n commandPath: string,\n allowedDir: string,\n currentDir: string\n): string | null {\n try {\n // Resolve the path relative to current directory\n const resolvedPath = path.resolve(currentDir, commandPath);\n const normalizedPath = path.normalize(resolvedPath);\n const normalizedAllowed = path.normalize(allowedDir);\n\n // Check if the resolved path is within the allowed directory\n if (!normalizedPath.startsWith(normalizedAllowed)) {\n logger.warn(\n `Path validation failed: ${normalizedPath} is outside allowed directory ${normalizedAllowed}`\n );\n return null;\n }\n\n return normalizedPath;\n } catch (error) {\n logger.error('Error validating path:', error);\n return null;\n }\n}\n\n/**\n * Checks if a command contains path traversal attempts or dangerous patterns\n * @param command The command to check\n * @returns true if the command appears safe, false if it contains dangerous patterns\n */\nexport function isSafeCommand(command: string): boolean {\n // Check for path traversal patterns\n const pathTraversalPatterns = [\n /\\.\\.\\//g, // ../\n /\\.\\.\\\\/g, // ..\\\n /\\/\\.\\./g, // /..\n /\\\\\\.\\./g, // \\..\n ];\n\n // Check for dangerous command patterns (but allow safe file operations)\n const dangerousPatterns = [\n /\\$\\(/g, // Command substitution $(\n /`[^']*`/g, // Command substitution ` (but allow in quotes)\n /\\|\\s*sudo/g, // Pipe to sudo\n /;\\s*sudo/g, // Chain with sudo\n /&\\s*&/g, // && chaining\n /\\|\\s*\\|/g, // || chaining\n ];\n\n // First check for path traversal\n for (const pattern of pathTraversalPatterns) {\n if (pattern.test(command)) {\n logger.warn(`Path traversal detected in command: ${command}`);\n return false;\n }\n }\n\n // Then check for dangerous command patterns\n for (const pattern of dangerousPatterns) {\n if (pattern.test(command)) {\n logger.warn(`Dangerous pattern detected in command: ${command}`);\n return false;\n }\n }\n\n // Allow single pipes and redirects for file operations\n // but block multiple pipes or complex chains\n const pipeCount = (command.match(/\\|/g) || []).length;\n if (pipeCount > 1) {\n logger.warn(`Multiple pipes detected in command: ${command}`);\n return false;\n }\n\n return true;\n}\n\n/**\n * Extracts the base command from a full command string\n * @param fullCommand The full command string\n * @returns The base command\n */\nexport function extractBaseCommand(fullCommand: string): string {\n // Split by space and get the first part\n const parts = fullCommand.trim().split(/\\s+/);\n return parts[0] || '';\n}\n\n/**\n * Checks if a command is in the forbidden list\n * @param command The command to check\n * @param forbiddenCommands List of forbidden commands/patterns\n * @returns true if the command is forbidden\n */\nexport function isForbiddenCommand(\n command: string,\n forbiddenCommands: string[]\n): boolean {\n const normalizedCommand = command.trim().toLowerCase();\n \n // Check each forbidden pattern\n return forbiddenCommands.some((forbidden) => {\n const forbiddenLower = forbidden.toLowerCase();\n \n // Check if the command starts with the forbidden pattern\n if (normalizedCommand.startsWith(forbiddenLower)) {\n return true;\n }\n \n // Also check if it's the exact base command for single-word forbidden commands\n if (!forbidden.includes(' ')) {\n const baseCommand = extractBaseCommand(command);\n if (baseCommand.toLowerCase() === forbiddenLower) {\n return true;\n }\n }\n \n return false;\n });\n} ","import {\n type Action,\n type ActionExample,\n type Content,\n type HandlerCallback,\n type IAgentRuntime,\n type Memory,\n ModelType,\n type State,\n composePromptFromState,\n parseJSONObjectFromText,\n logger,\n} from '@elizaos/core';\nimport { ShellService } from '../services/shellService';\n\n/**\n * Template for extracting command from user input\n */\nexport const commandExtractionTemplate = `# Extracting shell command from request\n{{recentMessages}}\n\n# Instructions: {{senderName}} wants to execute a shell command. Extract the COMPLETE shell command they want to run.\n\nIMPORTANT: \n1. Always return the FULL executable shell command, not just the content or partial command.\n2. If the user mentions installing something, create the appropriate brew/npm/apt command.\n3. If the user directly provides a command (like \"brew install X\"), use it exactly as provided.\n4. ALWAYS extract a command if the user is asking for ANY kind of system operation.\n\nCommon patterns:\n- \"run ls -la\" -> command: \"ls -la\"\n- \"execute npm test\" -> command: \"npm test\"\n- \"show me the files\" or \"list files\" -> command: \"ls -la\"\n- \"what's in this directory\" -> command: \"ls -la\"\n- \"check git status\" -> command: \"git status\"\n- \"navigate to src folder\" -> command: \"cd src\"\n- \"create a file called test.txt\" -> command: \"touch test.txt\"\n- \"write hello world to a file\" -> command: \"echo 'hello world' > file.txt\"\n- \"create hello.js with javascript code\" -> command: \"echo 'console.log(\\\"Hello, World!\\\");' > hello.js\"\n- \"create hello_world.py and write a python hello world script inside\" -> command: \"echo 'print(\\\"Hello, World!\\\")' > hello_world.py\"\n- \"make a new directory\" -> command: \"mkdir newdir\"\n- \"list files inside your filesystem\" -> command: \"ls -la\"\n- \"install orbstack\" or \"brew install orbstack\" -> command: \"brew install orbstack\"\n- \"install mullvad vpn\" -> command: \"brew install --cask mullvad-vpn\"\n- \"get system info\" -> command: \"system_profiler SPHardwareDataType\"\n- \"check memory usage\" -> command: \"vm_stat\"\n- \"install package\" -> command: \"brew install <package>\"\n\nSpecial cases:\n- \"Run it in your shell\" or \"execute it\" -> Extract the command from previous context\n- \"Install these\" -> Look for package names in previous messages\n- Direct commands should be used exactly as provided\n\nKey rules:\n1. For file creation with content, use: echo 'content' > filename\n2. For listing files, use: ls -la (not just ls)\n3. Always include the echo command when writing to files\n4. Include all flags and arguments\n5. When user says \"run it\", \"execute it\", or similar, they want you to run the command\n\nYour response must be formatted as a JSON block:\n\\`\\`\\`json\n{\n \"command\": \"<complete shell command to execute>\"\n}\n\\`\\`\\`\n`;\n\n/**\n * Extracts the command from the message\n */\nconst extractCommand = async (\n runtime: IAgentRuntime,\n _message: Memory,\n state: State\n): Promise<{ command: string } | null> => {\n const prompt = composePromptFromState({\n state,\n template: commandExtractionTemplate,\n });\n\n for (let i = 0; i < 3; i++) {\n const response = await runtime.useModel(ModelType.TEXT_SMALL, {\n prompt,\n });\n\n const parsedResponse = parseJSONObjectFromText(response);\n if (parsedResponse?.command) {\n return { command: parsedResponse.command };\n }\n }\n return null;\n};\n\nexport const executeCommand: Action = {\n name: 'EXECUTE_COMMAND',\n similes: [\n 'RUN_COMMAND',\n 'SHELL_COMMAND',\n 'TERMINAL_COMMAND',\n 'EXEC',\n 'RUN',\n 'EXECUTE',\n 'CREATE_FILE',\n 'WRITE_FILE',\n 'MAKE_FILE',\n 'INSTALL',\n 'BREW_INSTALL',\n 'NPM_INSTALL',\n 'APT_INSTALL',\n ],\n description:\n 'Execute ANY shell command in the terminal. Use this to run ANY command including: brew install, npm install, apt-get, system commands, file operations (create, write, delete), navigate directories, execute scripts, or perform any other shell operation. I CAN and SHOULD execute commands when asked. This includes brew, npm, git, ls, cd, echo, touch, cat, mkdir, system_profiler, and literally ANY other terminal command.',\n validate: async (runtime: IAgentRuntime, message: Memory, _state: State) => {\n // Check if shell service is available\n const shellService = runtime.getService<ShellService>('shell');\n if (!shellService) {\n return false;\n }\n \n // This action should be used for ANY command execution request\n const text = message.content.text?.toLowerCase() || '';\n const commandKeywords = [\n 'run', 'execute', 'command', 'shell', 'install', 'brew', 'npm',\n 'create', 'file', 'directory', 'folder', 'list', 'show',\n 'system', 'info', 'check', 'status', 'cd', 'ls', 'mkdir',\n 'echo', 'cat', 'touch', 'git', 'build', 'test'\n ];\n \n // Be very permissive - if any command-related keyword is found, this action is valid\n const hasCommandKeyword = commandKeywords.some(keyword => text.includes(keyword));\n \n // Also check for direct commands\n const hasDirectCommand = /^(brew|npm|apt|git|ls|cd|echo|cat|touch|mkdir|rm|mv|cp)\\s/i.test(message.content.text || '');\n \n return hasCommandKeyword || hasDirectCommand;\n },\n handler: async (\n runtime: IAgentRuntime,\n message: Memory,\n state: State,\n _options: any,\n callback: HandlerCallback\n ) => {\n const shellService = runtime.getService<ShellService>('shell');\n \n if (!shellService) {\n await callback({\n text: 'Shell service is not available.',\n source: message.content.source,\n });\n return;\n }\n\n // Extract command from message\n const commandInfo = await extractCommand(runtime, message, state);\n if (!commandInfo?.command) {\n logger.error('Failed to extract command from message:', message.content.text);\n await callback({\n text: \"I couldn't understand which command you want to execute. Please specify a shell command.\",\n source: message.content.source,\n });\n return;\n }\n\n logger.info(`User request: \"${message.content.text}\"`);\n logger.info(`Extracted command: \"${commandInfo.command}\"`);\n\n try {\n // Get conversation ID for history tracking\n const conversationId = message.roomId || message.agentId;\n \n // Execute the command with conversation tracking\n const result = await shellService.executeCommand(commandInfo.command, conversationId);\n \n // Format the response\n let responseText = '';\n \n if (result.success) {\n responseText = `Command executed successfully in ${result.executedIn}\\n\\n`;\n if (result.stdout) {\n responseText += `Output:\\n\\`\\`\\`\\n${result.stdout}\\n\\`\\`\\``;\n } else {\n responseText += 'Command completed with no output.';\n }\n } else {\n responseText = `Command failed with exit code ${result.exitCode} in ${result.executedIn}\\n\\n`;\n if (result.error) {\n responseText += `Error: ${result.error}\\n`;\n }\n if (result.stderr) {\n responseText += `\\nError output:\\n\\`\\`\\`\\n${result.stderr}\\n\\`\\`\\``;\n }\n }\n\n const response: Content = {\n text: responseText,\n source: message.content.source,\n };\n\n await callback(response);\n } catch (error) {\n logger.error('Error executing command:', error);\n await callback({\n text: `Failed to execute command: ${error instanceof Error ? error.message : 'Unknown error'}`,\n source: message.content.source,\n });\n }\n },\n examples: [\n [\n {\n name: '{{name1}}',\n content: {\n text: 'run ls -la',\n },\n },\n {\n name: '{{name2}}',\n content: {\n text: \"I'll execute that command for you.\",\n actions: ['EXECUTE_COMMAND'],\n },\n },\n ],\n [\n {\n name: '{{name1}}',\n content: {\n text: 'show me what files are in this directory',\n },\n },\n {\n name: '{{name2}}',\n content: {\n text: \"I'll list the files in the current directory.\",\n actions: ['EXECUTE_COMMAND'],\n },\n },\n ],\n [\n {\n name: '{{name1}}',\n content: {\n text: 'navigate to the src folder',\n },\n },\n {\n name: '{{name2}}',\n content: {\n text: \"I'll change to the src directory.\",\n actions: ['EXECUTE_COMMAND'],\n },\n },\n ],\n [\n {\n name: '{{name1}}',\n content: {\n text: 'check the git status',\n },\n },\n {\n name: '{{name2}}',\n content: {\n text: \"I'll check the git repository status.\",\n actions: ['EXECUTE_COMMAND'],\n },\n },\n ],\n [\n {\n name: '{{name1}}',\n content: {\n text: 'create a file called hello.txt',\n },\n },\n {\n name: '{{name2}}',\n content: {\n text: \"I'll create hello.txt for you.\",\n actions: ['EXECUTE_COMMAND'],\n },\n },\n ],\n [\n {\n name: '{{name1}}',\n content: {\n text: 'create hello_world.py and write a python hello world script inside',\n },\n },\n {\n name: '{{name2}}',\n content: {\n text: \"I'll create hello_world.py with a Python hello world script.\",\n actions: ['EXECUTE_COMMAND'],\n },\n },\n ],\n [\n {\n name: '{{name1}}',\n content: {\n text: 'write some content to a file',\n },\n },\n {\n name: '{{name2}}',\n content: {\n text: \"I'll write content to a file for you.\",\n actions: ['EXECUTE_COMMAND'],\n },\n },\n ],\n [\n {\n name: '{{name1}}',\n content: {\n text: 'brew install orbstack',\n },\n },\n {\n name: '{{name2}}',\n content: {\n text: \"I'll install orbstack using brew.\",\n actions: ['EXECUTE_COMMAND'],\n },\n },\n ],\n [\n {\n name: '{{name1}}',\n content: {\n text: 'install mullvad vpn',\n },\n },\n {\n name: '{{name2}}',\n content: {\n text: \"I'll install Mullvad VPN for you.\",\n actions: ['EXECUTE_COMMAND'],\n },\n },\n ],\n [\n {\n name: '{{name1}}',\n content: {\n text: 'run the command brew install --cask docker',\n },\n },\n {\n name: '{{name2}}',\n content: {\n text: \"I'll run that brew install command for you.\",\n actions: ['EXECUTE_COMMAND'],\n },\n },\n ],\n ] as ActionExample[][],\n} as Action;\n\nexport default executeCommand; ","import {\n type Action,\n type ActionExample,\n type Content,\n type HandlerCallback,\n type IAgentRuntime,\n type Memory,\n type State,\n logger,\n} from '@elizaos/core';\nimport { ShellService } from '../services/shellService';\n\nexport const clearHistory: Action = {\n name: 'CLEAR_SHELL_HISTORY',\n similes: ['RESET_SHELL', 'CLEAR_TERMINAL', 'CLEAR_HISTORY', 'RESET_HISTORY'],\n description: 'Clears the recorded history of shell commands for the current conversation',\n validate: async (runtime: IAgentRuntime, message: Memory, _state: State) => {\n // Check if shell service is available\n const shellService = runtime.getService<ShellService>('shell');\n if (!shellService) {\n return false;\n }\n \n // Check if message contains clear history intent\n const text = message.content.text?.toLowerCase() || '';\n const clearKeywords = ['clear', 'reset', 'delete', 'remove', 'clean'];\n const historyKeywords = ['history', 'terminal', 'shell', 'command'];\n \n // Must have at least one clear keyword and one history keyword\n const hasClearKeyword = clearKeywords.some(keyword => text.includes(keyword));\n const hasHistoryKeyword = historyKeywords.some(keyword => text.includes(keyword));\n \n return hasClearKeyword && hasHistoryKeyword;\n },\n handler: async (\n runtime: IAgentRuntime,\n message: Memory,\n _state: State,\n _options: any,\n callback: HandlerCallback\n ) => {\n const shellService = runtime.getService<ShellService>('shell');\n \n if (!shellService) {\n await callback({\n text: 'Shell service is not available.',\n source: message.content.source,\n });\n return;\n }\n\n try {\n // Get conversation ID\n const conversationId = message.roomId || message.agentId;\n \n // Clear the history\n shellService.clearCommandHistory(conversationId);\n \n logger.info(`Cleared shell history for conversation: ${conversationId}`);\n\n const response: Content = {\n text: 'Shell command history has been cleared.',\n source: message.content.source,\n };\n\n await callback(response);\n } catch (error) {\n logger.error('Error clearing shell history:', error);\n await callback({\n text: `Failed to clear shell history: ${error instanceof Error ? error.message : 'Unknown error'}`,\n source: message.content.source,\n });\n }\n },\n examples: [\n [\n {\n name: '{{name1}}',\n content: {\n text: 'clear my shell history',\n },\n },\n {\n name: '{{name2}}',\n content: {\n text: 'Shell command history has been cleared.',\n actions: ['CLEAR_SHELL_HISTORY'],\n },\n },\n ],\n [\n {\n name: '{{name1}}',\n content: {\n text: 'reset the terminal history',\n },\n },\n {\n name: '{{name2}}',\n content: {\n text: 'Shell command history has been cleared.',\n actions: ['CLEAR_SHELL_HISTORY'],\n },\n },\n ],\n [\n {\n name: '{{name1}}',\n content: {\n text: 'delete command history',\n },\n },\n {\n name: '{{name2}}',\n content: {\n text: 'Shell command history has been cleared.',\n actions: ['CLEAR_SHELL_HISTORY'],\n },\n },\n ],\n ] as ActionExample[][],\n} as Action;\n\nexport default clearHistory; ","import {\n type IAgentRuntime,\n type Memory,\n type Provider,\n type State,\n addHeader,\n logger,\n} from '@elizaos/core';\nimport { ShellService } from '../services/shellService';\n\nconst MAX_OUTPUT_LENGTH = 8000; // Max length before truncating\nconst TRUNCATE_SEGMENT_LENGTH = 4000; // Length of head/tail segments\n\nexport const shellHistoryProvider: Provider = {\n name: 'SHELL_HISTORY',\n description: 'Provides recent shell command history, current working directory, and file operations within the restricted environment',\n position: 99,\n get: async (runtime: IAgentRuntime, message: Memory, _state: State) => {\n const shellService = runtime.getService<ShellService>('shell');\n\n if (!shellService) {\n logger.warn('[shellHistoryProvider] Shell service not found');\n return {\n values: {\n shellHistory: 'Shell service is not available',\n currentWorkingDirectory: 'N/A',\n allowedDirectory: 'N/A'\n },\n text: addHeader('# Shell Status', 'Shell service is not available'),\n data: { history: [], cwd: 'N/A', allowedDir: 'N/A' }\n };\n }\n\n // Get conversation ID from message context\n const conversationId = message.roomId || message.agentId;\n \n // Get history for this conversation (last 10 commands)\n const history = shellService.getCommandHistory(conversationId, 10);\n const cwd = shellService.getCurrentDirectory(conversationId);\n const allowedDir = shellService.getAllowedDirectory();\n\n let historyText = 'No commands in history.';\n if (history.length > 0) {\n historyText = history.map((entry) => {\n let entryStr = `[${new Date(entry.timestamp).toISOString()}] ${entry.workingDirectory}> ${entry.command}`;\n \n // Truncate long outputs\n if (entry.stdout) {\n if (entry.stdout.length > MAX_OUTPUT_LENGTH) {\n entryStr += `\\n Output: ${entry.stdout.substring(0, TRUNCATE_SEGMENT_LENGTH)}\\n ... [TRUNCATED] ...\\n ${entry.stdout.substring(entry.stdout.length - TRUNCATE_SEGMENT_LENGTH)}`;\n } else {\n entryStr += `\\n Output: ${entry.stdout}`;\n }\n }\n\n if (entry.stderr) {\n if (entry.stderr.length > MAX_OUTPUT_LENGTH) {\n entryStr += `\\n Error: ${entry.stderr.substring(0, TRUNCATE_SEGMENT_LENGTH)}\\n ... [TRUNCATED] ...\\n ${entry.stderr.substring(entry.stderr.length - TRUNCATE_SEGMENT_LENGTH)}`;\n } else {\n entryStr += `\\n Error: ${entry.stderr}`;\n }\n }\n\n entryStr += `\\n Exit Code: ${entry.exitCode}`;\n\n // Add file operations if any\n if (entry.fileOperations && entry.fileOperations.length > 0) {\n entryStr += '\\n File Operations:';\n entry.fileOperations.forEach(op => {\n if (op.secondaryTarget) {\n entryStr += `\\n - ${op.type}: ${op.target} → ${op.secondaryTarget}`;\n } else {\n entryStr += `\\n - ${op.type}: ${op.target}`;\n }\n });\n }\n\n return entryStr;\n }).join('\\n\\n');\n }\n\n // Get recent file operations\n const recentFileOps = history\n .filter(entry => entry.fileOperations && entry.fileOperations.length > 0)\n .flatMap(entry => entry.fileOperations!)\n .slice(-5); // Last 5 file operations\n\n let fileOpsText = '';\n if (recentFileOps.length > 0) {\n fileOpsText = '\\n\\n' + addHeader('# Recent File Operations', \n recentFileOps.map(op => {\n if (op.secondaryTarget) {\n return `- ${op.type}: ${op.target} → ${op.secondaryTarget}`;\n }\n return `- ${op.type}: ${op.target}`;\n }).join('\\n')\n );\n }\n\n const text = `Current Directory: ${cwd}\nAllowed Directory: ${allowedDir}\n\n${addHeader('# Shell History (Last 10)', historyText)}${fileOpsText}`;\n\n return {\n values: {\n shellHistory: historyText,\n currentWorkingDirectory: cwd,\n allowedDirectory: allowedDir,\n recentFileOperations: recentFileOps\n },\n text,\n data: {\n history,\n cwd,\n allowedDir,\n fileOperations: recentFileOps\n }\n };\n }\n};\n\nexport default shellHistoryProvider; ","import { Plugin } from '@elizaos/core';\nimport { ShellService } from './services/shellService';\nimport { executeCommand, clearHistory } from './actions';\nimport { shellHistoryProvider } from './providers';\n\nexport const shellPlugin: Plugin = {\n name: 'shell',\n description: 'Execute shell commands within a restricted directory with history tracking',\n services: [ShellService],\n actions: [executeCommand, clearHistory],\n providers: [shellHistoryProvider],\n};\n\nexport default shellPlugin;\n\n// Export types and utilities for external use\nexport { type CommandResult, ShellService } from './services/shellService';\nexport { executeCommand } from './actions/executeCommand';\nexport { type ShellConfig, loadShellConfig } from './environment'; "],"mappings":"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","names":["logger","path","error","path","logger","logger","result","path","logger","logger","logger"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@elizaos/plugin-shell",
|
|
3
|
+
"version": "1.2.0",
|
|
4
|
+
"description": "Shell command execution plugin for ElizaOS with directory restrictions and history tracking",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"module": "dist/index.js",
|
|
8
|
+
"types": "dist/index.d.ts",
|
|
9
|
+
"scripts": {
|
|
10
|
+
"build": "tsup",
|
|
11
|
+
"test": "vitest run",
|
|
12
|
+
"test:watch": "vitest"
|
|
13
|
+
},
|
|
14
|
+
"keywords": ["eliza", "plugin", "shell", "terminal", "command", "history"],
|
|
15
|
+
"author": "elizaOS",
|
|
16
|
+
"license": "MIT",
|
|
17
|
+
"repository": {
|
|
18
|
+
"type": "git",
|
|
19
|
+
"url": "https://github.com/elizaos/eliza.git"
|
|
20
|
+
},
|
|
21
|
+
"dependencies": {
|
|
22
|
+
"@elizaos/core": "^1.2.0",
|
|
23
|
+
"cross-spawn": "^7.0.6",
|
|
24
|
+
"joi": "^17.13.3"
|
|
25
|
+
},
|
|
26
|
+
"devDependencies": {
|
|
27
|
+
"@types/cross-spawn": "^6.0.6",
|
|
28
|
+
"@types/node": "^20.11.16",
|
|
29
|
+
"tsup": "^8.0.1",
|
|
30
|
+
"typescript": "^5.3.3",
|
|
31
|
+
"vitest": "^1.2.1"
|
|
32
|
+
},
|
|
33
|
+
"files": [
|
|
34
|
+
"dist"
|
|
35
|
+
],
|
|
36
|
+
"publishConfig": {
|
|
37
|
+
"access": "public"
|
|
38
|
+
}
|
|
39
|
+
}
|