diff --git a/README.md b/README.md index b6f1949..21c6c85 100644 --- a/README.md +++ b/README.md @@ -191,6 +191,7 @@ Process a single prompt and exit (useful for scripting and automation): grok --prompt "show me the package.json file" grok -p "create a new file called example.js with a hello world function" grok --prompt "run npm test and show me the results" --directory /path/to/project +grok --prompt "complex task" --max-tool-rounds 50 # Limit tool usage for faster execution ``` This mode is particularly useful for: @@ -199,6 +200,27 @@ This mode is particularly useful for: - **Terminal benchmarks**: Perfect for tools like Terminal Bench that need non-interactive execution - **Batch processing**: Process multiple prompts programmatically +### Tool Execution Control + +By default, Grok CLI allows up to 400 tool execution rounds to handle complex multi-step tasks. You can control this behavior: + +```bash +# Limit tool rounds for faster execution on simple tasks +grok --max-tool-rounds 10 --prompt "show me the current directory" + +# Increase limit for very complex tasks (use with caution) +grok --max-tool-rounds 1000 --prompt "comprehensive code refactoring" + +# Works with all modes +grok --max-tool-rounds 20 # Interactive mode +grok git commit-and-push --max-tool-rounds 30 # Git commands +``` + +**Use Cases**: +- **Fast responses**: Lower limits (10-50) for simple queries +- **Complex automation**: Higher limits (500+) for comprehensive tasks +- **Resource control**: Prevent runaway executions in automated environments + ### Model Selection You can specify which AI model to use with the `--model` parameter or `GROK_MODEL` environment variable: @@ -244,6 +266,7 @@ Options: -u, --base-url Grok API base URL (or set GROK_BASE_URL env var) -m, --model AI model to use (e.g., grok-4-latest, grok-3-latest) (or set GROK_MODEL env var) -p, --prompt process a single prompt and exit (headless mode) + --max-tool-rounds maximum number of tool execution rounds (default: 400) -h, --help display help for command ``` diff --git a/package.json b/package.json index d38578f..4710bad 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@vibe-kit/grok-cli", - "version": "0.0.18", + "version": "0.0.19", "description": "An open-source AI agent that brings the power of Grok directly into your terminal.", "main": "dist/index.js", "bin": { diff --git a/src/agent/grok-agent.ts b/src/agent/grok-agent.ts index 55f3f61..b357637 100644 --- a/src/agent/grok-agent.ts +++ b/src/agent/grok-agent.ts @@ -51,12 +51,14 @@ export class GrokAgent extends EventEmitter { private tokenCounter: TokenCounter; private abortController: AbortController | null = null; private mcpInitialized: boolean = false; + private maxToolRounds: number; - constructor(apiKey: string, baseURL?: string, model?: string) { + constructor(apiKey: string, baseURL?: string, model?: string, maxToolRounds?: number) { super(); const manager = getSettingsManager(); const savedModel = manager.getCurrentModel(); const modelToUse = model || savedModel || "grok-4-latest"; + this.maxToolRounds = maxToolRounds || 400; this.grokClient = new GrokClient(apiKey, modelToUse, baseURL); this.textEditor = new TextEditorTool(); this.bash = new BashTool(); @@ -179,7 +181,7 @@ Current working directory: ${process.cwd()}`, this.messages.push({ role: "user", content: message }); const newEntries: ChatEntry[] = [userEntry]; - const maxToolRounds = 10; // Prevent infinite loops + const maxToolRounds = this.maxToolRounds; // Prevent infinite loops let toolRounds = 0; try { @@ -382,7 +384,7 @@ Current working directory: ${process.cwd()}`, tokenCount: inputTokens, }; - const maxToolRounds = 30; // Prevent infinite loops + const maxToolRounds = this.maxToolRounds; // Prevent infinite loops let toolRounds = 0; let totalOutputTokens = 0; diff --git a/src/index.ts b/src/index.ts index 6640e35..f072bb4 100755 --- a/src/index.ts +++ b/src/index.ts @@ -108,10 +108,11 @@ function loadModel(): string | undefined { async function handleCommitAndPushHeadless( apiKey: string, baseURL?: string, - model?: string + model?: string, + maxToolRounds?: number ): Promise { try { - const agent = new GrokAgent(apiKey, baseURL, model); + const agent = new GrokAgent(apiKey, baseURL, model, maxToolRounds); // Configure confirmation service for headless mode (auto-approve all operations) const confirmationService = ConfirmationService.getInstance(); @@ -229,10 +230,11 @@ async function processPromptHeadless( prompt: string, apiKey: string, baseURL?: string, - model?: string + model?: string, + maxToolRounds?: number ): Promise { try { - const agent = new GrokAgent(apiKey, baseURL, model); + const agent = new GrokAgent(apiKey, baseURL, model, maxToolRounds); // Configure confirmation service for headless mode (auto-approve all operations) const confirmationService = ConfirmationService.getInstance(); @@ -322,6 +324,11 @@ program "-p, --prompt ", "process a single prompt and exit (headless mode)" ) + .option( + "--max-tool-rounds ", + "maximum number of tool execution rounds (default: 400)", + "400" + ) .action(async (options) => { if (options.directory) { try { @@ -340,6 +347,7 @@ program const apiKey = options.apiKey || loadApiKey(); const baseURL = options.baseUrl || loadBaseURL(); const model = options.model || loadModel(); + const maxToolRounds = parseInt(options.maxToolRounds) || 400; if (!apiKey) { console.error( @@ -355,12 +363,12 @@ program // Headless mode: process prompt and exit if (options.prompt) { - await processPromptHeadless(options.prompt, apiKey, baseURL, model); + await processPromptHeadless(options.prompt, apiKey, baseURL, model, maxToolRounds); return; } // Interactive mode: launch UI - const agent = new GrokAgent(apiKey, baseURL, model); + const agent = new GrokAgent(apiKey, baseURL, model, maxToolRounds); console.log("🤖 Starting Grok CLI Conversational Assistant...\n"); ensureUserSettingsDirectory(); @@ -390,6 +398,11 @@ gitCommand "-m, --model ", "AI model to use (e.g., gemini-2.5-pro, grok-4-latest) (or set GROK_MODEL env var)" ) + .option( + "--max-tool-rounds ", + "maximum number of tool execution rounds (default: 400)", + "400" + ) .action(async (options) => { if (options.directory) { try { @@ -408,6 +421,7 @@ gitCommand const apiKey = options.apiKey || loadApiKey(); const baseURL = options.baseUrl || loadBaseURL(); const model = options.model || loadModel(); + const maxToolRounds = parseInt(options.maxToolRounds) || 400; if (!apiKey) { console.error( @@ -421,7 +435,7 @@ gitCommand await saveCommandLineSettings(options.apiKey, options.baseUrl); } - await handleCommitAndPushHeadless(apiKey, baseURL, model); + await handleCommitAndPushHeadless(apiKey, baseURL, model, maxToolRounds); } catch (error: any) { console.error("❌ Error during git commit-and-push:", error.message); process.exit(1);